From cdf9b869e582011630ad7c4a0443f5ecd240951d Mon Sep 17 00:00:00 2001 From: Haejeong Kim Date: Fri, 18 Aug 2017 15:15:27 +0900 Subject: [PATCH] Imported Upstream version 12.1 Change-Id: Ic6182be15482901abc5a2884bee1a371fe6ffabc --- .gitignore | 37 +- .travis.yml | 26 + Changelog | 221 +- LICENSE | 3 +- Makefile | 29 +- README.md | 2 + RELEASE | 2 +- VERSION | 1 + arch.mak | 1 + avconv.c | 1623 ++-- avconv.h | 100 +- avconv_dxva2.c | 345 +- avconv_filter.c | 320 +- avconv_opt.c | 449 +- avconv_qsv.c | 96 + avconv_vaapi.c | 538 ++ avconv_vda.c | 2 + avconv_vdpau.c | 254 +- avplay.c | 725 +- avprobe.c | 375 +- cmdutils.c | 162 +- cmdutils.h | 12 - common.mak | 15 +- compat/dispatch_semaphore/semaphore.h | 42 + compat/solaris/make_sunver.pl | 352 + compat/w32pthreads.h | 171 +- compat/windows/mslink | 9 + configure | 1156 ++- doc/.gitignore | 6 + doc/APIchanges | 289 +- doc/Doxyfile | 2 +- doc/Makefile | 1 + doc/RELEASE_NOTES | 97 +- doc/avconv.texi | 54 +- doc/avplay.texi | 10 +- doc/avtools-common-opts.texi | 6 +- doc/avutil.txt | 2 +- doc/build_system.txt | 5 +- doc/decoders.texi | 2 +- doc/developer.texi | 8 +- doc/doxy/.gitignore | 1 + doc/encoders.texi | 115 +- doc/examples/.gitignore | 5 + doc/examples/avcodec.c | 48 +- doc/examples/output.c | 110 +- doc/examples/qsvdec.c | 487 ++ doc/examples/transcode_aac.c | 101 +- doc/fate.texi | 13 +- doc/filters.texi | 132 +- doc/general.texi | 95 +- doc/git-howto.texi | 2 +- doc/indevs.texi | 13 + doc/muxers.texi | 64 +- doc/nut.texi | 2 +- doc/optimization.txt | 4 +- doc/platform.texi | 55 +- doc/protocols.texi | 21 +- doc/swscale.txt | 4 +- doc/texi2pod.pl | 7 +- doc/viterbi.txt | 14 +- libavcodec/.gitignore | 4 + libavcodec/4xm.c | 46 +- libavcodec/8bps.c | 3 +- libavcodec/8svx.c | 16 +- libavcodec/Makefile | 278 +- libavcodec/a64multienc.c | 42 +- libavcodec/aac.h | 4 +- libavcodec/aac_ac3_parser.c | 8 - libavcodec/aac_adtstoasc_bsf.c | 102 +- libavcodec/aac_parser.c | 2 +- libavcodec/aaccoder.c | 4 +- libavcodec/aacdec.c | 256 +- libavcodec/aacdectab.h | 19 +- libavcodec/aacenc.c | 30 +- libavcodec/aacps.c | 2 +- libavcodec/aacpsy.c | 20 +- libavcodec/aacsbr.c | 51 +- libavcodec/aactab.c | 494 +- libavcodec/aactab.h | 6 +- libavcodec/aarch64/Makefile | 23 +- libavcodec/aarch64/asm-offsets.h | 3 + libavcodec/aarch64/dcadsp_init.c | 60 + libavcodec/aarch64/dcadsp_neon.S | 109 + libavcodec/aarch64/fft_init_aarch64.c | 15 +- libavcodec/aarch64/fft_neon.S | 2 +- libavcodec/aarch64/fmtconvert_init.c | 43 + libavcodec/aarch64/fmtconvert_neon.S | 76 + libavcodec/aarch64/h264idct_neon.S | 24 +- libavcodec/aarch64/h264pred_init.c | 93 + libavcodec/aarch64/h264pred_neon.S | 361 + libavcodec/aarch64/h264qpel_init_aarch64.c | 128 +- .../aarch64/{opus_imdct_init.c => imdct15_init.c} | 19 +- .../aarch64/{opus_imdct_neon.S => imdct15_neon.S} | 2 +- libavcodec/aarch64/mdct_init.c | 39 + libavcodec/aarch64/mpegaudiodsp_neon.S | 2 +- libavcodec/aarch64/neon.S | 12 +- libavcodec/aarch64/neontest.c | 2 +- libavcodec/aarch64/synth_filter_neon.S | 119 + libavcodec/aasc.c | 6 +- libavcodec/ac3.c | 3 +- libavcodec/ac3_parser.c | 2 +- libavcodec/ac3dec.c | 437 +- libavcodec/ac3dec.h | 4 +- libavcodec/ac3dsp.c | 3 +- libavcodec/ac3enc.c | 67 +- libavcodec/ac3enc.h | 2 + libavcodec/ac3enc_float.c | 2 +- libavcodec/ac3enc_opts_template.c | 6 +- libavcodec/ac3enc_template.c | 4 +- libavcodec/acelp_filters.h | 1 - libavcodec/adpcm.c | 4 +- libavcodec/adpcm.h | 2 +- libavcodec/adpcm_data.c | 2 +- libavcodec/adpcm_data.h | 2 +- libavcodec/adpcmenc.c | 5 +- libavcodec/adxdec.c | 2 +- libavcodec/aic.c | 24 +- libavcodec/alac.c | 36 +- libavcodec/alacenc.c | 47 +- libavcodec/aliaspixdec.c | 2 +- libavcodec/aliaspixenc.c | 20 +- libavcodec/allcodecs.c | 77 +- libavcodec/alsdec.c | 48 +- libavcodec/amrnbdec.c | 6 +- libavcodec/amrwbdata.h | 2 +- libavcodec/amrwbdec.c | 7 +- libavcodec/anm.c | 2 +- libavcodec/ansi.c | 6 +- libavcodec/apedec.c | 19 +- libavcodec/arm/Makefile | 48 +- libavcodec/arm/dcadsp_init_arm.c | 11 +- libavcodec/arm/dcadsp_neon.S | 29 - libavcodec/arm/fft_fixed_init_arm.c | 12 +- libavcodec/arm/fft_fixed_neon.S | 2 +- libavcodec/arm/fft_init_arm.c | 34 +- libavcodec/arm/fft_neon.S | 2 +- libavcodec/arm/fft_vfp.S | 14 +- libavcodec/arm/fmtconvert_init_arm.c | 20 +- libavcodec/arm/fmtconvert_neon.S | 378 +- libavcodec/arm/fmtconvert_vfp_armv6.S | 78 - libavcodec/arm/g722dsp_init_arm.c | 35 + libavcodec/arm/g722dsp_neon.S | 69 + libavcodec/arm/h264pred_init_arm.c | 30 +- libavcodec/arm/idctdsp_init_arm.c | 7 - libavcodec/arm/mdct_fixed_init_arm.c | 40 + libavcodec/arm/mdct_init_arm.c | 47 + libavcodec/arm/me_cmp_init_arm.c | 10 +- libavcodec/arm/mlpdsp_armv5te.S | 45 +- libavcodec/arm/mlpdsp_armv6.S | 2 +- libavcodec/arm/mpegvideo_armv5te.c | 2 +- libavcodec/arm/neontest.c | 2 +- libavcodec/arm/rdft_init_arm.c | 33 + libavcodec/arm/simple_idct_arm.S | 6 +- libavcodec/arm/simple_idct_armv5te.S | 7 - libavcodec/arm/videodsp_armv5te.S | 3 +- libavcodec/arm/vp3dsp_init_arm.c | 6 +- libavcodec/arm/vp6dsp_init_arm.c | 8 +- libavcodec/arm/vp8dsp_armv6.S | 35 +- libavcodec/arm/vp8dsp_neon.S | 4 +- libavcodec/ass.c | 2 +- libavcodec/ass.h | 2 +- libavcodec/assdec.c | 2 +- libavcodec/asv.c | 77 +- libavcodec/asv.h | 2 +- libavcodec/asvdec.c | 59 +- libavcodec/asvenc.c | 278 +- libavcodec/atrac1.c | 8 +- libavcodec/atrac1data.h | 2 +- libavcodec/atrac3.c | 9 +- libavcodec/atrac3plus.c | 15 +- libavcodec/atrac3plusdec.c | 3 +- libavcodec/audio_frame_queue.c | 14 +- libavcodec/audio_frame_queue.h | 2 +- libavcodec/aura.c | 2 +- libavcodec/avcodec.h | 1976 +++-- libavcodec/avpacket.c | 196 +- libavcodec/avpicture.c | 64 +- libavcodec/avs.c | 5 +- libavcodec/bethsoftvideo.c | 2 +- libavcodec/bfi.c | 2 +- libavcodec/bgmc.c | 6 +- libavcodec/bink.c | 65 +- libavcodec/binkaudio.c | 20 +- libavcodec/bitstream.c | 19 +- libavcodec/bitstream_filter.c | 139 +- libavcodec/bitstream_filters.c | 83 + libavcodec/bmp.c | 4 +- libavcodec/bmpenc.c | 15 +- libavcodec/bmvaudio.c | 2 +- libavcodec/bmvvideo.c | 2 +- libavcodec/brenderpix.c | 2 +- libavcodec/bsf.c | 219 + libavcodec/bsf.h | 33 + libavcodec/bytestream.h | 4 +- libavcodec/c93.c | 4 +- libavcodec/cabac.c | 228 +- libavcodec/cabac.h | 3 +- libavcodec/cabac_functions.h | 9 +- libavcodec/canopus.c | 63 + libavcodec/canopus.h | 32 + libavcodec/cavs.c | 25 +- libavcodec/cavs.h | 4 +- libavcodec/cavsdec.c | 8 +- libavcodec/cavsdsp.c | 55 +- libavcodec/cavsdsp.h | 10 +- libavcodec/cdgraphics.c | 2 +- libavcodec/cdxl.c | 6 +- libavcodec/celp_filters.c | 2 +- libavcodec/celp_math.c | 13 + libavcodec/celp_math.h | 10 + libavcodec/chomp_bsf.c | 29 +- libavcodec/cinepak.c | 8 +- libavcodec/cljrdec.c | 2 +- libavcodec/cljrenc.c | 21 +- libavcodec/cllc.c | 12 +- libavcodec/cngdec.c | 2 +- libavcodec/codec_desc.c | 115 + libavcodec/cook.c | 55 +- libavcodec/cookdata.h | 2 +- libavcodec/cscd.c | 4 +- libavcodec/cyuv.c | 6 +- libavcodec/d3d11va.c | 48 + libavcodec/d3d11va.h | 112 + libavcodec/dca.c | 23 +- libavcodec/dca.h | 271 +- libavcodec/dca_exss.c | 368 + libavcodec/dca_parser.c | 76 +- libavcodec/dca_syncwords.h | 37 + libavcodec/dca_xll.c | 747 ++ libavcodec/dcadata.c | 8391 ++++++++++++++++++++ libavcodec/dcadata.h | 7646 +----------------- libavcodec/dcadec.c | 1499 ++-- libavcodec/dcadsp.c | 60 +- libavcodec/dcadsp.h | 11 +- libavcodec/dcahuff.h | 947 ++- libavcodec/dcamath.h | 42 + libavcodec/dct.c | 2 + libavcodec/dct.h | 2 + libavcodec/dct32.h | 2 +- libavcodec/dds.c | 716 ++ libavcodec/dfa.c | 2 +- libavcodec/dirac.c | 325 +- libavcodec/dirac.h | 33 +- libavcodec/dirac_parser.c | 58 +- libavcodec/dnxhddata.c | 467 +- libavcodec/dnxhddata.h | 3 +- libavcodec/dnxhddec.c | 128 +- libavcodec/dnxhdenc.c | 67 +- libavcodec/dnxhdenc.h | 1 + libavcodec/dpcm.c | 4 +- libavcodec/dpx.c | 2 +- libavcodec/dpx_parser.c | 116 + libavcodec/dpxenc.c | 34 +- libavcodec/dsicinaudio.c | 2 +- libavcodec/dsicinvideo.c | 2 +- libavcodec/dss_sp.c | 780 ++ libavcodec/dump_extradata_bsf.c | 92 +- libavcodec/dv.c | 238 +- libavcodec/dv.h | 75 +- libavcodec/dv_profile.c | 389 +- libavcodec/dv_tablegen.h | 70 +- libavcodec/dvbsub.c | 6 +- libavcodec/dvbsub_parser.c | 23 +- libavcodec/dvbsubdec.c | 270 +- libavcodec/dvdata.c | 494 +- libavcodec/dvdec.c | 191 +- libavcodec/dvdsubdec.c | 89 +- libavcodec/dvdsubenc.c | 24 +- libavcodec/dvenc.c | 614 +- libavcodec/dxa.c | 2 +- libavcodec/dxtory.c | 583 +- libavcodec/dxv.c | 504 ++ libavcodec/dxva2.c | 189 +- libavcodec/dxva2.h | 6 +- libavcodec/dxva2_h264.c | 300 +- libavcodec/dxva2_hevc.c | 449 ++ libavcodec/dxva2_internal.h | 77 +- libavcodec/dxva2_mpeg2.c | 112 +- libavcodec/dxva2_vc1.c | 139 +- libavcodec/eac3dec.c | 10 +- libavcodec/eacmv.c | 4 +- libavcodec/eamad.c | 16 +- libavcodec/eatgq.c | 16 +- libavcodec/eatgv.c | 15 +- libavcodec/eatqi.c | 95 +- libavcodec/elbg.c | 41 +- libavcodec/elbg.h | 14 +- libavcodec/elsdec.c | 422 + libavcodec/elsdec.h | 60 + libavcodec/error_resilience.c | 29 +- libavcodec/error_resilience.h | 6 +- libavcodec/escape124.c | 16 +- libavcodec/escape130.c | 9 +- libavcodec/exr.c | 143 +- libavcodec/faandct.c | 16 +- libavcodec/faanidct.c | 7 - libavcodec/faxcompr.h | 2 +- libavcodec/fdctdsp.c | 20 +- libavcodec/fft.h | 7 + libavcodec/fft_template.c | 7 - libavcodec/ffv1.c | 30 +- libavcodec/ffv1.h | 8 +- libavcodec/ffv1dec.c | 61 +- libavcodec/ffv1enc.c | 219 +- libavcodec/fic.c | 2 +- libavcodec/flac.c | 19 +- libavcodec/flac.h | 14 +- libavcodec/flac_parser.c | 9 + libavcodec/flacdec.c | 10 +- libavcodec/flacenc.c | 73 +- libavcodec/flashsv.c | 12 +- libavcodec/flashsvenc.c | 22 +- libavcodec/flicvideo.c | 10 +- libavcodec/flv.h | 8 +- libavcodec/flvdec.c | 22 +- libavcodec/flvenc.c | 87 +- libavcodec/fmtconvert.c | 69 +- libavcodec/fmtconvert.h | 59 +- libavcodec/fraps.c | 8 +- libavcodec/frwu.c | 2 +- libavcodec/g2meet.c | 763 +- libavcodec/g722.c | 70 +- libavcodec/g722.h | 5 +- libavcodec/g722dec.c | 19 +- libavcodec/g722dsp.c | 74 + libavcodec/g722dsp.h | 33 + libavcodec/g722enc.c | 23 +- libavcodec/g723_1.c | 1348 +--- libavcodec/{g723_1_data.h => g723_1.h} | 234 +- libavcodec/g723_1dec.c | 1045 +++ libavcodec/g723_1enc.c | 1202 +++ libavcodec/g726.c | 39 +- libavcodec/get_bits.h | 166 +- libavcodec/gif.c | 14 +- libavcodec/gifdec.c | 14 +- libavcodec/golomb.h | 32 +- libavcodec/gsmdec.c | 4 +- libavcodec/gsmdec_data.c | 7 + libavcodec/gsmdec_data.h | 1 + libavcodec/gsmdec_template.c | 9 +- libavcodec/h261.c | 6 +- libavcodec/h261.h | 4 +- libavcodec/h261_parser.c | 4 +- libavcodec/h261dec.c | 14 +- libavcodec/h261enc.c | 16 +- libavcodec/h263.c | 25 +- libavcodec/h263.h | 45 +- libavcodec/h263data.c | 292 + libavcodec/h263data.h | 271 +- libavcodec/h263dec.c | 61 +- libavcodec/h264.c | 1880 ----- libavcodec/h264.h | 1039 +-- libavcodec/h2645_parse.c | 330 + libavcodec/h2645_parse.h | 88 + libavcodec/h264_cabac.c | 744 +- libavcodec/h264_cavlc.c | 431 +- libavcodec/h264_direct.c | 335 +- libavcodec/h264_loopfilter.c | 247 +- libavcodec/h264_mb.c | 583 +- libavcodec/h264_mb_template.c | 260 +- libavcodec/h264_mc_template.c | 70 +- libavcodec/h264_mp4toannexb_bsf.c | 162 +- libavcodec/h264_mvpred.h | 390 +- libavcodec/h264_parse.c | 488 ++ libavcodec/h264_parse.h | 92 + libavcodec/h264_parser.c | 376 +- libavcodec/h264_picture.c | 46 +- libavcodec/h264_ps.c | 603 +- libavcodec/h264_ps.h | 155 + libavcodec/h264_refs.c | 539 +- libavcodec/h264_sei.c | 359 +- libavcodec/h264_sei.h | 137 + libavcodec/h264_slice.c | 2535 +++--- libavcodec/h264addpx_template.c | 2 +- libavcodec/h264data.c | 206 + libavcodec/h264data.h | 145 +- libavcodec/h264dec.c | 811 ++ libavcodec/h264dec.h | 817 ++ libavcodec/h264dsp.c | 2 +- libavcodec/h264dsp.h | 2 +- libavcodec/h264dsp_template.c | 2 +- libavcodec/h264idct_template.c | 2 +- libavcodec/h264pred.c | 12 +- libavcodec/h264pred.h | 7 +- libavcodec/h264pred_template.c | 2 +- libavcodec/h264qpel_template.c | 2 +- libavcodec/hap.c | 55 + libavcodec/hap.h | 98 + libavcodec/hapdec.c | 430 + libavcodec/hapenc.c | 334 + libavcodec/hevc.c | 1351 ++-- libavcodec/hevc.h | 73 +- libavcodec/hevc_cabac.c | 58 +- libavcodec/hevc_data.c | 75 + libavcodec/hevc_filter.c | 145 +- libavcodec/hevc_mp4toannexb_bsf.c | 195 + libavcodec/hevc_mvs.c | 110 +- libavcodec/hevc_parser.c | 127 +- libavcodec/hevc_ps.c | 625 +- libavcodec/hevc_ps_enc.c | 116 + libavcodec/hevc_refs.c | 76 +- libavcodec/hevc_sei.c | 90 +- libavcodec/hevcdsp.c | 129 +- libavcodec/hevcdsp.h | 66 +- libavcodec/hevcdsp_template.c | 521 +- libavcodec/hevcpred_template.c | 54 +- libavcodec/hnm4video.c | 6 +- libavcodec/hpeldsp.h | 6 +- libavcodec/hq_hqa.c | 391 + libavcodec/hq_hqa.h | 60 + libavcodec/hq_hqadata.c | 8377 +++++++++++++++++++ libavcodec/hq_hqadsp.c | 130 + libavcodec/hq_hqadsp.h | 38 + libavcodec/hqx.c | 544 ++ libavcodec/hqx.h | 86 + libavcodec/hqxdsp.c | 131 + libavcodec/hqxdsp.h | 39 + libavcodec/hqxvlc.c | 2163 +++++ libavcodec/huffman.c | 14 +- libavcodec/huffman.h | 5 +- libavcodec/huffyuv.h | 1 + libavcodec/huffyuvdec.c | 32 +- libavcodec/huffyuvenc.c | 96 +- libavcodec/idcinvideo.c | 7 +- libavcodec/idctdsp.c | 24 +- libavcodec/idctdsp.h | 3 + libavcodec/iff.c | 10 +- libavcodec/iirfilter.c | 150 +- libavcodec/imc.c | 17 +- libavcodec/{opus_imdct.c => imdct15.c} | 30 +- libavcodec/{opus_imdct.h => imdct15.h} | 18 +- libavcodec/imgconvert.c | 272 +- libavcodec/imgconvert.h | 47 - libavcodec/imx_dump_header_bsf.c | 61 +- libavcodec/indeo2.c | 20 +- libavcodec/indeo2data.h | 273 +- libavcodec/indeo3.c | 8 +- libavcodec/indeo3data.h | 12 +- libavcodec/indeo4.c | 33 +- libavcodec/indeo4data.h | 3 +- libavcodec/indeo5.c | 4 +- libavcodec/intelh263dec.c | 12 +- libavcodec/internal.h | 58 +- libavcodec/interplayvideo.c | 20 +- libavcodec/intrax8.c | 1138 +-- libavcodec/intrax8.h | 80 +- libavcodec/intrax8dsp.c | 602 +- libavcodec/intrax8dsp.h | 4 +- libavcodec/intrax8huf.h | 1793 +++-- libavcodec/ituh263dec.c | 72 +- libavcodec/ituh263enc.c | 27 +- libavcodec/{ivi_common.c => ivi.c} | 44 +- libavcodec/{ivi_common.h => ivi.h} | 13 +- libavcodec/ivi_dsp.c | 12 +- libavcodec/ivi_dsp.h | 7 +- libavcodec/jfdctint_template.c | 9 +- libavcodec/jpeg2000.c | 438 +- libavcodec/jpeg2000dec.c | 392 +- libavcodec/jpeg2000dsp.c | 98 + libavcodec/jpeg2000dsp.h | 35 + libavcodec/jpeg2000dwt.h | 3 +- libavcodec/jpegls.c | 3 +- libavcodec/jpeglsdec.c | 16 +- libavcodec/jpeglsenc.c | 88 +- libavcodec/{mjpeg.c => jpegtables.c} | 2 +- libavcodec/jpegtables.h | 43 + libavcodec/jrevdct.c | 50 +- libavcodec/jvdec.c | 2 +- libavcodec/kgv1dec.c | 4 +- libavcodec/kmvc.c | 2 +- libavcodec/lagarith.c | 12 +- libavcodec/lagarithrac.c | 2 +- libavcodec/lcldec.c | 23 +- libavcodec/lclenc.c | 34 +- libavcodec/libavcodec.v | 8 +- libavcodec/libdcadec.c | 205 + libavcodec/libfaac.c | 10 +- libavcodec/libfdk-aacdec.c | 161 +- libavcodec/libfdk-aacenc.c | 14 +- libavcodec/libgsmdec.c | 4 +- libavcodec/libilbc.c | 7 +- libavcodec/libkvazaar.c | 300 + libavcodec/libmp3lame.c | 19 +- libavcodec/libopencore-amr.c | 31 +- libavcodec/libopenh264.c | 62 + libavcodec/libopenh264.h | 39 + libavcodec/libopenh264dec.c | 242 + libavcodec/libopenh264enc.c | 301 + libavcodec/libopenjpegdec.c | 14 +- libavcodec/libopenjpegenc.c | 14 +- libavcodec/libopus.c | 8 +- libavcodec/libopus.h | 8 +- libavcodec/libopusdec.c | 12 +- libavcodec/libopusenc.c | 20 +- libavcodec/libschroedinger.c | 23 +- libavcodec/libschroedingerdec.c | 19 +- libavcodec/libschroedingerenc.c | 89 +- libavcodec/libspeexdec.c | 4 +- libavcodec/libspeexenc.c | 16 +- libavcodec/libtheoraenc.c | 32 +- libavcodec/libtwolame.c | 8 +- libavcodec/libvo-aacenc.c | 10 +- libavcodec/libvo-amrwbenc.c | 8 +- libavcodec/libvorbis.c | 21 +- libavcodec/libvpx.c | 60 +- libavcodec/libvpx.h | 5 +- libavcodec/libvpxdec.c | 23 +- libavcodec/libvpxenc.c | 172 +- libavcodec/libwavpackenc.c | 2 +- libavcodec/libwebpenc.c | 4 + libavcodec/libx264.c | 440 +- libavcodec/libx265.c | 130 +- libavcodec/libxavs.c | 155 +- libavcodec/libxvid.c | 643 +- libavcodec/libxvid.h | 8 +- libavcodec/libxvid_rc.c | 148 +- libavcodec/ljpegenc.c | 56 +- libavcodec/loco.c | 2 +- libavcodec/lpc.c | 2 +- libavcodec/lpc.h | 2 +- libavcodec/lsp.c | 2 +- libavcodec/lsp.h | 2 +- libavcodec/lzf.c | 90 + libavcodec/lzf.h | 29 + libavcodec/mace.c | 4 +- libavcodec/magicyuv.c | 480 ++ libavcodec/mathops.h | 11 +- libavcodec/mathtables.c | 7 + libavcodec/mdct_template.c | 20 + libavcodec/mdec.c | 9 +- libavcodec/me_cmp.c | 116 +- libavcodec/me_cmp.h | 3 +- libavcodec/metasound.c | 7 +- libavcodec/mimic.c | 47 +- libavcodec/mips/mathops.h | 37 +- libavcodec/mjpeg.h | 30 +- libavcodec/mjpeg2jpeg_bsf.c | 71 +- libavcodec/mjpega_dump_header_bsf.c | 104 +- libavcodec/mjpegbdec.c | 4 +- libavcodec/mjpegdec.c | 114 +- libavcodec/mjpegdec.h | 2 +- libavcodec/mjpegenc.c | 24 +- libavcodec/mjpegenc.h | 12 +- libavcodec/mjpegenc_common.c | 8 +- libavcodec/mjpegenc_common.h | 2 +- libavcodec/mlp.h | 2 +- libavcodec/mlp_parser.c | 51 +- libavcodec/mlp_parser.h | 7 +- libavcodec/mlpdec.c | 32 +- libavcodec/mmaldec.c | 845 ++ libavcodec/mmvideo.c | 8 +- libavcodec/motion_est.c | 167 +- libavcodec/motion_est.h | 130 + libavcodec/motion_est_template.c | 29 +- libavcodec/motionpixels.c | 18 +- libavcodec/motionpixels_tablegen.c | 2 +- libavcodec/motionpixels_tablegen.h | 2 +- libavcodec/movsub_bsf.c | 92 +- libavcodec/mpc.c | 1 - libavcodec/mpc.h | 3 +- libavcodec/mpc7.c | 2 +- libavcodec/mpc8.c | 2 +- libavcodec/mpeg12.c | 93 +- libavcodec/mpeg12.h | 33 +- libavcodec/mpeg12data.c | 24 +- libavcodec/mpeg12data.h | 4 +- libavcodec/mpeg12dec.c | 399 +- libavcodec/mpeg12enc.c | 42 +- libavcodec/mpeg12framerate.c | 39 + libavcodec/mpeg12vlc.h | 52 + libavcodec/mpeg4audio.h | 1 + libavcodec/mpeg4data.h | 6 +- libavcodec/mpeg4video.c | 16 +- libavcodec/mpeg4video.h | 7 +- libavcodec/mpeg4video_parser.c | 2 +- libavcodec/mpeg4video_parser.h | 2 +- libavcodec/mpeg4videodec.c | 139 +- libavcodec/mpeg4videoenc.c | 74 +- libavcodec/mpeg_er.c | 71 + libavcodec/mpeg_er.h | 1 + libavcodec/mpegaudio_parser.c | 15 +- libavcodec/mpegaudiodec_fixed.c | 10 +- libavcodec/mpegaudiodec_float.c | 10 +- libavcodec/mpegaudiodec_template.c | 87 +- libavcodec/mpegaudiodecheader.c | 35 +- libavcodec/mpegaudiodecheader.h | 7 +- libavcodec/mpegaudioenc.c | 16 +- libavcodec/mpegpicture.c | 427 + libavcodec/mpegpicture.h | 111 + libavcodec/mpegutils.h | 17 +- libavcodec/mpegvideo.c | 911 +-- libavcodec/mpegvideo.h | 427 +- libavcodec/mpegvideo_enc.c | 698 +- libavcodec/mpegvideo_motion.c | 130 +- libavcodec/mpegvideo_parser.c | 43 +- libavcodec/mpegvideo_xvmc.c | 2 +- libavcodec/mpegvideodata.c | 102 + libavcodec/mpegvideodata.h | 33 + libavcodec/mpegvideoencdsp.c | 105 +- libavcodec/mqc.h | 4 +- libavcodec/msgsmdec.c | 3 +- libavcodec/msmpeg4.c | 11 +- libavcodec/msmpeg4.h | 12 +- libavcodec/msmpeg4data.c | 3604 +++++---- libavcodec/msmpeg4data.h | 6 +- libavcodec/msmpeg4dec.c | 89 +- libavcodec/msmpeg4enc.c | 38 +- libavcodec/msrle.c | 6 +- libavcodec/msrledec.c | 6 +- libavcodec/msrledec.h | 2 +- libavcodec/mss1.c | 2 +- libavcodec/mss12.c | 10 + libavcodec/mss2.c | 16 +- libavcodec/mss3.c | 2 +- libavcodec/mss4.c | 2 +- libavcodec/msvideo1.c | 5 +- libavcodec/mvcdec.c | 4 +- libavcodec/mxpegdec.c | 3 +- libavcodec/nellymoser.c | 7 +- libavcodec/nellymoserdec.c | 11 +- libavcodec/nellymoserenc.c | 16 +- libavcodec/noise_bsf.c | 72 +- libavcodec/nuv.c | 21 +- libavcodec/nvenc.c | 1460 ++++ libavcodec/nvenc.h | 174 + libavcodec/nvenc_h264.c | 143 + libavcodec/nvenc_hevc.c | 139 + libavcodec/omx.c | 931 +++ libavcodec/on2avc.c | 19 +- libavcodec/options.c | 39 +- libavcodec/options_table.h | 189 +- libavcodec/opus.c | 15 +- libavcodec/opus.h | 9 + libavcodec/opus_celt.c | 14 +- libavcodec/opus_parser.c | 139 +- libavcodec/opus_silk.c | 14 +- libavcodec/opusdec.c | 8 +- libavcodec/pafaudio.c | 2 +- libavcodec/pafvideo.c | 2 +- libavcodec/pamenc.c | 23 +- libavcodec/parser.c | 38 +- libavcodec/pcm-bluray.c | 8 +- libavcodec/pcm-dvd.c | 16 +- libavcodec/pcm.c | 19 +- libavcodec/pcm_tablegen.h | 5 +- libavcodec/pcx.c | 84 +- libavcodec/pcxenc.c | 25 +- libavcodec/pgssubdec.c | 56 +- libavcodec/pictordec.c | 2 +- libavcodec/pngdec.c | 51 +- libavcodec/pngdsp.h | 2 +- libavcodec/pngenc.c | 74 +- libavcodec/pnm_parser.c | 13 +- libavcodec/pnmdec.c | 10 +- libavcodec/pnmenc.c | 27 +- libavcodec/ppc/Makefile | 10 +- libavcodec/ppc/apedsp_altivec.c | 4 +- libavcodec/ppc/audiodsp.c | 4 +- libavcodec/ppc/fdctdsp.c | 4 +- libavcodec/ppc/fft_altivec.S | 4 +- libavcodec/ppc/fft_init.c | 128 +- libavcodec/ppc/fmtconvert_altivec.c | 115 +- libavcodec/ppc/h264chroma_init.c | 4 +- libavcodec/ppc/h264dsp.c | 12 +- libavcodec/ppc/h264qpel.c | 4 +- libavcodec/ppc/hpeldsp_altivec.c | 4 +- libavcodec/ppc/huffyuvdsp_altivec.c | 4 +- libavcodec/ppc/idctdsp.c | 4 +- libavcodec/ppc/mdct_init.c | 154 + libavcodec/ppc/me_cmp.c | 60 +- libavcodec/ppc/mpegaudiodsp_altivec.c | 4 +- libavcodec/ppc/mpegvideo_altivec.c | 4 +- libavcodec/ppc/mpegvideodsp.c | 4 +- libavcodec/ppc/mpegvideoencdsp.c | 4 +- libavcodec/ppc/pixblockdsp.c | 91 +- libavcodec/ppc/svq1enc_altivec.c | 4 +- libavcodec/ppc/vc1dsp_altivec.c | 4 +- libavcodec/ppc/vorbisdsp_altivec.c | 4 +- libavcodec/ppc/vp3dsp_altivec.c | 8 +- libavcodec/ppc/vp8dsp_altivec.c | 4 +- libavcodec/profiles.c | 123 + libavcodec/profiles.h | 33 + libavcodec/proresdec.c | 6 +- libavcodec/proresdsp.c | 6 +- libavcodec/proresdsp.h | 3 +- libavcodec/proresenc.c | 52 +- libavcodec/psymodel.c | 12 + libavcodec/pthread.c | 12 +- libavcodec/pthread_frame.c | 48 +- libavcodec/pthread_internal.h | 2 +- libavcodec/ptx.c | 2 +- libavcodec/qcelpdec.c | 6 +- libavcodec/qdm2.c | 166 +- libavcodec/qdrw.c | 331 +- libavcodec/qpeg.c | 6 +- libavcodec/qsv.c | 380 + libavcodec/qsv.h | 107 + libavcodec/qsv_api.c | 42 + libavcodec/qsv_internal.h | 79 + libavcodec/qsvdec.c | 501 ++ libavcodec/qsvdec.h | 79 + libavcodec/qsvdec_h2645.c | 315 + libavcodec/qsvdec_mpeg2.c | 179 + libavcodec/qsvenc.c | 1121 +++ libavcodec/qsvenc.h | 143 + libavcodec/qsvenc_h264.c | 135 + libavcodec/qsvenc_hevc.c | 271 + libavcodec/qsvenc_mpeg2.c | 114 + libavcodec/qtrle.c | 4 +- libavcodec/qtrleenc.c | 65 +- libavcodec/r210dec.c | 4 +- libavcodec/ra144.c | 2 +- libavcodec/ra144.h | 2 +- libavcodec/ra144dec.c | 2 +- libavcodec/ra144enc.c | 10 +- libavcodec/ra288.c | 17 +- libavcodec/ra288.h | 2 +- libavcodec/ralf.c | 2 +- libavcodec/rangecoder.c | 51 +- libavcodec/rangecoder.h | 14 - libavcodec/ratecontrol.c | 961 ++- libavcodec/ratecontrol.h | 7 +- libavcodec/raw.c | 1 + libavcodec/rawdec.c | 26 +- libavcodec/rawenc.c | 16 +- libavcodec/rdft.c | 9 +- libavcodec/rectangle.h | 2 +- libavcodec/remove_extradata_bsf.c | 109 +- libavcodec/rl.c | 142 + libavcodec/rl.h | 15 +- libavcodec/rl2.c | 4 +- libavcodec/rle.c | 49 +- libavcodec/rle.h | 20 +- libavcodec/roqaudioenc.c | 5 +- libavcodec/roqvideodec.c | 16 +- libavcodec/roqvideoenc.c | 116 +- libavcodec/rpza.c | 58 +- libavcodec/rscc.c | 313 + libavcodec/rv10.c | 22 +- libavcodec/rv10.h | 33 + libavcodec/rv10enc.c | 10 +- libavcodec/rv20enc.c | 10 +- libavcodec/rv30.c | 8 +- libavcodec/rv30data.h | 2 +- libavcodec/rv30dsp.c | 2 +- libavcodec/rv34.c | 24 +- libavcodec/rv34.h | 4 +- libavcodec/rv34_parser.c | 2 +- libavcodec/rv40.c | 15 +- libavcodec/rv40dsp.c | 2 +- libavcodec/s302m.c | 2 +- libavcodec/s3tc.c | 97 - libavcodec/s3tc.h | 55 - libavcodec/sanm.c | 2 +- libavcodec/sbrdsp.c | 2 +- libavcodec/screenpresso.c | 197 + libavcodec/sgidec.c | 13 +- libavcodec/sgienc.c | 175 +- libavcodec/sgirledec.c | 34 +- libavcodec/shorten.c | 7 +- libavcodec/simple_idct.c | 2 + libavcodec/simple_idct_template.c | 34 +- libavcodec/sipr.c | 8 +- libavcodec/smacker.c | 27 +- libavcodec/smc.c | 4 +- libavcodec/snappy.c | 183 + libavcodec/snappy.h | 60 + libavcodec/sp5x.h | 2 +- libavcodec/sp5xdec.c | 6 +- libavcodec/srtdec.c | 2 +- libavcodec/startcode.c | 2 +- libavcodec/sunrast.c | 2 +- libavcodec/sunrastenc.c | 48 +- libavcodec/svq1.c | 2 +- libavcodec/svq1.h | 2 +- libavcodec/svq1_cb.h | 2 +- libavcodec/svq1_vlc.h | 2 +- libavcodec/svq1dec.c | 27 +- libavcodec/svq1enc.c | 106 +- libavcodec/svq1enc.h | 9 +- libavcodec/svq3.c | 960 ++- libavcodec/synth_filter.c | 8 +- libavcodec/synth_filter.h | 1 + libavcodec/tak.c | 2 + libavcodec/tak.h | 3 +- libavcodec/tak_parser.c | 3 +- libavcodec/takdec.c | 18 +- libavcodec/targa.c | 2 +- libavcodec/targaenc.c | 58 +- libavcodec/tdsc.c | 627 ++ libavcodec/tests/.gitignore | 6 + libavcodec/{arm/dct-test.c => tests/arm/dct.c} | 2 +- libavcodec/{dct-test.c => tests/dct.c} | 51 +- libavcodec/{fft-fixed-test.c => tests/fft-fixed.c} | 2 +- libavcodec/{fft-test.c => tests/fft.c} | 12 +- libavcodec/{golomb-test.c => tests/golomb.c} | 6 +- libavcodec/tests/iirfilter.c | 54 + libavcodec/{ppc/dct-test.c => tests/ppc/dct.c} | 4 +- libavcodec/tests/rangecoder.c | 64 + libavcodec/{x86/dct-test.c => tests/x86/dct.c} | 12 +- libavcodec/texturedsp.c | 613 ++ libavcodec/texturedsp.h | 64 + libavcodec/texturedspenc.c | 655 ++ libavcodec/tiertexseqv.c | 4 +- libavcodec/tiff.c | 145 +- libavcodec/tiffenc.c | 55 +- libavcodec/tmv.c | 2 +- libavcodec/truemotion1.c | 2 +- libavcodec/truemotion2.c | 16 +- libavcodec/truemotion2rt.c | 230 + libavcodec/truespeech.c | 4 +- libavcodec/tscc.c | 5 +- libavcodec/tscc2.c | 7 +- libavcodec/tscc2data.h | 7 - libavcodec/tta.c | 8 +- libavcodec/twinvq.c | 2 +- libavcodec/twinvq.h | 8 +- libavcodec/twinvqdec.c | 4 +- libavcodec/txd.c | 36 +- libavcodec/ulti.c | 9 +- libavcodec/utils.c | 1287 ++- libavcodec/utvideo.c | 2 + libavcodec/utvideo.h | 1 + libavcodec/utvideodec.c | 6 +- libavcodec/utvideoenc.c | 54 +- libavcodec/v210dec.c | 2 +- libavcodec/v210enc.c | 241 +- libavcodec/v210enc.h | 39 + libavcodec/v210x.c | 2 +- libavcodec/v410dec.c | 2 +- libavcodec/v410enc.c | 19 +- libavcodec/vaapi.c | 5 +- libavcodec/vaapi_encode.c | 1336 ++++ libavcodec/vaapi_encode.h | 234 + libavcodec/vaapi_encode_h264.c | 1351 ++++ libavcodec/vaapi_encode_h265.c | 1369 ++++ libavcodec/vaapi_encode_h26x.c | 68 + libavcodec/vaapi_encode_h26x.h | 45 + libavcodec/vaapi_encode_mjpeg.c | 422 + libavcodec/vaapi_h264.c | 165 +- libavcodec/vaapi_internal.h | 1 - libavcodec/vaapi_mpeg2.c | 16 +- libavcodec/vaapi_mpeg4.c | 14 +- libavcodec/vaapi_vc1.c | 39 +- libavcodec/vb.c | 2 +- libavcodec/vble.c | 13 +- libavcodec/vc1.c | 24 +- libavcodec/vc1.h | 107 +- libavcodec/vc1_block.c | 3062 +++++++ libavcodec/vc1_common.h | 92 + libavcodec/vc1_loopfilter.c | 353 + libavcodec/vc1_mc.c | 949 +++ libavcodec/vc1_parser.c | 2 +- libavcodec/vc1_pred.c | 953 +++ libavcodec/vc1_pred.h | 59 + libavcodec/vc1data.h | 6 +- libavcodec/vc1dec.c | 5351 +------------ libavcodec/vc1dsp.c | 1 - libavcodec/vc1dsp.h | 1 - libavcodec/vcr1.c | 2 +- libavcodec/vda.c | 11 +- libavcodec/vda.h | 17 + libavcodec/vda_h264.c | 35 +- libavcodec/vdpau.c | 309 +- libavcodec/vdpau.h | 45 + libavcodec/vdpau_h264.c | 132 +- libavcodec/vdpau_hevc.c | 426 + libavcodec/vdpau_internal.h | 58 +- libavcodec/vdpau_mpeg12.c | 31 + libavcodec/vdpau_mpeg4.c | 36 +- libavcodec/vdpau_vc1.c | 27 + libavcodec/version.h | 151 +- libavcodec/vima.c | 2 +- libavcodec/vlc.h | 65 + libavcodec/vmdaudio.c | 2 +- libavcodec/vmdvideo.c | 2 +- libavcodec/vmnc.c | 37 +- libavcodec/vorbis.c | 27 +- libavcodec/vorbis_parser.c | 124 +- libavcodec/vorbis_parser.h | 43 +- libavcodec/vorbis_parser_internal.h | 71 + libavcodec/vorbisdec.c | 179 +- libavcodec/vorbisenc.c | 23 +- libavcodec/vp3.c | 93 +- libavcodec/vp3data.h | 2 +- libavcodec/vp3dsp.c | 22 +- libavcodec/vp3dsp.h | 10 +- libavcodec/vp5.c | 4 +- libavcodec/vp56.c | 16 +- libavcodec/vp56.h | 9 +- libavcodec/vp56dsp.c | 71 +- libavcodec/vp56dsp.h | 18 +- libavcodec/vp6.c | 22 +- libavcodec/vp6dsp.c | 2 +- libavcodec/vp8.c | 75 +- libavcodec/vp8.h | 11 +- libavcodec/vp8data.h | 8 - libavcodec/vp8dsp.h | 4 +- libavcodec/vp9.c | 660 +- libavcodec/vp9.h | 51 +- libavcodec/vp9block.c | 197 +- libavcodec/vp9mvs.c | 20 +- libavcodec/vqavideo.c | 16 +- libavcodec/wavpack.c | 12 +- libavcodec/webp.c | 9 +- libavcodec/wma.c | 279 +- libavcodec/wma.h | 33 +- libavcodec/wma_common.c | 21 +- libavcodec/wma_freqs.c | 28 + libavcodec/{svq3.h => wma_freqs.h} | 9 +- libavcodec/wmadata.h | 2567 +++--- libavcodec/wmadec.c | 419 +- libavcodec/wmaenc.c | 286 +- libavcodec/wmalosslessdec.c | 33 +- libavcodec/wmaprodec.c | 46 +- libavcodec/wmavoice.c | 10 +- libavcodec/wmv2.c | 137 +- libavcodec/wmv2.h | 22 +- libavcodec/wmv2data.c | 35 + libavcodec/wmv2data.h | 27 + libavcodec/wmv2dec.c | 506 +- libavcodec/wmv2enc.c | 157 +- libavcodec/wnv1.c | 4 +- libavcodec/wrapped_avframe.c | 73 + libavcodec/ws-snd1.c | 2 +- libavcodec/x86/Makefile | 52 +- libavcodec/x86/ac3dsp_init.c | 14 +- libavcodec/x86/apedsp.asm | 2 +- libavcodec/x86/audiodsp.asm | 40 +- libavcodec/x86/audiodsp_init.c | 1 - libavcodec/x86/blockdsp.c | 48 +- libavcodec/x86/bswapdsp.asm | 25 +- libavcodec/x86/cabac.h | 24 +- libavcodec/x86/cavsdsp.c | 35 +- libavcodec/x86/constants.c | 3 + libavcodec/x86/constants.h | 3 + libavcodec/x86/dcadsp.asm | 90 +- libavcodec/x86/dcadsp_init.c | 24 +- libavcodec/x86/dct32.asm | 5 +- libavcodec/x86/dct_init.c | 4 +- libavcodec/x86/deinterlace.asm | 82 - libavcodec/x86/fft.asm | 130 +- libavcodec/x86/fft.h | 8 - libavcodec/x86/fft_init.c | 20 +- libavcodec/x86/fmtconvert.asm | 375 +- libavcodec/x86/fmtconvert_init.c | 98 - libavcodec/x86/fpel_mmx.c | 24 +- libavcodec/x86/h263_loopfilter.asm | 2 +- libavcodec/x86/h264_chromamc.asm | 2 +- libavcodec/x86/h264_deblock.asm | 4 +- libavcodec/x86/h264_i386.h | 14 +- libavcodec/x86/h264_idct.asm | 21 + libavcodec/x86/h264_idct_10bit.asm | 8 + libavcodec/x86/h264_intrapred.asm | 98 +- libavcodec/x86/h264_intrapred_10bit.asm | 2 +- libavcodec/x86/h264_qpel.c | 13 +- libavcodec/x86/h264_weight.asm | 10 + libavcodec/x86/hevc_deblock.asm | 2 +- libavcodec/x86/hevc_idct.asm | 107 + libavcodec/x86/hevc_mc.asm | 851 ++ libavcodec/x86/hevcdsp_init.c | 302 +- libavcodec/x86/hpeldsp.asm | 91 +- libavcodec/x86/hpeldsp.h | 4 + libavcodec/x86/hpeldsp_init.c | 57 +- libavcodec/x86/hpeldsp_rnd_template.c | 56 +- libavcodec/x86/hpeldsp_vp3.asm | 111 + libavcodec/x86/hpeldsp_vp3_init.c | 52 + libavcodec/x86/huffyuvdsp.asm | 6 +- libavcodec/x86/huffyuvdsp_init.c | 10 +- libavcodec/x86/idct_mmx_xvid.c | 562 -- libavcodec/x86/imdct36.asm | 2 +- libavcodec/x86/inline_asm.h | 2 +- libavcodec/x86/lpc.c | 2 +- libavcodec/x86/mdct.h | 32 + libavcodec/x86/mdct_init.c | 51 + libavcodec/x86/me_cmp_init.c | 180 +- libavcodec/x86/mpegvideo.c | 94 +- libavcodec/x86/mpegvideodsp.c | 1 - libavcodec/x86/mpegvideoenc_template.c | 41 +- libavcodec/x86/mpegvideoencdsp_init.c | 6 +- libavcodec/x86/pngdsp.asm | 2 +- libavcodec/x86/proresdsp.asm | 5 +- libavcodec/x86/proresdsp_init.c | 6 +- libavcodec/x86/qpeldsp.asm | 2 +- libavcodec/x86/rnd_template.c | 44 +- libavcodec/x86/rv34dsp_init.c | 1 - libavcodec/x86/rv40dsp.asm | 10 +- libavcodec/x86/sbrdsp.asm | 2 +- libavcodec/x86/simple_idct.c | 262 +- libavcodec/x86/v210enc.asm | 178 + libavcodec/x86/v210enc_init.c | 54 + libavcodec/x86/vc1dsp_mmx.c | 26 +- libavcodec/x86/vp3dsp.asm | 11 - libavcodec/x86/vp3dsp_init.c | 17 +- libavcodec/x86/vp6dsp.asm | 5 +- libavcodec/x86/vp6dsp_init.c | 7 +- libavcodec/x86/vp8dsp.asm | 14 +- libavcodec/x86/vp8dsp_init.c | 5 +- libavcodec/x86/vp8dsp_loopfilter.asm | 6 +- libavcodec/x86/vp9dsp.asm | 277 - libavcodec/x86/vp9dsp_init.c | 295 +- libavcodec/x86/vp9mc.asm | 622 ++ libavcodec/x86/w64xmmtest.c | 2 +- libavcodec/x86/{idct_xvid.h => xvididct.h} | 24 +- libavcodec/x86/xvididct_init.c | 29 +- libavcodec/x86/xvididct_mmx.c | 548 ++ .../x86/{idct_sse2_xvid.c => xvididct_sse2.c} | 211 +- libavcodec/xan.c | 7 +- libavcodec/xbmdec.c | 2 +- libavcodec/xbmenc.c | 15 +- libavcodec/xl.c | 2 +- libavcodec/xsubdec.c | 43 +- libavcodec/xsubenc.c | 27 +- libavcodec/xvididct.c | 324 +- libavcodec/xvididct.h | 9 +- libavcodec/xwddec.c | 4 +- libavcodec/xwdenc.c | 22 +- libavcodec/xxan.c | 7 +- libavcodec/yop.c | 8 +- libavcodec/zerocodec.c | 4 +- libavcodec/zmbv.c | 4 +- libavcodec/zmbvenc.c | 12 +- libavdevice/Makefile | 29 +- libavdevice/alldevices.c | 3 +- libavdevice/{alsa-audio-common.c => alsa.c} | 4 +- libavdevice/{alsa-audio.h => alsa.h} | 6 +- libavdevice/{alsa-audio-dec.c => alsa_dec.c} | 25 +- libavdevice/{alsa-audio-enc.c => alsa_enc.c} | 15 +- libavdevice/avdevice.h | 2 +- libavdevice/avfoundation_dec.m | 686 ++ libavdevice/bktr.c | 45 +- libavdevice/dv1394.c | 4 +- libavdevice/fbdev.c | 39 +- libavdevice/{jack_audio.c => jack.c} | 24 +- libavdevice/libavdevice.v | 8 +- libavdevice/libcdio.c | 12 +- libavdevice/libdc1394.c | 75 +- libavdevice/{oss_audio.c => oss.c} | 2 +- libavdevice/{oss_audio.h => oss.h} | 6 +- libavdevice/{oss_audio_dec.c => oss_dec.c} | 12 +- libavdevice/{oss_audio_enc.c => oss_enc.c} | 6 +- libavdevice/pulse.c | 16 +- libavdevice/{sndio_common.c => sndio.c} | 2 +- libavdevice/{sndio_common.h => sndio.h} | 6 +- libavdevice/sndio_dec.c | 18 +- libavdevice/sndio_enc.c | 8 +- libavdevice/tests/.gitignore | 1 + libavdevice/tests/timefilter.c | 79 + libavdevice/timefilter.c | 73 +- libavdevice/v4l2.c | 134 +- libavdevice/version.h | 6 +- libavdevice/vfwcap.c | 49 +- libavdevice/x11grab.c | 615 -- libavdevice/xcbgrab.c | 696 ++ libavfilter/Makefile | 22 +- libavfilter/af_ashowinfo.c | 27 + libavfilter/af_channelmap.c | 8 +- libavfilter/af_hdcd.c | 197 + libavfilter/af_join.c | 1 - libavfilter/af_resample.c | 52 +- libavfilter/allfilters.c | 8 + libavfilter/audio.c | 72 - libavfilter/avfilter.c | 36 +- libavfilter/avfilter.h | 406 +- libavfilter/avfiltergraph.c | 22 +- libavfilter/buffer.c | 181 - libavfilter/buffersink.c | 74 - libavfilter/buffersink.h | 37 - libavfilter/buffersrc.c | 214 +- libavfilter/buffersrc.h | 80 +- libavfilter/formats.c | 18 +- libavfilter/formats.h | 1 - libavfilter/graphparser.c | 45 +- libavfilter/interlace.h | 59 + libavfilter/internal.h | 19 +- libavfilter/libavfilter.v | 9 +- libavfilter/pthread.c | 3 +- libavfilter/setpts.c | 13 +- libavfilter/tests/.gitignore | 1 + libavfilter/{ => tests}/filtfmts.c | 15 +- libavfilter/thread.h | 1 - libavfilter/version.h | 25 +- libavfilter/vf_crop.c | 2 +- libavfilter/vf_deinterlace_qsv.c | 580 ++ libavfilter/vf_drawtext.c | 108 +- libavfilter/vf_fade.c | 3 +- libavfilter/vf_fieldorder.c | 2 +- libavfilter/vf_fps.c | 7 +- libavfilter/vf_framepack.c | 189 +- libavfilter/vf_frei0r.c | 49 +- libavfilter/vf_gradfun.c | 10 +- libavfilter/vf_hqdn3d.c | 46 +- libavfilter/vf_hwdownload.c | 215 + libavfilter/vf_hwupload.c | 241 + libavfilter/vf_hwupload_cuda.c | 237 + libavfilter/vf_interlace.c | 74 +- libavfilter/vf_libopencv.c | 40 +- libavfilter/vf_overlay.c | 6 +- libavfilter/vf_pad.c | 11 +- libavfilter/vf_scale.c | 5 +- libavfilter/vf_scale_npp.c | 660 ++ libavfilter/vf_scale_qsv.c | 633 ++ libavfilter/vf_scale_vaapi.c | 461 ++ libavfilter/vf_select.c | 2 +- libavfilter/vf_showinfo.c | 27 +- libavfilter/vf_unsharp.c | 9 +- libavfilter/vf_yadif.c | 10 +- libavfilter/video.c | 47 - libavfilter/vsrc_color.c | 13 +- libavfilter/vsrc_movie.c | 24 +- libavfilter/vsrc_testsrc.c | 14 +- libavfilter/x86/Makefile | 2 + libavfilter/x86/af_volume.asm | 2 +- libavfilter/x86/af_volume_init.c | 2 +- libavfilter/x86/vf_gradfun_init.c | 1 - libavfilter/x86/vf_interlace.asm | 65 + libavfilter/x86/vf_interlace_init.c | 46 + libavfilter/x86/vf_yadif_init.c | 1 - libavformat/.gitignore | 1 + libavformat/4xm.c | 48 +- libavformat/Makefile | 82 +- libavformat/a64.c | 10 +- libavformat/aacdec.c | 4 +- libavformat/adtsenc.c | 20 +- libavformat/adxdec.c | 38 +- libavformat/aea.c | 24 +- libavformat/aiff.h | 1 + libavformat/aiffdec.c | 79 +- libavformat/aiffenc.c | 36 +- libavformat/allformats.c | 55 +- libavformat/amr.c | 42 +- libavformat/anm.c | 22 +- libavformat/apc.c | 32 +- libavformat/ape.c | 26 +- libavformat/apetag.c | 34 +- libavformat/asf.h | 23 +- libavformat/asfcrypt.c | 26 +- libavformat/asfdec.c | 2617 +++--- libavformat/asfenc.c | 121 +- libavformat/assdec.c | 12 +- libavformat/assenc.c | 16 +- libavformat/au.c | 30 +- libavformat/audiointerleave.c | 14 +- libavformat/avc.c | 19 +- libavformat/avc.h | 3 + libavformat/avformat.h | 196 +- libavformat/avidec.c | 354 +- libavformat/avienc.c | 102 +- libavformat/avio.c | 117 +- libavformat/avio.h | 90 +- libavformat/avio_internal.h | 17 +- libavformat/aviobuf.c | 285 +- libavformat/avisynth.c | 134 +- libavformat/avlanguage.h | 2 +- libavformat/avs.c | 14 +- libavformat/bethsoftvid.c | 30 +- libavformat/bfi.c | 36 +- libavformat/bink.c | 50 +- libavformat/bmv.c | 22 +- libavformat/c93.c | 16 +- libavformat/cafdec.c | 82 +- libavformat/cdg.c | 6 +- libavformat/cdxl.c | 28 +- libavformat/concat.c | 32 +- libavformat/crypto.c | 6 +- libavformat/cutils.c | 28 +- libavformat/dashenc.c | 1006 +++ libavformat/dauddec.c | 18 +- libavformat/daudenc.c | 4 +- libavformat/dfa.c | 12 +- libavformat/dsicin.c | 28 +- libavformat/dss.c | 342 + libavformat/dtsdec.c | 13 +- libavformat/dump.c | 132 +- libavformat/dv.c | 63 +- libavformat/dvenc.c | 32 +- libavformat/dxa.c | 24 +- libavformat/eacdata.c | 12 +- libavformat/electronicarts.c | 40 +- libavformat/ffmetadec.c | 4 +- libavformat/file.c | 21 +- libavformat/filmstripdec.c | 22 +- libavformat/filmstripenc.c | 8 +- libavformat/flac_picture.c | 18 +- libavformat/flacdec.c | 52 +- libavformat/flacenc.c | 16 +- libavformat/flic.c | 60 +- libavformat/flv.h | 2 +- libavformat/flvdec.c | 310 +- libavformat/flvenc.c | 325 +- libavformat/format.c | 12 +- libavformat/framecrcenc.c | 2 +- libavformat/g722.c | 16 +- libavformat/g723_1.c | 14 +- libavformat/g729dec.c | 105 + libavformat/gif.c | 37 +- libavformat/gopher.c | 6 +- libavformat/gsmdec.c | 16 +- libavformat/gxf.c | 78 +- libavformat/gxfenc.c | 64 +- libavformat/hdsenc.c | 46 +- libavformat/hevc.c | 48 +- libavformat/hls.c | 145 +- libavformat/hlsenc.c | 81 +- libavformat/hlsproto.c | 16 +- libavformat/hnm.c | 18 +- libavformat/http.c | 32 +- libavformat/http.h | 2 +- libavformat/httpauth.c | 19 +- libavformat/httpauth.h | 2 +- libavformat/icecast.c | 8 +- libavformat/id3v2.c | 47 +- libavformat/id3v2enc.c | 4 +- libavformat/idcin.c | 50 +- libavformat/idroqdec.c | 38 +- libavformat/iff.c | 58 +- libavformat/ilbc.c | 38 +- libavformat/img2.c | 10 +- libavformat/img2dec.c | 37 +- libavformat/img2enc.c | 87 +- libavformat/ingenientdec.c | 2 +- libavformat/internal.h | 93 +- libavformat/ipmovie.c | 118 +- libavformat/isom.c | 145 +- libavformat/isom.h | 14 +- libavformat/iss.c | 32 +- libavformat/iv8.c | 6 +- libavformat/ivfdec.c | 10 +- libavformat/ivfenc.c | 12 +- libavformat/jvdec.c | 30 +- libavformat/latmenc.c | 18 +- libavformat/libavformat.v | 8 +- libavformat/librtmp.c | 12 +- libavformat/lmlm4.c | 45 +- libavformat/lxfdec.c | 38 +- libavformat/m4vdec.c | 34 +- libavformat/matroska.c | 15 +- libavformat/matroska.h | 19 +- libavformat/matroskadec.c | 356 +- libavformat/matroskaenc.c | 353 +- libavformat/md5enc.c | 2 +- libavformat/md5proto.c | 5 +- libavformat/mm.c | 30 +- libavformat/mmf.c | 30 +- libavformat/mms.c | 4 +- libavformat/mmsh.c | 22 +- libavformat/mmst.c | 30 +- libavformat/mov.c | 1185 ++- libavformat/mov_chan.c | 11 +- libavformat/movenc.c | 1550 +++- libavformat/movenc.h | 46 +- libavformat/movenchint.c | 16 +- libavformat/mp3dec.c | 117 +- libavformat/mp3enc.c | 202 +- libavformat/mpc.c | 32 +- libavformat/mpc8.c | 24 +- libavformat/mpeg.c | 17 +- libavformat/mpeg.h | 3 +- libavformat/mpegenc.c | 65 +- libavformat/mpegts.c | 276 +- libavformat/mpegts.h | 2 +- libavformat/mpegtsenc.c | 143 +- libavformat/mpjpeg.c | 16 +- libavformat/mpjpegdec.c | 232 + libavformat/msnwc_tcp.c | 63 +- libavformat/mtv.c | 24 +- libavformat/mux.c | 297 +- libavformat/mvdec.c | 74 +- libavformat/mvi.c | 36 +- libavformat/mxf.c | 10 +- libavformat/mxfdec.c | 199 +- libavformat/mxfenc.c | 148 +- libavformat/mxg.c | 30 +- libavformat/ncdec.c | 6 +- libavformat/network.c | 95 +- libavformat/network.h | 4 + libavformat/nsvdec.c | 123 +- libavformat/nullenc.c | 4 +- libavformat/nut.c | 1 + libavformat/nut.h | 24 +- libavformat/nutdec.c | 84 +- libavformat/nutenc.c | 92 +- libavformat/nuv.c | 90 +- libavformat/oggdec.c | 51 +- libavformat/oggdec.h | 1 + libavformat/oggenc.c | 169 +- libavformat/oggparsecelt.c | 16 +- libavformat/oggparsedirac.c | 41 +- libavformat/oggparseflac.c | 27 +- libavformat/oggparseogm.c | 50 +- libavformat/oggparseopus.c | 16 +- libavformat/oggparseskeleton.c | 2 +- libavformat/oggparsespeex.c | 30 +- libavformat/oggparsetheora.c | 28 +- libavformat/oggparsevorbis.c | 46 +- libavformat/oggparsevp8.c | 142 + libavformat/omadec.c | 121 +- libavformat/omaenc.c | 28 +- libavformat/options.c | 41 +- libavformat/options_table.h | 9 + libavformat/os_support.c | 11 +- libavformat/os_support.h | 118 +- libavformat/paf.c | 24 +- libavformat/pcm.c | 11 +- libavformat/pcmdec.c | 26 +- libavformat/pmpdec.c | 18 +- libavformat/protocols.c | 120 + libavformat/psxstr.c | 45 +- libavformat/pva.c | 10 +- libavformat/qcp.c | 14 +- libavformat/r3d.c | 127 +- libavformat/rawdec.c | 12 +- libavformat/rawenc.c | 28 +- libavformat/rawvideodec.c | 17 +- libavformat/rdt.c | 47 +- libavformat/replaygain.c | 25 +- libavformat/riff.c | 21 + libavformat/riff.h | 9 +- libavformat/riffdec.c | 111 +- libavformat/riffenc.c | 140 +- libavformat/rl2.c | 48 +- libavformat/rmdec.c | 154 +- libavformat/rmenc.c | 79 +- libavformat/rpl.c | 76 +- libavformat/rsodec.c | 14 +- libavformat/rsoenc.c | 14 +- libavformat/rtmp.h | 3 - libavformat/rtmpcrypt.c | 81 +- libavformat/rtmpdh.c | 75 +- libavformat/rtmpdh.h | 24 +- libavformat/rtmphttp.c | 6 +- libavformat/rtmppkt.c | 17 +- libavformat/rtmpproto.c | 337 +- libavformat/rtp.c | 28 +- libavformat/rtp.h | 8 +- libavformat/rtpdec.c | 76 +- libavformat/rtpdec.h | 16 +- libavformat/rtpdec_ac3.c | 133 + libavformat/rtpdec_amr.c | 31 +- libavformat/rtpdec_asf.c | 46 +- libavformat/rtpdec_dv.c | 143 + libavformat/rtpdec_formats.h | 18 + libavformat/rtpdec_g726.c | 6 +- libavformat/rtpdec_h261.c | 174 + libavformat/rtpdec_h263.c | 13 +- libavformat/rtpdec_h263_rfc2190.c | 38 +- libavformat/rtpdec_h264.c | 454 +- libavformat/rtpdec_hevc.c | 350 + libavformat/rtpdec_ilbc.c | 8 +- libavformat/rtpdec_jpeg.c | 43 +- libavformat/rtpdec_latm.c | 48 +- libavformat/rtpdec_mpa_robust.c | 200 + libavformat/rtpdec_mpeg12.c | 14 +- libavformat/rtpdec_mpeg4.c | 152 +- libavformat/rtpdec_mpegts.c | 15 +- libavformat/rtpdec_qcelp.c | 17 +- libavformat/rtpdec_qdm2.c | 41 +- libavformat/rtpdec_qt.c | 36 +- libavformat/rtpdec_svq3.c | 43 +- libavformat/rtpdec_vp8.c | 38 +- libavformat/rtpdec_vp9.c | 341 + libavformat/rtpdec_xiph.c | 89 +- libavformat/rtpenc.c | 155 +- libavformat/rtpenc.h | 6 +- libavformat/rtpenc_aac.c | 29 +- libavformat/rtpenc_amr.c | 7 +- libavformat/rtpenc_chain.c | 9 +- libavformat/rtpenc_h261.c | 102 + libavformat/rtpenc_h263_rfc2190.c | 6 +- libavformat/rtpenc_h264.c | 109 - libavformat/rtpenc_h264_hevc.c | 207 + libavformat/rtpenc_jpeg.c | 18 +- libavformat/rtpenc_latm.c | 2 +- libavformat/rtpenc_mpegts.c | 155 + libavformat/rtpenc_xiph.c | 30 +- libavformat/rtpproto.c | 118 +- libavformat/rtsp.c | 349 +- libavformat/rtsp.h | 12 +- libavformat/rtspdec.c | 76 +- libavformat/sapdec.c | 18 +- libavformat/sapenc.c | 18 +- libavformat/sauce.c | 8 +- libavformat/sctp.c | 90 +- libavformat/sdp.c | 324 +- libavformat/seek.c | 508 -- libavformat/seek.h | 122 - libavformat/segafilm.c | 141 +- libavformat/segment.c | 53 +- libavformat/sierravmd.c | 62 +- libavformat/siff.c | 145 +- libavformat/smacker.c | 64 +- libavformat/smjpegdec.c | 26 +- libavformat/smjpegenc.c | 26 +- libavformat/smoothstreamingenc.c | 110 +- libavformat/smush.c | 36 +- libavformat/sol.c | 33 +- libavformat/soxdec.c | 30 +- libavformat/soxenc.c | 20 +- libavformat/spdif.h | 4 +- libavformat/spdifdec.c | 16 +- libavformat/spdifenc.c | 29 +- libavformat/srtdec.c | 4 +- libavformat/srtp.c | 147 - libavformat/srtpproto.c | 9 +- libavformat/swf.h | 18 +- libavformat/swfdec.c | 122 +- libavformat/swfenc.c | 93 +- libavformat/takdec.c | 24 +- libavformat/tcp.c | 52 +- libavformat/tests/.gitignore | 5 + libavformat/tests/movenc.c | 748 ++ libavformat/{noproxy-test.c => tests/noproxy.c} | 2 +- libavformat/tests/rtmpdh.c | 158 + libavformat/{seek-test.c => tests/seek.c} | 3 +- libavformat/tests/srtp.c | 167 + libavformat/{url-test.c => tests/url.c} | 2 +- libavformat/thp.c | 29 +- libavformat/tiertexseq.c | 28 +- libavformat/tls.c | 329 +- libavformat/tls.h | 60 + libavformat/tls_gnutls.c | 255 + libavformat/tls_openssl.c | 297 + libavformat/tmv.c | 40 +- libavformat/tta.c | 38 +- libavformat/tty.c | 12 +- libavformat/txd.c | 4 +- libavformat/udp.c | 106 +- libavformat/unix.c | 17 +- libavformat/url.h | 56 +- libavformat/utils.c | 722 +- libavformat/vc1test.c | 16 +- libavformat/vc1testenc.c | 10 +- libavformat/version.h | 21 +- libavformat/voc_packet.c | 119 + libavformat/vocdec.c | 112 +- libavformat/vocenc.c | 26 +- libavformat/vqf.c | 46 +- libavformat/wavdec.c | 26 +- libavformat/wavenc.c | 12 +- libavformat/wc3movie.c | 38 +- libavformat/westwood_aud.c | 24 +- libavformat/westwood_vqa.c | 50 +- libavformat/wtv.c | 115 +- libavformat/wvdec.c | 24 +- libavformat/wvenc.c | 2 +- libavformat/xa.c | 16 +- libavformat/xmv.c | 38 +- libavformat/xwma.c | 50 +- libavformat/yop.c | 49 +- libavformat/yuv4mpegdec.c | 29 +- libavformat/yuv4mpegenc.c | 55 +- libavresample/aarch64/Makefile | 8 +- libavresample/aarch64/resample_init.c | 4 +- libavresample/arm/Makefile | 6 +- libavresample/arm/asm-offsets.h | 29 + libavresample/arm/resample_init.c | 74 + libavresample/arm/resample_neon.S | 358 + libavresample/audio_convert.c | 4 +- libavresample/audio_data.c | 7 +- libavresample/audio_data.h | 7 +- libavresample/audio_mix.c | 2 +- libavresample/avresample.h | 9 +- libavresample/dither.h | 4 +- libavresample/internal.h | 3 + libavresample/libavresample.v | 8 +- libavresample/resample.c | 67 +- libavresample/tests/.gitignore | 1 + .../{avresample-test.c => tests/avresample.c} | 3 +- libavresample/utils.c | 84 +- libavresample/version.h | 8 +- libavresample/x86/audio_convert.asm | 2 +- libavresample/x86/audio_convert_init.c | 4 +- libavresample/x86/audio_mix.asm | 2 +- libavresample/x86/audio_mix_init.c | 4 +- libavresample/x86/dither.asm | 2 +- libavresample/x86/dither_init.c | 4 +- libavutil/.gitignore | 1 + libavutil/Makefile | 27 +- libavutil/aarch64/asm.S | 10 +- libavutil/aarch64/timer.h | 44 + libavutil/adler32.c | 33 - libavutil/aes.c | 108 +- libavutil/aes.h | 4 - libavutil/arm/asm.S | 16 +- libavutil/arm/cpu.c | 4 + libavutil/arm/cpu.h | 5 + libavutil/arm/intmath.h | 8 + libavutil/atomic.c | 18 - libavutil/atomic_suncc.h | 1 - libavutil/attributes.h | 4 +- libavutil/audioconvert.h | 6 - libavutil/avassert.h | 2 +- libavutil/avr32/intreadwrite.h | 2 +- libavutil/avstring.c | 74 - libavutil/avstring.h | 26 +- libavutil/avutil.h | 9 +- libavutil/base64.c | 65 - libavutil/blowfish.c | 185 +- libavutil/blowfish.h | 10 + libavutil/buffer.c | 29 +- libavutil/buffer.h | 19 +- libavutil/buffer_internal.h | 3 + libavutil/channel_layout.c | 2 + libavutil/channel_layout.h | 1 + libavutil/colorspace.h | 11 + libavutil/common.h | 31 +- libavutil/cpu.c | 125 +- libavutil/cpu.h | 8 +- libavutil/cpu_internal.h | 10 + libavutil/crc.c | 29 +- libavutil/des.c | 366 +- libavutil/des.h | 25 +- libavutil/dict.c | 28 +- libavutil/dict.h | 8 +- libavutil/display.c | 4 +- libavutil/display.h | 10 +- libavutil/eval.c | 124 - libavutil/fifo.c | 34 - libavutil/file.c | 2 +- libavutil/file_open.c | 13 +- libavutil/float_dsp.c | 285 - libavutil/frame.c | 44 +- libavutil/frame.h | 139 +- libavutil/hmac.c | 79 +- libavutil/hmac.h | 2 + libavutil/hwcontext.c | 497 ++ libavutil/hwcontext.h | 437 + libavutil/hwcontext_cuda.c | 314 + libavutil/hwcontext_cuda.h | 46 + libavutil/hwcontext_dxva2.c | 428 + libavutil/hwcontext_dxva2.h | 72 + libavutil/hwcontext_internal.h | 108 + libavutil/hwcontext_qsv.c | 792 ++ libavutil/hwcontext_qsv.h | 53 + libavutil/hwcontext_vaapi.c | 999 +++ libavutil/hwcontext_vaapi.h | 104 + libavutil/hwcontext_vdpau.c | 489 ++ libavutil/hwcontext_vdpau.h | 44 + libavutil/imgutils.c | 93 +- libavutil/imgutils.h | 59 + libavutil/internal.h | 22 +- libavutil/intreadwrite.h | 23 +- libavutil/lfg.c | 40 - libavutil/libavutil.v | 8 +- libavutil/lls.c | 58 +- libavutil/lls.h | 9 +- libavutil/log.c | 20 +- libavutil/log.h | 9 + libavutil/macros.h | 2 + libavutil/mathematics.c | 30 - libavutil/md5.c | 75 +- libavutil/md5.h | 4 - libavutil/mem.c | 32 +- libavutil/mem.h | 2 +- libavutil/old_pix_fmts.h | 134 - libavutil/opt.c | 498 +- libavutil/opt.h | 21 +- libavutil/parseutils.c | 232 +- libavutil/parseutils.h | 31 + libavutil/pixdesc.c | 905 ++- libavutil/pixdesc.h | 96 +- libavutil/pixfmt.h | 140 +- libavutil/ppc/Makefile | 2 + libavutil/ppc/cpu.c | 72 +- libavutil/ppc/cpu.h | 2 + libavutil/ppc/float_dsp_altivec.c | 18 +- libavutil/ppc/float_dsp_init.c | 23 +- libavutil/ppc/float_dsp_vsx.c | 117 + libavutil/ppc/float_dsp_vsx.h | 38 + libavutil/ppc/intreadwrite.h | 50 +- libavutil/ppc/util_altivec.h | 28 +- libavutil/random_seed.c | 2 +- libavutil/rc4.c | 13 +- libavutil/rc4.h | 25 +- libavutil/replaygain.h | 1 - libavutil/samplefmt.h | 1 - libavutil/sha.c | 56 - libavutil/sha.h | 4 - libavutil/stereo3d.c | 33 + libavutil/stereo3d.h | 18 + libavutil/tests/.gitignore | 21 + libavutil/tests/adler32.c | 51 + libavutil/tests/aes.c | 92 + libavutil/tests/atomic.c | 35 + libavutil/tests/avstring.c | 69 + libavutil/tests/base64.c | 84 + libavutil/tests/blowfish.c | 194 + libavutil/tests/cpu.c | 136 + libavutil/tests/crc.c | 45 + libavutil/tests/des.c | 128 + libavutil/tests/eval.c | 145 + libavutil/tests/fifo.c | 51 + libavutil/tests/float_dsp.c | 296 + libavutil/tests/hmac.c | 92 + libavutil/tests/lfg.c | 56 + libavutil/tests/lls.c | 54 + libavutil/tests/md5.c | 54 + libavutil/tests/opt.c | 110 + libavutil/tests/parseutils.c | 116 + libavutil/tests/sha.c | 69 + libavutil/tests/tree.c | 110 + libavutil/tests/xtea.c | 124 + libavutil/thread.h | 19 +- libavutil/time.c | 14 + libavutil/time.h | 9 + libavutil/time_internal.h | 47 + libavutil/timer.h | 4 +- libavutil/tree.c | 96 - libavutil/tree.h | 3 - libavutil/utils.c | 7 + libavutil/version.h | 46 +- libavutil/wchar_filename.h | 44 + libavutil/x86/asm.h | 65 +- libavutil/x86/cpu.c | 29 +- libavutil/x86/cpu.h | 24 + libavutil/x86/float_dsp_init.c | 2 +- libavutil/x86/lls_init.c | 2 +- libavutil/x86/timer.h | 7 +- libavutil/x86/x86inc.asm | 1046 +-- libavutil/x86/x86util.asm | 9 +- libavutil/xtea.c | 156 +- libavutil/xtea.h | 39 +- library.mak | 23 +- libswscale/Makefile | 16 +- libswscale/input.c | 64 + libswscale/libswscale.v | 9 +- libswscale/options.c | 4 +- libswscale/output.c | 24 +- libswscale/ppc/swscale_altivec.c | 2 +- libswscale/ppc/yuv2rgb_altivec.c | 2 - libswscale/rgb2rgb.c | 4 +- libswscale/rgb2rgb.h | 4 +- libswscale/rgb2rgb_template.c | 8 +- libswscale/swscale.c | 16 +- libswscale/swscale.h | 18 +- libswscale/swscale_internal.h | 131 +- libswscale/swscale_unscaled.c | 96 +- libswscale/tests/.gitignore | 2 + .../{colorspace-test.c => tests/colorspace.c} | 7 +- libswscale/{swscale-test.c => tests/swscale.c} | 3 +- libswscale/utils.c | 67 +- libswscale/version.h | 9 +- libswscale/x86/output.asm | 8 +- libswscale/x86/rgb2rgb.c | 3 +- libswscale/x86/rgb2rgb_template.c | 376 +- libswscale/x86/scale.asm | 6 +- libswscale/x86/swscale.c | 1 - libswscale/x86/swscale_template.c | 504 +- libswscale/x86/yuv2rgb.c | 1 - libswscale/yuv2rgb.c | 11 + tests/.gitignore | 8 + tests/Makefile | 14 +- tests/checkasm/.gitignore | 1 + tests/checkasm/Makefile | 42 + tests/checkasm/aarch64/Makefile | 1 + tests/checkasm/aarch64/checkasm.S | 148 + tests/checkasm/arm/Makefile | 1 + tests/checkasm/arm/checkasm.S | 168 + tests/checkasm/bswapdsp.c | 76 + tests/checkasm/checkasm.c | 650 ++ tests/checkasm/checkasm.h | 176 + tests/checkasm/dcadsp.c | 92 + tests/checkasm/fmtconvert.c | 105 + tests/checkasm/h264dsp.c | 232 + tests/checkasm/h264pred.c | 260 + tests/checkasm/h264qpel.c | 81 + tests/checkasm/hevc_idct.c | 73 + tests/checkasm/hevc_mc.c | 328 + tests/checkasm/synth_filter.c | 121 + tests/checkasm/v210enc.c | 94 + tests/checkasm/vp8dsp.c | 519 ++ tests/checkasm/vp9dsp.c | 127 + tests/checkasm/x86/Makefile | 6 + tests/checkasm/x86/checkasm.asm | 243 + tests/fate-run.sh | 22 +- tests/fate.sh | 5 +- tests/fate/aac.mak | 4 + tests/fate/ac3.mak | 10 +- tests/fate/audio.mak | 20 +- tests/fate/canopus.mak | 34 + tests/fate/checkasm.mak | 5 + tests/fate/demux.mak | 12 +- tests/fate/fft.mak | 43 +- tests/fate/filter-video.mak | 2 +- tests/fate/h264.mak | 23 +- tests/fate/hevc.mak | 3 + tests/fate/image.mak | 105 +- tests/fate/indeo.mak | 21 +- tests/fate/libavcodec.mak | 16 +- tests/fate/libavdevice.mak | 6 +- tests/fate/libavformat.mak | 22 +- tests/fate/libavresample.mak | 10 +- tests/fate/libavutil.mak | 72 +- tests/fate/lossless-audio.mak | 8 +- tests/fate/lossless-video.mak | 12 - tests/fate/microsoft.mak | 15 + tests/fate/mp3.mak | 37 +- tests/fate/mpeg4.mak | 9 + tests/fate/qt.mak | 3 + tests/fate/real.mak | 12 +- tests/fate/screen.mak | 54 +- tests/fate/seek.mak | 20 +- tests/fate/utvideo.mak | 8 +- tests/fate/vcodec.mak | 22 +- tests/fate/video.mak | 69 +- tests/fate/voice.mak | 24 +- tests/fate/vpx.mak | 27 + tests/fate/wavpack.mak | 4 +- tests/fate/wma.mak | 8 +- tests/fate/xvid.mak | 5 +- tests/ref/fate/aasc | 1 + tests/ref/fate/aic-oddsize | 58 + tests/ref/fate/asf-repldata | 15 + tests/ref/fate/{cllc-argb => canopus-cllc-argb} | 1 + tests/ref/fate/{cllc-rgb => canopus-cllc-rgb} | 1 + ...cllc-yuy2-noblock => canopus-cllc-yuy2-noblock} | 1 + tests/ref/fate/canopus-hq_hqa-hq | 9 + tests/ref/fate/canopus-hq_hqa-hqa | 2 + tests/ref/fate/canopus-hq_hqa-inter | 2 + tests/ref/fate/canopus-hqx422 | 2 + tests/ref/fate/canopus-hqx422a | 2 + tests/ref/fate/cvid-partial | 1 + tests/ref/fate/dds-alpha8 | 2 + tests/ref/fate/dds-argb | 2 + tests/ref/fate/dds-argb-aexp | 2 + tests/ref/fate/dds-dx10-bc1 | 2 + tests/ref/fate/dds-dx10-bc1a | 2 + tests/ref/fate/dds-dx10-bc2 | 2 + tests/ref/fate/dds-dx10-bc3 | 2 + tests/ref/fate/dds-dx10-bc4 | 2 + tests/ref/fate/dds-dx10-bc5 | 2 + tests/ref/fate/dds-dxt1 | 2 + tests/ref/fate/dds-dxt1-normalmap | 2 + tests/ref/fate/dds-dxt1a | 2 + tests/ref/fate/dds-dxt2 | 2 + tests/ref/fate/dds-dxt3 | 2 + tests/ref/fate/dds-dxt4 | 2 + tests/ref/fate/dds-dxt5 | 2 + tests/ref/fate/dds-dxt5-aexp | 2 + tests/ref/fate/dds-dxt5-normalmap | 2 + tests/ref/fate/dds-dxt5-normalmap-ati | 2 + tests/ref/fate/dds-dxt5-rbxg | 2 + tests/ref/fate/dds-dxt5-rgxb | 2 + tests/ref/fate/dds-dxt5-rxbg | 2 + tests/ref/fate/dds-dxt5-rxgb | 2 + tests/ref/fate/dds-dxt5-xgbr | 2 + tests/ref/fate/dds-dxt5-xgxr | 2 + tests/ref/fate/dds-dxt5-xrbg | 2 + tests/ref/fate/dds-dxt5-ycocg | 2 + tests/ref/fate/dds-dxt5-ycocg-scaled | 2 + tests/ref/fate/dds-monob | 2 + tests/ref/fate/dds-pal | 2 + tests/ref/fate/dds-pal-ati | 2 + tests/ref/fate/dds-rgb1555 | 2 + tests/ref/fate/dds-rgb16 | 2 + tests/ref/fate/dds-rgb24 | 2 + tests/ref/fate/dds-rgb555 | 2 + tests/ref/fate/dds-rgba | 2 + tests/ref/fate/dds-rgtc1s | 2 + tests/ref/fate/dds-rgtc1u | 2 + tests/ref/fate/dds-rgtc2s | 2 + tests/ref/fate/dds-rgtc2u | 2 + tests/ref/fate/dds-rgtc2u-xy | 2 + tests/ref/fate/dds-uyvy | 2 + tests/ref/fate/dds-xbgr | 2 + tests/ref/fate/dds-xrgb | 2 + tests/ref/fate/dds-y | 2 + tests/ref/fate/dds-ya | 2 + tests/ref/fate/dds-ycocg | 2 + tests/ref/fate/dds-yuyv | 2 + tests/ref/fate/dpxparser | 5 + tests/ref/fate/dss-lp | 31 + tests/ref/fate/dss-sp | 31 + tests/ref/fate/dxtory | 1 - tests/ref/fate/dxv-dxt1 | 2 + tests/ref/fate/dxv-dxt5 | 2 + tests/ref/fate/dxv3-dxt1 | 2 + tests/ref/fate/dxv3-dxt5 | 2 + tests/ref/fate/ea-mad | 194 +- tests/ref/fate/ea-tgq | 558 +- tests/ref/fate/ea-tqi | 54 +- tests/ref/fate/fic-avi | 1 + tests/ref/fate/filter-crop | 2 +- tests/ref/fate/filter-crop_scale | 2 +- tests/ref/fate/filter-crop_scale_vflip | 2 +- tests/ref/fate/filter-crop_vflip | 2 +- tests/ref/fate/filter-null | 2 +- tests/ref/fate/filter-pixdesc-abgr | 2 +- tests/ref/fate/filter-pixdesc-argb | 2 +- tests/ref/fate/filter-pixdesc-bgr24 | 2 +- tests/ref/fate/filter-pixdesc-bgr444be | 2 +- tests/ref/fate/filter-pixdesc-bgr444le | 2 +- tests/ref/fate/filter-pixdesc-bgr48be | 2 +- tests/ref/fate/filter-pixdesc-bgr48le | 2 +- tests/ref/fate/filter-pixdesc-bgr4_byte | 2 +- tests/ref/fate/filter-pixdesc-bgr555be | 2 +- tests/ref/fate/filter-pixdesc-bgr555le | 2 +- tests/ref/fate/filter-pixdesc-bgr565be | 2 +- tests/ref/fate/filter-pixdesc-bgr565le | 2 +- tests/ref/fate/filter-pixdesc-bgr8 | 2 +- tests/ref/fate/filter-pixdesc-bgra | 2 +- tests/ref/fate/filter-pixdesc-gbrap | 1 + tests/ref/fate/filter-pixdesc-gbrp | 2 +- tests/ref/fate/filter-pixdesc-gbrp10be | 2 +- tests/ref/fate/filter-pixdesc-gbrp10le | 2 +- tests/ref/fate/filter-pixdesc-gbrp9be | 2 +- tests/ref/fate/filter-pixdesc-gbrp9le | 2 +- tests/ref/fate/filter-pixdesc-gray | 2 +- tests/ref/fate/filter-pixdesc-gray16be | 2 +- tests/ref/fate/filter-pixdesc-gray16le | 2 +- tests/ref/fate/filter-pixdesc-monob | 2 +- tests/ref/fate/filter-pixdesc-monow | 2 +- tests/ref/fate/filter-pixdesc-nv12 | 2 +- tests/ref/fate/filter-pixdesc-nv21 | 2 +- tests/ref/fate/filter-pixdesc-rgb24 | 2 +- tests/ref/fate/filter-pixdesc-rgb444be | 2 +- tests/ref/fate/filter-pixdesc-rgb444le | 2 +- tests/ref/fate/filter-pixdesc-rgb48be | 2 +- tests/ref/fate/filter-pixdesc-rgb48le | 2 +- tests/ref/fate/filter-pixdesc-rgb4_byte | 2 +- tests/ref/fate/filter-pixdesc-rgb555be | 2 +- tests/ref/fate/filter-pixdesc-rgb555le | 2 +- tests/ref/fate/filter-pixdesc-rgb565be | 2 +- tests/ref/fate/filter-pixdesc-rgb565le | 2 +- tests/ref/fate/filter-pixdesc-rgb8 | 2 +- tests/ref/fate/filter-pixdesc-rgba | 2 +- tests/ref/fate/filter-pixdesc-uyvy422 | 2 +- tests/ref/fate/filter-pixdesc-yuv410p | 2 +- tests/ref/fate/filter-pixdesc-yuv411p | 2 +- tests/ref/fate/filter-pixdesc-yuv420p | 2 +- tests/ref/fate/filter-pixdesc-yuv420p10be | 2 +- tests/ref/fate/filter-pixdesc-yuv420p10le | 2 +- tests/ref/fate/filter-pixdesc-yuv420p16be | 2 +- tests/ref/fate/filter-pixdesc-yuv420p16le | 2 +- tests/ref/fate/filter-pixdesc-yuv420p9be | 2 +- tests/ref/fate/filter-pixdesc-yuv420p9le | 2 +- tests/ref/fate/filter-pixdesc-yuv422p | 2 +- tests/ref/fate/filter-pixdesc-yuv422p10be | 2 +- tests/ref/fate/filter-pixdesc-yuv422p10le | 2 +- tests/ref/fate/filter-pixdesc-yuv422p16be | 2 +- tests/ref/fate/filter-pixdesc-yuv422p16le | 2 +- tests/ref/fate/filter-pixdesc-yuv422p9be | 2 +- tests/ref/fate/filter-pixdesc-yuv422p9le | 2 +- tests/ref/fate/filter-pixdesc-yuv440p | 2 +- tests/ref/fate/filter-pixdesc-yuv444p | 2 +- tests/ref/fate/filter-pixdesc-yuv444p10be | 2 +- tests/ref/fate/filter-pixdesc-yuv444p10le | 2 +- tests/ref/fate/filter-pixdesc-yuv444p16be | 2 +- tests/ref/fate/filter-pixdesc-yuv444p16le | 2 +- tests/ref/fate/filter-pixdesc-yuv444p9be | 2 +- tests/ref/fate/filter-pixdesc-yuv444p9le | 2 +- tests/ref/fate/filter-pixdesc-yuva420p | 2 +- tests/ref/fate/filter-pixdesc-yuva420p10be | 2 +- tests/ref/fate/filter-pixdesc-yuva420p10le | 2 +- tests/ref/fate/filter-pixdesc-yuva420p16be | 2 +- tests/ref/fate/filter-pixdesc-yuva420p16le | 2 +- tests/ref/fate/filter-pixdesc-yuva420p9be | 2 +- tests/ref/fate/filter-pixdesc-yuva420p9le | 2 +- tests/ref/fate/filter-pixdesc-yuva422p | 2 +- tests/ref/fate/filter-pixdesc-yuva422p10be | 2 +- tests/ref/fate/filter-pixdesc-yuva422p10le | 2 +- tests/ref/fate/filter-pixdesc-yuva422p16be | 2 +- tests/ref/fate/filter-pixdesc-yuva422p16le | 2 +- tests/ref/fate/filter-pixdesc-yuva422p9be | 2 +- tests/ref/fate/filter-pixdesc-yuva422p9le | 2 +- tests/ref/fate/filter-pixdesc-yuva444p | 2 +- tests/ref/fate/filter-pixdesc-yuva444p10be | 2 +- tests/ref/fate/filter-pixdesc-yuva444p10le | 2 +- tests/ref/fate/filter-pixdesc-yuva444p16be | 2 +- tests/ref/fate/filter-pixdesc-yuva444p16le | 2 +- tests/ref/fate/filter-pixdesc-yuva444p9be | 2 +- tests/ref/fate/filter-pixdesc-yuva444p9le | 2 +- tests/ref/fate/filter-pixdesc-yuvj420p | 2 +- tests/ref/fate/filter-pixdesc-yuvj422p | 2 +- tests/ref/fate/filter-pixdesc-yuvj440p | 2 +- tests/ref/fate/filter-pixdesc-yuvj444p | 2 +- tests/ref/fate/filter-pixdesc-yuyv422 | 2 +- tests/ref/fate/filter-pixdesc-yvyu422 | 2 +- tests/ref/fate/filter-pixfmts-copy | 181 +- tests/ref/fate/filter-pixfmts-crop | 84 +- tests/ref/fate/filter-pixfmts-hflip | 84 +- tests/ref/fate/filter-pixfmts-null | 181 +- tests/ref/fate/filter-pixfmts-pad | 34 +- tests/ref/fate/filter-pixfmts-scale | 181 +- tests/ref/fate/filter-pixfmts-vflip | 181 +- tests/ref/fate/filter-scale200 | 2 +- tests/ref/fate/filter-scale500 | 2 +- tests/ref/fate/filter-vflip | 2 +- tests/ref/fate/filter-vflip_crop | 2 +- tests/ref/fate/filter-vflip_vflip | 2 +- tests/ref/fate/g2m2 | 161 + tests/ref/fate/g2m3 | 21 + tests/ref/fate/g2m4 | 29 + tests/ref/fate/h264-intra-refresh-recovery | 11 + tests/ref/fate/h264-invalid-ref-mod | 11 + tests/ref/fate/h264-mixed-nal-coding | 6 + tests/ref/fate/h264-twofields-packet | 31 + tests/ref/fate/h264-unescaped-extradata | 11 + tests/ref/fate/hap-chunk | 2 + tests/ref/fate/hap1 | 2 + tests/ref/fate/hap5 | 2 + tests/ref/fate/hapy | 2 + tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 | 267 + tests/ref/fate/hmac | 20 +- tests/ref/fate/indeo2-delta | 115 + tests/ref/fate/{indeo2 => indeo2-intra} | 0 tests/ref/fate/{indeo3 => indeo3-1} | 0 tests/ref/fate/iscc | 6 + tests/ref/fate/iv8-demux | 10 +- tests/ref/fate/lmlm4-demux | 180 +- tests/ref/fate/lossless-truehd-5.1 | 1 + tests/ref/fate/lossless-truehd-5.1-downmix-2.0 | 1 + tests/ref/fate/lossless-wma | 2 +- tests/ref/fate/magicyuv-rgb | 2 + tests/ref/fate/magicyuv-rgba | 2 + tests/ref/fate/magicyuv-y400i | 2 + tests/ref/fate/magicyuv-y420 | 2 + tests/ref/fate/magicyuv-y422i | 2 + tests/ref/fate/magicyuv-y444 | 2 + tests/ref/fate/magicyuv-y4444i | 2 + tests/ref/fate/movenc | 135 + tests/ref/fate/mpeg4-resolution-change-down-down | 151 + tests/ref/fate/mpeg4-resolution-change-down-up | 151 + tests/ref/fate/mpeg4-resolution-change-up-down | 151 + tests/ref/fate/mpeg4-resolution-change-up-up | 151 + tests/ref/fate/mss1 | 137 + tests/ref/fate/mts2 | 129 + tests/ref/fate/mxf-demux | 190 +- tests/ref/fate/nc-demux | 182 +- tests/ref/fate/pict | 2 + tests/ref/fate/ra3-144 | 51 + tests/ref/fate/rscc-16bit | 16 + tests/ref/fate/rscc-24bit | 2 + tests/ref/fate/rscc-32bit | 9 + tests/ref/fate/rtmpdh | 3 + tests/ref/fate/screenpresso-16bit | 9 + tests/ref/fate/screenpresso-24bit | 5 + tests/ref/fate/screenpresso-32bit | 5 + tests/ref/fate/sgi-gray16 | 2 +- tests/ref/fate/sgi-gray16-rle | 2 + tests/ref/fate/{sgi-gray => sgi-gray8} | 0 tests/ref/fate/sgi-gray8-rle | 2 + tests/ref/fate/sgi-rgba-rle | 2 + tests/ref/fate/sgi-rgba64-rle | 2 +- tests/ref/fate/svq1-headerswap | 5 + tests/ref/fate/tdsc | 42 + tests/ref/fate/theora-offset | 11 + tests/ref/fate/truemotion1-24 | 1 + tests/ref/fate/truemotion2rt-high | 2 + tests/ref/fate/truemotion2rt-low | 2 + tests/ref/fate/truemotion2rt-mid | 2 + tests/ref/fate/{tscc2 => tscc2-avi} | 0 tests/ref/fate/tscc2-mov | 16 + tests/ref/fate/txd-16bpp | 22 +- tests/ref/fate/txd-odd | 2 + tests/ref/fate/v210 | 2 +- tests/ref/fate/vc1-ism | 182 +- tests/ref/fate/vc1_ilaced_twomv | 14 + tests/ref/fate/vc1_sa10143 | 28 +- tests/ref/fate/vp5 | 1 + tests/ref/fate/webp | 2 + tests/ref/fate/wmv8-drm-nodec | 1 - tests/ref/fate/wmv8-intrax8 | 475 ++ tests/ref/fate/wtv-demux | 68 +- tests/ref/fate/{xvid-idctmmx => xvid-idct} | 0 tests/ref/fate/zmbv-8bit | 1 + tests/ref/lavf/dpx | 2 +- tests/ref/lavf/flv_fmt | 2 +- tests/ref/lavf/mkv | 4 +- tests/ref/lavf/mxf_d10 | 2 +- tests/ref/lavf/nut | 4 +- tests/ref/lavf/sgi | 4 +- tests/ref/lavf/ts | 2 +- tests/ref/seek/lavf-asf | 54 +- tests/ref/seek/lavf-mkv | 44 +- tests/ref/seek/lavf-nut | 54 +- tests/ref/seek/lavf-sgi | 2 +- tests/ref/seek/vsynth2-ffv1 | 40 +- tests/ref/vsynth/vsynth1-dnxhd-720p-10bit | 4 +- tests/ref/vsynth/vsynth1-ffv1 | 4 +- tests/ref/vsynth/vsynth1-flashsv | 2 +- tests/ref/vsynth/vsynth1-flv | 2 +- tests/ref/vsynth/vsynth1-h261 | 2 +- tests/ref/vsynth/vsynth1-mpeg4 | 4 +- tests/ref/vsynth/vsynth1-v210 | 6 +- tests/ref/vsynth/vsynth1-v210-10 | 4 + tests/ref/vsynth/vsynth2-dnxhd-720p-10bit | 6 +- tests/ref/vsynth/vsynth2-ffv1 | 4 +- tests/ref/vsynth/vsynth2-flashsv | 2 +- tests/ref/vsynth/vsynth2-flv | 2 +- tests/ref/vsynth/vsynth2-h261 | 2 +- tests/ref/vsynth/vsynth2-mpeg4 | 4 +- tests/ref/vsynth/vsynth2-v210 | 6 +- tests/ref/vsynth/vsynth2-v210-10 | 4 + tests/tiny_psnr.c | 13 +- tools/.gitignore | 9 + tools/aviocat.c | 4 +- tools/cws2fws.c | 21 +- tools/graph2dot.c | 1 - tools/ismindex.c | 368 +- tools/pktdumper.c | 2 +- tools/qt-faststart.c | 4 + tools/sidxindex.c | 387 + 2003 files changed, 147001 insertions(+), 68508 deletions(-) create mode 100644 .travis.yml create mode 100644 VERSION create mode 100644 avconv_qsv.c create mode 100644 avconv_vaapi.c create mode 100644 compat/dispatch_semaphore/semaphore.h create mode 100755 compat/solaris/make_sunver.pl create mode 100755 compat/windows/mslink create mode 100644 doc/.gitignore create mode 100644 doc/doxy/.gitignore create mode 100644 doc/examples/.gitignore create mode 100644 doc/examples/qsvdec.c create mode 100644 libavcodec/.gitignore create mode 100644 libavcodec/aarch64/dcadsp_init.c create mode 100644 libavcodec/aarch64/dcadsp_neon.S create mode 100644 libavcodec/aarch64/fmtconvert_init.c create mode 100644 libavcodec/aarch64/fmtconvert_neon.S create mode 100644 libavcodec/aarch64/h264pred_init.c create mode 100644 libavcodec/aarch64/h264pred_neon.S rename libavcodec/aarch64/{opus_imdct_init.c => imdct15_init.c} (66%) rename libavcodec/aarch64/{opus_imdct_neon.S => imdct15_neon.S} (99%) create mode 100644 libavcodec/aarch64/mdct_init.c create mode 100644 libavcodec/aarch64/synth_filter_neon.S delete mode 100644 libavcodec/arm/fmtconvert_vfp_armv6.S create mode 100644 libavcodec/arm/g722dsp_init_arm.c create mode 100644 libavcodec/arm/g722dsp_neon.S create mode 100644 libavcodec/arm/mdct_fixed_init_arm.c create mode 100644 libavcodec/arm/mdct_init_arm.c create mode 100644 libavcodec/arm/rdft_init_arm.c create mode 100644 libavcodec/bitstream_filters.c create mode 100644 libavcodec/bsf.c create mode 100644 libavcodec/bsf.h create mode 100644 libavcodec/canopus.c create mode 100644 libavcodec/canopus.h create mode 100644 libavcodec/d3d11va.c create mode 100644 libavcodec/d3d11va.h create mode 100644 libavcodec/dca_exss.c create mode 100644 libavcodec/dca_syncwords.h create mode 100644 libavcodec/dca_xll.c create mode 100644 libavcodec/dcadata.c create mode 100644 libavcodec/dcamath.h create mode 100644 libavcodec/dds.c create mode 100644 libavcodec/dpx_parser.c create mode 100644 libavcodec/dss_sp.c create mode 100644 libavcodec/dxv.c create mode 100644 libavcodec/dxva2_hevc.c create mode 100644 libavcodec/elsdec.c create mode 100644 libavcodec/elsdec.h create mode 100644 libavcodec/g722dsp.c create mode 100644 libavcodec/g722dsp.h rename libavcodec/{g723_1_data.h => g723_1.h} (91%) create mode 100644 libavcodec/g723_1dec.c create mode 100644 libavcodec/g723_1enc.c create mode 100644 libavcodec/h263data.c delete mode 100644 libavcodec/h264.c create mode 100644 libavcodec/h2645_parse.c create mode 100644 libavcodec/h2645_parse.h create mode 100644 libavcodec/h264_parse.c create mode 100644 libavcodec/h264_parse.h create mode 100644 libavcodec/h264_ps.h create mode 100644 libavcodec/h264_sei.h create mode 100644 libavcodec/h264data.c create mode 100644 libavcodec/h264dec.c create mode 100644 libavcodec/h264dec.h create mode 100644 libavcodec/hap.c create mode 100644 libavcodec/hap.h create mode 100644 libavcodec/hapdec.c create mode 100644 libavcodec/hapenc.c create mode 100644 libavcodec/hevc_data.c create mode 100644 libavcodec/hevc_mp4toannexb_bsf.c create mode 100644 libavcodec/hevc_ps_enc.c create mode 100644 libavcodec/hq_hqa.c create mode 100644 libavcodec/hq_hqa.h create mode 100644 libavcodec/hq_hqadata.c create mode 100644 libavcodec/hq_hqadsp.c create mode 100644 libavcodec/hq_hqadsp.h create mode 100644 libavcodec/hqx.c create mode 100644 libavcodec/hqx.h create mode 100644 libavcodec/hqxdsp.c create mode 100644 libavcodec/hqxdsp.h create mode 100644 libavcodec/hqxvlc.c rename libavcodec/{opus_imdct.c => imdct15.c} (91%) rename libavcodec/{opus_imdct.h => imdct15.h} (74%) delete mode 100644 libavcodec/imgconvert.h rename libavcodec/{ivi_common.c => ivi.c} (98%) rename libavcodec/{ivi_common.h => ivi.h} (98%) create mode 100644 libavcodec/jpeg2000dsp.c create mode 100644 libavcodec/jpeg2000dsp.h rename libavcodec/{mjpeg.c => jpegtables.c} (99%) create mode 100644 libavcodec/jpegtables.h create mode 100644 libavcodec/libdcadec.c create mode 100644 libavcodec/libkvazaar.c create mode 100644 libavcodec/libopenh264.c create mode 100644 libavcodec/libopenh264.h create mode 100644 libavcodec/libopenh264dec.c create mode 100644 libavcodec/libopenh264enc.c create mode 100644 libavcodec/lzf.c create mode 100644 libavcodec/lzf.h create mode 100644 libavcodec/magicyuv.c create mode 100644 libavcodec/mmaldec.c create mode 100644 libavcodec/motion_est.h create mode 100644 libavcodec/mpeg12framerate.c create mode 100644 libavcodec/mpeg12vlc.h create mode 100644 libavcodec/mpegpicture.c create mode 100644 libavcodec/mpegpicture.h create mode 100644 libavcodec/mpegvideodata.c create mode 100644 libavcodec/mpegvideodata.h create mode 100644 libavcodec/nvenc.c create mode 100644 libavcodec/nvenc.h create mode 100644 libavcodec/nvenc_h264.c create mode 100644 libavcodec/nvenc_hevc.c create mode 100644 libavcodec/omx.c create mode 100644 libavcodec/ppc/mdct_init.c create mode 100644 libavcodec/profiles.c create mode 100644 libavcodec/profiles.h create mode 100644 libavcodec/qsv.c create mode 100644 libavcodec/qsv.h create mode 100644 libavcodec/qsv_api.c create mode 100644 libavcodec/qsv_internal.h create mode 100644 libavcodec/qsvdec.c create mode 100644 libavcodec/qsvdec.h create mode 100644 libavcodec/qsvdec_h2645.c create mode 100644 libavcodec/qsvdec_mpeg2.c create mode 100644 libavcodec/qsvenc.c create mode 100644 libavcodec/qsvenc.h create mode 100644 libavcodec/qsvenc_h264.c create mode 100644 libavcodec/qsvenc_hevc.c create mode 100644 libavcodec/qsvenc_mpeg2.c create mode 100644 libavcodec/rl.c create mode 100644 libavcodec/rscc.c create mode 100644 libavcodec/rv10.h delete mode 100644 libavcodec/s3tc.c delete mode 100644 libavcodec/s3tc.h create mode 100644 libavcodec/screenpresso.c create mode 100644 libavcodec/snappy.c create mode 100644 libavcodec/snappy.h create mode 100644 libavcodec/tdsc.c create mode 100644 libavcodec/tests/.gitignore rename libavcodec/{arm/dct-test.c => tests/arm/dct.c} (97%) rename libavcodec/{dct-test.c => tests/dct.c} (92%) rename libavcodec/{fft-fixed-test.c => tests/fft-fixed.c} (97%) rename libavcodec/{fft-test.c => tests/fft.c} (98%) rename libavcodec/{golomb-test.c => tests/golomb.c} (96%) create mode 100644 libavcodec/tests/iirfilter.c rename libavcodec/{ppc/dct-test.c => tests/ppc/dct.c} (93%) create mode 100644 libavcodec/tests/rangecoder.c rename libavcodec/{x86/dct-test.c => tests/x86/dct.c} (89%) create mode 100644 libavcodec/texturedsp.c create mode 100644 libavcodec/texturedsp.h create mode 100644 libavcodec/texturedspenc.c create mode 100644 libavcodec/truemotion2rt.c create mode 100644 libavcodec/v210enc.h create mode 100644 libavcodec/vaapi_encode.c create mode 100644 libavcodec/vaapi_encode.h create mode 100644 libavcodec/vaapi_encode_h264.c create mode 100644 libavcodec/vaapi_encode_h265.c create mode 100644 libavcodec/vaapi_encode_h26x.c create mode 100644 libavcodec/vaapi_encode_h26x.h create mode 100644 libavcodec/vaapi_encode_mjpeg.c create mode 100644 libavcodec/vc1_block.c create mode 100644 libavcodec/vc1_common.h create mode 100644 libavcodec/vc1_loopfilter.c create mode 100644 libavcodec/vc1_mc.c create mode 100644 libavcodec/vc1_pred.c create mode 100644 libavcodec/vc1_pred.h create mode 100644 libavcodec/vdpau_hevc.c create mode 100644 libavcodec/vlc.h create mode 100644 libavcodec/vorbis_parser_internal.h create mode 100644 libavcodec/wma_freqs.c rename libavcodec/{svq3.h => wma_freqs.h} (76%) create mode 100644 libavcodec/wmv2data.c create mode 100644 libavcodec/wmv2data.h create mode 100644 libavcodec/wrapped_avframe.c delete mode 100644 libavcodec/x86/deinterlace.asm create mode 100644 libavcodec/x86/hevc_idct.asm create mode 100644 libavcodec/x86/hevc_mc.asm create mode 100644 libavcodec/x86/hpeldsp_vp3.asm create mode 100644 libavcodec/x86/hpeldsp_vp3_init.c delete mode 100644 libavcodec/x86/idct_mmx_xvid.c create mode 100644 libavcodec/x86/mdct.h create mode 100644 libavcodec/x86/mdct_init.c create mode 100644 libavcodec/x86/v210enc.asm create mode 100644 libavcodec/x86/v210enc_init.c delete mode 100644 libavcodec/x86/vp9dsp.asm create mode 100644 libavcodec/x86/vp9mc.asm rename libavcodec/x86/{idct_xvid.h => xvididct.h} (60%) create mode 100644 libavcodec/x86/xvididct_mmx.c rename libavcodec/x86/{idct_sse2_xvid.c => xvididct_sse2.c} (64%) rename libavdevice/{alsa-audio-common.c => alsa.c} (99%) rename libavdevice/{alsa-audio.h => alsa.h} (96%) rename libavdevice/{alsa-audio-dec.c => alsa_dec.c} (92%) rename libavdevice/{alsa-audio-enc.c => alsa_enc.c} (91%) create mode 100644 libavdevice/avfoundation_dec.m rename libavdevice/{jack_audio.c => jack.c} (94%) rename libavdevice/{oss_audio.c => oss.c} (99%) rename libavdevice/{oss_audio.h => oss.h} (93%) rename libavdevice/{oss_audio_dec.c => oss_dec.c} (94%) rename libavdevice/{oss_audio_enc.c => oss_enc.c} (96%) rename libavdevice/{sndio_common.c => sndio.c} (99%) rename libavdevice/{sndio_common.h => sndio.h} (92%) create mode 100644 libavdevice/tests/.gitignore create mode 100644 libavdevice/tests/timefilter.c delete mode 100644 libavdevice/x11grab.c create mode 100644 libavdevice/xcbgrab.c create mode 100644 libavfilter/af_hdcd.c delete mode 100644 libavfilter/buffer.c create mode 100644 libavfilter/interlace.h create mode 100644 libavfilter/tests/.gitignore rename libavfilter/{ => tests}/filtfmts.c (91%) create mode 100644 libavfilter/vf_deinterlace_qsv.c create mode 100644 libavfilter/vf_hwdownload.c create mode 100644 libavfilter/vf_hwupload.c create mode 100644 libavfilter/vf_hwupload_cuda.c create mode 100644 libavfilter/vf_scale_npp.c create mode 100644 libavfilter/vf_scale_qsv.c create mode 100644 libavfilter/vf_scale_vaapi.c create mode 100644 libavfilter/x86/vf_interlace.asm create mode 100644 libavfilter/x86/vf_interlace_init.c create mode 100644 libavformat/.gitignore mode change 100755 => 100644 libavformat/Makefile create mode 100644 libavformat/dashenc.c create mode 100644 libavformat/dss.c create mode 100644 libavformat/g729dec.c create mode 100644 libavformat/mpjpegdec.c create mode 100644 libavformat/oggparsevp8.c create mode 100644 libavformat/protocols.c create mode 100644 libavformat/rtpdec_ac3.c create mode 100644 libavformat/rtpdec_dv.c create mode 100644 libavformat/rtpdec_h261.c create mode 100644 libavformat/rtpdec_hevc.c create mode 100644 libavformat/rtpdec_mpa_robust.c create mode 100644 libavformat/rtpdec_vp9.c create mode 100644 libavformat/rtpenc_h261.c delete mode 100644 libavformat/rtpenc_h264.c create mode 100644 libavformat/rtpenc_h264_hevc.c create mode 100644 libavformat/rtpenc_mpegts.c delete mode 100644 libavformat/seek.c delete mode 100644 libavformat/seek.h create mode 100644 libavformat/tests/.gitignore create mode 100644 libavformat/tests/movenc.c rename libavformat/{noproxy-test.c => tests/noproxy.c} (97%) create mode 100644 libavformat/tests/rtmpdh.c rename libavformat/{seek-test.c => tests/seek.c} (99%) create mode 100644 libavformat/tests/srtp.c rename libavformat/{url-test.c => tests/url.c} (98%) create mode 100644 libavformat/tls.h create mode 100644 libavformat/tls_gnutls.c create mode 100644 libavformat/tls_openssl.c create mode 100644 libavformat/voc_packet.c create mode 100644 libavresample/arm/asm-offsets.h create mode 100644 libavresample/arm/resample_init.c create mode 100644 libavresample/arm/resample_neon.S create mode 100644 libavresample/tests/.gitignore rename libavresample/{avresample-test.c => tests/avresample.c} (99%) create mode 100644 libavutil/.gitignore create mode 100644 libavutil/aarch64/timer.h delete mode 100644 libavutil/audioconvert.h create mode 100644 libavutil/hwcontext.c create mode 100644 libavutil/hwcontext.h create mode 100644 libavutil/hwcontext_cuda.c create mode 100644 libavutil/hwcontext_cuda.h create mode 100644 libavutil/hwcontext_dxva2.c create mode 100644 libavutil/hwcontext_dxva2.h create mode 100644 libavutil/hwcontext_internal.h create mode 100644 libavutil/hwcontext_qsv.c create mode 100644 libavutil/hwcontext_qsv.h create mode 100644 libavutil/hwcontext_vaapi.c create mode 100644 libavutil/hwcontext_vaapi.h create mode 100644 libavutil/hwcontext_vdpau.c create mode 100644 libavutil/hwcontext_vdpau.h delete mode 100644 libavutil/old_pix_fmts.h create mode 100644 libavutil/ppc/float_dsp_vsx.c create mode 100644 libavutil/ppc/float_dsp_vsx.h create mode 100644 libavutil/tests/.gitignore create mode 100644 libavutil/tests/adler32.c create mode 100644 libavutil/tests/aes.c create mode 100644 libavutil/tests/atomic.c create mode 100644 libavutil/tests/avstring.c create mode 100644 libavutil/tests/base64.c create mode 100644 libavutil/tests/blowfish.c create mode 100644 libavutil/tests/cpu.c create mode 100644 libavutil/tests/crc.c create mode 100644 libavutil/tests/des.c create mode 100644 libavutil/tests/eval.c create mode 100644 libavutil/tests/fifo.c create mode 100644 libavutil/tests/float_dsp.c create mode 100644 libavutil/tests/hmac.c create mode 100644 libavutil/tests/lfg.c create mode 100644 libavutil/tests/lls.c create mode 100644 libavutil/tests/md5.c create mode 100644 libavutil/tests/opt.c create mode 100644 libavutil/tests/parseutils.c create mode 100644 libavutil/tests/sha.c create mode 100644 libavutil/tests/tree.c create mode 100644 libavutil/tests/xtea.c create mode 100644 libavutil/time_internal.h create mode 100644 libavutil/wchar_filename.h mode change 100755 => 100644 library.mak create mode 100644 libswscale/tests/.gitignore rename libswscale/{colorspace-test.c => tests/colorspace.c} (98%) rename libswscale/{swscale-test.c => tests/swscale.c} (99%) create mode 100644 tests/.gitignore create mode 100644 tests/checkasm/.gitignore create mode 100644 tests/checkasm/Makefile create mode 100644 tests/checkasm/aarch64/Makefile create mode 100644 tests/checkasm/aarch64/checkasm.S create mode 100644 tests/checkasm/arm/Makefile create mode 100644 tests/checkasm/arm/checkasm.S create mode 100644 tests/checkasm/bswapdsp.c create mode 100644 tests/checkasm/checkasm.c create mode 100644 tests/checkasm/checkasm.h create mode 100644 tests/checkasm/dcadsp.c create mode 100644 tests/checkasm/fmtconvert.c create mode 100644 tests/checkasm/h264dsp.c create mode 100644 tests/checkasm/h264pred.c create mode 100644 tests/checkasm/h264qpel.c create mode 100644 tests/checkasm/hevc_idct.c create mode 100644 tests/checkasm/hevc_mc.c create mode 100644 tests/checkasm/synth_filter.c create mode 100644 tests/checkasm/v210enc.c create mode 100644 tests/checkasm/vp8dsp.c create mode 100644 tests/checkasm/vp9dsp.c create mode 100644 tests/checkasm/x86/Makefile create mode 100644 tests/checkasm/x86/checkasm.asm create mode 100644 tests/fate/canopus.mak create mode 100644 tests/fate/checkasm.mak create mode 100644 tests/fate/mpeg4.mak create mode 100644 tests/ref/fate/aic-oddsize create mode 100644 tests/ref/fate/asf-repldata rename tests/ref/fate/{cllc-argb => canopus-cllc-argb} (81%) rename tests/ref/fate/{cllc-rgb => canopus-cllc-rgb} (93%) rename tests/ref/fate/{cllc-yuy2-noblock => canopus-cllc-yuy2-noblock} (93%) create mode 100644 tests/ref/fate/canopus-hq_hqa-hq create mode 100644 tests/ref/fate/canopus-hq_hqa-hqa create mode 100644 tests/ref/fate/canopus-hq_hqa-inter create mode 100644 tests/ref/fate/canopus-hqx422 create mode 100644 tests/ref/fate/canopus-hqx422a create mode 100644 tests/ref/fate/dds-alpha8 create mode 100644 tests/ref/fate/dds-argb create mode 100644 tests/ref/fate/dds-argb-aexp create mode 100644 tests/ref/fate/dds-dx10-bc1 create mode 100644 tests/ref/fate/dds-dx10-bc1a create mode 100644 tests/ref/fate/dds-dx10-bc2 create mode 100644 tests/ref/fate/dds-dx10-bc3 create mode 100644 tests/ref/fate/dds-dx10-bc4 create mode 100644 tests/ref/fate/dds-dx10-bc5 create mode 100644 tests/ref/fate/dds-dxt1 create mode 100644 tests/ref/fate/dds-dxt1-normalmap create mode 100644 tests/ref/fate/dds-dxt1a create mode 100644 tests/ref/fate/dds-dxt2 create mode 100644 tests/ref/fate/dds-dxt3 create mode 100644 tests/ref/fate/dds-dxt4 create mode 100644 tests/ref/fate/dds-dxt5 create mode 100644 tests/ref/fate/dds-dxt5-aexp create mode 100644 tests/ref/fate/dds-dxt5-normalmap create mode 100644 tests/ref/fate/dds-dxt5-normalmap-ati create mode 100644 tests/ref/fate/dds-dxt5-rbxg create mode 100644 tests/ref/fate/dds-dxt5-rgxb create mode 100644 tests/ref/fate/dds-dxt5-rxbg create mode 100644 tests/ref/fate/dds-dxt5-rxgb create mode 100644 tests/ref/fate/dds-dxt5-xgbr create mode 100644 tests/ref/fate/dds-dxt5-xgxr create mode 100644 tests/ref/fate/dds-dxt5-xrbg create mode 100644 tests/ref/fate/dds-dxt5-ycocg create mode 100644 tests/ref/fate/dds-dxt5-ycocg-scaled create mode 100644 tests/ref/fate/dds-monob create mode 100644 tests/ref/fate/dds-pal create mode 100644 tests/ref/fate/dds-pal-ati create mode 100644 tests/ref/fate/dds-rgb1555 create mode 100644 tests/ref/fate/dds-rgb16 create mode 100644 tests/ref/fate/dds-rgb24 create mode 100644 tests/ref/fate/dds-rgb555 create mode 100644 tests/ref/fate/dds-rgba create mode 100644 tests/ref/fate/dds-rgtc1s create mode 100644 tests/ref/fate/dds-rgtc1u create mode 100644 tests/ref/fate/dds-rgtc2s create mode 100644 tests/ref/fate/dds-rgtc2u create mode 100644 tests/ref/fate/dds-rgtc2u-xy create mode 100644 tests/ref/fate/dds-uyvy create mode 100644 tests/ref/fate/dds-xbgr create mode 100644 tests/ref/fate/dds-xrgb create mode 100644 tests/ref/fate/dds-y create mode 100644 tests/ref/fate/dds-ya create mode 100644 tests/ref/fate/dds-ycocg create mode 100644 tests/ref/fate/dds-yuyv create mode 100644 tests/ref/fate/dpxparser create mode 100644 tests/ref/fate/dss-lp create mode 100644 tests/ref/fate/dss-sp create mode 100644 tests/ref/fate/dxv-dxt1 create mode 100644 tests/ref/fate/dxv-dxt5 create mode 100644 tests/ref/fate/dxv3-dxt1 create mode 100644 tests/ref/fate/dxv3-dxt5 create mode 100644 tests/ref/fate/filter-pixdesc-gbrap create mode 100644 tests/ref/fate/g2m2 create mode 100644 tests/ref/fate/g2m3 create mode 100644 tests/ref/fate/g2m4 create mode 100644 tests/ref/fate/h264-intra-refresh-recovery create mode 100644 tests/ref/fate/h264-invalid-ref-mod create mode 100644 tests/ref/fate/h264-mixed-nal-coding create mode 100644 tests/ref/fate/h264-twofields-packet create mode 100644 tests/ref/fate/h264-unescaped-extradata create mode 100644 tests/ref/fate/hap-chunk create mode 100644 tests/ref/fate/hap1 create mode 100644 tests/ref/fate/hap5 create mode 100644 tests/ref/fate/hapy create mode 100644 tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 create mode 100644 tests/ref/fate/indeo2-delta rename tests/ref/fate/{indeo2 => indeo2-intra} (100%) rename tests/ref/fate/{indeo3 => indeo3-1} (100%) create mode 100644 tests/ref/fate/iscc create mode 100644 tests/ref/fate/lossless-truehd-5.1 create mode 100644 tests/ref/fate/lossless-truehd-5.1-downmix-2.0 create mode 100644 tests/ref/fate/magicyuv-rgb create mode 100644 tests/ref/fate/magicyuv-rgba create mode 100644 tests/ref/fate/magicyuv-y400i create mode 100644 tests/ref/fate/magicyuv-y420 create mode 100644 tests/ref/fate/magicyuv-y422i create mode 100644 tests/ref/fate/magicyuv-y444 create mode 100644 tests/ref/fate/magicyuv-y4444i create mode 100644 tests/ref/fate/movenc create mode 100644 tests/ref/fate/mpeg4-resolution-change-down-down create mode 100644 tests/ref/fate/mpeg4-resolution-change-down-up create mode 100644 tests/ref/fate/mpeg4-resolution-change-up-down create mode 100644 tests/ref/fate/mpeg4-resolution-change-up-up create mode 100644 tests/ref/fate/mss1 create mode 100644 tests/ref/fate/mts2 create mode 100644 tests/ref/fate/pict create mode 100644 tests/ref/fate/ra3-144 create mode 100644 tests/ref/fate/rscc-16bit create mode 100644 tests/ref/fate/rscc-24bit create mode 100644 tests/ref/fate/rscc-32bit create mode 100644 tests/ref/fate/rtmpdh create mode 100644 tests/ref/fate/screenpresso-16bit create mode 100644 tests/ref/fate/screenpresso-24bit create mode 100644 tests/ref/fate/screenpresso-32bit create mode 100644 tests/ref/fate/sgi-gray16-rle rename tests/ref/fate/{sgi-gray => sgi-gray8} (100%) create mode 100644 tests/ref/fate/sgi-gray8-rle create mode 100644 tests/ref/fate/sgi-rgba-rle create mode 100644 tests/ref/fate/svq1-headerswap create mode 100644 tests/ref/fate/tdsc create mode 100644 tests/ref/fate/theora-offset create mode 100644 tests/ref/fate/truemotion2rt-high create mode 100644 tests/ref/fate/truemotion2rt-low create mode 100644 tests/ref/fate/truemotion2rt-mid rename tests/ref/fate/{tscc2 => tscc2-avi} (100%) create mode 100644 tests/ref/fate/tscc2-mov create mode 100644 tests/ref/fate/txd-odd create mode 100644 tests/ref/fate/vc1_ilaced_twomv create mode 100644 tests/ref/fate/webp create mode 100644 tests/ref/fate/wmv8-intrax8 rename tests/ref/fate/{xvid-idctmmx => xvid-idct} (100%) create mode 100644 tests/ref/vsynth/vsynth1-v210-10 create mode 100644 tests/ref/vsynth/vsynth2-v210-10 create mode 100644 tools/.gitignore create mode 100644 tools/sidxindex.c diff --git a/.gitignore b/.gitignore index 19bb757..e71246c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,46 +17,13 @@ *.so.* *.swp *.ver -*-example -*-test /.config /.version /avconv /avplay /avprobe +/avversion.h /config.* /coverage.info -/version.h -/doc/*.1 -/doc/*.html -/doc/*.pod -/doc/avoptions_codec.texi -/doc/avoptions_format.texi -/doc/doxy/html/ -/doc/examples/avcodec -/doc/examples/filter_audio -/doc/examples/metadata -/doc/examples/output -/doc/examples/transcode_aac -/doc/print_options /lcov/ -/libavcodec/*_tablegen -/libavcodec/*_tables.c -/libavcodec/*_tables.h -/libavutil/avconfig.h -/tests/audiogen -/tests/base64 -/tests/data/ -/tests/pixfmts.mak -/tests/rotozoom -/tests/tiny_psnr -/tests/videogen -/tests/vsynth1/ -/tools/aviocat -/tools/cws2fws -/tools/graph2dot -/tools/ismindex -/tools/pktdumper -/tools/probetest -/tools/qt-faststart -/tools/trasher +/mapfile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8e9629a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: c +sudo: false +os: + - linux + - osx +addons: + apt: + packages: + - yasm + - diffutils +compiler: + - clang + - gcc +cache: + directories: + - libav-samples +before_install: + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update --all; fi +install: + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install yasm; fi +script: + - mkdir -p libav-samples + - ./configure --samples=libav-samples --cc=$CC + - make -j 8 + - make fate-rsync + - make check -j 8 diff --git a/Changelog b/Changelog index 9fc1556..1a314e7 100644 --- a/Changelog +++ b/Changelog @@ -1,108 +1,121 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. -version 11.4: - - - h264: Make sure reinit failures mark the context as not initialized (CVE-2015-3417) - - msrle: Use FFABS to determine the frame size in msrle_decode_pal4 (CVE-2015-3395) - - cavs: Remove an unneeded scratch buffer - - configure: Disable i686 for i586 and lower CPUs (debian/783082) - - mjpegenc: Fix JFIF header byte ordering (bug/808) - - nut: Make sure to clean up on read_header failure - - png: Set the color range as full range - - avi: Validate sample_size - - nut: Check chapter creation in decode_info_header - - alac: Reject rice_limit 0 if compression is used - - ape: Support _0000 files with nblock smaller than 64 - - mux: Do not leave stale side data pointers in ff_interleave_add_packet() - - avresample: Reallocate the internal buffer to the correct size (bug/825) - - mpegts: Update the PSI/SI table only if the version change - - rtsp: Make sure we don't write too many transport entries into a fixed-size array - - rtpenc_jpeg: Handle case of picture dimensions not dividing by 8 - - mov: Fix little endian audio detection - - x86: Put COPY3_IF_LT under HAVE_6REGS (gentoo/541930) - - roqvideoenc: set enc->avctx in roq_encode_init - - mp3: Properly use AVCodecContext API - - libvpx: Fix mixed use of av_malloc() and av_reallocp() - - Revert "lavfi: always check av_expr_parse_and_eval() return value" - - alsdec: only adapt order for positive max_order - - alsdec: check sample pointer range in revert_channel_correlation - - aacpsy: correct calculation of minath in psy_3gpp_init - - alsdec: limit avctx->bits_per_raw_sample to 32 - - aasc: return correct buffer size from aasc_decode_frame - - matroskadec: fix crash when parsing invalid mkv - - avconv: do not overwrite the stream codec context for streamcopy - - webp: ensure that each transform is only used once - - h264_ps: properly check cropping parameters against overflow - - hevc: zero the correct variables on invalid crop parameters - - hevc: make the crop sizes unsigned - -version 11.3: - -- utvideodec: Handle slice_height being zero (CVE-2014-9604) -- adxdec: set avctx->channels in adx_read_header -- rmenc: limit packet size -- webp: validate the distance prefix code -- rv10: check size of s->mb_width * s->mb_height -- eamad: check for out of bounds read (CID/1257500) -- mdec: check for out of bounds read (CID/1257501) -- configure: Properly fail when libcdio/cdparanoia is not found -- tiff: Check that there is no aliasing in pixel format selection (CVE-2014-8544) -- aic: Fix decoding files with odd dimensions -- vorbis: Check the vlc value in setup_classifs -- arm: Suppress tags about used cpu arch and extensions -- prores: Extend the padding check to 16bit -- icecast: Do not use chunked post, allows feeding to icecast properly -- img2dec: correctly use the parsed value from -start_number -- h264_cabac: Break infinite loops -- hevc_deblock: Fix compilation with nasm (libav #795) -- h264: initialize H264Context.avctx in init_thread_copy -- h264: Do not share rbsp_buffer across threads -- h264: only ref cur_pic in update_thread_context if it is initialized -- matroskadec: Fix read-after-free in matroska_read_seek() (chromium #427266) -- log: Unbreak no-tty support on 256color terminals - -version 11.2: - -- h264: restore a block mistakenly removed in e10fd08a (libav #781) -- on2avc: check number of channels (CVE-2014-8549) -- smc: fix the bounds check (CVE-2014-8548) -- gifdec: refactor interleave end handling (CVE-2014-8547) -- mmvideo: check frame dimensions (CVE-2014-8543) -- jvdec: check frame dimensions (CVE-2014-8542) -- mjpegdec: check for pixel format changes (CVE-2014-8541) -- mov: avoid a memleak when multiple stss boxes are present -- vc1: Do not assume seek happens after decoding -- avconv: Use the mpeg12 private option scan_offset (debian/773055) -- xsub: Support DXSA subtitles -- mp3dec: fix reading the Xing tag -- matroskaenc: write correct Display{Width, Height} in stereo encoding -- configure: Fix enabling memalign_hack automatically -- mp3enc: fix a triggerable assert -- latm: Do not give a score for a single instance -- mp3: Tweak the probe scores -- matroskaenc: write correct Display{Width, Height} in stereo encoding -- configure: Fix enabling memalign_hack automatically -- coverity: Fix most of the reported warnings and issues - -version 11.1: - -- Replace lena.pnm (debian#771126) -- Treat all '*.pnm' files as non-text file -- opusdec: make sure all substreams have the same number of coded samples -- lavu: fix memory leaks by using a mutex instead of atomics -- lavu: add wrappers for the pthreads mutex API -- mp3enc: fix a triggerable assert -- resample: Avoid off-by-1 errors in PTS calcs. (libav#753) -- imc: fix order of operations in coefficients read -- hevc_mvs: make sure to always initialize the temporal MV fully -- hevc_mvs: initialize the temporal MV in case of missing ref -- h264: reset ret to avoid propagating minor failures (libav#750 / lp#905753) -- hevc: Initialize mergecand_list to 0 -- mpeg12: Always invoke the get_format() callback -- h264: Always invoke the get_format() callback -- Update default FATE URL for release/11 -- apetag: Fix APE tag size check +version 12.1: + + - vaapi_h264: fix RefPicList[] field flags. + - libilbc: support for latest git of libilbc + - libopusdec: default to stereo for invalid number of channels + - avpacket: fix leak on realloc in av_packet_add_side_data() + - mpegvideo: Return correct coded frame sizes from parser + - hwcontext_vaapi: Don't abort on failing to allocate from a fixed-size pool + - mov: Update colr values + - avconv: Fix the audio next dts computation + - mss2: only use error correction for matching block counts + - h264_slice: Wait for refs to be available before we use them in error concealment + - hevc: decouple calling get_format() from exporting the SPS parameters + - hevcdec: do not set decoder-global SPS prematurely + - mov: fix a possible invalid read in mov_read_mac_string() (bug/972, bug/1003) + - mpegvideo_parser: avoid signed overflow in bitrate calculation (bug/981) + - mpeg12dec: avoid signed overflow in bitrate calculation (bug/981) + - mpeg12dec: move setting first_field to mpeg_field_start() (bug/999) + - h264dec: make sure to only end a field if it has been started (bug/977, bug/978, bug/992) + - matroskadec: fix SRT subtitle duration + - http: Check for negative chunk sizes + - cmdutils: update copyright year to 2017 + - matroskadec: make sure not to leave EbmlBin in an inconsistent state (bug/1001) + - asfdec: Use the ASF stream count when iterating + - aac: Validate the sbr sample rate before using the value (bug/1027) + - mov: Do not try to parse multiple stsd for the same track (bug/1017) + - vf_fade: Make sure to not miss the last lines of a frame + - asfdec: Account for different Format Data sizes (bug/1020) + - asfdec: fix reading files larger than 2GB + - h264dec: fix dropped initial SEI recovery point + - rtmppkt: Check for packet size mismatches + - apetag: fix flag value to signal footer presence + - apetag: account for header size if present when returning the start position + - lavc: make sure not to return EAGAIN from codecs + - h264dec: initialize field_started to 0 on each decode call (bug/1019) + - h2645_parse: use the bytestream2 API for packet splitting (bug/1002) + - h264_cavlc: check the value of run_before (bug/1000) + - nsvdec: don't ignore the return value of av_get_packet() (bug/1039) + - mpeg4videodec: raise an error if sprite_trajectory.table is NULL (bug/1012) + - dca: Validate the channel map (bug/1016) + - avformat: Free the internal codec context at the end + - dca: Account for lfe when checking for the channel count (bug/1037) + - flv: Validate the packet size (bug/1041) + - mjpeg: Report non-3 component rgb lossless as not supported (bug/1043) + - mm: Skip unexpected audio packets (bug/1046) + - vc1dec: raise an error if sprite picture data is missing (bug/1013) + - avplay: Do not try to allocate new frames when the player is closing (bug/1052) + - avprobe: Handle unknown values for the color description (bug/1040) + - aacsbr: Turnoff in the event of over read. (bug/1047) + - h264_refs: validate the SPS pointer in ff_h264_execute_ref_pic_marking() (bug/1036) + +version 12: +- aliases and defaults for Ogg subtypes (opus, spx) +- HEVC/H.265 RTP payload format (draft v6) packetizer and depacketizer +- avplay now exits by default at the end of playback +- XCB-based screen-grabber +- creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer +- H.261 RTP payload format (RFC 4587) depacketizer and experimental packetizer +- RTP/mpegts muxer +- VP8 in Ogg demuxing +- OpenH264 encoder wrapper +- Support DNx100 (960x720@8) +- Direct3D11-accelerated decoding +- DXVA2-accelerated HEVC decoding +- AAC ELD 480 decoding +- Intel QSV-accelerated H.264 decoding +- DSS SP decoder and DSS demuxer +- RTP depacketizer for AC3 payload format (RFC 4184) +- RTP depacketizer for loss tolerant payload format for MP3 audio (RFC 5219) +- RTP depacketizer for DV (RFC 6469) +- Canopus HQX decoder +- RTP depacketization of T.140 text (RFC 4103) +- VP9 RTP payload format (draft 0) experimental depacketizer +- TDSC decoder +- DTS lossless extension (XLL) decoding (not lossless, disabled by default) +- Intel QSV-accelerated H.264 encoding +- MMAL-accelerated H.264 decoding +- DTS decoding through libdcadec +- Canopus HQ/HQA decoder +- Automatically rotate videos based on metadata in avconv +- improved Quickdraw compatibility +- NVIDIA NVENC-accelerated H.264 and HEVC encoding support +- Multipart JPEG demuxer +- Support the extended vp9 profiles in the libvpx wrapper +- Hap decoder and encoder +- DirectDraw Surface image/texture decoder +- rewritten ASF demuxer +- Go2Meeting decoding support +- Intel QSV-accelerated MPEG-2 video and HEVC encoding +- bitstream filter for converting HEVC from MP4 to Annex B +- Intel QSV-accelerated MPEG-2 video and HEVC decoding +- Support DNx100 (1440x1080@8) +- DXV decoding +- Screenpresso SPV1 decoding +- zero-copy Intel QSV transcoding in avconv +- libkvazaar HEVC encoder +- innoHeim/Rsupport Screen Capture Codec decoder +- support encoding 16-bit RLE SGI images +- support Apple AVFoundation video capture +- G.723.1 muxer and encoder +- compressed SWF +- VAAPI-accelerated format conversion and scaling +- libnpp/CUDA-accelerated format conversion and scaling +- VAAPI-accelerate H.264/HEVC/MJPEG encoding +- Generic OpenMAX IL encoder with support for Raspberry Pi +- MMAL-accelerated MPEG-2 and VC-1 decoding +- G.729 raw demuxer +- MagicYUV decoder +- Duck TrueMotion 2.0 Real Time decoder +- Intel QSV video scaling and deinterlacing filter +- Support MOV with multiple sample description tables +- OpenH264 decoder wrapper +- Removed the legacy X11 screen grabber, use XCB instead +- HDCD decoding filter through libhdcd + version 11: - libx265 encoder @@ -423,7 +436,7 @@ version 0.7_beta2: - DPX image encoder - SMPTE 302M AES3 audio decoder - ffmpeg no longer quits after the 'q' key is pressed; use 'ctrl+c' instead -- 9bit and 10bit per sample support in the H.264 decoder +- 9 bits and 10 bits per sample support in the H.264 decoder version 0.7_beta1: @@ -778,7 +791,7 @@ version 0.4.9-pre1: - rate distorted optimal lambda->qp support - AAC encoding with libfaac - Sunplus JPEG codec (SP5X) support -- use Lagrange multipler instead of QP for ratecontrol +- use Lagrange multiplier instead of QP for ratecontrol - Theora/VP3 decoding support - XA and ADX ADPCM codecs - export MPEG-2 active display area / pan scan diff --git a/LICENSE b/LICENSE index 701e6e1..a2de35c 100644 --- a/LICENSE +++ b/LICENSE @@ -13,7 +13,6 @@ configure to activate them. In this case, Libav's license changes to GPL v2+. Specifically, the GPL parts of Libav are -- the X11 grabber in libavdevice/x11grab.c - the texi2pod.pl tool - the following filters in libavfilter: - vf_blackframe.c @@ -62,5 +61,5 @@ incompatible libraries The Fraunhofer AAC library, FAAC and OpenSSL are under licenses incompatible with all (L)GPL versions. Thus, unfortunately, since both licenses cannot be satisfied simultaneously, binaries resulting from the combination of Libav -with these libraries are nonfree und unredistributable. If you wish to enable +with these libraries are nonfree and unredistributable. If you wish to enable any of these libraries nonetheless, pass --enable-nonfree to configure. diff --git a/Makefile b/Makefile index cc016b3..4e026b0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ include config.mak vpath %.c $(SRC_PATH) +vpath %.m $(SRC_PATH) vpath %.h $(SRC_PATH) vpath %.S $(SRC_PATH) vpath %.asm $(SRC_PATH) @@ -26,6 +27,8 @@ IFLAGS := -I. -I$(SRC_PATH) CPPFLAGS := $(IFLAGS) $(CPPFLAGS) CFLAGS += $(ECFLAGS) CCFLAGS = $(CPPFLAGS) $(CFLAGS) +OBJCFLAGS += $(EOBJCFLAGS) +OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS) ASFLAGS := $(CPPFLAGS) $(ASFLAGS) YASMFLAGS += $(IFLAGS:%=%/) -Pconfig.asm HOSTCCFLAGS = $(IFLAGS) $(HOSTCPPFLAGS) $(HOSTCFLAGS) @@ -38,6 +41,7 @@ endef COMPILE_C = $(call COMPILE,CC) COMPILE_S = $(call COMPILE,AS) +COMPILE_M = $(call COMPILE,OBJCC) COMPILE_HOSTC = $(call COMPILE,HOSTCC) %.o: %.c @@ -46,6 +50,9 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) %.o: %.S $(COMPILE_S) +%.o: %.m + $(COMPILE_M) + %_host.o: %.c $(COMPILE_HOSTC) @@ -55,10 +62,7 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) %.h.c: $(Q)echo '#include "$*.h"' >$@ -%.ver: %.v - $(Q)sed 's/$$MAJOR/$($(basename $(@F))_VERSION_MAJOR)/' $^ > $@ - -%.c %.h: TAG = GEN +%.c %.h %.ver: TAG = GEN AVPROGS-$(CONFIG_AVCONV) += avconv AVPROGS-$(CONFIG_AVPLAY) += avplay @@ -73,9 +77,11 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(EXESUF)) $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o)) OBJS-avconv += avconv_opt.o avconv_filter.o -OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o -OBJS-avconv-$(HAVE_DXVA2_LIB) += avconv_dxva2.o +OBJS-avconv-$(CONFIG_LIBMFX) += avconv_qsv.o +OBJS-avconv-$(CONFIG_VAAPI) += avconv_vaapi.o OBJS-avconv-$(CONFIG_VDA) += avconv_vda.o +OBJS-avconv-$(HAVE_DXVA2_LIB) += avconv_dxva2.o +OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o TESTTOOLS = audiogen videogen rotozoom tiny_psnr base64 HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options @@ -94,12 +100,14 @@ FFLIBS := avutil DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.avpreset) -SKIPHEADERS = cmdutils_common_opts.h compat/w32pthreads.h +SKIPHEADERS = cmdutils_common_opts.h \ + compat/w32pthreads.h include $(SRC_PATH)/common.mak FF_EXTRALIBS := $(FFEXTRALIBS) FF_DEP_LIBS := $(DEP_LIBS) +FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS) all: $(AVPROGS) @@ -162,8 +170,8 @@ GIT_LOG = $(SRC_PATH)/.git/logs/HEAD .version: $(wildcard $(GIT_LOG)) $(VERSION_SH) config.mak .version: M=@ -version.h .version: - $(M)$(VERSION_SH) $(SRC_PATH) version.h $(EXTRA_VERSION) +avversion.h .version: + $(M)$(VERSION_SH) $(SRC_PATH) avversion.h $(EXTRA_VERSION) $(Q)touch .version # force version.sh to run whenever version might have changed @@ -204,7 +212,8 @@ clean:: distclean:: $(RM) $(DISTCLEANSUFFIXES) - $(RM) config.* .config libavutil/avconfig.h .version version.h + $(RM) config.* .config libavutil/avconfig.h .version avversion.h \ + mapfile libavcodec/bsf_list.c libavformat/protocol_list.c config: $(SRC_PATH)/configure $(value LIBAV_CONFIGURATION) diff --git a/README.md b/README.md index 2dc668a..169f878 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Libav ===== +[![Build Status](https://travis-ci.org/libav/libav.svg)](https://travis-ci.org/libav/libav) + Libav is a collection of libraries and tools to process multimedia content such as audio, video, subtitles and related metadata. diff --git a/RELEASE b/RELEASE index 1c7134d..40e6bd9 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -11.4 +12.1 diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..40e6bd9 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +12.1 diff --git a/arch.mak b/arch.mak index 4bfc883..720062a 100644 --- a/arch.mak +++ b/arch.mak @@ -5,6 +5,7 @@ OBJS-$(HAVE_VFP) += $(VFP-OBJS) $(VFP-OBJS-yes) OBJS-$(HAVE_NEON) += $(NEON-OBJS) $(NEON-OBJS-yes) OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes) +OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes) OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes) OBJS-$(HAVE_YASM) += $(YASM-OBJS) $(YASM-OBJS-yes) diff --git a/avconv.c b/avconv.c index 66148c0..b2affe9 100644 --- a/avconv.c +++ b/avconv.c @@ -1,6 +1,6 @@ /* * avconv main - * Copyright (c) 2000-2011 The libav developers. + * Copyright (c) 2000-2011 The Libav developers * * This file is part of Libav. * @@ -38,6 +38,7 @@ #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/fifo.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" @@ -86,15 +87,13 @@ static FILE *vstats_file; static int nb_frames_drop = 0; - +static int want_sdp = 1; #if HAVE_PTHREADS /* signal to input threads that they should exit; set by the main thread */ static int transcoding_finished; #endif -#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass" - InputStream **input_streams = NULL; int nb_input_streams = 0; InputFile **input_files = NULL; @@ -148,12 +147,23 @@ static void avconv_cleanup(int ret) FilterGraph *fg = filtergraphs[i]; avfilter_graph_free(&fg->graph); for (j = 0; j < fg->nb_inputs; j++) { + while (av_fifo_size(fg->inputs[j]->frame_queue)) { + AVFrame *frame; + av_fifo_generic_read(fg->inputs[j]->frame_queue, &frame, + sizeof(frame), NULL); + av_frame_free(&frame); + } + av_fifo_free(fg->inputs[j]->frame_queue); + av_buffer_unref(&fg->inputs[j]->hw_frames_ctx); av_freep(&fg->inputs[j]->name); av_freep(&fg->inputs[j]); } av_freep(&fg->inputs); for (j = 0; j < fg->nb_outputs; j++) { av_freep(&fg->outputs[j]->name); + av_freep(&fg->outputs[j]->formats); + av_freep(&fg->outputs[j]->channel_layouts); + av_freep(&fg->outputs[j]->sample_rates); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); @@ -176,16 +186,16 @@ static void avconv_cleanup(int ret) } for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - AVBitStreamFilterContext *bsfc = ost->bitstream_filters; - while (bsfc) { - AVBitStreamFilterContext *next = bsfc->next; - av_bitstream_filter_close(bsfc); - bsfc = next; - } - ost->bitstream_filters = NULL; + + for (j = 0; j < ost->nb_bitstream_filters; j++) + av_bsf_free(&ost->bsf_ctx[j]); + av_freep(&ost->bsf_ctx); + av_freep(&ost->bitstream_filters); + av_frame_free(&ost->filtered_frame); av_parser_close(ost->parser); + avcodec_free_context(&ost->parser_avctx); av_freep(&ost->forced_keyframes); av_freep(&ost->avfilter); @@ -193,6 +203,15 @@ static void avconv_cleanup(int ret) avcodec_free_context(&ost->enc_ctx); + if (ost->muxing_queue) { + while (av_fifo_size(ost->muxing_queue)) { + AVPacket pkt; + av_log(NULL, AV_LOG_INFO, "after av_fifo_size()\n"); + av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + av_fifo_free(ost->muxing_queue); + } av_freep(&output_streams[i]); } for (i = 0; i < nb_input_files; i++) { @@ -250,76 +269,38 @@ static void abort_codec_experimental(AVCodec *c, int encoder) "results.\nAdd '-strict experimental' if you want to use it.\n", codec_string, c->name); codec = encoder ? avcodec_find_encoder(c->id) : avcodec_find_decoder(c->id); - if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) + if (!(codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL)) av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n", codec_string, codec->name); exit_program(1); } -/* - * Update the requested input sample format based on the output sample format. - * This is currently only used to request float output from decoders which - * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT. - * Ideally this will be removed in the future when decoders do not do format - * conversion and only output in their native format. - */ -static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec, - AVCodecContext *enc) +static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) { - /* if sample formats match or a decoder sample format has already been - requested, just return */ - if (enc->sample_fmt == dec->sample_fmt || - dec->request_sample_fmt > AV_SAMPLE_FMT_NONE) - return; + AVFormatContext *s = of->ctx; + AVStream *st = ost->st; + int ret; - /* if decoder supports more than one output format */ - if (dec_codec && dec_codec->sample_fmts && - dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE && - dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) { - const enum AVSampleFormat *p; - int min_dec = INT_MAX, min_inc = INT_MAX; - enum AVSampleFormat dec_fmt = AV_SAMPLE_FMT_NONE; - enum AVSampleFormat inc_fmt = AV_SAMPLE_FMT_NONE; - - /* find a matching sample format in the encoder */ - for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) { - if (*p == enc->sample_fmt) { - dec->request_sample_fmt = *p; - return; - } else { - enum AVSampleFormat dfmt = av_get_packed_sample_fmt(*p); - enum AVSampleFormat efmt = av_get_packed_sample_fmt(enc->sample_fmt); - int fmt_diff = 32 * abs(dfmt - efmt); - if (av_sample_fmt_is_planar(*p) != - av_sample_fmt_is_planar(enc->sample_fmt)) - fmt_diff++; - if (dfmt == efmt) { - min_inc = fmt_diff; - inc_fmt = *p; - } else if (dfmt > efmt) { - if (fmt_diff < min_inc) { - min_inc = fmt_diff; - inc_fmt = *p; - } - } else { - if (fmt_diff < min_dec) { - min_dec = fmt_diff; - dec_fmt = *p; - } - } + if (!of->header_written) { + AVPacket tmp_pkt; + /* the muxer is not initialized yet, buffer the packet */ + if (!av_fifo_space(ost->muxing_queue)) { + int new_size = FFMIN(2 * av_fifo_size(ost->muxing_queue), + ost->max_muxing_queue_size); + if (new_size <= av_fifo_size(ost->muxing_queue)) { + av_log(NULL, AV_LOG_ERROR, + "Too many packets buffered for output stream %d:%d.\n", + ost->file_index, ost->st->index); + exit_program(1); } + ret = av_fifo_realloc2(ost->muxing_queue, new_size); + if (ret < 0) + exit_program(1); } - - /* if none match, provide the one that matches quality closest */ - dec->request_sample_fmt = min_inc != INT_MAX ? inc_fmt : dec_fmt; + av_packet_move_ref(&tmp_pkt, pkt); + av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); + return; } -} - -static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) -{ - AVBitStreamFilterContext *bsfc = ost->bitstream_filters; - AVCodecContext *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec; - int ret; /* * Audio encoders may split the packets -- #frames in != #packets out. @@ -328,37 +309,22 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) * Counting encoded video frames needs to be done separately because of * reordering, see do_video_out() */ - if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) { + if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) { if (ost->frame_number >= ost->max_frames) { - av_free_packet(pkt); + av_packet_unref(pkt); return; } ost->frame_number++; } + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + NULL); + ost->quality = sd ? *(int *)sd : -1; - 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 & AV_PKT_FLAG_KEY); - if (a > 0) { - av_free_packet(pkt); - new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, - av_buffer_default_free, NULL, 0); - if (!new_pkt.buf) - exit_program(1); - } else if (a < 0) { - av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s", - bsfc->filter->name, pkt->stream_index, - avctx->codec ? avctx->codec->name : "copy"); - print_error("", a); - if (exit_on_error) - exit_program(1); + if (ost->frame_rate.num) { + pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), + ost->mux_timebase); } - *pkt = new_pkt; - - bsfc = bsfc->next; } if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS) && @@ -384,6 +350,8 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) ost->packets_written++; pkt->stream_index = ost->index; + av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); + ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { print_error("av_interleaved_write_frame()", ret); @@ -391,6 +359,49 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } } +static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) +{ + int ret = 0; + + /* apply the output bitstream filters, if any */ + if (ost->nb_bitstream_filters) { + int idx; + + ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt); + if (ret < 0) + goto finish; + + idx = 1; + while (idx) { + /* get a packet from the previous filter up the chain */ + ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt); + if (ret == AVERROR(EAGAIN)) { + ret = 0; + idx--; + continue; + } else if (ret < 0) + goto finish; + + /* send it to the next filter down the chain or to the muxer */ + if (idx < ost->nb_bitstream_filters) { + ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt); + if (ret < 0) + goto finish; + idx++; + } else + write_packet(of, pkt, ost); + } + } else + write_packet(of, pkt, ost); + +finish: + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_FATAL, "Error applying bitstream filters to an output " + "packet for stream #%d:%d.\n", ost->file_index, ost->index); + exit_program(1); + } +} + static int check_recording_time(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -404,12 +415,12 @@ static int check_recording_time(OutputStream *ost) return 1; } -static void do_audio_out(AVFormatContext *s, OutputStream *ost, +static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; AVPacket pkt; - int got_packet = 0; + int ret; av_init_packet(&pkt); pkt.data = NULL; @@ -422,18 +433,27 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, ost->samples_encoded += frame->nb_samples; ost->frames_encoded++; - if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) { - av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); - exit_program(1); - } + ret = avcodec_send_frame(enc, frame); + if (ret < 0) + goto error; + + while (1) { + ret = avcodec_receive_packet(enc, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + goto error; - if (got_packet) { - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); - write_frame(s, &pkt, ost); + output_packet(of, &pkt, ost); } + + return; +error: + av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); + exit_program(1); } -static void do_subtitle_out(AVFormatContext *s, +static void do_subtitle_out(OutputFile *of, OutputStream *ost, InputStream *ist, AVSubtitle *sub, @@ -489,7 +509,7 @@ static void do_subtitle_out(AVFormatContext *s, av_init_packet(&pkt); pkt.data = subtitle_out; pkt.size = subtitle_out_size; - pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base); + pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling it in the codec would be better */ @@ -498,11 +518,11 @@ static void do_subtitle_out(AVFormatContext *s, else pkt.pts += 90 * sub->end_display_time; } - write_frame(s, &pkt, ost); + output_packet(of, &pkt, ost); } } -static void do_video_out(AVFormatContext *s, +static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *in_picture, int *frame_size) @@ -515,8 +535,8 @@ static void do_video_out(AVFormatContext *s, format_video_sync = video_sync_method; if (format_video_sync == VSYNC_AUTO) - format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : - (s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR; + format_video_sync = (of->ctx->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : + (of->ctx->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR; if (format_video_sync != VSYNC_PASSTHROUGH && ost->frame_number && in_picture->pts != AV_NOPTS_VALUE && @@ -543,67 +563,61 @@ static void do_video_out(AVFormatContext *s, if (ost->frame_number >= ost->max_frames) return; - if (s->oformat->flags & AVFMT_RAWPICTURE && - enc->codec->id == AV_CODEC_ID_RAWVIDEO) { - /* raw pictures are written as AVPicture structure to - avoid any copies. We support temporarily the older - method. */ - enc->coded_frame->interlaced_frame = in_picture->interlaced_frame; - enc->coded_frame->top_field_first = in_picture->top_field_first; - pkt.data = (uint8_t *)in_picture; - pkt.size = sizeof(AVPicture); - pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base); - pkt.flags |= AV_PKT_FLAG_KEY; - - write_frame(s, &pkt, ost); - } else { - int got_packet; + if (enc->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && + ost->top_field_first >= 0) + in_picture->top_field_first = !!ost->top_field_first; - if (enc->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) && - ost->top_field_first >= 0) - in_picture->top_field_first = !!ost->top_field_first; + in_picture->quality = enc->global_quality; + in_picture->pict_type = 0; + if (ost->forced_kf_index < ost->forced_kf_count && + in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) { + in_picture->pict_type = AV_PICTURE_TYPE_I; + ost->forced_kf_index++; + } - in_picture->quality = enc->global_quality; - if (!enc->me_threshold) - in_picture->pict_type = 0; - if (ost->forced_kf_index < ost->forced_kf_count && - in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) { - in_picture->pict_type = AV_PICTURE_TYPE_I; - ost->forced_kf_index++; - } + ost->frames_encoded++; - ost->frames_encoded++; + ret = avcodec_send_frame(enc, in_picture); + if (ret < 0) + goto error; - ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); - exit_program(1); - } + /* + * For video, there may be reordering, so we can't throw away frames on + * encoder flush, we need to limit them here, before they go into encoder. + */ + ost->frame_number++; + + while (1) { + ret = avcodec_receive_packet(enc, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + goto error; - if (got_packet) { - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); - write_frame(s, &pkt, ost); - *frame_size = pkt.size; + output_packet(of, &pkt, ost); + *frame_size = pkt.size; - /* if two pass, output log */ - if (ost->logfile && enc->stats_out) { - fprintf(ost->logfile, "%s", enc->stats_out); - } + /* if two pass, output log */ + if (ost->logfile && enc->stats_out) { + fprintf(ost->logfile, "%s", enc->stats_out); } + + ost->sync_opts++; } - ost->sync_opts++; - /* - * For video, number of frames in == number of packets out. - * But there may be reordering, so we can't throw away frames on encoder - * flush, we need to limit them here, before they go into encoder. - */ - ost->frame_number++; + + return; +error: + av_assert0(ret != AVERROR(EAGAIN) && ret != AVERROR_EOF); + av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); + exit_program(1); } +#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME static double psnr(double d) { return -10.0 * log(d) / log(10.0); } +#endif static void do_video_stats(OutputStream *ost, int frame_size) { @@ -623,9 +637,15 @@ static void do_video_stats(OutputStream *ost, int frame_size) enc = ost->enc_ctx; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { frame_number = ost->frame_number; - fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality / (float)FF_QP2LAMBDA); - if (enc->flags&CODEC_FLAG_PSNR) + fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); + +#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + if (enc->flags & AV_CODEC_FLAG_PSNR) fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0] / (enc->width * enc->height * 255.0 * 255.0))); +FF_ENABLE_DEPRECATION_WARNINGS +#endif fprintf(vstats_file,"f_size= %6d ", frame_size); /* compute pts value */ @@ -637,10 +657,16 @@ static void do_video_stats(OutputStream *ost, int frame_size) avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0; fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(enc->coded_frame->pict_type)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } +static int init_output_stream(OutputStream *ost, char *error, int error_len); + /* * Read one frame for lavfi output for ost and encode it. */ @@ -655,8 +681,18 @@ static int poll_filter(OutputStream *ost) } filtered_frame = ost->filtered_frame; + if (!ost->initialized) { + char error[1024]; + ret = init_output_stream(ost, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + exit_program(1); + } + } + if (ost->enc->type == AVMEDIA_TYPE_AUDIO && - !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) + !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame, ost->enc_ctx->frame_size); else @@ -680,12 +716,12 @@ static int poll_filter(OutputStream *ost) if (!ost->frame_aspect_ratio) ost->enc_ctx->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; - do_video_out(of->ctx, ost, filtered_frame, &frame_size); + do_video_out(of, ost, filtered_frame, &frame_size); if (vstats_filename && frame_size) do_video_stats(ost, frame_size); break; case AVMEDIA_TYPE_AUDIO: - do_audio_out(of->ctx, ost, filtered_frame); + do_audio_out(of, ost, filtered_frame); break; default: // TODO support subtitle filters @@ -730,7 +766,17 @@ static int poll_filters(void) for (i = 0; i < nb_output_streams; i++) { int64_t pts = output_streams[i]->sync_opts; - if (!output_streams[i]->filter || output_streams[i]->finished) + if (output_streams[i]->filter && !output_streams[i]->filter->graph->graph && + !output_streams[i]->filter->graph->nb_inputs) { + ret = configure_filtergraph(output_streams[i]->filter->graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } + } + + if (!output_streams[i]->filter || output_streams[i]->finished || + !output_streams[i]->filter->graph->graph) continue; pts = av_rescale_q(pts, output_streams[i]->enc_ctx->time_base, @@ -877,7 +923,7 @@ static void print_report(int is_last_report, int64_t timer_start) if (!is_last_report) { int64_t cur_time; /* display the report every 0.5 seconds */ - cur_time = av_gettime(); + cur_time = av_gettime_relative(); if (last_time == -1) { last_time = cur_time; return; @@ -908,13 +954,14 @@ static void print_report(int is_last_report, int64_t timer_start) float q = -1; ost = output_streams[i]; enc = ost->enc_ctx; - if (!ost->stream_copy && enc->coded_frame) - q = enc->coded_frame->quality / (float)FF_QP2LAMBDA; + if (!ost->stream_copy) + q = ost->quality / (float) FF_QP2LAMBDA; + if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q); } if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { - float t = (av_gettime() - timer_start) / 1000000.0; + float t = (av_gettime_relative() - timer_start) / 1000000.0; frame_number = ost->frame_number; snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ", @@ -929,7 +976,10 @@ static void print_report(int is_last_report, int64_t timer_start) for (j = 0; j < 32; j++) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log2(qp_histogram[j] + 1))); } - if (enc->flags&CODEC_FLAG_PSNR) { + +#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + if (enc->flags & AV_CODEC_FLAG_PSNR) { int j; double error, error_sum = 0; double scale, scale_sum = 0; @@ -951,10 +1001,12 @@ static void print_report(int is_last_report, int64_t timer_start) } snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum)); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif vid = 1; } /* compute min output value */ - pts = (double)ost->last_mux_dts * av_q2d(ost->st->time_base); + pts = (double)ost->last_mux_dts * av_q2d(ost->mux_timebase); if ((pts < ti1) && (pts > 0)) ti1 = pts; } @@ -987,7 +1039,7 @@ static void flush_encoders(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; AVCodecContext *enc = ost->enc_ctx; - AVFormatContext *os = output_files[ost->file_index]->ctx; + OutputFile *of = output_files[ost->file_index]; int stop_encoding = 0; if (!ost->encoding_needed) @@ -995,47 +1047,45 @@ static void flush_encoders(void) if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) continue; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) + + if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; + avcodec_send_frame(enc, NULL); + for (;;) { - int (*encode)(AVCodecContext*, AVPacket*, const AVFrame*, int*) = NULL; - const char *desc; + const char *desc = NULL; switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: - encode = avcodec_encode_audio2; desc = "Audio"; break; case AVMEDIA_TYPE_VIDEO: - encode = avcodec_encode_video2; desc = "Video"; break; default: - stop_encoding = 1; + av_assert0(0); } - if (encode) { + if (1) { AVPacket pkt; - int got_packet; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; - ret = encode(enc, &pkt, NULL, &got_packet); - if (ret < 0) { + ret = avcodec_receive_packet(enc, &pkt); + if (ret < 0 && ret != AVERROR_EOF) { av_log(NULL, AV_LOG_FATAL, "%s encoding failed\n", desc); exit_program(1); } if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } - if (!got_packet) { + if (ret == AVERROR_EOF) { stop_encoding = 1; break; } - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); - write_frame(os, &pkt, ost); + output_packet(of, &pkt, ost); } if (stop_encoding) @@ -1066,7 +1116,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p OutputFile *of = output_files[ost->file_index]; InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; - int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); + int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); AVPacket opkt; av_init_packet(&opkt); @@ -1096,17 +1146,17 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p ost->sync_opts++; if (pkt->pts != AV_NOPTS_VALUE) - opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; + opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; else opkt.pts = AV_NOPTS_VALUE; if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->last_dts, AV_TIME_BASE_Q, ost->st->time_base); + opkt.dts = av_rescale_q(ist->last_dts, AV_TIME_BASE_Q, ost->mux_timebase); else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); opkt.dts -= ost_tb_start_time; - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); + opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); opkt.flags = pkt->flags; // FIXME remove the following 2 lines they shall be replaced by the bitstream filters @@ -1115,7 +1165,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p && ost->enc_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO && ost->enc_ctx->codec_id != AV_CODEC_ID_VC1 ) { - if (av_parser_change(ost->parser, ost->st->codec, + if (av_parser_change(ost->parser, ost->parser_avctx, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) { @@ -1128,7 +1178,134 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.size = pkt->size; } - write_frame(of->ctx, &opkt, ost); + output_packet(of, &opkt, ost); +} + +static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +{ + FilterGraph *fg = ifilter->graph; + int need_reinit, ret, i; + + /* determine if the parameters for this input changed */ + need_reinit = ifilter->format != frame->format; + if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || + (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + need_reinit = 1; + + switch (ifilter->ist->st->codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + need_reinit |= ifilter->sample_rate != frame->sample_rate || + ifilter->channel_layout != frame->channel_layout; + break; + case AVMEDIA_TYPE_VIDEO: + need_reinit |= ifilter->width != frame->width || + ifilter->height != frame->height; + break; + } + + if (need_reinit) { + ret = ifilter_parameters_from_frame(ifilter, frame); + if (ret < 0) + return ret; + } + + /* (re)init the graph if possible, otherwise buffer the frame and return */ + if (need_reinit || !fg->graph) { + for (i = 0; i < fg->nb_inputs; i++) { + if (fg->inputs[i]->format < 0) { + AVFrame *tmp = av_frame_clone(frame); + if (!tmp) + return AVERROR(ENOMEM); + av_frame_unref(frame); + + if (!av_fifo_space(ifilter->frame_queue)) { + ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); + if (ret < 0) + return ret; + } + av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); + return 0; + } + } + + ret = poll_filters(); + if (ret < 0 && ret != AVERROR_EOF) { + char errbuf[128]; + av_strerror(ret, errbuf, sizeof(errbuf)); + + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf); + return ret; + } + + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } + } + + ret = av_buffersrc_add_frame(ifilter->filter, frame); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error while filtering\n"); + return ret; + } + + return 0; +} + +static int ifilter_send_eof(InputFilter *ifilter) +{ + int i, j, ret; + + ifilter->eof = 1; + + if (ifilter->filter) { + ret = av_buffersrc_add_frame(ifilter->filter, NULL); + if (ret < 0) + return ret; + } else { + // the filtergraph was never configured + FilterGraph *fg = ifilter->graph; + for (i = 0; i < fg->nb_inputs; i++) + if (!fg->inputs[i]->eof) + break; + if (i == fg->nb_inputs) { + // All the input streams have finished without the filtergraph + // ever being configured. + // Mark the output streams as finished. + for (j = 0; j < fg->nb_outputs; j++) + finish_output_stream(fg->outputs[j]->ost); + } + } + + return 0; +} + +// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. +// There is the following difference: if you got a frame, you must call +// it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0 +// (pkt==NULL means get more output, pkt.size==0 is a flush/drain packet) +static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) +{ + int ret; + + *got_frame = 0; + + if (pkt) { + ret = avcodec_send_packet(avctx, pkt); + // In particular, we don't expect AVERROR(EAGAIN), because we read all + // decoded frames with avcodec_receive_frame() until done. + if (ret < 0) + return ret == AVERROR_EOF ? 0 : ret; + } + + ret = avcodec_receive_frame(avctx, frame); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + if (ret >= 0) + *got_frame = 1; + + return 0; } int guess_input_channel_layout(InputStream *ist) @@ -1143,7 +1320,7 @@ int guess_input_channel_layout(InputStream *ist) return 0; av_get_channel_layout_string(layout_name, sizeof(layout_name), dec->channels, dec->channel_layout); - av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " + av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name); } return 1; @@ -1153,7 +1330,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) { AVFrame *decoded_frame, *f; AVCodecContext *avctx = ist->dec_ctx; - int i, ret, err = 0, resample_changed; + int i, ret, err = 0; if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); @@ -1161,14 +1338,9 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; - ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt); - if (!*got_output || ret < 0) { - if (!pkt->size) { - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame(ist->filters[i]->filter, NULL); - } + ret = decode(avctx, decoded_frame, got_output, pkt); + if (!*got_output || ret < 0) return ret; - } ist->samples_decoded += decoded_frame->nb_samples; ist->frames_decoded++; @@ -1176,56 +1348,16 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) /* if the decoder provides a pts, use it instead of the last packet pts. the decoder could be delaying output by a packet or more. */ if (decoded_frame->pts != AV_NOPTS_VALUE) - ist->next_dts = decoded_frame->pts; - else if (pkt->pts != AV_NOPTS_VALUE) + ist->next_dts = av_rescale_q(decoded_frame->pts, ist->st->time_base, AV_TIME_BASE_Q); + else if (pkt && pkt->pts != AV_NOPTS_VALUE) { decoded_frame->pts = pkt->pts; - pkt->pts = AV_NOPTS_VALUE; - - resample_changed = ist->resample_sample_fmt != decoded_frame->format || - ist->resample_channels != avctx->channels || - ist->resample_channel_layout != decoded_frame->channel_layout || - ist->resample_sample_rate != decoded_frame->sample_rate; - if (resample_changed) { - char layout1[64], layout2[64]; - - if (!guess_input_channel_layout(ist)) { - av_log(NULL, AV_LOG_FATAL, "Unable to find default channel " - "layout for Input Stream #%d.%d\n", ist->file_index, - ist->st->index); - exit_program(1); - } - decoded_frame->channel_layout = avctx->channel_layout; - - av_get_channel_layout_string(layout1, sizeof(layout1), ist->resample_channels, - ist->resample_channel_layout); - av_get_channel_layout_string(layout2, sizeof(layout2), avctx->channels, - decoded_frame->channel_layout); - - av_log(NULL, AV_LOG_INFO, - "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:%s to rate:%d fmt:%s ch:%d chl:%s\n", - ist->file_index, ist->st->index, - ist->resample_sample_rate, av_get_sample_fmt_name(ist->resample_sample_fmt), - ist->resample_channels, layout1, - decoded_frame->sample_rate, av_get_sample_fmt_name(decoded_frame->format), - avctx->channels, layout2); - - ist->resample_sample_fmt = decoded_frame->format; - ist->resample_sample_rate = decoded_frame->sample_rate; - ist->resample_channel_layout = decoded_frame->channel_layout; - ist->resample_channels = avctx->channels; - - for (i = 0; i < nb_filtergraphs; i++) - if (ist_in_filtergraph(filtergraphs[i], ist) && - configure_filtergraph(filtergraphs[i]) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit_program(1); - } } if (decoded_frame->pts != AV_NOPTS_VALUE) decoded_frame->pts = av_rescale_q(decoded_frame->pts, ist->st->time_base, (AVRational){1, avctx->sample_rate}); + ist->nb_samples = decoded_frame->nb_samples; for (i = 0; i < ist->nb_filters; i++) { if (i < ist->nb_filters - 1) { f = ist->filter_frame; @@ -1235,7 +1367,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) } else f = decoded_frame; - err = av_buffersrc_add_frame(ist->filters[i]->filter, f); + err = ifilter_send_frame(ist->filters[i], f); if (err < 0) break; } @@ -1248,7 +1380,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) { AVFrame *decoded_frame, *f; - int i, ret = 0, err = 0, resample_changed; + int i, ret = 0, err = 0; if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); @@ -1256,15 +1388,9 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; - ret = avcodec_decode_video2(ist->dec_ctx, - decoded_frame, got_output, pkt); - if (!*got_output || ret < 0) { - if (!pkt->size) { - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame(ist->filters[i]->filter, NULL); - } + ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt); + if (!*got_output || ret < 0) return ret; - } ist->frames_decoded++; @@ -1275,39 +1401,14 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } ist->hwaccel_retrieved_pix_fmt = decoded_frame->format; - decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, + decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pts, decoded_frame->pkt_dts); - pkt->size = 0; + if (ist->framerate.num) + decoded_frame->pts = ist->cfr_next_pts++; if (ist->st->sample_aspect_ratio.num) decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; - resample_changed = ist->resample_width != decoded_frame->width || - ist->resample_height != decoded_frame->height || - ist->resample_pix_fmt != decoded_frame->format; - if (resample_changed) { - av_log(NULL, AV_LOG_INFO, - "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", - ist->file_index, ist->st->index, - ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt), - decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format)); - - ret = poll_filters(); - if (ret < 0 && (ret != AVERROR_EOF && ret != AVERROR(EAGAIN))) - av_log(NULL, AV_LOG_ERROR, "Error while filtering.\n"); - - ist->resample_width = decoded_frame->width; - ist->resample_height = decoded_frame->height; - ist->resample_pix_fmt = decoded_frame->format; - - for (i = 0; i < nb_filtergraphs; i++) - if (ist_in_filtergraph(filtergraphs[i], ist) && - configure_filtergraph(filtergraphs[i]) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit_program(1); - } - } - for (i = 0; i < ist->nb_filters; i++) { if (i < ist->nb_filters - 1) { f = ist->filter_frame; @@ -1317,7 +1418,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } else f = decoded_frame; - err = av_buffersrc_add_frame(ist->filters[i]->filter, f); + err = ifilter_send_frame(ist->filters[i], f); if (err < 0) break; } @@ -1346,18 +1447,29 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (!check_output_constraints(ist, ost) || !ost->encoding_needed) continue; - do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pkt->pts); + do_subtitle_out(output_files[ost->file_index], ost, ist, &subtitle, pkt->pts); } avsubtitle_free(&subtitle); return ret; } +static int send_filter_eof(InputStream *ist) +{ + int i, ret; + for (i = 0; i < ist->nb_filters; i++) { + ret = ifilter_send_eof(ist->filters[i]); + if (ret < 0) + return ret; + } + return 0; +} + /* pkt = NULL means EOF (needed to flush decoder buffers) */ -static int process_input_packet(InputStream *ist, const AVPacket *pkt) +static void process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { int i; - int got_output; + int repeating = 0; AVPacket avpkt; if (ist->next_dts == AV_NOPTS_VALUE) @@ -1368,61 +1480,70 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt) av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; - goto handle_eof; } else { avpkt = *pkt; } - if (pkt->dts != AV_NOPTS_VALUE) + if (pkt && pkt->dts != AV_NOPTS_VALUE) ist->next_dts = ist->last_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); // while we have more to decode or while the decoder did output something on EOF - while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) { + while (ist->decoding_needed && (!pkt || avpkt.size > 0)) { int ret = 0; - handle_eof: - - ist->last_dts = ist->next_dts; + int got_output = 0; - if (avpkt.size && avpkt.size != pkt->size && - !(ist->dec->capabilities & CODEC_CAP_SUBFRAMES)) { - av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING, - "Multiple frames in a packet from stream %d\n", pkt->stream_index); - ist->showed_multi_packet_warning = 1; - } + if (!repeating) + ist->last_dts = ist->next_dts; switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, &avpkt, &got_output); + ret = decode_audio (ist, repeating ? NULL : &avpkt, &got_output); break; case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, &avpkt, &got_output); - if (avpkt.duration) - ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q); + ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output); + if (repeating && !got_output) + ; + else if (pkt && pkt->duration) + ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); else if (ist->st->avg_frame_rate.num) ist->next_dts += av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), AV_TIME_BASE_Q); - else if (ist->dec_ctx->time_base.num != 0) { + else if (ist->dec_ctx->framerate.num != 0) { int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame; - ist->next_dts += av_rescale_q(ticks, ist->dec_ctx->time_base, AV_TIME_BASE_Q); + ist->next_dts += av_rescale_q(ticks, ist->dec_ctx->framerate, AV_TIME_BASE_Q); } break; case AVMEDIA_TYPE_SUBTITLE: + if (repeating) + break; ret = transcode_subtitles(ist, &avpkt, &got_output); break; default: - return -1; + return; } - if (ret < 0) - return ret; - // touch data and size only if not EOF - if (pkt) { - avpkt.data += ret; - avpkt.size -= ret; + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n", + ist->file_index, ist->st->index); + if (exit_on_error) + exit_program(1); + break; } - if (!got_output) { - continue; + + if (!got_output) + break; + + repeating = 1; + } + + /* after flushing, send an EOF on all the filter inputs attached to the stream */ + /* except when looping we need to flush but not to send an EOF */ + if (!pkt && ist->decoding_needed && !no_eof) { + int ret = send_filter_eof(ist); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); + exit_program(1); } } @@ -1435,11 +1556,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt) ist->dec_ctx->sample_rate; break; case AVMEDIA_TYPE_VIDEO: - if (ist->dec_ctx->time_base.num != 0) { + if (ist->dec_ctx->framerate.num != 0) { int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame; ist->next_dts += ((int64_t)AV_TIME_BASE * - ist->dec_ctx->time_base.num * ticks) / - ist->dec_ctx->time_base.den; + ist->dec_ctx->framerate.den * ticks) / + ist->dec_ctx->framerate.num; } break; } @@ -1453,15 +1574,21 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt) do_streamcopy(ist, ost, pkt); } - return 0; + return; } static void print_sdp(void) { char sdp[16384]; int i; - AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); + AVFormatContext **avc; + + for (i = 0; i < nb_output_files; i++) { + if (!output_files[i]->header_written) + return; + } + avc = av_malloc(sizeof(*avc) * nb_output_files); if (!avc) exit_program(1); for (i = 0; i < nb_output_files; i++) @@ -1508,10 +1635,17 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat "%s hwaccel requested for input stream #%d:%d, " "but cannot be initialized.\n", hwaccel->name, ist->file_index, ist->st->index); - exit_program(1); + return AV_PIX_FMT_NONE; } continue; } + + if (ist->hw_frames_ctx) { + s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx); + if (!s->hw_frames_ctx) + return AV_PIX_FMT_NONE; + } + ist->active_hwaccel_id = hwaccel->id; ist->hwaccel_pix_fmt = *p; break; @@ -1532,8 +1666,9 @@ static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags) static int init_input_stream(int ist_index, char *error, int error_len) { - int i, ret; + int ret; InputStream *ist = input_streams[ist_index]; + if (ist->decoding_needed) { AVCodec *codec = ist->dec; if (!codec) { @@ -1542,16 +1677,6 @@ static int init_input_stream(int ist_index, char *error, int error_len) return AVERROR(EINVAL); } - /* update requested sample format for the decoder based on the - corresponding encoder sample format */ - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - if (ost->source_index == ist_index) { - update_sample_fmt(ist->dec_ctx, codec, ost->enc_ctx); - break; - } - } - ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; ist->dec_ctx->get_buffer2 = get_buffer; @@ -1601,42 +1726,168 @@ static InputStream *get_input_stream(OutputStream *ost) return NULL; } -static void parse_forced_key_frames(char *kf, OutputStream *ost, - AVCodecContext *avctx) +/* open the muxer when all the streams are initialized */ +static int check_init_output_file(OutputFile *of, int file_index) { - char *p; - int n = 1, i; - int64_t t; + int ret, i; - for (p = kf; *p; p++) - if (*p == ',') - n++; - ost->forced_kf_count = n; - ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n); - if (!ost->forced_kf_pts) { - av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); - exit_program(1); + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + if (!ost->initialized) + return 0; } - p = kf; - for (i = 0; i < n; i++) { - char *next = strchr(p, ','); + of->ctx->interrupt_callback = int_cb; - if (next) - *next++ = 0; + ret = avformat_write_header(of->ctx, &of->opts); + if (ret < 0) { + char errbuf[128]; - t = parse_time_or_die("force_key_frames", p, 1); - ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); + av_strerror(ret, errbuf, sizeof(errbuf)); - p = next; + av_log(NULL, AV_LOG_ERROR, + "Could not write header for output file #%d " + "(incorrect codec parameters ?): %s", + file_index, errbuf); + return ret; + } + assert_avoptions(of->opts); + of->header_written = 1; + + av_dump_format(of->ctx, file_index, of->ctx->filename, 1); + + if (want_sdp) + print_sdp(); + + /* flush the muxing queues */ + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + + while (av_fifo_size(ost->muxing_queue)) { + AVPacket pkt; + av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + write_packet(of, &pkt, ost); + } } + + return 0; } -static void set_encoder_id(OutputFile *of, OutputStream *ost) +static int init_output_bsfs(OutputStream *ost) { - AVDictionaryEntry *e; + AVBSFContext *ctx; + int i, ret; - uint8_t *encoder_string; + if (!ost->nb_bitstream_filters) + return 0; + + ost->bsf_ctx = av_mallocz_array(ost->nb_bitstream_filters, sizeof(*ost->bsf_ctx)); + if (!ost->bsf_ctx) + return AVERROR(ENOMEM); + + for (i = 0; i < ost->nb_bitstream_filters; i++) { + ret = av_bsf_alloc(ost->bitstream_filters[i], &ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n"); + return ret; + } + ost->bsf_ctx[i] = ctx; + + ret = avcodec_parameters_copy(ctx->par_in, + i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar); + if (ret < 0) + return ret; + + ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base; + + ret = av_bsf_init(ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", + ost->bitstream_filters[i]->name); + return ret; + } + } + + ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1]; + ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); + if (ret < 0) + return ret; + + ost->st->time_base = ctx->time_base_out; + + return 0; +} + +static int init_output_stream_streamcopy(OutputStream *ost) +{ + OutputFile *of = output_files[ost->file_index]; + InputStream *ist = get_input_stream(ost); + AVCodecParameters *par_dst = ost->st->codecpar; + AVCodecParameters *par_src = ist->st->codecpar; + AVRational sar; + uint32_t codec_tag = par_dst->codec_tag; + int i, ret; + + if (!codec_tag) { + if (!of->ctx->oformat->codec_tag || + av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_src->codec_id || + av_codec_get_tag(of->ctx->oformat->codec_tag, par_src->codec_id) <= 0) + codec_tag = par_src->codec_tag; + } + + ret = avcodec_parameters_copy(par_dst, par_src); + if (ret < 0) + return ret; + + par_dst->codec_tag = codec_tag; + + ost->st->disposition = ist->st->disposition; + + ost->st->time_base = ist->st->time_base; + + if (ist->st->nb_side_data) { + ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data, + sizeof(*ist->st->side_data)); + if (!ost->st->side_data) + return AVERROR(ENOMEM); + + for (i = 0; i < ist->st->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->st->side_data[i]; + AVPacketSideData *sd_dst = &ost->st->side_data[i]; + + sd_dst->data = av_malloc(sd_src->size); + if (!sd_dst->data) + return AVERROR(ENOMEM); + memcpy(sd_dst->data, sd_src->data, sd_src->size); + sd_dst->size = sd_src->size; + sd_dst->type = sd_src->type; + ost->st->nb_side_data++; + } + } + + ost->parser = av_parser_init(par_dst->codec_id); + ost->parser_avctx = avcodec_alloc_context3(NULL); + if (!ost->parser_avctx) + return AVERROR(ENOMEM); + + if (par_dst->codec_type == AVMEDIA_TYPE_VIDEO) { + if (ost->frame_aspect_ratio) + sar = av_d2q(ost->frame_aspect_ratio * par_dst->height / par_dst->width, 255); + else if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = par_src->sample_aspect_ratio; + ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar; + } + + return 0; +} + +static void set_encoder_id(OutputFile *of, OutputStream *ost) +{ + AVDictionaryEntry *e; + + uint8_t *encoder_string; int encoder_string_len; int format_flags = 0; @@ -1660,321 +1911,217 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost) AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); } -static int transcode_init(void) +static void parse_forced_key_frames(char *kf, OutputStream *ost, + AVCodecContext *avctx) { - int ret = 0, i, j, k; - AVFormatContext *oc; - OutputStream *ost; - InputStream *ist; - char error[1024]; - int want_sdp = 1; + char *p; + int n = 1, i; + int64_t t; - /* init framerate emulation */ - for (i = 0; i < nb_input_files; i++) { - InputFile *ifile = input_files[i]; - if (ifile->rate_emu) - for (j = 0; j < ifile->nb_streams; j++) - input_streams[j + ifile->ist_index]->start = av_gettime(); + for (p = kf; *p; p++) + if (*p == ',') + n++; + ost->forced_kf_count = n; + ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n); + if (!ost->forced_kf_pts) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); + exit_program(1); } - /* output stream init */ - for (i = 0; i < nb_output_files; i++) { - oc = output_files[i]->ctx; - if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(oc, i, oc->filename, 1); - av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i); - return AVERROR(EINVAL); - } + p = kf; + for (i = 0; i < n; i++) { + char *next = strchr(p, ','); + + if (next) + *next++ = 0; + + t = parse_time_or_die("force_key_frames", p, 1); + ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); + + p = next; } +} - /* init complex filtergraphs */ - for (i = 0; i < nb_filtergraphs; i++) - if ((ret = avfilter_graph_config(filtergraphs[i]->graph, NULL)) < 0) - return ret; +static int init_output_stream_encode(OutputStream *ost) +{ + InputStream *ist = get_input_stream(ost); + AVCodecContext *enc_ctx = ost->enc_ctx; + AVCodecContext *dec_ctx = NULL; - /* for each output stream, we compute the right encoding parameters */ - for (i = 0; i < nb_output_streams; i++) { - AVCodecContext *enc_ctx; - AVCodecContext *dec_ctx = NULL; - ost = output_streams[i]; - oc = output_files[ost->file_index]->ctx; - ist = get_input_stream(ost); + set_encoder_id(output_files[ost->file_index], ost); - if (ost->attachment_filename) - continue; + if (ist) { + ost->st->disposition = ist->st->disposition; - enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx; + dec_ctx = ist->dec_ctx; - if (ist) { - dec_ctx = ist->dec_ctx; + enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; + enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; + } - ost->st->disposition = ist->st->disposition; - enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; - enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; + switch (enc_ctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format; + enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate; + enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout; + enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); + enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate }; + break; + case AVMEDIA_TYPE_VIDEO: + enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base; + + enc_ctx->width = ost->filter->filter->inputs[0]->w; + enc_ctx->height = ost->filter->filter->inputs[0]->h; + enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = + ost->frame_aspect_ratio ? // overridden by the -aspect cli option + av_d2q(ost->frame_aspect_ratio * enc_ctx->height/enc_ctx->width, 255) : + ost->filter->filter->inputs[0]->sample_aspect_ratio; + enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format; + + ost->st->avg_frame_rate = ost->frame_rate; + + if (dec_ctx && + (enc_ctx->width != dec_ctx->width || + enc_ctx->height != dec_ctx->height || + enc_ctx->pix_fmt != dec_ctx->pix_fmt)) { + enc_ctx->bits_per_raw_sample = 0; } - if (ost->stream_copy) { - AVRational sar; - uint64_t extra_size; + if (ost->forced_keyframes) + parse_forced_key_frames(ost->forced_keyframes, ost, + ost->enc_ctx); + break; + case AVMEDIA_TYPE_SUBTITLE: + enc_ctx->time_base = (AVRational){1, 1000}; + break; + default: + abort(); + break; + } - av_assert0(ist && !ost->filter); + return 0; +} - extra_size = (uint64_t)dec_ctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; +static int init_output_stream(OutputStream *ost, char *error, int error_len) +{ + int ret = 0; - if (extra_size > INT_MAX) { - return AVERROR(EINVAL); - } + if (ost->encoding_needed) { + AVCodec *codec = ost->enc; + AVCodecContext *dec = NULL; + InputStream *ist; - /* if stream_copy is selected, no need to decode or encode */ - enc_ctx->codec_id = dec_ctx->codec_id; - enc_ctx->codec_type = dec_ctx->codec_type; + ret = init_output_stream_encode(ost); + if (ret < 0) + return ret; - if (!enc_ctx->codec_tag) { - if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id || - av_codec_get_tag(oc->oformat->codec_tag, dec_ctx->codec_id) <= 0) - enc_ctx->codec_tag = dec_ctx->codec_tag; - } + if ((ist = get_input_stream(ost))) + dec = ist->dec_ctx; + if (dec && dec->subtitle_header) { + ost->enc_ctx->subtitle_header = av_malloc(dec->subtitle_header_size); + if (!ost->enc_ctx->subtitle_header) + return AVERROR(ENOMEM); + memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); + ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; + } + if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) + av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - enc_ctx->bit_rate = dec_ctx->bit_rate; - enc_ctx->rc_max_rate = dec_ctx->rc_max_rate; - enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size; - enc_ctx->field_order = dec_ctx->field_order; - enc_ctx->extradata = av_mallocz(extra_size); - if (!enc_ctx->extradata) { + if (ost->filter && ost->filter->filter->inputs[0]->hw_frames_ctx) { + ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ost->filter->filter->inputs[0]->hw_frames_ctx); + if (!ost->enc_ctx->hw_frames_ctx) return AVERROR(ENOMEM); - } - memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size); - enc_ctx->extradata_size = dec_ctx->extradata_size; - if (!copy_tb) { - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, - enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); - } else - enc_ctx->time_base = ist->st->time_base; + } - ost->parser = av_parser_init(enc_ctx->codec_id); + if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 1); + snprintf(error, error_len, + "Error while opening encoder for output stream #%d:%d - " + "maybe incorrect parameters such as bit_rate, rate, width or height", + ost->file_index, ost->index); + return ret; + } + assert_avoptions(ost->encoder_opts); + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) + av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." + "It takes bits/s as argument, not kbits/s\n"); - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if (audio_volume != 256) { - av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n"); - exit_program(1); - } - enc_ctx->channel_layout = dec_ctx->channel_layout; - enc_ctx->sample_rate = dec_ctx->sample_rate; - enc_ctx->channels = dec_ctx->channels; - enc_ctx->frame_size = dec_ctx->frame_size; - enc_ctx->audio_service_type = dec_ctx->audio_service_type; - enc_ctx->block_align = dec_ctx->block_align; - break; - case AVMEDIA_TYPE_VIDEO: - enc_ctx->pix_fmt = dec_ctx->pix_fmt; - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - enc_ctx->has_b_frames = dec_ctx->has_b_frames; - if (ost->frame_aspect_ratio) - sar = av_d2q(ost->frame_aspect_ratio * enc_ctx->height / enc_ctx->width, 255); - else if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = dec_ctx->sample_aspect_ratio; - ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar; - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - break; - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_ATTACHMENT: - break; - default: - abort(); - } - } else { - if (!ost->enc) { - /* should only happen when a default codec is not present. */ - snprintf(error, sizeof(error), "Automatic encoder selection " - "failed for output stream #%d:%d. Default encoder for " - "format %s is probably disabled. Please choose an " - "encoder manually.\n", ost->file_index, ost->index, - oc->oformat->name); - ret = AVERROR(EINVAL); - goto dump_format; - } + ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, + "Error initializing the output stream codec context.\n"); + exit_program(1); + } - if (ist) - ist->decoding_needed = 1; - ost->encoding_needed = 1; - - set_encoder_id(output_files[ost->file_index], ost); - - /* - * We want CFR output if and only if one of those is true: - * 1) user specified output framerate with -r - * 2) user specified -vsync cfr - * 3) output format is CFR and the user didn't force vsync to - * something else than CFR - * - * in such a case, set ost->frame_rate - */ - if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && - !ost->frame_rate.num && ist && - (video_sync_method == VSYNC_CFR || - (video_sync_method == VSYNC_AUTO && - !(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS))))) { - if (ist->framerate.num) - ost->frame_rate = ist->framerate; - else if (ist->st->avg_frame_rate.num) - ost->frame_rate = ist->st->avg_frame_rate; - else { - av_log(NULL, AV_LOG_WARNING, "Constant framerate requested " - "for the output stream #%d:%d, but no information " - "about the input framerate is available. Falling " - "back to a default value of 25fps. Use the -r option " - "if you want a different framerate.\n", - ost->file_index, ost->index); - ost->frame_rate = (AVRational){ 25, 1 }; - } + if (ost->enc_ctx->nb_coded_side_data) { + int i; - if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) { - int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); - ost->frame_rate = ost->enc->supported_framerates[idx]; - } - } + ost->st->side_data = av_realloc_array(NULL, ost->enc_ctx->nb_coded_side_data, + sizeof(*ost->st->side_data)); + if (!ost->st->side_data) + return AVERROR(ENOMEM); - if (!ost->filter && - (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO || - enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) { - FilterGraph *fg; - fg = init_simple_filtergraph(ist, ost); - if (configure_filtergraph(fg)) { - av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); - exit_program(1); - } + for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { + const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; + AVPacketSideData *sd_dst = &ost->st->side_data[i]; + + sd_dst->data = av_malloc(sd_src->size); + if (!sd_dst->data) + return AVERROR(ENOMEM); + memcpy(sd_dst->data, sd_src->data, sd_src->size); + sd_dst->size = sd_src->size; + sd_dst->type = sd_src->type; + ost->st->nb_side_data++; } + } - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format; - enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate; - enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout; - enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); - enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate }; - break; - case AVMEDIA_TYPE_VIDEO: - enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base; - - enc_ctx->width = ost->filter->filter->inputs[0]->w; - enc_ctx->height = ost->filter->filter->inputs[0]->h; - enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = - ost->frame_aspect_ratio ? // overridden by the -aspect cli option - av_d2q(ost->frame_aspect_ratio * enc_ctx->height/enc_ctx->width, 255) : - ost->filter->filter->inputs[0]->sample_aspect_ratio; - enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format; - - ost->st->avg_frame_rate = ost->frame_rate; - - if (dec_ctx && - (enc_ctx->width != dec_ctx->width || - enc_ctx->height != dec_ctx->height || - enc_ctx->pix_fmt != dec_ctx->pix_fmt)) { - enc_ctx->bits_per_raw_sample = 0; - } + ost->st->time_base = ost->enc_ctx->time_base; + } else if (ost->stream_copy) { + ret = init_output_stream_streamcopy(ost); + if (ret < 0) + return ret; - if (ost->forced_keyframes) - parse_forced_key_frames(ost->forced_keyframes, ost, - ost->enc_ctx); - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->time_base = (AVRational){1, 1000}; - break; - default: - abort(); - break; - } - /* two pass mode */ - if ((enc_ctx->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) { - char logfilename[1024]; - FILE *f; - - snprintf(logfilename, sizeof(logfilename), "%s-%d.log", - ost->logfile_prefix ? ost->logfile_prefix : - DEFAULT_PASS_LOGFILENAME_PREFIX, - i); - if (!strcmp(ost->enc->name, "libx264")) { - av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); - } else { - if (enc_ctx->flags & CODEC_FLAG_PASS1) { - f = fopen(logfilename, "wb"); - if (!f) { - av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", - logfilename, strerror(errno)); - exit_program(1); - } - ost->logfile = f; - } else { - char *logbuffer; - size_t logbuffer_size; - if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", - logfilename); - exit_program(1); - } - enc_ctx->stats_in = logbuffer; - } - } - } - } + /* + * FIXME: will the codec context used by the parser during streamcopy + * This should go away with the new parser API. + */ + ret = avcodec_parameters_to_context(ost->parser_avctx, ost->st->codecpar); + if (ret < 0) + return ret; } - /* open each encoder */ - for (i = 0; i < nb_output_streams; i++) { - ost = output_streams[i]; - if (ost->encoding_needed) { - AVCodec *codec = ost->enc; - AVCodecContext *dec = NULL; - - if ((ist = get_input_stream(ost))) - dec = ist->dec_ctx; - if (dec && dec->subtitle_header) { - ost->enc_ctx->subtitle_header = av_malloc(dec->subtitle_header_size); - if (!ost->enc_ctx->subtitle_header) { - ret = AVERROR(ENOMEM); - goto dump_format; - } - memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); - ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; - } - if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) - av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - av_dict_set(&ost->encoder_opts, "side_data_only_packets", "1", 0); - - if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 1); - snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", - ost->file_index, ost->index); - goto dump_format; - } - assert_avoptions(ost->encoder_opts); - if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) - av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." - "It takes bits/s as argument, not kbits/s\n"); + /* initialize bitstream filters for the output stream + * needs to be done here, because the codec id for streamcopy is not + * known until now */ + ret = init_output_bsfs(ost); + if (ret < 0) + return ret; - ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "Error initializing the output stream codec context.\n"); - exit_program(1); - } + ost->mux_timebase = ost->st->time_base; - ost->st->time_base = ost->enc_ctx->time_base; - } else { - av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); - ost->st->time_base = ost->st->codec->time_base; - } + ost->initialized = 1; + + ret = check_init_output_file(output_files[ost->file_index], ost->file_index); + if (ret < 0) + return ret; + + return ret; +} + +static int transcode_init(void) +{ + int ret = 0, i, j, k; + OutputStream *ost; + InputStream *ist; + char error[1024]; + + /* init framerate emulation */ + for (i = 0; i < nb_input_files; i++) { + InputFile *ifile = input_files[i]; + if (ifile->rate_emu) + for (j = 0; j < ifile->nb_streams; j++) + input_streams[j + ifile->ist_index]->start = av_gettime_relative(); } /* init input streams */ @@ -1982,6 +2129,18 @@ static int transcode_init(void) if ((ret = init_input_stream(i, error, sizeof(error))) < 0) goto dump_format; + /* open each encoder */ + for (i = 0; i < nb_output_streams; i++) { + // skip streams fed from filtergraphs until we have a frame for them + if (output_streams[i]->filter) + continue; + + ret = init_output_stream(output_streams[i], error, sizeof(error)); + if (ret < 0) + goto dump_format; + } + + /* discard unused programs */ for (i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; @@ -1998,40 +2157,14 @@ static int transcode_init(void) } } - /* open files and write file headers */ - for (i = 0; i < nb_output_files; i++) { - oc = output_files[i]->ctx; - oc->interrupt_callback = int_cb; - if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) { - char errbuf[128]; - av_strerror(ret, errbuf, sizeof(errbuf)); - snprintf(error, sizeof(error), - "Could not write header for output file #%d " - "(incorrect codec parameters ?): %s", - i, errbuf); - ret = AVERROR(EINVAL); - goto dump_format; - } - assert_avoptions(output_files[i]->opts); - if (strcmp(oc->oformat->name, "rtp")) { - want_sdp = 0; - } - } - dump_format: - /* dump the file output parameters - cannot be done before in case - of stream copy */ - for (i = 0; i < nb_output_files; i++) { - av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1); - } - /* dump the stream mapping */ av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; for (j = 0; j < ist->nb_filters; j++) { - if (ist->filters[j]->graph->graph_desc) { + if (!filtergraph_is_simple(ist->filters[j]->graph)) { av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s", ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?", ist->filters[j]->name); @@ -2052,7 +2185,7 @@ static int transcode_init(void) continue; } - if (ost->filter && ost->filter->graph->graph_desc) { + if (ost->filter && !filtergraph_is_simple(ost->filter->graph)) { /* output from a complex graph */ av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name); if (nb_filtergraphs > 1) @@ -2081,17 +2214,22 @@ static int transcode_init(void) const char *in_codec_name = "?"; const char *encoder_name = "?"; const char *out_codec_name = "?"; + const AVCodecDescriptor *desc; if (in_codec) { decoder_name = in_codec->name; - in_codec_name = avcodec_descriptor_get(in_codec->id)->name; + desc = avcodec_descriptor_get(in_codec->id); + if (desc) + in_codec_name = desc->name; if (!strcmp(decoder_name, in_codec_name)) decoder_name = "native"; } if (out_codec) { encoder_name = out_codec->name; - out_codec_name = avcodec_descriptor_get(out_codec->id)->name; + desc = avcodec_descriptor_get(out_codec->id); + if (desc) + out_codec_name = desc->name; if (!strcmp(encoder_name, out_codec_name)) encoder_name = "native"; } @@ -2108,10 +2246,6 @@ static int transcode_init(void) return ret; } - if (want_sdp) { - print_sdp(); - } - return 0; } @@ -2185,7 +2319,6 @@ static void *input_thread(void *arg) while (!av_fifo_space(f->fifo)) pthread_cond_wait(&f->fifo_cond, &f->fifo_lock); - av_dup_packet(&pkt); av_fifo_generic_write(f->fifo, &pkt, sizeof(pkt), NULL); pthread_mutex_unlock(&f->fifo_lock); @@ -2214,7 +2347,7 @@ static void free_input_threads(void) pthread_mutex_lock(&f->fifo_lock); while (av_fifo_size(f->fifo)) { av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); - av_free_packet(&pkt); + av_packet_unref(&pkt); } pthread_cond_signal(&f->fifo_cond); pthread_mutex_unlock(&f->fifo_lock); @@ -2224,7 +2357,7 @@ static void free_input_threads(void) while (av_fifo_size(f->fifo)) { av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); - av_free_packet(&pkt); + av_packet_unref(&pkt); } av_fifo_free(f->fifo); } @@ -2281,7 +2414,7 @@ static int get_input_packet(InputFile *f, AVPacket *pkt) for (i = 0; i < f->nb_streams; i++) { InputStream *ist = input_streams[f->ist_index + i]; int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE); - int64_t now = av_gettime() - ist->start; + int64_t now = av_gettime_relative() - ist->start; if (pts > now) return AVERROR(EAGAIN); } @@ -2310,6 +2443,87 @@ static void reset_eagain(void) input_files[i]->eagain = 0; } +// set duration to max(tmp, duration) in a proper time base and return duration's time_base +static AVRational duration_max(int64_t tmp, int64_t *duration, AVRational tmp_time_base, + AVRational time_base) +{ + int ret; + + if (!*duration) { + *duration = tmp; + return tmp_time_base; + } + + ret = av_compare_ts(*duration, time_base, tmp, tmp_time_base); + if (ret < 0) { + *duration = tmp; + return tmp_time_base; + } + + return time_base; +} + +static int seek_to_start(InputFile *ifile, AVFormatContext *is) +{ + InputStream *ist; + AVCodecContext *avctx; + int i, ret, has_audio = 0; + int64_t duration = 0; + + ret = av_seek_frame(is, -1, is->start_time, 0); + if (ret < 0) + return ret; + + for (i = 0; i < ifile->nb_streams; i++) { + ist = input_streams[ifile->ist_index + i]; + avctx = ist->dec_ctx; + + // flush decoders + if (ist->decoding_needed) { + process_input_packet(ist, NULL, 1); + avcodec_flush_buffers(avctx); + } + + /* duration is the length of the last frame in a stream + * when audio stream is present we don't care about + * last video frame length because it's not defined exactly */ + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) + has_audio = 1; + } + + for (i = 0; i < ifile->nb_streams; i++) { + ist = input_streams[ifile->ist_index + i]; + avctx = ist->dec_ctx; + + if (has_audio) { + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) { + AVRational sample_rate = {1, avctx->sample_rate}; + + duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base); + } else + continue; + } else { + if (ist->framerate.num) { + duration = av_rescale_q(1, ist->framerate, ist->st->time_base); + } else if (ist->st->avg_frame_rate.num) { + duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base); + } else duration = 1; + } + if (!ifile->duration) + ifile->time_base = ist->st->time_base; + /* the total duration of the stream, max_pts - min_pts is + * the duration of the stream without the last frame */ + duration += ist->max_pts - ist->min_pts; + ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base, + ifile->time_base); + } + + if (ifile->loop > 0) + ifile->loop--; + + return ret; +} + /* * Read one packet from an input file and send it for * - decoding -> lavfi (audio/video) @@ -2329,6 +2543,7 @@ static int process_input(void) InputStream *ist; AVPacket pkt; int ret, i, j; + int64_t duration; /* select the stream that we must read now */ ifile = select_input_file(); @@ -2350,6 +2565,11 @@ static int process_input(void) ifile->eagain = 1; return ret; } + if (ret < 0 && ifile->loop) { + if ((ret = seek_to_start(ifile, is)) < 0) + return ret; + ret = get_input_packet(ifile, &pkt); + } if (ret < 0) { if (ret != AVERROR_EOF) { print_error(is->filename, ret); @@ -2361,7 +2581,7 @@ static int process_input(void) for (i = 0; i < ifile->nb_streams; i++) { ist = input_streams[ifile->ist_index + i]; if (ist->decoding_needed) - process_input_packet(ist, NULL); + process_input_packet(ist, NULL, 0); /* mark all outputs that don't go through lavfi as finished */ for (j = 0; j < nb_output_streams; j++) { @@ -2403,6 +2623,8 @@ static int process_input(void) if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) continue; + if (ist->autorotate && src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) + continue; dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); if (!dst_data) @@ -2421,7 +2643,9 @@ static int process_input(void) if (pkt.dts != AV_NOPTS_VALUE) pkt.dts *= ist->ts_scale; - if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && + if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || + ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && + pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && (is->iformat->flags & AVFMT_TS_DISCONT)) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); int64_t delta = pkt_dts - ist->next_dts; @@ -2436,17 +2660,20 @@ static int process_input(void) pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } - - ret = process_input_packet(ist, &pkt); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n", - ist->file_index, ist->st->index); - if (exit_on_error) - exit_program(1); + duration = av_rescale_q(ifile->duration, ifile->time_base, ist->st->time_base); + if (pkt.pts != AV_NOPTS_VALUE) { + pkt.pts += duration; + ist->max_pts = FFMAX(pkt.pts, ist->max_pts); + ist->min_pts = FFMIN(pkt.pts, ist->min_pts); } + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts += duration; + + process_input_packet(ist, &pkt, 0); + discard_packet: - av_free_packet(&pkt); + av_packet_unref(&pkt); return 0; } @@ -2469,7 +2696,7 @@ static int transcode(void) av_log(NULL, AV_LOG_INFO, "Press ctrl-c to stop encoding\n"); term_init(); - timer_start = av_gettime(); + timer_start = av_gettime_relative(); #if HAVE_PTHREADS if ((ret = init_input_threads()) < 0) @@ -2491,11 +2718,11 @@ static int transcode(void) } ret = poll_filters(); - if (ret < 0) { - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) - continue; + if (ret < 0 && ret != AVERROR_EOF) { + char errbuf[128]; + av_strerror(ret, errbuf, sizeof(errbuf)); - av_log(NULL, AV_LOG_ERROR, "Error while filtering.\n"); + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf); break; } @@ -2510,7 +2737,7 @@ static int transcode(void) for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) { - process_input_packet(ist, NULL); + process_input_packet(ist, NULL, 0); } } poll_filters(); @@ -2521,6 +2748,13 @@ static int transcode(void) /* write the trailer if needed and close file */ for (i = 0; i < nb_output_files; i++) { os = output_files[i]->ctx; + if (!output_files[i]->header_written) { + av_log(NULL, AV_LOG_ERROR, + "Nothing was written into output file %d (%s), because " + "at least one of its streams received no packets.\n", + i, os->filename); + continue; + } av_write_trailer(os); } @@ -2545,6 +2779,8 @@ static int transcode(void) } } + av_buffer_unref(&hw_device_ctx); + /* finished ! */ ret = 0; @@ -2584,7 +2820,7 @@ static int64_t getutime(void) GetProcessTimes(proc, &c, &e, &k, &u); return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10; #else - return av_gettime(); + return av_gettime_relative(); #endif } @@ -2608,7 +2844,7 @@ static int64_t getmaxrss(void) int main(int argc, char **argv) { - int ret; + int i, ret; int64_t ti; register_exit(avconv_cleanup); @@ -2643,6 +2879,11 @@ int main(int argc, char **argv) exit_program(1); } + for (i = 0; i < nb_output_files; i++) { + if (strcmp(output_files[i]->ctx->oformat->name, "rtp")) + want_sdp = 0; + } + ti = getutime(); if (transcode() < 0) exit_program(1); diff --git a/avconv.h b/avconv.h index b932d7e..fcdf3d0 100644 --- a/avconv.h +++ b/avconv.h @@ -54,6 +54,8 @@ enum HWAccelID { HWACCEL_VDPAU, HWACCEL_DXVA2, HWACCEL_VDA, + HWACCEL_QSV, + HWACCEL_VAAPI, }; typedef struct HWAccel { @@ -102,6 +104,7 @@ typedef struct OptionsContext { /* input options */ int64_t input_ts_offset; + int loop; int rate_emu; int accurate_seek; @@ -113,6 +116,10 @@ typedef struct OptionsContext { int nb_hwaccels; SpecifierOpt *hwaccel_devices; int nb_hwaccel_devices; + SpecifierOpt *hwaccel_output_formats; + int nb_hwaccel_output_formats; + SpecifierOpt *autorotate; + int nb_autorotate; /* output options */ StreamMap *stream_maps; @@ -183,6 +190,8 @@ typedef struct OptionsContext { int nb_pass; SpecifierOpt *passlogfiles; int nb_passlogfiles; + SpecifierOpt *max_muxing_queue_size; + int nb_max_muxing_queue_size; } OptionsContext; typedef struct InputFilter { @@ -190,6 +199,21 @@ typedef struct InputFilter { struct InputStream *ist; struct FilterGraph *graph; uint8_t *name; + + AVFifoBuffer *frame_queue; + + // parameters configured for this input + int format; + + int width, height; + AVRational sample_aspect_ratio; + + int sample_rate; + uint64_t channel_layout; + + AVBufferRef *hw_frames_ctx; + + int eof; } InputFilter; typedef struct OutputFilter { @@ -200,6 +224,19 @@ typedef struct OutputFilter { /* temporary storage until stream maps are processed */ AVFilterInOut *out_tmp; + enum AVMediaType type; + + /* desired output stream properties */ + int width, height; + AVRational frame_rate; + int format; + int sample_rate; + uint64_t channel_layout; + + // those are only set if no format is specified and the encoder gives us multiple options + int *formats; + uint64_t *channel_layouts; + int *sample_rates; } OutputFilter; typedef struct FilterGraph { @@ -230,20 +267,20 @@ typedef struct InputStream { int64_t next_dts; /* dts of the last packet read for this stream */ int64_t last_dts; + int64_t min_pts; /* pts with the smallest value in a current stream */ + int64_t max_pts; /* pts with the higher value in a current stream */ + + // when forcing constant input framerate through -r, + // this contains the pts that will be given to the next decoded frame + int64_t cfr_next_pts; + + int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ PtsCorrectionContext pts_ctx; double ts_scale; - int showed_multi_packet_warning; AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ - int resample_height; - int resample_width; - int resample_pix_fmt; - - int resample_sample_fmt; - int resample_sample_rate; - int resample_channels; - uint64_t resample_channel_layout; + int autorotate; /* decoded data from this stream goes into all those filters * currently video and audio only */ @@ -253,6 +290,7 @@ typedef struct InputStream { /* hwaccel options */ enum HWAccelID hwaccel_id; char *hwaccel_device; + enum AVPixelFormat hwaccel_output_format; /* hwaccel context */ enum HWAccelID active_hwaccel_id; @@ -262,6 +300,7 @@ typedef struct InputStream { int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; + AVBufferRef *hw_frames_ctx; /* stats */ // combined size of all the packets read @@ -278,6 +317,10 @@ typedef struct InputFile { int eof_reached; /* true if eof reached */ int eagain; /* true if last read attempt returned EAGAIN */ int ist_index; /* index of first stream in ist_table */ + int loop; /* set number of times input stream should be looped */ + int64_t duration; /* actual duration of the longest stream in a file + at the moment when looping happens */ + AVRational time_base; /* time base of the duration */ int64_t ts_offset; int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */ int64_t recording_time; @@ -313,12 +356,20 @@ typedef struct OutputStream { int64_t first_pts; /* dts of the last packet sent to the muxer */ int64_t last_mux_dts; - AVBitStreamFilterContext *bitstream_filters; + // the timebase of the packets sent to the muxer + AVRational mux_timebase; + + int nb_bitstream_filters; + const AVBitStreamFilter **bitstream_filters; + AVBSFContext **bsf_ctx; + AVCodecContext *enc_ctx; AVCodec *enc; int64_t max_frames; AVFrame *filtered_frame; + void *hwaccel_ctx; + /* video only */ AVRational frame_rate; int force_fps; @@ -343,12 +394,19 @@ typedef struct OutputStream { AVDictionary *resample_opts; int finished; /* no more packets should be written for this stream */ int stream_copy; + + // init_output_stream() has been called for this stream + // The encoder and the bistream filters have been initialized and the stream + // parameters are set in the AVStream. + int initialized; + const char *attachment_filename; int copy_initial_nonkeyframes; enum AVPixelFormat pix_fmts[2]; AVCodecParserContext *parser; + AVCodecContext *parser_avctx; /* stats */ // combined size of all the packets written @@ -358,6 +416,14 @@ typedef struct OutputStream { // number of frames/samples sent to the encoder uint64_t frames_encoded; uint64_t samples_encoded; + + /* packet quality factor */ + int quality; + + int max_muxing_queue_size; + + /* the packets are buffered here until the muxer is ready to be initialized */ + AVFifoBuffer *muxing_queue; } OutputStream; typedef struct OutputFile { @@ -369,6 +435,8 @@ typedef struct OutputFile { uint64_t limit_filesize; int shortest; + + int header_written; } OutputFile; extern InputStream **input_streams; @@ -407,6 +475,8 @@ extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; extern const HWAccel hwaccels[]; +extern int hwaccel_lax_profile_check; +extern AVBufferRef *hw_device_ctx; void reset_options(OptionsContext *o); void show_usage(void); @@ -420,12 +490,20 @@ int guess_input_channel_layout(InputStream *ist); int configure_filtergraph(FilterGraph *fg); int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out); int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); -FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); +int filtergraph_is_simple(FilterGraph *fg); +int init_simple_filtergraph(InputStream *ist, OutputStream *ost); +int init_complex_filtergraph(FilterGraph *fg); + +int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int avconv_parse_options(int argc, char **argv); int vdpau_init(AVCodecContext *s); int dxva2_init(AVCodecContext *s); int vda_init(AVCodecContext *s); +int qsv_init(AVCodecContext *s); +int qsv_transcode_init(OutputStream *ost); +int vaapi_decode_init(AVCodecContext *avctx); +int vaapi_device_init(const char *device); #endif /* AVCONV_H */ diff --git a/avconv_dxva2.c b/avconv_dxva2.c index 4457a21..7578c3f 100644 --- a/avconv_dxva2.c +++ b/avconv_dxva2.c @@ -40,6 +40,9 @@ #include "libavutil/imgutils.h" #include "libavutil/pixfmt.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_dxva2.h" + /* define all the GUIDs used directly here, to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ #include @@ -52,12 +55,11 @@ DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0 DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6); DEFINE_GUID(DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); +DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); -typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT); -typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **); - typedef struct dxva2_mode { const GUID *guid; enum AVCodecID codec; @@ -80,64 +82,25 @@ static const dxva2_mode dxva2_modes[] = { { &DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 }, { &DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, + /* HEVC/H.265 */ + { &DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC }, + { &DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC }, + { NULL, 0 }, }; -typedef struct surface_info { - int used; - uint64_t age; -} surface_info; - typedef struct DXVA2Context { - HMODULE d3dlib; - HMODULE dxva2lib; - - HANDLE deviceHandle; - - IDirect3D9 *d3d9; - IDirect3DDevice9 *d3d9device; - IDirect3DDeviceManager9 *d3d9devmgr; - IDirectXVideoDecoderService *decoder_service; IDirectXVideoDecoder *decoder; GUID decoder_guid; DXVA2_ConfigPictureDecode decoder_config; - - LPDIRECT3DSURFACE9 *surfaces; - surface_info *surface_infos; - uint32_t num_surfaces; - uint64_t surface_age; + IDirectXVideoDecoderService *decoder_service; AVFrame *tmp_frame; -} DXVA2Context; - -typedef struct DXVA2SurfaceWrapper { - DXVA2Context *ctx; - LPDIRECT3DSURFACE9 surface; - IDirectXVideoDecoder *decoder; -} DXVA2SurfaceWrapper; - -static void dxva2_destroy_decoder(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - DXVA2Context *ctx = ist->hwaccel_ctx; - if (ctx->surfaces) { - for (int i = 0; i < ctx->num_surfaces; i++) { - if (ctx->surfaces[i]) - IDirect3DSurface9_Release(ctx->surfaces[i]); - } - } - av_freep(&ctx->surfaces); - av_freep(&ctx->surface_infos); - ctx->num_surfaces = 0; - ctx->surface_age = 0; - - if (ctx->decoder) { - IDirectXVideoDecoder_Release(ctx->decoder); - ctx->decoder = NULL; - } -} + AVBufferRef *hw_device_ctx; + AVBufferRef *hw_frames_ctx; +} DXVA2Context; static void dxva2_uninit(AVCodecContext *s) { @@ -148,29 +111,11 @@ static void dxva2_uninit(AVCodecContext *s) ist->hwaccel_get_buffer = NULL; ist->hwaccel_retrieve_data = NULL; - if (ctx->decoder) - dxva2_destroy_decoder(s); - if (ctx->decoder_service) IDirectXVideoDecoderService_Release(ctx->decoder_service); - if (ctx->d3d9devmgr && ctx->deviceHandle != INVALID_HANDLE_VALUE) - IDirect3DDeviceManager9_CloseDeviceHandle(ctx->d3d9devmgr, ctx->deviceHandle); - - if (ctx->d3d9devmgr) - IDirect3DDeviceManager9_Release(ctx->d3d9devmgr); - - if (ctx->d3d9device) - IDirect3DDevice9_Release(ctx->d3d9device); - - if (ctx->d3d9) - IDirect3D9_Release(ctx->d3d9); - - if (ctx->d3dlib) - FreeLibrary(ctx->d3dlib); - - if (ctx->dxva2lib) - FreeLibrary(ctx->dxva2lib); + av_buffer_unref(&ctx->hw_frames_ctx); + av_buffer_unref(&ctx->hw_device_ctx); av_frame_free(&ctx->tmp_frame); @@ -178,119 +123,34 @@ static void dxva2_uninit(AVCodecContext *s) av_freep(&s->hwaccel_context); } -static void dxva2_release_buffer(void *opaque, uint8_t *data) -{ - DXVA2SurfaceWrapper *w = opaque; - DXVA2Context *ctx = w->ctx; - int i; - - for (i = 0; i < ctx->num_surfaces; i++) { - if (ctx->surfaces[i] == w->surface) { - ctx->surface_infos[i].used = 0; - break; - } - } - IDirect3DSurface9_Release(w->surface); - IDirectXVideoDecoder_Release(w->decoder); - av_free(w); -} - static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) { InputStream *ist = s->opaque; DXVA2Context *ctx = ist->hwaccel_ctx; - int i, old_unused = -1; - LPDIRECT3DSURFACE9 surface; - DXVA2SurfaceWrapper *w = NULL; - - av_assert0(frame->format == AV_PIX_FMT_DXVA2_VLD); - - for (i = 0; i < ctx->num_surfaces; i++) { - surface_info *info = &ctx->surface_infos[i]; - if (!info->used && (old_unused == -1 || info->age < ctx->surface_infos[old_unused].age)) - old_unused = i; - } - if (old_unused == -1) { - av_log(NULL, AV_LOG_ERROR, "No free DXVA2 surface!\n"); - return AVERROR(ENOMEM); - } - i = old_unused; - surface = ctx->surfaces[i]; - - w = av_mallocz(sizeof(*w)); - if (!w) - return AVERROR(ENOMEM); - - frame->buf[0] = av_buffer_create((uint8_t*)surface, 0, - dxva2_release_buffer, w, - AV_BUFFER_FLAG_READONLY); - if (!frame->buf[0]) { - av_free(w); - return AVERROR(ENOMEM); - } - - w->ctx = ctx; - w->surface = surface; - IDirect3DSurface9_AddRef(w->surface); - w->decoder = ctx->decoder; - IDirectXVideoDecoder_AddRef(w->decoder); - - ctx->surface_infos[i].used = 1; - ctx->surface_infos[i].age = ctx->surface_age++; - - frame->data[3] = (uint8_t *)surface; - - return 0; + return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0); } static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) { - LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->data[3]; InputStream *ist = s->opaque; DXVA2Context *ctx = ist->hwaccel_ctx; - D3DSURFACE_DESC surfaceDesc; - D3DLOCKED_RECT LockedRect; - HRESULT hr; int ret; - IDirect3DSurface9_GetDesc(surface, &surfaceDesc); - - ctx->tmp_frame->width = frame->width; - ctx->tmp_frame->height = frame->height; - ctx->tmp_frame->format = AV_PIX_FMT_NV12; - - ret = av_frame_get_buffer(ctx->tmp_frame, 32); + ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); if (ret < 0) return ret; - hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY); - if (FAILED(hr)) { - av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); - return AVERROR_UNKNOWN; - } - - av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0], - (uint8_t*)LockedRect.pBits, - LockedRect.Pitch, frame->width, frame->height); - - av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1], - (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, - LockedRect.Pitch, frame->width, frame->height / 2); - - IDirect3DSurface9_UnlockRect(surface); - ret = av_frame_copy_props(ctx->tmp_frame, frame); - if (ret < 0) - goto fail; + if (ret < 0) { + av_frame_unref(ctx->tmp_frame); + return ret; + } av_frame_unref(frame); av_frame_move_ref(frame, ctx->tmp_frame); return 0; -fail: - av_frame_unref(ctx->tmp_frame); - return ret; } static int dxva2_alloc(AVCodecContext *s) @@ -298,94 +158,40 @@ static int dxva2_alloc(AVCodecContext *s) InputStream *ist = s->opaque; int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; DXVA2Context *ctx; - pDirect3DCreate9 *createD3D = NULL; - pCreateDeviceManager9 *createDeviceManager = NULL; + HANDLE device_handle; HRESULT hr; - D3DPRESENT_PARAMETERS d3dpp = {0}; - D3DDISPLAYMODE d3ddm; - unsigned resetToken = 0; - UINT adapter = D3DADAPTER_DEFAULT; + + AVHWDeviceContext *device_ctx; + AVDXVA2DeviceContext *device_hwctx; + int ret; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM); - ctx->deviceHandle = INVALID_HANDLE_VALUE; - ist->hwaccel_ctx = ctx; ist->hwaccel_uninit = dxva2_uninit; ist->hwaccel_get_buffer = dxva2_get_buffer; ist->hwaccel_retrieve_data = dxva2_retrieve_data; - ctx->d3dlib = LoadLibrary("d3d9.dll"); - if (!ctx->d3dlib) { - av_log(NULL, loglevel, "Failed to load D3D9 library\n"); - goto fail; - } - ctx->dxva2lib = LoadLibrary("dxva2.dll"); - if (!ctx->dxva2lib) { - av_log(NULL, loglevel, "Failed to load DXVA2 library\n"); - goto fail; - } - - createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9"); - if (!createD3D) { - av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n"); - goto fail; - } - createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); - if (!createDeviceManager) { - av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); - goto fail; - } - - ctx->d3d9 = createD3D(D3D_SDK_VERSION); - if (!ctx->d3d9) { - av_log(NULL, loglevel, "Failed to create IDirect3D object\n"); - goto fail; - } - - if (ist->hwaccel_device) { - adapter = atoi(ist->hwaccel_device); - av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter); - } - - IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm); - d3dpp.Windowed = TRUE; - d3dpp.BackBufferWidth = 640; - d3dpp.BackBufferHeight = 480; - d3dpp.BackBufferCount = 0; - d3dpp.BackBufferFormat = d3ddm.Format; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.Flags = D3DPRESENTFLAG_VIDEO; - - hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, - &d3dpp, &ctx->d3d9device); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to create Direct3D device\n"); - goto fail; - } - - hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to create Direct3D device manager\n"); - goto fail; - } - - hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n"); + ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, AV_HWDEVICE_TYPE_DXVA2, + ist->hwaccel_device, NULL, 0); + if (ret < 0) goto fail; - } + device_ctx = (AVHWDeviceContext*)ctx->hw_device_ctx->data; + device_hwctx = device_ctx->hwctx; - hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle); + hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, + &device_handle); if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to open device handle\n"); + av_log(NULL, loglevel, "Failed to open a device handle\n"); goto fail; } - hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); + hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle, + &IID_IDirectXVideoDecoderService, + (void **)&ctx->decoder_service); + IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); goto fail; @@ -461,13 +267,18 @@ static int dxva2_create_decoder(AVCodecContext *s) GUID *guid_list = NULL; unsigned guid_count = 0, i, j; GUID device_guid = GUID_NULL; + const D3DFORMAT surface_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2'); D3DFORMAT target_format = 0; DXVA2_VideoDesc desc = { 0 }; DXVA2_ConfigPictureDecode config; HRESULT hr; - int surface_alignment; + int surface_alignment, num_surfaces; int ret; + AVDXVA2FramesContext *frames_hwctx; + AVHWFramesContext *frames_ctx; + hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n"); @@ -494,7 +305,7 @@ static int dxva2_create_decoder(AVCodecContext *s) } for (j = 0; j < target_count; j++) { const D3DFORMAT format = target_list[j]; - if (format == MKTAG('N','V','1','2')) { + if (format == surface_format) { target_format = format; break; } @@ -525,45 +336,50 @@ static int dxva2_create_decoder(AVCodecContext *s) but it causes issues for H.264 on certain AMD GPUs..... */ if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) surface_alignment = 32; + /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure + all coding features have enough room to work with */ + else if (s->codec_id == AV_CODEC_ID_HEVC) + surface_alignment = 128; else surface_alignment = 16; /* 4 base work surfaces */ - ctx->num_surfaces = 4; + num_surfaces = 4; /* add surfaces based on number of possible refs */ - if (s->codec_id == AV_CODEC_ID_H264) - ctx->num_surfaces += 16; + if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC) + num_surfaces += 16; else - ctx->num_surfaces += 2; + num_surfaces += 2; /* add extra surfaces for frame threading */ if (s->active_thread_type & FF_THREAD_FRAME) - ctx->num_surfaces += s->thread_count; + num_surfaces += s->thread_count; - ctx->surfaces = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surfaces)); - ctx->surface_infos = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surface_infos)); - - if (!ctx->surfaces || !ctx->surface_infos) { - av_log(NULL, loglevel, "Unable to allocate surface arrays\n"); + ctx->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->hw_device_ctx); + if (!ctx->hw_frames_ctx) goto fail; - } + frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; + frames_hwctx = frames_ctx->hwctx; - hr = IDirectXVideoDecoderService_CreateSurface(ctx->decoder_service, - FFALIGN(s->coded_width, surface_alignment), - FFALIGN(s->coded_height, surface_alignment), - ctx->num_surfaces - 1, - target_format, D3DPOOL_DEFAULT, 0, - DXVA2_VideoDecoderRenderTarget, - ctx->surfaces, NULL); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to create %d video surfaces\n", ctx->num_surfaces); + frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; + frames_ctx->sw_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + frames_ctx->width = FFALIGN(s->coded_width, surface_alignment); + frames_ctx->height = FFALIGN(s->coded_height, surface_alignment); + frames_ctx->initial_pool_size = num_surfaces; + + frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; + + ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); + if (ret < 0) { + av_log(NULL, loglevel, "Failed to initialize the HW frames context\n"); goto fail; } hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid, - &desc, &config, ctx->surfaces, - ctx->num_surfaces, &ctx->decoder); + &desc, &config, frames_hwctx->surfaces, + frames_hwctx->nb_surfaces, &frames_hwctx->decoder_to_release); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n"); goto fail; @@ -573,16 +389,16 @@ static int dxva2_create_decoder(AVCodecContext *s) ctx->decoder_config = config; dxva_ctx->cfg = &ctx->decoder_config; - dxva_ctx->decoder = ctx->decoder; - dxva_ctx->surface = ctx->surfaces; - dxva_ctx->surface_count = ctx->num_surfaces; + dxva_ctx->decoder = frames_hwctx->decoder_to_release; + dxva_ctx->surface = frames_hwctx->surfaces; + dxva_ctx->surface_count = frames_hwctx->nb_surfaces; if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E)) dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; return 0; fail: - dxva2_destroy_decoder(s); + av_buffer_unref(&ctx->hw_frames_ctx); return AVERROR(EINVAL); } @@ -606,8 +422,13 @@ int dxva2_init(AVCodecContext *s) return AVERROR(EINVAL); } - if (ctx->decoder) - dxva2_destroy_decoder(s); + if (s->codec_id == AV_CODEC_ID_HEVC && + s->profile != FF_PROFILE_HEVC_MAIN && s->profile != FF_PROFILE_HEVC_MAIN_10) { + av_log(NULL, loglevel, "Unsupported HEVC profile for DXVA2 HWAccel: %d\n", s->profile); + return AVERROR(EINVAL); + } + + av_buffer_unref(&ctx->hw_frames_ctx); ret = dxva2_create_decoder(s); if (ret < 0) { diff --git a/avconv_filter.c b/avconv_filter.c index 1eda7b8..4330802 100644 --- a/avconv_filter.c +++ b/avconv_filter.c @@ -23,12 +23,14 @@ #include "avconv.h" #include "libavfilter/avfilter.h" +#include "libavfilter/buffersrc.h" #include "libavresample/avresample.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" @@ -36,13 +38,13 @@ /* Define a function for building a string containing a list of * allowed formats. */ -#define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name) \ -static char *choose_ ## var ## s(OutputStream *ost) \ +#define DEF_CHOOSE_FORMAT(suffix, type, var, supported_list, none, get_name) \ +static char *choose_ ## suffix (OutputFilter *ofilter) \ { \ - if (ost->enc_ctx->var != none) { \ - get_name(ost->enc_ctx->var); \ + if (ofilter->var != none) { \ + get_name(ofilter->var); \ return av_strdup(name); \ - } else if (ost->enc && ost->enc->supported_list) { \ + } else if (ofilter->supported_list) { \ const type *p; \ AVIOContext *s = NULL; \ uint8_t *ret; \ @@ -51,7 +53,7 @@ static char *choose_ ## var ## s(OutputStream *ost) \ if (avio_open_dyn_buf(&s) < 0) \ exit(1); \ \ - for (p = ost->enc->supported_list; *p != none; p++) { \ + for (p = ofilter->supported_list; *p != none; p++) { \ get_name(*p); \ avio_printf(s, "%s|", name); \ } \ @@ -62,19 +64,19 @@ static char *choose_ ## var ## s(OutputStream *ost) \ return NULL; \ } -DEF_CHOOSE_FORMAT(enum AVPixelFormat, pix_fmt, pix_fmts, AV_PIX_FMT_NONE, +DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats, AV_PIX_FMT_NONE, GET_PIX_FMT_NAME) -DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts, +DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME) -DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0, +DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, GET_SAMPLE_RATE_NAME) -DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0, +DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0, GET_CH_LAYOUT_NAME) -FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) +int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg = av_mallocz(sizeof(*fg)); @@ -87,6 +89,7 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit(1); fg->outputs[0]->ost = ost; fg->outputs[0]->graph = fg; + fg->outputs[0]->format = -1; ost->filter = fg->outputs[0]; @@ -95,6 +98,11 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit(1); fg->inputs[0]->ist = ist; fg->inputs[0]->graph = fg; + fg->inputs[0]->format = -1; + + fg->inputs[0]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!fg->inputs[0]) + exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = fg->inputs[0]; @@ -102,7 +110,7 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; - return fg; + return 0; } static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) @@ -132,7 +140,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) s = input_files[file_idx]->ctx; for (i = 0; i < s->nb_streams; i++) { - if (s->streams[i]->codec->codec_type != type) + if (s->streams[i]->codecpar->codec_type != type) continue; if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { st = s->streams[i]; @@ -170,11 +178,55 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit(1); fg->inputs[fg->nb_inputs - 1]->ist = ist; fg->inputs[fg->nb_inputs - 1]->graph = fg; + fg->inputs[fg->nb_inputs - 1]->format = -1; + + fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!fg->inputs[fg->nb_inputs - 1]->frame_queue) + exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; } +int init_complex_filtergraph(FilterGraph *fg) +{ + AVFilterInOut *inputs, *outputs, *cur; + AVFilterGraph *graph; + int ret = 0; + + /* this graph is only used for determining the kinds of inputs + * and outputs we have, and is discarded on exit from this function */ + graph = avfilter_graph_alloc(); + if (!graph) + return AVERROR(ENOMEM); + + ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); + if (ret < 0) + goto fail; + + for (cur = inputs; cur; cur = cur->next) + init_input_filter(fg, cur); + + for (cur = outputs; cur;) { + GROW_ARRAY(fg->outputs, fg->nb_outputs); + fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])); + if (!fg->outputs[fg->nb_outputs - 1]) + exit(1); + + fg->outputs[fg->nb_outputs - 1]->graph = fg; + fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; + fg->outputs[fg->nb_outputs - 1]->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, + cur->pad_idx); + cur = cur->next; + fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; + } + +fail: + avfilter_inout_free(&inputs); + avfilter_graph_free(&graph); + return ret; +} + static int insert_trim(int64_t start_time, int64_t duration, AVFilterContext **last_filter, int *pad_idx, const char *filter_name) @@ -226,12 +278,33 @@ static int insert_trim(int64_t start_time, int64_t duration, return 0; } +static int insert_filter(AVFilterContext **last_filter, int *pad_idx, + const char *filter_name, const char *args) +{ + AVFilterGraph *graph = (*last_filter)->graph; + AVFilterContext *ctx; + int ret; + + ret = avfilter_graph_create_filter(&ctx, + avfilter_get_by_name(filter_name), + filter_name, args, NULL, graph); + if (ret < 0) + return ret; + + ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); + if (ret < 0) + return ret; + + *last_filter = ctx; + *pad_idx = 0; + return 0; +} + static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; int ret; @@ -244,13 +317,12 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, if (ret < 0) return ret; - if (codec->width || codec->height) { + if (ofilter->width || ofilter->height) { char args[255]; AVFilterContext *filter; snprintf(args, sizeof(args), "%d:%d:0x%X", - codec->width, - codec->height, + ofilter->width, ofilter->height, (unsigned)ost->sws_flags); snprintf(name, sizeof(name), "scaler for output stream %d:%d", ost->file_index, ost->index); @@ -264,21 +336,21 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if ((pix_fmts = choose_pix_fmts(ost))) { + if ((pix_fmts = choose_pix_fmts(ofilter))) { AVFilterContext *filter; snprintf(name, sizeof(name), "pixel format for output stream %d:%d", ost->file_index, ost->index); - if ((ret = avfilter_graph_create_filter(&filter, - avfilter_get_by_name("format"), - "format", pix_fmts, NULL, - fg->graph)) < 0) + ret = avfilter_graph_create_filter(&filter, + avfilter_get_by_name("format"), + "format", pix_fmts, NULL, fg->graph); + av_freep(&pix_fmts); + if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) return ret; last_filter = filter; pad_idx = 0; - av_freep(&pix_fmts); } if (ost->frame_rate.num) { @@ -337,9 +409,9 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, if (codec->channels && !codec->channel_layout) codec->channel_layout = av_get_default_channel_layout(codec->channels); - sample_fmts = choose_sample_fmts(ost); - sample_rates = choose_sample_rates(ost); - channel_layouts = choose_channel_layouts(ost); + sample_fmts = choose_sample_fmts(ofilter); + sample_rates = choose_sample_rates(ofilter); + channel_layouts = choose_channel_layouts(ofilter); if (sample_fmts || sample_rates || channel_layouts) { AVFilterContext *format; char args[256]; @@ -427,40 +499,59 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, InputFile *f = input_files[ist->file_index]; AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : ist->st->time_base; - AVRational sar; - char args[255], name[255]; + AVBufferSrcParameters *par; + char name[255]; int ret, pad_idx = 0; - sar = ist->st->sample_aspect_ratio.num ? - ist->st->sample_aspect_ratio : - ist->dec_ctx->sample_aspect_ratio; - snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->dec_ctx->width, - ist->dec_ctx->height, - ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->dec_ctx->pix_fmt, - tb.num, tb.den, sar.num, sar.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, - args, NULL, fg->graph)) < 0) - return ret; - last_filter = ifilter->filter; + ifilter->filter = avfilter_graph_alloc_filter(fg->graph, buffer_filt, name); + if (!ifilter->filter) + return AVERROR(ENOMEM); - if (ist->framerate.num) { - AVFilterContext *setpts; + par = av_buffersrc_parameters_alloc(); + if (!par) + return AVERROR(ENOMEM); - snprintf(name, sizeof(name), "force CFR for input from stream %d:%d", - ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&setpts, - avfilter_get_by_name("setpts"), - name, "N", NULL, - fg->graph)) < 0) - return ret; + par->sample_aspect_ratio = ifilter->sample_aspect_ratio; + par->width = ifilter->width; + par->height = ifilter->height; + par->format = ifilter->format; + par->time_base = tb; + if (ist->framerate.num) + par->frame_rate = ist->framerate; + par->hw_frames_ctx = ifilter->hw_frames_ctx; + + ret = av_buffersrc_parameters_set(ifilter->filter, par); + av_freep(&par); + if (ret < 0) + return ret; - if ((ret = avfilter_link(last_filter, 0, setpts, 0)) < 0) - return ret; + ret = avfilter_init_str(ifilter->filter, NULL); + if (ret < 0) + return ret; + + last_filter = ifilter->filter; - last_filter = setpts; + if (ist->autorotate) { + uint8_t* displaymatrix = av_stream_get_side_data(ist->st, + AV_PKT_DATA_DISPLAYMATRIX, NULL); + if (displaymatrix) { + double rot = av_display_rotation_get((int32_t*) displaymatrix); + if (rot < -135 || rot > 135) { + ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); + if (ret < 0) + return ret; + ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); + } else if (rot < -45) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=clock"); + } else if (rot > 45) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=cclock"); + } + if (ret < 0) + return ret; + } } snprintf(name, sizeof(name), "trim for input stream %d:%d", @@ -482,21 +573,33 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); InputStream *ist = ifilter->ist; InputFile *f = input_files[ist->file_index]; + AVBufferSrcParameters *par; char args[255], name[255]; int ret, pad_idx = 0; - snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s" - ":channel_layout=0x%"PRIx64, - 1, ist->dec_ctx->sample_rate, - ist->dec_ctx->sample_rate, - av_get_sample_fmt_name(ist->dec_ctx->sample_fmt), - ist->dec_ctx->channel_layout); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, - name, args, NULL, - fg->graph)) < 0) + ifilter->filter = avfilter_graph_alloc_filter(fg->graph, abuffer_filt, name); + if (!ifilter->filter) + return AVERROR(ENOMEM); + + par = av_buffersrc_parameters_alloc(); + if (!par) + return AVERROR(ENOMEM); + + par->time_base = (AVRational){ 1, ifilter->sample_rate }; + par->sample_rate = ifilter->sample_rate; + par->format = ifilter->format; + par->channel_layout = ifilter->channel_layout; + + ret = av_buffersrc_parameters_set(ifilter->filter, par); + av_freep(&par); + if (ret < 0) + return ret; + + ret = avfilter_init_str(ifilter->filter, NULL); + if (ret < 0) return ret; last_filter = ifilter->filter; @@ -579,7 +682,7 @@ static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; - int ret, i, init = !fg->graph, simple = !fg->graph_desc; + int ret, i, simple = filtergraph_is_simple(fg); const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; @@ -608,45 +711,94 @@ int configure_filtergraph(FilterGraph *fg) if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; + if (hw_device_ctx) { + for (i = 0; i < fg->graph->nb_filters; i++) { + fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(hw_device_ctx); + } + } + if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " "exactly one input and output.\n", graph_desc); return AVERROR(EINVAL); } - for (cur = inputs; !simple && init && cur; cur = cur->next) - init_input_filter(fg, cur); - for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) return ret; avfilter_inout_free(&inputs); - if (!init || simple) { - /* we already know the mappings between lavfi outputs and output streams, - * so we can finish the setup */ - for (cur = outputs, i = 0; cur; cur = cur->next, i++) - configure_output_filter(fg, fg->outputs[i], cur); - avfilter_inout_free(&outputs); + for (cur = outputs, i = 0; cur; cur = cur->next, i++) { + OutputFilter *ofilter = fg->outputs[i]; + if (ofilter->ost) + configure_output_filter(fg, ofilter, cur); + } - if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) - return ret; - } else { - /* wait until output mappings are processed */ - for (cur = outputs; cur;) { - GROW_ARRAY(fg->outputs, fg->nb_outputs); - if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])))) - exit(1); - fg->outputs[fg->nb_outputs - 1]->graph = fg; - fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; - cur = cur->next; - fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; + avfilter_inout_free(&outputs); + + if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) + return ret; + + /* limit the lists of allowed formats to the ones selected, to + * make sure they stay the same if the filtergraph is reconfigured later */ + for (i = 0; i < fg->nb_outputs; i++) { + OutputFilter *ofilter = fg->outputs[i]; + AVFilterLink *link = ofilter->filter->inputs[0]; + + ofilter->format = link->format; + + ofilter->width = link->w; + ofilter->height = link->h; + + ofilter->sample_rate = link->sample_rate; + ofilter->channel_layout = link->channel_layout; + } + + for (i = 0; i < fg->nb_inputs; i++) { + while (av_fifo_size(fg->inputs[i]->frame_queue)) { + AVFrame *tmp; + av_fifo_generic_read(fg->inputs[i]->frame_queue, &tmp, sizeof(tmp), NULL); + ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); + av_frame_free(&tmp); + if (ret < 0) + return ret; + } + } + + /* send the EOFs for the finished inputs */ + for (i = 0; i < fg->nb_inputs; i++) { + if (fg->inputs[i]->eof) { + ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL); + if (ret < 0) + return ret; } } return 0; } +int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) +{ + av_buffer_unref(&ifilter->hw_frames_ctx); + + ifilter->format = frame->format; + + ifilter->width = frame->width; + ifilter->height = frame->height; + ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; + + ifilter->sample_rate = frame->sample_rate; + ifilter->channel_layout = frame->channel_layout; + + if (frame->hw_frames_ctx) { + ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); + if (!ifilter->hw_frames_ctx) + return AVERROR(ENOMEM); + } + + return 0; +} + int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) { int i; @@ -656,3 +808,7 @@ int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) return 0; } +int filtergraph_is_simple(FilterGraph *fg) +{ + return !fg->graph_desc; +} diff --git a/avconv_opt.c b/avconv_opt.c index 6d43bc1..362a5b7 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -41,6 +41,8 @@ #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" +#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass" + #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ {\ int i, ret;\ @@ -63,8 +65,16 @@ const HWAccel hwaccels[] = { #if CONFIG_VDA { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, #endif +#if CONFIG_LIBMFX + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, +#endif +#if CONFIG_VAAPI + { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI }, +#endif { 0 }, }; +int hwaccel_lax_profile_check = 0; +AVBufferRef *hw_device_ctx; char *vstats_filename; @@ -175,6 +185,18 @@ static double parse_frame_aspect_ratio(const char *arg) return ar; } +static int show_hwaccels(void *optctx, const char *opt, const char *arg) +{ + int i; + + printf("Supported hardware acceleration:\n"); + for (i = 0; i < FF_ARRAY_ELEMS(hwaccels) - 1; i++) { + printf("%s\n", hwaccels[i].name); + } + printf("\n"); + return 0; +} + static int opt_audio_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -213,6 +235,8 @@ static int opt_map(void *optctx, const char *opt, const char *arg) arg++; } map = av_strdup(arg); + if (!map) + return AVERROR(ENOMEM); /* parse sync stream first, just pick first matching stream */ if (sync = strchr(map, ',')) { @@ -302,6 +326,17 @@ static int opt_attach(void *optctx, const char *opt, const char *arg) return 0; } +#if CONFIG_VAAPI +static int opt_vaapi_device(void *optctx, const char *opt, const char *arg) +{ + int err; + err = vaapi_device_init(arg); + if (err < 0) + exit_program(1); + return 0; +} +#endif + /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse @@ -451,11 +486,11 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream * MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st); if (codec_name) { - AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0); - st->codec->codec_id = codec->id; + AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); + st->codecpar->codec_id = codec->id; return codec; } else - return avcodec_find_decoder(st->codec->codec_id); + return avcodec_find_decoder(st->codecpar->codec_id); } /* Add all the streams from the given input file to the global @@ -466,9 +501,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; - AVCodecContext *dec = st->codec; + AVCodecParameters *par = st->codecpar; InputStream *ist = av_mallocz(sizeof(*ist)); char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; + char *hwaccel_output_format = NULL; char *codec_tag = NULL; char *next; @@ -482,20 +518,26 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->file_index = nb_input_files; ist->discard = 1; st->discard = AVDISCARD_ALL; + ist->nb_samples = 0; + ist->min_pts = INT64_MAX; + ist->max_pts = INT64_MIN; ist->ts_scale = 1.0; MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); + ist->autorotate = 1; + MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); if (codec_tag) { uint32_t tag = strtol(codec_tag, &next, 0); if (*next) tag = AV_RL32(codec_tag); - st->codec->codec_tag = tag; + st->codecpar->codec_tag = tag; } ist->dec = choose_decoder(o, ic, st); - ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, ist->dec); + ist->decoder_opts = filter_codec_opts(o->g->codec_opts, par->codec_id, ic, st, ist->dec); ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) { @@ -503,18 +545,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } - ret = avcodec_copy_context(ist->dec_ctx, dec); + ret = avcodec_parameters_to_context(ist->dec_ctx, par); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); exit_program(1); } - switch (dec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: - ist->resample_height = ist->dec_ctx->height; - ist->resample_width = ist->dec_ctx->width; - ist->resample_pix_fmt = ist->dec_ctx->pix_fmt; - MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); if (framerate && av_parse_video_rate(&ist->framerate, framerate) < 0) { @@ -556,17 +594,24 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if (!ist->hwaccel_device) exit_program(1); } + + MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, + hwaccel_output_format, ic, st); + if (hwaccel_output_format) { + ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); + if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { + av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output " + "format: %s", hwaccel_output_format); + } + } else { + ist->hwaccel_output_format = AV_PIX_FMT_NONE; + } + ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; break; case AVMEDIA_TYPE_AUDIO: guess_input_channel_layout(ist); - - ist->resample_sample_fmt = ist->dec_ctx->sample_fmt; - ist->resample_sample_rate = ist->dec_ctx->sample_rate; - ist->resample_channels = ist->dec_ctx->channels; - ist->resample_channel_layout = ist->dec_ctx->channel_layout; - break; case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_SUBTITLE: @@ -612,7 +657,7 @@ static void dump_attachment(AVStream *st, const char *filename) AVIOContext *out = NULL; AVDictionaryEntry *e; - if (!st->codec->extradata_size) { + if (!st->codecpar->extradata_size) { av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", nb_input_files - 1, st->index); return; @@ -633,7 +678,7 @@ static void dump_attachment(AVStream *st, const char *filename) exit_program(1); } - avio_write(out, st->codec->extradata, st->codec->extradata_size); + avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size); avio_flush(out); avio_close(out); } @@ -705,7 +750,7 @@ static int open_input_file(OptionsContext *o, const char *filename) ic->flags |= AVFMT_FLAG_NONBLOCK; ic->interrupt_callback = int_cb; - /* open the input file with generic libav function */ + /* open the input file with generic Libav function */ err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts); if (err < 0) { print_error(filename, err); @@ -764,6 +809,9 @@ static int open_input_file(OptionsContext *o, const char *filename) f->nb_streams = ic->nb_streams; f->rate_emu = o->rate_emu; f->accurate_seek = o->accurate_seek; + f->loop = o->loop; + f->duration = 0; + f->time_base = (AVRational){ 1, 1 }; /* check if all codec options have been used */ unused_opts = strip_specifiers(o->g->codec_opts); @@ -861,21 +909,39 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV return ret; } -static void choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost) +static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost) { + enum AVMediaType type = ost->st->codecpar->codec_type; char *codec_name = NULL; - MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); - if (!codec_name) { - ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, - NULL, ost->st->codec->codec_type); - ost->enc = avcodec_find_encoder(ost->st->codec->codec_id); - } else if (!strcmp(codec_name, "copy")) - ost->stream_copy = 1; - else { - ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1); - ost->st->codec->codec_id = ost->enc->id; + if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { + MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); + if (!codec_name) { + ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->filename, + NULL, ost->st->codecpar->codec_type); + ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id); + if (!ost->enc) { + av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for " + "output stream #%d:%d. Default encoder for format %s is " + "probably disabled. Please choose an encoder manually.\n", + ost->file_index, ost->index, s->oformat->name); + return AVERROR_ENCODER_NOT_FOUND; + } + } else if (!strcmp(codec_name, "copy")) + ost->stream_copy = 1; + else { + ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1); + ost->st->codecpar->codec_id = ost->enc->id; + } + + ost->encoding_needed = !ost->stream_copy; + } else { + /* no encoding supported for other media types */ + ost->stream_copy = 1; + ost->encoding_needed = 0; } + + return 0; } static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type) @@ -883,8 +949,8 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e OutputStream *ost; AVStream *st = avformat_new_stream(oc, NULL); int idx = oc->nb_streams - 1, ret = 0; - char *bsf = NULL, *next, *codec_tag = NULL; - AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL; + const char *bsfs = NULL; + char *next, *codec_tag = NULL; double qscale = -1; if (!st) { @@ -903,8 +969,14 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->file_index = nb_output_files - 1; ost->index = idx; ost->st = st; - st->codec->codec_type = type; - choose_encoder(o, oc, ost); + st->codecpar->codec_type = type; + + ret = choose_encoder(o, oc, ost); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream " + "%d:%d\n", ost->file_index, ost->index); + exit_program(1); + } ost->enc_ctx = avcodec_alloc_context3(ost->enc); if (!ost->enc_ctx) { @@ -950,21 +1022,31 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); - MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st); - while (bsf) { - if (next = strchr(bsf, ',')) - *next++ = 0; - if (!(bsfc = av_bitstream_filter_init(bsf))) { + MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); + while (bsfs && *bsfs) { + const AVBitStreamFilter *filter; + char *bsf; + + bsf = av_get_token(&bsfs, ","); + if (!bsf) + exit_program(1); + + filter = av_bsf_get_by_name(bsf); + if (!filter) { av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf); exit_program(1); } - if (bsfc_prev) - bsfc_prev->next = bsfc; - else - ost->bitstream_filters = bsfc; + av_freep(&bsf); - bsfc_prev = bsfc; - bsf = next; + ost->bitstream_filters = av_realloc_array(ost->bitstream_filters, + ost->nb_bitstream_filters + 1, + sizeof(*ost->bitstream_filters)); + if (!ost->bitstream_filters) + exit_program(1); + + ost->bitstream_filters[ost->nb_bitstream_filters++] = filter; + if (*bsfs) + bsfs++; } MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); @@ -977,12 +1059,16 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); if (qscale >= 0) { - ost->enc_ctx->flags |= CODEC_FLAG_QSCALE; + ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; } + ost->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); + ost->max_muxing_queue_size *= sizeof(AVPacket); + if (oc->oformat->flags & AVFMT_GLOBALHEADER) - ost->enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; + ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags); @@ -991,6 +1077,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->pix_fmts[0] = ost->pix_fmts[1] = AV_PIX_FMT_NONE; ost->last_mux_dts = AV_NOPTS_VALUE; + ost->muxing_queue = av_fifo_alloc(8 * sizeof(AVPacket)); + if (!ost->muxing_queue) + exit_program(1); + return ost; } @@ -1060,7 +1150,7 @@ static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, else if (filter) return av_strdup(filter); - return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ? + return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); } @@ -1134,6 +1224,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) video_enc->rc_override = av_realloc(video_enc->rc_override, sizeof(RcOverride) * (i + 1)); + if (!video_enc->rc_override) { + av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); + exit_program(1); + } video_enc->rc_override[i].start_frame = start; video_enc->rc_override[i].end_frame = end; if (q > 0) { @@ -1154,9 +1248,9 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st); if (do_pass) { if (do_pass == 1) { - video_enc->flags |= CODEC_FLAG_PASS1; + video_enc->flags |= AV_CODEC_FLAG_PASS1; } else { - video_enc->flags |= CODEC_FLAG_PASS2; + video_enc->flags |= AV_CODEC_FLAG_PASS2; } } @@ -1165,6 +1259,38 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) exit_program(1); + if (do_pass) { + char logfilename[1024]; + FILE *f; + + snprintf(logfilename, sizeof(logfilename), "%s-%d.log", + ost->logfile_prefix ? ost->logfile_prefix : + DEFAULT_PASS_LOGFILENAME_PREFIX, + i); + if (!strcmp(ost->enc->name, "libx264")) { + av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); + } else { + if (video_enc->flags & AV_CODEC_FLAG_PASS1) { + f = fopen(logfilename, "wb"); + if (!f) { + av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", + logfilename, strerror(errno)); + exit_program(1); + } + ost->logfile = f; + } else { + char *logbuffer = read_file(logfilename); + + if (!logbuffer) { + av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", + logfilename); + exit_program(1); + } + video_enc->stats_in = logbuffer; + } + } + } + MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st); if (ost->forced_keyframes) ost->forced_keyframes = av_strdup(ost->forced_keyframes); @@ -1324,8 +1450,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, { OutputStream *ost; - switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads, - ofilter->out_tmp->pad_idx)) { + switch (ofilter->type) { case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break; default: @@ -1338,6 +1463,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, ost->filter = ofilter; ofilter->ost = ost; + ofilter->format = -1; if (ost->stream_copy) { av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " @@ -1346,21 +1472,18 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, exit_program(1); } - if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n"); - exit_program(1); - } avfilter_inout_free(&ofilter->out_tmp); } -static int configure_complex_filters(void) +static int init_complex_filters(void) { int i, ret = 0; - for (i = 0; i < nb_filtergraphs; i++) - if (!filtergraphs[i]->graph && - (ret = configure_filtergraph(filtergraphs[i])) < 0) + for (i = 0; i < nb_filtergraphs; i++) { + ret = init_complex_filtergraph(filtergraphs[i]); + if (ret < 0) return ret; + } return 0; } @@ -1375,11 +1498,6 @@ static int open_output_file(OptionsContext *o, const char *filename) AVDictionary *unused_opts = NULL; AVDictionaryEntry *e = NULL; - if (configure_complex_filters() < 0) { - av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n"); - exit_program(1); - } - GROW_ARRAY(output_files, nb_output_files); of = av_mallocz(sizeof(*of)); if (!of) @@ -1433,8 +1551,7 @@ static int open_output_file(OptionsContext *o, const char *filename) if (!ofilter->out_tmp || ofilter->out_tmp->name) continue; - switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads, - ofilter->out_tmp->pad_idx)) { + switch (ofilter->type) { case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break; case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break; case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break; @@ -1459,9 +1576,9 @@ static int open_output_file(OptionsContext *o, const char *filename) int area = 0, idx = -1; for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - ist->st->codec->width * ist->st->codec->height > area) { - area = ist->st->codec->width * ist->st->codec->height; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + ist->st->codecpar->width * ist->st->codecpar->height > area) { + area = ist->st->codecpar->width * ist->st->codecpar->height; idx = i; } } @@ -1473,9 +1590,9 @@ static int open_output_file(OptionsContext *o, const char *filename) int channels = 0, idx = -1; for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - ist->st->codec->channels > channels) { - channels = ist->st->codec->channels; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + ist->st->codecpar->channels > channels) { + channels = ist->st->codecpar->channels; idx = i; } } @@ -1485,7 +1602,7 @@ static int open_output_file(OptionsContext *o, const char *filename) /* subtitles: pick first */ if (!o->subtitle_disable && oc->oformat->subtitle_codec != AV_CODEC_ID_NONE) { for (i = 0; i < nb_input_streams; i++) - if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { NEW_STREAM(subtitle, i); break; } @@ -1522,7 +1639,7 @@ loop_end: init_output_filter(ofilter, o, oc); } else { ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index]; - switch (ist->st->codec->codec_type) { + switch (ist->st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break; case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break; @@ -1571,14 +1688,20 @@ loop_end: ost->stream_copy = 0; ost->source_index = -1; ost->attachment_filename = o->attachments[i]; - ost->st->codec->extradata = attachment; - ost->st->codec->extradata_size = len; + ost->st->codecpar->extradata = attachment; + ost->st->codecpar->extradata_size = len; p = strrchr(o->attachments[i], '/'); av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); avio_close(pb); } + if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { + av_dump_format(oc, nb_output_files - 1, oc->filename, 1); + av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); + exit_program(1); + } + /* check if all codec options have been used */ unused_opts = strip_specifiers(o->g->codec_opts); for (i = of->ost_index; i < nb_output_streams; i++) { @@ -1612,6 +1735,131 @@ loop_end: } av_dict_free(&unused_opts); + /* set the decoding_needed flags and create simple filtergraphs */ + for (i = of->ost_index; i < nb_output_streams; i++) { + OutputStream *ost = output_streams[i]; + + if (ost->encoding_needed && ost->source_index >= 0) { + InputStream *ist = input_streams[ost->source_index]; + ist->decoding_needed = 1; + + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + err = init_simple_filtergraph(ist, ost); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Error initializing a simple filtergraph between streams " + "%d:%d->%d:%d\n", ist->file_index, ost->source_index, + nb_output_files - 1, ost->st->index); + exit_program(1); + } + } + } + + /* + * We want CFR output if and only if one of those is true: + * 1) user specified output framerate with -r + * 2) user specified -vsync cfr + * 3) output format is CFR and the user didn't force vsync to + * something else than CFR + * + * in such a case, set ost->frame_rate + */ + if (ost->encoding_needed && ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { + int format_cfr = !(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS)); + int need_cfr = !!ost->frame_rate.num; + + if (video_sync_method == VSYNC_CFR || + (video_sync_method == VSYNC_AUTO && format_cfr)) + need_cfr = 1; + + if (need_cfr && !ost->frame_rate.num) { + InputStream *ist = ost->source_index >= 0 ? input_streams[ost->source_index] : NULL; + + if (ist && ist->framerate.num) + ost->frame_rate = ist->framerate; + else if (ist && ist->st->avg_frame_rate.num) + ost->frame_rate = ist->st->avg_frame_rate; + else { + av_log(NULL, AV_LOG_WARNING, "Constant framerate requested " + "for the output stream #%d:%d, but no information " + "about the input framerate is available. Falling " + "back to a default value of 25fps. Use the -r option " + "if you want a different framerate.\n", + ost->file_index, ost->index); + ost->frame_rate = (AVRational){ 25, 1 }; + } + } + + if (need_cfr && ost->enc->supported_framerates && !ost->force_fps) { + int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); + ost->frame_rate = ost->enc->supported_framerates[idx]; + } + } + + /* set the filter output constraints */ + if (ost->filter) { + OutputFilter *f = ost->filter; + int count; + switch (ost->enc_ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + f->frame_rate = ost->frame_rate; + f->width = ost->enc_ctx->width; + f->height = ost->enc_ctx->height; + if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { + f->format = ost->enc_ctx->pix_fmt; + } else if (ost->enc->pix_fmts) { + count = 0; + while (ost->enc->pix_fmts[count] != AV_PIX_FMT_NONE) + count++; + f->formats = av_mallocz_array(count + 1, sizeof(*f->formats)); + if (!f->formats) + exit_program(1); + memcpy(f->formats, ost->enc->pix_fmts, (count + 1) * sizeof(*f->formats)); + } + break; + case AVMEDIA_TYPE_AUDIO: + if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { + f->format = ost->enc_ctx->sample_fmt; + } else if (ost->enc->sample_fmts) { + count = 0; + while (ost->enc->sample_fmts[count] != AV_SAMPLE_FMT_NONE) + count++; + f->formats = av_mallocz_array(count + 1, sizeof(*f->formats)); + if (!f->formats) + exit_program(1); + memcpy(f->formats, ost->enc->sample_fmts, (count + 1) * sizeof(*f->formats)); + } + if (ost->enc_ctx->sample_rate) { + f->sample_rate = ost->enc_ctx->sample_rate; + } else if (ost->enc->supported_samplerates) { + count = 0; + while (ost->enc->supported_samplerates[count]) + count++; + f->sample_rates = av_mallocz_array(count + 1, sizeof(*f->sample_rates)); + if (!f->sample_rates) + exit_program(1); + memcpy(f->sample_rates, ost->enc->supported_samplerates, + (count + 1) * sizeof(*f->sample_rates)); + } + if (ost->enc_ctx->channels) { + f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels); + } else if (ost->enc->channel_layouts) { + count = 0; + while (ost->enc->channel_layouts[count]) + count++; + f->channel_layouts = av_mallocz_array(count + 1, sizeof(*f->channel_layouts)); + if (!f->channel_layouts) + exit_program(1); + memcpy(f->channel_layouts, ost->enc->channel_layouts, + (count + 1) * sizeof(*f->channel_layouts)); + } + break; + } + } + + } + /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(oc->filename)) { @@ -1756,11 +2004,10 @@ static int opt_target(void *optctx, const char *opt, const char *arg) int i, j, fr; for (j = 0; j < nb_input_files; j++) { for (i = 0; i < input_files[j]->nb_streams; i++) { - AVCodecContext *c = input_files[j]->ctx->streams[i]->codec; - if (c->codec_type != AVMEDIA_TYPE_VIDEO || - !c->time_base.num) + AVStream *st = input_files[j]->ctx->streams[i]; + if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) continue; - fr = c->time_base.den * 1000 / c->time_base.num; + fr = st->time_base.den * 1000 / st->time_base.num; if (fr == 25000) { norm = PAL; break; @@ -1890,6 +2137,11 @@ static int opt_vstats(void *optctx, const char *opt, const char *arg) time_t today2 = time(NULL); struct tm *today = localtime(&today2); + if (!today) { // maybe tomorrow + av_log(NULL, AV_LOG_FATAL, "Unable to get current time.\n"); + exit_program(1); + } + snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min, today->tm_sec); return opt_vstats_file(NULL, opt, filename); @@ -2043,6 +2295,7 @@ void show_help_default(const char *opt, const char *arg) " -h -- print basic options\n" " -h long -- print more options\n" " -h full -- print all options (including all format and codec specific options, very long)\n" + " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter\n" " See man %s for detailed description of the options.\n" "\n", program_name); @@ -2167,6 +2420,13 @@ int avconv_parse_options(int argc, char **argv) goto fail; } + /* create the complex filtergraphs */ + ret = init_complex_filters(); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n"); + goto fail; + } + /* open output files */ ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file); if (ret < 0) { @@ -2298,6 +2558,8 @@ const OptionDef options[] = { { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(dump_attachment) }, "extract an attachment into a file", "filename" }, + { "loop", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_INPUT | + OPT_OFFSET, { .off = OFFSET(loop) }, "set number of times input stream shall be looped", "loop count" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -2365,7 +2627,18 @@ const OptionDef options[] = { "use HW accelerated decoding", "hwaccel name" }, { "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) }, - "select a device for HW acceleration" "devicename" }, + "select a device for HW acceleration", "devicename" }, + { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, + "select output format used with HW accelerated decoding", "format" }, + + { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, + "show available HW acceleration methods" }, + { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) }, + "automatically insert correct rotate filters" }, + { "hwaccel_lax_profile_check", OPT_BOOL | OPT_EXPERT, { &hwaccel_lax_profile_check}, + "attempt to decode anyway if HW accelerated decoder's supported profiles do not exactly match the stream" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, @@ -2417,9 +2690,17 @@ const OptionDef options[] = { { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) }, "A comma-separated list of bitstream filters", "bitstream_filters" }, + { "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) }, + "maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" }, + /* data codec support */ { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec }, "force data codec ('copy' to copy stream)", "codec" }, +#if CONFIG_VAAPI + { "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device }, + "set VAAPI hardware device (DRM path or X11 display name)", "device" }, +#endif + { NULL, }, }; diff --git a/avconv_qsv.c b/avconv_qsv.c new file mode 100644 index 0000000..723c6e0 --- /dev/null +++ b/avconv_qsv.c @@ -0,0 +1,96 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/dict.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavcodec/qsv.h" + +#include "avconv.h" + +static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) +{ + InputStream *ist = s->opaque; + + return av_hwframe_get_buffer(ist->hw_frames_ctx, frame, 0); +} + +static void qsv_uninit(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + av_buffer_unref(&ist->hw_frames_ctx); +} + +static int qsv_device_init(InputStream *ist) +{ + int err; + + err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, + ist->hwaccel_device, NULL, 0); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, "Error creating a QSV device\n"); + return err; + } + + return 0; +} + +int qsv_init(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + AVHWFramesContext *frames_ctx; + AVQSVFramesContext *frames_hwctx; + int ret; + + if (!hw_device_ctx) { + ret = qsv_device_init(ist); + if (ret < 0) + return ret; + } + + av_buffer_unref(&ist->hw_frames_ctx); + ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); + if (!ist->hw_frames_ctx) + return AVERROR(ENOMEM); + + frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data; + frames_hwctx = frames_ctx->hwctx; + + frames_ctx->width = FFALIGN(s->coded_width, 32); + frames_ctx->height = FFALIGN(s->coded_height, 32); + frames_ctx->format = AV_PIX_FMT_QSV; + frames_ctx->sw_format = s->sw_pix_fmt; + frames_ctx->initial_pool_size = 32; + frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + + ret = av_hwframe_ctx_init(ist->hw_frames_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n"); + return ret; + } + + ist->hwaccel_get_buffer = qsv_get_buffer; + ist->hwaccel_uninit = qsv_uninit; + + return 0; +} diff --git a/avconv_vaapi.c b/avconv_vaapi.c new file mode 100644 index 0000000..ddee72c --- /dev/null +++ b/avconv_vaapi.c @@ -0,0 +1,538 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include + +#include +#if HAVE_VAAPI_X11 +# include +#endif +#if HAVE_VAAPI_DRM +# include +#endif + +#include "libavutil/avassert.h" +#include "libavutil/avconfig.h" +#include "libavutil/buffer.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vaapi.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +#include "libavcodec/vaapi.h" + +#include "avconv.h" + + +static AVClass vaapi_class = { + .class_name = "vaapi", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +#define DEFAULT_SURFACES 20 + +typedef struct VAAPIDecoderContext { + const AVClass *class; + + AVBufferRef *device_ref; + AVHWDeviceContext *device; + AVBufferRef *frames_ref; + AVHWFramesContext *frames; + + VAProfile va_profile; + VAEntrypoint va_entrypoint; + VAConfigID va_config; + VAContextID va_context; + + enum AVPixelFormat decode_format; + int decode_width; + int decode_height; + int decode_surfaces; + + // The output need not have the same format, width and height as the + // decoded frames - the copy for non-direct-mapped access is actually + // a whole vpp instance which can do arbitrary scaling and format + // conversion. + enum AVPixelFormat output_format; + + struct vaapi_context decoder_vaapi_context; +} VAAPIDecoderContext; + + +static int vaapi_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + InputStream *ist = avctx->opaque; + VAAPIDecoderContext *ctx = ist->hwaccel_ctx; + int err; + + err = av_hwframe_get_buffer(ctx->frames_ref, frame, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate decoder surface.\n"); + } else { + av_log(ctx, AV_LOG_DEBUG, "Decoder given surface %#x.\n", + (unsigned int)(uintptr_t)frame->data[3]); + } + return err; +} + +static int vaapi_retrieve_data(AVCodecContext *avctx, AVFrame *input) +{ + InputStream *ist = avctx->opaque; + VAAPIDecoderContext *ctx = ist->hwaccel_ctx; + AVFrame *output = 0; + int err; + + av_assert0(input->format == AV_PIX_FMT_VAAPI); + + if (ctx->output_format == AV_PIX_FMT_VAAPI) { + // Nothing to do. + return 0; + } + + av_log(ctx, AV_LOG_DEBUG, "Retrieve data from surface %#x.\n", + (unsigned int)(uintptr_t)input->data[3]); + + output = av_frame_alloc(); + if (!output) + return AVERROR(ENOMEM); + + output->format = ctx->output_format; + + err = av_hwframe_transfer_data(output, input, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to transfer data to " + "output frame: %d.\n", err); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) { + av_frame_unref(output); + goto fail; + } + + av_frame_unref(input); + av_frame_move_ref(input, output); + av_frame_free(&output); + + return 0; + +fail: + if (output) + av_frame_free(&output); + return err; +} + + +static const struct { + enum AVCodecID codec_id; + int codec_profile; + VAProfile va_profile; +} vaapi_profile_map[] = { +#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v } + MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ), + MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ), + MAP(H263, UNKNOWN, H263Baseline), + MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ), + MAP(MPEG4, MPEG4_ADVANCED_SIMPLE, + MPEG4AdvancedSimple), + MAP(MPEG4, MPEG4_MAIN, MPEG4Main ), + MAP(H264, H264_CONSTRAINED_BASELINE, + H264ConstrainedBaseline), + MAP(H264, H264_BASELINE, H264Baseline), + MAP(H264, H264_MAIN, H264Main ), + MAP(H264, H264_HIGH, H264High ), +#if VA_CHECK_VERSION(0, 37, 0) + MAP(HEVC, HEVC_MAIN, HEVCMain ), +#endif + MAP(WMV3, VC1_SIMPLE, VC1Simple ), + MAP(WMV3, VC1_MAIN, VC1Main ), + MAP(WMV3, VC1_COMPLEX, VC1Advanced ), + MAP(WMV3, VC1_ADVANCED, VC1Advanced ), + MAP(VC1, VC1_SIMPLE, VC1Simple ), + MAP(VC1, VC1_MAIN, VC1Main ), + MAP(VC1, VC1_COMPLEX, VC1Advanced ), + MAP(VC1, VC1_ADVANCED, VC1Advanced ), +#if VA_CHECK_VERSION(0, 35, 0) + MAP(VP8, UNKNOWN, VP8Version0_3 ), +#endif +#if VA_CHECK_VERSION(0, 37, 1) + MAP(VP9, VP9_0, VP9Profile0 ), +#endif +#undef MAP +}; + +static int vaapi_build_decoder_config(VAAPIDecoderContext *ctx, + AVCodecContext *avctx, + int fallback_allowed) +{ + AVVAAPIDeviceContext *hwctx = ctx->device->hwctx; + AVVAAPIHWConfig *hwconfig = NULL; + AVHWFramesConstraints *constraints = NULL; + VAStatus vas; + int err, i, j; + int loglevel = fallback_allowed ? AV_LOG_VERBOSE : AV_LOG_ERROR; + const AVCodecDescriptor *codec_desc; + const AVPixFmtDescriptor *pix_desc; + enum AVPixelFormat pix_fmt; + VAProfile profile, *profile_list = NULL; + int profile_count, exact_match, alt_profile; + + codec_desc = avcodec_descriptor_get(avctx->codec_id); + if (!codec_desc) { + err = AVERROR(EINVAL); + goto fail; + } + + profile_count = vaMaxNumProfiles(hwctx->display); + profile_list = av_malloc(profile_count * sizeof(VAProfile)); + if (!profile_list) { + err = AVERROR(ENOMEM); + goto fail; + } + + vas = vaQueryConfigProfiles(hwctx->display, + profile_list, &profile_count); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, loglevel, "Failed to query profiles: %d (%s).\n", + vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + profile = VAProfileNone; + exact_match = 0; + + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) { + int profile_match = 0; + if (avctx->codec_id != vaapi_profile_map[i].codec_id) + continue; + if (avctx->profile == vaapi_profile_map[i].codec_profile) + profile_match = 1; + profile = vaapi_profile_map[i].va_profile; + for (j = 0; j < profile_count; j++) { + if (profile == profile_list[j]) { + exact_match = profile_match; + break; + } + } + if (j < profile_count) { + if (exact_match) + break; + alt_profile = vaapi_profile_map[i].codec_profile; + } + } + av_freep(&profile_list); + + if (profile == VAProfileNone) { + av_log(ctx, loglevel, "No VAAPI support for codec %s.\n", + codec_desc->name); + err = AVERROR(ENOSYS); + goto fail; + } + if (!exact_match) { + if (fallback_allowed || !hwaccel_lax_profile_check) { + av_log(ctx, loglevel, "No VAAPI support for codec %s " + "profile %d.\n", codec_desc->name, avctx->profile); + if (!fallback_allowed) { + av_log(ctx, AV_LOG_WARNING, "If you want attempt decoding " + "anyway with a possibly-incompatible profile, add " + "the option -hwaccel_lax_profile_check.\n"); + } + err = AVERROR(EINVAL); + goto fail; + } else { + av_log(ctx, AV_LOG_WARNING, "No VAAPI support for codec %s " + "profile %d: trying instead with profile %d.\n", + codec_desc->name, avctx->profile, alt_profile); + av_log(ctx, AV_LOG_WARNING, "This may fail or give " + "incorrect results, depending on your hardware.\n"); + } + } + + ctx->va_profile = profile; + ctx->va_entrypoint = VAEntrypointVLD; + + vas = vaCreateConfig(hwctx->display, ctx->va_profile, + ctx->va_entrypoint, 0, 0, &ctx->va_config); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create decode pipeline " + "configuration: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); + if (!hwconfig) { + err = AVERROR(ENOMEM); + goto fail; + } + hwconfig->config_id = ctx->va_config; + + constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); + if (!constraints) + goto fail; + + // Decide on the decoder target format. + // If the user specified something with -hwaccel_output_format then + // try to use that to minimise conversions later. + ctx->decode_format = AV_PIX_FMT_NONE; + if (ctx->output_format != AV_PIX_FMT_NONE && + ctx->output_format != AV_PIX_FMT_VAAPI) { + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + if (constraints->valid_sw_formats[i] == ctx->decode_format) { + ctx->decode_format = ctx->output_format; + av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (output " + "format).\n", av_get_pix_fmt_name(ctx->decode_format)); + break; + } + } + } + // Otherwise, we would like to try to choose something which matches the + // decoder output, but there isn't enough information available here to + // do so. Assume for now that we are always dealing with YUV 4:2:0, so + // pick a format which does that. + if (ctx->decode_format == AV_PIX_FMT_NONE) { + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + pix_fmt = constraints->valid_sw_formats[i]; + pix_desc = av_pix_fmt_desc_get(pix_fmt); + if (pix_desc->nb_components == 3 && + pix_desc->log2_chroma_w == 1 && + pix_desc->log2_chroma_h == 1) { + ctx->decode_format = pix_fmt; + av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (format " + "matched).\n", av_get_pix_fmt_name(ctx->decode_format)); + break; + } + } + } + // Otherwise pick the first in the list and hope for the best. + if (ctx->decode_format == AV_PIX_FMT_NONE) { + ctx->decode_format = constraints->valid_sw_formats[0]; + av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (first in list).\n", + av_get_pix_fmt_name(ctx->decode_format)); + if (i > 1) { + // There was a choice, and we picked randomly. Warn the user + // that they might want to choose intelligently instead. + av_log(ctx, AV_LOG_WARNING, "Using randomly chosen decode " + "format %s.\n", av_get_pix_fmt_name(ctx->decode_format)); + } + } + + // Ensure the picture size is supported by the hardware. + ctx->decode_width = avctx->coded_width; + ctx->decode_height = avctx->coded_height; + if (ctx->decode_width < constraints->min_width || + ctx->decode_height < constraints->min_height || + ctx->decode_width > constraints->max_width || + ctx->decode_height >constraints->max_height) { + av_log(ctx, AV_LOG_ERROR, "VAAPI hardware does not support image " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->decode_width, ctx->decode_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); + err = AVERROR(EINVAL); + goto fail; + } + + av_hwframe_constraints_free(&constraints); + av_freep(&hwconfig); + + // Decide how many reference frames we need. This might be doable more + // nicely based on the codec and input stream? + ctx->decode_surfaces = DEFAULT_SURFACES; + // For frame-threaded decoding, one additional surfaces is needed for + // each thread. + if (avctx->active_thread_type & FF_THREAD_FRAME) + ctx->decode_surfaces += avctx->thread_count; + + return 0; + +fail: + av_hwframe_constraints_free(&constraints); + av_freep(&hwconfig); + vaDestroyConfig(hwctx->display, ctx->va_config); + av_freep(&profile_list); + return err; +} + +static void vaapi_decode_uninit(AVCodecContext *avctx) +{ + InputStream *ist = avctx->opaque; + VAAPIDecoderContext *ctx = ist->hwaccel_ctx; + + if (ctx) { + AVVAAPIDeviceContext *hwctx = ctx->device->hwctx; + + if (ctx->va_context != VA_INVALID_ID) { + vaDestroyContext(hwctx->display, ctx->va_context); + ctx->va_context = VA_INVALID_ID; + } + if (ctx->va_config != VA_INVALID_ID) { + vaDestroyConfig(hwctx->display, ctx->va_config); + ctx->va_config = VA_INVALID_ID; + } + + av_buffer_unref(&ctx->frames_ref); + av_buffer_unref(&ctx->device_ref); + av_free(ctx); + } + + av_buffer_unref(&ist->hw_frames_ctx); + + ist->hwaccel_ctx = 0; + ist->hwaccel_uninit = 0; + ist->hwaccel_get_buffer = 0; + ist->hwaccel_retrieve_data = 0; +} + +int vaapi_decode_init(AVCodecContext *avctx) +{ + InputStream *ist = avctx->opaque; + AVVAAPIDeviceContext *hwctx; + AVVAAPIFramesContext *avfc; + VAAPIDecoderContext *ctx; + VAStatus vas; + int err; + int loglevel = (ist->hwaccel_id != HWACCEL_VAAPI ? AV_LOG_VERBOSE + : AV_LOG_ERROR); + + if (ist->hwaccel_ctx) + vaapi_decode_uninit(avctx); + + // We have -hwaccel without -vaapi_device, so just initialise here with + // the device passed as -hwaccel_device (if -vaapi_device was passed, it + // will always have been called before now). + if (!hw_device_ctx) { + err = vaapi_device_init(ist->hwaccel_device); + if (err < 0) + return err; + } + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return AVERROR(ENOMEM); + ctx->class = &vaapi_class; + + ctx->device_ref = av_buffer_ref(hw_device_ctx); + ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; + + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + + hwctx = ctx->device->hwctx; + + ctx->output_format = ist->hwaccel_output_format; + + err = vaapi_build_decoder_config(ctx, avctx, + ist->hwaccel_id != HWACCEL_VAAPI); + if (err < 0) { + av_log(ctx, loglevel, "No supported configuration for this codec."); + goto fail; + } + + avctx->pix_fmt = ctx->output_format; + + ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); + if (!ctx->frames_ref) { + av_log(ctx, loglevel, "Failed to create VAAPI frame context.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data; + + ctx->frames->format = AV_PIX_FMT_VAAPI; + ctx->frames->sw_format = ctx->decode_format; + ctx->frames->width = ctx->decode_width; + ctx->frames->height = ctx->decode_height; + ctx->frames->initial_pool_size = ctx->decode_surfaces; + + err = av_hwframe_ctx_init(ctx->frames_ref); + if (err < 0) { + av_log(ctx, loglevel, "Failed to initialise VAAPI frame " + "context: %d\n", err); + goto fail; + } + + avfc = ctx->frames->hwctx; + + vas = vaCreateContext(hwctx->display, ctx->va_config, + ctx->decode_width, ctx->decode_height, + VA_PROGRESSIVE, + avfc->surface_ids, avfc->nb_surfaces, + &ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create decode pipeline " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EINVAL); + goto fail; + } + + av_log(ctx, AV_LOG_DEBUG, "VAAPI decoder (re)init complete.\n"); + + // We would like to set this on the AVCodecContext for use by whoever gets + // the frames from the decoder, but unfortunately the AVCodecContext we + // have here need not be the "real" one (H.264 makes many copies for + // threading purposes). To avoid the problem, we instead store it in the + // InputStream and propagate it from there. + ist->hw_frames_ctx = av_buffer_ref(ctx->frames_ref); + if (!ist->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } + + ist->hwaccel_ctx = ctx; + ist->hwaccel_uninit = vaapi_decode_uninit; + ist->hwaccel_get_buffer = vaapi_get_buffer; + ist->hwaccel_retrieve_data = vaapi_retrieve_data; + + ctx->decoder_vaapi_context.display = hwctx->display; + ctx->decoder_vaapi_context.config_id = ctx->va_config; + ctx->decoder_vaapi_context.context_id = ctx->va_context; + avctx->hwaccel_context = &ctx->decoder_vaapi_context; + + return 0; + +fail: + vaapi_decode_uninit(avctx); + return err; +} + +static AVClass *vaapi_log = &vaapi_class; + +av_cold int vaapi_device_init(const char *device) +{ + int err; + + err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, + device, NULL, 0); + if (err < 0) { + av_log(&vaapi_log, AV_LOG_ERROR, "Failed to create a VAAPI device\n"); + return err; + } + + return 0; +} diff --git a/avconv_vda.c b/avconv_vda.c index 40f87c4..d86076e 100644 --- a/avconv_vda.c +++ b/avconv_vda.c @@ -76,6 +76,8 @@ static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame) data, linesize, vda->tmp_frame->format, frame->width, frame->height); + CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); + ret = av_frame_copy_props(vda->tmp_frame, frame); if (ret < 0) return ret; diff --git a/avconv_vdpau.c b/avconv_vdpau.c index 820678e..5fedcee 100644 --- a/avconv_vdpau.c +++ b/avconv_vdpau.c @@ -18,43 +18,19 @@ #include -#include -#include - -#include - #include "avconv.h" #include "libavcodec/vdpau.h" -#include "libavutil/avassert.h" #include "libavutil/buffer.h" #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vdpau.h" #include "libavutil/pixfmt.h" typedef struct VDPAUContext { - Display *dpy; - - VdpDevice device; - VdpDecoder decoder; - VdpGetProcAddress *get_proc_address; - - VdpGetErrorString *get_error_string; - VdpGetInformationString *get_information_string; - VdpDeviceDestroy *device_destroy; - VdpDecoderCreate *decoder_create; - VdpDecoderDestroy *decoder_destroy; - VdpDecoderRender *decoder_render; - VdpVideoSurfaceCreate *video_surface_create; - VdpVideoSurfaceDestroy *video_surface_destroy; - VdpVideoSurfaceGetBitsYCbCr *video_surface_get_bits; - VdpVideoSurfaceGetParameters *video_surface_get_parameters; - VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *video_surface_query; - + AVBufferRef *hw_frames_ctx; AVFrame *tmp_frame; - - enum AVPixelFormat pix_fmt; - VdpYCbCrFormat vdpau_format; } VDPAUContext; static void vdpau_uninit(AVCodecContext *s) @@ -66,135 +42,54 @@ static void vdpau_uninit(AVCodecContext *s) ist->hwaccel_get_buffer = NULL; ist->hwaccel_retrieve_data = NULL; - if (ctx->decoder_destroy) - ctx->decoder_destroy(ctx->decoder); - - if (ctx->device_destroy) - ctx->device_destroy(ctx->device); - - if (ctx->dpy) - XCloseDisplay(ctx->dpy); - + av_buffer_unref(&ctx->hw_frames_ctx); av_frame_free(&ctx->tmp_frame); av_freep(&ist->hwaccel_ctx); av_freep(&s->hwaccel_context); } -static void vdpau_release_buffer(void *opaque, uint8_t *data) -{ - VdpVideoSurface surface = *(VdpVideoSurface*)data; - VDPAUContext *ctx = opaque; - - ctx->video_surface_destroy(surface); - av_freep(&data); -} - static int vdpau_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) { InputStream *ist = s->opaque; VDPAUContext *ctx = ist->hwaccel_ctx; - VdpVideoSurface *surface; - VdpStatus err; - - av_assert0(frame->format == AV_PIX_FMT_VDPAU); - - surface = av_malloc(sizeof(*surface)); - if (!surface) - return AVERROR(ENOMEM); - frame->buf[0] = av_buffer_create((uint8_t*)surface, sizeof(*surface), - vdpau_release_buffer, ctx, - AV_BUFFER_FLAG_READONLY); - if (!frame->buf[0]) { - av_freep(&surface); - return AVERROR(ENOMEM); - } - - // properly we should keep a pool of surfaces instead of creating - // them anew for each frame, but since we don't care about speed - // much in this code, we don't bother - err = ctx->video_surface_create(ctx->device, VDP_CHROMA_TYPE_420, - frame->width, frame->height, surface); - if (err != VDP_STATUS_OK) { - av_log(NULL, AV_LOG_ERROR, "Error allocating a VDPAU video surface: %s\n", - ctx->get_error_string(err)); - av_buffer_unref(&frame->buf[0]); - return AVERROR_UNKNOWN; - } - - frame->data[3] = (uint8_t*)(uintptr_t)*surface; - - return 0; + return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0); } static int vdpau_retrieve_data(AVCodecContext *s, AVFrame *frame) { - VdpVideoSurface surface = (VdpVideoSurface)(uintptr_t)frame->data[3]; InputStream *ist = s->opaque; VDPAUContext *ctx = ist->hwaccel_ctx; - VdpStatus err; - int ret, chroma_type; - - err = ctx->video_surface_get_parameters(surface, &chroma_type, - &ctx->tmp_frame->width, - &ctx->tmp_frame->height); - if (err != VDP_STATUS_OK) { - av_log(NULL, AV_LOG_ERROR, "Error getting surface parameters: %s\n", - ctx->get_error_string(err)); - return AVERROR_UNKNOWN; - } - ctx->tmp_frame->format = ctx->pix_fmt; + int ret; - ret = av_frame_get_buffer(ctx->tmp_frame, 32); + ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); if (ret < 0) return ret; - ctx->tmp_frame->width = frame->width; - ctx->tmp_frame->height = frame->height; - - err = ctx->video_surface_get_bits(surface, ctx->vdpau_format, - (void * const *)ctx->tmp_frame->data, - ctx->tmp_frame->linesize); - if (err != VDP_STATUS_OK) { - av_log(NULL, AV_LOG_ERROR, "Error retrieving frame data from VDPAU: %s\n", - ctx->get_error_string(err)); - ret = AVERROR_UNKNOWN; - goto fail; - } - - if (ctx->vdpau_format == VDP_YCBCR_FORMAT_YV12) - FFSWAP(uint8_t*, ctx->tmp_frame->data[1], ctx->tmp_frame->data[2]); - ret = av_frame_copy_props(ctx->tmp_frame, frame); - if (ret < 0) - goto fail; + if (ret < 0) { + av_frame_unref(ctx->tmp_frame); + return ret; + } av_frame_unref(frame); av_frame_move_ref(frame, ctx->tmp_frame); - return 0; -fail: - av_frame_unref(ctx->tmp_frame); - return ret; + return 0; } -static const int vdpau_formats[][2] = { - { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV420P }, - { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV12 }, - { VDP_YCBCR_FORMAT_YUYV, AV_PIX_FMT_YUYV422 }, - { VDP_YCBCR_FORMAT_UYVY, AV_PIX_FMT_UYVY422 }, -}; - static int vdpau_alloc(AVCodecContext *s) { InputStream *ist = s->opaque; int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - AVVDPAUContext *vdpau_ctx; VDPAUContext *ctx; - const char *display, *vendor; - VdpStatus err; - int i; + int ret; + + AVBufferRef *device_ref = NULL; + AVHWDeviceContext *device_ctx; + AVVDPAUDeviceContext *device_hwctx; + AVHWFramesContext *frames_ctx; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) @@ -209,84 +104,40 @@ static int vdpau_alloc(AVCodecContext *s) if (!ctx->tmp_frame) goto fail; - ctx->dpy = XOpenDisplay(ist->hwaccel_device); - if (!ctx->dpy) { - av_log(NULL, loglevel, "Cannot open the X11 display %s.\n", - XDisplayName(ist->hwaccel_device)); + ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_VDPAU, + ist->hwaccel_device, NULL, 0); + if (ret < 0) goto fail; - } - display = XDisplayString(ctx->dpy); + device_ctx = (AVHWDeviceContext*)device_ref->data; + device_hwctx = device_ctx->hwctx; - err = vdp_device_create_x11(ctx->dpy, XDefaultScreen(ctx->dpy), &ctx->device, - &ctx->get_proc_address); - if (err != VDP_STATUS_OK) { - av_log(NULL, loglevel, "VDPAU device creation on X11 display %s failed.\n", - display); + ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); + if (!ctx->hw_frames_ctx) goto fail; - } + av_buffer_unref(&device_ref); -#define GET_CALLBACK(id, result) \ -do { \ - void *tmp; \ - err = ctx->get_proc_address(ctx->device, id, &tmp); \ - if (err != VDP_STATUS_OK) { \ - av_log(NULL, loglevel, "Error getting the " #id " callback.\n"); \ - goto fail; \ - } \ - ctx->result = tmp; \ -} while (0) - - GET_CALLBACK(VDP_FUNC_ID_GET_ERROR_STRING, get_error_string); - GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string); - GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, device_destroy); - GET_CALLBACK(VDP_FUNC_ID_DECODER_CREATE, decoder_create); - GET_CALLBACK(VDP_FUNC_ID_DECODER_DESTROY, decoder_destroy); - GET_CALLBACK(VDP_FUNC_ID_DECODER_RENDER, decoder_render); - GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_CREATE, video_surface_create); - GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, video_surface_destroy); - GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, video_surface_get_bits); - GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, video_surface_get_parameters); - GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - video_surface_query); - - for (i = 0; i < FF_ARRAY_ELEMS(vdpau_formats); i++) { - VdpBool supported; - err = ctx->video_surface_query(ctx->device, VDP_CHROMA_TYPE_420, - vdpau_formats[i][0], &supported); - if (err != VDP_STATUS_OK) { - av_log(NULL, loglevel, - "Error querying VDPAU surface capabilities: %s\n", - ctx->get_error_string(err)); - goto fail; - } - if (supported) - break; - } - if (i == FF_ARRAY_ELEMS(vdpau_formats)) { - av_log(NULL, loglevel, - "No supported VDPAU format for retrieving the data.\n"); - return AVERROR(EINVAL); - } - ctx->vdpau_format = vdpau_formats[i][0]; - ctx->pix_fmt = vdpau_formats[i][1]; + frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; + frames_ctx->format = AV_PIX_FMT_VDPAU; + frames_ctx->sw_format = s->sw_pix_fmt; + frames_ctx->width = s->coded_width; + frames_ctx->height = s->coded_height; - vdpau_ctx = av_vdpau_alloc_context(); - if (!vdpau_ctx) + ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); + if (ret < 0) goto fail; - vdpau_ctx->render = ctx->decoder_render; - s->hwaccel_context = vdpau_ctx; + if (av_vdpau_bind_context(s, device_hwctx->device, device_hwctx->get_proc_address, 0)) + goto fail; - ctx->get_information_string(&vendor); - av_log(NULL, AV_LOG_VERBOSE, "Using VDPAU -- %s -- on X11 display %s, " - "to decode input stream #%d:%d.\n", vendor, - display, ist->file_index, ist->st->index); + av_log(NULL, AV_LOG_VERBOSE, "Using VDPAU to decode input stream #%d:%d.\n", + ist->file_index, ist->st->index); return 0; fail: av_log(NULL, loglevel, "VDPAU init failed for stream #%d:%d.\n", ist->file_index, ist->st->index); + av_buffer_unref(&device_ref); vdpau_uninit(s); return AVERROR(EINVAL); } @@ -294,39 +145,12 @@ fail: int vdpau_init(AVCodecContext *s) { InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - AVVDPAUContext *vdpau_ctx; - VDPAUContext *ctx; - VdpStatus err; - int profile, ret; if (!ist->hwaccel_ctx) { - ret = vdpau_alloc(s); + int ret = vdpau_alloc(s); if (ret < 0) return ret; } - ctx = ist->hwaccel_ctx; - vdpau_ctx = s->hwaccel_context; - - ret = av_vdpau_get_profile(s, &profile); - if (ret < 0) { - av_log(NULL, loglevel, "No known VDPAU decoder profile for this stream.\n"); - return AVERROR(EINVAL); - } - - if (ctx->decoder) - ctx->decoder_destroy(ctx->decoder); - - err = ctx->decoder_create(ctx->device, profile, - s->coded_width, s->coded_height, - 16, &ctx->decoder); - if (err != VDP_STATUS_OK) { - av_log(NULL, loglevel, "Error creating the VDPAU decoder: %s\n", - ctx->get_error_string(err)); - return AVERROR_UNKNOWN; - } - - vdpau_ctx->decoder = ctx->decoder; ist->hwaccel_get_buffer = vdpau_get_buffer; ist->hwaccel_retrieve_data = vdpau_retrieve_data; diff --git a/avplay.c b/avplay.c index 816733f..3bbc2c1 100644 --- a/avplay.c +++ b/avplay.c @@ -27,6 +27,7 @@ #include "libavutil/avstring.h" #include "libavutil/colorspace.h" +#include "libavutil/display.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" @@ -36,16 +37,13 @@ #include "libavutil/time.h" #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" -#include "libswscale/swscale.h" #include "libavresample/avresample.h" #include "libavutil/opt.h" #include "libavcodec/avfft.h" -#if CONFIG_AVFILTER -# include "libavfilter/avfilter.h" -# include "libavfilter/buffersink.h" -# include "libavfilter/buffersrc.h" -#endif +#include "libavfilter/avfilter.h" +#include "libavfilter/buffersink.h" +#include "libavfilter/buffersrc.h" #include "cmdutils.h" @@ -101,7 +99,7 @@ typedef struct PacketQueue { typedef struct VideoPicture { double pts; // presentation timestamp for this picture - double target_clock; // av_gettime() time at which this should be displayed ideally + double target_clock; // av_gettime_relative() time at which this should be displayed ideally int64_t pos; // byte position in file SDL_Overlay *bmp; int width, height; /* source height & width */ @@ -123,7 +121,7 @@ enum { AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */ }; -typedef struct VideoState { +typedef struct PlayerState { SDL_Thread *parse_tid; SDL_Thread *video_tid; SDL_Thread *refresh_tid; @@ -151,6 +149,7 @@ typedef struct VideoState { double audio_diff_threshold; int audio_diff_avg_count; AVStream *audio_st; + AVCodecContext *audio_dec; PacketQueue audioq; int audio_hw_buf_size; uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE]; @@ -183,6 +182,7 @@ typedef struct VideoState { int subtitle_stream; int subtitle_stream_changed; AVStream *subtitle_st; + AVCodecContext *subtitle_dec; PacketQueue subtitleq; SubPicture subpq[SUBPICTURE_QUEUE_SIZE]; int subpq_size, subpq_rindex, subpq_windex; @@ -195,17 +195,15 @@ typedef struct VideoState { double video_clock; // pts of last decoded frame / predicted pts of next decoded frame int video_stream; AVStream *video_st; + AVCodecContext *video_dec; PacketQueue videoq; double video_current_pts; // current displayed pts (different from video_clock if frame fifos are used) - double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts + double video_current_pts_drift; // video_current_pts - time (av_gettime_relative) at which we updated video_current_pts - used to have running video pts int64_t video_current_pos; // current displayed file pos VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; int pictq_size, pictq_rindex, pictq_windex; SDL_mutex *pictq_mutex; SDL_cond *pictq_cond; -#if !CONFIG_AVFILTER - struct SwsContext *img_convert_ctx; -#endif // QETimer *video_timer; char filename[1024]; @@ -213,15 +211,17 @@ typedef struct VideoState { PtsCorrectionContext pts_ctx; -#if CONFIG_AVFILTER AVFilterContext *in_video_filter; // the first filter in the video chain AVFilterContext *out_video_filter; // the last filter in the video chain -#endif + SDL_mutex *video_filter_mutex; float skip_frames; float skip_frames_index; int refresh; -} VideoState; + + SpecifierOpt *codec_names; + int nb_codec_names; +} PlayerState; /* options specified by the user */ static AVInputFormat *file_iformat; @@ -254,7 +254,7 @@ static enum AVDiscard skip_idct = AVDISCARD_DEFAULT; static enum AVDiscard skip_loop_filter = AVDISCARD_DEFAULT; static int error_concealment = 3; static int decoder_reorder_pts = -1; -static int autoexit; +static int noautoexit; static int exit_on_keydown; static int exit_on_mousedown; static int loop = 1; @@ -262,13 +262,13 @@ static int framedrop = 1; static int infinite_buffer = 0; static int rdftspeed = 20; -#if CONFIG_AVFILTER static char *vfilters = NULL; -#endif +static int autorotate = 1; /* current context */ static int is_full_screen; -static VideoState *cur_stream; +static PlayerState player_state; +static PlayerState *player = &player_state; static int64_t audio_callback_time; static AVPacket flush_pkt; @@ -297,7 +297,7 @@ static void packet_queue_flush(PacketQueue *q) SDL_LockMutex(q->mutex); for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { pkt1 = pkt->next; - av_free_packet(&pkt->pkt); + av_packet_unref(&pkt->pkt); av_freep(&pkt); } q->last_pkt = NULL; @@ -318,10 +318,6 @@ 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; @@ -433,7 +429,8 @@ static inline void fill_rectangle(SDL_Surface *screen, #define BPP 1 -static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh) +static void blend_subrect(uint8_t *dst[4], uint16_t dst_linesize[4], + const AVSubtitleRect *rect, int imgw, int imgh) { int wrap, wrap3, width2, skip2; int y, u, v, a, u1, v1, a1, w, h; @@ -446,16 +443,17 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, dsth = av_clip(rect->h, 0, imgh); dstx = av_clip(rect->x, 0, imgw - dstw); dsty = av_clip(rect->y, 0, imgh - dsth); - lum = dst->data[0] + dsty * dst->linesize[0]; - cb = dst->data[1] + (dsty >> 1) * dst->linesize[1]; - cr = dst->data[2] + (dsty >> 1) * dst->linesize[2]; + /* sdl has U and V inverted */ + lum = dst[0] + dsty * dst_linesize[0]; + cb = dst[2] + (dsty >> 1) * dst_linesize[2]; + cr = dst[1] + (dsty >> 1) * dst_linesize[1]; width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1); skip2 = dstx >> 1; - wrap = dst->linesize[0]; - wrap3 = rect->pict.linesize[0]; - p = rect->pict.data[0]; - pal = (const uint32_t *)rect->pict.data[1]; /* Now in YCrCb! */ + wrap = dst_linesize[0]; + wrap3 = rect->linesize[0]; + p = rect->data[0]; + pal = (const uint32_t *)rect->data[1]; /* Now in YCrCb! */ if (dsty & 1) { lum += dstx; @@ -501,8 +499,8 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, } p += wrap3 - dstw * BPP; lum += wrap - dstw - dstx; - cb += dst->linesize[1] - width2 - skip2; - cr += dst->linesize[2] - width2 - skip2; + cb += dst_linesize[2] - width2 - skip2; + cr += dst_linesize[1] - width2 - skip2; } for (h = dsth - (dsty & 1); h >= 2; h -= 2) { lum += dstx; @@ -586,8 +584,8 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, } p += wrap3 + (wrap3 - dstw * BPP); lum += wrap + (wrap - dstw - dstx); - cb += dst->linesize[1] - width2 - skip2; - cr += dst->linesize[2] - width2 - skip2; + cb += dst_linesize[2] - width2 - skip2; + cr += dst_linesize[1] - width2 - skip2; } /* handle odd height */ if (h) { @@ -638,11 +636,10 @@ static void free_subpicture(SubPicture *sp) avsubtitle_free(&sp->sub); } -static void video_image_display(VideoState *is) +static void video_image_display(PlayerState *is) { VideoPicture *vp; SubPicture *sp; - AVPicture pict; float aspect_ratio; int width, height, x, y; SDL_Rect rect; @@ -650,21 +647,10 @@ static void video_image_display(VideoState *is) vp = &is->pictq[is->pictq_rindex]; if (vp->bmp) { -#if CONFIG_AVFILTER if (!vp->sar.num) aspect_ratio = 0; else aspect_ratio = av_q2d(vp->sar); -#else - - /* XXX: use variable in the frame */ - if (is->video_st->sample_aspect_ratio.num) - aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio); - else if (is->video_st->codec->sample_aspect_ratio.num) - aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio); - else - aspect_ratio = 0; -#endif if (aspect_ratio <= 0.0) aspect_ratio = 1.0; aspect_ratio *= (float)vp->width / (float)vp->height; @@ -679,17 +665,9 @@ static void video_image_display(VideoState *is) { 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], - vp->bmp->w, vp->bmp->h); + blend_subrect(vp->bmp->pixels, vp->bmp->pitches, + sp->sub.rects[i], vp->bmp->w, vp->bmp->h); SDL_UnlockYUVOverlay (vp->bmp); } @@ -717,7 +695,7 @@ static void video_image_display(VideoState *is) /* 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) +static int audio_write_get_buf_size(PlayerState *is) { return is->audio_buf_size - is->audio_buf_index; } @@ -731,7 +709,7 @@ static inline int compute_mod(int a, int b) return a + b; } -static void video_audio_display(VideoState *s) +static void video_audio_display(PlayerState *s) { int i, i_start, x, y1, y, ys, delay, n, nb_display_channels; int ch, channels, h, h2, bgcolor, fgcolor; @@ -754,7 +732,7 @@ static void video_audio_display(VideoState *s) /* 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; + time_diff = av_gettime_relative() - audio_callback_time; delay -= (time_diff * s->sdl_sample_rate) / 1000000; } @@ -871,7 +849,7 @@ static void video_audio_display(VideoState *s) } } -static int video_open(VideoState *is) +static int video_open(PlayerState *is) { int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; int w,h; @@ -885,15 +863,9 @@ static int video_open(VideoState *is) } else if (!is_full_screen && screen_width) { w = screen_width; h = screen_height; -#if CONFIG_AVFILTER } else if (is->out_video_filter && is->out_video_filter->inputs[0]) { w = is->out_video_filter->inputs[0]->w; h = is->out_video_filter->inputs[0]->h; -#else - } else if (is->video_st && is->video_st->codec->width) { - w = is->video_st->codec->width; - h = is->video_st->codec->height; -#endif } else { w = 640; h = 480; @@ -923,10 +895,10 @@ static int video_open(VideoState *is) } /* display the current picture, if any */ -static void video_display(VideoState *is) +static void video_display(PlayerState *is) { if (!screen) - video_open(cur_stream); + video_open(player); if (is->audio_st && is->show_audio) video_audio_display(is); else if (is->video_st) @@ -935,7 +907,7 @@ static void video_display(VideoState *is) static int refresh_thread(void *opaque) { - VideoState *is= opaque; + PlayerState *is= opaque; while (!is->abort_request) { SDL_Event event; event.type = FF_REFRESH_EVENT; @@ -950,7 +922,7 @@ static int refresh_thread(void *opaque) } /* get the current audio clock value */ -static double get_audio_clock(VideoState *is) +static double get_audio_clock(PlayerState *is) { double pts; int hw_buf_size, bytes_per_sec; @@ -967,25 +939,25 @@ static double get_audio_clock(VideoState *is) } /* get the current video clock value */ -static double get_video_clock(VideoState *is) +static double get_video_clock(PlayerState *is) { if (is->paused) { return is->video_current_pts; } else { - return is->video_current_pts_drift + av_gettime() / 1000000.0; + return is->video_current_pts_drift + av_gettime_relative() / 1000000.0; } } /* get the current external clock value */ -static double get_external_clock(VideoState *is) +static double get_external_clock(PlayerState *is) { int64_t ti; - ti = av_gettime(); + ti = av_gettime_relative(); return is->external_clock + ((ti - is->external_clock_time) * 1e-6); } /* get the current master clock value */ -static double get_master_clock(VideoState *is) +static double get_master_clock(PlayerState *is) { double val; @@ -1006,7 +978,7 @@ static double get_master_clock(VideoState *is) } /* seek in the stream */ -static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes) +static void stream_seek(PlayerState *is, int64_t pos, int64_t rel, int seek_by_bytes) { if (!is->seek_req) { is->seek_pos = pos; @@ -1019,21 +991,21 @@ static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_by } /* pause or resume the video */ -static void stream_pause(VideoState *is) +static void stream_pause(PlayerState *is) { if (is->paused) { - is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts; + is->frame_timer += av_gettime_relative() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts; if (is->read_pause_return != AVERROR(ENOSYS)) { - is->video_current_pts = is->video_current_pts_drift + av_gettime() / 1000000.0; + is->video_current_pts = is->video_current_pts_drift + av_gettime_relative() / 1000000.0; } - is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0; + is->video_current_pts_drift = is->video_current_pts - av_gettime_relative() / 1000000.0; } is->paused = !is->paused; } -static double compute_target_time(double frame_current_pts, VideoState *is) +static double compute_target_time(double frame_current_pts, PlayerState *is) { - double delay, sync_threshold, diff; + double delay, sync_threshold, diff = 0; /* compute nominal delay */ delay = frame_current_pts - is->frame_last_pts; @@ -1065,7 +1037,7 @@ static double compute_target_time(double frame_current_pts, VideoState *is) } is->frame_timer += delay; - av_dlog(NULL, "video: delay=%0.3f pts=%0.3f A-V=%f\n", + av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f pts=%0.3f A-V=%f\n", delay, frame_current_pts, -diff); return is->frame_timer; @@ -1074,7 +1046,7 @@ static double compute_target_time(double frame_current_pts, VideoState *is) /* called to display each frame */ static void video_refresh_timer(void *opaque) { - VideoState *is = opaque; + PlayerState *is = opaque; VideoPicture *vp; SubPicture *sp, *sp2; @@ -1084,7 +1056,7 @@ retry: if (is->pictq_size == 0) { // nothing to do, no picture to display in the que } else { - double time = av_gettime() / 1000000.0; + double time = av_gettime_relative() / 1000000.0; double next_target; /* dequeue the picture */ vp = &is->pictq[is->pictq_rindex]; @@ -1190,7 +1162,7 @@ retry: int aqsize, vqsize, sqsize; double av_diff; - cur_time = av_gettime(); + cur_time = av_gettime_relative(); if (!last_time || (cur_time - last_time) >= 30000) { aqsize = 0; vqsize = 0; @@ -1213,7 +1185,7 @@ retry: } } -static void stream_close(VideoState *is) +static void player_close(PlayerState *is) { VideoPicture *vp; int i; @@ -1230,22 +1202,18 @@ static void stream_close(VideoState *is) vp->bmp = NULL; } } + SDL_DestroyMutex(is->video_filter_mutex); SDL_DestroyMutex(is->pictq_mutex); SDL_DestroyCond(is->pictq_cond); SDL_DestroyMutex(is->subpq_mutex); SDL_DestroyCond(is->subpq_cond); -#if !CONFIG_AVFILTER - if (is->img_convert_ctx) - sws_freeContext(is->img_convert_ctx); -#endif - av_free(is); } static void do_exit(void) { - if (cur_stream) { - stream_close(cur_stream); - cur_stream = NULL; + if (player) { + player_close(player); + player = NULL; } uninit_opts(); avformat_network_deinit(); @@ -1260,7 +1228,7 @@ static void do_exit(void) potential locking problems */ static void alloc_picture(void *opaque) { - VideoState *is = opaque; + PlayerState *is = opaque; VideoPicture *vp; vp = &is->pictq[is->pictq_windex]; @@ -1268,15 +1236,9 @@ static void alloc_picture(void *opaque) if (vp->bmp) SDL_FreeYUVOverlay(vp->bmp); -#if CONFIG_AVFILTER vp->width = is->out_video_filter->inputs[0]->w; vp->height = is->out_video_filter->inputs[0]->h; vp->pix_fmt = is->out_video_filter->inputs[0]->format; -#else - vp->width = is->video_st->codec->width; - vp->height = is->video_st->codec->height; - vp->pix_fmt = is->video_st->codec->pix_fmt; -#endif vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height, SDL_YV12_OVERLAY, @@ -1298,14 +1260,10 @@ static void alloc_picture(void *opaque) /* The 'pts' parameter is the dts of the packet / pts of the frame and * guessed if not known. */ -static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos) +static int queue_picture(PlayerState *is, AVFrame *src_frame, double pts, int64_t pos) { VideoPicture *vp; -#if CONFIG_AVFILTER - AVPicture pict_src; -#else - int dst_pix_fmt = AV_PIX_FMT_YUV420P; -#endif + /* wait until we have space to put a new picture */ SDL_LockMutex(is->pictq_mutex); @@ -1327,13 +1285,8 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t /* alloc or resize hardware picture buffer */ if (!vp->bmp || vp->reallocate || -#if CONFIG_AVFILTER vp->width != is->out_video_filter->inputs[0]->w || vp->height != is->out_video_filter->inputs[0]->h) { -#else - vp->width != is->video_st->codec->width || - vp->height != is->video_st->codec->height) { -#endif SDL_Event event; vp->allocated = 0; @@ -1358,43 +1311,24 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t /* if the frame is not skipped, then display it */ if (vp->bmp) { - AVPicture pict = { { 0 } }; + uint8_t *data[4]; + int linesize[4]; /* get a pointer on the bitmap */ 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]; + data[0] = vp->bmp->pixels[0]; + data[1] = vp->bmp->pixels[2]; + data[2] = vp->bmp->pixels[1]; -#if CONFIG_AVFILTER - pict_src.data[0] = src_frame->data[0]; - pict_src.data[1] = src_frame->data[1]; - pict_src.data[2] = src_frame->data[2]; - - pict_src.linesize[0] = src_frame->linesize[0]; - pict_src.linesize[1] = src_frame->linesize[1]; - pict_src.linesize[2] = src_frame->linesize[2]; + linesize[0] = vp->bmp->pitches[0]; + linesize[1] = vp->bmp->pitches[2]; + linesize[2] = vp->bmp->pitches[1]; // FIXME use direct rendering - av_picture_copy(&pict, &pict_src, - vp->pix_fmt, vp->width, vp->height); -#else - av_opt_get_int(sws_opts, "sws_flags", 0, &sws_flags); - is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx, - vp->width, vp->height, vp->pix_fmt, vp->width, vp->height, - dst_pix_fmt, sws_flags, NULL, NULL, NULL); - if (!is->img_convert_ctx) { - fprintf(stderr, "Cannot initialize the conversion context\n"); - exit(1); - } - sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize, - 0, vp->height, pict.data, pict.linesize); -#endif + av_image_copy(data, linesize, src_frame->data, src_frame->linesize, + vp->pix_fmt, vp->width, vp->height); + /* update the bitmap content */ SDL_UnlockYUVOverlay(vp->bmp); @@ -1415,7 +1349,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t /* Compute the exact PTS for the picture if it is omitted in the stream. * The 'pts1' parameter is the dts of the packet / pts of the frame. */ -static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos) +static int output_picture2(PlayerState *is, AVFrame *src_frame, double pts1, int64_t pos) { double frame_delay, pts; int ret; @@ -1429,8 +1363,8 @@ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int6 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 + frame_delay = av_q2d(is->video_dec->time_base); + /* For MPEG-2, 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; @@ -1440,7 +1374,7 @@ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int6 return ret; } -static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt) +static int get_video_frame(PlayerState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt) { int got_picture, i; @@ -1448,7 +1382,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke return -1; if (pkt->data == flush_pkt.data) { - avcodec_flush_buffers(is->video_st->codec); + avcodec_flush_buffers(is->video_dec); SDL_LockMutex(is->pictq_mutex); // Make sure there are no long delay timers (ideally we should just flush the que but thats harder) @@ -1464,19 +1398,19 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke init_pts_correction(&is->pts_ctx); is->frame_last_pts = AV_NOPTS_VALUE; is->frame_last_delay = 0; - is->frame_timer = (double)av_gettime() / 1000000.0; + is->frame_timer = (double)av_gettime_relative() / 1000000.0; is->skip_frames = 1; is->skip_frames_index = 0; return 0; } - avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt); + avcodec_decode_video2(is->video_dec, frame, &got_picture, pkt); if (got_picture) { if (decoder_reorder_pts == -1) { - *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts); + *pts = guess_correct_pts(&is->pts_ctx, frame->pts, frame->pkt_dts); } else if (decoder_reorder_pts) { - *pts = frame->pkt_pts; + *pts = frame->pts; } else { *pts = frame->pkt_dts; } @@ -1498,14 +1432,13 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke return 0; } -#if CONFIG_AVFILTER -static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters) +static int configure_video_filters(AVFilterGraph *graph, PlayerState *is, const char *vfilters) { char sws_flags_str[128]; char buffersrc_args[256]; int ret; - AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format; - AVCodecContext *codec = is->video_st->codec; + AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter; + AVCodecContext *codec = is->video_dec; snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags); graph->scale_sws_opts = av_strdup(sws_flags_str); @@ -1526,13 +1459,43 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c "out", NULL, NULL, graph)) < 0) return ret; - if ((ret = avfilter_graph_create_filter(&filt_format, - avfilter_get_by_name("format"), - "format", "yuv420p", NULL, graph)) < 0) - return ret; - if ((ret = avfilter_link(filt_format, 0, filt_out, 0)) < 0) - return ret; - + last_filter = filt_out; + +/* Note: this macro adds a filter before the lastly added filter, so the + * processing order of the filters is in reverse */ +#define INSERT_FILT(name, arg) do { \ + AVFilterContext *filt_ctx; \ + \ + ret = avfilter_graph_create_filter(&filt_ctx, \ + avfilter_get_by_name(name), \ + "avplay_" name, arg, NULL, graph); \ + if (ret < 0) \ + return ret; \ + \ + ret = avfilter_link(filt_ctx, 0, last_filter, 0); \ + if (ret < 0) \ + return ret; \ + \ + last_filter = filt_ctx; \ +} while (0) + + INSERT_FILT("format", "yuv420p"); + + if (autorotate) { + uint8_t* displaymatrix = av_stream_get_side_data(is->video_st, + AV_PKT_DATA_DISPLAYMATRIX, NULL); + if (displaymatrix) { + double rot = av_display_rotation_get((int32_t*) displaymatrix); + if (rot < -135 || rot > 135) { + INSERT_FILT("vflip", NULL); + INSERT_FILT("hflip", NULL); + } else if (rot < -45) { + INSERT_FILT("transpose", "dir=clock"); + } else if (rot > 45) { + INSERT_FILT("transpose", "dir=cclock"); + } + } + } if (vfilters) { AVFilterInOut *outputs = avfilter_inout_alloc(); @@ -1544,14 +1507,14 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c outputs->next = NULL; inputs->name = av_strdup("out"); - inputs->filter_ctx = filt_format; + inputs->filter_ctx = last_filter; inputs->pad_idx = 0; inputs->next = NULL; if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0) return ret; } else { - if ((ret = avfilter_link(filt_src, 0, filt_format, 0)) < 0) + if ((ret = avfilter_link(filt_src, 0, last_filter, 0)) < 0) return ret; } @@ -1564,37 +1527,40 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c return ret; } -#endif /* CONFIG_AVFILTER */ - static int video_thread(void *arg) { AVPacket pkt = { 0 }; - VideoState *is = arg; + PlayerState *is = arg; AVFrame *frame = av_frame_alloc(); int64_t pts_int; double pts; int ret; -#if CONFIG_AVFILTER AVFilterGraph *graph = avfilter_graph_alloc(); AVFilterContext *filt_out = NULL, *filt_in = NULL; - int last_w = is->video_st->codec->width; - int last_h = is->video_st->codec->height; + int last_w = is->video_dec->width; + int last_h = is->video_dec->height; + if (!graph) { + av_frame_free(&frame); + return AVERROR(ENOMEM); + } if ((ret = configure_video_filters(graph, is, vfilters)) < 0) goto the_end; filt_in = is->in_video_filter; filt_out = is->out_video_filter; -#endif + + if (!frame) { + avfilter_graph_free(&graph); + return AVERROR(ENOMEM); + } for (;;) { -#if CONFIG_AVFILTER AVRational tb; -#endif while (is->paused && !is->videoq.abort_request) SDL_Delay(10); - av_free_packet(&pkt); + av_packet_unref(&pkt); ret = get_video_frame(is, frame, &pts_int, &pkt); if (ret < 0) @@ -1603,19 +1569,18 @@ static int video_thread(void *arg) if (!ret) continue; -#if CONFIG_AVFILTER - if ( last_w != is->video_st->codec->width - || last_h != is->video_st->codec->height) { - av_dlog(NULL, "Changing size %dx%d -> %dx%d\n", last_w, last_h, - is->video_st->codec->width, is->video_st->codec->height); + if ( last_w != is->video_dec->width + || last_h != is->video_dec->height) { + av_log(NULL, AV_LOG_TRACE, "Changing size %dx%d -> %dx%d\n", last_w, last_h, + is->video_dec->width, is->video_dec->height); avfilter_graph_free(&graph); graph = avfilter_graph_alloc(); if ((ret = configure_video_filters(graph, is, vfilters)) < 0) goto the_end; filt_in = is->in_video_filter; filt_out = is->out_video_filter; - last_w = is->video_st->codec->width; - last_h = is->video_st->codec->height; + last_w = is->video_dec->width; + last_h = is->video_dec->height; } frame->pts = pts_int; @@ -1635,7 +1600,7 @@ static int video_thread(void *arg) if (av_cmp_q(tb, is->video_st->time_base)) { av_unused int64_t pts1 = pts_int; pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base); - av_dlog(NULL, "video_thread(): " + av_log(NULL, AV_LOG_TRACE, "video_thread(): " "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", tb.num, tb.den, pts1, is->video_st->time_base.num, is->video_st->time_base.den, pts_int); @@ -1643,32 +1608,29 @@ static int video_thread(void *arg) pts = pts_int * av_q2d(is->video_st->time_base); ret = output_picture2(is, frame, pts, 0); } -#else - pts = pts_int * av_q2d(is->video_st->time_base); - ret = output_picture2(is, frame, pts, pkt.pos); -#endif if (ret < 0) goto the_end; if (step) - if (cur_stream) - stream_pause(cur_stream); + if (player) + stream_pause(player); } the_end: -#if CONFIG_AVFILTER + SDL_LockMutex(is->video_filter_mutex); + is->out_video_filter = NULL; + SDL_UnlockMutex(is->video_filter_mutex); av_freep(&vfilters); avfilter_graph_free(&graph); -#endif - av_free_packet(&pkt); + av_packet_unref(&pkt); av_frame_free(&frame); return 0; } static int subtitle_thread(void *arg) { - VideoState *is = arg; + PlayerState *is = arg; SubPicture *sp; AVPacket pkt1, *pkt = &pkt1; int got_subtitle; @@ -1684,7 +1646,7 @@ static int subtitle_thread(void *arg) break; if (pkt->data == flush_pkt.data) { - avcodec_flush_buffers(is->subtitle_st->codec); + avcodec_flush_buffers(is->subtitle_dec); continue; } SDL_LockMutex(is->subpq_mutex); @@ -1703,9 +1665,9 @@ static int subtitle_thread(void *arg) this packet, if any */ pts = 0; if (pkt->pts != AV_NOPTS_VALUE) - pts = av_q2d(is->subtitle_st->time_base) * pkt->pts; + pts = av_q2d(is->subtitle_dec->time_base) * pkt->pts; - avcodec_decode_subtitle2(is->subtitle_st->codec, &sp->sub, + avcodec_decode_subtitle2(is->subtitle_dec, &sp->sub, &got_subtitle, pkt); if (got_subtitle && sp->sub.format == 0) { @@ -1715,11 +1677,11 @@ static int subtitle_thread(void *arg) { for (j = 0; j < sp->sub.rects[i]->nb_colors; j++) { - RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j); + RGBA_IN(r, g, b, a, (uint32_t *)sp->sub.rects[i]->data[1] + 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((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a); + YUVA_OUT((uint32_t *)sp->sub.rects[i]->data[1] + j, y, u, v, a); } } @@ -1730,13 +1692,13 @@ static int subtitle_thread(void *arg) is->subpq_size++; SDL_UnlockMutex(is->subpq_mutex); } - av_free_packet(pkt); + av_packet_unref(pkt); } return 0; } /* copy samples for viewing in editor window */ -static void update_sample_display(VideoState *is, short *samples, int samples_size) +static void update_sample_display(PlayerState *is, short *samples, int samples_size) { int size, len; @@ -1756,7 +1718,7 @@ static void update_sample_display(VideoState *is, short *samples, int samples_si /* 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, +static int synchronize_audio(PlayerState *is, short *samples, int samples_size1, double pts) { int n, samples_size; @@ -1814,7 +1776,7 @@ static int synchronize_audio(VideoState *is, short *samples, samples_size = wanted_size; } } - av_dlog(NULL, "diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n", + av_log(NULL, AV_LOG_TRACE, "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); } @@ -1830,11 +1792,11 @@ static int synchronize_audio(VideoState *is, short *samples, } /* decode one audio frame and returns its uncompressed size */ -static int audio_decode_frame(VideoState *is, double *pts_ptr) +static int audio_decode_frame(PlayerState *is, double *pts_ptr) { AVPacket *pkt_temp = &is->audio_pkt_temp; AVPacket *pkt = &is->audio_pkt; - AVCodecContext *dec = is->audio_st->codec; + AVCodecContext *dec = is->audio_dec; int n, len1, data_size, got_frame; double pts; int new_packet = 0; @@ -1865,7 +1827,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) if (!got_frame) { /* stop sending empty packets if the decoder is finished */ - if (!pkt_temp->data && dec->codec->capabilities & CODEC_CAP_DELAY) + if (!pkt_temp->data && (dec->codec->capabilities & AV_CODEC_CAP_DELAY)) flush_complete = 1; continue; } @@ -1961,7 +1923,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) /* free the current packet */ if (pkt->data) - av_free_packet(pkt); + av_packet_unref(pkt); memset(pkt_temp, 0, sizeof(*pkt_temp)); if (is->paused || is->audioq.abort_request) { @@ -1989,11 +1951,11 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) /* prepare a new audio buffer */ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) { - VideoState *is = opaque; + PlayerState *is = opaque; int audio_size, len1; double pts; - audio_callback_time = av_gettime(); + audio_callback_time = av_gettime_relative(); while (len > 0) { if (is->audio_buf_index >= is->audio_buf_size) { @@ -2021,8 +1983,54 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) } } +static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type) +{ + const AVCodecDescriptor *desc; + AVCodec *codec = avcodec_find_decoder_by_name(name); + + if (!codec && (desc = avcodec_descriptor_get_by_name(name))) { + codec = avcodec_find_decoder(desc->id); + if (codec) + av_log(NULL, AV_LOG_VERBOSE, "Matched decoder '%s' for codec '%s'.\n", + codec->name, desc->name); + } + + if (!codec) { + av_log(NULL, AV_LOG_FATAL, "Unknown decoder '%s'\n", name); + exit_program(1); + } + + if (codec->type != type) { + av_log(NULL, AV_LOG_FATAL, "Invalid decoder type '%s'\n", name); + exit_program(1); + } + + return codec; +} + +static AVCodec *choose_decoder(PlayerState *is, AVFormatContext *ic, AVStream *st) +{ + char *codec_name = NULL; + int i, ret; + + for (i = 0; i < is->nb_codec_names; i++) { + char *spec = is->codec_names[i].specifier; + if ((ret = check_stream_specifier(ic, st, spec)) > 0) + codec_name = is->codec_names[i].u.str; + else if (ret < 0) + exit_program(1); + } + + if (codec_name) { + AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type); + st->codecpar->codec_id = codec->id; + return codec; + } else + return avcodec_find_decoder(st->codecpar->codec_id); +} + /* open a given stream. Return 0 if OK */ -static int stream_component_open(VideoState *is, int stream_index) +static int stream_component_open(PlayerState *is, int stream_index) { AVFormatContext *ic = is->ic; AVCodecContext *avctx; @@ -2030,14 +2038,24 @@ static int stream_component_open(VideoState *is, int stream_index) SDL_AudioSpec wanted_spec, spec; AVDictionary *opts; AVDictionaryEntry *t = NULL; + int ret = 0; if (stream_index < 0 || stream_index >= ic->nb_streams) return -1; - avctx = ic->streams[stream_index]->codec; + + avctx = avcodec_alloc_context3(NULL); + if (!avctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar); + if (ret < 0) { + avcodec_free_context(&avctx); + return ret; + } opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], NULL); - codec = avcodec_find_decoder(avctx->codec_id); + codec = choose_decoder(is, ic, ic->streams[stream_index]); avctx->workaround_bugs = workaround_bugs; avctx->idct_algo = idct; avctx->skip_frame = skip_frame; @@ -2045,18 +2063,21 @@ static int stream_component_open(VideoState *is, int stream_index) avctx->skip_loop_filter = skip_loop_filter; avctx->error_concealment = error_concealment; - if (fast) avctx->flags2 |= CODEC_FLAG2_FAST; + if (fast) + avctx->flags2 |= AV_CODEC_FLAG2_FAST; if (!av_dict_get(opts, "threads", NULL, 0)) av_dict_set(&opts, "threads", "auto", 0); if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) av_dict_set(&opts, "refcounted_frames", "1", 0); if (!codec || - avcodec_open2(avctx, codec, &opts) < 0) - return -1; + (ret = avcodec_open2(avctx, codec, &opts)) < 0) { + goto fail; + } if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key); - return AVERROR_OPTION_NOT_FOUND; + ret = AVERROR_OPTION_NOT_FOUND; + goto fail; } /* prepare audio output */ @@ -2067,7 +2088,8 @@ static int stream_component_open(VideoState *is, int stream_index) avctx->channel_layout = av_get_default_channel_layout(avctx->channels); if (!avctx->channel_layout) { fprintf(stderr, "unable to guess channel layout\n"); - return -1; + ret = AVERROR_INVALIDDATA; + goto fail; } if (avctx->channels == 1) is->sdl_channel_layout = AV_CH_LAYOUT_MONO; @@ -2084,7 +2106,8 @@ static int stream_component_open(VideoState *is, int stream_index) wanted_spec.userdata = is; if (SDL_OpenAudio(&wanted_spec, &spec) < 0) { fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); - return -1; + ret = AVERROR_UNKNOWN; + goto fail; } is->audio_hw_buf_size = spec.size; is->sdl_sample_fmt = AV_SAMPLE_FMT_S16; @@ -2098,13 +2121,14 @@ static int stream_component_open(VideoState *is, int stream_index) case AVMEDIA_TYPE_AUDIO: is->audio_stream = stream_index; is->audio_st = ic->streams[stream_index]; + is->audio_dec = avctx; 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, + /* since we do not have a precise enough audio FIFO fullness, we correct audio sync only if larger than this threshold */ is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate; @@ -2115,6 +2139,7 @@ static int stream_component_open(VideoState *is, int stream_index) case AVMEDIA_TYPE_VIDEO: is->video_stream = stream_index; is->video_st = ic->streams[stream_index]; + is->video_dec = avctx; packet_queue_init(&is->videoq); is->video_tid = SDL_CreateThread(video_thread, is); @@ -2122,6 +2147,7 @@ static int stream_component_open(VideoState *is, int stream_index) case AVMEDIA_TYPE_SUBTITLE: is->subtitle_stream = stream_index; is->subtitle_st = ic->streams[stream_index]; + is->subtitle_dec = avctx; packet_queue_init(&is->subtitleq); is->subtitle_tid = SDL_CreateThread(subtitle_thread, is); @@ -2129,26 +2155,30 @@ static int stream_component_open(VideoState *is, int stream_index) default: break; } - return 0; + +fail: + av_dict_free(&opts); + + return ret; } -static void stream_component_close(VideoState *is, int stream_index) +static void stream_component_close(PlayerState *is, int stream_index) { AVFormatContext *ic = is->ic; - AVCodecContext *avctx; + AVCodecParameters *par; if (stream_index < 0 || stream_index >= ic->nb_streams) return; - avctx = ic->streams[stream_index]->codec; + par = ic->streams[stream_index]->codecpar; - switch (avctx->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: packet_queue_abort(&is->audioq); SDL_CloseAudio(); packet_queue_end(&is->audioq); - av_free_packet(&is->audio_pkt); + av_packet_unref(&is->audio_pkt); if (is->avr) avresample_free(&is->avr); av_freep(&is->audio_buf1); @@ -2195,17 +2225,19 @@ static void stream_component_close(VideoState *is, int stream_index) } ic->streams[stream_index]->discard = AVDISCARD_ALL; - avcodec_close(avctx); - switch (avctx->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: + avcodec_free_context(&is->audio_dec); is->audio_st = NULL; is->audio_stream = -1; break; case AVMEDIA_TYPE_VIDEO: + avcodec_free_context(&is->video_dec); is->video_st = NULL; is->video_stream = -1; break; case AVMEDIA_TYPE_SUBTITLE: + avcodec_free_context(&is->subtitle_dec); is->subtitle_st = NULL; is->subtitle_stream = -1; break; @@ -2216,23 +2248,35 @@ static void stream_component_close(VideoState *is, int stream_index) /* 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 PlayerState *global_video_state; static int decode_interrupt_cb(void *ctx) { 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) +static void stream_close(PlayerState *is) +{ + /* 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) { + avformat_close_input(&is->ic); + } +} + +static int stream_setup(PlayerState *is) { - VideoState *is = arg; AVFormatContext *ic = NULL; int err, i, ret; int st_index[AVMEDIA_TYPE_NB]; - AVPacket pkt1, *pkt = &pkt1; - int eof = 0; - int pkt_in_play_range = 0; AVDictionaryEntry *t; AVDictionary **opts; int orig_nb_streams; @@ -2245,6 +2289,11 @@ static int decode_thread(void *arg) global_video_state = is; ic = avformat_alloc_context(); + if (!ic) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } ic->interrupt_callback.callback = decode_interrupt_cb; err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts); if (err < 0) { @@ -2252,6 +2301,7 @@ static int decode_thread(void *arg) ret = -1; goto fail; } + if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key); ret = AVERROR_OPTION_NOT_FOUND; @@ -2265,15 +2315,20 @@ static int decode_thread(void *arg) opts = setup_find_stream_info_opts(ic, codec_opts); orig_nb_streams = ic->nb_streams; + for (i = 0; i < ic->nb_streams; i++) + choose_decoder(is, ic, ic->streams[i]); + err = avformat_find_stream_info(ic, opts); + + for (i = 0; i < orig_nb_streams; i++) + av_dict_free(&opts[i]); + av_freep(&opts); + if (err < 0) { fprintf(stderr, "%s: could not find codec parameters\n", is->filename); ret = -1; goto fail; } - for (i = 0; i < orig_nb_streams; i++) - av_dict_free(&opts[i]); - av_freep(&opts); if (ic->pb) ic->pb->eof_reached = 0; // FIXME hack, avplay maybe should not use url_feof() to test for the end @@ -2329,7 +2384,6 @@ static int decode_thread(void *arg) if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]); } - is->refresh_tid = SDL_CreateThread(refresh_thread, is); if (ret < 0) { if (!display_disable) is->show_audio = 2; @@ -2345,6 +2399,21 @@ static int decode_thread(void *arg) goto fail; } + return 0; + +fail: + return ret; +} + +/* this thread gets the stream from the disk or the network */ +static int decode_thread(void *arg) +{ + PlayerState *is = arg; + AVPacket pkt1, *pkt = &pkt1; + AVFormatContext *ic = is->ic; + int pkt_in_play_range = 0; + int ret, eof = 0; + for (;;) { if (is->abort_request) break; @@ -2410,7 +2479,7 @@ static int decode_thread(void *arg) packet_queue_put(&is->videoq, pkt); } if (is->audio_stream >= 0 && - is->audio_st->codec->codec->capabilities & CODEC_CAP_DELAY) { + (is->audio_dec->codec->capabilities & AV_CODEC_CAP_DELAY)) { av_init_packet(pkt); pkt->data = NULL; pkt->size = 0; @@ -2420,8 +2489,8 @@ static int decode_thread(void *arg) SDL_Delay(10); if (is->audioq.size + is->videoq.size + is->subtitleq.size == 0) { if (loop != 1 && (!loop || --loop)) { - stream_seek(cur_stream, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0); - } else if (autoexit) { + stream_seek(player, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0); + } else if (!noautoexit) { ret = AVERROR_EOF; goto fail; } @@ -2450,7 +2519,7 @@ static int decode_thread(void *arg) } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) { packet_queue_put(&is->subtitleq, pkt); } else { - av_free_packet(pkt); + av_packet_unref(pkt); } } /* wait until the end */ @@ -2459,20 +2528,9 @@ static int decode_thread(void *arg) } 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) { - avformat_close_input(&is->ic); - } +fail: + stream_close(is); if (ret != 0) { SDL_Event event; @@ -2484,18 +2542,22 @@ static int decode_thread(void *arg) return 0; } -static VideoState *stream_open(const char *filename, AVInputFormat *iformat) +static int stream_open(PlayerState *is, + const char *filename, AVInputFormat *iformat) { - VideoState *is; + int ret; - is = av_mallocz(sizeof(VideoState)); - if (!is) - return NULL; av_strlcpy(is->filename, filename, sizeof(is->filename)); is->iformat = iformat; is->ytop = 0; is->xleft = 0; + if ((ret = stream_setup(is)) < 0) { + return ret; + } + + is->video_filter_mutex = SDL_CreateMutex(); + /* start video display */ is->pictq_mutex = SDL_CreateMutex(); is->pictq_cond = SDL_CreateCond(); @@ -2504,15 +2566,16 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) is->subpq_cond = SDL_CreateCond(); is->av_sync_type = av_sync_type; + is->refresh_tid = SDL_CreateThread(refresh_thread, is); + if (!is->refresh_tid) + return -1; is->parse_tid = SDL_CreateThread(decode_thread, is); - if (!is->parse_tid) { - av_free(is); - return NULL; - } - return is; + if (!is->parse_tid) + return -1; + return 0; } -static void stream_cycle_channel(VideoState *is, int codec_type) +static void stream_cycle_channel(PlayerState *is, int codec_type) { AVFormatContext *ic = is->ic; int start_index, stream_index; @@ -2540,12 +2603,12 @@ static void stream_cycle_channel(VideoState *is, int codec_type) if (stream_index == start_index) return; st = ic->streams[stream_index]; - if (st->codec->codec_type == codec_type) { + if (st->codecpar->codec_type == codec_type) { /* check that parameters are OK */ switch (codec_type) { case AVMEDIA_TYPE_AUDIO: - if (st->codec->sample_rate != 0 && - st->codec->channels != 0) + if (st->codecpar->sample_rate != 0 && + st->codecpar->channels != 0) goto the_end; break; case AVMEDIA_TYPE_VIDEO: @@ -2568,42 +2631,42 @@ static void toggle_full_screen(void) /* OS X needs to empty the picture_queue */ int i; for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) - cur_stream->pictq[i].reallocate = 1; + player->pictq[i].reallocate = 1; #endif is_full_screen = !is_full_screen; - video_open(cur_stream); + video_open(player); } static void toggle_pause(void) { - if (cur_stream) - stream_pause(cur_stream); + if (player) + stream_pause(player); step = 0; } static void step_to_next_frame(void) { - if (cur_stream) { + if (player) { /* if the stream is paused unpause it, then step */ - if (cur_stream->paused) - stream_pause(cur_stream); + if (player->paused) + stream_pause(player); } step = 1; } static void toggle_audio_display(void) { - if (cur_stream) { + if (player) { int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); - cur_stream->show_audio = (cur_stream->show_audio + 1) % 3; + player->show_audio = (player->show_audio + 1) % 3; fill_rectangle(screen, - cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height, + player->xleft, player->ytop, player->width, player->height, bgcolor); - SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height); + SDL_UpdateRect(screen, player->xleft, player->ytop, player->width, player->height); } } -static void seek_chapter(VideoState *is, int incr) +static void seek_chapter(PlayerState *is, int incr) { int64_t pos = get_master_clock(is) * AV_TIME_BASE; int i; @@ -2661,25 +2724,25 @@ static void event_loop(void) step_to_next_frame(); break; case SDLK_a: - if (cur_stream) - stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO); + if (player) + stream_cycle_channel(player, AVMEDIA_TYPE_AUDIO); break; case SDLK_v: - if (cur_stream) - stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO); + if (player) + stream_cycle_channel(player, AVMEDIA_TYPE_VIDEO); break; case SDLK_t: - if (cur_stream) - stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE); + if (player) + stream_cycle_channel(player, AVMEDIA_TYPE_SUBTITLE); break; case SDLK_w: toggle_audio_display(); break; case SDLK_PAGEUP: - seek_chapter(cur_stream, 1); + seek_chapter(player, 1); break; case SDLK_PAGEDOWN: - seek_chapter(cur_stream, -1); + seek_chapter(player, -1); break; case SDLK_LEFT: incr = -10.0; @@ -2693,24 +2756,24 @@ static void event_loop(void) case SDLK_DOWN: incr = -60.0; do_seek: - if (cur_stream) { + if (player) { if (seek_by_bytes) { - if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos >= 0) { - pos = cur_stream->video_current_pos; - } else if (cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos >= 0) { - pos = cur_stream->audio_pkt.pos; + if (player->video_stream >= 0 && player->video_current_pos >= 0) { + pos = player->video_current_pos; + } else if (player->audio_stream >= 0 && player->audio_pkt.pos >= 0) { + pos = player->audio_pkt.pos; } else - pos = avio_tell(cur_stream->ic->pb); - if (cur_stream->ic->bit_rate) - incr *= cur_stream->ic->bit_rate / 8.0; + pos = avio_tell(player->ic->pb); + if (player->ic->bit_rate) + incr *= player->ic->bit_rate / 8.0; else incr *= 180000.0; pos += incr; - stream_seek(cur_stream, pos, incr, 1); + stream_seek(player, pos, incr, 1); } else { - pos = get_master_clock(cur_stream); + pos = get_master_clock(player); pos += incr; - stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0); + stream_seek(player, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0); } } break; @@ -2731,38 +2794,38 @@ static void event_loop(void) break; x = event.motion.x; } - if (cur_stream) { - if (seek_by_bytes || cur_stream->ic->duration <= 0) { - uint64_t size = avio_size(cur_stream->ic->pb); - stream_seek(cur_stream, size*x/cur_stream->width, 0, 1); + if (player) { + if (seek_by_bytes || player->ic->duration <= 0) { + uint64_t size = avio_size(player->ic->pb); + stream_seek(player, size*x/player->width, 0, 1); } else { int64_t ts; int ns, hh, mm, ss; int tns, thh, tmm, tss; - tns = cur_stream->ic->duration / 1000000LL; + tns = player->ic->duration / 1000000LL; thh = tns / 3600; tmm = (tns % 3600) / 60; tss = (tns % 60); - frac = x / cur_stream->width; + frac = x / player->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); - ts = frac * cur_stream->ic->duration; - if (cur_stream->ic->start_time != AV_NOPTS_VALUE) - ts += cur_stream->ic->start_time; - stream_seek(cur_stream, ts, 0, 0); + ts = frac * player->ic->duration; + if (player->ic->start_time != AV_NOPTS_VALUE) + ts += player->ic->start_time; + stream_seek(player, ts, 0, 0); } } break; case SDL_VIDEORESIZE: - if (cur_stream) { + if (player) { screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL); - screen_width = cur_stream->width = event.resize.w; - screen_height = cur_stream->height = event.resize.h; + screen_width = player->width = event.resize.w; + screen_height = player->height = event.resize.h; } break; case SDL_QUIT: @@ -2770,12 +2833,16 @@ static void event_loop(void) do_exit(); break; case FF_ALLOC_EVENT: - video_open(event.user.data1); - alloc_picture(event.user.data1); + SDL_LockMutex(player->video_filter_mutex); + if (player->out_video_filter) { + video_open(event.user.data1); + alloc_picture(event.user.data1); + } + SDL_UnlockMutex(player->video_filter_mutex); break; case FF_REFRESH_EVENT: video_refresh_timer(event.user.data1); - cur_stream->refresh = 0; + player->refresh = 0; break; default: break; @@ -2846,6 +2913,7 @@ static int opt_duration(void *optctx, const char *opt, const char *arg) return 0; } +#define OFF(x) offsetof(PlayerState, x) static const OptionDef options[] = { #include "cmdutils_common_opts.h" { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" }, @@ -2874,19 +2942,21 @@ static const OptionDef options[] = { { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { &idct }, "set idct algo", "algo" }, { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { &error_concealment }, "set error concealment options", "bit_mask" }, { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" }, - { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" }, + { "noautoexit", OPT_BOOL | OPT_EXPERT, { &noautoexit }, "Do not exit at the end of playback", "" }, { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" }, { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" }, { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" }, { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" }, { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" }, { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" }, -#if CONFIG_AVFILTER { "vf", OPT_STRING | HAS_ARG, { &vfilters }, "video filters", "filter list" }, -#endif { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" }, { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { opt_default }, "generic catch all option", "" }, { "i", 0, { NULL }, "avconv compatibility dummy option", ""}, + { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" }, + { "c", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFF(codec_names) }, "codec name", "codec" }, + { "codec", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFF(codec_names) }, "codec name", "codec" }, + { NULL, }, }; @@ -2906,9 +2976,6 @@ void show_help_default(const char *opt, const char *arg) printf("\n"); show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM); show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM); -#if !CONFIG_AVFILTER - show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM); -#endif printf("\nWhile playing:\n" "q, ESC quit\n" "f toggle full screen\n" @@ -2949,9 +3016,7 @@ int main(int argc, char **argv) #if CONFIG_AVDEVICE avdevice_register_all(); #endif -#if CONFIG_AVFILTER avfilter_register_all(); -#endif av_register_all(); avformat_network_init(); @@ -2959,7 +3024,7 @@ int main(int argc, char **argv) show_banner(); - parse_options(NULL, argc, argv, options, opt_input_file); + parse_options(player, argc, argv, options, opt_input_file); if (!input_filename) { show_usage(); @@ -2993,7 +3058,11 @@ int main(int argc, char **argv) av_init_packet(&flush_pkt); flush_pkt.data = (uint8_t *)&flush_pkt; - cur_stream = stream_open(input_filename, file_iformat); + if (stream_open(player, input_filename, file_iformat) < 0) { + fprintf(stderr, "Could not setup the player\n"); + stream_close(player); + exit(1); + } event_loop(); diff --git a/avprobe.c b/avprobe.c index c7b3d39..f60e1ad 100644 --- a/avprobe.c +++ b/avprobe.c @@ -24,13 +24,28 @@ #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libavutil/avstring.h" +#include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/stereo3d.h" #include "libavutil/dict.h" #include "libavutil/libm.h" #include "libavdevice/avdevice.h" #include "cmdutils.h" +typedef struct InputStream { + AVStream *st; + + AVCodecContext *dec_ctx; +} InputStream; + +typedef struct InputFile { + AVFormatContext *fmt_ctx; + + InputStream *streams; + int nb_streams; +} InputFile; + const char program_name[] = "avprobe"; const int program_birth_year = 2007; @@ -48,7 +63,7 @@ static int use_value_sexagesimal_format = 0; /* globals */ static const OptionDef *options; -/* AVprobe context */ +/* avprobe context */ static const char *input_filename; static AVInputFormat *iformat = NULL; @@ -84,21 +99,21 @@ typedef enum { OBJECT } PrintElementType; -typedef struct { +typedef struct PrintElement { const char *name; PrintElementType type; int64_t index; int64_t nb_elems; } PrintElement; -typedef struct { +typedef struct PrintContext { PrintElement *prefix; int level; void (*print_header)(void); void (*print_footer)(void); - void (*print_array_header) (const char *name); - void (*print_array_footer) (const char *name); + void (*print_array_header) (const char *name, int plain_values); + void (*print_array_footer) (const char *name, int plain_values); void (*print_object_header)(const char *name); void (*print_object_footer)(const char *name); @@ -157,9 +172,21 @@ static void ini_escape_print(const char *s) } } -static void ini_print_array_header(const char *name) +static void ini_print_array_header(const char *name, int plain_values) { - if (octx.prefix[octx.level -1].nb_elems) + if (!plain_values) { + /* Add a new line if we create a new full group */ + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, "\n"); + } else { + ini_escape_print(name); + avio_w8(probe_out, '='); + } +} + +static void ini_print_array_footer(const char *name, int plain_values) +{ + if (plain_values) avio_printf(probe_out, "\n"); } @@ -181,15 +208,21 @@ static void ini_print_object_header(const char *name) } avio_printf(probe_out, "%s", name); - if (el && el->type == ARRAY) + if (el->type == ARRAY) avio_printf(probe_out, ".%"PRId64"", el->nb_elems); avio_printf(probe_out, "]\n"); } static void ini_print_integer(const char *key, int64_t value) { - ini_escape_print(key); - avio_printf(probe_out, "=%"PRId64"\n", value); + if (key) { + ini_escape_print(key); + avio_printf(probe_out, "=%"PRId64"\n", value); + } else { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ","); + avio_printf(probe_out, "%"PRId64, value); + } } @@ -214,7 +247,7 @@ static void json_print_footer(void) avio_printf(probe_out, "}\n"); } -static void json_print_array_header(const char *name) +static void json_print_array_header(const char *name, int plain_values) { if (octx.prefix[octx.level -1].nb_elems) avio_printf(probe_out, ",\n"); @@ -223,7 +256,7 @@ static void json_print_array_header(const char *name) avio_printf(probe_out, "[\n"); } -static void json_print_array_footer(const char *name) +static void json_print_array_footer(const char *name, int plain_values) { avio_printf(probe_out, "\n"); AVP_INDENT(); @@ -249,10 +282,18 @@ static void json_print_object_footer(const char *name) static void json_print_integer(const char *key, int64_t value) { - if (octx.prefix[octx.level -1].nb_elems) - avio_printf(probe_out, ",\n"); - AVP_INDENT(); - avio_printf(probe_out, "\"%s\" : %"PRId64"", key, value); + if (key) { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ",\n"); + AVP_INDENT(); + avio_printf(probe_out, "\"%s\" : ", key); + } else { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ", "); + else + AVP_INDENT(); + } + avio_printf(probe_out, "%"PRId64, value); } static void json_escape_print(const char *s) @@ -302,6 +343,8 @@ static void old_print_object_header(const char *name) return; str = p = av_strdup(name); + if (!str) + return; while (*p) { *p = av_toupper(*p); p++; @@ -319,6 +362,8 @@ static void old_print_object_footer(const char *name) return; str = p = av_strdup(name); + if (!str) + return; while (*p) { *p = av_toupper(*p); p++; @@ -399,19 +444,19 @@ static void probe_footer(void) } -static void probe_array_header(const char *name) +static void probe_array_header(const char *name, int plain_values) { if (octx.print_array_header) - octx.print_array_header(name); + octx.print_array_header(name, plain_values); probe_group_enter(name, ARRAY); } -static void probe_array_footer(const char *name) +static void probe_array_footer(const char *name, int plain_values) { probe_group_leave(); if (octx.print_array_footer) - octx.print_array_footer(name); + octx.print_array_footer(name, plain_values); } static void probe_object_header(const char *name) @@ -526,13 +571,19 @@ static char *tag_string(char *buf, int buf_size, int tag) return buf; } +static char *unknown_string(char *buf, int buf_size, int val) +{ + snprintf(buf, buf_size, "Unknown (%d)", val); + return buf; +} + static void show_packet(AVFormatContext *fmt_ctx, AVPacket *pkt) { char val_str[128]; AVStream *st = fmt_ctx->streams[pkt->stream_index]; probe_object_header("packet"); - probe_str("codec_type", media_type_string(st->codec->codec_type)); + probe_str("codec_type", media_type_string(st->codecpar->codec_type)); probe_int("stream_index", pkt->stream_index); probe_str("pts", ts_value_string(val_str, sizeof(val_str), pkt->pts)); probe_str("pts_time", time_value_string(val_str, sizeof(val_str), @@ -552,91 +603,125 @@ static void show_packet(AVFormatContext *fmt_ctx, AVPacket *pkt) probe_object_footer("packet"); } -static void show_packets(AVFormatContext *fmt_ctx) +static void show_packets(InputFile *ifile) { + AVFormatContext *fmt_ctx = ifile->fmt_ctx; AVPacket pkt; av_init_packet(&pkt); - probe_array_header("packets"); - while (!av_read_frame(fmt_ctx, &pkt)) + probe_array_header("packets", 0); + while (!av_read_frame(fmt_ctx, &pkt)) { show_packet(fmt_ctx, &pkt); - probe_array_footer("packets"); + av_packet_unref(&pkt); + } + probe_array_footer("packets", 0); } -static void show_stream(AVFormatContext *fmt_ctx, int stream_idx) +static void show_stream(InputFile *ifile, InputStream *ist) { - AVStream *stream = fmt_ctx->streams[stream_idx]; + AVFormatContext *fmt_ctx = ifile->fmt_ctx; + AVStream *stream = ist->st; + AVCodecParameters *par; AVCodecContext *dec_ctx; - const AVCodec *dec; + const AVCodecDescriptor *codec_desc; const char *profile; char val_str[128]; AVRational display_aspect_ratio, *sar = NULL; const AVPixFmtDescriptor *desc; + const char *val; probe_object_header("stream"); probe_int("index", stream->index); - if ((dec_ctx = stream->codec)) { - if ((dec = dec_ctx->codec)) { - probe_str("codec_name", dec->name); - probe_str("codec_long_name", dec->long_name); - } else { - probe_str("codec_name", "unknown"); - } + par = stream->codecpar; + dec_ctx = ist->dec_ctx; + codec_desc = avcodec_descriptor_get(par->codec_id); + if (codec_desc) { + probe_str("codec_name", codec_desc->name); + probe_str("codec_long_name", codec_desc->long_name); + } else { + probe_str("codec_name", "unknown"); + } - probe_str("codec_type", media_type_string(dec_ctx->codec_type)); - probe_str("codec_time_base", - rational_string(val_str, sizeof(val_str), - "/", &dec_ctx->time_base)); - - /* print AVI/FourCC tag */ - av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag); - probe_str("codec_tag_string", val_str); - probe_str("codec_tag", tag_string(val_str, sizeof(val_str), - dec_ctx->codec_tag)); - - /* print profile, if there is one */ - if (dec && (profile = av_get_profile_name(dec, dec_ctx->profile))) - probe_str("profile", profile); - - switch (dec_ctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - probe_int("width", dec_ctx->width); - probe_int("height", dec_ctx->height); + probe_str("codec_type", media_type_string(par->codec_type)); + + /* print AVI/FourCC tag */ + av_get_codec_tag_string(val_str, sizeof(val_str), par->codec_tag); + probe_str("codec_tag_string", val_str); + probe_str("codec_tag", tag_string(val_str, sizeof(val_str), + par->codec_tag)); + + /* print profile, if there is one */ + profile = avcodec_profile_name(par->codec_id, par->profile); + if (profile) + probe_str("profile", profile); + + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + probe_int("width", par->width); + probe_int("height", par->height); + if (dec_ctx) { + probe_int("coded_width", dec_ctx->coded_width); + probe_int("coded_height", dec_ctx->coded_height); probe_int("has_b_frames", dec_ctx->has_b_frames); - if (dec_ctx->sample_aspect_ratio.num) - sar = &dec_ctx->sample_aspect_ratio; - else if (stream->sample_aspect_ratio.num) - sar = &stream->sample_aspect_ratio; - - if (sar) { - probe_str("sample_aspect_ratio", - rational_string(val_str, sizeof(val_str), ":", sar)); - av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, - dec_ctx->width * sar->num, dec_ctx->height * sar->den, - 1024*1024); - probe_str("display_aspect_ratio", - rational_string(val_str, sizeof(val_str), ":", - &display_aspect_ratio)); - } - desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt); - probe_str("pix_fmt", desc ? desc->name : "unknown"); - probe_int("level", dec_ctx->level); - break; - - case AVMEDIA_TYPE_AUDIO: - probe_str("sample_rate", - value_string(val_str, sizeof(val_str), - dec_ctx->sample_rate, - unit_hertz_str)); - probe_int("channels", dec_ctx->channels); - probe_int("bits_per_sample", - av_get_bits_per_sample(dec_ctx->codec_id)); - break; } - } else { - probe_str("codec_type", "unknown"); + if (dec_ctx && dec_ctx->sample_aspect_ratio.num) + sar = &dec_ctx->sample_aspect_ratio; + else if (par->sample_aspect_ratio.num) + sar = &par->sample_aspect_ratio; + else if (stream->sample_aspect_ratio.num) + sar = &stream->sample_aspect_ratio; + + if (sar) { + probe_str("sample_aspect_ratio", + rational_string(val_str, sizeof(val_str), ":", sar)); + av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, + par->width * sar->num, par->height * sar->den, + 1024*1024); + probe_str("display_aspect_ratio", + rational_string(val_str, sizeof(val_str), ":", + &display_aspect_ratio)); + } + desc = av_pix_fmt_desc_get(par->format); + probe_str("pix_fmt", desc ? desc->name : "unknown"); + probe_int("level", par->level); + + val = av_color_range_name(par->color_range); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_range); + probe_str("color_range", val); + + val = av_color_space_name(par->color_space); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_space); + probe_str("color_space", val); + + val = av_color_transfer_name(par->color_trc); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_trc); + probe_str("color_trc", val); + + val = av_color_primaries_name(par->color_primaries); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_primaries); + probe_str("color_pri", val); + + val = av_chroma_location_name(par->chroma_location); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->chroma_location); + probe_str("chroma_loc", val); + break; + + case AVMEDIA_TYPE_AUDIO: + probe_str("sample_rate", + value_string(val_str, sizeof(val_str), + par->sample_rate, + unit_hertz_str)); + probe_int("channels", par->channels); + probe_int("bits_per_sample", + av_get_bits_per_sample(par->codec_id)); + break; } if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) @@ -644,10 +729,11 @@ static void show_stream(AVFormatContext *fmt_ctx, int stream_idx) probe_str("avg_frame_rate", rational_string(val_str, sizeof(val_str), "/", &stream->avg_frame_rate)); - if (dec_ctx->bit_rate) + + if (par->bit_rate) probe_str("bit_rate", value_string(val_str, sizeof(val_str), - dec_ctx->bit_rate, unit_bit_per_second_str)); + par->bit_rate, unit_bit_per_second_str)); probe_str("time_base", rational_string(val_str, sizeof(val_str), "/", &stream->time_base)); @@ -662,11 +748,44 @@ static void show_stream(AVFormatContext *fmt_ctx, int stream_idx) probe_dict(stream->metadata, "tags"); + if (stream->nb_side_data) { + int i, j; + + probe_object_header("sidedata"); + for (i = 0; i < stream->nb_side_data; i++) { + const AVPacketSideData* sd = &stream->side_data[i]; + AVStereo3D *stereo; + + switch (sd->type) { + case AV_PKT_DATA_DISPLAYMATRIX: + probe_object_header("displaymatrix"); + probe_array_header("matrix", 1); + for (j = 0; j < 9; j++) + probe_int(NULL, ((int32_t *)sd->data)[j]); + probe_array_footer("matrix", 1); + probe_int("rotation", + av_display_rotation_get((int32_t *)sd->data)); + probe_object_footer("displaymatrix"); + break; + case AV_PKT_DATA_STEREO3D: + stereo = (AVStereo3D *)sd->data; + probe_object_header("stereo3d"); + probe_str("type", av_stereo3d_type_name(stereo->type)); + probe_int("inverted", + !!(stereo->flags & AV_STEREO3D_FLAG_INVERT)); + probe_object_footer("stereo3d"); + break; + } + } + probe_object_footer("sidedata"); + } + probe_object_footer("stream"); } -static void show_format(AVFormatContext *fmt_ctx) +static void show_format(InputFile *ifile) { + AVFormatContext *fmt_ctx = ifile->fmt_ctx; char val_str[128]; int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1; @@ -694,7 +813,7 @@ static void show_format(AVFormatContext *fmt_ctx) probe_object_footer("format"); } -static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename) +static int open_input_file(InputFile *ifile, const char *filename) { int err, i; AVFormatContext *fmt_ctx = NULL; @@ -719,64 +838,95 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename) av_dump_format(fmt_ctx, 0, filename, 0); + ifile->streams = av_mallocz_array(fmt_ctx->nb_streams, + sizeof(*ifile->streams)); + if (!ifile->streams) + exit(1); + ifile->nb_streams = fmt_ctx->nb_streams; + /* bind a decoder to each input stream */ for (i = 0; i < fmt_ctx->nb_streams; i++) { + InputStream *ist = &ifile->streams[i]; AVStream *stream = fmt_ctx->streams[i]; AVCodec *codec; - if (stream->codec->codec_id == AV_CODEC_ID_PROBE) { + ist->st = stream; + + if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) { fprintf(stderr, "Failed to probe codec for input stream %d\n", stream->index); - } else if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) { + continue; + } + + codec = avcodec_find_decoder(stream->codecpar->codec_id); + if (!codec) { fprintf(stderr, "Unsupported codec with id %d for input stream %d\n", - stream->codec->codec_id, stream->index); - } else if (avcodec_open2(stream->codec, codec, NULL) < 0) { + stream->codecpar->codec_id, stream->index); + continue; + } + + ist->dec_ctx = avcodec_alloc_context3(codec); + if (!ist->dec_ctx) + exit(1); + + err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar); + if (err < 0) + exit(1); + + err = avcodec_open2(ist->dec_ctx, NULL, NULL); + if (err < 0) { fprintf(stderr, "Error while opening codec for input stream %d\n", stream->index); + exit(1); + } } - *fmt_ctx_ptr = fmt_ctx; + ifile->fmt_ctx = fmt_ctx; return 0; } -static void close_input_file(AVFormatContext **ctx_ptr) +static void close_input_file(InputFile *ifile) { int i; - AVFormatContext *fmt_ctx = *ctx_ptr; /* close decoder for each stream */ - for (i = 0; i < fmt_ctx->nb_streams; i++) { - AVStream *stream = fmt_ctx->streams[i]; + for (i = 0; i < ifile->nb_streams; i++) { + InputStream *ist = &ifile->streams[i]; - avcodec_close(stream->codec); + avcodec_free_context(&ist->dec_ctx); } - avformat_close_input(ctx_ptr); + + av_freep(&ifile->streams); + ifile->nb_streams = 0; + + avformat_close_input(&ifile->fmt_ctx); } static int probe_file(const char *filename) { - AVFormatContext *fmt_ctx; + InputFile ifile; int ret, i; - if ((ret = open_input_file(&fmt_ctx, filename))) + ret = open_input_file(&ifile, filename); + if (ret < 0) return ret; if (do_show_format) - show_format(fmt_ctx); + show_format(&ifile); if (do_show_streams) { - probe_array_header("streams"); - for (i = 0; i < fmt_ctx->nb_streams; i++) - show_stream(fmt_ctx, i); - probe_array_footer("streams"); + probe_array_header("streams", 0); + for (i = 0; i < ifile.nb_streams; i++) + show_stream(&ifile, &ifile.streams[i]); + probe_array_footer("streams", 0); } if (do_show_packets) - show_packets(fmt_ctx); + show_packets(&ifile); - close_input_file(&fmt_ctx); + close_input_file(&ifile); return 0; } @@ -814,6 +964,7 @@ static int opt_output_format(void *optctx, const char *opt, const char *arg) octx.print_header = ini_print_header; octx.print_footer = ini_print_footer; octx.print_array_header = ini_print_array_header; + octx.print_array_footer = ini_print_array_footer; octx.print_object_header = ini_print_object_header; octx.print_integer = ini_print_integer; @@ -936,6 +1087,7 @@ int main(int argc, char **argv) octx.print_footer = ini_print_footer; octx.print_array_header = ini_print_array_header; + octx.print_array_footer = ini_print_array_footer; octx.print_object_header = ini_print_object_header; octx.print_integer = ini_print_integer; @@ -961,8 +1113,9 @@ int main(int argc, char **argv) ret = probe_file(input_filename); probe_footer(); avio_flush(probe_out); - avio_close(probe_out); - + av_freep(&probe_out); + av_freep(&buffer); + uninit_opts(); avformat_network_deinit(); return ret; diff --git a/cmdutils.c b/cmdutils.c index 3415c0f..b0445eb 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -45,8 +45,8 @@ #include "libavutil/dict.h" #include "libavutil/opt.h" #include "libavutil/cpu.h" +#include "avversion.h" #include "cmdutils.h" -#include "version.h" #if CONFIG_NETWORK #include "libavformat/network.h" #endif @@ -58,7 +58,7 @@ struct SwsContext *sws_opts; AVDictionary *format_opts, *codec_opts, *resample_opts; -static const int this_year = 2014; +static const int this_year = 2017; void init_opts(void) { @@ -261,10 +261,14 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, if (po->flags & OPT_SPEC) { SpecifierOpt **so = dst; char *p = strchr(opt, ':'); + char *str; dstcount = (int *)(so + 1); *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); - (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : ""); + str = av_strdup(p ? p + 1 : ""); + if (!str) + return AVERROR(ENOMEM); + (*so)[*dstcount - 1].specifier = str; dst = &(*so)[*dstcount - 1].u; } @@ -272,6 +276,8 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, char *str; str = av_strdup(arg); av_freep(dst); + if (!str) + return AVERROR(ENOMEM); *(char **)dst = str; } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); @@ -718,6 +724,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) { "info" , AV_LOG_INFO }, { "verbose", AV_LOG_VERBOSE }, { "debug" , AV_LOG_DEBUG }, + { "trace" , AV_LOG_TRACE }, }; char *tail; int level; @@ -970,15 +977,46 @@ static void print_codec(const AVCodec *c) printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name, c->long_name ? c->long_name : ""); + printf(" General capabilities: "); + if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND) + printf("horizband "); + if (c->capabilities & AV_CODEC_CAP_DR1) + printf("dr1 "); + if (c->capabilities & AV_CODEC_CAP_TRUNCATED) + printf("trunc "); + if (c->capabilities & AV_CODEC_CAP_DELAY) + printf("delay "); + if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) + printf("small "); + if (c->capabilities & AV_CODEC_CAP_SUBFRAMES) + printf("subframes "); + if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL) + printf("exp "); + if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF) + printf("chconf "); + if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE) + printf("paramchange "); + if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) + printf("variable "); + if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_AUTO_THREADS)) + printf("threads "); + if (!c->capabilities) + printf("none"); + printf("\n"); + if (c->type == AVMEDIA_TYPE_VIDEO) { printf(" Threading capabilities: "); - switch (c->capabilities & (CODEC_CAP_FRAME_THREADS | - CODEC_CAP_SLICE_THREADS)) { - case CODEC_CAP_FRAME_THREADS | - CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; - case CODEC_CAP_FRAME_THREADS: printf("frame"); break; - case CODEC_CAP_SLICE_THREADS: printf("slice"); break; - default: printf("no"); break; + switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_AUTO_THREADS)) { + case AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; + case AV_CODEC_CAP_FRAME_THREADS: printf("frame"); break; + case AV_CODEC_CAP_SLICE_THREADS: printf("slice"); break; + case AV_CODEC_CAP_AUTO_THREADS : printf("auto"); break; + default: printf("none"); break; } printf("\n"); } @@ -1108,9 +1146,9 @@ static void print_codecs(int encoder) while ((codec = next_codec_for_id(desc->id, codec, encoder))) { printf("%c", get_media_type_char(desc->type)); - printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : "."); - printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : "."); - printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : "."); + printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : "."); + printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : "."); + printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : "."); printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); if (strcmp(codec->name, desc->name)) @@ -1135,10 +1173,11 @@ int show_encoders(void *optctx, const char *opt, const char *arg) int show_bsfs(void *optctx, const char *opt, const char *arg) { - AVBitStreamFilter *bsf = NULL; + const AVBitStreamFilter *bsf = NULL; + void *opaque = NULL; printf("Bitstream filters:\n"); - while ((bsf = av_bitstream_filter_next(bsf))) + while ((bsf = av_bsf_next(&opaque))) printf("%s\n", bsf->name); printf("\n"); return 0; @@ -1161,12 +1200,14 @@ int show_protocols(void *optctx, const char *opt, const char *arg) int show_filters(void *optctx, const char *opt, const char *arg) { - const AVFilter av_unused(*filter) = NULL; +#if CONFIG_AVFILTER + const AVFilter *filter = NULL; printf("Filters:\n"); -#if CONFIG_AVFILTER while ((filter = avfilter_next(filter))) printf("%-16s %s\n", filter->name, filter->description); +#else + printf("No filters available: libavfilter disabled\n"); #endif return 0; } @@ -1348,6 +1389,8 @@ int show_help(void *optctx, const char *opt, const char *arg) av_log_set_callback(log_callback_help); topic = av_strdup(arg ? arg : ""); + if (!topic) + return AVERROR(ENOMEM); par = strchr(topic, '='); if (par) *par++ = 0; @@ -1385,61 +1428,6 @@ int read_yesno(void) return yesno; } -int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) -{ - int ret; - FILE *f = fopen(filename, "rb"); - - if (!f) { - av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, - strerror(errno)); - return AVERROR(errno); - } - - ret = fseek(f, 0, SEEK_END); - if (ret == -1) { - ret = AVERROR(errno); - goto out; - } - - ret = ftell(f); - if (ret < 0) { - ret = AVERROR(errno); - goto out; - } - *size = ret; - - ret = fseek(f, 0, SEEK_SET); - if (ret == -1) { - ret = AVERROR(errno); - goto out; - } - - *bufptr = av_malloc(*size + 1); - if (!*bufptr) { - av_log(NULL, AV_LOG_ERROR, "Could not allocate file buffer\n"); - ret = AVERROR(ENOMEM); - goto out; - } - ret = fread(*bufptr, 1, *size, f); - if (ret < *size) { - av_free(*bufptr); - if (ferror(f)) { - av_log(NULL, AV_LOG_ERROR, "Error while reading file '%s': %s\n", - filename, strerror(errno)); - ret = AVERROR(errno); - } else - ret = AVERROR_EOF; - } else { - ret = 0; - (*bufptr)[(*size)++] = '\0'; - } - -out: - fclose(f); - return ret; -} - void init_pts_correction(PtsCorrectionContext *ctx) { ctx->num_faulty_pts = ctx->num_faulty_dts = 0; @@ -1517,12 +1505,12 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; default: av_assert0(0); } - if (type != st->codec->codec_type) + if (type != st->codecpar->codec_type) return 0; if (*spec++ == ':') { /* possibly followed by :index */ int i, index = strtol(spec, NULL, 0); for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->codec->codec_type == type && index-- == 0) + if (s->streams[i]->codecpar->codec_type == type && index-- == 0) return i == st->index; return 0; } @@ -1577,6 +1565,28 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) av_freep(&key); return ret; + } else if (*spec == 'u') { + AVCodecParameters *par = st->codecpar; + int val; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + val = par->sample_rate && par->channels; + if (par->format == AV_SAMPLE_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_VIDEO: + val = par->width && par->height; + if (par->format == AV_PIX_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_UNKNOWN: + val = 0; + break; + default: + val = 1; + break; + } + return par->codec_id != AV_CODEC_ID_NONE && val != 0; } else if (!*spec) /* empty specifier, matches everything */ return 1; @@ -1598,7 +1608,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, codec = s->oformat ? avcodec_find_encoder(codec_id) : avcodec_find_decoder(codec_id); - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: prefix = 'v'; flags |= AV_OPT_FLAG_VIDEO_PARAM; @@ -1655,7 +1665,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, return NULL; } for (i = 0; i < s->nb_streams; i++) - opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, + opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, s, s->streams[i], NULL); return opts; } diff --git a/cmdutils.h b/cmdutils.h index d90ad45..45d9858 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -460,18 +460,6 @@ int show_sample_fmts(void *optctx, const char *opt, const char *arg); */ int read_yesno(void); -/** - * Read the file with name filename, and put its content in a newly - * allocated 0-terminated buffer. - * - * @param filename file to read from - * @param bufptr location where pointer to buffer is returned - * @param size location where size of buffer is returned - * @return 0 in case of success, a negative value corresponding to an - * AVERROR error code in case of failure. - */ -int cmdutils_read_file(const char *filename, char **bufptr, size_t *size); - typedef struct PtsCorrectionContext { int64_t num_faulty_pts; /// Number of incorrect PTS values so far int64_t num_faulty_dts; /// Number of incorrect DTS values so far diff --git a/common.mak b/common.mak index 9244fd3..8f6a61f 100644 --- a/common.mak +++ b/common.mak @@ -15,8 +15,8 @@ LDLIBS = $(FFLIBS:%=%$(BUILDSUF)) FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(EXTRALIBS) OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) -TESTOBJS := $(TESTOBJS:%=$(SUBDIR)%) $(TESTPROGS:%=$(SUBDIR)%-test.o) -TESTPROGS := $(TESTPROGS:%=$(SUBDIR)%-test$(EXESUF)) +TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) +TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF)) HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o) HOSTPROGS := $(HOSTPROGS:%=$(SUBDIR)%$(HOSTEXESUF)) TOOLS += $(TOOLS-yes) @@ -24,8 +24,9 @@ TOOLOBJS := $(TOOLS:%=tools/%.o) TOOLS := $(TOOLS:%=tools/%$(EXESUF)) HEADERS += $(HEADERS-yes) -PATH_LIBNAME = $(foreach NAME,$(1),lib$(NAME)/$($(CONFIG_SHARED:yes=S)LIBNAME)) -DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib))) +PATH_LIBNAME = $(foreach NAME,$(1),lib$(NAME)/$($(2)LIBNAME)) +DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib),$(CONFIG_SHARED:yes=S))) +STATIC_DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib))) SRC_DIR := $(SRC_PATH)/lib$(NAME) ALLHEADERS := $(subst $(SRC_DIR)/,$(SUBDIR),$(wildcard $(SRC_DIR)/*.h $(SRC_DIR)/$(ARCH)/*.h)) @@ -51,15 +52,13 @@ $(TOOLOBJS): | tools OBJDIRS := $(OBJDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(TESTOBJS)) -CLEANSUFFIXES = *.d *.o *~ *.h.c *.map *.ver *.gcno *.gcda +CLEANSUFFIXES = *.d *.o *~ *.h.c *.gcda *.gcno *.map *.ver DISTCLEANSUFFIXES = *.pc LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a define RULES clean:: - $(RM) $(OBJS) $(OBJS:.o=.d) - $(RM) $(HOSTPROGS) - $(RM) $(TOOLS) + $(RM) $(HOSTPROGS) $(TESTPROGS) $(TOOLS) endef $(eval $(RULES)) diff --git a/compat/dispatch_semaphore/semaphore.h b/compat/dispatch_semaphore/semaphore.h new file mode 100644 index 0000000..2461daf --- /dev/null +++ b/compat/dispatch_semaphore/semaphore.h @@ -0,0 +1,42 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H +#define COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H + +#include +#include + +#define sem_t dispatch_semaphore_t +#define sem_post(psem) dispatch_semaphore_signal(*psem) +#define sem_wait(psem) dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER) +#define sem_timedwait(psem, val) dispatch_semaphore_wait(*psem, dispatch_walltime(val, 0)) +#define sem_destroy(psem) dispatch_release(*psem) + +static inline int compat_sem_init(dispatch_semaphore_t *psem, + int unused, int val) +{ + int ret = !!(*psem = dispatch_semaphore_create(val)) - 1; + if (ret < 0) + errno = ENOMEM; + return ret; +} + +#define sem_init compat_sem_init + +#endif /* COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H */ diff --git a/compat/solaris/make_sunver.pl b/compat/solaris/make_sunver.pl new file mode 100755 index 0000000..929bdda --- /dev/null +++ b/compat/solaris/make_sunver.pl @@ -0,0 +1,352 @@ +#!/usr/bin/perl -w + +# make_sunver.pl +# +# Copyright (C) 2010, 2011, 2012, 2013 +# Free Software Foundation, Inc. +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that 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; see the file COPYING.GPLv3. If not see +# . + +# This script takes at least two arguments, a GNU style version script and +# a list of object and archive files, and generates a corresponding Sun +# style version script as follows: +# +# Each glob pattern, C++ mangled pattern or literal in the input script is +# matched against all global symbols in the input objects, emitting those +# that matched (or nothing if no match was found). +# A comment with the original pattern and its type is left in the output +# file to make it easy to understand the matches. +# +# It uses elfdump when present (native), GNU readelf otherwise. +# It depends on the GNU version of c++filt, since it must understand the +# GNU mangling style. + +use FileHandle; +use IPC::Open2; + +# Enforce C locale. +$ENV{'LC_ALL'} = "C"; +$ENV{'LANG'} = "C"; + +# Input version script, GNU style. +my $symvers = shift; + +########## +# Get all the symbols from the library, match them, and add them to a hash. + +my %sym_hash = (); + +# List of objects and archives to process. +my @OBJECTS = (); + +# List of shared objects to omit from processing. +my @SHAREDOBJS = (); + +# Filter out those input archives that have corresponding shared objects to +# avoid adding all symbols matched in the archive to the output map. +foreach $file (@ARGV) { + if (($so = $file) =~ s/\.a$/.so/ && -e $so) { + printf STDERR "omitted $file -> $so\n"; + push (@SHAREDOBJS, $so); + } else { + push (@OBJECTS, $file); + } +} + +# We need to detect and ignore hidden symbols. Solaris nm can only detect +# this in the harder to parse default output format, and GNU nm not at all, +# so use elfdump -s in the native case and GNU readelf -s otherwise. +# GNU objdump -t cannot be used since it produces a variable number of +# columns. + +# The path to elfdump. +my $elfdump = "/usr/ccs/bin/elfdump"; + +if (-f $elfdump) { + open ELFDUMP,$elfdump.' -s '.(join ' ',@OBJECTS).'|' or die $!; + my $skip_arsym = 0; + + while () { + chomp; + + # Ignore empty lines. + if (/^$/) { + # End of archive symbol table, stop skipping. + $skip_arsym = 0 if $skip_arsym; + next; + } + + # Keep skipping until end of archive symbol table. + next if ($skip_arsym); + + # Ignore object name header for individual objects and archives. + next if (/:$/); + + # Ignore table header lines. + next if (/^Symbol Table Section:/); + next if (/index.*value.*size/); + + # Start of archive symbol table: start skipping. + if (/^Symbol Table: \(archive/) { + $skip_arsym = 1; + next; + } + + # Split table. + (undef, undef, undef, undef, $bind, $oth, undef, $shndx, $name) = split; + + # Error out for unknown input. + die "unknown input line:\n$_" unless defined($bind); + + # Ignore local symbols. + next if ($bind eq "LOCL"); + # Ignore hidden symbols. + next if ($oth eq "H"); + # Ignore undefined symbols. + next if ($shndx eq "UNDEF"); + # Error out for unhandled cases. + if ($bind !~ /^(GLOB|WEAK)/ or $oth ne "D") { + die "unhandled symbol:\n$_"; + } + + # Remember symbol. + $sym_hash{$name}++; + } + close ELFDUMP or die "$elfdump error"; +} else { + open READELF, 'readelf -s -W '.(join ' ',@OBJECTS).'|' or die $!; + # Process each symbol. + while () { + chomp; + + # Ignore empty lines. + next if (/^$/); + + # Ignore object name header. + next if (/^File: .*$/); + + # Ignore table header lines. + next if (/^Symbol table.*contains.*:/); + next if (/Num:.*Value.*Size/); + + # Split table. + (undef, undef, undef, undef, $bind, $vis, $ndx, $name) = split; + + # Error out for unknown input. + die "unknown input line:\n$_" unless defined($bind); + + # Ignore local symbols. + next if ($bind eq "LOCAL"); + # Ignore hidden symbols. + next if ($vis eq "HIDDEN"); + # Ignore undefined symbols. + next if ($ndx eq "UND"); + # Error out for unhandled cases. + if ($bind !~ /^(GLOBAL|WEAK)/ or $vis ne "DEFAULT") { + die "unhandled symbol:\n$_"; + } + + # Remember symbol. + $sym_hash{$name}++; + } + close READELF or die "readelf error"; +} + +########## +# The various types of glob patterns. +# +# A glob pattern that is to be applied to the demangled name: 'cxx'. +# A glob patterns that applies directly to the name in the .o files: 'glob'. +# This pattern is ignored; used for local variables (usually just '*'): 'ign'. + +# The type of the current pattern. +my $glob = 'glob'; + +# We're currently inside `extern "C++"', which Sun ld doesn't understand. +my $in_extern = 0; + +# The c++filt command to use. This *must* be GNU c++filt; the Sun Studio +# c++filt doesn't handle the GNU mangling style. +my $cxxfilt = $ENV{'CXXFILT'} || "c++filt"; + +# The current version name. +my $current_version = ""; + +# Was there any attempt to match a symbol to this version? +my $matches_attempted; + +# The number of versions which matched this symbol. +my $matched_symbols; + +open F,$symvers or die $!; + +# Print information about generating this file +print "# This file was generated by make_sunver.pl. DO NOT EDIT!\n"; +print "# It was generated by:\n"; +printf "# %s %s %s\n", $0, $symvers, (join ' ',@ARGV); +printf "# Omitted archives with corresponding shared libraries: %s\n", + (join ' ', @SHAREDOBJS) if $#SHAREDOBJS >= 0; +print "#\n\n"; + +print "\$mapfile_version 2\n"; + +while () { + # Lines of the form '};' + if (/^([ \t]*)(\}[ \t]*;[ \t]*)$/) { + $glob = 'glob'; + if ($in_extern) { + $in_extern--; + print "$1##$2\n"; + } else { + print; + } + next; + } + + # Lines of the form '} SOME_VERSION_NAME_1.0;' + if (/^[ \t]*\}[ \tA-Z0-9_.a-z]+;[ \t]*$/) { + $glob = 'glob'; + # We tried to match symbols agains this version, but none matched. + # Emit dummy hidden symbol to avoid marking this version WEAK. + if ($matches_attempted && $matched_symbols == 0) { + print " hidden:\n"; + print " .force_WEAK_off_$current_version = DATA S0x0 V0x0;\n"; + } + print; next; + } + + # Comment and blank lines + if (/^[ \t]*\#/) { print; next; } + if (/^[ \t]*$/) { print; next; } + + # Lines of the form '{' + if (/^([ \t]*){$/) { + if ($in_extern) { + print "$1##{\n"; + } else { + print; + } + next; + } + + # Lines of the form 'SOME_VERSION_NAME_1.1 {' + if (/^([A-Z0-9_.]+)[ \t]+{$/) { + # Record version name. + $current_version = $1; + # Reset match attempts, #matched symbols for this version. + $matches_attempted = 0; + $matched_symbols = 0; + print "SYMBOL_VERSION $1 {\n"; + next; + } + + # Ignore 'global:' + if (/^[ \t]*global:$/) { print; next; } + + # After 'local:', globs should be ignored, they won't be exported. + if (/^[ \t]*local:$/) { + $glob = 'ign'; + print; + next; + } + + # After 'extern "C++"', globs are C++ patterns + if (/^([ \t]*)(extern \"C\+\+\"[ \t]*)$/) { + $in_extern++; + $glob = 'cxx'; + # Need to comment, Sun ld cannot handle this. + print "$1##$2\n"; next; + } + + # Chomp newline now we're done with passing through the input file. + chomp; + + # Catch globs. Note that '{}' is not allowed in globs by this script, + # so only '*' and '[]' are available. + if (/^([ \t]*)([^ \t;{}#]+);?[ \t]*$/) { + my $ws = $1; + my $ptn = $2; + # Turn the glob into a regex by replacing '*' with '.*', '?' with '.'. + # Keep $ptn so we can still print the original form. + ($pattern = $ptn) =~ s/\*/\.\*/g; + $pattern =~ s/\?/\./g; + + if ($glob eq 'ign') { + # We're in a local: * section; just continue. + print "$_\n"; + next; + } + + # Print the glob commented for human readers. + print "$ws##$ptn ($glob)\n"; + # We tried to match a symbol to this version. + $matches_attempted++; + + if ($glob eq 'glob') { + my %ptn_syms = (); + + # Match ptn against symbols in %sym_hash. + foreach my $sym (keys %sym_hash) { + # Maybe it matches one of the patterns based on the symbol in + # the .o file. + $ptn_syms{$sym}++ if ($sym =~ /^$pattern$/); + } + + foreach my $sym (sort keys(%ptn_syms)) { + $matched_symbols++; + print "$ws$sym;\n"; + } + } elsif ($glob eq 'cxx') { + my %dem_syms = (); + + # Verify that we're actually using GNU c++filt. Other versions + # most likely cannot handle GNU style symbol mangling. + my $cxxout = `$cxxfilt --version 2>&1`; + $cxxout =~ m/GNU/ or die "$0 requires GNU c++filt to function"; + + # Talk to c++filt through a pair of file descriptors. + # Need to start a fresh instance per pattern, otherwise the + # process grows to 500+ MB. + my $pid = open2(*FILTIN, *FILTOUT, $cxxfilt) or die $!; + + # Match ptn against symbols in %sym_hash. + foreach my $sym (keys %sym_hash) { + # No? Well, maybe its demangled form matches one of those + # patterns. + printf FILTOUT "%s\n",$sym; + my $dem = ; + chomp $dem; + $dem_syms{$sym}++ if ($dem =~ /^$pattern$/); + } + + close FILTOUT or die "c++filt error"; + close FILTIN or die "c++filt error"; + # Need to wait for the c++filt process to avoid lots of zombies. + waitpid $pid, 0; + + foreach my $sym (sort keys(%dem_syms)) { + $matched_symbols++; + print "$ws$sym;\n"; + } + } else { + # No? Well, then ignore it. + } + next; + } + # Important sanity check. This script can't handle lots of formats + # that GNU ld can, so be sure to error out if one is seen! + die "strange line `$_'"; +} +close F; diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index d0b90e8..2fe2a5a 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -39,6 +39,11 @@ #include #include +#if _WIN32_WINNT < 0x0600 && defined(__MINGW32__) +#undef MemoryBarrier +#define MemoryBarrier __sync_synchronize +#endif + #include "libavutil/attributes.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -54,35 +59,17 @@ typedef struct pthread_t { * not mutexes */ typedef CRITICAL_SECTION pthread_mutex_t; -/* This is the CONDITIONAL_VARIABLE typedef for using Window's native - * conditional variables on kernels 6.0+. - * MinGW does not currently have this typedef. */ +/* This is the CONDITION_VARIABLE typedef for using Windows' native + * conditional variables on kernels 6.0+. */ +#if HAVE_CONDITION_VARIABLE_PTR +typedef CONDITION_VARIABLE pthread_cond_t; +#else typedef struct pthread_cond_t { - void *ptr; + void *Ptr; } pthread_cond_t; +#endif -/* function pointers to conditional variable API on windows 6.0+ kernels */ -#if _WIN32_WINNT < 0x0600 -static void (WINAPI *cond_broadcast)(pthread_cond_t *cond); -static void (WINAPI *cond_init)(pthread_cond_t *cond); -static void (WINAPI *cond_signal)(pthread_cond_t *cond); -static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex, - DWORD milliseconds); -#else -#define cond_init InitializeConditionVariable -#define cond_broadcast WakeAllConditionVariable -#define cond_signal WakeConditionVariable -#define cond_wait SleepConditionVariableCS - -#define CreateEvent(a, reset, init, name) \ - CreateEventEx(a, name, \ - (reset ? CREATE_EVENT_MANUAL_RESET : 0) | \ - (init ? CREATE_EVENT_INITIAL_SET : 0), \ - EVENT_ALL_ACCESS) -// CreateSemaphoreExA seems to be desktop-only, but as long as we don't -// use named semaphores, it doesn't matter if we use the W version. -#define CreateSemaphore(a, b, c, d) \ - CreateSemaphoreExW(a, b, c, d, 0, SEMAPHORE_ALL_ACCESS) +#if _WIN32_WINNT >= 0x0600 #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) #define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) #endif @@ -135,8 +122,113 @@ static inline int pthread_mutex_unlock(pthread_mutex_t *m) return 0; } +#if _WIN32_WINNT >= 0x0600 + +typedef INIT_ONCE pthread_once_t; +#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT + +static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) +{ + BOOL pending = FALSE; + InitOnceBeginInitialize(once_control, 0, &pending, NULL); + if (pending) + init_routine(); + InitOnceComplete(once_control, 0, NULL); + return 0; +} + +static inline void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) +{ + InitializeConditionVariable(cond); +} + +/* native condition variables do not destroy */ +static inline void pthread_cond_destroy(pthread_cond_t *cond) +{ + return; +} + +static inline void pthread_cond_broadcast(pthread_cond_t *cond) +{ + WakeAllConditionVariable(cond); +} + +static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + SleepConditionVariableCS(cond, mutex, INFINITE); + return 0; +} + +static inline void pthread_cond_signal(pthread_cond_t *cond) +{ + WakeConditionVariable(cond); +} + +#else // _WIN32_WINNT < 0x0600 + +/* atomic init state of dynamically loaded functions */ +static LONG w32thread_init_state = 0; +static av_unused void w32thread_init(void); + +/* for pre-Windows 6.0 platforms, define INIT_ONCE struct, + * compatible to the one used in the native API */ + +typedef union pthread_once_t { + void * Ptr; ///< For the Windows 6.0+ native functions + LONG state; ///< For the pre-Windows 6.0 compat code +} pthread_once_t; + +#define PTHREAD_ONCE_INIT {0} + +/* function pointers to init once API on windows 6.0+ kernels */ +static BOOL (WINAPI *initonce_begin)(pthread_once_t *lpInitOnce, DWORD dwFlags, BOOL *fPending, void **lpContext); +static BOOL (WINAPI *initonce_complete)(pthread_once_t *lpInitOnce, DWORD dwFlags, void *lpContext); + +/* pre-Windows 6.0 compat using a spin-lock */ +static inline void w32thread_once_fallback(LONG volatile *state, void (*init_routine)(void)) +{ + switch (InterlockedCompareExchange(state, 1, 0)) { + /* Initial run */ + case 0: + init_routine(); + InterlockedExchange(state, 2); + break; + /* Another thread is running init */ + case 1: + while (1) { + MemoryBarrier(); + if (*state == 2) + break; + Sleep(0); + } + break; + /* Initialization complete */ + case 2: + break; + } +} + +static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) +{ + w32thread_once_fallback(&w32thread_init_state, w32thread_init); + + /* Use native functions on Windows 6.0+ */ + if (initonce_begin && initonce_complete) { + BOOL pending = FALSE; + initonce_begin(once_control, 0, &pending, NULL); + if (pending) + init_routine(); + initonce_complete(once_control, 0, NULL); + return 0; + } + + w32thread_once_fallback(&once_control->state, init_routine); + return 0; +} + /* for pre-Windows 6.0 platforms we need to define and use our own condition * variable and api */ + typedef struct win32_cond_t { pthread_mutex_t mtx_broadcast; pthread_mutex_t mtx_waiter_count; @@ -146,9 +238,19 @@ typedef struct win32_cond_t { volatile int is_broadcast; } win32_cond_t; +/* function pointers to conditional variable API on windows 6.0+ kernels */ +static void (WINAPI *cond_broadcast)(pthread_cond_t *cond); +static void (WINAPI *cond_init)(pthread_cond_t *cond); +static void (WINAPI *cond_signal)(pthread_cond_t *cond); +static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex, + DWORD milliseconds); + static av_unused void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) { win32_cond_t *win32_cond = NULL; + + w32thread_once_fallback(&w32thread_init_state, w32thread_init); + if (cond_init) { cond_init(cond); return; @@ -158,7 +260,7 @@ static av_unused void pthread_cond_init(pthread_cond_t *cond, const void *unused win32_cond = av_mallocz(sizeof(win32_cond_t)); if (!win32_cond) return; - cond->ptr = win32_cond; + cond->Ptr = win32_cond; win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); if (!win32_cond->semaphore) return; @@ -172,7 +274,7 @@ static av_unused void pthread_cond_init(pthread_cond_t *cond, const void *unused static av_unused void pthread_cond_destroy(pthread_cond_t *cond) { - win32_cond_t *win32_cond = cond->ptr; + win32_cond_t *win32_cond = cond->Ptr; /* native condition variables do not destroy */ if (cond_init) return; @@ -183,12 +285,12 @@ static av_unused void pthread_cond_destroy(pthread_cond_t *cond) pthread_mutex_destroy(&win32_cond->mtx_waiter_count); pthread_mutex_destroy(&win32_cond->mtx_broadcast); av_freep(&win32_cond); - cond->ptr = NULL; + cond->Ptr = NULL; } static av_unused void pthread_cond_broadcast(pthread_cond_t *cond) { - win32_cond_t *win32_cond = cond->ptr; + win32_cond_t *win32_cond = cond->Ptr; int have_waiter; if (cond_broadcast) { @@ -219,7 +321,7 @@ static av_unused void pthread_cond_broadcast(pthread_cond_t *cond) static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { - win32_cond_t *win32_cond = cond->ptr; + win32_cond_t *win32_cond = cond->Ptr; int last_waiter; if (cond_wait) { cond_wait(cond, mutex, INFINITE); @@ -251,7 +353,7 @@ static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu static av_unused void pthread_cond_signal(pthread_cond_t *cond) { - win32_cond_t *win32_cond = cond->ptr; + win32_cond_t *win32_cond = cond->Ptr; int have_waiter; if (cond_signal) { cond_signal(cond); @@ -273,6 +375,7 @@ static av_unused void pthread_cond_signal(pthread_cond_t *cond) pthread_mutex_unlock(&win32_cond->mtx_broadcast); } +#endif static av_unused void w32thread_init(void) { @@ -287,6 +390,10 @@ static av_unused void w32thread_init(void) (void*)GetProcAddress(kernel_dll, "WakeConditionVariable"); cond_wait = (void*)GetProcAddress(kernel_dll, "SleepConditionVariableCS"); + initonce_begin = + (void*)GetProcAddress(kernel_dll, "InitOnceBeginInitialize"); + initonce_complete = + (void*)GetProcAddress(kernel_dll, "InitOnceComplete"); #endif } diff --git a/compat/windows/mslink b/compat/windows/mslink new file mode 100755 index 0000000..07b2b3e --- /dev/null +++ b/compat/windows/mslink @@ -0,0 +1,9 @@ +#!/bin/sh + +LINK_EXE_PATH=$(dirname "$(command -v cl)")/link +if [ -x "$LINK_EXE_PATH" ]; then + "$LINK_EXE_PATH" $@ +else + link $@ +fi +exit $? diff --git a/configure b/configure index 34ec7a4..660b062 100755 --- a/configure +++ b/configure @@ -86,6 +86,7 @@ Standard options: --shlibdir=DIR install shared libs in DIR [PREFIX/lib] --incdir=DIR install includes in DIR [PREFIX/include] --mandir=DIR install man page in DIR [PREFIX/share/man] + --enable-rpath use rpath when linking programs [USE WITH CARE] Licensing options: --enable-gpl allow use of GPL code, the resulting libs @@ -129,12 +130,7 @@ Component options: --disable-mdct disable MDCT code --disable-rdft disable RDFT code --disable-fft disable FFT code - -Hardware accelerators: - --enable-dxva2 enable DXVA2 code - --enable-vaapi enable VAAPI code - --enable-vda enable VDA code - --enable-vdpau enable VDPAU code + --disable-faan disable floating point AAN (I)DCT code Individual component options: --disable-everything disable all components listed below @@ -174,45 +170,79 @@ Individual component options: --disable-filters disable all filters External library support: - --enable-avisynth enable reading of AviSynth script files [no] - --enable-bzlib enable bzlib [autodetect] - --enable-frei0r enable frei0r video filtering - --enable-gnutls enable gnutls [no] - --enable-libbs2b enable bs2b DSP library [no] - --enable-libcdio enable audio CD grabbing with libcdio - --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394 - and libraw1394 [no] - --enable-libfaac enable AAC encoding via libfaac [no] - --enable-libfdk-aac enable AAC de/encoding via libfdk-aac [no] - --enable-libfreetype enable libfreetype [no] - --enable-libgsm enable GSM de/encoding via libgsm [no] - --enable-libilbc enable iLBC de/encoding via libilbc [no] - --enable-libmp3lame enable MP3 encoding via libmp3lame [no] - --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] - --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] - --enable-libopencv enable video filtering via libopencv [no] - --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] - --enable-libopus enable Opus de/encoding via libopus [no] - --enable-libpulse enable Pulseaudio input via libpulse [no] - --enable-librtmp enable RTMP[E] support via librtmp [no] - --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no] - --enable-libspeex enable Speex de/encoding via libspeex [no] - --enable-libtheora enable Theora encoding via libtheora [no] - --enable-libtwolame enable MP2 encoding via libtwolame [no] - --enable-libvo-aacenc enable AAC encoding via libvo-aacenc [no] - --enable-libvo-amrwbenc enable AMR-WB encoding via libvo-amrwbenc [no] - --enable-libvorbis enable Vorbis encoding via libvorbis [no] - --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] - --enable-libwavpack enable wavpack encoding via libwavpack [no] - --enable-libwebp enable WebP encoding via libwebp [no] - --enable-libx264 enable H.264 encoding via x264 [no] - --enable-libx265 enable HEVC encoding via x265 [no] - --enable-libxavs enable AVS encoding via xavs [no] - --enable-libxvid enable Xvid encoding via xvidcore, - native MPEG-4/Xvid encoder exists [no] - --enable-openssl enable openssl [no] - --enable-x11grab enable X11 grabbing [no] - --enable-zlib enable zlib [autodetect] + + Using any of the following switches will allow Libav to link to the + corresponding external library. All the components depending on that library + will become enabled, if all their other dependencies are met and they are not + explicitly disabled. E.g. --enable-libwavpack will enable linking to + libwavpack and allow the libwavpack encoder to be built, unless it is + specifically disabled with --disable-encoder=libwavpack. + + Note that only the system libraries are auto-detected. All the other external + libraries must be explicitly enabled. + + Also note that the following help text describes the purpose of the libraries + themselves, not all their features will necessarily be usable by Libav. + + --enable-avisynth video frameserver + --enable-bzlib bzip2 compression [autodetect] + --enable-frei0r video filtering plugins + --enable-gnutls crypto + --enable-libbs2b Bauer stereophonic-to-binaural DSP + --enable-libcdio audio CD input + --enable-libdc1394 IEEE 1394/Firewire camera input + --enable-libdcadec DCA audio decoding + --enable-libfaac AAC audio encoding + --enable-libfdk-aac AAC audio encoding/decoding + --enable-libfontconfig font configuration and management + --enable-libfreetype font rendering + --enable-libgsm GSM audio encoding/decoding + --enable-libhdcd HDCD decoding filter + --enable-libilbc ILBC audio encoding/decoding + --enable-libkvazaar HEVC video encoding + --enable-libmp3lame MP3 audio encoding + --enable-libopencore-amrnb AMR-NB audio encoding/decoding + --enable-libopencore-amrwb AMR-WB audio decoding + --enable-libopencv computer vision + --enable-libopenh264 H.264 video encoding/decoding + --enable-libopenjpeg JPEG 2000 image encoding/decoding + --enable-libopus Opus audio encoding/decoding + --enable-libpulse Pulseaudio sound server + --enable-librtmp RTMP streaming + --enable-libschroedinger Dirac video encoding/decoding + --enable-libsnappy snappy compression + --enable-libspeex Speex audio encoding/decoding + --enable-libtheora Theora video encoding/decoding + --enable-libtwolame MP2 audio encoding + --enable-libvo-aacenc AAC audio encoding + --enable-libvo-amrwbenc AMR-WB audio encoding + --enable-libvorbis Vorbis audio encoding/decoding + --enable-libvpx VP* video encoding/decoding + --enable-libwavpack Wavpack audio encoding/decoding + --enable-libwebp WebP image encoding/decoding + --enable-libx264 H.264 video encoding + --enable-libx265 HEVC video encoding + --enable-libxavs Chinese AVS video encoding + --enable-libxcb X window system protocol communication + --enable-libxcb-shm X11 shm communication [auto] + --enable-libxcb-xfixes X11 mouse rendering [auto] + --enable-libxvid MPEG-4 ASP video encoding + --enable-openssl crypto + --enable-zlib compression [autodetect] + + The following libraries provide various hardware acceleration features: + --enable-cuda Nvidia CUDA (dynamically linked) + --enable-d3d11va Microsoft Direct3D 11 video acceleration [auto] + --enable-dxva2 Microsoft DirectX 9 video acceleration [auto] + --enable-libmfx Intel MediaSDK (AKA Quick Sync Video) + --enable-libnpp Nvidia CUDA processing + --enable-mmal Broadcom Multi-Media Abstraction Layer (Raspberry Pi) + --enable-nvenc Nvidia video encoding + --enable-omx OpenMAX IL + --enable-omx-rpi OpenMAX IL for Raspberry Pi + --enable-vaapi Video Acceleration API (mainly Unix/Intel) + --enable-vda Apple Video Decode Acceleration [auto] + --enable-vdpau Nvidia Video Decode and Presentation API for Unix [auto] Toolchain options: --arch=ARCH select architecture [$arch] @@ -231,6 +261,7 @@ Toolchain options: --ar=AR use archive tool AR [$ar_default] --as=AS use assembler AS [$as_default] --cc=CC use C compiler CC [$cc_default] + --objcc=OCC use ObjC compiler OCC [$cc_default] --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --ld=LD use linker LD --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] @@ -243,6 +274,7 @@ Toolchain options: --host-libs=HLIBS use libs HLIBS when linking for host --host-os=OS compiler host OS [$target_os] --extra-cflags=ECFLAGS add ECFLAGS to CFLAGS [$CFLAGS] + --extra-objcflags=FLAGS add FLAGS to OBJCFLAGS [$CFLAGS] --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS [$LDFLAGS] --extra-ldexeflags=ELDFLAGS add ELDFLAGS to LDEXEFLAGS [$LDEXEFLAGS] --extra-libs=ELIBS add ELIBS [$ELIBS] @@ -252,9 +284,11 @@ Toolchain options: --enable-pic build position-independent code --enable-thumb compile for Thumb instruction set --enable-lto use link-time optimization + --env="ENV=override" override the environment variables Advanced options (experts only): --malloc-prefix=PREFIX prefix malloc and related names with PREFIX + --custom-allocator=NAME use a supported custom allocator --disable-symver disable symbol versioning --enable-hardcoded-tables use hardcoded tables instead of runtime generation --disable-safe-bitstream-reader @@ -266,6 +300,8 @@ Advanced options (experts only): Optimization options (experts only): --disable-asm disable all assembly optimizations --disable-altivec disable AltiVec optimizations + --disable-vsx disable VSX optimizations + --disable-power8 disable POWER8 optimizations --disable-amd3dnow disable 3DNow! optimizations --disable-amd3dnowext disable 3DNow! extended optimizations --disable-mmx disable MMX optimizations @@ -308,6 +344,8 @@ Developer options (useful when working on Libav itself): (group) and PROB the probability associated with NAME (default 0.5). --random-seed=VALUE seed value for --enable/disable-random + --disable-valgrind-backtrace do not print a backtrace under Valgrind + (only applies to --disable-optimizations builds) NOTE: Object files are built at the place where configure is launched. EOF @@ -322,7 +360,11 @@ log(){ log_file(){ log BEGIN $1 - pr -n -t $1 >> $logfile + i=1 + while read line; do + printf '%5s %s\n' "${i}" "${line}" + i=$(($i+1)) + done < $1 >> $logfile log END $1 } @@ -639,7 +681,7 @@ print_enabled(){ suf=$1 shift for v; do - enabled $v && printf "%s\n" ${v%$suf}; + enabled $v && printf "%s\n" ${v%$suf} done } @@ -676,6 +718,10 @@ add_asflags(){ append ASFLAGS $($asflags_filter "$@") } +add_objcflags(){ + append OBJCFLAGS $($objcflags_filter "$@") +} + add_ldflags(){ append LDFLAGS $($ldflags_filter "$@") } @@ -730,6 +776,13 @@ check_cc(){ check_cmd $cc $CPPFLAGS $CFLAGS "$@" $CC_C $(cc_o $TMPO) $TMPC } +check_objcc(){ + log check_objcc "$@" + cat > $TMPC + log_file $TMPC + check_cmd $objcc $CPPFLAGS $CFLAGS $OBJCFLAGS "$@" $OBJCC_C $(cc_o $TMPO) $TMPC +} + check_cpp(){ log check_cpp "$@" cat > $TMPC @@ -828,6 +881,19 @@ check_cflags(){ test_cflags "$@" && add_cflags "$@" } +test_objcflags(){ + log test_cflags "$@" + set -- $($cflags_filter "$@") + check_objcc "$@" < $TMPC log_file $TMPC - check_cmd $host_cc $HOSTCPPFLAGS $HOSTCFLAGS "$@" $(hostcc_e $TMPO) $TMPC + check_cmd $host_cc $host_cppflags $host_cflags "$@" $(hostcc_e $TMPO) $TMPC } check_host_cppflags(){ @@ -1111,72 +1177,129 @@ cp_if_changed(){ # CONFIG_LIST contains configurable options, while HAVE_LIST is for # system-dependent things. -COMPONENT_LIST=" +AVCODEC_COMPONENTS=" bsfs decoders - demuxers encoders - filters hwaccels + parsers +" + +AVDEVICE_COMPONENTS=" indevs - muxers outdevs - parsers +" +AVFILTER_COMPONENTS=" + filters +" +AVFORMAT_COMPONENTS=" + demuxers + muxers protocols " +AVRESAMPLE_COMPONENTS="" +AVUTIL_COMPONENTS="" + +COMPONENT_LIST=" + $AVCODEC_COMPONENTS + $AVDEVICE_COMPONENTS + $AVFILTER_COMPONENTS + $AVFORMAT_COMPONENTS + $AVRESAMPLE_COMPONENTS + $AVUTIL_COMPONENTS +" + EXAMPLE_LIST=" avcodec_example filter_audio_example metadata_example output_example + qsvdec_example transcode_aac_example " +HWACCEL_LIBRARY_NONFREE_LIST=" + cuda + libnpp +" +HWACCEL_LIBRARY_LIST=" + $HWACCEL_LIBRARY_NONFREE_LIST + d3d11va + dxva2 + libmfx + mmal + nvenc + omx + vaapi + vda + vdpau +" + +EXTERNAL_LIBRARY_GPL_LIST=" + libcdio + libx264 + libx265 + libxavs + libxvid +" + +EXTERNAL_LIBRARY_NONFREE_LIST=" + libfaac + libfdk_aac + openssl +" + +EXTERNAL_LIBRARY_VERSION3_LIST=" + libopencore_amrnb + libopencore_amrwb + libvo_aacenc + libvo_amrwbenc +" + EXTERNAL_LIBRARY_LIST=" + $EXTERNAL_LIBRARY_GPL_LIST + $EXTERNAL_LIBRARY_NONFREE_LIST + $EXTERNAL_LIBRARY_VERSION3_LIST avisynth bzlib frei0r gnutls libbs2b - libcdio libdc1394 - libfaac - libfdk_aac + libdcadec libfontconfig libfreetype libgsm + libhdcd libilbc + libkvazaar libmp3lame - libopencore_amrnb - libopencore_amrwb libopencv + libopenh264 libopenjpeg libopus libpulse librtmp libschroedinger + libsnappy libspeex libtheora libtwolame - libvo_aacenc - libvo_amrwbenc libvorbis libvpx libwavpack libwebp - libx264 - libx265 - libxavs - libxvid - openssl - x11grab + libxcb + libxcb_shm + libxcb_xfixes zlib " FEATURE_LIST=" gray hardcoded_tables + omx_rpi runtime_cpudetect safe_bitstream_reader shared @@ -1186,13 +1309,6 @@ FEATURE_LIST=" swscale_alpha " -HWACCEL_LIST=" - dxva2 - vaapi - vda - vdpau -" - LIBRARY_LIST=" avcodec avdevice @@ -1219,6 +1335,7 @@ SUBSYSTEM_LIST=" dct doc error_resilience + faan fft lsp lzo @@ -1231,8 +1348,8 @@ CONFIG_LIST=" $COMPONENT_LIST $EXAMPLE_LIST $EXTERNAL_LIBRARY_LIST + $HWACCEL_LIBRARY_LIST $FEATURE_LIST - $HWACCEL_LIST $LICENSE_LIST $LIBRARY_LIST $PROGRAM_LIST @@ -1243,6 +1360,7 @@ CONFIG_LIST=" pod2man texi2html thumb + valgrind_backtrace xmm_clobber_test " @@ -1316,7 +1434,9 @@ ARCH_EXT_LIST_PPC=" altivec dcbzl ldbrx + power8 ppc4xx + vsx " ARCH_EXT_LIST_X86=" @@ -1350,7 +1470,10 @@ ARCH_FEATURES=" fast_cmov local_aligned_8 local_aligned_16 + local_aligned_32 + simd_align simd_align_16 + simd_align_32 " BUILTIN_LIST=" @@ -1359,6 +1482,7 @@ BUILTIN_LIST=" MemoryBarrier mm_empty rdtsc + sem_timedwait sync_val_compare_and_swap " HAVE_LIST_CMDLINE=" @@ -1373,11 +1497,13 @@ HAVE_LIST_PUB=" " HEADERS_LIST=" + AVFoundation_AVFoundation_h alsa_asoundlib_h altivec_h arpa_inet_h cdio_paranoia_h cdio_paranoia_paranoia_h + dispatch_dispatch_h dev_bktr_ioctl_bt848_h dev_bktr_ioctl_meteor_h dev_ic_bt8xx_h @@ -1385,6 +1511,7 @@ HEADERS_LIST=" dev_video_meteor_ioctl_meteor_h direct_h dlfcn_h + d3d11_h dxva_h gsm_h io_h @@ -1404,6 +1531,7 @@ HEADERS_LIST=" sys_un_h sys_videoio_h unistd_h + valgrind_valgrind_h windows_h winsock2_h " @@ -1441,6 +1569,7 @@ MATH_FUNCS=" SYSTEM_FUNCS=" aligned_malloc + clock_gettime closesocket CommandLineToArgvW CoTaskMemFree @@ -1456,12 +1585,13 @@ SYSTEM_FUNCS=" GetProcessMemoryInfo GetProcessTimes getrusage - getservbyport GetSystemTimeAsFileTime gettimeofday + gmtime_r inet_aton isatty jack_port_get_latency_range + LoadLibrary localtime_r mach_absolute_time MapViewOfFile @@ -1477,7 +1607,6 @@ SYSTEM_FUNCS=" setrlimit Sleep strerror_r - strptime sysconf sysctl usleep @@ -1486,6 +1615,7 @@ SYSTEM_FUNCS=" TOOLCHAIN_FEATURES=" as_dn_directive + as_fpu_directive as_func as_object_arch asm_mod_q @@ -1505,6 +1635,7 @@ TOOLCHAIN_FEATURES=" " TYPES_LIST=" + CONDITION_VARIABLE_Ptr socklen_t struct_addrinfo struct_group_source_req @@ -1540,8 +1671,12 @@ HAVE_LIST=" libc_msvcrt libdc1394_1 libdc1394_2 + MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS sdl + section_data_rel_ro threads + vaapi_drm + vaapi_x11 vdpau_x11 xlib " @@ -1555,14 +1690,22 @@ CONFIG_EXTRA=" blockdsp bswapdsp cabac + dirac_parse dvprofile + faandct + faanidct fdctdsp + flacdsp + fmtconvert + g722dsp gcrypt + gmp golomb gplv3 h263dsp h264chroma h264dsp + h264parse h264pred h264qpel hpeldsp @@ -1571,28 +1714,48 @@ CONFIG_EXTRA=" huffyuvencdsp idctdsp iirfilter + imdct15 intrax8 + iso_media + ividsp + jpegtables + libx262 lgplv3 lpc + lzf me_cmp mpeg_er mpegaudio mpegaudiodsp mpegvideo mpegvideoenc - nettle + mss34dsp pixblockdsp qpeldsp + qsv + qsvdec + qsvenc rangecoder riffdec riffenc rtpdec rtpenc_chain + rv34dsp sinewin + snappy + srtp startcode + texturedsp + texturedspenc tpeldsp + vaapi_encode + vc1dsp videodsp vp3dsp + vp56dsp + vp8dsp + wma_freqs + wmv2dsp " CMDLINE_SELECT=" @@ -1607,6 +1770,7 @@ CMDLINE_SELECT=" logging lto optimizations + rpath " PATHS_LIST=" @@ -1627,9 +1791,12 @@ CMDLINE_SET=" as build_suffix cc + objcc cpu cross_prefix + custom_allocator dep_cc + env extra_version host_cc host_cflags @@ -1657,6 +1824,7 @@ CMDLINE_SET=" CMDLINE_APPEND=" extra_cflags + extra_objcflags host_cppflags " @@ -1677,6 +1845,8 @@ map 'eval ${v}_inline_deps=inline_asm' $ARCH_EXT_LIST_ARM altivec_deps="ppc" ppc4xx_deps="ppc" +vsx_deps="altivec" +power8_deps="vsx" cpunop_deps="i686" x86_64_select="i686" @@ -1714,12 +1884,13 @@ aligned_stack_if_any="aarch64 ppc x86" fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 sparc64 x86_64" fast_clz_if_any="aarch64 alpha avr32 mips ppc x86" fast_unaligned_if_any="aarch64 ppc x86" +simd_align_if_any="simd_align_16 simd_align_32" simd_align_16_if_any="altivec neon sse" +simd_align_32_if_any="avx" # system capabilities -log2_deps="!libc_msvcrt" - symver_if_any="symver_asm_label symver_gnu_asm" +valgrind_backtrace_deps="!optimizations valgrind_valgrind_h" # threading support atomics_gcc_if="sync_val_compare_and_swap" @@ -1731,24 +1902,31 @@ threads_if_any="$THREADS_LIST" # subsystems dct_select="rdft" +dirac_parse_select="golomb" error_resilience_select="me_cmp" -intrax8_select="error_resilience" +faandct_deps="faan fdctdsp" +faanidct_deps="faan idctdsp" +h264dsp_select="startcode" +intrax8_select="blockdsp idctdsp" mdct_select="fft" rdft_select="fft" me_cmp_select="fdctdsp idctdsp pixblockdsp" mpeg_er_select="error_resilience" mpegaudio_select="mpegaudiodsp" mpegaudiodsp_select="dct" -mpegvideo_select="blockdsp hpeldsp idctdsp me_cmp videodsp" +mpegvideo_select="blockdsp hpeldsp idctdsp me_cmp mpeg_er videodsp" mpegvideoenc_select="me_cmp mpegvideo pixblockdsp qpeldsp" +vc1dsp_select="h264chroma qpeldsp startcode" # decoders / encoders -aac_decoder_select="mdct sinewin" +aac_decoder_select="imdct15 mdct sinewin" aac_encoder_select="audio_frame_queue iirfilter mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" -ac3_decoder_select="ac3_parser ac3dsp bswapdsp mdct" +ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" ac3_encoder_select="ac3dsp audiodsp mdct me_cmp" ac3_fixed_encoder_select="ac3dsp audiodsp mdct me_cmp" +adpcm_g722_decoder_select="g722dsp" +adpcm_g722_encoder_select="g722dsp" aic_decoder_select="golomb idctdsp" alac_encoder_select="lpc" als_decoder_select="bswapdsp" @@ -1764,33 +1942,35 @@ atrac1_decoder_select="mdct sinewin" atrac3_decoder_select="mdct" atrac3p_decoder_select="mdct sinewin" bink_decoder_select="blockdsp hpeldsp" -binkaudio_dct_decoder_select="mdct rdft dct sinewin" -binkaudio_rdft_decoder_select="mdct rdft sinewin" +binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs" +binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs" cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp" cllc_decoder_select="bswapdsp" comfortnoise_encoder_select="lpc" cook_decoder_select="audiodsp mdct sinewin" cscd_decoder_select="lzo" cscd_decoder_suggest="zlib" -dca_decoder_select="mdct" +dca_decoder_select="fmtconvert mdct" +dds_decoder_select="texturedsp" dnxhd_decoder_select="blockdsp idctdsp" dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp" dvvideo_decoder_select="dvprofile idctdsp" dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp" dxa_decoder_deps="zlib" +dxv_decoder_select="lzf texturedsp" eac3_decoder_select="ac3_decoder" eac3_encoder_select="ac3_encoder" eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo" eatgq_decoder_select="aandcttables idctdsp" -eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpeg1video_decoder" +eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp" exr_decoder_deps="zlib" ffv1_decoder_select="golomb rangecoder" ffv1_encoder_select="rangecoder" ffvhuff_decoder_select="huffyuv_decoder" ffvhuff_encoder_select="huffyuv_encoder" fic_decoder_select="golomb" -flac_decoder_select="golomb" -flac_encoder_select="bswapdsp golomb lpc" +flac_decoder_select="flacdsp golomb" +flac_encoder_select="bswapdsp flacdsp golomb lpc" flashsv_decoder_deps="zlib" flashsv_encoder_deps="zlib" flashsv2_decoder_deps="zlib" @@ -1799,34 +1979,42 @@ flv_encoder_select="h263_encoder" fourxm_decoder_select="blockdsp bswapdsp" fraps_decoder_select="bswapdsp huffman" g2m_decoder_deps="zlib" -g2m_decoder_select="blockdsp idctdsp" +g2m_decoder_select="blockdsp idctdsp jpegtables" h261_decoder_select="mpeg_er mpegvideo" h261_encoder_select="aandcttables mpegvideoenc" h263_decoder_select="error_resilience h263_parser h263dsp mpeg_er mpegvideo qpeldsp" h263_encoder_select="aandcttables h263dsp mpegvideoenc" h263i_decoder_select="h263_decoder" h263p_encoder_select="h263_encoder" -h264_decoder_select="cabac golomb h264chroma h264dsp h264pred h264qpel startcode videodsp" +h264_decoder_select="cabac golomb h264chroma h264dsp h264parse h264pred h264qpel videodsp" h264_decoder_suggest="error_resilience" +hap_decoder_select="snappy texturedsp" +hap_encoder_deps="libsnappy" +hap_encoder_select="texturedspenc" hevc_decoder_select="bswapdsp cabac golomb videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp" iac_decoder_select="imc_decoder" imc_decoder_select="bswapdsp fft mdct sinewin" indeo3_decoder_select="hpeldsp" +indeo4_decoder_select="ividsp" +indeo5_decoder_select="ividsp" interplay_video_decoder_select="hpeldsp" jpegls_decoder_select="golomb mjpeg_decoder" jpegls_encoder_select="golomb" jv_decoder_select="blockdsp" lagarith_decoder_select="huffyuvdsp" -ljpeg_encoder_select="aandcttables idctdsp" +ljpeg_encoder_select="aandcttables idctdsp jpegtables" loco_decoder_select="golomb" +magicyuv_decoder_select="huffyuvdsp" mdec_decoder_select="blockdsp idctdsp mpegvideo" metasound_decoder_select="lsp mdct sinewin" mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" -mjpeg_decoder_select="blockdsp hpeldsp idctdsp" -mjpeg_encoder_select="aandcttables mpegvideoenc" +mjpeg_decoder_select="blockdsp hpeldsp idctdsp jpegtables" +mjpeg_encoder_select="aandcttables jpegtables mpegvideoenc" mjpegb_decoder_select="mjpeg_decoder" +mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" +mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" mlp_decoder_select="mlp_parser" motionpixels_decoder_select="bswapdsp" mp1_decoder_select="mpegaudio" @@ -1849,18 +2037,21 @@ mpeg2video_decoder_select="error_resilience mpeg_er mpegvideo" mpeg2video_encoder_select="aandcttables mpegvideoenc" mpeg4_decoder_select="h263_decoder mpeg4video_parser" mpeg4_encoder_select="h263_encoder" +msa1_decoder_select="mss34dsp" msmpeg4v1_decoder_select="h263_decoder" msmpeg4v2_decoder_select="h263_decoder" msmpeg4v2_encoder_select="h263_encoder" msmpeg4v3_decoder_select="h263_decoder" msmpeg4v3_encoder_select="h263_encoder" -mss2_decoder_select="error_resilience mpeg_er qpeldsp vc1_decoder" +mss2_decoder_select="error_resilience mpeg_er mpegvideo vc1_decoder" +mts2_decoder_select="mss34dsp" mxpeg_decoder_select="mjpeg_decoder" nellymoser_decoder_select="mdct sinewin" nellymoser_encoder_select="audio_frame_queue mdct sinewin" nuv_decoder_select="idctdsp lzo" on2avc_decoder_select="mdct" opus_decoder_deps="avresample" +opus_decoder_select="imdct15" png_decoder_deps="zlib" png_encoder_deps="zlib" png_encoder_select="huffyuvencdsp" @@ -1870,20 +2061,24 @@ qcelp_decoder_select="lsp" qdm2_decoder_select="mdct rdft mpegaudiodsp" ra_144_encoder_select="audio_frame_queue lpc" ralf_decoder_select="golomb" +rscc_decoder_deps="zlib" rv10_decoder_select="error_resilience h263_decoder h263dsp mpeg_er" rv10_encoder_select="h263_encoder" rv20_decoder_select="error_resilience h263_decoder h263dsp mpeg_er" rv20_encoder_select="h263_encoder" -rv30_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpeg_er mpegvideo videodsp" -rv40_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpeg_er mpegvideo videodsp" +rv30_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpeg_er mpegvideo rv34dsp videodsp" +rv40_decoder_select="error_resilience golomb h264chroma h264pred h264qpel mpeg_er mpegvideo rv34dsp videodsp" +screenpresso_decoder_deps="zlib" shorten_decoder_select="golomb" sipr_decoder_select="lsp" sp5x_decoder_select="mjpeg_decoder" svq1_decoder_select="hpeldsp" svq1_encoder_select="aandcttables hpeldsp me_cmp mpegvideoenc" -svq3_decoder_select="h264_decoder hpeldsp tpeldsp" +svq3_decoder_select="golomb h264dsp h264parse h264pred hpeldsp tpeldsp videodsp" svq3_decoder_suggest="zlib" tak_decoder_select="audiodsp" +tdsc_decoder_deps="zlib" +tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib" @@ -1892,33 +2087,34 @@ truehd_decoder_select="mlp_decoder" truemotion2_decoder_select="bswapdsp" truespeech_decoder_select="bswapdsp" tscc_decoder_deps="zlib" +txd_decoder_select="texturedsp" twinvq_decoder_select="mdct lsp sinewin" utvideo_decoder_select="bswapdsp" utvideo_encoder_select="bswapdsp huffman huffyuvencdsp" vble_decoder_select="huffyuvdsp" -vc1_decoder_select="blockdsp error_resilience h263_decoder h264chroma h264qpel intrax8 mpeg_er qpeldsp startcode" +vc1_decoder_select="blockdsp error_resilience h263_decoder h264qpel intrax8 mpeg_er mpegvideo vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" vorbis_encoder_select="mdct" vp3_decoder_select="hpeldsp vp3dsp videodsp" -vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp" -vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp" +vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp vp56dsp" +vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp vp56dsp" vp6a_decoder_select="vp6_decoder" vp6f_decoder_select="vp6_decoder" -vp7_decoder_select="h264pred videodsp" -vp8_decoder_select="h264pred videodsp" +vp7_decoder_select="h264pred videodsp vp8dsp" +vp8_decoder_select="h264pred videodsp vp8dsp" vp9_decoder_select="videodsp" webp_decoder_select="vp8_decoder" -wmapro_decoder_select="mdct sinewin" -wmav1_decoder_select="mdct sinewin" -wmav1_encoder_select="mdct sinewin" -wmav2_decoder_select="mdct sinewin" -wmav2_encoder_select="mdct sinewin" +wmapro_decoder_select="mdct sinewin wma_freqs" +wmav1_decoder_select="mdct sinewin wma_freqs" +wmav1_encoder_select="mdct sinewin wma_freqs" +wmav2_decoder_select="mdct sinewin wma_freqs" +wmav2_encoder_select="mdct sinewin wma_freqs" wmavoice_decoder_select="lsp rdft dct mdct sinewin" wmv1_decoder_select="h263_decoder" wmv1_encoder_select="h263_encoder" -wmv2_decoder_select="blockdsp h263_decoder idctdsp intrax8 videodsp" -wmv2_encoder_select="h263_encoder" +wmv2_decoder_select="blockdsp error_resilience h263_decoder idctdsp intrax8 videodsp wmv2dsp" +wmv2_encoder_select="h263_encoder wmv2dsp" wmv3_decoder_select="vc1_decoder" wmv3image_decoder_select="wmv3_decoder" zerocodec_decoder_deps="zlib" @@ -1928,7 +2124,8 @@ zmbv_decoder_deps="zlib" zmbv_encoder_deps="zlib" # hardware accelerators -dxva2_deps="dxva2api_h" +d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder" +dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode" vaapi_deps="va_va_h" vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore" @@ -1936,10 +2133,15 @@ vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" -h263_vdpau_hwaccel_deps="vdpau" -h263_vdpau_hwaccel_select="h263_decoder" +h264_d3d11va_hwaccel_deps="d3d11va" +h264_d3d11va_hwaccel_select="h264_decoder" h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" +h264_mmal_decoder_deps="mmal" +h264_mmal_decoder_select="mmal" +h264_mmal_hwaccel_deps="mmal" +h264_omx_encoder_deps="omx" +h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" h264_vaapi_hwaccel_select="h264_decoder" h264_vda_hwaccel_deps="vda" @@ -1948,35 +2150,95 @@ h264_vda_old_hwaccel_deps="vda" h264_vda_old_hwaccel_select="h264_decoder" h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" +hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" +hevc_d3d11va_hwaccel_select="hevc_decoder" +hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" +hevc_dxva2_hwaccel_select="hevc_decoder" +hevc_qsv_hwaccel_deps="libmfx" +hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" +hevc_vdpau_hwaccel_select="hevc_decoder" mpeg1_vdpau_hwaccel_deps="vdpau" mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" +mpeg2_d3d11va_hwaccel_deps="d3d11va" +mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" mpeg2_dxva2_hwaccel_deps="dxva2" mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" +mpeg2_mmal_decoder_deps="mmal" +mpeg2_mmal_decoder_select="mmal" +mpeg2_mmal_hwaccel_deps="mmal" +mpeg2_qsv_hwaccel_deps="libmfx" mpeg2_vaapi_hwaccel_deps="vaapi" mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" mpeg2_vdpau_hwaccel_deps="vdpau" mpeg2_vdpau_hwaccel_select="mpeg2video_decoder" +mpeg4_omx_encoder_deps="omx" mpeg4_vaapi_hwaccel_deps="vaapi" mpeg4_vaapi_hwaccel_select="mpeg4_decoder" mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" +vc1_d3d11va_hwaccel_deps="d3d11va" +vc1_d3d11va_hwaccel_select="vc1_decoder" vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_select="vc1_decoder" +vc1_mmal_decoder_deps="mmal" +vc1_mmal_decoder_select="mmal" +vc1_mmal_hwaccel_deps="mmal" vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" +wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" +# hardware-accelerated codecs +nvenc_deps_any="dlopen LoadLibrary" +nvenc_extralibs='$ldl' +omx_deps="dlopen pthreads" +omx_extralibs='$ldl' +qsvdec_select="qsv" +qsvenc_select="qsv" +vaapi_encode_deps="vaapi" + +hwupload_cuda_filter_deps="cuda" +scale_npp_filter_deps="cuda libnpp" + +h264_nvenc_encoder_deps="nvenc" +h264_qsv_decoder_deps="libmfx" +h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" +h264_qsv_encoder_deps="libmfx" +h264_qsv_encoder_select="qsvenc" +h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" +h264_vaapi_encoder_select="vaapi_encode golomb" + +hevc_nvenc_encoder_deps="nvenc" +hevc_qsv_decoder_deps="libmfx" +hevc_qsv_encoder_deps="libmfx" +hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" +hevc_qsv_encoder_select="qsvenc" +hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" +hevc_vaapi_encoder_select="vaapi_encode golomb" +mpeg2_qsv_decoder_deps="libmfx" +mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel mpegvideo_parser" +mpeg2_qsv_encoder_deps="libmfx" +mpeg2_qsv_encoder_select="qsvenc" + +nvenc_h264_encoder_deps="nvenc" +nvenc_hevc_encoder_deps="nvenc" + # parsers -h264_parser_select="h264_decoder" +h264_parser_select="golomb h264dsp h264parse" +hevc_parser_select="golomb" mpegvideo_parser_select="mpegvideo" -mpeg4video_parser_select="error_resilience h263dsp mpeg_er mpegvideo qpeldsp" -vc1_parser_select="mpegvideo startcode" +mpeg4video_parser_select="error_resilience h263dsp mpegvideo qpeldsp" +vc1_parser_select="vc1dsp" + +# bitstream_filters +mjpeg2jpeg_bsf_select="jpegtables" # external libraries +libdcadec_decoder_deps="libdcadec" libfaac_encoder_deps="libfaac" libfaac_encoder_select="audio_frame_queue" libfdk_aac_decoder_deps="libfdk_aac" @@ -1988,12 +2250,16 @@ libgsm_ms_decoder_deps="libgsm" libgsm_ms_encoder_deps="libgsm" libilbc_decoder_deps="libilbc" libilbc_encoder_deps="libilbc" +libkvazaar_encoder_deps="libkvazaar" libmp3lame_encoder_deps="libmp3lame" libmp3lame_encoder_select="audio_frame_queue" libopencore_amrnb_decoder_deps="libopencore_amrnb" libopencore_amrnb_encoder_deps="libopencore_amrnb" libopencore_amrnb_encoder_select="audio_frame_queue" libopencore_amrwb_decoder_deps="libopencore_amrwb" +libopenh264_decoder_deps="libopenh264" +libopenh264_decoder_select="h264_mp4toannexb_bsf" +libopenh264_encoder_deps="libopenh264" libopenjpeg_decoder_deps="libopenjpeg" libopenjpeg_encoder_deps="libopenjpeg" libopus_decoder_deps="libopus" @@ -2017,6 +2283,7 @@ libvpx_vp9_decoder_deps="libvpx" libvpx_vp9_encoder_deps="libvpx" libwavpack_encoder_deps="libwavpack" libwebp_encoder_deps="libwebp" +libx262_encoder_deps="libx262" libx264_encoder_deps="libx264" libx265_encoder_deps="libx265" libxavs_encoder_deps="libxavs" @@ -2027,11 +2294,12 @@ ac3_demuxer_select="ac3_parser" asf_demuxer_select="riffdec" asf_muxer_select="riffenc" asf_stream_muxer_select="asf_muxer" -avi_demuxer_select="riffdec" +avi_demuxer_select="iso_media riffdec" avi_muxer_select="riffenc" avisynth_demuxer_deps="avisynth" avisynth_demuxer_select="riffdec" -caf_demuxer_select="riffdec" +caf_demuxer_select="iso_media riffdec" +dash_muxer_select="mp4_muxer" dirac_demuxer_select="dirac_parser" dv_demuxer_select="dvprofile" dv_muxer_select="dvprofile" @@ -2044,24 +2312,27 @@ hls_muxer_select="mpegts_muxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" matroska_audio_muxer_select="matroska_muxer" -matroska_demuxer_select="riffdec" +matroska_demuxer_select="iso_media riffdec" matroska_demuxer_suggest="bzlib lzo zlib" -matroska_muxer_select="riffenc" +matroska_muxer_select="iso_media riffenc" mmf_muxer_select="riffenc" -mov_demuxer_select="riffdec" +mov_demuxer_select="iso_media riffdec" mov_demuxer_suggest="zlib" -mov_muxer_select="riffenc rtpenc_chain" +mov_muxer_select="iso_media riffenc rtpenc_chain" mp3_demuxer_select="mpegaudio_parser" mp4_muxer_select="mov_muxer" +mpegts_demuxer_select="iso_media" mpegts_muxer_select="adts_muxer latm_muxer" mpegtsraw_demuxer_select="mpegts_demuxer" mxf_d10_muxer_select="mxf_muxer" nut_muxer_select="riffenc" nuv_demuxer_select="riffdec" -ogg_demuxer_select="golomb" +oga_muxer_select="ogg_muxer" +ogg_demuxer_select="dirac_parse" +opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtpdec_select="asf_demuxer rm_demuxer rtp_protocol mpegts_demuxer mov_demuxer" +rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" sap_demuxer_select="sdp_demuxer" @@ -2069,25 +2340,30 @@ sap_muxer_select="rtp_muxer rtp_protocol rtpenc_chain" sdp_demuxer_select="rtpdec" smoothstreaming_muxer_select="ismv_muxer" spdif_muxer_select="aac_parser" +spx_muxer_select="ogg_muxer" +swf_demuxer_suggest="zlib" tak_demuxer_select="tak_parser" tg2_muxer_select="mov_muxer" tgp_muxer_select="mov_muxer" w64_demuxer_select="wav_demuxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" -webm_muxer_select="riffenc" -wtv_demuxer_select="riffdec" +webm_muxer_select="iso_media riffenc" +webm_muxer_suggest="libopus_encoder libvorbis_encoder libvpx_vp8_encoder libvpx_vp9_encoder" +wtv_demuxer_select="mpegts_demuxer riffdec" xmv_demuxer_select="riffdec" xwma_demuxer_select="riffdec" # indevs / outdevs alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" alsa_outdev_deps="alsa_asoundlib_h" +avfoundation_indev_deps="AVFoundation_AVFoundation_h" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" dv1394_indev_deps="dv1394" dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" -jack_indev_deps="jack_jack_h pthreads" +jack_indev_deps="jack_jack_h" +jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" oss_indev_deps_any="soundcard_h sys_soundcard_h" @@ -2098,11 +2374,11 @@ sndio_outdev_deps="sndio_h" v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" vfwcap_indev_deps="capCreateCaptureWindow vfwcap_defines" vfwcap_indev_extralibs="-lavicap32" -x11grab_indev_deps="x11grab XShmCreateImage" +xcbgrab_indev_deps="libxcb" # protocols ffrtmpcrypt_protocol_deps="!librtmp_protocol" -ffrtmpcrypt_protocol_deps_any="gcrypt nettle openssl" +ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl" ffrtmpcrypt_protocol_select="tcp_protocol" ffrtmphttp_protocol_deps="!librtmp_protocol" ffrtmphttp_protocol_select="http_protocol" @@ -2129,10 +2405,13 @@ rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" rtp_protocol_select="udp_protocol" sctp_protocol_deps="struct_sctp_event_subscribe" sctp_protocol_select="network" -srtp_protocol_select="rtp_protocol" +srtp_protocol_select="rtp_protocol srtp" tcp_protocol_select="network" -tls_protocol_deps_any="openssl gnutls" -tls_protocol_select="tcp_protocol" +tls_gnutls_protocol_deps="gnutls" +tls_gnutls_protocol_select="tcp_protocol" +tls_openssl_protocol_deps="openssl !tls_gnutls_protocol" +tls_openssl_protocol_select="tcp_protocol" +tls_protocol_deps_any="tls_gnutls_protocol tls_openssl_protocol" udp_protocol_select="network" unix_protocol_deps="sys_un_h" unix_protocol_select="network" @@ -2142,23 +2421,28 @@ blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" bs2b_filter_deps="libbs2b" cropdetect_filter_deps="gpl" +deinterlace_qsv_filter_deps="libmfx" delogo_filter_deps="gpl" drawtext_filter_deps="libfreetype" frei0r_filter_deps="frei0r dlopen" frei0r_filter_extralibs='$ldl' frei0r_src_filter_deps="frei0r dlopen" frei0r_src_filter_extralibs='$ldl' +hdcd_filter_deps="libhdcd" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" ocv_filter_deps="libopencv" resample_filter_deps="avresample" scale_filter_deps="swscale" +scale_qsv_filter_deps="libmfx" +scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" # examples avcodec_example_deps="avcodec avutil" filter_audio_example_deps="avfilter avutil" metadata_example_deps="avformat avutil" output_example_deps="avcodec avformat avutil swscale" +qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder vaapi_x11" transcode_aac_example_deps="avcodec avformat avresample" # libraries, in linking order @@ -2173,10 +2457,10 @@ swscale_deps="avutil" avconv_deps="avcodec avfilter avformat avresample swscale" avconv_select="aformat_filter anull_filter asyncts_filter atrim_filter format_filter fps_filter null_filter resample_filter scale_filter - setpts_filter trim_filter" -avplay_deps="avcodec avformat avresample swscale sdl" + trim_filter" +avplay_deps="avcodec avfilter avformat avresample sdl" avplay_libs='$sdl_libs' -avplay_select="rdft" +avplay_select="rdft format_filter transpose_filter hflip_filter vflip_filter" avprobe_deps="avcodec avformat" # documentation @@ -2208,6 +2492,7 @@ objformat="elf" pkg_config_default=pkg-config ranlib="ranlib" strip="strip" +version_script='--version-script' yasmexe="yasm" # machine @@ -2225,13 +2510,15 @@ enable $EXAMPLE_LIST $LIBRARY_LIST $PROGRAM_LIST enable asm enable debug enable doc +enable faan faandct faanidct enable optimizations enable safe_bitstream_reader enable static enable swscale_alpha +enable valgrind_backtrace # By default, enable only those hwaccels that have no external dependencies. -enable dxva2 vdpau +enable d3d11va dxva2 vda vdpau # build settings SHFLAGS='-shared -Wl,-soname,$$(@F)' @@ -2247,6 +2534,7 @@ SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)' +VERSION_SCRIPT_POSTPROCESS_CMD="cat" asflags_filter=echo cflags_filter=echo @@ -2257,6 +2545,9 @@ AS_O='-o $@' CC_C='-c' CC_E='-E -o $@' CC_O='-o $@' +OBJCC_C='-c' +OBJCC_E='-E -o $@' +OBJCC_O='-o $@' LD_O='-o $@' LD_LIB='-l%' LD_PATH='-L' @@ -2305,14 +2596,22 @@ ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c) DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c) PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) -BSF_LIST=$(find_things bsf BSF libavcodec/allcodecs.c) MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) -PROTOCOL_LIST=$(find_things protocol PROTOCOL libavformat/allformats.c) FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c) +find_things_extern(){ + thing=$1 + pattern=$2 + file=$source_path/$3 + sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" +} + +BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) +PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) + ALL_COMPONENTS=" $BSF_LIST $DECODER_LIST @@ -2342,7 +2641,7 @@ die_unknown(){ } print_3_columns() { - cat | tr ' ' '\n' | sort | pr -r -3 -t + printf "%-25s %-25s %-25s\n" $(cat | tr ' ' '\n' | sort) } show_list() { @@ -2454,65 +2753,69 @@ for opt do esac done +for e in $env; do + eval "export $e" +done + disabled logging && logfile=/dev/null -echo "# $0 $LIBAV_CONFIGURATION" > $logfile -set >> $logfile +# Disable all the library-specific components if the library itself +# is disabled, see AVCODEC_LIST and following _LIST variables. -test -n "$cross_prefix" && enable cross_compile +disable_components(){ + disabled ${1} && disable $( + eval components="\$$(toupper ${1})_COMPONENTS" + map 'eval echo \${$(toupper ${v%s})_LIST}' $components + ) +} -if enabled cross_compile; then - test -n "$arch" && test -n "$target_os" || - die "Must specify target arch and OS when cross-compiling" -fi +map 'disable_components $v' $LIBRARY_LIST -ar_default="${cross_prefix}${ar_default}" -cc_default="${cross_prefix}${cc_default}" -nm_default="${cross_prefix}${nm_default}" -pkg_config_default="${cross_prefix}${pkg_config_default}" -ranlib="${cross_prefix}${ranlib}" -strip="${cross_prefix}${strip}" - -sysinclude_default="${sysroot}/usr/include" +echo "# $0 $LIBAV_CONFIGURATION" > $logfile +set >> $logfile case "$toolchain" in - clang-asan) - cc_default="clang" + *-asan) + cc_default="${toolchain%-asan}" add_cflags -fsanitize=address add_ldflags -fsanitize=address ;; - clang-tsan) - cc_default="clang" + *-msan) + cc_default="${toolchain%-msan}" + add_cflags -fsanitize=memory -fsanitize-memory-track-origins + add_ldflags -fsanitize=memory + ;; + *-tsan) + cc_default="${toolchain%-tsan}" add_cflags -fsanitize=thread -pie add_ldflags -fsanitize=thread -pie + case "$toolchain" in + gcc-tsan) + add_cflags -fPIC + add_ldflags -fPIC + ;; + esac ;; - clang-usan) - cc_default="clang" - add_cflags -fsanitize=undefined -O1 - add_ldflags -fsanitize=undefined - ;; - gcc-asan) - cc_default="gcc" - add_cflags -fsanitize=address - add_ldflags -fsanitize=address - ;; - gcc-tsan) - cc_default="gcc" - add_cflags -fsanitize=thread -pie -fPIC - add_ldflags -fsanitize=thread -pie -fPIC - ;; - gcc-usan) - cc_default="gcc" + *-usan) + cc_default="${toolchain%-usan}" add_cflags -fsanitize=undefined add_ldflags -fsanitize=undefined + case "$toolchain" in + clang-usan) + add_cflags -O1 + ;; + esac ;; - valgrind-massif) - target_exec_default="valgrind" - target_exec_args="--alloc-fn=av_malloc --alloc-fn=av_mallocz" - ;; - valgrind-memcheck) + valgrind-*) target_exec_default="valgrind" - target_exec_args="--track-origins=yes --leak-check=full" + case "$toolchain" in + valgrind-massif) + target_exec_args="--alloc-fn=av_malloc --alloc-fn=av_mallocz" + ;; + valgrind-memcheck) + target_exec_args="--track-origins=yes --leak-check=full" + ;; + esac ;; msvc) # Check whether the current MSVC version needs the C99 converter. @@ -2527,9 +2830,14 @@ case "$toolchain" in else cc_default="c99wrap cl" fi - ld_default="link" + ld_default="$source_path/compat/windows/mslink" nm_default="dumpbin -symbols" ar_default="lib" + case "$arch" in + arm*) + as_default="armasm" + ;; + esac target_os_default="win32" # Use a relative path for TMPDIR. This makes sure all the # ffconf temp files are written with a relative path, avoiding @@ -2549,15 +2857,37 @@ case "$toolchain" in add_cflags -fprofile-arcs -ftest-coverage add_ldflags -fprofile-arcs -ftest-coverage ;; + llvm-cov) + add_cflags -fprofile-arcs -ftest-coverage + add_ldflags --coverage + ;; hardened) - add_cflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all - add_ldflags -Wl,-z,relro -Wl,-z,now + add_cppflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 + add_cflags -fno-strict-overflow -fstack-protector-all + add_ldflags -Wl,-z,relro -Wl,-z,now ;; ?*) die "Unknown toolchain $toolchain" ;; esac +test -n "$cross_prefix" && enable cross_compile + +if enabled cross_compile; then + test -n "$arch" && test -n "$target_os" || + die "Must specify target arch and OS when cross-compiling" +fi + +ar_default="${cross_prefix}${ar_default}" +cc_default="${cross_prefix}${cc_default}" +occ_default="${cross_prefix}${occ_default}" +nm_default="${cross_prefix}${nm_default}" +pkg_config_default="${cross_prefix}${pkg_config_default}" +ranlib="${cross_prefix}${ranlib}" +strip="${cross_prefix}${strip}" + +sysinclude_default="${sysroot}/usr/include" + set_default arch cc pkg_config sysinclude target_exec target_os enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -2569,7 +2899,7 @@ fi exesuf() { case $1 in - mingw32*|win32|win64|cygwin*|*-dos|freedos|opendos|os/2*|symbian) echo .exe ;; + mingw32*|mingw64*|win32|win64|cygwin*|*-dos|freedos|opendos|os/2*|symbian) echo .exe ;; esac } @@ -2686,7 +3016,9 @@ msvc_common_flags(){ -lz) echo zlib.lib ;; -lavifil32) echo vfw32.lib ;; -lavicap32) echo vfw32.lib user32.lib ;; + -lx264) echo libx264.lib ;; -l*) echo ${flag#-l}.lib ;; + -L*) echo -libpath:${flag#-L} ;; *) echo $flag ;; esac done @@ -2699,7 +3031,7 @@ msvc_flags(){ -Wall) echo -W4 -wd4244 -wd4127 -wd4018 -wd4389 \ -wd4146 -wd4057 -wd4204 -wd4706 -wd4305 \ -wd4152 -wd4324 -we4013 -wd4100 -wd4214 \ - -wd4273 ;; + -wd4273 -wd4554 -wd4701 ;; esac done } @@ -2804,8 +3136,8 @@ probe_cc(){ if $_cc -v 2>&1 | grep -q '^gcc.*LLVM'; then _type=llvm_gcc - gcc_extra_ver=$(expr "$($_cc --version | head -n1)" : '.*\((.*)\)') - _ident="llvm-gcc $($_cc -dumpversion) $gcc_extra_ver" + gcc_extra_ver=$(expr "$($_cc --version 2>/dev/null | head -n1)" : '.*\((.*)\)') + _ident="llvm-gcc $($_cc -dumpversion 2>/dev/null) $gcc_extra_ver" _depflags='-MMD -MF $(@:.o=.d) -MT $@' _cflags_speed='-O3' _cflags_size='-Os' @@ -2868,7 +3200,7 @@ probe_cc(){ _flags_filter=tms470_flags elif $_cc -v 2>&1 | grep -q clang; then _type=clang - _ident=$($_cc --version | head -n1) + _ident=$($_cc --version 2>/dev/null | head -n1) _depflags='-MMD -MF $(@:.o=.d) -MT $@' _cflags_speed='-O3' _cflags_size='-Os' @@ -2909,14 +3241,14 @@ probe_cc(){ # 4509: "This form of conditional instruction is deprecated" _flags="-nologo -ignore 4509" _flags_filter=armasm_flags - elif $_cc 2>&1 | grep -q Microsoft; then + elif $_cc -nologo- 2>&1 | grep -q Microsoft; then _type=msvc - _ident=$($cc 2>&1 | head -n1) + _ident=$($_cc 2>&1 | head -n1) _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs' _cflags_speed="-O2" _cflags_size="-O1" - if $_cc 2>&1 | grep -q Linker; then + if $_cc -nologo- 2>&1 | grep -q Linker; then _ld_o='-out:$@' else _ld_o='-Fe$@' @@ -2927,13 +3259,9 @@ probe_cc(){ _ld_lib='lib%.a' _ld_path='-libpath:' _flags='-nologo' - _cflags='-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64' - if [ $pfx = hostcc ]; then - append _cflags -Dsnprintf=_snprintf - fi elif $_cc 2>&1 | grep -q Intel; then _type=icl - _ident=$($cc 2>&1 | head -n1) + _ident=$($_cc 2>&1 | head -n1) _depflags='-QMMD -QMF$(@:.o=.d) -QMT$@' # Not only is O3 broken on 13.x+ but it is slower on all previous # versions (tested) as well. @@ -2953,10 +3281,19 @@ probe_cc(){ _flags='-nologo -Qdiag-error:4044,10157' # -Qvec- -Qsimd- to prevent miscompilation, -GS for consistency # with MSVC which enables it by default. - _cflags='-D_USE_MATH_DEFINES -FIstdlib.h -Dstrtoll=_strtoi64 -Qms0 -Qvec- -Qsimd- -GS' - if [ $pfx = hostcc ]; then - append _cflags -Dsnprintf=_snprintf - fi + _cflags='-Qms0 -Qvec- -Qsimd- -GS' + elif $_cc -? 2>/dev/null | grep -q 'LLVM.*Linker'; then + # lld can emulate multiple different linkers; in ms link.exe mode, + # the -? parameter gives the help output which contains an identifyable + # string, while it gives an error in other modes. + _type=lld-link + # The link.exe mode doesn't have a switch for getting the version, + # but we can force it back to gnu mode and get the version from there. + _ident=$($_cc -flavor gnu --version) + _ld_o='-out:$@' + _flags_filter=msvc_flags + _ld_lib='lib%.a' + _ld_path='-libpath:' elif $_cc --version 2>/dev/null | grep -q ^cparser; then _type=cparser _ident=$($_cc --version | head -n1) @@ -3002,16 +3339,22 @@ test -n "$cc_type" && enable $cc_type || warn "Unknown C compiler $cc, unable to select optimal CFLAGS" : ${as_default:=$cc} +: ${objcc_default:=$cc} : ${dep_cc_default:=$cc} : ${ld_default:=$cc} : ${host_ld_default:=$host_cc} -set_default ar as dep_cc ld host_ld +set_default ar as objcc dep_cc ld host_ld probe_cc as "$as" asflags_filter=$_flags_filter add_asflags $_flags $_cflags set_ccvars AS +probe_cc objcc "$objcc" +objcflags_filter=$_flags_filter +add_objcflags $_flags $_cflags +set_ccvars OBJC + probe_cc ld "$ld" ldflags_filter=$_flags_filter add_ldflags $_flags $_ldflags @@ -3047,6 +3390,7 @@ else fi add_cflags $extra_cflags +add_objcflags $extra_objcflags add_asflags $extra_cflags if test -n "$sysroot"; then @@ -3093,6 +3437,16 @@ case "$arch" in arch="arm" ;; mips*|IP*) + case "$arch" in + *el) + add_cppflags -EL + add_ldflags -EL + ;; + *eb) + add_cppflags -EB + add_ldflags -EB + ;; + esac arch="mips" ;; parisc*|hppa*) @@ -3146,25 +3500,26 @@ elif enabled arm; then } probe_arm_arch() { - if check_arm_arch 4; then echo armv4; - elif check_arm_arch 4T; then echo armv4t; - elif check_arm_arch 5; then echo armv5; - elif check_arm_arch 5E; then echo armv5e; - elif check_arm_arch 5T; then echo armv5t; - elif check_arm_arch 5TE; then echo armv5te; - elif check_arm_arch 5TEJ; then echo armv5te; - elif check_arm_arch 6; then echo armv6; - elif check_arm_arch 6J; then echo armv6j; - elif check_arm_arch 6K; then echo armv6k; - elif check_arm_arch 6Z; then echo armv6z; - elif check_arm_arch 6ZK; then echo armv6zk; - elif check_arm_arch 6T2; then echo armv6t2; - elif check_arm_arch 7; then echo armv7; - elif check_arm_arch 7A 7_A; then echo armv7-a; - elif check_arm_arch 7R 7_R; then echo armv7-r; - elif check_arm_arch 7M 7_M; then echo armv7-m; - elif check_arm_arch 7EM 7E_M; then echo armv7-m; - elif check_arm_arch 8A 8_A; then echo armv8-a; + if check_arm_arch 4; then echo armv4 + elif check_arm_arch 4T; then echo armv4t + elif check_arm_arch 5; then echo armv5 + elif check_arm_arch 5E; then echo armv5e + elif check_arm_arch 5T; then echo armv5t + elif check_arm_arch 5TE; then echo armv5te + elif check_arm_arch 5TEJ; then echo armv5te + elif check_arm_arch 6; then echo armv6 + elif check_arm_arch 6J; then echo armv6j + elif check_arm_arch 6K; then echo armv6k + elif check_arm_arch 6Z; then echo armv6z + elif check_arm_arch 6ZK; then echo armv6zk + elif check_arm_arch 6T2; then echo armv6t2 + elif check_arm_arch 7; then echo armv7 + elif check_arm_arch 7A 7_A; then echo armv7-a + elif check_arm_arch 7S; then echo armv7-a + elif check_arm_arch 7R 7_R; then echo armv7-r + elif check_arm_arch 7M 7_M; then echo armv7-m + elif check_arm_arch 7EM 7E_M; then echo armv7-m + elif check_arm_arch 8A 8_A; then echo armv8-a fi } @@ -3246,19 +3601,28 @@ elif enabled ppc; then ;; g4|745*|ppc745*|powerpc745*) cpuflags="-mcpu=7450" + disable vsx ;; 74*|ppc74*|powerpc74*) cpuflags="-mcpu=7400" + disable vsx ;; g5|970|ppc970|powerpc970) cpuflags="-mcpu=970" + disable vsx ;; - power[3-7]*) + power[3-6]*) cpuflags="-mcpu=$cpu" + disable vsx + ;; + power[7-8]*) + cpuflags="-mcpu=$cpu" + enable ldbrx ;; cell) cpuflags="-mcpu=cell" enable ldbrx + disable vsx ;; e500mc) cpuflags="-mcpu=e500mc" @@ -3401,10 +3765,10 @@ case $target_os in ;; android) disable symver + enable section_data_rel_ro SLIB_INSTALL_NAME='$(SLIBNAME)' SLIB_INSTALL_LINKS= - # soname not set on purpose - SHFLAGS=-shared + SHFLAGS='-shared -Wl,-soname,$(SLIBNAME)' ;; haiku) prefix_default="/boot/common" @@ -3424,6 +3788,8 @@ case $target_os in echo "hwcap_1 = OVERRIDE;" > mapfile && add_ldflags -Wl,-M,mapfile nm_default='nm -P -g' + version_script='-M' + VERSION_SCRIPT_POSTPROCESS_CMD='perl $(SRC_PATH)/compat/solaris/make_sunver.pl - $(OBJS)' ;; netbsd) disable symver @@ -3458,8 +3824,13 @@ case $target_os in enabled x86_64 && objformat="macho64" enabled_any pic shared || { check_cflags -mdynamic-no-pic && add_asflags -mdynamic-no-pic; } + check_header dispatch/dispatch.h && + add_cppflags '-I\$(SRC_PATH)/compat/dispatch_semaphore' + ;; + msys*) + die "Native MSYS builds are discouraged, please use the MINGW environment." ;; - mingw32*) + mingw32*|mingw64*) if test $target_os = "mingw32ce"; then disable network else @@ -3535,6 +3906,7 @@ case $target_os in ;; linux) enable dv1394 + enable section_data_rel_ro ;; irix*) target_os=irix @@ -3552,11 +3924,10 @@ case $target_os in SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(shell echo $(NAME) | cut -c1-6)$(LIBMAJOR)$(SLIBSUF)' SLIB_CREATE_DEF_CMD='echo LIBRARY $(SLIBNAME_WITH_MAJOR) INITINSTANCE TERMINSTANCE > $(SUBDIR)$(NAME).def; \ - echo PROTMODE >> $(SUBDIR)$(NAME).def; \ echo CODE PRELOAD MOVEABLE DISCARDABLE >> $(SUBDIR)$(NAME).def; \ echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $(SUBDIR)$(NAME).def; \ echo EXPORTS >> $(SUBDIR)$(NAME).def; \ - emxexp -o $(OBJS) >> $(SUBDIR)$(NAME).def' + emxexp $(OBJS) >> $(SUBDIR)$(NAME).def' SLIB_EXTRA_CMD='emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.a $(SUBDIR)$(NAME).def; \ emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib $(SUBDIR)$(NAME).def;' SLIB_INSTALL_EXTRA_LIB='$(LIBPREF)$(NAME)_dll.a $(LIBPREF)$(NAME)_dll.lib' @@ -3635,18 +4006,45 @@ probe_libc(){ (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" || die "ERROR: MinGW32 runtime version must be >= 3.15." add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 + check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700__" && + add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ elif check_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then eval ${pfx}libc_type=msvcrt + if check_${pfx}cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION < 14"; then + if [ "$pfx" = host_ ]; then + add_host_cppflags -Dsnprintf=_snprintf + else + add_compat strtod.o strtod=avpriv_strtod + add_compat msvcrt/snprintf.o snprintf=avpriv_snprintf \ + _snprintf=avpriv_snprintf \ + vsnprintf=avpriv_vsnprintf + fi + fi + add_${pfx}cppflags -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS # The MSVC 2010 headers (Win 7.0 SDK) set _WIN32_WINNT to # 0x601 by default unless something else is set by the user. # This can easily lead to us detecting functions only present # in such new versions and producing binaries requiring windows 7.0. # Therefore explicitly set the default to XP unless the user has # set something else on the command line. + # Don't do this if WINAPI_FAMILY is set and is set to a non-desktop + # family. For these cases, configure is free to use any functions + # found in the SDK headers by default. (Alternatively, we could force + # _WIN32_WINNT to 0x0602 in that case.) check_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" || - add_${pfx}cppflags -D_WIN32_WINNT=0x0502 + { check_${pfx}cpp < +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error not desktop +#endif +#endif +EOF + if [ "$pfx" = "" ]; then + check_func strtoll || add_cflags -Dstrtoll=_strtoi64 + fi elif check_${pfx}cpp_condition stddef.h "defined __KLIBC__"; then eval ${pfx}libc_type=klibc elif check_${pfx}cpp_condition sys/cdefs.h "defined __BIONIC__"; then @@ -3654,6 +4052,9 @@ probe_libc(){ elif check_${pfx}cpp_condition sys/brand.h "defined LABELED_BRAND_NAME"; then eval ${pfx}libc_type=solaris add_${pfx}cppflags -D__EXTENSIONS__ -D_XOPEN_SOURCE=600 + else + eval ${pfx}libc_type=default + add_${pfx}cppflags -D_DEFAULT_SOURCE fi } @@ -3666,12 +4067,6 @@ case $libc_type in bionic) add_compat strtod.o strtod=avpriv_strtod ;; - msvcrt) - add_compat strtod.o strtod=avpriv_strtod - add_compat msvcrt/snprintf.o snprintf=avpriv_snprintf \ - _snprintf=avpriv_snprintf \ - vsnprintf=avpriv_vsnprintf - ;; esac # hacks for compiler/libc/os combinations @@ -3710,28 +4105,16 @@ 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; + exit 1 fi die_license_disabled() { - enabled $1 || { enabled $2 && die "$2 is $1 and --enable-$1 is not specified."; } + enabled $1 || { enabled $v && die "$v is $1 and --enable-$1 is not specified."; } } -die_license_disabled gpl libcdio -die_license_disabled gpl libx264 -die_license_disabled gpl libx265 -die_license_disabled gpl libxavs -die_license_disabled gpl libxvid -die_license_disabled gpl x11grab - -die_license_disabled nonfree libfaac -die_license_disabled nonfree libfdk_aac -die_license_disabled nonfree openssl - -die_license_disabled version3 libopencore_amrnb -die_license_disabled version3 libopencore_amrwb -die_license_disabled version3 libvo_aacenc -die_license_disabled version3 libvo_amrwbenc +map "die_license_disabled gpl" $EXTERNAL_LIBRARY_GPL_LIST +map "die_license_disabled nonfree" $EXTERNAL_LIBRARY_NONFREE_LIST $HWACCEL_LIBRARY_NONFREE_LIST +map "die_license_disabled version3" $EXTERNAL_LIBRARY_VERSION3_LIST enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; } @@ -3849,12 +4232,15 @@ elif enabled alpha; then elif enabled arm; then + enabled msvc && check_cpp_condition stddef.h "defined _M_ARMT" && enable thumb check_cpp_condition stddef.h "defined __thumb__" && enable_weak thumb enabled thumb && check_cflags -mthumb || check_cflags -marm if check_cpp_condition stddef.h "defined __ARM_PCS_VFP"; then enable vfp_args - elif ! check_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__"; then + elif check_cpp_condition stddef.h "defined _M_ARM_FP && _M_ARM_FP >= 30"; then + enable vfp_args + elif ! check_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then case "${cross_prefix:-$cc}" in *hardfloat*) enable vfp_args; fpabi=vfp ;; *) check_ld <= 0.8.1" kvazaar.h kvz_api_get +enabled libmfx && require_pkg_config libmfx "mfx/mfxvideo.h" MFXInit enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame +enabled libnpp && require libnpp npp.h nppGetLibVersion -lnppi -lnppc enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb enabled libopencv && require_pkg_config opencv opencv/cv.h cvCreateImageHeader +enabled libopenh264 && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion enabled libopenjpeg && { { check_header openjpeg.h && check_lib2 openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC; } || { require_pkg_config libopenjpeg1 openjpeg.h opj_version -DOPJ_STATIC; } } enabled libopus && require_pkg_config opus opus_multistream.h opus_multistream_decoder_create enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init +enabled libsnappy && require snappy snappy-c.h snappy_compress -lsnappy enabled libspeex && require_pkg_config speex speex/speex.h speex_decoder_init -lspeex enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc enabled libvorbis && require libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg -enabled libvpx && { - enabled libvpx_vp8_decoder && { check_lib2 "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_dec_init_ver -lvpx || - die "ERROR: libvpx decoder version must be >=0.9.1"; } - enabled libvpx_vp8_encoder && { check_lib2 "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VPX_CQ" -lvpx || - die "ERROR: libvpx encoder version must be >=0.9.6"; } - enabled libvpx_vp9_decoder && { check_lib2 "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx" -lvpx || disable libvpx_vp9_decoder; } - enabled libvpx_vp9_encoder && { check_lib2 "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx" -lvpx || disable libvpx_vp9_encoder; } } +enabled libvpx && require_pkg_config "vpx >= 1.3.0" vpx/vpx_codec.h vpx_codec_version && { + enabled libvpx_vp8_decoder && { + check_pkg_config vpx "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx || + disable libvpx_vp8_decoder; + } + enabled libvpx_vp8_encoder && { + check_pkg_config vpx "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx || + disable libvpx_vp8_encoder; + } + enabled libvpx_vp9_decoder && { + check_pkg_config vpx "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || + disable libvpx_vp9_decoder; + } + enabled libvpx_vp9_encoder && { + check_pkg_config vpx "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || + disable libvpx_vp9_encoder; + } + if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then + die "libvpx enabled but no supported decoders found" + fi +} enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack enabled libwebp && require_pkg_config libwebp webp/encode.h WebPGetEncoderVersion enabled libx264 && require_pkg_config x264 "stdint.h x264.h" x264_encoder_encode && { check_cpp_condition x264.h "X264_BUILD >= 118" || - die "ERROR: libx264 version must be >= 0.118."; } -enabled libx265 && require_pkg_config x265 x265.h x265_encoder_encode && - { check_cpp_condition x265.h "X265_BUILD >= 17" || - die "ERROR: libx265 version must be >= 17."; } + die "ERROR: libx264 version must be >= 0.118."; } && + { check_cpp_condition x264.h "X264_MPEG2" && + enable libx262; } +enabled libx265 && require_pkg_config x265 x265.h x265_api_get && + { check_cpp_condition x265.h "X265_BUILD >= 57" || + die "ERROR: libx265 version must be >= 57."; } enabled libxavs && require libxavs xavs.h xavs_encoder_encode -lxavs enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore -enabled openssl && { check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto || +enabled mmal && { check_lib interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host || + { ! enabled cross_compile && { + add_cflags -isystem/opt/vc/include/ -isystem/opt/vc/include/interface/vmcs_host/linux -isystem/opt/vc/include/interface/vcos/pthreads -fgnu89-inline ; + add_extralibs -L/opt/vc/lib/ -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host ; + check_lib interface/mmal/mmal.h mmal_port_connect ; } + check_lib interface/mmal/mmal.h mmal_port_connect ; } || + die "ERROR: mmal not found"; } +enabled mmal && check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS" +enabled omx_rpi && enable omx +enabled omx && { check_header OMX_Core.h || + { ! enabled cross_compile && enabled omx_rpi && { + add_cflags -isystem/opt/vc/include/IL ; } + check_header OMX_Core.h ; } || + die "ERROR: OpenMAX IL headers not found"; } +enabled openssl && { check_pkg_config openssl openssl/ssl.h SSL_library_init && { + add_cflags $openssl_cflags && add_extralibs $openssl_libs; }|| + check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto || check_lib openssl/ssl.h SSL_library_init -lssl32 -leay32 || check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || die "ERROR: openssl not found"; } if enabled gnutls; then - { check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed -lgmp && enable nettle; } || + { check_lib2 gmp.h mpz_export -lgmp && enable gmp; } || { check_lib gcrypt.h gcry_mpi_new -lgcrypt && enable gcrypt; } fi # libdc1394 check if enabled libdc1394; then - { check_lib dc1394/dc1394.h dc1394_new -ldc1394 -lraw1394 && + { require_pkg_config libdc1394-2 dc1394/dc1394.h dc1394_new && enable libdc1394_2; } || { check_lib libdc1394/dc1394_control.h dc1394_create_handle -ldc1394_control -lraw1394 && enable libdc1394_1; } || die "ERROR: No version of libdc1394 found " fi +if enabled nvenc; then + check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h not found." + check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" || + die "ERROR: NVENC API version 5 or older is not supported" +fi + if check_pkg_config sdl SDL_events.h SDL_PollEvent; then check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x010201" $sdl_cflags && check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x010300" $sdl_cflags && @@ -4243,6 +4719,11 @@ check_header linux/fb.h check_header linux/videodev2.h check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete +check_header AVFoundation/AVFoundation.h && + check_objcflags -fobjc-arc && + add_extralibs -framework Foundation -framework AVFoundation -framework CoreVideo -framework CoreMedia || + disable AVFoundation_AVFoundation_h + check_header sys/videoio.h check_func_headers "windows.h vfw.h" capCreateCaptureWindow "$vfwcap_indev_extralibs" @@ -4279,18 +4760,44 @@ fi check_lib X11/Xlib.h XOpenDisplay -lX11 && enable xlib -enabled x11grab && -require Xext X11/extensions/XShm.h XShmCreateImage -lXext && -require Xfixes X11/extensions/Xfixes.h XFixesGetCursorImage -lXfixes && -{ enabled xlib || die "ERROR: Xlib not found"; } +if enabled libxcb; then + check_pkg_config xcb-shape xcb/shape.h xcb_shape_rectangles || { + enabled libxcb && die "ERROR: libxcb not found"; + } && enable libxcb + + disabled libxcb_shm || + check_pkg_config xcb-shm xcb/shm.h xcb_shm_attach || { + enabled libxcb_shm && die "ERROR: libxcb_shm not found"; + } && check_header sys/shm.h && enable libxcb_shm + + disabled libxcb_xfixes || + check_pkg_config xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image || { + enabled libxcb_xfixes && die "ERROR: libxcb_xfixes not found"; + } && enable libxcb_xfixes + + add_cflags "$xcb_event_cflags $xcb_shm_cflags $xcb_xfixes_cflags" + add_extralibs "$xcb_event_libs $xcb_shm_libs $xcb_xfixes_libs" +fi + +enabled vaapi && + check_code cc "va/va.h" "vaCreateSurfaces(0, 0, 0, 0, 0, 0, 0, 0)" || + disable vaapi + +if enabled vaapi ; then + enabled xlib && + check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 && + enable vaapi_x11 + + check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm && + enable vaapi_drm +fi enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau enabled vdpau && enabled xlib && - check_func_headers "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau && - prepend avconv_libs $($ldflags_filter "-lvdpau") && + check_lib2 "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau && enable vdpau_x11 enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel" @@ -4301,13 +4808,13 @@ check_cflags -Wall check_cflags -Wdisabled-optimization check_cflags -Wpointer-arith check_cflags -Wredundant-decls -check_cflags -Wcast-qual check_cflags -Wwrite-strings check_cflags -Wtype-limits check_cflags -Wundef check_cflags -Wmissing-prototypes check_cflags -Wstrict-prototypes enabled extra_warnings && check_cflags -Winline +enabled extra_warnings && check_cflags -Wcast-qual check_disable_warning(){ warning_flag=-W${1#-Wno-} @@ -4322,6 +4829,7 @@ check_disable_warning -Wno-pointer-sign # add some linker flags check_ldflags -Wl,--warn-common check_ldflags -Wl,-rpath-link=libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample +enabled rpath && add_ldexeflags -Wl,-rpath,$libdir test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic # add some strip flags @@ -4351,17 +4859,25 @@ enabled xmm_clobber_test && -Wl,--wrap,sws_scale || disable xmm_clobber_test -echo "X{};" > $TMPV -if test_ldflags -Wl,--version-script,$TMPV; then - append SHFLAGS '-Wl,--version-script,\$(SUBDIR)lib\$(NAME).ver' - check_cc < $TMPV + if test_ldflags -Wl,${version_script},$TMPV; then + append SHFLAGS '-Wl,${version_script},\$(SUBDIR)lib\$(NAME).ver' + check_cc <= 12" || disable log2 + # The CRT headers contain __declspec(restrict) in a few places, but if redefining + # restrict, this might break. MSVC 2010 and 2012 fail with __declspec(__restrict) + # (as it ends up if the restrict redefine is done before including stdlib.h), while + # MSVC 2013 and newer can handle it fine. + # If this declspec fails, force including stdlib.h before the restrict redefinition + # happens in config.h. + if [ $_restrict != restrict ]; then + check_cc < $TMPH + for c in $*; do + enabled $c && printf " &ff_%s,\n" $c >> $TMPH + done + echo " NULL };" >> $TMPH + cp_if_changed $TMPH $file +} + +print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST +print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST + # build pkg-config files lib_version(){ @@ -4847,7 +5421,7 @@ Cflags: -I\${includedir} EOF } -pkgconfig_generate libavutil "Libav utility library" "$LIBAVUTIL_VERSION" "$LIBM" +pkgconfig_generate libavutil "Libav utility library" "$LIBAVUTIL_VERSION" "$LIBRT $LIBM" pkgconfig_generate libavcodec "Libav codec library" "$LIBAVCODEC_VERSION" "$extralibs" pkgconfig_generate libavformat "Libav container format library" "$LIBAVFORMAT_VERSION" "$extralibs" pkgconfig_generate libavdevice "Libav device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..b057241 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,6 @@ +/*.1 +/*.html +/*.pod +/avoptions_codec.texi +/avoptions_format.texi +/print_options diff --git a/doc/APIchanges b/doc/APIchanges index 7134e78..e8956e9 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,17 +2,280 @@ Never assume the API of libav* to be stable unless at least 1 month has passed since the last major version increase. The last version increases were: -libavcodec: 2014-08-09 -libavdevice: 2014-08-09 -libavfilter: 2014-08-09 -libavformat: 2014-08-09 -libavresample: 2014-08-09 -libswscale: 2014-08-09 -libavutil: 2014-08-09 +libavcodec: 2015-08-28 +libavdevice: 2015-08-28 +libavfilter: 2015-08-28 +libavformat: 2015-08-28 +libavresample: 2015-08-28 +libswscale: 2015-08-28 +libavutil: 2015-08-28 API changes, most recent first: +2016-07-20 - 7d7355a - lavu 55.20.0 - cpu.h + Add AV_CPU_FLAG_SSSE3SLOW. + +2016-07-02 - 4926fa9 - lavu 55.19.0 - hwcontext_vaapi.h + Add driver quirks field to VAAPI-specific hwdevice and enum with + members AV_VAAPI_DRIVER_QUIRK_* to represent its values. + +2016-07-02 - b7c5f88 - lavu 55.18.0 - pixfmt.h + Add AV_PIX_FMT_P010(LE/BE). + +2016-06-21 - 32c8359 - lavc 57.24.0 - avcodec.h + Decoders now export the frame timestamp as AVFrame.pts. It was + previously exported as AVFrame.pkt_pts, which is now deprecated. + +2016-06-21 - 59e7361 - lavu 55.16.0 - hwcontext.h hwcontext_qsv.h + Add AV_HWDEVICE_TYPE_QSV and a new installed header with QSV-specific + hwcontext definitions. + +2016-06-21 - e85f6f7 - lavc 57.23.0 - avcodec.h + AVCodecContext.hw_frames_ctx now may be used by decoders. + +2016-06-12 - 90f469a - lavc 57.20.0 - avcodec.h + Add FF_PROFILE_H264_MULTIVIEW_HIGH and FF_PROFILE_H264_STEREO_HIGH. + +2016-05-26 - 1c9e861 - lavu 55.13.0 - hwcontext.h + Add av_hwdevice_ctx_create(). + +2016-05-24 - ad61da05 - lavc 57.19.1 - avcodec.h + Adjust values for JPEG 2000 profiles. + +2016-05-18 - db7968b - lavf 57.7.0 - avio.h + Add AVIODataMarkerType, write_data_type, ignore_boundary_point and + avio_write_marker. + +2016-05-17 - 0c4468d - lavu 55.12.0 - opt.h + Add av_stereo3d_type_name() and av_stereo3d_from_name(). + +2016-05-17 - c46db38 - lavu 55.11.0 - hwcontext_dxva2.h + Add new installed header with DXVA2-specific hwcontext definitions. + +2016-03-24 - 564b459 - lavu 55.10.0 - opt.h + Add av_opt_copy(). + +2016-03-23 - 05f6670 - lavc 57.16.0 - avcodec.h + Add a new audio/video encoding and decoding API with decoupled input + and output -- avcodec_send_packet(), avcodec_receive_frame(), + avcodec_send_frame() and avcodec_receive_packet(). + +2016-03-20 - 33d1898 - lavc 57.15.0 - avcodec.h + Add a new bitstream filtering API working with AVPackets. + Deprecate the old bitstream filtering API. + +2016-03-19 - 07a844f - lavfi 6.3.0 - avfilter.h + Add AVFilterContext.hw_device_ctx. + +2016-03-19 - 551c677 - lavu 55.9.0 - hwcontext_vaapi.h + Add new installed header with VAAPI-specific hwcontext definitions. + +2016-03-19 - d264c72 - lavu 55.8.0 - pixfmt.h + Deprecate all AV_PIX_FMT_VAAPI_* formats. + Replaced by AV_PIX_FMT_VAAPI. + +2016-03-19 - b1f01e8 - lavu 55.7.0 - hwcontext.h + Add AVHWFramesConstraints and associated API. + +2016-02-23 - 9200514 - lavf 57.5.0 - avformat.h + Add AVStream.codecpar, deprecate AVStream.codec. + +2016-02-23 - lavc 57.14.0 - avcodec.h + 998e1b8 - Add AVCodecParameters and its related API. + a806834 - Add av_get_audio_frame_duration2(). + +2016-02-22 - ec4c483 - lavf 57.4.0 - avformat.h + Add AVFormatContext.protocol_whitelist and protocol_blacklist. + Add 'protocol_whitelist' and 'protocol_blacklist' private options for + avio_open2(). + +2016-02-14 - 7b3214d0 - lavc 57.13.0 - avcodec.h + Add AVCodecContext.hw_frames_ctx. + +2016-02-14 - lavfi 6.2.0 - avfilter.h + b3dd30d avfilter.h - Add AVFilterLink.hw_frames_ctx. + buffersrc.h - Add AVBufferSrcParameters and functions for handling it. + +2016-02-14 - lavu 55.6.0 + 721a4ef buffer.h - Add av_buffer_pool_init2(). + 89923e4 hwcontext.h - Add a new installed header hwcontext.h with a new API + for handling hwaccel frames. + ad884d1 hwcontext_cuda.h - Add a new installed header hwcontext_cuda.h with + CUDA-specific hwcontext definitions. + a001ce3 hwcontext_vdpau.h - Add a new installed header hwcontext_vdpau.h with + VDPAU-specific hwcontext definitions. + 7bc780c pixfmt.h - Add AV_PIX_FMT_CUDA. + +2016-01-24 - 9f61abc - lavf 57.3.0 - avformat.h + Add AVFormatContext.opaque, io_open and io_close, allowing custom IO + for muxers and demuxers that open additional files. + +2015-12-12 - 2c68113 - lavc 57.12.0 - avcodec.h + Add AVCodecDescriptor.profiles and avcodec_profile_name(). + +2015-12-06 - lavc 57.11.0 - avcodec.h dirac.h + 31c51f7 - Add av_packet_add_side_data(). + 84adab3 - Add AVCodecContext.coded_side_data. + f0b769c - Add AVCPBProperties API. + e02de9d - Add a new public header dirac.h containing + av_dirac_parse_sequence_header() + +2015-11-20 - 462a54e - lavc 57.9.1 - avcodec.h + Deprecate rtp_callback without replacement, i.e. it won't be possible to + get image slices before the full frame is encoded any more. The libavformat + rtpenc muxer can still be used for RFC-2190 packetization. + +2015-11-18 - 79ae1e6 - lavc 57.9.0 - avcodec.h + Add AV_PKT_DATA_FALLBACK_TRACK for making fallback associations between + streams. + +2015-11-18 - 7f4ec43 - lavf 57.1.0 - avformat.h + Add av_stream_new_side_data(). + +2015-11-13 - 92d107a - lavu 55.3.0 - xtea.h + Add av_xtea_le_init and av_xtea_le_crypt + +2015-11-09 - 48ff668 - lavfi 6.1.0 - avfilter.h + Add a frame_rate field to AVFilterLink + +2015-10-26 - lavc 57.7.0 - avcodec.h + ce70f28 - Deprecate av_free_packet(). Use av_packet_unref() as replacement, + it resets the packet in a more consistent way. + 9b56d5c - Deprecate av_dup_packet(), it is a no-op for most cases. + Use av_packet_ref() to make a non-refcounted AVPacket refcounted. + a9a6010 - Add av_packet_alloc(), av_packet_clone(), av_packet_free(). + They match the AVFrame functions with the same name. + +2015-10-21 - a17a766 - lavc 57.5.0 - avcodec.h + Add data and linesize array to AVSubtitleRect, to be used instead of + the ones from the embedded AVPicture. + +2015-10-16 - dc923bc - lavc 57.0.0 - qsv.h + Add an API for allocating opaque surfaces. + +2015-10-12 - 11c5f43 - lavu 55.2.0 - dict.h + Change return type of av_dict_copy() from void to int, so that a proper + error code can be reported. + +2015-09-29 - 948f3c1 - lavc 57.0.0 - avcodec.h + Change type of AVPacket.duration from int to int64_t. + +2015-09-18 - e3d4784 - lavc 57.2.0 - d3d11va.h + Add av_d3d11va_alloc_context(). This function must from now on be used for + allocating AVD3D11VAContext. + +2015-09-07 - lavu 55.0.0 + b8b5d82 - Change type of AVPixFmtDescriptor.flags from uint8_t to uint64_t. + 6b3ef7f - Change type of AVComponentDescriptor fields from uint16_t to int + and drop bit packing. + 2268db2 - Add step, offset, and depth to AVComponentDescriptor to replace + the deprecated step_minus1, offset_plus1, and depth_minus1. + +2015-07-31 - lavu 54.17.0 + 7a7df34 - Add av_blowfish_alloc(). + ae36545 - Add av_rc4_alloc(). + 5d8bea3 - Add av_xtea_alloc(). + d9e8b47 - Add av_des_alloc(). + +2015-07-29 - 7e38340 - lavu 54.16.0 - hmac.h + Add AV_HMAC_SHA224 and AV_HMAC_SHA256. + +2015-07-27 - lavc 56.35.0 - avcodec.h + 7c6eb0a - Rename CODEC_FLAG* defines to AV_CODEC_FLAG*. + def9785 - Rename CODEC_CAP_* defines to AV_CODEC_CAP_*. + 059a934 - Rename FF_INPUT_BUFFER_PADDING_SIZE and FF_MIN_BUFFER_SIZE + to AV_INPUT_BUFFER_PADDING_SIZE and AV_INPUT_BUFFER_MIN_SIZE. + +2015-07-20 - 5d3addb - lavc 56.33.0 - avcodec.h + Add AV_PKT_DATA_QUALITY_FACTOR to export the quality value of an AVPacket. + +2015-07-02 - 1316df7 - lavu 56.15.0 + Add av_version_info(). + +2015-07-01 - 0d449c8 - lavfi 5.1.0 - version.h + 0f87f9b - lavd 55.2.0 - version.h + Add library identification symbols, LIBAVFILTER_IDENT and LIBAVDEVICE_IDENT. + +2015-06-07 - 252d620 - lavf 56.20.0 - avio.h + Add avio_put_str16be. + +2015-05-13 - f7cafb5 - lavu 54.14.0 - cpu.h + Add AV_CPU_FLAG_AVXSLOW. + +2015-05-13 - e7c5e17 - lavc 56.23.0 + Add av_vda_default_init2. + +2015-04-19 - c253340 - lavu 54.12.0 + Add AV_LOG_TRACE for extremely verbose debugging. + +2015-04-07 - 27f2746 - lavu 54.11.0 + Add av_small_strptime(). + +2015-03-29 - 6fe2641 - lavc 56.22.0 + Add FF_PROFILE_DTS_EXPRESS. + +2015-03-29 - c484561 - lavu 54.10.0 + Add AV_PIX_FMT_MMAL for MMAL hardware acceleration. + +2015-02-19 - 31d2039 - lavc 56.13 + Add width, height, coded_width, coded_height and format to + AVCodecParserContext. + +2015-02-19 - 5b1d9ce - lavu 54.9.0 + Add AV_PIX_FMT_QSV for QSV hardware acceleration. + +2015-01-27 - 728685f - lavc 56.12.0, lavu 54.8.0 - avcodec.h, frame.h + Add AV_PKT_DATA_AUDIO_SERVICE_TYPE and AV_FRAME_DATA_AUDIO_SERVICE_TYPE for + storing the audio service type as side data. + +2015-01-14 - e2ad0b6 - lavu 54.6.0 - imgutils.h + Add utility functions for image manipulation: av_image_get_buffer_size() + av_image_fill_arrays() and av_image_copy_to_buffer(). + +2014-12-25 - c220a60 - lavc 56.10.0 - vdpau.h + Add av_vdpau_get_surface_parameters(). + +2014-12-25 - 6c99c92 - lavc 56.9.0 - avcodec.h + Add AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH flag to av_vdpau_bind_context(). + +2014-12-25 - 57b6704 - lavc 56.8.0 - avcodec.h + Add AVCodecContext.sw_pix_fmt. + +2014-11-07 - 1384df6 - lavf 56.06.3 - avformat.h + Add AVFormatContext.avoid_negative_ts. + +2014-11-06 - 5e80fb7 - lavc 56.6.0 - vorbis_parser.h + Add a public API for parsing vorbis packets. + +2014-10-24 - 1bd0bdc - lavu 54.5.0 - time.h + Add av_gettime_relative(). + +2014-10-15 - 7ea1b34 - lavc 56.5.0 - avcodec.h + Replace AVCodecContext.time_base used for decoding + with AVCodecContext.framerate. + +2014-10-15 - d565fef1- lavc 56.4.0 - avcodec.h + Add AV_HWACCEL_FLAG_IGNORE_LEVEL flag to av_vdpau_bind_context(). + +2014-10-13 - 2df0c32 - lavc 56.03.0 - avcodec.h + Add AVCodecContext.initial_padding. Deprecate the use of AVCodecContext.delay + for audio encoding. + +2014-10-08 - 5a419b2 - lavu 54.04.0 - pixdesc.h + Add API to return the name of frame and context color properties. + +2014-10-06 - e3e158e - lavc 56.2.0 - vdpau.h + Add av_vdpau_bind_context(). This function should now be used for creating + (or resetting) a AVVDPAUContext instead of av_vdpau_alloc_context(). + +2014-08-25 - b263f8f - lavf 56.03.0 - avformat.h + Add AVFormatContext.max_ts_probe. + +------------------------------8<------------------------------------- + 11 branch was cut here +----------------------------->8-------------------------------------- + 2014-08-28 - 9301486 - lavc 56.1.0 - avcodec.h Add AV_PKT_DATA_STEREO3D to export container-level stereo3d information. @@ -126,7 +389,7 @@ API changes, most recent first: AVCodecContext. 2014-05-15 - 0c1959b - lavf 55.17.0 - avformat.h - Add AVMFT_FLAG_BITEXACT flag. Muxers now use it instead of checking + Add AVFMT_FLAG_BITEXACT flag. Muxers now use it instead of checking CODEC_FLAG_BITEXACT on the first stream. 2014-05-11 - 66e6c8a - lavu 53.14.0 - pixfmt.h @@ -278,7 +541,7 @@ API changes, most recent first: 2013-08-05 - f824535 - lavc 55.13.0 - avcodec.h Deprecate the bitstream-related members from struct AVVDPAUContext. - The bistream buffers no longer need to be explicitly freed. + The bitstream buffers no longer need to be explicitly freed. 2013-08-05 - 549294f - lavc 55.12.0 - avcodec.h Deprecate the CODEC_CAP_HWACCEL_VDPAU codec capability. Use CODEC_CAP_HWACCEL @@ -368,7 +631,7 @@ lavd 54.0.0, lavfi 3.5.0 * base -- is now stored in AVBufferRef * reference, type, buffer_hints -- are unnecessary in the new API * hwaccel_picture_private, owner, thread_opaque -- should not - have been acessed from outside of lavc + have been accessed from outside of lavc * qscale_table, qstride, qscale_type, mbskip_table, motion_val, mb_type, dct_coeff, ref_index -- mpegvideo-specific tables, which are not exported anymore. @@ -409,8 +672,10 @@ lavd 54.0.0, lavfi 3.5.0 9 branch was cut here ----------------------------->8-------------------------------------- -2012-12-29 - d8fd06c - lavu 52.3.0 - avstring.h - Add av_basename() and av_dirname(). +2012-12-29 - lavu 52.3.0 + d8fd06c - Add av_basename() and av_dirname(). + c1a02e8 - Add av_pix_fmt_get_chroma_sub_sample and deprecate + avcodec_get_chroma_sub_sample. 2012-11-11 - 5980f5d - lavu 52.2.0 - audioconvert.h Rename audioconvert.h to channel_layout.h. audioconvert.h is now deprecated. diff --git a/doc/Doxyfile b/doc/Doxyfile index 58f7dfb..08c81f3 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -646,7 +646,7 @@ EXAMPLE_PATH = # and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = *-example.c +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 diff --git a/doc/Makefile b/doc/Makefile index 1c205a5..2f6a5fb 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -19,6 +19,7 @@ DOC_EXAMPLES-$(CONFIG_AVCODEC_EXAMPLE) += avcodec DOC_EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata DOC_EXAMPLES-$(CONFIG_OUTPUT_EXAMPLE) += output +DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec DOC_EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac ALL_DOC_EXAMPLES = avcodec filter_audio metadata output transcode_aac diff --git a/doc/RELEASE_NOTES b/doc/RELEASE_NOTES index bda4789..a440a3a 100644 --- a/doc/RELEASE_NOTES +++ b/doc/RELEASE_NOTES @@ -1,48 +1,31 @@ Release Notes ============= -* 11 "One Louder" +* 12 "Not Enough Trocadero" General notes ------------- -With this release we are trying to answer the numerous calls from our users for -shorter development cycles. From now on we will aim for approximately two major -releases per year. +This release once again bumps the major versions of all the libraries, removing +some long-deprecated APIs. This means that it is neither API nor ABI-compatible +with the previous release. The users who still did not update their code are +advised to look at the next section of these release notes, the doc/APIchanges +file and the API migration guide on our wiki. If those are not sufficient, do +not hesitate to contact us on IRC or through the user mailing list. -Libav 11 is API-, but not ABI-compatible with the previous major release. This -means that the code using our libraries needs to be rebuilt, but no source -changes should be required. Note however, that a number of old APIs remain -deprecated and will be dropped in the near future. All users are strongly -encouraged to update their code as soon as possible. The doc/APIchanges file in -the Libav source tree and the migration guide on the wiki should help with -migration to the new APIs. If those are not sufficient, do not hesitate to -contact us on IRC or through the user mailing list. +Among the main highlights of this release are several additions related to +hardware acceleration. There is a new API for managing hardware devices and +frame pools, which allows to add new features such as zero-copy +hardware-accelerated filtering with libavfilter and should reduce the +boilerplate code required for existing hardware-accelerated decoders. We have +added QuickSync decoding and encoding, NVENC encoding and CUDA image scaling, +VAAPI encoding and image scaling, OpenMAX encoding, MMAL decoding and Direct3D11 +decoding. -One specific API issue in libavformat deserves mentioning here. When using -libavcodec for decoding or encoding and libavformat for demuxing or muxing, -the standard practice was to use the stream codec context (AVStream.codec) for -actual decoding or encoding. There are multiple problems with this pattern -(the main one is that the decoder/demuxer or encoder/muxer are not necessarily -synchronized and may overwrite each other's state), so it is now strongly -discouraged and will likely be deprecated in the future. Users should instead -allocate a separate decoding or encoding context and populate it from the -demuxing codec context (or the reverse for encoding) with the -avcodec_copy_context() function. - -The main highlights of this release include native Opus, VP7, OpenEXR, and On2 -AVC decoders, HEVC encoding through libx265, new APIs for exporting ReplayGain -and display transformation metadata and countless bug fixes. A large effort was -also expended on internal cleanups which are not very visible to our users, -but should make the codebase cleaner, safer and easier to maintain and extend. -One point worth mentioning is refactoring the large monolithic framework for -architecture-specific codec optimizations into small blocks, which reduces the -size of configurations that selectively enable or disable certain codecs. - -The avserver streaming tool, which has not been maintained for many years and -was mostly broken, was removed from the tree. It was decided that it is a -significant maintenance burden and that we do our users no service by pretending -to support it, while we in fact do not. +Other significant additions not related to hardware acceleration include +decoders for Canopus HQ/HQA and HQX, Go2Meeting, AAC ELD, TDSC, Hap, DXV, SPV1, +and a new ASF demuxer written according to the specification. There were also +countless smaller changes and bug fixes. See the Changelog file for a more extensive list of significant changes. @@ -54,22 +37,38 @@ have been deprecated and are scheduled for removal in the next release. Significant API changes include: [libavcodec] -+ Added the avcodec_copy_context() function that must from now on be used for - freeing codec contexts. -+- Added a new VDA hardware acceleration API, since the old one was broken and - not fixable in a compatible way. Deprecated the old VDA API. ++ Added an object for storing codec parameters (AVCodecParameters) and its + related API. It will now replace AVCodecContext everywhere except the actual + encoders/decoders. ++- Added a new API for handling refcounted AVPackets, mirroring the AVFrame API. + Deprecated certain old ill-defined AVPacket functions. ++- Added a new API for audio/video encoding and decoding, with decoupled input + and output. This will e.g. allow a decoder to produce multiple output frames + for a single input packet, which was not possible with the previous API. All + users are strongly encouraged to switch to this new API as soon as possible, + since certain decoders and encoders might start requiring the new API to be + used. ++- Added a new API for bitstream filtering, which works with refcounted + AVPackets and is more clearly defined and documented. The old bitstream + filtering API is now deprecated. [libavformat] -+ Added support for exporting stream-global (as opposed to per-packet) side - data. This feature is now used by some demuxers to export ReplayGain or - display transformation matrix (aka rotation) or stereoscopic 3D mode. -+ Added an API for live metadata updates through event flags. -+- Changed the way to provide a hint about the desired timebase to muxers. - Previously it was done by setting AVStream.codec.time_base. Now callers - should set AVStream.time_base. ++ Added new IO callbacks to AVFormatContext, allowing the caller to provide + custom IO for certain special muxers and demuxers. ++- Replaced AVStream.codec (AVCodecContext) with AVStream.codecpar + (AVCodecParameters) as the means of signalling codec parameters between the + muxers/demuxers and the caller. + +[libavutil] ++ Added a new API (hwcontext.h) for handling hardware acceleration devices and + hardware frame pools. -[libavresample] -+ Added an API for working with AVFrames. +[libavfilter] ++ Added a new struct, AVBufferSrcParameters, for passing the stream parameters + to the buffer source. It is now the recommended way of configuring the buffer + source. ++ Added AVFilterContext.hw_device_ctx and AVFilterLink.hw_frames_ctx that allow + hardware frames to be used in filter graphs. Please see the file doc/APIchanges for details along with similar programmer-centric information. diff --git a/doc/avconv.texi b/doc/avconv.texi index 37733bc..9f2f295 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -253,6 +253,10 @@ Overwrite output files without asking. @item -n (@emph{global}) Immediately exit when output files already exist. +@item -loop @var{number} (@emph{input}) +Set number of times input stream shall be looped. Loop 0 means no loop, +loop -1 means infinite loop. + @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream}) @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream}) Select an encoder (when used before an output file) or a decoder (when used @@ -401,6 +405,9 @@ Technical note -- attachments are implemented as codec extradata, so this option can actually be used to extract extradata from any stream, not just attachments. +@item -noautorotate +Disable automatically rotating video based on file metadata. + @end table @section Video Options @@ -490,6 +497,14 @@ abbreviations are recognized: 1280x720 @item hd1080 1920x1080 +@item 2kdci +2048x1080 +@item 4kdci +4096x2160 +@item uhd2160 +3840x2160 +@item uhd4320 +7680x4320 @end table @item -aspect[:@var{stream_specifier}] @var{aspect} (@emph{output,per-stream}) @@ -588,6 +603,16 @@ Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. @item dxva2 Use DXVA2 (DirectX Video Acceleration) hardware acceleration. + +@item qsv +Use the Intel QuickSync Video acceleration for video transcoding. + +Unlike most other values, this option does not enable accelerated decoding (that +is used automatically whenever a qsv decoder is selected), but accelerated +transcoding, without copying the frames into the system memory. + +For it to work, both the decoder and the encoder must support QSV acceleration +and no filters must be used. @end table This option has no effect if the selected hwaccel is not available or not @@ -614,7 +639,25 @@ is not specified, the value of the @var{DISPLAY} environment variable is used @item dxva2 For DXVA2, this option should contain the number of the display adapter to use. If this option is not specified, the default adapter is used. + +@item qsv +For QSV, this option corresponds to the values of MFX_IMPL_* . Allowed values +are: +@table @option +@item auto +@item sw +@item hw +@item auto_any +@item hw_any +@item hw2 +@item hw3 +@item hw4 +@end table @end table + +@item -hwaccels +List all hardware acceleration methods supported in this build of avconv. + @end table @section Audio Options @@ -843,7 +886,7 @@ avconv -i infile -streamid 0:33 -streamid 1:36 out.ts @end example @item -bsf[:@var{stream_specifier}] @var{bitstream_filters} (@emph{output,per-stream}) -Set bitstream filters for matching streams. @var{bistream_filters} is +Set bitstream filters for matching streams. @var{bitstream_filters} is a comma-separated list of bitstream filters. Use the @code{-bsfs} option to get the list of bitstream filters. @example @@ -913,6 +956,15 @@ This option enables or disables accurate seeking in input files with the transcoding. Use @option{-noaccurate_seek} to disable it, which may be useful e.g. when copying some streams and transcoding the others. +@item -max_muxing_queue_size @var{packets} (@emph{output,per-stream}) +When transcoding audio and/or video streams, avconv will not begin writing into +the output until it has one packet for each such stream. While waiting for that +to happen, packets for other streams are buffered. This option sets the size of +this buffer, in packets, for the matching output stream. + +The default value of this option should be high enough for most uses, so only +touch this option if you are sure that you need it. + @end table @c man end OPTIONS diff --git a/doc/avplay.texi b/doc/avplay.texi index 71981f6..0f72cfd 100644 --- a/doc/avplay.texi +++ b/doc/avplay.texi @@ -20,7 +20,7 @@ avplay [options] @file{input_file} @chapter Description @c man begin DESCRIPTION -AVplay is a very simple and portable media player using the Libav +avplay is a very simple and portable media player using the Libav libraries and the SDL library. It is mostly used as a testbed for the various Libav APIs. @c man end @@ -109,12 +109,14 @@ Select the desired subtitle stream number, counting from 0. The number refers to the list of all the input subtitle streams. If it is greater than the number of subtitle streams minus one, then the last one is selected, if it is negative the subtitle rendering is disabled. -@item -autoexit -Exit when video is done playing. +@item -noautoexit +Do not exit after playback is finished. @item -exitonkeydown Exit if any key is pressed. @item -exitonmousedown Exit if any mouse button is pressed. +@item -noautorotate +Disable automatically rotating video based on file metadata. @end table @section While playing @@ -169,7 +171,7 @@ Seek to percentage in file corresponding to fraction of width. @ignore @setfilename avplay -@settitle AVplay media player +@settitle avplay media player @c man begin SEEALSO avconv(1), avprobe(1) and the Libav HTML documentation diff --git a/doc/avtools-common-opts.texi b/doc/avtools-common-opts.texi index 8468eca..a7b0e03 100644 --- a/doc/avtools-common-opts.texi +++ b/doc/avtools-common-opts.texi @@ -19,7 +19,7 @@ are used to precisely specify which stream(s) does a given option belong to. A stream specifier is a string generally appended to the option name and separated from it by a colon. E.g. @code{-codec:a:1 ac3} option contains -@code{a:1} stream specifer, which matches the second audio stream. Therefore it +@code{a:1} stream specifier, which matches the second audio stream. Therefore it would select the ac3 codec for the second audio stream. A stream specifier can match several stream, the option is then applied to all @@ -48,6 +48,9 @@ Match the stream by stream id (e.g. PID in MPEG-TS container). Matches streams with the metadata tag @var{key} having the specified value. If @var{value} is not given, matches streams that contain the given tag with any value. +@item u +Matches streams with usable configuration, the codec must be defined and the +essential information such as video dimension or audio sample rate must be present. Note that in @command{avconv}, matching by metadata will only work properly for input files. @@ -142,6 +145,7 @@ Set the logging level used by the library. @item info @item verbose @item debug +@item trace @end table By default the program logs to stderr, if coloring is supported by the diff --git a/doc/avutil.txt b/doc/avutil.txt index 0847683..b8e5ca5 100644 --- a/doc/avutil.txt +++ b/doc/avutil.txt @@ -15,7 +15,7 @@ md5.c MD5 Message-Digest Algorithm rational.c code to perform exact calculations with rational numbers tree.c generic AVL tree crc.c generic CRC checksumming code -integer.c 128bit integer math +integer.c 128-bit integer math lls.c mathematics.c greatest common divisor, integer sqrt, integer log2, ... mem.c memory allocation routines with guaranteed alignment diff --git a/doc/build_system.txt b/doc/build_system.txt index c3dede7..3c5f156 100644 --- a/doc/build_system.txt +++ b/doc/build_system.txt @@ -19,11 +19,8 @@ all install Install headers, libraries and programs. -libavformat/output-example +doc/examples/output Build the libavformat basic example. -libavcodec/api-example - Build the libavcodec basic example. - libswscale/swscale-test Build the swscale self-test (useful also as example). diff --git a/doc/decoders.texi b/doc/decoders.texi index c3573a6..99d2008 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -32,7 +32,7 @@ AC-3 audio decoder. This decoder implements part of ATSC A/52:2010 and ETSI TS 102 366, as well as the undocumented RealAudio 3 (a.k.a. dnet). -@subsubsection AC-3 Decoder Options +@subsection AC-3 Decoder Options @table @option diff --git a/doc/developer.texi b/doc/developer.texi index 00e2b60..31c2baf 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -15,15 +15,15 @@ @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. +decoding). Look at @file{doc/examples/avcodec.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{avplay.c} to use it in a -player. See @file{libavformat/output-example.c} to use it to generate +player. See @file{doc/examples/output.c} to use it to generate audio or video streams. @end itemize -@section Integrating libav in your program +@section Integrating Libav in your program Shared libraries should be used whenever is possible in order to reduce the effort distributors have to pour to support programs and to ensure @@ -617,7 +617,7 @@ least make sure that it does not break anything. If the code changed has already a test present in FATE you should run it, otherwise it is advised to add it. -Improvements to codec or demuxer might change the FATE results. Make sure +Improvements to a codec or demuxer might change the FATE results. Make sure to commit the update reference with the change and to explain in the comment why the expected result changed. diff --git a/doc/doxy/.gitignore b/doc/doxy/.gitignore new file mode 100644 index 0000000..ac7af2e --- /dev/null +++ b/doc/doxy/.gitignore @@ -0,0 +1 @@ +/html/ diff --git a/doc/encoders.texi b/doc/encoders.texi index 94d8340..bc5b336 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -603,8 +603,6 @@ options follow the Libav ones. @tab Noise reduction. @item me_range @tab merange @tab Maximum range of the motion search in pixels. -@item me_method @tab me -@tab Full-pixel motion estimation method. @item subq @tab subme @tab Sub-pixel motion estimation method. @item b_strategy @tab b-adapt @@ -805,8 +803,8 @@ Use @var{0} to disable alpha plane coding. @subsection Speed considerations In the default mode of operation the encoder has to honor frame constraints -(i.e. not produc frames with size bigger than requested) while still making -output picture as good as possible. +(i.e. not produce frames with a size larger than requested) while still making +the output picture as good as possible. A frame containing a lot of small details is harder to compress and the encoder would spend more time searching for appropriate quantizers for each slice. @@ -815,4 +813,113 @@ Setting a higher @option{bits_per_mb} limit will improve the speed. For the fastest encoding speed set the @option{qscale} parameter (4 is the recommended value) and do not set a size constraint. +@section libkvazaar + +Kvazaar H.265/HEVC encoder. + +Requires the presence of the libkvazaar headers and library during +configuration. You need to explicitly configure the build with +@option{--enable-libkvazaar}. + +@subsection Options + +@table @option + +@item b +Set target video bitrate in bit/s and enable rate control. + +@item kvazaar-params +Set kvazaar parameters as a list of @var{name}=@var{value} pairs separated +by commas (,). See kvazaar documentation for a list of options. + +@end table + +@section QSV encoders + +The family of Intel QuickSync Video encoders (MPEG-2, H.264 and HEVC) + +The ratecontrol method is selected as follows: + +@itemize @bullet +@item +When @option{global_quality} is specified, a quality-based mode is used. +Specifically this means either +@itemize @minus +@item +@var{CQP} - constant quantizer scale, when the @option{qscale} codec flag is +also set (the @option{-qscale} avconv option). + +@item +@var{LA_ICQ} - intelligent constant quality with lookahead, when the +@option{la_depth} option is also set. + +@item +@var{ICQ} -- intelligent constant quality otherwise. +@end itemize + +@item +Otherwise, a bitrate-based mode is used. For all of those, you should specify at +least the desired average bitrate with the @option{b} option. +@itemize @minus +@item +@var{LA} - VBR with lookahead, when the @option{la_depth} option is specified. + +@item +@var{VCM} - video conferencing mode, when the @option{vcm} option is set. + +@item +@var{CBR} - constant bitrate, when @option{maxrate} is specified and equal to +the average bitrate. + +@item +@var{VBR} - variable bitrate, when @option{maxrate} is specified, but is higher +than the average bitrate. + +@item +@var{AVBR} - average VBR mode, when @option{maxrate} is not specified. This mode +is further configured by the @option{avbr_accuracy} and +@option{avbr_convergence} options. +@end itemize +@end itemize + +Note that depending on your system, a different mode than the one you specified +may be selected by the encoder. Set the verbosity level to @var{verbose} or +higher to see the actual settings used by the QSV runtime. + +Additional libavcodec global options are mapped to MSDK options as follows: + +@itemize +@item +@option{g/gop_size} -> @option{GopPicSize} + +@item +@option{bf/max_b_frames}+1 -> @option{GopRefDist} + +@item +@option{rc_init_occupancy/rc_initial_buffer_occupancy} -> +@option{InitialDelayInKB} + +@item +@option{slices} -> @option{NumSlice} + +@item +@option{refs} -> @option{NumRefFrame} + +@item +@option{b_strategy/b_frame_strategy} -> @option{BRefType} + +@item +@option{cgop/CLOSED_GOP} codec flag -> @option{GopOptFlag} + +@item +For the @var{CQP} mode, the @option{i_qfactor/i_qoffset} and +@option{b_qfactor/b_qoffset} set the difference between @var{QPP} and @var{QPI}, +and @var{QPP} and @var{QPB} respectively. + +@item +Setting the @option{coder} option to the value @var{vlc} will make the H.264 +encoder use CAVLC instead of CABAC. + +@end itemize + @c man end VIDEO ENCODERS diff --git a/doc/examples/.gitignore b/doc/examples/.gitignore new file mode 100644 index 0000000..3f60af7 --- /dev/null +++ b/doc/examples/.gitignore @@ -0,0 +1,5 @@ +/avcodec +/filter_audio +/metadata +/output +/transcode_aac diff --git a/doc/examples/avcodec.c b/doc/examples/avcodec.c index 1478881..8fee552 100644 --- a/doc/examples/avcodec.c +++ b/doc/examples/avcodec.c @@ -23,9 +23,9 @@ * libavcodec API use example. * * @example avcodec.c - * Note that this library only handles codecs (mpeg, mpeg4, etc...), - * not file formats (avi, vob, etc...). See library 'libavformat' for the - * format handling + * Note that this library only handles codecs (MPEG, MPEG-4, etc...), + * not file formats (AVI, VOB, etc...). See library 'libavformat' for the + * format handling. */ #include @@ -206,15 +206,14 @@ static void audio_encode_example(const char *filename) } if (got_output) { fwrite(pkt.data, 1, pkt.size, f); - av_free_packet(&pkt); + av_packet_unref(&pkt); } } fclose(f); av_freep(&samples); av_frame_free(&frame); - avcodec_close(c); - av_free(c); + avcodec_free_context(&c); } /* @@ -226,7 +225,7 @@ static void audio_decode_example(const char *outfilename, const char *filename) AVCodecContext *c= NULL; int len; FILE *f, *outfile; - uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; AVPacket avpkt; AVFrame *decoded_frame = NULL; @@ -234,7 +233,7 @@ static void audio_decode_example(const char *outfilename, const char *filename) printf("Audio decoding\n"); - /* find the mpeg audio decoder */ + /* find the MPEG audio decoder */ codec = avcodec_find_decoder(AV_CODEC_ID_MP2); if (!codec) { fprintf(stderr, "codec not found\n"); @@ -305,8 +304,7 @@ static void audio_decode_example(const char *outfilename, const char *filename) fclose(outfile); fclose(f); - avcodec_close(c); - av_free(c); + avcodec_free_context(&c); av_frame_free(&decoded_frame); } @@ -325,7 +323,7 @@ static void video_encode_example(const char *filename) printf("Video encoding\n"); - /* find the mpeg1 video encoder */ + /* find the mpeg1video encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "codec not found\n"); @@ -403,7 +401,7 @@ static void video_encode_example(const char *filename) if (got_output) { printf("encoding frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); - av_free_packet(&pkt); + av_packet_unref(&pkt); } } @@ -420,16 +418,15 @@ static void video_encode_example(const char *filename) if (got_output) { printf("encoding frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); - av_free_packet(&pkt); + av_packet_unref(&pkt); } } - /* add sequence end code to have a real mpeg file */ + /* add sequence end code to have a real MPEG file */ fwrite(endcode, 1, sizeof(endcode), f); fclose(f); - avcodec_close(c); - av_free(c); + avcodec_free_context(&c); av_freep(&picture->data[0]); av_frame_free(&picture); printf("\n"); @@ -459,18 +456,18 @@ static void video_decode_example(const char *outfilename, const char *filename) int frame, got_picture, len; FILE *f; AVFrame *picture; - uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; char buf[1024]; AVPacket avpkt; av_init_packet(&avpkt); - /* 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); + /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ + memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); printf("Video decoding\n"); - /* find the mpeg1 video decoder */ + /* find the MPEG-1 video decoder */ codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "codec not found\n"); @@ -480,8 +477,8 @@ static void video_decode_example(const char *outfilename, const char *filename) c = avcodec_alloc_context3(codec); picture = av_frame_alloc(); - if(codec->capabilities&CODEC_CAP_TRUNCATED) - c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ + if (codec->capabilities & AV_CODEC_CAP_TRUNCATED) + c->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not @@ -545,9 +542,9 @@ static void video_decode_example(const char *outfilename, const char *filename) } } - /* some codecs, such as MPEG, transmit the I and P frame with a + /* 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 */ + chance to get the last frame of the video. */ avpkt.data = NULL; avpkt.size = 0; len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); @@ -565,8 +562,7 @@ static void video_decode_example(const char *outfilename, const char *filename) fclose(f); - avcodec_close(c); - av_free(c); + avcodec_free_context(&c); av_frame_free(&picture); printf("\n"); } diff --git a/doc/examples/output.c b/doc/examples/output.c index 0534554..44a55f5 100644 --- a/doc/examples/output.c +++ b/doc/examples/output.c @@ -52,6 +52,7 @@ // a wrapper around a single output AVStream typedef struct OutputStream { AVStream *st; + AVCodecContext *enc; /* pts of the next frame that will be generated */ int64_t next_pts; @@ -85,13 +86,18 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc, exit(1); } - ost->st = avformat_new_stream(oc, codec); + ost->st = avformat_new_stream(oc, NULL); if (!ost->st) { fprintf(stderr, "Could not alloc stream\n"); exit(1); } - c = ost->st->codec; + c = avcodec_alloc_context3(codec); + if (!c) { + fprintf(stderr, "Could not alloc an encoding context\n"); + exit(1); + } + ost->enc = c; /* put sample parameters */ c->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16; @@ -104,7 +110,7 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc, // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; /* initialize sample format conversion; * to simplify the code, we always pass the data through lavr, even @@ -162,9 +168,9 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, static void open_audio(AVFormatContext *oc, OutputStream *ost) { AVCodecContext *c; - int nb_samples; + int nb_samples, ret; - c = ost->st->codec; + c = ost->enc; /* open it */ if (avcodec_open2(c, NULL, NULL) < 0) { @@ -178,7 +184,7 @@ static void open_audio(AVFormatContext *oc, OutputStream *ost) /* increment frequency by 110 Hz per second */ ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) + if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) nb_samples = 10000; else nb_samples = c->frame_size; @@ -187,6 +193,13 @@ static void open_audio(AVFormatContext *oc, OutputStream *ost) c->sample_rate, nb_samples); ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_STEREO, 44100, nb_samples); + + /* copy the stream parameters to the muxer */ + ret = avcodec_parameters_from_context(ost->st->codecpar, c); + if (ret < 0) { + fprintf(stderr, "Could not copy the stream parameters\n"); + exit(1); + } } /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and @@ -198,14 +211,14 @@ static AVFrame *get_audio_frame(OutputStream *ost) int16_t *q = (int16_t*)frame->data[0]; /* check if we want to generate more frames */ - if (av_compare_ts(ost->next_pts, ost->st->codec->time_base, + if (av_compare_ts(ost->next_pts, ost->enc->time_base, STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) return NULL; for (j = 0; j < frame->nb_samples; j++) { v = (int)(sin(ost->t) * 10000); - for (i = 0; i < ost->st->codec->channels; i++) + for (i = 0; i < ost->enc->channels; i++) *q++ = v; ost->t += ost->tincr; ost->tincr += ost->tincr2; @@ -224,12 +237,12 @@ static int encode_audio_frame(AVFormatContext *oc, OutputStream *ost, int got_packet; av_init_packet(&pkt); - avcodec_encode_audio2(ost->st->codec, &pkt, frame, &got_packet); + avcodec_encode_audio2(ost->enc, &pkt, frame, &got_packet); if (got_packet) { pkt.stream_index = ost->st->index; - av_packet_rescale_ts(&pkt, ost->st->codec->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, ost->enc->time_base, ost->st->time_base); /* Write the compressed frame to the media file. */ if (av_interleaved_write_frame(oc, &pkt) != 0) { @@ -324,13 +337,18 @@ static void add_video_stream(OutputStream *ost, AVFormatContext *oc, exit(1); } - ost->st = avformat_new_stream(oc, codec); + ost->st = avformat_new_stream(oc, NULL); if (!ost->st) { fprintf(stderr, "Could not alloc stream\n"); exit(1); } - c = ost->st->codec; + c = avcodec_alloc_context3(codec); + if (!c) { + fprintf(stderr, "Could not alloc an encoding context\n"); + exit(1); + } + ost->enc = c; /* Put sample parameters. */ c->bit_rate = 400000; @@ -347,7 +365,7 @@ static void add_video_stream(OutputStream *ost, AVFormatContext *oc, c->gop_size = 12; /* emit one intra frame every twelve frames at most */ c->pix_fmt = STREAM_PIX_FMT; if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - /* just for testing, we also add B frames */ + /* just for testing, we also add B-frames */ c->max_b_frames = 2; } if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) { @@ -358,7 +376,7 @@ static void add_video_stream(OutputStream *ost, AVFormatContext *oc, } /* Some formats want stream headers to be separate. */ if (oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height) @@ -387,8 +405,9 @@ static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height) static void open_video(AVFormatContext *oc, OutputStream *ost) { AVCodecContext *c; + int ret; - c = ost->st->codec; + c = ost->enc; /* open the codec */ if (avcodec_open2(c, NULL, NULL) < 0) { @@ -414,6 +433,13 @@ static void open_video(AVFormatContext *oc, OutputStream *ost) exit(1); } } + + /* copy the stream parameters to the muxer */ + ret = avcodec_parameters_from_context(ost->st->codecpar, c); + if (ret < 0) { + fprintf(stderr, "Could not copy the stream parameters\n"); + exit(1); + } } /* Prepare a dummy image. */ @@ -448,10 +474,10 @@ static void fill_yuv_image(AVFrame *pict, int frame_index, static AVFrame *get_video_frame(OutputStream *ost) { - AVCodecContext *c = ost->st->codec; + AVCodecContext *c = ost->enc; /* check if we want to generate more frames */ - if (av_compare_ts(ost->next_pts, ost->st->codec->time_base, + if (av_compare_ts(ost->next_pts, c->time_base, STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) return NULL; @@ -491,48 +517,30 @@ static int write_video_frame(AVFormatContext *oc, OutputStream *ost) int ret; AVCodecContext *c; AVFrame *frame; + AVPacket pkt = { 0 }; int got_packet = 0; - c = ost->st->codec; + c = ost->enc; frame = get_video_frame(ost); - if (oc->oformat->flags & AVFMT_RAWPICTURE) { - /* a hack to avoid data copy with some raw video muxers */ - AVPacket pkt; - av_init_packet(&pkt); - - if (!frame) - return 1; + av_init_packet(&pkt); - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index = ost->st->index; - pkt.data = (uint8_t *)frame; - pkt.size = sizeof(AVPicture); + /* encode the image */ + ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); + if (ret < 0) { + fprintf(stderr, "Error encoding a video frame\n"); + exit(1); + } - pkt.pts = pkt.dts = frame->pts; + if (got_packet) { av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base); + pkt.stream_index = ost->st->index; + /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(oc, &pkt); - } else { - AVPacket pkt = { 0 }; - av_init_packet(&pkt); - - /* encode the image */ - ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); - if (ret < 0) { - fprintf(stderr, "Error encoding a video frame\n"); - exit(1); - } - - if (got_packet) { - av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base); - pkt.stream_index = ost->st->index; - - /* Write the compressed frame to the media file. */ - ret = av_interleaved_write_frame(oc, &pkt); - } } + if (ret != 0) { fprintf(stderr, "Error while writing video frame\n"); exit(1); @@ -543,7 +551,7 @@ static int write_video_frame(AVFormatContext *oc, OutputStream *ost) static void close_stream(AVFormatContext *oc, OutputStream *ost) { - avcodec_close(ost->st->codec); + avcodec_free_context(&ost->enc); av_frame_free(&ost->frame); av_frame_free(&ost->tmp_frame); sws_freeContext(ost->sws_ctx); @@ -632,8 +640,8 @@ int main(int argc, char **argv) while (encode_video || encode_audio) { /* select the stream to encode */ if (encode_video && - (!encode_audio || av_compare_ts(video_st.next_pts, video_st.st->codec->time_base, - audio_st.next_pts, audio_st.st->codec->time_base) <= 0)) { + (!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base, + audio_st.next_pts, audio_st.enc->time_base) <= 0)) { encode_video = !write_video_frame(oc, &video_st); } else { encode_audio = !process_audio_stream(oc, &audio_st); diff --git a/doc/examples/qsvdec.c b/doc/examples/qsvdec.c new file mode 100644 index 0000000..aaecd81 --- /dev/null +++ b/doc/examples/qsvdec.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2015 Anton Khirnov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @file + * Intel QSV-accelerated H.264 decoding example. + * + * @example qsvdec.c + * This example shows how to do QSV-accelerated H.264 decoding with output + * frames in the VA-API video surfaces. + */ + +#include "config.h" + +#include + +#include + +#include +#include +#include + +#include "libavformat/avformat.h" +#include "libavformat/avio.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/qsv.h" + +#include "libavutil/error.h" +#include "libavutil/mem.h" + +typedef struct DecodeContext { + mfxSession mfx_session; + VADisplay va_dpy; + + VASurfaceID *surfaces; + mfxMemId *surface_ids; + int *surface_used; + int nb_surfaces; + + mfxFrameInfo frame_info; +} DecodeContext; + +static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + DecodeContext *decode = pthis; + int err, i; + + if (decode->surfaces) { + fprintf(stderr, "Multiple allocation requests.\n"); + return MFX_ERR_MEMORY_ALLOC; + } + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)) { + fprintf(stderr, "Unsupported surface type: %d\n", req->Type); + return MFX_ERR_UNSUPPORTED; + } + if (req->Info.BitDepthLuma != 8 || req->Info.BitDepthChroma != 8 || + req->Info.Shift || req->Info.FourCC != MFX_FOURCC_NV12 || + req->Info.ChromaFormat != MFX_CHROMAFORMAT_YUV420) { + fprintf(stderr, "Unsupported surface properties.\n"); + return MFX_ERR_UNSUPPORTED; + } + + decode->surfaces = av_malloc_array (req->NumFrameSuggested, sizeof(*decode->surfaces)); + decode->surface_ids = av_malloc_array (req->NumFrameSuggested, sizeof(*decode->surface_ids)); + decode->surface_used = av_mallocz_array(req->NumFrameSuggested, sizeof(*decode->surface_used)); + if (!decode->surfaces || !decode->surface_ids || !decode->surface_used) + goto fail; + + err = vaCreateSurfaces(decode->va_dpy, VA_RT_FORMAT_YUV420, + req->Info.Width, req->Info.Height, + decode->surfaces, req->NumFrameSuggested, + NULL, 0); + if (err != VA_STATUS_SUCCESS) { + fprintf(stderr, "Error allocating VA surfaces\n"); + goto fail; + } + decode->nb_surfaces = req->NumFrameSuggested; + + for (i = 0; i < decode->nb_surfaces; i++) + decode->surface_ids[i] = &decode->surfaces[i]; + + resp->mids = decode->surface_ids; + resp->NumFrameActual = decode->nb_surfaces; + + decode->frame_info = req->Info; + + return MFX_ERR_NONE; +fail: + av_freep(&decode->surfaces); + av_freep(&decode->surface_ids); + av_freep(&decode->surface_used); + + return MFX_ERR_MEMORY_ALLOC; +} + +static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + return MFX_ERR_NONE; +} + +static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +static void free_surfaces(DecodeContext *decode) +{ + if (decode->surfaces) + vaDestroySurfaces(decode->va_dpy, decode->surfaces, decode->nb_surfaces); + av_freep(&decode->surfaces); + av_freep(&decode->surface_ids); + av_freep(&decode->surface_used); + decode->nb_surfaces = 0; +} + +static void free_buffer(void *opaque, uint8_t *data) +{ + int *used = opaque; + *used = 0; + av_freep(&data); +} + +static int get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + DecodeContext *decode = avctx->opaque; + + mfxFrameSurface1 *surf; + AVBufferRef *surf_buf; + int idx; + + for (idx = 0; idx < decode->nb_surfaces; idx++) { + if (!decode->surface_used[idx]) + break; + } + if (idx == decode->nb_surfaces) { + fprintf(stderr, "No free surfaces\n"); + return AVERROR(ENOMEM); + } + + surf = av_mallocz(sizeof(*surf)); + if (!surf) + return AVERROR(ENOMEM); + surf_buf = av_buffer_create((uint8_t*)surf, sizeof(*surf), free_buffer, + &decode->surface_used[idx], AV_BUFFER_FLAG_READONLY); + if (!surf_buf) { + av_freep(&surf); + return AVERROR(ENOMEM); + } + + surf->Info = decode->frame_info; + surf->Data.MemId = &decode->surfaces[idx]; + + frame->buf[0] = surf_buf; + frame->data[3] = (uint8_t*)surf; + + decode->surface_used[idx] = 1; + + return 0; +} + +static int get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts) +{ + while (*pix_fmts != AV_PIX_FMT_NONE) { + if (*pix_fmts == AV_PIX_FMT_QSV) { + if (!avctx->hwaccel_context) { + DecodeContext *decode = avctx->opaque; + AVQSVContext *qsv = av_qsv_alloc_context(); + if (!qsv) + return AV_PIX_FMT_NONE; + + qsv->session = decode->mfx_session; + qsv->iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; + + avctx->hwaccel_context = qsv; + } + + return AV_PIX_FMT_QSV; + } + + pix_fmts++; + } + + fprintf(stderr, "The QSV pixel format not offered in get_format()\n"); + + return AV_PIX_FMT_NONE; +} + +static int decode_packet(DecodeContext *decode, AVCodecContext *decoder_ctx, + AVFrame *frame, AVPacket *pkt, + AVIOContext *output_ctx) +{ + int ret = 0; + int got_frame = 1; + + while (pkt->size > 0 || (!pkt->data && got_frame)) { + ret = avcodec_decode_video2(decoder_ctx, frame, &got_frame, pkt); + if (ret < 0) { + fprintf(stderr, "Error during decoding\n"); + return ret; + } + + pkt->data += ret; + pkt->size -= ret; + + /* A real program would do something useful with the decoded frame here. + * We just retrieve the raw data and write it to a file, which is rather + * useless but pedagogic. */ + if (got_frame) { + mfxFrameSurface1 *surf = (mfxFrameSurface1*)frame->data[3]; + VASurfaceID surface = *(VASurfaceID*)surf->Data.MemId; + + VAImageFormat img_fmt = { + .fourcc = VA_FOURCC_NV12, + .byte_order = VA_LSB_FIRST, + .bits_per_pixel = 8, + .depth = 8, + }; + + VAImage img; + + VAStatus err; + uint8_t *data; + int i, j; + + img.buf = VA_INVALID_ID; + img.image_id = VA_INVALID_ID; + + err = vaCreateImage(decode->va_dpy, &img_fmt, + frame->width, frame->height, &img); + if (err != VA_STATUS_SUCCESS) { + fprintf(stderr, "Error creating an image: %s\n", + vaErrorStr(err)); + ret = AVERROR_UNKNOWN; + goto fail; + } + + err = vaGetImage(decode->va_dpy, surface, 0, 0, + frame->width, frame->height, + img.image_id); + if (err != VA_STATUS_SUCCESS) { + fprintf(stderr, "Error getting an image: %s\n", + vaErrorStr(err)); + ret = AVERROR_UNKNOWN; + goto fail; + } + + err = vaMapBuffer(decode->va_dpy, img.buf, (void**)&data); + if (err != VA_STATUS_SUCCESS) { + fprintf(stderr, "Error mapping the image buffer: %s\n", + vaErrorStr(err)); + ret = AVERROR_UNKNOWN; + goto fail; + } + + for (i = 0; i < img.num_planes; i++) + for (j = 0; j < (img.height >> (i > 0)); j++) + avio_write(output_ctx, data + img.offsets[i] + j * img.pitches[i], img.width); + +fail: + if (img.buf != VA_INVALID_ID) + vaUnmapBuffer(decode->va_dpy, img.buf); + if (img.image_id != VA_INVALID_ID) + vaDestroyImage(decode->va_dpy, img.image_id); + av_frame_unref(frame); + + if (ret < 0) + return ret; + } + } + + return 0; +} + +int main(int argc, char **argv) +{ + AVFormatContext *input_ctx = NULL; + AVStream *video_st = NULL; + AVCodecContext *decoder_ctx = NULL; + const AVCodec *decoder; + + AVPacket pkt = { 0 }; + AVFrame *frame = NULL; + + DecodeContext decode = { NULL }; + + Display *dpy = NULL; + int va_ver_major, va_ver_minor; + + mfxIMPL mfx_impl = MFX_IMPL_AUTO_ANY; + mfxVersion mfx_ver = { { 1, 1 } }; + + mfxFrameAllocator frame_allocator = { + .pthis = &decode, + .Alloc = frame_alloc, + .Lock = frame_lock, + .Unlock = frame_unlock, + .GetHDL = frame_get_hdl, + .Free = frame_free, + }; + + AVIOContext *output_ctx = NULL; + + int ret, i, err; + + av_register_all(); + + if (argc < 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + /* open the input file */ + ret = avformat_open_input(&input_ctx, argv[1], NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Cannot open input file '%s': ", argv[1]); + goto finish; + } + + /* find the first H.264 video stream */ + for (i = 0; i < input_ctx->nb_streams; i++) { + AVStream *st = input_ctx->streams[i]; + + if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !video_st) + video_st = st; + else + st->discard = AVDISCARD_ALL; + } + if (!video_st) { + fprintf(stderr, "No H.264 video stream in the input file\n"); + goto finish; + } + + /* initialize VA-API */ + dpy = XOpenDisplay(NULL); + if (!dpy) { + fprintf(stderr, "Cannot open the X display\n"); + goto finish; + } + decode.va_dpy = vaGetDisplay(dpy); + if (!decode.va_dpy) { + fprintf(stderr, "Cannot open the VA display\n"); + goto finish; + } + + err = vaInitialize(decode.va_dpy, &va_ver_major, &va_ver_minor); + if (err != VA_STATUS_SUCCESS) { + fprintf(stderr, "Cannot initialize VA: %s\n", vaErrorStr(err)); + goto finish; + } + fprintf(stderr, "Initialized VA v%d.%d\n", va_ver_major, va_ver_minor); + + /* initialize an MFX session */ + err = MFXInit(mfx_impl, &mfx_ver, &decode.mfx_session); + if (err != MFX_ERR_NONE) { + fprintf(stderr, "Error initializing an MFX session\n"); + goto finish; + } + + MFXVideoCORE_SetHandle(decode.mfx_session, MFX_HANDLE_VA_DISPLAY, decode.va_dpy); + MFXVideoCORE_SetFrameAllocator(decode.mfx_session, &frame_allocator); + + /* initialize the decoder */ + decoder = avcodec_find_decoder_by_name("h264_qsv"); + if (!decoder) { + fprintf(stderr, "The QSV decoder is not present in libavcodec\n"); + goto finish; + } + + decoder_ctx = avcodec_alloc_context3(decoder); + if (!decoder_ctx) { + ret = AVERROR(ENOMEM); + goto finish; + } + decoder_ctx->codec_id = AV_CODEC_ID_H264; + if (video_st->codecpar->extradata_size) { + decoder_ctx->extradata = av_mallocz(video_st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!decoder_ctx->extradata) { + ret = AVERROR(ENOMEM); + goto finish; + } + memcpy(decoder_ctx->extradata, video_st->codecpar->extradata, + video_st->codecpar->extradata_size); + decoder_ctx->extradata_size = video_st->codecpar->extradata_size; + } + decoder_ctx->refcounted_frames = 1; + + decoder_ctx->opaque = &decode; + decoder_ctx->get_buffer2 = get_buffer; + decoder_ctx->get_format = get_format; + + ret = avcodec_open2(decoder_ctx, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Error opening the decoder: "); + goto finish; + } + + /* open the output stream */ + ret = avio_open(&output_ctx, argv[2], AVIO_FLAG_WRITE); + if (ret < 0) { + fprintf(stderr, "Error opening the output context: "); + goto finish; + } + + frame = av_frame_alloc(); + if (!frame) { + ret = AVERROR(ENOMEM); + goto finish; + } + + /* actual decoding */ + while (ret >= 0) { + ret = av_read_frame(input_ctx, &pkt); + if (ret < 0) + break; + + if (pkt.stream_index == video_st->index) + ret = decode_packet(&decode, decoder_ctx, frame, &pkt, output_ctx); + + av_packet_unref(&pkt); + } + + /* flush the decoder */ + pkt.data = NULL; + pkt.size = 0; + ret = decode_packet(&decode, decoder_ctx, frame, &pkt, output_ctx); + +finish: + if (ret < 0) { + char buf[1024]; + av_strerror(ret, buf, sizeof(buf)); + fprintf(stderr, "%s\n", buf); + } + + avformat_close_input(&input_ctx); + + av_frame_free(&frame); + + if (decoder_ctx) + av_freep(&decoder_ctx->hwaccel_context); + avcodec_free_context(&decoder_ctx); + + free_surfaces(&decode); + + if (decode.mfx_session) + MFXClose(decode.mfx_session); + if (decode.va_dpy) + vaTerminate(decode.va_dpy); + if (dpy) + XCloseDisplay(dpy); + + avio_close(output_ctx); + + return ret; +} diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 6206afe..be86fe5 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -40,11 +40,9 @@ #include "libavresample/avresample.h" /** The output bit rate in kbit/s */ -#define OUTPUT_BIT_RATE 48000 +#define OUTPUT_BIT_RATE 96000 /** The number of output channels */ #define OUTPUT_CHANNELS 2 -/** The audio sample output format */ -#define OUTPUT_SAMPLE_FORMAT AV_SAMPLE_FMT_S16 /** * Convert an error code into a text message. @@ -63,6 +61,7 @@ static int open_input_file(const char *filename, AVFormatContext **input_format_context, AVCodecContext **input_codec_context) { + AVCodecContext *avctx; AVCodec *input_codec; int error; @@ -92,23 +91,39 @@ static int open_input_file(const char *filename, } /** Find a decoder for the audio stream. */ - if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codec->codec_id))) { + if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) { fprintf(stderr, "Could not find input codec\n"); avformat_close_input(input_format_context); return AVERROR_EXIT; } + /** allocate a new decoding context */ + avctx = avcodec_alloc_context3(input_codec); + if (!avctx) { + fprintf(stderr, "Could not allocate a decoding context\n"); + avformat_close_input(input_format_context); + return AVERROR(ENOMEM); + } + + /** initialize the stream parameters with demuxer information */ + error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar); + if (error < 0) { + avformat_close_input(input_format_context); + avcodec_free_context(&avctx); + return error; + } + /** Open the decoder for the audio stream to use it later. */ - if ((error = avcodec_open2((*input_format_context)->streams[0]->codec, - input_codec, NULL)) < 0) { + if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) { fprintf(stderr, "Could not open input codec (error '%s')\n", get_error_text(error)); + avcodec_free_context(&avctx); avformat_close_input(input_format_context); return error; } /** Save the decoder context for easier access later. */ - *input_codec_context = (*input_format_context)->streams[0]->codec; + *input_codec_context = avctx; return 0; } @@ -123,6 +138,7 @@ static int open_output_file(const char *filename, AVFormatContext **output_format_context, AVCodecContext **output_codec_context) { + AVCodecContext *avctx = NULL; AVIOContext *output_io_context = NULL; AVStream *stream = NULL; AVCodec *output_codec = NULL; @@ -162,42 +178,63 @@ static int open_output_file(const char *filename, } /** Create a new audio stream in the output file container. */ - if (!(stream = avformat_new_stream(*output_format_context, output_codec))) { + if (!(stream = avformat_new_stream(*output_format_context, NULL))) { fprintf(stderr, "Could not create new stream\n"); error = AVERROR(ENOMEM); goto cleanup; } - /** Save the encoder context for easiert access later. */ - *output_codec_context = stream->codec; + avctx = avcodec_alloc_context3(output_codec); + if (!avctx) { + fprintf(stderr, "Could not allocate an encoding context\n"); + error = AVERROR(ENOMEM); + goto cleanup; + } /** * Set the basic encoder parameters. * The input file's sample rate is used to avoid a sample rate conversion. */ - (*output_codec_context)->channels = OUTPUT_CHANNELS; - (*output_codec_context)->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS); - (*output_codec_context)->sample_rate = input_codec_context->sample_rate; - (*output_codec_context)->sample_fmt = AV_SAMPLE_FMT_S16; - (*output_codec_context)->bit_rate = OUTPUT_BIT_RATE; + avctx->channels = OUTPUT_CHANNELS; + avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS); + avctx->sample_rate = input_codec_context->sample_rate; + avctx->sample_fmt = output_codec->sample_fmts[0]; + avctx->bit_rate = OUTPUT_BIT_RATE; + + /** Allow the use of the experimental AAC encoder */ + avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + + /** Set the sample rate for the container. */ + stream->time_base.den = input_codec_context->sample_rate; + stream->time_base.num = 1; /** * Some container formats (like MP4) require global headers to be present * Mark the encoder so that it behaves accordingly. */ if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER) - (*output_codec_context)->flags |= CODEC_FLAG_GLOBAL_HEADER; + avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; /** Open the encoder for the audio stream to use it later. */ - if ((error = avcodec_open2(*output_codec_context, output_codec, NULL)) < 0) { + if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) { fprintf(stderr, "Could not open output codec (error '%s')\n", get_error_text(error)); goto cleanup; } + error = avcodec_parameters_from_context(stream->codecpar, avctx); + if (error < 0) { + fprintf(stderr, "Could not initialize stream parameters\n"); + goto cleanup; + } + + /** Save the encoder context for easier access later. */ + *output_codec_context = avctx; + return 0; cleanup: + avcodec_free_context(&avctx); avio_close((*output_format_context)->pb); avformat_free_context(*output_format_context); *output_format_context = NULL; @@ -276,10 +313,11 @@ static int init_resampler(AVCodecContext *input_codec_context, } /** Initialize a FIFO buffer for the audio samples to be encoded. */ -static int init_fifo(AVAudioFifo **fifo) +static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context) { /** Create the FIFO buffer based on the specified output sample format. */ - if (!(*fifo = av_audio_fifo_alloc(OUTPUT_SAMPLE_FORMAT, OUTPUT_CHANNELS, 1))) { + if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt, + output_codec_context->channels, 1))) { fprintf(stderr, "Could not allocate FIFO\n"); return AVERROR(ENOMEM); } @@ -331,7 +369,7 @@ static int decode_audio_frame(AVFrame *frame, data_present, &input_packet)) < 0) { fprintf(stderr, "Could not decode frame (error '%s')\n", get_error_text(error)); - av_free_packet(&input_packet); + av_packet_unref(&input_packet); return error; } @@ -341,7 +379,7 @@ static int decode_audio_frame(AVFrame *frame, */ if (*finished && *data_present) *finished = 0; - av_free_packet(&input_packet); + av_packet_unref(&input_packet); return 0; } @@ -551,6 +589,9 @@ static int init_output_frame(AVFrame **frame, return 0; } +/** Global timestamp for the audio frames */ +static int64_t pts = 0; + /** Encode one frame worth of audio to the output file. */ static int encode_audio_frame(AVFrame *frame, AVFormatContext *output_format_context, @@ -562,6 +603,12 @@ static int encode_audio_frame(AVFrame *frame, int error; init_packet(&output_packet); + /** Set a timestamp based on the sample rate for the container. */ + if (frame) { + frame->pts = pts; + pts += frame->nb_samples; + } + /** * Encode the audio frame and store it in the temporary packet. * The output audio stream encoder is used to do this. @@ -570,7 +617,7 @@ static int encode_audio_frame(AVFrame *frame, frame, data_present)) < 0) { fprintf(stderr, "Could not encode frame (error '%s')\n", get_error_text(error)); - av_free_packet(&output_packet); + av_packet_unref(&output_packet); return error; } @@ -579,11 +626,11 @@ static int encode_audio_frame(AVFrame *frame, if ((error = av_write_frame(output_format_context, &output_packet)) < 0) { fprintf(stderr, "Could not write frame (error '%s')\n", get_error_text(error)); - av_free_packet(&output_packet); + av_packet_unref(&output_packet); return error; } - av_free_packet(&output_packet); + av_packet_unref(&output_packet); } return 0; @@ -673,7 +720,7 @@ int main(int argc, char **argv) &resample_context)) goto cleanup; /** Initialize the FIFO buffer to store audio samples to be encoded. */ - if (init_fifo(&fifo)) + if (init_fifo(&fifo, output_codec_context)) goto cleanup; /** Write the header of the output file container. */ if (write_output_file_header(output_format_context)) @@ -758,13 +805,13 @@ cleanup: avresample_free(&resample_context); } if (output_codec_context) - avcodec_close(output_codec_context); + avcodec_free_context(&output_codec_context); if (output_format_context) { avio_close(output_format_context->pb); avformat_free_context(output_format_context); } if (input_codec_context) - avcodec_close(input_codec_context); + avcodec_free_context(&input_codec_context); if (input_format_context) avformat_close_input(&input_format_context); diff --git a/doc/fate.texi b/doc/fate.texi index 0185d87..9b8d953 100644 --- a/doc/fate.texi +++ b/doc/fate.texi @@ -11,7 +11,7 @@ @chapter Introduction -FATE provides a regression testsuite embedded within the Libav build system. +FATE provides a regression test suite embedded within the Libav build system. It can be run locally and optionally configured to send reports to a web aggregator and viewer @url{http://fate.libav.org}. @@ -24,7 +24,7 @@ and provide new tests when submitting patches to add additional features. In order to run, FATE needs a large amount of data (samples and references) that is provided separately from the actual source distribution. -To inform the build system about the testsuite location, pass +To inform the build system about the test suite location, pass @option{--samples=} to @command{configure} or set the @var{SAMPLES} Make variable or the @var{LIBAV_SAMPLES} environment variable to a suitable value. @@ -57,7 +57,7 @@ Specific Makefile targets and Makefile variables are available: List all fate/regression test targets. @item fate-rsync -Shortcut to download the fate test samples to the specified testsuite location. +Shortcut to download the fate test samples to the specified test suite location. @item fate Run the FATE test suite (requires the fate-suite dataset). @@ -99,6 +99,11 @@ Specify or override the wrapper used to run the tests. @item GEN Set to @var{1} to generate the missing or mismatched references. + +@item HWACCEL +Specify which hardware acceleration to use while running regression tests, +by default none is used. + @end table @example @@ -128,6 +133,7 @@ can be passed. @example slot= # some unique identifier repo=git://git.libav.org/libav.git # the source repository +#branch=release/10 # the branch to test samples=/path/to/fate/samples workdir= # directory in which to do all the work fate_recv="ssh -T fate@@fate.libav.org" # command to submit report @@ -165,4 +171,3 @@ through @command{ssh}. @section Submitting Reports In order to send reports you need to create an @command{ssh} key and send it to @email{root@@libav.org}. -The current server fingerprint is @var{a4:99:d7:d3:1c:92:0d:56:d6:d5:61:be:01:ae:7d:e6} diff --git a/doc/filters.texi b/doc/filters.texi index 28e3292..954765f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -209,6 +209,9 @@ The expression is evaluated through the eval API and can contain the following constants: @table @option +@item FRAME_RATE +frame rate, only defined for constant frame-rate video + @item PTS the presentation timestamp in input @@ -495,9 +498,9 @@ Split a 5.1 WAV file into per-channel files: @example avconv -i in.wav -filter_complex 'channelsplit=channel_layout=5.1[FL][FR][FC][LFE][SL][SR]' --map '[FL]' front_left.wav -map '[FR]' front_right.wav -map '[FC]' -front_center.wav -map '[LFE]' lfe.wav -map '[SL]' side_left.wav -map '[SR]' -side_right.wav +-map '[FL]' front_left.wav -map '[FR]' front_right.wav +-map '[FC]' front_center.wav -map '[LFE]' low_frequency_effects.wav +-map '[SL]' side_left.wav -map '[SR]' side_right.wav @end example @section channelmap @@ -530,7 +533,7 @@ the input. To fix a 5.1 WAV improperly encoded in AAC's native channel order @example -avconv -i in.wav -filter 'channelmap=1|2|0|5|3|4:channel_layout=5.1' out.wav +avconv -i in.wav -filter 'channelmap=1|2|0|5|3|4:5.1' out.wav @end example @section compand @@ -644,6 +647,53 @@ avconv -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex out @end example +@section hdcd + +Decodes High Definition Compatible Digital (HDCD) data. A 16-bit PCM stream with +embedded HDCD codes is expanded into a 20-bit PCM stream. + +The filter supports the Peak Extend and Low-level Gain Adjustment features +of HDCD, and detects the Transient Filter flag. + +@example +avconv -i HDCD16.flac -af hdcd OUT24.flac +@end example + +When using the filter with WAV, note that the default encoding for WAV is 16-bit, +so the resulting 20-bit stream will be truncated back to 16-bit. Use something +like @command{-acodec pcm_s24le} after the filter to get 24-bit PCM output. +@example +avconv -i HDCD16.wav -af hdcd OUT16.wav +avconv -i HDCD16.wav -af hdcd -acodec pcm_s24le OUT24.wav +@end example + +The filter accepts the following options: + +@table @option +@item analyze_mode +Replace audio with a solid tone and adjust the amplitude to signal some +specific aspect of the decoding process. The output file can be loaded in +an audio editor alongside the original to aid analysis. + +Modes are: +@table @samp +@item 0, off +Disabled +@item 1, lle +Gain adjustment level at each sample +@item 2, pe +Samples where peak extend occurs +@item 3, cdt +Samples where the code detect timer is active +@item 4, tgm +Samples where the target gain does not match between channels +@item 5, pel +Any samples above peak extend level +@item 6, ltgm +Gain adjustment level at each sample, in each channel +@end table +@end table + @section resample Convert the audio sample format, sample rate and channel layout. It is not meant to be used directly; it is inserted automatically by libavfilter @@ -1209,6 +1259,17 @@ The timestamp, expressed in seconds. It's NAN if the input timestamp is unknown. The default value of @var{x} and @var{y} is 0. +@item draw +Draw the text only if the expression evaluates as non-zero. +The expression accepts the same variables @var{x, y} do. +The default value is 1. + +@item alpha +Draw the text applying alpha blending. The value can +be either a number between 0.0 and 1.0 +The expression accepts the same variables @var{x, y} do. +The default value is 1. + @item fontsize The font size to be used for drawing text. The default value of @var{fontsize} is 16. @@ -1527,7 +1588,7 @@ For more information, see @section gradfun Fix the banding artifacts that are sometimes introduced into nearly flat -regions by truncation to 8bit colordepth. +regions by truncation to 8-bit colordepth. Interpolate the gradients that should go where the bands are, and dither them. @@ -1596,6 +1657,17 @@ A floating point number which specifies chroma temporal strength. It defaults to @var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}. @end table +@section hwupload_cuda + +Upload system memory frames to a CUDA device. + +It accepts the following optional parameters: + +@table @option +@item device +The number of the CUDA device to use +@end table + @section interlace Simple interlacing filter from progressive contents. This interleaves upper (or @@ -1875,7 +1947,7 @@ libopencv function @code{cvSmooth}. Overlay one video on top of another. It takes two inputs and has one output. The first input is the "main" -video on which the second input is overlayed. +video on which the second input is overlaid. It accepts the following parameters: @@ -2156,6 +2228,44 @@ scale="trunc(3/2*iw/hsub)*hsub:trunc(3/2*ih/vsub)*vsub" scale=w='min(500\, iw*3/2):h=-1' @end example +@section scale_npp + +Use the NVIDIA Performance Primitives (libnpp) to perform scaling and/or pixel +format conversion on CUDA video frames. Setting the output width and height +works in the same way as for the @var{scale} filter. + +The following additional options are accepted: +@table @option +@item format +The pixel format of the output CUDA frames. If set to the string "same" (the +default), the input format will be kept. Note that automatic format negotiation +and conversion is not yet supported for hardware frames + +@item interp_algo +The interpolation algorithm used for resizing. One of the following: +@table @option +@item nn +Nearest neighbour. + +@item linear +@item cubic +@item cubic2p_bspline +2-parameter cubic (B=1, C=0) + +@item cubic2p_catmullrom +2-parameter cubic (B=0, C=1/2) + +@item cubic2p_b05c03 +2-parameter cubic (B=1/2, C=3/10) + +@item super +Supersampling + +@item lanczos +@end table + +@end table + @section select Select frames to pass in output. @@ -2264,7 +2374,7 @@ select='not(mod(n\,100))' # Select only frames contained in the 10-20 time interval select='gte(t\,10)*lte(t\,20)' -# Select only I frames contained in the 10-20 time interval +# Select only I-frames contained in the 10-20 time interval select='gte(t\,10)*lte(t\,20)*eq(pict_type\,I)' # Select frames with a minimum distance of 10 seconds @@ -2850,6 +2960,10 @@ The time base used for input timestamps. @item sar The sample (pixel) aspect ratio of the input video. +@item hw_frames_ctx +When using a hardware pixel format, this should be a reference to an +AVHWFramesContext describing input frames. + @end table For example: @@ -2890,7 +3004,7 @@ number or a valid video frame rate abbreviation. The default value is The following graph description will generate a red source with an opacity of 0.2, with size "qcif" and a frame rate of 10 -frames per second, which will be overlayed over the source connected +frames per second, which will be overlaid over the source connected to the pad with identifier "in": @example @@ -3003,7 +3117,7 @@ A '|'-separated list of parameters to pass to the frei0r source. An example: @example # Generate a frei0r partik0l source with size 200x200 and framerate 10 -# which is overlayed on the overlay filter main input +# which is overlaid on the overlay filter's main input frei0r_src=size=200x200:framerate=10:filter_name=partik0l:filter_params=1234 [overlay]; [in][overlay] overlay @end example diff --git a/doc/general.texi b/doc/general.texi index ae59941..1708871 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -95,6 +95,21 @@ Go to @url{http://www.wavpack.com/} and follow the instructions for installing the library. Then pass @code{--enable-libwavpack} to configure to enable it. +@section OpenH264 + +Libav can make use of the OpenH264 library for H.264 encoding and decoding. + +Go to @url{http://www.openh264.org/} and follow the instructions for +installing the library. Then pass @code{--enable-libopenh264} to configure to +enable it. + +For decoding, this library is much more limited than the built-in decoder +in libavcodec; currently, this library lacks support for decoding B-frames +and some other main/high profile features. (It currently only supports +constrained baseline profile and CABAC.) Using it is mostly useful for +testing and for taking advantage of Cisco's patent portfolio license +(@url{http://www.openh264.org/BINARY_LICENSE.txt}). + @section x264 Libav can make use of the x264 library for H.264 encoding. @@ -123,6 +138,14 @@ x265 is under the GNU Public License Version 2 or later details), you must upgrade Libav's license to GPL in order to use it. @end float +@section kvazaar + +Libav can make use of the kvazaar library for HEVC encoding. + +Go to @url{https://github.com/ultravideo/kvazaar} and follow the +instructions for installing the library. Then pass +@code{--enable-libkvazaar} to configure to enable it. + @section libilbc iLBC is a narrowband speech codec that has been made freely available @@ -134,23 +157,37 @@ Go to @url{https://github.com/dekkers/libilbc} and follow the instructions for installing the library. Then pass @code{--enable-libilbc} to configure to enable it. +@section libhdcd + +Libav can make use of the libhdcd library for High Definition Compatible +Digital (HDCD) decoding via the @code{hdcd} filter. + +Go to @url{https://github.com/bp0/libhdcd} and follow the instructions for +installing the library. Then pass @code{--enable-libhdcd} to configure to +enable it. + @section AviSynth Libav can read AviSynth scripts as input. To enable support you need a -suitable @file{avisynth_c.h} header to compile against. The header in -classic AviSynth's CVS repository is not compatible as it has not been -updated to support AviSynth 2.6. AviSynth 2.5 is not supported by Libav. -Once you have the appropriate header, pass @code{--enable-avisynth} to -configure to enable AviSynth support. +suitable @file{avisynth_c.h} header to compile against. The header as +provided by AviSynth+ is fully compatible. AviSynth 2.5 is not supported +by Libav. Once you have the appropriate header, pass +@code{--enable-avisynth} to configure to enable AviSynth support. For Windows, supported AviSynth variants are -@url{http://avisynth.nl, AviSynth 2.6} for 32-bit builds and -@url{http://avs-plus.net, AviSynth+ 0.1} for 32-bit and 64-bit builds. -The necessary @file{avisynth_c.h} header is the variant in the @file{extras/} -directory of the @url{https://www.videolan.org/developers/x264.html, x264} -source tree. For convenience, this header is also available from a -@url{https://github.com/qyot27/avisynth_headers, temporary repository} -along with an installation routine. +@url{http://avisynth.nl, AviSynth 2.6 RC1 or higher} for 32-bit builds and +@url{http://avs-plus.net, AviSynth+ r1718 or higher} for 32-bit and 64-bit builds. +@url{https://github.com/AviSynth/AviSynthPlus, AviSynth+'s git repository} +provides a GNU-style Makefile which can install just the headers using +@code{make install PREFIX=/install/prefix}. + +@float NOTE +When using AviSynth+'s installed headers, the user must also pass +the avisynth/ include directory to @code{--extra-cflags}. For example, +if the PREFIX given to AviSynth+'s Makefile was /usr/i686-w64-mingw32, +then the correct command would be +@code{--extra-cflags="-I/usr/i686-w64-mingw32/include/avisynth"}. +@end float For Linux and OS X, the supported AviSynth variant is @url{https://github.com/avxsynth/avxsynth, AvxSynth}. @@ -168,6 +205,17 @@ end user having AviSynth or AvxSynth installed - they'll only need to be installed to use AviSynth scripts (obviously). @end float +@section Intel QuickSync Video + +Libav can use Intel QuickSync Video (QSV) for accelerated encoding and decoding +of multiple codecs. To use QSV, Libav must be linked against the @code{libmfx} +dispatcher, which loads the actual decoding libraries. + +The dispatcher is open source and can be downloaded from +@url{https://github.com/lu-zero/mfx_dispatch.git}. Libav needs to be configured +with the @code{--enable-libmfx} option and @code{pkg-config} needs to be able to +locate the dispatcher's @code{.pc} files. + @chapter Supported File Formats and Codecs You can use the @code{-formats} and @code{-codecs} options to have an exhaustive list. @@ -213,6 +261,10 @@ library: @tab Used in the game Cyberia from Interplay. @item Delphine Software International CIN @tab @tab X @tab Multimedia format used by Delphine Software games. +@item Digital Speech Standard (DSS) @tab @tab X +@item Canopus HQ @tab @tab X +@item Canopus HQA @tab @tab X +@item Canopus HQX @tab @tab X @item CD+G @tab @tab X @tab Video format used by CD+G karaoke disks @item Commodore CDXL @tab @tab X @@ -228,6 +280,7 @@ library: @item Deluxe Paint Animation @tab @tab X @item DFA @tab @tab X @tab This format is used in Chronomaster game +@item DirectDraw Surface @tab @tab X @item DV video @tab X @tab X @item DXA @tab @tab X @tab This format is used in the non-Windows version of the Feeble Files @@ -370,6 +423,7 @@ library: @item RealMedia @tab X @tab X @item Redirector @tab @tab X @item Renderware TeXture Dictionary @tab @tab X +@item Resolume DXV @tab @tab X @item RL2 @tab @tab X @tab Audio and video format used in some games by Entertainment Software Partners. @item RPL/ARMovie @tab @tab X @@ -379,6 +433,7 @@ library: @item RTP @tab X @tab X @item RTSP @tab X @tab X @item SAP @tab X @tab X +@item Screenpresso @tab @tab X @item SDP @tab @tab X @item Sega FILM/CPK @tab @tab X @tab Used in many Sega Saturn console games. @@ -399,6 +454,7 @@ library: @item Sony Wave64 (W64) @tab @tab X @item SoX native format @tab X @tab X @item SUN AU format @tab X @tab X +@item TDSC @tab @tab X @item Text files @tab @tab X @item THP @tab @tab X @tab Used on the Nintendo GameCube. @@ -406,6 +462,7 @@ library: @tab Tiertex .seq files used in the DOS CD-ROM version of the game Flashback. @item True Audio @tab @tab X @item VC-1 test bitstream @tab X @tab X +@item Vidvox Hap @tab X @tab X @item WAV @tab X @tab X @item WavPack @tab @tab X @item WebM @tab X @tab X @@ -566,6 +623,8 @@ following image formats are supported: @tab fourcc: DUCK @item Duck TrueMotion 2.0 @tab @tab X @tab fourcc: TM20 +@item Duck TrueMotion 2.0 RT @tab @tab X + @tab fourcc: TR20 @item DV (Digital Video) @tab X @tab X @item Dxtory capture format @tab @tab X @item Feeble Files/ScummVM DXA @tab @tab X @@ -587,15 +646,17 @@ following image formats are supported: @tab Sorenson H.263 used in Flash @item Forward Uncompressed @tab @tab X @item Fraps @tab @tab X +@item Go2Meeting @tab @tab X + @tab fourcc: G2M2, G2M3 @item Go2Webinar @tab @tab X @tab fourcc: G2M4 @item H.261 @tab X @tab X @item H.263 / H.263-1996 @tab X @tab X @item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X @item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X - @tab encoding supported through external library libx264 + @tab encoding supported through external library libx264 and OpenH264 @item HEVC @tab X @tab X - @tab encoding supported through the external library libx265 + @tab encoding supported through external library libx265 and libkvazaar @item HNM version 4 @tab @tab X @item HuffYUV @tab X @tab X @item HuffYUV FFmpeg variant @tab X @tab X @@ -629,6 +690,7 @@ following image formats are supported: @item LucasArts SANM @tab @tab X @tab Used in LucasArts SMUSH animations. @item lossless MJPEG @tab X @tab X +@item MagicYUV Lossless Video @tab @tab X @item Microsoft ATC Screen @tab @tab X @tab Also known as Microsoft Screen 3. @item Microsoft Expression Encoder Screen @tab @tab X @@ -812,10 +874,12 @@ following image formats are supported: @tab Used in Bink and Smacker files in many games. @item Delphine Software International CIN audio @tab @tab X @tab Codec used in Delphine Software International games. +@item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X @item Discworld II BMV Audio @tab @tab X @item COOK @tab @tab X @tab All versions except 5.1 are supported. @item DCA (DTS Coherent Acoustics) @tab @tab X + @tab supported extensions: XCh, XLL (partially) @item DPCM id RoQ @tab X @tab X @tab Used in Quake III, Jedi Knight 2, other computer games. @item DPCM Interplay @tab @tab X @@ -829,7 +893,7 @@ following image formats are supported: @item DV audio @tab @tab X @item Enhanced AC-3 @tab X @tab X @item FLAC (Free Lossless Audio Codec) @tab X @tab IX -@item G.723.1 @tab @tab X +@item G.723.1 @tab X @tab X @item GSM @tab E @tab X @tab encoding supported through external library libgsm @item GSM Microsoft variant @tab E @tab X @@ -858,6 +922,7 @@ following image formats are supported: @tab supported through external library libopus @item PCM A-law @tab X @tab X @item PCM mu-law @tab X @tab X +@item PCM signed 16-bit big-endian planar @tab @tab X @item PCM signed 16-bit little-endian planar @tab @tab X @item PCM signed 24-bit little-endian planar @tab @tab X @item PCM signed 32-bit little-endian planar @tab @tab X diff --git a/doc/git-howto.texi b/doc/git-howto.texi index 5a8e2a3..a746b1a 100644 --- a/doc/git-howto.texi +++ b/doc/git-howto.texi @@ -399,7 +399,7 @@ to ensure no local changes still need to be committed and that no local changes may have thrown off the results of your testing. @end itemize -Next let the code pass through a full run of our testsuite. Before you do, +Next let the code pass through a full run of our test suite. Before you do, the command @command{make fate-rsync} will update the test samples. Changes to the samples set are not very common and commits depending on samples changes are delayed for at least 24 hours to allow the new samples to diff --git a/doc/indevs.texi b/doc/indevs.texi index 8ff64a7..a08c7a5 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -271,6 +271,9 @@ supported using @command{-list_formats all} for Video4Linux2 devices. Some usage examples of the video4linux2 devices with avconv and avplay: @example +# List supported formats for a video4linux2 device. +avplay -f video4linux2 -list_formats all /dev/video0 + # Grab and show the input of a video4linux2 device. avplay -f video4linux2 -framerate 30 -video_size hd720 /dev/video0 @@ -359,4 +362,14 @@ avconv -f x11grab -show_region 1 -r 25 -s cif -i :0.0+10,20 out.mpg avconv -f x11grab -follow_mouse centered -show_region 1 -r 25 -s cif -i :0.0 out.mpg @end example +@subsection @var{grab_x} @var{grab_y} AVOption + +The syntax is: +@example +-grab_x @var{x_offset} -grab_y @var{y_offset} +@end example + +Set the grabbing region coordinates. The are expressed as offset from the top left +corner of the X11 window. The default value is 0. + @c man end INPUT DEVICES diff --git a/doc/muxers.texi b/doc/muxers.texi index 54109c7..58801aa 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -117,6 +117,11 @@ Start the sequence from @var{number}. @item -hls_base_url @var{baseurl} Append @var{baseurl} to every entry in the playlist. Useful to generate playlists with absolute paths. +@item -hls_allow_cache @var{allowcache} +Explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments +@item -hls_version @var{version} +Set the protocol version. Enables or disables version-specific features +such as the integer (version 2) or decimal EXTINF values (version 3). @end table @anchor{image2} @@ -317,7 +322,6 @@ a short portion of the file. With this option set, there is no initial mdat atom, and the moov atom only describes the tracks but has a zero duration. -Files written with this option set do not work in QuickTime. This option is implicitly set when writing ismv (Smooth Streaming) files. @item -movflags separate_moof Write a separate moof (movie fragment) atom for each track. Normally, @@ -335,6 +339,16 @@ Disable Nero chapter markers (chpl atom). Normally, both Nero chapters and a QuickTime chapter track are written to the file. With this option set, only the QuickTime chapter track will be written. Nero chapters can cause failures when the file is reprocessed with certain tagging programs. +@item -movflags omit_tfhd_offset +Do not write any absolute base_data_offset in tfhd atoms. This avoids +tying fragments to absolute byte positions in the file/streams. +@item -movflags default_base_moof +Similarly to the omit_tfhd_offset, this flag avoids writing the +absolute base_data_offset field in tfhd atoms, but does so by using +the new default-base-is-moof flag instead. This flag is new from +14496-12:2012. This may make the fragments easier to parse in certain +circumstances (avoiding basing track fragment location calculations +on the implicit end of the previous track fragment). @end table Smooth Streaming content can be pushed in real time to a publishing @@ -345,29 +359,38 @@ avconv -re @var{} -movflags isml+frag_keyframe @section mp3 -The MP3 muxer writes a raw MP3 stream with an ID3v2 header at the beginning and -optionally an ID3v1 tag at the end. ID3v2.3 and ID3v2.4 are supported, the -@code{id3v2_version} option controls which one is used. Setting -@code{id3v2_version} to 0 will disable the ID3v2 header completely. The legacy -ID3v1 tag is not written by default, but may be enabled with the -@code{write_id3v1} option. - -The muxer may also write a Xing frame at the beginning, which contains the -number of frames in the file. It is useful for computing duration of VBR files. -The Xing frame is written if the output stream is seekable and if the -@code{write_xing} option is set to 1 (the default). - -The muxer supports writing ID3v2 attached pictures (APIC frames). The pictures -are supplied to the muxer in form of a video stream with a single packet. There -can be any number of those streams, each will correspond to a single APIC frame. -The stream metadata tags @var{title} and @var{comment} map to APIC -@var{description} and @var{picture type} respectively. See +The MP3 muxer writes a raw MP3 stream with the following optional features: +@itemize @bullet +@item +An ID3v2 metadata header at the beginning (enabled by default). Versions 2.3 and +2.4 are supported, the @code{id3v2_version} private option controls which one is +used (3 or 4). Setting @code{id3v2_version} to 0 disables the ID3v2 header +completely. + +The muxer supports writing attached pictures (APIC frames) to the ID3v2 header. +The pictures are supplied to the muxer in form of a video stream with a single +packet. There can be any number of those streams, each will correspond to a +single APIC frame. The stream metadata tags @var{title} and @var{comment} map +to APIC @var{description} and @var{picture type} respectively. See @url{http://id3.org/id3v2.4.0-frames} for allowed picture types. Note that the APIC frames must be written at the beginning, so the muxer will buffer the audio frames until it gets all the pictures. It is therefore advised to provide the pictures as soon as possible to avoid excessive buffering. +@item +A Xing/LAME frame right after the ID3v2 header (if present). It is enabled by +default, but will be written only if the output is seekable. The +@code{write_xing} private option can be used to disable it. The frame contains +various information that may be useful to the decoder, like the audio duration +or encoder delay. + +@item +A legacy ID3v1 tag at the end of the file (disabled by default). It may be +enabled with the @code{write_id3v1} private option, but as its capabilities are +very limited, its usage is not recommended. +@end itemize + Examples: Write an mp3 with an ID3v2.3 header and an ID3v1 footer: @@ -484,6 +507,11 @@ is 1 second. A value of 0 will fill all segments, making pages as large as possible. A value of 1 will effectively use 1 packet-per-page in most situations, giving a small seek granularity at the cost of additional container overhead. +@item -serial_offset @var{value} +Serial value from which to set the streams serial number. +Setting it to different and sufficiently large values ensures that the produced +ogg files can be safely chained. + @end table @section segment diff --git a/doc/nut.texi b/doc/nut.texi index 042c88a..1b02c63 100644 --- a/doc/nut.texi +++ b/doc/nut.texi @@ -29,7 +29,7 @@ NUT has some variants signaled by using the flags field in its main header. The BROADCAST variant provides a secondary time reference to facilitate detecting endpoint latency and network delays. -It assumes all the endpoint clocks are syncronized. +It assumes all the endpoint clocks are synchronized. To be used in real-time scenarios. @section PIPE diff --git a/doc/optimization.txt b/doc/optimization.txt index b3dca64..9847dcf 100644 --- a/doc/optimization.txt +++ b/doc/optimization.txt @@ -7,7 +7,7 @@ If you plan to do non-x86 architecture specific optimizations (SIMD normally), then take a look in the x86/ 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 +If you want to do x86 optimizations then you can either try to fine-tune the stuff in the x86 directory or find some other functions in the C source to optimize, but there aren't many left. @@ -163,7 +163,7 @@ general x86 registers (e.g. eax) as well as XMM registers. This last one is particularly important on Win64, where xmm6-15 are callee-save, and not restoring their contents leads to undefined results. In external asm (e.g. yasm), you do this by using: -cglobal functon_name, num_args, num_regs, num_xmm_regs +cglobal function_name, num_args, num_regs, num_xmm_regs In inline asm, you specify clobbered registers at the end of your asm: __asm__(".." ::: "%eax"). If gcc is not set to support sse (-msse) it will not accept xmm registers diff --git a/doc/platform.texi b/doc/platform.texi index d4a6618..4feb50f 100644 --- a/doc/platform.texi +++ b/doc/platform.texi @@ -62,7 +62,7 @@ bash ./configure @section Darwin (OS X, iPhone) The toolchain provided with Xcode is sufficient to build the basic -unacelerated code. +unaccelerated code. OS X on PowerPC or ARM (iPhone) requires a preprocessor from @url{git://git.libav.org/gas-preprocessor.git} to build the optimized @@ -91,9 +91,9 @@ For information about compiling Libav on OS/2 see @section Native Windows compilation using MinGW or MinGW-w64 -Libav can be built to run natively on Windows using the MinGW or MinGW-w64 -toolchains. Install the latest versions of MSYS and MinGW or MinGW-w64 from -@url{http://www.mingw.org/} or @url{http://mingw-w64.sourceforge.net/}. +Libav can be built to run natively on Windows using the MinGW-w64 +toolchain. Install the latest versions of MSYS2 and MinGW-w64 from +@url{http://msys2.github.io/} and/or @url{http://mingw-w64.sourceforge.net/}. You can find detailed installation instructions in the download section and the FAQ. @@ -101,20 +101,44 @@ Notes: @itemize -@item Building natively using MSYS can be sped up by disabling implicit rules -in the Makefile by calling @code{make -r} instead of plain @code{make}. This +@item Building for the MSYS environment is discouraged, MSYS2 provides a full +MinGW-w64 environment through @file{mingw64_shell.bat} or +@file{mingw32_shell.bat} that should be used instead of the environment +provided by @file{msys2_shell.bat}. + +@item Building using MSYS2 can be sped up by disabling implicit rules in the +Makefile by calling @code{make -r} instead of plain @code{make}. This speed up is close to non-existent for normal one-off builds and is only noticeable when running make for a second time (for example during @code{make install}). -@item In order to compile AVplay, you must have the MinGW development library -of @uref{http://www.libsdl.org/, SDL} and @code{pkg-config} installed. +@item In order to compile @command{avplay}, you must have the MinGW development +library of @uref{http://www.libsdl.org/, SDL} and @code{pkg-config} installed. @item By using @code{./configure --enable-shared} when configuring Libav, you can build all libraries as DLLs. @end itemize +@subsection Native Windows compilation using MSYS2 + +The MSYS2 MinGW-w64 environment provides ready to use toolchains and dependencies +through @command{pacman}. + +Make sure to use @file{mingw64_shell.bat} or @file{mingw32_shell.bat} to have +the correct MinGW-w64 environment. The default install provides shortcuts to +them under @command{MinGW-w64 Win64 Shell} and @command{MinGW-w64 Win32 Shell}. + +@example +# normal msys2 packages +pacman -S make pkgconf diffutils + +# mingw-w64 packages and toolchains +pacman -S mingw-w64-x86_64-yasm mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL +@end example + +To target 32 bits replace @code{x86_64} with @code{i686} in the command above. + @section Microsoft Visual C++ or Intel C++ Compiler for Windows Libav can be built with MSVC 2012 or earlier using a C99-to-C89 conversion utility @@ -127,13 +151,12 @@ You will need the following prerequisites: (if using MSVC 2012 or earlier) @item @uref{http://code.google.com/p/msinttypes/, msinttypes} (if using MSVC 2012 or earlier) -@item @uref{http://www.mingw.org/, MSYS} +@item @uref{http://msys2.github.io/, MSYS2} @item @uref{http://yasm.tortall.net/, YASM} -@item @uref{http://gnuwin32.sourceforge.net/packages/bc.htm, bc for Windows} if -you want to run @uref{fate.html, FATE}. +(Also available via MSYS2's package manager.) @end itemize -To set up a proper environment in MSYS, you need to run @code{msys.bat} from +To set up a proper environment in MSYS2, you need to run @code{msys_shell.bat} from the Visual Studio or Intel Compiler command prompt. Place @code{yasm.exe} somewhere in your @code{PATH}. If using MSVC 2012 or @@ -169,12 +192,6 @@ Notes: @itemize -@item It is possible that coreutils' @code{link.exe} conflicts with MSVC's linker. -You can find out by running @code{which link} to see which @code{link.exe} you -are using. If it is located at @code{/bin/link.exe}, then you have the wrong one -in your @code{PATH}. Either move or remove that copy, or make sure MSVC's -@code{link.exe} takes precedence in your @code{PATH} over coreutils'. - @item If you wish to build with zlib support, you will have to grab a compatible zlib binary from somewhere, with an MSVC import lib, or if you wish to link statically, you can follow the instructions below to build a compatible @@ -277,7 +294,7 @@ binutils, gcc4-core, make, git, mingw-runtime, texi2html In order to run FATE you will also need the following "Utils" packages: @example -bc, diffutils +diffutils @end example If you want to build Libav with additional libraries, download Cygwin diff --git a/doc/protocols.texi b/doc/protocols.texi index 4957aff..c136c74 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -17,6 +17,14 @@ particular protocol using the option The option "-protocols" of the av* tools will display the list of supported protocols. +All protocols accept the following options: + +@table @option +@item rw_timeout +Maximum time to wait for (network) read/write operations to complete, +in microseconds. +@end table + A description of the currently available protocols follows. @section concat @@ -61,6 +69,17 @@ The av* tools default to the file protocol, that is a resource specified with the name "FILE.mpeg" is interpreted as the URL "file:FILE.mpeg". +This protocol accepts the following options: + +@table @option +@item follow +If set to 1, the protocol will retry reading at the end of the file, allowing +reading files that still are being written. In order for this to terminate, +you either need to use the rw_timeout option, or use the interrupt callback +(for API users). + +@end table + @section gopher Gopher protocol. @@ -638,7 +657,7 @@ avplay sap://[ff0e::2:7ffe] @section tcp -Trasmission Control Protocol. +Transmission Control Protocol. The required syntax for a TCP url is: @example diff --git a/doc/swscale.txt b/doc/swscale.txt index 2066009..dbb4e29 100644 --- a/doc/swscale.txt +++ b/doc/swscale.txt @@ -10,12 +10,12 @@ Current (simplified) Architecture: / \ special converter [Input to YUV converter] | | - | (8bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:0:0 ) + | (8-bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:0:0 ) | | | v | Horizontal scaler | | - | (15bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:1:1 / 4:0:0 ) + | (15-bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:1:1 / 4:0:0 ) | | | v | Vertical scaler and output converter diff --git a/doc/texi2pod.pl b/doc/texi2pod.pl index 54d5717..934c1a2 100755 --- a/doc/texi2pod.pl +++ b/doc/texi2pod.pl @@ -327,13 +327,14 @@ $inf = pop @instack; die "No filename or title\n" unless defined $fn && defined $tl; +# always use utf8 +print "=encoding utf8\n\n"; + $sects{NAME} = "$fn \- $tl\n"; $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; unshift @sects_sequence, "NAME"; for $sect (@sects_sequence) { - # always use utf8 - print "=encoding utf8\n"; if(exists $sects{$sect}) { $head = $sect; $head =~ s/SEEALSO/SEE ALSO/; @@ -379,7 +380,7 @@ sub postprocess # @* is also impossible in .pod; we discard it and any newline that # follows it. Similarly, our macro @gol must be discarded. - s/\@anchor{(?:[^\}]*)\}//g; + s/\@anchor\{(?:[^\}]*)\}//g; s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g; s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g; s/;\s+\@pxref\{(?:[^\}]*)\}//g; diff --git a/doc/viterbi.txt b/doc/viterbi.txt index 9782546..712fc4b 100644 --- a/doc/viterbi.txt +++ b/doc/viterbi.txt @@ -1,7 +1,7 @@ -This is a quick description of the viterbi aka dynamic programing -algorthm. +This is a quick description of the Viterbi aka dynamic programming +algorithm. -Its reason for existence is that wikipedia has become very poor on +Its reason for existence is that Wikipedia has become very poor on describing algorithms in a way that makes it useable for understanding them or anything else actually. It tends now to describe the very same algorithm under 50 different names and pages with few understandable @@ -41,7 +41,7 @@ readable) Our goal is to find a path from left to right through it which minimizes the sum of the score of all edges. (and of course left/right is just a convention here it could be top down too) -Similarly the minimum could be the maximum by just fliping the sign, +Similarly the minimum could be the maximum by just flipping the sign, Example of a path with scores: O O O O O O O @@ -53,7 +53,7 @@ Example of a path with scores: O O O O O O-1-O---> (sum here is 24) -The viterbi algorthm now solves this simply column by column +The Viterbi algorithm now solves this simply column by column For the previous column each point has a best path and a associated score: @@ -100,10 +100,10 @@ trivial given we know the previous column best paths and scores: O 0 4 -the viterbi algorthm continues exactly like this column for column until the +the Viterbi algorithm continues exactly like this column for column until the end and then just picks the path with the best score (above that would be the one with score 3) -Author: Michael niedermayer +Author: Michael Niedermayer Copyright LGPL diff --git a/libavcodec/.gitignore b/libavcodec/.gitignore new file mode 100644 index 0000000..77a2ab1 --- /dev/null +++ b/libavcodec/.gitignore @@ -0,0 +1,4 @@ +/*_tablegen +/*_tables.c +/*_tables.h +/bsf_list.c diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 36d9dc1..b2d4db2 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -340,22 +340,29 @@ static inline void mcdc(uint16_t *dst, uint16_t *src, int log2w, static int decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int log2w, int log2h, int stride) { - const int index = size2index[log2h][log2w]; - const int h = 1 << log2h; - int code = get_vlc2(&f->gb, - block_type_vlc[1 - (f->version > 1)][index].table, - BLOCK_TYPE_VLC_BITS, 1); - uint16_t *start = f->last_frame_buffer; - uint16_t *end = start + stride * (f->avctx->height - h + 1) - (1 << log2w); - int ret; - int scale = 1; + int index, h, code, ret, scale = 1; + uint16_t *start, *end; unsigned dc = 0; - if (code < 0 || code > 6 || log2w < 0) + if (log2h < 0 || log2w < 0) + return AVERROR_INVALIDDATA; + + index = size2index[log2h][log2w]; + if (index < 0) + return AVERROR_INVALIDDATA; + + h = 1 << log2h; + code = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index].table, + BLOCK_TYPE_VLC_BITS, 1); + if (code < 0 || code > 6) return AVERROR_INVALIDDATA; + start = f->last_frame_buffer; + end = start + stride * (f->avctx->height - h + 1) - (1 << log2w); + if (code == 1) { - log2h--; + if (--log2h < 0) + return AVERROR_INVALIDDATA; if ((ret = decode_p_block(f, dst, src, log2w, log2h, stride)) < 0) return ret; return decode_p_block(f, dst + (stride << log2h), @@ -439,13 +446,13 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length) } av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, - bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE); + bitstream_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!f->bitstream_buffer) return AVERROR(ENOMEM); f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) (buf + extra), bitstream_size / 4); memset((uint8_t*)f->bitstream_buffer + bitstream_size, - 0, FF_INPUT_BUFFER_PADDING_SIZE); + 0, AV_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size); wordstream_offset = extra + bitstream_size; @@ -527,7 +534,7 @@ static inline void idct_put(FourXContext *f, int x, int y) idct(block[i]); } - if (!(f->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(f->avctx->flags & AV_CODEC_FLAG_GRAY)) { for (i = 4; i < 6; i++) idct(block[i]); } @@ -762,13 +769,13 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length) prestream_size = length + buf - prestream; av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, - prestream_size + FF_INPUT_BUFFER_PADDING_SIZE); + prestream_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!f->bitstream_buffer) return AVERROR(ENOMEM); f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) prestream, prestream_size / 4); memset((uint8_t*)f->bitstream_buffer + prestream_size, - 0, FF_INPUT_BUFFER_PADDING_SIZE); + 0, AV_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&f->pre_gb, f->bitstream_buffer, 8 * prestream_size); f->last_dc = 0 * 128 * 8 * 8; @@ -820,9 +827,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, const int data_size = buf_size - 20; CFrameBuffer *cfrm; - if (data_size < 0) - return AVERROR_INVALIDDATA; - id = AV_RL32(buf + 12); whole_size = AV_RL32(buf + 16); @@ -845,7 +849,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, cfrm = &f->cfrm[i]; cfrm->data = av_fast_realloc(cfrm->data, &cfrm->allocated_size, - cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE); + cfrm->size + data_size + AV_INPUT_BUFFER_PADDING_SIZE); // explicit check needed as memcpy below might not catch a NULL if (!cfrm->data) { av_log(f->avctx, AV_LOG_ERROR, "realloc failure"); @@ -977,5 +981,5 @@ AVCodec ff_fourxm_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c index 3fd15e0..7ba2b31 100644 --- a/libavcodec/8bps.c +++ b/libavcodec/8bps.c @@ -28,7 +28,6 @@ * Supports: PAL8 (RGB 8bpp, paletted) * : BGR24 (RGB 24bpp) (can also output it as RGB32) * : RGB32 (RGB 32bpp, 4th plane is probably alpha and it's ignored) - * */ #include @@ -193,5 +192,5 @@ AVCodec ff_eightbps_decoder = { .priv_data_size = sizeof(EightBpsContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c index 11fbf19..fe90b16 100644 --- a/libavcodec/8svx.c +++ b/libavcodec/8svx.c @@ -96,11 +96,11 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, if (avpkt->size < hdr_size * avctx->channels) { av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } if (esc->data[0]) { av_log(avctx, AV_LOG_ERROR, "unexpected data after first packet\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } if (is_compr) { @@ -125,7 +125,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, } if (!esc->data[0]) { av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } /* decode next piece of data from the buffer */ @@ -166,7 +166,7 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx) if (avctx->channels < 1 || avctx->channels > 2) { av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } switch(avctx->codec->id) { @@ -179,7 +179,7 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx) case AV_CODEC_ID_PCM_S8_PLANAR: break; default: - return -1; + return AVERROR_INVALIDDATA; } avctx->sample_fmt = AV_SAMPLE_FMT_U8P; @@ -205,7 +205,7 @@ AVCodec ff_eightsvx_fib_decoder = { .init = eightsvx_decode_init, .close = eightsvx_decode_close, .decode = eightsvx_decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, }; @@ -219,7 +219,7 @@ AVCodec ff_eightsvx_exp_decoder = { .init = eightsvx_decode_init, .close = eightsvx_decode_close, .decode = eightsvx_decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, }; @@ -233,7 +233,7 @@ AVCodec ff_pcm_s8_planar_decoder = { .init = eightsvx_decode_init, .close = eightsvx_decode_close, .decode = eightsvx_decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 752340f..8eb7d36 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -2,12 +2,16 @@ NAME = avcodec HEADERS = avcodec.h \ avfft.h \ + d3d11va.h \ + dirac.h \ dv_profile.h \ dxva2.h \ + qsv.h \ vaapi.h \ vda.h \ vdpau.h \ version.h \ + vorbis_parser.h \ xvmc.h \ OBJS = allcodecs.o \ @@ -15,16 +19,24 @@ OBJS = allcodecs.o \ avpicture.o \ bitstream.o \ bitstream_filter.o \ + bitstream_filters.o \ + bsf.o \ codec_desc.o \ + d3d11va.o \ + dirac.o \ dv_profile.o \ - fmtconvert.o \ imgconvert.o \ log2_tab.o \ mathtables.o \ + mpeg12framerate.o \ options.o \ parser.o \ + profiles.o \ + qsv_api.o \ raw.o \ utils.o \ + vorbis_parser.o \ + xiph.o \ # subsystems OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o @@ -35,30 +47,36 @@ OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o -OBJS-$(CONFIG_DXVA2) += dxva2.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o -OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o faandct.o \ - jfdctfst.o jfdctint.o +OBJS-$(CONFIG_FAANDCT) += faandct.o +OBJS-$(CONFIG_FAANIDCT) += faanidct.o +OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o jfdctfst.o jfdctint.o FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o cos_fixed_tables.o OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \ $(FFT-OBJS-yes) +OBJS-$(CONFIG_FLACDSP) += flacdsp.o +OBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o OBJS-$(CONFIG_GOLOMB) += golomb.o OBJS-$(CONFIG_H263DSP) += h263dsp.o OBJS-$(CONFIG_H264CHROMA) += h264chroma.o OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o +OBJS-$(CONFIG_H264PARSE) += h264_parse.o h2645_parse.o h264_ps.o OBJS-$(CONFIG_H264PRED) += h264pred.o OBJS-$(CONFIG_H264QPEL) += h264qpel.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o OBJS-$(CONFIG_HUFFYUVENCDSP) += huffyuvencdsp.o -OBJS-$(CONFIG_IDCTDSP) += idctdsp.o faanidct.o \ - simple_idct.o jrevdct.o +OBJS-$(CONFIG_IDCTDSP) += idctdsp.o simple_idct.o jrevdct.o OBJS-$(CONFIG_IIRFILTER) += iirfilter.o +OBJS-$(CONFIG_IMDCT15) += imdct15.o OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o +OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o +OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o OBJS-$(CONFIG_LPC) += lpc.o OBJS-$(CONFIG_LSP) += lsp.o +OBJS-$(CONFIG_LZF) += lzf.o OBJS-$(CONFIG_MDCT) += mdct_fixed.o mdct_float.o OBJS-$(CONFIG_ME_CMP) += me_cmp.o OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o @@ -68,24 +86,37 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o -OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o \ - mpegvideo_motion.o mpegutils.o +OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ + mpegvideo_motion.o mpegutils.o \ + mpegvideodata.o mpegpicture.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o +OBJS-$(CONFIG_MSS34DSP) += mss34dsp.o +OBJS-$(CONFIG_NVENC) += nvenc.o OBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o OBJS-$(CONFIG_QPELDSP) += qpeldsp.o +OBJS-$(CONFIG_QSV) += qsv.o +OBJS-$(CONFIG_QSVDEC) += qsvdec.o +OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes) +OBJS-$(CONFIG_RV34DSP) += rv34dsp.o OBJS-$(CONFIG_SINEWIN) += sinewin.o +OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_STARTCODE) += startcode.o +OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o +OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI) += vaapi.o -OBJS-$(CONFIG_VDA) += vda.o -OBJS-$(CONFIG_VDPAU) += vdpau.o +OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o +OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP) += videodsp.o OBJS-$(CONFIG_VP3DSP) += vp3dsp.o +OBJS-$(CONFIG_VP56DSP) += vp56dsp.o +OBJS-$(CONFIG_VP8DSP) += vp8dsp.o +OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o +OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o # decoders/encoders OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o @@ -134,8 +165,8 @@ OBJS-$(CONFIG_AVS_DECODER) += avs.o OBJS-$(CONFIG_BETHSOFTVID_DECODER) += bethsoftvideo.o OBJS-$(CONFIG_BFI_DECODER) += bfi.o OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o -OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o wma.o wma_common.o -OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o wma_common.o +OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o +OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o @@ -149,14 +180,16 @@ OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o OBJS-$(CONFIG_CLJR_DECODER) += cljrdec.o OBJS-$(CONFIG_CLJR_ENCODER) += cljrenc.o -OBJS-$(CONFIG_CLLC_DECODER) += cllc.o -OBJS-$(CONFIG_COOK_DECODER) += cook.o +OBJS-$(CONFIG_CLLC_DECODER) += cllc.o canopus.o OBJS-$(CONFIG_COMFORTNOISE_DECODER) += cngdec.o celp_filters.o OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o +OBJS-$(CONFIG_COOK_DECODER) += cook.o OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadsp.o \ - synth_filter.o + dcadata.o dca_exss.o \ + dca_xll.o synth_filter.o +OBJS-$(CONFIG_DDS_DECODER) += dds.o OBJS-$(CONFIG_DFA_DECODER) += dfa.o OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o @@ -164,6 +197,7 @@ OBJS-$(CONFIG_DPX_DECODER) += dpx.o OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinaudio.o OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinvideo.o +OBJS-$(CONFIG_DSS_SP_DECODER) += dss_sp.o OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o @@ -172,6 +206,7 @@ OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o OBJS-$(CONFIG_DXA_DECODER) += dxa.o OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o +OBJS-$(CONFIG_DXV_DECODER) += dxv.o OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o @@ -179,7 +214,7 @@ OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \ mpeg12data.o OBJS-$(CONFIG_EATGQ_DECODER) += eatgq.o eaidct.o OBJS-$(CONFIG_EATGV_DECODER) += eatgv.o -OBJS-$(CONFIG_EATQI_DECODER) += eatqi.o eaidct.o +OBJS-$(CONFIG_EATQI_DECODER) += eatqi.o eaidct.o mpeg12.o mpeg12data.o mpegvideodata.o rl.o OBJS-$(CONFIG_EIGHTBPS_DECODER) += 8bps.o OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER) += 8svx.o OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER) += 8svx.o @@ -189,8 +224,8 @@ OBJS-$(CONFIG_EXR_DECODER) += exr.o OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o OBJS-$(CONFIG_FIC_DECODER) += fic.o -OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o flacdsp.o -OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o flacdsp.o +OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o +OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o OBJS-$(CONFIG_FLASHSV2_DECODER) += flashsv.o @@ -198,9 +233,13 @@ OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o OBJS-$(CONFIG_FRWU_DECODER) += frwu.o -OBJS-$(CONFIG_G2M_DECODER) += g2meet.o mjpeg.o -OBJS-$(CONFIG_G723_1_DECODER) += g723_1.o acelp_vectors.o \ - celp_filters.o +OBJS-$(CONFIG_G2M_DECODER) += g2meet.o elsdec.o +OBJS-$(CONFIG_G723_1_DECODER) += g723_1dec.o g723_1.o \ + acelp_vectors.o celp_filters.o \ + celp_math.o +OBJS-$(CONFIG_G723_1_ENCODER) += g723_1enc.o g723_1.o \ + acelp_vectors.o celp_filters.o \ + celp_math.o OBJS-$(CONFIG_GIF_DECODER) += gifdec.o lzw.o OBJS-$(CONFIG_GIF_ENCODER) += gif.o lzwenc.o OBJS-$(CONFIG_GSM_DECODER) += gsmdec.o gsmdec_data.o msgsmdec.o @@ -209,17 +248,33 @@ OBJS-$(CONFIG_H261_DECODER) += h261dec.o h261data.o h261.o OBJS-$(CONFIG_H261_ENCODER) += h261enc.o h261data.o h261.o OBJS-$(CONFIG_H263_DECODER) += h263dec.o h263.o ituh263dec.o \ mpeg4video.o mpeg4videodec.o flvdec.o\ - intelh263dec.o + intelh263dec.o h263data.o OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o mpeg4video.o \ - h263.o ituh263enc.o flvenc.o -OBJS-$(CONFIG_H264_DECODER) += h264.o h264_cabac.o h264_cavlc.o \ + h263.o ituh263enc.o flvenc.o h263data.o +OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ h264_direct.o h264_loopfilter.o \ - h264_mb.o h264_picture.o h264_ps.o \ - h264_refs.o h264_sei.o h264_slice.o + h264_mb.o h264_picture.o \ + h264_refs.o h264_sei.o \ + h264_slice.o h264data.o +OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o +OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o +OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o +OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o +OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o +OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o +OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o +OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ - hevcdsp.o hevc_filter.o + hevcdsp.o hevc_filter.o h2645_parse.o hevc_data.o +OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o +OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o +OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o h2645_parse.o +OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o +OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ + canopus.o +OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o hqxdsp.o canopus.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o @@ -228,11 +283,11 @@ OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o OBJS-$(CONFIG_IMC_DECODER) += imc.o OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o -OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi_common.o ivi_dsp.o -OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi_common.o ivi_dsp.o +OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi.o +OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi.o OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o -OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o \ +OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \ jpeg2000dwt.o mqcdec.o mqc.o OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o @@ -240,17 +295,19 @@ OBJS-$(CONFIG_JV_DECODER) += jvdec.o OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o -OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpeg.o mjpegenc_common.o +OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o +OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \ twinvq.o OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o -OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpeg.o -OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o mjpegenc_common.o +OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o +OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o +OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o @@ -271,21 +328,25 @@ OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEG_XVMC_DECODER) += mpegvideo_xvmc.o OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o +OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec_mpeg2.o +OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o +OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o +OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o +OBJS-$(CONFIG_MSA1_DECODER) += mss3.o OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V2_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V2_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o -OBJS-$(CONFIG_MSA1_DECODER) += mss3.o mss34dsp.o OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o -OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o +OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o wmv2data.o OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o -OBJS-$(CONFIG_MTS2_DECODER) += mss4.o mss34dsp.o +OBJS-$(CONFIG_MTS2_DECODER) += mss4.o OBJS-$(CONFIG_MVC1_DECODER) += mvcdec.o OBJS-$(CONFIG_MVC2_DECODER) += mvcdec.o OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o @@ -294,8 +355,7 @@ OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opus.o opus_celt.o \ - opus_imdct.o opus_silk.o \ - vorbis_data.o + opus_silk.o vorbis_data.o OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o @@ -339,14 +399,16 @@ OBJS-$(CONFIG_ROQ_ENCODER) += roqvideoenc.o roqvideo.o elbg.o OBJS-$(CONFIG_ROQ_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o OBJS-$(CONFIG_RPZA_DECODER) += rpza.o +OBJS-$(CONFIG_RSCC_DECODER) += rscc.o OBJS-$(CONFIG_RV10_DECODER) += rv10.o OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o OBJS-$(CONFIG_RV20_DECODER) += rv10.o OBJS-$(CONFIG_RV20_ENCODER) += rv20enc.o -OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o rv34dsp.o -OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv34dsp.o rv40dsp.o +OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o +OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv40dsp.o OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_SANM_DECODER) += sanm.o +OBJS-$(CONFIG_SCREENPRESSO_DECODER) += screenpresso.o OBJS-$(CONFIG_SGI_DECODER) += sgidec.o OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o @@ -363,53 +425,56 @@ OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o -OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263.o -OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o \ +OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263data.o +OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o h263data.o \ h263.o ituh263enc.o -OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o mpegutils.o +OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o mpegutils.o h264data.o OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o OBJS-$(CONFIG_TARGA_DECODER) += targa.o OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o -OBJS-$(CONFIG_THEORA_DECODER) += xiph.o +OBJS-$(CONFIG_TDSC_DECODER) += tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEMOTION1_DECODER) += truemotion1.o OBJS-$(CONFIG_TRUEMOTION2_DECODER) += truemotion2.o +OBJS-$(CONFIG_TRUEMOTION2RT_DECODER) += truemotion2rt.o OBJS-$(CONFIG_TRUESPEECH_DECODER) += truespeech.o OBJS-$(CONFIG_TSCC_DECODER) += tscc.o msrledec.o OBJS-$(CONFIG_TSCC2_DECODER) += tscc2.o OBJS-$(CONFIG_TTA_DECODER) += tta.o OBJS-$(CONFIG_TWINVQ_DECODER) += twinvqdec.o twinvq.o -OBJS-$(CONFIG_TXD_DECODER) += txd.o s3tc.o +OBJS-$(CONFIG_TXD_DECODER) += txd.o OBJS-$(CONFIG_ULTI_DECODER) += ulti.o OBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodec.o utvideo.o OBJS-$(CONFIG_UTVIDEO_ENCODER) += utvideoenc.o utvideo.o OBJS-$(CONFIG_V210_DECODER) += v210dec.o OBJS-$(CONFIG_V210_ENCODER) += v210enc.o +OBJS-$(CONFIG_V210X_DECODER) += v210x.o OBJS-$(CONFIG_V410_DECODER) += v410dec.o OBJS-$(CONFIG_V410_ENCODER) += v410enc.o -OBJS-$(CONFIG_V210X_DECODER) += v210x.o OBJS-$(CONFIG_VB_DECODER) += vb.o OBJS-$(CONFIG_VBLE_DECODER) += vble.o -OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \ - msmpeg4dec.o msmpeg4.o msmpeg4data.o +OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o \ + vc1_mc.o vc1_pred.o vc1.o vc1data.o \ + msmpeg4dec.o msmpeg4.o msmpeg4data.o \ + wmv2data.o +OBJS-$(CONFIG_VC1_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdaudio.o OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdvideo.o OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o OBJS-$(CONFIG_VORBIS_DECODER) += vorbisdec.o vorbisdsp.o vorbis.o \ - vorbis_data.o xiph.o + vorbis_data.o OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \ vorbis_data.o OBJS-$(CONFIG_VP3_DECODER) += vp3.o -OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \ - vp56rac.o -OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp56dsp.o \ +OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56rac.o +OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \ vp6dsp.o vp56rac.o -OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp8dsp.o vp56rac.o -OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56rac.o +OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp56rac.o +OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp56rac.o OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o \ vp9block.o vp9prob.o vp9mvs.o vp56rac.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o @@ -425,11 +490,12 @@ OBJS-$(CONFIG_WMAVOICE_DECODER) += wmavoice.o \ celp_filters.o \ acelp_vectors.o acelp_filters.o OBJS-$(CONFIG_WMV1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o -OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2dsp.o \ +OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2data.o \ msmpeg4dec.o msmpeg4.o msmpeg4data.o -OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2dsp.o \ +OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2data.o \ msmpeg4.o msmpeg4enc.o msmpeg4data.o OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o +OBJS-$(CONFIG_WRAPPED_AVFRAME_ENCODER) += wrapped_avframe.o OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_XAN_WC3_DECODER) += xan.o @@ -469,6 +535,7 @@ OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += 8svx.o OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S16BE_PLANAR_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S16LE_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S16LE_PLANAR_DECODER) += pcm.o @@ -510,8 +577,8 @@ OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_XAS_DECODER) += adpcm.o adpcm_data.o -OBJS-$(CONFIG_ADPCM_G722_DECODER) += g722.o g722dec.o -OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o g722enc.o +OBJS-$(CONFIG_ADPCM_G722_DECODER) += g722.o g722dsp.o g722dec.o +OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o g722dsp.o g722enc.o OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o @@ -541,61 +608,52 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o # hardware accelerators +OBJS-$(CONFIG_D3D11VA) += dxva2.o +OBJS-$(CONFIG_DXVA2) += dxva2.o +OBJS-$(CONFIG_VAAPI) += vaapi.o +OBJS-$(CONFIG_VDA) += vda.o +OBJS-$(CONFIG_VDPAU) += vdpau.o + OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o -OBJS-$(CONFIG_H263_VDPAU_HWACCEL) += vdpau_mpeg4.o +OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o +OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o +OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o +OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o +OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o +OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o # libavformat dependencies +OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o + OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_CAF_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ - ac3tab.o -OBJS-$(CONFIG_FLAC_DEMUXER) += flac.o flacdata.o \ - vorbis_parser.o xiph.o -OBJS-$(CONFIG_FLAC_MUXER) += flac.o flacdata.o +OBJS-$(CONFIG_CAF_DEMUXER) += ac3tab.o OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o -OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o -OBJS-$(CONFIG_IFF_DEMUXER) += iff.o -OBJS-$(CONFIG_ISMV_MUXER) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o \ - flac.o flacdata.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ - vorbis_parser.o xiph.o -OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o mpegaudiodata.o \ - flac.o flacdata.o xiph.o -OBJS-$(CONFIG_MP2_MUXER) += mpegaudiodata.o mpegaudiodecheader.o +OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o +OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o +OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_MP3_MUXER) += mpegaudiodata.o mpegaudiodecheader.o -OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o ac3tab.o -OBJS-$(CONFIG_MOV_MUXER) += mpeg4audio.o mpegaudiodata.o -OBJS-$(CONFIG_MPEGTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o -OBJS-$(CONFIG_OGG_DEMUXER) += xiph.o flac.o flacdata.o \ - mpeg12data.o vorbis_parser.o \ - dirac.o -OBJS-$(CONFIG_OGG_MUXER) += xiph.o flac.o flacdata.o -OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o xiph.o -OBJS-$(CONFIG_RTPDEC) += mjpeg.o OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o -OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o mpegaudiodata.o \ - xiph.o flac.o flacdata.o -OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # external codec libraries +OBJS-$(CONFIG_LIBDCADEC_DECODER) += libdcadec.o dca.o OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o @@ -605,10 +663,13 @@ OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsmdec.o OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsmenc.o OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o +OBJS-$(CONFIG_LIBKVAZAAR_ENCODER) += libkvazaar.o OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o +OBJS-$(CONFIG_LIBOPENH264_DECODER) += libopenh264dec.o libopenh264.o +OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o libopenh264.o OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ @@ -626,22 +687,23 @@ OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbis.o \ - vorbis_data.o vorbis_parser.o -OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o -OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o + vorbis_data.o +OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o libvpx.o +OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o libvpx.o OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc.o +OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o # parsers +OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ aacadtsdec.o mpeg4audio.o -OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \ aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o @@ -651,19 +713,20 @@ OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca.o OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o +OBJS-$(CONFIG_DPX_PARSER) += dpx_parser.o OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o OBJS-$(CONFIG_GSM_PARSER) += gsm_parser.o OBJS-$(CONFIG_H261_PARSER) += h261_parser.o OBJS-$(CONFIG_H263_PARSER) += h263_parser.o -OBJS-$(CONFIG_H264_PARSER) += h264_parser.o -OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o +OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264_sei.o h264data.o +OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o h2645_parse.o hevc_ps.o hevc_data.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \ mpeg4videodec.o mpeg4video.o \ - ituh263dec.o h263dec.o + ituh263dec.o h263dec.o h263data.o OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o \ mpegaudiodecheader.o mpegaudiodata.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ @@ -674,10 +737,8 @@ OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o -OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o vc1dsp.o \ - msmpeg4.o msmpeg4data.o mpeg4video.o \ - h263.o -OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o +OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ + simple_idct.o wmv2data.o OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o @@ -687,8 +748,9 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \ OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o +OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o -OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o mjpeg.o +OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o @@ -706,17 +768,23 @@ SKIPHEADERS += %_tablegen.h \ tableprint.h \ $(ARCH)/vp56_arith.h \ +SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h +SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h -SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h +SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h +SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h +SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h +SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_encode.h vaapi_internal.h SKIPHEADERS-$(CONFIG_VDA) += vda.h vda_internal.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h TESTPROGS-$(CONFIG_FFT) += fft fft-fixed +TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_IDCTDSP) += dct TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter -TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_RANGECODER) += rangecoder TESTOBJS = dctref.o @@ -734,7 +802,7 @@ HOSTPROGS = aac_tablegen \ CLEANFILES = *_tables.c *_tables.h *_tablegen$(HOSTEXESUF) -$(SUBDIR)dct-test$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o +$(SUBDIR)tests/dct$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o $(SUBDIR)dv_tablegen$(HOSTEXESUF): $(SUBDIR)dvdata_host.o TRIG_TABLES = cos cos_fixed sin @@ -762,10 +830,10 @@ $(SUBDIR)aacdec.o: $(SUBDIR)cbrt_tables.h $(SUBDIR)aacps.o: $(SUBDIR)aacps_tables.h $(SUBDIR)aactab.o: $(SUBDIR)aac_tables.h $(SUBDIR)dvenc.o: $(SUBDIR)dv_tables.h -$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h +$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h $(SUBDIR)mpegaudiodec_fixed.o: $(SUBDIR)mpegaudio_tables.h $(SUBDIR)mpegaudiodec_float.o: $(SUBDIR)mpegaudio_tables.h -$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h $(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h +$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h endif diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c index 786074f..5d8d162 100644 --- a/libavcodec/a64multienc.c +++ b/libavcodec/a64multienc.c @@ -44,7 +44,8 @@ static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1}; //static const int mc_colors[5]={0x0,0x8,0xa,0xf,0x7}; //static const int mc_colors[5]={0x0,0x9,0x8,0xa,0x3}; -static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest) +static void to_meta_with_crop(AVCodecContext *avctx, + const AVFrame *p, int *dest) { int blockx, blocky, x, y; int luma = 0; @@ -165,7 +166,6 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset, static av_cold int a64multi_close_encoder(AVCodecContext *avctx) { A64Context *c = avctx->priv_data; - av_frame_free(&avctx->coded_frame); av_free(c->mc_meta_charset); av_free(c->mc_best_cb); av_free(c->mc_charset); @@ -209,7 +209,7 @@ static av_cold int a64multi_encode_init(AVCodecContext *avctx) } /* set up extradata */ - if (!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) { + if (!(avctx->extradata = av_mallocz(8 * 4 + AV_INPUT_BUFFER_PADDING_SIZE))) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for extradata.\n"); return AVERROR(ENOMEM); } @@ -217,14 +217,12 @@ static av_cold int a64multi_encode_init(AVCodecContext *avctx) AV_WB32(avctx->extradata, c->mc_lifetime); AV_WB32(avctx->extradata + 16, INTERLACED); - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - a64multi_close_encoder(avctx); - return AVERROR(ENOMEM); - } - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!avctx->codec_tag) avctx->codec_tag = AV_RL32("a64m"); @@ -252,7 +250,6 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { A64Context *c = avctx->priv_data; - AVFrame *const p = avctx->coded_frame; int frame; int x, y; @@ -296,10 +293,13 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } else { /* fill up mc_meta_charset with data until lifetime exceeds */ if (c->mc_frame_counter < c->mc_lifetime) { - *p = *pict; - p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; - to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + to_meta_with_crop(avctx, pict, meta + 32000 * c->mc_frame_counter); c->mc_frame_counter++; if (c->next_pts == AV_NOPTS_VALUE) c->next_pts = pict->pts; @@ -321,8 +321,14 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, buf = pkt->data; /* calc optimal new charset + charmaps */ - ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); - ff_do_elbg (meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); + ret = ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, + CHARSET_CHARS, 50, charmap, &c->randctx); + if (ret < 0) + return ret; + ret = ff_do_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, + CHARSET_CHARS, 50, charmap, &c->randctx); + if (ret < 0) + return ret; /* create colorram map and a c64 readable charset */ render_charset(avctx, charset, colram); @@ -386,7 +392,7 @@ AVCodec ff_a64multi_encoder = { .encode2 = a64multi_encode_frame, .close = a64multi_close_encoder, .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, }; AVCodec ff_a64multi5_encoder = { @@ -399,5 +405,5 @@ AVCodec ff_a64multi5_encoder = { .encode2 = a64multi_encode_frame, .close = a64multi_close_encoder, .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, }; diff --git a/libavcodec/aac.h b/libavcodec/aac.h index 375e6b1..fed6bf4 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -32,10 +32,10 @@ #include "libavutil/float_dsp.h" #include "avcodec.h" +#include "imdct15.h" #include "fft.h" #include "mpeg4audio.h" #include "sbr.h" -#include "fmtconvert.h" #include @@ -291,7 +291,7 @@ typedef struct AACContext { FFTContext mdct_small; FFTContext mdct_ld; FFTContext mdct_ltp; - FmtConvertContext fmt_conv; + IMDCT15Context *mdct480; AVFloatDSPContext fdsp; int random_state; /** @} */ diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index d3da9b7..806a826 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -84,14 +84,6 @@ get_next: avctx->sample_rate = s->sample_rate; /* (E-)AC-3: allow downmixing to stereo or mono */ -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->request_channels == 1) - avctx->request_channel_layout = AV_CH_LAYOUT_MONO; - else if (avctx->request_channels == 2) - avctx->request_channel_layout = AV_CH_LAYOUT_STEREO; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (s->channels > 1 && avctx->request_channel_layout == AV_CH_LAYOUT_MONO) { avctx->channels = 1; diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c index bec6e7f..9168e2b 100644 --- a/libavcodec/aac_adtstoasc_bsf.c +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "aacadtsdec.h" +#include "bsf.h" #include "put_bits.h" #include "get_bits.h" #include "mpeg4audio.h" @@ -34,63 +35,76 @@ typedef struct AACBSFContext { * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 * ADTS header and removes the ADTS header. */ -static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, - AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int keyframe) +static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) { + AACBSFContext *ctx = bsfc->priv_data; + GetBitContext gb; PutBitContext pb; AACADTSHeaderInfo hdr; + AVPacket *in; + int ret; - AACBSFContext *ctx = bsfc->priv_data; + ret = ff_bsf_get_packet(bsfc, &in); + if (ret < 0) + return ret; - init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8); + if (in->size < AAC_ADTS_HEADER_SIZE) + goto packet_too_small; - *poutbuf = (uint8_t*) buf; - *poutbuf_size = buf_size; + init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8); - if (avctx->extradata) - if (show_bits(&gb, 12) != 0xfff) - return 0; + if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff) + goto finish; if (avpriv_aac_parse_header(&gb, &hdr) < 0) { - av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); - return -1; + av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); + ret = AVERROR_INVALIDDATA; + goto fail; } if (!hdr.crc_absent && hdr.num_aac_frames > 1) { - avpriv_report_missing_feature(avctx, + avpriv_report_missing_feature(bsfc, "Multiple RDBs per frame with CRC"); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } - buf += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; - buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; + in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; + if (in->size <= 0) + goto packet_too_small; + in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; if (!ctx->first_frame_done) { int pce_size = 0; uint8_t pce_data[MAX_PCE_SIZE]; + uint8_t *extradata; + if (!hdr.chan_config) { - init_get_bits(&gb, buf, buf_size * 8); + init_get_bits(&gb, in->data, in->size * 8); if (get_bits(&gb, 3) != 5) { - avpriv_report_missing_feature(avctx, + avpriv_report_missing_feature(bsfc, "PCE-based channel configuration " "without PCE as first syntax " "element"); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } init_put_bits(&pb, pce_data, MAX_PCE_SIZE); pce_size = avpriv_copy_pce_data(&pb, &gb)/8; flush_put_bits(&pb); - buf_size -= get_bits_count(&gb)/8; - buf += get_bits_count(&gb)/8; + in->size -= get_bits_count(&gb)/8; + in->data += get_bits_count(&gb)/8; } - avctx->extradata_size = 2 + pce_size; - avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - init_put_bits(&pb, avctx->extradata, avctx->extradata_size); + extradata = av_packet_new_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, + 2 + pce_size); + if (!extradata) { + ret = AVERROR(ENOMEM); + goto fail; + } + + init_put_bits(&pb, extradata, 2 + pce_size); put_bits(&pb, 5, hdr.object_type); put_bits(&pb, 4, hdr.sampling_index); put_bits(&pb, 4, hdr.chan_config); @@ -99,20 +113,42 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, put_bits(&pb, 1, 0); //is not extension flush_put_bits(&pb); if (pce_size) { - memcpy(avctx->extradata + 2, pce_data, pce_size); + memcpy(extradata + 2, pce_data, pce_size); } ctx->first_frame_done = 1; } - *poutbuf = (uint8_t*) buf; - *poutbuf_size = buf_size; +finish: + av_packet_move_ref(out, in); + av_packet_free(&in); + + return 0; + +packet_too_small: + av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n"); + ret = AVERROR_INVALIDDATA; +fail: + av_packet_free(&in); + return ret; +} + +static int aac_adtstoasc_init(AVBSFContext *ctx) +{ + av_freep(&ctx->par_out->extradata); + ctx->par_out->extradata_size = 0; return 0; } -AVBitStreamFilter ff_aac_adtstoasc_bsf = { - "aac_adtstoasc", - sizeof(AACBSFContext), - aac_adtstoasc_filter, +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_AAC, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_aac_adtstoasc_bsf = { + .name = "aac_adtstoasc", + .priv_data_size = sizeof(AACBSFContext), + .init = aac_adtstoasc_init, + .filter = aac_adtstoasc_filter, + .codec_ids = codec_ids, }; diff --git a/libavcodec/aac_parser.c b/libavcodec/aac_parser.c index acb05d4..eae120a 100644 --- a/libavcodec/aac_parser.c +++ b/libavcodec/aac_parser.c @@ -34,7 +34,7 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, int size; union { uint64_t u64; - uint8_t u8[8 + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t u8[8 + AV_INPUT_BUFFER_PADDING_SIZE]; } tmp; tmp.u64 = av_be2ne64(state); diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 35b98a9..ee89148 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -161,7 +161,7 @@ static av_always_inline float quantize_and_encode_band_cost_template( di = t - CLIPPED_ESCAPE; curbits += 21; } else { - int c = av_clip(quant(t, Q), 0, 8191); + int c = av_clip_uintp2(quant(t, Q), 13); di = t - c*cbrtf(c)*IQ; curbits += av_log2(c)*2 - 4 + 1; } @@ -191,7 +191,7 @@ static av_always_inline float quantize_and_encode_band_cost_template( if (BT_ESC) { for (j = 0; j < 2; j++) { if (ff_aac_codebook_vectors[cb-1][curidx*2+j] == 64.0f) { - int coef = av_clip(quant(fabsf(in[i+j]), Q), 0, 8191); + int coef = av_clip_uintp2(quant(fabsf(in[i+j]), Q), 13); int len = av_log2(coef); put_bits(pb, len - 4 + 1, (1 << (len - 4 + 1)) - 2); diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 2258aed..0e629ce 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -85,7 +85,7 @@ #include "internal.h" #include "get_bits.h" #include "fft.h" -#include "fmtconvert.h" +#include "imdct15.h" #include "lpc.h" #include "kbdwin.h" #include "sinewin.h" @@ -110,6 +110,8 @@ # include "arm/aac.h" #endif +#include "libavutil/thread.h" + static VLC vlc_scalefactors; static VLC vlc_spectral[11]; @@ -291,6 +293,11 @@ static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags) if (num_back_channels < 0) return 0; + if (num_side_channels == 0 && num_back_channels >= 4) { + num_side_channels = 2; + num_back_channels -= 2; + } + i = 0; if (num_front_channels & 1) { e2c_vec[i] = (struct elem_to_channel) { @@ -443,12 +450,18 @@ static int output_configure(AACContext *ac, AVCodecContext *avctx = ac->avctx; int i, channels = 0, ret; uint64_t layout = 0; + uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }}; + uint8_t type_counts[TYPE_END] = { 0 }; if (ac->oc[1].layout_map != layout_map) { memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0])); ac->oc[1].layout_map_tags = tags; } - + for (i = 0; i < tags; i++) { + int type = layout_map[i][0]; + int id = layout_map[i][1]; + id_map[type][id] = type_counts[type]++; + } // Try to sniff a reasonable channel order, otherwise output the // channels in the order the PCE declared them. if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) @@ -456,12 +469,14 @@ static int output_configure(AACContext *ac, for (i = 0; i < tags; i++) { int type = layout_map[i][0]; int id = layout_map[i][1]; + int iid = id_map[type][id]; int position = layout_map[i][2]; // Allocate or free elements depending on if they are in the // current program configuration. - ret = che_configure(ac, position, type, id, &channels); + ret = che_configure(ac, position, type, iid, &channels); if (ret < 0) return ret; + ac->tag_che_map[type][id] = ac->che[type][iid]; } if (ac->oc[1].m4ac.ps == 1 && channels == 2) { if (layout == AV_CH_FRONT_CENTER) { @@ -471,7 +486,6 @@ static int output_configure(AACContext *ac, } } - memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); avctx->channel_layout = ac->oc[1].channel_layout = layout; avctx->channels = ac->oc[1].channels = channels; ac->oc[1].status = oc_type; @@ -495,7 +509,8 @@ static int set_default_channel_config(AVCodecContext *avctx, int *tags, int channel_config) { - if (channel_config < 1 || channel_config > 7) { + if (channel_config < 1 || (channel_config > 7 && channel_config < 11) || + channel_config > 12) { av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n", channel_config); @@ -552,11 +567,19 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) /* For indexed channel configurations map the channels solely based * on position. */ switch (ac->oc[1].m4ac.chan_config) { + case 12: case 7: if (ac->tags_mapped == 3 && type == TYPE_CPE) { ac->tags_mapped++; return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2]; } + case 11: + if (ac->tags_mapped == 2 && + ac->oc[1].m4ac.chan_config == 11 && + type == TYPE_SCE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1]; + } case 6: /* Some streams incorrectly code 5.1 audio as * SCE[0] CPE[0] CPE[1] SCE[1] @@ -624,6 +647,9 @@ static void decode_channel_map(uint8_t layout_map[][3], case AAC_CHANNEL_LFE: syn_ele = TYPE_LFE; break; + default: + // AAC_CHANNEL_OFF has no channel map + return; } layout_map[0][0] = syn_ele; layout_map[0][1] = get_bits(gb, 4); @@ -716,6 +742,7 @@ static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, avpriv_request_sample(avctx, "960/120 MDCT window"); return AVERROR_PATCHWELCOME; } + m4ac->frame_length_short = 0; if (get_bits1(gb)) // dependsOnCoreCoder skip_bits(gb, 14); // coreCoderDelay @@ -793,11 +820,7 @@ static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx, m4ac->ps = 0; m4ac->sbr = 0; - if (get_bits1(gb)) { // frameLengthFlag - avpriv_request_sample(avctx, "960/120 MDCT window"); - return AVERROR_PATCHWELCOME; - } - + m4ac->frame_length_short = get_bits1(gb); res_flags = get_bits(gb, 3); if (res_flags) { avpriv_report_missing_feature(avctx, @@ -819,7 +842,7 @@ static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx, if (len == 15 + 255) len += get_bits(gb, 16); if (get_bits_left(gb) < len * 8 + 4) { - av_log(ac->avctx, AV_LOG_ERROR, overread_err); + av_log(avctx, AV_LOG_ERROR, overread_err); return AVERROR_INVALIDDATA; } skip_bits_long(gb, 8 * len); @@ -862,10 +885,10 @@ static int decode_audio_specific_config(AACContext *ac, GetBitContext gb; int i, ret; - av_dlog(avctx, "extradata size %d\n", avctx->extradata_size); + ff_dlog(avctx, "extradata size %d\n", avctx->extradata_size); for (i = 0; i < avctx->extradata_size; i++) - av_dlog(avctx, "%02x ", avctx->extradata[i]); - av_dlog(avctx, "\n"); + ff_dlog(avctx, "%02x ", avctx->extradata[i]); + ff_dlog(avctx, "\n"); if ((ret = init_get_bits(&gb, data, bit_size)) < 0) return ret; @@ -912,7 +935,7 @@ static int decode_audio_specific_config(AACContext *ac, return AVERROR(ENOSYS); } - av_dlog(avctx, + ff_dlog(avctx, "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n", m4ac->object_type, m4ac->chan_config, m4ac->sampling_index, m4ac->sample_rate, m4ac->sbr, @@ -982,11 +1005,56 @@ static void reset_predictor_group(PredictorState *ps, int group_num) sizeof(ff_aac_spectral_codes[num][0]), \ size); +static av_cold void aac_static_table_init(void) +{ + AAC_INIT_VLC_STATIC( 0, 304); + AAC_INIT_VLC_STATIC( 1, 270); + AAC_INIT_VLC_STATIC( 2, 550); + AAC_INIT_VLC_STATIC( 3, 300); + AAC_INIT_VLC_STATIC( 4, 328); + AAC_INIT_VLC_STATIC( 5, 294); + AAC_INIT_VLC_STATIC( 6, 306); + AAC_INIT_VLC_STATIC( 7, 268); + AAC_INIT_VLC_STATIC( 8, 510); + AAC_INIT_VLC_STATIC( 9, 366); + AAC_INIT_VLC_STATIC(10, 462); + + ff_aac_sbr_init(); + + ff_aac_tableinit(); + + INIT_VLC_STATIC(&vlc_scalefactors, 7, + FF_ARRAY_ELEMS(ff_aac_scalefactor_code), + ff_aac_scalefactor_bits, + sizeof(ff_aac_scalefactor_bits[0]), + sizeof(ff_aac_scalefactor_bits[0]), + ff_aac_scalefactor_code, + sizeof(ff_aac_scalefactor_code[0]), + sizeof(ff_aac_scalefactor_code[0]), + 352); + + + // window initialization + ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); + ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows( 9); + ff_init_ff_sine_windows( 7); + + cbrt_tableinit(); +} + +static AVOnce aac_init = AV_ONCE_INIT; + static av_cold int aac_decode_init(AVCodecContext *avctx) { AACContext *ac = avctx->priv_data; int ret; + ret = ff_thread_once(&aac_init, &aac_static_table_init); + if (ret != 0) + return AVERROR_UNKNOWN; + ac->avctx = avctx; ac->oc[1].m4ac.sample_rate = avctx->sample_rate; @@ -1028,49 +1096,17 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) } } - AAC_INIT_VLC_STATIC( 0, 304); - AAC_INIT_VLC_STATIC( 1, 270); - AAC_INIT_VLC_STATIC( 2, 550); - AAC_INIT_VLC_STATIC( 3, 300); - AAC_INIT_VLC_STATIC( 4, 328); - AAC_INIT_VLC_STATIC( 5, 294); - AAC_INIT_VLC_STATIC( 6, 306); - AAC_INIT_VLC_STATIC( 7, 268); - AAC_INIT_VLC_STATIC( 8, 510); - AAC_INIT_VLC_STATIC( 9, 366); - AAC_INIT_VLC_STATIC(10, 462); - - ff_aac_sbr_init(); - - ff_fmt_convert_init(&ac->fmt_conv, avctx); - avpriv_float_dsp_init(&ac->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&ac->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); ac->random_state = 0x1f2e3d4c; - ff_aac_tableinit(); - - INIT_VLC_STATIC(&vlc_scalefactors, 7, - FF_ARRAY_ELEMS(ff_aac_scalefactor_code), - ff_aac_scalefactor_bits, - sizeof(ff_aac_scalefactor_bits[0]), - sizeof(ff_aac_scalefactor_bits[0]), - ff_aac_scalefactor_code, - sizeof(ff_aac_scalefactor_code[0]), - sizeof(ff_aac_scalefactor_code[0]), - 352); - ff_mdct_init(&ac->mdct, 11, 1, 1.0 / (32768.0 * 1024.0)); ff_mdct_init(&ac->mdct_ld, 10, 1, 1.0 / (32768.0 * 512.0)); ff_mdct_init(&ac->mdct_small, 8, 1, 1.0 / (32768.0 * 128.0)); ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0 * 32768.0); - // window initialization - ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); - ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); - ff_init_ff_sine_windows(10); - ff_init_ff_sine_windows( 9); - ff_init_ff_sine_windows( 7); - - cbrt_tableinit(); + ret = ff_imdct15_init(&ac->mdct480, 5); + if (ret < 0) + return ret; return 0; } @@ -1134,11 +1170,14 @@ static void decode_ltp(LongTermPrediction *ltp, static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, GetBitContext *gb) { - int aot = ac->oc[1].m4ac.object_type; + const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac; + const int aot = m4ac->object_type; + const int sampling_index = m4ac->sampling_index; if (aot != AOT_ER_AAC_ELD) { if (get_bits1(gb)) { av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n"); - return AVERROR_INVALIDDATA; + if (ac->avctx->err_recognition & AV_EF_BITSTREAM) + return AVERROR_INVALIDDATA; } ics->window_sequence[1] = ics->window_sequence[0]; ics->window_sequence[0] = get_bits(gb, 2); @@ -1167,23 +1206,29 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, } } ics->num_windows = 8; - ics->swb_offset = ff_swb_offset_128[ac->oc[1].m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_128[ac->oc[1].m4ac.sampling_index]; - ics->tns_max_bands = ff_tns_max_bands_128[ac->oc[1].m4ac.sampling_index]; + ics->swb_offset = ff_swb_offset_128[sampling_index]; + ics->num_swb = ff_aac_num_swb_128[sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_128[sampling_index]; ics->predictor_present = 0; } else { - ics->max_sfb = get_bits(gb, 6); - ics->num_windows = 1; + ics->max_sfb = get_bits(gb, 6); + ics->num_windows = 1; if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) { - ics->swb_offset = ff_swb_offset_512[ac->oc[1].m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_512[ac->oc[1].m4ac.sampling_index]; - ics->tns_max_bands = ff_tns_max_bands_512[ac->oc[1].m4ac.sampling_index]; + if (m4ac->frame_length_short) { + ics->swb_offset = ff_swb_offset_480[sampling_index]; + ics->num_swb = ff_aac_num_swb_480[sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_480[sampling_index]; + } else { + ics->swb_offset = ff_swb_offset_512[sampling_index]; + ics->num_swb = ff_aac_num_swb_512[sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_512[sampling_index]; + } if (!ics->num_swb || !ics->swb_offset) return AVERROR_BUG; } else { - ics->swb_offset = ff_swb_offset_1024[ac->oc[1].m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_1024[ac->oc[1].m4ac.sampling_index]; - ics->tns_max_bands = ff_tns_max_bands_1024[ac->oc[1].m4ac.sampling_index]; + ics->swb_offset = ff_swb_offset_1024[sampling_index]; + ics->num_swb = ff_aac_num_swb_1024[sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_1024[sampling_index]; } if (aot != AOT_ER_AAC_ELD) { ics->predictor_present = get_bits1(gb); @@ -1416,13 +1461,12 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb, int ms_present) { int idx; + int max_idx = cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb; if (ms_present == 1) { - for (idx = 0; - idx < cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb; - idx++) + for (idx = 0; idx < max_idx; idx++) cpe->ms_mask[idx] = get_bits1(gb); } else if (ms_present == 2) { - memset(cpe->ms_mask, 1, cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb * sizeof(cpe->ms_mask[0])); + memset(cpe->ms_mask, 1, max_idx * sizeof(cpe->ms_mask[0])); } } @@ -1872,8 +1916,8 @@ static int decode_ics(AACContext *ac, SingleChannelElement *sce, avpriv_request_sample(ac->avctx, "SSR"); return AVERROR_PATCHWELCOME; } - // I see no textual basis in the spec for this occuring after SSR gain - // control, but this is what both reference and real implmentations do + // I see no textual basis in the spec for this occurring after SSR gain + // control, but this is what both reference and real implementations do if (tns->present && er_syntax) if (decode_tns(ac, tns, gb, ics) < 0) return AVERROR_INVALIDDATA; @@ -2453,12 +2497,13 @@ static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce) float *in = sce->coeffs; float *out = sce->ret; float *saved = sce->saved; - const float *const window = ff_aac_eld_window; float *buf = ac->buf_mdct; int i; - const int n = 512; + const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512; const int n2 = n >> 1; const int n4 = n >> 2; + const float *const window = n == 480 ? ff_aac_eld_window_480 : + ff_aac_eld_window_512; // Inverse transform, mapped to the conventional IMDCT by // Chivukula, R.K.; Reznik, Y.A.; Devarajan, V., @@ -2470,7 +2515,10 @@ static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce) temp = in[i ]; in[i ] = -in[n - 1 - i]; in[n - 1 - i] = temp; temp = -in[i + 1]; in[i + 1] = in[n - 2 - i]; in[n - 2 - i] = temp; } - ac->mdct.imdct_half(&ac->mdct_ld, buf, in); + if (n == 480) + ac->mdct480->imdct_half(ac->mdct480, buf, in, 1, -1.f/(16*1024*960)); + else + ac->mdct.imdct_half(&ac->mdct_ld, buf, in); for (i = 0; i < n; i+=2) { buf[i] = -buf[i]; } @@ -2683,6 +2731,7 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate; ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index; ac->oc[1].m4ac.object_type = hdr_info.object_type; + ac->oc[1].m4ac.frame_length_short = 0; if (ac->oc[0].status != OC_LOCKED || ac->oc[0].m4ac.chan_config != hdr_info.chan_config || ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) { @@ -2699,11 +2748,12 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, GetBitContext *gb) { AACContext *ac = avctx->priv_data; + const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac; ChannelElement *che; int err, i; - int samples = 1024; - int chan_config = ac->oc[1].m4ac.chan_config; - int aot = ac->oc[1].m4ac.object_type; + int samples = m4ac->frame_length_short ? 960 : 1024; + int chan_config = m4ac->chan_config; + int aot = m4ac->object_type; if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) samples >>= 1; @@ -2715,13 +2765,13 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data, // The FF_PROFILE_AAC_* defines are all object_type - 1 // This may lead to an undefined profile being signaled - ac->avctx->profile = ac->oc[1].m4ac.object_type - 1; + ac->avctx->profile = aot - 1; ac->tags_mapped = 0; - if (chan_config < 0 || chan_config >= 8) { + if (chan_config < 0 || (chan_config >= 8 && chan_config < 11) || chan_config >= 13) { avpriv_request_sample(avctx, "Unknown ER channel configuration %d", - ac->oc[1].m4ac.chan_config); + chan_config); return AVERROR_INVALIDDATA; } for (i = 0; i < tags_per_config[chan_config]; i++) { @@ -2783,8 +2833,9 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, } } - if ((err = frame_configure_elements(avctx)) < 0) - goto fail; + if (avctx->channels) + if ((err = frame_configure_elements(avctx)) < 0) + goto fail; // The FF_PROFILE_AAC_* defines are all object_type - 1 // This may lead to an undefined profile being signaled @@ -2795,6 +2846,11 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, while ((elem_type = get_bits(gb, 3)) != TYPE_END) { elem_id = get_bits(gb, 4); + if (!avctx->channels && elem_type != TYPE_PCE) { + err = AVERROR_INVALIDDATA; + goto fail; + } + if (elem_type < TYPE_DSE) { if (!(che=get_che(ac, elem_type, elem_id))) { av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n", @@ -2881,6 +2937,11 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, } } + if (!avctx->channels) { + *got_frame_ptr = 0; + return 0; + } + spectral_to_sample(ac); multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0; @@ -2922,7 +2983,7 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data, if (new_extradata) { av_free(avctx->extradata); avctx->extradata = av_mallocz(new_extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); avctx->extradata_size = new_extradata_size; @@ -2977,6 +3038,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx) ff_mdct_end(&ac->mdct_small); ff_mdct_end(&ac->mdct_ld); ff_mdct_end(&ac->mdct_ltp); + ff_imdct15_uninit(&ac->mdct480); return 0; } @@ -2985,7 +3047,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx) struct LATMContext { AACContext aac_ctx; ///< containing AACContext - int initialized; ///< initilized after a valid extradata was seen + int initialized; ///< initialized after a valid extradata was seen // parser data int audio_mux_version_A; ///< LATM syntax version @@ -3041,14 +3103,14 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx, if (avctx->extradata_size < esize) { av_free(avctx->extradata); - avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_malloc(esize + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); } avctx->extradata_size = esize; memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize); - memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(avctx->extradata+esize, 0, AV_INPUT_BUFFER_PADDING_SIZE); } skip_bits_long(gb, bits_consumed); @@ -3167,7 +3229,7 @@ static int read_audio_mux_element(struct LATMContext *latmctx, } else if (!latmctx->aac_ctx.avctx->extradata) { av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG, "no decoder config found\n"); - return AVERROR(EAGAIN); + return 1; } if (latmctx->audio_mux_version_A == 0) { int mux_slot_length_bytes = read_payload_length_info(latmctx, gb); @@ -3204,8 +3266,8 @@ static int latm_decode_frame(AVCodecContext *avctx, void *out, if (muxlength > avpkt->size) return AVERROR_INVALIDDATA; - if ((err = read_audio_mux_element(latmctx, &gb)) < 0) - return err; + if ((err = read_audio_mux_element(latmctx, &gb))) + return (err < 0) ? err : avpkt->size; if (!latmctx->initialized) { if (!avctx->extradata) { @@ -3230,7 +3292,17 @@ static int latm_decode_frame(AVCodecContext *avctx, void *out, return AVERROR_INVALIDDATA; } - if ((err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb)) < 0) + switch (latmctx->aac_ctx.oc[1].m4ac.object_type) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + err = aac_decode_er_frame(avctx, out, got_frame_ptr, &gb); + break; + default: + err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb); + } + if (err < 0) return err; return muxlength; @@ -3260,7 +3332,8 @@ AVCodec ff_aac_decoder = { .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = aac_channel_layout, }; @@ -3281,6 +3354,7 @@ AVCodec ff_aac_latm_decoder = { .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = aac_channel_layout, }; diff --git a/libavcodec/aacdectab.h b/libavcodec/aacdectab.h index 4c23f2d..b7c5f7e 100644 --- a/libavcodec/aacdectab.h +++ b/libavcodec/aacdectab.h @@ -78,9 +78,9 @@ static const float * const tns_tmp2_map[4] = { }; // @} -static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 4, 5, 0, 5, 0 }; -static const uint8_t aac_channel_layout_map[7][5][3] = { +static const uint8_t aac_channel_layout_map[16][5][3] = { { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, @@ -88,9 +88,16 @@ static const uint8_t aac_channel_layout_map[7][5][3] = { { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, + { { 0, } }, + { { 0, } }, + { { 0, } }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, + { { 0, } }, + /* TODO: Add 7+1 TOP configuration */ }; -static const uint64_t aac_channel_layout[8] = { +static const uint64_t aac_channel_layout[16] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND, @@ -99,6 +106,12 @@ static const uint64_t aac_channel_layout[8] = { AV_CH_LAYOUT_5POINT1_BACK, AV_CH_LAYOUT_7POINT1_WIDE_BACK, 0, + 0, + 0, + AV_CH_LAYOUT_6POINT1, + AV_CH_LAYOUT_7POINT1, + 0, + /* AV_CH_LAYOUT_7POINT1_TOP, */ }; #endif /* AVCODEC_AACDECTAB_H */ diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index a7d144c..c247c5b 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -510,6 +510,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, ChannelElement *cpe; int i, ch, w, g, chans, tag, start_ch, ret; int chan_el_counter[4]; + int frame_bits; FFPsyWindowInfo windows[AAC_MAX_CHANNELS]; if (s->last_frame == 2) @@ -577,11 +578,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } do { - int frame_bits; - init_put_bits(&s->pb, avpkt->data, avpkt->size); - if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & CODEC_FLAG_BITEXACT)) + if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & AV_CODEC_FLAG_BITEXACT)) put_bitstream_info(s, LIBAVCODEC_IDENT); start_ch = 0; memset(chan_el_counter, 0, sizeof(chan_el_counter)); @@ -651,11 +650,16 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, put_bits(&s->pb, 3, TYPE_END); flush_put_bits(&s->pb); - avctx->frame_bits = put_bits_count(&s->pb); + frame_bits = put_bits_count(&s->pb); +#if FF_API_STAT_BITS +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_bits = frame_bits; +FF_ENABLE_DEPRECATION_WARNINGS +#endif // rate control stuff - if (!(avctx->flags & CODEC_FLAG_QSCALE)) { - float ratio = avctx->bit_rate * 1024.0f / avctx->sample_rate / avctx->frame_bits; + if (!(avctx->flags & AV_CODEC_FLAG_QSCALE)) { + float ratio = avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits; s->lambda *= ratio; s->lambda = FFMIN(s->lambda, 65536.f); } @@ -690,7 +694,7 @@ static av_cold int dsp_init(AVCodecContext *avctx, AACEncContext *s) { int ret = 0; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); // window init ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); @@ -711,7 +715,7 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s) int ch; FF_ALLOCZ_OR_GOTO(avctx, s->buffer.samples, 3 * 1024 * s->channels * sizeof(s->buffer.samples[0]), alloc_fail); FF_ALLOCZ_OR_GOTO(avctx, s->cpe, sizeof(ChannelElement) * s->chan_map[0], alloc_fail); - FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + FF_INPUT_BUFFER_PADDING_SIZE, alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + AV_INPUT_BUFFER_PADDING_SIZE, alloc_fail); for(ch = 0; ch < s->channels; ch++) s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch; @@ -744,7 +748,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) ERROR_IF(avctx->profile != FF_PROFILE_UNKNOWN && avctx->profile != FF_PROFILE_AAC_LOW, "Unsupported profile %d\n", avctx->profile); ERROR_IF(1024.0 * avctx->bit_rate / avctx->sample_rate > 6144 * s->channels, - "Too many bits per frame requested\n"); + "Too many bits %f > %d per frame requested\n", + 1024.0 * avctx->bit_rate / avctx->sample_rate, + 6144 * s->channels); s->samplerate_index = i; @@ -778,7 +784,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) for (i = 0; i < 428; i++) ff_aac_pow34sf_tab[i] = sqrt(ff_aac_pow2sf_tab[i] * sqrt(ff_aac_pow2sf_tab[i])); - avctx->delay = 1024; + avctx->initial_padding = 1024; ff_af_queue_init(avctx, &s->afq); return 0; @@ -812,8 +818,8 @@ AVCodec ff_aac_encoder = { .init = aac_encode_init, .encode2 = aac_encode_frame, .close = aac_encode_end, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | - CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_EXPERIMENTAL, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &aacenc_class, diff --git a/libavcodec/aacps.c b/libavcodec/aacps.c index 8f55c7f..df069c3 100644 --- a/libavcodec/aacps.c +++ b/libavcodec/aacps.c @@ -139,7 +139,7 @@ static int ps_read_extension_data(GetBitContext *gb, PSContext *ps, int ps_exten return get_bits_count(gb) - count; } -static void ipdopd_reset(int8_t *opd_hist, int8_t *ipd_hist) +static void ipdopd_reset(int8_t *ipd_hist, int8_t *opd_hist) { int i; for (i = 0; i < PS_MAX_NR_IPDOPD; i++) { diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c index ee465a6..6cfae6b 100644 --- a/libavcodec/aacpsy.c +++ b/libavcodec/aacpsy.c @@ -160,7 +160,7 @@ typedef struct AacPsyContext{ /** * LAME psy model preset struct */ -typedef struct { +typedef struct PsyLamePreset { int quality; ///< Quality to map the rest of the vaules to. /* This is overloaded to be both kbps per channel in ABR mode, and * requested quality in constant quality mode. @@ -256,7 +256,7 @@ static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx) for (i = 0; i < avctx->channels; i++) { AacPsyChannel *pch = &ctx->ch[i]; - if (avctx->flags & CODEC_FLAG_QSCALE) + if (avctx->flags & AV_CODEC_FLAG_QSCALE) pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm; else pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->channels / 1000); @@ -298,6 +298,8 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { const float num_bark = calc_bark((float)bandwidth); ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext)); + if (!ctx->model_priv_data) + return AVERROR(ENOMEM); pctx = (AacPsyContext*) ctx->model_priv_data; pctx->chan_bitrate = chan_bitrate; @@ -349,6 +351,10 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { } pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->channels); + if (!pctx->ch) { + av_freep(&pctx); + return AVERROR(ENOMEM); + } lame_window_init(pctx, ctx->avctx); @@ -790,7 +796,7 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, if (la) { float hpfsmpl[AAC_BLOCK_SIZE_LONG]; - float const *pf = hpfsmpl; + const float *pf = hpfsmpl; float attack_intensity[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS]; float energy_subshort[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS]; float energy_short[AAC_NUM_BLOCKS_SHORT + 1] = { 0 }; @@ -820,7 +826,7 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, } for (i = 0; i < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; i++) { - float const *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS); + const float *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS); float p = 1.0f; for (; pf < pfe; pf++) p = FFMAX(p, fabsf(*pf)); @@ -853,9 +859,9 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */ /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */ for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++) { - float const u = energy_short[i - 1]; - float const v = energy_short[i]; - float const m = FFMAX(u, v); + const float u = energy_short[i - 1]; + const float v = energy_short[i]; + const float m = FFMAX(u, v); if (m < 40000) { /* (2) */ if (u < 1.7f * v && v < 1.7f * u) { /* (1) */ if (i == 1 && attacks[0] < attacks[i]) diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c index dbfb167..d9bbe5e 100644 --- a/libavcodec/aacsbr.c +++ b/libavcodec/aacsbr.c @@ -130,7 +130,7 @@ av_cold void ff_aac_sbr_init(void) /** Places SBR in pure upsampling mode. */ static void sbr_turnoff(SpectralBandReplication *sbr) { sbr->start = 0; - // Init defults used in pure upsampling mode + // Init defaults used in pure upsampling mode sbr->kx[1] = 32; //Typo in spec, kx' inits to 32 sbr->m[1] = 0; // Reset values for first SBR header @@ -321,22 +321,12 @@ static int check_n_master(AVCodecContext *avctx, int n_master, int bs_xover_band static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, SpectrumParameters *spectrum) { - unsigned int temp, max_qmf_subbands; + unsigned int temp, max_qmf_subbands = 0; unsigned int start_min, stop_min; int k; const int8_t *sbr_offset_ptr; int16_t stop_dk[13]; - if (sbr->sample_rate < 32000) { - temp = 3000; - } else if (sbr->sample_rate < 64000) { - temp = 4000; - } else - temp = 5000; - - start_min = ((temp << 7) + (sbr->sample_rate >> 1)) / sbr->sample_rate; - stop_min = ((temp << 8) + (sbr->sample_rate >> 1)) / sbr->sample_rate; - switch (sbr->sample_rate) { case 16000: sbr_offset_ptr = sbr_offset[0]; @@ -362,6 +352,16 @@ static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, return -1; } + if (sbr->sample_rate < 32000) { + temp = 3000; + } else if (sbr->sample_rate < 64000) { + temp = 4000; + } else + temp = 5000; + + start_min = ((temp << 7) + (sbr->sample_rate >> 1)) / sbr->sample_rate; + stop_min = ((temp << 8) + (sbr->sample_rate >> 1)) / sbr->sample_rate; + sbr->k[0] = start_min + sbr_offset_ptr[spectrum->bs_start_freq]; if (spectrum->bs_stop_freq < 14) { @@ -628,7 +628,7 @@ static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr, GetBitContext *gb, SBRData *ch_data) { int i; - unsigned bs_pointer = 0; + int bs_pointer = 0; // frameLengthFlag ? 15 : 16; 960 sample length frames unsupported; this value is numTimeSlots int abs_bord_trail = 16; int num_rel_lead, num_rel_trail; @@ -721,7 +721,7 @@ static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr, break; } - if (bs_pointer > ch_data->bs_num_env + 1) { + if (bs_pointer < 0 || bs_pointer > ch_data->bs_num_env + 1) { av_log(ac->avctx, AV_LOG_ERROR, "Invalid bitstream, bs_pointer points to a middle noise border outside the time borders table: %d\n", bs_pointer); @@ -740,7 +740,7 @@ static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr, ch_data->t_q[0] = ch_data->t_env[0]; ch_data->t_q[ch_data->bs_num_noise] = ch_data->t_env[ch_data->bs_num_env]; if (ch_data->bs_num_noise > 1) { - unsigned int idx; + int idx; if (ch_data->bs_frame_class == FIXFIX) { idx = ch_data->bs_num_env >> 1; } else if (ch_data->bs_frame_class & 1) { // FIXVAR or VARVAR @@ -918,18 +918,14 @@ static void read_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, skip_bits_long(gb, *num_bits_left); // bs_fill_bits *num_bits_left = 0; } else { -#if 1 *num_bits_left -= ff_ps_read_data(ac->avctx, gb, &sbr->ps, *num_bits_left); ac->avctx->profile = FF_PROFILE_AAC_HE_V2; -#else - avpriv_report_missing_feature(ac->avctx, "Parametric Stereo"); - skip_bits_long(gb, *num_bits_left); // bs_fill_bits - *num_bits_left = 0; -#endif } break; default: - avpriv_request_sample(ac->avctx, "Reserved SBR extensions"); + // some files contain 0-padding + if (bs_extension_id || *num_bits_left > 16 || show_bits(gb, *num_bits_left)) + avpriv_request_sample(ac->avctx, "Reserved SBR extensions"); skip_bits_long(gb, *num_bits_left); // bs_fill_bits *num_bits_left = 0; break; @@ -1101,6 +1097,7 @@ int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, if (bytes_read > cnt) { av_log(ac->avctx, AV_LOG_ERROR, "Expected to read %d SBR bytes actually read %d.\n", cnt, bytes_read); + sbr_turnoff(sbr); } return cnt; } @@ -1587,8 +1584,14 @@ static void sbr_hf_assemble(float Y1[38][64][2], memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0], m_max * sizeof(sbr->q_m[0][0])); } } else if (h_SL) { - memcpy(g_temp[2*ch_data->t_env[0]], g_temp[2*ch_data->t_env_num_env_old], 4*sizeof(g_temp[0])); - memcpy(q_temp[2*ch_data->t_env[0]], q_temp[2*ch_data->t_env_num_env_old], 4*sizeof(q_temp[0])); + for (i = 0; i < 4; i++) { + memcpy(g_temp[i + 2 * ch_data->t_env[0]], + g_temp[i + 2 * ch_data->t_env_num_env_old], + sizeof(g_temp[0])); + memcpy(q_temp[i + 2 * ch_data->t_env[0]], + q_temp[i + 2 * ch_data->t_env_num_env_old], + sizeof(q_temp[0])); + } } for (e = 0; e < ch_data->bs_num_env; e++) { diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c index ee9a735..9f1e8af 100644 --- a/libavcodec/aactab.c +++ b/libavcodec/aactab.c @@ -44,6 +44,10 @@ const uint8_t ff_aac_num_swb_512[] = { 0, 0, 0, 36, 36, 37, 31, 31, 0, 0, 0, 0, 0 }; +const uint8_t ff_aac_num_swb_480[] = { + 0, 0, 0, 35, 35, 37, 30, 30, 0, 0, 0, 0, 0 +}; + const uint8_t ff_aac_num_swb_128[] = { 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15 }; @@ -1126,6 +1130,14 @@ static const uint16_t swb_offset_512_48[] = { 364, 396, 428, 460, 512 }; +static const uint16_t swb_offset_480_48[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, + 156, 172, 188, 212, 240, 272, 304, 336, + 368, 400, 432, 480 +}; + static const uint16_t swb_offset_128_48[] = { 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128 @@ -1149,6 +1161,14 @@ static const uint16_t swb_offset_512_32[] = { 352, 384, 416, 448, 480, 512 }; +static const uint16_t swb_offset_480_32[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 64, 72, 80, 88, 96, 104, 112, 124, + 136, 148, 164, 180, 200, 224, 256, 288, + 320, 352, 384, 416, 448, 480 + }; + static const uint16_t swb_offset_1024_24[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76, @@ -1165,6 +1185,13 @@ static const uint16_t swb_offset_512_24[] = { 288, 320, 352, 384, 416, 448, 480, 512, }; +static const uint16_t swb_offset_480_24[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 52, 60, 68, 80, + 92, 104, 120, 140, 164, 192, 224, 256, + 288, 320, 352, 384, 416, 448, 480 +}; + static const uint16_t swb_offset_128_24[] = { 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128 @@ -1214,6 +1241,14 @@ const uint16_t * const ff_swb_offset_512[] = { NULL }; +const uint16_t * const ff_swb_offset_480[] = { + NULL, NULL, NULL, + swb_offset_480_48, swb_offset_480_48, swb_offset_480_32, + swb_offset_480_24, swb_offset_480_24, NULL, + NULL, NULL, NULL, + NULL +}; + const uint16_t * const ff_swb_offset_128[] = { /* The last entry on the following row is swb_offset_128_64 but is a duplicate of swb_offset_128_96. */ @@ -1240,12 +1275,16 @@ const uint8_t ff_tns_max_bands_512[] = { 0, 0, 0, 31, 32, 37, 31, 31, 0, 0, 0, 0, 0 }; +const uint8_t ff_tns_max_bands_480[] = { + 0, 0, 0, 31, 32, 37, 30, 30, 0, 0, 0, 0, 0 +}; + const uint8_t ff_tns_max_bands_128[] = { 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; // @} -const DECLARE_ALIGNED(32, float, ff_aac_eld_window)[1920] = { +const DECLARE_ALIGNED(32, float, ff_aac_eld_window_512)[1920] = { 0.00338834, 0.00567745, 0.00847677, 0.01172641, 0.01532555, 0.01917664, 0.02318809, 0.02729259, 0.03144503, 0.03560261, 0.03972499, 0.04379783, @@ -1727,3 +1766,456 @@ const DECLARE_ALIGNED(32, float, ff_aac_eld_window)[1920] = { -0.00116552, -0.00115223, -0.00113877, -0.00112517, -0.00111144, -0.00109764, -0.00108377, -0.00106989, }; + +const DECLARE_ALIGNED(32, float, ff_aac_eld_window_480)[1800] = { + 0.00101191, 0.00440397, 0.00718669, 0.01072130, + 0.01459757, 0.01875954, 0.02308987, 0.02751541, + 0.03198130, 0.03643738, 0.04085290, 0.04522835, + 0.04957620, 0.05390454, 0.05821503, 0.06251214, + 0.06680463, 0.07109582, 0.07538014, 0.07965207, + 0.08390857, 0.08815177, 0.09238785, 0.09662163, + 0.10085860, 0.10510892, 0.10938110, 0.11367819, + 0.11800355, 0.12236410, 0.12676834, 0.13122384, + 0.13573476, 0.14030106, 0.14492340, 0.14960315, + 0.15433828, 0.15912396, 0.16395663, 0.16883310, + 0.17374837, 0.17869679, 0.18367394, 0.18867661, + 0.19370368, 0.19875413, 0.20382641, 0.20892055, + 0.21403775, 0.21917761, 0.22433899, 0.22952250, + 0.23472991, 0.23996189, 0.24521859, 0.25049930, + 0.25580312, 0.26112942, 0.26647748, 0.27184703, + 0.27723785, 0.28264967, 0.28808086, 0.29352832, + 0.29898979, 0.30446379, 0.30994292, 0.31541664, + 0.32087942, 0.32632772, 0.33176291, 0.33718641, + 0.34259612, 0.34799346, 0.35338857, 0.35878843, + 0.36419504, 0.36960630, 0.37501567, 0.38042067, + 0.38582069, 0.39121276, 0.39659312, 0.40195993, + 0.40731155, 0.41264382, 0.41795277, 0.42323670, + 0.42849480, 0.43372753, 0.43893452, 0.44411398, + 0.44927117, 0.45441882, 0.45956191, 0.46470167, + 0.46983016, 0.47493636, 0.48001827, 0.48507480, + 0.49010240, 0.49509781, 0.50005986, 0.50499037, + 0.50989790, 0.51478708, 0.51965805, 0.52450975, + 0.52933955, 0.53414668, 0.53893113, 0.54369178, + 0.54842731, 0.55313757, 0.55782259, 0.56248253, + 0.56711762, 0.57172819, 0.57631468, 0.58087761, + 0.58719976, 0.59173064, 0.59623644, 0.60071719, + 0.60517294, 0.60960372, 0.61400958, 0.61839056, + 0.62274670, 0.62707805, 0.63138475, 0.63566700, + 0.63992500, 0.64415895, 0.64836893, 0.65255499, + 0.65671715, 0.66085548, 0.66497005, 0.66906094, + 0.67312824, 0.67717199, 0.68119219, 0.68518882, + 0.68916187, 0.69311129, 0.69703698, 0.70093884, + 0.70481679, 0.70867071, 0.71250047, 0.71630596, + 0.72008705, 0.72384360, 0.72757549, 0.73128256, + 0.73496463, 0.73862141, 0.74225263, 0.74585799, + 0.74943730, 0.75299039, 0.75651711, 0.76001729, + 0.76349062, 0.76693670, 0.77035516, 0.77374564, + 0.77710790, 0.78044169, 0.78374678, 0.78702291, + 0.79026979, 0.79348715, 0.79667471, 0.79983215, + 0.80295914, 0.80605536, 0.80912047, 0.81215417, + 0.81515616, 0.81812616, 0.82106389, 0.82396915, + 0.82684176, 0.82968154, 0.83248830, 0.83526186, + 0.83800204, 0.84070866, 0.84338156, 0.84602058, + 0.84862556, 0.85119636, 0.85373292, 0.85623523, + 0.85870326, 0.86113701, 0.86353649, 0.86590173, + 0.86823275, 0.87052968, 0.87279275, 0.87502220, + 0.87721829, 0.87938130, 0.88151157, 0.88360940, + 0.88567517, 0.88770954, 0.88971328, 0.89168716, + 0.89363199, 0.89554856, 0.89743771, 0.89930025, + 0.90113740, 0.90295086, 0.90474240, 0.90651380, + 0.90826684, 0.91000335, 0.91172515, 0.91343416, + 0.91513276, 0.91682357, 0.91850924, 0.92019170, + 0.92187129, 0.92354778, 0.92522116, 0.92688597, + 0.92852960, 0.93013861, 0.93169897, 0.93319114, + 0.93458502, 0.93587626, 0.93694276, 0.93825562, + 0.93882222, 0.93910780, 0.93944183, 0.93981497, + 0.94021434, 0.94062629, 0.94103714, 0.94144084, + 0.94184042, 0.94223966, 0.94264206, 0.94304859, + 0.94345831, 0.94387033, 0.94428390, 0.94469895, + 0.94511572, 0.94553441, 0.94595520, 0.94637816, + 0.94680335, 0.94723080, 0.94766054, 0.94809253, + 0.94852674, 0.94896314, 0.94940178, 0.94984276, + 0.95028618, 0.95073213, 0.95118056, 0.95163139, + 0.95208451, 0.95253992, 0.95299770, 0.95345799, + 0.95392092, 0.95438653, 0.95485472, 0.95532539, + 0.95579847, 0.95627397, 0.95675201, 0.95723273, + 0.95771618, 0.95820232, 0.95869103, 0.95918218, + 0.95967573, 0.96017172, 0.96067026, 0.96117144, + 0.96167526, 0.96218157, 0.96269026, 0.96320119, + 0.96371437, 0.96422988, 0.96474782, 0.96526824, + 0.96579106, 0.96631614, 0.96684334, 0.96737257, + 0.96790390, 0.96843740, 0.96897315, 0.96951112, + 0.97005119, 0.97059318, 0.97113697, 0.97168253, + 0.97222994, 0.97277928, 0.97333058, 0.97388375, + 0.97443863, 0.97499505, 0.97555292, 0.97611230, + 0.97667326, 0.97723589, 0.97780016, 0.97836591, + 0.97893300, 0.97950127, 0.98007071, 0.98064139, + 0.98121342, 0.98178684, 0.98236156, 0.98293743, + 0.98351428, 0.98409205, 0.98467078, 0.98525056, + 0.98583146, 0.98641348, 0.98699650, 0.98758037, + 0.98816497, 0.98875030, 0.98933647, 0.98992356, + 0.99051163, 0.99110062, 0.99169038, 0.99228079, + 0.99287177, 0.99346341, 0.99405581, 0.99464907, + 0.99524320, 0.99583812, 0.99643375, 0.99702997, + 0.99762671, 0.99822386, 0.99882134, 0.99941903, + 1.00058131, 1.00118006, 1.00177930, 1.00237893, + 1.00297887, 1.00357902, 1.00417927, 1.00477954, + 1.00537972, 1.00597973, 1.00657959, 1.00717940, + 1.00777926, 1.00837925, 1.00897929, 1.00957926, + 1.01017901, 1.01077847, 1.01137769, 1.01197678, + 1.01257582, 1.01317482, 1.01377365, 1.01437217, + 1.01497025, 1.01556786, 1.01616510, 1.01676205, + 1.01735876, 1.01795514, 1.01855103, 1.01914627, + 1.01974076, 1.02033455, 1.02092772, 1.02152037, + 1.02211247, 1.02270387, 1.02329439, 1.02388387, + 1.02447229, 1.02505972, 1.02564624, 1.02623190, + 1.02681660, 1.02740017, 1.02798242, 1.02856326, + 1.02914272, 1.02972087, 1.03029778, 1.03087344, + 1.03144768, 1.03202035, 1.03259127, 1.03316042, + 1.03372788, 1.03429373, 1.03485801, 1.03542064, + 1.03598146, 1.03654030, 1.03709708, 1.03765185, + 1.03820470, 1.03875571, 1.03930488, 1.03985206, + 1.04039712, 1.04093989, 1.04148037, 1.04201865, + 1.04255481, 1.04308893, 1.04362093, 1.04415068, + 1.04467803, 1.04520292, 1.04572542, 1.04624566, + 1.04676376, 1.04727974, 1.04779350, 1.04830493, + 1.04881391, 1.04932048, 1.04982477, 1.05032693, + 1.05082705, 1.05132510, 1.05182098, 1.05231457, + 1.05280584, 1.05329485, 1.05378171, 1.05426654, + 1.05474937, 1.05523018, 1.05570892, 1.05618554, + 1.05666005, 1.05713251, 1.05760297, 1.05807149, + 1.05853828, 1.05900355, 1.05946756, 1.05993024, + 1.06039075, 1.06084806, 1.06130111, 1.06175099, + 1.06220164, 1.06265732, 1.06312146, 1.06358726, + 1.06403924, 1.06446186, 1.06484048, 1.06516440, + 1.06527864, 1.06498077, 1.06470196, 1.06425743, + 1.06372091, 1.06311464, 1.06246622, 1.06179277, + 1.06110808, 1.06042455, 1.05974495, 1.05906206, + 1.05836706, 1.05765243, 1.05691470, 1.05615178, + 1.05536069, 1.05454152, 1.05370030, 1.05284445, + 1.05198094, 1.05111433, 1.05024634, 1.04937859, + 1.04851245, 1.04764614, 1.04677586, 1.04589855, + 1.04501046, 1.04410500, 1.04317417, 1.04221010, + 1.04120649, 1.04016012, 1.03906851, 1.03792894, + 1.03674090, 1.03550649, 1.03422800, 1.03290769, + 1.03154944, 1.03015834, 1.02873938, 1.02729712, + 1.02583470, 1.02435463, 1.02285952, 1.02135114, + 1.01982974, 1.01829520, 1.01674752, 1.01518534, + 1.01360559, 1.01200510, 1.01038076, 1.00872996, + 1.00705045, 1.00533999, 1.00359618, 1.00181613, + 0.99999673, 0.99813477, 0.99622793, 0.99427571, + 0.99227814, 0.99023501, 0.98815128, 0.98603857, + 0.98390898, 0.98177413, 0.97964151, 0.97751528, + 0.97539999, 0.97329751, 0.97119933, 0.96909179, + 0.96696152, 0.96479824, 0.96259840, 0.96036028, + 0.95808180, 0.95576295, 0.95340622, 0.95101436, + 0.94859030, 0.94614009, 0.94367232, 0.94119555, + 0.93871796, 0.93624630, 0.93378636, 0.93134465, + 0.92892076, 0.92649974, 0.92406255, 0.92159041, + 0.91907411, 0.91651711, 0.91392425, 0.91130056, + 0.90865471, 0.90599838, 0.90334350, 0.90069934, + 0.89806435, 0.89543132, 0.89279335, 0.89014496, + 0.88748403, 0.88480945, 0.88211997, 0.87941558, + 0.87669794, 0.87396891, 0.87123030, 0.86848394, + 0.86573164, 0.86297523, 0.86021649, 0.85745725, + 0.85474342, 0.85193656, 0.84911455, 0.84627969, + 0.84343424, 0.84058046, 0.83772057, 0.83485680, + 0.83199134, 0.82912621, 0.82626143, 0.82339529, + 0.82052619, 0.81765147, 0.81476433, 0.81185593, + 0.80891701, 0.80594452, 0.80294885, 0.79994431, + 0.79694485, 0.79396166, 0.79100220, 0.78807349, + 0.78518123, 0.78231422, 0.77944709, 0.77655407, + 0.77361369, 0.77062281, 0.76758806, 0.76451506, + 0.76141145, 0.75828860, 0.75515892, 0.75203479, + 0.74892561, 0.74583682, 0.74277342, 0.73974008, + 0.73673754, 0.73376310, 0.73081444, 0.72788616, + 0.72496070, 0.72201426, 0.71902283, 0.71596990, + 0.71285541, 0.70968427, 0.70646064, 0.70319589, + 0.69991077, 0.69662714, 0.69336592, 0.69013742, + 0.68694302, 0.68378420, 0.68066143, 0.67757157, + 0.67450951, 0.67147030, 0.66844879, 0.66543949, + 0.66243677, 0.65943505, 0.65642754, 0.65340591, + 0.65036160, 0.64728630, 0.64417440, 0.64102268, + 0.63782771, 0.63458757, 0.63130628, 0.62799109, + 0.62464879, 0.62128816, 0.61792203, 0.61456438, + 0.61122915, 0.60792802, 0.60466971, 0.60146257, + 0.59831460, 0.59522876, 0.59220375, 0.58923859, + 0.58632936, 0.58346064, 0.58061078, 0.57775874, + 0.57488246, 0.57195790, 0.56896078, 0.56586637, + 0.56266594, 0.55937186, 0.55599898, 0.55256299, + 0.54909184, 0.54562376, 0.54219742, 0.53884728, + 0.53559047, 0.53243453, 0.52938894, 0.52645052, + 0.52358958, 0.52076862, 0.51795080, 0.51510761, + 0.51222179, 0.50927733, 0.50625944, 0.50317073, + 0.50002767, 0.49685021, 0.49364116, 0.49048690, + 0.48726128, 0.48404889, 0.48090875, 0.47783482, + 0.47481564, 0.47184024, 0.46889391, 0.46595836, + 0.46301611, 0.46005089, 0.45705924, 0.45404822, + 0.45102447, 0.44799543, 0.44497138, 0.44196397, + 0.43898547, 0.43604105, 0.43312057, 0.43020942, + 0.42729337, 0.42436272, 0.42141388, 0.41844400, + 0.41545081, 0.41244014, 0.40942464, 0.40641716, + 0.40342874, 0.40046292, 0.39751923, 0.39459758, + 0.39169692, 0.38881435, 0.38594643, 0.38308980, + 0.38024146, 0.37739896, 0.37455986, 0.37172187, + 0.36888463, 0.36604937, 0.36321735, 0.36038967, + 0.35756668, 0.35474832, 0.35193455, 0.34912542, + 0.34632129, 0.34352258, 0.34072974, 0.33794323, + 0.33516354, 0.33239114, 0.32962648, 0.32686967, + 0.32412042, 0.32137919, 0.31864044, 0.31588373, + 0.31309909, 0.31028631, 0.30745528, 0.30462678, + 0.30180656, 0.29899424, 0.29619082, 0.29339717, + 0.29061333, 0.28783935, 0.28507563, 0.28232266, + 0.27958067, 0.27684984, 0.27413017, 0.27142157, + 0.26872396, 0.26603737, 0.26336211, 0.26069855, + 0.25804700, 0.25540830, 0.25278329, 0.25017211, + 0.24757451, 0.24498713, 0.24240740, 0.23983550, + 0.23727200, 0.23471866, 0.23217624, 0.22964458, + 0.22712346, 0.22461258, 0.22211202, 0.21962197, + 0.21714290, 0.21467522, 0.21221877, 0.20977323, + 0.20733693, 0.20490860, 0.20248823, 0.20007615, + 0.19767358, 0.19528091, 0.19289781, 0.19052347, + 0.18815661, 0.18579693, 0.18344441, 0.18110010, + 0.17876595, 0.17644344, 0.17413400, 0.17183905, + 0.16956003, 0.16729836, 0.16505547, 0.16283278, + 0.15990780, 0.15776021, 0.15563325, 0.15352557, + 0.15143584, 0.14936270, 0.14730481, 0.14526081, + 0.14322937, 0.14120918, 0.13919977, 0.13720138, + 0.13521422, 0.13323852, 0.13127445, 0.12932216, + 0.12738181, 0.12545358, 0.12353773, 0.12163457, + 0.11974436, 0.11786730, 0.11600347, 0.11415293, + 0.11231573, 0.11049201, 0.10868196, 0.10688578, + 0.10510362, 0.10333551, 0.10158143, 0.09984133, + 0.09811524, 0.09640327, 0.09470556, 0.09302228, + 0.09135347, 0.08969907, 0.08805903, 0.08643326, + 0.08482183, 0.08322486, 0.08164249, 0.08007481, + 0.07852179, 0.07698335, 0.07545938, 0.07394984, + 0.07245482, 0.07097444, 0.06950883, 0.06805800, + 0.06662187, 0.06520031, 0.06379324, 0.06240065, + 0.06102266, 0.05965936, 0.05831084, 0.05697701, + 0.05565775, 0.05435290, 0.05306239, 0.05178628, + 0.05052464, 0.04927758, 0.04804510, 0.04682709, + 0.04562344, 0.04443405, 0.04325893, 0.04209822, + 0.04095208, 0.03982059, 0.03870371, 0.03760131, + 0.03651325, 0.03543944, 0.03437987, 0.03333454, + 0.03230348, 0.03128653, 0.03028332, 0.02929346, + 0.02831658, 0.02735252, 0.02640127, 0.02546283, + 0.02453725, 0.02362471, 0.02272547, 0.02183980, + 0.02096810, 0.02011108, 0.01926957, 0.01844439, + 0.01763565, 0.01684248, 0.01606394, 0.01529909, + 0.01454726, 0.01380802, 0.01308092, 0.01236569, + 0.01166273, 0.01097281, 0.01029671, 0.00963479, + 0.00898646, 0.00835089, 0.00772725, 0.00711521, + 0.00651513, 0.00592741, 0.00535249, 0.00479089, + 0.00424328, 0.00371041, 0.00319271, 0.00268947, + 0.00219928, 0.00172084, 0.00125271, 0.00079311, + 0.00034023, -0.00010786, -0.00055144, -0.00098865, + -0.00141741, -0.00183557, -0.00224010, -0.00262725, + -0.00299314, -0.00333475, -0.00365250, -0.00394867, + -0.00422533, -0.00448528, -0.00473278, -0.00497252, + -0.00520916, -0.00544584, -0.00568360, -0.00592326, + -0.00616547, -0.00640861, -0.00664914, -0.00688354, + -0.00710845, -0.00732136, -0.00752022, -0.00770289, + -0.00786789, -0.00801521, -0.00814526, -0.00825839, + -0.00835563, -0.00843882, -0.00850996, -0.00857097, + -0.00862360, -0.00866943, -0.00871004, -0.00874688, + -0.00878091, -0.00881277, -0.00884320, -0.00887248, + -0.00890002, -0.00892494, -0.00894641, -0.00896355, + -0.00897541, -0.00898104, -0.00897948, -0.00896990, + -0.00895149, -0.00892346, -0.00888519, -0.00883670, + -0.00877839, -0.00871058, -0.00863388, -0.00854936, + -0.00845826, -0.00836179, -0.00826124, -0.00815807, + -0.00805372, -0.00794953, -0.00784572, -0.00774156, + -0.00763634, -0.00752929, -0.00741941, -0.00730556, + -0.00718664, -0.00706184, -0.00693107, -0.00679443, + -0.00665200, -0.00650428, -0.00635230, -0.00619718, + -0.00603995, -0.00588133, -0.00572169, -0.00556143, + -0.00540085, -0.00523988, -0.00507828, -0.00491582, + -0.00475220, -0.00458693, -0.00441953, -0.00424950, + -0.00407681, -0.00390204, -0.00372581, -0.00354874, + -0.00337115, -0.00319318, -0.00301494, -0.00283652, + -0.00265797, -0.00247934, -0.00230066, -0.00212197, + -0.00194331, -0.00176471, -0.00158620, -0.00140787, + -0.00122989, -0.00105244, -0.00087567, -0.00069976, + -0.00052487, -0.00035115, -0.00017875, -0.00000782, + 0.00000779, 0.00017701, 0.00034552, 0.00051313, + 0.00067966, 0.00084492, 0.00100873, 0.00117093, + 0.00133133, 0.00148978, 0.00164611, 0.00180023, + 0.00195211, 0.00210172, 0.00224898, 0.00239383, + 0.00253618, 0.00267593, 0.00281306, 0.00294756, + 0.00307942, 0.00320864, 0.00333502, 0.00345816, + 0.00357762, 0.00369297, 0.00380414, 0.00391140, + 0.00401499, 0.00411524, 0.00421242, 0.00430678, + 0.00439859, 0.00448799, 0.00457487, 0.00465908, + 0.00474045, 0.00481857, 0.00489277, 0.00496235, + 0.00502666, 0.00508546, 0.00513877, 0.00518662, + 0.00522904, 0.00526648, 0.00529956, 0.00532895, + 0.00535532, 0.00537929, 0.00540141, 0.00542228, + 0.00544196, 0.00545981, 0.00547515, 0.00548726, + 0.00549542, 0.00549899, 0.00549732, 0.00548986, + 0.00547633, 0.00545664, 0.00543067, 0.00539849, + 0.00536061, 0.00531757, 0.00526993, 0.00521822, + 0.00516300, 0.00510485, 0.00504432, 0.00498194, + 0.00491822, 0.00485364, 0.00478862, 0.00472309, + 0.00465675, 0.00458939, 0.00452067, 0.00445003, + 0.00437688, 0.00430063, 0.00422062, 0.00413609, + 0.00404632, 0.00395060, 0.00384863, 0.00374044, + 0.00362600, 0.00350540, 0.00337934, 0.00324885, + 0.00311486, 0.00297849, 0.00284122, 0.00270458, + 0.00257013, 0.00243867, 0.00231005, 0.00218399, + 0.00206023, 0.00193766, 0.00181460, 0.00168938, + 0.00156050, 0.00142701, 0.00128830, 0.00114365, + 0.00099297, 0.00083752, 0.00067884, 0.00051845, + 0.00035760, 0.00019720, 0.00003813, -0.00011885, + -0.00027375, -0.00042718, -0.00057975, -0.00073204, + -0.00088453, -0.00103767, -0.00119192, -0.00134747, + -0.00150411, -0.00166151, -0.00181932, -0.00197723, + -0.00213493, -0.00229210, -0.00244849, -0.00260415, + -0.00275928, -0.00291410, -0.00306879, -0.00322332, + -0.00337759, -0.00353145, -0.00368470, -0.00383722, + -0.00398892, -0.00413972, -0.00428967, -0.00443889, + -0.00458749, -0.00473571, -0.00488366, -0.00503137, + -0.00517887, -0.00532610, -0.00547302, -0.00561965, + -0.00576598, -0.00591199, -0.00605766, -0.00620300, + -0.00634801, -0.00649273, -0.00663727, -0.00678170, + -0.00692617, -0.00707084, -0.00721583, -0.00736129, + -0.00750735, -0.00765415, -0.00780184, -0.00795059, + -0.00810058, -0.00825195, -0.00840487, -0.00855950, + -0.00871607, -0.00887480, -0.00903596, -0.00919978, + -0.00936650, -0.00953635, -0.00970931, -0.00988421, + -0.01005916, -0.01023208, -0.01040130, -0.01056627, + -0.01072678, -0.01088259, -0.01103348, -0.01117933, + -0.01132004, -0.01145552, -0.01158573, -0.01171065, + -0.01183025, -0.01194454, -0.01205352, -0.01215722, + -0.01225572, -0.01234911, -0.01243749, -0.01252102, + -0.01259985, -0.01267419, -0.01274437, -0.01281078, + -0.01287379, -0.01293350, -0.01298972, -0.01304224, + -0.01309086, -0.01313556, -0.01317644, -0.01321357, + -0.01324707, -0.01327697, -0.01330334, -0.01332622, + -0.01334570, -0.01336194, -0.01337510, -0.01338538, + -0.01339276, -0.01339708, -0.01339816, -0.01339584, + -0.01339014, -0.01338116, -0.01336903, -0.01335382, + -0.01333545, -0.01331381, -0.01328876, -0.01326033, + -0.01322880, -0.01319457, -0.01315806, -0.01311968, + -0.01307987, -0.01303906, -0.01299769, -0.01295623, + -0.01308207, -0.01304153, -0.01299802, -0.01295155, + -0.01290215, -0.01284980, -0.01279450, -0.01273625, + -0.01267501, -0.01261077, -0.01254347, -0.01247306, + -0.01239950, -0.01232277, -0.01224304, -0.01216055, + -0.01207554, -0.01198813, -0.01189829, -0.01180590, + -0.01171090, -0.01161335, -0.01151352, -0.01141167, + -0.01130807, -0.01120289, -0.01109626, -0.01098830, + -0.01087916, -0.01076898, -0.01065793, -0.01054618, + -0.01043380, -0.01032068, -0.01020670, -0.01009171, + -0.00997585, -0.00985959, -0.00974338, -0.00962765, + -0.00951273, -0.00939888, -0.00928634, -0.00917534, + -0.00906604, -0.00895860, -0.00885313, -0.00874977, + -0.00864862, -0.00854979, -0.00845337, -0.00835939, + -0.00826785, -0.00817872, -0.00809195, -0.00800745, + -0.00792506, -0.00784469, -0.00776588, -0.00768695, + -0.00760568, -0.00752004, -0.00742875, -0.00733186, + -0.00722976, -0.00712279, -0.00701130, -0.00689559, + -0.00677595, -0.00665269, -0.00652610, -0.00639649, + -0.00626417, -0.00612943, -0.00599252, -0.00585368, + -0.00571315, -0.00557115, -0.00542792, -0.00528367, + -0.00513864, -0.00499301, -0.00484693, -0.00470054, + -0.00455395, -0.00440733, -0.00426086, -0.00411471, + -0.00396904, -0.00382404, -0.00367991, -0.00353684, + -0.00339502, -0.00325472, -0.00311618, -0.00297967, + -0.00284531, -0.00271307, -0.00258290, -0.00245475, + -0.00232860, -0.00220447, -0.00208236, -0.00196233, + -0.00184450, -0.00172906, -0.00161620, -0.00150603, + -0.00139852, -0.00129358, -0.00119112, -0.00109115, + -0.00099375, -0.00089902, -0.00080705, -0.00071796, + -0.00063185, -0.00054886, -0.00046904, -0.00039231, + -0.00031845, -0.00024728, -0.00017860, -0.00011216, + -0.00004771, 0.00001500, 0.00007600, 0.00013501, + 0.00019176, 0.00024595, 0.00029720, 0.00034504, + 0.00038902, 0.00042881, 0.00046456, 0.00049662, + 0.00052534, 0.00055114, 0.00057459, 0.00059629, + 0.00061684, 0.00063660, 0.00065568, 0.00067417, + 0.00069213, 0.00070935, 0.00072545, 0.00074005, + 0.00075283, 0.00076356, 0.00077209, 0.00077828, + 0.00078205, 0.00078350, 0.00078275, 0.00077992, + 0.00077520, 0.00076884, 0.00076108, 0.00075218, + 0.00074232, 0.00073170, 0.00072048, 0.00070881, + 0.00069680, 0.00068450, 0.00067201, 0.00065934, + 0.00064647, 0.00063335, 0.00061994, 0.00060621, + 0.00059211, 0.00057763, 0.00056274, 0.00054743, + 0.00053169, 0.00051553, 0.00049897, 0.00048206, + 0.00046487, 0.00044748, 0.00042996, 0.00041241, + 0.00039492, 0.00037759, 0.00036049, 0.00034371, + 0.00032732, 0.00031137, 0.00029587, 0.00028079, + 0.00026612, 0.00025183, 0.00023789, 0.00022428, + 0.00021097, 0.00019797, 0.00018530, 0.00017297, + 0.00016100, 0.00014942, 0.00013827, 0.00012757, + 0.00011736, 0.00010764, 0.00009841, 0.00008969, + 0.00008145, 0.00007369, 0.00006641, 0.00005958, + 0.00005320, 0.00004725, 0.00004171, 0.00003659, + 0.00003186, 0.00002752, 0.00002357, 0.00001999, + 0.00001679, 0.00001392, 0.00001140, 0.00000918, + 0.00000726, 0.00000562, 0.00000424, 0.00000309, + 0.00000217, 0.00000143, 0.00000088, 0.00000048, + 0.00000020, 0.00000004, -0.00000004, -0.00000006, + -0.00000004, -0.00000000, 0.00000002, 0.00000000, + 0.00000000, 0.00000002, -0.00000000, -0.00000004, + -0.00000005, -0.00000004, 0.00000004, 0.00000019, + 0.00000045, 0.00000083, 0.00000134, 0.00000201, + 0.00000285, 0.00000387, 0.00000510, 0.00000654, + 0.00000821, 0.00001011, 0.00001227, 0.00001468, + 0.00001735, 0.00002030, 0.00002352, 0.00002702, + 0.00003080, 0.00003486, 0.00003918, 0.00004379, + 0.00004866, 0.00005382, 0.00005924, 0.00006495, + 0.00007093, 0.00007719, 0.00008373, 0.00009053, + 0.00009758, 0.00010488, 0.00011240, 0.00012010, + 0.00012796, 0.00013596, 0.00014406, 0.00015226, + 0.00016053, 0.00016886, 0.00017725, 0.00018571, + 0.00019424, 0.00020286, 0.00021156, 0.00022037, + 0.00022928, 0.00023825, 0.00024724, 0.00025621, + 0.00026509, 0.00027385, 0.00028241, 0.00029072, + 0.00029874, 0.00030643, 0.00031374, 0.00032065, + 0.00032715, 0.00033325, 0.00033895, 0.00034425, + 0.00034917, 0.00035374, 0.00035796, 0.00036187, + 0.00036549, 0.00036883, 0.00037194, 0.00037479, + 0.00037736, 0.00037963, 0.00038154, 0.00038306, + 0.00038411, 0.00038462, 0.00038453, 0.00038373, + 0.00038213, 0.00037965, 0.00037621, 0.00037179, + 0.00036636, 0.00035989, 0.00035244, 0.00034407, + 0.00033488, 0.00032497, 0.00031449, 0.00030361, + 0.00029252, 0.00028133, 0.00027003, 0.00025862, + 0.00024706, 0.00023524, 0.00022297, 0.00021004, + 0.00019626, 0.00018150, 0.00016566, 0.00014864, + 0.00013041, 0.00011112, 0.00009096, 0.00007014, + 0.00004884, 0.00002718, 0.00000530, -0.00001667, + -0.00003871, -0.00006090, -0.00008331, -0.00010600, + -0.00012902, -0.00015244, -0.00017631, -0.00020065, + -0.00022541, -0.00025052, -0.00027594, -0.00030159, + -0.00032740, -0.00035332, -0.00037928, -0.00040527, + -0.00043131, -0.00045741, -0.00048357, -0.00050978, + -0.00053599, -0.00056217, -0.00058827, -0.00061423, + -0.00064002, -0.00066562, -0.00069100, -0.00071616, + -0.00074110, -0.00076584, -0.00079036, -0.00081465, + -0.00083869, -0.00086245, -0.00088590, -0.00090901, + -0.00093176, -0.00095413, -0.00097608, -0.00099758, + -0.00101862, -0.00103918, -0.00105924, -0.00107879, + -0.00109783, -0.00111635, -0.00113434, -0.00115181, + -0.00116873, -0.00118510, -0.00120091, -0.00121615, + -0.00123082, -0.00124490, -0.00125838, -0.00127125, + -0.00128350, -0.00129511, -0.00130610, -0.00131643, + -0.00132610, -0.00133509, -0.00134334, -0.00135069, + -0.00135711, -0.00136272, -0.00136768, -0.00137225, + -0.00137649, -0.00138042, -0.00138404, -0.00138737, + -0.00139041, -0.00139317, -0.00139565, -0.00139785, + -0.00139976, -0.00140137, -0.00140267, -0.00140366, + -0.00140432, -0.00140464, -0.00140461, -0.00140423, + -0.00140347, -0.00140235, -0.00140084, -0.00139894, + -0.00139664, -0.00139388, -0.00139065, -0.00138694, + -0.00138278, -0.00137818, -0.00137317, -0.00136772, + -0.00136185, -0.00135556, -0.00134884, -0.00134170, + -0.00133415, -0.00132619, -0.00131784, -0.00130908, + -0.00129991, -0.00129031, -0.00128031, -0.00126990, + -0.00125912, -0.00124797, -0.00123645, -0.00122458, + -0.00121233, -0.00119972, -0.00118676, -0.00117347, + -0.00115988, -0.00114605, -0.00113200, -0.00111778, + -0.00110343, -0.00108898, -0.00107448, -0.00105995, +}; diff --git a/libavcodec/aactab.h b/libavcodec/aactab.h index d19b3fd..fc26db8 100644 --- a/libavcodec/aactab.h +++ b/libavcodec/aactab.h @@ -46,7 +46,8 @@ */ DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_1024)[1024]; DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128]; -const DECLARE_ALIGNED(32, extern float, ff_aac_eld_window)[1920]; +const DECLARE_ALIGNED(32, extern float, ff_aac_eld_window_512)[1920]; +const DECLARE_ALIGNED(32, extern float, ff_aac_eld_window_480)[1800]; // @} /* @name number of scalefactor window bands for long and short transform windows respectively @@ -54,6 +55,7 @@ const DECLARE_ALIGNED(32, extern float, ff_aac_eld_window)[1920]; */ extern const uint8_t ff_aac_num_swb_1024[]; extern const uint8_t ff_aac_num_swb_512 []; +extern const uint8_t ff_aac_num_swb_480 []; extern const uint8_t ff_aac_num_swb_128 []; // @} @@ -72,10 +74,12 @@ extern const uint16_t *ff_aac_codebook_vector_idx[]; extern const uint16_t * const ff_swb_offset_1024[13]; extern const uint16_t * const ff_swb_offset_512 [13]; +extern const uint16_t * const ff_swb_offset_480 [13]; extern const uint16_t * const ff_swb_offset_128 [13]; extern const uint8_t ff_tns_max_bands_1024[13]; extern const uint8_t ff_tns_max_bands_512 [13]; +extern const uint8_t ff_tns_max_bands_480 [13]; extern const uint8_t ff_tns_max_bands_128 [13]; #endif /* AVCODEC_AACTAB_H */ diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index 964428e..764bedc 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -1,28 +1,45 @@ +# subsystems OBJS-$(CONFIG_FFT) += aarch64/fft_init_aarch64.o +OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_init.o OBJS-$(CONFIG_H264CHROMA) += aarch64/h264chroma_init_aarch64.o OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o +OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o +OBJS-$(CONFIG_IMDCT15) += aarch64/imdct15_init.o +OBJS-$(CONFIG_MDCT) += aarch64/mdct_init.o OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp_init.o -OBJS-$(CONFIG_OPUS_DECODER) += aarch64/opus_imdct_init.o +# decoders/encoders +OBJS-$(CONFIG_DCA_DECODER) += aarch64/dcadsp_init.o OBJS-$(CONFIG_RV40_DECODER) += aarch64/rv40dsp_init_aarch64.o OBJS-$(CONFIG_VC1_DECODER) += aarch64/vc1dsp_init_aarch64.o OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o +# ARMv8 optimizations + +# subsystems ARMV8-OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp.o +# NEON optimizations + +# subsystems NEON-OBJS-$(CONFIG_FFT) += aarch64/fft_neon.o +NEON-OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_neon.o NEON-OBJS-$(CONFIG_H264CHROMA) += aarch64/h264cmc_neon.o NEON-OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_neon.o \ aarch64/h264idct_neon.o +NEON-OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_neon.o NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \ aarch64/hpeldsp_neon.o NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o -NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o +NEON-OBJS-$(CONFIG_IMDCT15) += aarch64/imdct15_neon.o NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o +NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o -NEON-OBJS-$(CONFIG_OPUS_DECODER) += aarch64/opus_imdct_neon.o +# decoders/encoders +NEON-OBJS-$(CONFIG_DCA_DECODER) += aarch64/dcadsp_neon.o \ + aarch64/synth_filter_neon.o NEON-OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_neon.o diff --git a/libavcodec/aarch64/asm-offsets.h b/libavcodec/aarch64/asm-offsets.h index 45b5c40..60e32dd 100644 --- a/libavcodec/aarch64/asm-offsets.h +++ b/libavcodec/aarch64/asm-offsets.h @@ -27,4 +27,7 @@ #define CELT_TMP 0x10 #define CELT_TWIDDLE (CELT_TMP + 0x8) // loaded as pair +/* FFTContext */ +#define IMDCT_HALF 0x48 + #endif /* AVCODEC_AARCH64_ASM_OFFSETS_H */ diff --git a/libavcodec/aarch64/dcadsp_init.c b/libavcodec/aarch64/dcadsp_init.c new file mode 100644 index 0000000..d3430d0 --- /dev/null +++ b/libavcodec/aarch64/dcadsp_init.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/aarch64/cpu.h" +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "libavcodec/dcadsp.h" +#include "libavcodec/fft.h" + +#include "asm-offsets.h" + +#if HAVE_NEON || HAVE_VFP +AV_CHECK_OFFSET(FFTContext, imdct_half, IMDCT_HALF); +#endif + +void ff_dca_lfe_fir0_neon(float *out, const float *in, const float *coefs); +void ff_dca_lfe_fir1_neon(float *out, const float *in, const float *coefs); + +void ff_synth_filter_float_neon(FFTContext *imdct, + float *synth_buf_ptr, int *synth_buf_offset, + float synth_buf2[32], const float window[512], + float out[32], const float in[32], + float scale); + +av_cold void ff_dcadsp_init_aarch64(DCADSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->lfe_fir[0] = ff_dca_lfe_fir0_neon; + s->lfe_fir[1] = ff_dca_lfe_fir1_neon; + } +} + +av_cold void ff_synth_filter_init_aarch64(SynthFilterContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + s->synth_filter_float = ff_synth_filter_float_neon; +} diff --git a/libavcodec/aarch64/dcadsp_neon.S b/libavcodec/aarch64/dcadsp_neon.S new file mode 100644 index 0000000..4cd3328 --- /dev/null +++ b/libavcodec/aarch64/dcadsp_neon.S @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +function ff_dca_lfe_fir0_neon, export=1 + mov x3, #32 // decifactor + sub x1, x1, #7*4 + add x4, x0, #2*32*4 - 16 // out2 + mov x7, #-16 + + ld1 {v0.4s,v1.4s}, [x1] + // reverse [-num_coeffs + 1, 0] + ext v3.16b, v0.16b, v0.16b, #8 + ext v2.16b, v1.16b, v1.16b, #8 + rev64 v3.4s, v3.4s + rev64 v2.4s, v2.4s +1: + ld1 {v4.4s,v5.4s}, [x2], #32 + ld1 {v6.4s,v7.4s}, [x2], #32 + subs x3, x3, #4 + fmul v16.4s, v2.4s, v4.4s + fmul v23.4s, v0.4s, v4.4s + fmul v17.4s, v2.4s, v6.4s + fmul v22.4s, v0.4s, v6.4s + + fmla v16.4s, v3.4s, v5.4s + fmla v23.4s, v1.4s, v5.4s + ld1 {v4.4s,v5.4s}, [x2], #32 + fmla v17.4s, v3.4s, v7.4s + fmla v22.4s, v1.4s, v7.4s + ld1 {v6.4s,v7.4s}, [x2], #32 + fmul v18.4s, v2.4s, v4.4s + fmul v21.4s, v0.4s, v4.4s + fmul v19.4s, v2.4s, v6.4s + fmul v20.4s, v0.4s, v6.4s + + fmla v18.4s, v3.4s, v5.4s + fmla v21.4s, v1.4s, v5.4s + fmla v19.4s, v3.4s, v7.4s + fmla v20.4s, v1.4s, v7.4s + + faddp v16.4s, v16.4s, v17.4s + faddp v18.4s, v18.4s, v19.4s + faddp v20.4s, v20.4s, v21.4s + faddp v22.4s, v22.4s, v23.4s + faddp v16.4s, v16.4s, v18.4s + faddp v20.4s, v20.4s, v22.4s + + st1 {v16.4s}, [x0], #16 + st1 {v20.4s}, [x4], x7 + b.gt 1b + + ret +endfunc + +function ff_dca_lfe_fir1_neon, export=1 + mov x3, #64 // decifactor + sub x1, x1, #3*4 + add x4, x0, #2*64*4 - 16 // out2 + mov x7, #-16 + + ld1 {v0.4s}, [x1] + // reverse [-num_coeffs + 1, 0] + ext v1.16b, v0.16b, v0.16b, #8 + rev64 v1.4s, v1.4s + +1: + ld1 {v4.4s,v5.4s}, [x2], #32 + ld1 {v6.4s,v7.4s}, [x2], #32 + subs x3, x3, #4 + fmul v16.4s, v1.4s, v4.4s + fmul v23.4s, v0.4s, v4.4s + fmul v17.4s, v1.4s, v5.4s + fmul v22.4s, v0.4s, v5.4s + fmul v18.4s, v1.4s, v6.4s + fmul v21.4s, v0.4s, v6.4s + fmul v19.4s, v1.4s, v7.4s + fmul v20.4s, v0.4s, v7.4s + faddp v16.4s, v16.4s, v17.4s + faddp v18.4s, v18.4s, v19.4s + faddp v20.4s, v20.4s, v21.4s + faddp v22.4s, v22.4s, v23.4s + faddp v16.4s, v16.4s, v18.4s + faddp v20.4s, v20.4s, v22.4s + st1 {v16.4s}, [x0], #16 + st1 {v20.4s}, [x4], x7 + b.gt 1b + + ret +endfunc diff --git a/libavcodec/aarch64/fft_init_aarch64.c b/libavcodec/aarch64/fft_init_aarch64.c index 589e82d..9cc57d3 100644 --- a/libavcodec/aarch64/fft_init_aarch64.c +++ b/libavcodec/aarch64/fft_init_aarch64.c @@ -18,18 +18,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" - +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" #include "libavutil/aarch64/cpu.h" + #include "libavcodec/fft.h" void ff_fft_permute_neon(FFTContext *s, FFTComplex *z); void ff_fft_calc_neon(FFTContext *s, FFTComplex *z); -void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); - av_cold void ff_fft_init_aarch64(FFTContext *s) { int cpu_flags = av_get_cpu_flags(); @@ -37,11 +34,5 @@ av_cold void ff_fft_init_aarch64(FFTContext *s) if (have_neon(cpu_flags)) { s->fft_permute = ff_fft_permute_neon; s->fft_calc = ff_fft_calc_neon; -#if CONFIG_MDCT - s->imdct_calc = ff_imdct_calc_neon; - s->imdct_half = ff_imdct_half_neon; - s->mdct_calc = ff_mdct_calc_neon; - s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; -#endif } } diff --git a/libavcodec/aarch64/fft_neon.S b/libavcodec/aarch64/fft_neon.S index 5f88bed..e205e23 100644 --- a/libavcodec/aarch64/fft_neon.S +++ b/libavcodec/aarch64/fft_neon.S @@ -415,7 +415,7 @@ function ff_fft_permute_neon, export=1 ret endfunc -const fft_tab_neon +const fft_tab_neon, relocate=1 .quad fft4_neon .quad fft8_neon .quad fft16_neon diff --git a/libavcodec/aarch64/fmtconvert_init.c b/libavcodec/aarch64/fmtconvert_init.c new file mode 100644 index 0000000..0a55a1b --- /dev/null +++ b/libavcodec/aarch64/fmtconvert_init.c @@ -0,0 +1,43 @@ +/* + * ARM optimized Format Conversion Utils + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/fmtconvert.h" + +void ff_int32_to_float_fmul_array8_neon(FmtConvertContext *c, float *dst, + const int32_t *src, const float *mul, + int len); +void ff_int32_to_float_fmul_scalar_neon(float *dst, const int32_t *src, + float mul, int len); + +av_cold void ff_fmt_convert_init_aarch64(FmtConvertContext *c, + AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_neon; + c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_neon; + } +} diff --git a/libavcodec/aarch64/fmtconvert_neon.S b/libavcodec/aarch64/fmtconvert_neon.S new file mode 100644 index 0000000..3b33c87 --- /dev/null +++ b/libavcodec/aarch64/fmtconvert_neon.S @@ -0,0 +1,76 @@ +/* + * ARM NEON optimised Format Conversion Utils + * Copyright (c) 2008 Mans Rullgard + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/aarch64/asm.S" + +function ff_int32_to_float_fmul_scalar_neon, export=1 + ld1 {v1.4s,v2.4s}, [x1], #32 + scvtf v1.4s, v1.4s + scvtf v2.4s, v2.4s +1: + subs w2, w2, #8 + fmul v3.4s, v1.4s, v0.s[0] + fmul v4.4s, v2.4s, v0.s[0] + b.le 2f + ld1 {v1.4s,v2.4s}, [x1], #32 + st1 {v3.4s,v4.4s}, [x0], #32 + scvtf v1.4s, v1.4s + scvtf v2.4s, v2.4s + b 1b +2: + st1 {v3.4s,v4.4s}, [x0] + ret +endfunc + +function ff_int32_to_float_fmul_array8_neon, export=1 + lsr w4, w4, #3 + subs w5, w4, #1 + b.eq 1f +2: + ld1 {v0.4s,v1.4s}, [x2], #32 + ld1 {v2.4s,v3.4s}, [x2], #32 + scvtf v0.4s, v0.4s + scvtf v1.4s, v1.4s + ld1 {v16.2s}, [x3], #8 + scvtf v2.4s, v2.4s + scvtf v3.4s, v3.4s + fmul v4.4s, v0.4s, v16.s[0] + fmul v5.4s, v1.4s, v16.s[0] + fmul v6.4s, v2.4s, v16.s[1] + fmul v7.4s, v3.4s, v16.s[1] + st1 {v4.4s,v5.4s}, [x1], #32 + st1 {v6.4s,v7.4s}, [x1], #32 + subs w5, w5, #2 + b.gt 2b + b.eq 1f + ret +1: + ld1 {v0.4s,v1.4s}, [x2] + ld1 {v16.s}[0], [x3] + scvtf v0.4s, v0.4s + scvtf v1.4s, v1.4s + fmul v4.4s, v0.4s, v16.s[0] + fmul v5.4s, v1.4s, v16.s[0] + st1 {v4.4s,v5.4s}, [x1] + ret +endfunc diff --git a/libavcodec/aarch64/h264idct_neon.S b/libavcodec/aarch64/h264idct_neon.S index 99c2cb5..5395e14 100644 --- a/libavcodec/aarch64/h264idct_neon.S +++ b/libavcodec/aarch64/h264idct_neon.S @@ -33,25 +33,25 @@ function ff_h264_idct_add_neon, export=1 sshr v17.4H, v3.4H, #1 st1 {v30.8H}, [x1], #16 sub v5.4H, v0.4H, v2.4H - add v6.4H, v1.4H, v17.4H - sub v7.4H, v16.4H, v3.4H - add v0.4H, v4.4H, v6.4H - add v1.4H, v5.4H, v7.4H - sub v2.4H, v4.4H, v6.4H - sub v3.4H, v5.4H, v7.4H + sub v6.4H, v16.4H, v3.4H + add v7.4H, v1.4H, v17.4H + add v0.4H, v4.4H, v7.4H + add v1.4H, v5.4H, v6.4H + sub v2.4H, v5.4H, v6.4H + sub v3.4H, v4.4H, v7.4H transpose_4x4H v0, v1, v2, v3, v4, v5, v6, v7 - add v4.4H, v0.4H, v3.4H + add v4.4H, v0.4H, v2.4H ld1 {v18.S}[0], [x0], x2 - sshr v16.4H, v2.4H, #1 + sshr v16.4H, v3.4H, #1 sshr v17.4H, v1.4H, #1 - ld1 {v19.S}[1], [x0], x2 - sub v5.4H, v0.4H, v3.4H ld1 {v18.S}[1], [x0], x2 + sub v5.4H, v0.4H, v2.4H + ld1 {v19.S}[1], [x0], x2 add v6.4H, v16.4H, v1.4H ins v4.D[1], v5.D[0] - sub v7.4H, v2.4H, v17.4H + sub v7.4H, v17.4H, v3.4H ld1 {v19.S}[0], [x0], x2 ins v6.D[1], v7.D[0] sub x0, x0, x2, lsl #2 @@ -68,8 +68,8 @@ function ff_h264_idct_add_neon, export=1 sqxtun v1.8B, v1.8H st1 {v0.S}[0], [x0], x2 - st1 {v1.S}[1], [x0], x2 st1 {v0.S}[1], [x0], x2 + st1 {v1.S}[1], [x0], x2 st1 {v1.S}[0], [x0], x2 sub x1, x1, #32 diff --git a/libavcodec/aarch64/h264pred_init.c b/libavcodec/aarch64/h264pred_init.c new file mode 100644 index 0000000..8f912cb --- /dev/null +++ b/libavcodec/aarch64/h264pred_init.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/h264pred.h" + +void ff_pred16x16_vert_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_hor_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_plane_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_128_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_left_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_top_dc_neon(uint8_t *src, ptrdiff_t stride); + +void ff_pred8x8_vert_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_hor_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_plane_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_128_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_left_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_top_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_l0t_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_0lt_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_l00_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_0l0_dc_neon(uint8_t *src, ptrdiff_t stride); + +static av_cold void h264_pred_init_neon(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc) +{ + const int high_depth = bit_depth > 8; + + if (high_depth) + return; + + if (chroma_format_idc <= 1) { + h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vert_neon; + h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_hor_neon; + if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) + h->pred8x8[PLANE_PRED8x8] = ff_pred8x8_plane_neon; + h->pred8x8[DC_128_PRED8x8 ] = ff_pred8x8_128_dc_neon; + if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && + codec_id != AV_CODEC_ID_VP8) { + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_neon; + h->pred8x8[LEFT_DC_PRED8x8] = ff_pred8x8_left_dc_neon; + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_neon; + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = ff_pred8x8_l0t_dc_neon; + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = ff_pred8x8_0lt_dc_neon; + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = ff_pred8x8_l00_dc_neon; + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = ff_pred8x8_0l0_dc_neon; + } + } + + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_neon; + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vert_neon; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_hor_neon; + h->pred16x16[LEFT_DC_PRED8x8] = ff_pred16x16_left_dc_neon; + h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_neon; + h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_neon; + if (codec_id != AV_CODEC_ID_SVQ3 && codec_id != AV_CODEC_ID_RV40 && + codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_neon; +} + +av_cold void ff_h264_pred_init_aarch64(H264PredContext *h, int codec_id, + int bit_depth, const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + h264_pred_init_neon(h, codec_id, bit_depth, chroma_format_idc); +} diff --git a/libavcodec/aarch64/h264pred_neon.S b/libavcodec/aarch64/h264pred_neon.S new file mode 100644 index 0000000..a38a27f --- /dev/null +++ b/libavcodec/aarch64/h264pred_neon.S @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +.macro ldcol.8 rd, rs, rt, n=8, hi=0 +.if \n >= 8 || \hi == 0 + ld1 {\rd\().b}[0], [\rs], \rt + ld1 {\rd\().b}[1], [\rs], \rt + ld1 {\rd\().b}[2], [\rs], \rt + ld1 {\rd\().b}[3], [\rs], \rt +.endif +.if \n >= 8 || \hi == 1 + ld1 {\rd\().b}[4], [\rs], \rt + ld1 {\rd\().b}[5], [\rs], \rt + ld1 {\rd\().b}[6], [\rs], \rt + ld1 {\rd\().b}[7], [\rs], \rt +.endif +.if \n == 16 + ld1 {\rd\().b}[8], [\rs], \rt + ld1 {\rd\().b}[9], [\rs], \rt + ld1 {\rd\().b}[10], [\rs], \rt + ld1 {\rd\().b}[11], [\rs], \rt + ld1 {\rd\().b}[12], [\rs], \rt + ld1 {\rd\().b}[13], [\rs], \rt + ld1 {\rd\().b}[14], [\rs], \rt + ld1 {\rd\().b}[15], [\rs], \rt +.endif +.endm + +function ff_pred16x16_128_dc_neon, export=1 + movi v0.16b, #128 + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_top_dc_neon, export=1 + sub x2, x0, x1 + ld1 {v0.16b}, [x2] + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_left_dc_neon, export=1 + sub x2, x0, #1 + ldcol.8 v0, x2, x1, 16 + uaddlv h0, v0.16b + rshrn v0.8b, v0.8h, #4 + dup v0.16b, v0.b[0] + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_dc_neon, export=1 + sub x2, x0, x1 + sub x3, x0, #1 + ld1 {v0.16b}, [x2] + ldcol.8 v1, x3, x1, 16 + uaddlv h0, v0.16b + uaddlv h1, v1.16b + add v0.4h, v0.4h, v1.4h + rshrn v0.8b, v0.8h, #5 + dup v0.16b, v0.b[0] +.L_pred16x16_dc_end: + mov w3, #8 +6: st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x0], x1 + subs w3, w3, #1 + b.ne 6b + ret +endfunc + +function ff_pred16x16_hor_neon, export=1 + sub x2, x0, #1 + mov w3, #16 +1: ld1r {v0.16b}, [x2], x1 + st1 {v0.16b}, [x0], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_pred16x16_vert_neon, export=1 + sub x2, x0, x1 + add x1, x1, x1 + ld1 {v0.16b}, [x2], x1 + mov w3, #8 +1: st1 {v0.16b}, [x0], x1 + st1 {v0.16b}, [x2], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_pred16x16_plane_neon, export=1 + sub x3, x0, x1 + movrel x4, p16weight + add x2, x3, #8 + sub x3, x3, #1 + ld1 {v0.8b}, [x3] + ld1 {v2.8b}, [x2], x1 + ldcol.8 v1, x3, x1 + add x3, x3, x1 + ldcol.8 v3, x3, x1 + rev64 v0.8b, v0.8b + rev64 v1.8b, v1.8b + uaddl v7.8h, v2.8b, v3.8b + usubl v2.8h, v2.8b, v0.8b + usubl v3.8h, v3.8b, v1.8b + ld1 {v0.8h}, [x4] + mul v2.8h, v2.8h, v0.8h + mul v3.8h, v3.8h, v0.8h + addp v2.8h, v2.8h, v3.8h + addp v2.8h, v2.8h, v2.8h + addp v2.4h, v2.4h, v2.4h + sshll v3.4s, v2.4h, #2 + saddw v2.4s, v3.4s, v2.4h + rshrn v4.4h, v2.4s, #6 + trn2 v5.4h, v4.4h, v4.4h + add v2.4h, v4.4h, v5.4h + shl v3.4h, v2.4h, #3 + ext v7.16b, v7.16b, v7.16b, #14 + sub v3.4h, v3.4h, v2.4h // 7 * (b + c) + add v7.4h, v7.4h, v0.4h + shl v2.4h, v7.4h, #4 + sub v2.4h, v2.4h, v3.4h + shl v3.4h, v4.4h, #4 + ext v0.16b, v0.16b, v0.16b, #14 + sub v6.4h, v5.4h, v3.4h + mov v0.h[0], wzr + mul v0.8h, v0.8h, v4.h[0] + dup v1.8h, v2.h[0] + dup v2.8h, v4.h[0] + dup v3.8h, v6.h[0] + shl v2.8h, v2.8h, #3 + add v1.8h, v1.8h, v0.8h + add v3.8h, v3.8h, v2.8h + mov w3, #16 +1: + sqshrun v0.8b, v1.8h, #5 + add v1.8h, v1.8h, v2.8h + sqshrun2 v0.16b, v1.8h, #5 + add v1.8h, v1.8h, v3.8h + st1 {v0.16b}, [x0], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +const p16weight, align=4 + .short 1,2,3,4,5,6,7,8 +endconst +const p8weight, align=4 + .short 1,2,3,4,1,2,3,4 +endconst + +function ff_pred8x8_hor_neon, export=1 + sub x2, x0, #1 + mov w3, #8 +1: ld1r {v0.8b}, [x2], x1 + st1 {v0.8b}, [x0], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_pred8x8_vert_neon, export=1 + sub x2, x0, x1 + lsl x1, x1, #1 + ld1 {v0.8b}, [x2], x1 + mov w3, #4 +1: st1 {v0.8b}, [x0], x1 + st1 {v0.8b}, [x2], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_pred8x8_plane_neon, export=1 + sub x3, x0, x1 + movrel x4, p8weight + movrel x5, p16weight + add x2, x3, #4 + sub x3, x3, #1 + ld1 {v0.s}[0], [x3] + ld1 {v2.s}[0], [x2], x1 + ldcol.8 v0, x3, x1, 4, hi=1 + add x3, x3, x1 + ldcol.8 v3, x3, x1, 4 + uaddl v7.8h, v2.8b, v3.8b + rev32 v0.8b, v0.8b + trn1 v2.2s, v2.2s, v3.2s + usubl v2.8h, v2.8b, v0.8b + ld1 {v6.8h}, [x4] + mul v2.8h, v2.8h, v6.8h + ld1 {v0.8h}, [x5] + saddlp v2.4s, v2.8h + addp v2.4s, v2.4s, v2.4s + shl v3.4s, v2.4s, #4 + add v2.4s, v3.4s, v2.4s + rshrn v5.4h, v2.4s, #5 + addp v2.4h, v5.4h, v5.4h + shl v3.4h, v2.4h, #1 + add v3.4h, v3.4h, v2.4h + rev64 v7.4h, v7.4h + add v7.4h, v7.4h, v0.4h + shl v2.4h, v7.4h, #4 + sub v2.4h, v2.4h, v3.4h + ext v0.16b, v0.16b, v0.16b, #14 + mov v0.h[0], wzr + mul v0.8h, v0.8h, v5.h[0] + dup v1.8h, v2.h[0] + dup v2.8h, v5.h[1] + add v1.8h, v1.8h, v0.8h + mov w3, #8 +1: + sqshrun v0.8b, v1.8h, #5 + add v1.8h, v1.8h, v2.8h + st1 {v0.8b}, [x0], x1 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_pred8x8_128_dc_neon, export=1 + movi v0.8b, #128 + movi v1.8b, #128 + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_top_dc_neon, export=1 + sub x2, x0, x1 + ld1 {v0.8b}, [x2] + uaddlp v0.4h, v0.8b + addp v0.4h, v0.4h, v0.4h + zip1 v0.8h, v0.8h, v0.8h + rshrn v2.8b, v0.8h, #2 + zip1 v0.8b, v2.8b, v2.8b + zip1 v1.8b, v2.8b, v2.8b + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_left_dc_neon, export=1 + sub x2, x0, #1 + ldcol.8 v0, x2, x1 + uaddlp v0.4h, v0.8b + addp v0.4h, v0.4h, v0.4h + rshrn v2.8b, v0.8h, #2 + dup v1.8b, v2.b[1] + dup v0.8b, v2.b[0] + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_dc_neon, export=1 + sub x2, x0, x1 + sub x3, x0, #1 + ld1 {v0.8b}, [x2] + ldcol.8 v1, x3, x1 + uaddlp v0.4h, v0.8b + uaddlp v1.4h, v1.8b + trn1 v2.2s, v0.2s, v1.2s + trn2 v3.2s, v0.2s, v1.2s + addp v4.4h, v2.4h, v3.4h + addp v5.4h, v4.4h, v4.4h + rshrn v6.8b, v5.8h, #3 + rshrn v7.8b, v4.8h, #2 + dup v0.8b, v6.b[0] + dup v2.8b, v7.b[2] + dup v1.8b, v7.b[3] + dup v3.8b, v6.b[1] + zip1 v0.2s, v0.2s, v2.2s + zip1 v1.2s, v1.2s, v3.2s +.L_pred8x8_dc_end: + mov w3, #4 + add x2, x0, x1, lsl #2 +6: st1 {v0.8b}, [x0], x1 + st1 {v1.8b}, [x2], x1 + subs w3, w3, #1 + b.ne 6b + ret +endfunc + +function ff_pred8x8_l0t_dc_neon, export=1 + sub x2, x0, x1 + sub x3, x0, #1 + ld1 {v0.8b}, [x2] + ldcol.8 v1, x3, x1, 4 + zip1 v0.4s, v0.4s, v1.4s + uaddlp v0.8h, v0.16b + addp v0.8h, v0.8h, v0.8h + addp v1.4h, v0.4h, v0.4h + rshrn v2.8b, v0.8h, #2 + rshrn v3.8b, v1.8h, #3 + dup v4.8b, v3.b[0] + dup v6.8b, v2.b[2] + dup v5.8b, v2.b[0] + zip1 v0.2s, v4.2s, v6.2s + zip1 v1.2s, v5.2s, v6.2s + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_l00_dc_neon, export=1 + sub x2, x0, #1 + ldcol.8 v0, x2, x1, 4 + uaddlp v0.4h, v0.8b + addp v0.4h, v0.4h, v0.4h + rshrn v0.8b, v0.8h, #2 + movi v1.8b, #128 + dup v0.8b, v0.b[0] + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_0lt_dc_neon, export=1 + add x3, x0, x1, lsl #2 + sub x2, x0, x1 + sub x3, x3, #1 + ld1 {v0.8b}, [x2] + ldcol.8 v1, x3, x1, 4, hi=1 + zip1 v0.4s, v0.4s, v1.4s + uaddlp v0.8h, v0.16b + addp v0.8h, v0.8h, v0.8h + addp v1.4h, v0.4h, v0.4h + rshrn v2.8b, v0.8h, #2 + rshrn v3.8b, v1.8h, #3 + dup v4.8b, v2.b[0] + dup v5.8b, v2.b[3] + dup v6.8b, v2.b[2] + dup v7.8b, v3.b[1] + zip1 v0.2s, v4.2s, v6.2s + zip1 v1.2s, v5.2s, v7.2s + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_0l0_dc_neon, export=1 + add x2, x0, x1, lsl #2 + sub x2, x2, #1 + ldcol.8 v1, x2, x1, 4 + uaddlp v2.4h, v1.8b + addp v2.4h, v2.4h, v2.4h + rshrn v1.8b, v2.8h, #2 + movi v0.8b, #128 + dup v1.8b, v1.b[0] + b .L_pred8x8_dc_end +endfunc diff --git a/libavcodec/aarch64/h264qpel_init_aarch64.c b/libavcodec/aarch64/h264qpel_init_aarch64.c index 4beb11b..74088b2 100644 --- a/libavcodec/aarch64/h264qpel_init_aarch64.c +++ b/libavcodec/aarch64/h264qpel_init_aarch64.c @@ -27,73 +27,73 @@ #include "libavutil/aarch64/cpu.h" #include "libavcodec/h264qpel.h" -void ff_put_h264_qpel16_mc00_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc10_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc20_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc30_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc01_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc11_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc21_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc31_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc02_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc12_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc22_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc32_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc03_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc13_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc23_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel16_mc33_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc00_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc10_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc20_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc30_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc01_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc11_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc21_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc31_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc02_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc12_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc22_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc32_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc03_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc13_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc23_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel16_mc33_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc00_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc10_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc20_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc30_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc01_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc11_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc21_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc31_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc02_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc12_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc22_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc32_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc03_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc13_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc23_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_put_h264_qpel8_mc33_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc00_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc10_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc20_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc30_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc01_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc11_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc21_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc31_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc02_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc12_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc22_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc32_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc03_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc13_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc23_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_put_h264_qpel8_mc33_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc00_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc10_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc20_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc30_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc01_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc11_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc21_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc31_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc02_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc12_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc22_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc32_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc03_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc13_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc23_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel16_mc33_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc00_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc10_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc20_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc30_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc01_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc11_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc21_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc31_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc02_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc12_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc22_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc32_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc03_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc13_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc23_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel16_mc33_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc00_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc10_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc20_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc30_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc01_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc11_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc21_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc31_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc02_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc12_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc22_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc32_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc03_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc13_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc23_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); -void ff_avg_h264_qpel8_mc33_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc00_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc10_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc20_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc30_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc01_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc11_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc21_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc31_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc02_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc12_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc22_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc32_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc03_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc13_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc23_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); +void ff_avg_h264_qpel8_mc33_neon(uint8_t *dst, const uint8_t *src, ptrdiff_t stride); av_cold void ff_h264qpel_init_aarch64(H264QpelContext *c, int bit_depth) { diff --git a/libavcodec/aarch64/opus_imdct_init.c b/libavcodec/aarch64/imdct15_init.c similarity index 66% rename from libavcodec/aarch64/opus_imdct_init.c rename to libavcodec/aarch64/imdct15_init.c index 1a776dc..38018f2 100644 --- a/libavcodec/aarch64/opus_imdct_init.c +++ b/libavcodec/aarch64/imdct15_init.c @@ -21,21 +21,22 @@ #include "libavutil/cpu.h" #include "libavutil/aarch64/cpu.h" #include "libavutil/internal.h" -#include "libavcodec/opus_imdct.h" + +#include "libavcodec/imdct15.h" #include "asm-offsets.h" -AV_CHECK_OFFSET(CeltIMDCTContext, exptab, CELT_EXPTAB); -AV_CHECK_OFFSET(CeltIMDCTContext, fft_n, CELT_FFT_N); -AV_CHECK_OFFSET(CeltIMDCTContext, len2, CELT_LEN2); -AV_CHECK_OFFSET(CeltIMDCTContext, len4, CELT_LEN4); -AV_CHECK_OFFSET(CeltIMDCTContext, tmp, CELT_TMP); -AV_CHECK_OFFSET(CeltIMDCTContext, twiddle_exptab, CELT_TWIDDLE); +AV_CHECK_OFFSET(IMDCT15Context, exptab, CELT_EXPTAB); +AV_CHECK_OFFSET(IMDCT15Context, fft_n, CELT_FFT_N); +AV_CHECK_OFFSET(IMDCT15Context, len2, CELT_LEN2); +AV_CHECK_OFFSET(IMDCT15Context, len4, CELT_LEN4); +AV_CHECK_OFFSET(IMDCT15Context, tmp, CELT_TMP); +AV_CHECK_OFFSET(IMDCT15Context, twiddle_exptab, CELT_TWIDDLE); -void ff_celt_imdct_half_neon(CeltIMDCTContext *s, float *dst, const float *src, +void ff_celt_imdct_half_neon(IMDCT15Context *s, float *dst, const float *src, ptrdiff_t stride, float scale); -void ff_celt_imdct_init_aarch64(CeltIMDCTContext *s) +void ff_imdct15_init_aarch64(IMDCT15Context *s) { int cpu_flags = av_get_cpu_flags(); diff --git a/libavcodec/aarch64/opus_imdct_neon.S b/libavcodec/aarch64/imdct15_neon.S similarity index 99% rename from libavcodec/aarch64/opus_imdct_neon.S rename to libavcodec/aarch64/imdct15_neon.S index 5f6c502..d99edf4 100644 --- a/libavcodec/aarch64/opus_imdct_neon.S +++ b/libavcodec/aarch64/imdct15_neon.S @@ -451,7 +451,7 @@ function fft_b15_calc_neon ret endfunc -const fft_tab_neon +const fft_tab_neon, relocate=1 .quad fft15_neon .quad fft30_neon .quad fft60_neon diff --git a/libavcodec/aarch64/mdct_init.c b/libavcodec/aarch64/mdct_init.c new file mode 100644 index 0000000..816111a --- /dev/null +++ b/libavcodec/aarch64/mdct_init.c @@ -0,0 +1,39 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" + +#include "libavcodec/fft.h" + +void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); + +av_cold void ff_mdct_init_aarch64(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->imdct_calc = ff_imdct_calc_neon; + s->imdct_half = ff_imdct_half_neon; + s->mdct_calc = ff_mdct_calc_neon; + s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; + } +} diff --git a/libavcodec/aarch64/mpegaudiodsp_neon.S b/libavcodec/aarch64/mpegaudiodsp_neon.S index 808576a..c1edc64 100644 --- a/libavcodec/aarch64/mpegaudiodsp_neon.S +++ b/libavcodec/aarch64/mpegaudiodsp_neon.S @@ -142,7 +142,7 @@ function ff_mpadsp_apply_window_\type\()_neon, export=1 sub x10, x10, #4<<2 b.gt 1b -// comuting samples[16] +// computing samples[16] add x6, x1, #32<<2 ld1 {v0.2s}, [x6], x9 ld1 {v1.2s}, [x0], x9 diff --git a/libavcodec/aarch64/neon.S b/libavcodec/aarch64/neon.S index f1072b7..377009e 100644 --- a/libavcodec/aarch64/neon.S +++ b/libavcodec/aarch64/neon.S @@ -107,12 +107,12 @@ .macro transpose_4x4H r0, r1, r2, r3, r4, r5, r6, r7 trn1 \r4\().4H, \r0\().4H, \r1\().4H trn2 \r5\().4H, \r0\().4H, \r1\().4H - trn1 \r7\().4H, \r3\().4H, \r2\().4H - trn2 \r6\().4H, \r3\().4H, \r2\().4H - trn1 \r0\().2S, \r4\().2S, \r7\().2S - trn2 \r3\().2S, \r4\().2S, \r7\().2S - trn1 \r1\().2S, \r5\().2S, \r6\().2S - trn2 \r2\().2S, \r5\().2S, \r6\().2S + trn1 \r6\().4H, \r2\().4H, \r3\().4H + trn2 \r7\().4H, \r2\().4H, \r3\().4H + trn1 \r0\().2S, \r4\().2S, \r6\().2S + trn2 \r2\().2S, \r4\().2S, \r6\().2S + trn1 \r1\().2S, \r5\().2S, \r7\().2S + trn2 \r3\().2S, \r5\().2S, \r7\().2S .endm .macro transpose_8x8H r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 diff --git a/libavcodec/aarch64/neontest.c b/libavcodec/aarch64/neontest.c index 0414829..137c8e6 100644 --- a/libavcodec/aarch64/neontest.c +++ b/libavcodec/aarch64/neontest.c @@ -23,7 +23,7 @@ #include "libavutil/aarch64/neontest.h" wrap(avcodec_open2(AVCodecContext *avctx, - AVCodec *codec, + const AVCodec *codec, AVDictionary **options)) { testneonclobbers(avcodec_open2, avctx, codec, options); diff --git a/libavcodec/aarch64/synth_filter_neon.S b/libavcodec/aarch64/synth_filter_neon.S new file mode 100644 index 0000000..9551bff --- /dev/null +++ b/libavcodec/aarch64/synth_filter_neon.S @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "asm-offsets.h" + +#include "libavutil/aarch64/asm.S" + +.macro inner_loop + ld1 {v29.4s}, [x9], x15 + ld1 {v28.4s}, [x8], x15 + ld1 {v30.4s}, [x10], x15 + ld1 {v31.4s}, [x11], x15 + rev64 v28.4s, v28.4s + ld1 {v24.4s}, [x4], x15 + ld1 {v25.4s}, [x5], x15 + rev64 v31.4s, v31.4s + ld1 {v26.4s}, [x6], x15 + fmla v5.4s, v25.4s, v29.4s + ld1 {v27.4s}, [x7], x15 + ext v28.16b, v28.16b, v28.16b, #8 + ext v31.16b, v31.16b, v31.16b, #8 + fmla v6.4s, v26.4s, v30.4s + fmls v4.4s, v24.4s, v28.4s + fmla v7.4s, v27.4s, v31.4s +.endm + +function ff_synth_filter_float_neon, export=1 + ldr w7, [x2] // *synth_buf_offset + ldr x9, [x0, #IMDCT_HALF] // imdct_half function pointer + sxtw x7, w7 + stp x3, x4, [sp, #-64]! + add x1, x1, x7, lsl #2 // synth_buf + sub w8, w7, #32 + stp x5, x1, [sp, #16] + bic x7, x7, #63 + and w8, w8, #511 + stp x7, x30, [sp, #32] + str w8, [x2] + str s0, [sp, #48] + + mov x2, x6 // in + + blr x9 + + ldp x2, x4, [sp] // synct_buf_2, window + ldp x13, x9, [sp, #16] // out, synth_buf + ldp x0, x30, [sp, #32] // *synth_buf_offset + ldr s0, [sp, #48] + + add x3, x2, #16*4 // synct_buf_2 + 16 + add x14, x13, #16*4 // out + 16 + add x8, x9, #12*4 + mov x15, #64*4 + mov x1, #4 +1: + add x10, x9, #16*4 // synth_buf + add x11, x8, #16*4 + add x5, x4, #16*4 // window + add x6, x4, #32*4 + add x7, x4, #48*4 + + ld1 {v4.4s}, [x2] // a + ld1 {v5.4s}, [x3] // b + movi v6.4s, #0 // c + movi v7.4s, #0 // d + + mov x12, #512 +2: + sub x12, x12, #64 + cmp x12, x0 + inner_loop + b.gt 2b + + sub x8, x8, #512*4 + sub x9, x9, #512*4 + cbz x12, 4f + sub x10, x10, #512*4 + sub x11, x11, #512*4 +3: + subs x12, x12, #64 + inner_loop + b.gt 3b +4: + subs x1, x1, #1 + fmul v4.4s, v4.4s, v0.s[0] + fmul v5.4s, v5.4s, v0.s[0] + st1 {v6.4s}, [x2], #16 + st1 {v7.4s}, [x3], #16 + st1 {v4.4s}, [x13], #16 + st1 {v5.4s}, [x14], #16 + b.le 10f + + sub x4, x4, #508*4 // window + add x9, x9, #4*4 // synth_buf + sub x8, x8, #4*4 // synth_buf + b 1b + +10: + add sp, sp, #64 + ret +endfunc diff --git a/libavcodec/aasc.c b/libavcodec/aasc.c index 1e457ce..e65ea39 100644 --- a/libavcodec/aasc.c +++ b/libavcodec/aasc.c @@ -1,6 +1,6 @@ /* * Autodesk RLE Decoder - * Copyright (C) 2005 the ffmpeg project + * Copyright (C) 2005 The FFmpeg project * * This file is part of Libav. * @@ -85,7 +85,7 @@ static int aasc_decode_frame(AVCodecContext *avctx, break; case 1: bytestream2_init(&s->gb, buf, buf_size); - ff_msrle_decode(avctx, (AVPicture*)s->frame, 8, &s->gb); + ff_msrle_decode(avctx, s->frame, 8, &s->gb); break; default: av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr); @@ -118,5 +118,5 @@ AVCodec ff_aasc_decoder = { .init = aasc_decode_init, .close = aasc_decode_end, .decode = aasc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/ac3.c b/libavcodec/ac3.c index 99e5b50..1118b52 100644 --- a/libavcodec/ac3.c +++ b/libavcodec/ac3.c @@ -24,9 +24,10 @@ * Common code between the AC-3 encoder and decoder. */ +#include "libavutil/common.h" + #include "avcodec.h" #include "ac3.h" -#include "get_bits.h" /** * Starting frequency coefficient bin for each critical band. diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 69d88c1..9704848 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -150,7 +150,7 @@ static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info, int err; union { uint64_t u64; - uint8_t u8[8 + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t u8[8 + AV_INPUT_BUFFER_PADDING_SIZE]; } tmp = { av_be2ne64(state) }; AC3HeaderInfo hdr; GetBitContext gbc; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 4876ac0..9afc54d 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -182,22 +182,14 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) ff_mdct_init(&s->imdct_512, 9, 1, 1.0); ff_kbd_window_init(s->window, 5.0, 256); ff_bswapdsp_init(&s->bdsp); - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); - ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); + ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); ff_fmt_convert_init(&s->fmt_conv, avctx); av_lfg_init(&s->dith_state, 0); avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; /* allow downmixing to stereo or mono */ -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->request_channels == 1) - avctx->request_channel_layout = AV_CH_LAYOUT_MONO; - else if (avctx->request_channels == 2) - avctx->request_channel_layout = AV_CH_LAYOUT_STEREO; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (avctx->channels > 1 && avctx->request_channel_layout == AV_CH_LAYOUT_MONO) avctx->channels = 1; @@ -452,7 +444,7 @@ static void calc_transform_coeffs_cpl(AC3DecodeContext *s) /** * Grouped mantissas for 3-level 5-level and 11-level quantization */ -typedef struct { +typedef struct mant_groups { int b1_mant[2]; int b2_mant[2]; int b4_mant; @@ -556,8 +548,8 @@ static void remove_dithering(AC3DecodeContext *s) { } } -static void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk, int ch, - mant_groups *m) +static inline void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk, + int ch, mant_groups *m) { if (!s->channel_uses_aht[ch]) { ac3_decode_transform_coeffs_ch(s, ch, m); @@ -576,7 +568,7 @@ static void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk, int ch, /** * Decode the transform coefficients. */ -static void decode_transform_coeffs(AC3DecodeContext *s, int blk) +static inline void decode_transform_coeffs(AC3DecodeContext *s, int blk) { int ch, end; int got_cplchan = 0; @@ -754,6 +746,221 @@ static void decode_band_structure(GetBitContext *gbc, int blk, int eac3, memcpy(band_sizes, bnd_sz, n_bands); } +static inline int spx_strategy(AC3DecodeContext *s, int blk) +{ + GetBitContext *bc = &s->gbc; + int fbw_channels = s->fbw_channels; + int dst_start_freq, dst_end_freq, src_start_freq, + start_subband, end_subband, ch; + + /* determine which channels use spx */ + if (s->channel_mode == AC3_CHMODE_MONO) { + s->channel_uses_spx[1] = 1; + } else { + for (ch = 1; ch <= fbw_channels; ch++) + s->channel_uses_spx[ch] = get_bits1(bc); + } + + /* get the frequency bins of the spx copy region and the spx start + and end subbands */ + dst_start_freq = get_bits(bc, 2); + start_subband = get_bits(bc, 3) + 2; + if (start_subband > 7) + start_subband += start_subband - 7; + end_subband = get_bits(bc, 3) + 5; + if (end_subband > 7) + end_subband += end_subband - 7; + dst_start_freq = dst_start_freq * 12 + 25; + src_start_freq = start_subband * 12 + 25; + dst_end_freq = end_subband * 12 + 25; + + /* check validity of spx ranges */ + if (start_subband >= end_subband) { + av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " + "range (%d >= %d)\n", start_subband, end_subband); + return AVERROR_INVALIDDATA; + } + if (dst_start_freq >= src_start_freq) { + av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " + "copy start bin (%d >= %d)\n", dst_start_freq, src_start_freq); + return AVERROR_INVALIDDATA; + } + + s->spx_dst_start_freq = dst_start_freq; + s->spx_src_start_freq = src_start_freq; + s->spx_dst_end_freq = dst_end_freq; + + decode_band_structure(bc, blk, s->eac3, 0, + start_subband, end_subband, + ff_eac3_default_spx_band_struct, + &s->num_spx_bands, + s->spx_band_sizes); + + return 0; +} + +static inline void spx_coordinates(AC3DecodeContext *s) +{ + GetBitContext *bc = &s->gbc; + int fbw_channels = s->fbw_channels; + int ch, bnd; + + for (ch = 1; ch <= fbw_channels; ch++) { + if (s->channel_uses_spx[ch]) { + if (s->first_spx_coords[ch] || get_bits1(bc)) { + float spx_blend; + int bin, master_spx_coord; + + s->first_spx_coords[ch] = 0; + spx_blend = get_bits(bc, 5) * (1.0f / 32); + master_spx_coord = get_bits(bc, 2) * 3; + + bin = s->spx_src_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int bandsize; + int spx_coord_exp, spx_coord_mant; + float nratio, sblend, nblend, spx_coord; + + /* calculate blending factors */ + bandsize = s->spx_band_sizes[bnd]; + nratio = ((float)((bin + (bandsize >> 1))) / s->spx_dst_end_freq) - spx_blend; + nratio = av_clipf(nratio, 0.0f, 1.0f); + nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3) + // to give unity variance + sblend = sqrtf(1.0f - nratio); + bin += bandsize; + + /* decode spx coordinates */ + spx_coord_exp = get_bits(bc, 4); + spx_coord_mant = get_bits(bc, 2); + if (spx_coord_exp == 15) spx_coord_mant <<= 1; + else spx_coord_mant += 4; + spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord); + spx_coord = spx_coord_mant * (1.0f / (1 << 23)); + + /* multiply noise and signal blending factors by spx coordinate */ + s->spx_noise_blend [ch][bnd] = nblend * spx_coord; + s->spx_signal_blend[ch][bnd] = sblend * spx_coord; + } + } + } else { + s->first_spx_coords[ch] = 1; + } + } +} + +static inline int coupling_strategy(AC3DecodeContext *s, int blk, + uint8_t *bit_alloc_stages) +{ + GetBitContext *bc = &s->gbc; + int fbw_channels = s->fbw_channels; + int channel_mode = s->channel_mode; + int ch; + + memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS); + if (!s->eac3) + s->cpl_in_use[blk] = get_bits1(bc); + if (s->cpl_in_use[blk]) { + /* coupling in use */ + int cpl_start_subband, cpl_end_subband; + + if (channel_mode < AC3_CHMODE_STEREO) { + av_log(s->avctx, AV_LOG_ERROR, "coupling not allowed in mono or dual-mono\n"); + return AVERROR_INVALIDDATA; + } + + /* check for enhanced coupling */ + if (s->eac3 && get_bits1(bc)) { + /* TODO: parse enhanced coupling strategy info */ + avpriv_request_sample(s->avctx, "Enhanced coupling"); + return AVERROR_PATCHWELCOME; + } + + /* determine which channels are coupled */ + if (s->eac3 && s->channel_mode == AC3_CHMODE_STEREO) { + s->channel_in_cpl[1] = 1; + s->channel_in_cpl[2] = 1; + } else { + for (ch = 1; ch <= fbw_channels; ch++) + s->channel_in_cpl[ch] = get_bits1(bc); + } + + /* phase flags in use */ + if (channel_mode == AC3_CHMODE_STEREO) + s->phase_flags_in_use = get_bits1(bc); + + /* coupling frequency range */ + cpl_start_subband = get_bits(bc, 4); + cpl_end_subband = s->spx_in_use ? (s->spx_src_start_freq - 37) / 12 : + get_bits(bc, 4) + 3; + if (cpl_start_subband >= cpl_end_subband) { + av_log(s->avctx, AV_LOG_ERROR, "invalid coupling range (%d >= %d)\n", + cpl_start_subband, cpl_end_subband); + return AVERROR_INVALIDDATA; + } + s->start_freq[CPL_CH] = cpl_start_subband * 12 + 37; + s->end_freq[CPL_CH] = cpl_end_subband * 12 + 37; + + decode_band_structure(bc, blk, s->eac3, 0, cpl_start_subband, + cpl_end_subband, + ff_eac3_default_cpl_band_struct, + &s->num_cpl_bands, s->cpl_band_sizes); + } else { + /* coupling not in use */ + for (ch = 1; ch <= fbw_channels; ch++) { + s->channel_in_cpl[ch] = 0; + s->first_cpl_coords[ch] = 1; + } + s->first_cpl_leak = s->eac3; + s->phase_flags_in_use = 0; + } + + return 0; +} + +static inline int coupling_coordinates(AC3DecodeContext *s, int blk) +{ + GetBitContext *bc = &s->gbc; + int fbw_channels = s->fbw_channels; + int ch, bnd; + int cpl_coords_exist = 0; + + for (ch = 1; ch <= fbw_channels; ch++) { + if (s->channel_in_cpl[ch]) { + if ((s->eac3 && s->first_cpl_coords[ch]) || get_bits1(bc)) { + int master_cpl_coord, cpl_coord_exp, cpl_coord_mant; + s->first_cpl_coords[ch] = 0; + cpl_coords_exist = 1; + master_cpl_coord = 3 * get_bits(bc, 2); + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + cpl_coord_exp = get_bits(bc, 4); + cpl_coord_mant = get_bits(bc, 4); + if (cpl_coord_exp == 15) + s->cpl_coords[ch][bnd] = cpl_coord_mant << 22; + else + s->cpl_coords[ch][bnd] = (cpl_coord_mant + 16) << 21; + s->cpl_coords[ch][bnd] >>= (cpl_coord_exp + master_cpl_coord); + } + } else if (!blk) { + av_log(s->avctx, AV_LOG_ERROR, "new coupling coordinates must " + "be present in block 0\n"); + return AVERROR_INVALIDDATA; + } + } else { + /* channel not in coupling */ + s->first_cpl_coords[ch] = 1; + } + } + /* phase flags */ + if (s->channel_mode == AC3_CHMODE_STEREO && cpl_coords_exist) { + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + s->phase_flags[bnd] = s->phase_flags_in_use ? get_bits1(bc) : 0; + } + } + + return 0; +} + /** * Decode a single audio block from the AC-3 bitstream. */ @@ -761,7 +968,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) { int fbw_channels = s->fbw_channels; int channel_mode = s->channel_mode; - int i, bnd, seg, ch; + int i, bnd, seg, ch, ret; int different_transforms; int downmix_output; int cpl_in_use; @@ -805,51 +1012,8 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) if (s->eac3 && (!blk || get_bits1(gbc))) { s->spx_in_use = get_bits1(gbc); if (s->spx_in_use) { - int dst_start_freq, dst_end_freq, src_start_freq, - start_subband, end_subband; - - /* determine which channels use spx */ - if (s->channel_mode == AC3_CHMODE_MONO) { - s->channel_uses_spx[1] = 1; - } else { - for (ch = 1; ch <= fbw_channels; ch++) - s->channel_uses_spx[ch] = get_bits1(gbc); - } - - /* get the frequency bins of the spx copy region and the spx start - and end subbands */ - dst_start_freq = get_bits(gbc, 2); - start_subband = get_bits(gbc, 3) + 2; - if (start_subband > 7) - start_subband += start_subband - 7; - end_subband = get_bits(gbc, 3) + 5; - if (end_subband > 7) - end_subband += end_subband - 7; - dst_start_freq = dst_start_freq * 12 + 25; - src_start_freq = start_subband * 12 + 25; - dst_end_freq = end_subband * 12 + 25; - - /* check validity of spx ranges */ - if (start_subband >= end_subband) { - av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " - "range (%d >= %d)\n", start_subband, end_subband); - return AVERROR_INVALIDDATA; - } - if (dst_start_freq >= src_start_freq) { - av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " - "copy start bin (%d >= %d)\n", dst_start_freq, src_start_freq); - return AVERROR_INVALIDDATA; - } - - s->spx_dst_start_freq = dst_start_freq; - s->spx_src_start_freq = src_start_freq; - s->spx_dst_end_freq = dst_end_freq; - - decode_band_structure(gbc, blk, s->eac3, 0, - start_subband, end_subband, - ff_eac3_default_spx_band_struct, - &s->num_spx_bands, - s->spx_band_sizes); + if ((ret = spx_strategy(s, blk)) < 0) + return ret; } else { for (ch = 1; ch <= fbw_channels; ch++) { s->channel_uses_spx[ch] = 0; @@ -859,110 +1023,13 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) } /* spectral extension coordinates */ - if (s->spx_in_use) { - for (ch = 1; ch <= fbw_channels; ch++) { - if (s->channel_uses_spx[ch]) { - if (s->first_spx_coords[ch] || get_bits1(gbc)) { - float spx_blend; - int bin, master_spx_coord; - - s->first_spx_coords[ch] = 0; - spx_blend = get_bits(gbc, 5) * (1.0f/32); - master_spx_coord = get_bits(gbc, 2) * 3; - - bin = s->spx_src_start_freq; - for (bnd = 0; bnd < s->num_spx_bands; bnd++) { - int bandsize; - int spx_coord_exp, spx_coord_mant; - float nratio, sblend, nblend, spx_coord; - - /* calculate blending factors */ - bandsize = s->spx_band_sizes[bnd]; - nratio = ((float)((bin + (bandsize >> 1))) / s->spx_dst_end_freq) - spx_blend; - nratio = av_clipf(nratio, 0.0f, 1.0f); - nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3) - // to give unity variance - sblend = sqrtf(1.0f - nratio); - bin += bandsize; - - /* decode spx coordinates */ - spx_coord_exp = get_bits(gbc, 4); - spx_coord_mant = get_bits(gbc, 2); - if (spx_coord_exp == 15) spx_coord_mant <<= 1; - else spx_coord_mant += 4; - spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord); - spx_coord = spx_coord_mant * (1.0f / (1 << 23)); - - /* multiply noise and signal blending factors by spx coordinate */ - s->spx_noise_blend [ch][bnd] = nblend * spx_coord; - s->spx_signal_blend[ch][bnd] = sblend * spx_coord; - } - } - } else { - s->first_spx_coords[ch] = 1; - } - } - } + if (s->spx_in_use) + spx_coordinates(s); /* coupling strategy */ if (s->eac3 ? s->cpl_strategy_exists[blk] : get_bits1(gbc)) { - memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS); - if (!s->eac3) - s->cpl_in_use[blk] = get_bits1(gbc); - if (s->cpl_in_use[blk]) { - /* coupling in use */ - int cpl_start_subband, cpl_end_subband; - - if (channel_mode < AC3_CHMODE_STEREO) { - av_log(s->avctx, AV_LOG_ERROR, "coupling not allowed in mono or dual-mono\n"); - return AVERROR_INVALIDDATA; - } - - /* check for enhanced coupling */ - if (s->eac3 && get_bits1(gbc)) { - /* TODO: parse enhanced coupling strategy info */ - avpriv_request_sample(s->avctx, "Enhanced coupling"); - return AVERROR_PATCHWELCOME; - } - - /* determine which channels are coupled */ - if (s->eac3 && s->channel_mode == AC3_CHMODE_STEREO) { - s->channel_in_cpl[1] = 1; - s->channel_in_cpl[2] = 1; - } else { - for (ch = 1; ch <= fbw_channels; ch++) - s->channel_in_cpl[ch] = get_bits1(gbc); - } - - /* phase flags in use */ - if (channel_mode == AC3_CHMODE_STEREO) - s->phase_flags_in_use = get_bits1(gbc); - - /* coupling frequency range */ - cpl_start_subband = get_bits(gbc, 4); - cpl_end_subband = s->spx_in_use ? (s->spx_src_start_freq - 37) / 12 : - get_bits(gbc, 4) + 3; - if (cpl_start_subband >= cpl_end_subband) { - av_log(s->avctx, AV_LOG_ERROR, "invalid coupling range (%d >= %d)\n", - cpl_start_subband, cpl_end_subband); - return AVERROR_INVALIDDATA; - } - s->start_freq[CPL_CH] = cpl_start_subband * 12 + 37; - s->end_freq[CPL_CH] = cpl_end_subband * 12 + 37; - - decode_band_structure(gbc, blk, s->eac3, 0, cpl_start_subband, - cpl_end_subband, - ff_eac3_default_cpl_band_struct, - &s->num_cpl_bands, s->cpl_band_sizes); - } else { - /* coupling not in use */ - for (ch = 1; ch <= fbw_channels; ch++) { - s->channel_in_cpl[ch] = 0; - s->first_cpl_coords[ch] = 1; - } - s->first_cpl_leak = s->eac3; - s->phase_flags_in_use = 0; - } + if ((ret = coupling_strategy(s, blk, bit_alloc_stages)) < 0) + return ret; } else if (!s->eac3) { if (!blk) { av_log(s->avctx, AV_LOG_ERROR, "new coupling strategy must " @@ -976,40 +1043,8 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) /* coupling coordinates */ if (cpl_in_use) { - int cpl_coords_exist = 0; - - for (ch = 1; ch <= fbw_channels; ch++) { - if (s->channel_in_cpl[ch]) { - if ((s->eac3 && s->first_cpl_coords[ch]) || get_bits1(gbc)) { - int master_cpl_coord, cpl_coord_exp, cpl_coord_mant; - s->first_cpl_coords[ch] = 0; - cpl_coords_exist = 1; - master_cpl_coord = 3 * get_bits(gbc, 2); - for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { - cpl_coord_exp = get_bits(gbc, 4); - cpl_coord_mant = get_bits(gbc, 4); - if (cpl_coord_exp == 15) - s->cpl_coords[ch][bnd] = cpl_coord_mant << 22; - else - s->cpl_coords[ch][bnd] = (cpl_coord_mant + 16) << 21; - s->cpl_coords[ch][bnd] >>= (cpl_coord_exp + master_cpl_coord); - } - } else if (!blk) { - av_log(s->avctx, AV_LOG_ERROR, "new coupling coordinates must " - "be present in block 0\n"); - return AVERROR_INVALIDDATA; - } - } else { - /* channel not in coupling */ - s->first_cpl_coords[ch] = 1; - } - } - /* phase flags */ - if (channel_mode == AC3_CHMODE_STEREO && cpl_coords_exist) { - for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { - s->phase_flags[bnd] = s->phase_flags_in_use? get_bits1(gbc) : 0; - } - } + if ((ret = coupling_coordinates(s, blk)) < 0) + return ret; } /* stereo rematrixing strategy and band structure */ @@ -1236,8 +1271,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) /* unused dummy data */ if (s->skip_syntax && get_bits1(gbc)) { int skipl = get_bits(gbc, 9); - while (skipl--) - skip_bits(gbc, 8); + skip_bits_long(gbc, 8 * skipl); } /* unpack the transform coefficients @@ -1355,8 +1389,9 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, /* skip frame if CRC is ok. otherwise use error concealment. */ /* TODO: add support for substreams and dependent frames */ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) { - av_log(avctx, AV_LOG_WARNING, "unsupported frame type : " - "skipping frame\n"); + av_log(avctx, AV_LOG_DEBUG, + "unsupported frame type %d: skipping frame\n", + s->frame_type); *got_frame_ptr = 0; return buf_size; } else { @@ -1558,7 +1593,7 @@ AVCodec ff_ac3_decoder = { .init = ac3_decode_init, .close = ac3_decode_end, .decode = ac3_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &ac3_decoder_class, @@ -1581,7 +1616,7 @@ AVCodec ff_eac3_decoder = { .init = ac3_decode_init, .close = ac3_decode_end, .decode = ac3_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &eac3_decoder_class, diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index babd0a7..4c5359c 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -92,6 +92,8 @@ typedef struct AC3DecodeContext { int lfe_mix_level_exists; ///< indicates if lfemixlevcod is specified (lfemixlevcode) int lfe_mix_level; ///< LFE mix level index (lfemixlevcod) int eac3; ///< indicates if current frame is E-AC-3 + int eac3_frame_dependent_found; ///< bitstream has E-AC-3 dependent frame(s) + int eac3_subsbtreamid_found; ///< bitstream has E-AC-3 additional substream(s) int dolby_surround_mode; ///< dolby surround mode (dsurmod) int dolby_surround_ex_mode; ///< dolby surround ex mode (dsurexmod) int dolby_headphone_mode; ///< dolby headphone mode (dheadphonmod) @@ -217,7 +219,7 @@ typedef struct AC3DecodeContext { DECLARE_ALIGNED(32, float, window)[AC3_BLOCK_SIZE]; ///< window coefficients DECLARE_ALIGNED(32, float, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing - DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread + DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread ///@} } AC3DecodeContext; diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index 25bd6e3..38c35b1 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avassert.h" #include "avcodec.h" #include "ac3.h" #include "ac3dsp.h" @@ -125,7 +124,7 @@ static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd, band_end = FFMIN(band_end, end); for (; bin < band_end; bin++) { - int address = av_clip((psd[bin] - m) >> 5, 0, 63); + int address = av_clip_uintp2((psd[bin] - m) >> 5, 6); bap[bin] = bap_tab[address]; } } while (end > band_end); diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 5c02e7f..da141e1 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -42,6 +42,7 @@ #include "ac3dsp.h" #include "ac3.h" #include "fft.h" +#include "internal.h" #include "ac3enc.h" #include "eac3enc.h" @@ -1690,43 +1691,43 @@ static void dprint_options(AC3EncodeContext *s) case 16: av_strlcpy(strbuf, "E-AC-3 (enhanced)", 32); break; default: snprintf(strbuf, 32, "ERROR"); } - av_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id); - av_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt)); + ff_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id); + ff_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt)); av_get_channel_layout_string(strbuf, 32, s->channels, avctx->channel_layout); - av_dlog(avctx, "channel_layout: %s\n", strbuf); - av_dlog(avctx, "sample_rate: %d\n", s->sample_rate); - av_dlog(avctx, "bit_rate: %d\n", s->bit_rate); - av_dlog(avctx, "blocks/frame: %d (code=%d)\n", s->num_blocks, s->num_blks_code); + ff_dlog(avctx, "channel_layout: %s\n", strbuf); + ff_dlog(avctx, "sample_rate: %d\n", s->sample_rate); + ff_dlog(avctx, "bit_rate: %d\n", s->bit_rate); + ff_dlog(avctx, "blocks/frame: %d (code=%d)\n", s->num_blocks, s->num_blks_code); if (s->cutoff) - av_dlog(avctx, "cutoff: %d\n", s->cutoff); + ff_dlog(avctx, "cutoff: %d\n", s->cutoff); - av_dlog(avctx, "per_frame_metadata: %s\n", + ff_dlog(avctx, "per_frame_metadata: %s\n", opt->allow_per_frame_metadata?"on":"off"); if (s->has_center) - av_dlog(avctx, "center_mixlev: %0.3f (%d)\n", opt->center_mix_level, + ff_dlog(avctx, "center_mixlev: %0.3f (%d)\n", opt->center_mix_level, s->center_mix_level); else - av_dlog(avctx, "center_mixlev: {not written}\n"); + ff_dlog(avctx, "center_mixlev: {not written}\n"); if (s->has_surround) - av_dlog(avctx, "surround_mixlev: %0.3f (%d)\n", opt->surround_mix_level, + ff_dlog(avctx, "surround_mixlev: %0.3f (%d)\n", opt->surround_mix_level, s->surround_mix_level); else - av_dlog(avctx, "surround_mixlev: {not written}\n"); + ff_dlog(avctx, "surround_mixlev: {not written}\n"); if (opt->audio_production_info) { - av_dlog(avctx, "mixing_level: %ddB\n", opt->mixing_level); + ff_dlog(avctx, "mixing_level: %ddB\n", opt->mixing_level); switch (opt->room_type) { case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; case AC3ENC_OPT_LARGE_ROOM: av_strlcpy(strbuf, "large", 32); break; case AC3ENC_OPT_SMALL_ROOM: av_strlcpy(strbuf, "small", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->room_type); } - av_dlog(avctx, "room_type: %s\n", strbuf); + ff_dlog(avctx, "room_type: %s\n", strbuf); } else { - av_dlog(avctx, "mixing_level: {not written}\n"); - av_dlog(avctx, "room_type: {not written}\n"); + ff_dlog(avctx, "mixing_level: {not written}\n"); + ff_dlog(avctx, "room_type: {not written}\n"); } - av_dlog(avctx, "copyright: %s\n", opt->copyright?"on":"off"); - av_dlog(avctx, "dialnorm: %ddB\n", opt->dialogue_level); + ff_dlog(avctx, "copyright: %s\n", opt->copyright?"on":"off"); + ff_dlog(avctx, "dialnorm: %ddB\n", opt->dialogue_level); if (s->channel_mode == AC3_CHMODE_STEREO) { switch (opt->dolby_surround_mode) { case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; @@ -1734,11 +1735,11 @@ static void dprint_options(AC3EncodeContext *s) case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_surround_mode); } - av_dlog(avctx, "dsur_mode: %s\n", strbuf); + ff_dlog(avctx, "dsur_mode: %s\n", strbuf); } else { - av_dlog(avctx, "dsur_mode: {not written}\n"); + ff_dlog(avctx, "dsur_mode: {not written}\n"); } - av_dlog(avctx, "original: %s\n", opt->original?"on":"off"); + ff_dlog(avctx, "original: %s\n", opt->original?"on":"off"); if (s->bitstream_id == 6) { if (opt->extended_bsi_1) { @@ -1748,17 +1749,17 @@ static void dprint_options(AC3EncodeContext *s) case AC3ENC_OPT_DOWNMIX_LORO: av_strlcpy(strbuf, "loro", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->preferred_stereo_downmix); } - av_dlog(avctx, "dmix_mode: %s\n", strbuf); - av_dlog(avctx, "ltrt_cmixlev: %0.3f (%d)\n", + ff_dlog(avctx, "dmix_mode: %s\n", strbuf); + ff_dlog(avctx, "ltrt_cmixlev: %0.3f (%d)\n", opt->ltrt_center_mix_level, s->ltrt_center_mix_level); - av_dlog(avctx, "ltrt_surmixlev: %0.3f (%d)\n", + ff_dlog(avctx, "ltrt_surmixlev: %0.3f (%d)\n", opt->ltrt_surround_mix_level, s->ltrt_surround_mix_level); - av_dlog(avctx, "loro_cmixlev: %0.3f (%d)\n", + ff_dlog(avctx, "loro_cmixlev: %0.3f (%d)\n", opt->loro_center_mix_level, s->loro_center_mix_level); - av_dlog(avctx, "loro_surmixlev: %0.3f (%d)\n", + ff_dlog(avctx, "loro_surmixlev: %0.3f (%d)\n", opt->loro_surround_mix_level, s->loro_surround_mix_level); } else { - av_dlog(avctx, "extended bitstream info 1: {not written}\n"); + ff_dlog(avctx, "extended bitstream info 1: {not written}\n"); } if (opt->extended_bsi_2) { switch (opt->dolby_surround_ex_mode) { @@ -1767,23 +1768,23 @@ static void dprint_options(AC3EncodeContext *s) case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_surround_ex_mode); } - av_dlog(avctx, "dsurex_mode: %s\n", strbuf); + ff_dlog(avctx, "dsurex_mode: %s\n", strbuf); switch (opt->dolby_headphone_mode) { case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; case AC3ENC_OPT_MODE_ON: av_strlcpy(strbuf, "on", 32); break; case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_headphone_mode); } - av_dlog(avctx, "dheadphone_mode: %s\n", strbuf); + ff_dlog(avctx, "dheadphone_mode: %s\n", strbuf); switch (opt->ad_converter_type) { case AC3ENC_OPT_ADCONV_STANDARD: av_strlcpy(strbuf, "standard", 32); break; case AC3ENC_OPT_ADCONV_HDCD: av_strlcpy(strbuf, "hdcd", 32); break; default: snprintf(strbuf, 32, "ERROR (%d)", opt->ad_converter_type); } - av_dlog(avctx, "ad_conv_type: %s\n", strbuf); + ff_dlog(avctx, "ad_conv_type: %s\n", strbuf); } else { - av_dlog(avctx, "extended bitstream info 2: {not written}\n"); + ff_dlog(avctx, "extended bitstream info 2: {not written}\n"); } } #endif @@ -2436,7 +2437,7 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) return ret; avctx->frame_size = AC3_BLOCK_SIZE * s->num_blocks; - avctx->delay = AC3_BLOCK_SIZE; + avctx->initial_padding = AC3_BLOCK_SIZE; s->bitstream_mode = avctx->audio_service_type; if (s->bitstream_mode == AV_AUDIO_SERVICE_TYPE_KARAOKE) @@ -2484,7 +2485,7 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) ff_audiodsp_init(&s->adsp); ff_me_cmp_init(&s->mecc, avctx); - ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); dprint_options(s); diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index 30c15d0..76b6d7f 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -80,12 +80,14 @@ typedef int64_t CoefSumType; #define AC3ENC_OPT_NOT_INDICATED 0 #define AC3ENC_OPT_MODE_ON 2 #define AC3ENC_OPT_MODE_OFF 1 +#define AC3ENC_OPT_DSUREX_DPLIIZ 3 /* specific option values */ #define AC3ENC_OPT_LARGE_ROOM 1 #define AC3ENC_OPT_SMALL_ROOM 2 #define AC3ENC_OPT_DOWNMIX_LTRT 1 #define AC3ENC_OPT_DOWNMIX_LORO 2 +#define AC3ENC_OPT_DOWNMIX_DPLII 3 // reserved value in A/52, but used by encoders to indicate DPL2 #define AC3ENC_OPT_ADCONV_STANDARD 0 #define AC3ENC_OPT_ADCONV_HDCD 1 diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index d106d1b..822f431 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -129,7 +129,7 @@ static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl) av_cold int ff_ac3_float_encode_init(AVCodecContext *avctx) { AC3EncodeContext *s = avctx->priv_data; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); return ff_ac3_encode_init(avctx); } diff --git a/libavcodec/ac3enc_opts_template.c b/libavcodec/ac3enc_opts_template.c index 339a08f..a08c70d 100644 --- a/libavcodec/ac3enc_opts_template.c +++ b/libavcodec/ac3enc_opts_template.c @@ -46,18 +46,20 @@ static const AVOption ac3_options[] = { {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, {"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, /* extended bitstream information */ -{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_LORO, AC3ENC_PARAM, "dmix_mode"}, +{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_DPLII, AC3ENC_PARAM, "dmix_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"dplii", "Dolby Pro Logic II Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_DPLII }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, {"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, -{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsurex_mode"}, +{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DSUREX_DPLIIZ, AC3ENC_PARAM, "dsurex_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"dpliiz", "Dolby Pro Logic IIz-encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DSUREX_DPLIIZ }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, {"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dheadphone_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c index 79b4946..ec8ec4e 100644 --- a/libavcodec/ac3enc_template.c +++ b/libavcodec/ac3enc_template.c @@ -260,7 +260,7 @@ static void apply_channel_coupling(AC3EncodeContext *s) energy_cpl = energy[blk][CPL_CH][bnd]; energy_ch = energy[blk][ch][bnd]; blk1 = blk+1; - while (!s->blocks[blk1].new_cpl_coords[ch] && blk1 < s->num_blocks) { + while (blk1 < s->num_blocks && !s->blocks[blk1].new_cpl_coords[ch]) { if (s->blocks[blk1].cpl_in_use) { energy_cpl += energy[blk1][CPL_CH][bnd]; energy_ch += energy[blk1][ch][bnd]; @@ -450,7 +450,7 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt, ff_ac3_output_frame(s, avpkt->data); if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); *got_packet_ptr = 1; return 0; diff --git a/libavcodec/acelp_filters.h b/libavcodec/acelp_filters.h index 6a9ebd9..2be4c24 100644 --- a/libavcodec/acelp_filters.h +++ b/libavcodec/acelp_filters.h @@ -49,7 +49,6 @@ extern const int16_t ff_acelp_interp_filter[61]; * filter_coeffs contains coefficients of the right half of the symmetric * interpolation filter. filter_coeffs[0] should the central (unpaired) coefficient. * See ff_acelp_interp_filter for an example. - * */ void ff_acelp_interpolate(int16_t* out, const int16_t* in, const int16_t* filter_coeffs, int precision, diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index c6bc4d0..3ab16dd 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 The ffmpeg Project + * Copyright (c) 2001-2003 The FFmpeg project * * first version by Francois Revol (revol@free.fr) * fringe ADPCM codecs (e.g., DK3, DK4, Westwood) @@ -1298,7 +1298,7 @@ AVCodec ff_ ## name_ ## _decoder = { \ .priv_data_size = sizeof(ADPCMDecodeContext), \ .init = adpcm_decode_init, \ .decode = adpcm_decode_frame, \ - .capabilities = CODEC_CAP_DR1, \ + .capabilities = AV_CODEC_CAP_DR1, \ .sample_fmts = sample_fmts_, \ } diff --git a/libavcodec/adpcm.h b/libavcodec/adpcm.h index 16facb6..11be5a9 100644 --- a/libavcodec/adpcm.h +++ b/libavcodec/adpcm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 The ffmpeg Project + * Copyright (c) 2001-2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/adpcm_data.c b/libavcodec/adpcm_data.c index 3bc5de2..e40abc5 100644 --- a/libavcodec/adpcm_data.c +++ b/libavcodec/adpcm_data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 The ffmpeg Project + * Copyright (c) 2001-2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/adpcm_data.h b/libavcodec/adpcm_data.h index a46cb5b..cecd156 100644 --- a/libavcodec/adpcm_data.h +++ b/libavcodec/adpcm_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 The ffmpeg Project + * Copyright (c) 2001-2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index 341dda4..0757624 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 The ffmpeg Project + * Copyright (c) 2001-2003 The FFmpeg project * * first version by Francois Revol (revol@free.fr) * fringe ADPCM codecs (e.g., DK3, DK4, Westwood) @@ -23,7 +23,6 @@ */ #include "avcodec.h" -#include "get_bits.h" #include "put_bits.h" #include "bytestream.h" #include "adpcm.h" @@ -111,7 +110,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 / avctx->channels + 2; avctx->block_align = BLKSIZE; - if (!(avctx->extradata = av_malloc(32 + FF_INPUT_BUFFER_PADDING_SIZE))) + if (!(avctx->extradata = av_malloc(32 + AV_INPUT_BUFFER_PADDING_SIZE))) goto error; avctx->extradata_size = 32; extradata = avctx->extradata; diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c index 14fddf5..dc587b2 100644 --- a/libavcodec/adxdec.c +++ b/libavcodec/adxdec.c @@ -182,7 +182,7 @@ AVCodec ff_adpcm_adx_decoder = { .init = adx_decode_init, .decode = adx_decode_frame, .flush = adx_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/aic.c b/libavcodec/aic.c index 5687dbe..7c6dddd 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -28,6 +28,7 @@ #include "get_bits.h" #include "golomb.h" #include "idctdsp.h" +#include "thread.h" #include "unary.h" #define AIC_HDR_SIZE 24 @@ -373,6 +374,7 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, uint32_t off; int x, y, ret; int slice_size; + ThreadFrame frame = { .f = data }; ctx->frame = data; ctx->frame->pict_type = AV_PICTURE_TYPE_I; @@ -385,10 +387,13 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; } - if ((ret = aic_decode_header(ctx, buf, buf_size)) < 0) + ret = aic_decode_header(ctx, buf, buf_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid header\n"); return ret; + } - if ((ret = ff_get_buffer(avctx, ctx->frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; bytestream2_init(&gb, buf + AIC_HDR_SIZE, @@ -398,13 +403,17 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (x = 0; x < ctx->mb_width; x += ctx->slice_width) { slice_size = bytestream2_get_le16(&gb) * 4; if (slice_size + off > buf_size || !slice_size) { - av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + av_log(avctx, AV_LOG_ERROR, + "Incorrect slice size %d at %d.%d\n", slice_size, x, y); return AVERROR_INVALIDDATA; } - if ((ret = aic_decode_slice(ctx, x, y, - buf + off, slice_size)) < 0) + ret = aic_decode_slice(ctx, x, y, buf + off, slice_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error decoding slice at %d.%d\n", x, y); return ret; + } off += slice_size; } @@ -437,7 +446,7 @@ static av_cold int aic_decode_init(AVCodecContext *avctx) ctx->num_x_slices = (ctx->mb_width + 15) >> 4; ctx->slice_width = 16; for (i = 1; i < 32; i++) { - if (!(ctx->mb_width % i) && (ctx->mb_width / i < 32)) { + if (!(ctx->mb_width % i) && (ctx->mb_width / i <= 32)) { ctx->slice_width = ctx->mb_width / i; ctx->num_x_slices = i; break; @@ -477,5 +486,6 @@ AVCodec ff_aic_decoder = { .init = aic_decode_init, .close = aic_decode_close, .decode = aic_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(aic_decode_init), }; diff --git a/libavcodec/alac.c b/libavcodec/alac.c index 5c792c4..0d2a7ca 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -29,20 +29,20 @@ * passed through the extradata[_size] fields. This atom is tacked onto * the end of an 'alac' stsd atom and has the following format: * - * 32bit atom size - * 32bit tag ("alac") - * 32bit tag version (0) - * 32bit samples per frame (used when not set explicitly in the frames) - * 8bit compatible version (0) - * 8bit sample size - * 8bit history mult (40) - * 8bit initial history (14) - * 8bit rice param limit (10) - * 8bit channels - * 16bit maxRun (255) - * 32bit max coded frame size (0 means unknown) - * 32bit average bitrate (0 means unknown) - * 32bit samplerate + * 32 bits atom size + * 32 bits tag ("alac") + * 32 bits tag version (0) + * 32 bits samples per frame (used when not set explicitly in the frames) + * 8 bits compatible version (0) + * 8 bits sample size + * 8 bits history mult (40) + * 8 bits initial history (14) + * 8 bits rice param limit (10) + * 8 bits channels + * 16 bits maxRun (255) + * 32 bits max coded frame size (0 means unknown) + * 32 bits average bitrate (0 means unknown) + * 32 bits samplerate */ #include @@ -58,7 +58,7 @@ #define ALAC_EXTRADATA_SIZE 36 -typedef struct { +typedef struct ALACContext { AVCodecContext *avctx; GetBitContext gb; int channels; @@ -447,6 +447,10 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "no end tag found. incomplete packet.\n"); return AVERROR_INVALIDDATA; } + if (!alac->nb_samples) { + av_log(avctx, AV_LOG_ERROR, "No decodable data in the packet\n"); + return AVERROR_INVALIDDATA; + } if (avpkt->size * 8 - get_bits_count(&alac->gb) > 8) { av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n", @@ -587,5 +591,5 @@ AVCodec ff_alac_decoder = { .init = alac_decode_init, .close = alac_decode_close, .decode = alac_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c index 401f26f..d921fa1 100644 --- a/libavcodec/alacenc.c +++ b/libavcodec/alacenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" + #include "avcodec.h" #include "put_bits.h" #include "internal.h" @@ -57,6 +59,8 @@ typedef struct AlacLPCContext { } AlacLPCContext; typedef struct AlacEncodeContext { + const AVClass *class; + AVCodecContext *avctx; int frame_size; /**< current frame size */ int verbatim; /**< current frame verbatim mode flag */ int compression_level; @@ -73,12 +77,11 @@ typedef struct AlacEncodeContext { RiceContext rc; AlacLPCContext lpc[2]; LPCContext lpc_ctx; - AVCodecContext *avctx; } AlacEncodeContext; static void init_sample_buffers(AlacEncodeContext *s, int channels, - uint8_t const *samples[2]) + const uint8_t *samples[2]) { int ch, i; int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 - @@ -361,7 +364,7 @@ static void write_element(AlacEncodeContext *s, enum AlacRawDataBlockType element, int instance, const uint8_t *samples0, const uint8_t *samples1) { - uint8_t const *samples[2] = { samples0, samples1 }; + const uint8_t *samples[2] = { samples0, samples1 }; int i, j, channels; int prediction_type = 0; PutBitContext *pb = &s->pbctx; @@ -373,14 +376,14 @@ static void write_element(AlacEncodeContext *s, /* samples are channel-interleaved in verbatim mode */ if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P) { int shift = 32 - s->avctx->bits_per_raw_sample; - int32_t const *samples_s32[2] = { (const int32_t *)samples0, + const int32_t *samples_s32[2] = { (const int32_t *)samples0, (const int32_t *)samples1 }; for (i = 0; i < s->frame_size; i++) for (j = 0; j < channels; j++) put_sbits(pb, s->avctx->bits_per_raw_sample, samples_s32[j][i] >> shift); } else { - int16_t const *samples_s16[2] = { (const int16_t *)samples0, + const int16_t *samples_s16[2] = { (const int16_t *)samples0, (const int16_t *)samples1 }; for (i = 0; i < s->frame_size; i++) for (j = 0; j < channels; j++) @@ -483,7 +486,6 @@ static av_cold int alac_encode_close(AVCodecContext *avctx) ff_lpc_end(&s->lpc_ctx); av_freep(&avctx->extradata); avctx->extradata_size = 0; - av_freep(&avctx->coded_frame); return 0; } @@ -520,7 +522,7 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) avctx->channels, avctx->bits_per_raw_sample); - avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { ret = AVERROR(ENOMEM); goto error; @@ -545,7 +547,8 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) AV_WB8(alac_extradata+20, s->rc.k_modifier); } - s->min_prediction_order = DEFAULT_MIN_PRED_ORDER; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->min_prediction_order >= 0) { if (avctx->min_prediction_order < MIN_LPC_ORDER || avctx->min_prediction_order > ALAC_MAX_LPC_ORDER) { @@ -558,7 +561,6 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) s->min_prediction_order = avctx->min_prediction_order; } - s->max_prediction_order = DEFAULT_MAX_PRED_ORDER; if (avctx->max_prediction_order >= 0) { if (avctx->max_prediction_order < MIN_LPC_ORDER || avctx->max_prediction_order > ALAC_MAX_LPC_ORDER) { @@ -570,6 +572,8 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) s->max_prediction_order = avctx->max_prediction_order; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (s->max_prediction_order < s->min_prediction_order) { av_log(avctx, AV_LOG_ERROR, @@ -579,12 +583,6 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) goto error; } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - ret = AVERROR(ENOMEM); - goto error; - } - s->avctx = avctx; if ((ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, @@ -641,16 +639,33 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } +#define OFFSET(x) offsetof(AlacEncodeContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "min_prediction_order", NULL, OFFSET(min_prediction_order), AV_OPT_TYPE_INT, { .i64 = DEFAULT_MIN_PRED_ORDER }, MIN_LPC_ORDER, ALAC_MAX_LPC_ORDER, AE }, + { "max_prediction_order", NULL, OFFSET(max_prediction_order), AV_OPT_TYPE_INT, { .i64 = DEFAULT_MAX_PRED_ORDER }, MIN_LPC_ORDER, ALAC_MAX_LPC_ORDER, AE }, + + { NULL }, +}; + +static const AVClass alacenc_class = { + .class_name = "alacenc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_alac_encoder = { .name = "alac", .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_ALAC, .priv_data_size = sizeof(AlacEncodeContext), + .priv_class = &alacenc_class, .init = alac_encode_init, .encode2 = alac_encode_frame, .close = alac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .channel_layouts = ff_alac_channel_layouts, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P, diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c index 8969e17..8c18924 100644 --- a/libavcodec/aliaspixdec.c +++ b/libavcodec/aliaspixdec.c @@ -124,5 +124,5 @@ AVCodec ff_alias_pix_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_ALIAS_PIX, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c index 47e0612..63016af 100644 --- a/libavcodec/aliaspixenc.c +++ b/libavcodec/aliaspixenc.c @@ -27,22 +27,18 @@ #define ALIAS_HEADER_SIZE 10 -static av_cold int encode_init(AVCodecContext *avctx) -{ - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - return 0; -} - static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { int width, height, bits_pixel, i, j, length, ret; uint8_t *in_buf, *buf; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif width = avctx->width; height = avctx->height; @@ -114,20 +110,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - AVCodec ff_alias_pix_encoder = { .name = "alias_pix", .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_ALIAS_PIX, - .init = encode_init, .encode2 = encode_frame, - .close = encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 6a71b2c..e259de2 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -58,13 +58,6 @@ av_register_codec_parser(&ff_##x##_parser); \ } -#define REGISTER_BSF(X, x) \ - { \ - extern AVBitStreamFilter ff_##x##_bsf; \ - if (CONFIG_##X##_BSF) \ - av_register_bitstream_filter(&ff_##x##_bsf); \ - } - void avcodec_register_all(void) { static int initialized; @@ -75,21 +68,33 @@ void avcodec_register_all(void) /* hardware accelerators */ REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); - REGISTER_HWACCEL(H263_VDPAU, h263_vdpau); + REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); + REGISTER_HWACCEL(H264_MMAL, h264_mmal); + REGISTER_HWACCEL(H264_QSV, h264_qsv); REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); REGISTER_HWACCEL(H264_VDA, h264_vda); REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); + REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va); + REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); + REGISTER_HWACCEL(HEVC_QSV, hevc_qsv); + REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau); REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); + REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va); REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); + REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal); + REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv); REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi); REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau); REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); + REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); + REGISTER_HWACCEL(VC1_MMAL, vc1_mmal); + REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); @@ -124,6 +129,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); REGISTER_DECODER(CSCD, cscd); REGISTER_DECODER(CYUV, cyuv); + REGISTER_DECODER(DDS, dds); REGISTER_DECODER(DFA, dfa); REGISTER_ENCDEC (DNXHD, dnxhd); REGISTER_ENCDEC (DPX, dpx); @@ -131,6 +137,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (DVVIDEO, dvvideo); REGISTER_DECODER(DXA, dxa); REGISTER_DECODER(DXTORY, dxtory); + REGISTER_DECODER(DXV, dxv); REGISTER_DECODER(EACMV, eacmv); REGISTER_DECODER(EAMAD, eamad); REGISTER_DECODER(EATGQ, eatgq); @@ -159,8 +166,14 @@ void avcodec_register_all(void) REGISTER_DECODER(H263I, h263i); REGISTER_ENCODER(H263P, h263p); REGISTER_DECODER(H264, h264); + REGISTER_DECODER(H264_MMAL, h264_mmal); + REGISTER_DECODER(H264_QSV, h264_qsv); + REGISTER_ENCDEC (HAP, hap); REGISTER_DECODER(HEVC, hevc); + REGISTER_DECODER(HEVC_QSV, hevc_qsv); REGISTER_DECODER(HNM4_VIDEO, hnm4_video); + REGISTER_DECODER(HQ_HQA, hq_hqa); + REGISTER_DECODER(HQX, hqx); REGISTER_ENCDEC (HUFFYUV, huffyuv); REGISTER_DECODER(IDCIN, idcin); REGISTER_DECODER(IFF_BYTERUN1, iff_byterun1); @@ -178,6 +191,7 @@ void avcodec_register_all(void) REGISTER_DECODER(LAGARITH, lagarith); REGISTER_ENCODER(LJPEG, ljpeg); REGISTER_DECODER(LOCO, loco); + REGISTER_DECODER(MAGICYUV, magicyuv); REGISTER_DECODER(MDEC, mdec); REGISTER_DECODER(MIMIC, mimic); REGISTER_ENCDEC (MJPEG, mjpeg); @@ -189,6 +203,8 @@ void avcodec_register_all(void) #endif /* FF_API_XVMC */ REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video); REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video); + REGISTER_DECODER(MPEG2_MMAL, mpeg2_mmal); + REGISTER_DECODER(MPEG2_QSV, mpeg2_qsv); REGISTER_ENCDEC (MPEG4, mpeg4); REGISTER_DECODER(MSA1, msa1); REGISTER_DECODER(MSMPEG4V1, msmpeg4v1); @@ -224,12 +240,14 @@ void avcodec_register_all(void) REGISTER_DECODER(RL2, rl2); REGISTER_ENCDEC (ROQ, roq); REGISTER_DECODER(RPZA, rpza); + REGISTER_DECODER(RSCC, rscc); REGISTER_ENCDEC (RV10, rv10); REGISTER_ENCDEC (RV20, rv20); REGISTER_DECODER(RV30, rv30); REGISTER_DECODER(RV40, rv40); REGISTER_DECODER(S302M, s302m); REGISTER_DECODER(SANM, sanm); + REGISTER_DECODER(SCREENPRESSO, screenpresso); REGISTER_ENCDEC (SGI, sgi); REGISTER_DECODER(SGIRLE, sgirle); REGISTER_DECODER(SMACKER, smacker); @@ -239,6 +257,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (SVQ1, svq1); REGISTER_DECODER(SVQ3, svq3); REGISTER_ENCDEC (TARGA, targa); + REGISTER_DECODER(TDSC, tdsc); REGISTER_DECODER(THEORA, theora); REGISTER_DECODER(THP, thp); REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo); @@ -246,6 +265,7 @@ void avcodec_register_all(void) REGISTER_DECODER(TMV, tmv); REGISTER_DECODER(TRUEMOTION1, truemotion1); REGISTER_DECODER(TRUEMOTION2, truemotion2); + REGISTER_DECODER(TRUEMOTION2RT, truemotion2rt); REGISTER_DECODER(TSCC, tscc); REGISTER_DECODER(TSCC2, tscc2); REGISTER_DECODER(TXD, txd); @@ -258,6 +278,7 @@ void avcodec_register_all(void) REGISTER_DECODER(VBLE, vble); REGISTER_DECODER(VC1, vc1); REGISTER_DECODER(VC1IMAGE, vc1image); + REGISTER_DECODER(VC1_MMAL, vc1_mmal); REGISTER_DECODER(VCR1, vcr1); REGISTER_DECODER(VMDVIDEO, vmdvideo); REGISTER_DECODER(VMNC, vmnc); @@ -271,6 +292,7 @@ void avcodec_register_all(void) REGISTER_DECODER(VP9, vp9); REGISTER_DECODER(VQA, vqa); REGISTER_DECODER(WEBP, webp); + REGISTER_ENCODER(WRAPPED_AVFRAME, wrapped_avframe); REGISTER_ENCDEC (WMV1, wmv1); REGISTER_ENCDEC (WMV2, wmv2); REGISTER_DECODER(WMV3, wmv3); @@ -305,9 +327,10 @@ void avcodec_register_all(void) REGISTER_DECODER(COOK, cook); REGISTER_DECODER(DCA, dca); REGISTER_DECODER(DSICINAUDIO, dsicinaudio); + REGISTER_DECODER(DSS_SP, dss_sp); REGISTER_ENCDEC (EAC3, eac3); REGISTER_ENCDEC (FLAC, flac); - REGISTER_DECODER(G723_1, g723_1); + REGISTER_ENCDEC (G723_1, g723_1); REGISTER_DECODER(GSM, gsm); REGISTER_DECODER(GSM_MS, gsm_ms); REGISTER_DECODER(IAC, iac); @@ -368,6 +391,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (PCM_S8, pcm_s8); REGISTER_DECODER(PCM_S8_PLANAR, pcm_s8_planar); REGISTER_ENCDEC (PCM_S16BE, pcm_s16be); + REGISTER_DECODER(PCM_S16BE_PLANAR, pcm_s16be_planar); REGISTER_ENCDEC (PCM_S16LE, pcm_s16le); REGISTER_DECODER(PCM_S16LE_PLANAR, pcm_s16le_planar); REGISTER_ENCDEC (PCM_S24BE, pcm_s24be); @@ -434,6 +458,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (XSUB, xsub); /* external libraries */ + REGISTER_DECODER(LIBDCADEC, libdcadec) REGISTER_ENCODER(LIBFAAC, libfaac); REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); REGISTER_ENCDEC (LIBGSM, libgsm); @@ -455,11 +480,31 @@ void avcodec_register_all(void) REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9); REGISTER_ENCODER(LIBWAVPACK, libwavpack); REGISTER_ENCODER(LIBWEBP, libwebp); + REGISTER_ENCODER(LIBX262, libx262); REGISTER_ENCODER(LIBX264, libx264); REGISTER_ENCODER(LIBX265, libx265); REGISTER_ENCODER(LIBXAVS, libxavs); REGISTER_ENCODER(LIBXVID, libxvid); + /* external libraries, that shouldn't be used by default if one of the + * above is available */ + REGISTER_ENCDEC (LIBOPENH264, libopenh264); + REGISTER_ENCODER(H264_NVENC, h264_nvenc); + REGISTER_ENCODER(H264_OMX, h264_omx); + REGISTER_ENCODER(H264_QSV, h264_qsv); + REGISTER_ENCODER(H264_VAAPI, h264_vaapi); + REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); + REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc); + REGISTER_ENCODER(HEVC_QSV, hevc_qsv); + REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); + REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); + REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv); + REGISTER_ENCODER(MPEG4_OMX, mpeg4_omx); +#if FF_API_NVENC_OLD_NAME + REGISTER_ENCODER(NVENC_H264, nvenc_h264); + REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); +#endif + /* parsers */ REGISTER_PARSER(AAC, aac); REGISTER_PARSER(AAC_LATM, aac_latm); @@ -471,6 +516,7 @@ void avcodec_register_all(void) REGISTER_PARSER(DCA, dca); REGISTER_PARSER(DIRAC, dirac); REGISTER_PARSER(DNXHD, dnxhd); + REGISTER_PARSER(DPX, dpx); REGISTER_PARSER(DVBSUB, dvbsub); REGISTER_PARSER(DVDSUB, dvdsub); REGISTER_PARSER(FLAC, flac); @@ -494,17 +540,4 @@ void avcodec_register_all(void) REGISTER_PARSER(VORBIS, vorbis); REGISTER_PARSER(VP3, vp3); REGISTER_PARSER(VP8, vp8); - - /* bitstream filters */ - REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc); - REGISTER_BSF(CHOMP, chomp); - REGISTER_BSF(DUMP_EXTRADATA, dump_extradata); - REGISTER_BSF(H264_MP4TOANNEXB, h264_mp4toannexb); - REGISTER_BSF(IMX_DUMP_HEADER, imx_dump_header); - REGISTER_BSF(MJPEG2JPEG, mjpeg2jpeg); - REGISTER_BSF(MJPEGA_DUMP_HEADER, mjpega_dump_header); - REGISTER_BSF(MOV2TEXTSUB, mov2textsub); - REGISTER_BSF(NOISE, noise); - REGISTER_BSF(REMOVE_EXTRADATA, remove_extradata); - REGISTER_BSF(TEXT2MOVSUB, text2movsub); } diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 997c162..f356a70 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -152,7 +152,7 @@ enum RA_Flag { }; -typedef struct { +typedef struct ALSSpecificConfig { uint32_t samples; ///< number of samples, 0xFFFFFFFF if unknown int resolution; ///< 000 = 8-bit; 001 = 16-bit; 010 = 24-bit; 011 = 32-bit int floating; ///< 1 = IEEE 32-bit floating-point, 0 = integer @@ -178,7 +178,7 @@ typedef struct { } ALSSpecificConfig; -typedef struct { +typedef struct ALSChannelData { int stop_flag; int master_channel; int time_diff_flag; @@ -188,7 +188,7 @@ typedef struct { } ALSChannelData; -typedef struct { +typedef struct ALSDecContext { AVCodecContext *avctx; ALSSpecificConfig sconf; GetBitContext gb; @@ -227,7 +227,7 @@ typedef struct { } ALSDecContext; -typedef struct { +typedef struct ALSBlockData { unsigned int block_length; ///< number of samples within the block unsigned int ra_block; ///< if true, this is a random access block int *const_block; ///< if true, this is a constant value block @@ -252,24 +252,24 @@ static av_cold void dprint_specific_config(ALSDecContext *ctx) AVCodecContext *avctx = ctx->avctx; ALSSpecificConfig *sconf = &ctx->sconf; - av_dlog(avctx, "resolution = %i\n", sconf->resolution); - av_dlog(avctx, "floating = %i\n", sconf->floating); - av_dlog(avctx, "frame_length = %i\n", sconf->frame_length); - av_dlog(avctx, "ra_distance = %i\n", sconf->ra_distance); - av_dlog(avctx, "ra_flag = %i\n", sconf->ra_flag); - av_dlog(avctx, "adapt_order = %i\n", sconf->adapt_order); - av_dlog(avctx, "coef_table = %i\n", sconf->coef_table); - av_dlog(avctx, "long_term_prediction = %i\n", sconf->long_term_prediction); - av_dlog(avctx, "max_order = %i\n", sconf->max_order); - av_dlog(avctx, "block_switching = %i\n", sconf->block_switching); - av_dlog(avctx, "bgmc = %i\n", sconf->bgmc); - av_dlog(avctx, "sb_part = %i\n", sconf->sb_part); - av_dlog(avctx, "joint_stereo = %i\n", sconf->joint_stereo); - av_dlog(avctx, "mc_coding = %i\n", sconf->mc_coding); - av_dlog(avctx, "chan_config = %i\n", sconf->chan_config); - av_dlog(avctx, "chan_sort = %i\n", sconf->chan_sort); - av_dlog(avctx, "RLSLMS = %i\n", sconf->rlslms); - av_dlog(avctx, "chan_config_info = %i\n", sconf->chan_config_info); + ff_dlog(avctx, "resolution = %i\n", sconf->resolution); + ff_dlog(avctx, "floating = %i\n", sconf->floating); + ff_dlog(avctx, "frame_length = %i\n", sconf->frame_length); + ff_dlog(avctx, "ra_distance = %i\n", sconf->ra_distance); + ff_dlog(avctx, "ra_flag = %i\n", sconf->ra_flag); + ff_dlog(avctx, "adapt_order = %i\n", sconf->adapt_order); + ff_dlog(avctx, "coef_table = %i\n", sconf->coef_table); + ff_dlog(avctx, "long_term_prediction = %i\n", sconf->long_term_prediction); + ff_dlog(avctx, "max_order = %i\n", sconf->max_order); + ff_dlog(avctx, "block_switching = %i\n", sconf->block_switching); + ff_dlog(avctx, "bgmc = %i\n", sconf->bgmc); + ff_dlog(avctx, "sb_part = %i\n", sconf->sb_part); + ff_dlog(avctx, "joint_stereo = %i\n", sconf->joint_stereo); + ff_dlog(avctx, "mc_coding = %i\n", sconf->mc_coding); + ff_dlog(avctx, "chan_config = %i\n", sconf->chan_config); + ff_dlog(avctx, "chan_sort = %i\n", sconf->chan_sort); + ff_dlog(avctx, "RLSLMS = %i\n", sconf->rlslms); + ff_dlog(avctx, "chan_config_info = %i\n", sconf->chan_config_info); #endif } @@ -305,7 +305,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) skip_bits_long(&gb, 32); // sample rate already known sconf->samples = get_bits_long(&gb, 32); avctx->channels = m4ac.channels; - skip_bits(&gb, 16); // number of channels already knwon + skip_bits(&gb, 16); // number of channels already known skip_bits(&gb, 3); // skip file_type sconf->resolution = get_bits(&gb, 3); sconf->floating = get_bits1(&gb); @@ -1812,5 +1812,5 @@ AVCodec ff_als_decoder = { .close = decode_end, .decode = decode_frame, .flush = flush, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c index 7692cf0..e2b5641 100644 --- a/libavcodec/amrnbdec.c +++ b/libavcodec/amrnbdec.c @@ -532,13 +532,13 @@ static void decode_fixed_sparse(AMRFixed *fixed_sparse, const uint16_t *pulses, * @param p the context * @param subframe unpacked amr subframe * @param mode mode of the current frame - * @param fixed_sparse sparse respresentation of the fixed vector + * @param fixed_sparse sparse representation of the fixed vector */ static void pitch_sharpening(AMRContext *p, int subframe, enum Mode mode, AMRFixed *fixed_sparse) { // The spec suggests the current pitch gain is always used, but in other - // modes the pitch and codebook gains are joinly quantized (sec 5.8.2) + // modes the pitch and codebook gains are jointly quantized (sec 5.8.2) // so the codebook gain cannot depend on the quantized pitch gain. if (mode == MODE_12k2) p->beta = FFMIN(p->pitch_gain[4], 1.0); @@ -1070,7 +1070,7 @@ AVCodec ff_amrnb_decoder = { .priv_data_size = sizeof(AMRContext), .init = amrnb_decode_init, .decode = amrnb_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/amrwbdata.h b/libavcodec/amrwbdata.h index 81f8b47..c0078b3 100644 --- a/libavcodec/amrwbdata.h +++ b/libavcodec/amrwbdata.h @@ -38,7 +38,7 @@ #define MIN_ISF_SPACING (128.0 / 32768.0) ///< minimum isf gap #define PRED_FACTOR (1.0 / 3.0) -#define MIN_ENERGY -14.0 ///< initial innnovation energy (dB) +#define MIN_ENERGY -14.0 ///< initial innovation energy (dB) #define ENERGY_MEAN 30.0 ///< mean innovation energy (dB) in all modes #define PREEMPH_FAC 0.68 ///< factor used to de-emphasize synthesis diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c index 668c84d..f1fbcc0 100644 --- a/libavcodec/amrwbdec.c +++ b/libavcodec/amrwbdec.c @@ -42,7 +42,7 @@ #include "amrwbdata.h" -typedef struct { +typedef struct AMRWBContext { AMRWBFrame frame; ///< AMRWB parameters decoded from bitstream enum Mode fr_cur_mode; ///< mode index of current frame uint8_t fr_quality; ///< frame quality index (FQI) @@ -138,7 +138,6 @@ static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf) * * @param[in] ind Array of 5 indexes * @param[out] isf_q Buffer for isf_q[LP_ORDER] - * */ static void decode_isf_indices_36b(uint16_t *ind, float *isf_q) { @@ -165,7 +164,6 @@ static void decode_isf_indices_36b(uint16_t *ind, float *isf_q) * * @param[in] ind Array of 7 indexes * @param[out] isf_q Buffer for isf_q[LP_ORDER] - * */ static void decode_isf_indices_46b(uint16_t *ind, float *isf_q) { @@ -199,7 +197,6 @@ static void decode_isf_indices_46b(uint16_t *ind, float *isf_q) * * @param[in,out] isf_q Current quantized ISF * @param[in,out] isf_past Past quantized ISF - * */ static void isf_add_mean_and_past(float *isf_q, float *isf_past) { @@ -1254,7 +1251,7 @@ AVCodec ff_amrwb_decoder = { .priv_data_size = sizeof(AMRWBContext), .init = amrwb_decode_init, .decode = amrwb_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/anm.c b/libavcodec/anm.c index 3d5affb..b70d220 100644 --- a/libavcodec/anm.c +++ b/libavcodec/anm.c @@ -198,5 +198,5 @@ AVCodec ff_anm_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index 556bfe4..65e2e16 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -49,7 +49,7 @@ static const uint8_t ansi_to_cga[16] = { 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 }; -typedef struct { +typedef struct AnsiContext { AVFrame *frame; int x; /**< x cursor position (pixels) */ int y; /**< y cursor position (pixels) */ @@ -189,7 +189,7 @@ static int execute_code(AVCodecContext * avctx, int c) s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0; s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH, 0, avctx->width - FONT_WIDTH) : 0; break; - case 'h': //set creen mode + case 'h': //set screen mode case 'l': //reset screen mode if (s->nb_args < 2) s->args[0] = DEFAULT_SCREEN_MODE; @@ -450,5 +450,5 @@ AVCodec ff_ansi_decoder = { .init = decode_init, .close = decode_close, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 131c6f3..2f64488 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -359,10 +359,10 @@ static inline void range_dec_normalize(APEContext *ctx) } /** - * Calculate culmulative frequency for next symbol. Does NO update! + * Calculate cumulative frequency for next symbol. Does NO update! * @param ctx decoder context * @param tot_f is the total frequency or (code_value)1<adaptcoeffs = ((res & (-1<<31)) ^ (-1<<30)) >> - (25 + (absres <= f->avg*3) + (absres <= f->avg*4/3)); + *f->adaptcoeffs = APESIGN(res) * + (8 << ((absres > f->avg * 3) + (absres > f->avg * 4 / 3))); + /* equivalent to the following code + if (absres <= f->avg * 4 / 3) + *f->adaptcoeffs = APESIGN(res) * 8; + else if (absres <= f->avg * 3) + *f->adaptcoeffs = APESIGN(res) * 16; + else + *f->adaptcoeffs = APESIGN(res) * 32; + */ else *f->adaptcoeffs = 0; @@ -1596,7 +1604,8 @@ AVCodec ff_ape_decoder = { .init = ape_decode_init, .close = ape_decode_close, .decode = ape_decode_frame, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_DR1, .flush = ape_flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index 6cbb0b9..bd4dd4e 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -1,7 +1,5 @@ ARCH_HEADERS = mathops.h -OBJS += arm/fmtconvert_init_arm.o - # subsystems OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_init_arm.o \ arm/ac3dsp_arm.o @@ -9,6 +7,10 @@ OBJS-$(CONFIG_AUDIODSP) += arm/audiodsp_init_arm.o OBJS-$(CONFIG_BLOCKDSP) += arm/blockdsp_init_arm.o OBJS-$(CONFIG_FFT) += arm/fft_init_arm.o \ arm/fft_fixed_init_arm.o +OBJS-$(CONFIG_FLACDSP) += arm/flacdsp_init_arm.o \ + arm/flacdsp_arm.o +OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_init_arm.o +OBJS-$(CONFIG_G722DSP) += arm/g722dsp_init_arm.o OBJS-$(CONFIG_H264CHROMA) += arm/h264chroma_init_arm.o OBJS-$(CONFIG_H264DSP) += arm/h264dsp_init_arm.o OBJS-$(CONFIG_H264PRED) += arm/h264pred_init_arm.o @@ -19,31 +21,30 @@ OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_arm.o \ arm/idctdsp_arm.o \ arm/jrevdct_arm.o \ arm/simple_idct_arm.o +OBJS-$(CONFIG_MDCT) += arm/mdct_init_arm.o \ + arm/mdct_fixed_init_arm.o OBJS-$(CONFIG_ME_CMP) += arm/me_cmp_init_arm.o OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_init_arm.o OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_arm.o OBJS-$(CONFIG_MPEGVIDEOENC) += arm/mpegvideoencdsp_init_arm.o OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o OBJS-$(CONFIG_PIXBLOCKDSP) += arm/pixblockdsp_init_arm.o +OBJS-$(CONFIG_RDFT) += arm/rdft_init_arm.o +OBJS-$(CONFIG_RV34DSP) += arm/rv34dsp_init_arm.o +OBJS-$(CONFIG_VC1DSP) += arm/vc1dsp_init_arm.o OBJS-$(CONFIG_VIDEODSP) += arm/videodsp_init_arm.o OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_init_arm.o +OBJS-$(CONFIG_VP8DSP) += arm/vp8dsp_init_arm.o # decoders/encoders OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ arm/sbrdsp_init_arm.o OBJS-$(CONFIG_APE_DECODER) += arm/apedsp_init_arm.o OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o -OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \ - arm/flacdsp_arm.o OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o -OBJS-$(CONFIG_VC1_DECODER) += arm/vc1dsp_init_arm.o +OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o OBJS-$(CONFIG_VP6_DECODER) += arm/vp6dsp_init_arm.o -OBJS-$(CONFIG_VP7_DECODER) += arm/vp8dsp_init_arm.o -OBJS-$(CONFIG_VP8_DECODER) += arm/vp8dsp_init_arm.o -OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_init_arm.o -OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_init_arm.o \ - arm/rv40dsp_init_arm.o # ARMv5 optimizations @@ -71,25 +72,21 @@ ARMV6-OBJS-$(CONFIG_ME_CMP) += arm/me_cmp_armv6.o ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o ARMV6-OBJS-$(CONFIG_MPEGVIDEOENC) += arm/mpegvideoencdsp_armv6.o ARMV6-OBJS-$(CONFIG_PIXBLOCKDSP) += arm/pixblockdsp_armv6.o - -# decoders/encoders -ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o ARMV6-OBJS-$(CONFIG_STARTCODE) += arm/startcode_armv6.o -ARMV6-OBJS-$(CONFIG_VP7_DECODER) += arm/vp8_armv6.o \ - arm/vp8dsp_init_armv6.o \ - arm/vp8dsp_armv6.o -ARMV6-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8_armv6.o \ +ARMV6-OBJS-$(CONFIG_VP8DSP) += arm/vp8_armv6.o \ arm/vp8dsp_init_armv6.o \ arm/vp8dsp_armv6.o +# decoders/encoders +ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o + # VFP optimizations -VFP-OBJS += arm/fmtconvert_vfp.o # subsystems VFP-OBJS-$(CONFIG_FFT) += arm/fft_vfp.o +VFP-OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_vfp.o VFP-OBJS-$(CONFIG_MDCT) += arm/mdct_vfp.o -VFP-OBJS-$(HAVE_ARMV6) += arm/fmtconvert_vfp_armv6.o # decoders/encoders VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_vfp.o \ @@ -97,7 +94,6 @@ VFP-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_vfp.o \ # NEON optimizations -NEON-OBJS += arm/fmtconvert_neon.o # subsystems NEON-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_neon.o @@ -108,6 +104,8 @@ NEON-OBJS-$(CONFIG_BLOCKDSP) += arm/blockdsp_init_neon.o \ arm/blockdsp_neon.o NEON-OBJS-$(CONFIG_FFT) += arm/fft_neon.o \ arm/fft_fixed_neon.o +NEON-OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_neon.o +NEON-OBJS-$(CONFIG_G722DSP) += arm/g722dsp_neon.o NEON-OBJS-$(CONFIG_H264CHROMA) += arm/h264cmc_neon.o NEON-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_neon.o \ arm/h264idct_neon.o @@ -123,7 +121,11 @@ NEON-OBJS-$(CONFIG_MDCT) += arm/mdct_neon.o \ arm/mdct_fixed_neon.o NEON-OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_neon.o NEON-OBJS-$(CONFIG_RDFT) += arm/rdft_neon.o +NEON-OBJS-$(CONFIG_VC1DSP) += arm/vc1dsp_init_neon.o \ + arm/vc1dsp_neon.o NEON-OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_neon.o +NEON-OBJS-$(CONFIG_VP8DSP) += arm/vp8dsp_init_neon.o \ + arm/vp8dsp_neon.o # decoders/encoders NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ @@ -134,11 +136,5 @@ NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o -NEON-OBJS-$(CONFIG_VC1_DECODER) += arm/vc1dsp_init_neon.o \ - arm/vc1dsp_neon.o NEON-OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_neon.o NEON-OBJS-$(CONFIG_VP6_DECODER) += arm/vp6dsp_neon.o -NEON-OBJS-$(CONFIG_VP7_DECODER) += arm/vp8dsp_init_neon.o \ - arm/vp8dsp_neon.o -NEON-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8dsp_init_neon.o \ - arm/vp8dsp_neon.o diff --git a/libavcodec/arm/dcadsp_init_arm.c b/libavcodec/arm/dcadsp_init_arm.c index 5400484..bf0d9b4 100644 --- a/libavcodec/arm/dcadsp_init_arm.c +++ b/libavcodec/arm/dcadsp_init_arm.c @@ -49,17 +49,11 @@ void ff_synth_filter_float_neon(FFTContext *imdct, float out[32], const float in[32], float scale); -void ff_decode_hf_neon(float dst[DCA_SUBBANDS][8], - const int32_t vq_num[DCA_SUBBANDS], - const int8_t hf_vq[1024][32], intptr_t vq_offset, - int32_t scale[DCA_SUBBANDS][2], - intptr_t start, intptr_t end); - av_cold void ff_dcadsp_init_arm(DCADSPContext *s) { int cpu_flags = av_get_cpu_flags(); - if (have_vfp(cpu_flags) && !have_vfpv3(cpu_flags)) { + if (have_vfp_vm(cpu_flags)) { s->lfe_fir[0] = ff_dca_lfe_fir32_vfp; s->lfe_fir[1] = ff_dca_lfe_fir64_vfp; s->qmf_32_subbands = ff_dca_qmf_32_subbands_vfp; @@ -67,7 +61,6 @@ av_cold void ff_dcadsp_init_arm(DCADSPContext *s) if (have_neon(cpu_flags)) { s->lfe_fir[0] = ff_dca_lfe_fir0_neon; s->lfe_fir[1] = ff_dca_lfe_fir1_neon; - s->decode_hf = ff_decode_hf_neon; } } @@ -75,7 +68,7 @@ av_cold void ff_synth_filter_init_arm(SynthFilterContext *s) { int cpu_flags = av_get_cpu_flags(); - if (have_vfp(cpu_flags) && !have_vfpv3(cpu_flags)) + if (have_vfp_vm(cpu_flags)) s->synth_filter_float = ff_synth_filter_float_vfp; if (have_neon(cpu_flags)) s->synth_filter_float = ff_synth_filter_float_neon; diff --git a/libavcodec/arm/dcadsp_neon.S b/libavcodec/arm/dcadsp_neon.S index 70580cd..735c4c2 100644 --- a/libavcodec/arm/dcadsp_neon.S +++ b/libavcodec/arm/dcadsp_neon.S @@ -20,35 +20,6 @@ #include "libavutil/arm/asm.S" -function ff_decode_hf_neon, export=1 - push {r4-r5,lr} - add r2, r2, r3 - ldr r3, [sp, #12] - ldrd r4, r5, [sp, #16] - add r3, r3, r4, lsl #3 - add r1, r1, r4, lsl #2 - add r0, r0, r4, lsl #5 - -1: ldr_post lr, r1, #4 - add r4, r4, #1 - add lr, r2, lr, lsl #5 - cmp r4, r5 - vld1.32 {d7}, [r3]! - vld1.8 {d0}, [lr,:64] - vcvt.f32.s32 d7, d7, #4 - vmovl.s8 q1, d0 - vmovl.s16 q0, d2 - vmovl.s16 q1, d3 - vcvt.f32.s32 q0, q0 - vcvt.f32.s32 q1, q1 - vmul.f32 q0, q0, d7[0] - vmul.f32 q1, q1, d7[0] - vst1.32 {q0-q1}, [r0,:128]! - bne 1b - - pop {r4-r5,pc} -endfunc - function ff_dca_lfe_fir0_neon, export=1 push {r4-r6,lr} mov r3, #32 @ decifactor diff --git a/libavcodec/arm/fft_fixed_init_arm.c b/libavcodec/arm/fft_fixed_init_arm.c index 2f749e4..5132b09 100644 --- a/libavcodec/arm/fft_fixed_init_arm.c +++ b/libavcodec/arm/fft_fixed_init_arm.c @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" #include "libavutil/arm/cpu.h" #define FFT_FLOAT 0 #include "libavcodec/fft.h" void ff_fft_fixed_calc_neon(FFTContext *s, FFTComplex *z); -void ff_mdct_fixed_calc_neon(FFTContext *s, FFTSample *o, const FFTSample *i); -void ff_mdct_fixed_calcw_neon(FFTContext *s, FFTDouble *o, const FFTSample *i); av_cold void ff_fft_fixed_init_arm(FFTContext *s) { @@ -34,13 +34,5 @@ av_cold void ff_fft_fixed_init_arm(FFTContext *s) if (have_neon(cpu_flags)) { s->fft_permutation = FF_FFT_PERM_SWAP_LSBS; s->fft_calc = ff_fft_fixed_calc_neon; - -#if CONFIG_MDCT - if (!s->inverse && s->nbits >= 3) { - s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; - s->mdct_calc = ff_mdct_fixed_calc_neon; - s->mdct_calcw = ff_mdct_fixed_calcw_neon; - } -#endif } } diff --git a/libavcodec/arm/fft_fixed_neon.S b/libavcodec/arm/fft_fixed_neon.S index faddc00..c70a189 100644 --- a/libavcodec/arm/fft_fixed_neon.S +++ b/libavcodec/arm/fft_fixed_neon.S @@ -242,7 +242,7 @@ function ff_fft_fixed_calc_neon, export=1 bx r3 endfunc -const fft_fixed_tab_neon +const fft_fixed_tab_neon, relocate=1 .word fft4_neon .word fft8_neon .word fft16_neon diff --git a/libavcodec/arm/fft_init_arm.c b/libavcodec/arm/fft_init_arm.c index bc143c1..4d047ea 100644 --- a/libavcodec/arm/fft_init_arm.c +++ b/libavcodec/arm/fft_init_arm.c @@ -18,53 +18,27 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" #include "libavutil/arm/cpu.h" + #include "libavcodec/fft.h" -#include "libavcodec/rdft.h" -#include "libavcodec/synth_filter.h" void ff_fft_calc_vfp(FFTContext *s, FFTComplex *z); void ff_fft_permute_neon(FFTContext *s, FFTComplex *z); void ff_fft_calc_neon(FFTContext *s, FFTComplex *z); -void ff_imdct_half_vfp(FFTContext *s, FFTSample *output, const FFTSample *input); - -void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); - -void ff_rdft_calc_neon(struct RDFTContext *s, FFTSample *z); - av_cold void ff_fft_init_arm(FFTContext *s) { int cpu_flags = av_get_cpu_flags(); - if (have_vfp(cpu_flags) && !have_vfpv3(cpu_flags)) { + if (have_vfp_vm(cpu_flags)) { s->fft_calc = ff_fft_calc_vfp; -#if CONFIG_MDCT - s->imdct_half = ff_imdct_half_vfp; -#endif } if (have_neon(cpu_flags)) { s->fft_permute = ff_fft_permute_neon; s->fft_calc = ff_fft_calc_neon; -#if CONFIG_MDCT - s->imdct_calc = ff_imdct_calc_neon; - s->imdct_half = ff_imdct_half_neon; - s->mdct_calc = ff_mdct_calc_neon; - s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; -#endif } } - -#if CONFIG_RDFT -av_cold void ff_rdft_init_arm(RDFTContext *s) -{ - int cpu_flags = av_get_cpu_flags(); - - if (have_neon(cpu_flags)) - s->rdft_calc = ff_rdft_calc_neon; -} -#endif diff --git a/libavcodec/arm/fft_neon.S b/libavcodec/arm/fft_neon.S index c4d8918..b161015 100644 --- a/libavcodec/arm/fft_neon.S +++ b/libavcodec/arm/fft_neon.S @@ -348,7 +348,7 @@ function ff_fft_permute_neon, export=1 pop {r4,pc} endfunc -const fft_tab_neon +const fft_tab_neon, relocate=1 .word fft4_neon .word fft8_neon .word fft16_neon diff --git a/libavcodec/arm/fft_vfp.S b/libavcodec/arm/fft_vfp.S index 130d529..c2801fa 100644 --- a/libavcodec/arm/fft_vfp.S +++ b/libavcodec/arm/fft_vfp.S @@ -30,14 +30,10 @@ function ff_fft_calc_vfp, export=1 ldr ip, [a1, #0] @ nbits mov a1, a2 -A ldr pc, [pc, ip, lsl #2] -A .word 0 -A .word 0 -A .word 0 -T movrel a2, (fft_tab_vfp - 8) -T ldr pc, [a2, ip, lsl #2] -T endfunc -T const fft_tab_vfp + movrel a2, (fft_tab_vfp - 8) + ldr pc, [a2, ip, lsl #2] +endfunc +const fft_tab_vfp, relocate=1 .word fft4_vfp .word fft8_vfp .word X(ff_fft16_vfp) @ this one alone is exported @@ -53,7 +49,7 @@ T const fft_tab_vfp .word fft16384_vfp .word fft32768_vfp .word fft65536_vfp -A endfunc +endconst function fft4_vfp vldr d0, [a1, #0*2*4] @ s0,s1 = z[0] diff --git a/libavcodec/arm/fmtconvert_init_arm.c b/libavcodec/arm/fmtconvert_init_arm.c index 7c5bd91..11396e8 100644 --- a/libavcodec/arm/fmtconvert_init_arm.c +++ b/libavcodec/arm/fmtconvert_init_arm.c @@ -25,6 +25,9 @@ #include "libavcodec/avcodec.h" #include "libavcodec/fmtconvert.h" +void ff_int32_to_float_fmul_array8_neon(FmtConvertContext *c, float *dst, + const int32_t *src, const float *mul, + int len); void ff_int32_to_float_fmul_scalar_neon(float *dst, const int32_t *src, float mul, int len); @@ -34,32 +37,19 @@ void ff_int32_to_float_fmul_array8_vfp(FmtConvertContext *c, float *dst, const int32_t *src, const float *mul, int len); -void ff_float_to_int16_neon(int16_t *dst, const float *src, long len); -void ff_float_to_int16_interleave_neon(int16_t *, const float **, long, int); - -void ff_float_to_int16_vfp(int16_t *dst, const float *src, long len); - av_cold void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx) { int cpu_flags = av_get_cpu_flags(); - if (have_vfp(cpu_flags)) { + if (have_vfp_vm(cpu_flags)) { if (!have_vfpv3(cpu_flags)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_vfp; c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_vfp; } - - if (have_armv6(cpu_flags)) { - c->float_to_int16 = ff_float_to_int16_vfp; - } } if (have_neon(cpu_flags)) { + c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_neon; c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_neon; - - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->float_to_int16 = ff_float_to_int16_neon; - c->float_to_int16_interleave = ff_float_to_int16_interleave_neon; - } } } diff --git a/libavcodec/arm/fmtconvert_neon.S b/libavcodec/arm/fmtconvert_neon.S index e11e82c..5d48e3d 100644 --- a/libavcodec/arm/fmtconvert_neon.S +++ b/libavcodec/arm/fmtconvert_neon.S @@ -1,6 +1,7 @@ /* * ARM NEON optimised Format Conversion Utils * Copyright (c) 2008 Mans Rullgard + * Copyright (c) 2015 Janne Grunau b * * This file is part of Libav. * @@ -22,347 +23,6 @@ #include "config.h" #include "libavutil/arm/asm.S" -function ff_float_to_int16_neon, export=1 - subs r2, r2, #8 - vld1.64 {d0-d1}, [r1,:128]! - vcvt.s32.f32 q8, q0, #16 - vld1.64 {d2-d3}, [r1,:128]! - vcvt.s32.f32 q9, q1, #16 - beq 3f - bics ip, r2, #15 - beq 2f -1: subs ip, ip, #16 - vshrn.s32 d4, q8, #16 - vld1.64 {d0-d1}, [r1,:128]! - vcvt.s32.f32 q0, q0, #16 - vshrn.s32 d5, q9, #16 - vld1.64 {d2-d3}, [r1,:128]! - vcvt.s32.f32 q1, q1, #16 - vshrn.s32 d6, q0, #16 - vst1.64 {d4-d5}, [r0,:128]! - vshrn.s32 d7, q1, #16 - vld1.64 {d16-d17},[r1,:128]! - vcvt.s32.f32 q8, q8, #16 - vld1.64 {d18-d19},[r1,:128]! - vcvt.s32.f32 q9, q9, #16 - vst1.64 {d6-d7}, [r0,:128]! - bne 1b - ands r2, r2, #15 - beq 3f -2: vld1.64 {d0-d1}, [r1,:128]! - vshrn.s32 d4, q8, #16 - vcvt.s32.f32 q0, q0, #16 - vld1.64 {d2-d3}, [r1,:128]! - vshrn.s32 d5, q9, #16 - vcvt.s32.f32 q1, q1, #16 - vshrn.s32 d6, q0, #16 - vst1.64 {d4-d5}, [r0,:128]! - vshrn.s32 d7, q1, #16 - vst1.64 {d6-d7}, [r0,:128]! - bx lr -3: vshrn.s32 d4, q8, #16 - vshrn.s32 d5, q9, #16 - vst1.64 {d4-d5}, [r0,:128]! - bx lr -endfunc - -function ff_float_to_int16_interleave_neon, export=1 - cmp r3, #2 - itt lt - ldrlt r1, [r1] - blt X(ff_float_to_int16_neon) - bne 4f - - ldr r3, [r1] - ldr r1, [r1, #4] - - subs r2, r2, #8 - vld1.64 {d0-d1}, [r3,:128]! - vcvt.s32.f32 q8, q0, #16 - vld1.64 {d2-d3}, [r3,:128]! - vcvt.s32.f32 q9, q1, #16 - vld1.64 {d20-d21},[r1,:128]! - vcvt.s32.f32 q10, q10, #16 - vld1.64 {d22-d23},[r1,:128]! - vcvt.s32.f32 q11, q11, #16 - beq 3f - bics ip, r2, #15 - beq 2f -1: subs ip, ip, #16 - vld1.64 {d0-d1}, [r3,:128]! - vcvt.s32.f32 q0, q0, #16 - vsri.32 q10, q8, #16 - vld1.64 {d2-d3}, [r3,:128]! - vcvt.s32.f32 q1, q1, #16 - vld1.64 {d24-d25},[r1,:128]! - vcvt.s32.f32 q12, q12, #16 - vld1.64 {d26-d27},[r1,:128]! - vsri.32 q11, q9, #16 - vst1.64 {d20-d21},[r0,:128]! - vcvt.s32.f32 q13, q13, #16 - vst1.64 {d22-d23},[r0,:128]! - vsri.32 q12, q0, #16 - vld1.64 {d16-d17},[r3,:128]! - vsri.32 q13, q1, #16 - vst1.64 {d24-d25},[r0,:128]! - vcvt.s32.f32 q8, q8, #16 - vld1.64 {d18-d19},[r3,:128]! - vcvt.s32.f32 q9, q9, #16 - vld1.64 {d20-d21},[r1,:128]! - vcvt.s32.f32 q10, q10, #16 - vld1.64 {d22-d23},[r1,:128]! - vcvt.s32.f32 q11, q11, #16 - vst1.64 {d26-d27},[r0,:128]! - bne 1b - ands r2, r2, #15 - beq 3f -2: vsri.32 q10, q8, #16 - vld1.64 {d0-d1}, [r3,:128]! - vcvt.s32.f32 q0, q0, #16 - vld1.64 {d2-d3}, [r3,:128]! - vcvt.s32.f32 q1, q1, #16 - vld1.64 {d24-d25},[r1,:128]! - vcvt.s32.f32 q12, q12, #16 - vsri.32 q11, q9, #16 - vld1.64 {d26-d27},[r1,:128]! - vcvt.s32.f32 q13, q13, #16 - vst1.64 {d20-d21},[r0,:128]! - vsri.32 q12, q0, #16 - vst1.64 {d22-d23},[r0,:128]! - vsri.32 q13, q1, #16 - vst1.64 {d24-d27},[r0,:128]! - bx lr -3: vsri.32 q10, q8, #16 - vsri.32 q11, q9, #16 - vst1.64 {d20-d23},[r0,:128]! - bx lr - -4: push {r4-r8,lr} - cmp r3, #4 - lsl ip, r3, #1 - blt 4f - - @ 4 channels -5: ldmia r1!, {r4-r7} - mov lr, r2 - mov r8, r0 - vld1.64 {d16-d17},[r4,:128]! - vcvt.s32.f32 q8, q8, #16 - vld1.64 {d18-d19},[r5,:128]! - vcvt.s32.f32 q9, q9, #16 - vld1.64 {d20-d21},[r6,:128]! - vcvt.s32.f32 q10, q10, #16 - vld1.64 {d22-d23},[r7,:128]! - vcvt.s32.f32 q11, q11, #16 -6: subs lr, lr, #8 - vld1.64 {d0-d1}, [r4,:128]! - vcvt.s32.f32 q0, q0, #16 - vsri.32 q9, q8, #16 - vld1.64 {d2-d3}, [r5,:128]! - vcvt.s32.f32 q1, q1, #16 - vsri.32 q11, q10, #16 - vld1.64 {d4-d5}, [r6,:128]! - vcvt.s32.f32 q2, q2, #16 - vzip.32 d18, d22 - vld1.64 {d6-d7}, [r7,:128]! - vcvt.s32.f32 q3, q3, #16 - vzip.32 d19, d23 - vst1.64 {d18}, [r8], ip - vsri.32 q1, q0, #16 - vst1.64 {d22}, [r8], ip - vsri.32 q3, q2, #16 - vst1.64 {d19}, [r8], ip - vzip.32 d2, d6 - vst1.64 {d23}, [r8], ip - vzip.32 d3, d7 - beq 7f - vld1.64 {d16-d17},[r4,:128]! - vcvt.s32.f32 q8, q8, #16 - vst1.64 {d2}, [r8], ip - vld1.64 {d18-d19},[r5,:128]! - vcvt.s32.f32 q9, q9, #16 - vst1.64 {d6}, [r8], ip - vld1.64 {d20-d21},[r6,:128]! - vcvt.s32.f32 q10, q10, #16 - vst1.64 {d3}, [r8], ip - vld1.64 {d22-d23},[r7,:128]! - vcvt.s32.f32 q11, q11, #16 - vst1.64 {d7}, [r8], ip - b 6b -7: vst1.64 {d2}, [r8], ip - vst1.64 {d6}, [r8], ip - vst1.64 {d3}, [r8], ip - vst1.64 {d7}, [r8], ip - subs r3, r3, #4 - it eq - popeq {r4-r8,pc} - cmp r3, #4 - add r0, r0, #8 - bge 5b - - @ 2 channels -4: cmp r3, #2 - blt 4f - ldmia r1!, {r4-r5} - mov lr, r2 - mov r8, r0 - tst lr, #8 - vld1.64 {d16-d17},[r4,:128]! - vcvt.s32.f32 q8, q8, #16 - vld1.64 {d18-d19},[r5,:128]! - vcvt.s32.f32 q9, q9, #16 - vld1.64 {d20-d21},[r4,:128]! - vcvt.s32.f32 q10, q10, #16 - vld1.64 {d22-d23},[r5,:128]! - vcvt.s32.f32 q11, q11, #16 - beq 6f - subs lr, lr, #8 - beq 7f - vsri.32 d18, d16, #16 - vsri.32 d19, d17, #16 - vld1.64 {d16-d17},[r4,:128]! - vcvt.s32.f32 q8, q8, #16 - vst1.32 {d18[0]}, [r8], ip - vsri.32 d22, d20, #16 - vst1.32 {d18[1]}, [r8], ip - vsri.32 d23, d21, #16 - vst1.32 {d19[0]}, [r8], ip - vst1.32 {d19[1]}, [r8], ip - vld1.64 {d18-d19},[r5,:128]! - vcvt.s32.f32 q9, q9, #16 - vst1.32 {d22[0]}, [r8], ip - vst1.32 {d22[1]}, [r8], ip - vld1.64 {d20-d21},[r4,:128]! - vcvt.s32.f32 q10, q10, #16 - vst1.32 {d23[0]}, [r8], ip - vst1.32 {d23[1]}, [r8], ip - vld1.64 {d22-d23},[r5,:128]! - vcvt.s32.f32 q11, q11, #16 -6: subs lr, lr, #16 - vld1.64 {d0-d1}, [r4,:128]! - vcvt.s32.f32 q0, q0, #16 - vsri.32 d18, d16, #16 - vld1.64 {d2-d3}, [r5,:128]! - vcvt.s32.f32 q1, q1, #16 - vsri.32 d19, d17, #16 - vld1.64 {d4-d5}, [r4,:128]! - vcvt.s32.f32 q2, q2, #16 - vld1.64 {d6-d7}, [r5,:128]! - vcvt.s32.f32 q3, q3, #16 - vst1.32 {d18[0]}, [r8], ip - vsri.32 d22, d20, #16 - vst1.32 {d18[1]}, [r8], ip - vsri.32 d23, d21, #16 - vst1.32 {d19[0]}, [r8], ip - vsri.32 d2, d0, #16 - vst1.32 {d19[1]}, [r8], ip - vsri.32 d3, d1, #16 - vst1.32 {d22[0]}, [r8], ip - vsri.32 d6, d4, #16 - vst1.32 {d22[1]}, [r8], ip - vsri.32 d7, d5, #16 - vst1.32 {d23[0]}, [r8], ip - vst1.32 {d23[1]}, [r8], ip - beq 6f - vld1.64 {d16-d17},[r4,:128]! - vcvt.s32.f32 q8, q8, #16 - vst1.32 {d2[0]}, [r8], ip - vst1.32 {d2[1]}, [r8], ip - vld1.64 {d18-d19},[r5,:128]! - vcvt.s32.f32 q9, q9, #16 - vst1.32 {d3[0]}, [r8], ip - vst1.32 {d3[1]}, [r8], ip - vld1.64 {d20-d21},[r4,:128]! - vcvt.s32.f32 q10, q10, #16 - vst1.32 {d6[0]}, [r8], ip - vst1.32 {d6[1]}, [r8], ip - vld1.64 {d22-d23},[r5,:128]! - vcvt.s32.f32 q11, q11, #16 - vst1.32 {d7[0]}, [r8], ip - vst1.32 {d7[1]}, [r8], ip - bgt 6b -6: vst1.32 {d2[0]}, [r8], ip - vst1.32 {d2[1]}, [r8], ip - vst1.32 {d3[0]}, [r8], ip - vst1.32 {d3[1]}, [r8], ip - vst1.32 {d6[0]}, [r8], ip - vst1.32 {d6[1]}, [r8], ip - vst1.32 {d7[0]}, [r8], ip - vst1.32 {d7[1]}, [r8], ip - b 8f -7: vsri.32 d18, d16, #16 - vsri.32 d19, d17, #16 - vst1.32 {d18[0]}, [r8], ip - vsri.32 d22, d20, #16 - vst1.32 {d18[1]}, [r8], ip - vsri.32 d23, d21, #16 - vst1.32 {d19[0]}, [r8], ip - vst1.32 {d19[1]}, [r8], ip - vst1.32 {d22[0]}, [r8], ip - vst1.32 {d22[1]}, [r8], ip - vst1.32 {d23[0]}, [r8], ip - vst1.32 {d23[1]}, [r8], ip -8: subs r3, r3, #2 - add r0, r0, #4 - it eq - popeq {r4-r8,pc} - - @ 1 channel -4: ldr r4, [r1],#4 - tst r2, #8 - mov lr, r2 - mov r5, r0 - vld1.64 {d0-d1}, [r4,:128]! - vcvt.s32.f32 q0, q0, #16 - vld1.64 {d2-d3}, [r4,:128]! - vcvt.s32.f32 q1, q1, #16 - bne 8f -6: subs lr, lr, #16 - vld1.64 {d4-d5}, [r4,:128]! - vcvt.s32.f32 q2, q2, #16 - vld1.64 {d6-d7}, [r4,:128]! - vcvt.s32.f32 q3, q3, #16 - vst1.16 {d0[1]}, [r5,:16], ip - vst1.16 {d0[3]}, [r5,:16], ip - vst1.16 {d1[1]}, [r5,:16], ip - vst1.16 {d1[3]}, [r5,:16], ip - vst1.16 {d2[1]}, [r5,:16], ip - vst1.16 {d2[3]}, [r5,:16], ip - vst1.16 {d3[1]}, [r5,:16], ip - vst1.16 {d3[3]}, [r5,:16], ip - beq 7f - vld1.64 {d0-d1}, [r4,:128]! - vcvt.s32.f32 q0, q0, #16 - vld1.64 {d2-d3}, [r4,:128]! - vcvt.s32.f32 q1, q1, #16 -7: vst1.16 {d4[1]}, [r5,:16], ip - vst1.16 {d4[3]}, [r5,:16], ip - vst1.16 {d5[1]}, [r5,:16], ip - vst1.16 {d5[3]}, [r5,:16], ip - vst1.16 {d6[1]}, [r5,:16], ip - vst1.16 {d6[3]}, [r5,:16], ip - vst1.16 {d7[1]}, [r5,:16], ip - vst1.16 {d7[3]}, [r5,:16], ip - bgt 6b - pop {r4-r8,pc} -8: subs lr, lr, #8 - vst1.16 {d0[1]}, [r5,:16], ip - vst1.16 {d0[3]}, [r5,:16], ip - vst1.16 {d1[1]}, [r5,:16], ip - vst1.16 {d1[3]}, [r5,:16], ip - vst1.16 {d2[1]}, [r5,:16], ip - vst1.16 {d2[3]}, [r5,:16], ip - vst1.16 {d3[1]}, [r5,:16], ip - vst1.16 {d3[3]}, [r5,:16], ip - it eq - popeq {r4-r8,pc} - vld1.64 {d0-d1}, [r4,:128]! - vcvt.s32.f32 q0, q0, #16 - vld1.64 {d2-d3}, [r4,:128]! - vcvt.s32.f32 q1, q1, #16 - b 6b -endfunc - function ff_int32_to_float_fmul_scalar_neon, export=1 VFP vdup.32 q0, d0[0] VFP len .req r2 @@ -390,3 +50,39 @@ NOVFP len .req r3 bx lr .unreq len endfunc + +function ff_int32_to_float_fmul_array8_neon, export=1 + ldr r0, [sp] + lsr r0, r0, #3 + subs r0, r0, #1 + beq 1f +2: + vld1.32 {q0-q1}, [r2,:128]! + vld1.32 {q2-q3}, [r2,:128]! + vld1.32 {d20}, [r3]! + subs r0, r0, #2 + vcvt.f32.s32 q0, q0 + vcvt.f32.s32 q1, q1 + vdup.32 q8, d20[0] + vcvt.f32.s32 q2, q2 + vcvt.f32.s32 q3, q3 + vmul.f32 q0, q0, q8 + vdup.32 q9, d20[1] + vmul.f32 q1, q1, q8 + vmul.f32 q2, q2, q9 + vmul.f32 q3, q3, q9 + vst1.32 {q0-q1}, [r1,:128]! + vst1.32 {q2-q3}, [r1,:128]! + bgt 2b + it lt + bxlt lr +1: + vld1.32 {q0-q1}, [r2,:128] + vld1.32 {d16[],d17[]}, [r3] + vcvt.f32.s32 q0, q0 + vcvt.f32.s32 q1, q1 + vmul.f32 q0, q0, q8 + vmul.f32 q1, q1, q8 + vst1.32 {q0-q1}, [r1,:128] + bx lr +endfunc diff --git a/libavcodec/arm/fmtconvert_vfp_armv6.S b/libavcodec/arm/fmtconvert_vfp_armv6.S deleted file mode 100644 index fb12de1..0000000 --- a/libavcodec/arm/fmtconvert_vfp_armv6.S +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2008 Siarhei Siamashka - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "libavutil/arm/asm.S" - -/** - * ARM VFP optimized float to int16 conversion. - * Assume that len is a positive number and is multiple of 8, destination - * buffer is at least 4 bytes aligned (8 bytes alignment is better for - * performance), little-endian byte sex. - */ -@ void ff_float_to_int16_vfp(int16_t *dst, const float *src, int len) -function ff_float_to_int16_vfp, export=1 - push {r4-r8,lr} - vpush {d8-d11} - vldmia r1!, {s16-s23} - vcvt.s32.f32 s0, s16 - vcvt.s32.f32 s1, s17 - vcvt.s32.f32 s2, s18 - vcvt.s32.f32 s3, s19 - vcvt.s32.f32 s4, s20 - vcvt.s32.f32 s5, s21 - vcvt.s32.f32 s6, s22 - vcvt.s32.f32 s7, s23 -1: - subs r2, r2, #8 - vmov r3, r4, s0, s1 - vmov r5, r6, s2, s3 - vmov r7, r8, s4, s5 - vmov ip, lr, s6, s7 - it gt - vldmiagt r1!, {s16-s23} - ssat r4, #16, r4 - ssat r3, #16, r3 - ssat r6, #16, r6 - ssat r5, #16, r5 - pkhbt r3, r3, r4, lsl #16 - pkhbt r4, r5, r6, lsl #16 - itttt gt - vcvtgt.s32.f32 s0, s16 - vcvtgt.s32.f32 s1, s17 - vcvtgt.s32.f32 s2, s18 - vcvtgt.s32.f32 s3, s19 - itttt gt - vcvtgt.s32.f32 s4, s20 - vcvtgt.s32.f32 s5, s21 - vcvtgt.s32.f32 s6, s22 - vcvtgt.s32.f32 s7, s23 - ssat r8, #16, r8 - ssat r7, #16, r7 - ssat lr, #16, lr - ssat ip, #16, ip - pkhbt r5, r7, r8, lsl #16 - pkhbt r6, ip, lr, lsl #16 - stmia r0!, {r3-r6} - bgt 1b - - vpop {d8-d11} - pop {r4-r8,pc} -endfunc diff --git a/libavcodec/arm/g722dsp_init_arm.c b/libavcodec/arm/g722dsp_init_arm.c new file mode 100644 index 0000000..5edf619 --- /dev/null +++ b/libavcodec/arm/g722dsp_init_arm.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/g722dsp.h" + +extern void ff_g722_apply_qmf_neon(const int16_t *prev_samples, int xout[2]); + +av_cold void ff_g722dsp_init_arm(G722DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + dsp->apply_qmf = ff_g722_apply_qmf_neon; +} diff --git a/libavcodec/arm/g722dsp_neon.S b/libavcodec/arm/g722dsp_neon.S new file mode 100644 index 0000000..5fa3c27 --- /dev/null +++ b/libavcodec/arm/g722dsp_neon.S @@ -0,0 +1,69 @@ +/* + * ARM NEON optimised DSP functions for G722 coding + * Copyright (c) 2015 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_g722_apply_qmf_neon, export=1, align=4 + movrel r3, qmf_coeffs + vld1.s16 {d2,d3,d4}, [r0]! /* load prev_samples */ + vld1.s16 {d16,d17,d18}, [r3,:64]! /* load qmf_coeffs */ + vmull.s16 q0, d2, d16 + vmlal.s16 q0, d3, d17 + vmlal.s16 q0, d4, d18 + + vld1.s16 {d5,d6,d7}, [r0]! /* load prev_samples */ + vld1.s16 {d19,d20,d21}, [r3,:64]! /* load qmf_coeffs */ + vmlal.s16 q0, d5, d19 + vmlal.s16 q0, d6, d20 + vmlal.s16 q0, d7, d21 + + vadd.s32 d0, d1, d0 + vrev64.32 d0, d0 + vst1.s32 {d0}, [r1] + bx lr +endfunc + +const qmf_coeffs, align=4 + .hword 3 + .hword -11 + .hword -11 + .hword 53 + .hword 12 + .hword -156 + .hword 32 + .hword 362 + .hword -210 + .hword -805 + .hword 951 + .hword 3876 + .hword 3876 + .hword 951 + .hword -805 + .hword -210 + .hword 362 + .hword 32 + .hword -156 + .hword 12 + .hword 53 + .hword -11 + .hword -11 + .hword 3 +endconst diff --git a/libavcodec/arm/h264pred_init_arm.c b/libavcodec/arm/h264pred_init_arm.c index bbfe63f..a445d4d 100644 --- a/libavcodec/arm/h264pred_init_arm.c +++ b/libavcodec/arm/h264pred_init_arm.c @@ -54,20 +54,22 @@ static av_cold void h264_pred_init_neon(H264PredContext *h, int codec_id, if (high_depth) return; - h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vert_neon; - h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_hor_neon; - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) - h->pred8x8[PLANE_PRED8x8] = ff_pred8x8_plane_neon; - h->pred8x8[DC_128_PRED8x8 ] = ff_pred8x8_128_dc_neon; - if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && - codec_id != AV_CODEC_ID_VP8) { - h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_neon; - h->pred8x8[LEFT_DC_PRED8x8] = ff_pred8x8_left_dc_neon; - h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_neon; - h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = ff_pred8x8_l0t_dc_neon; - h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = ff_pred8x8_0lt_dc_neon; - h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = ff_pred8x8_l00_dc_neon; - h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = ff_pred8x8_0l0_dc_neon; + if (chroma_format_idc <= 1) { + h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vert_neon; + h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_hor_neon; + if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) + h->pred8x8[PLANE_PRED8x8] = ff_pred8x8_plane_neon; + h->pred8x8[DC_128_PRED8x8 ] = ff_pred8x8_128_dc_neon; + if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && + codec_id != AV_CODEC_ID_VP8) { + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_neon; + h->pred8x8[LEFT_DC_PRED8x8] = ff_pred8x8_left_dc_neon; + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_neon; + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = ff_pred8x8_l0t_dc_neon; + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = ff_pred8x8_0lt_dc_neon; + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = ff_pred8x8_l00_dc_neon; + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = ff_pred8x8_0l0_dc_neon; + } } h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_neon; diff --git a/libavcodec/arm/idctdsp_init_arm.c b/libavcodec/arm/idctdsp_init_arm.c index 0b32df0..8207c31 100644 --- a/libavcodec/arm/idctdsp_init_arm.c +++ b/libavcodec/arm/idctdsp_init_arm.c @@ -29,10 +29,6 @@ #include "idct.h" #include "idctdsp_arm.h" -/* XXX: local hack */ -static void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); -static void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); - void ff_add_pixels_clamped_arm(const int16_t *block, uint8_t *dest, int line_size); @@ -67,9 +63,6 @@ av_cold void ff_idctdsp_init_arm(IDCTDSPContext *c, AVCodecContext *avctx, { int cpu_flags = av_get_cpu_flags(); - ff_put_pixels_clamped = c->put_pixels_clamped; - ff_add_pixels_clamped = c->add_pixels_clamped; - if (!high_bit_depth) { if (avctx->idct_algo == FF_IDCT_AUTO || avctx->idct_algo == FF_IDCT_ARM) { diff --git a/libavcodec/arm/mdct_fixed_init_arm.c b/libavcodec/arm/mdct_fixed_init_arm.c new file mode 100644 index 0000000..606c80c --- /dev/null +++ b/libavcodec/arm/mdct_fixed_init_arm.c @@ -0,0 +1,40 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" + +#define FFT_FLOAT 0 +#include "libavcodec/fft.h" + +void ff_mdct_fixed_calc_neon(FFTContext *s, FFTSample *o, const FFTSample *i); +void ff_mdct_fixed_calcw_neon(FFTContext *s, FFTDouble *o, const FFTSample *i); + +av_cold void ff_mdct_fixed_init_arm(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + if (!s->inverse && s->nbits >= 3) { + s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; + s->mdct_calc = ff_mdct_fixed_calc_neon; + s->mdct_calcw = ff_mdct_fixed_calcw_neon; + } + } +} diff --git a/libavcodec/arm/mdct_init_arm.c b/libavcodec/arm/mdct_init_arm.c new file mode 100644 index 0000000..24678dd --- /dev/null +++ b/libavcodec/arm/mdct_init_arm.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" + +#include "libavcodec/fft.h" + +void ff_imdct_half_vfp(FFTContext *s, FFTSample *output, const FFTSample *input); + +void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); + +av_cold void ff_mdct_init_arm(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_vfp_vm(cpu_flags)) { + s->imdct_half = ff_imdct_half_vfp; + } + + if (have_neon(cpu_flags)) { + s->imdct_calc = ff_imdct_calc_neon; + s->imdct_half = ff_imdct_half_neon; + s->mdct_calc = ff_mdct_calc_neon; + s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; + } +} diff --git a/libavcodec/arm/me_cmp_init_arm.c b/libavcodec/arm/me_cmp_init_arm.c index 819d901..4d73f3e 100644 --- a/libavcodec/arm/me_cmp_init_arm.c +++ b/libavcodec/arm/me_cmp_init_arm.c @@ -26,17 +26,17 @@ #include "libavcodec/mpegvideo.h" int ff_pix_abs16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); + ptrdiff_t stride, int h); int ff_pix_abs16_x2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); + ptrdiff_t stride, int h); int ff_pix_abs16_y2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); + ptrdiff_t stride, int h); int ff_pix_abs8_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); + ptrdiff_t stride, int h); int ff_sse16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, - int line_size, int h); + ptrdiff_t stride, int h); av_cold void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx) { diff --git a/libavcodec/arm/mlpdsp_armv5te.S b/libavcodec/arm/mlpdsp_armv5te.S index cf7d367..4272dae 100644 --- a/libavcodec/arm/mlpdsp_armv5te.S +++ b/libavcodec/arm/mlpdsp_armv5te.S @@ -43,6 +43,14 @@ I .req ip PSAMP .req lr +.macro branch_pic_label first, remainder:vararg +A .word \first - 4 +T .hword (\first) / 2 +.ifnb \remainder + branch_pic_label \remainder +.endif +.endm + // Some macros that do loads/multiplies where the register number is determined // from an assembly-time expression. Boy is GNU assembler's syntax ugly... @@ -338,23 +346,20 @@ T orr AC0, AC0, AC1 .endm .macro switch_on_fir_taps mask_minus1, shift_0, shift_8, iir_taps -A ldr pc, [pc, a3, lsl #2] // firorder is in range 0-(8-iir_taps) +A ldr CO0, [pc, a3, lsl #2] // firorder is in range 0-(8-iir_taps) +A add pc, pc, CO0 T tbh [pc, a3, lsl #1] 0: -A .word 0, 70f, 71f, 72f, 73f, 74f -T .hword (70f - 0b) / 2, (71f - 0b) / 2, (72f - 0b) / 2, (73f - 0b) / 2, (74f - 0b) / 2 + branch_pic_label (70f - 0b), (71f - 0b), (72f - 0b), (73f - 0b) + branch_pic_label (74f - 0b) .if \iir_taps <= 3 -A .word 75f -T .hword (75f - 0b) / 2 + branch_pic_label (75f - 0b) .if \iir_taps <= 2 -A .word 76f -T .hword (76f - 0b) / 2 + branch_pic_label (76f - 0b) .if \iir_taps <= 1 -A .word 77f -T .hword (77f - 0b) / 2 + branch_pic_label (77f - 0b) .if \iir_taps == 0 -A .word 78f -T .hword (78f - 0b) / 2 + branch_pic_label (78f - 0b) .endif .endif .endif @@ -379,11 +384,12 @@ T .hword (78f - 0b) / 2 .endm .macro switch_on_iir_taps mask_minus1, shift_0, shift_8 -A ldr pc, [pc, a4, lsl #2] // irorder is in range 0-4 +A ldr CO0, [pc, a4, lsl #2] // irorder is in range 0-4 +A add pc, pc, CO0 T tbh [pc, a4, lsl #1] 0: -A .word 0, 60f, 61f, 62f, 63f, 64f -T .hword (60f - 0b) / 2, (61f - 0b) / 2, (62f - 0b) / 2, (63f - 0b) / 2, (64f - 0b) / 2 + branch_pic_label (60f - 0b), (61f - 0b), (62f - 0b), (63f - 0b) + branch_pic_label (64f - 0b) 60: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 0 61: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 1 62: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 2 @@ -604,13 +610,14 @@ function ff_mlp_rematrix_channel_arm, export=1 cmp v5, #1 beq 11f blo 10f -A ldr pc, [pc, v5, lsl #2] +A ldr v5, [pc, v5, lsl #2] +A add pc, pc, v5 T tbh [pc, v5, lsl #1] 0: -A .word 0, 0, 0, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 21f, 22f, 23f, 24f, 25f -T .hword 0, 0, (12f - 0b) / 2, (13f - 0b) / 2, (14f - 0b) / 2, (15f - 0b) / 2 -T .hword (16f - 0b) / 2, (17f - 0b) / 2, (18f - 0b) / 2, (19f - 0b) / 2 -T .hword (20f - 0b) / 2, (21f - 0b) / 2, (22f - 0b) / 2, (23f - 0b) / 2, (24f - 0b) / 2, (25f - 0b) / 2 + branch_pic_label 0, 0, (12f - 0b), (13f - 0b) + branch_pic_label (14f - 0b), (15f - 0b), (16f - 0b), (17f - 0b) + branch_pic_label (18f - 0b), (19f - 0b), (20f - 0b), (21f - 0b) + branch_pic_label (22f - 0b), (23f - 0b), (24f - 0b), (25f - 0b) 10: switch_on_au_size 0 11: switch_on_au_size 1 12: switch_on_au_size 2 diff --git a/libavcodec/arm/mlpdsp_armv6.S b/libavcodec/arm/mlpdsp_armv6.S index 3c88021..de9db46 100644 --- a/libavcodec/arm/mlpdsp_armv6.S +++ b/libavcodec/arm/mlpdsp_armv6.S @@ -240,7 +240,7 @@ DAT3 .req v4 DAT4 .req v5 DAT5 .req v6 DAT6 .req sl // use these rather than the otherwise unused -DAT7 .req fp // ip and lr so that we can load them usinf LDRD +DAT7 .req fp // ip and lr so that we can load them using LDRD .macro output4words tail, head, r0, r1, r2, r3, r4, r5, r6, r7, pointer_dead=0 .if \head diff --git a/libavcodec/arm/mpegvideo_armv5te.c b/libavcodec/arm/mpegvideo_armv5te.c index 3c44cd8..4bb7b6e 100644 --- a/libavcodec/arm/mpegvideo_armv5te.c +++ b/libavcodec/arm/mpegvideo_armv5te.c @@ -28,7 +28,7 @@ void ff_dct_unquantize_h263_armv5te(int16_t *block, int qmul, int qadd, int coun #ifdef ENABLE_ARM_TESTS /** - * h263 dequantizer supplementary function, it is performance critical and needs to + * H.263 dequantizer supplementary function, it is performance critical and needs to * have optimized implementations for each architecture. Is also used as a reference * implementation in regression tests */ diff --git a/libavcodec/arm/neontest.c b/libavcodec/arm/neontest.c index b77bcd7..692576e 100644 --- a/libavcodec/arm/neontest.c +++ b/libavcodec/arm/neontest.c @@ -23,7 +23,7 @@ #include "libavutil/arm/neontest.h" wrap(avcodec_open2(AVCodecContext *avctx, - AVCodec *codec, + const AVCodec *codec, AVDictionary **options)) { testneonclobbers(avcodec_open2, avctx, codec, options); diff --git a/libavcodec/arm/rdft_init_arm.c b/libavcodec/arm/rdft_init_arm.c new file mode 100644 index 0000000..2858ba9 --- /dev/null +++ b/libavcodec/arm/rdft_init_arm.c @@ -0,0 +1,33 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" + +#include "libavcodec/rdft.h" + +void ff_rdft_calc_neon(struct RDFTContext *s, FFTSample *z); + +av_cold void ff_rdft_init_arm(RDFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + s->rdft_calc = ff_rdft_calc_neon; +} diff --git a/libavcodec/arm/simple_idct_arm.S b/libavcodec/arm/simple_idct_arm.S index bf9ee3d..a651927 100644 --- a/libavcodec/arm/simple_idct_arm.S +++ b/libavcodec/arm/simple_idct_arm.S @@ -64,7 +64,7 @@ function ff_simple_idct_arm, export=1 __row_loop: - @@ read the row and check if it is null, almost null, or not, according to strongarm specs, it is not necessary to optimize ldr accesses (i.e. split 32bits in 2 16bits words), at least it gives more usable registers :) + @@ read the row and check if it is null, almost null, or not, according to strongarm specs, it is not necessary to optimize ldr accesses (i.e. split 32 bits in two 16-bit 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] @@ -234,8 +234,8 @@ __end_a_evaluation: @@ 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!!!) + @@ put two 16-bit half-words in a 32-bit word + @@ ROWr32[0]=ROWr16[0] | (ROWr16[1]<<16) (only little-endian compliant then!!!) ldr r10, =MASK_MSHW @ R10=0xFFFF0000 and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a1+b1)<<5) mvn r11, r10 @ R11= NOT R10= 0x0000FFFF diff --git a/libavcodec/arm/simple_idct_armv5te.S b/libavcodec/arm/simple_idct_armv5te.S index bf509ee..b196833 100644 --- a/libavcodec/arm/simple_idct_armv5te.S +++ b/libavcodec/arm/simple_idct_armv5te.S @@ -148,12 +148,6 @@ endfunc 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 @@ -161,7 +155,6 @@ endfunc 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 diff --git a/libavcodec/arm/videodsp_armv5te.S b/libavcodec/arm/videodsp_armv5te.S index bbd0a61..0510019 100644 --- a/libavcodec/arm/videodsp_armv5te.S +++ b/libavcodec/arm/videodsp_armv5te.S @@ -23,9 +23,10 @@ #include "libavutil/arm/asm.S" function ff_prefetch_arm, export=1 +1: subs r2, r2, #1 pld [r0] add r0, r0, r1 - bne X(ff_prefetch_arm) + bne 1b bx lr endfunc diff --git a/libavcodec/arm/vp3dsp_init_arm.c b/libavcodec/arm/vp3dsp_init_arm.c index 11e1f1c..1c91434 100644 --- a/libavcodec/arm/vp3dsp_init_arm.c +++ b/libavcodec/arm/vp3dsp_init_arm.c @@ -23,9 +23,9 @@ #include "libavutil/arm/cpu.h" #include "libavcodec/vp3dsp.h" -void ff_vp3_idct_put_neon(uint8_t *dest, int line_size, int16_t *data); -void ff_vp3_idct_add_neon(uint8_t *dest, int line_size, int16_t *data); -void ff_vp3_idct_dc_add_neon(uint8_t *dest, int line_size, int16_t *data); +void ff_vp3_idct_put_neon(uint8_t *dest, ptrdiff_t stride, int16_t *data); +void ff_vp3_idct_add_neon(uint8_t *dest, ptrdiff_t stride, int16_t *data); +void ff_vp3_idct_dc_add_neon(uint8_t *dest, ptrdiff_t stride, int16_t *data); void ff_vp3_v_loop_filter_neon(uint8_t *, int, int *); void ff_vp3_h_loop_filter_neon(uint8_t *, int, int *); diff --git a/libavcodec/arm/vp6dsp_init_arm.c b/libavcodec/arm/vp6dsp_init_arm.c index 4ec41ed..7e26150 100644 --- a/libavcodec/arm/vp6dsp_init_arm.c +++ b/libavcodec/arm/vp6dsp_init_arm.c @@ -22,13 +22,13 @@ #include "libavutil/attributes.h" #include "libavutil/arm/cpu.h" -#include "libavcodec/avcodec.h" + #include "libavcodec/vp56dsp.h" -void ff_vp6_edge_filter_hor_neon(uint8_t *yuv, int stride, int t); -void ff_vp6_edge_filter_ver_neon(uint8_t *yuv, int stride, int t); +void ff_vp6_edge_filter_hor_neon(uint8_t *yuv, ptrdiff_t stride, int t); +void ff_vp6_edge_filter_ver_neon(uint8_t *yuv, ptrdiff_t stride, int t); -av_cold void ff_vp6dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec) +av_cold void ff_vp6dsp_init_arm(VP56DSPContext *s) { int cpu_flags = av_get_cpu_flags(); diff --git a/libavcodec/arm/vp8dsp_armv6.S b/libavcodec/arm/vp8dsp_armv6.S index 03100cd..9eb9734 100644 --- a/libavcodec/arm/vp8dsp_armv6.S +++ b/libavcodec/arm/vp8dsp_armv6.S @@ -192,7 +192,7 @@ function ff_vp8_luma_dc_wht_dc_armv6, export=1 bx lr endfunc -@ void vp8_idct_add(uint8_t *dst, int16_t block[16], int stride) +@ void vp8_idct_add(uint8_t *dst, int16_t block[16], ptrdiff_t stride) function ff_vp8_idct_add_armv6, export=1 push {r4-r12, lr} sub sp, sp, #32 @@ -314,7 +314,7 @@ function ff_vp8_idct_add_armv6, export=1 pop {r4-r12, pc} endfunc -@ void vp8_idct_dc_add(uint8_t *dst, int16_t block[16], int stride) +@ void vp8_idct_dc_add(uint8_t *dst, int16_t block[16], ptrdiff_t stride) function ff_vp8_idct_dc_add_armv6, export=1 push {r4-r6, lr} add r6, r0, r2, lsl #1 @@ -355,7 +355,7 @@ function ff_vp8_idct_dc_add_armv6, export=1 pop {r4-r6, pc} endfunc -@ void vp8_idct_dc_add4uv(uint8_t *dst, int16_t block[4][16], int stride) +@ void vp8_idct_dc_add4uv(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride) function ff_vp8_idct_dc_add4uv_armv6, export=1 push {r4, lr} @@ -371,7 +371,7 @@ function ff_vp8_idct_dc_add4uv_armv6, export=1 pop {r4, pc} endfunc -@ void vp8_idct_dc_add4y(uint8_t *dst, int16_t block[4][16], int stride) +@ void vp8_idct_dc_add4y(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride) function ff_vp8_idct_dc_add4y_armv6, export=1 push {r4, lr} @@ -455,7 +455,7 @@ endfunc eor r5, r5, r2 @ *oq0 = u ^ 0x80 .endm -@ void vp8_v_loop_filter16_simple(uint8_t *dst, int stride, int flim) +@ void vp8_v_loop_filter16_simple(uint8_t *dst, ptrdiff_t stride, int flim) function ff_vp8_v_loop_filter16_simple_armv6, export=1 push {r4-r11, lr} @@ -866,7 +866,7 @@ function ff_vp8_v_loop_filter8uv_armv6, export=1 b vp8_v_loop_filter_armv6 endfunc -@ void vp8_h_loop_filter16_simple(uint8_t *dst, int stride, int flim) +@ void vp8_h_loop_filter16_simple(uint8_t *dst, ptrdiff_t stride, int flim) function ff_vp8_h_loop_filter16_simple_armv6, export=1 push {r4-r11, lr} orr r12, r2, r2, lsl #16 @@ -1113,8 +1113,8 @@ endfunc @ MC -@ void put_vp8_pixels16(uint8_t *dst, int dststride, uint8_t *src, -@ int srcstride, int h, int mx, int my) +@ void put_vp8_pixels16(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, +@ ptrdiff_t srcstride, int h, int mx, int my) function ff_put_vp8_pixels16_armv6, export=1 push {r4-r11} ldr r12, [sp, #32] @ h @@ -1137,8 +1137,8 @@ function ff_put_vp8_pixels16_armv6, export=1 bx lr endfunc -@ void put_vp8_pixels8(uint8_t *dst, int dststride, uint8_t *src, -@ int srcstride, int h, int mx, int my) +@ void put_vp8_pixels8(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, +@ ptrdiff_t srcstride, int h, int mx, int my) function ff_put_vp8_pixels8_armv6, export=1 push {r4-r11} ldr r12, [sp, #32] @ h @@ -1161,8 +1161,8 @@ function ff_put_vp8_pixels8_armv6, export=1 bx lr endfunc -@ void put_vp8_pixels4(uint8_t *dst, int dststride, uint8_t *src, -@ int srcstride, int h, int mx, int my) +@ void put_vp8_pixels4(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, +@ ptrdiff_t srcstride, int h, int mx, int my) function ff_put_vp8_pixels4_armv6, export=1 ldr r12, [sp, #0] @ h push {r4-r6,lr} @@ -1181,7 +1181,7 @@ function ff_put_vp8_pixels4_armv6, export=1 endfunc @ note: worst case sum of all 6-tap filter values * 255 is 0x7f80 so 16 bit -@ arithmatic can be used to apply filters +@ arithmetic can be used to apply filters const sixtap_filters_13245600, align=4 .short 2, 108, -11, 36, -8, 1, 0, 0 .short 3, 77, -16, 77, -16, 3, 0, 0 @@ -1226,13 +1226,8 @@ vp8_mc_1 bilin, 8, v vp8_mc_1 bilin, 4, h vp8_mc_1 bilin, 4, v -/* True relational expressions have the value -1 in the GNU assembler, - +1 in Apple's. */ -#ifdef __APPLE__ -# define TMPSIZE \size * (8 + 8*(\size > 4) + \ytaps - 1) -#else -# define TMPSIZE \size * (8 - 8*(\size > 4) + \ytaps - 1) -#endif +@ 4 and 8 pixel wide mc blocks might have height of 8 or 16 lines +#define TMPSIZE \size * (16 / ((16 / \size + 1) / 2) + \ytaps - 1) .macro vp8_mc_hv name, size, h, v, ytaps function ff_put_vp8_\name\size\()_\h\v\()_armv6, export=1 diff --git a/libavcodec/arm/vp8dsp_neon.S b/libavcodec/arm/vp8dsp_neon.S index 544332c..f43b4f7 100644 --- a/libavcodec/arm/vp8dsp_neon.S +++ b/libavcodec/arm/vp8dsp_neon.S @@ -322,7 +322,7 @@ endfunc vmov.i16 q12, #3 vsubl.s8 q10, d8, d6 @ QS0 - PS0 - vsubl.s8 q11, d9, d7 @ (widened to 16bit) + vsubl.s8 q11, d9, d7 @ (widened to 16 bits) veor q2, q2, q13 @ PS1 = P1 ^ 0x80 veor q5, q5, q13 @ QS1 = Q1 ^ 0x80 vmul.i16 q10, q10, q12 @ w = 3 * (QS0 - PS0) @@ -1562,7 +1562,7 @@ function ff_put_vp8_epel4_h4v4_neon, export=1 endfunc @ note: worst case sum of all 6-tap filter values * 255 is 0x7f80 so 16 bit -@ arithmatic can be used to apply filters +@ arithmetic can be used to apply filters const subpel_filters, align=4 .short 0, 6, 123, 12, 1, 0, 0, 0 .short 2, 11, 108, 36, 8, 1, 0, 0 diff --git a/libavcodec/ass.c b/libavcodec/ass.c index 098050a..def11f0 100644 --- a/libavcodec/ass.c +++ b/libavcodec/ass.c @@ -1,5 +1,5 @@ /* - * SSA/ASS common funtions + * SSA/ASS common functions * Copyright (c) 2010 Aurelien Jacobs * * This file is part of Libav. diff --git a/libavcodec/ass.h b/libavcodec/ass.h index 594b5f3..1302a04 100644 --- a/libavcodec/ass.h +++ b/libavcodec/ass.h @@ -1,5 +1,5 @@ /* - * SSA/ASS common funtions + * SSA/ASS common functions * Copyright (c) 2010 Aurelien Jacobs * * This file is part of Libav. diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c index 7a69582..48fe32e 100644 --- a/libavcodec/assdec.c +++ b/libavcodec/assdec.c @@ -29,7 +29,7 @@ static av_cold int ass_decode_init(AVCodecContext *avctx) { avctx->subtitle_header = av_malloc(avctx->extradata_size); - if (!avctx->extradata) + if (!avctx->subtitle_header) return AVERROR(ENOMEM); memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); avctx->subtitle_header_size = avctx->extradata_size; diff --git a/libavcodec/asv.c b/libavcodec/asv.c index 71c5e5f..b9e93f7 100644 --- a/libavcodec/asv.c +++ b/libavcodec/asv.c @@ -30,65 +30,66 @@ #include "bswapdsp.h" const uint8_t ff_asv_scantab[64] = { - 0x00,0x08,0x01,0x09,0x10,0x18,0x11,0x19, - 0x02,0x0A,0x03,0x0B,0x12,0x1A,0x13,0x1B, - 0x04,0x0C,0x05,0x0D,0x20,0x28,0x21,0x29, - 0x06,0x0E,0x07,0x0F,0x14,0x1C,0x15,0x1D, - 0x22,0x2A,0x23,0x2B,0x30,0x38,0x31,0x39, - 0x16,0x1E,0x17,0x1F,0x24,0x2C,0x25,0x2D, - 0x32,0x3A,0x33,0x3B,0x26,0x2E,0x27,0x2F, - 0x34,0x3C,0x35,0x3D,0x36,0x3E,0x37,0x3F, + 0x00, 0x08, 0x01, 0x09, 0x10, 0x18, 0x11, 0x19, + 0x02, 0x0A, 0x03, 0x0B, 0x12, 0x1A, 0x13, 0x1B, + 0x04, 0x0C, 0x05, 0x0D, 0x20, 0x28, 0x21, 0x29, + 0x06, 0x0E, 0x07, 0x0F, 0x14, 0x1C, 0x15, 0x1D, + 0x22, 0x2A, 0x23, 0x2B, 0x30, 0x38, 0x31, 0x39, + 0x16, 0x1E, 0x17, 0x1F, 0x24, 0x2C, 0x25, 0x2D, + 0x32, 0x3A, 0x33, 0x3B, 0x26, 0x2E, 0x27, 0x2F, + 0x34, 0x3C, 0x35, 0x3D, 0x36, 0x3E, 0x37, 0x3F, }; const uint8_t ff_asv_ccp_tab[17][2] = { - {0x2,2}, {0x7,5}, {0xB,5}, {0x3,5}, - {0xD,5}, {0x5,5}, {0x9,5}, {0x1,5}, - {0xE,5}, {0x6,5}, {0xA,5}, {0x2,5}, - {0xC,5}, {0x4,5}, {0x8,5}, {0x3,2}, - {0xF,5}, //EOB + { 0x2, 2 }, { 0x7, 5 }, { 0xB, 5 }, { 0x3, 5 }, + { 0xD, 5 }, { 0x5, 5 }, { 0x9, 5 }, { 0x1, 5 }, + { 0xE, 5 }, { 0x6, 5 }, { 0xA, 5 }, { 0x2, 5 }, + { 0xC, 5 }, { 0x4, 5 }, { 0x8, 5 }, { 0x3, 2 }, + { 0xF, 5 }, // EOB }; const uint8_t ff_asv_level_tab[7][2] = { - {3,4}, {3,3}, {3,2}, {0,3}, {2,2}, {2,3}, {2,4} + { 3, 4 }, { 3, 3 }, { 3, 2 }, { 0, 3 }, { 2, 2 }, { 2, 3 }, { 2, 4 } }; const uint8_t ff_asv_dc_ccp_tab[8][2] = { - {0x1,2}, {0xD,4}, {0xF,4}, {0xC,4}, - {0x5,3}, {0xE,4}, {0x4,3}, {0x0,2}, + { 0x1, 2 }, { 0xD, 4 }, { 0xF, 4 }, { 0xC, 4 }, + { 0x5, 3 }, { 0xE, 4 }, { 0x4, 3 }, { 0x0, 2 }, }; const uint8_t ff_asv_ac_ccp_tab[16][2] = { - {0x00,2}, {0x3B,6}, {0x0A,4}, {0x3A,6}, - {0x02,3}, {0x39,6}, {0x3C,6}, {0x38,6}, - {0x03,3}, {0x3D,6}, {0x08,4}, {0x1F,5}, - {0x09,4}, {0x0B,4}, {0x0D,4}, {0x0C,4}, + { 0x00, 2 }, { 0x3B, 6 }, { 0x0A, 4 }, { 0x3A, 6 }, + { 0x02, 3 }, { 0x39, 6 }, { 0x3C, 6 }, { 0x38, 6 }, + { 0x03, 3 }, { 0x3D, 6 }, { 0x08, 4 }, { 0x1F, 5 }, + { 0x09, 4 }, { 0x0B, 4 }, { 0x0D, 4 }, { 0x0C, 4 }, }; const uint8_t ff_asv2_level_tab[63][2] = { - {0x3F,10},{0x2F,10},{0x37,10},{0x27,10},{0x3B,10},{0x2B,10},{0x33,10},{0x23,10}, - {0x3D,10},{0x2D,10},{0x35,10},{0x25,10},{0x39,10},{0x29,10},{0x31,10},{0x21,10}, - {0x1F, 8},{0x17, 8},{0x1B, 8},{0x13, 8},{0x1D, 8},{0x15, 8},{0x19, 8},{0x11, 8}, - {0x0F, 6},{0x0B, 6},{0x0D, 6},{0x09, 6}, - {0x07, 4},{0x05, 4}, - {0x03, 2}, - {0x00, 5}, - {0x02, 2}, - {0x04, 4},{0x06, 4}, - {0x08, 6},{0x0C, 6},{0x0A, 6},{0x0E, 6}, - {0x10, 8},{0x18, 8},{0x14, 8},{0x1C, 8},{0x12, 8},{0x1A, 8},{0x16, 8},{0x1E, 8}, - {0x20,10},{0x30,10},{0x28,10},{0x38,10},{0x24,10},{0x34,10},{0x2C,10},{0x3C,10}, - {0x22,10},{0x32,10},{0x2A,10},{0x3A,10},{0x26,10},{0x36,10},{0x2E,10},{0x3E,10}, + { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 }, + { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 }, + { 0x1F, 8 }, { 0x17, 8 }, { 0x1B, 8 }, { 0x13, 8 }, { 0x1D, 8 }, { 0x15, 8 }, { 0x19, 8 }, { 0x11, 8 }, + { 0x0F, 6 }, { 0x0B, 6 }, { 0x0D, 6 }, { 0x09, 6 }, + { 0x07, 4 }, { 0x05, 4 }, + { 0x03, 2 }, + { 0x00, 5 }, + { 0x02, 2 }, + { 0x04, 4 }, { 0x06, 4 }, + { 0x08, 6 }, { 0x0C, 6 }, { 0x0A, 6 }, { 0x0E, 6 }, + { 0x10, 8 }, { 0x18, 8 }, { 0x14, 8 }, { 0x1C, 8 }, { 0x12, 8 }, { 0x1A, 8 }, { 0x16, 8 }, { 0x1E, 8 }, + { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 }, + { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 }, }; -av_cold void ff_asv_common_init(AVCodecContext *avctx) { - ASV1Context * const a = avctx->priv_data; +av_cold void ff_asv_common_init(AVCodecContext *avctx) +{ + ASV1Context *const a = avctx->priv_data; ff_bswapdsp_init(&a->bbdsp); 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; + a->mb_width2 = (avctx->width + 0) / 16; + a->mb_height2 = (avctx->height + 0) / 16; - a->avctx= avctx; + a->avctx = avctx; } diff --git a/libavcodec/asv.h b/libavcodec/asv.h index 9ae3737..18f7a95 100644 --- a/libavcodec/asv.h +++ b/libavcodec/asv.h @@ -39,7 +39,7 @@ #include "pixblockdsp.h" #include "put_bits.h" -typedef struct ASV1Context{ +typedef struct ASV1Context { AVCodecContext *avctx; BlockDSPContext bdsp; BswapDSPContext bbdsp; diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c index 252f88a..f17f064 100644 --- a/libavcodec/asvdec.c +++ b/libavcodec/asvdec.c @@ -35,7 +35,7 @@ #include "mathops.h" #include "mpeg12data.h" -#define VLC_BITS 6 +#define VLC_BITS 6 #define ASV2_LEVEL_VLC_BITS 10 static VLC ccp_vlc; @@ -69,10 +69,10 @@ static av_cold void init_vlcs(ASV1Context *a) } } -//FIXME write a reversed bitstream reader to avoid the double reverse +// 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)]; + return ff_reverse[get_bits(gb, n) << (8 - n)]; } static inline int asv1_get_level(GetBitContext *gb) @@ -90,7 +90,7 @@ 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); + return (int8_t) asv2_get_bits(gb, 8); else return code - 31; } @@ -149,13 +149,13 @@ static inline int asv2_decode_block(ASV1Context *a, int16_t block[64]) if (ccp) { if (ccp & 8) - block[a->scantable.permutated[4*i + 0]] = (asv2_get_level(&a->gb) * a->intra_matrix[4*i + 0]) >> 4; + 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; + 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; + 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; + block[a->scantable.permutated[4 * i + 3]] = (asv2_get_level(&a->gb) * a->intra_matrix[4 * i + 3]) >> 4; } } @@ -184,32 +184,31 @@ static inline int decode_mb(ASV1Context *a, int16_t block[6][64]) static inline void idct_put(ASV1Context *a, AVFrame *frame, int mb_x, int mb_y) { - int16_t (*block)[64] = a->block; - int linesize = frame->linesize[0]; + int16_t(*block)[64] = a->block; + int linesize = frame->linesize[0]; - uint8_t *dest_y = frame->data[0] + (mb_y * 16* linesize ) + mb_x * 16; - uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; - uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + uint8_t *dest_y = frame->data[0] + (mb_y * 16 * linesize) + mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; a->idsp.idct_put(dest_y, linesize, block[0]); a->idsp.idct_put(dest_y + 8, linesize, block[1]); a->idsp.idct_put(dest_y + 8 * linesize, linesize, block[2]); a->idsp.idct_put(dest_y + 8 * linesize + 8, linesize, block[3]); - if (!(a->avctx->flags&CODEC_FLAG_GRAY)) { + if (!(a->avctx->flags & AV_CODEC_FLAG_GRAY)) { a->idsp.idct_put(dest_cb, frame->linesize[1], block[4]); a->idsp.idct_put(dest_cr, frame->linesize[2], block[5]); } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - ASV1Context * const a = avctx->priv_data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - AVFrame * const p = data; + ASV1Context *const a = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *const p = data; int mb_x, mb_y, ret; if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { @@ -224,16 +223,16 @@ static int decode_frame(AVCodecContext *avctx, if (!a->bitstream_buffer) return AVERROR(ENOMEM); - if (avctx->codec_id == AV_CODEC_ID_ASV1) + if (avctx->codec_id == AV_CODEC_ID_ASV1) { a->bbdsp.bswap_buf((uint32_t *) a->bitstream_buffer, (const uint32_t *) buf, buf_size / 4); - else { + } 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); + 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++) { @@ -273,8 +272,8 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx) { - ASV1Context * const a = avctx->priv_data; - const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; + ASV1Context *const a = avctx->priv_data; + const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; int i; if (avctx->extradata_size < 1) { @@ -301,7 +300,8 @@ static av_cold int decode_init(AVCodecContext *avctx) for (i = 0; i < 64; i++) { int index = ff_asv_scantab[i]; - a->intra_matrix[i] = 64 * scale * ff_mpeg1_default_intra_matrix[index] / a->inv_qscale; + a->intra_matrix[i] = 64 * scale * ff_mpeg1_default_intra_matrix[index] / + a->inv_qscale; } return 0; @@ -309,7 +309,7 @@ static av_cold int decode_init(AVCodecContext *avctx) static av_cold int decode_end(AVCodecContext *avctx) { - ASV1Context * const a = avctx->priv_data; + ASV1Context *const a = avctx->priv_data; av_freep(&a->bitstream_buffer); a->bitstream_buffer_size = 0; @@ -326,7 +326,7 @@ AVCodec ff_asv1_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; AVCodec ff_asv2_decoder = { @@ -338,6 +338,5 @@ AVCodec ff_asv2_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; - diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c index 9944ffa..ac7c317 100644 --- a/libavcodec/asvenc.c +++ b/libavcodec/asvenc.c @@ -29,121 +29,161 @@ #include "asv.h" #include "avcodec.h" #include "fdctdsp.h" +#include "internal.h" #include "mathops.h" #include "mpeg12data.h" -static inline void asv2_put_bits(PutBitContext *pb, int n, int v){ - put_bits(pb, n, ff_reverse[ v << (8-n) ]); +static inline void asv2_put_bits(PutBitContext *pb, int n, int v) +{ + put_bits(pb, n, ff_reverse[v << (8 - n)]); } -static inline void asv1_put_level(PutBitContext *pb, int level){ - unsigned int index= level + 3; +static inline void asv1_put_level(PutBitContext *pb, int level) +{ + unsigned int index = level + 3; - if(index <= 6) put_bits(pb, ff_asv_level_tab[index][1], ff_asv_level_tab[index][0]); - else{ + if (index <= 6) { + put_bits(pb, ff_asv_level_tab[index][1], ff_asv_level_tab[index][0]); + } else { put_bits(pb, ff_asv_level_tab[3][1], ff_asv_level_tab[3][0]); put_sbits(pb, 8, level); } } -static inline void asv2_put_level(PutBitContext *pb, int level){ - unsigned int index= level + 31; +static inline void asv2_put_level(PutBitContext *pb, int level) +{ + unsigned int index = level + 31; - if(index <= 62) put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]); - else{ + if (index <= 62) { + put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]); + } else { put_bits(pb, ff_asv2_level_tab[31][1], ff_asv2_level_tab[31][0]); - asv2_put_bits(pb, 8, level&0xFF); + asv2_put_bits(pb, 8, level & 0xFF); } } -static inline void asv1_encode_block(ASV1Context *a, int16_t block[64]){ +static inline void asv1_encode_block(ASV1Context *a, int16_t block[64]) +{ int i; - int nc_count=0; - - put_bits(&a->pb, 8, (block[0] + 32)>>6); - block[0]= 0; - - for(i=0; i<10; i++){ - const int index = ff_asv_scantab[4*i]; - int ccp=0; - - if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8; - if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4; - if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2; - if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1; - - if(ccp){ - for(;nc_count; nc_count--) + int nc_count = 0; + + put_bits(&a->pb, 8, (block[0] + 32) >> 6); + block[0] = 0; + + for (i = 0; i < 10; i++) { + const int index = ff_asv_scantab[4 * i]; + int ccp = 0; + + if ((block[index + 0] = (block[index + 0] * + a->q_intra_matrix[index + 0] + (1 << 15)) >> 16)) + ccp |= 8; + if ((block[index + 8] = (block[index + 8] * + a->q_intra_matrix[index + 8] + (1 << 15)) >> 16)) + ccp |= 4; + if ((block[index + 1] = (block[index + 1] * + a->q_intra_matrix[index + 1] + (1 << 15)) >> 16)) + ccp |= 2; + if ((block[index + 9] = (block[index + 9] * + a->q_intra_matrix[index + 9] + (1 << 15)) >> 16)) + ccp |= 1; + + if (ccp) { + for (; nc_count; nc_count--) put_bits(&a->pb, ff_asv_ccp_tab[0][1], ff_asv_ccp_tab[0][0]); put_bits(&a->pb, ff_asv_ccp_tab[ccp][1], ff_asv_ccp_tab[ccp][0]); - if(ccp&8) asv1_put_level(&a->pb, block[index + 0]); - if(ccp&4) asv1_put_level(&a->pb, block[index + 8]); - if(ccp&2) asv1_put_level(&a->pb, block[index + 1]); - if(ccp&1) asv1_put_level(&a->pb, block[index + 9]); - }else{ + if (ccp & 8) + asv1_put_level(&a->pb, block[index + 0]); + if (ccp & 4) + asv1_put_level(&a->pb, block[index + 8]); + if (ccp & 2) + asv1_put_level(&a->pb, block[index + 1]); + if (ccp & 1) + asv1_put_level(&a->pb, block[index + 9]); + } else { nc_count++; } } put_bits(&a->pb, ff_asv_ccp_tab[16][1], ff_asv_ccp_tab[16][0]); } -static inline void asv2_encode_block(ASV1Context *a, int16_t block[64]){ +static inline int asv2_encode_block(ASV1Context *a, int16_t block[64]) +{ int i; - int count=0; + int count = 0; - for(count=63; count>3; count--){ + for (count = 63; count > 3; count--) { const int index = ff_asv_scantab[count]; - - if( (block[index]*a->q_intra_matrix[index] + (1<<15))>>16 ) + if ((block[index] * a->q_intra_matrix[index] + (1 << 15)) >> 16) break; } count >>= 2; asv2_put_bits(&a->pb, 4, count); - asv2_put_bits(&a->pb, 8, (block[0] + 32)>>6); - block[0]= 0; - - for(i=0; i<=count; i++){ - const int index = ff_asv_scantab[4*i]; - int ccp=0; - - if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8; - if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4; - if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2; - if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1; - - assert(i || ccp<8); - if(i) put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]); - else put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]); - - if(ccp){ - if(ccp&8) asv2_put_level(&a->pb, block[index + 0]); - if(ccp&4) asv2_put_level(&a->pb, block[index + 8]); - if(ccp&2) asv2_put_level(&a->pb, block[index + 1]); - if(ccp&1) asv2_put_level(&a->pb, block[index + 9]); + asv2_put_bits(&a->pb, 8, (block[0] + 32) >> 6); + block[0] = 0; + + for (i = 0; i <= count; i++) { + const int index = ff_asv_scantab[4 * i]; + int ccp = 0; + + if ((block[index + 0] = (block[index + 0] * + a->q_intra_matrix[index + 0] + (1 << 15)) >> 16)) + ccp |= 8; + if ((block[index + 8] = (block[index + 8] * + a->q_intra_matrix[index + 8] + (1 << 15)) >> 16)) + ccp |= 4; + if ((block[index + 1] = (block[index + 1] * + a->q_intra_matrix[index + 1] + (1 << 15)) >> 16)) + ccp |= 2; + if ((block[index + 9] = (block[index + 9] * + a->q_intra_matrix[index + 9] + (1 << 15)) >> 16)) + ccp |= 1; + + if (!i && ccp >= 8) + return AVERROR_BUG; + if (i) + put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]); + else + put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]); + + if (ccp) { + if (ccp & 8) + asv2_put_level(&a->pb, block[index + 0]); + if (ccp & 4) + asv2_put_level(&a->pb, block[index + 8]); + if (ccp & 2) + asv2_put_level(&a->pb, block[index + 1]); + if (ccp & 1) + asv2_put_level(&a->pb, block[index + 9]); } } + + return 0; } -#define MAX_MB_SIZE (30*16*16*3/2/8) +#define MAX_MB_SIZE (30 * 16 * 16 * 3 / 2 / 8) -static inline int encode_mb(ASV1Context *a, int16_t block[6][64]){ - int i; +static inline int encode_mb(ASV1Context *a, int16_t block[6][64]) +{ + int i, ret; - if (a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < MAX_MB_SIZE) { + if (a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb) >> 3) < MAX_MB_SIZE) { av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n"); return -1; } - if(a->avctx->codec_id == AV_CODEC_ID_ASV1){ - for(i=0; i<6; i++) + if (a->avctx->codec_id == AV_CODEC_ID_ASV1) { + for (i = 0; i < 6; i++) asv1_encode_block(a, block[i]); - }else{ - for(i=0; i<6; i++) - asv2_encode_block(a, block[i]); + } else { + for (i = 0; i < 6; i++) { + ret = asv2_encode_block(a, block[i]); + if (ret < 0) + return ret; + } } return 0; } @@ -151,25 +191,25 @@ static inline int encode_mb(ASV1Context *a, int16_t block[6][64]){ static inline void dct_get(ASV1Context *a, const AVFrame *frame, int mb_x, int mb_y) { - int16_t (*block)[64]= a->block; + int16_t (*block)[64] = a->block; int linesize = frame->linesize[0]; int i; - uint8_t *ptr_y = frame->data[0] + (mb_y * 16* linesize ) + mb_x * 16; - uint8_t *ptr_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; - uint8_t *ptr_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + uint8_t *ptr_y = frame->data[0] + (mb_y * 16 * linesize) + mb_x * 16; + uint8_t *ptr_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *ptr_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; a->pdsp.get_pixels(block[0], ptr_y, linesize); a->pdsp.get_pixels(block[1], ptr_y + 8, linesize); a->pdsp.get_pixels(block[2], ptr_y + 8 * linesize, linesize); a->pdsp.get_pixels(block[3], ptr_y + 8 * linesize + 8, linesize); - for(i=0; i<4; i++) + for (i = 0; i < 4; i++) a->fdsp.fdct(block[i]); - if(!(a->avctx->flags&CODEC_FLAG_GRAY)){ + if (!(a->avctx->flags & AV_CODEC_FLAG_GRAY)) { a->pdsp.get_pixels(block[4], ptr_cb, frame->linesize[1]); a->pdsp.get_pixels(block[5], ptr_cr, frame->linesize[2]); - for(i=4; i<6; i++) + for (i = 4; i < 6; i++) a->fdsp.fdct(block[i]); } } @@ -177,37 +217,37 @@ static inline void dct_get(ASV1Context *a, const AVFrame *frame, static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { - ASV1Context * const a = avctx->priv_data; + ASV1Context *const a = avctx->priv_data; int size, ret; int mb_x, mb_y; if (!pkt->data && - (ret = av_new_packet(pkt, a->mb_height*a->mb_width*MAX_MB_SIZE + - FF_MIN_BUFFER_SIZE)) < 0) { + (ret = av_new_packet(pkt, a->mb_height * a->mb_width * MAX_MB_SIZE + + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } init_put_bits(&a->pb, pkt->data, pkt->size); - for(mb_y=0; mb_ymb_height2; mb_y++){ - for(mb_x=0; mb_xmb_width2; mb_x++){ + 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, pict, mb_x, mb_y); encode_mb(a, a->block); } } - if(a->mb_width2 != a->mb_width){ - mb_x= a->mb_width2; - for(mb_y=0; mb_ymb_height2; mb_y++){ + 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, pict, mb_x, mb_y); encode_mb(a, a->block); } } - if(a->mb_height2 != a->mb_height){ - mb_y= a->mb_height2; - for(mb_x=0; mb_xmb_width; mb_x++){ + 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, pict, mb_x, mb_y); encode_mb(a, a->block); } @@ -215,64 +255,64 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, emms_c(); avpriv_align_put_bits(&a->pb); - while(put_bits_count(&a->pb)&31) + while (put_bits_count(&a->pb) & 31) put_bits(&a->pb, 8, 0); - size= put_bits_count(&a->pb)/32; + size = put_bits_count(&a->pb) / 32; - if(avctx->codec_id == AV_CODEC_ID_ASV1) + if (avctx->codec_id == AV_CODEC_ID_ASV1) { a->bbdsp.bswap_buf((uint32_t *) pkt->data, (uint32_t *) pkt->data, size); - else{ + } else { int i; - for(i=0; i<4*size; i++) + for (i = 0; i < 4 * size; i++) pkt->data[i] = ff_reverse[pkt->data[i]]; } - pkt->size = size*4; + pkt->size = size * 4; pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; } -static av_cold int encode_init(AVCodecContext *avctx){ - ASV1Context * const a = avctx->priv_data; +static av_cold int encode_init(AVCodecContext *avctx) +{ + ASV1Context *const a = avctx->priv_data; int i; - const int scale= avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; + const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ff_asv_common_init(avctx); ff_fdctdsp_init(&a->fdsp, avctx); ff_pixblockdsp_init(&a->pdsp, avctx); - if(avctx->global_quality == 0) avctx->global_quality= 4*FF_QUALITY_SCALE; + 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; + a->inv_qscale = (32 * scale * FF_QUALITY_SCALE + + avctx->global_quality / 2) / avctx->global_quality; - avctx->extradata= av_mallocz(8); - avctx->extradata_size=8; - ((uint32_t*)avctx->extradata)[0]= av_le2ne32(a->inv_qscale); - ((uint32_t*)avctx->extradata)[1]= av_le2ne32(AV_RL32("ASUS")); + avctx->extradata = av_mallocz(8); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = 8; + ((uint32_t *) avctx->extradata)[0] = av_le2ne32(a->inv_qscale); + ((uint32_t *) avctx->extradata)[1] = av_le2ne32(AV_RL32("ASUS")); - for(i=0; i<64; i++){ - int q= 32*scale*ff_mpeg1_default_intra_matrix[i]; - a->q_intra_matrix[i]= ((a->inv_qscale<<16) + q/2) / q; + 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; } -static av_cold int asv_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - - return 0; -} #if CONFIG_ASV1_ENCODER AVCodec ff_asv1_encoder = { @@ -283,9 +323,9 @@ AVCodec ff_asv1_encoder = { .priv_data_size = sizeof(ASV1Context), .init = encode_init, .encode2 = encode_frame, - .close = asv_encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif @@ -298,8 +338,8 @@ AVCodec ff_asv2_encoder = { .priv_data_size = sizeof(ASV1Context), .init = encode_init, .encode2 = encode_frame, - .close = asv_encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c index 9a89785..e938976 100644 --- a/libavcodec/atrac1.c +++ b/libavcodec/atrac1.c @@ -57,7 +57,7 @@ /** * Sound unit struct, one unit is used per channel */ -typedef struct { +typedef struct AT1SUCtx { int log2_block_count[AT1_QMF_BANDS]; ///< log2 number of blocks in a band int num_bfus; ///< number of Block Floating Units float* spectrum[2]; @@ -71,7 +71,7 @@ typedef struct { /** * The atrac1 context, holds all needed parameters for decoding */ -typedef struct { +typedef struct AT1Ctx { AT1SUCtx SUs[AT1_MAX_CHANNELS]; ///< channel sound unit DECLARE_ALIGNED(32, float, spec)[AT1_SU_SAMPLES]; ///< the mdct spectrum buffer @@ -356,7 +356,7 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx) ff_atrac_generate_tables(); - avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&q->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); q->bands[0] = q->low; q->bands[1] = q->mid; @@ -381,7 +381,7 @@ AVCodec ff_atrac1_decoder = { .init = atrac1_decode_init, .close = atrac1_decode_end, .decode = atrac1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/atrac1data.h b/libavcodec/atrac1data.h index d4b8cd0..539867b 100644 --- a/libavcodec/atrac1data.h +++ b/libavcodec/atrac1data.h @@ -43,7 +43,7 @@ static const uint8_t bfu_bands_t[4] = {0, 20, 36, 52}; */ static const uint8_t specs_per_bfu[52] = { 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, // low band - 6, 6, 6, 6, 7, 7, 7, 7, 9, 9, 9, 9, 10, 10, 10, 10, // midle band + 6, 6, 6, 6, 7, 7, 7, 7, 9, 9, 9, 9, 10, 10, 10, 10, // middle band 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20, 20, 20, 20 // high band }; diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 31f4844..2e1fd3c 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -41,7 +41,6 @@ #include "avcodec.h" #include "bytestream.h" #include "fft.h" -#include "fmtconvert.h" #include "get_bits.h" #include "internal.h" @@ -107,7 +106,6 @@ typedef struct ATRAC3Context { AtracGCContext gainc_ctx; FFTContext mdct_ctx; - FmtConvertContext fmt_conv; AVFloatDSPContext fdsp; } ATRAC3Context; @@ -881,7 +879,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) return AVERROR(EINVAL); q->decoded_bytes_buffer = av_mallocz(FFALIGN(avctx->block_align, 4) + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!q->decoded_bytes_buffer) return AVERROR(ENOMEM); @@ -909,8 +907,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) } ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3); - avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); - ff_fmt_convert_init(&q->fmt_conv, avctx); + avpriv_float_dsp_init(&q->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); q->units = av_mallocz(sizeof(*q->units) * avctx->channels); if (!q->units) { @@ -931,7 +928,7 @@ AVCodec ff_atrac3_decoder = { .init_static_data = atrac3_init_static_data, .close = atrac3_decode_close, .decode = atrac3_decode_frame, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/atrac3plus.c b/libavcodec/atrac3plus.c index f337fab..076fb84 100644 --- a/libavcodec/atrac3plus.c +++ b/libavcodec/atrac3plus.c @@ -39,9 +39,6 @@ static VLC spec_vlc_tabs[112]; static VLC gain_vlc_tabs[11]; static VLC tone_vlc_tabs[7]; -#define GET_DELTA(gb, delta_bits) \ - ((delta_bits) ? get_bits((gb), (delta_bits)) : 0) - /** * Generate canonical VLC table from given descriptor. * @@ -384,7 +381,7 @@ static int decode_channel_wordlen(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, chan->qu_wordlen[i] = get_bits(gb, 3); for (i = pos; i < chan->num_coded_vals; i++) - chan->qu_wordlen[i] = (min_val + GET_DELTA(gb, delta_bits)) & 7; + chan->qu_wordlen[i] = (min_val + get_bitsz(gb, delta_bits)) & 7; } } break; @@ -516,7 +513,7 @@ static int decode_channel_sf_idx(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, /* all others are: min_val + delta */ for (i = num_long_vals; i < ctx->used_quant_units; i++) chan->qu_sf_idx[i] = (chan->qu_sf_idx[i] + min_val + - GET_DELTA(gb, delta_bits)) & 0x3F; + get_bitsz(gb, delta_bits)) & 0x3F; } else { num_long_vals = get_bits(gb, 5); delta_bits = get_bits(gb, 3); @@ -534,7 +531,7 @@ static int decode_channel_sf_idx(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, /* all others are: min_val + delta */ for (i = num_long_vals; i < ctx->used_quant_units; i++) chan->qu_sf_idx[i] = (min_val + - GET_DELTA(gb, delta_bits)) & 0x3F; + get_bitsz(gb, delta_bits)) & 0x3F; } } break; @@ -1014,7 +1011,7 @@ static int decode_gainc_npoints(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, min_val = get_bits(gb, 3); for (i = 0; i < coded_subbands; i++) { - chan->gain_data[i].num_points = min_val + GET_DELTA(gb, delta_bits); + chan->gain_data[i].num_points = min_val + get_bitsz(gb, delta_bits); if (chan->gain_data[i].num_points > 7) return AVERROR_INVALIDDATA; } @@ -1134,7 +1131,7 @@ static int decode_gainc_levels(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, for (sb = 0; sb < coded_subbands; sb++) for (i = 0; i < chan->gain_data[sb].num_points; i++) { - chan->gain_data[sb].lev_code[i] = min_val + GET_DELTA(gb, delta_bits); + chan->gain_data[sb].lev_code[i] = min_val + get_bitsz(gb, delta_bits); if (chan->gain_data[sb].lev_code[i] > 15) return AVERROR_INVALIDDATA; } @@ -1575,7 +1572,7 @@ static void decode_tones_amplitude(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, { int mode, sb, j, i, diff, maxdiff, fi, delta, pred; Atrac3pWaveParam *wsrc, *wref; - int refwaves[48]; + int refwaves[48] = { 0 }; Atrac3pWavesData *dst = ctx->channels[ch_num].tones_info; Atrac3pWavesData *ref = ctx->channels[0].tones_info; diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c index ddbfb53..4a742c1 100644 --- a/libavcodec/atrac3plusdec.c +++ b/libavcodec/atrac3plusdec.c @@ -148,7 +148,7 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - avpriv_float_dsp_init(&ctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&ctx->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); /* initialize IPQF */ ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0); @@ -387,6 +387,7 @@ AVCodec ff_atrac3p_decoder = { .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_ATRAC3P, + .capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(ATRAC3PContext), .init = atrac3p_decode_init, .init_static_data = ff_atrac3p_init_vlcs, diff --git a/libavcodec/audio_frame_queue.c b/libavcodec/audio_frame_queue.c index 0a8b25c..c4ca02b 100644 --- a/libavcodec/audio_frame_queue.c +++ b/libavcodec/audio_frame_queue.c @@ -29,8 +29,8 @@ av_cold void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq) { afq->avctx = avctx; afq->next_pts = AV_NOPTS_VALUE; - afq->remaining_delay = avctx->delay; - afq->remaining_samples = avctx->delay; + afq->remaining_delay = avctx->initial_padding; + afq->remaining_samples = avctx->initial_padding; afq->frame_queue = NULL; } @@ -56,12 +56,12 @@ void ff_af_queue_close(AudioFrameQueue *afq) static void af_queue_log_state(AudioFrameQueue *afq) { AudioFrame *f; - av_dlog(afq->avctx, "remaining delay = %d\n", afq->remaining_delay); - av_dlog(afq->avctx, "remaining samples = %d\n", afq->remaining_samples); - av_dlog(afq->avctx, "frames:\n"); + ff_dlog(afq->avctx, "remaining delay = %d\n", afq->remaining_delay); + ff_dlog(afq->avctx, "remaining samples = %d\n", afq->remaining_samples); + ff_dlog(afq->avctx, "frames:\n"); f = afq->frame_queue; while (f) { - av_dlog(afq->avctx, " [ pts=%9"PRId64" duration=%d ]\n", + ff_dlog(afq->avctx, " [ pts=%9"PRId64" duration=%d ]\n", f->pts, f->duration); f = f->next; } @@ -111,7 +111,7 @@ int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f) } void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, - int *duration) + int64_t *duration) { int64_t out_pts = AV_NOPTS_VALUE; int removed_samples = 0; diff --git a/libavcodec/audio_frame_queue.h b/libavcodec/audio_frame_queue.h index 4a29770..1250ec2 100644 --- a/libavcodec/audio_frame_queue.h +++ b/libavcodec/audio_frame_queue.h @@ -78,6 +78,6 @@ int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f); * @param[out] duration output packet duration */ void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, - int *duration); + int64_t *duration); #endif /* AVCODEC_AUDIO_FRAME_QUEUE_H */ diff --git a/libavcodec/aura.c b/libavcodec/aura.c index a32c18b..a1ef6f8 100644 --- a/libavcodec/aura.c +++ b/libavcodec/aura.c @@ -106,5 +106,5 @@ AVCodec ff_aura2_decoder = { .id = AV_CODEC_ID_AURA2, .init = aura_decode_init, .decode = aura_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 253e45a..7a5f10f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -74,7 +74,95 @@ * @{ * @} * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the decoder an AVFrame + * containing uncompressed audio or video. + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed. In + * general, no codec will permit unlimited buffering of input or output. + * + * This API replaces the following legacy functions: + * - avcodec_decode_video2() and avcodec_decode_audio4(): + * Use avcodec_send_packet() to feed input to the decoder, then use + * avcodec_receive_frame() to receive decoded frames after each packet. + * Unlike with the old video decoding API, multiple frames might result from + * a packet. For audio, splitting the input packet into frames by partially + * decoding packets becomes transparent to the API user. You never need to + * feed an AVPacket to the API twice. + * Additionally, sending a flush/draining packet is required only once. + * - avcodec_encode_video2()/avcodec_encode_audio2(): + * Use avcodec_send_frame() to feed input to the encoder, then use + * avcodec_receive_packet() to receive encoded packets. + * Providing user-allocated buffers for avcodec_receive_packet() is not + * possible. + * - The new API does not handle subtitles yet. + * + * Mixing new and old function calls on the same AVCodecContext is not allowed, + * and will result in arbitrary behavior. + * + * Some codecs might require using the new API; using the old API will return + * an error when calling it. + * @} */ /** @@ -293,6 +381,17 @@ enum AVCodecID { AV_CODEC_ID_SGIRLE, AV_CODEC_ID_MVC1, AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_AV1, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs @@ -326,6 +425,7 @@ enum AVCodecID { AV_CODEC_ID_PCM_S8_PLANAR, AV_CODEC_ID_PCM_S24LE_PLANAR, AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, /* various ADPCM codecs */ AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, @@ -444,6 +544,7 @@ enum AVCodecID { AV_CODEC_ID_METASOUND, AV_CODEC_ID_PAF_AUDIO, AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. @@ -468,12 +569,13 @@ enum AVCodecID { AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems * stream (only used by libavformat) */ AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket }; /** * This struct describes the properties of a single codec described by an * AVCodecID. - * @see avcodec_get_descriptor() + * @see avcodec_descriptor_get() */ typedef struct AVCodecDescriptor { enum AVCodecID id; @@ -492,6 +594,11 @@ typedef struct AVCodecDescriptor { * Codec properties, a combination of AV_CODEC_PROP_* flags. */ int props; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with FF_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; } AVCodecDescriptor; /** @@ -528,20 +635,33 @@ typedef struct AVCodecDescriptor { * 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 +#define AV_INPUT_BUFFER_PADDING_SIZE 8 /** * @ingroup lavc_encoding * minimum encoding buffer size * Used to avoid some checks during header writing. */ -#define FF_MIN_BUFFER_SIZE 16384 +#define AV_INPUT_BUFFER_MIN_SIZE 16384 + +#if FF_API_WITHOUT_PREFIX +/** + * @deprecated use AV_INPUT_BUFFER_PADDING_SIZE instead + */ +#define FF_INPUT_BUFFER_PADDING_SIZE 8 +/** + * @deprecated use AV_INPUT_BUFFER_MIN_SIZE instead + */ +#define FF_MIN_BUFFER_SIZE 16384 +#endif /* FF_API_WITHOUT_PREFIX */ /** * @ingroup lavc_encoding * motion estimation type. + * @deprecated use codec private option instead */ +#if FF_API_MOTION_EST enum Motion_Est_ID { ME_ZERO = 1, ///< no search, that is use 0,0 vector whenever one is needed ME_FULL, @@ -553,6 +673,7 @@ enum Motion_Est_ID { ME_UMH, ///< uneven multi-hexagon search ME_TESA, ///< transformed exhaustive search algorithm }; +#endif /** * @ingroup lavc_decoding @@ -607,6 +728,191 @@ typedef struct RcOverride{ * Allow decoders to produce frames with data planes that are not aligned * to CPU requirements (e.g. due to cropping). */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Input bitstream might be truncated at a random location + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG_TRUNCATED (1 << 16) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1 << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() for allocating buffers and supports custom allocators. + * If not set, it might not use get_buffer() at all or use operations that + * assume the buffer was allocated by avcodec_default_get_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +#define AV_CODEC_CAP_TRUNCATED (1 << 3) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports avctx->thread_count == 0 (auto). + */ +#define AV_CODEC_CAP_AUTO_THREADS (1 << 15) +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) + +#if FF_API_WITHOUT_PREFIX +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ #define CODEC_FLAG_UNALIGNED 0x0001 #define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale. #define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. @@ -656,7 +962,7 @@ typedef struct RcOverride{ #define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. #define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. #define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT). -/* Fx : Flag for h263+ extra options */ +/* Fx : Flag for H.263+ extra options */ #define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction #define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter #define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation @@ -728,7 +1034,7 @@ typedef struct RcOverride{ * are connected to a parser to split what they return into proper frames. * This flag is reserved to the very rare category of codecs which have a * bitstream that cannot be split into frames without timeconsuming - * operations like full decoding. Demuxers carring such bitstreams thus + * operations like full decoding. Demuxers carrying such bitstreams thus * may return multiple frames in a packet. This has many disadvantages like * prohibiting stream copy in many cases thus it should only be considered * as a last resort. @@ -769,6 +1075,7 @@ typedef struct RcOverride{ * Audio encoder supports receiving a different number of samples in each call. */ #define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 +#endif /* FF_API_WITHOUT_PREFIX */ #if FF_API_MB_TYPE //The following defines may change, don't expect compatibility if you use them. @@ -793,7 +1100,7 @@ typedef struct RcOverride{ #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, ...) +// Note bits 24-31 are reserved for codec specific use (H.264 ref0, MPEG-1 0mv, ...) #endif /** @@ -825,6 +1132,44 @@ typedef struct AVPanScan{ int16_t position[3][2]; }AVPanScan; +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int max_bitrate; + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int min_bitrate; + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ + int avg_bitrate; + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + #if FF_API_QSCALE_TYPE #define FF_QSCALE_TYPE_MPEG1 0 #define FF_QSCALE_TYPE_MPEG2 1 @@ -832,18 +1177,6 @@ typedef struct AVPanScan{ #define FF_QSCALE_TYPE_VP56 3 #endif -#if FF_API_GET_BUFFER -#define FF_BUFFER_TYPE_INTERNAL 1 -#define FF_BUFFER_TYPE_USER 2 ///< direct rendering buffers (image is (de)allocated by user) -#define FF_BUFFER_TYPE_SHARED 4 ///< Buffer from somewhere else; don't deallocate image (data/base), all other tables are not shared. -#define FF_BUFFER_TYPE_COPY 8 ///< Just a (modified) copy of some other buffer, don't deallocate anything. - -#define FF_BUFFER_HINTS_VALID 0x01 // Buffer hints value is meaningful (if 0 ignore). -#define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer. -#define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content. -#define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update). -#endif - /** * The decoder will keep a reference to the frame and may reuse it later. */ @@ -857,6 +1190,14 @@ typedef struct AVPanScan{ */ enum AVPacketSideDataType { AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ AV_PKT_DATA_NEW_EXTRADATA, /** @@ -917,6 +1258,32 @@ enum AVPacketSideDataType { * Stereoscopic 3D information in form of the AVStereo3D struct. */ AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains an integer value representing the quality + * factor of the compressed frame. Allowed range is between 1 (good) + * and FF_LAMBDA_MAX (bad). + */ + AV_PKT_DATA_QUALITY_FACTOR, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, }; typedef struct AVPacketSideData { @@ -931,21 +1298,27 @@ typedef struct AVPacketSideData { * then passed to muxers. * * For video, it should typically contain one compressed frame. For audio it may - * contain several compressed frames. + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). * * AVPacket is one of the few structs in Libav, whose size is a part of public * ABI. Thus it may be allocated on stack and no new fields can be added to it * without libavcodec and libavformat major bump. * - * The semantics of data ownership depends on the buf or destruct (deprecated) - * fields. If either is set, the packet data is dynamically allocated and is - * valid indefinitely until av_free_packet() is called (which in turn calls - * av_buffer_unref()/the destruct callback to free the data). If neither is set, - * the packet data is typically backed by some static buffer somewhere and is - * only valid for a limited time (e.g. until the next read call when demuxing). + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. * - * The side data is always allocated with av_malloc() and is freed in - * av_free_packet(). + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * @see av_packet_ref + * @see av_packet_unref */ typedef struct AVPacket { /** @@ -988,33 +1361,19 @@ typedef struct AVPacket { * Duration of this packet in AVStream->time_base units, 0 if unknown. * Equals next_pts - this_pts in presentation order. */ - int duration; -#if FF_API_DESTRUCT_PACKET - attribute_deprecated - void (*destruct)(struct AVPacket *); - attribute_deprecated - void *priv; -#endif + int64_t duration; + int64_t pos; ///< byte position in stream, -1 if unknown +#if FF_API_CONVERGENCE_DURATION /** - * Time difference in AVStream->time_base units from the pts of this - * packet to the point at which the output from the decoder has converged - * independent from the availability of previous frames. That is, the - * frames are virtually identical no matter if decoding started from - * the very first frame or from this keyframe. - * Is AV_NOPTS_VALUE if unknown. - * This field is not the display duration of the current packet. - * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY - * set. - * - * The purpose of this field is to allow seeking in streams that have no - * keyframes in the conventional sense. It corresponds to the - * recovery point SEI in H.264 and match_time_delta in NUT. It is also - * essential for some types of subtitle streams to ensure that all - * subtitles are correctly displayed after seeking. + * @deprecated Same as the duration field, but as int64_t. This was required + * for Matroska subtitles, whose duration values could overflow when the + * duration field was still an int. */ + attribute_deprecated int64_t convergence_duration; +#endif } AVPacket; #define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe #define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted @@ -1081,13 +1440,13 @@ typedef struct AVCodecContext { */ unsigned int codec_tag; +#if FF_API_STREAM_CODEC_TAG /** - * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). - * This is used to work around some encoder bugs. - * - encoding: unused - * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + * @deprecated this field is unused */ + attribute_deprecated unsigned int stream_codec_tag; +#endif void *priv_data; @@ -1137,14 +1496,14 @@ typedef struct AVCodecContext { #define FF_COMPRESSION_DEFAULT -1 /** - * CODEC_FLAG_*. + * AV_CODEC_FLAG_*. * - encoding: Set by user. * - decoding: Set by user. */ int flags; /** - * CODEC_FLAG2_* + * AV_CODEC_FLAG2_* * - encoding: Set by user. * - decoding: Set by user. */ @@ -1152,11 +1511,11 @@ typedef struct AVCodecContext { /** * some codecs need / can use extradata like Huffman tables. - * mjpeg: Huffman tables + * MJPEG: Huffman tables * rv10: additional flags - * mpeg4: global headers (they can be in the bitstream or here) - * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger - * than extradata_size to avoid prolems if it is read with the bitstream reader. + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. * The bytewise contents of extradata must not depend on the architecture or CPU endianness. * - encoding: Set/allocated/freed by libavcodec. * - decoding: Set/allocated/freed by user. @@ -1170,7 +1529,8 @@ typedef struct AVCodecContext { * timebase should be 1/framerate and timestamp increments should be * identically 1. * - encoding: MUST be set by user. - * - decoding: Set by libavcodec. + * - decoding: the use of this field for decoding is deprecated. + * Use framerate instead. */ AVRational time_base; @@ -1191,16 +1551,7 @@ typedef struct AVCodecContext { * encoded input. * * Audio: - * For encoding, this is the number of "priming" samples added by the - * encoder to the beginning of the stream. The decoded output will be - * delayed by this many samples relative to the input to the encoder (or - * more, if the decoder adds its own padding). - * The timestamps on the output packets are adjusted by the encoder so - * that they always refer to the first sample of the data actually - * contained in the packet, including any added padding. - * E.g. if the timebase is 1/samplerate and the timestamp of the first - * input sample is 0, the timestamp of the first output packet will be - * -delay. + * For encoding, this field is unused (see initial_padding). * * For decoding, this is the number of samples the decoder needs to * output before the decoder's output is valid. When seeking, you should @@ -1215,21 +1566,31 @@ typedef struct AVCodecContext { /* video only */ /** * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_decode_video2 due frame + * reordering. + * * - encoding: MUST be set by user. * - decoding: May be set by the user before opening the decoder if known e.g. * from the container. Some decoders will require the dimensions * to be set by the caller. During decoding, the decoder may - * overwrite those values as required. + * overwrite those values as required while parsing the data. */ int width, height; /** * Bitstream width / height, may be different from width/height e.g. when * the decoded frame is cropped before being output. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * * - encoding: unused * - decoding: May be set by the user before opening the decoder if known * e.g. from the container. During decoding, the decoder may - * overwrite those values as required. + * overwrite those values as required while parsing the data. */ int coded_width, coded_height; @@ -1247,20 +1608,25 @@ typedef struct AVCodecContext { /** * Pixel format, see AV_PIX_FMT_xxx. * May be set by the demuxer if known from headers. - * May be overriden by the decoder if it knows better. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * * - encoding: Set by user. - * - decoding: Set by user if known, overridden by libavcodec if known + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. */ enum AVPixelFormat pix_fmt; +#if FF_API_MOTION_EST /** - * Motion estimation algorithm used for video coding. - * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), - * 8 (umh), 10 (tesa) [7, 8, 10 are x264 specific] - * - encoding: MUST be set by user. - * - decoding: unused + * This option does nothing + * @deprecated use codec private options instead */ - int me_method; + attribute_deprecated int me_method; +#endif /** * If non NULL, 'draw_horiz_band' is called by the libavcodec @@ -1294,6 +1660,10 @@ typedef struct AVCodecContext { * @param fmt is the list of formats which are supported by the codec, * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. * The first is always the native one. + * @note The callback may be called again immediately if initialization for + * the selected (hardware-accelerated) pixel format failed. + * @warning Behavior is undefined if the callback returns a value not + * in the fmt list of formats. * @return the chosen format * - encoding: unused * - decoding: Set by user, if not set the native format will be chosen. @@ -1317,11 +1687,17 @@ typedef struct AVCodecContext { */ float b_quant_factor; - /** obsolete FIXME remove */ - int rc_strategy; +#if FF_API_RC_STRATEGY + /** @deprecated use codec private option instead */ + attribute_deprecated int rc_strategy; #define FF_RC_STRATEGY_XVID 1 +#endif +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int b_frame_strategy; +#endif /** * qscale offset between IP and B-frames @@ -1338,16 +1714,15 @@ typedef struct AVCodecContext { */ int has_b_frames; - /** - * 0-> h263 quant 1-> mpeg quant - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int mpeg_quant; +#endif /** - * qscale factor between P and I-frames - * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset). + * 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 @@ -1402,15 +1777,15 @@ typedef struct AVCodecContext { * - decoding: Set by user (or 0). */ int slice_count; - /** - * prediction method (needed for huffyuv) - * - encoding: Set by user. - * - decoding: unused - */ + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int prediction_method; #define FF_PRED_LEFT 0 #define FF_PRED_PLANE 1 #define FF_PRED_MEDIAN 2 +#endif /** * slice offsets in the frame in bytes @@ -1481,12 +1856,11 @@ typedef struct AVCodecContext { */ int last_predictor_count; - /** - * prepass for motion estimation - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int pre_me; +#endif /** * motion estimation prepass comparison function @@ -1538,20 +1912,18 @@ typedef struct AVCodecContext { */ int me_range; +#if FF_API_QUANT_BIAS /** - * intra quantizer bias - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private option instead */ - int intra_quant_bias; + attribute_deprecated int intra_quant_bias; #define FF_DEFAULT_QUANT_BIAS 999999 /** - * inter quantizer bias - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private option instead */ - int inter_quant_bias; + attribute_deprecated int inter_quant_bias; +#endif /** * slice flags @@ -1560,7 +1932,7 @@ typedef struct AVCodecContext { */ 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_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) #define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) #if FF_API_XVMC @@ -1597,36 +1969,29 @@ typedef struct AVCodecContext { */ uint16_t *inter_matrix; - /** - * scene change detection threshold - * 0 is default, larger means fewer detected scene changes. - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int scenechange_threshold; - /** - * noise reduction strength - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int noise_reduction; +#endif +#if FF_API_MPV_OPT /** - * Motion estimation threshold below which no motion estimation is - * performed, but instead the user specified motion vectors are used. - * - * - encoding: Set by user. - * - decoding: unused + * @deprecated this field is unused */ + attribute_deprecated int me_threshold; /** - * Macroblock threshold below which the user specified macroblock types will be used. - * - encoding: Set by user. - * - decoding: unused + * @deprecated this field is unused */ + attribute_deprecated int mb_threshold; +#endif /** * precision of the intra DC coefficient - 8 @@ -1649,48 +2014,47 @@ typedef struct AVCodecContext { */ int skip_bottom; +#if FF_API_MPV_OPT /** - * Border processing masking, raises the quantizer for mbs on the borders - * of the picture. - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated float border_masking; +#endif /** - * minimum MB lagrange multipler + * minimum MB Lagrange multiplier * - encoding: Set by user. * - decoding: unused */ int mb_lmin; /** - * maximum MB lagrange multipler + * maximum MB Lagrange multiplier * - encoding: Set by user. * - decoding: unused */ int mb_lmax; +#if FF_API_PRIVATE_OPT /** - * - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated int me_penalty_compensation; +#endif /** - * * - encoding: Set by user. * - decoding: unused */ int bidir_refine; - /** - * - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int brd_scale; +#endif /** * minimum GOP size @@ -1706,12 +2070,11 @@ typedef struct AVCodecContext { */ int refs; - /** - * chroma qp offset from luma - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int chromaoffset; +#endif #if FF_API_UNUSED_MEMBERS /** @@ -1723,19 +2086,17 @@ typedef struct AVCodecContext { #endif /** - * * Note: Value depends upon the compare function used for fullpel ME. * - encoding: Set by user. * - decoding: unused */ int mv0_threshold; - /** - * Adjust sensitivity of b_frame_strategy 1. - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int b_sensitivity; +#endif /** * Chromaticity coordinates of the source primaries. @@ -1804,7 +2165,7 @@ typedef struct AVCodecContext { * * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame * except the last must contain exactly frame_size samples per channel. - * May be 0 when the codec has CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the * frame size is not restricted. * - decoding: may be set by some decoders to indicate constant frame size */ @@ -1834,16 +2195,6 @@ typedef struct AVCodecContext { */ int cutoff; -#if FF_API_REQUEST_CHANNELS - /** - * Decoder should decode to this many channels if it can (0 for default) - * - encoding: unused - * - decoding: Set by user. - * @deprecated Deprecated in favor of request_channel_layout. - */ - attribute_deprecated int request_channels; -#endif - /** * Audio channel layout. * - encoding: set by user. @@ -1872,102 +2223,6 @@ typedef struct AVCodecContext { */ enum AVSampleFormat request_sample_fmt; -#if FF_API_GET_BUFFER - /** - * Called at the beginning of each frame to get a buffer for it. - * - * The function will set AVFrame.data[], AVFrame.linesize[]. - * AVFrame.extended_data[] must also be set, but it should be the same as - * AVFrame.data[] except for planar audio with more channels than can fit - * in AVFrame.data[]. In that case, AVFrame.data[] shall still contain as - * many data pointers as it can hold. - * - * if CODEC_CAP_DR1 is not set then get_buffer() must call - * avcodec_default_get_buffer() instead of providing buffers allocated by - * some other means. - * - * AVFrame.data[] should be 32- or 16-byte-aligned unless the CPU doesn't - * need it. avcodec_default_get_buffer() aligns the output buffer properly, - * but if get_buffer() is overridden then alignment considerations should - * be taken into account. - * - * @see avcodec_default_get_buffer() - * - * Video: - * - * If pic.reference is set then the frame will be read later by libavcodec. - * avcodec_align_dimensions2() should be used to find the required width and - * height, as they normally need to be rounded up to the next multiple of 16. - * - * If frame multithreading is used and thread_safe_callbacks is set, - * it may be called from a different thread, but not from more than one at - * once. Does not need to be reentrant. - * - * @see release_buffer(), reget_buffer() - * @see avcodec_align_dimensions2() - * - * Audio: - * - * Decoders request a buffer of a particular size by setting - * AVFrame.nb_samples prior to calling get_buffer(). The decoder may, - * however, utilize only part of the buffer by setting AVFrame.nb_samples - * to a smaller value in the output frame. - * - * Decoders cannot use the buffer after returning from - * avcodec_decode_audio4(), so they will not call release_buffer(), as it - * is assumed to be released immediately upon return. In some rare cases, - * a decoder may need to call get_buffer() more than once in a single - * call to avcodec_decode_audio4(). In that case, when get_buffer() is - * called again after it has already been called once, the previously - * acquired buffer is assumed to be released at that time and may not be - * reused by the decoder. - * - * As a convenience, av_samples_get_buffer_size() and - * av_samples_fill_arrays() in libavutil may be used by custom get_buffer() - * functions to find the required data size and to fill data pointers and - * linesize. In AVFrame.linesize, only linesize[0] may be set for audio - * since all planes must be the same size. - * - * @see av_samples_get_buffer_size(), av_samples_fill_arrays() - * - * - encoding: unused - * - decoding: Set by libavcodec, user can override. - * - * @deprecated use get_buffer2() - */ - attribute_deprecated - int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); - - /** - * Called to release buffers which were allocated with get_buffer. - * A released buffer can be reused in get_buffer(). - * pic.data[*] must be set to NULL. - * May be called from a different thread if frame multithreading is used, - * but not by more than one thread at once, so does not need to be reentrant. - * - encoding: unused - * - decoding: Set by libavcodec, user can override. - * - * @deprecated custom freeing callbacks should be set from get_buffer2() - */ - attribute_deprecated - void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); - - /** - * Called at the beginning of a frame to get cr buffer for it. - * Buffer type (size, hints) must be the same. libavcodec won't check it. - * libavcodec will pass previous buffer in pic, function should return - * same buffer or new buffer with old frame "painted" into it. - * If pic.data[0] == NULL must behave like get_buffer(). - * if CODEC_CAP_DR1 is not set then reget_buffer() must call - * avcodec_default_reget_buffer() instead of providing buffers allocated by - * some other means. - * - encoding: unused - * - decoding: Set by libavcodec, user can override. - */ - attribute_deprecated - int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); -#endif - /** * This callback is called at the beginning of each frame to get data * buffer(s) for it. There may be one contiguous buffer for all the data or @@ -1994,7 +2249,7 @@ typedef struct AVCodecContext { * to all data planes. data[] must hold as many pointers as it can. * extended_data must be allocated with av_malloc() and will be freed in * av_frame_unref(). - * * otherwise exended_data must point to data + * * otherwise extended_data must point to data * - buf[] must contain one or more pointers to AVBufferRef structures. Each of * the frame's data and extended_data pointers must be contained in these. That * is, one AVBufferRef for each allocated chunk of memory, not necessarily one @@ -2005,7 +2260,7 @@ typedef struct AVCodecContext { * buffers than buf[] can hold. extended_buf will be freed in * av_frame_unref(). * - * If CODEC_CAP_DR1 is not set then get_buffer2() must call + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call * avcodec_default_get_buffer2() instead of providing buffers allocated by * some other means. * @@ -2056,6 +2311,8 @@ typedef struct AVCodecContext { * Otherwise, the decoded frames must not be freed by the caller and are * only valid until the next decode call. * + * This is always automatically enabled if avcodec_receive_frame() is used. + * * - encoding: unused * - decoding: set by the caller before avcodec_open2(). */ @@ -2086,16 +2343,18 @@ typedef struct AVCodecContext { */ int max_qdiff; +#if FF_API_MPV_OPT /** - * ratecontrol qmin qmax limiting method - * 0-> clipping, 1-> use a nice continuous function to limit qscale wthin qmin/qmax. - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated float rc_qsquish; + attribute_deprecated float rc_qmod_amp; + attribute_deprecated int rc_qmod_freq; +#endif /** * decoder bitstream buffer size @@ -2112,12 +2371,13 @@ typedef struct AVCodecContext { int rc_override_count; RcOverride *rc_override; +#if FF_API_MPV_OPT /** - * rate control equation - * - encoding: Set by user - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated const char *rc_eq; +#endif /** * maximum bitrate @@ -2133,14 +2393,16 @@ typedef struct AVCodecContext { */ int rc_min_rate; - float rc_buffer_aggressivity; - +#if FF_API_MPV_OPT /** - * initial complexity for pass1 ratecontrol - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated + float rc_buffer_aggressivity; + + attribute_deprecated float rc_initial_cplx; +#endif /** * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. @@ -2163,6 +2425,7 @@ typedef struct AVCodecContext { */ int rc_initial_buffer_occupancy; +#if FF_API_CODER_TYPE #define FF_CODER_TYPE_VLC 0 #define FF_CODER_TYPE_AC 1 #define FF_CODER_TYPE_RAW 2 @@ -2171,60 +2434,49 @@ typedef struct AVCodecContext { #define FF_CODER_TYPE_DEFLATE 4 #endif /* FF_API_UNUSED_MEMBERS */ /** - * coder type - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated int coder_type; +#endif /* FF_API_CODER_TYPE */ - /** - * context model - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int context_model; +#endif +#if FF_API_MPV_OPT /** - * minimum Lagrange multipler - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated int lmin; /** - * maximum Lagrange multipler - * - encoding: Set by user. - * - decoding: unused + * @deprecated use encoder private options instead */ + attribute_deprecated int lmax; +#endif - /** - * frame skip threshold - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int frame_skip_threshold; - /** - * frame skip factor - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int frame_skip_factor; - /** - * frame skip exponent - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int frame_skip_exp; - /** - * frame skip comparison function - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int frame_skip_cmp; +#endif /* FF_API_PRIVATE_OPT */ /** * trellis RD quantization @@ -2233,56 +2485,68 @@ typedef struct AVCodecContext { */ int trellis; - /** - * - encoding: Set by user. - * - decoding: unused - */ +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int min_prediction_order; - /** - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int max_prediction_order; - /** - * GOP timecode frame start number, in non drop frame format - * - encoding: Set by user. - * - decoding: unused - */ + /** @deprecated use encoder private options instead */ + attribute_deprecated int64_t timecode_frame_start; +#endif +#if FF_API_RTP_CALLBACK + /** + * @deprecated unused + */ /* The RTP callback: This function is called */ /* every time the encoder has a packet to send. */ /* It depends on the encoder if the data starts */ /* with a Start Code (it should). H.263 does. */ /* mb_nb contains the number of macroblocks */ /* encoded in the RTP payload. */ + attribute_deprecated void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); +#endif +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated int rtp_payload_size; /* The size of the RTP payload: the coder will */ /* do its best to deliver a chunk with size */ /* below rtp_payload_size, the chunk will start */ /* with a start code on some codecs like H.263. */ /* This doesn't take account of any particular */ /* headers inside the transmitted RTP payload. */ +#endif +#if FF_API_STAT_BITS /* statistics, used for 2-pass encoding */ + attribute_deprecated int mv_bits; + attribute_deprecated int header_bits; + attribute_deprecated int i_tex_bits; + attribute_deprecated int p_tex_bits; + attribute_deprecated int i_count; + attribute_deprecated int p_count; + attribute_deprecated int skip_count; + attribute_deprecated int misc_bits; - /** - * number of bits used for the previously encoded frame - * - encoding: Set by libavcodec. - * - decoding: unused - */ + /** @deprecated this field is unused */ + attribute_deprecated int frame_bits; +#endif /** * pass1 encoding statistics output buffer @@ -2327,7 +2591,7 @@ typedef struct AVCodecContext { #define FF_BUG_TRUNCATED 16384 /** - * strictly follow the standard (MPEG4, ...). + * strictly follow the standard (MPEG-4, ...). * - encoding: Set by user. * - decoding: Set by user. * Setting this to STRICT or higher means the encoder and decoder will @@ -2393,9 +2657,9 @@ typedef struct AVCodecContext { */ attribute_deprecated 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 +#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 #endif /** @@ -2417,7 +2681,7 @@ typedef struct AVCodecContext { #define AV_EF_EXPLODE (1<<3) /** - * opaque 64bit number (generally a PTS) that will be reordered and + * opaque 64-bit number (generally a PTS) that will be reordered and * output in AVFrame.reordered_opaque * - encoding: unused * - decoding: Set by user. @@ -2445,7 +2709,7 @@ typedef struct AVCodecContext { /** * error - * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR. + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. * - decoding: unused */ uint64_t error[AV_NUM_DATA_POINTERS]; @@ -2458,9 +2722,7 @@ typedef struct AVCodecContext { int dct_algo; #define FF_DCT_AUTO 0 #define FF_DCT_FASTINT 1 -#if FF_API_UNUSED_MEMBERS #define FF_DCT_INT 2 -#endif /* FF_API_UNUSED_MEMBERS */ #define FF_DCT_MMX 3 #define FF_DCT_ALTIVEC 5 #define FF_DCT_FAAN 6 @@ -2524,12 +2786,16 @@ typedef struct AVCodecContext { attribute_deprecated int lowres; #endif +#if FF_API_CODED_FRAME /** * the picture in the bitstream * - encoding: Set by libavcodec. * - decoding: unused + * + * @deprecated use the quality factor packet side data instead */ - AVFrame *coded_frame; + attribute_deprecated AVFrame *coded_frame; +#endif /** * thread count @@ -2599,16 +2865,8 @@ typedef struct AVCodecContext { */ int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); -#if FF_API_THREAD_OPAQUE - /** - * @deprecated this field should not be used from outside of lavc - */ - attribute_deprecated - void *thread_opaque; -#endif - /** - * noise vs. sse weight for the nsse comparsion function + * noise vs. sse weight for the nsse comparison function * - encoding: Set by user. * - decoding: unused */ @@ -2639,6 +2897,7 @@ typedef struct AVCodecContext { #define FF_PROFILE_DTS_96_24 40 #define FF_PROFILE_DTS_HD_HRA 50 #define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 #define FF_PROFILE_MPEG2_422 0 #define FF_PROFILE_MPEG2_HIGH 1 @@ -2657,8 +2916,10 @@ typedef struct AVCodecContext { #define FF_PROFILE_H264_HIGH 100 #define FF_PROFILE_H264_HIGH_10 110 #define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 #define FF_PROFILE_H264_HIGH_422 122 #define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 #define FF_PROFILE_H264_HIGH_444 144 #define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 #define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) @@ -2686,12 +2947,16 @@ typedef struct AVCodecContext { #define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 #define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 -#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 0 -#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 1 -#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 2 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 #define FF_PROFILE_JPEG2000_DCINEMA_2K 3 #define FF_PROFILE_JPEG2000_DCINEMA_4K 4 +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 #define FF_PROFILE_HEVC_MAIN 1 #define FF_PROFILE_HEVC_MAIN_10 2 @@ -2706,21 +2971,18 @@ typedef struct AVCodecContext { #define FF_LEVEL_UNKNOWN -99 /** - * * - 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. */ @@ -2746,36 +3008,98 @@ typedef struct AVCodecContext { int error_rate; #endif -#if FF_API_CODEC_PKT - /** - * @deprecated this field is not supposed to be accessed from outside lavc - */ - attribute_deprecated - AVPacket *pkt; -#endif - +#if FF_API_VBV_DELAY /** * VBV delay coded in the last frame (in periods of a 27 MHz clock). * Used for compliant TS muxing. * - encoding: Set by libavcodec. * - decoding: unused. + * @deprecated this value is now exported as a part of + * AV_PKT_DATA_CPB_PROPERTIES packet side data */ + attribute_deprecated uint64_t vbv_delay; +#endif +#if FF_API_SIDEDATA_ONLY_PKT /** - * Encoding only. Allow encoders to output packets that do not contain any - * encoded data, only side data. + * Encoding only and set by default. Allow encoders to output packets + * that do not contain any encoded data, only side data. * * Some encoders need to output such packets, e.g. to update some stream * parameters at the end of encoding. * - * All callers are strongly recommended to set this option to 1 and update - * their code to deal with such packets, since this behaviour may become - * always enabled in the future (then this option will be deprecated and - * later removed). To avoid ABI issues when this happens, the callers should - * use AVOptions to set this field. + * @deprecated this field disables the default behaviour and + * it is kept only for compatibility. */ + attribute_deprecated int side_data_only_packets; +#endif + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /* + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: unused + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; } AVCodecContext; /** @@ -2810,7 +3134,7 @@ typedef struct AVCodec { enum AVCodecID id; /** * Codec capabilities. - * see CODEC_CAP_* + * see AV_CODEC_CAP_* */ int capabilities; const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} @@ -2881,14 +3205,35 @@ typedef struct AVCodec { int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); int (*close)(AVCodecContext *); /** + * Decode/encode API with decoupled packet/frame dataflow. The API is the + * same as the avcodec_ prefixed APIs (avcodec_send_frame() etc.), except + * that: + * - never called if the codec is closed or the wrong type, + * - AVPacket parameter change side data is applied right before calling + * AVCodec->send_packet, + * - if AV_CODEC_CAP_DELAY is not set, drain packets or frames are never sent, + * - only one drain packet is ever passed down (until the next flush()), + * - a drain AVPacket is always NULL (no need to check for avpkt->size). + */ + int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame); + int (*send_packet)(AVCodecContext *avctx, const AVPacket *avpkt); + int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame); + int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt); + /** * Flush buffers. * Will be called when seeking */ void (*flush)(AVCodecContext *); + /** + * Internal codec capabilities. + * See FF_CODEC_CAP_* in internal.h + */ + int caps_internal; } AVCodec; /** - * AVHWAccel. + * @defgroup lavc_hwaccel AVHWAccel + * @{ */ typedef struct AVHWAccel { /** @@ -3013,6 +3358,24 @@ typedef struct AVHWAccel { } AVHWAccel; /** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * @} + */ + +#if FF_API_AVPICTURE +/** * @defgroup lavc_picture AVPicture * * Functions for working with AVPicture @@ -3022,15 +3385,19 @@ typedef struct AVHWAccel { /** * four components are given, that's all. * the last component is alpha + * @deprecated Use the imgutils functions */ typedef struct AVPicture { + attribute_deprecated uint8_t *data[AV_NUM_DATA_POINTERS]; + attribute_deprecated int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line } AVPicture; /** * @} */ +#endif #define AVPALETTE_SIZE 1024 #define AVPALETTE_COUNT 256 @@ -3062,18 +3429,27 @@ typedef struct AVSubtitleRect { int h; ///< height of pict, undefined when pict is not set int nb_colors; ///< number of colors in pict, undefined when pict is not set +#if FF_API_AVPICTURE /** - * data+linesize for the bitmap of this subtitle. - * can be set for text/ass as well once they where rendered + * @deprecated unused */ + attribute_deprecated AVPicture pict; +#endif + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + enum AVSubtitleType type; char *text; ///< 0 terminated plain UTF-8 text /** * 0 terminated ASS/SSA compatible event line. - * The pressentation of this is unaffected by the other values in this + * The presentation of this is unaffected by the other values in this * struct. */ char *ass; @@ -3090,11 +3466,132 @@ typedef struct AVSubtitle { } AVSubtitle; /** - * If c is NULL, returns the first registered codec, - * if c is non-NULL, returns the next registered codec after c, - * or NULL if c is the last one. + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). */ -AVCodec *av_codec_next(const AVCodec *c); +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int bit_rate; + + int bits_per_coded_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + */ + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + */ + int channels; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; +} AVCodecParameters; + +/** + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. + */ +AVCodec *av_codec_next(const AVCodec *c); /** * Return the LIBAVCODEC_VERSION_INT constant. @@ -3145,7 +3642,6 @@ void avcodec_register_all(void); * important mainly for encoders, e.g. libx264). * * @return An AVCodecContext filled with default values or NULL on failure. - * @see avcodec_get_context_defaults */ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); @@ -3155,16 +3651,14 @@ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); */ void avcodec_free_context(AVCodecContext **avctx); +#if FF_API_GET_CONTEXT_DEFAULTS /** - * Set the fields of the given AVCodecContext to default values corresponding - * to the given codec (defaults may be codec-dependent). - * - * Do not call this function if a non-NULL codec has been passed - * to avcodec_alloc_context3() that allocated this AVCodecContext. - * If codec is non-NULL, it is illegal to call avcodec_open2() with a - * different codec on this AVCodecContext. + * @deprecated This function should not be used, as closing and opening a codec + * context multiple time is not supported. A new codec context should be + * allocated for each new use. */ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); +#endif /** * Get the AVClass for AVCodecContext. It can be used in combination with @@ -3174,6 +3668,7 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); */ const AVClass *avcodec_get_class(void); +#if FF_API_COPY_CONTEXT /** * Copy the settings of the source AVCodecContext into the destination * AVCodecContext. The resulting destination codec context will be @@ -3184,41 +3679,58 @@ const AVClass *avcodec_get_class(void); * avcodec_alloc_context3(), but otherwise uninitialized * @param src source codec context * @return AVERROR() on error (e.g. memory allocation error), 0 on success + * + * @deprecated The semantics of this function are ill-defined and it should not + * be used. If you need to transfer the stream parameters from one codec context + * to another, use an intermediate AVCodecParameters instance and the + * avcodec_parameters_from_context() / avcodec_parameters_to_context() + * functions. */ +attribute_deprecated int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); +#endif -#if FF_API_AVFRAME_LAVC /** - * @deprecated use av_frame_alloc() + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). */ -attribute_deprecated -AVFrame *avcodec_alloc_frame(void); +AVCodecParameters *avcodec_parameters_alloc(void); /** - * Set the fields of the given AVFrame to default values. - * - * @param frame The AVFrame of which the fields should be set to default values. - * - * @deprecated use av_frame_unref() + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. */ -attribute_deprecated -void avcodec_get_frame_defaults(AVFrame *frame); +void avcodec_parameters_free(AVCodecParameters **par); /** - * Free the frame and any dynamically allocated objects in it, - * e.g. extended_data. + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. * - * @param frame frame to be freed. The pointer will be set to NULL. + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. * - * @warning this function does NOT free the data buffers themselves - * (it does not know how, since they might have been allocated with - * a custom get_buffer()). + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. * - * @deprecated use av_frame_free() + * @return >= 0 on success, a negative AVERROR code on failure. */ -attribute_deprecated -void avcodec_free_frame(AVFrame **frame); -#endif +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par); /** * Initialize the AVCodecContext to use the given AVCodec. Prior to using this @@ -3230,6 +3742,9 @@ void avcodec_free_frame(AVFrame **frame); * * @warning This function is not thread safe! * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * * @code * avcodec_register_all(); * av_dict_set(&opts, "b", "2.5M", 0); @@ -3246,9 +3761,8 @@ void avcodec_free_frame(AVFrame **frame); * @param avctx The context to initialize. * @param codec The codec to open this context for. If a non-NULL codec has been * previously passed to avcodec_alloc_context3() or - * avcodec_get_context_defaults3() for this context, then this - * parameter MUST be either NULL or equal to the previously passed - * codec. + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. * @param options A dictionary filled with AVCodecContext and codec-private options. * On return this object will be filled with options that were not found. * @@ -3263,9 +3777,13 @@ int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **op * (but not the AVCodecContext itself). * * Calling this function on an AVCodecContext that hasn't been opened will free - * the codec-specific data allocated in avcodec_alloc_context3() / - * avcodec_get_context_defaults3() with a non-NULL codec. Subsequent calls will - * do nothing. + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. */ int avcodec_close(AVCodecContext *avctx); @@ -3285,14 +3803,39 @@ void avsubtitle_free(AVSubtitle *sub); * @{ */ -#if FF_API_DESTRUCT_PACKET /** - * Default packet destructor. - * @deprecated use the AVBuffer API instead + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet */ -attribute_deprecated -void av_destruct_packet(AVPacket *pkt); -#endif +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param packet packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); /** * Initialize optional fields of a packet with default values. @@ -3339,25 +3882,31 @@ int av_grow_packet(AVPacket *pkt, int grow_by); * function returns successfully, the data is owned by the underlying AVBuffer. * The caller may not access the data through other means. * @param size size of data in bytes, without the padding. I.e. the full buffer - * size is assumed to be size + FF_INPUT_BUFFER_PADDING_SIZE. + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. * * @return 0 on success, a negative AVERROR on error */ int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); +#if FF_API_AVPACKET_OLD_API /** * @warning This is a hack - the packet memory allocation stuff is broken. The * packet is allocated if it was not really allocated. + * + * @deprecated Use av_packet_ref */ +attribute_deprecated int av_dup_packet(AVPacket *pkt); - /** * Free a packet. * + * @deprecated Use av_packet_unref + * * @param pkt packet to free */ +attribute_deprecated void av_free_packet(AVPacket *pkt); - +#endif /** * Allocate new information of a packet. * @@ -3370,6 +3919,22 @@ uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size); /** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** * Shrink the already allocated side data buffer * * @param pkt packet @@ -3447,7 +4012,6 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src); * @param src Source packet * * @return 0 on success AVERROR on failure. - * */ int av_packet_copy_props(AVPacket *dst, const AVPacket *src); @@ -3489,16 +4053,10 @@ AVCodec *avcodec_find_decoder(enum AVCodecID id); */ AVCodec *avcodec_find_decoder_by_name(const char *name); -#if FF_API_GET_BUFFER -attribute_deprecated int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); -attribute_deprecated void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); -attribute_deprecated int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); -#endif - /** * The default callback for AVCodecContext.get_buffer2(). It is made public so * it can be called by custom get_buffer2() implementations for decoders without - * CODEC_CAP_DR1 set. + * AV_CODEC_CAP_DR1 set. */ int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); @@ -3522,7 +4080,7 @@ unsigned avcodec_get_edge_width(void); * buffer that is acceptable for the codec if you do not use any horizontal * padding. * - * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. */ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); @@ -3531,7 +4089,7 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); * buffer that is acceptable for the codec if you also ensure that all * line sizes are a multiple of the respective linesize_align[i]. * - * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. */ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[AV_NUM_DATA_POINTERS]); @@ -3547,18 +4105,21 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, * needs to be fed to the decoder with remaining data until it is completely * consumed or an error occurs. * - * Some decoders (those marked with CODEC_CAP_DELAY) have a delay between input + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input * and output. This means that for some packets they will not immediately * produce decoded output and need to be flushed at the end of decoding to get * all the decoded data. Flushing is done by calling this function with packets * with avpkt->data set to NULL and avpkt->size set to 0 until it stops * returning samples. It is safe to flush even those decoders that are not - * marked with CODEC_CAP_DELAY, then no samples will be returned. + * marked with AV_CODEC_CAP_DELAY, then no samples will be returned. * - * @warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE * larger than the actual read bytes because some optimized bitstream * readers read 32 or 64 bits at once and could read over the end. * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * * @param avctx the codec context * @param[out] frame The AVFrame in which to store decoded audio samples. * The decoder will allocate a buffer for the decoded frame by @@ -3575,7 +4136,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is * non-zero. Note that this field being set to zero * does not mean that an error has occurred. For - * decoders with CODEC_CAP_DELAY set, no given decode + * decoders with AV_CODEC_CAP_DELAY set, no given decode * call is guaranteed to produce a frame. * @param[in] avpkt The input AVPacket containing the input buffer. * At least avpkt->data and avpkt->size should be set. Some @@ -3583,7 +4144,10 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, * @return A negative error code is returned if an error occurred during * decoding, otherwise the number of bytes consumed from the input * AVPacket is returned. + * +* @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). */ +attribute_deprecated int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt); @@ -3592,17 +4156,20 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, * Some decoders may support multiple frames in a single AVPacket, such * decoders would then just decode the first frame. * - * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * @warning The input buffer must be AV_INPUT_BUFFER_PADDING_SIZE larger than * the actual read bytes because some optimized bitstream readers read 32 or 64 * bits at once and could read over the end. * * @warning The end of the input buffer buf should be set to 0 to ensure that * no overreading happens for damaged MPEG streams. * - * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * @note Codecs which have the AV_CODEC_CAP_DELAY capability set have a delay * between input and output, these need to be fed with avpkt->data=NULL, * avpkt->size=0 at the end to return the remaining frames. * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * * @param avctx the codec context * @param[out] picture The AVFrame in which the decoded video frame will be stored. * Use av_frame_alloc() to get an AVFrame. The codec will @@ -3618,7 +4185,7 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, * next call to this function or until closing or flushing the * decoder. The caller may not write to it. * - * @param[in] avpkt The input AVpacket containing the input buffer. + * @param[in] avpkt The input AVPacket containing the input buffer. * You can create such packet with av_init_packet() and by then setting * data and size, some decoders might in addition need other fields like * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least @@ -3626,7 +4193,10 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. * @return On error a negative value is returned, otherwise the number of bytes * used or zero if no frame could be decompressed. + * + * @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). */ +attribute_deprecated int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt); @@ -3636,11 +4206,14 @@ int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, * Return a negative value on error, otherwise return the number of bytes used. * If no subtitle could be decompressed, got_sub_ptr is zero. * Otherwise, the subtitle is stored in *sub. - * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for * simplicity, because the performance difference is expect to be negligible * and reusing a get_buffer written for video codecs would probably perform badly * due to a potentially very different allocation pattern. * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * * @param avctx the codec context * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be freed with avsubtitle_free if *got_sub_ptr is set. @@ -3652,6 +4225,129 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, AVPacket *avpkt); /** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @warning Do not mix this API with the legacy API (like avcodec_decode_video2()) + * on the same AVCodecContext. It will return unexpected results now + * or in future libavcodec versions. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted right now - the packet must be + * resent after trying to read output + * AVERROR_EOF: the decoder has been flushed, and no new packets can + * be sent to it (also returned if more than 1 flush + * packet is sent) + * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder. + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * decoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @return + * 0: success, a frame was returned + * AVERROR(EAGAIN): output is not available right now - user must try + * to send new input + * AVERROR_EOF: the decoder has been fully flushed, and there will be + * no more output frames + * AVERROR(EINVAL): codec not opened, or it is an encoder + * other negative values: legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted right now - the frame must be + * resent after trying to read output packets + * AVERROR_EOF: the encoder has been flushed, and no new frames can + * be sent to it + * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a + * decoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): output is not available right now - user must try + * to send input + * AVERROR_EOF: the encoder has been fully flushed, and there will be + * no more output packets + * AVERROR(EINVAL): codec not opened, or it is an encoder + * other errors: legitimate decoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + + +/** * @defgroup lavc_parsing Frame parsing * @{ */ @@ -3713,24 +4409,13 @@ typedef struct AVCodecParserContext { */ int key_frame; +#if FF_API_CONVERGENCE_DURATION /** - * Time difference in stream time base units from the pts of this - * packet to the point at which the output from the decoder has converged - * independent from the availability of previous frames. That is, the - * frames are virtually identical no matter if decoding started from - * the very first frame or from this keyframe. - * Is AV_NOPTS_VALUE if unknown. - * This field is not the display duration of the current frame. - * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY - * set. - * - * The purpose of this field is to allow seeking in streams that have no - * keyframes in the conventional sense. It corresponds to the - * recovery point SEI in H.264 and match_time_delta in NUT. It is also - * essential for some types of subtitle streams to ensure that all - * subtitles are correctly displayed after seeking. + * @deprecated unused */ + attribute_deprecated int64_t convergence_duration; +#endif // Timestamp generation support: /** @@ -3816,12 +4501,36 @@ typedef struct AVCodecParserContext { * For example, this corresponds to H.264 PicOrderCnt. */ int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; } AVCodecParserContext; typedef struct AVCodecParser { int codec_ids[5]; /* several codec IDs are permitted */ int priv_data_size; int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ int (*parser_parse)(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, @@ -3927,12 +4636,11 @@ AVCodec *avcodec_find_encoder_by_name(const char *name); * output packet. * * If this function fails or produces no output, avpkt will be - * freed using av_free_packet() (i.e. avpkt->destruct will be - * called to free the user supplied buffer). + * freed using av_packet_unref(). * @param[in] frame AVFrame containing the raw audio data to be encoded. * May be NULL when flushing an encoder that has the - * CODEC_CAP_DELAY capability set. - * If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * AV_CODEC_CAP_DELAY capability set. + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame * can have any number of samples. * If it is not set, frame->nb_samples must be equal to * avctx->frame_size for all frames except the last. @@ -3944,7 +4652,10 @@ AVCodec *avcodec_find_encoder_by_name(const char *name); * value of got_packet_ptr is undefined and should * not be used. * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead */ +attribute_deprecated int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); @@ -3969,11 +4680,10 @@ int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, * caller, he is responsible for freeing it. * * If this function fails or produces no output, avpkt will be - * freed using av_free_packet() (i.e. avpkt->destruct will be - * called to free the user supplied buffer). + * freed using av_packet_unref(). * @param[in] frame AVFrame containing the raw video data to be encoded. * May be NULL when flushing an encoder that has the - * CODEC_CAP_DELAY capability set. + * AV_CODEC_CAP_DELAY capability set. * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the * output packet is non-empty, and to 0 if it is * empty. If the function returns an error, the @@ -3981,7 +4691,10 @@ int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, * value of got_packet_ptr is undefined and should * not be used. * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead */ +attribute_deprecated int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); @@ -3993,120 +4706,70 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, * @} */ +#if FF_API_AVPICTURE /** * @addtogroup lavc_picture * @{ */ /** - * Allocate memory for a picture. Call avpicture_free() to free it. - * - * @see avpicture_fill() - * - * @param picture the picture to be filled in - * @param pix_fmt the format of the picture - * @param width the width of the picture - * @param height the height of the picture - * @return zero if successful, a negative value if not + * @deprecated unused */ +attribute_deprecated int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height); /** - * Free a picture previously allocated by avpicture_alloc(). - * The data buffer used by the AVPicture is freed, but the AVPicture structure - * itself is not. - * - * @param picture the AVPicture to be freed + * @deprecated unused */ +attribute_deprecated void avpicture_free(AVPicture *picture); /** - * Fill in the AVPicture fields. - * The fields of the given AVPicture are filled in by using the 'ptr' address - * which points to the image data buffer. Depending on the specified picture - * format, one or multiple image data pointers and line sizes will be set. - * If a planar format is specified, several pointers will be set pointing to - * the different picture planes and the line sizes of the different planes - * will be stored in the lines_sizes array. - * Call with ptr == NULL to get the required size for the ptr buffer. - * - * To allocate the buffer and fill in the AVPicture fields in one call, - * use avpicture_alloc(). - * - * @param picture AVPicture whose fields are to be filled in - * @param ptr Buffer which will contain or contains the actual image data - * @param pix_fmt The format in which the picture data is stored. - * @param width the width of the image in pixels - * @param height the height of the image in pixels - * @return size of the image data in bytes + * @deprecated use av_image_fill_arrays() instead. */ +attribute_deprecated int avpicture_fill(AVPicture *picture, uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height); /** - * Copy pixel data from an AVPicture into a buffer. - * The data is stored compactly, without any gaps for alignment or padding - * which may be applied by avpicture_fill(). - * - * @see avpicture_get_size() - * - * @param[in] src AVPicture containing image data - * @param[in] pix_fmt The format in which the picture data is stored. - * @param[in] width the width of the image in pixels. - * @param[in] height the height of the image in pixels. - * @param[out] dest A buffer into which picture data will be copied. - * @param[in] dest_size The size of 'dest'. - * @return The number of bytes written to dest, or a negative value (error code) on error. + * @deprecated use av_image_copy_to_buffer() instead. */ +attribute_deprecated int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, int width, int height, unsigned char *dest, int dest_size); /** - * Calculate the size in bytes that a picture of the given width and height - * would occupy if stored in the given picture format. - * Note that this returns the size of a compact representation as generated - * by avpicture_layout(), which can be smaller than the size required for e.g. - * avpicture_fill(). - * - * @param pix_fmt the given picture format - * @param width the width of the image - * @param height the height of the image - * @return Image data size in bytes or -1 on error (e.g. too large dimensions). + * @deprecated use av_image_get_buffer_size() instead. */ +attribute_deprecated int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height); -#if FF_API_DEINTERLACE /** - * deinterlace - if not supported return -1 - * - * @deprecated - use yadif (in libavfilter) instead + * @deprecated av_image_copy() instead. */ attribute_deprecated -int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, - enum AVPixelFormat pix_fmt, int width, int height); -#endif -/** - * Copy image src to dst. Wraps av_picture_data_copy() above. - */ void av_picture_copy(AVPicture *dst, const AVPicture *src, enum AVPixelFormat pix_fmt, int width, int height); /** - * Crop image top and left side. + * @deprecated unused */ +attribute_deprecated int av_picture_crop(AVPicture *dst, const AVPicture *src, enum AVPixelFormat pix_fmt, int top_band, int left_band); /** - * Pad image. + * @deprecated unused */ +attribute_deprecated int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright, int *color); /** * @} */ +#endif /** * @defgroup lavc_misc Utility functions @@ -4221,6 +4884,19 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); */ const char *av_get_profile_name(const AVCodec *codec, int profile); +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); //FIXME func typedef @@ -4284,35 +4960,227 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id); */ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); +#if FF_API_OLD_BSF typedef struct AVBitStreamFilterContext { void *priv_data; struct AVBitStreamFilter *filter; AVCodecParserContext *parser; struct AVBitStreamFilterContext *next; } AVBitStreamFilterContext; +#endif + +typedef struct AVBSFInternal AVBSFInternal; + +/** + * The bitstream filter state. + * + * This struct must be allocated with av_bsf_alloc() and freed with + * av_bsf_free(). + * + * The fields in the struct will only be changed (by the caller or by the + * filter) as described in their documentation, and are to be considered + * immutable otherwise. + */ +typedef struct AVBSFContext { + /** + * A class for logging and AVOptions + */ + const AVClass *av_class; + + /** + * The bitstream filter this context is an instance of. + */ + const struct AVBitStreamFilter *filter; + + /** + * Opaque libavcodec internal data. Must not be touched by the caller in any + * way. + */ + AVBSFInternal *internal; + + /** + * Opaque filter-specific private data. If filter->priv_class is non-NULL, + * this is an AVOptions-enabled struct. + */ + void *priv_data; + + /** + * Parameters of the input stream. Set by the caller before av_bsf_init(). + */ + AVCodecParameters *par_in; + + /** + * Parameters of the output stream. Set by the filter in av_bsf_init(). + */ + AVCodecParameters *par_out; + /** + * The timebase used for the timestamps of the input packets. Set by the + * caller before av_bsf_init(). + */ + AVRational time_base_in; + + /** + * The timebase used for the timestamps of the output packets. Set by the + * filter in av_bsf_init(). + */ + AVRational time_base_out; +} AVBSFContext; typedef struct AVBitStreamFilter { const char *name; + + /** + * A list of codec ids supported by the filter, terminated by + * AV_CODEC_ID_NONE. + * May be NULL, in that case the bitstream filter works with any codec id. + */ + const enum AVCodecID *codec_ids; + + /** + * A class for the private data, used to declare bitstream filter private + * AVOptions. This field is NULL for bitstream filters that do not declare + * any options. + * + * If this field is non-NULL, the first member of the filter private data + * must be a pointer to AVClass, which will be set by libavcodec generic + * code to this class. + */ + const AVClass *priv_class; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; - int (*filter)(AVBitStreamFilterContext *bsfc, - AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe); - void (*close)(AVBitStreamFilterContext *bsfc); - struct AVBitStreamFilter *next; + int (*init)(AVBSFContext *ctx); + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); + void (*close)(AVBSFContext *ctx); } AVBitStreamFilter; +#if FF_API_OLD_BSF +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use the new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated void av_register_bitstream_filter(AVBitStreamFilter *bsf); +attribute_deprecated AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); +attribute_deprecated 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); +attribute_deprecated void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); - +attribute_deprecated AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); +#endif + +/** + * @return a bitstream filter with the specified name or NULL if no such + * bitstream filter exists. + */ +const AVBitStreamFilter *av_bsf_get_by_name(const char *name); + +/** + * Iterate over all registered bitstream filters. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered bitstream filter or NULL when the iteration is + * finished + */ +const AVBitStreamFilter *av_bsf_next(void **opaque); + +/** + * Allocate a context for a given bitstream filter. The caller must fill in the + * context parameters as described in the documentation and then call + * av_bsf_init() before sending any data to the filter. + * + * @param filter the filter for which to allocate an instance. + * @param ctx a pointer into which the pointer to the newly-allocated context + * will be written. It must be freed with av_bsf_free() after the + * filtering is done. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); + +/** + * Prepare the filter for use, after all the parameters and options have been + * set. + */ +int av_bsf_init(AVBSFContext *ctx); + +/** + * Submit a packet for filtering. + * + * After sending each packet, the filter must be completely drained by calling + * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or + * AVERROR_EOF. + * + * @param pkt the packet to filter. The bitstream filter will take ownership of + * the packet and reset the contents of pkt. pkt is not touched if an error occurs. + * This parameter may be NULL, which signals the end of the stream (i.e. no more + * packets will be sent). That will cause the filter to output any packets it + * may have buffered internally. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Retrieve a filtered packet. + * + * @param[out] pkt this struct will be filled with the contents of the filtered + * packet. It is owned by the caller and must be freed using + * av_packet_unref() when it is no longer needed. + * This parameter should be "clean" (i.e. freshly allocated + * with av_packet_alloc() or unreffed with av_packet_unref()) + * when this function is called. If this function returns + * successfully, the contents of pkt will be completely + * overwritten by the returned data. On failure, pkt is not + * touched. + * + * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the + * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there + * will be no further output from the filter. Another negative AVERROR value if + * an error occurs. + * + * @note one input packet may result in several output packets, so after sending + * a packet with av_bsf_send_packet(), this function needs to be called + * repeatedly until it stops returning 0. It is also possible for a filter to + * output fewer packets than were sent to it, so this function may return + * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. + */ +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Free a bitstream filter context and everything associated with it; write NULL + * into the supplied pointer. + */ +void av_bsf_free(AVBSFContext **ctx); + +/** + * Get the AVClass for AVBSFContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_bsf_get_class(void); /* memory */ @@ -4320,8 +5188,7 @@ AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); * Allocate a buffer with padding, reusing the given one if large enough. * * Same behaviour av_fast_malloc but the buffer has additional - * FF_INPUT_PADDING_SIZE at the end which will always memset to 0. - * + * AV_INPUT_PADDING_SIZE at the end which will always memset to 0. */ void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); @@ -4343,7 +5210,7 @@ unsigned int av_xiphlacing(unsigned char *s, unsigned int v); * a pointer to an AVClass struct * @param[in] feature string containing the name of the missing feature * @param[in] want_sample indicates if samples are wanted which exhibit this feature. - * If want_sample is non-zero, additional verbage will be added to the log + * If want_sample is non-zero, additional verbiage will be added to the log * message which tells the user how to report samples to the development * mailing list. * @deprecated Use avpriv_report_missing_feature() instead. @@ -4389,16 +5256,26 @@ enum AVLockOp { /** * Register a user provided lock manager supporting the operations - * specified by AVLockOp. mutex points to a (void *) where the - * lockmgr should store/get a pointer to a user allocated mutex. It's - * NULL upon AV_LOCK_CREATE and != NULL for all other ops. + * specified by AVLockOp. The "mutex" argument to the function points + * to a (void *) where the lockmgr should store/get a pointer to a user + * allocated mutex. It is NULL upon AV_LOCK_CREATE and equal to the + * value left by the last call for all other ops. If the lock manager is + * unable to perform the op then it should leave the mutex in the same + * state as when it was called and return a non-zero value. However, + * when called with AV_LOCK_DESTROY the mutex will always be assumed to + * have been successfully destroyed. If av_lockmgr_register succeeds + * it will return a non-negative value, if it fails it will return a + * negative value and destroy all mutex and unregister all callbacks. + * av_lockmgr_register is not thread-safe, it must be called from a + * single thread before any calls which make use of locking are used. * - * @param cb User defined callback. Note: Libav may invoke calls to this - * callback during the call to av_lockmgr_register(). - * Thus, the application must be prepared to handle that. - * If cb is set to NULL the lockmgr will be unregistered. - * Also note that during unregistration the previously registered - * lockmgr callback may also be invoked. + * @param cb User defined callback. av_lockmgr_register invokes calls + * to this callback and the previously registered callback. + * The callback will be used to create more than one mutex + * each of which must be backed by its own underlying locking + * mechanism (i.e. do not use a single static object to + * implement your lock manager). If cb is set to NULL the + * lockmgr will be unregistered. */ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); @@ -4444,6 +5321,17 @@ const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); /** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** * @} */ diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 25eabdb..7856dbf 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -27,22 +27,6 @@ #include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "avcodec.h" -#if FF_API_DESTRUCT_PACKET - -void av_destruct_packet(AVPacket *pkt) -{ - av_free(pkt->data); - pkt->data = NULL; - pkt->size = 0; -} - -/* a dummy destruct callback for the callers that assume AVPacket.destruct == - * NULL => static data */ -static void dummy_destruct_packet(AVPacket *pkt) -{ - av_assert0(0); -} -#endif void av_init_packet(AVPacket *pkt) { @@ -50,30 +34,49 @@ void av_init_packet(AVPacket *pkt) pkt->dts = AV_NOPTS_VALUE; pkt->pos = -1; pkt->duration = 0; - pkt->convergence_duration = 0; - pkt->flags = 0; - pkt->stream_index = 0; -#if FF_API_DESTRUCT_PACKET +#if FF_API_CONVERGENCE_DURATION FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = NULL; + pkt->convergence_duration = 0; FF_ENABLE_DEPRECATION_WARNINGS #endif + pkt->flags = 0; + pkt->stream_index = 0; pkt->buf = NULL; pkt->side_data = NULL; pkt->side_data_elems = 0; } +AVPacket *av_packet_alloc(void) +{ + AVPacket *pkt = av_mallocz(sizeof(AVPacket)); + if (!pkt) + return pkt; + + av_packet_unref(pkt); + + return pkt; +} + +void av_packet_free(AVPacket **pkt) +{ + if (!pkt || !*pkt) + return; + + av_packet_unref(*pkt); + av_freep(pkt); +} + static int packet_alloc(AVBufferRef **buf, int size) { int ret; - if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) + if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return AVERROR(EINVAL); - ret = av_buffer_realloc(buf, size + FF_INPUT_BUFFER_PADDING_SIZE); + ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE); if (ret < 0) return ret; - memset((*buf)->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); return 0; } @@ -89,11 +92,6 @@ int av_new_packet(AVPacket *pkt, int size) pkt->buf = buf; pkt->data = buf->data; pkt->size = size; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dummy_destruct_packet; -FF_ENABLE_DEPRECATION_WARNINGS -#endif return 0; } @@ -103,20 +101,20 @@ void av_shrink_packet(AVPacket *pkt, int size) if (pkt->size <= size) return; pkt->size = size; - memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(pkt->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } int av_grow_packet(AVPacket *pkt, int grow_by) { int new_size; - av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE); + av_assert0((unsigned)pkt->size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); if (!pkt->size) return av_new_packet(pkt, grow_by); if ((unsigned)grow_by > - INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) + INT_MAX - (pkt->size + AV_INPUT_BUFFER_PADDING_SIZE)) return -1; - new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE; + new_size = pkt->size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE; if (pkt->buf) { int ret = av_buffer_realloc(&pkt->buf, new_size); if (ret < 0) @@ -126,40 +124,32 @@ int av_grow_packet(AVPacket *pkt, int grow_by) if (!pkt->buf) return AVERROR(ENOMEM); memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by)); -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dummy_destruct_packet; -FF_ENABLE_DEPRECATION_WARNINGS -#endif } pkt->data = pkt->buf->data; pkt->size += grow_by; - memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); return 0; } int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) { - if (size >= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + if (size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return AVERROR(EINVAL); - pkt->buf = av_buffer_create(data, size + FF_INPUT_BUFFER_PADDING_SIZE, + pkt->buf = av_buffer_create(data, size + AV_INPUT_BUFFER_PADDING_SIZE, av_buffer_default_free, NULL, 0); if (!pkt->buf) return AVERROR(ENOMEM); pkt->data = data; pkt->size = size; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dummy_destruct_packet; -FF_ENABLE_DEPRECATION_WARNINGS -#endif return 0; } +#if FF_API_AVPACKET_OLD_API +FF_DISABLE_DEPRECATION_WARNINGS #define ALLOC_MALLOC(data, size) data = av_malloc(size) #define ALLOC_BUF(data, size) \ do { \ @@ -172,9 +162,9 @@ do { \ void *data; \ if (padding) { \ if ((unsigned)(size) > \ - (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ + (unsigned)(size) + AV_INPUT_BUFFER_PADDING_SIZE) \ goto failed_alloc; \ - ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \ + ALLOC(data, size + AV_INPUT_BUFFER_PADDING_SIZE); \ } else { \ ALLOC(data, size); \ } \ @@ -183,7 +173,7 @@ do { \ memcpy(data, src, size); \ if (padding) \ memset((uint8_t *)data + size, 0, \ - FF_INPUT_BUFFER_PADDING_SIZE); \ + AV_INPUT_BUFFER_PADDING_SIZE); \ dst = data; \ } while (0) @@ -191,23 +181,12 @@ int av_dup_packet(AVPacket *pkt) { AVPacket tmp_pkt; -FF_DISABLE_DEPRECATION_WARNINGS - if (!pkt->buf && pkt->data -#if FF_API_DESTRUCT_PACKET - && !pkt->destruct -#endif - ) { -FF_ENABLE_DEPRECATION_WARNINGS + if (!pkt->buf && pkt->data) { tmp_pkt = *pkt; pkt->data = NULL; pkt->side_data = NULL; DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1, ALLOC_BUF); -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dummy_destruct_packet; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (pkt->side_data_elems) { int i; @@ -227,9 +206,11 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; failed_alloc: - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif void av_packet_free_side_data(AVPacket *pkt) { @@ -240,48 +221,64 @@ void av_packet_free_side_data(AVPacket *pkt) pkt->side_data_elems = 0; } +#if FF_API_AVPACKET_OLD_API +FF_DISABLE_DEPRECATION_WARNINGS void av_free_packet(AVPacket *pkt) { if (pkt) { -FF_DISABLE_DEPRECATION_WARNINGS if (pkt->buf) av_buffer_unref(&pkt->buf); -#if FF_API_DESTRUCT_PACKET - else if (pkt->destruct) - pkt->destruct(pkt); - pkt->destruct = NULL; -#endif -FF_ENABLE_DEPRECATION_WARNINGS pkt->data = NULL; pkt->size = 0; av_packet_free_side_data(pkt); } } +FF_ENABLE_DEPRECATION_WARNINGS +#endif -uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - int size) +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size) { + AVPacketSideData *tmp; int elems = pkt->side_data_elems; if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) - return NULL; - if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) - return NULL; + return AVERROR(ERANGE); - pkt->side_data = av_realloc(pkt->side_data, - (elems + 1) * sizeof(*pkt->side_data)); - if (!pkt->side_data) - return NULL; + tmp = av_realloc(pkt->side_data, (elems + 1) * sizeof(*tmp)); + if (!tmp) + return AVERROR(ENOMEM); - pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!pkt->side_data[elems].data) - return NULL; + pkt->side_data = tmp; + pkt->side_data[elems].data = data; pkt->side_data[elems].size = size; pkt->side_data[elems].type = type; pkt->side_data_elems++; - return pkt->side_data[elems].data; + return 0; +} + + +uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size) +{ + int ret; + uint8_t *data; + + if (!size || (unsigned)size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) + return NULL; + data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!data) + return NULL; + + ret = av_packet_add_side_data(pkt, type, data, size); + if (ret < 0) { + av_freep(&data); + return NULL; + } + + return data; } uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, @@ -323,7 +320,11 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src) dst->dts = src->dts; dst->pos = src->pos; dst->duration = src->duration; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS dst->convergence_duration = src->convergence_duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->flags = src->flags; dst->stream_index = src->stream_index; @@ -365,21 +366,44 @@ int av_packet_ref(AVPacket *dst, AVPacket *src) if (ret < 0) goto fail; memcpy(dst->buf->data, src->data, src->size); - } else + + dst->data = dst->buf->data; + } else { dst->buf = av_buffer_ref(src->buf); + if (!dst->buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + dst->data = src->data; + } dst->size = src->size; - dst->data = dst->buf->data; + return 0; fail: av_packet_free_side_data(dst); return ret; } +AVPacket *av_packet_clone(AVPacket *src) +{ + AVPacket *ret = av_packet_alloc(); + + if (!ret) + return ret; + + if (av_packet_ref(ret, src)) + av_packet_free(&ret); + + return ret; +} + void av_packet_move_ref(AVPacket *dst, AVPacket *src) { *dst = *src; av_init_packet(src); + src->data = NULL; + src->size = 0; } void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) @@ -390,6 +414,10 @@ void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); if (pkt->duration > 0) pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS if (pkt->convergence_duration > 0) pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } diff --git a/libavcodec/avpicture.c b/libavcodec/avpicture.c index a50bbc4..786d740 100644 --- a/libavcodec/avpicture.c +++ b/libavcodec/avpicture.c @@ -29,73 +29,30 @@ #include "libavutil/common.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" +#include "libavutil/internal.h" #include "libavutil/colorspace.h" +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS int avpicture_fill(AVPicture *picture, uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height) { - int ret; - - if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) - return ret; - - if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0) - return ret; - - return av_image_fill_pointers(picture->data, pix_fmt, - height, ptr, picture->linesize); + return av_image_fill_arrays(picture->data, picture->linesize, + ptr, pix_fmt, width, height, 1); } int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, int width, int height, unsigned char *dest, int dest_size) { - int i, j, nb_planes = 0, linesizes[4]; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int size = avpicture_get_size(pix_fmt, width, height); - - if (size > dest_size || size < 0) - return AVERROR(EINVAL); - - for (i = 0; i < desc->nb_components; i++) - nb_planes = FFMAX(desc->comp[i].plane, nb_planes); - - nb_planes++; - - av_image_fill_linesizes(linesizes, pix_fmt, width); - for (i = 0; i < nb_planes; i++) { - int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - const unsigned char *s = src->data[i]; - h = (height + (1 << shift) - 1) >> shift; - - for (j = 0; j < h; j++) { - memcpy(dest, s, linesizes[i]); - dest += linesizes[i]; - s += src->linesize[i]; - } - } - - if (desc->flags & AV_PIX_FMT_FLAG_PAL) - memcpy((unsigned char *)(((size_t)dest + 3) & ~3), - src->data[1], 256 * 4); - - return size; + return av_image_copy_to_buffer(dest, dest_size, + src->data, src->linesize, + pix_fmt, width, height, 1); } int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - AVPicture dummy_pict; - int ret; - - if (!desc) - return AVERROR(EINVAL); - if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) - return ret; - if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) - // do not include palette for these pseudo-paletted formats - return width * height; - return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); + return av_image_get_buffer_size(pix_fmt, width, height, 1); } int avpicture_alloc(AVPicture *picture, @@ -122,4 +79,5 @@ void av_picture_copy(AVPicture *dst, const AVPicture *src, av_image_copy(dst->data, dst->linesize, src->data, src->linesize, pix_fmt, width, height); } - +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* FF_API_AVPICTURE */ diff --git a/libavcodec/avs.c b/libavcodec/avs.c index eb2da66..0d127f8 100644 --- a/libavcodec/avs.c +++ b/libavcodec/avs.c @@ -23,8 +23,7 @@ #include "get_bits.h" #include "internal.h" - -typedef struct { +typedef struct AvsContext { AVFrame *frame; } AvsContext; @@ -186,5 +185,5 @@ AVCodec ff_avs_decoder = { .init = avs_decode_init, .decode = avs_decode_frame, .close = avs_decode_end, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c index 7e93a27..11e2cfa 100644 --- a/libavcodec/bethsoftvideo.c +++ b/libavcodec/bethsoftvideo.c @@ -163,5 +163,5 @@ AVCodec ff_bethsoftvid_decoder = { .init = bethsoftvid_decode_init, .close = bethsoftvid_decode_end, .decode = bethsoftvid_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c index 75b6710..8335e9d 100644 --- a/libavcodec/bfi.c +++ b/libavcodec/bfi.c @@ -180,5 +180,5 @@ AVCodec ff_bfi_decoder = { .init = bfi_decode_init, .close = bfi_decode_close, .decode = bfi_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bgmc.c b/libavcodec/bgmc.c index c7f732e..ad8baae 100644 --- a/libavcodec/bgmc.c +++ b/libavcodec/bgmc.c @@ -460,8 +460,8 @@ static uint8_t *bgmc_lut_getp(uint8_t *lut, int *lut_status, int delta) av_cold int ff_bgmc_init(AVCodecContext *avctx, uint8_t **cf_lut, int **cf_lut_status) { - *cf_lut = av_malloc(sizeof(*cf_lut) * LUT_BUFF * 16 * LUT_SIZE); - *cf_lut_status = av_malloc(sizeof(*cf_lut_status) * LUT_BUFF); + *cf_lut = av_malloc(sizeof(**cf_lut) * LUT_BUFF * 16 * LUT_SIZE); + *cf_lut_status = av_malloc(sizeof(**cf_lut_status) * LUT_BUFF); if (!*cf_lut || !*cf_lut_status) { ff_bgmc_end(cf_lut, cf_lut_status); @@ -469,7 +469,7 @@ av_cold int ff_bgmc_init(AVCodecContext *avctx, return AVERROR(ENOMEM); } else { // initialize lut_status buffer to a value never used to compare against - memset(*cf_lut_status, -1, sizeof(*cf_lut_status) * LUT_BUFF); + memset(*cf_lut_status, -1, sizeof(**cf_lut_status) * LUT_BUFF); } return 0; diff --git a/libavcodec/bink.c b/libavcodec/bink.c index e34585b..7433697 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -23,17 +23,17 @@ #include "libavutil/attributes.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "binkdata.h" #include "binkdsp.h" #include "blockdsp.h" +#include "get_bits.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" -#define BITSTREAM_READER_LE -#include "get_bits.h" - #define BINK_FLAG_ALPHA 0x00100000 #define BINK_FLAG_GRAY 0x00020000 @@ -944,15 +944,32 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, return 0; } +static int bink_put_pixels(BinkContext *c, + uint8_t *dst, uint8_t *prev, int stride, + uint8_t *ref_start, + uint8_t *ref_end) +{ + int xoff = get_value(c, BINK_SRC_X_OFF); + int yoff = get_value(c, BINK_SRC_Y_OFF); + uint8_t *ref = prev + xoff + yoff * stride; + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + xoff, yoff); + return AVERROR_INVALIDDATA; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + + return 0; +} + static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, int plane_idx, int is_chroma) { int blk, ret; int i, j, bx, by; - uint8_t *dst, *prev, *ref, *ref_start, *ref_end; + uint8_t *dst, *prev, *ref_start, *ref_end; int v, col[2]; const uint8_t *scan; - int xoff, yoff; LOCAL_ALIGNED_16(int16_t, block, [64]); LOCAL_ALIGNED_16(uint8_t, ublock, [64]); LOCAL_ALIGNED_16(int32_t, dctblock, [64]); @@ -1074,15 +1091,10 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, prev += 8; break; case MOTION_BLOCK: - xoff = get_value(c, BINK_SRC_X_OFF); - yoff = get_value(c, BINK_SRC_Y_OFF); - ref = prev + xoff + yoff * stride; - if (ref < ref_start || ref > ref_end) { - av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", - bx*8 + xoff, by*8 + yoff); - return AVERROR_INVALIDDATA; - } - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; break; case RUN_BLOCK: scan = bink_patterns[get_bits(gb, 4)]; @@ -1108,15 +1120,10 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); break; case RESIDUE_BLOCK: - xoff = get_value(c, BINK_SRC_X_OFF); - yoff = get_value(c, BINK_SRC_Y_OFF); - ref = prev + xoff + yoff * stride; - if (ref < ref_start || ref > ref_end) { - av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", - bx*8 + xoff, by*8 + yoff); - return AVERROR_INVALIDDATA; - } - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; c->bdsp.clear_block(block); v = get_bits(gb, 7); read_residue(gb, block, v); @@ -1133,10 +1140,10 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, c->bdsp.fill_block_tab[1](dst, v, stride, 8); break; case INTER_BLOCK: - xoff = get_value(c, BINK_SRC_X_OFF); - yoff = get_value(c, BINK_SRC_Y_OFF); - ref = prev + xoff + yoff * stride; - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + ret = bink_put_pixels(c, dst, prev, stride, + ref_start, ref_end); + if (ret < 0) + return ret; memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTER_DC); read_dct_coeffs(gb, dctblock, bink_scan, bink_inter_quant, -1); @@ -1229,7 +1236,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } /** - * Caclulate quantization tables for version b + * Calculate quantization tables for version b */ static av_cold void binkb_calc_quant(void) { @@ -1345,5 +1352,5 @@ AVCodec ff_bink_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index ddaa613..2638eb2 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -29,22 +29,22 @@ */ #include "libavutil/channel_layout.h" -#include "avcodec.h" +#include "libavutil/intfloat.h" + #define BITSTREAM_READER_LE -#include "get_bits.h" +#include "avcodec.h" #include "dct.h" -#include "rdft.h" -#include "fmtconvert.h" +#include "get_bits.h" #include "internal.h" -#include "wma.h" -#include "libavutil/intfloat.h" +#include "rdft.h" +#include "wma_freqs.h" static float quant_table[96]; #define MAX_CHANNELS 2 #define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) -typedef struct { +typedef struct BinkAudioContext { GetBitContext gb; int version_b; ///< Bink version 'b' int first; @@ -303,7 +303,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); return AVERROR_INVALIDDATA; } - buf = av_realloc(s->packet_buffer, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + buf = av_realloc(s->packet_buffer, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); if (!buf) return AVERROR(ENOMEM); s->packet_buffer = buf; @@ -344,7 +344,7 @@ AVCodec ff_binkaudio_rdft_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, }; AVCodec ff_binkaudio_dct_decoder = { @@ -356,5 +356,5 @@ AVCodec ff_binkaudio_dct_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index 8e9f657..656ac47 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -29,9 +29,10 @@ */ #include "avcodec.h" +#include "internal.h" #include "mathops.h" -#include "get_bits.h" #include "put_bits.h" +#include "vlc.h" const uint8_t ff_log2_run[41]={ 0, 0, 0, 0, 1, 1, 1, 1, @@ -129,7 +130,7 @@ static av_always_inline uint32_t bitswap_32(uint32_t x) (uint32_t)ff_reverse[ x >> 24]; } -typedef struct { +typedef struct VLCcode { uint8_t bits; uint16_t symbol; /** codeword, with the first bit-to-be-read in the msb @@ -145,7 +146,7 @@ static int compare_vlcspec(const void *a, const void *b) /** * Build VLC decoding tables suitable for use with get_vlc(). * - * @param vlc the context to be initted + * @param vlc the context to be initialized * * @param table_nb_bits max length of vlc codes to store directly in this table * (Longer codes are delegated to subtables.) @@ -166,7 +167,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, table_size = 1 << table_nb_bits; table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); - av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); + ff_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); if (table_index < 0) return table_index; table = &vlc->table[table_index]; @@ -181,7 +182,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, n = codes[i].bits; code = codes[i].code; symbol = codes[i].symbol; - av_dlog(NULL, "i=%d n=%d code=0x%x\n", i, n, code); + ff_dlog(NULL, "i=%d n=%d code=0x%x\n", i, n, code); if (n <= table_nb_bits) { /* no need to add another table */ j = code >> (32 - table_nb_bits); @@ -192,7 +193,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, inc = 1 << n; } for (k = 0; k < nb; k++) { - av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); + ff_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); if (table[j][1] /*bits*/ != 0) { av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); return AVERROR_INVALIDDATA; @@ -222,7 +223,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, subtable_bits = FFMIN(subtable_bits, table_nb_bits); j = (flags & INIT_VLC_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; table[j][1] = -subtable_bits; - av_dlog(NULL, "%4x: n=%d (subtable)\n", + ff_dlog(NULL, "%4x: n=%d (subtable)\n", j, codes[i].bits + table_nb_bits); index = build_table(vlc, subtable_bits, k-i, codes+i, flags); if (index < 0) @@ -239,7 +240,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, /* Build VLC decoding tables suitable for use with get_vlc(). - 'nb_bits' set thee decoding table size (2^nb_bits) entries. The + 'nb_bits' sets the 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. @@ -285,7 +286,7 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, vlc->table_size = 0; } - av_dlog(NULL, "build table nb_codes=%d\n", nb_codes); + ff_dlog(NULL, "build table nb_codes=%d\n", nb_codes); buf = av_malloc((nb_codes + 1) * sizeof(VLCcode)); if (!buf) diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c index f524d3e..ab608a9 100644 --- a/libavcodec/bitstream_filter.c +++ b/libavcodec/bitstream_filter.c @@ -21,48 +21,70 @@ #include #include "avcodec.h" + +#include "libavutil/internal.h" #include "libavutil/mem.h" -static AVBitStreamFilter *first_bitstream_filter = NULL; +#if FF_API_OLD_BSF +FF_DISABLE_DEPRECATION_WARNINGS AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) { - if (f) - return f->next; - else - return first_bitstream_filter; + const AVBitStreamFilter *filter = NULL; + void *opaque = NULL; + + while (filter != f) + filter = av_bsf_next(&opaque); + + return av_bsf_next(&opaque); } void av_register_bitstream_filter(AVBitStreamFilter *bsf) { - bsf->next = first_bitstream_filter; - first_bitstream_filter = bsf; } +typedef struct BSFCompatContext { + AVBSFContext *ctx; +} BSFCompatContext; + AVBitStreamFilterContext *av_bitstream_filter_init(const char *name) { - AVBitStreamFilter *bsf = first_bitstream_filter; - - while (bsf) { - if (!strcmp(name, bsf->name)) { - AVBitStreamFilterContext *bsfc = - av_mallocz(sizeof(AVBitStreamFilterContext)); - bsfc->filter = bsf; - bsfc->priv_data = - bsf->priv_data_size ? av_mallocz(bsf->priv_data_size) : NULL; - return bsfc; - } - bsf = bsf->next; - } + AVBitStreamFilterContext *ctx = NULL; + BSFCompatContext *priv = NULL; + const AVBitStreamFilter *bsf; + + bsf = av_bsf_get_by_name(name); + if (!bsf) + return NULL; + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return NULL; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + goto fail; + + + ctx->filter = bsf; + ctx->priv_data = priv; + + return ctx; + +fail: + if (priv) + av_bsf_free(&priv->ctx); + av_freep(&priv); + av_freep(&ctx); return NULL; } void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) { - if (bsfc->filter->close) - bsfc->filter->close(bsfc); + BSFCompatContext *priv = bsfc->priv_data; + + av_bsf_free(&priv->ctx); av_freep(&bsfc->priv_data); - av_parser_close(bsfc->parser); av_free(bsfc); } @@ -71,8 +93,71 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, 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); + BSFCompatContext *priv = bsfc->priv_data; + AVPacket pkt = { 0 }; + int ret; + + if (!priv->ctx) { + ret = av_bsf_alloc(bsfc->filter, &priv->ctx); + if (ret < 0) + return ret; + + ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx); + if (ret < 0) + return ret; + + priv->ctx->time_base_in = avctx->time_base; + + ret = av_bsf_init(priv->ctx); + if (ret < 0) + return ret; + + if (priv->ctx->par_out->extradata_size) { + av_freep(&avctx->extradata); + avctx->extradata_size = 0; + avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + memcpy(avctx->extradata, priv->ctx->par_out->extradata, + priv->ctx->par_out->extradata_size); + avctx->extradata_size = priv->ctx->par_out->extradata_size; + } + } + + pkt.data = buf; + pkt.size = buf_size; + + ret = av_bsf_send_packet(priv->ctx, &pkt); + if (ret < 0) + return ret; + + *poutbuf = NULL; + *poutbuf_size = 0; + + ret = av_bsf_receive_packet(priv->ctx, &pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return 0; + else if (ret < 0) + return ret; + + *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!*poutbuf) { + av_packet_unref(&pkt); + return AVERROR(ENOMEM); + } + + *poutbuf_size = pkt.size; + memcpy(*poutbuf, pkt.data, pkt.size); + + av_packet_unref(&pkt); + + /* drain all the remaining packets we cannot return */ + while (ret >= 0) { + ret = av_bsf_receive_packet(priv->ctx, &pkt); + av_packet_unref(&pkt); + } + + return 1; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c new file mode 100644 index 0000000..3b4026c --- /dev/null +++ b/libavcodec/bitstream_filters.c @@ -0,0 +1,83 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/log.h" + +#include "avcodec.h" +#include "bsf.h" + +extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; +extern const AVBitStreamFilter ff_chomp_bsf; +extern const AVBitStreamFilter ff_dump_extradata_bsf; +extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; +extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; +extern const AVBitStreamFilter ff_imx_dump_header_bsf; +extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; +extern const AVBitStreamFilter ff_mjpega_dump_header_bsf; +extern const AVBitStreamFilter ff_mov2textsub_bsf; +extern const AVBitStreamFilter ff_text2movsub_bsf; +extern const AVBitStreamFilter ff_noise_bsf; +extern const AVBitStreamFilter ff_remove_extradata_bsf; + +#include "libavcodec/bsf_list.c" + +const AVBitStreamFilter *av_bsf_next(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVBitStreamFilter *f = bitstream_filters[i]; + + if (f) + *opaque = (void*)(i + 1); + + return f; +} + +const AVBitStreamFilter *av_bsf_get_by_name(const char *name) +{ + int i; + + for (i = 0; bitstream_filters[i]; i++) { + const AVBitStreamFilter *f = bitstream_filters[i]; + if (!strcmp(f->name, name)) + return f; + } + + return NULL; +} + +const AVClass *ff_bsf_child_class_next(const AVClass *prev) +{ + int i; + + /* find the filter that corresponds to prev */ + for (i = 0; prev && bitstream_filters[i]; i++) { + if (bitstream_filters[i]->priv_class == prev) { + i++; + break; + } + } + + /* find next filter with priv options */ + for (; bitstream_filters[i]; i++) + if (bitstream_filters[i]->priv_class) + return bitstream_filters[i]->priv_class; + return NULL; +} diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index 15c33a0..648fa68 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -264,7 +264,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, p->linesize[0] = -p->linesize[0]; } bytestream2_init(&gb, buf, dsize); - ff_msrle_decode(avctx, (AVPicture*)p, depth, &gb); + ff_msrle_decode(avctx, p, depth, &gb); if (height < 0) { p->data[0] += p->linesize[0] * (avctx->height - 1); p->linesize[0] = -p->linesize[0]; @@ -353,5 +353,5 @@ AVCodec ff_bmp_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_BMP, .decode = bmp_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bmpenc.c b/libavcodec/bmpenc.c index a14fc61..915c396 100644 --- a/libavcodec/bmpenc.c +++ b/libavcodec/bmpenc.c @@ -56,10 +56,6 @@ static av_cold int bmp_encode_init(AVCodecContext *avctx){ return -1; } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - return 0; } @@ -73,8 +69,12 @@ static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int bit_count = avctx->bits_per_coded_sample; uint8_t *ptr, *buf; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif switch (avctx->pix_fmt) { case AV_PIX_FMT_RGB444: compression = BMP_BITFIELDS; @@ -157,12 +157,6 @@ static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int bmp_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - AVCodec ff_bmp_encoder = { .name = "bmp", .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), @@ -170,7 +164,6 @@ AVCodec ff_bmp_encoder = { .id = AV_CODEC_ID_BMP, .init = bmp_encode_init, .encode2 = bmp_encode_frame, - .close = bmp_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444, AV_PIX_FMT_RGB565, diff --git a/libavcodec/bmvaudio.c b/libavcodec/bmvaudio.c index 0f8c224..8b4bd78 100644 --- a/libavcodec/bmvaudio.c +++ b/libavcodec/bmvaudio.c @@ -87,5 +87,5 @@ AVCodec ff_bmv_audio_decoder = { .id = AV_CODEC_ID_BMV_AUDIO, .init = bmv_aud_decode_init, .decode = bmv_aud_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bmvvideo.c b/libavcodec/bmvvideo.c index ebc8e7a..f4b8f29 100644 --- a/libavcodec/bmvvideo.c +++ b/libavcodec/bmvvideo.c @@ -289,5 +289,5 @@ AVCodec ff_bmv_video_decoder = { .priv_data_size = sizeof(BMVDecContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c index 25aebed..a4b4c87 100644 --- a/libavcodec/brenderpix.c +++ b/libavcodec/brenderpix.c @@ -290,5 +290,5 @@ AVCodec ff_brender_pix_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_BRENDER_PIX, .decode = pix_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c new file mode 100644 index 0000000..284c7c8 --- /dev/null +++ b/libavcodec/bsf.c @@ -0,0 +1,219 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bsf.h" + +struct AVBSFInternal { + AVPacket *buffer_pkt; + int eof; +}; + +void av_bsf_free(AVBSFContext **pctx) +{ + AVBSFContext *ctx; + + if (!pctx || !*pctx) + return; + ctx = *pctx; + + if (ctx->filter->close) + ctx->filter->close(ctx); + if (ctx->filter->priv_class && ctx->priv_data) + av_opt_free(ctx->priv_data); + + av_opt_free(ctx); + + av_packet_free(&ctx->internal->buffer_pkt); + av_freep(&ctx->internal); + av_freep(&ctx->priv_data); + + avcodec_parameters_free(&ctx->par_in); + avcodec_parameters_free(&ctx->par_out); + + av_freep(pctx); +} + +static void *bsf_child_next(void *obj, void *prev) +{ + AVBSFContext *ctx = obj; + if (!prev && ctx->filter->priv_class) + return ctx->priv_data; + return NULL; +} + +static const AVClass bsf_class = { + .class_name = "AVBSFContext", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .child_next = bsf_child_next, + .child_class_next = ff_bsf_child_class_next, +}; + +const AVClass *av_bsf_get_class(void) +{ + return &bsf_class; +} + +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx) +{ + AVBSFContext *ctx; + int ret; + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return AVERROR(ENOMEM); + + ctx->av_class = &bsf_class; + ctx->filter = filter; + + ctx->par_in = avcodec_parameters_alloc(); + ctx->par_out = avcodec_parameters_alloc(); + if (!ctx->par_in || !ctx->par_out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ctx->internal = av_mallocz(sizeof(*ctx->internal)); + if (!ctx->internal) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ctx->internal->buffer_pkt = av_packet_alloc(); + if (!ctx->internal->buffer_pkt) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_opt_set_defaults(ctx); + + /* allocate priv data and init private options */ + if (filter->priv_data_size) { + ctx->priv_data = av_mallocz(filter->priv_data_size); + if (!ctx->priv_data) { + ret = AVERROR(ENOMEM); + goto fail; + } + if (filter->priv_class) { + *(const AVClass **)ctx->priv_data = filter->priv_class; + av_opt_set_defaults(ctx->priv_data); + } + } + + *pctx = ctx; + return 0; +fail: + av_bsf_free(&ctx); + return ret; +} + +int av_bsf_init(AVBSFContext *ctx) +{ + int ret, i; + + /* check that the codec is supported */ + if (ctx->filter->codec_ids) { + for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) + if (ctx->par_in->codec_id == ctx->filter->codec_ids[i]) + break; + if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) { + const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id); + av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the " + "bitstream filter '%s'. Supported codecs are: ", + desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name); + for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) { + desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]); + av_log(ctx, AV_LOG_ERROR, "%s (%d) ", + desc ? desc->name : "unknown", ctx->filter->codec_ids[i]); + } + av_log(ctx, AV_LOG_ERROR, "\n"); + return AVERROR(EINVAL); + } + } + + /* initialize output parameters to be the same as input + * init below might overwrite that */ + ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in); + if (ret < 0) + return ret; + + ctx->time_base_out = ctx->time_base_in; + + if (ctx->filter->init) { + ret = ctx->filter->init(ctx); + if (ret < 0) + return ret; + } + + return 0; +} + +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) +{ + if (!pkt || !pkt->data) { + ctx->internal->eof = 1; + return 0; + } + + if (ctx->internal->eof) { + av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n"); + return AVERROR(EINVAL); + } + + if (ctx->internal->buffer_pkt->data || + ctx->internal->buffer_pkt->side_data_elems) + return AVERROR(EAGAIN); + + av_packet_move_ref(ctx->internal->buffer_pkt, pkt); + + return 0; +} + +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt) +{ + return ctx->filter->filter(ctx, pkt); +} + +int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) +{ + AVBSFInternal *in = ctx->internal; + AVPacket *tmp_pkt; + + if (in->eof) + return AVERROR_EOF; + + if (!ctx->internal->buffer_pkt->data && + !ctx->internal->buffer_pkt->side_data_elems) + return AVERROR(EAGAIN); + + tmp_pkt = av_packet_alloc(); + if (!tmp_pkt) + return AVERROR(ENOMEM); + + *pkt = ctx->internal->buffer_pkt; + ctx->internal->buffer_pkt = tmp_pkt; + + return 0; +} diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h new file mode 100644 index 0000000..cf35fc8 --- /dev/null +++ b/libavcodec/bsf.h @@ -0,0 +1,33 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_BSF_H +#define AVCODEC_BSF_H + +#include "avcodec.h" + +/** + * Called by the bitstream filters to get the next packet for filtering. + * The filter is responsible for either freeing the packet or passing it to the + * caller. + */ +int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt); + +const AVClass *ff_bsf_child_class_next(const AVClass *prev); + +#endif /* AVCODEC_BSF_H */ diff --git a/libavcodec/bytestream.h b/libavcodec/bytestream.h index 3eab225..cb3573b 100644 --- a/libavcodec/bytestream.h +++ b/libavcodec/bytestream.h @@ -70,8 +70,10 @@ static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g) \ } \ static av_always_inline type bytestream2_get_ ## name(GetByteContext *g) \ { \ - if (g->buffer_end - g->buffer < bytes) \ + if (g->buffer_end - g->buffer < bytes) { \ + g->buffer = g->buffer_end; \ return 0; \ + } \ return bytestream2_get_ ## name ## u(g); \ } \ static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \ diff --git a/libavcodec/c93.c b/libavcodec/c93.c index c7cc682..18df958 100644 --- a/libavcodec/c93.c +++ b/libavcodec/c93.c @@ -23,7 +23,7 @@ #include "bytestream.h" #include "internal.h" -typedef struct { +typedef struct C93DecoderContext { AVFrame *pictures[2]; int currentpic; } C93DecoderContext; @@ -260,5 +260,5 @@ AVCodec ff_c93_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c index b6f56f0..5c59003 100644 --- a/libavcodec/cabac.c +++ b/libavcodec/cabac.c @@ -27,83 +27,137 @@ #include #include "libavutil/common.h" -#include "get_bits.h" + #include "cabac.h" #include "cabac_functions.h" -uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = { - 9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -}; - -static const uint8_t lps_range[64][4]= { -{128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205}, -{116,142,169,195}, {111,135,160,185}, {105,128,152,175}, {100,122,144,166}, -{ 95,116,137,158}, { 90,110,130,150}, { 85,104,123,142}, { 81, 99,117,135}, -{ 77, 94,111,128}, { 73, 89,105,122}, { 69, 85,100,116}, { 66, 80, 95,110}, -{ 62, 76, 90,104}, { 59, 72, 86, 99}, { 56, 69, 81, 94}, { 53, 65, 77, 89}, -{ 51, 62, 73, 85}, { 48, 59, 69, 80}, { 46, 56, 66, 76}, { 43, 53, 63, 72}, -{ 41, 50, 59, 69}, { 39, 48, 56, 65}, { 37, 45, 54, 62}, { 35, 43, 51, 59}, -{ 33, 41, 48, 56}, { 32, 39, 46, 53}, { 30, 37, 43, 50}, { 29, 35, 41, 48}, -{ 27, 33, 39, 45}, { 26, 31, 37, 43}, { 24, 30, 35, 41}, { 23, 28, 33, 39}, -{ 22, 27, 32, 37}, { 21, 26, 30, 35}, { 20, 24, 29, 33}, { 19, 23, 27, 31}, -{ 18, 22, 26, 30}, { 17, 21, 25, 28}, { 16, 20, 23, 27}, { 15, 19, 22, 25}, -{ 14, 18, 21, 24}, { 14, 17, 20, 23}, { 13, 16, 19, 22}, { 12, 15, 18, 21}, -{ 12, 14, 17, 20}, { 11, 14, 16, 19}, { 11, 13, 15, 18}, { 10, 12, 15, 17}, -{ 10, 12, 14, 16}, { 9, 11, 13, 15}, { 9, 11, 12, 14}, { 8, 10, 12, 14}, -{ 8, 9, 11, 13}, { 7, 9, 11, 12}, { 7, 9, 10, 12}, { 7, 8, 10, 11}, -{ 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2}, -}; - -static const uint8_t mps_state[64]= { - 1, 2, 3, 4, 5, 6, 7, 8, - 9,10,11,12,13,14,15,16, - 17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31,32, - 33,34,35,36,37,38,39,40, - 41,42,43,44,45,46,47,48, - 49,50,51,52,53,54,55,56, - 57,58,59,60,61,62,62,63, -}; - -static const uint8_t lps_state[64]= { - 0, 0, 1, 2, 2, 4, 4, 5, - 6, 7, 8, 9, 9,11,11,12, - 13,13,15,15,16,16,18,18, - 19,19,21,21,22,22,23,24, - 24,25,26,26,27,27,28,29, - 29,30,30,30,31,32,32,33, - 33,33,34,34,35,35,35,36, - 36,36,37,37,37,38,38,63, -}; - -static const uint8_t last_coeff_flag_offset_8x8[63] = { - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8 +const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = { + 9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + // LPS range + -128, -128, -128, -128, -128, -128, 123, 123, + 116, 116, 111, 111, 105, 105, 100, 100, + 95, 95, 90, 90, 85, 85, 81, 81, + 77, 77, 73, 73, 69, 69, 66, 66, + 62, 62, 59, 59, 56, 56, 53, 53, + 51, 51, 48, 48, 46, 46, 43, 43, + 41, 41, 39, 39, 37, 37, 35, 35, + 33, 33, 32, 32, 30, 30, 29, 29, + 27, 27, 26, 26, 24, 24, 23, 23, + 22, 22, 21, 21, 20, 20, 19, 19, + 18, 18, 17, 17, 16, 16, 15, 15, + 14, 14, 14, 14, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 11, 10, 10, + 10, 10, 9, 9, 9, 9, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, + 6, 6, 6, 6, 6, 6, 2, 2, + -80, -80, -89, -89, -98, -98, -106, -106, + -114, -114, -121, -121, -128, -128, 122, 122, + 116, 116, 110, 110, 104, 104, 99, 99, + 94, 94, 89, 89, 85, 85, 80, 80, + 76, 76, 72, 72, 69, 69, 65, 65, + 62, 62, 59, 59, 56, 56, 53, 53, + 50, 50, 48, 48, 45, 45, 43, 43, + 41, 41, 39, 39, 37, 37, 35, 35, + 33, 33, 31, 31, 30, 30, 28, 28, + 27, 27, 26, 26, 24, 24, 23, 23, + 22, 22, 21, 21, 20, 20, 19, 19, + 18, 18, 17, 17, 16, 16, 15, 15, + 14, 14, 14, 14, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 11, 10, 10, + 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 7, 7, 7, 7, 2, 2, + -48, -48, -59, -59, -69, -69, -78, -78, + -87, -87, -96, -96, -104, -104, -112, -112, + -119, -119, -126, -126, 123, 123, 117, 117, + 111, 111, 105, 105, 100, 100, 95, 95, + 90, 90, 86, 86, 81, 81, 77, 77, + 73, 73, 69, 69, 66, 66, 63, 63, + 59, 59, 56, 56, 54, 54, 51, 51, + 48, 48, 46, 46, 43, 43, 41, 41, + 39, 39, 37, 37, 35, 35, 33, 33, + 32, 32, 30, 30, 29, 29, 27, 27, + 26, 26, 25, 25, 23, 23, 22, 22, + 21, 21, 20, 20, 19, 19, 18, 18, + 17, 17, 16, 16, 15, 15, 15, 15, + 14, 14, 13, 13, 12, 12, 12, 12, + 11, 11, 11, 11, 10, 10, 10, 10, + 9, 9, 9, 9, 8, 8, 2, 2, + -16, -16, -29, -29, -40, -40, -51, -51, + -61, -61, -71, -71, -81, -81, -90, -90, + -98, -98, -106, -106, -114, -114, -121, -121, + -128, -128, 122, 122, 116, 116, 110, 110, + 104, 104, 99, 99, 94, 94, 89, 89, + 85, 85, 80, 80, 76, 76, 72, 72, + 69, 69, 65, 65, 62, 62, 59, 59, + 56, 56, 53, 53, 50, 50, 48, 48, + 45, 45, 43, 43, 41, 41, 39, 39, + 37, 37, 35, 35, 33, 33, 31, 31, + 30, 30, 28, 28, 27, 27, 25, 25, + 24, 24, 23, 23, 22, 22, 21, 21, + 20, 20, 19, 19, 18, 18, 17, 17, + 16, 16, 15, 15, 14, 14, 14, 14, + 13, 13, 12, 12, 12, 12, 11, 11, + 11, 11, 10, 10, 9, 9, 2, 2, + // mlps state + 127, 126, 77, 76, 77, 76, 75, 74, + 75, 74, 75, 74, 73, 72, 73, 72, + 73, 72, 71, 70, 71, 70, 71, 70, + 69, 68, 69, 68, 67, 66, 67, 66, + 67, 66, 65, 64, 65, 64, 63, 62, + 61, 60, 61, 60, 61, 60, 59, 58, + 59, 58, 57, 56, 55, 54, 55, 54, + 53, 52, 53, 52, 51, 50, 49, 48, + 49, 48, 47, 46, 45, 44, 45, 44, + 43, 42, 43, 42, 39, 38, 39, 38, + 37, 36, 37, 36, 33, 32, 33, 32, + 31, 30, 31, 30, 27, 26, 27, 26, + 25, 24, 23, 22, 23, 22, 19, 18, + 19, 18, 17, 16, 15, 14, 13, 12, + 11, 10, 9, 8, 9, 8, 5, 4, + 5, 4, 3, 2, 1, 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, 124, 125, 126, 127, + // last_coeff_flag_offset_8x8 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8 }; /** - * * @param buf_size size of buf in bits */ void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ @@ -120,35 +174,3 @@ void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ c->low+= ((*c->bytestream++)<<2) + 2; c->range= 0x1FE; } - -void ff_init_cabac_states(void) -{ - int i, j; - static int initialized = 0; - - if (initialized) - return; - - 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] = 2 * mps_state[i] + 0; - ff_h264_mlps_state[128 + 2 * i + 1] = 2 * mps_state[i] + 1; - - if( i ){ - 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; - } - } - for(i=0; i< 63; i++){ - ff_h264_last_coeff_flag_offset_8x8[i] = last_coeff_flag_offset_8x8[i]; - } - - initialized = 1; -} diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h index 426f338..40eefed 100644 --- a/libavcodec/cabac.h +++ b/libavcodec/cabac.h @@ -31,7 +31,7 @@ #include "put_bits.h" -extern uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; +extern const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; #define H264_NORM_SHIFT_OFFSET 0 #define H264_LPS_RANGE_OFFSET 512 #define H264_MLPS_STATE_OFFSET 1024 @@ -49,6 +49,5 @@ typedef struct CABACContext{ }CABACContext; void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size); -void ff_init_cabac_states(void); #endif /* AVCODEC_CABAC_H */ diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h index 4b8f1bc..beb5016 100644 --- a/libavcodec/cabac_functions.h +++ b/libavcodec/cabac_functions.h @@ -42,10 +42,10 @@ # include "x86/cabac.h" #endif -static uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; -static uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; -static uint8_t * const ff_h264_mlps_state = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET; -static uint8_t * const ff_h264_last_coeff_flag_offset_8x8 = ff_h264_cabac_tables + H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET; +static const uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; +static const uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; +static const uint8_t * const ff_h264_mlps_state = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET; +static const uint8_t * const ff_h264_last_coeff_flag_offset_8x8 = ff_h264_cabac_tables + H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET; static void refill(CABACContext *c){ #if CABAC_BITS == 16 @@ -154,7 +154,6 @@ static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ #endif /** - * * @return the number of bytes read or 0 if no end */ static int av_unused get_cabac_terminate(CABACContext *c){ diff --git a/libavcodec/canopus.c b/libavcodec/canopus.c new file mode 100644 index 0000000..729e7ef --- /dev/null +++ b/libavcodec/canopus.c @@ -0,0 +1,63 @@ +/* + * Canopus common routines + * Copyright (c) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/rational.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "canopus.h" + +int ff_canopus_parse_info_tag(AVCodecContext *avctx, + const uint8_t *src, size_t size) +{ + GetByteContext gbc; + int par_x, par_y, field_order; + + bytestream2_init(&gbc, src, size); + + /* Parse aspect ratio. */ + bytestream2_skip(&gbc, 8); // unknown, 16 bits 1 + par_x = bytestream2_get_le32(&gbc); + par_y = bytestream2_get_le32(&gbc); + if (par_x && par_y) + av_reduce(&avctx->sample_aspect_ratio.num, + &avctx->sample_aspect_ratio.den, + par_x, par_y, 255); + + /* Short INFO tag (used in CLLC) has only AR data. */ + if (size == 0x18) + return 0; + + bytestream2_skip(&gbc, 16); // unknown RDRT tag + + /* Parse FIEL tag. */ + bytestream2_skip(&gbc, 8); // 'FIEL' and 4 bytes 0 + field_order = bytestream2_get_le32(&gbc); + switch (field_order) { + case 0: avctx->field_order = AV_FIELD_TT; break; + case 1: avctx->field_order = AV_FIELD_BB; break; + case 2: avctx->field_order = AV_FIELD_PROGRESSIVE; break; + } + + return 0; +} diff --git a/libavcodec/canopus.h b/libavcodec/canopus.h new file mode 100644 index 0000000..9e5702d --- /dev/null +++ b/libavcodec/canopus.h @@ -0,0 +1,32 @@ +/* + * Canopus common routines + * Copyright (c) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CANOPUS_H +#define AVCODEC_CANOPUS_H + +#include + +#include "avcodec.h" + +int ff_canopus_parse_info_tag(AVCodecContext *avctx, + const uint8_t *src, size_t size); + +#endif /* AVCODEC_CANOPUS_H */ diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index 788fcad..cf66629 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -90,9 +90,9 @@ static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b) } #define SET_PARAMS \ - alpha = alpha_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)]; \ - beta = beta_tab[av_clip(qp_avg + h->beta_offset, 0, 63)]; \ - tc = tc_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)]; + alpha = alpha_tab[av_clip_uintp2(qp_avg + h->alpha_offset, 6)]; \ + beta = beta_tab[av_clip_uintp2(qp_avg + h->beta_offset, 6)]; \ + tc = tc_tab[av_clip_uintp2(qp_avg + h->alpha_offset, 6)]; /** * in-loop deblocking filter for a single macroblock @@ -104,7 +104,6 @@ static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b) * | 6 | 7 | * 1 3 | * --------- - * */ void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type) { @@ -247,7 +246,7 @@ void ff_cavs_load_intra_pred_chroma(AVSContext *h) } } -static void intra_pred_vert(uint8_t *d, uint8_t *top, uint8_t *left, int stride) +static void intra_pred_vert(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int y; uint64_t a = AV_RN64(&top[1]); @@ -255,7 +254,7 @@ static void intra_pred_vert(uint8_t *d, uint8_t *top, uint8_t *left, int stride) *((uint64_t *)(d + y * stride)) = a; } -static void intra_pred_horiz(uint8_t *d, uint8_t *top, uint8_t *left, int stride) +static void intra_pred_horiz(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int y; uint64_t a; @@ -265,7 +264,7 @@ static void intra_pred_horiz(uint8_t *d, uint8_t *top, uint8_t *left, int stride } } -static void intra_pred_dc_128(uint8_t *d, uint8_t *top, uint8_t *left, int stride) +static void intra_pred_dc_128(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int y; uint64_t a = 0x8080808080808080ULL; @@ -273,7 +272,7 @@ static void intra_pred_dc_128(uint8_t *d, uint8_t *top, uint8_t *left, int strid *((uint64_t *)(d + y * stride)) = a; } -static void intra_pred_plane(uint8_t *d, uint8_t *top, uint8_t *left, int stride) +static void intra_pred_plane(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y, ia; int ih = 0; @@ -295,7 +294,7 @@ static void intra_pred_plane(uint8_t *d, uint8_t *top, uint8_t *left, int stride #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) +static void intra_pred_lp(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y; for (y = 0; y < 8; y++) @@ -303,7 +302,7 @@ static void intra_pred_lp(uint8_t *d, uint8_t *top, uint8_t *left, int stride) 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) +static void intra_pred_down_left(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y; for (y = 0; y < 8; y++) @@ -311,7 +310,7 @@ static void intra_pred_down_left(uint8_t *d, uint8_t *top, uint8_t *left, int st 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) +static void intra_pred_down_right(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y; for (y = 0; y < 8; y++) @@ -324,7 +323,7 @@ static void intra_pred_down_right(uint8_t *d, uint8_t *top, uint8_t *left, int s 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) +static void intra_pred_lp_left(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y; for (y = 0; y < 8; y++) @@ -332,7 +331,7 @@ static void intra_pred_lp_left(uint8_t *d, uint8_t *top, uint8_t *left, int stri 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) +static void intra_pred_lp_top(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride) { int x, y; for (y = 0; y < 8; y++) diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h index cfae055..e8729d5 100644 --- a/libavcodec/cavs.h +++ b/libavcodec/cavs.h @@ -226,8 +226,8 @@ typedef struct AVSContext { 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); + void (*intra_pred_l[8])(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride); + void (*intra_pred_c[7])(uint8_t *d, uint8_t *top, uint8_t *left, ptrdiff_t stride); uint8_t *col_type_base; /* scaling factors for MV prediction */ diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index a091eeb..1c4f276 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -31,7 +31,6 @@ #include "cavs.h" #include "internal.h" #include "mpeg12data.h" -#include "mpegvideo.h" static const uint8_t mv_scan[4] = { MV_FWD_X0, MV_FWD_X1, @@ -548,7 +547,7 @@ static inline int dequant(AVSContext *h, int16_t *level_buf, uint8_t *run_buf, */ static int decode_residual_block(AVSContext *h, GetBitContext *gb, const struct dec_2dvlc *r, int esc_golomb_order, - int qp, uint8_t *dst, int stride) + int qp, uint8_t *dst, ptrdiff_t stride) { int i, level_code, esc_code, level, run, mask, ret; int16_t level_buf[65]; @@ -1106,8 +1105,7 @@ static int decode_seq_header(AVSContext *h) h->low_delay = get_bits1(&h->gb); h->mb_width = (h->width + 15) >> 4; h->mb_height = (h->height + 15) >> 4; - h->avctx->time_base.den = ff_mpeg12_frame_rate_tab[frame_rate_code].num; - h->avctx->time_base.num = ff_mpeg12_frame_rate_tab[frame_rate_code].den; + h->avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_code]; h->avctx->width = h->width; h->avctx->height = h->height; if (!h->top_qp) @@ -1203,6 +1201,6 @@ AVCodec ff_cavs_decoder = { .init = ff_cavs_init, .close = ff_cavs_end, .decode = cavs_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .flush = cavs_flush, }; diff --git a/libavcodec/cavsdsp.c b/libavcodec/cavsdsp.c index cc78989..a374dec 100644 --- a/libavcodec/cavsdsp.c +++ b/libavcodec/cavsdsp.c @@ -42,7 +42,8 @@ #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) { +static inline void loop_filter_l2(uint8_t *p0_p, ptrdiff_t stride, int alpha, int beta) +{ int p0 = P0; int q0 = Q0; @@ -62,7 +63,8 @@ static inline void loop_filter_l2(uint8_t *p0_p,int stride,int alpha, int beta) } } -static inline void loop_filter_l1(uint8_t *p0_p, int stride, int alpha, int beta, int tc) { +static inline void loop_filter_l1(uint8_t *p0_p, ptrdiff_t stride, int alpha, int beta, int tc) +{ int p0 = P0; int q0 = Q0; @@ -81,7 +83,8 @@ static inline void loop_filter_l1(uint8_t *p0_p, int stride, int alpha, int beta } } -static inline void loop_filter_c2(uint8_t *p0_p,int stride,int alpha, int beta) { +static inline void loop_filter_c2(uint8_t *p0_p, ptrdiff_t stride, int alpha, int beta) +{ int p0 = P0; int q0 = Q0; @@ -99,8 +102,9 @@ static inline void loop_filter_c2(uint8_t *p0_p,int stride,int alpha, int beta) } } -static inline void loop_filter_c1(uint8_t *p0_p,int stride,int alpha, int beta, - int tc) { +static inline void loop_filter_c1(uint8_t *p0_p, ptrdiff_t stride, int alpha, int beta, + int tc) +{ if(abs(P0-Q0)>3, -tc, tc); P0 = av_clip_uint8(P0+delta); @@ -115,8 +119,9 @@ static inline void loop_filter_c1(uint8_t *p0_p,int stride,int alpha, int beta, #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) { +static void cavs_filter_lv_c(uint8_t *d, ptrdiff_t stride, int alpha, int beta, int tc, + int bs1, int bs2) +{ int i; if(bs1==2) for(i=0;i<16;i++) @@ -131,8 +136,9 @@ static void cavs_filter_lv_c(uint8_t *d, int stride, int alpha, int beta, int tc } } -static void cavs_filter_lh_c(uint8_t *d, int stride, int alpha, int beta, int tc, - int bs1, int bs2) { +static void cavs_filter_lh_c(uint8_t *d, ptrdiff_t stride, int alpha, int beta, int tc, + int bs1, int bs2) +{ int i; if(bs1==2) for(i=0;i<16;i++) @@ -147,8 +153,9 @@ static void cavs_filter_lh_c(uint8_t *d, int stride, int alpha, int beta, int tc } } -static void cavs_filter_cv_c(uint8_t *d, int stride, int alpha, int beta, int tc, - int bs1, int bs2) { +static void cavs_filter_cv_c(uint8_t *d, ptrdiff_t stride, int alpha, int beta, int tc, + int bs1, int bs2) +{ int i; if(bs1==2) for(i=0;i<8;i++) @@ -163,8 +170,9 @@ static void cavs_filter_cv_c(uint8_t *d, int stride, int alpha, int beta, int tc } } -static void cavs_filter_ch_c(uint8_t *d, int stride, int alpha, int beta, int tc, - int bs1, int bs2) { +static void cavs_filter_ch_c(uint8_t *d, ptrdiff_t stride, int alpha, int beta, int tc, + int bs1, int bs2) +{ int i; if(bs1==2) for(i=0;i<8;i++) @@ -185,7 +193,8 @@ static void cavs_filter_ch_c(uint8_t *d, int stride, int alpha, int beta, int tc * ****************************************************************************/ -static void cavs_idct8_add_c(uint8_t *dst, int16_t *block, int stride) { +static void cavs_idct8_add_c(uint8_t *dst, int16_t *block, ptrdiff_t stride) +{ int i; int16_t (*src)[8] = (int16_t(*)[8])block; const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; @@ -261,7 +270,8 @@ static void cavs_idct8_add_c(uint8_t *dst, int16_t *block, int stride) { ****************************************************************************/ #define CAVS_SUBPIX(OPNAME, OP, NAME, A, B, C, D, E, F) \ -static void OPNAME ## cavs_filt8_h_ ## NAME(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_filt8_h_ ## NAME(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ const int h=8;\ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ @@ -280,7 +290,8 @@ static void OPNAME ## cavs_filt8_h_ ## NAME(uint8_t *dst, const uint8_t *src, in }\ }\ \ -static void OPNAME ## cavs_filt8_v_ ## NAME(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_filt8_v_ ## NAME(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ const int w=8;\ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ @@ -312,7 +323,8 @@ static void OPNAME ## cavs_filt8_v_ ## NAME(uint8_t *dst, const uint8_t *src, i }\ }\ \ -static void OPNAME ## cavs_filt16_v_ ## NAME(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_filt16_v_ ## NAME(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_filt8_v_ ## NAME(dst , src , dstStride, srcStride);\ OPNAME ## cavs_filt8_v_ ## NAME(dst+8, src+8, dstStride, srcStride);\ src += 8*srcStride;\ @@ -321,7 +333,8 @@ static void OPNAME ## cavs_filt16_v_ ## NAME(uint8_t *dst, const uint8_t *src, i OPNAME ## cavs_filt8_v_ ## NAME(dst+8, src+8, dstStride, srcStride);\ }\ \ -static void OPNAME ## cavs_filt16_h_ ## NAME(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_filt16_h_ ## NAME(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_filt8_h_ ## NAME(dst , src , dstStride, srcStride);\ OPNAME ## cavs_filt8_h_ ## NAME(dst+8, src+8, dstStride, srcStride);\ src += 8*srcStride;\ @@ -331,7 +344,8 @@ static void OPNAME ## cavs_filt16_h_ ## NAME(uint8_t *dst, const uint8_t *src, i }\ #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, const uint8_t *src1, const uint8_t *src2, int dstStride, int srcStride){\ +static void OPNAME ## cavs_filt8_hv_ ## NAME(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ int16_t temp[8*(8+5)];\ int16_t *tmp = temp;\ const int h=8;\ @@ -412,7 +426,8 @@ static void OPNAME ## cavs_filt8_hv_ ## NAME(uint8_t *dst, const uint8_t *src1, }\ }\ \ -static void OPNAME ## cavs_filt16_hv_ ## NAME(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dstStride, int srcStride){ \ +static void OPNAME ## cavs_filt16_hv_ ## NAME(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t 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;\ diff --git a/libavcodec/cavsdsp.h b/libavcodec/cavsdsp.h index 248afd5..65aa38a 100644 --- a/libavcodec/cavsdsp.h +++ b/libavcodec/cavsdsp.h @@ -30,11 +30,11 @@ typedef struct CAVSDSPContext { qpel_mc_func put_cavs_qpel_pixels_tab[2][16]; qpel_mc_func avg_cavs_qpel_pixels_tab[2][16]; - void (*cavs_filter_lv)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); - void (*cavs_filter_lh)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); - void (*cavs_filter_cv)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); - void (*cavs_filter_ch)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); - void (*cavs_idct8_add)(uint8_t *dst, int16_t *block, int stride); + void (*cavs_filter_lv)(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_lh)(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_cv)(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_ch)(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_idct8_add)(uint8_t *dst, int16_t *block, ptrdiff_t stride); int idct_perm; } CAVSDSPContext; diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index c3e42e7..3b68f45 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -372,5 +372,5 @@ AVCodec ff_cdgraphics_decoder = { .init = cdg_decode_init, .close = cdg_decode_end, .decode = cdg_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c index 80a3671..99e96eb 100644 --- a/libavcodec/cdxl.c +++ b/libavcodec/cdxl.c @@ -31,7 +31,7 @@ #define BIT_LINE 0x80 #define BYTE_LINE 0xC0 -typedef struct { +typedef struct CDXLVideoContext { AVCodecContext *avctx; int bpp; int format; @@ -263,7 +263,7 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data, if (encoding) { av_fast_padded_malloc(&c->new_video, &c->new_video_size, - h * w + FF_INPUT_BUFFER_PADDING_SIZE); + h * w + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->new_video) return AVERROR(ENOMEM); if (c->bpp == 8) @@ -296,5 +296,5 @@ AVCodec ff_cdxl_decoder = { .init = cdxl_decode_init, .close = cdxl_decode_end, .decode = cdxl_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/celp_filters.c b/libavcodec/celp_filters.c index 381ffa4..61474f5 100644 --- a/libavcodec/celp_filters.c +++ b/libavcodec/celp_filters.c @@ -133,7 +133,7 @@ void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs, out2 -= val * old_out2; out3 -= val * old_out3; - for (i = 5; i <= filter_length; i += 2) { + for (i = 5; i < filter_length; i += 2) { old_out3 = out[-i]; val = filter_coeffs[i-1]; diff --git a/libavcodec/celp_math.c b/libavcodec/celp_math.c index a9ebef6..8a788f5 100644 --- a/libavcodec/celp_math.c +++ b/libavcodec/celp_math.c @@ -26,6 +26,8 @@ #include "avcodec.h" #include "celp_math.h" +#include "mathops.h" + #include "libavutil/common.h" static const uint16_t exp2a[]= @@ -86,3 +88,14 @@ int ff_log2_q15(uint32_t value) return (power_int << 15) + value; } + +int64_t ff_dot_product(const int16_t *a, const int16_t *b, int length) +{ + int i; + int64_t sum = 0; + + for (i = 0; i < length; i++) + sum += MUL16(a[i], b[i]); + + return sum; +} diff --git a/libavcodec/celp_math.h b/libavcodec/celp_math.h index ed3f8c0..9cebdfe 100644 --- a/libavcodec/celp_math.h +++ b/libavcodec/celp_math.h @@ -43,6 +43,16 @@ int ff_exp2(uint16_t power); int ff_log2_q15(uint32_t value); /** + * Calculate the dot product of 2 int16_t vectors. + * @param a input data array + * @param b input data array + * @param length number of elements + * + * @return dot product = sum of elementwise products + */ +int64_t ff_dot_product(const int16_t *a, const int16_t *b, int length); + +/** * Shift value left or right depending on sign of offset parameter. * @param value value to shift * @param offset shift offset diff --git a/libavcodec/chomp_bsf.c b/libavcodec/chomp_bsf.c index 9ed7496..2e76113 100644 --- a/libavcodec/chomp_bsf.c +++ b/libavcodec/chomp_bsf.c @@ -20,19 +20,23 @@ */ #include "avcodec.h" +#include "bsf.h" #include "internal.h" -static int chomp_filter(AVBitStreamFilterContext *bsfc, - AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int keyframe) +static int chomp_filter(AVBSFContext *ctx, AVPacket *out) { - while (buf_size > 0 && !buf[buf_size-1]) - buf_size--; + AVPacket *in; + int ret; - *poutbuf = (uint8_t*) buf; - *poutbuf_size = buf_size; + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + while (in->size > 0 && !in->data[in->size - 1]) + in->size--; + + av_packet_move_ref(out, in); + av_packet_free(&in); return 0; } @@ -40,8 +44,7 @@ static int chomp_filter(AVBitStreamFilterContext *bsfc, /** * This filter removes a string of NULL bytes from the end of a packet. */ -AVBitStreamFilter ff_chomp_bsf = { - "chomp", - 0, - chomp_filter, +const AVBitStreamFilter ff_chomp_bsf = { + .name = "chomp", + .filter = chomp_filter, }; diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index caf14cb..611ffe5 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -1,6 +1,6 @@ /* * Cinepak Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -40,14 +40,14 @@ #include "internal.h" -typedef struct { +typedef struct cvid_codebook { uint8_t y0, y1, y2, y3; uint8_t u, v; } cvid_codebook; #define MAX_STRIPS 32 -typedef struct { +typedef struct cvid_strip { uint16_t id; uint16_t x1, y1; uint16_t x2, y2; @@ -477,5 +477,5 @@ AVCodec ff_cinepak_decoder = { .init = cinepak_decode_init, .close = cinepak_decode_end, .decode = cinepak_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cljrdec.c b/libavcodec/cljrdec.c index e74d1fa..33d8023 100644 --- a/libavcodec/cljrdec.c +++ b/libavcodec/cljrdec.c @@ -91,5 +91,5 @@ AVCodec ff_cljr_decoder = { .id = AV_CODEC_ID_CLJR, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c index 2c31555..0687e30 100644 --- a/libavcodec/cljrenc.c +++ b/libavcodec/cljrenc.c @@ -30,21 +30,6 @@ #include "internal.h" #include "put_bits.h" -static av_cold int encode_init(AVCodecContext *avctx) -{ - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - - return 0; -} - -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { @@ -56,8 +41,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return ret; } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif init_put_bits(&pb, pkt->data, pkt->size); @@ -89,9 +78,7 @@ AVCodec ff_cljr_encoder = { .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_CLJR, - .init = encode_init, .encode2 = encode_frame, - .close = encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c index f081c68..cdbed74 100644 --- a/libavcodec/cllc.c +++ b/libavcodec/cllc.c @@ -24,6 +24,7 @@ #include "libavutil/intreadwrite.h" #include "bswapdsp.h" +#include "canopus.h" #include "get_bits.h" #include "avcodec.h" #include "internal.h" @@ -362,7 +363,11 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, GetBitContext gb; int coding_type, ret; - /* Skip the INFO header if present */ + if (avpkt->size < 4 + 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small %d.\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + info_offset = 0; info_tag = AV_RL32(src); if (info_tag == MKTAG('I', 'N', 'F', 'O')) { @@ -373,11 +378,10 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, info_offset); return AVERROR_INVALIDDATA; } + ff_canopus_parse_info_tag(avctx, src + 8, info_offset); info_offset += 8; src += info_offset; - - av_log(avctx, AV_LOG_DEBUG, "Skipping INFO chunk.\n"); } data_size = (avpkt->size - info_offset) & ~1; @@ -499,5 +503,5 @@ AVCodec ff_cllc_decoder = { .init = cllc_decode_init, .decode = cllc_decode_frame, .close = cllc_decode_close, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c index 89f5c81..482ef94 100644 --- a/libavcodec/cngdec.c +++ b/libavcodec/cngdec.c @@ -169,5 +169,5 @@ AVCodec ff_comfortnoise_decoder = { .close = cng_decode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index c21c57e..18568c9 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -21,6 +21,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "avcodec.h" +#include "profiles.h" #include "version.h" static const AVCodecDescriptor codec_descriptors[] = { @@ -38,6 +39,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "mpeg2video", .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), }, #if FF_API_XVMC { @@ -96,6 +98,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "mpeg4", .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), }, { .id = AV_CODEC_ID_RAWVIDEO, @@ -201,6 +204,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "h264", .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), }, { .id = AV_CODEC_ID_INDEO3, @@ -460,6 +464,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "vc1", .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles), }, { .id = AV_CODEC_ID_WMV3, @@ -467,6 +472,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "wmv3", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles), }, { .id = AV_CODEC_ID_LOCO, @@ -587,6 +593,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + .profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles), }, { .id = AV_CODEC_ID_VMNC, @@ -1098,6 +1105,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "hevc", .long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), }, { .id = AV_CODEC_ID_FIC, @@ -1134,6 +1142,76 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_HQX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "hqx", + .long_name = NULL_IF_CONFIG_SMALL("Canopus HQX"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_HQ_HQA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "hq_hqa", + .long_name = NULL_IF_CONFIG_SMALL("Canopus HQ/HQA"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_HAP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "hap", + .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap decoder"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DXV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dxv", + .long_name = NULL_IF_CONFIG_SMALL("Resolume DXV"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SCREENPRESSO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "screenpresso", + .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_WRAPPED_AVFRAME, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wrapped_avframe", + .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_RSCC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rscc", + .long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MAGICYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "magicyuv", + .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TRUEMOTION2RT, + .type = AVMEDIA_TYPE_VIDEO, + .name = "truemotion2rt", + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "av1", + .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), + .props = AV_CODEC_PROP_LOSSY, + }, /* image codecs */ { @@ -1158,6 +1236,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { + .id = AV_CODEC_ID_DDS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dds", + .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { .id = AV_CODEC_ID_DPX, .type = AVMEDIA_TYPE_VIDEO, .name = "dpx", @@ -1279,6 +1365,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { + .id = AV_CODEC_ID_TDSC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tdsc", + .long_name = NULL_IF_CONFIG_SMALL("TDSC"), + .props = AV_CODEC_PROP_LOSSY, + }, + { .id = AV_CODEC_ID_TIFF, .type = AVMEDIA_TYPE_VIDEO, .name = "tiff", @@ -1455,6 +1548,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { + .id = AV_CODEC_ID_PCM_S16BE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s16be_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { .id = AV_CODEC_ID_PCM_S16LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s16le_planar", @@ -1841,6 +1941,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "aac", .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), .props = AV_CODEC_PROP_LOSSY, + .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }, { .id = AV_CODEC_ID_AC3, @@ -1855,6 +1956,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "dts", .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), }, { .id = AV_CODEC_ID_VORBIS, @@ -2202,6 +2304,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { + .id = AV_CODEC_ID_DSS_SP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dss_sp", + .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { .id = AV_CODEC_ID_G729, .type = AVMEDIA_TYPE_AUDIO, .name = "g729", @@ -2378,3 +2487,9 @@ const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name) return desc; return NULL; } + +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id) +{ + const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); + return desc ? desc->type : AVMEDIA_TYPE_UNKNOWN; +} diff --git a/libavcodec/cook.c b/libavcodec/cook.c index 8c2fab7..016b1d0 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -64,12 +64,12 @@ #define SUBBAND_SIZE 20 #define MAX_SUBPACKETS 5 -typedef struct { +typedef struct cook_gains { int *now; int *previous; } cook_gains; -typedef struct { +typedef struct COOKSubpacket { int ch_idx; int size; int num_channels; @@ -140,7 +140,7 @@ typedef struct cook { VLC envelope_quant_index[13]; VLC sqvh[7]; // scalar quantization - /* generatable tables and related variables */ + /* generate tables and related variables */ int gain_size_factor; float gain_table[23]; @@ -1013,14 +1013,14 @@ static int cook_decode_frame(AVCodecContext *avctx, void *data, static void dump_cook_context(COOKContext *q) { //int i=0; -#define PRINT(a, b) av_dlog(q->avctx, " %s = %d\n", a, b); - av_dlog(q->avctx, "COOKextradata\n"); - av_dlog(q->avctx, "cookversion=%x\n", q->subpacket[0].cookversion); +#define PRINT(a, b) ff_dlog(q->avctx, " %s = %d\n", a, b); + ff_dlog(q->avctx, "COOKextradata\n"); + ff_dlog(q->avctx, "cookversion=%x\n", q->subpacket[0].cookversion); if (q->subpacket[0].cookversion > STEREO) { PRINT("js_subband_start", q->subpacket[0].js_subband_start); PRINT("js_vlc_bits", q->subpacket[0].js_vlc_bits); } - av_dlog(q->avctx, "COOKContext\n"); + ff_dlog(q->avctx, "COOKContext\n"); PRINT("nb_channels", q->avctx->channels); PRINT("bit_rate", q->avctx->bit_rate); PRINT("sample_rate", q->avctx->sample_rate); @@ -1041,9 +1041,7 @@ static void dump_cook_context(COOKContext *q) static av_cold int cook_decode_init(AVCodecContext *avctx) { COOKContext *q = avctx->priv_data; - const uint8_t *edata_ptr = avctx->extradata; - const uint8_t *edata_ptr_end = edata_ptr + avctx->extradata_size; - int extradata_size = avctx->extradata_size; + GetByteContext gb; int s = 0; unsigned int channel_mask = 0; int samples_per_frame; @@ -1051,12 +1049,14 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->avctx = avctx; /* Take care of the codec specific extradata. */ - if (extradata_size < 8) { + if (avctx->extradata_size < 8) { av_log(avctx, AV_LOG_ERROR, "Necessary extradata missing!\n"); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "codecdata_length=%d\n", avctx->extradata_size); + bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); + /* Take data from the AVCodecContext (RM container). */ if (!avctx->channels) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); @@ -1068,21 +1068,15 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) ff_audiodsp_init(&q->adsp); - while (edata_ptr < edata_ptr_end) { + while (bytestream2_get_bytes_left(&gb)) { /* 8 for mono, 16 for stereo, ? for multichannel Swap to right endianness so we don't need to care later on. */ - if (extradata_size >= 8) { - q->subpacket[s].cookversion = bytestream_get_be32(&edata_ptr); - samples_per_frame = bytestream_get_be16(&edata_ptr); - q->subpacket[s].subbands = bytestream_get_be16(&edata_ptr); - extradata_size -= 8; - } - if (extradata_size >= 8) { - bytestream_get_be32(&edata_ptr); // Unknown unused - q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr); - q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr); - extradata_size -= 8; - } + q->subpacket[s].cookversion = bytestream2_get_be32(&gb); + samples_per_frame = bytestream2_get_be16(&gb); + q->subpacket[s].subbands = bytestream2_get_be16(&gb); + bytestream2_get_be32(&gb); // Unknown unused + q->subpacket[s].js_subband_start = bytestream2_get_be16(&gb); + q->subpacket[s].js_vlc_bits = bytestream2_get_be16(&gb); /* Initialize extradata related variables. */ q->subpacket[s].samples_per_channel = samples_per_frame / avctx->channels; @@ -1134,8 +1128,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) break; case MC_COOK: av_log(avctx, AV_LOG_DEBUG, "MULTI_CHANNEL\n"); - if (extradata_size >= 4) - channel_mask |= q->subpacket[s].channel_mask = bytestream_get_be32(&edata_ptr); + channel_mask |= q->subpacket[s].channel_mask = bytestream2_get_be32(&gb); if (av_get_channel_layout_nb_channels(q->subpacket[s].channel_mask) > 1) { q->subpacket[s].total_subbands = q->subpacket[s].subbands + @@ -1170,7 +1163,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) /* Initialize variable relations */ q->subpacket[s].numvector_size = (1 << q->subpacket[s].log2_numvector_size); - /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + /* Try to catch some obviously faulty streams, otherwise it might be exploitable */ if (q->subpacket[s].total_subbands > 53) { avpriv_request_sample(avctx, "total_subbands > 53"); return AVERROR_PATCHWELCOME; @@ -1213,11 +1206,11 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) /* Pad the databuffer with: DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), - FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ + AV_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ q->decoded_bytes_buffer = av_mallocz(avctx->block_align + DECODE_BYTES_PAD1(avctx->block_align) - + FF_INPUT_BUFFER_PADDING_SIZE); + + AV_INPUT_BUFFER_PADDING_SIZE); if (!q->decoded_bytes_buffer) return AVERROR(ENOMEM); @@ -1234,7 +1227,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->saturate_output = saturate_output_float; } - /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + /* Try to catch some obviously faulty streams, otherwise it might be exploitable */ if (q->samples_per_channel != 256 && q->samples_per_channel != 512 && q->samples_per_channel != 1024) { avpriv_request_sample(avctx, "samples_per_channel = %d", @@ -1263,7 +1256,7 @@ AVCodec ff_cook_decoder = { .init = cook_decode_init, .close = cook_decode_close, .decode = cook_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/cookdata.h b/libavcodec/cookdata.h index c4c26fa..714ba1e 100644 --- a/libavcodec/cookdata.h +++ b/libavcodec/cookdata.h @@ -22,7 +22,7 @@ /** * @file - * Cook AKA RealAudio G2 compatible decoderdata + * Cook AKA RealAudio G2 compatible decoder data */ #ifndef AVCODEC_COOKDATA_H diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c index 9ae7e33..0cb375b 100644 --- a/libavcodec/cscd.c +++ b/libavcodec/cscd.c @@ -30,7 +30,7 @@ #endif #include "libavutil/lzo.h" -typedef struct { +typedef struct CamStudioContext { int linelen, height, bpp; unsigned int decomp_size; unsigned char* decomp_buf; @@ -256,5 +256,5 @@ AVCodec ff_cscd_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/cyuv.c b/libavcodec/cyuv.c index f628ba1..86f7aac 100644 --- a/libavcodec/cyuv.c +++ b/libavcodec/cyuv.c @@ -4,7 +4,7 @@ * based on "Creative YUV (CYUV) stream format for AVI": * http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt * - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -172,7 +172,7 @@ AVCodec ff_aura_decoder = { .priv_data_size = sizeof(CyuvDecodeContext), .init = cyuv_decode_init, .decode = cyuv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -185,6 +185,6 @@ AVCodec ff_cyuv_decoder = { .priv_data_size = sizeof(CyuvDecodeContext), .init = cyuv_decode_init, .decode = cyuv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/d3d11va.c b/libavcodec/d3d11va.c new file mode 100644 index 0000000..946de06 --- /dev/null +++ b/libavcodec/d3d11va.c @@ -0,0 +1,48 @@ +/* + * Direct3D11 HW acceleration + * + * copyright (c) 2015 Steve Lhomme + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#if CONFIG_D3D11VA +#include "libavutil/error.h" +#include "libavutil/mem.h" + +#include "d3d11va.h" + +AVD3D11VAContext *av_d3d11va_alloc_context(void) +{ + AVD3D11VAContext* res = av_mallocz(sizeof(AVD3D11VAContext)); + if (!res) + return NULL; + res->context_mutex = INVALID_HANDLE_VALUE; + return res; +} +#else +struct AVD3D11VAContext *av_d3d11va_alloc_context(void); + +struct AVD3D11VAContext *av_d3d11va_alloc_context(void) +{ + return NULL; +} +#endif /* CONFIG_D3D11VA */ diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h new file mode 100644 index 0000000..9264ec6 --- /dev/null +++ b/libavcodec/d3d11va.h @@ -0,0 +1,112 @@ +/* + * Direct3D11 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * copyright (c) 2015 Steve Lhomme + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_D3D11VA_H +#define AVCODEC_D3D11VA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_d3d11va + * Public libavcodec D3D11VA header. + */ + +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + +#include +#include + +/** + * @defgroup lavc_codec_hwaccel_d3d11va Direct3D11 + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards +#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface + +/** + * This structure is used to provides the necessary configurations and data + * to the Direct3D11 Libav HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + * + * Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext. + */ +typedef struct AVD3D11VAContext { + /** + * D3D11 decoder object + */ + ID3D11VideoDecoder *decoder; + + /** + * D3D11 VideoContext + */ + ID3D11VideoContext *video_context; + + /** + * D3D11 configuration used to create the decoder + */ + D3D11_VIDEO_DECODER_CONFIG *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + ID3D11VideoDecoderOutputView **surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the Libav AVHWAccel implementation + */ + unsigned report_id; + + /** + * Mutex to access video_context + */ + HANDLE context_mutex; +} AVD3D11VAContext; + +/** + * Allocate an AVD3D11VAContext. + * + * @return Newly-allocated AVD3D11VAContext or NULL on failure. + */ +AVD3D11VAContext *av_d3d11va_alloc_context(void); + +/** + * @} + */ + +#endif /* AVCODEC_D3D11VA_H */ diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 3fab173..c5daf07 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -24,10 +24,10 @@ #include "libavutil/error.h" #include "dca.h" +#include "dca_syncwords.h" #include "put_bits.h" -const uint32_t avpriv_dca_sample_rates[16] = -{ +const uint32_t avpriv_dca_sample_rates[16] = { 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 96000, 192000 }; @@ -37,8 +37,6 @@ int ff_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, { uint32_t mrk; int i, tmp; - const uint16_t *ssrc = (const uint16_t *) src; - uint16_t *sdst = (uint16_t *) dst; PutBitContext pb; if ((unsigned) src_size > (unsigned) max_size) @@ -46,18 +44,21 @@ int ff_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, mrk = AV_RB32(src); switch (mrk) { - case DCA_MARKER_RAW_BE: + case DCA_SYNCWORD_CORE_BE: memcpy(dst, src, src_size); return src_size; - case DCA_MARKER_RAW_LE: - for (i = 0; i < (src_size + 1) >> 1; i++) - *sdst++ = av_bswap16(*ssrc++); + case DCA_SYNCWORD_CORE_LE: + for (i = 0; i < (src_size + 1) >> 1; i++) { + AV_WB16(dst, AV_RL16(src)); + src += 2; + dst += 2; + } return src_size; - case DCA_MARKER_14B_BE: - case DCA_MARKER_14B_LE: + case DCA_SYNCWORD_CORE_14B_BE: + case DCA_SYNCWORD_CORE_14B_LE: init_put_bits(&pb, dst, max_size); for (i = 0; i < (src_size + 1) >> 1; i++, src += 2) { - tmp = ((mrk == DCA_MARKER_14B_BE) ? AV_RB16(src) : AV_RL16(src)) & 0x3FFF; + tmp = ((mrk == DCA_SYNCWORD_CORE_14B_BE) ? AV_RB16(src) : AV_RL16(src)) & 0x3FFF; put_bits(&pb, 14, tmp); } flush_put_bits(&pb); diff --git a/libavcodec/dca.h b/libavcodec/dca.h index 0037de2..787a9c7 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -26,16 +26,267 @@ #define AVCODEC_DCA_H #include + +#include "libavutil/float_dsp.h" #include "libavutil/internal.h" -/** DCA syncwords, also used for bitstream type detection */ -#define DCA_MARKER_RAW_BE 0x7FFE8001 -#define DCA_MARKER_RAW_LE 0xFE7F0180 -#define DCA_MARKER_14B_BE 0x1FFFE800 -#define DCA_MARKER_14B_LE 0xFF1F00E8 +#include "avcodec.h" +#include "dcadsp.h" +#include "fmtconvert.h" +#include "get_bits.h" + +#define DCA_PRIM_CHANNELS_MAX (7) +#define DCA_ABITS_MAX (32) /* Should be 28 */ +#define DCA_SUBSUBFRAMES_MAX (4) +#define DCA_SUBFRAMES_MAX (16) +#define DCA_BLOCKS_MAX (16) +#define DCA_LFE_MAX (3) + +#define DCA_PRIM_CHANNELS_MAX (7) +#define DCA_ABITS_MAX (32) /* Should be 28 */ +#define DCA_SUBSUBFRAMES_MAX (4) +#define DCA_SUBFRAMES_MAX (16) +#define DCA_BLOCKS_MAX (16) +#define DCA_LFE_MAX (3) +#define DCA_XLL_FBANDS_MAX (4) +#define DCA_XLL_SEGMENTS_MAX (16) +#define DCA_XLL_CHSETS_MAX (16) +#define DCA_XLL_CHANNELS_MAX (16) +#define DCA_XLL_AORDER_MAX (15) + +/* Arbitrary limit; not sure what the maximum really is, but much larger. */ +#define DCA_XLL_DMIX_NCOEFFS_MAX (18) + +#define DCA_MAX_FRAME_SIZE 16384 +#define DCA_MAX_EXSS_HEADER_SIZE 4096 + +#define DCA_BUFFER_PADDING_SIZE 1024 + +enum DCAExtensionMask { + DCA_EXT_CORE = 0x001, ///< core in core substream + DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream + DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream + DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream + DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream) + DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS + DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS + DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS + DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS + DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS +}; + +typedef struct XllChSetSubHeader { + int channels; ///< number of channels in channel set, at most 16 + int residual_encode; ///< residual channel encoding + int bit_resolution; ///< input sample bit-width + int bit_width; ///< original input sample bit-width + int sampling_frequency; ///< sampling frequency + int samp_freq_interp; ///< sampling frequency interpolation multiplier + int replacement_set; ///< replacement channel set group + int active_replace_set; ///< current channel set is active channel set + int primary_ch_set; + int downmix_coeff_code_embedded; + int downmix_embedded; + int downmix_type; + int hier_chset; ///< hierarchical channel set + int downmix_ncoeffs; + int downmix_coeffs[DCA_XLL_DMIX_NCOEFFS_MAX]; + int ch_mask_enabled; + int ch_mask; + int mapping_coeffs_present; + int num_freq_bands; + + /* m_nOrigChanOrder */ + uint8_t orig_chan_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; + uint8_t orig_chan_order_inv[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; + /* Coefficients for channel pairs (at most 8), m_anPWChPairsCoeffs */ + int8_t pw_ch_pairs_coeffs[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX/2]; + /* m_nCurrHighestLPCOrder */ + uint8_t adapt_order_max[DCA_XLL_FBANDS_MAX]; + /* m_pnAdaptPredOrder */ + uint8_t adapt_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; + /* m_pnFixedPredOrder */ + uint8_t fixed_order[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; + /* m_pnLPCReflCoeffsQInd, unsigned version */ + uint8_t lpc_refl_coeffs_q_ind[DCA_XLL_FBANDS_MAX] + [DCA_XLL_CHANNELS_MAX][DCA_XLL_AORDER_MAX]; + + int lsb_fsize[DCA_XLL_FBANDS_MAX]; + int8_t scalable_lsbs[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; + int8_t bit_width_adj_per_ch[DCA_XLL_FBANDS_MAX][DCA_XLL_CHANNELS_MAX]; +} XllChSetSubHeader; + +typedef struct XllNavi { + GetBitContext gb; // Context for parsing the data segments + unsigned band_size[DCA_XLL_FBANDS_MAX]; + unsigned segment_size[DCA_XLL_FBANDS_MAX][DCA_XLL_SEGMENTS_MAX]; + unsigned chset_size[DCA_XLL_FBANDS_MAX][DCA_XLL_SEGMENTS_MAX][DCA_XLL_CHSETS_MAX]; +} XllNavi; + +typedef struct QMF64_table { + float dct4_coeff[32][32]; + float dct2_coeff[32][32]; + float rcos[32]; + float rsin[32]; +} QMF64_table; + +/* Primary audio coding header */ +typedef struct DCAAudioHeader { + int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count + int vq_start_subband[DCA_PRIM_CHANNELS_MAX]; ///< high frequency vq start subband + int joint_intensity[DCA_PRIM_CHANNELS_MAX]; ///< joint intensity coding index + int transient_huffman[DCA_PRIM_CHANNELS_MAX]; ///< transient mode code book + int scalefactor_huffman[DCA_PRIM_CHANNELS_MAX]; ///< scale factor code book + int bitalloc_huffman[DCA_PRIM_CHANNELS_MAX]; ///< bit allocation quantizer select + int quant_index_huffman[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< quantization index codebook select + uint32_t scalefactor_adj[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< scale factor adjustment + + int subframes; ///< number of subframes + int total_channels; ///< number of channels including extensions + int prim_channels; ///< number of primary audio channels +} DCAAudioHeader; + +typedef struct DCAChan { + DECLARE_ALIGNED(32, int32_t, subband_samples)[DCA_BLOCKS_MAX][DCA_SUBBANDS][SAMPLES_PER_SUBBAND]; + + /* Subband samples history (for ADPCM) */ + DECLARE_ALIGNED(32, int32_t, subband_samples_hist)[DCA_SUBBANDS][4]; + int hist_index; + + /* Half size is sufficient for core decoding, but for 96 kHz data + * we need QMF with 64 subbands and 1024 samples. */ + DECLARE_ALIGNED(32, float, subband_fir_hist)[1024]; + DECLARE_ALIGNED(32, float, subband_fir_noidea)[64]; + + /* Primary audio coding side information */ + int prediction_mode[DCA_SUBBANDS]; ///< prediction mode (ADPCM used or not) + int prediction_vq[DCA_SUBBANDS]; ///< prediction VQ coefs + int bitalloc[DCA_SUBBANDS]; ///< bit allocation index + int transition_mode[DCA_SUBBANDS]; ///< transition mode (transients) + int32_t scale_factor[DCA_SUBBANDS][2];///< scale factors (2 if transient) + int joint_huff; ///< joint subband scale factors codebook + int joint_scale_factor[DCA_SUBBANDS]; ///< joint subband scale factors + + int32_t high_freq_vq[DCA_SUBBANDS]; ///< VQ encoded high frequency subbands +} DCAChan; + -/** DCA-HD specific block starts with this marker. */ -#define DCA_HD_MARKER 0x64582025 +typedef struct DCAContext { + AVClass *class; ///< class for AVOptions + AVCodecContext *avctx; + /* Frame header */ + int frame_type; ///< type of the current frame + int samples_deficit; ///< deficit sample count + int crc_present; ///< crc is present in the bitstream + int sample_blocks; ///< number of PCM sample blocks + int frame_size; ///< primary frame byte size + int amode; ///< audio channels arrangement + int sample_rate; ///< audio sampling rate + int bit_rate; ///< transmission bit rate + int bit_rate_index; ///< transmission bit rate index + + int dynrange; ///< embedded dynamic range flag + int timestamp; ///< embedded time stamp flag + int aux_data; ///< auxiliary data flag + int hdcd; ///< source material is mastered in HDCD + int ext_descr; ///< extension audio descriptor flag + int ext_coding; ///< extended coding flag + int aspf; ///< audio sync word insertion flag + int lfe; ///< low frequency effects flag + int predictor_history; ///< predictor history flag + int header_crc; ///< header crc check bytes + int multirate_inter; ///< multirate interpolator switch + int version; ///< encoder software revision + int copy_history; ///< copy history + int source_pcm_res; ///< source pcm resolution + int front_sum; ///< front sum/difference flag + int surround_sum; ///< surround sum/difference flag + int dialog_norm; ///< dialog normalisation parameter + + /* Primary audio coding header */ + DCAAudioHeader audio_header; + + /* Primary audio coding side information */ + int subsubframes[DCA_SUBFRAMES_MAX]; ///< number of subsubframes + int partial_samples[DCA_SUBFRAMES_MAX]; ///< partial subsubframe samples count + float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients + int dynrange_coef; ///< dynamic range coefficient + + /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1) + * Input: primary audio channels (incl. LFE if present) + * Output: downmix audio channels (up to 4, no LFE) */ + uint8_t core_downmix; ///< embedded downmix coefficients available + uint8_t core_downmix_amode; ///< audio channel arrangement of embedded downmix + uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< embedded downmix coefficients (9-bit codes) + + + float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data + int lfe_scale_factor; + + /* Subband samples history (for ADPCM) */ + DECLARE_ALIGNED(32, float, raXin)[32]; + + DCAChan dca_chan[DCA_PRIM_CHANNELS_MAX]; + + int output; ///< type of output + + float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1]; + float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1]; + uint8_t *extra_channels_buffer; + unsigned int extra_channels_buffer_size; + + uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE]; + int dca_buffer_size; ///< how much data is in the dca_buffer + + const int8_t *channel_order_tab; ///< channel reordering table, lfe and non lfe + GetBitContext gb; + /* Current position in DCA frame */ + int current_subframe; + int current_subsubframe; + + int core_ext_mask; ///< present extensions in the core substream + int exss_ext_mask; ///< Non-core extensions + + /* XCh extension information */ + int xch_present; ///< XCh extension present and valid + int xch_base_channel; ///< index of first (only) channel containing XCH data + int xch_disable; ///< whether the XCh extension should be decoded or not + + /* XLL extension information */ + int xll_disable; + int xll_nch_sets; ///< number of channel sets per frame + int xll_channels; ///< total number of channels (in all channel sets) + int xll_residual_channels; ///< number of residual channels + int xll_segments; ///< number of segments per frame + int xll_log_smpl_in_seg; ///< supposedly this is "nBits4SamplLoci" + int xll_smpl_in_seg; ///< samples in segment per one frequency band for the first channel set + int xll_bits4seg_size; ///< number of bits used to read segment size + int xll_banddata_crc; ///< presence of CRC16 within each frequency band + int xll_scalable_lsb; + int xll_bits4ch_mask; ///< channel position mask + int xll_fixed_lsb_width; + XllChSetSubHeader xll_chsets[DCA_XLL_CHSETS_MAX]; + XllNavi xll_navi; + int *xll_sample_buf; + unsigned int xll_sample_buf_size; + + /* ExSS header parser */ + int static_fields; ///< static fields present + int mix_metadata; ///< mixing metadata present + int num_mix_configs; ///< number of mix out configurations + int mix_config_num_ch[4]; ///< number of channels in each mix out configuration + + int profile; + int one2one_map_chtospkr; + + int debug_flag; ///< used for suppressing repeated error messages output + AVFloatDSPContext fdsp; + FFTContext imdct; + SynthFilterContext synth; + DCADSPContext dcadsp; + QMF64_table *qmf64_table; + FmtConvertContext fmt_conv; +} DCAContext; extern av_export const uint32_t avpriv_dca_sample_rates[16]; @@ -45,4 +296,10 @@ extern av_export const uint32_t avpriv_dca_sample_rates[16]; int ff_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, int max_size); +void ff_dca_exss_parse_header(DCAContext *s); + +int ff_dca_xll_decode_header(DCAContext *s); +int ff_dca_xll_decode_navi(DCAContext *s, int asset_end); +int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame); + #endif /* AVCODEC_DCA_H */ diff --git a/libavcodec/dca_exss.c b/libavcodec/dca_exss.c new file mode 100644 index 0000000..2895e20 --- /dev/null +++ b/libavcodec/dca_exss.c @@ -0,0 +1,368 @@ +/* + * DCA ExSS extension + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/log.h" + +#include "dca.h" +#include "dca_syncwords.h" +#include "get_bits.h" + +/* extensions that reside in core substream */ +#define DCA_CORE_EXTS (DCA_EXT_XCH | DCA_EXT_XXCH | DCA_EXT_X96) + +/* these are unconfirmed but should be mostly correct */ +enum DCAExSSSpeakerMask { + DCA_EXSS_FRONT_CENTER = 0x0001, + DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002, + DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004, + DCA_EXSS_LFE = 0x0008, + DCA_EXSS_REAR_CENTER = 0x0010, + DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020, + DCA_EXSS_REAR_LEFT_RIGHT = 0x0040, + DCA_EXSS_FRONT_HIGH_CENTER = 0x0080, + DCA_EXSS_OVERHEAD = 0x0100, + DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200, + DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400, + DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800, + DCA_EXSS_LFE2 = 0x1000, + DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000, + DCA_EXSS_REAR_HIGH_CENTER = 0x4000, + DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000, +}; + +/** + * Return the number of channels in an ExSS speaker mask (HD) + */ +static int dca_exss_mask2count(int mask) +{ + /* count bits that mean speaker pairs twice */ + return av_popcount(mask) + + av_popcount(mask & (DCA_EXSS_CENTER_LEFT_RIGHT | + DCA_EXSS_FRONT_LEFT_RIGHT | + DCA_EXSS_FRONT_HIGH_LEFT_RIGHT | + DCA_EXSS_WIDE_LEFT_RIGHT | + DCA_EXSS_SIDE_LEFT_RIGHT | + DCA_EXSS_SIDE_HIGH_LEFT_RIGHT | + DCA_EXSS_SIDE_REAR_LEFT_RIGHT | + DCA_EXSS_REAR_LEFT_RIGHT | + DCA_EXSS_REAR_HIGH_LEFT_RIGHT)); +} + +/** + * Skip mixing coefficients of a single mix out configuration (HD) + */ +static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch) +{ + int i; + + for (i = 0; i < channels; i++) { + int mix_map_mask = get_bits(gb, out_ch); + int num_coeffs = av_popcount(mix_map_mask); + skip_bits_long(gb, num_coeffs * 6); + } +} + +/** + * Parse extension substream asset header (HD) + */ +static int dca_exss_parse_asset_header(DCAContext *s) +{ + int header_pos = get_bits_count(&s->gb); + int header_size; + int channels = 0; + int embedded_stereo = 0; + int embedded_6ch = 0; + int drc_code_present; + int extensions_mask = 0; + int i, j; + + if (get_bits_left(&s->gb) < 16) + return AVERROR_INVALIDDATA; + + /* We will parse just enough to get to the extensions bitmask with which + * we can set the profile value. */ + + header_size = get_bits(&s->gb, 9) + 1; + skip_bits(&s->gb, 3); // asset index + + if (s->static_fields) { + if (get_bits1(&s->gb)) + skip_bits(&s->gb, 4); // asset type descriptor + if (get_bits1(&s->gb)) + skip_bits_long(&s->gb, 24); // language descriptor + + if (get_bits1(&s->gb)) { + /* How can one fit 1024 bytes of text here if the maximum value + * for the asset header size field above was 512 bytes? */ + int text_length = get_bits(&s->gb, 10) + 1; + if (get_bits_left(&s->gb) < text_length * 8) + return AVERROR_INVALIDDATA; + skip_bits_long(&s->gb, text_length * 8); // info text + } + + skip_bits(&s->gb, 5); // bit resolution - 1 + skip_bits(&s->gb, 4); // max sample rate code + channels = get_bits(&s->gb, 8) + 1; + + s->one2one_map_chtospkr = get_bits1(&s->gb); + if (s->one2one_map_chtospkr) { + int spkr_remap_sets; + int spkr_mask_size = 16; + int num_spkrs[7]; + + if (channels > 2) + embedded_stereo = get_bits1(&s->gb); + if (channels > 6) + embedded_6ch = get_bits1(&s->gb); + + if (get_bits1(&s->gb)) { + spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2; + skip_bits(&s->gb, spkr_mask_size); // spkr activity mask + } + + spkr_remap_sets = get_bits(&s->gb, 3); + + for (i = 0; i < spkr_remap_sets; i++) { + /* std layout mask for each remap set */ + num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size)); + } + + for (i = 0; i < spkr_remap_sets; i++) { + int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1; + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + for (j = 0; j < num_spkrs[i]; j++) { + int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps); + int num_dec_ch = av_popcount(remap_dec_ch_mask); + skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes + } + } + } else { + skip_bits(&s->gb, 3); // representation type + } + } + + drc_code_present = get_bits1(&s->gb); + if (drc_code_present) + get_bits(&s->gb, 8); // drc code + + if (get_bits1(&s->gb)) + skip_bits(&s->gb, 5); // dialog normalization code + + if (drc_code_present && embedded_stereo) + get_bits(&s->gb, 8); // drc stereo code + + if (s->mix_metadata && get_bits1(&s->gb)) { + skip_bits(&s->gb, 1); // external mix + skip_bits(&s->gb, 6); // post mix gain code + + if (get_bits(&s->gb, 2) != 3) // mixer drc code + skip_bits(&s->gb, 3); // drc limit + else + skip_bits(&s->gb, 8); // custom drc code + + if (get_bits1(&s->gb)) // channel specific scaling + for (i = 0; i < s->num_mix_configs; i++) + skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes + else + skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes + + for (i = 0; i < s->num_mix_configs; i++) { + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]); + if (embedded_6ch) + dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]); + if (embedded_stereo) + dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]); + } + } + + switch (get_bits(&s->gb, 2)) { + case 0: + extensions_mask = get_bits(&s->gb, 12); + break; + case 1: + extensions_mask = DCA_EXT_EXSS_XLL; + break; + case 2: + extensions_mask = DCA_EXT_EXSS_LBR; + break; + case 3: + extensions_mask = 0; /* aux coding */ + break; + } + + /* not parsed further, we were only interested in the extensions mask */ + + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + if (get_bits_count(&s->gb) - header_pos > header_size * 8) { + av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n"); + return AVERROR_INVALIDDATA; + } + skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb)); + + if (extensions_mask & DCA_EXT_EXSS_XLL) + s->profile = FF_PROFILE_DTS_HD_MA; + else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 | + DCA_EXT_EXSS_XXCH)) + s->profile = FF_PROFILE_DTS_HD_HRA; + + if (!(extensions_mask & DCA_EXT_CORE)) + av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n"); + if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask) + av_log(s->avctx, AV_LOG_WARNING, + "DTS extensions detection mismatch (%d, %d)\n", + extensions_mask & DCA_CORE_EXTS, s->core_ext_mask); + + return 0; +} + +/** + * Parse extension substream header (HD) + */ +void ff_dca_exss_parse_header(DCAContext *s) +{ + int asset_size[8]; + int ss_index; + int blownup; + int num_audiop = 1; + int num_assets = 1; + int active_ss_mask[8]; + int i, j; + int start_pos; + int hdrsize; + uint32_t mkr; + + if (get_bits_left(&s->gb) < 52) + return; + + start_pos = get_bits_count(&s->gb) - 32; + + skip_bits(&s->gb, 8); // user data + ss_index = get_bits(&s->gb, 2); + + blownup = get_bits1(&s->gb); + hdrsize = get_bits(&s->gb, 8 + 4 * blownup) + 1; // header_size + skip_bits(&s->gb, 16 + 4 * blownup); // hd_size + + s->static_fields = get_bits1(&s->gb); + if (s->static_fields) { + skip_bits(&s->gb, 2); // reference clock code + skip_bits(&s->gb, 3); // frame duration code + + if (get_bits1(&s->gb)) + skip_bits_long(&s->gb, 36); // timestamp + + /* a single stream can contain multiple audio assets that can be + * combined to form multiple audio presentations */ + + num_audiop = get_bits(&s->gb, 3) + 1; + if (num_audiop > 1) { + avpriv_request_sample(s->avctx, + "Multiple DTS-HD audio presentations"); + /* ignore such streams for now */ + return; + } + + num_assets = get_bits(&s->gb, 3) + 1; + if (num_assets > 1) { + avpriv_request_sample(s->avctx, "Multiple DTS-HD audio assets"); + /* ignore such streams for now */ + return; + } + + for (i = 0; i < num_audiop; i++) + active_ss_mask[i] = get_bits(&s->gb, ss_index + 1); + + for (i = 0; i < num_audiop; i++) + for (j = 0; j <= ss_index; j++) + if (active_ss_mask[i] & (1 << j)) + skip_bits(&s->gb, 8); // active asset mask + + s->mix_metadata = get_bits1(&s->gb); + if (s->mix_metadata) { + int mix_out_mask_size; + + skip_bits(&s->gb, 2); // adjustment level + mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2; + s->num_mix_configs = get_bits(&s->gb, 2) + 1; + + for (i = 0; i < s->num_mix_configs; i++) { + int mix_out_mask = get_bits(&s->gb, mix_out_mask_size); + s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask); + } + } + } + + for (i = 0; i < num_assets; i++) + asset_size[i] = get_bits_long(&s->gb, 16 + 4 * blownup) + 1; + + for (i = 0; i < num_assets; i++) { + if (dca_exss_parse_asset_header(s)) + return; + } + + if (num_assets > 0) { + j = get_bits_count(&s->gb); + if (start_pos + hdrsize * 8 > j) + skip_bits_long(&s->gb, start_pos + hdrsize * 8 - j); + + for (i = 0; i < num_assets; i++) { + int end_pos; + start_pos = get_bits_count(&s->gb); + end_pos = start_pos + asset_size[i] * 8; + mkr = get_bits_long(&s->gb, 32); + + /* parse extensions that we know about */ + switch (mkr) { + case DCA_SYNCWORD_XLL: + if (s->xll_disable) { + av_log(s->avctx, AV_LOG_DEBUG, + "DTS-XLL: ignoring XLL extension\n"); + break; + } + av_log(s->avctx, AV_LOG_DEBUG, + "DTS-XLL: decoding XLL extension\n"); + if (ff_dca_xll_decode_header(s) == 0 && + ff_dca_xll_decode_navi(s, end_pos) == 0) + s->exss_ext_mask |= DCA_EXT_EXSS_XLL; + break; + case DCA_SYNCWORD_XBR: + case DCA_SYNCWORD_XXCH: + default: + av_log(s->avctx, AV_LOG_VERBOSE, + "DTS-ExSS: unknown marker = 0x%08"PRIx32"\n", mkr); + } + + /* skip to end of block */ + j = get_bits_count(&s->gb); + if (j > end_pos) + av_log(s->avctx, AV_LOG_ERROR, + "DTS-ExSS: Processed asset too long.\n"); + if (j < end_pos) + skip_bits_long(&s->gb, end_pos - j); + } + } +} diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index e233f50..c33cc9a 100644 --- a/libavcodec/dca_parser.c +++ b/libavcodec/dca_parser.c @@ -22,49 +22,58 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "parser.h" #include "dca.h" +#include "dca_syncwords.h" #include "get_bits.h" +#include "parser.h" typedef struct DCAParseContext { ParseContext pc; uint32_t lastmarker; int size; int framesize; - int hd_pos; } DCAParseContext; -#define IS_MARKER(state, i, buf, buf_size) \ - ((state == DCA_MARKER_14B_LE && (i < buf_size-2) && (buf[i+1] & 0xF0) == 0xF0 && buf[i+2] == 0x07) \ - || (state == DCA_MARKER_14B_BE && (i < buf_size-2) && buf[i+1] == 0x07 && (buf[i+2] & 0xF0) == 0xF0) \ - || state == DCA_MARKER_RAW_LE || state == DCA_MARKER_RAW_BE) +#define IS_CORE_MARKER(state) \ + (((state & 0xFFFFFFFFF0FF) == (((uint64_t)DCA_SYNCWORD_CORE_14B_LE << 16) | 0xF007)) || \ + ((state & 0xFFFFFFFFFFF0) == (((uint64_t)DCA_SYNCWORD_CORE_14B_BE << 16) | 0x07F0)) || \ + ((state & 0xFFFFFFFF00FC) == (((uint64_t)DCA_SYNCWORD_CORE_LE << 16) | 0x00FC)) || \ + ((state & 0xFFFFFFFFFC00) == (((uint64_t)DCA_SYNCWORD_CORE_BE << 16) | 0xFC00))) + +#define IS_EXSS_MARKER(state) ((state & 0xFFFFFFFF) == DCA_SYNCWORD_SUBSTREAM) + +#define IS_MARKER(state) (IS_CORE_MARKER(state) || IS_EXSS_MARKER(state)) + +#define CORE_MARKER(state) ((state >> 16) & 0xFFFFFFFF) +#define EXSS_MARKER(state) (state & 0xFFFFFFFF) /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ -static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf, +static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf, int buf_size) { int start_found, i; - uint32_t state; + uint64_t state; ParseContext *pc = &pc1->pc; start_found = pc->frame_start_found; - state = pc->state; + state = pc->state64; i = 0; if (!start_found) { for (i = 0; i < buf_size; i++) { state = (state << 8) | buf[i]; - if (IS_MARKER(state, i, buf, buf_size)) { - if (pc1->lastmarker && state == pc1->lastmarker) { - start_found = 1; - i++; - break; - } else if (!pc1->lastmarker) { + if (IS_MARKER(state)) { + if (!pc1->lastmarker || + pc1->lastmarker == CORE_MARKER(state) || + pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM) { start_found = 1; - pc1->lastmarker = state; + if (IS_EXSS_MARKER(state)) + pc1->lastmarker = EXSS_MARKER(state); + else + pc1->lastmarker = CORE_MARKER(state); i++; break; } @@ -75,24 +84,24 @@ static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf, for (; i < buf_size; i++) { pc1->size++; state = (state << 8) | buf[i]; - if (state == DCA_HD_MARKER && !pc1->hd_pos) - pc1->hd_pos = pc1->size; - if (state == pc1->lastmarker && IS_MARKER(state, i, buf, buf_size)) { - if(pc1->framesize > pc1->size) + if (IS_MARKER(state) && + (pc1->lastmarker == CORE_MARKER(state) || + pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) { + if (pc1->framesize > pc1->size) continue; pc->frame_start_found = 0; - pc->state = -1; - pc1->size = 0; - return i - 3; + pc->state64 = -1; + pc1->size = 0; + return IS_EXSS_MARKER(state) ? i - 3 : i - 5; } } } pc->frame_start_found = start_found; - pc->state = state; + pc->state64 = state; return END_NOT_FOUND; } -static av_cold int dca_parse_init(AVCodecParserContext * s) +static av_cold int dca_parse_init(AVCodecParserContext *s) { DCAParseContext *pc1 = s->priv_data; @@ -104,7 +113,7 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, int *sample_rate, int *framesize) { GetBitContext gb; - uint8_t hdr[12 + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 }; + uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 }; int ret, sample_blocks, sr_code; if (buf_size < 12) @@ -126,7 +135,7 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, return AVERROR_INVALIDDATA; skip_bits(&gb, 6); - sr_code = get_bits(&gb, 4); + sr_code = get_bits(&gb, 4); *sample_rate = avpriv_dca_sample_rates[sr_code]; if (*sample_rate == 0) return AVERROR_INVALIDDATA; @@ -134,10 +143,9 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, return 0; } -static int dca_parse(AVCodecParserContext * s, - AVCodecContext * avctx, - const uint8_t ** poutbuf, int *poutbuf_size, - const uint8_t * buf, int buf_size) +static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) { DCAParseContext *pc1 = s->priv_data; ParseContext *pc = &pc1->pc; @@ -149,7 +157,7 @@ static int dca_parse(AVCodecParserContext * s, next = dca_find_frame_end(pc1, buf, buf_size); if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { - *poutbuf = NULL; + *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } @@ -157,12 +165,12 @@ static int dca_parse(AVCodecParserContext * s, /* read the duration and sample rate from the frame header */ if (!dca_parse_params(buf, buf_size, &duration, &sample_rate, &pc1->framesize)) { - s->duration = duration; + s->duration = duration; avctx->sample_rate = sample_rate; } else s->duration = 0; - *poutbuf = buf; + *poutbuf = buf; *poutbuf_size = buf_size; return next; } diff --git a/libavcodec/dca_syncwords.h b/libavcodec/dca_syncwords.h new file mode 100644 index 0000000..07b60e0 --- /dev/null +++ b/libavcodec/dca_syncwords.h @@ -0,0 +1,37 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCA_SYNCWORDS_H +#define AVCODEC_DCA_SYNCWORDS_H + +enum DCASyncwords { + DCA_SYNCWORD_CORE_BE = 0x7FFE8001U, + DCA_SYNCWORD_CORE_LE = 0xFE7F0180U, + DCA_SYNCWORD_CORE_14B_BE = 0x1FFFE800U, + DCA_SYNCWORD_CORE_14B_LE = 0xFF1F00E8U, + DCA_SYNCWORD_XCH = 0x5A5A5A5AU, + DCA_SYNCWORD_XXCH = 0x47004A03U, + DCA_SYNCWORD_X96 = 0x1D95F262U, + DCA_SYNCWORD_XBR = 0x655E315EU, + DCA_SYNCWORD_LBR = 0x0A801921U, + DCA_SYNCWORD_XLL = 0x41A29547U, + DCA_SYNCWORD_SUBSTREAM = 0x64582025U, + DCA_SYNCWORD_SUBSTREAM_CORE = 0x02B09261U, +}; + +#endif /* AVCODEC_DCA_SYNCWORDS_H */ diff --git a/libavcodec/dca_xll.c b/libavcodec/dca_xll.c new file mode 100644 index 0000000..5a558b8 --- /dev/null +++ b/libavcodec/dca_xll.c @@ -0,0 +1,747 @@ +/* + * DCA XLL extension + * + * Copyright (C) 2012 Paul B Mahol + * Copyright (C) 2014 Niels Möller + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" + +#include "avcodec.h" +#include "dca.h" +#include "dcadata.h" +#include "get_bits.h" +#include "unary.h" + +/* Sign as bit 0 */ +static inline int get_bits_sm(GetBitContext *s, unsigned n) +{ + int x = get_bits(s, n); + if (x & 1) + return -(x >> 1) - 1; + else + return x >> 1; +} + +/* Return -1 on error. */ +static int32_t get_dmix_coeff(DCAContext *s, int inverse) +{ + unsigned code = get_bits(&s->gb, 9); + int32_t sign = (int32_t) (code >> 8) - 1; + unsigned idx = code & 0xff; + int inv_offset = FF_DCA_DMIXTABLE_SIZE -FF_DCA_INV_DMIXTABLE_SIZE; + if (idx >= FF_DCA_DMIXTABLE_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, + "XLL: Invalid channel set downmix code %x\n", code); + return -1; + } else if (!inverse) { + return (ff_dca_dmixtable[idx] ^ sign) - sign; + } else if (idx < inv_offset) { + av_log(s->avctx, AV_LOG_ERROR, + "XLL: Invalid channel set inverse downmix code %x\n", code); + return -1; + } else { + return (ff_dca_inv_dmixtable[idx - inv_offset] ^ sign) - sign; + } +} + +static int32_t dca_get_dmix_coeff(DCAContext *s) +{ + return get_dmix_coeff(s, 0); +} + +static int32_t dca_get_inv_dmix_coeff(DCAContext *s) +{ + return get_dmix_coeff(s, 1); +} + +/* parse XLL header */ +int ff_dca_xll_decode_header(DCAContext *s) +{ + int hdr_pos, hdr_size; + av_unused int version, frame_size; + int i, chset_index; + + /* get bit position of sync header */ + hdr_pos = get_bits_count(&s->gb) - 32; + + version = get_bits(&s->gb, 4) + 1; + hdr_size = get_bits(&s->gb, 8) + 1; + + frame_size = get_bits_long(&s->gb, get_bits(&s->gb, 5) + 1) + 1; + + s->xll_channels = + s->xll_residual_channels = 0; + s->xll_nch_sets = get_bits(&s->gb, 4) + 1; + s->xll_segments = 1 << get_bits(&s->gb, 4); + s->xll_log_smpl_in_seg = get_bits(&s->gb, 4); + s->xll_smpl_in_seg = 1 << s->xll_log_smpl_in_seg; + s->xll_bits4seg_size = get_bits(&s->gb, 5) + 1; + s->xll_banddata_crc = get_bits(&s->gb, 2); + s->xll_scalable_lsb = get_bits1(&s->gb); + s->xll_bits4ch_mask = get_bits(&s->gb, 5) + 1; + + if (s->xll_scalable_lsb) { + s->xll_fixed_lsb_width = get_bits(&s->gb, 4); + if (s->xll_fixed_lsb_width) + av_log(s->avctx, AV_LOG_WARNING, + "XLL: fixed lsb width = %d, non-zero not supported.\n", + s->xll_fixed_lsb_width); + } + /* skip to the end of the common header */ + i = get_bits_count(&s->gb); + if (hdr_pos + hdr_size * 8 > i) + skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i); + + for (chset_index = 0; chset_index < s->xll_nch_sets; chset_index++) { + XllChSetSubHeader *chset = &s->xll_chsets[chset_index]; + hdr_pos = get_bits_count(&s->gb); + hdr_size = get_bits(&s->gb, 10) + 1; + + chset->channels = get_bits(&s->gb, 4) + 1; + chset->residual_encode = get_bits(&s->gb, chset->channels); + chset->bit_resolution = get_bits(&s->gb, 5) + 1; + chset->bit_width = get_bits(&s->gb, 5) + 1; + chset->sampling_frequency = ff_dca_sampling_freqs[get_bits(&s->gb, 4)]; + chset->samp_freq_interp = get_bits(&s->gb, 2); + chset->replacement_set = get_bits(&s->gb, 2); + if (chset->replacement_set) + chset->active_replace_set = get_bits(&s->gb, 1); + + if (s->one2one_map_chtospkr) { + chset->primary_ch_set = get_bits(&s->gb, 1); + chset->downmix_coeff_code_embedded = get_bits(&s->gb, 1); + if (chset->downmix_coeff_code_embedded) { + chset->downmix_embedded = get_bits(&s->gb, 1); + if (chset->primary_ch_set) { + chset->downmix_type = get_bits(&s->gb, 3); + if (chset->downmix_type > 6) { + av_log(s->avctx, AV_LOG_ERROR, + "XLL: Invalid channel set downmix type\n"); + return AVERROR_INVALIDDATA; + } + } + } + chset->hier_chset = get_bits(&s->gb, 1); + + if (chset->downmix_coeff_code_embedded) { + /* nDownmixCoeffs is specified as N * M. For a primary + * channel set, it appears that N = number of + * channels, and M is the number of downmix channels. + * + * For a non-primary channel set, N is specified as + * number of channels + 1, and M is derived from the + * channel set hierarchy, and at least in simple cases + * M is the number of channels in preceding channel + * sets. */ + if (chset->primary_ch_set) { + static const char dmix_table[7] = { 1, 2, 2, 3, 3, 4, 4 }; + chset->downmix_ncoeffs = chset->channels * dmix_table[chset->downmix_type]; + } else + chset->downmix_ncoeffs = (chset->channels + 1) * s->xll_channels; + + if (chset->downmix_ncoeffs > DCA_XLL_DMIX_NCOEFFS_MAX) { + avpriv_request_sample(s->avctx, + "XLL: More than %d downmix coefficients", + DCA_XLL_DMIX_NCOEFFS_MAX); + return AVERROR_PATCHWELCOME; + } else if (chset->primary_ch_set) { + for (i = 0; i < chset->downmix_ncoeffs; i++) + if ((chset->downmix_coeffs[i] = dca_get_dmix_coeff(s)) == -1) + return AVERROR_INVALIDDATA; + } else { + unsigned c, r; + for (c = 0, i = 0; c < s->xll_channels; c++, i += chset->channels + 1) { + if ((chset->downmix_coeffs[i] = dca_get_inv_dmix_coeff(s)) == -1) + return AVERROR_INVALIDDATA; + for (r = 1; r <= chset->channels; r++) { + int32_t coeff = dca_get_dmix_coeff(s); + if (coeff == -1) + return AVERROR_INVALIDDATA; + chset->downmix_coeffs[i + r] = + (chset->downmix_coeffs[i] * (int64_t) coeff + (1 << 15)) >> 16; + } + } + } + } + chset->ch_mask_enabled = get_bits(&s->gb, 1); + if (chset->ch_mask_enabled) + chset->ch_mask = get_bits(&s->gb, s->xll_bits4ch_mask); + else + /* Skip speaker configuration bits */ + skip_bits_long(&s->gb, 25 * chset->channels); + } else { + chset->primary_ch_set = 1; + chset->downmix_coeff_code_embedded = 0; + /* Spec: NumChHierChSet = 0, NumDwnMixCodeCoeffs = 0, whatever that means. */ + chset->mapping_coeffs_present = get_bits(&s->gb, 1); + if (chset->mapping_coeffs_present) { + avpriv_report_missing_feature(s->avctx, "XLL: mapping coefficients"); + return AVERROR_PATCHWELCOME; + } + } + if (chset->sampling_frequency > 96000) + chset->num_freq_bands = 2 * (1 + get_bits(&s->gb, 1)); + else + chset->num_freq_bands = 1; + + if (chset->num_freq_bands > 1) { + avpriv_report_missing_feature(s->avctx, "XLL: num_freq_bands > 1"); + return AVERROR_PATCHWELCOME; + } + + if (get_bits(&s->gb, 1)) { /* pw_ch_decor_enabled */ + int bits = av_ceil_log2(chset->channels); + for (i = 0; i < chset->channels; i++) { + unsigned j = get_bits(&s->gb, bits); + if (j >= chset->channels) { + av_log(s->avctx, AV_LOG_ERROR, + "Original channel order value %u too large, only %d channels.\n", + j, chset->channels); + return AVERROR_INVALIDDATA; + } + chset->orig_chan_order[0][i] = j; + chset->orig_chan_order_inv[0][j] = i; + } + for (i = 0; i < chset->channels / 2; i++) { + if (get_bits(&s->gb, 1)) /* bChPFlag */ + chset->pw_ch_pairs_coeffs[0][i] = get_bits_sm(&s->gb, 7); + else + chset->pw_ch_pairs_coeffs[0][i] = 0; + } + } else { + for (i = 0; i < chset->channels; i++) + chset->orig_chan_order[0][i] = + chset->orig_chan_order_inv[0][i] = i; + for (i = 0; i < chset->channels / 2; i++) + chset->pw_ch_pairs_coeffs[0][i] = 0; + } + /* Adaptive prediction order */ + chset->adapt_order_max[0] = 0; + for (i = 0; i < chset->channels; i++) { + chset->adapt_order[0][i] = get_bits(&s->gb, 4); + if (chset->adapt_order_max[0] < chset->adapt_order[0][i]) + chset->adapt_order_max[0] = chset->adapt_order[0][i]; + } + /* Fixed prediction order, used in case the adaptive order + * above is zero */ + for (i = 0; i < chset->channels; i++) + chset->fixed_order[0][i] = + chset->adapt_order[0][i] ? 0 : get_bits(&s->gb, 2); + + for (i = 0; i < chset->channels; i++) { + unsigned j; + for (j = 0; j < chset->adapt_order[0][i]; j++) + chset->lpc_refl_coeffs_q_ind[0][i][j] = get_bits(&s->gb, 8); + } + + if (s->xll_scalable_lsb) { + chset->lsb_fsize[0] = get_bits(&s->gb, s->xll_bits4seg_size); + + for (i = 0; i < chset->channels; i++) + chset->scalable_lsbs[0][i] = get_bits(&s->gb, 4); + for (i = 0; i < chset->channels; i++) + chset->bit_width_adj_per_ch[0][i] = get_bits(&s->gb, 4); + } else { + memset(chset->scalable_lsbs[0], 0, + chset->channels * sizeof(chset->scalable_lsbs[0][0])); + memset(chset->bit_width_adj_per_ch[0], 0, + chset->channels * sizeof(chset->bit_width_adj_per_ch[0][0])); + } + + s->xll_channels += chset->channels; + s->xll_residual_channels += chset->channels - + av_popcount(chset->residual_encode); + + /* FIXME: Parse header data for extra frequency bands. */ + + /* Skip to end of channel set sub header. */ + i = get_bits_count(&s->gb); + if (hdr_pos + 8 * hdr_size < i) { + av_log(s->avctx, AV_LOG_ERROR, + "chset header too large, %d bits, should be <= %d bits\n", + i - hdr_pos, 8 * hdr_size); + return AVERROR_INVALIDDATA; + } + if (hdr_pos + 8 * hdr_size > i) + skip_bits_long(&s->gb, hdr_pos + 8 * hdr_size - i); + } + return 0; +} + +/* parse XLL navigation table */ +int ff_dca_xll_decode_navi(DCAContext *s, int asset_end) +{ + int nbands, band, chset, seg, data_start; + + /* FIXME: Supports only a single frequency band */ + nbands = 1; + + for (band = 0; band < nbands; band++) { + s->xll_navi.band_size[band] = 0; + for (seg = 0; seg < s->xll_segments; seg++) { + /* Note: The spec, ETSI TS 102 114 V1.4.1 (2012-09), says + * we should read a base value for segment_size from the + * stream, before reading the sizes of the channel sets. + * But that's apparently incorrect. */ + s->xll_navi.segment_size[band][seg] = 0; + + for (chset = 0; chset < s->xll_nch_sets; chset++) + if (band < s->xll_chsets[chset].num_freq_bands) { + s->xll_navi.chset_size[band][seg][chset] = + get_bits(&s->gb, s->xll_bits4seg_size) + 1; + s->xll_navi.segment_size[band][seg] += + s->xll_navi.chset_size[band][seg][chset]; + } + s->xll_navi.band_size[band] += s->xll_navi.segment_size[band][seg]; + } + } + /* Align to 8 bits and skip 16-bit CRC. */ + skip_bits_long(&s->gb, 16 + ((-get_bits_count(&s->gb)) & 7)); + + data_start = get_bits_count(&s->gb); + if (data_start + 8 * s->xll_navi.band_size[0] > asset_end) { + av_log(s->avctx, AV_LOG_ERROR, + "XLL: Data in NAVI table exceeds containing asset\n" + "start: %d (bit), size %u (bytes), end %d (bit), error %u\n", + data_start, s->xll_navi.band_size[0], asset_end, + data_start + 8 * s->xll_navi.band_size[0] - asset_end); + return AVERROR_INVALIDDATA; + } + init_get_bits(&s->xll_navi.gb, s->gb.buffer + data_start / 8, + 8 * s->xll_navi.band_size[0]); + return 0; +} + +static void dca_xll_inv_adapt_pred(int *samples, int nsamples, unsigned order, + const int *prev, const uint8_t *q_ind) +{ + static const uint16_t table[0x81] = { + 0, 3070, 5110, 7140, 9156, 11154, 13132, 15085, + 17010, 18904, 20764, 22588, 24373, 26117, 27818, 29474, + 31085, 32648, 34164, 35631, 37049, 38418, 39738, 41008, + 42230, 43404, 44530, 45609, 46642, 47630, 48575, 49477, + 50337, 51157, 51937, 52681, 53387, 54059, 54697, 55302, + 55876, 56421, 56937, 57426, 57888, 58326, 58741, 59132, + 59502, 59852, 60182, 60494, 60789, 61066, 61328, 61576, + 61809, 62029, 62236, 62431, 62615, 62788, 62951, 63105, + 63250, 63386, 63514, 63635, 63749, 63855, 63956, 64051, + 64140, 64224, 64302, 64376, 64446, 64512, 64573, 64631, + 64686, 64737, 64785, 64830, 64873, 64913, 64950, 64986, + 65019, 65050, 65079, 65107, 65133, 65157, 65180, 65202, + 65222, 65241, 65259, 65275, 65291, 65306, 65320, 65333, + 65345, 65357, 65368, 65378, 65387, 65396, 65405, 65413, + 65420, 65427, 65434, 65440, 65446, 65451, 65456, 65461, + 65466, 65470, 65474, 65478, 65481, 65485, 65488, 65491, + 65535, /* Final value is for the -128 corner case, see below. */ + }; + int c[DCA_XLL_AORDER_MAX]; + int64_t s; + unsigned i, j; + + for (i = 0; i < order; i++) { + if (q_ind[i] & 1) + /* The index value 0xff corresponds to a lookup of entry 0x80 in + * the table, and no value is provided in the specification. */ + c[i] = -table[(q_ind[i] >> 1) + 1]; + else + c[i] = table[q_ind[i] >> 1]; + } + /* The description in the spec is a bit convoluted. We can convert + * the reflected values to direct values in place, using a + * sequence of reflections operating on two values. */ + for (i = 1; i < order; i++) { + /* i = 1: scale c[0] + * i = 2: reflect c[0] <-> c[1] + * i = 3: scale c[1], reflect c[0] <-> c[2] + * i = 4: reflect c[0] <-> c[3] reflect c[1] <-> c[2] + * ... */ + if (i & 1) + c[i / 2] += ((int64_t) c[i] * c[i / 2] + 0x8000) >> 16; + for (j = 0; j < i / 2; j++) { + int r0 = c[j]; + int r1 = c[i - j - 1]; + c[j] += ((int64_t) c[i] * r1 + 0x8000) >> 16; + c[i - j - 1] += ((int64_t) c[i] * r0 + 0x8000) >> 16; + } + } + /* Apply predictor. */ + /* NOTE: Processing samples in this order means that the + * predictor is applied to the newly reconstructed samples. */ + if (prev) { + for (i = 0; i < order; i++) { + for (j = s = 0; j < i; j++) + s += (int64_t) c[j] * samples[i - 1 - j]; + for (; j < order; j++) + s += (int64_t) c[j] * prev[DCA_XLL_AORDER_MAX + i - 1 - j]; + + samples[i] -= av_clip((s + 0x8000) >> 16, -0x1000000, 0xffffff); + } + } + for (i = order; i < nsamples; i++) { + for (j = s = 0; j < order; j++) + s += (int64_t) c[j] * samples[i - 1 - j]; + + /* NOTE: Equations seem to imply addition, while the + * pseudocode seems to use subtraction.*/ + samples[i] -= av_clip((s + 0x8000) >> 16, -0x1000000, 0xffffff); + } +} + +int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame) +{ + /* FIXME: Decodes only the first frequency band. */ + int seg, chset_i; + + /* Coding parameters for each channel set. */ + struct coding_params { + int seg_type; + int rice_code_flag[16]; + int pancAuxABIT[16]; + int pancABIT0[16]; /* Not sure what this is */ + int pancABIT[16]; /* Not sure what this is */ + int nSamplPart0[16]; + } param_state[16]; + + GetBitContext *gb = &s->xll_navi.gb; + int *history; + + /* Layout: First the sample buffer for one segment per channel, + * followed by history buffers of DCA_XLL_AORDER_MAX samples for + * each channel. */ + av_fast_malloc(&s->xll_sample_buf, &s->xll_sample_buf_size, + (s->xll_smpl_in_seg + DCA_XLL_AORDER_MAX) * + s->xll_channels * sizeof(*s->xll_sample_buf)); + if (!s->xll_sample_buf) + return AVERROR(ENOMEM); + + history = s->xll_sample_buf + s->xll_smpl_in_seg * s->xll_channels; + + for (seg = 0; seg < s->xll_segments; seg++) { + unsigned in_channel; + + for (chset_i = in_channel = 0; chset_i < s->xll_nch_sets; chset_i++) { + /* The spec isn't very explicit, but I think the NAVI sizes are in bytes. */ + int end_pos = get_bits_count(gb) + + 8 * s->xll_navi.chset_size[0][seg][chset_i]; + int i, j; + struct coding_params *params = ¶m_state[chset_i]; + /* I think this flag means that we should keep seg_type and + * other parameters from the previous segment. */ + int use_seg_state_code_param; + XllChSetSubHeader *chset = &s->xll_chsets[chset_i]; + if (in_channel >= s->avctx->channels) + /* FIXME: Could go directly to next segment */ + goto next_chset; + + if (s->avctx->sample_rate != chset->sampling_frequency) { + av_log(s->avctx, AV_LOG_WARNING, + "XLL: unexpected chset sample rate %d, expected %d\n", + chset->sampling_frequency, s->avctx->sample_rate); + goto next_chset; + } + if (seg != 0) + use_seg_state_code_param = get_bits(gb, 1); + else + use_seg_state_code_param = 0; + + if (!use_seg_state_code_param) { + int num_param_sets, i; + unsigned bits4ABIT; + + params->seg_type = get_bits(gb, 1); + num_param_sets = params->seg_type ? 1 : chset->channels; + + if (chset->bit_width > 16) { + bits4ABIT = 5; + } else { + if (chset->bit_width > 8) + bits4ABIT = 4; + else + bits4ABIT = 3; + if (s->xll_nch_sets > 1) + bits4ABIT++; + } + + for (i = 0; i < num_param_sets; i++) { + params->rice_code_flag[i] = get_bits(gb, 1); + if (!params->seg_type && params->rice_code_flag[i] && get_bits(gb, 1)) + params->pancAuxABIT[i] = get_bits(gb, bits4ABIT) + 1; + else + params->pancAuxABIT[i] = 0; + } + + for (i = 0; i < num_param_sets; i++) { + if (!seg) { + /* Parameters for part 1 */ + params->pancABIT0[i] = get_bits(gb, bits4ABIT); + if (params->rice_code_flag[i] == 0 && params->pancABIT0[i] > 0) + /* For linear code */ + params->pancABIT0[i]++; + + /* NOTE: In the spec, not indexed by band??? */ + if (params->seg_type == 0) + params->nSamplPart0[i] = chset->adapt_order[0][i]; + else + params->nSamplPart0[i] = chset->adapt_order_max[0]; + } else + params->nSamplPart0[i] = 0; + + /* Parameters for part 2 */ + params->pancABIT[i] = get_bits(gb, bits4ABIT); + if (params->rice_code_flag[i] == 0 && params->pancABIT[i] > 0) + /* For linear code */ + params->pancABIT[i]++; + } + } + for (i = 0; i < chset->channels; i++) { + int param_index = params->seg_type ? 0 : i; + int part0 = params->nSamplPart0[param_index]; + int bits = part0 ? params->pancABIT0[param_index] : 0; + int *sample_buf = s->xll_sample_buf + + (in_channel + i) * s->xll_smpl_in_seg; + + if (!params->rice_code_flag[param_index]) { + /* Linear code */ + if (bits) + for (j = 0; j < part0; j++) + sample_buf[j] = get_bits_sm(gb, bits); + else + memset(sample_buf, 0, part0 * sizeof(sample_buf[0])); + + /* Second part */ + bits = params->pancABIT[param_index]; + if (bits) + for (j = part0; j < s->xll_smpl_in_seg; j++) + sample_buf[j] = get_bits_sm(gb, bits); + else + memset(sample_buf + part0, 0, + (s->xll_smpl_in_seg - part0) * sizeof(sample_buf[0])); + } else { + int aux_bits = params->pancAuxABIT[param_index]; + + for (j = 0; j < part0; j++) { + /* FIXME: Is this identical to Golomb code? */ + int t = get_unary(gb, 1, 33) << bits; + /* FIXME: Could move this test outside of the loop, for efficiency. */ + if (bits) + t |= get_bits(gb, bits); + sample_buf[j] = (t & 1) ? -(t >> 1) - 1 : (t >> 1); + } + + /* Second part */ + bits = params->pancABIT[param_index]; + + /* Follow the spec's suggestion of using the + * buffer also to store the hybrid-rice flags. */ + memset(sample_buf + part0, 0, + (s->xll_smpl_in_seg - part0) * sizeof(sample_buf[0])); + + if (aux_bits > 0) { + /* For hybrid rice encoding, some samples are linearly + * coded. According to the spec, "nBits4SamplLoci" bits + * are used for each index, but this value is not + * defined. I guess we should use log2(xll_smpl_in_seg) + * bits. */ + int count = get_bits(gb, s->xll_log_smpl_in_seg); + av_log(s->avctx, AV_LOG_DEBUG, "aux count %d (bits %d)\n", + count, s->xll_log_smpl_in_seg); + + for (j = 0; j < count; j++) + sample_buf[get_bits(gb, s->xll_log_smpl_in_seg)] = 1; + } + for (j = part0; j < s->xll_smpl_in_seg; j++) { + if (!sample_buf[j]) { + int t = get_unary(gb, 1, 33); + if (bits) + t = (t << bits) | get_bits(gb, bits); + sample_buf[j] = (t & 1) ? -(t >> 1) - 1 : (t >> 1); + } else + sample_buf[j] = get_bits_sm(gb, aux_bits); + } + } + } + + for (i = 0; i < chset->channels; i++) { + unsigned adapt_order = chset->adapt_order[0][i]; + int *sample_buf = s->xll_sample_buf + + (in_channel + i) * s->xll_smpl_in_seg; + int *prev = history + (in_channel + i) * DCA_XLL_AORDER_MAX; + + if (!adapt_order) { + unsigned order; + for (order = chset->fixed_order[0][i]; order > 0; order--) { + unsigned j; + for (j = 1; j < s->xll_smpl_in_seg; j++) + sample_buf[j] += sample_buf[j - 1]; + } + } else + /* Inverse adaptive prediction, in place. */ + dca_xll_inv_adapt_pred(sample_buf, s->xll_smpl_in_seg, + adapt_order, seg ? prev : NULL, + chset->lpc_refl_coeffs_q_ind[0][i]); + memcpy(prev, sample_buf + s->xll_smpl_in_seg - DCA_XLL_AORDER_MAX, + DCA_XLL_AORDER_MAX * sizeof(*prev)); + } + for (i = 1; i < chset->channels; i += 2) { + int coeff = chset->pw_ch_pairs_coeffs[0][i / 2]; + if (coeff != 0) { + int *sample_buf = s->xll_sample_buf + + (in_channel + i) * s->xll_smpl_in_seg; + int *prev = sample_buf - s->xll_smpl_in_seg; + unsigned j; + for (j = 0; j < s->xll_smpl_in_seg; j++) + /* Shift is unspecified, but should apparently be 3. */ + sample_buf[j] += ((int64_t) coeff * prev[j] + 4) >> 3; + } + } + + if (s->xll_scalable_lsb) { + int lsb_start = end_pos - 8 * chset->lsb_fsize[0] - + 8 * (s->xll_banddata_crc & 2); + int done; + i = get_bits_count(gb); + if (i > lsb_start) { + av_log(s->avctx, AV_LOG_ERROR, + "chset data lsb exceeds NAVI size, end_pos %d, lsb_start %d, pos %d\n", + end_pos, lsb_start, i); + return AVERROR_INVALIDDATA; + } + if (i < lsb_start) + skip_bits_long(gb, lsb_start - i); + + for (i = done = 0; i < chset->channels; i++) { + int bits = chset->scalable_lsbs[0][i]; + if (bits > 0) { + /* The channel reordering is conceptually done + * before adding the lsb:s, so we need to do + * the inverse permutation here. */ + unsigned pi = chset->orig_chan_order_inv[0][i]; + int *sample_buf = s->xll_sample_buf + + (in_channel + pi) * s->xll_smpl_in_seg; + int adj = chset->bit_width_adj_per_ch[0][i]; + int msb_shift = bits; + unsigned j; + + if (adj > 0) + msb_shift += adj - 1; + + for (j = 0; j < s->xll_smpl_in_seg; j++) + sample_buf[j] = (sample_buf[j] << msb_shift) + + (get_bits(gb, bits) << adj); + + done += bits * s->xll_smpl_in_seg; + } + } + if (done > 8 * chset->lsb_fsize[0]) { + av_log(s->avctx, AV_LOG_ERROR, + "chset lsb exceeds lsb_size\n"); + return AVERROR_INVALIDDATA; + } + } + + /* Store output. */ + for (i = 0; i < chset->channels; i++) { + int *sample_buf = s->xll_sample_buf + + (in_channel + i) * s->xll_smpl_in_seg; + int shift = 1 - chset->bit_resolution; + int out_channel = chset->orig_chan_order[0][i]; + float *out; + + /* XLL uses the channel order C, L, R, and we want L, + * R, C. FIXME: Generalize. */ + if (chset->ch_mask_enabled && + (chset->ch_mask & 7) == 7 && out_channel < 3) + out_channel = out_channel ? out_channel - 1 : 2; + + out_channel += in_channel; + if (out_channel >= s->avctx->channels) + continue; + + out = (float *) frame->extended_data[out_channel]; + out += seg * s->xll_smpl_in_seg; + + /* NOTE: A one bit means residual encoding is *not* used. */ + if ((chset->residual_encode >> i) & 1) { + /* Replace channel samples. + * FIXME: Most likely not the right thing to do. */ + for (j = 0; j < s->xll_smpl_in_seg; j++) + out[j] = ldexpf(sample_buf[j], shift); + } else { + /* Add residual signal to core channel */ + for (j = 0; j < s->xll_smpl_in_seg; j++) + out[j] += ldexpf(sample_buf[j], shift); + } + } + + if (chset->downmix_coeff_code_embedded && + !chset->primary_ch_set && chset->hier_chset) { + /* Undo hierarchical downmix of earlier channels. */ + unsigned mix_channel; + for (mix_channel = 0; mix_channel < in_channel; mix_channel++) { + float *mix_buf; + const int *col; + float coeff; + unsigned row; + /* Similar channel reorder C, L, R vs L, R, C reorder. */ + if (chset->ch_mask_enabled && + (chset->ch_mask & 7) == 7 && mix_channel < 3) + mix_buf = (float *) frame->extended_data[mix_channel ? mix_channel - 1 : 2]; + else + mix_buf = (float *) frame->extended_data[mix_channel]; + + mix_buf += seg * s->xll_smpl_in_seg; + col = &chset->downmix_coeffs[mix_channel * (chset->channels + 1)]; + + /* Scale */ + coeff = ldexpf(col[0], -16); + for (j = 0; j < s->xll_smpl_in_seg; j++) + mix_buf[j] *= coeff; + + for (row = 0; + row < chset->channels && in_channel + row < s->avctx->channels; + row++) + if (col[row + 1]) { + const float *new_channel = + (const float *) frame->extended_data[in_channel + row]; + new_channel += seg * s->xll_smpl_in_seg; + coeff = ldexpf(col[row + 1], -15); + for (j = 0; j < s->xll_smpl_in_seg; j++) + mix_buf[j] -= coeff * new_channel[j]; + } + } + } + +next_chset: + in_channel += chset->channels; + /* Skip to next channel set using the NAVI info. */ + i = get_bits_count(gb); + if (i > end_pos) { + av_log(s->avctx, AV_LOG_ERROR, + "chset data exceeds NAVI size\n"); + return AVERROR_INVALIDDATA; + } + if (i < end_pos) + skip_bits_long(gb, end_pos - i); + } + } + return 0; +} diff --git a/libavcodec/dcadata.c b/libavcodec/dcadata.c new file mode 100644 index 0000000..2369f55 --- /dev/null +++ b/libavcodec/dcadata.c @@ -0,0 +1,8391 @@ +/* + * DCA compatible decoder data + * Copyright (C) 2004 Gildas Bazin + * Copyright (c) 2006 Benjamin Larsson + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/mem.h" + +#include "dcadata.h" + +/* Generic tables */ + +const uint32_t ff_dca_bit_rates[32] = { + 32000, 56000, 64000, 96000, 112000, 128000, + 192000, 224000, 256000, 320000, 384000, + 448000, 512000, 576000, 640000, 768000, + 896000, 1024000, 1152000, 1280000, 1344000, + 1408000, 1411200, 1472000, 1536000, 1920000, + 2048000, 3072000, 3840000, 1 /* open */, 2 /* variable */, 3 /* lossless */ +}; + +const uint8_t ff_dca_channels[16] = { + 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8 +}; + +const uint8_t ff_dca_bits_per_sample[7] = { + 16, 16, 20, 20, 0, 24, 24 +}; + +/* ADPCM data */ + +/* 16 bits signed fractional Q13 binary codes */ +const int16_t ff_dca_adpcm_vb[4096][4] = { + { 9928, -2618, -1093, -1263 }, + { 11077, -2876, -1747, -308 }, + { 10503, -1082, -1426, -1167 }, + { 9337, -2403, -1495, 274 }, + { 10698, -2529, -532, -1122 }, + { 10368, -3974, -1264, -750 }, + { 10070, -3667, 346, 863 }, + { 10278, -3093, 311, -576 }, + { 9894, -1330, -1428, -860 }, + { 10544, -1923, -1058, -971 }, + { 10996, -1632, -841, -1404 }, + { 11832, -3465, 1658, -1990 }, + { 10852, -688, -2658, -499 }, + { 10546, -1749, -147, -1733 }, + { 10801, -1004, -708, -1453 }, + { 10588, -441, -2113, -952 }, + { 10141, -3331, -582, -1432 }, + { 9608, -2590, 383, 258 }, + { 11422, -3265, 229, -1544 }, + { 10460, -1338, -713, -1568 }, + { 10306, -1721, -1660, -603 }, + { 9580, -1812, -1235, -1061 }, + { 11471, -2285, -1617, -607 }, + { 10081, -2225, -1408, -868 }, + { 10715, -2624, -1367, -704 }, + { 10616, -1871, -2770, -35 }, + { 9352, -2340, -1024, -1566 }, + { 11065, -1458, -1926, -735 }, + { 11334, -2056, -1041, -1144 }, + { 9825, -2048, -794, -1536 }, + { 11850, -2695, -1123, -867 }, + { 10654, -2226, -1891, -373 }, + { 10024, -1557, -808, -1069 }, + { 11142, -1266, -3238, 128 }, + { 11729, -3282, -514, -1011 }, + { 11402, -2094, -2335, -189 }, + { 10195, -3658, 181, -1875 }, + { 11431, -2626, -404, -1377 }, + { 11001, -3868, -619, -1077 }, + { 10894, -2559, 274, -1758 }, + { 9633, -1482, -2253, -773 }, + { 11245, -3321, 830, -1972 }, + { 9768, -2701, -199, -1859 }, + { 10500, -2042, 525, -2043 }, + { 11669, -4069, 293, -1468 }, + { 9192, -1991, -583, -61 }, + { 10057, -3220, -2015, -473 }, + { 9497, -2315, -2490, -467 }, + { 10455, -3069, -1194, -1007 }, + { 9994, -1936, -60, -1225 }, + { 9295, -2156, -1761, -1134 }, + { 10085, -3748, -1026, 197 }, + { 9334, -2360, 804, -351 }, + { 11561, -2553, 1352, -2313 }, + { 12837, -3998, 1195, -1958 }, + { 10114, -1100, -2414, -394 }, + { 9341, -2530, 315, 755 }, + { 10131, -3164, 1411, -674 }, + { 9535, -905, -1551, 579 }, + { 11717, -1519, -3051, 91 }, + { 9824, -2911, -2775, 192 }, + { 9662, -2934, -561, 1450 }, + { 11085, -3392, -1298, -659 }, + { 8955, -2102, -1899, 703 }, + { 8607, -1742, -4348, 814 }, + { 7640, -2063, -3617, 52 }, + { 7074, -826, -4325, 4375 }, + { 7714, 584, -4238, 1927 }, + { 6355, -952, -4912, 3127 }, + { 7069, -660, -6413, 4087 }, + { 8313, -132, -2964, -876 }, + { 6952, -1422, -3962, -24 }, + { 9299, -734, -3088, -263 }, + { 9484, -574, -4513, 466 }, + { 7246, -91, -3735, -704 }, + { 8325, -1417, -3090, -530 }, + { 6469, -1226, -4757, 829 }, + { 6652, -368, -5682, 1393 }, + { 7971, -1278, -2284, 1205 }, + { 7229, -699, -3556, 1840 }, + { 7994, 1284, -2729, 732 }, + { 9005, -698, -4522, 2189 }, + { 6963, 197, -2727, 380 }, + { 8527, 135, -3991, -213 }, + { 8840, 934, -3014, -567 }, + { 10125, 418, -3284, -371 }, + { 6367, 361, -2318, 2554 }, + { 7892, 172, -5247, 4673 }, + { 6674, 387, -5424, 4398 }, + { 6240, 684, -4047, 1219 }, + { 11170, -794, -5081, 1195 }, + { 11765, -648, -6265, 2052 }, + { 10845, -775, -3837, 366 }, + { 12496, -689, -8260, 3562 }, + { 7893, -1166, -4972, 988 }, + { 8592, 1052, -5986, 3087 }, + { 7277, 1874, -5685, 3579 }, + { 6900, 2016, -4809, 3491 }, + { 8530, -2405, -3250, 1986 }, + { 9426, 494, -7067, 5038 }, + { 10285, 564, -8210, 5370 }, + { 8749, -2207, -3980, 2852 }, + { 9653, -2686, -4300, 1400 }, + { 9770, -2286, -5663, 4233 }, + { 8490, -4, -7048, 4496 }, + { 7697, -1209, -5328, 3183 }, + { 6451, 801, -4324, -554 }, + { 7387, 1806, -5265, 545 }, + { 7450, -2302, -4445, 1418 }, + { 8817, -1370, -5827, 2168 }, + { 10324, -2406, -5629, 2579 }, + { 8863, -2578, -3537, 467 }, + { 6901, -1624, -3169, 3392 }, + { 7846, 156, -6948, 3381 }, + { 7928, -1115, -5972, 4816 }, + { 6089, -599, -4368, -320 }, + { 7833, 1246, -3960, -621 }, + { 8931, 2521, -6768, 2052 }, + { 8900, 1944, -4126, 40 }, + { 7661, -34, -2855, 2480 }, + { 5873, 474, -3262, 3712 }, + { 7535, -234, -4699, 216 }, + { 5856, 143, -5142, 73 }, + { 8944, -106, -5874, 3663 }, + { 7134, 426, -5879, 2895 }, + { 10199, 1011, -4762, 369 }, + { 8454, 264, -5971, 1291 }, + { 7822, -2449, -4333, 4540 }, + { 6200, -2758, -2632, 1497 }, + { 6070, -4315, -2699, 414 }, + { 7047, -3739, -3210, 1060 }, + { 5675, -3801, -2717, -407 }, + { 4789, -4063, -2628, -744 }, + { 4023, -3366, -3133, -726 }, + { 4296, -2407, -3381, -513 }, + { 4388, -2931, -2820, 1512 }, + { 4559, -4233, -1941, 1976 }, + { 6702, -3208, -1755, 1680 }, + { 4416, -3521, -1052, 2984 }, + { 7154, -4266, -1203, 3732 }, + { 3625, -4242, -3244, 1395 }, + { 6518, -2856, -1304, 2887 }, + { 6170, -1949, -3014, 3973 }, + { 5189, -2451, -4020, 3477 }, + { 6218, -2988, -1921, 3844 }, + { 4827, -3688, -1928, 3343 }, + { 6668, -3991, -2805, 3095 }, + { 5297, -3115, -3684, 2390 }, + { 5354, -4614, -2662, 1504 }, + { 4196, -3091, -4147, 1135 }, + { 3540, -2893, -4007, 100 }, + { 5569, -1602, -4007, 1909 }, + { 4341, -2091, -4272, 252 }, + { 5559, -2878, -3832, 498 }, + { 4548, -4479, -2898, -27 }, + { 5176, -2494, -4635, 1476 }, + { 3294, -3485, -3738, 716 }, + { 4920, -1229, -4195, -365 }, + { 3257, -3518, -3349, 2862 }, + { 5286, -1948, -3485, -778 }, + { 6502, -3051, -152, 2854 }, + { 5864, -4192, -1076, 3451 }, + { 4656, -3122, -3448, 179 }, + { 5907, -754, -1596, 3116 }, + { 7229, -3680, -1590, 2892 }, + { 5107, -3888, -3364, 806 }, + { 6764, -2635, -3450, 134 }, + { 5258, -2827, -2844, -1052 }, + { 5798, -1725, -4305, 205 }, + { 5404, -1213, -3362, 449 }, + { 6224, -2738, -3046, -581 }, + { 4223, -2438, -2725, 3745 }, + { 4751, -3411, -2123, 116 }, + { 3868, -3000, -3954, 2297 }, + { 6819, -2899, -4277, 2825 }, + { 4207, -4754, -2808, 865 }, + { 4804, -1494, -1997, 4688 }, + { 5282, -2213, -548, 3559 }, + { 5580, -1912, -566, 4370 }, + { 6168, -2857, -672, 4053 }, + { 6583, -4515, -2850, 1670 }, + { 6511, -3093, -3988, 1421 }, + { 4646, -1790, -1443, 3650 }, + { 5915, -924, -2020, 896 }, + { 7814, -4181, -3152, 2007 }, + { 6190, -2238, -4817, 2279 }, + { 4737, -4034, -3288, 1835 }, + { 8161, -3633, -3423, 3137 }, + { 7415, -2351, -2088, 4290 }, + { 4106, -2517, -62, 2905 }, + { 4909, -3145, -614, 4112 }, + { 4938, -3281, -397, 1100 }, + { -173, 919, 1589, -5363 }, + { -13, 796, -295, -6655 }, + { -1860, -829, 1141, -4555 }, + { 2298, -838, -664, -5005 }, + { -884, -1097, 2074, -4613 }, + { -101, 281, 2846, -4535 }, + { 1166, 453, 2429, -5910 }, + { 879, -664, 2370, -5452 }, + { 1415, -370, -1699, -4727 }, + { -1413, 1277, -669, -6649 }, + { 2133, 304, -968, -4624 }, + { 380, 586, -2087, -4892 }, + { 1336, 275, -82, -5789 }, + { -2459, 1057, -34, -5416 }, + { 2278, -1758, 866, -5653 }, + { 1945, -2295, -149, -5302 }, + { 1287, -3525, 996, -5255 }, + { 2297, 803, 1177, -6067 }, + { 187, -180, -619, -6202 }, + { -793, -2537, 1554, -5057 }, + { -2703, -204, -629, -5853 }, + { -1007, -146, 313, -5582 }, + { 830, 357, 869, -6363 }, + { -228, -575, -3177, -4433 }, + { -1001, -1553, -142, -5708 }, + { -1644, 1683, 1721, -4533 }, + { 893, 1924, -15, -5791 }, + { 2195, 2061, -262, -5471 }, + { 3031, 270, 311, -5096 }, + { 1912, 1638, -1523, -4677 }, + { -3142, -55, 253, -4914 }, + { 356, -1680, 343, -6123 }, + { -2241, -1734, -976, -5939 }, + { -2196, -2893, 547, -4938 }, + { -1245, 126, -1916, -5419 }, + { -249, -3755, -1422, -5594 }, + { 575, -2683, -1926, -4566 }, + { -762, 1885, 192, -5880 }, + { -811, -2562, -1068, -6013 }, + { -2264, -3086, -976, -4775 }, + { 70, -1215, 2880, -4410 }, + { 714, -3760, 2916, -4691 }, + { -244, -3404, 1740, -4493 }, + { 684, -5137, -328, -5608 }, + { -529, -3825, -1786, -4535 }, + { -713, -4743, -1118, -5546 }, + { 2718, -3788, 1798, -5708 }, + { -1639, -3679, -1564, -6095 }, + { 1693, -2642, -1389, -4539 }, + { 505, -1573, -1651, -4878 }, + { -835, -2256, -1941, -5352 }, + { 1464, -411, 1993, -6441 }, + { 493, -3184, -145, -6148 }, + { -1413, 499, -1617, -6479 }, + { -294, 1722, -1419, -5725 }, + { -2937, -1528, -175, -4624 }, + { -594, -5911, -56, -6146 }, + { -300, -4275, 1156, -5947 }, + { 552, -2643, 2669, -3959 }, + { 905, -4158, 1789, -5809 }, + { 1336, -2009, 2108, -5903 }, + { 1555, -3600, 1110, -6759 }, + { -1294, -3464, 77, -6084 }, + { -1139, -4006, -1270, -4181 }, + { -5094, -3296, 1092, -2847 }, + { -5503, -2883, 1984, -2067 }, + { -4671, -4218, -1417, -4132 }, + { -3763, -3818, 1262, -3082 }, + { -5132, -3430, 2928, -728 }, + { -5957, -2877, 1251, -2446 }, + { -4425, -2319, -212, -4276 }, + { -6201, -1993, 1774, -2182 }, + { -5500, -3836, 2201, -1396 }, + { -6934, -2334, 2366, -1293 }, + { -6124, -4140, 1337, -1977 }, + { -6553, -4186, 1756, -1325 }, + { -5126, -1258, 744, -3656 }, + { -5167, -1390, 1581, -2895 }, + { -4525, -3398, 2429, -1865 }, + { -4076, -3183, 2027, -2510 }, + { -6191, -3274, 1838, -1814 }, + { -4454, -2753, 2723, -1185 }, + { -6655, -4797, 251, -2595 }, + { -6332, -2232, 1832, 217 }, + { -5869, -1698, 134, 340 }, + { -6614, -1045, 2126, -1932 }, + { -4859, -2107, 2010, -2435 }, + { -6274, -1622, 2808, -1374 }, + { -3119, -3209, 521, -3988 }, + { -5676, -2082, -420, -2711 }, + { -7073, -3623, 696, -2343 }, + { -5986, -4224, 572, -2454 }, + { -4340, -4521, 882, -2771 }, + { -6178, -1933, 535, -1444 }, + { -4923, -4163, 1744, -2066 }, + { -6410, -1519, 1058, -2683 }, + { -5077, -1185, 856, -2216 }, + { -7091, -2444, 687, -2597 }, + { -5284, -2165, 3239, -993 }, + { -4763, -1497, 197, -3179 }, + { -4128, -4958, -396, -3578 }, + { -5054, -3878, -647, -2672 }, + { -7005, -3348, 1679, -1579 }, + { -5767, -1017, 2582, -1915 }, + { -7069, -2787, 1331, -2070 }, + { -5532, -2296, 706, -2950 }, + { -5059, -3543, -821, -3637 }, + { -6639, -1835, 1016, -696 }, + { -5611, -5220, -694, -3371 }, + { -5994, -2803, 2933, -729 }, + { -5948, -619, 1596, -2676 }, + { -5486, -4419, 153, -3265 }, + { -4329, -3440, 1646, -1439 }, + { -4083, -3978, 177, -3569 }, + { -4289, -2599, 1224, -3075 }, + { -5707, -3253, 1912, -759 }, + { -6606, -3437, 2562, -571 }, + { -5254, -2444, 769, -352 }, + { -6545, -3154, 582, -1103 }, + { -5328, -2241, 2566, -1775 }, + { -7216, -1936, 1538, -1983 }, + { -3730, -2451, 426, -3869 }, + { -5110, -1385, 2031, -1169 }, + { -6470, -2715, 269, -3123 }, + { -5806, -2480, -97, -3832 }, + { -3683, -4916, -490, -4330 }, + { -6341, -2083, -669, -115 }, + { -4913, -4079, -837, -4673 }, + { -3274, -2497, 2334, -2652 }, + { -1286, -1731, 2550, -3756 }, + { -3375, -877, 926, -3977 }, + { -2525, -2079, 2879, -2625 }, + { -5308, -504, 3111, -1607 }, + { -4904, 460, 4093, -1232 }, + { -1993, 1616, 4656, -1913 }, + { -3481, -1176, 3119, -2236 }, + { -4132, -1502, 2339, -2545 }, + { -2542, 1151, 3569, -2550 }, + { -4381, 430, 3147, -2082 }, + { -3888, 867, 3899, -1657 }, + { -2861, 1290, 4202, -1979 }, + { -3893, -253, 2363, -2764 }, + { -1705, 688, 3827, -2923 }, + { -2223, 2312, 3700, -3148 }, + { -1986, -720, 5021, -795 }, + { -3177, 242, 1952, -3352 }, + { -1854, 1509, 2528, -3815 }, + { -3173, 97, 5019, -706 }, + { -2689, -145, 1375, -3915 }, + { -4838, -385, 2488, -2427 }, + { -4557, -355, 1603, -3060 }, + { -3522, 1832, 3292, -2674 }, + { -3769, 780, 2378, -2704 }, + { -4323, -1932, 3414, -1169 }, + { -2740, 1158, 2729, -3273 }, + { -3647, 210, 1464, -2892 }, + { -2342, -2097, 1513, -3727 }, + { -4422, -1242, 3130, -1833 }, + { -1308, -1039, 4290, -1875 }, + { -1754, -2535, 3298, -2314 }, + { -4102, -186, 4037, -1094 }, + { -1008, 1570, 3290, 171 }, + { -3322, -2621, 2791, -1536 }, + { -2539, -2597, 3442, -1672 }, + { -3411, -2015, 3670, -1174 }, + { -2097, 730, 5581, -1399 }, + { -1510, -74, 4820, -2004 }, + { -4086, -868, 4425, -771 }, + { -956, -986, 3640, -2925 }, + { -2087, -1250, 3464, -2458 }, + { -3308, -2411, 1334, -3667 }, + { -2264, -389, 4004, -1854 }, + { -680, 239, 4058, -3388 }, + { -1357, 30, 2993, -3658 }, + { -3601, -552, 1177, -1136 }, + { -2641, 442, 4374, -1625 }, + { -2525, 770, 1640, -3895 }, + { -3172, -891, 3893, -1608 }, + { -2996, 13, 3277, -2414 }, + { -899, 1055, 4470, -2501 }, + { -422, -584, 3475, -3787 }, + { -1978, -593, 2566, -3415 }, + { -3150, -1280, 2362, -3047 }, + { -3592, 224, 1026, -3932 }, + { -4840, -1189, 3633, -879 }, + { -3952, -2255, 2916, -1826 }, + { -1695, 28, 1810, -349 }, + { -745, -2484, 3308, -3293 }, + { -1016, 1563, 5365, -1823 }, + { -2172, -1787, 4266, -1287 }, + { -1241, -1951, 3982, -2413 }, + { -2009, -2639, 2330, -3480 }, + { 5105, -1618, -2588, -2015 }, + { 6497, -1523, -3218, -910 }, + { 6526, -2305, -2029, -1790 }, + { 5289, -99, -3436, -400 }, + { 5781, -1623, -1577, -2617 }, + { 5259, -670, -3125, -1700 }, + { 6343, -1256, -331, -3222 }, + { 7967, -678, -2195, -1462 }, + { 6119, -695, -2988, -1538 }, + { 6108, 494, -3359, -1548 }, + { 5067, 969, -2328, -2707 }, + { 7595, -435, -1497, -2056 }, + { 6929, -719, -2420, -1665 }, + { 5190, 584, -2982, -2103 }, + { 6106, -444, -1411, -2739 }, + { 5584, 289, -1804, -2803 }, + { 5276, 227, -1180, -3361 }, + { 7544, -1525, -1834, -1725 }, + { 5986, -1470, -2606, -1701 }, + { 5096, -765, -1712, -3006 }, + { 5423, -149, -3933, -1157 }, + { 7651, 26, -2445, -1507 }, + { 4745, -464, -1735, -2362 }, + { 5352, -1011, -1094, -1999 }, + { 6300, -672, -542, -1950 }, + { 6675, -1020, -1318, -1059 }, + { 7218, -2036, -603, -2462 }, + { 7755, -1514, -2430, -1229 }, + { 5041, 449, -1056, -2405 }, + { 6710, -2277, -1344, -2284 }, + { 6824, -1347, -2254, 251 }, + { 6068, -1857, -983, -1316 }, + { 5603, -2177, -2730, -1477 }, + { 5838, -1059, -3604, -970 }, + { 5076, -789, -335, -2413 }, + { 6191, -1634, -2000, -2129 }, + { 5092, -1292, -2543, -1034 }, + { 5305, 435, -1710, -1850 }, + { 6140, 561, -2176, -2380 }, + { 6752, 348, -2496, -1890 }, + { 6405, 273, -1098, -2778 }, + { 6942, -1340, -496, -1381 }, + { 5238, -687, -2454, -2349 }, + { 6959, -882, -1833, -2061 }, + { 6292, -253, -2125, -2199 }, + { 5838, -574, -759, -3215 }, + { 6954, -1484, -640, -2771 }, + { 7498, -1706, -1210, -2154 }, + { 6772, -1003, -1235, -2532 }, + { 6014, 228, -2154, -1108 }, + { 6943, -2178, -2644, -1122 }, + { 7262, -763, -3056, -1090 }, + { 6273, -1478, -1072, 177 }, + { 4734, 425, -2912, 357 }, + { 7129, 168, -1537, -2327 }, + { 7204, -434, -746, -2660 }, + { 6879, 57, -3087, -1310 }, + { 4623, -610, -718, -3459 }, + { 6565, -543, -1998, -339 }, + { 4752, -277, -2066, -1405 }, + { 7435, -1416, -1904, -505 }, + { 4076, 150, -1222, -3556 }, + { 7082, -28, -1456, -1174 }, + { 5941, -446, -1326, -1158 }, + { 3870, -1648, -2474, -2589 }, + { 858, 37, -3387, -3721 }, + { 3557, -1503, -1664, -3383 }, + { 3336, -1972, -3079, -2216 }, + { 3186, 60, -4185, -863 }, + { 3456, -773, -3066, -2457 }, + { 4131, -913, -2060, -2601 }, + { 4431, -691, -4114, -972 }, + { 3461, -334, -3680, -1751 }, + { 2006, -459, -2214, -3827 }, + { 1322, 32, -2816, -3203 }, + { 4425, -1897, -2791, -1946 }, + { 4504, 23, -3421, -1909 }, + { 3090, -885, -2366, -3264 }, + { 3209, -2363, -3730, -834 }, + { 3312, -1471, -3641, -1579 }, + { 4184, -1669, -3323, -1248 }, + { 2190, -931, -3302, -2944 }, + { 2947, -229, -4791, -1195 }, + { 2020, -1626, -2700, -3125 }, + { 2214, -326, -4352, -1683 }, + { 3286, -2619, -2412, -2458 }, + { 1000, -2571, -4129, -2158 }, + { 2496, -2627, -3611, -1433 }, + { 2043, -2191, -2167, -3827 }, + { 2571, -2544, -1915, -3222 }, + { 2022, -1501, -3856, -2165 }, + { 2685, -1180, -1461, -4038 }, + { 1610, -2313, -4391, -1173 }, + { 2340, -2490, -4215, -516 }, + { 1742, -2615, -3632, -2146 }, + { 523, -1293, -4246, -2442 }, + { 3725, -2723, -3014, -1576 }, + { 3554, -1381, -4200, -824 }, + { 1291, -1594, -4777, -1430 }, + { 1452, 515, -2960, -3830 }, + { 4264, -894, -3305, -1826 }, + { 2606, -1452, -4522, -966 }, + { 1196, -830, -4807, -1816 }, + { 1054, -775, -2616, -4071 }, + { 4206, 415, -4344, -1132 }, + { 3044, 491, -4126, -1934 }, + { 988, -901, -3353, -3443 }, + { 1729, -3063, -2267, -3370 }, + { 3915, 912, -2989, -2387 }, + { 3781, 300, -2457, -3050 }, + { 2712, 924, -1350, -1206 }, + { 4230, 405, -2343, 665 }, + { 1878, -873, -225, -29 }, + { 3510, 56, -1334, -3420 }, + { 2850, 1447, -2651, -3150 }, + { 1510, -706, -4125, -2483 }, + { 3115, 793, -1692, -3894 }, + { 2667, 213, -2973, -2786 }, + { 1184, -2384, -3051, -3173 }, + { 2139, 796, -2079, -3697 }, + { 1464, -1483, -3726, -2754 }, + { 2407, -1148, -3915, -1569 }, + { 2612, -1779, -3217, -2271 }, + { 2406, -2870, -2937, -2496 }, + { 2140, 126, -3646, -2758 }, + { 2952, -1036, 268, -1423 }, + { 93, -1931, -3841, -3535 }, + { 389, -2953, -3383, -3343 }, + { 8652, -5511, -1662, 565 }, + { 7427, -2791, -2535, -842 }, + { 8541, -4253, -1407, -988 }, + { 8018, -3203, -2998, 105 }, + { 7231, -3926, -958, 1308 }, + { 7331, -3690, -363, 2586 }, + { 6803, -3646, -2226, -903 }, + { 8163, -2811, -477, -2235 }, + { 9356, -3818, -1685, -684 }, + { 8466, -2854, -302, -698 }, + { 8458, -3224, 517, 279 }, + { 8074, -2619, -1326, 2596 }, + { 8779, -2761, -2527, -441 }, + { 6533, -2887, -899, -696 }, + { 7394, -2305, -1642, -120 }, + { 8281, -3780, -22, 1305 }, + { 9158, -4413, -779, 901 }, + { 9031, -5240, -1109, 1678 }, + { 8717, -3650, 410, -1075 }, + { 7317, -3197, -818, -2264 }, + { 7934, -2385, -1214, -1886 }, + { 8256, -4441, -291, -587 }, + { 7358, -3395, 1090, -270 }, + { 9446, -4910, -1343, -473 }, + { 8187, -4726, -808, 1166 }, + { 7504, -3845, -47, 267 }, + { 8029, -2146, -1283, -383 }, + { 7461, -2705, -853, 783 }, + { 9367, -3636, -645, -354 }, + { 8955, -3473, -308, -1947 }, + { 8676, -2683, -2099, 1485 }, + { 7481, -3003, -871, -444 }, + { 8015, -2839, -1673, 1175 }, + { 6947, -4643, -1527, -1047 }, + { 7622, -2575, -137, -960 }, + { 9388, -4279, -707, -1322 }, + { 8382, -5259, -1283, -565 }, + { 6856, -4138, -1030, 630 }, + { 8659, -2571, -1124, -1666 }, + { 8763, -3807, -537, 2543 }, + { 8049, -3578, -2186, -604 }, + { 8272, -2351, -1985, -1214 }, + { 6855, -3796, -1527, -1631 }, + { 7178, -2896, -1600, -1756 }, + { 7040, -2888, -89, -1586 }, + { 6261, -3403, -264, 998 }, + { 7756, -4699, -1543, -834 }, + { 7682, -4622, -758, -1721 }, + { 8839, -4232, -2932, 1959 }, + { 9363, -4679, -1956, 39 }, + { 7883, -3616, -1414, -1432 }, + { 8828, -3188, -1356, -1312 }, + { 7746, -3987, -121, -2424 }, + { 9262, -3256, -693, 818 }, + { 7670, -3420, -148, 3504 }, + { 7344, -3183, 608, 1595 }, + { 8976, -4139, -1848, 1304 }, + { 6708, -4131, 33, -852 }, + { 7840, -4429, -2275, 79 }, + { 8980, -3858, -2838, 453 }, + { 7815, -4604, -2563, 944 }, + { 8372, -4422, -1783, 3071 }, + { 8623, -5128, -1754, 2888 }, + { 7462, -3281, 889, 920 }, + { 8416, -59, -1320, -1825 }, + { 7928, -1488, -414, -2499 }, + { 8110, -977, -1047, -2042 }, + { 8278, -687, -1597, -1550 }, + { 7988, -174, -977, -2106 }, + { 8609, -1547, -1628, -1527 }, + { 9000, -1798, -946, -1761 }, + { 8954, -872, -1404, -1594 }, + { 8939, 466, -748, -1212 }, + { 9549, -329, -177, -1360 }, + { 9411, -18, -1126, -1568 }, + { 8859, -782, -488, -1338 }, + { 8955, -218, -43, -1209 }, + { 9131, -69, -453, -1001 }, + { 9069, -1519, -1091, -1199 }, + { 9247, -1309, -566, -1146 }, + { 8528, -1617, -287, -1313 }, + { 7763, -745, -149, -2040 }, + { 8294, -343, 257, -2633 }, + { 10149, -893, -552, -1649 }, + { 9398, -915, 218, -2042 }, + { 9703, -1194, -675, -1592 }, + { 9586, -700, -427, -1710 }, + { 8930, 497, -1445, -1218 }, + { 9285, -1323, -163, -1552 }, + { 8431, -1289, -985, -1404 }, + { 8965, -655, 653, -1483 }, + { 9542, -1001, -951, -1128 }, + { 9205, -647, -37, -882 }, + { 8603, -56, 514, -1793 }, + { 9300, -12, -1324, -567 }, + { 8773, 238, -184, -1456 }, + { 9941, -1306, -69, -1792 }, + { 9360, 279, -376, -1919 }, + { 9180, -285, 95, -2170 }, + { 9922, -501, -970, -1570 }, + { 8341, -1493, -856, -2092 }, + { 8780, -981, -850, -1014 }, + { 9721, -548, -1504, -1094 }, + { 9973, -1493, 482, -2105 }, + { 8707, -333, -1027, -1087 }, + { 9098, -469, -315, -1723 }, + { 8879, -1050, -661, -2020 }, + { 8857, 602, -866, -1918 }, + { 8945, -1025, -2154, -1071 }, + { 8484, -1930, -468, -2179 }, + { 9177, -1903, -224, -2112 }, + { 8652, -137, -2097, -1214 }, + { 9063, -973, -1405, -772 }, + { 9328, -456, 662, -2469 }, + { 10101, -697, 127, -2113 }, + { 9685, 811, -2359, -1024 }, + { 8586, -94, -460, -1982 }, + { 7924, -141, -509, -2513 }, + { 7773, -669, -107, -2835 }, + { 8636, -1064, -46, -2409 }, + { 9748, 596, -1815, -1349 }, + { 8924, 304, 547, -2614 }, + { 9442, 746, -1153, -1679 }, + { 9454, -278, -529, -1976 }, + { 8488, 561, -32, -2160 }, + { 10083, -63, -1544, -1364 }, + { 9390, -1278, 568, -1131 }, + { 9740, -49, -2253, -910 }, + { 3636, -2391, -1115, -3614 }, + { 6014, -3204, -1902, -1808 }, + { 5787, -3497, -1116, -2590 }, + { 4365, -3046, -1632, -2668 }, + { 4733, -2192, -2029, -2468 }, + { 5412, -2753, -1633, -2464 }, + { 4455, -3375, -767, -3399 }, + { 4456, -1644, -983, -2841 }, + { 4039, -2523, 38, -3967 }, + { 3406, -2662, 72, -4757 }, + { 4279, -2005, 1055, -4399 }, + { 4321, -1377, -860, -3786 }, + { 3743, -5739, -651, -3047 }, + { 3528, -5510, 361, -4060 }, + { 6496, -4886, -136, -2689 }, + { 4513, -5254, 551, -4010 }, + { 6557, -3413, -92, -3063 }, + { 4186, -2059, 187, 47 }, + { 6210, -4117, -1256, -1985 }, + { 6038, -4343, 351, -2124 }, + { 4305, -4780, -2077, -1897 }, + { 4480, -3815, -2228, -1533 }, + { 5582, -3689, 1221, -3429 }, + { 5532, -4874, 1195, -2765 }, + { 6518, -2853, -905, -2568 }, + { 5467, -2192, 470, -4115 }, + { 4139, -1577, 240, -3493 }, + { 5281, -1926, -729, -3340 }, + { 5214, -2870, 1359, -4289 }, + { 3046, -3510, -1536, -3214 }, + { 5433, -2881, -1230, -1184 }, + { 4861, -3932, -1071, -2791 }, + { 5693, -4234, -1906, -1502 }, + { 4004, -3935, -1804, -2383 }, + { 3728, -3792, 681, -4773 }, + { 3621, -3030, -1951, -2598 }, + { 5133, -3903, 44, -3700 }, + { 3561, -3451, 1183, -5301 }, + { 5026, -2762, -2341, -1780 }, + { 5841, -2492, -467, -3210 }, + { 5591, -1791, 497, -2472 }, + { 5054, -3898, -1822, -2097 }, + { 5813, -2792, 83, -1469 }, + { 4432, -4497, 1670, -5193 }, + { 5338, -4653, -1109, -2200 }, + { 3239, -4401, -648, -3655 }, + { 2147, -3598, -1200, -4242 }, + { 4417, -2271, -1552, -3210 }, + { 6494, -4360, 852, -3565 }, + { 2393, -6358, -856, -4524 }, + { 4959, -4196, -847, -1403 }, + { 4924, -5438, -226, -3026 }, + { 4254, -5303, -1306, -2424 }, + { 4121, -3126, -2334, -1981 }, + { 3437, -4443, -1464, -2953 }, + { 3203, -3459, -529, -4339 }, + { 5896, -5945, 543, -3246 }, + { 1987, -4733, -220, -4863 }, + { 4358, -4431, -514, -3081 }, + { 4583, -2416, -492, -2287 }, + { 2943, -5035, 419, -4927 }, + { 5358, -5129, 987, -4309 }, + { 4460, -3392, 1752, -5634 }, + { 3415, -4633, 1507, -5945 }, + { 811, -4692, -445, 2333 }, + { 1009, -5613, -1857, 1360 }, + { 1338, -2712, -2720, 3036 }, + { 1002, -3754, -2582, 2344 }, + { 750, -4608, -2334, 714 }, + { 2043, -3207, -2822, 2173 }, + { -140, -4654, -2953, 357 }, + { -54, -4026, -2376, 2695 }, + { 1858, -5022, -717, 2287 }, + { 2064, -3894, -722, 3255 }, + { 2727, -4558, -332, 2603 }, + { 1810, -5378, 283, 1826 }, + { 3935, -4326, 762, 3383 }, + { -767, -4697, -2510, 1922 }, + { 2146, -4312, -3090, 1641 }, + { 54, -5881, -2114, 921 }, + { 1992, -5766, -640, 1574 }, + { 1200, -5371, -1114, 1828 }, + { 2973, -5337, 34, 2266 }, + { 1531, -5018, -2817, 1192 }, + { 3078, -4570, 117, 1990 }, + { 924, -4286, -1388, 2713 }, + { 142, -5058, -2848, 1487 }, + { -106, -6180, -881, 842 }, + { 673, -5433, -229, 1596 }, + { 783, -5710, -2784, 562 }, + { 1935, -5729, -2009, 856 }, + { -410, -3375, -3326, 2734 }, + { 234, -3000, -2628, 3260 }, + { 733, -3405, -3806, 1589 }, + { 771, -4285, -3544, 1314 }, + { 1192, -3563, -3960, 2178 }, + { 206, -5555, -1250, 1546 }, + { -130, -3815, -1210, 3041 }, + { 646, -3940, -393, 2992 }, + { -184, -4931, -1767, 1925 }, + { 2746, -5120, -2275, 1464 }, + { 2440, -3731, -3352, 2729 }, + { -490, -4942, -3779, 997 }, + { 68, -2636, -4167, 3778 }, + { 48, -3986, -4118, 2106 }, + { -978, -5486, -1336, 1390 }, + { 1126, -5297, -855, 640 }, + { -472, -3975, -3622, 1557 }, + { 2456, -5344, -1523, 1648 }, + { -774, -5652, -2417, 1147 }, + { 995, -6122, -812, 1132 }, + { 3282, -4571, -1763, 2175 }, + { 3655, -3862, -676, 3568 }, + { 3038, -3647, -1672, 3381 }, + { 2595, -2964, -2772, 3263 }, + { 4176, -3353, -1148, 4354 }, + { 1603, -3442, -1500, 3444 }, + { 828, -6226, -1783, 678 }, + { 1421, -3333, -3080, 3403 }, + { 1121, -4727, -1924, 1984 }, + { -186, -5083, -682, 1796 }, + { 819, -2778, -3488, 530 }, + { 421, -2873, -3832, 2596 }, + { 2164, -4263, -1605, 2282 }, + { 585, -4437, -682, -491 }, + { -644, -4452, -1157, 2325 }, + { 1991, -4299, 210, 2834 }, + { 2135, -3632, -2113, 665 }, + { -7482, -2724, -2662, -1380 }, + { -6983, -2166, -3756, -3509 }, + { -7085, -1439, -2397, -3112 }, + { -7760, -3049, -3319, -2822 }, + { -8413, -2760, -4406, -3298 }, + { -5995, -3943, -1260, -3750 }, + { -7879, -1554, -3464, -2606 }, + { -6314, -2034, -3878, -1681 }, + { -8849, -2084, -1399, -1231 }, + { -7153, -2602, -1384, -817 }, + { -8041, -2571, -407, -2785 }, + { -7246, -2233, -1578, 260 }, + { -7336, -3883, -4061, -1342 }, + { -7619, -3908, -2342, 382 }, + { -8684, -3724, -1662, -727 }, + { -7850, -2922, -1770, -3449 }, + { -6766, -2034, -1293, -1988 }, + { -6895, -2116, -968, -3744 }, + { -7136, -5147, -2618, -2809 }, + { -8224, -3724, -2519, -1589 }, + { -6711, -2750, -3021, -219 }, + { -8059, -1638, -1102, -3175 }, + { -8710, -4839, -3963, -3143 }, + { -9363, -4965, -3257, -1002 }, + { -6099, -1751, -3157, -395 }, + { -6453, -3216, -4597, -483 }, + { -7879, -5477, -839, -2638 }, + { -7202, -4038, -526, -2856 }, + { -8022, -1228, -1910, -1646 }, + { -9117, -1393, -1582, -2535 }, + { -9095, -2693, -636, -2605 }, + { -9076, -2580, -3481, -2519 }, + { -8327, -4859, -2422, 83 }, + { -8368, -2129, -2324, -2173 }, + { -8554, -4563, -3842, -2007 }, + { -10462, -4261, -1934, -2084 }, + { -9717, -3187, -2294, -1896 }, + { -9625, -3889, -3020, -3224 }, + { -9857, -4955, -4239, -2184 }, + { -9752, -2351, -2277, -3129 }, + { -7219, -1302, -2639, -1603 }, + { -7477, -4360, -3718, -559 }, + { -5680, -2033, -2326, -3078 }, + { -10190, -5548, -4643, -3601 }, + { -9431, -4121, -879, -2479 }, + { -8365, -5450, -2020, -1439 }, + { -6289, -5178, -1605, -3845 }, + { -8319, -3866, -687, -2792 }, + { -8131, -1031, -3608, -3947 }, + { -10510, -2560, -1199, -2082 }, + { -11015, -3640, -2748, -3041 }, + { -8762, -5022, -5231, -1162 }, + { -10153, -2715, -4648, -4859 }, + { -7930, -5205, -1900, -3600 }, + { -9561, -3548, -4812, -3722 }, + { -7663, -4709, -1180, -1475 }, + { -9073, -5707, -1815, -2980 }, + { -8602, -2363, -2675, -3770 }, + { -9967, -5614, -3575, -3838 }, + { -8324, -1005, -2131, -3254 }, + { -10331, -5737, -2550, -2940 }, + { -8234, -3354, -3361, -4479 }, + { -8140, -1951, -4526, -4545 }, + { -6679, -2662, -2284, -4182 }, + { -1122, -1514, -6427, -212 }, + { 54, -1660, -5424, -1404 }, + { 254, -2778, -5222, 846 }, + { -267, -1661, -6577, 814 }, + { -305, -2021, -5759, 1484 }, + { -1791, -2446, -6867, -86 }, + { -2929, -3158, -6603, -1799 }, + { -1391, -3189, -5557, -1053 }, + { -1602, -884, -6767, -1213 }, + { -361, -318, -6219, -44 }, + { -4078, -2635, -5523, -433 }, + { -956, 478, -4382, 1470 }, + { -3300, -2462, -6021, -2721 }, + { 708, -2434, -5085, -540 }, + { -2435, -3607, -5647, -2110 }, + { -491, -1134, -4681, -2886 }, + { 87, -3435, -4641, -1194 }, + { -586, -2927, -4784, 366 }, + { -1394, -2326, -6021, 350 }, + { 97, -2519, -4678, -2120 }, + { -1547, -1907, -5069, -2993 }, + { 268, -3724, -4719, 127 }, + { -827, -1190, -5912, 1144 }, + { -3959, -2322, -6898, -1974 }, + { -2728, -2228, -6426, -562 }, + { -456, -666, -5785, -1609 }, + { 531, -1096, -5731, -656 }, + { -3569, -688, -3915, 110 }, + { -4752, -1725, -4393, -377 }, + { -3210, -3315, -6960, -840 }, + { -688, -3416, -4971, 1221 }, + { -1833, 77, -6491, -2434 }, + { -239, -255, -6850, -886 }, + { -2112, -1490, -6291, -2689 }, + { -1544, -4579, -5198, -1261 }, + { -2771, -4014, -5520, 683 }, + { -1635, -2829, -5512, 1214 }, + { -958, -2582, -4823, 2360 }, + { -2077, -4566, -4642, 365 }, + { -3112, -4214, -5960, -823 }, + { -2467, -2510, -4858, 1467 }, + { -1561, -3399, -5822, 211 }, + { -775, -1081, -4424, 2636 }, + { -1263, 25, -6378, -1392 }, + { -3476, -366, -5417, -1393 }, + { -3176, -1476, -4149, 1466 }, + { -2479, 518, -4448, -257 }, + { -2992, 158, -4660, -1279 }, + { -1320, -3872, -4479, 1147 }, + { -1475, -312, -5318, 539 }, + { -3527, -1679, -5860, -1681 }, + { -3397, -3438, -5593, 1866 }, + { -4089, -2439, -4763, 1275 }, + { -748, -4513, -4687, -48 }, + { -2166, -4531, -4691, -2856 }, + { -2385, -853, -6035, -627 }, + { -1194, -4091, -4472, -1963 }, + { -682, -3234, -4084, -3033 }, + { -3255, -5015, -5328, -12 }, + { -2313, -3436, -4601, -155 }, + { -2792, -1038, -6947, -2019 }, + { -1244, -1526, -5771, -1882 }, + { -4679, -3731, -5506, 283 }, + { -3062, -66, -3558, -758 }, + { -4895, -1187, 4751, 3728 }, + { -7600, -2752, 3320, 4613 }, + { -5703, -2975, 3944, 2659 }, + { -4972, -1257, -246, 2952 }, + { -4221, -2487, 1702, 4295 }, + { -2900, -1529, 2458, 4935 }, + { -5061, 407, 2416, 4050 }, + { -6931, -3478, 2761, 2213 }, + { -6037, -3921, 3192, 1866 }, + { -6113, -811, 2407, 3782 }, + { -5878, -1716, 1207, 3478 }, + { -5953, -2853, 2207, 2712 }, + { -6807, -3223, 2749, 3595 }, + { -3272, -3157, 1389, 3788 }, + { -5368, -1904, 1980, 5077 }, + { -7235, -1398, 3075, 4548 }, + { -4765, -3487, 2755, 2796 }, + { -7658, -4435, 2694, 2582 }, + { -6997, -4282, 456, 3832 }, + { -5563, -3115, -63, 3713 }, + { -4244, -4220, 1450, 2767 }, + { -3801, -2194, 190, 4303 }, + { -5458, -4119, 1958, 2274 }, + { -7300, -3469, 3514, 3193 }, + { -4594, -2067, 775, 4752 }, + { -3389, -1654, 1464, 5412 }, + { -4845, -3483, 964, 3437 }, + { -6007, -2818, 1666, 4659 }, + { -8709, -5007, 1757, 3287 }, + { -5833, -4389, 1025, 3171 }, + { -5788, -1780, 3944, 3661 }, + { -4430, -920, 1938, 4753 }, + { -7066, -1857, 4591, 4538 }, + { -3549, -513, 1427, 5317 }, + { -7517, -1220, 2883, 3049 }, + { -7605, -2687, 1874, 2735 }, + { -8718, -4035, 2676, 3730 }, + { -7990, -3907, 1185, 2607 }, + { -6058, -1744, 3349, 5157 }, + { -5954, 565, 3161, 3250 }, + { -6478, -612, 1930, 2271 }, + { -6535, -1445, -2, 1618 }, + { -8963, -4151, 1192, 4044 }, + { -7227, -3570, 1600, 4234 }, + { -4674, 79, 595, 3015 }, + { -3974, 430, 2727, 5137 }, + { -5299, 9, 3714, 4779 }, + { -6779, -2699, -8, 2436 }, + { -7016, -1145, 1293, 2310 }, + { -6955, -3312, 1534, 1801 }, + { -4025, 740, 1850, 4054 }, + { -9589, -3460, 4154, 5270 }, + { -4404, -1181, 4298, 5173 }, + { -7356, -4583, -18, 2644 }, + { -6516, -1235, 4439, 6234 }, + { -3453, -301, 4344, 4464 }, + { -4643, 1530, 3315, 4340 }, + { -4575, -2557, 3754, 3682 }, + { -3643, -3501, 2051, 2997 }, + { -5412, -2475, 2301, 1579 }, + { -5846, 259, 1360, 2348 }, + { -5258, -1358, 1050, 838 }, + { -5542, -219, 6377, 5750 }, + { -5713, -2952, 922, 899 }, + { -2049, -1135, 5206, 1033 }, + { -1693, -1886, 4835, -106 }, + { -2344, -3504, 4232, -13 }, + { -2475, -2334, 5043, 1126 }, + { -787, -2549, 3880, 2138 }, + { -3159, -2341, 4830, 2887 }, + { -1780, -1009, 6240, 2061 }, + { -4327, -3363, 2818, 886 }, + { -3376, -2743, 4104, 207 }, + { -3250, -4640, 2718, 1498 }, + { -382, -1075, 4382, 3460 }, + { -2416, -4168, 3530, 816 }, + { -1756, -2708, 4861, 622 }, + { -1879, -2097, 5156, 2889 }, + { -2496, -2418, 3722, 2671 }, + { -2717, -3252, 3341, 1944 }, + { -4063, -4091, 3306, 267 }, + { -3549, -3808, 3747, 842 }, + { -2635, 546, 5794, 1894 }, + { -1857, -1121, 4383, 3964 }, + { -2226, -2166, 3489, 3678 }, + { -3492, -660, 5323, 1063 }, + { -3033, -3130, 4382, 1828 }, + { -2703, -625, 6369, 2851 }, + { -1656, -2842, 4584, -528 }, + { -4781, -2622, 4390, 2097 }, + { -413, -2045, 5081, 3035 }, + { -3810, -2662, 4532, 1095 }, + { -3144, -1858, 5215, 1880 }, + { -3562, -1795, 4928, 670 }, + { -4800, -1509, 5189, 1859 }, + { -1085, -3832, 4169, 900 }, + { -1969, -3270, 2857, 2878 }, + { -4267, -4140, 3176, 1805 }, + { -5145, -3727, 3524, 1168 }, + { -1346, -1876, 5501, 1748 }, + { -4998, -2945, 3699, 338 }, + { -3458, -3096, 3406, -635 }, + { -1751, -3209, 3508, 395 }, + { -2507, 170, 5987, 705 }, + { -3756, -1072, 5647, 3536 }, + { -2870, -1439, 5026, 3212 }, + { -3913, -3225, 3669, 2144 }, + { -3739, 226, 5747, 764 }, + { -2052, -820, 5266, 3093 }, + { -3214, -3820, 2409, 2391 }, + { -4398, -2588, 3501, -218 }, + { -4484, -1763, 4180, -198 }, + { -3368, -1525, 4362, -134 }, + { -2407, 224, 4905, 3533 }, + { -1369, -2937, 4728, 1788 }, + { -4848, -1707, 4159, 851 }, + { -3454, -1749, 4281, 3230 }, + { -1990, -3853, 3487, 1735 }, + { -3117, 92, 6155, 4075 }, + { -2676, -2472, 4078, -589 }, + { -1547, -2012, 2626, 1835 }, + { -4275, -588, 4824, 725 }, + { -601, -2249, 3736, 3548 }, + { -4060, -61, 5333, 3097 }, + { -4303, 7, 6551, 3054 }, + { -5003, -1029, 5786, 3319 }, + { -2810, -728, 5392, 199 }, + { -1232, -200, 5228, 3121 }, + { 2621, 165, -6255, 298 }, + { 3669, 537, -6844, 1564 }, + { 1598, -1190, -6235, 2523 }, + { 2164, -32, -6894, 1383 }, + { 853, -1597, -6069, 1449 }, + { 1377, -1661, -5266, 108 }, + { 2660, 48, -5172, -517 }, + { 1903, -391, -5677, 1010 }, + { 3792, 206, -5274, -11 }, + { 1239, 2776, -2929, 2721 }, + { 4071, 149, -7259, 3125 }, + { 1436, -480, -6156, -196 }, + { 1373, -1960, -5005, 3122 }, + { 3413, -1271, -5176, 3283 }, + { 3060, -68, -6495, 2238 }, + { 2700, -2075, -4681, 91 }, + { 2928, -1728, -5168, 1858 }, + { 4424, 828, -4471, 88 }, + { 2672, -2604, -4038, 2753 }, + { 5223, -123, -6749, 2295 }, + { 4237, -420, -5538, 1353 }, + { 4744, -1281, -4097, 4708 }, + { 1103, -2764, -4751, 2024 }, + { 3747, -1913, -3911, 3960 }, + { 2470, -1416, -5542, 615 }, + { 4847, -1354, -5334, 1733 }, + { 5336, 88, -7593, 4007 }, + { 2388, -2880, -4807, 1037 }, + { 4495, 1391, -5685, -139 }, + { 5253, 1637, -6450, 1533 }, + { 1199, 795, -5515, 1261 }, + { 1397, -1259, -4252, 3838 }, + { 746, 70, -6640, 604 }, + { 1584, 166, -4972, 3072 }, + { 380, -999, -5397, 2267 }, + { 2974, 1707, -3242, 5360 }, + { 5202, -403, -5453, 2832 }, + { 3718, -1731, -4760, 714 }, + { 4150, -975, -4792, 61 }, + { 2925, -818, -4841, 15 }, + { 5301, 577, -4006, 3259 }, + { 5265, 1986, -5679, 3028 }, + { 3752, 1928, -4509, 3729 }, + { 3278, 1925, -6370, 1247 }, + { 5107, 1721, -4853, 3127 }, + { 3279, 2982, -2515, 4005 }, + { 4622, 668, -6204, 759 }, + { 6034, 317, -5763, 4818 }, + { -558, 57, -3785, 2817 }, + { 4476, 1616, -3965, 4536 }, + { 5953, 2056, -8215, 2715 }, + { 4387, 2613, -7463, 868 }, + { 5834, 1088, -4736, 4924 }, + { 6473, -856, -6991, 4172 }, + { 4959, -293, -5162, 76 }, + { 2731, -843, -6119, 3847 }, + { 3245, 1202, -6833, 616 }, + { 2553, 1383, -3829, 3859 }, + { 4332, 2099, -3480, 3622 }, + { 2110, 2683, -2728, 3990 }, + { 876, 1167, -3290, 3466 }, + { 3991, 1709, -2410, 4077 }, + { 5105, 939, -2584, 3256 }, + { 4719, 688, -1566, 3040 }, + { -3632, 4335, 1266, -3303 }, + { -4956, 3207, 1312, -2806 }, + { -4669, 2627, 2663, -2435 }, + { -4282, 3708, 2303, -3038 }, + { -4536, 2297, -175, -3350 }, + { -5234, 2503, -139, -880 }, + { -3978, 1512, 1092, -3619 }, + { -4519, 4649, 1363, -2455 }, + { -5118, 3132, 1961, -1577 }, + { -5196, 3379, -182, -1378 }, + { -6420, 4486, 2397, -1993 }, + { -5030, 5046, 1292, -1118 }, + { -4559, 2573, -927, -1406 }, + { -3501, 3730, 691, -4930 }, + { -4364, 2758, 1007, -3909 }, + { -4026, 2839, -1559, -2340 }, + { -5037, 4053, 836, -1571 }, + { -4727, 5136, 1110, -3588 }, + { -5245, 2799, -999, -2164 }, + { -4954, 1501, 422, -3963 }, + { -5994, 2726, 1462, -2833 }, + { -5621, 5159, 2038, -2512 }, + { -4991, 2291, 1917, -3151 }, + { -5469, 4382, -148, -2978 }, + { -5858, 1983, 807, -2720 }, + { -4709, 3556, 952, -467 }, + { -2489, 2362, 1714, -4230 }, + { -4717, 5004, -1180, -3672 }, + { -5914, 3653, 1359, -1317 }, + { -5506, 2995, 780, -1059 }, + { -5287, 3945, 2480, -2293 }, + { -3849, 4358, 322, -1770 }, + { -3911, 3570, 252, -3185 }, + { -3660, 5128, 158, -3719 }, + { -4599, 3277, -503, -2727 }, + { -3673, 3760, -1252, -3339 }, + { -5161, 2337, 388, -1943 }, + { -3529, 2216, 2156, -3080 }, + { -4309, 4331, 1808, -1460 }, + { -4782, 3820, 480, -2504 }, + { -4166, 3544, -378, -1567 }, + { -5572, 2466, -418, -2909 }, + { -6096, 2930, 119, -1878 }, + { -5963, 3554, 1011, -2233 }, + { -6433, 4335, 935, -2930 }, + { -5004, 3314, -1352, -3430 }, + { -6042, 3463, -1008, -3940 }, + { -4671, 2214, -640, -5040 }, + { -2795, 3759, 1412, -3803 }, + { -3647, 4436, 729, -515 }, + { -3594, 1033, 56, -4148 }, + { -2908, 3027, 2889, -3485 }, + { -3338, 2234, 313, -4285 }, + { -3825, 4497, -561, -2634 }, + { -6167, 3012, -48, -3149 }, + { -4828, 3515, -969, -4475 }, + { -5789, 2757, -539, -4173 }, + { -2452, 3067, 564, -4249 }, + { -4921, 1358, 1331, -2889 }, + { -3127, 4239, -1045, -1523 }, + { -4780, 2326, -1118, -3446 }, + { -3908, 5546, 152, -2622 }, + { -6972, 2976, 337, -2809 }, + { -4839, 4613, -35, -4077 }, + { -1408, 4822, -1149, -4997 }, + { -981, 4979, -912, -6304 }, + { -2098, 5689, -888, -2878 }, + { -3343, 4814, -657, -4434 }, + { -2461, 3601, -967, -4869 }, + { -2652, 3944, 87, -5520 }, + { -1104, 6076, 174, -6407 }, + { 355, 5370, -1721, -5869 }, + { 1242, 4497, -1107, -5091 }, + { -89, 4002, -1491, -5182 }, + { 1059, 5693, -1591, -4905 }, + { 1323, 4682, -2078, -4768 }, + { 818, 3996, -549, -5468 }, + { -287, 4529, 929, -5543 }, + { -919, 5519, -2791, -2844 }, + { -1407, 5679, -3289, -3974 }, + { -189, 6530, -3547, -4002 }, + { -900, 7039, -3371, -4855 }, + { -2983, 7211, -363, -4835 }, + { -814, 6503, -104, -5106 }, + { -2386, 6896, 809, -4919 }, + { 845, 4492, 352, -6621 }, + { -1998, 7237, -1646, -4231 }, + { -3380, 6251, 471, -4577 }, + { -1908, 7059, 84, -5726 }, + { -340, 6346, -803, -6265 }, + { -2279, 5834, -47, -4633 }, + { -1532, 5286, -1748, -1901 }, + { -2757, 6188, -453, -3415 }, + { -1255, 6405, -2043, -6357 }, + { 918, 5581, -121, -5667 }, + { 1840, 5336, -821, -5034 }, + { -2475, 4992, -1825, -3104 }, + { -2413, 5606, -1789, -4298 }, + { 132, 5128, -2389, -4442 }, + { 223, 6400, -2653, -4742 }, + { -673, 5012, 680, -4582 }, + { -1657, 6624, -349, -3596 }, + { -755, 6289, -1860, -3978 }, + { -572, 6894, -1946, -5207 }, + { -1141, 4756, -2665, -5586 }, + { -1073, 4269, -431, -4030 }, + { 186, 5761, 916, -5868 }, + { -1907, 4836, 1017, -5106 }, + { -963, 3363, -1248, -6348 }, + { -3262, 4774, -1818, -5858 }, + { 847, 3812, -2538, -4302 }, + { -1223, 5903, 1360, -5479 }, + { -1094, 6923, -1244, -2381 }, + { 267, 6276, -709, -2846 }, + { -157, 5840, 1124, -4266 }, + { 889, 3206, -910, -5305 }, + { -1736, 3344, 582, -4838 }, + { -2357, 5676, -2695, -6277 }, + { -1916, 6901, -986, -5397 }, + { -3062, 6028, -695, -5687 }, + { 1836, 3566, -1357, -5226 }, + { -2176, 4938, 646, -3872 }, + { -2199, 3055, -208, -6124 }, + { -236, 3032, -821, -5325 }, + { -3989, 7277, -565, -3899 }, + { -595, 4362, 74, -5975 }, + { 684, 5874, -841, -4424 }, + { -2731, 6305, -2389, -5465 }, + { -5775, 1325, -56, -2528 }, + { -7029, -534, -1890, -3278 }, + { -5798, -15, -2734, -2210 }, + { -5504, -1198, -353, -3659 }, + { -5079, 960, -894, -4336 }, + { -6073, -36, -133, -3014 }, + { -5782, -259, -1025, -3986 }, + { -6843, 1262, -807, -1639 }, + { -5263, -918, -3290, -579 }, + { -4840, 461, -2158, -533 }, + { -6014, -50, -620, 504 }, + { -5843, 241, -1359, -282 }, + { -5898, 577, 769, -3271 }, + { -6833, -946, -466, -3347 }, + { -6026, 1459, -512, -729 }, + { -7361, 747, -388, -1110 }, + { -6391, 2142, -1160, -2513 }, + { -6995, 304, 498, -2673 }, + { -6757, 679, -386, -433 }, + { -5222, 1688, -1093, -1032 }, + { -5019, 575, 184, -3627 }, + { -4237, 628, -3507, -1243 }, + { -7479, -456, -1722, -1486 }, + { -6464, 713, -1273, -1153 }, + { -6255, 1682, -606, -3607 }, + { -7033, 1497, -71, -1955 }, + { -6694, 1556, -1721, -3214 }, + { -6114, -356, 813, -2575 }, + { -5308, 632, -1851, -1636 }, + { -5742, -911, -1733, 383 }, + { -6083, -387, -2313, -879 }, + { -6535, -530, -1505, -2083 }, + { -4896, 1223, -2750, -1816 }, + { -6392, -463, -3247, -2093 }, + { -5373, 1264, -2706, -3042 }, + { -3894, -1390, -1020, -891 }, + { -6179, 1168, -1966, -1922 }, + { -5162, 1668, -1617, -1916 }, + { -6453, 920, -1169, -2432 }, + { -6130, 2005, -536, -1519 }, + { -6552, -98, -518, -1938 }, + { -7528, 355, -1101, -1772 }, + { -5745, 610, -247, -1360 }, + { -7003, 177, -2064, -1958 }, + { -6956, -570, -2220, -4225 }, + { -7830, 791, -1394, -2774 }, + { -7634, 480, -3171, -4224 }, + { -7913, 1154, -350, -2381 }, + { -5063, 1704, -1804, -2977 }, + { -4887, -524, -2703, 188 }, + { -5551, 406, -1620, -3063 }, + { -7109, 1342, 381, -3021 }, + { -6846, 631, -458, -3398 }, + { -4606, -605, 11, -3930 }, + { -8134, -225, -1738, -2648 }, + { -7043, 402, -2734, -3059 }, + { -7417, 1825, -2545, -4389 }, + { -6971, -236, -1031, -665 }, + { -5752, 2111, -1632, -3808 }, + { -7660, -78, -624, -3135 }, + { -6358, 619, -1951, -3911 }, + { -8134, 408, -1935, -3695 }, + { -6335, 1911, -2368, -4505 }, + { -7116, 2163, -344, -2753 }, + { 2357, 4488, 2220, -5682 }, + { 1385, 3206, 2300, -5305 }, + { 1419, 2557, 5203, -3516 }, + { 262, 4315, 3920, -1847 }, + { 3316, 3187, 1612, -5609 }, + { 1729, 2350, 1673, -6068 }, + { 1603, 6126, 1467, -2839 }, + { -1339, 3316, 3691, -3530 }, + { -563, 4618, 3180, -4548 }, + { 463, 4624, 3111, -5614 }, + { 1246, 5455, 3356, -5720 }, + { 480, 2149, 5422, -2893 }, + { 1768, 4827, 913, -5579 }, + { -149, 5381, 4366, -3297 }, + { 985, 3672, 2644, -92 }, + { -258, 2911, 5817, -2213 }, + { 3428, 3289, 3351, -3541 }, + { -666, 3295, 4727, -2869 }, + { 35, 6641, 4160, -4052 }, + { 623, 6787, 3156, -4560 }, + { 2654, 4360, 4676, -4632 }, + { 1386, 5246, 4834, -4497 }, + { 3488, 4574, 3856, -5946 }, + { 383, 4481, 4168, -4110 }, + { 1753, 3652, 4288, -3326 }, + { 1344, 4905, 2508, -4660 }, + { 1580, 4106, 3104, -2224 }, + { 2027, 5038, 1683, -1554 }, + { 446, 3699, 5872, -3013 }, + { 4637, 4087, 3578, -5018 }, + { 2629, 3560, 5331, -4900 }, + { 1527, 6674, 2523, -4131 }, + { -1437, 2804, 2528, -4464 }, + { -229, 3355, 2016, -5537 }, + { 3666, 3418, 4374, -4581 }, + { 1192, 3799, 923, -6596 }, + { 2040, 2956, 448, -5322 }, + { 2468, 5768, 4029, -5869 }, + { 3438, 6516, 3529, -6667 }, + { 2737, 5495, 680, -5535 }, + { 3896, 5727, 1801, -4958 }, + { 4988, 4957, 3592, -6518 }, + { -542, 4416, 5794, -2787 }, + { 4136, 4354, 2064, -4696 }, + { 3067, 5936, 1207, -3396 }, + { 2789, 4966, 2405, -3854 }, + { 1731, 3270, 3251, -1063 }, + { 1767, 5537, 2084, -2349 }, + { 465, 3116, 4532, -837 }, + { 1499, 2627, 4610, -2212 }, + { 122, 3095, 3642, -3552 }, + { 2542, 2866, 2705, -6402 }, + { 3134, 4323, 698, -4785 }, + { 731, 1859, 3112, -5242 }, + { 2553, 2980, 3241, -4846 }, + { 1329, 5310, 1607, -6624 }, + { 2468, 1858, 3476, -1034 }, + { -172, 4996, 2000, -5562 }, + { 2621, 4220, 1574, -3386 }, + { -333, 1832, 3362, -4117 }, + { 2169, 6762, 3065, -6225 }, + { 2844, 5528, 3223, -4765 }, + { 526, 5175, 1644, -4267 }, + { 2922, 4426, 2414, -2610 }, + { 452, 1399, -4516, -2636 }, + { 2872, 1720, -4667, -1435 }, + { 1279, 702, -5424, -1984 }, + { 2187, 870, -5021, -1341 }, + { 583, -144, -4628, -2464 }, + { 3, 2237, -5284, -2827 }, + { -19, 1005, -5460, -1819 }, + { 2897, 2084, -5885, -515 }, + { -400, 3370, -5527, -2947 }, + { 1505, 2593, -5518, -1802 }, + { 1341, 4534, -5094, -1899 }, + { 3241, 3670, -5493, -1252 }, + { -1287, 921, -5994, -1675 }, + { 627, 408, -6652, -364 }, + { -260, 1127, -4849, -3247 }, + { 371, 3400, -5976, -2285 }, + { 1533, 1566, -6373, -610 }, + { 2462, 4274, -6184, -1254 }, + { 1782, 3363, -6222, -1381 }, + { 572, 4650, -5673, -2754 }, + { 2674, 3414, -4460, -2154 }, + { 3614, 3820, -6883, -398 }, + { 1136, -1, -5511, -1112 }, + { -1773, 1137, -5647, -2377 }, + { -753, 2104, -6085, -2565 }, + { -204, 3025, -4731, -1418 }, + { -1486, 1438, -4380, -216 }, + { 302, 858, -5786, -264 }, + { 3486, 1495, -5234, -783 }, + { 888, 2327, -3423, -3720 }, + { -259, 772, -6596, -1311 }, + { -1197, 2073, -5174, -1826 }, + { 1500, 3470, -4462, -2645 }, + { 3072, 1960, -3277, -2264 }, + { 1841, 952, -4324, -2340 }, + { 1994, 2200, -3940, -2923 }, + { -1782, 1699, -4667, -1075 }, + { -1464, 2906, -3468, -375 }, + { 366, 2380, -3747, 1467 }, + { -545, 1645, -4619, 376 }, + { 1724, 2350, -2374, -3512 }, + { 3184, 2628, -2996, -3275 }, + { 734, 2010, -6239, -1479 }, + { 524, 3756, -4496, -3263 }, + { 1492, 3570, -3494, -3600 }, + { -932, 618, -5389, -2894 }, + { -133, 2161, -4083, -3267 }, + { 786, 774, -3279, -3731 }, + { 1078, 803, -3843, -3007 }, + { -332, 3405, -3347, 40 }, + { -17, 6, -4005, -3690 }, + { -189, 4372, -4488, -2561 }, + { -450, 3846, -3790, -1370 }, + { 362, 2212, -5272, -15 }, + { -1529, 791, -6802, -2296 }, + { 2145, 4241, -4474, 376 }, + { 1813, 2426, -2932, -2726 }, + { -542, 4557, -3140, -1080 }, + { 1192, 3784, -4371, -20 }, + { 2784, 5188, -6399, -1394 }, + { 431, 4561, -3673, -1398 }, + { 1382, 3096, -4083, 1253 }, + { 1209, 4224, -2930, 1500 }, + { 2798, 2684, -6676, -606 }, + { -2396, 1510, -5381, -2713 }, + { -2625, 2542, -4032, -2880 }, + { -1231, 3967, -4098, -2886 }, + { -1393, 2374, -3862, -4525 }, + { -2495, 1665, -1637, -5445 }, + { -3854, 1759, -1750, -4944 }, + { -2373, 1668, -2856, -6251 }, + { -2668, 1981, -886, -4557 }, + { -2927, 4427, -3451, -6172 }, + { -1925, 2596, -4696, -2527 }, + { -3202, 2847, -3928, -5896 }, + { -3332, 1665, -5025, -3412 }, + { -3212, 3115, -4155, -4062 }, + { -1013, 3205, -5133, -3751 }, + { -2022, 4595, -3947, -5611 }, + { -3556, 1755, -3715, -2300 }, + { -1784, 4114, -2723, -1773 }, + { -3586, 4081, -2733, -4942 }, + { -1608, 3685, -4154, -4573 }, + { -3368, 4042, -4452, -6227 }, + { -1407, 3881, -5729, -3719 }, + { -2751, 3281, -5077, -4999 }, + { -3791, 2410, -4906, -5288 }, + { -730, 2303, -4217, -3755 }, + { -1812, 2311, -5492, -3709 }, + { -610, 4336, -3915, -3783 }, + { -2841, 4337, -4278, -4430 }, + { -1662, 4666, -4661, -3964 }, + { -589, 5209, -4923, -3682 }, + { -4155, 2234, -4076, -4218 }, + { -3951, 2770, -2665, -2805 }, + { -2302, 3228, -3717, -1908 }, + { -3129, 4373, -2264, -2851 }, + { -447, 1363, -3578, -4323 }, + { -2648, 4237, -3159, -3071 }, + { -4072, 3241, -3541, -4605 }, + { -4507, 3458, -2339, -3838 }, + { -1646, 997, -4926, -3970 }, + { -3025, 1614, -3940, -1242 }, + { -1337, 1756, -3163, -5529 }, + { -3203, 1865, -3282, -4354 }, + { -1646, 2118, -2203, -6018 }, + { 174, 1871, -2707, -4639 }, + { -2607, 1485, -4778, -4750 }, + { -2199, 3991, -3134, -4879 }, + { -2962, 3323, -2816, -2419 }, + { -5286, 2495, -4548, -5395 }, + { -2810, 3710, -2274, -4211 }, + { -330, 3006, -2993, -4678 }, + { -1187, 2411, -2743, -5196 }, + { -664, 4033, -3101, -5641 }, + { -1458, 3602, -2816, -5371 }, + { -4116, 4923, -3321, -5630 }, + { -4165, 2528, -2592, -4798 }, + { -2759, 3080, -2333, -5719 }, + { -5157, 3011, -5526, -6348 }, + { -3095, 2126, -5881, -4234 }, + { -4377, 3849, -3600, -6099 }, + { -1994, 4947, -5235, -4753 }, + { -1067, 600, -3258, -5133 }, + { -4992, 3302, -2208, -5051 }, + { -3377, 2981, -1655, -4815 }, + { -3325, 2446, -1787, -6116 }, + { -2341, 2737, -3240, -6347 }, + { -2258, -3732, 3710, -1235 }, + { -1558, -3849, 2694, -3012 }, + { -599, -4837, 3050, -2951 }, + { -2246, -5433, 2798, -1910 }, + { -2255, -4989, 3260, 270 }, + { -3026, -5353, 2693, -1036 }, + { -1151, -6097, 1097, -3782 }, + { -3391, -6012, 2130, -1303 }, + { -2850, -4422, 3375, -480 }, + { -1138, -3779, 1491, -4162 }, + { -551, -3892, 3787, -2082 }, + { -3221, -3676, 3144, -1202 }, + { -3023, -5196, 2650, 605 }, + { -1756, -5729, 2646, 321 }, + { -2693, -4409, 494, -4797 }, + { -1913, -4573, 3372, -1730 }, + { -1277, -3604, 4061, -993 }, + { -420, -4993, 1351, -4796 }, + { -3052, -5333, 1435, -1242 }, + { -602, -5034, 3869, -1141 }, + { -2436, -4680, 1665, -3019 }, + { -2657, -3658, 1459, -3391 }, + { -1220, -6246, 2749, -525 }, + { -3838, -4844, 2265, -1735 }, + { -1247, -5679, 3356, -1417 }, + { -917, -5448, 3342, 105 }, + { -1756, -6839, 2276, -2350 }, + { -412, -5206, 1764, -3539 }, + { -1439, -6915, 1442, -3750 }, + { -1381, -4439, 3863, -282 }, + { -3482, -4953, 2726, -336 }, + { -1376, -5931, 1714, -1987 }, + { -1716, -4405, 2608, 105 }, + { -1590, -5191, 2652, -2704 }, + { -2149, -6442, 2453, -1263 }, + { -3426, -3832, 2334, -1829 }, + { -2747, -5948, 2362, -173 }, + { -2435, -3267, 2966, -1710 }, + { -3979, -4282, 2705, -775 }, + { -356, -4238, 2544, -4343 }, + { -1363, -6471, 2817, -1836 }, + { -2878, -5117, 218, -3149 }, + { -3539, -5196, 1710, -2356 }, + { -2888, -4537, 2746, -1701 }, + { -1870, -4439, 1496, -4121 }, + { -1486, -3388, 3349, -2145 }, + { -3333, -4138, 1467, -2876 }, + { -345, -5340, 1012, -1190 }, + { -1672, -4992, 2289, -1029 }, + { -2146, -5528, 3038, -635 }, + { -316, -3656, 3426, -3152 }, + { -2695, -5812, 2336, -2050 }, + { -2067, -6052, 737, -3258 }, + { -2664, -4205, -350, -1266 }, + { -617, -5406, 80, -4853 }, + { -2418, -3825, 1853, -1326 }, + { -1961, -4339, 583, -4315 }, + { -1495, -5141, -133, -5205 }, + { -3208, -6440, 1691, -2069 }, + { -2632, -3633, 2325, -2761 }, + { -2624, -5670, 1252, -3676 }, + { -3687, -5608, 687, -2833 }, + { -3320, -5707, 16, -3877 }, + { -2738, -6112, 84, -5135 }, + { 2277, -5661, 3076, 843 }, + { 1555, -5769, 2821, -5236 }, + { 536, -6381, 603, -4910 }, + { 734, -4609, 3314, -4092 }, + { 1836, -4547, 3267, -4322 }, + { -13, -5976, 3752, -1607 }, + { 1423, -6318, 2336, 398 }, + { 365, -7779, 1498, -534 }, + { 2104, -8366, 2946, -1345 }, + { 143, -5545, 1898, -3756 }, + { 655, -6852, 1430, 148 }, + { 4, -6653, 2397, -59 }, + { 2346, -5996, 4562, -934 }, + { 1229, -7104, 2963, -598 }, + { -528, -7048, 2887, -1790 }, + { 1451, -6857, 3900, -1637 }, + { 554, -6018, 3336, 9 }, + { 3278, -5758, 4034, 129 }, + { 3541, -7145, 4905, -1575 }, + { 2339, -6907, 3464, -301 }, + { 2775, -7301, 1667, -3894 }, + { 539, -7887, 991, -4156 }, + { 2115, -7421, 3131, -3075 }, + { 2803, -8546, 2564, -5836 }, + { 2869, -5833, 1620, -4561 }, + { 2591, -7281, 3215, -4719 }, + { -1228, -8477, 706, -4782 }, + { 1967, -5243, 4813, -1940 }, + { 701, -7010, 2273, -3893 }, + { 915, -8470, 1918, -5620 }, + { -94, -6715, 156, -3873 }, + { 1074, -5607, 4389, -1017 }, + { 2739, -6551, 1227, -3521 }, + { 725, -7835, 2701, -1291 }, + { -493, -7475, 2263, -1075 }, + { -412, -6508, 2984, -744 }, + { 665, -5451, 3725, -2692 }, + { 1499, -8129, 3564, -2072 }, + { 2870, -6333, 4487, -2108 }, + { 706, -5007, 3911, -152 }, + { -482, -8660, 1483, -2900 }, + { 2481, -6596, 2518, -1715 }, + { 1403, -6414, 1398, -5387 }, + { 652, -6267, 583, -5942 }, + { 694, -7540, 646, -6272 }, + { 2275, -7614, 256, -5015 }, + { 1416, -9727, 1900, -3153 }, + { 2760, -6433, 3875, -3771 }, + { 2325, -11196, 2182, -5155 }, + { 1223, -11061, 1377, -5097 }, + { 108, -10603, 307, -4952 }, + { -118, -8268, 1650, -1572 }, + { 1839, -7943, 1755, -612 }, + { 2501, -9056, 981, -2969 }, + { 2902, -8476, 1491, -5780 }, + { 1995, -11175, 1585, -3643 }, + { 696, -8212, 828, -2474 }, + { 1526, -8649, 1380, -1210 }, + { 461, -7253, 3222, -2229 }, + { 2966, -8641, 4121, -3271 }, + { 833, -6039, 2361, -1086 }, + { 3565, -7312, 1980, -5427 }, + { 2850, -8671, 3760, -1846 }, + { 2643, -7281, 2163, -173 }, + { 3463, -3706, -3132, -923 }, + { 1315, -3825, -3443, 2 }, + { 2594, -4083, -3815, 670 }, + { 1826, -4291, -2741, -155 }, + { 868, -3749, -4175, -298 }, + { 2008, -4237, -3897, -517 }, + { 1242, -3493, -4335, -1335 }, + { -88, -4142, -3390, -1529 }, + { 2176, -3488, -3822, -975 }, + { 1706, -5188, -3415, -637 }, + { 2717, -6159, -2333, -882 }, + { 1276, -3978, -4361, 537 }, + { 2471, -5556, -2866, -208 }, + { 799, -4673, -4086, 56 }, + { 1901, -4786, -3533, 270 }, + { 3036, -3902, -3606, -333 }, + { 2249, -3317, -4319, -144 }, + { 2594, -4207, -2105, -2930 }, + { 4008, -4774, -2626, -902 }, + { 1038, -3659, -3496, -2454 }, + { 2725, -3597, -3298, -1535 }, + { 1662, -5803, -2813, 175 }, + { 705, -3757, -3441, -1484 }, + { 1860, -5987, -2821, -886 }, + { 3786, -4918, -2199, -1929 }, + { 3683, -4235, -2547, -1287 }, + { 2531, -4896, -2956, -1593 }, + { 1005, -5585, -3324, -180 }, + { 1625, -5229, -1756, -3642 }, + { 1494, -5041, -2989, -2685 }, + { 2718, -4655, -3224, -867 }, + { 2374, -6640, -1745, -2975 }, + { 2133, -6436, -2477, -1499 }, + { 1833, -4418, -3523, -1512 }, + { 1128, -4910, -2658, -1106 }, + { 689, -4777, -2831, -2085 }, + { 3593, -5280, -2627, -315 }, + { 3264, -3771, -2673, -1861 }, + { 3202, -5602, -2409, 402 }, + { 552, -4618, -2221, -3002 }, + { 3095, -5356, -2666, -1083 }, + { 3401, -4609, -3146, 45 }, + { 3051, -4662, -2192, -2232 }, + { 2798, -5552, -2462, -1941 }, + { 2354, -5815, -2223, -2619 }, + { 192, -3708, -2807, -2658 }, + { 1886, -4226, -1862, -3529 }, + { 2526, -3976, -2819, -2332 }, + { 1577, -3870, -2711, -2806 }, + { 1288, -5588, -3382, -1403 }, + { 2711, -5399, -1564, -3253 }, + { 1459, -5492, -2222, -322 }, + { 2823, -5091, -2886, 776 }, + { 3559, -5821, -2109, -1360 }, + { 1587, -6331, -2760, -1909 }, + { 2139, -5213, -2874, -2120 }, + { 1318, -4337, -3695, -2098 }, + { 821, -4471, -1849, -565 }, + { 3329, -4782, -1725, -89 }, + { 582, -4914, -4105, -1119 }, + { 417, -4144, -4072, -2529 }, + { -199, -3803, -2765, -4042 }, + { 2731, -4283, -2143, 1 }, + { 2911, -6187, -1951, -2116 }, + { 1573, -6094, -493, -2838 }, + { 2081, -6927, -864, -3211 }, + { 1058, -7826, 79, -364 }, + { 3147, -5570, -684, -978 }, + { 3572, -5856, 1060, 1824 }, + { 1143, -6702, -1478, 338 }, + { 2341, -7220, -88, 260 }, + { 3639, -6861, 668, 815 }, + { 2227, -6268, -1706, 446 }, + { 3390, -6082, -353, 1302 }, + { 1123, -7556, -1237, -430 }, + { 1729, -7742, 729, -218 }, + { 1457, -6774, 587, 579 }, + { 505, -6919, -569, 371 }, + { 1106, -7245, 78, 158 }, + { 2755, -6745, -1122, 338 }, + { 3069, -6040, -1415, 986 }, + { 2174, -7064, -1430, -283 }, + { 1390, -8626, -446, -3031 }, + { 3534, -6890, -431, 547 }, + { 2267, -9618, 475, -2994 }, + { 3672, -7673, 75, -115 }, + { 2131, -7560, -1206, -750 }, + { 2972, -7477, -685, -262 }, + { 1604, -6637, -672, 699 }, + { 1666, -7577, -577, -240 }, + { 1591, -6554, -2158, -94 }, + { 2348, -6286, -353, 1123 }, + { 2017, -8810, -412, -1805 }, + { 2892, -6713, -1765, -554 }, + { 2500, -6828, -1995, -1197 }, + { 3877, -6639, -224, -1655 }, + { 2392, -7872, -91, -333 }, + { 3562, -7370, -532, -2836 }, + { 2552, -7614, 164, -1805 }, + { 990, -6104, 218, 438 }, + { 910, -7861, 312, -1195 }, + { 1472, -6327, 372, -640 }, + { 1576, -7143, -1983, -843 }, + { 422, -7625, -457, -278 }, + { 1797, -8532, 405, -1011 }, + { 1088, -7396, -238, -2277 }, + { 3209, -6753, -1431, -2072 }, + { 2617, -6839, 100, -2573 }, + { 2575, -8573, -387, -3188 }, + { 3618, -6971, -1190, -321 }, + { 2205, -7361, -1695, -2008 }, + { 2985, -6297, 1464, 1179 }, + { 2804, -7310, 1053, 338 }, + { 1362, -6074, -1163, -840 }, + { 3336, -6325, -1794, 21 }, + { 2836, -8109, 818, -329 }, + { 2791, -5879, 560, 1546 }, + { 2392, -6064, 135, 100 }, + { 1838, -6194, 596, 1085 }, + { 1926, -7515, -414, -4901 }, + { 3225, -7298, -1202, -1189 }, + { 3960, -7558, -659, -719 }, + { 3442, -6647, -1692, -1095 }, + { 3381, -6441, 262, -886 }, + { 1431, -8150, -1186, -1406 }, + { 340, -8498, -150, -899 }, + { 3004, -8149, -260, -953 }, + { 2749, -6611, 563, 873 }, + { -6647, -1325, -4517, -4691 }, + { -6005, -1657, -4089, -3797 }, + { -3157, 588, -5213, -3068 }, + { -3311, -1425, -6329, -3726 }, + { -5866, -819, -3857, -2744 }, + { -5001, -1799, -1075, -4621 }, + { -5330, -2650, -2672, -4664 }, + { -4930, -539, -2363, -4010 }, + { -2984, 10, -3863, -5749 }, + { -1055, -2106, -3713, -4267 }, + { -5476, -502, -4279, -6504 }, + { -5231, -1543, -5018, -6425 }, + { -5134, -363, -3165, -5109 }, + { -3953, -771, -4107, -6393 }, + { -2159, -563, -3652, -5342 }, + { -3888, -2321, -919, -5057 }, + { -1236, -597, -4235, -4193 }, + { -4053, 675, -3083, -6174 }, + { -2793, -1089, -5396, -3460 }, + { -3000, -44, -2209, -6575 }, + { -3336, -1531, -4313, -5160 }, + { -2127, 128, -4851, -3692 }, + { -3321, 136, -2067, -5660 }, + { -5215, 1404, -4374, -4356 }, + { -2747, 400, -6340, -3691 }, + { -3926, -599, -5361, -5006 }, + { -2875, -2592, -5143, -4092 }, + { -4991, -1958, -5322, -4891 }, + { -4965, -1318, -6652, -5333 }, + { -4920, -1691, -3388, -5561 }, + { -3644, -3354, -2688, -5982 }, + { -5076, -919, -4563, -2984 }, + { -6114, 250, -3884, -3915 }, + { -4014, 744, -3973, -1924 }, + { -5543, -1041, -5557, -3847 }, + { -4711, -1352, -5649, -2603 }, + { -3362, 775, -5305, -4879 }, + { -5001, 107, -3554, -2888 }, + { -6258, -1651, -6356, -6566 }, + { -4529, 407, -5003, -3865 }, + { -5154, 550, -5278, -5465 }, + { -4195, -467, -1894, -3129 }, + { -5022, 1127, -3349, -3314 }, + { -6075, 1250, -4313, -5641 }, + { -2677, -2283, -2312, -5903 }, + { -4113, 193, -1195, -4833 }, + { -3940, -1048, -1389, -5079 }, + { -3703, 917, -4043, -4451 }, + { -3366, -4231, -1534, -5488 }, + { -3326, -3583, -2091, -4903 }, + { -5144, 1254, -2532, -4949 }, + { -5982, -870, -2545, -4555 }, + { -3925, -157, -5367, -2281 }, + { -6419, -746, -5668, -4371 }, + { -5787, 518, -7096, -5805 }, + { -4258, 954, -6453, -4321 }, + { -4771, -695, -4158, -1639 }, + { -7078, -760, -5195, -5877 }, + { -7348, 83, -4101, -4586 }, + { -2430, 184, -2874, -1679 }, + { -2284, -3943, -2924, -5034 }, + { -1804, -1785, -3002, -4710 }, + { -4399, -2772, -1815, -4637 }, + { -6340, -2626, -2824, -5191 }, + { -4998, -5168, -3480, 1905 }, + { -3958, -5492, -1599, 1579 }, + { -2471, -3755, -276, 3182 }, + { -3033, -5779, -1063, 1554 }, + { -2936, -4829, -1290, 2386 }, + { -1835, -5073, -3051, 1299 }, + { -1724, -3771, -3935, 2324 }, + { -5070, -2550, -3692, 768 }, + { -4326, -5333, -297, 1878 }, + { -3472, -5619, -3094, 992 }, + { -3027, -4384, -3038, 2265 }, + { -3201, -5332, 67, 2200 }, + { -1681, -4373, -1947, 2461 }, + { -3221, -3329, -4238, 2564 }, + { -1262, -2968, -2915, 3227 }, + { -3419, -1878, -3373, 2110 }, + { -2244, -5583, -2012, 1288 }, + { -1971, -5266, -990, 1812 }, + { -2975, -2778, -452, 4063 }, + { -2198, -1165, -3298, 2965 }, + { -4782, -4894, -4767, 664 }, + { -6002, -3950, -2806, 2025 }, + { -3142, -3162, -2859, 3295 }, + { -3262, -3340, -4123, 1596 }, + { -4014, -3918, -1955, 3361 }, + { -1700, -3463, -1346, 3449 }, + { -4245, -4445, -4743, 1644 }, + { -4180, -3969, -401, 3281 }, + { -2782, -5240, -4117, 1156 }, + { -5744, -4040, -1439, 3470 }, + { -5063, -4663, -323, 3172 }, + { -4531, -3319, -844, 3988 }, + { -6226, -5125, -2064, 2976 }, + { -3115, -3267, -1531, 3898 }, + { -4628, -4421, -2864, 2808 }, + { -4559, -2989, -3442, 2024 }, + { -1775, -4487, -656, 2477 }, + { -2664, -1865, -1884, 4081 }, + { -1828, -2575, -3894, 3378 }, + { -6441, -3677, -2025, 1677 }, + { -4141, -2156, -1191, 3474 }, + { -4802, -1623, -1727, 2160 }, + { -5474, -2745, -1475, 2498 }, + { -3664, -1056, -1975, 2491 }, + { -4672, -3062, -2235, 2933 }, + { -4205, -5960, -2849, 1517 }, + { -4995, -5708, -1739, 1805 }, + { -4892, -6080, -4793, 872 }, + { -4270, -4172, -4263, 2185 }, + { -4687, -1470, -2905, 1023 }, + { -6446, -5017, -3919, 1000 }, + { -6046, -5538, -3943, 2006 }, + { -6028, -3750, -3953, 771 }, + { -5959, -4582, -5024, 824 }, + { -5818, -2576, -2249, 1326 }, + { -5659, -5345, -1119, 2500 }, + { -3346, -4155, 606, 2749 }, + { -5680, -4827, -2501, 1838 }, + { -6193, -2543, -1295, 840 }, + { -6871, -4925, -3512, 1801 }, + { -5605, -1788, -1895, 779 }, + { -3922, -5712, -4644, 510 }, + { -4745, -3869, -4533, 99 }, + { -2984, -4907, -399, 1497 }, + { 1847, -478, 3061, -5812 }, + { 4450, -1116, 3609, -6570 }, + { 3139, 99, 3007, -5532 }, + { 2590, -3782, 3138, -4770 }, + { 1881, 1204, 5778, -3404 }, + { 3631, 2060, 5566, -5038 }, + { 3461, 1961, 5167, -3800 }, + { 2947, 273, 4536, -4389 }, + { 4453, -1730, 5788, -4370 }, + { 4032, 1805, 2666, -4534 }, + { 3487, -944, 2313, -6028 }, + { 1313, 34, 4210, -4067 }, + { 5632, -1502, 5825, -5855 }, + { 7736, -547, 4879, -5476 }, + { 4906, -1512, 4760, -5760 }, + { 3843, 447, 1091, -4958 }, + { 2982, -1135, 5442, -4386 }, + { 3579, 271, 3031, -6770 }, + { 3932, -211, 4688, -5507 }, + { 4411, 1720, 2387, -5584 }, + { 5379, -479, 4575, -6280 }, + { 3613, -362, 2012, -4885 }, + { 3744, -2013, 4493, -5073 }, + { 5693, 109, 4379, -3362 }, + { 5475, -621, 5317, -3985 }, + { 6411, -673, 5708, -4752 }, + { 4933, -796, 7262, -4290 }, + { 2804, 444, 6276, -3655 }, + { 4120, -517, 6078, -4531 }, + { 5119, 841, 3486, -3910 }, + { 4738, 1539, 3525, -2970 }, + { 5086, 370, 5895, -5640 }, + { 4235, 2716, 4589, -5044 }, + { 3691, 682, 6199, -4700 }, + { 6111, -570, 6271, -6528 }, + { 2611, 1277, 3756, -4802 }, + { 4395, 970, 3807, -5879 }, + { 5225, 2299, 3242, -4333 }, + { 5144, 1778, 4946, -5545 }, + { 2989, -3016, 3247, -5495 }, + { 2983, 920, 2071, -6059 }, + { 5270, -903, 4434, -2350 }, + { 6415, -585, 3970, -3554 }, + { 3866, -197, 5216, -2884 }, + { 3767, -1298, 6702, -3315 }, + { 6299, 2620, 5284, -6824 }, + { 6654, 646, 3653, -4927 }, + { 4770, 3047, 5160, -6287 }, + { 5364, 434, 2919, -5207 }, + { 2998, 1344, 4801, -2456 }, + { 3896, 1013, 3773, -1864 }, + { 2115, 655, 2999, -6344 }, + { 5170, -981, 2849, -4464 }, + { 2735, -2159, 2717, -5776 }, + { 2430, -1952, 4392, -4559 }, + { 6143, -1180, 3659, -4746 }, + { 4978, -1483, 1726, -4875 }, + { 3486, -2383, 3306, -4301 }, + { 1434, -1372, 4171, -4770 }, + { 3354, -2627, 1525, -5093 }, + { 6790, 2386, 3995, -5909 }, + { 1475, -2674, 3451, -4204 }, + { 1999, -3494, 3693, -5556 }, + { 4764, -2848, 2856, -5589 }, + { -3677, 5131, 2827, -2934 }, + { -2844, 7078, 2852, -3580 }, + { -3902, 6434, 4118, -1911 }, + { -1769, 7530, 3492, -3541 }, + { -1937, 5679, -447, -1127 }, + { -2456, 4680, 4196, -2407 }, + { -2778, 8241, 1698, -4288 }, + { -2876, 6104, 5182, -2387 }, + { -2802, 7341, 4463, -2938 }, + { -1025, 6267, 4752, -3201 }, + { -2349, 5413, 2041, -3794 }, + { -2252, 8225, 2856, -4269 }, + { -1465, 4967, 4976, -2500 }, + { -636, 7565, 3517, -4233 }, + { -1905, 5618, 3904, -2942 }, + { -302, 6816, 3343, -3316 }, + { -2210, 4156, 2817, -3511 }, + { -717, 6568, 1863, -2951 }, + { -3873, 5682, 2164, -575 }, + { -2878, 5835, 440, -2597 }, + { -3228, 7701, 2610, -2514 }, + { -3608, 8888, 3377, -2468 }, + { -2582, 9717, 2519, -3126 }, + { -5238, 6202, 2866, -2831 }, + { -3428, 7370, 3056, -335 }, + { -1681, 8836, 1210, -2010 }, + { -3276, 6724, 1156, -3930 }, + { -894, 8149, 827, -1258 }, + { -2965, 8631, 2549, -1320 }, + { -3961, 6902, 3581, 55 }, + { -1894, 7745, 1750, -841 }, + { -821, 6844, 850, -676 }, + { -608, 6948, -4, -1376 }, + { 615, 6524, 1089, -1147 }, + { -2972, 5668, 1091, -489 }, + { -157, 4649, 2904, -413 }, + { 673, 5121, 1498, -66 }, + { -390, 5902, 1611, -245 }, + { -2349, 5478, 4772, -1320 }, + { 88, 6798, 1972, -1859 }, + { -1213, 5120, 2991, 200 }, + { -2347, 6040, 2839, 376 }, + { -578, 5976, 3364, -1796 }, + { -1391, 5872, 3002, -965 }, + { -564, 4496, 3946, -1186 }, + { -2299, 6386, 3135, -2176 }, + { -2131, 5641, 2011, 1223 }, + { -772, 5807, 1124, 895 }, + { -2837, 6758, 2297, -740 }, + { -3091, 6298, 1415, -2126 }, + { -4197, 6036, 1843, -3022 }, + { -41, 6459, 92, 344 }, + { -2241, 6860, 2095, -4396 }, + { -1931, 7088, 2117, -2135 }, + { -2375, 4422, 1688, -3169 }, + { -1742, 6674, 1538, -119 }, + { -4818, 7749, 4192, -1577 }, + { -2004, 5672, 193, -430 }, + { -3825, 6042, 2128, -1898 }, + { -1108, 8033, 2119, -3013 }, + { -2370, 5453, 1721, 266 }, + { -1570, 7134, 614, -2638 }, + { -1519, 8752, 3503, -4330 }, + { -2050, 3845, 2907, -1126 }, + { 5085, 4412, -335, -1923 }, + { 3618, 1423, -613, -4012 }, + { 4481, 3729, 589, -4631 }, + { 4270, 3216, -1763, -3168 }, + { 4241, 1796, -1701, -2796 }, + { 4787, 2338, -487, -3639 }, + { 2915, 3429, -621, -4753 }, + { 5175, 1660, -1265, -3223 }, + { 4280, 4057, -684, -4079 }, + { 4980, 4419, -1455, -2719 }, + { 5436, 2464, 387, -4197 }, + { 4507, 4018, 1121, -3314 }, + { 6020, 2401, -413, -3201 }, + { 4200, 3789, -333, -2813 }, + { 5229, 2493, -1194, -1878 }, + { 5851, 2695, -492, -2292 }, + { 5743, 3288, -697, -1221 }, + { 5692, 2612, 979, -2227 }, + { 5085, 2067, 1046, -1214 }, + { 3163, 2240, -2098, -3435 }, + { 5228, 1898, 145, -2397 }, + { 5860, 3976, -418, -2872 }, + { 6008, 3399, 1027, -3506 }, + { 4126, 2035, 1865, -893 }, + { 5375, 3596, 511, -2362 }, + { 1937, 1493, -852, -122 }, + { 3473, 4849, 547, -2603 }, + { 4631, 2977, 1141, -1768 }, + { 6149, 3050, -71, -1886 }, + { 4069, 4353, -289, -1429 }, + { 2884, 1225, -1388, 365 }, + { 5485, 2518, -235, -571 }, + { 1216, 4375, 1443, 398 }, + { 4988, 3106, 107, -1435 }, + { 4511, 2801, 307, -444 }, + { 3235, 4386, 327, -676 }, + { 2055, 3708, 1657, -305 }, + { 5839, 2374, 290, -1385 }, + { 5110, 3305, 1936, -4206 }, + { 6416, 2920, 338, -2736 }, + { 3350, 2824, -1269, -3881 }, + { 4840, 1815, 464, 186 }, + { 2399, 3332, 238, 1238 }, + { 3516, 1363, 1582, 688 }, + { 3582, 1874, 154, -4770 }, + { 3261, 2878, 886, 283 }, + { 3877, 2658, -327, 884 }, + { 4151, 3436, 2173, -2923 }, + { 3592, 3674, 1281, -1295 }, + { 4561, 3730, -1114, -1747 }, + { 4595, 3625, -558, -575 }, + { 2577, 2348, 2267, 120 }, + { 5242, 3299, 32, -3412 }, + { 4264, 3637, 709, -2320 }, + { 6556, 3570, -838, -2472 }, + { 5745, 4014, -940, -1973 }, + { 5629, 4475, 477, -3328 }, + { 5269, 3199, 1682, -3085 }, + { 4432, 2416, 1145, -3299 }, + { 4465, 2505, 2162, -2186 }, + { 4643, 4941, -88, -2885 }, + { 4568, 5231, 552, -3915 }, + { 5667, 3075, -1406, -2963 }, + { 5418, 5259, -771, -2818 }, + { -256, -7875, 511, -471 }, + { -1813, -7971, -424, -396 }, + { -306, -7006, 862, 282 }, + { -2306, -6422, -1440, 508 }, + { -245, -6787, 375, -100 }, + { -1309, -6065, -20, 779 }, + { -1656, -6047, -641, 1307 }, + { -1496, -6522, 964, 726 }, + { -2291, -6588, -202, 795 }, + { -762, -7522, 1454, -558 }, + { -2270, -7004, -834, -580 }, + { -1139, -7078, 259, 362 }, + { -2535, -7568, -1040, 49 }, + { -3786, -7280, 934, -476 }, + { -3336, -6368, 606, 1056 }, + { -3602, -6924, 52, 714 }, + { -2278, -6550, 1674, 204 }, + { -2855, -5765, 930, 1530 }, + { -2889, -7325, -215, 305 }, + { -2749, -6080, -237, 1452 }, + { -985, -6667, 1577, 400 }, + { -2036, -6083, 380, 1267 }, + { -2077, -7460, 380, -30 }, + { -1775, -7175, 1540, -386 }, + { -3065, -6927, 989, 168 }, + { -2836, -7602, 117, -3392 }, + { -1058, -6396, 593, -3078 }, + { -844, -6062, 999, -236 }, + { -3261, -6951, 1491, -720 }, + { -2186, -8484, 75, -1287 }, + { -2882, -7756, 456, -510 }, + { -1800, -6879, 960, -1183 }, + { -2554, -7241, 1614, -1474 }, + { -2608, -5305, 392, 851 }, + { -2973, -6562, -859, 858 }, + { -2640, -5989, 1031, -416 }, + { -977, -8366, 705, -1434 }, + { -1213, -7409, -77, -1390 }, + { -1335, -6657, 2125, -123 }, + { -2544, -6862, 1852, -737 }, + { -3235, -6422, 1752, -103 }, + { -1300, -7557, 939, -348 }, + { -3476, -7579, 202, -109 }, + { -2482, -6572, 753, 619 }, + { -2554, -8136, -648, -429 }, + { -1012, -7870, -3, -421 }, + { -3604, -6247, 32, -3102 }, + { -1486, -7271, 2013, -1021 }, + { -578, -6799, -523, 405 }, + { -2841, -5948, 1644, 911 }, + { -2411, -7473, 1084, -484 }, + { -2238, -6033, 294, -1059 }, + { -3459, -6470, -201, -790 }, + { -2027, -6009, 1833, 805 }, + { -1433, -8047, 1531, -1754 }, + { -3258, -7884, 763, -1422 }, + { -1544, -6928, -729, 478 }, + { -2314, -8415, 74, -3757 }, + { -3201, -5684, 95, -2214 }, + { -2423, -8694, 725, -3631 }, + { -3545, -7071, 1162, -1798 }, + { -294, -9662, 403, -2274 }, + { -2290, -5460, 1196, 402 }, + { -1603, -6713, 903, -2363 }, + { 4121, 2491, -3142, -2482 }, + { 4500, 3305, -3671, -1567 }, + { 5973, 3172, -1348, -534 }, + { 4830, 3379, -1549, 643 }, + { 5214, 3938, -2641, -2302 }, + { 4639, 4826, -5532, -847 }, + { 5639, 2731, -2170, -963 }, + { 6084, 3487, -3525, -1346 }, + { 5971, 3154, -2190, -2316 }, + { 5618, 4865, -6927, 116 }, + { 5345, 3568, -7391, 709 }, + { 5429, 5078, -3811, -1524 }, + { 6960, 2037, -3515, -1096 }, + { 7092, 2531, -4557, -588 }, + { 6061, 4247, -5651, -478 }, + { 4595, 3684, -4907, -827 }, + { 7497, 3213, -3048, -424 }, + { 5996, 2137, -3098, -1745 }, + { 6198, 5199, -2223, -2274 }, + { 6888, 2851, -2768, -1675 }, + { 6114, 4210, -2316, -954 }, + { 7127, 4242, -3041, -1408 }, + { 6126, 3668, -1517, -1427 }, + { 6245, 6129, -4225, -1186 }, + { 6816, 3213, -2101, -964 }, + { 5345, 5276, -2643, -847 }, + { 6592, 4665, -4338, 484 }, + { 6746, 3751, -3443, 124 }, + { 5453, 1980, -2738, 2606 }, + { 4662, 2179, -4226, -1059 }, + { 5571, 3208, -3554, 174 }, + { 5256, 4447, -1815, -1481 }, + { 5400, 2570, -1210, 235 }, + { 7056, 2549, -2674, 318 }, + { 4574, 4340, -2892, -130 }, + { 6203, 4587, -3273, -305 }, + { 5103, 1925, -2715, -2137 }, + { 3905, 4296, -1700, 247 }, + { 4421, 4605, -3299, 811 }, + { 5671, 1273, -3870, -924 }, + { 5486, 1805, -4901, 133 }, + { 6437, 2578, -1828, -106 }, + { 5530, 5253, -5058, 1223 }, + { 4816, 2025, -1215, 1443 }, + { 3457, 3525, -2456, 3217 }, + { 3316, 2595, -1108, 2459 }, + { 3068, 3810, -2207, 1926 }, + { 6351, 5436, -6470, 600 }, + { 6324, 4240, -5365, 2416 }, + { 4851, 4774, -4075, 1878 }, + { 4900, 3679, -5198, 1078 }, + { 8347, 3633, -4565, -171 }, + { 5244, 5718, -3853, 173 }, + { 3960, 3492, -2939, 2105 }, + { 6070, 3473, -2351, 161 }, + { 8228, 3034, -3360, -901 }, + { 7006, 3985, -1940, -1926 }, + { 7123, 4681, -4301, -878 }, + { 5122, 4097, -1851, -449 }, + { 6200, 2060, -2251, 1049 }, + { 7106, 3844, -7209, 2625 }, + { 7108, 3370, -6734, 533 }, + { 6859, 2849, -3992, 1360 }, + { 5458, 2278, -3253, 1131 }, + { -1072, -2109, 4783, -1073 }, + { -319, -2604, 4257, -2418 }, + { 2466, 1300, 3476, -314 }, + { 2847, -1502, 5296, -141 }, + { 1667, -1273, 5559, -2725 }, + { 2877, -3402, 6434, 204 }, + { 53, -2637, 5275, -1181 }, + { 1091, -2215, 5803, -1549 }, + { 2397, -922, 4327, 1182 }, + { 219, -3747, 4647, -1564 }, + { -29, -2705, 4812, 1277 }, + { 1499, -2608, 5648, 1407 }, + { 2139, -2399, 4202, 2791 }, + { -426, -2064, 5528, 151 }, + { 2560, -2803, 6179, -2806 }, + { 4537, -2479, 3797, 1095 }, + { 888, -3357, 5341, -415 }, + { 4460, -1814, 5388, -1227 }, + { 3920, -3268, 6364, -703 }, + { 3343, -4698, 4410, 784 }, + { 309, -1897, 6306, 1223 }, + { 958, -3318, 4254, -3167 }, + { -99, 1596, 6018, -1983 }, + { -429, -853, 6407, 878 }, + { 1170, -1322, 6290, -417 }, + { 2288, -505, 6303, -1999 }, + { 3312, -1674, 6749, -2494 }, + { -415, -3401, 4721, -371 }, + { -189, -1210, 4844, -2002 }, + { 888, -4142, 4377, 130 }, + { 2469, -4381, 5398, -2492 }, + { 2879, -2912, 5094, -2598 }, + { -717, -617, 5650, -685 }, + { 1470, -3863, 5352, -1684 }, + { 3935, -96, 3823, -730 }, + { 3769, -430, 3168, 694 }, + { 2556, 385, 3539, 512 }, + { 77, -1415, 5111, 2655 }, + { 2724, -2158, 6715, -822 }, + { 1832, 1001, 5385, -1900 }, + { 900, 2198, 4464, -559 }, + { 441, 69, 5921, -1743 }, + { -1161, 738, 6732, -308 }, + { 257, 2035, 4091, 736 }, + { 1607, 1288, 4355, -23 }, + { -13, 1316, 4180, 1672 }, + { 1511, 1336, 3057, 1435 }, + { 2189, -3813, 4530, 939 }, + { 3632, -706, 2646, 1375 }, + { 4266, -3761, 4241, 1077 }, + { 3101, -427, 5273, -1202 }, + { 2293, 276, 4810, -313 }, + { 3430, -1851, 3101, 2045 }, + { 3453, -2979, 5142, 942 }, + { 1683, -3281, 4802, 2002 }, + { 3954, -4715, 5611, 578 }, + { 1272, -155, 5085, 454 }, + { 128, -194, 5095, 1409 }, + { 820, 880, 5797, -2658 }, + { -1095, 656, 5774, 1095 }, + { 813, -1669, 4320, -3251 }, + { -119, 518, 6372, -651 }, + { 2922, -4299, 6115, -877 }, + { 4205, -4273, 4004, 2642 }, + { -1211, -3892, 224, 3127 }, + { -34, -4371, 1321, 2318 }, + { 77, -6326, 1201, 828 }, + { 3995, -3775, 1958, 3233 }, + { 178, -3301, 1985, 3318 }, + { 2330, -3801, 1033, 3195 }, + { 1413, -5536, 826, 1709 }, + { 2468, -3499, 3653, 3631 }, + { 741, -4617, 1723, 2008 }, + { 1246, -3043, 2978, 3949 }, + { -343, -4308, 2258, 2189 }, + { -682, -4640, 454, 2272 }, + { 1236, -4829, 2491, 1642 }, + { -512, -3766, 1182, 3052 }, + { 119, -3939, 3712, 971 }, + { -1145, -4624, 1360, 2281 }, + { 101, -4746, 2866, 1255 }, + { -1500, -5455, 539, 1637 }, + { -969, -5909, 1414, 1128 }, + { -1261, -4939, -231, 2022 }, + { -226, -5345, 1207, 705 }, + { 2712, -5109, 3205, 1866 }, + { -476, -5913, 273, 1208 }, + { -2039, -4464, 624, 2545 }, + { -2351, -3930, 2019, 2673 }, + { -2675, -4849, 1522, 1990 }, + { -1524, -3461, 1446, 3204 }, + { 477, -5314, 1710, 1577 }, + { 656, -3729, 2346, 2511 }, + { 550, -5917, 1975, 1040 }, + { 1728, -4704, 3067, 1058 }, + { -9, -5247, 506, 1760 }, + { -574, -5135, 1675, 1672 }, + { 2129, -3781, 3444, 2313 }, + { 1144, -4439, 2214, 2529 }, + { 1292, -4160, 3185, 1833 }, + { 2445, -3262, 2534, 3227 }, + { 2266, -4401, 2023, 2400 }, + { -587, -3602, 3408, 2067 }, + { -885, -4951, 3228, 1174 }, + { -728, -2711, 2807, 3552 }, + { 1019, -3043, 3195, 2954 }, + { 1888, -4615, 1140, 2454 }, + { 660, -5616, 754, 800 }, + { -1975, -5371, 1649, 1585 }, + { -1544, -5436, 2422, 1081 }, + { -422, -5882, 2390, 750 }, + { 1336, -5557, 2441, 1230 }, + { 136, -4001, 267, 2854 }, + { -522, -3289, 2226, 2728 }, + { -971, -4580, 2471, 708 }, + { 704, -5306, 3300, 1001 }, + { 325, -3464, 3555, 2398 }, + { 794, -3686, 848, 3169 }, + { 660, -3017, 4584, 3242 }, + { -1486, -3978, 2170, 1644 }, + { -1615, -4650, 2688, 1844 }, + { 750, -4578, 538, 2239 }, + { 1668, -5849, 1455, 1031 }, + { 3486, -4681, 2030, 2183 }, + { 2642, -5429, 1696, 1761 }, + { 4491, -4502, 3538, 2767 }, + { 3545, -4528, 3514, 2982 }, + { 3269, -3676, 2758, 3966 }, + { 5572, 1146, 209, -3379 }, + { 7459, 1053, 593, -1896 }, + { 4480, 200, -310, -4259 }, + { 5577, -939, 242, -3992 }, + { 8142, 442, 1257, -3083 }, + { 5442, 1261, 1424, -3236 }, + { 6260, -183, 3125, -2532 }, + { 7179, 889, 1618, -2548 }, + { 6416, 932, 2379, -2487 }, + { 7094, 2560, 961, -3392 }, + { 7322, 463, 2732, -3735 }, + { 6632, 1577, 1912, -3272 }, + { 6312, 1349, 3028, -3460 }, + { 6105, 386, 1213, -977 }, + { 5478, 1158, 1114, -486 }, + { 6493, 410, 1686, -2180 }, + { 6378, 1881, 1333, -2240 }, + { 5711, 812, 1958, -1300 }, + { 6844, 877, 730, -1189 }, + { 6824, -245, 2249, -2000 }, + { 7515, 1521, 1251, -3058 }, + { 6697, 1051, 1300, -1749 }, + { 6476, 1425, 811, -2773 }, + { 7350, 465, -76, -2849 }, + { 6975, 2095, 567, -2492 }, + { 4691, 1736, 2660, -2289 }, + { 7837, 1456, 340, -2767 }, + { 7930, 507, 838, -2074 }, + { 6106, 1502, 766, -1110 }, + { 4891, -659, 835, -3954 }, + { 7250, 141, 1369, -1523 }, + { 7651, 67, 1651, -2298 }, + { 7364, -305, 601, -3132 }, + { 7179, 193, 2491, -2871 }, + { 6504, -272, 2167, -1322 }, + { 4456, 983, 2300, -421 }, + { 4817, 457, 1695, 371 }, + { 6914, 555, 850, -3159 }, + { 5904, 1030, 202, -1959 }, + { 6258, 880, 2233, -4503 }, + { 6029, 10, 2130, -3600 }, + { 6449, 985, 1129, -3963 }, + { 6616, -18, -111, -3285 }, + { 4496, 775, 817, -4276 }, + { 6134, 2338, 1470, -2973 }, + { 6911, 152, 430, -1946 }, + { 4053, 991, 3218, -1193 }, + { 5435, 1285, 3124, -2412 }, + { 5507, 1836, 1935, -1988 }, + { 5240, 689, 2189, -2670 }, + { 6638, 1719, 606, -1799 }, + { 5556, -180, 129, -2595 }, + { 5644, 1918, 1281, -4316 }, + { 6410, 1088, -282, -3117 }, + { 6503, 1841, 312, -3514 }, + { 6947, 20, 1358, -3886 }, + { 5464, 2109, 2398, -3194 }, + { 5616, -407, 2140, -498 }, + { 6121, 2707, 2379, -4096 }, + { 7303, 1846, 2266, -4095 }, + { 5444, 470, 2718, -1553 }, + { 5817, -645, 3285, -1349 }, + { 5625, 1427, 1103, -1991 }, + { 6041, -806, 1196, -2943 }, + { 3050, -5722, 4070, -5460 }, + { 3420, -4386, 4078, -5155 }, + { 6020, -3982, 7268, -2689 }, + { 7502, -4317, 7894, -3973 }, + { 4156, -3558, 5247, -4316 }, + { 4725, -4401, 7290, -1540 }, + { 6688, -5122, 8216, -3210 }, + { 9176, -6576, 9276, -4963 }, + { 8706, -5708, 7987, -4621 }, + { 7060, -3535, 6532, -3308 }, + { 5600, -2719, 5363, -1568 }, + { 4661, -2803, 6263, -4716 }, + { 3673, -3636, 6147, -3433 }, + { 5305, -2585, 6073, -2638 }, + { 7614, -1962, 6079, -5266 }, + { 6760, -3366, 7382, -4322 }, + { 6385, -3883, 4797, -1353 }, + { 8182, -5120, 4298, -4641 }, + { 9130, -6198, 4975, -3063 }, + { 7421, -5436, 5576, -3713 }, + { 3483, -4898, 5443, -2745 }, + { 4907, -5643, 6390, -4105 }, + { 8119, -7008, 7992, -6764 }, + { 6528, -6122, 6967, -5590 }, + { 5890, -4190, 6624, -5688 }, + { 6815, -7934, 7275, -5456 }, + { 5434, -4306, 5169, -5378 }, + { 4364, -6436, 5376, -2604 }, + { 8152, -3404, 5913, -5048 }, + { 7983, -4863, 4262, -2461 }, + { 8023, -6188, 6238, -5062 }, + { 6753, -3692, 3935, -3723 }, + { 6826, -4760, 3284, -4051 }, + { 7224, -7423, 4492, -3875 }, + { 6904, -2590, 6587, -6248 }, + { 6106, -1944, 7345, -5506 }, + { 4956, -2990, 7808, -3146 }, + { 6908, -6885, 5949, -1288 }, + { 7162, -6058, 3419, -3401 }, + { 7015, -7080, 6907, -3018 }, + { 6971, -6832, 5646, -3273 }, + { 8014, -5546, 5471, -1544 }, + { 6792, -2220, 5105, -2879 }, + { 8494, -3974, 4408, -3999 }, + { 9591, -4866, 6027, -4558 }, + { 5264, -5161, 6101, -738 }, + { 5803, -6141, 5197, -5231 }, + { 4657, -6822, 3232, -5189 }, + { 4791, -5135, 3809, -4665 }, + { 6108, -5103, 2379, -3873 }, + { 4680, -3909, 3234, -5093 }, + { 5802, -3853, 3795, -4984 }, + { 4360, -7483, 4802, -3877 }, + { 5429, -7517, 5911, -3717 }, + { 6866, -2280, 4880, -4634 }, + { 10131, -4628, 4414, -4092 }, + { 10811, -5189, 7746, -5337 }, + { 5663, -8941, 5287, -5680 }, + { 8023, -5991, 7403, -2796 }, + { 9669, -6919, 6525, -4932 }, + { 7275, -3796, 4962, -2547 }, + { 8848, -4806, 5677, -3080 }, + { 8128, -4308, 7749, -6569 }, + { 4032, -5196, 2282, -6239 }, + { 6593, 700, -229, 304 }, + { 8260, 539, -66, -1259 }, + { 6605, 176, -814, -109 }, + { 8057, 0, -1, -136 }, + { 7382, -38, -484, -1129 }, + { 8373, -929, 682, -454 }, + { 7674, 690, -1278, 546 }, + { 7326, -517, 406, -1283 }, + { 7612, -1715, -1167, 1175 }, + { 8590, 441, -782, -710 }, + { 8572, -1202, -291, 260 }, + { 7308, -147, -1785, 414 }, + { 6787, -353, -672, 934 }, + { 5177, -133, 179, 82 }, + { 4161, -34, 447, 1497 }, + { 5997, -902, 1533, -121 }, + { 5727, -871, -1370, 945 }, + { 8386, -252, 293, -823 }, + { 6573, -1354, 682, 616 }, + { 7650, -2096, 725, 457 }, + { 8122, 78, 636, -1400 }, + { 8421, 428, -1620, 131 }, + { 7341, -1292, -717, 186 }, + { 7998, -49, -720, 266 }, + { 5987, -351, 669, 844 }, + { 7314, -1620, 250, -603 }, + { 7219, -1562, -572, 1994 }, + { 8682, -358, -290, -388 }, + { 5810, 155, -178, 1199 }, + { 7246, -12, 1042, -786 }, + { 7357, -923, 1468, -475 }, + { 7801, 621, -212, -724 }, + { 5346, -514, 1210, 1356 }, + { 8459, 36, -127, -779 }, + { 6878, -2429, 854, 1750 }, + { 7280, -1401, -1353, 2845 }, + { 7579, -2148, -1463, 2087 }, + { 6637, 946, -872, 750 }, + { 4807, -1100, 1289, 2602 }, + { 4495, 219, 1551, 1128 }, + { 7639, 506, 446, -1107 }, + { 6359, 188, 1009, -115 }, + { 6641, -1820, 1655, 723 }, + { 5394, -2382, 1604, 2542 }, + { 6021, -2644, 2396, 1407 }, + { 4698, 882, 245, 1525 }, + { 8103, 573, -798, -349 }, + { 8045, -519, 997, -1092 }, + { 7571, -122, 227, -338 }, + { 5347, -1200, 630, 1718 }, + { 7070, 790, 218, -544 }, + { 7440, 728, -527, -20 }, + { 6402, -355, 197, -736 }, + { 4031, 771, 866, 1895 }, + { 6009, 896, 445, -31 }, + { 5160, 1098, -856, 1784 }, + { 7980, -886, -1293, 1396 }, + { 6318, -1361, 2423, 252 }, + { 7547, -699, 133, 506 }, + { 8562, -2344, 940, 264 }, + { 5890, 1187, -1425, 2194 }, + { 6558, -645, -1311, 2621 }, + { 4634, -1671, 2075, 1623 }, + { 5614, 105, -816, 2376 }, + { 6646, 1558, -1365, 630 }, + { 6998, 1150, -2117, -990 }, + { 6555, 2311, -1093, -1783 }, + { 6682, 1430, -2391, -1940 }, + { 7861, 1555, -2977, -1188 }, + { 6745, 1723, -459, -2085 }, + { 7504, 1229, -1666, -2060 }, + { 7937, 671, -2128, -1529 }, + { 7139, 991, -735, -2632 }, + { 6867, 1592, -1303, -2324 }, + { 6401, 2230, -1732, -2508 }, + { 7201, 2184, -2169, -1988 }, + { 6636, 2190, -995, -2840 }, + { 7620, 2306, -2089, -651 }, + { 7584, 1875, -1438, -631 }, + { 9214, 1561, -2464, -1139 }, + { 6154, 1318, -1237, -2917 }, + { 7917, 2847, -1797, -1599 }, + { 8309, 2029, -2555, -465 }, + { 8204, 1282, -584, -2405 }, + { 8440, 1035, -1147, -1137 }, + { 7107, 1858, -60, -1568 }, + { 6781, 2912, -873, -1463 }, + { 7603, 1316, -319, -1249 }, + { 7833, 1335, -78, -1849 }, + { 7930, 1141, -1016, -695 }, + { 7883, 1610, -1017, -1314 }, + { 8069, 1409, -1811, -196 }, + { 8319, 1031, -582, -1590 }, + { 5948, 1537, -2153, -2373 }, + { 8684, 1171, -1871, -850 }, + { 8357, 2484, -2411, -1292 }, + { 6516, 2092, -193, -1167 }, + { 6112, 1697, 22, -525 }, + { 7161, 703, -602, -1879 }, + { 6047, 2351, -807, -219 }, + { 8072, 1854, -1817, -1553 }, + { 6956, 1304, 76, -1011 }, + { 6607, 1481, -544, -162 }, + { 6958, 2541, -265, -1938 }, + { 6416, 2514, -777, -850 }, + { 7272, 2110, -899, -1171 }, + { 7741, 2153, -283, -2614 }, + { 6482, 2041, -1758, -1221 }, + { 6762, 940, -1862, -2281 }, + { 5610, 1194, -1691, -1561 }, + { 7833, 2164, -823, -1952 }, + { 5460, 1438, -848, 1189 }, + { 6011, 1377, -771, -1557 }, + { 7679, 544, -1134, -2214 }, + { 7209, 1292, -2714, -1564 }, + { 5567, 1200, -404, -169 }, + { 5853, 1461, -1465, -518 }, + { 6782, 689, -844, -860 }, + { 7330, 1337, -1152, -71 }, + { 7189, 1506, -653, -685 }, + { 6860, 2116, -1403, -240 }, + { 8804, 1516, -1391, -1760 }, + { 7210, 2689, -1498, -989 }, + { 7030, 3022, -1441, -2083 }, + { 5649, 1836, -407, 525 }, + { 7451, 3099, -717, -2464 }, + { 7384, 1656, -2007, 398 }, + { 6504, 707, -1919, -134 }, + { -1851, 3639, -2279, -695 }, + { -4037, 1644, -77, 1329 }, + { -4025, 1960, -1565, -567 }, + { -3430, 2495, -795, 368 }, + { -4771, 2480, 993, 756 }, + { -3431, 2058, -2539, -971 }, + { -3802, 3418, 380, 217 }, + { -3074, 3350, -1652, -1056 }, + { -3705, 326, -1650, 1535 }, + { -3122, 1281, -1192, 1607 }, + { -4601, 1367, -968, 53 }, + { -3808, 958, 44, 2560 }, + { -2079, 2530, -1485, 1166 }, + { -3707, 343, -2889, 180 }, + { -5249, 1431, -31, 688 }, + { -4990, 125, -704, 1270 }, + { -2771, 1334, -2446, 746 }, + { -2292, 994, -1527, 2630 }, + { -1261, 3070, -2519, 268 }, + { -2544, 3890, -1057, -552 }, + { -4421, 255, -1980, 530 }, + { -2951, 454, -13, 3643 }, + { -2262, 1815, -370, 2880 }, + { -2383, 3657, -649, 576 }, + { -3541, -161, -1389, 2550 }, + { -4241, 1575, 1325, 2561 }, + { -2767, 4037, 1221, 1578 }, + { -3748, 2697, 1148, 1801 }, + { -4686, 2385, -220, 0 }, + { -1531, 1645, -2751, 1327 }, + { -45, 4032, -799, 2298 }, + { -2915, 2280, 709, 2495 }, + { -1199, 3278, -406, 2346 }, + { -2471, 116, -2706, 2060 }, + { -2440, 2173, -2894, -344 }, + { -3375, 2287, 1781, 3226 }, + { -2153, 3568, 1827, 2918 }, + { -862, 2267, -1626, 2527 }, + { -2698, 1135, 301, 4239 }, + { -2364, 2123, 1010, 3710 }, + { -2447, 3281, -81, 1408 }, + { -2660, 4735, 472, 258 }, + { -1053, 3097, 2682, 2398 }, + { -3366, -1037, -1152, -868 }, + { -643, 4242, 2212, 1259 }, + { 971, 3991, 934, 643 }, + { -1617, 2002, 2139, 2195 }, + { -4897, 972, 784, 1719 }, + { -1275, 2992, 1039, 3821 }, + { -392, 4973, -209, 1821 }, + { -1028, 4718, -1479, -137 }, + { 50, 3914, 553, 2210 }, + { 678, 4364, 359, 1303 }, + { -582, 4911, 514, 1671 }, + { 1276, 3914, -1252, 2934 }, + { -1496, 3984, 857, 2330 }, + { 772, 4744, -655, 2332 }, + { -799, 5283, -439, 624 }, + { 1341, 2937, 650, 2027 }, + { -1739, 4892, 1275, 1702 }, + { -892, 2596, -151, 3951 }, + { -3532, 1090, 1292, 32 }, + { 321, 3146, 2647, 1475 }, + { 264, 4199, -1591, 1317 }, + { -452, -2357, 2266, 4192 }, + { 3022, -1033, -2389, 5678 }, + { -1162, -1342, 3543, 4990 }, + { -474, -1477, -1223, 5016 }, + { -699, -2857, 900, 3835 }, + { -461, -2255, -117, 4626 }, + { 1204, -2062, -1211, 4403 }, + { 2192, -3035, -337, 3966 }, + { 108, -831, 279, 5643 }, + { 1457, -620, -2908, 5276 }, + { -2527, -78, 1085, 5460 }, + { -1978, -1918, -949, 4733 }, + { 32, 367, -1904, 5166 }, + { 1890, -1665, 440, 4752 }, + { -518, -348, 2816, 4891 }, + { 3695, -2490, -1374, 4603 }, + { 246, -1965, 3549, 3969 }, + { 1100, -3111, 656, 3737 }, + { -1379, 870, -414, 4575 }, + { 628, -357, -1227, 6179 }, + { -1129, -1318, -2457, 4576 }, + { -425, -98, -73, 6336 }, + { 367, -887, 2990, 4207 }, + { 2091, -1251, 2444, 3557 }, + { -1759, -1610, 2046, 5273 }, + { 3210, 1414, -20, 2616 }, + { 3303, -2636, 1005, 4237 }, + { -327, -3107, -640, 3687 }, + { -197, 764, 572, 5486 }, + { 646, -767, 1388, 5464 }, + { 104, 2742, -228, 3907 }, + { -236, 1829, -579, 4585 }, + { -2150, -474, -1525, 4006 }, + { -23, -2632, -2400, 3892 }, + { -12, -1739, -2910, 4867 }, + { -2310, -368, -102, 4583 }, + { -1991, -2061, 533, 4531 }, + { 3884, -1446, -153, 4393 }, + { 1568, 14, -289, 5268 }, + { -1376, -253, -2797, 3417 }, + { 3193, -2577, 2475, 3566 }, + { 3418, 617, 1350, 1857 }, + { 3792, -24, -272, 3370 }, + { 153, 1159, 2906, 2877 }, + { 511, 2162, 1548, 2741 }, + { 262, 819, -2791, 3734 }, + { 4232, -2015, 1486, 3477 }, + { 2943, -1110, -1014, 5480 }, + { 2842, 369, 703, 3476 }, + { 3011, 1634, -933, 3553 }, + { 4412, -1548, -942, 5021 }, + { -1405, 593, 2372, 5267 }, + { 2093, 2129, 896, 2365 }, + { 4845, -1980, 0, 3823 }, + { -2140, 81, 3278, 5637 }, + { 1484, 2665, -324, 3653 }, + { 10, 192, 1620, 5291 }, + { 2152, 738, -2269, 5000 }, + { 2102, 2748, -1652, 4707 }, + { 2855, -2131, -387, 5188 }, + { 1173, 676, 1338, 3277 }, + { 2340, -2329, -2064, 4095 }, + { 861, -2024, 1296, 5055 }, + { 2189, 3225, -695, 2626 }, + { 6196, -7079, 1943, -822 }, + { 4547, -4813, 3261, 1856 }, + { 4243, -6904, 3443, 448 }, + { 4581, -7503, 946, 506 }, + { 6626, -7754, 3427, 470 }, + { 3407, -9088, 3269, -1496 }, + { 4079, -6464, 2304, 777 }, + { 5621, -9336, 2684, -768 }, + { 5351, -6464, 5238, -214 }, + { 5961, -8007, 1724, -3091 }, + { 4213, -8067, 603, -246 }, + { 7208, -7403, 3168, -1738 }, + { 6098, -7700, 329, -1379 }, + { 6525, -6735, 4248, -1072 }, + { 6073, -6241, 2167, -2378 }, + { 4609, -9218, 3051, -1033 }, + { 6813, -7283, 1581, -1897 }, + { 6126, -6275, 2789, 681 }, + { 4423, -6538, 1621, -1692 }, + { 6272, -8298, 3167, -1855 }, + { 6172, -8558, 4498, -1169 }, + { 4844, -8588, 1647, -366 }, + { 6209, -8807, 1581, -369 }, + { 5389, -8059, 550, -192 }, + { 6654, -9775, 2504, -1063 }, + { 7103, -7998, 806, 530 }, + { 5662, -6736, 1565, -3620 }, + { 4165, -9564, 4191, -2131 }, + { 4526, -7181, 576, -2875 }, + { 4633, -8623, 2807, -4742 }, + { 3709, -7794, 1815, 34 }, + { 3634, -8622, 2313, -826 }, + { 6991, -8447, 2063, -3198 }, + { 7757, -9486, 2255, -558 }, + { 4149, -7778, 4728, -1696 }, + { 5767, -7427, 1113, 707 }, + { 4592, -6261, 2329, 1864 }, + { 3159, -10498, 1677, -4273 }, + { 3534, -9010, 2437, -3565 }, + { 4479, -10821, 2715, -4942 }, + { 3207, -9805, 3054, -3886 }, + { 4627, -8189, 3018, -2354 }, + { 5527, -10566, 3244, -2749 }, + { 4346, -10127, 3335, -3084 }, + { 6132, -10085, 3316, -1308 }, + { 5629, -9704, 2178, -3058 }, + { 3603, -8538, 1246, -624 }, + { 3737, -8488, 395, -3167 }, + { 5465, -11414, 2810, -4640 }, + { 5306, -7745, 2721, -3988 }, + { 7000, -9111, 1695, -1409 }, + { 6663, -7741, 2466, -4079 }, + { 4083, -7175, 1836, -4831 }, + { 3613, -9926, 1342, -3455 }, + { 6588, -8033, 457, -258 }, + { 4720, -8102, 17, -1209 }, + { 7414, -8709, 1294, -344 }, + { 5437, -10030, 4043, -1704 }, + { 4862, -9281, 1558, -1431 }, + { 6800, -6403, 5113, 862 }, + { 4623, -8242, 2667, -228 }, + { 5919, -5083, 3348, 2135 }, + { 5985, -8889, 2733, -5105 }, + { 5029, -5767, 4407, 719 }, + { 354, -6158, -838, -3001 }, + { 351, -5943, -2104, -1534 }, + { -633, -7190, -25, -4798 }, + { -1595, -7235, -3812, -1400 }, + { 103, -6197, -2933, -78 }, + { -1722, -5020, -3441, -4333 }, + { -1963, -5644, -4365, -270 }, + { -846, -5743, -3477, 196 }, + { -191, -5348, -4054, -469 }, + { -2515, -7754, -3495, -818 }, + { -2090, -6710, -2701, 117 }, + { -546, -7036, -1398, 163 }, + { -278, -7091, -2662, -536 }, + { -622, -7962, -2731, -1464 }, + { -1555, -8118, -3612, -2057 }, + { -1094, -6280, -2314, 505 }, + { -2556, -8538, -4024, -2247 }, + { 109, -7134, -3107, -1823 }, + { -900, -6954, -3340, -717 }, + { -605, -7113, -3656, -2154 }, + { 837, -6263, -3211, -2177 }, + { -417, -5810, -3871, -1469 }, + { -1318, -5649, -4207, -3198 }, + { 413, -6765, -2082, -33 }, + { -3101, -6450, -4362, -766 }, + { 755, -6489, -2967, -846 }, + { 1117, -7106, -2452, -1352 }, + { -1202, -8387, -3072, -2897 }, + { -365, -4894, -3561, -2937 }, + { -2372, -8776, -265, -4441 }, + { -1224, -8678, -896, -5074 }, + { -755, -10096, -600, -6623 }, + { 300, -8206, -225, -4568 }, + { -1176, -6824, -2633, -3527 }, + { -2006, -5443, -1526, -5849 }, + { -1115, -5540, -2363, -4785 }, + { 1059, -6812, -2543, -2654 }, + { -1976, -6861, -3062, -5508 }, + { -379, -5328, -2321, -3624 }, + { -2108, -5860, -4518, -1915 }, + { -379, -7885, -1329, -594 }, + { 774, -5389, -581, -5213 }, + { -2601, -5083, -1849, -4921 }, + { -176, -5580, 74, -5075 }, + { -204, -6780, -190, -6232 }, + { 418, -7594, -1987, -820 }, + { -1873, -8529, -2926, -1609 }, + { 1340, -6362, -919, -4975 }, + { 577, -7990, -2044, -1873 }, + { -2572, -7413, -1745, -2224 }, + { -2037, -7030, -1461, -7138 }, + { -2559, -8756, -2039, -5836 }, + { -2079, -6764, -1209, -5669 }, + { -1613, -7801, -2006, -685 }, + { -1865, -6583, -722, -3529 }, + { -589, -6358, -1377, -1003 }, + { -540, -7514, -1331, -3542 }, + { 419, -6192, -1677, -4927 }, + { -2786, -8763, -2966, -5065 }, + { -2172, -8411, -1726, -4675 }, + { -3382, -9833, -3497, -5722 }, + { -2433, -10169, -2077, -5775 }, + { -424, -9451, -1096, -3658 }, + { -537, -8522, -910, -1897 }, + { -5550, 2807, 1683, -693 }, + { -6395, 635, 3573, -1246 }, + { -7544, 2280, 2140, 44 }, + { -8751, 1136, 2951, -794 }, + { -5605, 2709, 2052, 916 }, + { -7650, 654, 869, 135 }, + { -6939, 967, 1409, 870 }, + { -7834, 2123, 3310, 974 }, + { -6935, 2818, 1274, -1678 }, + { -5605, 2233, 1013, 471 }, + { -7095, 1849, 1648, 198 }, + { -6636, 1634, 712, -37 }, + { -7279, 978, 296, -315 }, + { -7664, 3504, 3292, -216 }, + { -7836, 1209, 1221, -257 }, + { -7913, 2201, 1765, -1529 }, + { -7077, 3783, 2632, -1407 }, + { -5565, 1645, 1410, -622 }, + { -6494, 2879, 1181, -759 }, + { -7073, 3137, 3010, 550 }, + { -7249, 1839, 847, -805 }, + { -6630, 2197, 282, -1096 }, + { -8836, 1573, 1988, -1090 }, + { -7809, 1274, 836, -1198 }, + { -7895, 2970, 3511, -1097 }, + { -6960, 1664, 1356, -2442 }, + { -6582, 2866, 2273, 307 }, + { -7221, 821, 2851, -1435 }, + { -6015, 1703, 2001, -2367 }, + { -8082, 1034, 2103, 239 }, + { -5952, 1912, 301, -465 }, + { -6099, 841, 379, 567 }, + { -6343, 50, 494, 658 }, + { -6586, 983, 591, -893 }, + { -5500, 869, 2187, -2479 }, + { -6482, 60, 1545, -979 }, + { -6705, 515, 1974, -53 }, + { -6460, 1755, 1325, -1275 }, + { -6093, 2617, 2465, -623 }, + { -7330, 2161, 594, -2115 }, + { -7324, 762, 1593, -2004 }, + { -6385, 679, 1510, -2514 }, + { -6159, 241, 2976, -1631 }, + { -8583, 3030, 4045, -162 }, + { -6299, 66, 2209, -2103 }, + { -5428, 1279, 3267, -1846 }, + { -6438, 1335, 2728, -1631 }, + { -8012, 1070, 2428, -1151 }, + { -6201, 2781, 2349, -1918 }, + { -5918, 1139, 3121, -148 }, + { -6314, 2481, 3137, -1808 }, + { -7180, 1722, 2435, -1602 }, + { -6750, 1829, 3763, -1145 }, + { -6713, 1777, 2221, 1212 }, + { -7479, 1835, 3627, -479 }, + { -7299, 10, 2406, -1593 }, + { -8249, 3129, 996, -2870 }, + { -8374, 1534, 1333, -1882 }, + { -7507, 3353, 1598, -2299 }, + { -7379, 2701, 2326, -1167 }, + { -8440, 2276, 2796, -542 }, + { -10348, 1527, 2649, -1165 }, + { -8184, 3614, 2574, -1738 }, + { -5539, 1574, 1733, 1138 }, + { 9404, -7652, 67, 79 }, + { 8654, -3972, 1358, -60 }, + { 8617, -4794, 117, 2318 }, + { 7886, -4505, 1784, 1200 }, + { 8636, -6125, 3879, -1003 }, + { 9654, -6836, 1816, 205 }, + { 9374, -6553, 913, 1875 }, + { 8020, -6150, 1134, 2390 }, + { 7786, -4970, 2078, -1857 }, + { 8691, -6119, 711, 708 }, + { 9039, -5568, 2944, -1902 }, + { 9955, -5048, 1433, -601 }, + { 8089, -6927, 3093, -2846 }, + { 8487, -7024, 2415, 19 }, + { 9388, -5287, 3577, -2655 }, + { 8591, -7371, 2300, -996 }, + { 9104, -4763, 1453, -2558 }, + { 7615, -5457, 596, 164 }, + { 9860, -7047, 3433, -614 }, + { 8756, -4404, 2235, -964 }, + { 9462, -4660, 299, -1822 }, + { 10119, -5550, 2689, -1273 }, + { 10915, -7471, 2705, -1007 }, + { 11433, -7090, 1410, -1198 }, + { 9882, -7431, 2965, -1895 }, + { 7628, -5219, 769, -2661 }, + { 8169, -5318, 2262, 70 }, + { 8846, -6320, 1939, -754 }, + { 7147, -5593, 1248, -971 }, + { 10652, -5485, 935, 137 }, + { 7778, -6533, 2564, -1932 }, + { 8878, -5173, 1214, -361 }, + { 9828, -4943, 282, 510 }, + { 10042, -6134, 3895, -1914 }, + { 7965, -6630, 3566, -433 }, + { 8573, -4502, 3574, -1209 }, + { 8398, -4801, 1031, -1347 }, + { 10136, -7772, 2612, 1547 }, + { 9890, -7280, 1768, -1083 }, + { 8407, -6585, -706, -58 }, + { 7976, -7582, 229, -131 }, + { 10481, -8866, 1166, -147 }, + { 10914, -4342, 3189, -2412 }, + { 10440, -5198, -104, -1109 }, + { 11227, -6530, 2381, -2449 }, + { 8487, -8064, 1086, 230 }, + { 9975, -6123, -857, -134 }, + { 8339, -6498, 1232, -2337 }, + { 11042, -4506, 1119, -2098 }, + { 12563, -5592, 1837, -2062 }, + { 11801, -5590, 632, -1296 }, + { 10152, -5617, 1511, -1917 }, + { 7800, -6473, 51, -1337 }, + { 7941, -5560, 2438, -3270 }, + { 6554, -3834, 2100, 1476 }, + { 9065, -5520, -226, -1120 }, + { 10794, -7120, -243, 122 }, + { 10429, -6968, 272, -806 }, + { 8942, -8914, 1442, -392 }, + { 9969, -5051, 2033, -2953 }, + { 7275, -4152, 3058, -64 }, + { 11127, -5488, 4589, -3227 }, + { 9626, -6666, 2739, -2958 }, + { 6943, -5362, 4470, 1008 }, + { -7456, -967, 2936, -1002 }, + { -8622, -333, 6962, 2606 }, + { -7486, -3392, 3668, 1287 }, + { -8053, -827, 5148, 1097 }, + { -6610, 454, 4952, 96 }, + { -7701, -1982, 3161, -468 }, + { -7307, -1132, 4071, -36 }, + { -8125, -271, 5199, 3862 }, + { -9182, -1950, 2813, 1878 }, + { -9855, -952, 4794, 3010 }, + { -7241, 1431, 4202, 2468 }, + { -9646, 157, 4766, 1046 }, + { -9371, 1230, 6009, 2958 }, + { -11514, -64, 8630, 5248 }, + { -6766, 565, 2766, 2140 }, + { -8426, -9, 2852, 1271 }, + { -11291, -1113, 5087, 2937 }, + { -8297, 2092, 4495, 1264 }, + { -9983, 735, 3809, -51 }, + { -9048, -1000, 3191, -308 }, + { -7331, -1987, 2655, 1391 }, + { -7144, -21, 4333, 2161 }, + { -6032, -1540, 3543, 896 }, + { -7987, -1036, 1985, 1529 }, + { -9264, 2004, 5194, 290 }, + { -11308, -840, 5754, 1654 }, + { -9130, -2398, 4292, 2973 }, + { -6248, 838, 3563, 1223 }, + { -6819, -2760, 3511, 119 }, + { -7213, -2006, 4364, 762 }, + { -5431, -1047, 4533, 166 }, + { -7098, -641, 2021, 639 }, + { -8628, -2249, 3588, 399 }, + { -6352, -1498, 3560, -648 }, + { -7033, -2190, 4870, 2562 }, + { -7405, -46, 3772, -581 }, + { -6104, 796, 5143, 1965 }, + { -5787, 943, 5784, 3030 }, + { -8367, 1465, 7192, 4097 }, + { -8259, 789, 5694, 1963 }, + { -10614, -1899, 5748, 2645 }, + { -8258, -805, 3698, 2275 }, + { -6877, -972, 6431, 3160 }, + { -6483, 363, 7018, 3129 }, + { -6283, -1358, 5191, 1524 }, + { -8853, -3157, 4119, 1741 }, + { -6086, -267, 3883, -835 }, + { -7254, 1032, 6613, 4017 }, + { -11470, -3350, 4649, 3426 }, + { -6743, 481, 6148, 1239 }, + { -5394, -166, 5309, 3165 }, + { -7958, 1068, 4268, -240 }, + { -10520, 2256, 7916, 2828 }, + { -5132, -4, 5739, 1176 }, + { -8643, 120, 3255, -629 }, + { -9631, 1974, 8870, 4362 }, + { -10663, -1221, 3733, 589 }, + { -8224, -1843, 5806, 2655 }, + { -8282, 1255, 8647, 3478 }, + { -12311, -1505, 9043, 6256 }, + { -11312, -856, 7136, 4681 }, + { -11944, -722, 7941, 3309 }, + { -7868, -463, 6846, 4196 }, + { -8679, -241, 7410, 5347 }, + { 6759, -4680, -508, 1220 }, + { 5176, -6111, 944, 121 }, + { 6843, -5667, -1368, -533 }, + { 5616, -5884, -1471, -695 }, + { 6030, -5089, -1808, -940 }, + { 7444, -5463, -52, 1881 }, + { 4207, -6079, -506, 1571 }, + { 6785, -4410, -649, 3084 }, + { 4838, -5214, 2026, 2998 }, + { 4201, -5790, 645, 1811 }, + { 6930, -5129, -1940, 1698 }, + { 6332, -4627, 692, 3027 }, + { 6285, -4314, -106, 3644 }, + { 6255, -5450, -1975, 742 }, + { 4199, -4676, -459, 1796 }, + { 5592, -5500, 1345, 1300 }, + { 4358, -5556, -2236, 114 }, + { 4620, -5875, -1563, 888 }, + { 4892, -7550, -327, -419 }, + { 4734, -7085, 7, 613 }, + { 3883, -5562, -1969, 1080 }, + { 5610, -4990, -204, 834 }, + { 4117, -6482, -1271, 341 }, + { 6585, -5107, 892, 1169 }, + { 6632, -3683, 302, 3002 }, + { 6326, -5351, -983, -1250 }, + { 4382, -7192, -730, -158 }, + { 5227, -6540, -451, 1123 }, + { 5468, -6472, -870, -1471 }, + { 5191, -6402, -1365, -127 }, + { 7407, -6317, -973, -336 }, + { 4611, -6530, -820, -1980 }, + { 4963, -5159, -2050, -966 }, + { 4414, -5691, -211, -998 }, + { 5954, -5873, 750, -1749 }, + { 4394, -4796, -1268, 254 }, + { 7161, -6214, -1010, 689 }, + { 4965, -3598, 2372, 1711 }, + { 6248, -6180, 981, 864 }, + { 6473, -5336, 525, -600 }, + { 4591, -6864, -1131, -900 }, + { 6314, -6440, -1021, -375 }, + { 5838, -6209, -1199, 944 }, + { 5308, -5283, -2100, 1267 }, + { 4342, -5860, -1637, -1356 }, + { 5680, -4388, -1227, -104 }, + { 4900, -4098, 1449, 4046 }, + { 4677, -4284, -106, 3190 }, + { 7574, -6173, -848, 1859 }, + { 6493, -7207, -131, 726 }, + { 5513, -5261, -2117, 4 }, + { 6191, -7352, -193, -505 }, + { 5885, -4333, 324, -134 }, + { 6162, -6081, -312, -2044 }, + { 4216, -6200, -1810, -572 }, + { 5652, -7035, -696, -197 }, + { 7131, -7189, -366, -60 }, + { 5032, -4803, -1514, 2832 }, + { 7386, -4610, -606, 3489 }, + { 4211, -5031, 1221, 3047 }, + { 4050, -4653, 1584, 1469 }, + { 6852, -5302, -1861, 206 }, + { 7736, -4816, -1794, 3359 }, + { 6290, -3439, 1522, 2454 }, + { 1768, 5990, -5560, -2594 }, + { 3903, 5326, -1530, -1501 }, + { 2472, 3738, -2117, -4240 }, + { 3260, 5448, -904, -4733 }, + { 1435, 7297, -3676, -4102 }, + { 4096, 5951, -656, -3312 }, + { 2178, 6009, -3146, -3724 }, + { 3787, 5493, -5473, -1633 }, + { 2998, 7286, -3334, -3571 }, + { 2894, 6576, -4708, -2804 }, + { 830, 6163, -4286, -3348 }, + { 4755, 5569, -1730, -2739 }, + { 4604, 6065, -3562, -2605 }, + { 2749, 5141, -3986, -2775 }, + { 3942, 4875, -2143, -3340 }, + { 2819, 8517, -2004, -2724 }, + { 2146, 6298, -689, -3093 }, + { 5196, 6504, -3393, -1475 }, + { 1851, 8386, -1748, -1420 }, + { 3474, 8572, -3534, -2688 }, + { 4503, 7560, -3561, -2245 }, + { 4433, 6219, -2393, -1575 }, + { 3506, 7248, -2275, -1977 }, + { 3490, 7409, -3147, -604 }, + { 4214, 6447, -3520, 516 }, + { 619, 7034, -829, -1705 }, + { 1732, 7395, -356, -2208 }, + { 1226, 5204, -3294, -3732 }, + { 2027, 5619, -1813, -4146 }, + { 3078, 5877, 47, -2651 }, + { 1654, 5458, 424, -682 }, + { 3163, 5464, -2026, -270 }, + { 2884, 5375, -685, -530 }, + { 2950, 7286, -35, -2967 }, + { 1986, 5066, -597, 482 }, + { 3459, 4308, -3845, -2333 }, + { 3155, 7037, -1346, -4345 }, + { 2193, 6696, -717, -1319 }, + { 3677, 5089, -3892, -487 }, + { 2186, 5136, -4186, -1492 }, + { 773, 5796, -917, 817 }, + { 2489, 6546, -3570, -2117 }, + { 1223, 6469, -1362, -33 }, + { 271, 6061, -1466, -1725 }, + { 2540, 5171, -1847, 1032 }, + { 2548, 5251, -2697, 1677 }, + { 771, 7600, -768, -632 }, + { 4710, 6647, -4736, -1275 }, + { 1369, 5917, -2971, -1056 }, + { 163, 5239, -3499, -2275 }, + { 2104, 4285, -3211, -3286 }, + { 1107, 7411, -1972, -1671 }, + { 2196, 7262, -2310, -1926 }, + { -244, 6439, -1745, -839 }, + { 3293, 3832, -2890, -3000 }, + { 419, 6443, -379, -407 }, + { 3077, 4930, -1156, -2869 }, + { 2131, 5874, -2330, 224 }, + { 690, 6538, -2212, -2841 }, + { 1602, 4421, -2515, 1542 }, + { 3318, 9373, -3032, -3477 }, + { 5646, 7462, -5153, -1463 }, + { 4139, 7137, -1539, -3321 }, + { 3481, 9077, -1645, -3653 }, + { -7747, 375, -106, -543 }, + { -8587, -1379, -586, -461 }, + { -10146, -892, 2094, 694 }, + { -8103, 382, 504, -325 }, + { -8548, -92, 94, -656 }, + { -7460, 38, 152, 388 }, + { -8266, -271, -459, -883 }, + { -7935, -664, -1026, -802 }, + { -8341, -109, 853, 161 }, + { -8802, -1355, 1099, 630 }, + { -8957, -6, 1108, -669 }, + { -7260, -1520, -43, -407 }, + { -7555, -174, 668, -2562 }, + { -9014, -126, 227, -1191 }, + { -8184, 769, 290, -1375 }, + { -9476, 55, 962, -1528 }, + { -8679, 541, 755, -1030 }, + { -9842, -1626, 838, -1588 }, + { -8513, -702, 788, -1998 }, + { -10101, -1558, -366, -1841 }, + { -8135, 78, 1479, -1813 }, + { -9128, -454, 313, -1786 }, + { -7554, -1084, 831, -2442 }, + { -7576, -701, 2068, -1665 }, + { -7791, -1481, 1587, -1808 }, + { -6701, -596, -97, 802 }, + { -7418, -15, 684, -963 }, + { -7127, -477, -139, -426 }, + { -8097, -110, -36, -264 }, + { -7620, -1922, -590, -101 }, + { -7647, -1201, 279, 660 }, + { -7856, -1974, 758, -2271 }, + { -8496, -167, 2232, -1143 }, + { -8506, -1359, 624, -740 }, + { -7274, -1052, 1062, -139 }, + { -7800, -217, 91, -1794 }, + { -7030, -1694, -955, 615 }, + { -9020, -1864, 101, -2182 }, + { -9400, -740, 598, -667 }, + { -8448, -1184, 2024, -1272 }, + { -8812, -570, -897, -2384 }, + { -10559, -1286, 538, -1536 }, + { -8728, -888, -1089, -1397 }, + { -7080, -1185, 636, -1252 }, + { -9880, 233, 2344, -782 }, + { -7952, -1326, -378, -1947 }, + { -7207, -378, 1408, -2237 }, + { -8467, -1545, 902, -1987 }, + { -9163, -1474, 924, -1739 }, + { -8159, -992, -77, -2744 }, + { -8343, 148, -423, -1573 }, + { -9105, -649, -254, -1214 }, + { -8939, 456, 281, -1905 }, + { -8837, 179, -394, -2634 }, + { -9145, 757, 1547, -1319 }, + { -9775, -723, 441, -1680 }, + { -8910, -686, 1529, -1525 }, + { -9492, -1134, 2064, -938 }, + { -6111, -943, 677, -31 }, + { -7411, -613, -814, 46 }, + { -9479, -922, -430, -2061 }, + { -11298, -1268, 1318, -1117 }, + { -8190, 832, 671, -2214 }, + { -10453, -550, 1672, -886 }, + { 1044, 9353, -1651, -5423 }, + { 1034, 8149, -455, -6166 }, + { 761, 8293, -3214, -4838 }, + { 938, 8077, 164, -5130 }, + { 1295, 8673, 2582, -5490 }, + { -314, 7973, -2395, -5231 }, + { -507, 9012, -2497, -5775 }, + { 2396, 8314, -1022, -4673 }, + { -1516, 8501, 1950, -4969 }, + { -308, 7401, 1549, -4866 }, + { -112, 8340, 3003, -4920 }, + { -50, 9315, 1371, -5666 }, + { -659, 9449, 2496, -5547 }, + { 2573, 9148, -2270, -4783 }, + { 830, 7104, -438, -3907 }, + { 522, 10672, -677, -6483 }, + { -1190, 10108, -510, -6518 }, + { -427, 8271, -579, -6315 }, + { 1602, 8113, -1927, -4418 }, + { -2266, 8180, 448, -5190 }, + { -1633, 8816, -226, -5771 }, + { 759, 9481, -105, -5813 }, + { 2254, 6679, -466, -5662 }, + { -88, 6946, 895, -5958 }, + { -1705, 10009, 1394, -5574 }, + { 748, 7943, 540, -6692 }, + { 1411, 7009, 232, -6145 }, + { 697, 7290, -1221, -5342 }, + { -1764, 10580, 1944, -3981 }, + { -1334, 9124, 1195, -3903 }, + { -905, 10067, 635, -5039 }, + { 664, 10680, 49, -4625 }, + { 1374, 9536, -777, -3591 }, + { 252, 9698, -597, -2931 }, + { 824, 9164, -1014, -2144 }, + { 2438, 10569, -2289, -4424 }, + { 2101, 7102, 507, -3614 }, + { 294, 8051, -432, -1518 }, + { -665, 10337, 547, -2852 }, + { 1168, 11989, -492, -5427 }, + { 1344, 6416, 302, -5061 }, + { -1727, 12264, 1507, -4543 }, + { 674, 10889, -902, -3605 }, + { -582, 9504, 300, -3618 }, + { 641, 7654, 689, -2109 }, + { 2065, 9243, 508, -4367 }, + { 1055, 8373, 688, -3144 }, + { -641, 8185, 986, -3307 }, + { 1120, 7426, 1785, -3757 }, + { 1660, 8070, -593, -3104 }, + { 2002, 9467, -1722, -3475 }, + { 2361, 8368, 100, -3709 }, + { -772, 7845, -613, -4988 }, + { 1485, 7430, 1896, -6127 }, + { -432, 7823, -947, -2882 }, + { 313, 11122, -760, -4871 }, + { 412, 8412, -283, -4231 }, + { 1585, 10402, -1884, -3267 }, + { 321, 6952, 773, -3016 }, + { -105, 9014, 121, -2249 }, + { 1585, 10313, -977, -4812 }, + { 1619, 11869, 1306, -6876 }, + { -1168, 8886, -81, -2500 }, + { -395, 10886, 733, -6490 }, + { -4949, 4274, 3992, -1054 }, + { -4241, 5299, 4262, -1584 }, + { -2710, 3862, 4552, -1673 }, + { -4608, 2472, 3672, -1715 }, + { -2843, 2816, 4003, -2326 }, + { -5229, 2964, 5636, 90 }, + { -4924, 3442, 5015, -1096 }, + { -1281, 3313, 5537, -2066 }, + { -3808, 1939, 4351, -919 }, + { -1915, 2585, 4939, -1614 }, + { -3470, 1843, 5562, -682 }, + { -3800, 870, 5827, 144 }, + { -4985, 1452, 4728, -709 }, + { -3745, 2750, 7220, 259 }, + { -1875, 1900, 6514, -826 }, + { -4329, 1574, 7192, 1304 }, + { -5408, 1444, 6208, 631 }, + { -3327, 5312, 5707, -1541 }, + { -6966, 3334, 4034, 1028 }, + { -7484, 4245, 4218, -212 }, + { -6567, 5839, 4539, -512 }, + { -5715, 5935, 3747, -1186 }, + { -6410, 4881, 3356, -1610 }, + { -5146, 2590, 2850, 2172 }, + { -5196, 4095, 2569, -373 }, + { -5043, 6025, 4318, 692 }, + { -5525, 4884, 3513, 370 }, + { -6804, 7533, 5812, -488 }, + { -5657, 2480, 4061, 1234 }, + { -3155, 1472, 6071, 1188 }, + { -3427, 5217, 3442, 858 }, + { -4698, 3013, 5517, 2586 }, + { -4449, 2226, 5418, 3580 }, + { -6395, 3547, 5487, 2028 }, + { -3500, 5019, 4787, 1 }, + { -4038, 2578, 3073, 3151 }, + { -2750, 1955, 4469, 3856 }, + { -5696, 1659, 6118, 2469 }, + { -4350, 1241, 6840, 3126 }, + { -5565, 5058, 5196, 1314 }, + { -1642, 4190, 3948, 607 }, + { -1233, 4108, 4850, -640 }, + { -997, 3428, 3239, 1378 }, + { -6488, 2741, 6926, 2792 }, + { -4188, 3763, 4235, 2018 }, + { -3210, 3224, 5646, 1427 }, + { -5526, 6909, 5070, -627 }, + { -2815, 3994, 3425, 1903 }, + { -2163, 2734, 5423, 145 }, + { -4149, 4247, 2355, 734 }, + { -410, 2521, 4138, -16 }, + { -2411, 2385, 4927, 2105 }, + { -6077, 3591, 3114, 594 }, + { -4186, 4834, 5926, -1004 }, + { -7315, 3369, 5966, 448 }, + { -7042, 5721, 5771, 238 }, + { -4466, 3907, 3535, -1751 }, + { -2116, 3970, 6163, -1392 }, + { -7239, 2143, 8407, 3630 }, + { -5431, 4486, 6486, -42 }, + { -1874, 1617, 6333, 519 }, + { -6478, 2629, 4634, -505 }, + { -7784, 2342, 7216, 1365 }, + { -1154, 1432, 4831, 1544 }, + { -4964, -5801, 1797, 506 }, + { -4436, -6905, 1059, -1237 }, + { -5400, -6886, 884, -290 }, + { -6259, -7103, 523, -227 }, + { -4819, -6450, 1412, -450 }, + { -4056, -6213, 1725, -943 }, + { -5642, -6091, 1357, 605 }, + { -4196, -5678, 2187, -173 }, + { -4726, -5126, 2470, 321 }, + { -6642, -5091, 1507, -1005 }, + { -5304, -5250, 1944, 1579 }, + { -7179, -5520, 1468, -425 }, + { -6033, -4895, 1876, -955 }, + { -6595, -5143, 2207, 1291 }, + { -4224, -4943, 1846, 1792 }, + { -7128, -6950, 539, 724 }, + { -4369, -4901, 2590, 1103 }, + { -7413, -5696, 1712, 1440 }, + { -5885, -6821, 418, 871 }, + { -6828, -5599, 710, -1563 }, + { -6123, -5817, 1358, 1631 }, + { -5291, -5622, 578, 2138 }, + { -7171, -6004, 347, 2208 }, + { -6083, -5251, 2132, 425 }, + { -4329, -5721, 407, -2993 }, + { -5326, -5056, 1119, -1837 }, + { -5485, -5856, 185, -2389 }, + { -6529, -5178, 403, -697 }, + { -6719, -4412, 2726, 871 }, + { -5126, -5629, 1835, -771 }, + { -5622, -4361, 2973, 858 }, + { -5282, -5895, 45, -335 }, + { -4357, -5656, 1696, -1558 }, + { -7139, -6659, 627, -409 }, + { -4415, -6328, 35, 1306 }, + { -7639, -6110, 1134, 197 }, + { -3626, -5592, 2019, 901 }, + { -3547, -5064, 1176, 1738 }, + { -5075, -3899, 2087, 266 }, + { -4086, -6311, 1479, 360 }, + { -6210, -5220, -199, -1477 }, + { -3910, -5063, 1356, -15 }, + { -7616, -4977, 461, 2401 }, + { -6118, -6131, 1258, -563 }, + { -6127, -4968, 1286, -27 }, + { -4121, -5852, 1113, 1476 }, + { -5157, -4881, 1162, -662 }, + { -4637, -5031, 1179, 709 }, + { -5509, -5452, -397, 1224 }, + { -4597, -6861, 646, 467 }, + { -6247, -4043, 468, 278 }, + { -5336, -6465, 874, -1472 }, + { -6998, -6346, 78, -1798 }, + { -4915, -4530, 2756, -203 }, + { -6048, -4373, 1468, 1052 }, + { -4273, -7100, 942, -323 }, + { -6552, -4287, 2351, 69 }, + { -6954, -4613, 722, 1521 }, + { -4201, -5361, 763, -1562 }, + { -6881, -5596, -748, 669 }, + { -6695, -3547, -34, 1299 }, + { -3981, -5728, 84, 111 }, + { -4663, -4809, 2173, -1031 }, + { -6599, -6077, 1303, 256 }, + { -7596, -4265, -5791, -4140 }, + { -6610, -2758, -5288, -3936 }, + { -5880, -3865, -6563, -3088 }, + { -7228, -5510, -7677, -3912 }, + { -8854, -6553, -8318, -5361 }, + { -9362, -5249, -6413, -4319 }, + { -4418, -3110, -6368, -4358 }, + { -5544, -4203, -6863, -5013 }, + { -3056, -4316, -5567, -3181 }, + { -3078, -5999, -5051, -2657 }, + { -5884, -6292, -5756, -4013 }, + { -4825, -4549, -5535, -4053 }, + { -4443, -6126, -5316, -1368 }, + { -3972, -6341, -6098, -2686 }, + { -5751, -2781, -5398, -6230 }, + { -4466, -6135, -5570, -3679 }, + { -4291, -5992, -3564, -5189 }, + { -7189, -4429, -7279, -6082 }, + { -5076, -4433, -2748, -5366 }, + { -6225, -2825, -6833, -5663 }, + { -2989, -4792, -3960, -4492 }, + { -7836, -7773, -7722, -5741 }, + { -6559, -5703, -5844, -5589 }, + { -7612, -5438, -4136, -3774 }, + { -4218, -4176, -6591, -2333 }, + { -4837, -5063, -6581, 322 }, + { -6590, -5990, -2980, -3847 }, + { -5558, -2971, -5489, -1932 }, + { -7001, -5323, -4975, -1697 }, + { -4694, -2688, -6904, -3044 }, + { -8511, -5379, -5767, -2549 }, + { -7548, -5412, -6522, -2572 }, + { -6597, -4973, -6423, -1274 }, + { -6415, -4022, -5168, -1072 }, + { -5528, -5530, -7218, -2345 }, + { -4845, -4805, -5943, -1227 }, + { -6049, -7150, -6744, -2161 }, + { -9061, -7299, -8542, -4375 }, + { -5010, -5546, -5416, -82 }, + { -4135, -4205, -5109, -3373 }, + { -3311, -5869, -4007, -5061 }, + { -5993, -6472, -3962, -4718 }, + { -2966, -5832, -2821, -6305 }, + { -4851, -5152, -2067, -3930 }, + { -3620, -4441, -3362, -5836 }, + { -4469, -5221, -4534, -5592 }, + { -4022, -6335, -4321, -6107 }, + { -4899, -4503, -3084, -3725 }, + { -4490, -8276, -4620, -6236 }, + { -6591, -4342, -7365, -4063 }, + { -6498, -5057, -5553, 485 }, + { -6060, -2714, -7093, -4144 }, + { -6199, -7774, -7094, -4057 }, + { -7536, -6424, -6415, -4265 }, + { -7439, -2454, -6348, -4827 }, + { -5333, -7565, -4417, -4639 }, + { -4353, -7103, -4197, -2689 }, + { -5229, -6549, -5129, -6804 }, + { -6129, -7701, -5236, -4836 }, + { -6797, -3983, -3884, -4406 }, + { -6624, -4467, -4745, -5052 }, + { -3324, -7596, -2720, -6553 }, + { -5473, -6284, -1704, -4511 }, + { -4131, -7263, -3180, -5196 }, + { -7116, -5565, -3469, 685 }, + { -6002, -6021, -3858, 576 }, + { -3144, -8203, -1291, -434 }, + { -6096, -7027, -4004, 1353 }, + { -3943, -7709, -2344, -36 }, + { -4510, -6767, -2642, 631 }, + { -3657, -11541, -2570, -3984 }, + { -5959, -8854, -1333, -867 }, + { -6699, -8866, -1606, -344 }, + { -3836, -7961, -2334, -2028 }, + { -3430, -8045, -3037, -672 }, + { -3868, -9184, -3635, -1819 }, + { -4258, -9060, -2621, -1008 }, + { -3595, -8693, -2022, -752 }, + { -4573, -8048, -3166, -2622 }, + { -4852, -7903, -1405, 256 }, + { -4591, -7057, -1560, 965 }, + { -6963, -7655, -980, 808 }, + { -5179, -6641, -3356, 1196 }, + { -7102, -6941, -2798, 2123 }, + { -6867, -5834, -3320, -770 }, + { -5977, -7369, -2500, -778 }, + { -6160, -6400, -934, -2543 }, + { -6741, -7608, -355, -1289 }, + { -6856, -6466, -1433, -1643 }, + { -4786, -6292, -4970, 376 }, + { -5407, -8866, -2255, -400 }, + { -3814, -6506, -1387, -3620 }, + { -4998, -6137, -1200, -4092 }, + { -5123, -9557, -2849, -1306 }, + { -4259, -6444, -4395, -338 }, + { -5221, -6810, -883, 1225 }, + { -6137, -6215, -2165, 554 }, + { -3895, -6557, -3176, -1829 }, + { -3886, -8188, -87, -954 }, + { -7243, -6707, -2216, -316 }, + { -5592, -7606, 85, -432 }, + { -3957, -7945, -504, -144 }, + { -4617, -7624, 218, -312 }, + { -4797, -8737, -844, -1051 }, + { -4478, -8516, -1401, -454 }, + { -4557, -7058, -302, -2332 }, + { -6623, -7736, -271, -50 }, + { -3157, -7532, -1111, -2207 }, + { -3590, -7300, -1271, 517 }, + { -4442, -7306, -507, 590 }, + { -6458, -7524, -2807, 666 }, + { -4991, -8466, -3363, -785 }, + { -7474, -7541, -1056, -1839 }, + { -7501, -8316, -938, -180 }, + { -5329, -7739, -579, -2341 }, + { -4549, -7063, -176, -3539 }, + { -5191, -8612, -1504, -4250 }, + { -3083, -7058, -2251, 32 }, + { -4003, -7043, -1093, -791 }, + { -5523, -8093, -678, -114 }, + { -3022, -10265, -2070, -3109 }, + { -3905, -6274, -182, -3652 }, + { -3269, -9217, -551, -2650 }, + { -3138, -9314, -1726, -1704 }, + { -4420, -10339, -1744, -3459 }, + { -4163, -8609, -2298, -4113 }, + { -5566, -6505, -1241, -463 }, + { -3130, -9746, -2352, -4884 }, + { -7825, -3439, 1451, -1468 }, + { -8451, -3318, 2360, -435 }, + { -8462, -4130, 1438, -1024 }, + { -9425, -4564, 1328, -689 }, + { -11014, -3202, 2278, 2080 }, + { -8269, -2761, -146, -440 }, + { -7497, -2618, -166, 413 }, + { -8250, -3060, 522, -2133 }, + { -8365, -5366, 1347, -451 }, + { -8589, -3979, 2943, 714 }, + { -8111, -2572, 1272, -1748 }, + { -7830, -5193, 605, -1484 }, + { -8119, -4736, 2141, 256 }, + { -7724, -4769, 1463, -812 }, + { -7363, -3911, 2540, 4 }, + { -7974, -3397, 2363, 1366 }, + { -7359, -4204, 1752, -958 }, + { -7622, -3505, 660, 916 }, + { -9934, -3665, 3165, 828 }, + { -8721, -4162, 62, 1718 }, + { -9433, -4768, 2722, 1234 }, + { -7960, -4496, 138, 1528 }, + { -8198, -3454, -443, 631 }, + { -7756, -2246, 655, 1137 }, + { -8841, -3145, 1113, 829 }, + { -7817, -3298, 1251, 230 }, + { -9413, -2733, 323, -1862 }, + { -9408, -4168, 1270, 1549 }, + { -9037, -3892, -942, 283 }, + { -8255, -3849, 1301, 1762 }, + { -9057, -3987, -41, -682 }, + { -9441, -4187, 2019, -111 }, + { -9740, -3178, 1602, -871 }, + { -8344, -2474, 1461, 1506 }, + { -9752, -2925, 1996, 1243 }, + { -9199, -3796, 180, 537 }, + { -9060, -2405, 1140, -1562 }, + { -9348, -2376, 309, -162 }, + { -10786, -3182, -5, -1500 }, + { -8142, -4540, -434, -826 }, + { -7528, -2341, 1104, -73 }, + { -9360, -2658, 3062, 56 }, + { -8267, -2335, 2000, -1193 }, + { -12169, -3154, 1287, -640 }, + { -11398, -2120, 946, -1163 }, + { -8940, -4559, 328, -1696 }, + { -11025, -4213, 2813, 840 }, + { -9224, -3581, 2224, 2039 }, + { -8943, -3337, 1248, -1298 }, + { -7900, -4042, 485, -2080 }, + { -9221, -1947, 2191, -880 }, + { -10762, -1800, 2516, -324 }, + { -10095, -2238, 981, -1335 }, + { -11908, -2808, 3255, 645 }, + { -10640, -4105, 1283, -595 }, + { -7663, -2863, 2467, -797 }, + { -10712, -3854, 3710, 1538 }, + { -10823, -2893, 1408, -801 }, + { -9874, -3832, 256, -1638 }, + { -10394, -3391, 2315, -94 }, + { -11525, -4079, 4153, 2122 }, + { -9546, -2088, 1541, 481 }, + { -8731, -2433, 1042, 2160 }, + { -7852, -3977, -1370, 1677 }, + { 7072, -3420, 1398, -1741 }, + { 6180, -1976, 1280, -3557 }, + { 7692, -1793, 2844, -1700 }, + { 8363, -1773, 3104, -2679 }, + { 9213, -3266, 3756, -3542 }, + { 9650, -2644, 1426, -1318 }, + { 7712, -2796, 3686, -1975 }, + { 7316, -3517, 2821, -622 }, + { 7434, -2594, 2305, -2264 }, + { 7237, -1797, 255, -3114 }, + { 8663, -1983, 1338, -3056 }, + { 6616, -952, 4059, -2652 }, + { 8823, -1327, 1362, -1356 }, + { 9938, -1722, 1287, -2362 }, + { 7207, -1057, 1913, -1315 }, + { 7508, -1585, 870, -1982 }, + { 8217, -3680, 1417, -3170 }, + { 8329, -2541, 1684, -585 }, + { 8062, -2335, 252, -2800 }, + { 8204, -4108, 3097, -2569 }, + { 7701, -3367, 576, -3008 }, + { 7350, -786, 2414, -2129 }, + { 6948, -2568, 1607, -225 }, + { 7684, -2387, 1308, -3449 }, + { 8306, -3458, 2394, -1454 }, + { 8438, -2781, 1043, -1362 }, + { 9175, -2076, 2144, -1987 }, + { 8347, -2709, 3489, -4301 }, + { 5696, -2377, 2870, 851 }, + { 8825, -1243, 2219, -2603 }, + { 8801, -1614, 584, -2513 }, + { 8413, -384, 1421, -2244 }, + { 9228, -3050, 3279, -2164 }, + { 6342, -2698, 3547, -107 }, + { 10053, -2476, 2837, -3168 }, + { 7439, -604, 3177, -3991 }, + { 7749, -1064, 4329, -4855 }, + { 8655, -2177, 2252, -3519 }, + { 8490, -228, 1958, -3233 }, + { 10513, -2968, 1911, -2340 }, + { 8146, -862, 1884, -1723 }, + { 7788, -666, 3004, -2891 }, + { 7785, -1620, 4133, -3417 }, + { 10262, -3731, 3455, -2971 }, + { 8570, -905, 4519, -4649 }, + { 9129, -2562, 463, -2465 }, + { 9451, -3587, 1904, -3056 }, + { 6549, -2236, 3010, -4523 }, + { 7175, -2684, 2967, -3458 }, + { 9872, -3278, 1054, -2472 }, + { 9153, -931, 1217, -2565 }, + { 8789, -3469, 753, -2568 }, + { 6683, -3791, 1797, -3968 }, + { 6801, -1977, 2311, -452 }, + { 6336, -1572, 2612, -3264 }, + { 7996, -1008, 730, -2964 }, + { 7521, -1059, 1573, -3694 }, + { 8148, -3973, 2600, -3572 }, + { 7765, -1532, 2528, -3856 }, + { 7404, -3918, 4472, -143 }, + { 8894, -1398, 3299, -3685 }, + { 5768, -2041, 1487, -637 }, + { 5131, -2865, 2463, -811 }, + { 6439, -1568, 3500, -1550 }, + { -8878, -6798, -5319, -1452 }, + { -6332, -9713, -3112, -990 }, + { -8444, -6316, -3694, -687 }, + { -6123, -10840, -3637, -4358 }, + { -4784, -9580, -4577, -2581 }, + { -6108, -10515, -4859, -2524 }, + { -7605, -7518, -2327, -2797 }, + { -9662, -8775, -2467, -2010 }, + { -6494, -7523, -4715, -118 }, + { -8290, -8982, -1672, -317 }, + { -8798, -11051, -3888, -1426 }, + { -6273, -6623, -6791, -142 }, + { -8313, -7668, -2141, -1275 }, + { -6453, -8412, -3589, -4102 }, + { -6747, -7750, -5690, -2498 }, + { -7814, -6693, -3174, -2446 }, + { -10383, -10130, -3931, -2364 }, + { -10606, -8467, -5539, -2772 }, + { -9475, -6671, -3305, -2271 }, + { -8982, -9457, -5635, -4005 }, + { -10111, -7965, -6515, -4180 }, + { -7301, -6479, -5364, 720 }, + { -9543, -8999, -7921, -912 }, + { -9534, -8562, -3469, -384 }, + { -7601, -10344, -3205, -1127 }, + { -8088, -8620, -4954, -2888 }, + { -8202, -8406, -7038, -3775 }, + { -7312, -8324, -3334, -1775 }, + { -8566, -9262, -8071, -4174 }, + { -7068, -11300, -5573, -2907 }, + { -8295, -8952, -4366, -1544 }, + { -11104, -10210, -2285, -384 }, + { -5213, -7520, -5008, -1339 }, + { -5889, -7940, -5987, -1385 }, + { -10816, -8201, -4153, -1485 }, + { -10277, -8919, -6315, -1652 }, + { -5888, -10320, -3821, -1733 }, + { -10497, -7181, -6083, -3032 }, + { -7721, -9724, -6591, -5336 }, + { -5688, -7894, -3486, -2552 }, + { -10014, -10500, -3247, -820 }, + { -6301, -8765, -4506, -2923 }, + { -8261, -7847, -6213, -1552 }, + { -10212, -7481, -8113, -3954 }, + { -6938, -10874, -6074, -4703 }, + { -7183, -10968, -4446, -1773 }, + { -7120, -9193, -1966, -2509 }, + { -6234, -9263, -2313, -4284 }, + { -8503, -9857, -2429, -608 }, + { -9372, -7844, -8391, -2120 }, + { -7951, -7157, -6535, -11 }, + { -7256, -9473, -2172, -660 }, + { -10063, -9612, -2515, -15 }, + { -6684, -9134, -6109, -4206 }, + { -8204, -11932, -5220, -2306 }, + { -9710, -6706, -4115, -3275 }, + { -6855, -7078, -2409, -4447 }, + { -7344, -7673, -4479, -4116 }, + { -8851, -6842, -4927, -2948 }, + { -8927, -10452, -5633, -2194 }, + { -8627, -9002, -7176, -1575 }, + { -8209, -9722, -7021, -3324 }, + { -3770, -10249, -3623, -4816 }, + { -8183, -7465, -4090, 646 }, + { -8163, -7149, 200, 498 }, + { -8289, -6266, 686, -206 }, + { -10030, -6241, -1032, -1864 }, + { -8793, -8327, -773, -169 }, + { -9149, -6215, 969, -15 }, + { -8303, -5859, -7, 2006 }, + { -9682, -7283, 255, 1322 }, + { -9293, -7227, 71, -231 }, + { -8525, -6215, 287, -837 }, + { -10477, -5379, 1159, 1449 }, + { -10726, -7856, -130, 102 }, + { -8694, -7461, -1210, 690 }, + { -9367, -5324, 1103, 3170 }, + { -10686, -8055, -831, 1633 }, + { -9201, -6873, -2704, 2258 }, + { -8421, -5358, -1405, 226 }, + { -9066, -5830, -307, -1571 }, + { -11150, -7381, -2746, -900 }, + { -9978, -5925, -2006, -437 }, + { -9464, -4741, -273, 1061 }, + { -10543, -6684, -1113, 1660 }, + { -10073, -5576, 1083, -269 }, + { -8826, -5763, 1600, 1486 }, + { -10445, -9071, -1253, -64 }, + { -12085, -5799, 2, 769 }, + { -12939, -6663, 1650, 1437 }, + { -10932, -6434, -1252, -649 }, + { -11650, -7826, -2053, 710 }, + { -12122, -6733, -1889, -731 }, + { -9093, -6095, -2463, -842 }, + { -10977, -4364, 469, 420 }, + { -11488, -6908, -521, 893 }, + { -9669, -5478, -842, 337 }, + { -10606, -5203, -632, -1361 }, + { -10198, -6284, 1662, 1277 }, + { -10135, -5292, 2435, 3493 }, + { -11027, -6561, 655, 56 }, + { -10977, -5030, 1127, -358 }, + { -12766, -3986, 1348, -335 }, + { -14244, -7731, 264, 317 }, + { -15124, -10309, -508, 1447 }, + { -12821, -8638, -608, 137 }, + { -13076, -8693, -2852, -431 }, + { -11156, -5546, -2252, -1600 }, + { -8692, -7366, -819, -1223 }, + { -12507, -9816, -1714, -121 }, + { -10712, -6666, 544, 3349 }, + { -12462, -5890, -2491, -2318 }, + { -12468, -7226, 437, 232 }, + { -11300, -5226, 2068, 687 }, + { -11994, -8320, -626, 2728 }, + { -12222, -5476, 1142, 18 }, + { -10277, -8122, -2418, 2003 }, + { -13418, -6115, -3563, -2802 }, + { -14759, -9834, -1243, 21 }, + { -13699, -5665, 1525, 507 }, + { -16269, -9476, -701, 163 }, + { -12677, -5437, -247, -1019 }, + { -11827, -4295, -181, -1243 }, + { -12847, -4496, 2984, 1123 }, + { -13860, -7915, -1166, -547 }, + { -12276, -8145, -2290, -1527 }, + { -11417, -4830, 2983, 1854 }, + { -11793, -6002, 1163, 1940 }, + { 11443, -4920, -3235, 3151 }, + { 11300, -6616, -1506, 1175 }, + { 9198, -4628, -2060, 2390 }, + { 10532, -4027, -643, 912 }, + { 9902, -3573, -1606, 1327 }, + { 9653, -3536, -2240, 1869 }, + { 9948, -5171, -423, 2662 }, + { 12316, -4004, -1989, 281 }, + { 12125, -4800, -1265, -163 }, + { 10650, -2617, -2337, 1462 }, + { 9909, -4968, -2376, 916 }, + { 12944, -4647, -1958, 460 }, + { 12988, -5283, -1141, 41 }, + { 12321, -2915, -3621, 1025 }, + { 11449, -2894, -2728, 351 }, + { 12087, -3041, -2002, -32 }, + { 11558, -4031, -1343, -399 }, + { 12983, -3740, -3516, 1245 }, + { 12099, -2515, -2752, 225 }, + { 12515, -3465, -2701, 550 }, + { 14683, -5022, -5272, 2996 }, + { 12260, -3383, -1215, -528 }, + { 13810, -5422, -2443, 1166 }, + { 13421, -5378, -1886, 721 }, + { 12961, -4259, -2594, 796 }, + { 12266, -2104, -4768, 1591 }, + { 13523, -4710, -3045, 1342 }, + { 12437, -2099, -5610, 2117 }, + { 11850, -2183, -3497, 661 }, + { 12275, -3936, -597, -697 }, + { 12459, -5253, -517, -544 }, + { 12835, -4094, -1322, -168 }, + { 14360, -5677, -3305, 1859 }, + { 13905, -4552, -4309, 2117 }, + { 11559, -3412, -1847, -81 }, + { 13379, -3167, -5764, 2746 }, + { 11910, -1634, -4342, 1052 }, + { 12662, -4742, 71, -974 }, + { 13057, -3254, -4424, 1705 }, + { 15046, -5706, -4851, 3019 }, + { 14162, -4142, -5514, 2843 }, + { 12764, -1845, -6684, 2888 }, + { 13714, -2374, -7838, 3857 }, + { 13295, -1663, -8293, 4073 }, + { 10032, -4152, -3403, 1421 }, + { 10942, -5386, -2222, 950 }, + { 10532, -6385, -1750, 1925 }, + { 10273, -5972, -1534, 643 }, + { 10605, -4782, -1695, 27 }, + { 10988, -5153, -1123, -341 }, + { 11629, -5884, -1060, 48 }, + { 10441, -4045, -2431, 311 }, + { 10788, -3595, -4171, 1807 }, + { 12110, -5686, -2127, 976 }, + { 11746, -4773, -2639, 891 }, + { 11541, -5299, -3031, 1732 }, + { 11416, -2559, -5359, 2198 }, + { 11583, -5376, -704, 677 }, + { 10416, -3214, -3516, 872 }, + { 9651, -5435, -1618, 3255 }, + { 9973, -5133, -996, 3923 }, + { 11707, -4643, -430, -796 }, + { 10994, -2709, -3587, 2302 }, + { 10716, -5118, -645, 270 }, + { 14100, -10314, 1095, 1531 }, + { 12944, -8049, 1105, -741 }, + { 13276, -7035, -511, 274 }, + { 14008, -7254, -283, 139 }, + { 11594, -6536, -91, 1671 }, + { 11732, -8645, 746, 15 }, + { 14613, -7085, -1578, 1183 }, + { 13083, -6224, -750, -4 }, + { 13988, -6256, -1592, 820 }, + { 14678, -8683, 441, 126 }, + { 15571, -8872, -521, 1139 }, + { 15642, -9533, 341, 697 }, + { 15960, -9586, -168, 1121 }, + { 15464, -10239, 1433, -1 }, + { 14934, -7887, -1046, 1080 }, + { 15252, -7630, -1899, 1628 }, + { 15485, -8384, -1234, 1484 }, + { 15962, -8638, -1815, 1931 }, + { 16501, -10664, 398, 1167 }, + { 16146, -10145, 411, 918 }, + { 14573, -7475, -697, 601 }, + { 14302, -7996, 28, 257 }, + { 14769, -6792, -2286, 1574 }, + { 14144, -6137, -2169, 1257 }, + { 14770, -6271, -3111, 1933 }, + { 14110, -8312, 1083, -531 }, + { 15235, -6991, -2993, 2174 }, + { 13222, -5805, 547, -891 }, + { 14796, -8762, 1254, -246 }, + { 16040, -9181, -1005, 1551 }, + { 16487, -10086, -373, 1420 }, + { 15077, -9479, 966, 51 }, + { 13026, -6468, 932, -1080 }, + { 12703, -6152, -33, -573 }, + { 15641, -6810, -4128, 2874 }, + { 13282, -7673, 1583, -1283 }, + { 12373, -7150, 1512, -917 }, + { 12992, -7751, -678, 783 }, + { 10907, -6858, -313, 2597 }, + { 13026, -8963, 125, 2152 }, + { 12770, -9946, 1957, -505 }, + { 12482, -6849, -1268, 833 }, + { 13790, -6181, -138, -279 }, + { 12709, -8382, 2044, 227 }, + { 12244, -6630, 203, -457 }, + { 14209, -6816, -1032, 632 }, + { 15134, -8267, -288, 640 }, + { 13619, -6157, -1090, 356 }, + { 14044, -7413, 725, -484 }, + { 12958, -7753, 2585, -1980 }, + { 13188, -8396, 2306, -1558 }, + { 14379, -9980, 2132, -688 }, + { 14275, -9857, 1162, 179 }, + { 13690, -8648, 1621, -889 }, + { 11770, -6829, -746, 278 }, + { 12732, -8202, 286, 90 }, + { 13630, -10146, 1867, -207 }, + { 12072, -8740, 1299, -645 }, + { 12852, -9492, 1226, 62 }, + { 11792, -7382, -54, -116 }, + { 13779, -9014, 487, 351 }, + { 11951, -7729, 121, 834 }, + { 11970, -9781, 2276, -4 }, + { 12680, -7984, 2787, -787 }, + { 13300, -14488, 6408, -1927 }, + { 13635, -15355, 9153, -3073 }, + { 12804, -13566, 5517, -1625 }, + { 16624, -10854, 1690, 28 }, + { 20387, -18532, 6162, -261 }, + { 16515, -12642, 3392, -519 }, + { 15800, -11095, 2151, -202 }, + { 16824, -11790, 1651, 599 }, + { 17604, -13213, 2563, 538 }, + { 17892, -14177, 3562, 147 }, + { 16987, -11399, 869, 1052 }, + { 17003, -12456, 2442, 265 }, + { 21657, -21806, 9198, -1250 }, + { 16825, -13341, 3980, -686 }, + { 17525, -12714, 1887, 805 }, + { 16419, -11034, 1216, 617 }, + { 20931, -19939, 7469, -684 }, + { 18452, -15390, 4573, -191 }, + { 14778, -10077, 2841, -1209 }, + { 17402, -13319, 3042, 160 }, + { 19365, -17922, 7087, -1061 }, + { 16298, -11941, 2810, -351 }, + { 19087, -16176, 4775, -84 }, + { 17666, -12289, 938, 1224 }, + { 18581, -15894, 5132, -430 }, + { 19823, -16717, 4142, 545 }, + { 19960, -19423, 8400, -1492 }, + { 18973, -16817, 5906, -594 }, + { 19079, -15431, 3528, 503 }, + { 16667, -12485, 4467, -1302 }, + { 19791, -17797, 6196, -529 }, + { 20005, -17606, 5354, -20 }, + { 20123, -18599, 6886, -728 }, + { 19068, -14805, 2394, 1105 }, + { 14443, -13723, 5631, -2029 }, + { 14730, -14231, 5631, -1450 }, + { 16089, -15959, 7271, -2029 }, + { 13473, -11200, 3236, -924 }, + { 14413, -10902, 2347, -267 }, + { 17666, -18662, 11381, -3496 }, + { 14749, -11042, 3305, -275 }, + { 15304, -10486, 1869, -240 }, + { 14809, -12126, 3369, -616 }, + { 16896, -16561, 7307, -1845 }, + { 15782, -14336, 5380, -1264 }, + { 16395, -15520, 6415, -1588 }, + { 13681, -11114, 2584, -320 }, + { 14244, -12326, 4480, -1632 }, + { 15247, -13119, 4265, -898 }, + { 13987, -12091, 3469, -597 }, + { 13941, -12770, 4240, -839 }, + { 13771, -13627, 5252, -1384 }, + { 15010, -16074, 7592, -2249 }, + { 15852, -17226, 8619, -2655 }, + { 18921, -16916, 6875, -1501 }, + { 14909, -11678, 2768, -295 }, + { 18988, -18353, 8424, -2070 }, + { 15457, -15080, 6218, -1513 }, + { 14916, -15512, 6949, -1883 }, + { 18108, -14702, 4681, -701 }, + { 17600, -15733, 5616, -775 }, + { 14070, -13683, 6472, -2626 }, + { 13832, -11914, 5201, -2232 }, + { 18846, -19009, 9192, -1961 }, + { -11981, -10994, -6324, -2264 }, + { -10976, -9047, -6546, -3828 }, + { -11288, -10532, -7014, -4191 }, + { -10139, -10189, -7799, -2688 }, + { -10555, -9988, -9181, -2040 }, + { -11596, -11339, -10022, -2707 }, + { -13400, -13395, -11306, -4206 }, + { -9774, -12281, -7466, -4133 }, + { -10842, -13125, -8777, -4956 }, + { -11964, -15082, -9779, -5095 }, + { -9382, -10188, -9053, -4927 }, + { -11562, -11296, -3651, -985 }, + { -9287, -10083, -7918, -4069 }, + { -12821, -16556, -11410, -6195 }, + { -12628, -8959, -4521, -1113 }, + { -13845, -11581, -3649, -681 }, + { -12685, -10269, -5483, -1275 }, + { -14988, -12874, -5107, -1189 }, + { -13761, -11367, -6202, -1804 }, + { -13225, -11249, -7820, -3354 }, + { -14809, -11992, -3202, -312 }, + { -15620, -15519, -10210, -3433 }, + { -12954, -10200, -3139, -611 }, + { -11536, -9981, -5284, -923 }, + { -13034, -12417, -4612, -1098 }, + { -16911, -15505, -6123, -1352 }, + { -17396, -17685, -8330, -2171 }, + { -14120, -10764, -2265, -99 }, + { -12598, -7367, -5406, -3530 }, + { -14143, -12793, -10909, -5226 }, + { -14692, -16871, -11626, -5554 }, + { -12581, -11197, -9194, -3837 }, + { -16752, -16726, -9746, -2808 }, + { -10600, -10358, -6560, -1227 }, + { -14573, -13312, -8957, -3393 }, + { -10172, -8463, -8579, -3387 }, + { -11418, -12421, -5522, -1842 }, + { -11855, -14204, -6669, -2625 }, + { -13308, -8191, -3941, -2194 }, + { -10007, -12266, -5022, -1811 }, + { -13532, -15771, -9497, -3175 }, + { -11760, -11148, -10339, -5529 }, + { -12149, -12763, -11198, -3697 }, + { -12029, -12119, -8555, -1792 }, + { -16995, -19957, -11447, -3471 }, + { -13144, -14504, -9988, -3191 }, + { -9938, -11064, -6139, -3162 }, + { -8873, -11550, -8294, -6550 }, + { -9303, -13010, -6150, -2711 }, + { -15463, -10469, -1766, -170 }, + { -15985, -11693, -3007, -650 }, + { -17142, -10671, -1434, 47 }, + { -16063, -13858, -4817, -1058 }, + { -19446, -19599, -9594, -2464 }, + { -20076, -18744, -8313, -1889 }, + { -15047, -16085, -7590, -2250 }, + { -13481, -16195, -8552, -2998 }, + { -13829, -14869, -6704, -1932 }, + { -16357, -18484, -9802, -2959 }, + { -10551, -8393, -9303, -5070 }, + { -11345, -9156, -5641, -3107 }, + { -13217, -13449, -9270, -4541 }, + { -11988, -13732, -9995, -6374 }, + { -11007, -9519, -5168, -4107 }, + { 9930, -7858, 8061, -4375 }, + { 8274, -7867, 5992, -2096 }, + { 9692, -9675, 7621, -3670 }, + { 9589, -8110, 6509, -3010 }, + { 12617, -11976, 10122, -5360 }, + { 11867, -8895, 7948, -5323 }, + { 10388, -10482, 9234, -4324 }, + { 8188, -8220, 7810, -2737 }, + { 10407, -8787, 4806, -1930 }, + { 10348, -8845, 9233, -6614 }, + { 9422, -7091, 4820, -2878 }, + { 9758, -9796, 5584, -2256 }, + { 10188, -7994, 5347, -3343 }, + { 11133, -7455, 4015, -2306 }, + { 10676, -10744, 6093, -2629 }, + { 11522, -12184, 7848, -3375 }, + { 8805, -9883, 5317, -3071 }, + { 9498, -9654, 6555, -3592 }, + { 10488, -8008, 4066, -1252 }, + { 11261, -8930, 6068, -2738 }, + { 12180, -10397, 5027, -1531 }, + { 9138, -8531, 3601, -1959 }, + { 8107, -8380, 4970, -2061 }, + { 9737, -13248, 6438, -2617 }, + { 11178, -10423, 2622, -522 }, + { 9572, -12372, 5199, -2019 }, + { 12057, -12144, 4147, -1099 }, + { 9047, -9925, 2516, -665 }, + { 10790, -8030, 5882, -4386 }, + { 7199, -8426, 6337, -2841 }, + { 7778, -8285, 3529, -3442 }, + { 7559, -10569, 3484, -1332 }, + { 9404, -8115, 7484, -5541 }, + { 7792, -11976, 5546, -2573 }, + { 9313, -10264, 7661, -5195 }, + { 6701, -10725, 4370, -1784 }, + { 4918, -11361, 4507, -4527 }, + { 5147, -12305, 3978, -5556 }, + { 6525, -9899, 4481, -3129 }, + { 7538, -12855, 6060, -4826 }, + { 8659, -12111, 7159, -4430 }, + { 8440, -11304, 4547, -1747 }, + { 9216, -10918, 3507, -1195 }, + { 6165, -9254, 4771, -4677 }, + { 9163, -11019, 5637, -4935 }, + { 13441, -11509, 6676, -2434 }, + { 7912, -9398, 6663, -4048 }, + { 11723, -13745, 8131, -4148 }, + { 6065, -10257, 5005, -6327 }, + { 11618, -12417, 5336, -1894 }, + { 8891, -13924, 8407, -6131 }, + { 9622, -12563, 7908, -5109 }, + { 11479, -10315, 8349, -3991 }, + { 11676, -14103, 6611, -2330 }, + { 11951, -8953, 3829, -1550 }, + { 10486, -8044, 10493, -5920 }, + { 11801, -10769, 9763, -5305 }, + { 6109, -8676, 5827, -1346 }, + { 7030, -9611, 5624, -5761 }, + { 12808, -12886, 8683, -4148 }, + { 13213, -10464, 6381, -3189 }, + { 11796, -13681, 10703, -6075 }, + { 9639, -7949, 9625, -3944 }, + { 8538, -6997, 5309, 453 } +}; + +/* quantization tables */ + +const uint32_t ff_dca_scale_factor_quant6[64] = { + 1, 2, 2, 3, 3, 4, 6, 7, + 10, 12, 16, 20, 26, 34, 44, 56, + 72, 93, 120, 155, 200, 257, 331, 427, + 550, 708, 912, 1175, 1514, 1950, 2512, 3236, + 4169, 5370, 6918, 8913, 11482, 14791, 19055, 24547, + 31623, 40738, 52481, 67608, 87096, 112202, 144544, 186209, + 239883, 309030, 398107, 512861, 660693, 851138, 1096478, 1412538, + 1819701, 2344229, 3019952, 3890451, 5011872, 6456542, 8317638, 0 +}; + +const uint32_t ff_dca_scale_factor_quant7[128] = { + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 5, 6, 7, 7, 8, + 10, 11, 12, 14, 16, 18, 20, 23, + 26, 30, 34, 38, 44, 50, 56, 64, + 72, 82, 93, 106, 120, 136, 155, 176, + 200, 226, 257, 292, 331, 376, 427, 484, + 550, 624, 708, 804, 912, 1035, 1175, 1334, + 1514, 1718, 1950, 2213, 2512, 2851, 3236, 3673, + 4169, 4732, 5370, 6095, 6918, 7852, 8913, 10116, + 11482, 13032, 14791, 16788, 19055, 21627, 24547, 27861, + 31623, 35892, 40738, 46238, 52481, 59566, 67608, 76736, + 87096, 98855, 112202, 127350, 144544, 164059, 186209, 211349, + 239883, 272270, 309030, 350752, 398107, 451856, 512861, 582103, + 660693, 749894, 851138, 966051, 1096478, 1244515, 1412538, 1603245, + 1819701, 2065380, 2344229, 2660725, 3019952, 3427678, 3890451, 4415704, + 5011872, 5688529, 6456542, 7328245, 8317638, 0, 0, 0 +}; + +/* 20 bits unsigned fractional binary codes */ +const uint32_t ff_dca_lossy_quant[32] = { + 0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063, + 796918, 461373, 251658, 146801, 79692, 46137, 27263, 16777, + 10486, 5872, 3355, 1887, 1258, 713, 336, 168, + 84, 42, 21, 0, 0, 0, 0, 0 +}; + +/* 20 bits unsigned fractional binary codes */ +const uint32_t ff_dca_lossless_quant[32] = { + 0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127, + 262144, 131072, 65431, 33026, 16450, 8208, 4100, 2049, + 1024, 512, 256, 128, 64, 32, 16, 8, + 4, 2, 1, 0, 0, 0, 0, 0 +}; + +/* Vector quantization tables */ + +DECLARE_ALIGNED(8, const int8_t, ff_dca_high_freq_vq)[1024][32] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -4, -2, 2, 1,-16,-10, 1, 3, 1, 0, 6, 1, -3, 7, 1,-22, + 2, -4, -3, 11, 14, 6, -1, 1,-13, 29,-28, 10, 10, -8, 0, -9 }, + { -8, 8, -7, 10, -3,-12, -5, -8, 1, -2, 9, -2, -5,-18, 1, 9, + -8, -8, 3, 41, 7, -9, -9, 22,-42,-29, 14,-18,-14,-32, 1,-15 }, + {-16, 8, 15, 16,-16, 5, 2, 7, -6,-16, -7, 1, 1, -3, -2, 0, + 8, 20,-26,-11, 2,-17, 0, -3,-34,-37, 10, 44, -2, 22, 2, -4 }, + { 7, 14, 5, 6, 15, -1, 3, -3, -9,-23, -5,-14, 8, -1,-14, -6, + -5, -8, 54, 31, -6, 18, 2,-19, -2,-11,-30, -6,-19, 2, -2,-14 }, + { 1, 2, -2, -1, -3, -3, 1, -5, 1, -3, -4, -8, 5, -4, 0, 1, + 3, 7, -5, -4, -3,-12, 3, -2, -3, 12,-53,-51, 6, -1, 6, 8 }, + { 0, -1, 5, 1, -6, -8, 7, 5,-18, -4, -1, 1, 0, -3, -3,-14, + -1, -6, 0,-14, -1, -1, 5, -3,-11, 1,-20, 10, 2, 19, -2, -2 }, + { 2, 4, 3, 0, 5, 0, 3, 1, -2, 0, -6, -3, -4, -5, -3, -3, + -7, 0,-34, 4,-43, 17, 0,-53,-13, -7, 24, 14, 5,-18, 9,-20 }, + { 1, 0, -3, 2, 3, -5, -2, 7,-21, 5,-25, 23, 11,-28, 2, 1, + -11, 9, 13, -6,-12, 5, 7, 2, 4,-11, -6, -1, 8, 0, 1, -2 }, + { 2, -4, -6, -4, 0, -5,-29, 13, -6,-22, -3,-43, 12,-41, 5, 24, + 18, -9,-36, -6, 4, -7, -4, 13, 4,-15, -1, -5, 1, 2, -5, 4 }, + { 0, -1, 13, -6, -5, 1, 0, -3, 1, -5, 19,-22, 31,-27, 4,-15, + -6, 15, 9,-13, 1, -9, 10,-17, 4, -1, -1, 4, 2, 0, -3, -5 }, + { -7, 3, -8, 13, 19,-12, 8,-19, -3, -2,-24, 31, 14, 0, 7,-13, + -18, 0, 3, 6, 13, -2, 1,-12,-21, 9, -2, 30, 21,-14, 2,-14 }, + { -3, -7, 8, -1, -2, -9, 6, 1, -7, 7, 13, 3, -1,-10, 30, 4, + -10, 12, 5, 6,-13, -7, -4, -2, -2, 7, -3, -6, 3, 4, 1, 2 }, + { -8, 9, 2, -3, -5, 2, 0, 9, 3, 7, -4,-16,-13, 3, 23,-27, + 18, 46,-38, 6, 4, 43, -1, 0, 8, -7, -4, -1, 11, -7, 6, -3 }, + { 1, 1, 18, -8, -6, 0, 3, 4, 22, -3, -4, -2, -4,-11, 40, -7, + -3,-13,-14, -7,-10, 14, 7, 5,-14, 11, -5, 7, 21, -2, 9, -3 }, + { 0, 0, -2, 4, -2, 0, 2, 0, -1, 2, -1, 0, 0, 2, 2, 2, + -1, 1, -3, -1,-15, -2,-63,-27,-21,-47,-14, 1,-14, 10, 0, 2 }, + { 1, 0, -4, 0, -3, -9, 4, 2, 6, -6, 0, -5, 11, -7,-15, 6, + -7, -6, 3, 7,-15, -5, 23,-13, -6, 12, -8, 9, 2, -3, 3, 4 }, + { 6, 0, 3, 0, -2, -4, 2, 1, 1, -1, 1, -2, -1, -4,-22,-15, + -46,-66, 10, 20, 2,-17, 12, -6, 1, -2, -2, 0, 1, -5, 1, 2 }, + { -1, 0, 0, 1, 0, -4, 0, 1,-10, -3, -8, 5, 7,-11, 2,-11, + 29,-25, 11, 10, 0, -1, 5, -7, -2, -5, -2, 4, 4, -3, 5, -2 }, + { 1, -1, -1, -3, -2, 1, -8, -3, 2, -2, 4, -5, -1, -7, -2, 1, + -14, -7, 3,-30,-15,-14, 3, -4, -1, 3,-13, -1, -3, 1, 2, 3 }, + { -1, -2, -3, 2, 2, -3, 3, 1, -3, 2, 0, -4, 6, 5, -5, 10, + -57, 3, 22,-50, 1, -2, -5, -6, -1, 5, 1, 2, 2, 1, -2, 2 }, + { 2, 0, -1, -7, 2, 1, 3, 2, 0, 4, 3, -2, 3, -3, 4, -4, + 24,-35, -3, 38, -6, -5, 15, 20, 3, 16, -7, -5, 0, -4, -5, 0 }, + { 0, 1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -2, 0, 0, 0, 0, + 0, -1, -2, -1, -5, -2,-43, -3, 46,-52,-10, 7, -8, 11, -2, -1 }, + { 0, 0, -1, 0, -1, 2,-41, 33,-44,-48,-15,-26, -9, 6, 3, 3, + -3, 2, 2, 2, 2, -1, -1, -2, 1, 3, 0, 0, 5, 2, 3, 1 }, + { -4, 1, 6, 1, -6, -1, -2, 1,-14, -4, 0, -5, -2, 2, -2, 0, + -6, 1, 0, 8,-21, 32, -3,-36, -6, -2, -1, -7, 3, 0, 1, -6 }, + { -3, -2, 3, 0, 2, 2, 8, -4, -4, 6, 2, 1, 3, -6, 4, 3, + 13, 0,-12, -1, 25,-20, -2,-23,-15, 7, -3,-11, -3, 6, -1, 0 }, + { 0, 0, -3, -1, 0, 0, -2, -1, -2, -2, 1, -1, 0, 0, 10, 3, + -2, 3, 3, -7, -6, -5, 0, -4,-60,-16, -6, 38, 5, 6, -5, 0 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 1, 0, 0, 1, + 0, 0, -1, 0, -8, 2, -9, 10, 40, 31,-56,-21, 4, 20, -4, 7 }, + { -2, -2, 0, 4, -3, -1, 7, 3, 1, 3, -8, 0, 3, 1, 2, 5, + 1, -2, 14, 5, 4, 5, 5, 5, -5, 9,-66, 0,-20, -2, -8, 4 }, + { -2, -1, 4, -1, -8, -2, -4, -1, -3, -3, 2, -7, -3, 5, 7, -2, + 45, 31,-17,-16, -2, -2, -1,-22, 1, -1, -3, 3, 5, -3, 5, -1 }, + { -4, 0, 7, 5, 8, 7, 2, 9, -9, -9, -7,-11, -3, -8, 17, -4, + 34, 32, 18, 22, 1, 2, 1, -7, -5, 6, -1, 6, 4, 10, -2, -7 }, + { 6, 0, 14, 9, 6, -1, -2, -3, 4, -6, -8, 4, 7, -1, 28, 38, + 15, -1, 16,-11, 5, 8, 4,-10, 3,-10,-17, 5, 3, 3, 3, 1 }, + { 1, 1, 2, -1, 2, 1, 0, 0, -1, 0, 0, -2, 1, -3, 0, 1, + 2, -2, -4, -2, 0, -1, 1, -3, 1, 1, 1, -1, 8, 8, 66, 33 }, + { -5, 2, -3, -7, 2, -8, -4, 10, 17,-18, -7, 4, -4, -7, -6, -6, + -5, 5,-12, 2, 0, 6, 8, -2, 1, 4,-11, 2, 1, 8, 31, 19 }, + { 6, 9, 16, -6, -6, -1, -2, -3,-11, -2, 7, 7, 17, 3, 4, 10, + 2, 5,-13, 8, 7, 1, 4, 5, 7, 6, 7, -8, 9, -8, 33, 6 }, + { 3, -1, 1, 0, -7, -5, 0, 14, -7, 1, -7, 1, 2, -4, 7, 10, + -16, 12, 1, -6, 3, 8, -1, 10,-13, -6,-12,-23, 12, -3, 30, 14 }, + { -2,-15, 0, 8, 3,-19, 5, -3, 2, 3, 13, 7, 14, -3,-10, 0, + 8, 5, -6,-16, -8, -8, 14, 2, -1, 1, -9,-11, 11, -5, 27, 9 }, + { -8, 6, -4, 4, -4, -1, 5, 4, 1, -7, -5, -4,-15, 1, 9, 0, + 8, 4, 1,-17, 11, -2,-19, -1, -6, -8, 3,-12, 3,-17, 33,-10 }, + { -3, -1, 2, 7, 7, -2, 9, 8,-18, -1,-13,-10, -3, -3, 11, 8, + -2,-12, -8, 1, 4, 9, 14, 10, -3, 0, 2, 1, -2, 3, 31, 10 }, + { -3,-10, 8, -1, -5,-11, 7, -5, 3, 6, 1, 4,-16, 10, 5, -4, + -2,-10, -1, 13, 6, -5, -7, 12, 7, -3,-17, 1, 12, -4, 29, 8 }, + { 1, 2, 5, 2, -6, -7, 0, -1, 6, -1, 10, 6, -4, 5, 2, 2, + -2, -8, -6,-11, 14,-13, 27, 3, -2,-12, 5,-16, 2,-26, 20, 15 }, + { -1, -3, -5, -3, -3, 6, -1, 3, -5, 1, 7, 2, 1, 0, -1, -1, + 0, -1, 9, 7, -6, -3, 4, -5, -4, 8, -8,-25, -8, -4, 34, 23 }, + { -1, -2, 1, 1, -1, -2, -1, 1, -1, 0, 0, 0, 0, -2, -1, 1, + 0, 2, 1, -1, 4, 0, 0, 1, -1, 0, 5, 3, 12, -9, 68,-16 }, + { 10, 0, -8, 14, -6, 1,-12, 0, 0, -3, -5,-11, -6, 12, 9,-10, + -3, 5, 0, 7, 11, 2, 4, -3, -8, -3, 7, 4, 3, -3, 34, 4 }, + {-12, 13, -5, 7,-11, -2, -1, 1, -4,-14,-21, 3, -3, -3, -4, -7, + -9, -4, 3,-17, -2,-13, 10, -2, 12, -4, 0, -9, 1, -5, 31, 10 }, + {-10, 6, 5, 6, 4, -7, 10, 0,-28, -3, 0,-11, -1, -5, 16,-10, + -16, 7, 20, 2, -4, 2, -5, 0, 15, 6, 5,-10, 7, -9, 20, 4 }, + { 1, -7, -2, -7, 4, -3, -2, -7, -1,-14, 6,-16, 4, -5, -4, -6, + -5, 0, -2, 2, -6, 9, -5, 4,-18, 8,-10, 8, 15, 0, 32, 1 }, + { -5, 7, -3, 7, 15, -4, 0,-16, 9, 5, -5, 5, 4, -3,-12, -9, + -18, 10, 2, 2, -3, 7, 3, -1, 6, -9,-10, 3, 15, -4, 35, -7 }, + { -1,-10, 2, 2, -4, -2, 10, 2, -1, 2, -2, 1, -1,-14,-11, 3, + -8, 5, -8, -2, 6, -1, -7, 1, 7, 5, 7, 8, 30, -4, 30, 14 }, + { 2, -2, 1, 2, 3, -8, 3, 0, -2, 0, -9, 2, 1, 4, -6, -1, + -2, 5, 0, 1, -2, 12, 6, -3, 9, -3, 4,-12, 21,-39, 24, -2 }, + { 3, 5, 1, -2, -2, -2, -3, 6, -8, -2,-11, -8, -1, 4, 2, 2, + -4,-10, 12, -5,-11, 1,-15,-34,-11, -7,-11, -1, 7,-14, 38, -1 }, + { -4, 4, 8, 9, 8, 1, -5, -9, 4, -2, 15, -4, 11,-15, 20, -1, + -1, -3, 4, -9, -2, -2, -2, 8, 6, 12, -5, 0, 11,-12, 27, -4 }, + { 0, 8, -4, 3,-11, 6,-11, 2, 3, 0, 5, -8, -7, -6, -9,-21, + 4,-11, -1,-16, -7, 16, -3, 7, -7, 4, -5, 0, 11, -7, 31, 3 }, + { 1, 3, 4, 11,-11, -2, -3, -6, 6, 5, 0, 3, -9, -6, 4, -4, + 0, 4, -8, 13, -6,-13, -1, -5, -1, 4, 0, 0, 9,-22, 24, 18 }, + { -7, 3, 10,-13, -6, 6, -6, 6, 22, 1, 0,-14, 2, 3, 7, -1, + 8, 20, -1, 5, -4, 13, 9, -9, -9, 6, 0, -4, 0, -8, 31, -4 }, + { -3, -4, 0, 1, 7, 3, -7, 0, 5, -2, 1, 3, 3, 1, -5, -2, + 5, 2,-11, 4, 0, -1, 12, 0, -3,-13, 15, 8, -6,-27, 34, 0 }, + { -3, -3, 10, -4, 2, -1, -3, 0, -1, -1, -4, 2, 6, -2, 12, 1, + 3, -6, -7, -6, -5, 4,-19, -6, -8,-34, -4, -8, 10, -7, 23, 10 }, + { -7, 0, -1, -6, 8, 4, -4, 2, -5, -8, -7, -9, -8, 5, 9, 7, + -6, 1,-12,-12, -1,-16, 5, 0, 16, 3, -7, -8, 27, -4, 23, 15 }, + { -8, 4, 8, 5, 6, 11, -3, 5, 3, -1,-11, 6, -5, 0, 2, -6, + -3, -6, 4, -1, 5, -5,-12, -6, 7, -5, 9, 3, 6, -7, 29, 1 }, + { 1, 3, -2, -2, -6, -2, 1, 6, -6, -3, 1, 2, 3, 4, 1, 5, + -1, 0, 4, 2, 11, 6, 2, -3, 13, -9,-19, 18,-15,-10, 36, 21 }, + { -3, -3, 2, -1, -7, 6, -4, 1, -3, -1, -2, 2, 3, -7, -3, 0, + -2, 0, -2, 6,-19, 3, -8, 2, -6, 7, -1, 0, 29, -6, 28,-10 }, + { -5, 1, -3, -7,-12, -4, 1, 1, -1, 13,-10, -1, -9, -5,-13, 6, + 13, 3, -4, 2, 3, 11, 2, 6,-25,-16, -6, 0, 14, -1, 27, 16 }, + { -6, -1, -7, -5, -2, -5, -5, -1, 9, 1, 0, 3, -8,-12, -6, 5, + -6, 5, 3, -9, 1, 4, -7,-10, -9, -7,-17, -5,-15,-23, 25, 3 }, + { -8, -2, 9, -3, -4, 3, -1, 8, -7, -7, -5, -4, -2, 9, 4, -1, + -7, -4, -5,-16, 3, -6, 18,-13, -9, 16,-15, 8, 15,-10, 24, 5 }, + { 1,-38, 2, 34, 9, 10, 11, 2, 2, -6, 3, 2, -2, 5, 4, -7, + -1, 1, 4, 0, 3, 1, -8, -1, -6, 5, 4, 2, -4, 5, 2, -1 }, + { 1,-22, 15, 18, -2, 10,-16, -9, -8,-11, 8, 4, 0, 7,-14, -5, + -1, -7, 12, 17, 9, 5, -7, -4,-12, -6, 7, 0, 7, 2, -2, 1 }, + {-11,-29, 7, 10, 19, -1, -8, -9, 7, 1, 9, 6, 8, -7,-14, 8, + -3,-11,-13, 0, -7,-23, -2, -8, 12, 9, 2, 14, 19, 1, -1, 5 }, + {-24,-27,-11, 36, 2, 6, -3, 4, -6, 8, 0, 12, -1, -4, -6, 3, + 4, -1, 2, -3, -2, 3, 2, -1, -2, -4, 0, -1, -2, 7, 2, 3 }, + { -9,-24, 11, 13,-10,-12, 12, -2, 7, 4, 8, 13, -3, -3, 2, 9, + -3, -4, 4, 13, 5, 13, -6, -3, 1, 15, 7, -3, 0, 19, -2, -9 }, + { -8,-15, 7, 14, -4, -5, 2,-18,-19, -2, 2, 17, 16, 6,-10, 10, + -9, 14, -1, -5, -1, -6, -7, 2, 9, 11, 13, 6, -5,-12, 3, 2 }, + {-10,-37, 13, 1, 3,-14, 0,-20, 4, -3, 8, 2, -2, -3, -9, -5, + -3,-17, -1, 13,-11, 2, -6, 4, 4, 0, 3, 1, -9, -4, -5, -4 }, + { -2,-22, -5, 46, -8, 5, 9,-11, 8, 7, 7, -1, -1, -2, -7, 2, + -3, 3, -1, -2, 7, 0, 2, -1, 1, -2, -2, -3, 6, 0, -4, -6 }, + {-16,-27, 15, 16, -4, 14, -7,-26, 2, -2, 6, 5, -3, 11, 0, 2, + 3, 9, -7, -1, 2, -4, -4, -1, 6, 10, 1, 1, -3, -2, 3, 0 }, + { -3,-22, 10, 26, 1, 2, -3, 3, 17, -3, -7, 9, 1,-21, -4, 5, + 3, 0, -7, -6, 3, 3, -8, -7, -9, 3, 7, 1, -8, 12, 6, -7 }, + { -9,-25, 3, 18, 9, -6,-11, 0, -5,-12, 9, -8, -7, -6, -6, 22, + 2, -6, -3, 15, 3, 2, -2, 9, 14,-10, -7, 15, 13, 6, -2, 11 }, + { 5,-20, -5, 28, 11, 10, -4, -4, 0, -7, 3, 5, 2, -5, -8, 2, + 6, 10, 9, -9,-18, 3, 14, 1, 3, -3, -1, -6, 7, 7, 2, -1 }, + { -8,-30, 7, 12, 10, 8, 7,-13,-16, 0, 1, -1, -6,-11,-15, 4, + 1, -2, 10,-15, 1, 11, -2, 8, 9, -7, -7, 9, -5, 2, 7,-18 }, + {-10,-32, 10, 11, 3, -1, 3, -5, 5, 2, 14, -6, 3, 1, 5,-15, + -11, 6, 20, 4, 0,-12, -7, 3, 1, -1, 10, 6, -1, -9, -4, -1 }, + { 1,-25,-14, 12,-11, 9, 9,-16,-24,-17, 22, -9, 11,-30, -3, -4, + 6, -7, 9, 2, -1, -5, -6, 2, -1, -1, 10, 1, -3, 3, 4, 8 }, + {-14,-26, -6, 9, 8, 17,-11,-24, -7, -4, -8, -2, 10, 2, 2, -1, + 2, 13, 12, -7, 4, -6,-10, 6, 6,-13,-11, -7,-16, 0, -2, 5 }, + { -4,-30,-13, 12, 16, -6, 12,-16,-13, 5, 15, -2, -2,-10, -7, 7, + 11, -1, -4, -2, -4, 7, 4, -8, 1, 3, 0, 11, 3, -2, -5, 4 }, + { -4,-21, 20, 22, 2, 20, -8, 1,-12, -5, -9, 4,-10,-17, -3, -8, + -3, 3,-12, 1, -3, 0, 7, 4, 7, 7, -3, 7, 5, 3, 1, -5 }, + {-12,-20, 2, 29, 11, -6, 9, -7, -6, -4, 0, 6, 17,-13, -2,-10, + -17, -1,-18, 2, 0, 14, -6, 1, 0, 3, 2,-10, 1, -5, -2, 5 }, + { 16,-37, -1, 26, -2,-14, 1, -5,-14, 2, 2, 3, 6, 1, 1, 4, + 0, -1, 0, -2, -2, 4, 9, -6, 0, -2, 10, -7, -2, 4, 1, 0 }, + { -9,-24,-12, 5, 5, 3,-17,-14, 4, 3, 2, -4, 10,-22, -8, -3, + 6, 1, 12, -8, 4, 1, 9, -1, 18, -3, 6, 5, 3, -5, 9, -5 }, + {-14,-33, -2, 20,-13,-10, 2, -7, -1, 11, -9, -8, 18, -3, 1, 8, + 0, -2, 10, 7, -2,-13, 9, -3, -4, 5, -2, -2, -1, -5, 1, -7 }, + {-10,-23, 8, 14, 1, 7, 1, -3, -7, 4, 1, 1, 8, -7, 15,-14, + 13, 14, 2, 5,-13, -5, -8, -1, 6, 3, 6, 9, 6, 15, 14, 5 }, + {-13,-25,-10, 13,-17,-24, -7,-13, -6,-10, -8, 2, 0,-13,-10, -4, + -8, 4, -9, 9, -4, 4, -3, -3, 3, 3, -5, -9, 1, -2, 11, 2 }, + {-12,-23, 1, 18,-11, -2, 5, 9, -5, 5, 14, -9, -3, -2, -6, 2, + -2, 11,-13, 1, -3, 11, -9, -4, -2, -6, 8, 10, 1, 4, 2, 1 }, + { -5,-18, 16, 22, 2, 0, 8, -6, -9, -7, 10,-16, 23, 10,-11, -1, + 7, 2, 7, 2, 1, -5, 6, 1, 0, -4, 9, 2, -3, 1, 0, -4 }, + { -3,-26, 14, 11, 2, -9, 17, -2, -1, -5,-16, -9, -5, 10,-13, 1, + 6, 12, 10, 11, 0, 0, -3,-14, 6, -2, 0, 4, -5, -1, -7, -1 }, + {-10,-33, 1, 8, 11, -5, 1, -6, 7, 4, 5, 6, 1, -2,-10, -5, + -6, 12,-11, 5,-10, 4, 12, -1, -1, -3, 4, -1, 9, 0, 16,-17 }, + {-14,-37, 7, 7, -2, 5, -8,-11, 2,-13, 4,-19, 1, 8, 8, 4, + -9, 2, -4, 3, 12, 2, 4, -4, -8, 8, 1, 4, 8, -1, 6, -2 }, + { -6,-30, 18, 17, 1,-22, -3, 4, -7,-10, 7, 0, -8, 8, -1, 4, + 2, 8, 6, -2, 2, 7, 4, 4, 3, -6, 2, 1, -3, 1, -1, -5 }, + {-17,-18, -3, 22, -8, 1, 9, -2,-17, 20, -5, -5,-12, -5, 4, -5, + -9, 8, -2, 16, -3, 0, 19, -8, 8, 1, 2, -4, 0, 11, 0, -3 }, + { -9,-23, 3, 10, 4, 4, -3, -2, -2, -2, 1,-22, 11, 0, -2, 5, + -2, 14, -9,-11, -4, 7, 5, 32, 1, -3, -7, 0, 21, -9, 7, -6 }, + { 0, 0, 0, 2, -1, 1, 0, 1, 3, 0, 0, 1, 0, 1, 0, 1, + -3, 0, -1, -2, 0, -1, -1, -3, -1, 1, -4, 1, -1, -5,-69,-19 }, + { -3, -5, -8,-12, 4, -3,-19,-11, -5, 0,-14, 7, 18, -6, 7, 22, + 8, 14, 15, 10, 3, -1, -3, 5, -1, 7, -7, 1, -6, 3,-26,-11 }, + { -1, -6, 4, -4, -5,-16, 0, -6, -3, 11, 1, 0, 9, 5, 16, 3, + -4,-33, -4, 4, -7, 0, 1, 6,-11, -2,-13, -2,-18, 20,-25,-16 }, + { 4, 0, -1, 0, -5, 1, 0, 2, 0, 11,-10, 4,-10, 7, 16, 2, + 16, 15, 2, -1, 2, 9, 2, 8, -3, -5, -2, 0, -3, 0,-33, -2 }, + { -3,-15, 10, 10, -9, -1, 7, 3, 5, -5, -8, -8, -3, 15, -9, 4, + 12, 13,-13,-14, 10, -6, 9, 22,-27, 23, -1, 5,-24, 2,-30, 5 }, + { 0, -2, 7, -5, -5, 3, 5, 3, -3, -5, 2, 1, -4, 3, -3, -1, + 1, -2, 10, 22, -3, -4, -2, -2, -7, 3, 8, 1, 14, 4,-37, 9 }, + { -3, -4, -1, 1, -4, 0, 6, 2, 6, -7,-10,-10, -1, -4, 11, -3, + 7, -6, 4,-12, -1, 5, 1, -7, 10, -6, 17, -4, 8, 3,-40, 13 }, + { 2, 12, 4, -7, 14, -3, 16, -2, 18, 2, 13, 5, 5, 1, 11, -1, + 0, 9, 2, -6, -1, 2, -6, 2, -5, 3, 5, 1, -1, 1,-32, -7 }, + {-16, 11, 7, -4, 2, -5, -9, 9, 11, 11, 15,-13,-11, 11, 9, 4, + 3, -8,-10, 12, 12, 0, 0,-16, -9, 13, 2, 9, 4,-13,-33, 3 }, + { 6, 4, 5, 4, 3, -1, 5, 6, 4, 2,-11, -1,-15,-11, -1, 1, + 11, -3, -2, 24, -4, -6,-25,-10,-15, -8, 0, 0, -5, 4,-30, 2 }, + { 10, -3, -6, 1, -9, -5, 6, 9,-10, -3, 8, -1, 4, -1, 11,-11, + 3, 9, 11, -3, 6,-17, 5, -8,-33, 9,-13, 19, -2, 9,-25, 2 }, + { 0, 0, -1, -3, 0, -2, 1, 0, 0, 2, 1, 0, -2, 0, -1, 2, + 0, -1, 4, -1, 2, -3, 4, -2, 3, 3, 1, 0,-15, 12,-63, 27 }, + { -2, 14, 9, -1, 3, 0, 1, 1,-19, 15, 3, 4, 0,-10, 1, -5, + 3, 0, -5,-10, 2,-16, -4, 8,-12, -6, 7, -5,-10, -1,-33, -4 }, + { 0, 3, 1, 3, 1, 2, 4, 4, 9, -6, -8, -5, 1,-12, 3, 8, + -10, 6, -1, 1, 13, -5, -5, 2, -4, 13,-18,-10, -7, -9,-33, 10 }, + { -6, -3,-12, 5, -1, 11, -6, 0, -2, 1, 2, -7, 3, 1, 3, -2, + 1, 8,-10, 7, -1, -3, 3, 0, 13, 1, 6, 7,-16, -7,-39, 8 }, + { -6, -1, 11, 6, -3, 8, 3, -5, 3, 0, -5, -2, -6, -3, -4, 2, + -3, 13,-11, 1, 7, 5, 19, -5, -3,-15, -1, 7, -1, 6,-33, 8 }, + { -7, 3, -4, -3, -4, 1, 6, -5, -5, 6, -8, -1, -7, 4, -1, -6, + -2, 1, 7, 0, 1, 1, -5, 2, -2, 0,-13, -2,-31,-14,-39,-12 }, + {-10, 9, 0, -3, 1, -1, -1, 0, 1, -5, -1, -4, -2, 5, 2, -7, + 18, -8, -2,-19, -7, -7,-12,-14,-11, -1, -9,-13, -7,-12,-31, -9 }, + { -3,-16, 10, 9, 1,-10,-12, 2, -2, 2, 7, -3, -3, 1, -4, -5, + -9, 5, 7, 3, -1, 4,-11, -8, 4, 13,-10, 13, 10, -4,-36, 1 }, + { -7,-12, 4,-20, -7, -7, 2, 11, -1, -2, 3,-12, 1, 0, -6, -7, + 6, 4, 13, 3, -3, 4, 3, -6,-12, 5, -5,-22,-13, -8,-37, -6 }, + { -7, 5, 3, 5, 7, 9,-14, -3, 10, 17, -1, 1,-12, 5, -6, 0, + -4, -9, 0,-11,-14, 3, 13, 6,-25, -8,-12, 4,-10, 18,-30, -1 }, + {-10, 6,-10, 6, 6, 1,-10, 0, -7, 5, -2, 17,-18, -4, 0, -3, + -16, -6, -3, -8, 5, 1, -4, 6, -7, 16, 6, 10, -1, 0,-32,-11 }, + { -1, 9, 9, -5, 4, 9, 6, 9, -4, -2, 7, 11, 4, 2, -5, -4, + -6, 0, 2, -3, -1, 5, 10, 0, 12,-10,-18, -3, -1, 14,-33, 2 }, + { 4, -8,-18, -4, -5,-11, 4,-10, -4, 9, 13,-12, 1, -6, 1, 2, + 4, -9, 8, 3, -6, 21, 13, -1, -2, 1, -2, 6, -7, 0,-30, 1 }, + { 6, -1, 2, -3, -1, -4, 6, -4, 0, 4, 2, 2, -9, 2, 6, 3, + -2, 4, -1, 9, -6, 0, 7, -8, 5, 19, -2, 9, -5, 2,-33, -8 }, + { 2, 1, 12, -5, -8, 8, 3, -2, -4, 1, -2, 5, -4, -9, -8, -8, + 7,-11, -4, 6,-10, 7, -1, -1, -2, -1, 16, 32, -7, 20,-33, -6 }, + {-18, 2, 6, 13, 9, 9, -1, 3,-17, 24, -2, -6, 28, 8, -2, 6, + 3,-10,-34,-16,-13, -4,-15,-11,-12, -3,-10, 4, -8, 4,-31, -4 }, + {-11, 0, 18, 2,-16, -9,-13, -2, -2,-12, -3,-22, 30, 0, 8, 3, + 9, -4,-16, 1, 0,-11, 15, -2, -4, 6, -5, 6, 1, 2,-25,-12 }, + { 14, -1, 5, 7, 3,-15, -8, 1, 5, -2, 12, 13, 11,-25, 3, 1, + 0, -2, -4,-16,-23, 0, -5,-17, 7, 5, -9, 6, -5, 2,-32, -7 }, + { 3, -1, 6, 14, 2,-12, -9, -9, 4, 7, 4, 6, 5, -8, 4, 2, + 4, 5, -2, 8, 8, -6, 0, 10,-20, -1, 3, -1, 8, 23,-33, -5 }, + { -3, 11, -6, 3, -4, 5, 7, 3, 4, 5, -2, 3, -1, 30, 6, 1, + 8, -6, 0, 0, -9, 6, -9, 4, 2, 9, -6, 1,-12, 0,-34, 18 }, + {-17, 13, 0, 1, 9, -4,-11, 0, 7, 0,-10, -4, -1, 6, -6, 4, + 1, 6, -9, 3, -5, -6,-11, 2, -4, 14, 23, -3, 2, 5,-30, 12 }, + {-14, 5,-27, 2, 0, 7, 1, 4, 30, 8, 7, 5, 1, -1, 0, 5, + 8,-10, 48,-11, 12, 33, 6, 8,-15, 20, -2, -5, 32, 5,-19, 10 }, + {-16, -4,-12, -7, -2, 0, 8, -6,-20,-18, 16, -3, 0, 31, -2, 11, + 2, -9, 49,-19,-12,-23, 10, 26, 16, -2, 4,-21,-14, 13,-11, -9 }, + { -5, -9, -1, 3, -5,-21, 2, 10, 0, 0, 10,-21, -7, 7,-26, -9, + 22, 32, 58, 11, -3, 11, -5, -8,-13, 6, -5, -9, 1, 10, 14, -8 }, + { 7, 7, 10, 3, -2, -1,-11,-11, -6,-43, -3, 14,-19,-18, 19, 18, + -32, 10, 45, -6, 6, 21,-20,-12, 2, 4, 6, 6, -4, 3, 3, 1 }, + { 21, 22, -3, -2,-11, -6, -1, -2, 8, 8, 32,-21, 7, 28, -4, -6, + -3, -2, 50, 2, 2, 27, -5, -8, 12, 7, -5, -1, -4,-17, 27, 6 }, + { 13, 7, 2, -6,-12, 2,-10, -5,-17, 11, 4, 17,-12, -2, 5,-17, + 37,-16, 48,-14,-18, 29, 8, 24, 11, -5, -9, 11, -1, 1,-13, -3 }, + { 1, 1, -1, 2, 0, 0, 0, -1, 1, -1, 7, 2, -3, 3, 0, 6, + 2, 10, 54,-25, 7, 54, -5, -6, -1,-15, 9, 13,-24,-15,-12, 3 }, + { 21, 5, 8, 3, -3, -4, -2, -4, 3,-11, -5, -8, 9, 16, 8, -9, + -10, -3, 46,-46, 2, 1,-10, 10, 17, 11,-20,-36, 10, 14, 0, -5 }, + { 7,-13, -6, -9,-24, 45, 2, 8, 8, 0, 17, 20, 12,-24, 1, -7, + -15, -3, 46,-13, -2, 20, 1,-13,-11,-13, 2, 15, 1, 10, -1, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, -1, + -16, -9, 31,-69,-34, 26, 7, 17, -1, -6, -1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, + -5,-20, 18,-82, 22, 3, -7, 9, 4, 6, 2, -4, -1, 0, -2, 2 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, -1, + 15, -5, 62,-36, 4, 52, -7, 5, 0, 6, 1, 2, 1, 1, -1, 0 }, + { 3,-19, 19,-20, 13, -4,-11, 8, 8,-16, 10, 1,-14, 30, 1,-33, + 10,-11, 45,-30, 3, -4, -3,-13, 7, 12, 3,-22, 3, -2, -4, -2 }, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, + 11, 8, 70, 48,-10, 21, 4, 9, -9, -9, -4, -6, 0, -1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 2, -1, 80, 2,-15,-36,-10, -5, -2, 8, -2, 2, 0, 0, 0, 0 }, + { 10, 8, -8, -8,-24, 12, -1, 0, 20, 9, -1, -2, 2, -2, 12,-10, + -2,-13, 35,-43, 44, 15,-10,-25, 4, 10, -3, -5, -5, 7, -1, 3 }, + { 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -1, + -18, 9, 49,-72, 7, -8, 7, -5, 2, 3, 2, -2, 1, -2, -3, 1 }, + { -1, 4, -3, 10, 19, 4, 3, 20, 6,-24, 6, 9, 8, 15, 18, 18, + -36, 19, 57,-11, 4, -3, 8, 7, 2, -3, -2, -9,-15, -2, 12, -4 }, + { 20, 3, 11, -9, -4, 22, 42,-25, 1, 5,-10,-19, 0, 9,-16, 5, + 2, 10, 44,-29, 17, -3, -9, -2, -1, 8, 14, -7, -1, 16, -5, 1 }, + { -7, 16,-11, 12, 6, 33,-15, 14,-23, 2,-26, 8, 2, 10, 0, -5, + 8, -8, 38,-38, -4, 5, 5, 5, 1, 22,-15, 7, 6, 0, 4, 28 }, + { -1,-12, 2, 10, -2, 0, 7, 17, 12, 22, -4, 10, 25, 29, 5, 18, + 4, 1, 27,-39, 31, 17, 2, 2, 22,-23, 13, 16, 1, -7, -4, -5 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 0,-14, 0, + -7,-11, 49,-22, -4, 19, 17,-39, 4,-29, 10, 2, 36, -4, 23, -1 }, + { -2, -2, -2, -2, 1, 15, -5, -7,-16, -8,-19, 16, -3,-20, 36, -9, + -3, 20, 39,-20, 0, 2, 27,-16, 10, 10,-14,-22,-16, -3, 13, -8 }, + { 5, -9, 6,-25, 7, 37, 13,-10, -5, 3, -5, 7, 18,-22, -7, 9, + -5, -4, 50,-11, -4, -5, -5, 8, -4, -2, -4,-27, 14, 20, 7, -9 }, + { 0,-14,-10,-27,-14,-17, -6, 26, 10, 2, 14,-12, -5, 0, 8, 9, + 0,-28, 55, -7,-12, -7, 4,-10, 10, 7,-12, 11, 3, 5, 9, -8 }, + { 2, 23, 4, -2, -1,-20, -2, 14, 10, -9, -9,-24, 10, 0, 11,-12, + 12, 11, 49,-25, -2, 29, 7,-13, 21,-10, 11,-17, 3, 1, -8, 5 }, + { 3, 0,-14, -6, 18, -2, 17, -9,-19, 9, -5, 9, 14, 6, 19, -3, + 27, 1, 41,-21, 20,-15, 33, 0, 26, 14, 7, 10, 3, 20, -3,-12 }, + { -1, 16, 15, -8, 3, -8, -8, 21, -5,-16,-29, 4, 1, -6, -4,-28, + 2, 31, 37,-26, -2, 13, 24, 8, -9, -6,-29, 10, 7, 2, 7, 8 }, + {-10,-10, 11, 13,-32, 2, 16, 9, 14, 23,-15,-13, 24, 13, 4,-27, + 14, 12, 31,-18, 17, 23, -2, -7,-14, 9,-17, -6,-10, 20, 9, 6 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 5, 1, 89, 8, 10, -6, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, + 4, -7, 64,-50, 7, 37, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -2, 5, 3, -4, -4, -3, 2, -3, 3, -3, 5, 4, 1, -6, -1, 1, + 6, -2, 50,-35, -7, 43, 7, -7, -5,-26, 24, 21, 3,-15, 5, 6 }, + { -8, 21,-19, 33, -8, 22,-11, 17, 3, 0, 0, -2, 1, -3, 6, -1, + 10, -8, 4,-11, -4, -5, 0, 8, -4, 3, 1, -4, 4, 2, 8, 4 }, + { -7, 5,-20, 9,-22, 3,-14, 1, 6, 13, 23, -2, -4, -7, 2, 0, + 11, 4, 6, 3, -7,-11, -7, 4, 5, 5,-12, 8, 2, 4, 7, -3 }, + { -7, 6, -4, 20,-20, 16, -2, 7, 6, 16, 11, 12, -7, -7, 5, 3, + -9, -4, 1, 2, 5, 2, 1, -9, -2,-17, -4, 6,-10, 7, -7, -6 }, + { -9, 18,-17, 12,-24, 1, -1, 4, 14, 9, 4, 3, 2, 8,-12,-14, + 4, -8, -4, 7, 7, 6, -1, 13, -9, -4, -1, 1, 0, -4, 15, 8 }, + {-25, 2,-11, 6, -5, 24,-28, -5, 8, 12, -2, 6, 8, -3, 8, -9, + -1, -5, -1, -5, 6, -1, -1, -1, -4, 8,-12, -2,-13, 7, 2, 1 }, + {-14, 14,-18, 20,-10, 12, -2, 9, 1, 0, 12, -2, 15,-10, 26,-17, + 16,-11, 10,-10, 9, -2, 4, -8, 2, -3, 4, 4, 2, -3, -5, 1 }, + {-18, 12,-18, 21, -6, 12, -6, 13,-25, 18, 1, 11, -9, -5, 0, 10, + -5, 3, -3, 8, -9, 7, 4, 2, -9, 0, 5, 0, 2, -3, 9, -8 }, + { -4, 16, 1, 18,-30, 9, 1, 6, -8, 13, 13,-12, -6, -1, 13, 7, + 6, 2,-15, -3, 5, 5, 1, -6, 1, -5, 0, 2,-16, 0, 3, -4 }, + {-21, 1, -2, 6,-43, 18, -1, 5, -1, 4, 6, -2, -1, -3, -1, -3, + 0, 1, 2, -9, 0, -1, 0, -2, 0, -1, -1, -2, 6, 0, 1, -2 }, + {-23, 10, 4, 7,-32,-11,-18, 2, -2, -7, -6, -3, -3,-12, 19, 3, + -5, -6, 16, -6, 16, 2, 16, 16, 8, -2, 13, 8,-15,-11, 2, 10 }, + { -8, 2,-13, 2,-29, 24,-20, 19, 1, 10, -4, 10, 1, 2, -9, 11, + -1, -2, 9, -5, 19, -7, 16, -9, -2,-18, 11, 1, 1, 0, 7, -3 }, + { -6, 3, 4, 13,-26, 10,-10, 28, -7, 28, 1, 7, 0,-14, 5, 7, + 4, -4, 3, -2, 3, 3,-11, 7, 6, 4, 0, -1, 2, -1, -3, 2 }, + { -6, 16,-31, 13,-10, 17, -6, 4,-14, 4, 4, -1,-10, 12, -5, 1, + -14, 15, 0, -8, 1, -5, 3, 3, 9, -5, 7,-20, 7, 4, 11, -5 }, + {-19, 3,-17, 14,-12, 16,-22, 18, 14, 8, -2, 4, 10, 12,-14, 4, + -3, 2, 3, 7, -7, 7, -6, 2, -2, -4, -5, 0, -5, -2, 2, 1 }, + { -9, -7,-11, 24,-36, -9,-11, 5, 7,-12,-13, 18, -2, 20, 1, -4, + -1,-10, 15, -6, 14, 1, 0, 2, 1, 2, -9,-16,-11, 7, 13, 0 }, + {-24, 24,-18, 18,-22, 14,-11, 13,-12, 11,-10, 11, -7, 11, -5, -4, + -1, 1, 5, 2, 3, -1, 1, -5, 7, -4, 5, -6, 8, -7, 8, -6 }, + { -6, 18,-22, 22, 5, 11, -1, 6, 19, 22, 8, 4, -8, 20, -2, 15, + -6,-18, 0,-33, -9,-12, -1, 6, 5, 2, 5, 5, -5,-17, -3, -3 }, + { 1, 11,-16, 9,-18, 11, -4, 18, 20, 26,-10, 8, 1,-11, 8, -4, + 0, 7, 3, 5, 2, 2, 10, -2, -4, 4, -4, -2, 1, -4, -5, -1 }, + {-10, 6, -1, 18,-17, 27, -3, 10, -2, 12, -7, -9, 1, 1, -1, 7, + -12, -1, -7, -6, -1, 8, 3,-15, 8, 9, 3, -7, 4, -1, 1, -1 }, + {-14, 6,-16, 22, 2, 5, 0, 5,-18, 11, 6, -3, 22,-20, -9, -3, + 6, -6, -7,-15, 1, 15, -8, 11, 8, -3, -8, 1, -8, 2, 6, -2 }, + {-21, 5,-19, 19, -7, 4, -7, 0, -8, 6, 12, 5, -3,-22,-13, -6, + -1, -3, -2,-14, 6, -3, 1, -8, -7, -5, -6, 11, -3,-10, -5, 2 }, + { -1, 9,-12, 15, -6, 6,-19, 14, -9, 11, 3, 12,-17, -3, 8, -4, + -3, -4, 1, -5, 4, 5, -7,-15, -7, 15, -6, -5, 1, -5, -3, 1 }, + {-12, 20,-15, 20,-14, 3,-14, 9, -6, 33,-13, 6, -2, 8, -6, 7, + -5, -6, -3, -3, 0, 8, -3, -3, 1, -2, 2, 2, 6, -5, -5, -2 }, + { -7, 12,-18, 12,-18, 10, -4, 8, 2, 4, 8, 9, 0, 3, -8, 3, + 6,-12, -4, 1, 25, -5, -9, 6, -7, 0, -9, -7, 3, -5, -4, -4 }, + {-18, 12,-10, 11,-22, 0,-15, 5, -2, 2, -3, 6, -4, -4, -3,-15, + -2, -3, 21, 6,-12,-11, 19, 3, 3,-14, 7, 0,-11,-22,-10, 0 }, + {-15, 2,-30, 15,-17, 13,-16, 8, -7, 10, -8, 2, 11, 3, 10, -7, + 7,-22, 12,-10, 3,-12, 6,-10, 12,-10, 7, -8, 5, 2, 9, 1 }, + { -9, 11,-14, 6,-10, 21, 5, 12, -5, 5, 7, 21, 6, 2, -2, -1, + -1, 4, 2,-20,-18, -1,-14, 3, -1, 4, -7, 10, 1, 11, 4, -4 }, + {-22, 8,-30, 13,-21, -4, 4, -1, 12, 9, -2, -3, 2, -6, 4,-13, + -2, 8, 8, 1, -7, 3, -4, -5, -1, -7, -2, 8, 8, 7, 8, 0 }, + { -6, -4,-35, 16,-13, 15,-11, 14, -7, 9, -1, 11, 7, 0, 13, 10, + -1, 8, 1, 1, -2, 8, -1, 2, 2, 3,-10, -1, 7,-13, -3, -7 }, + {-15, 7,-16, 14,-18, 17, -6, 14, 3, 4, 7, -3, 10,-22, 5,-15, + 4, -4,-11, 15,-15, 11,-11, 20, 1, 0, 2, 1, 11, -3, 11, -7 }, + {-12, 3, 5, 16,-37, -1, 15, 15,-15, 10, 3,-10, 1, 15, 7,-15, + -13, 8, 9, -3, 2, 12, -8, 2, -5, 0, -3, 4, 5, -9, -4, 5 }, + {-16, 26, -4, 14,-22, 26, 6, -3, -8, 4, 21, 6, 16, -4,-11, 7, + -10, 3, 3, 7, -4, 2, -9, 8, -2, 2, 5, -2, -4, -2, 7, -1 }, + { -7,-10, 4, 3, 2, -4,-12,-10, -4, -5, 16, 19,-16, 1, 2, -9, + -10, 0, 9, 7, -8, 3, 12, 8, -6,-11,-13, -1, -3,-20, 6, -5 }, + {-14,-17, 3, -5, 14,-12,-12, 8, -6,-25, 21, 21, 10, -8,-12, 4, + 10, -4, 3, -9, 11, 9, 0, 4, 2,-15, 1,-14, 4, 1, 0, -4 }, + { -4, -9, -3, -1, 6, 3, -6, 6,-10, -4, 14, 8, 2, -3,-12,-19, + 0, 11,-20, 1, 6, -2,-27, -6, 10,-17,-14,-17, -9, 8, -8, 3 }, + {-12,-13, 16, -4, -2, 12, -7,-11, 2,-13, 3, 7,-16,-18, -1,-12, + -2, 1,-12, -9, -2, -6, 2, 9,-22, -3, -4,-14, -7, 7, -1, 2 }, + { -7, -8, -8, 15, 15, 18, 15, 16, -4,-37, 11, 15,-12, -1, -3, 3, + 6, 6, 0, -5, -3, -5, 9, 1, 1,-11, -1, -8, -6, 2, 3, 0 }, + { -6, 7, -5,-12, 13, 10,-18, -4, -3,-21, 6, 16,-15, -7,-12, -9, + 1,-12, -1, 10, -2, -1, -3, 4, -4, 1,-16, -1, 12, -9, 5, 9 }, + {-14, -5, 9, 3, 4, 26,-28, 3, -6,-24, 4, 5, 3, 13, 5, -1, + 3, -1, 3, 1, 1, -5, 3, 0, -7, -8, -7, -3, 3, -5, 4, 0 }, + { -4, 2,-10, -6, 25, 26, -6, 10, -6, -8, 15, 11, -6, -3, 2, -7, + 5, 14, 9, -1, 0,-12, 4, -4,-10, 1, -3, 3, -2, -2, -6, -1 }, + {-10, 8,-15,-10, 19, 17, -8, 0, -3, -7, 7, 5,-13, -1, 7, -7, + 1, 13,-12,-13, 17,-12, 1, 26,-18, -3, -5, -6, 4, 5, 8, 1 }, + { 2, -5, 3, 0, 0, 0, 2, -3, -2, -5, 7, 13, -4, 9, 0, -5, + 4, -1,-11, -8, -4, 0,-13, 2,-47,-23, -8,-11, -4, 4, -2, -3 }, + {-18, -4, 4, 5, -1, 17,-12, -8, 1,-12, 7, 20,-12, 3, -2,-11, + 16, 12, -6, 1,-13,-16, -6, -3, -3, -5, 4,-12, -5, -9, 10, 1 }, + {-11, 0, 4, 7, 7, 8, 3, -1, 3,-19, 32, 8,-19, -8, 2, 4, + -12, 15,-16, 3, 1, 9, -2, 1, -2, 8, 5, 6, -4, -1, 11, -8 }, + { 3, -1, 4, -2, 14, 32, -9,-23,-10,-12, 22, 15, -1, -2, 10, 0, + 4, 6, -8, 4,-15, -2, -1, -4, 0, -8, 4, 1, -8, 3, 4, 1 }, + {-17,-12, 6, -8, 16, 13,-20, -8, -1,-16, 10, 21,-19, 11, -9, -5, + 7, 18, -6, 7, -7,-18, 13, 2, -2, 8,-12, -9, 2, 4, -5, 16 }, + { 4, 0, 17,-11, 12, 7,-12, 5, -1,-25, 30, -8, -7, -6, -4, -7, + 9, 8, 7, 3, 3,-16, 8, 0, -2, -2,-18, -3, -4, -5, 1, 4 }, + { -3, -6, 6,-16, 17, 6, -3, 2, -9,-17, 12, 11, 11, 2,-20, 8, + 1, 1, 0, 2, -2, -6,-21,-13, -9,-15, -1, -8, -6, -8, 0, -2 }, + {-11, -7, 6, -9, 3, 6, 8, 16, 4, -5, 23, 26,-10, -3, 4, 0, + 2, 2, -4, 4, -2,-12, 12, 10,-11, 0,-10,-16, 3, 0, 0,-10 }, + { -5,-16, 10, -6, 27, 13, -3, 4, -2,-13, 15, 5, 2, 5, 3, -4, + 13, 12,-11, -7, 0, 1, 11, 12, 2, 13,-15, -8, 9, -2, 3, 8 }, + { -5, -8, 4, 3, 9, 3,-11, 10, 14,-25, 14, 8, -2, 5,-12,-21, + 2, 10, -7, 2, -3, 2, 0, 2, -1, -3, -5, -6, -1,-16, 2, 8 }, + { -1, 5, 1,-11, 5, 9, -7, 8,-13,-12, 4, 12, -4, 1, -1, -1, + 27, 29, 10, 15, 2, -6, -3, 4,-21, 10, -9,-11, -6, -1, -9, -3 }, + { -6, -3, -1, -6, 11, -5, 0, -2, -5,-31, 11, 3, -1, 5, -3, 4, + 5, 7,-10, 5,-10,-13, 4, 12,-15, -2, 2, -7, 1, -9, -3,-10 }, + { -3, -7, 17, -8, -5, 36, 8, -7, -8,-20, 12, 8, 1, -1, 3, 0, + 1, 4,-10, 3, 1, 4, -2, -3, -2, -3,-10, 4, -1, -7, 3, 2 }, + {-13, -3, -5, 9, 22, 6,-23, 3,-10, -7, 17, 17, 18,-14, -8, -8, + 2, 4, -8, 2, -3, -8, 6, 4, -1, 7, 0, 0, -3, 0,-12, -3 }, + { -3,-10,-15, -3, 9, 3,-23, -9,-13,-18, 12, 13, -2, 0, 1, 8, + -1, 2, -7,-12, -5, 14, 2, 1,-22, 6,-10, -8, -9, 28, -7,-14 }, + { -3, 1, 2, -1, 13, 7, -2, -7, 1, -3, 6, 9, -3, -2, 4, -2, + 2, 1,-10, -2, -2,-22, -2, -7,-10, -5,-11,-27,-12,-16, 4, -7 }, + { 2, -6, -3, 1, 8, 0, -2, 12, -3, -4, 58, 15,-10, -4, -2, 2, + -2, 0, -2, -6, 2, 4, -1, 1, -4, 1, -1, -5, -4, -3, 3, 1 }, + { 10, -1, 0, 5, 21, 7,-14, 6, -3,-16, 15, 17,-16, 13, 3, -6, + -4, 6,-12, -5, 1, -4, -7, -8, 2, 3, -6, 6, -1, -8, 5, 4 }, + { -6, -2, -8,-11, 15, 10, 0, 8, -6,-15, 33, 8, -2, 18,-15,-11, + 5, -1, 0, 15,-15, -4, -4, -1, 10, 7,-13, 4, -4, 0, 8, 3 }, + { -7, -2, 0, -2, 0, -2, -4, -5,-14,-16, 12, 38, 7, 12, 6, -4, + 0, -1, 0, 3, -2, -6, 0, 2, -9, 1, 0, -1, 0, -2, 4, 1 }, + { -8, -4, 18, 1, 14, 5,-12, -3, 20,-17, 5, 19,-11, -8, 11, -3, + 3, 9, -7, -8, 9,-17, 2, 15,-10,-11, 5, -5, 7, 15, -6, -2 }, + { -7, 2, 38, 5, 19, 16, -5, 4,-13,-20, 0, 4, -4, 6, 4, 2, + -7, 6, -8, -2, -5, -7, 6, 3, -4, -3, -2, -3, 7, -6, -4, 0 }, + {-11,-12, 8,-15, -3, 14, -7,-22,-11, 2, 22, 14,-19, 2,-19, -6, + 1, 3,-18, 14, 2, -6, -2, -8, -3, -6, 5, -7, -8, -4, 1, 1 }, + { 8, 7, 25,-21, 12, -6, -5, -4,-10, 6, 0, 10, 1,-12, 18, -5, + -15, 4, 1, 14, -1, 5, 8, -7, 1, -7, -3, 9, 10, 1, -1, 0 }, + { 9, 10, 32,-15, 8, 2, 11, -7,-18, -8, 2, -6, -9,-16, -3, 3, + -1, 3, 1, -5, 4, -2, 1, -8, 0, -6, -3,-11, 1, 5, 0, 0 }, + { 14, 0, 23,-25, 22, 3, 7, 10, 0, -2, 7, 8, 0, 10, 0, 0, + 3, 2, 3,-10, 0, 10, 0, -7, 0, 10, -1, -5, -7, 1, -1, 2 }, + { 12, 0, 25,-18, -5, -4, 13,-10, 3, -6, 7, 21, 0,-16, 3,-10, + -6, 5, -7, -3, 2, 5, 3, -6, 4, 9, -8, 12, -2, 3, 2, 4 }, + { 31, 15, 27,-20, 10, -7, 15,-10, 9, -8, 4, -5, 3, -3, 5, 6, + 11, -2,-12, -2, 6, -2, 1, 2, -1, -1, 1, 1, 3, 1, 1, 2 }, + { 12, -4, 13,-23, 12, -6, 2, 4, -3, 13, 6, -7, 5,-19, -7, 18, + 1, -7, 7, 1, 16, -7, 3, 0, 3, 0,-12, 8,-11, 9, 4, 7 }, + { 29, 1, 3,-22, -5, 6, 0, 12,-14, 11, 1, 6, -3, 4, 6, -2, + 4,-13, 12, 1, 1, 3,-11, 9,-10, -1, -7, 16,-11, -1, 3, 9 }, + { 4, 4, 36,-23, -5, -8,-15, 1, -6, 3, 13, -1, -5, -7, 4, 9, + 2,-11, -3, 5, 1, 3, -6, -1, -4, -4, -2, 2, 3, -1, -5, -2 }, + { 19, 10, 6,-17, 2, -4, -2, -4, -3, 13, 2, 2,-13, -7, -3,-11, + 9, -6, 1, -9, -5, 4, -5, -9,-18, -7,-11, 9, 4,-11, 8, 4 }, + { 16, -3, 9,-16, 18, -2,-12,-16,-11, 11,-18, 16,-13, 6, 2, 8, + 3, 8, -4,-16, 10,-11, -1, -3, -8, 5, -9, -4, 9, -4, 0, -3 }, + { 14, 15, 3,-23, -5, 7, -8, -6, 2, 17, 2, 12, -8,-12, 13, -1, + -9, 3, 1, 1, 19, 15, 4, -1, 1, 2, -3, 2, -3, 1, 5, 3 }, + { 32, 5,-10,-47, -5, -1, 4, 11, -7, 0, 2, -2, 1, -7, 6, -4, + 6, 2, -4, -2, 2, -2, 0, -4, 1, -6, -5, 2, -2, -1, -3, -4 }, + { 20, 8, 10,-21, -7, -9,-16, 12, 1, 4, 6, -5, 9,-11, -7, 4, + -11, 28, -3, 2, 4, -6, 10, -8, -5, -5, -9, 9, -2, -1, 6, -5 }, + { 38, 3, 23,-25, -6,-18, 3,-10, -8, 6,-10, 1,-10, 2, 2, 0, + -7, 2, -4, 5, -1, 8, -3, 0, 3, 3, -1, 1, 0, -4, -4, 0 }, + { 20, 5, 16,-22, 24,-18, 2,-12,-14, -7, -3, 10, 2, 7,-10, 2, + -8, 1, 8, -1, 4, 1, 4, -2, 5, -9,-18, -8,-13, 5,-11, 10 }, + { 14, 8,-12,-16, 9,-11, -3, -6,-25, -7, 6, 5, -7,-16, 10, 2, + -7, -1, -9, -3, 16, 4, 3, 3, -3, -3,-15, 13, -3, 4, 13, -7 }, + { 16, -9, 19,-23, 7,-19, -3, -5,-15, 11,-21, 21,-16, 18, -1, 6, + 10,-10, 18,-14, 16,-15, 6, -5, -9, 5,-17, 13,-10, 13, 0, 10 }, + { 8, -4, 4,-24, 8,-21,-18, 9,-11, 4, -6, 17, 5, -9, -2, -2, + 2, 15, -2, -3, -2, 1, 7,-13, 15,-10, -8,-11, 3, 3, -1, -1 }, + { 14, 17, 6,-32, 5,-17, -2, 0, 15, -1, -5, 16, 1, -5, -2, 9, + -3, 8, 4, -2, -2, -4, -3, 1, 0, 7, -3, 4, -5, 0, -7, 2 }, + { 24, 6, 22,-12, 8, 3,-14, 4, -7, 8, 6, 5, 6, 1, 6,-12, + 15, 10, 4, 11, 9, 6, -7, -4, 10, -9, 2, -1, -5, 11, 15, 3 }, + { 17, 12, 3,-23, 5, -1, -2, 1, -9, -1, -3, 1, 8, 1, -5, 17, + 11, 0, -2,-11, 7, 4, 0,-27, -7, 1, 2, -8, 9, 7, 5, 3 }, + { 12, 10, 12,-10, -4, 5, -1, 2,-24, 5, -8, 2, 6,-17, 19, 5, + 12, -2, 16, -7, -6,-14, 4, 1, -3, 13,-16, 5, -1, 4, 1, 1 }, + { 31, 9, 11,-17, 10, -3, -7, 7, 1, 2, 2, 4, -3, -1, 11, 4, + -5, -8, 1, 4, 15, -6,-28, 1, 8, 3, -6, 5, 17, -2, 2, -4 }, + { 11, 19, 16,-26, 0, -7, -7, 2,-13,-15,-12, 9, -3, 27, 8, 4, + -6, 1, 4, -6, 11, -1, -6, -7, -3, 0, -6, 4, -6, -7, -3, -1 }, + { 10, 18, 16,-32, 19, -9, -4, -3, -7, 8, 8, -3,-11, -2, -6,-16, + 13, 13, -6, -1, 10, -2, -2, -9, 0, -3, 9, 4, 11, -2, -6, 6 }, + { 9, 4, 19,-33, 4, 7,-12, 36, -3, -1, 8, -2, 2, -8, -9, -4, + -8, 0, 1, -1, 0, -4, -4, 3, 0, 3, 6, 0, -6, 2, 0, -2 }, + { 25, 7, 15,-12, 2,-24, -1, 24, -4, 4, 9, 0, -2, -9, 4, 6, + 3, 13, -3, 1, 5, -1, -3, -5, -1, 7, -2, 3, 4, 4, 1, 0 }, + { 19, 6, 8,-20, 9, -9, 5, -4,-13, 7, 11, -3, 5,-13, -9, 6, + -11, -1, 0, 4, 11, 26, 3, 6, -7, 12, 6, -3, 1, -9, 7, 1 }, + { 15, 6, 19,-23, -3, -9, 3, 16, -6, -4, 6, -5,-10, 1, 16,-14, + 2, 0, 2,-13, -3, 8, -6, 3, 1, 1, 2, -5, 12, -4, -8, -3 }, + { 14, 4, 16,-20, 1, 12, 0, 6, -3, 9, 4, 16, 10,-16, 5, 7, + 5, -4, -4,-18, -3,-11, -4, 4, -7, 3, 13, 7, 3, 3, 2, -7 }, + { 22, 3, -1,-30, 18, -3, -9, 9, -2, 11,-16, -2,-14, 12, 0, 4, + -5, 4, -1, 3,-20, 12, 4,-10, -2, -2,-12,-12, 10, 6, 11, -3 }, + { 15, 7, 2,-21, 5, 4, 9, -9,-33, 7, 7, 3, -6,-14, -8, 10, + 12, 0, 2, -1, 5, 4, -2, 0, -7, 0, 2, 4, 0, 1, -3, 8 }, + { -7, 0, 12, 3, 0, -6, 8, -4, 0, 2, 14,-15, 2, -7,-31, -3, + 14, 0, 14,-15, -1, -4,-15, 10, 1, -3, 1, 2, 5, 2, -8, 1 }, + { -2, 5, 1, 0, -3, 3, 3, -6, -1, 2, -4, 1,-19, 0,-11, 18, + 11, 10, 21, 5, 6, 2, 10, 3, -6, 0, -2, 13, 5, -1, -2, 9 }, + { -9, 1, -5, 0, 0,-15, 8, 4, 8, 3, 8, 12,-13, -2,-39, -2, + 4, -4, 5, -3, -4, 3, -3, 3, 10, 5, 3, 2, -3, 5, -2, 8 }, + { -9, 6, 6, -8, 12,-12, 23,-18, 4,-15, -5, 2,-20, 13, -7, 7, + 7,-12, 14,-12, 6, 1, 1, -3, -8, 9, 0, 1, -7, 3, 7, -6 }, + {-18, 13, 4, 3,-10,-30,-10, -6,-14, 1, -7, -4,-35, 5,-25, 11, + 9, 8, 19, -4, -7, -3,-18, -8, 1, 5, 10, -4,-14, -9, 3, -4 }, + { -6, -1, 4, -9, -9, 4, 20, 0, 0, 3, 11, 7,-16,-17,-20, 11, + -6,-14, 1, 4, 19, 2, -8, 6,-15, 3, 6, -5,-14, 3, 7, 2 }, + { 1, 6, -2, -8, -5, -3, 3, -8, 21, 1, 3, 16,-14, -2, -9, -4, + 13, -2, 18, 14, 14, 19,-13, 5,-10, 2, -3, 3, 5, 5, 1, -1 }, + { -1, -5, -6, -2,-11, -7, 5, -4, 5, -1, 0, 3, -3, 2,-19, 18, + 16, 4, 14,-22, -2,-11,-22, 1, -1, 11, 1, 2, 11,-10, 7,-12 }, + { 1, 4, 5, -1, -9, -5, 1, 12, 5, 6, 12, 9,-24, 23, 1, 20, + 14,-11, 13, 5, -2, -2, 5, 6, 2, 1, -9, 6, 10, 5, -4, 11 }, + { -1, -1, 1, 7, -3, -4, 8,-16, 15, -1, -7, 9,-22,-11,-11, 10, + 16, 9, -2, 4, 13, 10, 6, 16, 4, 7, 1, -8, -7,-14, -7, 4 }, + { 1, 3, -6, 0, 15, -9, -4, 0, 4, 6, 12, 9, -6, -5,-22, 17, + 7,-11, 15, -5, 1, 3,-19, 0,-15, -3, 16, 5, 5, -7,-11, 12 }, + { -2, -1, 13, 2, 4,-24, 37, -5, -2, -6, 12, 7, -2,-23, -4, 9, + 2, -3, 3, 2, 3, 3,-14, 11, 0, -4, -2, -2, 3, 10,-10, 4 }, + { 2, 9, 8, -6,-28, 14, 28,-11, 18,-11, 0, 2, -2, 4,-12, 3, + 6, 0, 7, -7, -6, 2, 5, -1, -1, -1, 5, 2, 3, 0, -3, 9 }, + { -7, 14, 5,-10, -3, 7, 4, -5, 7, -8, -7, 4,-12, 14,-16, 25, + 3, 0, 1, -5, 12,-10, 0,-10, 0, 12, 12, 17, 12, 10, -1, 0 }, + { -4, -2, 5, -2,-17, -3, 5, -5, 7,-17, 1, 5, -4, 4,-20, 0, + 11,-15, 13, -8, 10, 1, 1, 5,-12, 9, -8, 0, 6, -1,-11, 4 }, + { -3, 12, 13,-15, -7, -7, 0, 5, 33, 3, 3, -6,-13, -7,-15, 10, + 3, 3, 3, -5, 2, 7, -1, 0,-12, 2, 11, -6, -9, 0, 5, 11 }, + { -8, 5, 10, -7,-14, -4, 13, 0, 18, -3, -6, 7, 1, -6, 0, 21, + 8, -7, 10, -8, -3, 17, -9, 0, -5, 1, 4, 8, -3, 11, -5, 0 }, + { -8, 8, -3, -8, 8,-11, 16,-16, 17, 0, 8, 16,-17, 10,-16, 10, + -8, 6, 11, 0, 10, 7, 4, 5, 7, -5, -5, -6, -7, -5, -1, 16 }, + { -6, 0, 6, 1, -8, -8, 8, -7, -5,-10,-11, 8,-19, 6, -7, 13, + 5, -3, 4, -8, 7, -1,-18, 9, 0, -5, 6, 26, 3, 8, 2, 4 }, + { -2, -2, 23, -2,-20, 2, 7, -7, -6,-15, 3, 9,-19, -2,-10, 7, + -2, 7, 9, 11, 0, 4, -4, 6, 9, -2, 4, -3, 4, 3, 2, 8 }, + { -6, 12, 10,-10, -7, 4, 17, 11, -6, 1, 12, 11,-18, 8,-12, 4, + 1, 13, 6,-13, 23, 9, -5, 8, -2, -5, 1, 3, 0, -2, -4, 4 }, + { 7, 1, 7,-17, -8, 8, -1, -7, 5, -6, 4, -3,-16, 9,-24, 18, + -3, 10, 13,-11, -6,-11, -4, 10, 0, 11, 8, 2, 6, -5,-11, 4 }, + { -4, 1, -5,-10, 0, -3, 9, -2, 4, -1, 1, 5,-41,-10, -7, 4, + -3, 3, 1, 0,-12, 4, -3, 0, 2, -1, -2, -5, 3, 2, -7, 5 }, + { -2, 1, 4, 4, -3, -6, 1, 0, 12, -5, 11, 0,-17, -3, -1, 11, + 4, 1, 27,-12, 0,-14, 2,-15, -3, -9, 0, -7, -3, 15, -8, 6 }, + { -6, 4, 9, 2, 4, 3, 7,-10, 28, 1, -2, 48, 7, 0,-10, 10, + 1, -9, 2, -1, 0, 3, -5, 5, -4, -2, 7, 7, 1, 3, 2, 5 }, + { -3, 3, -1, 3, -9, 0, -1, 3, 2, -6, 39,-14,-12, 5,-19, 21, + 7, -6, 4, -1, -4, 0, -4, 1, 0, -9, 1, 10, 0, -2, 0, 7 }, + { 4, 2,-29, 12, 5, -3, 16, -6, 15,-13, -4, -1,-13, 22,-16, 17, + 16, 4, 9, -4, 4, -6, -4, 11, -8, 7, 8, 4, 3, -3, -7,-13 }, + { 0, 3, 3, -6, -4, 0, 9, 0, 5, 0, 10, 10, 4,-13,-12, 16, + 23, -4,-12, -6, -4, 20, 2, 0, -4, 23, 1, 8, 11, -4, -5, 15 }, + { -6, 4,-15, -9, -1,-19, 12,-30,-17, -4, 1,-13,-13, 4, -3, 26, + 5,-25, 11,-14, -6,-13, 0, -7, 9, 2, 8, -1, -8, 1, -8, 13 }, + { 1, 6, 1, -4, -4, 1, 2, 0, -3, 2, 10, 6, -6, -2,-11, 4, + 32, 15, 15,-47, -8, 3,-12, 4, -5, 4, -1, 0, -5, 5, 1, -7 }, + { 2, -1, 0, 0, -1, -6, 0, -6, 4, -4, 5, 9, -5, 1, -3, 51, + 4, -5, 4,-14, -1, -4, -3, 1, -4, -1, 0, 2, -8, 0, 1, 2 }, + { 0, 4, -2, -7, -2, -9, 6, -8, 11, -3, -6, 3,-11, -8,-12, 8, + 11, 5, 19, 3,-24, 19,-14, 11, -5,-18, -8,-12, -5, -4, -1, 4 }, + { 16, 9, 10, 14,-18, -2,-18,-27, 10, -5, 12, 14, 4, 0, -2, -6, + -12, -7, -1, 3, 4, 7, 11, 10, 5, -5, -7,-16, -3, -6, 6, 9 }, + { 7, 15, -9, 10,-19, 4, -5,-37, -2, -4, 8, 2, 4, -1, 1, 9, + -5, -5,-12, 1, -1, -8, 3, -3, 4, 6, 9, 3, 3, -1, 2, 4 }, + { 13, 17, 3, 9, -7, -7,-15,-17, -8,-13, -4, -8, 19, 2, 16, 25, + 7, 15, 2, 16, -5, -6,-10, -9, -7, -6, -2, -7, 7, 2, 4, 5 }, + { 24, 7, 9, 8,-13, -2, 0, -4, 1,-13, 3, 6, 7, 10, -4, 15, + 5, 7, -4, 5, -5, 3, 13, -7, 5, 15,-11, -2, 7, 5, 8, 6 }, + { 17, 6,-15, 23, -2, -1, -6, -2, 0, -4, 11, -3, 12, 15, 6, -8, + -15, 10, -9, 7, -1,-11, 2, -8, -4, 3, 4,-10, 4, 4, 11, 1 }, + { 21, 12, -3, 6, -8, 8,-11, -8, -5, -5, 3, 7, -1, -5, 12, 15, + -10,-11, 3, 15, 8, 4, 2,-15, 0, 14, 1, -8, -1, 3, 10, -7 }, + { 16, 12, 5, 13, -6, 15,-23, 0,-17, -9, 0, 4, -9, 13, 6, 18, + 0, 0, -4, -1, 0, 14, 5, -1, 8, -4, -8, -6, 5, -2, -2, 0 }, + { 14, 16, -1, 12,-15, -9, -6,-20, 4, 6, 8, 9, 3, 1, -9, -4, + -1,-11, 9, 11,-12, 1,-14, -7, 2, -8, 11, 9, -4, 10, 4,-16 }, + { 13, 10, 3, 7, 0, -8,-33, -6, 4, -4, 19, -2, 14, 6, 5, 7, + 6, -3, -1,-10,-10, -9, 4, -3, 5, 9, 2, 2, 10, 9, -2, -3 }, + { 11, 10, 25, 18, -1, -6,-21,-21,-11,-16, 6, 5, 14, 4, 8, 7, + 0,-10, -7, -9, -5, -4, 3, -1, 1, 6, -1, 6, -2, 2, -3, -9 }, + { 15, 9, 5, 22,-17, 15, -9, 7, 7, -9, 13, 9, 10, -1, 8, -3, + -2, 6, 1, 17, 8,-14, 7, -3, 12, 9, 1, 0, 1, -5, 17,-18 }, + { 25, 19,-17, 12, -4,-10, 1,-13,-19, -7, -3, 9, 6, -2, 3, 1, + 4, -2,-11,-14, -1, -7, -5, -9, 7, -1, -3, 4, -5, 1, 0, -1 }, + { 20, 8, -3,-10,-24, 3, -6, -2, 0,-12, 14, 6, 7, 11, 4, 7, + -12, -5, -8,-10, 5, -1, -4, 4, 16, 7,-14, 6, -1, -2, -7,-11 }, + { 16, 18, 17, 1,-15, -6, -5, -3, -1,-19, 8, -2, 2, 8, 12,-19, + -12, 8, 0, -3, -1, -1, 4,-14, 9, -1,-12, -1, -7, 10, -3, 5 }, + { 18, 12, -7, 7, 0, -3,-13, 0, -1, -4, 9, -2, 6, -1, 0, 1, + 15,-21, 1, -8, 25,-19, 13, -9, 2, 12, 5, -7, -3, -1, -3, 1 }, + { 13, 16, -4, 9, -2, 2, -1,-19, -7, -4, 18, -6, 14, 18, -5, 4, + -6, -3,-19,-14, -1,-12, 10, 6, 7, 17,-12,-13,-10, -4, 5, 4 }, + { 27, 17, 4, 14, -9, -2, -4, -8, 0, -6, 14,-11, -7, 2, -3, -3, + -2, -3,-13, 12, 16, 1, -5, -9,-10,-11, -2, 3, -7, 5, 11, -7 }, + { 7, 17,-16, -2,-14,-28, -7, -8, 15,-10, 7, 15, 8, 17, 13, -1, + 4, -7,-12,-11, 0, 0, 2, 3, -3, 7, -6, 6, 1,-16, 1, -2 }, + { 23, 11, -9, 15,-23, -4, -6, -4, 2, -9, -7, 9, -8, 3,-13, -4, + 8, 18, -6, -2, 1, -5, 6,-14, -5, -2, -6, -5, -3, -2, 4, -5 }, + { 12, 13, 18, 18,-35, 2, 7,-17, 3,-11, 6, 9, -3, -2, 10, -4, + 3, 3, -2, -7, 0, 2, -4, 0, -4, 0, -6, 5, 10, 4, -3, -1 }, + { 19, 11, 1, 20,-14, 4, -9,-13, -2, 11, 0, 17, -1, -1, -1, -1, + -5, -8, 0, 5, -1, -8, 5, -1, 3, 2,-12, 21, -2,-24, 5, 7 }, + { 15, 15,-15, 17,-14,-22, 3, -4,-11, -3, -7, 1, 18, 10, 1, 10, + -6, -3, 8, 2, -7, 0, -2, 1, 1, 2, -9, -2, 1, 2, -3, 4 }, + { 45, 13, 8, 17, -5, 2,-16, 2, 8, -2, 8,-15, 4, 5, -1, 7, + -6, -2, -6, 2, -3, 0, 0, -9, -1, 7, 2, 3, -3, -3, -1, 5 }, + { 1, 18, -8, 18,-12,-10, 3, 4,-22,-12, 20, 8, -3, 9, 2, 10, + -10, -3, 9, 3, 6, -3, 10, -1, -3, 2, -2, 4, 2, 3, -3,-18 }, + { 9, 10, -5, 9,-35,-21,-18,-16, -1,-12, -6, -7,-15,-19, 12, 4, + 4, 9, -7, 2, 14, 1, 4, 0, -1, 6, -7, 2, 1, 1, -4, 4 }, + { 31, 8,-17, 35, -8, 1, -5, -6, -7, -6, 10, -2, -3, 6, 9, 3, + -6, -2, 3, 3, 5, -3, 0, 6, 0, 1, -5, -3, -2, -4, -1, 0 }, + { 18, 4, -8, 7, -8,-15, -1,-16, 12, 18, 3, 19, 2, 4, 8, 8, + 0, -5, -8,-12, 10, -5, 0, 1, 0, 4, -3, 16, 11, 11, -2, -6 }, + { 27, 15,-17,-10,-23,-22, -1,-14, -4, -7, 20, -2, -7, 6, 15, -5, + 32, 4, 9,-11, -3, -8, 11, -4, -1, -4, -8, -6, -4, -5, -2, -7 }, + { 22, 4, -7, 2,-15,-11,-17,-10, 2, 0, 15, 11, 7, 12, -8, 6, + -10,-18, -6,-12, 7, 3, 22, 3, -7, 14, -5, -2,-13, -7, -1, -7 }, + { 18, 13, 9, 24, -4,-19, -9,-11, 13, 8, 2, 4, -1, 8, 14, 10, + -12, 0, 0, 5, 10, 5, 4, -1, 5, 1, -1, 11, 2, -4, 0, -9 }, + { 15, 19, -5, 1, -4,-10, -8,-27, 6, 8, 5, 10, 4, 11, 5, -5, + -11, 0,-11,-14, -4, -9, -8, -8, 6, -9, 4, -5, -1, 1, 5, -4 }, + { 18, 1,-13, 14,-14, 9,-15, -7, 12, 1, 13, -4,-20, 12, 10, 12, + -12, 7, 1,-13, 10, -6, 5, -3, 4, 8, 10,-13, -3, -6, 9, -3 }, + { 19,-14, 5, -8, -6, 2, -5, 5, -3, -1,-28, 11, 18, -6, -4, -2, + 11, 14,-43,-42, 9, 2, 20,-23, 6, 32, 0, 5, 0, 6, 9, 5 }, + { 8, 11,-14, -1, 7, 12, -7, 2,-16, 2, 10, -3, -1, -7, -7, -1, + 1,-10,-60,-23,-18, 42,-13, 9, 18,-11, 0, 1, 0, 2, -5, 1 }, + { -5, -1, 2, 0, 3, -3, 3, -2, -6, 0, -3, -3, 7, 2, 0, -2, + -2, 3,-34,-15, 37, 47, 10, 20, 9, 1, 3,-21,-25,-33,-14, 8 }, + { 5, 6, 2, -2, -2, -2, 6, 5, -5, 7, -3, 1, -5,-13, 9, 3, + -17,-19, -2,-79,-12, -7, -8, -6, -2, -2, -1, -1, -7,-13, 6, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, + 0, 3, 4,-87, 6,-11, 16, -9, -1, 8, 0, 5, 0, 1, 2, 1 }, + { -5, 6, 2,-24, 5, -9, -7, 0, 7, 3, -3, 16,-14,-16, 0, 18, + 15, -9,-14,-28,-17, 53, 14, -6,-28, -1, -3,-10, -7,-14, 19,-15 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, + -13, 0,-53, 3,-22, 63, 19, 16, 1,-11, 0, -3, 0, -3, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -1, -6,-43,-43, -2, 65,-13, -4, 9, 1, 1, 2, 1, 0, 0, 1 }, + { 0, 1, 0, 0, -1, 0, 1, 1, 0, 0, 1, 2, -1, -1, -3, -1, + -23, 1,-61,-55, 3,-28, -6, -4, -4, 8, 2, 1, 1, -1, 0, 0 }, + { 0, 1, -1, 1, -1, 0, -1, 0, 1, -1, 0, 1, -1, 0, -9, -4, + -48,-19,-52,-46, 11,-12, 5,-14, 0,-10, 0, 0, -1, -2, -1, 0 }, + { 0, -3, -1, -4, 2, -1, -7, 3, 1, 3, -1, 1, -3, 0, -7, 0, + 3, -7,-61,-51, -4,-21,-16,-21,-11, 14, -7, 8, 3, -5, 1, 2 }, + { 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 9, -3, + 56,-11, -6,-67, -1, 13, 0, 7, 1, -9, -1, -1, 0, 0, 1, 0 }, + { 14, 9, -2, 14,-10,-10, 9, -5, 1, -8,-23, 30, 8, -7, 23, 8, + 2, 10, -1,-27,-17, 57, 22, 4, -5, 2,-12, -6, 2, -7, -4, -9 }, + { 1, 5, 12, -2, -2, -3, 2, -3, 6, 0, 4, -2, -8, -6, 0, 16, + -15, 29,-55,-29,-24, 29, 3, 10, 6, 13, 10, -5, 21, 11,-14, 5 }, + { 4, 2, 26, -6, 10, 11,-23,-10,-27,-20, 3,-24,-11,-10,-13, 25, + -10, 5, -9,-36, -7, 43, 3,-13, 6, 13, -2, 0, 1, 3, -3, -4 }, + { -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, 0, -1, 1, + -12, 12,-26,-64,-15, 29, 37, -7, -3,-12, -5, 14, 8, -8,-10, -2 }, + { 19, -4,-11,-16, 8, 14, 5, 19, 3, 22,-11,-21, -1, -6,-11, 11, + 10,-24,-23,-40, -8, 20, 17, 5, 13, -6, 3, 14,-20, -8, 3, 28 }, + { 2,-12, 10,-14,-18, 26,-22, 4, -2, 5,-21, 8, 3, 1, 19, 0, + -12, 24,-14,-40, 15, 29,-15, 6, 15, 1,-19, 2, 4, 7,-12, -3 }, + { 0, 17, 13, 7, -5,-11, 2,-19, 3, 38,-21, -3, -6, -4, 7, 1, + 1, -5,-40,-10, -2, 35, 8, 8,-10, -8, -9, 33, 4, 4, 0, -2 }, + { -2,-12, 7, 29,-24, 2, 16, -1, -7, 16, 10, -2, -2, -2, 13, -2, + -37, 15,-22,-40,-11, 33, 10, -1, 8, 10, 6, 8, 9, 0,-12, 2 }, + { 15, -8, -9, -2, 7,-17, 7, 19, 14, 4, 12, 27, 11, 10, 4, 11, + -15, 14,-13,-48, 5, 18, 0, -9,-36,-11, 2, 4, 5, 5,-15,-12 }, + {-12, 0, 3, 4, 7, -5, 5,-14,-24,-18, -6,-15, -8,-20, 1, -7, + -33,-28,-40,-38,-18,-10, -5, 17,-12, 4, 3, -5, 5,-13, 4, -7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, + { -8, 2, 1, 22,-31, -6,-25, -3, -3, 1,-15,-11, -2, -3, 4,-13, + -9, 15,-18, 37, -7,-37, 12,-13,-11,-25,-10,-11,-22, 7, 16, 7 }, + { 14, 10, 4,-10, -1, -5, -7, -3, 16, 13, -5,-15, 5, 11, -1, 8, + -27, 7,-12, 49, 17,-22, 9, -2, -9, -1, 2,-15, -1, 41,-18,-17 }, + { -4, -9,-15, -3, 3, 4, 4, 2, 7, -3, -7, -8, -5, 17,-19, -7, + 36, -9,-38, 17, 1,-48, 11,-18,-13, -2, -8, 4,-10, -5, 21, 11 }, + { 15,-13, 4, 2, 1, -5, -2, 1,-10, 7, -1, 3, -6, 0, 11,-11, + 8, 20,-17, 51,-17,-41, 2, 15, 4, 8, -2, 16,-32, -1, 17, 6 }, + { -8, 8,-18, -5, 4, 6, -3, 8, 0, -4, 2, 0, -1, -4, 5, 8, + 30, 30, -8, 70, 2, 8, 2, 0, 7, 1, 13, -1, -6, -7,-11, 2 }, + { -8, -7, 9,-10,-13, 6,-11,-14, 13, 25,-26, 5, 2, -5, -5, 5, + -8, 4, 0, 33, 12,-38, -4, 6, 13, 6, 25, 34, -1, 25,-19, -5 }, + { 18, 3,-17, 4, -8, 7, 20, 1, -1, 5, -5, -2, -8, 8,-35, 15, + 24, 43, -5, 51, 5,-12, -3, 1, -2, 3, -3, -3, -9, 8, -9, 2 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 10, 24, 76, -2,-22, 11, -1, 4, 33, 4, 1, -1, 1, 2, 0 }, + { 0, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 0, + 24, 13, 32, 70, 26, 5,-21, -9, -6,-15, 2, -2, 2, 4, 1, 1 }, + { 5, -4,-11, 4, -4, 22, 10, -2, 13,-11, -4,-21,-17, 0, -7, 4, + 10,-34, 11, 52, 2,-46, -5, 0, 0, -1, 2, 4, -9, 1, 1, -7 }, + { 0, 1, 1, 0, -1, 0, 1, 0, 1, 1, 0, 1, 0, 0, -3, 1, + -8, 9, -1, 64,-13,-61, -3, 3, -5, 10, 1, 3, -1, -1, -1, -1 }, + { 0, 1, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, + 10, -2,-31, 79,-10, 27, 0, -1, 3, 8, 1, 1, 0, -1, 0, -1 }, + { 3, 12, 10, 26,-19, 10, -9, 6, -4,-15, 10, 3,-16, 6, 11,-19, + 3, 10, 18, 44, 5,-30, 5, -9, 21, 4, 20, 10, 14,-25, 8,-17 }, + { 0, 0, 0, 1, -1, 0, -1, 0, 1, 0, 1, 1, 0, 0, -6, -2, + 8, -8, 13, 69, 26,-19,-25,-17, 16, 6,-12, 22, 2, -6, 9, 5 }, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, + { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, + -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, + { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, + -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, + { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, + 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, + { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, + 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, + { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, + -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, + 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, + { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, + -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, + { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, + -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, + { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, + 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, + { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, + 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, + { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, + -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, + 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, + { 16,-18, 7, -4, 31,-15, -9,-13, 20,-12, -6, 0, 12, -6, -2, 4, + 3, -3, -1, 0, 1, 3, 3, -2, 1, 6, 4, 0, -3, 2, -5, 1 }, + { 38, -5,-13, -4, 8,-15, 11, 1, 2, -4, -1, 9, 13, 4,-12, -7, + 0, -2, 7, 2, -6, -2, -3, -2, 3, -4, 6, 15, 1, 1,-11, -2 }, + { 47,-22, 9,-26, 3, -5, 2, -7, 4, -2, 2, -2, 3, 0, 3, -4, + 3, -3, 2, -3, 7, -3, -1, 1, 1, -5, 5, 0, 2, -5, -3, -2 }, + { 14,-16, 2, -6, 7, -2, -7, -4, -4, -7, 14, -3, 7,-19,-14,-17, + -29, 6, 26, 16, -5, 13, -4, -1, 21, 14, 1, 3, -6, 0, -7, -1 }, + { 29,-11, 5, -3, 4, 11, 4,-10, 1,-22, -3,-10, 5, 4, 2, 8, + -2, -7,-12,-12, -8, -3,-18, -2, -9, -5, -1, -3, 2,-14,-14, 7 }, + { 28,-12, 5, 3, 9, -7, 0, -2, 2, 1, 4, 0, -7, -3, -2, 4, + 4, 14, 8, -1, -4, 14, -7, 17, -2, -2, -9, 2, 19, -7, 9, -8 }, + { 31,-18,-22, 8, 15, -5,-10,-15, 1, 10, 6, 7, 6, -8, 2, -1, + 12, -3, 3, -1, 1, 5, -6, -4, 0, 1, 7,-10, -2, 4, -3, -4 }, + { 53,-30, -4, 12, 2, 3, -3, -3, 0, 1, 6, 5, -5, -4, -7, 1, + 0, 2, 1, 3, 1, 5, 0, 2, 2, -1, 0, 4, 2, 0, -2, 0 }, + { 27,-18, -3, -2, 4, -8, 3, -2,-11, 2, 10, -8, -8, -4, 0, -2, + 8, 0, 9, 0,-16, 11, 1, -6, 13, -3,-10,-13,-15, 25, 1, 0 }, + { 35, -5, -1, -8, 23, 11,-14, -3, 2, -2, 8, -6, 17, -2, 7, 0, + -2, 10,-17, 13, -2, -2, 11, 11,-14, 2, -2, -3, -8, -1,-12, -5 }, + { 29, -9, 7, 3, 2,-10, 0, 3, 9, 0, -3, 5, 1,-10, 10, -5, + 3, 6,-20, -9, -6, -4, 1, 0, 12, 17, -8, 9, 3, -1, -9, 0 }, + { 15,-16, 18,-19, 16,-15, 17,-18, 13,-16, 17,-14, 15, -9, 13,-17, + 9, -7, 4, -5, 3, -4, -3, 0, -6, 7, -9, 7, -2, 7, -9, 9 }, + { 21,-10, 7, -2, 12, -7, 13,-17, 11, -2, 20, 3, 5,-11, -6, -6, + -15, 0, -9, 5,-11, 7, -1, 7, 8,-10, -9, 3, -5, 9, -8, -2 }, + { 23,-22, 15, -5, 16, -4, -3,-12, 9, 3, -1, -2, -8, 2, -2,-16, + 3, 4, -2, -6, -7, 12, -8, 2,-14, 2, -7, 11, -2, 6, -4, -1 }, + { 34,-17, -4, 8, 4, -6, 1, 8, 4, 16, 3, 6, 12, -1, -1,-15, + 6, 4, -7, -6, 6, 0, 2, 1, -2, 2, 3, 3, -3, -2, 8, -6 }, + { 18,-18, 2, -2, 10, 1, 18,-23, -3,-10, 0, 4, 20,-19, -3, -4, + 2, 8, 6, 1, -3, 1, 1, 3, 5, -1,-11, 3, -7, 5, -1, 1 }, + { 15,-14, 2, 3, 10, -8, 12,-13, 13,-15, 6, -8, -4,-10, 14, -9, + 24, 2, -7,-18, 13,-11, 8, 14, -6, -2, 3, -1, -4, 7, -7, -4 }, + { 20,-12, 13, 5, -1,-10, 15, -6, 8, -1, -3,-10, 17, 0, -6,-19, + 2, -1, 8, -3,-16, 0, -3, 2, -2, 0, 8, -9, 0, 1,-10, -9 }, + { 32, 0, -9, -5, -1, 5, 13,-11, 8, 3, 11,-11, 0, -8, -2,-14, + 7, 10, 6, -5, 1, 10, 2, 12,-10, 4, 4, 6, 4, 0, -7,-10 }, + { 16,-14, 10, -7, 11,-11, 11,-11, 18,-13, 8,-15, 16,-11, 13, -9, + 8, -7, 12,-11, 7, -6, 3, -5, 9, -5, 4, -1, 7, -4, 8, -3 }, + { 24,-27, -1, 5, 8, -5, 12, 7, 4, -3, 3, -1, -9,-11,-13, -5, + 10, 0,-13, 7, 1, -5, 4, -9, 7, -3, 13, 2, -5, -3,-17, -2 }, + { 23,-19, 15, 1,-10,-18,-12, -6, 8, -3, 12, 0,-12,-10, -4, -4, + 8,-10, 4, 2, -2, -8, 13, -3, -2, -6, 2, -3, 5, -2, 2, 11 }, + { 25,-12, 4, 2, 24, -3, 3, -6, 14, 11, 0,-21, -3, -3, 1, -8, + 7, 0, 0, 3, 3, -6, -7, 6, 2, 1, -4, 5, -1, 10, -2, 9 }, + { 24, -8, -6, 7, 16,-12, 13, -1, 11,-21, 2, -6, 3,-12, 0, 9, + 4, 11, -7, 1, 4, 1, -8, 3, 3, -6, 3, 3, 0, -8, 8, 4 }, + { 25,-21, 13, 14, 13,-18, 4, -3, 0, -5, -4, 5, -3, 0, 4, 12, + 7, 3, 5, -5, 2, -2, 3,-10, 2, -9,-15, 6, 1, 7, -5, 1 }, + { 23,-16, -2, 10, 4, -1, 3, 1, 32, 3, -5, -2, 9, 10, -1, -4, + -6, 2, 9, -1, 14, 12, -6, -1,-17, -2, -4, -9, -7, -6, -8, 3 }, + { 50, -8, 5, 2,-11, 10, 0, 0, 6, -3, 7, 0, -3, -2, -3, 0, + 6, -4, 2, -5, -9, 0, 3, 10, 1, -7, -2, -3, -6, -9, 1, -2 }, + { 28,-17, 0, -2, 2, -9, 1, 5, -4, -1, 0, 0, 19,-27, 5,-12, + 7,-14, -3, -6, 10, -2, -4, -2, 4, -5, -2, -7, 1, 7, -9, 4 }, + { 22,-19, -6, -6, 3,-22, 3, 5, 20, -8,-14, -5, 1, 1, 20, 2, + 16, 6, 3, 14, 4, 3, 5, 1, 5, -7,-10, -6, 3, -6, 1,-14 }, + { 29,-14, -8, 13, 8,-10, -6, 4, 4, -6, 5, -7, 1, 12, 14, 11, + -7, 1, 2, -9,-11, -9, 0, 4, -1, 7, 10, 4, 4, 20, -1,-11 }, + { 18, -9, 4, 1, 7,-29, 12, 1, -1, -9, -2, -1, -2, 2, 9, -8, + -13, 5, 4,-13, -4, 2, -5, -7, -6, 14,-10,-34, -3, 1, -3,-13 }, + { 38, -9, 24, 8, 11, 4, -6,-11, -2,-12, 1, 1,-11, -8, -5, -2, + -15, -8, 8, 0, 1, -7, 5, 4, -1, 8, -2, 11, -3, -1, -5, -5 }, + {-20, 11, -4, 24,-11, 1, 15, 4, 0,-28,-10, -1, 10, 10, -6, 5, + -6, 2, 7, -2, 1, -2, -6, -3, -7, 1, 2, 12, -1, 7, 0, -2 }, + { -9, 10,-23, 27, -4,-17, 20, -6, 14,-17, 5, -1, 5, -9, -7, 5, + -6, 4, -2, 9, 0, 8, 0, 1, -3, -3, -5, -8, 5, -2, -2, 12 }, + {-10, 19, 4, 9, 1,-16, 17, -2, 9,-29,-16,-11, -4, 7, -5, 4, + -1, -3, 3, 2, 3, -4, 5,-12, -2, 6, 5, -4, 4, 1, 4, 10 }, + {-20, 10,-24, 14, -5, 11, 9, 0, 16,-20, 10, -5, -6, -6, -1, 2, + -4, 5,-16, 8, -2, 5, 5,-11, 9,-11, 4,-11, -1, -1, 4, 3 }, + { -9, 11, 3, 19, 24, 4, 5,-14, 30,-17, -4, -2,-17, 7, 2, 3, + 1, 3, -7, -4, 2, -3, 1, 4, -1, -1, 3,-12, -2, 3, -3, 10 }, + {-19, 18, 11, 19, 19, 19, 10, 4, 13, 6, 5, 4, 8, 3, -2, 12, + -6, -2, 7, -6, 15, 12, 16, 16, 18, -3, -4,-20, 0, 10, -9, -3 }, + {-21, 9, 20, 12, 0, -3, 5, -9, 15,-13, 5, -5, -6, 24, 2, 9, + -5, 2, -7, 2, 5, 7, -5, 2, 15, 3, 1, -1, -4, -2, 7, 0 }, + {-18, 16, 13, 15, 2,-10, 14,-11, 4,-11, 5, 12, 12, 20, 8, 30, + 2, 11, -9, 7, 0, -3,-16, -5, -6, 5, -4,-21, 0, 5, 6, 1 }, + {-26, 8,-13, 9, 6,-10, 2,-11, 7, -4, 6,-19,-11, -6,-12, 16, + 0, 5, -7, 8, 5, 6, 17, -9, 10,-10, 5, -3,-11, 2, 4, 10 }, + {-11, 17, -3, 22, -5, 18, 3, 1, 4, -5, 14,-27, 5, -7, -4, -5, + -10, 11, 1, 15, 1, 1, -6, -5, 10,-22, -7, -7,-15, 13, -4, 5 }, + {-17, 14, -7, 13, 3, 0, 13, -6, 9,-14,-22, -1, 1, 19, 14, -3, + 4,-13,-13, 2, -4, 8, -2, -2, 13,-12, 13,-12, -7, -5, -3, 6 }, + {-17, 17, -1, 33, 6, 3, 9,-16, 3,-14, -8, 6,-17, 8, 3, 13, + 8, -6, 3, 1, -2, 0, -2, 8, 4, 9, 13,-10, 4,-17, 0, -6 }, + {-20, 7, 7, 21, 1, -3, 7, -3, -2,-12, 9, -7, 2, -3, 14, 1, + -1, -7, 12,-10, 5,-20, 11, -2, 0,-24,-17, 6, 6, -4, 3, -1 }, + { -8, 10, 6, 7, -1, -6, 28, -6, 10,-33, 1,-20, 0,-12, 10, 1, + -6, 8, -3, -1,-10, 8, 5, 0, 10, -2, 8, 16, -5, -3, -7, 4 }, + {-17, 13, 3, 15, 1, -5, 27, -5, 6, -6, 12, 2, -4, 8, -1, -3, + -2, 12,-15, 3, 4, 1, 2, -9, 0,-16,-21, 2, -4, 16, -7, 4 }, + {-15, 20, 8, 17, 5,-14, 15,-11, 21,-11, 13,-13, 2,-15,-13, 1, + -5, 5, 2, 10, -9, 4, -1, 3, 2, -4, 13, -5, 1, -4, 5, -3 }, + {-21, 8, 2, 16, -1, 2, 15,-16, 13,-12,-12, -7, -8, 2, -7, 11, + -8, 5, 2, -7, 16, -4, 1, -7, 3,-15, 6, -5, -8, 2, -8, 5 }, + {-15, 17, -6, 3, -3, 3, 9, -7, 14,-23, 11, 1, -1, 4, 7, 6, + -1,-14, 7, 6, -8, 5, 1,-15, 10, -9, 2, -3, -1, 4,-10, -4 }, + {-10, 18, 3, 11, 1, 4, 14,-14, 7, -4, 15,-10, 10,-11, 10, -4, + 5,-14, 10, 4, 15,-12, 15,-13, 20,-15, 14,-15, 8,-11, 4, -6 }, + { -7, 23, 2, 20, 7, 8, 19, -5, 9,-16, -8,-17, -5, 1, 5, -6, + -8, 1, -6, -4, 10, 6, 6, 2,-11, -4, 0, 2, 4, 7, 9, -4 }, + {-15, 20, -5, 22, 11, -8, 9, -5, 10,-13, -8, 8, 2, -2, -3, 7, + 6, 10, 1, 2, -5, -9, 1, 10, 16,-22, -7, 0, 7, 7, 6, 1 }, + {-26, 19, -5, 3, 5, 25, 18, -5, 9,-14, -8, -6, -2, -6, 2, 3, + -8, -2, -7, 7, -3, 7, 3, 4, -8, 0, 1, -8, -4, -2, -2, 1 }, + {-20, 14,-10, 6, -3, 7, 8,-32, -2, -7, -2,-10, 16,-12, -9, 15, + -2, -5, -6, 2, -7, 5, 9, 1, 6, -7, -1, 0, -2, -4, -7, 3 }, + {-14, 16, 4, 11, -8, 1, 23, -4, 17,-13,-10, 1, 12, 9, 12, -4, + 7, -1, -1, 5, -8, -6, 3, 3, -6, -3,-18, 0, 18, 20, 4, -2 }, + {-33, 19,-10, 30, 15, 2, -3, -1, -4,-14, 7, -7, -1, 7, -8, 9, + -1, -3, -5, 2, 2, 4, 0, 5, 0, 0, 2, 3, 3, -3, -3, 4 }, + { -6, 20, 0, 5, 17,-10, 18,-17, 9,-16, 4,-13, -6, 2,-14, 14, + -28, 9,-12, 25, -4, 7, 7, -8, 6, -6, -2,-10, 2,-11, -1, 2 }, + {-12, 14, 12, 52, -3, 5, -5, 4, 8,-13, 2, -5, -4, 2, -2, -1, + -2, 3, 3, 5, 2, 3, 0, 1, -5, 2, -4, -3, 1, -5, -2, 0 }, + {-13, 6, 9, 24, 0, 8, 14,-15, 18, -9,-11, -8, 3, 15, -2, -4, + -9, 4, -3, 12, 14,-13, 11, -4, 2, -4, 0, -6, -6, -6,-14, -1 }, + {-10, 28, 3, 12, 9, 3, 11,-28, 6,-11, -7, 4, 0, 7, 8, -9, + 0, -6, 0,-16, 4, 7, 4, 4, 7, 3, 4, -7, 0, -3,-10, 6 }, + {-11, 14, -2, 19, -1, -1, 7, 9, -2,-27, 10,-14, 15, -4, 12, -4, + 2, -2, -6, 12, -6, 0, -5, -4, -5, 1, 3,-11, 5, -9, 3, -8 }, + {-18, 7, 13, 16, -4, 3, 9,-10, 10,-10, -3,-22, -4,-12, 3,-16, + 0, -3,-16, 8,-11, 1, 10, -7, 15, 3, 0, -1,-13, 8, 1, 6 }, + {-20, 10,-10, 10, 8, -1, 6, 0, 16,-12, 9,-10, -1, -5, -4,-13, + 13, 16, -8, 12, -2, 14, 18, 13, 0,-16, 2, -5, -5, -5, -4, 3 }, + {-14, 5, -7,-17, 5,-13, 23, 20, -4, -1, 1, -6, 13, 5, -1, 4, + -14, -2, -7, 8, 3, 2, 2, -7, 2, -1, 4, 7, 3, -9, -1, -5 }, + {-19, 3,-24,-28, -9, -7, 19, 3, 2, 19, 7, 5,-13, 8,-15,-17, + 3,-11, 4, 13, 3, 2, -1, -3, -4, -4, 2, 0, -5, -6, 6, 2 }, + {-17, 18,-30,-20, -2, -3, 1, 15, -1,-11, 6, -4, 11, 11, -4, -5, + -10, 0, 0, 1, 3, -7, 8, 2, 5, 1, 5, -5, 1, 6, 4, 1 }, + { -6, 1,-30,-25, -1, -8, -2, -9,-17, 16, 3, -1, -2, -9, -6, -7, + -3, 12, 6, -4,-10, 0, 10, -8, -6, -5, -3,-11, -4, 0, -1, -3 }, + { -1, -1,-34,-28, 1,-10, 2, 9, 4, 16, 2, 6, 14, 17, 0, 7, + -4, 4, 4, 4, 0, 1, -1, -5, 8, 1, -4, 1, -9, -2, 5, 6 }, + {-11, 14, 1,-31, -7,-24, 9, 7, 6, 5,-13, 1, -1, 3, 4, -1, + -2, -8, -6, 3, 5, -4, -6, 7, -2, 5, 3, 3, 0, 0, -5, 2 }, + {-25, 8,-11,-18, 1, -4, 8, -3, -4, 15, 6, -5, 8, 2, 3, 4, + -4, 5, 6, 8, -7, 6, 1,-11,-15,-13, 9, -4,-14, 10, 12, 7 }, + {-20, 11,-15,-25, 3, 4, 18, 13, -4, -5, -9, -1, -5, -2, -2, -7, + 16, 5, -4, -5, -7, -2, -3, -9, 11, -2, 0, -7,-17, -6,-11, 6 }, + {-11, 18, -5,-20,-15, -3, 9, 11,-20, 12, 5, 5, 11, -3, 7, 1, + 10, -6, -3, -3, 3, 3, 14, -7, 10,-17, 9,-11, -2, -6, 7,-12 }, + {-20, 8,-14,-17, -9,-13, -3, 0,-27,-14, -3,-14, 4, 3, 6, -6, + 7, 4, 23, 9, 11, 9, 3, -4, 9, 2, 4, -1, -6, 1, -8,-11 }, + { -9, 14, 2,-37, -7, 13, 6,-11, -6, 9, 18,-11, -6, 2, 12, 4, + -1, 3, 1, -2, -2, 1, -9, -4, -2, -3, 3, 5, -6, 0, -2, -8 }, + {-29, 8, -1,-13, -2, 8, 23, 2,-10, 7, 13, -6, -5, 11, 13, 0, + -10,-13, 11,-12,-10, 6, 4, 6, 4, 3, 6, -5, -9, -2, -1, 3 }, + {-18, 6,-10,-55, -4,-11, -2, 0, 1, -3, -9, -6, 3, -2, -1, 6, + 3, -1, 3, 1, -4, -7, -2, 6, 3, -2, -1, -3, -2, 0, 4, 1 }, + {-14, 5, 3,-21, -8,-16, -4, -2,-11, 27, 15,-20, 3, 0, 1, 1, + 2, -5, -5, 4, 1, -9, 5, -3, 3, 0, -4, -2,-11, -4, -3, 7 }, + {-17, -1, -9,-17, -8,-18, 12,-13, -9, 13, -3, 3, 3, -3, 1, -2, + 0, 16, -9, 6, 12, 9, 5, 11, 2,-15, 1, -4,-16, 7, -4,-12 }, + {-18, 8, -6,-11, -8, -7, 13, 7, 1, 6, 8, -1, 21, -4, 14, 15, + 18, -4, -3, 15, 0, 9, 4, 7, 3, -1, 9, -2, 0, 7, -8, 2 }, + {-10, 7,-18,-29, 3, 12, 12, 9, 11, 4, -1,-15, 1, -1, 8, -2, + -2, 10,-15, -1, 0, 6, 12, -6, -1, 10, -6, -3,-11, -4, 9, -6 }, + {-14, 14, -9,-21,-12, -2, -1, -7, -5,-10, 5, -8, 0, 6, 9,-11, + 11, -3, -5, 3, 8, 15, -2, -4,-22, 4, -6, 12, 2, 13, 6, -7 }, + {-12, 11, -5,-29,-25, 4, 12,-13,-11, -7, 4, 2, 2, -5, 5, 8, + 7, -5, -5, 6, 3,-10, 1, -6, 6, -6, -5, -1, -2, -4, 7, 6 }, + {-15, 11, -5,-16, 0,-13, 26,-23, -6, -3, 5, -2, -2, 21, -6, -3, + -5, -1, 6, -1, 0,-13, 2, -3, -9, -1, -4, -3, 5, -4, 12,-16 }, + { -9, 9, -1,-17, -3, -6, 12, 6,-18, -2, 11,-14, -6, 3, 14,-12, + -11, -5, 14, 2, 5, -8, -4,-11, 2, -5, 16, 6, -7, -4, 8, 13 }, + {-13, 5, 3,-28,-14, 0, 6, 23, 5, 4, -1,-17, 1, -3, 0, 0, + 5, 4, 0,-18, 14, 10, 4, 2, 5, -2, 4, -3, 2, 0, 2, 0 }, + {-15, 4,-13,-16, -3,-12, -2, 2, 7, 10, 9, 3, 11, 4, 23, 14, + 9, 16, 4, 1,-12, -3, 4, -7,-15, -7,-10,-14, -6, -8, -1, -6 }, + { -7, 10, -5,-10, -3,-13, 16, -1,-12, 7, -3,-12, 2, 13, 13, 2, + 17, 15,-13, 1, -5, -2, 3, -1, 1, -3, 6, -3,-12,-16, 7, -7 }, + {-11, -5,-12,-30, -6,-22, 1, 4, -6, -3, 12, 6, 7, 0, 16, 6, + -2, 0,-22, -2, -9, 2,-13, 8, 6, -8, 4, -7, -1, -6, 4, 6 }, + {-14, 5, 1,-27, -4, 2, 1, 14,-11, -7, -8, -4, 1, 8, 0, -6, + -13, 11,-12, -7, -5, 1, 10, 7, 3, -2, 0, 6, -8, 2, 10, -1 }, + {-10, 10,-25,-13,-20, -4, 19, 3, 13, 5, 5, 7, -8, 2, 4, 2, + 3, -1, -1, -9, 14, 10, 9, 14, 3, 3, -6, 0, -5, 4, 1, -1 }, + { -9, 15,-18,-17, 4,-11, 6, 7,-12, 8, -1,-11, 2, 3, 7, 16, + -3, -9, 7,-12, 23, 0, 6, 7,-14, -9, 8, 1, -2, 6, -2, -1 }, + { -6, 9,-16,-26,-14,-11, 9, -6, 5, -2, 13, 17, 21, 7, 18,-19, + 6,-23, -2,-15, -2, 2,-10, -8, 2, 1, -2, 4, -3, -4, -5, -4 }, + { 0, 6, -5,-28,-17,-32, 2,-10, 11, 3, -5, 9, 10, 3, 11, 11, + -3, 12, -2, 2, 4, -6, 9, -4, -4, -4, -4, -9, 2, 0, 2, 4 }, + { 0, -8,-18,-34, -9, -7, -4,-11, 10, 15, 11, -1, -8, 15, 6,-13, + 9, 2, -4,-12, 0, -1, 19, 12, 6, 5, 0, -3,-10,-12, 3, -5 }, + {-10, 6, -9,-17,-12,-11, 9, -6, 11, 11, 18, -7, 0, 16, 4, 2, + -6, 3,-12, -1, 0, 1, -5,-22, -2,-12, 0, 6, 17, 5, 5, 6 }, + { 12, -5, 7, 1, -5, -2, -1, 2, 2, -4, -3, -3, -3, -2,-29, 11, + 5,-13,-73, 24, 12, 4,-14,-10, 5, 1, 0,-11, -7, -7, 7, 3 }, + { 10, -3, -1, -3, 4,-11, -5, -2, -8, 7, 9, 2, -8, -6, 6, 7, + 21, 17,-54, 47,-14,-10, 14, 19, 13, 21, -4, 3, 1, 2, -4, 2 }, + {-12, 4,-16,-12, 5, -9, -4, 19, -7,-22,-22,-17, 3, 0, -6, 8, + 23, -4,-55,-28, 2,-26, 2, 1, 4, 0,-13, 6, 0, 10, -7,-11 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, + 35, -1,-67,-35,-24,-24, -6, 2, 2, -2, 1, 3, 2, 0, -1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, + 41, -4,-73,-15, 18, 4, 17, 8, -1,-16, -1, -2, 1, 0, 0, 0 }, + { -4, -4, 4, 6, -1, 2,-16,-10,-15,-10, 21, -2, -6, -2, 14, -7, + 10, -5,-55, 34,-12, 11,-13, -2, 2, 28,-26, 0, 7, 4, 21, -7 }, + { 2, 1, 15,-22, 10, -3, 14, -6, -2, 15, -2, -7, 20, 6,-15, -7, + 23, 10,-60, 8, -4, 29,-22, 2,-13, 9,-10, 12, -1, -3, 4, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -2, 11, -5, + -21,-11,-60,-27,-17,-39, 6, 36, 0, -8, 2, 2, 0, 0, -2, 3 }, + { 2, -5, 9,-17, -1, 2, -3, -6, 8, 12, 7, -6,-33,-11,-14,-40, + 10, 36,-46, 0,-19, 5, 0,-10, 3, 12, -6, -8, 6,-12, -7, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -2, 0, + 4, -2,-87, -3, -2, 2, -2, 20, 2, 6, -1, 6, 0, 0, 2, -1 }, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, + { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, + -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, + { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, + -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, + 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, + -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, + { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, + 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, + { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, + -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, + { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, + -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, + 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, + -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, + { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, + 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 16, 65, -2, -2, 4, 3, 0, -7, 3, 1, 3, 1, 0, 5, 1, -5, + 0, 2, -1, 3, 0, 0, -1, -2, 6, 0, -2, 0, 0, -1, 1, 1 }, + { 5, 37, -4, 8, -4, -1, 9, 17, 6, -7, 5, -1, 11, 6, -4, 7, + -2, 4, 1, -3, 11, 3, 3, -9, 6, 0, -2, -4, -5, 4,-12,-11 }, + { 15, 24,-14, 2, 6, 17, 26, 5, 8, 11, -9, -7, -6, -8, 3, -5, + 9, 10, -3, 10, 0, 1, 4, -9, 4, 9, 3, 0, 4, 0, -5, 3 }, + { 9, 36, -9, -8, 7, 7, 4, 3, -1,-16, -2, 7, -5, -6, 6, 12, + -11,-12, 9, -1, -3, -9, 12, 6, -6, 2, 2, 5, 0, 5, 6, -6 }, + { 25, 39, -5, 24, 3, 10, 3, -6, 13, -8, 3, -7, 2,-10, -5, 2, + -2, 3, 5, -2, 1, 5, -2, 3, -4, 1, -5, -4, 0, 1, -2, 0 }, + { 16, 27, -1, 0,-14, 6, 4, -5, 7, -2, -6, 0, -3, -5, 2, -1, + -1,-19, 5, -8, 0, 11, 12, 5, 0, 3, 10, 6,-14, 14,-13,-15 }, + { 12, 23,-14, 2, 1, 4, -3, 16, 7, -8, 2, -8, 8, 6, -8, -7, + -3, 0, 2, 8,-13, 7, 13, -6, -4, 6,-13,-16, 14, 11, -7, 5 }, + { 16, 28, -7, -1, 6, -3, 9, 0, -7, 3, 0, 3,-12, 20, 8, 9, + 8, 23, 8,-13, -2, 4, 9, 3, -5, 13, 5, -2, 12, 14, 5, -1 }, + { 19, 37, 19, 5, 7, 5, 10, 5, 19, 10, 14, 0, 2, 5, 1, -4, + -4, 2, 2, -5, -2, -1, 2, -6, -4, -4, -5, -3, 2, -2, -2, -2 }, + { 24, 21, 1,-11,-10, 17,-14, 14, 6, -1, -6, -1, 0,-13, -1,-12, + -2, -5, 6, -4,-12, 14, 5, -2, -8, -8, 15, -7,-30,-12, 4, 0 }, + { 11, 26, -3, 3, 5, -1, -2, 3, -2, 10, 15, -4, 10,-28, 10,-17, + -8, 1, 2, -7, -1, -6,-15, -1, 4, 5, -7, 9, 0, -5, -4, 4 }, + { 18, 32, 1, 2, -7, 4, 15, 2, -9, -2, 12,-11, 7, 11, 13, 2, + 0, 5, 9,-10, 16, 3, -3, 5, -9,-23, 2, -2, -1, 5, 2, 11 }, + { 35, 24,-20, 2, 4, -1, 5, 14,-10, -9, 8, -7, 0, 5, -7, -7, + 11, 1, 5, 3, 2, 0, -2, 3, 0, 1, 4, 0, -2, -8, 0, -4 }, + { 9, 35, -1, 2, -1,-19, -3, 12, -1, 8, 8,-13, -1, -2, 2, 5, + -8, -1, 13, -2, 11, 1, 0,-10, 0, -3, -7, 2, 1,-12, 3, 12 }, + { 20, 27,-12,-12, 7, 4, -1,-13, -1, -9, 2, 13,-11, 5, 7, -9, + 9, 1, 1, 8, -9, 0, -6, 7, 4, 2, -2, 7, 3, -2, 1, -9 }, + { 8, 37,-20, -5, 0,-21, 10, -8, 3, 19, -9, 7, -3, -8, 10, -2, + 0, 5, 6, -4, -2, -1, 0, -7, 6, 1, 0, 4, -5, 6, -8, 2 }, + { 8, 27, 1, -3, -5, 1, 6, 0, 15, 2, 17, -1, 3,-17, 10, 5, + 5, -6, -6, 6,-10, 18, -5, 0, 0, 13, 7, 10, -5, -6, -2, -4 }, + { 14, 29,-20, -4, -3, 1, -5, -1, 2, 12,-10, -3, 4,-18, 4, 14, + -4, -1, -9, 15, -2, 2, -5, -3, 2, 9, -2,-14, -3, 4, -4, -7 }, + { 23, 23,-23,-11, 27, 4, 4, -1, 7, 0, -5, 9, 2,-11, 3, 7, + -2, -5, 2, -7, -7, 13, -3, -6, 2, 3, 3, -4, -1, -8, 5, -2 }, + { 16, 26, -6, 8, -9, -1, -2, -1, -8, 4, -2, 0,-12, 9, -1, 0, + -17, -9, 30, -5,-15,-16,-13, 0, 10,-11, -7, -3, -1, 0,-11, -2 }, + { 12, 32, -4, -5, 10, 19,-10, 4,-12, 5, -6, 9,-12, -6, -6, -8, + 4, 1, 3, 0, 8, 0, -3, -4, -7, -4, 10, 8, 6, 5, -1, 4 }, + { 46, 42, -3,-14, -2, -6, 6, -2, -5, -1, -3, -3, 1, -1, 3, 1, + 1, 4, -1, 2, 3, 1, -2, 6, 0, -1, -2, 4, -2, -1, 2, 2 }, + { 9, 33,-13, 4,-11, 3, -8, 22, 12, -2, 4, 0,-16, 5, 4, -1, + 7, -6, -9, 1, 7, 5, 0, -5, 5, -1, 10, 3, -2, -1, 3, -2 }, + { 9, 30, 6, -3, 6, 1, -7, 5, 11, 14, 7, 1, 0, 2, 2, -1, + 8, 7, -6,-13,-10, -2, 1, -6, 10, 7, 6, 5, -2, -5, -1,-16 }, + { 9, 28,-11,-10, 9,-10, 15, 8, 4, 9, -4, -7, 0, -5, 9, 8, + -7, 2,-15,-23, 4, -4, 4, 16, -8, -3, 0, -8, 14, 5, -3, 15 }, + { 17, 26, -5, -5, -1, -8, 20, 18, -7, -2, 4, -7, -8, -5, -4, 16, + 0, 0, -7, -2,-13, -5, -2, 3, 12, 1, 3, -5, 2, 2, 0, -1 }, + { 11, 37, 7,-23, 6, -1, 15, 13, 4, -9, 7, 5, 3, -3, -5, -8, + -2, 3, -5, -1, -8, 7, 2, 13, 1, 3, 0, -3, -1, 2, 0, -2 }, + { 21, 33, 7, 20, 21,-10, 6, -5, -5, -6, -9, 2, 10, 0, 8, -4, + 10, 2, -2, -2, 0,-10, -6, -2, 0, -5, 3,-11, 3, -9, -3, 1 }, + { 6, 30,-15, -8, 16, 1, 4, 6, 4, 5, 8, -3, 8, -9, -1, -6, + 8, 2, -2, 4, -2, 5, 11,-21, 3,-10, 16,-11, 24, 10, 14, -6 }, + { 15, 36, -3, -9,-20, 12, 0, -7,-18, -4, -8, -9, 9, -7, -3, -1, + 2, 7, -5, -8, 6, 2, 2, -1, 7, 1, 1, -3, 3, -4, -8, 1 }, + { 16, 34, 21, 3, -9, 10, 7, 9, -7, 1, -4, -9, -4, -5, -5, 3, + 3,-19, 1, 5, 4, -2, -6, -5,-10,-11, -8, -2, 2, -5, -8, -7 }, + { 28, 29, -3, 18, -2, 0, -6, 12, -2, 10,-11, -4,-13,-12, -6, -4, + 0, 4, -1, -8, 6, 4, 12, 11, 10, 10, -3, -6, 1, 2, 1, 7 }, + { 3, 8, 22, -8, 3, 36, -8, -1, 9, 6,-13,-14, 8, -1, 1, 2, + -2, -8, 0, 3, 1, 2, -1, 5, -1, -8, 0, -2, 2, 2, -1, 1 }, + { 0, 6, 0, 0, 4, 13, -7,-16, -6, 15,-14,-21, -9,-10,-10, -6, + -21, 5, 4, 2, 12, 4, 12, 11, -4, -6, -6,-10, -7,-18, 1, 4 }, + { -1, 3, 10, 1, -1, 15, 4, -7,-16, 3, 0,-22, 10, 2, -3, -2, + 13, 5, -8, 16, -5, 4, 0,-11,-10,-22, 0, -4,-17, 5, 2, 1 }, + { 12, 8, -4, -9, 14, 40,-21, 0, 1,-15,-10,-12, 12, 6,-10, 2, + 8, 6,-12,-10,-11, 1, 0,-11, 2, 1, 13, 0, 6, 3, 8, 4 }, + {-10, 3, 5, -4, -3, 3, 0, -9, 2, 8,-22,-23, 17, 8,-17, -3, + 14, -8, -4, 1, -8, 3, 0, 5, -1, -3, -2, -4, 1,-10, 0, -2 }, + { 0, -1, 5, -7, 4, 12, -2, 0, -7, 2,-16,-15, 12, 21, -7, -4, + 7, -7,-11,-15, -7, -9, -5, -8, 0, -6, 8, -3, -8, 22, -7, -9 }, + { 7, 19, 4, -9, 24, 22, 2, -6, 8, 13,-14,-20, -4, 11, 8, -4, + -1, 2, 0, -7, 5,-17, -3, 3, -6, 5, 3, 4, -5, -7, -3, 14 }, + { -2, 6, 2, 8, -2, 5, -4, -2,-10, 3,-45,-30, -3, -3,-12, -4, + -3, -3, -1, 9, -6, -6, 5, -4, 0, 5, -1, -2, -1, 0, -6, -1 }, + { -3, 14,-16,-10, 10, 0, -2,-40, -9, 12, 2,-19, 15, -4, 4, 3, + 3, -4, 7, 1, -4, -5, 0, 4, -1, 0, -9, -2, -4, -1, -2, 0 }, + { 7, 16, 2, -7, 8, 2, 0, 1, 5, 21,-10,-26, 7, 2, -9, -7, + -3,-16, 8, 5, 5, -6, 10, 4,-14, -6, 5, 3, -2, -2, -4, 1 }, + { -9, 14, -1, 3, 3, 11, 1, -5, -3, 13,-16,-18, 20, 6, -5, 0, + -3, 2, 8, 4,-19, -9, 12, 0, -8, 2, 2, 1, 6, 13, -7,-11 }, + { 2, 5, 16, -4, 19, 15, 4, 0,-11, 7,-10,-10,-16, 18,-11,-12, + -9, -4, 7, -4, -4,-17, 1, 1, -8, -3, -3, 5, -2, -6,-11, -5 }, + { 2, 12, 0, -9,-10, 14, 6, 2, -3, 2,-12,-28, 12, 1, -1, 2, + 0, -3, -4, 7, 16, 5, -7, 8, -4, -3, -1, 3,-12, 4,-17, -5 }, + { -4, 7, 11, 6, 1, 14, -4, -6, 5, 5, -6,-24, 23, -9,-15, 13, + -7, -9,-15, 10, -1, 8, -5, 1, 12, 6, 2, 0, 4, -2, 9,-10 }, + { 1, 5, 11, 3, 6, 12, -3, 8,-21, 5, -7,-20, 12, -2, -9, -3, + 17, -7, -8, -9,-14, 3,-13, 18, -8, 9, 2, -8, 4, -8, -5, -2 }, + { -3, -3, -1, 5, -2, 15, 3, 2, 1, -8, 1,-39, -6, 13,-13, 0, + -2, -5, -6, -3, 0, -5, -2, 15, -9, 5, -3, -6, -2, 7, 0,-13 }, + { 2, 8, 5,-12,-13, 22, 8,-16, 11, 5, -2,-32, -2, -4, 11, 5, + 5, -6, 1, 3, 1, 5, 3, 6, -5, 4, 4, -8, 8, 4, 1, 3 }, + { 13, 9, 5, -4, 9, 18,-11, 2, -1, 15,-10,-19, -2, 14, 0,-10, + 1, 1,-18, 3, 2, -6, -8, 20, 7, -8, 16, 9, 9,-13, -3, -2 }, + {-13, 11, 11, -9,-10, 13, -3,-18, 2, 10, 5,-21, 6, 15,-11,-21, + 3, 14, 0,-12, 9, -1, -2, -4, 3, -3, -9, -8, -5, -2, -8, 2 }, + { 3, 3, 11, 4, 0, 13, 1, -8, 10, 13, -6,-26, 2, 12, -3, -5, + 12, -2, 1, 8, -7,-17,-19, 5, 10, 7, -3, 2, -3, 0, 5, 0 }, + { 5, 0, 3, -3, -9, 5,-15, -5, -5, 17, -5,-31, 0, 13, 13, 5, + -1, -6,-14, 7, -8, 9,-14, -2,-16, -4, -4, -6, 6, -6,-10, 6 }, + { 13, 3, 1, 7, -3, 4, -1, -2, -1, 4, -8,-32, -1, -4, 0, 3, + -10, 7, 10,-10, 4, -1, 6, 2,-16, -9, 4, 3, 13,-23, -3, -4 }, + { 4, 11, -4, -9, 4, 11,-12,-12,-12, 6, 1,-28, -3, 14, 18, -2, + -12, 7, 15, -3, -5, -7, -3, 2, -6, 4, 4, -2, -5, -3, 2,-13 }, + { 8, 7, -7, 0, 13, 7, -8, -7, 8, 36,-10,-22, 3, 23, -3,-10, + -3, 11, 1, -7, 3, 3, -1, -7, -4, 2, 3, 2, 5, 3, -4, -1 }, + { -1, 1, 13, 1, -6, -1, -6, -9,-18, 17, -5,-37, -1, -1, -6, -4, + 1, -6,-15, 2, 17, -9, 0, -3, 0, 4, 0, -5, 0, 4, 1, -5 }, + { 0, 14, 5, 0, -7, 2, -6, 17, -6, -9, 7,-16, -5, 23,-14,-13, + 8,-15, 11, 10,-11,-13,-33, -5, -2, 1, 6, 8, 0,-13, -9, 5 }, + { 11, 7, -2, -8, 9, 11, 25,-14, 7, 3, -1,-33, 14, 8, -6,-19, + 3, 3, 2, -1, -3, -1, -2,-10, -3, 1, 2, 1, 4, 2, -3, 4 }, + { -2, 8, 4, -2, 9, 13, -4, -2,-15, -3, 19,-37, 9, 25, -9, 2, + -5, -2, -2, -4, 4, 2, 2, 0, 3, 3, 3, 5, -2, -3, -4, -3 }, + { 10, 13, -1,-15, 4, 6,-18, -4, 25, 1,-23,-17, 15, 13, -8, -8, + 7, 4, -5, 3, 6, 9, -7, 6, 0, -5, 8, 0, -6, -1, -2, -2 }, + { 1, 3, 9, -5, 27, 15, -9,-31, -1, 23, -2, -9, 1, 8, -1, -7, + -2, -8, -4, -4, -2, -1, 3, 5, 0, 0, -1, 1, -7, 7, -3, -3 }, + { -8, 7, 3, -6, 8, 3,-11, -2, 36, 14, 1,-30, 6, 10,-12, -6, + -6, -2, -4, -3, -5, 0, 9, 4, -5, -5, -8, 12, 4, -3, 1, -8 }, + { -2, 9, 33, 0, 12, -3, -7, -4, -4, -1, 6,-25, 11, -6, -9,-11, + -2, -4, -2, 6, -1, -3, -6, 15, -6, 3, 10, -4, 1, 0, 5, 8 }, + {-22,-21, -9,-19, -5, -7,-12,-15, -8, 9,-19, 14, -7, -4, 5, -8, + -2, 7, 1, -3, 4, -4, 6, 11, 2, 6, -3, -5, 2, -2, 0, -3 }, + {-32,-13, 3,-24, 3, -8, 4, 1,-10, 14,-15, 0, 4, 6, -1, 6, + 7, -1, 6, 4, -3,-17, 1, 4, -6, -1, 1, 0, 3, 3, -7, -4 }, + {-32,-11, 7, -8,-12, 13, -5,-22, -4, 12,-16, 2, 0, 4, 0, 1, + 0, 6, -5, -8, 2, 6, 5, 0, -3, -6, 5, 6, 5, 5, 13, -4 }, + {-44,-33, 6, -4, 2, 0, -9, 10, 3, 4, 7, 0, -1, 7, 5, 1, + 1, -3, 1, 6, -1, 0, 2, 3, -4, 0, 0, 1, 0, -1, -2, -1 }, + {-30,-18,-24, -8, 5, 0, -2, 14, 7, 0, 1, 12, 6, 4, -9, 7, + 5, 7,-11, -5, 1, -8, -1, 2, 2, -9, 7, -1, 7, 5, 6, 6 }, + {-22,-20,-13, -9, 20, -3, 10, -8, 6, -4, 2, -7, 10, 8, 0, -1, + 2, -3, 6,-19, 2, 4, 3, 3, -7, 2, -1, -6, 1, 1, 6, -2 }, + {-27, -8, -1, 3, -1,-11, 24, 4, -1, 1, -8, 8, 5,-11, 15, -3, + -15, -1, -1,-13, -1, 1, -5, 5, 2, 3, -9, 0, 4, 3, -7, 6 }, + {-33,-16, -1, -8, 10,-23, 6, 13, -1, -3, -9, 0, 5, -7, -5,-12, + -2, 3, 3, 6, -2, -3, 2, -3, 9, -6, -3, -2, 0, 5, -3, -4 }, + {-22,-17, 11, -3, 3, 1, -1, -5, 17, 2,-15, -2, 10, -9, 6, 14, + -16,-12, 20, -1, -7, 6, -3,-12, 1, 10,-10, -1, 7, -3, -1, 10 }, + {-28,-13, 1, -3, -1, -1, 0, 3, 3, 5, 1, 10,-10, -3, 7, 2, + 4, 19, -1, -1, 10, 5, -8, 1, 11,-15, -4, -3, -5, 4,-13, 3 }, + {-22,-13, 42,-20, 5,-13, 7,-11, 1, 1, -1, 1, 6, 3, 6,-11, + 3, 3, -2, 0, -4, 4, -3, -1, -5, 2, 0, 0, -9, -1, 4, 4 }, + {-26,-15, -2, -6, -4, -2, 16, 8, 21, 8, 1, -3,-10, 7, -8,-12, + -5, 12, -9, 3, -2, -3, 18, 1,-12,-15, -4, 5, -3, 0, 12, 7 }, + {-26,-16, 5, 6, 14, -3, 15, 6, 1, -7,-13, 16,-15, 5, 11, -2, + 9, -7, -4, -2, 0, 0, -2, 7, -8, -6, -5, 2, 7, -3, 2, 12 }, + {-31,-17, -8,-30, 4, 14, 6, -6, 6,-11, 0, 3, -4, 0, 0, -4, + 0, -4, 1, 4, 3, 4, 0, -5, 3, 2, 2, 0, 2, 1, 3, 5 }, + {-61,-10, 4, 10, 4, 7, 0, -3, 0, 1, 0, -3, 0, 1, 0, -2, + -1, 1, 2, -2, 4, -3, 1, 1, -1, 1, -2, -4, -4, 4, 0, 0 }, + {-28,-13, -8, -4, 3, -3, 2, 1, 11, 14, 3, 9, 1, 13, 3, 5, + -3, -2, -2,-12,-14, -9,-11,-15,-12, -5, -4,-12, 3, -3, 0, -5 }, + {-41, 0, 12,-24, 13, 4, 5, 16, -5, -4, 0, 0, 13, -4, 1, -9, + 9, -6, -1, 6, -2, 5, 2, 9, 6, -9, -8, 8, -2, -3, -6, -4 }, + {-26,-19, -2,-15, 4,-14, 6, 0, 26, 20, 8, 9, 9, 3, -4, -5, + -8, 1, 0, -1, 5, 9, 3, 4, 4, 7, 1, 3, -2, -2,-10, 0 }, + {-29,-18, 9, -4, 1, -5,-14,-12, 5,-10, -5, 4, -5, 0, -1, -1, + 4, -5, 7,-16,-11, 2, 7,-15, 2, -4, 6, -4, -6, 7, -3, 7 }, + {-27,-16, 9,-14, 3, -8, 9, 0, 7, -4, -3, -7, 0,-10, -1, 2, + 1, -2, 15,-10, 14, 7, 6, 17, 3, -4, 3,-10, 8, -8, 3, 11 }, + {-21,-20, -8, -8, 4, 5, -3, -2, 0, -5, 14,-10, 11, -4, 13, 0, + 5,-11, 19,-18, 18, 3, -5, -3, -4, -8, 11,-10, 10, 3, 4, -9 }, + {-35,-15, 13,-12, 4, 0, -2, -4,-12, -3, -8,-24, -7, 1, 7, 8, + -3, 0, -2, -1, 3, -2, -2, -6, 8, 1, 0, 1, -6, -1, 2, -6 }, + {-19,-14, 13,-10, 9, -1, 1, 3,-12, 5,-16, 7, 13, 9, 4, -4, + 6, -5, 4, 9, -3, 17, -4, 12,-11, -6, -5, -6, 13, 2, 7, -9 }, + {-34, -8, -4, 1, 2, -1, 3, 6,-20,-11, 8, -1, 4, 2, -9, 4, + -4, -5, 16, 10, -4, 14,-13, 1, -6, 0, 2,-10, 0, -3, -3, 7 }, + {-36,-10, -8, -3, 2, -2, 14, -4, -1, -7, -4, 10, -1, -3, 15,-11, + 0, 2, 3, -1, 4, 0, 8, -1, 0, 18,-11, -5, 15, -5, 13,-12 }, + {-22,-13, 14,-20, 15, 25, 16, 10, 8, -2,-10, -5, -1, -8, 11, 8, + -1, -2, -4, 1, 2, -1, -7, 0, 0, 0, -3, 0, 2, -1, 0, 2 }, + {-31,-22, 7, 6, -2, 5,-20, 14, -6, 7, 0, 14, 3, -7, 3, -6, + -2, 1, -3, -5, 1,-10, 1,-24, 6, -2, 3, -7, 1, -7, 8, 7 }, + {-25,-20, -3, -9, 10, 6, 12, 7, 5, 4, -3, 6, -1, -5, -6, -8, + 3, 5, 6, 5,-10, 10, -4,-15,-15, -2, -9, 2, 18, 1, 8, 12 }, + {-24,-19, -2, -4, -7, 11, 6, 9, 16, 2, -7, 18, 6, -7, 6, 6, + -2, -9, 3, 12, -2, 3, -1, 6, 7, 8, 0, 8,-11, 8, 4, 2 }, + {-26,-20,-12,-12, -2, -3, 1, -5, -1, -2, 0, 3, 7, 9, -2, 2, + 9, 22, 13, 4, -4, -1, -2,-14, 5, 15, -8, -5, -7,-11,-14, -6 }, + {-21,-18, -1, -4, 0, 3, 7, -2, 10, 8, -8, -1, 15, 1, -9, 3, + 1, 3, -5, -2, 2, 4, 0, -1, 10, 2,-19, -8, 8, 30, -7, 8 }, + {-25, -6, 26, 4, -8, 4, -2, 21, 5, -4,-16, 5, 13, 4,-10, -1, + -6, -2, 2,-10,-13, 1, 3, -3, -6, -8, 2, 11, 1, -7, 0, 5 }, + { 0, -1, -2, 19,-12,-48, -6, 11, 8, -2, -4, -2, -7, 5, -3, 2, + -2, -1, -1, -7, 0, -3, -3, -4, -4, 4, 1, 3, -3, -1, -2, -5 }, + {-11, -8,-28, 18, 16,-24, -8, 19, 4, 8,-12, 9, -4, -2, 4, -7, + 6, 2, 3, 3, -4, 0, 1, -6, -4, -2, 2, 6, 0, -3, 1,-16 }, + { -9, -5,-26, 7, -3,-37,-16, -2, 2, -7, 4,-13, 0, -4, -6, -5, + -6, -4, 0, 3, 4, -3, -4, -4, 4, -3, 9, -4, -2, 2, 7, -4 }, + { 2, 9,-18, 7, 29,-24, -1, 7, 14, 10, 3, -3, -2, -5, 6,-10, + -6, -3, -8, 0, 5, 1, 4, 3,-12, 2, 6, 1, 3, 4, 1, -3 }, + {-20, 2, 8, 20, -9,-24, -4, 18, 3, 11, -1,-11, 6, 9, -1, -3, + 1, -1,-15, 3, 15, 9, 3, 2,-13, 2, -8, 8, 1, -1, 1, -8 }, + {-12, 5,-11, 6, 19,-26,-17, -6, 4, 14, 6, -8, 9, 5, -6, -5, + 2, -1, 20, 1,-11,-10,-18, 20, -7, 0, -3, 4, 2, 0, 10, 4 }, + {-15, 1, -2, 13, -8,-21,-22, 4, 4, 3, 3, -7,-31, 4,-10,-14, + 0, 8, 4, 5, 8, 11, 2, -8, 6, 7, 0, -2, 6, 8, 8, 7 }, + {-13,-10, -9, 12, 19,-16, -3, -2, 9, 2, 11,-29, -1, 9, 4, -3, + 1,-10,-10, 16, 1, 7, -7, -6, -4, -1, -5, 3, 6, 0, 3, 1 }, + {-17, -1, -5, 19, 12, -9,-21, -5, 2, 12, -7, -7, -3, 8, 7, -2, + 6, -9, -9, 1, -4, 1, 1, 3,-14, 2, -8, 0, 10, 1,-12, -6 }, + {-13, -5, 8, 15, 0,-20, -2, 20, 8, -8, 8,-19, 12, 10, 2,-11, + 0, 12, 1,-11, 0,-11,-15, 5,-11, 2, 4, -4,-11, 5, -4, -5 }, + { 3,-11, -7, 8, 0,-17,-26, 15, 19, -7, 10, -9, -5, -5, 14,-25, + 0, -8, 2, -9, -3, 9, 1, -6, 4, -4, 3, -9, -1, 6, 2, 2 }, + {-12, 5, 5, 9, 14,-18,-19, 4, 2, 16, 14,-21,-15, -9, -1, 16, + 12,-11,-10, -5, -7, 4, 15, -8, -5, -1, 1, 14, 13, -7, -1, -4 }, + {-10, -5, -1, 8, 7,-23,-10, 14, 6, 11, 10,-16, -3, 16, 6, 0, + 0, 9, 6, -2, -7, 1, 22, 5, 3, -8, 0, 3, -2,-10, 3, 0 }, + { -2,-14, 2, 16, 15,-17,-17, 6, 19, 4,-10,-15, -1, 15, 11,-14, + -8, 5, 8, 8, -2, -8,-11, 10, 10, -8,-14, 2, 13, 4, -2,-12 }, + {-10, 3, 6, 4, 19,-23,-19, 1, 4, -9,-30, 3, -6, 18, 0, 2, + 0,-11, 0, 3, 7, -2, 8, 5, 2, -3, 6, -9, 1, -4, 7, -6 }, + { 9, 5, -2, 21, 20,-33,-13, 7,-10, 8, 8,-15, -6, -4, 1, 5, + 3, 7, -2, -9, -1, 4, -6, 1, 0, 9, -1, -5, 2, 1, -3, 3 }, + { -9, -3, 3, 15, -3,-30, -7, -7,-25, 6, 2, -6, 1, 19, 1,-12, + 1, -8,-13, 9, 13, 1, 8, 2, 5, 15, -2, 3, -9, 0, -4, 4 }, + { -6,-12,-17, 25, 22,-13,-10, 9, 2, 11, -7,-16, 4, 6, 1, 0, + 0, 18, -4, -5, 4, -2, -1, -5, 0, -4, 6, 1, 6, -1, 7, 0 }, + { -1, 0,-10, 8, 8,-27, 0, -2, 29, 16, -2, -4, 9, -1, 2, 0, + 6, 10, 6, 4, 2, -7, 9,-18, 3, 3, 3,-10, 17, 10, 9, -6 }, + { -3,-12, -6, 11, 20,-32, 5, 21, 3, -4, -9, 2,-10, 1, 7, -4, + 5, 0, 0, -1, -8, -9, -7, 4,-10, 5, 0, 2, -5, 4, 9, 1 }, + { -5, -1, -5, 1, 2,-19,-13, 1, 6, 12, 2,-16,-17, 11, 10, 13, + 16,-12,-11, 3, -6, 0, 6, 4, -3, 1, 8, 2, 5,-11, 3,-14 }, + {-19, 5, 10, 11, 2,-23, -9, 16, -2, 7, 0,-11, -7, 10, 6, -7, + 26,-15, -4, 8, 6, -4, 7, -9,-15, 1, 8, -4, 4, 2,-12, 16 }, + {-11, 1, 11, -4, 1,-31,-13, -1, 8, 5, 4, -2, 0, 13, 7,-17, + 7,-10, -6, 1, 4, -1, 2, -9, -4, 9, 3, 3, -4, -5, 3, 4 }, + { -3, 1, 10, -1, 0,-15,-22, 4, 40,-11, -4, -3,-14, 9, 11, -1, + 9, -1, -6, 6, 3, -6, 0, 0,-12, 7, -2, 0, 9, 3, 1, 3 }, + { -1, -1, -1, 14, 8,-24,-14, -8, 5, 8, 5,-12,-17, 8, 2, 7, + 10, -8, 0, 4, -6, -6,-10, 8, 4,-12, 3, -9,-12, 5, 4, -3 }, + { -5, 1,-11, 8, 9,-24, 0, 2, 2, 14,-12,-13, 1, 6, 7, 0, + 7, -6, 9, 26, 11,-14, 8, 10, 1, 9, 0, 11, -2, 6, 2,-10 }, + {-13, 1, 4, 34, 19,-17,-15, 0, 3, -2, -7, -1, 0, -3, -3, -1, + 1, -1,-10, 8, 5, 0, -8, 4,-17, 9, -2, 0, 0, 6, 2, -3 }, + { -6, -4, 1, 2, 2,-14,-29, 0, 9, 34, -3, -5,-14, 6,-10, -9, + -5, -1, 0, 3, 3, 0, 1, -1, -2, -1, -1, -3, -3, -4, 3, -3 }, + { -4, 6, 3, 14, 14, -8,-29, 31, 11, 14, -4, -5, -6, 10, 6, -9, + -1,-11, -7, 1, 7, 4, 1, -6, 4, 0, 10, -7, -5, -1, 2, 4 }, + { -4, -4, -2, 14, 6,-32, -6,-14, 14, -5,-11, 10,-18, -4, 6, -8, + 9, 5, -4, 1, -4, 5, -2, -9, 3, 5, 2,-10, -6,-17, 3, 17 }, + {-16, 9, 21, 19, 4,-20,-17, 14, 9, 15, -6,-17, -1, 1, 6, -3, + 1, 1, 8, -3, -6, 6, 9, 4, 9, -9, -5, 1, -1, 0, -1, 2 }, + { -7, -5, 3, 19, 1,-20, -9, 14, 21, -7,-18, -9, 26, -7,-17, -7, + 12, 6, 0, -9, -6, 14, 9, -9, -8, 4, 15, -7, -9, -1, 9, 1 }, + {-20, 30, -6, 11, 24, -4, 0, -6, -2, 8, -4, 12, -8,-17, 0, 5, + -4, 1, -1, 3, -3, 5, 3, 3, 7, -2, -3, -2, 4, 0, 0, -1 }, + {-35, 17, 6, 1, -9, -1,-16, 3,-20,-13, 8, 7, -4, -7, -4,-20, + 7, 12, -5, 5, -5,-11, 12, -1, 15, -9, -6, 16, -4, -9,-13, 4 }, + {-21, 36,-19, 9, 0, -7, -8, 9, -4, -3, 3, 0, 7, -8, -2, -2, + -11, 13, -1, 5, -3, 7, 2, 3, -1, -2, -5, 1, -1, -2, -5, -3 }, + {-12, 33, -4, 1,-12, -9, 0,-13, -1, 2, -8, 4,-10, 6,-16, -7, + -1, -4,-10, 15, -1, 0, -5, -8, 5, 5, -3, 0, 2, -7, 1, -7 }, + {-14, 32, 5, -7,-15, 3, -5, 8, 14, 5, 9, 13, 3, 18, -3, 7, + 4,-10,-10, 10, -1, 2, 0, -2,-11, 5, -3, -4, 2, 2, 7, 4 }, + {-14, 34, 1, 20, -1,-12, 0, -3, -7, -4, 7, 18, 9, -3, 14, -7, + -9,-20, -7, -4,-13, 12, 1, 12, 5, -6, 2, -4, 0,-15, 1, 3 }, + {-21, 23, 7, -8, 3,-13, -3, 0, -6, -2, -7, 6,-12, 9, -6, -2, + -2, -4, -1, 6, 9, 5, -9, 15, 0, 8, -8, 7, 6,-15, 3, -5 }, + {-27, 32, -1, -4, -2, 4,-10, 12, -3, 8, 13, 7, 0,-15, 4, -2, + 3, 5, 7, -4, 9,-12, -1, -2, -1, -4, 0, -4, 2, -5, 6, -6 }, + {-17, 29, 15, 0, -1, -4,-10, 13, 12, -1, -8,-10,-10, 4, 7, -2, + 6, -5,-13, 19, 6, 1, -7, 2, -9, -2, 12, -4, -8, -3, 2, 4 }, + {-38, 27, 16,-15, -6, 3, -7, -4, 0, -1, 6, -2, -3, -6, 6, -6, + -3, 0, 2, 0, -4, 6, 1, -1, 0, 4, -1, 3, 4, 1, -2, 5 }, + {-33, 40, -4, 2, 1, 0, 0,-10,-14, 0, -7, 4, -1, 3, -2, 5, + 7, 6, -1, 4, 1, 3, 1, -7, 1, -4, 5, 7, 0, 4, 3, -4 }, + {-20, 25, 12, -4, 16, -4, 2, 2,-14, -2, -3, 29, -1, 1, 3, 1, + 9, -5, 2, -8, -3, 1, -7, -2, -7, 1, 0, 4, 16, -2, -1, -1 }, + {-10, 30, 17, 3, -5, -2, 0, -5,-22, 4, 5, 5, -3,-18, -6, 10, + -5, -7, 2, 8, 7, -7,-11, -2, 0, -3, 3, 2, 11, -4, 4, -4 }, + {-11, 30, 11, 4, -3, -8, 1, -2, 4, 18, 3, 1, -1, 0, -8, -4, + -3, 10, 13, 14, 5, -5, 1, 1,-10, 2, 15, 4, 9, -1, -5, -3 }, + {-17, 32, 18,-18, -3, -5, 6, 10, 1,-15, -5, 9, 8,-12,-10, -6, + 11, 9, -5, -8, -7, 10, 5,-10,-14, -4, -3, 1, 9,-11, 2, 1 }, + {-13, 28,-11, -1, 2,-16, -2, 7,-24, 0, 3, 6, 3, -1, -8, -7, + -12, 2, 2,-20, 10, 4, 0,-13, -2, -2, 1, 8,-14, 0, 4, 1 }, + {-14, 23, 12, 8, 8,-26, 2, -4,-14, 13,-14, 15, 3, -9, -1,-13, + -10, -2,-10, 6,-16, 12, 8, 0, 9,-10, -7, -4, -4, 7, -8, 8 }, + {-20, 45, 10,-14, 4, 16, 8, -9, 1, -8, 10, 5, -7, -2, 2, -5, + -1, 0, -5, 4, -6, -2, 4, 1, 3, 4, -4, 2, -2, -2, 5, 1 }, + {-20, 26, -4, 1, 7, 4, -8, 1, -5,-13, 2, 13, -7, -3, 6, -6, + 22, 0, 5, 11, -4,-11, 8, -9, 2, -2, -4, -2, 2,-13, -4, -8 }, + {-28, 18, 17, 3, -8,-23,-16, -6, 5,-10, 14, 10, 5, -1, -8, 4, + -2, 13, -3, -2, 3, 4, 3, -2, -3, -4, 0, 1, 3, 4, 0, 4 }, + {-12, 32, -6,-16, 18, 12,-16, 0, 7, 13, -4, 5, -8, -1, -3, 4, + 6, -2, -1,-13, 4, -1, 3, 12, -3,-10, 1, 6, 8,-11, -2, 4 }, + {-18, 26, 2, 5, 0, -9,-17, 14, 5, 1, 7, -3, -8, -3, 11, 7, + -5,-12, -8, 7, 0, -7, 2,-12, -9, 13,-11, 9, 6,-11, -5, 11 }, + {-24, 22,-15, -9, 8, 1, -7,-12, -9, 3, 11, 15, 14,-11, 12,-15, + -5, 7, -2, 0, -8, 3, 3, -1, 2, 11,-11, 14, -6, 13, 1, -6 }, + {-20, 28, 18, -4, -6, -5, 12, 14, 2, 10,-13, -6, -8, -6,-13, -1, + -26, 22, -3,-14, 6, 0, 10,-15,-13, -9, 6, -7, 1, -5, -4, -1 }, + {-19, 26, -8, -3,-14, -6, -9, -4, -8, 15, -8, 3,-12, -4, -2, -7, + -5, 3, 13, -3, -4,-25, 4, -1, 5,-12, -1,-13, 5, 2, 0, 6 }, + {-18, 43, 14, -8, 1,-23, -2, -2, 1, 3, -7, 0, 0, 8, -1, -3, + -5, 1, 5, 2, 0, -2, -2, -2, 1, -1, -1, -7, 0, 3, -3, 9 }, + {-11, 30, 10,-14, 3, 1, 10,-11, 1, -7, -4, 14, 2, 1, -9, 1, + -11, -2, -7, 5,-11, 1, 3, 14, 1,-16, -8, 3, -5, 7, -4, 4 }, + {-18, 24, 6, 3, 8, 7,-22, -7, -7, 3, -8, 4, 23, 9, 3, -1, + 3, 6, 7, -1, -7, 6, 4, 1, -3, 1, -6, -1, 2, -7, 3, 3 }, + {-15, 38, -7, -1,-11, 2,-17,-24, 24, 8, 7, -4, -5, 2, 2, -7, + 1, 4, 0, -9, 5, 0, -1, 1, -1, -5, -6, 3, 0, 7, 8, -3 }, + {-14, 22, 1, -5, 9,-12, -9, -5, -6, 5, 7, 8, -1, -4, -9, -3, + -33,-16, -9, -1, 12,-11, 17, -7, -3, -1, -7, 3, 2, -3, 16, -4 }, + {-14, 20, 6, 4,-10, -4, -4, -4, 1, -7, 2, 6, 8,-12, 4, 1, + -1, 12, 10, 3,-14,-10, -3, 18, -2, 33, -5,-17, 17, -5, 9, 7 }, + {-12, 23, 13, 0,-11, -8,-11, 12, -5, -9,-16, 11, 6, 4, 12, -5, + 5,-13, 7,-12, -3, 1, 2, 12, 1, -4, -1, 5, 4, 11,-12, -3 }, + { 15, 2, 14, 7, 1, 2, 1, 12, 10, 23, 4, 6,-20,-10, 4, 26, + -6, 13, 4, 3, 2,-11, 5, -7,-10, 4, 9, 1, 10, -4, 11, 4 }, + { 17, 15, 31, 17, 18, 16, 11, 24, 2, 4, 2, 3, -8, -3, 7, -3, + -5, -7, -2, -6, -4, -5, -4, -1, -4, -2, -5, -6, 2, -1, 4, -2 }, + { 16, 8, 15, 14, 3, 7, 21, 9, 8, 15, 21, 6, 8, 12, 5, -5, + 7, -3, 10, 2, -3, 8, 6, 0, 5, 5, 6, -3, 2, 4, 0, -5 }, + { 5, -4, 6, 12, 6, 13, 24, 17, -5, 17, -1, -6, -7,-10, -8,-18, + 3, -2, 2, 7,-15,-11, 12, -3, -2, -2, -4, -7, 2, 0, 5, 5 }, + { 10, -6, 8, 11, 12, 20, 22,-11, -3, 15, -3, 15, -2, -2, 0, 2, + 5, -8, 4, -5, -9, -4, -1, 2, -1, -3, 1, 3, 13, -1, 9, 7 }, + { -5, 8, 5, 11, 14, -5, 14, -9, 2, 35, 8, 15, 1, -2, 2, -2, + 4, -9, -3,-14,-12, -2, -2, -4, -2, -8, -3, 1, -6, 3, 10, 0 }, + { 16, 0, -6, 15, -3, 4, 4, 3, 3, 20, 5, -4, 10, 9, -9, -3, + -10, -2, -7, 11,-11,-10, 17, -1, 3,-15, 2, 9,-15,-10, 16, 10 }, + { 14, 4, -7, 19, 3, 0, 19, 8, 16, 34, -9, 6,-13, -1, 6, 5, + -1, -2, 4, 3, 2, 1, 1, -1, 0, -7, 2, -1, 1, 0, 6, -1 }, + { 1, 6, 9, 13, 9, 10, 15, 16, 10, 18, 13, 17, 3, -1, -7, 2, + -15,-11,-10, -4,-13, -6,-17,-13, -6,-14, 1,-10, 6, 4, -1, -1 }, + { 13, 1, 7, 10, 14, 13, -7, 5, 5, 28, 14, 14, -2, 2, 3, -3, + -13, -4, 10, -9, 19, -4, -3, 4, -5, -5, 0, 5, -5, 0, 3, -4 }, + { 1, 0, 6, 22, 9, 18, 18, -3, 5, 10, 12, -2, 1, -3, -8,-12, + 9,-10, -7, 1, -1, 19, 0, 2, -8,-11,-10, 9, 6, 11, 0, 3 }, + { 10, 11, 19, 44, 0, 14, 1, -7, 6, 22, 2, -1, 9, 2, 0, -4, + 4, 0, -6, -6, 3, 0, 0, -2, 2, -5, 1, -2, 0, 1, 1, 1 }, + { 5, 7, 0, 32, 30, 26, 5, 4, -7, -3, 15, -6, 3,-10, 7, 6, + -8, -7, 2,-13, -5, -1, -3, 7, 3, -2, -8, 0, 6, 4, 5, 0 }, + { 9, 8, -2, 4, 2, 11, 4, 29, -5, 14, 8, -5,-14, 8, 0, 9, + 8,-10, 5,-15, -6, -9, 9, -1, 18,-16, 9,-21, -3,-13, -2, 8 }, + { 25, 7, -9, 23, 20, 18, 6, 16, -9, 8, 8, -5, 11, 13, -8, 7, + 4, 10, -2, -1, -7, -9, -7, -9, -4, 1, 1, -5,-10, 8, 4, -5 }, + { 9, 2, 16, 14, -5, 14, 1, 0,-21, 17, -1, 9, 12, -3, -3, 4, + -4, 14, 10, 3, 0,-10, 7, 4, 4,-11, 2, 4, -1, -3, 9, -1 }, + { 17, 8, 11, 26, 15, -3, 14, -1, 12, 9, 10, -8, 8,-18,-11, -3, + -14, -7, 7, -3, -3, -4, 1, -7, -3, 2, -3, 16, 10, 0, 9, 6 }, + { 9, 8, 3, 8, 18, 14, 11, 1, 10, 6, 1, -4,-16, -2, 14, -2, + 1, 8, 12, 14, 3, -3, 8, 8, 12,-15, 3, -3, 3, -2, 14, 10 }, + { 22, -3,-11, 13, -7, 11, 4, 11, 3, 14, 0, -6, -2, -9, 4, 2, + -2, 0, -5,-27,-10, 3, -1, 5, 8,-24, -3,-11, -3, 2, 11, -1 }, + { 19, 2, 8, 36, 5, -6, 3, 15, -3, -4, -5, 14,-10, 1,-12,-10, + -3, -4, 3, -2, 1, -8, 4, 3, 5, -3, 0, 4, 8, -2, 8, 4 }, + { 8, 14, 15, 9, -4, 10, 5, 11, 9, 10, 8, 9,-15, 15, 6, -8, + -10,-13, 5, -8,-20,-13, -6,-11, -1, -3, -6, -4, -1, 0, 13, 15 }, + { -2, -1, 9, 12, 2, 2, 13, 3,-23, 33, 15, 2, -4, -1, 3, 8, + 8, 6, 6, -7, 8, 6, 9, -1, 3, -8, 0, -4, 1, -8, 11, -1 }, + { 6, 5, -6, 16, 2, -3, 31, 21, -9, 12, 0, -1, -4, 1,-12, 3, + -13,-18, 2,-11, -9, 2, -8, -6, 11, -3, -1, 0, -1, 0, 13, 5 }, + { 5, -1, 2, 0, 25, 5, 10, 16, -5, 21, 14, 12, 13, 2, -5, 5, + 5, -3, -2,-14, 0,-12, 7, 11, -1, -7, 19, -1, -1, -1, 8, -1 }, + { 10, 7, 3, 11, 0, 8, 22, 3, 3, 19, -4, 12, 15, 9, 5, 15, + 2, 1, 2,-10,-10, 0, 2, -1, 0, 1,-12, -1, 21, 16, 9, -7 }, + { 11, -4, -5, 24, -7, 11, 20, 11,-15, 18, 5,-13,-15, 0, -5, 9, + 1, 0, -1, -9, 4, -8, 6, -8, 1, -2, -7, 20, 9, 3, 9, 3 }, + { 20, 0,-12, -6, 9, 31, 9, 12, 8, 27, 15, 7,-16, 5, -3, -7, + -1, -9, -2, -7, -3, 4, -8, -3, 3, -6, -2, -2, -3, -6, -1, 2 }, + { 6, -6, 48, 8, -3, 19, 12, 11, -7, 2, 3, 0, -1, 1, 8, -4, + 4, -6, 0, -4, -4, -3, 3, 6, 3,-13, -8, 5, -3, -7, 8, 5 }, + { 7, -2, 6, 11, 12, 2, 14, 4, -5, 12, 2, 9, 4, 2, 0, -1, + 2, 0,-15, -9,-16, -2, 8,-17, -5,-22,-19, -5, -1,-10, 1, -2 }, + { 11, -9, 3, 12, 6, 6, 1, 17, -6, 19, 14, 7, -7, -1, -1, -9, + 9,-11,-17, 0, -6, 16, 0, 1, 9,-24, 3, 3, -9, -3, 3, -2 }, + { 9, 0, 1, 8, 1, 7, 2, -5, -3, 8, -1, 7, 2, 6, -3, -6, + 5, -2, 6, -2, -4, -3, 0, -3, 13,-50, 1, -2, 2, 4, 4, 3 }, + { 7, 0, 26, 21, -4, 2, 17, 8, 7, 11, -7, 1, -1,-15, -1,-15, + -11, -4,-17, -4, 1, -7, 3, 6, 3, -9, 2, 3, 6, 10, 6, 12 }, + { 1, -2, 2, -1,-10, -4, 6, -3, -5, -2, -8, 2, 2, 2, 8, 0, + 1, 1, 6, 0, 11, 13, 3, 4, 0,-12, 11, -5, 19, 20, 2, 5 }, + { 5, 3,-13, -2, 1,-12, 11, -7,-12, 7, 10, 0, 7, 0, -2, 4, + -6, -9,-11,-12,-23, 12, 10, -3, 0, 6, 19, -1, 24, 18, 9, 12 }, + { 6, -3, 2, 5, 2, 2, -2, -5, -8,-11, -4, 3, -8, -4, 5, -3, + -16, -4, 3,-12, -4, 3, 32, 7, 2, 8, 32,-18, -1, 12, 1, 7 }, + { 0, -8, -1, 0, -8, 7, -8, -1, -1, 4,-12, -1, 3, 0, 1,-18, + 8, 8,-14,-10,-11, 19, 9, 5, -7, 6, 8, -4, 26, 12, -1, 6 }, + { 3, 5,-14, 7, 14, 8, 20,-13,-16,-10, -2, 17, -7, 4, -8, -9, + 14, -5, 3, -4,-12, 7, 14,-10,-19,-20, 35, 8, 13, 14, -2, 9 }, + { -2, -4, -1, 1, -3, 0, -1, 1, 2, 2, 6, 0, 0, 4, 5, -2, + 3, 3, 3, -2, -7, -3, -3, -1, 6, -2, 29, 22, 13, 34, 0, 14 }, + { -3, -9, 3, 1, 5, -4, 2, 0, 7, -9, 0, 2, -5, -3, 0, 6, + -1, -1, -1, 2, 2, 4, 8, 7, 20, -6, 7, 16, 33, 20, 6, -1 }, + {-11, 1, -3, -3,-11, 3, -9,-25, -1,-16, 4, -8, 15, 1, -2, 7, + 8, 23, 2, 18,-13, 16, 3, -7, 6, 3, 16, -8, 12, 16, 3, 4 }, + { 0, 5, 5, -5, 1, -1, 2, -3, -2, 1,-13, 2, 2, 10, 6, 7, + 18, 18, 7, 9, 8, 9, 21, 14, 7, 12, 15, 14, 15, 12, 11, 5 }, + { 1, -5, 11, -2, 17, 8, 3, 0, -1, 6, 11, -7, 6, 6, 7, 5, + -15, 14, 1, 11, 4, 10, 12, 1, 2, 4, 30, 1, 11, 1, 6, 13 }, + { 2, 4, 3, -7, 5, 8,-11, 7, -5, 9,-10, 6, 8,-10, -3, 10, + 1,-29, -4,-26, 5, -8, 13, 4, 3, 6, 35, 1, 3, 6, 3, 0 }, + { -2, 1, 0, 0, -1, -3, -7, -3, -9, -3, -1, -6, 3, 4, 4, 0, + 5, -1, -2, -2, -1, -4,-10, 8, 0, -6, 10, -4, 46, 12, 2, 28 }, + { 4, -1, 4, 1, 0, 4, -2, -2, -2, -1, 2, -4, 1, 5, 0, -3, + 1, 1, -2, 0, 1, -2, -1, -1, 3, -6, 35,-11, 13, 53, -3, -1 }, + { -5, -2, 0,-13,-16, 5,-12,-11, 1,-30, 3,-18,-24, -8, -5,-19, + 1, -3, -8, 7, -7, -8, 15,-19, 4, 10, 30, 24, 6, 1, -9, 10 }, + { -4, 8, -7, -4, -6, 12, -1, -9, -4, 2, -9, 3, 2, -2, 4, 2, + 22, 9, 4, -5, 0, 5, -2, -9, -3, 1, 18,-12, 18, 16, 4, 16 }, + { -5, -8, -3, -5, -3, 6, -7, -3, -2, -5, -3, 1, 2, 2, 4, -6, + 10, 3, 12, -3, 20, 0, 27, -4, 16, 5, 18, -3, 23, 4, 12, 11 }, + { 0, 1, 0, 1, -2, 1, 2, 1, -1, 0, -2, 2, -2, -4, 1, -2, + -2, -1, -5, -2, 0, 0, -2, 2, 9, 7, 63, 5, 12, -1, 1, 0 }, + { 4, -3, -7, -5,-11, -5,-12,-10,-10,-12,-15,-12,-14,-14, 1, 1, + 10,-10, 16, 6, 2, 9, 11, 9, 9, 8, 12, -1, 13, 12, 6, 3 }, + { 7, -3, -2, 4, 6, -8, 2, -3,-12, -5, -9, -8,-10, 15, -2, -4, + 8, 9, 7,-13,-18, 34, -5, 7, 12, 22, 16,-11, 13, 25,-15,-11 }, + { -3, -2, 0, -4, 1, 0, -3,-13, -7, 13, 12, -7,-10, 13, 19, 6, + 16, 15,-12,-15, -3, 34, 1, 5, 1, -9, 11, 21, 8, 17, -5, -6 }, + { 3, -5, 0, -4, 0, 4,-11, 4, -7, -3, -1, -8, 3, -2, 2, 1, + 11, 5, 6, 14, -3, 2, -4, -7, 0, 31, 15, -2, 24, 11, 5, 4 }, + { -1, -4, -9, 5, -8,-18, -4, -9,-20,-18, 7,-14,-16, 3, 8, -3, + 29, 11,-13,-13, 7, 1, 17, 6, 6, 21, 11, 1, 14, -8, 2, 5 }, + { -3, 8,-10, -6, 12, 2, 1, 3, 3, 3, 3, -6, -8,-14, 15, -5, + 16, 4, 16, 0, 7, -1, 0, 16, 2, 1, 22, 4, 19, 13,-11, 1 }, + { 2, -3, 10, 20, -4, -1, -8, 5, -8, -9, -6, -2, -4, -7, 8,-10, + 0, 8, -6, 1, -8, 14, 13, 5, 17, -6, 26, -1, 7, -1, 0, 12 }, + { -4, -7,-31, -2, -7, -1, 5, -5, -5,-12, 4, -7, -6, 3, 15, -2, + 5, -2, 7, -1, 10, 7, 8, -1, 14, 20, 14, 9, 16, 16, 8, 24 }, + { -7, 0, -3, -6, 1, 3,-13, -6, -4, -4, -5, -9, -1,-10, -4, -8, + 2, 0, -1, 1, 24, 24, 21, 31, 5, 2, 11, 12, 7, 4, 3, 6 }, + { -3, -5, 6, -4, -3, -1, 2, -1, -2, 1, 0, -8, -1, 2, 0, -4, + 6, 22, -1, -5, 8, 12, -1, -2, 28, 27, 20,-27, 14, 1, 2, -3 }, + { 1, -5, -2, -2, 6, -2, 9, 1, -2, -5, 3, 4, 11, 5, 2, 8, + -3, -1, 1, -2, -3, -5, 5, 8, 49, 12, 8, -3, 9, 20, 12, 17 }, + { -6, 0, 1, 7, 0, 9, -2, -4, 8, 0, -2,-10, 0, 7, 21, -1, + 0, 1, 17, -7, -5, 2, 4, 16, -2, 17, 14,-20, 15, 14, 4, 15 }, + { 0, 3, -4, 9, -4, 0, 6, 4, -6, -6, -5, -7, 2, -9,-10, -2, + -5, 0, -3,-21, 9, 14,-11, 13, 29, 2, 25, 4, 22, -1, 2, -3 }, + { 2, 12,-11, 2, 16, 9, -4, 7, 1,-10,-15, 11, -4, 3, -2, 4, + 4, -5,-10, 1, 4, 19,-15, 6, -4, -2, 30, -7, 11, 21,-12, 5 }, + { -2, -3, -2, 4, -1, -5, -3, -7, -5, 1, 0, -6, 1, -6, 7, 0, + 8, -7, -3, -2, 2, 14, 2, -3,-26, -1, 26, 22, 32, 1, -2, 6 }, + { 1,-38, -1,-20, -2, -3, -6, -4, 2, 2, 7, 0, 3, 5, 3, 10, + 6, 1, -3, -5, 7, 5, -5, -4, 8, 3, 1,-14, -1, -9, -5, -4 }, + { -5,-26, -7,-19,-10, -5,-11, 5,-11,-25, -8,-14, -9,-16, -8, -6, + -17,-14, -1, -1, 6, 2, 2, 2, 3, 0, 2, 8, -8, 3, 0, -3 }, + { 17,-49, -3,-23, -1, 11, 7, 3, 4, -4, 0, 0, -1, 4, 2, 4, + -2, -4, 2, -2, -1, -2, 2, 0, 0, -1, 0, 0, 1, 2, 0, 0 }, + { 4,-34, -6, -9, 1, 21, -7, 3, -2, -1, -3, 18, 2,-16, 7, -3, + 8, 7, -5, 7, 2, 4, 8, -6, -7, -2, -5, -1, 4, 1, 2, -4 }, + { 5,-29, 13, -2,-14, 3, 1, 18,-15, 4, -8, 8,-10, 8, 2, 1, + -8, 15, 3,-10, -4, -4, -2, 0, -3, -4, 2, -3, -4, -3, 12, -6 }, + { 13,-20, 3,-18,-17, 4,-14, 13, 28, 11, -8, -6, 16, 6, 0, 10, + 3, 4, -9, 13, 5, -7, 12, -5, 0, -7, 5, 1, 3, 3, 2, 1 }, + { 3,-27, -5,-11,-21,-11,-12, 0, -5, 7,-22, 1, 3, 5, 0, -5, + 8, 7, 1, -5, -7, 2, -5, 4, 1, 3, -8, -2, 0, 4, -2, 6 }, + { 31,-45, 0, -1,-12, 1, 2, -6, 4, 3, -1, 3, 3, 0, 5, 3, + -5, 12, 4, 6, 2, 1, -2, 1, 3, 2, 5, 2, 2, 2, 3, -1 }, + { 9,-45, 6, 5, -1,-17, -2, 18, -3, 2, 0, 1, 0, -1, 10, 8, + -7, -2, -5, -8, 6, -1, 0, 4, 6, -3, 12, -1, -2, 0, 5, -7 }, + { 3,-26, -2,-12,-12, 2,-10, 16, -3, 12, 4, 5, 11, 8,-16,-17, + -2, -3, -3, 2, 5, -9, 13, 1, 10, 11, 3, 5, -2, 2, 2, -7 }, + { 8,-26, 32, -7, -5, 22, 2, 14,-10, -8, -7, 3, 3, 7, 0, -5, + 0, -1, -3, 0, 8, 4, -5, -7, 6, -1, 4, 8, 1, 1, 7, -6 }, + { 4,-31, 2,-14, 2, 0, 1, 8, -6, -1, 17, -3, 13, -6, 5,-10, + -2,-10, -2,-10, -3, 7, 1, 5, -8, 8,-14, -3,-15, 7,-10, -6 }, + { 16,-27, 13, -4,-23, 7, -9, 6, -7, 5, 4, 2, -1, -3, 23,-18, + 7, 0, -3, 4, -3, 9, -6, -2, -1, 8, -6, 2, 6, -3, 2, -2 }, + { -1,-35, -2, -8, 11, -1, -7, -3, -2, 11, 7, 6, -6,-10, 9, 6, + -3, -5, -6, -3, 9, 16,-16, -9,-20, 12, 3, 5, -3, 1, -9, 4 }, + { 2,-24, 1,-12,-16, 5, -4, 3, -4, -1,-11,-11, -8,-14, 14, 10, + -8, 20, 8, -3,-11, 1, 1, -4, -4, -7, -3, 15, 2, -6, -2, 7 }, + { 9,-21, 2,-19, -7, -5, -8, 25, 3, 17, 5, -3, 9,-12, 8, 2, + -4, 3, 3, 1, 11, -9, -4, -3, 4, 3,-22, 6, 4, 6, 11, -5 }, + { 16,-23, 13,-17,-21,-12, 5, 9,-20, 7, 6, -6, 0, 2, -9, 6, + -6,-13, -7, -1, 5, -3, 5, -7,-10, 1, 0, 8, -9, 11, 0, -8 }, + { 10,-26, -9, -7,-19, -4, 6, 16, -7, 5, -4, 4, 8, 0, 4, -1, + 6, -7, 1, -8,-11, 10,-14, 0,-16, 6, -3, 5, -1, 14, 12, 1 }, + { 8,-27, 12,-14, -1, -1,-19, 10,-11, 21,-14, 9, -8, -3, 8, -1, + 12,-13, 3, -4, -2, 0, -9, 0, -7, 2, -3, 12, 1, -3, 3, 1 }, + { 18,-20,-14,-14,-16, -3,-24, 6,-17, 2, -3,-11, 2, -3, 12, 10, + 10, 1, 10, 7, 8, 5, 5, 4, -1, 7, 2, 2, 0, 4, 7, 0 }, + { 0,-30, 9,-16,-18, 15, 12, -3, 4, -4, -5,-11, -4,-12,-10, 0, + 2, -2, -4, -1, 2, 0, -1, -6, 2, -3, 4, -5, 7, 3, 5, 7 }, + { 25,-24, -1, -6, -9, 6,-13, -2, 3, 15, -3, 11, 4, -8,-11, 2, + 0, -9, -2, 7, 4, 8, 5, -8, 5, 6, -1,-11,-15, -5, 0, 11 }, + { 0,-34, -7,-11, -7, 9, -3, 19, 4, -8, 3,-11, 11, -3, -9, 12, + 9, 9, 2, 1, -7, 1, -3, 0, -6, -2, -1, 3, 0, -7, -2, -5 }, + { 6,-34, -4, -5, -3, -9, 2, 9, -1, 9, -5, -3,-26,-12, 8, -6, + -7, 11, -8, 4, 4, 1, -1, 0, 8, 9, -4, 7, -1, 1, -3, -1 }, + { 3,-30, 5, 6,-10, 3, -7, 6, 3, 3,-26,-19, -3, 1, 7, 5, + -4, -5, 6, 10, 13,-10, 4, -7, -4, 5, -3, 9, -6, 3, 9, 5 }, + { 4,-24, 9,-19, 2, -4, -5, 8, -3, 2, 0,-15, -1, 9, -4, 22, + 6, 9, 3, 7, 11, -9, 0, -3, 4, 5, -5, 10, -8, 5, -7, -3 }, + { 8,-27, 7, -3, -1, 2, -9, 13, 7, 12, -4, -6, -6, 5, 0, 7, + 5, 1, 15, -3, -4, 0, -5, -2, 7, -5, -7, 1, -2, 13, -8, 13 }, + { 17,-22,-15,-11, -8, 16,-14, 18, 2, -1, 14, -7, 14, -6, -6, -7, + -8, 17, 6, 4, 4, -7, -5, -9,-14, -6, -1, 9, -3, 1, 6, -5 }, + { 25,-30, 2,-12,-13, 18,-18, 16, 8, -3, 10, -8, -3, -1, -6, 3, + -5, -7, 4, 6, 7, 1, 1,-11, -5, 6, 2, -4, 9, -1, -5, -2 }, + { 7,-23, 7,-15, -1, -3, -1, 0,-10, 12, 2, 5, -4, 0, 4, 6, + -1, 5, -9, -1, -1, -7, 1, 17, 9,-17,-16, 8, 4,-14, 11, 14 }, + { 0,-31, 7,-13, 3,-11, -7, 6, 1,-11, 8, -7, 15, -3, 16,-11, + -1,-15, 16, -3, 5, 0, -2, -2, -6, 11, 5, 6, 5, -5, 6, 3 }, + { 13,-24, -2,-20,-10, 7, -3, -1, 15, 2, 6, -5, -7,-10,-20, 1, + -4, 14, 8, -2, 3,-13, -3, 1, -4, 1, -3, 2, 8, -7, 16, -4 }, + { 1, -2, -2, -3, -4, -7, 0, 3, 6, 7, 3, 2, 1, -2, -1, 0, + -6, 4, 2, -4, -3, -4, 5, 9, 5, 0, -3, -3, -4, -7,-31,-50 }, + { -1, -3, 7, 2, -1, 2, 4, 6, 0, 10, -2, 0,-20, -6, -3, 9, + -20,-22, -1, -1, 15, 9,-12, 10,-13,-20, 12, 3, 5, 6, -7,-26 }, + { 0, 4, -2,-14,-12, 6,-13, 11,-10, 3, 22, 6, 16, -2, -5, 1, + -3,-11, 0, -7, 5, -5, 0, 1, -1, -6, 8, 8, 10, 9, -5,-27 }, + { -5, 10, -2, 7, 9, -9, 5, -9, 5, 4,-15, 14, 1, 3,-10, 5, + 0, -2, 7, 3,-13, 6, 9, -6, 5,-14,-17, -1, 11, 14, -2,-26 }, + { 0, 6, -3, 0, -8, 6, 0, 1, 4, -8, 2, -5, 4, 7, 15, 11, + 9, 19, -2, 14, -8, 7, -1, 3, -3, -3,-10, -2, 12, -2,-12,-29 }, + {-12, -5, 0, -3, -2, 6, 3, -3, 2, -2, 1, 11, 2, -7, 5, 1, + 2, -2,-14, 0, -1, -5, 3, 8,-28,-26, 6, -6, 3, 8,-10,-27 }, + { -1, -3, 6, 2, 4, 15, 1, 0, 2, -2, -2, 13, 3, 6, 0, 6, + -1, -4, -1, -5, 8, -1, 5, -5,-15, 11, -8, -5, 14, -6,-14,-29 }, + { -5, -6, 0, 1, 0, 6, -3, 2, -5, -1, 5, -3, 2,-10, 3, 4, + 3, 0, 13, -3, -1, 4, -4, -6, 2, 9, 8, 2, -3, 28,-11,-31 }, + { 1, -4,-10, -9, -4, -3,-15, -6, 1, 5, -3, -6, 5, -6,-22, 27, + -13, 5, 3, -7, -4, 20, -7,-12, -1,-24, -4,-13, -8,-11,-15,-21 }, + { -6, -4, 19, -6, 2, 11, -6, 1, -3,-10, 9, -9, 12,-10, 2, 1, + -9, 1, 15, 7, -5, 5,-29,-35, 4,-30, 9, 9, 19, 17, 2,-17 }, + { -3, 3, -3, 1, 2, 5, -1, 5, -2, -3, 1, -3, -8, 3, -4, -2, + -4, -1, 12, 0, 2, -8, -6, -4, 16, -1,-14, -2, 25, -6,-15,-36 }, + { 0, -1, 3, -4, -4, -1, 7, -4, 8, 0, 10, 9, -4, 1, 10, -1, + -3,-13, -5, -4, -1, -4, 8, 11, 14, -7, -5, 16, 12, 13, -1,-28 }, + { 1, -2, 2, -3, -8, 10, 4, 9, 12, 3, 5, 0, 8, -3, -6, 2, + 16,-11, 11, 0, 1, 6, 1, 18,-10,-16, -1, -4, 5,-14,-15,-20 }, + { 1,-12, 5, 4, -7, 8, -1,-17, -2, -9,-14,-11, 6, -9, 5, -4, + 3, -2, 7, 18, -5, 5, 6, -1,-11, -2,-10, -3, 8, -3, -2,-32 }, + {-12, 5, 20, -5, -6,-11, -6, -6,-13, 4, -6, 19, -8, 2, 3, -9, + -4, -4, -1, 9, -1, 21, -1, 7, 15,-10, -1, -3, 9, -3, 2,-24 }, + { 0, -3, 2, -6, 4, -1, -9, -2, -1, -3, 6, -1, -5, -6, -5, -8, + 0, -2, -6, 9, -4, 3, 2,-13, 1, -7, 23,-13, 4, -3,-15,-33 }, + { -7, 2,-15, 11,-10, 14, 0,-11, 3, -1, 12, -4, -4, 9, 11,-13, + -13, -3,-14, 1, 3, 6, -5, 8, 0, 5, 5,-10, 4, 5, -6,-30 }, + { -6, 4, 0, -5, 4, 1, -1, -1, 3, 6, 5, -2, -5, 0, -2, 5, + -4, -2, -4, -2, 4, 7, -7, -1, 1, -4, -3,-19, 37, 12, 10,-40 }, + { -7, 2, -7,-12, 17, 11, -7, 2, 2, 3, 1, -1, 3, 4, -2, -5, + 9, -9, 6, 4, 9, 12, 11, -5, 2, -1, 0, 9, 5, -7, -2,-24 }, + { -7, 6, 1, 3, 1, 0, 6, 0, 4,-12, -2, -2, 1, -9, 10, -2, + 11, -1, 21,-12, 15, -5, 10, -5, 5, -5, 14, -6, 5, -7, -3,-29 }, + { -2, 0, -5, -2, -3, 1, -3, 0, 4, 2, 3, 0, 2, -2, 7, -2, + 3, -5, 2, -1, 6, -4, 0, -3, 8,-11, 19, -8, 22,-34, 13,-35 }, + { -1, -3, -1, 9, 11, -3, -3, -1, 7, 18, 11, -5, 2,-12,-11, 18, + 9, -5, 1, -6, -9, 12, 1, -3, -3, -9,-14, 9, 9, 8, -6,-26 }, + { 0, 5, -5, -1, -1, -2, 4, 6, 8, 2, -1, -2, 5, 1, -5, -4, + 1, 1, 18, 1, 7,-10, 3, -2, 12, -1,-15, 9, 12,-14, 13,-38 }, + { 3, 0, -8, -1, 0, 8, -9, -3, -8, 16, 3, 16, -5, -9, 0, -1, + -7, -1, -4, 13, 7, 0, 1, 2, -1,-16, 0, -2, 1, 8, -8,-28 }, + { 7, 9, -5, -3, -2, 2, 0, 3, 11, -6, -4, -2, -2, -5, 28,-18, + -6, 2, 15,-10,-15,-10, -2, 0, -2, -2, 4, -3, 7, 11, 5,-30 }, + { 9, 0, -7, -1, -4, -7, 2, 2, 9, -2, 2, 3, -8, -6, -6, 3, + -10, 4, 10, 5, 21, -4, 14,-18, 1, 3,-10, -2, 6, 14, -8,-26 }, + {-14, -1, 2, 3, -3, 7, 1,-22, -1, -1, 0, 1, 12,-14, 3, -5, + 0, 10, -3, 1, -5, 12, -3, 10, -8,-22,-11,-13, -7,-10,-13,-25 }, + { -2, -5, -4, -4, -9,-18, 9, -3, -5, 17, 13, 5, 6, 11, 3, 8, + 20, 4, 2, 9, 8, 5, 6, 1, 7, -7, -6, -2, -7, 0,-17,-23 }, + { -5, -5, 2, 0, 6, 2, -2, 2, -3, 4, 4, 0, -5, -2, -4, 6, + 8, 10, -1, 1, -5, 5,-14, -2,-11, 8, 6, 25, 7, -1, 0,-43 }, + { -4, 0, 4, -2, 7, 0, 3, 17, 5, 2, -5, 1, 21, 3, -2,-10, + -16, -9, 7,-12, 9, -8, 2, 5, -5,-10, -2,-11, -5, -1, -9,-30 }, + { -2, 3, 1, -4, -1, 0, 8, 1, 12, 4, -1, -1, 3,-17, 13, 9, + 0, 7, -6, -5, 9, 1, 5, 4,-10,-18, 0, 14, 11, -4,-16,-28 }, + { -1, 0, 2, -1, 4, 1, -1, 1, -1, -2, -1, -2, 3, 0, 0, -1, + -1, 1, 2, -2, 3, 3, -2, 4, -2, -1, -6, 1, -1, -1, 6,-70 }, + { 7, 3,-11, -1, 12, -4,-14, 4, 4, -4, 4, -2, 2,-12, -4, 15, + -17, -4, -3, 6, 8, -5, 22,-22, 5,-11, 15, -4, 4, -1,-21, -1 }, + { 10, -2,-13, 11, 4, 14, 4, 9, 8, 8, 19, 15, 14, 15, 5, 10, + 8, 15, -5, 4, 14, -8, 1, 1, 2, 1, -1, -3, 21, 8,-29, 13 }, + { -6, 0, -6, 6, -1, 2, 8, -4, -5, 4, -4, -5, 0, -2, -4, 0, + 9, -2, 1, -2, 26,-19, 21,-10, 4, 1, -8, 5, 22,-10,-13, 15 }, + { 11, -5, 1, 0, 6, 3, 7, -2, -2, -3, -5, -1, -2, -6, 1, 1, + -8, -5,-13, 13, -2, -3, -1, -9,-28, 4, 2,-11, 18,-20,-24, 9 }, + { 7, 4, -3, 6, 6, -6, -7, -5, -7, -4, -4, 0, -7, -5, -6, -5, + 2,-13,-12, 2, 0, 5, 18, 15,-13, -7, 13,-20, 16,-10,-19, 6 }, + { 5, -8, -1, 5, 10, 2, -1,-10,-11, 23, 8, -5, -8, 4, -5, -4, + -5, -5,-11, -8, 5, 1, 7, -9, -9, -6, 12, 14, 17,-12,-22, 3 }, + { -5, -8, -3, 3, 12, -1, 0, -4, -5, 1, 1, 6, 1, 5, -5, 7, + -2, 7, 1, 6, 6, 2, 0, -5, 17, -4, -5,-24, 13,-20,-27, 14 }, + { -1, 2, -3, 1, -3, 1, -3, 0, -2, 3, -2, 1, 2, -1, -2, -1, + -2, -5, 5, -2, 0, -7, 1, -6, 8, 8, 11, -5, 24,-43,-13, 2 }, + { -2, 4, 7, -3, -4, 4, 13, -4, 0, 0, -2, 9, 0, -3, -6, 1, + -7, 1, -1, 10, 0, 5, -1,-24, 25,-15, 7, 2, 22,-10,-21, 0 }, + { -5, 2, 6, -2, 13, 3, 5,-12,-11, 16, 6, 10, -5, 0, -3, 6, + 5, -5, -5, 10, 12, 10, 11, -7, 8,-14, 2,-15, 13,-14, -8, -3 }, + { 5, 6, -7, -5, 5, 2, 9, 5, 0, -1, -4, 2, 8, 0, 3, 5, + -12, 3, -3, -6, 2, -1, -5, 14, 11,-20,-21,-25, 24, -1,-10, 6 }, + { -5, 5, -2, 9, 4, -4, -1, -6, 11, -6, 5, 0, 2, -3, 6, -1, + -17,-18, -4,-13, 9, -1, 9, -7, -4, -8, 2, -3, 12,-31,-18, 5 }, + { -7,-11, 6, -8, 4, -3,-12, 0, -1, -6, -3, 0, 5, 9, 7, 2, + 1, -8, -6, 8, 2, -5, 7, -1, 16,-10, 16,-12, 18, -1,-25,-12 }, + { 3,-12, 1, 2, -2,-18, -8,-15,-10, -9, 2, -7, 11,-11, 2, -1, + -1, -1, -9, -6, 3,-14, -2, -1, 2,-13, -7, -9, 19, -5,-17, 2 }, + { 7, 1, -8, 7, 17,-13,-10, 5, 7, 1, -6, 4, 9, -4, 0, 3, + 8, 1,-14, -9, 4, 7, -9, 0, 6, -5,-12, -2, 25, -2,-19, 1 }, + { 7, -3, 6, -3, 1, 6, -7, 0, 10, 0, 4, -5,-17, -4, 4, -1, + 0, -3, -7, 19, 24, -1, 21, 8, 10, 9, 8, -1, 23, -2,-18, -2 }, + { 3, -3, 0, 5, 8, -2, -9, 2, 9, 6, 19, 8, 2, 6, -9, -2, + -4, -3, -8, 7, -7, -8, 5, 4, 26, -6, 7, 18, 24, 0,-13, 4 }, + { 0,-13,-11, -1, 3, -9, 5, 4, -7, 3, 0, 2, -1, 4, -5, 2, + 9, -2,-11, 15, 1,-21, 1, -1, 0, 4,-14, -4, 24,-16,-13, 1 }, + { 1, -9, -8, 0, 0, -4, 11, -1, 14, 16, 0, 17, -2, -9,-12, 0, + -1,-14, -9,-14, 0, -2, 19, 4, 6, 4, 4,-11, 8,-17,-19, -5 }, + { -3, 1, 2, 12, -4,-18, -1, -4, -7, 14, -3, 2, 0, -7, -8, 12, + -5, -9, 14, 12, -9, -2, 4, -6, 4, 18, -1,-25, 22, 2,-23, -5 }, + { -2, 0, 0, 0, 1, 3, 5, -1, 5, -2, -2, 2, -3, 0, 1, 2, + 0, -1, 2, -1, -9, -6, -7, -4, -2, 4, -7, -5, 64, -3,-25, 4 }, + { 12, -2, -3, 0, 8, -9, 13, -7, 6, -3,-12, 12, 15, -9, -4, 2, + 9, -4,-12, 3, 14, 1, 7,-15, 15, 0, -6,-12, 0, -3,-20, 6 }, + { 2, -1, -4, 5, 9, 6, -7, 2, -2, -7, -2, 0, -1,-18, -4, -6, + -15, -5, 11, 5,-10, -1, 2, 7, 12,-19, -7, 8, 21, -4,-15, 4 }, + { 4, 2, 5, 5, -5, 1, 3, 2, -8, 13, 0, -5, -2,-14,-11, 6, + 2, 17, 8,-13, 26, -2, 5,-15, -4,-14, 12, -9, 13,-21,-23, -4 }, + { 2, -3, -2, -3, 3, -2, 6, 9, -9, 13, 4, 2, 12, -3, -3, 1, + -17,-22, -3, 4, 3, -2, 1, -9, 1, -6, 11,-13, 14, 0,-15, 6 }, + {-16, -4, 17, -2,-20,-11, 11, 10, 5, -8, 16, 2,-17,-14, 11, 11, + -6,-11, -7, 12, 12,-10, -6, 5, 8, -4, -2, -5, 28, 3,-13, 4 }, + { 0, -3, 3, -7, 6, 8,-12, 20,-19, 18,-11, 10, -5, 0, -9, 11, + 3, 0, -2, 9, -7, -5, 18, 3, -2,-16, 1, 6, 12, -7,-16, 1 }, + { 4, 1, 5, -5, 15, 2, -8, 3, 5,-11, 15, -3, 8, -8, -1, 7, + 4, 7, -2, 6, -9, 5, 12, 2, 33, -2, -6,-18, 4, 0,-18, 11 }, + { 3, -1, 1, -1, 0, 1, 4, -1, -5, 0, 1, 0, 4, 2, -1, 4, + -3, 2, 0, -2, 4, 6, -1, 6, 42, 19, -4,-37, 19, 1,-15, -4 }, + { 2, 0, -5, 0, 10, 0, 0, -5, 3, 0, 0, -3, -3, 0, 2, -4, + -10, 2, -6, 4, 4, 1, 27, -7, 17,-34, 5, -9, 15,-16, -7, -5 }, + { -2, 7, 7, -2, 9, -2,-15, 11, 11, 7, 5, 1, 15, 1, -9, 31, + 2,-15, 2, 4, 3, 4, -1, -8, 2, -7, 6,-17, 11,-14,-11, 2 }, + { 1, 1,-11, 9, 9, -6,-14,-11,-10, 8, -3, 11, 16, -9, -8,-13, + -8, 9, 0, 6, 6, -2, 13, -8, -2, 3, 13, -3, 10, -6,-17, 4 }, + { 14, 5, 4, -6,-12, 10, -7, 8, 21, -8,-30, 15, -2, 1, 11, -9, + -5, 1, 0, -1, -1, -6, -2, 3, -5, 7, 9, 5, -5, 2, 0, 1 }, + { -1, 2, 20,-17,-15, 3, 3, 7, 11,-17,-13, -6, -3, 18, 17,-15, + -4, -4, -5, 22, 14,-14, -2,-10, -7, 11, 8, -7, -3, 0, -7, 11 }, + { 7,-11, -7, -8,-14, 22, 5, 2, 6, 13,-12, -2, 10, 3, 0,-21, + -4, 20, 3, 10, 21,-10,-12, 8, 11, 2, -5, 2, 1, 3, -1, 15 }, + { -1, -2, -1, -2,-13, 8, -4, 0, 7, -2,-17, 8, 18, 5, 3, 8, + -8, -2, 3, -4, 14,-18,-13, 14, 15,-13, -1, -2, 4, 11, 1, 12 }, + { 13, -6, -4,-16,-17, 16, 21, -2, 5,-11, -9, 19, 21,-17, -3,-17, + 3, 12, 8,-12, -6, 1, -7, 9, 9, -7, -5, -1, -3, 5, -6, -4 }, + { 11, 5, 12,-20, -6, 10, 4, 12, 8, -5,-10, 15, 13, 14, 10,-15, + -13, 1, 6, 14, 15,-17,-13, 4, -5, 10, 7, -6, -8, -3, -4, 12 }, + { 25, -1, 7, -5, -7, 11, 1, 17, 13,-15,-14, -4, 5, 3, 8, -3, + -2, 2, 0, 6, 16,-12, -6, -4, 4, -3, 7,-10, -3, -7,-13, 7 }, + { -8, 10, -3,-13, 5, 2, 4, 9, 9,-17,-13, 2, 11, 1, 6, -4, + 8,-10, 4, 1, 19,-15, -4, 12, 31, 7, -5,-17, -4, 9, -2, 7 }, + { 14, -6, -6, -6,-14, 13, 17, -5, 4,-14, -9, 7, 7, -9, 3,-16, + -15, 11, 11, 6, 4,-11,-19, 3, 5, 8, 13,-14,-14, 3, -4, 12 }, + { -2, -4, 10, -4, -7, -1, 27, 5, 2,-16,-18, 4, 12, -2, -3, -2, + -1, 1, -8,-12, 3, -4, 8, 15, 2, 4, 9,-13,-14, 9, -7, 5 }, + { 4, 2,-10, -5, -7, 2, 1, 4, -1, -6,-15, 6, 1, 10, 5,-10, + -9, -1, 13, -3, 5,-21,-11, 8, 8, 5, 27,-21,-18, -5, -1, 15 }, + { 11, 1,-16, -8,-11, 0, 5, -8,-12,-13,-17, 22, 4, -6, -1,-18, + -10, 0, 19, 2, -2, -8, -7, -3, 2, -2, -9,-17, -5, 4, 4, 10 }, + { 8, -6,-19, -5, -4, 12, 14, 15, 10, -9, -1, -9, 19, 12, 0, -1, + 2, 4, 7, 9, 16,-16,-14, 9, -4, 3, 1, 0, -2, 10, -1, -1 }, + { 12, -8, 12, -9, 0, 25, 7, 9, 2,-31, -9, -4, 15, 4, -5, 1, + -10, 11, 8, 10, 0, -6, 5, 11, -1, -6, 4,-10, -9, 6, 4, 5 }, + { 14, 6,-17, -2, 17, 12, -9, 2, 0,-25,-14, 5, 20, 14, 8,-20, + 5, 2, -2, -3, 9,-13, -3, -1, -6, 3, 7, -6, 0, 2, 3, 1 }, + { 8, 4,-15, -3, 10, 18, -4, 13, 8,-22,-10, 9, 19,-15, 7, -5, + -13, 12, -4, 9, 2, -9, -6, 0, 2, 1, -9, -6, 6, 1, -1, 11 }, + { 4, 1, 4, -5,-10, 18, 7, 2, -4, -9,-11, 0, 32, -7, 4,-16, + -1, 0, 6, 3, 6, -3,-14, 16, 9, -2, 7, -1, 0, -5, 5, -3 }, + { -3, 2, 3, -8, -6, 4, 6, 2, 4,-12,-15, 2, 8, 8, 9, -3, + -18, 6, 34, 11, 12,-15, -1, 2, 9, 2, -4, -4, 2, 4, 2, -3 }, + { 18, -6,-12, -8, -1, 15, 20, -4, -1,-11, -5, 6, 6,-11,-15, -7, + 3, 7, 10, 2, 8,-10, -5, 8, 15, -5, 5,-17,-13, 13, 11, 7 }, + { 8, -4, -6, -1,-14, -3, 6, -2, 1, -5, -1, 10, 10,-15, 5, 0, + -10, -4, -3, 7, -4,-19,-15, 27, 11, 18, 3,-19, -2, 6, 0, 12 }, + { 12, 0, -5, 0, 4, -5, 1, 5, 10, -7,-11, 21, 29, 1, -2, 1, + -4,-11, -1, 13, 11,-20, -1, 4, 4, 4, -5, 6,-13, -2, 11, 9 }, + { 2, -7, -7, -3,-10, -1, 20, 12, 1,-19,-19, -1, 5, 4, -7,-25, + 14, 1, -3, 2, 12, -4, -3, -3, -2, 6, 1, 0, 3, 2, 5, -1 }, + { 12, -8, 3,-12,-10, 10, 13, 0, 23,-14,-18, 10, 0, 15, 3,-12, + -3, -5, 5, -4, 2,-14,-10, 8, 2, 9, -1,-11, -3, 5, 13, 2 }, + { 9, -6, 7, -7,-30, 17, 6, 13, 1,-14, 0, -1, 6, -9, 8, 3, + -4, 0, -1, -7, -5,-13,-19, -3, -4, 4, -6, -2,-13, 1, -2, 3 }, + { 10, 1, 3,-18,-26, 17, 4,-16, 4, -3,-13, -4, -6,-11, -4,-21, + 7, 8, 2, 5, 13, -6, 1, 5, 8, 7, 9, -6, -6, 1, -1, 2 }, + { -3, -1, 0, -2, -2, 0, -1, 3, 4,-14, -8, -9, 13, 2, 50,-23, + -8, 8, 7, 11, 16, 3, -7, 0, -2, 6, 5, -1, 1, -2, 4, 3 }, + { 1, 3, 1, 1, -6, 3, 6, 6, 2, -2, -3, 10, 2, -8, -5, -5, + 5, 4, 4, -2, 10, -8,-40, -1, 21, 8, 3, -4, -1, 13, 4, 7 }, + { 2, 0, -4, -8, 5, 2, 7, -5, 5, -8, -4, -1, 12, 2, 12,-13, + -9, 0, 1,-12, 9,-43, 1, -5, 12, 1, 3, 6, 1, -1, 3, -2 }, + { 6, -2, -1, 1, 0, 4, 8, 14, 4, -7,-23, -5, 23,-17, -6,-15, + -8, 7, 10, -1, 7,-16, 4, -6, 2, 3, -3, -3, -1, 8, -1, 4 }, + { 10, 4, -4, 1, 7, -3, 2, 11, 4, -6, -3, 8, 5, 4, 1,-45, + -6, -4, 4, 2, 1,-14,-10, 1, 1, 6, 2, -8, -1, -3, 3, 3 }, + { 1, -1, 2, -3, -8, 9, 3, 3, -2, -5, -8, 8, 7, -7, -4, -6, + 5, -9, 11, -2, 46, -5, -1, 9, -2, 0, 3, -5, -3, -5, 7, 0 }, + { -4, 1, -2, -1,-11, 11, 8, -3, -2,-10, 0, 4, 9, 9,-17,-17, + -34, -4, -5, -7, -3,-12, -3, 11, 18, 3, -2, -5,-18, -5, -3, 6 }, + { 7, -5, -3, 1, -4, -3, -5, -1, 2, 5, -2, 3,-10, 12,-18, -5, + -10, 12, -9, 4, -6, 2, 0, 16,-17, 15, 14,-12,-10, -2, -9, -1 }, + { 4, -5, -3, -5, -3, -1, 7, 18, -7, 12, 3, 5, -8, -4,-20, 1, + -25, 1, -8, 13,-10, 8,-19, -1, -8, 10, 6, -9, -1, 0, 12, 4 }, + { -4, 5, 0, -1, 2, 5, -8, -2, -6, 4, -8, 9, 3, 2, -7, 4, + -25, 13,-23, 10, 14, 15,-11, 3,-18, 4, 16, -4, 1,-10,-10, 3 }, + { 5, -3, -1, -3, 4, 1, -3, -4, -5, 1,-12, 14, -7, 11,-15, 6, + -6, 24, -4, 13, -1, 15,-13, 8, 3, 7, -5, 2, 2, 0, 3, -7 }, + { -3, 1, 0, 8, 6, -1, 6, 5, -5, -2,-12, 4, 0, -2, -3, 5, + -6, 0, -8, 9,-10, 4,-28, 12,-20, 11,-13, 7,-18, 1,-11, 1 }, + { 1, -4,-15, 5, 0,-13, -5, 13,-11, 4, -4, -5, 5,-14,-16, 0, + -14, 5,-20, 12, 10, -7, -5, 6, 6, 22, 6, -4, -2, 3, 8, 11 }, + { 13,-11, -2, 16, 16, -7, 0, 20, -7, -1, 0, 5, -9, 12, -2, -5, + -22, 5,-10, 12, -6, 11, 9, 21, -8, 15, 4, 0, -8, -4, -4, 10 }, + { 18, -4,-13, 0, 1,-15, -1, -3, 2, 10, -1, 6, 1, -4,-20, -5, + -8, 6, -8, 17, -5, 5,-10, 8,-22, 6, -5, -2, 8,-17, 8, 2 }, + { 1, -2, -9, 6,-31, -8, -8, 8, 0, 5, -9, -4, 2, 3,-12, 11, + -18, 10, -5, 3,-11, 13, -6, 11, -3, 12, -7, 3, -9, -1, 2, 11 }, + { -9, -6, 21, -8,-15, 4,-11, 12,-11, 17, -1, 2, -6, 0,-15, 13, + -12, 19, 0, 2, -6, -3, -9, 10, 3, 17, -2, 5,-10, -3, 0, 1 }, + { 4, -6, 5,-10, 1, -5, 1, 0, 0, 0, 2, 7, -2, 2, -2, 0, + -4, 3, -4, 1,-12, 6,-49, 16,-10, 13, 0, -2, 8, 6, 1, 8 }, + { 5, -8, -7, 9, 13, -5, 7, 0, 10, 11, -4, -3, -1, 13,-14, 6, + -15, -6,-14, 16, 15, 1,-18, -4,-20, 20, -7, -1, -9, -2,-10, 10 }, + {-12, 4, 0, 10, 0, 3, 8, 4,-27, -1, -2, 19, -4, 2,-13, 3, + 1, 9,-12, 1,-22, 19, -5, 4, -9, 12, 2, -9, -8, 11, -3, 7 }, + { 4, -5, 11, -6, 17,-17, 5, -4, -2, -6, 1, -5, 2, 4,-14, 6, + -20, 19,-20, 12,-21, 5,-14, 13, -2, 11, 4, -3, 0,-10, -4, -2 }, + { -2, -1, -3, 8, -9, -7,-22, -3,-24, 13, -2, 10,-15, 5, -9, 4, + -7, 0, -5, 15, -8, 11,-13, 6, -4, 19, -8, 12, -4, 6, 9, 7 }, + { 2, -3, 2, -1, 0, 3, 1, 2, 1, -4, -2, -3, 1, 5,-12, 6, + -16, 14,-23, 10,-14, 17,-15, 16, -2, 9,-25, 9,-10, 16, 4, 9 }, + { -3, 7, -8, -3, 2, 2, -4, -8, -9, 10, 3,-11, 25,-10,-28, 27, + -9, 7,-13, 9, -2, 4,-12, -8,-14, 6, 7,-10, 3, 3, -3, 5 }, + { -8, -3, 1,-10, 8, -3, -9, -4, 13, 7, 2, 4,-10, 4, 3, 7, + -18, 2,-22, 15, 4, 20, -7, 5, -6, 13, -1, 4, -7, -6, 6, 13 }, + { -2, 3, 0, 2, -4, -2, 0, 0, 1, 2, -2, -5, 0, 1, -4, 0, + -2, -3, 1, 2, -1, 2, -8, -1,-24, 68, -3, 8, 3, 3, -1, -1 }, + {-15, -2, -9, -7, -1, 8,-14, 8, 3, 6, 0, -1, -8, 8,-23, 2, + -14, 17,-15, 8, -4, 7,-18, 0, -8, -3, -1, -4,-10, 4, -1, 4 }, + { 8, 0, 2, -7, 0, 5, 1, 3,-11, 4, -8, 14, 3, 20, 1, 26, + -11, 13,-13, 20, -2, 0, -8, 2, -6, 6, -1, 9, 3, -6, -3, 10 }, + { 5, 0, -1, -7, 10, 1, -3, 5, 4, 7, -5, -1, -3, -1, 12, -3, + -15, 7, -9, 22,-19, 8, -9, 4,-23, 13,-14, 6, -6,-14, -4, 7 }, + { 14, -5, -8,-10, 25, 3,-23, -7,-28, 0, -1, -9, 4, 1,-13, 20, + -8, 10,-16, 8, 12,-13,-21, 5,-13, 11, -2, 1, 12, -7, 2,-10 }, + { -5, -4, 9, 5, -6, 35, -7, 8, 15, 2, -1, -9, -6, 2,-18, 7, + -15, 6, -3, 2, 8, 12,-30, 7, -4, 20, 2, 6, 13, -6, -4, 0 }, + { 1, 8, -9, 9, -5, 12, -9, 16, -9, 16,-17, 14,-13, 15,-18, 14, + -15, 17,-12, 14,-13, 7,-16, 13, -9, 5,-11, 10, -9, 6,-12, 13 }, + {-10, -4, 5, 3, 1, 6, 8,-14, -5, 15, 7, 4, 8, 7,-22, 8, + -7, -8,-15, 26, 1, 13, -3, 17, -5, 9, -2, 4, -6, 3, -8, 9 }, + { 8, -3, 2, 3, 3, 1, -2, -1,-11, 8, -4, 0, -6, -5, -1, 13, + -37, 9, 1, -6,-10, -2,-10, 11, 8, 13, -3, -2, -6, 8, -4, 13 }, + { 3, 2, -3, -4, -4, 7, -8, 9, -8, 9,-20, 12,-19, 15,-18, 17, + -15, 7, -1, 20,-11, 6, -6, 3, 1, 9, 2,-14, -2, -2, 2, 1 }, + { -7, 1, -1, -3, -6, 4, 4, -3, 3, -1, 5, -4, 3, 2, -1, 9, + -59, 5, -4, 30, 3, 3, -2, -3, -1, 2, 2, 1, -1, -1, -2, 1 }, + { 0, -3, 2, 0, -1, -8, 0, 2, -3, 4, -4, 1, 10, 6, -6, 8, + -7, 4, 10, 11,-41, 27,-20, 3, -3, 8, 1, 11, -5, -8, 0, 4 }, + { 5, 1, 4, -2, 1, 2, -1, 6, -7, 2, 11, 4, 0, 0, -8, 7, + -10, 0, 0, 8, 2, 10, -1, 1, -2, 44, -2,-21,-12, -3, -1, 2 }, + { -4, 4, -2, -2, 6, -8, 2, 1,-10, 14, 8, 6, 5, 1, -2, 4, + -13, 4, 2, 5, 10, -2,-21, 32, -3, 18, 9, -6, -9, -9, 10, 2 }, + { 9,-16, -6, -2, 1, 4, 22, 2, -2, 1, -3, -2, -9, 3, 16, 19, + -24, -6, -6, -5, -8, -7, 8, -7, -1,-12, 5, -3, 0, 4, 2, -3 }, + { 10, 3,-16, -4, -1, 13, 4, 4, 1, -3, 1, -6,-14, 18, 3, 8, + -8,-28,-16, 4, 4, 2, 12, 7, 9, -4, -4, 5, -1, -1, 2, 2 }, + { -5,-13,-22, -3, -8, 21, -2, -9, 21, -4, -9, 5, -8, 15, 5, 1, + -5, -9, -7, -2, -5, -5, -1, -5, -5, -5, 3, 10, -4, 0, -7, -2 }, + { 5,-10,-18, 2, 20, 4, 13,-10, 8,-15,-11, -3, -1, 16, 10, 9, + -8, 6, 7, -5, 6, 11, 5, 17, -4, 7,-11, 5, -3, -6, 2, 1 }, + { 3, -5,-19, 1, 1, -3, -2,-25,-11,-17, 0,-13, -4, 10, 10, 2, + -5, 4, 0, 3, -3, -5,-10, -2, 13,-22, 0, 3,-11, -5, 7, -1 }, + { 12,-14,-29, 6, -1, 10, 7,-17,-12, 14, 3, 9, -9, 9, 7, 6, + -3,-13, 0, 5, 3, -1, -6, -1, 0, 2, 4,-12, -5, -1, 2, 11 }, + { 12,-15, -7, -2,-12, 17, 20,-16, -2,-12, -6, 15, -6, 12, 11, 9, + 7, -6, 7, -4,-19, 6, 2, 2, 3,-11,-10, -4, -5, -3, 3, 2 }, + { 11,-22, -6, 0, 8, 18, 3,-11, -4, -7,-15,-17,-12, 6, 16, 4, + -9, 4, -5, 3, 6,-16, 10, -7, -7, -3, 5, 0, 1,-15, -4, 5 }, + { 12,-22,-16, 5, -6, 8, 12, -4, -9,-17,-11, 3, 5, 8,-17, 0, + 11, -4,-13, -6, 2, -1, -1, 3, 3,-11,-12, -1, 1, 1, 12, -2 }, + { 8,-10,-33, -5, -3, -6, 1, -7, -8, -4, -6, -1, 5, -4, -6,-12, + -16, -8, 11, 8,-14, 7, 12, 11, 4,-14, -3, 6, -7, -5, -3, 3 }, + { 0, -8, -7, 2, -4, 24, 2, -9,-11, -3, -7, 11,-12, 17, 1, -1, + 3, -5, -7, 12, 4, 11, 0, 3, 2,-18, -3, 4, 7, -6, 3, 15 }, + { 10,-15,-16, -2, -4, -9, 7,-15, -6, 2,-16, 13, -8, 7, 19,-21, + -4,-12, -9, -3, -3, 6, 11, -3, -1,-19, 3, -7, -9, -4, 3, -6 }, + { -5,-10,-21, 0, -3, -7, 18,-21, 15, -5,-12, -4,-13, 2, 6, -9, + -9,-11, -4, 13, -3, 6, 4, -1, 7, -9, -4, 9, 5, 2, 6, 3 }, + { 15, -1,-27, -2, 10, 3, 7, -8, 9, -2, 7, 1, -2, -5, 18, 9, + -11,-17, -2, 7, -9, 11, 10, 0, -8, 6,-16, -3, 2, -7, 3, 11 }, + { 4, -9,-39, 19, 6,-13, 13, -5, -5,-15, -2, 9, 0, 4, 14, 6, + -10, -4, -5, 2, -4, -2, 5,-11, 3, 3, -2, -2, -7, 9, 7,-10 }, + { 5,-11, -8, 10, -2, 12, 16, 0, 12, -2, -6, 8, 14, 8, 7, 1, + 18,-30, 4, 10, -4, -6, 2,-11, 9,-10, -8, 5, 0, 0, -7, 6 }, + { -1,-16,-10, 11, 0, 13, 12, -4, -4, -5,-21, 12, 4, 13, 14, -7, + 6,-16,-13, 8, 2, 9, 15,-12, 1, -9,-22, 10, -9, 9, 9, -7 }, + { 4,-12,-27, 1, -2, 11, 15, 3, 14,-14, -9, 0, -9, 16, 22, 10, + 16,-10, 5, -5, -9, 1, 1, 6, 6, -4, 2,-17, -5, -6,-15, -1 }, + { 7,-12,-17, 1, -9, 5, 20, -7, 3, 23, -8, -8, -8, -1, 13, 17, + -7,-13, 4, -4, 7, 14, 8, 11, -3, -3, 4, 0, 4, 6, -1, -9 }, + { 7,-15,-15, -4, 10, 12, 3,-13, 6, 14, 9, -8,-15, 14, 23, -5, + -10, -5, 1, 15,-10, -7, 1, 9, 4,-13,-10, 10, 7, -3, 2, 3 }, + { 4,-10,-14, 0, 3, 4, 0, -9, -3, -4,-11, 2,-17, 8, 2, 15, + 6,-12,-12, 15, -5, 17, 18, 3, -3, -3, -4, -6, -8, 13, 4, 10 }, + { -2,-18,-26, 10, -4, 10, 13, 4, -4,-16, -7,-17, -3, 5, -4, 2, + -15,-10, -1, -8, -7, -3, 2, 2, 8,-10, -7, 2, 2, -4, 4, -1 }, + { 4,-19, -5, -1, -1, -6, 2, -8, 10,-16,-28, -6, 8, -1, 11, 28, + 2,-10, -4, 6, -6, 6, 11, 15, -4, -2, 7, 3, 7, -7, 4, 1 }, + { -3, -6,-10, -5, 13, 18, 10,-15, -5, -3,-13, 5, 1, 2, 18, -5, + -10,-10, -7, 4, 2, 1, 5, 4, 2, 5, 4, 8, -9,-17, 7, 7 }, + { 20,-12, -2, -4, 5, 14, 7,-11, -1,-16, -6, -4,-11, 17, 14, 0, + -8,-10, -8, 10, 3, 5, 10,-16, 3, -8,-14, 10, 3, 9, 0, 3 }, + { 12,-10,-36, 0, 7, 15, 2,-16, 2, -1, 0, -1, 5, 4, 5, -3, + 1,-10, 5, -1,-15, -3,-12, 12, 2, 5, -1, 5, 6, -3, -2, 2 }, + { 17,-15,-31, 23, -4, 15, -2, -3, 6, -7, -5, 1,-12, 4, 6, 8, + -10, 8, 3, 5, -4, 1, 5, 3, -1, -4, -3, 1, 10, -4, -2, -2 }, + { 6,-18, -5, 12, 10, 12, 14,-11, 15, 2, -9, -6, -5, -2, -9, 4, + -5,-28, -4, 14, 0,-16, 9, 14, -1, 3, -4, -4, 2, 1, 0, 4 }, + { -5,-14,-31, 8, 16, 7, 13,-13, 5, 6,-16, 10, -5, 2, -2, 2, + 14, -5, 8, -5, 7,-16, 6,-13, -5, 0, -5, 8, -3, -1, 4, 3 }, + { 1, -2, -1, 0, 6, 5, 2, -4, -3, -1, 0, 1, 4, 2, 43, 28, + -12,-35, -2, -2, -7, -1, 0, 2, -1, -2, -2, 1, -4, 0, -2, 3 }, + { 2, -9,-22, 12, 3, 3, -7, -4,-19,-22,-14, -4, -1, 21, 9, -3, + -15,-16,-13, 1,-11, 4, -9, 1, -7, -1, -1, 0, -2, 9,-13, -3 }, + { -1, -3,-23, 0, 2, 12, 3, -9, -4, 7, 3, 9,-10, 1, 27, 28, + 0, 9,-15, -2, -2, 1, 6, 8, -8, 7, -3, 20, 0, 0, -1, -6 }, + { -1, 11, 8, -2, 1, 5, -6, -1, 4, 2, -4, 0, -1, -5, 4, -6, + -10,-12, 19, 1, -7, 9, -8, -9,-16,-11, -2, 12, 14, 4, 4, 34 }, + { 17, 7, -6, 1, 4,-10, -5, 4,-11, 3,-18, 4, 14,-13, -3, 1, + 0, 0,-11, 0, 7,-17, -4, 4,-11, -6, -8, 18, 0, 0, 0, 26 }, + { -6, -7, -1, -1, 11, -8, 1, 3, 2, 11, -6, -6, 10, -3, 1, -3, + 7, 4,-12, -8, 0, -9, 8,-22, -5, 0, -6, 22, -2, 11,-13, 24 }, + { -3, 4, 0, 3, 9, 10, -1, 3, -9,-12, 1, -5, 18, 0, -3, 8, + 25, 15, -8, 2, 2, -2, 4, 8, 9, -1, -5, 10, -3, 1, -1, 23 }, + { -5, 2, -9, -1, -3, 0, 3, -1,-10, -4, 0,-13, 16, 9, -1,-14, + 2, 6, -2, -6, -5, -2, -7, 7, 5, 3, 11, -2,-14, 0, -9, 30 }, + { 4, 6, 6, 5, -3, -1, 4, 5, 10, 0, 5, -4, 7,-11, 14, 14, + 7, 34, -9, 0,-10, 22, -7, -1, 7, -9, 2, -8, 0, -7, -5, 29 }, + { -4, 3, -1, -4, -3, 5, 1, -4, 0, 2, 4, 2, 1, -1,-10, 1, + 6, -6, -4, 1, 4, -3, -3, -5, 0, 3, 7,-12, 0, -2,-10, 55 }, + { 5, 9, -1, 0, 4, 9,-21, -9, 4, 2, 6, -7, 11, -7, 1, -5, + 0, -4, 2, -3,-13, -8, 0, -9, -4, 2, 16, -2,-15, -7,-11, 31 }, + { 8, 2, -1, 0, 3, -5, -5, 5, 1, -1, -9, 1, 0, -6, -2, -1, + 5, 2, 0, 0, 12, 20,-19, 1, 8,-12,-11, 0, 6, -5, 2, 31 }, + { -1, -1, -2, 1, -1, 3, -9, -5, 8, -2, 5, -1, 0, -2, 4, -2, + -3,-12, 0, -2, 3, 0, 9, 4, -1, 21, -8, 3, -4, 9, -6, 30 }, + { -4, 0, -7, 17, 10,-12, -2,-10,-12, -3, 10, 0, 11, -4,-13, -3, + 5, 6, 10, 7, -8, 0, -7,-13, 1, 0, -2, 7,-12, 4, -3, 24 }, + {-13, 9, 4, -2, 2, -4,-14, -1, -3, -5,-10, 4, 13, -2, 5, 13, + 8, 3, -2, 1, 5, -6, 7,-18,-10, 1, -1, 5, 4, 1, 0, 25 }, + { -5, -1, 18, 12, 8, 8,-16, -1, 1, 1, 1, -4, -5, 3, 3, 4, + 4,-11,-12,-16, -6, 2, 12,-13, 0, 9, 7, 9, -9, 0,-10, 24 }, + { -4, 1, -3, 0, 2, -4, 4, 1, 5, 0, -3, 2, -3, -2, 2, -1, + 1, 4, -1, -2, -2, 1, -1, -1, -4, -1, -4, -2, -6, 6, 12, 69 }, + { 8, 5, 11, 0,-15, -4, 13, 6, 0, -4, 9, 1, -5, -3, 15, 0, + 1, 6, -5, 0, 1, 6, 5, 8, 0, 7, 1, -1, -4,-11, -9, 41 }, + { -4, -9, 32, -6, 0, 7, -4, 6, -6, 1, -6, -2, 4, -8, -5, -3, + -16, -1, -2, -6, 1, 15, 0, 21, 3, -3, -4, 3,-12, 16, 2, 27 }, + { -6, -5, 1, -9, -5, 3, 7, -3, 5, 5, 14, 13, 20, -7, -1, 12, + -1, 10,-11,-11, -7, -4,-14, 7,-14, 13, 22, 18, -1, 0, 14, 28 }, + { -8, 3, -2, 0, 5, 6, -1, -4, 1, 3, -7, 3, 1,-15, 4, -9, + 22,-10, -9, -4, 1, 8, -4, 9,-15, 2, -6, -4,-16, 12,-10, 23 }, + { 0, 0, 2, 0, -1, 3, -3, -1, 3, -5, 7, 1, 5, -5, -8, 1, + 13,-15, -5, -7, 12, -6, -2, 3, 10, -5, -8, 17, -5,-11,-14, 23 }, + { -7, -4, 6, -4, 5, -6, -5, 2, -4, 11, 9, -4, 2, -2, -4, 6, + 15, 3, -3, 18,-15, -2, -6, 3, 3,-20, 17, 11, -4, 2, 3, 29 }, + { 6, 1, -6, 2, 3, 0, 0, -3, 3, 3, -1, 3, -4, -6, -6, -7, + -3, -2, -7, -2, -4, 5, 3, -5,-20,-13, -4, 10,-14,-29, 14, 37 }, + { 3, 4, 3, -6, -4, 5, 0, 3, 2, 3, 0, -2, 4, 0, -3, -5, + -4, 4, -4, 4, 4, 3, 1, -4, -4, -9,-14, 20,-30, 3,-18, 33 }, + { 0, 2, 5, -2, -4, -2, -1, 2, -6, -3, -2, -2, 2, -5, -1, 4, + 3, 2, -3, 0, -1, -1,-10, -7, 2, -4,-18, 2,-37, -1, 12, 40 }, + { -7, 2, -1, 0, -2, 4, -8, 1, -4, 12, 7, 4, 15, -7, 1, -9, + 18, 0, 12,-17, -3, -1, 0, 0, 0, 2, -6, 0, -4, -3, -1, 26 }, + { -6, 4, 8, -5, -6, -2, 2, -1, 1, -1,-15, 8, 7, -1,-17, -4, + 1, 5, 6,-11, -6, 14, 17, -5,-15, 11, 8, 0, -3,-15, -6, 28 }, + { -1, 0, 0, 0, 1, 0, -1, 0, 1, 3, 2, -2, 3, -1, -1, 2, + 2, -1, -1, -7, 1, 2, -9, 0, -1, -4,-18, 7,-10, 49,-13, 32 }, + { -1, -3, 4, 1, 2, -5, 1, -7, -1, 5, -9, 4, 4, 25, 1, -1, + 2, -5, 2, -7, 17, -2, 10, -5, 0, 2,-15, 3, -9, 7, -9, 30 }, + { -5, -1, 0, 2, 1, -1, 2, 5,-33, 3, -5, 14, 11, 7, 5, -3, + 2, -8, -4, -2, -7, -6, 4, -8, -1, -8, 2, -2, -8, -1, -4, 27 }, + { -1, 0, -1, -2, 1, -1, -2, -1, 2, 0, 1, 2, 2, 4, 1, 3, + 4, 2, 1, -7, -4, 1, -3, -4,-35,-25, 17, 10, -3,-26, -7, 32 }, + { -5, 1, 6, -2, 6, 6, -9, 3, -1, -4, 5, -4, -2, -2, -9, 2, + -5, 2, 2, 4, 3, 5, -5,-16,-31,-12,-11, 2,-19, 20, -2, 21 }, + { -5, 2, 7, -7, -7, 5, -7, 2, 0, 0, -4, 3, -1, 0, -1, -2, + 0, -3, 5,-11, -8, -3, -7, -7, 28,-11, -7, 0,-16,-11, -4, 29 }, + { 2, 1, -3, -2, -1, 3, 4, 0, 1, 0, -1, -5, 4, -5,-12, 2, + -2, -5,-22, -2, -1, 11, 8, -7,-12, 0,-34, 6, -5, 11, -8, 19 }, + { -1, -3, 5, 11, 18, -2, -2, -5, -2, 4, -1, 8, 5, -6, 1, -1, + 2, 8, 4, -5, -8, -2, 5,-18, 7, 12, 7, 19,-18, 2, -6,-13 }, + { 9, 0, 0, 5, 4, 3, -6, 4, 1, -4, 5, -1, -4, 8, 8, 6, + -8, -6, 0, 6, -3, 3, 5, -3, 17, 31, 16, 10,-13, 0, -9,-19 }, + { 12,-10, 2, -2, -2, -1, -3, 6,-12, -5, -2, 14,-16, 4, 12, 12, + 17, 4, 7,-16, 7, -6, 11, 7, 7, 2,-25, 23,-24, 5, -7, -9 }, + { 10, 4, 13, 10, 10, 3, -6, 3, 3, 2, -1, -6, 8, 4, 10, 0, + 1, 2, -4, 2, -3, -8, 0, -1, 9, 9,-10, -3,-29, 1, -1,-27 }, + { 2, 2, 0, 7, 9, -2,-10, -1, -1, 1, -9, -5, 8, 4, 1, 2, + -10, 1, 13, 12, -3, 15, -9, 2, -7, 1,-10, 23,-20,-18, -9,-15 }, + { -3, -5, -1, 8, 0, -5, -1, 4, 7, -1, -7, 2, -8, -5, 11, 7, + -6, 3, -3, -9, 7, 9,-22, 1, 6, -4, 14, 27,-25,-14, 3, -5 }, + { 1, 3, 8, 4, 7, 6, 12,-17,-15, 1, -8,-10, 7,-14, -8, 6, + -2, -2,-11,-11, -7, 13, -2, -2, 4, 5, -5, 13,-23, -6,-17, -8 }, + { -5, 4,-14, -5, -4, -5, 6, 5, -8, -5, -2,-11, -7,-12, 3,-11, + 2, -6, 4,-10, -5, -7, 14, 5, 23, 11, 7, 12,-16, -6, -4,-16 }, + { 5, 6, 2, 5, -2, -5, -5, -6, -5,-19,-13, -1, -3,-13, 5, 0, + 6, -2, -2, -6, -7, -7, -1, -9, 4, 14, 17,-12,-27, 3, 0, -1 }, + { 7, -1, 9,-10, 8, 2, -7, -2, 5, 2, -3, -7, 3, 0, 6, 4, + 12, 5, 11, 14,-13, -1, 8, 1, 13, 9, 12, 12,-18,-14,-11,-16 }, + { -7, -5, -6, -5, 0, -1, -3, 2, 2, 1, 4, 9, 2, 3, 5, -2, + 2, 1, 8, 0, 3, 0, -2, 2, 1, 7, 29, 0,-36, -5, -9,-21 }, + { 14, -6, -9, 0, -1, -8, -8,-11, 2, 2, -9,-12, 12, -4, 5, 3, + -5, -9, 11, -1, -3, 12,-21, -3, 12, 5, 3, 11,-18,-15, 1, -2 }, + { -1, 3, -9, -3, 7, -7,-18, 2, 4, 12,-10, 2, 8, -3,-14, 13, + 17, -5, 5, -9, 13, -3, -7,-18, 17, -2, 5, 7,-20, -3, -6,-11 }, + { -3, 3, 3, -1, 1, -6, -5, 1, 5, -3,-14, -6, -5, -8, 14, -6, + 7, -1, 5, 1, 15, -1, -7, -4, 6,-11, 9, -2,-37, 16, -7, -3 }, + { -1, 0, 6, 1, -3, -9, 0, 11, -8, 2, -2, 0, 5, 2, 12,-10, + 10, 13, 2, 7, -6, 2,-10,-10, 21, -5, 5, 5,-12,-23, 3,-14 }, + { 6, 0, -2, 1, 0, 1, 0, -4, 1, 1, 8, -2, 2, -5, -2, 1, + 8, -4, -1, -1, 4, -1, 2, 6, 32, 1, -5,-20,-40, -4,-18,-14 }, + { 2, 2, -7, -2, 4, 4, -1, 2, 0, -2, -4, -7, 3, 5, 0, -5, + 1, 2, -6, 4, -1, -2, -1,-15, 8, 3, 9, 46, -7,-18, 6,-11 }, + { 5, 5, 16, 21, 3,-11, -4, 11,-12, 2, 4,-12, -1, 11, 8, 1, + -4, 11,-11,-21, 1, 1,-11, 3, 13, 1, 5, 12,-25, 1, -3, -2 }, + { 1, 6, -7, 4, 2, 3, 1, -5, 8, 9,-15, 3, -3,-14, 17, 4, + -8, 14, -2, -8, -4, 5, 8, -7, 8, 9, 7, 6,-29,-17, 8, 4 }, + { -7, -7, 4, 0, 13, 1, 0, 4, 4,-16,-10, -7, 5, 9,-15,-10, + -10, 8, -4, -1,-11, -1,-10,-15, 3, 3, 14, 10,-19, 2,-18,-12 }, + { -4, 0, 2, 0, 5, -2, -9, 0, 4, -4, 2, -1, -2, 2, -4, 9, + 2, -6, -4, -2, -1, -3, -3, -1, 2, 5, -1, 11,-24,-44, -9,-15 }, + { -1,-10, 6, 21, 11, 15, -7, 10,-14, -9, -8, -8, 4, 6, 19, 1, + -6, 1, -5,-17, -8,-10, 9, 5, 11, 18, -1, 10,-16, -7, -9, -8 }, + { 3, -5, 0, 0, -2, -2, -6, 4, -4, 1, -1, 0, 7, -3, 4, -4, + -7, 7, 17,-20, 6, 4, 1, -6,-12, 31, 13, 19,-14,-10, -7, -2 }, + { -2, 6,-10, 3, 9, 6,-14, 15, 2, -5, 2,-11, 9, -8, 4, 6, + 20,-15, -3, -3, -1, 32,-21, 6, 1, 9, 11, 17,-19, 6, -1, -3 }, + { 8, 10, -2, 0, -8,-16, 7, 7, 6, 10, 4,-14, 7, -6, 21, -7, + 10, 5, 5, 0, -7, 2, -6, 0, -7, 11, -9, 15,-20, -7,-11, 2 }, + { 0, -7, 5, 2, 0, -3, -6, -4, -2, -1, -4, -5,-13, -1, 27, -9, + -6,-11, -7, 1, 11, -4, -4,-14, -2, 11, 6, 10,-19, -6,-15, 2 }, + { 0, 7, -1, 2, -7,-15, -2, -3, 13, -5, -5, 12, 3, 0, 5, -5, + -22, 2, 7, 22, 13, 0, -1, 2, 3, 2, -7, 7,-27, -4, -4,-12 }, + { 11, 1,-16, 6,-15, 1, 3, 2, 0, 2, -3, 2, 5, -2, -5, 9, + 5, -3, 3, -2,-11, 3, 9, 6, 9, 3, -1, 12,-41, 8, -6, 9 }, + { 3, -7, 3, 2, 5, 5, 0, -1, 1, 3, -5, -2,-13, 7, -1, -2, + -2, -6, 4, -6, 0, 2, -2, 2, 4, 1, -4, 1,-47,-21, 7, -6 }, + { 3, 16, -7, 13, -4, -2, 10, -3, -1, 18,-13, 7,-13, -4, 8, 4, + 8, 9, -5, 13, 8, -5, 3, -6, 7, 18, -8, 10,-25, -3,-12,-12 }, + { 1, -1, -1, 0, 2, 5, -5, -3, 0, -5, -1, 0, -4, -8, -2, 3, + 2, -2,-17, -6, -4, 1, 33, -6,-20, -6, 8, 31,-26, -8, -1, -4 }, + { 3, -3, -3, 5, -3, -2, 1, 7, 0, 3, 6, 3, 6, -2, 9, 15, + -10, -3,-15, -5, -3, -4, -6,-30, 17, -8, -2, 2,-20, 0, -8, -2 }, + { -2, -1, -1, -1, 3, -5, -2, -3, 4, -2, 0, 5, 8, -3, 1, -4, + 1, 1, -3, 4, 4,-14, 3, 11, -5, 3, -3, 7, -3, 13, 23,-16 }, + { 2, -6, 1, -3, 5, 0, -6,-11, -7, -4, -1, 2, -7, -1, -1, 7, + 1, -2, 6, 12, -6, 8,-13, 17, 25,-23,-19, -7,-12, 9, 16,-17 }, + { 9, 4, 4, 4, -3, -1, 6, -2, -3, 0, 13, -4, -7, 14, 1, -7, + 0, -5, 3,-19, -3, 5, 3, 9, -1, 9,-13, 13,-17, 4, 21,-26 }, + { 0, -5, 0, 0, -4, -5, 2, -6, -4, 5, -7, 10, 0, 2, 0, -2, + -2, 0, 4, -6, 7, -2, 6, 5, -5, 2,-12, 1,-29, 29, 27, 12 }, + { 9,-10,-22, 6, -1, -1, 9,-14,-12, -2, 1, -1, 10,-11,-16, 0, + 3, 11, 13,-14, -9, -2, -1, 6, 4,-14, 0,-10, -2, 16, 17,-11 }, + { 2, 0, -1, -2, 4, 3, -6, -2, 1, -1, 1, 3, -4, 1, 3, -4, + -1, -1, 4, -1, 1, 0, 1, 6, -5, -7, 2, 1,-47, -3, 50,-17 }, + { 8, -4,-11, -7, 11, 11, 14, -7, 12, -7, 6, 2, 13, -6, -3, -2, + -14, 6, 6, 6, 0, 2, -1, 5,-20, 2, -1, 4, -5, 6, 21,-11 }, + { -2, -9, 3, 0, -6, 7, 8, -8, 1, -3, 4, 1, 5, -2, -3, -7, + 4, 7,-12, -9, -2, 10, -6, 13, 6, 5, 20, 2,-15, 9, 28, -7 }, + { 0, -5, -6, -6, -6, 1, -6, 6, -2, 4, 8, -3, 12, -1, -4, -2, + 6, 16,-14, 9,-14, -2, -8,-27, -3, 18, -1, -7, -3, 8, 23,-23 }, + { 1, 4, -9, -1, -5, 10, -2, 1,-11, 1, -9, 4, 7, 14, -9, -2, + -3, 2, -5, -1, -6,-10, -7, 11, 20, 2, 3,-19, 3, 15, 30, -9 }, + { 7, 2,-14, -4, 0, -2, 5, 2, 5, -2, 8, -3, -7, 6, 6,-11, + -14, 1, 10, -1, -7, -8, 1, 10, 3, -6,-15,-12,-17, 4, 30, -6 }, + { 4, 2, 1, -2, 3, 0, 1, 0, 2, 0, 1, 6, -7, 0, 3, 4, + 4, -4, -2, -5, -2, 2, -1, -2, 0, -2,-11, -7, -3, 42, 24,-14 }, + { 4, 1, 3, 2, 0, -2, -3, -2, 2, -1, 4, 11, -2, 2, 3, -4, + -5, 9, 2, -4, -9, 5, 8, -1, -7, 1, 24,-13,-28, 20, 15,-22 }, + { -3, 7, 6, 3, -2, -5,-10, -2, -2, -1, -6, -6, -2,-14,-16, -6, + -5, 0, 18, 0, 9, 1, 7,-13, -5, -6, -9, 11,-15, 9, 22,-11 }, + { 9, -2, 6, 5, 2, 9,-10, 1, 1, 5, -4, 12, 2, 2,-10, -7, + -4, -6, 7, 9, 6, 15, 6, 6,-10, 10, 5,-13, -5, 6, 24,-12 }, + { 1, 3, -3, -3, 8, 1, -6, 2, -5, -3, 7, 2, 14, 6, 9, -6, + -5, -4, 27, 7, -3, 8, -6, 3, -8, 8, 22, -5, -6, -2, 22,-17 }, + { -2, -2, 3, 10, 9, 9, 12,-15, -1,-11,-13, 3, -2, 1, -3,-11, + 7, 9, 16, -3,-10, -5, -5, 1, 8, -3, 9, 9, -5, 3, 31,-12 }, + { 7, -5, 10, -4, -8, 2, 16, -2, 10, 10, -3, -2, 3, -8, -3, 3, + -13, -6, 15, 20, -9, -3,-12, 1, -2,-16, 8, 8, -1, 16, 22, -5 }, + { 5, -3,-15, -2, 12, -8, 8, -5, 2, -8, 20,-18, 14, -4, 3, 3, + 7,-13,-16, 1,-10, 7, 16, 7, 4,-14, -4, -5, -9, 8, 23, -6 }, + { 5, -4, -5, -4, 1, 8, 4, -7, -5, 8, 10, 6, -6,-10, -2, 6, + 9,-17,-14, 11, 12, -3,-13, -7, 2, 18, 3,-25,-16, 18, 22, -5 }, + { 5, 6, -7,-20, -4, 2, 8, 4,-24, -4, 1, 4, -5, -2, 1,-10, + -2, 9, 3, -4, -3, -4, -4, -4, 10, 10, 3, 0, -6, 25, 21,-11 }, + { 0, 7, -1, 14, -6, -4,-10, 5, 4, 4, 4, -5, 3, 4, -1, -7, + 8,-19, 0, 6, 2, 3,-18, -3, -6, 2, 8, 14,-26, 22, 27,-13 }, + { -2, -6, 7, -5, 12, -7, 8, -1, 3, -2, 4, 1, 8, -2, 0, 14, + 6, -5, 6, -4, -7, 7,-21, 8, 1, 8, -9, -4, -3, 11, 25,-13 }, + { 4, 4, -1, -6, 4, 9, -8, 1, -3,-10, -2, 0, 15, -9,-16, 11, + 1, 1, 6, 3, -9, -5, 16, 26, 1,-14, 1, -3,-14, 7, 15, -9 }, + {-12, -2, -9,-13, 2, 6, 14, 0, 1, 0, -1,-13, 0, 10, -1, 6, + 9, -7, 8, 8, 19, 6, -1, 9, 10, -4, 1, -7,-22, -2, 29, -7 }, + { 2, 4, 13,-12, -8, -4, -5, 13, 12, -5, -3, -3, -4, 1, -1, 10, + 15, -6, -1,-11,-30, 4, 15, -1, 9, -7, 0, -2, -7, 10, 25,-16 }, + { 7,-15, -7, -7, -1, -5, -5,-11,-20, 10, 3,-10, -3, 5, 20, -4, + 0, -2, -2, 17, 2, 0, -3, 3, 6, 5, -1,-12, -3, 15, 22,-16 }, + { 4, -1, 3, 4, -5, 0, -1, -5,-24,-29, 4, -9, 1, -3, 0, 0, + 0, -4, 7, -4, -4, -4, 3, 1, -6, 5, -3, -5,-10, 3, 25,-10 }, + { -2, -1, -1, 4, 4, -1, 2, 0, -4, -4, 2, -1, -3, -1, -2, -2, + 1, -3, -5, -1, 2, -3, -4, -4, -3, 5, -9, 1,-11, 7, 46,-46 }, + { 0, -9, 3, 4, 4, 3, -5, -6, 5, -4, 4, -2, 1, 7, -4,-10, + 13, 1, 3, -6, 4, -4, 7, 2,-19,-25, -3,-16,-12, 16, 20, -1 }, + { 18, 6, 4,-12, 0,-14, 9, -6, -1, -4, -5, 2, 1, 12, 4, 2, + 7, 0, 2, 5,-11, -5, -2, 2, -4, 10, 0, -9, -7, 9, 25, -8 }, + { 5, 0, -6, 5, 6, 3, 3,-10, -5, 1, -1, 4, 3,-11, -8, 5, + 4, -5, 5, -5, -7, -5, 11, 5, 20, -8,-16, 21, -4, 27, 23, -5 } +}; + +/* FIR filter coefficients, they can be cut on half and maybe use float instead of double */ + +DECLARE_ALIGNED(16, const float, ff_dca_fir_32bands_perfect)[512] = { + +1.135985195E-010, + +7.018770981E-011, + -1.608403011E-008, + -5.083275667E-008, + -1.543309907E-007, + -3.961981463E-007, + -7.342250683E-007, + -3.970030775E-007, + -4.741137047E-007, + -6.022448247E-007, + -6.628192182E-007, + -6.982898526E-007, + -7.020648809E-007, + -6.767839409E-007, + -6.262345096E-007, + -5.564140224E-007, + +7.003467317E-007, + +8.419976893E-007, + +9.742954035E-007, + +1.085227950E-006, + +1.162929266E-006, + +1.194632091E-006, + +1.179182050E-006, + +1.033426656E-006, + +9.451737242E-007, + +1.975324267E-006, + +1.190443072E-006, + +5.234479659E-007, + +2.014677420E-007, + +7.834767501E-008, + -6.702406963E-010, + -1.613285505E-009, + -2.682709610E-009, + -3.399493131E-009, + +1.314406006E-008, + +7.506701927E-009, + +2.788728892E-008, + +1.444918922E-007, + +3.132386439E-007, + +1.399798180E-006, + +2.032118118E-006, + +2.715013807E-006, + +3.453840463E-006, + +4.195037945E-006, + +4.896494374E-006, + +5.516381407E-006, + +6.015239251E-006, + +6.361419310E-006, + +8.006985809E-006, + +8.087732567E-006, + +7.941360309E-006, + +7.568834008E-006, + +6.986399967E-006, + +6.225028756E-006, + +5.315936960E-006, + +4.429412002E-006, + +3.332600045E-006, + +8.427224429E-007, + +4.341498823E-007, + +9.458596395E-008, + +2.975164826E-008, + +6.402664354E-008, + -3.246264413E-008, + -3.809887872E-008, + +8.434094667E-008, + +6.437721822E-008, + +1.189317118E-006, + +2.497214155E-006, + +3.617151151E-006, + +3.157242645E-006, + +2.319611212E-006, + +7.869333785E-006, + +9.826449968E-006, + +1.177108606E-005, + +1.379448349E-005, + +1.571428584E-005, + +1.743183020E-005, + +1.884208177E-005, + +1.987093310E-005, + +2.042970118E-005, + -3.144468428E-005, + -3.334947178E-005, + -3.460439257E-005, + -3.515914432E-005, + -3.495384954E-005, + -3.397853652E-005, + -3.225446198E-005, + -2.978993689E-005, + -2.677291741E-005, + -1.806914770E-005, + -1.776598037E-005, + -1.661818715E-005, + -1.207003334E-005, + -6.993315310E-006, + -5.633860383E-007, + -9.984935332E-007, + -1.470520488E-006, + -1.853591357E-006, + +7.198007665E-007, + +3.086857760E-006, + +6.084746474E-006, + +9.561075785E-006, + +1.309637537E-005, + +2.263354872E-005, + +2.847247197E-005, + +3.415624451E-005, + +3.946387005E-005, + +4.425736552E-005, + +4.839275425E-005, + +5.176846025E-005, + +5.429694284E-005, + +5.595519906E-005, + +4.916387297E-006, + +9.299508747E-006, + +1.356193479E-005, + +1.751866148E-005, + +2.093936746E-005, + +2.362549276E-005, + +2.537086584E-005, + +2.618136386E-005, + +2.554462844E-005, + +3.018750249E-005, + +2.570833203E-005, + +1.985177369E-005, + +1.191342653E-005, + +2.525620175E-006, + -1.521241393E-005, + -1.617751332E-005, + +1.992636317E-005, + +1.774702469E-005, + +4.624524081E-005, + +5.610509834E-005, + +6.568001118E-005, + +7.513730816E-005, + +8.413690375E-005, + +8.757545584E-005, + +9.517164290E-005, + +1.020687996E-004, + +1.084438481E-004, + +1.140582463E-004, + +1.187910311E-004, + +1.224978914E-004, + +1.250260248E-004, + +1.262027217E-004, + +1.226499153E-004, + +1.213575742E-004, + +1.180980107E-004, + +1.126275165E-004, + +1.047207043E-004, + +9.417100227E-005, + +8.078388782E-005, + +6.447290798E-005, + +4.491530854E-005, + +2.470704203E-005, + -1.714242217E-006, + -3.193307566E-005, + -6.541742187E-005, + -1.024175072E-004, + -1.312203676E-004, + -1.774113771E-004, + -2.233728592E-004, + -2.682086197E-004, + -3.347633174E-004, + -3.906481725E-004, + -4.490280990E-004, + -5.099929986E-004, + -5.729619297E-004, + -6.358824321E-004, + -7.021900383E-004, + -7.698345580E-004, + -8.385353722E-004, + -9.078957955E-004, + -9.775133803E-004, + -1.046945457E-003, + -1.115717343E-003, + -1.183370827E-003, + -1.252829796E-003, + -1.316190348E-003, + -1.376571832E-003, + -1.433344092E-003, + -1.485876855E-003, + -1.533520175E-003, + -1.575609902E-003, + -1.611457788E-003, + -1.640390139E-003, + -1.661288203E-003, + -1.674512983E-003, + -1.678415807E-003, + -1.672798418E-003, + -1.656501088E-003, + -1.633993932E-003, + -1.593449386E-003, + +1.542080659E-003, + +1.479332102E-003, + +1.395521569E-003, + +1.303116791E-003, + +1.196175464E-003, + +1.073757303E-003, + +9.358961834E-004, + +7.817269652E-004, + +6.114174030E-004, + +4.244441516E-004, + +2.206075296E-004, + -2.719412748E-007, + -2.382978710E-004, + -4.935106263E-004, + -7.658848190E-004, + -1.055365428E-003, + -1.361547387E-003, + -1.684492454E-003, + -2.023874084E-003, + -2.379294252E-003, + -2.750317100E-003, + -3.136433195E-003, + -3.537061159E-003, + -3.951539751E-003, + -4.379155114E-003, + -4.819062538E-003, + -5.270531867E-003, + -5.732392892E-003, + -6.203945260E-003, + -6.683901884E-003, + -7.170005701E-003, + -7.664063945E-003, + -8.162760176E-003, + -8.665001951E-003, + -9.170533158E-003, + -9.676489048E-003, + -1.018219907E-002, + -1.068630442E-002, + -1.118756086E-002, + -1.168460958E-002, + -1.217562053E-002, + -1.265939046E-002, + -1.313448418E-002, + -1.359948888E-002, + -1.405300573E-002, + -1.449365262E-002, + -1.492007636E-002, + -1.533095632E-002, + -1.572482102E-002, + -1.610082202E-002, + -1.645756140E-002, + -1.679391414E-002, + -1.710879989E-002, + -1.740120351E-002, + -1.767017506E-002, + -1.791484281E-002, + -1.813439466E-002, + -1.832821220E-002, + -1.849545911E-002, + -1.863567345E-002, + -1.874836907E-002, + -1.883326657E-002, + -1.889026538E-002, + -1.891860925E-002, + +1.891860925E-002, + +1.889026538E-002, + +1.883326657E-002, + +1.874836907E-002, + +1.863567345E-002, + +1.849545911E-002, + +1.832821220E-002, + +1.813439466E-002, + +1.791484281E-002, + +1.767017506E-002, + +1.740120351E-002, + +1.710879989E-002, + +1.679391414E-002, + +1.645756140E-002, + +1.610082202E-002, + +1.572482102E-002, + +1.533095632E-002, + +1.492007636E-002, + +1.449365262E-002, + +1.405300573E-002, + +1.359948888E-002, + +1.313448418E-002, + +1.265939046E-002, + +1.217562053E-002, + +1.168460958E-002, + +1.118756086E-002, + +1.068630442E-002, + +1.018219907E-002, + +9.676489048E-003, + +9.170533158E-003, + +8.665001951E-003, + +8.162760176E-003, + +7.664063945E-003, + +7.170005701E-003, + +6.683901884E-003, + +6.203945260E-003, + +5.732392892E-003, + +5.270531867E-003, + +4.819062538E-003, + +4.379155114E-003, + +3.951539751E-003, + +3.537061159E-003, + +3.136433195E-003, + +2.750317100E-003, + +2.379294252E-003, + +2.023874084E-003, + +1.684492454E-003, + +1.361547387E-003, + +1.055365428E-003, + +7.658848190E-004, + +4.935106263E-004, + +2.382978710E-004, + +2.719412748E-007, + -2.206075296E-004, + -4.244441516E-004, + -6.114174030E-004, + -7.817269652E-004, + -9.358961834E-004, + -1.073757303E-003, + -1.196175464E-003, + -1.303116791E-003, + -1.395521569E-003, + -1.479332102E-003, + -1.542080659E-003, + +1.593449386E-003, + +1.633993932E-003, + +1.656501088E-003, + +1.672798418E-003, + +1.678415807E-003, + +1.674512983E-003, + +1.661288203E-003, + +1.640390139E-003, + +1.611457788E-003, + +1.575609902E-003, + +1.533520175E-003, + +1.485876855E-003, + +1.433344092E-003, + +1.376571832E-003, + +1.316190348E-003, + +1.252829796E-003, + +1.183370827E-003, + +1.115717343E-003, + +1.046945457E-003, + +9.775133803E-004, + +9.078957955E-004, + +8.385353722E-004, + +7.698345580E-004, + +7.021900383E-004, + +6.358824321E-004, + +5.729619297E-004, + +5.099929986E-004, + +4.490280990E-004, + +3.906481725E-004, + +3.347633174E-004, + +2.682086197E-004, + +2.233728592E-004, + +1.774113771E-004, + +1.312203676E-004, + +1.024175072E-004, + +6.541742187E-005, + +3.193307566E-005, + +1.714242217E-006, + -2.470704203E-005, + -4.491530854E-005, + -6.447290798E-005, + -8.078388782E-005, + -9.417100227E-005, + -1.047207043E-004, + -1.126275165E-004, + -1.180980107E-004, + -1.213575742E-004, + -1.226499153E-004, + -1.262027217E-004, + -1.250260248E-004, + -1.224978914E-004, + -1.187910311E-004, + -1.140582463E-004, + -1.084438481E-004, + -1.020687996E-004, + -9.517164290E-005, + -8.757545584E-005, + -8.413690375E-005, + -7.513730816E-005, + -6.568001118E-005, + -5.610509834E-005, + -4.624524081E-005, + -1.774702469E-005, + -1.992636317E-005, + +1.617751332E-005, + +1.521241393E-005, + -2.525620175E-006, + -1.191342653E-005, + -1.985177369E-005, + -2.570833203E-005, + -3.018750249E-005, + -2.554462844E-005, + -2.618136386E-005, + -2.537086584E-005, + -2.362549276E-005, + -2.093936746E-005, + -1.751866148E-005, + -1.356193479E-005, + -9.299508747E-006, + -4.916387297E-006, + -5.595519906E-005, + -5.429694284E-005, + -5.176846025E-005, + -4.839275425E-005, + -4.425736552E-005, + -3.946387005E-005, + -3.415624451E-005, + -2.847247197E-005, + -2.263354872E-005, + -1.309637537E-005, + -9.561075785E-006, + -6.084746474E-006, + -3.086857760E-006, + -7.198007665E-007, + +1.853591357E-006, + +1.470520488E-006, + +9.984935332E-007, + +5.633860383E-007, + +6.993315310E-006, + +1.207003334E-005, + +1.661818715E-005, + +1.776598037E-005, + +1.806914770E-005, + +2.677291741E-005, + +2.978993689E-005, + +3.225446198E-005, + +3.397853652E-005, + +3.495384954E-005, + +3.515914432E-005, + +3.460439257E-005, + +3.334947178E-005, + +3.144468428E-005, + -2.042970118E-005, + -1.987093310E-005, + -1.884208177E-005, + -1.743183020E-005, + -1.571428584E-005, + -1.379448349E-005, + -1.177108606E-005, + -9.826449968E-006, + -7.869333785E-006, + -2.319611212E-006, + -3.157242645E-006, + -3.617151151E-006, + -2.497214155E-006, + -1.189317118E-006, + -6.437721822E-008, + -8.434094667E-008, + +3.809887872E-008, + +3.246264413E-008, + -6.402664354E-008, + -2.975164826E-008, + -9.458596395E-008, + -4.341498823E-007, + -8.427224429E-007, + -3.332600045E-006, + -4.429412002E-006, + -5.315936960E-006, + -6.225028756E-006, + -6.986399967E-006, + -7.568834008E-006, + -7.941360309E-006, + -8.087732567E-006, + -8.006985809E-006, + -6.361419310E-006, + -6.015239251E-006, + -5.516381407E-006, + -4.896494374E-006, + -4.195037945E-006, + -3.453840463E-006, + -2.715013807E-006, + -2.032118118E-006, + -1.399798180E-006, + -3.132386439E-007, + -1.444918922E-007, + -2.788728892E-008, + -7.506701927E-009, + -1.314406006E-008, + +3.399493131E-009, + +2.682709610E-009, + +1.613285505E-009, + +6.702406963E-010, + -7.834767501E-008, + -2.014677420E-007, + -5.234479659E-007, + -1.190443072E-006, + -1.975324267E-006, + -9.451737242E-007, + -1.033426656E-006, + -1.179182050E-006, + -1.194632091E-006, + -1.162929266E-006, + -1.085227950E-006, + -9.742954035E-007, + -8.419976893E-007, + -7.003467317E-007, + +5.564140224E-007, + +6.262345096E-007, + +6.767839409E-007, + +7.020648809E-007, + +6.982898526E-007, + +6.628192182E-007, + +6.022448247E-007, + +4.741137047E-007, + +3.970030775E-007, + +7.342250683E-007, + +3.961981463E-007, + +1.543309907E-007, + +5.083275667E-008, + +1.608403011E-008, + -7.018770981E-011, + -1.135985195E-010 +}; + +DECLARE_ALIGNED(16, const float, ff_dca_fir_32bands_nonperfect)[512] = { + -1.390191784E-007, + -1.693738625E-007, + -2.030677564E-007, + -2.404238444E-007, + -2.818143514E-007, + -3.276689142E-007, + -3.784752209E-007, + -4.347855338E-007, + -4.972276315E-007, + -5.665120852E-007, + -6.434325428E-007, + -7.288739425E-007, + -8.238164355E-007, + -9.293416952E-007, + -1.046637067E-006, + -1.176999604E-006, + -1.321840614E-006, + -1.482681114E-006, + -1.661159786E-006, + -1.859034001E-006, + -2.078171747E-006, + -2.320550948E-006, + -2.588257530E-006, + -2.883470643E-006, + -3.208459020E-006, + -3.565570978E-006, + -3.957220997E-006, + -4.385879038E-006, + -4.854050530E-006, + -5.364252502E-006, + -5.918994248E-006, + -6.520755960E-006, + -7.171964626E-006, + -7.874960829E-006, + -8.631964192E-006, + -9.445050637E-006, + -1.031611009E-005, + -1.124680875E-005, + -1.223855270E-005, + -1.329243969E-005, + -1.440921824E-005, + -1.558924305E-005, + -1.683242772E-005, + -1.813820381E-005, + -1.950545993E-005, + -2.093250441E-005, + -2.241701623E-005, + -2.395598858E-005, + -2.554569073E-005, + -2.718161704E-005, + -2.885844333E-005, + -3.056998685E-005, + -3.230916263E-005, + -3.406793985E-005, + -3.583733633E-005, + -3.760734762E-005, + -3.936696885E-005, + -4.110412556E-005, + -4.280570283E-005, + -4.445751256E-005, + -4.604430433E-005, + -4.754976908E-005, + -4.895655002E-005, + -5.024627535E-005, + +5.139957648E-005, + +5.239612074E-005, + +5.321469871E-005, + +5.383323878E-005, + +5.422891263E-005, + +5.437819709E-005, + +5.425697600E-005, + +5.384063843E-005, + +5.310418419E-005, + +5.202236207E-005, + +5.056979353E-005, + +4.872112549E-005, + +4.645117951E-005, + +4.373511547E-005, + +4.054862075E-005, + +3.686808850E-005, + +3.267079956E-005, + +2.793515523E-005, + +2.264085742E-005, + +1.676913780E-005, + +1.030297699E-005, + +3.227306706E-006, + -4.470633485E-006, + -1.280130618E-005, + -2.177240640E-005, + -3.138873581E-005, + -4.165195787E-005, + -5.256036457E-005, + -6.410864444E-005, + -7.628766616E-005, + -8.908427117E-005, + -1.024810626E-004, + -1.164562127E-004, + -1.309833024E-004, + -1.460311323E-004, + -1.615635992E-004, + -1.775395358E-004, + -1.939126523E-004, + -2.106313768E-004, + -2.276388550E-004, + -2.448728774E-004, + -2.622658503E-004, + -2.797449124E-004, + -2.972317743E-004, + -3.146430245E-004, + -3.318900708E-004, + -3.488793736E-004, + -3.655125911E-004, + -3.816867538E-004, + -3.972945851E-004, + -4.122247046E-004, + -4.263620067E-004, + -4.395879805E-004, + -4.517810594E-004, + -4.628172028E-004, + -4.725702747E-004, + -4.809123348E-004, + -4.877146275E-004, + -4.928477574E-004, + -4.961824161E-004, + -4.975944757E-004, + -4.969481961E-004, + -4.941228544E-004, + -4.889960401E-004, + +4.814492422E-004, + +4.713678791E-004, + +4.586426076E-004, + +4.431701091E-004, + +4.248536134E-004, + +4.036037717E-004, + +3.793396754E-004, + +3.519894381E-004, + +3.214911267E-004, + +2.877934603E-004, + +2.508567995E-004, + +2.106537577E-004, + +1.671699720E-004, + +1.204049113E-004, + +7.037253090E-005, + +1.710198012E-005, + -3.936182839E-005, + -9.895755647E-005, + -1.616069785E-004, + -2.272142592E-004, + -2.956659591E-004, + -3.668301215E-004, + -4.405563814E-004, + -5.166754709E-004, + -5.949990009E-004, + -6.753197522E-004, + -7.574109477E-004, + -8.410271257E-004, + -9.259034996E-004, + -1.011756598E-003, + -1.098284614E-003, + -1.185167348E-003, + -1.272067428E-003, + -1.358630019E-003, + -1.444484224E-003, + -1.529243193E-003, + -1.612505526E-003, + -1.693855622E-003, + -1.772865304E-003, + -1.849094522E-003, + -1.922092517E-003, + -1.991399564E-003, + -2.056547208E-003, + -2.117061289E-003, + -2.172462177E-003, + -2.222266514E-003, + -2.265989315E-003, + -2.303145360E-003, + -2.333251061E-003, + -2.355825622E-003, + -2.370394068E-003, + -2.376487479E-003, + -2.373647178E-003, + -2.361423569E-003, + -2.339380793E-003, + -2.307097195E-003, + -2.264167881E-003, + -2.210205887E-003, + -2.144844970E-003, + -2.067740774E-003, + -1.978572691E-003, + -1.877046190E-003, + -1.762894331E-003, + -1.635878929E-003, + +1.495792647E-003, + +1.342460280E-003, + +1.175740734E-003, + +9.955273708E-004, + +8.017504588E-004, + +5.943773431E-004, + +3.734139318E-004, + +1.389056415E-004, + -1.090620208E-004, + -3.703625989E-004, + -6.448282511E-004, + -9.322494152E-004, + -1.232374110E-003, + -1.544908970E-003, + -1.869517611E-003, + -2.205822384E-003, + -2.553403843E-003, + -2.911801683E-003, + -3.280514618E-003, + -3.659002949E-003, + -4.046686925E-003, + -4.442950245E-003, + -4.847140983E-003, + -5.258570891E-003, + -5.676518660E-003, + -6.100233644E-003, + -6.528933067E-003, + -6.961807609E-003, + -7.398022339E-003, + -7.836719044E-003, + -8.277016692E-003, + -8.718019351E-003, + -9.158811532E-003, + -9.598465636E-003, + -1.003604382E-002, + -1.047059800E-002, + -1.090117730E-002, + -1.132682897E-002, + -1.174659748E-002, + -1.215953380E-002, + -1.256469358E-002, + -1.296114177E-002, + -1.334795821E-002, + -1.372423489E-002, + -1.408908330E-002, + -1.444163360E-002, + -1.478104480E-002, + -1.510649733E-002, + -1.541720331E-002, + -1.571240649E-002, + -1.599138230E-002, + -1.625344716E-002, + -1.649795473E-002, + -1.672429405E-002, + -1.693190821E-002, + -1.712027565E-002, + -1.728892699E-002, + -1.743743755E-002, + -1.756543480E-002, + -1.767260395E-002, + -1.775865816E-002, + -1.782339066E-002, + -1.786663756E-002, + -1.788828894E-002, + +1.788828894E-002, + +1.786663756E-002, + +1.782339066E-002, + +1.775865816E-002, + +1.767260395E-002, + +1.756543480E-002, + +1.743743755E-002, + +1.728892699E-002, + +1.712027565E-002, + +1.693190821E-002, + +1.672429405E-002, + +1.649795473E-002, + +1.625344716E-002, + +1.599138230E-002, + +1.571240649E-002, + +1.541720331E-002, + +1.510649733E-002, + +1.478104480E-002, + +1.444163360E-002, + +1.408908330E-002, + +1.372423489E-002, + +1.334795821E-002, + +1.296114177E-002, + +1.256469358E-002, + +1.215953380E-002, + +1.174659748E-002, + +1.132682897E-002, + +1.090117730E-002, + +1.047059800E-002, + +1.003604382E-002, + +9.598465636E-003, + +9.158811532E-003, + +8.718019351E-003, + +8.277016692E-003, + +7.836719044E-003, + +7.398022339E-003, + +6.961807609E-003, + +6.528933067E-003, + +6.100233644E-003, + +5.676518660E-003, + +5.258570891E-003, + +4.847140983E-003, + +4.442950245E-003, + +4.046686925E-003, + +3.659002949E-003, + +3.280514618E-003, + +2.911801683E-003, + +2.553403843E-003, + +2.205822384E-003, + +1.869517611E-003, + +1.544908970E-003, + +1.232374110E-003, + +9.322494152E-004, + +6.448282511E-004, + +3.703625989E-004, + +1.090620208E-004, + -1.389056415E-004, + -3.734139318E-004, + -5.943773431E-004, + -8.017504588E-004, + -9.955273708E-004, + -1.175740734E-003, + -1.342460280E-003, + -1.495792647E-003, + +1.635878929E-003, + +1.762894331E-003, + +1.877046190E-003, + +1.978572691E-003, + +2.067740774E-003, + +2.144844970E-003, + +2.210205887E-003, + +2.264167881E-003, + +2.307097195E-003, + +2.339380793E-003, + +2.361423569E-003, + +2.373647178E-003, + +2.376487479E-003, + +2.370394068E-003, + +2.355825622E-003, + +2.333251061E-003, + +2.303145360E-003, + +2.265989315E-003, + +2.222266514E-003, + +2.172462177E-003, + +2.117061289E-003, + +2.056547208E-003, + +1.991399564E-003, + +1.922092517E-003, + +1.849094522E-003, + +1.772865304E-003, + +1.693855622E-003, + +1.612505526E-003, + +1.529243193E-003, + +1.444484224E-003, + +1.358630019E-003, + +1.272067428E-003, + +1.185167348E-003, + +1.098284614E-003, + +1.011756598E-003, + +9.259034996E-004, + +8.410271257E-004, + +7.574109477E-004, + +6.753197522E-004, + +5.949990009E-004, + +5.166754709E-004, + +4.405563814E-004, + +3.668301215E-004, + +2.956659591E-004, + +2.272142592E-004, + +1.616069785E-004, + +9.895755647E-005, + +3.936182839E-005, + -1.710198012E-005, + -7.037253090E-005, + -1.204049113E-004, + -1.671699720E-004, + -2.106537577E-004, + -2.508567995E-004, + -2.877934603E-004, + -3.214911267E-004, + -3.519894381E-004, + -3.793396754E-004, + -4.036037717E-004, + -4.248536134E-004, + -4.431701091E-004, + -4.586426076E-004, + -4.713678791E-004, + -4.814492422E-004, + +4.889960401E-004, + +4.941228544E-004, + +4.969481961E-004, + +4.975944757E-004, + +4.961824161E-004, + +4.928477574E-004, + +4.877146275E-004, + +4.809123348E-004, + +4.725702747E-004, + +4.628172028E-004, + +4.517810594E-004, + +4.395879805E-004, + +4.263620067E-004, + +4.122247046E-004, + +3.972945851E-004, + +3.816867538E-004, + +3.655125911E-004, + +3.488793736E-004, + +3.318900708E-004, + +3.146430245E-004, + +2.972317743E-004, + +2.797449124E-004, + +2.622658503E-004, + +2.448728774E-004, + +2.276388550E-004, + +2.106313768E-004, + +1.939126523E-004, + +1.775395358E-004, + +1.615635992E-004, + +1.460311323E-004, + +1.309833024E-004, + +1.164562127E-004, + +1.024810626E-004, + +8.908427117E-005, + +7.628766616E-005, + +6.410864444E-005, + +5.256036457E-005, + +4.165195787E-005, + +3.138873581E-005, + +2.177240640E-005, + +1.280130618E-005, + +4.470633485E-006, + -3.227306706E-006, + -1.030297699E-005, + -1.676913780E-005, + -2.264085742E-005, + -2.793515523E-005, + -3.267079956E-005, + -3.686808850E-005, + -4.054862075E-005, + -4.373511547E-005, + -4.645117951E-005, + -4.872112549E-005, + -5.056979353E-005, + -5.202236207E-005, + -5.310418419E-005, + -5.384063843E-005, + -5.425697600E-005, + -5.437819709E-005, + -5.422891263E-005, + -5.383323878E-005, + -5.321469871E-005, + -5.239612074E-005, + -5.139957648E-005, + +5.024627535E-005, + +4.895655002E-005, + +4.754976908E-005, + +4.604430433E-005, + +4.445751256E-005, + +4.280570283E-005, + +4.110412556E-005, + +3.936696885E-005, + +3.760734762E-005, + +3.583733633E-005, + +3.406793985E-005, + +3.230916263E-005, + +3.056998685E-005, + +2.885844333E-005, + +2.718161704E-005, + +2.554569073E-005, + +2.395598858E-005, + +2.241701623E-005, + +2.093250441E-005, + +1.950545993E-005, + +1.813820381E-005, + +1.683242772E-005, + +1.558924305E-005, + +1.440921824E-005, + +1.329243969E-005, + +1.223855270E-005, + +1.124680875E-005, + +1.031611009E-005, + +9.445050637E-006, + +8.631964192E-006, + +7.874960829E-006, + +7.171964626E-006, + +6.520755960E-006, + +5.918994248E-006, + +5.364252502E-006, + +4.854050530E-006, + +4.385879038E-006, + +3.957220997E-006, + +3.565570978E-006, + +3.208459020E-006, + +2.883470643E-006, + +2.588257530E-006, + +2.320550948E-006, + +2.078171747E-006, + +1.859034001E-006, + +1.661159786E-006, + +1.482681114E-006, + +1.321840614E-006, + +1.176999604E-006, + +1.046637067E-006, + +9.293416952E-007, + +8.238164355E-007, + +7.288739425E-007, + +6.434325428E-007, + +5.665120852E-007, + +4.972276315E-007, + +4.347855338E-007, + +3.784752209E-007, + +3.276689142E-007, + +2.818143514E-007, + +2.404238444E-007, + +2.030677564E-007, + +1.693738625E-007, + +1.390191784E-007 +}; + +/* pre-scale lfe fir coefficients + * + * Permuted compared to table D.8 in the spec. First, the table in the + * spec has twice the number of coefficients, but they are reflected, + * T[i] = T[511 - i]. Furthermore, the indices are permuted, so that + * + * lfe_fir_64[8 * k + j] = T[64 * j + k] + * + * for 0 <= k < 32 and 0 <= j < 8. (This corresponds to adding a + * leading zero to the 8-bit index, and rotating it right by 3 bits + * as a 9-bit field). Values with j >= 4 can be reflected, as + * + * lfe_fir_64[8 * k + j] = T[64 * (7 - j) + (63 - k)] + * + * so all values in T get included. */ +#define SCALE(c) ((c) / (256.0f * 32768.0f)) +DECLARE_ALIGNED(16, const float, ff_dca_lfe_fir_64)[256] = { + SCALE(2.658434386830777e-4), SCALE(9.029330685734748e-3), + SCALE(7.939263433218002e-2), SCALE(2.425158768892288e-1), + SCALE(3.430179357528686e-1), SCALE(2.398228943347931e-1), + SCALE(7.746443897485733e-2), SCALE(8.622321300208569e-3), + SCALE(8.179365249816328e-5), SCALE(9.450953453779220e-3), + SCALE(8.134882897138596e-2), SCALE(2.451938837766648e-1), + SCALE(3.429597318172455e-1), SCALE(2.371159791946411e-1), + SCALE(7.556436210870743e-2), SCALE(8.229630999267101e-3), + SCALE(9.439323912374676e-5), SCALE(9.887560270726680e-3), + SCALE(8.333285897970200e-2), SCALE(2.478559017181396e-1), + SCALE(3.428434133529663e-1), SCALE(2.343961596488952e-1), + SCALE(7.369252294301987e-2), SCALE(7.850865833461285e-3), + SCALE(1.082170274457894e-4), SCALE(1.033949479460716e-2), + SCALE(8.534456789493561e-2), SCALE(2.505008876323700e-1), + SCALE(3.426689505577088e-1), SCALE(2.316644787788391e-1), + SCALE(7.184901088476181e-2), SCALE(7.485736627131701e-3), + SCALE(1.233371440321207e-4), SCALE(1.080708485096693e-2), + SCALE(8.738376945257187e-2), SCALE(2.531278133392334e-1), + SCALE(3.424364924430847e-1), SCALE(2.289219647645950e-1), + SCALE(7.003392279148102e-2), SCALE(7.133882027119398e-3), + SCALE(1.397485757479444e-4), SCALE(1.129068247973919e-2), + SCALE(8.945026248693466e-2), SCALE(2.557355761528015e-1), + SCALE(3.421461284160614e-1), SCALE(2.261696159839630e-1), + SCALE(6.824731826782227e-2), SCALE(6.794991903007030e-3), + SCALE(1.575958012836054e-4), SCALE(1.179065089672804e-2), + SCALE(9.154383838176728e-2), SCALE(2.583232223987580e-1), + SCALE(3.417979776859284e-1), SCALE(2.234084606170654e-1), + SCALE(6.648923456668854e-2), SCALE(6.468691397458315e-3), + SCALE(1.769922382663936e-4), SCALE(1.230732165277004e-2), + SCALE(9.366425126791000e-2), SCALE(2.608896791934967e-1), + SCALE(3.413922190666198e-1), SCALE(2.206395119428635e-1), + SCALE(6.475970894098282e-2), SCALE(6.154712289571762e-3), + SCALE(1.981738605536520e-4), SCALE(1.284105982631445e-2), + SCALE(9.581124037504196e-2), SCALE(2.634339034557342e-1), + SCALE(3.409290313720703e-1), SCALE(2.178637981414795e-1), + SCALE(6.305878609418869e-2), SCALE(5.852684378623962e-3), + SCALE(2.211847313446924e-4), SCALE(1.339218579232693e-2), + SCALE(9.798453748226166e-2), SCALE(2.659549415111542e-1), + SCALE(3.404086530208588e-1), SCALE(2.150822728872299e-1), + SCALE(6.138643622398376e-2), SCALE(5.562345497310162e-3), + SCALE(2.460231189616024e-4), SCALE(1.396108977496624e-2), + SCALE(1.001838669180870e-1), SCALE(2.684516608715058e-1), + SCALE(3.398312926292420e-1), SCALE(2.122959494590759e-1), + SCALE(5.974265560507774e-2), SCALE(5.283284001052380e-3), + SCALE(2.726115926634520e-4), SCALE(1.454808749258518e-2), + SCALE(1.024089083075523e-1), SCALE(2.709231376647949e-1), + SCALE(3.391972482204438e-1), SCALE(2.095058411359787e-1), + SCALE(5.812742188572884e-2), SCALE(5.015311297029257e-3), + SCALE(3.013863170053810e-4), SCALE(1.515355054289102e-2), + SCALE(1.046593263745308e-1), SCALE(2.733682692050934e-1), + SCALE(3.385068178176880e-1), SCALE(2.067128717899322e-1), + SCALE(5.654069408774376e-2), SCALE(4.758012015372515e-3), + SCALE(3.328395541757345e-4), SCALE(1.577781140804291e-2), + SCALE(1.069347932934761e-1), SCALE(2.757860720157624e-1), + SCALE(3.377602994441986e-1), SCALE(2.039180546998978e-1), + SCALE(5.498242005705833e-2), SCALE(4.511159844696522e-3), + SCALE(3.658991190604866e-4), SCALE(1.642123050987720e-2), + SCALE(1.092349365353584e-1), SCALE(2.781755328178406e-1), + SCALE(3.369580209255218e-1), SCALE(2.011223286390304e-1), + SCALE(5.345252528786659e-2), SCALE(4.274417180567980e-3), + SCALE(4.018281470052898e-4), SCALE(1.708412915468216e-2), + SCALE(1.115593686699867e-1), SCALE(2.805356979370117e-1), + SCALE(3.361004292964936e-1), SCALE(1.983266174793244e-1), + SCALE(5.195093154907227e-2), SCALE(4.047499038279056e-3), + SCALE(4.401875485200435e-4), SCALE(1.776690222322941e-2), + SCALE(1.139076948165894e-1), SCALE(2.828655838966370e-1), + SCALE(3.351879119873047e-1), SCALE(1.955319195985794e-1), + SCALE(5.047753453254700e-2), SCALE(3.830091329291463e-3), + SCALE(4.812776169274002e-4), SCALE(1.846982724964619e-2), + SCALE(1.162794977426529e-1), SCALE(2.851640880107880e-1), + SCALE(3.342207968235016e-1), SCALE(1.927391141653061e-1), + SCALE(4.903224110603333e-2), SCALE(3.621967276558280e-3), + SCALE(5.252459668554366e-4), SCALE(1.919330470263958e-2), + SCALE(1.186743453145027e-1), SCALE(2.874303460121155e-1), + SCALE(3.331996202468872e-1), SCALE(1.899491697549820e-1), + SCALE(4.761491715908051e-2), SCALE(3.422776935622096e-3), + SCALE(5.721592460758984e-4), SCALE(1.993762329220772e-2), + SCALE(1.210917681455612e-1), SCALE(2.896633744239807e-1), + SCALE(3.321248590946198e-1), SCALE(1.871629506349564e-1), + SCALE(4.622544348239899e-2), SCALE(3.232272574678064e-3), + SCALE(6.222130032256246e-4), SCALE(2.070316113531590e-2), + SCALE(1.235313042998314e-1), SCALE(2.918621897697448e-1), + SCALE(3.309969604015350e-1), SCALE(1.843813359737396e-1), + SCALE(4.486365616321564e-2), SCALE(3.050152910873294e-3), + SCALE(6.755515350960195e-4), SCALE(2.149021252989769e-2), + SCALE(1.259924471378326e-1), SCALE(2.940258979797364e-1), + SCALE(3.298164308071136e-1), SCALE(1.816052496433258e-1), + SCALE(4.352942481637001e-2), SCALE(2.876190468668938e-3), + SCALE(7.324148900806904e-4), SCALE(2.229913882911205e-2), + SCALE(1.284746825695038e-1), SCALE(2.961534857749939e-1), + SCALE(3.285838961601258e-1), SCALE(1.788355410099030e-1), + SCALE(4.222255200147629e-2), SCALE(2.710093278437853e-3), + SCALE(7.928516715764999e-4), SCALE(2.313023805618286e-2), + SCALE(1.309774816036224e-1), SCALE(2.982441186904907e-1), + SCALE(3.272998929023742e-1), SCALE(1.760730892419815e-1), + SCALE(4.094288870692253e-2), SCALE(2.551567042246461e-3), + SCALE(8.570110658183694e-4), SCALE(2.398385666310787e-2), + SCALE(1.335003077983856e-1), SCALE(3.002967536449432e-1), + SCALE(3.259649574756622e-1), SCALE(1.733186990022659e-1), + SCALE(3.969023004174232e-2), SCALE(2.400433411821723e-3), + SCALE(9.251192095689476e-4), SCALE(2.486028522253036e-2), + SCALE(1.360425949096680e-1), SCALE(3.023106753826142e-1), + SCALE(3.245797157287598e-1), SCALE(1.705732345581055e-1), + SCALE(3.846437484025955e-2), SCALE(2.256359672173858e-3), + SCALE(9.974770946428180e-4), SCALE(2.575986087322235e-2), + SCALE(1.386037617921829e-1), SCALE(3.042849004268646e-1), + SCALE(3.231448531150818e-1), SCALE(1.678375005722046e-1), + SCALE(3.726511076092720e-2), SCALE(2.119151875376701e-3), + SCALE(1.073930296115577e-3), SCALE(2.668286114931106e-2), + SCALE(1.411831974983215e-1), SCALE(3.062185347080230e-1), + SCALE(3.216609656810760e-1), SCALE(1.651122719049454e-1), + SCALE(3.609224036335945e-2), SCALE(1.988604199141264e-3), + SCALE(1.155023579485714e-3), SCALE(2.762960828840732e-2), + SCALE(1.437802612781525e-1), SCALE(3.081108033657074e-1), + SCALE(3.201287388801574e-1), SCALE(1.623983532190323e-1), + SCALE(3.494550660252571e-2), SCALE(1.864377525635064e-3), + SCALE(1.240676851011813e-3), SCALE(2.860039286315441e-2), + SCALE(1.463943719863892e-1), SCALE(3.099608123302460e-1), + SCALE(3.185488879680634e-1), SCALE(1.596965193748474e-1), + SCALE(3.382468968629837e-2), SCALE(1.746327499859035e-3), + SCALE(1.331258914433420e-3), SCALE(2.959549613296986e-2), + SCALE(1.490248143672943e-1), SCALE(3.117676973342896e-1), + SCALE(3.169221282005310e-1), SCALE(1.570075154304504e-1), + SCALE(3.272953629493714e-2), SCALE(1.634211512282491e-3), + SCALE(1.426893868483603e-3), SCALE(3.061520494520664e-2), + SCALE(1.516709625720978e-1), SCALE(3.135308027267456e-1), + SCALE(3.152491748332978e-1), SCALE(1.543320864439010e-1), + SCALE(3.165979683399200e-2), SCALE(1.527829794213176e-3), +}; + +/* Permuted compared to table D.8 in the spec. First, the table in the + * spec has twice the number of coefficients, but they are reflected, + * T[i] = T[511 - i]. Furthermore, the indices are permuted, so that + * + * lfe_fir_128[4 * k + j] = T[128 * j + k] + * + * for 0 <= k < 64 and 0 <= j < 4. Values with j >= 2 can be + * reflected, as + * + * lfe_fir_128[4 * k + j] = T[128 * (3 - j) + (127 - k)] + * + * so all values in T get included. */ +DECLARE_ALIGNED(16, const float, ff_dca_lfe_fir_128)[256] = { + SCALE(0.00053168571), SCALE(0.15878495574), SCALE(0.68603444099), SCALE(0.15492856503), + SCALE(0.00016358691), SCALE(0.16269733012), SCALE(0.68591803312), SCALE(0.15112841129), + SCALE(0.00018878609), SCALE(0.16666537523), SCALE(0.68568539619), SCALE(0.14738474786), + SCALE(0.00021643363), SCALE(0.17068879306), SCALE(0.68533653021), SCALE(0.14369773865), + SCALE(0.00024667382), SCALE(0.17476719618), SCALE(0.68487155437), SCALE(0.14006754756), + SCALE(0.00027949660), SCALE(0.17890018225), SCALE(0.68429082632), SCALE(0.13649433851), + SCALE(0.00031519096), SCALE(0.18308731914), SCALE(0.68359452486), SCALE(0.13297818601), + SCALE(0.00035398375), SCALE(0.18732811511), SCALE(0.68278300762), SCALE(0.12951917946), + SCALE(0.00039634691), SCALE(0.19162209332), SCALE(0.68185669184), SCALE(0.12611730397), + SCALE(0.00044236859), SCALE(0.19596865773), SCALE(0.68081587553), SCALE(0.12277261168), + SCALE(0.00049204525), SCALE(0.20036731660), SCALE(0.67966115475), SCALE(0.11948505789), + SCALE(0.00054522208), SCALE(0.20481738448), SCALE(0.67839306593), SCALE(0.11625462025), + SCALE(0.00060277141), SCALE(0.20931822062), SCALE(0.67701220512), SCALE(0.11308115721), + SCALE(0.00066567765), SCALE(0.21386915445), SCALE(0.67551922798), SCALE(0.10996460915), + SCALE(0.00073179678), SCALE(0.21846942604), SCALE(0.67391467094), SCALE(0.10690483451), + SCALE(0.00080365466), SCALE(0.22311829031), SCALE(0.67219948769), SCALE(0.10390164703), + SCALE(0.00088037323), SCALE(0.22781492770), SCALE(0.67037439346), SCALE(0.10095486045), + SCALE(0.00096255314), SCALE(0.23255851865), SCALE(0.66844022274), SCALE(0.09806428105), + SCALE(0.00105048984), SCALE(0.23734821379), SCALE(0.66639786959), SCALE(0.09522963315), + SCALE(0.00114431616), SCALE(0.24218304455), SCALE(0.66424828768), SCALE(0.09245070815), + SCALE(0.00124442333), SCALE(0.24706205726), SCALE(0.66199249029), SCALE(0.08972713351), + SCALE(0.00135110028), SCALE(0.25198432803), SCALE(0.65963155031), SCALE(0.08705867827), + SCALE(0.00146482687), SCALE(0.25694879889), SCALE(0.65716648102), SCALE(0.08444493264), + SCALE(0.00158570008), SCALE(0.26195442677), SCALE(0.65459835529), SCALE(0.08188561350), + SCALE(0.00171401864), SCALE(0.26700007915), SCALE(0.65192854404), SCALE(0.07938029617), + SCALE(0.00185023469), SCALE(0.27208462358), SCALE(0.64915806055), SCALE(0.07692859322), + SCALE(0.00199495023), SCALE(0.27720692754), SCALE(0.64628833532), SCALE(0.07453006506), + SCALE(0.00214785640), SCALE(0.28236576915), SCALE(0.64332056046), SCALE(0.07218432426), + SCALE(0.00231004250), SCALE(0.28755992651), SCALE(0.64025616646), SCALE(0.06989086419), + SCALE(0.00248134881), SCALE(0.29278811812), SCALE(0.63709646463), SCALE(0.06764923781), + SCALE(0.00266251224), SCALE(0.29804900289), SCALE(0.63384294510), SCALE(0.06545893103), + SCALE(0.00285378192), SCALE(0.30334126949), SCALE(0.63049703836), SCALE(0.06331945211), + SCALE(0.00305565330), SCALE(0.30866351724), SCALE(0.62706029415), SCALE(0.06123027951), + SCALE(0.00326841651), SCALE(0.31401440501), SCALE(0.62353414297), SCALE(0.05919086933), + SCALE(0.00349264755), SCALE(0.31939238310), SCALE(0.61992025375), SCALE(0.05720067024), + SCALE(0.00372874714), SCALE(0.32479602098), SCALE(0.61622029543), SCALE(0.05525910854), + SCALE(0.00397720048), SCALE(0.33022382855), SCALE(0.61243581772), SCALE(0.05336561054), + SCALE(0.00423829490), SCALE(0.33567428589), SCALE(0.60856848955), SCALE(0.05151961371), + SCALE(0.00451271003), SCALE(0.34114575386), SCALE(0.60462015867), SCALE(0.04972046614), + SCALE(0.00480085658), SCALE(0.34663668275), SCALE(0.60059231520), SCALE(0.04796761274), + SCALE(0.00510312291), SCALE(0.35214546323), SCALE(0.59648692608), SCALE(0.04626038298), + SCALE(0.00542017492), SCALE(0.35767036676), SCALE(0.59230577946), SCALE(0.04459818453), + SCALE(0.00575236930), SCALE(0.36320972443), SCALE(0.58805054426), SCALE(0.04298033938), + SCALE(0.00610029325), SCALE(0.36876192689), SCALE(0.58372318745), SCALE(0.04140623659), + SCALE(0.00646453211), SCALE(0.37432509661), SCALE(0.57932555676), SCALE(0.03987516090), + SCALE(0.00684553990), SCALE(0.37989753485), SCALE(0.57485944033), SCALE(0.03838652745), + SCALE(0.00724391919), SCALE(0.38547745347), SCALE(0.57032698393), SCALE(0.03693958372), + SCALE(0.00766016589), SCALE(0.39106300473), SCALE(0.56572991610), SCALE(0.03553372994), + SCALE(0.00809498038), SCALE(0.39665243030), SCALE(0.56107026339), SCALE(0.03416819125), + SCALE(0.00854881573), SCALE(0.40224379301), SCALE(0.55634999275), SCALE(0.03284239396), + SCALE(0.00902230106), SCALE(0.40783521533), SCALE(0.55157101154), SCALE(0.03155555204), + SCALE(0.00951600447), SCALE(0.41342487931), SCALE(0.54673534632), SCALE(0.03030703776), + SCALE(0.01003060210), SCALE(0.41901078820), SCALE(0.54184508324), SCALE(0.02909611352), + SCALE(0.01056654565), SCALE(0.42459106445), SCALE(0.53690224886), SCALE(0.02792212367), + SCALE(0.01112466771), SCALE(0.43016362190), SCALE(0.53190881014), SCALE(0.02678431384), + SCALE(0.01170534454), SCALE(0.43572667241), SCALE(0.52686679363), SCALE(0.02568206564), + SCALE(0.01230939943), SCALE(0.44127810001), SCALE(0.52177828550), SCALE(0.02461459488), + SCALE(0.01293735672), SCALE(0.44681602716), SCALE(0.51664537191), SCALE(0.02358125709), + SCALE(0.01358995494), SCALE(0.45233830810), SCALE(0.51147013903), SCALE(0.02258131653), + SCALE(0.01426773332), SCALE(0.45784294605), SCALE(0.50625455379), SCALE(0.02161412500), + SCALE(0.01497144438), SCALE(0.46332800388), SCALE(0.50100076199), SCALE(0.02067894675), + SCALE(0.01570170000), SCALE(0.46879136562), SCALE(0.49571081996), SCALE(0.01977507770), + SCALE(0.01645922661), SCALE(0.47423094511), SCALE(0.49038675427), SCALE(0.01890186779), + SCALE(0.01724460535), SCALE(0.47964480519), SCALE(0.48503074050), SCALE(0.01805862412), +}; +#undef SCALE + + +#define SCALE(c) ((float)(c) / (256.0f * 32768.0f * 8388608.0f)) +DECLARE_ALIGNED(16, const float, ff_dca_lfe_xll_fir_64)[256] = { + SCALE( 6103), SCALE( 52170), SCALE(-558064), SCALE(1592440), + SCALE(6290049), SCALE(1502534), SCALE(-546669), SCALE( 53047), + SCALE( 1930), SCALE( 51089), SCALE(-568920), SCALE(1683709), + SCALE(6286575), SCALE(1414057), SCALE(-534782), SCALE( 53729), + SCALE( 2228), SCALE( 49794), SCALE(-579194), SCALE(1776276), + SCALE(6279634), SCALE(1327070), SCALE(-522445), SCALE( 54228), + SCALE( 2552), SCALE( 48275), SCALE(-588839), SCALE(1870070), + SCALE(6269231), SCALE(1241632), SCALE(-509702), SCALE( 54550), + SCALE( 2904), SCALE( 46523), SCALE(-597808), SCALE(1965017), + SCALE(6255380), SCALE(1157798), SCALE(-496595), SCALE( 54708), + SCALE( 3287), SCALE( 44529), SCALE(-606054), SCALE(2061044), + SCALE(6238099), SCALE(1075621), SCALE(-483164), SCALE( 54710), + SCALE( 3704), SCALE( 42282), SCALE(-613529), SCALE(2158071), + SCALE(6217408), SCALE( 995149), SCALE(-469451), SCALE( 54566), + SCALE( 4152), SCALE( 39774), SCALE(-620186), SCALE(2256019), + SCALE(6193332), SCALE( 916430), SCALE(-455494), SCALE( 54285), + SCALE( 4631), SCALE( 36995), SCALE(-625976), SCALE(2354805), + SCALE(6165900), SCALE( 839507), SCALE(-441330), SCALE( 53876), + SCALE( 5139), SCALE( 33937), SCALE(-630850), SCALE(2454343), + SCALE(6135146), SCALE( 764419), SCALE(-426998), SCALE( 53348), + SCALE( 5682), SCALE( 30591), SCALE(-634759), SCALE(2554547), + SCALE(6101107), SCALE( 691203), SCALE(-412531), SCALE( 52711), + SCALE( 6264), SCALE( 26948), SCALE(-637655), SCALE(2655326), + SCALE(6063824), SCALE( 619894), SCALE(-397966), SCALE( 51972), + SCALE( 6886), SCALE( 23001), SCALE(-639488), SCALE(2756591), + SCALE(6023343), SCALE( 550521), SCALE(-383335), SCALE( 51140), + SCALE( 7531), SCALE( 18741), SCALE(-640210), SCALE(2858248), + SCALE(5979711), SCALE( 483113), SCALE(-368671), SCALE( 50224), + SCALE( 8230), SCALE( 14162), SCALE(-639772), SCALE(2960201), + SCALE(5932981), SCALE( 417692), SCALE(-354003), SCALE( 49231), + SCALE( 8959), SCALE( 9257), SCALE(-638125), SCALE(3062355), + SCALE(5883210), SCALE( 354281), SCALE(-339362), SCALE( 48168), + SCALE( 9727), SCALE( 4018), SCALE(-635222), SCALE(3164612), + SCALE(5830457), SCALE( 292897), SCALE(-324777), SCALE( 47044), + SCALE( 10535), SCALE( -1558), SCALE(-631014), SCALE(3266872), + SCALE(5774785), SCALE( 233555), SCALE(-310273), SCALE( 45866), + SCALE( 11381), SCALE( -7480), SCALE(-625455), SCALE(3369035), + SCALE(5716260), SCALE( 176267), SCALE(-295877), SCALE( 44640), + SCALE( 12267), SCALE( -13750), SCALE(-618499), SCALE(3471000), + SCALE(5654952), SCALE( 121042), SCALE(-281613), SCALE( 43373), + SCALE( 13190), SCALE( -20372), SCALE(-610098), SCALE(3572664), + SCALE(5590933), SCALE( 67886), SCALE(-267505), SCALE( 42072), + SCALE( 14152), SCALE( -27352), SCALE(-600209), SCALE(3673924), + SCALE(5524280), SCALE( 16800), SCALE(-253574), SCALE( 40743), + SCALE( 15153), SCALE( -34691), SCALE(-588788), SCALE(3774676), + SCALE(5455069), SCALE( -32214), SCALE(-239840), SCALE( 39391), + SCALE( 16192), SCALE( -42390), SCALE(-575791), SCALE(3874816), + SCALE(5383383), SCALE( -79159), SCALE(-226323), SCALE( 38022), + SCALE( 17267), SCALE( -50453), SCALE(-561178), SCALE(3974239), + SCALE(5309305), SCALE(-124041), SCALE(-213041), SCALE( 36642), + SCALE( 18377), SCALE( -58879), SCALE(-544906), SCALE(4072841), + SCALE(5232922), SCALE(-166869), SCALE(-200010), SCALE( 35256), + SCALE( 19525), SCALE( -67667), SCALE(-526937), SCALE(4170517), + SCALE(5154321), SCALE(-207653), SCALE(-187246), SCALE( 33866), + SCALE( 20704), SCALE( -76817), SCALE(-507233), SCALE(4267162), + SCALE(5073593), SCALE(-246406), SCALE(-174764), SCALE( 32480), + SCALE( 21915), SCALE( -86327), SCALE(-485757), SCALE(4362672), + SCALE(4990831), SCALE(-283146), SCALE(-162575), SCALE( 31101), + SCALE( 23157), SCALE( -96193), SCALE(-462476), SCALE(4456942), + SCALE(4906129), SCALE(-317890), SCALE(-150692), SCALE( 29732), + SCALE( 24426), SCALE(-106412), SCALE(-437356), SCALE(4549871), + SCALE(4819584), SCALE(-350658), SCALE(-139125), SCALE( 28376), + SCALE( 25721), SCALE(-116977), SCALE(-410365), SCALE(4641355), + SCALE(4731293), SCALE(-381475), SCALE(-127884), SCALE( 27038), +}; +#undef SCALE + +DECLARE_ALIGNED(16, const float, ff_dca_fir_64bands)[1024] = { + /* Bank 0 */ + -7.1279389866041690e-8, -7.0950903150874990e-8, + -7.9525034321375090e-8, -8.9326871281374790e-8, + -9.7483190494874640e-8, -1.0586659510721950e-7, + -1.1527363411865760e-7, -1.2523109645615350e-7, + -1.3555636137971380e-7, -1.4640931821191640e-7, + -1.5787424998123710e-7, -1.6994592926571220e-7, + -1.8264184311018150e-7, -1.9600594587757850e-7, + -2.1007899706006800e-7, -2.2489759047553620e-7, + -2.4050245877923400e-7, -2.5693874615777660e-7, + -2.7425370308549580e-7, -2.9249662541757600e-7, + -3.1171981968268900e-7, -3.3197864040473180e-7, + -3.5333134588843600e-7, -3.7583910465412180e-7, + -3.9956628121669190e-7, -4.2458045296159330e-7, + -4.5095249563698380e-7, -4.7875659112606760e-7, + -5.0807031294631050e-7, -5.3897464223335550e-7, + -5.7155423388793000e-7, -6.0589741192019800e-7, + -6.4209580087853050e-7, -6.8024432849991400e-7, + -7.2044165259013450e-7, -7.6279018172077200e-7, + -8.0739610368280600e-7, -8.5436937020293650e-7, + -9.0382333224895500e-7, -9.5587472540498280e-7, + -1.0106437128213760e-6, -1.0682538906146330e-6, + -1.1288323637155430e-6, -1.1925097184646100e-6, + -1.2594193438633260e-6, -1.3296974052300520e-6, + -1.4034829433780260e-6, -1.4809178634979940e-6, + -1.5621465913980060e-6, -1.6473160377545360e-6, + -1.7365751553971340e-6, -1.8300749104526120e-6, + -1.9279680902322050e-6, -2.0304092660990760e-6, + -2.1375541686662320e-6, -2.2495596253776460e-6, + -2.3665828120950560e-6, -2.4887811970856540e-6, + -2.6163120571644820e-6, -2.7493324266391140e-6, + -2.8879984579501380e-6, -3.0324653639203880e-6, + -3.1828867865974640e-6, -3.3394147240855820e-6, + -3.5021985520037540e-6, -3.6713849262294680e-6, + -3.8471166218015830e-6, -4.0295324657699800e-6, + -4.2187670209852250e-6, -4.4149505043312320e-6, + -4.6182073040543900e-6, -4.8286558658894680e-6, + -5.0464076705003400e-6, -5.2715671455405850e-6, + -5.5042307535458100e-6, -5.7444868785028750e-6, + -5.9924142424804800e-6, -6.2480817863072800e-6, + -6.5115476278604000e-6, -6.7828589565804950e-6, + -7.0620507545154100e-6, -7.3491456697144900e-6, + -7.6441525098592000e-6, -7.9470661364365490e-6, + -8.2578666429227760e-6, -8.5765192154768100e-6, + -8.9029718900122000e-6, -9.2371554195468400e-6, + -9.5789825988253100e-6, -9.9283481667264540e-6, + -1.0285127334608450e-5, -1.0649175634328590e-5, + -1.1020327046334650e-5, -1.1398393880881060e-5, + -1.1783166036693560e-5, -1.2174410889256530e-5, + -1.2571871574469220e-5, -1.2975266858030310e-5, + -1.3384289978242060e-5, -1.3798608540965960e-5, + -1.4217863365843780e-5, -1.4641668383496450e-5, + -1.5069609527679710e-5, -1.5501244597782600e-5, + -1.5936101341640500e-5, -1.6373677426466900e-5, + -1.6813441716539560e-5, -1.7254834143068570e-5, + -1.7697261563607500e-5, -1.8140097714618200e-5, + -1.8582686308483550e-5, -1.9024340970099240e-5, + -1.9464340744880170e-5, -1.9901930030141080e-5, + -2.0336321557464510e-5, -2.0766696417773940e-5, + -2.1192201630574280e-5, -2.1611950084231910e-5, + -2.2025021652894630e-5, -2.2430463239517170e-5, + -2.2827288605503470e-5, -2.3214478371918170e-5, + -2.3590980216497750e-5, -2.3955708939763280e-5, + -2.4307547722489910e-5, -2.4645348200903720e-5, + -2.4967930863542620e-5, -2.5274085082324960e-5, + /* Bank 1 */ + 2.5562569399199020e-5, 2.5832111724562040e-5, + 2.6081413415833200e-5, 2.6309149390520640e-5, + 2.6513966535124460e-5, 2.6694483850464800e-5, + 2.6849297239997120e-5, 2.6976979753245170e-5, + 2.7076082153012070e-5, 2.7145133103663890e-5, + 2.7182642746157720e-5, 2.7187102980536760e-5, + 2.7156990105794550e-5, 2.7090765064735940e-5, + 2.6986876191054700e-5, 2.6843759539035120e-5, + 2.6659843389908530e-5, 2.6433548592482960e-5, + 2.6163291550639320e-5, 2.5847484577439320e-5, + 2.5484540698002960e-5, 2.5072874052447260e-5, + 2.4610903957661350e-5, 2.4097055300584120e-5, + 2.3529763128539150e-5, 2.2907473117403740e-5, + 2.2228647280994560e-5, 2.1491764461832140e-5, + 2.0695325418576370e-5, 1.9837853265502040e-5, + /* NOTE: The spec has a duplicated row "160 | 1.7934037335534700e-5" ! */ + 1.8917898053528080e-5, 1.7934037335534700e-5, + 1.6884884022311310e-5, 1.5769086921577900e-5, + 1.4585334740507920e-5, 1.3332356590263080e-5, + 1.2008929083235120e-5, 1.0613876973541650e-5, + 9.1460801506922300e-6, 7.6044740757265500e-6, + 5.9880523825897000e-6, 4.2958677847708840e-6, + 2.5270494199802070e-6, 6.8080315386959900e-7, + -1.2435990827839660e-6, -3.2468187066945930e-6, + -5.3294268968052800e-6, -7.4919036559427900e-6, + -9.7346407524871100e-6, -1.2057941408635810e-5, + -1.4462010500550970e-5, -1.6946953848107710e-5, + -1.9512772389215240e-5, -2.2159361597292710e-5, + -2.4886504491416160e-5, -2.7693871041862060e-5, + -3.0581012081916960e-5, -3.3547358765259040e-5, + -3.6592216716540970e-5, -3.9714765485539260e-5, + -4.2914052387856640e-5, -4.6188991961724560e-5, + -4.9538360176954340e-5, -5.2960794000140600e-5, + -5.6454787620185350e-5, -6.0018691972791050e-5, + -6.3650708053788550e-5, -6.7348886525882700e-5, + -7.1111125753722860e-5, -7.4935171411178040e-5, + -7.8818609806320000e-5, -8.2758867628623800e-5, + -8.6753213062403400e-5, -9.0798755482139240e-5, + -9.4892437636254000e-5, -9.9031035415475500e-5, + -1.0321116057304920e-4, -1.0742926070674010e-4, + -1.1168161614264270e-4, -1.1596433966772030e-4, + -1.2027337376184880e-4, -1.2460449089034750e-4, + -1.2895330270761850e-4, -1.3331525983885840e-4, + -1.3768563787408340e-4, -1.4205953760578120e-4, + -1.4643190426323540e-4, -1.5079752791692290e-4, + -1.5515103314094370e-4, -1.5948687909058970e-4, + -1.6379937154642740e-4, -1.6808266356446820e-4, + -1.7233075773584680e-4, -1.7653750646560020e-4, + -1.8069661584612290e-4, -1.8480164638953740e-4, + -1.8884602526638050e-4, -1.9282304696531290e-4, + -1.9672587556804270e-4, -2.0054754547108610e-4, + -2.0428097498957360e-4, -2.0791896735659270e-4, + -2.1145421910491280e-4, -2.1487932080488700e-4, + -2.1818676491655660e-4, -2.2136894706917190e-4, + -2.2441818635854840e-4, -2.2732672676686290e-4, + -2.3008674810081220e-4, -2.3269036653525150e-4, + -2.3512963563507800e-4, -2.3739654799291240e-4, + -2.3948307023621970e-4, -2.4138114593372380e-4, + -2.4308272452941820e-4, -2.4457975717687980e-4, + -2.4586407616017000e-4, -2.4692741569938220e-4, + -2.4776199025177680e-4, -2.4836046092637280e-4, + -2.4871461830381660e-4, -2.4881540457247040e-4, + -2.4865471770248810e-4, -2.4822543333608940e-4, + -2.4752008219951220e-4, -2.4653081794176570e-4, + -2.4525003217524440e-4, -2.4367037437341020e-4, + /* Bank 2 */ + 2.4178457457919800e-4, 2.3958543985834340e-4, + 2.3706595356421380e-4, 2.3421928008696620e-4, + 2.3103877007019660e-4, 2.2751796132972940e-4, + 2.2365059385031200e-4, 2.1943061159567880e-4, + 2.1485218733324290e-4, 2.0990972538755550e-4, + 2.0459789739171640e-4, 1.9891164424316180e-4, + 1.9284618337957900e-4, 1.8639701070854740e-4, + 1.7955993578371750e-4, 1.7233108395155490e-4, + 1.6470690840351980e-4, 1.5668419239382670e-4, + 1.4826008597798460e-4, 1.3943210818407590e-4, + 1.3019815804235450e-4, 1.2055651618705740e-4, + 1.1050586906665980e-4, 1.0004531116378850e-4, + 8.9174369623037550e-5, 7.7893006105444910e-5, + 6.6201632959158800e-5, 5.4101115008963200e-5, + 4.1592792755171040e-5, 2.8678484003389880e-5, + 1.5360496520469550e-5, 1.6416297019304470e-6, + -1.2474801400564880e-5, -2.6984964757674160e-5, + -4.1884506316022560e-5, -5.7168548169515050e-5, + -7.2831653374563650e-5, -8.8867825335203200e-5, + -1.0527052946041040e-4, -1.2203269185287530e-4, + -1.3914664880465400e-4, -1.5660414556657680e-4, + -1.7439635977956720e-4, -1.9251390142613000e-4, + -2.1094678833176480e-4, -2.2968444457655940e-4, + -2.4871569004884240e-4, -2.6802874127778880e-4, + -2.8761124019708440e-4, -3.0745025297166030e-4, + -3.2753221542219500e-4, -3.4784293347385130e-4, + -3.6836764760397900e-4, -3.8909103335715320e-4, + -4.0999714822829530e-4, -4.3106943097409840e-4, + -4.5229073958127750e-4, -4.7364335350426610e-4, + -4.9510898492628230e-4, -5.1666877822680600e-4, + -5.3830328700499900e-4, -5.5999247625413450e-4, + -5.8171579317559550e-4, -6.0345216810040500e-4, + -6.2517996394886800e-4, -6.4687697763330650e-4, + -6.6852052145861900e-4, -6.9008742526480550e-4, + -7.1155400216196750e-4, -7.3289605035434600e-4, + -7.5408892753413600e-4, -7.7510755325530950e-4, + -7.9592638676398950e-4, -8.1651942936660300e-4, + -8.3686029869896850e-4, -8.5692223230171550e-4, + -8.7667809201044900e-4, -8.9610036547340950e-4, + -9.1516119514986000e-4, -9.3383238324995840e-4, + -9.5208547141354700e-4, -9.6989174214394400e-4, + -9.8722217067251400e-4, -1.0040474297445790e-3, + -1.0203380430448350e-3, -1.0360643900964910e-3, + -1.0511966606168980e-3, -1.0657048556038330e-3, + -1.0795588568782010e-3, -1.0927284332850520e-3, + -1.1051833075734240e-3, -1.1168931605293980e-3, + -1.1278276550234160e-3, -1.1379564405661050e-3, + -1.1472492294891640e-3, -1.1556758000499310e-3, + -1.1632059885511800e-3, -1.1698096960154200e-3, + -1.1754570428998680e-3, -1.1801183720212010e-3, + -1.1837641581852870e-3, -1.1863650153060240e-3, + -1.1878919433902330e-3, -1.1883163316843900e-3, + -1.1876097809178440e-3, -1.1857441072376680e-3, + -1.1826916065321440e-3, -1.1784250628415020e-3, + -1.1729176690707690e-3, -1.1661430294353880e-3, + -1.1580752925519680e-3, -1.1486891568700730e-3, + -1.1379598570807350e-3, -1.1258631690530700e-3, + -1.1123755320313420e-3, -1.0974740543942100e-3, + -1.0811365181610850e-3, -1.0633413819325920e-3, + -1.0440678410743190e-3, -1.0232958338441730e-3, + -1.0010061160103870e-3, -9.7718026613602800e-4, + -9.5180072722007060e-4, -9.2485080945546600e-4, + -8.9631470926558100e-4, -8.6617751390929650e-4, + -8.3442528375666700e-4, -8.0104505655578600e-4, + /* Bank 3 */ + 7.6602485902806300e-4, 7.2935371157849700e-4, + 6.9102172032639350e-4, 6.5102007948960100e-4, + 6.0934103180698750e-4, 5.6597787244591100e-4, + 5.2092507454409450e-4, 4.7417829303612970e-4, + 4.2573432329476060e-4, 3.7559110239316400e-4, + 3.2374777823389440e-4, 2.7020471361387040e-4, + 2.1496350652513040e-4, 1.5802699163104190e-4, + 9.9399252442146460e-5, 3.9085623279149610e-5, + -2.2907279717153710e-5, -8.6571556658577800e-5, + -1.5189801251884410e-4, -2.1887615668780720e-4, + -2.8749420455512610e-4, -3.5773907519488100e-4, + -4.2959633884346400e-4, -5.0305021853266900e-4, + -5.7808367853976800e-4, -6.5467842279709950e-4, + -7.3281477145293300e-4, -8.1247166091487090e-4, + -8.9362676824381250e-4, -9.7625651350435400e-4, + -1.0603359870796300e-3, -1.1458389497708370e-3, + -1.2327379076720450e-3, -1.3210041125919850e-3, + -1.4106074964587530e-3, -1.5015166759080980e-3, + -1.5936991188210680e-3, -1.6871211446584360e-3, + -1.7817477652804130e-3, -1.8775426862784720e-3, + -1.9744684954557180e-3, -2.0724866717198650e-3, + -2.1715575922482770e-3, -2.2716405301701940e-3, + -2.3726935964105480e-3, -2.4746737418493600e-3, + -2.5775368629845300e-3, -2.6812378156433060e-3, + -2.7857306109716460e-3, -2.8909684129992950e-3, + -2.9969032890820140e-3, -3.1034862132032660e-3, + -3.2106673881690480e-3, -3.3183962566563890e-3, + -3.4266214220855450e-3, -3.5352906520539890e-3, + -3.6443510330122110e-3, -3.7537489709635930e-3, + -3.8634300521859240e-3, -3.9733390588103910e-3, + -4.0834204508378470e-3, -4.1936183686073460e-3, + -4.3038762050876900e-3, -4.4141366059086620e-3, + -4.5243418977567100e-3, -4.6344341075783170e-3, + -4.7443549566589130e-3, -4.8540458565358850e-3, + -4.9634478250060780e-3, -5.0725014978718950e-3, + -5.1811474713480250e-3, -5.2893263173827950e-3, + -5.3969785783205650e-3, -5.5040447592375600e-3, + -5.6104651646665850e-3, -5.7161799140263450e-3, + -5.8211294443412250e-3, -5.9252545216101900e-3, + -6.0284959882028950e-3, -6.1307947602360250e-3, + -6.2320920224565700e-3, -6.3323292492425800e-3, + -6.4314484717364400e-3, -6.5293922762311450e-3, + -6.6261035015351700e-3, -6.7215252466922100e-3, + -6.8156013434509950e-3, -6.9082763630156450e-3, + -6.9994952920827200e-3, -7.0892035490577050e-3, + -7.1773476647806300e-3, -7.2638752839566550e-3, + -7.3487345159041400e-3, -7.4318739341000500e-3, + -7.5132432154309250e-3, -7.5927931627681400e-3, + -7.6704755623721500e-3, -7.7462431738117650e-3, + -7.8200496507836000e-3, -7.8918495587816850e-3, + -7.9615988430090790e-3, -8.0292548409052500e-3, + -8.0947760898363200e-3, -8.1581223027535600e-3, + -8.2192540249893810e-3, -8.2781326752680240e-3, + -8.3347217911436610e-3, -8.3889870206274740e-3, + -8.4408946925453690e-3, -8.4904118087845760e-3, + -8.5375073033623590e-3, -8.5821520672029750e-3, + -8.6243182341614300e-3, -8.6639791627160300e-3, + -8.7011097471794110e-3, -8.7356864659172800e-3, + -8.7676881309490440e-3, -8.7970958152554810e-3, + -8.8238905039462850e-3, -8.8480531477483150e-3, + -8.8695681885783190e-3, -8.8884235927356400e-3, + -8.9046080555685600e-3, -8.9181109318560050e-3, + -8.9289234995380550e-3, -8.9370390010903460e-3, + -8.9424522900292110e-3, -8.9451598223763610e-3, + /* Bank 4 */ + 8.9451598223763610e-3, 8.9424522900292110e-3, + 8.9370390010903460e-3, 8.9289234995380550e-3, + 8.9181109318560050e-3, 8.9046080555685600e-3, + 8.8884235927356400e-3, 8.8695681885783190e-3, + 8.8480531477483150e-3, 8.8238905039462850e-3, + 8.7970958152554810e-3, 8.7676881309490440e-3, + 8.7356864659172800e-3, 8.7011097471794110e-3, + 8.6639791627160300e-3, 8.6243182341614300e-3, + 8.5821520672029750e-3, 8.5375073033623590e-3, + 8.4904118087845760e-3, 8.4408946925453690e-3, + 8.3889870206274740e-3, 8.3347217911436610e-3, + 8.2781326752680240e-3, 8.2192540249893810e-3, + 8.1581223027535600e-3, 8.0947760898363200e-3, + 8.0292548409052500e-3, 7.9615988430090790e-3, + 7.8918495587816850e-3, 7.8200496507836000e-3, + 7.7462431738117650e-3, 7.6704755623721500e-3, + 7.5927931627681400e-3, 7.5132432154309250e-3, + 7.4318739341000500e-3, 7.3487345159041400e-3, + 7.2638752839566550e-3, 7.1773476647806300e-3, + 7.0892035490577050e-3, 6.9994952920827200e-3, + 6.9082763630156450e-3, 6.8156013434509950e-3, + 6.7215252466922100e-3, 6.6261035015351700e-3, + 6.5293922762311450e-3, 6.4314484717364400e-3, + 6.3323292492425800e-3, 6.2320920224565700e-3, + 6.1307947602360250e-3, 6.0284959882028950e-3, + 5.9252545216101900e-3, 5.8211294443412250e-3, + 5.7161799140263450e-3, 5.6104651646665850e-3, + 5.5040447592375600e-3, 5.3969785783205650e-3, + 5.2893263173827950e-3, 5.1811474713480250e-3, + 5.0725014978718950e-3, 4.9634478250060780e-3, + 4.8540458565358850e-3, 4.7443549566589130e-3, + 4.6344341075783170e-3, 4.5243418977567100e-3, + 4.4141366059086620e-3, 4.3038762050876900e-3, + 4.1936183686073460e-3, 4.0834204508378470e-3, + 3.9733390588103910e-3, 3.8634300521859240e-3, + 3.7537489709635930e-3, 3.6443510330122110e-3, + 3.5352906520539890e-3, 3.4266214220855450e-3, + 3.3183962566563890e-3, 3.2106673881690480e-3, + 3.1034862132032660e-3, 2.9969032890820140e-3, + 2.8909684129992950e-3, 2.7857306109716460e-3, + 2.6812378156433060e-3, 2.5775368629845300e-3, + 2.4746737418493600e-3, 2.3726935964105480e-3, + 2.2716405301701940e-3, 2.1715575922482770e-3, + 2.0724866717198650e-3, 1.9744684954557180e-3, + 1.8775426862784720e-3, 1.7817477652804130e-3, + 1.6871211446584360e-3, 1.5936991188210680e-3, + 1.5015166759080980e-3, 1.4106074964587530e-3, + 1.3210041125919850e-3, 1.2327379076720450e-3, + 1.1458389497708370e-3, 1.0603359870796300e-3, + 9.7625651350435400e-4, 8.9362676824381250e-4, + 8.1247166091487090e-4, 7.3281477145293300e-4, + 6.5467842279709950e-4, 5.7808367853976800e-4, + 5.0305021853266900e-4, 4.2959633884346400e-4, + 3.5773907519488100e-4, 2.8749420455512610e-4, + 2.1887615668780720e-4, 1.5189801251884410e-4, + 8.6571556658577800e-5, 2.2907279717153710e-5, + -3.9085623279149610e-5, -9.9399252442146460e-5, + -1.5802699163104190e-4, -2.1496350652513040e-4, + -2.7020471361387040e-4, -3.2374777823389440e-4, + -3.7559110239316400e-4, -4.2573432329476060e-4, + -4.7417829303612970e-4, -5.2092507454409450e-4, + -5.6597787244591100e-4, -6.0934103180698750e-4, + -6.5102007948960100e-4, -6.9102172032639350e-4, + -7.2935371157849700e-4, -7.6602485902806300e-4, + /* Bank 5 */ + 8.0104505655578600e-4, 8.3442528375666700e-4, + 8.6617751390929650e-4, 8.9631470926558100e-4, + 9.2485080945546600e-4, 9.5180072722007060e-4, + 9.7718026613602800e-4, 1.0010061160103870e-3, + 1.0232958338441730e-3, 1.0440678410743190e-3, + 1.0633413819325920e-3, 1.0811365181610850e-3, + 1.0974740543942100e-3, 1.1123755320313420e-3, + 1.1258631690530700e-3, 1.1379598570807350e-3, + 1.1486891568700730e-3, 1.1580752925519680e-3, + 1.1661430294353880e-3, 1.1729176690707690e-3, + 1.1784250628415020e-3, 1.1826916065321440e-3, + 1.1857441072376680e-3, 1.1876097809178440e-3, + 1.1883163316843900e-3, 1.1878919433902330e-3, + 1.1863650153060240e-3, 1.1837641581852870e-3, + 1.1801183720212010e-3, 1.1754570428998680e-3, + 1.1698096960154200e-3, 1.1632059885511800e-3, + 1.1556758000499310e-3, 1.1472492294891640e-3, + 1.1379564405661050e-3, 1.1278276550234160e-3, + 1.1168931605293980e-3, 1.1051833075734240e-3, + 1.0927284332850520e-3, 1.0795588568782010e-3, + 1.0657048556038330e-3, 1.0511966606168980e-3, + 1.0360643900964910e-3, 1.0203380430448350e-3, + 1.0040474297445790e-3, 9.8722217067251400e-4, + 9.6989174214394400e-4, 9.5208547141354700e-4, + 9.3383238324995840e-4, 9.1516119514986000e-4, + 8.9610036547340950e-4, 8.7667809201044900e-4, + 8.5692223230171550e-4, 8.3686029869896850e-4, + 8.1651942936660300e-4, 7.9592638676398950e-4, + 7.7510755325530950e-4, 7.5408892753413600e-4, + 7.3289605035434600e-4, 7.1155400216196750e-4, + 6.9008742526480550e-4, 6.6852052145861900e-4, + 6.4687697763330650e-4, 6.2517996394886800e-4, + 6.0345216810040500e-4, 5.8171579317559550e-4, + 5.5999247625413450e-4, 5.3830328700499900e-4, + 5.1666877822680600e-4, 4.9510898492628230e-4, + 4.7364335350426610e-4, 4.5229073958127750e-4, + 4.3106943097409840e-4, 4.0999714822829530e-4, + 3.8909103335715320e-4, 3.6836764760397900e-4, + 3.4784293347385130e-4, 3.2753221542219500e-4, + 3.0745025297166030e-4, 2.8761124019708440e-4, + 2.6802874127778880e-4, 2.4871569004884240e-4, + 2.2968444457655940e-4, 2.1094678833176480e-4, + 1.9251390142613000e-4, 1.7439635977956720e-4, + 1.5660414556657680e-4, 1.3914664880465400e-4, + 1.2203269185287530e-4, 1.0527052946041040e-4, + 8.8867825335203200e-5, 7.2831653374563650e-5, + 5.7168548169515050e-5, 4.1884506316022560e-5, + 2.6984964757674160e-5, 1.2474801400564880e-5, + -1.6416297019304470e-6, -1.5360496520469550e-5, + -2.8678484003389880e-5, -4.1592792755171040e-5, + -5.4101115008963200e-5, -6.6201632959158800e-5, + -7.7893006105444910e-5, -8.9174369623037550e-5, + -1.0004531116378850e-4, -1.1050586906665980e-4, + -1.2055651618705740e-4, -1.3019815804235450e-4, + -1.3943210818407590e-4, -1.4826008597798460e-4, + -1.5668419239382670e-4, -1.6470690840351980e-4, + -1.7233108395155490e-4, -1.7955993578371750e-4, + -1.8639701070854740e-4, -1.9284618337957900e-4, + -1.9891164424316180e-4, -2.0459789739171640e-4, + -2.0990972538755550e-4, -2.1485218733324290e-4, + -2.1943061159567880e-4, -2.2365059385031200e-4, + -2.2751796132972940e-4, -2.3103877007019660e-4, + -2.3421928008696620e-4, -2.3706595356421380e-4, + -2.3958543985834340e-4, -2.4178457457919800e-4, + /* Bank 6 */ + 2.4367037437341020e-4, 2.4525003217524440e-4, + 2.4653081794176570e-4, 2.4752008219951220e-4, + 2.4822543333608940e-4, 2.4865471770248810e-4, + 2.4881540457247040e-4, 2.4871461830381660e-4, + 2.4836046092637280e-4, 2.4776199025177680e-4, + 2.4692741569938220e-4, 2.4586407616017000e-4, + 2.4457975717687980e-4, 2.4308272452941820e-4, + 2.4138114593372380e-4, 2.3948307023621970e-4, + 2.3739654799291240e-4, 2.3512963563507800e-4, + 2.3269036653525150e-4, 2.3008674810081220e-4, + 2.2732672676686290e-4, 2.2441818635854840e-4, + 2.2136894706917190e-4, 2.1818676491655660e-4, + 2.1487932080488700e-4, 2.1145421910491280e-4, + 2.0791896735659270e-4, 2.0428097498957360e-4, + 2.0054754547108610e-4, 1.9672587556804270e-4, + 1.9282304696531290e-4, 1.8884602526638050e-4, + 1.8480164638953740e-4, 1.8069661584612290e-4, + 1.7653750646560020e-4, 1.7233075773584680e-4, + 1.6808266356446820e-4, 1.6379937154642740e-4, + 1.5948687909058970e-4, 1.5515103314094370e-4, + 1.5079752791692290e-4, 1.4643190426323540e-4, + 1.4205953760578120e-4, 1.3768563787408340e-4, + 1.3331525983885840e-4, 1.2895330270761850e-4, + 1.2460449089034750e-4, 1.2027337376184880e-4, + 1.1596433966772030e-4, 1.1168161614264270e-4, + 1.0742926070674010e-4, 1.0321116057304920e-4, + 9.9031035415475500e-5, 9.4892437636254000e-5, + 9.0798755482139240e-5, 8.6753213062403400e-5, + 8.2758867628623800e-5, 7.8818609806320000e-5, + 7.4935171411178040e-5, 7.1111125753722860e-5, + 6.7348886525882700e-5, 6.3650708053788550e-5, + 6.0018691972791050e-5, 5.6454787620185350e-5, + 5.2960794000140600e-5, 4.9538360176954340e-5, + 4.6188991961724560e-5, 4.2914052387856640e-5, + 3.9714765485539260e-5, 3.6592216716540970e-5, + 3.3547358765259040e-5, 3.0581012081916960e-5, + 2.7693871041862060e-5, 2.4886504491416160e-5, + 2.2159361597292710e-5, 1.9512772389215240e-5, + 1.6946953848107710e-5, 1.4462010500550970e-5, + 1.2057941408635810e-5, 9.7346407524871100e-6, + 7.4919036559427900e-6, 5.3294268968052800e-6, + 3.2468187066945930e-6, 1.2435990827839660e-6, + -6.8080315386959900e-7, -2.5270494199802070e-6, + -4.2958677847708840e-6, -5.9880523825897000e-6, + -7.6044740757265500e-6, -9.1460801506922300e-6, + -1.0613876973541650e-5, -1.2008929083235120e-5, + -1.3332356590263080e-5, -1.4585334740507920e-5, + -1.5769086921577900e-5, -1.6884884022311310e-5, + -1.7934037335534700e-5, -1.8917898053528080e-5, + -1.9837853265502040e-5, -2.0695325418576370e-5, + -2.1491764461832140e-5, -2.2228647280994560e-5, + -2.2907473117403740e-5, -2.3529763128539150e-5, + -2.4097055300584120e-5, -2.4610903957661350e-5, + -2.5072874052447260e-5, -2.5484540698002960e-5, + -2.5847484577439320e-5, -2.6163291550639320e-5, + -2.6433548592482960e-5, -2.6659843389908530e-5, + -2.6843759539035120e-5, -2.6986876191054700e-5, + -2.7090765064735940e-5, -2.7156990105794550e-5, + -2.7187102980536760e-5, -2.7182642746157720e-5, + -2.7145133103663890e-5, -2.7076082153012070e-5, + -2.6976979753245170e-5, -2.6849297239997120e-5, + -2.6694483850464800e-5, -2.6513966535124460e-5, + -2.6309149390520640e-5, -2.6081413415833200e-5, + -2.5832111724562040e-5, -2.5562569399199020e-5, + /* Bank 7 */ + 2.5274085082324960e-5, 2.4967930863542620e-5, + 2.4645348200903720e-5, 2.4307547722489910e-5, + 2.3955708939763280e-5, 2.3590980216497750e-5, + 2.3214478371918170e-5, 2.2827288605503470e-5, + 2.2430463239517170e-5, 2.2025021652894630e-5, + 2.1611950084231910e-5, 2.1192201630574280e-5, + 2.0766696417773940e-5, 2.0336321557464510e-5, + 1.9901930030141080e-5, 1.9464340744880170e-5, + 1.9024340970099240e-5, 1.8582686308483550e-5, + 1.8140097714618200e-5, 1.7697261563607500e-5, + 1.7254834143068570e-5, 1.6813441716539560e-5, + 1.6373677426466900e-5, 1.5936101341640500e-5, + 1.5501244597782600e-5, 1.5069609527679710e-5, + 1.4641668383496450e-5, 1.4217863365843780e-5, + 1.3798608540965960e-5, 1.3384289978242060e-5, + 1.2975266858030310e-5, 1.2571871574469220e-5, + 1.2174410889256530e-5, 1.1783166036693560e-5, + 1.1398393880881060e-5, 1.1020327046334650e-5, + 1.0649175634328590e-5, 1.0285127334608450e-5, + 9.9283481667264540e-6, 9.5789825988253100e-6, + 9.2371554195468400e-6, 8.9029718900122000e-6, + 8.5765192154768100e-6, 8.2578666429227760e-6, + 7.9470661364365490e-6, 7.6441525098592000e-6, + 7.3491456697144900e-6, 7.0620507545154100e-6, + 6.7828589565804950e-6, 6.5115476278604000e-6, + 6.2480817863072800e-6, 5.9924142424804800e-6, + 5.7444868785028750e-6, 5.5042307535458100e-6, + 5.2715671455405850e-6, 5.0464076705003400e-6, + 4.8286558658894680e-6, 4.6182073040543900e-6, + 4.4149505043312320e-6, 4.2187670209852250e-6, + 4.0295324657699800e-6, 3.8471166218015830e-6, + 3.6713849262294680e-6, 3.5021985520037540e-6, + 3.3394147240855820e-6, 3.1828867865974640e-6, + 3.0324653639203880e-6, 2.8879984579501380e-6, + 2.7493324266391140e-6, 2.6163120571644820e-6, + 2.4887811970856540e-6, 2.3665828120950560e-6, + 2.2495596253776460e-6, 2.1375541686662320e-6, + 2.0304092660990760e-6, 1.9279680902322050e-6, + 1.8300749104526120e-6, 1.7365751553971340e-6, + 1.6473160377545360e-6, 1.5621465913980060e-6, + 1.4809178634979940e-6, 1.4034829433780260e-6, + 1.3296974052300520e-6, 1.2594193438633260e-6, + 1.1925097184646100e-6, 1.1288323637155430e-6, + 1.0682538906146330e-6, 1.0106437128213760e-6, + 9.5587472540498280e-7, 9.0382333224895500e-7, + 8.5436937020293650e-7, 8.0739610368280600e-7, + 7.6279018172077200e-7, 7.2044165259013450e-7, + 6.8024432849991400e-7, 6.4209580087853050e-7, + 6.0589741192019800e-7, 5.7155423388793000e-7, + 5.3897464223335550e-7, 5.0807031294631050e-7, + 4.7875659112606760e-7, 4.5095249563698380e-7, + 4.2458045296159330e-7, 3.9956628121669190e-7, + 3.7583910465412180e-7, 3.5333134588843600e-7, + 3.3197864040473180e-7, 3.1171981968268900e-7, + 2.9249662541757600e-7, 2.7425370308549580e-7, + 2.5693874615777660e-7, 2.4050245877923400e-7, + 2.2489759047553620e-7, 2.1007899706006800e-7, + 1.9600594587757850e-7, 1.8264184311018150e-7, + 1.6994592926571220e-7, 1.5787424998123710e-7, + 1.4640931821191640e-7, 1.3555636137971380e-7, + 1.2523109645615350e-7, 1.1527363411865760e-7, + 1.0586659510721950e-7, 9.7483190494874640e-8, + 8.9326871281374790e-8, 7.9525034321375090e-8, + 7.0950903150874990e-8, 7.1279389866041690e-8, +}; + +/* + * D.11 Look-up Table for Downmix Scale Factors + * + * Note that the range of the entries in DmixTable[] is between -60 dB and 0 dB + * with addition of -inf (|DMixCoeff| = 0), which is coded with a DmixCode = 0. + * Furthermore, the range [-60 to 0] is subdivided into 3 regions, each with a + * different grid resolution: + * + * 1) [-60.000 to -30] with resolution of 0.500 dB + * 2) [-29.750 to -15] with resolution of 0.250 dB + * 3) [-14.875 to 0] with resolution of 0.125 dB + */ +const uint16_t ff_dca_dmixtable[FF_DCA_DMIXTABLE_SIZE] = { + 0, 33, 35, 37, 39, 41, 44, 46, + 49, 52, 55, 58, 62, 65, 69, 73, + 78, 82, 87, 92, 98, 104, 110, 116, + 123, 130, 138, 146, 155, 164, 174, 184, + 195, 207, 219, 232, 246, 260, 276, 292, + 309, 328, 347, 368, 389, 413, 437, 463, + 490, 519, 550, 583, 617, 654, 693, 734, + 777, 823, 872, 924, 978, 1036, 1066, 1098, + 1130, 1163, 1197, 1232, 1268, 1305, 1343, 1382, + 1422, 1464, 1506, 1550, 1596, 1642, 1690, 1740, + 1790, 1843, 1896, 1952, 2009, 2068, 2128, 2190, + 2254, 2320, 2388, 2457, 2529, 2603, 2679, 2757, + 2838, 2920, 3006, 3093, 3184, 3277, 3372, 3471, + 3572, 3677, 3784, 3894, 4008, 4125, 4246, 4370, + 4497, 4629, 4764, 4903, 5046, 5193, 5345, 5501, + 5662, 5827, 5912, 5997, 6084, 6172, 6262, 6353, + 6445, 6538, 6633, 6729, 6827, 6925, 7026, 7128, + 7231, 7336, 7442, 7550, 7659, 7771, 7883, 7997, + 8113, 8231, 8350, 8471, 8594, 8719, 8845, 8973, + 9103, 9235, 9369, 9505, 9643, 9783, 9924, 10068, + 10214, 10362, 10512, 10665, 10819, 10976, 11135, 11297, + 11460, 11627, 11795, 11966, 12139, 12315, 12494, 12675, + 12859, 13045, 13234, 13426, 13621, 13818, 14018, 14222, + 14428, 14637, 14849, 15064, 15283, 15504, 15729, 15957, + 16188, 16423, 16661, 16902, 17147, 17396, 17648, 17904, + 18164, 18427, 18694, 18965, 19240, 19519, 19802, 20089, + 20380, 20675, 20975, 21279, 21587, 21900, 22218, 22540, + 22867, 23170, 23534, 23875, 24221, 24573, 24929, 25290, + 25657, 26029, 26406, 26789, 27177, 27571, 27970, 28376, + 28787, 29205, 29628, 30057, 30493, 30935, 31383, 31838, + 32300, 32768, +}; + +const uint32_t ff_dca_inv_dmixtable[FF_DCA_INV_DMIXTABLE_SIZE] = { + 6553600, 6186997, 5840902, 5514167, 5205710, 4914507, 4639593, 4380059, + 4135042, 3903731, 3685360, 3479204, 3284581, 3100844, 2927386, 2763630, + 2609035, 2463088, 2325305, 2195230, 2072430, 2013631, 1956500, 1900990, + 1847055, 1794651, 1743733, 1694260, 1646190, 1599484, 1554103, 1510010, + 1467168, 1425542, 1385096, 1345798, 1307615, 1270515, 1234468, 1199444, + 1165413, 1132348, 1100221, 1069005, 1038676, 1009206, 980573, 952752, + 925721, 899456, 873937, 849141, 825049, 801641, 778897, 756798, + 735326, 714463, 694193, 674497, 655360, 636766, 618700, 601146, + 584090, 567518, 551417, 535772, 520571, 505801, 491451, 477507, + 463959, 450796, 438006, 425579, 413504, 401772, 390373, 379297, + 368536, 363270, 358080, 352964, 347920, 342949, 338049, 333219, + 328458, 323765, 319139, 314579, 310084, 305654, 301287, 296982, + 292739, 288556, 284433, 280369, 276363, 272414, 268522, 264685, + 260904, 257176, 253501, 249879, 246309, 242790, 239321, 235901, + 232531, 229208, 225933, 222705, 219523, 216386, 213295, 210247, + 207243, 204282, 201363, 198486, 195650, 192855, 190099, 187383, + 184706, 182066, 179465, 176901, 174373, 171882, 169426, 167005, + 164619, 162267, 159948, 157663, 155410, 153190, 151001, 148844, + 146717, 144621, 142554, 140517, 138510, 136531, 134580, 132657, + 130762, 128893, 127052, 125236, 123447, 121683, 119944, 118231, + 116541, 114876, 113235, 111617, 110022, 108450, 106901, 105373, + 103868, 102383, 100921, 99479, 98057, 96656, 95275, 93914, + 92682, 91249, 89946, 88660, 87394, 86145, 84914, 83701, + 82505, 81326, 80164, 79019, 77890, 76777, 75680, 74598, + 73533, 72482, 71446, 70425, 69419, 68427, 67450, 66486, + 65536, +}; + +const float ff_dca_default_coeffs[10][6][2] = { + { { 0.707107, 0.707107 }, { 0.000000, 0.000000 }, }, // A [LFE] + { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // A + B (dual mono) [LFE] + { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // L + R (stereo) [LFE] + { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // (L+R) + (L-R) (sum-difference) [LFE] + { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // LT + RT (left and right total) [LFE] + { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.000000, 0.000000 }, }, // C + L + R [LFE] + { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + S [LFE] + { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + S [LFE] + { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + SL + SR [LFE] + { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + SL + SR [LFE] +}; + +const int32_t ff_dca_sampling_freqs[16] = { + 8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200, + 176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000, +}; + +/* downmix coeffs + * + * TABLE 9 + * ______________________________________ + * Down-mix coefficients for 8-channel source + * audio (5 + 3 format) + * lt + * cen- rt lt ctr rt + * lt ter ctr center + * rt srd srd srd + * ______________________________________ + * 1 0.71 0.74 1.0 0.71 0.71 0.58 0.58 0.58 + * 2 left 1.0 0.89 0.71 0.46 0.71 0.50 + * rt 0.45 0.71 0.89 1.0 0.50 0.71 + * 3 lt 1.0 0.89 0.71 0.45 + * rt 0.45 0.71 0.89 1.0 + * srd 0.71 0.71 0.71 + * 4 lt 1.0 0.89 0.71 0.45 + * rt 0.45 0.71 0.89 1.0 + * lt srd 1.0 0.71 + * rt srd 0.71 0.71 + * 4 lt 1.0 0.5 + * ctr 0.87 1.0 0.87 + * rt 0.5 1.0 + * srd 0.71 0.71 0.71 + * 5 lt 1.0 0.5 + * ctr 0.87 1.0 0.87 + * rt 0.5 1.0 + * lt srd 1.0 0.71 + * rt srd 0.71 1.0 + * 6 lt 1.0 0.5 + * lt ctr 0.87 0.71 + * rt ctr 0.71 0.87 + * rt 0.5 1.0 + * lt srd 1.0 0.71 + * rt srd 0.71 1.0 + * 6 lt 1.0 0.5 + * ctr 0.86 1.0 0.86 + * rt 0.5 1.0 + * lt srd 1.0 + * ctr srd 1.0 + * rt srd 1.0 + * 7 lt 1.0 + * lt ctr 1.0 + * ctr 1.0 + * rt ctr 1.0 + * rt 1.0 + * lt srd 1.0 0.71 + * rt srd 0.71 1.0 + * 7 lt 1.0 0.5 + * lt ctr 0.87 0.71 + * rt ctr 0.71 0.87 + * rt 0.5 1.0 + * lt srd 1.0 + * ctr srd 1.0 + * rt srd 1.0 + * 8 lt 1.0 0.5 + * lt ctr 0.87 0.71 + * rt ctr 0.71 0.87 + * rt 0.5 1.0 + * lt 1 srd 0.87 0.35 + * lt 2 srd 0.5 0.61 + * rt 2 srd 0.61 0.50 + * rt 2 srd 0.35 0.87 + * + * Generation of Lt Rt + * + * In the case when the playback system has analog or digital surround + * multi-channel capability, a down matrix from 5, 4, or 3 channel to + * Lt Rt may be desirable. In the case when the number of decoded audio + * channels exceeds 5, 4 or 3 respectively a first stage down mix to 5, + * 4 or 3 chs should be used as described above. + * + * The down matrixing equations for 5-channel source audio to a + * two-channel Lt Rt playback system are given by: + * + * Left = left + 0.7 * center - 0.7 * (lt surround + rt surround) + * + * Right = right + 0.7 * center + 0.7 * (lt surround + rt surround) + * + * Embedded mixing to 2-channel + * + * One concern arising from the proliferation of multi-channel audio + * systems is that most home systems presently have only two channel + * playback capability. To accommodate this a fixed 2-channel down + * matrix processes is commonly used following the multi-channel + * decoding stage. However, for music only applications the image + * quality etc. of the down matrixed signal may not match that of an + * equivalent stereo recording found on CD. + * + * The concept of embedded mixing is to allow the producer to + * dynamically specify the matrixing coefficients within the audio + * frame itself. In this way the stereo down mix at the decoder may be + * better matched to a 2-channel playback environment. + * + * CHS*2, 7-bit down mix indexes (MCOEFFS) are transmitted along with + * the multi-channel audio once in every frame. The indexes are + * converted to attenuation factors using a 7 bit LUT. The 2-ch down + * mix equations are as follows, + * + * Left Ch = sum (MCOEFF[n] * Ch[n]) for n=1, CHS + * + * Right Ch = sum (MCOEFF[n + CHS] * Ch[n]) for n=1, CHS + * + * where Ch(n) represents the subband samples in the (n)th audio channel. + */ + +const int8_t ff_dca_lfe_index[16] = { + 1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3 +}; + +const int8_t ff_dca_channel_reorder_lfe[16][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 3, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 4, -1, -1, -1, -1, -1 }, + { 0, 1, 3, 4, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 4, 5, -1, -1, -1, -1 }, + { 3, 4, 0, 1, 5, 6, -1, -1, -1 }, + { 2, 0, 1, 4, 5, 6, -1, -1, -1 }, + { 0, 6, 4, 5, 2, 3, -1, -1, -1 }, + { 4, 2, 5, 0, 1, 6, 7, -1, -1 }, + { 5, 6, 0, 1, 7, 3, 8, 4, -1 }, + { 4, 2, 5, 0, 1, 6, 8, 7, -1 }, +}; + +const int8_t ff_dca_channel_reorder_lfe_xch[16][9] = { + { 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 3, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 3, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 3, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 3, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 4, -1, -1, -1, -1, -1 }, + { 0, 1, 3, 4, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 4, 5, -1, -1, -1, -1 }, + { 0, 1, 4, 5, 3, -1, -1, -1, -1 }, + { 2, 0, 1, 5, 6, 4, -1, -1, -1 }, + { 3, 4, 0, 1, 6, 7, 5, -1, -1 }, + { 2, 0, 1, 4, 5, 6, 7, -1, -1 }, + { 0, 6, 4, 5, 2, 3, 7, -1, -1 }, + { 4, 2, 5, 0, 1, 7, 8, 6, -1 }, + { 5, 6, 0, 1, 8, 3, 9, 4, 7 }, + { 4, 2, 5, 0, 1, 6, 9, 8, 7 }, +}; + +const int8_t ff_dca_channel_reorder_nolfe[16][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 3, -1, -1, -1, -1, -1 }, + { 0, 1, 2, 3, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 3, 4, -1, -1, -1, -1 }, + { 2, 3, 0, 1, 4, 5, -1, -1, -1 }, + { 2, 0, 1, 3, 4, 5, -1, -1, -1 }, + { 0, 5, 3, 4, 1, 2, -1, -1, -1 }, + { 3, 2, 4, 0, 1, 5, 6, -1, -1 }, + { 4, 5, 0, 1, 6, 2, 7, 3, -1 }, + { 3, 2, 4, 0, 1, 5, 7, 6, -1 }, +}; + +const int8_t ff_dca_channel_reorder_nolfe_xch[16][9] = { + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 3, -1, -1, -1, -1, -1 }, + { 0, 1, 2, 3, -1, -1, -1, -1, -1 }, + { 2, 0, 1, 3, 4, -1, -1, -1, -1 }, + { 0, 1, 3, 4, 2, -1, -1, -1, -1 }, + { 2, 0, 1, 4, 5, 3, -1, -1, -1 }, + { 2, 3, 0, 1, 5, 6, 4, -1, -1 }, + { 2, 0, 1, 3, 4, 5, 6, -1, -1 }, + { 0, 5, 3, 4, 1, 2, 6, -1, -1 }, + { 3, 2, 4, 0, 1, 6, 7, 5, -1 }, + { 4, 5, 0, 1, 7, 2, 8, 3, 6 }, + { 3, 2, 4, 0, 1, 5, 8, 7, 6 }, +}; + +const uint16_t ff_dca_vlc_offs[63] = { + 0, 512, 640, 768, 1282, 1794, 2436, 3080, 3770, 4454, 5364, + 5372, 5380, 5388, 5392, 5396, 5412, 5420, 5428, 5460, 5492, 5508, + 5572, 5604, 5668, 5796, 5860, 5892, 6412, 6668, 6796, 7308, 7564, + 7820, 8076, 8620, 9132, 9388, 9910, 10166, 10680, 11196, 11726, 12240, + 12752, 13298, 13810, 14326, 14840, 15500, 16022, 16540, 17158, 17678, 18264, + 18796, 19352, 19926, 20468, 21472, 22398, 23014, 23622, +}; diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h index 28c40cf..0a3139e 100644 --- a/libavcodec/dcadata.h +++ b/libavcodec/dcadata.h @@ -1,7 +1,5 @@ /* * DCA compatible decoder data - * Copyright (C) 2004 Gildas Bazin - * Copyright (c) 2006 Benjamin Larsson * * This file is part of Libav. * @@ -24,7639 +22,49 @@ #define AVCODEC_DCADATA_H #include -#include "libavutil/mem.h" -/* Generic tables */ +extern const uint32_t ff_dca_bit_rates[32]; -static const uint32_t dca_bit_rates[32] = -{ - 32000, 56000, 64000, 96000, 112000, 128000, - 192000, 224000, 256000, 320000, 384000, - 448000, 512000, 576000, 640000, 768000, - 896000, 1024000, 1152000, 1280000, 1344000, - 1408000, 1411200, 1472000, 1536000, 1920000, - 2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/ -}; +extern const uint8_t ff_dca_channels[16]; -static const uint8_t dca_channels[16] = -{ - 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8 -}; +extern const uint8_t ff_dca_bits_per_sample[7]; -static const uint8_t dca_bits_per_sample[7] = -{ - 16, 16, 20, 20, 0, 24, 24 -}; +extern const int16_t ff_dca_adpcm_vb[4096][4]; +extern const uint32_t ff_dca_scale_factor_quant6[64]; +extern const uint32_t ff_dca_scale_factor_quant7[128]; -/* Adpcm data */ +extern const uint32_t ff_dca_lossy_quant[32]; -/* 16bits signed fractional Q13 binary codes */ -static const int16_t adpcm_vb[4096][4] = -{ - { 9928, -2618, -1093, -1263 }, - { 11077, -2876, -1747, -308 }, - { 10503, -1082, -1426, -1167 }, - { 9337, -2403, -1495, 274 }, - { 10698, -2529, -532, -1122 }, - { 10368, -3974, -1264, -750 }, - { 10070, -3667, 346, 863 }, - { 10278, -3093, 311, -576 }, - { 9894, -1330, -1428, -860 }, - { 10544, -1923, -1058, -971 }, - { 10996, -1632, -841, -1404 }, - { 11832, -3465, 1658, -1990 }, - { 10852, -688, -2658, -499 }, - { 10546, -1749, -147, -1733 }, - { 10801, -1004, -708, -1453 }, - { 10588, -441, -2113, -952 }, - { 10141, -3331, -582, -1432 }, - { 9608, -2590, 383, 258 }, - { 11422, -3265, 229, -1544 }, - { 10460, -1338, -713, -1568 }, - { 10306, -1721, -1660, -603 }, - { 9580, -1812, -1235, -1061 }, - { 11471, -2285, -1617, -607 }, - { 10081, -2225, -1408, -868 }, - { 10715, -2624, -1367, -704 }, - { 10616, -1871, -2770, -35 }, - { 9352, -2340, -1024, -1566 }, - { 11065, -1458, -1926, -735 }, - { 11334, -2056, -1041, -1144 }, - { 9825, -2048, -794, -1536 }, - { 11850, -2695, -1123, -867 }, - { 10654, -2226, -1891, -373 }, - { 10024, -1557, -808, -1069 }, - { 11142, -1266, -3238, 128 }, - { 11729, -3282, -514, -1011 }, - { 11402, -2094, -2335, -189 }, - { 10195, -3658, 181, -1875 }, - { 11431, -2626, -404, -1377 }, - { 11001, -3868, -619, -1077 }, - { 10894, -2559, 274, -1758 }, - { 9633, -1482, -2253, -773 }, - { 11245, -3321, 830, -1972 }, - { 9768, -2701, -199, -1859 }, - { 10500, -2042, 525, -2043 }, - { 11669, -4069, 293, -1468 }, - { 9192, -1991, -583, -61 }, - { 10057, -3220, -2015, -473 }, - { 9497, -2315, -2490, -467 }, - { 10455, -3069, -1194, -1007 }, - { 9994, -1936, -60, -1225 }, - { 9295, -2156, -1761, -1134 }, - { 10085, -3748, -1026, 197 }, - { 9334, -2360, 804, -351 }, - { 11561, -2553, 1352, -2313 }, - { 12837, -3998, 1195, -1958 }, - { 10114, -1100, -2414, -394 }, - { 9341, -2530, 315, 755 }, - { 10131, -3164, 1411, -674 }, - { 9535, -905, -1551, 579 }, - { 11717, -1519, -3051, 91 }, - { 9824, -2911, -2775, 192 }, - { 9662, -2934, -561, 1450 }, - { 11085, -3392, -1298, -659 }, - { 8955, -2102, -1899, 703 }, - { 8607, -1742, -4348, 814 }, - { 7640, -2063, -3617, 52 }, - { 7074, -826, -4325, 4375 }, - { 7714, 584, -4238, 1927 }, - { 6355, -952, -4912, 3127 }, - { 7069, -660, -6413, 4087 }, - { 8313, -132, -2964, -876 }, - { 6952, -1422, -3962, -24 }, - { 9299, -734, -3088, -263 }, - { 9484, -574, -4513, 466 }, - { 7246, -91, -3735, -704 }, - { 8325, -1417, -3090, -530 }, - { 6469, -1226, -4757, 829 }, - { 6652, -368, -5682, 1393 }, - { 7971, -1278, -2284, 1205 }, - { 7229, -699, -3556, 1840 }, - { 7994, 1284, -2729, 732 }, - { 9005, -698, -4522, 2189 }, - { 6963, 197, -2727, 380 }, - { 8527, 135, -3991, -213 }, - { 8840, 934, -3014, -567 }, - { 10125, 418, -3284, -371 }, - { 6367, 361, -2318, 2554 }, - { 7892, 172, -5247, 4673 }, - { 6674, 387, -5424, 4398 }, - { 6240, 684, -4047, 1219 }, - { 11170, -794, -5081, 1195 }, - { 11765, -648, -6265, 2052 }, - { 10845, -775, -3837, 366 }, - { 12496, -689, -8260, 3562 }, - { 7893, -1166, -4972, 988 }, - { 8592, 1052, -5986, 3087 }, - { 7277, 1874, -5685, 3579 }, - { 6900, 2016, -4809, 3491 }, - { 8530, -2405, -3250, 1986 }, - { 9426, 494, -7067, 5038 }, - { 10285, 564, -8210, 5370 }, - { 8749, -2207, -3980, 2852 }, - { 9653, -2686, -4300, 1400 }, - { 9770, -2286, -5663, 4233 }, - { 8490, -4, -7048, 4496 }, - { 7697, -1209, -5328, 3183 }, - { 6451, 801, -4324, -554 }, - { 7387, 1806, -5265, 545 }, - { 7450, -2302, -4445, 1418 }, - { 8817, -1370, -5827, 2168 }, - { 10324, -2406, -5629, 2579 }, - { 8863, -2578, -3537, 467 }, - { 6901, -1624, -3169, 3392 }, - { 7846, 156, -6948, 3381 }, - { 7928, -1115, -5972, 4816 }, - { 6089, -599, -4368, -320 }, - { 7833, 1246, -3960, -621 }, - { 8931, 2521, -6768, 2052 }, - { 8900, 1944, -4126, 40 }, - { 7661, -34, -2855, 2480 }, - { 5873, 474, -3262, 3712 }, - { 7535, -234, -4699, 216 }, - { 5856, 143, -5142, 73 }, - { 8944, -106, -5874, 3663 }, - { 7134, 426, -5879, 2895 }, - { 10199, 1011, -4762, 369 }, - { 8454, 264, -5971, 1291 }, - { 7822, -2449, -4333, 4540 }, - { 6200, -2758, -2632, 1497 }, - { 6070, -4315, -2699, 414 }, - { 7047, -3739, -3210, 1060 }, - { 5675, -3801, -2717, -407 }, - { 4789, -4063, -2628, -744 }, - { 4023, -3366, -3133, -726 }, - { 4296, -2407, -3381, -513 }, - { 4388, -2931, -2820, 1512 }, - { 4559, -4233, -1941, 1976 }, - { 6702, -3208, -1755, 1680 }, - { 4416, -3521, -1052, 2984 }, - { 7154, -4266, -1203, 3732 }, - { 3625, -4242, -3244, 1395 }, - { 6518, -2856, -1304, 2887 }, - { 6170, -1949, -3014, 3973 }, - { 5189, -2451, -4020, 3477 }, - { 6218, -2988, -1921, 3844 }, - { 4827, -3688, -1928, 3343 }, - { 6668, -3991, -2805, 3095 }, - { 5297, -3115, -3684, 2390 }, - { 5354, -4614, -2662, 1504 }, - { 4196, -3091, -4147, 1135 }, - { 3540, -2893, -4007, 100 }, - { 5569, -1602, -4007, 1909 }, - { 4341, -2091, -4272, 252 }, - { 5559, -2878, -3832, 498 }, - { 4548, -4479, -2898, -27 }, - { 5176, -2494, -4635, 1476 }, - { 3294, -3485, -3738, 716 }, - { 4920, -1229, -4195, -365 }, - { 3257, -3518, -3349, 2862 }, - { 5286, -1948, -3485, -778 }, - { 6502, -3051, -152, 2854 }, - { 5864, -4192, -1076, 3451 }, - { 4656, -3122, -3448, 179 }, - { 5907, -754, -1596, 3116 }, - { 7229, -3680, -1590, 2892 }, - { 5107, -3888, -3364, 806 }, - { 6764, -2635, -3450, 134 }, - { 5258, -2827, -2844, -1052 }, - { 5798, -1725, -4305, 205 }, - { 5404, -1213, -3362, 449 }, - { 6224, -2738, -3046, -581 }, - { 4223, -2438, -2725, 3745 }, - { 4751, -3411, -2123, 116 }, - { 3868, -3000, -3954, 2297 }, - { 6819, -2899, -4277, 2825 }, - { 4207, -4754, -2808, 865 }, - { 4804, -1494, -1997, 4688 }, - { 5282, -2213, -548, 3559 }, - { 5580, -1912, -566, 4370 }, - { 6168, -2857, -672, 4053 }, - { 6583, -4515, -2850, 1670 }, - { 6511, -3093, -3988, 1421 }, - { 4646, -1790, -1443, 3650 }, - { 5915, -924, -2020, 896 }, - { 7814, -4181, -3152, 2007 }, - { 6190, -2238, -4817, 2279 }, - { 4737, -4034, -3288, 1835 }, - { 8161, -3633, -3423, 3137 }, - { 7415, -2351, -2088, 4290 }, - { 4106, -2517, -62, 2905 }, - { 4909, -3145, -614, 4112 }, - { 4938, -3281, -397, 1100 }, - { -173, 919, 1589, -5363 }, - { -13, 796, -295, -6655 }, - { -1860, -829, 1141, -4555 }, - { 2298, -838, -664, -5005 }, - { -884, -1097, 2074, -4613 }, - { -101, 281, 2846, -4535 }, - { 1166, 453, 2429, -5910 }, - { 879, -664, 2370, -5452 }, - { 1415, -370, -1699, -4727 }, - { -1413, 1277, -669, -6649 }, - { 2133, 304, -968, -4624 }, - { 380, 586, -2087, -4892 }, - { 1336, 275, -82, -5789 }, - { -2459, 1057, -34, -5416 }, - { 2278, -1758, 866, -5653 }, - { 1945, -2295, -149, -5302 }, - { 1287, -3525, 996, -5255 }, - { 2297, 803, 1177, -6067 }, - { 187, -180, -619, -6202 }, - { -793, -2537, 1554, -5057 }, - { -2703, -204, -629, -5853 }, - { -1007, -146, 313, -5582 }, - { 830, 357, 869, -6363 }, - { -228, -575, -3177, -4433 }, - { -1001, -1553, -142, -5708 }, - { -1644, 1683, 1721, -4533 }, - { 893, 1924, -15, -5791 }, - { 2195, 2061, -262, -5471 }, - { 3031, 270, 311, -5096 }, - { 1912, 1638, -1523, -4677 }, - { -3142, -55, 253, -4914 }, - { 356, -1680, 343, -6123 }, - { -2241, -1734, -976, -5939 }, - { -2196, -2893, 547, -4938 }, - { -1245, 126, -1916, -5419 }, - { -249, -3755, -1422, -5594 }, - { 575, -2683, -1926, -4566 }, - { -762, 1885, 192, -5880 }, - { -811, -2562, -1068, -6013 }, - { -2264, -3086, -976, -4775 }, - { 70, -1215, 2880, -4410 }, - { 714, -3760, 2916, -4691 }, - { -244, -3404, 1740, -4493 }, - { 684, -5137, -328, -5608 }, - { -529, -3825, -1786, -4535 }, - { -713, -4743, -1118, -5546 }, - { 2718, -3788, 1798, -5708 }, - { -1639, -3679, -1564, -6095 }, - { 1693, -2642, -1389, -4539 }, - { 505, -1573, -1651, -4878 }, - { -835, -2256, -1941, -5352 }, - { 1464, -411, 1993, -6441 }, - { 493, -3184, -145, -6148 }, - { -1413, 499, -1617, -6479 }, - { -294, 1722, -1419, -5725 }, - { -2937, -1528, -175, -4624 }, - { -594, -5911, -56, -6146 }, - { -300, -4275, 1156, -5947 }, - { 552, -2643, 2669, -3959 }, - { 905, -4158, 1789, -5809 }, - { 1336, -2009, 2108, -5903 }, - { 1555, -3600, 1110, -6759 }, - { -1294, -3464, 77, -6084 }, - { -1139, -4006, -1270, -4181 }, - { -5094, -3296, 1092, -2847 }, - { -5503, -2883, 1984, -2067 }, - { -4671, -4218, -1417, -4132 }, - { -3763, -3818, 1262, -3082 }, - { -5132, -3430, 2928, -728 }, - { -5957, -2877, 1251, -2446 }, - { -4425, -2319, -212, -4276 }, - { -6201, -1993, 1774, -2182 }, - { -5500, -3836, 2201, -1396 }, - { -6934, -2334, 2366, -1293 }, - { -6124, -4140, 1337, -1977 }, - { -6553, -4186, 1756, -1325 }, - { -5126, -1258, 744, -3656 }, - { -5167, -1390, 1581, -2895 }, - { -4525, -3398, 2429, -1865 }, - { -4076, -3183, 2027, -2510 }, - { -6191, -3274, 1838, -1814 }, - { -4454, -2753, 2723, -1185 }, - { -6655, -4797, 251, -2595 }, - { -6332, -2232, 1832, 217 }, - { -5869, -1698, 134, 340 }, - { -6614, -1045, 2126, -1932 }, - { -4859, -2107, 2010, -2435 }, - { -6274, -1622, 2808, -1374 }, - { -3119, -3209, 521, -3988 }, - { -5676, -2082, -420, -2711 }, - { -7073, -3623, 696, -2343 }, - { -5986, -4224, 572, -2454 }, - { -4340, -4521, 882, -2771 }, - { -6178, -1933, 535, -1444 }, - { -4923, -4163, 1744, -2066 }, - { -6410, -1519, 1058, -2683 }, - { -5077, -1185, 856, -2216 }, - { -7091, -2444, 687, -2597 }, - { -5284, -2165, 3239, -993 }, - { -4763, -1497, 197, -3179 }, - { -4128, -4958, -396, -3578 }, - { -5054, -3878, -647, -2672 }, - { -7005, -3348, 1679, -1579 }, - { -5767, -1017, 2582, -1915 }, - { -7069, -2787, 1331, -2070 }, - { -5532, -2296, 706, -2950 }, - { -5059, -3543, -821, -3637 }, - { -6639, -1835, 1016, -696 }, - { -5611, -5220, -694, -3371 }, - { -5994, -2803, 2933, -729 }, - { -5948, -619, 1596, -2676 }, - { -5486, -4419, 153, -3265 }, - { -4329, -3440, 1646, -1439 }, - { -4083, -3978, 177, -3569 }, - { -4289, -2599, 1224, -3075 }, - { -5707, -3253, 1912, -759 }, - { -6606, -3437, 2562, -571 }, - { -5254, -2444, 769, -352 }, - { -6545, -3154, 582, -1103 }, - { -5328, -2241, 2566, -1775 }, - { -7216, -1936, 1538, -1983 }, - { -3730, -2451, 426, -3869 }, - { -5110, -1385, 2031, -1169 }, - { -6470, -2715, 269, -3123 }, - { -5806, -2480, -97, -3832 }, - { -3683, -4916, -490, -4330 }, - { -6341, -2083, -669, -115 }, - { -4913, -4079, -837, -4673 }, - { -3274, -2497, 2334, -2652 }, - { -1286, -1731, 2550, -3756 }, - { -3375, -877, 926, -3977 }, - { -2525, -2079, 2879, -2625 }, - { -5308, -504, 3111, -1607 }, - { -4904, 460, 4093, -1232 }, - { -1993, 1616, 4656, -1913 }, - { -3481, -1176, 3119, -2236 }, - { -4132, -1502, 2339, -2545 }, - { -2542, 1151, 3569, -2550 }, - { -4381, 430, 3147, -2082 }, - { -3888, 867, 3899, -1657 }, - { -2861, 1290, 4202, -1979 }, - { -3893, -253, 2363, -2764 }, - { -1705, 688, 3827, -2923 }, - { -2223, 2312, 3700, -3148 }, - { -1986, -720, 5021, -795 }, - { -3177, 242, 1952, -3352 }, - { -1854, 1509, 2528, -3815 }, - { -3173, 97, 5019, -706 }, - { -2689, -145, 1375, -3915 }, - { -4838, -385, 2488, -2427 }, - { -4557, -355, 1603, -3060 }, - { -3522, 1832, 3292, -2674 }, - { -3769, 780, 2378, -2704 }, - { -4323, -1932, 3414, -1169 }, - { -2740, 1158, 2729, -3273 }, - { -3647, 210, 1464, -2892 }, - { -2342, -2097, 1513, -3727 }, - { -4422, -1242, 3130, -1833 }, - { -1308, -1039, 4290, -1875 }, - { -1754, -2535, 3298, -2314 }, - { -4102, -186, 4037, -1094 }, - { -1008, 1570, 3290, 171 }, - { -3322, -2621, 2791, -1536 }, - { -2539, -2597, 3442, -1672 }, - { -3411, -2015, 3670, -1174 }, - { -2097, 730, 5581, -1399 }, - { -1510, -74, 4820, -2004 }, - { -4086, -868, 4425, -771 }, - { -956, -986, 3640, -2925 }, - { -2087, -1250, 3464, -2458 }, - { -3308, -2411, 1334, -3667 }, - { -2264, -389, 4004, -1854 }, - { -680, 239, 4058, -3388 }, - { -1357, 30, 2993, -3658 }, - { -3601, -552, 1177, -1136 }, - { -2641, 442, 4374, -1625 }, - { -2525, 770, 1640, -3895 }, - { -3172, -891, 3893, -1608 }, - { -2996, 13, 3277, -2414 }, - { -899, 1055, 4470, -2501 }, - { -422, -584, 3475, -3787 }, - { -1978, -593, 2566, -3415 }, - { -3150, -1280, 2362, -3047 }, - { -3592, 224, 1026, -3932 }, - { -4840, -1189, 3633, -879 }, - { -3952, -2255, 2916, -1826 }, - { -1695, 28, 1810, -349 }, - { -745, -2484, 3308, -3293 }, - { -1016, 1563, 5365, -1823 }, - { -2172, -1787, 4266, -1287 }, - { -1241, -1951, 3982, -2413 }, - { -2009, -2639, 2330, -3480 }, - { 5105, -1618, -2588, -2015 }, - { 6497, -1523, -3218, -910 }, - { 6526, -2305, -2029, -1790 }, - { 5289, -99, -3436, -400 }, - { 5781, -1623, -1577, -2617 }, - { 5259, -670, -3125, -1700 }, - { 6343, -1256, -331, -3222 }, - { 7967, -678, -2195, -1462 }, - { 6119, -695, -2988, -1538 }, - { 6108, 494, -3359, -1548 }, - { 5067, 969, -2328, -2707 }, - { 7595, -435, -1497, -2056 }, - { 6929, -719, -2420, -1665 }, - { 5190, 584, -2982, -2103 }, - { 6106, -444, -1411, -2739 }, - { 5584, 289, -1804, -2803 }, - { 5276, 227, -1180, -3361 }, - { 7544, -1525, -1834, -1725 }, - { 5986, -1470, -2606, -1701 }, - { 5096, -765, -1712, -3006 }, - { 5423, -149, -3933, -1157 }, - { 7651, 26, -2445, -1507 }, - { 4745, -464, -1735, -2362 }, - { 5352, -1011, -1094, -1999 }, - { 6300, -672, -542, -1950 }, - { 6675, -1020, -1318, -1059 }, - { 7218, -2036, -603, -2462 }, - { 7755, -1514, -2430, -1229 }, - { 5041, 449, -1056, -2405 }, - { 6710, -2277, -1344, -2284 }, - { 6824, -1347, -2254, 251 }, - { 6068, -1857, -983, -1316 }, - { 5603, -2177, -2730, -1477 }, - { 5838, -1059, -3604, -970 }, - { 5076, -789, -335, -2413 }, - { 6191, -1634, -2000, -2129 }, - { 5092, -1292, -2543, -1034 }, - { 5305, 435, -1710, -1850 }, - { 6140, 561, -2176, -2380 }, - { 6752, 348, -2496, -1890 }, - { 6405, 273, -1098, -2778 }, - { 6942, -1340, -496, -1381 }, - { 5238, -687, -2454, -2349 }, - { 6959, -882, -1833, -2061 }, - { 6292, -253, -2125, -2199 }, - { 5838, -574, -759, -3215 }, - { 6954, -1484, -640, -2771 }, - { 7498, -1706, -1210, -2154 }, - { 6772, -1003, -1235, -2532 }, - { 6014, 228, -2154, -1108 }, - { 6943, -2178, -2644, -1122 }, - { 7262, -763, -3056, -1090 }, - { 6273, -1478, -1072, 177 }, - { 4734, 425, -2912, 357 }, - { 7129, 168, -1537, -2327 }, - { 7204, -434, -746, -2660 }, - { 6879, 57, -3087, -1310 }, - { 4623, -610, -718, -3459 }, - { 6565, -543, -1998, -339 }, - { 4752, -277, -2066, -1405 }, - { 7435, -1416, -1904, -505 }, - { 4076, 150, -1222, -3556 }, - { 7082, -28, -1456, -1174 }, - { 5941, -446, -1326, -1158 }, - { 3870, -1648, -2474, -2589 }, - { 858, 37, -3387, -3721 }, - { 3557, -1503, -1664, -3383 }, - { 3336, -1972, -3079, -2216 }, - { 3186, 60, -4185, -863 }, - { 3456, -773, -3066, -2457 }, - { 4131, -913, -2060, -2601 }, - { 4431, -691, -4114, -972 }, - { 3461, -334, -3680, -1751 }, - { 2006, -459, -2214, -3827 }, - { 1322, 32, -2816, -3203 }, - { 4425, -1897, -2791, -1946 }, - { 4504, 23, -3421, -1909 }, - { 3090, -885, -2366, -3264 }, - { 3209, -2363, -3730, -834 }, - { 3312, -1471, -3641, -1579 }, - { 4184, -1669, -3323, -1248 }, - { 2190, -931, -3302, -2944 }, - { 2947, -229, -4791, -1195 }, - { 2020, -1626, -2700, -3125 }, - { 2214, -326, -4352, -1683 }, - { 3286, -2619, -2412, -2458 }, - { 1000, -2571, -4129, -2158 }, - { 2496, -2627, -3611, -1433 }, - { 2043, -2191, -2167, -3827 }, - { 2571, -2544, -1915, -3222 }, - { 2022, -1501, -3856, -2165 }, - { 2685, -1180, -1461, -4038 }, - { 1610, -2313, -4391, -1173 }, - { 2340, -2490, -4215, -516 }, - { 1742, -2615, -3632, -2146 }, - { 523, -1293, -4246, -2442 }, - { 3725, -2723, -3014, -1576 }, - { 3554, -1381, -4200, -824 }, - { 1291, -1594, -4777, -1430 }, - { 1452, 515, -2960, -3830 }, - { 4264, -894, -3305, -1826 }, - { 2606, -1452, -4522, -966 }, - { 1196, -830, -4807, -1816 }, - { 1054, -775, -2616, -4071 }, - { 4206, 415, -4344, -1132 }, - { 3044, 491, -4126, -1934 }, - { 988, -901, -3353, -3443 }, - { 1729, -3063, -2267, -3370 }, - { 3915, 912, -2989, -2387 }, - { 3781, 300, -2457, -3050 }, - { 2712, 924, -1350, -1206 }, - { 4230, 405, -2343, 665 }, - { 1878, -873, -225, -29 }, - { 3510, 56, -1334, -3420 }, - { 2850, 1447, -2651, -3150 }, - { 1510, -706, -4125, -2483 }, - { 3115, 793, -1692, -3894 }, - { 2667, 213, -2973, -2786 }, - { 1184, -2384, -3051, -3173 }, - { 2139, 796, -2079, -3697 }, - { 1464, -1483, -3726, -2754 }, - { 2407, -1148, -3915, -1569 }, - { 2612, -1779, -3217, -2271 }, - { 2406, -2870, -2937, -2496 }, - { 2140, 126, -3646, -2758 }, - { 2952, -1036, 268, -1423 }, - { 93, -1931, -3841, -3535 }, - { 389, -2953, -3383, -3343 }, - { 8652, -5511, -1662, 565 }, - { 7427, -2791, -2535, -842 }, - { 8541, -4253, -1407, -988 }, - { 8018, -3203, -2998, 105 }, - { 7231, -3926, -958, 1308 }, - { 7331, -3690, -363, 2586 }, - { 6803, -3646, -2226, -903 }, - { 8163, -2811, -477, -2235 }, - { 9356, -3818, -1685, -684 }, - { 8466, -2854, -302, -698 }, - { 8458, -3224, 517, 279 }, - { 8074, -2619, -1326, 2596 }, - { 8779, -2761, -2527, -441 }, - { 6533, -2887, -899, -696 }, - { 7394, -2305, -1642, -120 }, - { 8281, -3780, -22, 1305 }, - { 9158, -4413, -779, 901 }, - { 9031, -5240, -1109, 1678 }, - { 8717, -3650, 410, -1075 }, - { 7317, -3197, -818, -2264 }, - { 7934, -2385, -1214, -1886 }, - { 8256, -4441, -291, -587 }, - { 7358, -3395, 1090, -270 }, - { 9446, -4910, -1343, -473 }, - { 8187, -4726, -808, 1166 }, - { 7504, -3845, -47, 267 }, - { 8029, -2146, -1283, -383 }, - { 7461, -2705, -853, 783 }, - { 9367, -3636, -645, -354 }, - { 8955, -3473, -308, -1947 }, - { 8676, -2683, -2099, 1485 }, - { 7481, -3003, -871, -444 }, - { 8015, -2839, -1673, 1175 }, - { 6947, -4643, -1527, -1047 }, - { 7622, -2575, -137, -960 }, - { 9388, -4279, -707, -1322 }, - { 8382, -5259, -1283, -565 }, - { 6856, -4138, -1030, 630 }, - { 8659, -2571, -1124, -1666 }, - { 8763, -3807, -537, 2543 }, - { 8049, -3578, -2186, -604 }, - { 8272, -2351, -1985, -1214 }, - { 6855, -3796, -1527, -1631 }, - { 7178, -2896, -1600, -1756 }, - { 7040, -2888, -89, -1586 }, - { 6261, -3403, -264, 998 }, - { 7756, -4699, -1543, -834 }, - { 7682, -4622, -758, -1721 }, - { 8839, -4232, -2932, 1959 }, - { 9363, -4679, -1956, 39 }, - { 7883, -3616, -1414, -1432 }, - { 8828, -3188, -1356, -1312 }, - { 7746, -3987, -121, -2424 }, - { 9262, -3256, -693, 818 }, - { 7670, -3420, -148, 3504 }, - { 7344, -3183, 608, 1595 }, - { 8976, -4139, -1848, 1304 }, - { 6708, -4131, 33, -852 }, - { 7840, -4429, -2275, 79 }, - { 8980, -3858, -2838, 453 }, - { 7815, -4604, -2563, 944 }, - { 8372, -4422, -1783, 3071 }, - { 8623, -5128, -1754, 2888 }, - { 7462, -3281, 889, 920 }, - { 8416, -59, -1320, -1825 }, - { 7928, -1488, -414, -2499 }, - { 8110, -977, -1047, -2042 }, - { 8278, -687, -1597, -1550 }, - { 7988, -174, -977, -2106 }, - { 8609, -1547, -1628, -1527 }, - { 9000, -1798, -946, -1761 }, - { 8954, -872, -1404, -1594 }, - { 8939, 466, -748, -1212 }, - { 9549, -329, -177, -1360 }, - { 9411, -18, -1126, -1568 }, - { 8859, -782, -488, -1338 }, - { 8955, -218, -43, -1209 }, - { 9131, -69, -453, -1001 }, - { 9069, -1519, -1091, -1199 }, - { 9247, -1309, -566, -1146 }, - { 8528, -1617, -287, -1313 }, - { 7763, -745, -149, -2040 }, - { 8294, -343, 257, -2633 }, - { 10149, -893, -552, -1649 }, - { 9398, -915, 218, -2042 }, - { 9703, -1194, -675, -1592 }, - { 9586, -700, -427, -1710 }, - { 8930, 497, -1445, -1218 }, - { 9285, -1323, -163, -1552 }, - { 8431, -1289, -985, -1404 }, - { 8965, -655, 653, -1483 }, - { 9542, -1001, -951, -1128 }, - { 9205, -647, -37, -882 }, - { 8603, -56, 514, -1793 }, - { 9300, -12, -1324, -567 }, - { 8773, 238, -184, -1456 }, - { 9941, -1306, -69, -1792 }, - { 9360, 279, -376, -1919 }, - { 9180, -285, 95, -2170 }, - { 9922, -501, -970, -1570 }, - { 8341, -1493, -856, -2092 }, - { 8780, -981, -850, -1014 }, - { 9721, -548, -1504, -1094 }, - { 9973, -1493, 482, -2105 }, - { 8707, -333, -1027, -1087 }, - { 9098, -469, -315, -1723 }, - { 8879, -1050, -661, -2020 }, - { 8857, 602, -866, -1918 }, - { 8945, -1025, -2154, -1071 }, - { 8484, -1930, -468, -2179 }, - { 9177, -1903, -224, -2112 }, - { 8652, -137, -2097, -1214 }, - { 9063, -973, -1405, -772 }, - { 9328, -456, 662, -2469 }, - { 10101, -697, 127, -2113 }, - { 9685, 811, -2359, -1024 }, - { 8586, -94, -460, -1982 }, - { 7924, -141, -509, -2513 }, - { 7773, -669, -107, -2835 }, - { 8636, -1064, -46, -2409 }, - { 9748, 596, -1815, -1349 }, - { 8924, 304, 547, -2614 }, - { 9442, 746, -1153, -1679 }, - { 9454, -278, -529, -1976 }, - { 8488, 561, -32, -2160 }, - { 10083, -63, -1544, -1364 }, - { 9390, -1278, 568, -1131 }, - { 9740, -49, -2253, -910 }, - { 3636, -2391, -1115, -3614 }, - { 6014, -3204, -1902, -1808 }, - { 5787, -3497, -1116, -2590 }, - { 4365, -3046, -1632, -2668 }, - { 4733, -2192, -2029, -2468 }, - { 5412, -2753, -1633, -2464 }, - { 4455, -3375, -767, -3399 }, - { 4456, -1644, -983, -2841 }, - { 4039, -2523, 38, -3967 }, - { 3406, -2662, 72, -4757 }, - { 4279, -2005, 1055, -4399 }, - { 4321, -1377, -860, -3786 }, - { 3743, -5739, -651, -3047 }, - { 3528, -5510, 361, -4060 }, - { 6496, -4886, -136, -2689 }, - { 4513, -5254, 551, -4010 }, - { 6557, -3413, -92, -3063 }, - { 4186, -2059, 187, 47 }, - { 6210, -4117, -1256, -1985 }, - { 6038, -4343, 351, -2124 }, - { 4305, -4780, -2077, -1897 }, - { 4480, -3815, -2228, -1533 }, - { 5582, -3689, 1221, -3429 }, - { 5532, -4874, 1195, -2765 }, - { 6518, -2853, -905, -2568 }, - { 5467, -2192, 470, -4115 }, - { 4139, -1577, 240, -3493 }, - { 5281, -1926, -729, -3340 }, - { 5214, -2870, 1359, -4289 }, - { 3046, -3510, -1536, -3214 }, - { 5433, -2881, -1230, -1184 }, - { 4861, -3932, -1071, -2791 }, - { 5693, -4234, -1906, -1502 }, - { 4004, -3935, -1804, -2383 }, - { 3728, -3792, 681, -4773 }, - { 3621, -3030, -1951, -2598 }, - { 5133, -3903, 44, -3700 }, - { 3561, -3451, 1183, -5301 }, - { 5026, -2762, -2341, -1780 }, - { 5841, -2492, -467, -3210 }, - { 5591, -1791, 497, -2472 }, - { 5054, -3898, -1822, -2097 }, - { 5813, -2792, 83, -1469 }, - { 4432, -4497, 1670, -5193 }, - { 5338, -4653, -1109, -2200 }, - { 3239, -4401, -648, -3655 }, - { 2147, -3598, -1200, -4242 }, - { 4417, -2271, -1552, -3210 }, - { 6494, -4360, 852, -3565 }, - { 2393, -6358, -856, -4524 }, - { 4959, -4196, -847, -1403 }, - { 4924, -5438, -226, -3026 }, - { 4254, -5303, -1306, -2424 }, - { 4121, -3126, -2334, -1981 }, - { 3437, -4443, -1464, -2953 }, - { 3203, -3459, -529, -4339 }, - { 5896, -5945, 543, -3246 }, - { 1987, -4733, -220, -4863 }, - { 4358, -4431, -514, -3081 }, - { 4583, -2416, -492, -2287 }, - { 2943, -5035, 419, -4927 }, - { 5358, -5129, 987, -4309 }, - { 4460, -3392, 1752, -5634 }, - { 3415, -4633, 1507, -5945 }, - { 811, -4692, -445, 2333 }, - { 1009, -5613, -1857, 1360 }, - { 1338, -2712, -2720, 3036 }, - { 1002, -3754, -2582, 2344 }, - { 750, -4608, -2334, 714 }, - { 2043, -3207, -2822, 2173 }, - { -140, -4654, -2953, 357 }, - { -54, -4026, -2376, 2695 }, - { 1858, -5022, -717, 2287 }, - { 2064, -3894, -722, 3255 }, - { 2727, -4558, -332, 2603 }, - { 1810, -5378, 283, 1826 }, - { 3935, -4326, 762, 3383 }, - { -767, -4697, -2510, 1922 }, - { 2146, -4312, -3090, 1641 }, - { 54, -5881, -2114, 921 }, - { 1992, -5766, -640, 1574 }, - { 1200, -5371, -1114, 1828 }, - { 2973, -5337, 34, 2266 }, - { 1531, -5018, -2817, 1192 }, - { 3078, -4570, 117, 1990 }, - { 924, -4286, -1388, 2713 }, - { 142, -5058, -2848, 1487 }, - { -106, -6180, -881, 842 }, - { 673, -5433, -229, 1596 }, - { 783, -5710, -2784, 562 }, - { 1935, -5729, -2009, 856 }, - { -410, -3375, -3326, 2734 }, - { 234, -3000, -2628, 3260 }, - { 733, -3405, -3806, 1589 }, - { 771, -4285, -3544, 1314 }, - { 1192, -3563, -3960, 2178 }, - { 206, -5555, -1250, 1546 }, - { -130, -3815, -1210, 3041 }, - { 646, -3940, -393, 2992 }, - { -184, -4931, -1767, 1925 }, - { 2746, -5120, -2275, 1464 }, - { 2440, -3731, -3352, 2729 }, - { -490, -4942, -3779, 997 }, - { 68, -2636, -4167, 3778 }, - { 48, -3986, -4118, 2106 }, - { -978, -5486, -1336, 1390 }, - { 1126, -5297, -855, 640 }, - { -472, -3975, -3622, 1557 }, - { 2456, -5344, -1523, 1648 }, - { -774, -5652, -2417, 1147 }, - { 995, -6122, -812, 1132 }, - { 3282, -4571, -1763, 2175 }, - { 3655, -3862, -676, 3568 }, - { 3038, -3647, -1672, 3381 }, - { 2595, -2964, -2772, 3263 }, - { 4176, -3353, -1148, 4354 }, - { 1603, -3442, -1500, 3444 }, - { 828, -6226, -1783, 678 }, - { 1421, -3333, -3080, 3403 }, - { 1121, -4727, -1924, 1984 }, - { -186, -5083, -682, 1796 }, - { 819, -2778, -3488, 530 }, - { 421, -2873, -3832, 2596 }, - { 2164, -4263, -1605, 2282 }, - { 585, -4437, -682, -491 }, - { -644, -4452, -1157, 2325 }, - { 1991, -4299, 210, 2834 }, - { 2135, -3632, -2113, 665 }, - { -7482, -2724, -2662, -1380 }, - { -6983, -2166, -3756, -3509 }, - { -7085, -1439, -2397, -3112 }, - { -7760, -3049, -3319, -2822 }, - { -8413, -2760, -4406, -3298 }, - { -5995, -3943, -1260, -3750 }, - { -7879, -1554, -3464, -2606 }, - { -6314, -2034, -3878, -1681 }, - { -8849, -2084, -1399, -1231 }, - { -7153, -2602, -1384, -817 }, - { -8041, -2571, -407, -2785 }, - { -7246, -2233, -1578, 260 }, - { -7336, -3883, -4061, -1342 }, - { -7619, -3908, -2342, 382 }, - { -8684, -3724, -1662, -727 }, - { -7850, -2922, -1770, -3449 }, - { -6766, -2034, -1293, -1988 }, - { -6895, -2116, -968, -3744 }, - { -7136, -5147, -2618, -2809 }, - { -8224, -3724, -2519, -1589 }, - { -6711, -2750, -3021, -219 }, - { -8059, -1638, -1102, -3175 }, - { -8710, -4839, -3963, -3143 }, - { -9363, -4965, -3257, -1002 }, - { -6099, -1751, -3157, -395 }, - { -6453, -3216, -4597, -483 }, - { -7879, -5477, -839, -2638 }, - { -7202, -4038, -526, -2856 }, - { -8022, -1228, -1910, -1646 }, - { -9117, -1393, -1582, -2535 }, - { -9095, -2693, -636, -2605 }, - { -9076, -2580, -3481, -2519 }, - { -8327, -4859, -2422, 83 }, - { -8368, -2129, -2324, -2173 }, - { -8554, -4563, -3842, -2007 }, - { -10462, -4261, -1934, -2084 }, - { -9717, -3187, -2294, -1896 }, - { -9625, -3889, -3020, -3224 }, - { -9857, -4955, -4239, -2184 }, - { -9752, -2351, -2277, -3129 }, - { -7219, -1302, -2639, -1603 }, - { -7477, -4360, -3718, -559 }, - { -5680, -2033, -2326, -3078 }, - { -10190, -5548, -4643, -3601 }, - { -9431, -4121, -879, -2479 }, - { -8365, -5450, -2020, -1439 }, - { -6289, -5178, -1605, -3845 }, - { -8319, -3866, -687, -2792 }, - { -8131, -1031, -3608, -3947 }, - { -10510, -2560, -1199, -2082 }, - { -11015, -3640, -2748, -3041 }, - { -8762, -5022, -5231, -1162 }, - { -10153, -2715, -4648, -4859 }, - { -7930, -5205, -1900, -3600 }, - { -9561, -3548, -4812, -3722 }, - { -7663, -4709, -1180, -1475 }, - { -9073, -5707, -1815, -2980 }, - { -8602, -2363, -2675, -3770 }, - { -9967, -5614, -3575, -3838 }, - { -8324, -1005, -2131, -3254 }, - { -10331, -5737, -2550, -2940 }, - { -8234, -3354, -3361, -4479 }, - { -8140, -1951, -4526, -4545 }, - { -6679, -2662, -2284, -4182 }, - { -1122, -1514, -6427, -212 }, - { 54, -1660, -5424, -1404 }, - { 254, -2778, -5222, 846 }, - { -267, -1661, -6577, 814 }, - { -305, -2021, -5759, 1484 }, - { -1791, -2446, -6867, -86 }, - { -2929, -3158, -6603, -1799 }, - { -1391, -3189, -5557, -1053 }, - { -1602, -884, -6767, -1213 }, - { -361, -318, -6219, -44 }, - { -4078, -2635, -5523, -433 }, - { -956, 478, -4382, 1470 }, - { -3300, -2462, -6021, -2721 }, - { 708, -2434, -5085, -540 }, - { -2435, -3607, -5647, -2110 }, - { -491, -1134, -4681, -2886 }, - { 87, -3435, -4641, -1194 }, - { -586, -2927, -4784, 366 }, - { -1394, -2326, -6021, 350 }, - { 97, -2519, -4678, -2120 }, - { -1547, -1907, -5069, -2993 }, - { 268, -3724, -4719, 127 }, - { -827, -1190, -5912, 1144 }, - { -3959, -2322, -6898, -1974 }, - { -2728, -2228, -6426, -562 }, - { -456, -666, -5785, -1609 }, - { 531, -1096, -5731, -656 }, - { -3569, -688, -3915, 110 }, - { -4752, -1725, -4393, -377 }, - { -3210, -3315, -6960, -840 }, - { -688, -3416, -4971, 1221 }, - { -1833, 77, -6491, -2434 }, - { -239, -255, -6850, -886 }, - { -2112, -1490, -6291, -2689 }, - { -1544, -4579, -5198, -1261 }, - { -2771, -4014, -5520, 683 }, - { -1635, -2829, -5512, 1214 }, - { -958, -2582, -4823, 2360 }, - { -2077, -4566, -4642, 365 }, - { -3112, -4214, -5960, -823 }, - { -2467, -2510, -4858, 1467 }, - { -1561, -3399, -5822, 211 }, - { -775, -1081, -4424, 2636 }, - { -1263, 25, -6378, -1392 }, - { -3476, -366, -5417, -1393 }, - { -3176, -1476, -4149, 1466 }, - { -2479, 518, -4448, -257 }, - { -2992, 158, -4660, -1279 }, - { -1320, -3872, -4479, 1147 }, - { -1475, -312, -5318, 539 }, - { -3527, -1679, -5860, -1681 }, - { -3397, -3438, -5593, 1866 }, - { -4089, -2439, -4763, 1275 }, - { -748, -4513, -4687, -48 }, - { -2166, -4531, -4691, -2856 }, - { -2385, -853, -6035, -627 }, - { -1194, -4091, -4472, -1963 }, - { -682, -3234, -4084, -3033 }, - { -3255, -5015, -5328, -12 }, - { -2313, -3436, -4601, -155 }, - { -2792, -1038, -6947, -2019 }, - { -1244, -1526, -5771, -1882 }, - { -4679, -3731, -5506, 283 }, - { -3062, -66, -3558, -758 }, - { -4895, -1187, 4751, 3728 }, - { -7600, -2752, 3320, 4613 }, - { -5703, -2975, 3944, 2659 }, - { -4972, -1257, -246, 2952 }, - { -4221, -2487, 1702, 4295 }, - { -2900, -1529, 2458, 4935 }, - { -5061, 407, 2416, 4050 }, - { -6931, -3478, 2761, 2213 }, - { -6037, -3921, 3192, 1866 }, - { -6113, -811, 2407, 3782 }, - { -5878, -1716, 1207, 3478 }, - { -5953, -2853, 2207, 2712 }, - { -6807, -3223, 2749, 3595 }, - { -3272, -3157, 1389, 3788 }, - { -5368, -1904, 1980, 5077 }, - { -7235, -1398, 3075, 4548 }, - { -4765, -3487, 2755, 2796 }, - { -7658, -4435, 2694, 2582 }, - { -6997, -4282, 456, 3832 }, - { -5563, -3115, -63, 3713 }, - { -4244, -4220, 1450, 2767 }, - { -3801, -2194, 190, 4303 }, - { -5458, -4119, 1958, 2274 }, - { -7300, -3469, 3514, 3193 }, - { -4594, -2067, 775, 4752 }, - { -3389, -1654, 1464, 5412 }, - { -4845, -3483, 964, 3437 }, - { -6007, -2818, 1666, 4659 }, - { -8709, -5007, 1757, 3287 }, - { -5833, -4389, 1025, 3171 }, - { -5788, -1780, 3944, 3661 }, - { -4430, -920, 1938, 4753 }, - { -7066, -1857, 4591, 4538 }, - { -3549, -513, 1427, 5317 }, - { -7517, -1220, 2883, 3049 }, - { -7605, -2687, 1874, 2735 }, - { -8718, -4035, 2676, 3730 }, - { -7990, -3907, 1185, 2607 }, - { -6058, -1744, 3349, 5157 }, - { -5954, 565, 3161, 3250 }, - { -6478, -612, 1930, 2271 }, - { -6535, -1445, -2, 1618 }, - { -8963, -4151, 1192, 4044 }, - { -7227, -3570, 1600, 4234 }, - { -4674, 79, 595, 3015 }, - { -3974, 430, 2727, 5137 }, - { -5299, 9, 3714, 4779 }, - { -6779, -2699, -8, 2436 }, - { -7016, -1145, 1293, 2310 }, - { -6955, -3312, 1534, 1801 }, - { -4025, 740, 1850, 4054 }, - { -9589, -3460, 4154, 5270 }, - { -4404, -1181, 4298, 5173 }, - { -7356, -4583, -18, 2644 }, - { -6516, -1235, 4439, 6234 }, - { -3453, -301, 4344, 4464 }, - { -4643, 1530, 3315, 4340 }, - { -4575, -2557, 3754, 3682 }, - { -3643, -3501, 2051, 2997 }, - { -5412, -2475, 2301, 1579 }, - { -5846, 259, 1360, 2348 }, - { -5258, -1358, 1050, 838 }, - { -5542, -219, 6377, 5750 }, - { -5713, -2952, 922, 899 }, - { -2049, -1135, 5206, 1033 }, - { -1693, -1886, 4835, -106 }, - { -2344, -3504, 4232, -13 }, - { -2475, -2334, 5043, 1126 }, - { -787, -2549, 3880, 2138 }, - { -3159, -2341, 4830, 2887 }, - { -1780, -1009, 6240, 2061 }, - { -4327, -3363, 2818, 886 }, - { -3376, -2743, 4104, 207 }, - { -3250, -4640, 2718, 1498 }, - { -382, -1075, 4382, 3460 }, - { -2416, -4168, 3530, 816 }, - { -1756, -2708, 4861, 622 }, - { -1879, -2097, 5156, 2889 }, - { -2496, -2418, 3722, 2671 }, - { -2717, -3252, 3341, 1944 }, - { -4063, -4091, 3306, 267 }, - { -3549, -3808, 3747, 842 }, - { -2635, 546, 5794, 1894 }, - { -1857, -1121, 4383, 3964 }, - { -2226, -2166, 3489, 3678 }, - { -3492, -660, 5323, 1063 }, - { -3033, -3130, 4382, 1828 }, - { -2703, -625, 6369, 2851 }, - { -1656, -2842, 4584, -528 }, - { -4781, -2622, 4390, 2097 }, - { -413, -2045, 5081, 3035 }, - { -3810, -2662, 4532, 1095 }, - { -3144, -1858, 5215, 1880 }, - { -3562, -1795, 4928, 670 }, - { -4800, -1509, 5189, 1859 }, - { -1085, -3832, 4169, 900 }, - { -1969, -3270, 2857, 2878 }, - { -4267, -4140, 3176, 1805 }, - { -5145, -3727, 3524, 1168 }, - { -1346, -1876, 5501, 1748 }, - { -4998, -2945, 3699, 338 }, - { -3458, -3096, 3406, -635 }, - { -1751, -3209, 3508, 395 }, - { -2507, 170, 5987, 705 }, - { -3756, -1072, 5647, 3536 }, - { -2870, -1439, 5026, 3212 }, - { -3913, -3225, 3669, 2144 }, - { -3739, 226, 5747, 764 }, - { -2052, -820, 5266, 3093 }, - { -3214, -3820, 2409, 2391 }, - { -4398, -2588, 3501, -218 }, - { -4484, -1763, 4180, -198 }, - { -3368, -1525, 4362, -134 }, - { -2407, 224, 4905, 3533 }, - { -1369, -2937, 4728, 1788 }, - { -4848, -1707, 4159, 851 }, - { -3454, -1749, 4281, 3230 }, - { -1990, -3853, 3487, 1735 }, - { -3117, 92, 6155, 4075 }, - { -2676, -2472, 4078, -589 }, - { -1547, -2012, 2626, 1835 }, - { -4275, -588, 4824, 725 }, - { -601, -2249, 3736, 3548 }, - { -4060, -61, 5333, 3097 }, - { -4303, 7, 6551, 3054 }, - { -5003, -1029, 5786, 3319 }, - { -2810, -728, 5392, 199 }, - { -1232, -200, 5228, 3121 }, - { 2621, 165, -6255, 298 }, - { 3669, 537, -6844, 1564 }, - { 1598, -1190, -6235, 2523 }, - { 2164, -32, -6894, 1383 }, - { 853, -1597, -6069, 1449 }, - { 1377, -1661, -5266, 108 }, - { 2660, 48, -5172, -517 }, - { 1903, -391, -5677, 1010 }, - { 3792, 206, -5274, -11 }, - { 1239, 2776, -2929, 2721 }, - { 4071, 149, -7259, 3125 }, - { 1436, -480, -6156, -196 }, - { 1373, -1960, -5005, 3122 }, - { 3413, -1271, -5176, 3283 }, - { 3060, -68, -6495, 2238 }, - { 2700, -2075, -4681, 91 }, - { 2928, -1728, -5168, 1858 }, - { 4424, 828, -4471, 88 }, - { 2672, -2604, -4038, 2753 }, - { 5223, -123, -6749, 2295 }, - { 4237, -420, -5538, 1353 }, - { 4744, -1281, -4097, 4708 }, - { 1103, -2764, -4751, 2024 }, - { 3747, -1913, -3911, 3960 }, - { 2470, -1416, -5542, 615 }, - { 4847, -1354, -5334, 1733 }, - { 5336, 88, -7593, 4007 }, - { 2388, -2880, -4807, 1037 }, - { 4495, 1391, -5685, -139 }, - { 5253, 1637, -6450, 1533 }, - { 1199, 795, -5515, 1261 }, - { 1397, -1259, -4252, 3838 }, - { 746, 70, -6640, 604 }, - { 1584, 166, -4972, 3072 }, - { 380, -999, -5397, 2267 }, - { 2974, 1707, -3242, 5360 }, - { 5202, -403, -5453, 2832 }, - { 3718, -1731, -4760, 714 }, - { 4150, -975, -4792, 61 }, - { 2925, -818, -4841, 15 }, - { 5301, 577, -4006, 3259 }, - { 5265, 1986, -5679, 3028 }, - { 3752, 1928, -4509, 3729 }, - { 3278, 1925, -6370, 1247 }, - { 5107, 1721, -4853, 3127 }, - { 3279, 2982, -2515, 4005 }, - { 4622, 668, -6204, 759 }, - { 6034, 317, -5763, 4818 }, - { -558, 57, -3785, 2817 }, - { 4476, 1616, -3965, 4536 }, - { 5953, 2056, -8215, 2715 }, - { 4387, 2613, -7463, 868 }, - { 5834, 1088, -4736, 4924 }, - { 6473, -856, -6991, 4172 }, - { 4959, -293, -5162, 76 }, - { 2731, -843, -6119, 3847 }, - { 3245, 1202, -6833, 616 }, - { 2553, 1383, -3829, 3859 }, - { 4332, 2099, -3480, 3622 }, - { 2110, 2683, -2728, 3990 }, - { 876, 1167, -3290, 3466 }, - { 3991, 1709, -2410, 4077 }, - { 5105, 939, -2584, 3256 }, - { 4719, 688, -1566, 3040 }, - { -3632, 4335, 1266, -3303 }, - { -4956, 3207, 1312, -2806 }, - { -4669, 2627, 2663, -2435 }, - { -4282, 3708, 2303, -3038 }, - { -4536, 2297, -175, -3350 }, - { -5234, 2503, -139, -880 }, - { -3978, 1512, 1092, -3619 }, - { -4519, 4649, 1363, -2455 }, - { -5118, 3132, 1961, -1577 }, - { -5196, 3379, -182, -1378 }, - { -6420, 4486, 2397, -1993 }, - { -5030, 5046, 1292, -1118 }, - { -4559, 2573, -927, -1406 }, - { -3501, 3730, 691, -4930 }, - { -4364, 2758, 1007, -3909 }, - { -4026, 2839, -1559, -2340 }, - { -5037, 4053, 836, -1571 }, - { -4727, 5136, 1110, -3588 }, - { -5245, 2799, -999, -2164 }, - { -4954, 1501, 422, -3963 }, - { -5994, 2726, 1462, -2833 }, - { -5621, 5159, 2038, -2512 }, - { -4991, 2291, 1917, -3151 }, - { -5469, 4382, -148, -2978 }, - { -5858, 1983, 807, -2720 }, - { -4709, 3556, 952, -467 }, - { -2489, 2362, 1714, -4230 }, - { -4717, 5004, -1180, -3672 }, - { -5914, 3653, 1359, -1317 }, - { -5506, 2995, 780, -1059 }, - { -5287, 3945, 2480, -2293 }, - { -3849, 4358, 322, -1770 }, - { -3911, 3570, 252, -3185 }, - { -3660, 5128, 158, -3719 }, - { -4599, 3277, -503, -2727 }, - { -3673, 3760, -1252, -3339 }, - { -5161, 2337, 388, -1943 }, - { -3529, 2216, 2156, -3080 }, - { -4309, 4331, 1808, -1460 }, - { -4782, 3820, 480, -2504 }, - { -4166, 3544, -378, -1567 }, - { -5572, 2466, -418, -2909 }, - { -6096, 2930, 119, -1878 }, - { -5963, 3554, 1011, -2233 }, - { -6433, 4335, 935, -2930 }, - { -5004, 3314, -1352, -3430 }, - { -6042, 3463, -1008, -3940 }, - { -4671, 2214, -640, -5040 }, - { -2795, 3759, 1412, -3803 }, - { -3647, 4436, 729, -515 }, - { -3594, 1033, 56, -4148 }, - { -2908, 3027, 2889, -3485 }, - { -3338, 2234, 313, -4285 }, - { -3825, 4497, -561, -2634 }, - { -6167, 3012, -48, -3149 }, - { -4828, 3515, -969, -4475 }, - { -5789, 2757, -539, -4173 }, - { -2452, 3067, 564, -4249 }, - { -4921, 1358, 1331, -2889 }, - { -3127, 4239, -1045, -1523 }, - { -4780, 2326, -1118, -3446 }, - { -3908, 5546, 152, -2622 }, - { -6972, 2976, 337, -2809 }, - { -4839, 4613, -35, -4077 }, - { -1408, 4822, -1149, -4997 }, - { -981, 4979, -912, -6304 }, - { -2098, 5689, -888, -2878 }, - { -3343, 4814, -657, -4434 }, - { -2461, 3601, -967, -4869 }, - { -2652, 3944, 87, -5520 }, - { -1104, 6076, 174, -6407 }, - { 355, 5370, -1721, -5869 }, - { 1242, 4497, -1107, -5091 }, - { -89, 4002, -1491, -5182 }, - { 1059, 5693, -1591, -4905 }, - { 1323, 4682, -2078, -4768 }, - { 818, 3996, -549, -5468 }, - { -287, 4529, 929, -5543 }, - { -919, 5519, -2791, -2844 }, - { -1407, 5679, -3289, -3974 }, - { -189, 6530, -3547, -4002 }, - { -900, 7039, -3371, -4855 }, - { -2983, 7211, -363, -4835 }, - { -814, 6503, -104, -5106 }, - { -2386, 6896, 809, -4919 }, - { 845, 4492, 352, -6621 }, - { -1998, 7237, -1646, -4231 }, - { -3380, 6251, 471, -4577 }, - { -1908, 7059, 84, -5726 }, - { -340, 6346, -803, -6265 }, - { -2279, 5834, -47, -4633 }, - { -1532, 5286, -1748, -1901 }, - { -2757, 6188, -453, -3415 }, - { -1255, 6405, -2043, -6357 }, - { 918, 5581, -121, -5667 }, - { 1840, 5336, -821, -5034 }, - { -2475, 4992, -1825, -3104 }, - { -2413, 5606, -1789, -4298 }, - { 132, 5128, -2389, -4442 }, - { 223, 6400, -2653, -4742 }, - { -673, 5012, 680, -4582 }, - { -1657, 6624, -349, -3596 }, - { -755, 6289, -1860, -3978 }, - { -572, 6894, -1946, -5207 }, - { -1141, 4756, -2665, -5586 }, - { -1073, 4269, -431, -4030 }, - { 186, 5761, 916, -5868 }, - { -1907, 4836, 1017, -5106 }, - { -963, 3363, -1248, -6348 }, - { -3262, 4774, -1818, -5858 }, - { 847, 3812, -2538, -4302 }, - { -1223, 5903, 1360, -5479 }, - { -1094, 6923, -1244, -2381 }, - { 267, 6276, -709, -2846 }, - { -157, 5840, 1124, -4266 }, - { 889, 3206, -910, -5305 }, - { -1736, 3344, 582, -4838 }, - { -2357, 5676, -2695, -6277 }, - { -1916, 6901, -986, -5397 }, - { -3062, 6028, -695, -5687 }, - { 1836, 3566, -1357, -5226 }, - { -2176, 4938, 646, -3872 }, - { -2199, 3055, -208, -6124 }, - { -236, 3032, -821, -5325 }, - { -3989, 7277, -565, -3899 }, - { -595, 4362, 74, -5975 }, - { 684, 5874, -841, -4424 }, - { -2731, 6305, -2389, -5465 }, - { -5775, 1325, -56, -2528 }, - { -7029, -534, -1890, -3278 }, - { -5798, -15, -2734, -2210 }, - { -5504, -1198, -353, -3659 }, - { -5079, 960, -894, -4336 }, - { -6073, -36, -133, -3014 }, - { -5782, -259, -1025, -3986 }, - { -6843, 1262, -807, -1639 }, - { -5263, -918, -3290, -579 }, - { -4840, 461, -2158, -533 }, - { -6014, -50, -620, 504 }, - { -5843, 241, -1359, -282 }, - { -5898, 577, 769, -3271 }, - { -6833, -946, -466, -3347 }, - { -6026, 1459, -512, -729 }, - { -7361, 747, -388, -1110 }, - { -6391, 2142, -1160, -2513 }, - { -6995, 304, 498, -2673 }, - { -6757, 679, -386, -433 }, - { -5222, 1688, -1093, -1032 }, - { -5019, 575, 184, -3627 }, - { -4237, 628, -3507, -1243 }, - { -7479, -456, -1722, -1486 }, - { -6464, 713, -1273, -1153 }, - { -6255, 1682, -606, -3607 }, - { -7033, 1497, -71, -1955 }, - { -6694, 1556, -1721, -3214 }, - { -6114, -356, 813, -2575 }, - { -5308, 632, -1851, -1636 }, - { -5742, -911, -1733, 383 }, - { -6083, -387, -2313, -879 }, - { -6535, -530, -1505, -2083 }, - { -4896, 1223, -2750, -1816 }, - { -6392, -463, -3247, -2093 }, - { -5373, 1264, -2706, -3042 }, - { -3894, -1390, -1020, -891 }, - { -6179, 1168, -1966, -1922 }, - { -5162, 1668, -1617, -1916 }, - { -6453, 920, -1169, -2432 }, - { -6130, 2005, -536, -1519 }, - { -6552, -98, -518, -1938 }, - { -7528, 355, -1101, -1772 }, - { -5745, 610, -247, -1360 }, - { -7003, 177, -2064, -1958 }, - { -6956, -570, -2220, -4225 }, - { -7830, 791, -1394, -2774 }, - { -7634, 480, -3171, -4224 }, - { -7913, 1154, -350, -2381 }, - { -5063, 1704, -1804, -2977 }, - { -4887, -524, -2703, 188 }, - { -5551, 406, -1620, -3063 }, - { -7109, 1342, 381, -3021 }, - { -6846, 631, -458, -3398 }, - { -4606, -605, 11, -3930 }, - { -8134, -225, -1738, -2648 }, - { -7043, 402, -2734, -3059 }, - { -7417, 1825, -2545, -4389 }, - { -6971, -236, -1031, -665 }, - { -5752, 2111, -1632, -3808 }, - { -7660, -78, -624, -3135 }, - { -6358, 619, -1951, -3911 }, - { -8134, 408, -1935, -3695 }, - { -6335, 1911, -2368, -4505 }, - { -7116, 2163, -344, -2753 }, - { 2357, 4488, 2220, -5682 }, - { 1385, 3206, 2300, -5305 }, - { 1419, 2557, 5203, -3516 }, - { 262, 4315, 3920, -1847 }, - { 3316, 3187, 1612, -5609 }, - { 1729, 2350, 1673, -6068 }, - { 1603, 6126, 1467, -2839 }, - { -1339, 3316, 3691, -3530 }, - { -563, 4618, 3180, -4548 }, - { 463, 4624, 3111, -5614 }, - { 1246, 5455, 3356, -5720 }, - { 480, 2149, 5422, -2893 }, - { 1768, 4827, 913, -5579 }, - { -149, 5381, 4366, -3297 }, - { 985, 3672, 2644, -92 }, - { -258, 2911, 5817, -2213 }, - { 3428, 3289, 3351, -3541 }, - { -666, 3295, 4727, -2869 }, - { 35, 6641, 4160, -4052 }, - { 623, 6787, 3156, -4560 }, - { 2654, 4360, 4676, -4632 }, - { 1386, 5246, 4834, -4497 }, - { 3488, 4574, 3856, -5946 }, - { 383, 4481, 4168, -4110 }, - { 1753, 3652, 4288, -3326 }, - { 1344, 4905, 2508, -4660 }, - { 1580, 4106, 3104, -2224 }, - { 2027, 5038, 1683, -1554 }, - { 446, 3699, 5872, -3013 }, - { 4637, 4087, 3578, -5018 }, - { 2629, 3560, 5331, -4900 }, - { 1527, 6674, 2523, -4131 }, - { -1437, 2804, 2528, -4464 }, - { -229, 3355, 2016, -5537 }, - { 3666, 3418, 4374, -4581 }, - { 1192, 3799, 923, -6596 }, - { 2040, 2956, 448, -5322 }, - { 2468, 5768, 4029, -5869 }, - { 3438, 6516, 3529, -6667 }, - { 2737, 5495, 680, -5535 }, - { 3896, 5727, 1801, -4958 }, - { 4988, 4957, 3592, -6518 }, - { -542, 4416, 5794, -2787 }, - { 4136, 4354, 2064, -4696 }, - { 3067, 5936, 1207, -3396 }, - { 2789, 4966, 2405, -3854 }, - { 1731, 3270, 3251, -1063 }, - { 1767, 5537, 2084, -2349 }, - { 465, 3116, 4532, -837 }, - { 1499, 2627, 4610, -2212 }, - { 122, 3095, 3642, -3552 }, - { 2542, 2866, 2705, -6402 }, - { 3134, 4323, 698, -4785 }, - { 731, 1859, 3112, -5242 }, - { 2553, 2980, 3241, -4846 }, - { 1329, 5310, 1607, -6624 }, - { 2468, 1858, 3476, -1034 }, - { -172, 4996, 2000, -5562 }, - { 2621, 4220, 1574, -3386 }, - { -333, 1832, 3362, -4117 }, - { 2169, 6762, 3065, -6225 }, - { 2844, 5528, 3223, -4765 }, - { 526, 5175, 1644, -4267 }, - { 2922, 4426, 2414, -2610 }, - { 452, 1399, -4516, -2636 }, - { 2872, 1720, -4667, -1435 }, - { 1279, 702, -5424, -1984 }, - { 2187, 870, -5021, -1341 }, - { 583, -144, -4628, -2464 }, - { 3, 2237, -5284, -2827 }, - { -19, 1005, -5460, -1819 }, - { 2897, 2084, -5885, -515 }, - { -400, 3370, -5527, -2947 }, - { 1505, 2593, -5518, -1802 }, - { 1341, 4534, -5094, -1899 }, - { 3241, 3670, -5493, -1252 }, - { -1287, 921, -5994, -1675 }, - { 627, 408, -6652, -364 }, - { -260, 1127, -4849, -3247 }, - { 371, 3400, -5976, -2285 }, - { 1533, 1566, -6373, -610 }, - { 2462, 4274, -6184, -1254 }, - { 1782, 3363, -6222, -1381 }, - { 572, 4650, -5673, -2754 }, - { 2674, 3414, -4460, -2154 }, - { 3614, 3820, -6883, -398 }, - { 1136, -1, -5511, -1112 }, - { -1773, 1137, -5647, -2377 }, - { -753, 2104, -6085, -2565 }, - { -204, 3025, -4731, -1418 }, - { -1486, 1438, -4380, -216 }, - { 302, 858, -5786, -264 }, - { 3486, 1495, -5234, -783 }, - { 888, 2327, -3423, -3720 }, - { -259, 772, -6596, -1311 }, - { -1197, 2073, -5174, -1826 }, - { 1500, 3470, -4462, -2645 }, - { 3072, 1960, -3277, -2264 }, - { 1841, 952, -4324, -2340 }, - { 1994, 2200, -3940, -2923 }, - { -1782, 1699, -4667, -1075 }, - { -1464, 2906, -3468, -375 }, - { 366, 2380, -3747, 1467 }, - { -545, 1645, -4619, 376 }, - { 1724, 2350, -2374, -3512 }, - { 3184, 2628, -2996, -3275 }, - { 734, 2010, -6239, -1479 }, - { 524, 3756, -4496, -3263 }, - { 1492, 3570, -3494, -3600 }, - { -932, 618, -5389, -2894 }, - { -133, 2161, -4083, -3267 }, - { 786, 774, -3279, -3731 }, - { 1078, 803, -3843, -3007 }, - { -332, 3405, -3347, 40 }, - { -17, 6, -4005, -3690 }, - { -189, 4372, -4488, -2561 }, - { -450, 3846, -3790, -1370 }, - { 362, 2212, -5272, -15 }, - { -1529, 791, -6802, -2296 }, - { 2145, 4241, -4474, 376 }, - { 1813, 2426, -2932, -2726 }, - { -542, 4557, -3140, -1080 }, - { 1192, 3784, -4371, -20 }, - { 2784, 5188, -6399, -1394 }, - { 431, 4561, -3673, -1398 }, - { 1382, 3096, -4083, 1253 }, - { 1209, 4224, -2930, 1500 }, - { 2798, 2684, -6676, -606 }, - { -2396, 1510, -5381, -2713 }, - { -2625, 2542, -4032, -2880 }, - { -1231, 3967, -4098, -2886 }, - { -1393, 2374, -3862, -4525 }, - { -2495, 1665, -1637, -5445 }, - { -3854, 1759, -1750, -4944 }, - { -2373, 1668, -2856, -6251 }, - { -2668, 1981, -886, -4557 }, - { -2927, 4427, -3451, -6172 }, - { -1925, 2596, -4696, -2527 }, - { -3202, 2847, -3928, -5896 }, - { -3332, 1665, -5025, -3412 }, - { -3212, 3115, -4155, -4062 }, - { -1013, 3205, -5133, -3751 }, - { -2022, 4595, -3947, -5611 }, - { -3556, 1755, -3715, -2300 }, - { -1784, 4114, -2723, -1773 }, - { -3586, 4081, -2733, -4942 }, - { -1608, 3685, -4154, -4573 }, - { -3368, 4042, -4452, -6227 }, - { -1407, 3881, -5729, -3719 }, - { -2751, 3281, -5077, -4999 }, - { -3791, 2410, -4906, -5288 }, - { -730, 2303, -4217, -3755 }, - { -1812, 2311, -5492, -3709 }, - { -610, 4336, -3915, -3783 }, - { -2841, 4337, -4278, -4430 }, - { -1662, 4666, -4661, -3964 }, - { -589, 5209, -4923, -3682 }, - { -4155, 2234, -4076, -4218 }, - { -3951, 2770, -2665, -2805 }, - { -2302, 3228, -3717, -1908 }, - { -3129, 4373, -2264, -2851 }, - { -447, 1363, -3578, -4323 }, - { -2648, 4237, -3159, -3071 }, - { -4072, 3241, -3541, -4605 }, - { -4507, 3458, -2339, -3838 }, - { -1646, 997, -4926, -3970 }, - { -3025, 1614, -3940, -1242 }, - { -1337, 1756, -3163, -5529 }, - { -3203, 1865, -3282, -4354 }, - { -1646, 2118, -2203, -6018 }, - { 174, 1871, -2707, -4639 }, - { -2607, 1485, -4778, -4750 }, - { -2199, 3991, -3134, -4879 }, - { -2962, 3323, -2816, -2419 }, - { -5286, 2495, -4548, -5395 }, - { -2810, 3710, -2274, -4211 }, - { -330, 3006, -2993, -4678 }, - { -1187, 2411, -2743, -5196 }, - { -664, 4033, -3101, -5641 }, - { -1458, 3602, -2816, -5371 }, - { -4116, 4923, -3321, -5630 }, - { -4165, 2528, -2592, -4798 }, - { -2759, 3080, -2333, -5719 }, - { -5157, 3011, -5526, -6348 }, - { -3095, 2126, -5881, -4234 }, - { -4377, 3849, -3600, -6099 }, - { -1994, 4947, -5235, -4753 }, - { -1067, 600, -3258, -5133 }, - { -4992, 3302, -2208, -5051 }, - { -3377, 2981, -1655, -4815 }, - { -3325, 2446, -1787, -6116 }, - { -2341, 2737, -3240, -6347 }, - { -2258, -3732, 3710, -1235 }, - { -1558, -3849, 2694, -3012 }, - { -599, -4837, 3050, -2951 }, - { -2246, -5433, 2798, -1910 }, - { -2255, -4989, 3260, 270 }, - { -3026, -5353, 2693, -1036 }, - { -1151, -6097, 1097, -3782 }, - { -3391, -6012, 2130, -1303 }, - { -2850, -4422, 3375, -480 }, - { -1138, -3779, 1491, -4162 }, - { -551, -3892, 3787, -2082 }, - { -3221, -3676, 3144, -1202 }, - { -3023, -5196, 2650, 605 }, - { -1756, -5729, 2646, 321 }, - { -2693, -4409, 494, -4797 }, - { -1913, -4573, 3372, -1730 }, - { -1277, -3604, 4061, -993 }, - { -420, -4993, 1351, -4796 }, - { -3052, -5333, 1435, -1242 }, - { -602, -5034, 3869, -1141 }, - { -2436, -4680, 1665, -3019 }, - { -2657, -3658, 1459, -3391 }, - { -1220, -6246, 2749, -525 }, - { -3838, -4844, 2265, -1735 }, - { -1247, -5679, 3356, -1417 }, - { -917, -5448, 3342, 105 }, - { -1756, -6839, 2276, -2350 }, - { -412, -5206, 1764, -3539 }, - { -1439, -6915, 1442, -3750 }, - { -1381, -4439, 3863, -282 }, - { -3482, -4953, 2726, -336 }, - { -1376, -5931, 1714, -1987 }, - { -1716, -4405, 2608, 105 }, - { -1590, -5191, 2652, -2704 }, - { -2149, -6442, 2453, -1263 }, - { -3426, -3832, 2334, -1829 }, - { -2747, -5948, 2362, -173 }, - { -2435, -3267, 2966, -1710 }, - { -3979, -4282, 2705, -775 }, - { -356, -4238, 2544, -4343 }, - { -1363, -6471, 2817, -1836 }, - { -2878, -5117, 218, -3149 }, - { -3539, -5196, 1710, -2356 }, - { -2888, -4537, 2746, -1701 }, - { -1870, -4439, 1496, -4121 }, - { -1486, -3388, 3349, -2145 }, - { -3333, -4138, 1467, -2876 }, - { -345, -5340, 1012, -1190 }, - { -1672, -4992, 2289, -1029 }, - { -2146, -5528, 3038, -635 }, - { -316, -3656, 3426, -3152 }, - { -2695, -5812, 2336, -2050 }, - { -2067, -6052, 737, -3258 }, - { -2664, -4205, -350, -1266 }, - { -617, -5406, 80, -4853 }, - { -2418, -3825, 1853, -1326 }, - { -1961, -4339, 583, -4315 }, - { -1495, -5141, -133, -5205 }, - { -3208, -6440, 1691, -2069 }, - { -2632, -3633, 2325, -2761 }, - { -2624, -5670, 1252, -3676 }, - { -3687, -5608, 687, -2833 }, - { -3320, -5707, 16, -3877 }, - { -2738, -6112, 84, -5135 }, - { 2277, -5661, 3076, 843 }, - { 1555, -5769, 2821, -5236 }, - { 536, -6381, 603, -4910 }, - { 734, -4609, 3314, -4092 }, - { 1836, -4547, 3267, -4322 }, - { -13, -5976, 3752, -1607 }, - { 1423, -6318, 2336, 398 }, - { 365, -7779, 1498, -534 }, - { 2104, -8366, 2946, -1345 }, - { 143, -5545, 1898, -3756 }, - { 655, -6852, 1430, 148 }, - { 4, -6653, 2397, -59 }, - { 2346, -5996, 4562, -934 }, - { 1229, -7104, 2963, -598 }, - { -528, -7048, 2887, -1790 }, - { 1451, -6857, 3900, -1637 }, - { 554, -6018, 3336, 9 }, - { 3278, -5758, 4034, 129 }, - { 3541, -7145, 4905, -1575 }, - { 2339, -6907, 3464, -301 }, - { 2775, -7301, 1667, -3894 }, - { 539, -7887, 991, -4156 }, - { 2115, -7421, 3131, -3075 }, - { 2803, -8546, 2564, -5836 }, - { 2869, -5833, 1620, -4561 }, - { 2591, -7281, 3215, -4719 }, - { -1228, -8477, 706, -4782 }, - { 1967, -5243, 4813, -1940 }, - { 701, -7010, 2273, -3893 }, - { 915, -8470, 1918, -5620 }, - { -94, -6715, 156, -3873 }, - { 1074, -5607, 4389, -1017 }, - { 2739, -6551, 1227, -3521 }, - { 725, -7835, 2701, -1291 }, - { -493, -7475, 2263, -1075 }, - { -412, -6508, 2984, -744 }, - { 665, -5451, 3725, -2692 }, - { 1499, -8129, 3564, -2072 }, - { 2870, -6333, 4487, -2108 }, - { 706, -5007, 3911, -152 }, - { -482, -8660, 1483, -2900 }, - { 2481, -6596, 2518, -1715 }, - { 1403, -6414, 1398, -5387 }, - { 652, -6267, 583, -5942 }, - { 694, -7540, 646, -6272 }, - { 2275, -7614, 256, -5015 }, - { 1416, -9727, 1900, -3153 }, - { 2760, -6433, 3875, -3771 }, - { 2325, -11196, 2182, -5155 }, - { 1223, -11061, 1377, -5097 }, - { 108, -10603, 307, -4952 }, - { -118, -8268, 1650, -1572 }, - { 1839, -7943, 1755, -612 }, - { 2501, -9056, 981, -2969 }, - { 2902, -8476, 1491, -5780 }, - { 1995, -11175, 1585, -3643 }, - { 696, -8212, 828, -2474 }, - { 1526, -8649, 1380, -1210 }, - { 461, -7253, 3222, -2229 }, - { 2966, -8641, 4121, -3271 }, - { 833, -6039, 2361, -1086 }, - { 3565, -7312, 1980, -5427 }, - { 2850, -8671, 3760, -1846 }, - { 2643, -7281, 2163, -173 }, - { 3463, -3706, -3132, -923 }, - { 1315, -3825, -3443, 2 }, - { 2594, -4083, -3815, 670 }, - { 1826, -4291, -2741, -155 }, - { 868, -3749, -4175, -298 }, - { 2008, -4237, -3897, -517 }, - { 1242, -3493, -4335, -1335 }, - { -88, -4142, -3390, -1529 }, - { 2176, -3488, -3822, -975 }, - { 1706, -5188, -3415, -637 }, - { 2717, -6159, -2333, -882 }, - { 1276, -3978, -4361, 537 }, - { 2471, -5556, -2866, -208 }, - { 799, -4673, -4086, 56 }, - { 1901, -4786, -3533, 270 }, - { 3036, -3902, -3606, -333 }, - { 2249, -3317, -4319, -144 }, - { 2594, -4207, -2105, -2930 }, - { 4008, -4774, -2626, -902 }, - { 1038, -3659, -3496, -2454 }, - { 2725, -3597, -3298, -1535 }, - { 1662, -5803, -2813, 175 }, - { 705, -3757, -3441, -1484 }, - { 1860, -5987, -2821, -886 }, - { 3786, -4918, -2199, -1929 }, - { 3683, -4235, -2547, -1287 }, - { 2531, -4896, -2956, -1593 }, - { 1005, -5585, -3324, -180 }, - { 1625, -5229, -1756, -3642 }, - { 1494, -5041, -2989, -2685 }, - { 2718, -4655, -3224, -867 }, - { 2374, -6640, -1745, -2975 }, - { 2133, -6436, -2477, -1499 }, - { 1833, -4418, -3523, -1512 }, - { 1128, -4910, -2658, -1106 }, - { 689, -4777, -2831, -2085 }, - { 3593, -5280, -2627, -315 }, - { 3264, -3771, -2673, -1861 }, - { 3202, -5602, -2409, 402 }, - { 552, -4618, -2221, -3002 }, - { 3095, -5356, -2666, -1083 }, - { 3401, -4609, -3146, 45 }, - { 3051, -4662, -2192, -2232 }, - { 2798, -5552, -2462, -1941 }, - { 2354, -5815, -2223, -2619 }, - { 192, -3708, -2807, -2658 }, - { 1886, -4226, -1862, -3529 }, - { 2526, -3976, -2819, -2332 }, - { 1577, -3870, -2711, -2806 }, - { 1288, -5588, -3382, -1403 }, - { 2711, -5399, -1564, -3253 }, - { 1459, -5492, -2222, -322 }, - { 2823, -5091, -2886, 776 }, - { 3559, -5821, -2109, -1360 }, - { 1587, -6331, -2760, -1909 }, - { 2139, -5213, -2874, -2120 }, - { 1318, -4337, -3695, -2098 }, - { 821, -4471, -1849, -565 }, - { 3329, -4782, -1725, -89 }, - { 582, -4914, -4105, -1119 }, - { 417, -4144, -4072, -2529 }, - { -199, -3803, -2765, -4042 }, - { 2731, -4283, -2143, 1 }, - { 2911, -6187, -1951, -2116 }, - { 1573, -6094, -493, -2838 }, - { 2081, -6927, -864, -3211 }, - { 1058, -7826, 79, -364 }, - { 3147, -5570, -684, -978 }, - { 3572, -5856, 1060, 1824 }, - { 1143, -6702, -1478, 338 }, - { 2341, -7220, -88, 260 }, - { 3639, -6861, 668, 815 }, - { 2227, -6268, -1706, 446 }, - { 3390, -6082, -353, 1302 }, - { 1123, -7556, -1237, -430 }, - { 1729, -7742, 729, -218 }, - { 1457, -6774, 587, 579 }, - { 505, -6919, -569, 371 }, - { 1106, -7245, 78, 158 }, - { 2755, -6745, -1122, 338 }, - { 3069, -6040, -1415, 986 }, - { 2174, -7064, -1430, -283 }, - { 1390, -8626, -446, -3031 }, - { 3534, -6890, -431, 547 }, - { 2267, -9618, 475, -2994 }, - { 3672, -7673, 75, -115 }, - { 2131, -7560, -1206, -750 }, - { 2972, -7477, -685, -262 }, - { 1604, -6637, -672, 699 }, - { 1666, -7577, -577, -240 }, - { 1591, -6554, -2158, -94 }, - { 2348, -6286, -353, 1123 }, - { 2017, -8810, -412, -1805 }, - { 2892, -6713, -1765, -554 }, - { 2500, -6828, -1995, -1197 }, - { 3877, -6639, -224, -1655 }, - { 2392, -7872, -91, -333 }, - { 3562, -7370, -532, -2836 }, - { 2552, -7614, 164, -1805 }, - { 990, -6104, 218, 438 }, - { 910, -7861, 312, -1195 }, - { 1472, -6327, 372, -640 }, - { 1576, -7143, -1983, -843 }, - { 422, -7625, -457, -278 }, - { 1797, -8532, 405, -1011 }, - { 1088, -7396, -238, -2277 }, - { 3209, -6753, -1431, -2072 }, - { 2617, -6839, 100, -2573 }, - { 2575, -8573, -387, -3188 }, - { 3618, -6971, -1190, -321 }, - { 2205, -7361, -1695, -2008 }, - { 2985, -6297, 1464, 1179 }, - { 2804, -7310, 1053, 338 }, - { 1362, -6074, -1163, -840 }, - { 3336, -6325, -1794, 21 }, - { 2836, -8109, 818, -329 }, - { 2791, -5879, 560, 1546 }, - { 2392, -6064, 135, 100 }, - { 1838, -6194, 596, 1085 }, - { 1926, -7515, -414, -4901 }, - { 3225, -7298, -1202, -1189 }, - { 3960, -7558, -659, -719 }, - { 3442, -6647, -1692, -1095 }, - { 3381, -6441, 262, -886 }, - { 1431, -8150, -1186, -1406 }, - { 340, -8498, -150, -899 }, - { 3004, -8149, -260, -953 }, - { 2749, -6611, 563, 873 }, - { -6647, -1325, -4517, -4691 }, - { -6005, -1657, -4089, -3797 }, - { -3157, 588, -5213, -3068 }, - { -3311, -1425, -6329, -3726 }, - { -5866, -819, -3857, -2744 }, - { -5001, -1799, -1075, -4621 }, - { -5330, -2650, -2672, -4664 }, - { -4930, -539, -2363, -4010 }, - { -2984, 10, -3863, -5749 }, - { -1055, -2106, -3713, -4267 }, - { -5476, -502, -4279, -6504 }, - { -5231, -1543, -5018, -6425 }, - { -5134, -363, -3165, -5109 }, - { -3953, -771, -4107, -6393 }, - { -2159, -563, -3652, -5342 }, - { -3888, -2321, -919, -5057 }, - { -1236, -597, -4235, -4193 }, - { -4053, 675, -3083, -6174 }, - { -2793, -1089, -5396, -3460 }, - { -3000, -44, -2209, -6575 }, - { -3336, -1531, -4313, -5160 }, - { -2127, 128, -4851, -3692 }, - { -3321, 136, -2067, -5660 }, - { -5215, 1404, -4374, -4356 }, - { -2747, 400, -6340, -3691 }, - { -3926, -599, -5361, -5006 }, - { -2875, -2592, -5143, -4092 }, - { -4991, -1958, -5322, -4891 }, - { -4965, -1318, -6652, -5333 }, - { -4920, -1691, -3388, -5561 }, - { -3644, -3354, -2688, -5982 }, - { -5076, -919, -4563, -2984 }, - { -6114, 250, -3884, -3915 }, - { -4014, 744, -3973, -1924 }, - { -5543, -1041, -5557, -3847 }, - { -4711, -1352, -5649, -2603 }, - { -3362, 775, -5305, -4879 }, - { -5001, 107, -3554, -2888 }, - { -6258, -1651, -6356, -6566 }, - { -4529, 407, -5003, -3865 }, - { -5154, 550, -5278, -5465 }, - { -4195, -467, -1894, -3129 }, - { -5022, 1127, -3349, -3314 }, - { -6075, 1250, -4313, -5641 }, - { -2677, -2283, -2312, -5903 }, - { -4113, 193, -1195, -4833 }, - { -3940, -1048, -1389, -5079 }, - { -3703, 917, -4043, -4451 }, - { -3366, -4231, -1534, -5488 }, - { -3326, -3583, -2091, -4903 }, - { -5144, 1254, -2532, -4949 }, - { -5982, -870, -2545, -4555 }, - { -3925, -157, -5367, -2281 }, - { -6419, -746, -5668, -4371 }, - { -5787, 518, -7096, -5805 }, - { -4258, 954, -6453, -4321 }, - { -4771, -695, -4158, -1639 }, - { -7078, -760, -5195, -5877 }, - { -7348, 83, -4101, -4586 }, - { -2430, 184, -2874, -1679 }, - { -2284, -3943, -2924, -5034 }, - { -1804, -1785, -3002, -4710 }, - { -4399, -2772, -1815, -4637 }, - { -6340, -2626, -2824, -5191 }, - { -4998, -5168, -3480, 1905 }, - { -3958, -5492, -1599, 1579 }, - { -2471, -3755, -276, 3182 }, - { -3033, -5779, -1063, 1554 }, - { -2936, -4829, -1290, 2386 }, - { -1835, -5073, -3051, 1299 }, - { -1724, -3771, -3935, 2324 }, - { -5070, -2550, -3692, 768 }, - { -4326, -5333, -297, 1878 }, - { -3472, -5619, -3094, 992 }, - { -3027, -4384, -3038, 2265 }, - { -3201, -5332, 67, 2200 }, - { -1681, -4373, -1947, 2461 }, - { -3221, -3329, -4238, 2564 }, - { -1262, -2968, -2915, 3227 }, - { -3419, -1878, -3373, 2110 }, - { -2244, -5583, -2012, 1288 }, - { -1971, -5266, -990, 1812 }, - { -2975, -2778, -452, 4063 }, - { -2198, -1165, -3298, 2965 }, - { -4782, -4894, -4767, 664 }, - { -6002, -3950, -2806, 2025 }, - { -3142, -3162, -2859, 3295 }, - { -3262, -3340, -4123, 1596 }, - { -4014, -3918, -1955, 3361 }, - { -1700, -3463, -1346, 3449 }, - { -4245, -4445, -4743, 1644 }, - { -4180, -3969, -401, 3281 }, - { -2782, -5240, -4117, 1156 }, - { -5744, -4040, -1439, 3470 }, - { -5063, -4663, -323, 3172 }, - { -4531, -3319, -844, 3988 }, - { -6226, -5125, -2064, 2976 }, - { -3115, -3267, -1531, 3898 }, - { -4628, -4421, -2864, 2808 }, - { -4559, -2989, -3442, 2024 }, - { -1775, -4487, -656, 2477 }, - { -2664, -1865, -1884, 4081 }, - { -1828, -2575, -3894, 3378 }, - { -6441, -3677, -2025, 1677 }, - { -4141, -2156, -1191, 3474 }, - { -4802, -1623, -1727, 2160 }, - { -5474, -2745, -1475, 2498 }, - { -3664, -1056, -1975, 2491 }, - { -4672, -3062, -2235, 2933 }, - { -4205, -5960, -2849, 1517 }, - { -4995, -5708, -1739, 1805 }, - { -4892, -6080, -4793, 872 }, - { -4270, -4172, -4263, 2185 }, - { -4687, -1470, -2905, 1023 }, - { -6446, -5017, -3919, 1000 }, - { -6046, -5538, -3943, 2006 }, - { -6028, -3750, -3953, 771 }, - { -5959, -4582, -5024, 824 }, - { -5818, -2576, -2249, 1326 }, - { -5659, -5345, -1119, 2500 }, - { -3346, -4155, 606, 2749 }, - { -5680, -4827, -2501, 1838 }, - { -6193, -2543, -1295, 840 }, - { -6871, -4925, -3512, 1801 }, - { -5605, -1788, -1895, 779 }, - { -3922, -5712, -4644, 510 }, - { -4745, -3869, -4533, 99 }, - { -2984, -4907, -399, 1497 }, - { 1847, -478, 3061, -5812 }, - { 4450, -1116, 3609, -6570 }, - { 3139, 99, 3007, -5532 }, - { 2590, -3782, 3138, -4770 }, - { 1881, 1204, 5778, -3404 }, - { 3631, 2060, 5566, -5038 }, - { 3461, 1961, 5167, -3800 }, - { 2947, 273, 4536, -4389 }, - { 4453, -1730, 5788, -4370 }, - { 4032, 1805, 2666, -4534 }, - { 3487, -944, 2313, -6028 }, - { 1313, 34, 4210, -4067 }, - { 5632, -1502, 5825, -5855 }, - { 7736, -547, 4879, -5476 }, - { 4906, -1512, 4760, -5760 }, - { 3843, 447, 1091, -4958 }, - { 2982, -1135, 5442, -4386 }, - { 3579, 271, 3031, -6770 }, - { 3932, -211, 4688, -5507 }, - { 4411, 1720, 2387, -5584 }, - { 5379, -479, 4575, -6280 }, - { 3613, -362, 2012, -4885 }, - { 3744, -2013, 4493, -5073 }, - { 5693, 109, 4379, -3362 }, - { 5475, -621, 5317, -3985 }, - { 6411, -673, 5708, -4752 }, - { 4933, -796, 7262, -4290 }, - { 2804, 444, 6276, -3655 }, - { 4120, -517, 6078, -4531 }, - { 5119, 841, 3486, -3910 }, - { 4738, 1539, 3525, -2970 }, - { 5086, 370, 5895, -5640 }, - { 4235, 2716, 4589, -5044 }, - { 3691, 682, 6199, -4700 }, - { 6111, -570, 6271, -6528 }, - { 2611, 1277, 3756, -4802 }, - { 4395, 970, 3807, -5879 }, - { 5225, 2299, 3242, -4333 }, - { 5144, 1778, 4946, -5545 }, - { 2989, -3016, 3247, -5495 }, - { 2983, 920, 2071, -6059 }, - { 5270, -903, 4434, -2350 }, - { 6415, -585, 3970, -3554 }, - { 3866, -197, 5216, -2884 }, - { 3767, -1298, 6702, -3315 }, - { 6299, 2620, 5284, -6824 }, - { 6654, 646, 3653, -4927 }, - { 4770, 3047, 5160, -6287 }, - { 5364, 434, 2919, -5207 }, - { 2998, 1344, 4801, -2456 }, - { 3896, 1013, 3773, -1864 }, - { 2115, 655, 2999, -6344 }, - { 5170, -981, 2849, -4464 }, - { 2735, -2159, 2717, -5776 }, - { 2430, -1952, 4392, -4559 }, - { 6143, -1180, 3659, -4746 }, - { 4978, -1483, 1726, -4875 }, - { 3486, -2383, 3306, -4301 }, - { 1434, -1372, 4171, -4770 }, - { 3354, -2627, 1525, -5093 }, - { 6790, 2386, 3995, -5909 }, - { 1475, -2674, 3451, -4204 }, - { 1999, -3494, 3693, -5556 }, - { 4764, -2848, 2856, -5589 }, - { -3677, 5131, 2827, -2934 }, - { -2844, 7078, 2852, -3580 }, - { -3902, 6434, 4118, -1911 }, - { -1769, 7530, 3492, -3541 }, - { -1937, 5679, -447, -1127 }, - { -2456, 4680, 4196, -2407 }, - { -2778, 8241, 1698, -4288 }, - { -2876, 6104, 5182, -2387 }, - { -2802, 7341, 4463, -2938 }, - { -1025, 6267, 4752, -3201 }, - { -2349, 5413, 2041, -3794 }, - { -2252, 8225, 2856, -4269 }, - { -1465, 4967, 4976, -2500 }, - { -636, 7565, 3517, -4233 }, - { -1905, 5618, 3904, -2942 }, - { -302, 6816, 3343, -3316 }, - { -2210, 4156, 2817, -3511 }, - { -717, 6568, 1863, -2951 }, - { -3873, 5682, 2164, -575 }, - { -2878, 5835, 440, -2597 }, - { -3228, 7701, 2610, -2514 }, - { -3608, 8888, 3377, -2468 }, - { -2582, 9717, 2519, -3126 }, - { -5238, 6202, 2866, -2831 }, - { -3428, 7370, 3056, -335 }, - { -1681, 8836, 1210, -2010 }, - { -3276, 6724, 1156, -3930 }, - { -894, 8149, 827, -1258 }, - { -2965, 8631, 2549, -1320 }, - { -3961, 6902, 3581, 55 }, - { -1894, 7745, 1750, -841 }, - { -821, 6844, 850, -676 }, - { -608, 6948, -4, -1376 }, - { 615, 6524, 1089, -1147 }, - { -2972, 5668, 1091, -489 }, - { -157, 4649, 2904, -413 }, - { 673, 5121, 1498, -66 }, - { -390, 5902, 1611, -245 }, - { -2349, 5478, 4772, -1320 }, - { 88, 6798, 1972, -1859 }, - { -1213, 5120, 2991, 200 }, - { -2347, 6040, 2839, 376 }, - { -578, 5976, 3364, -1796 }, - { -1391, 5872, 3002, -965 }, - { -564, 4496, 3946, -1186 }, - { -2299, 6386, 3135, -2176 }, - { -2131, 5641, 2011, 1223 }, - { -772, 5807, 1124, 895 }, - { -2837, 6758, 2297, -740 }, - { -3091, 6298, 1415, -2126 }, - { -4197, 6036, 1843, -3022 }, - { -41, 6459, 92, 344 }, - { -2241, 6860, 2095, -4396 }, - { -1931, 7088, 2117, -2135 }, - { -2375, 4422, 1688, -3169 }, - { -1742, 6674, 1538, -119 }, - { -4818, 7749, 4192, -1577 }, - { -2004, 5672, 193, -430 }, - { -3825, 6042, 2128, -1898 }, - { -1108, 8033, 2119, -3013 }, - { -2370, 5453, 1721, 266 }, - { -1570, 7134, 614, -2638 }, - { -1519, 8752, 3503, -4330 }, - { -2050, 3845, 2907, -1126 }, - { 5085, 4412, -335, -1923 }, - { 3618, 1423, -613, -4012 }, - { 4481, 3729, 589, -4631 }, - { 4270, 3216, -1763, -3168 }, - { 4241, 1796, -1701, -2796 }, - { 4787, 2338, -487, -3639 }, - { 2915, 3429, -621, -4753 }, - { 5175, 1660, -1265, -3223 }, - { 4280, 4057, -684, -4079 }, - { 4980, 4419, -1455, -2719 }, - { 5436, 2464, 387, -4197 }, - { 4507, 4018, 1121, -3314 }, - { 6020, 2401, -413, -3201 }, - { 4200, 3789, -333, -2813 }, - { 5229, 2493, -1194, -1878 }, - { 5851, 2695, -492, -2292 }, - { 5743, 3288, -697, -1221 }, - { 5692, 2612, 979, -2227 }, - { 5085, 2067, 1046, -1214 }, - { 3163, 2240, -2098, -3435 }, - { 5228, 1898, 145, -2397 }, - { 5860, 3976, -418, -2872 }, - { 6008, 3399, 1027, -3506 }, - { 4126, 2035, 1865, -893 }, - { 5375, 3596, 511, -2362 }, - { 1937, 1493, -852, -122 }, - { 3473, 4849, 547, -2603 }, - { 4631, 2977, 1141, -1768 }, - { 6149, 3050, -71, -1886 }, - { 4069, 4353, -289, -1429 }, - { 2884, 1225, -1388, 365 }, - { 5485, 2518, -235, -571 }, - { 1216, 4375, 1443, 398 }, - { 4988, 3106, 107, -1435 }, - { 4511, 2801, 307, -444 }, - { 3235, 4386, 327, -676 }, - { 2055, 3708, 1657, -305 }, - { 5839, 2374, 290, -1385 }, - { 5110, 3305, 1936, -4206 }, - { 6416, 2920, 338, -2736 }, - { 3350, 2824, -1269, -3881 }, - { 4840, 1815, 464, 186 }, - { 2399, 3332, 238, 1238 }, - { 3516, 1363, 1582, 688 }, - { 3582, 1874, 154, -4770 }, - { 3261, 2878, 886, 283 }, - { 3877, 2658, -327, 884 }, - { 4151, 3436, 2173, -2923 }, - { 3592, 3674, 1281, -1295 }, - { 4561, 3730, -1114, -1747 }, - { 4595, 3625, -558, -575 }, - { 2577, 2348, 2267, 120 }, - { 5242, 3299, 32, -3412 }, - { 4264, 3637, 709, -2320 }, - { 6556, 3570, -838, -2472 }, - { 5745, 4014, -940, -1973 }, - { 5629, 4475, 477, -3328 }, - { 5269, 3199, 1682, -3085 }, - { 4432, 2416, 1145, -3299 }, - { 4465, 2505, 2162, -2186 }, - { 4643, 4941, -88, -2885 }, - { 4568, 5231, 552, -3915 }, - { 5667, 3075, -1406, -2963 }, - { 5418, 5259, -771, -2818 }, - { -256, -7875, 511, -471 }, - { -1813, -7971, -424, -396 }, - { -306, -7006, 862, 282 }, - { -2306, -6422, -1440, 508 }, - { -245, -6787, 375, -100 }, - { -1309, -6065, -20, 779 }, - { -1656, -6047, -641, 1307 }, - { -1496, -6522, 964, 726 }, - { -2291, -6588, -202, 795 }, - { -762, -7522, 1454, -558 }, - { -2270, -7004, -834, -580 }, - { -1139, -7078, 259, 362 }, - { -2535, -7568, -1040, 49 }, - { -3786, -7280, 934, -476 }, - { -3336, -6368, 606, 1056 }, - { -3602, -6924, 52, 714 }, - { -2278, -6550, 1674, 204 }, - { -2855, -5765, 930, 1530 }, - { -2889, -7325, -215, 305 }, - { -2749, -6080, -237, 1452 }, - { -985, -6667, 1577, 400 }, - { -2036, -6083, 380, 1267 }, - { -2077, -7460, 380, -30 }, - { -1775, -7175, 1540, -386 }, - { -3065, -6927, 989, 168 }, - { -2836, -7602, 117, -3392 }, - { -1058, -6396, 593, -3078 }, - { -844, -6062, 999, -236 }, - { -3261, -6951, 1491, -720 }, - { -2186, -8484, 75, -1287 }, - { -2882, -7756, 456, -510 }, - { -1800, -6879, 960, -1183 }, - { -2554, -7241, 1614, -1474 }, - { -2608, -5305, 392, 851 }, - { -2973, -6562, -859, 858 }, - { -2640, -5989, 1031, -416 }, - { -977, -8366, 705, -1434 }, - { -1213, -7409, -77, -1390 }, - { -1335, -6657, 2125, -123 }, - { -2544, -6862, 1852, -737 }, - { -3235, -6422, 1752, -103 }, - { -1300, -7557, 939, -348 }, - { -3476, -7579, 202, -109 }, - { -2482, -6572, 753, 619 }, - { -2554, -8136, -648, -429 }, - { -1012, -7870, -3, -421 }, - { -3604, -6247, 32, -3102 }, - { -1486, -7271, 2013, -1021 }, - { -578, -6799, -523, 405 }, - { -2841, -5948, 1644, 911 }, - { -2411, -7473, 1084, -484 }, - { -2238, -6033, 294, -1059 }, - { -3459, -6470, -201, -790 }, - { -2027, -6009, 1833, 805 }, - { -1433, -8047, 1531, -1754 }, - { -3258, -7884, 763, -1422 }, - { -1544, -6928, -729, 478 }, - { -2314, -8415, 74, -3757 }, - { -3201, -5684, 95, -2214 }, - { -2423, -8694, 725, -3631 }, - { -3545, -7071, 1162, -1798 }, - { -294, -9662, 403, -2274 }, - { -2290, -5460, 1196, 402 }, - { -1603, -6713, 903, -2363 }, - { 4121, 2491, -3142, -2482 }, - { 4500, 3305, -3671, -1567 }, - { 5973, 3172, -1348, -534 }, - { 4830, 3379, -1549, 643 }, - { 5214, 3938, -2641, -2302 }, - { 4639, 4826, -5532, -847 }, - { 5639, 2731, -2170, -963 }, - { 6084, 3487, -3525, -1346 }, - { 5971, 3154, -2190, -2316 }, - { 5618, 4865, -6927, 116 }, - { 5345, 3568, -7391, 709 }, - { 5429, 5078, -3811, -1524 }, - { 6960, 2037, -3515, -1096 }, - { 7092, 2531, -4557, -588 }, - { 6061, 4247, -5651, -478 }, - { 4595, 3684, -4907, -827 }, - { 7497, 3213, -3048, -424 }, - { 5996, 2137, -3098, -1745 }, - { 6198, 5199, -2223, -2274 }, - { 6888, 2851, -2768, -1675 }, - { 6114, 4210, -2316, -954 }, - { 7127, 4242, -3041, -1408 }, - { 6126, 3668, -1517, -1427 }, - { 6245, 6129, -4225, -1186 }, - { 6816, 3213, -2101, -964 }, - { 5345, 5276, -2643, -847 }, - { 6592, 4665, -4338, 484 }, - { 6746, 3751, -3443, 124 }, - { 5453, 1980, -2738, 2606 }, - { 4662, 2179, -4226, -1059 }, - { 5571, 3208, -3554, 174 }, - { 5256, 4447, -1815, -1481 }, - { 5400, 2570, -1210, 235 }, - { 7056, 2549, -2674, 318 }, - { 4574, 4340, -2892, -130 }, - { 6203, 4587, -3273, -305 }, - { 5103, 1925, -2715, -2137 }, - { 3905, 4296, -1700, 247 }, - { 4421, 4605, -3299, 811 }, - { 5671, 1273, -3870, -924 }, - { 5486, 1805, -4901, 133 }, - { 6437, 2578, -1828, -106 }, - { 5530, 5253, -5058, 1223 }, - { 4816, 2025, -1215, 1443 }, - { 3457, 3525, -2456, 3217 }, - { 3316, 2595, -1108, 2459 }, - { 3068, 3810, -2207, 1926 }, - { 6351, 5436, -6470, 600 }, - { 6324, 4240, -5365, 2416 }, - { 4851, 4774, -4075, 1878 }, - { 4900, 3679, -5198, 1078 }, - { 8347, 3633, -4565, -171 }, - { 5244, 5718, -3853, 173 }, - { 3960, 3492, -2939, 2105 }, - { 6070, 3473, -2351, 161 }, - { 8228, 3034, -3360, -901 }, - { 7006, 3985, -1940, -1926 }, - { 7123, 4681, -4301, -878 }, - { 5122, 4097, -1851, -449 }, - { 6200, 2060, -2251, 1049 }, - { 7106, 3844, -7209, 2625 }, - { 7108, 3370, -6734, 533 }, - { 6859, 2849, -3992, 1360 }, - { 5458, 2278, -3253, 1131 }, - { -1072, -2109, 4783, -1073 }, - { -319, -2604, 4257, -2418 }, - { 2466, 1300, 3476, -314 }, - { 2847, -1502, 5296, -141 }, - { 1667, -1273, 5559, -2725 }, - { 2877, -3402, 6434, 204 }, - { 53, -2637, 5275, -1181 }, - { 1091, -2215, 5803, -1549 }, - { 2397, -922, 4327, 1182 }, - { 219, -3747, 4647, -1564 }, - { -29, -2705, 4812, 1277 }, - { 1499, -2608, 5648, 1407 }, - { 2139, -2399, 4202, 2791 }, - { -426, -2064, 5528, 151 }, - { 2560, -2803, 6179, -2806 }, - { 4537, -2479, 3797, 1095 }, - { 888, -3357, 5341, -415 }, - { 4460, -1814, 5388, -1227 }, - { 3920, -3268, 6364, -703 }, - { 3343, -4698, 4410, 784 }, - { 309, -1897, 6306, 1223 }, - { 958, -3318, 4254, -3167 }, - { -99, 1596, 6018, -1983 }, - { -429, -853, 6407, 878 }, - { 1170, -1322, 6290, -417 }, - { 2288, -505, 6303, -1999 }, - { 3312, -1674, 6749, -2494 }, - { -415, -3401, 4721, -371 }, - { -189, -1210, 4844, -2002 }, - { 888, -4142, 4377, 130 }, - { 2469, -4381, 5398, -2492 }, - { 2879, -2912, 5094, -2598 }, - { -717, -617, 5650, -685 }, - { 1470, -3863, 5352, -1684 }, - { 3935, -96, 3823, -730 }, - { 3769, -430, 3168, 694 }, - { 2556, 385, 3539, 512 }, - { 77, -1415, 5111, 2655 }, - { 2724, -2158, 6715, -822 }, - { 1832, 1001, 5385, -1900 }, - { 900, 2198, 4464, -559 }, - { 441, 69, 5921, -1743 }, - { -1161, 738, 6732, -308 }, - { 257, 2035, 4091, 736 }, - { 1607, 1288, 4355, -23 }, - { -13, 1316, 4180, 1672 }, - { 1511, 1336, 3057, 1435 }, - { 2189, -3813, 4530, 939 }, - { 3632, -706, 2646, 1375 }, - { 4266, -3761, 4241, 1077 }, - { 3101, -427, 5273, -1202 }, - { 2293, 276, 4810, -313 }, - { 3430, -1851, 3101, 2045 }, - { 3453, -2979, 5142, 942 }, - { 1683, -3281, 4802, 2002 }, - { 3954, -4715, 5611, 578 }, - { 1272, -155, 5085, 454 }, - { 128, -194, 5095, 1409 }, - { 820, 880, 5797, -2658 }, - { -1095, 656, 5774, 1095 }, - { 813, -1669, 4320, -3251 }, - { -119, 518, 6372, -651 }, - { 2922, -4299, 6115, -877 }, - { 4205, -4273, 4004, 2642 }, - { -1211, -3892, 224, 3127 }, - { -34, -4371, 1321, 2318 }, - { 77, -6326, 1201, 828 }, - { 3995, -3775, 1958, 3233 }, - { 178, -3301, 1985, 3318 }, - { 2330, -3801, 1033, 3195 }, - { 1413, -5536, 826, 1709 }, - { 2468, -3499, 3653, 3631 }, - { 741, -4617, 1723, 2008 }, - { 1246, -3043, 2978, 3949 }, - { -343, -4308, 2258, 2189 }, - { -682, -4640, 454, 2272 }, - { 1236, -4829, 2491, 1642 }, - { -512, -3766, 1182, 3052 }, - { 119, -3939, 3712, 971 }, - { -1145, -4624, 1360, 2281 }, - { 101, -4746, 2866, 1255 }, - { -1500, -5455, 539, 1637 }, - { -969, -5909, 1414, 1128 }, - { -1261, -4939, -231, 2022 }, - { -226, -5345, 1207, 705 }, - { 2712, -5109, 3205, 1866 }, - { -476, -5913, 273, 1208 }, - { -2039, -4464, 624, 2545 }, - { -2351, -3930, 2019, 2673 }, - { -2675, -4849, 1522, 1990 }, - { -1524, -3461, 1446, 3204 }, - { 477, -5314, 1710, 1577 }, - { 656, -3729, 2346, 2511 }, - { 550, -5917, 1975, 1040 }, - { 1728, -4704, 3067, 1058 }, - { -9, -5247, 506, 1760 }, - { -574, -5135, 1675, 1672 }, - { 2129, -3781, 3444, 2313 }, - { 1144, -4439, 2214, 2529 }, - { 1292, -4160, 3185, 1833 }, - { 2445, -3262, 2534, 3227 }, - { 2266, -4401, 2023, 2400 }, - { -587, -3602, 3408, 2067 }, - { -885, -4951, 3228, 1174 }, - { -728, -2711, 2807, 3552 }, - { 1019, -3043, 3195, 2954 }, - { 1888, -4615, 1140, 2454 }, - { 660, -5616, 754, 800 }, - { -1975, -5371, 1649, 1585 }, - { -1544, -5436, 2422, 1081 }, - { -422, -5882, 2390, 750 }, - { 1336, -5557, 2441, 1230 }, - { 136, -4001, 267, 2854 }, - { -522, -3289, 2226, 2728 }, - { -971, -4580, 2471, 708 }, - { 704, -5306, 3300, 1001 }, - { 325, -3464, 3555, 2398 }, - { 794, -3686, 848, 3169 }, - { 660, -3017, 4584, 3242 }, - { -1486, -3978, 2170, 1644 }, - { -1615, -4650, 2688, 1844 }, - { 750, -4578, 538, 2239 }, - { 1668, -5849, 1455, 1031 }, - { 3486, -4681, 2030, 2183 }, - { 2642, -5429, 1696, 1761 }, - { 4491, -4502, 3538, 2767 }, - { 3545, -4528, 3514, 2982 }, - { 3269, -3676, 2758, 3966 }, - { 5572, 1146, 209, -3379 }, - { 7459, 1053, 593, -1896 }, - { 4480, 200, -310, -4259 }, - { 5577, -939, 242, -3992 }, - { 8142, 442, 1257, -3083 }, - { 5442, 1261, 1424, -3236 }, - { 6260, -183, 3125, -2532 }, - { 7179, 889, 1618, -2548 }, - { 6416, 932, 2379, -2487 }, - { 7094, 2560, 961, -3392 }, - { 7322, 463, 2732, -3735 }, - { 6632, 1577, 1912, -3272 }, - { 6312, 1349, 3028, -3460 }, - { 6105, 386, 1213, -977 }, - { 5478, 1158, 1114, -486 }, - { 6493, 410, 1686, -2180 }, - { 6378, 1881, 1333, -2240 }, - { 5711, 812, 1958, -1300 }, - { 6844, 877, 730, -1189 }, - { 6824, -245, 2249, -2000 }, - { 7515, 1521, 1251, -3058 }, - { 6697, 1051, 1300, -1749 }, - { 6476, 1425, 811, -2773 }, - { 7350, 465, -76, -2849 }, - { 6975, 2095, 567, -2492 }, - { 4691, 1736, 2660, -2289 }, - { 7837, 1456, 340, -2767 }, - { 7930, 507, 838, -2074 }, - { 6106, 1502, 766, -1110 }, - { 4891, -659, 835, -3954 }, - { 7250, 141, 1369, -1523 }, - { 7651, 67, 1651, -2298 }, - { 7364, -305, 601, -3132 }, - { 7179, 193, 2491, -2871 }, - { 6504, -272, 2167, -1322 }, - { 4456, 983, 2300, -421 }, - { 4817, 457, 1695, 371 }, - { 6914, 555, 850, -3159 }, - { 5904, 1030, 202, -1959 }, - { 6258, 880, 2233, -4503 }, - { 6029, 10, 2130, -3600 }, - { 6449, 985, 1129, -3963 }, - { 6616, -18, -111, -3285 }, - { 4496, 775, 817, -4276 }, - { 6134, 2338, 1470, -2973 }, - { 6911, 152, 430, -1946 }, - { 4053, 991, 3218, -1193 }, - { 5435, 1285, 3124, -2412 }, - { 5507, 1836, 1935, -1988 }, - { 5240, 689, 2189, -2670 }, - { 6638, 1719, 606, -1799 }, - { 5556, -180, 129, -2595 }, - { 5644, 1918, 1281, -4316 }, - { 6410, 1088, -282, -3117 }, - { 6503, 1841, 312, -3514 }, - { 6947, 20, 1358, -3886 }, - { 5464, 2109, 2398, -3194 }, - { 5616, -407, 2140, -498 }, - { 6121, 2707, 2379, -4096 }, - { 7303, 1846, 2266, -4095 }, - { 5444, 470, 2718, -1553 }, - { 5817, -645, 3285, -1349 }, - { 5625, 1427, 1103, -1991 }, - { 6041, -806, 1196, -2943 }, - { 3050, -5722, 4070, -5460 }, - { 3420, -4386, 4078, -5155 }, - { 6020, -3982, 7268, -2689 }, - { 7502, -4317, 7894, -3973 }, - { 4156, -3558, 5247, -4316 }, - { 4725, -4401, 7290, -1540 }, - { 6688, -5122, 8216, -3210 }, - { 9176, -6576, 9276, -4963 }, - { 8706, -5708, 7987, -4621 }, - { 7060, -3535, 6532, -3308 }, - { 5600, -2719, 5363, -1568 }, - { 4661, -2803, 6263, -4716 }, - { 3673, -3636, 6147, -3433 }, - { 5305, -2585, 6073, -2638 }, - { 7614, -1962, 6079, -5266 }, - { 6760, -3366, 7382, -4322 }, - { 6385, -3883, 4797, -1353 }, - { 8182, -5120, 4298, -4641 }, - { 9130, -6198, 4975, -3063 }, - { 7421, -5436, 5576, -3713 }, - { 3483, -4898, 5443, -2745 }, - { 4907, -5643, 6390, -4105 }, - { 8119, -7008, 7992, -6764 }, - { 6528, -6122, 6967, -5590 }, - { 5890, -4190, 6624, -5688 }, - { 6815, -7934, 7275, -5456 }, - { 5434, -4306, 5169, -5378 }, - { 4364, -6436, 5376, -2604 }, - { 8152, -3404, 5913, -5048 }, - { 7983, -4863, 4262, -2461 }, - { 8023, -6188, 6238, -5062 }, - { 6753, -3692, 3935, -3723 }, - { 6826, -4760, 3284, -4051 }, - { 7224, -7423, 4492, -3875 }, - { 6904, -2590, 6587, -6248 }, - { 6106, -1944, 7345, -5506 }, - { 4956, -2990, 7808, -3146 }, - { 6908, -6885, 5949, -1288 }, - { 7162, -6058, 3419, -3401 }, - { 7015, -7080, 6907, -3018 }, - { 6971, -6832, 5646, -3273 }, - { 8014, -5546, 5471, -1544 }, - { 6792, -2220, 5105, -2879 }, - { 8494, -3974, 4408, -3999 }, - { 9591, -4866, 6027, -4558 }, - { 5264, -5161, 6101, -738 }, - { 5803, -6141, 5197, -5231 }, - { 4657, -6822, 3232, -5189 }, - { 4791, -5135, 3809, -4665 }, - { 6108, -5103, 2379, -3873 }, - { 4680, -3909, 3234, -5093 }, - { 5802, -3853, 3795, -4984 }, - { 4360, -7483, 4802, -3877 }, - { 5429, -7517, 5911, -3717 }, - { 6866, -2280, 4880, -4634 }, - { 10131, -4628, 4414, -4092 }, - { 10811, -5189, 7746, -5337 }, - { 5663, -8941, 5287, -5680 }, - { 8023, -5991, 7403, -2796 }, - { 9669, -6919, 6525, -4932 }, - { 7275, -3796, 4962, -2547 }, - { 8848, -4806, 5677, -3080 }, - { 8128, -4308, 7749, -6569 }, - { 4032, -5196, 2282, -6239 }, - { 6593, 700, -229, 304 }, - { 8260, 539, -66, -1259 }, - { 6605, 176, -814, -109 }, - { 8057, 0, -1, -136 }, - { 7382, -38, -484, -1129 }, - { 8373, -929, 682, -454 }, - { 7674, 690, -1278, 546 }, - { 7326, -517, 406, -1283 }, - { 7612, -1715, -1167, 1175 }, - { 8590, 441, -782, -710 }, - { 8572, -1202, -291, 260 }, - { 7308, -147, -1785, 414 }, - { 6787, -353, -672, 934 }, - { 5177, -133, 179, 82 }, - { 4161, -34, 447, 1497 }, - { 5997, -902, 1533, -121 }, - { 5727, -871, -1370, 945 }, - { 8386, -252, 293, -823 }, - { 6573, -1354, 682, 616 }, - { 7650, -2096, 725, 457 }, - { 8122, 78, 636, -1400 }, - { 8421, 428, -1620, 131 }, - { 7341, -1292, -717, 186 }, - { 7998, -49, -720, 266 }, - { 5987, -351, 669, 844 }, - { 7314, -1620, 250, -603 }, - { 7219, -1562, -572, 1994 }, - { 8682, -358, -290, -388 }, - { 5810, 155, -178, 1199 }, - { 7246, -12, 1042, -786 }, - { 7357, -923, 1468, -475 }, - { 7801, 621, -212, -724 }, - { 5346, -514, 1210, 1356 }, - { 8459, 36, -127, -779 }, - { 6878, -2429, 854, 1750 }, - { 7280, -1401, -1353, 2845 }, - { 7579, -2148, -1463, 2087 }, - { 6637, 946, -872, 750 }, - { 4807, -1100, 1289, 2602 }, - { 4495, 219, 1551, 1128 }, - { 7639, 506, 446, -1107 }, - { 6359, 188, 1009, -115 }, - { 6641, -1820, 1655, 723 }, - { 5394, -2382, 1604, 2542 }, - { 6021, -2644, 2396, 1407 }, - { 4698, 882, 245, 1525 }, - { 8103, 573, -798, -349 }, - { 8045, -519, 997, -1092 }, - { 7571, -122, 227, -338 }, - { 5347, -1200, 630, 1718 }, - { 7070, 790, 218, -544 }, - { 7440, 728, -527, -20 }, - { 6402, -355, 197, -736 }, - { 4031, 771, 866, 1895 }, - { 6009, 896, 445, -31 }, - { 5160, 1098, -856, 1784 }, - { 7980, -886, -1293, 1396 }, - { 6318, -1361, 2423, 252 }, - { 7547, -699, 133, 506 }, - { 8562, -2344, 940, 264 }, - { 5890, 1187, -1425, 2194 }, - { 6558, -645, -1311, 2621 }, - { 4634, -1671, 2075, 1623 }, - { 5614, 105, -816, 2376 }, - { 6646, 1558, -1365, 630 }, - { 6998, 1150, -2117, -990 }, - { 6555, 2311, -1093, -1783 }, - { 6682, 1430, -2391, -1940 }, - { 7861, 1555, -2977, -1188 }, - { 6745, 1723, -459, -2085 }, - { 7504, 1229, -1666, -2060 }, - { 7937, 671, -2128, -1529 }, - { 7139, 991, -735, -2632 }, - { 6867, 1592, -1303, -2324 }, - { 6401, 2230, -1732, -2508 }, - { 7201, 2184, -2169, -1988 }, - { 6636, 2190, -995, -2840 }, - { 7620, 2306, -2089, -651 }, - { 7584, 1875, -1438, -631 }, - { 9214, 1561, -2464, -1139 }, - { 6154, 1318, -1237, -2917 }, - { 7917, 2847, -1797, -1599 }, - { 8309, 2029, -2555, -465 }, - { 8204, 1282, -584, -2405 }, - { 8440, 1035, -1147, -1137 }, - { 7107, 1858, -60, -1568 }, - { 6781, 2912, -873, -1463 }, - { 7603, 1316, -319, -1249 }, - { 7833, 1335, -78, -1849 }, - { 7930, 1141, -1016, -695 }, - { 7883, 1610, -1017, -1314 }, - { 8069, 1409, -1811, -196 }, - { 8319, 1031, -582, -1590 }, - { 5948, 1537, -2153, -2373 }, - { 8684, 1171, -1871, -850 }, - { 8357, 2484, -2411, -1292 }, - { 6516, 2092, -193, -1167 }, - { 6112, 1697, 22, -525 }, - { 7161, 703, -602, -1879 }, - { 6047, 2351, -807, -219 }, - { 8072, 1854, -1817, -1553 }, - { 6956, 1304, 76, -1011 }, - { 6607, 1481, -544, -162 }, - { 6958, 2541, -265, -1938 }, - { 6416, 2514, -777, -850 }, - { 7272, 2110, -899, -1171 }, - { 7741, 2153, -283, -2614 }, - { 6482, 2041, -1758, -1221 }, - { 6762, 940, -1862, -2281 }, - { 5610, 1194, -1691, -1561 }, - { 7833, 2164, -823, -1952 }, - { 5460, 1438, -848, 1189 }, - { 6011, 1377, -771, -1557 }, - { 7679, 544, -1134, -2214 }, - { 7209, 1292, -2714, -1564 }, - { 5567, 1200, -404, -169 }, - { 5853, 1461, -1465, -518 }, - { 6782, 689, -844, -860 }, - { 7330, 1337, -1152, -71 }, - { 7189, 1506, -653, -685 }, - { 6860, 2116, -1403, -240 }, - { 8804, 1516, -1391, -1760 }, - { 7210, 2689, -1498, -989 }, - { 7030, 3022, -1441, -2083 }, - { 5649, 1836, -407, 525 }, - { 7451, 3099, -717, -2464 }, - { 7384, 1656, -2007, 398 }, - { 6504, 707, -1919, -134 }, - { -1851, 3639, -2279, -695 }, - { -4037, 1644, -77, 1329 }, - { -4025, 1960, -1565, -567 }, - { -3430, 2495, -795, 368 }, - { -4771, 2480, 993, 756 }, - { -3431, 2058, -2539, -971 }, - { -3802, 3418, 380, 217 }, - { -3074, 3350, -1652, -1056 }, - { -3705, 326, -1650, 1535 }, - { -3122, 1281, -1192, 1607 }, - { -4601, 1367, -968, 53 }, - { -3808, 958, 44, 2560 }, - { -2079, 2530, -1485, 1166 }, - { -3707, 343, -2889, 180 }, - { -5249, 1431, -31, 688 }, - { -4990, 125, -704, 1270 }, - { -2771, 1334, -2446, 746 }, - { -2292, 994, -1527, 2630 }, - { -1261, 3070, -2519, 268 }, - { -2544, 3890, -1057, -552 }, - { -4421, 255, -1980, 530 }, - { -2951, 454, -13, 3643 }, - { -2262, 1815, -370, 2880 }, - { -2383, 3657, -649, 576 }, - { -3541, -161, -1389, 2550 }, - { -4241, 1575, 1325, 2561 }, - { -2767, 4037, 1221, 1578 }, - { -3748, 2697, 1148, 1801 }, - { -4686, 2385, -220, 0 }, - { -1531, 1645, -2751, 1327 }, - { -45, 4032, -799, 2298 }, - { -2915, 2280, 709, 2495 }, - { -1199, 3278, -406, 2346 }, - { -2471, 116, -2706, 2060 }, - { -2440, 2173, -2894, -344 }, - { -3375, 2287, 1781, 3226 }, - { -2153, 3568, 1827, 2918 }, - { -862, 2267, -1626, 2527 }, - { -2698, 1135, 301, 4239 }, - { -2364, 2123, 1010, 3710 }, - { -2447, 3281, -81, 1408 }, - { -2660, 4735, 472, 258 }, - { -1053, 3097, 2682, 2398 }, - { -3366, -1037, -1152, -868 }, - { -643, 4242, 2212, 1259 }, - { 971, 3991, 934, 643 }, - { -1617, 2002, 2139, 2195 }, - { -4897, 972, 784, 1719 }, - { -1275, 2992, 1039, 3821 }, - { -392, 4973, -209, 1821 }, - { -1028, 4718, -1479, -137 }, - { 50, 3914, 553, 2210 }, - { 678, 4364, 359, 1303 }, - { -582, 4911, 514, 1671 }, - { 1276, 3914, -1252, 2934 }, - { -1496, 3984, 857, 2330 }, - { 772, 4744, -655, 2332 }, - { -799, 5283, -439, 624 }, - { 1341, 2937, 650, 2027 }, - { -1739, 4892, 1275, 1702 }, - { -892, 2596, -151, 3951 }, - { -3532, 1090, 1292, 32 }, - { 321, 3146, 2647, 1475 }, - { 264, 4199, -1591, 1317 }, - { -452, -2357, 2266, 4192 }, - { 3022, -1033, -2389, 5678 }, - { -1162, -1342, 3543, 4990 }, - { -474, -1477, -1223, 5016 }, - { -699, -2857, 900, 3835 }, - { -461, -2255, -117, 4626 }, - { 1204, -2062, -1211, 4403 }, - { 2192, -3035, -337, 3966 }, - { 108, -831, 279, 5643 }, - { 1457, -620, -2908, 5276 }, - { -2527, -78, 1085, 5460 }, - { -1978, -1918, -949, 4733 }, - { 32, 367, -1904, 5166 }, - { 1890, -1665, 440, 4752 }, - { -518, -348, 2816, 4891 }, - { 3695, -2490, -1374, 4603 }, - { 246, -1965, 3549, 3969 }, - { 1100, -3111, 656, 3737 }, - { -1379, 870, -414, 4575 }, - { 628, -357, -1227, 6179 }, - { -1129, -1318, -2457, 4576 }, - { -425, -98, -73, 6336 }, - { 367, -887, 2990, 4207 }, - { 2091, -1251, 2444, 3557 }, - { -1759, -1610, 2046, 5273 }, - { 3210, 1414, -20, 2616 }, - { 3303, -2636, 1005, 4237 }, - { -327, -3107, -640, 3687 }, - { -197, 764, 572, 5486 }, - { 646, -767, 1388, 5464 }, - { 104, 2742, -228, 3907 }, - { -236, 1829, -579, 4585 }, - { -2150, -474, -1525, 4006 }, - { -23, -2632, -2400, 3892 }, - { -12, -1739, -2910, 4867 }, - { -2310, -368, -102, 4583 }, - { -1991, -2061, 533, 4531 }, - { 3884, -1446, -153, 4393 }, - { 1568, 14, -289, 5268 }, - { -1376, -253, -2797, 3417 }, - { 3193, -2577, 2475, 3566 }, - { 3418, 617, 1350, 1857 }, - { 3792, -24, -272, 3370 }, - { 153, 1159, 2906, 2877 }, - { 511, 2162, 1548, 2741 }, - { 262, 819, -2791, 3734 }, - { 4232, -2015, 1486, 3477 }, - { 2943, -1110, -1014, 5480 }, - { 2842, 369, 703, 3476 }, - { 3011, 1634, -933, 3553 }, - { 4412, -1548, -942, 5021 }, - { -1405, 593, 2372, 5267 }, - { 2093, 2129, 896, 2365 }, - { 4845, -1980, 0, 3823 }, - { -2140, 81, 3278, 5637 }, - { 1484, 2665, -324, 3653 }, - { 10, 192, 1620, 5291 }, - { 2152, 738, -2269, 5000 }, - { 2102, 2748, -1652, 4707 }, - { 2855, -2131, -387, 5188 }, - { 1173, 676, 1338, 3277 }, - { 2340, -2329, -2064, 4095 }, - { 861, -2024, 1296, 5055 }, - { 2189, 3225, -695, 2626 }, - { 6196, -7079, 1943, -822 }, - { 4547, -4813, 3261, 1856 }, - { 4243, -6904, 3443, 448 }, - { 4581, -7503, 946, 506 }, - { 6626, -7754, 3427, 470 }, - { 3407, -9088, 3269, -1496 }, - { 4079, -6464, 2304, 777 }, - { 5621, -9336, 2684, -768 }, - { 5351, -6464, 5238, -214 }, - { 5961, -8007, 1724, -3091 }, - { 4213, -8067, 603, -246 }, - { 7208, -7403, 3168, -1738 }, - { 6098, -7700, 329, -1379 }, - { 6525, -6735, 4248, -1072 }, - { 6073, -6241, 2167, -2378 }, - { 4609, -9218, 3051, -1033 }, - { 6813, -7283, 1581, -1897 }, - { 6126, -6275, 2789, 681 }, - { 4423, -6538, 1621, -1692 }, - { 6272, -8298, 3167, -1855 }, - { 6172, -8558, 4498, -1169 }, - { 4844, -8588, 1647, -366 }, - { 6209, -8807, 1581, -369 }, - { 5389, -8059, 550, -192 }, - { 6654, -9775, 2504, -1063 }, - { 7103, -7998, 806, 530 }, - { 5662, -6736, 1565, -3620 }, - { 4165, -9564, 4191, -2131 }, - { 4526, -7181, 576, -2875 }, - { 4633, -8623, 2807, -4742 }, - { 3709, -7794, 1815, 34 }, - { 3634, -8622, 2313, -826 }, - { 6991, -8447, 2063, -3198 }, - { 7757, -9486, 2255, -558 }, - { 4149, -7778, 4728, -1696 }, - { 5767, -7427, 1113, 707 }, - { 4592, -6261, 2329, 1864 }, - { 3159, -10498, 1677, -4273 }, - { 3534, -9010, 2437, -3565 }, - { 4479, -10821, 2715, -4942 }, - { 3207, -9805, 3054, -3886 }, - { 4627, -8189, 3018, -2354 }, - { 5527, -10566, 3244, -2749 }, - { 4346, -10127, 3335, -3084 }, - { 6132, -10085, 3316, -1308 }, - { 5629, -9704, 2178, -3058 }, - { 3603, -8538, 1246, -624 }, - { 3737, -8488, 395, -3167 }, - { 5465, -11414, 2810, -4640 }, - { 5306, -7745, 2721, -3988 }, - { 7000, -9111, 1695, -1409 }, - { 6663, -7741, 2466, -4079 }, - { 4083, -7175, 1836, -4831 }, - { 3613, -9926, 1342, -3455 }, - { 6588, -8033, 457, -258 }, - { 4720, -8102, 17, -1209 }, - { 7414, -8709, 1294, -344 }, - { 5437, -10030, 4043, -1704 }, - { 4862, -9281, 1558, -1431 }, - { 6800, -6403, 5113, 862 }, - { 4623, -8242, 2667, -228 }, - { 5919, -5083, 3348, 2135 }, - { 5985, -8889, 2733, -5105 }, - { 5029, -5767, 4407, 719 }, - { 354, -6158, -838, -3001 }, - { 351, -5943, -2104, -1534 }, - { -633, -7190, -25, -4798 }, - { -1595, -7235, -3812, -1400 }, - { 103, -6197, -2933, -78 }, - { -1722, -5020, -3441, -4333 }, - { -1963, -5644, -4365, -270 }, - { -846, -5743, -3477, 196 }, - { -191, -5348, -4054, -469 }, - { -2515, -7754, -3495, -818 }, - { -2090, -6710, -2701, 117 }, - { -546, -7036, -1398, 163 }, - { -278, -7091, -2662, -536 }, - { -622, -7962, -2731, -1464 }, - { -1555, -8118, -3612, -2057 }, - { -1094, -6280, -2314, 505 }, - { -2556, -8538, -4024, -2247 }, - { 109, -7134, -3107, -1823 }, - { -900, -6954, -3340, -717 }, - { -605, -7113, -3656, -2154 }, - { 837, -6263, -3211, -2177 }, - { -417, -5810, -3871, -1469 }, - { -1318, -5649, -4207, -3198 }, - { 413, -6765, -2082, -33 }, - { -3101, -6450, -4362, -766 }, - { 755, -6489, -2967, -846 }, - { 1117, -7106, -2452, -1352 }, - { -1202, -8387, -3072, -2897 }, - { -365, -4894, -3561, -2937 }, - { -2372, -8776, -265, -4441 }, - { -1224, -8678, -896, -5074 }, - { -755, -10096, -600, -6623 }, - { 300, -8206, -225, -4568 }, - { -1176, -6824, -2633, -3527 }, - { -2006, -5443, -1526, -5849 }, - { -1115, -5540, -2363, -4785 }, - { 1059, -6812, -2543, -2654 }, - { -1976, -6861, -3062, -5508 }, - { -379, -5328, -2321, -3624 }, - { -2108, -5860, -4518, -1915 }, - { -379, -7885, -1329, -594 }, - { 774, -5389, -581, -5213 }, - { -2601, -5083, -1849, -4921 }, - { -176, -5580, 74, -5075 }, - { -204, -6780, -190, -6232 }, - { 418, -7594, -1987, -820 }, - { -1873, -8529, -2926, -1609 }, - { 1340, -6362, -919, -4975 }, - { 577, -7990, -2044, -1873 }, - { -2572, -7413, -1745, -2224 }, - { -2037, -7030, -1461, -7138 }, - { -2559, -8756, -2039, -5836 }, - { -2079, -6764, -1209, -5669 }, - { -1613, -7801, -2006, -685 }, - { -1865, -6583, -722, -3529 }, - { -589, -6358, -1377, -1003 }, - { -540, -7514, -1331, -3542 }, - { 419, -6192, -1677, -4927 }, - { -2786, -8763, -2966, -5065 }, - { -2172, -8411, -1726, -4675 }, - { -3382, -9833, -3497, -5722 }, - { -2433, -10169, -2077, -5775 }, - { -424, -9451, -1096, -3658 }, - { -537, -8522, -910, -1897 }, - { -5550, 2807, 1683, -693 }, - { -6395, 635, 3573, -1246 }, - { -7544, 2280, 2140, 44 }, - { -8751, 1136, 2951, -794 }, - { -5605, 2709, 2052, 916 }, - { -7650, 654, 869, 135 }, - { -6939, 967, 1409, 870 }, - { -7834, 2123, 3310, 974 }, - { -6935, 2818, 1274, -1678 }, - { -5605, 2233, 1013, 471 }, - { -7095, 1849, 1648, 198 }, - { -6636, 1634, 712, -37 }, - { -7279, 978, 296, -315 }, - { -7664, 3504, 3292, -216 }, - { -7836, 1209, 1221, -257 }, - { -7913, 2201, 1765, -1529 }, - { -7077, 3783, 2632, -1407 }, - { -5565, 1645, 1410, -622 }, - { -6494, 2879, 1181, -759 }, - { -7073, 3137, 3010, 550 }, - { -7249, 1839, 847, -805 }, - { -6630, 2197, 282, -1096 }, - { -8836, 1573, 1988, -1090 }, - { -7809, 1274, 836, -1198 }, - { -7895, 2970, 3511, -1097 }, - { -6960, 1664, 1356, -2442 }, - { -6582, 2866, 2273, 307 }, - { -7221, 821, 2851, -1435 }, - { -6015, 1703, 2001, -2367 }, - { -8082, 1034, 2103, 239 }, - { -5952, 1912, 301, -465 }, - { -6099, 841, 379, 567 }, - { -6343, 50, 494, 658 }, - { -6586, 983, 591, -893 }, - { -5500, 869, 2187, -2479 }, - { -6482, 60, 1545, -979 }, - { -6705, 515, 1974, -53 }, - { -6460, 1755, 1325, -1275 }, - { -6093, 2617, 2465, -623 }, - { -7330, 2161, 594, -2115 }, - { -7324, 762, 1593, -2004 }, - { -6385, 679, 1510, -2514 }, - { -6159, 241, 2976, -1631 }, - { -8583, 3030, 4045, -162 }, - { -6299, 66, 2209, -2103 }, - { -5428, 1279, 3267, -1846 }, - { -6438, 1335, 2728, -1631 }, - { -8012, 1070, 2428, -1151 }, - { -6201, 2781, 2349, -1918 }, - { -5918, 1139, 3121, -148 }, - { -6314, 2481, 3137, -1808 }, - { -7180, 1722, 2435, -1602 }, - { -6750, 1829, 3763, -1145 }, - { -6713, 1777, 2221, 1212 }, - { -7479, 1835, 3627, -479 }, - { -7299, 10, 2406, -1593 }, - { -8249, 3129, 996, -2870 }, - { -8374, 1534, 1333, -1882 }, - { -7507, 3353, 1598, -2299 }, - { -7379, 2701, 2326, -1167 }, - { -8440, 2276, 2796, -542 }, - { -10348, 1527, 2649, -1165 }, - { -8184, 3614, 2574, -1738 }, - { -5539, 1574, 1733, 1138 }, - { 9404, -7652, 67, 79 }, - { 8654, -3972, 1358, -60 }, - { 8617, -4794, 117, 2318 }, - { 7886, -4505, 1784, 1200 }, - { 8636, -6125, 3879, -1003 }, - { 9654, -6836, 1816, 205 }, - { 9374, -6553, 913, 1875 }, - { 8020, -6150, 1134, 2390 }, - { 7786, -4970, 2078, -1857 }, - { 8691, -6119, 711, 708 }, - { 9039, -5568, 2944, -1902 }, - { 9955, -5048, 1433, -601 }, - { 8089, -6927, 3093, -2846 }, - { 8487, -7024, 2415, 19 }, - { 9388, -5287, 3577, -2655 }, - { 8591, -7371, 2300, -996 }, - { 9104, -4763, 1453, -2558 }, - { 7615, -5457, 596, 164 }, - { 9860, -7047, 3433, -614 }, - { 8756, -4404, 2235, -964 }, - { 9462, -4660, 299, -1822 }, - { 10119, -5550, 2689, -1273 }, - { 10915, -7471, 2705, -1007 }, - { 11433, -7090, 1410, -1198 }, - { 9882, -7431, 2965, -1895 }, - { 7628, -5219, 769, -2661 }, - { 8169, -5318, 2262, 70 }, - { 8846, -6320, 1939, -754 }, - { 7147, -5593, 1248, -971 }, - { 10652, -5485, 935, 137 }, - { 7778, -6533, 2564, -1932 }, - { 8878, -5173, 1214, -361 }, - { 9828, -4943, 282, 510 }, - { 10042, -6134, 3895, -1914 }, - { 7965, -6630, 3566, -433 }, - { 8573, -4502, 3574, -1209 }, - { 8398, -4801, 1031, -1347 }, - { 10136, -7772, 2612, 1547 }, - { 9890, -7280, 1768, -1083 }, - { 8407, -6585, -706, -58 }, - { 7976, -7582, 229, -131 }, - { 10481, -8866, 1166, -147 }, - { 10914, -4342, 3189, -2412 }, - { 10440, -5198, -104, -1109 }, - { 11227, -6530, 2381, -2449 }, - { 8487, -8064, 1086, 230 }, - { 9975, -6123, -857, -134 }, - { 8339, -6498, 1232, -2337 }, - { 11042, -4506, 1119, -2098 }, - { 12563, -5592, 1837, -2062 }, - { 11801, -5590, 632, -1296 }, - { 10152, -5617, 1511, -1917 }, - { 7800, -6473, 51, -1337 }, - { 7941, -5560, 2438, -3270 }, - { 6554, -3834, 2100, 1476 }, - { 9065, -5520, -226, -1120 }, - { 10794, -7120, -243, 122 }, - { 10429, -6968, 272, -806 }, - { 8942, -8914, 1442, -392 }, - { 9969, -5051, 2033, -2953 }, - { 7275, -4152, 3058, -64 }, - { 11127, -5488, 4589, -3227 }, - { 9626, -6666, 2739, -2958 }, - { 6943, -5362, 4470, 1008 }, - { -7456, -967, 2936, -1002 }, - { -8622, -333, 6962, 2606 }, - { -7486, -3392, 3668, 1287 }, - { -8053, -827, 5148, 1097 }, - { -6610, 454, 4952, 96 }, - { -7701, -1982, 3161, -468 }, - { -7307, -1132, 4071, -36 }, - { -8125, -271, 5199, 3862 }, - { -9182, -1950, 2813, 1878 }, - { -9855, -952, 4794, 3010 }, - { -7241, 1431, 4202, 2468 }, - { -9646, 157, 4766, 1046 }, - { -9371, 1230, 6009, 2958 }, - { -11514, -64, 8630, 5248 }, - { -6766, 565, 2766, 2140 }, - { -8426, -9, 2852, 1271 }, - { -11291, -1113, 5087, 2937 }, - { -8297, 2092, 4495, 1264 }, - { -9983, 735, 3809, -51 }, - { -9048, -1000, 3191, -308 }, - { -7331, -1987, 2655, 1391 }, - { -7144, -21, 4333, 2161 }, - { -6032, -1540, 3543, 896 }, - { -7987, -1036, 1985, 1529 }, - { -9264, 2004, 5194, 290 }, - { -11308, -840, 5754, 1654 }, - { -9130, -2398, 4292, 2973 }, - { -6248, 838, 3563, 1223 }, - { -6819, -2760, 3511, 119 }, - { -7213, -2006, 4364, 762 }, - { -5431, -1047, 4533, 166 }, - { -7098, -641, 2021, 639 }, - { -8628, -2249, 3588, 399 }, - { -6352, -1498, 3560, -648 }, - { -7033, -2190, 4870, 2562 }, - { -7405, -46, 3772, -581 }, - { -6104, 796, 5143, 1965 }, - { -5787, 943, 5784, 3030 }, - { -8367, 1465, 7192, 4097 }, - { -8259, 789, 5694, 1963 }, - { -10614, -1899, 5748, 2645 }, - { -8258, -805, 3698, 2275 }, - { -6877, -972, 6431, 3160 }, - { -6483, 363, 7018, 3129 }, - { -6283, -1358, 5191, 1524 }, - { -8853, -3157, 4119, 1741 }, - { -6086, -267, 3883, -835 }, - { -7254, 1032, 6613, 4017 }, - { -11470, -3350, 4649, 3426 }, - { -6743, 481, 6148, 1239 }, - { -5394, -166, 5309, 3165 }, - { -7958, 1068, 4268, -240 }, - { -10520, 2256, 7916, 2828 }, - { -5132, -4, 5739, 1176 }, - { -8643, 120, 3255, -629 }, - { -9631, 1974, 8870, 4362 }, - { -10663, -1221, 3733, 589 }, - { -8224, -1843, 5806, 2655 }, - { -8282, 1255, 8647, 3478 }, - { -12311, -1505, 9043, 6256 }, - { -11312, -856, 7136, 4681 }, - { -11944, -722, 7941, 3309 }, - { -7868, -463, 6846, 4196 }, - { -8679, -241, 7410, 5347 }, - { 6759, -4680, -508, 1220 }, - { 5176, -6111, 944, 121 }, - { 6843, -5667, -1368, -533 }, - { 5616, -5884, -1471, -695 }, - { 6030, -5089, -1808, -940 }, - { 7444, -5463, -52, 1881 }, - { 4207, -6079, -506, 1571 }, - { 6785, -4410, -649, 3084 }, - { 4838, -5214, 2026, 2998 }, - { 4201, -5790, 645, 1811 }, - { 6930, -5129, -1940, 1698 }, - { 6332, -4627, 692, 3027 }, - { 6285, -4314, -106, 3644 }, - { 6255, -5450, -1975, 742 }, - { 4199, -4676, -459, 1796 }, - { 5592, -5500, 1345, 1300 }, - { 4358, -5556, -2236, 114 }, - { 4620, -5875, -1563, 888 }, - { 4892, -7550, -327, -419 }, - { 4734, -7085, 7, 613 }, - { 3883, -5562, -1969, 1080 }, - { 5610, -4990, -204, 834 }, - { 4117, -6482, -1271, 341 }, - { 6585, -5107, 892, 1169 }, - { 6632, -3683, 302, 3002 }, - { 6326, -5351, -983, -1250 }, - { 4382, -7192, -730, -158 }, - { 5227, -6540, -451, 1123 }, - { 5468, -6472, -870, -1471 }, - { 5191, -6402, -1365, -127 }, - { 7407, -6317, -973, -336 }, - { 4611, -6530, -820, -1980 }, - { 4963, -5159, -2050, -966 }, - { 4414, -5691, -211, -998 }, - { 5954, -5873, 750, -1749 }, - { 4394, -4796, -1268, 254 }, - { 7161, -6214, -1010, 689 }, - { 4965, -3598, 2372, 1711 }, - { 6248, -6180, 981, 864 }, - { 6473, -5336, 525, -600 }, - { 4591, -6864, -1131, -900 }, - { 6314, -6440, -1021, -375 }, - { 5838, -6209, -1199, 944 }, - { 5308, -5283, -2100, 1267 }, - { 4342, -5860, -1637, -1356 }, - { 5680, -4388, -1227, -104 }, - { 4900, -4098, 1449, 4046 }, - { 4677, -4284, -106, 3190 }, - { 7574, -6173, -848, 1859 }, - { 6493, -7207, -131, 726 }, - { 5513, -5261, -2117, 4 }, - { 6191, -7352, -193, -505 }, - { 5885, -4333, 324, -134 }, - { 6162, -6081, -312, -2044 }, - { 4216, -6200, -1810, -572 }, - { 5652, -7035, -696, -197 }, - { 7131, -7189, -366, -60 }, - { 5032, -4803, -1514, 2832 }, - { 7386, -4610, -606, 3489 }, - { 4211, -5031, 1221, 3047 }, - { 4050, -4653, 1584, 1469 }, - { 6852, -5302, -1861, 206 }, - { 7736, -4816, -1794, 3359 }, - { 6290, -3439, 1522, 2454 }, - { 1768, 5990, -5560, -2594 }, - { 3903, 5326, -1530, -1501 }, - { 2472, 3738, -2117, -4240 }, - { 3260, 5448, -904, -4733 }, - { 1435, 7297, -3676, -4102 }, - { 4096, 5951, -656, -3312 }, - { 2178, 6009, -3146, -3724 }, - { 3787, 5493, -5473, -1633 }, - { 2998, 7286, -3334, -3571 }, - { 2894, 6576, -4708, -2804 }, - { 830, 6163, -4286, -3348 }, - { 4755, 5569, -1730, -2739 }, - { 4604, 6065, -3562, -2605 }, - { 2749, 5141, -3986, -2775 }, - { 3942, 4875, -2143, -3340 }, - { 2819, 8517, -2004, -2724 }, - { 2146, 6298, -689, -3093 }, - { 5196, 6504, -3393, -1475 }, - { 1851, 8386, -1748, -1420 }, - { 3474, 8572, -3534, -2688 }, - { 4503, 7560, -3561, -2245 }, - { 4433, 6219, -2393, -1575 }, - { 3506, 7248, -2275, -1977 }, - { 3490, 7409, -3147, -604 }, - { 4214, 6447, -3520, 516 }, - { 619, 7034, -829, -1705 }, - { 1732, 7395, -356, -2208 }, - { 1226, 5204, -3294, -3732 }, - { 2027, 5619, -1813, -4146 }, - { 3078, 5877, 47, -2651 }, - { 1654, 5458, 424, -682 }, - { 3163, 5464, -2026, -270 }, - { 2884, 5375, -685, -530 }, - { 2950, 7286, -35, -2967 }, - { 1986, 5066, -597, 482 }, - { 3459, 4308, -3845, -2333 }, - { 3155, 7037, -1346, -4345 }, - { 2193, 6696, -717, -1319 }, - { 3677, 5089, -3892, -487 }, - { 2186, 5136, -4186, -1492 }, - { 773, 5796, -917, 817 }, - { 2489, 6546, -3570, -2117 }, - { 1223, 6469, -1362, -33 }, - { 271, 6061, -1466, -1725 }, - { 2540, 5171, -1847, 1032 }, - { 2548, 5251, -2697, 1677 }, - { 771, 7600, -768, -632 }, - { 4710, 6647, -4736, -1275 }, - { 1369, 5917, -2971, -1056 }, - { 163, 5239, -3499, -2275 }, - { 2104, 4285, -3211, -3286 }, - { 1107, 7411, -1972, -1671 }, - { 2196, 7262, -2310, -1926 }, - { -244, 6439, -1745, -839 }, - { 3293, 3832, -2890, -3000 }, - { 419, 6443, -379, -407 }, - { 3077, 4930, -1156, -2869 }, - { 2131, 5874, -2330, 224 }, - { 690, 6538, -2212, -2841 }, - { 1602, 4421, -2515, 1542 }, - { 3318, 9373, -3032, -3477 }, - { 5646, 7462, -5153, -1463 }, - { 4139, 7137, -1539, -3321 }, - { 3481, 9077, -1645, -3653 }, - { -7747, 375, -106, -543 }, - { -8587, -1379, -586, -461 }, - { -10146, -892, 2094, 694 }, - { -8103, 382, 504, -325 }, - { -8548, -92, 94, -656 }, - { -7460, 38, 152, 388 }, - { -8266, -271, -459, -883 }, - { -7935, -664, -1026, -802 }, - { -8341, -109, 853, 161 }, - { -8802, -1355, 1099, 630 }, - { -8957, -6, 1108, -669 }, - { -7260, -1520, -43, -407 }, - { -7555, -174, 668, -2562 }, - { -9014, -126, 227, -1191 }, - { -8184, 769, 290, -1375 }, - { -9476, 55, 962, -1528 }, - { -8679, 541, 755, -1030 }, - { -9842, -1626, 838, -1588 }, - { -8513, -702, 788, -1998 }, - { -10101, -1558, -366, -1841 }, - { -8135, 78, 1479, -1813 }, - { -9128, -454, 313, -1786 }, - { -7554, -1084, 831, -2442 }, - { -7576, -701, 2068, -1665 }, - { -7791, -1481, 1587, -1808 }, - { -6701, -596, -97, 802 }, - { -7418, -15, 684, -963 }, - { -7127, -477, -139, -426 }, - { -8097, -110, -36, -264 }, - { -7620, -1922, -590, -101 }, - { -7647, -1201, 279, 660 }, - { -7856, -1974, 758, -2271 }, - { -8496, -167, 2232, -1143 }, - { -8506, -1359, 624, -740 }, - { -7274, -1052, 1062, -139 }, - { -7800, -217, 91, -1794 }, - { -7030, -1694, -955, 615 }, - { -9020, -1864, 101, -2182 }, - { -9400, -740, 598, -667 }, - { -8448, -1184, 2024, -1272 }, - { -8812, -570, -897, -2384 }, - { -10559, -1286, 538, -1536 }, - { -8728, -888, -1089, -1397 }, - { -7080, -1185, 636, -1252 }, - { -9880, 233, 2344, -782 }, - { -7952, -1326, -378, -1947 }, - { -7207, -378, 1408, -2237 }, - { -8467, -1545, 902, -1987 }, - { -9163, -1474, 924, -1739 }, - { -8159, -992, -77, -2744 }, - { -8343, 148, -423, -1573 }, - { -9105, -649, -254, -1214 }, - { -8939, 456, 281, -1905 }, - { -8837, 179, -394, -2634 }, - { -9145, 757, 1547, -1319 }, - { -9775, -723, 441, -1680 }, - { -8910, -686, 1529, -1525 }, - { -9492, -1134, 2064, -938 }, - { -6111, -943, 677, -31 }, - { -7411, -613, -814, 46 }, - { -9479, -922, -430, -2061 }, - { -11298, -1268, 1318, -1117 }, - { -8190, 832, 671, -2214 }, - { -10453, -550, 1672, -886 }, - { 1044, 9353, -1651, -5423 }, - { 1034, 8149, -455, -6166 }, - { 761, 8293, -3214, -4838 }, - { 938, 8077, 164, -5130 }, - { 1295, 8673, 2582, -5490 }, - { -314, 7973, -2395, -5231 }, - { -507, 9012, -2497, -5775 }, - { 2396, 8314, -1022, -4673 }, - { -1516, 8501, 1950, -4969 }, - { -308, 7401, 1549, -4866 }, - { -112, 8340, 3003, -4920 }, - { -50, 9315, 1371, -5666 }, - { -659, 9449, 2496, -5547 }, - { 2573, 9148, -2270, -4783 }, - { 830, 7104, -438, -3907 }, - { 522, 10672, -677, -6483 }, - { -1190, 10108, -510, -6518 }, - { -427, 8271, -579, -6315 }, - { 1602, 8113, -1927, -4418 }, - { -2266, 8180, 448, -5190 }, - { -1633, 8816, -226, -5771 }, - { 759, 9481, -105, -5813 }, - { 2254, 6679, -466, -5662 }, - { -88, 6946, 895, -5958 }, - { -1705, 10009, 1394, -5574 }, - { 748, 7943, 540, -6692 }, - { 1411, 7009, 232, -6145 }, - { 697, 7290, -1221, -5342 }, - { -1764, 10580, 1944, -3981 }, - { -1334, 9124, 1195, -3903 }, - { -905, 10067, 635, -5039 }, - { 664, 10680, 49, -4625 }, - { 1374, 9536, -777, -3591 }, - { 252, 9698, -597, -2931 }, - { 824, 9164, -1014, -2144 }, - { 2438, 10569, -2289, -4424 }, - { 2101, 7102, 507, -3614 }, - { 294, 8051, -432, -1518 }, - { -665, 10337, 547, -2852 }, - { 1168, 11989, -492, -5427 }, - { 1344, 6416, 302, -5061 }, - { -1727, 12264, 1507, -4543 }, - { 674, 10889, -902, -3605 }, - { -582, 9504, 300, -3618 }, - { 641, 7654, 689, -2109 }, - { 2065, 9243, 508, -4367 }, - { 1055, 8373, 688, -3144 }, - { -641, 8185, 986, -3307 }, - { 1120, 7426, 1785, -3757 }, - { 1660, 8070, -593, -3104 }, - { 2002, 9467, -1722, -3475 }, - { 2361, 8368, 100, -3709 }, - { -772, 7845, -613, -4988 }, - { 1485, 7430, 1896, -6127 }, - { -432, 7823, -947, -2882 }, - { 313, 11122, -760, -4871 }, - { 412, 8412, -283, -4231 }, - { 1585, 10402, -1884, -3267 }, - { 321, 6952, 773, -3016 }, - { -105, 9014, 121, -2249 }, - { 1585, 10313, -977, -4812 }, - { 1619, 11869, 1306, -6876 }, - { -1168, 8886, -81, -2500 }, - { -395, 10886, 733, -6490 }, - { -4949, 4274, 3992, -1054 }, - { -4241, 5299, 4262, -1584 }, - { -2710, 3862, 4552, -1673 }, - { -4608, 2472, 3672, -1715 }, - { -2843, 2816, 4003, -2326 }, - { -5229, 2964, 5636, 90 }, - { -4924, 3442, 5015, -1096 }, - { -1281, 3313, 5537, -2066 }, - { -3808, 1939, 4351, -919 }, - { -1915, 2585, 4939, -1614 }, - { -3470, 1843, 5562, -682 }, - { -3800, 870, 5827, 144 }, - { -4985, 1452, 4728, -709 }, - { -3745, 2750, 7220, 259 }, - { -1875, 1900, 6514, -826 }, - { -4329, 1574, 7192, 1304 }, - { -5408, 1444, 6208, 631 }, - { -3327, 5312, 5707, -1541 }, - { -6966, 3334, 4034, 1028 }, - { -7484, 4245, 4218, -212 }, - { -6567, 5839, 4539, -512 }, - { -5715, 5935, 3747, -1186 }, - { -6410, 4881, 3356, -1610 }, - { -5146, 2590, 2850, 2172 }, - { -5196, 4095, 2569, -373 }, - { -5043, 6025, 4318, 692 }, - { -5525, 4884, 3513, 370 }, - { -6804, 7533, 5812, -488 }, - { -5657, 2480, 4061, 1234 }, - { -3155, 1472, 6071, 1188 }, - { -3427, 5217, 3442, 858 }, - { -4698, 3013, 5517, 2586 }, - { -4449, 2226, 5418, 3580 }, - { -6395, 3547, 5487, 2028 }, - { -3500, 5019, 4787, 1 }, - { -4038, 2578, 3073, 3151 }, - { -2750, 1955, 4469, 3856 }, - { -5696, 1659, 6118, 2469 }, - { -4350, 1241, 6840, 3126 }, - { -5565, 5058, 5196, 1314 }, - { -1642, 4190, 3948, 607 }, - { -1233, 4108, 4850, -640 }, - { -997, 3428, 3239, 1378 }, - { -6488, 2741, 6926, 2792 }, - { -4188, 3763, 4235, 2018 }, - { -3210, 3224, 5646, 1427 }, - { -5526, 6909, 5070, -627 }, - { -2815, 3994, 3425, 1903 }, - { -2163, 2734, 5423, 145 }, - { -4149, 4247, 2355, 734 }, - { -410, 2521, 4138, -16 }, - { -2411, 2385, 4927, 2105 }, - { -6077, 3591, 3114, 594 }, - { -4186, 4834, 5926, -1004 }, - { -7315, 3369, 5966, 448 }, - { -7042, 5721, 5771, 238 }, - { -4466, 3907, 3535, -1751 }, - { -2116, 3970, 6163, -1392 }, - { -7239, 2143, 8407, 3630 }, - { -5431, 4486, 6486, -42 }, - { -1874, 1617, 6333, 519 }, - { -6478, 2629, 4634, -505 }, - { -7784, 2342, 7216, 1365 }, - { -1154, 1432, 4831, 1544 }, - { -4964, -5801, 1797, 506 }, - { -4436, -6905, 1059, -1237 }, - { -5400, -6886, 884, -290 }, - { -6259, -7103, 523, -227 }, - { -4819, -6450, 1412, -450 }, - { -4056, -6213, 1725, -943 }, - { -5642, -6091, 1357, 605 }, - { -4196, -5678, 2187, -173 }, - { -4726, -5126, 2470, 321 }, - { -6642, -5091, 1507, -1005 }, - { -5304, -5250, 1944, 1579 }, - { -7179, -5520, 1468, -425 }, - { -6033, -4895, 1876, -955 }, - { -6595, -5143, 2207, 1291 }, - { -4224, -4943, 1846, 1792 }, - { -7128, -6950, 539, 724 }, - { -4369, -4901, 2590, 1103 }, - { -7413, -5696, 1712, 1440 }, - { -5885, -6821, 418, 871 }, - { -6828, -5599, 710, -1563 }, - { -6123, -5817, 1358, 1631 }, - { -5291, -5622, 578, 2138 }, - { -7171, -6004, 347, 2208 }, - { -6083, -5251, 2132, 425 }, - { -4329, -5721, 407, -2993 }, - { -5326, -5056, 1119, -1837 }, - { -5485, -5856, 185, -2389 }, - { -6529, -5178, 403, -697 }, - { -6719, -4412, 2726, 871 }, - { -5126, -5629, 1835, -771 }, - { -5622, -4361, 2973, 858 }, - { -5282, -5895, 45, -335 }, - { -4357, -5656, 1696, -1558 }, - { -7139, -6659, 627, -409 }, - { -4415, -6328, 35, 1306 }, - { -7639, -6110, 1134, 197 }, - { -3626, -5592, 2019, 901 }, - { -3547, -5064, 1176, 1738 }, - { -5075, -3899, 2087, 266 }, - { -4086, -6311, 1479, 360 }, - { -6210, -5220, -199, -1477 }, - { -3910, -5063, 1356, -15 }, - { -7616, -4977, 461, 2401 }, - { -6118, -6131, 1258, -563 }, - { -6127, -4968, 1286, -27 }, - { -4121, -5852, 1113, 1476 }, - { -5157, -4881, 1162, -662 }, - { -4637, -5031, 1179, 709 }, - { -5509, -5452, -397, 1224 }, - { -4597, -6861, 646, 467 }, - { -6247, -4043, 468, 278 }, - { -5336, -6465, 874, -1472 }, - { -6998, -6346, 78, -1798 }, - { -4915, -4530, 2756, -203 }, - { -6048, -4373, 1468, 1052 }, - { -4273, -7100, 942, -323 }, - { -6552, -4287, 2351, 69 }, - { -6954, -4613, 722, 1521 }, - { -4201, -5361, 763, -1562 }, - { -6881, -5596, -748, 669 }, - { -6695, -3547, -34, 1299 }, - { -3981, -5728, 84, 111 }, - { -4663, -4809, 2173, -1031 }, - { -6599, -6077, 1303, 256 }, - { -7596, -4265, -5791, -4140 }, - { -6610, -2758, -5288, -3936 }, - { -5880, -3865, -6563, -3088 }, - { -7228, -5510, -7677, -3912 }, - { -8854, -6553, -8318, -5361 }, - { -9362, -5249, -6413, -4319 }, - { -4418, -3110, -6368, -4358 }, - { -5544, -4203, -6863, -5013 }, - { -3056, -4316, -5567, -3181 }, - { -3078, -5999, -5051, -2657 }, - { -5884, -6292, -5756, -4013 }, - { -4825, -4549, -5535, -4053 }, - { -4443, -6126, -5316, -1368 }, - { -3972, -6341, -6098, -2686 }, - { -5751, -2781, -5398, -6230 }, - { -4466, -6135, -5570, -3679 }, - { -4291, -5992, -3564, -5189 }, - { -7189, -4429, -7279, -6082 }, - { -5076, -4433, -2748, -5366 }, - { -6225, -2825, -6833, -5663 }, - { -2989, -4792, -3960, -4492 }, - { -7836, -7773, -7722, -5741 }, - { -6559, -5703, -5844, -5589 }, - { -7612, -5438, -4136, -3774 }, - { -4218, -4176, -6591, -2333 }, - { -4837, -5063, -6581, 322 }, - { -6590, -5990, -2980, -3847 }, - { -5558, -2971, -5489, -1932 }, - { -7001, -5323, -4975, -1697 }, - { -4694, -2688, -6904, -3044 }, - { -8511, -5379, -5767, -2549 }, - { -7548, -5412, -6522, -2572 }, - { -6597, -4973, -6423, -1274 }, - { -6415, -4022, -5168, -1072 }, - { -5528, -5530, -7218, -2345 }, - { -4845, -4805, -5943, -1227 }, - { -6049, -7150, -6744, -2161 }, - { -9061, -7299, -8542, -4375 }, - { -5010, -5546, -5416, -82 }, - { -4135, -4205, -5109, -3373 }, - { -3311, -5869, -4007, -5061 }, - { -5993, -6472, -3962, -4718 }, - { -2966, -5832, -2821, -6305 }, - { -4851, -5152, -2067, -3930 }, - { -3620, -4441, -3362, -5836 }, - { -4469, -5221, -4534, -5592 }, - { -4022, -6335, -4321, -6107 }, - { -4899, -4503, -3084, -3725 }, - { -4490, -8276, -4620, -6236 }, - { -6591, -4342, -7365, -4063 }, - { -6498, -5057, -5553, 485 }, - { -6060, -2714, -7093, -4144 }, - { -6199, -7774, -7094, -4057 }, - { -7536, -6424, -6415, -4265 }, - { -7439, -2454, -6348, -4827 }, - { -5333, -7565, -4417, -4639 }, - { -4353, -7103, -4197, -2689 }, - { -5229, -6549, -5129, -6804 }, - { -6129, -7701, -5236, -4836 }, - { -6797, -3983, -3884, -4406 }, - { -6624, -4467, -4745, -5052 }, - { -3324, -7596, -2720, -6553 }, - { -5473, -6284, -1704, -4511 }, - { -4131, -7263, -3180, -5196 }, - { -7116, -5565, -3469, 685 }, - { -6002, -6021, -3858, 576 }, - { -3144, -8203, -1291, -434 }, - { -6096, -7027, -4004, 1353 }, - { -3943, -7709, -2344, -36 }, - { -4510, -6767, -2642, 631 }, - { -3657, -11541, -2570, -3984 }, - { -5959, -8854, -1333, -867 }, - { -6699, -8866, -1606, -344 }, - { -3836, -7961, -2334, -2028 }, - { -3430, -8045, -3037, -672 }, - { -3868, -9184, -3635, -1819 }, - { -4258, -9060, -2621, -1008 }, - { -3595, -8693, -2022, -752 }, - { -4573, -8048, -3166, -2622 }, - { -4852, -7903, -1405, 256 }, - { -4591, -7057, -1560, 965 }, - { -6963, -7655, -980, 808 }, - { -5179, -6641, -3356, 1196 }, - { -7102, -6941, -2798, 2123 }, - { -6867, -5834, -3320, -770 }, - { -5977, -7369, -2500, -778 }, - { -6160, -6400, -934, -2543 }, - { -6741, -7608, -355, -1289 }, - { -6856, -6466, -1433, -1643 }, - { -4786, -6292, -4970, 376 }, - { -5407, -8866, -2255, -400 }, - { -3814, -6506, -1387, -3620 }, - { -4998, -6137, -1200, -4092 }, - { -5123, -9557, -2849, -1306 }, - { -4259, -6444, -4395, -338 }, - { -5221, -6810, -883, 1225 }, - { -6137, -6215, -2165, 554 }, - { -3895, -6557, -3176, -1829 }, - { -3886, -8188, -87, -954 }, - { -7243, -6707, -2216, -316 }, - { -5592, -7606, 85, -432 }, - { -3957, -7945, -504, -144 }, - { -4617, -7624, 218, -312 }, - { -4797, -8737, -844, -1051 }, - { -4478, -8516, -1401, -454 }, - { -4557, -7058, -302, -2332 }, - { -6623, -7736, -271, -50 }, - { -3157, -7532, -1111, -2207 }, - { -3590, -7300, -1271, 517 }, - { -4442, -7306, -507, 590 }, - { -6458, -7524, -2807, 666 }, - { -4991, -8466, -3363, -785 }, - { -7474, -7541, -1056, -1839 }, - { -7501, -8316, -938, -180 }, - { -5329, -7739, -579, -2341 }, - { -4549, -7063, -176, -3539 }, - { -5191, -8612, -1504, -4250 }, - { -3083, -7058, -2251, 32 }, - { -4003, -7043, -1093, -791 }, - { -5523, -8093, -678, -114 }, - { -3022, -10265, -2070, -3109 }, - { -3905, -6274, -182, -3652 }, - { -3269, -9217, -551, -2650 }, - { -3138, -9314, -1726, -1704 }, - { -4420, -10339, -1744, -3459 }, - { -4163, -8609, -2298, -4113 }, - { -5566, -6505, -1241, -463 }, - { -3130, -9746, -2352, -4884 }, - { -7825, -3439, 1451, -1468 }, - { -8451, -3318, 2360, -435 }, - { -8462, -4130, 1438, -1024 }, - { -9425, -4564, 1328, -689 }, - { -11014, -3202, 2278, 2080 }, - { -8269, -2761, -146, -440 }, - { -7497, -2618, -166, 413 }, - { -8250, -3060, 522, -2133 }, - { -8365, -5366, 1347, -451 }, - { -8589, -3979, 2943, 714 }, - { -8111, -2572, 1272, -1748 }, - { -7830, -5193, 605, -1484 }, - { -8119, -4736, 2141, 256 }, - { -7724, -4769, 1463, -812 }, - { -7363, -3911, 2540, 4 }, - { -7974, -3397, 2363, 1366 }, - { -7359, -4204, 1752, -958 }, - { -7622, -3505, 660, 916 }, - { -9934, -3665, 3165, 828 }, - { -8721, -4162, 62, 1718 }, - { -9433, -4768, 2722, 1234 }, - { -7960, -4496, 138, 1528 }, - { -8198, -3454, -443, 631 }, - { -7756, -2246, 655, 1137 }, - { -8841, -3145, 1113, 829 }, - { -7817, -3298, 1251, 230 }, - { -9413, -2733, 323, -1862 }, - { -9408, -4168, 1270, 1549 }, - { -9037, -3892, -942, 283 }, - { -8255, -3849, 1301, 1762 }, - { -9057, -3987, -41, -682 }, - { -9441, -4187, 2019, -111 }, - { -9740, -3178, 1602, -871 }, - { -8344, -2474, 1461, 1506 }, - { -9752, -2925, 1996, 1243 }, - { -9199, -3796, 180, 537 }, - { -9060, -2405, 1140, -1562 }, - { -9348, -2376, 309, -162 }, - { -10786, -3182, -5, -1500 }, - { -8142, -4540, -434, -826 }, - { -7528, -2341, 1104, -73 }, - { -9360, -2658, 3062, 56 }, - { -8267, -2335, 2000, -1193 }, - { -12169, -3154, 1287, -640 }, - { -11398, -2120, 946, -1163 }, - { -8940, -4559, 328, -1696 }, - { -11025, -4213, 2813, 840 }, - { -9224, -3581, 2224, 2039 }, - { -8943, -3337, 1248, -1298 }, - { -7900, -4042, 485, -2080 }, - { -9221, -1947, 2191, -880 }, - { -10762, -1800, 2516, -324 }, - { -10095, -2238, 981, -1335 }, - { -11908, -2808, 3255, 645 }, - { -10640, -4105, 1283, -595 }, - { -7663, -2863, 2467, -797 }, - { -10712, -3854, 3710, 1538 }, - { -10823, -2893, 1408, -801 }, - { -9874, -3832, 256, -1638 }, - { -10394, -3391, 2315, -94 }, - { -11525, -4079, 4153, 2122 }, - { -9546, -2088, 1541, 481 }, - { -8731, -2433, 1042, 2160 }, - { -7852, -3977, -1370, 1677 }, - { 7072, -3420, 1398, -1741 }, - { 6180, -1976, 1280, -3557 }, - { 7692, -1793, 2844, -1700 }, - { 8363, -1773, 3104, -2679 }, - { 9213, -3266, 3756, -3542 }, - { 9650, -2644, 1426, -1318 }, - { 7712, -2796, 3686, -1975 }, - { 7316, -3517, 2821, -622 }, - { 7434, -2594, 2305, -2264 }, - { 7237, -1797, 255, -3114 }, - { 8663, -1983, 1338, -3056 }, - { 6616, -952, 4059, -2652 }, - { 8823, -1327, 1362, -1356 }, - { 9938, -1722, 1287, -2362 }, - { 7207, -1057, 1913, -1315 }, - { 7508, -1585, 870, -1982 }, - { 8217, -3680, 1417, -3170 }, - { 8329, -2541, 1684, -585 }, - { 8062, -2335, 252, -2800 }, - { 8204, -4108, 3097, -2569 }, - { 7701, -3367, 576, -3008 }, - { 7350, -786, 2414, -2129 }, - { 6948, -2568, 1607, -225 }, - { 7684, -2387, 1308, -3449 }, - { 8306, -3458, 2394, -1454 }, - { 8438, -2781, 1043, -1362 }, - { 9175, -2076, 2144, -1987 }, - { 8347, -2709, 3489, -4301 }, - { 5696, -2377, 2870, 851 }, - { 8825, -1243, 2219, -2603 }, - { 8801, -1614, 584, -2513 }, - { 8413, -384, 1421, -2244 }, - { 9228, -3050, 3279, -2164 }, - { 6342, -2698, 3547, -107 }, - { 10053, -2476, 2837, -3168 }, - { 7439, -604, 3177, -3991 }, - { 7749, -1064, 4329, -4855 }, - { 8655, -2177, 2252, -3519 }, - { 8490, -228, 1958, -3233 }, - { 10513, -2968, 1911, -2340 }, - { 8146, -862, 1884, -1723 }, - { 7788, -666, 3004, -2891 }, - { 7785, -1620, 4133, -3417 }, - { 10262, -3731, 3455, -2971 }, - { 8570, -905, 4519, -4649 }, - { 9129, -2562, 463, -2465 }, - { 9451, -3587, 1904, -3056 }, - { 6549, -2236, 3010, -4523 }, - { 7175, -2684, 2967, -3458 }, - { 9872, -3278, 1054, -2472 }, - { 9153, -931, 1217, -2565 }, - { 8789, -3469, 753, -2568 }, - { 6683, -3791, 1797, -3968 }, - { 6801, -1977, 2311, -452 }, - { 6336, -1572, 2612, -3264 }, - { 7996, -1008, 730, -2964 }, - { 7521, -1059, 1573, -3694 }, - { 8148, -3973, 2600, -3572 }, - { 7765, -1532, 2528, -3856 }, - { 7404, -3918, 4472, -143 }, - { 8894, -1398, 3299, -3685 }, - { 5768, -2041, 1487, -637 }, - { 5131, -2865, 2463, -811 }, - { 6439, -1568, 3500, -1550 }, - { -8878, -6798, -5319, -1452 }, - { -6332, -9713, -3112, -990 }, - { -8444, -6316, -3694, -687 }, - { -6123, -10840, -3637, -4358 }, - { -4784, -9580, -4577, -2581 }, - { -6108, -10515, -4859, -2524 }, - { -7605, -7518, -2327, -2797 }, - { -9662, -8775, -2467, -2010 }, - { -6494, -7523, -4715, -118 }, - { -8290, -8982, -1672, -317 }, - { -8798, -11051, -3888, -1426 }, - { -6273, -6623, -6791, -142 }, - { -8313, -7668, -2141, -1275 }, - { -6453, -8412, -3589, -4102 }, - { -6747, -7750, -5690, -2498 }, - { -7814, -6693, -3174, -2446 }, - { -10383, -10130, -3931, -2364 }, - { -10606, -8467, -5539, -2772 }, - { -9475, -6671, -3305, -2271 }, - { -8982, -9457, -5635, -4005 }, - { -10111, -7965, -6515, -4180 }, - { -7301, -6479, -5364, 720 }, - { -9543, -8999, -7921, -912 }, - { -9534, -8562, -3469, -384 }, - { -7601, -10344, -3205, -1127 }, - { -8088, -8620, -4954, -2888 }, - { -8202, -8406, -7038, -3775 }, - { -7312, -8324, -3334, -1775 }, - { -8566, -9262, -8071, -4174 }, - { -7068, -11300, -5573, -2907 }, - { -8295, -8952, -4366, -1544 }, - { -11104, -10210, -2285, -384 }, - { -5213, -7520, -5008, -1339 }, - { -5889, -7940, -5987, -1385 }, - { -10816, -8201, -4153, -1485 }, - { -10277, -8919, -6315, -1652 }, - { -5888, -10320, -3821, -1733 }, - { -10497, -7181, -6083, -3032 }, - { -7721, -9724, -6591, -5336 }, - { -5688, -7894, -3486, -2552 }, - { -10014, -10500, -3247, -820 }, - { -6301, -8765, -4506, -2923 }, - { -8261, -7847, -6213, -1552 }, - { -10212, -7481, -8113, -3954 }, - { -6938, -10874, -6074, -4703 }, - { -7183, -10968, -4446, -1773 }, - { -7120, -9193, -1966, -2509 }, - { -6234, -9263, -2313, -4284 }, - { -8503, -9857, -2429, -608 }, - { -9372, -7844, -8391, -2120 }, - { -7951, -7157, -6535, -11 }, - { -7256, -9473, -2172, -660 }, - { -10063, -9612, -2515, -15 }, - { -6684, -9134, -6109, -4206 }, - { -8204, -11932, -5220, -2306 }, - { -9710, -6706, -4115, -3275 }, - { -6855, -7078, -2409, -4447 }, - { -7344, -7673, -4479, -4116 }, - { -8851, -6842, -4927, -2948 }, - { -8927, -10452, -5633, -2194 }, - { -8627, -9002, -7176, -1575 }, - { -8209, -9722, -7021, -3324 }, - { -3770, -10249, -3623, -4816 }, - { -8183, -7465, -4090, 646 }, - { -8163, -7149, 200, 498 }, - { -8289, -6266, 686, -206 }, - { -10030, -6241, -1032, -1864 }, - { -8793, -8327, -773, -169 }, - { -9149, -6215, 969, -15 }, - { -8303, -5859, -7, 2006 }, - { -9682, -7283, 255, 1322 }, - { -9293, -7227, 71, -231 }, - { -8525, -6215, 287, -837 }, - { -10477, -5379, 1159, 1449 }, - { -10726, -7856, -130, 102 }, - { -8694, -7461, -1210, 690 }, - { -9367, -5324, 1103, 3170 }, - { -10686, -8055, -831, 1633 }, - { -9201, -6873, -2704, 2258 }, - { -8421, -5358, -1405, 226 }, - { -9066, -5830, -307, -1571 }, - { -11150, -7381, -2746, -900 }, - { -9978, -5925, -2006, -437 }, - { -9464, -4741, -273, 1061 }, - { -10543, -6684, -1113, 1660 }, - { -10073, -5576, 1083, -269 }, - { -8826, -5763, 1600, 1486 }, - { -10445, -9071, -1253, -64 }, - { -12085, -5799, 2, 769 }, - { -12939, -6663, 1650, 1437 }, - { -10932, -6434, -1252, -649 }, - { -11650, -7826, -2053, 710 }, - { -12122, -6733, -1889, -731 }, - { -9093, -6095, -2463, -842 }, - { -10977, -4364, 469, 420 }, - { -11488, -6908, -521, 893 }, - { -9669, -5478, -842, 337 }, - { -10606, -5203, -632, -1361 }, - { -10198, -6284, 1662, 1277 }, - { -10135, -5292, 2435, 3493 }, - { -11027, -6561, 655, 56 }, - { -10977, -5030, 1127, -358 }, - { -12766, -3986, 1348, -335 }, - { -14244, -7731, 264, 317 }, - { -15124, -10309, -508, 1447 }, - { -12821, -8638, -608, 137 }, - { -13076, -8693, -2852, -431 }, - { -11156, -5546, -2252, -1600 }, - { -8692, -7366, -819, -1223 }, - { -12507, -9816, -1714, -121 }, - { -10712, -6666, 544, 3349 }, - { -12462, -5890, -2491, -2318 }, - { -12468, -7226, 437, 232 }, - { -11300, -5226, 2068, 687 }, - { -11994, -8320, -626, 2728 }, - { -12222, -5476, 1142, 18 }, - { -10277, -8122, -2418, 2003 }, - { -13418, -6115, -3563, -2802 }, - { -14759, -9834, -1243, 21 }, - { -13699, -5665, 1525, 507 }, - { -16269, -9476, -701, 163 }, - { -12677, -5437, -247, -1019 }, - { -11827, -4295, -181, -1243 }, - { -12847, -4496, 2984, 1123 }, - { -13860, -7915, -1166, -547 }, - { -12276, -8145, -2290, -1527 }, - { -11417, -4830, 2983, 1854 }, - { -11793, -6002, 1163, 1940 }, - { 11443, -4920, -3235, 3151 }, - { 11300, -6616, -1506, 1175 }, - { 9198, -4628, -2060, 2390 }, - { 10532, -4027, -643, 912 }, - { 9902, -3573, -1606, 1327 }, - { 9653, -3536, -2240, 1869 }, - { 9948, -5171, -423, 2662 }, - { 12316, -4004, -1989, 281 }, - { 12125, -4800, -1265, -163 }, - { 10650, -2617, -2337, 1462 }, - { 9909, -4968, -2376, 916 }, - { 12944, -4647, -1958, 460 }, - { 12988, -5283, -1141, 41 }, - { 12321, -2915, -3621, 1025 }, - { 11449, -2894, -2728, 351 }, - { 12087, -3041, -2002, -32 }, - { 11558, -4031, -1343, -399 }, - { 12983, -3740, -3516, 1245 }, - { 12099, -2515, -2752, 225 }, - { 12515, -3465, -2701, 550 }, - { 14683, -5022, -5272, 2996 }, - { 12260, -3383, -1215, -528 }, - { 13810, -5422, -2443, 1166 }, - { 13421, -5378, -1886, 721 }, - { 12961, -4259, -2594, 796 }, - { 12266, -2104, -4768, 1591 }, - { 13523, -4710, -3045, 1342 }, - { 12437, -2099, -5610, 2117 }, - { 11850, -2183, -3497, 661 }, - { 12275, -3936, -597, -697 }, - { 12459, -5253, -517, -544 }, - { 12835, -4094, -1322, -168 }, - { 14360, -5677, -3305, 1859 }, - { 13905, -4552, -4309, 2117 }, - { 11559, -3412, -1847, -81 }, - { 13379, -3167, -5764, 2746 }, - { 11910, -1634, -4342, 1052 }, - { 12662, -4742, 71, -974 }, - { 13057, -3254, -4424, 1705 }, - { 15046, -5706, -4851, 3019 }, - { 14162, -4142, -5514, 2843 }, - { 12764, -1845, -6684, 2888 }, - { 13714, -2374, -7838, 3857 }, - { 13295, -1663, -8293, 4073 }, - { 10032, -4152, -3403, 1421 }, - { 10942, -5386, -2222, 950 }, - { 10532, -6385, -1750, 1925 }, - { 10273, -5972, -1534, 643 }, - { 10605, -4782, -1695, 27 }, - { 10988, -5153, -1123, -341 }, - { 11629, -5884, -1060, 48 }, - { 10441, -4045, -2431, 311 }, - { 10788, -3595, -4171, 1807 }, - { 12110, -5686, -2127, 976 }, - { 11746, -4773, -2639, 891 }, - { 11541, -5299, -3031, 1732 }, - { 11416, -2559, -5359, 2198 }, - { 11583, -5376, -704, 677 }, - { 10416, -3214, -3516, 872 }, - { 9651, -5435, -1618, 3255 }, - { 9973, -5133, -996, 3923 }, - { 11707, -4643, -430, -796 }, - { 10994, -2709, -3587, 2302 }, - { 10716, -5118, -645, 270 }, - { 14100, -10314, 1095, 1531 }, - { 12944, -8049, 1105, -741 }, - { 13276, -7035, -511, 274 }, - { 14008, -7254, -283, 139 }, - { 11594, -6536, -91, 1671 }, - { 11732, -8645, 746, 15 }, - { 14613, -7085, -1578, 1183 }, - { 13083, -6224, -750, -4 }, - { 13988, -6256, -1592, 820 }, - { 14678, -8683, 441, 126 }, - { 15571, -8872, -521, 1139 }, - { 15642, -9533, 341, 697 }, - { 15960, -9586, -168, 1121 }, - { 15464, -10239, 1433, -1 }, - { 14934, -7887, -1046, 1080 }, - { 15252, -7630, -1899, 1628 }, - { 15485, -8384, -1234, 1484 }, - { 15962, -8638, -1815, 1931 }, - { 16501, -10664, 398, 1167 }, - { 16146, -10145, 411, 918 }, - { 14573, -7475, -697, 601 }, - { 14302, -7996, 28, 257 }, - { 14769, -6792, -2286, 1574 }, - { 14144, -6137, -2169, 1257 }, - { 14770, -6271, -3111, 1933 }, - { 14110, -8312, 1083, -531 }, - { 15235, -6991, -2993, 2174 }, - { 13222, -5805, 547, -891 }, - { 14796, -8762, 1254, -246 }, - { 16040, -9181, -1005, 1551 }, - { 16487, -10086, -373, 1420 }, - { 15077, -9479, 966, 51 }, - { 13026, -6468, 932, -1080 }, - { 12703, -6152, -33, -573 }, - { 15641, -6810, -4128, 2874 }, - { 13282, -7673, 1583, -1283 }, - { 12373, -7150, 1512, -917 }, - { 12992, -7751, -678, 783 }, - { 10907, -6858, -313, 2597 }, - { 13026, -8963, 125, 2152 }, - { 12770, -9946, 1957, -505 }, - { 12482, -6849, -1268, 833 }, - { 13790, -6181, -138, -279 }, - { 12709, -8382, 2044, 227 }, - { 12244, -6630, 203, -457 }, - { 14209, -6816, -1032, 632 }, - { 15134, -8267, -288, 640 }, - { 13619, -6157, -1090, 356 }, - { 14044, -7413, 725, -484 }, - { 12958, -7753, 2585, -1980 }, - { 13188, -8396, 2306, -1558 }, - { 14379, -9980, 2132, -688 }, - { 14275, -9857, 1162, 179 }, - { 13690, -8648, 1621, -889 }, - { 11770, -6829, -746, 278 }, - { 12732, -8202, 286, 90 }, - { 13630, -10146, 1867, -207 }, - { 12072, -8740, 1299, -645 }, - { 12852, -9492, 1226, 62 }, - { 11792, -7382, -54, -116 }, - { 13779, -9014, 487, 351 }, - { 11951, -7729, 121, 834 }, - { 11970, -9781, 2276, -4 }, - { 12680, -7984, 2787, -787 }, - { 13300, -14488, 6408, -1927 }, - { 13635, -15355, 9153, -3073 }, - { 12804, -13566, 5517, -1625 }, - { 16624, -10854, 1690, 28 }, - { 20387, -18532, 6162, -261 }, - { 16515, -12642, 3392, -519 }, - { 15800, -11095, 2151, -202 }, - { 16824, -11790, 1651, 599 }, - { 17604, -13213, 2563, 538 }, - { 17892, -14177, 3562, 147 }, - { 16987, -11399, 869, 1052 }, - { 17003, -12456, 2442, 265 }, - { 21657, -21806, 9198, -1250 }, - { 16825, -13341, 3980, -686 }, - { 17525, -12714, 1887, 805 }, - { 16419, -11034, 1216, 617 }, - { 20931, -19939, 7469, -684 }, - { 18452, -15390, 4573, -191 }, - { 14778, -10077, 2841, -1209 }, - { 17402, -13319, 3042, 160 }, - { 19365, -17922, 7087, -1061 }, - { 16298, -11941, 2810, -351 }, - { 19087, -16176, 4775, -84 }, - { 17666, -12289, 938, 1224 }, - { 18581, -15894, 5132, -430 }, - { 19823, -16717, 4142, 545 }, - { 19960, -19423, 8400, -1492 }, - { 18973, -16817, 5906, -594 }, - { 19079, -15431, 3528, 503 }, - { 16667, -12485, 4467, -1302 }, - { 19791, -17797, 6196, -529 }, - { 20005, -17606, 5354, -20 }, - { 20123, -18599, 6886, -728 }, - { 19068, -14805, 2394, 1105 }, - { 14443, -13723, 5631, -2029 }, - { 14730, -14231, 5631, -1450 }, - { 16089, -15959, 7271, -2029 }, - { 13473, -11200, 3236, -924 }, - { 14413, -10902, 2347, -267 }, - { 17666, -18662, 11381, -3496 }, - { 14749, -11042, 3305, -275 }, - { 15304, -10486, 1869, -240 }, - { 14809, -12126, 3369, -616 }, - { 16896, -16561, 7307, -1845 }, - { 15782, -14336, 5380, -1264 }, - { 16395, -15520, 6415, -1588 }, - { 13681, -11114, 2584, -320 }, - { 14244, -12326, 4480, -1632 }, - { 15247, -13119, 4265, -898 }, - { 13987, -12091, 3469, -597 }, - { 13941, -12770, 4240, -839 }, - { 13771, -13627, 5252, -1384 }, - { 15010, -16074, 7592, -2249 }, - { 15852, -17226, 8619, -2655 }, - { 18921, -16916, 6875, -1501 }, - { 14909, -11678, 2768, -295 }, - { 18988, -18353, 8424, -2070 }, - { 15457, -15080, 6218, -1513 }, - { 14916, -15512, 6949, -1883 }, - { 18108, -14702, 4681, -701 }, - { 17600, -15733, 5616, -775 }, - { 14070, -13683, 6472, -2626 }, - { 13832, -11914, 5201, -2232 }, - { 18846, -19009, 9192, -1961 }, - { -11981, -10994, -6324, -2264 }, - { -10976, -9047, -6546, -3828 }, - { -11288, -10532, -7014, -4191 }, - { -10139, -10189, -7799, -2688 }, - { -10555, -9988, -9181, -2040 }, - { -11596, -11339, -10022, -2707 }, - { -13400, -13395, -11306, -4206 }, - { -9774, -12281, -7466, -4133 }, - { -10842, -13125, -8777, -4956 }, - { -11964, -15082, -9779, -5095 }, - { -9382, -10188, -9053, -4927 }, - { -11562, -11296, -3651, -985 }, - { -9287, -10083, -7918, -4069 }, - { -12821, -16556, -11410, -6195 }, - { -12628, -8959, -4521, -1113 }, - { -13845, -11581, -3649, -681 }, - { -12685, -10269, -5483, -1275 }, - { -14988, -12874, -5107, -1189 }, - { -13761, -11367, -6202, -1804 }, - { -13225, -11249, -7820, -3354 }, - { -14809, -11992, -3202, -312 }, - { -15620, -15519, -10210, -3433 }, - { -12954, -10200, -3139, -611 }, - { -11536, -9981, -5284, -923 }, - { -13034, -12417, -4612, -1098 }, - { -16911, -15505, -6123, -1352 }, - { -17396, -17685, -8330, -2171 }, - { -14120, -10764, -2265, -99 }, - { -12598, -7367, -5406, -3530 }, - { -14143, -12793, -10909, -5226 }, - { -14692, -16871, -11626, -5554 }, - { -12581, -11197, -9194, -3837 }, - { -16752, -16726, -9746, -2808 }, - { -10600, -10358, -6560, -1227 }, - { -14573, -13312, -8957, -3393 }, - { -10172, -8463, -8579, -3387 }, - { -11418, -12421, -5522, -1842 }, - { -11855, -14204, -6669, -2625 }, - { -13308, -8191, -3941, -2194 }, - { -10007, -12266, -5022, -1811 }, - { -13532, -15771, -9497, -3175 }, - { -11760, -11148, -10339, -5529 }, - { -12149, -12763, -11198, -3697 }, - { -12029, -12119, -8555, -1792 }, - { -16995, -19957, -11447, -3471 }, - { -13144, -14504, -9988, -3191 }, - { -9938, -11064, -6139, -3162 }, - { -8873, -11550, -8294, -6550 }, - { -9303, -13010, -6150, -2711 }, - { -15463, -10469, -1766, -170 }, - { -15985, -11693, -3007, -650 }, - { -17142, -10671, -1434, 47 }, - { -16063, -13858, -4817, -1058 }, - { -19446, -19599, -9594, -2464 }, - { -20076, -18744, -8313, -1889 }, - { -15047, -16085, -7590, -2250 }, - { -13481, -16195, -8552, -2998 }, - { -13829, -14869, -6704, -1932 }, - { -16357, -18484, -9802, -2959 }, - { -10551, -8393, -9303, -5070 }, - { -11345, -9156, -5641, -3107 }, - { -13217, -13449, -9270, -4541 }, - { -11988, -13732, -9995, -6374 }, - { -11007, -9519, -5168, -4107 }, - { 9930, -7858, 8061, -4375 }, - { 8274, -7867, 5992, -2096 }, - { 9692, -9675, 7621, -3670 }, - { 9589, -8110, 6509, -3010 }, - { 12617, -11976, 10122, -5360 }, - { 11867, -8895, 7948, -5323 }, - { 10388, -10482, 9234, -4324 }, - { 8188, -8220, 7810, -2737 }, - { 10407, -8787, 4806, -1930 }, - { 10348, -8845, 9233, -6614 }, - { 9422, -7091, 4820, -2878 }, - { 9758, -9796, 5584, -2256 }, - { 10188, -7994, 5347, -3343 }, - { 11133, -7455, 4015, -2306 }, - { 10676, -10744, 6093, -2629 }, - { 11522, -12184, 7848, -3375 }, - { 8805, -9883, 5317, -3071 }, - { 9498, -9654, 6555, -3592 }, - { 10488, -8008, 4066, -1252 }, - { 11261, -8930, 6068, -2738 }, - { 12180, -10397, 5027, -1531 }, - { 9138, -8531, 3601, -1959 }, - { 8107, -8380, 4970, -2061 }, - { 9737, -13248, 6438, -2617 }, - { 11178, -10423, 2622, -522 }, - { 9572, -12372, 5199, -2019 }, - { 12057, -12144, 4147, -1099 }, - { 9047, -9925, 2516, -665 }, - { 10790, -8030, 5882, -4386 }, - { 7199, -8426, 6337, -2841 }, - { 7778, -8285, 3529, -3442 }, - { 7559, -10569, 3484, -1332 }, - { 9404, -8115, 7484, -5541 }, - { 7792, -11976, 5546, -2573 }, - { 9313, -10264, 7661, -5195 }, - { 6701, -10725, 4370, -1784 }, - { 4918, -11361, 4507, -4527 }, - { 5147, -12305, 3978, -5556 }, - { 6525, -9899, 4481, -3129 }, - { 7538, -12855, 6060, -4826 }, - { 8659, -12111, 7159, -4430 }, - { 8440, -11304, 4547, -1747 }, - { 9216, -10918, 3507, -1195 }, - { 6165, -9254, 4771, -4677 }, - { 9163, -11019, 5637, -4935 }, - { 13441, -11509, 6676, -2434 }, - { 7912, -9398, 6663, -4048 }, - { 11723, -13745, 8131, -4148 }, - { 6065, -10257, 5005, -6327 }, - { 11618, -12417, 5336, -1894 }, - { 8891, -13924, 8407, -6131 }, - { 9622, -12563, 7908, -5109 }, - { 11479, -10315, 8349, -3991 }, - { 11676, -14103, 6611, -2330 }, - { 11951, -8953, 3829, -1550 }, - { 10486, -8044, 10493, -5920 }, - { 11801, -10769, 9763, -5305 }, - { 6109, -8676, 5827, -1346 }, - { 7030, -9611, 5624, -5761 }, - { 12808, -12886, 8683, -4148 }, - { 13213, -10464, 6381, -3189 }, - { 11796, -13681, 10703, -6075 }, - { 9639, -7949, 9625, -3944 }, - { 8538, -6997, 5309, 453 } -}; +extern const uint32_t ff_dca_lossless_quant[32]; -/* quantization tables */ +extern const int8_t ff_dca_high_freq_vq[1024][32]; -static const uint32_t scale_factor_quant6[64] = { - 1, 2, 2, 3, 3, 4, 6, 7, - 10, 12, 16, 20, 26, 34, 44, 56, - 72, 93, 120, 155, 200, 257, 331, 427, - 550, 708, 912, 1175, 1514, 1950, 2512, 3236, - 4169, 5370, 6918, 8913, 11482, 14791, 19055, 24547, - 31623, 40738, 52481, 67608, 87096, 112202, 144544, 186209, - 239883, 309030, 398107, 512861, 660693, 851138, 1096478, 1412538, - 1819701, 2344229, 3019952, 3890451, 5011872, 6456542, 8317638, 0 -}; +extern const float ff_dca_fir_32bands_perfect[512]; +extern const float ff_dca_fir_32bands_nonperfect[512]; -static const uint32_t scale_factor_quant7[128] = { - 1, 1, 2, 2, 2, 2, 3, 3, - 3, 4, 4, 5, 6, 7, 7, 8, - 10, 11, 12, 14, 16, 18, 20, 23, - 26, 30, 34, 38, 44, 50, 56, 64, - 72, 82, 93, 106, 120, 136, 155, 176, - 200, 226, 257, 292, 331, 376, 427, 484, - 550, 624, 708, 804, 912, 1035, 1175, 1334, - 1514, 1718, 1950, 2213, 2512, 2851, 3236, 3673, - 4169, 4732, 5370, 6095, 6918, 7852, 8913, 10116, - 11482, 13032, 14791, 16788, 19055, 21627, 24547, 27861, - 31623, 35892, 40738, 46238, 52481, 59566, 67608, 76736, - 87096, 98855, 112202, 127350, 144544, 164059, 186209, 211349, - 239883, 272270, 309030, 350752, 398107, 451856, 512861, 582103, - 660693, 749894, 851138, 966051, 1096478, 1244515, 1412538, 1603245, - 1819701, 2065380, 2344229, 2660725, 3019952, 3427678, 3890451, 4415704, - 5011872, 5688529, 6456542, 7328245, 8317638, 0, 0, 0 -}; +extern const float ff_dca_lfe_fir_64[256]; +extern const float ff_dca_lfe_fir_128[256]; +extern const float ff_dca_lfe_xll_fir_64[256]; +extern const float ff_dca_fir_64bands[1024]; -/* 20bits unsigned fractional binary codes */ -static const uint32_t lossy_quant[32] = { - 0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063, - 796918, 461373, 251658, 146801, 79692, 46137, 27263, 16777, - 10486, 5872, 3355, 1887, 1258, 713, 336, 168, - 84, 42, 21, 0, 0, 0, 0, 0 -}; +#define FF_DCA_DMIXTABLE_SIZE 242 +#define FF_DCA_INV_DMIXTABLE_SIZE 201 -static const float lossy_quant_d[32] = { - 0, 1.6, 1.0, 0.8, 0.59, 0.50, 0.42, 0.34, - 0.19, 0.11, 0.06, 0.035, 0.019, 0.011, 0.0065, 0.0040, - 0.0025, 0.0014, 0.0008, 0.00045, 0.00030, 0.00017, 0.00008, 0.00004, - 0.00002, 0.00001, 0.000005, 0, 0, 0, 0, 0 -}; +extern const uint16_t ff_dca_dmixtable[FF_DCA_DMIXTABLE_SIZE]; +extern const uint32_t ff_dca_inv_dmixtable[FF_DCA_INV_DMIXTABLE_SIZE]; -/* 20bits unsigned fractional binary codes */ -static const uint32_t lossless_quant[32] = { - 0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127, - 262144, 131072, 65431, 33026, 16450, 8208, 4100, 2049, - 1024, 512, 256, 128, 64, 32, 16, 8, - 4, 2, 1, 0, 0, 0, 0, 0 -}; +extern const float ff_dca_default_coeffs[10][6][2]; -static const float lossless_quant_d[32] = { - 0, 1.0, 0.5, 0.33, 0.25, 0.166, 0.125, - 0.083, 0.0625, 0.03125, 0.0156, 7.874E-3, 3.922E-3, 1.957E-3, - 9.775E-4, 4.885E-4, 2.442E-4, 1.221E-4, 6.104E-5, 3.052E-5, 1.526E-5, - 7.629E-6, 3.815E-6, 1.907E-6, 9.537E-7, 4.768E-7, 2.384E-7, 0, - 0, 0, 0, 0 -}; +extern const int32_t ff_dca_sampling_freqs[16]; +extern const int8_t ff_dca_lfe_index[16]; -/* Vector quantization tables */ +extern const int8_t ff_dca_channel_reorder_lfe[16][9]; +extern const int8_t ff_dca_channel_reorder_lfe_xch[16][9]; +extern const int8_t ff_dca_channel_reorder_nolfe[16][9]; +extern const int8_t ff_dca_channel_reorder_nolfe_xch[16][9]; -DECLARE_ALIGNED(8, static const int8_t, high_freq_vq)[1024][32] = -{ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -4, -2, 2, 1,-16,-10, 1, 3, 1, 0, 6, 1, -3, 7, 1,-22, - 2, -4, -3, 11, 14, 6, -1, 1,-13, 29,-28, 10, 10, -8, 0, -9 }, - { -8, 8, -7, 10, -3,-12, -5, -8, 1, -2, 9, -2, -5,-18, 1, 9, - -8, -8, 3, 41, 7, -9, -9, 22,-42,-29, 14,-18,-14,-32, 1,-15 }, - {-16, 8, 15, 16,-16, 5, 2, 7, -6,-16, -7, 1, 1, -3, -2, 0, - 8, 20,-26,-11, 2,-17, 0, -3,-34,-37, 10, 44, -2, 22, 2, -4 }, - { 7, 14, 5, 6, 15, -1, 3, -3, -9,-23, -5,-14, 8, -1,-14, -6, - -5, -8, 54, 31, -6, 18, 2,-19, -2,-11,-30, -6,-19, 2, -2,-14 }, - { 1, 2, -2, -1, -3, -3, 1, -5, 1, -3, -4, -8, 5, -4, 0, 1, - 3, 7, -5, -4, -3,-12, 3, -2, -3, 12,-53,-51, 6, -1, 6, 8 }, - { 0, -1, 5, 1, -6, -8, 7, 5,-18, -4, -1, 1, 0, -3, -3,-14, - -1, -6, 0,-14, -1, -1, 5, -3,-11, 1,-20, 10, 2, 19, -2, -2 }, - { 2, 4, 3, 0, 5, 0, 3, 1, -2, 0, -6, -3, -4, -5, -3, -3, - -7, 0,-34, 4,-43, 17, 0,-53,-13, -7, 24, 14, 5,-18, 9,-20 }, - { 1, 0, -3, 2, 3, -5, -2, 7,-21, 5,-25, 23, 11,-28, 2, 1, - -11, 9, 13, -6,-12, 5, 7, 2, 4,-11, -6, -1, 8, 0, 1, -2 }, - { 2, -4, -6, -4, 0, -5,-29, 13, -6,-22, -3,-43, 12,-41, 5, 24, - 18, -9,-36, -6, 4, -7, -4, 13, 4,-15, -1, -5, 1, 2, -5, 4 }, - { 0, -1, 13, -6, -5, 1, 0, -3, 1, -5, 19,-22, 31,-27, 4,-15, - -6, 15, 9,-13, 1, -9, 10,-17, 4, -1, -1, 4, 2, 0, -3, -5 }, - { -7, 3, -8, 13, 19,-12, 8,-19, -3, -2,-24, 31, 14, 0, 7,-13, - -18, 0, 3, 6, 13, -2, 1,-12,-21, 9, -2, 30, 21,-14, 2,-14 }, - { -3, -7, 8, -1, -2, -9, 6, 1, -7, 7, 13, 3, -1,-10, 30, 4, - -10, 12, 5, 6,-13, -7, -4, -2, -2, 7, -3, -6, 3, 4, 1, 2 }, - { -8, 9, 2, -3, -5, 2, 0, 9, 3, 7, -4,-16,-13, 3, 23,-27, - 18, 46,-38, 6, 4, 43, -1, 0, 8, -7, -4, -1, 11, -7, 6, -3 }, - { 1, 1, 18, -8, -6, 0, 3, 4, 22, -3, -4, -2, -4,-11, 40, -7, - -3,-13,-14, -7,-10, 14, 7, 5,-14, 11, -5, 7, 21, -2, 9, -3 }, - { 0, 0, -2, 4, -2, 0, 2, 0, -1, 2, -1, 0, 0, 2, 2, 2, - -1, 1, -3, -1,-15, -2,-63,-27,-21,-47,-14, 1,-14, 10, 0, 2 }, - { 1, 0, -4, 0, -3, -9, 4, 2, 6, -6, 0, -5, 11, -7,-15, 6, - -7, -6, 3, 7,-15, -5, 23,-13, -6, 12, -8, 9, 2, -3, 3, 4 }, - { 6, 0, 3, 0, -2, -4, 2, 1, 1, -1, 1, -2, -1, -4,-22,-15, - -46,-66, 10, 20, 2,-17, 12, -6, 1, -2, -2, 0, 1, -5, 1, 2 }, - { -1, 0, 0, 1, 0, -4, 0, 1,-10, -3, -8, 5, 7,-11, 2,-11, - 29,-25, 11, 10, 0, -1, 5, -7, -2, -5, -2, 4, 4, -3, 5, -2 }, - { 1, -1, -1, -3, -2, 1, -8, -3, 2, -2, 4, -5, -1, -7, -2, 1, - -14, -7, 3,-30,-15,-14, 3, -4, -1, 3,-13, -1, -3, 1, 2, 3 }, - { -1, -2, -3, 2, 2, -3, 3, 1, -3, 2, 0, -4, 6, 5, -5, 10, - -57, 3, 22,-50, 1, -2, -5, -6, -1, 5, 1, 2, 2, 1, -2, 2 }, - { 2, 0, -1, -7, 2, 1, 3, 2, 0, 4, 3, -2, 3, -3, 4, -4, - 24,-35, -3, 38, -6, -5, 15, 20, 3, 16, -7, -5, 0, -4, -5, 0 }, - { 0, 1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -2, 0, 0, 0, 0, - 0, -1, -2, -1, -5, -2,-43, -3, 46,-52,-10, 7, -8, 11, -2, -1 }, - { 0, 0, -1, 0, -1, 2,-41, 33,-44,-48,-15,-26, -9, 6, 3, 3, - -3, 2, 2, 2, 2, -1, -1, -2, 1, 3, 0, 0, 5, 2, 3, 1 }, - { -4, 1, 6, 1, -6, -1, -2, 1,-14, -4, 0, -5, -2, 2, -2, 0, - -6, 1, 0, 8,-21, 32, -3,-36, -6, -2, -1, -7, 3, 0, 1, -6 }, - { -3, -2, 3, 0, 2, 2, 8, -4, -4, 6, 2, 1, 3, -6, 4, 3, - 13, 0,-12, -1, 25,-20, -2,-23,-15, 7, -3,-11, -3, 6, -1, 0 }, - { 0, 0, -3, -1, 0, 0, -2, -1, -2, -2, 1, -1, 0, 0, 10, 3, - -2, 3, 3, -7, -6, -5, 0, -4,-60,-16, -6, 38, 5, 6, -5, 0 }, - { 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 1, 0, 0, 1, - 0, 0, -1, 0, -8, 2, -9, 10, 40, 31,-56,-21, 4, 20, -4, 7 }, - { -2, -2, 0, 4, -3, -1, 7, 3, 1, 3, -8, 0, 3, 1, 2, 5, - 1, -2, 14, 5, 4, 5, 5, 5, -5, 9,-66, 0,-20, -2, -8, 4 }, - { -2, -1, 4, -1, -8, -2, -4, -1, -3, -3, 2, -7, -3, 5, 7, -2, - 45, 31,-17,-16, -2, -2, -1,-22, 1, -1, -3, 3, 5, -3, 5, -1 }, - { -4, 0, 7, 5, 8, 7, 2, 9, -9, -9, -7,-11, -3, -8, 17, -4, - 34, 32, 18, 22, 1, 2, 1, -7, -5, 6, -1, 6, 4, 10, -2, -7 }, - { 6, 0, 14, 9, 6, -1, -2, -3, 4, -6, -8, 4, 7, -1, 28, 38, - 15, -1, 16,-11, 5, 8, 4,-10, 3,-10,-17, 5, 3, 3, 3, 1 }, - { 1, 1, 2, -1, 2, 1, 0, 0, -1, 0, 0, -2, 1, -3, 0, 1, - 2, -2, -4, -2, 0, -1, 1, -3, 1, 1, 1, -1, 8, 8, 66, 33 }, - { -5, 2, -3, -7, 2, -8, -4, 10, 17,-18, -7, 4, -4, -7, -6, -6, - -5, 5,-12, 2, 0, 6, 8, -2, 1, 4,-11, 2, 1, 8, 31, 19 }, - { 6, 9, 16, -6, -6, -1, -2, -3,-11, -2, 7, 7, 17, 3, 4, 10, - 2, 5,-13, 8, 7, 1, 4, 5, 7, 6, 7, -8, 9, -8, 33, 6 }, - { 3, -1, 1, 0, -7, -5, 0, 14, -7, 1, -7, 1, 2, -4, 7, 10, - -16, 12, 1, -6, 3, 8, -1, 10,-13, -6,-12,-23, 12, -3, 30, 14 }, - { -2,-15, 0, 8, 3,-19, 5, -3, 2, 3, 13, 7, 14, -3,-10, 0, - 8, 5, -6,-16, -8, -8, 14, 2, -1, 1, -9,-11, 11, -5, 27, 9 }, - { -8, 6, -4, 4, -4, -1, 5, 4, 1, -7, -5, -4,-15, 1, 9, 0, - 8, 4, 1,-17, 11, -2,-19, -1, -6, -8, 3,-12, 3,-17, 33,-10 }, - { -3, -1, 2, 7, 7, -2, 9, 8,-18, -1,-13,-10, -3, -3, 11, 8, - -2,-12, -8, 1, 4, 9, 14, 10, -3, 0, 2, 1, -2, 3, 31, 10 }, - { -3,-10, 8, -1, -5,-11, 7, -5, 3, 6, 1, 4,-16, 10, 5, -4, - -2,-10, -1, 13, 6, -5, -7, 12, 7, -3,-17, 1, 12, -4, 29, 8 }, - { 1, 2, 5, 2, -6, -7, 0, -1, 6, -1, 10, 6, -4, 5, 2, 2, - -2, -8, -6,-11, 14,-13, 27, 3, -2,-12, 5,-16, 2,-26, 20, 15 }, - { -1, -3, -5, -3, -3, 6, -1, 3, -5, 1, 7, 2, 1, 0, -1, -1, - 0, -1, 9, 7, -6, -3, 4, -5, -4, 8, -8,-25, -8, -4, 34, 23 }, - { -1, -2, 1, 1, -1, -2, -1, 1, -1, 0, 0, 0, 0, -2, -1, 1, - 0, 2, 1, -1, 4, 0, 0, 1, -1, 0, 5, 3, 12, -9, 68,-16 }, - { 10, 0, -8, 14, -6, 1,-12, 0, 0, -3, -5,-11, -6, 12, 9,-10, - -3, 5, 0, 7, 11, 2, 4, -3, -8, -3, 7, 4, 3, -3, 34, 4 }, - {-12, 13, -5, 7,-11, -2, -1, 1, -4,-14,-21, 3, -3, -3, -4, -7, - -9, -4, 3,-17, -2,-13, 10, -2, 12, -4, 0, -9, 1, -5, 31, 10 }, - {-10, 6, 5, 6, 4, -7, 10, 0,-28, -3, 0,-11, -1, -5, 16,-10, - -16, 7, 20, 2, -4, 2, -5, 0, 15, 6, 5,-10, 7, -9, 20, 4 }, - { 1, -7, -2, -7, 4, -3, -2, -7, -1,-14, 6,-16, 4, -5, -4, -6, - -5, 0, -2, 2, -6, 9, -5, 4,-18, 8,-10, 8, 15, 0, 32, 1 }, - { -5, 7, -3, 7, 15, -4, 0,-16, 9, 5, -5, 5, 4, -3,-12, -9, - -18, 10, 2, 2, -3, 7, 3, -1, 6, -9,-10, 3, 15, -4, 35, -7 }, - { -1,-10, 2, 2, -4, -2, 10, 2, -1, 2, -2, 1, -1,-14,-11, 3, - -8, 5, -8, -2, 6, -1, -7, 1, 7, 5, 7, 8, 30, -4, 30, 14 }, - { 2, -2, 1, 2, 3, -8, 3, 0, -2, 0, -9, 2, 1, 4, -6, -1, - -2, 5, 0, 1, -2, 12, 6, -3, 9, -3, 4,-12, 21,-39, 24, -2 }, - { 3, 5, 1, -2, -2, -2, -3, 6, -8, -2,-11, -8, -1, 4, 2, 2, - -4,-10, 12, -5,-11, 1,-15,-34,-11, -7,-11, -1, 7,-14, 38, -1 }, - { -4, 4, 8, 9, 8, 1, -5, -9, 4, -2, 15, -4, 11,-15, 20, -1, - -1, -3, 4, -9, -2, -2, -2, 8, 6, 12, -5, 0, 11,-12, 27, -4 }, - { 0, 8, -4, 3,-11, 6,-11, 2, 3, 0, 5, -8, -7, -6, -9,-21, - 4,-11, -1,-16, -7, 16, -3, 7, -7, 4, -5, 0, 11, -7, 31, 3 }, - { 1, 3, 4, 11,-11, -2, -3, -6, 6, 5, 0, 3, -9, -6, 4, -4, - 0, 4, -8, 13, -6,-13, -1, -5, -1, 4, 0, 0, 9,-22, 24, 18 }, - { -7, 3, 10,-13, -6, 6, -6, 6, 22, 1, 0,-14, 2, 3, 7, -1, - 8, 20, -1, 5, -4, 13, 9, -9, -9, 6, 0, -4, 0, -8, 31, -4 }, - { -3, -4, 0, 1, 7, 3, -7, 0, 5, -2, 1, 3, 3, 1, -5, -2, - 5, 2,-11, 4, 0, -1, 12, 0, -3,-13, 15, 8, -6,-27, 34, 0 }, - { -3, -3, 10, -4, 2, -1, -3, 0, -1, -1, -4, 2, 6, -2, 12, 1, - 3, -6, -7, -6, -5, 4,-19, -6, -8,-34, -4, -8, 10, -7, 23, 10 }, - { -7, 0, -1, -6, 8, 4, -4, 2, -5, -8, -7, -9, -8, 5, 9, 7, - -6, 1,-12,-12, -1,-16, 5, 0, 16, 3, -7, -8, 27, -4, 23, 15 }, - { -8, 4, 8, 5, 6, 11, -3, 5, 3, -1,-11, 6, -5, 0, 2, -6, - -3, -6, 4, -1, 5, -5,-12, -6, 7, -5, 9, 3, 6, -7, 29, 1 }, - { 1, 3, -2, -2, -6, -2, 1, 6, -6, -3, 1, 2, 3, 4, 1, 5, - -1, 0, 4, 2, 11, 6, 2, -3, 13, -9,-19, 18,-15,-10, 36, 21 }, - { -3, -3, 2, -1, -7, 6, -4, 1, -3, -1, -2, 2, 3, -7, -3, 0, - -2, 0, -2, 6,-19, 3, -8, 2, -6, 7, -1, 0, 29, -6, 28,-10 }, - { -5, 1, -3, -7,-12, -4, 1, 1, -1, 13,-10, -1, -9, -5,-13, 6, - 13, 3, -4, 2, 3, 11, 2, 6,-25,-16, -6, 0, 14, -1, 27, 16 }, - { -6, -1, -7, -5, -2, -5, -5, -1, 9, 1, 0, 3, -8,-12, -6, 5, - -6, 5, 3, -9, 1, 4, -7,-10, -9, -7,-17, -5,-15,-23, 25, 3 }, - { -8, -2, 9, -3, -4, 3, -1, 8, -7, -7, -5, -4, -2, 9, 4, -1, - -7, -4, -5,-16, 3, -6, 18,-13, -9, 16,-15, 8, 15,-10, 24, 5 }, - { 1,-38, 2, 34, 9, 10, 11, 2, 2, -6, 3, 2, -2, 5, 4, -7, - -1, 1, 4, 0, 3, 1, -8, -1, -6, 5, 4, 2, -4, 5, 2, -1 }, - { 1,-22, 15, 18, -2, 10,-16, -9, -8,-11, 8, 4, 0, 7,-14, -5, - -1, -7, 12, 17, 9, 5, -7, -4,-12, -6, 7, 0, 7, 2, -2, 1 }, - {-11,-29, 7, 10, 19, -1, -8, -9, 7, 1, 9, 6, 8, -7,-14, 8, - -3,-11,-13, 0, -7,-23, -2, -8, 12, 9, 2, 14, 19, 1, -1, 5 }, - {-24,-27,-11, 36, 2, 6, -3, 4, -6, 8, 0, 12, -1, -4, -6, 3, - 4, -1, 2, -3, -2, 3, 2, -1, -2, -4, 0, -1, -2, 7, 2, 3 }, - { -9,-24, 11, 13,-10,-12, 12, -2, 7, 4, 8, 13, -3, -3, 2, 9, - -3, -4, 4, 13, 5, 13, -6, -3, 1, 15, 7, -3, 0, 19, -2, -9 }, - { -8,-15, 7, 14, -4, -5, 2,-18,-19, -2, 2, 17, 16, 6,-10, 10, - -9, 14, -1, -5, -1, -6, -7, 2, 9, 11, 13, 6, -5,-12, 3, 2 }, - {-10,-37, 13, 1, 3,-14, 0,-20, 4, -3, 8, 2, -2, -3, -9, -5, - -3,-17, -1, 13,-11, 2, -6, 4, 4, 0, 3, 1, -9, -4, -5, -4 }, - { -2,-22, -5, 46, -8, 5, 9,-11, 8, 7, 7, -1, -1, -2, -7, 2, - -3, 3, -1, -2, 7, 0, 2, -1, 1, -2, -2, -3, 6, 0, -4, -6 }, - {-16,-27, 15, 16, -4, 14, -7,-26, 2, -2, 6, 5, -3, 11, 0, 2, - 3, 9, -7, -1, 2, -4, -4, -1, 6, 10, 1, 1, -3, -2, 3, 0 }, - { -3,-22, 10, 26, 1, 2, -3, 3, 17, -3, -7, 9, 1,-21, -4, 5, - 3, 0, -7, -6, 3, 3, -8, -7, -9, 3, 7, 1, -8, 12, 6, -7 }, - { -9,-25, 3, 18, 9, -6,-11, 0, -5,-12, 9, -8, -7, -6, -6, 22, - 2, -6, -3, 15, 3, 2, -2, 9, 14,-10, -7, 15, 13, 6, -2, 11 }, - { 5,-20, -5, 28, 11, 10, -4, -4, 0, -7, 3, 5, 2, -5, -8, 2, - 6, 10, 9, -9,-18, 3, 14, 1, 3, -3, -1, -6, 7, 7, 2, -1 }, - { -8,-30, 7, 12, 10, 8, 7,-13,-16, 0, 1, -1, -6,-11,-15, 4, - 1, -2, 10,-15, 1, 11, -2, 8, 9, -7, -7, 9, -5, 2, 7,-18 }, - {-10,-32, 10, 11, 3, -1, 3, -5, 5, 2, 14, -6, 3, 1, 5,-15, - -11, 6, 20, 4, 0,-12, -7, 3, 1, -1, 10, 6, -1, -9, -4, -1 }, - { 1,-25,-14, 12,-11, 9, 9,-16,-24,-17, 22, -9, 11,-30, -3, -4, - 6, -7, 9, 2, -1, -5, -6, 2, -1, -1, 10, 1, -3, 3, 4, 8 }, - {-14,-26, -6, 9, 8, 17,-11,-24, -7, -4, -8, -2, 10, 2, 2, -1, - 2, 13, 12, -7, 4, -6,-10, 6, 6,-13,-11, -7,-16, 0, -2, 5 }, - { -4,-30,-13, 12, 16, -6, 12,-16,-13, 5, 15, -2, -2,-10, -7, 7, - 11, -1, -4, -2, -4, 7, 4, -8, 1, 3, 0, 11, 3, -2, -5, 4 }, - { -4,-21, 20, 22, 2, 20, -8, 1,-12, -5, -9, 4,-10,-17, -3, -8, - -3, 3,-12, 1, -3, 0, 7, 4, 7, 7, -3, 7, 5, 3, 1, -5 }, - {-12,-20, 2, 29, 11, -6, 9, -7, -6, -4, 0, 6, 17,-13, -2,-10, - -17, -1,-18, 2, 0, 14, -6, 1, 0, 3, 2,-10, 1, -5, -2, 5 }, - { 16,-37, -1, 26, -2,-14, 1, -5,-14, 2, 2, 3, 6, 1, 1, 4, - 0, -1, 0, -2, -2, 4, 9, -6, 0, -2, 10, -7, -2, 4, 1, 0 }, - { -9,-24,-12, 5, 5, 3,-17,-14, 4, 3, 2, -4, 10,-22, -8, -3, - 6, 1, 12, -8, 4, 1, 9, -1, 18, -3, 6, 5, 3, -5, 9, -5 }, - {-14,-33, -2, 20,-13,-10, 2, -7, -1, 11, -9, -8, 18, -3, 1, 8, - 0, -2, 10, 7, -2,-13, 9, -3, -4, 5, -2, -2, -1, -5, 1, -7 }, - {-10,-23, 8, 14, 1, 7, 1, -3, -7, 4, 1, 1, 8, -7, 15,-14, - 13, 14, 2, 5,-13, -5, -8, -1, 6, 3, 6, 9, 6, 15, 14, 5 }, - {-13,-25,-10, 13,-17,-24, -7,-13, -6,-10, -8, 2, 0,-13,-10, -4, - -8, 4, -9, 9, -4, 4, -3, -3, 3, 3, -5, -9, 1, -2, 11, 2 }, - {-12,-23, 1, 18,-11, -2, 5, 9, -5, 5, 14, -9, -3, -2, -6, 2, - -2, 11,-13, 1, -3, 11, -9, -4, -2, -6, 8, 10, 1, 4, 2, 1 }, - { -5,-18, 16, 22, 2, 0, 8, -6, -9, -7, 10,-16, 23, 10,-11, -1, - 7, 2, 7, 2, 1, -5, 6, 1, 0, -4, 9, 2, -3, 1, 0, -4 }, - { -3,-26, 14, 11, 2, -9, 17, -2, -1, -5,-16, -9, -5, 10,-13, 1, - 6, 12, 10, 11, 0, 0, -3,-14, 6, -2, 0, 4, -5, -1, -7, -1 }, - {-10,-33, 1, 8, 11, -5, 1, -6, 7, 4, 5, 6, 1, -2,-10, -5, - -6, 12,-11, 5,-10, 4, 12, -1, -1, -3, 4, -1, 9, 0, 16,-17 }, - {-14,-37, 7, 7, -2, 5, -8,-11, 2,-13, 4,-19, 1, 8, 8, 4, - -9, 2, -4, 3, 12, 2, 4, -4, -8, 8, 1, 4, 8, -1, 6, -2 }, - { -6,-30, 18, 17, 1,-22, -3, 4, -7,-10, 7, 0, -8, 8, -1, 4, - 2, 8, 6, -2, 2, 7, 4, 4, 3, -6, 2, 1, -3, 1, -1, -5 }, - {-17,-18, -3, 22, -8, 1, 9, -2,-17, 20, -5, -5,-12, -5, 4, -5, - -9, 8, -2, 16, -3, 0, 19, -8, 8, 1, 2, -4, 0, 11, 0, -3 }, - { -9,-23, 3, 10, 4, 4, -3, -2, -2, -2, 1,-22, 11, 0, -2, 5, - -2, 14, -9,-11, -4, 7, 5, 32, 1, -3, -7, 0, 21, -9, 7, -6 }, - { 0, 0, 0, 2, -1, 1, 0, 1, 3, 0, 0, 1, 0, 1, 0, 1, - -3, 0, -1, -2, 0, -1, -1, -3, -1, 1, -4, 1, -1, -5,-69,-19 }, - { -3, -5, -8,-12, 4, -3,-19,-11, -5, 0,-14, 7, 18, -6, 7, 22, - 8, 14, 15, 10, 3, -1, -3, 5, -1, 7, -7, 1, -6, 3,-26,-11 }, - { -1, -6, 4, -4, -5,-16, 0, -6, -3, 11, 1, 0, 9, 5, 16, 3, - -4,-33, -4, 4, -7, 0, 1, 6,-11, -2,-13, -2,-18, 20,-25,-16 }, - { 4, 0, -1, 0, -5, 1, 0, 2, 0, 11,-10, 4,-10, 7, 16, 2, - 16, 15, 2, -1, 2, 9, 2, 8, -3, -5, -2, 0, -3, 0,-33, -2 }, - { -3,-15, 10, 10, -9, -1, 7, 3, 5, -5, -8, -8, -3, 15, -9, 4, - 12, 13,-13,-14, 10, -6, 9, 22,-27, 23, -1, 5,-24, 2,-30, 5 }, - { 0, -2, 7, -5, -5, 3, 5, 3, -3, -5, 2, 1, -4, 3, -3, -1, - 1, -2, 10, 22, -3, -4, -2, -2, -7, 3, 8, 1, 14, 4,-37, 9 }, - { -3, -4, -1, 1, -4, 0, 6, 2, 6, -7,-10,-10, -1, -4, 11, -3, - 7, -6, 4,-12, -1, 5, 1, -7, 10, -6, 17, -4, 8, 3,-40, 13 }, - { 2, 12, 4, -7, 14, -3, 16, -2, 18, 2, 13, 5, 5, 1, 11, -1, - 0, 9, 2, -6, -1, 2, -6, 2, -5, 3, 5, 1, -1, 1,-32, -7 }, - {-16, 11, 7, -4, 2, -5, -9, 9, 11, 11, 15,-13,-11, 11, 9, 4, - 3, -8,-10, 12, 12, 0, 0,-16, -9, 13, 2, 9, 4,-13,-33, 3 }, - { 6, 4, 5, 4, 3, -1, 5, 6, 4, 2,-11, -1,-15,-11, -1, 1, - 11, -3, -2, 24, -4, -6,-25,-10,-15, -8, 0, 0, -5, 4,-30, 2 }, - { 10, -3, -6, 1, -9, -5, 6, 9,-10, -3, 8, -1, 4, -1, 11,-11, - 3, 9, 11, -3, 6,-17, 5, -8,-33, 9,-13, 19, -2, 9,-25, 2 }, - { 0, 0, -1, -3, 0, -2, 1, 0, 0, 2, 1, 0, -2, 0, -1, 2, - 0, -1, 4, -1, 2, -3, 4, -2, 3, 3, 1, 0,-15, 12,-63, 27 }, - { -2, 14, 9, -1, 3, 0, 1, 1,-19, 15, 3, 4, 0,-10, 1, -5, - 3, 0, -5,-10, 2,-16, -4, 8,-12, -6, 7, -5,-10, -1,-33, -4 }, - { 0, 3, 1, 3, 1, 2, 4, 4, 9, -6, -8, -5, 1,-12, 3, 8, - -10, 6, -1, 1, 13, -5, -5, 2, -4, 13,-18,-10, -7, -9,-33, 10 }, - { -6, -3,-12, 5, -1, 11, -6, 0, -2, 1, 2, -7, 3, 1, 3, -2, - 1, 8,-10, 7, -1, -3, 3, 0, 13, 1, 6, 7,-16, -7,-39, 8 }, - { -6, -1, 11, 6, -3, 8, 3, -5, 3, 0, -5, -2, -6, -3, -4, 2, - -3, 13,-11, 1, 7, 5, 19, -5, -3,-15, -1, 7, -1, 6,-33, 8 }, - { -7, 3, -4, -3, -4, 1, 6, -5, -5, 6, -8, -1, -7, 4, -1, -6, - -2, 1, 7, 0, 1, 1, -5, 2, -2, 0,-13, -2,-31,-14,-39,-12 }, - {-10, 9, 0, -3, 1, -1, -1, 0, 1, -5, -1, -4, -2, 5, 2, -7, - 18, -8, -2,-19, -7, -7,-12,-14,-11, -1, -9,-13, -7,-12,-31, -9 }, - { -3,-16, 10, 9, 1,-10,-12, 2, -2, 2, 7, -3, -3, 1, -4, -5, - -9, 5, 7, 3, -1, 4,-11, -8, 4, 13,-10, 13, 10, -4,-36, 1 }, - { -7,-12, 4,-20, -7, -7, 2, 11, -1, -2, 3,-12, 1, 0, -6, -7, - 6, 4, 13, 3, -3, 4, 3, -6,-12, 5, -5,-22,-13, -8,-37, -6 }, - { -7, 5, 3, 5, 7, 9,-14, -3, 10, 17, -1, 1,-12, 5, -6, 0, - -4, -9, 0,-11,-14, 3, 13, 6,-25, -8,-12, 4,-10, 18,-30, -1 }, - {-10, 6,-10, 6, 6, 1,-10, 0, -7, 5, -2, 17,-18, -4, 0, -3, - -16, -6, -3, -8, 5, 1, -4, 6, -7, 16, 6, 10, -1, 0,-32,-11 }, - { -1, 9, 9, -5, 4, 9, 6, 9, -4, -2, 7, 11, 4, 2, -5, -4, - -6, 0, 2, -3, -1, 5, 10, 0, 12,-10,-18, -3, -1, 14,-33, 2 }, - { 4, -8,-18, -4, -5,-11, 4,-10, -4, 9, 13,-12, 1, -6, 1, 2, - 4, -9, 8, 3, -6, 21, 13, -1, -2, 1, -2, 6, -7, 0,-30, 1 }, - { 6, -1, 2, -3, -1, -4, 6, -4, 0, 4, 2, 2, -9, 2, 6, 3, - -2, 4, -1, 9, -6, 0, 7, -8, 5, 19, -2, 9, -5, 2,-33, -8 }, - { 2, 1, 12, -5, -8, 8, 3, -2, -4, 1, -2, 5, -4, -9, -8, -8, - 7,-11, -4, 6,-10, 7, -1, -1, -2, -1, 16, 32, -7, 20,-33, -6 }, - {-18, 2, 6, 13, 9, 9, -1, 3,-17, 24, -2, -6, 28, 8, -2, 6, - 3,-10,-34,-16,-13, -4,-15,-11,-12, -3,-10, 4, -8, 4,-31, -4 }, - {-11, 0, 18, 2,-16, -9,-13, -2, -2,-12, -3,-22, 30, 0, 8, 3, - 9, -4,-16, 1, 0,-11, 15, -2, -4, 6, -5, 6, 1, 2,-25,-12 }, - { 14, -1, 5, 7, 3,-15, -8, 1, 5, -2, 12, 13, 11,-25, 3, 1, - 0, -2, -4,-16,-23, 0, -5,-17, 7, 5, -9, 6, -5, 2,-32, -7 }, - { 3, -1, 6, 14, 2,-12, -9, -9, 4, 7, 4, 6, 5, -8, 4, 2, - 4, 5, -2, 8, 8, -6, 0, 10,-20, -1, 3, -1, 8, 23,-33, -5 }, - { -3, 11, -6, 3, -4, 5, 7, 3, 4, 5, -2, 3, -1, 30, 6, 1, - 8, -6, 0, 0, -9, 6, -9, 4, 2, 9, -6, 1,-12, 0,-34, 18 }, - {-17, 13, 0, 1, 9, -4,-11, 0, 7, 0,-10, -4, -1, 6, -6, 4, - 1, 6, -9, 3, -5, -6,-11, 2, -4, 14, 23, -3, 2, 5,-30, 12 }, - {-14, 5,-27, 2, 0, 7, 1, 4, 30, 8, 7, 5, 1, -1, 0, 5, - 8,-10, 48,-11, 12, 33, 6, 8,-15, 20, -2, -5, 32, 5,-19, 10 }, - {-16, -4,-12, -7, -2, 0, 8, -6,-20,-18, 16, -3, 0, 31, -2, 11, - 2, -9, 49,-19,-12,-23, 10, 26, 16, -2, 4,-21,-14, 13,-11, -9 }, - { -5, -9, -1, 3, -5,-21, 2, 10, 0, 0, 10,-21, -7, 7,-26, -9, - 22, 32, 58, 11, -3, 11, -5, -8,-13, 6, -5, -9, 1, 10, 14, -8 }, - { 7, 7, 10, 3, -2, -1,-11,-11, -6,-43, -3, 14,-19,-18, 19, 18, - -32, 10, 45, -6, 6, 21,-20,-12, 2, 4, 6, 6, -4, 3, 3, 1 }, - { 21, 22, -3, -2,-11, -6, -1, -2, 8, 8, 32,-21, 7, 28, -4, -6, - -3, -2, 50, 2, 2, 27, -5, -8, 12, 7, -5, -1, -4,-17, 27, 6 }, - { 13, 7, 2, -6,-12, 2,-10, -5,-17, 11, 4, 17,-12, -2, 5,-17, - 37,-16, 48,-14,-18, 29, 8, 24, 11, -5, -9, 11, -1, 1,-13, -3 }, - { 1, 1, -1, 2, 0, 0, 0, -1, 1, -1, 7, 2, -3, 3, 0, 6, - 2, 10, 54,-25, 7, 54, -5, -6, -1,-15, 9, 13,-24,-15,-12, 3 }, - { 21, 5, 8, 3, -3, -4, -2, -4, 3,-11, -5, -8, 9, 16, 8, -9, - -10, -3, 46,-46, 2, 1,-10, 10, 17, 11,-20,-36, 10, 14, 0, -5 }, - { 7,-13, -6, -9,-24, 45, 2, 8, 8, 0, 17, 20, 12,-24, 1, -7, - -15, -3, 46,-13, -2, 20, 1,-13,-11,-13, 2, 15, 1, 10, -1, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, -1, - -16, -9, 31,-69,-34, 26, 7, 17, -1, -6, -1, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, - -5,-20, 18,-82, 22, 3, -7, 9, 4, 6, 2, -4, -1, 0, -2, 2 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, -1, - 15, -5, 62,-36, 4, 52, -7, 5, 0, 6, 1, 2, 1, 1, -1, 0 }, - { 3,-19, 19,-20, 13, -4,-11, 8, 8,-16, 10, 1,-14, 30, 1,-33, - 10,-11, 45,-30, 3, -4, -3,-13, 7, 12, 3,-22, 3, -2, -4, -2 }, - { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, - 11, 8, 70, 48,-10, 21, 4, 9, -9, -9, -4, -6, 0, -1, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, - 2, -1, 80, 2,-15,-36,-10, -5, -2, 8, -2, 2, 0, 0, 0, 0 }, - { 10, 8, -8, -8,-24, 12, -1, 0, 20, 9, -1, -2, 2, -2, 12,-10, - -2,-13, 35,-43, 44, 15,-10,-25, 4, 10, -3, -5, -5, 7, -1, 3 }, - { 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -1, - -18, 9, 49,-72, 7, -8, 7, -5, 2, 3, 2, -2, 1, -2, -3, 1 }, - { -1, 4, -3, 10, 19, 4, 3, 20, 6,-24, 6, 9, 8, 15, 18, 18, - -36, 19, 57,-11, 4, -3, 8, 7, 2, -3, -2, -9,-15, -2, 12, -4 }, - { 20, 3, 11, -9, -4, 22, 42,-25, 1, 5,-10,-19, 0, 9,-16, 5, - 2, 10, 44,-29, 17, -3, -9, -2, -1, 8, 14, -7, -1, 16, -5, 1 }, - { -7, 16,-11, 12, 6, 33,-15, 14,-23, 2,-26, 8, 2, 10, 0, -5, - 8, -8, 38,-38, -4, 5, 5, 5, 1, 22,-15, 7, 6, 0, 4, 28 }, - { -1,-12, 2, 10, -2, 0, 7, 17, 12, 22, -4, 10, 25, 29, 5, 18, - 4, 1, 27,-39, 31, 17, 2, 2, 22,-23, 13, 16, 1, -7, -4, -5 }, - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 0,-14, 0, - -7,-11, 49,-22, -4, 19, 17,-39, 4,-29, 10, 2, 36, -4, 23, -1 }, - { -2, -2, -2, -2, 1, 15, -5, -7,-16, -8,-19, 16, -3,-20, 36, -9, - -3, 20, 39,-20, 0, 2, 27,-16, 10, 10,-14,-22,-16, -3, 13, -8 }, - { 5, -9, 6,-25, 7, 37, 13,-10, -5, 3, -5, 7, 18,-22, -7, 9, - -5, -4, 50,-11, -4, -5, -5, 8, -4, -2, -4,-27, 14, 20, 7, -9 }, - { 0,-14,-10,-27,-14,-17, -6, 26, 10, 2, 14,-12, -5, 0, 8, 9, - 0,-28, 55, -7,-12, -7, 4,-10, 10, 7,-12, 11, 3, 5, 9, -8 }, - { 2, 23, 4, -2, -1,-20, -2, 14, 10, -9, -9,-24, 10, 0, 11,-12, - 12, 11, 49,-25, -2, 29, 7,-13, 21,-10, 11,-17, 3, 1, -8, 5 }, - { 3, 0,-14, -6, 18, -2, 17, -9,-19, 9, -5, 9, 14, 6, 19, -3, - 27, 1, 41,-21, 20,-15, 33, 0, 26, 14, 7, 10, 3, 20, -3,-12 }, - { -1, 16, 15, -8, 3, -8, -8, 21, -5,-16,-29, 4, 1, -6, -4,-28, - 2, 31, 37,-26, -2, 13, 24, 8, -9, -6,-29, 10, 7, 2, 7, 8 }, - {-10,-10, 11, 13,-32, 2, 16, 9, 14, 23,-15,-13, 24, 13, 4,-27, - 14, 12, 31,-18, 17, 23, -2, -7,-14, 9,-17, -6,-10, 20, 9, 6 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, - 5, 1, 89, 8, 10, -6, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, - 4, -7, 64,-50, 7, 37, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -2, 5, 3, -4, -4, -3, 2, -3, 3, -3, 5, 4, 1, -6, -1, 1, - 6, -2, 50,-35, -7, 43, 7, -7, -5,-26, 24, 21, 3,-15, 5, 6 }, - { -8, 21,-19, 33, -8, 22,-11, 17, 3, 0, 0, -2, 1, -3, 6, -1, - 10, -8, 4,-11, -4, -5, 0, 8, -4, 3, 1, -4, 4, 2, 8, 4 }, - { -7, 5,-20, 9,-22, 3,-14, 1, 6, 13, 23, -2, -4, -7, 2, 0, - 11, 4, 6, 3, -7,-11, -7, 4, 5, 5,-12, 8, 2, 4, 7, -3 }, - { -7, 6, -4, 20,-20, 16, -2, 7, 6, 16, 11, 12, -7, -7, 5, 3, - -9, -4, 1, 2, 5, 2, 1, -9, -2,-17, -4, 6,-10, 7, -7, -6 }, - { -9, 18,-17, 12,-24, 1, -1, 4, 14, 9, 4, 3, 2, 8,-12,-14, - 4, -8, -4, 7, 7, 6, -1, 13, -9, -4, -1, 1, 0, -4, 15, 8 }, - {-25, 2,-11, 6, -5, 24,-28, -5, 8, 12, -2, 6, 8, -3, 8, -9, - -1, -5, -1, -5, 6, -1, -1, -1, -4, 8,-12, -2,-13, 7, 2, 1 }, - {-14, 14,-18, 20,-10, 12, -2, 9, 1, 0, 12, -2, 15,-10, 26,-17, - 16,-11, 10,-10, 9, -2, 4, -8, 2, -3, 4, 4, 2, -3, -5, 1 }, - {-18, 12,-18, 21, -6, 12, -6, 13,-25, 18, 1, 11, -9, -5, 0, 10, - -5, 3, -3, 8, -9, 7, 4, 2, -9, 0, 5, 0, 2, -3, 9, -8 }, - { -4, 16, 1, 18,-30, 9, 1, 6, -8, 13, 13,-12, -6, -1, 13, 7, - 6, 2,-15, -3, 5, 5, 1, -6, 1, -5, 0, 2,-16, 0, 3, -4 }, - {-21, 1, -2, 6,-43, 18, -1, 5, -1, 4, 6, -2, -1, -3, -1, -3, - 0, 1, 2, -9, 0, -1, 0, -2, 0, -1, -1, -2, 6, 0, 1, -2 }, - {-23, 10, 4, 7,-32,-11,-18, 2, -2, -7, -6, -3, -3,-12, 19, 3, - -5, -6, 16, -6, 16, 2, 16, 16, 8, -2, 13, 8,-15,-11, 2, 10 }, - { -8, 2,-13, 2,-29, 24,-20, 19, 1, 10, -4, 10, 1, 2, -9, 11, - -1, -2, 9, -5, 19, -7, 16, -9, -2,-18, 11, 1, 1, 0, 7, -3 }, - { -6, 3, 4, 13,-26, 10,-10, 28, -7, 28, 1, 7, 0,-14, 5, 7, - 4, -4, 3, -2, 3, 3,-11, 7, 6, 4, 0, -1, 2, -1, -3, 2 }, - { -6, 16,-31, 13,-10, 17, -6, 4,-14, 4, 4, -1,-10, 12, -5, 1, - -14, 15, 0, -8, 1, -5, 3, 3, 9, -5, 7,-20, 7, 4, 11, -5 }, - {-19, 3,-17, 14,-12, 16,-22, 18, 14, 8, -2, 4, 10, 12,-14, 4, - -3, 2, 3, 7, -7, 7, -6, 2, -2, -4, -5, 0, -5, -2, 2, 1 }, - { -9, -7,-11, 24,-36, -9,-11, 5, 7,-12,-13, 18, -2, 20, 1, -4, - -1,-10, 15, -6, 14, 1, 0, 2, 1, 2, -9,-16,-11, 7, 13, 0 }, - {-24, 24,-18, 18,-22, 14,-11, 13,-12, 11,-10, 11, -7, 11, -5, -4, - -1, 1, 5, 2, 3, -1, 1, -5, 7, -4, 5, -6, 8, -7, 8, -6 }, - { -6, 18,-22, 22, 5, 11, -1, 6, 19, 22, 8, 4, -8, 20, -2, 15, - -6,-18, 0,-33, -9,-12, -1, 6, 5, 2, 5, 5, -5,-17, -3, -3 }, - { 1, 11,-16, 9,-18, 11, -4, 18, 20, 26,-10, 8, 1,-11, 8, -4, - 0, 7, 3, 5, 2, 2, 10, -2, -4, 4, -4, -2, 1, -4, -5, -1 }, - {-10, 6, -1, 18,-17, 27, -3, 10, -2, 12, -7, -9, 1, 1, -1, 7, - -12, -1, -7, -6, -1, 8, 3,-15, 8, 9, 3, -7, 4, -1, 1, -1 }, - {-14, 6,-16, 22, 2, 5, 0, 5,-18, 11, 6, -3, 22,-20, -9, -3, - 6, -6, -7,-15, 1, 15, -8, 11, 8, -3, -8, 1, -8, 2, 6, -2 }, - {-21, 5,-19, 19, -7, 4, -7, 0, -8, 6, 12, 5, -3,-22,-13, -6, - -1, -3, -2,-14, 6, -3, 1, -8, -7, -5, -6, 11, -3,-10, -5, 2 }, - { -1, 9,-12, 15, -6, 6,-19, 14, -9, 11, 3, 12,-17, -3, 8, -4, - -3, -4, 1, -5, 4, 5, -7,-15, -7, 15, -6, -5, 1, -5, -3, 1 }, - {-12, 20,-15, 20,-14, 3,-14, 9, -6, 33,-13, 6, -2, 8, -6, 7, - -5, -6, -3, -3, 0, 8, -3, -3, 1, -2, 2, 2, 6, -5, -5, -2 }, - { -7, 12,-18, 12,-18, 10, -4, 8, 2, 4, 8, 9, 0, 3, -8, 3, - 6,-12, -4, 1, 25, -5, -9, 6, -7, 0, -9, -7, 3, -5, -4, -4 }, - {-18, 12,-10, 11,-22, 0,-15, 5, -2, 2, -3, 6, -4, -4, -3,-15, - -2, -3, 21, 6,-12,-11, 19, 3, 3,-14, 7, 0,-11,-22,-10, 0 }, - {-15, 2,-30, 15,-17, 13,-16, 8, -7, 10, -8, 2, 11, 3, 10, -7, - 7,-22, 12,-10, 3,-12, 6,-10, 12,-10, 7, -8, 5, 2, 9, 1 }, - { -9, 11,-14, 6,-10, 21, 5, 12, -5, 5, 7, 21, 6, 2, -2, -1, - -1, 4, 2,-20,-18, -1,-14, 3, -1, 4, -7, 10, 1, 11, 4, -4 }, - {-22, 8,-30, 13,-21, -4, 4, -1, 12, 9, -2, -3, 2, -6, 4,-13, - -2, 8, 8, 1, -7, 3, -4, -5, -1, -7, -2, 8, 8, 7, 8, 0 }, - { -6, -4,-35, 16,-13, 15,-11, 14, -7, 9, -1, 11, 7, 0, 13, 10, - -1, 8, 1, 1, -2, 8, -1, 2, 2, 3,-10, -1, 7,-13, -3, -7 }, - {-15, 7,-16, 14,-18, 17, -6, 14, 3, 4, 7, -3, 10,-22, 5,-15, - 4, -4,-11, 15,-15, 11,-11, 20, 1, 0, 2, 1, 11, -3, 11, -7 }, - {-12, 3, 5, 16,-37, -1, 15, 15,-15, 10, 3,-10, 1, 15, 7,-15, - -13, 8, 9, -3, 2, 12, -8, 2, -5, 0, -3, 4, 5, -9, -4, 5 }, - {-16, 26, -4, 14,-22, 26, 6, -3, -8, 4, 21, 6, 16, -4,-11, 7, - -10, 3, 3, 7, -4, 2, -9, 8, -2, 2, 5, -2, -4, -2, 7, -1 }, - { -7,-10, 4, 3, 2, -4,-12,-10, -4, -5, 16, 19,-16, 1, 2, -9, - -10, 0, 9, 7, -8, 3, 12, 8, -6,-11,-13, -1, -3,-20, 6, -5 }, - {-14,-17, 3, -5, 14,-12,-12, 8, -6,-25, 21, 21, 10, -8,-12, 4, - 10, -4, 3, -9, 11, 9, 0, 4, 2,-15, 1,-14, 4, 1, 0, -4 }, - { -4, -9, -3, -1, 6, 3, -6, 6,-10, -4, 14, 8, 2, -3,-12,-19, - 0, 11,-20, 1, 6, -2,-27, -6, 10,-17,-14,-17, -9, 8, -8, 3 }, - {-12,-13, 16, -4, -2, 12, -7,-11, 2,-13, 3, 7,-16,-18, -1,-12, - -2, 1,-12, -9, -2, -6, 2, 9,-22, -3, -4,-14, -7, 7, -1, 2 }, - { -7, -8, -8, 15, 15, 18, 15, 16, -4,-37, 11, 15,-12, -1, -3, 3, - 6, 6, 0, -5, -3, -5, 9, 1, 1,-11, -1, -8, -6, 2, 3, 0 }, - { -6, 7, -5,-12, 13, 10,-18, -4, -3,-21, 6, 16,-15, -7,-12, -9, - 1,-12, -1, 10, -2, -1, -3, 4, -4, 1,-16, -1, 12, -9, 5, 9 }, - {-14, -5, 9, 3, 4, 26,-28, 3, -6,-24, 4, 5, 3, 13, 5, -1, - 3, -1, 3, 1, 1, -5, 3, 0, -7, -8, -7, -3, 3, -5, 4, 0 }, - { -4, 2,-10, -6, 25, 26, -6, 10, -6, -8, 15, 11, -6, -3, 2, -7, - 5, 14, 9, -1, 0,-12, 4, -4,-10, 1, -3, 3, -2, -2, -6, -1 }, - {-10, 8,-15,-10, 19, 17, -8, 0, -3, -7, 7, 5,-13, -1, 7, -7, - 1, 13,-12,-13, 17,-12, 1, 26,-18, -3, -5, -6, 4, 5, 8, 1 }, - { 2, -5, 3, 0, 0, 0, 2, -3, -2, -5, 7, 13, -4, 9, 0, -5, - 4, -1,-11, -8, -4, 0,-13, 2,-47,-23, -8,-11, -4, 4, -2, -3 }, - {-18, -4, 4, 5, -1, 17,-12, -8, 1,-12, 7, 20,-12, 3, -2,-11, - 16, 12, -6, 1,-13,-16, -6, -3, -3, -5, 4,-12, -5, -9, 10, 1 }, - {-11, 0, 4, 7, 7, 8, 3, -1, 3,-19, 32, 8,-19, -8, 2, 4, - -12, 15,-16, 3, 1, 9, -2, 1, -2, 8, 5, 6, -4, -1, 11, -8 }, - { 3, -1, 4, -2, 14, 32, -9,-23,-10,-12, 22, 15, -1, -2, 10, 0, - 4, 6, -8, 4,-15, -2, -1, -4, 0, -8, 4, 1, -8, 3, 4, 1 }, - {-17,-12, 6, -8, 16, 13,-20, -8, -1,-16, 10, 21,-19, 11, -9, -5, - 7, 18, -6, 7, -7,-18, 13, 2, -2, 8,-12, -9, 2, 4, -5, 16 }, - { 4, 0, 17,-11, 12, 7,-12, 5, -1,-25, 30, -8, -7, -6, -4, -7, - 9, 8, 7, 3, 3,-16, 8, 0, -2, -2,-18, -3, -4, -5, 1, 4 }, - { -3, -6, 6,-16, 17, 6, -3, 2, -9,-17, 12, 11, 11, 2,-20, 8, - 1, 1, 0, 2, -2, -6,-21,-13, -9,-15, -1, -8, -6, -8, 0, -2 }, - {-11, -7, 6, -9, 3, 6, 8, 16, 4, -5, 23, 26,-10, -3, 4, 0, - 2, 2, -4, 4, -2,-12, 12, 10,-11, 0,-10,-16, 3, 0, 0,-10 }, - { -5,-16, 10, -6, 27, 13, -3, 4, -2,-13, 15, 5, 2, 5, 3, -4, - 13, 12,-11, -7, 0, 1, 11, 12, 2, 13,-15, -8, 9, -2, 3, 8 }, - { -5, -8, 4, 3, 9, 3,-11, 10, 14,-25, 14, 8, -2, 5,-12,-21, - 2, 10, -7, 2, -3, 2, 0, 2, -1, -3, -5, -6, -1,-16, 2, 8 }, - { -1, 5, 1,-11, 5, 9, -7, 8,-13,-12, 4, 12, -4, 1, -1, -1, - 27, 29, 10, 15, 2, -6, -3, 4,-21, 10, -9,-11, -6, -1, -9, -3 }, - { -6, -3, -1, -6, 11, -5, 0, -2, -5,-31, 11, 3, -1, 5, -3, 4, - 5, 7,-10, 5,-10,-13, 4, 12,-15, -2, 2, -7, 1, -9, -3,-10 }, - { -3, -7, 17, -8, -5, 36, 8, -7, -8,-20, 12, 8, 1, -1, 3, 0, - 1, 4,-10, 3, 1, 4, -2, -3, -2, -3,-10, 4, -1, -7, 3, 2 }, - {-13, -3, -5, 9, 22, 6,-23, 3,-10, -7, 17, 17, 18,-14, -8, -8, - 2, 4, -8, 2, -3, -8, 6, 4, -1, 7, 0, 0, -3, 0,-12, -3 }, - { -3,-10,-15, -3, 9, 3,-23, -9,-13,-18, 12, 13, -2, 0, 1, 8, - -1, 2, -7,-12, -5, 14, 2, 1,-22, 6,-10, -8, -9, 28, -7,-14 }, - { -3, 1, 2, -1, 13, 7, -2, -7, 1, -3, 6, 9, -3, -2, 4, -2, - 2, 1,-10, -2, -2,-22, -2, -7,-10, -5,-11,-27,-12,-16, 4, -7 }, - { 2, -6, -3, 1, 8, 0, -2, 12, -3, -4, 58, 15,-10, -4, -2, 2, - -2, 0, -2, -6, 2, 4, -1, 1, -4, 1, -1, -5, -4, -3, 3, 1 }, - { 10, -1, 0, 5, 21, 7,-14, 6, -3,-16, 15, 17,-16, 13, 3, -6, - -4, 6,-12, -5, 1, -4, -7, -8, 2, 3, -6, 6, -1, -8, 5, 4 }, - { -6, -2, -8,-11, 15, 10, 0, 8, -6,-15, 33, 8, -2, 18,-15,-11, - 5, -1, 0, 15,-15, -4, -4, -1, 10, 7,-13, 4, -4, 0, 8, 3 }, - { -7, -2, 0, -2, 0, -2, -4, -5,-14,-16, 12, 38, 7, 12, 6, -4, - 0, -1, 0, 3, -2, -6, 0, 2, -9, 1, 0, -1, 0, -2, 4, 1 }, - { -8, -4, 18, 1, 14, 5,-12, -3, 20,-17, 5, 19,-11, -8, 11, -3, - 3, 9, -7, -8, 9,-17, 2, 15,-10,-11, 5, -5, 7, 15, -6, -2 }, - { -7, 2, 38, 5, 19, 16, -5, 4,-13,-20, 0, 4, -4, 6, 4, 2, - -7, 6, -8, -2, -5, -7, 6, 3, -4, -3, -2, -3, 7, -6, -4, 0 }, - {-11,-12, 8,-15, -3, 14, -7,-22,-11, 2, 22, 14,-19, 2,-19, -6, - 1, 3,-18, 14, 2, -6, -2, -8, -3, -6, 5, -7, -8, -4, 1, 1 }, - { 8, 7, 25,-21, 12, -6, -5, -4,-10, 6, 0, 10, 1,-12, 18, -5, - -15, 4, 1, 14, -1, 5, 8, -7, 1, -7, -3, 9, 10, 1, -1, 0 }, - { 9, 10, 32,-15, 8, 2, 11, -7,-18, -8, 2, -6, -9,-16, -3, 3, - -1, 3, 1, -5, 4, -2, 1, -8, 0, -6, -3,-11, 1, 5, 0, 0 }, - { 14, 0, 23,-25, 22, 3, 7, 10, 0, -2, 7, 8, 0, 10, 0, 0, - 3, 2, 3,-10, 0, 10, 0, -7, 0, 10, -1, -5, -7, 1, -1, 2 }, - { 12, 0, 25,-18, -5, -4, 13,-10, 3, -6, 7, 21, 0,-16, 3,-10, - -6, 5, -7, -3, 2, 5, 3, -6, 4, 9, -8, 12, -2, 3, 2, 4 }, - { 31, 15, 27,-20, 10, -7, 15,-10, 9, -8, 4, -5, 3, -3, 5, 6, - 11, -2,-12, -2, 6, -2, 1, 2, -1, -1, 1, 1, 3, 1, 1, 2 }, - { 12, -4, 13,-23, 12, -6, 2, 4, -3, 13, 6, -7, 5,-19, -7, 18, - 1, -7, 7, 1, 16, -7, 3, 0, 3, 0,-12, 8,-11, 9, 4, 7 }, - { 29, 1, 3,-22, -5, 6, 0, 12,-14, 11, 1, 6, -3, 4, 6, -2, - 4,-13, 12, 1, 1, 3,-11, 9,-10, -1, -7, 16,-11, -1, 3, 9 }, - { 4, 4, 36,-23, -5, -8,-15, 1, -6, 3, 13, -1, -5, -7, 4, 9, - 2,-11, -3, 5, 1, 3, -6, -1, -4, -4, -2, 2, 3, -1, -5, -2 }, - { 19, 10, 6,-17, 2, -4, -2, -4, -3, 13, 2, 2,-13, -7, -3,-11, - 9, -6, 1, -9, -5, 4, -5, -9,-18, -7,-11, 9, 4,-11, 8, 4 }, - { 16, -3, 9,-16, 18, -2,-12,-16,-11, 11,-18, 16,-13, 6, 2, 8, - 3, 8, -4,-16, 10,-11, -1, -3, -8, 5, -9, -4, 9, -4, 0, -3 }, - { 14, 15, 3,-23, -5, 7, -8, -6, 2, 17, 2, 12, -8,-12, 13, -1, - -9, 3, 1, 1, 19, 15, 4, -1, 1, 2, -3, 2, -3, 1, 5, 3 }, - { 32, 5,-10,-47, -5, -1, 4, 11, -7, 0, 2, -2, 1, -7, 6, -4, - 6, 2, -4, -2, 2, -2, 0, -4, 1, -6, -5, 2, -2, -1, -3, -4 }, - { 20, 8, 10,-21, -7, -9,-16, 12, 1, 4, 6, -5, 9,-11, -7, 4, - -11, 28, -3, 2, 4, -6, 10, -8, -5, -5, -9, 9, -2, -1, 6, -5 }, - { 38, 3, 23,-25, -6,-18, 3,-10, -8, 6,-10, 1,-10, 2, 2, 0, - -7, 2, -4, 5, -1, 8, -3, 0, 3, 3, -1, 1, 0, -4, -4, 0 }, - { 20, 5, 16,-22, 24,-18, 2,-12,-14, -7, -3, 10, 2, 7,-10, 2, - -8, 1, 8, -1, 4, 1, 4, -2, 5, -9,-18, -8,-13, 5,-11, 10 }, - { 14, 8,-12,-16, 9,-11, -3, -6,-25, -7, 6, 5, -7,-16, 10, 2, - -7, -1, -9, -3, 16, 4, 3, 3, -3, -3,-15, 13, -3, 4, 13, -7 }, - { 16, -9, 19,-23, 7,-19, -3, -5,-15, 11,-21, 21,-16, 18, -1, 6, - 10,-10, 18,-14, 16,-15, 6, -5, -9, 5,-17, 13,-10, 13, 0, 10 }, - { 8, -4, 4,-24, 8,-21,-18, 9,-11, 4, -6, 17, 5, -9, -2, -2, - 2, 15, -2, -3, -2, 1, 7,-13, 15,-10, -8,-11, 3, 3, -1, -1 }, - { 14, 17, 6,-32, 5,-17, -2, 0, 15, -1, -5, 16, 1, -5, -2, 9, - -3, 8, 4, -2, -2, -4, -3, 1, 0, 7, -3, 4, -5, 0, -7, 2 }, - { 24, 6, 22,-12, 8, 3,-14, 4, -7, 8, 6, 5, 6, 1, 6,-12, - 15, 10, 4, 11, 9, 6, -7, -4, 10, -9, 2, -1, -5, 11, 15, 3 }, - { 17, 12, 3,-23, 5, -1, -2, 1, -9, -1, -3, 1, 8, 1, -5, 17, - 11, 0, -2,-11, 7, 4, 0,-27, -7, 1, 2, -8, 9, 7, 5, 3 }, - { 12, 10, 12,-10, -4, 5, -1, 2,-24, 5, -8, 2, 6,-17, 19, 5, - 12, -2, 16, -7, -6,-14, 4, 1, -3, 13,-16, 5, -1, 4, 1, 1 }, - { 31, 9, 11,-17, 10, -3, -7, 7, 1, 2, 2, 4, -3, -1, 11, 4, - -5, -8, 1, 4, 15, -6,-28, 1, 8, 3, -6, 5, 17, -2, 2, -4 }, - { 11, 19, 16,-26, 0, -7, -7, 2,-13,-15,-12, 9, -3, 27, 8, 4, - -6, 1, 4, -6, 11, -1, -6, -7, -3, 0, -6, 4, -6, -7, -3, -1 }, - { 10, 18, 16,-32, 19, -9, -4, -3, -7, 8, 8, -3,-11, -2, -6,-16, - 13, 13, -6, -1, 10, -2, -2, -9, 0, -3, 9, 4, 11, -2, -6, 6 }, - { 9, 4, 19,-33, 4, 7,-12, 36, -3, -1, 8, -2, 2, -8, -9, -4, - -8, 0, 1, -1, 0, -4, -4, 3, 0, 3, 6, 0, -6, 2, 0, -2 }, - { 25, 7, 15,-12, 2,-24, -1, 24, -4, 4, 9, 0, -2, -9, 4, 6, - 3, 13, -3, 1, 5, -1, -3, -5, -1, 7, -2, 3, 4, 4, 1, 0 }, - { 19, 6, 8,-20, 9, -9, 5, -4,-13, 7, 11, -3, 5,-13, -9, 6, - -11, -1, 0, 4, 11, 26, 3, 6, -7, 12, 6, -3, 1, -9, 7, 1 }, - { 15, 6, 19,-23, -3, -9, 3, 16, -6, -4, 6, -5,-10, 1, 16,-14, - 2, 0, 2,-13, -3, 8, -6, 3, 1, 1, 2, -5, 12, -4, -8, -3 }, - { 14, 4, 16,-20, 1, 12, 0, 6, -3, 9, 4, 16, 10,-16, 5, 7, - 5, -4, -4,-18, -3,-11, -4, 4, -7, 3, 13, 7, 3, 3, 2, -7 }, - { 22, 3, -1,-30, 18, -3, -9, 9, -2, 11,-16, -2,-14, 12, 0, 4, - -5, 4, -1, 3,-20, 12, 4,-10, -2, -2,-12,-12, 10, 6, 11, -3 }, - { 15, 7, 2,-21, 5, 4, 9, -9,-33, 7, 7, 3, -6,-14, -8, 10, - 12, 0, 2, -1, 5, 4, -2, 0, -7, 0, 2, 4, 0, 1, -3, 8 }, - { -7, 0, 12, 3, 0, -6, 8, -4, 0, 2, 14,-15, 2, -7,-31, -3, - 14, 0, 14,-15, -1, -4,-15, 10, 1, -3, 1, 2, 5, 2, -8, 1 }, - { -2, 5, 1, 0, -3, 3, 3, -6, -1, 2, -4, 1,-19, 0,-11, 18, - 11, 10, 21, 5, 6, 2, 10, 3, -6, 0, -2, 13, 5, -1, -2, 9 }, - { -9, 1, -5, 0, 0,-15, 8, 4, 8, 3, 8, 12,-13, -2,-39, -2, - 4, -4, 5, -3, -4, 3, -3, 3, 10, 5, 3, 2, -3, 5, -2, 8 }, - { -9, 6, 6, -8, 12,-12, 23,-18, 4,-15, -5, 2,-20, 13, -7, 7, - 7,-12, 14,-12, 6, 1, 1, -3, -8, 9, 0, 1, -7, 3, 7, -6 }, - {-18, 13, 4, 3,-10,-30,-10, -6,-14, 1, -7, -4,-35, 5,-25, 11, - 9, 8, 19, -4, -7, -3,-18, -8, 1, 5, 10, -4,-14, -9, 3, -4 }, - { -6, -1, 4, -9, -9, 4, 20, 0, 0, 3, 11, 7,-16,-17,-20, 11, - -6,-14, 1, 4, 19, 2, -8, 6,-15, 3, 6, -5,-14, 3, 7, 2 }, - { 1, 6, -2, -8, -5, -3, 3, -8, 21, 1, 3, 16,-14, -2, -9, -4, - 13, -2, 18, 14, 14, 19,-13, 5,-10, 2, -3, 3, 5, 5, 1, -1 }, - { -1, -5, -6, -2,-11, -7, 5, -4, 5, -1, 0, 3, -3, 2,-19, 18, - 16, 4, 14,-22, -2,-11,-22, 1, -1, 11, 1, 2, 11,-10, 7,-12 }, - { 1, 4, 5, -1, -9, -5, 1, 12, 5, 6, 12, 9,-24, 23, 1, 20, - 14,-11, 13, 5, -2, -2, 5, 6, 2, 1, -9, 6, 10, 5, -4, 11 }, - { -1, -1, 1, 7, -3, -4, 8,-16, 15, -1, -7, 9,-22,-11,-11, 10, - 16, 9, -2, 4, 13, 10, 6, 16, 4, 7, 1, -8, -7,-14, -7, 4 }, - { 1, 3, -6, 0, 15, -9, -4, 0, 4, 6, 12, 9, -6, -5,-22, 17, - 7,-11, 15, -5, 1, 3,-19, 0,-15, -3, 16, 5, 5, -7,-11, 12 }, - { -2, -1, 13, 2, 4,-24, 37, -5, -2, -6, 12, 7, -2,-23, -4, 9, - 2, -3, 3, 2, 3, 3,-14, 11, 0, -4, -2, -2, 3, 10,-10, 4 }, - { 2, 9, 8, -6,-28, 14, 28,-11, 18,-11, 0, 2, -2, 4,-12, 3, - 6, 0, 7, -7, -6, 2, 5, -1, -1, -1, 5, 2, 3, 0, -3, 9 }, - { -7, 14, 5,-10, -3, 7, 4, -5, 7, -8, -7, 4,-12, 14,-16, 25, - 3, 0, 1, -5, 12,-10, 0,-10, 0, 12, 12, 17, 12, 10, -1, 0 }, - { -4, -2, 5, -2,-17, -3, 5, -5, 7,-17, 1, 5, -4, 4,-20, 0, - 11,-15, 13, -8, 10, 1, 1, 5,-12, 9, -8, 0, 6, -1,-11, 4 }, - { -3, 12, 13,-15, -7, -7, 0, 5, 33, 3, 3, -6,-13, -7,-15, 10, - 3, 3, 3, -5, 2, 7, -1, 0,-12, 2, 11, -6, -9, 0, 5, 11 }, - { -8, 5, 10, -7,-14, -4, 13, 0, 18, -3, -6, 7, 1, -6, 0, 21, - 8, -7, 10, -8, -3, 17, -9, 0, -5, 1, 4, 8, -3, 11, -5, 0 }, - { -8, 8, -3, -8, 8,-11, 16,-16, 17, 0, 8, 16,-17, 10,-16, 10, - -8, 6, 11, 0, 10, 7, 4, 5, 7, -5, -5, -6, -7, -5, -1, 16 }, - { -6, 0, 6, 1, -8, -8, 8, -7, -5,-10,-11, 8,-19, 6, -7, 13, - 5, -3, 4, -8, 7, -1,-18, 9, 0, -5, 6, 26, 3, 8, 2, 4 }, - { -2, -2, 23, -2,-20, 2, 7, -7, -6,-15, 3, 9,-19, -2,-10, 7, - -2, 7, 9, 11, 0, 4, -4, 6, 9, -2, 4, -3, 4, 3, 2, 8 }, - { -6, 12, 10,-10, -7, 4, 17, 11, -6, 1, 12, 11,-18, 8,-12, 4, - 1, 13, 6,-13, 23, 9, -5, 8, -2, -5, 1, 3, 0, -2, -4, 4 }, - { 7, 1, 7,-17, -8, 8, -1, -7, 5, -6, 4, -3,-16, 9,-24, 18, - -3, 10, 13,-11, -6,-11, -4, 10, 0, 11, 8, 2, 6, -5,-11, 4 }, - { -4, 1, -5,-10, 0, -3, 9, -2, 4, -1, 1, 5,-41,-10, -7, 4, - -3, 3, 1, 0,-12, 4, -3, 0, 2, -1, -2, -5, 3, 2, -7, 5 }, - { -2, 1, 4, 4, -3, -6, 1, 0, 12, -5, 11, 0,-17, -3, -1, 11, - 4, 1, 27,-12, 0,-14, 2,-15, -3, -9, 0, -7, -3, 15, -8, 6 }, - { -6, 4, 9, 2, 4, 3, 7,-10, 28, 1, -2, 48, 7, 0,-10, 10, - 1, -9, 2, -1, 0, 3, -5, 5, -4, -2, 7, 7, 1, 3, 2, 5 }, - { -3, 3, -1, 3, -9, 0, -1, 3, 2, -6, 39,-14,-12, 5,-19, 21, - 7, -6, 4, -1, -4, 0, -4, 1, 0, -9, 1, 10, 0, -2, 0, 7 }, - { 4, 2,-29, 12, 5, -3, 16, -6, 15,-13, -4, -1,-13, 22,-16, 17, - 16, 4, 9, -4, 4, -6, -4, 11, -8, 7, 8, 4, 3, -3, -7,-13 }, - { 0, 3, 3, -6, -4, 0, 9, 0, 5, 0, 10, 10, 4,-13,-12, 16, - 23, -4,-12, -6, -4, 20, 2, 0, -4, 23, 1, 8, 11, -4, -5, 15 }, - { -6, 4,-15, -9, -1,-19, 12,-30,-17, -4, 1,-13,-13, 4, -3, 26, - 5,-25, 11,-14, -6,-13, 0, -7, 9, 2, 8, -1, -8, 1, -8, 13 }, - { 1, 6, 1, -4, -4, 1, 2, 0, -3, 2, 10, 6, -6, -2,-11, 4, - 32, 15, 15,-47, -8, 3,-12, 4, -5, 4, -1, 0, -5, 5, 1, -7 }, - { 2, -1, 0, 0, -1, -6, 0, -6, 4, -4, 5, 9, -5, 1, -3, 51, - 4, -5, 4,-14, -1, -4, -3, 1, -4, -1, 0, 2, -8, 0, 1, 2 }, - { 0, 4, -2, -7, -2, -9, 6, -8, 11, -3, -6, 3,-11, -8,-12, 8, - 11, 5, 19, 3,-24, 19,-14, 11, -5,-18, -8,-12, -5, -4, -1, 4 }, - { 16, 9, 10, 14,-18, -2,-18,-27, 10, -5, 12, 14, 4, 0, -2, -6, - -12, -7, -1, 3, 4, 7, 11, 10, 5, -5, -7,-16, -3, -6, 6, 9 }, - { 7, 15, -9, 10,-19, 4, -5,-37, -2, -4, 8, 2, 4, -1, 1, 9, - -5, -5,-12, 1, -1, -8, 3, -3, 4, 6, 9, 3, 3, -1, 2, 4 }, - { 13, 17, 3, 9, -7, -7,-15,-17, -8,-13, -4, -8, 19, 2, 16, 25, - 7, 15, 2, 16, -5, -6,-10, -9, -7, -6, -2, -7, 7, 2, 4, 5 }, - { 24, 7, 9, 8,-13, -2, 0, -4, 1,-13, 3, 6, 7, 10, -4, 15, - 5, 7, -4, 5, -5, 3, 13, -7, 5, 15,-11, -2, 7, 5, 8, 6 }, - { 17, 6,-15, 23, -2, -1, -6, -2, 0, -4, 11, -3, 12, 15, 6, -8, - -15, 10, -9, 7, -1,-11, 2, -8, -4, 3, 4,-10, 4, 4, 11, 1 }, - { 21, 12, -3, 6, -8, 8,-11, -8, -5, -5, 3, 7, -1, -5, 12, 15, - -10,-11, 3, 15, 8, 4, 2,-15, 0, 14, 1, -8, -1, 3, 10, -7 }, - { 16, 12, 5, 13, -6, 15,-23, 0,-17, -9, 0, 4, -9, 13, 6, 18, - 0, 0, -4, -1, 0, 14, 5, -1, 8, -4, -8, -6, 5, -2, -2, 0 }, - { 14, 16, -1, 12,-15, -9, -6,-20, 4, 6, 8, 9, 3, 1, -9, -4, - -1,-11, 9, 11,-12, 1,-14, -7, 2, -8, 11, 9, -4, 10, 4,-16 }, - { 13, 10, 3, 7, 0, -8,-33, -6, 4, -4, 19, -2, 14, 6, 5, 7, - 6, -3, -1,-10,-10, -9, 4, -3, 5, 9, 2, 2, 10, 9, -2, -3 }, - { 11, 10, 25, 18, -1, -6,-21,-21,-11,-16, 6, 5, 14, 4, 8, 7, - 0,-10, -7, -9, -5, -4, 3, -1, 1, 6, -1, 6, -2, 2, -3, -9 }, - { 15, 9, 5, 22,-17, 15, -9, 7, 7, -9, 13, 9, 10, -1, 8, -3, - -2, 6, 1, 17, 8,-14, 7, -3, 12, 9, 1, 0, 1, -5, 17,-18 }, - { 25, 19,-17, 12, -4,-10, 1,-13,-19, -7, -3, 9, 6, -2, 3, 1, - 4, -2,-11,-14, -1, -7, -5, -9, 7, -1, -3, 4, -5, 1, 0, -1 }, - { 20, 8, -3,-10,-24, 3, -6, -2, 0,-12, 14, 6, 7, 11, 4, 7, - -12, -5, -8,-10, 5, -1, -4, 4, 16, 7,-14, 6, -1, -2, -7,-11 }, - { 16, 18, 17, 1,-15, -6, -5, -3, -1,-19, 8, -2, 2, 8, 12,-19, - -12, 8, 0, -3, -1, -1, 4,-14, 9, -1,-12, -1, -7, 10, -3, 5 }, - { 18, 12, -7, 7, 0, -3,-13, 0, -1, -4, 9, -2, 6, -1, 0, 1, - 15,-21, 1, -8, 25,-19, 13, -9, 2, 12, 5, -7, -3, -1, -3, 1 }, - { 13, 16, -4, 9, -2, 2, -1,-19, -7, -4, 18, -6, 14, 18, -5, 4, - -6, -3,-19,-14, -1,-12, 10, 6, 7, 17,-12,-13,-10, -4, 5, 4 }, - { 27, 17, 4, 14, -9, -2, -4, -8, 0, -6, 14,-11, -7, 2, -3, -3, - -2, -3,-13, 12, 16, 1, -5, -9,-10,-11, -2, 3, -7, 5, 11, -7 }, - { 7, 17,-16, -2,-14,-28, -7, -8, 15,-10, 7, 15, 8, 17, 13, -1, - 4, -7,-12,-11, 0, 0, 2, 3, -3, 7, -6, 6, 1,-16, 1, -2 }, - { 23, 11, -9, 15,-23, -4, -6, -4, 2, -9, -7, 9, -8, 3,-13, -4, - 8, 18, -6, -2, 1, -5, 6,-14, -5, -2, -6, -5, -3, -2, 4, -5 }, - { 12, 13, 18, 18,-35, 2, 7,-17, 3,-11, 6, 9, -3, -2, 10, -4, - 3, 3, -2, -7, 0, 2, -4, 0, -4, 0, -6, 5, 10, 4, -3, -1 }, - { 19, 11, 1, 20,-14, 4, -9,-13, -2, 11, 0, 17, -1, -1, -1, -1, - -5, -8, 0, 5, -1, -8, 5, -1, 3, 2,-12, 21, -2,-24, 5, 7 }, - { 15, 15,-15, 17,-14,-22, 3, -4,-11, -3, -7, 1, 18, 10, 1, 10, - -6, -3, 8, 2, -7, 0, -2, 1, 1, 2, -9, -2, 1, 2, -3, 4 }, - { 45, 13, 8, 17, -5, 2,-16, 2, 8, -2, 8,-15, 4, 5, -1, 7, - -6, -2, -6, 2, -3, 0, 0, -9, -1, 7, 2, 3, -3, -3, -1, 5 }, - { 1, 18, -8, 18,-12,-10, 3, 4,-22,-12, 20, 8, -3, 9, 2, 10, - -10, -3, 9, 3, 6, -3, 10, -1, -3, 2, -2, 4, 2, 3, -3,-18 }, - { 9, 10, -5, 9,-35,-21,-18,-16, -1,-12, -6, -7,-15,-19, 12, 4, - 4, 9, -7, 2, 14, 1, 4, 0, -1, 6, -7, 2, 1, 1, -4, 4 }, - { 31, 8,-17, 35, -8, 1, -5, -6, -7, -6, 10, -2, -3, 6, 9, 3, - -6, -2, 3, 3, 5, -3, 0, 6, 0, 1, -5, -3, -2, -4, -1, 0 }, - { 18, 4, -8, 7, -8,-15, -1,-16, 12, 18, 3, 19, 2, 4, 8, 8, - 0, -5, -8,-12, 10, -5, 0, 1, 0, 4, -3, 16, 11, 11, -2, -6 }, - { 27, 15,-17,-10,-23,-22, -1,-14, -4, -7, 20, -2, -7, 6, 15, -5, - 32, 4, 9,-11, -3, -8, 11, -4, -1, -4, -8, -6, -4, -5, -2, -7 }, - { 22, 4, -7, 2,-15,-11,-17,-10, 2, 0, 15, 11, 7, 12, -8, 6, - -10,-18, -6,-12, 7, 3, 22, 3, -7, 14, -5, -2,-13, -7, -1, -7 }, - { 18, 13, 9, 24, -4,-19, -9,-11, 13, 8, 2, 4, -1, 8, 14, 10, - -12, 0, 0, 5, 10, 5, 4, -1, 5, 1, -1, 11, 2, -4, 0, -9 }, - { 15, 19, -5, 1, -4,-10, -8,-27, 6, 8, 5, 10, 4, 11, 5, -5, - -11, 0,-11,-14, -4, -9, -8, -8, 6, -9, 4, -5, -1, 1, 5, -4 }, - { 18, 1,-13, 14,-14, 9,-15, -7, 12, 1, 13, -4,-20, 12, 10, 12, - -12, 7, 1,-13, 10, -6, 5, -3, 4, 8, 10,-13, -3, -6, 9, -3 }, - { 19,-14, 5, -8, -6, 2, -5, 5, -3, -1,-28, 11, 18, -6, -4, -2, - 11, 14,-43,-42, 9, 2, 20,-23, 6, 32, 0, 5, 0, 6, 9, 5 }, - { 8, 11,-14, -1, 7, 12, -7, 2,-16, 2, 10, -3, -1, -7, -7, -1, - 1,-10,-60,-23,-18, 42,-13, 9, 18,-11, 0, 1, 0, 2, -5, 1 }, - { -5, -1, 2, 0, 3, -3, 3, -2, -6, 0, -3, -3, 7, 2, 0, -2, - -2, 3,-34,-15, 37, 47, 10, 20, 9, 1, 3,-21,-25,-33,-14, 8 }, - { 5, 6, 2, -2, -2, -2, 6, 5, -5, 7, -3, 1, -5,-13, 9, 3, - -17,-19, -2,-79,-12, -7, -8, -6, -2, -2, -1, -1, -7,-13, 6, -1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, - 0, 3, 4,-87, 6,-11, 16, -9, -1, 8, 0, 5, 0, 1, 2, 1 }, - { -5, 6, 2,-24, 5, -9, -7, 0, 7, 3, -3, 16,-14,-16, 0, 18, - 15, -9,-14,-28,-17, 53, 14, -6,-28, -1, -3,-10, -7,-14, 19,-15 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, - -13, 0,-53, 3,-22, 63, 19, 16, 1,-11, 0, -3, 0, -3, 0, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, - -1, -6,-43,-43, -2, 65,-13, -4, 9, 1, 1, 2, 1, 0, 0, 1 }, - { 0, 1, 0, 0, -1, 0, 1, 1, 0, 0, 1, 2, -1, -1, -3, -1, - -23, 1,-61,-55, 3,-28, -6, -4, -4, 8, 2, 1, 1, -1, 0, 0 }, - { 0, 1, -1, 1, -1, 0, -1, 0, 1, -1, 0, 1, -1, 0, -9, -4, - -48,-19,-52,-46, 11,-12, 5,-14, 0,-10, 0, 0, -1, -2, -1, 0 }, - { 0, -3, -1, -4, 2, -1, -7, 3, 1, 3, -1, 1, -3, 0, -7, 0, - 3, -7,-61,-51, -4,-21,-16,-21,-11, 14, -7, 8, 3, -5, 1, 2 }, - { 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 9, -3, - 56,-11, -6,-67, -1, 13, 0, 7, 1, -9, -1, -1, 0, 0, 1, 0 }, - { 14, 9, -2, 14,-10,-10, 9, -5, 1, -8,-23, 30, 8, -7, 23, 8, - 2, 10, -1,-27,-17, 57, 22, 4, -5, 2,-12, -6, 2, -7, -4, -9 }, - { 1, 5, 12, -2, -2, -3, 2, -3, 6, 0, 4, -2, -8, -6, 0, 16, - -15, 29,-55,-29,-24, 29, 3, 10, 6, 13, 10, -5, 21, 11,-14, 5 }, - { 4, 2, 26, -6, 10, 11,-23,-10,-27,-20, 3,-24,-11,-10,-13, 25, - -10, 5, -9,-36, -7, 43, 3,-13, 6, 13, -2, 0, 1, 3, -3, -4 }, - { -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, 0, -1, 1, - -12, 12,-26,-64,-15, 29, 37, -7, -3,-12, -5, 14, 8, -8,-10, -2 }, - { 19, -4,-11,-16, 8, 14, 5, 19, 3, 22,-11,-21, -1, -6,-11, 11, - 10,-24,-23,-40, -8, 20, 17, 5, 13, -6, 3, 14,-20, -8, 3, 28 }, - { 2,-12, 10,-14,-18, 26,-22, 4, -2, 5,-21, 8, 3, 1, 19, 0, - -12, 24,-14,-40, 15, 29,-15, 6, 15, 1,-19, 2, 4, 7,-12, -3 }, - { 0, 17, 13, 7, -5,-11, 2,-19, 3, 38,-21, -3, -6, -4, 7, 1, - 1, -5,-40,-10, -2, 35, 8, 8,-10, -8, -9, 33, 4, 4, 0, -2 }, - { -2,-12, 7, 29,-24, 2, 16, -1, -7, 16, 10, -2, -2, -2, 13, -2, - -37, 15,-22,-40,-11, 33, 10, -1, 8, 10, 6, 8, 9, 0,-12, 2 }, - { 15, -8, -9, -2, 7,-17, 7, 19, 14, 4, 12, 27, 11, 10, 4, 11, - -15, 14,-13,-48, 5, 18, 0, -9,-36,-11, 2, 4, 5, 5,-15,-12 }, - {-12, 0, 3, 4, 7, -5, 5,-14,-24,-18, -6,-15, -8,-20, 1, -7, - -33,-28,-40,-38,-18,-10, -5, 17,-12, 4, 3, -5, 5,-13, 4, -7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, - -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, - -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, - -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, - -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, - { -8, 2, 1, 22,-31, -6,-25, -3, -3, 1,-15,-11, -2, -3, 4,-13, - -9, 15,-18, 37, -7,-37, 12,-13,-11,-25,-10,-11,-22, 7, 16, 7 }, - { 14, 10, 4,-10, -1, -5, -7, -3, 16, 13, -5,-15, 5, 11, -1, 8, - -27, 7,-12, 49, 17,-22, 9, -2, -9, -1, 2,-15, -1, 41,-18,-17 }, - { -4, -9,-15, -3, 3, 4, 4, 2, 7, -3, -7, -8, -5, 17,-19, -7, - 36, -9,-38, 17, 1,-48, 11,-18,-13, -2, -8, 4,-10, -5, 21, 11 }, - { 15,-13, 4, 2, 1, -5, -2, 1,-10, 7, -1, 3, -6, 0, 11,-11, - 8, 20,-17, 51,-17,-41, 2, 15, 4, 8, -2, 16,-32, -1, 17, 6 }, - { -8, 8,-18, -5, 4, 6, -3, 8, 0, -4, 2, 0, -1, -4, 5, 8, - 30, 30, -8, 70, 2, 8, 2, 0, 7, 1, 13, -1, -6, -7,-11, 2 }, - { -8, -7, 9,-10,-13, 6,-11,-14, 13, 25,-26, 5, 2, -5, -5, 5, - -8, 4, 0, 33, 12,-38, -4, 6, 13, 6, 25, 34, -1, 25,-19, -5 }, - { 18, 3,-17, 4, -8, 7, 20, 1, -1, 5, -5, -2, -8, 8,-35, 15, - 24, 43, -5, 51, 5,-12, -3, 1, -2, 3, -3, -3, -9, 8, -9, 2 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 2, 10, 24, 76, -2,-22, 11, -1, 4, 33, 4, 1, -1, 1, 2, 0 }, - { 0, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 0, - 24, 13, 32, 70, 26, 5,-21, -9, -6,-15, 2, -2, 2, 4, 1, 1 }, - { 5, -4,-11, 4, -4, 22, 10, -2, 13,-11, -4,-21,-17, 0, -7, 4, - 10,-34, 11, 52, 2,-46, -5, 0, 0, -1, 2, 4, -9, 1, 1, -7 }, - { 0, 1, 1, 0, -1, 0, 1, 0, 1, 1, 0, 1, 0, 0, -3, 1, - -8, 9, -1, 64,-13,-61, -3, 3, -5, 10, 1, 3, -1, -1, -1, -1 }, - { 0, 1, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, - 10, -2,-31, 79,-10, 27, 0, -1, 3, 8, 1, 1, 0, -1, 0, -1 }, - { 3, 12, 10, 26,-19, 10, -9, 6, -4,-15, 10, 3,-16, 6, 11,-19, - 3, 10, 18, 44, 5,-30, 5, -9, 21, 4, 20, 10, 14,-25, 8,-17 }, - { 0, 0, 0, 1, -1, 0, -1, 0, 1, 0, 1, 1, 0, 0, -6, -2, - 8, -8, 13, 69, 26,-19,-25,-17, 16, 6,-12, 22, 2, -6, 9, 5 }, - { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, - -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, - { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, - -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, - { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, - -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, - { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, - 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, - { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, - 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, - { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, - -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, - 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, - { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, - -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, - { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, - -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, - { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, - -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, - { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, - 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, - { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, - 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, - { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, - -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, - 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, - { 16,-18, 7, -4, 31,-15, -9,-13, 20,-12, -6, 0, 12, -6, -2, 4, - 3, -3, -1, 0, 1, 3, 3, -2, 1, 6, 4, 0, -3, 2, -5, 1 }, - { 38, -5,-13, -4, 8,-15, 11, 1, 2, -4, -1, 9, 13, 4,-12, -7, - 0, -2, 7, 2, -6, -2, -3, -2, 3, -4, 6, 15, 1, 1,-11, -2 }, - { 47,-22, 9,-26, 3, -5, 2, -7, 4, -2, 2, -2, 3, 0, 3, -4, - 3, -3, 2, -3, 7, -3, -1, 1, 1, -5, 5, 0, 2, -5, -3, -2 }, - { 14,-16, 2, -6, 7, -2, -7, -4, -4, -7, 14, -3, 7,-19,-14,-17, - -29, 6, 26, 16, -5, 13, -4, -1, 21, 14, 1, 3, -6, 0, -7, -1 }, - { 29,-11, 5, -3, 4, 11, 4,-10, 1,-22, -3,-10, 5, 4, 2, 8, - -2, -7,-12,-12, -8, -3,-18, -2, -9, -5, -1, -3, 2,-14,-14, 7 }, - { 28,-12, 5, 3, 9, -7, 0, -2, 2, 1, 4, 0, -7, -3, -2, 4, - 4, 14, 8, -1, -4, 14, -7, 17, -2, -2, -9, 2, 19, -7, 9, -8 }, - { 31,-18,-22, 8, 15, -5,-10,-15, 1, 10, 6, 7, 6, -8, 2, -1, - 12, -3, 3, -1, 1, 5, -6, -4, 0, 1, 7,-10, -2, 4, -3, -4 }, - { 53,-30, -4, 12, 2, 3, -3, -3, 0, 1, 6, 5, -5, -4, -7, 1, - 0, 2, 1, 3, 1, 5, 0, 2, 2, -1, 0, 4, 2, 0, -2, 0 }, - { 27,-18, -3, -2, 4, -8, 3, -2,-11, 2, 10, -8, -8, -4, 0, -2, - 8, 0, 9, 0,-16, 11, 1, -6, 13, -3,-10,-13,-15, 25, 1, 0 }, - { 35, -5, -1, -8, 23, 11,-14, -3, 2, -2, 8, -6, 17, -2, 7, 0, - -2, 10,-17, 13, -2, -2, 11, 11,-14, 2, -2, -3, -8, -1,-12, -5 }, - { 29, -9, 7, 3, 2,-10, 0, 3, 9, 0, -3, 5, 1,-10, 10, -5, - 3, 6,-20, -9, -6, -4, 1, 0, 12, 17, -8, 9, 3, -1, -9, 0 }, - { 15,-16, 18,-19, 16,-15, 17,-18, 13,-16, 17,-14, 15, -9, 13,-17, - 9, -7, 4, -5, 3, -4, -3, 0, -6, 7, -9, 7, -2, 7, -9, 9 }, - { 21,-10, 7, -2, 12, -7, 13,-17, 11, -2, 20, 3, 5,-11, -6, -6, - -15, 0, -9, 5,-11, 7, -1, 7, 8,-10, -9, 3, -5, 9, -8, -2 }, - { 23,-22, 15, -5, 16, -4, -3,-12, 9, 3, -1, -2, -8, 2, -2,-16, - 3, 4, -2, -6, -7, 12, -8, 2,-14, 2, -7, 11, -2, 6, -4, -1 }, - { 34,-17, -4, 8, 4, -6, 1, 8, 4, 16, 3, 6, 12, -1, -1,-15, - 6, 4, -7, -6, 6, 0, 2, 1, -2, 2, 3, 3, -3, -2, 8, -6 }, - { 18,-18, 2, -2, 10, 1, 18,-23, -3,-10, 0, 4, 20,-19, -3, -4, - 2, 8, 6, 1, -3, 1, 1, 3, 5, -1,-11, 3, -7, 5, -1, 1 }, - { 15,-14, 2, 3, 10, -8, 12,-13, 13,-15, 6, -8, -4,-10, 14, -9, - 24, 2, -7,-18, 13,-11, 8, 14, -6, -2, 3, -1, -4, 7, -7, -4 }, - { 20,-12, 13, 5, -1,-10, 15, -6, 8, -1, -3,-10, 17, 0, -6,-19, - 2, -1, 8, -3,-16, 0, -3, 2, -2, 0, 8, -9, 0, 1,-10, -9 }, - { 32, 0, -9, -5, -1, 5, 13,-11, 8, 3, 11,-11, 0, -8, -2,-14, - 7, 10, 6, -5, 1, 10, 2, 12,-10, 4, 4, 6, 4, 0, -7,-10 }, - { 16,-14, 10, -7, 11,-11, 11,-11, 18,-13, 8,-15, 16,-11, 13, -9, - 8, -7, 12,-11, 7, -6, 3, -5, 9, -5, 4, -1, 7, -4, 8, -3 }, - { 24,-27, -1, 5, 8, -5, 12, 7, 4, -3, 3, -1, -9,-11,-13, -5, - 10, 0,-13, 7, 1, -5, 4, -9, 7, -3, 13, 2, -5, -3,-17, -2 }, - { 23,-19, 15, 1,-10,-18,-12, -6, 8, -3, 12, 0,-12,-10, -4, -4, - 8,-10, 4, 2, -2, -8, 13, -3, -2, -6, 2, -3, 5, -2, 2, 11 }, - { 25,-12, 4, 2, 24, -3, 3, -6, 14, 11, 0,-21, -3, -3, 1, -8, - 7, 0, 0, 3, 3, -6, -7, 6, 2, 1, -4, 5, -1, 10, -2, 9 }, - { 24, -8, -6, 7, 16,-12, 13, -1, 11,-21, 2, -6, 3,-12, 0, 9, - 4, 11, -7, 1, 4, 1, -8, 3, 3, -6, 3, 3, 0, -8, 8, 4 }, - { 25,-21, 13, 14, 13,-18, 4, -3, 0, -5, -4, 5, -3, 0, 4, 12, - 7, 3, 5, -5, 2, -2, 3,-10, 2, -9,-15, 6, 1, 7, -5, 1 }, - { 23,-16, -2, 10, 4, -1, 3, 1, 32, 3, -5, -2, 9, 10, -1, -4, - -6, 2, 9, -1, 14, 12, -6, -1,-17, -2, -4, -9, -7, -6, -8, 3 }, - { 50, -8, 5, 2,-11, 10, 0, 0, 6, -3, 7, 0, -3, -2, -3, 0, - 6, -4, 2, -5, -9, 0, 3, 10, 1, -7, -2, -3, -6, -9, 1, -2 }, - { 28,-17, 0, -2, 2, -9, 1, 5, -4, -1, 0, 0, 19,-27, 5,-12, - 7,-14, -3, -6, 10, -2, -4, -2, 4, -5, -2, -7, 1, 7, -9, 4 }, - { 22,-19, -6, -6, 3,-22, 3, 5, 20, -8,-14, -5, 1, 1, 20, 2, - 16, 6, 3, 14, 4, 3, 5, 1, 5, -7,-10, -6, 3, -6, 1,-14 }, - { 29,-14, -8, 13, 8,-10, -6, 4, 4, -6, 5, -7, 1, 12, 14, 11, - -7, 1, 2, -9,-11, -9, 0, 4, -1, 7, 10, 4, 4, 20, -1,-11 }, - { 18, -9, 4, 1, 7,-29, 12, 1, -1, -9, -2, -1, -2, 2, 9, -8, - -13, 5, 4,-13, -4, 2, -5, -7, -6, 14,-10,-34, -3, 1, -3,-13 }, - { 38, -9, 24, 8, 11, 4, -6,-11, -2,-12, 1, 1,-11, -8, -5, -2, - -15, -8, 8, 0, 1, -7, 5, 4, -1, 8, -2, 11, -3, -1, -5, -5 }, - {-20, 11, -4, 24,-11, 1, 15, 4, 0,-28,-10, -1, 10, 10, -6, 5, - -6, 2, 7, -2, 1, -2, -6, -3, -7, 1, 2, 12, -1, 7, 0, -2 }, - { -9, 10,-23, 27, -4,-17, 20, -6, 14,-17, 5, -1, 5, -9, -7, 5, - -6, 4, -2, 9, 0, 8, 0, 1, -3, -3, -5, -8, 5, -2, -2, 12 }, - {-10, 19, 4, 9, 1,-16, 17, -2, 9,-29,-16,-11, -4, 7, -5, 4, - -1, -3, 3, 2, 3, -4, 5,-12, -2, 6, 5, -4, 4, 1, 4, 10 }, - {-20, 10,-24, 14, -5, 11, 9, 0, 16,-20, 10, -5, -6, -6, -1, 2, - -4, 5,-16, 8, -2, 5, 5,-11, 9,-11, 4,-11, -1, -1, 4, 3 }, - { -9, 11, 3, 19, 24, 4, 5,-14, 30,-17, -4, -2,-17, 7, 2, 3, - 1, 3, -7, -4, 2, -3, 1, 4, -1, -1, 3,-12, -2, 3, -3, 10 }, - {-19, 18, 11, 19, 19, 19, 10, 4, 13, 6, 5, 4, 8, 3, -2, 12, - -6, -2, 7, -6, 15, 12, 16, 16, 18, -3, -4,-20, 0, 10, -9, -3 }, - {-21, 9, 20, 12, 0, -3, 5, -9, 15,-13, 5, -5, -6, 24, 2, 9, - -5, 2, -7, 2, 5, 7, -5, 2, 15, 3, 1, -1, -4, -2, 7, 0 }, - {-18, 16, 13, 15, 2,-10, 14,-11, 4,-11, 5, 12, 12, 20, 8, 30, - 2, 11, -9, 7, 0, -3,-16, -5, -6, 5, -4,-21, 0, 5, 6, 1 }, - {-26, 8,-13, 9, 6,-10, 2,-11, 7, -4, 6,-19,-11, -6,-12, 16, - 0, 5, -7, 8, 5, 6, 17, -9, 10,-10, 5, -3,-11, 2, 4, 10 }, - {-11, 17, -3, 22, -5, 18, 3, 1, 4, -5, 14,-27, 5, -7, -4, -5, - -10, 11, 1, 15, 1, 1, -6, -5, 10,-22, -7, -7,-15, 13, -4, 5 }, - {-17, 14, -7, 13, 3, 0, 13, -6, 9,-14,-22, -1, 1, 19, 14, -3, - 4,-13,-13, 2, -4, 8, -2, -2, 13,-12, 13,-12, -7, -5, -3, 6 }, - {-17, 17, -1, 33, 6, 3, 9,-16, 3,-14, -8, 6,-17, 8, 3, 13, - 8, -6, 3, 1, -2, 0, -2, 8, 4, 9, 13,-10, 4,-17, 0, -6 }, - {-20, 7, 7, 21, 1, -3, 7, -3, -2,-12, 9, -7, 2, -3, 14, 1, - -1, -7, 12,-10, 5,-20, 11, -2, 0,-24,-17, 6, 6, -4, 3, -1 }, - { -8, 10, 6, 7, -1, -6, 28, -6, 10,-33, 1,-20, 0,-12, 10, 1, - -6, 8, -3, -1,-10, 8, 5, 0, 10, -2, 8, 16, -5, -3, -7, 4 }, - {-17, 13, 3, 15, 1, -5, 27, -5, 6, -6, 12, 2, -4, 8, -1, -3, - -2, 12,-15, 3, 4, 1, 2, -9, 0,-16,-21, 2, -4, 16, -7, 4 }, - {-15, 20, 8, 17, 5,-14, 15,-11, 21,-11, 13,-13, 2,-15,-13, 1, - -5, 5, 2, 10, -9, 4, -1, 3, 2, -4, 13, -5, 1, -4, 5, -3 }, - {-21, 8, 2, 16, -1, 2, 15,-16, 13,-12,-12, -7, -8, 2, -7, 11, - -8, 5, 2, -7, 16, -4, 1, -7, 3,-15, 6, -5, -8, 2, -8, 5 }, - {-15, 17, -6, 3, -3, 3, 9, -7, 14,-23, 11, 1, -1, 4, 7, 6, - -1,-14, 7, 6, -8, 5, 1,-15, 10, -9, 2, -3, -1, 4,-10, -4 }, - {-10, 18, 3, 11, 1, 4, 14,-14, 7, -4, 15,-10, 10,-11, 10, -4, - 5,-14, 10, 4, 15,-12, 15,-13, 20,-15, 14,-15, 8,-11, 4, -6 }, - { -7, 23, 2, 20, 7, 8, 19, -5, 9,-16, -8,-17, -5, 1, 5, -6, - -8, 1, -6, -4, 10, 6, 6, 2,-11, -4, 0, 2, 4, 7, 9, -4 }, - {-15, 20, -5, 22, 11, -8, 9, -5, 10,-13, -8, 8, 2, -2, -3, 7, - 6, 10, 1, 2, -5, -9, 1, 10, 16,-22, -7, 0, 7, 7, 6, 1 }, - {-26, 19, -5, 3, 5, 25, 18, -5, 9,-14, -8, -6, -2, -6, 2, 3, - -8, -2, -7, 7, -3, 7, 3, 4, -8, 0, 1, -8, -4, -2, -2, 1 }, - {-20, 14,-10, 6, -3, 7, 8,-32, -2, -7, -2,-10, 16,-12, -9, 15, - -2, -5, -6, 2, -7, 5, 9, 1, 6, -7, -1, 0, -2, -4, -7, 3 }, - {-14, 16, 4, 11, -8, 1, 23, -4, 17,-13,-10, 1, 12, 9, 12, -4, - 7, -1, -1, 5, -8, -6, 3, 3, -6, -3,-18, 0, 18, 20, 4, -2 }, - {-33, 19,-10, 30, 15, 2, -3, -1, -4,-14, 7, -7, -1, 7, -8, 9, - -1, -3, -5, 2, 2, 4, 0, 5, 0, 0, 2, 3, 3, -3, -3, 4 }, - { -6, 20, 0, 5, 17,-10, 18,-17, 9,-16, 4,-13, -6, 2,-14, 14, - -28, 9,-12, 25, -4, 7, 7, -8, 6, -6, -2,-10, 2,-11, -1, 2 }, - {-12, 14, 12, 52, -3, 5, -5, 4, 8,-13, 2, -5, -4, 2, -2, -1, - -2, 3, 3, 5, 2, 3, 0, 1, -5, 2, -4, -3, 1, -5, -2, 0 }, - {-13, 6, 9, 24, 0, 8, 14,-15, 18, -9,-11, -8, 3, 15, -2, -4, - -9, 4, -3, 12, 14,-13, 11, -4, 2, -4, 0, -6, -6, -6,-14, -1 }, - {-10, 28, 3, 12, 9, 3, 11,-28, 6,-11, -7, 4, 0, 7, 8, -9, - 0, -6, 0,-16, 4, 7, 4, 4, 7, 3, 4, -7, 0, -3,-10, 6 }, - {-11, 14, -2, 19, -1, -1, 7, 9, -2,-27, 10,-14, 15, -4, 12, -4, - 2, -2, -6, 12, -6, 0, -5, -4, -5, 1, 3,-11, 5, -9, 3, -8 }, - {-18, 7, 13, 16, -4, 3, 9,-10, 10,-10, -3,-22, -4,-12, 3,-16, - 0, -3,-16, 8,-11, 1, 10, -7, 15, 3, 0, -1,-13, 8, 1, 6 }, - {-20, 10,-10, 10, 8, -1, 6, 0, 16,-12, 9,-10, -1, -5, -4,-13, - 13, 16, -8, 12, -2, 14, 18, 13, 0,-16, 2, -5, -5, -5, -4, 3 }, - {-14, 5, -7,-17, 5,-13, 23, 20, -4, -1, 1, -6, 13, 5, -1, 4, - -14, -2, -7, 8, 3, 2, 2, -7, 2, -1, 4, 7, 3, -9, -1, -5 }, - {-19, 3,-24,-28, -9, -7, 19, 3, 2, 19, 7, 5,-13, 8,-15,-17, - 3,-11, 4, 13, 3, 2, -1, -3, -4, -4, 2, 0, -5, -6, 6, 2 }, - {-17, 18,-30,-20, -2, -3, 1, 15, -1,-11, 6, -4, 11, 11, -4, -5, - -10, 0, 0, 1, 3, -7, 8, 2, 5, 1, 5, -5, 1, 6, 4, 1 }, - { -6, 1,-30,-25, -1, -8, -2, -9,-17, 16, 3, -1, -2, -9, -6, -7, - -3, 12, 6, -4,-10, 0, 10, -8, -6, -5, -3,-11, -4, 0, -1, -3 }, - { -1, -1,-34,-28, 1,-10, 2, 9, 4, 16, 2, 6, 14, 17, 0, 7, - -4, 4, 4, 4, 0, 1, -1, -5, 8, 1, -4, 1, -9, -2, 5, 6 }, - {-11, 14, 1,-31, -7,-24, 9, 7, 6, 5,-13, 1, -1, 3, 4, -1, - -2, -8, -6, 3, 5, -4, -6, 7, -2, 5, 3, 3, 0, 0, -5, 2 }, - {-25, 8,-11,-18, 1, -4, 8, -3, -4, 15, 6, -5, 8, 2, 3, 4, - -4, 5, 6, 8, -7, 6, 1,-11,-15,-13, 9, -4,-14, 10, 12, 7 }, - {-20, 11,-15,-25, 3, 4, 18, 13, -4, -5, -9, -1, -5, -2, -2, -7, - 16, 5, -4, -5, -7, -2, -3, -9, 11, -2, 0, -7,-17, -6,-11, 6 }, - {-11, 18, -5,-20,-15, -3, 9, 11,-20, 12, 5, 5, 11, -3, 7, 1, - 10, -6, -3, -3, 3, 3, 14, -7, 10,-17, 9,-11, -2, -6, 7,-12 }, - {-20, 8,-14,-17, -9,-13, -3, 0,-27,-14, -3,-14, 4, 3, 6, -6, - 7, 4, 23, 9, 11, 9, 3, -4, 9, 2, 4, -1, -6, 1, -8,-11 }, - { -9, 14, 2,-37, -7, 13, 6,-11, -6, 9, 18,-11, -6, 2, 12, 4, - -1, 3, 1, -2, -2, 1, -9, -4, -2, -3, 3, 5, -6, 0, -2, -8 }, - {-29, 8, -1,-13, -2, 8, 23, 2,-10, 7, 13, -6, -5, 11, 13, 0, - -10,-13, 11,-12,-10, 6, 4, 6, 4, 3, 6, -5, -9, -2, -1, 3 }, - {-18, 6,-10,-55, -4,-11, -2, 0, 1, -3, -9, -6, 3, -2, -1, 6, - 3, -1, 3, 1, -4, -7, -2, 6, 3, -2, -1, -3, -2, 0, 4, 1 }, - {-14, 5, 3,-21, -8,-16, -4, -2,-11, 27, 15,-20, 3, 0, 1, 1, - 2, -5, -5, 4, 1, -9, 5, -3, 3, 0, -4, -2,-11, -4, -3, 7 }, - {-17, -1, -9,-17, -8,-18, 12,-13, -9, 13, -3, 3, 3, -3, 1, -2, - 0, 16, -9, 6, 12, 9, 5, 11, 2,-15, 1, -4,-16, 7, -4,-12 }, - {-18, 8, -6,-11, -8, -7, 13, 7, 1, 6, 8, -1, 21, -4, 14, 15, - 18, -4, -3, 15, 0, 9, 4, 7, 3, -1, 9, -2, 0, 7, -8, 2 }, - {-10, 7,-18,-29, 3, 12, 12, 9, 11, 4, -1,-15, 1, -1, 8, -2, - -2, 10,-15, -1, 0, 6, 12, -6, -1, 10, -6, -3,-11, -4, 9, -6 }, - {-14, 14, -9,-21,-12, -2, -1, -7, -5,-10, 5, -8, 0, 6, 9,-11, - 11, -3, -5, 3, 8, 15, -2, -4,-22, 4, -6, 12, 2, 13, 6, -7 }, - {-12, 11, -5,-29,-25, 4, 12,-13,-11, -7, 4, 2, 2, -5, 5, 8, - 7, -5, -5, 6, 3,-10, 1, -6, 6, -6, -5, -1, -2, -4, 7, 6 }, - {-15, 11, -5,-16, 0,-13, 26,-23, -6, -3, 5, -2, -2, 21, -6, -3, - -5, -1, 6, -1, 0,-13, 2, -3, -9, -1, -4, -3, 5, -4, 12,-16 }, - { -9, 9, -1,-17, -3, -6, 12, 6,-18, -2, 11,-14, -6, 3, 14,-12, - -11, -5, 14, 2, 5, -8, -4,-11, 2, -5, 16, 6, -7, -4, 8, 13 }, - {-13, 5, 3,-28,-14, 0, 6, 23, 5, 4, -1,-17, 1, -3, 0, 0, - 5, 4, 0,-18, 14, 10, 4, 2, 5, -2, 4, -3, 2, 0, 2, 0 }, - {-15, 4,-13,-16, -3,-12, -2, 2, 7, 10, 9, 3, 11, 4, 23, 14, - 9, 16, 4, 1,-12, -3, 4, -7,-15, -7,-10,-14, -6, -8, -1, -6 }, - { -7, 10, -5,-10, -3,-13, 16, -1,-12, 7, -3,-12, 2, 13, 13, 2, - 17, 15,-13, 1, -5, -2, 3, -1, 1, -3, 6, -3,-12,-16, 7, -7 }, - {-11, -5,-12,-30, -6,-22, 1, 4, -6, -3, 12, 6, 7, 0, 16, 6, - -2, 0,-22, -2, -9, 2,-13, 8, 6, -8, 4, -7, -1, -6, 4, 6 }, - {-14, 5, 1,-27, -4, 2, 1, 14,-11, -7, -8, -4, 1, 8, 0, -6, - -13, 11,-12, -7, -5, 1, 10, 7, 3, -2, 0, 6, -8, 2, 10, -1 }, - {-10, 10,-25,-13,-20, -4, 19, 3, 13, 5, 5, 7, -8, 2, 4, 2, - 3, -1, -1, -9, 14, 10, 9, 14, 3, 3, -6, 0, -5, 4, 1, -1 }, - { -9, 15,-18,-17, 4,-11, 6, 7,-12, 8, -1,-11, 2, 3, 7, 16, - -3, -9, 7,-12, 23, 0, 6, 7,-14, -9, 8, 1, -2, 6, -2, -1 }, - { -6, 9,-16,-26,-14,-11, 9, -6, 5, -2, 13, 17, 21, 7, 18,-19, - 6,-23, -2,-15, -2, 2,-10, -8, 2, 1, -2, 4, -3, -4, -5, -4 }, - { 0, 6, -5,-28,-17,-32, 2,-10, 11, 3, -5, 9, 10, 3, 11, 11, - -3, 12, -2, 2, 4, -6, 9, -4, -4, -4, -4, -9, 2, 0, 2, 4 }, - { 0, -8,-18,-34, -9, -7, -4,-11, 10, 15, 11, -1, -8, 15, 6,-13, - 9, 2, -4,-12, 0, -1, 19, 12, 6, 5, 0, -3,-10,-12, 3, -5 }, - {-10, 6, -9,-17,-12,-11, 9, -6, 11, 11, 18, -7, 0, 16, 4, 2, - -6, 3,-12, -1, 0, 1, -5,-22, -2,-12, 0, 6, 17, 5, 5, 6 }, - { 12, -5, 7, 1, -5, -2, -1, 2, 2, -4, -3, -3, -3, -2,-29, 11, - 5,-13,-73, 24, 12, 4,-14,-10, 5, 1, 0,-11, -7, -7, 7, 3 }, - { 10, -3, -1, -3, 4,-11, -5, -2, -8, 7, 9, 2, -8, -6, 6, 7, - 21, 17,-54, 47,-14,-10, 14, 19, 13, 21, -4, 3, 1, 2, -4, 2 }, - {-12, 4,-16,-12, 5, -9, -4, 19, -7,-22,-22,-17, 3, 0, -6, 8, - 23, -4,-55,-28, 2,-26, 2, 1, 4, 0,-13, 6, 0, 10, -7,-11 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, - 35, -1,-67,-35,-24,-24, -6, 2, 2, -2, 1, 3, 2, 0, -1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, - 41, -4,-73,-15, 18, 4, 17, 8, -1,-16, -1, -2, 1, 0, 0, 0 }, - { -4, -4, 4, 6, -1, 2,-16,-10,-15,-10, 21, -2, -6, -2, 14, -7, - 10, -5,-55, 34,-12, 11,-13, -2, 2, 28,-26, 0, 7, 4, 21, -7 }, - { 2, 1, 15,-22, 10, -3, 14, -6, -2, 15, -2, -7, 20, 6,-15, -7, - 23, 10,-60, 8, -4, 29,-22, 2,-13, 9,-10, 12, -1, -3, 4, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -2, 11, -5, - -21,-11,-60,-27,-17,-39, 6, 36, 0, -8, 2, 2, 0, 0, -2, 3 }, - { 2, -5, 9,-17, -1, 2, -3, -6, 8, 12, 7, -6,-33,-11,-14,-40, - 10, 36,-46, 0,-19, 5, 0,-10, 3, 12, -6, -8, 6,-12, -7, 1 }, - { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -2, 0, - 4, -2,-87, -3, -2, 2, -2, 20, 2, 6, -1, 6, 0, 0, 2, -1 }, - { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, - 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, - { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, - -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, - { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, - -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, - { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, - 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, - { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, - -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, - 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, - { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, - 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, - { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, - -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, - { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, - 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, - -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, - -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, - 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, - { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, - -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, - { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, - -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, - { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, - 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, - { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, - -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, - 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, - { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, - 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, - { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, - -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, - { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, - 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, - -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, - -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 16, 65, -2, -2, 4, 3, 0, -7, 3, 1, 3, 1, 0, 5, 1, -5, - 0, 2, -1, 3, 0, 0, -1, -2, 6, 0, -2, 0, 0, -1, 1, 1 }, - { 5, 37, -4, 8, -4, -1, 9, 17, 6, -7, 5, -1, 11, 6, -4, 7, - -2, 4, 1, -3, 11, 3, 3, -9, 6, 0, -2, -4, -5, 4,-12,-11 }, - { 15, 24,-14, 2, 6, 17, 26, 5, 8, 11, -9, -7, -6, -8, 3, -5, - 9, 10, -3, 10, 0, 1, 4, -9, 4, 9, 3, 0, 4, 0, -5, 3 }, - { 9, 36, -9, -8, 7, 7, 4, 3, -1,-16, -2, 7, -5, -6, 6, 12, - -11,-12, 9, -1, -3, -9, 12, 6, -6, 2, 2, 5, 0, 5, 6, -6 }, - { 25, 39, -5, 24, 3, 10, 3, -6, 13, -8, 3, -7, 2,-10, -5, 2, - -2, 3, 5, -2, 1, 5, -2, 3, -4, 1, -5, -4, 0, 1, -2, 0 }, - { 16, 27, -1, 0,-14, 6, 4, -5, 7, -2, -6, 0, -3, -5, 2, -1, - -1,-19, 5, -8, 0, 11, 12, 5, 0, 3, 10, 6,-14, 14,-13,-15 }, - { 12, 23,-14, 2, 1, 4, -3, 16, 7, -8, 2, -8, 8, 6, -8, -7, - -3, 0, 2, 8,-13, 7, 13, -6, -4, 6,-13,-16, 14, 11, -7, 5 }, - { 16, 28, -7, -1, 6, -3, 9, 0, -7, 3, 0, 3,-12, 20, 8, 9, - 8, 23, 8,-13, -2, 4, 9, 3, -5, 13, 5, -2, 12, 14, 5, -1 }, - { 19, 37, 19, 5, 7, 5, 10, 5, 19, 10, 14, 0, 2, 5, 1, -4, - -4, 2, 2, -5, -2, -1, 2, -6, -4, -4, -5, -3, 2, -2, -2, -2 }, - { 24, 21, 1,-11,-10, 17,-14, 14, 6, -1, -6, -1, 0,-13, -1,-12, - -2, -5, 6, -4,-12, 14, 5, -2, -8, -8, 15, -7,-30,-12, 4, 0 }, - { 11, 26, -3, 3, 5, -1, -2, 3, -2, 10, 15, -4, 10,-28, 10,-17, - -8, 1, 2, -7, -1, -6,-15, -1, 4, 5, -7, 9, 0, -5, -4, 4 }, - { 18, 32, 1, 2, -7, 4, 15, 2, -9, -2, 12,-11, 7, 11, 13, 2, - 0, 5, 9,-10, 16, 3, -3, 5, -9,-23, 2, -2, -1, 5, 2, 11 }, - { 35, 24,-20, 2, 4, -1, 5, 14,-10, -9, 8, -7, 0, 5, -7, -7, - 11, 1, 5, 3, 2, 0, -2, 3, 0, 1, 4, 0, -2, -8, 0, -4 }, - { 9, 35, -1, 2, -1,-19, -3, 12, -1, 8, 8,-13, -1, -2, 2, 5, - -8, -1, 13, -2, 11, 1, 0,-10, 0, -3, -7, 2, 1,-12, 3, 12 }, - { 20, 27,-12,-12, 7, 4, -1,-13, -1, -9, 2, 13,-11, 5, 7, -9, - 9, 1, 1, 8, -9, 0, -6, 7, 4, 2, -2, 7, 3, -2, 1, -9 }, - { 8, 37,-20, -5, 0,-21, 10, -8, 3, 19, -9, 7, -3, -8, 10, -2, - 0, 5, 6, -4, -2, -1, 0, -7, 6, 1, 0, 4, -5, 6, -8, 2 }, - { 8, 27, 1, -3, -5, 1, 6, 0, 15, 2, 17, -1, 3,-17, 10, 5, - 5, -6, -6, 6,-10, 18, -5, 0, 0, 13, 7, 10, -5, -6, -2, -4 }, - { 14, 29,-20, -4, -3, 1, -5, -1, 2, 12,-10, -3, 4,-18, 4, 14, - -4, -1, -9, 15, -2, 2, -5, -3, 2, 9, -2,-14, -3, 4, -4, -7 }, - { 23, 23,-23,-11, 27, 4, 4, -1, 7, 0, -5, 9, 2,-11, 3, 7, - -2, -5, 2, -7, -7, 13, -3, -6, 2, 3, 3, -4, -1, -8, 5, -2 }, - { 16, 26, -6, 8, -9, -1, -2, -1, -8, 4, -2, 0,-12, 9, -1, 0, - -17, -9, 30, -5,-15,-16,-13, 0, 10,-11, -7, -3, -1, 0,-11, -2 }, - { 12, 32, -4, -5, 10, 19,-10, 4,-12, 5, -6, 9,-12, -6, -6, -8, - 4, 1, 3, 0, 8, 0, -3, -4, -7, -4, 10, 8, 6, 5, -1, 4 }, - { 46, 42, -3,-14, -2, -6, 6, -2, -5, -1, -3, -3, 1, -1, 3, 1, - 1, 4, -1, 2, 3, 1, -2, 6, 0, -1, -2, 4, -2, -1, 2, 2 }, - { 9, 33,-13, 4,-11, 3, -8, 22, 12, -2, 4, 0,-16, 5, 4, -1, - 7, -6, -9, 1, 7, 5, 0, -5, 5, -1, 10, 3, -2, -1, 3, -2 }, - { 9, 30, 6, -3, 6, 1, -7, 5, 11, 14, 7, 1, 0, 2, 2, -1, - 8, 7, -6,-13,-10, -2, 1, -6, 10, 7, 6, 5, -2, -5, -1,-16 }, - { 9, 28,-11,-10, 9,-10, 15, 8, 4, 9, -4, -7, 0, -5, 9, 8, - -7, 2,-15,-23, 4, -4, 4, 16, -8, -3, 0, -8, 14, 5, -3, 15 }, - { 17, 26, -5, -5, -1, -8, 20, 18, -7, -2, 4, -7, -8, -5, -4, 16, - 0, 0, -7, -2,-13, -5, -2, 3, 12, 1, 3, -5, 2, 2, 0, -1 }, - { 11, 37, 7,-23, 6, -1, 15, 13, 4, -9, 7, 5, 3, -3, -5, -8, - -2, 3, -5, -1, -8, 7, 2, 13, 1, 3, 0, -3, -1, 2, 0, -2 }, - { 21, 33, 7, 20, 21,-10, 6, -5, -5, -6, -9, 2, 10, 0, 8, -4, - 10, 2, -2, -2, 0,-10, -6, -2, 0, -5, 3,-11, 3, -9, -3, 1 }, - { 6, 30,-15, -8, 16, 1, 4, 6, 4, 5, 8, -3, 8, -9, -1, -6, - 8, 2, -2, 4, -2, 5, 11,-21, 3,-10, 16,-11, 24, 10, 14, -6 }, - { 15, 36, -3, -9,-20, 12, 0, -7,-18, -4, -8, -9, 9, -7, -3, -1, - 2, 7, -5, -8, 6, 2, 2, -1, 7, 1, 1, -3, 3, -4, -8, 1 }, - { 16, 34, 21, 3, -9, 10, 7, 9, -7, 1, -4, -9, -4, -5, -5, 3, - 3,-19, 1, 5, 4, -2, -6, -5,-10,-11, -8, -2, 2, -5, -8, -7 }, - { 28, 29, -3, 18, -2, 0, -6, 12, -2, 10,-11, -4,-13,-12, -6, -4, - 0, 4, -1, -8, 6, 4, 12, 11, 10, 10, -3, -6, 1, 2, 1, 7 }, - { 3, 8, 22, -8, 3, 36, -8, -1, 9, 6,-13,-14, 8, -1, 1, 2, - -2, -8, 0, 3, 1, 2, -1, 5, -1, -8, 0, -2, 2, 2, -1, 1 }, - { 0, 6, 0, 0, 4, 13, -7,-16, -6, 15,-14,-21, -9,-10,-10, -6, - -21, 5, 4, 2, 12, 4, 12, 11, -4, -6, -6,-10, -7,-18, 1, 4 }, - { -1, 3, 10, 1, -1, 15, 4, -7,-16, 3, 0,-22, 10, 2, -3, -2, - 13, 5, -8, 16, -5, 4, 0,-11,-10,-22, 0, -4,-17, 5, 2, 1 }, - { 12, 8, -4, -9, 14, 40,-21, 0, 1,-15,-10,-12, 12, 6,-10, 2, - 8, 6,-12,-10,-11, 1, 0,-11, 2, 1, 13, 0, 6, 3, 8, 4 }, - {-10, 3, 5, -4, -3, 3, 0, -9, 2, 8,-22,-23, 17, 8,-17, -3, - 14, -8, -4, 1, -8, 3, 0, 5, -1, -3, -2, -4, 1,-10, 0, -2 }, - { 0, -1, 5, -7, 4, 12, -2, 0, -7, 2,-16,-15, 12, 21, -7, -4, - 7, -7,-11,-15, -7, -9, -5, -8, 0, -6, 8, -3, -8, 22, -7, -9 }, - { 7, 19, 4, -9, 24, 22, 2, -6, 8, 13,-14,-20, -4, 11, 8, -4, - -1, 2, 0, -7, 5,-17, -3, 3, -6, 5, 3, 4, -5, -7, -3, 14 }, - { -2, 6, 2, 8, -2, 5, -4, -2,-10, 3,-45,-30, -3, -3,-12, -4, - -3, -3, -1, 9, -6, -6, 5, -4, 0, 5, -1, -2, -1, 0, -6, -1 }, - { -3, 14,-16,-10, 10, 0, -2,-40, -9, 12, 2,-19, 15, -4, 4, 3, - 3, -4, 7, 1, -4, -5, 0, 4, -1, 0, -9, -2, -4, -1, -2, 0 }, - { 7, 16, 2, -7, 8, 2, 0, 1, 5, 21,-10,-26, 7, 2, -9, -7, - -3,-16, 8, 5, 5, -6, 10, 4,-14, -6, 5, 3, -2, -2, -4, 1 }, - { -9, 14, -1, 3, 3, 11, 1, -5, -3, 13,-16,-18, 20, 6, -5, 0, - -3, 2, 8, 4,-19, -9, 12, 0, -8, 2, 2, 1, 6, 13, -7,-11 }, - { 2, 5, 16, -4, 19, 15, 4, 0,-11, 7,-10,-10,-16, 18,-11,-12, - -9, -4, 7, -4, -4,-17, 1, 1, -8, -3, -3, 5, -2, -6,-11, -5 }, - { 2, 12, 0, -9,-10, 14, 6, 2, -3, 2,-12,-28, 12, 1, -1, 2, - 0, -3, -4, 7, 16, 5, -7, 8, -4, -3, -1, 3,-12, 4,-17, -5 }, - { -4, 7, 11, 6, 1, 14, -4, -6, 5, 5, -6,-24, 23, -9,-15, 13, - -7, -9,-15, 10, -1, 8, -5, 1, 12, 6, 2, 0, 4, -2, 9,-10 }, - { 1, 5, 11, 3, 6, 12, -3, 8,-21, 5, -7,-20, 12, -2, -9, -3, - 17, -7, -8, -9,-14, 3,-13, 18, -8, 9, 2, -8, 4, -8, -5, -2 }, - { -3, -3, -1, 5, -2, 15, 3, 2, 1, -8, 1,-39, -6, 13,-13, 0, - -2, -5, -6, -3, 0, -5, -2, 15, -9, 5, -3, -6, -2, 7, 0,-13 }, - { 2, 8, 5,-12,-13, 22, 8,-16, 11, 5, -2,-32, -2, -4, 11, 5, - 5, -6, 1, 3, 1, 5, 3, 6, -5, 4, 4, -8, 8, 4, 1, 3 }, - { 13, 9, 5, -4, 9, 18,-11, 2, -1, 15,-10,-19, -2, 14, 0,-10, - 1, 1,-18, 3, 2, -6, -8, 20, 7, -8, 16, 9, 9,-13, -3, -2 }, - {-13, 11, 11, -9,-10, 13, -3,-18, 2, 10, 5,-21, 6, 15,-11,-21, - 3, 14, 0,-12, 9, -1, -2, -4, 3, -3, -9, -8, -5, -2, -8, 2 }, - { 3, 3, 11, 4, 0, 13, 1, -8, 10, 13, -6,-26, 2, 12, -3, -5, - 12, -2, 1, 8, -7,-17,-19, 5, 10, 7, -3, 2, -3, 0, 5, 0 }, - { 5, 0, 3, -3, -9, 5,-15, -5, -5, 17, -5,-31, 0, 13, 13, 5, - -1, -6,-14, 7, -8, 9,-14, -2,-16, -4, -4, -6, 6, -6,-10, 6 }, - { 13, 3, 1, 7, -3, 4, -1, -2, -1, 4, -8,-32, -1, -4, 0, 3, - -10, 7, 10,-10, 4, -1, 6, 2,-16, -9, 4, 3, 13,-23, -3, -4 }, - { 4, 11, -4, -9, 4, 11,-12,-12,-12, 6, 1,-28, -3, 14, 18, -2, - -12, 7, 15, -3, -5, -7, -3, 2, -6, 4, 4, -2, -5, -3, 2,-13 }, - { 8, 7, -7, 0, 13, 7, -8, -7, 8, 36,-10,-22, 3, 23, -3,-10, - -3, 11, 1, -7, 3, 3, -1, -7, -4, 2, 3, 2, 5, 3, -4, -1 }, - { -1, 1, 13, 1, -6, -1, -6, -9,-18, 17, -5,-37, -1, -1, -6, -4, - 1, -6,-15, 2, 17, -9, 0, -3, 0, 4, 0, -5, 0, 4, 1, -5 }, - { 0, 14, 5, 0, -7, 2, -6, 17, -6, -9, 7,-16, -5, 23,-14,-13, - 8,-15, 11, 10,-11,-13,-33, -5, -2, 1, 6, 8, 0,-13, -9, 5 }, - { 11, 7, -2, -8, 9, 11, 25,-14, 7, 3, -1,-33, 14, 8, -6,-19, - 3, 3, 2, -1, -3, -1, -2,-10, -3, 1, 2, 1, 4, 2, -3, 4 }, - { -2, 8, 4, -2, 9, 13, -4, -2,-15, -3, 19,-37, 9, 25, -9, 2, - -5, -2, -2, -4, 4, 2, 2, 0, 3, 3, 3, 5, -2, -3, -4, -3 }, - { 10, 13, -1,-15, 4, 6,-18, -4, 25, 1,-23,-17, 15, 13, -8, -8, - 7, 4, -5, 3, 6, 9, -7, 6, 0, -5, 8, 0, -6, -1, -2, -2 }, - { 1, 3, 9, -5, 27, 15, -9,-31, -1, 23, -2, -9, 1, 8, -1, -7, - -2, -8, -4, -4, -2, -1, 3, 5, 0, 0, -1, 1, -7, 7, -3, -3 }, - { -8, 7, 3, -6, 8, 3,-11, -2, 36, 14, 1,-30, 6, 10,-12, -6, - -6, -2, -4, -3, -5, 0, 9, 4, -5, -5, -8, 12, 4, -3, 1, -8 }, - { -2, 9, 33, 0, 12, -3, -7, -4, -4, -1, 6,-25, 11, -6, -9,-11, - -2, -4, -2, 6, -1, -3, -6, 15, -6, 3, 10, -4, 1, 0, 5, 8 }, - {-22,-21, -9,-19, -5, -7,-12,-15, -8, 9,-19, 14, -7, -4, 5, -8, - -2, 7, 1, -3, 4, -4, 6, 11, 2, 6, -3, -5, 2, -2, 0, -3 }, - {-32,-13, 3,-24, 3, -8, 4, 1,-10, 14,-15, 0, 4, 6, -1, 6, - 7, -1, 6, 4, -3,-17, 1, 4, -6, -1, 1, 0, 3, 3, -7, -4 }, - {-32,-11, 7, -8,-12, 13, -5,-22, -4, 12,-16, 2, 0, 4, 0, 1, - 0, 6, -5, -8, 2, 6, 5, 0, -3, -6, 5, 6, 5, 5, 13, -4 }, - {-44,-33, 6, -4, 2, 0, -9, 10, 3, 4, 7, 0, -1, 7, 5, 1, - 1, -3, 1, 6, -1, 0, 2, 3, -4, 0, 0, 1, 0, -1, -2, -1 }, - {-30,-18,-24, -8, 5, 0, -2, 14, 7, 0, 1, 12, 6, 4, -9, 7, - 5, 7,-11, -5, 1, -8, -1, 2, 2, -9, 7, -1, 7, 5, 6, 6 }, - {-22,-20,-13, -9, 20, -3, 10, -8, 6, -4, 2, -7, 10, 8, 0, -1, - 2, -3, 6,-19, 2, 4, 3, 3, -7, 2, -1, -6, 1, 1, 6, -2 }, - {-27, -8, -1, 3, -1,-11, 24, 4, -1, 1, -8, 8, 5,-11, 15, -3, - -15, -1, -1,-13, -1, 1, -5, 5, 2, 3, -9, 0, 4, 3, -7, 6 }, - {-33,-16, -1, -8, 10,-23, 6, 13, -1, -3, -9, 0, 5, -7, -5,-12, - -2, 3, 3, 6, -2, -3, 2, -3, 9, -6, -3, -2, 0, 5, -3, -4 }, - {-22,-17, 11, -3, 3, 1, -1, -5, 17, 2,-15, -2, 10, -9, 6, 14, - -16,-12, 20, -1, -7, 6, -3,-12, 1, 10,-10, -1, 7, -3, -1, 10 }, - {-28,-13, 1, -3, -1, -1, 0, 3, 3, 5, 1, 10,-10, -3, 7, 2, - 4, 19, -1, -1, 10, 5, -8, 1, 11,-15, -4, -3, -5, 4,-13, 3 }, - {-22,-13, 42,-20, 5,-13, 7,-11, 1, 1, -1, 1, 6, 3, 6,-11, - 3, 3, -2, 0, -4, 4, -3, -1, -5, 2, 0, 0, -9, -1, 4, 4 }, - {-26,-15, -2, -6, -4, -2, 16, 8, 21, 8, 1, -3,-10, 7, -8,-12, - -5, 12, -9, 3, -2, -3, 18, 1,-12,-15, -4, 5, -3, 0, 12, 7 }, - {-26,-16, 5, 6, 14, -3, 15, 6, 1, -7,-13, 16,-15, 5, 11, -2, - 9, -7, -4, -2, 0, 0, -2, 7, -8, -6, -5, 2, 7, -3, 2, 12 }, - {-31,-17, -8,-30, 4, 14, 6, -6, 6,-11, 0, 3, -4, 0, 0, -4, - 0, -4, 1, 4, 3, 4, 0, -5, 3, 2, 2, 0, 2, 1, 3, 5 }, - {-61,-10, 4, 10, 4, 7, 0, -3, 0, 1, 0, -3, 0, 1, 0, -2, - -1, 1, 2, -2, 4, -3, 1, 1, -1, 1, -2, -4, -4, 4, 0, 0 }, - {-28,-13, -8, -4, 3, -3, 2, 1, 11, 14, 3, 9, 1, 13, 3, 5, - -3, -2, -2,-12,-14, -9,-11,-15,-12, -5, -4,-12, 3, -3, 0, -5 }, - {-41, 0, 12,-24, 13, 4, 5, 16, -5, -4, 0, 0, 13, -4, 1, -9, - 9, -6, -1, 6, -2, 5, 2, 9, 6, -9, -8, 8, -2, -3, -6, -4 }, - {-26,-19, -2,-15, 4,-14, 6, 0, 26, 20, 8, 9, 9, 3, -4, -5, - -8, 1, 0, -1, 5, 9, 3, 4, 4, 7, 1, 3, -2, -2,-10, 0 }, - {-29,-18, 9, -4, 1, -5,-14,-12, 5,-10, -5, 4, -5, 0, -1, -1, - 4, -5, 7,-16,-11, 2, 7,-15, 2, -4, 6, -4, -6, 7, -3, 7 }, - {-27,-16, 9,-14, 3, -8, 9, 0, 7, -4, -3, -7, 0,-10, -1, 2, - 1, -2, 15,-10, 14, 7, 6, 17, 3, -4, 3,-10, 8, -8, 3, 11 }, - {-21,-20, -8, -8, 4, 5, -3, -2, 0, -5, 14,-10, 11, -4, 13, 0, - 5,-11, 19,-18, 18, 3, -5, -3, -4, -8, 11,-10, 10, 3, 4, -9 }, - {-35,-15, 13,-12, 4, 0, -2, -4,-12, -3, -8,-24, -7, 1, 7, 8, - -3, 0, -2, -1, 3, -2, -2, -6, 8, 1, 0, 1, -6, -1, 2, -6 }, - {-19,-14, 13,-10, 9, -1, 1, 3,-12, 5,-16, 7, 13, 9, 4, -4, - 6, -5, 4, 9, -3, 17, -4, 12,-11, -6, -5, -6, 13, 2, 7, -9 }, - {-34, -8, -4, 1, 2, -1, 3, 6,-20,-11, 8, -1, 4, 2, -9, 4, - -4, -5, 16, 10, -4, 14,-13, 1, -6, 0, 2,-10, 0, -3, -3, 7 }, - {-36,-10, -8, -3, 2, -2, 14, -4, -1, -7, -4, 10, -1, -3, 15,-11, - 0, 2, 3, -1, 4, 0, 8, -1, 0, 18,-11, -5, 15, -5, 13,-12 }, - {-22,-13, 14,-20, 15, 25, 16, 10, 8, -2,-10, -5, -1, -8, 11, 8, - -1, -2, -4, 1, 2, -1, -7, 0, 0, 0, -3, 0, 2, -1, 0, 2 }, - {-31,-22, 7, 6, -2, 5,-20, 14, -6, 7, 0, 14, 3, -7, 3, -6, - -2, 1, -3, -5, 1,-10, 1,-24, 6, -2, 3, -7, 1, -7, 8, 7 }, - {-25,-20, -3, -9, 10, 6, 12, 7, 5, 4, -3, 6, -1, -5, -6, -8, - 3, 5, 6, 5,-10, 10, -4,-15,-15, -2, -9, 2, 18, 1, 8, 12 }, - {-24,-19, -2, -4, -7, 11, 6, 9, 16, 2, -7, 18, 6, -7, 6, 6, - -2, -9, 3, 12, -2, 3, -1, 6, 7, 8, 0, 8,-11, 8, 4, 2 }, - {-26,-20,-12,-12, -2, -3, 1, -5, -1, -2, 0, 3, 7, 9, -2, 2, - 9, 22, 13, 4, -4, -1, -2,-14, 5, 15, -8, -5, -7,-11,-14, -6 }, - {-21,-18, -1, -4, 0, 3, 7, -2, 10, 8, -8, -1, 15, 1, -9, 3, - 1, 3, -5, -2, 2, 4, 0, -1, 10, 2,-19, -8, 8, 30, -7, 8 }, - {-25, -6, 26, 4, -8, 4, -2, 21, 5, -4,-16, 5, 13, 4,-10, -1, - -6, -2, 2,-10,-13, 1, 3, -3, -6, -8, 2, 11, 1, -7, 0, 5 }, - { 0, -1, -2, 19,-12,-48, -6, 11, 8, -2, -4, -2, -7, 5, -3, 2, - -2, -1, -1, -7, 0, -3, -3, -4, -4, 4, 1, 3, -3, -1, -2, -5 }, - {-11, -8,-28, 18, 16,-24, -8, 19, 4, 8,-12, 9, -4, -2, 4, -7, - 6, 2, 3, 3, -4, 0, 1, -6, -4, -2, 2, 6, 0, -3, 1,-16 }, - { -9, -5,-26, 7, -3,-37,-16, -2, 2, -7, 4,-13, 0, -4, -6, -5, - -6, -4, 0, 3, 4, -3, -4, -4, 4, -3, 9, -4, -2, 2, 7, -4 }, - { 2, 9,-18, 7, 29,-24, -1, 7, 14, 10, 3, -3, -2, -5, 6,-10, - -6, -3, -8, 0, 5, 1, 4, 3,-12, 2, 6, 1, 3, 4, 1, -3 }, - {-20, 2, 8, 20, -9,-24, -4, 18, 3, 11, -1,-11, 6, 9, -1, -3, - 1, -1,-15, 3, 15, 9, 3, 2,-13, 2, -8, 8, 1, -1, 1, -8 }, - {-12, 5,-11, 6, 19,-26,-17, -6, 4, 14, 6, -8, 9, 5, -6, -5, - 2, -1, 20, 1,-11,-10,-18, 20, -7, 0, -3, 4, 2, 0, 10, 4 }, - {-15, 1, -2, 13, -8,-21,-22, 4, 4, 3, 3, -7,-31, 4,-10,-14, - 0, 8, 4, 5, 8, 11, 2, -8, 6, 7, 0, -2, 6, 8, 8, 7 }, - {-13,-10, -9, 12, 19,-16, -3, -2, 9, 2, 11,-29, -1, 9, 4, -3, - 1,-10,-10, 16, 1, 7, -7, -6, -4, -1, -5, 3, 6, 0, 3, 1 }, - {-17, -1, -5, 19, 12, -9,-21, -5, 2, 12, -7, -7, -3, 8, 7, -2, - 6, -9, -9, 1, -4, 1, 1, 3,-14, 2, -8, 0, 10, 1,-12, -6 }, - {-13, -5, 8, 15, 0,-20, -2, 20, 8, -8, 8,-19, 12, 10, 2,-11, - 0, 12, 1,-11, 0,-11,-15, 5,-11, 2, 4, -4,-11, 5, -4, -5 }, - { 3,-11, -7, 8, 0,-17,-26, 15, 19, -7, 10, -9, -5, -5, 14,-25, - 0, -8, 2, -9, -3, 9, 1, -6, 4, -4, 3, -9, -1, 6, 2, 2 }, - {-12, 5, 5, 9, 14,-18,-19, 4, 2, 16, 14,-21,-15, -9, -1, 16, - 12,-11,-10, -5, -7, 4, 15, -8, -5, -1, 1, 14, 13, -7, -1, -4 }, - {-10, -5, -1, 8, 7,-23,-10, 14, 6, 11, 10,-16, -3, 16, 6, 0, - 0, 9, 6, -2, -7, 1, 22, 5, 3, -8, 0, 3, -2,-10, 3, 0 }, - { -2,-14, 2, 16, 15,-17,-17, 6, 19, 4,-10,-15, -1, 15, 11,-14, - -8, 5, 8, 8, -2, -8,-11, 10, 10, -8,-14, 2, 13, 4, -2,-12 }, - {-10, 3, 6, 4, 19,-23,-19, 1, 4, -9,-30, 3, -6, 18, 0, 2, - 0,-11, 0, 3, 7, -2, 8, 5, 2, -3, 6, -9, 1, -4, 7, -6 }, - { 9, 5, -2, 21, 20,-33,-13, 7,-10, 8, 8,-15, -6, -4, 1, 5, - 3, 7, -2, -9, -1, 4, -6, 1, 0, 9, -1, -5, 2, 1, -3, 3 }, - { -9, -3, 3, 15, -3,-30, -7, -7,-25, 6, 2, -6, 1, 19, 1,-12, - 1, -8,-13, 9, 13, 1, 8, 2, 5, 15, -2, 3, -9, 0, -4, 4 }, - { -6,-12,-17, 25, 22,-13,-10, 9, 2, 11, -7,-16, 4, 6, 1, 0, - 0, 18, -4, -5, 4, -2, -1, -5, 0, -4, 6, 1, 6, -1, 7, 0 }, - { -1, 0,-10, 8, 8,-27, 0, -2, 29, 16, -2, -4, 9, -1, 2, 0, - 6, 10, 6, 4, 2, -7, 9,-18, 3, 3, 3,-10, 17, 10, 9, -6 }, - { -3,-12, -6, 11, 20,-32, 5, 21, 3, -4, -9, 2,-10, 1, 7, -4, - 5, 0, 0, -1, -8, -9, -7, 4,-10, 5, 0, 2, -5, 4, 9, 1 }, - { -5, -1, -5, 1, 2,-19,-13, 1, 6, 12, 2,-16,-17, 11, 10, 13, - 16,-12,-11, 3, -6, 0, 6, 4, -3, 1, 8, 2, 5,-11, 3,-14 }, - {-19, 5, 10, 11, 2,-23, -9, 16, -2, 7, 0,-11, -7, 10, 6, -7, - 26,-15, -4, 8, 6, -4, 7, -9,-15, 1, 8, -4, 4, 2,-12, 16 }, - {-11, 1, 11, -4, 1,-31,-13, -1, 8, 5, 4, -2, 0, 13, 7,-17, - 7,-10, -6, 1, 4, -1, 2, -9, -4, 9, 3, 3, -4, -5, 3, 4 }, - { -3, 1, 10, -1, 0,-15,-22, 4, 40,-11, -4, -3,-14, 9, 11, -1, - 9, -1, -6, 6, 3, -6, 0, 0,-12, 7, -2, 0, 9, 3, 1, 3 }, - { -1, -1, -1, 14, 8,-24,-14, -8, 5, 8, 5,-12,-17, 8, 2, 7, - 10, -8, 0, 4, -6, -6,-10, 8, 4,-12, 3, -9,-12, 5, 4, -3 }, - { -5, 1,-11, 8, 9,-24, 0, 2, 2, 14,-12,-13, 1, 6, 7, 0, - 7, -6, 9, 26, 11,-14, 8, 10, 1, 9, 0, 11, -2, 6, 2,-10 }, - {-13, 1, 4, 34, 19,-17,-15, 0, 3, -2, -7, -1, 0, -3, -3, -1, - 1, -1,-10, 8, 5, 0, -8, 4,-17, 9, -2, 0, 0, 6, 2, -3 }, - { -6, -4, 1, 2, 2,-14,-29, 0, 9, 34, -3, -5,-14, 6,-10, -9, - -5, -1, 0, 3, 3, 0, 1, -1, -2, -1, -1, -3, -3, -4, 3, -3 }, - { -4, 6, 3, 14, 14, -8,-29, 31, 11, 14, -4, -5, -6, 10, 6, -9, - -1,-11, -7, 1, 7, 4, 1, -6, 4, 0, 10, -7, -5, -1, 2, 4 }, - { -4, -4, -2, 14, 6,-32, -6,-14, 14, -5,-11, 10,-18, -4, 6, -8, - 9, 5, -4, 1, -4, 5, -2, -9, 3, 5, 2,-10, -6,-17, 3, 17 }, - {-16, 9, 21, 19, 4,-20,-17, 14, 9, 15, -6,-17, -1, 1, 6, -3, - 1, 1, 8, -3, -6, 6, 9, 4, 9, -9, -5, 1, -1, 0, -1, 2 }, - { -7, -5, 3, 19, 1,-20, -9, 14, 21, -7,-18, -9, 26, -7,-17, -7, - 12, 6, 0, -9, -6, 14, 9, -9, -8, 4, 15, -7, -9, -1, 9, 1 }, - {-20, 30, -6, 11, 24, -4, 0, -6, -2, 8, -4, 12, -8,-17, 0, 5, - -4, 1, -1, 3, -3, 5, 3, 3, 7, -2, -3, -2, 4, 0, 0, -1 }, - {-35, 17, 6, 1, -9, -1,-16, 3,-20,-13, 8, 7, -4, -7, -4,-20, - 7, 12, -5, 5, -5,-11, 12, -1, 15, -9, -6, 16, -4, -9,-13, 4 }, - {-21, 36,-19, 9, 0, -7, -8, 9, -4, -3, 3, 0, 7, -8, -2, -2, - -11, 13, -1, 5, -3, 7, 2, 3, -1, -2, -5, 1, -1, -2, -5, -3 }, - {-12, 33, -4, 1,-12, -9, 0,-13, -1, 2, -8, 4,-10, 6,-16, -7, - -1, -4,-10, 15, -1, 0, -5, -8, 5, 5, -3, 0, 2, -7, 1, -7 }, - {-14, 32, 5, -7,-15, 3, -5, 8, 14, 5, 9, 13, 3, 18, -3, 7, - 4,-10,-10, 10, -1, 2, 0, -2,-11, 5, -3, -4, 2, 2, 7, 4 }, - {-14, 34, 1, 20, -1,-12, 0, -3, -7, -4, 7, 18, 9, -3, 14, -7, - -9,-20, -7, -4,-13, 12, 1, 12, 5, -6, 2, -4, 0,-15, 1, 3 }, - {-21, 23, 7, -8, 3,-13, -3, 0, -6, -2, -7, 6,-12, 9, -6, -2, - -2, -4, -1, 6, 9, 5, -9, 15, 0, 8, -8, 7, 6,-15, 3, -5 }, - {-27, 32, -1, -4, -2, 4,-10, 12, -3, 8, 13, 7, 0,-15, 4, -2, - 3, 5, 7, -4, 9,-12, -1, -2, -1, -4, 0, -4, 2, -5, 6, -6 }, - {-17, 29, 15, 0, -1, -4,-10, 13, 12, -1, -8,-10,-10, 4, 7, -2, - 6, -5,-13, 19, 6, 1, -7, 2, -9, -2, 12, -4, -8, -3, 2, 4 }, - {-38, 27, 16,-15, -6, 3, -7, -4, 0, -1, 6, -2, -3, -6, 6, -6, - -3, 0, 2, 0, -4, 6, 1, -1, 0, 4, -1, 3, 4, 1, -2, 5 }, - {-33, 40, -4, 2, 1, 0, 0,-10,-14, 0, -7, 4, -1, 3, -2, 5, - 7, 6, -1, 4, 1, 3, 1, -7, 1, -4, 5, 7, 0, 4, 3, -4 }, - {-20, 25, 12, -4, 16, -4, 2, 2,-14, -2, -3, 29, -1, 1, 3, 1, - 9, -5, 2, -8, -3, 1, -7, -2, -7, 1, 0, 4, 16, -2, -1, -1 }, - {-10, 30, 17, 3, -5, -2, 0, -5,-22, 4, 5, 5, -3,-18, -6, 10, - -5, -7, 2, 8, 7, -7,-11, -2, 0, -3, 3, 2, 11, -4, 4, -4 }, - {-11, 30, 11, 4, -3, -8, 1, -2, 4, 18, 3, 1, -1, 0, -8, -4, - -3, 10, 13, 14, 5, -5, 1, 1,-10, 2, 15, 4, 9, -1, -5, -3 }, - {-17, 32, 18,-18, -3, -5, 6, 10, 1,-15, -5, 9, 8,-12,-10, -6, - 11, 9, -5, -8, -7, 10, 5,-10,-14, -4, -3, 1, 9,-11, 2, 1 }, - {-13, 28,-11, -1, 2,-16, -2, 7,-24, 0, 3, 6, 3, -1, -8, -7, - -12, 2, 2,-20, 10, 4, 0,-13, -2, -2, 1, 8,-14, 0, 4, 1 }, - {-14, 23, 12, 8, 8,-26, 2, -4,-14, 13,-14, 15, 3, -9, -1,-13, - -10, -2,-10, 6,-16, 12, 8, 0, 9,-10, -7, -4, -4, 7, -8, 8 }, - {-20, 45, 10,-14, 4, 16, 8, -9, 1, -8, 10, 5, -7, -2, 2, -5, - -1, 0, -5, 4, -6, -2, 4, 1, 3, 4, -4, 2, -2, -2, 5, 1 }, - {-20, 26, -4, 1, 7, 4, -8, 1, -5,-13, 2, 13, -7, -3, 6, -6, - 22, 0, 5, 11, -4,-11, 8, -9, 2, -2, -4, -2, 2,-13, -4, -8 }, - {-28, 18, 17, 3, -8,-23,-16, -6, 5,-10, 14, 10, 5, -1, -8, 4, - -2, 13, -3, -2, 3, 4, 3, -2, -3, -4, 0, 1, 3, 4, 0, 4 }, - {-12, 32, -6,-16, 18, 12,-16, 0, 7, 13, -4, 5, -8, -1, -3, 4, - 6, -2, -1,-13, 4, -1, 3, 12, -3,-10, 1, 6, 8,-11, -2, 4 }, - {-18, 26, 2, 5, 0, -9,-17, 14, 5, 1, 7, -3, -8, -3, 11, 7, - -5,-12, -8, 7, 0, -7, 2,-12, -9, 13,-11, 9, 6,-11, -5, 11 }, - {-24, 22,-15, -9, 8, 1, -7,-12, -9, 3, 11, 15, 14,-11, 12,-15, - -5, 7, -2, 0, -8, 3, 3, -1, 2, 11,-11, 14, -6, 13, 1, -6 }, - {-20, 28, 18, -4, -6, -5, 12, 14, 2, 10,-13, -6, -8, -6,-13, -1, - -26, 22, -3,-14, 6, 0, 10,-15,-13, -9, 6, -7, 1, -5, -4, -1 }, - {-19, 26, -8, -3,-14, -6, -9, -4, -8, 15, -8, 3,-12, -4, -2, -7, - -5, 3, 13, -3, -4,-25, 4, -1, 5,-12, -1,-13, 5, 2, 0, 6 }, - {-18, 43, 14, -8, 1,-23, -2, -2, 1, 3, -7, 0, 0, 8, -1, -3, - -5, 1, 5, 2, 0, -2, -2, -2, 1, -1, -1, -7, 0, 3, -3, 9 }, - {-11, 30, 10,-14, 3, 1, 10,-11, 1, -7, -4, 14, 2, 1, -9, 1, - -11, -2, -7, 5,-11, 1, 3, 14, 1,-16, -8, 3, -5, 7, -4, 4 }, - {-18, 24, 6, 3, 8, 7,-22, -7, -7, 3, -8, 4, 23, 9, 3, -1, - 3, 6, 7, -1, -7, 6, 4, 1, -3, 1, -6, -1, 2, -7, 3, 3 }, - {-15, 38, -7, -1,-11, 2,-17,-24, 24, 8, 7, -4, -5, 2, 2, -7, - 1, 4, 0, -9, 5, 0, -1, 1, -1, -5, -6, 3, 0, 7, 8, -3 }, - {-14, 22, 1, -5, 9,-12, -9, -5, -6, 5, 7, 8, -1, -4, -9, -3, - -33,-16, -9, -1, 12,-11, 17, -7, -3, -1, -7, 3, 2, -3, 16, -4 }, - {-14, 20, 6, 4,-10, -4, -4, -4, 1, -7, 2, 6, 8,-12, 4, 1, - -1, 12, 10, 3,-14,-10, -3, 18, -2, 33, -5,-17, 17, -5, 9, 7 }, - {-12, 23, 13, 0,-11, -8,-11, 12, -5, -9,-16, 11, 6, 4, 12, -5, - 5,-13, 7,-12, -3, 1, 2, 12, 1, -4, -1, 5, 4, 11,-12, -3 }, - { 15, 2, 14, 7, 1, 2, 1, 12, 10, 23, 4, 6,-20,-10, 4, 26, - -6, 13, 4, 3, 2,-11, 5, -7,-10, 4, 9, 1, 10, -4, 11, 4 }, - { 17, 15, 31, 17, 18, 16, 11, 24, 2, 4, 2, 3, -8, -3, 7, -3, - -5, -7, -2, -6, -4, -5, -4, -1, -4, -2, -5, -6, 2, -1, 4, -2 }, - { 16, 8, 15, 14, 3, 7, 21, 9, 8, 15, 21, 6, 8, 12, 5, -5, - 7, -3, 10, 2, -3, 8, 6, 0, 5, 5, 6, -3, 2, 4, 0, -5 }, - { 5, -4, 6, 12, 6, 13, 24, 17, -5, 17, -1, -6, -7,-10, -8,-18, - 3, -2, 2, 7,-15,-11, 12, -3, -2, -2, -4, -7, 2, 0, 5, 5 }, - { 10, -6, 8, 11, 12, 20, 22,-11, -3, 15, -3, 15, -2, -2, 0, 2, - 5, -8, 4, -5, -9, -4, -1, 2, -1, -3, 1, 3, 13, -1, 9, 7 }, - { -5, 8, 5, 11, 14, -5, 14, -9, 2, 35, 8, 15, 1, -2, 2, -2, - 4, -9, -3,-14,-12, -2, -2, -4, -2, -8, -3, 1, -6, 3, 10, 0 }, - { 16, 0, -6, 15, -3, 4, 4, 3, 3, 20, 5, -4, 10, 9, -9, -3, - -10, -2, -7, 11,-11,-10, 17, -1, 3,-15, 2, 9,-15,-10, 16, 10 }, - { 14, 4, -7, 19, 3, 0, 19, 8, 16, 34, -9, 6,-13, -1, 6, 5, - -1, -2, 4, 3, 2, 1, 1, -1, 0, -7, 2, -1, 1, 0, 6, -1 }, - { 1, 6, 9, 13, 9, 10, 15, 16, 10, 18, 13, 17, 3, -1, -7, 2, - -15,-11,-10, -4,-13, -6,-17,-13, -6,-14, 1,-10, 6, 4, -1, -1 }, - { 13, 1, 7, 10, 14, 13, -7, 5, 5, 28, 14, 14, -2, 2, 3, -3, - -13, -4, 10, -9, 19, -4, -3, 4, -5, -5, 0, 5, -5, 0, 3, -4 }, - { 1, 0, 6, 22, 9, 18, 18, -3, 5, 10, 12, -2, 1, -3, -8,-12, - 9,-10, -7, 1, -1, 19, 0, 2, -8,-11,-10, 9, 6, 11, 0, 3 }, - { 10, 11, 19, 44, 0, 14, 1, -7, 6, 22, 2, -1, 9, 2, 0, -4, - 4, 0, -6, -6, 3, 0, 0, -2, 2, -5, 1, -2, 0, 1, 1, 1 }, - { 5, 7, 0, 32, 30, 26, 5, 4, -7, -3, 15, -6, 3,-10, 7, 6, - -8, -7, 2,-13, -5, -1, -3, 7, 3, -2, -8, 0, 6, 4, 5, 0 }, - { 9, 8, -2, 4, 2, 11, 4, 29, -5, 14, 8, -5,-14, 8, 0, 9, - 8,-10, 5,-15, -6, -9, 9, -1, 18,-16, 9,-21, -3,-13, -2, 8 }, - { 25, 7, -9, 23, 20, 18, 6, 16, -9, 8, 8, -5, 11, 13, -8, 7, - 4, 10, -2, -1, -7, -9, -7, -9, -4, 1, 1, -5,-10, 8, 4, -5 }, - { 9, 2, 16, 14, -5, 14, 1, 0,-21, 17, -1, 9, 12, -3, -3, 4, - -4, 14, 10, 3, 0,-10, 7, 4, 4,-11, 2, 4, -1, -3, 9, -1 }, - { 17, 8, 11, 26, 15, -3, 14, -1, 12, 9, 10, -8, 8,-18,-11, -3, - -14, -7, 7, -3, -3, -4, 1, -7, -3, 2, -3, 16, 10, 0, 9, 6 }, - { 9, 8, 3, 8, 18, 14, 11, 1, 10, 6, 1, -4,-16, -2, 14, -2, - 1, 8, 12, 14, 3, -3, 8, 8, 12,-15, 3, -3, 3, -2, 14, 10 }, - { 22, -3,-11, 13, -7, 11, 4, 11, 3, 14, 0, -6, -2, -9, 4, 2, - -2, 0, -5,-27,-10, 3, -1, 5, 8,-24, -3,-11, -3, 2, 11, -1 }, - { 19, 2, 8, 36, 5, -6, 3, 15, -3, -4, -5, 14,-10, 1,-12,-10, - -3, -4, 3, -2, 1, -8, 4, 3, 5, -3, 0, 4, 8, -2, 8, 4 }, - { 8, 14, 15, 9, -4, 10, 5, 11, 9, 10, 8, 9,-15, 15, 6, -8, - -10,-13, 5, -8,-20,-13, -6,-11, -1, -3, -6, -4, -1, 0, 13, 15 }, - { -2, -1, 9, 12, 2, 2, 13, 3,-23, 33, 15, 2, -4, -1, 3, 8, - 8, 6, 6, -7, 8, 6, 9, -1, 3, -8, 0, -4, 1, -8, 11, -1 }, - { 6, 5, -6, 16, 2, -3, 31, 21, -9, 12, 0, -1, -4, 1,-12, 3, - -13,-18, 2,-11, -9, 2, -8, -6, 11, -3, -1, 0, -1, 0, 13, 5 }, - { 5, -1, 2, 0, 25, 5, 10, 16, -5, 21, 14, 12, 13, 2, -5, 5, - 5, -3, -2,-14, 0,-12, 7, 11, -1, -7, 19, -1, -1, -1, 8, -1 }, - { 10, 7, 3, 11, 0, 8, 22, 3, 3, 19, -4, 12, 15, 9, 5, 15, - 2, 1, 2,-10,-10, 0, 2, -1, 0, 1,-12, -1, 21, 16, 9, -7 }, - { 11, -4, -5, 24, -7, 11, 20, 11,-15, 18, 5,-13,-15, 0, -5, 9, - 1, 0, -1, -9, 4, -8, 6, -8, 1, -2, -7, 20, 9, 3, 9, 3 }, - { 20, 0,-12, -6, 9, 31, 9, 12, 8, 27, 15, 7,-16, 5, -3, -7, - -1, -9, -2, -7, -3, 4, -8, -3, 3, -6, -2, -2, -3, -6, -1, 2 }, - { 6, -6, 48, 8, -3, 19, 12, 11, -7, 2, 3, 0, -1, 1, 8, -4, - 4, -6, 0, -4, -4, -3, 3, 6, 3,-13, -8, 5, -3, -7, 8, 5 }, - { 7, -2, 6, 11, 12, 2, 14, 4, -5, 12, 2, 9, 4, 2, 0, -1, - 2, 0,-15, -9,-16, -2, 8,-17, -5,-22,-19, -5, -1,-10, 1, -2 }, - { 11, -9, 3, 12, 6, 6, 1, 17, -6, 19, 14, 7, -7, -1, -1, -9, - 9,-11,-17, 0, -6, 16, 0, 1, 9,-24, 3, 3, -9, -3, 3, -2 }, - { 9, 0, 1, 8, 1, 7, 2, -5, -3, 8, -1, 7, 2, 6, -3, -6, - 5, -2, 6, -2, -4, -3, 0, -3, 13,-50, 1, -2, 2, 4, 4, 3 }, - { 7, 0, 26, 21, -4, 2, 17, 8, 7, 11, -7, 1, -1,-15, -1,-15, - -11, -4,-17, -4, 1, -7, 3, 6, 3, -9, 2, 3, 6, 10, 6, 12 }, - { 1, -2, 2, -1,-10, -4, 6, -3, -5, -2, -8, 2, 2, 2, 8, 0, - 1, 1, 6, 0, 11, 13, 3, 4, 0,-12, 11, -5, 19, 20, 2, 5 }, - { 5, 3,-13, -2, 1,-12, 11, -7,-12, 7, 10, 0, 7, 0, -2, 4, - -6, -9,-11,-12,-23, 12, 10, -3, 0, 6, 19, -1, 24, 18, 9, 12 }, - { 6, -3, 2, 5, 2, 2, -2, -5, -8,-11, -4, 3, -8, -4, 5, -3, - -16, -4, 3,-12, -4, 3, 32, 7, 2, 8, 32,-18, -1, 12, 1, 7 }, - { 0, -8, -1, 0, -8, 7, -8, -1, -1, 4,-12, -1, 3, 0, 1,-18, - 8, 8,-14,-10,-11, 19, 9, 5, -7, 6, 8, -4, 26, 12, -1, 6 }, - { 3, 5,-14, 7, 14, 8, 20,-13,-16,-10, -2, 17, -7, 4, -8, -9, - 14, -5, 3, -4,-12, 7, 14,-10,-19,-20, 35, 8, 13, 14, -2, 9 }, - { -2, -4, -1, 1, -3, 0, -1, 1, 2, 2, 6, 0, 0, 4, 5, -2, - 3, 3, 3, -2, -7, -3, -3, -1, 6, -2, 29, 22, 13, 34, 0, 14 }, - { -3, -9, 3, 1, 5, -4, 2, 0, 7, -9, 0, 2, -5, -3, 0, 6, - -1, -1, -1, 2, 2, 4, 8, 7, 20, -6, 7, 16, 33, 20, 6, -1 }, - {-11, 1, -3, -3,-11, 3, -9,-25, -1,-16, 4, -8, 15, 1, -2, 7, - 8, 23, 2, 18,-13, 16, 3, -7, 6, 3, 16, -8, 12, 16, 3, 4 }, - { 0, 5, 5, -5, 1, -1, 2, -3, -2, 1,-13, 2, 2, 10, 6, 7, - 18, 18, 7, 9, 8, 9, 21, 14, 7, 12, 15, 14, 15, 12, 11, 5 }, - { 1, -5, 11, -2, 17, 8, 3, 0, -1, 6, 11, -7, 6, 6, 7, 5, - -15, 14, 1, 11, 4, 10, 12, 1, 2, 4, 30, 1, 11, 1, 6, 13 }, - { 2, 4, 3, -7, 5, 8,-11, 7, -5, 9,-10, 6, 8,-10, -3, 10, - 1,-29, -4,-26, 5, -8, 13, 4, 3, 6, 35, 1, 3, 6, 3, 0 }, - { -2, 1, 0, 0, -1, -3, -7, -3, -9, -3, -1, -6, 3, 4, 4, 0, - 5, -1, -2, -2, -1, -4,-10, 8, 0, -6, 10, -4, 46, 12, 2, 28 }, - { 4, -1, 4, 1, 0, 4, -2, -2, -2, -1, 2, -4, 1, 5, 0, -3, - 1, 1, -2, 0, 1, -2, -1, -1, 3, -6, 35,-11, 13, 53, -3, -1 }, - { -5, -2, 0,-13,-16, 5,-12,-11, 1,-30, 3,-18,-24, -8, -5,-19, - 1, -3, -8, 7, -7, -8, 15,-19, 4, 10, 30, 24, 6, 1, -9, 10 }, - { -4, 8, -7, -4, -6, 12, -1, -9, -4, 2, -9, 3, 2, -2, 4, 2, - 22, 9, 4, -5, 0, 5, -2, -9, -3, 1, 18,-12, 18, 16, 4, 16 }, - { -5, -8, -3, -5, -3, 6, -7, -3, -2, -5, -3, 1, 2, 2, 4, -6, - 10, 3, 12, -3, 20, 0, 27, -4, 16, 5, 18, -3, 23, 4, 12, 11 }, - { 0, 1, 0, 1, -2, 1, 2, 1, -1, 0, -2, 2, -2, -4, 1, -2, - -2, -1, -5, -2, 0, 0, -2, 2, 9, 7, 63, 5, 12, -1, 1, 0 }, - { 4, -3, -7, -5,-11, -5,-12,-10,-10,-12,-15,-12,-14,-14, 1, 1, - 10,-10, 16, 6, 2, 9, 11, 9, 9, 8, 12, -1, 13, 12, 6, 3 }, - { 7, -3, -2, 4, 6, -8, 2, -3,-12, -5, -9, -8,-10, 15, -2, -4, - 8, 9, 7,-13,-18, 34, -5, 7, 12, 22, 16,-11, 13, 25,-15,-11 }, - { -3, -2, 0, -4, 1, 0, -3,-13, -7, 13, 12, -7,-10, 13, 19, 6, - 16, 15,-12,-15, -3, 34, 1, 5, 1, -9, 11, 21, 8, 17, -5, -6 }, - { 3, -5, 0, -4, 0, 4,-11, 4, -7, -3, -1, -8, 3, -2, 2, 1, - 11, 5, 6, 14, -3, 2, -4, -7, 0, 31, 15, -2, 24, 11, 5, 4 }, - { -1, -4, -9, 5, -8,-18, -4, -9,-20,-18, 7,-14,-16, 3, 8, -3, - 29, 11,-13,-13, 7, 1, 17, 6, 6, 21, 11, 1, 14, -8, 2, 5 }, - { -3, 8,-10, -6, 12, 2, 1, 3, 3, 3, 3, -6, -8,-14, 15, -5, - 16, 4, 16, 0, 7, -1, 0, 16, 2, 1, 22, 4, 19, 13,-11, 1 }, - { 2, -3, 10, 20, -4, -1, -8, 5, -8, -9, -6, -2, -4, -7, 8,-10, - 0, 8, -6, 1, -8, 14, 13, 5, 17, -6, 26, -1, 7, -1, 0, 12 }, - { -4, -7,-31, -2, -7, -1, 5, -5, -5,-12, 4, -7, -6, 3, 15, -2, - 5, -2, 7, -1, 10, 7, 8, -1, 14, 20, 14, 9, 16, 16, 8, 24 }, - { -7, 0, -3, -6, 1, 3,-13, -6, -4, -4, -5, -9, -1,-10, -4, -8, - 2, 0, -1, 1, 24, 24, 21, 31, 5, 2, 11, 12, 7, 4, 3, 6 }, - { -3, -5, 6, -4, -3, -1, 2, -1, -2, 1, 0, -8, -1, 2, 0, -4, - 6, 22, -1, -5, 8, 12, -1, -2, 28, 27, 20,-27, 14, 1, 2, -3 }, - { 1, -5, -2, -2, 6, -2, 9, 1, -2, -5, 3, 4, 11, 5, 2, 8, - -3, -1, 1, -2, -3, -5, 5, 8, 49, 12, 8, -3, 9, 20, 12, 17 }, - { -6, 0, 1, 7, 0, 9, -2, -4, 8, 0, -2,-10, 0, 7, 21, -1, - 0, 1, 17, -7, -5, 2, 4, 16, -2, 17, 14,-20, 15, 14, 4, 15 }, - { 0, 3, -4, 9, -4, 0, 6, 4, -6, -6, -5, -7, 2, -9,-10, -2, - -5, 0, -3,-21, 9, 14,-11, 13, 29, 2, 25, 4, 22, -1, 2, -3 }, - { 2, 12,-11, 2, 16, 9, -4, 7, 1,-10,-15, 11, -4, 3, -2, 4, - 4, -5,-10, 1, 4, 19,-15, 6, -4, -2, 30, -7, 11, 21,-12, 5 }, - { -2, -3, -2, 4, -1, -5, -3, -7, -5, 1, 0, -6, 1, -6, 7, 0, - 8, -7, -3, -2, 2, 14, 2, -3,-26, -1, 26, 22, 32, 1, -2, 6 }, - { 1,-38, -1,-20, -2, -3, -6, -4, 2, 2, 7, 0, 3, 5, 3, 10, - 6, 1, -3, -5, 7, 5, -5, -4, 8, 3, 1,-14, -1, -9, -5, -4 }, - { -5,-26, -7,-19,-10, -5,-11, 5,-11,-25, -8,-14, -9,-16, -8, -6, - -17,-14, -1, -1, 6, 2, 2, 2, 3, 0, 2, 8, -8, 3, 0, -3 }, - { 17,-49, -3,-23, -1, 11, 7, 3, 4, -4, 0, 0, -1, 4, 2, 4, - -2, -4, 2, -2, -1, -2, 2, 0, 0, -1, 0, 0, 1, 2, 0, 0 }, - { 4,-34, -6, -9, 1, 21, -7, 3, -2, -1, -3, 18, 2,-16, 7, -3, - 8, 7, -5, 7, 2, 4, 8, -6, -7, -2, -5, -1, 4, 1, 2, -4 }, - { 5,-29, 13, -2,-14, 3, 1, 18,-15, 4, -8, 8,-10, 8, 2, 1, - -8, 15, 3,-10, -4, -4, -2, 0, -3, -4, 2, -3, -4, -3, 12, -6 }, - { 13,-20, 3,-18,-17, 4,-14, 13, 28, 11, -8, -6, 16, 6, 0, 10, - 3, 4, -9, 13, 5, -7, 12, -5, 0, -7, 5, 1, 3, 3, 2, 1 }, - { 3,-27, -5,-11,-21,-11,-12, 0, -5, 7,-22, 1, 3, 5, 0, -5, - 8, 7, 1, -5, -7, 2, -5, 4, 1, 3, -8, -2, 0, 4, -2, 6 }, - { 31,-45, 0, -1,-12, 1, 2, -6, 4, 3, -1, 3, 3, 0, 5, 3, - -5, 12, 4, 6, 2, 1, -2, 1, 3, 2, 5, 2, 2, 2, 3, -1 }, - { 9,-45, 6, 5, -1,-17, -2, 18, -3, 2, 0, 1, 0, -1, 10, 8, - -7, -2, -5, -8, 6, -1, 0, 4, 6, -3, 12, -1, -2, 0, 5, -7 }, - { 3,-26, -2,-12,-12, 2,-10, 16, -3, 12, 4, 5, 11, 8,-16,-17, - -2, -3, -3, 2, 5, -9, 13, 1, 10, 11, 3, 5, -2, 2, 2, -7 }, - { 8,-26, 32, -7, -5, 22, 2, 14,-10, -8, -7, 3, 3, 7, 0, -5, - 0, -1, -3, 0, 8, 4, -5, -7, 6, -1, 4, 8, 1, 1, 7, -6 }, - { 4,-31, 2,-14, 2, 0, 1, 8, -6, -1, 17, -3, 13, -6, 5,-10, - -2,-10, -2,-10, -3, 7, 1, 5, -8, 8,-14, -3,-15, 7,-10, -6 }, - { 16,-27, 13, -4,-23, 7, -9, 6, -7, 5, 4, 2, -1, -3, 23,-18, - 7, 0, -3, 4, -3, 9, -6, -2, -1, 8, -6, 2, 6, -3, 2, -2 }, - { -1,-35, -2, -8, 11, -1, -7, -3, -2, 11, 7, 6, -6,-10, 9, 6, - -3, -5, -6, -3, 9, 16,-16, -9,-20, 12, 3, 5, -3, 1, -9, 4 }, - { 2,-24, 1,-12,-16, 5, -4, 3, -4, -1,-11,-11, -8,-14, 14, 10, - -8, 20, 8, -3,-11, 1, 1, -4, -4, -7, -3, 15, 2, -6, -2, 7 }, - { 9,-21, 2,-19, -7, -5, -8, 25, 3, 17, 5, -3, 9,-12, 8, 2, - -4, 3, 3, 1, 11, -9, -4, -3, 4, 3,-22, 6, 4, 6, 11, -5 }, - { 16,-23, 13,-17,-21,-12, 5, 9,-20, 7, 6, -6, 0, 2, -9, 6, - -6,-13, -7, -1, 5, -3, 5, -7,-10, 1, 0, 8, -9, 11, 0, -8 }, - { 10,-26, -9, -7,-19, -4, 6, 16, -7, 5, -4, 4, 8, 0, 4, -1, - 6, -7, 1, -8,-11, 10,-14, 0,-16, 6, -3, 5, -1, 14, 12, 1 }, - { 8,-27, 12,-14, -1, -1,-19, 10,-11, 21,-14, 9, -8, -3, 8, -1, - 12,-13, 3, -4, -2, 0, -9, 0, -7, 2, -3, 12, 1, -3, 3, 1 }, - { 18,-20,-14,-14,-16, -3,-24, 6,-17, 2, -3,-11, 2, -3, 12, 10, - 10, 1, 10, 7, 8, 5, 5, 4, -1, 7, 2, 2, 0, 4, 7, 0 }, - { 0,-30, 9,-16,-18, 15, 12, -3, 4, -4, -5,-11, -4,-12,-10, 0, - 2, -2, -4, -1, 2, 0, -1, -6, 2, -3, 4, -5, 7, 3, 5, 7 }, - { 25,-24, -1, -6, -9, 6,-13, -2, 3, 15, -3, 11, 4, -8,-11, 2, - 0, -9, -2, 7, 4, 8, 5, -8, 5, 6, -1,-11,-15, -5, 0, 11 }, - { 0,-34, -7,-11, -7, 9, -3, 19, 4, -8, 3,-11, 11, -3, -9, 12, - 9, 9, 2, 1, -7, 1, -3, 0, -6, -2, -1, 3, 0, -7, -2, -5 }, - { 6,-34, -4, -5, -3, -9, 2, 9, -1, 9, -5, -3,-26,-12, 8, -6, - -7, 11, -8, 4, 4, 1, -1, 0, 8, 9, -4, 7, -1, 1, -3, -1 }, - { 3,-30, 5, 6,-10, 3, -7, 6, 3, 3,-26,-19, -3, 1, 7, 5, - -4, -5, 6, 10, 13,-10, 4, -7, -4, 5, -3, 9, -6, 3, 9, 5 }, - { 4,-24, 9,-19, 2, -4, -5, 8, -3, 2, 0,-15, -1, 9, -4, 22, - 6, 9, 3, 7, 11, -9, 0, -3, 4, 5, -5, 10, -8, 5, -7, -3 }, - { 8,-27, 7, -3, -1, 2, -9, 13, 7, 12, -4, -6, -6, 5, 0, 7, - 5, 1, 15, -3, -4, 0, -5, -2, 7, -5, -7, 1, -2, 13, -8, 13 }, - { 17,-22,-15,-11, -8, 16,-14, 18, 2, -1, 14, -7, 14, -6, -6, -7, - -8, 17, 6, 4, 4, -7, -5, -9,-14, -6, -1, 9, -3, 1, 6, -5 }, - { 25,-30, 2,-12,-13, 18,-18, 16, 8, -3, 10, -8, -3, -1, -6, 3, - -5, -7, 4, 6, 7, 1, 1,-11, -5, 6, 2, -4, 9, -1, -5, -2 }, - { 7,-23, 7,-15, -1, -3, -1, 0,-10, 12, 2, 5, -4, 0, 4, 6, - -1, 5, -9, -1, -1, -7, 1, 17, 9,-17,-16, 8, 4,-14, 11, 14 }, - { 0,-31, 7,-13, 3,-11, -7, 6, 1,-11, 8, -7, 15, -3, 16,-11, - -1,-15, 16, -3, 5, 0, -2, -2, -6, 11, 5, 6, 5, -5, 6, 3 }, - { 13,-24, -2,-20,-10, 7, -3, -1, 15, 2, 6, -5, -7,-10,-20, 1, - -4, 14, 8, -2, 3,-13, -3, 1, -4, 1, -3, 2, 8, -7, 16, -4 }, - { 1, -2, -2, -3, -4, -7, 0, 3, 6, 7, 3, 2, 1, -2, -1, 0, - -6, 4, 2, -4, -3, -4, 5, 9, 5, 0, -3, -3, -4, -7,-31,-50 }, - { -1, -3, 7, 2, -1, 2, 4, 6, 0, 10, -2, 0,-20, -6, -3, 9, - -20,-22, -1, -1, 15, 9,-12, 10,-13,-20, 12, 3, 5, 6, -7,-26 }, - { 0, 4, -2,-14,-12, 6,-13, 11,-10, 3, 22, 6, 16, -2, -5, 1, - -3,-11, 0, -7, 5, -5, 0, 1, -1, -6, 8, 8, 10, 9, -5,-27 }, - { -5, 10, -2, 7, 9, -9, 5, -9, 5, 4,-15, 14, 1, 3,-10, 5, - 0, -2, 7, 3,-13, 6, 9, -6, 5,-14,-17, -1, 11, 14, -2,-26 }, - { 0, 6, -3, 0, -8, 6, 0, 1, 4, -8, 2, -5, 4, 7, 15, 11, - 9, 19, -2, 14, -8, 7, -1, 3, -3, -3,-10, -2, 12, -2,-12,-29 }, - {-12, -5, 0, -3, -2, 6, 3, -3, 2, -2, 1, 11, 2, -7, 5, 1, - 2, -2,-14, 0, -1, -5, 3, 8,-28,-26, 6, -6, 3, 8,-10,-27 }, - { -1, -3, 6, 2, 4, 15, 1, 0, 2, -2, -2, 13, 3, 6, 0, 6, - -1, -4, -1, -5, 8, -1, 5, -5,-15, 11, -8, -5, 14, -6,-14,-29 }, - { -5, -6, 0, 1, 0, 6, -3, 2, -5, -1, 5, -3, 2,-10, 3, 4, - 3, 0, 13, -3, -1, 4, -4, -6, 2, 9, 8, 2, -3, 28,-11,-31 }, - { 1, -4,-10, -9, -4, -3,-15, -6, 1, 5, -3, -6, 5, -6,-22, 27, - -13, 5, 3, -7, -4, 20, -7,-12, -1,-24, -4,-13, -8,-11,-15,-21 }, - { -6, -4, 19, -6, 2, 11, -6, 1, -3,-10, 9, -9, 12,-10, 2, 1, - -9, 1, 15, 7, -5, 5,-29,-35, 4,-30, 9, 9, 19, 17, 2,-17 }, - { -3, 3, -3, 1, 2, 5, -1, 5, -2, -3, 1, -3, -8, 3, -4, -2, - -4, -1, 12, 0, 2, -8, -6, -4, 16, -1,-14, -2, 25, -6,-15,-36 }, - { 0, -1, 3, -4, -4, -1, 7, -4, 8, 0, 10, 9, -4, 1, 10, -1, - -3,-13, -5, -4, -1, -4, 8, 11, 14, -7, -5, 16, 12, 13, -1,-28 }, - { 1, -2, 2, -3, -8, 10, 4, 9, 12, 3, 5, 0, 8, -3, -6, 2, - 16,-11, 11, 0, 1, 6, 1, 18,-10,-16, -1, -4, 5,-14,-15,-20 }, - { 1,-12, 5, 4, -7, 8, -1,-17, -2, -9,-14,-11, 6, -9, 5, -4, - 3, -2, 7, 18, -5, 5, 6, -1,-11, -2,-10, -3, 8, -3, -2,-32 }, - {-12, 5, 20, -5, -6,-11, -6, -6,-13, 4, -6, 19, -8, 2, 3, -9, - -4, -4, -1, 9, -1, 21, -1, 7, 15,-10, -1, -3, 9, -3, 2,-24 }, - { 0, -3, 2, -6, 4, -1, -9, -2, -1, -3, 6, -1, -5, -6, -5, -8, - 0, -2, -6, 9, -4, 3, 2,-13, 1, -7, 23,-13, 4, -3,-15,-33 }, - { -7, 2,-15, 11,-10, 14, 0,-11, 3, -1, 12, -4, -4, 9, 11,-13, - -13, -3,-14, 1, 3, 6, -5, 8, 0, 5, 5,-10, 4, 5, -6,-30 }, - { -6, 4, 0, -5, 4, 1, -1, -1, 3, 6, 5, -2, -5, 0, -2, 5, - -4, -2, -4, -2, 4, 7, -7, -1, 1, -4, -3,-19, 37, 12, 10,-40 }, - { -7, 2, -7,-12, 17, 11, -7, 2, 2, 3, 1, -1, 3, 4, -2, -5, - 9, -9, 6, 4, 9, 12, 11, -5, 2, -1, 0, 9, 5, -7, -2,-24 }, - { -7, 6, 1, 3, 1, 0, 6, 0, 4,-12, -2, -2, 1, -9, 10, -2, - 11, -1, 21,-12, 15, -5, 10, -5, 5, -5, 14, -6, 5, -7, -3,-29 }, - { -2, 0, -5, -2, -3, 1, -3, 0, 4, 2, 3, 0, 2, -2, 7, -2, - 3, -5, 2, -1, 6, -4, 0, -3, 8,-11, 19, -8, 22,-34, 13,-35 }, - { -1, -3, -1, 9, 11, -3, -3, -1, 7, 18, 11, -5, 2,-12,-11, 18, - 9, -5, 1, -6, -9, 12, 1, -3, -3, -9,-14, 9, 9, 8, -6,-26 }, - { 0, 5, -5, -1, -1, -2, 4, 6, 8, 2, -1, -2, 5, 1, -5, -4, - 1, 1, 18, 1, 7,-10, 3, -2, 12, -1,-15, 9, 12,-14, 13,-38 }, - { 3, 0, -8, -1, 0, 8, -9, -3, -8, 16, 3, 16, -5, -9, 0, -1, - -7, -1, -4, 13, 7, 0, 1, 2, -1,-16, 0, -2, 1, 8, -8,-28 }, - { 7, 9, -5, -3, -2, 2, 0, 3, 11, -6, -4, -2, -2, -5, 28,-18, - -6, 2, 15,-10,-15,-10, -2, 0, -2, -2, 4, -3, 7, 11, 5,-30 }, - { 9, 0, -7, -1, -4, -7, 2, 2, 9, -2, 2, 3, -8, -6, -6, 3, - -10, 4, 10, 5, 21, -4, 14,-18, 1, 3,-10, -2, 6, 14, -8,-26 }, - {-14, -1, 2, 3, -3, 7, 1,-22, -1, -1, 0, 1, 12,-14, 3, -5, - 0, 10, -3, 1, -5, 12, -3, 10, -8,-22,-11,-13, -7,-10,-13,-25 }, - { -2, -5, -4, -4, -9,-18, 9, -3, -5, 17, 13, 5, 6, 11, 3, 8, - 20, 4, 2, 9, 8, 5, 6, 1, 7, -7, -6, -2, -7, 0,-17,-23 }, - { -5, -5, 2, 0, 6, 2, -2, 2, -3, 4, 4, 0, -5, -2, -4, 6, - 8, 10, -1, 1, -5, 5,-14, -2,-11, 8, 6, 25, 7, -1, 0,-43 }, - { -4, 0, 4, -2, 7, 0, 3, 17, 5, 2, -5, 1, 21, 3, -2,-10, - -16, -9, 7,-12, 9, -8, 2, 5, -5,-10, -2,-11, -5, -1, -9,-30 }, - { -2, 3, 1, -4, -1, 0, 8, 1, 12, 4, -1, -1, 3,-17, 13, 9, - 0, 7, -6, -5, 9, 1, 5, 4,-10,-18, 0, 14, 11, -4,-16,-28 }, - { -1, 0, 2, -1, 4, 1, -1, 1, -1, -2, -1, -2, 3, 0, 0, -1, - -1, 1, 2, -2, 3, 3, -2, 4, -2, -1, -6, 1, -1, -1, 6,-70 }, - { 7, 3,-11, -1, 12, -4,-14, 4, 4, -4, 4, -2, 2,-12, -4, 15, - -17, -4, -3, 6, 8, -5, 22,-22, 5,-11, 15, -4, 4, -1,-21, -1 }, - { 10, -2,-13, 11, 4, 14, 4, 9, 8, 8, 19, 15, 14, 15, 5, 10, - 8, 15, -5, 4, 14, -8, 1, 1, 2, 1, -1, -3, 21, 8,-29, 13 }, - { -6, 0, -6, 6, -1, 2, 8, -4, -5, 4, -4, -5, 0, -2, -4, 0, - 9, -2, 1, -2, 26,-19, 21,-10, 4, 1, -8, 5, 22,-10,-13, 15 }, - { 11, -5, 1, 0, 6, 3, 7, -2, -2, -3, -5, -1, -2, -6, 1, 1, - -8, -5,-13, 13, -2, -3, -1, -9,-28, 4, 2,-11, 18,-20,-24, 9 }, - { 7, 4, -3, 6, 6, -6, -7, -5, -7, -4, -4, 0, -7, -5, -6, -5, - 2,-13,-12, 2, 0, 5, 18, 15,-13, -7, 13,-20, 16,-10,-19, 6 }, - { 5, -8, -1, 5, 10, 2, -1,-10,-11, 23, 8, -5, -8, 4, -5, -4, - -5, -5,-11, -8, 5, 1, 7, -9, -9, -6, 12, 14, 17,-12,-22, 3 }, - { -5, -8, -3, 3, 12, -1, 0, -4, -5, 1, 1, 6, 1, 5, -5, 7, - -2, 7, 1, 6, 6, 2, 0, -5, 17, -4, -5,-24, 13,-20,-27, 14 }, - { -1, 2, -3, 1, -3, 1, -3, 0, -2, 3, -2, 1, 2, -1, -2, -1, - -2, -5, 5, -2, 0, -7, 1, -6, 8, 8, 11, -5, 24,-43,-13, 2 }, - { -2, 4, 7, -3, -4, 4, 13, -4, 0, 0, -2, 9, 0, -3, -6, 1, - -7, 1, -1, 10, 0, 5, -1,-24, 25,-15, 7, 2, 22,-10,-21, 0 }, - { -5, 2, 6, -2, 13, 3, 5,-12,-11, 16, 6, 10, -5, 0, -3, 6, - 5, -5, -5, 10, 12, 10, 11, -7, 8,-14, 2,-15, 13,-14, -8, -3 }, - { 5, 6, -7, -5, 5, 2, 9, 5, 0, -1, -4, 2, 8, 0, 3, 5, - -12, 3, -3, -6, 2, -1, -5, 14, 11,-20,-21,-25, 24, -1,-10, 6 }, - { -5, 5, -2, 9, 4, -4, -1, -6, 11, -6, 5, 0, 2, -3, 6, -1, - -17,-18, -4,-13, 9, -1, 9, -7, -4, -8, 2, -3, 12,-31,-18, 5 }, - { -7,-11, 6, -8, 4, -3,-12, 0, -1, -6, -3, 0, 5, 9, 7, 2, - 1, -8, -6, 8, 2, -5, 7, -1, 16,-10, 16,-12, 18, -1,-25,-12 }, - { 3,-12, 1, 2, -2,-18, -8,-15,-10, -9, 2, -7, 11,-11, 2, -1, - -1, -1, -9, -6, 3,-14, -2, -1, 2,-13, -7, -9, 19, -5,-17, 2 }, - { 7, 1, -8, 7, 17,-13,-10, 5, 7, 1, -6, 4, 9, -4, 0, 3, - 8, 1,-14, -9, 4, 7, -9, 0, 6, -5,-12, -2, 25, -2,-19, 1 }, - { 7, -3, 6, -3, 1, 6, -7, 0, 10, 0, 4, -5,-17, -4, 4, -1, - 0, -3, -7, 19, 24, -1, 21, 8, 10, 9, 8, -1, 23, -2,-18, -2 }, - { 3, -3, 0, 5, 8, -2, -9, 2, 9, 6, 19, 8, 2, 6, -9, -2, - -4, -3, -8, 7, -7, -8, 5, 4, 26, -6, 7, 18, 24, 0,-13, 4 }, - { 0,-13,-11, -1, 3, -9, 5, 4, -7, 3, 0, 2, -1, 4, -5, 2, - 9, -2,-11, 15, 1,-21, 1, -1, 0, 4,-14, -4, 24,-16,-13, 1 }, - { 1, -9, -8, 0, 0, -4, 11, -1, 14, 16, 0, 17, -2, -9,-12, 0, - -1,-14, -9,-14, 0, -2, 19, 4, 6, 4, 4,-11, 8,-17,-19, -5 }, - { -3, 1, 2, 12, -4,-18, -1, -4, -7, 14, -3, 2, 0, -7, -8, 12, - -5, -9, 14, 12, -9, -2, 4, -6, 4, 18, -1,-25, 22, 2,-23, -5 }, - { -2, 0, 0, 0, 1, 3, 5, -1, 5, -2, -2, 2, -3, 0, 1, 2, - 0, -1, 2, -1, -9, -6, -7, -4, -2, 4, -7, -5, 64, -3,-25, 4 }, - { 12, -2, -3, 0, 8, -9, 13, -7, 6, -3,-12, 12, 15, -9, -4, 2, - 9, -4,-12, 3, 14, 1, 7,-15, 15, 0, -6,-12, 0, -3,-20, 6 }, - { 2, -1, -4, 5, 9, 6, -7, 2, -2, -7, -2, 0, -1,-18, -4, -6, - -15, -5, 11, 5,-10, -1, 2, 7, 12,-19, -7, 8, 21, -4,-15, 4 }, - { 4, 2, 5, 5, -5, 1, 3, 2, -8, 13, 0, -5, -2,-14,-11, 6, - 2, 17, 8,-13, 26, -2, 5,-15, -4,-14, 12, -9, 13,-21,-23, -4 }, - { 2, -3, -2, -3, 3, -2, 6, 9, -9, 13, 4, 2, 12, -3, -3, 1, - -17,-22, -3, 4, 3, -2, 1, -9, 1, -6, 11,-13, 14, 0,-15, 6 }, - {-16, -4, 17, -2,-20,-11, 11, 10, 5, -8, 16, 2,-17,-14, 11, 11, - -6,-11, -7, 12, 12,-10, -6, 5, 8, -4, -2, -5, 28, 3,-13, 4 }, - { 0, -3, 3, -7, 6, 8,-12, 20,-19, 18,-11, 10, -5, 0, -9, 11, - 3, 0, -2, 9, -7, -5, 18, 3, -2,-16, 1, 6, 12, -7,-16, 1 }, - { 4, 1, 5, -5, 15, 2, -8, 3, 5,-11, 15, -3, 8, -8, -1, 7, - 4, 7, -2, 6, -9, 5, 12, 2, 33, -2, -6,-18, 4, 0,-18, 11 }, - { 3, -1, 1, -1, 0, 1, 4, -1, -5, 0, 1, 0, 4, 2, -1, 4, - -3, 2, 0, -2, 4, 6, -1, 6, 42, 19, -4,-37, 19, 1,-15, -4 }, - { 2, 0, -5, 0, 10, 0, 0, -5, 3, 0, 0, -3, -3, 0, 2, -4, - -10, 2, -6, 4, 4, 1, 27, -7, 17,-34, 5, -9, 15,-16, -7, -5 }, - { -2, 7, 7, -2, 9, -2,-15, 11, 11, 7, 5, 1, 15, 1, -9, 31, - 2,-15, 2, 4, 3, 4, -1, -8, 2, -7, 6,-17, 11,-14,-11, 2 }, - { 1, 1,-11, 9, 9, -6,-14,-11,-10, 8, -3, 11, 16, -9, -8,-13, - -8, 9, 0, 6, 6, -2, 13, -8, -2, 3, 13, -3, 10, -6,-17, 4 }, - { 14, 5, 4, -6,-12, 10, -7, 8, 21, -8,-30, 15, -2, 1, 11, -9, - -5, 1, 0, -1, -1, -6, -2, 3, -5, 7, 9, 5, -5, 2, 0, 1 }, - { -1, 2, 20,-17,-15, 3, 3, 7, 11,-17,-13, -6, -3, 18, 17,-15, - -4, -4, -5, 22, 14,-14, -2,-10, -7, 11, 8, -7, -3, 0, -7, 11 }, - { 7,-11, -7, -8,-14, 22, 5, 2, 6, 13,-12, -2, 10, 3, 0,-21, - -4, 20, 3, 10, 21,-10,-12, 8, 11, 2, -5, 2, 1, 3, -1, 15 }, - { -1, -2, -1, -2,-13, 8, -4, 0, 7, -2,-17, 8, 18, 5, 3, 8, - -8, -2, 3, -4, 14,-18,-13, 14, 15,-13, -1, -2, 4, 11, 1, 12 }, - { 13, -6, -4,-16,-17, 16, 21, -2, 5,-11, -9, 19, 21,-17, -3,-17, - 3, 12, 8,-12, -6, 1, -7, 9, 9, -7, -5, -1, -3, 5, -6, -4 }, - { 11, 5, 12,-20, -6, 10, 4, 12, 8, -5,-10, 15, 13, 14, 10,-15, - -13, 1, 6, 14, 15,-17,-13, 4, -5, 10, 7, -6, -8, -3, -4, 12 }, - { 25, -1, 7, -5, -7, 11, 1, 17, 13,-15,-14, -4, 5, 3, 8, -3, - -2, 2, 0, 6, 16,-12, -6, -4, 4, -3, 7,-10, -3, -7,-13, 7 }, - { -8, 10, -3,-13, 5, 2, 4, 9, 9,-17,-13, 2, 11, 1, 6, -4, - 8,-10, 4, 1, 19,-15, -4, 12, 31, 7, -5,-17, -4, 9, -2, 7 }, - { 14, -6, -6, -6,-14, 13, 17, -5, 4,-14, -9, 7, 7, -9, 3,-16, - -15, 11, 11, 6, 4,-11,-19, 3, 5, 8, 13,-14,-14, 3, -4, 12 }, - { -2, -4, 10, -4, -7, -1, 27, 5, 2,-16,-18, 4, 12, -2, -3, -2, - -1, 1, -8,-12, 3, -4, 8, 15, 2, 4, 9,-13,-14, 9, -7, 5 }, - { 4, 2,-10, -5, -7, 2, 1, 4, -1, -6,-15, 6, 1, 10, 5,-10, - -9, -1, 13, -3, 5,-21,-11, 8, 8, 5, 27,-21,-18, -5, -1, 15 }, - { 11, 1,-16, -8,-11, 0, 5, -8,-12,-13,-17, 22, 4, -6, -1,-18, - -10, 0, 19, 2, -2, -8, -7, -3, 2, -2, -9,-17, -5, 4, 4, 10 }, - { 8, -6,-19, -5, -4, 12, 14, 15, 10, -9, -1, -9, 19, 12, 0, -1, - 2, 4, 7, 9, 16,-16,-14, 9, -4, 3, 1, 0, -2, 10, -1, -1 }, - { 12, -8, 12, -9, 0, 25, 7, 9, 2,-31, -9, -4, 15, 4, -5, 1, - -10, 11, 8, 10, 0, -6, 5, 11, -1, -6, 4,-10, -9, 6, 4, 5 }, - { 14, 6,-17, -2, 17, 12, -9, 2, 0,-25,-14, 5, 20, 14, 8,-20, - 5, 2, -2, -3, 9,-13, -3, -1, -6, 3, 7, -6, 0, 2, 3, 1 }, - { 8, 4,-15, -3, 10, 18, -4, 13, 8,-22,-10, 9, 19,-15, 7, -5, - -13, 12, -4, 9, 2, -9, -6, 0, 2, 1, -9, -6, 6, 1, -1, 11 }, - { 4, 1, 4, -5,-10, 18, 7, 2, -4, -9,-11, 0, 32, -7, 4,-16, - -1, 0, 6, 3, 6, -3,-14, 16, 9, -2, 7, -1, 0, -5, 5, -3 }, - { -3, 2, 3, -8, -6, 4, 6, 2, 4,-12,-15, 2, 8, 8, 9, -3, - -18, 6, 34, 11, 12,-15, -1, 2, 9, 2, -4, -4, 2, 4, 2, -3 }, - { 18, -6,-12, -8, -1, 15, 20, -4, -1,-11, -5, 6, 6,-11,-15, -7, - 3, 7, 10, 2, 8,-10, -5, 8, 15, -5, 5,-17,-13, 13, 11, 7 }, - { 8, -4, -6, -1,-14, -3, 6, -2, 1, -5, -1, 10, 10,-15, 5, 0, - -10, -4, -3, 7, -4,-19,-15, 27, 11, 18, 3,-19, -2, 6, 0, 12 }, - { 12, 0, -5, 0, 4, -5, 1, 5, 10, -7,-11, 21, 29, 1, -2, 1, - -4,-11, -1, 13, 11,-20, -1, 4, 4, 4, -5, 6,-13, -2, 11, 9 }, - { 2, -7, -7, -3,-10, -1, 20, 12, 1,-19,-19, -1, 5, 4, -7,-25, - 14, 1, -3, 2, 12, -4, -3, -3, -2, 6, 1, 0, 3, 2, 5, -1 }, - { 12, -8, 3,-12,-10, 10, 13, 0, 23,-14,-18, 10, 0, 15, 3,-12, - -3, -5, 5, -4, 2,-14,-10, 8, 2, 9, -1,-11, -3, 5, 13, 2 }, - { 9, -6, 7, -7,-30, 17, 6, 13, 1,-14, 0, -1, 6, -9, 8, 3, - -4, 0, -1, -7, -5,-13,-19, -3, -4, 4, -6, -2,-13, 1, -2, 3 }, - { 10, 1, 3,-18,-26, 17, 4,-16, 4, -3,-13, -4, -6,-11, -4,-21, - 7, 8, 2, 5, 13, -6, 1, 5, 8, 7, 9, -6, -6, 1, -1, 2 }, - { -3, -1, 0, -2, -2, 0, -1, 3, 4,-14, -8, -9, 13, 2, 50,-23, - -8, 8, 7, 11, 16, 3, -7, 0, -2, 6, 5, -1, 1, -2, 4, 3 }, - { 1, 3, 1, 1, -6, 3, 6, 6, 2, -2, -3, 10, 2, -8, -5, -5, - 5, 4, 4, -2, 10, -8,-40, -1, 21, 8, 3, -4, -1, 13, 4, 7 }, - { 2, 0, -4, -8, 5, 2, 7, -5, 5, -8, -4, -1, 12, 2, 12,-13, - -9, 0, 1,-12, 9,-43, 1, -5, 12, 1, 3, 6, 1, -1, 3, -2 }, - { 6, -2, -1, 1, 0, 4, 8, 14, 4, -7,-23, -5, 23,-17, -6,-15, - -8, 7, 10, -1, 7,-16, 4, -6, 2, 3, -3, -3, -1, 8, -1, 4 }, - { 10, 4, -4, 1, 7, -3, 2, 11, 4, -6, -3, 8, 5, 4, 1,-45, - -6, -4, 4, 2, 1,-14,-10, 1, 1, 6, 2, -8, -1, -3, 3, 3 }, - { 1, -1, 2, -3, -8, 9, 3, 3, -2, -5, -8, 8, 7, -7, -4, -6, - 5, -9, 11, -2, 46, -5, -1, 9, -2, 0, 3, -5, -3, -5, 7, 0 }, - { -4, 1, -2, -1,-11, 11, 8, -3, -2,-10, 0, 4, 9, 9,-17,-17, - -34, -4, -5, -7, -3,-12, -3, 11, 18, 3, -2, -5,-18, -5, -3, 6 }, - { 7, -5, -3, 1, -4, -3, -5, -1, 2, 5, -2, 3,-10, 12,-18, -5, - -10, 12, -9, 4, -6, 2, 0, 16,-17, 15, 14,-12,-10, -2, -9, -1 }, - { 4, -5, -3, -5, -3, -1, 7, 18, -7, 12, 3, 5, -8, -4,-20, 1, - -25, 1, -8, 13,-10, 8,-19, -1, -8, 10, 6, -9, -1, 0, 12, 4 }, - { -4, 5, 0, -1, 2, 5, -8, -2, -6, 4, -8, 9, 3, 2, -7, 4, - -25, 13,-23, 10, 14, 15,-11, 3,-18, 4, 16, -4, 1,-10,-10, 3 }, - { 5, -3, -1, -3, 4, 1, -3, -4, -5, 1,-12, 14, -7, 11,-15, 6, - -6, 24, -4, 13, -1, 15,-13, 8, 3, 7, -5, 2, 2, 0, 3, -7 }, - { -3, 1, 0, 8, 6, -1, 6, 5, -5, -2,-12, 4, 0, -2, -3, 5, - -6, 0, -8, 9,-10, 4,-28, 12,-20, 11,-13, 7,-18, 1,-11, 1 }, - { 1, -4,-15, 5, 0,-13, -5, 13,-11, 4, -4, -5, 5,-14,-16, 0, - -14, 5,-20, 12, 10, -7, -5, 6, 6, 22, 6, -4, -2, 3, 8, 11 }, - { 13,-11, -2, 16, 16, -7, 0, 20, -7, -1, 0, 5, -9, 12, -2, -5, - -22, 5,-10, 12, -6, 11, 9, 21, -8, 15, 4, 0, -8, -4, -4, 10 }, - { 18, -4,-13, 0, 1,-15, -1, -3, 2, 10, -1, 6, 1, -4,-20, -5, - -8, 6, -8, 17, -5, 5,-10, 8,-22, 6, -5, -2, 8,-17, 8, 2 }, - { 1, -2, -9, 6,-31, -8, -8, 8, 0, 5, -9, -4, 2, 3,-12, 11, - -18, 10, -5, 3,-11, 13, -6, 11, -3, 12, -7, 3, -9, -1, 2, 11 }, - { -9, -6, 21, -8,-15, 4,-11, 12,-11, 17, -1, 2, -6, 0,-15, 13, - -12, 19, 0, 2, -6, -3, -9, 10, 3, 17, -2, 5,-10, -3, 0, 1 }, - { 4, -6, 5,-10, 1, -5, 1, 0, 0, 0, 2, 7, -2, 2, -2, 0, - -4, 3, -4, 1,-12, 6,-49, 16,-10, 13, 0, -2, 8, 6, 1, 8 }, - { 5, -8, -7, 9, 13, -5, 7, 0, 10, 11, -4, -3, -1, 13,-14, 6, - -15, -6,-14, 16, 15, 1,-18, -4,-20, 20, -7, -1, -9, -2,-10, 10 }, - {-12, 4, 0, 10, 0, 3, 8, 4,-27, -1, -2, 19, -4, 2,-13, 3, - 1, 9,-12, 1,-22, 19, -5, 4, -9, 12, 2, -9, -8, 11, -3, 7 }, - { 4, -5, 11, -6, 17,-17, 5, -4, -2, -6, 1, -5, 2, 4,-14, 6, - -20, 19,-20, 12,-21, 5,-14, 13, -2, 11, 4, -3, 0,-10, -4, -2 }, - { -2, -1, -3, 8, -9, -7,-22, -3,-24, 13, -2, 10,-15, 5, -9, 4, - -7, 0, -5, 15, -8, 11,-13, 6, -4, 19, -8, 12, -4, 6, 9, 7 }, - { 2, -3, 2, -1, 0, 3, 1, 2, 1, -4, -2, -3, 1, 5,-12, 6, - -16, 14,-23, 10,-14, 17,-15, 16, -2, 9,-25, 9,-10, 16, 4, 9 }, - { -3, 7, -8, -3, 2, 2, -4, -8, -9, 10, 3,-11, 25,-10,-28, 27, - -9, 7,-13, 9, -2, 4,-12, -8,-14, 6, 7,-10, 3, 3, -3, 5 }, - { -8, -3, 1,-10, 8, -3, -9, -4, 13, 7, 2, 4,-10, 4, 3, 7, - -18, 2,-22, 15, 4, 20, -7, 5, -6, 13, -1, 4, -7, -6, 6, 13 }, - { -2, 3, 0, 2, -4, -2, 0, 0, 1, 2, -2, -5, 0, 1, -4, 0, - -2, -3, 1, 2, -1, 2, -8, -1,-24, 68, -3, 8, 3, 3, -1, -1 }, - {-15, -2, -9, -7, -1, 8,-14, 8, 3, 6, 0, -1, -8, 8,-23, 2, - -14, 17,-15, 8, -4, 7,-18, 0, -8, -3, -1, -4,-10, 4, -1, 4 }, - { 8, 0, 2, -7, 0, 5, 1, 3,-11, 4, -8, 14, 3, 20, 1, 26, - -11, 13,-13, 20, -2, 0, -8, 2, -6, 6, -1, 9, 3, -6, -3, 10 }, - { 5, 0, -1, -7, 10, 1, -3, 5, 4, 7, -5, -1, -3, -1, 12, -3, - -15, 7, -9, 22,-19, 8, -9, 4,-23, 13,-14, 6, -6,-14, -4, 7 }, - { 14, -5, -8,-10, 25, 3,-23, -7,-28, 0, -1, -9, 4, 1,-13, 20, - -8, 10,-16, 8, 12,-13,-21, 5,-13, 11, -2, 1, 12, -7, 2,-10 }, - { -5, -4, 9, 5, -6, 35, -7, 8, 15, 2, -1, -9, -6, 2,-18, 7, - -15, 6, -3, 2, 8, 12,-30, 7, -4, 20, 2, 6, 13, -6, -4, 0 }, - { 1, 8, -9, 9, -5, 12, -9, 16, -9, 16,-17, 14,-13, 15,-18, 14, - -15, 17,-12, 14,-13, 7,-16, 13, -9, 5,-11, 10, -9, 6,-12, 13 }, - {-10, -4, 5, 3, 1, 6, 8,-14, -5, 15, 7, 4, 8, 7,-22, 8, - -7, -8,-15, 26, 1, 13, -3, 17, -5, 9, -2, 4, -6, 3, -8, 9 }, - { 8, -3, 2, 3, 3, 1, -2, -1,-11, 8, -4, 0, -6, -5, -1, 13, - -37, 9, 1, -6,-10, -2,-10, 11, 8, 13, -3, -2, -6, 8, -4, 13 }, - { 3, 2, -3, -4, -4, 7, -8, 9, -8, 9,-20, 12,-19, 15,-18, 17, - -15, 7, -1, 20,-11, 6, -6, 3, 1, 9, 2,-14, -2, -2, 2, 1 }, - { -7, 1, -1, -3, -6, 4, 4, -3, 3, -1, 5, -4, 3, 2, -1, 9, - -59, 5, -4, 30, 3, 3, -2, -3, -1, 2, 2, 1, -1, -1, -2, 1 }, - { 0, -3, 2, 0, -1, -8, 0, 2, -3, 4, -4, 1, 10, 6, -6, 8, - -7, 4, 10, 11,-41, 27,-20, 3, -3, 8, 1, 11, -5, -8, 0, 4 }, - { 5, 1, 4, -2, 1, 2, -1, 6, -7, 2, 11, 4, 0, 0, -8, 7, - -10, 0, 0, 8, 2, 10, -1, 1, -2, 44, -2,-21,-12, -3, -1, 2 }, - { -4, 4, -2, -2, 6, -8, 2, 1,-10, 14, 8, 6, 5, 1, -2, 4, - -13, 4, 2, 5, 10, -2,-21, 32, -3, 18, 9, -6, -9, -9, 10, 2 }, - { 9,-16, -6, -2, 1, 4, 22, 2, -2, 1, -3, -2, -9, 3, 16, 19, - -24, -6, -6, -5, -8, -7, 8, -7, -1,-12, 5, -3, 0, 4, 2, -3 }, - { 10, 3,-16, -4, -1, 13, 4, 4, 1, -3, 1, -6,-14, 18, 3, 8, - -8,-28,-16, 4, 4, 2, 12, 7, 9, -4, -4, 5, -1, -1, 2, 2 }, - { -5,-13,-22, -3, -8, 21, -2, -9, 21, -4, -9, 5, -8, 15, 5, 1, - -5, -9, -7, -2, -5, -5, -1, -5, -5, -5, 3, 10, -4, 0, -7, -2 }, - { 5,-10,-18, 2, 20, 4, 13,-10, 8,-15,-11, -3, -1, 16, 10, 9, - -8, 6, 7, -5, 6, 11, 5, 17, -4, 7,-11, 5, -3, -6, 2, 1 }, - { 3, -5,-19, 1, 1, -3, -2,-25,-11,-17, 0,-13, -4, 10, 10, 2, - -5, 4, 0, 3, -3, -5,-10, -2, 13,-22, 0, 3,-11, -5, 7, -1 }, - { 12,-14,-29, 6, -1, 10, 7,-17,-12, 14, 3, 9, -9, 9, 7, 6, - -3,-13, 0, 5, 3, -1, -6, -1, 0, 2, 4,-12, -5, -1, 2, 11 }, - { 12,-15, -7, -2,-12, 17, 20,-16, -2,-12, -6, 15, -6, 12, 11, 9, - 7, -6, 7, -4,-19, 6, 2, 2, 3,-11,-10, -4, -5, -3, 3, 2 }, - { 11,-22, -6, 0, 8, 18, 3,-11, -4, -7,-15,-17,-12, 6, 16, 4, - -9, 4, -5, 3, 6,-16, 10, -7, -7, -3, 5, 0, 1,-15, -4, 5 }, - { 12,-22,-16, 5, -6, 8, 12, -4, -9,-17,-11, 3, 5, 8,-17, 0, - 11, -4,-13, -6, 2, -1, -1, 3, 3,-11,-12, -1, 1, 1, 12, -2 }, - { 8,-10,-33, -5, -3, -6, 1, -7, -8, -4, -6, -1, 5, -4, -6,-12, - -16, -8, 11, 8,-14, 7, 12, 11, 4,-14, -3, 6, -7, -5, -3, 3 }, - { 0, -8, -7, 2, -4, 24, 2, -9,-11, -3, -7, 11,-12, 17, 1, -1, - 3, -5, -7, 12, 4, 11, 0, 3, 2,-18, -3, 4, 7, -6, 3, 15 }, - { 10,-15,-16, -2, -4, -9, 7,-15, -6, 2,-16, 13, -8, 7, 19,-21, - -4,-12, -9, -3, -3, 6, 11, -3, -1,-19, 3, -7, -9, -4, 3, -6 }, - { -5,-10,-21, 0, -3, -7, 18,-21, 15, -5,-12, -4,-13, 2, 6, -9, - -9,-11, -4, 13, -3, 6, 4, -1, 7, -9, -4, 9, 5, 2, 6, 3 }, - { 15, -1,-27, -2, 10, 3, 7, -8, 9, -2, 7, 1, -2, -5, 18, 9, - -11,-17, -2, 7, -9, 11, 10, 0, -8, 6,-16, -3, 2, -7, 3, 11 }, - { 4, -9,-39, 19, 6,-13, 13, -5, -5,-15, -2, 9, 0, 4, 14, 6, - -10, -4, -5, 2, -4, -2, 5,-11, 3, 3, -2, -2, -7, 9, 7,-10 }, - { 5,-11, -8, 10, -2, 12, 16, 0, 12, -2, -6, 8, 14, 8, 7, 1, - 18,-30, 4, 10, -4, -6, 2,-11, 9,-10, -8, 5, 0, 0, -7, 6 }, - { -1,-16,-10, 11, 0, 13, 12, -4, -4, -5,-21, 12, 4, 13, 14, -7, - 6,-16,-13, 8, 2, 9, 15,-12, 1, -9,-22, 10, -9, 9, 9, -7 }, - { 4,-12,-27, 1, -2, 11, 15, 3, 14,-14, -9, 0, -9, 16, 22, 10, - 16,-10, 5, -5, -9, 1, 1, 6, 6, -4, 2,-17, -5, -6,-15, -1 }, - { 7,-12,-17, 1, -9, 5, 20, -7, 3, 23, -8, -8, -8, -1, 13, 17, - -7,-13, 4, -4, 7, 14, 8, 11, -3, -3, 4, 0, 4, 6, -1, -9 }, - { 7,-15,-15, -4, 10, 12, 3,-13, 6, 14, 9, -8,-15, 14, 23, -5, - -10, -5, 1, 15,-10, -7, 1, 9, 4,-13,-10, 10, 7, -3, 2, 3 }, - { 4,-10,-14, 0, 3, 4, 0, -9, -3, -4,-11, 2,-17, 8, 2, 15, - 6,-12,-12, 15, -5, 17, 18, 3, -3, -3, -4, -6, -8, 13, 4, 10 }, - { -2,-18,-26, 10, -4, 10, 13, 4, -4,-16, -7,-17, -3, 5, -4, 2, - -15,-10, -1, -8, -7, -3, 2, 2, 8,-10, -7, 2, 2, -4, 4, -1 }, - { 4,-19, -5, -1, -1, -6, 2, -8, 10,-16,-28, -6, 8, -1, 11, 28, - 2,-10, -4, 6, -6, 6, 11, 15, -4, -2, 7, 3, 7, -7, 4, 1 }, - { -3, -6,-10, -5, 13, 18, 10,-15, -5, -3,-13, 5, 1, 2, 18, -5, - -10,-10, -7, 4, 2, 1, 5, 4, 2, 5, 4, 8, -9,-17, 7, 7 }, - { 20,-12, -2, -4, 5, 14, 7,-11, -1,-16, -6, -4,-11, 17, 14, 0, - -8,-10, -8, 10, 3, 5, 10,-16, 3, -8,-14, 10, 3, 9, 0, 3 }, - { 12,-10,-36, 0, 7, 15, 2,-16, 2, -1, 0, -1, 5, 4, 5, -3, - 1,-10, 5, -1,-15, -3,-12, 12, 2, 5, -1, 5, 6, -3, -2, 2 }, - { 17,-15,-31, 23, -4, 15, -2, -3, 6, -7, -5, 1,-12, 4, 6, 8, - -10, 8, 3, 5, -4, 1, 5, 3, -1, -4, -3, 1, 10, -4, -2, -2 }, - { 6,-18, -5, 12, 10, 12, 14,-11, 15, 2, -9, -6, -5, -2, -9, 4, - -5,-28, -4, 14, 0,-16, 9, 14, -1, 3, -4, -4, 2, 1, 0, 4 }, - { -5,-14,-31, 8, 16, 7, 13,-13, 5, 6,-16, 10, -5, 2, -2, 2, - 14, -5, 8, -5, 7,-16, 6,-13, -5, 0, -5, 8, -3, -1, 4, 3 }, - { 1, -2, -1, 0, 6, 5, 2, -4, -3, -1, 0, 1, 4, 2, 43, 28, - -12,-35, -2, -2, -7, -1, 0, 2, -1, -2, -2, 1, -4, 0, -2, 3 }, - { 2, -9,-22, 12, 3, 3, -7, -4,-19,-22,-14, -4, -1, 21, 9, -3, - -15,-16,-13, 1,-11, 4, -9, 1, -7, -1, -1, 0, -2, 9,-13, -3 }, - { -1, -3,-23, 0, 2, 12, 3, -9, -4, 7, 3, 9,-10, 1, 27, 28, - 0, 9,-15, -2, -2, 1, 6, 8, -8, 7, -3, 20, 0, 0, -1, -6 }, - { -1, 11, 8, -2, 1, 5, -6, -1, 4, 2, -4, 0, -1, -5, 4, -6, - -10,-12, 19, 1, -7, 9, -8, -9,-16,-11, -2, 12, 14, 4, 4, 34 }, - { 17, 7, -6, 1, 4,-10, -5, 4,-11, 3,-18, 4, 14,-13, -3, 1, - 0, 0,-11, 0, 7,-17, -4, 4,-11, -6, -8, 18, 0, 0, 0, 26 }, - { -6, -7, -1, -1, 11, -8, 1, 3, 2, 11, -6, -6, 10, -3, 1, -3, - 7, 4,-12, -8, 0, -9, 8,-22, -5, 0, -6, 22, -2, 11,-13, 24 }, - { -3, 4, 0, 3, 9, 10, -1, 3, -9,-12, 1, -5, 18, 0, -3, 8, - 25, 15, -8, 2, 2, -2, 4, 8, 9, -1, -5, 10, -3, 1, -1, 23 }, - { -5, 2, -9, -1, -3, 0, 3, -1,-10, -4, 0,-13, 16, 9, -1,-14, - 2, 6, -2, -6, -5, -2, -7, 7, 5, 3, 11, -2,-14, 0, -9, 30 }, - { 4, 6, 6, 5, -3, -1, 4, 5, 10, 0, 5, -4, 7,-11, 14, 14, - 7, 34, -9, 0,-10, 22, -7, -1, 7, -9, 2, -8, 0, -7, -5, 29 }, - { -4, 3, -1, -4, -3, 5, 1, -4, 0, 2, 4, 2, 1, -1,-10, 1, - 6, -6, -4, 1, 4, -3, -3, -5, 0, 3, 7,-12, 0, -2,-10, 55 }, - { 5, 9, -1, 0, 4, 9,-21, -9, 4, 2, 6, -7, 11, -7, 1, -5, - 0, -4, 2, -3,-13, -8, 0, -9, -4, 2, 16, -2,-15, -7,-11, 31 }, - { 8, 2, -1, 0, 3, -5, -5, 5, 1, -1, -9, 1, 0, -6, -2, -1, - 5, 2, 0, 0, 12, 20,-19, 1, 8,-12,-11, 0, 6, -5, 2, 31 }, - { -1, -1, -2, 1, -1, 3, -9, -5, 8, -2, 5, -1, 0, -2, 4, -2, - -3,-12, 0, -2, 3, 0, 9, 4, -1, 21, -8, 3, -4, 9, -6, 30 }, - { -4, 0, -7, 17, 10,-12, -2,-10,-12, -3, 10, 0, 11, -4,-13, -3, - 5, 6, 10, 7, -8, 0, -7,-13, 1, 0, -2, 7,-12, 4, -3, 24 }, - {-13, 9, 4, -2, 2, -4,-14, -1, -3, -5,-10, 4, 13, -2, 5, 13, - 8, 3, -2, 1, 5, -6, 7,-18,-10, 1, -1, 5, 4, 1, 0, 25 }, - { -5, -1, 18, 12, 8, 8,-16, -1, 1, 1, 1, -4, -5, 3, 3, 4, - 4,-11,-12,-16, -6, 2, 12,-13, 0, 9, 7, 9, -9, 0,-10, 24 }, - { -4, 1, -3, 0, 2, -4, 4, 1, 5, 0, -3, 2, -3, -2, 2, -1, - 1, 4, -1, -2, -2, 1, -1, -1, -4, -1, -4, -2, -6, 6, 12, 69 }, - { 8, 5, 11, 0,-15, -4, 13, 6, 0, -4, 9, 1, -5, -3, 15, 0, - 1, 6, -5, 0, 1, 6, 5, 8, 0, 7, 1, -1, -4,-11, -9, 41 }, - { -4, -9, 32, -6, 0, 7, -4, 6, -6, 1, -6, -2, 4, -8, -5, -3, - -16, -1, -2, -6, 1, 15, 0, 21, 3, -3, -4, 3,-12, 16, 2, 27 }, - { -6, -5, 1, -9, -5, 3, 7, -3, 5, 5, 14, 13, 20, -7, -1, 12, - -1, 10,-11,-11, -7, -4,-14, 7,-14, 13, 22, 18, -1, 0, 14, 28 }, - { -8, 3, -2, 0, 5, 6, -1, -4, 1, 3, -7, 3, 1,-15, 4, -9, - 22,-10, -9, -4, 1, 8, -4, 9,-15, 2, -6, -4,-16, 12,-10, 23 }, - { 0, 0, 2, 0, -1, 3, -3, -1, 3, -5, 7, 1, 5, -5, -8, 1, - 13,-15, -5, -7, 12, -6, -2, 3, 10, -5, -8, 17, -5,-11,-14, 23 }, - { -7, -4, 6, -4, 5, -6, -5, 2, -4, 11, 9, -4, 2, -2, -4, 6, - 15, 3, -3, 18,-15, -2, -6, 3, 3,-20, 17, 11, -4, 2, 3, 29 }, - { 6, 1, -6, 2, 3, 0, 0, -3, 3, 3, -1, 3, -4, -6, -6, -7, - -3, -2, -7, -2, -4, 5, 3, -5,-20,-13, -4, 10,-14,-29, 14, 37 }, - { 3, 4, 3, -6, -4, 5, 0, 3, 2, 3, 0, -2, 4, 0, -3, -5, - -4, 4, -4, 4, 4, 3, 1, -4, -4, -9,-14, 20,-30, 3,-18, 33 }, - { 0, 2, 5, -2, -4, -2, -1, 2, -6, -3, -2, -2, 2, -5, -1, 4, - 3, 2, -3, 0, -1, -1,-10, -7, 2, -4,-18, 2,-37, -1, 12, 40 }, - { -7, 2, -1, 0, -2, 4, -8, 1, -4, 12, 7, 4, 15, -7, 1, -9, - 18, 0, 12,-17, -3, -1, 0, 0, 0, 2, -6, 0, -4, -3, -1, 26 }, - { -6, 4, 8, -5, -6, -2, 2, -1, 1, -1,-15, 8, 7, -1,-17, -4, - 1, 5, 6,-11, -6, 14, 17, -5,-15, 11, 8, 0, -3,-15, -6, 28 }, - { -1, 0, 0, 0, 1, 0, -1, 0, 1, 3, 2, -2, 3, -1, -1, 2, - 2, -1, -1, -7, 1, 2, -9, 0, -1, -4,-18, 7,-10, 49,-13, 32 }, - { -1, -3, 4, 1, 2, -5, 1, -7, -1, 5, -9, 4, 4, 25, 1, -1, - 2, -5, 2, -7, 17, -2, 10, -5, 0, 2,-15, 3, -9, 7, -9, 30 }, - { -5, -1, 0, 2, 1, -1, 2, 5,-33, 3, -5, 14, 11, 7, 5, -3, - 2, -8, -4, -2, -7, -6, 4, -8, -1, -8, 2, -2, -8, -1, -4, 27 }, - { -1, 0, -1, -2, 1, -1, -2, -1, 2, 0, 1, 2, 2, 4, 1, 3, - 4, 2, 1, -7, -4, 1, -3, -4,-35,-25, 17, 10, -3,-26, -7, 32 }, - { -5, 1, 6, -2, 6, 6, -9, 3, -1, -4, 5, -4, -2, -2, -9, 2, - -5, 2, 2, 4, 3, 5, -5,-16,-31,-12,-11, 2,-19, 20, -2, 21 }, - { -5, 2, 7, -7, -7, 5, -7, 2, 0, 0, -4, 3, -1, 0, -1, -2, - 0, -3, 5,-11, -8, -3, -7, -7, 28,-11, -7, 0,-16,-11, -4, 29 }, - { 2, 1, -3, -2, -1, 3, 4, 0, 1, 0, -1, -5, 4, -5,-12, 2, - -2, -5,-22, -2, -1, 11, 8, -7,-12, 0,-34, 6, -5, 11, -8, 19 }, - { -1, -3, 5, 11, 18, -2, -2, -5, -2, 4, -1, 8, 5, -6, 1, -1, - 2, 8, 4, -5, -8, -2, 5,-18, 7, 12, 7, 19,-18, 2, -6,-13 }, - { 9, 0, 0, 5, 4, 3, -6, 4, 1, -4, 5, -1, -4, 8, 8, 6, - -8, -6, 0, 6, -3, 3, 5, -3, 17, 31, 16, 10,-13, 0, -9,-19 }, - { 12,-10, 2, -2, -2, -1, -3, 6,-12, -5, -2, 14,-16, 4, 12, 12, - 17, 4, 7,-16, 7, -6, 11, 7, 7, 2,-25, 23,-24, 5, -7, -9 }, - { 10, 4, 13, 10, 10, 3, -6, 3, 3, 2, -1, -6, 8, 4, 10, 0, - 1, 2, -4, 2, -3, -8, 0, -1, 9, 9,-10, -3,-29, 1, -1,-27 }, - { 2, 2, 0, 7, 9, -2,-10, -1, -1, 1, -9, -5, 8, 4, 1, 2, - -10, 1, 13, 12, -3, 15, -9, 2, -7, 1,-10, 23,-20,-18, -9,-15 }, - { -3, -5, -1, 8, 0, -5, -1, 4, 7, -1, -7, 2, -8, -5, 11, 7, - -6, 3, -3, -9, 7, 9,-22, 1, 6, -4, 14, 27,-25,-14, 3, -5 }, - { 1, 3, 8, 4, 7, 6, 12,-17,-15, 1, -8,-10, 7,-14, -8, 6, - -2, -2,-11,-11, -7, 13, -2, -2, 4, 5, -5, 13,-23, -6,-17, -8 }, - { -5, 4,-14, -5, -4, -5, 6, 5, -8, -5, -2,-11, -7,-12, 3,-11, - 2, -6, 4,-10, -5, -7, 14, 5, 23, 11, 7, 12,-16, -6, -4,-16 }, - { 5, 6, 2, 5, -2, -5, -5, -6, -5,-19,-13, -1, -3,-13, 5, 0, - 6, -2, -2, -6, -7, -7, -1, -9, 4, 14, 17,-12,-27, 3, 0, -1 }, - { 7, -1, 9,-10, 8, 2, -7, -2, 5, 2, -3, -7, 3, 0, 6, 4, - 12, 5, 11, 14,-13, -1, 8, 1, 13, 9, 12, 12,-18,-14,-11,-16 }, - { -7, -5, -6, -5, 0, -1, -3, 2, 2, 1, 4, 9, 2, 3, 5, -2, - 2, 1, 8, 0, 3, 0, -2, 2, 1, 7, 29, 0,-36, -5, -9,-21 }, - { 14, -6, -9, 0, -1, -8, -8,-11, 2, 2, -9,-12, 12, -4, 5, 3, - -5, -9, 11, -1, -3, 12,-21, -3, 12, 5, 3, 11,-18,-15, 1, -2 }, - { -1, 3, -9, -3, 7, -7,-18, 2, 4, 12,-10, 2, 8, -3,-14, 13, - 17, -5, 5, -9, 13, -3, -7,-18, 17, -2, 5, 7,-20, -3, -6,-11 }, - { -3, 3, 3, -1, 1, -6, -5, 1, 5, -3,-14, -6, -5, -8, 14, -6, - 7, -1, 5, 1, 15, -1, -7, -4, 6,-11, 9, -2,-37, 16, -7, -3 }, - { -1, 0, 6, 1, -3, -9, 0, 11, -8, 2, -2, 0, 5, 2, 12,-10, - 10, 13, 2, 7, -6, 2,-10,-10, 21, -5, 5, 5,-12,-23, 3,-14 }, - { 6, 0, -2, 1, 0, 1, 0, -4, 1, 1, 8, -2, 2, -5, -2, 1, - 8, -4, -1, -1, 4, -1, 2, 6, 32, 1, -5,-20,-40, -4,-18,-14 }, - { 2, 2, -7, -2, 4, 4, -1, 2, 0, -2, -4, -7, 3, 5, 0, -5, - 1, 2, -6, 4, -1, -2, -1,-15, 8, 3, 9, 46, -7,-18, 6,-11 }, - { 5, 5, 16, 21, 3,-11, -4, 11,-12, 2, 4,-12, -1, 11, 8, 1, - -4, 11,-11,-21, 1, 1,-11, 3, 13, 1, 5, 12,-25, 1, -3, -2 }, - { 1, 6, -7, 4, 2, 3, 1, -5, 8, 9,-15, 3, -3,-14, 17, 4, - -8, 14, -2, -8, -4, 5, 8, -7, 8, 9, 7, 6,-29,-17, 8, 4 }, - { -7, -7, 4, 0, 13, 1, 0, 4, 4,-16,-10, -7, 5, 9,-15,-10, - -10, 8, -4, -1,-11, -1,-10,-15, 3, 3, 14, 10,-19, 2,-18,-12 }, - { -4, 0, 2, 0, 5, -2, -9, 0, 4, -4, 2, -1, -2, 2, -4, 9, - 2, -6, -4, -2, -1, -3, -3, -1, 2, 5, -1, 11,-24,-44, -9,-15 }, - { -1,-10, 6, 21, 11, 15, -7, 10,-14, -9, -8, -8, 4, 6, 19, 1, - -6, 1, -5,-17, -8,-10, 9, 5, 11, 18, -1, 10,-16, -7, -9, -8 }, - { 3, -5, 0, 0, -2, -2, -6, 4, -4, 1, -1, 0, 7, -3, 4, -4, - -7, 7, 17,-20, 6, 4, 1, -6,-12, 31, 13, 19,-14,-10, -7, -2 }, - { -2, 6,-10, 3, 9, 6,-14, 15, 2, -5, 2,-11, 9, -8, 4, 6, - 20,-15, -3, -3, -1, 32,-21, 6, 1, 9, 11, 17,-19, 6, -1, -3 }, - { 8, 10, -2, 0, -8,-16, 7, 7, 6, 10, 4,-14, 7, -6, 21, -7, - 10, 5, 5, 0, -7, 2, -6, 0, -7, 11, -9, 15,-20, -7,-11, 2 }, - { 0, -7, 5, 2, 0, -3, -6, -4, -2, -1, -4, -5,-13, -1, 27, -9, - -6,-11, -7, 1, 11, -4, -4,-14, -2, 11, 6, 10,-19, -6,-15, 2 }, - { 0, 7, -1, 2, -7,-15, -2, -3, 13, -5, -5, 12, 3, 0, 5, -5, - -22, 2, 7, 22, 13, 0, -1, 2, 3, 2, -7, 7,-27, -4, -4,-12 }, - { 11, 1,-16, 6,-15, 1, 3, 2, 0, 2, -3, 2, 5, -2, -5, 9, - 5, -3, 3, -2,-11, 3, 9, 6, 9, 3, -1, 12,-41, 8, -6, 9 }, - { 3, -7, 3, 2, 5, 5, 0, -1, 1, 3, -5, -2,-13, 7, -1, -2, - -2, -6, 4, -6, 0, 2, -2, 2, 4, 1, -4, 1,-47,-21, 7, -6 }, - { 3, 16, -7, 13, -4, -2, 10, -3, -1, 18,-13, 7,-13, -4, 8, 4, - 8, 9, -5, 13, 8, -5, 3, -6, 7, 18, -8, 10,-25, -3,-12,-12 }, - { 1, -1, -1, 0, 2, 5, -5, -3, 0, -5, -1, 0, -4, -8, -2, 3, - 2, -2,-17, -6, -4, 1, 33, -6,-20, -6, 8, 31,-26, -8, -1, -4 }, - { 3, -3, -3, 5, -3, -2, 1, 7, 0, 3, 6, 3, 6, -2, 9, 15, - -10, -3,-15, -5, -3, -4, -6,-30, 17, -8, -2, 2,-20, 0, -8, -2 }, - { -2, -1, -1, -1, 3, -5, -2, -3, 4, -2, 0, 5, 8, -3, 1, -4, - 1, 1, -3, 4, 4,-14, 3, 11, -5, 3, -3, 7, -3, 13, 23,-16 }, - { 2, -6, 1, -3, 5, 0, -6,-11, -7, -4, -1, 2, -7, -1, -1, 7, - 1, -2, 6, 12, -6, 8,-13, 17, 25,-23,-19, -7,-12, 9, 16,-17 }, - { 9, 4, 4, 4, -3, -1, 6, -2, -3, 0, 13, -4, -7, 14, 1, -7, - 0, -5, 3,-19, -3, 5, 3, 9, -1, 9,-13, 13,-17, 4, 21,-26 }, - { 0, -5, 0, 0, -4, -5, 2, -6, -4, 5, -7, 10, 0, 2, 0, -2, - -2, 0, 4, -6, 7, -2, 6, 5, -5, 2,-12, 1,-29, 29, 27, 12 }, - { 9,-10,-22, 6, -1, -1, 9,-14,-12, -2, 1, -1, 10,-11,-16, 0, - 3, 11, 13,-14, -9, -2, -1, 6, 4,-14, 0,-10, -2, 16, 17,-11 }, - { 2, 0, -1, -2, 4, 3, -6, -2, 1, -1, 1, 3, -4, 1, 3, -4, - -1, -1, 4, -1, 1, 0, 1, 6, -5, -7, 2, 1,-47, -3, 50,-17 }, - { 8, -4,-11, -7, 11, 11, 14, -7, 12, -7, 6, 2, 13, -6, -3, -2, - -14, 6, 6, 6, 0, 2, -1, 5,-20, 2, -1, 4, -5, 6, 21,-11 }, - { -2, -9, 3, 0, -6, 7, 8, -8, 1, -3, 4, 1, 5, -2, -3, -7, - 4, 7,-12, -9, -2, 10, -6, 13, 6, 5, 20, 2,-15, 9, 28, -7 }, - { 0, -5, -6, -6, -6, 1, -6, 6, -2, 4, 8, -3, 12, -1, -4, -2, - 6, 16,-14, 9,-14, -2, -8,-27, -3, 18, -1, -7, -3, 8, 23,-23 }, - { 1, 4, -9, -1, -5, 10, -2, 1,-11, 1, -9, 4, 7, 14, -9, -2, - -3, 2, -5, -1, -6,-10, -7, 11, 20, 2, 3,-19, 3, 15, 30, -9 }, - { 7, 2,-14, -4, 0, -2, 5, 2, 5, -2, 8, -3, -7, 6, 6,-11, - -14, 1, 10, -1, -7, -8, 1, 10, 3, -6,-15,-12,-17, 4, 30, -6 }, - { 4, 2, 1, -2, 3, 0, 1, 0, 2, 0, 1, 6, -7, 0, 3, 4, - 4, -4, -2, -5, -2, 2, -1, -2, 0, -2,-11, -7, -3, 42, 24,-14 }, - { 4, 1, 3, 2, 0, -2, -3, -2, 2, -1, 4, 11, -2, 2, 3, -4, - -5, 9, 2, -4, -9, 5, 8, -1, -7, 1, 24,-13,-28, 20, 15,-22 }, - { -3, 7, 6, 3, -2, -5,-10, -2, -2, -1, -6, -6, -2,-14,-16, -6, - -5, 0, 18, 0, 9, 1, 7,-13, -5, -6, -9, 11,-15, 9, 22,-11 }, - { 9, -2, 6, 5, 2, 9,-10, 1, 1, 5, -4, 12, 2, 2,-10, -7, - -4, -6, 7, 9, 6, 15, 6, 6,-10, 10, 5,-13, -5, 6, 24,-12 }, - { 1, 3, -3, -3, 8, 1, -6, 2, -5, -3, 7, 2, 14, 6, 9, -6, - -5, -4, 27, 7, -3, 8, -6, 3, -8, 8, 22, -5, -6, -2, 22,-17 }, - { -2, -2, 3, 10, 9, 9, 12,-15, -1,-11,-13, 3, -2, 1, -3,-11, - 7, 9, 16, -3,-10, -5, -5, 1, 8, -3, 9, 9, -5, 3, 31,-12 }, - { 7, -5, 10, -4, -8, 2, 16, -2, 10, 10, -3, -2, 3, -8, -3, 3, - -13, -6, 15, 20, -9, -3,-12, 1, -2,-16, 8, 8, -1, 16, 22, -5 }, - { 5, -3,-15, -2, 12, -8, 8, -5, 2, -8, 20,-18, 14, -4, 3, 3, - 7,-13,-16, 1,-10, 7, 16, 7, 4,-14, -4, -5, -9, 8, 23, -6 }, - { 5, -4, -5, -4, 1, 8, 4, -7, -5, 8, 10, 6, -6,-10, -2, 6, - 9,-17,-14, 11, 12, -3,-13, -7, 2, 18, 3,-25,-16, 18, 22, -5 }, - { 5, 6, -7,-20, -4, 2, 8, 4,-24, -4, 1, 4, -5, -2, 1,-10, - -2, 9, 3, -4, -3, -4, -4, -4, 10, 10, 3, 0, -6, 25, 21,-11 }, - { 0, 7, -1, 14, -6, -4,-10, 5, 4, 4, 4, -5, 3, 4, -1, -7, - 8,-19, 0, 6, 2, 3,-18, -3, -6, 2, 8, 14,-26, 22, 27,-13 }, - { -2, -6, 7, -5, 12, -7, 8, -1, 3, -2, 4, 1, 8, -2, 0, 14, - 6, -5, 6, -4, -7, 7,-21, 8, 1, 8, -9, -4, -3, 11, 25,-13 }, - { 4, 4, -1, -6, 4, 9, -8, 1, -3,-10, -2, 0, 15, -9,-16, 11, - 1, 1, 6, 3, -9, -5, 16, 26, 1,-14, 1, -3,-14, 7, 15, -9 }, - {-12, -2, -9,-13, 2, 6, 14, 0, 1, 0, -1,-13, 0, 10, -1, 6, - 9, -7, 8, 8, 19, 6, -1, 9, 10, -4, 1, -7,-22, -2, 29, -7 }, - { 2, 4, 13,-12, -8, -4, -5, 13, 12, -5, -3, -3, -4, 1, -1, 10, - 15, -6, -1,-11,-30, 4, 15, -1, 9, -7, 0, -2, -7, 10, 25,-16 }, - { 7,-15, -7, -7, -1, -5, -5,-11,-20, 10, 3,-10, -3, 5, 20, -4, - 0, -2, -2, 17, 2, 0, -3, 3, 6, 5, -1,-12, -3, 15, 22,-16 }, - { 4, -1, 3, 4, -5, 0, -1, -5,-24,-29, 4, -9, 1, -3, 0, 0, - 0, -4, 7, -4, -4, -4, 3, 1, -6, 5, -3, -5,-10, 3, 25,-10 }, - { -2, -1, -1, 4, 4, -1, 2, 0, -4, -4, 2, -1, -3, -1, -2, -2, - 1, -3, -5, -1, 2, -3, -4, -4, -3, 5, -9, 1,-11, 7, 46,-46 }, - { 0, -9, 3, 4, 4, 3, -5, -6, 5, -4, 4, -2, 1, 7, -4,-10, - 13, 1, 3, -6, 4, -4, 7, 2,-19,-25, -3,-16,-12, 16, 20, -1 }, - { 18, 6, 4,-12, 0,-14, 9, -6, -1, -4, -5, 2, 1, 12, 4, 2, - 7, 0, 2, 5,-11, -5, -2, 2, -4, 10, 0, -9, -7, 9, 25, -8 }, - { 5, 0, -6, 5, 6, 3, 3,-10, -5, 1, -1, 4, 3,-11, -8, 5, - 4, -5, 5, -5, -7, -5, 11, 5, 20, -8,-16, 21, -4, 27, 23, -5 } -}; - - -/* FIR filter coefficients, they can be cut on half and maybe use float instead of double*/ - -DECLARE_ALIGNED(16, static const float, fir_32bands_perfect)[] = -{ -+1.135985195E-010, -+7.018770981E-011, --1.608403011E-008, --5.083275667E-008, --1.543309907E-007, --3.961981463E-007, --7.342250683E-007, --3.970030775E-007, --4.741137047E-007, --6.022448247E-007, --6.628192182E-007, --6.982898526E-007, --7.020648809E-007, --6.767839409E-007, --6.262345096E-007, --5.564140224E-007, -+7.003467317E-007, -+8.419976893E-007, -+9.742954035E-007, -+1.085227950E-006, -+1.162929266E-006, -+1.194632091E-006, -+1.179182050E-006, -+1.033426656E-006, -+9.451737242E-007, -+1.975324267E-006, -+1.190443072E-006, -+5.234479659E-007, -+2.014677420E-007, -+7.834767501E-008, --6.702406963E-010, --1.613285505E-009, --2.682709610E-009, --3.399493131E-009, -+1.314406006E-008, -+7.506701927E-009, -+2.788728892E-008, -+1.444918922E-007, -+3.132386439E-007, -+1.399798180E-006, -+2.032118118E-006, -+2.715013807E-006, -+3.453840463E-006, -+4.195037945E-006, -+4.896494374E-006, -+5.516381407E-006, -+6.015239251E-006, -+6.361419310E-006, -+8.006985809E-006, -+8.087732567E-006, -+7.941360309E-006, -+7.568834008E-006, -+6.986399967E-006, -+6.225028756E-006, -+5.315936960E-006, -+4.429412002E-006, -+3.332600045E-006, -+8.427224429E-007, -+4.341498823E-007, -+9.458596395E-008, -+2.975164826E-008, -+6.402664354E-008, --3.246264413E-008, --3.809887872E-008, -+8.434094667E-008, -+6.437721822E-008, -+1.189317118E-006, -+2.497214155E-006, -+3.617151151E-006, -+3.157242645E-006, -+2.319611212E-006, -+7.869333785E-006, -+9.826449968E-006, -+1.177108606E-005, -+1.379448349E-005, -+1.571428584E-005, -+1.743183020E-005, -+1.884208177E-005, -+1.987093310E-005, -+2.042970118E-005, --3.144468428E-005, --3.334947178E-005, --3.460439257E-005, --3.515914432E-005, --3.495384954E-005, --3.397853652E-005, --3.225446198E-005, --2.978993689E-005, --2.677291741E-005, --1.806914770E-005, --1.776598037E-005, --1.661818715E-005, --1.207003334E-005, --6.993315310E-006, --5.633860383E-007, --9.984935332E-007, --1.470520488E-006, --1.853591357E-006, -+7.198007665E-007, -+3.086857760E-006, -+6.084746474E-006, -+9.561075785E-006, -+1.309637537E-005, -+2.263354872E-005, -+2.847247197E-005, -+3.415624451E-005, -+3.946387005E-005, -+4.425736552E-005, -+4.839275425E-005, -+5.176846025E-005, -+5.429694284E-005, -+5.595519906E-005, -+4.916387297E-006, -+9.299508747E-006, -+1.356193479E-005, -+1.751866148E-005, -+2.093936746E-005, -+2.362549276E-005, -+2.537086584E-005, -+2.618136386E-005, -+2.554462844E-005, -+3.018750249E-005, -+2.570833203E-005, -+1.985177369E-005, -+1.191342653E-005, -+2.525620175E-006, --1.521241393E-005, --1.617751332E-005, -+1.992636317E-005, -+1.774702469E-005, -+4.624524081E-005, -+5.610509834E-005, -+6.568001118E-005, -+7.513730816E-005, -+8.413690375E-005, -+8.757545584E-005, -+9.517164290E-005, -+1.020687996E-004, -+1.084438481E-004, -+1.140582463E-004, -+1.187910311E-004, -+1.224978914E-004, -+1.250260248E-004, -+1.262027217E-004, -+1.226499153E-004, -+1.213575742E-004, -+1.180980107E-004, -+1.126275165E-004, -+1.047207043E-004, -+9.417100227E-005, -+8.078388782E-005, -+6.447290798E-005, -+4.491530854E-005, -+2.470704203E-005, --1.714242217E-006, --3.193307566E-005, --6.541742187E-005, --1.024175072E-004, --1.312203676E-004, --1.774113771E-004, --2.233728592E-004, --2.682086197E-004, --3.347633174E-004, --3.906481725E-004, --4.490280990E-004, --5.099929986E-004, --5.729619297E-004, --6.358824321E-004, --7.021900383E-004, --7.698345580E-004, --8.385353722E-004, --9.078957955E-004, --9.775133803E-004, --1.046945457E-003, --1.115717343E-003, --1.183370827E-003, --1.252829796E-003, --1.316190348E-003, --1.376571832E-003, --1.433344092E-003, --1.485876855E-003, --1.533520175E-003, --1.575609902E-003, --1.611457788E-003, --1.640390139E-003, --1.661288203E-003, --1.674512983E-003, --1.678415807E-003, --1.672798418E-003, --1.656501088E-003, --1.633993932E-003, --1.593449386E-003, -+1.542080659E-003, -+1.479332102E-003, -+1.395521569E-003, -+1.303116791E-003, -+1.196175464E-003, -+1.073757303E-003, -+9.358961834E-004, -+7.817269652E-004, -+6.114174030E-004, -+4.244441516E-004, -+2.206075296E-004, --2.719412748E-007, --2.382978710E-004, --4.935106263E-004, --7.658848190E-004, --1.055365428E-003, --1.361547387E-003, --1.684492454E-003, --2.023874084E-003, --2.379294252E-003, --2.750317100E-003, --3.136433195E-003, --3.537061159E-003, --3.951539751E-003, --4.379155114E-003, --4.819062538E-003, --5.270531867E-003, --5.732392892E-003, --6.203945260E-003, --6.683901884E-003, --7.170005701E-003, --7.664063945E-003, --8.162760176E-003, --8.665001951E-003, --9.170533158E-003, --9.676489048E-003, --1.018219907E-002, --1.068630442E-002, --1.118756086E-002, --1.168460958E-002, --1.217562053E-002, --1.265939046E-002, --1.313448418E-002, --1.359948888E-002, --1.405300573E-002, --1.449365262E-002, --1.492007636E-002, --1.533095632E-002, --1.572482102E-002, --1.610082202E-002, --1.645756140E-002, --1.679391414E-002, --1.710879989E-002, --1.740120351E-002, --1.767017506E-002, --1.791484281E-002, --1.813439466E-002, --1.832821220E-002, --1.849545911E-002, --1.863567345E-002, --1.874836907E-002, --1.883326657E-002, --1.889026538E-002, --1.891860925E-002, -+1.891860925E-002, -+1.889026538E-002, -+1.883326657E-002, -+1.874836907E-002, -+1.863567345E-002, -+1.849545911E-002, -+1.832821220E-002, -+1.813439466E-002, -+1.791484281E-002, -+1.767017506E-002, -+1.740120351E-002, -+1.710879989E-002, -+1.679391414E-002, -+1.645756140E-002, -+1.610082202E-002, -+1.572482102E-002, -+1.533095632E-002, -+1.492007636E-002, -+1.449365262E-002, -+1.405300573E-002, -+1.359948888E-002, -+1.313448418E-002, -+1.265939046E-002, -+1.217562053E-002, -+1.168460958E-002, -+1.118756086E-002, -+1.068630442E-002, -+1.018219907E-002, -+9.676489048E-003, -+9.170533158E-003, -+8.665001951E-003, -+8.162760176E-003, -+7.664063945E-003, -+7.170005701E-003, -+6.683901884E-003, -+6.203945260E-003, -+5.732392892E-003, -+5.270531867E-003, -+4.819062538E-003, -+4.379155114E-003, -+3.951539751E-003, -+3.537061159E-003, -+3.136433195E-003, -+2.750317100E-003, -+2.379294252E-003, -+2.023874084E-003, -+1.684492454E-003, -+1.361547387E-003, -+1.055365428E-003, -+7.658848190E-004, -+4.935106263E-004, -+2.382978710E-004, -+2.719412748E-007, --2.206075296E-004, --4.244441516E-004, --6.114174030E-004, --7.817269652E-004, --9.358961834E-004, --1.073757303E-003, --1.196175464E-003, --1.303116791E-003, --1.395521569E-003, --1.479332102E-003, --1.542080659E-003, -+1.593449386E-003, -+1.633993932E-003, -+1.656501088E-003, -+1.672798418E-003, -+1.678415807E-003, -+1.674512983E-003, -+1.661288203E-003, -+1.640390139E-003, -+1.611457788E-003, -+1.575609902E-003, -+1.533520175E-003, -+1.485876855E-003, -+1.433344092E-003, -+1.376571832E-003, -+1.316190348E-003, -+1.252829796E-003, -+1.183370827E-003, -+1.115717343E-003, -+1.046945457E-003, -+9.775133803E-004, -+9.078957955E-004, -+8.385353722E-004, -+7.698345580E-004, -+7.021900383E-004, -+6.358824321E-004, -+5.729619297E-004, -+5.099929986E-004, -+4.490280990E-004, -+3.906481725E-004, -+3.347633174E-004, -+2.682086197E-004, -+2.233728592E-004, -+1.774113771E-004, -+1.312203676E-004, -+1.024175072E-004, -+6.541742187E-005, -+3.193307566E-005, -+1.714242217E-006, --2.470704203E-005, --4.491530854E-005, --6.447290798E-005, --8.078388782E-005, --9.417100227E-005, --1.047207043E-004, --1.126275165E-004, --1.180980107E-004, --1.213575742E-004, --1.226499153E-004, --1.262027217E-004, --1.250260248E-004, --1.224978914E-004, --1.187910311E-004, --1.140582463E-004, --1.084438481E-004, --1.020687996E-004, --9.517164290E-005, --8.757545584E-005, --8.413690375E-005, --7.513730816E-005, --6.568001118E-005, --5.610509834E-005, --4.624524081E-005, --1.774702469E-005, --1.992636317E-005, -+1.617751332E-005, -+1.521241393E-005, --2.525620175E-006, --1.191342653E-005, --1.985177369E-005, --2.570833203E-005, --3.018750249E-005, --2.554462844E-005, --2.618136386E-005, --2.537086584E-005, --2.362549276E-005, --2.093936746E-005, --1.751866148E-005, --1.356193479E-005, --9.299508747E-006, --4.916387297E-006, --5.595519906E-005, --5.429694284E-005, --5.176846025E-005, --4.839275425E-005, --4.425736552E-005, --3.946387005E-005, --3.415624451E-005, --2.847247197E-005, --2.263354872E-005, --1.309637537E-005, --9.561075785E-006, --6.084746474E-006, --3.086857760E-006, --7.198007665E-007, -+1.853591357E-006, -+1.470520488E-006, -+9.984935332E-007, -+5.633860383E-007, -+6.993315310E-006, -+1.207003334E-005, -+1.661818715E-005, -+1.776598037E-005, -+1.806914770E-005, -+2.677291741E-005, -+2.978993689E-005, -+3.225446198E-005, -+3.397853652E-005, -+3.495384954E-005, -+3.515914432E-005, -+3.460439257E-005, -+3.334947178E-005, -+3.144468428E-005, --2.042970118E-005, --1.987093310E-005, --1.884208177E-005, --1.743183020E-005, --1.571428584E-005, --1.379448349E-005, --1.177108606E-005, --9.826449968E-006, --7.869333785E-006, --2.319611212E-006, --3.157242645E-006, --3.617151151E-006, --2.497214155E-006, --1.189317118E-006, --6.437721822E-008, --8.434094667E-008, -+3.809887872E-008, -+3.246264413E-008, --6.402664354E-008, --2.975164826E-008, --9.458596395E-008, --4.341498823E-007, --8.427224429E-007, --3.332600045E-006, --4.429412002E-006, --5.315936960E-006, --6.225028756E-006, --6.986399967E-006, --7.568834008E-006, --7.941360309E-006, --8.087732567E-006, --8.006985809E-006, --6.361419310E-006, --6.015239251E-006, --5.516381407E-006, --4.896494374E-006, --4.195037945E-006, --3.453840463E-006, --2.715013807E-006, --2.032118118E-006, --1.399798180E-006, --3.132386439E-007, --1.444918922E-007, --2.788728892E-008, --7.506701927E-009, --1.314406006E-008, -+3.399493131E-009, -+2.682709610E-009, -+1.613285505E-009, -+6.702406963E-010, --7.834767501E-008, --2.014677420E-007, --5.234479659E-007, --1.190443072E-006, --1.975324267E-006, --9.451737242E-007, --1.033426656E-006, --1.179182050E-006, --1.194632091E-006, --1.162929266E-006, --1.085227950E-006, --9.742954035E-007, --8.419976893E-007, --7.003467317E-007, -+5.564140224E-007, -+6.262345096E-007, -+6.767839409E-007, -+7.020648809E-007, -+6.982898526E-007, -+6.628192182E-007, -+6.022448247E-007, -+4.741137047E-007, -+3.970030775E-007, -+7.342250683E-007, -+3.961981463E-007, -+1.543309907E-007, -+5.083275667E-008, -+1.608403011E-008, --7.018770981E-011, --1.135985195E-010 -}; - -DECLARE_ALIGNED(16, static const float, fir_32bands_nonperfect)[] = -{ --1.390191784E-007, --1.693738625E-007, --2.030677564E-007, --2.404238444E-007, --2.818143514E-007, --3.276689142E-007, --3.784752209E-007, --4.347855338E-007, --4.972276315E-007, --5.665120852E-007, --6.434325428E-007, --7.288739425E-007, --8.238164355E-007, --9.293416952E-007, --1.046637067E-006, --1.176999604E-006, --1.321840614E-006, --1.482681114E-006, --1.661159786E-006, --1.859034001E-006, --2.078171747E-006, --2.320550948E-006, --2.588257530E-006, --2.883470643E-006, --3.208459020E-006, --3.565570978E-006, --3.957220997E-006, --4.385879038E-006, --4.854050530E-006, --5.364252502E-006, --5.918994248E-006, --6.520755960E-006, --7.171964626E-006, --7.874960829E-006, --8.631964192E-006, --9.445050637E-006, --1.031611009E-005, --1.124680875E-005, --1.223855270E-005, --1.329243969E-005, --1.440921824E-005, --1.558924305E-005, --1.683242772E-005, --1.813820381E-005, --1.950545993E-005, --2.093250441E-005, --2.241701623E-005, --2.395598858E-005, --2.554569073E-005, --2.718161704E-005, --2.885844333E-005, --3.056998685E-005, --3.230916263E-005, --3.406793985E-005, --3.583733633E-005, --3.760734762E-005, --3.936696885E-005, --4.110412556E-005, --4.280570283E-005, --4.445751256E-005, --4.604430433E-005, --4.754976908E-005, --4.895655002E-005, --5.024627535E-005, -+5.139957648E-005, -+5.239612074E-005, -+5.321469871E-005, -+5.383323878E-005, -+5.422891263E-005, -+5.437819709E-005, -+5.425697600E-005, -+5.384063843E-005, -+5.310418419E-005, -+5.202236207E-005, -+5.056979353E-005, -+4.872112549E-005, -+4.645117951E-005, -+4.373511547E-005, -+4.054862075E-005, -+3.686808850E-005, -+3.267079956E-005, -+2.793515523E-005, -+2.264085742E-005, -+1.676913780E-005, -+1.030297699E-005, -+3.227306706E-006, --4.470633485E-006, --1.280130618E-005, --2.177240640E-005, --3.138873581E-005, --4.165195787E-005, --5.256036457E-005, --6.410864444E-005, --7.628766616E-005, --8.908427117E-005, --1.024810626E-004, --1.164562127E-004, --1.309833024E-004, --1.460311323E-004, --1.615635992E-004, --1.775395358E-004, --1.939126523E-004, --2.106313768E-004, --2.276388550E-004, --2.448728774E-004, --2.622658503E-004, --2.797449124E-004, --2.972317743E-004, --3.146430245E-004, --3.318900708E-004, --3.488793736E-004, --3.655125911E-004, --3.816867538E-004, --3.972945851E-004, --4.122247046E-004, --4.263620067E-004, --4.395879805E-004, --4.517810594E-004, --4.628172028E-004, --4.725702747E-004, --4.809123348E-004, --4.877146275E-004, --4.928477574E-004, --4.961824161E-004, --4.975944757E-004, --4.969481961E-004, --4.941228544E-004, --4.889960401E-004, -+4.814492422E-004, -+4.713678791E-004, -+4.586426076E-004, -+4.431701091E-004, -+4.248536134E-004, -+4.036037717E-004, -+3.793396754E-004, -+3.519894381E-004, -+3.214911267E-004, -+2.877934603E-004, -+2.508567995E-004, -+2.106537577E-004, -+1.671699720E-004, -+1.204049113E-004, -+7.037253090E-005, -+1.710198012E-005, --3.936182839E-005, --9.895755647E-005, --1.616069785E-004, --2.272142592E-004, --2.956659591E-004, --3.668301215E-004, --4.405563814E-004, --5.166754709E-004, --5.949990009E-004, --6.753197522E-004, --7.574109477E-004, --8.410271257E-004, --9.259034996E-004, --1.011756598E-003, --1.098284614E-003, --1.185167348E-003, --1.272067428E-003, --1.358630019E-003, --1.444484224E-003, --1.529243193E-003, --1.612505526E-003, --1.693855622E-003, --1.772865304E-003, --1.849094522E-003, --1.922092517E-003, --1.991399564E-003, --2.056547208E-003, --2.117061289E-003, --2.172462177E-003, --2.222266514E-003, --2.265989315E-003, --2.303145360E-003, --2.333251061E-003, --2.355825622E-003, --2.370394068E-003, --2.376487479E-003, --2.373647178E-003, --2.361423569E-003, --2.339380793E-003, --2.307097195E-003, --2.264167881E-003, --2.210205887E-003, --2.144844970E-003, --2.067740774E-003, --1.978572691E-003, --1.877046190E-003, --1.762894331E-003, --1.635878929E-003, -+1.495792647E-003, -+1.342460280E-003, -+1.175740734E-003, -+9.955273708E-004, -+8.017504588E-004, -+5.943773431E-004, -+3.734139318E-004, -+1.389056415E-004, --1.090620208E-004, --3.703625989E-004, --6.448282511E-004, --9.322494152E-004, --1.232374110E-003, --1.544908970E-003, --1.869517611E-003, --2.205822384E-003, --2.553403843E-003, --2.911801683E-003, --3.280514618E-003, --3.659002949E-003, --4.046686925E-003, --4.442950245E-003, --4.847140983E-003, --5.258570891E-003, --5.676518660E-003, --6.100233644E-003, --6.528933067E-003, --6.961807609E-003, --7.398022339E-003, --7.836719044E-003, --8.277016692E-003, --8.718019351E-003, --9.158811532E-003, --9.598465636E-003, --1.003604382E-002, --1.047059800E-002, --1.090117730E-002, --1.132682897E-002, --1.174659748E-002, --1.215953380E-002, --1.256469358E-002, --1.296114177E-002, --1.334795821E-002, --1.372423489E-002, --1.408908330E-002, --1.444163360E-002, --1.478104480E-002, --1.510649733E-002, --1.541720331E-002, --1.571240649E-002, --1.599138230E-002, --1.625344716E-002, --1.649795473E-002, --1.672429405E-002, --1.693190821E-002, --1.712027565E-002, --1.728892699E-002, --1.743743755E-002, --1.756543480E-002, --1.767260395E-002, --1.775865816E-002, --1.782339066E-002, --1.786663756E-002, --1.788828894E-002, -+1.788828894E-002, -+1.786663756E-002, -+1.782339066E-002, -+1.775865816E-002, -+1.767260395E-002, -+1.756543480E-002, -+1.743743755E-002, -+1.728892699E-002, -+1.712027565E-002, -+1.693190821E-002, -+1.672429405E-002, -+1.649795473E-002, -+1.625344716E-002, -+1.599138230E-002, -+1.571240649E-002, -+1.541720331E-002, -+1.510649733E-002, -+1.478104480E-002, -+1.444163360E-002, -+1.408908330E-002, -+1.372423489E-002, -+1.334795821E-002, -+1.296114177E-002, -+1.256469358E-002, -+1.215953380E-002, -+1.174659748E-002, -+1.132682897E-002, -+1.090117730E-002, -+1.047059800E-002, -+1.003604382E-002, -+9.598465636E-003, -+9.158811532E-003, -+8.718019351E-003, -+8.277016692E-003, -+7.836719044E-003, -+7.398022339E-003, -+6.961807609E-003, -+6.528933067E-003, -+6.100233644E-003, -+5.676518660E-003, -+5.258570891E-003, -+4.847140983E-003, -+4.442950245E-003, -+4.046686925E-003, -+3.659002949E-003, -+3.280514618E-003, -+2.911801683E-003, -+2.553403843E-003, -+2.205822384E-003, -+1.869517611E-003, -+1.544908970E-003, -+1.232374110E-003, -+9.322494152E-004, -+6.448282511E-004, -+3.703625989E-004, -+1.090620208E-004, --1.389056415E-004, --3.734139318E-004, --5.943773431E-004, --8.017504588E-004, --9.955273708E-004, --1.175740734E-003, --1.342460280E-003, --1.495792647E-003, -+1.635878929E-003, -+1.762894331E-003, -+1.877046190E-003, -+1.978572691E-003, -+2.067740774E-003, -+2.144844970E-003, -+2.210205887E-003, -+2.264167881E-003, -+2.307097195E-003, -+2.339380793E-003, -+2.361423569E-003, -+2.373647178E-003, -+2.376487479E-003, -+2.370394068E-003, -+2.355825622E-003, -+2.333251061E-003, -+2.303145360E-003, -+2.265989315E-003, -+2.222266514E-003, -+2.172462177E-003, -+2.117061289E-003, -+2.056547208E-003, -+1.991399564E-003, -+1.922092517E-003, -+1.849094522E-003, -+1.772865304E-003, -+1.693855622E-003, -+1.612505526E-003, -+1.529243193E-003, -+1.444484224E-003, -+1.358630019E-003, -+1.272067428E-003, -+1.185167348E-003, -+1.098284614E-003, -+1.011756598E-003, -+9.259034996E-004, -+8.410271257E-004, -+7.574109477E-004, -+6.753197522E-004, -+5.949990009E-004, -+5.166754709E-004, -+4.405563814E-004, -+3.668301215E-004, -+2.956659591E-004, -+2.272142592E-004, -+1.616069785E-004, -+9.895755647E-005, -+3.936182839E-005, --1.710198012E-005, --7.037253090E-005, --1.204049113E-004, --1.671699720E-004, --2.106537577E-004, --2.508567995E-004, --2.877934603E-004, --3.214911267E-004, --3.519894381E-004, --3.793396754E-004, --4.036037717E-004, --4.248536134E-004, --4.431701091E-004, --4.586426076E-004, --4.713678791E-004, --4.814492422E-004, -+4.889960401E-004, -+4.941228544E-004, -+4.969481961E-004, -+4.975944757E-004, -+4.961824161E-004, -+4.928477574E-004, -+4.877146275E-004, -+4.809123348E-004, -+4.725702747E-004, -+4.628172028E-004, -+4.517810594E-004, -+4.395879805E-004, -+4.263620067E-004, -+4.122247046E-004, -+3.972945851E-004, -+3.816867538E-004, -+3.655125911E-004, -+3.488793736E-004, -+3.318900708E-004, -+3.146430245E-004, -+2.972317743E-004, -+2.797449124E-004, -+2.622658503E-004, -+2.448728774E-004, -+2.276388550E-004, -+2.106313768E-004, -+1.939126523E-004, -+1.775395358E-004, -+1.615635992E-004, -+1.460311323E-004, -+1.309833024E-004, -+1.164562127E-004, -+1.024810626E-004, -+8.908427117E-005, -+7.628766616E-005, -+6.410864444E-005, -+5.256036457E-005, -+4.165195787E-005, -+3.138873581E-005, -+2.177240640E-005, -+1.280130618E-005, -+4.470633485E-006, --3.227306706E-006, --1.030297699E-005, --1.676913780E-005, --2.264085742E-005, --2.793515523E-005, --3.267079956E-005, --3.686808850E-005, --4.054862075E-005, --4.373511547E-005, --4.645117951E-005, --4.872112549E-005, --5.056979353E-005, --5.202236207E-005, --5.310418419E-005, --5.384063843E-005, --5.425697600E-005, --5.437819709E-005, --5.422891263E-005, --5.383323878E-005, --5.321469871E-005, --5.239612074E-005, --5.139957648E-005, -+5.024627535E-005, -+4.895655002E-005, -+4.754976908E-005, -+4.604430433E-005, -+4.445751256E-005, -+4.280570283E-005, -+4.110412556E-005, -+3.936696885E-005, -+3.760734762E-005, -+3.583733633E-005, -+3.406793985E-005, -+3.230916263E-005, -+3.056998685E-005, -+2.885844333E-005, -+2.718161704E-005, -+2.554569073E-005, -+2.395598858E-005, -+2.241701623E-005, -+2.093250441E-005, -+1.950545993E-005, -+1.813820381E-005, -+1.683242772E-005, -+1.558924305E-005, -+1.440921824E-005, -+1.329243969E-005, -+1.223855270E-005, -+1.124680875E-005, -+1.031611009E-005, -+9.445050637E-006, -+8.631964192E-006, -+7.874960829E-006, -+7.171964626E-006, -+6.520755960E-006, -+5.918994248E-006, -+5.364252502E-006, -+4.854050530E-006, -+4.385879038E-006, -+3.957220997E-006, -+3.565570978E-006, -+3.208459020E-006, -+2.883470643E-006, -+2.588257530E-006, -+2.320550948E-006, -+2.078171747E-006, -+1.859034001E-006, -+1.661159786E-006, -+1.482681114E-006, -+1.321840614E-006, -+1.176999604E-006, -+1.046637067E-006, -+9.293416952E-007, -+8.238164355E-007, -+7.288739425E-007, -+6.434325428E-007, -+5.665120852E-007, -+4.972276315E-007, -+4.347855338E-007, -+3.784752209E-007, -+3.276689142E-007, -+2.818143514E-007, -+2.404238444E-007, -+2.030677564E-007, -+1.693738625E-007, -+1.390191784E-007 -}; - -/* pre-scale lfe fir coefficients */ -#define SCALE(c) ((c) / (256.0f * 32768.0f)) -DECLARE_ALIGNED(16, static const float, lfe_fir_64)[] = -{ - SCALE(2.658434386830777e-4), SCALE(9.029330685734748e-3), - SCALE(7.939263433218002e-2), SCALE(2.425158768892288e-1), - SCALE(3.430179357528686e-1), SCALE(2.398228943347931e-1), - SCALE(7.746443897485733e-2), SCALE(8.622321300208569e-3), - SCALE(8.179365249816328e-5), SCALE(9.450953453779220e-3), - SCALE(8.134882897138596e-2), SCALE(2.451938837766648e-1), - SCALE(3.429597318172455e-1), SCALE(2.371159791946411e-1), - SCALE(7.556436210870743e-2), SCALE(8.229630999267101e-3), - SCALE(9.439323912374676e-5), SCALE(9.887560270726680e-3), - SCALE(8.333285897970200e-2), SCALE(2.478559017181396e-1), - SCALE(3.428434133529663e-1), SCALE(2.343961596488952e-1), - SCALE(7.369252294301987e-2), SCALE(7.850865833461285e-3), - SCALE(1.082170274457894e-4), SCALE(1.033949479460716e-2), - SCALE(8.534456789493561e-2), SCALE(2.505008876323700e-1), - SCALE(3.426689505577088e-1), SCALE(2.316644787788391e-1), - SCALE(7.184901088476181e-2), SCALE(7.485736627131701e-3), - SCALE(1.233371440321207e-4), SCALE(1.080708485096693e-2), - SCALE(8.738376945257187e-2), SCALE(2.531278133392334e-1), - SCALE(3.424364924430847e-1), SCALE(2.289219647645950e-1), - SCALE(7.003392279148102e-2), SCALE(7.133882027119398e-3), - SCALE(1.397485757479444e-4), SCALE(1.129068247973919e-2), - SCALE(8.945026248693466e-2), SCALE(2.557355761528015e-1), - SCALE(3.421461284160614e-1), SCALE(2.261696159839630e-1), - SCALE(6.824731826782227e-2), SCALE(6.794991903007030e-3), - SCALE(1.575958012836054e-4), SCALE(1.179065089672804e-2), - SCALE(9.154383838176728e-2), SCALE(2.583232223987580e-1), - SCALE(3.417979776859284e-1), SCALE(2.234084606170654e-1), - SCALE(6.648923456668854e-2), SCALE(6.468691397458315e-3), - SCALE(1.769922382663936e-4), SCALE(1.230732165277004e-2), - SCALE(9.366425126791000e-2), SCALE(2.608896791934967e-1), - SCALE(3.413922190666198e-1), SCALE(2.206395119428635e-1), - SCALE(6.475970894098282e-2), SCALE(6.154712289571762e-3), - SCALE(1.981738605536520e-4), SCALE(1.284105982631445e-2), - SCALE(9.581124037504196e-2), SCALE(2.634339034557342e-1), - SCALE(3.409290313720703e-1), SCALE(2.178637981414795e-1), - SCALE(6.305878609418869e-2), SCALE(5.852684378623962e-3), - SCALE(2.211847313446924e-4), SCALE(1.339218579232693e-2), - SCALE(9.798453748226166e-2), SCALE(2.659549415111542e-1), - SCALE(3.404086530208588e-1), SCALE(2.150822728872299e-1), - SCALE(6.138643622398376e-2), SCALE(5.562345497310162e-3), - SCALE(2.460231189616024e-4), SCALE(1.396108977496624e-2), - SCALE(1.001838669180870e-1), SCALE(2.684516608715058e-1), - SCALE(3.398312926292420e-1), SCALE(2.122959494590759e-1), - SCALE(5.974265560507774e-2), SCALE(5.283284001052380e-3), - SCALE(2.726115926634520e-4), SCALE(1.454808749258518e-2), - SCALE(1.024089083075523e-1), SCALE(2.709231376647949e-1), - SCALE(3.391972482204438e-1), SCALE(2.095058411359787e-1), - SCALE(5.812742188572884e-2), SCALE(5.015311297029257e-3), - SCALE(3.013863170053810e-4), SCALE(1.515355054289102e-2), - SCALE(1.046593263745308e-1), SCALE(2.733682692050934e-1), - SCALE(3.385068178176880e-1), SCALE(2.067128717899322e-1), - SCALE(5.654069408774376e-2), SCALE(4.758012015372515e-3), - SCALE(3.328395541757345e-4), SCALE(1.577781140804291e-2), - SCALE(1.069347932934761e-1), SCALE(2.757860720157624e-1), - SCALE(3.377602994441986e-1), SCALE(2.039180546998978e-1), - SCALE(5.498242005705833e-2), SCALE(4.511159844696522e-3), - SCALE(3.658991190604866e-4), SCALE(1.642123050987720e-2), - SCALE(1.092349365353584e-1), SCALE(2.781755328178406e-1), - SCALE(3.369580209255218e-1), SCALE(2.011223286390304e-1), - SCALE(5.345252528786659e-2), SCALE(4.274417180567980e-3), - SCALE(4.018281470052898e-4), SCALE(1.708412915468216e-2), - SCALE(1.115593686699867e-1), SCALE(2.805356979370117e-1), - SCALE(3.361004292964936e-1), SCALE(1.983266174793244e-1), - SCALE(5.195093154907227e-2), SCALE(4.047499038279056e-3), - SCALE(4.401875485200435e-4), SCALE(1.776690222322941e-2), - SCALE(1.139076948165894e-1), SCALE(2.828655838966370e-1), - SCALE(3.351879119873047e-1), SCALE(1.955319195985794e-1), - SCALE(5.047753453254700e-2), SCALE(3.830091329291463e-3), - SCALE(4.812776169274002e-4), SCALE(1.846982724964619e-2), - SCALE(1.162794977426529e-1), SCALE(2.851640880107880e-1), - SCALE(3.342207968235016e-1), SCALE(1.927391141653061e-1), - SCALE(4.903224110603333e-2), SCALE(3.621967276558280e-3), - SCALE(5.252459668554366e-4), SCALE(1.919330470263958e-2), - SCALE(1.186743453145027e-1), SCALE(2.874303460121155e-1), - SCALE(3.331996202468872e-1), SCALE(1.899491697549820e-1), - SCALE(4.761491715908051e-2), SCALE(3.422776935622096e-3), - SCALE(5.721592460758984e-4), SCALE(1.993762329220772e-2), - SCALE(1.210917681455612e-1), SCALE(2.896633744239807e-1), - SCALE(3.321248590946198e-1), SCALE(1.871629506349564e-1), - SCALE(4.622544348239899e-2), SCALE(3.232272574678064e-3), - SCALE(6.222130032256246e-4), SCALE(2.070316113531590e-2), - SCALE(1.235313042998314e-1), SCALE(2.918621897697448e-1), - SCALE(3.309969604015350e-1), SCALE(1.843813359737396e-1), - SCALE(4.486365616321564e-2), SCALE(3.050152910873294e-3), - SCALE(6.755515350960195e-4), SCALE(2.149021252989769e-2), - SCALE(1.259924471378326e-1), SCALE(2.940258979797364e-1), - SCALE(3.298164308071136e-1), SCALE(1.816052496433258e-1), - SCALE(4.352942481637001e-2), SCALE(2.876190468668938e-3), - SCALE(7.324148900806904e-4), SCALE(2.229913882911205e-2), - SCALE(1.284746825695038e-1), SCALE(2.961534857749939e-1), - SCALE(3.285838961601258e-1), SCALE(1.788355410099030e-1), - SCALE(4.222255200147629e-2), SCALE(2.710093278437853e-3), - SCALE(7.928516715764999e-4), SCALE(2.313023805618286e-2), - SCALE(1.309774816036224e-1), SCALE(2.982441186904907e-1), - SCALE(3.272998929023742e-1), SCALE(1.760730892419815e-1), - SCALE(4.094288870692253e-2), SCALE(2.551567042246461e-3), - SCALE(8.570110658183694e-4), SCALE(2.398385666310787e-2), - SCALE(1.335003077983856e-1), SCALE(3.002967536449432e-1), - SCALE(3.259649574756622e-1), SCALE(1.733186990022659e-1), - SCALE(3.969023004174232e-2), SCALE(2.400433411821723e-3), - SCALE(9.251192095689476e-4), SCALE(2.486028522253036e-2), - SCALE(1.360425949096680e-1), SCALE(3.023106753826142e-1), - SCALE(3.245797157287598e-1), SCALE(1.705732345581055e-1), - SCALE(3.846437484025955e-2), SCALE(2.256359672173858e-3), - SCALE(9.974770946428180e-4), SCALE(2.575986087322235e-2), - SCALE(1.386037617921829e-1), SCALE(3.042849004268646e-1), - SCALE(3.231448531150818e-1), SCALE(1.678375005722046e-1), - SCALE(3.726511076092720e-2), SCALE(2.119151875376701e-3), - SCALE(1.073930296115577e-3), SCALE(2.668286114931106e-2), - SCALE(1.411831974983215e-1), SCALE(3.062185347080230e-1), - SCALE(3.216609656810760e-1), SCALE(1.651122719049454e-1), - SCALE(3.609224036335945e-2), SCALE(1.988604199141264e-3), - SCALE(1.155023579485714e-3), SCALE(2.762960828840732e-2), - SCALE(1.437802612781525e-1), SCALE(3.081108033657074e-1), - SCALE(3.201287388801574e-1), SCALE(1.623983532190323e-1), - SCALE(3.494550660252571e-2), SCALE(1.864377525635064e-3), - SCALE(1.240676851011813e-3), SCALE(2.860039286315441e-2), - SCALE(1.463943719863892e-1), SCALE(3.099608123302460e-1), - SCALE(3.185488879680634e-1), SCALE(1.596965193748474e-1), - SCALE(3.382468968629837e-2), SCALE(1.746327499859035e-3), - SCALE(1.331258914433420e-3), SCALE(2.959549613296986e-2), - SCALE(1.490248143672943e-1), SCALE(3.117676973342896e-1), - SCALE(3.169221282005310e-1), SCALE(1.570075154304504e-1), - SCALE(3.272953629493714e-2), SCALE(1.634211512282491e-3), - SCALE(1.426893868483603e-3), SCALE(3.061520494520664e-2), - SCALE(1.516709625720978e-1), SCALE(3.135308027267456e-1), - SCALE(3.152491748332978e-1), SCALE(1.543320864439010e-1), - SCALE(3.165979683399200e-2), SCALE(1.527829794213176e-3), -}; - -DECLARE_ALIGNED(16, static const float, lfe_fir_128)[] = -{ - SCALE(0.00053168571), SCALE(0.15878495574), SCALE(0.68603444099), SCALE(0.15492856503), - SCALE(0.00016358691), SCALE(0.16269733012), SCALE(0.68591803312), SCALE(0.15112841129), - SCALE(0.00018878609), SCALE(0.16666537523), SCALE(0.68568539619), SCALE(0.14738474786), - SCALE(0.00021643363), SCALE(0.17068879306), SCALE(0.68533653021), SCALE(0.14369773865), - SCALE(0.00024667382), SCALE(0.17476719618), SCALE(0.68487155437), SCALE(0.14006754756), - SCALE(0.00027949660), SCALE(0.17890018225), SCALE(0.68429082632), SCALE(0.13649433851), - SCALE(0.00031519096), SCALE(0.18308731914), SCALE(0.68359452486), SCALE(0.13297818601), - SCALE(0.00035398375), SCALE(0.18732811511), SCALE(0.68278300762), SCALE(0.12951917946), - SCALE(0.00039634691), SCALE(0.19162209332), SCALE(0.68185669184), SCALE(0.12611730397), - SCALE(0.00044236859), SCALE(0.19596865773), SCALE(0.68081587553), SCALE(0.12277261168), - SCALE(0.00049204525), SCALE(0.20036731660), SCALE(0.67966115475), SCALE(0.11948505789), - SCALE(0.00054522208), SCALE(0.20481738448), SCALE(0.67839306593), SCALE(0.11625462025), - SCALE(0.00060277141), SCALE(0.20931822062), SCALE(0.67701220512), SCALE(0.11308115721), - SCALE(0.00066567765), SCALE(0.21386915445), SCALE(0.67551922798), SCALE(0.10996460915), - SCALE(0.00073179678), SCALE(0.21846942604), SCALE(0.67391467094), SCALE(0.10690483451), - SCALE(0.00080365466), SCALE(0.22311829031), SCALE(0.67219948769), SCALE(0.10390164703), - SCALE(0.00088037323), SCALE(0.22781492770), SCALE(0.67037439346), SCALE(0.10095486045), - SCALE(0.00096255314), SCALE(0.23255851865), SCALE(0.66844022274), SCALE(0.09806428105), - SCALE(0.00105048984), SCALE(0.23734821379), SCALE(0.66639786959), SCALE(0.09522963315), - SCALE(0.00114431616), SCALE(0.24218304455), SCALE(0.66424828768), SCALE(0.09245070815), - SCALE(0.00124442333), SCALE(0.24706205726), SCALE(0.66199249029), SCALE(0.08972713351), - SCALE(0.00135110028), SCALE(0.25198432803), SCALE(0.65963155031), SCALE(0.08705867827), - SCALE(0.00146482687), SCALE(0.25694879889), SCALE(0.65716648102), SCALE(0.08444493264), - SCALE(0.00158570008), SCALE(0.26195442677), SCALE(0.65459835529), SCALE(0.08188561350), - SCALE(0.00171401864), SCALE(0.26700007915), SCALE(0.65192854404), SCALE(0.07938029617), - SCALE(0.00185023469), SCALE(0.27208462358), SCALE(0.64915806055), SCALE(0.07692859322), - SCALE(0.00199495023), SCALE(0.27720692754), SCALE(0.64628833532), SCALE(0.07453006506), - SCALE(0.00214785640), SCALE(0.28236576915), SCALE(0.64332056046), SCALE(0.07218432426), - SCALE(0.00231004250), SCALE(0.28755992651), SCALE(0.64025616646), SCALE(0.06989086419), - SCALE(0.00248134881), SCALE(0.29278811812), SCALE(0.63709646463), SCALE(0.06764923781), - SCALE(0.00266251224), SCALE(0.29804900289), SCALE(0.63384294510), SCALE(0.06545893103), - SCALE(0.00285378192), SCALE(0.30334126949), SCALE(0.63049703836), SCALE(0.06331945211), - SCALE(0.00305565330), SCALE(0.30866351724), SCALE(0.62706029415), SCALE(0.06123027951), - SCALE(0.00326841651), SCALE(0.31401440501), SCALE(0.62353414297), SCALE(0.05919086933), - SCALE(0.00349264755), SCALE(0.31939238310), SCALE(0.61992025375), SCALE(0.05720067024), - SCALE(0.00372874714), SCALE(0.32479602098), SCALE(0.61622029543), SCALE(0.05525910854), - SCALE(0.00397720048), SCALE(0.33022382855), SCALE(0.61243581772), SCALE(0.05336561054), - SCALE(0.00423829490), SCALE(0.33567428589), SCALE(0.60856848955), SCALE(0.05151961371), - SCALE(0.00451271003), SCALE(0.34114575386), SCALE(0.60462015867), SCALE(0.04972046614), - SCALE(0.00480085658), SCALE(0.34663668275), SCALE(0.60059231520), SCALE(0.04796761274), - SCALE(0.00510312291), SCALE(0.35214546323), SCALE(0.59648692608), SCALE(0.04626038298), - SCALE(0.00542017492), SCALE(0.35767036676), SCALE(0.59230577946), SCALE(0.04459818453), - SCALE(0.00575236930), SCALE(0.36320972443), SCALE(0.58805054426), SCALE(0.04298033938), - SCALE(0.00610029325), SCALE(0.36876192689), SCALE(0.58372318745), SCALE(0.04140623659), - SCALE(0.00646453211), SCALE(0.37432509661), SCALE(0.57932555676), SCALE(0.03987516090), - SCALE(0.00684553990), SCALE(0.37989753485), SCALE(0.57485944033), SCALE(0.03838652745), - SCALE(0.00724391919), SCALE(0.38547745347), SCALE(0.57032698393), SCALE(0.03693958372), - SCALE(0.00766016589), SCALE(0.39106300473), SCALE(0.56572991610), SCALE(0.03553372994), - SCALE(0.00809498038), SCALE(0.39665243030), SCALE(0.56107026339), SCALE(0.03416819125), - SCALE(0.00854881573), SCALE(0.40224379301), SCALE(0.55634999275), SCALE(0.03284239396), - SCALE(0.00902230106), SCALE(0.40783521533), SCALE(0.55157101154), SCALE(0.03155555204), - SCALE(0.00951600447), SCALE(0.41342487931), SCALE(0.54673534632), SCALE(0.03030703776), - SCALE(0.01003060210), SCALE(0.41901078820), SCALE(0.54184508324), SCALE(0.02909611352), - SCALE(0.01056654565), SCALE(0.42459106445), SCALE(0.53690224886), SCALE(0.02792212367), - SCALE(0.01112466771), SCALE(0.43016362190), SCALE(0.53190881014), SCALE(0.02678431384), - SCALE(0.01170534454), SCALE(0.43572667241), SCALE(0.52686679363), SCALE(0.02568206564), - SCALE(0.01230939943), SCALE(0.44127810001), SCALE(0.52177828550), SCALE(0.02461459488), - SCALE(0.01293735672), SCALE(0.44681602716), SCALE(0.51664537191), SCALE(0.02358125709), - SCALE(0.01358995494), SCALE(0.45233830810), SCALE(0.51147013903), SCALE(0.02258131653), - SCALE(0.01426773332), SCALE(0.45784294605), SCALE(0.50625455379), SCALE(0.02161412500), - SCALE(0.01497144438), SCALE(0.46332800388), SCALE(0.50100076199), SCALE(0.02067894675), - SCALE(0.01570170000), SCALE(0.46879136562), SCALE(0.49571081996), SCALE(0.01977507770), - SCALE(0.01645922661), SCALE(0.47423094511), SCALE(0.49038675427), SCALE(0.01890186779), - SCALE(0.01724460535), SCALE(0.47964480519), SCALE(0.48503074050), SCALE(0.01805862412), -}; -#undef SCALE - -/* - * D.11 Look-up Table for Downmix Scale Factors - * - * Note that the range of the entries in DmixTable[] is between -60 dB and 0 dB - * with addition of -inf (|DMixCoeff| = 0), which is coded with a DmixCode = 0. - * Furthermore, the range [-60 to 0] is subdivided into 3 regions, each with a - * different grid resolution: - * - * 1) [-60.000 to -30] with resolution of 0.500 dB - * 2) [-29.750 to -15] with resolution of 0.250 dB - * 3) [-14.875 to 0] with resolution of 0.125 dB - */ -static const uint16_t dca_dmixtable[242] = { - 0, 33, 35, 37, 39, 41, 44, 46, - 49, 52, 55, 58, 62, 65, 69, 73, - 78, 82, 87, 92, 98, 104, 110, 116, - 123, 130, 138, 146, 155, 164, 174, 184, - 195, 207, 219, 232, 246, 260, 276, 292, - 309, 328, 347, 368, 389, 413, 437, 463, - 490, 519, 550, 583, 617, 654, 693, 734, - 777, 823, 872, 924, 978, 1036, 1066, 1098, - 1130, 1163, 1197, 1232, 1268, 1305, 1343, 1382, - 1422, 1464, 1506, 1550, 1596, 1642, 1690, 1740, - 1790, 1843, 1896, 1952, 2009, 2068, 2128, 2190, - 2254, 2320, 2388, 2457, 2529, 2603, 2679, 2757, - 2838, 2920, 3006, 3093, 3184, 3277, 3372, 3471, - 3572, 3677, 3784, 3894, 4008, 4125, 4246, 4370, - 4497, 4629, 4764, 4903, 5046, 5193, 5345, 5501, - 5662, 5827, 5912, 5997, 6084, 6172, 6262, 6353, - 6445, 6538, 6633, 6729, 6827, 6925, 7026, 7128, - 7231, 7336, 7442, 7550, 7659, 7771, 7883, 7997, - 8113, 8231, 8350, 8471, 8594, 8719, 8845, 8973, - 9103, 9235, 9369, 9505, 9643, 9783, 9924, 10068, - 10214, 10362, 10512, 10665, 10819, 10976, 11135, 11297, - 11460, 11627, 11795, 11966, 12139, 12315, 12494, 12675, - 12859, 13045, 13234, 13426, 13621, 13818, 14018, 14222, - 14428, 14637, 14849, 15064, 15283, 15504, 15729, 15957, - 16188, 16423, 16661, 16902, 17147, 17396, 17648, 17904, - 18164, 18427, 18694, 18965, 19240, 19519, 19802, 20089, - 20380, 20675, 20975, 21279, 21587, 21900, 22218, 22540, - 22867, 23170, 23534, 23875, 24221, 24573, 24929, 25290, - 25657, 26029, 26406, 26789, 27177, 27571, 27970, 28376, - 28787, 29205, 29628, 30057, 30493, 30935, 31383, 31838, - 32300, 32768, -}; - -static const float dca_default_coeffs[10][6][2] = { - { { 0.707107, 0.707107 }, { 0.000000, 0.000000 }, }, // A [LFE] - { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // A + B (dual mono) [LFE] - { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // L + R (stereo) [LFE] - { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // (L+R) + (L-R) (sum-difference) [LFE] - { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // LT + RT (left and right total) [LFE] - { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.000000, 0.000000 }, }, // C + L + R [LFE] - { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + S [LFE] - { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + S [LFE] - { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + SL + SR [LFE] - { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + SL + SR [LFE] -}; - -/* downmix coeffs - - TABLE 9 -______________________________________ -Down-mix coefficients for 8-channel source -audio (5 + 3 format) - lt - cen- rt lt ctr rt -lt ter ctr center - rt srd srd srd -______________________________________ -1 0.71 0.74 1.0 0.71 0.71 0.58 0.58 0.58 -2 left 1.0 0.89 0.71 0.46 0.71 0.50 - rt 0.45 0.71 0.89 1.0 0.50 0.71 -3 lt 1.0 0.89 0.71 0.45 - rt 0.45 0.71 0.89 1.0 - srd 0.71 0.71 0.71 -4 lt 1.0 0.89 0.71 0.45 - rt 0.45 0.71 0.89 1.0 - lt srd 1.0 0.71 - rt srd 0.71 0.71 -4 lt 1.0 0.5 - ctr 0.87 1.0 0.87 - rt 0.5 1.0 - srd 0.71 0.71 0.71 -5 lt 1.0 0.5 - ctr 0.87 1.0 0.87 - rt 0.5 1.0 - lt srd 1.0 0.71 - rt srd 0.71 1.0 -6 lt 1.0 0.5 - lt ctr 0.87 0.71 - rt ctr 0.71 0.87 - rt 0.5 1.0 - lt srd 1.0 0.71 - rt srd 0.71 1.0 -6 lt 1.0 0.5 - ctr 0.86 1.0 0.86 - rt 0.5 1.0 - lt srd 1.0 - ctr srd 1.0 - rt srd 1.0 -7 lt 1.0 - lt ctr 1.0 - ctr 1.0 - rt ctr 1.0 - rt 1.0 - lt srd 1.0 0.71 - rt srd 0.71 1.0 -7 lt 1.0 0.5 - lt ctr 0.87 0.71 - rt ctr 0.71 0.87 - rt 0.5 1.0 - lt srd 1.0 - ctr srd 1.0 - rt srd 1.0 -8 lt 1.0 0.5 - lt ctr 0.87 0.71 - rt ctr 0.71 0.87 - rt 0.5 1.0 - lt 1 srd 0.87 0.35 - lt 2 srd 0.5 0.61 - rt 2 srd 0.61 0.50 - rt 2 srd 0.35 0.87 - - Generation of Lt Rt - -In the case when the playback system has analog or digital surround multi-channel capability, a down matrix from 5, 4, or 3 channel to Lt Rt may be desirable. In the case when the number of decoded audio channels exceeds 5, 4 or 3 respectively a first stage down mix to 5, 4 or 3 chs should be used as described above. - -The down matrixing equations for 5-channel source audio to a two-channel Lt Rt playback system are given by: - -Left left+0.7*center-0.7*(lt surround+rt surround) - -Right=right+0.7*center+0.7*(lt surround+rt surround) - -Embedded mixing to 2-channel - -One concern arising from the proliferation of multi-channel audio systems is that most home systems presently have only two channel playback capability. To accommodate this a fixed 2-channel down matrix processes is commonly used following the multi-channel decoding stage. However, for music only applications the image quality etc. of the down matrixed signal may not match that of an equivalent stereo recording found on CD. - -The concept of embedded mixing is to allow the producer to dynamically specify the matrixing coefficients within the audio frame itself. In this way the stereo down mix at the decoder may be better matched to a 2-channel playback environment. - -CHS*2, 7-bit down mix indexes (MCOEFFS) are transmitted along with the multi-channel audio once in every frame. The indexes are converted to attenuation factors using a 7 bit LUT. The 2-ch down mix equations are as follows, - -Left Ch=sum (MCOEFF[n]*Ch[n]) for n=1, CHS - -Right Ch sum (MCOEFF[n+CHS]*Ch[n]) for n=1, CHS - -where Ch(n) represents the subband samples in the (n)th audio channel. - - -*/ +extern const uint16_t ff_dca_vlc_offs[63]; #endif /* AVCODEC_DCADATA_H */ diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index e988e94..c82c54e 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -4,6 +4,8 @@ * Copyright (C) 2004 Benjamin Zores * Copyright (C) 2006 Benjamin Larsson * Copyright (C) 2007 Konstantin Shishkov + * Copyright (C) 2012 Paul B Mahol + * Copyright (C) 2014 Niels Möller * * This file is part of Libav. * @@ -26,6 +28,7 @@ #include #include +#include "libavutil/attributes.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/float_dsp.h" @@ -34,32 +37,26 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/samplefmt.h" + #include "avcodec.h" -#include "fft.h" -#include "get_bits.h" -#include "put_bits.h" -#include "dcadata.h" -#include "dcahuff.h" #include "dca.h" -#include "mathops.h" -#include "synth_filter.h" +#include "dca_syncwords.h" +#include "dcadata.h" #include "dcadsp.h" +#include "dcahuff.h" +#include "fft.h" #include "fmtconvert.h" +#include "get_bits.h" #include "internal.h" +#include "mathops.h" +#include "profiles.h" +#include "put_bits.h" +#include "synth_filter.h" #if ARCH_ARM # include "arm/dca.h" #endif -//#define TRACE - -#define DCA_PRIM_CHANNELS_MAX (7) -#define DCA_ABITS_MAX (32) /* Should be 28 */ -#define DCA_SUBSUBFRAMES_MAX (4) -#define DCA_SUBFRAMES_MAX (16) -#define DCA_BLOCKS_MAX (16) -#define DCA_LFE_MAX (3) - enum DCAMode { DCA_MONO = 0, DCA_CHANNEL, @@ -74,39 +71,6 @@ enum DCAMode { DCA_4F2R }; -/* these are unconfirmed but should be mostly correct */ -enum DCAExSSSpeakerMask { - DCA_EXSS_FRONT_CENTER = 0x0001, - DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002, - DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004, - DCA_EXSS_LFE = 0x0008, - DCA_EXSS_REAR_CENTER = 0x0010, - DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020, - DCA_EXSS_REAR_LEFT_RIGHT = 0x0040, - DCA_EXSS_FRONT_HIGH_CENTER = 0x0080, - DCA_EXSS_OVERHEAD = 0x0100, - DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200, - DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400, - DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800, - DCA_EXSS_LFE2 = 0x1000, - DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000, - DCA_EXSS_REAR_HIGH_CENTER = 0x4000, - DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000, -}; - -enum DCAExtensionMask { - DCA_EXT_CORE = 0x001, ///< core in core substream - DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream - DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream - DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream - DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream) - DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS - DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS - DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS - DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS - DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS -}; - /* -1 are reserved or unknown */ static const int dca_ext_audio_descr_mask[] = { DCA_EXT_XCH, @@ -119,9 +83,6 @@ static const int dca_ext_audio_descr_mask[] = { -1, }; -/* extensions that reside in core substream */ -#define DCA_CORE_EXTS (DCA_EXT_XCH | DCA_EXT_XXCH | DCA_EXT_X96) - /* Tables for mapping dts channel configurations to libavcodec multichannel api. * Some compromises have been made for special configurations. Most configurations * are never used so complete accuracy is not needed. @@ -168,86 +129,6 @@ static const uint64_t dca_core_channel_layout[] = { AV_CH_SIDE_LEFT | AV_CH_BACK_CENTER | AV_CH_SIDE_RIGHT, ///< 8, CL + C + CR + L + R + SL + S + SR }; -static const int8_t dca_lfe_index[] = { - 1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3 -}; - -static const int8_t dca_channel_reorder_lfe[][9] = { - { 0, -1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, -1, -1, -1, -1, -1, -1}, - { 0, 1, 3, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, 4, -1, -1, -1, -1, -1}, - { 0, 1, 3, 4, -1, -1, -1, -1, -1}, - { 2, 0, 1, 4, 5, -1, -1, -1, -1}, - { 3, 4, 0, 1, 5, 6, -1, -1, -1}, - { 2, 0, 1, 4, 5, 6, -1, -1, -1}, - { 0, 6, 4, 5, 2, 3, -1, -1, -1}, - { 4, 2, 5, 0, 1, 6, 7, -1, -1}, - { 5, 6, 0, 1, 7, 3, 8, 4, -1}, - { 4, 2, 5, 0, 1, 6, 8, 7, -1}, -}; - -static const int8_t dca_channel_reorder_lfe_xch[][9] = { - { 0, 2, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, 3, -1, -1, -1, -1, -1, -1}, - { 0, 1, 3, -1, -1, -1, -1, -1, -1}, - { 0, 1, 3, -1, -1, -1, -1, -1, -1}, - { 0, 1, 3, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, 4, -1, -1, -1, -1, -1}, - { 0, 1, 3, 4, -1, -1, -1, -1, -1}, - { 2, 0, 1, 4, 5, -1, -1, -1, -1}, - { 0, 1, 4, 5, 3, -1, -1, -1, -1}, - { 2, 0, 1, 5, 6, 4, -1, -1, -1}, - { 3, 4, 0, 1, 6, 7, 5, -1, -1}, - { 2, 0, 1, 4, 5, 6, 7, -1, -1}, - { 0, 6, 4, 5, 2, 3, 7, -1, -1}, - { 4, 2, 5, 0, 1, 7, 8, 6, -1}, - { 5, 6, 0, 1, 8, 3, 9, 4, 7}, - { 4, 2, 5, 0, 1, 6, 9, 8, 7}, -}; - -static const int8_t dca_channel_reorder_nolfe[][9] = { - { 0, -1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, -1, -1, -1, -1, -1, -1}, - { 0, 1, 2, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, 3, -1, -1, -1, -1, -1}, - { 0, 1, 2, 3, -1, -1, -1, -1, -1}, - { 2, 0, 1, 3, 4, -1, -1, -1, -1}, - { 2, 3, 0, 1, 4, 5, -1, -1, -1}, - { 2, 0, 1, 3, 4, 5, -1, -1, -1}, - { 0, 5, 3, 4, 1, 2, -1, -1, -1}, - { 3, 2, 4, 0, 1, 5, 6, -1, -1}, - { 4, 5, 0, 1, 6, 2, 7, 3, -1}, - { 3, 2, 4, 0, 1, 5, 7, 6, -1}, -}; - -static const int8_t dca_channel_reorder_nolfe_xch[][9] = { - { 0, 1, -1, -1, -1, -1, -1, -1, -1}, - { 0, 1, 2, -1, -1, -1, -1, -1, -1}, - { 0, 1, 2, -1, -1, -1, -1, -1, -1}, - { 0, 1, 2, -1, -1, -1, -1, -1, -1}, - { 0, 1, 2, -1, -1, -1, -1, -1, -1}, - { 2, 0, 1, 3, -1, -1, -1, -1, -1}, - { 0, 1, 2, 3, -1, -1, -1, -1, -1}, - { 2, 0, 1, 3, 4, -1, -1, -1, -1}, - { 0, 1, 3, 4, 2, -1, -1, -1, -1}, - { 2, 0, 1, 4, 5, 3, -1, -1, -1}, - { 2, 3, 0, 1, 5, 6, 4, -1, -1}, - { 2, 0, 1, 3, 4, 5, 6, -1, -1}, - { 0, 5, 3, 4, 1, 2, 6, -1, -1}, - { 3, 2, 4, 0, 1, 6, 7, 5, -1}, - { 4, 5, 0, 1, 7, 2, 8, 3, 6}, - { 3, 2, 4, 0, 1, 5, 8, 7, 6}, -}; - #define DCA_DOLBY 101 /* FIXME */ #define DCA_CHANNEL_BITS 6 @@ -257,15 +138,10 @@ static const int8_t dca_channel_reorder_nolfe_xch[][9] = { #define HEADER_SIZE 14 -#define DCA_MAX_FRAME_SIZE 16384 -#define DCA_MAX_EXSS_HEADER_SIZE 4096 - -#define DCA_BUFFER_PADDING_SIZE 1024 - #define DCA_NSYNCAUX 0x9A1105A0 /** Bit allocation */ -typedef struct { +typedef struct BitAlloc { int offset; ///< code values offset int maxbits[8]; ///< max bits in VLC int wrap; ///< wrap for get_vlc2() @@ -284,132 +160,6 @@ static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba, ba->offset; } -typedef struct { - AVClass *class; ///< class for AVOptions - AVCodecContext *avctx; - /* Frame header */ - int frame_type; ///< type of the current frame - int samples_deficit; ///< deficit sample count - int crc_present; ///< crc is present in the bitstream - int sample_blocks; ///< number of PCM sample blocks - int frame_size; ///< primary frame byte size - int amode; ///< audio channels arrangement - int sample_rate; ///< audio sampling rate - int bit_rate; ///< transmission bit rate - int bit_rate_index; ///< transmission bit rate index - - int dynrange; ///< embedded dynamic range flag - int timestamp; ///< embedded time stamp flag - int aux_data; ///< auxiliary data flag - int hdcd; ///< source material is mastered in HDCD - int ext_descr; ///< extension audio descriptor flag - int ext_coding; ///< extended coding flag - int aspf; ///< audio sync word insertion flag - int lfe; ///< low frequency effects flag - int predictor_history; ///< predictor history flag - int header_crc; ///< header crc check bytes - int multirate_inter; ///< multirate interpolator switch - int version; ///< encoder software revision - int copy_history; ///< copy history - int source_pcm_res; ///< source pcm resolution - int front_sum; ///< front sum/difference flag - int surround_sum; ///< surround sum/difference flag - int dialog_norm; ///< dialog normalisation parameter - - /* Primary audio coding header */ - int subframes; ///< number of subframes - int total_channels; ///< number of channels including extensions - int prim_channels; ///< number of primary audio channels - int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count - int vq_start_subband[DCA_PRIM_CHANNELS_MAX]; ///< high frequency vq start subband - int joint_intensity[DCA_PRIM_CHANNELS_MAX]; ///< joint intensity coding index - int transient_huffman[DCA_PRIM_CHANNELS_MAX]; ///< transient mode code book - int scalefactor_huffman[DCA_PRIM_CHANNELS_MAX]; ///< scale factor code book - int bitalloc_huffman[DCA_PRIM_CHANNELS_MAX]; ///< bit allocation quantizer select - int quant_index_huffman[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< quantization index codebook select - float scalefactor_adj[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< scale factor adjustment - - /* Primary audio coding side information */ - int subsubframes[DCA_SUBFRAMES_MAX]; ///< number of subsubframes - int partial_samples[DCA_SUBFRAMES_MAX]; ///< partial subsubframe samples count - int prediction_mode[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< prediction mode (ADPCM used or not) - int prediction_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< prediction VQ coefs - int bitalloc[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< bit allocation index - int transition_mode[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< transition mode (transients) - int32_t scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2];///< scale factors (2 if transient) - int joint_huff[DCA_PRIM_CHANNELS_MAX]; ///< joint subband scale factors codebook - int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors - float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients - int dynrange_coef; ///< dynamic range coefficient - - /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1) - * Input: primary audio channels (incl. LFE if present) - * Output: downmix audio channels (up to 4, no LFE) */ - uint8_t core_downmix; ///< embedded downmix coefficients available - uint8_t core_downmix_amode; ///< audio channel arrangement of embedded downmix - uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< embedded downmix coefficients (9-bit codes) - - int32_t high_freq_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< VQ encoded high frequency subbands - - float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data - int lfe_scale_factor; - - /* Subband samples history (for ADPCM) */ - DECLARE_ALIGNED(16, float, subband_samples_hist)[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][4]; - DECLARE_ALIGNED(32, float, subband_fir_hist)[DCA_PRIM_CHANNELS_MAX][512]; - DECLARE_ALIGNED(32, float, subband_fir_noidea)[DCA_PRIM_CHANNELS_MAX][32]; - int hist_index[DCA_PRIM_CHANNELS_MAX]; - DECLARE_ALIGNED(32, float, raXin)[32]; - - int output; ///< type of output - - DECLARE_ALIGNED(32, float, subband_samples)[DCA_BLOCKS_MAX][DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8]; - float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1]; - float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1]; - uint8_t *extra_channels_buffer; - unsigned int extra_channels_buffer_size; - - uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE]; - int dca_buffer_size; ///< how much data is in the dca_buffer - - const int8_t *channel_order_tab; ///< channel reordering table, lfe and non lfe - GetBitContext gb; - /* Current position in DCA frame */ - int current_subframe; - int current_subsubframe; - - int core_ext_mask; ///< present extensions in the core substream - - /* XCh extension information */ - int xch_present; ///< XCh extension present and valid - int xch_base_channel; ///< index of first (only) channel containing XCH data - int xch_disable; ///< whether the XCh extension should be decoded or not - - /* ExSS header parser */ - int static_fields; ///< static fields present - int mix_metadata; ///< mixing metadata present - int num_mix_configs; ///< number of mix out configurations - int mix_config_num_ch[4]; ///< number of channels in each mix out configuration - - int profile; - - int debug_flag; ///< used for suppressing repeated error messages output - AVFloatDSPContext fdsp; - FFTContext imdct; - SynthFilterContext synth; - DCADSPContext dcadsp; - FmtConvertContext fmt_conv; -} DCAContext; - -static const uint16_t dca_vlc_offs[] = { - 0, 512, 640, 768, 1282, 1794, 2436, 3080, 3770, 4454, 5364, - 5372, 5380, 5388, 5392, 5396, 5412, 5420, 5428, 5460, 5492, 5508, - 5572, 5604, 5668, 5796, 5860, 5892, 6412, 6668, 6796, 7308, 7564, - 7820, 8076, 8620, 9132, 9388, 9910, 10166, 10680, 11196, 11726, 12240, - 12752, 13298, 13810, 14326, 14840, 15500, 16022, 16540, 17158, 17678, 18264, - 18796, 19352, 19926, 20468, 21472, 22398, 23014, 23622, -}; - static av_cold void dca_init_vlcs(void) { static int vlcs_initialized = 0; @@ -420,28 +170,28 @@ static av_cold void dca_init_vlcs(void) return; dca_bitalloc_index.offset = 1; - dca_bitalloc_index.wrap = 2; + dca_bitalloc_index.wrap = 2; for (i = 0; i < 5; i++) { - dca_bitalloc_index.vlc[i].table = &dca_table[dca_vlc_offs[i]]; - dca_bitalloc_index.vlc[i].table_allocated = dca_vlc_offs[i + 1] - dca_vlc_offs[i]; + dca_bitalloc_index.vlc[i].table = &dca_table[ff_dca_vlc_offs[i]]; + dca_bitalloc_index.vlc[i].table_allocated = ff_dca_vlc_offs[i + 1] - ff_dca_vlc_offs[i]; init_vlc(&dca_bitalloc_index.vlc[i], bitalloc_12_vlc_bits[i], 12, bitalloc_12_bits[i], 1, 1, bitalloc_12_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); } dca_scalefactor.offset = -64; - dca_scalefactor.wrap = 2; + dca_scalefactor.wrap = 2; for (i = 0; i < 5; i++) { - dca_scalefactor.vlc[i].table = &dca_table[dca_vlc_offs[i + 5]]; - dca_scalefactor.vlc[i].table_allocated = dca_vlc_offs[i + 6] - dca_vlc_offs[i + 5]; + dca_scalefactor.vlc[i].table = &dca_table[ff_dca_vlc_offs[i + 5]]; + dca_scalefactor.vlc[i].table_allocated = ff_dca_vlc_offs[i + 6] - ff_dca_vlc_offs[i + 5]; init_vlc(&dca_scalefactor.vlc[i], SCALES_VLC_BITS, 129, scales_bits[i], 1, 1, scales_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); } dca_tmode.offset = 0; - dca_tmode.wrap = 1; + dca_tmode.wrap = 1; for (i = 0; i < 4; i++) { - dca_tmode.vlc[i].table = &dca_table[dca_vlc_offs[i + 10]]; - dca_tmode.vlc[i].table_allocated = dca_vlc_offs[i + 11] - dca_vlc_offs[i + 10]; + dca_tmode.vlc[i].table = &dca_table[ff_dca_vlc_offs[i + 10]]; + dca_tmode.vlc[i].table_allocated = ff_dca_vlc_offs[i + 11] - ff_dca_vlc_offs[i + 10]; init_vlc(&dca_tmode.vlc[i], tmode_vlc_bits[i], 4, tmode_bits[i], 1, 1, tmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); @@ -453,8 +203,8 @@ static av_cold void dca_init_vlcs(void) break; dca_smpl_bitalloc[i + 1].offset = bitalloc_offsets[i]; dca_smpl_bitalloc[i + 1].wrap = 1 + (j > 4); - dca_smpl_bitalloc[i + 1].vlc[j].table = &dca_table[dca_vlc_offs[c]]; - dca_smpl_bitalloc[i + 1].vlc[j].table_allocated = dca_vlc_offs[c + 1] - dca_vlc_offs[c]; + dca_smpl_bitalloc[i + 1].vlc[j].table = &dca_table[ff_dca_vlc_offs[c]]; + dca_smpl_bitalloc[i + 1].vlc[j].table_allocated = ff_dca_vlc_offs[c + 1] - ff_dca_vlc_offs[c]; init_vlc(&dca_smpl_bitalloc[i + 1].vlc[j], bitalloc_maxbits[i][j], bitalloc_sizes[i], @@ -474,48 +224,51 @@ static inline void get_array(GetBitContext *gb, int *dst, int len, int bits) static int dca_parse_audio_coding_header(DCAContext *s, int base_channel) { int i, j; - static const float adj_table[4] = { 1.0, 1.1250, 1.2500, 1.4375 }; + static const uint8_t adj_table[4] = { 16, 18, 20, 23 }; static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 }; - s->total_channels = get_bits(&s->gb, 3) + 1 + base_channel; - s->prim_channels = s->total_channels; - - if (s->prim_channels > DCA_PRIM_CHANNELS_MAX) - s->prim_channels = DCA_PRIM_CHANNELS_MAX; + s->audio_header.total_channels = get_bits(&s->gb, 3) + 1 + base_channel; + s->audio_header.prim_channels = s->audio_header.total_channels; + if (s->audio_header.prim_channels > DCA_PRIM_CHANNELS_MAX) + s->audio_header.prim_channels = DCA_PRIM_CHANNELS_MAX; - for (i = base_channel; i < s->prim_channels; i++) { - s->subband_activity[i] = get_bits(&s->gb, 5) + 2; - if (s->subband_activity[i] > DCA_SUBBANDS) - s->subband_activity[i] = DCA_SUBBANDS; + for (i = base_channel; i < s->audio_header.prim_channels; i++) { + s->audio_header.subband_activity[i] = get_bits(&s->gb, 5) + 2; + if (s->audio_header.subband_activity[i] > DCA_SUBBANDS) + s->audio_header.subband_activity[i] = DCA_SUBBANDS; } - for (i = base_channel; i < s->prim_channels; i++) { - s->vq_start_subband[i] = get_bits(&s->gb, 5) + 1; - if (s->vq_start_subband[i] > DCA_SUBBANDS) - s->vq_start_subband[i] = DCA_SUBBANDS; + for (i = base_channel; i < s->audio_header.prim_channels; i++) { + s->audio_header.vq_start_subband[i] = get_bits(&s->gb, 5) + 1; + if (s->audio_header.vq_start_subband[i] > DCA_SUBBANDS) + s->audio_header.vq_start_subband[i] = DCA_SUBBANDS; } - get_array(&s->gb, s->joint_intensity + base_channel, s->prim_channels - base_channel, 3); - get_array(&s->gb, s->transient_huffman + base_channel, s->prim_channels - base_channel, 2); - get_array(&s->gb, s->scalefactor_huffman + base_channel, s->prim_channels - base_channel, 3); - get_array(&s->gb, s->bitalloc_huffman + base_channel, s->prim_channels - base_channel, 3); + get_array(&s->gb, s->audio_header.joint_intensity + base_channel, + s->audio_header.prim_channels - base_channel, 3); + get_array(&s->gb, s->audio_header.transient_huffman + base_channel, + s->audio_header.prim_channels - base_channel, 2); + get_array(&s->gb, s->audio_header.scalefactor_huffman + base_channel, + s->audio_header.prim_channels - base_channel, 3); + get_array(&s->gb, s->audio_header.bitalloc_huffman + base_channel, + s->audio_header.prim_channels - base_channel, 3); /* Get codebooks quantization indexes */ if (!base_channel) - memset(s->quant_index_huffman, 0, sizeof(s->quant_index_huffman)); + memset(s->audio_header.quant_index_huffman, 0, sizeof(s->audio_header.quant_index_huffman)); for (j = 1; j < 11; j++) - for (i = base_channel; i < s->prim_channels; i++) - s->quant_index_huffman[i][j] = get_bits(&s->gb, bitlen[j]); + for (i = base_channel; i < s->audio_header.prim_channels; i++) + s->audio_header.quant_index_huffman[i][j] = get_bits(&s->gb, bitlen[j]); /* Get scale factor adjustment */ for (j = 0; j < 11; j++) - for (i = base_channel; i < s->prim_channels; i++) - s->scalefactor_adj[i][j] = 1; + for (i = base_channel; i < s->audio_header.prim_channels; i++) + s->audio_header.scalefactor_adj[i][j] = 16; for (j = 1; j < 11; j++) - for (i = base_channel; i < s->prim_channels; i++) - if (s->quant_index_huffman[i][j] < thr[j]) - s->scalefactor_adj[i][j] = adj_table[get_bits(&s->gb, 2)]; + for (i = base_channel; i < s->audio_header.prim_channels; i++) + if (s->audio_header.quant_index_huffman[i][j] < thr[j]) + s->audio_header.scalefactor_adj[i][j] = adj_table[get_bits(&s->gb, 2)]; if (s->crc_present) { /* Audio header CRC check */ @@ -525,33 +278,6 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel) s->current_subframe = 0; s->current_subsubframe = 0; -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "subframes: %i\n", s->subframes); - av_log(s->avctx, AV_LOG_DEBUG, "prim channels: %i\n", s->prim_channels); - for (i = base_channel; i < s->prim_channels; i++) { - av_log(s->avctx, AV_LOG_DEBUG, "subband activity: %i\n", - s->subband_activity[i]); - av_log(s->avctx, AV_LOG_DEBUG, "vq start subband: %i\n", - s->vq_start_subband[i]); - av_log(s->avctx, AV_LOG_DEBUG, "joint intensity: %i\n", - s->joint_intensity[i]); - av_log(s->avctx, AV_LOG_DEBUG, "transient mode codebook: %i\n", - s->transient_huffman[i]); - av_log(s->avctx, AV_LOG_DEBUG, "scale factor codebook: %i\n", - s->scalefactor_huffman[i]); - av_log(s->avctx, AV_LOG_DEBUG, "bit allocation quantizer: %i\n", - s->bitalloc_huffman[i]); - av_log(s->avctx, AV_LOG_DEBUG, "quant index huff:"); - for (j = 0; j < 11; j++) - av_log(s->avctx, AV_LOG_DEBUG, " %i", s->quant_index_huffman[i][j]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - av_log(s->avctx, AV_LOG_DEBUG, "scalefac adj:"); - for (j = 0; j < 11; j++) - av_log(s->avctx, AV_LOG_DEBUG, " %1.3f", s->scalefactor_adj[i][j]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } -#endif - return 0; } @@ -575,7 +301,7 @@ static int dca_parse_frame_header(DCAContext *s) if (!s->sample_rate) return AVERROR_INVALIDDATA; s->bit_rate_index = get_bits(&s->gb, 5); - s->bit_rate = dca_bit_rates[s->bit_rate_index]; + s->bit_rate = ff_dca_bit_rates[s->bit_rate_index]; if (!s->bit_rate) return AVERROR_INVALIDDATA; @@ -612,56 +338,18 @@ static int dca_parse_frame_header(DCAContext *s) if (s->lfe) s->output |= DCA_LFE; -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "frame type: %i\n", s->frame_type); - av_log(s->avctx, AV_LOG_DEBUG, "samples deficit: %i\n", s->samples_deficit); - av_log(s->avctx, AV_LOG_DEBUG, "crc present: %i\n", s->crc_present); - av_log(s->avctx, AV_LOG_DEBUG, "sample blocks: %i (%i samples)\n", - s->sample_blocks, s->sample_blocks * 32); - av_log(s->avctx, AV_LOG_DEBUG, "frame size: %i bytes\n", s->frame_size); - av_log(s->avctx, AV_LOG_DEBUG, "amode: %i (%i channels)\n", - s->amode, dca_channels[s->amode]); - av_log(s->avctx, AV_LOG_DEBUG, "sample rate: %i Hz\n", - s->sample_rate); - av_log(s->avctx, AV_LOG_DEBUG, "bit rate: %i bits/s\n", - s->bit_rate); - av_log(s->avctx, AV_LOG_DEBUG, "dynrange: %i\n", s->dynrange); - av_log(s->avctx, AV_LOG_DEBUG, "timestamp: %i\n", s->timestamp); - av_log(s->avctx, AV_LOG_DEBUG, "aux_data: %i\n", s->aux_data); - av_log(s->avctx, AV_LOG_DEBUG, "hdcd: %i\n", s->hdcd); - av_log(s->avctx, AV_LOG_DEBUG, "ext descr: %i\n", s->ext_descr); - av_log(s->avctx, AV_LOG_DEBUG, "ext coding: %i\n", s->ext_coding); - av_log(s->avctx, AV_LOG_DEBUG, "aspf: %i\n", s->aspf); - av_log(s->avctx, AV_LOG_DEBUG, "lfe: %i\n", s->lfe); - av_log(s->avctx, AV_LOG_DEBUG, "predictor history: %i\n", - s->predictor_history); - av_log(s->avctx, AV_LOG_DEBUG, "header crc: %i\n", s->header_crc); - av_log(s->avctx, AV_LOG_DEBUG, "multirate inter: %i\n", - s->multirate_inter); - av_log(s->avctx, AV_LOG_DEBUG, "version number: %i\n", s->version); - av_log(s->avctx, AV_LOG_DEBUG, "copy history: %i\n", s->copy_history); - av_log(s->avctx, AV_LOG_DEBUG, - "source pcm resolution: %i (%i bits/sample)\n", - s->source_pcm_res, dca_bits_per_sample[s->source_pcm_res]); - av_log(s->avctx, AV_LOG_DEBUG, "front sum: %i\n", s->front_sum); - av_log(s->avctx, AV_LOG_DEBUG, "surround sum: %i\n", s->surround_sum); - av_log(s->avctx, AV_LOG_DEBUG, "dialog norm: %i\n", s->dialog_norm); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); -#endif - /* Primary audio coding header */ - s->subframes = get_bits(&s->gb, 4) + 1; + s->audio_header.subframes = get_bits(&s->gb, 4) + 1; return dca_parse_audio_coding_header(s, 0); } - static inline int get_scale(GetBitContext *gb, int level, int value, int log2range) { if (level < 5) { /* huffman encoded */ value += get_bitalloc(gb, &dca_scalefactor, level); - value = av_clip(value, 0, (1 << log2range) - 1); + value = av_clip(value, 0, (1 << log2range) - 1); } else if (level < 8) { if (level + 1 > log2range) { skip_bits(gb, level + 1 - log2range); @@ -686,53 +374,53 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) s->partial_samples[s->current_subframe] = get_bits(&s->gb, 3); } - for (j = base_channel; j < s->prim_channels; j++) { - for (k = 0; k < s->subband_activity[j]; k++) - s->prediction_mode[j][k] = get_bits(&s->gb, 1); + for (j = base_channel; j < s->audio_header.prim_channels; j++) { + for (k = 0; k < s->audio_header.subband_activity[j]; k++) + s->dca_chan[j].prediction_mode[k] = get_bits(&s->gb, 1); } /* Get prediction codebook */ - for (j = base_channel; j < s->prim_channels; j++) { - for (k = 0; k < s->subband_activity[j]; k++) { - if (s->prediction_mode[j][k] > 0) { + for (j = base_channel; j < s->audio_header.prim_channels; j++) { + for (k = 0; k < s->audio_header.subband_activity[j]; k++) { + if (s->dca_chan[j].prediction_mode[k] > 0) { /* (Prediction coefficient VQ address) */ - s->prediction_vq[j][k] = get_bits(&s->gb, 12); + s->dca_chan[j].prediction_vq[k] = get_bits(&s->gb, 12); } } } /* Bit allocation index */ - for (j = base_channel; j < s->prim_channels; j++) { - for (k = 0; k < s->vq_start_subband[j]; k++) { - if (s->bitalloc_huffman[j] == 6) - s->bitalloc[j][k] = get_bits(&s->gb, 5); - else if (s->bitalloc_huffman[j] == 5) - s->bitalloc[j][k] = get_bits(&s->gb, 4); - else if (s->bitalloc_huffman[j] == 7) { + for (j = base_channel; j < s->audio_header.prim_channels; j++) { + for (k = 0; k < s->audio_header.vq_start_subband[j]; k++) { + if (s->audio_header.bitalloc_huffman[j] == 6) + s->dca_chan[j].bitalloc[k] = get_bits(&s->gb, 5); + else if (s->audio_header.bitalloc_huffman[j] == 5) + s->dca_chan[j].bitalloc[k] = get_bits(&s->gb, 4); + else if (s->audio_header.bitalloc_huffman[j] == 7) { av_log(s->avctx, AV_LOG_ERROR, "Invalid bit allocation index\n"); return AVERROR_INVALIDDATA; } else { - s->bitalloc[j][k] = - get_bitalloc(&s->gb, &dca_bitalloc_index, s->bitalloc_huffman[j]); + s->dca_chan[j].bitalloc[k] = + get_bitalloc(&s->gb, &dca_bitalloc_index, s->audio_header.bitalloc_huffman[j]); } - if (s->bitalloc[j][k] > 26) { - av_dlog(s->avctx, "bitalloc index [%i][%i] too big (%i)\n", - j, k, s->bitalloc[j][k]); + if (s->dca_chan[j].bitalloc[k] > 26) { + ff_dlog(s->avctx, "bitalloc index [%i][%i] too big (%i)\n", + j, k, s->dca_chan[j].bitalloc[k]); return AVERROR_INVALIDDATA; } } } /* Transition mode */ - for (j = base_channel; j < s->prim_channels; j++) { - for (k = 0; k < s->subband_activity[j]; k++) { - s->transition_mode[j][k] = 0; + for (j = base_channel; j < s->audio_header.prim_channels; j++) { + for (k = 0; k < s->audio_header.subband_activity[j]; k++) { + s->dca_chan[j].transition_mode[k] = 0; if (s->subsubframes[s->current_subframe] > 1 && - k < s->vq_start_subband[j] && s->bitalloc[j][k] > 0) { - s->transition_mode[j][k] = - get_bitalloc(&s->gb, &dca_tmode, s->transient_huffman[j]); + k < s->audio_header.vq_start_subband[j] && s->dca_chan[j].bitalloc[k] > 0) { + s->dca_chan[j].transition_mode[k] = + get_bitalloc(&s->gb, &dca_tmode, s->audio_header.transient_huffman[j]); } } } @@ -740,63 +428,64 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; - for (j = base_channel; j < s->prim_channels; j++) { + for (j = base_channel; j < s->audio_header.prim_channels; j++) { const uint32_t *scale_table; int scale_sum, log_size; - memset(s->scale_factor[j], 0, - s->subband_activity[j] * sizeof(s->scale_factor[0][0][0]) * 2); + memset(s->dca_chan[j].scale_factor, 0, + s->audio_header.subband_activity[j] * sizeof(s->dca_chan[j].scale_factor[0][0]) * 2); - if (s->scalefactor_huffman[j] == 6) { - scale_table = scale_factor_quant7; - log_size = 7; + if (s->audio_header.scalefactor_huffman[j] == 6) { + scale_table = ff_dca_scale_factor_quant7; + log_size = 7; } else { - scale_table = scale_factor_quant6; - log_size = 6; + scale_table = ff_dca_scale_factor_quant6; + log_size = 6; } /* When huffman coded, only the difference is encoded */ scale_sum = 0; - for (k = 0; k < s->subband_activity[j]; k++) { - if (k >= s->vq_start_subband[j] || s->bitalloc[j][k] > 0) { - scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size); - s->scale_factor[j][k][0] = scale_table[scale_sum]; + for (k = 0; k < s->audio_header.subband_activity[j]; k++) { + if (k >= s->audio_header.vq_start_subband[j] || s->dca_chan[j].bitalloc[k] > 0) { + scale_sum = get_scale(&s->gb, s->audio_header.scalefactor_huffman[j], scale_sum, log_size); + s->dca_chan[j].scale_factor[k][0] = scale_table[scale_sum]; } - if (k < s->vq_start_subband[j] && s->transition_mode[j][k]) { + if (k < s->audio_header.vq_start_subband[j] && s->dca_chan[j].transition_mode[k]) { /* Get second scale factor */ - scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size); - s->scale_factor[j][k][1] = scale_table[scale_sum]; + scale_sum = get_scale(&s->gb, s->audio_header.scalefactor_huffman[j], scale_sum, log_size); + s->dca_chan[j].scale_factor[k][1] = scale_table[scale_sum]; } } } /* Joint subband scale factor codebook select */ - for (j = base_channel; j < s->prim_channels; j++) { + for (j = base_channel; j < s->audio_header.prim_channels; j++) { /* Transmitted only if joint subband coding enabled */ - if (s->joint_intensity[j] > 0) - s->joint_huff[j] = get_bits(&s->gb, 3); + if (s->audio_header.joint_intensity[j] > 0) + s->dca_chan[j].joint_huff = get_bits(&s->gb, 3); } if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; /* Scale factors for joint subband coding */ - for (j = base_channel; j < s->prim_channels; j++) { + for (j = base_channel; j < s->audio_header.prim_channels; j++) { int source_channel; /* Transmitted only if joint subband coding enabled */ - if (s->joint_intensity[j] > 0) { + if (s->audio_header.joint_intensity[j] > 0) { int scale = 0; - source_channel = s->joint_intensity[j] - 1; + source_channel = s->audio_header.joint_intensity[j] - 1; /* When huffman coded, only the difference is encoded * (is this valid as well for joint scales ???) */ - for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++) { - scale = get_scale(&s->gb, s->joint_huff[j], 64 /* bias */, 7); - s->joint_scale_factor[j][k] = scale; /*joint_scale_table[scale]; */ + for (k = s->audio_header.subband_activity[j]; + k < s->audio_header.subband_activity[source_channel]; k++) { + scale = get_scale(&s->gb, s->dca_chan[j].joint_huff, 64 /* bias */, 7); + s->dca_chan[j].joint_scale_factor[k] = scale; /*joint_scale_table[scale]; */ } if (!(s->debug_flag & 0x02)) { @@ -821,15 +510,15 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) */ /* VQ encoded high frequency subbands */ - for (j = base_channel; j < s->prim_channels; j++) - for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++) + for (j = base_channel; j < s->audio_header.prim_channels; j++) + for (k = s->audio_header.vq_start_subband[j]; k < s->audio_header.subband_activity[j]; k++) /* 1 vector -> 32 samples */ - s->high_freq_vq[j][k] = get_bits(&s->gb, 10); + s->dca_chan[j].high_freq_vq[k] = get_bits(&s->gb, 10); /* Low frequency effect data */ if (!base_channel && s->lfe) { /* LFE samples */ - int lfe_samples = 2 * s->lfe * (4 + block_index); + int lfe_samples = 2 * s->lfe * (4 + block_index); int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]); float lfe_scale; @@ -840,7 +529,7 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) /* Scale factor index */ skip_bits(&s->gb, 1); - s->lfe_scale_factor = scale_factor_quant7[get_bits(&s->gb, 7)]; + s->lfe_scale_factor = ff_dca_scale_factor_quant7[get_bits(&s->gb, 7)]; /* Quantization step size * scale factor */ lfe_scale = 0.035 * s->lfe_scale_factor; @@ -849,100 +538,110 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) s->lfe_data[j] *= lfe_scale; } -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "subsubframes: %i\n", - s->subsubframes[s->current_subframe]); - av_log(s->avctx, AV_LOG_DEBUG, "partial samples: %i\n", - s->partial_samples[s->current_subframe]); - - for (j = base_channel; j < s->prim_channels; j++) { - av_log(s->avctx, AV_LOG_DEBUG, "prediction mode:"); - for (k = 0; k < s->subband_activity[j]; k++) - av_log(s->avctx, AV_LOG_DEBUG, " %i", s->prediction_mode[j][k]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - for (j = base_channel; j < s->prim_channels; j++) { - for (k = 0; k < s->subband_activity[j]; k++) - av_log(s->avctx, AV_LOG_DEBUG, - "prediction coefs: %f, %f, %f, %f\n", - (float) adpcm_vb[s->prediction_vq[j][k]][0] / 8192, - (float) adpcm_vb[s->prediction_vq[j][k]][1] / 8192, - (float) adpcm_vb[s->prediction_vq[j][k]][2] / 8192, - (float) adpcm_vb[s->prediction_vq[j][k]][3] / 8192); - } - for (j = base_channel; j < s->prim_channels; j++) { - av_log(s->avctx, AV_LOG_DEBUG, "bitalloc index: "); - for (k = 0; k < s->vq_start_subband[j]; k++) - av_log(s->avctx, AV_LOG_DEBUG, "%2.2i ", s->bitalloc[j][k]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - for (j = base_channel; j < s->prim_channels; j++) { - av_log(s->avctx, AV_LOG_DEBUG, "Transition mode:"); - for (k = 0; k < s->subband_activity[j]; k++) - av_log(s->avctx, AV_LOG_DEBUG, " %i", s->transition_mode[j][k]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - for (j = base_channel; j < s->prim_channels; j++) { - av_log(s->avctx, AV_LOG_DEBUG, "Scale factor:"); - for (k = 0; k < s->subband_activity[j]; k++) { - if (k >= s->vq_start_subband[j] || s->bitalloc[j][k] > 0) - av_log(s->avctx, AV_LOG_DEBUG, " %i", s->scale_factor[j][k][0]); - if (k < s->vq_start_subband[j] && s->transition_mode[j][k]) - av_log(s->avctx, AV_LOG_DEBUG, " %i(t)", s->scale_factor[j][k][1]); - } - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - for (j = base_channel; j < s->prim_channels; j++) { - if (s->joint_intensity[j] > 0) { - int source_channel = s->joint_intensity[j] - 1; - av_log(s->avctx, AV_LOG_DEBUG, "Joint scale factor index:\n"); - for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++) - av_log(s->avctx, AV_LOG_DEBUG, " %i", s->joint_scale_factor[j][k]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - } - for (j = base_channel; j < s->prim_channels; j++) - for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++) - av_log(s->avctx, AV_LOG_DEBUG, "VQ index: %i\n", s->high_freq_vq[j][k]); - if (!base_channel && s->lfe) { - int lfe_samples = 2 * s->lfe * (4 + block_index); - int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]); - - av_log(s->avctx, AV_LOG_DEBUG, "LFE samples:\n"); - for (j = lfe_samples; j < lfe_end_sample; j++) - av_log(s->avctx, AV_LOG_DEBUG, " %f", s->lfe_data[j]); - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } -#endif - return 0; } static void qmf_32_subbands(DCAContext *s, int chans, - float samples_in[32][8], float *samples_out, + float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], float *samples_out, float scale) { const float *prCoeff; - int sb_act = s->subband_activity[chans]; + int sb_act = s->audio_header.subband_activity[chans]; scale *= sqrt(1 / 8.0); /* Select filter */ if (!s->multirate_inter) /* Non-perfect reconstruction */ - prCoeff = fir_32bands_nonperfect; + prCoeff = ff_dca_fir_32bands_nonperfect; else /* Perfect reconstruction */ - prCoeff = fir_32bands_perfect; + prCoeff = ff_dca_fir_32bands_perfect; s->dcadsp.qmf_32_subbands(samples_in, sb_act, &s->synth, &s->imdct, - s->subband_fir_hist[chans], - &s->hist_index[chans], - s->subband_fir_noidea[chans], prCoeff, + s->dca_chan[chans].subband_fir_hist, + &s->dca_chan[chans].hist_index, + s->dca_chan[chans].subband_fir_noidea, prCoeff, samples_out, s->raXin, scale); } -static void lfe_interpolation_fir(DCAContext *s, int decimation_select, - int num_deci_sample, float *samples_in, +static QMF64_table *qmf64_precompute(void) +{ + unsigned i, j; + QMF64_table *table = av_malloc(sizeof(*table)); + if (!table) + return NULL; + + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + table->dct4_coeff[i][j] = cos((2 * i + 1) * (2 * j + 1) * M_PI / 128); + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + table->dct2_coeff[i][j] = cos((2 * i + 1) * j * M_PI / 64); + + /* FIXME: Is the factor 0.125 = 1/8 right? */ + for (i = 0; i < 32; i++) + table->rcos[i] = 0.125 / cos((2 * i + 1) * M_PI / 256); + for (i = 0; i < 32; i++) + table->rsin[i] = -0.125 / sin((2 * i + 1) * M_PI / 256); + + return table; +} + +/* FIXME: Totally unoptimized. Based on the reference code and + * http://multimedia.cx/mirror/dca-transform.pdf, with guessed tweaks + * for doubling the size. */ +static void qmf_64_subbands(DCAContext *s, int chans, + float samples_in[DCA_SUBBANDS_X96K][SAMPLES_PER_SUBBAND], + float *samples_out, float scale) +{ + float raXin[64]; + float A[32], B[32]; + float *raX = s->dca_chan[chans].subband_fir_hist; + float *raZ = s->dca_chan[chans].subband_fir_noidea; + unsigned i, j, k, subindex; + + for (i = s->audio_header.subband_activity[chans]; i < DCA_SUBBANDS_X96K; i++) + raXin[i] = 0.0; + for (subindex = 0; subindex < SAMPLES_PER_SUBBAND; subindex++) { + for (i = 0; i < s->audio_header.subband_activity[chans]; i++) + raXin[i] = samples_in[i][subindex]; + + for (k = 0; k < 32; k++) { + A[k] = 0.0; + for (i = 0; i < 32; i++) + A[k] += (raXin[2 * i] + raXin[2 * i + 1]) * s->qmf64_table->dct4_coeff[k][i]; + } + for (k = 0; k < 32; k++) { + B[k] = raXin[0] * s->qmf64_table->dct2_coeff[k][0]; + for (i = 1; i < 32; i++) + B[k] += (raXin[2 * i] + raXin[2 * i - 1]) * s->qmf64_table->dct2_coeff[k][i]; + } + for (k = 0; k < 32; k++) { + raX[k] = s->qmf64_table->rcos[k] * (A[k] + B[k]); + raX[63 - k] = s->qmf64_table->rsin[k] * (A[k] - B[k]); + } + + for (i = 0; i < DCA_SUBBANDS_X96K; i++) { + float out = raZ[i]; + for (j = 0; j < 1024; j += 128) + out += ff_dca_fir_64bands[j + i] * (raX[j + i] - raX[j + 63 - i]); + *samples_out++ = out * scale; + } + + for (i = 0; i < DCA_SUBBANDS_X96K; i++) { + float hist = 0.0; + for (j = 0; j < 1024; j += 128) + hist += ff_dca_fir_64bands[64 + j + i] * (-raX[i + j] - raX[j + 63 - i]); + + raZ[i] = hist; + } + + /* FIXME: Make buffer circular, to avoid this move. */ + memmove(raX + 64, raX, (1024 - 64) * sizeof(*raX)); + } +} + +static void lfe_interpolation_fir(DCAContext *s, const float *samples_in, float *samples_out) { /* samples_in: An array holding decimated samples. @@ -958,15 +657,18 @@ static void lfe_interpolation_fir(DCAContext *s, int decimation_select, int deciindex; /* Select decimation filter */ - if (decimation_select == 1) { - idx = 1; - prCoeff = lfe_fir_128; + if (s->lfe == 1) { + idx = 1; + prCoeff = ff_dca_lfe_fir_128; } else { idx = 0; - prCoeff = lfe_fir_64; + if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) + prCoeff = ff_dca_lfe_xll_fir_64; + else + prCoeff = ff_dca_lfe_fir_64; } /* Interpolation */ - for (deciindex = 0; deciindex < num_deci_sample; deciindex++) { + for (deciindex = 0; deciindex < 2 * s->lfe; deciindex++) { s->dcadsp.lfe_fir[idx](samples_out, samples_in, prCoeff); samples_in++; samples_out += 2 * 32 * (1 + idx); @@ -1047,8 +749,8 @@ static void dca_downmix(float **samples, int srcfmt, int lfe_present, break; } if (lfe_present) { - int lf_buf = dca_lfe_index[srcfmt]; - int lf_idx = dca_channels [srcfmt]; + int lf_buf = ff_dca_lfe_index[srcfmt]; + int lf_idx = ff_dca_channels[srcfmt]; for (i = 0; i < 256; i++) { samples[0][i] += samples[lf_buf][i] * coef[lf_idx][0]; samples[1][i] += samples[lf_buf][i] * coef[lf_idx][1]; @@ -1056,7 +758,6 @@ static void dca_downmix(float **samples, int srcfmt, int lfe_present, } } - #ifndef decode_blockcodes /* Very compact version of the block code decoder that does not use table * look-up but is slightly slower */ @@ -1068,7 +769,7 @@ static int decode_blockcode(int code, int levels, int32_t *values) for (i = 0; i < 4; i++) { int div = FASTDIV(code, levels); values[i] = code - offset - div * levels; - code = div; + code = div; } return code; @@ -1088,12 +789,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) { int k, l; int subsubframe = s->current_subsubframe; - - const float *quant_step_table; - - /* FIXME */ - float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index]; - LOCAL_ALIGNED_16(int32_t, block, [8 * DCA_SUBBANDS]); + const uint32_t *quant_step_table; /* * Audio data @@ -1101,42 +797,41 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) /* Select quantization step size table */ if (s->bit_rate_index == 0x1f) - quant_step_table = lossless_quant_d; + quant_step_table = ff_dca_lossless_quant; else - quant_step_table = lossy_quant_d; + quant_step_table = ff_dca_lossy_quant; - for (k = base_channel; k < s->prim_channels; k++) { - float rscale[DCA_SUBBANDS]; + for (k = base_channel; k < s->audio_header.prim_channels; k++) { + int32_t (*subband_samples)[8] = s->dca_chan[k].subband_samples[block_index]; if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; - for (l = 0; l < s->vq_start_subband[k]; l++) { + for (l = 0; l < s->audio_header.vq_start_subband[k]; l++) { int m; /* Select the mid-tread linear quantizer */ - int abits = s->bitalloc[k][l]; + int abits = s->dca_chan[k].bitalloc[l]; - float quant_step_size = quant_step_table[abits]; - - /* - * Determine quantization index code book and its type - */ - - /* Select quantization index code book */ - int sel = s->quant_index_huffman[k][abits]; + uint32_t quant_step_size = quant_step_table[abits]; /* * Extract bits from the bit stream */ - if (!abits) { - rscale[l] = 0; - memset(block + 8 * l, 0, 8 * sizeof(block[0])); - } else { + if (!abits) + memset(subband_samples[l], 0, SAMPLES_PER_SUBBAND * + sizeof(subband_samples[l][0])); + else { + uint32_t rscale; /* Deal with transients */ - int sfi = s->transition_mode[k][l] && subsubframe >= s->transition_mode[k][l]; - rscale[l] = quant_step_size * s->scale_factor[k][l][sfi] * - s->scalefactor_adj[k][sel]; + int sfi = s->dca_chan[k].transition_mode[l] && + subsubframe >= s->dca_chan[k].transition_mode[l]; + /* Determine quantization index code book and its type. + Select quantization index code book */ + int sel = s->audio_header.quant_index_huffman[k][abits]; + + rscale = (s->dca_chan[k].scale_factor[l][sfi] * + s->audio_header.scalefactor_adj[k][sel] + 8) >> 4; if (abits >= 11 || !dca_smpl_bitalloc[abits].vlc[sel].table) { if (abits <= 7) { @@ -1148,8 +843,8 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) block_code1 = get_bits(&s->gb, size); block_code2 = get_bits(&s->gb, size); - err = decode_blockcodes(block_code1, block_code2, - levels, block + 8 * l); + err = decode_blockcodes(block_code1, block_code2, + levels, subband_samples[l]); if (err) { av_log(s->avctx, AV_LOG_ERROR, "ERROR: block code look-up failed\n"); @@ -1157,115 +852,153 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) } } else { /* no coding */ - for (m = 0; m < 8; m++) - block[8 * l + m] = get_sbits(&s->gb, abits - 3); + for (m = 0; m < SAMPLES_PER_SUBBAND; m++) + subband_samples[l][m] = get_sbits(&s->gb, abits - 3); } } else { /* Huffman coded */ - for (m = 0; m < 8; m++) - block[8 * l + m] = get_bitalloc(&s->gb, - &dca_smpl_bitalloc[abits], sel); + for (m = 0; m < SAMPLES_PER_SUBBAND; m++) + subband_samples[l][m] = get_bitalloc(&s->gb, + &dca_smpl_bitalloc[abits], sel); } - + s->dcadsp.dequantize(subband_samples[l], quant_step_size, rscale); } } - s->fmt_conv.int32_to_float_fmul_array8(&s->fmt_conv, subband_samples[k][0], - block, rscale, 8 * s->vq_start_subband[k]); - - for (l = 0; l < s->vq_start_subband[k]; l++) { + for (l = 0; l < s->audio_header.vq_start_subband[k]; l++) { int m; /* * Inverse ADPCM if in prediction mode */ - if (s->prediction_mode[k][l]) { + if (s->dca_chan[k].prediction_mode[l]) { int n; if (s->predictor_history) - subband_samples[k][l][0] += (adpcm_vb[s->prediction_vq[k][l]][0] * - s->subband_samples_hist[k][l][3] + - adpcm_vb[s->prediction_vq[k][l]][1] * - s->subband_samples_hist[k][l][2] + - adpcm_vb[s->prediction_vq[k][l]][2] * - s->subband_samples_hist[k][l][1] + - adpcm_vb[s->prediction_vq[k][l]][3] * - s->subband_samples_hist[k][l][0]) * - (1.0f / 8192); - for (m = 1; m < 8; m++) { - float sum = adpcm_vb[s->prediction_vq[k][l]][0] * - subband_samples[k][l][m - 1]; + subband_samples[l][0] += (ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][0] * + (int64_t)s->dca_chan[k].subband_samples_hist[l][3] + + ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][1] * + (int64_t)s->dca_chan[k].subband_samples_hist[l][2] + + ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][2] * + (int64_t)s->dca_chan[k].subband_samples_hist[l][1] + + ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][3] * + (int64_t)s->dca_chan[k].subband_samples_hist[l][0]) + + (1 << 12) >> 13; + for (m = 1; m < SAMPLES_PER_SUBBAND; m++) { + int64_t sum = ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][0] * + (int64_t)subband_samples[l][m - 1]; for (n = 2; n <= 4; n++) if (m >= n) - sum += adpcm_vb[s->prediction_vq[k][l]][n - 1] * - subband_samples[k][l][m - n]; + sum += ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][n - 1] * + (int64_t)subband_samples[l][m - n]; else if (s->predictor_history) - sum += adpcm_vb[s->prediction_vq[k][l]][n - 1] * - s->subband_samples_hist[k][l][m - n + 4]; - subband_samples[k][l][m] += sum * 1.0f / 8192; + sum += ff_dca_adpcm_vb[s->dca_chan[k].prediction_vq[l]][n - 1] * + (int64_t)s->dca_chan[k].subband_samples_hist[l][m - n + 4]; + subband_samples[l][m] += (int32_t)(sum + (1 << 12) >> 13); } } + } + /* Backup predictor history for adpcm */ + for (l = 0; l < DCA_SUBBANDS; l++) + AV_COPY128(s->dca_chan[k].subband_samples_hist[l], &subband_samples[l][4]); + /* * Decode VQ encoded high frequencies */ - if (s->subband_activity[k] > s->vq_start_subband[k]) { + if (s->audio_header.subband_activity[k] > s->audio_header.vq_start_subband[k]) { if (!s->debug_flag & 0x01) { av_log(s->avctx, AV_LOG_DEBUG, "Stream with high frequencies VQ coding\n"); s->debug_flag |= 0x01; } - s->dcadsp.decode_hf(subband_samples[k], s->high_freq_vq[k], - high_freq_vq, subsubframe * 8, - s->scale_factor[k], s->vq_start_subband[k], - s->subband_activity[k]); + + s->dcadsp.decode_hf(subband_samples, s->dca_chan[k].high_freq_vq, + ff_dca_high_freq_vq, + subsubframe * SAMPLES_PER_SUBBAND, + s->dca_chan[k].scale_factor, + s->audio_header.vq_start_subband[k], + s->audio_header.subband_activity[k]); } } /* Check for DSYNC after subsubframe */ if (s->aspf || subsubframe == s->subsubframes[s->current_subframe] - 1) { - if (0xFFFF == get_bits(&s->gb, 16)) { /* 0xFFFF */ -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "Got subframe DSYNC\n"); -#endif - } else { + if (get_bits(&s->gb, 16) != 0xFFFF) { av_log(s->avctx, AV_LOG_ERROR, "Didn't get subframe DSYNC\n"); return AVERROR_INVALIDDATA; } } - /* Backup predictor history for adpcm */ - for (k = base_channel; k < s->prim_channels; k++) - for (l = 0; l < s->vq_start_subband[k]; l++) - AV_COPY128(s->subband_samples_hist[k][l], &subband_samples[k][l][4]); - return 0; } -static int dca_filter_channels(DCAContext *s, int block_index) +static int dca_filter_channels(DCAContext *s, int block_index, int upsample) { - float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index]; int k; - /* 32 subbands QMF */ - for (k = 0; k < s->prim_channels; k++) { -/* static float pcm_to_double[8] = { 32768.0, 32768.0, 524288.0, 524288.0, - 0, 8388608.0, 8388608.0 };*/ - if (s->channel_order_tab[k] >= 0) - qmf_32_subbands(s, k, subband_samples[k], - s->samples_chanptr[s->channel_order_tab[k]], - M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */); + if (upsample) { + LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS_X96K], [SAMPLES_PER_SUBBAND]); + + if (!s->qmf64_table) { + s->qmf64_table = qmf64_precompute(); + if (!s->qmf64_table) + return AVERROR(ENOMEM); + } + + /* 64 subbands QMF */ + for (k = 0; k < s->audio_header.prim_channels; k++) { + int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] = + s->dca_chan[k].subband_samples[block_index]; + + s->fmt_conv.int32_to_float(samples[0], subband_samples[0], + DCA_SUBBANDS_X96K * SAMPLES_PER_SUBBAND); + + if (s->channel_order_tab[k] >= 0) + qmf_64_subbands(s, k, samples, + s->samples_chanptr[s->channel_order_tab[k]], + /* Upsampling needs a factor 2 here. */ + M_SQRT2 / 32768.0); + } + } else { + /* 32 subbands QMF */ + LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS], [SAMPLES_PER_SUBBAND]); + + for (k = 0; k < s->audio_header.prim_channels; k++) { + int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] = + s->dca_chan[k].subband_samples[block_index]; + + s->fmt_conv.int32_to_float(samples[0], subband_samples[0], + DCA_SUBBANDS * SAMPLES_PER_SUBBAND); + + if (s->channel_order_tab[k] >= 0) + qmf_32_subbands(s, k, samples, + s->samples_chanptr[s->channel_order_tab[k]], + M_SQRT1_2 / 32768.0); + } } /* Generate LFE samples for this subsubframe FIXME!!! */ if (s->lfe) { - lfe_interpolation_fir(s, s->lfe, 2 * s->lfe, + float *samples = s->samples_chanptr[ff_dca_lfe_index[s->amode]]; + lfe_interpolation_fir(s, s->lfe_data + 2 * s->lfe * (block_index + 4), - s->samples_chanptr[dca_lfe_index[s->amode]]); - /* Outputs 20bits pcm samples */ + samples); + if (upsample) { + unsigned i; + /* Should apply the filter in Table 6-11 when upsampling. For + * now, just duplicate. */ + for (i = 511; i > 0; i--) { + samples[2 * i] = + samples[2 * i + 1] = samples[i]; + } + samples[1] = samples[0]; + } } + /* FIXME: This downmixing is probably broken with upsample. + * Probably totally broken also with XLL in general. */ /* Downmixing to Stereo */ - if (s->prim_channels + !!s->lfe > 2 && + if (s->audio_header.prim_channels + !!s->lfe > 2 && s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef, s->channel_order_tab); @@ -1274,7 +1007,6 @@ static int dca_filter_channels(DCAContext *s, int block_index) return 0; } - static int dca_subframe_footer(DCAContext *s, int base_channel) { int in, out, aux_data_count, aux_data_end, reserved; @@ -1342,8 +1074,8 @@ static int dca_subframe_footer(DCAContext *s, int base_channel) am); return AVERROR_INVALIDDATA; } - for (out = 0; out < dca_channels[s->core_downmix_amode]; out++) { - for (in = 0; in < s->prim_channels + !!s->lfe; in++) { + for (out = 0; out < ff_dca_channels[s->core_downmix_amode]; out++) { + for (in = 0; in < s->audio_header.prim_channels + !!s->lfe; in++) { uint16_t tmp = get_bits(&s->gb, 9); if ((tmp & 0xFF) > 241) { av_log(s->avctx, AV_LOG_ERROR, @@ -1359,12 +1091,12 @@ static int dca_subframe_footer(DCAContext *s, int base_channel) align_get_bits(&s->gb); // byte align skip_bits(&s->gb, 16); // nAUXCRC16 - // additional data (reserved, cf. ETSI TS 102 114 V1.4.1) - if ((reserved = (aux_data_end - get_bits_count(&s->gb))) < 0) { - av_log(s->avctx, AV_LOG_ERROR, - "Overread auxiliary data by %d bits\n", -reserved); - return AVERROR_INVALIDDATA; - } else if (reserved) { + /* + * additional data (reserved, cf. ETSI TS 102 114 V1.4.1) + * + * Note: don't check for overreads, aux_data_count can't be trusted. + */ + if ((reserved = (aux_data_end - get_bits_count(&s->gb))) > 0) { avpriv_request_sample(s->avctx, "Core auxiliary data reserved content"); skip_bits_long(&s->gb, reserved); @@ -1389,25 +1121,19 @@ static int dca_decode_block(DCAContext *s, int base_channel, int block_index) int ret; /* Sanity check */ - if (s->current_subframe >= s->subframes) { + if (s->current_subframe >= s->audio_header.subframes) { av_log(s->avctx, AV_LOG_DEBUG, "check failed: %i>%i", - s->current_subframe, s->subframes); + s->current_subframe, s->audio_header.subframes); return AVERROR_INVALIDDATA; } if (!s->current_subsubframe) { -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subframe_header\n"); -#endif /* Read subframe header */ if ((ret = dca_subframe_header(s, base_channel, block_index))) return ret; } /* Read subsubframe */ -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subsubframe\n"); -#endif if ((ret = dca_subsubframe(s, base_channel, block_index))) return ret; @@ -1417,10 +1143,7 @@ static int dca_decode_block(DCAContext *s, int base_channel, int block_index) s->current_subsubframe = 0; s->current_subframe++; } - if (s->current_subframe >= s->subframes) { -#ifdef TRACE - av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subframe_footer\n"); -#endif + if (s->current_subframe >= s->audio_header.subframes) { /* Read subframe footer */ if ((ret = dca_subframe_footer(s, base_channel))) return ret; @@ -1429,339 +1152,23 @@ static int dca_decode_block(DCAContext *s, int base_channel, int block_index) return 0; } -/** - * Return the number of channels in an ExSS speaker mask (HD) - */ -static int dca_exss_mask2count(int mask) -{ - /* count bits that mean speaker pairs twice */ - return av_popcount(mask) + - av_popcount(mask & (DCA_EXSS_CENTER_LEFT_RIGHT | - DCA_EXSS_FRONT_LEFT_RIGHT | - DCA_EXSS_FRONT_HIGH_LEFT_RIGHT | - DCA_EXSS_WIDE_LEFT_RIGHT | - DCA_EXSS_SIDE_LEFT_RIGHT | - DCA_EXSS_SIDE_HIGH_LEFT_RIGHT | - DCA_EXSS_SIDE_REAR_LEFT_RIGHT | - DCA_EXSS_REAR_LEFT_RIGHT | - DCA_EXSS_REAR_HIGH_LEFT_RIGHT)); -} - -/** - * Skip mixing coefficients of a single mix out configuration (HD) - */ -static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch) -{ - int i; - - for (i = 0; i < channels; i++) { - int mix_map_mask = get_bits(gb, out_ch); - int num_coeffs = av_popcount(mix_map_mask); - skip_bits_long(gb, num_coeffs * 6); - } -} - -/** - * Parse extension substream asset header (HD) - */ -static int dca_exss_parse_asset_header(DCAContext *s) -{ - int header_pos = get_bits_count(&s->gb); - int header_size; - int channels; - int embedded_stereo = 0; - int embedded_6ch = 0; - int drc_code_present; - int extensions_mask; - int i, j; - - if (get_bits_left(&s->gb) < 16) - return -1; - - /* We will parse just enough to get to the extensions bitmask with which - * we can set the profile value. */ - - header_size = get_bits(&s->gb, 9) + 1; - skip_bits(&s->gb, 3); // asset index - - if (s->static_fields) { - if (get_bits1(&s->gb)) - skip_bits(&s->gb, 4); // asset type descriptor - if (get_bits1(&s->gb)) - skip_bits_long(&s->gb, 24); // language descriptor - - if (get_bits1(&s->gb)) { - /* How can one fit 1024 bytes of text here if the maximum value - * for the asset header size field above was 512 bytes? */ - int text_length = get_bits(&s->gb, 10) + 1; - if (get_bits_left(&s->gb) < text_length * 8) - return -1; - skip_bits_long(&s->gb, text_length * 8); // info text - } - - skip_bits(&s->gb, 5); // bit resolution - 1 - skip_bits(&s->gb, 4); // max sample rate code - channels = get_bits(&s->gb, 8) + 1; - - if (get_bits1(&s->gb)) { // 1-to-1 channels to speakers - int spkr_remap_sets; - int spkr_mask_size = 16; - int num_spkrs[7]; - - if (channels > 2) - embedded_stereo = get_bits1(&s->gb); - if (channels > 6) - embedded_6ch = get_bits1(&s->gb); - - if (get_bits1(&s->gb)) { - spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2; - skip_bits(&s->gb, spkr_mask_size); // spkr activity mask - } - - spkr_remap_sets = get_bits(&s->gb, 3); - - for (i = 0; i < spkr_remap_sets; i++) { - /* std layout mask for each remap set */ - num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size)); - } - - for (i = 0; i < spkr_remap_sets; i++) { - int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1; - if (get_bits_left(&s->gb) < 0) - return -1; - - for (j = 0; j < num_spkrs[i]; j++) { - int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps); - int num_dec_ch = av_popcount(remap_dec_ch_mask); - skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes - } - } - - } else { - skip_bits(&s->gb, 3); // representation type - } - } - - drc_code_present = get_bits1(&s->gb); - if (drc_code_present) - get_bits(&s->gb, 8); // drc code - - if (get_bits1(&s->gb)) - skip_bits(&s->gb, 5); // dialog normalization code - - if (drc_code_present && embedded_stereo) - get_bits(&s->gb, 8); // drc stereo code - - if (s->mix_metadata && get_bits1(&s->gb)) { - skip_bits(&s->gb, 1); // external mix - skip_bits(&s->gb, 6); // post mix gain code - - if (get_bits(&s->gb, 2) != 3) // mixer drc code - skip_bits(&s->gb, 3); // drc limit - else - skip_bits(&s->gb, 8); // custom drc code - - if (get_bits1(&s->gb)) // channel specific scaling - for (i = 0; i < s->num_mix_configs; i++) - skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes - else - skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes - - for (i = 0; i < s->num_mix_configs; i++) { - if (get_bits_left(&s->gb) < 0) - return -1; - dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]); - if (embedded_6ch) - dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]); - if (embedded_stereo) - dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]); - } - } - - switch (get_bits(&s->gb, 2)) { - case 0: extensions_mask = get_bits(&s->gb, 12); break; - case 1: extensions_mask = DCA_EXT_EXSS_XLL; break; - case 2: extensions_mask = DCA_EXT_EXSS_LBR; break; - case 3: extensions_mask = 0; /* aux coding */ break; - } - - /* not parsed further, we were only interested in the extensions mask */ - - if (get_bits_left(&s->gb) < 0) - return -1; - - if (get_bits_count(&s->gb) - header_pos > header_size * 8) { - av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n"); - return -1; - } - skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb)); - - if (extensions_mask & DCA_EXT_EXSS_XLL) - s->profile = FF_PROFILE_DTS_HD_MA; - else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 | - DCA_EXT_EXSS_XXCH)) - s->profile = FF_PROFILE_DTS_HD_HRA; - - if (!(extensions_mask & DCA_EXT_CORE)) - av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n"); - if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask) - av_log(s->avctx, AV_LOG_WARNING, - "DTS extensions detection mismatch (%d, %d)\n", - extensions_mask & DCA_CORE_EXTS, s->core_ext_mask); - - return 0; -} - -/** - * Parse extension substream header (HD) - */ -static void dca_exss_parse_header(DCAContext *s) -{ - int ss_index; - int blownup; - int num_audiop = 1; - int num_assets = 1; - int active_ss_mask[8]; - int i, j; - - if (get_bits_left(&s->gb) < 52) - return; - - skip_bits(&s->gb, 8); // user data - ss_index = get_bits(&s->gb, 2); - - blownup = get_bits1(&s->gb); - skip_bits(&s->gb, 8 + 4 * blownup); // header_size - skip_bits(&s->gb, 16 + 4 * blownup); // hd_size - - s->static_fields = get_bits1(&s->gb); - if (s->static_fields) { - skip_bits(&s->gb, 2); // reference clock code - skip_bits(&s->gb, 3); // frame duration code - - if (get_bits1(&s->gb)) - skip_bits_long(&s->gb, 36); // timestamp - - /* a single stream can contain multiple audio assets that can be - * combined to form multiple audio presentations */ - - num_audiop = get_bits(&s->gb, 3) + 1; - if (num_audiop > 1) { - avpriv_request_sample(s->avctx, - "Multiple DTS-HD audio presentations"); - /* ignore such streams for now */ - return; - } - - num_assets = get_bits(&s->gb, 3) + 1; - if (num_assets > 1) { - avpriv_request_sample(s->avctx, "Multiple DTS-HD audio assets"); - /* ignore such streams for now */ - return; - } - - for (i = 0; i < num_audiop; i++) - active_ss_mask[i] = get_bits(&s->gb, ss_index + 1); - - for (i = 0; i < num_audiop; i++) - for (j = 0; j <= ss_index; j++) - if (active_ss_mask[i] & (1 << j)) - skip_bits(&s->gb, 8); // active asset mask - - s->mix_metadata = get_bits1(&s->gb); - if (s->mix_metadata) { - int mix_out_mask_size; - - skip_bits(&s->gb, 2); // adjustment level - mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2; - s->num_mix_configs = get_bits(&s->gb, 2) + 1; - - for (i = 0; i < s->num_mix_configs; i++) { - int mix_out_mask = get_bits(&s->gb, mix_out_mask_size); - s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask); - } - } - } - - for (i = 0; i < num_assets; i++) - skip_bits_long(&s->gb, 16 + 4 * blownup); // asset size - - for (i = 0; i < num_assets; i++) { - if (dca_exss_parse_asset_header(s)) - return; - } - - /* not parsed further, we were only interested in the extensions mask - * from the asset header */ -} - static float dca_dmix_code(unsigned code) { int sign = (code >> 8) - 1; code &= 0xff; - return ((dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1U << 15)); + return ((ff_dca_dmixtable[code] ^ sign) - sign) * (1.0 / (1U << 15)); } -/** - * Main frame decoding function - * FIXME add arguments - */ -static int dca_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) +static int scan_for_extensions(AVCodecContext *avctx) { - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - - int lfe_samples; - int num_core_channels = 0; - int i, ret; - float **samples_flt; DCAContext *s = avctx->priv_data; - int channels, full_channels; - int core_ss_end; - - - s->xch_present = 0; - - s->dca_buffer_size = ff_dca_convert_bitstream(buf, buf_size, s->dca_buffer, - DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE); - if (s->dca_buffer_size == AVERROR_INVALIDDATA) { - av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n"); - return AVERROR_INVALIDDATA; - } - - if ((ret = dca_parse_frame_header(s)) < 0) { - //seems like the frame is corrupt, try with the next one - return ret; - } - //set AVCodec values with parsed data - avctx->sample_rate = s->sample_rate; - avctx->bit_rate = s->bit_rate; - - s->profile = FF_PROFILE_DTS; - - for (i = 0; i < (s->sample_blocks / 8); i++) { - if ((ret = dca_decode_block(s, 0, i))) { - av_log(avctx, AV_LOG_ERROR, "error decoding block\n"); - return ret; - } - } - - /* record number of core channels incase less than max channels are requested */ - num_core_channels = s->prim_channels; - - if (s->ext_coding) - s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr]; - else - s->core_ext_mask = 0; + int core_ss_end, ret = 0; core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8; /* only scan for extensions if ext_descr was unknown or indicated a * supported XCh extension */ if (s->core_ext_mask < 0 || s->core_ext_mask & DCA_EXT_XCH) { - /* if ext_descr was unknown, clear s->core_ext_mask so that the * extensions scan can fill it up */ s->core_ext_mask = FFMAX(s->core_ext_mask, 0); @@ -1771,12 +1178,13 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, while (core_ss_end - get_bits_count(&s->gb) >= 32) { uint32_t bits = get_bits_long(&s->gb, 32); + int i; switch (bits) { - case 0x5a5a5a5a: { + case DCA_SYNCWORD_XCH: { int ext_amode, xch_fsize; - s->xch_base_channel = s->prim_channels; + s->xch_base_channel = s->audio_header.prim_channels; /* validate sync word using XCHFSIZE field */ xch_fsize = show_bits(&s->gb, 10); @@ -1792,8 +1200,9 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, /* extension amode(number of channels in extension) should be 1 */ /* AFAIK XCh is not used for more channels */ if ((ext_amode = get_bits(&s->gb, 4)) != 1) { - av_log(avctx, AV_LOG_ERROR, "XCh extension amode %d not" - " supported!\n", ext_amode); + av_log(avctx, AV_LOG_ERROR, + "XCh extension amode %d not supported!\n", + ext_amode); continue; } @@ -1809,7 +1218,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, s->xch_present = 1; break; } - case 0x47004a03: + case DCA_SYNCWORD_XXCH: /* XXCh: extended channels */ /* usually found either in core or HD part in DTS-HD HRA streams, * but not in DTS-ES which contains XCh extensions instead */ @@ -1846,17 +1255,21 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, /* check for ExSS (HD part) */ if (s->dca_buffer_size - s->frame_size > 32 && - get_bits_long(&s->gb, 32) == DCA_HD_MARKER) - dca_exss_parse_header(s); + get_bits_long(&s->gb, 32) == DCA_SYNCWORD_SUBSTREAM) + ff_dca_exss_parse_header(s); - avctx->profile = s->profile; + return ret; +} - full_channels = channels = s->prim_channels + !!s->lfe; +static int set_channel_layout(AVCodecContext *avctx, int channels, int num_core_channels) +{ + DCAContext *s = avctx->priv_data; + int i; if (s->amode < 16) { avctx->channel_layout = dca_core_channel_layout[s->amode]; - if (s->prim_channels + !!s->lfe > 2 && + if (s->audio_header.prim_channels + !!s->lfe > 2 && avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { /* * Neither the core's auxiliary data nor our default tables contain @@ -1866,40 +1279,35 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, s->xch_disable = 1; } -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (s->xch_present && !s->xch_disable && - (!avctx->request_channels || - avctx->request_channels > num_core_channels + !!s->lfe)) { -FF_ENABLE_DEPRECATION_WARNINGS -#else if (s->xch_present && !s->xch_disable) { -#endif avctx->channel_layout |= AV_CH_BACK_CENTER; if (s->lfe) { avctx->channel_layout |= AV_CH_LOW_FREQUENCY; - s->channel_order_tab = dca_channel_reorder_lfe_xch[s->amode]; + s->channel_order_tab = ff_dca_channel_reorder_lfe_xch[s->amode]; } else { - s->channel_order_tab = dca_channel_reorder_nolfe_xch[s->amode]; + s->channel_order_tab = ff_dca_channel_reorder_nolfe_xch[s->amode]; } } else { - channels = num_core_channels + !!s->lfe; + channels = num_core_channels + !!s->lfe; s->xch_present = 0; /* disable further xch processing */ if (s->lfe) { avctx->channel_layout |= AV_CH_LOW_FREQUENCY; - s->channel_order_tab = dca_channel_reorder_lfe[s->amode]; + s->channel_order_tab = ff_dca_channel_reorder_lfe[s->amode]; } else - s->channel_order_tab = dca_channel_reorder_nolfe[s->amode]; + s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode]; } + if (channels < ff_dca_channels[s->amode] + !!s->lfe) + return AVERROR_INVALIDDATA; + if (channels > !!s->lfe && s->channel_order_tab[channels - 1 - !!s->lfe] < 0) return AVERROR_INVALIDDATA; if (num_core_channels + !!s->lfe > 2 && avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { - channels = 2; - s->output = s->prim_channels == 2 ? s->amode : DCA_STEREO; + channels = 2; + s->output = s->audio_header.prim_channels == 2 ? s->amode : DCA_STEREO; avctx->channel_layout = AV_CH_LAYOUT_STEREO; /* Stereo downmix coefficients @@ -1917,44 +1325,148 @@ FF_ENABLE_DEPRECATION_WARNINGS s->output = s->core_downmix_amode; } else { int am = s->amode & DCA_CHANNEL_MASK; - if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) { + if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) { av_log(s->avctx, AV_LOG_ERROR, "Invalid channel mode %d\n", am); return AVERROR_INVALIDDATA; } if (num_core_channels + !!s->lfe > - FF_ARRAY_ELEMS(dca_default_coeffs[0])) { + FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) { avpriv_request_sample(s->avctx, "Downmixing %d channels", - s->prim_channels + !!s->lfe); + s->audio_header.prim_channels + !!s->lfe); return AVERROR_PATCHWELCOME; } for (i = 0; i < num_core_channels + !!s->lfe; i++) { - s->downmix_coef[i][0] = dca_default_coeffs[am][i][0]; - s->downmix_coef[i][1] = dca_default_coeffs[am][i][1]; + s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0]; + s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1]; } } - av_dlog(s->avctx, "Stereo downmix coeffs:\n"); + ff_dlog(s->avctx, "Stereo downmix coeffs:\n"); for (i = 0; i < num_core_channels + !!s->lfe; i++) { - av_dlog(s->avctx, "L, input channel %d = %f\n", i, + ff_dlog(s->avctx, "L, input channel %d = %f\n", i, s->downmix_coef[i][0]); - av_dlog(s->avctx, "R, input channel %d = %f\n", i, + ff_dlog(s->avctx, "R, input channel %d = %f\n", i, s->downmix_coef[i][1]); } - av_dlog(s->avctx, "\n"); + ff_dlog(s->avctx, "\n"); } } else { - av_log(avctx, AV_LOG_ERROR, "Non standard configuration %d !\n", s->amode); + av_log(avctx, AV_LOG_ERROR, "Nonstandard configuration %d !\n", s->amode); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/** + * Main frame decoding function + * FIXME add arguments + */ +static int dca_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + + int lfe_samples; + int num_core_channels = 0; + int i, ret; + float **samples_flt; + DCAContext *s = avctx->priv_data; + int channels, full_channels; + int upsample = 0; + + s->exss_ext_mask = 0; + s->xch_present = 0; + + s->dca_buffer_size = ff_dca_convert_bitstream(buf, buf_size, s->dca_buffer, + DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE); + if (s->dca_buffer_size == AVERROR_INVALIDDATA) { + av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n"); return AVERROR_INVALIDDATA; } + + if ((ret = dca_parse_frame_header(s)) < 0) { + // seems like the frame is corrupt, try with the next one + return ret; + } + // set AVCodec values with parsed data + avctx->sample_rate = s->sample_rate; + avctx->bit_rate = s->bit_rate; + + s->profile = FF_PROFILE_DTS; + + for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) { + if ((ret = dca_decode_block(s, 0, i))) { + av_log(avctx, AV_LOG_ERROR, "error decoding block\n"); + return ret; + } + } + + /* record number of core channels incase less than max channels are requested */ + num_core_channels = s->audio_header.prim_channels; + + if (s->ext_coding) + s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr]; + else + s->core_ext_mask = 0; + + ret = scan_for_extensions(avctx); + + avctx->profile = s->profile; + + full_channels = channels = s->audio_header.prim_channels + !!s->lfe; + + ret = set_channel_layout(avctx, channels, num_core_channels); + if (ret < 0) + return ret; avctx->channels = channels; /* get output buffer */ - frame->nb_samples = 256 * (s->sample_blocks / 8); + frame->nb_samples = 256 * (s->sample_blocks / SAMPLES_PER_SUBBAND); + if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) { + int xll_nb_samples = s->xll_segments * s->xll_smpl_in_seg; + /* Check for invalid/unsupported conditions first */ + if (s->xll_residual_channels > channels) { + av_log(s->avctx, AV_LOG_WARNING, + "DCA: too many residual channels (%d, core channels %d). Disabling XLL\n", + s->xll_residual_channels, channels); + s->exss_ext_mask &= ~DCA_EXT_EXSS_XLL; + } else if (xll_nb_samples != frame->nb_samples && + 2 * frame->nb_samples != xll_nb_samples) { + av_log(s->avctx, AV_LOG_WARNING, + "DCA: unsupported upsampling (%d XLL samples, %d core samples). Disabling XLL\n", + xll_nb_samples, frame->nb_samples); + s->exss_ext_mask &= ~DCA_EXT_EXSS_XLL; + } else { + if (2 * frame->nb_samples == xll_nb_samples) { + av_log(s->avctx, AV_LOG_INFO, + "XLL: upsampling core channels by a factor of 2\n"); + upsample = 1; + + frame->nb_samples = xll_nb_samples; + // FIXME: Is it good enough to copy from the first channel set? + avctx->sample_rate = s->xll_chsets[0].sampling_frequency; + } + /* If downmixing to stereo, don't decode additional channels. + * FIXME: Using the xch_disable flag for this doesn't seem right. */ + if (!s->xch_disable) + avctx->channels += s->xll_channels - s->xll_residual_channels; + } + } + + /* FIXME: This is an ugly hack, to just revert to the default + * layout if we have additional channels. Need to convert the XLL + * channel masks to libav channel_layout mask. */ + if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) + avctx->channel_layout = 0; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - samples_flt = (float **)frame->extended_data; + samples_flt = (float **) frame->extended_data; /* allocate buffer for extra channels if downmixing */ if (avctx->channels < full_channels) { @@ -1969,7 +1481,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!s->extra_channels_buffer) return AVERROR(ENOMEM); - ret = av_samples_fill_arrays((uint8_t **)s->extra_channels, NULL, + ret = av_samples_fill_arrays((uint8_t **) s->extra_channels, NULL, s->extra_channels_buffer, full_channels - channels, frame->nb_samples, avctx->sample_fmt, 0); @@ -1978,15 +1490,15 @@ FF_ENABLE_DEPRECATION_WARNINGS } /* filter to get final output */ - for (i = 0; i < (s->sample_blocks / 8); i++) { + for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) { int ch; - + unsigned block = upsample ? 512 : 256; for (ch = 0; ch < channels; ch++) - s->samples_chanptr[ch] = samples_flt[ch] + i * 256; + s->samples_chanptr[ch] = samples_flt[ch] + i * block; for (; ch < full_channels; ch++) - s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * 256; + s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * block; - dca_filter_channels(s, i); + dca_filter_channels(s, i, upsample); /* If this was marked as a DTS-ES stream we need to subtract back- */ /* channel from SL & SR to remove matrixed back-channel signal */ @@ -2000,10 +1512,15 @@ FF_ENABLE_DEPRECATION_WARNINGS } /* update lfe history */ - lfe_samples = 2 * s->lfe * (s->sample_blocks / 8); + lfe_samples = 2 * s->lfe * (s->sample_blocks / SAMPLES_PER_SUBBAND); for (i = 0; i < 2 * s->lfe * 4; i++) s->lfe_data[i] = s->lfe_data[i + lfe_samples]; + if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) { + ret = ff_dca_xll_decode_audio(s, frame); + if (ret < 0) + return ret; + } /* AVMatrixEncoding * * DCA_STEREO_TOTAL (Lt/Rt) is equivalent to Dolby Surround */ @@ -2018,8 +1535,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return buf_size; } - - /** * DCA initialization * @@ -2033,7 +1548,7 @@ static av_cold int dca_decode_init(AVCodecContext *avctx) s->avctx = avctx; dca_init_vlcs(); - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); ff_mdct_init(&s->imdct, 6, 1, 1.0); ff_synth_filter_init(&s->synth); ff_dcadsp_init(&s->dcadsp); @@ -2042,12 +1557,6 @@ static av_cold int dca_decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; /* allow downmixing to stereo */ -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->request_channels == 2) - avctx->request_channel_layout = AV_CH_LAYOUT_STEREO; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (avctx->channels > 2 && avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) avctx->channels = 2; @@ -2060,20 +1569,14 @@ static av_cold int dca_decode_end(AVCodecContext *avctx) DCAContext *s = avctx->priv_data; ff_mdct_end(&s->imdct); av_freep(&s->extra_channels_buffer); + av_freep(&s->xll_sample_buf); + av_freep(&s->qmf64_table); return 0; } -static const AVProfile profiles[] = { - { FF_PROFILE_DTS, "DTS" }, - { FF_PROFILE_DTS_ES, "DTS-ES" }, - { FF_PROFILE_DTS_96_24, "DTS 96/24" }, - { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, - { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, - { FF_PROFILE_UNKNOWN }, -}; - static const AVOption options[] = { - { "disable_xch", "disable decoding of the XCh extension", offsetof(DCAContext, xch_disable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_AUDIO_PARAM }, + { "disable_xch", "disable decoding of the XCh extension", offsetof(DCAContext, xch_disable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM }, + { "disable_xll", "disable decoding of the XLL extension", offsetof(DCAContext, xll_disable), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM }, { NULL }, }; @@ -2093,9 +1596,9 @@ AVCodec ff_dca_decoder = { .init = dca_decode_init, .decode = dca_decode_frame, .close = dca_decode_end, - .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .profiles = NULL_IF_CONFIG_SMALL(profiles), + .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), .priv_class = &dca_decoder_class, }; diff --git a/libavcodec/dcadsp.c b/libavcodec/dcadsp.c index 18732dc..beec200 100644 --- a/libavcodec/dcadsp.c +++ b/libavcodec/dcadsp.c @@ -20,31 +20,30 @@ */ #include "config.h" + #include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" + #include "dcadsp.h" +#include "dcamath.h" -static void decode_hf_c(float dst[DCA_SUBBANDS][8], +static void decode_hf_c(int32_t dst[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], const int32_t vq_num[DCA_SUBBANDS], const int8_t hf_vq[1024][32], intptr_t vq_offset, int32_t scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end) { - int i, l; + int i, j; - for (l = start; l < end; l++) { - /* 1 vector -> 32 samples but we only need the 8 samples - * for this subsubframe. */ - const int8_t *ptr = &hf_vq[vq_num[l]][vq_offset]; - float fscale = scale[l][0] * (1 / 16.0); + for (j = start; j < end; j++) { + const int8_t *ptr = &hf_vq[vq_num[j]][vq_offset]; for (i = 0; i < 8; i++) - dst[l][i] = ptr[i] * fscale; + dst[j][i] = ptr[i] * scale[j][0] + 8 >> 4; } } -static inline void -dca_lfe_fir(float *out, const float *in, const float *coefs, - int decifactor) +static inline void dca_lfe_fir(float *out, const float *in, const float *coefs, + int decifactor) { float *out2 = out + 2 * decifactor - 1; int num_coeffs = 256 / decifactor; @@ -55,7 +54,7 @@ dca_lfe_fir(float *out, const float *in, const float *coefs, float v0 = 0.0; float v1 = 0.0; for (j = 0; j < num_coeffs; j++, coefs++) { - v0 += in[-j] * *coefs; + v0 += in[-j] * *coefs; v1 += in[j + 1 - num_coeffs] * *coefs; } *out++ = v0; @@ -63,7 +62,7 @@ dca_lfe_fir(float *out, const float *in, const float *coefs, } } -static void dca_qmf_32_subbands(float samples_in[32][8], int sb_act, +static void dca_qmf_32_subbands(float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], int sb_act, SynthFilterContext *synth, FFTContext *imdct, float synth_buf_ptr[512], int *synth_buf_offset, float synth_buf2[32], @@ -86,11 +85,28 @@ static void dca_qmf_32_subbands(float samples_in[32][8], int sb_act, } synth->synth_filter_float(imdct, synth_buf_ptr, synth_buf_offset, - synth_buf2, window, samples_out, raXin, scale); + synth_buf2, window, samples_out, raXin, + scale); samples_out += 32; } } +static void dequantize_c(int32_t *samples, uint32_t step_size, uint32_t scale) +{ + int64_t step = (int64_t)step_size * scale; + int shift, i; + int32_t step_scale; + + if (step > (1 << 23)) + shift = av_log2(step >> 23) + 1; + else + shift = 0; + step_scale = (int32_t)(step >> shift); + + for (i = 0; i < SAMPLES_PER_SUBBAND; i++) + samples[i] = dca_clip23(dca_norm((int64_t)samples[i] * step_scale, 22 - shift)); +} + static void dca_lfe_fir0_c(float *out, const float *in, const float *coefs) { dca_lfe_fir(out, in, coefs, 32); @@ -103,10 +119,16 @@ static void dca_lfe_fir1_c(float *out, const float *in, const float *coefs) av_cold void ff_dcadsp_init(DCADSPContext *s) { - s->lfe_fir[0] = dca_lfe_fir0_c; - s->lfe_fir[1] = dca_lfe_fir1_c; + s->lfe_fir[0] = dca_lfe_fir0_c; + s->lfe_fir[1] = dca_lfe_fir1_c; s->qmf_32_subbands = dca_qmf_32_subbands; - s->decode_hf = decode_hf_c; - if (ARCH_ARM) ff_dcadsp_init_arm(s); - if (ARCH_X86) ff_dcadsp_init_x86(s); + s->decode_hf = decode_hf_c; + s->dequantize = dequantize_c; + + if (ARCH_AARCH64) + ff_dcadsp_init_aarch64(s); + if (ARCH_ARM) + ff_dcadsp_init_arm(s); + if (ARCH_X86) + ff_dcadsp_init_x86(s); } diff --git a/libavcodec/dcadsp.h b/libavcodec/dcadsp.h index 0fa75a5..9ea89ea 100644 --- a/libavcodec/dcadsp.h +++ b/libavcodec/dcadsp.h @@ -22,24 +22,29 @@ #include "avfft.h" #include "synth_filter.h" -#define DCA_SUBBANDS 32 +#define DCA_SUBBANDS_X96K 64 +#define DCA_SUBBANDS 32 +#define SAMPLES_PER_SUBBAND 8 // number of samples per subband per subsubframe + typedef struct DCADSPContext { void (*lfe_fir[2])(float *out, const float *in, const float *coefs); - void (*qmf_32_subbands)(float samples_in[32][8], int sb_act, + void (*qmf_32_subbands)(float samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], int sb_act, SynthFilterContext *synth, FFTContext *imdct, float synth_buf_ptr[512], int *synth_buf_offset, float synth_buf2[32], const float window[512], float *samples_out, float raXin[32], float scale); - void (*decode_hf)(float dst[DCA_SUBBANDS][8], + void (*decode_hf)(int32_t dst[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], const int32_t vq_num[DCA_SUBBANDS], const int8_t hf_vq[1024][32], intptr_t vq_offset, int32_t scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end); + void (*dequantize)(int32_t *samples, uint32_t step_size, uint32_t scale); } DCADSPContext; void ff_dcadsp_init(DCADSPContext *s); +void ff_dcadsp_init_aarch64(DCADSPContext *s); void ff_dcadsp_init_arm(DCADSPContext *s); void ff_dcadsp_init_x86(DCADSPContext *s); diff --git a/libavcodec/dcahuff.h b/libavcodec/dcahuff.h index 254fc76..79be493 100644 --- a/libavcodec/dcahuff.h +++ b/libavcodec/dcahuff.h @@ -29,632 +29,595 @@ #define TMODE_COUNT 4 static const uint8_t tmode_vlc_bits[TMODE_COUNT] = { 3, 3, 3, 2 }; static const uint16_t tmode_codes[TMODE_COUNT][4] = { - { 0x0000, 0x0002, 0x0006, 0x0007 }, - { 0x0002, 0x0006, 0x0007, 0x0000 }, - { 0x0006, 0x0007, 0x0000, 0x0002 }, - { 0x0000, 0x0001, 0x0002, 0x0003 } + { 0x0000, 0x0002, 0x0006, 0x0007 }, + { 0x0002, 0x0006, 0x0007, 0x0000 }, + { 0x0006, 0x0007, 0x0000, 0x0002 }, + { 0x0000, 0x0001, 0x0002, 0x0003 } }; + static const uint8_t tmode_bits[TMODE_COUNT][4] = { - { 1, 2, 3, 3 }, - { 2, 3, 3, 1 }, - { 3, 3, 1, 2 }, - { 2, 2, 2, 2 } + { 1, 2, 3, 3 }, + { 2, 3, 3, 1 }, + { 3, 3, 1, 2 }, + { 2, 2, 2, 2 } }; - -#define BITALLOC_12_COUNT 5 +#define BITALLOC_12_COUNT 5 #define BITALLOC_12_VLC_BITS 9 static const uint8_t bitalloc_12_vlc_bits[BITALLOC_12_COUNT] = { - 9, 7, 7, 9, 9 + 9, 7, 7, 9, 9 }; + static const uint16_t bitalloc_12_codes[BITALLOC_12_COUNT][12] = { - { - 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x00FF, 0x00FE, - 0x01FB, 0x01FA, 0x01F9, 0x01F8, - }, - { - 0x0001, 0x0000, 0x0002, 0x000F, 0x000C, 0x001D, 0x0039, 0x0038, - 0x0037, 0x0036, 0x0035, 0x0034, - }, - { - 0x0000, 0x0007, 0x0005, 0x0004, 0x0002, 0x000D, 0x000C, 0x0006, - 0x000F, 0x001D, 0x0039, 0x0038, - }, - { - 0x0003, 0x0002, 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, - 0x007E, 0x00FE, 0x01FF, 0x01FE, - }, - { - 0x0001, 0x0000, 0x0002, 0x0006, 0x000E, 0x003F, 0x003D, 0x007C, - 0x0079, 0x0078, 0x00FB, 0x00FA, - } + { 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x00FF, 0x00FE, + 0x01FB, 0x01FA, 0x01F9, 0x01F8, }, + { 0x0001, 0x0000, 0x0002, 0x000F, 0x000C, 0x001D, 0x0039, 0x0038, + 0x0037, 0x0036, 0x0035, 0x0034, }, + { 0x0000, 0x0007, 0x0005, 0x0004, 0x0002, 0x000D, 0x000C, 0x0006, + 0x000F, 0x001D, 0x0039, 0x0038, }, + { 0x0003, 0x0002, 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, + 0x007E, 0x00FE, 0x01FF, 0x01FE, }, + { 0x0001, 0x0000, 0x0002, 0x0006, 0x000E, 0x003F, 0x003D, 0x007C, + 0x0079, 0x0078, 0x00FB, 0x00FA, } }; + static const uint8_t bitalloc_12_bits[BITALLOC_12_COUNT][12] = { - { 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 9, 9 }, - { 1, 2, 3, 5, 5, 6, 7, 7, 7, 7, 7, 7 }, - { 2, 3, 3, 3, 3, 4, 4, 4, 5, 6, 7, 7 }, - { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10 }, - { 1, 2, 3, 4, 5, 7, 7, 8, 8, 8, 9, 9 } + { 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 9, 9 }, + { 1, 2, 3, 5, 5, 6, 7, 7, 7, 7, 7, 7 }, + { 2, 3, 3, 3, 3, 4, 4, 4, 5, 6, 7, 7 }, + { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10 }, + { 1, 2, 3, 4, 5, 7, 7, 8, 8, 8, 9, 9 } }; - -#define SCALES_COUNT 5 +#define SCALES_COUNT 5 #define SCALES_VLC_BITS 9 static const uint16_t scales_codes[SCALES_COUNT][129] = { - { - 0x3AB0, 0x3AB2, 0x3AB4, 0x3AB6, 0x3AB8, 0x3ABA, 0x3ABC, 0x3ABE, - 0x3AC0, 0x3AC2, 0x3AC4, 0x3AC6, 0x3AC8, 0x3ACA, 0x3ACC, 0x3ACE, - 0x3AD0, 0x3AD2, 0x3AD4, 0x3AD6, 0x3AD8, 0x3ADA, 0x3ADC, 0x3ADE, - 0x3AE0, 0x3AE2, 0x3AE4, 0x3AE6, 0x3AE8, 0x3AEA, 0x3AEC, 0x3AEE, - 0x3AF0, 0x3AF2, 0x3AF4, 0x3AF6, 0x3AF8, 0x3AFA, 0x3AFC, 0x3AFE, - 0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, - 0x0558, 0x055E, 0x02AD, 0x0154, 0x0754, 0x03A8, 0x0056, 0x0028, - 0x00E8, 0x004A, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, - 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x004B, - 0x00E9, 0x0029, 0x0057, 0x03A9, 0x0755, 0x0155, 0x02AE, 0x055F, - 0x0559, 0x054F, 0x054D, 0x054B, 0x0549, 0x0547, 0x0545, 0x0543, - 0x0541, 0x3AFF, 0x3AFD, 0x3AFB, 0x3AF9, 0x3AF7, 0x3AF5, 0x3AF3, - 0x3AF1, 0x3AEF, 0x3AED, 0x3AEB, 0x3AE9, 0x3AE7, 0x3AE5, 0x3AE3, - 0x3AE1, 0x3ADF, 0x3ADD, 0x3ADB, 0x3AD9, 0x3AD7, 0x3AD5, 0x3AD3, - 0x3AD1, 0x3ACF, 0x3ACD, 0x3ACB, 0x3AC9, 0x3AC7, 0x3AC5, 0x3AC3, - 0x3AC1, 0x3ABF, 0x3ABD, 0x3ABB, 0x3AB9, 0x3AB7, 0x3AB5, 0x3AB3, - 0x3AB1, - }, - { - 0x0F60, 0x0F62, 0x0F64, 0x0F66, 0x0F68, 0x0F6A, 0x0F6C, 0x0F6E, - 0x0F70, 0x0F72, 0x0F74, 0x0F76, 0x0F78, 0x0F7A, 0x0F7C, 0x0F7E, - 0x0F80, 0x0F82, 0x0F84, 0x0F86, 0x0F88, 0x0F8A, 0x0F8C, 0x0F8E, - 0x0F90, 0x0F92, 0x0F94, 0x0F96, 0x0F98, 0x0F9A, 0x0F9C, 0x0F9E, - 0x0FA0, 0x0FA2, 0x0FA4, 0x0FA6, 0x0FA8, 0x0FAA, 0x0FAC, 0x0FAE, - 0x0FB0, 0x0FB2, 0x0FB4, 0x0FB6, 0x0FB8, 0x0FBA, 0x0FBC, 0x0FBE, - 0x07A0, 0x07A2, 0x03D2, 0x01EA, 0x00FC, 0x007F, 0x001C, 0x000C, - 0x0004, 0x0034, 0x0010, 0x001B, 0x0009, 0x000B, 0x000E, 0x0001, - 0x0003, 0x0002, 0x000F, 0x000C, 0x000A, 0x0000, 0x0011, 0x0035, - 0x0005, 0x000D, 0x001D, 0x003C, 0x00FD, 0x01EB, 0x03D3, 0x07A3, - 0x07A1, 0x0FBF, 0x0FBD, 0x0FBB, 0x0FB9, 0x0FB7, 0x0FB5, 0x0FB3, - 0x0FB1, 0x0FAF, 0x0FAD, 0x0FAB, 0x0FA9, 0x0FA7, 0x0FA5, 0x0FA3, - 0x0FA1, 0x0F9F, 0x0F9D, 0x0F9B, 0x0F99, 0x0F97, 0x0F95, 0x0F93, - 0x0F91, 0x0F8F, 0x0F8D, 0x0F8B, 0x0F89, 0x0F87, 0x0F85, 0x0F83, - 0x0F81, 0x0F7F, 0x0F7D, 0x0F7B, 0x0F79, 0x0F77, 0x0F75, 0x0F73, - 0x0F71, 0x0F6F, 0x0F6D, 0x0F6B, 0x0F69, 0x0F67, 0x0F65, 0x0F63, - 0x0F61, - }, - { - 0x51D0, 0x51D2, 0x51D4, 0x51D6, 0x51D8, 0x51DA, 0x51DC, 0x51DE, - 0x51E0, 0x51E2, 0x51E4, 0x51E6, 0x51E8, 0x51EA, 0x51EC, 0x51EE, - 0x51F0, 0x51F2, 0x51F4, 0x51F6, 0x51F8, 0x51FA, 0x51FC, 0x51FE, - 0x70C0, 0x70C2, 0x70C4, 0x70C6, 0x70C8, 0x70CA, 0x70CC, 0x70CE, - 0x70EC, 0x10EA, 0x3868, 0x3877, 0x0876, 0x1C35, 0x0434, 0x0A34, - 0x0E1B, 0x021B, 0x051B, 0x070F, 0x010F, 0x0380, 0x0080, 0x0140, - 0x01C1, 0x0041, 0x00A1, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012, - 0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000, - 0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B, - 0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A2, 0x0042, - 0x01C2, 0x0141, 0x0081, 0x0381, 0x028C, 0x010C, 0x051C, 0x021C, - 0x0E1C, 0x0A35, 0x0435, 0x1C3A, 0x0877, 0x0874, 0x3869, 0x10EB, - 0x70ED, 0x70CF, 0x70CD, 0x70CB, 0x70C9, 0x70C7, 0x70C5, 0x70C3, - 0x70C1, 0x51FF, 0x51FD, 0x51FB, 0x51F9, 0x51F7, 0x51F5, 0x51F3, - 0x51F1, 0x51EF, 0x51ED, 0x51EB, 0x51E9, 0x51E7, 0x51E5, 0x51E3, - 0x51E1, 0x51DF, 0x51DD, 0x51DB, 0x51D9, 0x51D7, 0x51D5, 0x51D3, - 0x51D1, - }, - { - 0x6F64, 0x6F66, 0x6F68, 0x6F6A, 0x6F6C, 0x6F6E, 0x6F70, 0x6F72, - 0x6F74, 0x6F76, 0x6F78, 0x6F7A, 0x6F7C, 0x6F7E, 0x6F80, 0x6F82, - 0x6F84, 0x6F86, 0x6F88, 0x6F8A, 0x6F8C, 0x6F8E, 0x6F90, 0x6F92, - 0x6F94, 0x6F96, 0x6F98, 0x6F9A, 0x6F9C, 0x6F9E, 0x6FA0, 0x6FA2, - 0x6FA4, 0x6FA6, 0x6FA8, 0x6FAA, 0x6FAC, 0x6FAE, 0x6FB0, 0x6FB2, - 0x6FB4, 0x6FB6, 0x17B4, 0x37DC, 0x0BDB, 0x1BEF, 0x05EE, 0x0DF8, - 0x02F8, 0x06FD, 0x017D, 0x037F, 0x00BF, 0x0040, 0x00C0, 0x0021, - 0x0061, 0x0011, 0x0031, 0x0009, 0x0019, 0x0006, 0x000E, 0x0004, - 0x0000, 0x0005, 0x000F, 0x0007, 0x001A, 0x000A, 0x0036, 0x0016, - 0x006E, 0x002E, 0x00C1, 0x0041, 0x01BC, 0x00BC, 0x037A, 0x017A, - 0x02F9, 0x0DF9, 0x05EF, 0x05EC, 0x1BD8, 0x37DD, 0x17B5, 0x6FB7, - 0x6FB5, 0x6FB3, 0x6FB1, 0x6FAF, 0x6FAD, 0x6FAB, 0x6FA9, 0x6FA7, - 0x6FA5, 0x6FA3, 0x6FA1, 0x6F9F, 0x6F9D, 0x6F9B, 0x6F99, 0x6F97, - 0x6F95, 0x6F93, 0x6F91, 0x6F8F, 0x6F8D, 0x6F8B, 0x6F89, 0x6F87, - 0x6F85, 0x6F83, 0x6F81, 0x6F7F, 0x6F7D, 0x6F7B, 0x6F79, 0x6F77, - 0x6F75, 0x6F73, 0x6F71, 0x6F6F, 0x6F6D, 0x6F6B, 0x6F69, 0x6F67, - 0x6F65, - }, - { - 0xDF54, 0xDF56, 0xDFC8, 0xDFCA, 0xDFCC, 0xDFCE, 0xDFD0, 0xDFD2, - 0xDFD4, 0xDFD6, 0xDFD8, 0xDFDA, 0xDFDC, 0xDFDE, 0xDFE0, 0xDFE2, - 0x0FE8, 0x2FEA, 0x6FA8, 0x6FF6, 0x07F5, 0x07F7, 0x37D2, 0x37F9, - 0x03F8, 0x0BF8, 0x0BFB, 0x1BEB, 0x01FA, 0x05FA, 0x09FA, 0x0DFA, - 0x0DFF, 0x00FF, 0x02FF, 0x06FB, 0x007C, 0x017C, 0x027C, 0x027F, - 0x003C, 0x00BC, 0x013C, 0x01BC, 0x001C, 0x005C, 0x009C, 0x00DC, - 0x000C, 0x002C, 0x004C, 0x006C, 0x0004, 0x0014, 0x0024, 0x0034, - 0x0000, 0x0008, 0x0010, 0x0018, 0x001E, 0x0002, 0x0006, 0x000A, - 0x000E, 0x000B, 0x0007, 0x0003, 0x001F, 0x0019, 0x0011, 0x0009, - 0x0001, 0x0035, 0x0025, 0x0015, 0x0005, 0x006D, 0x004D, 0x002D, - 0x000D, 0x00DD, 0x009D, 0x005D, 0x001D, 0x01BD, 0x013D, 0x00BD, - 0x003D, 0x037C, 0x027D, 0x017D, 0x007D, 0x06FC, 0x04FC, 0x02FC, - 0x00FC, 0x0DFB, 0x09FB, 0x05FB, 0x01FB, 0x1BF8, 0x1BE8, 0x0BF9, - 0x03F9, 0x37FA, 0x37D3, 0x17F4, 0x07F6, 0x6FF7, 0x6FA9, 0x2FEB, - 0x0FE9, 0xDFE3, 0xDFE1, 0xDFDF, 0xDFDD, 0xDFDB, 0xDFD9, 0xDFD7, - 0xDFD5, 0xDFD3, 0xDFD1, 0xDFCF, 0xDFCD, 0xDFCB, 0xDFC9, 0xDF57, - 0xDF55, - } + { 0x3AB0, 0x3AB2, 0x3AB4, 0x3AB6, 0x3AB8, 0x3ABA, 0x3ABC, 0x3ABE, + 0x3AC0, 0x3AC2, 0x3AC4, 0x3AC6, 0x3AC8, 0x3ACA, 0x3ACC, 0x3ACE, + 0x3AD0, 0x3AD2, 0x3AD4, 0x3AD6, 0x3AD8, 0x3ADA, 0x3ADC, 0x3ADE, + 0x3AE0, 0x3AE2, 0x3AE4, 0x3AE6, 0x3AE8, 0x3AEA, 0x3AEC, 0x3AEE, + 0x3AF0, 0x3AF2, 0x3AF4, 0x3AF6, 0x3AF8, 0x3AFA, 0x3AFC, 0x3AFE, + 0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, + 0x0558, 0x055E, 0x02AD, 0x0154, 0x0754, 0x03A8, 0x0056, 0x0028, + 0x00E8, 0x004A, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, + 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x004B, + 0x00E9, 0x0029, 0x0057, 0x03A9, 0x0755, 0x0155, 0x02AE, 0x055F, + 0x0559, 0x054F, 0x054D, 0x054B, 0x0549, 0x0547, 0x0545, 0x0543, + 0x0541, 0x3AFF, 0x3AFD, 0x3AFB, 0x3AF9, 0x3AF7, 0x3AF5, 0x3AF3, + 0x3AF1, 0x3AEF, 0x3AED, 0x3AEB, 0x3AE9, 0x3AE7, 0x3AE5, 0x3AE3, + 0x3AE1, 0x3ADF, 0x3ADD, 0x3ADB, 0x3AD9, 0x3AD7, 0x3AD5, 0x3AD3, + 0x3AD1, 0x3ACF, 0x3ACD, 0x3ACB, 0x3AC9, 0x3AC7, 0x3AC5, 0x3AC3, + 0x3AC1, 0x3ABF, 0x3ABD, 0x3ABB, 0x3AB9, 0x3AB7, 0x3AB5, 0x3AB3, + 0x3AB1, }, + { 0x0F60, 0x0F62, 0x0F64, 0x0F66, 0x0F68, 0x0F6A, 0x0F6C, 0x0F6E, + 0x0F70, 0x0F72, 0x0F74, 0x0F76, 0x0F78, 0x0F7A, 0x0F7C, 0x0F7E, + 0x0F80, 0x0F82, 0x0F84, 0x0F86, 0x0F88, 0x0F8A, 0x0F8C, 0x0F8E, + 0x0F90, 0x0F92, 0x0F94, 0x0F96, 0x0F98, 0x0F9A, 0x0F9C, 0x0F9E, + 0x0FA0, 0x0FA2, 0x0FA4, 0x0FA6, 0x0FA8, 0x0FAA, 0x0FAC, 0x0FAE, + 0x0FB0, 0x0FB2, 0x0FB4, 0x0FB6, 0x0FB8, 0x0FBA, 0x0FBC, 0x0FBE, + 0x07A0, 0x07A2, 0x03D2, 0x01EA, 0x00FC, 0x007F, 0x001C, 0x000C, + 0x0004, 0x0034, 0x0010, 0x001B, 0x0009, 0x000B, 0x000E, 0x0001, + 0x0003, 0x0002, 0x000F, 0x000C, 0x000A, 0x0000, 0x0011, 0x0035, + 0x0005, 0x000D, 0x001D, 0x003C, 0x00FD, 0x01EB, 0x03D3, 0x07A3, + 0x07A1, 0x0FBF, 0x0FBD, 0x0FBB, 0x0FB9, 0x0FB7, 0x0FB5, 0x0FB3, + 0x0FB1, 0x0FAF, 0x0FAD, 0x0FAB, 0x0FA9, 0x0FA7, 0x0FA5, 0x0FA3, + 0x0FA1, 0x0F9F, 0x0F9D, 0x0F9B, 0x0F99, 0x0F97, 0x0F95, 0x0F93, + 0x0F91, 0x0F8F, 0x0F8D, 0x0F8B, 0x0F89, 0x0F87, 0x0F85, 0x0F83, + 0x0F81, 0x0F7F, 0x0F7D, 0x0F7B, 0x0F79, 0x0F77, 0x0F75, 0x0F73, + 0x0F71, 0x0F6F, 0x0F6D, 0x0F6B, 0x0F69, 0x0F67, 0x0F65, 0x0F63, + 0x0F61, }, + { 0x51D0, 0x51D2, 0x51D4, 0x51D6, 0x51D8, 0x51DA, 0x51DC, 0x51DE, + 0x51E0, 0x51E2, 0x51E4, 0x51E6, 0x51E8, 0x51EA, 0x51EC, 0x51EE, + 0x51F0, 0x51F2, 0x51F4, 0x51F6, 0x51F8, 0x51FA, 0x51FC, 0x51FE, + 0x70C0, 0x70C2, 0x70C4, 0x70C6, 0x70C8, 0x70CA, 0x70CC, 0x70CE, + 0x70EC, 0x10EA, 0x3868, 0x3877, 0x0876, 0x1C35, 0x0434, 0x0A34, + 0x0E1B, 0x021B, 0x051B, 0x070F, 0x010F, 0x0380, 0x0080, 0x0140, + 0x01C1, 0x0041, 0x00A1, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012, + 0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000, + 0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B, + 0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A2, 0x0042, + 0x01C2, 0x0141, 0x0081, 0x0381, 0x028C, 0x010C, 0x051C, 0x021C, + 0x0E1C, 0x0A35, 0x0435, 0x1C3A, 0x0877, 0x0874, 0x3869, 0x10EB, + 0x70ED, 0x70CF, 0x70CD, 0x70CB, 0x70C9, 0x70C7, 0x70C5, 0x70C3, + 0x70C1, 0x51FF, 0x51FD, 0x51FB, 0x51F9, 0x51F7, 0x51F5, 0x51F3, + 0x51F1, 0x51EF, 0x51ED, 0x51EB, 0x51E9, 0x51E7, 0x51E5, 0x51E3, + 0x51E1, 0x51DF, 0x51DD, 0x51DB, 0x51D9, 0x51D7, 0x51D5, 0x51D3, + 0x51D1, }, + { 0x6F64, 0x6F66, 0x6F68, 0x6F6A, 0x6F6C, 0x6F6E, 0x6F70, 0x6F72, + 0x6F74, 0x6F76, 0x6F78, 0x6F7A, 0x6F7C, 0x6F7E, 0x6F80, 0x6F82, + 0x6F84, 0x6F86, 0x6F88, 0x6F8A, 0x6F8C, 0x6F8E, 0x6F90, 0x6F92, + 0x6F94, 0x6F96, 0x6F98, 0x6F9A, 0x6F9C, 0x6F9E, 0x6FA0, 0x6FA2, + 0x6FA4, 0x6FA6, 0x6FA8, 0x6FAA, 0x6FAC, 0x6FAE, 0x6FB0, 0x6FB2, + 0x6FB4, 0x6FB6, 0x17B4, 0x37DC, 0x0BDB, 0x1BEF, 0x05EE, 0x0DF8, + 0x02F8, 0x06FD, 0x017D, 0x037F, 0x00BF, 0x0040, 0x00C0, 0x0021, + 0x0061, 0x0011, 0x0031, 0x0009, 0x0019, 0x0006, 0x000E, 0x0004, + 0x0000, 0x0005, 0x000F, 0x0007, 0x001A, 0x000A, 0x0036, 0x0016, + 0x006E, 0x002E, 0x00C1, 0x0041, 0x01BC, 0x00BC, 0x037A, 0x017A, + 0x02F9, 0x0DF9, 0x05EF, 0x05EC, 0x1BD8, 0x37DD, 0x17B5, 0x6FB7, + 0x6FB5, 0x6FB3, 0x6FB1, 0x6FAF, 0x6FAD, 0x6FAB, 0x6FA9, 0x6FA7, + 0x6FA5, 0x6FA3, 0x6FA1, 0x6F9F, 0x6F9D, 0x6F9B, 0x6F99, 0x6F97, + 0x6F95, 0x6F93, 0x6F91, 0x6F8F, 0x6F8D, 0x6F8B, 0x6F89, 0x6F87, + 0x6F85, 0x6F83, 0x6F81, 0x6F7F, 0x6F7D, 0x6F7B, 0x6F79, 0x6F77, + 0x6F75, 0x6F73, 0x6F71, 0x6F6F, 0x6F6D, 0x6F6B, 0x6F69, 0x6F67, + 0x6F65, }, + { 0xDF54, 0xDF56, 0xDFC8, 0xDFCA, 0xDFCC, 0xDFCE, 0xDFD0, 0xDFD2, + 0xDFD4, 0xDFD6, 0xDFD8, 0xDFDA, 0xDFDC, 0xDFDE, 0xDFE0, 0xDFE2, + 0x0FE8, 0x2FEA, 0x6FA8, 0x6FF6, 0x07F5, 0x07F7, 0x37D2, 0x37F9, + 0x03F8, 0x0BF8, 0x0BFB, 0x1BEB, 0x01FA, 0x05FA, 0x09FA, 0x0DFA, + 0x0DFF, 0x00FF, 0x02FF, 0x06FB, 0x007C, 0x017C, 0x027C, 0x027F, + 0x003C, 0x00BC, 0x013C, 0x01BC, 0x001C, 0x005C, 0x009C, 0x00DC, + 0x000C, 0x002C, 0x004C, 0x006C, 0x0004, 0x0014, 0x0024, 0x0034, + 0x0000, 0x0008, 0x0010, 0x0018, 0x001E, 0x0002, 0x0006, 0x000A, + 0x000E, 0x000B, 0x0007, 0x0003, 0x001F, 0x0019, 0x0011, 0x0009, + 0x0001, 0x0035, 0x0025, 0x0015, 0x0005, 0x006D, 0x004D, 0x002D, + 0x000D, 0x00DD, 0x009D, 0x005D, 0x001D, 0x01BD, 0x013D, 0x00BD, + 0x003D, 0x037C, 0x027D, 0x017D, 0x007D, 0x06FC, 0x04FC, 0x02FC, + 0x00FC, 0x0DFB, 0x09FB, 0x05FB, 0x01FB, 0x1BF8, 0x1BE8, 0x0BF9, + 0x03F9, 0x37FA, 0x37D3, 0x17F4, 0x07F6, 0x6FF7, 0x6FA9, 0x2FEB, + 0x0FE9, 0xDFE3, 0xDFE1, 0xDFDF, 0xDFDD, 0xDFDB, 0xDFD9, 0xDFD7, + 0xDFD5, 0xDFD3, 0xDFD1, 0xDFCF, 0xDFCD, 0xDFCB, 0xDFC9, 0xDF57, + 0xDF55, } }; static const uint8_t scales_bits[SCALES_COUNT][129] = { - { - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 11, 11, 10, 9, 8, - 8, 7, 6, 6, 5, 4, 4, 3, - 2, 3, 3, 4, 5, 5, 6, 7, - 8, 8, 9, 10, 11, 11, 12, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, - }, - { - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 13, 12, 11, 10, 8, 7, - 6, 6, 5, 5, 4, 4, 4, 3, - 3, 3, 4, 4, 4, 4, 5, 6, - 6, 7, 8, 9, 11, 12, 13, 14, - 14, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, - }, - { - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 14, 14, 14, 13, 13, 12, 12, - 12, 11, 11, 11, 10, 10, 9, 9, - 9, 8, 8, 8, 7, 7, 7, 6, - 6, 6, 5, 5, 5, 4, 4, 3, - 3, 3, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, - 9, 9, 9, 10, 10, 10, 11, 11, - 12, 12, 12, 13, 13, 13, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, - }, - { - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 14, 14, 13, 13, 12, 12, - 11, 11, 10, 10, 9, 8, 8, 7, - 7, 6, 6, 5, 5, 4, 4, 3, - 2, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, - 11, 12, 12, 12, 13, 14, 14, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, - }, - { - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 14, 14, 14, 14, - 13, 13, 13, 13, 12, 12, 12, 12, - 12, 11, 11, 11, 10, 10, 10, 10, - 9, 9, 9, 9, 8, 8, 8, 8, - 7, 7, 7, 7, 6, 6, 6, 6, - 5, 5, 5, 5, 5, 4, 4, 4, - 4, 4, 4, 4, 5, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, - } + { 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 11, 11, 10, 9, 8, + 8, 7, 6, 6, 5, 4, 4, 3, + 2, 3, 3, 4, 5, 5, 6, 7, + 8, 8, 9, 10, 11, 11, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, }, + { 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 13, 12, 11, 10, 8, 7, + 6, 6, 5, 5, 4, 4, 4, 3, + 3, 3, 4, 4, 4, 4, 5, 6, + 6, 7, 8, 9, 11, 12, 13, 14, + 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, }, + { 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 14, 14, 14, 13, 13, 12, 12, + 12, 11, 11, 11, 10, 10, 9, 9, + 9, 8, 8, 8, 7, 7, 7, 6, + 6, 6, 5, 5, 5, 4, 4, 3, + 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 11, 11, + 12, 12, 12, 13, 13, 13, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, }, + { 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 14, 13, 13, 12, 12, + 11, 11, 10, 10, 9, 8, 8, 7, + 7, 6, 6, 5, 5, 4, 4, 3, + 2, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, + 11, 12, 12, 12, 13, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, }, + { 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 14, 14, 14, + 13, 13, 13, 13, 12, 12, 12, 12, + 12, 11, 11, 11, 10, 10, 10, 10, + 9, 9, 9, 9, 8, 8, 8, 8, + 7, 7, 7, 7, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 4, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, + } }; -static const uint16_t bitalloc_3_codes[3] = -{ +static const uint16_t bitalloc_3_codes[3] = { 0x0003, 0x0000, 0x0002, }; -static const uint8_t bitalloc_3_bits[3] = -{ - 2, 1, 2, + +static const uint8_t bitalloc_3_bits[3] = { + 2, 1, 2, }; -static const uint16_t bitalloc_5_codes_a[5] = -{ +static const uint16_t bitalloc_5_codes_a[5] = { 0x000F, 0x0006, 0x0000, 0x0002, 0x000E, }; -static const uint16_t bitalloc_5_codes_b[5] = -{ + +static const uint16_t bitalloc_5_codes_b[5] = { 0x0007, 0x0001, 0x0002, 0x0000, 0x0006, }; -static const uint16_t bitalloc_5_codes_c[5] = -{ + +static const uint16_t bitalloc_5_codes_c[5] = { 0x0007, 0x0005, 0x0000, 0x0004, 0x0006, }; -static const uint8_t bitalloc_5_bits_a[5] = -{ - 4, 3, 1, 2, 4, + +static const uint8_t bitalloc_5_bits_a[5] = { + 4, 3, 1, 2, 4, }; -static const uint8_t bitalloc_5_bits_b[5] = -{ - 3, 2, 2, 2, 3, + +static const uint8_t bitalloc_5_bits_b[5] = { + 3, 2, 2, 2, 3, }; -static const uint8_t bitalloc_5_bits_c[5] = -{ - 3, 3, 1, 3, 3, + +static const uint8_t bitalloc_5_bits_c[5] = { + 3, 3, 1, 3, 3, }; -static const uint16_t bitalloc_7_codes_a[7] = -{ +static const uint16_t bitalloc_7_codes_a[7] = { 0x001E, 0x000E, 0x0005, 0x0000, 0x0006, 0x0004, 0x001F, }; -static const uint16_t bitalloc_7_codes_b[7] = -{ + +static const uint16_t bitalloc_7_codes_b[7] = { 0x0014, 0x000B, 0x0000, 0x0003, 0x0001, 0x0004, 0x0015, }; -static const uint16_t bitalloc_7_codes_c[7] = -{ + +static const uint16_t bitalloc_7_codes_c[7] = { 0x0000, 0x0002, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001, }; -static const uint8_t bitalloc_7_bits_a[7] = -{ - 5, 4, 3, 1, 3, 3, 5, + +static const uint8_t bitalloc_7_bits_a[7] = { + 5, 4, 3, 1, 3, 3, 5, }; -static const uint8_t bitalloc_7_bits_b[7] = -{ - 5, 4, 2, 2, 2, 3, 5, + +static const uint8_t bitalloc_7_bits_b[7] = { + 5, 4, 2, 2, 2, 3, 5, }; -static const uint8_t bitalloc_7_bits_c[7] = -{ - 4, 4, 2, 2, 2, 4, 4, + +static const uint8_t bitalloc_7_bits_c[7] = { + 4, 4, 2, 2, 2, 4, 4, }; -static const uint16_t bitalloc_9_codes_a[9] = -{ +static const uint16_t bitalloc_9_codes_a[9] = { 0x0030, 0x0019, 0x0009, 0x0005, 0x0000, 0x0007, 0x000D, 0x0008, 0x0031, }; -static const uint16_t bitalloc_9_codes_b[9] = -{ + +static const uint16_t bitalloc_9_codes_b[9] = { 0x0018, 0x001A, 0x0002, 0x0007, 0x0002, 0x0000, 0x0003, 0x001B, 0x0019, }; -static const uint16_t bitalloc_9_codes_c[9] = -{ + +static const uint16_t bitalloc_9_codes_c[9] = { 0x001C, 0x000F, 0x0002, 0x0007, 0x0002, 0x0000, 0x0006, 0x0006, 0x001D, }; -static const uint8_t bitalloc_9_bits_a[9] = -{ - 6, 5, 4, 3, 1, 3, 4, 4, 6, + +static const uint8_t bitalloc_9_bits_a[9] = { + 6, 5, 4, 3, 1, 3, 4, 4, 6, }; -static const uint8_t bitalloc_9_bits_b[9] = -{ - 5, 5, 3, 3, 2, 2, 3, 5, 5, + +static const uint8_t bitalloc_9_bits_b[9] = { + 5, 5, 3, 3, 2, 2, 3, 5, 5, }; -static const uint8_t bitalloc_9_bits_c[9] = -{ - 6, 5, 3, 3, 2, 2, 3, 4, 6, + +static const uint8_t bitalloc_9_bits_c[9] = { + 6, 5, 3, 3, 2, 2, 3, 4, 6, }; -static const uint16_t bitalloc_13_codes_a[13] = -{ +static const uint16_t bitalloc_13_codes_a[13] = { 0x0070, 0x002E, 0x0039, 0x001D, 0x000C, 0x000F, 0x0000, 0x0004, 0x000D, 0x000A, 0x0016, 0x002F, 0x0071, }; -static const uint16_t bitalloc_13_codes_b[13] = -{ + +static const uint16_t bitalloc_13_codes_b[13] = { 0x0038, 0x0010, 0x001D, 0x0007, 0x000F, 0x0005, 0x0000, 0x0006, 0x0002, 0x0009, 0x0006, 0x0011, 0x0039, }; -static const uint16_t bitalloc_13_codes_c[13] = -{ + +static const uint16_t bitalloc_13_codes_c[13] = { 0x0004, 0x001A, 0x0003, 0x000E, 0x0000, 0x0003, 0x0005, 0x0004, 0x0002, 0x000F, 0x000C, 0x001B, 0x0005, }; -static const uint8_t bitalloc_13_bits_a[13] = -{ + +static const uint8_t bitalloc_13_bits_a[13] = { 7, 6, 6, 5, 4, 4, 1, 3, 4, 4, 5, 6, 7, }; -static const uint8_t bitalloc_13_bits_b[13] = -{ + +static const uint8_t bitalloc_13_bits_b[13] = { 6, 5, 5, 4, 4, 3, 2, 3, 3, 4, 4, 5, 6, }; -static const uint8_t bitalloc_13_bits_c[13] = -{ + +static const uint8_t bitalloc_13_bits_c[13] = { 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, }; -static const uint16_t bitalloc_17_codes_a[17] = -{ +static const uint16_t bitalloc_17_codes_a[17] = { 0x0154, 0x00AB, 0x002B, 0x000B, 0x0003, 0x000A, 0x0001, 0x0006, 0x0001, 0x0007, 0x0004, 0x000B, 0x0000, 0x0004, 0x0014, 0x0054, 0x0155, }; -static const uint16_t bitalloc_17_codes_b[17] = -{ + +static const uint16_t bitalloc_17_codes_b[17] = { 0x007C, 0x003F, 0x0019, 0x000D, 0x001C, 0x0008, 0x000F, 0x0005, 0x0000, 0x0006, 0x0002, 0x0009, 0x001D, 0x000E, 0x001E, 0x0018, 0x007D, }; -static const uint16_t bitalloc_17_codes_c[17] = -{ + +static const uint16_t bitalloc_17_codes_c[17] = { 0x002C, 0x0017, 0x0005, 0x001C, 0x0003, 0x000A, 0x000F, 0x0003, 0x0006, 0x0004, 0x0000, 0x000B, 0x0004, 0x001D, 0x000A, 0x0004, 0x002D, }; -static const uint16_t bitalloc_17_codes_d[17] = -{ + +static const uint16_t bitalloc_17_codes_d[17] = { 0x0100, 0x0102, 0x0082, 0x0042, 0x0022, 0x0012, 0x000A, 0x0006, 0x0000, 0x0007, 0x000B, 0x0013, 0x0023, 0x0043, 0x0083, 0x0103, 0x0101, }; -static const uint16_t bitalloc_17_codes_e[17] = -{ + +static const uint16_t bitalloc_17_codes_e[17] = { 0x00E8, 0x00F6, 0x0075, 0x0034, 0x003B, 0x001B, 0x001F, 0x0004, 0x0000, 0x0005, 0x000C, 0x001C, 0x003C, 0x0035, 0x007A, 0x00F7, 0x00E9, }; -static const uint16_t bitalloc_17_codes_f[17] = -{ + +static const uint16_t bitalloc_17_codes_f[17] = { 0x0004, 0x0003, 0x001E, 0x0001, 0x0001, 0x000E, 0x0001, 0x0004, 0x0006, 0x0005, 0x0002, 0x000F, 0x0006, 0x000E, 0x001F, 0x0000, 0x0005, }; -static const uint16_t bitalloc_17_codes_g[17] = -{ + +static const uint16_t bitalloc_17_codes_g[17] = { 0x0060, 0x007E, 0x0031, 0x0019, 0x000D, 0x0004, 0x0000, 0x0006, 0x0002, 0x0007, 0x0001, 0x0005, 0x000E, 0x001E, 0x003E, 0x007F, 0x0061, }; -static const uint8_t bitalloc_17_bits_a[17] = -{ + +static const uint8_t bitalloc_17_bits_a[17] = { 12, 11, 9, 7, 5, 4, 3, 3, 2, 3, 3, 4, 4, 6, 8, 10, 12, }; -static const uint8_t bitalloc_17_bits_b[17] = -{ - 8, 7, 6, 5, 5, 4, 4, 3, 2, 3, 3, 4, 5, 5, 6, 6, - 8, + +static const uint8_t bitalloc_17_bits_b[17] = { + 8, 7, 6, 5, 5, 4, 4, 3, 2, 3, 3, 4, 5, 5, 6, 6, + 8, }; -static const uint8_t bitalloc_17_bits_c[17] = -{ - 7, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5, 5, - 7, + +static const uint8_t bitalloc_17_bits_c[17] = { + 7, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5, 5, + 7, }; -static const uint8_t bitalloc_17_bits_d[17] = -{ - 9, 9, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7, 8, 9, - 9, + +static const uint8_t bitalloc_17_bits_d[17] = { + 9, 9, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7, 8, 9, + 9, }; -static const uint8_t bitalloc_17_bits_e[17] = -{ - 8, 8, 7, 6, 6, 5, 5, 3, 1, 3, 4, 5, 6, 6, 7, 8, - 8, + +static const uint8_t bitalloc_17_bits_e[17] = { + 8, 8, 7, 6, 6, 5, 5, 3, 1, 3, 4, 5, 6, 6, 7, 8, + 8, }; -static const uint8_t bitalloc_17_bits_f[17] = -{ - 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, - 8, + +static const uint8_t bitalloc_17_bits_f[17] = { + 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, + 8, }; -static const uint8_t bitalloc_17_bits_g[17] = -{ - 8, 8, 7, 6, 5, 4, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, - 8, + +static const uint8_t bitalloc_17_bits_g[17] = { + 8, 8, 7, 6, 5, 4, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, + 8, }; -static const uint16_t bitalloc_25_codes_a[25] = -{ +static const uint16_t bitalloc_25_codes_a[25] = { 0x2854, 0x142B, 0x050B, 0x0143, 0x00A2, 0x0052, 0x002E, 0x0015, 0x0004, 0x000E, 0x0000, 0x0003, 0x0006, 0x0004, 0x0001, 0x000F, 0x0005, 0x0016, 0x002F, 0x0053, 0x00A3, 0x00A0, 0x0284, 0x0A14, 0x2855, }; -static const uint16_t bitalloc_25_codes_b[25] = -{ + +static const uint16_t bitalloc_25_codes_b[25] = { 0x001C, 0x000F, 0x0005, 0x0000, 0x0030, 0x0036, 0x000E, 0x0019, 0x0001, 0x0008, 0x000E, 0x0001, 0x0005, 0x0002, 0x000F, 0x0009, 0x0006, 0x001A, 0x000F, 0x0037, 0x0031, 0x0001, 0x0006, 0x0004, 0x001D, }; -static const uint16_t bitalloc_25_codes_c[25] = -{ + +static const uint16_t bitalloc_25_codes_c[25] = { 0x004C, 0x0027, 0x006D, 0x0028, 0x0037, 0x000E, 0x0015, 0x0000, 0x0005, 0x0008, 0x000B, 0x000E, 0x0001, 0x000F, 0x000C, 0x0009, 0x0006, 0x0001, 0x001A, 0x000F, 0x0008, 0x0029, 0x0012, 0x006C, 0x004D, }; -static const uint16_t bitalloc_25_codes_d[25] = -{ + +static const uint16_t bitalloc_25_codes_d[25] = { 0x0780, 0x0782, 0x03C2, 0x01E2, 0x00FE, 0x0079, 0x003D, 0x001C, 0x000C, 0x0004, 0x0000, 0x0006, 0x0002, 0x0007, 0x0001, 0x0005, 0x000D, 0x001D, 0x003E, 0x007E, 0x00FF, 0x01E3, 0x03C3, 0x0783, 0x0781, }; -static const uint16_t bitalloc_25_codes_e[25] = -{ + +static const uint16_t bitalloc_25_codes_e[25] = { 0x003C, 0x0092, 0x0018, 0x001F, 0x004E, 0x000D, 0x0025, 0x0004, 0x0010, 0x0000, 0x000A, 0x0002, 0x0003, 0x0003, 0x000B, 0x0001, 0x0011, 0x0005, 0x0026, 0x000E, 0x004F, 0x0048, 0x0019, 0x0093, 0x003D, }; -static const uint16_t bitalloc_25_codes_f[25] = -{ + +static const uint16_t bitalloc_25_codes_f[25] = { 0x0324, 0x0193, 0x00CE, 0x0065, 0x0024, 0x000C, 0x0013, 0x0004, 0x0007, 0x000A, 0x000D, 0x000F, 0x0001, 0x0000, 0x000E, 0x000B, 0x0008, 0x0005, 0x0018, 0x000D, 0x0025, 0x0066, 0x00CF, 0x00C8, 0x0325, }; -static const uint16_t bitalloc_25_codes_g[25] = -{ + +static const uint16_t bitalloc_25_codes_g[25] = { 0x03A8, 0x03AE, 0x01D5, 0x0094, 0x0014, 0x004B, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x0074, 0x0015, 0x0095, 0x01D6, 0x03AF, 0x03A9, }; -static const uint8_t bitalloc_25_bits_a[25] = -{ + +static const uint8_t bitalloc_25_bits_a[25] = { 14, 13, 11, 9, 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 6, 7, 8, 8, 10, 12, 14, }; -static const uint8_t bitalloc_25_bits_b[25] = -{ - 9, 8, 7, 6, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, - 4, 5, 5, 6, 6, 6, 7, 7, 9, + +static const uint8_t bitalloc_25_bits_b[25] = { + 9, 8, 7, 6, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, + 4, 5, 5, 6, 6, 6, 7, 7, 9, }; -static const uint8_t bitalloc_25_bits_c[25] = -{ - 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4, 4, 3, 4, 4, 4, - 4, 4, 5, 5, 5, 6, 6, 7, 8, + +static const uint8_t bitalloc_25_bits_c[25] = { + 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4, 4, 3, 4, 4, 4, + 4, 4, 5, 5, 5, 6, 6, 7, 8, }; -static const uint8_t bitalloc_25_bits_d[25] = -{ + +static const uint8_t bitalloc_25_bits_d[25] = { 12, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, }; -static const uint8_t bitalloc_25_bits_e[25] = -{ - 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, 2, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 7, 8, 8, + +static const uint8_t bitalloc_25_bits_e[25] = { + 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, 2, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 7, 8, 8, }; -static const uint8_t bitalloc_25_bits_f[25] = -{ + +static const uint8_t bitalloc_25_bits_f[25] = { 10, 9, 8, 7, 6, 5, 5, 4, 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 8, 8, 10, }; -static const uint8_t bitalloc_25_bits_g[25] = -{ + +static const uint8_t bitalloc_25_bits_g[25] = { 10, 10, 9, 8, 7, 7, 6, 6, 5, 4, 4, 3, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, }; -static const uint16_t bitalloc_33_codes_a[33] = -{ +static const uint16_t bitalloc_33_codes_a[33] = { 0x1580, 0x1582, 0x0AC2, 0x0562, 0x02B2, 0x015E, 0x00AD, 0x0054, 0x001C, 0x003C, 0x000F, 0x001F, 0x0008, 0x000B, 0x000D, 0x0000, 0x0002, 0x0001, 0x000E, 0x000C, 0x0009, 0x0006, 0x0014, 0x003D, 0x001D, 0x0055, 0x00AE, 0x015F, 0x02B3, 0x0563, 0x0AC3, 0x1583, 0x1581, }; -static const uint16_t bitalloc_33_codes_b[33] = -{ + +static const uint16_t bitalloc_33_codes_b[33] = { 0x030C, 0x0187, 0x006D, 0x0028, 0x0037, 0x0066, 0x0015, 0x0031, 0x0000, 0x000B, 0x0012, 0x001A, 0x0001, 0x0007, 0x000A, 0x000E, 0x0001, 0x000F, 0x000B, 0x0008, 0x0004, 0x001B, 0x0013, 0x000C, 0x0001, 0x0032, 0x001A, 0x0067, 0x0060, 0x0029, 0x00C2, 0x006C, 0x030D, }; -static const uint16_t bitalloc_33_codes_c[33] = -{ + +static const uint16_t bitalloc_33_codes_c[33] = { 0x00CC, 0x0067, 0x0005, 0x0070, 0x0003, 0x001A, 0x0039, 0x003F, 0x000A, 0x0012, 0x0018, 0x001D, 0x0001, 0x0003, 0x0007, 0x000A, 0x000D, 0x000B, 0x0008, 0x0004, 0x0002, 0x001E, 0x0019, 0x0013, 0x000B, 0x0000, 0x003E, 0x001B, 0x0018, 0x0071, 0x0032, 0x0004, 0x00CD, }; -static const uint16_t bitalloc_33_codes_d[33] = -{ + +static const uint16_t bitalloc_33_codes_d[33] = { 0x3AF8, 0x3AFA, 0x1D7E, 0x0EBC, 0x075C, 0x03AC, 0x01D4, 0x0094, 0x0014, 0x004B, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x0074, 0x0015, 0x0095, 0x01D5, 0x03AD, 0x075D, 0x0EBD, 0x1D7F, 0x3AFB, 0x3AF9, }; -static const uint16_t bitalloc_33_codes_e[33] = -{ + +static const uint16_t bitalloc_33_codes_e[33] = { 0x01C8, 0x01E6, 0x0064, 0x00E2, 0x00E5, 0x0030, 0x0033, 0x0073, 0x007A, 0x001A, 0x003A, 0x0002, 0x001A, 0x001F, 0x0007, 0x0001, 0x0002, 0x0002, 0x000C, 0x0000, 0x001B, 0x0003, 0x003B, 0x001B, 0x007B, 0x0078, 0x0070, 0x0031, 0x00F2, 0x00E3, 0x0065, 0x01E7, 0x01C9, }; -static const uint16_t bitalloc_33_codes_f[33] = -{ + +static const uint16_t bitalloc_33_codes_f[33] = { 0x0724, 0x0393, 0x01CE, 0x00E5, 0x002C, 0x0008, 0x0017, 0x003E, 0x0005, 0x0014, 0x001D, 0x0000, 0x0003, 0x0006, 0x0008, 0x000B, 0x000D, 0x000C, 0x0009, 0x0007, 0x0004, 0x0001, 0x001E, 0x0015, 0x000A, 0x003F, 0x0038, 0x0009, 0x002D, 0x00E6, 0x01CF, 0x01C8, 0x0725, }; -static const uint16_t bitalloc_33_codes_g[33] = -{ + +static const uint16_t bitalloc_33_codes_g[33] = { 0x0284, 0x0042, 0x0140, 0x0143, 0x003E, 0x00BE, 0x0011, 0x0051, 0x0009, 0x0029, 0x0005, 0x0015, 0x0000, 0x0008, 0x000E, 0x0002, 0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0016, 0x0006, 0x002E, 0x000E, 0x005E, 0x001E, 0x00BF, 0x003F, 0x0020, 0x0141, 0x0043, 0x0285, }; -static const uint8_t bitalloc_33_bits_a[33] = -{ + +static const uint8_t bitalloc_33_bits_a[33] = { 13, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 13, }; -static const uint8_t bitalloc_33_bits_b[33] = -{ + +static const uint8_t bitalloc_33_bits_b[33] = { 10, 9, 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 10, }; -static const uint8_t bitalloc_33_bits_c[33] = -{ - 9, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, - 9, + +static const uint8_t bitalloc_33_bits_c[33] = { + 9, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, + 9, }; -static const uint8_t bitalloc_33_bits_d[33] = -{ + +static const uint8_t bitalloc_33_bits_d[33] = { 14, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 5, 4, 4, 3, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 14, }; -static const uint8_t bitalloc_33_bits_e[33] = -{ - 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 5, 5, 5, 4, 3, - 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, - 9, + +static const uint8_t bitalloc_33_bits_e[33] = { + 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 5, 5, 5, 4, 3, + 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, + 9, }; -static const uint8_t bitalloc_33_bits_f[33] = -{ + +static const uint8_t bitalloc_33_bits_f[33] = { 11, 10, 9, 8, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, 11, }; -static const uint8_t bitalloc_33_bits_g[33] = -{ + +static const uint8_t bitalloc_33_bits_g[33] = { 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, }; -static const uint16_t bitalloc_65_codes_a[65] = -{ +static const uint16_t bitalloc_65_codes_a[65] = { 0x9E5C, 0x9E5E, 0x4F2C, 0x2794, 0x13C4, 0x1E44, 0x09E3, 0x0F23, 0x04F3, 0x0792, 0x027E, 0x03CE, 0x013D, 0x01E5, 0x009C, 0x00CC, 0x0040, 0x0058, 0x0067, 0x001E, 0x0021, 0x002D, 0x003D, 0x0007, @@ -665,8 +628,8 @@ static const uint16_t bitalloc_65_codes_a[65] = 0x0790, 0x04F0, 0x09E4, 0x1E45, 0x13C5, 0x2795, 0x4F2D, 0x9E5F, 0x9E5D, }; -static const uint16_t bitalloc_65_codes_b[65] = -{ + +static const uint16_t bitalloc_65_codes_b[65] = { 0x0A8C, 0x0547, 0x01B5, 0x0008, 0x00DB, 0x0152, 0x0005, 0x000B, 0x008E, 0x00AE, 0x00E4, 0x0003, 0x0037, 0x0039, 0x0055, 0x006C, 0x0073, 0x0003, 0x0015, 0x001D, 0x0028, 0x0030, 0x0037, 0x003E, @@ -677,8 +640,8 @@ static const uint16_t bitalloc_65_codes_b[65] = 0x008F, 0x006C, 0x000A, 0x0153, 0x0150, 0x0009, 0x02A2, 0x01B4, 0x0A8D, }; -static const uint16_t bitalloc_65_codes_c[65] = -{ + +static const uint16_t bitalloc_65_codes_c[65] = { 0x045C, 0x022F, 0x03F5, 0x01BC, 0x01FB, 0x0059, 0x00D0, 0x00DF, 0x000A, 0x002D, 0x002F, 0x0052, 0x0069, 0x0078, 0x007F, 0x000A, 0x0010, 0x001C, 0x0023, 0x002A, 0x0035, 0x003A, 0x003D, 0x0000, @@ -689,8 +652,8 @@ static const uint16_t bitalloc_65_codes_c[65] = 0x000B, 0x00FC, 0x00D1, 0x008A, 0x0058, 0x01BD, 0x0116, 0x03F4, 0x045D, }; -static const uint16_t bitalloc_65_codes_d[65] = -{ + +static const uint16_t bitalloc_65_codes_d[65] = { 0x70B0, 0x70B2, 0x70B4, 0x2852, 0x385B, 0x142E, 0x1C2E, 0x0A15, 0x0E14, 0x0214, 0x0704, 0x0104, 0x010B, 0x0383, 0x0083, 0x0143, 0x01C3, 0x0043, 0x00A2, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012, @@ -701,8 +664,8 @@ static const uint16_t bitalloc_65_codes_d[65] = 0x0E15, 0x0A16, 0x1C2F, 0x142F, 0x1428, 0x2853, 0x70B5, 0x70B3, 0x70B1, }; -static const uint16_t bitalloc_65_codes_e[65] = -{ + +static const uint16_t bitalloc_65_codes_e[65] = { 0x032C, 0x0332, 0x0378, 0x037E, 0x008C, 0x014A, 0x0188, 0x0197, 0x019E, 0x01BD, 0x0044, 0x0047, 0x00AA, 0x00C5, 0x00CD, 0x00DC, 0x001C, 0x002C, 0x0053, 0x0063, 0x0068, 0x0008, 0x000F, 0x0017, @@ -713,8 +676,8 @@ static const uint16_t bitalloc_65_codes_e[65] = 0x019F, 0x0198, 0x0189, 0x014B, 0x008D, 0x037F, 0x0379, 0x0333, 0x032D, }; -static const uint16_t bitalloc_65_codes_f[65] = -{ + +static const uint16_t bitalloc_65_codes_f[65] = { 0x0FE0, 0x0FE2, 0x0FE8, 0x0FEA, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2, 0x0FF4, 0x2FF2, 0x07F2, 0x07FB, 0x03F6, 0x0BFA, 0x0BFD, 0x01FF, 0x05FF, 0x02FC, 0x007C, 0x017C, 0x003C, 0x00BC, 0x001C, 0x005C, @@ -725,8 +688,8 @@ static const uint16_t bitalloc_65_codes_f[65] = 0x0FF5, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x0FEB, 0x0FE9, 0x0FE3, 0x0FE1, }; -static const uint16_t bitalloc_65_codes_g[65] = -{ + +static const uint16_t bitalloc_65_codes_g[65] = { 0x010C, 0x038A, 0x0608, 0x0786, 0x0084, 0x0087, 0x0302, 0x0305, 0x0040, 0x00E0, 0x00E3, 0x0183, 0x001E, 0x005E, 0x009E, 0x00DE, 0x00F1, 0x0011, 0x0039, 0x0061, 0x0079, 0x0009, 0x001D, 0x0031, @@ -737,56 +700,56 @@ static const uint16_t bitalloc_65_codes_g[65] = 0x0041, 0x03C2, 0x0303, 0x01C4, 0x0085, 0x0787, 0x0609, 0x038B, 0x010D, }; -static const uint8_t bitalloc_65_bits_a[65] = -{ + +static const uint8_t bitalloc_65_bits_a[65] = { 16, 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 13, 13, 14, 15, 16, 16, }; -static const uint8_t bitalloc_65_bits_b[65] = -{ + +static const uint8_t bitalloc_65_bits_b[65] = { 12, 11, 10, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 10, 10, 12, }; -static const uint8_t bitalloc_65_bits_c[65] = -{ + +static const uint8_t bitalloc_65_bits_c[65] = { 11, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 11, }; -static const uint8_t bitalloc_65_bits_d[65] = -{ + +static const uint8_t bitalloc_65_bits_d[65] = { 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 15, 15, 15, }; -static const uint8_t bitalloc_65_bits_e[65] = -{ + +static const uint8_t bitalloc_65_bits_e[65] = { 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, }; -static const uint8_t bitalloc_65_bits_f[65] = -{ + +static const uint8_t bitalloc_65_bits_f[65] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, }; -static const uint8_t bitalloc_65_bits_g[65] = -{ + +static const uint8_t bitalloc_65_bits_g[65] = { 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, @@ -794,8 +757,7 @@ static const uint8_t bitalloc_65_bits_g[65] = 11, }; -static const uint16_t bitalloc_129_codes_a[129] = -{ +static const uint16_t bitalloc_129_codes_a[129] = { 0x0660, 0x0666, 0x06EC, 0x0722, 0x0760, 0x076E, 0x004C, 0x004E, 0x00F4, 0x010A, 0x0148, 0x0156, 0x01D4, 0x01F2, 0x0331, 0x0370, 0x0377, 0x0396, 0x03B1, 0x0024, 0x0064, 0x007B, 0x008A, 0x00A5, @@ -814,8 +776,8 @@ static const uint16_t bitalloc_129_codes_a[129] = 0x00F5, 0x004F, 0x004D, 0x076F, 0x0761, 0x0723, 0x06ED, 0x0667, 0x0661, }; -static const uint16_t bitalloc_129_codes_b[129] = -{ + +static const uint16_t bitalloc_129_codes_b[129] = { 0x29DC, 0x14EF, 0x0455, 0x0E9C, 0x022B, 0x0489, 0x0740, 0x074F, 0x0172, 0x0245, 0x0247, 0x030A, 0x03A1, 0x001C, 0x008B, 0x00D6, 0x010C, 0x0148, 0x014F, 0x0186, 0x01D1, 0x0008, 0x000F, 0x0046, @@ -834,8 +796,8 @@ static const uint16_t bitalloc_129_codes_b[129] = 0x0173, 0x0114, 0x0741, 0x053A, 0x0488, 0x0E9D, 0x0A76, 0x0454, 0x29DD, }; -static const uint16_t bitalloc_129_codes_c[129] = -{ + +static const uint16_t bitalloc_129_codes_c[129] = { 0x0E5C, 0x072F, 0x001D, 0x0724, 0x000F, 0x010D, 0x0324, 0x0393, 0x03E9, 0x0080, 0x0087, 0x00FA, 0x0164, 0x0193, 0x01DE, 0x01F5, 0x0010, 0x002A, 0x0041, 0x0064, 0x0073, 0x008E, 0x00A4, 0x00B3, @@ -854,8 +816,8 @@ static const uint16_t bitalloc_129_codes_c[129] = 0x0006, 0x03E8, 0x0325, 0x01CA, 0x010C, 0x0725, 0x0396, 0x001C, 0x0E5D, }; -static const uint16_t bitalloc_129_codes_d[129] = -{ + +static const uint16_t bitalloc_129_codes_d[129] = { 0xA598, 0xA59A, 0xA59C, 0xA59E, 0xC598, 0xE586, 0x3ACC, 0x52CA, 0x62CD, 0x0D48, 0x1D67, 0x2978, 0x3167, 0x3966, 0x06A5, 0x0EBC, 0x14BD, 0x1CB1, 0x0350, 0x0353, 0x075F, 0x0A5F, 0x0C5E, 0x0E5E, @@ -874,8 +836,8 @@ static const uint16_t bitalloc_129_codes_d[129] = 0x72C2, 0x52CB, 0x3ACD, 0xE587, 0xC599, 0xA59F, 0xA59D, 0xA59B, 0xA599, }; -static const uint16_t bitalloc_129_codes_e[129] = -{ + +static const uint16_t bitalloc_129_codes_e[129] = { 0xA13C, 0xC720, 0xA13F, 0xA13E, 0xA13D, 0xE722, 0x5090, 0x6393, 0x7392, 0x2849, 0x31CE, 0x39CE, 0x1425, 0x18E5, 0x1CE5, 0x0844, 0x0A1C, 0x0C7C, 0x036C, 0x0423, 0x050F, 0x063F, 0x01B7, 0x0216, @@ -894,8 +856,8 @@ static const uint16_t bitalloc_129_codes_e[129] = 0x7393, 0x7390, 0x5091, 0xE723, 0xC724, 0xC725, 0xC722, 0xC723, 0xC721, }; -static const uint16_t bitalloc_129_codes_f[129] = -{ + +static const uint16_t bitalloc_129_codes_f[129] = { 0x762C, 0x3B17, 0x1555, 0x0608, 0x0AAB, 0x0FF2, 0x0305, 0x0307, 0x0763, 0x0046, 0x010C, 0x01BC, 0x02AB, 0x03B6, 0x03FD, 0x0080, 0x0087, 0x00DF, 0x0156, 0x01D9, 0x01F8, 0x01FF, 0x002A, 0x0041, @@ -914,8 +876,8 @@ static const uint16_t bitalloc_129_codes_f[129] = 0x07F8, 0x0554, 0x0306, 0x0FF3, 0x0EC4, 0x0609, 0x1D8A, 0x1554, 0x762D, }; -static const uint16_t bitalloc_129_codes_g[129] = -{ + +static const uint16_t bitalloc_129_codes_g[129] = { 0x1E20, 0x1E5E, 0x031C, 0x051A, 0x0718, 0x0916, 0x0B14, 0x0D12, 0x0F11, 0x0090, 0x018F, 0x028E, 0x038D, 0x048C, 0x058B, 0x068A, 0x0789, 0x0049, 0x00C8, 0x0148, 0x01C7, 0x0247, 0x02C6, 0x0346, @@ -934,8 +896,8 @@ static const uint16_t bitalloc_129_codes_g[129] = 0x0F2E, 0x0D13, 0x0B15, 0x0917, 0x0719, 0x051B, 0x031D, 0x1E5F, 0x1E21, }; -static const uint8_t bitalloc_129_bits_a[129] = -{ + +static const uint8_t bitalloc_129_bits_a[129] = { 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, @@ -946,8 +908,8 @@ static const uint8_t bitalloc_129_bits_a[129] = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, }; -static const uint8_t bitalloc_129_bits_b[129] = -{ + +static const uint8_t bitalloc_129_bits_b[129] = { 14, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, @@ -958,8 +920,8 @@ static const uint8_t bitalloc_129_bits_b[129] = 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 14, }; -static const uint8_t bitalloc_129_bits_c[129] = -{ + +static const uint8_t bitalloc_129_bits_c[129] = { 13, 12, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, @@ -970,8 +932,8 @@ static const uint8_t bitalloc_129_bits_c[129] = 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 13, }; -static const uint8_t bitalloc_129_bits_d[129] = -{ + +static const uint8_t bitalloc_129_bits_d[129] = { 16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, @@ -982,8 +944,8 @@ static const uint8_t bitalloc_129_bits_d[129] = 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 16, }; -static const uint8_t bitalloc_129_bits_e[129] = -{ + +static const uint8_t bitalloc_129_bits_e[129] = { 16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, @@ -994,8 +956,8 @@ static const uint8_t bitalloc_129_bits_e[129] = 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 16, }; -static const uint8_t bitalloc_129_bits_f[129] = -{ + +static const uint8_t bitalloc_129_bits_f[129] = { 15, 14, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, @@ -1006,8 +968,8 @@ static const uint8_t bitalloc_129_bits_f[129] = 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 15, }; -static const uint8_t bitalloc_129_bits_g[129] = -{ + +static const uint8_t bitalloc_129_bits_g[129] = { 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, @@ -1019,10 +981,13 @@ static const uint8_t bitalloc_129_bits_g[129] = 13, }; -static const uint8_t bitalloc_sizes[10] = { 3, 5, 7, 9, 13, 17, 25, 33, 65, 129 }; +static const uint8_t bitalloc_sizes[10] = { + 3, 5, 7, 9, 13, 17, 25, 33, 65, 129 +}; -static const int8_t bitalloc_offsets[10] = - { -1, -2, -3, -4, -6, -8, -12, -16, -32, -64 }; +static const int8_t bitalloc_offsets[10] = { + -1, -2, -3, -4, -6, -8, -12, -16, -32, -64 +}; static const uint8_t bitalloc_maxbits[10][7] = { { 2 }, @@ -1037,40 +1002,40 @@ static const uint8_t bitalloc_maxbits[10][7] = { { 9, 9, 9, 9, 9, 9, 9 } }; -static const uint16_t* const bitalloc_codes[10][8] = { - { bitalloc_3_codes, NULL }, - { bitalloc_5_codes_a, bitalloc_5_codes_b, bitalloc_5_codes_c, NULL }, - { bitalloc_7_codes_a, bitalloc_7_codes_b, bitalloc_7_codes_c, NULL }, - { bitalloc_9_codes_a, bitalloc_9_codes_b, bitalloc_9_codes_c, NULL }, - { bitalloc_13_codes_a, bitalloc_13_codes_b, bitalloc_13_codes_c, NULL }, - { bitalloc_17_codes_a, bitalloc_17_codes_b, bitalloc_17_codes_c, bitalloc_17_codes_d, - bitalloc_17_codes_e, bitalloc_17_codes_f, bitalloc_17_codes_g, NULL }, - { bitalloc_25_codes_a, bitalloc_25_codes_b, bitalloc_25_codes_c, bitalloc_25_codes_d, - bitalloc_25_codes_e, bitalloc_25_codes_f, bitalloc_25_codes_g, NULL }, - { bitalloc_33_codes_a, bitalloc_33_codes_b, bitalloc_33_codes_c, bitalloc_33_codes_d, - bitalloc_33_codes_e, bitalloc_33_codes_f, bitalloc_33_codes_g, NULL }, - { bitalloc_65_codes_a, bitalloc_65_codes_b, bitalloc_65_codes_c, bitalloc_65_codes_d, - bitalloc_65_codes_e, bitalloc_65_codes_f, bitalloc_65_codes_g, NULL }, - { bitalloc_129_codes_a, bitalloc_129_codes_b, bitalloc_129_codes_c, bitalloc_129_codes_d, - bitalloc_129_codes_e, bitalloc_129_codes_f, bitalloc_129_codes_g, NULL } -}; - -static const uint8_t* const bitalloc_bits[10][8] = { - { bitalloc_3_bits, NULL }, - { bitalloc_5_bits_a, bitalloc_5_bits_b, bitalloc_5_bits_c, NULL }, - { bitalloc_7_bits_a, bitalloc_7_bits_b, bitalloc_7_bits_c, NULL }, - { bitalloc_9_bits_a, bitalloc_9_bits_b, bitalloc_9_bits_c, NULL }, - { bitalloc_13_bits_a, bitalloc_13_bits_b, bitalloc_13_bits_c, NULL }, - { bitalloc_17_bits_a, bitalloc_17_bits_b, bitalloc_17_bits_c, bitalloc_17_bits_d, - bitalloc_17_bits_e, bitalloc_17_bits_f, bitalloc_17_bits_g, NULL }, - { bitalloc_25_bits_a, bitalloc_25_bits_b, bitalloc_25_bits_c, bitalloc_25_bits_d, - bitalloc_25_bits_e, bitalloc_25_bits_f, bitalloc_25_bits_g, NULL }, - { bitalloc_33_bits_a, bitalloc_33_bits_b, bitalloc_33_bits_c, bitalloc_33_bits_d, - bitalloc_33_bits_e, bitalloc_33_bits_f, bitalloc_33_bits_g, NULL }, - { bitalloc_65_bits_a, bitalloc_65_bits_b, bitalloc_65_bits_c, bitalloc_65_bits_d, - bitalloc_65_bits_e, bitalloc_65_bits_f, bitalloc_65_bits_g, NULL }, - { bitalloc_129_bits_a, bitalloc_129_bits_b, bitalloc_129_bits_c, bitalloc_129_bits_d, - bitalloc_129_bits_e, bitalloc_129_bits_f, bitalloc_129_bits_g, NULL } +static const uint16_t *const bitalloc_codes[10][8] = { + { bitalloc_3_codes, NULL }, + { bitalloc_5_codes_a, bitalloc_5_codes_b, bitalloc_5_codes_c, NULL }, + { bitalloc_7_codes_a, bitalloc_7_codes_b, bitalloc_7_codes_c, NULL }, + { bitalloc_9_codes_a, bitalloc_9_codes_b, bitalloc_9_codes_c, NULL }, + { bitalloc_13_codes_a, bitalloc_13_codes_b, bitalloc_13_codes_c, NULL }, + { bitalloc_17_codes_a, bitalloc_17_codes_b, bitalloc_17_codes_c, bitalloc_17_codes_d, + bitalloc_17_codes_e, bitalloc_17_codes_f, bitalloc_17_codes_g, NULL }, + { bitalloc_25_codes_a, bitalloc_25_codes_b, bitalloc_25_codes_c, bitalloc_25_codes_d, + bitalloc_25_codes_e, bitalloc_25_codes_f, bitalloc_25_codes_g, NULL }, + { bitalloc_33_codes_a, bitalloc_33_codes_b, bitalloc_33_codes_c, bitalloc_33_codes_d, + bitalloc_33_codes_e, bitalloc_33_codes_f, bitalloc_33_codes_g, NULL }, + { bitalloc_65_codes_a, bitalloc_65_codes_b, bitalloc_65_codes_c, bitalloc_65_codes_d, + bitalloc_65_codes_e, bitalloc_65_codes_f, bitalloc_65_codes_g, NULL }, + { bitalloc_129_codes_a, bitalloc_129_codes_b, bitalloc_129_codes_c, bitalloc_129_codes_d, + bitalloc_129_codes_e, bitalloc_129_codes_f, bitalloc_129_codes_g, NULL } +}; + +static const uint8_t *const bitalloc_bits[10][8] = { + { bitalloc_3_bits, NULL }, + { bitalloc_5_bits_a, bitalloc_5_bits_b, bitalloc_5_bits_c, NULL }, + { bitalloc_7_bits_a, bitalloc_7_bits_b, bitalloc_7_bits_c, NULL }, + { bitalloc_9_bits_a, bitalloc_9_bits_b, bitalloc_9_bits_c, NULL }, + { bitalloc_13_bits_a, bitalloc_13_bits_b, bitalloc_13_bits_c, NULL }, + { bitalloc_17_bits_a, bitalloc_17_bits_b, bitalloc_17_bits_c, bitalloc_17_bits_d, + bitalloc_17_bits_e, bitalloc_17_bits_f, bitalloc_17_bits_g, NULL }, + { bitalloc_25_bits_a, bitalloc_25_bits_b, bitalloc_25_bits_c, bitalloc_25_bits_d, + bitalloc_25_bits_e, bitalloc_25_bits_f, bitalloc_25_bits_g, NULL }, + { bitalloc_33_bits_a, bitalloc_33_bits_b, bitalloc_33_bits_c, bitalloc_33_bits_d, + bitalloc_33_bits_e, bitalloc_33_bits_f, bitalloc_33_bits_g, NULL }, + { bitalloc_65_bits_a, bitalloc_65_bits_b, bitalloc_65_bits_c, bitalloc_65_bits_d, + bitalloc_65_bits_e, bitalloc_65_bits_f, bitalloc_65_bits_g, NULL }, + { bitalloc_129_bits_a, bitalloc_129_bits_b, bitalloc_129_bits_c, bitalloc_129_bits_d, + bitalloc_129_bits_e, bitalloc_129_bits_f, bitalloc_129_bits_g, NULL } }; #endif /* AVCODEC_DCAHUFF_H */ diff --git a/libavcodec/dcamath.h b/libavcodec/dcamath.h new file mode 100644 index 0000000..e21eb07 --- /dev/null +++ b/libavcodec/dcamath.h @@ -0,0 +1,42 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" + + +// clip a signed integer into the (-2^23), (2^23-1) range +static inline int dca_clip23(int a) +{ + return av_clip_intp2(a, 23); +} + +static inline int32_t dca_norm(int64_t a, int bits) +{ + if (bits > 0) + return (int32_t)((a + (INT64_C(1) << (bits - 1))) >> bits); + else + return (int32_t)a; +} + +static inline int64_t dca_round(int64_t a, int bits) +{ + if (bits > 0) + return (a + (INT64_C(1) << (bits - 1))) & ~((INT64_C(1) << bits) - 1); + else + return a; +} diff --git a/libavcodec/dct.c b/libavcodec/dct.c index 4dbbff8..180477e 100644 --- a/libavcodec/dct.c +++ b/libavcodec/dct.c @@ -191,6 +191,8 @@ av_cold int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType inverse) s->costab = ff_cos_tabs[nbits + 2]; s->csc2 = av_malloc(n / 2 * sizeof(FFTSample)); + if (!s->csc2) + return AVERROR(ENOMEM); if (ff_rdft_init(&s->rdft, nbits, inverse == DCT_III) < 0) { av_free(s->csc2); diff --git a/libavcodec/dct.h b/libavcodec/dct.h index 3fd4e27..4a31f54 100644 --- a/libavcodec/dct.h +++ b/libavcodec/dct.h @@ -59,5 +59,7 @@ void ff_fdct248_islow_8(int16_t *data); void ff_fdct248_islow_10(int16_t *data); void ff_j_rev_dct(int16_t *data); +void ff_jref_idct_put(uint8_t *dest, int line_size, int16_t *block); +void ff_jref_idct_add(uint8_t *dest, int line_size, int16_t *block); #endif /* AVCODEC_DCT_H */ diff --git a/libavcodec/dct32.h b/libavcodec/dct32.h index 110338d..8bf6880 100644 --- a/libavcodec/dct32.h +++ b/libavcodec/dct32.h @@ -22,4 +22,4 @@ void ff_dct32_float(float *dst, const float *src); void ff_dct32_fixed(int *dst, const int *src); -#endif +#endif /* AVCODEC_DCT32_H */ diff --git a/libavcodec/dds.c b/libavcodec/dds.c new file mode 100644 index 0000000..91e0c24 --- /dev/null +++ b/libavcodec/dds.c @@ -0,0 +1,716 @@ +/* + * DirectDraw Surface image decoder + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * DDS decoder + * + * https://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx + */ + +#include + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "texturedsp.h" +#include "thread.h" + +#define DDPF_FOURCC (1 << 2) +#define DDPF_PALETTE (1 << 5) +#define DDPF_NORMALMAP (1 << 31) + +enum DDSPostProc { + DDS_NONE = 0, + DDS_ALPHA_EXP, + DDS_NORMAL_MAP, + DDS_RAW_YCOCG, + DDS_SWIZZLE_A2XY, + DDS_SWIZZLE_RBXG, + DDS_SWIZZLE_RGXB, + DDS_SWIZZLE_RXBG, + DDS_SWIZZLE_RXGB, + DDS_SWIZZLE_XGBR, + DDS_SWIZZLE_XRBG, + DDS_SWIZZLE_XGXR, +}; + +enum DDSDXGIFormat { + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, +}; + +typedef struct DDSContext { + TextureDSPContext texdsp; + GetByteContext gbc; + + int compressed; + int paletted; + enum DDSPostProc postproc; + + const uint8_t *tex_data; // Compressed texture + int tex_ratio; // Compression ratio + int slice_count; // Number of slices for threaded operations + + /* Pointer to the selected compress or decompress function. */ + int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); +} DDSContext; + +static int parse_pixel_format(AVCodecContext *avctx) +{ + DDSContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + char buf[32]; + uint32_t flags, fourcc, gimp_tag; + enum DDSDXGIFormat dxgi; + int size, bpp, r, g, b, a; + int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array; + + /* Alternative DDS implementations use reserved1 as custom header. */ + bytestream2_skip(gbc, 4 * 3); + gimp_tag = bytestream2_get_le32(gbc); + alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P'); + ycocg_classic = gimp_tag == MKTAG('Y', 'C', 'G', '1'); + ycocg_scaled = gimp_tag == MKTAG('Y', 'C', 'G', '2'); + bytestream2_skip(gbc, 4 * 7); + + /* Now the real DDPF starts. */ + size = bytestream2_get_le32(gbc); + if (size != 32) { + av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size); + return AVERROR_INVALIDDATA; + } + flags = bytestream2_get_le32(gbc); + ctx->compressed = flags & DDPF_FOURCC; + ctx->paletted = flags & DDPF_PALETTE; + normal_map = flags & DDPF_NORMALMAP; + fourcc = bytestream2_get_le32(gbc); + + if (ctx->compressed && ctx->paletted) { + av_log(avctx, AV_LOG_WARNING, + "Disabling invalid palette flag for compressed dds.\n"); + ctx->paletted = 0; + } + + bpp = bytestream2_get_le32(gbc); // rgbbitcount + r = bytestream2_get_le32(gbc); // rbitmask + g = bytestream2_get_le32(gbc); // gbitmask + b = bytestream2_get_le32(gbc); // bbitmask + a = bytestream2_get_le32(gbc); // abitmask + + bytestream2_skip(gbc, 4); // caps + bytestream2_skip(gbc, 4); // caps2 + bytestream2_skip(gbc, 4); // caps3 + bytestream2_skip(gbc, 4); // caps4 + bytestream2_skip(gbc, 4); // reserved2 + + av_get_codec_tag_string(buf, sizeof(buf), fourcc); + av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d " + "r 0x%x g 0x%x b 0x%x a 0x%x\n", buf, bpp, r, g, b, a); + if (gimp_tag) { + av_get_codec_tag_string(buf, sizeof(buf), gimp_tag); + av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", buf); + } + + if (ctx->compressed) + avctx->pix_fmt = AV_PIX_FMT_RGBA; + + if (ctx->compressed) { + switch (fourcc) { + case MKTAG('D', 'X', 'T', '1'): + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.dxt1a_block; + break; + case MKTAG('D', 'X', 'T', '2'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt2_block; + break; + case MKTAG('D', 'X', 'T', '3'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt3_block; + break; + case MKTAG('D', 'X', 'T', '4'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt4_block; + break; + case MKTAG('D', 'X', 'T', '5'): + ctx->tex_ratio = 16; + if (ycocg_scaled) + ctx->tex_funct = ctx->texdsp.dxt5ys_block; + else if (ycocg_classic) + ctx->tex_funct = ctx->texdsp.dxt5y_block; + else + ctx->tex_funct = ctx->texdsp.dxt5_block; + break; + case MKTAG('R', 'X', 'G', 'B'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt5_block; + /* This format may be considered as a normal map, + * but it is handled differently in a separate postproc. */ + ctx->postproc = DDS_SWIZZLE_RXGB; + normal_map = 0; + break; + case MKTAG('A', 'T', 'I', '1'): + case MKTAG('B', 'C', '4', 'U'): + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.rgtc1u_block; + break; + case MKTAG('B', 'C', '4', 'S'): + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.rgtc1s_block; + break; + case MKTAG('A', 'T', 'I', '2'): + /* RGT2 variant with swapped R and G (3Dc)*/ + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxn3dc_block; + break; + case MKTAG('B', 'C', '5', 'U'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.rgtc2u_block; + break; + case MKTAG('B', 'C', '5', 'S'): + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.rgtc2s_block; + break; + case MKTAG('U', 'Y', 'V', 'Y'): + ctx->compressed = 0; + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + break; + case MKTAG('Y', 'U', 'Y', '2'): + ctx->compressed = 0; + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + break; + case MKTAG('P', '8', ' ', ' '): + /* ATI Palette8, same as normal palette */ + ctx->compressed = 0; + ctx->paletted = 1; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + case MKTAG('G', '1', ' ', ' '): + ctx->compressed = 0; + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + break; + case MKTAG('D', 'X', '1', '0'): + /* DirectX 10 extra header */ + dxgi = bytestream2_get_le32(gbc); + bytestream2_skip(gbc, 4); // resourceDimension + bytestream2_skip(gbc, 4); // miscFlag + array = bytestream2_get_le32(gbc); + bytestream2_skip(gbc, 4); // miscFlag2 + + if (array != 0) + av_log(avctx, AV_LOG_VERBOSE, + "Found array of size %d (ignored).\n", array); + + /* Only BC[1-5] are actually compressed. */ + ctx->compressed = (dxgi >= 70) && (dxgi <= 84); + + av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi); + switch (dxgi) { + /* RGB types. */ + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + avctx->pix_fmt = AV_PIX_FMT_BGRA64; + break; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM: + avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM: + avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque + break; + case DXGI_FORMAT_B5G6R5_UNORM: + avctx->pix_fmt = AV_PIX_FMT_RGB565LE; + break; + /* Texture types. */ + case DXGI_FORMAT_BC1_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.dxt1a_block; + break; + case DXGI_FORMAT_BC2_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt3_block; + break; + case DXGI_FORMAT_BC3_UNORM_SRGB: + avctx->colorspace = AVCOL_SPC_RGB; + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.dxt5_block; + break; + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.rgtc1u_block; + break; + case DXGI_FORMAT_BC4_SNORM: + ctx->tex_ratio = 8; + ctx->tex_funct = ctx->texdsp.rgtc1s_block; + break; + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.rgtc2u_block; + break; + case DXGI_FORMAT_BC5_SNORM: + ctx->tex_ratio = 16; + ctx->tex_funct = ctx->texdsp.rgtc2s_block; + break; + default: + av_log(avctx, AV_LOG_ERROR, + "Unsupported DXGI format %d.\n", dxgi); + return AVERROR_INVALIDDATA; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", buf); + return AVERROR_INVALIDDATA; + } + } else if (ctx->paletted) { + if (bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp); + return AVERROR_INVALIDDATA; + } + } else { + /* 8 bpp */ + if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0) + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff) + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + /* 16 bpp */ + else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00) + avctx->pix_fmt = AV_PIX_FMT_YA8; + else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0) + avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; + else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0) + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000) + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored + else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0) + avctx->pix_fmt = AV_PIX_FMT_RGB565LE; + /* 24 bpp */ + else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0) + avctx->pix_fmt = AV_PIX_FMT_BGR24; + /* 32 bpp */ + else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0) + avctx->pix_fmt = AV_PIX_FMT_BGRA; // opaque + else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0) + avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque + else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000) + avctx->pix_fmt = AV_PIX_FMT_BGRA; + else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000) + avctx->pix_fmt = AV_PIX_FMT_RGBA; + /* give up */ + else { + av_log(avctx, AV_LOG_ERROR, "Unknown pixel format " + "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a); + return AVERROR_INVALIDDATA; + } + } + + /* Set any remaining post-proc that should happen before frame is ready. */ + if (alpha_exponent) + ctx->postproc = DDS_ALPHA_EXP; + else if (normal_map) + ctx->postproc = DDS_NORMAL_MAP; + else if (ycocg_classic && !ctx->compressed) + ctx->postproc = DDS_RAW_YCOCG; + + /* ATI/NVidia variants sometimes add swizzling in bpp. */ + switch (bpp) { + case MKTAG('A', '2', 'X', 'Y'): + ctx->postproc = DDS_SWIZZLE_A2XY; + break; + case MKTAG('x', 'G', 'B', 'R'): + ctx->postproc = DDS_SWIZZLE_XGBR; + break; + case MKTAG('x', 'R', 'B', 'G'): + ctx->postproc = DDS_SWIZZLE_XRBG; + break; + case MKTAG('R', 'B', 'x', 'G'): + ctx->postproc = DDS_SWIZZLE_RBXG; + break; + case MKTAG('R', 'G', 'x', 'B'): + ctx->postproc = DDS_SWIZZLE_RGXB; + break; + case MKTAG('R', 'x', 'B', 'G'): + ctx->postproc = DDS_SWIZZLE_RXBG; + break; + case MKTAG('x', 'G', 'x', 'R'): + ctx->postproc = DDS_SWIZZLE_XGXR; + break; + case MKTAG('A', '2', 'D', '5'): + ctx->postproc = DDS_NORMAL_MAP; + break; + } + + return 0; +} + +static int decompress_texture_thread(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + DDSContext *ctx = avctx->priv_data; + AVFrame *frame = arg; + const uint8_t *d = ctx->tex_data; + int w_block = avctx->coded_width / TEXTURE_BLOCK_W; + int h_block = avctx->coded_height / TEXTURE_BLOCK_H; + int x, y; + int start_slice, end_slice; + int base_blocks_per_slice = h_block / ctx->slice_count; + int remainder_blocks = h_block % ctx->slice_count; + + /* When the frame height (in blocks) doesn't divide evenly between the + * number of slices, spread the remaining blocks evenly between the first + * operations */ + start_slice = slice * base_blocks_per_slice; + /* Add any extra blocks (one per slice) that have been added before this slice */ + start_slice += FFMIN(slice, remainder_blocks); + + end_slice = start_slice + base_blocks_per_slice; + /* Add an extra block if there are still remainder blocks to be accounted for */ + if (slice < remainder_blocks) + end_slice++; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_funct(p + x * 16, frame->linesize[0], + d + (off + x) * ctx->tex_ratio); + } + } + + return 0; +} + +static void do_swizzle(AVFrame *frame, int x, int y) +{ + int i; + for (i = 0; i < frame->linesize[0] * frame->height; i += 4) { + uint8_t *src = frame->data[0] + i; + FFSWAP(uint8_t, src[x], src[y]); + } +} + +static void run_postproc(AVCodecContext *avctx, AVFrame *frame) +{ + DDSContext *ctx = avctx->priv_data; + int i, x_off; + + switch (ctx->postproc) { + case DDS_ALPHA_EXP: + /* Alpha-exponential mode divides each channel by the maximum + * R, G or B value, and stores the multiplying factor in the + * alpha channel. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n"); + + for (i = 0; i < frame->linesize[0] * frame->height; i += 4) { + uint8_t *src = frame->data[0] + i; + int r = src[0]; + int g = src[1]; + int b = src[2]; + int a = src[3]; + + src[0] = r * a / 255; + src[1] = g * a / 255; + src[2] = b * a / 255; + src[3] = 255; + } + break; + case DDS_NORMAL_MAP: + /* Normal maps work in the XYZ color space and they encode + * X in R or in A, depending on the texture type, Y in G and + * derive Z with a square root of the distance. + * + * http://www.realtimecollisiondetection.net/blog/?p=28 */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n"); + + x_off = ctx->tex_ratio == 8 ? 0 : 3; + for (i = 0; i < frame->linesize[0] * frame->height; i += 4) { + uint8_t *src = frame->data[0] + i; + int x = src[x_off]; + int y = src[1]; + int z = 127; + + int d = (255 * 255 - x * x - y * y) / 2; + if (d > 0) + z = rint(sqrtf(d)); + + src[0] = x; + src[1] = y; + src[2] = z; + src[3] = 255; + } + break; + case DDS_RAW_YCOCG: + /* Data is Y-Co-Cg-A and not RGBA, but they are represented + * with the same masks in the DDPF header. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n"); + + for (i = 0; i < frame->linesize[0] * frame->height; i += 4) { + uint8_t *src = frame->data[0] + i; + int a = src[0]; + int cg = src[1] - 128; + int co = src[2] - 128; + int y = src[3]; + + src[0] = av_clip_uint8(y + co - cg); + src[1] = av_clip_uint8(y + cg); + src[2] = av_clip_uint8(y - co - cg); + src[3] = a; + } + break; + case DDS_SWIZZLE_A2XY: + /* Swap R and G, often used to restore a standard RGTC2. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n"); + do_swizzle(frame, 0, 1); + break; + case DDS_SWIZZLE_RBXG: + /* Swap G and A, then B and new A (G). */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n"); + do_swizzle(frame, 1, 3); + do_swizzle(frame, 2, 3); + break; + case DDS_SWIZZLE_RGXB: + /* Swap B and A. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n"); + do_swizzle(frame, 2, 3); + break; + case DDS_SWIZZLE_RXBG: + /* Swap G and A. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n"); + do_swizzle(frame, 1, 3); + break; + case DDS_SWIZZLE_RXGB: + /* Swap R and A (misleading name). */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n"); + do_swizzle(frame, 0, 3); + break; + case DDS_SWIZZLE_XGBR: + /* Swap B and A, then R and new A (B). */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n"); + do_swizzle(frame, 2, 3); + do_swizzle(frame, 0, 3); + break; + case DDS_SWIZZLE_XGXR: + /* Swap G and A, then R and new A (G), then new R (G) and new G (A). + * This variant does not store any B component. */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n"); + do_swizzle(frame, 1, 3); + do_swizzle(frame, 0, 3); + do_swizzle(frame, 0, 1); + break; + case DDS_SWIZZLE_XRBG: + /* Swap G and A, then R and new A (G). */ + av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n"); + do_swizzle(frame, 1, 3); + do_swizzle(frame, 0, 3); + break; + } +} + +static int dds_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + DDSContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + AVFrame *frame = data; + int mipmap; + int ret; + + ff_texturedsp_init(&ctx->texdsp); + bytestream2_init(gbc, avpkt->data, avpkt->size); + + if (bytestream2_get_bytes_left(gbc) < 128) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n", + bytestream2_get_bytes_left(gbc)); + return AVERROR_INVALIDDATA; + } + + if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') || + bytestream2_get_le32(gbc) != 124) { // header size + av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(gbc, 4); // flags + + avctx->height = bytestream2_get_le32(gbc); + avctx->width = bytestream2_get_le32(gbc); + ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + /* Since codec is based on 4x4 blocks, size is aligned to 4. */ + avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W); + avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H); + + bytestream2_skip(gbc, 4); // pitch + bytestream2_skip(gbc, 4); // depth + mipmap = bytestream2_get_le32(gbc); + if (mipmap != 0) + av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap); + + /* Extract pixel format information, considering additional elements + * in reserved1 and reserved2. */ + ret = parse_pixel_format(avctx); + if (ret < 0) + return ret; + + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + return ret; + + if (ctx->compressed) { + int size = (avctx->coded_height / TEXTURE_BLOCK_H) * + (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->tex_ratio; + ctx->slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / TEXTURE_BLOCK_H); + + if (bytestream2_get_bytes_left(gbc) < size) { + av_log(avctx, AV_LOG_ERROR, + "Compressed Buffer is too small (%d < %d).\n", + bytestream2_get_bytes_left(gbc), size); + return AVERROR_INVALIDDATA; + } + + /* Use the decompress function on the texture, one block per thread. */ + ctx->tex_data = gbc->buffer; + avctx->execute2(avctx, decompress_texture_thread, frame, NULL, ctx->slice_count); + } else { + int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0); + + if (ctx->paletted) { + int i; + uint32_t *p = (uint32_t*) frame->data[1]; + + /* Use the first 1024 bytes as palette, then copy the rest. */ + for (i = 0; i < 256; i++) { + uint32_t rgba = 0; + rgba |= bytestream2_get_byte(gbc) << 16; + rgba |= bytestream2_get_byte(gbc) << 8; + rgba |= bytestream2_get_byte(gbc) << 0; + rgba |= bytestream2_get_byte(gbc) << 24; + p[i] = rgba; + } + + frame->palette_has_changed = 1; + } + + if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) { + av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n", + bytestream2_get_bytes_left(gbc), frame->height * linesize); + return AVERROR_INVALIDDATA; + } + + av_image_copy_plane(frame->data[0], frame->linesize[0], + gbc->buffer, linesize, + linesize, frame->height); + } + + /* Run any post processing here if needed. */ + if (ctx->postproc != DDS_NONE) + run_postproc(avctx, frame); + + /* Frame is ready to be output. */ + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_dds_decoder = { + .name = "dds", + .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DDS, + .decode = dds_decode, + .priv_data_size = sizeof(DDSContext), + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE +}; diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 6fa4edc..8021193 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -404,5 +404,5 @@ AVCodec ff_dfa_decoder = { .init = dfa_decode_init, .close = dfa_decode_end, .decode = dfa_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dirac.c b/libavcodec/dirac.c index ed0ea9f..142af20 100644 --- a/libavcodec/dirac.c +++ b/libavcodec/dirac.c @@ -26,55 +26,78 @@ */ #include "libavutil/imgutils.h" -#include "dirac.h" + #include "avcodec.h" +#include "dirac.h" #include "golomb.h" #include "internal.h" #include "mpeg12data.h" +#if CONFIG_DIRAC_PARSE + +typedef struct dirac_source_params { + unsigned width; + unsigned height; + uint8_t chroma_format; ///< 0: 444 1: 422 2: 420 + + uint8_t interlaced; + uint8_t top_field_first; + + uint8_t frame_rate_index; ///< index into dirac_frame_rate[] + uint8_t aspect_ratio_index; ///< index into dirac_aspect_ratio[] + + uint16_t clean_width; + uint16_t clean_height; + uint16_t clean_left_offset; + uint16_t clean_right_offset; + + uint8_t pixel_range_index; ///< index into dirac_pixel_range_presets[] + uint8_t color_spec_index; ///< index into dirac_color_spec_presets[] +} dirac_source_params; + // defaults for source parameters static const dirac_source_params dirac_source_parameters_defaults[] = { - { 640, 480, 2, 0, 0, 1, 1, 640, 480, 0, 0, 1, 0 }, - { 176, 120, 2, 0, 0, 9, 2, 176, 120, 0, 0, 1, 1 }, - { 176, 144, 2, 0, 1, 10, 3, 176, 144, 0, 0, 1, 2 }, - { 352, 240, 2, 0, 0, 9, 2, 352, 240, 0, 0, 1, 1 }, - { 352, 288, 2, 0, 1, 10, 3, 352, 288, 0, 0, 1, 2 }, - { 704, 480, 2, 0, 0, 9, 2, 704, 480, 0, 0, 1, 1 }, - { 704, 576, 2, 0, 1, 10, 3, 704, 576, 0, 0, 1, 2 }, - { 720, 480, 1, 1, 0, 4, 2, 704, 480, 8, 0, 3, 1 }, - { 720, 576, 1, 1, 1, 3, 3, 704, 576, 8, 0, 3, 2 }, - - { 1280, 720, 1, 0, 1, 7, 1, 1280, 720, 0, 0, 3, 3 }, - { 1280, 720, 1, 0, 1, 6, 1, 1280, 720, 0, 0, 3, 3 }, - { 1920, 1080, 1, 1, 1, 4, 1, 1920, 1080, 0, 0, 3, 3 }, - { 1920, 1080, 1, 1, 1, 3, 1, 1920, 1080, 0, 0, 3, 3 }, - { 1920, 1080, 1, 0, 1, 7, 1, 1920, 1080, 0, 0, 3, 3 }, - { 1920, 1080, 1, 0, 1, 6, 1, 1920, 1080, 0, 0, 3, 3 }, - { 2048, 1080, 0, 0, 1, 2, 1, 2048, 1080, 0, 0, 4, 4 }, - { 4096, 2160, 0, 0, 1, 2, 1, 4096, 2160, 0, 0, 4, 4 }, - - { 3840, 2160, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, - { 3840, 2160, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, - { 7680, 4320, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, - { 7680, 4320, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, + { 640, 480, 2, 0, 0, 1, 1, 640, 480, 0, 0, 1, 0 }, + { 176, 120, 2, 0, 0, 9, 2, 176, 120, 0, 0, 1, 1 }, + { 176, 144, 2, 0, 1, 10, 3, 176, 144, 0, 0, 1, 2 }, + { 352, 240, 2, 0, 0, 9, 2, 352, 240, 0, 0, 1, 1 }, + { 352, 288, 2, 0, 1, 10, 3, 352, 288, 0, 0, 1, 2 }, + { 704, 480, 2, 0, 0, 9, 2, 704, 480, 0, 0, 1, 1 }, + { 704, 576, 2, 0, 1, 10, 3, 704, 576, 0, 0, 1, 2 }, + { 720, 480, 1, 1, 0, 4, 2, 704, 480, 8, 0, 3, 1 }, + { 720, 576, 1, 1, 1, 3, 3, 704, 576, 8, 0, 3, 2 }, + + { 1280, 720, 1, 0, 1, 7, 1, 1280, 720, 0, 0, 3, 3 }, + { 1280, 720, 1, 0, 1, 6, 1, 1280, 720, 0, 0, 3, 3 }, + { 1920, 1080, 1, 1, 1, 4, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 1, 1, 3, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 0, 1, 7, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 0, 1, 6, 1, 1920, 1080, 0, 0, 3, 3 }, + { 2048, 1080, 0, 0, 1, 2, 1, 2048, 1080, 0, 0, 4, 4 }, + { 4096, 2160, 0, 0, 1, 2, 1, 4096, 2160, 0, 0, 4, 4 }, + + { 3840, 2160, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, + { 3840, 2160, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, + { 7680, 4320, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, + { 7680, 4320, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, }; /* [DIRAC_STD] Table 10.4 - Available preset pixel aspect ratio values */ static const AVRational dirac_preset_aspect_ratios[] = { - {1, 1}, - {10, 11}, - {12, 11}, - {40, 33}, - {16, 11}, - {4, 3}, + { 1, 1 }, + { 10, 11 }, + { 12, 11 }, + { 40, 33 }, + { 16, 11 }, + { 4, 3 }, }; /* [DIRAC_STD] Values 9,10 of 10.3.5 Frame Rate. * Table 10.3 Available preset frame rate values */ static const AVRational dirac_frame_rate[] = { - {15000, 1001}, - {25, 2}, + { 15000, 1001 }, + { 25, 2 }, }; /* [DIRAC_STD] This should be equivalent to Table 10.5 Available signal @@ -83,10 +106,10 @@ static const struct { uint8_t bitdepth; enum AVColorRange color_range; } pixel_range_presets[] = { - {8, AVCOL_RANGE_JPEG}, - {8, AVCOL_RANGE_MPEG}, - {10, AVCOL_RANGE_MPEG}, - {12, AVCOL_RANGE_MPEG}, + { 8, AVCOL_RANGE_JPEG }, + { 8, AVCOL_RANGE_MPEG }, + { 10, AVCOL_RANGE_MPEG }, + { 12, AVCOL_RANGE_MPEG }, }; static const enum AVColorPrimaries dirac_primaries[] = { @@ -115,18 +138,18 @@ static const enum AVPixelFormat dirac_pix_fmt[2][3] = { /* [DIRAC_STD] 10.3 Parse Source Parameters. * source_parameters(base_video_format) */ -static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, - dirac_source_params *source) +static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb, + void *log_ctx) { - AVRational frame_rate = {0,0}; + AVRational frame_rate = { 0, 0 }; unsigned luma_depth = 8, luma_offset = 16; int idx; /* [DIRAC_STD] 10.3.2 Frame size. frame_size(video_params) */ /* [DIRAC_STD] custom_dimensions_flag */ if (get_bits1(gb)) { - source->width = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_WIDTH */ - source->height = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_HEIGHT */ + dsh->width = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] FRAME_WIDTH */ + dsh->height = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] FRAME_HEIGHT */ } /* [DIRAC_STD] 10.3.3 Chroma Sampling Format. @@ -134,10 +157,11 @@ static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, /* [DIRAC_STD] custom_chroma_format_flag */ if (get_bits1(gb)) /* [DIRAC_STD] CHROMA_FORMAT_INDEX */ - source->chroma_format = svq3_get_ue_golomb(gb); - if (source->chroma_format > 2) { - av_log(avctx, AV_LOG_ERROR, "Unknown chroma format %d\n", - source->chroma_format); + dsh->chroma_format = get_interleaved_ue_golomb(gb); + if (dsh->chroma_format > 2) { + if (log_ctx) + av_log(log_ctx, AV_LOG_ERROR, "Unknown chroma format %d\n", + dsh->chroma_format); return AVERROR_INVALIDDATA; } @@ -145,65 +169,64 @@ static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, /* [DIRAC_STD] custom_scan_format_flag */ if (get_bits1(gb)) /* [DIRAC_STD] SOURCE_SAMPLING */ - source->interlaced = svq3_get_ue_golomb(gb); - if (source->interlaced > 1) + dsh->interlaced = get_interleaved_ue_golomb(gb); + if (dsh->interlaced > 1) return AVERROR_INVALIDDATA; /* [DIRAC_STD] 10.3.5 Frame Rate. frame_rate(video_params) */ if (get_bits1(gb)) { /* [DIRAC_STD] custom_frame_rate_flag */ - source->frame_rate_index = svq3_get_ue_golomb(gb); + dsh->frame_rate_index = get_interleaved_ue_golomb(gb); - if (source->frame_rate_index > 10) + if (dsh->frame_rate_index > 10) return AVERROR_INVALIDDATA; - if (!source->frame_rate_index) { + if (!dsh->frame_rate_index) { /* [DIRAC_STD] FRAME_RATE_NUMER */ - frame_rate.num = svq3_get_ue_golomb(gb); + frame_rate.num = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] FRAME_RATE_DENOM */ - frame_rate.den = svq3_get_ue_golomb(gb); + frame_rate.den = get_interleaved_ue_golomb(gb); } } /* [DIRAC_STD] preset_frame_rate(video_params, index) */ - if (source->frame_rate_index > 0) { - if (source->frame_rate_index <= 8) - frame_rate = ff_mpeg12_frame_rate_tab[source->frame_rate_index]; + if (dsh->frame_rate_index > 0) { + if (dsh->frame_rate_index <= 8) + frame_rate = ff_mpeg12_frame_rate_tab[dsh->frame_rate_index]; else - /* [DIRAC_STD] Table 10.3 values 9-10 */ - frame_rate = dirac_frame_rate[source->frame_rate_index-9]; + /* [DIRAC_STD] Table 10.3 values 9-10 */ + frame_rate = dirac_frame_rate[dsh->frame_rate_index - 9]; } - av_reduce(&avctx->time_base.num, &avctx->time_base.den, - frame_rate.den, frame_rate.num, 1<<30); + dsh->framerate = frame_rate; /* [DIRAC_STD] 10.3.6 Pixel Aspect Ratio. * pixel_aspect_ratio(video_params) */ if (get_bits1(gb)) { /* [DIRAC_STD] custom_pixel_aspect_ratio_flag */ - /* [DIRAC_STD] index */ - source->aspect_ratio_index = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] index */ + dsh->aspect_ratio_index = get_interleaved_ue_golomb(gb); - if (source->aspect_ratio_index > 6) + if (dsh->aspect_ratio_index > 6) return AVERROR_INVALIDDATA; - if (!source->aspect_ratio_index) { - avctx->sample_aspect_ratio.num = svq3_get_ue_golomb(gb); - avctx->sample_aspect_ratio.den = svq3_get_ue_golomb(gb); + if (!dsh->aspect_ratio_index) { + dsh->sample_aspect_ratio.num = get_interleaved_ue_golomb(gb); + dsh->sample_aspect_ratio.den = get_interleaved_ue_golomb(gb); } } /* [DIRAC_STD] Take value from Table 10.4 Available preset pixel * aspect ratio values */ - if (source->aspect_ratio_index > 0) - avctx->sample_aspect_ratio = - dirac_preset_aspect_ratios[source->aspect_ratio_index-1]; + if (dsh->aspect_ratio_index > 0) + dsh->sample_aspect_ratio = + dirac_preset_aspect_ratios[dsh->aspect_ratio_index - 1]; /* [DIRAC_STD] 10.3.7 Clean area. clean_area(video_params) */ if (get_bits1(gb)) { /* [DIRAC_STD] custom_clean_area_flag */ /* [DIRAC_STD] CLEAN_WIDTH */ - source->clean_width = svq3_get_ue_golomb(gb); - /* [DIRAC_STD] CLEAN_HEIGHT */ - source->clean_height = svq3_get_ue_golomb(gb); - /* [DIRAC_STD] CLEAN_LEFT_OFFSET */ - source->clean_left_offset = svq3_get_ue_golomb(gb); + dsh->clean_width = get_interleaved_ue_golomb(gb); + /* [DIRAC_STD] CLEAN_HEIGHT */ + dsh->clean_height = get_interleaved_ue_golomb(gb); + /* [DIRAC_STD] CLEAN_LEFT_OFFSET */ + dsh->clean_left_offset = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] CLEAN_RIGHT_OFFSET */ - source->clean_right_offset = svq3_get_ue_golomb(gb); + dsh->clean_right_offset = get_interleaved_ue_golomb(gb); } /* [DIRAC_STD] 10.3.8 Signal range. signal_range(video_params) @@ -211,120 +234,160 @@ static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, * AVCOL_RANGE_MPEG/JPEG values */ if (get_bits1(gb)) { /* [DIRAC_STD] custom_signal_range_flag */ /* [DIRAC_STD] index */ - source->pixel_range_index = svq3_get_ue_golomb(gb); + dsh->pixel_range_index = get_interleaved_ue_golomb(gb); - if (source->pixel_range_index > 4) + if (dsh->pixel_range_index > 4) return AVERROR_INVALIDDATA; // This assumes either fullrange or MPEG levels only - if (!source->pixel_range_index) { - luma_offset = svq3_get_ue_golomb(gb); - luma_depth = av_log2(svq3_get_ue_golomb(gb))+1; - svq3_get_ue_golomb(gb); /* chroma offset */ - svq3_get_ue_golomb(gb); /* chroma excursion */ - avctx->color_range = luma_offset ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + if (!dsh->pixel_range_index) { + luma_offset = get_interleaved_ue_golomb(gb); + luma_depth = av_log2(get_interleaved_ue_golomb(gb)) + 1; + get_interleaved_ue_golomb(gb); /* chroma offset */ + get_interleaved_ue_golomb(gb); /* chroma excursion */ + dsh->color_range = luma_offset ? AVCOL_RANGE_MPEG + : AVCOL_RANGE_JPEG; } } /* [DIRAC_STD] Table 10.5 * Available signal range presets <--> pixel_range_presets */ - if (source->pixel_range_index > 0) { - idx = source->pixel_range_index-1; + if (dsh->pixel_range_index > 0) { + idx = dsh->pixel_range_index - 1; luma_depth = pixel_range_presets[idx].bitdepth; - avctx->color_range = pixel_range_presets[idx].color_range; + dsh->color_range = pixel_range_presets[idx].color_range; } - if (luma_depth > 8) - av_log(avctx, AV_LOG_WARNING, "Bitdepth greater than 8"); + if (luma_depth > 8 && log_ctx) + av_log(log_ctx, AV_LOG_WARNING, "Bitdepth greater than 8"); - avctx->pix_fmt = dirac_pix_fmt[!luma_offset][source->chroma_format]; + dsh->pix_fmt = dirac_pix_fmt[!luma_offset][dsh->chroma_format]; /* [DIRAC_STD] 10.3.9 Colour specification. colour_spec(video_params) */ if (get_bits1(gb)) { /* [DIRAC_STD] custom_colour_spec_flag */ - /* [DIRAC_STD] index */ - idx = source->color_spec_index = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] index */ + idx = dsh->color_spec_index = get_interleaved_ue_golomb(gb); - if (source->color_spec_index > 4) + if (dsh->color_spec_index > 4) return AVERROR_INVALIDDATA; - avctx->color_primaries = dirac_color_presets[idx].color_primaries; - avctx->colorspace = dirac_color_presets[idx].colorspace; - avctx->color_trc = dirac_color_presets[idx].color_trc; + dsh->color_primaries = dirac_color_presets[idx].color_primaries; + dsh->colorspace = dirac_color_presets[idx].colorspace; + dsh->color_trc = dirac_color_presets[idx].color_trc; - if (!source->color_spec_index) { + if (!dsh->color_spec_index) { /* [DIRAC_STD] 10.3.9.1 Colour primaries */ if (get_bits1(gb)) { - idx = svq3_get_ue_golomb(gb); + idx = get_interleaved_ue_golomb(gb); if (idx < 3) - avctx->color_primaries = dirac_primaries[idx]; + dsh->color_primaries = dirac_primaries[idx]; } /* [DIRAC_STD] 10.3.9.2 Colour matrix */ if (get_bits1(gb)) { - idx = svq3_get_ue_golomb(gb); + idx = get_interleaved_ue_golomb(gb); if (!idx) - avctx->colorspace = AVCOL_SPC_BT709; + dsh->colorspace = AVCOL_SPC_BT709; else if (idx == 1) - avctx->colorspace = AVCOL_SPC_BT470BG; + dsh->colorspace = AVCOL_SPC_BT470BG; } /* [DIRAC_STD] 10.3.9.3 Transfer function */ - if (get_bits1(gb) && !svq3_get_ue_golomb(gb)) - avctx->color_trc = AVCOL_TRC_BT709; + if (get_bits1(gb) && !get_interleaved_ue_golomb(gb)) + dsh->color_trc = AVCOL_TRC_BT709; } } else { - idx = source->color_spec_index; - avctx->color_primaries = dirac_color_presets[idx].color_primaries; - avctx->colorspace = dirac_color_presets[idx].colorspace; - avctx->color_trc = dirac_color_presets[idx].color_trc; + idx = dsh->color_spec_index; + dsh->color_primaries = dirac_color_presets[idx].color_primaries; + dsh->colorspace = dirac_color_presets[idx].colorspace; + dsh->color_trc = dirac_color_presets[idx].color_trc; } return 0; } /* [DIRAC_STD] 10. Sequence Header. sequence_header() */ -int avpriv_dirac_parse_sequence_header(AVCodecContext *avctx, GetBitContext *gb, - dirac_source_params *source) +int av_dirac_parse_sequence_header(AVDiracSeqHeader **pdsh, + const uint8_t *buf, size_t buf_size, + void *log_ctx) { + AVDiracSeqHeader *dsh; + GetBitContext gb; unsigned version_major; unsigned video_format, picture_coding_mode; int ret; + dsh = av_mallocz(sizeof(*dsh)); + if (!dsh) + return AVERROR(ENOMEM); + + ret = init_get_bits8(&gb, buf, buf_size); + if (ret < 0) + goto fail; + /* [DIRAC_SPEC] 10.1 Parse Parameters. parse_parameters() */ - version_major = svq3_get_ue_golomb(gb); - svq3_get_ue_golomb(gb); /* version_minor */ - avctx->profile = svq3_get_ue_golomb(gb); - avctx->level = svq3_get_ue_golomb(gb); + version_major = get_interleaved_ue_golomb(&gb); + get_interleaved_ue_golomb(&gb); /* version_minor */ + dsh->profile = get_interleaved_ue_golomb(&gb); + dsh->level = get_interleaved_ue_golomb(&gb); /* [DIRAC_SPEC] sequence_header() -> base_video_format as defined in * 10.2 Base Video Format, table 10.1 Dirac predefined video formats */ - video_format = svq3_get_ue_golomb(gb); + video_format = get_interleaved_ue_golomb(&gb); - if (version_major < 2) - av_log(avctx, AV_LOG_WARNING, "Stream is old and may not work\n"); - else if (version_major > 2) - av_log(avctx, AV_LOG_WARNING, "Stream may have unhandled features\n"); + if (log_ctx) { + if (version_major < 2) + av_log(log_ctx, AV_LOG_WARNING, "Stream is old and may not work\n"); + else if (version_major > 2) + av_log(log_ctx, AV_LOG_WARNING, "Stream may have unhandled features\n"); + } - if (video_format > 20) - return AVERROR_INVALIDDATA; + if (video_format > 20) { + ret = AVERROR_INVALIDDATA; + goto fail; + } // Fill in defaults for the source parameters. - *source = dirac_source_parameters_defaults[video_format]; + dsh->width = dirac_source_parameters_defaults[video_format].width; + dsh->height = dirac_source_parameters_defaults[video_format].height; + dsh->chroma_format = dirac_source_parameters_defaults[video_format].chroma_format; + dsh->interlaced = dirac_source_parameters_defaults[video_format].interlaced; + dsh->top_field_first = dirac_source_parameters_defaults[video_format].top_field_first; + dsh->frame_rate_index = dirac_source_parameters_defaults[video_format].frame_rate_index; + dsh->aspect_ratio_index = dirac_source_parameters_defaults[video_format].aspect_ratio_index; + dsh->clean_width = dirac_source_parameters_defaults[video_format].clean_width; + dsh->clean_height = dirac_source_parameters_defaults[video_format].clean_height; + dsh->clean_left_offset = dirac_source_parameters_defaults[video_format].clean_left_offset; + dsh->clean_right_offset = dirac_source_parameters_defaults[video_format].clean_right_offset; + dsh->pixel_range_index = dirac_source_parameters_defaults[video_format].pixel_range_index; + dsh->color_spec_index = dirac_source_parameters_defaults[video_format].color_spec_index; /* [DIRAC_STD] 10.3 Source Parameters * Override the defaults. */ - if (ret = parse_source_parameters(avctx, gb, source)) - return ret; - - ret = ff_set_dimensions(avctx, source->width, source->height); + ret = parse_source_parameters(dsh, &gb, log_ctx); if (ret < 0) - return ret; - - ff_set_sar(avctx, avctx->sample_aspect_ratio); + goto fail; /* [DIRAC_STD] picture_coding_mode shall be 0 for fields and 1 for frames * currently only used to signal field coding */ - picture_coding_mode = svq3_get_ue_golomb(gb); + picture_coding_mode = get_interleaved_ue_golomb(&gb); if (picture_coding_mode != 0) { - av_log(avctx, AV_LOG_ERROR, "Unsupported picture coding mode %d", - picture_coding_mode); - return AVERROR_INVALIDDATA; + if (log_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Unsupported picture coding mode %d", + picture_coding_mode); + } + ret = AVERROR_INVALIDDATA; + goto fail; } + + *pdsh = dsh; return 0; +fail: + av_freep(&dsh); + *pdsh = NULL; + return ret; +} +#else +int av_dirac_parse_sequence_header(AVDiracSeqHeader **pdsh, + const uint8_t *buf, size_t buf_size, + void *log_ctx) +{ + return AVERROR(ENOSYS); } +#endif diff --git a/libavcodec/dirac.h b/libavcodec/dirac.h index e5b79b0..25cefdb 100644 --- a/libavcodec/dirac.h +++ b/libavcodec/dirac.h @@ -29,9 +29,8 @@ */ #include "avcodec.h" -#include "get_bits.h" -typedef struct dirac_source_params { +typedef struct AVDiracSeqHeader { unsigned width; unsigned height; uint8_t chroma_format; ///< 0: 444 1: 422 2: 420 @@ -49,9 +48,33 @@ typedef struct dirac_source_params { uint8_t pixel_range_index; ///< index into dirac_pixel_range_presets[] uint8_t color_spec_index; ///< index into dirac_color_spec_presets[] -} dirac_source_params; -int avpriv_dirac_parse_sequence_header(AVCodecContext *avctx, GetBitContext *gb, - dirac_source_params *source); + int profile; + int level; + + AVRational framerate; + AVRational sample_aspect_ratio; + + enum AVPixelFormat pix_fmt; + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; +} AVDiracSeqHeader; + +/** + * Parse a Dirac sequence header. + * + * @param dsh this function will allocate and fill an AVDiracSeqHeader struct + * and write it into this pointer. The caller must free it with + * av_free(). + * @param buf the data buffer + * @param buf_size the size of the data buffer in bytes + * @param log_ctx if non-NULL, this function will log errors here + * @return 0 on success, a negative AVERROR code on failure + */ +int av_dirac_parse_sequence_header(AVDiracSeqHeader **dsh, + const uint8_t *buf, size_t buf_size, + void *log_ctx); #endif /* AVCODEC_DIRAC_H */ diff --git a/libavcodec/dirac_parser.c b/libavcodec/dirac_parser.c index 46f5430..5c9d266 100644 --- a/libavcodec/dirac_parser.c +++ b/libavcodec/dirac_parser.c @@ -31,6 +31,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" + #include "parser.h" #define DIRAC_PARSE_INFO_PREFIX 0x42424344 @@ -75,23 +76,22 @@ static int find_frame_end(DiracParseContext *pc, pc->sync_offset = 0; for (; i < buf_size; i++) { if (state == DIRAC_PARSE_INFO_PREFIX) { - if ((buf_size-i) >= pc->header_bytes_needed) { + if ((buf_size - i) >= pc->header_bytes_needed) { pc->state = -1; return i + pc->header_bytes_needed; } else { - pc->header_bytes_needed = 9-(buf_size-i); + pc->header_bytes_needed = 9 - (buf_size - i); break; } } else - state = (state << 8) | buf[i]; + state = (state << 8) | buf[i]; } } pc->state = state; return -1; } -typedef struct DiracParseUnit -{ +typedef struct DiracParseUnit { int next_pu_offset; int prev_pu_offset; uint8_t pu_type; @@ -102,12 +102,12 @@ static int unpack_parse_unit(DiracParseUnit *pu, DiracParseContext *pc, { uint8_t *start = pc->buffer + offset; uint8_t *end = pc->buffer + pc->index; - if (start < pc->buffer || (start+13 > end)) + if (start < pc->buffer || (start + 13 > end)) return 0; pu->pu_type = start[4]; - pu->next_pu_offset = AV_RB32(start+5); - pu->prev_pu_offset = AV_RB32(start+9); + pu->next_pu_offset = AV_RB32(start + 5); + pu->prev_pu_offset = AV_RB32(start + 9); if (pu->pu_type == 0x10 && pu->next_pu_offset == 0) pu->next_pu_offset = 13; @@ -125,7 +125,7 @@ static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, if (pc->overread_index) { memcpy(pc->buffer, pc->buffer + pc->overread_index, pc->index - pc->overread_index); - pc->index -= pc->overread_index; + pc->index -= pc->overread_index; pc->overread_index = 0; if (*buf_size == 0 && pc->buffer[4] == 0x10) { *buf = pc->buffer; @@ -134,13 +134,13 @@ static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, } } - if ( next == -1) { + if (next == -1) { /* Found a possible frame start but not a frame end */ - void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, - pc->index + (*buf_size - - pc->sync_offset)); + void *new_buffer = + av_fast_realloc(pc->buffer, &pc->buffer_size, + pc->index + (*buf_size - pc->sync_offset)); pc->buffer = new_buffer; - memcpy(pc->buffer+pc->index, (*buf + pc->sync_offset), + memcpy(pc->buffer + pc->index, (*buf + pc->sync_offset), *buf_size - pc->sync_offset); pc->index += *buf_size - pc->sync_offset; return -1; @@ -162,8 +162,8 @@ static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, if (!unpack_parse_unit(&pu1, pc, pc->index - 13) || !unpack_parse_unit(&pu, pc, pc->index - 13 - pu1.prev_pu_offset) || pu.next_pu_offset != pu1.prev_pu_offset) { - pc->index -= 9; - *buf_size = next-9; + pc->index -= 9; + *buf_size = next - 9; pc->header_bytes_needed = 9; return -1; } @@ -177,9 +177,9 @@ static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, pc->dirac_unit_size += pu.next_pu_offset; - if ((pu.pu_type&0x08) != 0x08) { + if ((pu.pu_type & 0x08) != 0x08) { pc->header_bytes_needed = 9; - *buf_size = next; + *buf_size = next; return -1; } @@ -187,24 +187,24 @@ static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, if (parse_timing_info) { uint8_t *cur_pu = pc->buffer + pc->index - 13 - pu1.prev_pu_offset; - int pts = AV_RB32(cur_pu + 13); + int pts = AV_RB32(cur_pu + 13); if (s->last_pts == 0 && s->last_dts == 0) s->dts = pts - 1; else - s->dts = s->last_dts+1; + s->dts = s->last_dts + 1; s->pts = pts; if (!avctx->has_b_frames && (cur_pu[4] & 0x03)) avctx->has_b_frames = 1; } if (avctx->has_b_frames && s->pts == s->dts) - s->pict_type = AV_PICTURE_TYPE_B; + s->pict_type = AV_PICTURE_TYPE_B; /* Finally have a complete Dirac data unit */ *buf = pc->dirac_unit; *buf_size = pc->dirac_unit_size; pc->dirac_unit_size = 0; - pc->overread_index = pc->index-13; + pc->overread_index = pc->index - 13; pc->header_bytes_needed = 9; } return next; @@ -217,27 +217,25 @@ static int dirac_parse(AVCodecParserContext *s, AVCodecContext *avctx, DiracParseContext *pc = s->priv_data; int next; - *poutbuf = NULL; + *poutbuf = NULL; *poutbuf_size = 0; if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { - next = buf_size; - *poutbuf = buf; + next = buf_size; + *poutbuf = buf; *poutbuf_size = buf_size; /* Assume that data has been packetized into an encapsulation unit. */ } else { next = find_frame_end(pc, buf, buf_size); - if (!pc->is_synced && next == -1) { + if (!pc->is_synced && next == -1) /* No frame start found yet. So throw away the entire buffer. */ return buf_size; - } - if (dirac_combine_frame(s, avctx, next, &buf, &buf_size) < 0) { + if (dirac_combine_frame(s, avctx, next, &buf, &buf_size) < 0) return buf_size; - } } - *poutbuf = buf; + *poutbuf = buf; *poutbuf_size = buf_size; return next; } diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index 0edaeec..55272e9 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -23,28 +23,33 @@ #include "dnxhddata.h" #include "libavutil/common.h" +/* The quantization tables below are in zigzag order! */ + +/* Used in CID 1235, 1256 */ static const uint8_t dnxhd_1235_luma_weight[] = { - 0, 32, 32, 32, 33, 35, 38, 39, - 32, 33, 32, 33, 36, 36, 39, 42, - 32, 32, 33, 36, 35, 37, 41, 43, - 31, 33, 34, 36, 36, 40, 42, 48, - 32, 34, 36, 37, 39, 42, 46, 51, - 36, 37, 37, 39, 41, 46, 51, 55, - 37, 39, 41, 41, 47, 50, 55, 56, - 41, 42, 41, 44, 50, 53, 60, 60 + 0, 32, 32, 32, 33, 32, 32, 32, + 32, 31, 32, 33, 33, 33, 33, 35, + 36, 36, 34, 34, 36, 37, 37, 36, + 36, 35, 36, 38, 39, 39, 37, 36, + 37, 37, 39, 41, 42, 41, 39, 39, + 40, 41, 42, 43, 42, 42, 41, 41, + 41, 44, 47, 46, 46, 48, 51, 51, + 50, 50, 53, 55, 55, 56, 60, 60, }; +/* Used in CID 1235, 1256 */ static const uint8_t dnxhd_1235_chroma_weight[] = { - 0, 32, 33, 34, 39, 41, 54, 59, - 33, 34, 35, 38, 43, 49, 58, 84, - 34, 37, 39, 44, 46, 55, 74, 87, - 40, 42, 47, 48, 58, 70, 87, 86, - 43, 50, 56, 63, 72, 94, 91, 82, - 55, 63, 65, 75, 93, 89, 85, 73, - 61, 67, 82, 81, 83, 90, 79, 73, - 74, 84, 75, 78, 90, 85, 73, 73 + 0, 32, 33, 34, 34, 33, 34, 35, + 37, 40, 43, 42, 39, 38, 39, 41, + 43, 44, 47, 50, 55, 61, 63, 56, + 48, 46, 49, 54, 59, 58, 55, 58, + 63, 65, 67, 74, 84, 82, 75, 72, + 70, 74, 84, 87, 87, 94, 93, 81, + 75, 78, 83, 89, 91, 86, 82, 85, + 90, 90, 85, 79, 73, 73, 73, 73, }; +/* Used in CID 1237, 1253, 1259 */ static const uint8_t dnxhd_1237_luma_weight[] = { 0, 32, 33, 34, 34, 36, 37, 36, 36, 37, 38, 38, 38, 39, 41, 44, @@ -56,6 +61,7 @@ static const uint8_t dnxhd_1237_luma_weight[] = { 97, 100, 104, 102, 98, 98, 99, 99, }; +/* Used in CID 1237, 1253, 1259 */ static const uint8_t dnxhd_1237_chroma_weight[] = { 0, 32, 36, 39, 39, 38, 39, 41, 45, 51, 57, 58, 53, 48, 47, 51, @@ -156,25 +162,25 @@ static const uint8_t dnxhd_1243_chroma_weight[] = { }; static const uint8_t dnxhd_1250_luma_weight[] = { - 0, 32, 35, 35, 36, 36, 41, 43, - 32, 34, 35, 36, 37, 39, 43, 47, - 33, 34, 36, 38, 38, 42, 42, 50, - 34, 36, 38, 38, 41, 40, 47, 54, - 35, 38, 39, 40, 39, 45, 49, 58, - 38, 39, 40, 39, 46, 47, 54, 60, - 38, 39, 41, 46, 46, 48, 57, 62, - 40, 41, 44, 45, 49, 54, 63, 63 + 0, 32, 32, 33, 34, 35, 35, 35, + 34, 34, 35, 36, 36, 36, 36, 36, + 37, 38, 38, 38, 38, 38, 39, 39, + 38, 38, 39, 41, 43, 43, 42, 41, + 40, 40, 39, 40, 41, 41, 39, 39, + 40, 42, 47, 50, 47, 45, 46, 46, + 44, 45, 46, 47, 49, 54, 58, 54, + 48, 49, 54, 57, 60, 62, 63, 63, }; static const uint8_t dnxhd_1250_chroma_weight[] = { - 0, 32, 35, 36, 40, 42, 51, 51, - 35, 36, 39, 39, 43, 51, 52, 55, - 36, 41, 41, 43, 51, 53, 54, 56, - 43, 44, 45, 50, 54, 54, 55, 57, - 45, 48, 50, 51, 55, 58, 59, 58, - 49, 52, 49, 57, 58, 62, 58, 60, - 51, 51, 56, 58, 62, 61, 59, 62, - 52, 52, 60, 61, 59, 59, 63, 63 + 0, 32, 35, 36, 36, 35, 36, 39, + 41, 43, 45, 44, 41, 39, 40, 42, + 43, 43, 45, 48, 49, 51, 52, 50, + 50, 51, 51, 51, 51, 52, 53, 54, + 51, 49, 51, 52, 52, 56, 57, 55, + 54, 54, 55, 56, 55, 58, 58, 58, + 60, 61, 62, 62, 59, 57, 58, 58, + 61, 59, 59, 59, 60, 62, 63, 63, }; static const uint8_t dnxhd_1251_luma_weight[] = { @@ -199,6 +205,7 @@ static const uint8_t dnxhd_1251_chroma_weight[] = { 61, 59, 59, 59, 61, 62, 62, 62, }; +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_luma_weight[] = { 0, 32, 34, 35, 36, 36, 36, 37, 36, 37, 39, 40, 41, 40, 40, 40, @@ -209,6 +216,8 @@ static const uint8_t dnxhd_1252_luma_weight[] = { 71, 82, 90, 90, 88, 87, 90, 95, 100, 107, 103, 97, 95, 93, 99, 99, }; + +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_chroma_weight[] = { 0, 32, 35, 36, 37, 37, 38, 40, 42, 46, 49, 50, 50, 49, 49, 53, @@ -220,25 +229,49 @@ static const uint8_t dnxhd_1252_chroma_weight[] = { 114, 128, 125, 129, 134, 125, 116, 116, }; -static const uint8_t dnxhd_1256_chroma_weight[] = { - 0, 32, 32, 32, 32, 32, 32, 33, - 32, 32, 32, 32, 32, 32, 32, 34, - 32, 32, 32, 32, 32, 32, 33, 37, - 32, 32, 32, 32, 32, 32, 36, 39, - 32, 32, 32, 32, 32, 34, 39, 44, - 32, 37, 32, 32, 35, 40, 43, 49, - 32, 33, 36, 36, 40, 43, 50, 60, - 34, 37, 39, 44, 51, 56, 61, 70, +static const uint8_t dnxhd_1260_luma_weight[] = { + 0, 32, 33, 34, 36, 37, 37, 36, + 34, 33, 34, 35, 37, 38, 40, 41, + 40, 39, 38, 37, 34, 33, 34, 37, + 40, 44, 48, 52, 53, 49, 47, 45, + 42, 38, 36, 36, 38, 41, 43, 44, + 46, 49, 52, 54, 54, 49, 44, 44, + 44, 47, 51, 51, 52, 51, 48, 50, + 52, 53, 53, 50, 50, 54, 54, 54, +}; + +static const uint8_t dnxhd_1260_chroma_weight[] = { + 0, 32, 34, 38, 42, 40, 38, 36, + 35, 35, 38, 42, 43, 43, 42, 40, + 38, 39, 43, 43, 42, 41, 43, 43, + 42, 44, 46, 45, 45, 46, 47, 46, + 44, 44, 45, 46, 46, 46, 50, 50, + 47, 47, 49, 49, 49, 49, 51, 53, + 51, 49, 53, 57, 56, 52, 50, 52, + 56, 56, 53, 53, 53, 54, 58, 58, +}; + +/* Used in CID 1235, 1241, 1250, 1256 */ +static const uint8_t dnxhd_1235_dc_codes[14] = { + 10, 62, 11, 12, 13, 0, 1, 2, 3, 4, 14, 30, 126, 127, +}; + +/* Used in CID 1235, 1241, 1250, 1256 */ +static const uint8_t dnxhd_1235_dc_bits[14] = { + 4, 6, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 7, 7, }; +/* Used in CID 1237, 1238, 1242, 1243, 1251, 1252, 1253, 1258, 1259, 1260 */ static const uint8_t dnxhd_1237_dc_codes[12] = { 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, }; +/* Used in CID 1237, 1238, 1242, 1243, 1251, 1252, 1253, 1258, 1259, 1260 */ static const uint8_t dnxhd_1237_dc_bits[12] = { 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, }; +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ static const uint16_t dnxhd_1237_ac_codes[257] = { 0, 1, 4, 5, 12, 26, 27, 56, 57, 58, 59, 120, 121, 244, 245, 246, @@ -275,6 +308,7 @@ static const uint16_t dnxhd_1237_ac_codes[257] = { 65535, }; +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ static const uint8_t dnxhd_1237_ac_bits[257] = { 2, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, @@ -295,6 +329,7 @@ static const uint8_t dnxhd_1237_ac_bits[257] = { 16, }; +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ static const uint8_t dnxhd_1237_ac_level[257] = { 1, 1, 2, 0, 3, 4, 2, 5, 6, 7, 3, 8, 9, 10, 11, 12, 4, 5, 13, 14, 15, 16, 6, 17, 18, 19, 20, 21, 7, 22, 23, 24, @@ -315,6 +350,7 @@ static const uint8_t dnxhd_1237_ac_level[257] = { 64, }; +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ static const uint8_t dnxhd_1237_ac_run_flag[257] = { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -335,6 +371,7 @@ static const uint8_t dnxhd_1237_ac_run_flag[257] = { 1, }; +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ static const uint8_t dnxhd_1237_ac_index_flag[257] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -355,39 +392,7 @@ static const uint8_t dnxhd_1237_ac_index_flag[257] = { 1, }; -static const uint16_t dnxhd_1237_run_codes[62] = { - 0, 4, 10, 11, 24, 25, 26, 54, - 55, 56, 57, 58, 118, 119, 240, 482, - 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 990, 991, 992, 993, - 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, -}; - -static const uint8_t dnxhd_1237_run_bits[62] = { - 1, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 8, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, -}; - -static const uint8_t dnxhd_1237_run[62] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 53, 57, 58, 59, 60, 61, 62, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55, 56, -}; - -static const uint8_t dnxhd_1238_dc_codes[12] = { - 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, -}; - -static const uint8_t dnxhd_1238_dc_bits[12] = { - 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, -}; - +/* Used in CID 1238, 1243 */ static const uint16_t dnxhd_1238_ac_codes[257] = { 0, 1, 4, 10, 11, 24, 25, 26, 54, 55, 56, 57, 116, 117, 118, 119, @@ -424,6 +429,7 @@ static const uint16_t dnxhd_1238_ac_codes[257] = { 65535, }; +/* Used in CID 1238, 1243 */ static const uint8_t dnxhd_1238_ac_bits[257] = { 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, @@ -444,6 +450,7 @@ static const uint8_t dnxhd_1238_ac_bits[257] = { 16, }; +/* Used in CID 1238, 1243 */ static const uint8_t dnxhd_1238_ac_level[257] = { 1, 1, 2, 3, 0, 4, 5, 2, 6, 7, 8, 3, 9, 10, 11, 4, 12, 13, 14, 15, 16, 5, 17, 18, 19, 20, 21, 22, 6, 7, 23, 24, @@ -464,6 +471,7 @@ static const uint8_t dnxhd_1238_ac_level[257] = { 64, }; /* 0 is EOB */ +/* Used in CID 1238, 1243 */ static const uint8_t dnxhd_1238_ac_run_flag[257] = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, @@ -484,6 +492,7 @@ static const uint8_t dnxhd_1238_ac_run_flag[257] = { 1, }; +/* Used in CID 1238, 1243 */ static const uint8_t dnxhd_1238_ac_index_flag[257] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -504,40 +513,8 @@ static const uint8_t dnxhd_1238_ac_index_flag[257] = { 1, }; -static const uint16_t dnxhd_1235_1238_1241_run_codes[62] = { - 0, 4, 10, 11, 24, 25, 26, 27, - 56, 57, 58, 59, 120, 242, 486, 487, - 488, 489, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, -}; - -static const uint8_t dnxhd_1235_1238_1241_run_bits[62] = { - 1, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 8, 9, 9, - 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, -}; - -static const uint8_t dnxhd_1238_run[62] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 20, 21, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -}; - -static const uint8_t dnxhd_1235_1241_dc_codes[14] = { - 10, 62, 11, 12, 13, 0, 1, 2, 3, 4, 14, 30, 126, 127, -}; - -static const uint8_t dnxhd_1235_1241_dc_bits[14] = { - 4, 6, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 7, 7, -}; - -static const uint16_t dnxhd_1235_1241_ac_codes[257] = { +/* Used in CID 1235, 1241, 1256 */ +static const uint16_t dnxhd_1235_ac_codes[257] = { 0, 1, 4, 10, 11, 24, 25, 26, 54, 55, 56, 57, 116, 117, 118, 119, 240, 241, 242, 243, 244, 245, 492, 493, @@ -573,7 +550,8 @@ static const uint16_t dnxhd_1235_1241_ac_codes[257] = { 65535, }; -static const uint8_t dnxhd_1235_1241_ac_bits[257] = { +/* Used in CID 1235, 1241, 1256 */ +static const uint8_t dnxhd_1235_ac_bits[257] = { 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, @@ -593,7 +571,8 @@ static const uint8_t dnxhd_1235_1241_ac_bits[257] = { 16, }; -static const uint8_t dnxhd_1235_1241_ac_level[257] = { +/* Used in CID 1235, 1241, 1256 */ +static const uint8_t dnxhd_1235_ac_level[257] = { 1, 1, 2, 3, 0, 4, 5, 2, 6, 7, 8, 3, 9, 10, 11, 4, 12, 13, 14, 15, 16, 5, 17, 18, 19, 20, 21, 6, 7, 22, 23, 24, 25, 26, 27, 28, 29, 8, 9, 30, 31, 32, 33, 34, 35, 36, 37, 38, @@ -613,7 +592,8 @@ static const uint8_t dnxhd_1235_1241_ac_level[257] = { 64, }; -static const uint8_t dnxhd_1235_1241_ac_run_flag[257] = { +/* Used in CID 1235, 1241, 1256 */ +static const uint8_t dnxhd_1235_ac_run_flag[257] = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -633,7 +613,8 @@ static const uint8_t dnxhd_1235_1241_ac_run_flag[257] = { 1, }; -static const uint8_t dnxhd_1235_1241_ac_index_flag[257] = { +/* Used in CID 1235, 1241, 1256 */ +static const uint8_t dnxhd_1235_ac_index_flag[257] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -653,19 +634,6 @@ static const uint8_t dnxhd_1235_1241_ac_index_flag[257] = { 1, }; -static const uint8_t dnxhd_1235_1241_run[62] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 18, 20, 17, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -}; - -static const uint8_t dnxhd_1250_dc_codes[14] = { - 10, 62, 11, 12, 13, 0, 1, 2, 3, 4, 14, 30, 126, 127 -}; -static const uint8_t dnxhd_1250_dc_bits[14] = { - 4, 6, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 7, 7 -}; static const uint16_t dnxhd_1250_ac_codes[257] = { 0, 1, 4, 10, 11, 24, 25, 26, 54, 55, 56, 57, 116, 117, 118, 119, @@ -777,36 +745,6 @@ static const uint8_t dnxhd_1250_ac_index_flag[257] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -static const uint16_t dnxhd_1250_run_codes[62] = { - 0, 4, 5, 12, 26, 27, 28, 58, - 118, 119, 120, 242, 486, 487, 976, 977, - 978, 979, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023 -}; -static const uint8_t dnxhd_1250_run_bits[62] = { - 1, 3, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 -}; -static const uint8_t dnxhd_1250_run[62] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62 -}; - -static const uint8_t dnxhd_1251_dc_codes[12] = { - 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, -}; - -static const uint8_t dnxhd_1251_dc_bits[12] = { - 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, -}; static const uint16_t dnxhd_1251_ac_codes[257] = { 0, 1, 4, 10, 11, 24, 25, 26, @@ -924,39 +862,7 @@ static const uint8_t dnxhd_1251_ac_index_flag[257] = { 1, }; -static const uint16_t dnxhd_1251_run_codes[62] = { - 0, 4, 5, 12, 26, 27, 28, 58, - 118, 119, 120, 242, 486, 487, 976, 977, - 978, 979, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, -}; - -static const uint8_t dnxhd_1251_run_bits[62] = { - 1, 3, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, -}; - -static const uint8_t dnxhd_1251_run[62] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -}; - -static const uint8_t dnxhd_1252_dc_codes[12] = { - 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, -}; - -static const uint8_t dnxhd_1252_dc_bits[12] = { - 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, -}; - +/* Used in CID 1252, 1258 */ static const uint16_t dnxhd_1252_ac_codes[257] = { 0, 1, 4, 10, 11, 12, 26, 27, 56, 57, 58, 118, 119, 120, 242, 243, @@ -993,6 +899,7 @@ static const uint16_t dnxhd_1252_ac_codes[257] = { 65535, }; +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_ac_bits[257] = { 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, @@ -1013,6 +920,7 @@ static const uint8_t dnxhd_1252_ac_bits[257] = { 16, }; +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_ac_level[257] = { 1, 1, 2, 3, 2, 0, 4, 5, 6, 7, 3, 8, 9, 10, 11, 12, 13, 14, 4, 5, 15, 16, 17, 18, 6, 19, 20, 21, 22, 23, 24, 7, @@ -1033,6 +941,7 @@ static const uint8_t dnxhd_1252_ac_level[257] = { 64, }; +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_ac_run_flag[257] = { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, @@ -1053,6 +962,7 @@ static const uint8_t dnxhd_1252_ac_run_flag[257] = { 1, }; +/* Used in CID 1252, 1258 */ static const uint8_t dnxhd_1252_ac_index_flag[257] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1073,13 +983,104 @@ static const uint8_t dnxhd_1252_ac_index_flag[257] = { 1, }; +/* Used in CID 1235, 1238, 1241, 1256 */ +static const uint16_t dnxhd_1235_run_codes[62] = { + 0, 4, 10, 11, 24, 25, 26, 27, + 56, 57, 58, 59, 120, 242, 486, 487, + 488, 489, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +/* Used in CID 1235, 1238, 1241, 1243, 1256 */ +static const uint8_t dnxhd_1235_run_bits[62] = { + 1, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 8, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +/* Used in CID 1235, 1241, 1256 */ +static const uint8_t dnxhd_1235_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 18, 20, 17, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ +static const uint16_t dnxhd_1237_run_codes[62] = { + 0, 4, 10, 11, 24, 25, 26, 54, + 55, 56, 57, 58, 118, 119, 240, 482, + 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ +static const uint8_t dnxhd_1237_run_bits[62] = { + 1, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +/* Used in CID 1237, 1242, 1253, 1259, 1260 */ +static const uint8_t dnxhd_1237_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 53, 57, 58, 59, 60, 61, 62, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55, 56, +}; + +static const uint8_t dnxhd_1238_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 20, 21, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + +/* Used in CID 1250, 1251, 1252, 1258 */ +static const uint16_t dnxhd_1250_run_codes[62] = { + 0, 4, 5, 12, 26, 27, 28, 58, + 118, 119, 120, 242, 486, 487, 976, 977, + 978, 979, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +/* Used in CID 1250, 1251, 1252, 1258 */ +static const uint8_t dnxhd_1250_run_bits[62] = { + 1, 3, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +/* Used in CID 1250, 1251, 1252, 1258 */ +static const uint8_t dnxhd_1250_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + const CIDEntry ff_dnxhd_cid_table[] = { { 1235, 1920, 1080, 0, 917504, 917504, 6, 10, dnxhd_1235_luma_weight, dnxhd_1235_chroma_weight, - dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits, - dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level, - dnxhd_1235_1241_ac_run_flag, dnxhd_1235_1241_ac_index_flag, - dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run, + dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, + dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_level, + dnxhd_1235_ac_run_flag, dnxhd_1235_ac_index_flag, + dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, { 175, 185, 365, 440 } }, { 1237, 1920, 1080, 0, 606208, 606208, 4, 8, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, @@ -1090,17 +1091,17 @@ const CIDEntry ff_dnxhd_cid_table[] = { { 115, 120, 145, 240, 290 } }, { 1238, 1920, 1080, 0, 917504, 917504, 4, 8, dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight, - dnxhd_1238_dc_codes, dnxhd_1238_dc_bits, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_level, dnxhd_1238_ac_run_flag, dnxhd_1238_ac_index_flag, - dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1238_run, + dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run, { 175, 185, 220, 365, 440 } }, { 1241, 1920, 1080, 1, 917504, 458752, 6, 10, dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight, - dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits, - dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level, - dnxhd_1235_1241_ac_run_flag, dnxhd_1235_1241_ac_index_flag, - dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run, + dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, + dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_level, + dnxhd_1235_ac_run_flag, dnxhd_1235_ac_index_flag, + dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, { 185, 220 } }, { 1242, 1920, 1080, 1, 606208, 303104, 4, 8, dnxhd_1242_luma_weight, dnxhd_1242_chroma_weight, @@ -1111,31 +1112,31 @@ const CIDEntry ff_dnxhd_cid_table[] = { { 120, 145 } }, { 1243, 1920, 1080, 1, 917504, 458752, 4, 8, dnxhd_1243_luma_weight, dnxhd_1243_chroma_weight, - dnxhd_1238_dc_codes, dnxhd_1238_dc_bits, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_level, dnxhd_1238_ac_run_flag, dnxhd_1238_ac_index_flag, - dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1238_run, + dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run, { 185, 220 } }, { 1250, 1280, 720, 0, 458752, 458752, 6, 10, dnxhd_1250_luma_weight, dnxhd_1250_chroma_weight, - dnxhd_1250_dc_codes, dnxhd_1250_dc_bits, + dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1250_ac_codes, dnxhd_1250_ac_bits, dnxhd_1250_ac_level, dnxhd_1250_ac_run_flag, dnxhd_1250_ac_index_flag, dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, { 90, 180, 220 } }, { 1251, 1280, 720, 0, 458752, 458752, 4, 8, dnxhd_1251_luma_weight, dnxhd_1251_chroma_weight, - dnxhd_1251_dc_codes, dnxhd_1251_dc_bits, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1251_ac_codes, dnxhd_1251_ac_bits, dnxhd_1251_ac_level, dnxhd_1251_ac_run_flag, dnxhd_1251_ac_index_flag, - dnxhd_1251_run_codes, dnxhd_1251_run_bits, dnxhd_1251_run, + dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, { 90, 110, 175, 220 } }, { 1252, 1280, 720, 0, 303104, 303104, 4, 8, dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight, - dnxhd_1252_dc_codes, dnxhd_1252_dc_bits, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1252_ac_codes, dnxhd_1252_ac_bits, dnxhd_1252_ac_level, dnxhd_1252_ac_run_flag, dnxhd_1252_ac_index_flag, - dnxhd_1251_run_codes, dnxhd_1251_run_bits, dnxhd_1251_run, + dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, { 60, 75, 115, 145 } }, { 1253, 1920, 1080, 0, 188416, 188416, 4, 8, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, @@ -1145,12 +1146,33 @@ const CIDEntry ff_dnxhd_cid_table[] = { dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, { 36, 45, 75, 90 } }, { 1256, 1920, 1080, 0, 1835008, 1835008, 6, 10, - dnxhd_1235_luma_weight, dnxhd_1256_chroma_weight, - dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits, - dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level, - dnxhd_1235_1241_ac_run_flag, dnxhd_1235_1241_ac_index_flag, - dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run, + dnxhd_1235_luma_weight, dnxhd_1235_chroma_weight, + dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, + dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_level, + dnxhd_1235_ac_run_flag, dnxhd_1235_ac_index_flag, + dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, { 350, 390, 440, 730, 880 } }, + { 1258, 960, 720, 0, 212992, 212992, 4, 8, + dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1252_ac_codes, dnxhd_1252_ac_bits, dnxhd_1252_ac_level, + dnxhd_1252_ac_run_flag, dnxhd_1252_ac_index_flag, + dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, + { 42, 60, 75, 115 } }, + { 1259, 1440, 1080, 0, 417792, 417792, 4, 8, + dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_level, + dnxhd_1237_ac_run_flag, dnxhd_1237_ac_index_flag, + dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, + { 63, 84, 100, 110 } }, + { 1260, 1440, 1080, 1, 835584, 417792, 4, 8, + dnxhd_1260_luma_weight, dnxhd_1260_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_level, + dnxhd_1237_ac_run_flag, dnxhd_1237_ac_index_flag, + dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, + { 80, 90, 100, 110 } }, }; int ff_dnxhd_get_cid_table(int cid) @@ -1171,7 +1193,7 @@ int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth) for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { const CIDEntry *cid = &ff_dnxhd_cid_table[i]; if (cid->width == avctx->width && cid->height == avctx->height && - cid->interlaced == !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT) && + cid->interlaced == !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) && cid->bit_depth == bit_depth) { for (j = 0; j < sizeof(cid->bit_rates); j++) { if (cid->bit_rates[j] == mbs) @@ -1181,3 +1203,26 @@ int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth) } return 0; } + +void ff_dnxhd_list_cid(AVCodecContext *avctx) +{ + int i, j; + + for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { + const CIDEntry *cid = &ff_dnxhd_cid_table[i]; + av_log(avctx, AV_LOG_INFO, + "cid %d %ux%u %dbits %s bit rates", + cid->cid, + cid->width, cid->height, + cid->bit_depth, + cid->interlaced ? "interlaced " : + "progressive"); + for (j = 0; j < FF_ARRAY_ELEMS(cid->bit_rates); j++) { + if (!cid->bit_rates[j]) + break; + av_log(avctx, AV_LOG_INFO, " %dM", + cid->bit_rates[j]); + } + av_log(avctx, AV_LOG_INFO, "\n"); + } +} diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index 66b0349..cc877b6 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -40,12 +40,13 @@ typedef struct CIDEntry { const uint8_t *ac_run_flag, *ac_index_flag; const uint16_t *run_codes; const uint8_t *run_bits, *run; - int bit_rates[5]; ///< Helpher to choose variants, rounded to nearest 5Mb/s + int bit_rates[5]; ///< Helper to choose variants, rounded to nearest 5Mb/s } CIDEntry; extern const CIDEntry ff_dnxhd_cid_table[]; int ff_dnxhd_get_cid_table(int cid); int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth); +void ff_dnxhd_list_cid(AVCodecContext *avctx); #endif /* AVCODEC_DNXHDDATA_H */ diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index ca67990..50747ea 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -30,6 +30,7 @@ #include "dnxhddata.h" #include "idctdsp.h" #include "internal.h" +#include "thread.h" typedef struct DNXHDContext { AVCodecContext *avctx; @@ -48,6 +49,7 @@ typedef struct DNXHDContext { const CIDEntry *cid_table; int bit_depth; // 8, 10 or 0 if not initialized at all. int is_444; + int mbaff; void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block, int n, int qscale); } DNXHDContext; @@ -80,6 +82,7 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, int cid) return AVERROR(ENOSYS); } ctx->cid_table = &ff_dnxhd_cid_table[index]; + av_log(ctx->avctx, AV_LOG_VERBOSE, "Profile cid %d.\n", cid); ff_free_vlc(&ctx->ac_vlc); ff_free_vlc(&ctx->dc_vlc); @@ -109,12 +112,18 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; static const uint8_t header_prefix444[] = { 0x00, 0x00, 0x02, 0x80, 0x02 }; int i, cid, ret; + int old_bit_depth = ctx->bit_depth; - if (buf_size < 0x280) + if (buf_size < 0x280) { + av_log(ctx->avctx, AV_LOG_ERROR, "buffer too small (%d < 640).\n", + buf_size); return AVERROR_INVALIDDATA; + } if (memcmp(buf, header_prefix, 5) && memcmp(buf, header_prefix444, 5)) { - av_log(ctx->avctx, AV_LOG_ERROR, "error in header\n"); + av_log(ctx->avctx, AV_LOG_ERROR, + "unknown header 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", + buf[0], buf[1], buf[2], buf[3], buf[4]); return AVERROR_INVALIDDATA; } if (buf[5] & 2) { /* interlaced */ @@ -124,58 +133,67 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); } + ctx->mbaff = buf[0x6] & 32; ctx->height = AV_RB16(buf + 0x18); ctx->width = AV_RB16(buf + 0x1a); - av_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height); + ff_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height); + + if (buf[0x21] == 0x58) { /* 10 bit */ + ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 10; - ctx->is_444 = 0; - if (buf[0x4] == 0x2) { - ctx->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; - ctx->avctx->bits_per_raw_sample = 10; - if (ctx->bit_depth != 10) { - ff_blockdsp_init(&ctx->bdsp, ctx->avctx); - ff_idctdsp_init(&ctx->idsp, ctx->avctx); - ctx->bit_depth = 10; + if (buf[0x4] == 0x2) { ctx->decode_dct_block = dnxhd_decode_dct_block_10_444; - } - ctx->is_444 = 1; - } else if (buf[0x21] & 0x40) { - ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; - ctx->avctx->bits_per_raw_sample = 10; - if (ctx->bit_depth != 10) { - ff_blockdsp_init(&ctx->bdsp, ctx->avctx); - ff_idctdsp_init(&ctx->idsp, ctx->avctx); - ctx->bit_depth = 10; + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; + ctx->is_444 = 1; + } else { ctx->decode_dct_block = dnxhd_decode_dct_block_10; + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; } - } else { + } else if (buf[0x21] == 0x38) { /* 8 bit */ + ctx->bit_depth = ctx->avctx->bits_per_raw_sample = 8; + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P; - ctx->avctx->bits_per_raw_sample = 8; - if (ctx->bit_depth != 8) { - ff_blockdsp_init(&ctx->bdsp, ctx->avctx); - ff_idctdsp_init(&ctx->idsp, ctx->avctx); - ctx->bit_depth = 8; - ctx->decode_dct_block = dnxhd_decode_dct_block_8; - } + ctx->decode_dct_block = dnxhd_decode_dct_block_8; + } else { + av_log(ctx->avctx, AV_LOG_ERROR, "invalid bit depth value (%d).\n", + buf[0x21]); + return AVERROR_INVALIDDATA; + } + if (ctx->bit_depth != old_bit_depth) { + ff_blockdsp_init(&ctx->bdsp, ctx->avctx); + ff_idctdsp_init(&ctx->idsp, ctx->avctx); } cid = AV_RB32(buf + 0x28); - av_dlog(ctx->avctx, "compression id %d\n", cid); + ff_dlog(ctx->avctx, "compression id %d\n", cid); if ((ret = dnxhd_init_vlc(ctx, cid)) < 0) return ret; + if (ctx->mbaff && ctx->cid_table->cid != 1260) + av_log(ctx->avctx, AV_LOG_WARNING, + "Adaptive MB interlace flag in an unsupported profile.\n"); + + // make sure profile size constraints are respected + // DNx100 allows 1920->1440 and 1280->960 subsampling + if (ctx->width != ctx->cid_table->width) { + av_reduce(&ctx->avctx->sample_aspect_ratio.num, + &ctx->avctx->sample_aspect_ratio.den, + ctx->width, ctx->cid_table->width, 255); + ctx->width = ctx->cid_table->width; + } if (buf_size < ctx->cid_table->coding_unit_size) { - av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size (%d < %d).\n", + buf_size, ctx->cid_table->coding_unit_size); return AVERROR_INVALIDDATA; } ctx->mb_width = ctx->width >> 4; ctx->mb_height = buf[0x16d]; - av_dlog(ctx->avctx, + ff_dlog(ctx->avctx, "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) @@ -190,9 +208,11 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, for (i = 0; i < ctx->mb_height; i++) { ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i << 2)); - av_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); + ff_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); if (buf_size < ctx->mb_scan_index[i] + 0x280) { - av_log(ctx->avctx, AV_LOG_ERROR, "invalid mb scan index\n"); + av_log(ctx->avctx, AV_LOG_ERROR, + "invalid mb scan index (%d < %d).\n", + buf_size, ctx->mb_scan_index[i] + 0x280); return AVERROR_INVALIDDATA; } } @@ -307,8 +327,14 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, uint8_t *dest_y, *dest_u, *dest_v; int dct_y_offset, dct_x_offset; int qscale, i; + int interlaced_mb = 0; - qscale = get_bits(&ctx->gb, 11); + if (ctx->mbaff) { + interlaced_mb = get_bits1(&ctx->gb); + qscale = get_bits(&ctx->gb, 10); + } else { + qscale = get_bits(&ctx->gb, 11); + } skip_bits1(&ctx->gb); for (i = 0; i < 8; i++) { @@ -336,8 +362,12 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, dest_u += frame->linesize[1]; dest_v += frame->linesize[2]; } + if (interlaced_mb) { + dct_linesize_luma <<= 1; + dct_linesize_chroma <<= 1; + } - dct_y_offset = dct_linesize_luma << 3; + dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3); dct_x_offset = 8 << shift1; if (!ctx->is_444) { ctx->idsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); @@ -345,8 +375,8 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, ctx->idsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, ctx->blocks[4]); ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]); - if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { - dct_y_offset = dct_linesize_chroma << 3; + if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { + dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3); ctx->idsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); ctx->idsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[3]); ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]); @@ -358,8 +388,8 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, ctx->idsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, ctx->blocks[6]); ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[7]); - if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { - dct_y_offset = dct_linesize_chroma << 3; + if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { + dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3); ctx->idsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); ctx->idsp.idct_put(dest_u + dct_x_offset, dct_linesize_chroma, ctx->blocks[3]); ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[8]); @@ -398,14 +428,16 @@ static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DNXHDContext *ctx = avctx->priv_data; - AVFrame *picture = data; + ThreadFrame tf; int first_field = 1; int ret; - av_dlog(avctx, "frame size %d\n", buf_size); + tf.f = data; + + ff_dlog(avctx, "frame size %d\n", buf_size); decode_coding_unit: - if ((ret = dnxhd_decode_header(ctx, picture, buf, buf_size, first_field)) < 0) + if ((ret = dnxhd_decode_header(ctx, tf.f, buf, buf_size, first_field)) < 0) return ret; if ((avctx->width || avctx->height) && @@ -420,17 +452,17 @@ decode_coding_unit: return ret; if (first_field) { - if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) { + if ((ret = ff_thread_get_buffer(avctx, &tf, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - picture->pict_type = AV_PICTURE_TYPE_I; - picture->key_frame = 1; + tf.f->pict_type = AV_PICTURE_TYPE_I; + tf.f->key_frame = 1; } - dnxhd_decode_macroblocks(ctx, picture, buf + 0x280, buf_size - 0x280); + dnxhd_decode_macroblocks(ctx, tf.f, buf + 0x280, buf_size - 0x280); - if (first_field && picture->interlaced_frame) { + if (first_field && tf.f->interlaced_frame) { buf += ctx->cid_table->coding_unit_size; buf_size -= ctx->cid_table->coding_unit_size; first_field = 0; @@ -460,5 +492,5 @@ AVCodec ff_dnxhd_decoder = { .init = dnxhd_decode_init, .close = dnxhd_decode_close, .decode = dnxhd_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index 6896fc1..c02b51e 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -36,7 +36,7 @@ #include "pixblockdsp.h" #include "dnxhdenc.h" -// The largest value that will not lead to overflow for 10bit samples. +// The largest value that will not lead to overflow for 10-bit samples. #define DNX10BIT_QMAT_SHIFT 18 #define RC_VARIANCE 1 // use variance or ssd for fast rc #define LAMBDA_FRAC_BITS 10 @@ -45,6 +45,9 @@ static const AVOption options[] = { { "nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "ibias", "intra quant bias", + offsetof(DNXHDEncContext, intra_quant_bias), AV_OPT_TYPE_INT, + { .i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, VE }, { NULL } }; @@ -205,14 +208,14 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) weight_matrix[j] = ctx->cid_table->luma_weight[i]; } ff_convert_matrix(&ctx->m, ctx->qmatrix_l, ctx->qmatrix_l16, - weight_matrix, ctx->m.intra_quant_bias, 1, + weight_matrix, ctx->intra_quant_bias, 1, ctx->m.avctx->qmax, 1); for (i = 1; i < 64; i++) { int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; weight_matrix[j] = ctx->cid_table->chroma_weight[i]; } ff_convert_matrix(&ctx->m, ctx->qmatrix_c, ctx->qmatrix_c16, - weight_matrix, ctx->m.intra_quant_bias, 1, + weight_matrix, ctx->intra_quant_bias, 1, ctx->m.avctx->qmax, 1); for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { @@ -286,19 +289,22 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) break; default: av_log(avctx, AV_LOG_ERROR, - "pixel format is incompatible with DNxHD\n"); + "Pixel format is incompatible with DNxHD, use yuv422p or yuv422p10.\n"); return AVERROR(EINVAL); } ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth); if (!ctx->cid) { av_log(avctx, AV_LOG_ERROR, - "video parameters incompatible with DNxHD\n"); + "Video parameters incompatible with DNxHD, available CIDs:\n"); + ff_dnxhd_list_cid(avctx); return AVERROR(EINVAL); } av_log(avctx, AV_LOG_DEBUG, "cid %d\n", ctx->cid); index = ff_dnxhd_get_cid_table(ctx->cid); + if (index < 0) + return index; ctx->cid_table = &ff_dnxhd_cid_table[index]; ctx->m.avctx = avctx; @@ -330,17 +336,21 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_height = (avctx->height + 15) / 16; ctx->m.mb_width = (avctx->width + 15) / 16; - if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) { + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { ctx->interlaced = 1; ctx->m.mb_height /= 2; } ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; +#if FF_API_QUANT_BIAS +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) - ctx->m.intra_quant_bias = avctx->intra_quant_bias; + ctx->intra_quant_bias = avctx->intra_quant_bias; +FF_ENABLE_DEPRECATION_WARNINGS +#endif // XXX tune lbias/cbias - if ((ret = dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0)) < 0) + if ((ret = dnxhd_init_qmat(ctx, ctx->intra_quant_bias, 0)) < 0) return ret; /* Avid Nitris hardware decoder requires a minimum amount of padding @@ -362,12 +372,12 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale, ctx->m.mb_num * sizeof(uint8_t), fail); - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->thread_count > MAX_THREADS) { av_log(avctx, AV_LOG_ERROR, "too many threads\n"); @@ -388,7 +398,7 @@ fail: // for FF_ALLOCZ_OR_GOTO static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) { DNXHDEncContext *ctx = avctx->priv_data; - const uint8_t header_prefix[5] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; + static const uint8_t header_prefix[5] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; memset(buf, 0, 640); @@ -741,7 +751,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, ctx->mb_cmp[mb].mb = mb; } } else { // 10-bit - int const linesize = ctx->m.linesize >> 1; + const int linesize = ctx->m.linesize >> 1; for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) { uint16_t *pix = (uint16_t *)ctx->thread[0]->src[0] + ((mb_y << 4) * linesize) + (mb_x << 4); @@ -754,7 +764,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, for (i = 0; i < 16; ++i) { for (j = 0; j < 16; ++j) { // Turn 16-bit pixels into 10-bit ones. - int const sample = (unsigned) pix[j] >> 6; + const int sample = (unsigned) pix[j] >> 6; sum += sample; sqsum += sample * sample; // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX @@ -812,7 +822,7 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) if (bits > ctx->frame_bits) break; } - // av_dlog(ctx->m.avctx, + // ff_dlog(ctx->m.avctx, // "lambda %d, up %u, down %u, bits %d, frame %d\n", // lambda, last_higher, last_lower, bits, ctx->frame_bits); if (end) { @@ -843,7 +853,7 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) down_step = 1<m.avctx, "out lambda %d\n", lambda); + //ff_dlog(ctx->m.avctx, "out lambda %d\n", lambda); ctx->lambda = lambda; return 0; } @@ -872,7 +882,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) if (bits > ctx->frame_bits) break; } - // av_dlog(ctx->m.avctx, + // ff_dlog(ctx->m.avctx, // "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n", // ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits, // last_higher, last_lower); @@ -904,7 +914,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) return AVERROR(EINVAL); } } - //av_dlog(ctx->m.avctx, "out qscale %d\n", qscale); + //ff_dlog(ctx->m.avctx, "out qscale %d\n", qscale); ctx->qscale = qscale; return 0; } @@ -1020,7 +1030,11 @@ static void dnxhd_load_picture(DNXHDEncContext *ctx, const AVFrame *frame) ctx->thread[i]->dct_uv_offset = ctx->m.uvlinesize*8; } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS ctx->m.avctx->coded_frame->interlaced_frame = frame->interlaced_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ctx->cur_field = frame->interlaced_frame && !frame->top_field_first; } @@ -1030,7 +1044,7 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, DNXHDEncContext *ctx = avctx->priv_data; int first_field = 1; int offset, i, ret; - uint8_t *buf; + uint8_t *buf, *sd; if ((ret = ff_alloc_packet(pkt, ctx->cid_table->frame_size)) < 0) { av_log(avctx, AV_LOG_ERROR, @@ -1084,7 +1098,16 @@ encode_coding_unit: goto encode_coding_unit; } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->quality = ctx->qscale * FF_QP2LAMBDA; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = ctx->qscale * FF_QP2LAMBDA; pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -1117,8 +1140,6 @@ static av_cold int dnxhd_encode_end(AVCodecContext *avctx) for (i = 1; i < avctx->thread_count; i++) av_freep(&ctx->thread[i]); - av_frame_free(&avctx->coded_frame); - return 0; } @@ -1131,7 +1152,7 @@ AVCodec ff_dnxhd_encoder = { .init = dnxhd_encode_init, .encode2 = dnxhd_encode_picture, .close = dnxhd_encode_end, - .capabilities = CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, diff --git a/libavcodec/dnxhdenc.h b/libavcodec/dnxhdenc.h index c3248a2..d3df0e0 100644 --- a/libavcodec/dnxhdenc.h +++ b/libavcodec/dnxhdenc.h @@ -63,6 +63,7 @@ typedef struct DNXHDEncContext { int nitris_compat; unsigned min_padding; + int intra_quant_bias; DECLARE_ALIGNED(16, int16_t, blocks)[8][64]; diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 5ab2331..7567643 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -1,6 +1,6 @@ /* * Assorted DPCM codecs - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -333,7 +333,7 @@ AVCodec ff_ ## name_ ## _decoder = { \ .priv_data_size = sizeof(DPCMContext), \ .init = dpcm_decode_init, \ .decode = dpcm_decode_frame, \ - .capabilities = CODEC_CAP_DR1, \ + .capabilities = AV_CODEC_CAP_DR1, \ } DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay"); diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index c796387..d4effa4 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -215,5 +215,5 @@ AVCodec ff_dpx_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DPX, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dpx_parser.c b/libavcodec/dpx_parser.c new file mode 100644 index 0000000..e3a7ac5 --- /dev/null +++ b/libavcodec/dpx_parser.c @@ -0,0 +1,116 @@ +/* + * DPX parser + * Copyright (c) 2013 Paul B Mahol + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * DPX parser + */ + +#include "libavutil/bswap.h" +#include "libavutil/common.h" + +#include "parser.h" + +typedef struct DPXParseContext { + ParseContext pc; + uint32_t index; + uint32_t fsize; + uint32_t remaining_size; + int is_be; +} DPXParseContext; + +static int dpx_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DPXParseContext *d = s->priv_data; + uint32_t state = d->pc.state; + int next = END_NOT_FOUND; + int i = 0; + + s->pict_type = AV_PICTURE_TYPE_I; + + *poutbuf_size = 0; + if (buf_size == 0) + next = 0; + + if (!d->pc.frame_start_found) { + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (state == MKBETAG('S','D','P','X') || + state == MKTAG('S','D','P','X')) { + d->pc.frame_start_found = 1; + d->is_be = state == MKBETAG('S','D','P','X'); + d->index = 0; + break; + } + } + d->pc.state = state; + } else { + if (d->remaining_size) { + i = FFMIN(d->remaining_size, buf_size); + d->remaining_size -= i; + if (d->remaining_size) + goto flush; + } + } + + for (; d->pc.frame_start_found && i < buf_size; i++) { + d->pc.state = (d->pc.state << 8) | buf[i]; + d->index++; + if (d->index == 17) { + d->fsize = d->is_be ? d->pc.state : av_bswap32(d->pc.state); + if (d->fsize <= 1664) { + d->pc.frame_start_found = 0; + goto flush; + } + if (d->fsize > buf_size - i + 19) + d->remaining_size = d->fsize - buf_size + i - 19; + else + i += d->fsize - 19; + + break; + } else if (d->index > 17) { + if (d->pc.state == MKBETAG('S','D','P','X') || + d->pc.state == MKTAG('S','D','P','X')) { + next = i - 3; + break; + } + } + } + +flush: + if (ff_combine_frame(&d->pc, next, &buf, &buf_size) < 0) + return buf_size; + + d->pc.frame_start_found = 0; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_dpx_parser = { + .codec_ids = { AV_CODEC_ID_DPX }, + .priv_data_size = sizeof(DPXParseContext), + .parser_parse = dpx_parse, + .parser_close = ff_parse_close, +}; diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c index 2232933..adcb529 100644 --- a/libavcodec/dpxenc.c +++ b/libavcodec/dpxenc.c @@ -35,12 +35,12 @@ static av_cold int encode_init(AVCodecContext *avctx) { DPXContext *s = avctx->priv_data; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->big_endian = 1; s->bits_per_component = 8; @@ -54,6 +54,7 @@ static av_cold int encode_init(AVCodecContext *avctx) break; case AV_PIX_FMT_RGB48LE: s->big_endian = 0; + /* fall-through */ case AV_PIX_FMT_RGB48BE: s->bits_per_component = avctx->bits_per_raw_sample ? avctx->bits_per_raw_sample : 16; break; @@ -77,7 +78,7 @@ do { \ else AV_WL32(p, value); \ } while(0) -static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, +static void encode_rgb48_10bit(AVCodecContext *avctx, const AVFrame *pic, uint8_t *dst) { DPXContext *s = avctx->priv_data; @@ -114,7 +115,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (s->bits_per_component == 10) size = avctx->height * avctx->width * 4; else - size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); if ((ret = ff_alloc_packet(pkt, size + HEADER_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; @@ -129,7 +131,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, memcpy (buf + 8, "V1.0", 4); write32(buf + 20, 1); /* new image */ write32(buf + 24, HEADER_SIZE); - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ @@ -143,6 +145,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, buf[802] = 2; /* linear colorimetric */ buf[803] = s->bits_per_component; write16(buf + 804, s->bits_per_component == 10 ? 1 : 0); /* packing method */ + write32(buf + 808, HEADER_SIZE); /* data offset */ /* Image source information header */ write32(buf + 1628, avctx->sample_aspect_ratio.num); @@ -151,14 +154,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, switch (s->bits_per_component) { case 8: case 16: - size = avpicture_layout((const AVPicture*)frame, avctx->pix_fmt, - avctx->width, avctx->height, - buf + HEADER_SIZE, pkt->size - HEADER_SIZE); + size = av_image_copy_to_buffer(buf + HEADER_SIZE, + pkt->size - HEADER_SIZE, + frame->data, frame->linesize, + avctx->pix_fmt, + avctx->width, avctx->height, 1); if (size < 0) return size; break; case 10: - encode_rgb48_10bit(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + encode_rgb48_10bit(avctx, frame, buf + HEADER_SIZE); break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); @@ -175,12 +180,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - AVCodec ff_dpx_encoder = { .name = "dpx", .long_name = NULL_IF_CONFIG_SMALL("DPX image"), @@ -189,7 +188,6 @@ AVCodec ff_dpx_encoder = { .priv_data_size = sizeof(DPXContext), .init = encode_init, .encode2 = encode_frame, - .close = encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, diff --git a/libavcodec/dsicinaudio.c b/libavcodec/dsicinaudio.c index 969e4ae..e0fecbe 100644 --- a/libavcodec/dsicinaudio.c +++ b/libavcodec/dsicinaudio.c @@ -131,5 +131,5 @@ AVCodec ff_dsicinaudio_decoder = { .priv_data_size = sizeof(CinAudioContext), .init = cinaudio_decode_init, .decode = cinaudio_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c index b56a581..7c62dcf 100644 --- a/libavcodec/dsicinvideo.c +++ b/libavcodec/dsicinvideo.c @@ -297,5 +297,5 @@ AVCodec ff_dsicinvideo_decoder = { .init = cinvideo_decode_init, .close = cinvideo_decode_end, .decode = cinvideo_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dss_sp.c b/libavcodec/dss_sp.c new file mode 100644 index 0000000..20b0528 --- /dev/null +++ b/libavcodec/dss_sp.c @@ -0,0 +1,780 @@ +/* + * Digital Speech Standard - Standard Play mode (DSS SP) audio decoder. + * Copyright (C) 2014 Oleksij Rempel + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +#define SUBFRAMES 4 +#define PULSE_MAX 8 + +#define DSS_SP_FRAME_SIZE 42 +#define DSS_SP_SAMPLE_COUNT (66 * SUBFRAMES) +#define DSS_SP_FORMULA(a, b, c) ((((a) << 15) + (b) * (c)) + 0x4000) >> 15 + +typedef struct DssSpSubframe { + int16_t gain; + int32_t combined_pulse_pos; + int16_t pulse_pos[7]; + int16_t pulse_val[7]; +} DssSpSubframe; + +typedef struct DssSpFrame { + int16_t filter_idx[14]; + int16_t sf_adaptive_gain[SUBFRAMES]; + int16_t pitch_lag[SUBFRAMES]; + struct DssSpSubframe sf[SUBFRAMES]; +} DssSpFrame; + +typedef struct DssSpContext { + int32_t excitation[288 + 6]; + int32_t history[187]; + DssSpFrame fparam; + int32_t working_buffer[SUBFRAMES][72]; + int32_t audio_buf[15]; + int32_t err_buf1[15]; + int32_t lpc_filter[14]; + int32_t filter[15]; + int32_t vector_buf[72]; + int noise_state; + int32_t err_buf2[15]; + + int pulse_dec_mode; + + DECLARE_ALIGNED(16, uint8_t, bits)[DSS_SP_FRAME_SIZE + + AV_INPUT_BUFFER_PADDING_SIZE]; +} DssSpContext; + +/* + * Used for the coding/decoding of the pulse positions for the MP-MLQ codebook. + */ +static const uint32_t dss_sp_combinatorial_table[PULSE_MAX][72] = { + { 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 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 }, + { 0, 0, 1, 3, 6, 10, + 15, 21, 28, 36, 45, 55, + 66, 78, 91, 105, 120, 136, + 153, 171, 190, 210, 231, 253, + 276, 300, 325, 351, 378, 406, + 435, 465, 496, 528, 561, 595, + 630, 666, 703, 741, 780, 820, + 861, 903, 946, 990, 1035, 1081, + 1128, 1176, 1225, 1275, 1326, 1378, + 1431, 1485, 1540, 1596, 1653, 1711, + 1770, 1830, 1891, 1953, 2016, 2080, + 2145, 2211, 2278, 2346, 2415, 2485 }, + { 0, 0, 0, 1, 4, 10, + 20, 35, 56, 84, 120, 165, + 220, 286, 364, 455, 560, 680, + 816, 969, 1140, 1330, 1540, 1771, + 2024, 2300, 2600, 2925, 3276, 3654, + 4060, 4495, 4960, 5456, 5984, 6545, + 7140, 7770, 8436, 9139, 9880, 10660, + 11480, 12341, 13244, 14190, 15180, 16215, + 17296, 18424, 19600, 20825, 22100, 23426, + 24804, 26235, 27720, 29260, 30856, 32509, + 34220, 35990, 37820, 39711, 41664, 43680, + 45760, 47905, 50116, 52394, 54740, 57155 }, + { 0, 0, 0, 0, 1, 5, + 15, 35, 70, 126, 210, 330, + 495, 715, 1001, 1365, 1820, 2380, + 3060, 3876, 4845, 5985, 7315, 8855, + 10626, 12650, 14950, 17550, 20475, 23751, + 27405, 31465, 35960, 40920, 46376, 52360, + 58905, 66045, 73815, 82251, 91390, 101270, + 111930, 123410, 135751, 148995, 163185, 178365, + 194580, 211876, 230300, 249900, 270725, 292825, + 316251, 341055, 367290, 395010, 424270, 455126, + 487635, 521855, 557845, 595665, 635376, 677040, + 720720, 766480, 814385, 864501, 916895, 971635 }, + { 0, 0, 0, 0, 0, 1, + 6, 21, 56, 126, 252, 462, + 792, 1287, 2002, 3003, 4368, 6188, + 8568, 11628, 15504, 20349, 26334, 33649, + 42504, 53130, 65780, 80730, 98280, 118755, + 142506, 169911, 201376, 237336, 278256, 324632, + 376992, 435897, 501942, 575757, 658008, 749398, + 850668, 962598, 1086008, 1221759, 1370754, 1533939, + 1712304, 1906884, 2118760, 2349060, 2598960, 2869685, + 3162510, 3478761, 3819816, 4187106, 4582116, 5006386, + 5461512, 5949147, 6471002, 7028847, 7624512, 8259888, + 8936928, 9657648, 10424128, 11238513, 12103014, 13019909 }, + { 0, 0, 0, 0, 0, 0, + 1, 7, 28, 84, 210, 462, + 924, 1716, 3003, 5005, 8008, 12376, + 18564, 27132, 38760, 54264, 74613, 100947, + 134596, 177100, 230230, 296010, 376740, 475020, + 593775, 736281, 906192, 1107568, 1344904, 1623160, + 1947792, 2324784, 2760681, 3262623, 3838380, 4496388, + 5245786, 6096454, 7059052, 8145060, 9366819, 10737573, + 12271512, 13983816, 15890700, 18009460, 20358520, 22957480, + 25827165, 28989675, 32468436, 36288252, 40475358, 45057474, + 50063860, 55525372, 61474519, 67945521, 74974368, 82598880, + 90858768, 99795696, 109453344, 119877472, 131115985, 143218999 }, + { 0, 0, 0, 0, 0, 0, + 0, 1, 8, 36, 120, 330, + 792, 1716, 3432, 6435, 11440, 19448, + 31824, 50388, 77520, 116280, 170544, 245157, + 346104, 480700, 657800, 888030, 1184040, 1560780, + 2035800, 2629575, 3365856, 4272048, 5379616, 6724520, + 8347680, 10295472, 12620256, 15380937, 18643560, 22481940, + 26978328, 32224114, 38320568, 45379620, 53524680, 62891499, + 73629072, 85900584, 99884400, 115775100, 133784560, 154143080, + 177100560, 202927725, 231917400, 264385836, 300674088, 341149446, + 386206920, 436270780, 491796152, 553270671, 621216192, 696190560, + 778789440, 869648208, 969443904, 1078897248, 1198774720, 1329890705 }, +}; + +static const int16_t dss_sp_filter_cb[14][32] = { + { -32653, -32587, -32515, -32438, -32341, -32216, -32062, -31881, + -31665, -31398, -31080, -30724, -30299, -29813, -29248, -28572, + -27674, -26439, -24666, -22466, -19433, -16133, -12218, -7783, + -2834, 1819, 6544, 11260, 16050, 20220, 24774, 28120 }, + + { -27503, -24509, -20644, -17496, -14187, -11277, -8420, -5595, + -3013, -624, 1711, 3880, 5844, 7774, 9739, 11592, + 13364, 14903, 16426, 17900, 19250, 20586, 21803, 23006, + 24142, 25249, 26275, 27300, 28359, 29249, 30118, 31183 }, + + { -27827, -24208, -20943, -17781, -14843, -11848, -9066, -6297, + -3660, -910, 1918, 5025, 8223, 11649, 15086, 18423, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -17128, -11975, -8270, -5123, -2296, 183, 2503, 4707, + 6798, 8945, 11045, 13239, 15528, 18248, 21115, 24785, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -21557, -17280, -14286, -11644, -9268, -7087, -4939, -2831, + -691, 1407, 3536, 5721, 8125, 10677, 13721, 17731, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -15030, -10377, -7034, -4327, -1900, 364, 2458, 4450, + 6422, 8374, 10374, 12486, 14714, 16997, 19626, 22954, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -16155, -12362, -9698, -7460, -5258, -3359, -1547, 219, + 1916, 3599, 5299, 6994, 8963, 11226, 13716, 16982, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -14742, -9848, -6921, -4648, -2769, -1065, 499, 2083, + 3633, 5219, 6857, 8580, 10410, 12672, 15561, 20101, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -11099, -7014, -3855, -1025, 1680, 4544, 7807, 11932, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -9060, -4570, -1381, 1419, 4034, 6728, 9865, 14149, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -12450, -7985, -4596, -1734, 961, 3629, 6865, 11142, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -11831, -7404, -4010, -1096, 1606, 4291, 7386, 11482, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -13404, -9250, -5995, -3312, -890, 1594, 4464, 8198, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + + { -11239, -7220, -4040, -1406, 971, 3321, 6006, 9697, + 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 uint16_t dss_sp_fixed_cb_gain[64] = { + 0, 4, 8, 13, 17, 22, 26, 31, + 35, 40, 44, 48, 53, 58, 63, 69, + 76, 83, 91, 99, 109, 119, 130, 142, + 155, 170, 185, 203, 222, 242, 265, 290, + 317, 346, 378, 414, 452, 494, 540, 591, + 646, 706, 771, 843, 922, 1007, 1101, 1204, + 1316, 1438, 1572, 1719, 1879, 2053, 2244, 2453, + 2682, 2931, 3204, 3502, 3828, 4184, 4574, 5000, +}; + +static const int16_t dss_sp_pulse_val[8] = { + -31182, -22273, -13364, -4455, 4455, 13364, 22273, 31182 +}; + +static const uint16_t binary_decreasing_array[] = { + 32767, 16384, 8192, 4096, 2048, 1024, 512, 256, + 128, 64, 32, 16, 8, 4, 2, +}; + +static const uint16_t dss_sp_unc_decreasing_array[] = { + 32767, 26214, 20972, 16777, 13422, 10737, 8590, 6872, + 5498, 4398, 3518, 2815, 2252, 1801, 1441, +}; + +static const uint16_t dss_sp_adaptive_gain[] = { + 102, 231, 360, 488, 617, 746, 875, 1004, + 1133, 1261, 1390, 1519, 1648, 1777, 1905, 2034, + 2163, 2292, 2421, 2550, 2678, 2807, 2936, 3065, + 3194, 3323, 3451, 3580, 3709, 3838, 3967, 4096, +}; + +static const int32_t dss_sp_sinc[67] = { + 262, 293, 323, 348, 356, 336, 269, 139, + -67, -358, -733, -1178, -1668, -2162, -2607, -2940, + -3090, -2986, -2562, -1760, -541, 1110, 3187, 5651, + 8435, 11446, 14568, 17670, 20611, 23251, 25460, 27125, + 28160, 28512, 28160, + 27125, 25460, 23251, 20611, 17670, 14568, 11446, 8435, + 5651, 3187, 1110, -541, -1760, -2562, -2986, -3090, + -2940, -2607, -2162, -1668, -1178, -733, -358, -67, + 139, 269, 336, 356, 348, 323, 293, 262, +}; + +static av_cold int dss_sp_decode_init(AVCodecContext *avctx) +{ + DssSpContext *p = avctx->priv_data; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->sample_rate = 11025; + + memset(p->history, 0, sizeof(p->history)); + p->pulse_dec_mode = 1; + + return 0; +} + +static void dss_sp_unpack_coeffs(DssSpContext *p, const uint8_t *src) +{ + GetBitContext gb; + DssSpFrame *fparam = &p->fparam; + int i; + int subframe_idx; + uint32_t combined_pitch; + uint32_t tmp; + uint32_t pitch_lag; + + for (i = 0; i < DSS_SP_FRAME_SIZE; i += 2) { + p->bits[i] = src[i + 1]; + p->bits[i + 1] = src[i]; + } + + init_get_bits(&gb, p->bits, DSS_SP_FRAME_SIZE * 8); + + for (i = 0; i < 2; i++) + fparam->filter_idx[i] = get_bits(&gb, 5); + for (; i < 8; i++) + fparam->filter_idx[i] = get_bits(&gb, 4); + for (; i < 14; i++) + fparam->filter_idx[i] = get_bits(&gb, 3); + + for (subframe_idx = 0; subframe_idx < 4; subframe_idx++) { + fparam->sf_adaptive_gain[subframe_idx] = get_bits(&gb, 5); + + fparam->sf[subframe_idx].combined_pulse_pos = get_bits_long(&gb, 31); + + fparam->sf[subframe_idx].gain = get_bits(&gb, 6); + + for (i = 0; i < 7; i++) + fparam->sf[subframe_idx].pulse_val[i] = get_bits(&gb, 3); + } + + for (subframe_idx = 0; subframe_idx < 4; subframe_idx++) { + unsigned int C72_binomials[PULSE_MAX] = { + 72, 2556, 59640, 1028790, 13991544, 156238908, 1473109704, + 3379081753 + }; + unsigned int combined_pulse_pos = + fparam->sf[subframe_idx].combined_pulse_pos; + int index = 6; + + if (combined_pulse_pos < C72_binomials[PULSE_MAX - 1]) { + if (p->pulse_dec_mode) { + int pulse, pulse_idx; + pulse = PULSE_MAX - 1; + pulse_idx = 71; + combined_pulse_pos = + fparam->sf[subframe_idx].combined_pulse_pos; + + /* this part seems to be close to g723.1 gen_fcb_excitation() + * RATE_6300 */ + + /* TODO: what is 7? size of subframe? */ + for (i = 0; i < 7; i++) { + for (; + combined_pulse_pos < + dss_sp_combinatorial_table[pulse][pulse_idx]; + --pulse_idx) + ; + combined_pulse_pos -= + dss_sp_combinatorial_table[pulse][pulse_idx]; + pulse--; + fparam->sf[subframe_idx].pulse_pos[i] = pulse_idx; + } + } + } else { + p->pulse_dec_mode = 0; + + /* why do we need this? */ + fparam->sf[subframe_idx].pulse_pos[6] = 0; + + for (i = 71; i >= 0; i--) { + if (C72_binomials[index] <= combined_pulse_pos) { + combined_pulse_pos -= C72_binomials[index]; + + fparam->sf[subframe_idx].pulse_pos[(index ^ 7) - 1] = i; + + if (!index) + break; + --index; + } + --C72_binomials[0]; + if (index) { + int a; + for (a = 0; a < index; a++) + C72_binomials[a + 1] -= C72_binomials[a]; + } + } + } + } + + combined_pitch = get_bits(&gb, 24); + + fparam->pitch_lag[0] = (combined_pitch % 151) + 36; + + combined_pitch /= 151; + + for (i = 1; i < SUBFRAMES; i++) { + fparam->pitch_lag[i] = combined_pitch % 48; + combined_pitch /= 48; + } + + pitch_lag = fparam->pitch_lag[0]; + for (i = 1; i < SUBFRAMES; i++) { + if (pitch_lag > 162) { + fparam->pitch_lag[i] += 162 - 23; + } else { + tmp = pitch_lag - 23; + if (tmp < 36) + tmp = 36; + fparam->pitch_lag[i] += tmp; + } + pitch_lag = fparam->pitch_lag[i]; + } +} + +static void dss_sp_unpack_filter(DssSpContext *p) +{ + int i; + + for (i = 0; i < 14; i++) + p->lpc_filter[i] = dss_sp_filter_cb[i][p->fparam.filter_idx[i]]; +} + +static void dss_sp_convert_coeffs(int32_t *lpc_filter, int32_t *coeffs) +{ + int a, a_plus, i; + + coeffs[0] = 0x2000; + for (a = 0; a < 14; a++) { + a_plus = a + 1; + coeffs[a_plus] = lpc_filter[a] >> 2; + if (a_plus / 2 >= 1) { + for (i = 1; i <= a_plus / 2; i++) { + int coeff_1, coeff_2, tmp; + + coeff_1 = coeffs[i]; + coeff_2 = coeffs[a_plus - i]; + + tmp = DSS_SP_FORMULA(coeff_1, lpc_filter[a], coeff_2); + coeffs[i] = av_clip_int16(tmp); + + tmp = DSS_SP_FORMULA(coeff_2, lpc_filter[a], coeff_1); + coeffs[a_plus - i] = av_clip_int16(tmp); + } + } + } +} + +static void dss_sp_add_pulses(int32_t *vector_buf, + const struct DssSpSubframe *sf) +{ + int i; + + for (i = 0; i < 7; i++) + vector_buf[sf->pulse_pos[i]] += (dss_sp_fixed_cb_gain[sf->gain] * + dss_sp_pulse_val[sf->pulse_val[i]] + + 0x4000) >> 15; +} + +static void dss_sp_gen_exc(int32_t *vector, int32_t *prev_exc, + int pitch_lag, int gain) +{ + int i; + + /* do we actually need this check? we can use just [a3 - i % a3] + * for both cases */ + if (pitch_lag < 72) + for (i = 0; i < 72; i++) + vector[i] = prev_exc[pitch_lag - i % pitch_lag]; + else + for (i = 0; i < 72; i++) + vector[i] = prev_exc[pitch_lag - i]; + + for (i = 0; i < 72; i++) { + int tmp = gain * vector[i] >> 11; + vector[i] = av_clip_int16(tmp); + } +} + +static void dss_sp_scale_vector(int32_t *vec, int bits, int size) +{ + int i; + + if (bits < 0) + for (i = 0; i < size; i++) + vec[i] = vec[i] >> -bits; + else + for (i = 0; i < size; i++) + vec[i] = vec[i] << bits; +} + +static void dss_sp_update_buf(int32_t *hist, int32_t *vector) +{ + int i; + + for (i = 114; i > 0; i--) + vector[i + 72] = vector[i]; + + for (i = 0; i < 72; i++) + vector[72 - i] = hist[i]; +} + +static void dss_sp_shift_sq_sub(const int32_t *filter_buf, + int32_t *error_buf, int32_t *dst) +{ + int a; + + for (a = 0; a < 72; a++) { + int i, tmp; + + tmp = dst[a] * filter_buf[0]; + + for (i = 14; i > 0; i--) + tmp -= error_buf[i] * filter_buf[i]; + + for (i = 14; i > 0; i--) + error_buf[i] = error_buf[i - 1]; + + tmp = (tmp + 4096) >> 13; + + error_buf[1] = tmp; + + dst[a] = av_clip_int16(tmp); + } +} + +static void dss_sp_shift_sq_add(const int32_t *filter_buf, int32_t *audio_buf, + int32_t *dst) +{ + int a; + + for (a = 0; a < 72; a++) { + int i, tmp = 0; + + audio_buf[0] = dst[a]; + + for (i = 14; i >= 0; i--) + tmp += audio_buf[i] * filter_buf[i]; + + for (i = 14; i > 0; i--) + audio_buf[i] = audio_buf[i - 1]; + + tmp = (tmp + 4096) >> 13; + + dst[a] = av_clip_int16(tmp); + } +} + +static void dss_sp_vec_mult(const int32_t *src, int32_t *dst, + const int16_t *mult) +{ + int i; + + dst[0] = src[0]; + + for (i = 1; i < 15; i++) + dst[i] = (src[i] * mult[i] + 0x4000) >> 15; +} + +static int dss_sp_get_normalize_bits(int32_t *vector_buf, int16_t size) +{ + unsigned int val; + int max_val; + int i; + + val = 1; + for (i = 0; i < size; i++) + val |= FFABS(vector_buf[i]); + + for (max_val = 0; val <= 0x4000; ++max_val) + val *= 2; + return max_val; +} + +static int dss_sp_vector_sum(DssSpContext *p, int size) +{ + int i, sum = 0; + for (i = 0; i < size; i++) + sum += FFABS(p->vector_buf[i]); + return sum; +} + +static void dss_sp_sf_synthesis(DssSpContext *p, int32_t lpc_filter, + int32_t *dst, int size) +{ + int32_t tmp_buf[15]; + int32_t noise[72]; + int bias, vsum_2 = 0, vsum_1 = 0, v36, normalize_bits; + int i, tmp; + + if (size > 0) { + vsum_1 = dss_sp_vector_sum(p, size); + + if (vsum_1 > 0xFFFFF) + vsum_1 = 0xFFFFF; + } + + normalize_bits = dss_sp_get_normalize_bits(p->vector_buf, size); + + dss_sp_scale_vector(p->vector_buf, normalize_bits - 3, size); + dss_sp_scale_vector(p->audio_buf, normalize_bits, 15); + dss_sp_scale_vector(p->err_buf1, normalize_bits, 15); + + v36 = p->err_buf1[1]; + + dss_sp_vec_mult(p->filter, tmp_buf, binary_decreasing_array); + dss_sp_shift_sq_add(tmp_buf, p->audio_buf, p->vector_buf); + + dss_sp_vec_mult(p->filter, tmp_buf, dss_sp_unc_decreasing_array); + dss_sp_shift_sq_sub(tmp_buf, p->err_buf1, p->vector_buf); + + /* lpc_filter can be negative */ + lpc_filter = lpc_filter >> 1; + if (lpc_filter >= 0) + lpc_filter = 0; + + if (size > 1) { + for (i = size - 1; i > 0; i--) { + tmp = DSS_SP_FORMULA(p->vector_buf[i], lpc_filter, + p->vector_buf[i - 1]); + p->vector_buf[i] = av_clip_int16(tmp); + } + } + + tmp = DSS_SP_FORMULA(p->vector_buf[0], lpc_filter, v36); + p->vector_buf[0] = av_clip_int16(tmp); + + dss_sp_scale_vector(p->vector_buf, -normalize_bits, size); + dss_sp_scale_vector(p->audio_buf, -normalize_bits, 15); + dss_sp_scale_vector(p->err_buf1, -normalize_bits, 15); + + if (size > 0) + vsum_2 = dss_sp_vector_sum(p, size); + + if (vsum_2 >= 0x40) + tmp = (vsum_1 << 11) / vsum_2; + else + tmp = 1; + + bias = 409 * tmp >> 15 << 15; + tmp = (bias + 32358 * p->noise_state) >> 15; + noise[0] = av_clip_int16(tmp); + + for (i = 1; i < size; i++) { + tmp = (bias + 32358 * noise[i - 1]) >> 15; + noise[i] = av_clip_int16(tmp); + } + + p->noise_state = noise[size - 1]; + for (i = 0; i < size; i++) { + tmp = (p->vector_buf[i] * noise[i]) >> 11; + dst[i] = av_clip_int16(tmp); + } +} + +static void dss_sp_update_state(DssSpContext *p, int32_t *dst) +{ + int i, offset = 6, counter = 0, a = 0; + + for (i = 0; i < 6; i++) + p->excitation[i] = p->excitation[288 + i]; + + for (i = 0; i < 72 * SUBFRAMES; i++) + p->excitation[6 + i] = dst[i]; + + do { + int tmp = 0; + + for (i = 0; i < 6; i++) + tmp += p->excitation[offset--] * dss_sp_sinc[a + i * 11]; + + offset += 7; + + tmp >>= 15; + dst[counter] = av_clip_int16(tmp); + + counter++; + + a = (a + 1) % 11; + if (!a) + offset++; + } while (offset < FF_ARRAY_ELEMS(p->excitation)); +} + +static void dss_sp_32to16bit(int16_t *dst, int32_t *src, int size) +{ + int i; + + for (i = 0; i < size; i++) + dst[i] = av_clip_int16(src[i]); +} + +static int dss_sp_decode_one_frame(DssSpContext *p, + int16_t *abuf_dst, const uint8_t *abuf_src) +{ + int i, j; + + dss_sp_unpack_coeffs(p, abuf_src); + + dss_sp_unpack_filter(p); + + dss_sp_convert_coeffs(p->lpc_filter, p->filter); + + for (j = 0; j < SUBFRAMES; j++) { + dss_sp_gen_exc(p->vector_buf, p->history, + p->fparam.pitch_lag[j], + dss_sp_adaptive_gain[p->fparam.sf_adaptive_gain[j]]); + + dss_sp_add_pulses(p->vector_buf, &p->fparam.sf[j]); + + dss_sp_update_buf(p->vector_buf, p->history); + + for (i = 0; i < 72; i++) + p->vector_buf[i] = p->history[72 - i]; + + dss_sp_shift_sq_sub(p->filter, + p->err_buf2, p->vector_buf); + + dss_sp_sf_synthesis(p, p->lpc_filter[0], + &p->working_buffer[j][0], 72); + } + + dss_sp_update_state(p, &p->working_buffer[0][0]); + + dss_sp_32to16bit(abuf_dst, + &p->working_buffer[0][0], 264); + return 0; +} + +static int dss_sp_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + DssSpContext *p = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + + int16_t *out; + int ret; + + if (buf_size < DSS_SP_FRAME_SIZE) { + if (buf_size) + av_log(avctx, AV_LOG_WARNING, + "Expected %d bytes, got %d - skipping packet.\n", + DSS_SP_FRAME_SIZE, buf_size); + *got_frame_ptr = 0; + return AVERROR_INVALIDDATA; + } + + frame->nb_samples = DSS_SP_SAMPLE_COUNT; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); + return ret; + } + + out = (int16_t *)frame->data[0]; + + dss_sp_decode_one_frame(p, out, buf); + + *got_frame_ptr = 1; + + return DSS_SP_FRAME_SIZE; +} + +AVCodec ff_dss_sp_decoder = { + .name = "dss_sp", + .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DSS_SP, + .priv_data_size = sizeof(DssSpContext), + .init = dss_sp_decode_init, + .decode = dss_sp_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, +}; diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c index 17d9434..c960d6a 100644 --- a/libavcodec/dump_extradata_bsf.c +++ b/libavcodec/dump_extradata_bsf.c @@ -21,33 +21,81 @@ #include #include "avcodec.h" +#include "bsf.h" + +#include "libavutil/log.h" #include "libavutil/mem.h" +#include "libavutil/opt.h" + +enum DumpFreq { + DUMP_FREQ_KEYFRAME, + DUMP_FREQ_ALL, +}; + +typedef struct DumpExtradataContext { + const AVClass *class; + int freq; +} DumpExtradataContext; + +static int dump_extradata(AVBSFContext *ctx, AVPacket *out) +{ + DumpExtradataContext *s = ctx->priv_data; + AVPacket *in; + int ret = 0; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (ctx->par_in->extradata && + (s->freq == DUMP_FREQ_ALL || + (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY))) { + if (in->size >= INT_MAX - ctx->par_in->extradata_size) { + ret = AVERROR(ERANGE); + goto fail; + } + ret = av_new_packet(out, in->size + ctx->par_in->extradata_size); + if (ret < 0) + goto fail; -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; + ret = av_packet_copy_props(out, in); + if (ret < 0) { + av_packet_unref(out); + goto fail; } + + memcpy(out->data, ctx->par_in->extradata, ctx->par_in->extradata_size); + memcpy(out->data + ctx->par_in->extradata_size, in->data, in->size); + } else { + av_packet_move_ref(out, in); } - return 0; + +fail: + av_packet_free(&in); + + return ret; } -AVBitStreamFilter ff_dump_extradata_bsf={ - "dump_extra", - 0, - dump_extradata, +#define OFFSET(x) offsetof(DumpExtradataContext, x) +static const AVOption options[] = { + { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT, + { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" }, + { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" }, + { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .unit = "freq" }, + { NULL }, +}; + +static const AVClass dump_extradata_class = { + .class_name = "dump_extradata bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_MAJOR, +}; + +const AVBitStreamFilter ff_dump_extradata_bsf = { + .name = "dump_extra", + .priv_data_size = sizeof(DumpExtradataContext), + .priv_class = &dump_extradata_class, + .filter = dump_extradata, }; diff --git a/libavcodec/dv.c b/libavcodec/dv.c index e05c878..52a015e 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -40,128 +40,134 @@ #include "libavutil/internal.h" #include "libavutil/pixdesc.h" + #include "avcodec.h" -#include "get_bits.h" +#include "dv.h" +#include "dvdata.h" #include "internal.h" #include "put_bits.h" #include "simple_idct.h" -#include "dvdata.h" -#include "dv.h" /* XXX: also include quantization */ RL_VLC_ELEM ff_dv_rl_vlc[1184]; -static inline void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, int seq, int slot, - uint16_t *tbl) +static inline void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, + int seq, int slot, uint16_t *tbl) { - static const uint8_t off[] = { 2, 6, 8, 0, 4 }; + static const uint8_t off[] = { 2, 6, 8, 0, 4 }; static const uint8_t shuf1[] = { 36, 18, 54, 0, 72 }; static const uint8_t shuf2[] = { 24, 12, 36, 0, 48 }; - static const uint8_t shuf3[] = { 18, 9, 27, 0, 36 }; + static const uint8_t shuf3[] = { 18, 9, 27, 0, 36 }; - static const uint8_t l_start[] = {0, 4, 9, 13, 18, 22, 27, 31, 36, 40}; + static const uint8_t l_start[] = { 0, 4, 9, 13, 18, 22, 27, 31, 36, 40 }; static const uint8_t l_start_shuffled[] = { 9, 4, 13, 0, 18 }; - static const uint8_t serpent1[] = {0, 1, 2, 2, 1, 0, - 0, 1, 2, 2, 1, 0, - 0, 1, 2, 2, 1, 0, - 0, 1, 2, 2, 1, 0, - 0, 1, 2}; - static const uint8_t serpent2[] = {0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, - 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, - 0, 1, 2, 3, 4, 5}; - - static const uint8_t remap[][2] = {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, /* dummy */ - { 0, 0}, { 0, 1}, { 0, 2}, { 0, 3}, {10, 0}, - {10, 1}, {10, 2}, {10, 3}, {20, 0}, {20, 1}, - {20, 2}, {20, 3}, {30, 0}, {30, 1}, {30, 2}, - {30, 3}, {40, 0}, {40, 1}, {40, 2}, {40, 3}, - {50, 0}, {50, 1}, {50, 2}, {50, 3}, {60, 0}, - {60, 1}, {60, 2}, {60, 3}, {70, 0}, {70, 1}, - {70, 2}, {70, 3}, { 0,64}, { 0,65}, { 0,66}, - {10,64}, {10,65}, {10,66}, {20,64}, {20,65}, - {20,66}, {30,64}, {30,65}, {30,66}, {40,64}, - {40,65}, {40,66}, {50,64}, {50,65}, {50,66}, - {60,64}, {60,65}, {60,66}, {70,64}, {70,65}, - {70,66}, { 0,67}, {20,67}, {40,67}, {60,67}}; + static const uint8_t serpent1[] = { + 0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2 + }; + static const uint8_t serpent2[] = { + 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5 + }; + + static const uint8_t remap[][2] = { + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* dummy */ + { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 10, 0 }, + { 10, 1 }, { 10, 2 }, { 10, 3 }, { 20, 0 }, { 20, 1 }, + { 20, 2 }, { 20, 3 }, { 30, 0 }, { 30, 1 }, { 30, 2 }, + { 30, 3 }, { 40, 0 }, { 40, 1 }, { 40, 2 }, { 40, 3 }, + { 50, 0 }, { 50, 1 }, { 50, 2 }, { 50, 3 }, { 60, 0 }, + { 60, 1 }, { 60, 2 }, { 60, 3 }, { 70, 0 }, { 70, 1 }, + { 70, 2 }, { 70, 3 }, { 0, 64 }, { 0, 65 }, { 0, 66 }, + { 10, 64 }, { 10, 65 }, { 10, 66 }, { 20, 64 }, { 20, 65 }, + { 20, 66 }, { 30, 64 }, { 30, 65 }, { 30, 66 }, { 40, 64 }, + { 40, 65 }, { 40, 66 }, { 50, 64 }, { 50, 65 }, { 50, 66 }, + { 60, 64 }, { 60, 65 }, { 60, 66 }, { 70, 64 }, { 70, 65 }, + { 70, 66 }, { 0, 67 }, { 20, 67 }, { 40, 67 }, { 60, 67 } + }; int i, k, m; int x, y, blk; - for (m=0; m<5; m++) { - switch (d->width) { - case 1440: - blk = (chan*11+seq)*27+slot; - - if (chan == 0 && seq == 11) { - x = m*27+slot; - if (x<90) { - y = 0; - } else { - x = (x - 90)*2; - y = 67; - } - } else { - i = (4*chan + blk + off[m])%11; - k = (blk/11)%27; - - x = shuf1[m] + (chan&1)*9 + k%9; - y = (i*3+k/9)*2 + (chan>>1) + 1; - } - tbl[m] = (x<<1)|(y<<9); - break; - case 1280: - blk = (chan*10+seq)*27+slot; - - i = (4*chan + (seq/5) + 2*blk + off[m])%10; - k = (blk/5)%27; - - x = shuf1[m]+(chan&1)*9 + k%9; - y = (i*3+k/9)*2 + (chan>>1) + 4; - - if (x >= 80) { - x = remap[y][0]+((x-80)<<(y>59)); - y = remap[y][1]; - } - tbl[m] = (x<<1)|(y<<9); - break; - case 960: - blk = (chan*10+seq)*27+slot; - - i = (4*chan + (seq/5) + 2*blk + off[m])%10; - k = (blk/5)%27 + (i&1)*3; - - x = shuf2[m] + k%6 + 6*(chan&1); - y = l_start[i] + k/6 + 45*(chan>>1); - tbl[m] = (x<<1)|(y<<9); - break; + for (m = 0; m < 5; m++) { + switch (d->width) { + case 1440: + blk = (chan * 11 + seq) * 27 + slot; + + if (chan == 0 && seq == 11) { + x = m * 27 + slot; + if (x < 90) { + y = 0; + } else { + x = (x - 90) * 2; + y = 67; + } + } else { + i = (4 * chan + blk + off[m]) % 11; + k = (blk / 11) % 27; + + x = shuf1[m] + (chan & 1) * 9 + k % 9; + y = (i * 3 + k / 9) * 2 + (chan >> 1) + 1; + } + tbl[m] = (x << 1) | (y << 9); + break; + case 1280: + blk = (chan * 10 + seq) * 27 + slot; + + i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10; + k = (blk / 5) % 27; + + x = shuf1[m] + (chan & 1) * 9 + k % 9; + y = (i * 3 + k / 9) * 2 + (chan >> 1) + 4; + + if (x >= 80) { + x = remap[y][0] + ((x - 80) << (y > 59)); + y = remap[y][1]; + } + tbl[m] = (x << 1) | (y << 9); + break; + case 960: + blk = (chan * 10 + seq) * 27 + slot; + + i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10; + k = (blk / 5) % 27 + (i & 1) * 3; + + x = shuf2[m] + k % 6 + 6 * (chan & 1); + y = l_start[i] + k / 6 + 45 * (chan >> 1); + tbl[m] = (x << 1) | (y << 9); + break; case 720: - switch (d->pix_fmt) { - case AV_PIX_FMT_YUV422P: - x = shuf3[m] + slot/3; - y = serpent1[slot] + - ((((seq + off[m]) % d->difseg_size)<<1) + chan)*3; - tbl[m] = (x<<1)|(y<<8); - break; - case AV_PIX_FMT_YUV420P: - x = shuf3[m] + slot/3; - y = serpent1[slot] + - ((seq + off[m]) % d->difseg_size)*3; - tbl[m] = (x<<1)|(y<<9); - break; - case AV_PIX_FMT_YUV411P: - i = (seq + off[m]) % d->difseg_size; - k = slot + ((m==1||m==2)?3:0); - - x = l_start_shuffled[m] + k/6; - y = serpent2[k] + i*6; - if (x>21) - y = y*2 - i*6; - tbl[m] = (x<<2)|(y<<8); - break; - } + switch (d->pix_fmt) { + case AV_PIX_FMT_YUV422P: + x = shuf3[m] + slot / 3; + y = serpent1[slot] + + ((((seq + off[m]) % d->difseg_size) << 1) + chan) * 3; + tbl[m] = (x << 1) | (y << 8); + break; + case AV_PIX_FMT_YUV420P: + x = shuf3[m] + slot / 3; + y = serpent1[slot] + + ((seq + off[m]) % d->difseg_size) * 3; + tbl[m] = (x << 1) | (y << 9); + break; + case AV_PIX_FMT_YUV411P: + i = (seq + off[m]) % d->difseg_size; + k = slot + ((m == 1 || m == 2) ? 3 : 0); + + x = l_start_shuffled[m] + k / 6; + y = serpent2[k] + i * 6; + if (x > 21) + y = y * 2 - i * 6; + tbl[m] = (x << 2) | (y << 8); + break; + } default: - break; + break; } } } @@ -173,11 +179,11 @@ static const uint8_t dv100_qstep[16] = { 2, 3, 4, 5, 6, 7, 8, 16, 18, 20, 22, 24, 28, 52 }; -static const uint8_t dv_quant_areas[4] = { 6, 21, 43, 64 }; +static const uint8_t dv_quant_areas[4] = { 6, 21, 43, 64 }; int ff_dv_init_dynamic_tables(DVVideoContext *ctx, const AVDVProfile *d) { - int j,i,c,s,p; + int j, i, c, s, p; uint32_t *factor1, *factor2; const int *iweight1, *iweight2; @@ -189,8 +195,8 @@ int ff_dv_init_dynamic_tables(DVVideoContext *ctx, const AVDVProfile *d) p += !(j % 3); if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) && !(DV_PROFILE_IS_720p50(d) && s > 9)) { - dv_calc_mb_coordinates(d, c, s, j, &ctx->work_chunks[i].mb_coordinates[0]); - ctx->work_chunks[i++].buf_offset = p; + dv_calc_mb_coordinates(d, c, s, j, &ctx->work_chunks[i].mb_coordinates[0]); + ctx->work_chunks[i++].buf_offset = p; } p += 5; } @@ -240,10 +246,10 @@ av_cold int ff_dvvideo_init(AVCodecContext *avctx) 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]; + 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; @@ -267,21 +273,21 @@ av_cold int ff_dvvideo_init(AVCodecContext *avctx) } /* 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); + * 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); assert(dv_vlc.table_size == 1184); - for (i = 0; i < dv_vlc.table_size; i++){ + 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 + if (len < 0) { // more bits needed run = 0; level = code; } else { - run = new_dv_vlc_run [code] + 1; + run = new_dv_vlc_run[code] + 1; level = new_dv_vlc_level[code]; } ff_dv_rl_vlc[i].len = len; diff --git a/libavcodec/dv.h b/libavcodec/dv.h index 019c15a..1d1650c 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -28,22 +28,22 @@ #define AVCODEC_DV_H #include "avcodec.h" -#include "me_cmp.h" -#include "get_bits.h" #include "dv_profile.h" +#include "me_cmp.h" +#include "vlc.h" typedef struct DVwork_chunk { - uint16_t buf_offset; - uint16_t mb_coordinates[5]; + uint16_t buf_offset; + uint16_t mb_coordinates[5]; } DVwork_chunk; typedef struct DVVideoContext { const AVDVProfile *sys; - AVFrame *frame; + const AVFrame *frame; AVCodecContext *avctx; uint8_t *buf; - uint8_t dv_zigzag[2][64]; + uint8_t dv_zigzag[2][64]; void (*get_pixels)(int16_t *block, const uint8_t *pixels, int line_size); void (*fdct[2])(int16_t *block); @@ -54,26 +54,26 @@ typedef struct DVVideoContext { } DVVideoContext; enum dv_section_type { - dv_sect_header = 0x1f, - dv_sect_subcode = 0x3f, - dv_sect_vaux = 0x56, - dv_sect_audio = 0x76, - dv_sect_video = 0x96, + 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, + 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, }; #define DV_PROFILE_IS_HD(p) ((p)->video_stype & 0x10) @@ -81,8 +81,8 @@ enum dv_pack_type { #define DV_PROFILE_IS_720p50(p) (((p)->video_stype == 0x18) && ((p)->dsf == 1)) /* 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 */ + * determine the profile */ +#define DV_PROFILE_BYTES (6 * 80) /* 6 DIF blocks */ /** * largest possible DV frame, in bytes (1080i50) @@ -103,23 +103,26 @@ int ff_dvvideo_init(AVCodecContext *avctx); static inline int dv_work_pool_size(const AVDVProfile *d) { - int size = d->n_difchan*d->difseg_size*27; + int size = d->n_difchan * d->difseg_size * 27; if (DV_PROFILE_IS_1080i50(d)) - size -= 3*27; + size -= 3 * 27; if (DV_PROFILE_IS_720p50(d)) - size -= 4*27; + size -= 4 * 27; return size; } -static inline void dv_calculate_mb_xy(DVVideoContext *s, DVwork_chunk *work_chunk, int m, int *mb_x, int *mb_y) +static inline void dv_calculate_mb_xy(DVVideoContext *s, + DVwork_chunk *work_chunk, + int m, int *mb_x, int *mb_y) { - *mb_x = work_chunk->mb_coordinates[m] & 0xff; - *mb_y = work_chunk->mb_coordinates[m] >> 8; - - /* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */ - if (s->sys->height == 720 && !(s->buf[1]&0x0C)) { - *mb_y -= (*mb_y>17)?18:-72; /* shifting the Y coordinate down by 72/2 macro blocks */ - } + *mb_x = work_chunk->mb_coordinates[m] & 0xff; + *mb_y = work_chunk->mb_coordinates[m] >> 8; + + /* We work with 720p frames split in half. + * The odd half-frame (chan == 2,3) is displaced :-( */ + if (s->sys->height == 720 && !(s->buf[1] & 0x0C)) + /* shifting the Y coordinate down by 72/2 macro blocks */ + *mb_y -= (*mb_y > 17) ? 18 : -72; } #endif /* AVCODEC_DV_H */ diff --git a/libavcodec/dv_profile.c b/libavcodec/dv_profile.c index f3cf86f..74c529d 100644 --- a/libavcodec/dv_profile.c +++ b/libavcodec/dv_profile.c @@ -16,13 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include "config.h" +#include + #include "libavutil/common.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" + #include "avcodec.h" #include "dv_profile.h" #include "dv_profile_internal.h" @@ -30,33 +31,33 @@ #if CONFIG_DVPROFILE static const uint8_t dv_audio_shuffle525[10][9] = { - { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ - { 6, 36, 66, 26, 56, 86, 16, 46, 76 }, - { 12, 42, 72, 2, 32, 62, 22, 52, 82 }, - { 18, 48, 78, 8, 38, 68, 28, 58, 88 }, - { 24, 54, 84, 14, 44, 74, 4, 34, 64 }, + { 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 }, + { 1, 31, 61, 21, 51, 81, 11, 41, 71 }, /* 2nd channel */ + { 7, 37, 67, 27, 57, 87, 17, 47, 77 }, + { 13, 43, 73, 3, 33, 63, 23, 53, 83 }, + { 19, 49, 79, 9, 39, 69, 29, 59, 89 }, + { 25, 55, 85, 15, 45, 75, 5, 35, 65 }, }; static const uint8_t dv_audio_shuffle625[12][9] = { - { 0, 36, 72, 26, 62, 98, 16, 52, 88}, /* 1st channel */ - { 6, 42, 78, 32, 68, 104, 22, 58, 94}, - { 12, 48, 84, 2, 38, 74, 28, 64, 100}, - { 18, 54, 90, 8, 44, 80, 34, 70, 106}, - { 24, 60, 96, 14, 50, 86, 4, 40, 76}, - { 30, 66, 102, 20, 56, 92, 10, 46, 82}, + { 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}, + { 1, 37, 73, 27, 63, 99, 17, 53, 89 }, /* 2nd channel */ + { 7, 43, 79, 33, 69, 105, 23, 59, 95 }, + { 13, 49, 85, 3, 39, 75, 29, 65, 101 }, + { 19, 55, 91, 9, 45, 81, 35, 71, 107 }, + { 25, 61, 97, 15, 51, 87, 5, 41, 77 }, + { 31, 67, 103, 21, 57, 93, 11, 47, 83 }, }; /* macroblock bit budgets */ @@ -69,186 +70,176 @@ static const uint8_t block_sizes_dv100[8] = { }; static const AVDVProfile dv_profiles[] = { - { .dsf = 0, - .video_stype = 0x0, - .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ - .difseg_size = 10, - .n_difchan = 1, - .time_base = { 1001, 30000 }, - .ltc_divisor = 30, - .height = 480, - .width = 720, - .sar = {{8, 9}, {32, 27}}, - .pix_fmt = AV_PIX_FMT_YUV411P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 90, + { .dsf = 0, + .video_stype = 0x0, + .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ + .difseg_size = 10, + .n_difchan = 1, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 480, + .width = 720, + .sar = { { 8, 9 }, { 32, 27 } }, + .pix_fmt = AV_PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ - .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ - .audio_shuffle = dv_audio_shuffle525, - }, - { .dsf = 1, - .video_stype = 0x0, - .frame_size = 144000, /* IEC 61834 - 625/50 (PAL) */ - .difseg_size = 12, - .n_difchan = 1, - .time_base = { 1, 25 }, - .ltc_divisor = 25, - .height = 576, - .width = 720, - .sar = {{16, 15}, {64, 45}}, - .pix_fmt = AV_PIX_FMT_YUV420P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 108, + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, }, + { .dsf = 1, + .video_stype = 0x0, + .frame_size = 144000, /* IEC 61834 - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = { { 16, 15 }, { 64, 45 } }, + .pix_fmt = AV_PIX_FMT_YUV420P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - }, - { .dsf = 1, - .video_stype = 0x0, - .frame_size = 144000, /* SMPTE-314M - 625/50 (PAL) */ - .difseg_size = 12, - .n_difchan = 1, - .time_base = { 1, 25 }, - .ltc_divisor = 25, - .height = 576, - .width = 720, - .sar = {{16, 15}, {64, 45}}, - .pix_fmt = AV_PIX_FMT_YUV411P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 108, + .audio_shuffle = dv_audio_shuffle625, }, + { .dsf = 1, + .video_stype = 0x0, + .frame_size = 144000, /* SMPTE-314M - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = { { 16, 15 }, { 64, 45 } }, + .pix_fmt = AV_PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - }, - { .dsf = 0, - .video_stype = 0x4, - .frame_size = 240000, /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */ - .difseg_size = 10, /* also known as "DVCPRO50" */ - .n_difchan = 2, - .time_base = { 1001, 30000 }, - .ltc_divisor = 30, - .height = 480, - .width = 720, - .sar = {{8, 9}, {32, 27}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 90, + .audio_shuffle = dv_audio_shuffle625, }, + { .dsf = 0, + .video_stype = 0x4, + .frame_size = 240000, /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO50" */ + .n_difchan = 2, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 480, + .width = 720, + .sar = { { 8, 9 }, { 32, 27 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ - .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ - .audio_shuffle = dv_audio_shuffle525, - }, - { .dsf = 1, - .video_stype = 0x4, - .frame_size = 288000, /* SMPTE-314M - 625/50 (PAL) 50 Mbps */ - .difseg_size = 12, /* also known as "DVCPRO50" */ - .n_difchan = 2, - .time_base = { 1, 25 }, - .ltc_divisor = 25, - .height = 576, - .width = 720, - .sar = {{16, 15}, {64, 45}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 108, + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, }, + { .dsf = 1, + .video_stype = 0x4, + .frame_size = 288000, /* SMPTE-314M - 625/50 (PAL) 50 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO50" */ + .n_difchan = 2, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = { { 16, 15 }, { 64, 45 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - }, - { .dsf = 0, - .video_stype = 0x14, - .frame_size = 480000, /* SMPTE-370M - 1080i60 100 Mbps */ - .difseg_size = 10, /* also known as "DVCPRO HD" */ - .n_difchan = 4, - .time_base = { 1001, 30000 }, - .ltc_divisor = 30, - .height = 1080, - .width = 1280, - .sar = {{1, 1}, {3, 2}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 8, - .block_sizes = block_sizes_dv100, - .audio_stride = 90, + .audio_shuffle = dv_audio_shuffle625, }, + { .dsf = 0, + .video_stype = 0x14, + .frame_size = 480000, /* SMPTE-370M - 1080i60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 1080, + .width = 1280, + .sar = { { 1, 1 }, { 3, 2 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ - .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ - .audio_shuffle = dv_audio_shuffle525, - }, - { .dsf = 1, - .video_stype = 0x14, - .frame_size = 576000, /* SMPTE-370M - 1080i50 100 Mbps */ - .difseg_size = 12, /* also known as "DVCPRO HD" */ - .n_difchan = 4, - .time_base = { 1, 25 }, - .ltc_divisor = 25, - .height = 1080, - .width = 1440, - .sar = {{1, 1}, {4, 3}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 8, - .block_sizes = block_sizes_dv100, - .audio_stride = 108, + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, }, + { .dsf = 1, + .video_stype = 0x14, + .frame_size = 576000, /* SMPTE-370M - 1080i50 100 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 1080, + .width = 1440, + .sar = { { 1, 1 }, { 4, 3 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - }, - { .dsf = 0, - .video_stype = 0x18, - .frame_size = 240000, /* SMPTE-370M - 720p60 100 Mbps */ - .difseg_size = 10, /* also known as "DVCPRO HD" */ - .n_difchan = 2, - .time_base = { 1001, 60000 }, - .ltc_divisor = 60, - .height = 720, - .width = 960, - .sar = {{1, 1}, {4, 3}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 8, - .block_sizes = block_sizes_dv100, - .audio_stride = 90, + .audio_shuffle = dv_audio_shuffle625, }, + { .dsf = 0, + .video_stype = 0x18, + .frame_size = 240000, /* SMPTE-370M - 720p60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 2, + .time_base = { 1001, 60000 }, + .ltc_divisor = 60, + .height = 720, + .width = 960, + .sar = { { 1, 1 }, { 4, 3 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ - .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ - .audio_shuffle = dv_audio_shuffle525, - }, - { .dsf = 1, - .video_stype = 0x18, - .frame_size = 288000, /* SMPTE-370M - 720p50 100 Mbps */ - .difseg_size = 12, /* also known as "DVCPRO HD" */ - .n_difchan = 2, - .time_base = { 1, 50 }, - .ltc_divisor = 50, - .height = 720, - .width = 960, - .sar = {{1, 1}, {4, 3}}, - .pix_fmt = AV_PIX_FMT_YUV422P, - .bpm = 8, - .block_sizes = block_sizes_dv100, - .audio_stride = 90, + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, }, + { .dsf = 1, + .video_stype = 0x18, + .frame_size = 288000, /* SMPTE-370M - 720p50 100 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO HD" */ + .n_difchan = 2, + .time_base = { 1, 50 }, + .ltc_divisor = 50, + .height = 720, + .width = 960, + .sar = { { 1, 1 }, { 4, 3 } }, + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - }, - { .dsf = 1, - .video_stype = 0x1, - .frame_size = 144000, /* IEC 61883-5 - 625/50 (PAL) */ - .difseg_size = 12, - .n_difchan = 1, - .time_base = { 1, 25 }, - .ltc_divisor = 25, - .height = 576, - .width = 720, - .sar = {{16, 15}, {64, 45}}, - .pix_fmt = AV_PIX_FMT_YUV420P, - .bpm = 6, - .block_sizes = block_sizes_dv2550, - .audio_stride = 108, + .audio_shuffle = dv_audio_shuffle625, }, + { .dsf = 1, + .video_stype = 0x1, + .frame_size = 144000, /* IEC 61883-5 - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = { { 16, 15 }, { 64, 45 } }, + .pix_fmt = AV_PIX_FMT_YUV420P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, - .audio_shuffle = dv_audio_shuffle625, - } + .audio_shuffle = dv_audio_shuffle625, } }; void ff_dv_print_profiles(void *logctx, int loglevel) @@ -256,8 +247,9 @@ void ff_dv_print_profiles(void *logctx, int loglevel) int i; for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) { const AVDVProfile *p = &dv_profiles[i]; - av_log(logctx, loglevel, "Frame size: %dx%d; pixel format: %s, " - "framerate: %d/%d\n", p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), + av_log(logctx, loglevel, + "Frame size: %dx%d; pixel format: %s, framerate: %d/%d\n", + p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), p->time_base.den, p->time_base.num); } } @@ -265,7 +257,7 @@ void ff_dv_print_profiles(void *logctx, int loglevel) #endif /* CONFIG_DVPROFILE */ const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, - const uint8_t* frame, unsigned buf_size) + const uint8_t *frame, unsigned buf_size) { #if CONFIG_DVPROFILE int i, dsf, stype; @@ -273,13 +265,12 @@ const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, if (buf_size < 80 * 5 + 48 + 4) return NULL; - dsf = (frame[3] & 0x80) >> 7; + dsf = (frame[3] & 0x80) >> 7; stype = frame[80 * 5 + 48 + 3] & 0x1f; /* 576i50 25Mbps 4:1:1 is a special case */ - if (dsf == 1 && stype == 0 && frame[4] & 0x07 /* the APT field */) { + if (dsf == 1 && stype == 0 && frame[4] & 0x07 /* the APT field */) return &dv_profiles[2]; - } for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) if (dsf == dv_profiles[i].dsf && stype == dv_profiles[i].video_stype) @@ -299,11 +290,11 @@ const AVDVProfile *av_dv_codec_profile(int width, int height, #if CONFIG_DVPROFILE int i; - for (i=0; i= DV_VLC_MAP_RUN_SIZE) - continue; + if (ff_dv_vlc_run[i] >= DV_VLC_MAP_RUN_SIZE) + continue; #if CONFIG_SMALL - if (ff_dv_vlc_level[i] >= DV_VLC_MAP_LEV_SIZE) - continue; + if (ff_dv_vlc_level[i] >= DV_VLC_MAP_LEV_SIZE) + continue; #endif - if (dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].size != 0) - continue; + if (dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].size != 0) + continue; - dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].vlc = - ff_dv_vlc_bits[i] << (!!ff_dv_vlc_level[i]); - dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].size = - ff_dv_vlc_len[i] + (!!ff_dv_vlc_level[i]); + dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].vlc = + ff_dv_vlc_bits[i] << (!!ff_dv_vlc_level[i]); + dv_vlc_map[ff_dv_vlc_run[i]][ff_dv_vlc_level[i]].size = + ff_dv_vlc_len[i] + (!!ff_dv_vlc_level[i]); } for (i = 0; i < DV_VLC_MAP_RUN_SIZE; i++) { #if CONFIG_SMALL - for (j = 1; j < DV_VLC_MAP_LEV_SIZE; j++) { - if (dv_vlc_map[i][j].size == 0) { - dv_vlc_map[i][j].vlc = dv_vlc_map[0][j].vlc | - (dv_vlc_map[i-1][0].vlc << (dv_vlc_map[0][j].size)); - dv_vlc_map[i][j].size = dv_vlc_map[i-1][0].size + - dv_vlc_map[0][j].size; - } - } + 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; - } + 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 } } diff --git a/libavcodec/dvbsub.c b/libavcodec/dvbsub.c index 720e786..548bae1 100644 --- a/libavcodec/dvbsub.c +++ b/libavcodec/dvbsub.c @@ -262,7 +262,7 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s, *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ { int a, r, g, b; - uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i]; + uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i]; a = (x >> 24) & 0xff; r = (x >> 16) & 0xff; g = (x >> 8) & 0xff; @@ -359,10 +359,10 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s, dvb_encode_rle = dvb_encode_rle4; top_ptr = q; - dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2, + dvb_encode_rle(&q, h->rects[object_id]->data[0], h->rects[object_id]->w * 2, h->rects[object_id]->w, h->rects[object_id]->h >> 1); bottom_ptr = q; - dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w, + dvb_encode_rle(&q, h->rects[object_id]->data[0] + h->rects[object_id]->w, h->rects[object_id]->w * 2, h->rects[object_id]->w, h->rects[object_id]->h >> 1); diff --git a/libavcodec/dvbsub_parser.c b/libavcodec/dvbsub_parser.c index 295e03b..5afdc4b 100644 --- a/libavcodec/dvbsub_parser.c +++ b/libavcodec/dvbsub_parser.c @@ -18,8 +18,15 @@ * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + #include "avcodec.h" -#include "get_bits.h" +#include "internal.h" /* Parser (mostly) copied from dvdsub.c */ @@ -51,18 +58,18 @@ static int dvbsub_parse(AVCodecParserContext *s, uint8_t *p, *p_end; int i, len, buf_pos = 0; - av_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", + ff_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]); for (i=0; i < buf_size; i++) { - av_dlog(avctx, "%02x ", buf[i]); + ff_dlog(avctx, "%02x ", buf[i]); if (i % 16 == 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); } if (i % 16 != 0) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); *poutbuf = NULL; *poutbuf_size = 0; @@ -73,7 +80,7 @@ static int dvbsub_parse(AVCodecParserContext *s, { if (pc->packet_index != pc->packet_start) { - av_dlog(avctx, "Discarding %d bytes\n", + ff_dlog(avctx, "Discarding %d bytes\n", pc->packet_index - pc->packet_start); } @@ -81,7 +88,7 @@ static int dvbsub_parse(AVCodecParserContext *s, pc->packet_index = 0; if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) { - av_dlog(avctx, "Bad packet header\n"); + ff_dlog(avctx, "Bad packet header\n"); return -1; } @@ -138,7 +145,7 @@ static int dvbsub_parse(AVCodecParserContext *s, } else if (*p == 0xff) { if (p + 1 < p_end) { - av_dlog(avctx, "Junk at end of packet\n"); + ff_dlog(avctx, "Junk at end of packet\n"); } pc->packet_index = p - pc->packet_buf; pc->in_packet = 0; diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 1dcefae..ccdfc01 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "internal.h" #include "libavutil/colorspace.h" #define DVBSUB_PAGE_SEGMENT 0x10 @@ -34,65 +35,7 @@ #define cm (ff_crop_tab + MAX_NEG_CROP) #ifdef DEBUG -#if 0 -static void png_save(const char *filename, uint8_t *bitmap, int w, int h, - uint32_t *rgba_palette) -{ - int x, y, v; - FILE *f; - char fname[40], fname2[40]; - char command[1024]; - - snprintf(fname, 40, "%s.ppm", filename); - - f = fopen(fname, "w"); - if (!f) { - perror(fname); - return; - } - fprintf(f, "P6\n" - "%d %d\n" - "%d\n", - w, h, 255); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - v = rgba_palette[bitmap[y * w + x]]; - putc((v >> 16) & 0xff, f); - putc((v >> 8) & 0xff, f); - putc((v >> 0) & 0xff, f); - } - } - fclose(f); - - - snprintf(fname2, 40, "%s-a.pgm", filename); - - f = fopen(fname2, "w"); - if (!f) { - perror(fname2); - return; - } - fprintf(f, "P5\n" - "%d %d\n" - "%d\n", - w, h, 255); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - v = rgba_palette[bitmap[y * w + x]]; - putc((v >> 24) & 0xff, f); - } - } - fclose(f); - - snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename); - system(command); - - snprintf(command, 1024, "rm %s %s", fname, fname2); - system(command); -} -#endif - -static void png_save2(const char *filename, uint32_t *bitmap, int w, int h) +static void png_save(const char *filename, uint32_t *bitmap, int w, int h) { int x, y, v; FILE *f; @@ -343,7 +286,7 @@ static void delete_state(DVBSubContext *ctx) /* Should already be null */ if (ctx->object_list) - av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n"); + av_log(NULL, AV_LOG_ERROR, "Memory deallocation error!\n"); } static av_cold int dvbsub_init_decoder(AVCodecContext *avctx) @@ -538,7 +481,7 @@ static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len, } if (get_bits(&gb, 6)) - av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + av_log(NULL, AV_LOG_ERROR, "DVBSub error: line overflow\n"); (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; @@ -659,7 +602,7 @@ static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len, } if (get_bits(&gb, 8)) - av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + av_log(NULL, AV_LOG_ERROR, "DVBSub error: line overflow\n"); (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; @@ -693,32 +636,25 @@ static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len, if (run_length == 0) { return pixels_read; } - - if (map_table) - bits = map_table[0]; - else - bits = 0; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } } else { bits = *(*srcbuf)++; if (non_mod == 1 && bits == 1) pixels_read += run_length; - if (map_table) - bits = map_table[bits]; - else while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } + } + if (map_table) + bits = map_table[0]; + else + bits = 0; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; } } } if (*(*srcbuf)++) - av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + av_log(NULL, AV_LOG_ERROR, "DVBSub error: line overflow\n"); return pixels_read; } @@ -742,20 +678,20 @@ static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDis 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; uint8_t *map_table; - av_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size, + ff_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size, top_bottom ? "bottom" : "top"); for (i = 0; i < buf_size; i++) { if (i % 16 == 0) - av_dlog(avctx, "0x%8p: ", buf+i); + ff_dlog(avctx, "0x%8p: ", buf+i); - av_dlog(avctx, "%02x ", buf[i]); + ff_dlog(avctx, "%02x ", buf[i]); if (i % 16 == 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); } if (i % 16) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); if (region == 0) return; @@ -839,8 +775,8 @@ static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDis } -static void dvbsub_parse_object_segment(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) +static int dvbsub_parse_object_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) { DVBSubContext *ctx = avctx->priv_data; @@ -859,7 +795,7 @@ static void dvbsub_parse_object_segment(AVCodecContext *avctx, object = get_object(ctx, object_id); if (!object) - return; + return AVERROR_INVALIDDATA; coding_method = ((*buf) >> 2) & 3; non_modifying_color = ((*buf++) >> 1) & 1; @@ -872,7 +808,7 @@ static void dvbsub_parse_object_segment(AVCodecContext *avctx, if (buf + top_field_len + bottom_field_len > buf_end) { av_log(avctx, AV_LOG_ERROR, "Field data size too large\n"); - return; + return AVERROR_INVALIDDATA; } for (display = object->display_list; display; display = display->object_list_next) { @@ -896,10 +832,11 @@ static void dvbsub_parse_object_segment(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method); } + return 0; } -static void dvbsub_parse_clut_segment(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) +static int dvbsub_parse_clut_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) { DVBSubContext *ctx = avctx->priv_data; @@ -910,16 +847,16 @@ static void dvbsub_parse_clut_segment(AVCodecContext *avctx, int y, cr, cb, alpha; int r, g, b, r_add, g_add, b_add; - av_dlog(avctx, "DVB clut packet:\n"); + ff_dlog(avctx, "DVB clut packet:\n"); for (i=0; i < buf_size; i++) { - av_dlog(avctx, "%02x ", buf[i]); + ff_dlog(avctx, "%02x ", buf[i]); if (i % 16 == 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); } if (i % 16) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); clut_id = *buf++; buf += 1; @@ -928,6 +865,8 @@ static void dvbsub_parse_clut_segment(AVCodecContext *avctx, if (!clut) { clut = av_malloc(sizeof(DVBSubCLUT)); + if (!clut) + return AVERROR(ENOMEM); memcpy(clut, &default_clut, sizeof(DVBSubCLUT)); @@ -944,7 +883,7 @@ static void dvbsub_parse_clut_segment(AVCodecContext *avctx, if (depth == 0) { av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf); - return; + return AVERROR_INVALIDDATA; } full_range = (*buf++) & 1; @@ -969,7 +908,7 @@ static void dvbsub_parse_clut_segment(AVCodecContext *avctx, YUV_TO_RGB1_CCIR(cb, cr); YUV_TO_RGB2_CCIR(r, g, b, y); - av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); + ff_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); if (depth & 0x80) clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); @@ -978,11 +917,13 @@ static void dvbsub_parse_clut_segment(AVCodecContext *avctx, if (depth & 0x20) clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); } + + return 0; } -static void dvbsub_parse_region_segment(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) +static int dvbsub_parse_region_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) { DVBSubContext *ctx = avctx->priv_data; @@ -994,7 +935,7 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, int fill; if (buf_size < 10) - return; + return AVERROR_INVALIDDATA; region_id = *buf++; @@ -1002,6 +943,8 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, if (!region) { region = av_mallocz(sizeof(DVBSubRegion)); + if (!region) + return AVERROR(ENOMEM); region->id = region_id; @@ -1022,6 +965,8 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, region->buf_size = region->width * region->height; region->pbuf = av_malloc(region->buf_size); + if (!region->pbuf) + return AVERROR(ENOMEM); fill = 1; } @@ -1044,11 +989,11 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, region->bgcolor = (((*buf++) >> 2) & 3); } - av_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height); + ff_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height); if (fill) { memset(region->pbuf, region->bgcolor, region->buf_size); - av_dlog(avctx, "Fill region (%d)\n", region->bgcolor); + ff_dlog(avctx, "Fill region (%d)\n", region->bgcolor); } delete_region_display_list(ctx, region); @@ -1061,6 +1006,8 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, if (!object) { object = av_mallocz(sizeof(DVBSubObject)); + if (!object) + return AVERROR(ENOMEM); object->id = object_id; object->next = ctx->object_list; @@ -1070,6 +1017,8 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, object->type = (*buf) >> 6; display = av_mallocz(sizeof(DVBSubObjectDisplay)); + if (!display) + return AVERROR(ENOMEM); display->object_id = object_id; display->region_id = region_id; @@ -1090,10 +1039,12 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx, display->object_list_next = object->display_list; object->display_list = display; } + + return 0; } -static void dvbsub_parse_page_segment(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) +static int dvbsub_parse_page_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) { DVBSubContext *ctx = avctx->priv_data; DVBSubRegionDisplay *display; @@ -1104,12 +1055,12 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, int page_state; if (buf_size < 1) - return; + return AVERROR_INVALIDDATA; ctx->time_out = *buf++; page_state = ((*buf++) >> 2) & 3; - av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); + ff_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); if (page_state == 2) { delete_state(ctx); @@ -1131,8 +1082,11 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, display = display->next; } - if (!display) + if (!display) { display = av_mallocz(sizeof(DVBSubRegionDisplay)); + if (!display) + return AVERROR(ENOMEM); + } display->region_id = region_id; @@ -1147,7 +1101,7 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, ctx->display_list = display; ctx->display_list_size++; - av_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos); + ff_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos); } while (tmp_display_list) { @@ -1158,11 +1112,12 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx, av_free(display); } + return 0; } #ifdef DEBUG -static void save_display_set(DVBSubContext *ctx) +static int save_display_set(DVBSubContext *ctx) { DVBSubRegion *region; DVBSubRegionDisplay *display; @@ -1211,6 +1166,8 @@ static void save_display_set(DVBSubContext *ctx) if (x_pos >= 0) { pbuf = av_malloc(width * height * 4); + if (!pbuf) + return AVERROR(ENOMEM); for (display = ctx->display_list; display; display = display->next) { region = get_region(ctx, display->region_id); @@ -1247,37 +1204,38 @@ static void save_display_set(DVBSubContext *ctx) snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index); - png_save2(filename, pbuf, width, height); + png_save(filename, pbuf, width, height); av_free(pbuf); } fileno_index++; + return 0; } #endif -static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, - const uint8_t *buf, - int buf_size) +static int dvbsub_parse_display_definition_segment(AVCodecContext *avctx, + const uint8_t *buf, + int buf_size) { DVBSubContext *ctx = avctx->priv_data; DVBSubDisplayDefinition *display_def = ctx->display_definition; int dds_version, info_byte; if (buf_size < 5) - return; + return AVERROR_INVALIDDATA; info_byte = bytestream_get_byte(&buf); dds_version = info_byte >> 4; if (display_def && display_def->version == dds_version) - return; // already have this display definition version + return 0; // already have this display definition version if (!display_def) { display_def = av_mallocz(sizeof(*display_def)); + if (!display_def) + return AVERROR(ENOMEM); ctx->display_definition = display_def; } - if (!display_def) - return; display_def->version = dds_version; display_def->x = 0; @@ -1286,7 +1244,7 @@ static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, display_def->height = bytestream_get_be16(&buf) + 1; if (buf_size < 13) - return; + return AVERROR_INVALIDDATA; if (info_byte & 1<<3) { // display_window_flag display_def->x = bytestream_get_be16(&buf); @@ -1294,10 +1252,12 @@ static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, display_def->width = bytestream_get_be16(&buf) - display_def->x + 1; display_def->height = bytestream_get_be16(&buf) - display_def->y + 1; } + + return 0; } static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, - int buf_size, AVSubtitle *sub) + int buf_size, AVSubtitle *sub) { DVBSubContext *ctx = avctx->priv_data; DVBSubDisplayDefinition *display_def = ctx->display_definition; @@ -1321,12 +1281,13 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, } sub->num_rects = ctx->display_list_size; + if (sub->num_rects <= 0) + return AVERROR_INVALIDDATA; - if (sub->num_rects > 0){ - sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); - for(i=0; inum_rects; i++) - sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); - } + sub->rects = av_mallocz_array(sub->num_rects * sub->num_rects, + sizeof(*sub->rects)); + if (!sub->rects) + return AVERROR(ENOMEM); i = 0; @@ -1343,7 +1304,7 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, rect->h = region->height; rect->nb_colors = 16; rect->type = SUBTITLE_BITMAP; - rect->pict.linesize[0] = region->width; + rect->linesize[0] = region->width; clut = get_clut(ctx, region->clut); @@ -1363,11 +1324,32 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, break; } - rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE); - memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); + rect->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!rect->data[1]) { + av_free(sub->rects); + return AVERROR(ENOMEM); + } + memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); - rect->pict.data[0] = av_malloc(region->buf_size); - memcpy(rect->pict.data[0], region->pbuf, region->buf_size); + rect->data[0] = av_malloc(region->buf_size); + if (!rect->data[0]) { + av_free(rect->data[1]); + av_free(sub->rects); + return AVERROR(ENOMEM); + } + memcpy(rect->data[0], region->pbuf, region->buf_size); + +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS +{ + int j; + for (j = 0; j < 4; j++) { + rect->pict.data[j] = rect->data[j]; + rect->pict.linesize[j] = rect->linesize[j]; + } +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif i++; } @@ -1395,20 +1377,20 @@ static int dvbsub_decode(AVCodecContext *avctx, int segment_length; int i; - av_dlog(avctx, "DVB sub packet:\n"); + ff_dlog(avctx, "DVB sub packet:\n"); for (i=0; i < buf_size; i++) { - av_dlog(avctx, "%02x ", buf[i]); + ff_dlog(avctx, "%02x ", buf[i]); if (i % 16 == 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); } if (i % 16) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); if (buf_size <= 6 || *buf != 0x0f) { - av_dlog(avctx, "incomplete or broken packet"); - return -1; + ff_dlog(avctx, "incomplete or broken packet"); + return AVERROR_INVALIDDATA; } p = buf; @@ -1423,35 +1405,41 @@ static int dvbsub_decode(AVCodecContext *avctx, p += 2; if (p_end - p < segment_length) { - av_dlog(avctx, "incomplete or broken packet"); + ff_dlog(avctx, "incomplete or broken packet"); return -1; } if (page_id == ctx->composition_id || page_id == ctx->ancillary_id || ctx->composition_id == -1 || ctx->ancillary_id == -1) { + int ret = 0; switch (segment_type) { case DVBSUB_PAGE_SEGMENT: - dvbsub_parse_page_segment(avctx, p, segment_length); + ret = dvbsub_parse_page_segment(avctx, p, segment_length); break; case DVBSUB_REGION_SEGMENT: - dvbsub_parse_region_segment(avctx, p, segment_length); + ret = dvbsub_parse_region_segment(avctx, p, segment_length); break; case DVBSUB_CLUT_SEGMENT: - dvbsub_parse_clut_segment(avctx, p, segment_length); + ret = dvbsub_parse_clut_segment(avctx, p, segment_length); break; case DVBSUB_OBJECT_SEGMENT: - dvbsub_parse_object_segment(avctx, p, segment_length); + ret = dvbsub_parse_object_segment(avctx, p, segment_length); break; case DVBSUB_DISPLAYDEFINITION_SEGMENT: - dvbsub_parse_display_definition_segment(avctx, p, segment_length); + ret = dvbsub_parse_display_definition_segment(avctx, p, + segment_length); + break; case DVBSUB_DISPLAY_SEGMENT: - *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub); + ret = dvbsub_display_end_segment(avctx, p, segment_length, sub); + *data_size = ret; break; default: - av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n", + ff_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n", segment_type, page_id, segment_length); break; } + if (ret < 0) + return ret; } p += segment_length; diff --git a/libavcodec/dvdata.c b/libavcodec/dvdata.c index ad41a1b..985cda7 100644 --- a/libavcodec/dvdata.c +++ b/libavcodec/dvdata.c @@ -43,51 +43,51 @@ const uint8_t ff_dv_zigzag248_direct[64] = { /* unquant tables (not used directly) */ const uint8_t ff_dv_quant_shifts[22][4] = { - { 3,3,4,4 }, - { 3,3,4,4 }, - { 2,3,3,4 }, - { 2,3,3,4 }, - { 2,2,3,3 }, - { 2,2,3,3 }, - { 1,2,2,3 }, - { 1,2,2,3 }, - { 1,1,2,2 }, - { 1,1,2,2 }, - { 0,1,1,2 }, - { 0,1,1,2 }, - { 0,0,1,1 }, - { 0,0,1,1 }, - { 0,0,0,1 }, - { 0,0,0,0 }, - { 0,0,0,0 }, - { 0,0,0,0 }, - { 0,0,0,0 }, - { 0,0,0,0 }, - { 0,0,0,0 }, - { 0,0,0,0 }, + { 3, 3, 4, 4 }, + { 3, 3, 4, 4 }, + { 2, 3, 3, 4 }, + { 2, 3, 3, 4 }, + { 2, 2, 3, 3 }, + { 2, 2, 3, 3 }, + { 1, 2, 2, 3 }, + { 1, 2, 2, 3 }, + { 1, 1, 2, 2 }, + { 1, 1, 2, 2 }, + { 0, 1, 1, 2 }, + { 0, 1, 1, 2 }, + { 0, 0, 1, 1 }, + { 0, 0, 1, 1 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, }; -const uint8_t ff_dv_quant_offset[4] = { 6, 3, 0, 1 }; +const uint8_t ff_dv_quant_offset[4] = { 6, 3, 0, 1 }; const int ff_dv_iweight_88[64] = { - 32768, 16710, 16710, 17735, 17015, 17735, 18197, 18079, - 18079, 18197, 18725, 18559, 19196, 18559, 18725, 19284, - 19108, 19692, 19692, 19108, 19284, 21400, 19645, 20262, - 20214, 20262, 19645, 21400, 22733, 21845, 20867, 20815, - 20815, 20867, 21845, 22733, 23173, 23173, 21400, 21400, - 21400, 23173, 23173, 24600, 23764, 22017, 22017, 23764, - 24600, 25267, 24457, 22672, 24457, 25267, 25971, 25191, - 25191, 25971, 26715, 27962, 26715, 29642, 29642, 31536, + 32768, 16710, 16710, 17735, 17015, 17735, 18197, 18079, + 18079, 18197, 18725, 18559, 19196, 18559, 18725, 19284, + 19108, 19692, 19692, 19108, 19284, 21400, 19645, 20262, + 20214, 20262, 19645, 21400, 22733, 21845, 20867, 20815, + 20815, 20867, 21845, 22733, 23173, 23173, 21400, 21400, + 21400, 23173, 23173, 24600, 23764, 22017, 22017, 23764, + 24600, 25267, 24457, 22672, 24457, 25267, 25971, 25191, + 25191, 25971, 26715, 27962, 26715, 29642, 29642, 31536, }; const int ff_dv_iweight_248[64] = { - 32768, 17735, 16710, 18079, 18725, 21400, 17735, 19196, - 19108, 21845, 16384, 17735, 18725, 21400, 16710, 18079, - 20262, 23173, 18197, 19692, 18725, 20262, 20815, 23764, - 17735, 19196, 19108, 21845, 20262, 23173, 18197, 19692, - 21400, 24457, 19284, 20867, 21400, 23173, 22017, 25191, - 18725, 20262, 20815, 23764, 21400, 24457, 19284, 20867, - 24457, 27962, 22733, 24600, 25971, 29642, 21400, 23173, - 22017, 25191, 24457, 27962, 22733, 24600, 25971, 29642, + 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, }; /** @@ -140,221 +140,221 @@ const int ff_dv_iweight_720_c[64] = { * when building misc. tables. E.g. (1, 0) can be either 0x7cf or 0x1f82. */ const uint16_t ff_dv_vlc_bits[NB_DV_VLC] = { - 0x0000, 0x0002, 0x0007, 0x0008, 0x0009, 0x0014, 0x0015, 0x0016, - 0x0017, 0x0030, 0x0031, 0x0032, 0x0033, 0x0068, 0x0069, 0x006a, - 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x00e0, 0x00e1, 0x00e2, - 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, - 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x01e0, 0x01e1, 0x01e2, - 0x01e3, 0x01e4, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9, 0x01ea, - 0x01eb, 0x01ec, 0x01ed, 0x01ee, 0x01ef, 0x03e0, 0x03e1, 0x03e2, - 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x07ce, 0x07cf, 0x07d0, 0x07d1, - 0x07d2, 0x07d3, 0x07d4, 0x07d5, 0x0fac, 0x0fad, 0x0fae, 0x0faf, - 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, - 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, - 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, - 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, - 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, - 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, - 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, - 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, - 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, - 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, - 0x7f00, 0x7f01, 0x7f02, 0x7f03, 0x7f04, 0x7f05, 0x7f06, 0x7f07, - 0x7f08, 0x7f09, 0x7f0a, 0x7f0b, 0x7f0c, 0x7f0d, 0x7f0e, 0x7f0f, - 0x7f10, 0x7f11, 0x7f12, 0x7f13, 0x7f14, 0x7f15, 0x7f16, 0x7f17, - 0x7f18, 0x7f19, 0x7f1a, 0x7f1b, 0x7f1c, 0x7f1d, 0x7f1e, 0x7f1f, - 0x7f20, 0x7f21, 0x7f22, 0x7f23, 0x7f24, 0x7f25, 0x7f26, 0x7f27, - 0x7f28, 0x7f29, 0x7f2a, 0x7f2b, 0x7f2c, 0x7f2d, 0x7f2e, 0x7f2f, - 0x7f30, 0x7f31, 0x7f32, 0x7f33, 0x7f34, 0x7f35, 0x7f36, 0x7f37, - 0x7f38, 0x7f39, 0x7f3a, 0x7f3b, 0x7f3c, 0x7f3d, 0x7f3e, 0x7f3f, - 0x7f40, 0x7f41, 0x7f42, 0x7f43, 0x7f44, 0x7f45, 0x7f46, 0x7f47, - 0x7f48, 0x7f49, 0x7f4a, 0x7f4b, 0x7f4c, 0x7f4d, 0x7f4e, 0x7f4f, - 0x7f50, 0x7f51, 0x7f52, 0x7f53, 0x7f54, 0x7f55, 0x7f56, 0x7f57, - 0x7f58, 0x7f59, 0x7f5a, 0x7f5b, 0x7f5c, 0x7f5d, 0x7f5e, 0x7f5f, - 0x7f60, 0x7f61, 0x7f62, 0x7f63, 0x7f64, 0x7f65, 0x7f66, 0x7f67, - 0x7f68, 0x7f69, 0x7f6a, 0x7f6b, 0x7f6c, 0x7f6d, 0x7f6e, 0x7f6f, - 0x7f70, 0x7f71, 0x7f72, 0x7f73, 0x7f74, 0x7f75, 0x7f76, 0x7f77, - 0x7f78, 0x7f79, 0x7f7a, 0x7f7b, 0x7f7c, 0x7f7d, 0x7f7e, 0x7f7f, - 0x7f80, 0x7f81, 0x7f82, 0x7f83, 0x7f84, 0x7f85, 0x7f86, 0x7f87, - 0x7f88, 0x7f89, 0x7f8a, 0x7f8b, 0x7f8c, 0x7f8d, 0x7f8e, 0x7f8f, - 0x7f90, 0x7f91, 0x7f92, 0x7f93, 0x7f94, 0x7f95, 0x7f96, 0x7f97, - 0x7f98, 0x7f99, 0x7f9a, 0x7f9b, 0x7f9c, 0x7f9d, 0x7f9e, 0x7f9f, - 0x7fa0, 0x7fa1, 0x7fa2, 0x7fa3, 0x7fa4, 0x7fa5, 0x7fa6, 0x7fa7, - 0x7fa8, 0x7fa9, 0x7faa, 0x7fab, 0x7fac, 0x7fad, 0x7fae, 0x7faf, - 0x7fb0, 0x7fb1, 0x7fb2, 0x7fb3, 0x7fb4, 0x7fb5, 0x7fb6, 0x7fb7, - 0x7fb8, 0x7fb9, 0x7fba, 0x7fbb, 0x7fbc, 0x7fbd, 0x7fbe, 0x7fbf, - 0x7fc0, 0x7fc1, 0x7fc2, 0x7fc3, 0x7fc4, 0x7fc5, 0x7fc6, 0x7fc7, - 0x7fc8, 0x7fc9, 0x7fca, 0x7fcb, 0x7fcc, 0x7fcd, 0x7fce, 0x7fcf, - 0x7fd0, 0x7fd1, 0x7fd2, 0x7fd3, 0x7fd4, 0x7fd5, 0x7fd6, 0x7fd7, - 0x7fd8, 0x7fd9, 0x7fda, 0x7fdb, 0x7fdc, 0x7fdd, 0x7fde, 0x7fdf, - 0x7fe0, 0x7fe1, 0x7fe2, 0x7fe3, 0x7fe4, 0x7fe5, 0x7fe6, 0x7fe7, - 0x7fe8, 0x7fe9, 0x7fea, 0x7feb, 0x7fec, 0x7fed, 0x7fee, 0x7fef, - 0x7ff0, 0x7ff1, 0x7ff2, 0x7ff3, 0x7ff4, 0x7ff5, 0x7ff6, 0x7ff7, - 0x7ff8, 0x7ff9, 0x7ffa, 0x7ffb, 0x7ffc, 0x7ffd, 0x7ffe, 0x7fff, - 0x0006, + 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, }; const uint8_t ff_dv_vlc_len[NB_DV_VLC] = { - 2, 3, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, - 11, 11, 11, 11, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 4, + 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, }; const uint8_t ff_dv_vlc_run[NB_DV_VLC] = { - 0, 0, 1, 0, 0, 2, 1, 0, - 0, 3, 4, 0, 0, 5, 6, 2, - 1, 1, 0, 0, 0, 7, 8, 9, - 10, 3, 4, 2, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 11, 12, 13, - 14, 5, 6, 3, 4, 2, 2, 1, - 0, 0, 0, 0, 0, 5, 3, 3, - 2, 1, 1, 1, 0, 1, 6, 4, - 3, 1, 1, 1, 2, 3, 4, 5, - 7, 8, 9, 10, 7, 8, 4, 3, - 2, 2, 2, 2, 2, 1, 1, 1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -127, + 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, }; const uint8_t ff_dv_vlc_level[NB_DV_VLC] = { - 1, 2, 1, 3, 4, 1, 2, 5, - 6, 1, 1, 7, 8, 1, 1, 2, - 3, 4, 9, 10, 11, 1, 1, 1, - 1, 2, 2, 3, 5, 6, 7, 12, - 13, 14, 15, 16, 17, 1, 1, 1, - 1, 2, 2, 3, 3, 4, 5, 8, - 18, 19, 20, 21, 22, 3, 4, 5, - 6, 9, 10, 11, 0, 0, 3, 4, - 6, 12, 13, 14, 0, 0, 0, 0, - 2, 2, 2, 2, 3, 3, 5, 7, - 7, 8, 9, 10, 11, 15, 16, 17, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, - 0, + 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, }; diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 476f8c9..463d108 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -35,17 +35,18 @@ * DV decoder */ -#include "libavutil/internal.h" #include "libavutil/imgutils.h" +#include "libavutil/internal.h" #include "libavutil/pixdesc.h" + #include "avcodec.h" +#include "dv.h" +#include "dvdata.h" +#include "get_bits.h" #include "idctdsp.h" #include "internal.h" -#include "get_bits.h" #include "put_bits.h" #include "simple_idct.h" -#include "dvdata.h" -#include "dv.h" typedef struct BlockInfo { const uint32_t *factor_table; @@ -68,7 +69,7 @@ static av_cold int dvvideo_decode_init(AVCodecContext *avctx) ff_idctdsp_init(&idsp, avctx); for (i = 0; i < 64; i++) - s->dv_zigzag[0][i] = idsp.idct_permutation[ff_zigzag_direct[i]]; + s->dv_zigzag[0][i] = idsp.idct_permutation[ff_zigzag_direct[i]]; memcpy(s->dv_zigzag[1], ff_dv_zigzag248_direct, sizeof(s->dv_zigzag[1])); @@ -84,29 +85,30 @@ static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, int16_t *block) int last_index = gb->size_in_bits; const uint8_t *scan_table = mb->scan_table; const uint32_t *factor_table = mb->factor_table; - int pos = mb->pos; - int partial_bit_count = mb->partial_bit_count; + int pos = mb->pos; + int partial_bit_count = mb->partial_bit_count; int level, run, vlc_len, index; - OPEN_READER(re, gb); + OPEN_READER_NOSIZE(re, gb); UPDATE_CACHE(re, gb); /* if we must parse a partial VLC, we do it here */ if (partial_bit_count > 0) { - re_cache = re_cache >> partial_bit_count | mb->partial_bit_buffer; - re_index -= partial_bit_count; + re_cache = re_cache >> partial_bit_count | + mb->partial_bit_buffer; + re_index -= partial_bit_count; mb->partial_bit_count = 0; } /* get the AC coefficients until last_index is reached */ for (;;) { - av_dlog(NULL, "%2d: bits=%04x index=%d\n", pos, SHOW_UBITS(re, gb, 16), + ff_dlog(NULL, "%2d: bits=%04x index=%d\n", pos, SHOW_UBITS(re, gb, 16), re_index); /* our own optimized GET_RL_VLC */ index = NEG_USR32(re_cache, TEX_VLC_BITS); vlc_len = ff_dv_rl_vlc[index].len; if (vlc_len < 0) { - index = NEG_USR32((unsigned)re_cache << TEX_VLC_BITS, -vlc_len) + + index = NEG_USR32((unsigned) re_cache << TEX_VLC_BITS, -vlc_len) + ff_dv_rl_vlc[index].level; vlc_len = TEX_VLC_BITS - vlc_len; } @@ -116,19 +118,20 @@ static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, int16_t *block) /* 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_count = last_index - re_index; mb->partial_bit_buffer = re_cache & ~(-1u >> mb->partial_bit_count); - re_index = last_index; + re_index = last_index; break; } re_index += vlc_len; - av_dlog(NULL, "run=%d level=%d\n", run, level); + ff_dlog(NULL, "run=%d level=%d\n", run, level); pos += run; if (pos >= 64) break; - level = (level * factor_table[pos] + (1 << (dv_iweight_bits - 1))) >> dv_iweight_bits; + level = (level * factor_table[pos] + (1 << (dv_iweight_bits - 1))) >> + dv_iweight_bits; block[scan_table[pos]] = level; UPDATE_CACHE(re, gb); @@ -144,9 +147,8 @@ static inline void bit_copy(PutBitContext *pb, GetBitContext *gb) put_bits(pb, MIN_CACHE_BITS, get_bits(gb, MIN_CACHE_BITS)); bits_left -= MIN_CACHE_BITS; } - if (bits_left > 0) { + 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 */ @@ -164,25 +166,25 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) PutBitContext pb, vs_pb; GetBitContext gb; BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1; - LOCAL_ALIGNED_16(int16_t, sblock, [5*DV_MAX_BPM], [64]); - LOCAL_ALIGNED_16(uint8_t, mb_bit_buffer, [ 80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ - LOCAL_ALIGNED_16(uint8_t, vs_bit_buffer, [5*80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ + LOCAL_ALIGNED_16(int16_t, sblock, [5 * DV_MAX_BPM], [64]); + LOCAL_ALIGNED_16(uint8_t, mb_bit_buffer, [80 + AV_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ + LOCAL_ALIGNED_16(uint8_t, vs_bit_buffer, [80 * 5 + AV_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ const int log2_blocksize = 3; int is_field_mode[5]; - assert((((int)mb_bit_buffer) & 7) == 0); - assert((((int)vs_bit_buffer) & 7) == 0); + assert((((int) mb_bit_buffer) & 7) == 0); + assert((((int) vs_bit_buffer) & 7) == 0); - memset(sblock, 0, 5*DV_MAX_BPM*sizeof(*sblock)); + memset(sblock, 0, 5 * DV_MAX_BPM * sizeof(*sblock)); /* pass 1: read DC and AC coefficients in blocks */ - buf_ptr = &s->buf[work_chunk->buf_offset*80]; + buf_ptr = &s->buf[work_chunk->buf_offset * 80]; block1 = &sblock[0][0]; mb1 = mb_data; init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80); for (mb_index = 0; mb_index < 5; mb_index++, mb1 += s->sys->bpm, block1 += s->sys->bpm * 64) { /* skip header */ - quant = buf_ptr[3] & 0x0f; + quant = buf_ptr[3] & 0x0f; buf_ptr += 4; init_put_bits(&pb, mb_bit_buffer, 80); mb = mb1; @@ -199,28 +201,32 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) if (DV_PROFILE_IS_HD(s->sys)) { mb->idct_put = s->idct_put[0]; mb->scan_table = s->dv_zigzag[0]; - mb->factor_table = &s->idct_factor[(j >= 4)*4*16*64 + class1*16*64 + quant*64]; + mb->factor_table = &s->idct_factor[(j >= 4) * 4 * 16 * 64 + + class1 * 16 * 64 + + quant * 64]; is_field_mode[mb_index] |= !j && dct_mode; } else { mb->idct_put = s->idct_put[dct_mode && log2_blocksize == 3]; mb->scan_table = s->dv_zigzag[dct_mode]; - mb->factor_table = &s->idct_factor[(class1 == 3)*2*22*64 + dct_mode*22*64 + - (quant + ff_dv_quant_offset[class1])*64]; + mb->factor_table = + &s->idct_factor[(class1 == 3) * 2 * 22 * 64 + + dct_mode * 22 * 64 + + (quant + ff_dv_quant_offset[class1]) * 64]; } dc = dc << 2; /* convert to unsigned because 128 is not added in the - standard IDCT */ - dc += 1024; - block[0] = dc; - buf_ptr += last_index >> 3; + * standard IDCT */ + dc += 1024; + block[0] = dc; + buf_ptr += last_index >> 3; mb->pos = 0; mb->partial_bit_count = 0; - av_dlog(avctx, "MB block: %d, %d ", mb_index, j); + ff_dlog(avctx, "MB block: %d, %d ", mb_index, j); dv_decode_ac(&gb, mb, block); /* write the remaining bits in a new buffer only if the - block is finished */ + * block is finished */ if (mb->pos >= 64) bit_copy(&pb, &gb); @@ -229,7 +235,7 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) } /* pass 2: we can do it just after */ - av_dlog(avctx, "***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index); + ff_dlog(avctx, "***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index); block = block1; mb = mb1; init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb)); @@ -244,13 +250,13 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) } } /* all blocks are finished, so the extra bytes can be used at - the video segment level */ + * the video segment level */ if (j >= s->sys->bpm) bit_copy(&vs_pb, &gb); } /* we need a pass over the whole video segment */ - av_dlog(avctx, "***pass 3 size=%d\n", put_bits_count(&vs_pb)); + ff_dlog(avctx, "***pass 3 size=%d\n", put_bits_count(&vs_pb)); block = &sblock[0][0]; mb = mb_data; init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb)); @@ -259,11 +265,12 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) for (mb_index = 0; mb_index < 5; mb_index++) { for (j = 0; j < s->sys->bpm; j++) { if (mb->pos < 64) { - av_dlog(avctx, "start %d:%d\n", mb_index, j); + ff_dlog(avctx, "start %d:%d\n", mb_index, j); dv_decode_ac(&gb, mb, block); } if (mb->pos >= 64 && mb->pos < 127) - av_log(avctx, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos); + av_log(avctx, AV_LOG_ERROR, + "AC EOB marker is absent pos=%d\n", mb->pos); block += 64; mb++; } @@ -276,25 +283,27 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y); /* idct_put'ting luminance */ - if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || + if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) || (s->sys->height >= 720 && mb_y != 134)) { - y_stride = (s->frame->linesize[0] << ((!is_field_mode[mb_index]) * log2_blocksize)); + y_stride = (s->frame->linesize[0] << + ((!is_field_mode[mb_index]) * log2_blocksize)); } else { y_stride = (2 << log2_blocksize); } - y_ptr = s->frame->data[0] + ((mb_y * s->frame->linesize[0] + mb_x) << log2_blocksize); + y_ptr = s->frame->data[0] + + ((mb_y * s->frame->linesize[0] + mb_x) << log2_blocksize); linesize = s->frame->linesize[0] << is_field_mode[mb_index]; - mb[0] .idct_put(y_ptr , linesize, block + 0*64); + mb[0].idct_put(y_ptr, linesize, block + 0 * 64); if (s->sys->video_stype == 4) { /* SD 422 */ - mb[2].idct_put(y_ptr + (1 << log2_blocksize) , linesize, block + 2*64); + mb[2].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 2 * 64); } else { - mb[1].idct_put(y_ptr + (1 << log2_blocksize) , linesize, block + 1*64); - mb[2].idct_put(y_ptr + y_stride, linesize, block + 2*64); - mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3*64); + mb[1].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 1 * 64); + mb[2].idct_put(y_ptr + y_stride, linesize, block + 2 * 64); + mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3 * 64); } - mb += 4; - block += 4*64; + mb += 4; + block += 4 * 64; /* idct_put'ting chrominance */ c_offset = (((mb_y >> (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->frame->linesize[1] + @@ -302,28 +311,31 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) for (j = 2; j; j--) { uint8_t *c_ptr = s->frame->data[j] + c_offset; if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) { - uint64_t aligned_pixels[64/8]; - uint8_t *pixels = (uint8_t*)aligned_pixels; - uint8_t *c_ptr1, *ptr1; - int x, y; - mb->idct_put(pixels, 8, block); - for (y = 0; y < (1 << log2_blocksize); y++, c_ptr += s->frame->linesize[j], pixels += 8) { - ptr1 = pixels + (1 << (log2_blocksize - 1)); - c_ptr1 = c_ptr + (s->frame->linesize[j] << log2_blocksize); - for (x = 0; x < (1 << (log2_blocksize - 1)); x++) { - c_ptr[x] = pixels[x]; - c_ptr1[x] = ptr1[x]; - } - } - block += 64; mb++; + uint64_t aligned_pixels[64 / 8]; + uint8_t *pixels = (uint8_t *) aligned_pixels; + uint8_t *c_ptr1, *ptr1; + int x, y; + mb->idct_put(pixels, 8, block); + for (y = 0; y < (1 << log2_blocksize); y++, c_ptr += s->frame->linesize[j], pixels += 8) { + ptr1 = pixels + (1 << (log2_blocksize - 1)); + c_ptr1 = c_ptr + (s->frame->linesize[j] << log2_blocksize); + for (x = 0; x < (1 << (log2_blocksize - 1)); x++) { + c_ptr[x] = pixels[x]; + c_ptr1[x] = ptr1[x]; + } + } + block += 64; + mb++; } else { - y_stride = (mb_y == 134) ? (1 << log2_blocksize) : - s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); - linesize = s->frame->linesize[j] << is_field_mode[mb_index]; - (mb++)-> idct_put(c_ptr , linesize, block); block += 64; - if (s->sys->bpm == 8) { - (mb++)->idct_put(c_ptr + y_stride, linesize, block); block += 64; - } + y_stride = (mb_y == 134) ? (1 << log2_blocksize) : + s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); + linesize = s->frame->linesize[j] << is_field_mode[mb_index]; + (mb++)->idct_put(c_ptr, linesize, block); + block += 64; + if (s->sys->bpm == 8) { + (mb++)->idct_put(c_ptr + y_stride, linesize, block); + block += 64; + } } } } @@ -331,15 +343,15 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) } /* NOTE: exactly one frame must be given (120000 bytes for NTSC, - 144000 bytes for PAL - or twice those for 50Mbps) */ -static int dvvideo_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) + * 144000 bytes for PAL - or twice those for 50Mbps) */ +static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DVVideoContext *s = avctx->priv_data; - const uint8_t* vsc_pack; + AVFrame *frame = data; + const uint8_t *vsc_pack; int apt, is16_9, ret; const AVDVProfile *sys; @@ -358,30 +370,31 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, s->sys = sys; } - s->frame = data; - s->frame->key_frame = 1; - s->frame->pict_type = AV_PICTURE_TYPE_I; - avctx->pix_fmt = s->sys->pix_fmt; - avctx->time_base = s->sys->time_base; + s->frame = frame; + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + avctx->pix_fmt = s->sys->pix_fmt; + avctx->framerate = av_inv_q(s->sys->time_base); ret = ff_set_dimensions(avctx, s->sys->width, s->sys->height); if (ret < 0) return ret; /* Determine the codec's sample_aspect ratio from the packet */ - vsc_pack = buf + 80*5 + 48 + 5; - if ( *vsc_pack == dv_video_control ) { - apt = buf[4] & 0x07; - is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07))); + vsc_pack = buf + 80 * 5 + 48 + 5; + if (*vsc_pack == dv_video_control) { + apt = buf[4] & 0x07; + is16_9 = (vsc_pack[2] & 0x07) == 0x02 || + (!apt && (vsc_pack[2] & 0x07) == 0x07); ff_set_sar(avctx, s->sys->sar[is16_9]); } - if (ff_get_buffer(avctx, s->frame, 0) < 0) { + if (ff_get_buffer(avctx, frame, 0) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } - s->frame->interlaced_frame = 1; - s->frame->top_field_first = 0; + frame->interlaced_frame = 1; + frame->top_field_first = 0; s->buf = buf; avctx->execute(avctx, dv_decode_video_segment, s->work_chunks, NULL, @@ -403,5 +416,5 @@ AVCodec ff_dvvideo_decoder = { .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_decode_init, .decode = dvvideo_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, }; diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c index 15abac0..6e55a09 100644 --- a/libavcodec/dvdsubdec.c +++ b/libavcodec/dvdsubdec.c @@ -178,13 +178,14 @@ static void guess_palette(DVDSubContext* ctx, static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, const uint8_t *buf, int buf_size) { - int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos; + int cmd_pos, pos, cmd, x1, y1, x2, y2, next_cmd_pos; int big_offsets, offset_size, is_8bit = 0; const uint8_t *yuv_palette = 0; uint8_t colormap[4] = { 0 }, alpha[256] = { 0 }; int date; int i; int is_menu = 0; + int64_t offset1, offset2; if (buf_size < 10) return -1; @@ -205,7 +206,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) { date = AV_RB16(buf + cmd_pos); next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2); - av_dlog(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n", + ff_dlog(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n", cmd_pos, next_cmd_pos, date); pos = cmd_pos + 2 + offset_size; offset1 = -1; @@ -213,7 +214,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, x1 = y1 = x2 = y2 = 0; while (pos < buf_size) { cmd = buf[pos++]; - av_dlog(NULL, "cmd=%02x\n", cmd); + ff_dlog(NULL, "cmd=%02x\n", cmd); switch(cmd) { case 0x00: /* menu subpicture */ @@ -246,7 +247,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, alpha[1] = buf[pos + 1] >> 4; alpha[0] = buf[pos + 1] & 0x0f; pos += 2; - av_dlog(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]); + ff_dlog(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]); break; case 0x05: case 0x85: @@ -258,7 +259,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5]; if (cmd & 0x80) is_8bit = 1; - av_dlog(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2); + ff_dlog(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2); pos += 6; break; case 0x06: @@ -266,7 +267,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, goto fail; offset1 = AV_RB16(buf + pos); offset2 = AV_RB16(buf + pos + 2); - av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); + ff_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); pos += 4; break; case 0x86: @@ -274,7 +275,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, goto fail; offset1 = AV_RB32(buf + pos); offset2 = AV_RB32(buf + pos + 4); - av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); + ff_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); pos += 8; break; @@ -297,11 +298,14 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, case 0xff: goto the_end; default: - av_dlog(NULL, "unrecognised subpicture command 0x%x\n", cmd); + ff_dlog(NULL, "unrecognised subpicture command 0x%x\n", cmd); goto the_end; } } the_end: + if (offset1 >= buf_size || offset2 >= buf_size) + goto fail; + if (offset1 >= 0) { int w, h; uint8_t *bitmap; @@ -316,33 +320,42 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, if (w > 0 && h > 0) { if (sub_header->rects) { for (i = 0; i < sub_header->num_rects; i++) { - av_freep(&sub_header->rects[i]->pict.data[0]); - av_freep(&sub_header->rects[i]->pict.data[1]); + av_freep(&sub_header->rects[i]->data[0]); + av_freep(&sub_header->rects[i]->data[1]); av_freep(&sub_header->rects[i]); } av_freep(&sub_header->rects); sub_header->num_rects = 0; } - bitmap = av_malloc(w * h); sub_header->rects = av_mallocz(sizeof(*sub_header->rects)); + if (!sub_header->rects) + goto fail; sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect)); + if (!sub_header->rects[0]) + goto fail; sub_header->num_rects = 1; - sub_header->rects[0]->pict.data[0] = bitmap; + bitmap = sub_header->rects[0]->data[0] = av_malloc(w * h); + if (!bitmap) + goto fail; decode_rle(bitmap, w * 2, w, (h + 1) / 2, buf, offset1, buf_size, is_8bit); decode_rle(bitmap + w, w * 2, w, h / 2, buf, offset2, buf_size, is_8bit); - sub_header->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + sub_header->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!sub_header->rects[0]->data[1]) + goto fail; if (is_8bit) { if (yuv_palette == 0) goto fail; sub_header->rects[0]->nb_colors = 256; - yuv_a_to_rgba(yuv_palette, alpha, (uint32_t*)sub_header->rects[0]->pict.data[1], 256); + yuv_a_to_rgba(yuv_palette, alpha, + (uint32_t *)sub_header->rects[0]->data[1], + 256); } else { sub_header->rects[0]->nb_colors = 4; guess_palette(ctx, - (uint32_t*)sub_header->rects[0]->pict.data[1], + (uint32_t *)sub_header->rects[0]->data[1], colormap, alpha, 0xffff00); } sub_header->rects[0]->x = x1; @@ -350,7 +363,21 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, sub_header->rects[0]->w = w; sub_header->rects[0]->h = h; sub_header->rects[0]->type = SUBTITLE_BITMAP; - sub_header->rects[0]->pict.linesize[0] = w; + sub_header->rects[0]->linesize[0] = w; + +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS +{ + int j; + AVSubtitleRect *rect; + rect = sub_header->rects[0]; + for (j = 0; j < 4; j++) { + rect->pict.data[j] = rect->data[j]; + rect->pict.linesize[j] = rect->linesize[j]; + } +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } if (next_cmd_pos == cmd_pos) @@ -362,8 +389,8 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, fail: if (!sub_header->rects) { for (i = 0; i < sub_header->num_rects; i++) { - av_freep(&sub_header->rects[i]->pict.data[0]); - av_freep(&sub_header->rects[i]->pict.data[1]); + av_freep(&sub_header->rects[i]->data[0]); + av_freep(&sub_header->rects[i]->data[1]); av_freep(&sub_header->rects[i]); } av_freep(&sub_header->rects); @@ -395,29 +422,29 @@ static int find_smallest_bounding_rectangle(AVSubtitle *s) return 0; for(i = 0; i < s->rects[0]->nb_colors; i++) { - if ((((uint32_t*)s->rects[0]->pict.data[1])[i] >> 24) == 0) + if ((((uint32_t *)s->rects[0]->data[1])[i] >> 24) == 0) transp_color[i] = 1; } y1 = 0; - while (y1 < s->rects[0]->h && is_transp(s->rects[0]->pict.data[0] + y1 * s->rects[0]->pict.linesize[0], + while (y1 < s->rects[0]->h && is_transp(s->rects[0]->data[0] + y1 * s->rects[0]->linesize[0], 1, s->rects[0]->w, transp_color)) y1++; if (y1 == s->rects[0]->h) { - av_freep(&s->rects[0]->pict.data[0]); + av_freep(&s->rects[0]->data[0]); s->rects[0]->w = s->rects[0]->h = 0; return 0; } y2 = s->rects[0]->h - 1; - while (y2 > 0 && is_transp(s->rects[0]->pict.data[0] + y2 * s->rects[0]->pict.linesize[0], 1, + while (y2 > 0 && is_transp(s->rects[0]->data[0] + y2 * s->rects[0]->linesize[0], 1, s->rects[0]->w, transp_color)) y2--; x1 = 0; - while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->pict.data[0] + x1, s->rects[0]->pict.linesize[0], + while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->data[0] + x1, s->rects[0]->linesize[0], s->rects[0]->h, transp_color)) x1++; x2 = s->rects[0]->w - 1; - while (x2 > 0 && is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0], s->rects[0]->h, + while (x2 > 0 && is_transp(s->rects[0]->data[0] + x2, s->rects[0]->linesize[0], s->rects[0]->h, transp_color)) x2--; w = x2 - x1 + 1; @@ -426,11 +453,11 @@ static int find_smallest_bounding_rectangle(AVSubtitle *s) if (!bitmap) return 1; for(y = 0; y < h; y++) { - memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 + (y1 + y) * s->rects[0]->pict.linesize[0], w); + memcpy(bitmap + w * y, s->rects[0]->data[0] + x1 + (y1 + y) * s->rects[0]->linesize[0], w); } - av_freep(&s->rects[0]->pict.data[0]); - s->rects[0]->pict.data[0] = bitmap; - s->rects[0]->pict.linesize[0] = w; + av_freep(&s->rects[0]->data[0]); + s->rects[0]->data[0] = bitmap; + s->rects[0]->linesize[0] = w; s->rects[0]->w = w; s->rects[0]->h = h; s->rects[0]->x += x1; @@ -488,11 +515,11 @@ static int dvdsub_decode(AVCodecContext *avctx, goto no_subtitle; #if defined(DEBUG) - av_dlog(NULL, "start=%d ms end =%d ms\n", + ff_dlog(NULL, "start=%d ms end =%d ms\n", sub->start_display_time, sub->end_display_time); - ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0], - sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]); + ppm_save("/tmp/a.ppm", sub->rects[0]->data[0], + sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->data[1]); #endif *data_size = 1; diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c index f62e943e..b0c2b63 100644 --- a/libavcodec/dvdsubenc.c +++ b/libavcodec/dvdsubenc.c @@ -107,13 +107,27 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size, hist[i] = 0; cmap[i] = 0; } - for (object_id = 0; object_id < rects; object_id++) + for (object_id = 0; object_id < rects; object_id++) { +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS + if (!h->rects[object_id]->data[0]) { + AVSubtitleRect *rect = h->rects[object_id]; + int j; + for (j = 0; j < 4; j++) { + rect->data[j] = rect->pict.data[j]; + rect->linesize[j] = rect->pict.linesize[j]; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + for (i=0; irects[object_id]->w*h->rects[object_id]->h; ++i) { - color = h->rects[object_id]->pict.data[0][i]; + color = h->rects[object_id]->data[0][i]; // only count non-transparent pixels - alpha = ((uint32_t*)h->rects[object_id]->pict.data[1])[color] >> 24; + alpha = ((uint32_t *)h->rects[object_id]->data[1])[color] >> 24; hist[color] += alpha; } + } for (color=3;; --color) { hmax = 0; imax = 0; @@ -143,12 +157,12 @@ static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size, av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n"); return -1; } - dvd_encode_rle(&q, h->rects[object_id]->pict.data[0], + dvd_encode_rle(&q, h->rects[object_id]->data[0], 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]->pict.data[0] + h->rects[object_id]->w, + dvd_encode_rle(&q, h->rects[object_id]->data[0] + h->rects[object_id]->w, h->rects[object_id]->w*2, h->rects[object_id]->w, h->rects[object_id]->h >> 1, cmap); diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 74e29d8..e02f349 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -24,18 +24,22 @@ * DV encoder */ +#include "config.h" + #include "libavutil/attributes.h" +#include "libavutil/internal.h" #include "libavutil/pixdesc.h" -#include "config.h" + #include "avcodec.h" +#include "dv.h" +#include "dv_profile_internal.h" +#include "dv_tablegen.h" #include "fdctdsp.h" #include "internal.h" +#include "mathops.h" #include "me_cmp.h" #include "pixblockdsp.h" #include "put_bits.h" -#include "dv.h" -#include "dv_tablegen.h" -#include "dv_profile_internal.h" static av_cold int dvvideo_encode_init(AVCodecContext *avctx) { @@ -48,7 +52,7 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) s->sys = av_dv_codec_profile(avctx->width, avctx->height, avctx->pix_fmt); if (!s->sys) { av_log(avctx, AV_LOG_ERROR, "Found no DV profile for %ix%i %s video. " - "Valid DV profiles are:\n", + "Valid DV profiles are:\n", avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt)); ff_dv_print_profiles(avctx, AV_LOG_ERROR); return AVERROR(EINVAL); @@ -59,10 +63,6 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) return ret; } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - dv_vlc_map_tableinit(); ff_fdctdsp_init(&fdsp, avctx); @@ -80,19 +80,19 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) } /* bit budget for AC only in 5 MBs */ -static const int vs_total_ac_bits = (100 * 4 + 68*2) * 5; +static const int vs_total_ac_bits = (100 * 4 + 68 * 2) * 5; static const int mb_area_start[5] = { 1, 6, 21, 43, 64 }; #if CONFIG_SMALL -/* Converts run and level (where level != 0) pair into VLC, returning bit size */ -static av_always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc) +/* Convert run and level (where level != 0) pair into VLC, returning bit size */ +static av_always_inline int dv_rl2vlc(int run, int level, int sign, + uint32_t *vlc) { int size; if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { *vlc = dv_vlc_map[run][level].vlc | sign; size = dv_vlc_map[run][level].size; - } - else { + } else { if (level < DV_VLC_MAP_LEV_SIZE) { *vlc = dv_vlc_map[0][level].vlc | sign; size = dv_vlc_map[0][level].size; @@ -101,9 +101,9 @@ static av_always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vl 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; + *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; } } @@ -116,17 +116,15 @@ static av_always_inline int dv_rl2vlc_size(int run, int level) if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { size = dv_vlc_map[run][level].size; - } - else { + } 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; - } + if (run) + size += (run < 16) ? dv_vlc_map[run - 1][0].size : 13; } return size; } #else -static av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc) +static av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t *vlc) { *vlc = dv_vlc_map[run][l].vlc | sign; return dv_vlc_map[run][l].size; @@ -152,55 +150,60 @@ typedef struct EncBlockInfo { uint32_t partial_bit_buffer; /* we can't use uint16_t here */ } EncBlockInfo; -static av_always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, - PutBitContext* pb_pool, - PutBitContext* pb_end) +static av_always_inline PutBitContext *dv_encode_ac(EncBlockInfo *bi, + PutBitContext *pb_pool, + PutBitContext *pb_end) { int prev, bits_left; - PutBitContext* pb = pb_pool; - int size = bi->partial_bit_count; - uint32_t vlc = bi->partial_bit_buffer; - - bi->partial_bit_count = bi->partial_bit_buffer = 0; - for (;;){ - /* Find suitable storage space */ - for (; size > (bits_left = put_bits_left(pb)); pb++) { - if (bits_left) { - size -= bits_left; - put_bits(pb, bits_left, vlc >> size); - vlc = vlc & ((1 << size) - 1); - } - if (pb + 1 >= pb_end) { - bi->partial_bit_count = size; - bi->partial_bit_buffer = vlc; - return pb; - } - } - - /* Store VLC */ - put_bits(pb, size, vlc); - - if (bi->cur_ac >= 64) - break; - - /* Construct the next VLC */ - prev = bi->cur_ac; - bi->cur_ac = bi->next[prev]; - if (bi->cur_ac < 64){ - size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], bi->sign[bi->cur_ac], &vlc); - } else { - size = 4; vlc = 6; /* End Of Block stamp */ - } + PutBitContext *pb = pb_pool; + int size = bi->partial_bit_count; + uint32_t vlc = bi->partial_bit_buffer; + + bi->partial_bit_count = + bi->partial_bit_buffer = 0; + for (;;) { + /* Find suitable storage space */ + for (; size > (bits_left = put_bits_left(pb)); pb++) { + if (bits_left) { + size -= bits_left; + put_bits(pb, bits_left, vlc >> size); + vlc = vlc & ((1 << size) - 1); + } + if (pb + 1 >= pb_end) { + bi->partial_bit_count = size; + bi->partial_bit_buffer = vlc; + return pb; + } + } + + /* Store VLC */ + put_bits(pb, size, vlc); + + if (bi->cur_ac >= 64) + break; + + /* Construct the next VLC */ + prev = bi->cur_ac; + bi->cur_ac = bi->next[prev]; + if (bi->cur_ac < 64) { + size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], + bi->sign[bi->cur_ac], &vlc); + } else { + size = 4; + vlc = 6; /* End Of Block stamp */ + } } return pb; } -static av_always_inline int dv_guess_dct_mode(DVVideoContext *s, uint8_t *data, int linesize) { - if (s->avctx->flags & CODEC_FLAG_INTERLACED_DCT) { +static av_always_inline int dv_guess_dct_mode(DVVideoContext *s, uint8_t *data, + int linesize) +{ + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { int ps = s->ildct_cmp(NULL, data, NULL, linesize, 8) - 400; if (ps > 0) { - int is = s->ildct_cmp(NULL, data , NULL, linesize<<1, 4) + - s->ildct_cmp(NULL, data + linesize, NULL, linesize<<1, 4); + int is = s->ildct_cmp(NULL, data, NULL, linesize << 1, 4) + + s->ildct_cmp(NULL, data + linesize, NULL, linesize << 1, 4); return ps > is; } } @@ -210,94 +213,102 @@ static av_always_inline int dv_guess_dct_mode(DVVideoContext *s, uint8_t *data, 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, + 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, + 131072, 242189, 257107, 237536, 229376, 200636, 242189, 223754, + 224969, 196781, 262144, 242189, 229376, 200636, 257107, 237536, + 211916, 185364, 235923, 217965, 229376, 211916, 206433, 180568, + 242189, 223754, 224969, 196781, 211916, 185364, 235923, 217965, + 200704, 175557, 222935, 205965, 200636, 185364, 195068, 170627, + 229376, 211916, 206433, 180568, 200704, 175557, 222935, 205965, + 175557, 153560, 188995, 174609, 165371, 144651, 200636, 185364, + 195068, 170627, 175557, 153560, 188995, 174609, 165371, 144651, }; -static av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, int linesize, DVVideoContext *s, int bias) +static av_always_inline int dv_init_enc_block(EncBlockInfo *bi, uint8_t *data, + int linesize, DVVideoContext *s, + int bias) { const int *weight; - const uint8_t* zigzag_scan; + const uint8_t *zigzag_scan; LOCAL_ALIGNED_16(int16_t, blk, [64]); int i, area; /* We offer two different methods for class number assignment: the - method suggested in SMPTE 314M Table 22, and an improved - method. The SMPTE method is very conservative; it assigns class - 3 (i.e. severe quantization) to any block where the largest AC - component is greater than 36. Libav'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). */ + * 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. Libav'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}; + static const int classes[] = { 12, 24, 36, 0xffff }; #else /* improved Libav method */ - static const int classes[] = {-1, -1, 255, 0xffff}; + static const int classes[] = { -1, -1, 255, 0xffff }; #endif int max = classes[0]; int prev = 0; - assert((((int)blk) & 15) == 0); + assert((((int) blk) & 15) == 0); - bi->area_q[0] = bi->area_q[1] = bi->area_q[2] = bi->area_q[3] = 0; - bi->partial_bit_count = 0; + bi->area_q[0] = + bi->area_q[1] = + bi->area_q[2] = + bi->area_q[3] = 0; + bi->partial_bit_count = 0; bi->partial_bit_buffer = 0; - bi->cur_ac = 0; + bi->cur_ac = 0; if (data) { bi->dct_mode = dv_guess_dct_mode(s, data, linesize); s->get_pixels(blk, data, linesize); s->fdct[bi->dct_mode](blk); } else { - /* We rely on the fact that encoding all zeros leads to an immediate EOB, - which is precisely what the spec calls for in the "dummy" blocks. */ - memset(blk, 0, 64*sizeof(*blk)); + /* We rely on the fact that encoding all zeros leads to an immediate + * EOB, which is precisely what the spec calls for in the "dummy" + * blocks. */ + memset(blk, 0, 64 * sizeof(*blk)); bi->dct_mode = 0; } bi->mb[0] = blk[0]; zigzag_scan = bi->dct_mode ? ff_dv_zigzag248_direct : ff_zigzag_direct; - weight = bi->dct_mode ? dv_weight_248 : dv_weight_88; + weight = bi->dct_mode ? dv_weight_248 : dv_weight_88; for (area = 0; area < 4; area++) { - bi->prev[area] = prev; - bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) - for (i = mb_area_start[area]; i < mb_area_start[area+1]; i++) { - int level = blk[zigzag_scan[i]]; - - if (level + 15 > 30U) { - bi->sign[i] = (level >> 31) & 1; - /* weight it and and shift down into range, adding for rounding */ - /* the extra division by a factor of 2^4 reverses the 8x expansion of the DCT - AND the 2x doubling of the weights */ - level = (FFABS(level) * weight[i] + (1 << (dv_weight_bits+3))) >> (dv_weight_bits+4); - bi->mb[i] = level; - if (level > max) - max = level; - bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level); - bi->next[prev]= i; - prev = i; - } - } + bi->prev[area] = prev; + bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) + for (i = mb_area_start[area]; i < mb_area_start[area + 1]; i++) { + int level = blk[zigzag_scan[i]]; + + if (level + 15 > 30U) { + bi->sign[i] = (level >> 31) & 1; + /* Weight it and and shift down into range, adding for rounding. + * The extra division by a factor of 2^4 reverses the 8x + * expansion of the DCT AND the 2x doubling of the weights. */ + level = (FFABS(level) * weight[i] + (1 << (dv_weight_bits + 3))) >> + (dv_weight_bits + 4); + bi->mb[i] = level; + if (level > max) + max = level; + bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level); + bi->next[prev] = i; + prev = i; + } + } } - bi->next[prev]= i; - for (bi->cno = 0; max > classes[bi->cno]; bi->cno++); + bi->next[prev] = i; + for (bi->cno = 0; max > classes[bi->cno]; bi->cno++) + ; bi->cno += bias; @@ -308,85 +319,89 @@ static av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, i 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]) { + 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; + prev = i; } } } - bi->next[prev]= i; + bi->next[prev] = i; } - return bi->bit_size[0] + bi->bit_size[1] + bi->bit_size[2] + bi->bit_size[3]; + return bi->bit_size[0] + bi->bit_size[1] + + bi->bit_size[2] + bi->bit_size[3]; } -static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos) +static inline void dv_guess_qnos(EncBlockInfo *blks, int *qnos) { int size[5]; int i, j, k, a, prev, a2; - EncBlockInfo* b; + EncBlockInfo *b; - size[0] = size[1] = size[2] = size[3] = size[4] = 1 << 24; + size[0] = + size[1] = + size[2] = + size[3] = + size[4] = 1 << 24; do { - b = blks; - for (i = 0; i < 5; i++) { - if (!qnos[i]) - continue; - - qnos[i]--; - size[i] = 0; - for (j = 0; j < 6; j++, b++) { - for (a = 0; a < 4; a++) { - if (b->area_q[a] != ff_dv_quant_shifts[qnos[i] + ff_dv_quant_offset[b->cno]][a]) { - b->bit_size[a] = 1; // 4 areas 4 bits for EOB :) - b->area_q[a]++; - prev = b->prev[a]; - 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 = blks; + for (i = 0; i < 5; i++) { + if (!qnos[i]) + continue; + + qnos[i]--; + size[i] = 0; + for (j = 0; j < 6; j++, b++) { + for (a = 0; a < 4; a++) { + if (b->area_q[a] != ff_dv_quant_shifts[qnos[i] + ff_dv_quant_offset[b->cno]][a]) { + b->bit_size[a] = 1; // 4 areas 4 bits for EOB :) + b->area_q[a]++; + prev = b->prev[a]; + 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; - 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->next[prev] = b->next[k]; + } + } + b->prev[a + 1] = prev; } - b->prev[a+1]= prev; + size[i] += b->bit_size[a]; } - size[i] += b->bit_size[a]; - } - } - if (vs_total_ac_bits >= size[0] + size[1] + size[2] + size[3] + size[4]) + } + 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]); - + } + } 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++) { + 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){ + if (b->mb[k] < a && b->mb[k] > -a) { b->next[prev] = b->next[k]; - }else{ + } else { size[0] += dv_rl2vlc_size(k - prev - 1, b->mb[k]); - prev = k; + prev = k; } } } @@ -399,45 +414,46 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) DVwork_chunk *work_chunk = arg; int mb_index, i, j; int mb_x, mb_y, c_offset, linesize, y_stride; - uint8_t* y_ptr; - uint8_t* dif; + uint8_t *y_ptr; + uint8_t *dif; LOCAL_ALIGNED_8(uint8_t, scratch, [128]); - EncBlockInfo enc_blks[5*DV_MAX_BPM]; - PutBitContext pbs[5*DV_MAX_BPM]; - PutBitContext* pb; - EncBlockInfo* enc_blk; - int vs_bit_size = 0; - int qnos[5] = {15, 15, 15, 15, 15}; /* No quantization */ - int* qnosp = &qnos[0]; - - dif = &s->buf[work_chunk->buf_offset*80]; + EncBlockInfo enc_blks[5 * DV_MAX_BPM]; + PutBitContext pbs[5 * DV_MAX_BPM]; + PutBitContext *pb; + EncBlockInfo *enc_blk; + int vs_bit_size = 0; + int qnos[5] = { 15, 15, 15, 15, 15 }; /* No quantization */ + int *qnosp = &qnos[0]; + + dif = &s->buf[work_chunk->buf_offset * 80]; enc_blk = &enc_blks[0]; for (mb_index = 0; mb_index < 5; mb_index++) { dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y); /* initializing luminance blocks */ - if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || + if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) || (s->sys->height >= 720 && mb_y != 134)) { y_stride = s->frame->linesize[0] << 3; } else { y_stride = 16; } - y_ptr = s->frame->data[0] + ((mb_y * s->frame->linesize[0] + mb_x) << 3); + y_ptr = s->frame->data[0] + + ((mb_y * s->frame->linesize[0] + mb_x) << 3); linesize = s->frame->linesize[0]; if (s->sys->video_stype == 4) { /* SD 422 */ vs_bit_size += - dv_init_enc_block(enc_blk+0, y_ptr , linesize, s, 0) + - dv_init_enc_block(enc_blk+1, NULL , linesize, s, 0) + - dv_init_enc_block(enc_blk+2, y_ptr + 8 , linesize, s, 0) + - dv_init_enc_block(enc_blk+3, NULL , linesize, s, 0); + dv_init_enc_block(enc_blk + 0, y_ptr, linesize, s, 0) + + dv_init_enc_block(enc_blk + 1, NULL, linesize, s, 0) + + dv_init_enc_block(enc_blk + 2, y_ptr + 8, linesize, s, 0) + + dv_init_enc_block(enc_blk + 3, NULL, linesize, s, 0); } else { vs_bit_size += - dv_init_enc_block(enc_blk+0, y_ptr , linesize, s, 0) + - dv_init_enc_block(enc_blk+1, y_ptr + 8 , linesize, s, 0) + - dv_init_enc_block(enc_blk+2, y_ptr + y_stride, linesize, s, 0) + - dv_init_enc_block(enc_blk+3, y_ptr + 8 + y_stride, linesize, s, 0); + dv_init_enc_block(enc_blk + 0, y_ptr, linesize, s, 0) + + dv_init_enc_block(enc_blk + 1, y_ptr + 8, linesize, s, 0) + + dv_init_enc_block(enc_blk + 2, y_ptr + y_stride, linesize, s, 0) + + dv_init_enc_block(enc_blk + 3, y_ptr + 8 + y_stride, linesize, s, 0); } enc_blk += 4; @@ -449,23 +465,29 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) linesize = s->frame->linesize[j]; y_stride = (mb_y == 134) ? 8 : (s->frame->linesize[j] << 3); if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) { - uint8_t* d; - uint8_t* b = scratch; + uint8_t *d; + uint8_t *b = scratch; for (i = 0; i < 8; i++) { - d = c_ptr + (linesize << 3); - b[0] = c_ptr[0]; b[1] = c_ptr[1]; b[2] = c_ptr[2]; b[3] = c_ptr[3]; - b[4] = d[0]; b[5] = d[1]; b[6] = d[2]; b[7] = d[3]; + d = c_ptr + (linesize << 3); + b[0] = c_ptr[0]; + b[1] = c_ptr[1]; + b[2] = c_ptr[2]; + b[3] = c_ptr[3]; + b[4] = d[0]; + b[5] = d[1]; + b[6] = d[2]; + b[7] = d[3]; c_ptr += linesize; - b += 16; + b += 16; } - c_ptr = scratch; + c_ptr = scratch; linesize = 16; } - vs_bit_size += dv_init_enc_block( enc_blk++, c_ptr , linesize, s, 1); - if (s->sys->bpm == 8) { - vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr + y_stride, linesize, s, 1); - } + vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr, linesize, s, 1); + if (s->sys->bpm == 8) + vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr + y_stride, + linesize, s, 1); } } @@ -473,59 +495,60 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) dv_guess_qnos(&enc_blks[0], qnosp); /* DIF encoding process */ - for (j=0; j<5*s->sys->bpm;) { + for (j = 0; j < 5 * s->sys->bpm;) { int start_mb = j; dif[3] = *qnosp++; - dif += 4; + dif += 4; /* First pass over individual cells only */ - for (i=0; isys->bpm; i++, j++) { - int sz = s->sys->block_sizes[i]>>3; + for (i = 0; i < s->sys->bpm; i++, j++) { + int sz = s->sys->block_sizes[i] >> 3; init_put_bits(&pbs[j], dif, sz); put_sbits(&pbs[j], 9, ((enc_blks[j].mb[0] >> 3) - 1024 + 2) >> 2); put_bits(&pbs[j], 1, enc_blks[j].dct_mode); put_bits(&pbs[j], 2, enc_blks[j].cno); - dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]); + dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j + 1]); dif += sz; } /* Second pass over each MB space */ pb = &pbs[start_mb]; - for (i=0; isys->bpm; i++) { - if (enc_blks[start_mb+i].partial_bit_count) - pb = dv_encode_ac(&enc_blks[start_mb+i], pb, &pbs[start_mb+s->sys->bpm]); - } + for (i = 0; i < s->sys->bpm; i++) + if (enc_blks[start_mb + i].partial_bit_count) + pb = dv_encode_ac(&enc_blks[start_mb + i], pb, + &pbs[start_mb + s->sys->bpm]); } /* Third and final pass over the whole video segment space */ pb = &pbs[0]; - for (j=0; j<5*s->sys->bpm; j++) { - if (enc_blks[j].partial_bit_count) - pb = dv_encode_ac(&enc_blks[j], pb, &pbs[s->sys->bpm*5]); - if (enc_blks[j].partial_bit_count) + for (j = 0; j < 5 * s->sys->bpm; j++) { + if (enc_blks[j].partial_bit_count) + pb = dv_encode_ac(&enc_blks[j], pb, &pbs[s->sys->bpm * 5]); + if (enc_blks[j].partial_bit_count) av_log(avctx, AV_LOG_ERROR, "ac bitstream overflow\n"); } - for (j=0; j<5*s->sys->bpm; j++) { - int pos; - int size = pbs[j].size_in_bits >> 3; - flush_put_bits(&pbs[j]); - pos = put_bits_count(&pbs[j]) >> 3; - if (pos > size) { - av_log(avctx, AV_LOG_ERROR, "bitstream written beyond buffer size\n"); - return -1; - } - memset(pbs[j].buf + pos, 0xff, size - pos); + for (j = 0; j < 5 * s->sys->bpm; j++) { + int pos; + int size = pbs[j].size_in_bits >> 3; + flush_put_bits(&pbs[j]); + pos = put_bits_count(&pbs[j]) >> 3; + if (pos > size) { + av_log(avctx, AV_LOG_ERROR, + "bitstream written beyond buffer size\n"); + return -1; + } + memset(pbs[j].buf + pos, 0xff, size - pos); } return 0; } static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, - uint8_t* buf) + uint8_t *buf) { /* * Here's what SMPTE314M says about these two: @@ -545,62 +568,66 @@ static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, * 2. It is not at all clear what STYPE is used for 4:2:0 PAL * compression scheme (if any). */ - int apt = (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0 : 1); + int apt = (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0 : 1); uint8_t aspect = 0; - if ((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) >= 17) /* 16:9 */ + 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; + 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; + buf[1] = 0xf8 | /* reserved -- always 1 */ + (apt & 0x07); /* APT: Track application ID */ + buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP1: Audio application ID */ + buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP2: Video application ID */ + buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP3: Subcode application ID */ + break; case dv_video_source: - buf[1] = 0xff; /* reserved -- always 1 */ - buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */ - (1 << 6) | /* following CLF is valid - 0, invalid - 1 */ - (3 << 4) | /* CLF: color frames ID (see ITU-R BT.470-4) */ - 0xf; /* reserved -- always 1 */ - buf[3] = (3 << 6) | /* reserved -- always 1 */ - (c->sys->dsf << 5) | /* system: 60fields/50fields */ - c->sys->video_stype; /* signal type video compression */ - buf[4] = 0xff; /* VISC: 0xff -- no information */ - break; + buf[1] = 0xff; /* reserved -- always 1 */ + buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */ + (1 << 6) | /* following CLF is valid - 0, invalid - 1 */ + (3 << 4) | /* CLF: color frames ID (see ITU-R BT.470-4) */ + 0xf; /* reserved -- always 1 */ + buf[3] = (3 << 6) | /* reserved -- always 1 */ + (c->sys->dsf << 5) | /* system: 60fields/50fields */ + c->sys->video_stype; /* signal type video compression */ + buf[4] = 0xff; /* VISC: 0xff -- no information */ + break; case dv_video_control: - buf[1] = (0 << 6) | /* Copy generation management (CGMS) 0 -- free */ - 0x3f; /* reserved -- always 1 */ - buf[2] = 0xc8 | /* reserved -- always b11001xxx */ - aspect; - buf[3] = (1 << 7) | /* frame/field flag 1 -- frame, 0 -- field */ - (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; + 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; + buf[1] = + buf[2] = + buf[3] = + buf[4] = 0xff; } return 5; } 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) + uint8_t *buf) { - buf[0] = (uint8_t)t; /* Section type */ + 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 */ @@ -608,19 +635,16 @@ static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, return 3; } - -static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) +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) { + } else if (syb_num == 11) { buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */ 0x7f; /* reserved -- always 1 */ - } - else { + } 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 */ @@ -631,7 +655,7 @@ static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) return 3; } -static void dv_format_frame(DVVideoContext* c, uint8_t* buf) +static void dv_format_frame(DVVideoContext *c, uint8_t *buf) { int chan, i, j, k; @@ -641,14 +665,15 @@ static void dv_format_frame(DVVideoContext* c, uint8_t* buf) /* 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 += 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 += dv_write_ssyb_id(k, (i < c->sys->difseg_size / 2), buf) + 5; buf += 29; /* unused bytes */ } @@ -657,30 +682,29 @@ static void dv_format_frame(DVVideoContext* c, uint8_t* buf) 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 += 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 */ + 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) { + if (j % 15 == 0) { memset(buf, 0xff, 80); - buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf); + buf += dv_write_dif_id(dv_sect_audio, chan, i, j / 15, buf); buf += 77; /* audio control & shuffled PCM audio */ } buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf); buf += 77; /* 1 video macroblock: 1 bytes control - 4 * 14 bytes Y 8x8 data - 10 bytes Cr 8x8 data - 10 bytes Cb 8x8 data */ + * 4 * 14 bytes Y 8x8 data + * 10 bytes Cr 8x8 data + * 10 bytes Cb 8x8 data */ } } } } - static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -694,8 +718,12 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, c->pix_fmt = s->sys->pix_fmt; s->frame = frame; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS c->coded_frame->key_frame = 1; c->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->buf = pkt->data; c->execute(c, dv_encode_video_segment, s->work_chunks, NULL, @@ -711,12 +739,6 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, return 0; } -static int dvvideo_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - AVCodec ff_dvvideo_encoder = { .name = "dvvideo", .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), @@ -725,9 +747,9 @@ AVCodec ff_dvvideo_encoder = { .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_encode_init, .encode2 = dvvideo_encode_frame, - .close = dvvideo_encode_close, - .capabilities = CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/dxa.c b/libavcodec/dxa.c index 989fcb9..b804935 100644 --- a/libavcodec/dxa.c +++ b/libavcodec/dxa.c @@ -336,5 +336,5 @@ AVCodec ff_dxa_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 662cd9f..937b96c 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -22,14 +22,15 @@ #include +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" #include "get_bits.h" #include "internal.h" #include "unary.h" -#include "libavutil/common.h" -#include "libavutil/intreadwrite.h" static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, @@ -171,9 +172,9 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, return 0; } -const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF }; -const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F }; -const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F }; +static const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF }; +static const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F }; +static const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F }; static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8]) { @@ -192,6 +193,56 @@ static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8]) return val; } +static int check_slice_size(AVCodecContext *avctx, + const uint8_t *src, int src_size, + int slice_size, int off) +{ + int cur_slice_size; + + if (slice_size > src_size - off) { + av_log(avctx, AV_LOG_ERROR, + "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", + slice_size, src_size - off); + return AVERROR_INVALIDDATA; + } + if (slice_size <= 16) { + av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", + slice_size); + return AVERROR_INVALIDDATA; + } + + cur_slice_size = AV_RL32(src + off); + if (cur_slice_size != slice_size - 16) { + av_log(avctx, AV_LOG_ERROR, + "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", + cur_slice_size, slice_size - 16); + } + + return 0; +} + +static int load_buffer(AVCodecContext *avctx, + const uint8_t *src, int src_size, + GetByteContext *gb, + int *nslices, int *off) +{ + bytestream2_init(gb, src, src_size); + *nslices = bytestream2_get_le16(gb); + *off = FFALIGN(*nslices * 4 + 2, 16); + if (src_size < *off) { + av_log(avctx, AV_LOG_ERROR, "no slice data\n"); + return AVERROR_INVALIDDATA; + } + + if (!*nslices) { + avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices, + avctx->width, avctx->height); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8], int bits) { @@ -210,185 +261,182 @@ static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8], return val; } -static int dx2_decode_slice_565(GetBitContext *gb, int width, int height, - uint8_t *dst, int stride, int is_565) -{ - int x, y; - int r, g, b; - uint8_t lru[3][8]; +typedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame, + int line, int height, uint8_t lru[3][8]); - memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); - memcpy(lru[1], is_565 ? def_lru_565 : def_lru_555, 8 * sizeof(*def_lru)); - memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); +typedef void (*setup_lru_func)(uint8_t lru[3][8]); - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - b = decode_sym_565(gb, lru[0], 5); - g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); - r = decode_sym_565(gb, lru[2], 5); - dst[x * 3 + 0] = (r << 3) | (r >> 2); - dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); - dst[x * 3 + 2] = (b << 3) | (b >> 2); - } - - dst += stride; - } - - return 0; -} - -static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size, int is_565) +static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size, + decode_slice_func decode_slice, + setup_lru_func setup_lru, + enum AVPixelFormat fmt) { GetByteContext gb; GetBitContext gb2; - int nslices, slice, slice_height; + int nslices, slice, line = 0; uint32_t off, slice_size; - uint8_t *dst; + uint8_t lru[3][8]; int ret; - bytestream2_init(&gb, src, src_size); - nslices = bytestream2_get_le16(&gb); - off = FFALIGN(nslices * 4 + 2, 16); - if (src_size < off) { - av_log(avctx, AV_LOG_ERROR, "no slice data\n"); - return AVERROR_INVALIDDATA; - } - - if (!nslices || avctx->height % nslices) { - avpriv_request_sample(avctx, "%d slices for %dx%d", nslices, - avctx->width, avctx->height); - return AVERROR_PATCHWELCOME; - } + ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); + if (ret < 0) + return ret; - slice_height = avctx->height / nslices; - avctx->pix_fmt = AV_PIX_FMT_RGB24; + avctx->pix_fmt = fmt; if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - dst = pic->data[0]; for (slice = 0; slice < nslices; slice++) { slice_size = bytestream2_get_le32(&gb); - if (slice_size > src_size - off) { - av_log(avctx, AV_LOG_ERROR, - "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", - slice_size, src_size - off); - return AVERROR_INVALIDDATA; - } - if (slice_size <= 16) { - av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size); - return AVERROR_INVALIDDATA; - } - if (AV_RL32(src + off) != slice_size - 16) { - av_log(avctx, AV_LOG_ERROR, - "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", - AV_RL32(src + off), slice_size - 16); - } + setup_lru(lru); + + ret = check_slice_size(avctx, src, src_size, slice_size, off); + if (ret < 0) + return ret; + init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8); - dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst, - pic->linesize[0], is_565); - dst += pic->linesize[0] * slice_height; + line += decode_slice(&gb2, pic, line, avctx->height - line, lru); + off += slice_size; } + if (avctx->height - line) { + av_log(avctx, AV_LOG_VERBOSE, + "Not enough slice data available, " + "cropping the frame by %d pixels\n", + avctx->height - line); + avctx->height = line; + } + return 0; } -static int dx2_decode_slice_rgb(GetBitContext *gb, int width, int height, - uint8_t *dst, int stride) +av_always_inline +static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8], + int is_565) { - int x, y, i; - uint8_t lru[3][8]; - - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); + int x, y; + int r, g, b; + int width = frame->width; + int stride = frame->linesize[0]; + uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < height; y++) { + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { for (x = 0; x < width; x++) { - dst[x * 3 + 0] = decode_sym(gb, lru[0]); - dst[x * 3 + 1] = decode_sym(gb, lru[1]); - dst[x * 3 + 2] = decode_sym(gb, lru[2]); + b = decode_sym_565(gb, lru[0], 5); + g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); + r = decode_sym_565(gb, lru[2], 5); + dst[x * 3 + 0] = (r << 3) | (r >> 2); + dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); + dst[x * 3 + 2] = (b << 3) | (b >> 2); } dst += stride; } - return 0; + return y; } -static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) +static void setup_lru_555(uint8_t lru[3][8]) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - uint32_t off, slice_size; - uint8_t *dst; - int ret; + memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); +} - bytestream2_init(&gb, src, src_size); - nslices = bytestream2_get_le16(&gb); - off = FFALIGN(nslices * 4 + 2, 16); - if (src_size < off) { - av_log(avctx, AV_LOG_ERROR, "no slice data\n"); - return AVERROR_INVALIDDATA; - } +static void setup_lru_565(uint8_t lru[3][8]) +{ + memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); + memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru)); + memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); +} - if (!nslices || avctx->height % nslices) { - avpriv_request_sample(avctx, "%d slices for %dx%d", nslices, - avctx->width, avctx->height); - return AVERROR_PATCHWELCOME; - } +static int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0); +} - slice_height = avctx->height / nslices; - avctx->pix_fmt = AV_PIX_FMT_BGR24; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; +static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1); +} - dst = pic->data[0]; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - if (slice_size > src_size - off) { - av_log(avctx, AV_LOG_ERROR, - "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", - slice_size, src_size - off); - return AVERROR_INVALIDDATA; - } - if (slice_size <= 16) { - av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", - slice_size); - return AVERROR_INVALIDDATA; - } +static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size, int is_565) +{ + enum AVPixelFormat fmt = AV_PIX_FMT_RGB24; + if (is_565) + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_565, + setup_lru_565, + fmt); + else + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_555, + setup_lru_555, + fmt); +} - if (AV_RL32(src + off) != slice_size - 16) { - av_log(avctx, AV_LOG_ERROR, - "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", - AV_RL32(src + off), slice_size - 16); +static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, + int line, int left, uint8_t lru[3][8]) +{ + int x, y; + int width = frame->width; + int stride = frame->linesize[0]; + uint8_t *dst = frame->data[0] + stride * line; + + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { + for (x = 0; x < width; x++) { + dst[x * 3 + 0] = decode_sym(gb, lru[0]); + dst[x * 3 + 1] = decode_sym(gb, lru[1]); + dst[x * 3 + 2] = decode_sym(gb, lru[2]); } - init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8); - dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst, - pic->linesize[0]); - dst += pic->linesize[0] * slice_height; - off += slice_size; + dst += stride; } - return 0; + return y; } -static int dx2_decode_slice_410(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) +static void default_setup_lru(uint8_t lru[3][8]) { - int x, y, i, j; - uint8_t lru[3][8]; + int i; for (i = 0; i < 3; i++) memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); +} - for (y = 0; y < height; y += 4) { +static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, + const uint8_t *src, int src_size) +{ + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_rgb, + default_setup_lru, + AV_PIX_FMT_BGR24); +} + +static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) +{ + int x, y, i, j; + int width = frame->width; + + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; + + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + (ustride >> 2) * line; + uint8_t *V = frame->data[2] + (vstride >> 2) * line; + + for (y = 0; y < left - 3 && get_bits_left(gb) > 16; y += 4) { for (x = 0; x < width; x += 4) { for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) @@ -402,96 +450,37 @@ static int dx2_decode_slice_410(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } + static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height, ref_slice_height; - int cur_y, next_y; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - bytestream2_init(&gb, src, src_size); - nslices = bytestream2_get_le16(&gb); - off = FFALIGN(nslices * 4 + 2, 16); - if (src_size < off) { - av_log(avctx, AV_LOG_ERROR, "no slice data\n"); - return AVERROR_INVALIDDATA; - } - - if (!nslices || avctx->height % nslices) { - avpriv_request_sample(avctx, "%d slices for %dx%d", nslices, - avctx->width, avctx->height); - return AVERROR_PATCHWELCOME; - } - - ref_slice_height = avctx->height / nslices; - if ((avctx->width & 3) || (avctx->height & 3)) { - avpriv_request_sample(avctx, "Frame dimensions %dx%d", - avctx->width, avctx->height); - } - - avctx->pix_fmt = AV_PIX_FMT_YUV410P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_410, + default_setup_lru, + AV_PIX_FMT_YUV410P); +} - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; +static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) +{ + int x, y; - cur_y = 0; - next_y = ref_slice_height; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - slice_height = (next_y & ~3) - (cur_y & ~3); - if (slice_size > src_size - off) { - av_log(avctx, AV_LOG_ERROR, - "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", - slice_size, src_size - off); - return AVERROR_INVALIDDATA; - } - if (slice_size <= 16) { - av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size); - return AVERROR_INVALIDDATA; - } + int width = frame->width; - if (AV_RL32(src + off) != slice_size - 16) { - av_log(avctx, AV_LOG_ERROR, - "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", - AV_RL32(src + off), slice_size - 16); - } - init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8); - dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * (slice_height >> 2); - V += pic->linesize[2] * (slice_height >> 2); - off += slice_size; - cur_y = next_y; - next_y += ref_slice_height; - } + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + (ustride >> 1) * line; + uint8_t *V = frame->data[2] + (vstride >> 1) * line; - return 0; -} -static int dx2_decode_slice_420(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) -{ - int x, y, i; - uint8_t lru[3][8]; - - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); - - for (y = 0; y < height; y+=2) { + for (y = 0; y < left - 1 && get_bits_left(gb) > 16; y += 2) { for (x = 0; x < width; x += 2) { Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); @@ -506,96 +495,35 @@ static int dx2_decode_slice_420(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height, ref_slice_height; - int cur_y, next_y; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - bytestream2_init(&gb, src, src_size); - nslices = bytestream2_get_le16(&gb); - off = FFALIGN(nslices * 4 + 2, 16); - if (src_size < off) { - av_log(avctx, AV_LOG_ERROR, "no slice data\n"); - return AVERROR_INVALIDDATA; - } - - if (!nslices || avctx->height % nslices) { - avpriv_request_sample(avctx, "%d slices for %dx%d", nslices, - avctx->width, avctx->height); - return AVERROR_PATCHWELCOME; - } - - ref_slice_height = avctx->height / nslices; - if ((avctx->width & 1) || (avctx->height & 1)) { - avpriv_request_sample(avctx, "Frame dimensions %dx%d", - avctx->width, avctx->height); - } - - avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; - - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; - - cur_y = 0; - next_y = ref_slice_height; - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - slice_height = (next_y & ~1) - (cur_y & ~1); - if (slice_size > src_size - off) { - av_log(avctx, AV_LOG_ERROR, - "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", - slice_size, src_size - off); - return AVERROR_INVALIDDATA; - } - if (slice_size <= 16) { - av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size); - return AVERROR_INVALIDDATA; - } - - if (AV_RL32(src + off) != slice_size - 16) { - av_log(avctx, AV_LOG_ERROR, - "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", - AV_RL32(src + off), slice_size - 16); - } - init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8); - dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); - - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * (slice_height >> 1); - V += pic->linesize[2] * (slice_height >> 1); - off += slice_size; - cur_y = next_y; - next_y += ref_slice_height; - } - - return 0; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_420, + default_setup_lru, + AV_PIX_FMT_YUV420P); } -static int dx2_decode_slice_444(GetBitContext *gb, int width, int height, - uint8_t *Y, uint8_t *U, uint8_t *V, - int ystride, int ustride, int vstride) +static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, + int line, int left, + uint8_t lru[3][8]) { - int x, y, i; - uint8_t lru[3][8]; + int x, y; - for (i = 0; i < 3; i++) - memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); + int width = frame->width; + + int ystride = frame->linesize[0]; + int ustride = frame->linesize[1]; + int vstride = frame->linesize[2]; - for (y = 0; y < height; y++) { + uint8_t *Y = frame->data[0] + ystride * line; + uint8_t *U = frame->data[1] + ustride * line; + uint8_t *V = frame->data[2] + vstride * line; + + for (y = 0; y < left && get_bits_left(gb) > 16; y++) { for (x = 0; x < width; x++) { Y[x] = decode_sym(gb, lru[0]); U[x] = decode_sym(gb, lru[1]) ^ 0x80; @@ -607,73 +535,16 @@ static int dx2_decode_slice_444(GetBitContext *gb, int width, int height, V += vstride; } - return 0; + return y; } static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size) { - GetByteContext gb; - GetBitContext gb2; - int nslices, slice, slice_height; - uint32_t off, slice_size; - uint8_t *Y, *U, *V; - int ret; - - bytestream2_init(&gb, src, src_size); - nslices = bytestream2_get_le16(&gb); - off = FFALIGN(nslices * 4 + 2, 16); - if (src_size < off) { - av_log(avctx, AV_LOG_ERROR, "no slice data\n"); - return AVERROR_INVALIDDATA; - } - - if (!nslices || avctx->height % nslices) { - avpriv_request_sample(avctx, "%d slices for %dx%d", nslices, - avctx->width, avctx->height); - return AVERROR_PATCHWELCOME; - } - - slice_height = avctx->height / nslices; - - avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; - - Y = pic->data[0]; - U = pic->data[1]; - V = pic->data[2]; - - for (slice = 0; slice < nslices; slice++) { - slice_size = bytestream2_get_le32(&gb); - if (slice_size > src_size - off) { - av_log(avctx, AV_LOG_ERROR, - "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n", - slice_size, src_size - off); - return AVERROR_INVALIDDATA; - } - if (slice_size <= 16) { - av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size); - return AVERROR_INVALIDDATA; - } - - if (AV_RL32(src + off) != slice_size - 16) { - av_log(avctx, AV_LOG_ERROR, - "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n", - AV_RL32(src + off), slice_size - 16); - } - init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8); - dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V, - pic->linesize[0], pic->linesize[1], - pic->linesize[2]); - - Y += pic->linesize[0] * slice_height; - U += pic->linesize[1] * slice_height; - V += pic->linesize[2] * slice_height; - off += slice_size; - } - - return 0; + return dxtory_decode_v2(avctx, pic, src, src_size, + dx2_decode_slice_444, + default_setup_lru, + AV_PIX_FMT_YUV444P); } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, @@ -751,5 +622,5 @@ AVCodec ff_dxtory_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DXTORY, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c new file mode 100644 index 0000000..99327df --- /dev/null +++ b/libavcodec/dxv.c @@ -0,0 +1,504 @@ +/* + * Resolume DXV decoder + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "lzf.h" +#include "texturedsp.h" +#include "thread.h" + +typedef struct DXVContext { + TextureDSPContext texdsp; + GetByteContext gbc; + + uint8_t *tex_data; // Compressed texture + int tex_rat; // Compression ratio + int tex_step; // Distance between blocks + int64_t tex_size; // Texture size + + /* Optimal number of slices for parallel decoding */ + int slice_count; + + /* Pointer to the selected decompression function */ + int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); +} DXVContext; + +static int decompress_texture_thread(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + DXVContext *ctx = avctx->priv_data; + AVFrame *frame = arg; + const uint8_t *d = ctx->tex_data; + int w_block = avctx->coded_width / TEXTURE_BLOCK_W; + int h_block = avctx->coded_height / TEXTURE_BLOCK_H; + int x, y; + int start_slice, end_slice; + int base_blocks_per_slice = h_block / ctx->slice_count; + int remainder_blocks = h_block % ctx->slice_count; + + /* When the frame height (in blocks) doesn't divide evenly between the + * number of slices, spread the remaining blocks evenly between the first + * operations */ + start_slice = slice * base_blocks_per_slice; + /* Add any extra blocks (one per slice) that have been added + * before this slice */ + start_slice += FFMIN(slice, remainder_blocks); + + end_slice = start_slice + base_blocks_per_slice; + /* Add an extra block if there are remainder blocks to be accounted for */ + if (slice < remainder_blocks) + end_slice++; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_funct(p + x * 16, frame->linesize[0], + d + (off + x) * ctx->tex_step); + } + } + + return 0; +} + +/* This scheme addresses already decoded elements depending on 2-bit status: + * 0 -> copy new element + * 1 -> copy one element from position -x + * 2 -> copy one element from position -(get_byte() + 2) * x + * 3 -> copy one element from position -(get_16le() + 0x102) * x + * x is always 2 for dxt1 and 4 for dxt5. */ +#define CHECKPOINT(x) \ + do { \ + if (state == 0) { \ + value = bytestream2_get_le32(gbc); \ + state = 16; \ + } \ + op = value & 0x3; \ + value >>= 2; \ + state--; \ + switch (op) { \ + case 1: \ + idx = x; \ + break; \ + case 2: \ + idx = (bytestream2_get_byte(gbc) + 2) * x; \ + break; \ + case 3: \ + idx = (bytestream2_get_le16(gbc) + 0x102) * x; \ + break; \ + } \ + } while(0) + +static int dxv_decompress_dxt1(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + uint32_t value, prev, op; + int idx = 0, state = 0; + int pos = 2; + + /* Copy the first two elements */ + AV_WL32(ctx->tex_data, bytestream2_get_le32(gbc)); + AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc)); + + /* Process input until the whole texture has been filled */ + while (pos + 2 <= ctx->tex_size / 4) { + CHECKPOINT(2); + + /* Copy two elements from a previous offset or from the input buffer */ + if (op) { + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + } else { + CHECKPOINT(2); + + if (op) + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + else + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + CHECKPOINT(2); + + if (op) + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + else + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + } + } + + return 0; +} + +static int dxv_decompress_dxt5(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + uint32_t value, op; + int idx, prev, state = 0; + int pos = 4; + int run = 0; + int probe, check; + + /* Copy the first four elements */ + AV_WL32(ctx->tex_data + 0, bytestream2_get_le32(gbc)); + AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc)); + AV_WL32(ctx->tex_data + 8, bytestream2_get_le32(gbc)); + AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc)); + + /* Process input until the whole texture has been filled */ + while (pos + 2 <= ctx->tex_size / 4) { + if (run) { + run--; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + } else { + if (state == 0) { + value = bytestream2_get_le32(gbc); + state = 16; + } + op = value & 0x3; + value >>= 2; + state--; + + switch (op) { + case 0: + /* Long copy */ + check = bytestream2_get_byte(gbc) + 1; + if (check == 256) { + do { + probe = bytestream2_get_le16(gbc); + check += probe; + } while (probe == 0xFFFF); + } + while (check && pos + 4 <= ctx->tex_size / 4) { + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + check--; + } + + /* Restart (or exit) the loop */ + continue; + break; + case 1: + /* Load new run value */ + run = bytestream2_get_byte(gbc); + if (run == 255) { + do { + probe = bytestream2_get_le16(gbc); + run += probe; + } while (probe == 0xFFFF); + } + + /* Copy two dwords from previous data */ + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - 4)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + break; + case 2: + /* Copy two dwords from a previous index */ + idx = 8 + bytestream2_get_le16(gbc); + if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4) + return AVERROR_INVALIDDATA; + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + break; + case 3: + /* Copy two dwords from input */ + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + break; + } + } + + CHECKPOINT(4); + if (pos + 2 > ctx->tex_size / 4) + return AVERROR_INVALIDDATA; + + /* Copy two elements from a previous offset or from the input buffer */ + if (op) { + if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4) + return AVERROR_INVALIDDATA; + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + } else { + CHECKPOINT(4); + + if (op && (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)) + return AVERROR_INVALIDDATA; + if (op) + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + else + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + + CHECKPOINT(4); + + if (op) + prev = AV_RL32(ctx->tex_data + 4 * (pos - idx)); + else + prev = bytestream2_get_le32(gbc); + AV_WL32(ctx->tex_data + 4 * pos, prev); + pos++; + } + } + + return 0; +} + +static int dxv_decompress_lzf(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + return ff_lzf_uncompress(&ctx->gbc, &ctx->tex_data, &ctx->tex_size); +} + +static int dxv_decompress_raw(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + + bytestream2_get_buffer(gbc, ctx->tex_data, ctx->tex_size); + return 0; +} + +static int dxv_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + DXVContext *ctx = avctx->priv_data; + ThreadFrame tframe; + GetByteContext *gbc = &ctx->gbc; + int (*decompress_tex)(AVCodecContext *avctx); + const char *msgcomp, *msgtext; + uint32_t tag; + int version_major, version_minor = 0; + int size = 0, old_type = 0; + int ret; + + bytestream2_init(gbc, avpkt->data, avpkt->size); + + tag = bytestream2_get_le32(gbc); + switch (tag) { + case MKBETAG('D', 'X', 'T', '1'): + decompress_tex = dxv_decompress_dxt1; + ctx->tex_funct = ctx->texdsp.dxt1_block; + ctx->tex_rat = 8; + ctx->tex_step = 8; + msgcomp = "DXTR1"; + msgtext = "DXT1"; + break; + case MKBETAG('D', 'X', 'T', '5'): + decompress_tex = dxv_decompress_dxt5; + ctx->tex_funct = ctx->texdsp.dxt5_block; + ctx->tex_rat = 4; + ctx->tex_step = 16; + msgcomp = "DXTR5"; + msgtext = "DXT5"; + break; + case MKBETAG('Y', 'C', 'G', '6'): + case MKBETAG('Y', 'G', '1', '0'): + avpriv_report_missing_feature(avctx, "Tag 0x%08X", tag); + return AVERROR_PATCHWELCOME; + default: + /* Old version does not have a real header, just size and type. */ + size = tag & 0x00FFFFFF; + old_type = tag >> 24; + version_major = (old_type & 0x0F) - 1; + + if (old_type & 0x80) { + msgcomp = "RAW"; + decompress_tex = dxv_decompress_raw; + } else { + msgcomp = "LZF"; + decompress_tex = dxv_decompress_lzf; + } + + if (old_type & 0x40) { + msgtext = "DXT5"; + + ctx->tex_funct = ctx->texdsp.dxt5_block; + ctx->tex_step = 16; + } else if (old_type & 0x20 || version_major == 1) { + msgtext = "DXT1"; + + ctx->tex_funct = ctx->texdsp.dxt1_block; + ctx->tex_step = 8; + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08X)\n.", tag); + return AVERROR_INVALIDDATA; + } + ctx->tex_rat = 1; + break; + } + + /* New header is 12 bytes long. */ + if (!old_type) { + version_major = bytestream2_get_byte(gbc) - 1; + version_minor = bytestream2_get_byte(gbc); + + /* Encoder copies texture data when compression is not advantageous. */ + if (bytestream2_get_byte(gbc)) { + msgcomp = "RAW"; + ctx->tex_rat = 1; + decompress_tex = dxv_decompress_raw; + } + + bytestream2_skip(gbc, 1); // unknown + size = bytestream2_get_le32(gbc); + } + av_log(avctx, AV_LOG_DEBUG, + "%s compression with %s texture (version %d.%d)\n", + msgcomp, msgtext, version_major, version_minor); + + if (size != bytestream2_get_bytes_left(gbc)) { + av_log(avctx, AV_LOG_ERROR, + "Incomplete or invalid file (header %d, left %d).\n", + size, bytestream2_get_bytes_left(gbc)); + return AVERROR_INVALIDDATA; + } + + ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat; + ret = av_reallocp(&ctx->tex_data, ctx->tex_size); + if (ret < 0) + return ret; + + /* Decompress texture out of the intermediate compression. */ + ret = decompress_tex(avctx); + if (ret < 0) + return ret; + + tframe.f = data; + ret = ff_thread_get_buffer(avctx, &tframe, 0); + if (ret < 0) + return ret; + ff_thread_finish_setup(avctx); + + /* Now decompress the texture with the standard functions. */ + avctx->execute2(avctx, decompress_texture_thread, + tframe.f, NULL, ctx->slice_count); + + /* Frame is ready to be output. */ + tframe.f->pict_type = AV_PICTURE_TYPE_I; + tframe.f->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +static int dxv_init(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + /* Codec requires 16x16 alignment. */ + avctx->coded_width = FFALIGN(avctx->width, 16); + avctx->coded_height = FFALIGN(avctx->height, 16); + + ff_texturedsp_init(&ctx->texdsp); + avctx->pix_fmt = AV_PIX_FMT_RGBA; + + ctx->slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / TEXTURE_BLOCK_H); + + return 0; +} + +static int dxv_close(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + + av_freep(&ctx->tex_data); + + return 0; +} + +AVCodec ff_dxv_decoder = { + .name = "dxv", + .long_name = NULL_IF_CONFIG_SMALL("Resolume DXV"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DXV, + .init = dxv_init, + .decode = dxv_decode, + .close = dxv_close, + .priv_data_size = sizeof(DXVContext), + .capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 9ee22c8..9157094 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -27,7 +27,6 @@ #include "libavutil/time.h" #include "avcodec.h" -#include "mpegvideo.h" #include "dxva2_internal.h" void *ff_dxva2_get_surface(const AVFrame *frame) @@ -35,14 +34,15 @@ void *ff_dxva2_get_surface(const AVFrame *frame) return frame->data[3]; } -unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, +unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, + const AVDXVAContext *ctx, const AVFrame *frame) { void *surface = ff_dxva2_get_surface(frame); unsigned i; - for (i = 0; i < ctx->surface_count; i++) - if (ctx->surface[i] == surface) + for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) + if (DXVA_CONTEXT_SURFACE(avctx, ctx, i) == surface) return i; assert(0); @@ -50,8 +50,8 @@ unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, } int ff_dxva2_commit_buffer(AVCodecContext *avctx, - struct dxva_context *ctx, - DXVA2_DecodeBufferDesc *dsc, + AVDXVAContext *ctx, + DECODER_BUFFER_DESC *dsc, unsigned type, const void *data, unsigned size, unsigned mb_count) { @@ -60,8 +60,18 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, int result; HRESULT hr; - hr = IDirectXVideoDecoder_GetBuffer(ctx->decoder, type, - &dxva_data, &dxva_size); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data); +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type, + &dxva_data, &dxva_size); +#endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n", type, hr); @@ -70,10 +80,24 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, if (size <= dxva_size) { memcpy(dxva_data, data, size); - memset(dsc, 0, sizeof(*dsc)); - dsc->CompressedBufferType = type; - dsc->DataSize = size; - dsc->NumMBsInBuffer = mb_count; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = size; + dsc11->NumMBsInBuffer = mb_count; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = dsc; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = size; + dsc2->NumMBsInBuffer = mb_count; + } +#endif result = 0; } else { @@ -81,7 +105,14 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, result = -1; } - hr = IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type); +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type); +#endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %u: 0x%lx\n", @@ -95,31 +126,72 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int (*commit_bs_si)(AVCodecContext *, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *slice)) + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *slice)) { - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; unsigned buffer_count = 0; - DXVA2_DecodeBufferDesc buffer[4]; - DXVA2_DecodeExecuteParams exec = { 0 }; +#if CONFIG_D3D11VA + D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4]; +#endif +#if CONFIG_DXVA2 + DXVA2_DecodeBufferDesc buffer2[4]; +#endif + DECODER_BUFFER_DESC *buffer,*buffer_slice; int result, runs = 0; HRESULT hr; + unsigned type; do { - hr = IDirectXVideoDecoder_BeginFrame(ctx->decoder, - ff_dxva2_get_surface(frame), - NULL); - if (hr == E_PENDING) - av_usleep(2000); - } while (hr == E_PENDING && ++runs < 50); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); + hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, + ff_dxva2_get_surface(frame), + 0, NULL); + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder, + ff_dxva2_get_surface(frame), + NULL); +#endif + if (hr != E_PENDING || ++runs > 50) + break; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); +#endif + av_usleep(2000); + } while(1); if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); +#endif return -1; } - result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], - DXVA2_PictureParametersBufferType, +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + buffer = &buffer11[buffer_count]; + type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + buffer = &buffer2[buffer_count]; + type = DXVA2_PictureParametersBufferType; + } +#endif + result = ff_dxva2_commit_buffer(avctx, ctx, buffer, + type, pp, pp_size, 0); if (result) { av_log(avctx, AV_LOG_ERROR, @@ -129,8 +201,20 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, buffer_count++; if (qm_size > 0) { - result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], - DXVA2_InverseQuantizationMatrixBufferType, +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + buffer = &buffer11[buffer_count]; + type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + buffer = &buffer2[buffer_count]; + type = DXVA2_InverseQuantizationMatrixBufferType; + } +#endif + result = ff_dxva2_commit_buffer(avctx, ctx, buffer, + type, qm, qm_size, 0); if (result) { av_log(avctx, AV_LOG_ERROR, @@ -140,9 +224,22 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, buffer_count++; } +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + buffer = &buffer11[buffer_count + 0]; + buffer_slice = &buffer11[buffer_count + 1]; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + buffer = &buffer2[buffer_count + 0]; + buffer_slice = &buffer2[buffer_count + 1]; + } +#endif + result = commit_bs_si(avctx, - &buffer[buffer_count + 0], - &buffer[buffer_count + 1]); + buffer, + buffer_slice); if (result) { av_log(avctx, AV_LOG_ERROR, "Failed to add bitstream or slice control buffer\n"); @@ -154,17 +251,39 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, assert(buffer_count == 1 + (qm_size > 0) + 2); - exec.NumCompBuffers = buffer_count; - exec.pCompressedBuffers = buffer; - exec.pExtensionData = NULL; - hr = IDirectXVideoDecoder_Execute(ctx->decoder, &exec); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + buffer_count, buffer11); +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeExecuteParams exec = { + .NumCompBuffers = buffer_count, + .pCompressedBuffers = buffer2, + .pExtensionData = NULL, + }; + hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec); + } +#endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr); result = -1; } end: - hr = IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder); + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL); +#endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr); result = -1; diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h index 78939be..ec448a4 100644 --- a/libavcodec/dxva2.h +++ b/libavcodec/dxva2.h @@ -29,7 +29,11 @@ * Public libavcodec DXVA2 header. */ -#define _WIN32_WINNT 0x0600 +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + #include #include #include diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index fa205c4..5622c22 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -1,5 +1,5 @@ /* - * DXVA2 H264 HW acceleration. + * DXVA2 H.264 HW acceleration. * * copyright (c) 2009 Laurent Aimar * @@ -20,11 +20,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dxva2_internal.h" -#include "h264.h" +#include "h264dec.h" #include "h264data.h" +#include "h264_ps.h" #include "mpegutils.h" +// The headers above may include w32threads.h, which uses the original +// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a +// potentially newer version. +#include "dxva2_internal.h" + struct dxva2_picture_context { DXVA_PicParams_H264 pp; DXVA_Qmatrix_H264 qm; @@ -42,16 +47,18 @@ static void fill_picture_entry(DXVA_PicEntry_H264 *pic, pic->bPicEntry = index | (flag << 7); } -static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h, +static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_PicParams_H264 *pp) { const H264Picture *current_picture = h->cur_pic_ptr; + const SPS *sps = h->ps.sps; + const PPS *pps = h->ps.pps; int i, j; memset(pp, 0, sizeof(*pp)); /* Configure current picture */ fill_picture_entry(&pp->CurrPic, - ff_dxva2_get_surface_index(ctx, ¤t_picture->f), + ff_dxva2_get_surface_index(avctx, ctx, current_picture->f), h->picture_structure == PICT_BOTTOM_FIELD); /* Configure the set of references */ pp->UsedForReferenceFlags = 0; @@ -67,7 +74,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context } if (r) { fill_picture_entry(&pp->RefFrameList[i], - ff_dxva2_get_surface_index(ctx, &r->f), + ff_dxva2_get_surface_index(avctx, ctx, r->f), r->long_ref != 0); if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX) @@ -90,37 +97,37 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context pp->wFrameWidthInMbsMinus1 = h->mb_width - 1; pp->wFrameHeightInMbsMinus1 = h->mb_height - 1; - pp->num_ref_frames = h->sps.ref_frame_count; + pp->num_ref_frames = sps->ref_frame_count; pp->wBitFields = ((h->picture_structure != PICT_FRAME) << 0) | - ((h->sps.mb_aff && + ((sps->mb_aff && (h->picture_structure == PICT_FRAME)) << 1) | - (h->sps.residual_color_transform_flag << 2) | + (sps->residual_color_transform_flag << 2) | /* sp_for_switch_flag (not implemented by Libav) */ (0 << 3) | - (h->sps.chroma_format_idc << 4) | + (sps->chroma_format_idc << 4) | ((h->nal_ref_idc != 0) << 6) | - (h->pps.constrained_intra_pred << 7) | - (h->pps.weighted_pred << 8) | - (h->pps.weighted_bipred_idc << 9) | + (pps->constrained_intra_pred << 7) | + (pps->weighted_pred << 8) | + (pps->weighted_bipred_idc << 9) | /* MbsConsecutiveFlag */ (1 << 11) | - (h->sps.frame_mbs_only_flag << 12) | - (h->pps.transform_8x8_mode << 13) | - ((h->sps.level_idc >= 31) << 14) | + (sps->frame_mbs_only_flag << 12) | + (pps->transform_8x8_mode << 13) | + ((sps->level_idc >= 31) << 14) | /* IntraPicFlag (Modified if we detect a non * intra slice in dxva2_h264_decode_slice) */ (1 << 15); - pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; - pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) + pp->bit_depth_luma_minus8 = sps->bit_depth_luma - 8; + pp->bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8; + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) pp->Reserved16Bits = 0; - else if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + else if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) pp->Reserved16Bits = 0x34c; else pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ - pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; + pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; pp->CurrFieldOrderCnt[0] = 0; if ((h->picture_structure & PICT_TOP_FIELD) && current_picture->field_poc[0] != INT_MAX) @@ -129,63 +136,64 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context if ((h->picture_structure & PICT_BOTTOM_FIELD) && current_picture->field_poc[1] != INT_MAX) pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1]; - pp->pic_init_qs_minus26 = h->pps.init_qs - 26; - pp->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; - pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + pp->pic_init_qs_minus26 = pps->init_qs - 26; + pp->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; + pp->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; pp->ContinuationFlag = 1; - pp->pic_init_qp_minus26 = h->pps.init_qp - 26; - pp->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; - pp->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; + pp->pic_init_qp_minus26 = pps->init_qp - 26; + pp->num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1; + pp->num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1; pp->Reserved8BitsA = 0; - pp->frame_num = h->frame_num; - pp->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; - pp->pic_order_cnt_type = h->sps.poc_type; - if (h->sps.poc_type == 0) - pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; - else if (h->sps.poc_type == 1) - pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; - pp->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; - pp->entropy_coding_mode_flag = h->pps.cabac; - pp->pic_order_present_flag = h->pps.pic_order_present; - pp->num_slice_groups_minus1 = h->pps.slice_group_count - 1; - pp->slice_group_map_type = h->pps.mb_slice_group_map_type; - pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; - pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present; + pp->frame_num = h->poc.frame_num; + pp->log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4; + pp->pic_order_cnt_type = sps->poc_type; + if (sps->poc_type == 0) + pp->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4; + else if (sps->poc_type == 1) + pp->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pp->direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pp->entropy_coding_mode_flag = pps->cabac; + pp->pic_order_present_flag = pps->pic_order_present; + pp->num_slice_groups_minus1 = pps->slice_group_count - 1; + pp->slice_group_map_type = pps->mb_slice_group_map_type; + pp->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present; + pp->redundant_pic_cnt_present_flag= pps->redundant_pic_cnt_present; pp->Reserved8BitsB = 0; pp->slice_group_change_rate_minus1= 0; /* XXX not implemented by Libav */ //pp->SliceGroupMap[810]; /* XXX not implemented by Libav */ } -static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) +static void fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) { unsigned i, j; + const PPS *pps = h->ps.pps; memset(qm, 0, sizeof(*qm)); - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { for (i = 0; i < 6; i++) for (j = 0; j < 16; j++) - qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j]; + qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][j]; for (i = 0; i < 64; i++) { - qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][i]; - qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][i]; + qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][i]; + qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][i]; } } else { for (i = 0; i < 6; i++) for (j = 0; j < 16; j++) - qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]]; + qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]]; for (i = 0; i < 64; i++) { - qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][ff_zigzag_direct[i]]; - qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][ff_zigzag_direct[i]]; + qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][ff_zigzag_direct[i]]; + qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][ff_zigzag_direct[i]]; } } } -static int is_slice_short(struct dxva_context *ctx) +static int is_slice_short(const AVCodecContext *avctx, AVDXVAContext *ctx) { - assert(ctx->cfg->ConfigBitstreamRaw == 1 || - ctx->cfg->ConfigBitstreamRaw == 2); - return ctx->cfg->ConfigBitstreamRaw == 2; + assert(DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 1 || + DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2); + return DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2; } static void fill_slice_short(DXVA_Slice_H264_Short *slice, @@ -211,7 +219,8 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, const DXVA_PicParams_H264 *pp, unsigned position, unsigned size) { const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + H264SliceContext *sl = &h->slice_ctx[0]; + AVDXVAContext *ctx = avctx->hwaccel_context; unsigned list; memset(slice, 0, sizeof(*slice)); @@ -219,46 +228,46 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, slice->SliceBytesInBuffer = size; slice->wBadSliceChopping = 0; - slice->first_mb_in_slice = (h->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + h->mb_x; + slice->first_mb_in_slice = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x; slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices */ - slice->BitOffsetToSliceData = get_bits_count(&h->gb); - slice->slice_type = ff_h264_get_slice_type(h); - if (h->slice_type_fixed) + slice->BitOffsetToSliceData = get_bits_count(&sl->gb); + slice->slice_type = ff_h264_get_slice_type(sl); + if (sl->slice_type_fixed) slice->slice_type += 5; - slice->luma_log2_weight_denom = h->luma_log2_weight_denom; - slice->chroma_log2_weight_denom = h->chroma_log2_weight_denom; - if (h->list_count > 0) - slice->num_ref_idx_l0_active_minus1 = h->ref_count[0] - 1; - if (h->list_count > 1) - slice->num_ref_idx_l1_active_minus1 = h->ref_count[1] - 1; - slice->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2; - slice->slice_beta_offset_div2 = h->slice_beta_offset / 2; + slice->luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; + slice->chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; + if (sl->list_count > 0) + slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1; + if (sl->list_count > 1) + slice->num_ref_idx_l1_active_minus1 = sl->ref_count[1] - 1; + slice->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2; + slice->slice_beta_offset_div2 = sl->slice_beta_offset / 2; slice->Reserved8Bits = 0; for (list = 0; list < 2; list++) { unsigned i; for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) { - if (list < h->list_count && i < h->ref_count[list]) { - const H264Picture *r = &h->ref_list[list][i]; + if (list < sl->list_count && i < sl->ref_count[list]) { + const H264Picture *r = sl->ref_list[list][i].parent; unsigned plane; unsigned index; - if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) - index = ff_dxva2_get_surface_index(ctx, &r->f); + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + index = ff_dxva2_get_surface_index(avctx, ctx, r->f); else - index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, &r->f)); + index = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, r->f)); fill_picture_entry(&slice->RefPicList[list][i], index, r->reference == PICT_BOTTOM_FIELD); for (plane = 0; plane < 3; plane++) { int w, o; - if (plane == 0 && h->luma_weight_flag[list]) { - w = h->luma_weight[i][list][0]; - o = h->luma_weight[i][list][1]; - } else if (plane >= 1 && h->chroma_weight_flag[list]) { - w = h->chroma_weight[i][list][plane-1][0]; - o = h->chroma_weight[i][list][plane-1][1]; + if (plane == 0 && sl->pwt.luma_weight_flag[list]) { + w = sl->pwt.luma_weight[i][list][0]; + o = sl->pwt.luma_weight[i][list][1]; + } else if (plane >= 1 && sl->pwt.chroma_weight_flag[list]) { + w = sl->pwt.chroma_weight[i][list][plane-1][0]; + o = sl->pwt.chroma_weight[i][list][plane-1][1]; } else { - w = 1 << (plane == 0 ? h->luma_log2_weight_denom : - h->chroma_log2_weight_denom); + w = 1 << (plane == 0 ? sl->pwt.luma_log2_weight_denom : + sl->pwt.chroma_log2_weight_denom); o = 0; } slice->Weights[list][i][plane][0] = w; @@ -275,40 +284,59 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, } } slice->slice_qs_delta = 0; /* XXX not implemented by Libav */ - slice->slice_qp_delta = h->qscale - h->pps.init_qp; - slice->redundant_pic_cnt = h->redundant_pic_count; - if (h->slice_type == AV_PICTURE_TYPE_B) - slice->direct_spatial_mv_pred_flag = h->direct_spatial_mv_pred; - slice->cabac_init_idc = h->pps.cabac ? h->cabac_init_idc : 0; - if (h->deblocking_filter < 2) - slice->disable_deblocking_filter_idc = 1 - h->deblocking_filter; + slice->slice_qp_delta = sl->qscale - h->ps.pps->init_qp; + slice->redundant_pic_cnt = sl->redundant_pic_count; + if (sl->slice_type == AV_PICTURE_TYPE_B) + slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred; + slice->cabac_init_idc = h->ps.pps->cabac ? sl->cabac_init_idc : 0; + if (sl->deblocking_filter < 2) + slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter; else - slice->disable_deblocking_filter_idc = h->deblocking_filter; + slice->disable_deblocking_filter_idc = sl->deblocking_filter; slice->slice_id = h->current_slice - 1; } static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *sc) + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) { const H264Context *h = avctx->priv_data; const unsigned mb_count = h->mb_width * h->mb_height; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; DXVA_Slice_H264_Short *slice = NULL; + void *dxva_data_ptr; uint8_t *dxva_data, *current, *end; unsigned dxva_size; void *slice_data; unsigned slice_size; unsigned padding; unsigned i; + unsigned type; /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ - if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType, - &dxva_data, &dxva_size))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif + + dxva_data = dxva_data_ptr; current = dxva_data; end = dxva_data + dxva_size; @@ -322,7 +350,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); - if (is_slice_short(ctx)) + if (is_slice_short(avctx, ctx)) slice = &ctx_pic->slice_short[i]; else slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; @@ -337,7 +365,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->BSNALunitDataLocation = current - dxva_data; slice->SliceBytesInBuffer = start_code_size + size; - if (!is_slice_short(ctx)) { + if (!is_slice_short(avctx, ctx)) { DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice; if (i < ctx_pic->slice_count - 1) slice_long->NumMbsForSlice = @@ -359,18 +387,43 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->SliceBytesInBuffer += padding; } - if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif if (i < ctx_pic->slice_count) return -1; - memset(bs, 0, sizeof(*bs)); - bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; - bs->DataSize = current - dxva_data; - bs->NumMBsInBuffer = mb_count; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = current - dxva_data; + dsc11->NumMBsInBuffer = mb_count; - if (is_slice_short(ctx)) { + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = current - dxva_data; + dsc2->NumMBsInBuffer = mb_count; + + type = DXVA2_SliceControlBufferType; + } +#endif + + if (is_slice_short(avctx, ctx)) { slice_data = ctx_pic->slice_short; slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); } else { @@ -379,7 +432,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, } assert((bs->DataSize & 127) == 0); return ff_dxva2_commit_buffer(avctx, ctx, sc, - DXVA2_SliceControlBufferType, + type, slice_data, slice_size, mb_count); } @@ -389,18 +442,20 @@ static int dxva2_h264_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; - if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL || + DXVA_CONTEXT_CFG(avctx, ctx) == NULL || + DXVA_CONTEXT_COUNT(avctx, ctx) <= 0) return -1; assert(ctx_pic); /* Fill up DXVA_PicParams_H264 */ - fill_picture_parameters(ctx, h, &ctx_pic->pp); + fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp); /* Fill up DXVA_Qmatrix_H264 */ - fill_scaling_lists(ctx, h, &ctx_pic->qm); + fill_scaling_lists(avctx, ctx, h, &ctx_pic->qm); ctx_pic->slice_count = 0; ctx_pic->bitstream_size = 0; @@ -413,7 +468,8 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, uint32_t size) { const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + const H264SliceContext *sl = &h->slice_ctx[0]; + AVDXVAContext *ctx = avctx->hwaccel_context; const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; unsigned position; @@ -426,7 +482,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, ctx_pic->bitstream_size += size; position = buffer - ctx_pic->bitstream; - if (is_slice_short(ctx)) + if (is_slice_short(avctx, ctx)) fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position, size); else @@ -434,7 +490,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, &ctx_pic->pp, position, size); ctx_pic->slice_count++; - if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) + if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */ return 0; } @@ -442,21 +498,23 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, static int dxva2_h264_end_frame(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; + H264SliceContext *sl = &h->slice_ctx[0]; struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; int ret; if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, &h->cur_pic_ptr->f, + ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp), &ctx_pic->qm, sizeof(ctx_pic->qm), commit_bitstream_and_slice_buffer); if (!ret) - ff_h264_draw_horiz_band(h, 0, h->avctx->height); + ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height); return ret; } +#if CONFIG_H264_DXVA2_HWACCEL AVHWAccel ff_h264_dxva2_hwaccel = { .name = "h264_dxva2", .type = AVMEDIA_TYPE_VIDEO, @@ -467,3 +525,17 @@ AVHWAccel ff_h264_dxva2_hwaccel = { .end_frame = dxva2_h264_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; +#endif + +#if CONFIG_H264_D3D11VA_HWACCEL +AVHWAccel ff_h264_d3d11va_hwaccel = { + .name = "h264_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_h264_start_frame, + .decode_slice = dxva2_h264_decode_slice, + .end_frame = dxva2_h264_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c new file mode 100644 index 0000000..5bb10d6 --- /dev/null +++ b/libavcodec/dxva2_hevc.c @@ -0,0 +1,449 @@ +/* + * DXVA2 HEVC HW acceleration. + * + * copyright (c) 2014 - 2015 Hendrik Leppkes + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" + +#include "hevc.h" + +// The headers above may include w32threads.h, which uses the original +// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a +// potentially newer version. +#include "dxva2_internal.h" + +#define MAX_SLICES 256 + +struct hevc_dxva2_picture_context { + DXVA_PicParams_HEVC pp; + DXVA_Qmatrix_HEVC qm; + unsigned slice_count; + DXVA_Slice_HEVC_Short slice_short[MAX_SLICES]; + const uint8_t *bitstream; + unsigned bitstream_size; +}; + +static void fill_picture_entry(DXVA_PicEntry_HEVC *pic, + unsigned index, unsigned flag) +{ + av_assert0((index & 0x7f) == index && (flag & 0x01) == flag); + pic->bPicEntry = index | (flag << 7); +} + +static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) { + if ((pp->RefPicList[i].bPicEntry & 0x7f) == surface_index) + return i; + } + return 0xff; +} + +static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const HEVCContext *h, + DXVA_PicParams_HEVC *pp) +{ + const HEVCFrame *current_picture = h->ref; + const HEVCSPS *sps = h->ps.sps; + const HEVCPPS *pps = h->ps.pps; + int i, j; + + memset(pp, 0, sizeof(*pp)); + + pp->PicWidthInMinCbsY = sps->min_cb_width; + pp->PicHeightInMinCbsY = sps->min_cb_height; + + pp->wFormatAndSequenceInfoFlags = (sps->chroma_format_idc << 0) | + (sps->separate_colour_plane_flag << 2) | + ((sps->bit_depth - 8) << 3) | + ((sps->bit_depth - 8) << 6) | + ((sps->log2_max_poc_lsb - 4) << 9) | + (0 << 13) | + (0 << 14) | + (0 << 15); + + fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(avctx, ctx, current_picture->frame), 0); + + pp->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1; + pp->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3; + pp->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size; + pp->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2; + pp->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size; + pp->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter; + pp->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra; + pp->num_short_term_ref_pic_sets = sps->nb_st_rps; + pp->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps; + + pp->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1; + pp->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1; + pp->init_qp_minus26 = pps->pic_init_qp_minus26; + + if (h->sh.short_term_ref_pic_set_sps_flag == 0 && h->sh.short_term_rps) { + pp->ucNumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps->rps_idx_num_delta_pocs; + pp->wNumBitsForShortTermRPSInSlice = h->sh.short_term_ref_pic_set_size; + } + + pp->dwCodingParamToolFlags = (sps->scaling_list_enable_flag << 0) | + (sps->amp_enabled_flag << 1) | + (sps->sao_enabled << 2) | + (sps->pcm_enabled_flag << 3) | + ((sps->pcm_enabled_flag ? (sps->pcm.bit_depth - 1) : 0) << 4) | + ((sps->pcm_enabled_flag ? (sps->pcm.bit_depth_chroma - 1) : 0) << 8) | + ((sps->pcm_enabled_flag ? (sps->pcm.log2_min_pcm_cb_size - 3) : 0) << 12) | + ((sps->pcm_enabled_flag ? (sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size) : 0) << 14) | + (sps->pcm.loop_filter_disable_flag << 16) | + (sps->long_term_ref_pics_present_flag << 17) | + (sps->sps_temporal_mvp_enabled_flag << 18) | + (sps->sps_strong_intra_smoothing_enable_flag << 19) | + (pps->dependent_slice_segments_enabled_flag << 20) | + (pps->output_flag_present_flag << 21) | + (pps->num_extra_slice_header_bits << 22) | + (pps->sign_data_hiding_flag << 25) | + (pps->cabac_init_present_flag << 26) | + (0 << 27); + + pp->dwCodingSettingPicturePropertyFlags = (pps->constrained_intra_pred_flag << 0) | + (pps->transform_skip_enabled_flag << 1) | + (pps->cu_qp_delta_enabled_flag << 2) | + (pps->pic_slice_level_chroma_qp_offsets_present_flag << 3) | + (pps->weighted_pred_flag << 4) | + (pps->weighted_bipred_flag << 5) | + (pps->transquant_bypass_enable_flag << 6) | + (pps->tiles_enabled_flag << 7) | + (pps->entropy_coding_sync_enabled_flag << 8) | + (pps->uniform_spacing_flag << 9) | + ((pps->tiles_enabled_flag ? pps->loop_filter_across_tiles_enabled_flag : 0) << 10) | + (pps->seq_loop_filter_across_slices_enabled_flag << 11) | + (pps->deblocking_filter_override_enabled_flag << 12) | + (pps->disable_dbf << 13) | + (pps->lists_modification_present_flag << 14) | + (pps->slice_header_extension_present_flag << 15) | + (IS_IRAP(h) << 16) | + (IS_IDR(h) << 17) | + /* IntraPicFlag */ + (IS_IRAP(h) << 18) | + (0 << 19); + pp->pps_cb_qp_offset = pps->cb_qp_offset; + pp->pps_cr_qp_offset = pps->cr_qp_offset; + if (pps->tiles_enabled_flag) { + pp->num_tile_columns_minus1 = pps->num_tile_columns - 1; + pp->num_tile_rows_minus1 = pps->num_tile_rows - 1; + + if (!pps->uniform_spacing_flag) { + for (i = 0; i < pps->num_tile_columns; i++) + pp->column_width_minus1[i] = pps->column_width[i] - 1; + + for (i = 0; i < pps->num_tile_rows; i++) + pp->row_height_minus1[i] = pps->row_height[i] - 1; + } + } + + pp->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth; + pp->pps_beta_offset_div2 = pps->beta_offset / 2; + pp->pps_tc_offset_div2 = pps->tc_offset / 2; + pp->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2; + pp->CurrPicOrderCntVal = h->poc; + + // fill RefPicList from the DPB + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) { + const HEVCFrame *frame = NULL; + while (!frame && j < FF_ARRAY_ELEMS(h->DPB)) { + if (&h->DPB[j] != current_picture && (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) + frame = &h->DPB[j]; + j++; + } + + if (frame) { + fill_picture_entry(&pp->RefPicList[i], ff_dxva2_get_surface_index(avctx, ctx, frame->frame), !!(frame->flags & HEVC_FRAME_FLAG_LONG_REF)); + pp->PicOrderCntValList[i] = frame->poc; + } else { + pp->RefPicList[i].bPicEntry = 0xff; + pp->PicOrderCntValList[i] = 0; + } + } + + #define DO_REF_LIST(ref_idx, ref_list) { \ + const RefPicList *rpl = &h->rps[ref_idx]; \ + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->ref_list); i++) { \ + const HEVCFrame *frame = NULL; \ + while (!frame && j < rpl->nb_refs) \ + frame = rpl->ref[j++]; \ + if (frame) \ + pp->ref_list[i] = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, frame->frame)); \ + else \ + pp->ref_list[i] = 0xff; \ + } \ + } + + // Fill short term and long term lists + DO_REF_LIST(ST_CURR_BEF, RefPicSetStCurrBefore); + DO_REF_LIST(ST_CURR_AFT, RefPicSetStCurrAfter); + DO_REF_LIST(LT_CURR, RefPicSetLtCurr); + + pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; +} + +static void fill_scaling_lists(AVDXVAContext *ctx, const HEVCContext *h, DXVA_Qmatrix_HEVC *qm) +{ + unsigned i, j, pos; + const ScalingList *sl = h->ps.pps->scaling_list_data_present_flag ? + &h->ps.pps->scaling_list : &h->ps.sps->scaling_list; + + memset(qm, 0, sizeof(*qm)); + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; + qm->ucScalingLists0[i][j] = sl->sl[0][i][pos]; + } + + for (j = 0; j < 64; j++) { + pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + qm->ucScalingLists1[i][j] = sl->sl[1][i][pos]; + qm->ucScalingLists2[i][j] = sl->sl[2][i][pos]; + + if (i < 2) + qm->ucScalingLists3[i][j] = sl->sl[3][i * 3][pos]; + } + + qm->ucScalingListDCCoefSizeID2[i] = sl->sl_dc[0][i]; + if (i < 2) + qm->ucScalingListDCCoefSizeID3[i] = sl->sl_dc[1][i * 3]; + } +} + +static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, + unsigned position, unsigned size) +{ + memset(slice, 0, sizeof(*slice)); + slice->BSNALunitDataLocation = position; + slice->SliceBytesInBuffer = size; + slice->wBadSliceChopping = 0; +} + +static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) +{ + const HEVCContext *h = avctx->priv_data; + AVDXVAContext *ctx = avctx->hwaccel_context; + const HEVCFrame *current_picture = h->ref; + struct hevc_dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + DXVA_Slice_HEVC_Short *slice = NULL; + void *dxva_data_ptr; + uint8_t *dxva_data, *current, *end; + unsigned dxva_size; + void *slice_data; + unsigned slice_size; + unsigned padding; + unsigned i; + unsigned type; + + /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif + + dxva_data = dxva_data_ptr; + current = dxva_data; + end = dxva_data + dxva_size; + + for (i = 0; i < ctx_pic->slice_count; i++) { + static const uint8_t start_code[] = { 0, 0, 1 }; + static const unsigned start_code_size = sizeof(start_code); + unsigned position, size; + + slice = &ctx_pic->slice_short[i]; + + position = slice->BSNALunitDataLocation; + size = slice->SliceBytesInBuffer; + if (start_code_size + size > end - current) { + av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); + break; + } + + slice->BSNALunitDataLocation = current - dxva_data; + slice->SliceBytesInBuffer = start_code_size + size; + + memcpy(current, start_code, start_code_size); + current += start_code_size; + + memcpy(current, &ctx_pic->bitstream[position], size); + current += size; + } + padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); + if (slice && padding > 0) { + memset(current, 0, padding); + current += padding; + + slice->SliceBytesInBuffer += padding; + } +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif + if (i < ctx_pic->slice_count) + return -1; + +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = current - dxva_data; + dsc11->NumMBsInBuffer = 0; + + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = current - dxva_data; + dsc2->NumMBsInBuffer = 0; + + type = DXVA2_SliceControlBufferType; + } +#endif + + slice_data = ctx_pic->slice_short; + slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); + + av_assert0(((current - dxva_data) & 127) == 0); + return ff_dxva2_commit_buffer(avctx, ctx, sc, + type, + slice_data, slice_size, 0); +} + + +static int dxva2_hevc_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const HEVCContext *h = avctx->priv_data; + AVDXVAContext *ctx = avctx->hwaccel_context; + struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private; + + if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL || + DXVA_CONTEXT_CFG(avctx, ctx) == NULL || + DXVA_CONTEXT_COUNT(avctx, ctx) <= 0) + return -1; + av_assert0(ctx_pic); + + /* Fill up DXVA_PicParams_HEVC */ + fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp); + + /* Fill up DXVA_Qmatrix_HEVC */ + fill_scaling_lists(ctx, h, &ctx_pic->qm); + + ctx_pic->slice_count = 0; + ctx_pic->bitstream_size = 0; + ctx_pic->bitstream = NULL; + return 0; +} + +static int dxva2_hevc_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const HEVCContext *h = avctx->priv_data; + const HEVCFrame *current_picture = h->ref; + struct hevc_dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + unsigned position; + + if (ctx_pic->slice_count >= MAX_SLICES) + return -1; + + if (!ctx_pic->bitstream) + ctx_pic->bitstream = buffer; + ctx_pic->bitstream_size += size; + + position = buffer - ctx_pic->bitstream; + fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position, size); + ctx_pic->slice_count++; + + return 0; +} + +static int dxva2_hevc_end_frame(AVCodecContext *avctx) +{ + HEVCContext *h = avctx->priv_data; + struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private; + int scale = ctx_pic->pp.dwCodingParamToolFlags & 1; + int ret; + + if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) + return -1; + + ret = ff_dxva2_common_end_frame(avctx, h->ref->frame, + &ctx_pic->pp, sizeof(ctx_pic->pp), + scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, + commit_bitstream_and_slice_buffer); + return ret; +} + +#if CONFIG_HEVC_DXVA2_HWACCEL +AVHWAccel ff_hevc_dxva2_hwaccel = { + .name = "hevc_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .start_frame = dxva2_hevc_start_frame, + .decode_slice = dxva2_hevc_decode_slice, + .end_frame = dxva2_hevc_end_frame, + .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), +}; +#endif + +#if CONFIG_HEVC_D3D11VA_HWACCEL +AVHWAccel ff_hevc_d3d11va_hwaccel = { + .name = "hevc_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_hevc_start_frame, + .decode_slice = dxva2_hevc_decode_slice, + .end_frame = dxva2_hevc_end_frame, + .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), +}; +#endif diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h index f35a076..30aec8b 100644 --- a/libavcodec/dxva2_internal.h +++ b/libavcodec/dxva2_internal.h @@ -23,26 +23,89 @@ #ifndef AVCODEC_DXVA_INTERNAL_H #define AVCODEC_DXVA_INTERNAL_H -#define _WIN32_WINNT 0x0600 #define COBJMACROS #include "config.h" +/* define the proper COM entries before forcing desktop APIs */ +#include + +#if CONFIG_DXVA2 #include "dxva2.h" +#endif +#if CONFIG_D3D11VA +#include "d3d11va.h" +#endif #if HAVE_DXVA_H +/* When targeting WINAPI_FAMILY_PHONE_APP or WINAPI_FAMILY_APP, dxva.h + * defines nothing. Force the struct definitions to be visible. */ +#undef WINAPI_FAMILY +#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP +#undef _CRT_BUILD_DESKTOP_APP +#define _CRT_BUILD_DESKTOP_APP 0 #include #endif #include "avcodec.h" -#include "mpegvideo.h" + +typedef void DECODER_BUFFER_DESC; + +typedef union { +#if CONFIG_D3D11VA + struct AVD3D11VAContext d3d11va; +#endif +#if CONFIG_DXVA2 + struct dxva_context dxva2; +#endif +} AVDXVAContext; + +#if CONFIG_D3D11VA +#define D3D11VA_CONTEXT(ctx) (&ctx->d3d11va) +#endif +#if CONFIG_DXVA2 +#define DXVA2_CONTEXT(ctx) (&ctx->dxva2) +#endif + +#if CONFIG_D3D11VA && CONFIG_DXVA2 +#define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.workaround : ctx->dxva2.workaround) +#define DXVA_CONTEXT_COUNT(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.surface_count : ctx->dxva2.surface_count) +#define DXVA_CONTEXT_SURFACE(avctx, ctx, i) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.surface[i] : ctx->dxva2.surface[i]) +#define DXVA_CONTEXT_DECODER(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.decoder : ctx->dxva2.decoder) +#define DXVA_CONTEXT_REPORT_ID(avctx, ctx) (*(avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? &ctx->d3d11va.report_id : &ctx->dxva2.report_id)) +#define DXVA_CONTEXT_CFG(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg : ctx->dxva2.cfg) +#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigBitstreamRaw : ctx->dxva2.cfg->ConfigBitstreamRaw) +#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigIntraResidUnsigned : ctx->dxva2.cfg->ConfigIntraResidUnsigned) +#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigResidDiffAccelerator : ctx->dxva2.cfg->ConfigResidDiffAccelerator) +#elif CONFIG_DXVA2 +#define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (ctx->dxva2.workaround) +#define DXVA_CONTEXT_COUNT(avctx, ctx) (ctx->dxva2.surface_count) +#define DXVA_CONTEXT_SURFACE(avctx, ctx, i) (ctx->dxva2.surface[i]) +#define DXVA_CONTEXT_DECODER(avctx, ctx) (ctx->dxva2.decoder) +#define DXVA_CONTEXT_REPORT_ID(avctx, ctx) (*(&ctx->dxva2.report_id)) +#define DXVA_CONTEXT_CFG(avctx, ctx) (ctx->dxva2.cfg) +#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) (ctx->dxva2.cfg->ConfigBitstreamRaw) +#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (ctx->dxva2.cfg->ConfigIntraResidUnsigned) +#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (ctx->dxva2.cfg->ConfigResidDiffAccelerator) +#elif CONFIG_D3D11VA +#define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (ctx->d3d11va.workaround) +#define DXVA_CONTEXT_COUNT(avctx, ctx) (ctx->d3d11va.surface_count) +#define DXVA_CONTEXT_SURFACE(avctx, ctx, i) (ctx->d3d11va.surface[i]) +#define DXVA_CONTEXT_DECODER(avctx, ctx) (ctx->d3d11va.decoder) +#define DXVA_CONTEXT_REPORT_ID(avctx, ctx) (*(&ctx->d3d11va.report_id)) +#define DXVA_CONTEXT_CFG(avctx, ctx) (ctx->d3d11va.cfg) +#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) (ctx->d3d11va.cfg->ConfigBitstreamRaw) +#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (ctx->d3d11va.cfg->ConfigIntraResidUnsigned) +#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (ctx->d3d11va.cfg->ConfigResidDiffAccelerator) +#endif void *ff_dxva2_get_surface(const AVFrame *frame); -unsigned ff_dxva2_get_surface_index(const struct dxva_context *, +unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, + const AVDXVAContext *, const AVFrame *frame); -int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *, - DXVA2_DecodeBufferDesc *, +int ff_dxva2_commit_buffer(AVCodecContext *, AVDXVAContext *, + DECODER_BUFFER_DESC *, unsigned type, const void *data, unsigned size, unsigned mb_count); @@ -51,7 +114,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int (*commit_bs_si)(AVCodecContext *, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *slice)); + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *slice)); #endif /* AVCODEC_DXVA_INTERNAL_H */ diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index f6ef5e5..2d88f9b 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -21,8 +21,13 @@ */ #include "libavutil/log.h" -#include "dxva2_internal.h" #include "mpegutils.h" +#include "mpegvideo.h" + +// The headers above may include w32threads.h, which uses the original +// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a +// potentially newer version. +#include "dxva2_internal.h" #define MAX_SLICES 1024 struct dxva2_picture_context { @@ -36,7 +41,7 @@ struct dxva2_picture_context { }; static void fill_picture_parameters(AVCodecContext *avctx, - struct dxva_context *ctx, + AVDXVAContext *ctx, const struct MpegEncContext *s, DXVA_PictureParameters *pp) { @@ -44,14 +49,14 @@ static void fill_picture_parameters(AVCodecContext *avctx, int is_field = s->picture_structure != PICT_FRAME; memset(pp, 0, sizeof(*pp)); - pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture->f); + pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f); pp->wDeblockedPictureIndex = 0; if (s->pict_type != AV_PICTURE_TYPE_I) - pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->last_picture.f); + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f); else pp->wForwardRefPictureIndex = 0xffff; if (s->pict_type == AV_PICTURE_TYPE_B) - pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f); + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f); else pp->wBackwardRefPictureIndex = 0xffff; pp->wPicWidthInMBminus1 = s->mb_width - 1; @@ -102,7 +107,7 @@ static void fill_picture_parameters(AVCodecContext *avctx, } static void fill_quantization_matrices(AVCodecContext *avctx, - struct dxva_context *ctx, + AVDXVAContext *ctx, const struct MpegEncContext *s, DXVA_QmatrixData *qm) { @@ -147,23 +152,42 @@ static void fill_slice(AVCodecContext *avctx, slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb); } static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *sc) + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) { const struct MpegEncContext *s = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; const int is_field = s->picture_structure != PICT_FRAME; const unsigned mb_count = s->mb_width * (s->mb_height >> is_field); + void *dxva_data_ptr; uint8_t *dxva_data, *current, *end; unsigned dxva_size; unsigned i; + unsigned type; - if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType, - &dxva_data, &dxva_size))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif + + dxva_data = dxva_data_ptr; current = dxva_data; end = dxva_data + dxva_size; @@ -187,19 +211,44 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, memcpy(current, &ctx_pic->bitstream[position], size); current += size; } - if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif if (i < ctx_pic->slice_count) return -1; - memset(bs, 0, sizeof(*bs)); - bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; - bs->DataSize = current - dxva_data; - bs->NumMBsInBuffer = mb_count; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = current - dxva_data; + dsc11->NumMBsInBuffer = mb_count; + + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = current - dxva_data; + dsc2->NumMBsInBuffer = mb_count; + + type = DXVA2_SliceControlBufferType; + } +#endif return ff_dxva2_commit_buffer(avctx, ctx, sc, - DXVA2_SliceControlBufferType, + type, ctx_pic->slice, ctx_pic->slice_count * sizeof(*ctx_pic->slice), mb_count); @@ -210,11 +259,13 @@ static int dxva2_mpeg2_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const struct MpegEncContext *s = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; - if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL || + DXVA_CONTEXT_CFG(avctx, ctx) == NULL || + DXVA_CONTEXT_COUNT(avctx, ctx) <= 0) return -1; assert(ctx_pic); @@ -268,6 +319,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) return ret; } +#if CONFIG_MPEG2_DXVA2_HWACCEL AVHWAccel ff_mpeg2_dxva2_hwaccel = { .name = "mpeg2_dxva2", .type = AVMEDIA_TYPE_VIDEO, @@ -278,3 +330,17 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { .end_frame = dxva2_mpeg2_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; +#endif + +#if CONFIG_MPEG2_D3D11VA_HWACCEL +AVHWAccel ff_mpeg2_d3d11va_hwaccel = { + .name = "mpeg2_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_mpeg2_start_frame, + .decode_slice = dxva2_mpeg2_decode_slice, + .end_frame = dxva2_mpeg2_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 4f4dd17..d170e18 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -20,11 +20,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dxva2_internal.h" #include "mpegutils.h" #include "vc1.h" #include "vc1data.h" +// The headers above may include w32threads.h, which uses the original +// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a +// potentially newer version. +#include "dxva2_internal.h" + struct dxva2_picture_context { DXVA_PictureParameters pp; DXVA_SliceInfo si; @@ -34,7 +38,7 @@ struct dxva2_picture_context { }; static void fill_picture_parameters(AVCodecContext *avctx, - struct dxva_context *ctx, const VC1Context *v, + AVDXVAContext *ctx, const VC1Context *v, DXVA_PictureParameters *pp) { const MpegEncContext *s = &v->s; @@ -42,13 +46,13 @@ static void fill_picture_parameters(AVCodecContext *avctx, memset(pp, 0, sizeof(*pp)); pp->wDecodedPictureIndex = - pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture->f); + pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f); if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type) - pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->last_picture.f); + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f); else pp->wForwardRefPictureIndex = 0xffff; if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) - pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f); + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f); else pp->wBackwardRefPictureIndex = 0xffff; if (v->profile == PROFILE_ADVANCED) { @@ -73,8 +77,8 @@ static void fill_picture_parameters(AVCodecContext *avctx, pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type; pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type; pp->bBidirectionalAveragingMode = (1 << 7) | - ((ctx->cfg->ConfigIntraResidUnsigned != 0) << 6) | - ((ctx->cfg->ConfigResidDiffAccelerator != 0) << 5) | + ((DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) != 0) << 6) | + ((DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) != 0) << 5) | ((v->lumscale != 32 || v->lumshift != 0) << 4) | ((v->profile == PROFILE_ADVANCED) << 3); pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) | @@ -82,11 +86,11 @@ static void fill_picture_parameters(AVCodecContext *avctx, (0 << 1) | (!s->quarter_sample ); pp->bChromaFormat = v->chromaformat; - ctx->report_id++; - if (ctx->report_id >= (1 << 16)) - ctx->report_id = 1; - pp->bPicScanFixed = ctx->report_id >> 8; - pp->bPicScanMethod = ctx->report_id & 0xff; + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; + if (DXVA_CONTEXT_REPORT_ID(avctx, ctx) >= (1 << 16)) + DXVA_CONTEXT_REPORT_ID(avctx, ctx) = 1; + pp->bPicScanFixed = DXVA_CONTEXT_REPORT_ID(avctx, ctx) >> 8; + pp->bPicScanMethod = DXVA_CONTEXT_REPORT_ID(avctx, ctx) & 0xff; pp->bPicReadbackRequests = 0; pp->bRcontrol = v->rnd; pp->bPicSpatialResid8 = (v->panscanflag << 7) | @@ -157,11 +161,11 @@ static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, } static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *sc) + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) { const VC1Context *v = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; const MpegEncContext *s = &v->s; struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; @@ -173,15 +177,33 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, const unsigned padding = 128 - ((start_code_size + slice_size) & 127); const unsigned data_size = start_code_size + slice_size + padding; + void *dxva_data_ptr; uint8_t *dxva_data; unsigned dxva_size; int result; + unsigned type; - if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType, - &dxva_data, &dxva_size))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif + dxva_data = dxva_data_ptr; result = data_size <= dxva_size ? 0 : -1; if (!result) { if (start_code_size > 0) @@ -192,21 +214,46 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, memset(dxva_data + start_code_size + slice_size, 0, padding); slice->dwSliceBitsInBuffer = 8 * data_size; } - if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif if (result) return result; - memset(bs, 0, sizeof(*bs)); - bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; - bs->DataSize = data_size; - bs->NumMBsInBuffer = s->mb_width * s->mb_height; - assert((bs->DataSize & 127) == 0); +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = data_size; + dsc11->NumMBsInBuffer = s->mb_width * s->mb_height; + + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = data_size; + dsc2->NumMBsInBuffer = s->mb_width * s->mb_height; + + type = DXVA2_SliceControlBufferType; + } +#endif + assert((data_size & 127) == 0); return ff_dxva2_commit_buffer(avctx, ctx, sc, - DXVA2_SliceControlBufferType, - slice, sizeof(*slice), bs->NumMBsInBuffer); + type, + slice, sizeof(*slice), s->mb_width * s->mb_height); } static int dxva2_vc1_start_frame(AVCodecContext *avctx, @@ -214,10 +261,12 @@ static int dxva2_vc1_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const VC1Context *v = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; - if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL || + DXVA_CONTEXT_CFG(avctx, ctx) == NULL || + DXVA_CONTEXT_COUNT(avctx, ctx) <= 0) return -1; assert(ctx_pic); @@ -283,6 +332,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { }; #endif +#if CONFIG_VC1_DXVA2_HWACCEL AVHWAccel ff_vc1_dxva2_hwaccel = { .name = "vc1_dxva2", .type = AVMEDIA_TYPE_VIDEO, @@ -293,3 +343,30 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { .end_frame = dxva2_vc1_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; +#endif + +#if CONFIG_WMV3_D3D11VA_HWACCEL +AVHWAccel ff_wmv3_d3d11va_hwaccel = { + .name = "wmv3_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif + +#if CONFIG_VC1_D3D11VA_HWACCEL +AVHWAccel ff_vc1_d3d11va_hwaccel = { + .name = "vc1_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index b9d079c..fe52d27 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -300,7 +300,10 @@ int ff_eac3_parse_header(AC3DecodeContext *s) application can select from. each independent stream can also contain dependent streams which are used to add or replace channels. */ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { - avpriv_request_sample(s->avctx, "Dependent substream decoding"); + if (!s->eac3_frame_dependent_found) { + s->eac3_frame_dependent_found = 1; + avpriv_request_sample(s->avctx, "Dependent substream decoding"); + } return AAC_AC3_PARSE_ERROR_FRAME_TYPE; } else if (s->frame_type == EAC3_FRAME_TYPE_RESERVED) { av_log(s->avctx, AV_LOG_ERROR, "Reserved frame type\n"); @@ -312,7 +315,10 @@ int ff_eac3_parse_header(AC3DecodeContext *s) associated to an independent stream have matching substream id's. */ if (s->substreamid) { /* only decode substream with id=0. skip any additional substreams. */ - avpriv_request_sample(s->avctx, "Additional substreams"); + if (!s->eac3_subsbtreamid_found) { + s->eac3_subsbtreamid_found = 1; + avpriv_request_sample(s->avctx, "Additional substreams"); + } return AAC_AC3_PARSE_ERROR_FRAME_TYPE; } diff --git a/libavcodec/eacmv.c b/libavcodec/eacmv.c index 6adadb1..9668f64 100644 --- a/libavcodec/eacmv.c +++ b/libavcodec/eacmv.c @@ -153,7 +153,7 @@ static int cmv_process_header(CmvContext *s, const uint8_t *buf, const uint8_t * fps = AV_RL16(&buf[10]); if (fps > 0) - s->avctx->time_base = (AVRational){ 1, fps }; + s->avctx->framerate = (AVRational){ fps, 1 }; pal_start = AV_RL16(&buf[12]); pal_count = AV_RL16(&buf[14]); @@ -240,5 +240,5 @@ AVCodec ff_eacmv_decoder = { .init = cmv_decode_init, .close = cmv_decode_end, .decode = cmv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c index 28b933a..3e8d4fd 100644 --- a/libavcodec/eamad.c +++ b/libavcodec/eamad.c @@ -29,6 +29,7 @@ */ #include "avcodec.h" +#include "blockdsp.h" #include "bytestream.h" #include "bswapdsp.h" #include "get_bits.h" @@ -36,13 +37,12 @@ #include "eaidct.h" #include "idctdsp.h" #include "internal.h" -#include "mpeg12.h" #include "mpeg12data.h" -#include "libavutil/imgutils.h" +#include "mpeg12vlc.h" #define EA_PREAMBLE_SIZE 8 -#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */ -#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD p-frame */ +#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD I-frame */ +#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD P-frame */ #define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ typedef struct MadContext { @@ -98,7 +98,7 @@ static inline void comp_block(MadContext *t, AVFrame *frame, frame->linesize[0], t->last_frame->data[0] + (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame->linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x, t->last_frame->linesize[0], add); - } else if (!(t->avctx->flags & CODEC_FLAG_GRAY)) { + } else if (!(t->avctx->flags & AV_CODEC_FLAG_GRAY)) { int index = j - 3; comp(frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x * 8, frame->linesize[index], @@ -114,7 +114,7 @@ static inline void idct_put(MadContext *t, AVFrame *frame, int16_t *block, ff_ea_idct_put_c( frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3), frame->linesize[0], block); - } else if (!(t->avctx->flags & CODEC_FLAG_GRAY)) { + } else if (!(t->avctx->flags & AV_CODEC_FLAG_GRAY)) { int index = j - 3; ff_ea_idct_put_c( frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x*8, @@ -255,7 +255,7 @@ static int decode_frame(AVCodecContext *avctx, inter = (chunk_type == MADm_TAG || chunk_type == MADe_TAG); bytestream2_skip(&gb, 10); - av_reduce(&avctx->time_base.num, &avctx->time_base.den, + av_reduce(&avctx->framerate.den, &avctx->framerate.num, bytestream2_get_le16(&gb), 1000, 1<<30); width = bytestream2_get_le16(&gb); @@ -333,5 +333,5 @@ AVCodec ff_eamad_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index 0e4ba2f..ff0aa55 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -28,13 +28,13 @@ * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGQ */ -#include "avcodec.h" #define BITSTREAM_READER_LE -#include "get_bits.h" -#include "bytestream.h" -#include "idctdsp.h" #include "aandcttab.h" +#include "avcodec.h" +#include "bytestream.h" #include "eaidct.h" +#include "get_bits.h" +#include "idctdsp.h" #include "internal.h" typedef struct TgqContext { @@ -53,7 +53,7 @@ static av_cold int tgq_decode_init(AVCodecContext *avctx) s->avctx = avctx; ff_init_scantable_permutation(idct_permutation, FF_IDCT_PERM_NONE); ff_init_scantable(idct_permutation, &s->scantable, ff_zigzag_direct); - avctx->time_base = (AVRational){1, 15}; + avctx->framerate = (AVRational){ 15, 1 }; avctx->pix_fmt = AV_PIX_FMT_YUV420P; return 0; } @@ -116,7 +116,7 @@ static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame, ff_ea_idct_put_c(dest_y + 8, linesize, block[1]); ff_ea_idct_put_c(dest_y + 8 * linesize , linesize, block[2]); ff_ea_idct_put_c(dest_y + 8 * linesize + 8, linesize, block[3]); - if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]); ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]); } @@ -142,7 +142,7 @@ static void tgq_idct_put_mb_dconly(TgqContext *s, AVFrame *frame, tgq_dconly(s, dest_y + 8, linesize, dc[1]); tgq_dconly(s, dest_y + 8 * linesize, linesize, dc[2]); tgq_dconly(s, dest_y + 8 * linesize + 8, linesize, dc[3]); - if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { tgq_dconly(s, dest_cb, frame->linesize[1], dc[4]); tgq_dconly(s, dest_cr, frame->linesize[2], dc[5]); } @@ -247,5 +247,5 @@ AVCodec ff_eatgq_decoder = { .priv_data_size = sizeof(TgqContext), .init = tgq_decode_init, .decode = tgq_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/eatgv.c b/libavcodec/eatgv.c index 3bc6506..7f40f45 100644 --- a/libavcodec/eatgv.c +++ b/libavcodec/eatgv.c @@ -28,12 +28,13 @@ * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV */ -#include "avcodec.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" + #define BITSTREAM_READER_LE +#include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "libavutil/imgutils.h" -#include "libavutil/mem.h" #define EA_PREAMBLE_SIZE 8 #define kVGT_TAG MKTAG('k', 'V', 'G', 'T') @@ -55,7 +56,7 @@ static av_cold int tgv_decode_init(AVCodecContext *avctx) { TgvContext *s = avctx->priv_data; s->avctx = avctx; - avctx->time_base = (AVRational){1, 15}; + avctx->framerate = (AVRational){ 15, 1 }; avctx->pix_fmt = AV_PIX_FMT_PAL8; s->last_frame = av_frame_alloc(); @@ -173,7 +174,9 @@ static int tgv_decode_inter(TgvContext *s, AVFrame *frame, /* allocate codebook buffers as necessary */ if (num_mvs > s->num_mvs) { - s->mv_codebook = av_realloc(s->mv_codebook, num_mvs*2*sizeof(int)); + int err = av_reallocp(&s->mv_codebook, num_mvs * 2 * sizeof(int)); + if (err < 0) + return err; s->num_mvs = num_mvs; } @@ -355,5 +358,5 @@ AVCodec ff_eatgv_decoder = { .init = tgv_decode_init, .close = tgv_decode_end, .decode = tgv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index 25882da..f4cad9c 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -35,69 +35,85 @@ #include "idctdsp.h" #include "internal.h" #include "mpeg12.h" -#include "mpegvideo.h" typedef struct TqiContext { - MpegEncContext s; + GetBitContext gb; + BlockDSPContext bdsp; BswapDSPContext bsdsp; + IDCTDSPContext idsp; + ScanTable intra_scantable; + void *bitstream_buf; unsigned int bitstream_buf_size; + + int mb_x, mb_y; + uint16_t intra_matrix[64]; + int last_dc[3]; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; } TqiContext; static av_cold int tqi_decode_init(AVCodecContext *avctx) { TqiContext *t = avctx->priv_data; - MpegEncContext *s = &t->s; - s->avctx = avctx; - ff_blockdsp_init(&s->bdsp, avctx); + + ff_blockdsp_init(&t->bdsp, avctx); ff_bswapdsp_init(&t->bsdsp); - ff_idctdsp_init(&s->idsp, avctx); - ff_init_scantable_permutation(s->idsp.idct_permutation, FF_IDCT_PERM_NONE); - ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); - s->qscale = 1; - avctx->time_base = (AVRational){1, 15}; + ff_idctdsp_init(&t->idsp, avctx); + ff_init_scantable_permutation(t->idsp.idct_permutation, FF_IDCT_PERM_NONE); + ff_init_scantable(t->idsp.idct_permutation, &t->intra_scantable, ff_zigzag_direct); + + avctx->framerate = (AVRational){ 15, 1 }; avctx->pix_fmt = AV_PIX_FMT_YUV420P; ff_mpeg12_init_vlcs(); return 0; } -static int tqi_decode_mb(MpegEncContext *s, int16_t (*block)[64]) +static int tqi_decode_mb(TqiContext *t, int16_t (*block)[64]) { int n; - s->bdsp.clear_blocks(block[0]); - for (n=0; n<6; n++) - if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0) + + t->bdsp.clear_blocks(block[0]); + for (n = 0; n < 6; n++) { + int ret = ff_mpeg1_decode_block_intra(&t->gb, + t->intra_matrix, + t->intra_scantable.permutated, + t->last_dc, block[n], n, 1); + if (ret < 0) return -1; + } return 0; } -static inline void tqi_idct_put(TqiContext *t, AVFrame *frame, int16_t (*block)[64]) +static inline void tqi_idct_put(AVCodecContext *avctx, AVFrame *frame, + int16_t (*block)[64]) { - MpegEncContext *s = &t->s; + TqiContext *t = avctx->priv_data; int linesize = frame->linesize[0]; - uint8_t *dest_y = frame->data[0] + (s->mb_y * 16* linesize ) + s->mb_x * 16; - uint8_t *dest_cb = frame->data[1] + (s->mb_y * 8 * frame->linesize[1]) + s->mb_x * 8; - uint8_t *dest_cr = frame->data[2] + (s->mb_y * 8 * frame->linesize[2]) + s->mb_x * 8; + uint8_t *dest_y = frame->data[0] + t->mb_y * 16 * linesize + t->mb_x * 16; + uint8_t *dest_cb = frame->data[1] + t->mb_y * 8 * frame->linesize[1] + t->mb_x * 8; + uint8_t *dest_cr = frame->data[2] + t->mb_y * 8 * frame->linesize[2] + t->mb_x * 8; ff_ea_idct_put_c(dest_y , linesize, block[0]); ff_ea_idct_put_c(dest_y + 8, linesize, block[1]); ff_ea_idct_put_c(dest_y + 8*linesize , linesize, block[2]); ff_ea_idct_put_c(dest_y + 8*linesize + 8, linesize, block[3]); - if(!(s->avctx->flags&CODEC_FLAG_GRAY)) { + + if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) { ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]); ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]); } } -static void tqi_calculate_qtable(MpegEncContext *s, int quant) +static void tqi_calculate_qtable(TqiContext *t, int quant) { const int qscale = (215 - 2*quant)*5; int i; - s->intra_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0])>>11; + + t->intra_matrix[0] = (ff_inv_aanscales[0] * ff_mpeg1_default_intra_matrix[0]) >> 11; for(i=1; i<64; i++) - s->intra_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32)>>14; + t->intra_matrix[i] = (ff_inv_aanscales[i] * ff_mpeg1_default_intra_matrix[i] * qscale + 32) >> 14; } static int tqi_decode_frame(AVCodecContext *avctx, @@ -108,16 +124,15 @@ static int tqi_decode_frame(AVCodecContext *avctx, int buf_size = avpkt->size; const uint8_t *buf_end = buf+buf_size; TqiContext *t = avctx->priv_data; - MpegEncContext *s = &t->s; AVFrame *frame = data; - int ret; + int ret, w, h; - s->width = AV_RL16(&buf[0]); - s->height = AV_RL16(&buf[2]); - tqi_calculate_qtable(s, buf[4]); + w = AV_RL16(&buf[0]); + h = AV_RL16(&buf[2]); + tqi_calculate_qtable(t, buf[4]); buf += 8; - ret = ff_set_dimensions(s->avctx, s->width, s->height); + ret = ff_set_dimensions(avctx, w, h); if (ret < 0) return ret; @@ -132,15 +147,17 @@ static int tqi_decode_frame(AVCodecContext *avctx, return AVERROR(ENOMEM); t->bsdsp.bswap_buf(t->bitstream_buf, (const uint32_t *) buf, (buf_end - buf) / 4); - init_get_bits(&s->gb, t->bitstream_buf, 8*(buf_end-buf)); - - s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 0; - for (s->mb_y=0; s->mb_y<(avctx->height+15)/16; s->mb_y++) - for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++) - { - if (tqi_decode_mb(s, t->block) < 0) - break; - tqi_idct_put(t, frame, t->block); + init_get_bits(&t->gb, t->bitstream_buf, 8 * (buf_end - buf)); + + t->last_dc[0] = + t->last_dc[1] = + t->last_dc[2] = 0; + for (t->mb_y = 0; t->mb_y < (h + 15) / 16; t->mb_y++) { + for (t->mb_x = 0; t->mb_x < (w + 15) / 16; t->mb_x++) { + if (tqi_decode_mb(t, t->block) < 0) + break; + tqi_idct_put(avctx, frame, t->block); + } } *got_frame = 1; @@ -163,5 +180,5 @@ AVCodec ff_eatqi_decoder = { .init = tqi_decode_init, .close = tqi_decode_end, .decode = tqi_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/elbg.c b/libavcodec/elbg.c index 0aa8e16..07bb2e3 100644 --- a/libavcodec/elbg.c +++ b/libavcodec/elbg.c @@ -30,7 +30,7 @@ #include "elbg.h" #include "avcodec.h" -#define DELTA_ERR_MAX 0.1 ///< Precision of the ELBG algorithm (as percentual error) +#define DELTA_ERR_MAX 0.1 ///< Precision of the ELBG algorithm (as percentage error) /** * In the ELBG jargon, a cell is the set of points that are closest to a @@ -43,7 +43,7 @@ typedef struct cell_s { /** * ELBG internal data */ -typedef struct{ +typedef struct elbg_data { int error; int dim; int numCB; @@ -189,7 +189,7 @@ static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i, /** * Add the points in the low utility cell to its closest cell. Split the high - * utility cell, putting the separed points in the (now empty) low utility + * utility cell, putting the separated points in the (now empty) low utility * cell. * * @param elbg Internal elbg data @@ -323,41 +323,48 @@ static void do_shiftings(elbg_data *elbg) #define BIG_PRIME 433494437LL -void ff_init_elbg(int *points, int dim, int numpoints, int *codebook, - int numCB, int max_steps, int *closest_cb, - AVLFG *rand_state) +int ff_init_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int max_steps, int *closest_cb, + AVLFG *rand_state) { - int i, k; + int i, k, ret = 0; if (numpoints > 24*numCB) { /* ELBG is very costly for a big number of points. So if we have a lot of them, get a good initial codebook to save on iterations */ int *temp_points = av_malloc(dim*(numpoints/8)*sizeof(int)); + if (!temp_points) + return AVERROR(ENOMEM); for (i=0; iutility_inc = av_malloc(numCB*sizeof(int)); elbg->scratchbuf = av_malloc(5*dim*sizeof(int)); + if (!dist_cb || !size_part || !list_buffer || !elbg->cells || + !elbg->utility || !elbg->utility_inc || !elbg->scratchbuf) { + ret = AVERROR(ENOMEM); + goto out; + } + elbg->rand_state = rand_state; do { @@ -427,6 +440,7 @@ void ff_do_elbg(int *points, int dim, int numpoints, int *codebook, } while(((last_error - elbg->error) > DELTA_ERR_MAX*elbg->error) && (steps < max_steps)); +out: av_free(dist_cb); av_free(size_part); av_free(elbg->utility); @@ -434,4 +448,5 @@ void ff_do_elbg(int *points, int dim, int numpoints, int *codebook, av_free(elbg->cells); av_free(elbg->utility_inc); av_free(elbg->scratchbuf); + return ret; } diff --git a/libavcodec/elbg.h b/libavcodec/elbg.h index b8ea489..3b1587a 100644 --- a/libavcodec/elbg.h +++ b/libavcodec/elbg.h @@ -36,10 +36,11 @@ * @param num_steps The maximum number of steps. One step is already a good compromise between time and quality. * @param closest_cb Return the closest codebook to each point. Must be allocated. * @param rand_state A random number generator state. Should be already initialized by av_lfg_init(). + * @return < 0 in case of error, 0 otherwise */ -void ff_do_elbg(int *points, int dim, int numpoints, int *codebook, - int numCB, int num_steps, int *closest_cb, - AVLFG *rand_state); +int ff_do_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int num_steps, int *closest_cb, + AVLFG *rand_state); /** * Initialize the **codebook vector for the elbg algorithm. If you have already @@ -47,9 +48,10 @@ void ff_do_elbg(int *points, int dim, int numpoints, int *codebook, * If numpoints < 8*numCB this function fills **codebook with random numbers. * If not, it calls ff_do_elbg for a (smaller) random sample of the points in * **points. Get the same parameters as ff_do_elbg. + * @return < 0 in case of error, 0 otherwise */ -void ff_init_elbg(int *points, int dim, int numpoints, int *codebook, - int numCB, int num_steps, int *closest_cb, - AVLFG *rand_state); +int ff_init_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int num_steps, int *closest_cb, + AVLFG *rand_state); #endif /* AVCODEC_ELBG_H */ diff --git a/libavcodec/elsdec.c b/libavcodec/elsdec.c new file mode 100644 index 0000000..10a1a9d --- /dev/null +++ b/libavcodec/elsdec.c @@ -0,0 +1,422 @@ +/* + * ELS (Entropy Logarithmic-Scale) decoder + * + * Copyright (c) 2013 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Entropy Logarithmic-Scale binary arithmetic decoder + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "elsdec.h" + +/* ELS coder constants and structures. */ +#define ELS_JOTS_PER_BYTE 36 +#define ELS_MAX (1 << 24) +#define RUNG_SPACE (64 * sizeof(ElsRungNode)) + +/* ELS coder tables. */ +static const struct Ladder { + int8_t AMps; + int8_t ALps; + uint8_t next0; + uint8_t next1; +} Ladder[174] = { + { -6, -5, 2, 1 }, + { -2, -12, 3, 6 }, + { -2, -12, 4, 6 }, + { -1, -16, 7, 5 }, + { -1, -16, 8, 10 }, + { -5, -6, 11, 9 }, + { -6, -5, 10, 5 }, + { -1, -18, 13, 11 }, + { -1, -18, 12, 14 }, + { -6, -5, 15, 18 }, + { -5, -6, 14, 9 }, + { -3, -8, 17, 15 }, + { -1, -20, 20, 16 }, + { -1, -20, 23, 17 }, + { -3, -8, 16, 18 }, + { -5, -6, 19, 26 }, + { -3, -9, 22, 24 }, + { -3, -9, 21, 19 }, + { -5, -6, 24, 26 }, + { -4, -7, 27, 25 }, + { -1, -22, 34, 28 }, + { -2, -11, 29, 27 }, + { -2, -11, 28, 30 }, + { -1, -22, 39, 29 }, + { -4, -7, 30, 32 }, + { -6, -5, 33, 31 }, + { -6, -5, 32, 25 }, + { -3, -8, 35, 33 }, + { -2, -12, 36, 38 }, + { -2, -12, 37, 35 }, + { -3, -8, 38, 40 }, + { -6, -5, 41, 48 }, + { -6, -5, 40, 31 }, + { -5, -6, 43, 41 }, + { -1, -24, 94, 42 }, + { -3, -8, 45, 43 }, + { -2, -12, 42, 44 }, + { -2, -12, 47, 45 }, + { -3, -8, 44, 46 }, + { -1, -24, 125, 47 }, + { -5, -6, 46, 48 }, + { -6, -5, 49, 49 }, + { -2, -13, 152, 164 }, + { -4, -7, 51, 49 }, + { -3, -9, 164, 168 }, + { -3, -9, 55, 51 }, + { -4, -7, 168, 170 }, + { -2, -13, 67, 55 }, + { -6, -5, 170, 49 }, + { -6, -5, 51, 170 }, + { -1, -72, 50, 74 }, + { -4, -7, 53, 49 }, + { -1, -61, 50, 74 }, + { -3, -8, 55, 49 }, + { -1, -51, 52, 76 }, + { -3, -9, 57, 51 }, + { -1, -46, 54, 76 }, + { -2, -10, 59, 53 }, + { -1, -43, 56, 78 }, + { -2, -11, 61, 53 }, + { -1, -41, 58, 80 }, + { -2, -12, 63, 55 }, + { -1, -39, 60, 82 }, + { -2, -12, 65, 55 }, + { -1, -37, 62, 84 }, + { -2, -13, 67, 57 }, + { -1, -36, 64, 86 }, + { -1, -14, 69, 59 }, + { -1, -35, 66, 88 }, + { -1, -14, 71, 59 }, + { -1, -34, 68, 90 }, + { -1, -15, 73, 61 }, + { -1, -33, 70, 92 }, + { -1, -15, 75, 61 }, + { -1, -32, 72, 94 }, + { -1, -15, 77, 63 }, + { -1, -31, 74, 96 }, + { -1, -16, 79, 65 }, + { -1, -31, 76, 98 }, + { -1, -16, 81, 67 }, + { -1, -30, 78, 100 }, + { -1, -17, 83, 67 }, + { -1, -29, 80, 102 }, + { -1, -17, 85, 69 }, + { -1, -29, 82, 104 }, + { -1, -18, 87, 71 }, + { -1, -28, 84, 104 }, + { -1, -18, 89, 73 }, + { -1, -28, 86, 108 }, + { -1, -18, 91, 73 }, + { -1, -27, 88, 108 }, + { -1, -19, 93, 75 }, + { -1, -27, 90, 112 }, + { -1, -19, 95, 77 }, + { -1, -26, 92, 112 }, + { -1, -20, 97, 79 }, + { -1, -26, 94, 114 }, + { -1, -20, 99, 81 }, + { -1, -25, 96, 116 }, + { -1, -20, 101, 83 }, + { -1, -25, 98, 118 }, + { -1, -21, 103, 83 }, + { -1, -24, 100, 120 }, + { -1, -21, 105, 85 }, + { -1, -24, 102, 122 }, + { -1, -22, 107, 87 }, + { -1, -23, 104, 124 }, + { -1, -22, 109, 89 }, + { -1, -23, 106, 126 }, + { -1, -22, 111, 91 }, + { -1, -22, 108, 128 }, + { -1, -23, 113, 93 }, + { -1, -22, 110, 130 }, + { -1, -23, 115, 95 }, + { -1, -22, 112, 132 }, + { -1, -24, 117, 97 }, + { -1, -21, 114, 134 }, + { -1, -24, 119, 99 }, + { -1, -21, 116, 136 }, + { -1, -25, 121, 101 }, + { -1, -20, 118, 136 }, + { -1, -25, 123, 103 }, + { -1, -20, 120, 138 }, + { -1, -26, 125, 105 }, + { -1, -20, 122, 140 }, + { -1, -26, 127, 107 }, + { -1, -19, 124, 142 }, + { -1, -27, 129, 107 }, + { -1, -19, 126, 144 }, + { -1, -27, 131, 111 }, + { -1, -18, 128, 146 }, + { -1, -28, 133, 111 }, + { -1, -18, 130, 146 }, + { -1, -28, 135, 115 }, + { -1, -18, 132, 148 }, + { -1, -29, 137, 115 }, + { -1, -17, 134, 150 }, + { -1, -29, 139, 117 }, + { -1, -17, 136, 152 }, + { -1, -30, 141, 119 }, + { -1, -16, 138, 152 }, + { -1, -31, 143, 121 }, + { -1, -16, 140, 154 }, + { -1, -31, 145, 123 }, + { -1, -15, 142, 156 }, + { -1, -32, 147, 125 }, + { -1, -15, 144, 158 }, + { -1, -33, 149, 127 }, + { -1, -15, 146, 158 }, + { -1, -34, 151, 129 }, + { -1, -14, 148, 160 }, + { -1, -35, 153, 131 }, + { -1, -14, 150, 160 }, + { -1, -36, 155, 133 }, + { -2, -13, 152, 162 }, + { -1, -37, 157, 135 }, + { -2, -12, 154, 164 }, + { -1, -39, 159, 137 }, + { -2, -12, 156, 164 }, + { -1, -41, 161, 139 }, + { -2, -11, 158, 166 }, + { -1, -43, 163, 141 }, + { -2, -10, 160, 166 }, + { -1, -46, 165, 143 }, + { -3, -9, 162, 168 }, + { -1, -51, 167, 143 }, + { -3, -8, 164, 170 }, + { -1, -61, 169, 145 }, + { -4, -7, 166, 170 }, + { -1, -72, 169, 145 }, + { -6, -5, 168, 49 }, + { 0, -108, 171, 171 }, + { 0, -108, 172, 172 }, + { -6, -5, 173, 173 }, +}; + +static const uint32_t els_exp_tab[ELS_JOTS_PER_BYTE * 4 + 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, 1, 1, 1, + 1, 2, 2, 2, 3, 4, 4, 5, + 6, 7, 8, 10, 11, 13, 16, 18, + 21, 25, 29, 34, 40, 47, 54, 64, + 74, 87, 101, 118, 138, 161, 188, 219, + 256, 298, 348, 406, 474, 552, 645, 752, + 877, 1024, 1194, 1393, 1625, 1896, 2211, 2580, + 3010, 3511, 4096, 4778, 5573, 6501, 7584, 8847, + 10321, 12040, 14045, 16384, 19112, 22295, 26007, 30339, + 35391, 41285, 48160, 56180, 65536, 76288, 89088, 103936, + 121344, 141312, 165120, 192512, 224512, 262144, 305664, 356608, + 416000, 485376, 566016, 660480, 770560, 898816, 1048576, 1223168, + 1426688, 1664256, 1941504, 2264832, 2642176, 3082240, 3595520, 4194304, + 4892672, 5707520, 6657792, 7766784, 9060096, 10568960, 12328960, 14382080, + 16777216, +}; + +void ff_els_decoder_init(ElsDecCtx *ctx, const uint8_t *in, size_t data_size) +{ + int nbytes; + + /* consume up to 3 bytes from the input data */ + if (data_size >= 3) { + ctx->x = AV_RB24(in); + nbytes = 3; + } else if (data_size == 2) { + ctx->x = AV_RB16(in); + nbytes = 2; + } else { + ctx->x = *in; + nbytes = 1; + } + + ctx->in_buf = in + nbytes; + ctx->data_size = data_size - nbytes; + ctx->err = 0; + ctx->j = ELS_JOTS_PER_BYTE; + ctx->t = ELS_MAX; + ctx->diff = FFMIN(ELS_MAX - ctx->x, + ELS_MAX - els_exp_tab[ELS_JOTS_PER_BYTE * 4 - 1]); +} + +void ff_els_decoder_uninit(ElsUnsignedRung *rung) +{ + av_free(rung->rem_rung_list); +} + +static int els_import_byte(ElsDecCtx *ctx) +{ + if (!ctx->data_size) { + ctx->err = AVERROR_EOF; + return AVERROR_EOF; + } + ctx->x = (ctx->x << 8) | *ctx->in_buf++; + ctx->data_size--; + ctx->j += ELS_JOTS_PER_BYTE; + ctx->t <<= 8; + + return 0; +} + +int ff_els_decode_bit(ElsDecCtx *ctx, uint8_t *rung) +{ + int z, bit, ret; + const uint32_t *pAllowable = &els_exp_tab[ELS_JOTS_PER_BYTE * 3]; + + if (ctx->err) + return 0; + + z = pAllowable[ctx->j + Ladder[*rung].ALps]; + ctx->t -= z; + ctx->diff -= z; + if (ctx->diff > 0) + return *rung & 1; /* shortcut for x < t > pAllowable[j - 1] */ + + if (ctx->t > ctx->x) { /* decode most probable symbol (MPS) */ + ctx->j += Ladder[*rung].AMps; + while (ctx->t > pAllowable[ctx->j]) + ctx->j++; + + if (ctx->j <= 0) { /* MPS: import one byte from bytestream. */ + ret = els_import_byte(ctx); + if (ret < 0) + return ret; + } + + z = ctx->t; + bit = *rung & 1; + *rung = Ladder[*rung].next0; + } else { /* decode less probable symbol (LPS) */ + ctx->x -= ctx->t; + ctx->t = z; + + ctx->j += Ladder[*rung].ALps; + if (ctx->j <= 0) { + /* LPS: import one byte from bytestream. */ + z <<= 8; + ret = els_import_byte(ctx); + if (ret < 0) + return ret; + if (ctx->j <= 0) { + /* LPS: import second byte from bytestream. */ + z <<= 8; + ret = els_import_byte(ctx); + if (ret < 0) + return ret; + while (pAllowable[ctx->j - 1] >= z) + ctx->j--; + } + } + + bit = !(*rung & 1); + *rung = Ladder[*rung].next1; + } + + ctx->diff = FFMIN(z - ctx->x, z - pAllowable[ctx->j - 1]); + + return bit; +} + +unsigned ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur) +{ + int i, n, r, bit; + ElsRungNode *rung_node; + + if (ctx->err) + return 0; + + /* decode unary prefix */ + for (n = 0; n < ELS_EXPGOLOMB_LEN + 1; n++) + if (ff_els_decode_bit(ctx, &ur->prefix_rung[n])) + break; + + /* handle the error/overflow case */ + if (ctx->err || n >= ELS_EXPGOLOMB_LEN) { + ctx->err = AVERROR_INVALIDDATA; + return 0; + } + + /* handle the zero case */ + if (!n) + return 0; + + /* initialize probability tree */ + if (!ur->rem_rung_list) { + ur->rem_rung_list = av_realloc(NULL, RUNG_SPACE); + if (!ur->rem_rung_list) { + ctx->err = AVERROR(ENOMEM); + return 0; + } + memset(ur->rem_rung_list, 0, RUNG_SPACE); + ur->rung_list_size = RUNG_SPACE; + ur->avail_index = ELS_EXPGOLOMB_LEN; + } + + /* decode the remainder */ + for (i = 0, r = 0, bit = 0; i < n; i++) { + if (!i) + rung_node = &ur->rem_rung_list[n]; + else { + if (!rung_node->next_index) { + if (ur->rung_list_size <= (ur->avail_index + 2) * sizeof(ElsRungNode)) { + // remember rung_node position + ptrdiff_t pos = rung_node - ur->rem_rung_list; + ur->rem_rung_list = av_realloc(ur->rem_rung_list, + ur->rung_list_size + + RUNG_SPACE); + if (!ur->rem_rung_list) { + av_free(ur->rem_rung_list); + ctx->err = AVERROR(ENOMEM); + return 0; + } + memset((uint8_t *) ur->rem_rung_list + ur->rung_list_size, 0, + RUNG_SPACE); + ur->rung_list_size += RUNG_SPACE; + // restore rung_node position in the new list + rung_node = &ur->rem_rung_list[pos]; + } + rung_node->next_index = ur->avail_index; + ur->avail_index += 2; + } + rung_node = &ur->rem_rung_list[rung_node->next_index + bit]; + } + + bit = ff_els_decode_bit(ctx, &rung_node->rung); + if (ctx->err) + return bit; + + r = (r << 1) + bit; + } + + return (1 << n) - 1 + r; /* make value from exp golomb code */ +} diff --git a/libavcodec/elsdec.h b/libavcodec/elsdec.h new file mode 100644 index 0000000..515b49a --- /dev/null +++ b/libavcodec/elsdec.h @@ -0,0 +1,60 @@ +/* + * ELS (Entropy Logarithmic-Scale) decoder + * + * Copyright (c) 2013 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Entropy Logarithmic-Scale binary arithmetic coder + */ + +#ifndef AVCODEC_ELSDEC_H +#define AVCODEC_ELSDEC_H + +#include +#include + +#define ELS_EXPGOLOMB_LEN 10 + +typedef struct ElsDecCtx { + const uint8_t *in_buf; + unsigned x; + size_t data_size; + int j, t, diff, err; +} ElsDecCtx; + +typedef struct ElsRungNode { + uint8_t rung; + uint16_t next_index; +} ElsRungNode; + +typedef struct ElsUnsignedRung { + uint8_t prefix_rung[ELS_EXPGOLOMB_LEN + 1]; + ElsRungNode *rem_rung_list; + size_t rung_list_size; + uint16_t avail_index; +} ElsUnsignedRung; + +void ff_els_decoder_init(ElsDecCtx *ctx, const uint8_t *in, size_t data_size); +void ff_els_decoder_uninit(ElsUnsignedRung *rung); +int ff_els_decode_bit(ElsDecCtx *ctx, unsigned char *rung); +unsigned ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur); + +#endif /* AVCODEC_ELSDEC_H */ diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 33b0360..d53dfdd 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -30,6 +30,7 @@ #include "libavutil/internal.h" #include "avcodec.h" #include "error_resilience.h" +#include "me_cmp.h" #include "mpegutils.h" #include "mpegvideo.h" #include "rectangle.h" @@ -423,7 +424,7 @@ static void guess_mv(ERContext *s) int best_score = 256 * 256 * 256 * 64; int best_pred = 0; const int mot_index = (mb_x + mb_y * mot_stride) * mot_step; - int prev_x, prev_y, prev_ref; + int prev_x = 0, prev_y = 0, prev_ref = 0; if ((mb_x ^ mb_y ^ pass) & 1) continue; @@ -713,11 +714,11 @@ FF_ENABLE_DEPRECATION_WARNINGS } else { ff_thread_await_progress(s->last_pic.tf, mb_y, 0); } - is_intra_likely += s->mecc->sad[0](NULL, last_mb_ptr, mb_ptr, - linesize[0], 16); - is_intra_likely -= s->mecc->sad[0](NULL, last_mb_ptr, - last_mb_ptr + linesize[0] * 16, - linesize[0], 16); + is_intra_likely += s->mecc.sad[0](NULL, last_mb_ptr, mb_ptr, + linesize[0], 16); + is_intra_likely -= s->mecc.sad[0](NULL, last_mb_ptr, + last_mb_ptr + linesize[0] * 16, + linesize[0], 16); } else { if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) is_intra_likely++; @@ -734,6 +735,11 @@ void ff_er_frame_start(ERContext *s) if (!s->avctx->error_concealment) return; + if (!s->mecc_inited) { + ff_me_cmp_init(&s->mecc, s->avctx); + s->mecc_inited = 1; + } + memset(s->error_status_table, ER_MB_ERROR | VP_START | ER_MB_END, s->mb_stride * s->mb_height * sizeof(uint8_t)); s->error_count = 3 * s->mb_num; @@ -928,7 +934,7 @@ void ff_er_frame_end(ERContext *s) 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 + if (s->mbskip_table && !s->mbskip_table[mb_xy]) // FIXME partition specific distance++; if (error & (1 << error_type)) distance = 0; @@ -1041,7 +1047,7 @@ void ff_er_frame_end(ERContext *s) s->mv[0][0][1] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1]; } - s->decode_mb(s->opaque, 0 /* FIXME h264 partitioned slices need this set */, + s->decode_mb(s->opaque, 0 /* FIXME H.264 partitioned slices need this set */, mv_dir, mv_type, &s->mv, mb_x, mb_y, 0, 0); } } @@ -1193,17 +1199,20 @@ FF_ENABLE_DEPRECATION_WARNINGS s->mb_height, linesize[2], 0); } +#if FF_API_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->cur_pic.f->pict_type != AV_PICTURE_TYPE_B && + if (s->mbskip_table && s->cur_pic.f->pict_type != AV_PICTURE_TYPE_B && (error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) { s->mbskip_table[mb_xy] = 0; } - s->mbintra_table[mb_xy] = 1; + if (s->mbintra_table) + s->mbintra_table[mb_xy] = 1; } memset(&s->cur_pic, 0, sizeof(ERPicture)); diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 7b9ec19..3139880 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -42,7 +41,7 @@ typedef struct ERPicture { AVFrame *f; ThreadFrame *tf; - // it's the caller responsability to allocate these buffers + // it is the caller's responsibility to allocate these buffers int16_t (*motion_val[2])[2]; int8_t *ref_index[2]; @@ -52,7 +51,8 @@ typedef struct ERPicture { typedef struct ERContext { AVCodecContext *avctx; - MECmpContext *mecc; + MECmpContext mecc; + int mecc_inited; int *mb_index2xy; int mb_num; diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index 30f22e0..6d1b487 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -19,11 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" -#include "internal.h" - #define BITSTREAM_READER_LE +#include "avcodec.h" #include "get_bits.h" +#include "internal.h" typedef union MacroBlock { uint16_t pixels[4]; @@ -147,10 +146,11 @@ static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb, // This function reads a maximum of 22 bits; the callers // guard this function appropriately unsigned block_index, depth; - - if (get_bits1(gb)) { + int value = get_bits1(gb); + if (value) { static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} }; - *codebook_index = transitions[*codebook_index][get_bits1(gb)]; + value = get_bits1(gb); + *codebook_index = transitions[*codebook_index][value]; } depth = s->codebooks[*codebook_index].depth; @@ -158,7 +158,7 @@ static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb, // depth = 0 means that this shouldn't read any bits; // in theory, this is the same as get_bits(gb, 0), but // that doesn't actually work. - block_index = depth ? get_bits(gb, depth) : 0; + block_index = get_bitsz(gb, depth); if (*codebook_index == 1) { block_index += superblock_index << s->codebooks[1].depth; @@ -379,5 +379,5 @@ AVCodec ff_escape124_decoder = { .init = escape124_decode_init, .close = escape124_decode_close, .decode = escape124_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/escape130.c b/libavcodec/escape130.c index bc865a3..bfc1f3f 100644 --- a/libavcodec/escape130.c +++ b/libavcodec/escape130.c @@ -21,8 +21,9 @@ #include "libavutil/attributes.h" #include "libavutil/mem.h" -#include "avcodec.h" + #define BITSTREAM_READER_LE +#include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -105,7 +106,7 @@ static const int8_t chroma_adjust[2][8] = { { 0, 1, 1, 1, 0, -1, -1, -1 } }; -const uint8_t chroma_vals[] = { +static const uint8_t chroma_vals[] = { 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 106, 112, 116, 120, 124, 128, 132, 136, 140, 144, 150, 156, 164, @@ -331,7 +332,7 @@ static int escape130_decode_frame(AVCodecContext *avctx, void *data, new_cr += new_cr_stride; } - av_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n", + ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n", buf_size, get_bits_count(&gb) >> 3); FFSWAP(uint8_t*, s->old_y, s->new_y); @@ -352,5 +353,5 @@ AVCodec ff_escape130_decoder = { .init = escape130_decode_init, .close = escape130_decode_close, .decode = escape130_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 37a31ce..d10841d 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -27,12 +27,15 @@ * For more information on the OpenEXR format, visit: * http://openexr.com/ * - * exr_flt2uint() and exr_halflt2uint() is credited to Reimar Döffinger + * exr_flt2uint() and exr_halflt2uint() is credited to Reimar Döffinger. + * exr_half2float() is credited to Aaftab Munshi, Dan Ginsburg, Dave Shreiner. */ +#include #include #include "libavutil/imgutils.h" +#include "libavutil/intfloat.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -106,8 +109,74 @@ typedef struct EXRContext { EXRThreadData *thread_data; const char *layer; + + float gamma; + uint16_t gamma_table[65536]; } EXRContext; +/* -15 stored using a single precision bias of 127 */ +#define HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP 0x38000000 + +/* max exponent value in single precision that will be converted + * to Inf or Nan when stored as a half-float */ +#define HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP 0x47800000 + +/* 255 is the max exponent biased value */ +#define FLOAT_MAX_BIASED_EXP (0xFF << 23) + +#define HALF_FLOAT_MAX_BIASED_EXP (0x1F << 10) + +/** + * Convert a half float as a uint16_t into a full float. + * + * @param hf half float as uint16_t + * + * @return float value + */ +static union av_intfloat32 exr_half2float(uint16_t hf) +{ + unsigned int sign = (unsigned int) (hf >> 15); + unsigned int mantissa = (unsigned int) (hf & ((1 << 10) - 1)); + unsigned int exp = (unsigned int) (hf & HALF_FLOAT_MAX_BIASED_EXP); + union av_intfloat32 f; + + if (exp == HALF_FLOAT_MAX_BIASED_EXP) { + // we have a half-float NaN or Inf + // half-float NaNs will be converted to a single precision NaN + // half-float Infs will be converted to a single precision Inf + exp = FLOAT_MAX_BIASED_EXP; + if (mantissa) + mantissa = (1 << 23) - 1; // set all bits to indicate a NaN + } else if (exp == 0x0) { + // convert half-float zero/denorm to single precision value + if (mantissa) { + mantissa <<= 1; + exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; + // check for leading 1 in denorm mantissa + while ((mantissa & (1 << 10))) { + // for every leading 0, decrement single precision exponent by 1 + // and shift half-float mantissa value to the left + mantissa <<= 1; + exp -= (1 << 23); + } + // clamp the mantissa to 10 bits + mantissa &= ((1 << 10) - 1); + // shift left to generate single-precision mantissa of 23 bits + mantissa <<= 13; + } + } else { + // shift left to generate single-precision mantissa of 23 bits + mantissa <<= 13; + // generate single precision biased exponent value + exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; + } + + f.i = (sign << 31) | exp | mantissa; + + return f; +} + + /** * Convert from 32-bit float as uint32_t to uint16_t. * @@ -311,8 +380,9 @@ static int huf_unpack_enc_table(GetByteContext *gb, int32_t im, int32_t iM, uint64_t *hcode) { GetBitContext gbit; - - init_get_bits8(&gbit, gb->buffer, bytestream2_get_bytes_left(gb)); + int ret = init_get_bits8(&gbit, gb->buffer, bytestream2_get_bytes_left(gb)); + if (ret < 0) + return ret; for (; im <= iM; im++) { uint64_t l = hcode[im] = get_bits(&gbit, 6); @@ -389,7 +459,7 @@ static int huf_build_dec_table(const uint64_t *hcode, int im, lc += 8; \ } -#define get_code(po, rlc, c, lc, gb, out, oe) \ +#define get_code(po, rlc, c, lc, gb, out, oe, outb) \ { \ if (po == rlc) { \ if (lc < 8) \ @@ -398,7 +468,7 @@ static int huf_build_dec_table(const uint64_t *hcode, int im, \ cs = c >> lc; \ \ - if (out + cs > oe) \ + if (out + cs > oe || out == outb) \ return AVERROR_INVALIDDATA; \ \ s = out[-1]; \ @@ -431,7 +501,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, if (pl.len) { lc -= pl.len; - get_code(pl.lit, rlc, c, lc, gb, out, oe); + get_code(pl.lit, rlc, c, lc, gb, out, oe, outb); } else { int j; @@ -448,7 +518,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, if ((hcode[pl.p[j]] >> 6) == ((c >> (lc - l)) & ((1LL << l) - 1))) { lc -= l; - get_code(pl.p[j], rlc, c, lc, gb, out, oe); + get_code(pl.p[j], rlc, c, lc, gb, out, oe, outb); break; } } @@ -469,7 +539,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, if (pl.len) { lc -= pl.len; - get_code(pl.lit, rlc, c, lc, gb, out, oe); + get_code(pl.lit, rlc, c, lc, gb, out, oe, outb); } else { return AVERROR_INVALIDDATA; } @@ -771,6 +841,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; int bxmin = s->xmin * 2 * s->desc->nb_components; int i, x, buf_size = s->buf_size; + float one_gamma = 1.0f / s->gamma; int ret; line_offset = AV_RL64(s->gb.buffer + jobnr * 8); @@ -851,18 +922,30 @@ static int decode_block(AVCodecContext *avctx, void *tdata, if (s->pixel_type == EXR_FLOAT) { // 32-bit for (x = 0; x < xdelta; x++) { - *ptr_x++ = exr_flt2uint(bytestream_get_le32(&r)); - *ptr_x++ = exr_flt2uint(bytestream_get_le32(&g)); - *ptr_x++ = exr_flt2uint(bytestream_get_le32(&b)); + union av_intfloat32 t; + t.i = bytestream_get_le32(&r); + if (t.f > 0.0f) /* avoid negative values */ + t.f = powf(t.f, one_gamma); + *ptr_x++ = exr_flt2uint(t.i); + + t.i = bytestream_get_le32(&g); + if (t.f > 0.0f) + t.f = powf(t.f, one_gamma); + *ptr_x++ = exr_flt2uint(t.i); + + t.i = bytestream_get_le32(&b); + if (t.f > 0.0f) + t.f = powf(t.f, one_gamma); + *ptr_x++ = exr_flt2uint(t.i); if (channel_buffer[3]) *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a)); } } else { // 16-bit for (x = 0; x < xdelta; x++) { - *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&r)); - *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&g)); - *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&b)); + *ptr_x++ = s->gamma_table[bytestream_get_le16(&r)]; + *ptr_x++ = s->gamma_table[bytestream_get_le16(&g)]; + *ptr_x++ = s->gamma_table[bytestream_get_le16(&b)]; if (channel_buffer[3]) *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a)); } @@ -1009,8 +1092,7 @@ static int decode_header(EXRContext *s) current_pixel_type = bytestream2_get_le32(&ch_gb); if (current_pixel_type >= EXR_UNKNOWN) { - avpriv_report_missing_feature(s->avctx, - "Pixel type %d.\n", + avpriv_report_missing_feature(s->avctx, "Pixel type %d", current_pixel_type); return AVERROR_PATCHWELCOME; } @@ -1262,6 +1344,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, static av_cold int decode_init(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; + uint32_t i; + union av_intfloat32 t; + float one_gamma = 1.0f / s->gamma; s->avctx = avctx; s->xmin = ~0; @@ -1280,7 +1365,23 @@ static av_cold int decode_init(AVCodecContext *avctx) s->w = 0; s->h = 0; - // allocate thread data, used for non EXR_RAW compreesion types + if (one_gamma > 0.9999f && one_gamma < 1.0001f) { + for (i = 0; i < 65536; ++i) + s->gamma_table[i] = exr_halflt2uint(i); + } else { + for (i = 0; i < 65536; ++i) { + t = exr_half2float(i); + /* If negative value we reuse half value */ + if (t.f <= 0.0f) { + s->gamma_table[i] = exr_halflt2uint(i); + } else { + t.f = powf(t.f, one_gamma); + s->gamma_table[i] = exr_flt2uint(t.i); + } + } + } + + // allocate thread data, used for non EXR_RAW compression types s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData)); if (!s->thread_data) return AVERROR_INVALIDDATA; @@ -1291,7 +1392,7 @@ static av_cold int decode_init(AVCodecContext *avctx) static int decode_init_thread_copy(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; - // allocate thread data, used for non EXR_RAW compreesion types + // allocate thread data, used for non EXR_RAW compression types s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData)); if (!s->thread_data) return AVERROR_INVALIDDATA; @@ -1322,6 +1423,8 @@ static av_cold int decode_end(AVCodecContext *avctx) static const AVOption options[] = { { "layer", "Set the decoding layer", OFFSET(layer), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, + { "gamma", "Set the float gamma value when decoding", OFFSET(gamma), + AV_OPT_TYPE_FLOAT, { .dbl = 1.0f }, 0.001, FLT_MAX, VD }, { NULL }, }; @@ -1342,7 +1445,7 @@ AVCodec ff_exr_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | - CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS, .priv_class = &exr_class, }; diff --git a/libavcodec/faandct.c b/libavcodec/faandct.c index b1d7a14..7888633 100644 --- a/libavcodec/faandct.c +++ b/libavcodec/faandct.c @@ -68,7 +68,6 @@ static av_always_inline void row_fdct(FLOAT temp[64], int16_t *data) FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FLOAT tmp10, tmp11, tmp12, tmp13; FLOAT z2, z4, z11, z13; - FLOAT av_unused z5; int i; for (i=0; i<8*8; i+=8) { @@ -98,14 +97,9 @@ static av_always_inline void row_fdct(FLOAT temp[64], int16_t *data) tmp5 += tmp6; tmp6 += tmp7; -#if 0 - z5= (tmp4 - tmp6) * A5; - z2= tmp4*A2 + z5; - z4= tmp6*A4 + z5; -#else z2= tmp4*(A2+A5) - tmp6*A5; z4= tmp6*(A4-A5) + tmp4*A5; -#endif + tmp5*=A1; z11= tmp7 + tmp5; @@ -123,7 +117,6 @@ void ff_faandct(int16_t *data) FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FLOAT tmp10, tmp11, tmp12, tmp13; FLOAT z2, z4, z11, z13; - FLOAT av_unused z5; FLOAT temp[64]; int i; @@ -158,14 +151,9 @@ void ff_faandct(int16_t *data) tmp5 += tmp6; tmp6 += tmp7; -#if 0 - z5= (tmp4 - tmp6) * A5; - z2= tmp4*A2 + z5; - z4= tmp6*A4 + z5; -#else z2= tmp4*(A2+A5) - tmp6*A5; z4= tmp6*(A4-A5) + tmp4*A5; -#endif + tmp5*=A1; z11= tmp7 + tmp5; diff --git a/libavcodec/faanidct.c b/libavcodec/faanidct.c index 5cacfdd..b132f89 100644 --- a/libavcodec/faanidct.c +++ b/libavcodec/faanidct.c @@ -49,7 +49,6 @@ B7*B0/8, B7*B1/8, B7*B2/8, B7*B3/8, B7*B4/8, B7*B5/8, B7*B6/8, B7*B7/8, static inline void p8idct(int16_t data[64], FLOAT temp[64], uint8_t *dest, int stride, int x, int y, int type){ int i; - FLOAT av_unused tmp0; FLOAT s04, d04, s17, d17, s26, d26, s53, d53; FLOAT os07, os16, os25, os34; FLOAT od07, od16, od25, od34; @@ -63,14 +62,8 @@ static inline void p8idct(int16_t data[64], FLOAT temp[64], uint8_t *dest, int s od07= s17 + s53; od25= (s17 - s53)*(2*A4); -#if 0 //these 2 are equivalent - tmp0= (d17 + d53)*(2*A2); - od34= d17*( 2*B6) - tmp0; - od16= d53*(-2*B2) + tmp0; -#else od34= d17*(2*(B6-A2)) - d53*(2*A2); od16= d53*(2*(A2-B2)) + d17*(2*A2); -#endif od16 -= od07; od25 -= od16; diff --git a/libavcodec/faxcompr.h b/libavcodec/faxcompr.h index 8157f1f..0a8b64d 100644 --- a/libavcodec/faxcompr.h +++ b/libavcodec/faxcompr.h @@ -31,7 +31,7 @@ #include "tiff.h" /** - * initialize upacker code + * initialize unpacker code */ void ff_ccitt_unpack_init(void); diff --git a/libavcodec/fdctdsp.c b/libavcodec/fdctdsp.c index b245198..f299eae 100644 --- a/libavcodec/fdctdsp.c +++ b/libavcodec/fdctdsp.c @@ -30,17 +30,17 @@ av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx) if (avctx->bits_per_raw_sample == 10) { c->fdct = ff_jpeg_fdct_islow_10; c->fdct248 = ff_fdct248_islow_10; + } else if (avctx->dct_algo == FF_DCT_FASTINT) { + c->fdct = ff_fdct_ifast; + c->fdct248 = ff_fdct_ifast248; +#if CONFIG_FAANDCT + } else if (avctx->dct_algo == FF_DCT_FAAN) { + c->fdct = ff_faandct; + c->fdct248 = ff_faandct248; +#endif /* CONFIG_FAANDCT */ } else { - if (avctx->dct_algo == FF_DCT_FASTINT) { - c->fdct = ff_fdct_ifast; - c->fdct248 = ff_fdct_ifast248; - } else if (avctx->dct_algo == FF_DCT_FAAN) { - c->fdct = ff_faandct; - c->fdct248 = ff_faandct248; - } else { - c->fdct = ff_jpeg_fdct_islow_8; // slow/accurate/default - c->fdct248 = ff_fdct248_islow_8; - } + c->fdct = ff_jpeg_fdct_islow_8; // slow/accurate/default + c->fdct248 = ff_fdct248_islow_8; } if (ARCH_PPC) diff --git a/libavcodec/fft.h b/libavcodec/fft.h index 7daae24..57dc17f 100644 --- a/libavcodec/fft.h +++ b/libavcodec/fft.h @@ -154,4 +154,11 @@ void ff_fft_end(FFTContext *s); int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale); void ff_mdct_end(FFTContext *s); +void ff_mdct_init_aarch64(FFTContext *s); +void ff_mdct_init_arm(FFTContext *s); +void ff_mdct_init_ppc(FFTContext *s); +void ff_mdct_init_x86(FFTContext *s); + +void ff_mdct_fixed_init_arm(FFTContext *s); + #endif /* AVCODEC_FFT_H */ diff --git a/libavcodec/fft_template.c b/libavcodec/fft_template.c index 808f317..3642b43 100644 --- a/libavcodec/fft_template.c +++ b/libavcodec/fft_template.c @@ -151,20 +151,13 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse) s->fft_permute = fft_permute_c; s->fft_calc = fft_calc_c; -#if CONFIG_MDCT - s->imdct_calc = ff_imdct_calc_c; - s->imdct_half = ff_imdct_half_c; - s->mdct_calc = ff_mdct_calc_c; -#endif #if FFT_FLOAT if (ARCH_AARCH64) ff_fft_init_aarch64(s); if (ARCH_ARM) ff_fft_init_arm(s); if (ARCH_PPC) ff_fft_init_ppc(s); if (ARCH_X86) ff_fft_init_x86(s); - if (CONFIG_MDCT) s->mdct_calcw = s->mdct_calc; #else - if (CONFIG_MDCT) s->mdct_calcw = ff_mdct_calcw_c; if (ARCH_ARM) ff_fft_fixed_init_arm(s); #endif diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index d1a6a83..89d27bb 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -26,12 +26,10 @@ */ #include "libavutil/attributes.h" -#include "libavutil/avassert.h" + #include "avcodec.h" -#include "get_bits.h" #include "put_bits.h" #include "rangecoder.h" -#include "golomb.h" #include "mathops.h" #include "ffv1.h" @@ -160,7 +158,7 @@ int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) for (j = 0; j < f->plane_count; j++) { PlaneContext *const p = &fs->plane[j]; - if (fs->ac) { + if (fs->ac != AC_GOLOMB_RICE) { if (!p->state) p->state = av_malloc(CONTEXT_SIZE * p->context_count * sizeof(uint8_t)); @@ -174,7 +172,7 @@ int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) } } - if (fs->ac > 1) { + if (fs->ac == AC_RANGE_CUSTOM_TAB) { //FIXME only redo if state_transition changed for (j = 1; j < 256; j++) { fs->c.one_state[j] = f->state_transition[j]; @@ -187,7 +185,7 @@ int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) av_cold int ffv1_init_slice_contexts(FFV1Context *f) { - int i; + int i, j; f->slice_count = f->num_h_slices * f->num_v_slices; if (f->slice_count <= 0) { @@ -196,13 +194,16 @@ av_cold int ffv1_init_slice_contexts(FFV1Context *f) } for (i = 0; i < f->slice_count; i++) { - FFV1Context *fs = av_mallocz(sizeof(*fs)); int sx = i % f->num_h_slices; int sy = i / f->num_h_slices; int sxs = f->avctx->width * sx / f->num_h_slices; int sxe = f->avctx->width * (sx + 1) / f->num_h_slices; int sys = f->avctx->height * sy / f->num_v_slices; int sye = f->avctx->height * (sy + 1) / f->num_v_slices; + FFV1Context *fs = av_mallocz(sizeof(*fs)); + if (!fs) + goto memfail; + f->slice_context[i] = fs; memcpy(fs, f, sizeof(*fs)); memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2)); @@ -214,10 +215,19 @@ av_cold int ffv1_init_slice_contexts(FFV1Context *f) fs->sample_buffer = av_malloc(3 * MAX_PLANES * (fs->width + 6) * sizeof(*fs->sample_buffer)); - if (!fs->sample_buffer) - return AVERROR(ENOMEM); + if (!fs->sample_buffer) { + av_free(fs); + goto memfail; + } } return 0; + +memfail: + for (j = 0; j < i; j++) { + av_free(f->slice_context[j]->sample_buffer); + av_free(f->slice_context[j]); + } + return AVERROR(ENOMEM); } int ffv1_allocate_initial_states(FFV1Context *f) @@ -245,7 +255,7 @@ void ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs) p->interlace_bit_state[0] = 128; p->interlace_bit_state[1] = 128; - if (fs->ac) { + if (fs->ac != AC_GOLOMB_RICE) { if (f->initial_states[p->quant_table_index]) { memcpy(p->state, f->initial_states[p->quant_table_index], CONTEXT_SIZE * p->context_count); diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 5c3bdc1..34370fa 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -36,6 +36,10 @@ #define MAX_QUANT_TABLES 8 #define MAX_CONTEXT_INPUTS 5 +#define AC_GOLOMB_RICE 0 +#define AC_RANGE_DEFAULT_TAB 1 +#define AC_RANGE_CUSTOM_TAB 2 + extern const uint8_t ff_log2_run[41]; extern const int8_t ffv1_quant5_10bit[256]; @@ -78,7 +82,8 @@ typedef struct FFV1Context { int transparency; int flags; int picture_number; - AVFrame *frame; + int key_frame; + const AVFrame *frame; AVFrame *last_picture; AVFrame *cur; @@ -98,6 +103,7 @@ typedef struct FFV1Context { int ec; int slice_damaged; int key_frame_ok; + int context_model; int bits_per_raw_sample; int packed_at_lsb; diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 50b220f..d3169ec 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -80,15 +80,10 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, assert(k <= 8); v = get_sr_golomb(gb, k, 12, bits); - av_dlog(NULL, "v:%d bias:%d error:%d drift:%d count:%d k:%d", + ff_dlog(NULL, "v:%d bias:%d error:%d drift:%d count:%d k:%d", v, state->bias, state->error_sum, state->drift, state->count, k); -#if 0 // JPEG LS - if (k == 0 && 2 * state->drift <= -state->count) - v ^= (-1); -#else v ^= ((2 * state->drift + state->count) >> 31); -#endif ret = fold(v + state->bias, bits); @@ -120,7 +115,7 @@ static av_always_inline void decode_line(FFV1Context *s, int w, av_assert2(context < p->context_count); - if (s->ac) { + if (s->ac != AC_GOLOMB_RICE) { diff = get_symbol_inline(c, p->state[context], 1); } else { if (context == 0 && run_mode == 0) @@ -155,7 +150,7 @@ static av_always_inline void decode_line(FFV1Context *s, int w, } else diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); - av_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", + ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", run_count, run_index, run_mode, x, get_bits_count(&s->gb)); } @@ -274,7 +269,7 @@ static int decode_slice_header(FFV1Context *f, FFV1Context *fs) unsigned ps, i, context_count; memset(state, 128, sizeof(state)); - if (fs->ac > 1) { + if (fs->ac == AC_RANGE_CUSTOM_TAB) { for (i = 1; i < 256; i++) { fs->c.one_state[i] = f->state_transition[i]; fs->c.zero_state[256 - i] = 256 - fs->c.one_state[i]; @@ -364,7 +359,7 @@ static int decode_slice(AVCodecContext *c, void *arg) x = fs->slice_x; y = fs->slice_y; - if (!fs->ac) { + if (fs->ac == AC_GOLOMB_RICE) { if (f->version == 3 && f->minor_version > 1 || f->version > 3) get_rac(&fs->c, (uint8_t[]) { 129 }); fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0; @@ -375,8 +370,8 @@ static int decode_slice(AVCodecContext *c, void *arg) av_assert1(width && height); if (f->colorspace == 0) { - const int chroma_width = -((-width) >> f->chroma_h_shift); - const int chroma_height = -((-height) >> f->chroma_v_shift); + const int chroma_width = AV_CEIL_RSHIFT(width, f->chroma_h_shift); + const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift); const int cx = x >> f->chroma_h_shift; const int cy = y >> f->chroma_v_shift; decode_plane(fs, p->data[0] + ps * x + y * p->linesize[0], width, @@ -401,7 +396,7 @@ static int decode_slice(AVCodecContext *c, void *arg) p->data[2] + ps * x + y * p->linesize[2] }; decode_rgb_frame(fs, planes, width, height, p->linesize); } - if (fs->ac && f->version > 2) { + if (fs->ac != AC_GOLOMB_RICE && f->version > 2) { int v; get_rac(&fs->c, (uint8_t[]) { 129 }); v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5 * f->ec; @@ -477,9 +472,9 @@ static int read_extra_header(FFV1Context *f) c->bytestream_end -= 4; f->minor_version = get_symbol(c, state, 0); } - f->ac = f->avctx->coder_type = get_symbol(c, state, 0); + f->ac = get_symbol(c, state, 0); - if (f->ac > 1) { + if (f->ac == AC_RANGE_CUSTOM_TAB) { for (i = 1; i < 256; i++) f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i]; } @@ -537,6 +532,13 @@ static int read_extra_header(FFV1Context *f) } } + av_log(f->avctx, AV_LOG_VERBOSE, + "FFV1 version %d.%d colorspace %d - %d bits - %d/%d planes, %s transparent - tile geometry %dx%d - %s\n", + f->version, f->minor_version, f->colorspace, f->avctx->bits_per_raw_sample, + f->plane_count, f->chroma_planes, f->transparency ? "" : "not", + f->num_h_slices, f->num_v_slices, + f->ec ? "per-slice crc" : "no crc"); + return 0; } @@ -559,9 +561,9 @@ static int read_header(FFV1Context *f) } f->version = v; - f->ac = f->avctx->coder_type = get_symbol(c, state, 0); + f->ac = get_symbol(c, state, 0); - if (f->ac > 1) { + if (f->ac == AC_RANGE_CUSTOM_TAB) { for (i = 1; i < 256; i++) f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i]; @@ -597,6 +599,12 @@ static int read_header(FFV1Context *f) } if (f->colorspace == 0) { + if (f->transparency && f->avctx->bits_per_raw_sample > 8) { + av_log(f->avctx, AV_LOG_ERROR, + "Transparency not supported for bit depth %d\n", + f->avctx->bits_per_raw_sample); + return AVERROR(ENOSYS); + } if (!f->transparency && !f->chroma_planes) { if (f->avctx->bits_per_raw_sample <= 8) f->avctx->pix_fmt = AV_PIX_FMT_GRAY8; @@ -695,6 +703,11 @@ static int read_header(FFV1Context *f) "chroma subsampling not supported in this colorspace\n"); return AVERROR(ENOSYS); } + if (f->transparency) { + av_log(f->avctx, AV_LOG_ERROR, + "Transparency not supported in this colorspace\n"); + return AVERROR(ENOSYS); + } switch (f->avctx->bits_per_raw_sample) { case 0: case 8: @@ -717,7 +730,7 @@ static int read_header(FFV1Context *f) return AVERROR(ENOSYS); } - av_dlog(f->avctx, "%d %d %d\n", + ff_dlog(f->avctx, "%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift, f->avctx->pix_fmt); if (f->version < 2) { context_count = read_quant_tables(c, f->quant_table); @@ -827,13 +840,13 @@ static av_cold int ffv1_decode_init(AVCodecContext *avctx) static int ffv1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - const uint8_t *buf = avpkt->data; + uint8_t *buf = avpkt->data; int buf_size = avpkt->size; FFV1Context *f = avctx->priv_data; RangeCoder *const c = &f->slice_context[0]->c; int i, ret; uint8_t keystate = 128; - const uint8_t *buf_p; + uint8_t *buf_p; AVFrame *const p = data; f->cur = p; @@ -895,7 +908,7 @@ static int ffv1_decode_frame(AVCodecContext *avctx, void *data, if (i) { ff_init_range_decoder(&fs->c, buf_p, v); } else - fs->c.bytestream_end = (uint8_t *)(buf_p + v); + fs->c.bytestream_end = buf_p + v; fs->cur = p; } @@ -919,7 +932,7 @@ static int ffv1_decode_frame(AVCodecContext *avctx, void *data, f->last_picture->linesize[j] * (fs->slice_y >> sv) + (fs->slice_x >> sh); } - av_image_copy(dst, p->linesize, (const uint8_t **)src, + av_image_copy(dst, p->linesize, src, f->last_picture->linesize, avctx->pix_fmt, fs->slice_width, fs->slice_height); @@ -958,6 +971,6 @@ AVCodec ff_ffv1_decoder = { .init = ffv1_decode_init, .close = ffv1_decode_close, .decode = ffv1_decode_frame, - .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/ | - CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/ | + AV_CODEC_CAP_SLICE_THREADS, }; diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 93630b4..0eeccff 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -31,9 +31,9 @@ #include "libavutil/crc.h" #include "libavutil/opt.h" #include "libavutil/imgutils.h" + #include "avcodec.h" #include "internal.h" -#include "get_bits.h" #include "put_bits.h" #include "rangecoder.h" #include "golomb.h" @@ -151,16 +151,9 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, assert(k <= 13); -#if 0 // JPEG LS - if (k == 0 && 2 * state->drift <= -state->count) - code = v ^ (-1); - else - code = v; -#else code = v ^ ((2 * state->drift + state->count) >> 31); -#endif - av_dlog(NULL, "v:%d/%d bias:%d error:%d drift:%d count:%d k:%d\n", v, code, + ff_dlog(NULL, "v:%d/%d bias:%d error:%d drift:%d count:%d k:%d\n", v, code, state->bias, state->error_sum, state->drift, state->count, k); set_sr_golomb(pb, code, k, 12, bits); @@ -178,7 +171,7 @@ static av_always_inline int encode_line(FFV1Context *s, int w, int run_count = 0; int run_mode = 0; - if (s->ac) { + if (s->ac != AC_GOLOMB_RICE) { if (c->bytestream_end - c->bytestream < w * 20) { av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); return AVERROR_INVALIDDATA; @@ -203,8 +196,8 @@ static av_always_inline int encode_line(FFV1Context *s, int w, diff = fold(diff, bits); - if (s->ac) { - if (s->flags & CODEC_FLAG_PASS1) { + if (s->ac != AC_GOLOMB_RICE) { + if (s->flags & AV_CODEC_FLAG_PASS1) { put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, s->rc_stat2[p->quant_table_index][context]); } else { @@ -234,7 +227,7 @@ static av_always_inline int encode_line(FFV1Context *s, int w, } } - av_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", + ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", run_count, run_index, run_mode, x, (int)put_bits_count(&s->pb)); @@ -261,7 +254,7 @@ 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; + const int ring_size = s->context_model ? 3 : 2; int16_t *sample[3]; s->run_index = 0; @@ -293,11 +286,11 @@ static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, } } -static void encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, - int stride[3]) +static void encode_rgb_frame(FFV1Context *s, const uint8_t *src[3], + int w, int h, const int stride[3]) { int x, y, p, i; - const int ring_size = s->avctx->context_model ? 3 : 2; + const int ring_size = s->context_model ? 3 : 2; int16_t *sample[MAX_PLANES][3]; int lbd = s->avctx->bits_per_raw_sample <= 8; int bits = s->avctx->bits_per_raw_sample > 0 @@ -320,15 +313,15 @@ static void encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, for (x = 0; x < w; x++) { int b, g, r, av_uninit(a); if (lbd) { - unsigned v = *((uint32_t *)(src[0] + x * 4 + stride[0] * y)); + unsigned v = *((const uint32_t *)(src[0] + x * 4 + stride[0] * y)); b = v & 0xFF; g = (v >> 8) & 0xFF; r = (v >> 16) & 0xFF; a = v >> 24; } else { - b = *((uint16_t *)(src[0] + x * 2 + stride[0] * y)); - g = *((uint16_t *)(src[1] + x * 2 + stride[1] * y)); - r = *((uint16_t *)(src[2] + x * 2 + stride[2] * y)); + b = *((const uint16_t *)(src[0] + x * 2 + stride[0] * y)); + g = *((const uint16_t *)(src[1] + x * 2 + stride[1] * y)); + r = *((const uint16_t *)(src[2] + x * 2 + stride[2] * y)); } b -= g; @@ -380,7 +373,7 @@ static void write_quant_tables(RangeCoder *c, static void write_header(FFV1Context *f) { uint8_t state[CONTEXT_SIZE]; - int i, j; + int i; RangeCoder *const c = &f->slice_context[0]->c; memset(state, 128, sizeof(state)); @@ -388,7 +381,7 @@ static void write_header(FFV1Context *f) if (f->version < 2) { put_symbol(c, state, f->version, 0); put_symbol(c, state, f->ac, 0); - if (f->ac > 1) { + if (f->ac == AC_RANGE_CUSTOM_TAB) { for (i = 1; i < 256; i++) put_symbol(c, state, f->state_transition[i] - c->one_state[i], 1); @@ -402,25 +395,6 @@ static void write_header(FFV1Context *f) put_rac(c, state, f->transparency); write_quant_tables(c, f->quant_table); - } else if (f->version < 3) { - put_symbol(c, state, f->slice_count, 0); - for (i = 0; i < f->slice_count; i++) { - FFV1Context *fs = f->slice_context[i]; - put_symbol(c, state, - (fs->slice_x + 1) * f->num_h_slices / f->width, 0); - put_symbol(c, state, - (fs->slice_y + 1) * f->num_v_slices / f->height, 0); - put_symbol(c, state, - (fs->slice_width + 1) * f->num_h_slices / f->width - 1, - 0); - put_symbol(c, state, - (fs->slice_height + 1) * f->num_v_slices / f->height - 1, - 0); - for (j = 0; j < f->plane_count; j++) { - put_symbol(c, state, f->plane[j].quant_table_index, 0); - av_assert0(f->plane[j].quant_table_index == f->avctx->context_model); - } - } } } @@ -442,14 +416,14 @@ static int write_extradata(FFV1Context *f) ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8); put_symbol(c, state, f->version, 0); - if (f->version > 2) { + if (f->version > 1) { if (f->version == 3) f->minor_version = 2; put_symbol(c, state, f->minor_version, 0); } put_symbol(c, state, f->ac, 0); - if (f->ac > 1) + if (f->ac == AC_RANGE_CUSTOM_TAB) for (i = 1; i < 256; i++) put_symbol(c, state, f->state_transition[i] - c->one_state[i], 1); @@ -566,28 +540,50 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) s->version = 0; - if ((avctx->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) || - avctx->slices > 1) - s->version = FFMAX(s->version, 2); - - if (avctx->level == 3) { - s->version = 3; + switch (avctx->level) { + case 3: + break; + case 2: + av_log(avctx, AV_LOG_ERROR, + "Version 2 had been deemed non-standard and deprecated " + "the support for it had been removed\n"); + return AVERROR(ENOSYS); + case 1: + case 0: + if (avctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) { + av_log(avctx, AV_LOG_ERROR, + "Multiple pass encoding requires version 3.\n"); + return AVERROR(ENOSYS); + } + if (avctx->slices > 1) { + av_log(avctx, AV_LOG_ERROR, + "Multiple slices support requires version 3.\n"); + return AVERROR(ENOSYS); + } + break; + case FF_LEVEL_UNKNOWN: + if ((avctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) || + avctx->slices > 1) + s->version = 3; + else + s->version = 0; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Version %d not supported\n", + avctx->level); + return AVERROR(ENOSYS); } if (s->ec < 0) { s->ec = (s->version >= 3); } - if (s->version >= 2 && - avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(avctx, AV_LOG_ERROR, - "Version %d requested, please set -strict experimental in " - "order to enable it\n", - s->version); - return AVERROR(ENOSYS); - } - - s->ac = avctx->coder_type > 0 ? 2 : 0; +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type != -1) + s->ac = avctx->coder_type > 0 ? AC_RANGE_CUSTOM_TAB : AC_GOLOMB_RICE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->plane_count = 3; switch (avctx->pix_fmt) { @@ -615,16 +611,10 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "bits_per_raw_sample invalid\n"); return AVERROR_INVALIDDATA; } - if (!s->ac && avctx->coder_type == -1) { + if (s->ac == AC_GOLOMB_RICE) { av_log(avctx, AV_LOG_INFO, - "bits_per_raw_sample > 8, forcing coder 1\n"); - s->ac = 2; - } - if (!s->ac) { - av_log( - avctx, AV_LOG_ERROR, - "bits_per_raw_sample of more than 8 needs -coder 1 currently\n"); - return AVERROR_INVALIDDATA; + "bits_per_raw_sample > 8, forcing range coder\n"); + s->ac = AC_RANGE_CUSTOM_TAB; } s->version = FFMAX(s->version, 1); case AV_PIX_FMT_GRAY8: @@ -672,14 +662,20 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) avctx, AV_LOG_WARNING, "Storing alpha plane, this will require a recent FFV1 decoder to playback!\n"); } +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->context_model) + s->context_model = avctx->context_model; if (avctx->context_model > 1U) { av_log(avctx, AV_LOG_ERROR, "Invalid context model %d, valid values are 0 and 1\n", avctx->context_model); return AVERROR(EINVAL); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (s->ac > 1) + if (s->ac == AC_RANGE_CUSTOM_TAB) for (i = 1; i < 256; i++) s->state_transition[i] = ffv1_ver2_state[i]; @@ -707,25 +703,25 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) } s->context_count[0] = (11 * 11 * 11 + 1) / 2; s->context_count[1] = (11 * 11 * 5 * 5 * 5 + 1) / 2; - memcpy(s->quant_table, s->quant_tables[avctx->context_model], + memcpy(s->quant_table, s->quant_tables[s->context_model], sizeof(s->quant_table)); for (i = 0; i < s->plane_count; i++) { PlaneContext *const p = &s->plane[i]; memcpy(p->quant_table, s->quant_table, sizeof(p->quant_table)); - p->quant_table_index = avctx->context_model; + p->quant_table_index = s->context_model; p->context_count = s->context_count[p->quant_table_index]; } if ((ret = ffv1_allocate_initial_states(s)) < 0) return ret; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!s->transparency) s->plane_count = 2; @@ -735,7 +731,7 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) s->picture_number = 0; - if (avctx->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) { + if (avctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) { for (i = 0; i < s->quant_table_count; i++) { s->rc_stat2[i] = av_mallocz(s->context_count[i] * sizeof(*s->rc_stat2[i])); @@ -749,7 +745,7 @@ static av_cold int ffv1_encode_init(AVCodecContext *avctx) int gob_count = 0; char *next; - av_assert0(s->version >= 2); + av_assert0(s->version > 2); for (;; ) { for (j = 0; j < 256; j++) @@ -829,7 +825,7 @@ slices_ok: return ret; #define STATS_OUT_SIZE 1024 * 1024 * 6 - if (avctx->flags & CODEC_FLAG_PASS1) { + if (avctx->flags & AV_CODEC_FLAG_PASS1) { avctx->stats_out = av_mallocz(STATS_OUT_SIZE); for (i = 0; i < s->quant_table_count; i++) for (j = 0; j < s->slice_count; j++) { @@ -861,14 +857,14 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs) 0); for (j = 0; j < f->plane_count; j++) { put_symbol(c, state, f->plane[j].quant_table_index, 0); - av_assert0(f->plane[j].quant_table_index == f->avctx->context_model); + av_assert0(f->plane[j].quant_table_index == f->context_model); } - if (!f->avctx->coded_frame->interlaced_frame) + if (!f->frame->interlaced_frame) put_symbol(c, state, 3, 0); else - put_symbol(c, state, 1 + !f->avctx->coded_frame->top_field_first, 0); - put_symbol(c, state, f->avctx->coded_frame->sample_aspect_ratio.num, 0); - put_symbol(c, state, f->avctx->coded_frame->sample_aspect_ratio.den, 0); + put_symbol(c, state, 1 + !f->frame->top_field_first, 0); + put_symbol(c, state, f->frame->sample_aspect_ratio.num, 0); + put_symbol(c, state, f->frame->sample_aspect_ratio.den, 0); } static int encode_slice(AVCodecContext *c, void *arg) @@ -884,12 +880,12 @@ static int encode_slice(AVCodecContext *c, void *arg) ? (f->bits_per_raw_sample > 8) + 1 : 4; - if (c->coded_frame->key_frame) + if (f->key_frame) ffv1_clear_slice_state(f, fs); if (f->version > 2) { encode_slice_header(f, fs); } - if (!fs->ac) { + if (fs->ac == AC_GOLOMB_RICE) { if (f->version > 2) put_rac(&fs->c, (uint8_t[]) { 129 }, 0); fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate( &fs->c) : 0; @@ -898,8 +894,8 @@ static int encode_slice(AVCodecContext *c, void *arg) } if (f->colorspace == 0) { - const int chroma_width = -((-width) >> f->chroma_h_shift); - const int chroma_height = -((-height) >> f->chroma_v_shift); + const int chroma_width = AV_CEIL_RSHIFT(width, f->chroma_h_shift); + const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift); const int cx = x >> f->chroma_h_shift; const int cy = y >> f->chroma_v_shift; @@ -916,9 +912,9 @@ static int encode_slice(AVCodecContext *c, void *arg) encode_plane(fs, p->data[3] + ps * x + y * p->linesize[3], width, height, p->linesize[3], 2); } else { - uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0], - p->data[1] + ps * x + y * p->linesize[1], - p->data[2] + ps * x + y * p->linesize[2] }; + const uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0], + p->data[1] + ps * x + y * p->linesize[1], + p->data[2] + ps * x + y * p->linesize[2] }; encode_rgb_frame(fs, planes, width, height, p->linesize); } emms_c(); @@ -931,7 +927,6 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { FFV1Context *f = avctx->priv_data; RangeCoder *const c = &f->slice_context[0]->c; - AVFrame *const p = avctx->coded_frame; int used_count = 0; uint8_t keystate = 128; uint8_t *buf_p; @@ -941,7 +936,7 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if ((ret = ff_alloc_packet(pkt, avctx->width * avctx->height * ((8 * 2 + 1 + 1) * 4) / 8 + - FF_MIN_BUFFER_SIZE)) < 0) { + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } @@ -951,15 +946,15 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) { put_rac(c, &keystate, 1); - p->key_frame = 1; + f->key_frame = 1; f->gob_count++; write_header(f); } else { put_rac(c, &keystate, 0); - p->key_frame = 0; + f->key_frame = 0; } - if (f->ac > 1) { + if (f->ac == AC_RANGE_CUSTOM_TAB) { int i; for (i = 1; i < 256; i++) { c->one_state[i] = f->state_transition[i]; @@ -982,7 +977,7 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, FFV1Context *fs = f->slice_context[i]; int bytes; - if (fs->ac) { + if (fs->ac != AC_GOLOMB_RICE) { uint8_t state = 129; put_rac(&fs->c, &state, 0); bytes = ff_rac_terminate(&fs->c); @@ -1007,7 +1002,7 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, buf_p += bytes; } - if ((avctx->flags & CODEC_FLAG_PASS1) && (f->picture_number & 31) == 0) { + if ((avctx->flags & AV_CODEC_FLAG_PASS1) && (f->picture_number & 31) == 0) { int j, k, m; char *p = avctx->stats_out; char *end = p + STATS_OUT_SIZE; @@ -1047,12 +1042,18 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } } snprintf(p, end - p, "%d\n", f->gob_count); - } else if (avctx->flags & CODEC_FLAG_PASS1) + } else if (avctx->flags & AV_CODEC_FLAG_PASS1) avctx->stats_out[0] = '\0'; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->key_frame = f->key_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + f->picture_number++; pkt->size = buf_p - pkt->data; - pkt->flags |= AV_PKT_FLAG_KEY * p->key_frame; + pkt->flags |= AV_PKT_FLAG_KEY * f->key_frame; *got_packet = 1; return 0; @@ -1060,7 +1061,6 @@ static int ffv1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int ffv1_encode_close(AVCodecContext *avctx) { - av_frame_free(&avctx->coded_frame); ffv1_close(avctx); return 0; } @@ -1070,6 +1070,17 @@ static av_cold int ffv1_encode_close(AVCodecContext *avctx) static const AVOption options[] = { { "slicecrc", "Protect slices with CRCs", OFFSET(ec), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "coder", "Coder type", OFFSET(ac), AV_OPT_TYPE_INT, + { .i64 = AC_GOLOMB_RICE }, 0, 2, VE, "coder" }, + { "rice", "Golomb rice", 0, AV_OPT_TYPE_CONST, + { .i64 = AC_GOLOMB_RICE }, INT_MIN, INT_MAX, VE, "coder" }, + { "range_def", "Range with default table", 0, AV_OPT_TYPE_CONST, + { .i64 = AC_RANGE_DEFAULT_TAB }, INT_MIN, INT_MAX, VE, "coder" }, + { "range_tab", "Range with custom table", 0, AV_OPT_TYPE_CONST, + { .i64 = AC_RANGE_CUSTOM_TAB }, INT_MIN, INT_MAX, VE, "coder" }, + { "context", "Context model", OFFSET(context_model), AV_OPT_TYPE_INT, + { .i64 = 0 }, 0, 1, VE }, + { NULL } }; @@ -1080,10 +1091,12 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; +#if FF_API_CODER_TYPE static const AVCodecDefault ffv1_defaults[] = { { "coder", "-1" }, { NULL }, }; +#endif AVCodec ff_ffv1_encoder = { .name = "ffv1", @@ -1094,7 +1107,7 @@ AVCodec ff_ffv1_encoder = { .init = ffv1_encode_init, .encode2 = ffv1_encode_frame, .close = ffv1_encode_close, - .capabilities = CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, @@ -1108,6 +1121,8 @@ AVCodec ff_ffv1_encoder = { AV_PIX_FMT_NONE }, +#if FF_API_CODER_TYPE .defaults = ffv1_defaults, +#endif .priv_class = &class, }; diff --git a/libavcodec/fic.c b/libavcodec/fic.c index 8512ef3..b1286eb 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -454,5 +454,5 @@ AVCodec ff_fic_decoder = { .init = fic_decode_init, .decode = fic_decode_frame, .close = fic_decode_close, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, }; diff --git a/libavcodec/flac.c b/libavcodec/flac.c index ec0cb6f..3e51fde 100644 --- a/libavcodec/flac.c +++ b/libavcodec/flac.c @@ -166,7 +166,7 @@ int ff_flac_get_max_frame_size(int blocksize, int ch, int bps) return count; } -int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, +int ff_flac_is_extradata_valid(AVCodecContext *avctx, enum FLACExtradataFormat *format, uint8_t **streaminfo_start) { @@ -201,7 +201,7 @@ void ff_flac_set_channel_layout(AVCodecContext *avctx) avctx->channel_layout = 0; } -void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, +void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, const uint8_t *buffer) { GetBitContext gb; @@ -236,3 +236,18 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo * skip_bits_long(&gb, 64); /* md5 sum */ skip_bits_long(&gb, 64); /* md5 sum */ } + +#if LIBAVCODEC_VERSION_MAJOR < 57 +void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer) +{ + ff_flac_parse_streaminfo(avctx, s, buffer); +} + +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start) +{ + return ff_flac_is_extradata_valid(avctx, format, streaminfo_start); +} +#endif diff --git a/libavcodec/flac.h b/libavcodec/flac.h index 9baa330..3229682 100644 --- a/libavcodec/flac.h +++ b/libavcodec/flac.h @@ -96,8 +96,16 @@ typedef struct FLACFrameInfo { * @param[out] s where parsed information is stored * @param[in] buffer pointer to start of 34-byte streaminfo data */ +void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer); + +#if LIBAVCODEC_VERSION_MAJOR < 57 void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, const uint8_t *buffer); +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start); +#endif /** * Validate the FLAC extradata. @@ -106,9 +114,9 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo * * @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data. * @return 1 if valid, 0 if not valid. */ -int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, - enum FLACExtradataFormat *format, - uint8_t **streaminfo_start); +int ff_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start); /** * Calculate an estimate for the maximum frame size based on verbatim mode. diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index bf2c118..70b9a65 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -565,6 +565,15 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, nb_desired * FLAC_AVG_FRAME_SIZE); } + if (!av_fifo_space(fpc->fifo_buf) && + av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > + fpc->nb_headers_buffered * 10) { + /* There is less than one valid flac header buffered for 10 headers + * buffered. Therefore the fifo is most likely filled with invalid + * data and the input is not a flac file. */ + goto handle_error; + } + /* Fill the buffer. */ if (av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + av_fifo_size(fpc->fifo_buf)) < 0) { diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 9ca55cc..7af71f3 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -33,8 +33,6 @@ #include -#include "libavutil/channel_layout.h" -#include "libavutil/crc.h" #include "avcodec.h" #include "internal.h" #include "get_bits.h" @@ -99,11 +97,11 @@ static av_cold int flac_decode_init(AVCodecContext *avctx) if (!avctx->extradata) return 0; - if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo)) + if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo)) return AVERROR_INVALIDDATA; /* initialize based on the demuxer-supplied streamdata header */ - avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo); + ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo); ret = allocate_buffers(s); if (ret < 0) return ret; @@ -161,7 +159,7 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) metadata_size != FLAC_STREAMINFO_SIZE) { return AVERROR_INVALIDDATA; } - avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]); + ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]); ret = allocate_buffers(s); if (ret < 0) return ret; @@ -564,7 +562,7 @@ AVCodec ff_flac_decoder = { .init = flac_decode_init, .close = flac_decode_close, .decode = flac_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32, diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 1160da2..67f899f 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -23,9 +23,9 @@ #include "libavutil/intmath.h" #include "libavutil/md5.h" #include "libavutil/opt.h" + #include "avcodec.h" #include "bswapdsp.h" -#include "get_bits.h" #include "golomb.h" #include "internal.h" #include "lpc.h" @@ -67,6 +67,7 @@ typedef struct RiceContext { enum CodingMode coding_mode; int porder; int params[MAX_PARTITIONS]; + uint32_t udata[FLAC_MAX_BLOCKSIZE]; } RiceContext; typedef struct FlacSubframe { @@ -304,8 +305,10 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON})[level]; - s->options.min_prediction_order = ((int[]){ 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})[level]; - s->options.max_prediction_order = ((int[]){ 3, 4, 4, 6, 8, 8, 8, 8, 12, 12, 12, 32, 32})[level]; + if (s->options.min_prediction_order < 0) + s->options.min_prediction_order = ((int[]){ 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})[level]; + if (s->options.max_prediction_order < 0) + s->options.max_prediction_order = ((int[]){ 3, 4, 4, 6, 8, 8, 8, 8, 12, 12, 12, 32, 32})[level]; if (s->options.prediction_order_method < 0) s->options.prediction_order_method = ((int[]){ ORDER_METHOD_EST, ORDER_METHOD_EST, ORDER_METHOD_EST, @@ -324,14 +327,15 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) if (s->options.max_partition_order < 0) s->options.max_partition_order = ((int[]){ 2, 2, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8})[level]; - if (s->options.lpc_type == FF_LPC_TYPE_NONE) { - s->options.min_prediction_order = 0; - } else if (avctx->min_prediction_order >= 0) { +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->min_prediction_order >= 0) { if (s->options.lpc_type == FF_LPC_TYPE_FIXED) { if (avctx->min_prediction_order > MAX_FIXED_ORDER) { - av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n", - avctx->min_prediction_order); - return -1; + av_log(avctx, AV_LOG_WARNING, + "invalid min prediction order %d, clamped to %d\n", + avctx->min_prediction_order, MAX_FIXED_ORDER); + avctx->min_prediction_order = MAX_FIXED_ORDER; } } else if (avctx->min_prediction_order < MIN_LPC_ORDER || avctx->min_prediction_order > MAX_LPC_ORDER) { @@ -341,14 +345,13 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) } s->options.min_prediction_order = avctx->min_prediction_order; } - if (s->options.lpc_type == FF_LPC_TYPE_NONE) { - s->options.max_prediction_order = 0; - } else if (avctx->max_prediction_order >= 0) { + if (avctx->max_prediction_order >= 0) { if (s->options.lpc_type == FF_LPC_TYPE_FIXED) { if (avctx->max_prediction_order > MAX_FIXED_ORDER) { - av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n", - avctx->max_prediction_order); - return -1; + av_log(avctx, AV_LOG_WARNING, + "invalid max prediction order %d, clamped to %d\n", + avctx->max_prediction_order, MAX_FIXED_ORDER); + avctx->max_prediction_order = MAX_FIXED_ORDER; } } else if (avctx->max_prediction_order < MIN_LPC_ORDER || avctx->max_prediction_order > MAX_LPC_ORDER) { @@ -358,6 +361,26 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) } s->options.max_prediction_order = avctx->max_prediction_order; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (s->options.lpc_type == FF_LPC_TYPE_NONE) { + s->options.min_prediction_order = 0; + s->options.max_prediction_order = 0; + } else if (s->options.lpc_type == FF_LPC_TYPE_FIXED) { + if (s->options.min_prediction_order > MAX_FIXED_ORDER) { + av_log(avctx, AV_LOG_WARNING, + "invalid min prediction order %d, clamped to %d\n", + s->options.min_prediction_order, MAX_FIXED_ORDER); + s->options.min_prediction_order = MAX_FIXED_ORDER; + } + if (s->options.max_prediction_order > MAX_FIXED_ORDER) { + av_log(avctx, AV_LOG_WARNING, + "invalid max prediction order %d, clamped to %d\n", + s->options.max_prediction_order, MAX_FIXED_ORDER); + s->options.max_prediction_order = MAX_FIXED_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); @@ -616,8 +639,7 @@ static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, uint64_t bits[MAX_PARTITION_ORDER+1]; int opt_porder; RiceContext tmp_rc; - uint32_t *udata; - uint64_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS]; + uint64_t sums[MAX_PARTITION_ORDER + 1][MAX_PARTITIONS] = { { 0 } }; assert(pmin >= 0 && pmin <= MAX_PARTITION_ORDER); assert(pmax >= 0 && pmax <= MAX_PARTITION_ORDER); @@ -625,11 +647,10 @@ static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, tmp_rc.coding_mode = rc->coding_mode; - udata = av_malloc(n * sizeof(uint32_t)); for (i = 0; i < n; i++) - udata[i] = (2*data[i]) ^ (data[i]>>31); + rc->udata[i] = (2 * data[i]) ^ (data[i] >> 31); - calc_sums(pmin, pmax, udata, n, pred_order, sums); + calc_sums(pmin, pmax, rc->udata, n, pred_order, sums); opt_porder = pmin; bits[pmin] = UINT32_MAX; @@ -641,7 +662,6 @@ static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, } } - av_freep(&udata); return bits[opt_porder]; } @@ -1216,7 +1236,13 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_md5_final(s->md5ctx, s->md5sum); write_streaminfo(s, avctx->extradata); +#if FF_API_SIDEDATA_ONLY_PKT +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->side_data_only_packets && !s->flushed) { +FF_ENABLE_DEPRECATION_WARNINGS +#else + if (!s->flushed) { +#endif uint8_t *side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, avctx->extradata_size); if (!side_data) @@ -1326,6 +1352,9 @@ static const AVOption options[] = { { "left_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_LEFT_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, { "right_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_RIGHT_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, { "mid_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_MID_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ "min_prediction_order", NULL, offsetof(FlacEncodeContext, options.min_prediction_order), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_LPC_ORDER, FLAGS }, +{ "max_prediction_order", NULL, offsetof(FlacEncodeContext, options.max_prediction_order), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_LPC_ORDER, FLAGS }, + { NULL }, }; @@ -1345,7 +1374,7 @@ AVCodec ff_flac_encoder = { .init = flac_encode_init, .encode2 = flac_encode_frame, .close = flac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/flashsv.c b/libavcodec/flashsv.c index de7979c..2cf8f3f 100644 --- a/libavcodec/flashsv.c +++ b/libavcodec/flashsv.c @@ -339,15 +339,17 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); if (s->is_keyframe) { int err; + int nb_blocks = (v_blocks + !!v_part) * + (h_blocks + !!h_part) * sizeof(s->blocks[0]); if ((err = av_reallocp(&s->keyframedata, avpkt->size)) < 0) return err; memcpy(s->keyframedata, avpkt->data, avpkt->size); - if ((err = av_reallocp(&s->blocks, (v_blocks + !!v_part) * - (h_blocks + !!h_part) * sizeof(s->blocks[0]))) < 0) + if ((err = av_reallocp(&s->blocks, nb_blocks)) < 0) return err; + memset(s->blocks, 0, nb_blocks); } - av_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", + ff_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", s->image_width, s->image_height, s->block_width, s->block_height, h_blocks, v_blocks, h_part, v_part); @@ -493,7 +495,7 @@ AVCodec ff_flashsv_decoder = { .init = flashsv_decode_init, .close = flashsv_decode_end, .decode = flashsv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV_DECODER */ @@ -556,7 +558,7 @@ AVCodec ff_flashsv2_decoder = { .init = flashsv2_decode_init, .close = flashsv2_decode_end, .decode = flashsv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV2_DECODER */ diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index 71c81bd..7e14e47 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -98,8 +98,6 @@ static av_cold int flashsv_encode_end(AVCodecContext *avctx) av_free(s->previous_frame); av_free(s->tmpblock); - av_frame_free(&avctx->coded_frame); - return 0; } @@ -131,12 +129,6 @@ static av_cold int flashsv_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - flashsv_encode_end(avctx); - return AVERROR(ENOMEM); - } - return 0; } @@ -197,7 +189,7 @@ static int encode_bitstream(FlashSVContext *s, const AVFrame *p, uint8_t *buf, bytestream_put_be16(&ptr, zsize); buf_pos += zsize + 2; - av_dlog(s->avctx, "buf_pos = %d\n", buf_pos); + ff_dlog(s->avctx, "buf_pos = %d\n", buf_pos); } else { pred_blocks++; bytestream_put_be16(&ptr, 0); @@ -266,16 +258,24 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, //mark the frame type so the muxer can mux it correctly if (I_frame) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->last_key_frame = avctx->frame_number; - av_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number); + ff_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number); } else { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; avctx->coded_frame->key_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } - if (avctx->coded_frame->key_frame) + if (I_frame) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c index 68f45b4..13e6ae4 100644 --- a/libavcodec/flicvideo.c +++ b/libavcodec/flicvideo.c @@ -1,6 +1,6 @@ /* * FLI/FLC Animation Video Decoder - * Copyright (C) 2003, 2004 the ffmpeg project + * Copyright (C) 2003, 2004 The FFmpeg project * * This file is part of Libav. * @@ -115,7 +115,7 @@ static av_cold int flic_decode_init(AVCodecContext *avctx) case 8 : avctx->pix_fmt = AV_PIX_FMT_PAL8; break; case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break; case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break; - case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */ + case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but no files to test with */ av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n"); return AVERROR_PATCHWELCOME; default : @@ -493,7 +493,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, /* For some reason, it seems that non-palettized flics do * include one of these chunks in their first frame. * Why I do not know, it seems rather extraneous. */ - av_dlog(avctx, + ff_dlog(avctx, "Unexpected Palette chunk %d in non-palettized FLC\n", chunk_type); bytestream2_skip(&g2, chunk_size - 6); @@ -725,7 +725,7 @@ static int flic_decode_frame(AVCodecContext *avctx, /* Should not get here, ever as the pix_fmt is processed */ /* in flic_decode_init and the above if should deal with */ - /* the finite set of possibilites allowable by here. */ + /* the finite set of possibilities allowable by here. */ /* But in case we do, just error out. */ av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n"); return AVERROR_BUG; @@ -750,5 +750,5 @@ AVCodec ff_flic_decoder = { .init = flic_decode_init, .close = flic_decode_end, .decode = flic_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/flv.h b/libavcodec/flv.h index 3d9a2d5..801e357 100644 --- a/libavcodec/flv.h +++ b/libavcodec/flv.h @@ -1,5 +1,6 @@ /* * FLV specific private header. + * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -20,12 +21,13 @@ #ifndef AVCODEC_FLV_H #define AVCODEC_FLV_H -#include "mpegvideo.h" #include "get_bits.h" +#include "mpegvideo.h" #include "put_bits.h" -void ff_flv_encode_picture_header(MpegEncContext * s, int picture_number); -void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last); +void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, + int last); int ff_flv_decode_picture_header(MpegEncContext *s); void ff_flv2_decode_ac_esc(GetBitContext *gb, int *level, int *run, int *last); diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index 3405058..f2d4929 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -1,5 +1,6 @@ /* * FLV decoding. + * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -17,21 +18,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "mpegvideo.h" -#include "h263.h" -#include "flv.h" #include "libavutil/imgutils.h" +#include "flv.h" +#include "h263.h" +#include "mpegvideo.h" +#include "mpegvideodata.h" + void ff_flv2_decode_ac_esc(GetBitContext *gb, int *level, int *run, int *last) { int is11 = get_bits1(gb); *last = get_bits1(gb); *run = get_bits(gb, 6); - if (is11) { + if (is11) *level = get_sbits(gb, 11); - } else { + else *level = get_sbits(gb, 7); - } } int ff_flv_decode_picture_header(MpegEncContext *s) @@ -127,9 +129,7 @@ AVCodec ff_flv_decoder = { .init = ff_h263_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, - .pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE - }, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 4d5eb1d..f7c72c5 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -1,5 +1,6 @@ /* * FLV Encoding specific code. + * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -17,58 +18,64 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "mpegvideo.h" -#include "h263.h" #include "flv.h" +#include "h263.h" +#include "h263data.h" +#include "mpegvideo.h" +#include "mpegvideodata.h" -void ff_flv_encode_picture_header(MpegEncContext * s, int picture_number) +void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number) { - int format; + int format; - avpriv_align_put_bits(&s->pb); + avpriv_align_put_bits(&s->pb); - put_bits(&s->pb, 17, 1); - put_bits(&s->pb, 5, (s->h263_flv-1)); /* 0: h263 escape codes 1: 11-bit escape codes */ - put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->time_base.num) / //FIXME use timestamp - s->avctx->time_base.den) & 0xff); /* TemporalReference */ - if (s->width == 352 && s->height == 288) + put_bits(&s->pb, 17, 1); + /* 0: H.263 escape codes 1: 11-bit escape codes */ + put_bits(&s->pb, 5, (s->h263_flv - 1)); + 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) + else if (s->width == 176 && s->height == 144) format = 3; - else if (s->width == 128 && s->height == 96) + else if (s->width == 128 && s->height == 96) format = 4; - else if (s->width == 320 && s->height == 240) + else if (s->width == 320 && s->height == 240) format = 5; - else if (s->width == 160 && s->height == 120) + 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) { + 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) { + } else if (format == 1) { put_bits(&s->pb, 16, s->width); put_bits(&s->pb, 16, s->height); - } - put_bits(&s->pb, 2, s->pict_type == AV_PICTURE_TYPE_P); /* PictureType */ - put_bits(&s->pb, 1, 1); /* DeblockingFlag: on */ - put_bits(&s->pb, 5, s->qscale); /* Quantizer */ - put_bits(&s->pb, 1, 0); /* ExtraInformation */ + } + put_bits(&s->pb, 2, s->pict_type == AV_PICTURE_TYPE_P); /* PictureType */ + put_bits(&s->pb, 1, 1); /* DeblockingFlag: on */ + put_bits(&s->pb, 5, s->qscale); /* Quantizer */ + put_bits(&s->pb, 1, 0); /* ExtraInformation */ - if(s->h263_aic){ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_aic_dc_scale_table; - }else{ - s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; - } + if (s->h263_aic) { + s->y_dc_scale_table = + s->c_dc_scale_table = ff_aic_dc_scale_table; + } else { + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg1_dc_scale_table; + } } -void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last){ - if(level < 64) { // 7-bit level +void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, + int run, int last) +{ + if (level < 64) { // 7-bit level put_bits(pb, 1, 0); put_bits(pb, 1, last); put_bits(pb, 6, run); @@ -84,7 +91,12 @@ void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, in } } -FF_MPV_GENERIC_CLASS(flv) +static const AVClass flv_class = { + .class_name = "flv encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_flv_encoder = { .name = "flv", @@ -95,6 +107,7 @@ AVCodec ff_flv_encoder = { .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE}, .priv_class = &flv_class, }; diff --git a/libavcodec/fmtconvert.c b/libavcodec/fmtconvert.c index 63f62c3..f94d438 100644 --- a/libavcodec/fmtconvert.c +++ b/libavcodec/fmtconvert.c @@ -32,70 +32,35 @@ static void int32_to_float_fmul_scalar_c(float *dst, const int32_t *src, dst[i] = src[i] * mul; } -static void int32_to_float_fmul_array8_c(FmtConvertContext *c, float *dst, - const int32_t *src, const float *mul, - int len) +static void int32_to_float_c(float *dst, const int32_t *src, intptr_t len) { int i; - for (i = 0; i < len; i += 8) - c->int32_to_float_fmul_scalar(&dst[i], &src[i], *mul++, 8); -} -static av_always_inline int float_to_int16_one(const float *src){ - return av_clip_int16(lrintf(*src)); + for (i = 0; i < len; i++) + dst[i] = (float)src[i]; } -static void float_to_int16_c(int16_t *dst, const float *src, long len) +static void int32_to_float_fmul_array8_c(FmtConvertContext *c, float *dst, + const int32_t *src, const float *mul, + int len) { int i; - for(i=0; iint32_to_float_fmul_scalar(&dst[i], &src[i], *mul++, 8); } av_cold void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx) { + c->int32_to_float = int32_to_float_c; c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_c; c->int32_to_float_fmul_array8 = int32_to_float_fmul_array8_c; - c->float_to_int16 = float_to_int16_c; - c->float_to_int16_interleave = float_to_int16_interleave_c; - c->float_interleave = ff_float_interleave_c; - if (ARCH_ARM) ff_fmt_convert_init_arm(c, avctx); - if (ARCH_PPC) ff_fmt_convert_init_ppc(c, avctx); - if (ARCH_X86) ff_fmt_convert_init_x86(c, avctx); + if (ARCH_AARCH64) + ff_fmt_convert_init_aarch64(c, avctx); + if (ARCH_ARM) + ff_fmt_convert_init_arm(c, avctx); + if (ARCH_PPC) + ff_fmt_convert_init_ppc(c, avctx); + if (ARCH_X86) + ff_fmt_convert_init_x86(c, avctx); } diff --git a/libavcodec/fmtconvert.h b/libavcodec/fmtconvert.h index bd833ef..b2c2356 100644 --- a/libavcodec/fmtconvert.h +++ b/libavcodec/fmtconvert.h @@ -37,6 +37,16 @@ typedef struct FmtConvertContext { */ void (*int32_to_float_fmul_scalar)(float *dst, const int32_t *src, float mul, int len); + /** + * Convert an array of int32_t to float. + * @param dst destination array of float. + * constraints: 32-byte aligned + * @param src source array of int32_t. + * constraints: 32-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 8 + */ + void (*int32_to_float)(float *dst, const int32_t *src, intptr_t len); /** * Convert an array of int32_t to float and multiply by a float value from another array, @@ -54,58 +64,11 @@ typedef struct FmtConvertContext { float *dst, const int32_t *src, const float *mul, int len); - /** - * Convert an array of float to an array of int16_t. - * - * Convert floats from in the range [-32768.0,32767.0] to ints - * without rescaling - * - * @param dst destination array of int16_t. - * constraints: 16-byte aligned - * @param src source array of float. - * constraints: 16-byte aligned - * @param len number of elements to convert. - * constraints: multiple of 8 - */ - void (*float_to_int16)(int16_t *dst, const float *src, long len); - - /** - * Convert multiple arrays of float to an interleaved array of int16_t. - * - * Convert floats from in the range [-32768.0,32767.0] to ints - * without rescaling - * - * @param dst destination array of interleaved int16_t. - * constraints: 16-byte aligned - * @param src source array of float arrays, one for each channel. - * constraints: 16-byte aligned - * @param len number of elements to convert. - * constraints: multiple of 8 - * @param channels number of channels - */ - void (*float_to_int16_interleave)(int16_t *dst, const float **src, - long len, int channels); - - /** - * Convert multiple arrays of float to an array of interleaved float. - * - * @param dst destination array of interleaved float. - * constraints: 16-byte aligned - * @param src source array of float arrays, one for each channel. - * constraints: 16-byte aligned - * @param len number of elements to convert. - * constraints: multiple of 8 - * @param channels number of channels - */ - void (*float_interleave)(float *dst, const float **src, unsigned int len, - int channels); } FmtConvertContext; -void ff_float_interleave_c(float *dst, const float **src, unsigned int len, - int channels); - void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx); +void ff_fmt_convert_init_aarch64(FmtConvertContext *c, AVCodecContext *avctx); void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx); void ff_fmt_convert_init_ppc(FmtConvertContext *c, AVCodecContext *avctx); void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx); diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c index 4b4b02c..eb61c70 100644 --- a/libavcodec/fraps.c +++ b/libavcodec/fraps.c @@ -39,6 +39,7 @@ #include "internal.h" #define FPS_TAG MKTAG('F', 'P', 'S', 'x') +#define VLC_BITS 11 /** * local variable storage @@ -100,7 +101,8 @@ static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, for (i = 0; i < 256; i++) nodes[i].count = bytestream_get_le32(&src); size -= 1024; - if ((ret = ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp, + if ((ret = ff_huff_build_tree(s->avctx, &vlc, 256, VLC_BITS, + nodes, huff_cmp, FF_HUFFMAN_FLAG_ZERO_COUNT)) < 0) return ret; /* we have built Huffman table and are ready to decode plane */ @@ -112,7 +114,7 @@ static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, init_get_bits(&gb, s->tmpbuf, size * 8); for (j = 0; j < h; j++) { for (i = 0; i < w*step; i += step) { - dst[i] = get_vlc2(&gb, vlc.table, 9, 3); + dst[i] = get_vlc2(&gb, vlc.table, VLC_BITS, 3); /* lines are stored as deltas between previous lines * and we need to add 0x80 to the first lines of chroma planes */ @@ -382,5 +384,5 @@ AVCodec ff_fraps_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/frwu.c b/libavcodec/frwu.c index 568b94f..61cd315 100644 --- a/libavcodec/frwu.c +++ b/libavcodec/frwu.c @@ -101,5 +101,5 @@ AVCodec ff_frwu_decoder = { .id = AV_CODEC_ID_FRWU, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 33934f1..a89610d 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -1,6 +1,7 @@ /* - * Go2Webinar decoder + * Go2Webinar / Go2Meeting decoder * Copyright (c) 2012 Konstantin Shishkov + * Copyright (c) 2013 Maxim Poliakovski * * This file is part of Libav. * @@ -21,21 +22,27 @@ /** * @file - * Go2Webinar decoder + * Go2Webinar / Go2Meeting decoder */ #include #include #include "libavutil/intreadwrite.h" + #include "avcodec.h" #include "blockdsp.h" #include "bytestream.h" -#include "idctdsp.h" +#include "elsdec.h" #include "get_bits.h" +#include "idctdsp.h" #include "internal.h" +#include "jpegtables.h" #include "mjpeg.h" +#define EPIC_PIX_STACK_SIZE 1024 +#define EPIC_PIX_STACK_MAX (EPIC_PIX_STACK_SIZE - 1) + enum ChunkType { DISPLAY_INFO = 0xC8, TILE_DATA, @@ -72,6 +79,42 @@ static const uint8_t chroma_quant[64] = { 50, 50, 50, 50, 50, 50, 50, 50, }; +typedef struct ePICPixListElem { + struct ePICPixListElem *next; + uint32_t pixel; + uint8_t rung; +} ePICPixListElem; + +typedef struct ePICPixHashElem { + uint32_t pix_id; + struct ePICPixListElem *list; +} ePICPixHashElem; + +#define EPIC_HASH_SIZE 256 +typedef struct ePICPixHash { + ePICPixHashElem *bucket[EPIC_HASH_SIZE]; + int bucket_size[EPIC_HASH_SIZE]; + int bucket_fill[EPIC_HASH_SIZE]; +} ePICPixHash; + +typedef struct ePICContext { + ElsDecCtx els_ctx; + int next_run_pos; + ElsUnsignedRung unsigned_rung; + uint8_t W_flag_rung; + uint8_t N_flag_rung; + uint8_t W_ctx_rung[256]; + uint8_t N_ctx_rung[512]; + uint8_t nw_pred_rung[256]; + uint8_t ne_pred_rung[256]; + uint8_t prev_row_rung[14]; + uint8_t runlen_zeroes[14]; + uint8_t runlen_one; + int stack_pos; + uint32_t stack[EPIC_PIX_STACK_SIZE]; + ePICPixHash hash; +} ePICContext; + typedef struct JPGContext { BlockDSPContext bdsp; IDCTDSPContext idsp; @@ -85,7 +128,9 @@ typedef struct JPGContext { } JPGContext; typedef struct G2MContext { + ePICContext ec; JPGContext jc; + int version; int compression; @@ -99,8 +144,9 @@ typedef struct G2MContext { uint8_t *framebuf; int framebuf_stride, old_width, old_height; - uint8_t *synth_tile, *jpeg_tile; - int tile_stride, old_tile_w, old_tile_h; + uint8_t *synth_tile, *jpeg_tile, *epic_buf, *epic_buf_base; + int tile_stride, epic_buf_stride, old_tile_w, old_tile_h; + int swapuv; uint8_t *kempf_buf, *kempf_flags; @@ -227,11 +273,11 @@ static int jpg_decode_block(JPGContext *c, GetBitContext *gb, return 0; } -static inline void yuv2rgb(uint8_t *out, int Y, int U, int V) +static inline void yuv2rgb(uint8_t *out, int ridx, int Y, int U, int V) { - out[0] = av_clip_uint8(Y + ( 91881 * V + 32768 >> 16)); - out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16)); - out[2] = av_clip_uint8(Y + (116130 * U + 32768 >> 16)); + out[ridx] = av_clip_uint8(Y + (91881 * V + 32768 >> 16)); + out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16)); + out[2 - ridx] = av_clip_uint8(Y + (116130 * U + 32768 >> 16)); } static int jpg_decode_data(JPGContext *c, int width, int height, @@ -245,12 +291,13 @@ static int jpg_decode_data(JPGContext *c, int width, int height, int bx, by; int unesc_size; int ret; + const int ridx = swapuv ? 2 : 0; if ((ret = av_reallocp(&c->buf, - src_size + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) + src_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) return ret; jpg_unescape(src, src_size, c->buf, &unesc_size); - memset(c->buf + unesc_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(c->buf + unesc_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&gb, c->buf, unesc_size * 8); width = FFALIGN(width, 16); @@ -262,7 +309,8 @@ static int jpg_decode_data(JPGContext *c, int width, int height, for (i = 0; i < 3; i++) c->prev_dc[i] = 1024; - bx = by = 0; + bx = + by = 0; c->bdsp.clear_blocks(c->block[0]); for (mb_y = 0; mb_y < mb_h; mb_y++) { for (mb_x = 0; mb_x < mb_w; mb_x++) { @@ -295,9 +343,9 @@ static int jpg_decode_data(JPGContext *c, int width, int height, int Y, U, V; Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8]; - U = c->block[4 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128; - V = c->block[5 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128; - yuv2rgb(out + i * 3, Y, U, V); + U = c->block[4][(i >> 1) + (j >> 1) * 8] - 128; + V = c->block[5][(i >> 1) + (j >> 1) * 8] - 128; + yuv2rgb(out + i * 3, ridx, Y, U, V); } } @@ -314,6 +362,649 @@ static int jpg_decode_data(JPGContext *c, int width, int height, return 0; } +#define LOAD_NEIGHBOURS(x) \ + W = curr_row[(x) - 1]; \ + N = above_row[(x)]; \ + WW = curr_row[(x) - 2]; \ + NW = above_row[(x) - 1]; \ + NE = above_row[(x) + 1]; \ + NN = above2_row[(x)]; \ + NNW = above2_row[(x) - 1]; \ + NWW = above_row[(x) - 2]; \ + NNE = above2_row[(x) + 1] + +#define UPDATE_NEIGHBOURS(x) \ + NNW = NN; \ + NN = NNE; \ + NWW = NW; \ + NW = N; \ + N = NE; \ + NE = above_row[(x) + 1]; \ + NNE = above2_row[(x) + 1] + +#define R_shift 16 +#define G_shift 8 +#define B_shift 0 + +/* improved djb2 hash from http://www.cse.yorku.ca/~oz/hash.html */ +static int djb2_hash(uint32_t key) +{ + uint32_t h = 5381; + + h = (h * 33) ^ ((key >> 24) & 0xFF); // xxx: probably not needed at all + h = (h * 33) ^ ((key >> 16) & 0xFF); + h = (h * 33) ^ ((key >> 8) & 0xFF); + h = (h * 33) ^ (key & 0xFF); + + return h & (EPIC_HASH_SIZE - 1); +} + +static void epic_hash_init(ePICPixHash *hash) +{ + memset(hash, 0, sizeof(*hash)); +} + +static ePICPixHashElem *epic_hash_find(const ePICPixHash *hash, uint32_t key) +{ + int i, idx = djb2_hash(key); + ePICPixHashElem *bucket = hash->bucket[idx]; + + for (i = 0; i < hash->bucket_fill[idx]; i++) + if (bucket[i].pix_id == key) + return &bucket[i]; + + return NULL; +} + +static ePICPixHashElem *epic_hash_add(ePICPixHash *hash, uint32_t key) +{ + ePICPixHashElem *bucket, *ret; + int idx = djb2_hash(key); + + if (hash->bucket_size[idx] > INT_MAX / sizeof(**hash->bucket)) + return NULL; + + if (!(hash->bucket_fill[idx] < hash->bucket_size[idx])) { + int new_size = hash->bucket_size[idx] + 16; + bucket = av_realloc(hash->bucket[idx], new_size * sizeof(*bucket)); + if (!bucket) + return NULL; + hash->bucket[idx] = bucket; + hash->bucket_size[idx] = new_size; + } + + ret = &hash->bucket[idx][hash->bucket_fill[idx]++]; + memset(ret, 0, sizeof(*ret)); + ret->pix_id = key; + return ret; +} + +static int epic_add_pixel_to_cache(ePICPixHash *hash, uint32_t key, uint32_t pix) +{ + ePICPixListElem *new_elem; + ePICPixHashElem *hash_elem = epic_hash_find(hash, key); + + if (!hash_elem) { + if (!(hash_elem = epic_hash_add(hash, key))) + return AVERROR(ENOMEM); + } + + new_elem = av_mallocz(sizeof(*new_elem)); + if (!new_elem) + return AVERROR(ENOMEM); + + new_elem->pixel = pix; + new_elem->next = hash_elem->list; + hash_elem->list = new_elem; + + return 0; +} + +static inline int epic_cache_entries_for_pixel(const ePICPixHash *hash, + uint32_t pix) +{ + ePICPixHashElem *hash_elem = epic_hash_find(hash, pix); + + if (hash_elem != NULL && hash_elem->list != NULL) + return 1; + + return 0; +} + +static void epic_free_pixel_cache(ePICPixHash *hash) +{ + int i, j; + + for (i = 0; i < EPIC_HASH_SIZE; i++) { + for (j = 0; j < hash->bucket_fill[i]; j++) { + ePICPixListElem *list_elem = hash->bucket[i][j].list; + while (list_elem) { + ePICPixListElem *tmp = list_elem->next; + av_free(list_elem); + list_elem = tmp; + } + } + av_freep(&hash->bucket[i]); + hash->bucket_size[i] = + hash->bucket_fill[i] = 0; + } +} + +static inline int is_pixel_on_stack(const ePICContext *dc, uint32_t pix) +{ + int i; + + for (i = 0; i < dc->stack_pos; i++) + if (dc->stack[i] == pix) + break; + + return i != dc->stack_pos; +} + +#define TOSIGNED(val) (((val) >> 1) ^ -((val) & 1)) + +static inline int epic_decode_component_pred(ePICContext *dc, + int N, int W, int NW) +{ + unsigned delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung); + return mid_pred(N, N + W - NW, W) - TOSIGNED(delta); +} + +static uint32_t epic_decode_pixel_pred(ePICContext *dc, int x, int y, + const uint32_t *curr_row, + const uint32_t *above_row) +{ + uint32_t N, W, NW, pred; + unsigned delta; + int GN, GW, GNW, R, G, B; + + if (x && y) { + W = curr_row[x - 1]; + N = above_row[x]; + NW = above_row[x - 1]; + + GN = (N >> G_shift) & 0xFF; + GW = (W >> G_shift) & 0xFF; + GNW = (NW >> G_shift) & 0xFF; + + G = epic_decode_component_pred(dc, GN, GW, GNW); + + R = G + epic_decode_component_pred(dc, + ((N >> R_shift) & 0xFF) - GN, + ((W >> R_shift) & 0xFF) - GW, + ((NW >> R_shift) & 0xFF) - GNW); + + B = G + epic_decode_component_pred(dc, + ((N >> B_shift) & 0xFF) - GN, + ((W >> B_shift) & 0xFF) - GW, + ((NW >> B_shift) & 0xFF) - GNW); + } else { + if (x) + pred = curr_row[x - 1]; + else + pred = above_row[x]; + + delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung); + R = ((pred >> R_shift) & 0xFF) - TOSIGNED(delta); + + delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung); + G = ((pred >> G_shift) & 0xFF) - TOSIGNED(delta); + + delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung); + B = ((pred >> B_shift) & 0xFF) - TOSIGNED(delta); + } + + return (R << R_shift) | (G << G_shift) | (B << B_shift); +} + +static int epic_predict_pixel(ePICContext *dc, uint8_t *rung, + uint32_t *pPix, uint32_t pix) +{ + if (!ff_els_decode_bit(&dc->els_ctx, rung)) { + *pPix = pix; + return 1; + } + dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = pix; + return 0; +} + +static int epic_handle_edges(ePICContext *dc, int x, int y, + const uint32_t *curr_row, + const uint32_t *above_row, uint32_t *pPix) +{ + uint32_t pix; + + if (!x && !y) { /* special case: top-left pixel */ + /* the top-left pixel is coded independently with 3 unsigned numbers */ + *pPix = (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << R_shift) | + (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << G_shift) | + (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << B_shift); + return 1; + } + + if (x) { /* predict from W first */ + pix = curr_row[x - 1]; + if (epic_predict_pixel(dc, &dc->W_flag_rung, pPix, pix)) + return 1; + } + + if (y) { /* then try to predict from N */ + pix = above_row[x]; + if (!dc->stack_pos || dc->stack[0] != pix) { + if (epic_predict_pixel(dc, &dc->N_flag_rung, pPix, pix)) + return 1; + } + } + + return 0; +} + +static int epic_decode_run_length(ePICContext *dc, int x, int y, int tile_width, + const uint32_t *curr_row, + const uint32_t *above_row, + const uint32_t *above2_row, + uint32_t *pPix, int *pRun) +{ + int idx, got_pixel = 0, WWneW, old_WWneW = 0; + uint32_t W, WW, N, NN, NW, NE, NWW, NNW, NNE; + + *pRun = 0; + + LOAD_NEIGHBOURS(x); + + if (dc->next_run_pos == x) { + /* can't reuse W for the new pixel in this case */ + WWneW = 1; + } else { + idx = (WW != W) << 7 | + (NW != W) << 6 | + (N != NE) << 5 | + (NW != N) << 4 | + (NWW != NW) << 3 | + (NNE != NE) << 2 | + (NN != N) << 1 | + (NNW != NW); + WWneW = ff_els_decode_bit(&dc->els_ctx, &dc->W_ctx_rung[idx]); + } + + if (WWneW) + dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = W; + else { + *pPix = W; + got_pixel = 1; + } + + do { + int NWneW = 1; + if (got_pixel) // pixel value already known (derived from either W or N) + NWneW = *pPix != N; + else { // pixel value is unknown and will be decoded later + NWneW = *pRun ? NWneW : NW != W; + + /* TODO: RFC this mess! */ + switch (((NW != N) << 2) | (NWneW << 1) | WWneW) { + case 0: + break; // do nothing here + case 3: + case 5: + case 6: + case 7: + if (!is_pixel_on_stack(dc, N)) { + idx = WWneW << 8 | + (*pRun ? old_WWneW : WW != W) << 7 | + NWneW << 6 | + (N != NE) << 5 | + (NW != N) << 4 | + (NWW != NW) << 3 | + (NNE != NE) << 2 | + (NN != N) << 1 | + (NNW != NW); + if (!ff_els_decode_bit(&dc->els_ctx, &dc->N_ctx_rung[idx])) { + NWneW = 0; + *pPix = N; + got_pixel = 1; + break; + } + } + /* fall through */ + default: + NWneW = 1; + old_WWneW = WWneW; + if (!is_pixel_on_stack(dc, N)) + dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = N; + } + } + + (*pRun)++; + if (x + *pRun >= tile_width - 1) + break; + + UPDATE_NEIGHBOURS(x + *pRun); + + if (!NWneW && NW == N && N == NE) { + int pos, run, rle; + int start_pos = x + *pRun; + + /* scan for a run of pix in the line above */ + uint32_t pix = above_row[start_pos + 1]; + for (pos = start_pos + 2; pos < tile_width; pos++) + if (!(above_row[pos] == pix)) + break; + run = pos - start_pos - 1; + idx = av_ceil_log2(run); + if (ff_els_decode_bit(&dc->els_ctx, &dc->prev_row_rung[idx])) + *pRun += run; + else { + int flag; + /* run-length is coded as plain binary number of idx - 1 bits */ + for (pos = idx - 1, rle = 0, flag = 0; pos >= 0; pos--) { + if ((1 << pos) + rle < run && + ff_els_decode_bit(&dc->els_ctx, + flag ? &dc->runlen_one + : &dc->runlen_zeroes[pos])) { + flag = 1; + rle |= 1 << pos; + } + } + *pRun += rle; + break; // return immediately + } + if (x + *pRun >= tile_width - 1) + break; + + LOAD_NEIGHBOURS(x + *pRun); + WWneW = 0; + NWneW = 0; + } + + idx = WWneW << 7 | + NWneW << 6 | + (N != NE) << 5 | + (NW != N) << 4 | + (NWW != NW) << 3 | + (NNE != NE) << 2 | + (NN != N) << 1 | + (NNW != NW); + WWneW = ff_els_decode_bit(&dc->els_ctx, &dc->W_ctx_rung[idx]); + } while (!WWneW); + + dc->next_run_pos = x + *pRun; + return got_pixel; +} + +static int epic_predict_pixel2(ePICContext *dc, uint8_t *rung, + uint32_t *pPix, uint32_t pix) +{ + if (ff_els_decode_bit(&dc->els_ctx, rung)) { + *pPix = pix; + return 1; + } + dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = pix; + return 0; +} + +static int epic_predict_from_NW_NE(ePICContext *dc, int x, int y, int run, + int tile_width, const uint32_t *curr_row, + const uint32_t *above_row, uint32_t *pPix) +{ + int pos; + + /* try to reuse the NW pixel first */ + if (x && y) { + uint32_t NW = above_row[x - 1]; + if (NW != curr_row[x - 1] && NW != above_row[x] && !is_pixel_on_stack(dc, NW)) { + if (epic_predict_pixel2(dc, &dc->nw_pred_rung[NW & 0xFF], pPix, NW)) + return 1; + } + } + + /* try to reuse the NE[x + run, y] pixel */ + pos = x + run - 1; + if (pos < tile_width - 1 && y) { + uint32_t NE = above_row[pos + 1]; + if (NE != above_row[pos] && !is_pixel_on_stack(dc, NE)) { + if (epic_predict_pixel2(dc, &dc->ne_pred_rung[NE & 0xFF], pPix, NE)) + return 1; + } + } + + return 0; +} + +static int epic_decode_from_cache(ePICContext *dc, uint32_t W, uint32_t *pPix) +{ + ePICPixListElem *list, *prev = NULL; + ePICPixHashElem *hash_elem = epic_hash_find(&dc->hash, W); + + if (!hash_elem || !hash_elem->list) + return 0; + + list = hash_elem->list; + while (list) { + if (!is_pixel_on_stack(dc, list->pixel)) { + if (ff_els_decode_bit(&dc->els_ctx, &list->rung)) { + *pPix = list->pixel; + if (list != hash_elem->list) { + prev->next = list->next; + list->next = hash_elem->list; + hash_elem->list = list; + } + return 1; + } + dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = list->pixel; + } + prev = list; + list = list->next; + } + + return 0; +} + +static int epic_decode_tile(ePICContext *dc, uint8_t *out, int tile_height, + int tile_width, int stride) +{ + int x, y; + uint32_t pix; + uint32_t *curr_row = NULL, *above_row = NULL, *above2_row; + + for (y = 0; y < tile_height; y++, out += stride) { + above2_row = above_row; + above_row = curr_row; + curr_row = (uint32_t *) out; + + for (x = 0, dc->next_run_pos = 0; x < tile_width;) { + if (dc->els_ctx.err) + return AVERROR_INVALIDDATA; // bail out in the case of ELS overflow + + pix = curr_row[x - 1]; // get W pixel + + if (y >= 1 && x >= 2 && + pix != curr_row[x - 2] && pix != above_row[x - 1] && + pix != above_row[x - 2] && pix != above_row[x] && + !epic_cache_entries_for_pixel(&dc->hash, pix)) { + curr_row[x] = epic_decode_pixel_pred(dc, x, y, curr_row, above_row); + x++; + } else { + int got_pixel, run; + dc->stack_pos = 0; // empty stack + + if (y < 2 || x < 2 || x == tile_width - 1) { + run = 1; + got_pixel = epic_handle_edges(dc, x, y, curr_row, above_row, &pix); + } else + got_pixel = epic_decode_run_length(dc, x, y, tile_width, + curr_row, above_row, + above2_row, &pix, &run); + + if (!got_pixel && !epic_predict_from_NW_NE(dc, x, y, run, + tile_width, curr_row, + above_row, &pix)) { + uint32_t ref_pix = curr_row[x - 1]; + if (!x || !epic_decode_from_cache(dc, ref_pix, &pix)) { + pix = epic_decode_pixel_pred(dc, x, y, curr_row, above_row); + if (x) { + int ret = epic_add_pixel_to_cache(&dc->hash, + ref_pix, + pix); + if (ret) + return ret; + } + } + } + for (; run > 0; x++, run--) + curr_row[x] = pix; + } + } + } + + return 0; +} + +static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y, + const uint8_t *src, size_t src_size, + AVCodecContext *avctx) +{ + uint8_t prefix, mask = 0x80; + int extrabytes, tile_width, tile_height, awidth, aheight; + size_t els_dsize; + uint8_t *dst; + + if (!src_size) + return 0; + + /* get data size of the ELS partition as unsigned variable-length integer */ + prefix = *src++; + src_size--; + for (extrabytes = 0; (prefix & mask) && (extrabytes < 7); extrabytes++) + mask >>= 1; + if (extrabytes > 3 || src_size < extrabytes) { + av_log(avctx, AV_LOG_ERROR, "ePIC: invalid data size VLI\n"); + return AVERROR_INVALIDDATA; + } + + els_dsize = prefix & ((0x80 >> extrabytes) - 1); // mask out the length prefix + while (extrabytes-- > 0) { + els_dsize = (els_dsize << 8) | *src++; + src_size--; + } + + if (src_size < els_dsize) { + av_log(avctx, AV_LOG_ERROR, "ePIC: data too short, needed %zu, got %zu\n", + els_dsize, src_size); + return AVERROR_INVALIDDATA; + } + + tile_width = FFMIN(c->width - tile_x * c->tile_width, c->tile_width); + tile_height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height); + awidth = FFALIGN(tile_width, 16); + aheight = FFALIGN(tile_height, 16); + + if (els_dsize) { + int ret, i, j, k; + uint8_t tr_r, tr_g, tr_b, *buf; + uint32_t *in; + /* ELS decoder initializations */ + memset(&c->ec, 0, sizeof(c->ec)); + ff_els_decoder_init(&c->ec.els_ctx, src, els_dsize); + epic_hash_init(&c->ec.hash); + + /* decode transparent pixel value */ + tr_r = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung); + tr_g = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung); + tr_b = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung); + if (c->ec.els_ctx.err != 0) { + av_log(avctx, AV_LOG_ERROR, + "ePIC: couldn't decode transparency pixel!\n"); + return AVERROR_INVALIDDATA; + } + + ret = epic_decode_tile(&c->ec, c->epic_buf, tile_height, tile_width, + c->epic_buf_stride); + + epic_free_pixel_cache(&c->ec.hash); + ff_els_decoder_uninit(&c->ec.unsigned_rung); + + if (ret) { + av_log(avctx, AV_LOG_ERROR, + "ePIC: tile decoding failed, frame=%d, tile_x=%d, tile_y=%d\n", + avctx->frame_number, tile_x, tile_y); + return AVERROR_INVALIDDATA; + } + + buf = c->epic_buf; + dst = c->framebuf + tile_x * c->tile_width * 3 + + tile_y * c->tile_height * c->framebuf_stride; + + for (j = 0; j < tile_height; j++) { + uint8_t *out = dst; + in = (uint32_t *) buf; + for (i = 0; i < tile_width; i++) { + out[0] = (in[i] >> R_shift) & 0xFF; + out[1] = (in[i] >> G_shift) & 0xFF; + out[2] = (in[i] >> B_shift) & 0xFF; + out += 3; + } + buf += c->epic_buf_stride; + dst += c->framebuf_stride; + } + + if (src_size > els_dsize) { + uint8_t *jpg; + uint32_t tr; + int bstride = FFALIGN(tile_width, 16) >> 3; + int nblocks = 0; + int estride = c->epic_buf_stride >> 2; + + src += els_dsize; + src_size -= els_dsize; + + in = (uint32_t *) c->epic_buf; + tr = (tr_r << R_shift) | (tr_g << G_shift) | (tr_b << B_shift); + + memset(c->kempf_flags, 0, + (aheight >> 3) * bstride * sizeof(*c->kempf_flags)); + for (j = 0; j < tile_height; j += 8) { + for (i = 0; i < tile_width; i += 8) { + c->kempf_flags[(i >> 3) + (j >> 3) * bstride] = 0; + for (k = 0; k < 8 * 8; k++) { + if (in[i + (k & 7) + (k >> 3) * estride] == tr) { + c->kempf_flags[(i >> 3) + (j >> 3) * bstride] = 1; + nblocks++; + break; + } + } + } + in += 8 * estride; + } + + memset(c->jpeg_tile, 0, c->tile_stride * aheight); + jpg_decode_data(&c->jc, awidth, aheight, src, src_size, + c->jpeg_tile, c->tile_stride, + c->kempf_flags, bstride, nblocks, c->swapuv); + + in = (uint32_t *) c->epic_buf; + dst = c->framebuf + tile_x * c->tile_width * 3 + + tile_y * c->tile_height * c->framebuf_stride; + jpg = c->jpeg_tile; + for (j = 0; j < tile_height; j++) { + for (i = 0; i < tile_width; i++) + if (in[i] == tr) + memcpy(dst + i * 3, jpg + i * 3, 3); + in += c->epic_buf_stride >> 2; + dst += c->framebuf_stride; + jpg += c->tile_stride; + } + } + } else { + dst = c->framebuf + tile_x * c->tile_width * 3 + + tile_y * c->tile_height * c->framebuf_stride; + return jpg_decode_data(&c->jc, tile_width, tile_height, src, src_size, + dst, c->framebuf_stride, NULL, 0, 0, c->swapuv); + } + + return 0; +} + static void kempf_restore_buf(const uint8_t *src, int len, uint8_t *dst, int stride, const uint8_t *jpeg_tile, int tile_stride, @@ -322,6 +1013,7 @@ static void kempf_restore_buf(const uint8_t *src, int len, { GetBitContext gb; int i, j, nb, col; + int align_width = FFALIGN(width, 16); init_get_bits(&gb, src, len * 8); @@ -340,6 +1032,7 @@ static void kempf_restore_buf(const uint8_t *src, int len, else memcpy(dst + i * 3, jpeg_tile + i * 3, 3); } + skip_bits_long(&gb, nb * (align_width - width)); } } @@ -463,22 +1156,31 @@ static int g2m_init_buffers(G2MContext *c) return AVERROR(ENOMEM); } if (!c->synth_tile || !c->jpeg_tile || + (c->compression == 2 && !c->epic_buf_base) || c->old_tile_w < c->tile_width || c->old_tile_h < c->tile_height) { - c->tile_stride = FFALIGN(c->tile_width * 3, 16); - aligned_height = FFALIGN(c->tile_height, 16); + c->tile_stride = FFALIGN(c->tile_width * 3, 16); + c->epic_buf_stride = FFALIGN(c->tile_width * 4, 16); + aligned_height = FFALIGN(c->tile_height, 16); av_free(c->synth_tile); av_free(c->jpeg_tile); av_free(c->kempf_buf); av_free(c->kempf_flags); + av_free(c->epic_buf_base); c->synth_tile = av_mallocz(c->tile_stride * aligned_height); c->jpeg_tile = av_mallocz(c->tile_stride * aligned_height); - c->kempf_buf = av_mallocz((c->tile_width + 1) * aligned_height - + FF_INPUT_BUFFER_PADDING_SIZE); - c->kempf_flags = av_mallocz( c->tile_width * aligned_height); + c->kempf_buf = av_mallocz((c->tile_width + 1) * aligned_height + + AV_INPUT_BUFFER_PADDING_SIZE); + c->kempf_flags = av_mallocz(c->tile_width * aligned_height); if (!c->synth_tile || !c->jpeg_tile || !c->kempf_buf || !c->kempf_flags) return AVERROR(ENOMEM); + if (c->compression == 2) { + c->epic_buf_base = av_mallocz(c->epic_buf_stride * aligned_height + 4); + if (!c->epic_buf_base) + return AVERROR(ENOMEM); + c->epic_buf = c->epic_buf_base + 4; + } } return 0; @@ -682,15 +1384,12 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, magic = bytestream2_get_be32(&bc); if ((magic & ~0xF) != MKBETAG('G', '2', 'M', '0') || - (magic & 0xF) < 2 || (magic & 0xF) > 4) { + (magic & 0xF) < 2 || (magic & 0xF) > 5) { av_log(avctx, AV_LOG_ERROR, "Wrong magic %08X\n", magic); return AVERROR_INVALIDDATA; } - if ((magic & 0xF) != 4) { - av_log(avctx, AV_LOG_ERROR, "G2M2 and G2M3 are not yet supported\n"); - return AVERROR(ENOSYS); - } + c->swapuv = magic == MKBETAG('G', '2', 'M', '2'); while (bytestream2_get_bytes_left(&bc) > 5) { chunk_size = bytestream2_get_le32(&bc) - 1; @@ -711,8 +1410,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, } c->width = bytestream2_get_be32(&bc); c->height = bytestream2_get_be32(&bc); - if (c->width < 16 || c->width > c->orig_width || - c->height < 16 || c->height > c->orig_height) { + if (c->width < 16 || c->height < 16) { av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d\n", c->width, c->height); @@ -792,9 +1490,10 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, ret = 0; switch (c->compression) { case COMPR_EPIC_J_B: - av_log(avctx, AV_LOG_ERROR, - "ePIC j-b compression is not implemented yet\n"); - return AVERROR(ENOSYS); + ret = epic_jb_decode_tile(c, c->tile_x, c->tile_y, + buf + bytestream2_tell(&bc), + chunk_size - 2, avctx); + break; case COMPR_KEMPF_J_B: ret = kempf_decode_tile(c, c->tile_x, c->tile_y, buf + bytestream2_tell(&bc), @@ -892,6 +1591,7 @@ static av_cold int g2m_decode_end(AVCodecContext *avctx) jpg_free_context(&c->jc); + av_freep(&c->epic_buf_base); av_freep(&c->kempf_buf); av_freep(&c->kempf_flags); av_freep(&c->synth_tile); @@ -911,5 +1611,6 @@ AVCodec ff_g2m_decoder = { .init = g2m_decode_init, .close = g2m_decode_end, .decode = g2m_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/g722.c b/libavcodec/g722.c index a911bc7..830877e 100644 --- a/libavcodec/g722.c +++ b/libavcodec/g722.c @@ -71,15 +71,35 @@ const int16_t ff_g722_low_inv_quant6[64] = { 211, 170, 130, 91, 54, 17, -54, -17 }; -/** - * quadrature mirror filter (QMF) coefficients - * - * ITU-T G.722 Table 11 - */ -static const int16_t qmf_coeffs[12] = { - 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, -}; - +static inline void s_zero(int cur_diff, struct G722Band *band) +{ + int s_zero = 0; + + #define ACCUM(k, x, d) do { \ + int tmp = x; \ + band->zero_mem[k] = ((band->zero_mem[k] * 255) >> 8) + \ + d*((band->diff_mem[k]^cur_diff) < 0 ? -128 : 128); \ + band->diff_mem[k] = tmp; \ + s_zero += (tmp * band->zero_mem[k]) >> 15; \ + } while (0) + if (cur_diff) { + ACCUM(5, band->diff_mem[4], 1); + ACCUM(4, band->diff_mem[3], 1); + ACCUM(3, band->diff_mem[2], 1); + ACCUM(2, band->diff_mem[1], 1); + ACCUM(1, band->diff_mem[0], 1); + ACCUM(0, cur_diff << 1, 1); + } else { + ACCUM(5, band->diff_mem[4], 0); + ACCUM(4, band->diff_mem[3], 0); + ACCUM(3, band->diff_mem[2], 0); + ACCUM(2, band->diff_mem[1], 0); + ACCUM(1, band->diff_mem[0], 0); + ACCUM(0, cur_diff << 1, 0); + } + #undef ACCUM + band->s_zero = s_zero; +} /** * adaptive predictor @@ -89,7 +109,7 @@ static const int16_t qmf_coeffs[12] = { */ static void do_adaptive_prediction(struct G722Band *band, const int cur_diff) { - int sg[2], limit, i, cur_qtzd_reconst; + int sg[2], limit, cur_qtzd_reconst; const int cur_part_reconst = band->s_zero + cur_diff < 0; @@ -104,23 +124,7 @@ static void do_adaptive_prediction(struct G722Band *band, const int cur_diff) limit = 15360 - band->pole_mem[1]; band->pole_mem[0] = av_clip(-192 * sg[0] + (band->pole_mem[0] * 255 >> 8), -limit, limit); - - if (cur_diff) { - for (i = 0; i < 6; i++) - band->zero_mem[i] = ((band->zero_mem[i]*255) >> 8) + - ((band->diff_mem[i]^cur_diff) < 0 ? -128 : 128); - } else - for (i = 0; i < 6; i++) - band->zero_mem[i] = (band->zero_mem[i]*255) >> 8; - - for (i = 5; i > 0; i--) - band->diff_mem[i] = band->diff_mem[i-1]; - band->diff_mem[0] = av_clip_int16(cur_diff << 1); - - band->s_zero = 0; - for (i = 5; i >= 0; i--) - band->s_zero += (band->zero_mem[i]*band->diff_mem[i]) >> 15; - + s_zero(cur_diff, band); cur_qtzd_reconst = av_clip_int16((band->s_predictor + cur_diff) << 1); band->s_predictor = av_clip_int16(band->s_zero + @@ -157,15 +161,3 @@ void ff_g722_update_high_predictor(struct G722Band *band, const int dhigh, high_log_factor_step[ihigh&1], 0, 22528); band->scale_factor = linear_scale_factor(band->log_factor - (10 << 11)); } - -void ff_g722_apply_qmf(const int16_t *prev_samples, int *xout1, int *xout2) -{ - int i; - - *xout1 = 0; - *xout2 = 0; - for (i = 0; i < 12; i++) { - MAC16(*xout2, prev_samples[2*i ], qmf_coeffs[i ]); - MAC16(*xout1, prev_samples[2*i+1], qmf_coeffs[11-i]); - } -} diff --git a/libavcodec/g722.h b/libavcodec/g722.h index 71d03fc..4830170 100644 --- a/libavcodec/g722.h +++ b/libavcodec/g722.h @@ -27,6 +27,7 @@ #include #include "avcodec.h" +#include "g722dsp.h" #define PREV_SAMPLES_BUF_SIZE 1024 @@ -61,6 +62,8 @@ typedef struct G722Context { int value; int prev; } *paths[2]; + + G722DSPContext dsp; } G722Context; extern const int16_t ff_g722_high_inv_quant[4]; @@ -72,6 +75,4 @@ void ff_g722_update_low_predictor(struct G722Band *band, const int ilow); void ff_g722_update_high_predictor(struct G722Band *band, const int dhigh, const int ihigh); -void ff_g722_apply_qmf(const int16_t *prev_samples, int *xout1, int *xout2); - #endif /* AVCODEC_G722_H */ diff --git a/libavcodec/g722dec.c b/libavcodec/g722dec.c index 26f288b..c4c0ec8 100644 --- a/libavcodec/g722dec.c +++ b/libavcodec/g722dec.c @@ -67,6 +67,8 @@ static av_cold int g722_decode_init(AVCodecContext * avctx) c->band[1].scale_factor = 2; c->prev_samples_pos = 22; + ff_g722dsp_init(&c->dsp); + return 0; } @@ -104,28 +106,27 @@ static int g722_decode_frame(AVCodecContext *avctx, void *data, for (j = 0; j < avpkt->size; j++) { int ilow, ihigh, rlow, rhigh, dhigh; - int xout1, xout2; + int xout[2]; ihigh = get_bits(&gb, 2); ilow = get_bits(&gb, 6 - skip); skip_bits(&gb, skip); - rlow = av_clip((c->band[0].scale_factor * quantizer_table[ilow] >> 10) - + c->band[0].s_predictor, -16384, 16383); + rlow = av_clip_intp2((c->band[0].scale_factor * quantizer_table[ilow] >> 10) + + c->band[0].s_predictor, 14); ff_g722_update_low_predictor(&c->band[0], ilow >> (2 - skip)); dhigh = c->band[1].scale_factor * ff_g722_high_inv_quant[ihigh] >> 10; - rhigh = av_clip(dhigh + c->band[1].s_predictor, -16384, 16383); + rhigh = av_clip_intp2(dhigh + c->band[1].s_predictor, 14); ff_g722_update_high_predictor(&c->band[1], dhigh, ihigh); c->prev_samples[c->prev_samples_pos++] = rlow + rhigh; c->prev_samples[c->prev_samples_pos++] = rlow - rhigh; - ff_g722_apply_qmf(c->prev_samples + c->prev_samples_pos - 24, - &xout1, &xout2); - *out_buf++ = av_clip_int16(xout1 >> 11); - *out_buf++ = av_clip_int16(xout2 >> 11); + c->dsp.apply_qmf(c->prev_samples + c->prev_samples_pos - 24, xout); + *out_buf++ = av_clip_int16(xout[0] >> 11); + *out_buf++ = av_clip_int16(xout[1] >> 11); if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) { memmove(c->prev_samples, c->prev_samples + c->prev_samples_pos - 22, 22 * sizeof(c->prev_samples[0])); @@ -146,6 +147,6 @@ AVCodec ff_adpcm_g722_decoder = { .priv_data_size = sizeof(G722Context), .init = g722_decode_init, .decode = g722_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .priv_class = &g722_decoder_class, }; diff --git a/libavcodec/g722dsp.c b/libavcodec/g722dsp.c new file mode 100644 index 0000000..c7e41ff --- /dev/null +++ b/libavcodec/g722dsp.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "g722dsp.h" +#include "mathops.h" + +/* + * quadrature mirror filter (QMF) coefficients (ITU-T G.722 Table 11) inlined + * in code below: 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11 + */ + +static void g722_apply_qmf(const int16_t *prev_samples, int xout[2]) +{ + xout[1] = MUL16(*prev_samples++, 3); + xout[0] = MUL16(*prev_samples++, -11); + + MAC16(xout[1], *prev_samples++, -11); + MAC16(xout[0], *prev_samples++, 53); + + MAC16(xout[1], *prev_samples++, 12); + MAC16(xout[0], *prev_samples++, -156); + + MAC16(xout[1], *prev_samples++, 32); + MAC16(xout[0], *prev_samples++, 362); + + MAC16(xout[1], *prev_samples++, -210); + MAC16(xout[0], *prev_samples++, -805); + + MAC16(xout[1], *prev_samples++, 951); + MAC16(xout[0], *prev_samples++, 3876); + + MAC16(xout[1], *prev_samples++, 3876); + MAC16(xout[0], *prev_samples++, 951); + + MAC16(xout[1], *prev_samples++, -805); + MAC16(xout[0], *prev_samples++, -210); + + MAC16(xout[1], *prev_samples++, 362); + MAC16(xout[0], *prev_samples++, 32); + + MAC16(xout[1], *prev_samples++, -156); + MAC16(xout[0], *prev_samples++, 12); + + MAC16(xout[1], *prev_samples++, 53); + MAC16(xout[0], *prev_samples++, -11); + + MAC16(xout[1], *prev_samples++, -11); + MAC16(xout[0], *prev_samples++, 3); +} + +av_cold void ff_g722dsp_init(G722DSPContext *c) +{ + c->apply_qmf = g722_apply_qmf; + + if (ARCH_ARM) + ff_g722dsp_init_arm(c); +} diff --git a/libavcodec/g722dsp.h b/libavcodec/g722dsp.h new file mode 100644 index 0000000..ecd6a47 --- /dev/null +++ b/libavcodec/g722dsp.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_G722DSP_H +#define AVCODEC_G722DSP_H + +#include + +typedef struct G722DSPContext { + void (*apply_qmf)(const int16_t *prev_samples, int xout[2]); +} G722DSPContext; + +void ff_g722dsp_init(G722DSPContext *c); +void ff_g722dsp_init_arm(G722DSPContext *c); + +#endif /* AVCODEC_G722DSP_H */ diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c index e7b67da..545825b 100644 --- a/libavcodec/g722enc.c +++ b/libavcodec/g722enc.c @@ -106,7 +106,7 @@ static av_cold int g722_encode_init(AVCodecContext * avctx) a common packet size for VoIP applications */ avctx->frame_size = 320; } - avctx->delay = 22; + avctx->initial_padding = 22; if (avctx->trellis) { /* validate trellis */ @@ -119,6 +119,8 @@ static av_cold int g722_encode_init(AVCodecContext * avctx) } } + ff_g722dsp_init(&c->dsp); + return 0; error: g722_encode_close(avctx); @@ -135,12 +137,12 @@ static const int16_t low_quant[33] = { static inline void filter_samples(G722Context *c, const int16_t *samples, int *xlow, int *xhigh) { - int xout1, xout2; + int xout[2]; c->prev_samples[c->prev_samples_pos++] = samples[0]; c->prev_samples[c->prev_samples_pos++] = samples[1]; - ff_g722_apply_qmf(c->prev_samples + c->prev_samples_pos - 24, &xout1, &xout2); - *xlow = xout1 + xout2 >> 14; - *xhigh = xout1 - xout2 >> 14; + c->dsp.apply_qmf(c->prev_samples + c->prev_samples_pos - 24, xout); + *xlow = xout[0] + xout[1] >> 14; + *xhigh = xout[0] - xout[1] >> 14; if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) { memmove(c->prev_samples, c->prev_samples + c->prev_samples_pos - 22, @@ -223,9 +225,9 @@ static void g722_encode_trellis(G722Context *c, int trellis, if (k < 0) continue; - decoded = av_clip((cur_node->state.scale_factor * + decoded = av_clip_intp2((cur_node->state.scale_factor * ff_g722_low_inv_quant6[k] >> 10) - + cur_node->state.s_predictor, -16384, 16383); + + cur_node->state.s_predictor, 14); dec_diff = xlow - decoded; #define STORE_NODE(index, UPDATE, VALUE)\ @@ -282,8 +284,7 @@ static void g722_encode_trellis(G722Context *c, int trellis, dhigh = cur_node->state.scale_factor * ff_g722_high_inv_quant[ihigh] >> 10; - decoded = av_clip(dhigh + cur_node->state.s_predictor, - -16384, 16383); + decoded = av_clip_intp2(dhigh + cur_node->state.s_predictor, 14); dec_diff = xhigh - decoded; STORE_NODE(1, ff_g722_update_high_predictor(&node->state, dhigh, ihigh), ihigh); @@ -375,7 +376,7 @@ static int g722_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); *got_packet_ptr = 1; return 0; } @@ -389,7 +390,7 @@ AVCodec ff_adpcm_g722_encoder = { .init = g722_encode_init, .close = g722_encode_close, .encode2 = g722_encode_frame, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/g723_1.c b/libavcodec/g723_1.c index bbdb404..3d45f9d 100644 --- a/libavcodec/g723_1.c +++ b/libavcodec/g723_1.c @@ -20,360 +20,97 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file - * G.723.1 compatible decoder - */ - -#define BITSTREAM_READER_LE -#include "libavutil/channel_layout.h" -#include "libavutil/mem.h" -#include "libavutil/opt.h" -#include "avcodec.h" -#include "get_bits.h" -#include "acelp_vectors.h" -#include "celp_filters.h" -#include "g723_1_data.h" -#include "internal.h" - -#define CNG_RANDOM_SEED 12345 - -/** - * G723.1 frame types - */ -enum FrameType { - ACTIVE_FRAME, ///< Active speech - SID_FRAME, ///< Silence Insertion Descriptor frame - UNTRANSMITTED_FRAME -}; - -enum Rate { - RATE_6300, - RATE_5300 -}; - -/** - * G723.1 unpacked data subframe - */ -typedef struct { - int ad_cb_lag; ///< adaptive codebook lag - int ad_cb_gain; - int dirac_train; - int pulse_sign; - int grid_index; - int amp_index; - int pulse_pos; -} G723_1_Subframe; +#include -/** - * Pitch postfilter parameters - */ -typedef struct { - int index; ///< postfilter backward/forward lag - int16_t opt_gain; ///< optimal gain - int16_t sc_gain; ///< scaling gain -} PPFParam; +#include "libavutil/common.h" -typedef struct g723_1_context { - AVClass *class; - - G723_1_Subframe subframe[4]; - enum FrameType cur_frame_type; - enum FrameType past_frame_type; - enum Rate cur_rate; - uint8_t lsp_index[LSP_BANDS]; - int pitch_lag[2]; - int erased_frames; - - int16_t prev_lsp[LPC_ORDER]; - int16_t sid_lsp[LPC_ORDER]; - int16_t prev_excitation[PITCH_MAX]; - int16_t excitation[PITCH_MAX + FRAME_LEN + 4]; - int16_t synth_mem[LPC_ORDER]; - int16_t fir_mem[LPC_ORDER]; - int iir_mem[LPC_ORDER]; - - int random_seed; - int cng_random_seed; - int interp_index; - int interp_gain; - int sid_gain; - int cur_gain; - int reflection_coef; - int pf_gain; - int postfilter; - - int16_t audio[FRAME_LEN + LPC_ORDER + PITCH_MAX + 4]; -} G723_1_Context; - -static av_cold int g723_1_decode_init(AVCodecContext *avctx) -{ - G723_1_Context *p = avctx->priv_data; - - avctx->channel_layout = AV_CH_LAYOUT_MONO; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = 1; - avctx->sample_rate = 8000; - p->pf_gain = 1 << 12; - - memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); - memcpy(p->sid_lsp, dc_lsp, LPC_ORDER * sizeof(*p->sid_lsp)); - - p->cng_random_seed = CNG_RANDOM_SEED; - p->past_frame_type = SID_FRAME; - - return 0; -} +#include "acelp_vectors.h" +#include "avcodec.h" +#include "celp_math.h" +#include "g723_1.h" -/** - * Unpack the frame into parameters. - * - * @param p the context - * @param buf pointer to the input buffer - * @param buf_size size of the input buffer - */ -static int unpack_bitstream(G723_1_Context *p, const uint8_t *buf, - int buf_size) +int ff_g723_1_scale_vector(int16_t *dst, const int16_t *vector, int length) { - GetBitContext gb; - int ad_cb_len; - int temp, info_bits, i; - - init_get_bits(&gb, buf, buf_size * 8); - - /* Extract frame type and rate info */ - info_bits = get_bits(&gb, 2); - - if (info_bits == 3) { - p->cur_frame_type = UNTRANSMITTED_FRAME; - return 0; - } - - /* Extract 24 bit lsp indices, 8 bit for each band */ - p->lsp_index[2] = get_bits(&gb, 8); - p->lsp_index[1] = get_bits(&gb, 8); - p->lsp_index[0] = get_bits(&gb, 8); - - if (info_bits == 2) { - p->cur_frame_type = SID_FRAME; - p->subframe[0].amp_index = get_bits(&gb, 6); - return 0; - } - - /* Extract the info common to both rates */ - p->cur_rate = info_bits ? RATE_5300 : RATE_6300; - p->cur_frame_type = ACTIVE_FRAME; - - p->pitch_lag[0] = get_bits(&gb, 7); - if (p->pitch_lag[0] > 123) /* test if forbidden code */ - return -1; - p->pitch_lag[0] += PITCH_MIN; - p->subframe[1].ad_cb_lag = get_bits(&gb, 2); - - p->pitch_lag[1] = get_bits(&gb, 7); - if (p->pitch_lag[1] > 123) - return -1; - p->pitch_lag[1] += PITCH_MIN; - p->subframe[3].ad_cb_lag = get_bits(&gb, 2); - p->subframe[0].ad_cb_lag = 1; - p->subframe[2].ad_cb_lag = 1; - - for (i = 0; i < SUBFRAMES; i++) { - /* Extract combined gain */ - temp = get_bits(&gb, 12); - ad_cb_len = 170; - p->subframe[i].dirac_train = 0; - if (p->cur_rate == RATE_6300 && p->pitch_lag[i >> 1] < SUBFRAME_LEN - 2) { - p->subframe[i].dirac_train = temp >> 11; - temp &= 0x7FF; - ad_cb_len = 85; - } - p->subframe[i].ad_cb_gain = FASTDIV(temp, GAIN_LEVELS); - if (p->subframe[i].ad_cb_gain < ad_cb_len) { - p->subframe[i].amp_index = temp - p->subframe[i].ad_cb_gain * - GAIN_LEVELS; - } else { - return -1; - } - } - - p->subframe[0].grid_index = get_bits(&gb, 1); - p->subframe[1].grid_index = get_bits(&gb, 1); - p->subframe[2].grid_index = get_bits(&gb, 1); - p->subframe[3].grid_index = get_bits(&gb, 1); - - if (p->cur_rate == RATE_6300) { - skip_bits(&gb, 1); /* skip reserved bit */ - - /* Compute pulse_pos index using the 13-bit combined position index */ - temp = get_bits(&gb, 13); - p->subframe[0].pulse_pos = temp / 810; - - temp -= p->subframe[0].pulse_pos * 810; - p->subframe[1].pulse_pos = FASTDIV(temp, 90); - - temp -= p->subframe[1].pulse_pos * 90; - p->subframe[2].pulse_pos = FASTDIV(temp, 9); - p->subframe[3].pulse_pos = temp - p->subframe[2].pulse_pos * 9; + int bits, max = 0; + int i; - p->subframe[0].pulse_pos = (p->subframe[0].pulse_pos << 16) + - get_bits(&gb, 16); - p->subframe[1].pulse_pos = (p->subframe[1].pulse_pos << 14) + - get_bits(&gb, 14); - p->subframe[2].pulse_pos = (p->subframe[2].pulse_pos << 16) + - get_bits(&gb, 16); - p->subframe[3].pulse_pos = (p->subframe[3].pulse_pos << 14) + - get_bits(&gb, 14); + for (i = 0; i < length; i++) + max |= FFABS(vector[i]); - p->subframe[0].pulse_sign = get_bits(&gb, 6); - p->subframe[1].pulse_sign = get_bits(&gb, 5); - p->subframe[2].pulse_sign = get_bits(&gb, 6); - p->subframe[3].pulse_sign = get_bits(&gb, 5); - } else { /* 5300 bps */ - p->subframe[0].pulse_pos = get_bits(&gb, 12); - p->subframe[1].pulse_pos = get_bits(&gb, 12); - p->subframe[2].pulse_pos = get_bits(&gb, 12); - p->subframe[3].pulse_pos = get_bits(&gb, 12); + max = FFMIN(max, 0x7FFF); + bits = ff_g723_1_normalize_bits(max, 15); - p->subframe[0].pulse_sign = get_bits(&gb, 4); - p->subframe[1].pulse_sign = get_bits(&gb, 4); - p->subframe[2].pulse_sign = get_bits(&gb, 4); - p->subframe[3].pulse_sign = get_bits(&gb, 4); - } + for (i = 0; i < length; i++) + dst[i] = vector[i] << bits >> 3; - return 0; + return bits - 3; } -/** - * Bitexact implementation of sqrt(val/2). - */ -static int16_t square_root(int val) +int ff_g723_1_normalize_bits(int num, int width) { - int16_t res = 0; - int16_t exp = 0x4000; - int i; - - for (i = 0; i < 14; i ++) { - int res_exp = res + exp; - if (val >= res_exp * res_exp << 1) - res += exp; - exp >>= 1; - } - return res; + return width - av_log2(num) - 1; } -/** - * Calculate the number of left-shifts required for normalizing the input. - * - * @param num input number - * @param width width of the input, 16 bits(0) / 32 bits(1) - */ -static int normalize_bits(int num, int width) +int ff_g723_1_dot_product(const int16_t *a, const int16_t *b, int length) { - return width - av_log2(num) - 1; + int sum = ff_dot_product(a, b, length); + return av_sat_add32(sum, sum); } -/** - * Scale vector contents based on the largest of their absolutes. - */ -static int scale_vector(int16_t *dst, const int16_t *vector, int length) +void ff_g723_1_get_residual(int16_t *residual, int16_t *prev_excitation, + int lag) { - int bits, max = 0; + int offset = PITCH_MAX - PITCH_ORDER / 2 - lag; int i; + residual[0] = prev_excitation[offset]; + residual[1] = prev_excitation[offset + 1]; - for (i = 0; i < length; i++) - max |= FFABS(vector[i]); - - max = FFMIN(max, 0x7FFF); - bits = normalize_bits(max, 15); - - for (i = 0; i < length; i++) - dst[i] = vector[i] << bits >> 3; - - return bits - 3; + offset += 2; + for (i = 2; i < SUBFRAME_LEN + PITCH_ORDER - 1; i++) + residual[i] = prev_excitation[offset + (i - 2) % lag]; } -/** - * Perform inverse quantization of LSP frequencies. - * - * @param cur_lsp the current LSP vector - * @param prev_lsp the previous LSP vector - * @param lsp_index VQ indices - * @param bad_frame bad frame flag - */ -static void inverse_quant(int16_t *cur_lsp, int16_t *prev_lsp, - uint8_t *lsp_index, int bad_frame) +void ff_g723_1_gen_dirac_train(int16_t *buf, int pitch_lag) { - int min_dist, pred; - int i, j, temp, stable; + int16_t vector[SUBFRAME_LEN]; + int i, j; - /* Check for frame erasure */ - if (!bad_frame) { - min_dist = 0x100; - pred = 12288; - } else { - min_dist = 0x200; - pred = 23552; - lsp_index[0] = lsp_index[1] = lsp_index[2] = 0; + memcpy(vector, buf, SUBFRAME_LEN * sizeof(*vector)); + for (i = pitch_lag; i < SUBFRAME_LEN; i += pitch_lag) { + for (j = 0; j < SUBFRAME_LEN - i; j++) + buf[i + j] += vector[j]; } +} - /* Get the VQ table entry corresponding to the transmitted index */ - cur_lsp[0] = lsp_band0[lsp_index[0]][0]; - cur_lsp[1] = lsp_band0[lsp_index[0]][1]; - cur_lsp[2] = lsp_band0[lsp_index[0]][2]; - cur_lsp[3] = lsp_band1[lsp_index[1]][0]; - cur_lsp[4] = lsp_band1[lsp_index[1]][1]; - cur_lsp[5] = lsp_band1[lsp_index[1]][2]; - cur_lsp[6] = lsp_band2[lsp_index[2]][0]; - cur_lsp[7] = lsp_band2[lsp_index[2]][1]; - cur_lsp[8] = lsp_band2[lsp_index[2]][2]; - cur_lsp[9] = lsp_band2[lsp_index[2]][3]; +void ff_g723_1_gen_acb_excitation(int16_t *vector, int16_t *prev_excitation, + int pitch_lag, G723_1_Subframe *subfrm, + enum Rate cur_rate) +{ + int16_t residual[SUBFRAME_LEN + PITCH_ORDER - 1]; + const int16_t *cb_ptr; + int lag = pitch_lag + subfrm->ad_cb_lag - 1; - /* Add predicted vector & DC component to the previously quantized vector */ - for (i = 0; i < LPC_ORDER; i++) { - temp = ((prev_lsp[i] - dc_lsp[i]) * pred + (1 << 14)) >> 15; - cur_lsp[i] += dc_lsp[i] + temp; - } + int i; + int sum; - for (i = 0; i < LPC_ORDER; i++) { - cur_lsp[0] = FFMAX(cur_lsp[0], 0x180); - cur_lsp[LPC_ORDER - 1] = FFMIN(cur_lsp[LPC_ORDER - 1], 0x7e00); + ff_g723_1_get_residual(residual, prev_excitation, lag); - /* Stability check */ - for (j = 1; j < LPC_ORDER; j++) { - temp = min_dist + cur_lsp[j - 1] - cur_lsp[j]; - if (temp > 0) { - temp >>= 1; - cur_lsp[j - 1] -= temp; - cur_lsp[j] += temp; - } - } - stable = 1; - for (j = 1; j < LPC_ORDER; j++) { - temp = cur_lsp[j - 1] + min_dist - cur_lsp[j] - 4; - if (temp > 0) { - stable = 0; - break; - } - } - if (stable) - break; + /* Select quantization table */ + if (cur_rate == RATE_6300 && pitch_lag < SUBFRAME_LEN - 2) + cb_ptr = adaptive_cb_gain85; + else + cb_ptr = adaptive_cb_gain170; + + /* Calculate adaptive vector */ + cb_ptr += subfrm->ad_cb_gain * 20; + for (i = 0; i < SUBFRAME_LEN; i++) { + sum = ff_g723_1_dot_product(residual + i, cb_ptr, PITCH_ORDER); + vector[i] = av_sat_dadd32(1 << 15, sum) >> 16; } - if (!stable) - memcpy(cur_lsp, prev_lsp, LPC_ORDER * sizeof(*cur_lsp)); } /** - * Bitexact implementation of 2ab scaled by 1/2^16. - * - * @param a 32 bit multiplicand - * @param b 16 bit multiplier - */ -#define MULL2(a, b) \ - ((((a) >> 16) * (b) << 1) + (((a) & 0xffff) * (b) >> 15)) - -/** * Convert LSP frequencies to LPC coefficients. * * @param lpc buffer for LPC coefficients @@ -386,11 +123,11 @@ static void lsp2lpc(int16_t *lpc) /* Calculate negative cosine */ for (j = 0; j < LPC_ORDER; j++) { - int index = lpc[j] >> 7; - int offset = lpc[j] & 0x7f; - int temp1 = cos_tab[index] << 16; - int temp2 = (cos_tab[index + 1] - cos_tab[index]) * - ((offset << 8) + 0x80) << 1; + int index = (lpc[j] >> 7) & 0x1FF; + int offset = lpc[j] & 0x7f; + int temp1 = cos_tab[index] << 16; + int temp2 = (cos_tab[index + 1] - cos_tab[index]) * + ((offset << 8) + 0x80) << 1; lpc[j] = -(av_sat_dadd32(1 << 15, temp1 + temp2) >> 16); } @@ -425,8 +162,8 @@ static void lsp2lpc(int16_t *lpc) f1[0] >>= 1; f2[0] >>= 1; - f1[1] = ((lpc[2 * i] << 16 >> i) + f1[1]) >> 1; - f2[1] = ((lpc[2 * i + 1] << 16 >> i) + f2[1]) >> 1; + f1[1] = ((lpc[2 * i] << 16 >> i) + f1[1]) >> 1; + f2[1] = ((lpc[2 * i + 1] << 16 >> i) + f2[1]) >> 1; } /* Convert polynomial coefficients to LPC coefficients */ @@ -434,21 +171,15 @@ static void lsp2lpc(int16_t *lpc) int64_t ff1 = f1[i + 1] + f1[i]; int64_t ff2 = f2[i + 1] - f2[i]; - lpc[i] = av_clipl_int32(((ff1 + ff2) << 3) + (1 << 15)) >> 16; + lpc[i] = av_clipl_int32(((ff1 + ff2) << 3) + + (1 << 15)) >> 16; lpc[LPC_ORDER - i - 1] = av_clipl_int32(((ff1 - ff2) << 3) + (1 << 15)) >> 16; } } -/** - * Quantize LSP frequencies by interpolation and convert them to - * the corresponding LPC coefficients. - * - * @param lpc buffer for LPC coefficients - * @param cur_lsp the current LSP vector - * @param prev_lsp the previous LSP vector - */ -static void lsp_interpolate(int16_t *lpc, int16_t *cur_lsp, int16_t *prev_lsp) +void ff_g723_1_lsp_interpolate(int16_t *lpc, int16_t *cur_lsp, + int16_t *prev_lsp) { int i; int16_t *lpc_ptr = lpc; @@ -468,911 +199,64 @@ static void lsp_interpolate(int16_t *lpc, int16_t *cur_lsp, int16_t *prev_lsp) } } -/** - * Generate a train of dirac functions with period as pitch lag. - */ -static void gen_dirac_train(int16_t *buf, int pitch_lag) +void ff_g723_1_inverse_quant(int16_t *cur_lsp, int16_t *prev_lsp, + uint8_t *lsp_index, int bad_frame) { - int16_t vector[SUBFRAME_LEN]; - int i, j; - - memcpy(vector, buf, SUBFRAME_LEN * sizeof(*vector)); - for (i = pitch_lag; i < SUBFRAME_LEN; i += pitch_lag) { - for (j = 0; j < SUBFRAME_LEN - i; j++) - buf[i + j] += vector[j]; - } -} - -/** - * Generate fixed codebook excitation vector. - * - * @param vector decoded excitation vector - * @param subfrm current subframe - * @param cur_rate current bitrate - * @param pitch_lag closed loop pitch lag - * @param index current subframe index - */ -static void gen_fcb_excitation(int16_t *vector, G723_1_Subframe *subfrm, - enum Rate cur_rate, int pitch_lag, int index) -{ - int temp, i, j; - - memset(vector, 0, SUBFRAME_LEN * sizeof(*vector)); - - if (cur_rate == RATE_6300) { - if (subfrm->pulse_pos >= max_pos[index]) - return; - - /* Decode amplitudes and positions */ - j = PULSE_MAX - pulses[index]; - temp = subfrm->pulse_pos; - for (i = 0; i < SUBFRAME_LEN / GRID_SIZE; i++) { - temp -= combinatorial_table[j][i]; - if (temp >= 0) - continue; - temp += combinatorial_table[j++][i]; - if (subfrm->pulse_sign & (1 << (PULSE_MAX - j))) { - vector[subfrm->grid_index + GRID_SIZE * i] = - -fixed_cb_gain[subfrm->amp_index]; - } else { - vector[subfrm->grid_index + GRID_SIZE * i] = - fixed_cb_gain[subfrm->amp_index]; - } - if (j == PULSE_MAX) - break; - } - if (subfrm->dirac_train == 1) - gen_dirac_train(vector, pitch_lag); - } else { /* 5300 bps */ - int cb_gain = fixed_cb_gain[subfrm->amp_index]; - int cb_shift = subfrm->grid_index; - int cb_sign = subfrm->pulse_sign; - int cb_pos = subfrm->pulse_pos; - int offset, beta, lag; - - for (i = 0; i < 8; i += 2) { - offset = ((cb_pos & 7) << 3) + cb_shift + i; - vector[offset] = (cb_sign & 1) ? cb_gain : -cb_gain; - cb_pos >>= 3; - cb_sign >>= 1; - } - - /* Enhance harmonic components */ - lag = pitch_contrib[subfrm->ad_cb_gain << 1] + pitch_lag + - subfrm->ad_cb_lag - 1; - beta = pitch_contrib[(subfrm->ad_cb_gain << 1) + 1]; - - if (lag < SUBFRAME_LEN - 2) { - for (i = lag; i < SUBFRAME_LEN; i++) - vector[i] += beta * vector[i - lag] >> 15; - } - } -} - -/** - * Get delayed contribution from the previous excitation vector. - */ -static void get_residual(int16_t *residual, int16_t *prev_excitation, int lag) -{ - int offset = PITCH_MAX - PITCH_ORDER / 2 - lag; - int i; - - residual[0] = prev_excitation[offset]; - residual[1] = prev_excitation[offset + 1]; - - offset += 2; - for (i = 2; i < SUBFRAME_LEN + PITCH_ORDER - 1; i++) - residual[i] = prev_excitation[offset + (i - 2) % lag]; -} - -static int dot_product(const int16_t *a, const int16_t *b, int length) -{ - int i, sum = 0; - - for (i = 0; i < length; i++) { - int prod = a[i] * b[i]; - sum = av_sat_dadd32(sum, prod); - } - return sum; -} - -/** - * Generate adaptive codebook excitation. - */ -static void gen_acb_excitation(int16_t *vector, int16_t *prev_excitation, - int pitch_lag, G723_1_Subframe *subfrm, - enum Rate cur_rate) -{ - int16_t residual[SUBFRAME_LEN + PITCH_ORDER - 1]; - const int16_t *cb_ptr; - int lag = pitch_lag + subfrm->ad_cb_lag - 1; - - int i; - int sum; - - get_residual(residual, prev_excitation, lag); - - /* Select quantization table */ - if (cur_rate == RATE_6300 && pitch_lag < SUBFRAME_LEN - 2) - cb_ptr = adaptive_cb_gain85; - else - cb_ptr = adaptive_cb_gain170; - - /* Calculate adaptive vector */ - cb_ptr += subfrm->ad_cb_gain * 20; - for (i = 0; i < SUBFRAME_LEN; i++) { - sum = dot_product(residual + i, cb_ptr, PITCH_ORDER); - vector[i] = av_sat_dadd32(1 << 15, sum) >> 16; - } -} - -/** - * Estimate maximum auto-correlation around pitch lag. - * - * @param buf buffer with offset applied - * @param offset offset of the excitation vector - * @param ccr_max pointer to the maximum auto-correlation - * @param pitch_lag decoded pitch lag - * @param length length of autocorrelation - * @param dir forward lag(1) / backward lag(-1) - */ -static int autocorr_max(const int16_t *buf, int offset, int *ccr_max, - int pitch_lag, int length, int dir) -{ - int limit, ccr, lag = 0; - int i; - - pitch_lag = FFMIN(PITCH_MAX - 3, pitch_lag); - if (dir > 0) - limit = FFMIN(FRAME_LEN + PITCH_MAX - offset - length, pitch_lag + 3); - else - limit = pitch_lag + 3; - - for (i = pitch_lag - 3; i <= limit; i++) { - ccr = dot_product(buf, buf + dir * i, length); - - if (ccr > *ccr_max) { - *ccr_max = ccr; - lag = i; - } - } - return lag; -} - -/** - * Calculate pitch postfilter optimal and scaling gains. - * - * @param lag pitch postfilter forward/backward lag - * @param ppf pitch postfilter parameters - * @param cur_rate current bitrate - * @param tgt_eng target energy - * @param ccr cross-correlation - * @param res_eng residual energy - */ -static void comp_ppf_gains(int lag, PPFParam *ppf, enum Rate cur_rate, - int tgt_eng, int ccr, int res_eng) -{ - int pf_residual; /* square of postfiltered residual */ - int temp1, temp2; - - ppf->index = lag; - - temp1 = tgt_eng * res_eng >> 1; - temp2 = ccr * ccr << 1; - - if (temp2 > temp1) { - if (ccr >= res_eng) { - ppf->opt_gain = ppf_gain_weight[cur_rate]; - } else { - ppf->opt_gain = (ccr << 15) / res_eng * - ppf_gain_weight[cur_rate] >> 15; - } - /* pf_res^2 = tgt_eng + 2*ccr*gain + res_eng*gain^2 */ - temp1 = (tgt_eng << 15) + (ccr * ppf->opt_gain << 1); - temp2 = (ppf->opt_gain * ppf->opt_gain >> 15) * res_eng; - pf_residual = av_sat_add32(temp1, temp2 + (1 << 15)) >> 16; - - if (tgt_eng >= pf_residual << 1) { - temp1 = 0x7fff; - } else { - temp1 = (tgt_eng << 14) / pf_residual; - } - - /* scaling_gain = sqrt(tgt_eng/pf_res^2) */ - ppf->sc_gain = square_root(temp1 << 16); - } else { - ppf->opt_gain = 0; - ppf->sc_gain = 0x7fff; - } - - ppf->opt_gain = av_clip_int16(ppf->opt_gain * ppf->sc_gain >> 15); -} - -/** - * Calculate pitch postfilter parameters. - * - * @param p the context - * @param offset offset of the excitation vector - * @param pitch_lag decoded pitch lag - * @param ppf pitch postfilter parameters - * @param cur_rate current bitrate - */ -static void comp_ppf_coeff(G723_1_Context *p, int offset, int pitch_lag, - PPFParam *ppf, enum Rate cur_rate) -{ - - int16_t scale; - int i; - int temp1, temp2; - - /* - * 0 - target energy - * 1 - forward cross-correlation - * 2 - forward residual energy - * 3 - backward cross-correlation - * 4 - backward residual energy - */ - int energy[5] = {0, 0, 0, 0, 0}; - int16_t *buf = p->audio + LPC_ORDER + offset; - int fwd_lag = autocorr_max(buf, offset, &energy[1], pitch_lag, - SUBFRAME_LEN, 1); - int back_lag = autocorr_max(buf, offset, &energy[3], pitch_lag, - SUBFRAME_LEN, -1); - - ppf->index = 0; - ppf->opt_gain = 0; - ppf->sc_gain = 0x7fff; - - /* Case 0, Section 3.6 */ - if (!back_lag && !fwd_lag) - return; - - /* Compute target energy */ - energy[0] = dot_product(buf, buf, SUBFRAME_LEN); - - /* Compute forward residual energy */ - if (fwd_lag) - energy[2] = dot_product(buf + fwd_lag, buf + fwd_lag, SUBFRAME_LEN); - - /* Compute backward residual energy */ - if (back_lag) - energy[4] = dot_product(buf - back_lag, buf - back_lag, SUBFRAME_LEN); - - /* Normalize and shorten */ - temp1 = 0; - for (i = 0; i < 5; i++) - temp1 = FFMAX(energy[i], temp1); - - scale = normalize_bits(temp1, 31); - for (i = 0; i < 5; i++) - energy[i] = (energy[i] << scale) >> 16; - - if (fwd_lag && !back_lag) { /* Case 1 */ - comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], - energy[2]); - } else if (!fwd_lag) { /* Case 2 */ - comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], - energy[4]); - } else { /* Case 3 */ - - /* - * Select the largest of energy[1]^2/energy[2] - * and energy[3]^2/energy[4] - */ - temp1 = energy[4] * ((energy[1] * energy[1] + (1 << 14)) >> 15); - temp2 = energy[2] * ((energy[3] * energy[3] + (1 << 14)) >> 15); - if (temp1 >= temp2) { - comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], - energy[2]); - } else { - comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], - energy[4]); - } - } -} - -/** - * Classify frames as voiced/unvoiced. - * - * @param p the context - * @param pitch_lag decoded pitch_lag - * @param exc_eng excitation energy estimation - * @param scale scaling factor of exc_eng - * - * @return residual interpolation index if voiced, 0 otherwise - */ -static int comp_interp_index(G723_1_Context *p, int pitch_lag, - int *exc_eng, int *scale) -{ - int offset = PITCH_MAX + 2 * SUBFRAME_LEN; - int16_t *buf = p->audio + LPC_ORDER; - - int index, ccr, tgt_eng, best_eng, temp; - - *scale = scale_vector(buf, p->excitation, FRAME_LEN + PITCH_MAX); - buf += offset; - - /* Compute maximum backward cross-correlation */ - ccr = 0; - index = autocorr_max(buf, offset, &ccr, pitch_lag, SUBFRAME_LEN * 2, -1); - ccr = av_sat_add32(ccr, 1 << 15) >> 16; - - /* Compute target energy */ - tgt_eng = dot_product(buf, buf, SUBFRAME_LEN * 2); - *exc_eng = av_sat_add32(tgt_eng, 1 << 15) >> 16; - - if (ccr <= 0) - return 0; - - /* Compute best energy */ - best_eng = dot_product(buf - index, buf - index, SUBFRAME_LEN * 2); - best_eng = av_sat_add32(best_eng, 1 << 15) >> 16; - - temp = best_eng * *exc_eng >> 3; - - if (temp < ccr * ccr) - return index; - else - return 0; -} - -/** - * Peform residual interpolation based on frame classification. - * - * @param buf decoded excitation vector - * @param out output vector - * @param lag decoded pitch lag - * @param gain interpolated gain - * @param rseed seed for random number generator - */ -static void residual_interp(int16_t *buf, int16_t *out, int lag, - int gain, int *rseed) -{ - int i; - if (lag) { /* Voiced */ - int16_t *vector_ptr = buf + PITCH_MAX; - /* Attenuate */ - for (i = 0; i < lag; i++) - out[i] = vector_ptr[i - lag] * 3 >> 2; - av_memcpy_backptr((uint8_t*)(out + lag), lag * sizeof(*out), - (FRAME_LEN - lag) * sizeof(*out)); - } else { /* Unvoiced */ - for (i = 0; i < FRAME_LEN; i++) { - *rseed = *rseed * 521 + 259; - out[i] = gain * *rseed >> 15; - } - memset(buf, 0, (FRAME_LEN + PITCH_MAX) * sizeof(*buf)); - } -} - -/** - * Perform IIR filtering. - * - * @param fir_coef FIR coefficients - * @param iir_coef IIR coefficients - * @param src source vector - * @param dest destination vector - */ -static inline void iir_filter(int16_t *fir_coef, int16_t *iir_coef, - int16_t *src, int *dest) -{ - int m, n; - - for (m = 0; m < SUBFRAME_LEN; m++) { - int64_t filter = 0; - for (n = 1; n <= LPC_ORDER; n++) { - filter -= fir_coef[n - 1] * src[m - n] - - iir_coef[n - 1] * (dest[m - n] >> 16); - } - - dest[m] = av_clipl_int32((src[m] << 16) + (filter << 3) + (1 << 15)); - } -} - -/** - * Adjust gain of postfiltered signal. - * - * @param p the context - * @param buf postfiltered output vector - * @param energy input energy coefficient - */ -static void gain_scale(G723_1_Context *p, int16_t * buf, int energy) -{ - int num, denom, gain, bits1, bits2; - int i; - - num = energy; - denom = 0; - for (i = 0; i < SUBFRAME_LEN; i++) { - int temp = buf[i] >> 2; - temp *= temp; - denom = av_sat_dadd32(denom, temp); - } - - if (num && denom) { - bits1 = normalize_bits(num, 31); - bits2 = normalize_bits(denom, 31); - num = num << bits1 >> 1; - denom <<= bits2; - - bits2 = 5 + bits1 - bits2; - bits2 = FFMAX(0, bits2); - - gain = (num >> 1) / (denom >> 16); - gain = square_root(gain << 16 >> bits2); - } else { - gain = 1 << 12; - } - - for (i = 0; i < SUBFRAME_LEN; i++) { - p->pf_gain = (15 * p->pf_gain + gain + (1 << 3)) >> 4; - buf[i] = av_clip_int16((buf[i] * (p->pf_gain + (p->pf_gain >> 4)) + - (1 << 10)) >> 11); - } -} - -/** - * Perform formant filtering. - * - * @param p the context - * @param lpc quantized lpc coefficients - * @param buf input buffer - * @param dst output buffer - */ -static void formant_postfilter(G723_1_Context *p, int16_t *lpc, - int16_t *buf, int16_t *dst) -{ - int16_t filter_coef[2][LPC_ORDER]; - int filter_signal[LPC_ORDER + FRAME_LEN], *signal_ptr; - int i, j, k; - - memcpy(buf, p->fir_mem, LPC_ORDER * sizeof(*buf)); - memcpy(filter_signal, p->iir_mem, LPC_ORDER * sizeof(*filter_signal)); - - for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { - for (k = 0; k < LPC_ORDER; k++) { - filter_coef[0][k] = (-lpc[k] * postfilter_tbl[0][k] + - (1 << 14)) >> 15; - filter_coef[1][k] = (-lpc[k] * postfilter_tbl[1][k] + - (1 << 14)) >> 15; - } - iir_filter(filter_coef[0], filter_coef[1], buf + i, - filter_signal + i); - lpc += LPC_ORDER; - } - - memcpy(p->fir_mem, buf + FRAME_LEN, LPC_ORDER * sizeof(*p->fir_mem)); - memcpy(p->iir_mem, filter_signal + FRAME_LEN, - LPC_ORDER * sizeof(*p->iir_mem)); - - buf += LPC_ORDER; - signal_ptr = filter_signal + LPC_ORDER; - for (i = 0; i < SUBFRAMES; i++) { - int temp; - int auto_corr[2]; - int scale, energy; - - /* Normalize */ - scale = scale_vector(dst, buf, SUBFRAME_LEN); - - /* Compute auto correlation coefficients */ - auto_corr[0] = dot_product(dst, dst + 1, SUBFRAME_LEN - 1); - auto_corr[1] = dot_product(dst, dst, SUBFRAME_LEN); - - /* Compute reflection coefficient */ - temp = auto_corr[1] >> 16; - if (temp) { - temp = (auto_corr[0] >> 2) / temp; - } - p->reflection_coef = (3 * p->reflection_coef + temp + 2) >> 2; - temp = -p->reflection_coef >> 1 & ~3; - - /* Compensation filter */ - for (j = 0; j < SUBFRAME_LEN; j++) { - dst[j] = av_sat_dadd32(signal_ptr[j], - (signal_ptr[j - 1] >> 16) * temp) >> 16; - } - - /* Compute normalized signal energy */ - temp = 2 * scale + 4; - if (temp < 0) { - energy = av_clipl_int32((int64_t)auto_corr[1] << -temp); - } else - energy = auto_corr[1] >> temp; - - gain_scale(p, dst, energy); - - buf += SUBFRAME_LEN; - signal_ptr += SUBFRAME_LEN; - dst += SUBFRAME_LEN; - } -} - -static int sid_gain_to_lsp_index(int gain) -{ - if (gain < 0x10) - return gain << 6; - else if (gain < 0x20) - return gain - 8 << 7; - else - return gain - 20 << 8; -} - -static inline int cng_rand(int *state, int base) -{ - *state = (*state * 521 + 259) & 0xFFFF; - return (*state & 0x7FFF) * base >> 15; -} - -static int estimate_sid_gain(G723_1_Context *p) -{ - int i, shift, seg, seg2, t, val, val_add, x, y; - - shift = 16 - p->cur_gain * 2; - if (shift > 0) - t = p->sid_gain << shift; - else - t = p->sid_gain >> -shift; - x = t * cng_filt[0] >> 16; - - if (x >= cng_bseg[2]) - return 0x3F; - - if (x >= cng_bseg[1]) { - shift = 4; - seg = 3; - } else { - shift = 3; - seg = (x >= cng_bseg[0]); - } - seg2 = FFMIN(seg, 3); - - val = 1 << shift; - val_add = val >> 1; - for (i = 0; i < shift; i++) { - t = seg * 32 + (val << seg2); - t *= t; - if (x >= t) - val += val_add; - else - val -= val_add; - val_add >>= 1; - } + int min_dist, pred; + int i, j, temp, stable; - t = seg * 32 + (val << seg2); - y = t * t - x; - if (y <= 0) { - t = seg * 32 + (val + 1 << seg2); - t = t * t - x; - val = (seg2 - 1 << 4) + val; - if (t >= y) - val++; + /* Check for frame erasure */ + if (!bad_frame) { + min_dist = 0x100; + pred = 12288; } else { - t = seg * 32 + (val - 1 << seg2); - t = t * t - x; - val = (seg2 - 1 << 4) + val; - if (t >= y) - val--; - } - - return val; -} - -static void generate_noise(G723_1_Context *p) -{ - int i, j, idx, t; - int off[SUBFRAMES]; - int signs[SUBFRAMES / 2 * 11], pos[SUBFRAMES / 2 * 11]; - int tmp[SUBFRAME_LEN * 2]; - int16_t *vector_ptr; - int64_t sum; - int b0, c, delta, x, shift; - - p->pitch_lag[0] = cng_rand(&p->cng_random_seed, 21) + 123; - p->pitch_lag[1] = cng_rand(&p->cng_random_seed, 19) + 123; - - for (i = 0; i < SUBFRAMES; i++) { - p->subframe[i].ad_cb_gain = cng_rand(&p->cng_random_seed, 50) + 1; - p->subframe[i].ad_cb_lag = cng_adaptive_cb_lag[i]; - } - - for (i = 0; i < SUBFRAMES / 2; i++) { - t = cng_rand(&p->cng_random_seed, 1 << 13); - off[i * 2] = t & 1; - off[i * 2 + 1] = ((t >> 1) & 1) + SUBFRAME_LEN; - t >>= 2; - for (j = 0; j < 11; j++) { - signs[i * 11 + j] = (t & 1) * 2 - 1 << 14; - t >>= 1; - } - } - - idx = 0; - for (i = 0; i < SUBFRAMES; i++) { - for (j = 0; j < SUBFRAME_LEN / 2; j++) - tmp[j] = j; - t = SUBFRAME_LEN / 2; - for (j = 0; j < pulses[i]; j++, idx++) { - int idx2 = cng_rand(&p->cng_random_seed, t); - - pos[idx] = tmp[idx2] * 2 + off[i]; - tmp[idx2] = tmp[--t]; - } - } - - vector_ptr = p->audio + LPC_ORDER; - memcpy(vector_ptr, p->prev_excitation, - PITCH_MAX * sizeof(*p->excitation)); - for (i = 0; i < SUBFRAMES; i += 2) { - gen_acb_excitation(vector_ptr, vector_ptr, - p->pitch_lag[i >> 1], &p->subframe[i], - p->cur_rate); - gen_acb_excitation(vector_ptr + SUBFRAME_LEN, - vector_ptr + SUBFRAME_LEN, - p->pitch_lag[i >> 1], &p->subframe[i + 1], - p->cur_rate); - - t = 0; - for (j = 0; j < SUBFRAME_LEN * 2; j++) - t |= FFABS(vector_ptr[j]); - t = FFMIN(t, 0x7FFF); - if (!t) { - shift = 0; - } else { - shift = -10 + av_log2(t); - if (shift < -2) - shift = -2; - } - sum = 0; - if (shift < 0) { - for (j = 0; j < SUBFRAME_LEN * 2; j++) { - t = vector_ptr[j] << -shift; - sum += t * t; - tmp[j] = t; - } - } else { - for (j = 0; j < SUBFRAME_LEN * 2; j++) { - t = vector_ptr[j] >> shift; - sum += t * t; - tmp[j] = t; - } - } - - b0 = 0; - for (j = 0; j < 11; j++) - b0 += tmp[pos[(i / 2) * 11 + j]] * signs[(i / 2) * 11 + j]; - b0 = b0 * 2 * 2979LL + (1 << 29) >> 30; // approximated division by 11 - - c = p->cur_gain * (p->cur_gain * SUBFRAME_LEN >> 5); - if (shift * 2 + 3 >= 0) - c >>= shift * 2 + 3; - else - c <<= -(shift * 2 + 3); - c = (av_clipl_int32(sum << 1) - c) * 2979LL >> 15; - - delta = b0 * b0 * 2 - c; - if (delta <= 0) { - x = -b0; - } else { - delta = square_root(delta); - x = delta - b0; - t = delta + b0; - if (FFABS(t) < FFABS(x)) - x = -t; - } - shift++; - if (shift < 0) - x >>= -shift; - else - x <<= shift; - x = av_clip(x, -10000, 10000); - - for (j = 0; j < 11; j++) { - idx = (i / 2) * 11 + j; - vector_ptr[pos[idx]] = av_clip_int16(vector_ptr[pos[idx]] + - (x * signs[idx] >> 15)); - } - - /* copy decoded data to serve as a history for the next decoded subframes */ - memcpy(vector_ptr + PITCH_MAX, vector_ptr, - sizeof(*vector_ptr) * SUBFRAME_LEN * 2); - vector_ptr += SUBFRAME_LEN * 2; - } - /* Save the excitation for the next frame */ - memcpy(p->prev_excitation, p->audio + LPC_ORDER + FRAME_LEN, - PITCH_MAX * sizeof(*p->excitation)); -} - -static int g723_1_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - G723_1_Context *p = avctx->priv_data; - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - int dec_mode = buf[0] & 3; - - PPFParam ppf[SUBFRAMES]; - int16_t cur_lsp[LPC_ORDER]; - int16_t lpc[SUBFRAMES * LPC_ORDER]; - int16_t acb_vector[SUBFRAME_LEN]; - int16_t *out; - int bad_frame = 0, i, j, ret; - int16_t *audio = p->audio; - - if (buf_size < frame_size[dec_mode]) { - if (buf_size) - av_log(avctx, AV_LOG_WARNING, - "Expected %d bytes, got %d - skipping packet\n", - frame_size[dec_mode], buf_size); - *got_frame_ptr = 0; - return buf_size; + min_dist = 0x200; + pred = 23552; + lsp_index[0] = lsp_index[1] = lsp_index[2] = 0; } - if (unpack_bitstream(p, buf, buf_size) < 0) { - bad_frame = 1; - if (p->past_frame_type == ACTIVE_FRAME) - p->cur_frame_type = ACTIVE_FRAME; - else - p->cur_frame_type = UNTRANSMITTED_FRAME; - } + /* Get the VQ table entry corresponding to the transmitted index */ + cur_lsp[0] = lsp_band0[lsp_index[0]][0]; + cur_lsp[1] = lsp_band0[lsp_index[0]][1]; + cur_lsp[2] = lsp_band0[lsp_index[0]][2]; + cur_lsp[3] = lsp_band1[lsp_index[1]][0]; + cur_lsp[4] = lsp_band1[lsp_index[1]][1]; + cur_lsp[5] = lsp_band1[lsp_index[1]][2]; + cur_lsp[6] = lsp_band2[lsp_index[2]][0]; + cur_lsp[7] = lsp_band2[lsp_index[2]][1]; + cur_lsp[8] = lsp_band2[lsp_index[2]][2]; + cur_lsp[9] = lsp_band2[lsp_index[2]][3]; - frame->nb_samples = FRAME_LEN; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return ret; + /* Add predicted vector & DC component to the previously quantized vector */ + for (i = 0; i < LPC_ORDER; i++) { + temp = ((prev_lsp[i] - dc_lsp[i]) * pred + (1 << 14)) >> 15; + cur_lsp[i] += dc_lsp[i] + temp; } - out = (int16_t *)frame->data[0]; - - if (p->cur_frame_type == ACTIVE_FRAME) { - if (!bad_frame) - p->erased_frames = 0; - else if (p->erased_frames != 3) - p->erased_frames++; - - inverse_quant(cur_lsp, p->prev_lsp, p->lsp_index, bad_frame); - lsp_interpolate(lpc, cur_lsp, p->prev_lsp); - - /* Save the lsp_vector for the next frame */ - memcpy(p->prev_lsp, cur_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); - - /* Generate the excitation for the frame */ - memcpy(p->excitation, p->prev_excitation, - PITCH_MAX * sizeof(*p->excitation)); - if (!p->erased_frames) { - int16_t *vector_ptr = p->excitation + PITCH_MAX; - - /* Update interpolation gain memory */ - p->interp_gain = fixed_cb_gain[(p->subframe[2].amp_index + - p->subframe[3].amp_index) >> 1]; - for (i = 0; i < SUBFRAMES; i++) { - gen_fcb_excitation(vector_ptr, &p->subframe[i], p->cur_rate, - p->pitch_lag[i >> 1], i); - gen_acb_excitation(acb_vector, &p->excitation[SUBFRAME_LEN * i], - p->pitch_lag[i >> 1], &p->subframe[i], - p->cur_rate); - /* Get the total excitation */ - for (j = 0; j < SUBFRAME_LEN; j++) { - int v = av_clip_int16(vector_ptr[j] << 1); - vector_ptr[j] = av_clip_int16(v + acb_vector[j]); - } - vector_ptr += SUBFRAME_LEN; - } - - vector_ptr = p->excitation + PITCH_MAX; - - p->interp_index = comp_interp_index(p, p->pitch_lag[1], - &p->sid_gain, &p->cur_gain); - - /* Peform pitch postfiltering */ - if (p->postfilter) { - i = PITCH_MAX; - for (j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) - comp_ppf_coeff(p, i, p->pitch_lag[j >> 1], - ppf + j, p->cur_rate); - - for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) - ff_acelp_weighted_vector_sum(p->audio + LPC_ORDER + i, - vector_ptr + i, - vector_ptr + i + ppf[j].index, - ppf[j].sc_gain, - ppf[j].opt_gain, - 1 << 14, 15, SUBFRAME_LEN); - } else { - audio = vector_ptr - LPC_ORDER; - } - - /* Save the excitation for the next frame */ - memcpy(p->prev_excitation, p->excitation + FRAME_LEN, - PITCH_MAX * sizeof(*p->excitation)); - } else { - p->interp_gain = (p->interp_gain * 3 + 2) >> 2; - if (p->erased_frames == 3) { - /* Mute output */ - memset(p->excitation, 0, - (FRAME_LEN + PITCH_MAX) * sizeof(*p->excitation)); - memset(p->prev_excitation, 0, - PITCH_MAX * sizeof(*p->excitation)); - memset(frame->data[0], 0, - (FRAME_LEN + LPC_ORDER) * sizeof(int16_t)); - } else { - int16_t *buf = p->audio + LPC_ORDER; - - /* Regenerate frame */ - residual_interp(p->excitation, buf, p->interp_index, - p->interp_gain, &p->random_seed); + for (i = 0; i < LPC_ORDER; i++) { + cur_lsp[0] = FFMAX(cur_lsp[0], 0x180); + cur_lsp[LPC_ORDER - 1] = FFMIN(cur_lsp[LPC_ORDER - 1], 0x7e00); - /* Save the excitation for the next frame */ - memcpy(p->prev_excitation, buf + (FRAME_LEN - PITCH_MAX), - PITCH_MAX * sizeof(*p->excitation)); + /* Stability check */ + for (j = 1; j < LPC_ORDER; j++) { + temp = min_dist + cur_lsp[j - 1] - cur_lsp[j]; + if (temp > 0) { + temp >>= 1; + cur_lsp[j - 1] -= temp; + cur_lsp[j] += temp; } } - p->cng_random_seed = CNG_RANDOM_SEED; - } else { - if (p->cur_frame_type == SID_FRAME) { - p->sid_gain = sid_gain_to_lsp_index(p->subframe[0].amp_index); - inverse_quant(p->sid_lsp, p->prev_lsp, p->lsp_index, 0); - } else if (p->past_frame_type == ACTIVE_FRAME) { - p->sid_gain = estimate_sid_gain(p); + stable = 1; + for (j = 1; j < LPC_ORDER; j++) { + temp = cur_lsp[j - 1] + min_dist - cur_lsp[j] - 4; + if (temp > 0) { + stable = 0; + break; + } } - - if (p->past_frame_type == ACTIVE_FRAME) - p->cur_gain = p->sid_gain; - else - p->cur_gain = (p->cur_gain * 7 + p->sid_gain) >> 3; - generate_noise(p); - lsp_interpolate(lpc, p->sid_lsp, p->prev_lsp); - /* Save the lsp_vector for the next frame */ - memcpy(p->prev_lsp, p->sid_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); - } - - p->past_frame_type = p->cur_frame_type; - - memcpy(p->audio, p->synth_mem, LPC_ORDER * sizeof(*p->audio)); - for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) - ff_celp_lp_synthesis_filter(p->audio + i, &lpc[j * LPC_ORDER], - audio + i, SUBFRAME_LEN, LPC_ORDER, - 0, 1, 1 << 12); - memcpy(p->synth_mem, p->audio + FRAME_LEN, LPC_ORDER * sizeof(*p->audio)); - - if (p->postfilter) { - formant_postfilter(p, lpc, p->audio, out); - } else { // if output is not postfiltered it should be scaled by 2 - for (i = 0; i < FRAME_LEN; i++) - out[i] = av_clip_int16(p->audio[LPC_ORDER + i] << 1); + if (stable) + break; } - - *got_frame_ptr = 1; - - return frame_size[dec_mode]; + if (!stable) + memcpy(cur_lsp, prev_lsp, LPC_ORDER * sizeof(*cur_lsp)); } - -#define OFFSET(x) offsetof(G723_1_Context, x) -#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM - -static const AVOption options[] = { - { "postfilter", "postfilter on/off", OFFSET(postfilter), AV_OPT_TYPE_INT, - { .i64 = 1 }, 0, 1, AD }, - { NULL } -}; - - -static const AVClass g723_1dec_class = { - .class_name = "G.723.1 decoder", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_g723_1_decoder = { - .name = "g723_1", - .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_G723_1, - .priv_data_size = sizeof(G723_1_Context), - .init = g723_1_decode_init, - .decode = g723_1_decode_frame, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, - .priv_class = &g723_1dec_class, -}; diff --git a/libavcodec/g723_1_data.h b/libavcodec/g723_1.h similarity index 91% rename from libavcodec/g723_1_data.h rename to libavcodec/g723_1.h index 04f8a06..166d897 100644 --- a/libavcodec/g723_1_data.h +++ b/libavcodec/g723_1.h @@ -1,5 +1,5 @@ /* - * G.723.1 compatible decoder data tables. + * G.723.1 common header and data tables * Copyright (c) 2006 Benjamin Larsson * Copyright (c) 2010 Mohamed Naufal Basheer * @@ -22,17 +22,21 @@ /** * @file - * G.723.1 compatible decoder data tables + * G.723.1 types, functions and data tables */ -#ifndef AVCODEC_G723_1_DATA_H -#define AVCODEC_G723_1_DATA_H +#ifndef AVCODEC_G723_1_H +#define AVCODEC_G723_1_H #include +#include "libavutil/log.h" + #define SUBFRAMES 4 #define SUBFRAME_LEN 60 #define FRAME_LEN (SUBFRAME_LEN << 2) +#define HALF_FRAME_LEN (FRAME_LEN / 2) +#define LPC_FRAME (HALF_FRAME_LEN + SUBFRAME_LEN) #define LPC_ORDER 10 #define LSP_BANDS 3 #define LSP_CB_SIZE 256 @@ -44,6 +48,174 @@ #define GAIN_LEVELS 24 #define COS_TBL_SIZE 512 +/** + * Bitexact implementation of 2ab scaled by 1/2^16. + * + * @param a 32 bit multiplicand + * @param b 16 bit multiplier + */ +#define MULL2(a, b) \ + ((((a) >> 16) * (b) << 1) + (((a) & 0xffff) * (b) >> 15)) + +/** + * G723.1 frame types + */ +enum FrameType { + ACTIVE_FRAME, ///< Active speech + SID_FRAME, ///< Silence Insertion Descriptor frame + UNTRANSMITTED_FRAME +}; + +/** + * G723.1 rate values + */ +enum Rate { + RATE_6300, + RATE_5300 +}; + +/** + * G723.1 unpacked data subframe + */ +typedef struct G723_1_Subframe { + int ad_cb_lag; ///< adaptive codebook lag + int ad_cb_gain; + int dirac_train; + int pulse_sign; + int grid_index; + int amp_index; + int pulse_pos; +} G723_1_Subframe; + +/** + * Pitch postfilter parameters + */ +typedef struct PPFParam { + int index; ///< postfilter backward/forward lag + int16_t opt_gain; ///< optimal gain + int16_t sc_gain; ///< scaling gain +} PPFParam; + +/** + * Harmonic filter parameters + */ +typedef struct HFParam { + int index; + int gain; +} HFParam; + +/** + * Optimized fixed codebook excitation parameters + */ +typedef struct FCBParam { + int min_err; + int amp_index; + int grid_index; + int dirac_train; + int pulse_pos[PULSE_MAX]; + int pulse_sign[PULSE_MAX]; +} FCBParam; + +typedef struct g723_1_context { + AVClass *class; + + G723_1_Subframe subframe[4]; + enum FrameType cur_frame_type; + enum FrameType past_frame_type; + enum Rate cur_rate; + uint8_t lsp_index[LSP_BANDS]; + int pitch_lag[2]; + int erased_frames; + + int16_t prev_lsp[LPC_ORDER]; + int16_t sid_lsp[LPC_ORDER]; + int16_t prev_excitation[PITCH_MAX]; + int16_t excitation[PITCH_MAX + FRAME_LEN + 4]; + int16_t synth_mem[LPC_ORDER]; + int16_t fir_mem[LPC_ORDER]; + int iir_mem[LPC_ORDER]; + + int random_seed; + int cng_random_seed; + int interp_index; + int interp_gain; + int sid_gain; + int cur_gain; + int reflection_coef; + int pf_gain; + int postfilter; + + int16_t audio[FRAME_LEN + LPC_ORDER + PITCH_MAX + 4]; + + /* encoder */ + int16_t prev_data[HALF_FRAME_LEN]; + int16_t prev_weight_sig[PITCH_MAX]; + + int16_t hpf_fir_mem; ///< highpass filter fir + int hpf_iir_mem; ///< and iir memories + int16_t perf_fir_mem[LPC_ORDER]; ///< perceptual filter fir + int16_t perf_iir_mem[LPC_ORDER]; ///< and iir memories + + int16_t harmonic_mem[PITCH_MAX]; +} G723_1_Context; + + +/** + * Scale vector contents based on the largest of their absolutes. + */ +int ff_g723_1_scale_vector(int16_t *dst, const int16_t *vector, int length); + +/** + * Calculate the number of left-shifts required for normalizing the input. + * + * @param num input number + * @param width width of the input, 16 bits(0) / 32 bits(1) + */ +int ff_g723_1_normalize_bits(int num, int width); + +int ff_g723_1_dot_product(const int16_t *a, const int16_t *b, int length); + +/** + * Get delayed contribution from the previous excitation vector. + */ +void ff_g723_1_get_residual(int16_t *residual, int16_t *prev_excitation, + int lag); + +/** + * Generate a train of dirac functions with period as pitch lag. + */ +void ff_g723_1_gen_dirac_train(int16_t *buf, int pitch_lag); + + +/** + * Generate adaptive codebook excitation. + */ +void ff_g723_1_gen_acb_excitation(int16_t *vector, int16_t *prev_excitation, + int pitch_lag, G723_1_Subframe *subfrm, + enum Rate cur_rate); +/** + * Quantize LSP frequencies by interpolation and convert them to + * the corresponding LPC coefficients. + * + * @param lpc buffer for LPC coefficients + * @param cur_lsp the current LSP vector + * @param prev_lsp the previous LSP vector + */ +void ff_g723_1_lsp_interpolate(int16_t *lpc, int16_t *cur_lsp, + int16_t *prev_lsp); + +/** + * Perform inverse quantization of LSP frequencies. + * + * @param cur_lsp the current LSP vector + * @param prev_lsp the previous LSP vector + * @param lsp_index VQ indices + * @param bad_frame bad frame flag + */ +void ff_g723_1_inverse_quant(int16_t *cur_lsp, int16_t *prev_lsp, + uint8_t *lsp_index, int bad_frame); + + static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; /* Postfilter gain weighting factors scaled by 2^15 */ @@ -56,7 +228,7 @@ static const int16_t dc_lsp[LPC_ORDER] = { }; /* Cosine table scaled by 2^14 */ -static const int16_t cos_tab[COS_TBL_SIZE] = { +static const int16_t cos_tab[COS_TBL_SIZE + 1] = { 16384, 16383, 16379, 16373, 16364, 16353, 16340, 16324, 16305, 16284, 16261, 16235, 16207, 16176, 16143, 16107, 16069, 16029, 15986, 15941, 15893, 15843, 15791, 15736, @@ -121,6 +293,7 @@ static const int16_t cos_tab[COS_TBL_SIZE] = { 15679, 15736, 15791, 15843, 15893, 15941, 15986, 16029, 16069, 16107, 16143, 16176, 16207, 16235, 16261, 16284, 16305, 16324, 16340, 16353, 16364, 16373, 16379, 16383, + 16384 }; /* LSP VQ tables */ @@ -1191,10 +1364,59 @@ static const int16_t postfilter_tbl[2][LPC_ORDER] = { { 24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845 } }; + +/** + * Hamming window coefficients scaled by 2^15 + */ +static const int16_t hamming_window[LPC_FRAME] = { + 2621, 2631, 2659, 2705, 2770, 2853, 2955, 3074, 3212, 3367, + 3541, 3731, 3939, 4164, 4405, 4663, 4937, 5226, 5531, 5851, + 6186, 6534, 6897, 7273, 7661, 8062, 8475, 8899, 9334, 9780, + 10235, 10699, 11172, 11653, 12141, 12636, 13138, 13645, 14157, 14673, + 15193, 15716, 16242, 16769, 17298, 17827, 18356, 18884, 19411, 19935, + 20457, 20975, 21489, 21999, 22503, 23002, 23494, 23978, 24455, 24924, + 25384, 25834, 26274, 26704, 27122, 27529, 27924, 28306, 28675, 29031, + 29373, 29700, 30012, 30310, 30592, 30857, 31107, 31340, 31557, 31756, + 31938, 32102, 32249, 32377, 32488, 32580, 32654, 32710, 32747, 32766, + 32766, 32747, 32710, 32654, 32580, 32488, 32377, 32249, 32102, 31938, + 31756, 31557, 31340, 31107, 30857, 30592, 30310, 30012, 29700, 29373, + 29031, 28675, 28306, 27924, 27529, 27122, 26704, 26274, 25834, 25384, + 24924, 24455, 23978, 23494, 23002, 22503, 21999, 21489, 20975, 20457, + 19935, 19411, 18884, 18356, 17827, 17298, 16769, 16242, 15716, 15193, + 14673, 14157, 13645, 13138, 12636, 12141, 11653, 11172, 10699, 10235, + 9780, 9334, 8899, 8475, 8062, 7661, 7273, 6897, 6534, 6186, + 5851, 5531, 5226, 4937, 4663, 4405, 4164, 3939, 3731, 3541, + 3367, 3212, 3074, 2955, 2853, 2770, 2705, 2659, 2631, 2621 +}; + +/** + * Binomial window coefficients scaled by 2^15 + */ +static const int16_t binomial_window[LPC_ORDER] = { + 32749, 32695, 32604, 32477, 32315, 32118, 31887, 31622, 31324, 30995 +}; + +/** + * 0.994^i scaled by 2^15 + */ +static const int16_t bandwidth_expand[LPC_ORDER] = { + 32571, 32376, 32182, 31989, 31797, 31606, 31416, 31228, 31040, 30854 +}; + +/** + * 0.5^i scaled by 2^15 + */ +static const int16_t percept_flt_tbl[2][LPC_ORDER] = { + /* Zero part */ + {29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425}, + /* Pole part */ + {16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32} +}; + static const int cng_adaptive_cb_lag[4] = { 1, 0, 1, 3 }; static const int cng_filt[4] = { 273, 998, 499, 333 }; static const int cng_bseg[3] = { 2048, 18432, 231233 }; -#endif /* AVCODEC_G723_1_DATA_H */ +#endif /* AVCODEC_G723_1_H */ diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c new file mode 100644 index 0000000..f50bed1 --- /dev/null +++ b/libavcodec/g723_1dec.c @@ -0,0 +1,1045 @@ +/* + * G.723.1 compatible decoder + * Copyright (c) 2006 Benjamin Larsson + * Copyright (c) 2010 Mohamed Naufal Basheer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * G.723.1 compatible decoder + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#define BITSTREAM_READER_LE +#include "acelp_vectors.h" +#include "avcodec.h" +#include "celp_filters.h" +#include "get_bits.h" +#include "internal.h" +#include "g723_1.h" + +#define CNG_RANDOM_SEED 12345 + +static av_cold int g723_1_decode_init(AVCodecContext *avctx) +{ + G723_1_Context *p = avctx->priv_data; + + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->sample_rate = 8000; + p->pf_gain = 1 << 12; + + memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + memcpy(p->sid_lsp, dc_lsp, LPC_ORDER * sizeof(*p->sid_lsp)); + + p->cng_random_seed = CNG_RANDOM_SEED; + p->past_frame_type = SID_FRAME; + + return 0; +} + +/** + * Unpack the frame into parameters. + * + * @param p the context + * @param buf pointer to the input buffer + * @param buf_size size of the input buffer + */ +static int unpack_bitstream(G723_1_Context *p, const uint8_t *buf, + int buf_size) +{ + GetBitContext gb; + int ad_cb_len; + int temp, info_bits, i; + + init_get_bits(&gb, buf, buf_size * 8); + + /* Extract frame type and rate info */ + info_bits = get_bits(&gb, 2); + + if (info_bits == 3) { + p->cur_frame_type = UNTRANSMITTED_FRAME; + return 0; + } + + /* Extract 24 bit lsp indices, 8 bit for each band */ + p->lsp_index[2] = get_bits(&gb, 8); + p->lsp_index[1] = get_bits(&gb, 8); + p->lsp_index[0] = get_bits(&gb, 8); + + if (info_bits == 2) { + p->cur_frame_type = SID_FRAME; + p->subframe[0].amp_index = get_bits(&gb, 6); + return 0; + } + + /* Extract the info common to both rates */ + p->cur_rate = info_bits ? RATE_5300 : RATE_6300; + p->cur_frame_type = ACTIVE_FRAME; + + p->pitch_lag[0] = get_bits(&gb, 7); + if (p->pitch_lag[0] > 123) /* test if forbidden code */ + return -1; + p->pitch_lag[0] += PITCH_MIN; + p->subframe[1].ad_cb_lag = get_bits(&gb, 2); + + p->pitch_lag[1] = get_bits(&gb, 7); + if (p->pitch_lag[1] > 123) + return -1; + p->pitch_lag[1] += PITCH_MIN; + p->subframe[3].ad_cb_lag = get_bits(&gb, 2); + p->subframe[0].ad_cb_lag = 1; + p->subframe[2].ad_cb_lag = 1; + + for (i = 0; i < SUBFRAMES; i++) { + /* Extract combined gain */ + temp = get_bits(&gb, 12); + ad_cb_len = 170; + p->subframe[i].dirac_train = 0; + if (p->cur_rate == RATE_6300 && p->pitch_lag[i >> 1] < SUBFRAME_LEN - 2) { + p->subframe[i].dirac_train = temp >> 11; + temp &= 0x7FF; + ad_cb_len = 85; + } + p->subframe[i].ad_cb_gain = FASTDIV(temp, GAIN_LEVELS); + if (p->subframe[i].ad_cb_gain < ad_cb_len) { + p->subframe[i].amp_index = temp - p->subframe[i].ad_cb_gain * + GAIN_LEVELS; + } else { + return -1; + } + } + + p->subframe[0].grid_index = get_bits(&gb, 1); + p->subframe[1].grid_index = get_bits(&gb, 1); + p->subframe[2].grid_index = get_bits(&gb, 1); + p->subframe[3].grid_index = get_bits(&gb, 1); + + if (p->cur_rate == RATE_6300) { + skip_bits(&gb, 1); /* skip reserved bit */ + + /* Compute pulse_pos index using the 13-bit combined position index */ + temp = get_bits(&gb, 13); + p->subframe[0].pulse_pos = temp / 810; + + temp -= p->subframe[0].pulse_pos * 810; + p->subframe[1].pulse_pos = FASTDIV(temp, 90); + + temp -= p->subframe[1].pulse_pos * 90; + p->subframe[2].pulse_pos = FASTDIV(temp, 9); + p->subframe[3].pulse_pos = temp - p->subframe[2].pulse_pos * 9; + + p->subframe[0].pulse_pos = (p->subframe[0].pulse_pos << 16) + + get_bits(&gb, 16); + p->subframe[1].pulse_pos = (p->subframe[1].pulse_pos << 14) + + get_bits(&gb, 14); + p->subframe[2].pulse_pos = (p->subframe[2].pulse_pos << 16) + + get_bits(&gb, 16); + p->subframe[3].pulse_pos = (p->subframe[3].pulse_pos << 14) + + get_bits(&gb, 14); + + p->subframe[0].pulse_sign = get_bits(&gb, 6); + p->subframe[1].pulse_sign = get_bits(&gb, 5); + p->subframe[2].pulse_sign = get_bits(&gb, 6); + p->subframe[3].pulse_sign = get_bits(&gb, 5); + } else { /* 5300 bps */ + p->subframe[0].pulse_pos = get_bits(&gb, 12); + p->subframe[1].pulse_pos = get_bits(&gb, 12); + p->subframe[2].pulse_pos = get_bits(&gb, 12); + p->subframe[3].pulse_pos = get_bits(&gb, 12); + + p->subframe[0].pulse_sign = get_bits(&gb, 4); + p->subframe[1].pulse_sign = get_bits(&gb, 4); + p->subframe[2].pulse_sign = get_bits(&gb, 4); + p->subframe[3].pulse_sign = get_bits(&gb, 4); + } + + return 0; +} + +/** + * Bitexact implementation of sqrt(val/2). + */ +static int16_t square_root(int val) +{ + int16_t res = 0; + int16_t exp = 0x4000; + int i; + + for (i = 0; i < 14; i ++) { + int res_exp = res + exp; + if (val >= res_exp * res_exp << 1) + res += exp; + exp >>= 1; + } + return res; +} + +/** + * Bitexact implementation of 2ab scaled by 1/2^16. + * + * @param a 32 bit multiplicand + * @param b 16 bit multiplier + */ +#define MULL2(a, b) \ + ((((a) >> 16) * (b) << 1) + (((a) & 0xffff) * (b) >> 15)) + +/** + * Generate fixed codebook excitation vector. + * + * @param vector decoded excitation vector + * @param subfrm current subframe + * @param cur_rate current bitrate + * @param pitch_lag closed loop pitch lag + * @param index current subframe index + */ +static void gen_fcb_excitation(int16_t *vector, G723_1_Subframe *subfrm, + enum Rate cur_rate, int pitch_lag, int index) +{ + int temp, i, j; + + memset(vector, 0, SUBFRAME_LEN * sizeof(*vector)); + + if (cur_rate == RATE_6300) { + if (subfrm->pulse_pos >= max_pos[index]) + return; + + /* Decode amplitudes and positions */ + j = PULSE_MAX - pulses[index]; + temp = subfrm->pulse_pos; + for (i = 0; i < SUBFRAME_LEN / GRID_SIZE; i++) { + temp -= combinatorial_table[j][i]; + if (temp >= 0) + continue; + temp += combinatorial_table[j++][i]; + if (subfrm->pulse_sign & (1 << (PULSE_MAX - j))) { + vector[subfrm->grid_index + GRID_SIZE * i] = + -fixed_cb_gain[subfrm->amp_index]; + } else { + vector[subfrm->grid_index + GRID_SIZE * i] = + fixed_cb_gain[subfrm->amp_index]; + } + if (j == PULSE_MAX) + break; + } + if (subfrm->dirac_train == 1) + ff_g723_1_gen_dirac_train(vector, pitch_lag); + } else { /* 5300 bps */ + int cb_gain = fixed_cb_gain[subfrm->amp_index]; + int cb_shift = subfrm->grid_index; + int cb_sign = subfrm->pulse_sign; + int cb_pos = subfrm->pulse_pos; + int offset, beta, lag; + + for (i = 0; i < 8; i += 2) { + offset = ((cb_pos & 7) << 3) + cb_shift + i; + vector[offset] = (cb_sign & 1) ? cb_gain : -cb_gain; + cb_pos >>= 3; + cb_sign >>= 1; + } + + /* Enhance harmonic components */ + lag = pitch_contrib[subfrm->ad_cb_gain << 1] + pitch_lag + + subfrm->ad_cb_lag - 1; + beta = pitch_contrib[(subfrm->ad_cb_gain << 1) + 1]; + + if (lag < SUBFRAME_LEN - 2) { + for (i = lag; i < SUBFRAME_LEN; i++) + vector[i] += beta * vector[i - lag] >> 15; + } + } +} + +/** + * Estimate maximum auto-correlation around pitch lag. + * + * @param buf buffer with offset applied + * @param offset offset of the excitation vector + * @param ccr_max pointer to the maximum auto-correlation + * @param pitch_lag decoded pitch lag + * @param length length of autocorrelation + * @param dir forward lag(1) / backward lag(-1) + */ +static int autocorr_max(const int16_t *buf, int offset, int *ccr_max, + int pitch_lag, int length, int dir) +{ + int limit, ccr, lag = 0; + int i; + + pitch_lag = FFMIN(PITCH_MAX - 3, pitch_lag); + if (dir > 0) + limit = FFMIN(FRAME_LEN + PITCH_MAX - offset - length, pitch_lag + 3); + else + limit = pitch_lag + 3; + + for (i = pitch_lag - 3; i <= limit; i++) { + ccr = ff_g723_1_dot_product(buf, buf + dir * i, length); + + if (ccr > *ccr_max) { + *ccr_max = ccr; + lag = i; + } + } + return lag; +} + +/** + * Calculate pitch postfilter optimal and scaling gains. + * + * @param lag pitch postfilter forward/backward lag + * @param ppf pitch postfilter parameters + * @param cur_rate current bitrate + * @param tgt_eng target energy + * @param ccr cross-correlation + * @param res_eng residual energy + */ +static void comp_ppf_gains(int lag, PPFParam *ppf, enum Rate cur_rate, + int tgt_eng, int ccr, int res_eng) +{ + int pf_residual; /* square of postfiltered residual */ + int temp1, temp2; + + ppf->index = lag; + + temp1 = tgt_eng * res_eng >> 1; + temp2 = ccr * ccr << 1; + + if (temp2 > temp1) { + if (ccr >= res_eng) { + ppf->opt_gain = ppf_gain_weight[cur_rate]; + } else { + ppf->opt_gain = (ccr << 15) / res_eng * + ppf_gain_weight[cur_rate] >> 15; + } + /* pf_res^2 = tgt_eng + 2*ccr*gain + res_eng*gain^2 */ + temp1 = (tgt_eng << 15) + (ccr * ppf->opt_gain << 1); + temp2 = (ppf->opt_gain * ppf->opt_gain >> 15) * res_eng; + pf_residual = av_sat_add32(temp1, temp2 + (1 << 15)) >> 16; + + if (tgt_eng >= pf_residual << 1) { + temp1 = 0x7fff; + } else { + temp1 = (tgt_eng << 14) / pf_residual; + } + + /* scaling_gain = sqrt(tgt_eng/pf_res^2) */ + ppf->sc_gain = square_root(temp1 << 16); + } else { + ppf->opt_gain = 0; + ppf->sc_gain = 0x7fff; + } + + ppf->opt_gain = av_clip_int16(ppf->opt_gain * ppf->sc_gain >> 15); +} + +/** + * Calculate pitch postfilter parameters. + * + * @param p the context + * @param offset offset of the excitation vector + * @param pitch_lag decoded pitch lag + * @param ppf pitch postfilter parameters + * @param cur_rate current bitrate + */ +static void comp_ppf_coeff(G723_1_Context *p, int offset, int pitch_lag, + PPFParam *ppf, enum Rate cur_rate) +{ + + int16_t scale; + int i; + int temp1, temp2; + + /* + * 0 - target energy + * 1 - forward cross-correlation + * 2 - forward residual energy + * 3 - backward cross-correlation + * 4 - backward residual energy + */ + int energy[5] = {0, 0, 0, 0, 0}; + int16_t *buf = p->audio + LPC_ORDER + offset; + int fwd_lag = autocorr_max(buf, offset, &energy[1], pitch_lag, + SUBFRAME_LEN, 1); + int back_lag = autocorr_max(buf, offset, &energy[3], pitch_lag, + SUBFRAME_LEN, -1); + + ppf->index = 0; + ppf->opt_gain = 0; + ppf->sc_gain = 0x7fff; + + /* Case 0, Section 3.6 */ + if (!back_lag && !fwd_lag) + return; + + /* Compute target energy */ + energy[0] = ff_g723_1_dot_product(buf, buf, SUBFRAME_LEN); + + /* Compute forward residual energy */ + if (fwd_lag) + energy[2] = ff_g723_1_dot_product(buf + fwd_lag, buf + fwd_lag, + SUBFRAME_LEN); + + /* Compute backward residual energy */ + if (back_lag) + energy[4] = ff_g723_1_dot_product(buf - back_lag, buf - back_lag, + SUBFRAME_LEN); + + /* Normalize and shorten */ + temp1 = 0; + for (i = 0; i < 5; i++) + temp1 = FFMAX(energy[i], temp1); + + scale = ff_g723_1_normalize_bits(temp1, 31); + for (i = 0; i < 5; i++) + energy[i] = (energy[i] << scale) >> 16; + + if (fwd_lag && !back_lag) { /* Case 1 */ + comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], + energy[2]); + } else if (!fwd_lag) { /* Case 2 */ + comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], + energy[4]); + } else { /* Case 3 */ + + /* + * Select the largest of energy[1]^2/energy[2] + * and energy[3]^2/energy[4] + */ + temp1 = energy[4] * ((energy[1] * energy[1] + (1 << 14)) >> 15); + temp2 = energy[2] * ((energy[3] * energy[3] + (1 << 14)) >> 15); + if (temp1 >= temp2) { + comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], + energy[2]); + } else { + comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], + energy[4]); + } + } +} + +/** + * Classify frames as voiced/unvoiced. + * + * @param p the context + * @param pitch_lag decoded pitch_lag + * @param exc_eng excitation energy estimation + * @param scale scaling factor of exc_eng + * + * @return residual interpolation index if voiced, 0 otherwise + */ +static int comp_interp_index(G723_1_Context *p, int pitch_lag, + int *exc_eng, int *scale) +{ + int offset = PITCH_MAX + 2 * SUBFRAME_LEN; + int16_t *buf = p->audio + LPC_ORDER; + + int index, ccr, tgt_eng, best_eng, temp; + + *scale = ff_g723_1_scale_vector(buf, p->excitation, FRAME_LEN + PITCH_MAX); + buf += offset; + + /* Compute maximum backward cross-correlation */ + ccr = 0; + index = autocorr_max(buf, offset, &ccr, pitch_lag, SUBFRAME_LEN * 2, -1); + ccr = av_sat_add32(ccr, 1 << 15) >> 16; + + /* Compute target energy */ + tgt_eng = ff_g723_1_dot_product(buf, buf, SUBFRAME_LEN * 2); + *exc_eng = av_sat_add32(tgt_eng, 1 << 15) >> 16; + + if (ccr <= 0) + return 0; + + /* Compute best energy */ + best_eng = ff_g723_1_dot_product(buf - index, buf - index, + SUBFRAME_LEN * 2); + best_eng = av_sat_add32(best_eng, 1 << 15) >> 16; + + temp = best_eng * *exc_eng >> 3; + + if (temp < ccr * ccr) + return index; + else + return 0; +} + +/** + * Perform residual interpolation based on frame classification. + * + * @param buf decoded excitation vector + * @param out output vector + * @param lag decoded pitch lag + * @param gain interpolated gain + * @param rseed seed for random number generator + */ +static void residual_interp(int16_t *buf, int16_t *out, int lag, + int gain, int *rseed) +{ + int i; + if (lag) { /* Voiced */ + int16_t *vector_ptr = buf + PITCH_MAX; + /* Attenuate */ + for (i = 0; i < lag; i++) + out[i] = vector_ptr[i - lag] * 3 >> 2; + av_memcpy_backptr((uint8_t*)(out + lag), lag * sizeof(*out), + (FRAME_LEN - lag) * sizeof(*out)); + } else { /* Unvoiced */ + for (i = 0; i < FRAME_LEN; i++) { + *rseed = *rseed * 521 + 259; + out[i] = gain * *rseed >> 15; + } + memset(buf, 0, (FRAME_LEN + PITCH_MAX) * sizeof(*buf)); + } +} + +/** + * Perform IIR filtering. + * + * @param fir_coef FIR coefficients + * @param iir_coef IIR coefficients + * @param src source vector + * @param dest destination vector + */ +static void iir_filter(int16_t *fir_coef, int16_t *iir_coef, + int16_t *src, int *dest) +{ + int m, n; + + for (m = 0; m < SUBFRAME_LEN; m++) { + int64_t filter = 0; + for (n = 1; n <= LPC_ORDER; n++) { + filter -= fir_coef[n - 1] * src[m - n] - + iir_coef[n - 1] * (dest[m - n] >> 16); + } + + dest[m] = av_clipl_int32((src[m] << 16) + (filter << 3) + (1 << 15)); + } +} + +/** + * Adjust gain of postfiltered signal. + * + * @param p the context + * @param buf postfiltered output vector + * @param energy input energy coefficient + */ +static void gain_scale(G723_1_Context *p, int16_t * buf, int energy) +{ + int num, denom, gain, bits1, bits2; + int i; + + num = energy; + denom = 0; + for (i = 0; i < SUBFRAME_LEN; i++) { + int temp = buf[i] >> 2; + temp *= temp; + denom = av_sat_dadd32(denom, temp); + } + + if (num && denom) { + bits1 = ff_g723_1_normalize_bits(num, 31); + bits2 = ff_g723_1_normalize_bits(denom, 31); + num = num << bits1 >> 1; + denom <<= bits2; + + bits2 = 5 + bits1 - bits2; + bits2 = FFMAX(0, bits2); + + gain = (num >> 1) / (denom >> 16); + gain = square_root(gain << 16 >> bits2); + } else { + gain = 1 << 12; + } + + for (i = 0; i < SUBFRAME_LEN; i++) { + p->pf_gain = (15 * p->pf_gain + gain + (1 << 3)) >> 4; + buf[i] = av_clip_int16((buf[i] * (p->pf_gain + (p->pf_gain >> 4)) + + (1 << 10)) >> 11); + } +} + +/** + * Perform formant filtering. + * + * @param p the context + * @param lpc quantized lpc coefficients + * @param buf input buffer + * @param dst output buffer + */ +static void formant_postfilter(G723_1_Context *p, int16_t *lpc, + int16_t *buf, int16_t *dst) +{ + int16_t filter_coef[2][LPC_ORDER]; + int filter_signal[LPC_ORDER + FRAME_LEN], *signal_ptr; + int i, j, k; + + memcpy(buf, p->fir_mem, LPC_ORDER * sizeof(*buf)); + memcpy(filter_signal, p->iir_mem, LPC_ORDER * sizeof(*filter_signal)); + + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + for (k = 0; k < LPC_ORDER; k++) { + filter_coef[0][k] = (-lpc[k] * postfilter_tbl[0][k] + + (1 << 14)) >> 15; + filter_coef[1][k] = (-lpc[k] * postfilter_tbl[1][k] + + (1 << 14)) >> 15; + } + iir_filter(filter_coef[0], filter_coef[1], buf + i, filter_signal + i); + lpc += LPC_ORDER; + } + + memcpy(p->fir_mem, buf + FRAME_LEN, LPC_ORDER * sizeof(*p->fir_mem)); + memcpy(p->iir_mem, filter_signal + FRAME_LEN, + LPC_ORDER * sizeof(*p->iir_mem)); + + buf += LPC_ORDER; + signal_ptr = filter_signal + LPC_ORDER; + for (i = 0; i < SUBFRAMES; i++) { + int temp; + int auto_corr[2]; + int scale, energy; + + /* Normalize */ + scale = ff_g723_1_scale_vector(dst, buf, SUBFRAME_LEN); + + /* Compute auto correlation coefficients */ + auto_corr[0] = ff_g723_1_dot_product(dst, dst + 1, SUBFRAME_LEN - 1); + auto_corr[1] = ff_g723_1_dot_product(dst, dst, SUBFRAME_LEN); + + /* Compute reflection coefficient */ + temp = auto_corr[1] >> 16; + if (temp) { + temp = (auto_corr[0] >> 2) / temp; + } + p->reflection_coef = (3 * p->reflection_coef + temp + 2) >> 2; + temp = -p->reflection_coef >> 1 & ~3; + + /* Compensation filter */ + for (j = 0; j < SUBFRAME_LEN; j++) { + dst[j] = av_sat_dadd32(signal_ptr[j], + (signal_ptr[j - 1] >> 16) * temp) >> 16; + } + + /* Compute normalized signal energy */ + temp = 2 * scale + 4; + if (temp < 0) { + energy = av_clipl_int32((int64_t)auto_corr[1] << -temp); + } else + energy = auto_corr[1] >> temp; + + gain_scale(p, dst, energy); + + buf += SUBFRAME_LEN; + signal_ptr += SUBFRAME_LEN; + dst += SUBFRAME_LEN; + } +} + +static int sid_gain_to_lsp_index(int gain) +{ + if (gain < 0x10) + return gain << 6; + else if (gain < 0x20) + return gain - 8 << 7; + else + return gain - 20 << 8; +} + +static inline int cng_rand(int *state, int base) +{ + *state = (*state * 521 + 259) & 0xFFFF; + return (*state & 0x7FFF) * base >> 15; +} + +static int estimate_sid_gain(G723_1_Context *p) +{ + int i, shift, seg, seg2, t, val, val_add, x, y; + + shift = 16 - p->cur_gain * 2; + if (shift > 0) + t = p->sid_gain << shift; + else + t = p->sid_gain >> -shift; + x = t * cng_filt[0] >> 16; + + if (x >= cng_bseg[2]) + return 0x3F; + + if (x >= cng_bseg[1]) { + shift = 4; + seg = 3; + } else { + shift = 3; + seg = (x >= cng_bseg[0]); + } + seg2 = FFMIN(seg, 3); + + val = 1 << shift; + val_add = val >> 1; + for (i = 0; i < shift; i++) { + t = seg * 32 + (val << seg2); + t *= t; + if (x >= t) + val += val_add; + else + val -= val_add; + val_add >>= 1; + } + + t = seg * 32 + (val << seg2); + y = t * t - x; + if (y <= 0) { + t = seg * 32 + (val + 1 << seg2); + t = t * t - x; + val = (seg2 - 1 << 4) + val; + if (t >= y) + val++; + } else { + t = seg * 32 + (val - 1 << seg2); + t = t * t - x; + val = (seg2 - 1 << 4) + val; + if (t >= y) + val--; + } + + return val; +} + +static void generate_noise(G723_1_Context *p) +{ + int i, j, idx, t; + int off[SUBFRAMES]; + int signs[SUBFRAMES / 2 * 11], pos[SUBFRAMES / 2 * 11]; + int tmp[SUBFRAME_LEN * 2]; + int16_t *vector_ptr; + int64_t sum; + int b0, c, delta, x, shift; + + p->pitch_lag[0] = cng_rand(&p->cng_random_seed, 21) + 123; + p->pitch_lag[1] = cng_rand(&p->cng_random_seed, 19) + 123; + + for (i = 0; i < SUBFRAMES; i++) { + p->subframe[i].ad_cb_gain = cng_rand(&p->cng_random_seed, 50) + 1; + p->subframe[i].ad_cb_lag = cng_adaptive_cb_lag[i]; + } + + for (i = 0; i < SUBFRAMES / 2; i++) { + t = cng_rand(&p->cng_random_seed, 1 << 13); + off[i * 2] = t & 1; + off[i * 2 + 1] = ((t >> 1) & 1) + SUBFRAME_LEN; + t >>= 2; + for (j = 0; j < 11; j++) { + signs[i * 11 + j] = (t & 1) * 2 - 1 << 14; + t >>= 1; + } + } + + idx = 0; + for (i = 0; i < SUBFRAMES; i++) { + for (j = 0; j < SUBFRAME_LEN / 2; j++) + tmp[j] = j; + t = SUBFRAME_LEN / 2; + for (j = 0; j < pulses[i]; j++, idx++) { + int idx2 = cng_rand(&p->cng_random_seed, t); + + pos[idx] = tmp[idx2] * 2 + off[i]; + tmp[idx2] = tmp[--t]; + } + } + + vector_ptr = p->audio + LPC_ORDER; + memcpy(vector_ptr, p->prev_excitation, + PITCH_MAX * sizeof(*p->excitation)); + for (i = 0; i < SUBFRAMES; i += 2) { + ff_g723_1_gen_acb_excitation(vector_ptr, vector_ptr, + p->pitch_lag[i >> 1], &p->subframe[i], + p->cur_rate); + ff_g723_1_gen_acb_excitation(vector_ptr + SUBFRAME_LEN, + vector_ptr + SUBFRAME_LEN, + p->pitch_lag[i >> 1], &p->subframe[i + 1], + p->cur_rate); + + t = 0; + for (j = 0; j < SUBFRAME_LEN * 2; j++) + t |= FFABS(vector_ptr[j]); + t = FFMIN(t, 0x7FFF); + if (!t) { + shift = 0; + } else { + shift = -10 + av_log2(t); + if (shift < -2) + shift = -2; + } + sum = 0; + if (shift < 0) { + for (j = 0; j < SUBFRAME_LEN * 2; j++) { + t = vector_ptr[j] << -shift; + sum += t * t; + tmp[j] = t; + } + } else { + for (j = 0; j < SUBFRAME_LEN * 2; j++) { + t = vector_ptr[j] >> shift; + sum += t * t; + tmp[j] = t; + } + } + + b0 = 0; + for (j = 0; j < 11; j++) + b0 += tmp[pos[(i / 2) * 11 + j]] * signs[(i / 2) * 11 + j]; + b0 = b0 * 2 * 2979LL + (1 << 29) >> 30; // approximated division by 11 + + c = p->cur_gain * (p->cur_gain * SUBFRAME_LEN >> 5); + if (shift * 2 + 3 >= 0) + c >>= shift * 2 + 3; + else + c <<= -(shift * 2 + 3); + c = (av_clipl_int32(sum << 1) - c) * 2979LL >> 15; + + delta = b0 * b0 * 2 - c; + if (delta <= 0) { + x = -b0; + } else { + delta = square_root(delta); + x = delta - b0; + t = delta + b0; + if (FFABS(t) < FFABS(x)) + x = -t; + } + shift++; + if (shift < 0) + x >>= -shift; + else + x <<= shift; + x = av_clip(x, -10000, 10000); + + for (j = 0; j < 11; j++) { + idx = (i / 2) * 11 + j; + vector_ptr[pos[idx]] = av_clip_int16(vector_ptr[pos[idx]] + + (x * signs[idx] >> 15)); + } + + /* copy decoded data to serve as a history for the next decoded subframes */ + memcpy(vector_ptr + PITCH_MAX, vector_ptr, + sizeof(*vector_ptr) * SUBFRAME_LEN * 2); + vector_ptr += SUBFRAME_LEN * 2; + } + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, p->audio + LPC_ORDER + FRAME_LEN, + PITCH_MAX * sizeof(*p->excitation)); +} + +static int g723_1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + G723_1_Context *p = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int dec_mode = buf[0] & 3; + + PPFParam ppf[SUBFRAMES]; + int16_t cur_lsp[LPC_ORDER]; + int16_t lpc[SUBFRAMES * LPC_ORDER]; + int16_t acb_vector[SUBFRAME_LEN]; + int16_t *out; + int bad_frame = 0, i, j, ret; + int16_t *audio = p->audio; + + if (buf_size < frame_size[dec_mode]) { + if (buf_size) + av_log(avctx, AV_LOG_WARNING, + "Expected %d bytes, got %d - skipping packet\n", + frame_size[dec_mode], buf_size); + *got_frame_ptr = 0; + return buf_size; + } + + if (unpack_bitstream(p, buf, buf_size) < 0) { + bad_frame = 1; + if (p->past_frame_type == ACTIVE_FRAME) + p->cur_frame_type = ACTIVE_FRAME; + else + p->cur_frame_type = UNTRANSMITTED_FRAME; + } + + frame->nb_samples = FRAME_LEN; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + out = (int16_t *)frame->data[0]; + + if (p->cur_frame_type == ACTIVE_FRAME) { + if (!bad_frame) + p->erased_frames = 0; + else if (p->erased_frames != 3) + p->erased_frames++; + + ff_g723_1_inverse_quant(cur_lsp, p->prev_lsp, p->lsp_index, bad_frame); + ff_g723_1_lsp_interpolate(lpc, cur_lsp, p->prev_lsp); + + /* Save the lsp_vector for the next frame */ + memcpy(p->prev_lsp, cur_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + + /* Generate the excitation for the frame */ + memcpy(p->excitation, p->prev_excitation, + PITCH_MAX * sizeof(*p->excitation)); + if (!p->erased_frames) { + int16_t *vector_ptr = p->excitation + PITCH_MAX; + + /* Update interpolation gain memory */ + p->interp_gain = fixed_cb_gain[(p->subframe[2].amp_index + + p->subframe[3].amp_index) >> 1]; + for (i = 0; i < SUBFRAMES; i++) { + gen_fcb_excitation(vector_ptr, &p->subframe[i], p->cur_rate, + p->pitch_lag[i >> 1], i); + ff_g723_1_gen_acb_excitation(acb_vector, + &p->excitation[SUBFRAME_LEN * i], + p->pitch_lag[i >> 1], + &p->subframe[i], p->cur_rate); + /* Get the total excitation */ + for (j = 0; j < SUBFRAME_LEN; j++) { + int v = av_clip_int16(vector_ptr[j] << 1); + vector_ptr[j] = av_clip_int16(v + acb_vector[j]); + } + vector_ptr += SUBFRAME_LEN; + } + + vector_ptr = p->excitation + PITCH_MAX; + + p->interp_index = comp_interp_index(p, p->pitch_lag[1], + &p->sid_gain, &p->cur_gain); + + /* Perform pitch postfiltering */ + if (p->postfilter) { + i = PITCH_MAX; + for (j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + comp_ppf_coeff(p, i, p->pitch_lag[j >> 1], + ppf + j, p->cur_rate); + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + ff_acelp_weighted_vector_sum(p->audio + LPC_ORDER + i, + vector_ptr + i, + vector_ptr + i + ppf[j].index, + ppf[j].sc_gain, + ppf[j].opt_gain, + 1 << 14, 15, SUBFRAME_LEN); + } else { + audio = vector_ptr - LPC_ORDER; + } + + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, p->excitation + FRAME_LEN, + PITCH_MAX * sizeof(*p->excitation)); + } else { + p->interp_gain = (p->interp_gain * 3 + 2) >> 2; + if (p->erased_frames == 3) { + /* Mute output */ + memset(p->excitation, 0, + (FRAME_LEN + PITCH_MAX) * sizeof(*p->excitation)); + memset(p->prev_excitation, 0, + PITCH_MAX * sizeof(*p->excitation)); + memset(frame->data[0], 0, + (FRAME_LEN + LPC_ORDER) * sizeof(int16_t)); + } else { + int16_t *buf = p->audio + LPC_ORDER; + + /* Regenerate frame */ + residual_interp(p->excitation, buf, p->interp_index, + p->interp_gain, &p->random_seed); + + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, buf + (FRAME_LEN - PITCH_MAX), + PITCH_MAX * sizeof(*p->excitation)); + } + } + p->cng_random_seed = CNG_RANDOM_SEED; + } else { + if (p->cur_frame_type == SID_FRAME) { + p->sid_gain = sid_gain_to_lsp_index(p->subframe[0].amp_index); + ff_g723_1_inverse_quant(p->sid_lsp, p->prev_lsp, p->lsp_index, 0); + } else if (p->past_frame_type == ACTIVE_FRAME) { + p->sid_gain = estimate_sid_gain(p); + } + + if (p->past_frame_type == ACTIVE_FRAME) + p->cur_gain = p->sid_gain; + else + p->cur_gain = (p->cur_gain * 7 + p->sid_gain) >> 3; + generate_noise(p); + ff_g723_1_lsp_interpolate(lpc, p->sid_lsp, p->prev_lsp); + /* Save the lsp_vector for the next frame */ + memcpy(p->prev_lsp, p->sid_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + } + + p->past_frame_type = p->cur_frame_type; + + memcpy(p->audio, p->synth_mem, LPC_ORDER * sizeof(*p->audio)); + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + ff_celp_lp_synthesis_filter(p->audio + i, &lpc[j * LPC_ORDER], + audio + i, SUBFRAME_LEN, LPC_ORDER, + 0, 1, 1 << 12); + memcpy(p->synth_mem, p->audio + FRAME_LEN, LPC_ORDER * sizeof(*p->audio)); + + if (p->postfilter) { + formant_postfilter(p, lpc, p->audio, out); + } else { // if output is not postfiltered it should be scaled by 2 + for (i = 0; i < FRAME_LEN; i++) + out[i] = av_clip_int16(p->audio[LPC_ORDER + i] << 1); + } + + *got_frame_ptr = 1; + + return frame_size[dec_mode]; +} + +#define OFFSET(x) offsetof(G723_1_Context, x) +#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +static const AVOption options[] = { + { "postfilter", "postfilter on/off", OFFSET(postfilter), AV_OPT_TYPE_INT, + { .i64 = 1 }, 0, 1, AD }, + { NULL } +}; + + +static const AVClass g723_1dec_class = { + .class_name = "G.723.1 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_g723_1_decoder = { + .name = "g723_1", + .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_G723_1, + .priv_data_size = sizeof(G723_1_Context), + .init = g723_1_decode_init, + .decode = g723_1_decode_frame, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .priv_class = &g723_1dec_class, +}; diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c new file mode 100644 index 0000000..1ebd465 --- /dev/null +++ b/libavcodec/g723_1enc.c @@ -0,0 +1,1202 @@ +/* + * G.723.1 compatible encoder + * Copyright (c) Mohamed Naufal + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * G.723.1 compatible encoder + */ + +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "celp_math.h" +#include "g723_1.h" +#include "internal.h" + +#define BITSTREAM_WRITER_LE +#include "put_bits.h" + +static av_cold int g723_1_encode_init(AVCodecContext *avctx) +{ + G723_1_Context *p = avctx->priv_data; + + if (avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->bit_rate == 6300) { + p->cur_rate = RATE_6300; + } else if (avctx->bit_rate == 5300) { + av_log(avctx, AV_LOG_ERROR, "Bitrate not supported yet, use 6300\n"); + return AVERROR_PATCHWELCOME; + } else { + av_log(avctx, AV_LOG_ERROR, "Bitrate not supported, use 6300\n"); + return AVERROR(EINVAL); + } + avctx->frame_size = 240; + memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(int16_t)); + + return 0; +} + +/** + * Remove DC component from the input signal. + * + * @param buf input signal + * @param fir zero memory + * @param iir pole memory + */ +static void highpass_filter(int16_t *buf, int16_t *fir, int *iir) +{ + int i; + for (i = 0; i < FRAME_LEN; i++) { + *iir = (buf[i] << 15) + ((-*fir) << 15) + MULL2(*iir, 0x7f00); + *fir = buf[i]; + buf[i] = av_clipl_int32((int64_t) *iir + (1 << 15)) >> 16; + } +} + +/** + * Estimate autocorrelation of the input vector. + * + * @param buf input buffer + * @param autocorr autocorrelation coefficients vector + */ +static void comp_autocorr(int16_t *buf, int16_t *autocorr) +{ + int i, scale, temp; + int16_t vector[LPC_FRAME]; + + ff_g723_1_scale_vector(vector, buf, LPC_FRAME); + + /* Apply the Hamming window */ + for (i = 0; i < LPC_FRAME; i++) + vector[i] = (vector[i] * hamming_window[i] + (1 << 14)) >> 15; + + /* Compute the first autocorrelation coefficient */ + temp = ff_dot_product(vector, vector, LPC_FRAME); + + /* Apply a white noise correlation factor of (1025/1024) */ + temp += temp >> 10; + + /* Normalize */ + scale = ff_g723_1_normalize_bits(temp, 31); + autocorr[0] = av_clipl_int32((int64_t) (temp << scale) + + (1 << 15)) >> 16; + + /* Compute the remaining coefficients */ + if (!autocorr[0]) { + memset(autocorr + 1, 0, LPC_ORDER * sizeof(int16_t)); + } else { + for (i = 1; i <= LPC_ORDER; i++) { + temp = ff_dot_product(vector, vector + i, LPC_FRAME - i); + temp = MULL2((temp << scale), binomial_window[i - 1]); + autocorr[i] = av_clipl_int32((int64_t) temp + (1 << 15)) >> 16; + } + } +} + +/** + * Use Levinson-Durbin recursion to compute LPC coefficients from + * autocorrelation values. + * + * @param lpc LPC coefficients vector + * @param autocorr autocorrelation coefficients vector + * @param error prediction error + */ +static void levinson_durbin(int16_t *lpc, int16_t *autocorr, int16_t error) +{ + int16_t vector[LPC_ORDER]; + int16_t partial_corr; + int i, j, temp; + + memset(lpc, 0, LPC_ORDER * sizeof(int16_t)); + + for (i = 0; i < LPC_ORDER; i++) { + /* Compute the partial correlation coefficient */ + temp = 0; + for (j = 0; j < i; j++) + temp -= lpc[j] * autocorr[i - j - 1]; + temp = ((autocorr[i] << 13) + temp) << 3; + + if (FFABS(temp) >= (error << 16)) + break; + + partial_corr = temp / (error << 1); + + lpc[i] = av_clipl_int32((int64_t) (partial_corr << 14) + + (1 << 15)) >> 16; + + /* Update the prediction error */ + temp = MULL2(temp, partial_corr); + error = av_clipl_int32((int64_t) (error << 16) - temp + + (1 << 15)) >> 16; + + memcpy(vector, lpc, i * sizeof(int16_t)); + for (j = 0; j < i; j++) { + temp = partial_corr * vector[i - j - 1] << 1; + lpc[j] = av_clipl_int32((int64_t) (lpc[j] << 16) - temp + + (1 << 15)) >> 16; + } + } +} + +/** + * Calculate LPC coefficients for the current frame. + * + * @param buf current frame + * @param prev_data 2 trailing subframes of the previous frame + * @param lpc LPC coefficients vector + */ +static void comp_lpc_coeff(int16_t *buf, int16_t *lpc) +{ + int16_t autocorr[(LPC_ORDER + 1) * SUBFRAMES]; + int16_t *autocorr_ptr = autocorr; + int16_t *lpc_ptr = lpc; + int i, j; + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + comp_autocorr(buf + i, autocorr_ptr); + levinson_durbin(lpc_ptr, autocorr_ptr + 1, autocorr_ptr[0]); + + lpc_ptr += LPC_ORDER; + autocorr_ptr += LPC_ORDER + 1; + } +} + +static void lpc2lsp(int16_t *lpc, int16_t *prev_lsp, int16_t *lsp) +{ + int f[LPC_ORDER + 2]; ///< coefficients of the sum and difference + ///< polynomials (F1, F2) ordered as + ///< f1[0], f2[0], ...., f1[5], f2[5] + + int max, shift, cur_val, prev_val, count, p; + int i, j; + int64_t temp; + + /* Initialize f1[0] and f2[0] to 1 in Q25 */ + for (i = 0; i < LPC_ORDER; i++) + lsp[i] = (lpc[i] * bandwidth_expand[i] + (1 << 14)) >> 15; + + /* Apply bandwidth expansion on the LPC coefficients */ + f[0] = f[1] = 1 << 25; + + /* Compute the remaining coefficients */ + for (i = 0; i < LPC_ORDER / 2; i++) { + /* f1 */ + f[2 * i + 2] = -f[2 * i] - ((lsp[i] + lsp[LPC_ORDER - 1 - i]) << 12); + /* f2 */ + f[2 * i + 3] = f[2 * i + 1] - ((lsp[i] - lsp[LPC_ORDER - 1 - i]) << 12); + } + + /* Divide f1[5] and f2[5] by 2 for use in polynomial evaluation */ + f[LPC_ORDER] >>= 1; + f[LPC_ORDER + 1] >>= 1; + + /* Normalize and shorten */ + max = FFABS(f[0]); + for (i = 1; i < LPC_ORDER + 2; i++) + max = FFMAX(max, FFABS(f[i])); + + shift = ff_g723_1_normalize_bits(max, 31); + + for (i = 0; i < LPC_ORDER + 2; i++) + f[i] = av_clipl_int32((int64_t) (f[i] << shift) + (1 << 15)) >> 16; + + /** + * Evaluate F1 and F2 at uniform intervals of pi/256 along the + * unit circle and check for zero crossings. + */ + p = 0; + temp = 0; + for (i = 0; i <= LPC_ORDER / 2; i++) + temp += f[2 * i] * cos_tab[0]; + prev_val = av_clipl_int32(temp << 1); + count = 0; + for (i = 1; i < COS_TBL_SIZE / 2; i++) { + /* Evaluate */ + temp = 0; + for (j = 0; j <= LPC_ORDER / 2; j++) + temp += f[LPC_ORDER - 2 * j + p] * cos_tab[i * j % COS_TBL_SIZE]; + cur_val = av_clipl_int32(temp << 1); + + /* Check for sign change, indicating a zero crossing */ + if ((cur_val ^ prev_val) < 0) { + int abs_cur = FFABS(cur_val); + int abs_prev = FFABS(prev_val); + int sum = abs_cur + abs_prev; + + shift = ff_g723_1_normalize_bits(sum, 31); + sum <<= shift; + abs_prev = abs_prev << shift >> 8; + lsp[count++] = ((i - 1) << 7) + (abs_prev >> 1) / (sum >> 16); + + if (count == LPC_ORDER) + break; + + /* Switch between sum and difference polynomials */ + p ^= 1; + + /* Evaluate */ + temp = 0; + for (j = 0; j <= LPC_ORDER / 2; j++) + temp += f[LPC_ORDER - 2 * j + p] * + cos_tab[i * j % COS_TBL_SIZE]; + cur_val = av_clipl_int32(temp << 1); + } + prev_val = cur_val; + } + + if (count != LPC_ORDER) + memcpy(lsp, prev_lsp, LPC_ORDER * sizeof(int16_t)); +} + +/** + * Quantize the current LSP subvector. + * + * @param num band number + * @param offset offset of the current subvector in an LPC_ORDER vector + * @param size size of the current subvector + */ +#define get_index(num, offset, size) \ +{ \ + int error, max = -1; \ + int16_t temp[4]; \ + int i, j; \ + \ + for (i = 0; i < LSP_CB_SIZE; i++) { \ + for (j = 0; j < size; j++){ \ + temp[j] = (weight[j + (offset)] * lsp_band##num[i][j] + \ + (1 << 14)) >> 15; \ + } \ + error = ff_g723_1_dot_product(lsp + (offset), temp, size) << 1; \ + error -= ff_g723_1_dot_product(lsp_band##num[i], temp, size); \ + if (error > max) { \ + max = error; \ + lsp_index[num] = i; \ + } \ + } \ +} + +/** + * Vector quantize the LSP frequencies. + * + * @param lsp the current lsp vector + * @param prev_lsp the previous lsp vector + */ +static void lsp_quantize(uint8_t *lsp_index, int16_t *lsp, int16_t *prev_lsp) +{ + int16_t weight[LPC_ORDER]; + int16_t min, max; + int shift, i; + + /* Calculate the VQ weighting vector */ + weight[0] = (1 << 20) / (lsp[1] - lsp[0]); + weight[LPC_ORDER - 1] = (1 << 20) / + (lsp[LPC_ORDER - 1] - lsp[LPC_ORDER - 2]); + + for (i = 1; i < LPC_ORDER - 1; i++) { + min = FFMIN(lsp[i] - lsp[i - 1], lsp[i + 1] - lsp[i]); + if (min > 0x20) + weight[i] = (1 << 20) / min; + else + weight[i] = INT16_MAX; + } + + /* Normalize */ + max = 0; + for (i = 0; i < LPC_ORDER; i++) + max = FFMAX(weight[i], max); + + shift = ff_g723_1_normalize_bits(max, 15); + for (i = 0; i < LPC_ORDER; i++) { + weight[i] <<= shift; + } + + /* Compute the VQ target vector */ + for (i = 0; i < LPC_ORDER; i++) { + lsp[i] -= dc_lsp[i] + + (((prev_lsp[i] - dc_lsp[i]) * 12288 + (1 << 14)) >> 15); + } + + get_index(0, 0, 3); + get_index(1, 3, 3); + get_index(2, 6, 4); +} + +/** + * Perform IIR filtering. + * + * @param fir_coef FIR coefficients + * @param iir_coef IIR coefficients + * @param src source vector + * @param dest destination vector + */ +static void iir_filter(int16_t *fir_coef, int16_t *iir_coef, + int16_t *src, int16_t *dest) +{ + int m, n; + + for (m = 0; m < SUBFRAME_LEN; m++) { + int64_t filter = 0; + for (n = 1; n <= LPC_ORDER; n++) { + filter -= fir_coef[n - 1] * src[m - n] - + iir_coef[n - 1] * dest[m - n]; + } + + dest[m] = av_clipl_int32((src[m] << 16) + (filter << 3) + + (1 << 15)) >> 16; + } +} + +/** + * Apply the formant perceptual weighting filter. + * + * @param flt_coef filter coefficients + * @param unq_lpc unquantized lpc vector + */ +static void perceptual_filter(G723_1_Context *p, int16_t *flt_coef, + int16_t *unq_lpc, int16_t *buf) +{ + int16_t vector[FRAME_LEN + LPC_ORDER]; + int i, j, k, l = 0; + + memcpy(buf, p->iir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(vector, p->fir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(vector + LPC_ORDER, buf + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + for (k = 0; k < LPC_ORDER; k++) { + flt_coef[k + 2 * l] = (unq_lpc[k + l] * percept_flt_tbl[0][k] + + (1 << 14)) >> 15; + flt_coef[k + 2 * l + LPC_ORDER] = (unq_lpc[k + l] * + percept_flt_tbl[1][k] + + (1 << 14)) >> 15; + } + iir_filter(flt_coef + 2 * l, flt_coef + 2 * l + LPC_ORDER, + vector + i, buf + i); + l += LPC_ORDER; + } + memcpy(p->iir_mem, buf + FRAME_LEN, sizeof(int16_t) * LPC_ORDER); + memcpy(p->fir_mem, vector + FRAME_LEN, sizeof(int16_t) * LPC_ORDER); +} + +/** + * Estimate the open loop pitch period. + * + * @param buf perceptually weighted speech + * @param start estimation is carried out from this position + */ +static int estimate_pitch(int16_t *buf, int start) +{ + int max_exp = 32; + int max_ccr = 0x4000; + int max_eng = 0x7fff; + int index = PITCH_MIN; + int offset = start - PITCH_MIN + 1; + + int ccr, eng, orig_eng, ccr_eng, exp; + int diff, temp; + + int i; + + orig_eng = ff_dot_product(buf + offset, buf + offset, HALF_FRAME_LEN); + + for (i = PITCH_MIN; i <= PITCH_MAX - 3; i++) { + offset--; + + /* Update energy and compute correlation */ + orig_eng += buf[offset] * buf[offset] - + buf[offset + HALF_FRAME_LEN] * buf[offset + HALF_FRAME_LEN]; + ccr = ff_dot_product(buf + start, buf + offset, HALF_FRAME_LEN); + if (ccr <= 0) + continue; + + /* Split into mantissa and exponent to maintain precision */ + exp = ff_g723_1_normalize_bits(ccr, 31); + ccr = av_clipl_int32((int64_t) (ccr << exp) + (1 << 15)) >> 16; + exp <<= 1; + ccr *= ccr; + temp = ff_g723_1_normalize_bits(ccr, 31); + ccr = ccr << temp >> 16; + exp += temp; + + temp = ff_g723_1_normalize_bits(orig_eng, 31); + eng = av_clipl_int32((int64_t) (orig_eng << temp) + (1 << 15)) >> 16; + exp -= temp; + + if (ccr >= eng) { + exp--; + ccr >>= 1; + } + if (exp > max_exp) + continue; + + if (exp + 1 < max_exp) + goto update; + + /* Equalize exponents before comparison */ + if (exp + 1 == max_exp) + temp = max_ccr >> 1; + else + temp = max_ccr; + ccr_eng = ccr * max_eng; + diff = ccr_eng - eng * temp; + if (diff > 0 && (i - index < PITCH_MIN || diff > ccr_eng >> 2)) { +update: + index = i; + max_exp = exp; + max_ccr = ccr; + max_eng = eng; + } + } + return index; +} + +/** + * Compute harmonic noise filter parameters. + * + * @param buf perceptually weighted speech + * @param pitch_lag open loop pitch period + * @param hf harmonic filter parameters + */ +static void comp_harmonic_coeff(int16_t *buf, int16_t pitch_lag, HFParam *hf) +{ + int ccr, eng, max_ccr, max_eng; + int exp, max, diff; + int energy[15]; + int i, j; + + for (i = 0, j = pitch_lag - 3; j <= pitch_lag + 3; i++, j++) { + /* Compute residual energy */ + energy[i << 1] = ff_dot_product(buf - j, buf - j, SUBFRAME_LEN); + /* Compute correlation */ + energy[(i << 1) + 1] = ff_dot_product(buf, buf - j, SUBFRAME_LEN); + } + + /* Compute target energy */ + energy[14] = ff_dot_product(buf, buf, SUBFRAME_LEN); + + /* Normalize */ + max = 0; + for (i = 0; i < 15; i++) + max = FFMAX(max, FFABS(energy[i])); + + exp = ff_g723_1_normalize_bits(max, 31); + for (i = 0; i < 15; i++) { + energy[i] = av_clipl_int32((int64_t)(energy[i] << exp) + + (1 << 15)) >> 16; + } + + hf->index = -1; + hf->gain = 0; + max_ccr = 1; + max_eng = 0x7fff; + + for (i = 0; i <= 6; i++) { + eng = energy[i << 1]; + ccr = energy[(i << 1) + 1]; + + if (ccr <= 0) + continue; + + ccr = (ccr * ccr + (1 << 14)) >> 15; + diff = ccr * max_eng - eng * max_ccr; + if (diff > 0) { + max_ccr = ccr; + max_eng = eng; + hf->index = i; + } + } + + if (hf->index == -1) { + hf->index = pitch_lag; + return; + } + + eng = energy[14] * max_eng; + eng = (eng >> 2) + (eng >> 3); + ccr = energy[(hf->index << 1) + 1] * energy[(hf->index << 1) + 1]; + if (eng < ccr) { + eng = energy[(hf->index << 1) + 1]; + + if (eng >= max_eng) + hf->gain = 0x2800; + else + hf->gain = ((eng << 15) / max_eng * 0x2800 + (1 << 14)) >> 15; + } + hf->index += pitch_lag - 3; +} + +/** + * Apply the harmonic noise shaping filter. + * + * @param hf filter parameters + */ +static void harmonic_filter(HFParam *hf, const int16_t *src, int16_t *dest) +{ + int i; + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = hf->gain * src[i - hf->index] << 1; + dest[i] = av_clipl_int32((src[i] << 16) - temp + (1 << 15)) >> 16; + } +} + +static void harmonic_noise_sub(HFParam *hf, const int16_t *src, int16_t *dest) +{ + int i; + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = hf->gain * src[i - hf->index] << 1; + dest[i] = av_clipl_int32(((dest[i] - src[i]) << 16) + temp + + (1 << 15)) >> 16; + } +} + +/** + * Combined synthesis and formant perceptual weighting filer. + * + * @param qnt_lpc quantized lpc coefficients + * @param perf_lpc perceptual filter coefficients + * @param perf_fir perceptual filter fir memory + * @param perf_iir perceptual filter iir memory + * @param scale the filter output will be scaled by 2^scale + */ +static void synth_percept_filter(int16_t *qnt_lpc, int16_t *perf_lpc, + int16_t *perf_fir, int16_t *perf_iir, + const int16_t *src, int16_t *dest, int scale) +{ + int i, j; + int16_t buf_16[SUBFRAME_LEN + LPC_ORDER]; + int64_t buf[SUBFRAME_LEN]; + + int16_t *bptr_16 = buf_16 + LPC_ORDER; + + memcpy(buf_16, perf_fir, sizeof(int16_t) * LPC_ORDER); + memcpy(dest - LPC_ORDER, perf_iir, sizeof(int16_t) * LPC_ORDER); + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = 0; + for (j = 1; j <= LPC_ORDER; j++) + temp -= qnt_lpc[j - 1] * bptr_16[i - j]; + + buf[i] = (src[i] << 15) + (temp << 3); + bptr_16[i] = av_clipl_int32(buf[i] + (1 << 15)) >> 16; + } + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t fir = 0, iir = 0; + for (j = 1; j <= LPC_ORDER; j++) { + fir -= perf_lpc[j - 1] * bptr_16[i - j]; + iir += perf_lpc[j + LPC_ORDER - 1] * dest[i - j]; + } + dest[i] = av_clipl_int32(((buf[i] + (fir << 3)) << scale) + (iir << 3) + + (1 << 15)) >> 16; + } + memcpy(perf_fir, buf_16 + SUBFRAME_LEN, sizeof(int16_t) * LPC_ORDER); + memcpy(perf_iir, dest + SUBFRAME_LEN - LPC_ORDER, + sizeof(int16_t) * LPC_ORDER); +} + +/** + * Compute the adaptive codebook contribution. + * + * @param buf input signal + * @param index the current subframe index + */ +static void acb_search(G723_1_Context *p, int16_t *residual, + int16_t *impulse_resp, const int16_t *buf, + int index) +{ + int16_t flt_buf[PITCH_ORDER][SUBFRAME_LEN]; + + const int16_t *cb_tbl = adaptive_cb_gain85; + + int ccr_buf[PITCH_ORDER * SUBFRAMES << 2]; + + int pitch_lag = p->pitch_lag[index >> 1]; + int acb_lag = 1; + int acb_gain = 0; + int odd_frame = index & 1; + int iter = 3 + odd_frame; + int count = 0; + int tbl_size = 85; + + int i, j, k, l, max; + int64_t temp; + + if (!odd_frame) { + if (pitch_lag == PITCH_MIN) + pitch_lag++; + else + pitch_lag = FFMIN(pitch_lag, PITCH_MAX - 5); + } + + for (i = 0; i < iter; i++) { + ff_g723_1_get_residual(residual, p->prev_excitation, pitch_lag + i - 1); + + for (j = 0; j < SUBFRAME_LEN; j++) { + temp = 0; + for (k = 0; k <= j; k++) + temp += residual[PITCH_ORDER - 1 + k] * impulse_resp[j - k]; + flt_buf[PITCH_ORDER - 1][j] = av_clipl_int32((temp << 1) + + (1 << 15)) >> 16; + } + + for (j = PITCH_ORDER - 2; j >= 0; j--) { + flt_buf[j][0] = ((residual[j] << 13) + (1 << 14)) >> 15; + for (k = 1; k < SUBFRAME_LEN; k++) { + temp = (flt_buf[j + 1][k - 1] << 15) + + residual[j] * impulse_resp[k]; + flt_buf[j][k] = av_clipl_int32((temp << 1) + (1 << 15)) >> 16; + } + } + + /* Compute crosscorrelation with the signal */ + for (j = 0; j < PITCH_ORDER; j++) { + temp = ff_dot_product(buf, flt_buf[j], SUBFRAME_LEN); + ccr_buf[count++] = av_clipl_int32(temp << 1); + } + + /* Compute energies */ + for (j = 0; j < PITCH_ORDER; j++) { + ccr_buf[count++] = ff_g723_1_dot_product(flt_buf[j], flt_buf[j], + SUBFRAME_LEN); + } + + for (j = 1; j < PITCH_ORDER; j++) { + for (k = 0; k < j; k++) { + temp = ff_dot_product(flt_buf[j], flt_buf[k], SUBFRAME_LEN); + ccr_buf[count++] = av_clipl_int32(temp << 2); + } + } + } + + /* Normalize and shorten */ + max = 0; + for (i = 0; i < 20 * iter; i++) + max = FFMAX(max, FFABS(ccr_buf[i])); + + temp = ff_g723_1_normalize_bits(max, 31); + + for (i = 0; i < 20 * iter; i++) + ccr_buf[i] = av_clipl_int32((int64_t) (ccr_buf[i] << temp) + + (1 << 15)) >> 16; + + max = 0; + for (i = 0; i < iter; i++) { + /* Select quantization table */ + if (!odd_frame && pitch_lag + i - 1 >= SUBFRAME_LEN - 2 || + odd_frame && pitch_lag >= SUBFRAME_LEN - 2) { + cb_tbl = adaptive_cb_gain170; + tbl_size = 170; + } + + for (j = 0, k = 0; j < tbl_size; j++, k += 20) { + temp = 0; + for (l = 0; l < 20; l++) + temp += ccr_buf[20 * i + l] * cb_tbl[k + l]; + temp = av_clipl_int32(temp); + + if (temp > max) { + max = temp; + acb_gain = j; + acb_lag = i; + } + } + } + + if (!odd_frame) { + pitch_lag += acb_lag - 1; + acb_lag = 1; + } + + p->pitch_lag[index >> 1] = pitch_lag; + p->subframe[index].ad_cb_lag = acb_lag; + p->subframe[index].ad_cb_gain = acb_gain; +} + +/** + * Subtract the adaptive codebook contribution from the input + * to obtain the residual. + * + * @param buf target vector + */ +static void sub_acb_contrib(const int16_t *residual, const int16_t *impulse_resp, + int16_t *buf) +{ + int i, j; + /* Subtract adaptive CB contribution to obtain the residual */ + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = buf[i] << 14; + for (j = 0; j <= i; j++) + temp -= residual[j] * impulse_resp[i - j]; + + buf[i] = av_clipl_int32((temp << 2) + (1 << 15)) >> 16; + } +} + +/** + * Quantize the residual signal using the fixed codebook (MP-MLQ). + * + * @param optim optimized fixed codebook parameters + * @param buf excitation vector + */ +static void get_fcb_param(FCBParam *optim, int16_t *impulse_resp, + int16_t *buf, int pulse_cnt, int pitch_lag) +{ + FCBParam param; + int16_t impulse_r[SUBFRAME_LEN]; + int16_t temp_corr[SUBFRAME_LEN]; + int16_t impulse_corr[SUBFRAME_LEN]; + + int ccr1[SUBFRAME_LEN]; + int ccr2[SUBFRAME_LEN]; + int amp, err, max, max_amp_index, min, scale, i, j, k, l; + + int64_t temp; + + /* Update impulse response */ + memcpy(impulse_r, impulse_resp, sizeof(int16_t) * SUBFRAME_LEN); + param.dirac_train = 0; + if (pitch_lag < SUBFRAME_LEN - 2) { + param.dirac_train = 1; + ff_g723_1_gen_dirac_train(impulse_r, pitch_lag); + } + + for (i = 0; i < SUBFRAME_LEN; i++) + temp_corr[i] = impulse_r[i] >> 1; + + /* Compute impulse response autocorrelation */ + temp = ff_g723_1_dot_product(temp_corr, temp_corr, SUBFRAME_LEN); + + scale = ff_g723_1_normalize_bits(temp, 31); + impulse_corr[0] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16; + + for (i = 1; i < SUBFRAME_LEN; i++) { + temp = ff_g723_1_dot_product(temp_corr + i, temp_corr, + SUBFRAME_LEN - i); + impulse_corr[i] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16; + } + + /* Compute crosscorrelation of impulse response with residual signal */ + scale -= 4; + for (i = 0; i < SUBFRAME_LEN; i++) { + temp = ff_g723_1_dot_product(buf + i, impulse_r, SUBFRAME_LEN - i); + if (scale < 0) + ccr1[i] = temp >> -scale; + else + ccr1[i] = av_clipl_int32(temp << scale); + } + + /* Search loop */ + for (i = 0; i < GRID_SIZE; i++) { + /* Maximize the crosscorrelation */ + max = 0; + for (j = i; j < SUBFRAME_LEN; j += GRID_SIZE) { + temp = FFABS(ccr1[j]); + if (temp >= max) { + max = temp; + param.pulse_pos[0] = j; + } + } + + /* Quantize the gain (max crosscorrelation/impulse_corr[0]) */ + amp = max; + min = 1 << 30; + max_amp_index = GAIN_LEVELS - 2; + for (j = max_amp_index; j >= 2; j--) { + temp = av_clipl_int32((int64_t) fixed_cb_gain[j] * + impulse_corr[0] << 1); + temp = FFABS(temp - amp); + if (temp < min) { + min = temp; + max_amp_index = j; + } + } + + max_amp_index--; + /* Select additional gain values */ + for (j = 1; j < 5; j++) { + for (k = i; k < SUBFRAME_LEN; k += GRID_SIZE) { + temp_corr[k] = 0; + ccr2[k] = ccr1[k]; + } + param.amp_index = max_amp_index + j - 2; + amp = fixed_cb_gain[param.amp_index]; + + param.pulse_sign[0] = (ccr2[param.pulse_pos[0]] < 0) ? -amp : amp; + temp_corr[param.pulse_pos[0]] = 1; + + for (k = 1; k < pulse_cnt; k++) { + max = INT_MIN; + for (l = i; l < SUBFRAME_LEN; l += GRID_SIZE) { + if (temp_corr[l]) + continue; + temp = impulse_corr[FFABS(l - param.pulse_pos[k - 1])]; + temp = av_clipl_int32((int64_t) temp * + param.pulse_sign[k - 1] << 1); + ccr2[l] -= temp; + temp = FFABS(ccr2[l]); + if (temp > max) { + max = temp; + param.pulse_pos[k] = l; + } + } + + param.pulse_sign[k] = (ccr2[param.pulse_pos[k]] < 0) ? + -amp : amp; + temp_corr[param.pulse_pos[k]] = 1; + } + + /* Create the error vector */ + memset(temp_corr, 0, sizeof(int16_t) * SUBFRAME_LEN); + + for (k = 0; k < pulse_cnt; k++) + temp_corr[param.pulse_pos[k]] = param.pulse_sign[k]; + + for (k = SUBFRAME_LEN - 1; k >= 0; k--) { + temp = 0; + for (l = 0; l <= k; l++) { + int prod = av_clipl_int32((int64_t) temp_corr[l] * + impulse_r[k - l] << 1); + temp = av_clipl_int32(temp + prod); + } + temp_corr[k] = temp << 2 >> 16; + } + + /* Compute square of error */ + err = 0; + for (k = 0; k < SUBFRAME_LEN; k++) { + int64_t prod; + prod = av_clipl_int32((int64_t) buf[k] * temp_corr[k] << 1); + err = av_clipl_int32(err - prod); + prod = av_clipl_int32((int64_t) temp_corr[k] * temp_corr[k]); + err = av_clipl_int32(err + prod); + } + + /* Minimize */ + if (err < optim->min_err) { + optim->min_err = err; + optim->grid_index = i; + optim->amp_index = param.amp_index; + optim->dirac_train = param.dirac_train; + + for (k = 0; k < pulse_cnt; k++) { + optim->pulse_sign[k] = param.pulse_sign[k]; + optim->pulse_pos[k] = param.pulse_pos[k]; + } + } + } + } +} + +/** + * Encode the pulse position and gain of the current subframe. + * + * @param optim optimized fixed CB parameters + * @param buf excitation vector + */ +static void pack_fcb_param(G723_1_Subframe *subfrm, FCBParam *optim, + int16_t *buf, int pulse_cnt) +{ + int i, j; + + j = PULSE_MAX - pulse_cnt; + + subfrm->pulse_sign = 0; + subfrm->pulse_pos = 0; + + for (i = 0; i < SUBFRAME_LEN >> 1; i++) { + int val = buf[optim->grid_index + (i << 1)]; + if (!val) { + subfrm->pulse_pos += combinatorial_table[j][i]; + } else { + subfrm->pulse_sign <<= 1; + if (val < 0) + subfrm->pulse_sign++; + j++; + + if (j == PULSE_MAX) + break; + } + } + subfrm->amp_index = optim->amp_index; + subfrm->grid_index = optim->grid_index; + subfrm->dirac_train = optim->dirac_train; +} + +/** + * Compute the fixed codebook excitation. + * + * @param buf target vector + * @param impulse_resp impulse response of the combined filter + */ +static void fcb_search(G723_1_Context *p, int16_t *impulse_resp, + int16_t *buf, int index) +{ + FCBParam optim; + int pulse_cnt = pulses[index]; + int i; + + optim.min_err = 1 << 30; + get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, SUBFRAME_LEN); + + if (p->pitch_lag[index >> 1] < SUBFRAME_LEN - 2) { + get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, + p->pitch_lag[index >> 1]); + } + + /* Reconstruct the excitation */ + memset(buf, 0, sizeof(int16_t) * SUBFRAME_LEN); + for (i = 0; i < pulse_cnt; i++) + buf[optim.pulse_pos[i]] = optim.pulse_sign[i]; + + pack_fcb_param(&p->subframe[index], &optim, buf, pulse_cnt); + + if (optim.dirac_train) + ff_g723_1_gen_dirac_train(buf, p->pitch_lag[index >> 1]); +} + +/** + * Pack the frame parameters into output bitstream. + * + * @param frame output buffer + * @param size size of the buffer + */ +static int pack_bitstream(G723_1_Context *p, AVPacket *avpkt) +{ + PutBitContext pb; + int info_bits = 0; + int i, temp; + + init_put_bits(&pb, avpkt->data, avpkt->size); + + put_bits(&pb, 2, info_bits); + + put_bits(&pb, 8, p->lsp_index[2]); + put_bits(&pb, 8, p->lsp_index[1]); + put_bits(&pb, 8, p->lsp_index[0]); + + put_bits(&pb, 7, p->pitch_lag[0] - PITCH_MIN); + put_bits(&pb, 2, p->subframe[1].ad_cb_lag); + put_bits(&pb, 7, p->pitch_lag[1] - PITCH_MIN); + put_bits(&pb, 2, p->subframe[3].ad_cb_lag); + + /* Write 12 bit combined gain */ + for (i = 0; i < SUBFRAMES; i++) { + temp = p->subframe[i].ad_cb_gain * GAIN_LEVELS + + p->subframe[i].amp_index; + if (p->cur_rate == RATE_6300) + temp += p->subframe[i].dirac_train << 11; + put_bits(&pb, 12, temp); + } + + put_bits(&pb, 1, p->subframe[0].grid_index); + put_bits(&pb, 1, p->subframe[1].grid_index); + put_bits(&pb, 1, p->subframe[2].grid_index); + put_bits(&pb, 1, p->subframe[3].grid_index); + + if (p->cur_rate == RATE_6300) { + skip_put_bits(&pb, 1); /* reserved bit */ + + /* Write 13 bit combined position index */ + temp = (p->subframe[0].pulse_pos >> 16) * 810 + + (p->subframe[1].pulse_pos >> 14) * 90 + + (p->subframe[2].pulse_pos >> 16) * 9 + + (p->subframe[3].pulse_pos >> 14); + put_bits(&pb, 13, temp); + + put_bits(&pb, 16, p->subframe[0].pulse_pos & 0xffff); + put_bits(&pb, 14, p->subframe[1].pulse_pos & 0x3fff); + put_bits(&pb, 16, p->subframe[2].pulse_pos & 0xffff); + put_bits(&pb, 14, p->subframe[3].pulse_pos & 0x3fff); + + put_bits(&pb, 6, p->subframe[0].pulse_sign); + put_bits(&pb, 5, p->subframe[1].pulse_sign); + put_bits(&pb, 6, p->subframe[2].pulse_sign); + put_bits(&pb, 5, p->subframe[3].pulse_sign); + } + + flush_put_bits(&pb); + return frame_size[info_bits]; +} + +static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + G723_1_Context *p = avctx->priv_data; + int16_t unq_lpc[LPC_ORDER * SUBFRAMES]; + int16_t qnt_lpc[LPC_ORDER * SUBFRAMES]; + int16_t cur_lsp[LPC_ORDER]; + int16_t weighted_lpc[LPC_ORDER * SUBFRAMES << 1]; + int16_t vector[FRAME_LEN + PITCH_MAX]; + int offset, ret, i, j; + int16_t *in, *start; + HFParam hf[4]; + + /* duplicate input */ + start = in = av_malloc(frame->nb_samples * sizeof(int16_t)); + if (!in) + return AVERROR(ENOMEM); + memcpy(in, frame->data[0], frame->nb_samples * sizeof(int16_t)); + + highpass_filter(in, &p->hpf_fir_mem, &p->hpf_iir_mem); + + memcpy(vector, p->prev_data, HALF_FRAME_LEN * sizeof(int16_t)); + memcpy(vector + HALF_FRAME_LEN, in, FRAME_LEN * sizeof(int16_t)); + + comp_lpc_coeff(vector, unq_lpc); + lpc2lsp(&unq_lpc[LPC_ORDER * 3], p->prev_lsp, cur_lsp); + lsp_quantize(p->lsp_index, cur_lsp, p->prev_lsp); + + /* Update memory */ + memcpy(vector + LPC_ORDER, p->prev_data + SUBFRAME_LEN, + sizeof(int16_t) * SUBFRAME_LEN); + memcpy(vector + LPC_ORDER + SUBFRAME_LEN, in, + sizeof(int16_t) * (HALF_FRAME_LEN + SUBFRAME_LEN)); + memcpy(p->prev_data, in + HALF_FRAME_LEN, + sizeof(int16_t) * HALF_FRAME_LEN); + memcpy(in, vector + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + + perceptual_filter(p, weighted_lpc, unq_lpc, vector); + + memcpy(in, vector + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + memcpy(vector, p->prev_weight_sig, sizeof(int16_t) * PITCH_MAX); + memcpy(vector + PITCH_MAX, in, sizeof(int16_t) * FRAME_LEN); + + ff_g723_1_scale_vector(vector, vector, FRAME_LEN + PITCH_MAX); + + p->pitch_lag[0] = estimate_pitch(vector, PITCH_MAX); + p->pitch_lag[1] = estimate_pitch(vector, PITCH_MAX + HALF_FRAME_LEN); + + for (i = PITCH_MAX, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + comp_harmonic_coeff(vector + i, p->pitch_lag[j >> 1], hf + j); + + memcpy(vector, p->prev_weight_sig, sizeof(int16_t) * PITCH_MAX); + memcpy(vector + PITCH_MAX, in, sizeof(int16_t) * FRAME_LEN); + memcpy(p->prev_weight_sig, vector + FRAME_LEN, sizeof(int16_t) * PITCH_MAX); + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + harmonic_filter(hf + j, vector + PITCH_MAX + i, in + i); + + ff_g723_1_inverse_quant(cur_lsp, p->prev_lsp, p->lsp_index, 0); + ff_g723_1_lsp_interpolate(qnt_lpc, cur_lsp, p->prev_lsp); + + memcpy(p->prev_lsp, cur_lsp, sizeof(int16_t) * LPC_ORDER); + + offset = 0; + for (i = 0; i < SUBFRAMES; i++) { + int16_t impulse_resp[SUBFRAME_LEN]; + int16_t residual[SUBFRAME_LEN + PITCH_ORDER - 1]; + int16_t flt_in[SUBFRAME_LEN]; + int16_t zero[LPC_ORDER], fir[LPC_ORDER], iir[LPC_ORDER]; + + /** + * Compute the combined impulse response of the synthesis filter, + * formant perceptual weighting filter and harmonic noise shaping filter + */ + memset(zero, 0, sizeof(int16_t) * LPC_ORDER); + memset(vector, 0, sizeof(int16_t) * PITCH_MAX); + memset(flt_in, 0, sizeof(int16_t) * SUBFRAME_LEN); + + flt_in[0] = 1 << 13; /* Unit impulse */ + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + zero, zero, flt_in, vector + PITCH_MAX, 1); + harmonic_filter(hf + i, vector + PITCH_MAX, impulse_resp); + + /* Compute the combined zero input response */ + flt_in[0] = 0; + memcpy(fir, p->perf_fir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(iir, p->perf_iir_mem, sizeof(int16_t) * LPC_ORDER); + + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + fir, iir, flt_in, vector + PITCH_MAX, 0); + memcpy(vector, p->harmonic_mem, sizeof(int16_t) * PITCH_MAX); + harmonic_noise_sub(hf + i, vector + PITCH_MAX, in); + + acb_search(p, residual, impulse_resp, in, i); + ff_g723_1_gen_acb_excitation(residual, p->prev_excitation, + p->pitch_lag[i >> 1], &p->subframe[i], + RATE_6300); + sub_acb_contrib(residual, impulse_resp, in); + + fcb_search(p, impulse_resp, in, i); + + /* Reconstruct the excitation */ + ff_g723_1_gen_acb_excitation(impulse_resp, p->prev_excitation, + p->pitch_lag[i >> 1], &p->subframe[i], + RATE_6300); + + memmove(p->prev_excitation, p->prev_excitation + SUBFRAME_LEN, + sizeof(int16_t) * (PITCH_MAX - SUBFRAME_LEN)); + for (j = 0; j < SUBFRAME_LEN; j++) + in[j] = av_clip_int16((in[j] << 1) + impulse_resp[j]); + memcpy(p->prev_excitation + PITCH_MAX - SUBFRAME_LEN, in, + sizeof(int16_t) * SUBFRAME_LEN); + + /* Update filter memories */ + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + p->perf_fir_mem, p->perf_iir_mem, + in, vector + PITCH_MAX, 0); + memmove(p->harmonic_mem, p->harmonic_mem + SUBFRAME_LEN, + sizeof(int16_t) * (PITCH_MAX - SUBFRAME_LEN)); + memcpy(p->harmonic_mem + PITCH_MAX - SUBFRAME_LEN, vector + PITCH_MAX, + sizeof(int16_t) * SUBFRAME_LEN); + + in += SUBFRAME_LEN; + offset += LPC_ORDER; + } + + av_free(start); + + ret = ff_alloc_packet(avpkt, 24); + if (ret < 0) + return ret; + + *got_packet_ptr = 1; + return pack_bitstream(p, avpkt); +} + +AVCodec ff_g723_1_encoder = { + .name = "g723_1", + .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_G723_1, + .priv_data_size = sizeof(G723_1_Context), + .init = g723_1_encode_init, + .encode2 = g723_1_encode_frame, + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE + }, +}; diff --git a/libavcodec/g726.c b/libavcodec/g726.c index 62aeb79..e783e74 100644 --- a/libavcodec/g726.c +++ b/libavcodec/g726.c @@ -23,7 +23,6 @@ */ #include -#include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -32,15 +31,15 @@ #include "put_bits.h" /** - * G.726 11bit float. - * G.726 Standard uses rather odd 11bit floating point arithmentic for + * G.726 11-bit float. + * G.726 Standard uses rather odd 11-bit floating point arithmetic for * numerous occasions. It's a mystery to me why they did it this way - * instead of simply using 32bit integer arithmetic. + * instead of simply using 32-bit integer arithmetic. */ typedef struct Float11 { - uint8_t sign; /**< 1bit sign */ - uint8_t exp; /**< 4bit exponent */ - uint8_t mant; /**< 6bit mantissa */ + uint8_t sign; /**< 1 bit sign */ + uint8_t exp; /**< 4 bits exponent */ + uint8_t mant; /**< 6 bits mantissa */ } Float11; static inline Float11* i2f(int i, Float11* f) @@ -98,7 +97,7 @@ typedef struct G726Context { int code_size; } G726Context; -static const int quant_tbl16[] = /**< 16kbit/s 2bits per sample */ +static const int quant_tbl16[] = /**< 16kbit/s 2 bits per sample */ { 260, INT_MAX }; static const int16_t iquant_tbl16[] = { 116, 365, 365, 116 }; @@ -107,7 +106,7 @@ static const int16_t W_tbl16[] = static const uint8_t F_tbl16[] = { 0, 7, 7, 0 }; -static const int quant_tbl24[] = /**< 24kbit/s 3bits per sample */ +static const int quant_tbl24[] = /**< 24kbit/s 3 bits per sample */ { 7, 217, 330, INT_MAX }; static const int16_t iquant_tbl24[] = { INT16_MIN, 135, 273, 373, 373, 273, 135, INT16_MIN }; @@ -116,7 +115,7 @@ static const int16_t W_tbl24[] = static const uint8_t F_tbl24[] = { 0, 1, 2, 7, 7, 2, 1, 0 }; -static const int quant_tbl32[] = /**< 32kbit/s 4bits per sample */ +static const int quant_tbl32[] = /**< 32kbit/s 4 bits per sample */ { -125, 79, 177, 245, 299, 348, 399, INT_MAX }; static const int16_t iquant_tbl32[] = { INT16_MIN, 4, 135, 213, 273, 323, 373, 425, @@ -127,7 +126,7 @@ static const int16_t W_tbl32[] = static const uint8_t F_tbl32[] = { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 }; -static const int quant_tbl40[] = /**< 40kbit/s 5bits per sample */ +static const int quant_tbl40[] = /**< 40kbit/s 5 bits per sample */ { -122, -16, 67, 138, 197, 249, 297, 338, 377, 412, 444, 474, 501, 527, 552, INT_MAX }; static const int16_t iquant_tbl40[] = @@ -152,7 +151,7 @@ static const G726Tables G726Tables_pool[] = /** - * Para 4.2.2 page 18: Adaptive quantizer. + * Paragraph 4.2.2 page 18: Adaptive quantizer. */ static inline uint8_t quant(G726Context* c, int d) { @@ -178,14 +177,14 @@ static inline uint8_t quant(G726Context* c, int d) } /** - * Para 4.2.3 page 22: Inverse adaptive quantizer. + * Paragraph 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 */ + dex = (dql>>7) & 0xf; /* 4-bit exponent */ dqt = (1<<7) + (dql & 0x7f); /* log2 -> linear */ return (dql < 0) ? 0 : ((dqt<> 7); } @@ -218,7 +217,7 @@ static int16_t g726_decode(G726Context* c, int I) c->b[i] = 0; } else { /* This is a bit crazy, but it really is +255 not +256 */ - fa1 = av_clip((-c->a[0]*c->pk[0]*pk0)>>5, -256, 255); + fa1 = av_clip_intp2((-c->a[0]*c->pk[0]*pk0)>>5, 8); c->a[1] += 128*pk0*c->pk[1] + fa1 - (c->a[1]>>7); c->a[1] = av_clip(c->a[1], -12288, 12288); @@ -315,7 +314,11 @@ static av_cold int g726_encode_init(AVCodecContext *avctx) "Resample or reduce the compliance level.\n"); return AVERROR(EINVAL); } - av_assert0(avctx->sample_rate > 0); + if (avctx->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } if(avctx->channels != 1){ av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); @@ -390,7 +393,7 @@ AVCodec ff_adpcm_g726_encoder = { .priv_data_size = sizeof(G726Context), .init = g726_encode_init, .encode2 = g726_encode_frame, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .priv_class = &class, @@ -467,6 +470,6 @@ AVCodec ff_adpcm_g726_decoder = { .init = g726_decode_init, .decode = g726_decode_frame, .flush = g726_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 5a0089a..b225c13 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -32,6 +32,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "mathops.h" +#include "vlc.h" /* * Safe bitstream reading: @@ -59,20 +60,6 @@ typedef struct GetBitContext { #endif } GetBitContext; -#define VLC_TYPE int16_t - -typedef struct VLC { - int bits; - VLC_TYPE (*table)[2]; ///< code, bits - int table_size, table_allocated; -} VLC; - -typedef struct RL_VLC_ELEM { - int16_t level; - int8_t len; - uint8_t run; -} RL_VLC_ELEM; - /* Bitstream reader API docs: * name * arbitrary name which is used as prefix for the internal variables @@ -92,7 +79,7 @@ typedef struct RL_VLC_ELEM { * * GET_CACHE(name, gb) * Will output the contents of the internal cache, - * next bit is MSB of 32 or 64 bit (FIXME 64bit). + * next bit is MSB of 32 or 64 bits (FIXME 64 bits). * * SHOW_UBITS(name, gb, num) * Will return the next num bits. @@ -123,19 +110,20 @@ typedef struct RL_VLC_ELEM { # define MIN_CACHE_BITS 25 #endif -#if UNCHECKED_BITSTREAM_READER -#define OPEN_READER(name, gb) \ +#define OPEN_READER_NOSIZE(name, gb) \ unsigned int name ## _index = (gb)->index; \ unsigned int av_unused name ## _cache = 0 -#define HAVE_BITS_REMAINING(name, gb) 1 +#if UNCHECKED_BITSTREAM_READER +#define OPEN_READER(name, gb) OPEN_READER_NOSIZE(name, gb) + +#define BITS_AVAILABLE(name, gb) 1 #else #define OPEN_READER(name, gb) \ - unsigned int name ## _index = (gb)->index; \ - unsigned int av_unused name ## _cache = 0; \ - unsigned int av_unused name ## _size_plus8 = (gb)->size_in_bits_plus8 + OPEN_READER_NOSIZE(name, gb); \ + unsigned int name ## _size_plus8 = (gb)->size_in_bits_plus8 -#define HAVE_BITS_REMAINING(name, gb) name ## _index < name ## _size_plus8 +#define BITS_AVAILABLE(name, gb) name ## _index < name ## _size_plus8 #endif #define CLOSE_READER(name, gb) (gb)->index = name ## _index @@ -206,7 +194,7 @@ static inline void skip_bits_long(GetBitContext *s, int n) } /** - * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * Read MPEG-1 dc-style VLC (sign bit + mantisse with no MSB). * if MSB not set it is negative * @param n length in bits */ @@ -249,12 +237,20 @@ static inline unsigned int get_bits(GetBitContext *s, int n) } /** + * Read 0-25 bits. + */ +static av_always_inline int get_bitsz(GetBitContext *s, int n) +{ + return n ? get_bits(s, n) : 0; +} + +/** * Show 1-25 bits. */ static inline unsigned int show_bits(GetBitContext *s, int n) { register int tmp; - OPEN_READER(re, s); + OPEN_READER_NOSIZE(re, s); UPDATE_CACHE(re, s); tmp = SHOW_UBITS(re, s, n); return tmp; @@ -355,18 +351,9 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n) } } -static inline int check_marker(GetBitContext *s, const char *msg) -{ - int bit = get_bits1(s); - if (!bit) - av_log(NULL, AV_LOG_INFO, "Marker bit missing %s\n", msg); - - return bit; -} - /** * Initialize GetBitContext. - * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes * larger than the actual read bits because some optimized bitstream * readers read 32 or 64 bit at once and could read over the end * @param bit_size the size of the buffer in bits @@ -379,7 +366,7 @@ static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, int ret = 0; if (bit_size > INT_MAX - 7 || bit_size < 0 || !buffer) { - buffer_size = bit_size = 0; + bit_size = 0; buffer = NULL; ret = AVERROR_INVALIDDATA; } @@ -399,7 +386,7 @@ static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, /** * Initialize GetBitContext. - * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes * larger than the actual read bits because some optimized bitstream * readers read 32 or 64 bit at once and could read over the end * @param byte_size the size of the buffer in bytes @@ -421,33 +408,6 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) return s->buffer + (s->index >> 3); } -#define init_vlc(vlc, nb_bits, nb_codes, \ - bits, bits_wrap, bits_size, \ - codes, codes_wrap, codes_size, \ - flags) \ - ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \ - bits, bits_wrap, bits_size, \ - codes, codes_wrap, codes_size, \ - NULL, 0, 0, flags) - -int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, - const void *bits, int bits_wrap, int bits_size, - const void *codes, int codes_wrap, int codes_size, - const void *symbols, int symbols_wrap, int symbols_size, - int flags); -void ff_free_vlc(VLC *vlc); - -#define INIT_VLC_LE 2 -#define INIT_VLC_USE_NEW_STATIC 4 - -#define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \ - do { \ - static VLC_TYPE table[static_size][2]; \ - (vlc)->table = table; \ - (vlc)->table_allocated = static_size; \ - init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \ - } while (0) - /** * If the vlc code is invalid and max_depth=1, then no bits will be removed. * If the vlc code is invalid and max_depth>1, then the number of bits removed @@ -506,6 +466,17 @@ void ff_free_vlc(VLC *vlc); index = SHOW_UBITS(name, gb, nb_bits) + level; \ level = table[index].level; \ n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_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); \ @@ -557,73 +528,4 @@ static inline int get_bits_left(GetBitContext *gb) return gb->size_in_bits - get_bits_count(gb); } -//#define TRACE - -#ifdef TRACE -static inline void print_bin(int bits, int n) -{ - int i; - - for (i = n - 1; i >= 0; i--) - av_log(NULL, AV_LOG_DEBUG, "%d", (bits >> i) & 1); - for (i = n; i < 24; i++) - av_log(NULL, AV_LOG_DEBUG, " "); -} - -static inline int get_bits_trace(GetBitContext *s, int n, const char *file, - const char *func, int line) -{ - int r = get_bits(s, n); - - print_bin(r, n); - av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n", - r, n, r, get_bits_count(s) - n, file, func, line); - - return r; -} - -static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], - int bits, int max_depth, const char *file, - const char *func, int line) -{ - int show = show_bits(s, 24); - int pos = get_bits_count(s); - int r = get_vlc2(s, table, bits, max_depth); - int len = get_bits_count(s) - pos; - int bits2 = show >> (24 - len); - - print_bin(bits2, len); - - av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n", - bits2, len, r, pos, file, func, line); - - return r; -} - -static inline int get_xbits_trace(GetBitContext *s, int n, const char *file, - const char *func, int line) -{ - int show = show_bits(s, n); - int r = get_xbits(s, n); - - print_bin(show, n); - av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n", - show, n, r, get_bits_count(s) - n, file, func, line); - - return r; -} - -#define get_bits(s, n) get_bits_trace(s , n, __FILE__, __PRETTY_FUNCTION__, __LINE__) -#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) -#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) - -#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) -#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) - -#define tprintf(p, ...) av_log(p, AV_LOG_DEBUG, __VA_ARGS__) - -#else //TRACE -#define tprintf(p, ...) { } -#endif - #endif /* AVCODEC_GET_BITS_H */ diff --git a/libavcodec/gif.c b/libavcodec/gif.c index c6c37b6..451e335 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -52,7 +52,7 @@ #include "put_bits.h" -typedef struct { +typedef struct GIFContext { LZWState *lzw; uint8_t *buf; } GIFContext; @@ -130,12 +130,12 @@ static av_cold int gif_encode_init(AVCodecContext *avctx) { GIFContext *s = avctx->priv_data; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->lzw = av_mallocz(ff_lzw_encode_state_size); if (!s->lzw) @@ -153,7 +153,7 @@ static int gif_encode_frame(AVCodecContext *avctx, AVPacket *pkt, uint8_t *outbuf_ptr, *end; int ret; - if ((ret = ff_alloc_packet(pkt, avctx->width*avctx->height*7/5 + FF_MIN_BUFFER_SIZE)) < 0) { + if ((ret = ff_alloc_packet(pkt, avctx->width*avctx->height*7/5 + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } @@ -174,8 +174,6 @@ static int gif_encode_close(AVCodecContext *avctx) { GIFContext *s = avctx->priv_data; - av_frame_free(&avctx->coded_frame); - av_freep(&s->lzw); av_freep(&s->buf); return 0; diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c index df5ab78..f08d501 100644 --- a/libavcodec/gifdec.c +++ b/libavcodec/gifdec.c @@ -74,7 +74,7 @@ static int gif_read_image(GifState *s, AVFrame *frame) has_local_palette = flags & 0x80; bits_per_pixel = (flags & 0x07) + 1; - av_dlog(s->avctx, "gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); + ff_dlog(s->avctx, "gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); if (has_local_palette) { bytestream2_get_buffer(&s->gb, s->local_palette, 3 * (1 << bits_per_pixel)); @@ -159,7 +159,7 @@ static int gif_read_extension(GifState *s) ext_code = bytestream2_get_byte(&s->gb); ext_len = bytestream2_get_byte(&s->gb); - av_dlog(s->avctx, "gif: ext_code=0x%x len=%d\n", ext_code, ext_len); + ff_dlog(s->avctx, "gif: ext_code=0x%x len=%d\n", ext_code, ext_len); switch(ext_code) { case 0xf9: @@ -175,7 +175,7 @@ static int gif_read_extension(GifState *s) s->transparent_color_index = -1; s->gce_disposal = (gce_flags >> 2) & 0x7; - av_dlog(s->avctx, "gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n", + ff_dlog(s->avctx, "gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n", gce_flags, s->gce_delay, s->transparent_color_index, s->gce_disposal); @@ -190,7 +190,7 @@ static int gif_read_extension(GifState *s) bytestream2_get_byte(&s->gb); ext_len = bytestream2_get_byte(&s->gb); - av_dlog(s->avctx, "gif: ext_len1=%d\n", ext_len); + ff_dlog(s->avctx, "gif: ext_len1=%d\n", ext_len); } return 0; } @@ -227,7 +227,7 @@ static int gif_read_header1(GifState *s) s->background_color_index = bytestream2_get_byte(&s->gb); bytestream2_get_byte(&s->gb); /* ignored */ - av_dlog(s->avctx, "gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", + ff_dlog(s->avctx, "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); @@ -246,7 +246,7 @@ static int gif_parse_next_image(GifState *s, AVFrame *frame) int code = bytestream2_get_byte(&s->gb); int ret; - av_dlog(s->avctx, "gif: code=%02x '%c'\n", code, code); + ff_dlog(s->avctx, "gif: code=%02x '%c'\n", code, code); switch (code) { case ',': @@ -323,5 +323,5 @@ AVCodec ff_gif_decoder = { .init = gif_decode_init, .close = gif_decode_close, .decode = gif_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 1754706..bf80fae 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -108,7 +108,7 @@ static inline int get_ue_golomb_31(GetBitContext *gb) return ff_ue_golomb_vlc_code[buf]; } -static inline unsigned svq3_get_ue_golomb(GetBitContext *gb) +static inline unsigned get_interleaved_ue_golomb(GetBitContext *gb) { uint32_t buf; @@ -138,7 +138,7 @@ static inline unsigned svq3_get_ue_golomb(GetBitContext *gb) ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf]; UPDATE_CACHE(re, gb); buf = GET_CACHE(re, gb); - } while (HAVE_BITS_REMAINING(re, gb)); + } while (BITS_AVAILABLE(re, gb)); CLOSE_READER(re, gb); return ret - 1; @@ -218,7 +218,7 @@ static inline int get_se_golomb_long(GetBitContext *gb) return buf; } -static inline int svq3_get_se_golomb(GetBitContext *gb) +static inline int get_interleaved_se_golomb(GetBitContext *gb) { unsigned int buf; @@ -253,7 +253,7 @@ static inline int svq3_get_se_golomb(GetBitContext *gb) static inline int dirac_get_se_golomb(GetBitContext *gb) { - uint32_t ret = svq3_get_ue_golomb(gb); + uint32_t ret = get_interleaved_ue_golomb(gb); if (ret) { uint32_t buf; @@ -328,7 +328,7 @@ static inline int get_ur_golomb_jpegls(GetBitContext *gb, int k, int limit, return buf; } else { int i; - for (i = 0; i < limit && SHOW_UBITS(re, gb, 1) == 0 && HAVE_BITS_REMAINING(re, gb); i++) { + for (i = 0; i < limit && SHOW_UBITS(re, gb, 1) == 0 && BITS_AVAILABLE(re, gb); i++) { LAST_SKIP_BITS(re, gb, 1); UPDATE_CACHE(re, gb); } @@ -413,8 +413,6 @@ static inline int get_ue(GetBitContext *s, const char *file, const char *func, 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); @@ -430,8 +428,6 @@ static inline int get_se(GetBitContext *s, const char *file, const char *func, 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); @@ -447,8 +443,6 @@ static inline int get_te(GetBitContext *s, int r, char *file, const char *func, 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); @@ -469,12 +463,6 @@ static inline void set_ue_golomb(PutBitContext *pb, int i) { 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 { @@ -502,19 +490,9 @@ static inline void set_te_golomb(PutBitContext *pb, int i, int range) */ static inline void set_se_golomb(PutBitContext *pb, int i) { -#if 0 - if (i <= 0) - i = -2 * i; - else - i = 2 * i - 1; -#elif 1 i = 2 * i - 1; if (i < 0) i ^= -1; //FIXME check if gcc does the right thing -#else - i = 2 * i - 1; - i ^= (i >> 31); -#endif set_ue_golomb(pb, i); } diff --git a/libavcodec/gsmdec.c b/libavcodec/gsmdec.c index b763ce8..a333e58 100644 --- a/libavcodec/gsmdec.c +++ b/libavcodec/gsmdec.c @@ -121,7 +121,7 @@ AVCodec ff_gsm_decoder = { .init = gsm_init, .decode = gsm_decode_frame, .flush = gsm_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; AVCodec ff_gsm_ms_decoder = { @@ -133,5 +133,5 @@ AVCodec ff_gsm_ms_decoder = { .init = gsm_init, .decode = gsm_decode_frame, .flush = gsm_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/gsmdec_data.c b/libavcodec/gsmdec_data.c index c9b3183..71f788e 100644 --- a/libavcodec/gsmdec_data.c +++ b/libavcodec/gsmdec_data.c @@ -26,6 +26,13 @@ const uint16_t ff_gsm_long_term_gain_tab[4] = { 3277, 11469, 21299, 32767 }; +const uint8_t ff_gsm_requant_tab[4][8] = { + { 0 }, + { 0, 7 }, + { 0, 2, 5, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7 } +}; + const int16_t ff_gsm_dequant_tab[64][8] = { { -28, -20, -12, -4, 4, 12, 20, 28}, { -56, -40, -24, -8, 8, 24, 40, 56}, diff --git a/libavcodec/gsmdec_data.h b/libavcodec/gsmdec_data.h index f5581d5..f301f56 100644 --- a/libavcodec/gsmdec_data.h +++ b/libavcodec/gsmdec_data.h @@ -38,6 +38,7 @@ typedef struct GSMContext { } GSMContext; extern const uint16_t ff_gsm_long_term_gain_tab[4]; +extern const uint8_t ff_gsm_requant_tab[4][8]; extern const int16_t ff_gsm_dequant_tab[64][8]; extern const int* const ff_gsm_apcm_bits[][4]; diff --git a/libavcodec/gsmdec_template.c b/libavcodec/gsmdec_template.c index 0b54dc5..2794bd1 100644 --- a/libavcodec/gsmdec_template.c +++ b/libavcodec/gsmdec_template.c @@ -28,13 +28,6 @@ #include "gsm.h" #include "gsmdec_data.h" -static const int requant_tab[4][8] = { - { 0 }, - { 0, 7 }, - { 0, 2, 5, 7 }, - { 0, 1, 2, 3, 4, 5, 6, 7 } -}; - static void apcm_dequant_add(GetBitContext *gb, int16_t *dst, const int *frame_bits) { int i, val; @@ -42,7 +35,7 @@ static void apcm_dequant_add(GetBitContext *gb, int16_t *dst, const int *frame_b const int16_t *tab = ff_gsm_dequant_tab[maxidx]; for (i = 0; i < 13; i++) { val = get_bits(gb, frame_bits[i]); - dst[3*i] += tab[requant_tab[frame_bits[i]][val]]; + dst[3 * i] += tab[ff_gsm_requant_tab[frame_bits[i]][val]]; } } diff --git a/libavcodec/h261.c b/libavcodec/h261.c index b9783f1..320d621 100644 --- a/libavcodec/h261.c +++ b/libavcodec/h261.c @@ -1,5 +1,5 @@ /* - * H261 common code + * H.261 common code * Copyright (c) 2002-2004 Michael Niedermayer * Copyright (c) 2004 Maarten Daniels * @@ -22,7 +22,7 @@ /** * @file - * h261codec. + * H.261 codec */ #include "avcodec.h" @@ -87,6 +87,6 @@ av_cold void ff_h261_common_init(void) if (done) return; - ff_init_rl(&ff_h261_rl_tcoeff, ff_h261_rl_table_store); + ff_rl_init(&ff_h261_rl_tcoeff, ff_h261_rl_table_store); done = 1; } diff --git a/libavcodec/h261.h b/libavcodec/h261.h index ad7e28b..fdfe560 100644 --- a/libavcodec/h261.h +++ b/libavcodec/h261.h @@ -1,5 +1,5 @@ /* - * H261 decoder + * H.261 codec * Copyright (c) 2002-2004 Michael Niedermayer * Copyright (c) 2004 Maarten Daniels * @@ -22,7 +22,7 @@ /** * @file - * h261codec. + * H.261 codec. */ #ifndef AVCODEC_H261_H diff --git a/libavcodec/h261_parser.c b/libavcodec/h261_parser.c index 2469424..59eed02 100644 --- a/libavcodec/h261_parser.c +++ b/libavcodec/h261_parser.c @@ -1,5 +1,5 @@ /* - * H261 parser + * H.261 parser * Copyright (c) 2002-2004 Michael Niedermayer * Copyright (c) 2004 Maarten Daniels * @@ -22,7 +22,7 @@ /** * @file - * h261codec. + * H.261 parser */ #include "parser.h" diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 39c1a32..9a323ec 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -1,5 +1,5 @@ /* - * H261 decoder + * H.261 decoder * Copyright (c) 2002-2004 Michael Niedermayer * Copyright (c) 2004 Maarten Daniels * @@ -478,7 +478,7 @@ static int h261_decode_picture_header(H261Context *h) i += 32; s->picture_number = (s->picture_number & ~31) + i; - s->avctx->time_base = (AVRational) { 1001, 30000 }; + s->avctx->framerate = (AVRational) { 30000, 1001 }; /* PTYPE starts here */ skip_bits1(&s->gb); /* split screen off */ @@ -571,10 +571,8 @@ static int h261_decode_frame(AVCodecContext *avctx, void *data, int ret; AVFrame *pict = data; - av_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); - av_dlog(avctx, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); - s->flags = avctx->flags; - s->flags2 = avctx->flags2; + ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + ff_dlog(avctx, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); h->gob_start_code_skipped = 0; @@ -582,7 +580,7 @@ retry: init_get_bits(&s->gb, buf, buf_size * 8); if (!s->context_initialized) - // we need the IDCT permutaton for reading a custom matrix + // we need the IDCT permutation for reading a custom matrix ff_mpv_idct_init(s); ret = h261_decode_picture_header(h); @@ -666,5 +664,5 @@ AVCodec ff_h261_decoder = { .init = h261_decode_init, .close = h261_decode_end, .decode = h261_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index f24e590..3cac882 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -1,5 +1,5 @@ /* - * H261 encoder + * H.261 encoder * Copyright (c) 2002-2004 Michael Niedermayer * Copyright (c) 2004 Maarten Daniels * @@ -31,6 +31,7 @@ #include "mpegvideo.h" #include "h263.h" #include "h261.h" +#include "mpegvideodata.h" int ff_h261_get_picture_format(int width, int height) { @@ -63,14 +64,14 @@ void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number) 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 */ + put_bits(&s->pb, 1, s->pict_type == AV_PICTURE_TYPE_I); /* freeze picture release on/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, 1); /* still image mode */ + put_bits(&s->pb, 1, 1); /* reserved */ put_bits(&s->pb, 1, 0); /* no PEI */ if (format == 0) @@ -323,7 +324,12 @@ av_cold void ff_h261_encode_init(MpegEncContext *s) s->c_dc_scale_table = ff_mpeg1_dc_scale_table; } -FF_MPV_GENERIC_CLASS(h261) +static const AVClass h261_class = { + .class_name = "h261 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_h261_encoder = { .name = "h261", diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 9019548..f3a7dab 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -1,7 +1,7 @@ /* - * H263/MPEG4 backend for encoder and decoder + * H.263/MPEG-4 backend for encoder and decoder * Copyright (c) 2000,2001 Fabrice Bellard - * H263+ support. + * H.263+ support. * Copyright (c) 2001 Juan J. Sierralta P * Copyright (c) 2002-2004 Michael Niedermayer * @@ -24,7 +24,7 @@ /** * @file - * h263/mpeg4 codec. + * H.263/MPEG-4 codec. */ #include @@ -35,14 +35,10 @@ #include "h263data.h" #include "mathops.h" #include "mpegutils.h" -#include "unary.h" #include "flv.h" #include "mpeg4video.h" -uint8_t ff_h263_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; - - void ff_h263_update_motion_val(MpegEncContext * s){ const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; //FIXME a lot of that is only needed for !low_delay @@ -323,7 +319,7 @@ int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, 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) + // 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 @@ -367,16 +363,3 @@ int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, } return *mot_val; } - - -/** - * Get the GOB height based on picture height. - */ -int ff_h263_get_gob_height(MpegEncContext *s){ - if (s->height <= 400) - return 1; - else if (s->height <= 800) - return 2; - else - return 4; -} diff --git a/libavcodec/h263.h b/libavcodec/h263.h index dbbe7ce..42c78f4 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -1,5 +1,5 @@ /* - * H263 internal header + * H.263 internal header * * This file is part of Libav. * @@ -24,11 +24,13 @@ #include "libavutil/rational.h" #include "get_bits.h" #include "mpegvideo.h" +#include "h263data.h" #include "rl.h" #if !FF_API_ASPECT_EXTENDED #define FF_ASPECT_EXTENDED 15 #endif +#define INT_BIT (CHAR_BIT * sizeof(int)) // The defines below define the number of bits that are read at once for // reading vlc values. Changing these may improve speed and data cache needs @@ -39,39 +41,12 @@ #define CBPY_VLC_BITS 6 #define TEX_VLC_BITS 9 -extern const AVRational ff_h263_pixel_aspect[16]; -extern const uint8_t ff_h263_cbpy_tab[16][2]; - -extern const uint8_t ff_cbpc_b_tab[4][2]; - -extern const uint8_t ff_mvtab[33][2]; - -extern const uint8_t ff_h263_intra_MCBPC_code[9]; -extern const uint8_t ff_h263_intra_MCBPC_bits[9]; - -extern const uint8_t ff_h263_inter_MCBPC_code[28]; -extern const uint8_t ff_h263_inter_MCBPC_bits[28]; -extern const uint8_t ff_h263_mbtype_b_tab[15][2]; +#define H263_GOB_HEIGHT(h) ((h) <= 400 ? 1 : (h) <= 800 ? 2 : 4) extern VLC ff_h263_intra_MCBPC_vlc; extern VLC ff_h263_inter_MCBPC_vlc; extern VLC ff_h263_cbpy_vlc; -extern const uint16_t ff_inter_vlc[103][2]; -extern const int8_t ff_inter_level[102]; -extern const int8_t ff_inter_run[102]; - -extern RLTable ff_h263_rl_inter; - -extern RLTable ff_rl_intra_aic; - -extern const uint16_t ff_h263_format[8][2]; -extern const uint8_t ff_modified_quant_tab[2][32]; -extern uint16_t ff_mba_max[6]; -extern uint8_t ff_mba_length[7]; - -extern uint8_t ff_h263_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; - extern const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[]; @@ -112,7 +87,7 @@ int ff_h263_decode_mb(MpegEncContext *s, int16_t block[6][64]); /** - * Return the value of the 3bit "source format" syntax element. + * Return the value of the 3-bit "source format" syntax element. * This represents some standard picture dimensions or indicates that * width&height are explicitly stored later. */ @@ -121,7 +96,6 @@ int av_const h263_get_picture_format(int width, int height); void ff_clean_h263_qscales(MpegEncContext *s); int ff_h263_resync(MpegEncContext *s); const uint8_t *ff_h263_find_resync_marker(const uint8_t *p, const uint8_t *end); -int ff_h263_get_gob_height(MpegEncContext *s); void ff_h263_encode_motion(MpegEncContext * s, int val, int f_code); @@ -143,7 +117,7 @@ static inline int h263_get_motion_length(MpegEncContext * s, int val, int f_code } static inline void ff_h263_encode_motion_vector(MpegEncContext * s, int x, int y, int f_code){ - if(s->flags2 & CODEC_FLAG2_NO_OUTPUT){ + if (s->avctx->flags2 & AV_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)); @@ -210,11 +184,4 @@ static inline int get_p_cbp(MpegEncContext * s, return cbp; } -static inline void memsetw(short *tab, int val, int n) -{ - int i; - for(i=0;i + +#include "h263data.h" +#include "mpegvideo.h" + +uint8_t ff_h263_static_rl_table_store[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; + +/* intra MCBPC, mb_type = (intra), then (intraq) */ +const uint8_t ff_h263_intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 }; +const uint8_t ff_h263_intra_MCBPC_bits[9] = { 1, 3, 3, 3, 4, 6, 6, 6, 9 }; + +/* inter MCBPC, mb_type = (inter), (intra), (interq), (intraq), (inter4v) */ +/* Changed the tables for interq and inter4v+q, following the standard + * ** Juanjo ** */ +const uint8_t ff_h263_inter_MCBPC_code[28] = { + 1, 3, 2, 5, + 3, 4, 3, 3, + 3, 7, 6, 5, + 4, 4, 3, 2, + 2, 5, 4, 5, + 1, 0, 0, 0, /* Stuffing */ + 2, 12, 14, 15, +}; +const uint8_t ff_h263_inter_MCBPC_bits[28] = { + 1, 4, 4, 6, /* inter */ + 5, 8, 8, 7, /* intra */ + 3, 7, 7, 9, /* interQ */ + 6, 9, 9, 9, /* intraQ */ + 3, 7, 7, 8, /* inter4 */ + 9, 0, 0, 0, /* Stuffing */ + 11, 13, 13, 13, /* inter4Q */ +}; + +const uint8_t ff_h263_mbtype_b_tab[15][2] = { + { 1, 1 }, + { 3, 3 }, + { 1, 5 }, + { 4, 4 }, + { 5, 4 }, + { 6, 6 }, + { 2, 4 }, + { 3, 4 }, + { 7, 6 }, + { 4, 6 }, + { 5, 6 }, + { 1, 6 }, + { 1, 10 }, + { 1, 7 }, + { 1, 8 }, +}; + +const uint8_t ff_cbpc_b_tab[4][2] = { + { 0, 1 }, + { 2, 2 }, + { 7, 3 }, + { 6, 3 }, +}; + +const uint8_t ff_h263_cbpy_tab[16][2] = { + { 3, 4 }, { 5, 5 }, { 4, 5 }, { 9, 4 }, { 3, 5 }, { 7, 4 }, { 2, 6 }, + { 11, 4 }, { 2, 5 }, { 3, 6 }, { 5, 4 }, { 10, 4 }, { 4, 4 }, { 8, 4 }, + { 6, 4 }, { 3, 2 } +}; + +const uint8_t ff_mvtab[33][2] = { + { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 3, 6 }, { 5, 7 }, + { 4, 7 }, { 3, 7 }, { 11, 9 }, { 10, 9 }, { 9, 9 }, { 17, 10 }, + { 16, 10 }, { 15, 10 }, { 14, 10 }, { 13, 10 }, { 12, 10 }, { 11, 10 }, + { 10, 10 }, { 9, 10 }, { 8, 10 }, { 7, 10 }, { 6, 10 }, { 5, 10 }, + { 4, 10 }, { 7, 11 }, { 6, 11 }, { 5, 11 }, { 4, 11 }, { 3, 11 }, + { 2, 11 }, { 3, 12 }, { 2, 12 } +}; + +/* third non intra table */ +const uint16_t ff_inter_vlc[103][2] = { + { 0x2, 2 }, { 0xf, 4 }, { 0x15, 6 }, { 0x17, 7 }, + { 0x1f, 8 }, { 0x25, 9 }, { 0x24, 9 }, { 0x21, 10 }, + { 0x20, 10 }, { 0x7, 11 }, { 0x6, 11 }, { 0x20, 11 }, + { 0x6, 3 }, { 0x14, 6 }, { 0x1e, 8 }, { 0xf, 10 }, + { 0x21, 11 }, { 0x50, 12 }, { 0xe, 4 }, { 0x1d, 8 }, + { 0xe, 10 }, { 0x51, 12 }, { 0xd, 5 }, { 0x23, 9 }, + { 0xd, 10 }, { 0xc, 5 }, { 0x22, 9 }, { 0x52, 12 }, + { 0xb, 5 }, { 0xc, 10 }, { 0x53, 12 }, { 0x13, 6 }, + { 0xb, 10 }, { 0x54, 12 }, { 0x12, 6 }, { 0xa, 10 }, + { 0x11, 6 }, { 0x9, 10 }, { 0x10, 6 }, { 0x8, 10 }, + { 0x16, 7 }, { 0x55, 12 }, { 0x15, 7 }, { 0x14, 7 }, + { 0x1c, 8 }, { 0x1b, 8 }, { 0x21, 9 }, { 0x20, 9 }, + { 0x1f, 9 }, { 0x1e, 9 }, { 0x1d, 9 }, { 0x1c, 9 }, + { 0x1b, 9 }, { 0x1a, 9 }, { 0x22, 11 }, { 0x23, 11 }, + { 0x56, 12 }, { 0x57, 12 }, { 0x7, 4 }, { 0x19, 9 }, + { 0x5, 11 }, { 0xf, 6 }, { 0x4, 11 }, { 0xe, 6 }, + { 0xd, 6 }, { 0xc, 6 }, { 0x13, 7 }, { 0x12, 7 }, + { 0x11, 7 }, { 0x10, 7 }, { 0x1a, 8 }, { 0x19, 8 }, + { 0x18, 8 }, { 0x17, 8 }, { 0x16, 8 }, { 0x15, 8 }, + { 0x14, 8 }, { 0x13, 8 }, { 0x18, 9 }, { 0x17, 9 }, + { 0x16, 9 }, { 0x15, 9 }, { 0x14, 9 }, { 0x13, 9 }, + { 0x12, 9 }, { 0x11, 9 }, { 0x7, 10 }, { 0x6, 10 }, + { 0x5, 10 }, { 0x4, 10 }, { 0x24, 11 }, { 0x25, 11 }, + { 0x26, 11 }, { 0x27, 11 }, { 0x58, 12 }, { 0x59, 12 }, + { 0x5a, 12 }, { 0x5b, 12 }, { 0x5c, 12 }, { 0x5d, 12 }, + { 0x5e, 12 }, { 0x5f, 12 }, { 0x3, 7 }, +}; + +const int8_t ff_inter_level[102] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 1, 2, 3, 4, + 5, 6, 1, 2, 3, 4, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 3, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +const int8_t ff_inter_run[102] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 0, 1, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, +}; + +RLTable ff_h263_rl_inter = { + 102, + 58, + ff_inter_vlc, + ff_inter_run, + ff_inter_level, +}; + +static const uint16_t intra_vlc_aic[103][2] = { + { 0x2, 2 }, { 0x6, 3 }, { 0xe, 4 }, { 0xc, 5 }, + { 0xd, 5 }, { 0x10, 6 }, { 0x11, 6 }, { 0x12, 6 }, + { 0x16, 7 }, { 0x1b, 8 }, { 0x20, 9 }, { 0x21, 9 }, + { 0x1a, 9 }, { 0x1b, 9 }, { 0x1c, 9 }, { 0x1d, 9 }, + { 0x1e, 9 }, { 0x1f, 9 }, { 0x23, 11 }, { 0x22, 11 }, + { 0x57, 12 }, { 0x56, 12 }, { 0x55, 12 }, { 0x54, 12 }, + { 0x53, 12 }, { 0xf, 4 }, { 0x14, 6 }, { 0x14, 7 }, + { 0x1e, 8 }, { 0xf, 10 }, { 0x21, 11 }, { 0x50, 12 }, + { 0xb, 5 }, { 0x15, 7 }, { 0xe, 10 }, { 0x9, 10 }, + { 0x15, 6 }, { 0x1d, 8 }, { 0xd, 10 }, { 0x51, 12 }, + { 0x13, 6 }, { 0x23, 9 }, { 0x7, 11 }, { 0x17, 7 }, + { 0x22, 9 }, { 0x52, 12 }, { 0x1c, 8 }, { 0xc, 10 }, + { 0x1f, 8 }, { 0xb, 10 }, { 0x25, 9 }, { 0xa, 10 }, + { 0x24, 9 }, { 0x6, 11 }, { 0x21, 10 }, { 0x20, 10 }, + { 0x8, 10 }, { 0x20, 11 }, { 0x7, 4 }, { 0xc, 6 }, + { 0x10, 7 }, { 0x13, 8 }, { 0x11, 9 }, { 0x12, 9 }, + { 0x4, 10 }, { 0x27, 11 }, { 0x26, 11 }, { 0x5f, 12 }, + { 0xf, 6 }, { 0x13, 9 }, { 0x5, 10 }, { 0x25, 11 }, + { 0xe, 6 }, { 0x14, 9 }, { 0x24, 11 }, { 0xd, 6 }, + { 0x6, 10 }, { 0x5e, 12 }, { 0x11, 7 }, { 0x7, 10 }, + { 0x13, 7 }, { 0x5d, 12 }, { 0x12, 7 }, { 0x5c, 12 }, + { 0x14, 8 }, { 0x5b, 12 }, { 0x15, 8 }, { 0x1a, 8 }, + { 0x19, 8 }, { 0x18, 8 }, { 0x17, 8 }, { 0x16, 8 }, + { 0x19, 9 }, { 0x15, 9 }, { 0x16, 9 }, { 0x18, 9 }, + { 0x17, 9 }, { 0x4, 11 }, { 0x5, 11 }, { 0x58, 12 }, + { 0x59, 12 }, { 0x5a, 12 }, { 0x3, 7 }, +}; + +static const int8_t intra_run_aic[102] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 11, + 12, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 3, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, +}; + +static const int8_t intra_level_aic[102] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 1, 2, 3, 4, 5, 6, 7, + 1, 2, 3, 4, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 1, + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +RLTable ff_rl_intra_aic = { + 102, + 58, + intra_vlc_aic, + intra_run_aic, + intra_level_aic, +}; + +const uint16_t ff_h263_format[8][2] = { + { 0, 0 }, + { 128, 96 }, + { 176, 144 }, + { 352, 288 }, + { 704, 576 }, + { 1408, 1152 }, +}; + +const uint8_t ff_aic_dc_scale_table[32] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 +}; + +const uint8_t ff_modified_quant_tab[2][32] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + { + 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 + }, + { + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 31, 31, 26 + } +}; + +const uint8_t ff_h263_chroma_qscale_table[32] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15 +}; + +uint16_t ff_mba_max[6] = { + 47, 98, 395, 1583, 6335, 9215 +}; + +uint8_t ff_mba_length[7] = { + 6, 7, 9, 11, 13, 14, 14 +}; + +const AVRational ff_h263_pixel_aspect[16] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, +}; diff --git a/libavcodec/h263data.h b/libavcodec/h263data.h index c966aab..a431d58 100644 --- a/libavcodec/h263data.h +++ b/libavcodec/h263data.h @@ -1,6 +1,6 @@ /* * copyright (c) 2000,2001 Fabrice Bellard - * H263+ support + * H.263+ support * copyright (c) 2001 Juan J. Sierralta P * copyright (c) 2002-2004 Michael Niedermayer * @@ -30,265 +30,48 @@ #define AVCODEC_H263DATA_H #include -#include "mpegvideo.h" + +#include "libavutil/rational.h" + +#include "rl.h" + +extern const AVRational ff_h263_pixel_aspect[16]; /* intra MCBPC, mb_type = (intra), then (intraq) */ -const uint8_t ff_h263_intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 }; -const uint8_t ff_h263_intra_MCBPC_bits[9] = { 1, 3, 3, 3, 4, 6, 6, 6, 9 }; +extern const uint8_t ff_h263_intra_MCBPC_code[9]; +extern const uint8_t ff_h263_intra_MCBPC_bits[9]; /* inter MCBPC, mb_type = (inter), (intra), (interq), (intraq), (inter4v) */ /* Changed the tables for interq and inter4v+q, following the standard ** Juanjo ** */ -const uint8_t ff_h263_inter_MCBPC_code[28] = { - 1, 3, 2, 5, - 3, 4, 3, 3, - 3, 7, 6, 5, - 4, 4, 3, 2, - 2, 5, 4, 5, - 1, 0, 0, 0, /* Stuffing */ - 2, 12, 14, 15, -}; -const uint8_t ff_h263_inter_MCBPC_bits[28] = { - 1, 4, 4, 6, /* inter */ - 5, 8, 8, 7, /* intra */ - 3, 7, 7, 9, /* interQ */ - 6, 9, 9, 9, /* intraQ */ - 3, 7, 7, 8, /* inter4 */ - 9, 0, 0, 0, /* Stuffing */ - 11, 13, 13, 13,/* inter4Q*/ -}; +extern const uint8_t ff_h263_inter_MCBPC_code[28]; +extern const uint8_t ff_h263_inter_MCBPC_bits[28]; -const uint8_t ff_h263_mbtype_b_tab[15][2] = { - {1, 1}, - {3, 3}, - {1, 5}, - {4, 4}, - {5, 4}, - {6, 6}, - {2, 4}, - {3, 4}, - {7, 6}, - {4, 6}, - {5, 6}, - {1, 6}, - {1,10}, - {1, 7}, - {1, 8}, -}; +extern const uint8_t ff_h263_mbtype_b_tab[15][2]; -const uint8_t ff_cbpc_b_tab[4][2] = { -{0, 1}, -{2, 2}, -{7, 3}, -{6, 3}, -}; +extern const uint8_t ff_cbpc_b_tab[4][2]; +extern const uint8_t ff_h263_cbpy_tab[16][2]; -const uint8_t ff_h263_cbpy_tab[16][2] = -{ - {3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4}, - {2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2} -}; - -const uint8_t ff_mvtab[33][2] = -{ - {1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7}, - {11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10}, - {12,10}, {11,10}, {10,10}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10}, - {4,10}, {7,11}, {6,11}, {5,11}, {4,11}, {3,11}, {2,11}, {3,12}, - {2,12} -}; +extern const uint8_t ff_mvtab[33][2]; /* third non intra table */ -const uint16_t ff_inter_vlc[103][2] = { -{ 0x2, 2 },{ 0xf, 4 },{ 0x15, 6 },{ 0x17, 7 }, -{ 0x1f, 8 },{ 0x25, 9 },{ 0x24, 9 },{ 0x21, 10 }, -{ 0x20, 10 },{ 0x7, 11 },{ 0x6, 11 },{ 0x20, 11 }, -{ 0x6, 3 },{ 0x14, 6 },{ 0x1e, 8 },{ 0xf, 10 }, -{ 0x21, 11 },{ 0x50, 12 },{ 0xe, 4 },{ 0x1d, 8 }, -{ 0xe, 10 },{ 0x51, 12 },{ 0xd, 5 },{ 0x23, 9 }, -{ 0xd, 10 },{ 0xc, 5 },{ 0x22, 9 },{ 0x52, 12 }, -{ 0xb, 5 },{ 0xc, 10 },{ 0x53, 12 },{ 0x13, 6 }, -{ 0xb, 10 },{ 0x54, 12 },{ 0x12, 6 },{ 0xa, 10 }, -{ 0x11, 6 },{ 0x9, 10 },{ 0x10, 6 },{ 0x8, 10 }, -{ 0x16, 7 },{ 0x55, 12 },{ 0x15, 7 },{ 0x14, 7 }, -{ 0x1c, 8 },{ 0x1b, 8 },{ 0x21, 9 },{ 0x20, 9 }, -{ 0x1f, 9 },{ 0x1e, 9 },{ 0x1d, 9 },{ 0x1c, 9 }, -{ 0x1b, 9 },{ 0x1a, 9 },{ 0x22, 11 },{ 0x23, 11 }, -{ 0x56, 12 },{ 0x57, 12 },{ 0x7, 4 },{ 0x19, 9 }, -{ 0x5, 11 },{ 0xf, 6 },{ 0x4, 11 },{ 0xe, 6 }, -{ 0xd, 6 },{ 0xc, 6 },{ 0x13, 7 },{ 0x12, 7 }, -{ 0x11, 7 },{ 0x10, 7 },{ 0x1a, 8 },{ 0x19, 8 }, -{ 0x18, 8 },{ 0x17, 8 },{ 0x16, 8 },{ 0x15, 8 }, -{ 0x14, 8 },{ 0x13, 8 },{ 0x18, 9 },{ 0x17, 9 }, -{ 0x16, 9 },{ 0x15, 9 },{ 0x14, 9 },{ 0x13, 9 }, -{ 0x12, 9 },{ 0x11, 9 },{ 0x7, 10 },{ 0x6, 10 }, -{ 0x5, 10 },{ 0x4, 10 },{ 0x24, 11 },{ 0x25, 11 }, -{ 0x26, 11 },{ 0x27, 11 },{ 0x58, 12 },{ 0x59, 12 }, -{ 0x5a, 12 },{ 0x5b, 12 },{ 0x5c, 12 },{ 0x5d, 12 }, -{ 0x5e, 12 },{ 0x5f, 12 },{ 0x3, 7 }, -}; - -const int8_t ff_inter_level[102] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 1, 2, 3, 4, - 5, 6, 1, 2, 3, 4, 1, 2, - 3, 1, 2, 3, 1, 2, 3, 1, - 2, 3, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 3, 1, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, -}; - -const int8_t ff_inter_run[102] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 3, 3, - 3, 4, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 7, 8, 8, 9, 9, - 10, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 0, 0, 0, 1, 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, -}; - -RLTable ff_h263_rl_inter = { - 102, - 58, - ff_inter_vlc, - ff_inter_run, - ff_inter_level, -}; - -static const uint16_t intra_vlc_aic[103][2] = { -{ 0x2, 2 }, { 0x6, 3 }, { 0xe, 4 }, { 0xc, 5 }, -{ 0xd, 5 }, { 0x10, 6 }, { 0x11, 6 }, { 0x12, 6 }, -{ 0x16, 7 }, { 0x1b, 8 }, { 0x20, 9 }, { 0x21, 9 }, -{ 0x1a, 9 }, { 0x1b, 9 }, { 0x1c, 9 }, { 0x1d, 9 }, -{ 0x1e, 9 }, { 0x1f, 9 }, { 0x23, 11 }, { 0x22, 11 }, -{ 0x57, 12 }, { 0x56, 12 }, { 0x55, 12 }, { 0x54, 12 }, -{ 0x53, 12 }, { 0xf, 4 }, { 0x14, 6 }, { 0x14, 7 }, -{ 0x1e, 8 }, { 0xf, 10 }, { 0x21, 11 }, { 0x50, 12 }, -{ 0xb, 5 }, { 0x15, 7 }, { 0xe, 10 }, { 0x9, 10 }, -{ 0x15, 6 }, { 0x1d, 8 }, { 0xd, 10 }, { 0x51, 12 }, -{ 0x13, 6 }, { 0x23, 9 }, { 0x7, 11 }, { 0x17, 7 }, -{ 0x22, 9 }, { 0x52, 12 }, { 0x1c, 8 }, { 0xc, 10 }, -{ 0x1f, 8 }, { 0xb, 10 }, { 0x25, 9 }, { 0xa, 10 }, -{ 0x24, 9 }, { 0x6, 11 }, { 0x21, 10 }, { 0x20, 10 }, -{ 0x8, 10 }, { 0x20, 11 }, { 0x7, 4 }, { 0xc, 6 }, -{ 0x10, 7 }, { 0x13, 8 }, { 0x11, 9 }, { 0x12, 9 }, -{ 0x4, 10 }, { 0x27, 11 }, { 0x26, 11 }, { 0x5f, 12 }, -{ 0xf, 6 }, { 0x13, 9 }, { 0x5, 10 }, { 0x25, 11 }, -{ 0xe, 6 }, { 0x14, 9 }, { 0x24, 11 }, { 0xd, 6 }, -{ 0x6, 10 }, { 0x5e, 12 }, { 0x11, 7 }, { 0x7, 10 }, -{ 0x13, 7 }, { 0x5d, 12 }, { 0x12, 7 }, { 0x5c, 12 }, -{ 0x14, 8 }, { 0x5b, 12 }, { 0x15, 8 }, { 0x1a, 8 }, -{ 0x19, 8 }, { 0x18, 8 }, { 0x17, 8 }, { 0x16, 8 }, -{ 0x19, 9 }, { 0x15, 9 }, { 0x16, 9 }, { 0x18, 9 }, -{ 0x17, 9 }, { 0x4, 11 }, { 0x5, 11 }, { 0x58, 12 }, -{ 0x59, 12 }, { 0x5a, 12 }, { 0x3, 7 }, -}; - -static const int8_t intra_run_aic[102] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 5, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 11, -12, 13, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, - 2, 2, 2, 3, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 20, 21, 22, 23, -}; - -static const int8_t intra_level_aic[102] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, -25, 1, 2, 3, 4, 5, 6, 7, - 1, 2, 3, 4, 1, 2, 3, 4, - 1, 2, 3, 1, 2, 3, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 1, 2, 3, 4, - 1, 2, 3, 1, 2, 3, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, -}; - -RLTable ff_rl_intra_aic = { - 102, - 58, - intra_vlc_aic, - intra_run_aic, - intra_level_aic, -}; +extern const uint16_t ff_inter_vlc[103][2]; -const uint16_t ff_h263_format[8][2] = { - { 0, 0 }, - { 128, 96 }, - { 176, 144 }, - { 352, 288 }, - { 704, 576 }, - { 1408, 1152 }, -}; +extern const int8_t ff_inter_level[102]; +extern const int8_t ff_inter_run[102]; -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 -}; +extern RLTable ff_h263_rl_inter; +extern RLTable ff_rl_intra_aic; +extern uint8_t ff_h263_static_rl_table_store[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; -const uint8_t ff_modified_quant_tab[2][32]={ -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -{ - 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9,10,11,12,13,14,15,16,17,18,18,19,20,21,22,23,24,25,26,27,28 -},{ - 0, 2, 3, 4, 5, 6, 7, 8, 9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,31,31,26 -} -}; +extern const uint16_t ff_h263_format[8][2]; -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 -}; +extern const uint8_t ff_aic_dc_scale_table[32]; -uint16_t ff_mba_max[6]={ - 47, 98, 395,1583,6335,9215 -}; +extern const uint8_t ff_modified_quant_tab[2][32]; -uint8_t ff_mba_length[7]={ - 6, 7, 9, 11, 13, 14, 14 -}; +extern const uint8_t ff_h263_chroma_qscale_table[32]; -const AVRational ff_h263_pixel_aspect[16]={ - {0, 1}, - {1, 1}, - {12, 11}, - {10, 11}, - {16, 11}, - {40, 33}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, - {0, 1}, -}; +extern uint16_t ff_mba_max[6]; +extern uint8_t ff_mba_length[7]; #endif /* AVCODEC_H263DATA_H */ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index cfb77b0..e4a7227 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -35,10 +35,20 @@ #include "mpeg_er.h" #include "mpeg4video.h" #include "mpeg4video_parser.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4.h" #include "qpeldsp.h" #include "thread.h" +#include "wmv2.h" + +static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) +{ + if (avctx->codec->id == AV_CODEC_ID_MSS2) + return AV_PIX_FMT_YUV420P; + + return avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); +} av_cold int ff_h263_decode_init(AVCodecContext *avctx) { @@ -56,10 +66,6 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) s->quant_precision = 5; s->decode_mb = ff_h263_decode_mb; s->low_delay = 1; - if (avctx->codec->id == AV_CODEC_ID_MSS2) - avctx->pix_fmt = AV_PIX_FMT_YUV420P; - else - avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); s->unrestricted_mv = 1; /* select sub codec */ @@ -111,9 +117,10 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) } s->codec_id = avctx->codec->id; - /* for h263, we allocate the images after having read the header */ + /* for H.263, we allocate the images after having read the header */ if (avctx->codec->id != AV_CODEC_ID_H263 && avctx->codec->id != AV_CODEC_ID_MPEG4) { + avctx->pix_fmt = h263_get_format(avctx); ff_mpv_idct_init(s); if ((ret = ff_mpv_common_init(s)) < 0) return ret; @@ -145,7 +152,7 @@ static int get_consumed_bytes(MpegEncContext *s, int buf_size) /* We would have to scan through the whole buf to handle the weird * reordering ... */ return buf_size; - } else if (s->flags & CODEC_FLAG_TRUNCATED) { + } else if (s->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { pos -= s->parse_context.last_index; // padding is not really read so this might be -1 if (pos < 0) @@ -229,8 +236,8 @@ static int decode_slice(MpegEncContext *s) s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; - av_dlog(s, "%d %d %06X\n", - ret, get_bits_count(&s->gb), show_bits(&s->gb, 24)); + ff_dlog(s, "%d %06X\n", + get_bits_count(&s->gb), show_bits(&s->gb, 24)); ret = s->decode_mb(s, s->block); if (s->pict_type != AV_PICTURE_TYPE_B) @@ -316,7 +323,8 @@ static int decode_slice(MpegEncContext *s) } if (s->workaround_bugs & FF_BUG_AUTODETECT) { - if (s->padding_bug_score > -2 && !s->data_partitioning) + if (s->codec_id == AV_CODEC_ID_H263 || + (s->padding_bug_score > -2 && !s->data_partitioning)) s->workaround_bugs |= FF_BUG_NO_PADDING; else s->workaround_bugs &= ~FF_BUG_NO_PADDING; @@ -334,7 +342,7 @@ static int decode_slice(MpegEncContext *s) /* buggy padding but the frame should still end approximately at * the bitstream end */ if ((s->workaround_bugs & FF_BUG_NO_PADDING) && - (s->err_recognition & AV_EF_BUFFER)) + (s->avctx->err_recognition & AV_EF_BUFFER)) max_extra += 48; else if ((s->workaround_bugs & FF_BUG_NO_PADDING)) max_extra += 256 * 256 * 256 * 64; @@ -371,9 +379,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int ret; AVFrame *pict = data; - s->flags = avctx->flags; - s->flags2 = avctx->flags2; - /* no supplementary picture */ if (buf_size == 0) { /* special case for last picture */ @@ -388,7 +393,7 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return 0; } - if (s->flags & CODEC_FLAG_TRUNCATED) { + if (s->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { int next; if (CONFIG_MPEG4_DECODER && s->codec_id == AV_CODEC_ID_MPEG4) { @@ -417,7 +422,7 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; if (!s->context_initialized) - // we need the idct permutaton for reading a custom matrix + // we need the idct permutation for reading a custom matrix ff_mpv_idct_init(s); /* let's go :-) */ @@ -453,12 +458,14 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; } - if (!s->context_initialized) + if (!s->context_initialized) { + avctx->pix_fmt = h263_get_format(avctx); if ((ret = ff_mpv_common_init(s)) < 0) return ret; + } if (!s->current_picture_ptr || s->current_picture_ptr->f->data[0]) { - int i = ff_find_unused_picture(s, 0); + int i = ff_find_unused_picture(s->avctx, s->picture, 0); if (i < 0) return i; s->current_picture_ptr = &s->picture[i]; @@ -487,9 +494,9 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_old_c) } - /* After H263 & mpeg4 header decode we have the height, width, + /* After H.263 & MPEG-4 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 + * FIXME: By the way H.263 decoder is evolving it should have * an H263EncContext */ if (s->width != avctx->coded_width || s->height != avctx->coded_height || @@ -505,12 +512,18 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ff_mpv_common_frame_size_change(s))) return ret; + + if (avctx->pix_fmt != h263_get_format(avctx)) { + av_log(avctx, AV_LOG_ERROR, "format change not supported\n"); + avctx->pix_fmt = AV_PIX_FMT_NONE; + return AVERROR_UNKNOWN; + } } if (s->codec_id == AV_CODEC_ID_H263 || s->codec_id == AV_CODEC_ID_H263P || s->codec_id == AV_CODEC_ID_H263I) - s->gob_index = ff_h263_get_gob_height(s); + s->gob_index = H263_GOB_HEIGHT(s->height); // for skipping the frame s->current_picture.f->pict_type = s->pict_type; @@ -642,9 +655,9 @@ intrax8_decoded: const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[] = { #if CONFIG_H263_VAAPI_HWACCEL || CONFIG_MPEG4_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, + AV_PIX_FMT_VAAPI, #endif -#if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL +#if CONFIG_MPEG4_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif AV_PIX_FMT_YUV420P, @@ -660,8 +673,8 @@ AVCodec ff_h263_decoder = { .init = ff_h263_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | - CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY, .flush = ff_mpeg_flush, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, }; diff --git a/libavcodec/h264.c b/libavcodec/h264.c deleted file mode 100644 index e9236e9..0000000 --- a/libavcodec/h264.c +++ /dev/null @@ -1,1880 +0,0 @@ -/* - * H.26L/H.264/AVC/JVT/14496-10/... decoder - * Copyright (c) 2003 Michael Niedermayer - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * H.264 / AVC / MPEG4 part10 codec. - * @author Michael Niedermayer - */ - -#include "libavutil/avassert.h" -#include "libavutil/display.h" -#include "libavutil/imgutils.h" -#include "libavutil/stereo3d.h" -#include "libavutil/timer.h" -#include "internal.h" -#include "cabac.h" -#include "cabac_functions.h" -#include "error_resilience.h" -#include "avcodec.h" -#include "h264.h" -#include "h264data.h" -#include "h264chroma.h" -#include "h264_mvpred.h" -#include "golomb.h" -#include "mathops.h" -#include "me_cmp.h" -#include "mpegutils.h" -#include "rectangle.h" -#include "svq3.h" -#include "thread.h" - -#include - -const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 }; - -static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, - int (*mv)[2][4][2], - int mb_x, int mb_y, int mb_intra, int mb_skipped) -{ - H264Context *h = opaque; - - h->mb_x = mb_x; - h->mb_y = mb_y; - h->mb_xy = mb_x + mb_y * h->mb_stride; - memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); - assert(ref >= 0); - /* FIXME: It is possible albeit uncommon that slice references - * differ between slices. We take the easy approach and ignore - * it for now. If this turns out to have any relevance in - * practice then correct remapping should be added. */ - if (ref >= h->ref_count[0]) - ref = 0; - fill_rectangle(&h->cur_pic.ref_index[0][4 * h->mb_xy], - 2, 2, 2, ref, 1); - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); - fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, - pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4); - assert(!FRAME_MBAFF(h)); - ff_h264_hl_decode_mb(h); -} - -void ff_h264_draw_horiz_band(H264Context *h, int y, int height) -{ - AVCodecContext *avctx = h->avctx; - AVFrame *cur = &h->cur_pic.f; - AVFrame *last = h->ref_list[0][0].f.data[0] ? &h->ref_list[0][0].f : NULL; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - int vshift = desc->log2_chroma_h; - const int field_pic = h->picture_structure != PICT_FRAME; - if (field_pic) { - height <<= 1; - y <<= 1; - } - - height = FFMIN(height, avctx->height - y); - - if (field_pic && h->first_field && !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) - return; - - if (avctx->draw_horiz_band) { - AVFrame *src; - int offset[AV_NUM_DATA_POINTERS]; - int i; - - if (cur->pict_type == AV_PICTURE_TYPE_B || h->low_delay || - (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) - src = cur; - else if (last) - src = last; - else - return; - - offset[0] = y * src->linesize[0]; - offset[1] = - offset[2] = (y >> vshift) * src->linesize[1]; - for (i = 3; i < AV_NUM_DATA_POINTERS; i++) - offset[i] = 0; - - emms_c(); - - avctx->draw_horiz_band(avctx, src, offset, - y, h->picture_structure, height); - } -} - -/** - * Check if the top & left blocks are available if needed and - * change the dc mode so it only uses the available blocks. - */ -int ff_h264_check_intra4x4_pred_mode(H264Context *h) -{ - static const int8_t top[12] = { - -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0 - }; - static const int8_t left[12] = { - 0, -1, TOP_DC_PRED, 0, -1, -1, -1, 0, -1, DC_128_PRED - }; - int i; - - if (!(h->top_samples_available & 0x8000)) { - for (i = 0; i < 4; i++) { - int status = top[h->intra4x4_pred_mode_cache[scan8[0] + i]]; - if (status < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "top block unavailable for requested intra4x4 mode %d at %d %d\n", - status, h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } else if (status) { - h->intra4x4_pred_mode_cache[scan8[0] + i] = status; - } - } - } - - if ((h->left_samples_available & 0x8888) != 0x8888) { - static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 }; - for (i = 0; i < 4; i++) - if (!(h->left_samples_available & mask[i])) { - int status = left[h->intra4x4_pred_mode_cache[scan8[0] + 8 * i]]; - if (status < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "left block unavailable for requested intra4x4 mode %d at %d %d\n", - status, h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } else if (status) { - h->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status; - } - } - } - - return 0; -} // FIXME cleanup like ff_h264_check_intra_pred_mode - -/** - * Check if the top & left blocks are available if needed and - * change the dc mode so it only uses the available blocks. - */ -int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma) -{ - static const int8_t top[4] = { LEFT_DC_PRED8x8, 1, -1, -1 }; - static const int8_t left[5] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 }; - - if (mode > 3U) { - av_log(h->avctx, AV_LOG_ERROR, - "out of range intra chroma pred mode at %d %d\n", - h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } - - if (!(h->top_samples_available & 0x8000)) { - mode = top[mode]; - if (mode < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "top block unavailable for requested intra mode at %d %d\n", - h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } - } - - if ((h->left_samples_available & 0x8080) != 0x8080) { - mode = left[mode]; - if (is_chroma && (h->left_samples_available & 0x8080)) { - // mad cow disease mode, aka MBAFF + constrained_intra_pred - mode = ALZHEIMER_DC_L0T_PRED8x8 + - (!(h->left_samples_available & 0x8000)) + - 2 * (mode == DC_128_PRED8x8); - } - if (mode < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "left block unavailable for requested intra mode at %d %d\n", - h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } - } - - return mode; -} - -const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, - int *dst_length, int *consumed, int length) -{ - int i, si, di; - uint8_t *dst; - int bufidx; - - // src[0]&0x80; // forbidden bit - h->nal_ref_idc = src[0] >> 5; - h->nal_unit_type = src[0] & 0x1F; - - src++; - length--; - -#define STARTCODE_TEST \ - if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ - if (src[i + 2] != 3) { \ - /* startcode, so we must be past the end */ \ - length = i; \ - } \ - break; \ - } - -#if HAVE_FAST_UNALIGNED -#define FIND_FIRST_ZERO \ - if (i > 0 && !src[i]) \ - i--; \ - while (src[i]) \ - i++ - -#if HAVE_FAST_64BIT - for (i = 0; i + 1 < length; i += 9) { - if (!((~AV_RN64A(src + i) & - (AV_RN64A(src + i) - 0x0100010001000101ULL)) & - 0x8000800080008080ULL)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 7; - } -#else - for (i = 0; i + 1 < length; i += 5) { - if (!((~AV_RN32A(src + i) & - (AV_RN32A(src + i) - 0x01000101U)) & - 0x80008080U)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 3; - } -#endif -#else - for (i = 0; i + 1 < length; i += 2) { - if (src[i]) - continue; - if (i > 0 && src[i - 1] == 0) - i--; - STARTCODE_TEST; - } -#endif - - if (i >= length - 1) { // no escaped 0 - *dst_length = length; - *consumed = length + 1; // +1 for the header - return src; - } - - // use second escape buffer for inter data - bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; - av_fast_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], - length + FF_INPUT_BUFFER_PADDING_SIZE); - dst = h->rbsp_buffer[bufidx]; - - if (!dst) - return NULL; - - memcpy(dst, src, i); - si = di = i; - while (si + 2 < length) { - // remove escapes (very rare 1:2^22) - if (src[si + 2] > 3) { - dst[di++] = src[si++]; - dst[di++] = src[si++]; - } else if (src[si] == 0 && src[si + 1] == 0) { - if (src[si + 2] == 3) { // escape - dst[di++] = 0; - dst[di++] = 0; - si += 3; - continue; - } else // next start code - goto nsc; - } - - dst[di++] = src[si++]; - } - while (si < length) - dst[di++] = src[si++]; - -nsc: - memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE); - - *dst_length = di; - *consumed = si + 1; // +1 for the header - /* FIXME store exact number of bits in the getbitcontext - * (it is needed for decoding) */ - return dst; -} - -/** - * Identify the exact end of the bitstream - * @return the length of the trailing, or 0 if damaged - */ -static int decode_rbsp_trailing(H264Context *h, const uint8_t *src) -{ - int v = *src; - int r; - - tprintf(h->avctx, "rbsp trailing %X\n", v); - - for (r = 1; r < 9; r++) { - if (v & 1) - return r; - v >>= 1; - } - return 0; -} - -void ff_h264_free_tables(H264Context *h, int free_rbsp) -{ - int i; - H264Context *hx; - - av_freep(&h->intra4x4_pred_mode); - av_freep(&h->chroma_pred_mode_table); - av_freep(&h->cbp_table); - av_freep(&h->mvd_table[0]); - av_freep(&h->mvd_table[1]); - av_freep(&h->direct_table); - av_freep(&h->non_zero_count); - av_freep(&h->slice_table_base); - h->slice_table = NULL; - av_freep(&h->list_counts); - - av_freep(&h->mb2b_xy); - av_freep(&h->mb2br_xy); - - av_buffer_pool_uninit(&h->qscale_table_pool); - av_buffer_pool_uninit(&h->mb_type_pool); - av_buffer_pool_uninit(&h->motion_val_pool); - av_buffer_pool_uninit(&h->ref_index_pool); - - if (free_rbsp && h->DPB) { - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - ff_h264_unref_picture(h, &h->DPB[i]); - av_freep(&h->DPB); - } else if (h->DPB) { - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - h->DPB[i].needs_realloc = 1; - } - - h->cur_pic_ptr = NULL; - - for (i = 0; i < H264_MAX_THREADS; i++) { - hx = h->thread_context[i]; - if (!hx) - continue; - av_freep(&hx->top_borders[1]); - av_freep(&hx->top_borders[0]); - av_freep(&hx->bipred_scratchpad); - av_freep(&hx->edge_emu_buffer); - av_freep(&hx->dc_val_base); - av_freep(&hx->er.mb_index2xy); - av_freep(&hx->er.error_status_table); - av_freep(&hx->er.er_temp_buffer); - av_freep(&hx->er.mbintra_table); - av_freep(&hx->er.mbskip_table); - - if (free_rbsp) { - av_freep(&hx->rbsp_buffer[1]); - av_freep(&hx->rbsp_buffer[0]); - hx->rbsp_buffer_size[0] = 0; - hx->rbsp_buffer_size[1] = 0; - } - if (i) - av_freep(&h->thread_context[i]); - } -} - -int ff_h264_alloc_tables(H264Context *h) -{ - const int big_mb_num = h->mb_stride * (h->mb_height + 1); - const int row_mb_num = h->mb_stride * 2 * h->avctx->thread_count; - int x, y, i; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->intra4x4_pred_mode, - row_mb_num * 8 * sizeof(uint8_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->non_zero_count, - big_mb_num * 48 * sizeof(uint8_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->slice_table_base, - (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->cbp_table, - big_mb_num * sizeof(uint16_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->chroma_pred_mode_table, - big_mb_num * sizeof(uint8_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[0], - 16 * row_mb_num * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[1], - 16 * row_mb_num * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->direct_table, - 4 * big_mb_num * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->list_counts, - big_mb_num * sizeof(uint8_t), fail) - - memset(h->slice_table_base, -1, - (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base)); - h->slice_table = h->slice_table_base + h->mb_stride * 2 + 1; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2b_xy, - big_mb_num * sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2br_xy, - big_mb_num * sizeof(uint32_t), fail); - for (y = 0; y < h->mb_height; y++) - for (x = 0; x < h->mb_width; x++) { - const int mb_xy = x + y * h->mb_stride; - const int b_xy = 4 * x + 4 * y * h->b_stride; - - h->mb2b_xy[mb_xy] = b_xy; - h->mb2br_xy[mb_xy] = 8 * (FMO ? mb_xy : (mb_xy % (2 * h->mb_stride))); - } - - if (!h->dequant4_coeff[0]) - h264_init_dequant_tables(h); - - if (!h->DPB) { - h->DPB = av_mallocz_array(H264_MAX_PICTURE_COUNT, sizeof(*h->DPB)); - if (!h->DPB) - return AVERROR(ENOMEM); - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - av_frame_unref(&h->DPB[i].f); - av_frame_unref(&h->cur_pic.f); - } - - return 0; - -fail: - ff_h264_free_tables(h, 1); - return AVERROR(ENOMEM); -} - -/** - * Init context - * Allocate buffers which are not shared amongst multiple threads. - */ -int ff_h264_context_init(H264Context *h) -{ - ERContext *er = &h->er; - int mb_array_size = h->mb_height * h->mb_stride; - int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); - int c_size = h->mb_stride * (h->mb_height + 1); - int yc_size = y_size + 2 * c_size; - int x, y, i; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[0], - h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[1], - h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) - - h->ref_cache[0][scan8[5] + 1] = - h->ref_cache[0][scan8[7] + 1] = - h->ref_cache[0][scan8[13] + 1] = - h->ref_cache[1][scan8[5] + 1] = - h->ref_cache[1][scan8[7] + 1] = - h->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; - - if (CONFIG_ERROR_RESILIENCE) { - /* init ER */ - er->avctx = h->avctx; - er->mecc = &h->mecc; - er->decode_mb = h264_er_decode_mb; - er->opaque = h; - er->quarter_sample = 1; - - er->mb_num = h->mb_num; - er->mb_width = h->mb_width; - er->mb_height = h->mb_height; - er->mb_stride = h->mb_stride; - er->b8_stride = h->mb_width * 2 + 1; - - // error resilience code looks cleaner with this - FF_ALLOCZ_OR_GOTO(h->avctx, er->mb_index2xy, - (h->mb_num + 1) * sizeof(int), fail); - - for (y = 0; y < h->mb_height; y++) - for (x = 0; x < h->mb_width; x++) - er->mb_index2xy[x + y * h->mb_width] = x + y * h->mb_stride; - - er->mb_index2xy[h->mb_height * h->mb_width] = (h->mb_height - 1) * - h->mb_stride + h->mb_width; - - FF_ALLOCZ_OR_GOTO(h->avctx, er->error_status_table, - mb_array_size * sizeof(uint8_t), fail); - - FF_ALLOC_OR_GOTO(h->avctx, er->mbintra_table, mb_array_size, fail); - memset(er->mbintra_table, 1, mb_array_size); - - FF_ALLOCZ_OR_GOTO(h->avctx, er->mbskip_table, mb_array_size + 2, fail); - - FF_ALLOC_OR_GOTO(h->avctx, er->er_temp_buffer, - h->mb_height * h->mb_stride, fail); - - FF_ALLOCZ_OR_GOTO(h->avctx, h->dc_val_base, - yc_size * sizeof(int16_t), fail); - er->dc_val[0] = h->dc_val_base + h->mb_width * 2 + 2; - er->dc_val[1] = h->dc_val_base + y_size + h->mb_stride + 1; - er->dc_val[2] = er->dc_val[1] + c_size; - for (i = 0; i < yc_size; i++) - h->dc_val_base[i] = 1024; - } - - return 0; - -fail: - return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us -} - -static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, - int parse_extradata); - -int ff_h264_decode_extradata(H264Context *h) -{ - AVCodecContext *avctx = h->avctx; - int ret; - - if (avctx->extradata[0] == 1) { - int i, cnt, nalsize; - unsigned char *p = avctx->extradata; - - h->is_avc = 1; - - if (avctx->extradata_size < 7) { - av_log(avctx, AV_LOG_ERROR, - "avcC %d too short\n", avctx->extradata_size); - return AVERROR_INVALIDDATA; - } - /* sps and pps in the avcC always have length coded with 2 bytes, - * so put a fake nal_length_size = 2 while parsing them */ - h->nal_length_size = 2; - // Decode sps from avcC - cnt = *(p + 5) & 0x1f; // Number of sps - p += 6; - for (i = 0; i < cnt; i++) { - nalsize = AV_RB16(p) + 2; - if (p - avctx->extradata + nalsize > avctx->extradata_size) - return AVERROR_INVALIDDATA; - ret = decode_nal_units(h, p, nalsize, 1); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, - "Decoding sps %d from avcC failed\n", i); - return ret; - } - p += nalsize; - } - // Decode pps from avcC - cnt = *(p++); // Number of pps - for (i = 0; i < cnt; i++) { - nalsize = AV_RB16(p) + 2; - if (p - avctx->extradata + nalsize > avctx->extradata_size) - return AVERROR_INVALIDDATA; - ret = decode_nal_units(h, p, nalsize, 1); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, - "Decoding pps %d from avcC failed\n", i); - return ret; - } - p += nalsize; - } - // Store right nal length size that will be used to parse all other nals - h->nal_length_size = (avctx->extradata[4] & 0x03) + 1; - } else { - h->is_avc = 0; - ret = decode_nal_units(h, avctx->extradata, avctx->extradata_size, 1); - if (ret < 0) - return ret; - } - return 0; -} - -av_cold int ff_h264_decode_init(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - int i; - int ret; - - h->avctx = avctx; - - h->bit_depth_luma = 8; - h->chroma_format_idc = 1; - - ff_h264dsp_init(&h->h264dsp, 8, 1); - ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); - ff_h264qpel_init(&h->h264qpel, 8); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, 8, 1); - - h->dequant_coeff_pps = -1; - - /* needed so that IDCT permutation is known early */ - if (CONFIG_ERROR_RESILIENCE) - ff_me_cmp_init(&h->mecc, h->avctx); - ff_videodsp_init(&h->vdsp, 8); - - memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t)); - memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t)); - - h->picture_structure = PICT_FRAME; - h->slice_context_count = 1; - h->workaround_bugs = avctx->workaround_bugs; - h->flags = avctx->flags; - - /* set defaults */ - // s->decode_mb = ff_h263_decode_mb; - if (!avctx->has_b_frames) - h->low_delay = 1; - - avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; - - ff_h264_decode_init_vlc(); - - ff_init_cabac_states(); - - h->pixel_shift = 0; - h->sps.bit_depth_luma = avctx->bits_per_raw_sample = 8; - - h->thread_context[0] = h; - h->outputed_poc = h->next_outputed_poc = INT_MIN; - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) - h->last_pocs[i] = INT_MIN; - h->prev_poc_msb = 1 << 16; - h->x264_build = -1; - ff_h264_reset_sei(h); - h->recovery_frame = -1; - h->frame_recovered = 0; - if (avctx->codec_id == AV_CODEC_ID_H264) { - if (avctx->ticks_per_frame == 1) - h->avctx->time_base.den *= 2; - avctx->ticks_per_frame = 2; - } - - if (avctx->extradata_size > 0 && avctx->extradata) { - ret = ff_h264_decode_extradata(h); - if (ret < 0) - return ret; - } - - if (h->sps.bitstream_restriction_flag && - h->avctx->has_b_frames < h->sps.num_reorder_frames) { - h->avctx->has_b_frames = h->sps.num_reorder_frames; - h->low_delay = 0; - } - - avctx->internal->allocate_progress = 1; - - return 0; -} - -static int decode_init_thread_copy(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - - if (!avctx->internal->is_copy) - return 0; - memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); - memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); - - h->avctx = avctx; - h->rbsp_buffer[0] = NULL; - h->rbsp_buffer[1] = NULL; - h->rbsp_buffer_size[0] = 0; - h->rbsp_buffer_size[1] = 0; - h->context_initialized = 0; - - return 0; -} - -/** - * Run setup operations that must be run after slice header decoding. - * This includes finding the next displayed frame. - * - * @param h h264 master context - * @param setup_finished enough NALs have been read that we can call - * ff_thread_finish_setup() - */ -static void decode_postinit(H264Context *h, int setup_finished) -{ - H264Picture *out = h->cur_pic_ptr; - H264Picture *cur = h->cur_pic_ptr; - int i, pics, out_of_order, out_idx; - int invalid = 0, cnt = 0; - - h->cur_pic_ptr->f.pict_type = h->pict_type; - - if (h->next_output_pic) - return; - - if (cur->field_poc[0] == INT_MAX || cur->field_poc[1] == INT_MAX) { - /* FIXME: if we have two PAFF fields in one packet, we can't start - * the next thread here. If we have one field per packet, we can. - * The check in decode_nal_units() is not good enough to find this - * yet, so we assume the worst for now. */ - // if (setup_finished) - // ff_thread_finish_setup(h->avctx); - return; - } - - cur->f.interlaced_frame = 0; - cur->f.repeat_pict = 0; - - /* Signal interlacing information externally. */ - /* Prioritize picture timing SEI information over used - * decoding process if it exists. */ - - if (h->sps.pic_struct_present_flag) { - switch (h->sei_pic_struct) { - case SEI_PIC_STRUCT_FRAME: - break; - case SEI_PIC_STRUCT_TOP_FIELD: - case SEI_PIC_STRUCT_BOTTOM_FIELD: - cur->f.interlaced_frame = 1; - break; - case SEI_PIC_STRUCT_TOP_BOTTOM: - case SEI_PIC_STRUCT_BOTTOM_TOP: - if (FIELD_OR_MBAFF_PICTURE(h)) - cur->f.interlaced_frame = 1; - else - // try to flag soft telecine progressive - cur->f.interlaced_frame = h->prev_interlaced_frame; - break; - case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: - case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: - /* Signal the possibility of telecined film externally - * (pic_struct 5,6). From these hints, let the applications - * decide if they apply deinterlacing. */ - cur->f.repeat_pict = 1; - break; - case SEI_PIC_STRUCT_FRAME_DOUBLING: - cur->f.repeat_pict = 2; - break; - case SEI_PIC_STRUCT_FRAME_TRIPLING: - cur->f.repeat_pict = 4; - break; - } - - if ((h->sei_ct_type & 3) && - h->sei_pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) - cur->f.interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0; - } else { - /* Derive interlacing flag from used decoding process. */ - cur->f.interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); - } - h->prev_interlaced_frame = cur->f.interlaced_frame; - - if (cur->field_poc[0] != cur->field_poc[1]) { - /* Derive top_field_first from field pocs. */ - cur->f.top_field_first = cur->field_poc[0] < cur->field_poc[1]; - } else { - if (cur->f.interlaced_frame || h->sps.pic_struct_present_flag) { - /* Use picture timing SEI information. Even if it is a - * information of a past frame, better than nothing. */ - if (h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || - h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) - cur->f.top_field_first = 1; - else - cur->f.top_field_first = 0; - } else { - /* Most likely progressive */ - cur->f.top_field_first = 0; - } - } - - if (h->sei_frame_packing_present && - h->frame_packing_arrangement_type >= 0 && - h->frame_packing_arrangement_type <= 6 && - h->content_interpretation_type > 0 && - h->content_interpretation_type < 3) { - AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f); - if (!stereo) - return; - - switch (h->frame_packing_arrangement_type) { - case 0: - stereo->type = AV_STEREO3D_CHECKERBOARD; - break; - case 1: - stereo->type = AV_STEREO3D_COLUMNS; - break; - case 2: - stereo->type = AV_STEREO3D_LINES; - break; - case 3: - if (h->quincunx_subsampling) - stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; - else - stereo->type = AV_STEREO3D_SIDEBYSIDE; - break; - case 4: - stereo->type = AV_STEREO3D_TOPBOTTOM; - break; - case 5: - stereo->type = AV_STEREO3D_FRAMESEQUENCE; - break; - case 6: - stereo->type = AV_STEREO3D_2D; - break; - } - - if (h->content_interpretation_type == 2) - stereo->flags = AV_STEREO3D_FLAG_INVERT; - } - - if (h->sei_display_orientation_present && - (h->sei_anticlockwise_rotation || h->sei_hflip || h->sei_vflip)) { - double angle = h->sei_anticlockwise_rotation * 360 / (double) (1 << 16); - AVFrameSideData *rotation = av_frame_new_side_data(&cur->f, - AV_FRAME_DATA_DISPLAYMATRIX, - sizeof(int32_t) * 9); - if (!rotation) - return; - - av_display_rotation_set((int32_t *)rotation->data, angle); - av_display_matrix_flip((int32_t *)rotation->data, - h->sei_hflip, h->sei_vflip); - } - - // FIXME do something with unavailable reference frames - - /* Sort B-frames into display order */ - - if (h->sps.bitstream_restriction_flag && - h->avctx->has_b_frames < h->sps.num_reorder_frames) { - h->avctx->has_b_frames = h->sps.num_reorder_frames; - h->low_delay = 0; - } - - if (h->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT && - !h->sps.bitstream_restriction_flag) { - h->avctx->has_b_frames = MAX_DELAYED_PIC_COUNT - 1; - h->low_delay = 0; - } - - pics = 0; - while (h->delayed_pic[pics]) - pics++; - - assert(pics <= MAX_DELAYED_PIC_COUNT); - - h->delayed_pic[pics++] = cur; - if (cur->reference == 0) - cur->reference = DELAYED_PIC_REF; - - /* Frame reordering. This code takes pictures from coding order and sorts - * them by their incremental POC value into display order. It supports POC - * gaps, MMCO reset codes and random resets. - * A "display group" can start either with a IDR frame (f.key_frame = 1), - * and/or can be closed down with a MMCO reset code. In sequences where - * there is no delay, we can't detect that (since the frame was already - * output to the user), so we also set h->mmco_reset to detect the MMCO - * reset code. - * FIXME: if we detect insufficient delays (as per h->avctx->has_b_frames), - * we increase the delay between input and output. All frames affected by - * the lag (e.g. those that should have been output before another frame - * that we already returned to the user) will be dropped. This is a bug - * that we will fix later. */ - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { - cnt += out->poc < h->last_pocs[i]; - invalid += out->poc == INT_MIN; - } - if (!h->mmco_reset && !cur->f.key_frame && - cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) { - h->mmco_reset = 2; - if (pics > 1) - h->delayed_pic[pics - 2]->mmco_reset = 2; - } - if (h->mmco_reset || cur->f.key_frame) { - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) - h->last_pocs[i] = INT_MIN; - cnt = 0; - invalid = MAX_DELAYED_PIC_COUNT; - } - out = h->delayed_pic[0]; - out_idx = 0; - for (i = 1; i < MAX_DELAYED_PIC_COUNT && - h->delayed_pic[i] && - !h->delayed_pic[i - 1]->mmco_reset && - !h->delayed_pic[i]->f.key_frame; - i++) - if (h->delayed_pic[i]->poc < out->poc) { - out = h->delayed_pic[i]; - out_idx = i; - } - if (h->avctx->has_b_frames == 0 && - (h->delayed_pic[0]->f.key_frame || h->mmco_reset)) - h->next_outputed_poc = INT_MIN; - out_of_order = !out->f.key_frame && !h->mmco_reset && - (out->poc < h->next_outputed_poc); - - if (h->sps.bitstream_restriction_flag && - h->avctx->has_b_frames >= h->sps.num_reorder_frames) { - } else if (out_of_order && pics - 1 == h->avctx->has_b_frames && - h->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) { - if (invalid + cnt < MAX_DELAYED_PIC_COUNT) { - h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, cnt); - } - h->low_delay = 0; - } else if (h->low_delay && - ((h->next_outputed_poc != INT_MIN && - out->poc > h->next_outputed_poc + 2) || - cur->f.pict_type == AV_PICTURE_TYPE_B)) { - h->low_delay = 0; - h->avctx->has_b_frames++; - } - - if (pics > h->avctx->has_b_frames) { - out->reference &= ~DELAYED_PIC_REF; - // for frame threading, the owner must be the second field's thread or - // else the first thread can release the picture and reuse it unsafely - for (i = out_idx; h->delayed_pic[i]; i++) - h->delayed_pic[i] = h->delayed_pic[i + 1]; - } - memmove(h->last_pocs, &h->last_pocs[1], - sizeof(*h->last_pocs) * (MAX_DELAYED_PIC_COUNT - 1)); - h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = cur->poc; - if (!out_of_order && pics > h->avctx->has_b_frames) { - h->next_output_pic = out; - if (out->mmco_reset) { - if (out_idx > 0) { - h->next_outputed_poc = out->poc; - h->delayed_pic[out_idx - 1]->mmco_reset = out->mmco_reset; - } else { - h->next_outputed_poc = INT_MIN; - } - } else { - if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f.key_frame) { - h->next_outputed_poc = INT_MIN; - } else { - h->next_outputed_poc = out->poc; - } - } - h->mmco_reset = 0; - } else { - av_log(h->avctx, AV_LOG_DEBUG, "no picture\n"); - } - - if (h->next_output_pic) { - if (h->next_output_pic->recovered) { - // We have reached an recovery point and all frames after it in - // display order are "recovered". - h->frame_recovered |= FRAME_RECOVERED_SEI; - } - h->next_output_pic->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_SEI); - } - - if (setup_finished && !h->avctx->hwaccel) - ff_thread_finish_setup(h->avctx); -} - -int ff_pred_weight_table(H264Context *h) -{ - int list, i; - int luma_def, chroma_def; - - h->use_weight = 0; - h->use_weight_chroma = 0; - h->luma_log2_weight_denom = get_ue_golomb(&h->gb); - if (h->sps.chroma_format_idc) - h->chroma_log2_weight_denom = get_ue_golomb(&h->gb); - luma_def = 1 << h->luma_log2_weight_denom; - chroma_def = 1 << h->chroma_log2_weight_denom; - - for (list = 0; list < 2; list++) { - h->luma_weight_flag[list] = 0; - h->chroma_weight_flag[list] = 0; - for (i = 0; i < h->ref_count[list]; i++) { - int luma_weight_flag, chroma_weight_flag; - - luma_weight_flag = get_bits1(&h->gb); - if (luma_weight_flag) { - h->luma_weight[i][list][0] = get_se_golomb(&h->gb); - h->luma_weight[i][list][1] = get_se_golomb(&h->gb); - if (h->luma_weight[i][list][0] != luma_def || - h->luma_weight[i][list][1] != 0) { - h->use_weight = 1; - h->luma_weight_flag[list] = 1; - } - } else { - h->luma_weight[i][list][0] = luma_def; - h->luma_weight[i][list][1] = 0; - } - - if (h->sps.chroma_format_idc) { - chroma_weight_flag = get_bits1(&h->gb); - if (chroma_weight_flag) { - int j; - for (j = 0; j < 2; j++) { - h->chroma_weight[i][list][j][0] = get_se_golomb(&h->gb); - h->chroma_weight[i][list][j][1] = get_se_golomb(&h->gb); - if (h->chroma_weight[i][list][j][0] != chroma_def || - h->chroma_weight[i][list][j][1] != 0) { - h->use_weight_chroma = 1; - h->chroma_weight_flag[list] = 1; - } - } - } else { - int j; - for (j = 0; j < 2; j++) { - h->chroma_weight[i][list][j][0] = chroma_def; - h->chroma_weight[i][list][j][1] = 0; - } - } - } - } - if (h->slice_type_nos != AV_PICTURE_TYPE_B) - break; - } - h->use_weight = h->use_weight || h->use_weight_chroma; - return 0; -} - -/** - * instantaneous decoder refresh. - */ -static void idr(H264Context *h) -{ - ff_h264_remove_all_refs(h); - h->prev_frame_num = - h->prev_frame_num_offset = - h->prev_poc_msb = - h->prev_poc_lsb = 0; -} - -/* forget old pics after a seek */ -void ff_h264_flush_change(H264Context *h) -{ - int i; - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) - h->last_pocs[i] = INT_MIN; - h->outputed_poc = h->next_outputed_poc = INT_MIN; - h->prev_interlaced_frame = 1; - idr(h); - if (h->cur_pic_ptr) - h->cur_pic_ptr->reference = 0; - h->first_field = 0; - memset(h->ref_list[0], 0, sizeof(h->ref_list[0])); - memset(h->ref_list[1], 0, sizeof(h->ref_list[1])); - memset(h->default_ref_list[0], 0, sizeof(h->default_ref_list[0])); - memset(h->default_ref_list[1], 0, sizeof(h->default_ref_list[1])); - ff_h264_reset_sei(h); - h->recovery_frame = -1; - h->frame_recovered = 0; -} - -/* forget old pics after a seek */ -static void flush_dpb(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - int i; - - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { - if (h->delayed_pic[i]) - h->delayed_pic[i]->reference = 0; - h->delayed_pic[i] = NULL; - } - - ff_h264_flush_change(h); - - if (h->DPB) - for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) - ff_h264_unref_picture(h, &h->DPB[i]); - h->cur_pic_ptr = NULL; - ff_h264_unref_picture(h, &h->cur_pic); - - h->mb_x = h->mb_y = 0; - - h->parse_context.state = -1; - h->parse_context.frame_start_found = 0; - h->parse_context.overread = 0; - h->parse_context.overread_index = 0; - h->parse_context.index = 0; - h->parse_context.last_index = 0; - - ff_h264_free_tables(h, 1); - h->context_initialized = 0; -} - -int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc) -{ - const int max_frame_num = 1 << h->sps.log2_max_frame_num; - int field_poc[2]; - - h->frame_num_offset = h->prev_frame_num_offset; - if (h->frame_num < h->prev_frame_num) - h->frame_num_offset += max_frame_num; - - if (h->sps.poc_type == 0) { - const int max_poc_lsb = 1 << h->sps.log2_max_poc_lsb; - - if (h->poc_lsb < h->prev_poc_lsb && - h->prev_poc_lsb - h->poc_lsb >= max_poc_lsb / 2) - h->poc_msb = h->prev_poc_msb + max_poc_lsb; - else if (h->poc_lsb > h->prev_poc_lsb && - h->prev_poc_lsb - h->poc_lsb < -max_poc_lsb / 2) - h->poc_msb = h->prev_poc_msb - max_poc_lsb; - else - h->poc_msb = h->prev_poc_msb; - field_poc[0] = - field_poc[1] = h->poc_msb + h->poc_lsb; - if (h->picture_structure == PICT_FRAME) - field_poc[1] += h->delta_poc_bottom; - } else if (h->sps.poc_type == 1) { - int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc; - int i; - - if (h->sps.poc_cycle_length != 0) - abs_frame_num = h->frame_num_offset + h->frame_num; - else - abs_frame_num = 0; - - if (h->nal_ref_idc == 0 && abs_frame_num > 0) - abs_frame_num--; - - expected_delta_per_poc_cycle = 0; - for (i = 0; i < h->sps.poc_cycle_length; i++) - // FIXME integrate during sps parse - expected_delta_per_poc_cycle += h->sps.offset_for_ref_frame[i]; - - if (abs_frame_num > 0) { - int poc_cycle_cnt = (abs_frame_num - 1) / h->sps.poc_cycle_length; - int frame_num_in_poc_cycle = (abs_frame_num - 1) % h->sps.poc_cycle_length; - - expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle; - for (i = 0; i <= frame_num_in_poc_cycle; i++) - expectedpoc = expectedpoc + h->sps.offset_for_ref_frame[i]; - } else - expectedpoc = 0; - - if (h->nal_ref_idc == 0) - expectedpoc = expectedpoc + h->sps.offset_for_non_ref_pic; - - field_poc[0] = expectedpoc + h->delta_poc[0]; - field_poc[1] = field_poc[0] + h->sps.offset_for_top_to_bottom_field; - - if (h->picture_structure == PICT_FRAME) - field_poc[1] += h->delta_poc[1]; - } else { - int poc = 2 * (h->frame_num_offset + h->frame_num); - - if (!h->nal_ref_idc) - poc--; - - field_poc[0] = poc; - field_poc[1] = poc; - } - - if (h->picture_structure != PICT_BOTTOM_FIELD) - pic_field_poc[0] = field_poc[0]; - if (h->picture_structure != PICT_TOP_FIELD) - pic_field_poc[1] = field_poc[1]; - *pic_poc = FFMIN(pic_field_poc[0], pic_field_poc[1]); - - return 0; -} - -/** - * Compute profile from profile_idc and constraint_set?_flags. - * - * @param sps SPS - * - * @return profile as defined by FF_PROFILE_H264_* - */ -int ff_h264_get_profile(SPS *sps) -{ - int profile = sps->profile_idc; - - switch (sps->profile_idc) { - case FF_PROFILE_H264_BASELINE: - // constraint_set1_flag set to 1 - profile |= (sps->constraint_set_flags & 1 << 1) ? FF_PROFILE_H264_CONSTRAINED : 0; - break; - case FF_PROFILE_H264_HIGH_10: - case FF_PROFILE_H264_HIGH_422: - case FF_PROFILE_H264_HIGH_444_PREDICTIVE: - // constraint_set3_flag set to 1 - profile |= (sps->constraint_set_flags & 1 << 3) ? FF_PROFILE_H264_INTRA : 0; - break; - } - - return profile; -} - -int ff_h264_set_parameter_from_sps(H264Context *h) -{ - if (h->flags & CODEC_FLAG_LOW_DELAY || - (h->sps.bitstream_restriction_flag && - !h->sps.num_reorder_frames)) { - if (h->avctx->has_b_frames > 1 || h->delayed_pic[0]) - av_log(h->avctx, AV_LOG_WARNING, "Delayed frames seen. " - "Reenabling low delay requires a codec flush.\n"); - else - h->low_delay = 1; - } - - if (h->avctx->has_b_frames < 2) - h->avctx->has_b_frames = !h->low_delay; - - if (h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || - h->cur_chroma_format_idc != h->sps.chroma_format_idc) { - if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) { - h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; - h->cur_chroma_format_idc = h->sps.chroma_format_idc; - h->pixel_shift = h->sps.bit_depth_luma > 8; - - ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, - h->sps.chroma_format_idc); - ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); - ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma, - h->sps.chroma_format_idc); - if (CONFIG_ERROR_RESILIENCE) - ff_me_cmp_init(&h->mecc, h->avctx); - ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma); - } else { - av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n", - h->sps.bit_depth_luma); - return AVERROR_INVALIDDATA; - } - } - return 0; -} - -int ff_set_ref_count(H264Context *h) -{ - int ref_count[2], list_count; - int num_ref_idx_active_override_flag, max_refs; - - // set defaults, might be overridden a few lines later - ref_count[0] = h->pps.ref_count[0]; - ref_count[1] = h->pps.ref_count[1]; - - if (h->slice_type_nos != AV_PICTURE_TYPE_I) { - if (h->slice_type_nos == AV_PICTURE_TYPE_B) - h->direct_spatial_mv_pred = get_bits1(&h->gb); - num_ref_idx_active_override_flag = get_bits1(&h->gb); - - if (num_ref_idx_active_override_flag) { - ref_count[0] = get_ue_golomb(&h->gb) + 1; - if (ref_count[0] < 1) - return AVERROR_INVALIDDATA; - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { - ref_count[1] = get_ue_golomb(&h->gb) + 1; - if (ref_count[1] < 1) - return AVERROR_INVALIDDATA; - } - } - - if (h->slice_type_nos == AV_PICTURE_TYPE_B) - list_count = 2; - else - list_count = 1; - } else { - list_count = 0; - ref_count[0] = ref_count[1] = 0; - } - - max_refs = h->picture_structure == PICT_FRAME ? 16 : 32; - - if (ref_count[0] > max_refs || ref_count[1] > max_refs) { - av_log(h->avctx, AV_LOG_ERROR, "reference overflow\n"); - h->ref_count[0] = h->ref_count[1] = 0; - return AVERROR_INVALIDDATA; - } - - if (list_count != h->list_count || - ref_count[0] != h->ref_count[0] || - ref_count[1] != h->ref_count[1]) { - h->ref_count[0] = ref_count[0]; - h->ref_count[1] = ref_count[1]; - h->list_count = list_count; - return 1; - } - - return 0; -} - -static int find_start_code(const uint8_t *buf, int buf_size, - int buf_index, int next_avc) -{ - // start code prefix search - for (; buf_index + 3 < next_avc; buf_index++) - // This should always succeed in the first iteration. - if (buf[buf_index] == 0 && - buf[buf_index + 1] == 0 && - buf[buf_index + 2] == 1) - break; - - if (buf_index + 3 >= buf_size) - return buf_size; - - return buf_index + 3; -} - -static int get_avc_nalsize(H264Context *h, const uint8_t *buf, - int buf_size, int *buf_index) -{ - int i, nalsize = 0; - - if (*buf_index >= buf_size - h->nal_length_size) - return -1; - - for (i = 0; i < h->nal_length_size; i++) - nalsize = (nalsize << 8) | buf[(*buf_index)++]; - if (nalsize <= 0 || nalsize > buf_size - *buf_index) { - av_log(h->avctx, AV_LOG_ERROR, - "AVC: nal size %d\n", nalsize); - return -1; - } - return nalsize; -} - -static int get_bit_length(H264Context *h, const uint8_t *buf, - const uint8_t *ptr, int dst_length, - int i, int next_avc) -{ - if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc && - buf[i] == 0x00 && buf[i + 1] == 0x00 && - buf[i + 2] == 0x01 && buf[i + 3] == 0xE0) - h->workaround_bugs |= FF_BUG_TRUNCATED; - - if (!(h->workaround_bugs & FF_BUG_TRUNCATED)) - while (dst_length > 0 && ptr[dst_length - 1] == 0) - dst_length--; - - if (!dst_length) - return 0; - - return 8 * dst_length - decode_rbsp_trailing(h, ptr + dst_length - 1); -} - -static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size) -{ - int next_avc = h->is_avc ? 0 : buf_size; - int nal_index = 0; - int buf_index = 0; - int nals_needed = 0; - - while(1) { - int nalsize = 0; - int dst_length, bit_length, consumed; - const uint8_t *ptr; - - if (buf_index >= next_avc) { - nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index); - if (nalsize < 0) - break; - next_avc = buf_index + nalsize; - } else { - buf_index = find_start_code(buf, buf_size, buf_index, next_avc); - if (buf_index >= buf_size) - break; - } - - ptr = ff_h264_decode_nal(h, buf + buf_index, &dst_length, &consumed, - next_avc - buf_index); - - if (!ptr || dst_length < 0) - return AVERROR_INVALIDDATA; - - buf_index += consumed; - - bit_length = get_bit_length(h, buf, ptr, dst_length, - buf_index, next_avc); - nal_index++; - - /* packets can sometimes contain multiple PPS/SPS, - * e.g. two PAFF field pictures in one packet, or a demuxer - * which splits NALs strangely if so, when frame threading we - * can't start the next thread until we've read all of them */ - switch (h->nal_unit_type) { - case NAL_SPS: - case NAL_PPS: - nals_needed = nal_index; - break; - case NAL_DPA: - case NAL_IDR_SLICE: - case NAL_SLICE: - init_get_bits(&h->gb, ptr, bit_length); - if (!get_ue_golomb(&h->gb)) - nals_needed = nal_index; - } - } - - return nals_needed; -} - -static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, - int parse_extradata) -{ - AVCodecContext *const avctx = h->avctx; - H264Context *hx; ///< thread context - int buf_index; - unsigned context_count; - int next_avc; - int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts - int nal_index; - int ret = 0; - - h->max_contexts = h->slice_context_count; - if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS)) { - h->current_slice = 0; - if (!h->first_field) - h->cur_pic_ptr = NULL; - ff_h264_reset_sei(h); - } - - if (avctx->active_thread_type & FF_THREAD_FRAME) - nals_needed = get_last_needed_nal(h, buf, buf_size); - - { - buf_index = 0; - context_count = 0; - next_avc = h->is_avc ? 0 : buf_size; - nal_index = 0; - for (;;) { - int consumed; - int dst_length; - int bit_length; - const uint8_t *ptr; - int nalsize = 0; - int err; - - if (buf_index >= next_avc) { - nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index); - if (nalsize < 0) - break; - next_avc = buf_index + nalsize; - } else { - buf_index = find_start_code(buf, buf_size, buf_index, next_avc); - if (buf_index >= buf_size) - break; - if (buf_index >= next_avc) - continue; - } - - hx = h->thread_context[context_count]; - - ptr = ff_h264_decode_nal(hx, buf + buf_index, &dst_length, - &consumed, next_avc - buf_index); - if (!ptr || dst_length < 0) { - ret = -1; - goto end; - } - - bit_length = get_bit_length(h, buf, ptr, dst_length, - buf_index + consumed, next_avc); - - if (h->avctx->debug & FF_DEBUG_STARTCODE) - av_log(h->avctx, AV_LOG_DEBUG, - "NAL %d at %d/%d length %d\n", - hx->nal_unit_type, buf_index, buf_size, dst_length); - - if (h->is_avc && (nalsize != consumed) && nalsize) - av_log(h->avctx, AV_LOG_DEBUG, - "AVC: Consumed only %d bytes instead of %d\n", - consumed, nalsize); - - buf_index += consumed; - nal_index++; - - if (avctx->skip_frame >= AVDISCARD_NONREF && - h->nal_ref_idc == 0 && - h->nal_unit_type != NAL_SEI) - continue; - -again: - /* Ignore every NAL unit type except PPS and SPS during extradata - * parsing. Decoding slices is not possible in codec init - * with frame-mt */ - if (parse_extradata && HAVE_THREADS && - (h->avctx->active_thread_type & FF_THREAD_FRAME) && - (hx->nal_unit_type != NAL_PPS && - hx->nal_unit_type != NAL_SPS)) { - if (hx->nal_unit_type < NAL_AUD || - hx->nal_unit_type > NAL_AUXILIARY_SLICE) - av_log(avctx, AV_LOG_INFO, - "Ignoring NAL unit %d during extradata parsing\n", - hx->nal_unit_type); - hx->nal_unit_type = NAL_FF_IGNORE; - } - err = 0; - switch (hx->nal_unit_type) { - case NAL_IDR_SLICE: - if (h->nal_unit_type != NAL_IDR_SLICE) { - av_log(h->avctx, AV_LOG_ERROR, - "Invalid mix of idr and non-idr slices\n"); - ret = -1; - goto end; - } - idr(h); // FIXME ensure we don't lose some frames if there is reordering - case NAL_SLICE: - init_get_bits(&hx->gb, ptr, bit_length); - hx->intra_gb_ptr = - hx->inter_gb_ptr = &hx->gb; - hx->data_partitioning = 0; - - if ((err = ff_h264_decode_slice_header(hx, h))) - break; - - if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame < 0) { - h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) & - ((1 << h->sps.log2_max_frame_num) - 1); - } - - h->cur_pic_ptr->f.key_frame |= - (hx->nal_unit_type == NAL_IDR_SLICE) || - (h->sei_recovery_frame_cnt >= 0); - - if (hx->nal_unit_type == NAL_IDR_SLICE || - h->recovery_frame == h->frame_num) { - h->recovery_frame = -1; - h->cur_pic_ptr->recovered = 1; - } - // If we have an IDR, all frames after it in decoded order are - // "recovered". - if (hx->nal_unit_type == NAL_IDR_SLICE) - h->frame_recovered |= FRAME_RECOVERED_IDR; - h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR); - - if (h->current_slice == 1) { - if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS)) - decode_postinit(h, nal_index >= nals_needed); - - if (h->avctx->hwaccel && - (ret = h->avctx->hwaccel->start_frame(h->avctx, NULL, 0)) < 0) - return ret; - } - - if (hx->redundant_pic_count == 0 && - (avctx->skip_frame < AVDISCARD_NONREF || - hx->nal_ref_idc) && - (avctx->skip_frame < AVDISCARD_BIDIR || - hx->slice_type_nos != AV_PICTURE_TYPE_B) && - (avctx->skip_frame < AVDISCARD_NONKEY || - hx->slice_type_nos == AV_PICTURE_TYPE_I) && - avctx->skip_frame < AVDISCARD_ALL) { - if (avctx->hwaccel) { - ret = avctx->hwaccel->decode_slice(avctx, - &buf[buf_index - consumed], - consumed); - if (ret < 0) - return ret; - } else - context_count++; - } - break; - case NAL_DPA: - if (h->avctx->flags & CODEC_FLAG2_CHUNKS) { - av_log(h->avctx, AV_LOG_ERROR, - "Decoding in chunks is not supported for " - "partitioned slices.\n"); - return AVERROR(ENOSYS); - } - - init_get_bits(&hx->gb, ptr, bit_length); - hx->intra_gb_ptr = - hx->inter_gb_ptr = NULL; - - if ((err = ff_h264_decode_slice_header(hx, h)) < 0) { - /* make sure data_partitioning is cleared if it was set - * before, so we don't try decoding a slice without a valid - * slice header later */ - h->data_partitioning = 0; - break; - } - - hx->data_partitioning = 1; - break; - case NAL_DPB: - init_get_bits(&hx->intra_gb, ptr, bit_length); - hx->intra_gb_ptr = &hx->intra_gb; - break; - case NAL_DPC: - init_get_bits(&hx->inter_gb, ptr, bit_length); - hx->inter_gb_ptr = &hx->inter_gb; - - if (hx->redundant_pic_count == 0 && - hx->intra_gb_ptr && - hx->data_partitioning && - h->cur_pic_ptr && h->context_initialized && - (avctx->skip_frame < AVDISCARD_NONREF || hx->nal_ref_idc) && - (avctx->skip_frame < AVDISCARD_BIDIR || - hx->slice_type_nos != AV_PICTURE_TYPE_B) && - (avctx->skip_frame < AVDISCARD_NONKEY || - hx->slice_type_nos == AV_PICTURE_TYPE_I) && - avctx->skip_frame < AVDISCARD_ALL) - context_count++; - break; - case NAL_SEI: - init_get_bits(&h->gb, ptr, bit_length); - ret = ff_h264_decode_sei(h); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - goto end; - break; - case NAL_SPS: - init_get_bits(&h->gb, ptr, bit_length); - ret = ff_h264_decode_seq_parameter_set(h); - if (ret < 0 && h->is_avc && (nalsize != consumed) && nalsize) { - av_log(h->avctx, AV_LOG_DEBUG, - "SPS decoding failure, trying again with the complete NAL\n"); - init_get_bits(&h->gb, buf + buf_index + 1 - consumed, - 8 * (nalsize - 1)); - ff_h264_decode_seq_parameter_set(h); - } - - ret = ff_h264_set_parameter_from_sps(h); - if (ret < 0) - goto end; - - break; - case NAL_PPS: - init_get_bits(&h->gb, ptr, bit_length); - ret = ff_h264_decode_picture_parameter_set(h, bit_length); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - goto end; - break; - case NAL_AUD: - case NAL_END_SEQUENCE: - case NAL_END_STREAM: - case NAL_FILLER_DATA: - case NAL_SPS_EXT: - case NAL_AUXILIARY_SLICE: - break; - case NAL_FF_IGNORE: - break; - default: - av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n", - hx->nal_unit_type, bit_length); - } - - if (context_count == h->max_contexts) { - ret = ff_h264_execute_decode_slices(h, context_count); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - goto end; - context_count = 0; - } - - if (err < 0) { - av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n"); - h->ref_count[0] = h->ref_count[1] = h->list_count = 0; - } else if (err == 1) { - /* Slice could not be decoded in parallel mode, copy down - * NAL unit stuff to context 0 and restart. Note that - * rbsp_buffer is not transferred, but since we no longer - * run in parallel mode this should not be an issue. */ - h->nal_unit_type = hx->nal_unit_type; - h->nal_ref_idc = hx->nal_ref_idc; - hx = h; - goto again; - } - } - } - if (context_count) { - ret = ff_h264_execute_decode_slices(h, context_count); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - goto end; - } - - ret = 0; -end: - /* clean up */ - if (h->cur_pic_ptr && !h->droppable) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - } - - return (ret < 0) ? ret : buf_index; -} - -/** - * Return the number of bytes consumed for building the current frame. - */ -static int get_consumed_bytes(int pos, int buf_size) -{ - if (pos == 0) - pos = 1; // avoid infinite loops (I doubt that is needed but...) - if (pos + 10 > buf_size) - pos = buf_size; // oops ;) - - return pos; -} - -static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src) -{ - int i; - int ret = av_frame_ref(dst, src); - if (ret < 0) - return ret; - - if (!h->sps.crop) - return 0; - - for (i = 0; i < 3; i++) { - int hshift = (i > 0) ? h->chroma_x_shift : 0; - int vshift = (i > 0) ? h->chroma_y_shift : 0; - int off = ((h->sps.crop_left >> hshift) << h->pixel_shift) + - (h->sps.crop_top >> vshift) * dst->linesize[i]; - dst->data[i] += off; - } - return 0; -} - -static int h264_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) -{ - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - H264Context *h = avctx->priv_data; - AVFrame *pict = data; - int buf_index = 0; - int ret; - - h->flags = avctx->flags; - /* reset data partitioning here, to ensure GetBitContexts from previous - * packets do not get used. */ - h->data_partitioning = 0; - - /* end of stream, output what is still in the buffers */ -out: - if (buf_size == 0) { - H264Picture *out; - int i, out_idx; - - h->cur_pic_ptr = NULL; - - // FIXME factorize this with the output code below - out = h->delayed_pic[0]; - out_idx = 0; - for (i = 1; - h->delayed_pic[i] && - !h->delayed_pic[i]->f.key_frame && - !h->delayed_pic[i]->mmco_reset; - i++) - if (h->delayed_pic[i]->poc < out->poc) { - out = h->delayed_pic[i]; - out_idx = i; - } - - for (i = out_idx; h->delayed_pic[i]; i++) - h->delayed_pic[i] = h->delayed_pic[i + 1]; - - if (out) { - ret = output_frame(h, pict, &out->f); - if (ret < 0) - return ret; - *got_frame = 1; - } - - return buf_index; - } - - buf_index = decode_nal_units(h, buf, buf_size, 0); - if (buf_index < 0) - return AVERROR_INVALIDDATA; - - if (!h->cur_pic_ptr && h->nal_unit_type == NAL_END_SEQUENCE) { - buf_size = 0; - goto out; - } - - if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS) && !h->cur_pic_ptr) { - if (avctx->skip_frame >= AVDISCARD_NONREF) - return 0; - av_log(avctx, AV_LOG_ERROR, "no frame!\n"); - return AVERROR_INVALIDDATA; - } - - if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS) || - (h->mb_y >= h->mb_height && h->mb_height)) { - if (avctx->flags2 & CODEC_FLAG2_CHUNKS) - decode_postinit(h, 1); - - ff_h264_field_end(h, 0); - - *got_frame = 0; - if (h->next_output_pic && ((avctx->flags & CODEC_FLAG_OUTPUT_CORRUPT) || - h->next_output_pic->recovered)) { - if (!h->next_output_pic->recovered) - h->next_output_pic->f.flags |= AV_FRAME_FLAG_CORRUPT; - - ret = output_frame(h, pict, &h->next_output_pic->f); - if (ret < 0) - return ret; - *got_frame = 1; - } - } - - assert(pict->buf[0] || !*got_frame); - - return get_consumed_bytes(buf_index, buf_size); -} - -av_cold void ff_h264_free_context(H264Context *h) -{ - int i; - - ff_h264_free_tables(h, 1); // FIXME cleanup init stuff perhaps - - for (i = 0; i < MAX_SPS_COUNT; i++) - av_freep(h->sps_buffers + i); - - for (i = 0; i < MAX_PPS_COUNT; i++) - av_freep(h->pps_buffers + i); -} - -static av_cold int h264_decode_end(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - - ff_h264_free_context(h); - - ff_h264_unref_picture(h, &h->cur_pic); - - return 0; -} - -static const AVProfile profiles[] = { - { FF_PROFILE_H264_BASELINE, "Baseline" }, - { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" }, - { FF_PROFILE_H264_MAIN, "Main" }, - { FF_PROFILE_H264_EXTENDED, "Extended" }, - { FF_PROFILE_H264_HIGH, "High" }, - { FF_PROFILE_H264_HIGH_10, "High 10" }, - { FF_PROFILE_H264_HIGH_10_INTRA, "High 10 Intra" }, - { FF_PROFILE_H264_HIGH_422, "High 4:2:2" }, - { FF_PROFILE_H264_HIGH_422_INTRA, "High 4:2:2 Intra" }, - { FF_PROFILE_H264_HIGH_444, "High 4:4:4" }, - { FF_PROFILE_H264_HIGH_444_PREDICTIVE, "High 4:4:4 Predictive" }, - { FF_PROFILE_H264_HIGH_444_INTRA, "High 4:4:4 Intra" }, - { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" }, - { FF_PROFILE_UNKNOWN }, -}; - -AVCodec ff_h264_decoder = { - .name = "h264", - .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .priv_data_size = sizeof(H264Context), - .init = ff_h264_decode_init, - .close = h264_decode_end, - .decode = h264_decode_frame, - .capabilities = /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | - CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS | - CODEC_CAP_FRAME_THREADS, - .flush = flush_dpb, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), - .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), - .profiles = NULL_IF_CONFIG_SMALL(profiles), -}; diff --git a/libavcodec/h264.h b/libavcodec/h264.h index cd4bf87..eb3805c 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -1,7 +1,4 @@ /* - * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder - * Copyright (c) 2003 Michael Niedermayer - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -21,1036 +18,30 @@ /** * @file - * H.264 / AVC / MPEG4 part10 codec. - * @author Michael Niedermayer + * H.264 common definitions */ #ifndef AVCODEC_H264_H #define AVCODEC_H264_H -#include "libavutil/intreadwrite.h" -#include "cabac.h" -#include "error_resilience.h" -#include "get_bits.h" -#include "h264chroma.h" -#include "h264dsp.h" -#include "h264pred.h" -#include "h264qpel.h" -#include "me_cmp.h" -#include "mpegutils.h" -#include "parser.h" -#include "qpeldsp.h" -#include "rectangle.h" -#include "videodsp.h" - -#define H264_MAX_PICTURE_COUNT 32 -#define H264_MAX_THREADS 16 - -#define MAX_SPS_COUNT 32 -#define MAX_PPS_COUNT 256 - -#define MAX_MMCO_COUNT 66 - -#define MAX_DELAYED_PIC_COUNT 16 - -/* Compiling in interlaced support reduces the speed - * of progressive decoding by about 2%. */ -#define ALLOW_INTERLACE - -#define FMO 0 - -/** - * The maximum number of slices supported by the decoder. - * must be a power of 2 - */ -#define MAX_SLICES 16 - -#ifdef ALLOW_INTERLACE -#define MB_MBAFF(h) h->mb_mbaff -#define MB_FIELD(h) h->mb_field_decoding_flag -#define FRAME_MBAFF(h) h->mb_aff_frame -#define FIELD_PICTURE(h) (h->picture_structure != PICT_FRAME) -#define LEFT_MBS 2 -#define LTOP 0 -#define LBOT 1 -#define LEFT(i) (i) -#else -#define MB_MBAFF(h) 0 -#define MB_FIELD(h) 0 -#define FRAME_MBAFF(h) 0 -#define FIELD_PICTURE(h) 0 -#undef IS_INTERLACED -#define IS_INTERLACED(mb_type) 0 -#define LEFT_MBS 1 -#define LTOP 0 -#define LBOT 0 -#define LEFT(i) 0 -#endif -#define FIELD_OR_MBAFF_PICTURE(h) (FRAME_MBAFF(h) || FIELD_PICTURE(h)) - -#ifndef CABAC -#define CABAC(h) h->pps.cabac -#endif - -#define CHROMA422(h) (h->sps.chroma_format_idc == 2) -#define CHROMA444(h) (h->sps.chroma_format_idc == 3) - -#define EXTENDED_SAR 255 - -#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit -#define MB_TYPE_8x8DCT 0x01000000 -#define IS_REF0(a) ((a) & MB_TYPE_REF0) -#define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT) - #define QP_MAX_NUM (51 + 2 * 6) // The maximum supported qp /* NAL unit types */ enum { - NAL_SLICE = 1, - NAL_DPA = 2, - NAL_DPB = 3, - NAL_DPC = 4, - NAL_IDR_SLICE = 5, - NAL_SEI = 6, - NAL_SPS = 7, - NAL_PPS = 8, - NAL_AUD = 9, - NAL_END_SEQUENCE = 10, - NAL_END_STREAM = 11, - NAL_FILLER_DATA = 12, - NAL_SPS_EXT = 13, - NAL_AUXILIARY_SLICE = 19, - NAL_FF_IGNORE = 0xff0f001, + H264_NAL_SLICE = 1, + H264_NAL_DPA = 2, + H264_NAL_DPB = 3, + H264_NAL_DPC = 4, + H264_NAL_IDR_SLICE = 5, + H264_NAL_SEI = 6, + H264_NAL_SPS = 7, + H264_NAL_PPS = 8, + H264_NAL_AUD = 9, + H264_NAL_END_SEQUENCE = 10, + H264_NAL_END_STREAM = 11, + H264_NAL_FILLER_DATA = 12, + H264_NAL_SPS_EXT = 13, + H264_NAL_AUXILIARY_SLICE = 19, }; -/** - * SEI message types - */ -typedef enum { - SEI_TYPE_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) - SEI_TYPE_PIC_TIMING = 1, ///< picture timing - SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data - SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) - SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement - SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation -} SEI_Type; - -/** - * pic_struct in picture timing SEI message - */ -typedef enum { - SEI_PIC_STRUCT_FRAME = 0, ///< 0: %frame - SEI_PIC_STRUCT_TOP_FIELD = 1, ///< 1: top field - SEI_PIC_STRUCT_BOTTOM_FIELD = 2, ///< 2: bottom field - SEI_PIC_STRUCT_TOP_BOTTOM = 3, ///< 3: top field, bottom field, in that order - SEI_PIC_STRUCT_BOTTOM_TOP = 4, ///< 4: bottom field, top field, in that order - SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, ///< 5: top field, bottom field, top field repeated, in that order - SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///< 6: bottom field, top field, bottom field repeated, in that order - SEI_PIC_STRUCT_FRAME_DOUBLING = 7, ///< 7: %frame doubling - SEI_PIC_STRUCT_FRAME_TRIPLING = 8 ///< 8: %frame tripling -} SEI_PicStructType; - -/** - * Sequence parameter set - */ -typedef struct SPS { - unsigned int sps_id; - int profile_idc; - int level_idc; - int chroma_format_idc; - int transform_bypass; ///< qpprime_y_zero_transform_bypass_flag - int log2_max_frame_num; ///< log2_max_frame_num_minus4 + 4 - int poc_type; ///< pic_order_cnt_type - int log2_max_poc_lsb; ///< log2_max_pic_order_cnt_lsb_minus4 - int delta_pic_order_always_zero_flag; - int offset_for_non_ref_pic; - int offset_for_top_to_bottom_field; - int poc_cycle_length; ///< num_ref_frames_in_pic_order_cnt_cycle - int ref_frame_count; ///< num_ref_frames - int gaps_in_frame_num_allowed_flag; - int mb_width; ///< pic_width_in_mbs_minus1 + 1 - int mb_height; ///< pic_height_in_map_units_minus1 + 1 - int frame_mbs_only_flag; - int mb_aff; ///< mb_adaptive_frame_field_flag - int direct_8x8_inference_flag; - int crop; ///< frame_cropping_flag - - /* those 4 are already in luma samples */ - unsigned int crop_left; ///< frame_cropping_rect_left_offset - unsigned int crop_right; ///< frame_cropping_rect_right_offset - unsigned int crop_top; ///< frame_cropping_rect_top_offset - unsigned int crop_bottom; ///< frame_cropping_rect_bottom_offset - int vui_parameters_present_flag; - AVRational sar; - int video_signal_type_present_flag; - int full_range; - int colour_description_present_flag; - enum AVColorPrimaries color_primaries; - enum AVColorTransferCharacteristic color_trc; - enum AVColorSpace colorspace; - int timing_info_present_flag; - uint32_t num_units_in_tick; - uint32_t time_scale; - int fixed_frame_rate_flag; - short offset_for_ref_frame[256]; // FIXME dyn aloc? - int bitstream_restriction_flag; - int num_reorder_frames; - int scaling_matrix_present; - uint8_t scaling_matrix4[6][16]; - uint8_t scaling_matrix8[6][64]; - int nal_hrd_parameters_present_flag; - int vcl_hrd_parameters_present_flag; - int pic_struct_present_flag; - int time_offset_length; - int cpb_cnt; ///< See H.264 E.1.2 - int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 - int cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 - int dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 - int bit_depth_luma; ///< bit_depth_luma_minus8 + 8 - int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 - int residual_color_transform_flag; ///< residual_colour_transform_flag - int constraint_set_flags; ///< constraint_set[0-3]_flag - int new; ///< flag to keep track if the decoder context needs re-init due to changed SPS -} SPS; - -/** - * Picture parameter set - */ -typedef struct PPS { - unsigned int sps_id; - int cabac; ///< entropy_coding_mode_flag - int pic_order_present; ///< pic_order_present_flag - int slice_group_count; ///< num_slice_groups_minus1 + 1 - int mb_slice_group_map_type; - unsigned int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 - int weighted_pred; ///< weighted_pred_flag - int weighted_bipred_idc; - int init_qp; ///< pic_init_qp_minus26 + 26 - int init_qs; ///< pic_init_qs_minus26 + 26 - int chroma_qp_index_offset[2]; - int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag - int constrained_intra_pred; ///< constrained_intra_pred_flag - int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag - int transform_8x8_mode; ///< transform_8x8_mode_flag - uint8_t scaling_matrix4[6][16]; - uint8_t scaling_matrix8[6][64]; - uint8_t chroma_qp_table[2][64]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table - int chroma_qp_diff; -} PPS; - -/** - * Memory management control operation opcode. - */ -typedef enum MMCOOpcode { - MMCO_END = 0, - MMCO_SHORT2UNUSED, - MMCO_LONG2UNUSED, - MMCO_SHORT2LONG, - MMCO_SET_MAX_LONG, - MMCO_RESET, - MMCO_LONG, -} MMCOOpcode; - -/** - * Memory management control operation. - */ -typedef struct MMCO { - MMCOOpcode opcode; - int short_pic_num; ///< pic_num without wrapping (pic_num & max_pic_num) - int long_arg; ///< index, pic_num, or num long refs depending on opcode -} MMCO; - -typedef struct H264Picture { - struct AVFrame f; - ThreadFrame tf; - - AVBufferRef *qscale_table_buf; - int8_t *qscale_table; - - AVBufferRef *motion_val_buf[2]; - int16_t (*motion_val[2])[2]; - - AVBufferRef *mb_type_buf; - uint32_t *mb_type; - - AVBufferRef *hwaccel_priv_buf; - void *hwaccel_picture_private; ///< hardware accelerator private data - - AVBufferRef *ref_index_buf[2]; - int8_t *ref_index[2]; - - int field_poc[2]; ///< top/bottom POC - int poc; ///< frame POC - int frame_num; ///< frame_num (raw frame_num from slice header) - int mmco_reset; /**< MMCO_RESET set this 1. Reordering code must - not mix pictures before and after MMCO_RESET. */ - int pic_id; /**< pic_num (short -> no wrap version of pic_num, - pic_num & max_pic_num; long -> long_pic_num) */ - int long_ref; ///< 1->long term reference 0->short term reference - int ref_poc[2][2][32]; ///< POCs of the frames used as reference (FIXME need per slice) - int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) - int mbaff; ///< 1 -> MBAFF frame 0-> not MBAFF - int field_picture; ///< whether or not picture was encoded in separate fields - - int needs_realloc; ///< picture needs to be reallocated (eg due to a frame size change) - int reference; - int recovered; ///< picture at IDR or recovery point + recovery count -} H264Picture; - -/** - * H264Context - */ -typedef struct H264Context { - AVCodecContext *avctx; - MECmpContext mecc; - VideoDSPContext vdsp; - H264DSPContext h264dsp; - H264ChromaContext h264chroma; - H264QpelContext h264qpel; - ParseContext parse_context; - GetBitContext gb; - ERContext er; - - H264Picture *DPB; - H264Picture *cur_pic_ptr; - H264Picture cur_pic; - - int pixel_shift; ///< 0 for 8-bit H264, 1 for high-bit-depth H264 - int chroma_qp[2]; // QPc - - int qp_thresh; ///< QP threshold to skip loopfilter - - /* coded dimensions -- 16 * mb w/h */ - int width, height; - ptrdiff_t linesize, uvlinesize; - int chroma_x_shift, chroma_y_shift; - - int qscale; - int droppable; - int data_partitioning; - int coded_picture_number; - int low_delay; - - int context_initialized; - int flags; - int workaround_bugs; - - int prev_mb_skipped; - int next_mb_skipped; - - // prediction stuff - int chroma_pred_mode; - int intra16x16_pred_mode; - - int topleft_mb_xy; - int top_mb_xy; - int topright_mb_xy; - int left_mb_xy[LEFT_MBS]; - - int topleft_type; - int top_type; - int topright_type; - int left_type[LEFT_MBS]; - - const uint8_t *left_block; - int topleft_partition; - - int8_t intra4x4_pred_mode_cache[5 * 8]; - int8_t(*intra4x4_pred_mode); - H264PredContext hpc; - unsigned int topleft_samples_available; - unsigned int top_samples_available; - unsigned int topright_samples_available; - unsigned int left_samples_available; - uint8_t (*top_borders[2])[(16 * 3) * 2]; - - /** - * non zero coeff count cache. - * is 64 if not available. - */ - DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; - - uint8_t (*non_zero_count)[48]; - - /** - * Motion vector cache. - */ - DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2]; - DECLARE_ALIGNED(8, int8_t, ref_cache)[2][5 * 8]; -#define LIST_NOT_USED -1 // FIXME rename? -#define PART_NOT_AVAILABLE -2 - - /** - * number of neighbors (top and/or left) that used 8x8 dct - */ - int neighbor_transform_size; - - /** - * block_offset[ 0..23] for frame macroblocks - * block_offset[24..47] for field macroblocks - */ - int block_offset[2 * (16 * 3)]; - - uint32_t *mb2b_xy; // FIXME are these 4 a good idea? - uint32_t *mb2br_xy; - int b_stride; // FIXME use s->b4_stride - - ptrdiff_t mb_linesize; ///< may be equal to s->linesize or s->linesize * 2, for mbaff - ptrdiff_t mb_uvlinesize; - - SPS sps; ///< current sps - PPS pps; ///< current pps - - uint32_t dequant4_buffer[6][QP_MAX_NUM + 1][16]; // FIXME should these be moved down? - uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64]; - uint32_t(*dequant4_coeff[6])[16]; - uint32_t(*dequant8_coeff[6])[64]; - - int slice_num; - uint16_t *slice_table; ///< slice_table_base + 2*mb_stride + 1 - int slice_type; - int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) - int slice_type_fixed; - - // interlacing specific flags - int mb_aff_frame; - int mb_field_decoding_flag; - int mb_mbaff; ///< mb_aff_frame && mb_field_decoding_flag - int picture_structure; - int first_field; - - DECLARE_ALIGNED(8, uint16_t, sub_mb_type)[4]; - - // Weighted pred stuff - int use_weight; - int use_weight_chroma; - int luma_log2_weight_denom; - int chroma_log2_weight_denom; - // The following 2 can be changed to int8_t but that causes 10cpu cycles speedloss - int luma_weight[48][2][2]; - int chroma_weight[48][2][2][2]; - int implicit_weight[48][48][2]; - - int direct_spatial_mv_pred; - int col_parity; - int col_fieldoff; - int dist_scale_factor[32]; - int dist_scale_factor_field[2][32]; - int map_col_to_list0[2][16 + 32]; - int map_col_to_list0_field[2][2][16 + 32]; - - /** - * num_ref_idx_l0/1_active_minus1 + 1 - */ - unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode - unsigned int list_count; - uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type - H264Picture ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. - * Reordered version of default_ref_list - * according to picture reordering in slice header */ - int ref2frm[MAX_SLICES][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1 - - // data partitioning - GetBitContext intra_gb; - GetBitContext inter_gb; - GetBitContext *intra_gb_ptr; - GetBitContext *inter_gb_ptr; - - const uint8_t *intra_pcm_ptr; - DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2]; ///< as a dct coeffecient is int32_t in high depth, we need to reserve twice the space. - DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2]; - int16_t mb_padding[256 * 2]; ///< as mb is addressed by scantable[i] and scantable is uint8_t we can either check that i is not too large or ensure that there is some unused stuff after mb - - /** - * Cabac - */ - CABACContext cabac; - uint8_t cabac_state[1024]; - - /* 0x100 -> non null luma_dc, 0x80/0x40 -> non null chroma_dc (cb/cr), 0x?0 -> chroma_cbp(0, 1, 2), 0x0? luma_cbp */ - uint16_t *cbp_table; - int cbp; - int top_cbp; - int left_cbp; - /* chroma_pred_mode for i4x4 or i16x16, else 0 */ - uint8_t *chroma_pred_mode_table; - int last_qscale_diff; - uint8_t (*mvd_table[2])[2]; - DECLARE_ALIGNED(16, uint8_t, mvd_cache)[2][5 * 8][2]; - uint8_t *direct_table; - uint8_t direct_cache[5 * 8]; - - uint8_t zigzag_scan[16]; - uint8_t zigzag_scan8x8[64]; - uint8_t zigzag_scan8x8_cavlc[64]; - uint8_t field_scan[16]; - uint8_t field_scan8x8[64]; - uint8_t field_scan8x8_cavlc[64]; - 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; - - int mb_x, mb_y; - int resync_mb_x; - int resync_mb_y; - int mb_skip_run; - int mb_height, mb_width; - int mb_stride; - int mb_num; - int mb_xy; - - int is_complex; - - // deblock - int deblocking_filter; ///< disable_deblocking_filter_idc with 1 <-> 0 - int slice_alpha_c0_offset; - int slice_beta_offset; - - // ============================================================= - // Things below are not used in the MB or more inner code - - int nal_ref_idc; - int nal_unit_type; - uint8_t *rbsp_buffer[2]; - unsigned int rbsp_buffer_size[2]; - - /** - * Used to parse AVC variant of h264 - */ - int is_avc; ///< this flag is != 0 if codec is avc1 - int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) - int got_first; ///< this flag is != 0 if we've parsed a frame - - int bit_depth_luma; ///< luma bit depth from sps to detect changes - int chroma_format_idc; ///< chroma format from sps to detect changes - - SPS *sps_buffers[MAX_SPS_COUNT]; - PPS *pps_buffers[MAX_PPS_COUNT]; - - int dequant_coeff_pps; ///< reinit tables when pps changes - - uint16_t *slice_table_base; - - // POC stuff - int poc_lsb; - int poc_msb; - int delta_poc_bottom; - int delta_poc[2]; - int frame_num; - int prev_poc_msb; ///< poc_msb of the last reference pic for POC type 0 - int prev_poc_lsb; ///< poc_lsb of the last reference pic for POC type 0 - int frame_num_offset; ///< for POC type 2 - int prev_frame_num_offset; ///< for POC type 2 - int prev_frame_num; ///< frame_num of the last pic for POC type 1/2 - - /** - * frame_num for frames or 2 * frame_num + 1 for field pics. - */ - int curr_pic_num; - - /** - * max_frame_num or 2 * max_frame_num for field pics. - */ - int max_pic_num; - - int redundant_pic_count; - - H264Picture default_ref_list[2][32]; ///< base reference list for all slices of a coded picture - H264Picture *short_ref[32]; - H264Picture *long_ref[32]; - H264Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size? - int last_pocs[MAX_DELAYED_PIC_COUNT]; - H264Picture *next_output_pic; - int outputed_poc; - int next_outputed_poc; - - /** - * memory management control operations buffer. - */ - MMCO mmco[MAX_MMCO_COUNT]; - int mmco_index; - int mmco_reset; - - int long_ref_count; ///< number of actual long term references - int short_ref_count; ///< number of actual short term references - - int cabac_init_idc; - - /** - * @name Members for slice based multithreading - * @{ - */ - struct H264Context *thread_context[H264_MAX_THREADS]; - - /** - * current slice number, used to initalize slice_num of each thread/context - */ - int current_slice; - - /** - * Max number of threads / contexts. - * This is equal to AVCodecContext.thread_count unless - * multithreaded decoding is impossible, in which case it is - * reduced to 1. - */ - int max_contexts; - - int slice_context_count; - - /** - * 1 if the single thread fallback warning has already been - * displayed, 0 otherwise. - */ - int single_decode_warning; - - enum AVPictureType pict_type; - - int last_slice_type; - /** @} */ - - /** - * pic_struct in picture timing SEI message - */ - SEI_PicStructType sei_pic_struct; - - /** - * Complement sei_pic_struct - * SEI_PIC_STRUCT_TOP_BOTTOM and SEI_PIC_STRUCT_BOTTOM_TOP indicate interlaced frames. - * However, soft telecined frames may have these values. - * This is used in an attempt to flag soft telecine progressive. - */ - int prev_interlaced_frame; - - /** - * frame_packing_arrangment SEI message - */ - int sei_frame_packing_present; - int frame_packing_arrangement_type; - int content_interpretation_type; - int quincunx_subsampling; - - /** - * display orientation SEI message - */ - int sei_display_orientation_present; - int sei_anticlockwise_rotation; - int sei_hflip, sei_vflip; - - /** - * Bit set of clock types for fields/frames in picture timing SEI message. - * For each found ct_type, appropriate bit is set (e.g., bit 1 for - * interlaced). - */ - int sei_ct_type; - - /** - * dpb_output_delay in picture timing SEI message, see H.264 C.2.2 - */ - int sei_dpb_output_delay; - - /** - * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2 - */ - int sei_cpb_removal_delay; - - /** - * recovery_frame_cnt from SEI message - * - * Set to -1 if no recovery point SEI message found or to number of frames - * before playback synchronizes. Frames having recovery point are key - * frames. - */ - int sei_recovery_frame_cnt; - - /** - * recovery_frame is the frame_num at which the next frame should - * be fully constructed. - * - * Set to -1 when not expecting a recovery point. - */ - int recovery_frame; - -/** - * We have seen an IDR, so all the following frames in coded order are correctly - * decodable. - */ -#define FRAME_RECOVERED_IDR (1 << 0) -/** - * Sufficient number of frames have been decoded since a SEI recovery point, - * so all the following frames in presentation order are correct. - */ -#define FRAME_RECOVERED_SEI (1 << 1) - - int frame_recovered; ///< Initial frame has been completely recovered - - int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag - int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag - - // Timestamp stuff - int sei_buffering_period_present; ///< Buffering period SEI flag - int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs - - int cur_chroma_format_idc; - uint8_t *bipred_scratchpad; - uint8_t *edge_emu_buffer; - int16_t *dc_val_base; - - AVBufferPool *qscale_table_pool; - AVBufferPool *mb_type_pool; - AVBufferPool *motion_val_pool; - AVBufferPool *ref_index_pool; - - /* Motion Estimation */ - qpel_mc_func (*qpel_put)[16]; - qpel_mc_func (*qpel_avg)[16]; -} H264Context; - -extern const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1]; ///< One chroma qp table for each supported bit depth (8, 9, 10). -extern const uint16_t ff_h264_mb_sizes[4]; - -/** - * Decode SEI - */ -int ff_h264_decode_sei(H264Context *h); - -/** - * Decode SPS - */ -int ff_h264_decode_seq_parameter_set(H264Context *h); - -/** - * compute profile from sps - */ -int ff_h264_get_profile(SPS *sps); - -/** - * Decode PPS - */ -int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length); - -/** - * Decode a network abstraction layer unit. - * @param consumed is the number of bytes used as input - * @param length is the length of the array - * @param dst_length is the number of decoded bytes FIXME here - * or a decode rbsp tailing? - * @return decoded bytes, might be src+1 if no escapes - */ -const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, - int *dst_length, int *consumed, int length); - -/** - * Free any data that may have been allocated in the H264 context - * like SPS, PPS etc. - */ -void ff_h264_free_context(H264Context *h); - -/** - * Reconstruct bitstream slice_type. - */ -int ff_h264_get_slice_type(const H264Context *h); - -/** - * Allocate tables. - * needs width/height - */ -int ff_h264_alloc_tables(H264Context *h); - -/** - * Fill the default_ref_list. - */ -int ff_h264_fill_default_ref_list(H264Context *h); - -int ff_h264_decode_ref_pic_list_reordering(H264Context *h); -void ff_h264_fill_mbaff_ref_list(H264Context *h); -void ff_h264_remove_all_refs(H264Context *h); - -/** - * Execute the reference picture marking (memory management control operations). - */ -int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count); - -int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, - int first_slice); - -int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice); - -/** - * Check if the top & left blocks are available if needed & change the - * dc mode so it only uses the available blocks. - */ -int ff_h264_check_intra4x4_pred_mode(H264Context *h); - -/** - * Check if the top & left blocks are available if needed & change the - * dc mode so it only uses the available blocks. - */ -int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma); - -void ff_h264_hl_decode_mb(H264Context *h); -int ff_h264_decode_extradata(H264Context *h); -int ff_h264_decode_init(AVCodecContext *avctx); -void ff_h264_decode_init_vlc(void); - -/** - * Decode a macroblock - * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error - */ -int ff_h264_decode_mb_cavlc(H264Context *h); - -/** - * Decode a CABAC coded macroblock - * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error - */ -int ff_h264_decode_mb_cabac(H264Context *h); - -void ff_h264_init_cabac_states(H264Context *h); - -void h264_init_dequant_tables(H264Context *h); - -void ff_h264_direct_dist_scale_factor(H264Context *const h); -void ff_h264_direct_ref_list_init(H264Context *const h); -void ff_h264_pred_direct_motion(H264Context *const h, int *mb_type); - -void ff_h264_filter_mb_fast(H264Context *h, int mb_x, int mb_y, - uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, - unsigned int linesize, unsigned int uvlinesize); -void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y, - uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, - unsigned int linesize, unsigned int uvlinesize); - -/** - * Reset SEI values at the beginning of the frame. - * - * @param h H.264 context. - */ -void ff_h264_reset_sei(H264Context *h); - -/* - * o-o o-o - * / / / - * o-o o-o - * ,---' - * o-o o-o - * / / / - * o-o o-o - */ - -/* Scan8 organization: - * 0 1 2 3 4 5 6 7 - * 0 DY y y y y y - * 1 y Y Y Y Y - * 2 y Y Y Y Y - * 3 y Y Y Y Y - * 4 y Y Y Y Y - * 5 DU u u u u u - * 6 u U U U U - * 7 u U U U U - * 8 u U U U U - * 9 u U U U U - * 10 DV v v v v v - * 11 v V V V V - * 12 v V V V V - * 13 v V V V V - * 14 v V V V V - * DY/DU/DV are for luma/chroma DC. - */ - -#define LUMA_DC_BLOCK_INDEX 48 -#define CHROMA_DC_BLOCK_INDEX 49 - -// This table must be here because scan8[constant] must be known at compiletime -static const uint8_t scan8[16 * 3 + 3] = { - 4 + 1 * 8, 5 + 1 * 8, 4 + 2 * 8, 5 + 2 * 8, - 6 + 1 * 8, 7 + 1 * 8, 6 + 2 * 8, 7 + 2 * 8, - 4 + 3 * 8, 5 + 3 * 8, 4 + 4 * 8, 5 + 4 * 8, - 6 + 3 * 8, 7 + 3 * 8, 6 + 4 * 8, 7 + 4 * 8, - 4 + 6 * 8, 5 + 6 * 8, 4 + 7 * 8, 5 + 7 * 8, - 6 + 6 * 8, 7 + 6 * 8, 6 + 7 * 8, 7 + 7 * 8, - 4 + 8 * 8, 5 + 8 * 8, 4 + 9 * 8, 5 + 9 * 8, - 6 + 8 * 8, 7 + 8 * 8, 6 + 9 * 8, 7 + 9 * 8, - 4 + 11 * 8, 5 + 11 * 8, 4 + 12 * 8, 5 + 12 * 8, - 6 + 11 * 8, 7 + 11 * 8, 6 + 12 * 8, 7 + 12 * 8, - 4 + 13 * 8, 5 + 13 * 8, 4 + 14 * 8, 5 + 14 * 8, - 6 + 13 * 8, 7 + 13 * 8, 6 + 14 * 8, 7 + 14 * 8, - 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 -}; - -static av_always_inline uint32_t pack16to32(int a, int b) -{ -#if HAVE_BIGENDIAN - return (b & 0xFFFF) + (a << 16); -#else - return (a & 0xFFFF) + (b << 16); -#endif -} - -static av_always_inline uint16_t pack8to16(int a, int b) -{ -#if HAVE_BIGENDIAN - return (b & 0xFF) + (a << 8); -#else - return (a & 0xFF) + (b << 8); -#endif -} - -/** - * Get the chroma qp. - */ -static av_always_inline int get_chroma_qp(H264Context *h, int t, int qscale) -{ - return h->pps.chroma_qp_table[t][qscale]; -} - -/** - * Get the predicted intra4x4 prediction mode. - */ -static av_always_inline int pred_intra_mode(H264Context *h, int n) -{ - const int index8 = scan8[n]; - const int left = h->intra4x4_pred_mode_cache[index8 - 1]; - const int top = h->intra4x4_pred_mode_cache[index8 - 8]; - const int min = FFMIN(left, top); - - tprintf(h->avctx, "mode:%d %d min:%d\n", left, top, min); - - if (min < 0) - return DC_PRED; - else - return min; -} - -static av_always_inline void write_back_intra_pred_mode(H264Context *h) -{ - int8_t *i4x4 = h->intra4x4_pred_mode + h->mb2br_xy[h->mb_xy]; - int8_t *i4x4_cache = h->intra4x4_pred_mode_cache; - - AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4); - i4x4[4] = i4x4_cache[7 + 8 * 3]; - i4x4[5] = i4x4_cache[7 + 8 * 2]; - i4x4[6] = i4x4_cache[7 + 8 * 1]; -} - -static av_always_inline void write_back_non_zero_count(H264Context *h) -{ - const int mb_xy = h->mb_xy; - uint8_t *nnz = h->non_zero_count[mb_xy]; - uint8_t *nnz_cache = h->non_zero_count_cache; - - AV_COPY32(&nnz[ 0], &nnz_cache[4 + 8 * 1]); - AV_COPY32(&nnz[ 4], &nnz_cache[4 + 8 * 2]); - AV_COPY32(&nnz[ 8], &nnz_cache[4 + 8 * 3]); - AV_COPY32(&nnz[12], &nnz_cache[4 + 8 * 4]); - AV_COPY32(&nnz[16], &nnz_cache[4 + 8 * 6]); - AV_COPY32(&nnz[20], &nnz_cache[4 + 8 * 7]); - AV_COPY32(&nnz[32], &nnz_cache[4 + 8 * 11]); - AV_COPY32(&nnz[36], &nnz_cache[4 + 8 * 12]); - - if (!h->chroma_y_shift) { - AV_COPY32(&nnz[24], &nnz_cache[4 + 8 * 8]); - AV_COPY32(&nnz[28], &nnz_cache[4 + 8 * 9]); - AV_COPY32(&nnz[40], &nnz_cache[4 + 8 * 13]); - AV_COPY32(&nnz[44], &nnz_cache[4 + 8 * 14]); - } -} - -static av_always_inline void write_back_motion_list(H264Context *h, - int b_stride, - int b_xy, int b8_xy, - int mb_type, int list) -{ - int16_t(*mv_dst)[2] = &h->cur_pic.motion_val[list][b_xy]; - int16_t(*mv_src)[2] = &h->mv_cache[list][scan8[0]]; - AV_COPY128(mv_dst + 0 * b_stride, mv_src + 8 * 0); - AV_COPY128(mv_dst + 1 * b_stride, mv_src + 8 * 1); - AV_COPY128(mv_dst + 2 * b_stride, mv_src + 8 * 2); - AV_COPY128(mv_dst + 3 * b_stride, mv_src + 8 * 3); - if (CABAC(h)) { - uint8_t (*mvd_dst)[2] = &h->mvd_table[list][FMO ? 8 * h->mb_xy - : h->mb2br_xy[h->mb_xy]]; - uint8_t(*mvd_src)[2] = &h->mvd_cache[list][scan8[0]]; - if (IS_SKIP(mb_type)) { - AV_ZERO128(mvd_dst); - } else { - AV_COPY64(mvd_dst, mvd_src + 8 * 3); - AV_COPY16(mvd_dst + 3 + 3, mvd_src + 3 + 8 * 0); - AV_COPY16(mvd_dst + 3 + 2, mvd_src + 3 + 8 * 1); - AV_COPY16(mvd_dst + 3 + 1, mvd_src + 3 + 8 * 2); - } - } - - { - int8_t *ref_index = &h->cur_pic.ref_index[list][b8_xy]; - int8_t *ref_cache = h->ref_cache[list]; - ref_index[0 + 0 * 2] = ref_cache[scan8[0]]; - ref_index[1 + 0 * 2] = ref_cache[scan8[4]]; - ref_index[0 + 1 * 2] = ref_cache[scan8[8]]; - ref_index[1 + 1 * 2] = ref_cache[scan8[12]]; - } -} - -static av_always_inline void write_back_motion(H264Context *h, int mb_type) -{ - const int b_stride = h->b_stride; - const int b_xy = 4 * h->mb_x + 4 * h->mb_y * h->b_stride; // try mb2b(8)_xy - const int b8_xy = 4 * h->mb_xy; - - if (USES_LIST(mb_type, 0)) { - write_back_motion_list(h, b_stride, b_xy, b8_xy, mb_type, 0); - } else { - fill_rectangle(&h->cur_pic.ref_index[0][b8_xy], - 2, 2, 2, (uint8_t)LIST_NOT_USED, 1); - } - if (USES_LIST(mb_type, 1)) - write_back_motion_list(h, b_stride, b_xy, b8_xy, mb_type, 1); - - if (h->slice_type_nos == AV_PICTURE_TYPE_B && CABAC(h)) { - if (IS_8X8(mb_type)) { - uint8_t *direct_table = &h->direct_table[4 * h->mb_xy]; - direct_table[1] = h->sub_mb_type[1] >> 1; - direct_table[2] = h->sub_mb_type[2] >> 1; - direct_table[3] = h->sub_mb_type[3] >> 1; - } - } -} - -static av_always_inline int get_dct8x8_allowed(H264Context *h) -{ - if (h->sps.direct_8x8_inference_flag) - return !(AV_RN64A(h->sub_mb_type) & - ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8) * - 0x0001000100010001ULL)); - else - return !(AV_RN64A(h->sub_mb_type) & - ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8 | MB_TYPE_DIRECT2) * - 0x0001000100010001ULL)); -} - -int ff_h264_field_end(H264Context *h, int in_setup); - -int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src); -void ff_h264_unref_picture(H264Context *h, H264Picture *pic); - -int ff_h264_context_init(H264Context *h); -int ff_h264_set_parameter_from_sps(H264Context *h); - -void ff_h264_draw_horiz_band(H264Context *h, int y, int height); -int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc); -int ff_pred_weight_table(H264Context *h); -int ff_set_ref_count(H264Context *h); - -int ff_h264_decode_slice_header(H264Context *h, H264Context *h0); -int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count); -int ff_h264_update_thread_context(AVCodecContext *dst, - const AVCodecContext *src); - -void ff_h264_flush_change(H264Context *h); - -void ff_h264_free_tables(H264Context *h, int free_rbsp); - #endif /* AVCODEC_H264_H */ diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c new file mode 100644 index 0000000..b507b19 --- /dev/null +++ b/libavcodec/h2645_parse.c @@ -0,0 +1,330 @@ +/* + * H.264/HEVC common parsing code + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#include "libavutil/intmath.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "bytestream.h" +#include "h2645_parse.h" + +int ff_h2645_extract_rbsp(const uint8_t *src, int length, + H2645NAL *nal) +{ + int i, si, di; + uint8_t *dst; + +#define STARTCODE_TEST \ + if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ + if (src[i + 2] != 3) { \ + /* startcode, so we must be past the end */ \ + length = i; \ + } \ + break; \ + } +#if HAVE_FAST_UNALIGNED +#define FIND_FIRST_ZERO \ + if (i > 0 && !src[i]) \ + i--; \ + while (src[i]) \ + i++ +#if HAVE_FAST_64BIT + for (i = 0; i + 1 < length; i += 9) { + if (!((~AV_RN64A(src + i) & + (AV_RN64A(src + i) - 0x0100010001000101ULL)) & + 0x8000800080008080ULL)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 7; + } +#else + for (i = 0; i + 1 < length; i += 5) { + if (!((~AV_RN32A(src + i) & + (AV_RN32A(src + i) - 0x01000101U)) & + 0x80008080U)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 3; + } +#endif /* HAVE_FAST_64BIT */ +#else + for (i = 0; i + 1 < length; i += 2) { + if (src[i]) + continue; + if (i > 0 && src[i - 1] == 0) + i--; + STARTCODE_TEST; + } +#endif /* HAVE_FAST_UNALIGNED */ + + if (i >= length - 1) { // no escaped 0 + nal->data = + nal->raw_data = src; + nal->size = + nal->raw_size = length; + return length; + } + + av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size, + length + AV_INPUT_BUFFER_PADDING_SIZE); + if (!nal->rbsp_buffer) + return AVERROR(ENOMEM); + + dst = nal->rbsp_buffer; + + memcpy(dst, src, i); + si = di = i; + while (si + 2 < length) { + // remove escapes (very rare 1:2^22) + if (src[si + 2] > 3) { + dst[di++] = src[si++]; + dst[di++] = src[si++]; + } else if (src[si] == 0 && src[si + 1] == 0) { + if (src[si + 2] == 3) { // escape + dst[di++] = 0; + dst[di++] = 0; + si += 3; + + continue; + } else // next start code + goto nsc; + } + + dst[di++] = src[si++]; + } + while (si < length) + dst[di++] = src[si++]; + +nsc: + memset(dst + di, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + nal->data = dst; + nal->size = di; + nal->raw_data = src; + nal->raw_size = si; + return si; +} + +static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) +{ + int size = nal->size; + int v; + + while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0) + size--; + + if (!size) + return 0; + + v = nal->data[size - 1]; + + if (size > INT_MAX / 8) + return AVERROR(ERANGE); + size *= 8; + + /* remove the stop bit and following trailing zeros, + * or nothing for damaged bitstreams */ + if (v) + size -= av_ctz(v) + 1; + + return size; +} + +/** + * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, + * 0 if the unit should be skipped, 1 otherwise + */ +static int hevc_parse_nal_header(H2645NAL *nal, void *logctx) +{ + GetBitContext *gb = &nal->gb; + int nuh_layer_id; + + if (get_bits1(gb) != 0) + return AVERROR_INVALIDDATA; + + nal->type = get_bits(gb, 6); + + nuh_layer_id = get_bits(gb, 6); + nal->temporal_id = get_bits(gb, 3) - 1; + if (nal->temporal_id < 0) + return AVERROR_INVALIDDATA; + + av_log(logctx, AV_LOG_DEBUG, + "nal_unit_type: %d, nuh_layer_id: %dtemporal_id: %d\n", + nal->type, nuh_layer_id, nal->temporal_id); + + return nuh_layer_id == 0; +} + +static int h264_parse_nal_header(H2645NAL *nal, void *logctx) +{ + GetBitContext *gb = &nal->gb; + + if (get_bits1(gb) != 0) + return AVERROR_INVALIDDATA; + + nal->ref_idc = get_bits(gb, 2); + nal->type = get_bits(gb, 5); + + av_log(logctx, AV_LOG_DEBUG, + "nal_unit_type: %d, nal_ref_idc: %d\n", + nal->type, nal->ref_idc); + + return 1; +} + +static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc) +{ + int i = 0; + + if (buf + 3 >= next_avc) + return next_avc - buf; + + while (buf + i + 3 < next_avc) { + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) + break; + i++; + } + return i + 3; +} + +int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, + void *logctx, int is_nalff, int nal_length_size, + enum AVCodecID codec_id) +{ + GetByteContext bc; + int consumed, ret = 0; + size_t next_avc = is_nalff ? 0 : length; + + bytestream2_init(&bc, buf, length); + + pkt->nb_nals = 0; + while (bytestream2_get_bytes_left(&bc) >= 4) { + H2645NAL *nal; + int extract_length = 0; + int skip_trailing_zeros = 1; + + /* + * Only parse an AVC1 length field if one is expected at the current + * buffer position. There are unfortunately streams with multiple + * NAL units covered by the length field. Those NAL units are delimited + * by Annex B start code prefixes. ff_h2645_extract_rbsp() detects it + * correctly and consumes only the first NAL unit. The additional NAL + * units are handled here in the Annex B parsing code. + */ + if (bytestream2_tell(&bc) == next_avc) { + int i; + for (i = 0; i < nal_length_size; i++) + extract_length = (extract_length << 8) | bytestream2_get_byte(&bc); + + if (extract_length > bytestream2_get_bytes_left(&bc)) { + av_log(logctx, AV_LOG_ERROR, + "Invalid NAL unit size (%d > %d).\n", + extract_length, bytestream2_get_bytes_left(&bc)); + return AVERROR_INVALIDDATA; + } + // keep track of the next AVC1 length field + next_avc = bytestream2_tell(&bc) + extract_length; + } else { + /* + * expected to return immediately except for streams with mixed + * NAL unit coding + */ + int buf_index = find_next_start_code(bc.buffer, buf + next_avc); + + bytestream2_skip(&bc, buf_index); + + /* + * break if an AVC1 length field is expected at the current buffer + * position + */ + if (bytestream2_tell(&bc) == next_avc) + continue; + + if (bytestream2_get_bytes_left(&bc) > 0) { + extract_length = bytestream2_get_bytes_left(&bc); + } else if (pkt->nb_nals == 0) { + av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n"); + return AVERROR_INVALIDDATA; + } else { + break; + } + } + + if (pkt->nals_allocated < pkt->nb_nals + 1) { + int new_size = pkt->nals_allocated + 1; + H2645NAL *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*tmp)); + if (!tmp) + return AVERROR(ENOMEM); + + pkt->nals = tmp; + memset(pkt->nals + pkt->nals_allocated, 0, + (new_size - pkt->nals_allocated) * sizeof(*tmp)); + pkt->nals_allocated = new_size; + } + nal = &pkt->nals[pkt->nb_nals++]; + + consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal); + if (consumed < 0) + return consumed; + + bytestream2_skip(&bc, consumed); + + /* see commit 3566042a0 */ + if (bytestream2_get_bytes_left(&bc) >= 4 && + bytestream2_peek_be32(&bc) == 0x000001E0) + skip_trailing_zeros = 0; + + nal->size_bits = get_bit_length(nal, skip_trailing_zeros); + + ret = init_get_bits(&nal->gb, nal->data, nal->size_bits); + if (ret < 0) + return ret; + + if (codec_id == AV_CODEC_ID_HEVC) + ret = hevc_parse_nal_header(nal, logctx); + else + ret = h264_parse_nal_header(nal, logctx); + if (ret <= 0) { + if (ret < 0) { + av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", + nal->type); + } + pkt->nb_nals--; + } + } + + return 0; +} + +void ff_h2645_packet_uninit(H2645Packet *pkt) +{ + int i; + for (i = 0; i < pkt->nals_allocated; i++) + av_freep(&pkt->nals[i].rbsp_buffer); + av_freep(&pkt->nals); + pkt->nals_allocated = 0; +} diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h new file mode 100644 index 0000000..9cc4441 --- /dev/null +++ b/libavcodec/h2645_parse.h @@ -0,0 +1,88 @@ +/* + * H.264/HEVC common parsing code + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_H2645_PARSE_H +#define AVCODEC_H2645_PARSE_H + +#include + +#include "avcodec.h" +#include "get_bits.h" + +typedef struct H2645NAL { + uint8_t *rbsp_buffer; + int rbsp_buffer_size; + + int size; + const uint8_t *data; + + /** + * Size, in bits, of just the data, excluding the stop bit and any trailing + * padding. I.e. what HEVC calls SODB. + */ + int size_bits; + + int raw_size; + const uint8_t *raw_data; + + GetBitContext gb; + + /** + * NAL unit type + */ + int type; + + /** + * HEVC only, nuh_temporal_id_plus_1 - 1 + */ + int temporal_id; + + /** + * H.264 only, nal_ref_idc + */ + int ref_idc; +} H2645NAL; + +/* an input packet split into unescaped NAL units */ +typedef struct H2645Packet { + H2645NAL *nals; + int nb_nals; + int nals_allocated; +} H2645Packet; + +/** + * Extract the raw (unescaped) bitstream. + */ +int ff_h2645_extract_rbsp(const uint8_t *src, int length, + H2645NAL *nal); + +/** + * Split an input packet into NAL units. + */ +int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, + void *logctx, int is_nalff, int nal_length_size, + enum AVCodecID codec_id); + +/** + * Free all the allocated memory in the packet. + */ +void ff_h2645_packet_uninit(H2645Packet *pkt); + +#endif /* AVCODEC_H2645_PARSE_H */ diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index cce6450..ae1ef6b 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -21,11 +21,12 @@ /** * @file - * H.264 / AVC / MPEG4 part10 cabac decoding. + * H.264 / AVC / MPEG-4 part10 cabac decoding. * @author Michael Niedermayer */ #define CABAC(h) 1 +#define INT_BIT (CHAR_BIT * sizeof(int)) #include "libavutil/attributes.h" #include "libavutil/timer.h" @@ -34,10 +35,9 @@ #include "cabac_functions.h" #include "internal.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" #include "h264data.h" #include "h264_mvpred.h" -#include "golomb.h" #include "mpegutils.h" #if ARCH_X86 @@ -55,7 +55,7 @@ static const int8_t cabac_context_init_I[1024][2] = { 2, 54 }, { 3, 74 }, { -28,127 }, { -23, 104 }, { -6, 53 }, { -1, 54 }, { 7, 51 }, - /* 11 - 23 unsused for I */ + /* 11 - 23 unused 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 }, @@ -1260,13 +1260,14 @@ static const int8_t cabac_context_init_PB[3][1024][2] = } }; -void ff_h264_init_cabac_states(H264Context *h) { +void ff_h264_init_cabac_states(const H264Context *h, H264SliceContext *sl) +{ int i; const int8_t (*tab)[2]; - const int slice_qp = av_clip(h->qscale - 6*(h->sps.bit_depth_luma-8), 0, 51); + const int slice_qp = av_clip(sl->qscale - 6*(h->ps.sps->bit_depth_luma-8), 0, 51); - if( h->slice_type_nos == AV_PICTURE_TYPE_I ) tab = cabac_context_init_I; - else tab = cabac_context_init_PB[h->cabac_init_idc]; + if (sl->slice_type_nos == AV_PICTURE_TYPE_I) tab = cabac_context_init_I; + else tab = cabac_context_init_PB[sl->cabac_init_idc]; /* calculate pre-state */ for( i= 0; i < 1024; i++ ) { @@ -1276,52 +1277,57 @@ void ff_h264_init_cabac_states(H264Context *h) { if(pre > 124) pre= 124 + (pre&1); - h->cabac_state[i] = pre; + sl->cabac_state[i] = pre; } } -static int decode_cabac_field_decoding_flag(H264Context *h) { - const long mbb_xy = h->mb_xy - 2L*h->mb_stride; +static int decode_cabac_field_decoding_flag(const H264Context *h, H264SliceContext *sl) +{ + const long mbb_xy = sl->mb_xy - 2L*h->mb_stride; unsigned long ctx = 0; - ctx += h->mb_field_decoding_flag & !!h->mb_x; //for FMO:(s->current_picture.mb_type[mba_xy] >> 7) & (h->slice_table[mba_xy] == h->slice_num); - ctx += (h->cur_pic.mb_type[mbb_xy] >> 7) & (h->slice_table[mbb_xy] == h->slice_num); + ctx += sl->mb_field_decoding_flag & !!sl->mb_x; //for FMO:(s->current_picture.mb_type[mba_xy] >> 7) & (h->slice_table[mba_xy] == h->slice_num); + ctx += (h->cur_pic.mb_type[mbb_xy] >> 7) & (h->slice_table[mbb_xy] == sl->slice_num); - return get_cabac_noinline( &h->cabac, &(h->cabac_state+70)[ctx] ); + return get_cabac_noinline( &sl->cabac, &(sl->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]; +static int decode_cabac_intra_mb_type(H264SliceContext *sl, + int ctx_base, int intra_slice) +{ + uint8_t *state= &sl->cabac_state[ctx_base]; int mb_type; if(intra_slice){ int ctx=0; - if( h->left_type[LTOP] & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) + if (sl->left_type[LTOP] & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) ctx++; - if( h->top_type & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) + if (sl->top_type & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) ctx++; - if( get_cabac_noinline( &h->cabac, &state[ctx] ) == 0 ) + if( get_cabac_noinline( &sl->cabac, &state[ctx] ) == 0 ) return 0; /* I4x4 */ state += 2; }else{ - if( get_cabac_noinline( &h->cabac, state ) == 0 ) + if( get_cabac_noinline( &sl->cabac, state ) == 0 ) return 0; /* I4x4 */ } - if( get_cabac_terminate( &h->cabac ) ) + if( get_cabac_terminate( &sl->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] ); + mb_type += 12 * get_cabac_noinline( &sl->cabac, &state[1] ); /* cbp_luma != 0 */ + if( get_cabac_noinline( &sl->cabac, &state[2] ) ) /* cbp_chroma */ + mb_type += 4 + 4 * get_cabac_noinline( &sl->cabac, &state[2+intra_slice] ); + mb_type += 2 * get_cabac_noinline( &sl->cabac, &state[3+intra_slice] ); + mb_type += 1 * get_cabac_noinline( &sl->cabac, &state[3+2*intra_slice] ); return mb_type; } -static int decode_cabac_mb_skip( H264Context *h, int mb_x, int mb_y ) { +static int decode_cabac_mb_skip(const H264Context *h, H264SliceContext *sl, + int mb_x, int mb_y) +{ int mba_xy, mbb_xy; int ctx = 0; @@ -1329,141 +1335,148 @@ static int decode_cabac_mb_skip( H264Context *h, int mb_x, int mb_y ) { int mb_xy = mb_x + (mb_y&~1)*h->mb_stride; mba_xy = mb_xy - 1; if( (mb_y&1) - && h->slice_table[mba_xy] == h->slice_num - && MB_FIELD(h) == !!IS_INTERLACED( h->cur_pic.mb_type[mba_xy] ) ) + && h->slice_table[mba_xy] == sl->slice_num + && MB_FIELD(sl) == !!IS_INTERLACED( h->cur_pic.mb_type[mba_xy] ) ) mba_xy += h->mb_stride; - if (MB_FIELD(h)) { + if (MB_FIELD(sl)) { mbb_xy = mb_xy - h->mb_stride; if( !(mb_y&1) - && h->slice_table[mbb_xy] == h->slice_num + && h->slice_table[mbb_xy] == sl->slice_num && IS_INTERLACED( h->cur_pic.mb_type[mbb_xy] ) ) mbb_xy -= h->mb_stride; }else mbb_xy = mb_x + (mb_y-1)*h->mb_stride; }else{ - int mb_xy = h->mb_xy; + int mb_xy = sl->mb_xy; mba_xy = mb_xy - 1; mbb_xy = mb_xy - (h->mb_stride << FIELD_PICTURE(h)); } - if( h->slice_table[mba_xy] == h->slice_num && !IS_SKIP(h->cur_pic.mb_type[mba_xy] )) + if( h->slice_table[mba_xy] == sl->slice_num && !IS_SKIP(h->cur_pic.mb_type[mba_xy] )) ctx++; - if( h->slice_table[mbb_xy] == h->slice_num && !IS_SKIP(h->cur_pic.mb_type[mbb_xy] )) + if( h->slice_table[mbb_xy] == sl->slice_num && !IS_SKIP(h->cur_pic.mb_type[mbb_xy] )) ctx++; - if( h->slice_type_nos == AV_PICTURE_TYPE_B ) + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) ctx += 13; - return get_cabac_noinline( &h->cabac, &h->cabac_state[11+ctx] ); + return get_cabac_noinline( &sl->cabac, &sl->cabac_state[11+ctx] ); } -static int decode_cabac_mb_intra4x4_pred_mode( H264Context *h, int pred_mode ) { +static int decode_cabac_mb_intra4x4_pred_mode(H264SliceContext *sl, int pred_mode) +{ int mode = 0; - if( get_cabac( &h->cabac, &h->cabac_state[68] ) ) + if( get_cabac( &sl->cabac, &sl->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] ); + mode += 1 * get_cabac( &sl->cabac, &sl->cabac_state[69] ); + mode += 2 * get_cabac( &sl->cabac, &sl->cabac_state[69] ); + mode += 4 * get_cabac( &sl->cabac, &sl->cabac_state[69] ); return mode + ( mode >= pred_mode ); } -static int decode_cabac_mb_chroma_pre_mode( H264Context *h) { - const int mba_xy = h->left_mb_xy[0]; - const int mbb_xy = h->top_mb_xy; +static int decode_cabac_mb_chroma_pre_mode(const H264Context *h, H264SliceContext *sl) +{ + const int mba_xy = sl->left_mb_xy[0]; + const int mbb_xy = sl->top_mb_xy; int ctx = 0; /* No need to test for IS_INTRA4x4 and IS_INTRA16x16, as we set chroma_pred_mode_table to 0 */ - if( h->left_type[LTOP] && h->chroma_pred_mode_table[mba_xy] != 0 ) + if (sl->left_type[LTOP] && h->chroma_pred_mode_table[mba_xy] != 0) ctx++; - if( h->top_type && h->chroma_pred_mode_table[mbb_xy] != 0 ) + if (sl->top_type && h->chroma_pred_mode_table[mbb_xy] != 0) ctx++; - if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+ctx] ) == 0 ) + if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[64+ctx] ) == 0 ) return 0; - if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+3] ) == 0 ) + if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[64+3] ) == 0 ) return 1; - if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+3] ) == 0 ) + if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[64+3] ) == 0 ) return 2; else return 3; } -static int decode_cabac_mb_cbp_luma( H264Context *h) { +static int decode_cabac_mb_cbp_luma(H264SliceContext *sl) +{ int cbp_b, cbp_a, ctx, cbp = 0; - cbp_a = h->left_cbp; - cbp_b = h->top_cbp; + cbp_a = sl->left_cbp; + cbp_b = sl->top_cbp; ctx = !(cbp_a & 0x02) + 2 * !(cbp_b & 0x04); - cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]); + cbp += get_cabac_noinline(&sl->cabac, &sl->cabac_state[73 + ctx]); ctx = !(cbp & 0x01) + 2 * !(cbp_b & 0x08); - cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 1; + cbp += get_cabac_noinline(&sl->cabac, &sl->cabac_state[73 + ctx]) << 1; ctx = !(cbp_a & 0x08) + 2 * !(cbp & 0x01); - cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 2; + cbp += get_cabac_noinline(&sl->cabac, &sl->cabac_state[73 + ctx]) << 2; ctx = !(cbp & 0x04) + 2 * !(cbp & 0x02); - cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 3; + cbp += get_cabac_noinline(&sl->cabac, &sl->cabac_state[73 + ctx]) << 3; return cbp; } -static int decode_cabac_mb_cbp_chroma( H264Context *h) { +static int decode_cabac_mb_cbp_chroma(H264SliceContext *sl) +{ int ctx; int cbp_a, cbp_b; - cbp_a = (h->left_cbp>>4)&0x03; - cbp_b = (h-> top_cbp>>4)&0x03; + cbp_a = (sl->left_cbp>>4)&0x03; + cbp_b = (sl-> 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 ) + if( get_cabac_noinline( &sl->cabac, &sl->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] ); + return 1 + get_cabac_noinline( &sl->cabac, &sl->cabac_state[77 + ctx] ); } -static int decode_cabac_p_mb_sub_type( H264Context *h ) { - if( get_cabac( &h->cabac, &h->cabac_state[21] ) ) +static int decode_cabac_p_mb_sub_type(H264SliceContext *sl) +{ + if( get_cabac( &sl->cabac, &sl->cabac_state[21] ) ) return 0; /* 8x8 */ - if( !get_cabac( &h->cabac, &h->cabac_state[22] ) ) + if( !get_cabac( &sl->cabac, &sl->cabac_state[22] ) ) return 1; /* 8x4 */ - if( get_cabac( &h->cabac, &h->cabac_state[23] ) ) + if( get_cabac( &sl->cabac, &sl->cabac_state[23] ) ) return 2; /* 4x8 */ return 3; /* 4x4 */ } -static int decode_cabac_b_mb_sub_type( H264Context *h ) { +static int decode_cabac_b_mb_sub_type(H264SliceContext *sl) +{ int type; - if( !get_cabac( &h->cabac, &h->cabac_state[36] ) ) + if( !get_cabac( &sl->cabac, &sl->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 */ + if( !get_cabac( &sl->cabac, &sl->cabac_state[37] ) ) + return 1 + get_cabac( &sl->cabac, &sl->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 */ + if( get_cabac( &sl->cabac, &sl->cabac_state[38] ) ) { + if( get_cabac( &sl->cabac, &sl->cabac_state[39] ) ) + return 11 + get_cabac( &sl->cabac, &sl->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] ); + type += 2*get_cabac( &sl->cabac, &sl->cabac_state[39] ); + type += get_cabac( &sl->cabac, &sl->cabac_state[39] ); return type; } -static int decode_cabac_mb_ref( H264Context *h, int list, int n ) { - int refa = h->ref_cache[list][scan8[n] - 1]; - int refb = h->ref_cache[list][scan8[n] - 8]; +static int decode_cabac_mb_ref(H264SliceContext *sl, int list, int n) +{ + int refa = sl->ref_cache[list][scan8[n] - 1]; + int refb = sl->ref_cache[list][scan8[n] - 8]; int ref = 0; int ctx = 0; - if( h->slice_type_nos == AV_PICTURE_TYPE_B) { - if( refa > 0 && !(h->direct_cache[scan8[n] - 1]&(MB_TYPE_DIRECT2>>1)) ) + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { + if( refa > 0 && !(sl->direct_cache[scan8[n] - 1]&(MB_TYPE_DIRECT2>>1)) ) ctx++; - if( refb > 0 && !(h->direct_cache[scan8[n] - 8]&(MB_TYPE_DIRECT2>>1)) ) + if( refb > 0 && !(sl->direct_cache[scan8[n] - 8]&(MB_TYPE_DIRECT2>>1)) ) ctx += 2; } else { if( refa > 0 ) @@ -1472,7 +1485,7 @@ static int decode_cabac_mb_ref( H264Context *h, int list, int n ) { ctx += 2; } - while( get_cabac( &h->cabac, &h->cabac_state[54+ctx] ) ) { + while( get_cabac( &sl->cabac, &sl->cabac_state[54+ctx] ) ) { ref++; ctx = (ctx>>2)+4; if(ref >= 32 /*h->ref_list[list]*/){ @@ -1482,10 +1495,11 @@ static int decode_cabac_mb_ref( H264Context *h, int list, int n ) { return ref; } -static int decode_cabac_mb_mvd( H264Context *h, int ctxbase, int amvd, int *mvda) { +static int decode_cabac_mb_mvd(H264SliceContext *sl, int ctxbase, int amvd, int *mvda) +{ int mvd; - if(!get_cabac(&h->cabac, &h->cabac_state[ctxbase+((amvd-3)>>(INT_BIT-1))+((amvd-33)>>(INT_BIT-1))+2])){ + if(!get_cabac(&sl->cabac, &sl->cabac_state[ctxbase+((amvd-3)>>(INT_BIT-1))+((amvd-33)>>(INT_BIT-1))+2])){ // if(!get_cabac(&h->cabac, &h->cabac_state[ctxbase+(amvd>2)+(amvd>32)])){ *mvda= 0; return 0; @@ -1493,7 +1507,7 @@ static int decode_cabac_mb_mvd( H264Context *h, int ctxbase, int amvd, int *mvda mvd= 1; ctxbase+= 3; - while( mvd < 9 && get_cabac( &h->cabac, &h->cabac_state[ctxbase] ) ) { + while( mvd < 9 && get_cabac( &sl->cabac, &sl->cabac_state[ctxbase] ) ) { if( mvd < 4 ) ctxbase++; mvd++; @@ -1501,35 +1515,38 @@ static int decode_cabac_mb_mvd( H264Context *h, int ctxbase, int amvd, int *mvda if( mvd >= 9 ) { int k = 3; - while( get_cabac_bypass( &h->cabac ) ) { + while( get_cabac_bypass( &sl->cabac ) ) { mvd += 1 << k; k++; if(k>24){ - av_log(h->avctx, AV_LOG_ERROR, "overflow in decode_cabac_mb_mvd\n"); + av_log(sl->h264->avctx, AV_LOG_ERROR, "overflow in decode_cabac_mb_mvd\n"); return INT_MIN; } } while( k-- ) { - mvd += get_cabac_bypass( &h->cabac )<cabac )<cabac, -mvd ); + return get_cabac_bypass_sign( &sl->cabac, -mvd ); } -#define DECODE_CABAC_MB_MVD( h, list, n )\ +#define DECODE_CABAC_MB_MVD(sl, list, n )\ {\ - int amvd0 = h->mvd_cache[list][scan8[n] - 1][0] +\ - h->mvd_cache[list][scan8[n] - 8][0];\ - int amvd1 = h->mvd_cache[list][scan8[n] - 1][1] +\ - h->mvd_cache[list][scan8[n] - 8][1];\ + int amvd0 = sl->mvd_cache[list][scan8[n] - 1][0] +\ + sl->mvd_cache[list][scan8[n] - 8][0];\ + int amvd1 = sl->mvd_cache[list][scan8[n] - 1][1] +\ + sl->mvd_cache[list][scan8[n] - 8][1];\ \ - mx += decode_cabac_mb_mvd( h, 40, amvd0, &mpx );\ - my += decode_cabac_mb_mvd( h, 47, amvd1, &mpy );\ + mx += decode_cabac_mb_mvd(sl, 40, amvd0, &mpx);\ + my += decode_cabac_mb_mvd(sl, 47, amvd1, &mpy);\ } -static av_always_inline int get_cabac_cbf_ctx( H264Context *h, int cat, int idx, int max_coeff, int is_dc ) { +static av_always_inline int get_cabac_cbf_ctx(H264SliceContext *sl, + int cat, int idx, int max_coeff, + int is_dc) +{ int nza, nzb; int ctx = 0; static const uint16_t base_ctx[14] = {85,89,93,97,101,1012,460,464,468,1016,472,476,480,1020}; @@ -1537,16 +1554,16 @@ static av_always_inline int get_cabac_cbf_ctx( H264Context *h, int cat, int idx, if( is_dc ) { if( cat == 3 ) { idx -= CHROMA_DC_BLOCK_INDEX; - nza = (h->left_cbp>>(6+idx))&0x01; - nzb = (h-> top_cbp>>(6+idx))&0x01; + nza = (sl->left_cbp>>(6+idx))&0x01; + nzb = (sl-> top_cbp>>(6+idx))&0x01; } else { idx -= LUMA_DC_BLOCK_INDEX; - nza = h->left_cbp&(0x100< top_cbp&(0x100<left_cbp&(0x100< top_cbp&(0x100<non_zero_count_cache[scan8[idx] - 1]; - nzb = h->non_zero_count_cache[scan8[idx] - 8]; + nza = sl->non_zero_count_cache[scan8[idx] - 1]; + nzb = sl->non_zero_count_cache[scan8[idx] - 8]; } if( nza > 0 ) @@ -1559,7 +1576,8 @@ static av_always_inline int get_cabac_cbf_ctx( H264Context *h, int cat, int idx, } static av_always_inline void -decode_cabac_residual_internal(H264Context *h, int16_t *block, +decode_cabac_residual_internal(const H264Context *h, H264SliceContext *sl, + int16_t *block, int cat, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff, int is_dc, int chroma422) @@ -1604,7 +1622,7 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, int index[64]; - int av_unused last; + int last; int coeff_count = 0; int node_ctx = 0; @@ -1618,19 +1636,19 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, #ifdef CABAC_ON_STACK #define CC &cc CABACContext cc; - cc.range = h->cabac.range; - cc.low = h->cabac.low; - cc.bytestream= h->cabac.bytestream; - cc.bytestream_end = h->cabac.bytestream_end; + cc.range = sl->cabac.range; + cc.low = sl->cabac.low; + cc.bytestream= sl->cabac.bytestream; + cc.bytestream_end = sl->cabac.bytestream_end; #else -#define CC &h->cabac +#define CC &sl->cabac #endif - significant_coeff_ctx_base = h->cabac_state - + significant_coeff_flag_offset[MB_FIELD(h)][cat]; - last_coeff_ctx_base = h->cabac_state - + last_coeff_flag_offset[MB_FIELD(h)][cat]; - abs_level_m1_ctx_base = h->cabac_state + significant_coeff_ctx_base = sl->cabac_state + + significant_coeff_flag_offset[MB_FIELD(sl)][cat]; + last_coeff_ctx_base = sl->cabac_state + + last_coeff_flag_offset[MB_FIELD(sl)][cat]; + abs_level_m1_ctx_base = sl->cabac_state + coeff_abs_level_m1_offset[cat]; if( !is_dc && max_coeff == 64 ) { @@ -1649,7 +1667,7 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, if( last == max_coeff -1 ) {\ index[coeff_count++] = last;\ } - const uint8_t *sig_off = significant_coeff_flag_offset_8x8[MB_FIELD(h)]; + const uint8_t *sig_off = significant_coeff_flag_offset_8x8[MB_FIELD(sl)]; #ifdef decode_significance coeff_count = decode_significance_8x8(CC, significant_coeff_ctx_base, index, last_coeff_ctx_base, sig_off); @@ -1674,16 +1692,16 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, if( is_dc ) { if( cat == 3 ) - h->cbp_table[h->mb_xy] |= 0x40 << (n - CHROMA_DC_BLOCK_INDEX); + h->cbp_table[sl->mb_xy] |= 0x40 << (n - CHROMA_DC_BLOCK_INDEX); else - h->cbp_table[h->mb_xy] |= 0x100 << (n - LUMA_DC_BLOCK_INDEX); - h->non_zero_count_cache[scan8[n]] = coeff_count; + h->cbp_table[sl->mb_xy] |= 0x100 << (n - LUMA_DC_BLOCK_INDEX); + sl->non_zero_count_cache[scan8[n]] = coeff_count; } else { if( max_coeff == 64 ) - fill_rectangle(&h->non_zero_count_cache[scan8[n]], 2, 2, 8, coeff_count, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[n]], 2, 2, 8, coeff_count, 1); else { assert( cat == 1 || cat == 2 || cat == 4 || cat == 7 || cat == 8 || cat == 11 || cat == 12 ); - h->non_zero_count_cache[scan8[n]] = coeff_count; + sl->non_zero_count_cache[scan8[n]] = coeff_count; } } @@ -1736,39 +1754,42 @@ decode_cabac_residual_internal(H264Context *h, int16_t *block, STORE_BLOCK(int16_t) } #ifdef CABAC_ON_STACK - h->cabac.range = cc.range ; - h->cabac.low = cc.low ; - h->cabac.bytestream= cc.bytestream; + sl->cabac.range = cc.range ; + sl->cabac.low = cc.low ; + sl->cabac.bytestream= cc.bytestream; #endif } -static av_noinline void decode_cabac_residual_dc_internal(H264Context *h, +static av_noinline void decode_cabac_residual_dc_internal(const H264Context *h, + H264SliceContext *sl, int16_t *block, int cat, int n, const uint8_t *scantable, int max_coeff) { - decode_cabac_residual_internal(h, block, cat, n, scantable, NULL, max_coeff, 1, 0); + decode_cabac_residual_internal(h, sl, block, cat, n, scantable, NULL, max_coeff, 1, 0); } -static av_noinline void decode_cabac_residual_dc_internal_422(H264Context *h, +static av_noinline void decode_cabac_residual_dc_internal_422(const H264Context *h, + H264SliceContext *sl, int16_t *block, int cat, int n, const uint8_t *scantable, int max_coeff) { - decode_cabac_residual_internal(h, block, cat, n, scantable, NULL, max_coeff, 1, 1); + decode_cabac_residual_internal(h, sl, block, cat, n, scantable, NULL, max_coeff, 1, 1); } -static av_noinline void decode_cabac_residual_nondc_internal(H264Context *h, +static av_noinline void decode_cabac_residual_nondc_internal(const H264Context *h, + H264SliceContext *sl, int16_t *block, int cat, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff) { - decode_cabac_residual_internal(h, block, cat, n, scantable, qmul, max_coeff, 0, 0); + decode_cabac_residual_internal(h, sl, block, cat, n, scantable, qmul, max_coeff, 0, 0); } /* cat: 0-> DC 16x16 n = 0 @@ -1783,34 +1804,37 @@ static av_noinline void decode_cabac_residual_nondc_internal(H264Context *h, * because it allows improved constant propagation into get_cabac_cbf_ctx, * as well as because most blocks have zero CBFs. */ -static av_always_inline void decode_cabac_residual_dc(H264Context *h, +static av_always_inline void decode_cabac_residual_dc(const H264Context *h, + H264SliceContext *sl, int16_t *block, int cat, int n, const uint8_t *scantable, int max_coeff) { /* read coded block flag */ - if( get_cabac( &h->cabac, &h->cabac_state[get_cabac_cbf_ctx( h, cat, n, max_coeff, 1 ) ] ) == 0 ) { - h->non_zero_count_cache[scan8[n]] = 0; + if( get_cabac( &sl->cabac, &sl->cabac_state[get_cabac_cbf_ctx(sl, cat, n, max_coeff, 1)]) == 0 ) { + sl->non_zero_count_cache[scan8[n]] = 0; return; } - decode_cabac_residual_dc_internal( h, block, cat, n, scantable, max_coeff ); + decode_cabac_residual_dc_internal(h, sl, block, cat, n, scantable, max_coeff); } static av_always_inline void -decode_cabac_residual_dc_422(H264Context *h, int16_t *block, +decode_cabac_residual_dc_422(const H264Context *h, H264SliceContext *sl, + int16_t *block, int cat, int n, const uint8_t *scantable, int max_coeff) { /* read coded block flag */ - if (get_cabac(&h->cabac, &h->cabac_state[get_cabac_cbf_ctx(h, cat, n, max_coeff, 1)]) == 0) { - h->non_zero_count_cache[scan8[n]] = 0; + if (get_cabac(&sl->cabac, &sl->cabac_state[get_cabac_cbf_ctx(sl, cat, n, max_coeff, 1)]) == 0) { + sl->non_zero_count_cache[scan8[n]] = 0; return; } - decode_cabac_residual_dc_internal_422(h, block, cat, n, scantable, max_coeff); + decode_cabac_residual_dc_internal_422(h, sl, block, cat, n, scantable, max_coeff); } -static av_always_inline void decode_cabac_residual_nondc(H264Context *h, +static av_always_inline void decode_cabac_residual_nondc(const H264Context *h, + H264SliceContext *sl, int16_t *block, int cat, int n, const uint8_t *scantable, @@ -1818,38 +1842,40 @@ static av_always_inline void decode_cabac_residual_nondc(H264Context *h, int max_coeff) { /* read coded block flag */ - if( (cat != 5 || CHROMA444(h)) && get_cabac( &h->cabac, &h->cabac_state[get_cabac_cbf_ctx( h, cat, n, max_coeff, 0 ) ] ) == 0 ) { + if( (cat != 5 || CHROMA444(h)) && get_cabac( &sl->cabac, &sl->cabac_state[get_cabac_cbf_ctx(sl, cat, n, max_coeff, 0)]) == 0) { if( max_coeff == 64 ) { - fill_rectangle(&h->non_zero_count_cache[scan8[n]], 2, 2, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[n]], 2, 2, 8, 0, 1); } else { - h->non_zero_count_cache[scan8[n]] = 0; + sl->non_zero_count_cache[scan8[n]] = 0; } return; } - decode_cabac_residual_nondc_internal( h, block, cat, n, scantable, qmul, max_coeff ); + decode_cabac_residual_nondc_internal(h, sl, block, cat, n, scantable, qmul, max_coeff); } -static av_always_inline void decode_cabac_luma_residual( H264Context *h, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p ) +static av_always_inline void decode_cabac_luma_residual(const H264Context *h, H264SliceContext *sl, + const uint8_t *scan, const uint8_t *scan8x8, + int pixel_shift, int mb_type, int cbp, int p) { static const uint8_t ctx_cat[4][3] = {{0,6,10},{1,7,11},{2,8,12},{5,9,13}}; const uint32_t *qmul; int i8x8, i4x4; - int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1]; + int qscale = p == 0 ? sl->qscale : sl->chroma_qp[p - 1]; if( IS_INTRA16x16( mb_type ) ) { - AV_ZERO128(h->mb_luma_dc[p]+0); - AV_ZERO128(h->mb_luma_dc[p]+8); - AV_ZERO128(h->mb_luma_dc[p]+16); - AV_ZERO128(h->mb_luma_dc[p]+24); - decode_cabac_residual_dc(h, h->mb_luma_dc[p], ctx_cat[0][p], LUMA_DC_BLOCK_INDEX+p, scan, 16); + AV_ZERO128(sl->mb_luma_dc[p]+0); + AV_ZERO128(sl->mb_luma_dc[p]+8); + AV_ZERO128(sl->mb_luma_dc[p]+16); + AV_ZERO128(sl->mb_luma_dc[p]+24); + decode_cabac_residual_dc(h, sl, sl->mb_luma_dc[p], ctx_cat[0][p], LUMA_DC_BLOCK_INDEX+p, scan, 16); if( cbp&15 ) { - qmul = h->dequant4_coeff[p][qscale]; + qmul = h->ps.pps->dequant4_coeff[p][qscale]; for( i4x4 = 0; i4x4 < 16; i4x4++ ) { const int index = 16*p + i4x4; - decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), ctx_cat[1][p], index, scan + 1, qmul, 15); + decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[1][p], index, scan + 1, qmul, 15); } } else { - fill_rectangle(&h->non_zero_count_cache[scan8[16*p]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16*p]], 4, 4, 8, 0, 1); } } else { int cqm = (IS_INTRA( mb_type ) ? 0:3) + p; @@ -1857,19 +1883,19 @@ static av_always_inline void decode_cabac_luma_residual( H264Context *h, const u if( cbp & (1<mb + (16*index << pixel_shift), ctx_cat[3][p], index, - scan8x8, h->dequant8_coeff[cqm][qscale], 64); + decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[3][p], index, + scan8x8, h->ps.pps->dequant8_coeff[cqm][qscale], 64); } else { - qmul = h->dequant4_coeff[cqm][qscale]; + qmul = h->ps.pps->dequant4_coeff[cqm][qscale]; for( i4x4 = 0; i4x4 < 4; i4x4++ ) { const int index = 16*p + 4*i8x8 + i4x4; //START_TIMER - decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), ctx_cat[2][p], index, scan, qmul, 16); + decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[2][p], index, scan, qmul, 16); //STOP_TIMER("decode_residual") } } } else { - fill_rectangle(&h->non_zero_count_cache[scan8[4*i8x8+16*p]], 2, 2, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[4*i8x8+16*p]], 2, 2, 8, 0, 1); } } } @@ -1879,140 +1905,141 @@ static av_always_inline void decode_cabac_luma_residual( H264Context *h, const u * Decode a macroblock. * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR if an error is noticed */ -int ff_h264_decode_mb_cabac(H264Context *h) { +int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl) +{ + const SPS *sps = h->ps.sps; int mb_xy; int mb_type, partition_count, cbp = 0; - int dct8x8_allowed= h->pps.transform_8x8_mode; - int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2; + int dct8x8_allowed= h->ps.pps->transform_8x8_mode; + int decode_chroma = sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2; const int pixel_shift = h->pixel_shift; - mb_xy = h->mb_xy = h->mb_x + h->mb_y*h->mb_stride; + mb_xy = sl->mb_xy = sl->mb_x + sl->mb_y*h->mb_stride; - tprintf(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, h->mb_x, h->mb_y); - if( h->slice_type_nos != AV_PICTURE_TYPE_I ) { + if (sl->slice_type_nos != AV_PICTURE_TYPE_I) { int skip; /* a skipped mb needs the aff flag from the following mb */ - if (FRAME_MBAFF(h) && (h->mb_y & 1) == 1 && h->prev_mb_skipped) - skip = h->next_mb_skipped; + if (FRAME_MBAFF(h) && (sl->mb_y & 1) == 1 && sl->prev_mb_skipped) + skip = sl->next_mb_skipped; else - skip = decode_cabac_mb_skip( h, h->mb_x, h->mb_y ); + skip = decode_cabac_mb_skip(h, sl, sl->mb_x, sl->mb_y ); /* read skip flags */ if( skip ) { - if (FRAME_MBAFF(h) && (h->mb_y & 1) == 0) { + if (FRAME_MBAFF(h) && (sl->mb_y & 1) == 0) { h->cur_pic.mb_type[mb_xy] = MB_TYPE_SKIP; - h->next_mb_skipped = decode_cabac_mb_skip( h, h->mb_x, h->mb_y+1 ); - if(!h->next_mb_skipped) - h->mb_mbaff = h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h); + sl->next_mb_skipped = decode_cabac_mb_skip(h, sl, sl->mb_x, sl->mb_y+1 ); + if(!sl->next_mb_skipped) + sl->mb_mbaff = sl->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h, sl); } - decode_mb_skip(h); + decode_mb_skip(h, sl); h->cbp_table[mb_xy] = 0; h->chroma_pred_mode_table[mb_xy] = 0; - h->last_qscale_diff = 0; + sl->last_qscale_diff = 0; return 0; } } if (FRAME_MBAFF(h)) { - if( (h->mb_y&1) == 0 ) - h->mb_mbaff = - h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h); + if ((sl->mb_y & 1) == 0) + sl->mb_mbaff = + sl->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h, sl); } - h->prev_mb_skipped = 0; + sl->prev_mb_skipped = 0; - fill_decode_neighbors(h, -(MB_FIELD(h))); + fill_decode_neighbors(h, sl, -(MB_FIELD(sl))); - if( h->slice_type_nos == AV_PICTURE_TYPE_B ) { + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { int ctx = 0; - assert(h->slice_type_nos == AV_PICTURE_TYPE_B); + assert(sl->slice_type_nos == AV_PICTURE_TYPE_B); - if( !IS_DIRECT( h->left_type[LTOP]-1 ) ) + if (!IS_DIRECT(sl->left_type[LTOP] - 1)) ctx++; - if( !IS_DIRECT( h->top_type-1 ) ) + if (!IS_DIRECT(sl->top_type - 1)) ctx++; - if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+ctx] ) ){ + if( !get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+ctx] ) ){ mb_type= 0; /* B_Direct_16x16 */ - }else if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+3] ) ) { - mb_type= 1 + get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); /* B_L[01]_16x16 */ + }else if( !get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+3] ) ) { + mb_type= 1 + get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+5] ); /* B_L[01]_16x16 */ }else{ int bits; - bits = get_cabac_noinline( &h->cabac, &h->cabac_state[27+4] ) << 3; - bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ) << 2; - bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ) << 1; - bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); + bits = get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+4] ) << 3; + bits+= get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+5] ) << 2; + bits+= get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+5] ) << 1; + bits+= get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+5] ); if( bits < 8 ){ mb_type= bits + 3; /* B_Bi_16x16 through B_L1_L0_16x8 */ }else if( bits == 13 ){ - mb_type= decode_cabac_intra_mb_type(h, 32, 0); + mb_type = decode_cabac_intra_mb_type(sl, 32, 0); goto decode_intra_mb; }else if( bits == 14 ){ mb_type= 11; /* B_L1_L0_8x16 */ }else if( bits == 15 ){ mb_type= 22; /* B_8x8 */ }else{ - bits= ( bits<<1 ) + get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); + bits= ( bits<<1 ) + get_cabac_noinline( &sl->cabac, &sl->cabac_state[27+5] ); mb_type= bits - 4; /* B_L0_Bi_* through B_Bi_Bi_* */ } } - partition_count= b_mb_type_info[mb_type].partition_count; - mb_type= b_mb_type_info[mb_type].type; - } else if( h->slice_type_nos == AV_PICTURE_TYPE_P ) { - if( get_cabac_noinline( &h->cabac, &h->cabac_state[14] ) == 0 ) { + partition_count = ff_h264_b_mb_type_info[mb_type].partition_count; + mb_type = ff_h264_b_mb_type_info[mb_type].type; + } else if (sl->slice_type_nos == AV_PICTURE_TYPE_P) { + if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[14] ) == 0 ) { /* P-type */ - if( get_cabac_noinline( &h->cabac, &h->cabac_state[15] ) == 0 ) { + if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[15] ) == 0 ) { /* P_L0_D16x16, P_8x8 */ - mb_type= 3 * get_cabac_noinline( &h->cabac, &h->cabac_state[16] ); + mb_type= 3 * get_cabac_noinline( &sl->cabac, &sl->cabac_state[16] ); } else { /* P_L0_D8x16, P_L0_D16x8 */ - mb_type= 2 - get_cabac_noinline( &h->cabac, &h->cabac_state[17] ); + mb_type= 2 - get_cabac_noinline( &sl->cabac, &sl->cabac_state[17] ); } - partition_count= p_mb_type_info[mb_type].partition_count; - mb_type= p_mb_type_info[mb_type].type; + partition_count = ff_h264_p_mb_type_info[mb_type].partition_count; + mb_type = ff_h264_p_mb_type_info[mb_type].type; } else { - mb_type= decode_cabac_intra_mb_type(h, 17, 0); + mb_type = decode_cabac_intra_mb_type(sl, 17, 0); goto decode_intra_mb; } } else { - mb_type= decode_cabac_intra_mb_type(h, 3, 1); - if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type) + mb_type = decode_cabac_intra_mb_type(sl, 3, 1); + if (sl->slice_type == AV_PICTURE_TYPE_SI && mb_type) mb_type--; - assert(h->slice_type_nos == AV_PICTURE_TYPE_I); + assert(sl->slice_type_nos == AV_PICTURE_TYPE_I); decode_intra_mb: partition_count = 0; - cbp= i_mb_type_info[mb_type].cbp; - h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode; - mb_type= i_mb_type_info[mb_type].type; + cbp = ff_h264_i_mb_type_info[mb_type].cbp; + sl->intra16x16_pred_mode = ff_h264_i_mb_type_info[mb_type].pred_mode; + mb_type = ff_h264_i_mb_type_info[mb_type].type; } - if(MB_FIELD(h)) + if (MB_FIELD(sl)) mb_type |= MB_TYPE_INTERLACED; - h->slice_table[ mb_xy ]= h->slice_num; + h->slice_table[mb_xy] = sl->slice_num; if(IS_INTRA_PCM(mb_type)) { - const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] * - h->sps.bit_depth_luma >> 3; + const int mb_size = ff_h264_mb_sizes[sps->chroma_format_idc] * + sps->bit_depth_luma >> 3; const uint8_t *ptr; // We assume these blocks are very rare so we do not optimize it. // FIXME The two following lines get the bitstream position in the cabac // decode, I think it should be done by a function in cabac.h (or cabac.c). - ptr= h->cabac.bytestream; - if(h->cabac.low&0x1) ptr--; + ptr= sl->cabac.bytestream; + if(sl->cabac.low&0x1) ptr--; if(CABAC_BITS==16){ - if(h->cabac.low&0x1FF) ptr--; + if(sl->cabac.low&0x1FF) ptr--; } // The pixels are stored in the same order as levels in h->mb array. - if ((int) (h->cabac.bytestream_end - ptr) < mb_size) + if ((int) (sl->cabac.bytestream_end - ptr) < mb_size) return -1; - h->intra_pcm_ptr = ptr; + sl->intra_pcm_ptr = ptr; ptr += mb_size; - ff_init_cabac_decoder(&h->cabac, ptr, h->cabac.bytestream_end - ptr); + ff_init_cabac_decoder(&sl->cabac, ptr, sl->cabac.bytestream_end - ptr); // All blocks are present h->cbp_table[mb_xy] = 0xf7ef; @@ -2022,81 +2049,85 @@ decode_intra_mb: // All coeffs are present memset(h->non_zero_count[mb_xy], 16, 48); h->cur_pic.mb_type[mb_xy] = mb_type; - h->last_qscale_diff = 0; + sl->last_qscale_diff = 0; return 0; } - fill_decode_caches(h, mb_type); + fill_decode_caches(h, sl, mb_type); if( IS_INTRA( mb_type ) ) { int i, pred_mode; if( IS_INTRA4x4( mb_type ) ) { - if( dct8x8_allowed && get_cabac_noinline( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] ) ) { + if (dct8x8_allowed && get_cabac_noinline(&sl->cabac, &sl->cabac_state[399 + sl->neighbor_transform_size])) { mb_type |= MB_TYPE_8x8DCT; for( i = 0; i < 16; i+=4 ) { - int pred = pred_intra_mode( h, i ); - int mode = decode_cabac_mb_intra4x4_pred_mode( h, pred ); - fill_rectangle( &h->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 ); + int pred = pred_intra_mode(h, sl, i); + int mode = decode_cabac_mb_intra4x4_pred_mode(sl, pred); + fill_rectangle(&sl->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 ); + int pred = pred_intra_mode(h, sl, i); + sl->intra4x4_pred_mode_cache[scan8[i]] = decode_cabac_mb_intra4x4_pred_mode(sl, pred); - av_dlog(h->avctx, "i4x4 pred=%d mode=%d\n", pred, - h->intra4x4_pred_mode_cache[scan8[i]]); + ff_dlog(h->avctx, "i4x4 pred=%d mode=%d\n", pred, + sl->intra4x4_pred_mode_cache[scan8[i]]); } } - write_back_intra_pred_mode(h); - if( ff_h264_check_intra4x4_pred_mode(h) < 0 ) return -1; + write_back_intra_pred_mode(h, sl); + if (ff_h264_check_intra4x4_pred_mode(sl->intra4x4_pred_mode_cache, h->avctx, + sl->top_samples_available, sl->left_samples_available) < 0 ) + return -1; } else { - h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode( h, h->intra16x16_pred_mode, 0 ); - if( h->intra16x16_pred_mode < 0 ) return -1; + sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available, + sl->left_samples_available, sl->intra16x16_pred_mode, 0); + if (sl->intra16x16_pred_mode < 0) return -1; } if(decode_chroma){ h->chroma_pred_mode_table[mb_xy] = - pred_mode = decode_cabac_mb_chroma_pre_mode( h ); + pred_mode = decode_cabac_mb_chroma_pre_mode(h, sl); - pred_mode= ff_h264_check_intra_pred_mode( h, pred_mode, 1 ); + pred_mode= ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available, + sl->left_samples_available, pred_mode, 1 ); if( pred_mode < 0 ) return -1; - h->chroma_pred_mode= pred_mode; + sl->chroma_pred_mode = pred_mode; } else { - h->chroma_pred_mode= DC_128_PRED8x8; + sl->chroma_pred_mode = DC_128_PRED8x8; } } else if( partition_count == 4 ) { int i, j, sub_partition_count[4], list, ref[2][4]; - if( h->slice_type_nos == AV_PICTURE_TYPE_B ) { + if (sl->slice_type_nos == AV_PICTURE_TYPE_B ) { for( i = 0; i < 4; i++ ) { - h->sub_mb_type[i] = decode_cabac_b_mb_sub_type( h ); - sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; - h->sub_mb_type[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].type; + sl->sub_mb_type[i] = decode_cabac_b_mb_sub_type(sl); + sub_partition_count[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].partition_count; + sl->sub_mb_type[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].type; } - if( IS_DIRECT(h->sub_mb_type[0] | h->sub_mb_type[1] | - h->sub_mb_type[2] | h->sub_mb_type[3]) ) { - ff_h264_pred_direct_motion(h, &mb_type); - h->ref_cache[0][scan8[4]] = - h->ref_cache[1][scan8[4]] = - h->ref_cache[0][scan8[12]] = - h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; + if (IS_DIRECT(sl->sub_mb_type[0] | sl->sub_mb_type[1] | + sl->sub_mb_type[2] | sl->sub_mb_type[3])) { + ff_h264_pred_direct_motion(h, sl, &mb_type); + sl->ref_cache[0][scan8[4]] = + sl->ref_cache[1][scan8[4]] = + sl->ref_cache[0][scan8[12]] = + sl->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; for( i = 0; i < 4; i++ ) - fill_rectangle( &h->direct_cache[scan8[4*i]], 2, 2, 8, (h->sub_mb_type[i]>>1)&0xFF, 1 ); + fill_rectangle(&sl->direct_cache[scan8[4*i]], 2, 2, 8, (sl->sub_mb_type[i] >> 1) & 0xFF, 1); } } else { for( i = 0; i < 4; i++ ) { - h->sub_mb_type[i] = decode_cabac_p_mb_sub_type( h ); - sub_partition_count[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; - h->sub_mb_type[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].type; + sl->sub_mb_type[i] = decode_cabac_p_mb_sub_type(sl); + sub_partition_count[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].partition_count; + sl->sub_mb_type[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].type; } } - for( list = 0; list < h->list_count; list++ ) { + for( list = 0; list < sl->list_count; list++ ) { for( i = 0; i < 4; i++ ) { - if(IS_DIRECT(h->sub_mb_type[i])) continue; - if(IS_DIR(h->sub_mb_type[i], 0, list)){ - int rc = h->ref_count[list] << MB_MBAFF(h); + if(IS_DIRECT(sl->sub_mb_type[i])) continue; + if(IS_DIR(sl->sub_mb_type[i], 0, list)){ + int rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc > 1) { - ref[list][i] = decode_cabac_mb_ref( h, list, 4*i ); + ref[list][i] = decode_cabac_mb_ref(sl, list, 4 * i); if (ref[list][i] >= (unsigned) rc) { av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref[list][i], rc); return -1; @@ -2106,34 +2137,34 @@ decode_intra_mb: } 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]; + sl->ref_cache[list][scan8[4 * i] + 1] = + sl->ref_cache[list][scan8[4 * i] + 8] = sl->ref_cache[list][scan8[4 * i] + 9] = ref[list][i]; } } if(dct8x8_allowed) - dct8x8_allowed = get_dct8x8_allowed(h); + dct8x8_allowed = get_dct8x8_allowed(h, sl); - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<4; i++){ - h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ]; - if(IS_DIRECT(h->sub_mb_type[i])){ - fill_rectangle(h->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 2); + sl->ref_cache[list][scan8[4 * i]] = sl->ref_cache[list][scan8[4 * i] + 1]; + if(IS_DIRECT(sl->sub_mb_type[i])){ + fill_rectangle(sl->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 2); continue; } - if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){ - const int sub_mb_type= h->sub_mb_type[i]; + if(IS_DIR(sl->sub_mb_type[i], 0, list) && !IS_DIRECT(sl->sub_mb_type[i])){ + const int sub_mb_type= sl->sub_mb_type[i]; const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1; for(j=0; jmv_cache[list][ scan8[index] ]; - uint8_t (* mvd_cache)[2]= &h->mvd_cache[list][ scan8[index] ]; - pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my); - DECODE_CABAC_MB_MVD( h, list, index) - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + int16_t (* mv_cache)[2] = &sl->mv_cache[list][ scan8[index] ]; + uint8_t (* mvd_cache)[2]= &sl->mvd_cache[list][ scan8[index] ]; + pred_motion(h, sl, index, block_width, list, sl->ref_cache[list][ scan8[index] ], &mx, &my); + DECODE_CABAC_MB_MVD(sl, list, index) + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); if(IS_SUB_8X8(sub_mb_type)){ mv_cache[ 1 ][0]= @@ -2165,111 +2196,111 @@ decode_intra_mb: mvd_cache[ 0 ][1]= mpy; } }else{ - fill_rectangle(h->mv_cache [list][ scan8[4*i] ], 2, 2, 8, 0, 4); - fill_rectangle(h->mvd_cache[list][ scan8[4*i] ], 2, 2, 8, 0, 2); + fill_rectangle(sl->mv_cache [list][ scan8[4*i] ], 2, 2, 8, 0, 4); + fill_rectangle(sl->mvd_cache[list][ scan8[4*i] ], 2, 2, 8, 0, 2); } } } } else if( IS_DIRECT(mb_type) ) { - ff_h264_pred_direct_motion(h, &mb_type); - fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 2); - fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 2); - dct8x8_allowed &= h->sps.direct_8x8_inference_flag; + ff_h264_pred_direct_motion(h, sl, &mb_type); + fill_rectangle(sl->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 2); + fill_rectangle(sl->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 2); + dct8x8_allowed &= sps->direct_8x8_inference_flag; } else { int list, i; if(IS_16X16(mb_type)){ - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { if(IS_DIR(mb_type, 0, list)){ - int ref, rc = h->ref_count[list] << MB_MBAFF(h); + int ref, rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc > 1) { - ref= decode_cabac_mb_ref(h, list, 0); + ref= decode_cabac_mb_ref(sl, list, 0); if (ref >= (unsigned) rc) { av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, rc); return -1; } }else ref=0; - fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1); + fill_rectangle(&sl->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { if(IS_DIR(mb_type, 0, list)){ int mx,my,mpx,mpy; - pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mx, &my); - DECODE_CABAC_MB_MVD( h, list, 0) - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + pred_motion(h, sl, 0, 4, list, sl->ref_cache[list][ scan8[0] ], &mx, &my); + DECODE_CABAC_MB_MVD(sl, list, 0) + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); - fill_rectangle(h->mvd_cache[list][ scan8[0] ], 4, 4, 8, pack8to16(mpx,mpy), 2); - fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); + fill_rectangle(sl->mvd_cache[list][ scan8[0] ], 4, 4, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(sl->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); } } } else if(IS_16X8(mb_type)){ - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ if(IS_DIR(mb_type, i, list)){ - int ref, rc = h->ref_count[list] << MB_MBAFF(h); + int ref, rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc > 1) { - ref= decode_cabac_mb_ref( h, list, 8*i ); + ref= decode_cabac_mb_ref(sl, list, 8 * i); if (ref >= (unsigned) rc) { av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, rc); return -1; } }else ref=0; - fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1); + fill_rectangle(&sl->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); + fill_rectangle(&sl->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ if(IS_DIR(mb_type, i, list)){ int mx,my,mpx,mpy; - pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mx, &my); - DECODE_CABAC_MB_MVD( h, list, 8*i) - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + pred_16x8_motion(h, sl, 8*i, list, sl->ref_cache[list][scan8[0] + 16*i], &mx, &my); + DECODE_CABAC_MB_MVD(sl, list, 8*i) + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); - fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack8to16(mpx,mpy), 2); - fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4); + fill_rectangle(sl->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4); }else{ - fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 2); - fill_rectangle(h-> mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4); + fill_rectangle(sl->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 2); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4); } } } }else{ assert(IS_8X16(mb_type)); - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ if(IS_DIR(mb_type, i, list)){ //FIXME optimize - int ref, rc = h->ref_count[list] << MB_MBAFF(h); + int ref, rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc > 1) { - ref= decode_cabac_mb_ref( h, list, 4*i ); + ref = decode_cabac_mb_ref(sl, list, 4 * i); if (ref >= (unsigned) rc) { av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, rc); return -1; } }else ref=0; - fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1); + fill_rectangle(&sl->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); + fill_rectangle(&sl->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ if(IS_DIR(mb_type, i, list)){ int mx,my,mpx,mpy; - pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); - DECODE_CABAC_MB_MVD( h, list, 4*i) + pred_8x16_motion(h, sl, i*4, list, sl->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); + DECODE_CABAC_MB_MVD(sl, list, 4*i) - tprintf(h->avctx, "final mv:%d %d\n", mx, my); - fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack8to16(mpx,mpy), 2); - fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4); + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); + fill_rectangle(sl->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4); }else{ - fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 2); - fill_rectangle(h-> mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4); + fill_rectangle(sl->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 2); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4); } } } @@ -2278,28 +2309,28 @@ decode_intra_mb: if( IS_INTER( mb_type ) ) { h->chroma_pred_mode_table[mb_xy] = 0; - write_back_motion( h, mb_type ); + write_back_motion(h, sl, mb_type); } if( !IS_INTRA16x16( mb_type ) ) { - cbp = decode_cabac_mb_cbp_luma( h ); + cbp = decode_cabac_mb_cbp_luma(sl); if(decode_chroma) - cbp |= decode_cabac_mb_cbp_chroma( h ) << 4; + cbp |= decode_cabac_mb_cbp_chroma(sl) << 4; } - h->cbp_table[mb_xy] = h->cbp = cbp; + h->cbp_table[mb_xy] = sl->cbp = cbp; if( dct8x8_allowed && (cbp&15) && !IS_INTRA( mb_type ) ) { - mb_type |= MB_TYPE_8x8DCT * get_cabac_noinline( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] ); + mb_type |= MB_TYPE_8x8DCT * get_cabac_noinline(&sl->cabac, &sl->cabac_state[399 + sl->neighbor_transform_size]); } /* It would be better to do this in fill_decode_caches, but we don't know * the transform mode of the current macroblock there. */ if (CHROMA444(h) && IS_8x8DCT(mb_type)){ int i; - uint8_t *nnz_cache = h->non_zero_count_cache; + uint8_t *nnz_cache = sl->non_zero_count_cache; for (i = 0; i < 2; i++){ - if (h->left_type[LEFT(i)] && !IS_8x8DCT(h->left_type[LEFT(i)])){ + if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { nnz_cache[3+8* 1 + 2*8*i]= nnz_cache[3+8* 2 + 2*8*i]= nnz_cache[3+8* 6 + 2*8*i]= @@ -2308,8 +2339,8 @@ decode_intra_mb: nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; } } - if (h->top_type && !IS_8x8DCT(h->top_type)){ - uint32_t top_empty = CABAC(h) && !IS_INTRA(mb_type) ? 0 : 0x40404040; + if (sl->top_type && !IS_8x8DCT(sl->top_type)){ + uint32_t top_empty = !IS_INTRA(mb_type) ? 0 : 0x40404040; AV_WN32A(&nnz_cache[4+8* 0], top_empty); AV_WN32A(&nnz_cache[4+8* 5], top_empty); AV_WN32A(&nnz_cache[4+8*10], top_empty); @@ -2322,24 +2353,24 @@ decode_intra_mb: const uint32_t *qmul; if(IS_INTERLACED(mb_type)){ - scan8x8= h->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; - scan= h->qscale ? h->field_scan : h->field_scan_q0; + scan8x8 = sl->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; + scan = sl->qscale ? h->field_scan : h->field_scan_q0; }else{ - scan8x8= h->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; - scan= h->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + scan8x8 = sl->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; + scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; } // decode_cabac_mb_dqp - if(get_cabac_noinline( &h->cabac, &h->cabac_state[60 + (h->last_qscale_diff != 0)])){ + if(get_cabac_noinline( &sl->cabac, &sl->cabac_state[60 + (sl->last_qscale_diff != 0)])){ int val = 1; int ctx= 2; - const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8); + const int max_qp = 51 + 6*(sps->bit_depth_luma-8); - while( get_cabac_noinline( &h->cabac, &h->cabac_state[60 + ctx] ) ) { + while( get_cabac_noinline( &sl->cabac, &sl->cabac_state[60 + ctx] ) ) { ctx= 3; val++; if(val > 2*max_qp){ //prevent infinite loop - av_log(h->avctx, AV_LOG_ERROR, "cabac decode of qscale diff failed at %d %d\n", h->mb_x, h->mb_y); + av_log(h->avctx, AV_LOG_ERROR, "cabac decode of qscale diff failed at %d %d\n", sl->mb_x, sl->mb_y); return -1; } } @@ -2348,77 +2379,78 @@ decode_intra_mb: val= (val + 1)>>1 ; else val= -((val + 1)>>1); - h->last_qscale_diff = val; - h->qscale += val; - if(((unsigned)h->qscale) > max_qp){ - if(h->qscale<0) h->qscale+= max_qp+1; - else h->qscale-= max_qp+1; + sl->last_qscale_diff = val; + sl->qscale += val; + if (((unsigned)sl->qscale) > max_qp){ + if (sl->qscale < 0) sl->qscale += max_qp + 1; + else sl->qscale -= max_qp + 1; } - h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); + sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, sl->qscale); + sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, sl->qscale); }else - h->last_qscale_diff=0; + sl->last_qscale_diff=0; - decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 0); + decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 0); if (CHROMA444(h)) { - decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 1); - decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 2); + decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 1); + decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 2); } else if (CHROMA422(h)) { if( cbp&0x30 ){ int c; for (c = 0; c < 2; c++) - decode_cabac_residual_dc_422(h, h->mb + ((256 + 16*16*c) << pixel_shift), 3, + decode_cabac_residual_dc_422(h, sl, sl->mb + ((256 + 16*16*c) << pixel_shift), 3, CHROMA_DC_BLOCK_INDEX + c, - chroma422_dc_scan, 8); + ff_h264_chroma422_dc_scan, 8); } if( cbp&0x20 ) { int c, i, i8x8; for( c = 0; c < 2; c++ ) { - int16_t *mb = h->mb + (16*(16 + 16*c) << pixel_shift); - qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[c]]; + int16_t *mb = sl->mb + (16*(16 + 16*c) << pixel_shift); + qmul = h->ps.pps->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]]; for (i8x8 = 0; i8x8 < 2; i8x8++) { for (i = 0; i < 4; i++) { const int index = 16 + 16 * c + 8*i8x8 + i; - decode_cabac_residual_nondc(h, mb, 4, index, scan + 1, qmul, 15); + decode_cabac_residual_nondc(h, sl, mb, 4, index, scan + 1, qmul, 15); mb += 16<non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); } } else /* yuv420 */ { if( cbp&0x30 ){ int c; for (c = 0; c < 2; c++) - decode_cabac_residual_dc(h, h->mb + ((256 + 16*16*c) << pixel_shift), 3, CHROMA_DC_BLOCK_INDEX+c, chroma_dc_scan, 4); + decode_cabac_residual_dc(h, sl, sl->mb + ((256 + 16 * 16 * c) << pixel_shift), + 3, CHROMA_DC_BLOCK_INDEX + c, ff_h264_chroma_dc_scan, 4); } if( cbp&0x20 ) { int c, i; for( c = 0; c < 2; c++ ) { - qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[c]]; + qmul = h->ps.pps->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]]; for( i = 0; i < 4; i++ ) { const int index = 16 + 16 * c + i; - decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), 4, index, scan + 1, qmul, 15); + decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), 4, index, scan + 1, qmul, 15); } } } else { - fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); } } } else { - fill_rectangle(&h->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); - h->last_qscale_diff = 0; + fill_rectangle(&sl->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + sl->last_qscale_diff = 0; } - h->cur_pic.qscale_table[mb_xy] = h->qscale; - write_back_non_zero_count(h); + h->cur_pic.qscale_table[mb_xy] = sl->qscale; + write_back_non_zero_count(h, sl); return 0; } diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index 0ab0355..22a643b 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 cavlc bitstream decoding. + * H.264 / AVC / MPEG-4 part10 cavlc bitstream decoding. * @author Michael Niedermayer */ @@ -29,9 +29,9 @@ #include "internal.h" #include "avcodec.h" -#include "h264.h" -#include "h264data.h" // FIXME FIXME FIXME +#include "h264dec.h" #include "h264_mvpred.h" +#include "h264data.h" #include "golomb.h" #include "mpegutils.h" @@ -283,15 +283,16 @@ static int8_t cavlc_level_tab[7][1<non_zero_count_cache[index8 - 1]; - const int top = h->non_zero_count_cache[index8 - 8]; + const int left = sl->non_zero_count_cache[index8 - 1]; + const int top = sl->non_zero_count_cache[index8 - 8]; int i= left + top; if(i<64) i= (i+1)>>1; - tprintf(h->avctx, "pred_nnz L%X T%X n%d s%d P%X\n", left, top, n, scan8[n], i&31); + ff_tlog(h->avctx, "pred_nnz L%X T%X n%d s%d P%X\n", left, top, n, scan8[n], i&31); return i&31; } @@ -411,9 +412,6 @@ av_cold void ff_h264_decode_init_vlc(void){ } } -/** - * - */ static inline int get_level_prefix(GetBitContext *gb){ unsigned int buf; int log; @@ -423,10 +421,6 @@ static inline int get_level_prefix(GetBitContext *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); @@ -441,7 +435,11 @@ static inline int get_level_prefix(GetBitContext *gb){ * @param max_coeff number of coefficients in the block * @return <0 if an error occurred */ -static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff){ +static int decode_residual(const H264Context *h, H264SliceContext *sl, + GetBitContext *gb, int16_t *block, int n, + const uint8_t *scantable, const uint32_t *qmul, + int max_coeff) +{ static const int coeff_token_table_index[17]= {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3}; int level[16]; int zeros_left, coeff_token, total_coeff, i, trailing_ones, run_before; @@ -456,28 +454,28 @@ static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, in total_coeff= coeff_token>>2; }else{ if(n >= LUMA_DC_BLOCK_INDEX){ - total_coeff= pred_non_zero_count(h, (n - LUMA_DC_BLOCK_INDEX)*16); + total_coeff= pred_non_zero_count(h, sl, (n - LUMA_DC_BLOCK_INDEX)*16); coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2); total_coeff= coeff_token>>2; }else{ - total_coeff= pred_non_zero_count(h, n); + total_coeff= pred_non_zero_count(h, sl, 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; + sl->non_zero_count_cache[scan8[n]] = total_coeff; //FIXME set last_non_zero? if(total_coeff==0) return 0; if(total_coeff > (unsigned)max_coeff) { - av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", h->mb_x, h->mb_y, total_coeff); + av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", sl->mb_x, sl->mb_y, total_coeff); return -1; } trailing_ones= coeff_token&3; - tprintf(h->avctx, "trailing:%d, total:%d\n", trailing_ones, total_coeff); + ff_tlog(h->avctx, "trailing:%d, total:%d\n", trailing_ones, total_coeff); assert(total_coeff<=16); i = show_bits(gb, 3); @@ -581,8 +579,10 @@ static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, in for(i=1;i 0;i++) { \ if(zeros_left < 7) \ run_before= get_vlc2(gb, run_vlc[zeros_left - 1].table, RUN_VLC_BITS, 1); \ - else \ + else {\ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + run_before = FFMIN(zeros_left, run_before);\ + }\ zeros_left -= run_before; \ scantable -= 1 + run_before; \ ((type*)block)[*scantable]= level[i]; \ @@ -596,8 +596,10 @@ static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, in for(i=1;i 0;i++) { \ if(zeros_left < 7) \ run_before= get_vlc2(gb, run_vlc[zeros_left - 1].table, RUN_VLC_BITS, 1); \ - else \ + else {\ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + run_before = FFMIN(zeros_left, run_before);\ + }\ zeros_left -= run_before; \ scantable -= 1 + run_before; \ ((type*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6; \ @@ -610,7 +612,7 @@ static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, in if (zeros_left < 0) { av_log(h->avctx, AV_LOG_ERROR, - "negative number of zero coeffs at %d %d\n", h->mb_x, h->mb_y); + "negative number of zero coeffs at %d %d\n", sl->mb_x, sl->mb_y); return AVERROR_INVALIDDATA; } @@ -623,15 +625,20 @@ static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, in return 0; } -static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext *gb, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p){ +static av_always_inline +int decode_luma_residual(const H264Context *h, H264SliceContext *sl, + GetBitContext *gb, const uint8_t *scan, + const uint8_t *scan8x8, int pixel_shift, + int mb_type, int cbp, int p) +{ int i4x4, i8x8; - int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1]; + int qscale = p == 0 ? sl->qscale : sl->chroma_qp[p - 1]; if(IS_INTRA16x16(mb_type)){ - AV_ZERO128(h->mb_luma_dc[p]+0); - AV_ZERO128(h->mb_luma_dc[p]+8); - AV_ZERO128(h->mb_luma_dc[p]+16); - AV_ZERO128(h->mb_luma_dc[p]+24); - if( decode_residual(h, h->intra_gb_ptr, h->mb_luma_dc[p], LUMA_DC_BLOCK_INDEX+p, scan, NULL, 16) < 0){ + AV_ZERO128(sl->mb_luma_dc[p]+0); + AV_ZERO128(sl->mb_luma_dc[p]+8); + AV_ZERO128(sl->mb_luma_dc[p]+16); + AV_ZERO128(sl->mb_luma_dc[p]+24); + if (decode_residual(h, sl, gb, sl->mb_luma_dc[p], LUMA_DC_BLOCK_INDEX + p, scan, NULL, 16) < 0) { return -1; //FIXME continue if partitioned and other return -1 too } @@ -641,15 +648,15 @@ static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext * for(i8x8=0; i8x8<4; i8x8++){ for(i4x4=0; i4x4<4; i4x4++){ const int index= i4x4 + 4*i8x8 + p*16; - if( decode_residual(h, h->intra_gb_ptr, h->mb + (16*index << pixel_shift), - index, scan + 1, h->dequant4_coeff[p][qscale], 15) < 0 ){ + if( decode_residual(h, sl, gb, sl->mb + (16*index << pixel_shift), + index, scan + 1, h->ps.pps->dequant4_coeff[p][qscale], 15) < 0 ){ return -1; } } } return 0xf; }else{ - fill_rectangle(&h->non_zero_count_cache[scan8[p*16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[p*16]], 4, 4, 8, 0, 1); return 0; } }else{ @@ -659,29 +666,29 @@ static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext * for(i8x8=0; i8x8<4; i8x8++){ if(cbp & (1<mb[64*i8x8+256*p << pixel_shift]; + int16_t *buf = &sl->mb[64*i8x8+256*p << pixel_shift]; uint8_t *nnz; for(i4x4=0; i4x4<4; i4x4++){ const int index= i4x4 + 4*i8x8 + p*16; - if( decode_residual(h, gb, buf, index, scan8x8+16*i4x4, - h->dequant8_coeff[cqm][qscale], 16) < 0 ) + if( decode_residual(h, sl, gb, buf, index, scan8x8+16*i4x4, + h->ps.pps->dequant8_coeff[cqm][qscale], 16) < 0 ) return -1; } - nnz= &h->non_zero_count_cache[ scan8[4*i8x8+p*16] ]; + nnz = &sl->non_zero_count_cache[scan8[4 * i8x8 + p * 16]]; nnz[0] += nnz[1] + nnz[8] + nnz[9]; new_cbp |= !!nnz[0] << i8x8; }else{ for(i4x4=0; i4x4<4; i4x4++){ const int index= i4x4 + 4*i8x8 + p*16; - if( decode_residual(h, gb, h->mb + (16*index << pixel_shift), index, - scan, h->dequant4_coeff[cqm][qscale], 16) < 0 ){ + if( decode_residual(h, sl, gb, sl->mb + (16*index << pixel_shift), index, + scan, h->ps.pps->dequant4_coeff[cqm][qscale], 16) < 0 ){ return -1; } - new_cbp |= h->non_zero_count_cache[ scan8[index] ] << i8x8; + new_cbp |= sl->non_zero_count_cache[scan8[index]] << i8x8; } } }else{ - uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8+p*16] ]; + uint8_t * const nnz = &sl->non_zero_count_cache[scan8[4 * i8x8 + p * 16]]; nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0; } } @@ -689,87 +696,87 @@ static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext * } } -int ff_h264_decode_mb_cavlc(H264Context *h){ +int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl) +{ int mb_xy; int partition_count; unsigned int mb_type, cbp; - int dct8x8_allowed= h->pps.transform_8x8_mode; - int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2; + int dct8x8_allowed= h->ps.pps->transform_8x8_mode; + int decode_chroma = h->ps.sps->chroma_format_idc == 1 || h->ps.sps->chroma_format_idc == 2; const int pixel_shift = h->pixel_shift; - mb_xy = h->mb_xy = h->mb_x + h->mb_y*h->mb_stride; + mb_xy = sl->mb_xy = sl->mb_x + sl->mb_y*h->mb_stride; - tprintf(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, h->mb_x, h->mb_y); cbp = 0; /* avoid warning. FIXME: find a solution without slowing down the code */ - if(h->slice_type_nos != AV_PICTURE_TYPE_I){ - if(h->mb_skip_run==-1) - h->mb_skip_run= get_ue_golomb(&h->gb); - - if (h->mb_skip_run--) { - if(FRAME_MBAFF(h) && (h->mb_y&1) == 0){ - if(h->mb_skip_run==0) - h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&h->gb); + if (sl->slice_type_nos != AV_PICTURE_TYPE_I) { + if (sl->mb_skip_run == -1) + sl->mb_skip_run = get_ue_golomb(&sl->gb); + + if (sl->mb_skip_run--) { + if (FRAME_MBAFF(h) && (sl->mb_y & 1) == 0) { + if (sl->mb_skip_run == 0) + sl->mb_mbaff = sl->mb_field_decoding_flag = get_bits1(&sl->gb); } - decode_mb_skip(h); + decode_mb_skip(h, sl); return 0; } } if (FRAME_MBAFF(h)) { - if( (h->mb_y&1) == 0 ) - h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&h->gb); + if ((sl->mb_y & 1) == 0) + sl->mb_mbaff = sl->mb_field_decoding_flag = get_bits1(&sl->gb); } - h->prev_mb_skipped= 0; + sl->prev_mb_skipped = 0; - mb_type= get_ue_golomb(&h->gb); - if(h->slice_type_nos == AV_PICTURE_TYPE_B){ + mb_type= get_ue_golomb(&sl->gb); + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { if(mb_type < 23){ - partition_count= b_mb_type_info[mb_type].partition_count; - mb_type= b_mb_type_info[mb_type].type; + partition_count = ff_h264_b_mb_type_info[mb_type].partition_count; + mb_type = ff_h264_b_mb_type_info[mb_type].type; }else{ mb_type -= 23; goto decode_intra_mb; } - }else if(h->slice_type_nos == AV_PICTURE_TYPE_P){ + } else if (sl->slice_type_nos == AV_PICTURE_TYPE_P) { if(mb_type < 5){ - partition_count= p_mb_type_info[mb_type].partition_count; - mb_type= p_mb_type_info[mb_type].type; + partition_count = ff_h264_p_mb_type_info[mb_type].partition_count; + mb_type = ff_h264_p_mb_type_info[mb_type].type; }else{ mb_type -= 5; goto decode_intra_mb; } }else{ - assert(h->slice_type_nos == AV_PICTURE_TYPE_I); - if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type) + assert(sl->slice_type_nos == AV_PICTURE_TYPE_I); + if (sl->slice_type == AV_PICTURE_TYPE_SI && mb_type) mb_type--; decode_intra_mb: if(mb_type > 25){ - av_log(h->avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_picture_type_char(h->slice_type), h->mb_x, h->mb_y); + av_log(h->avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_picture_type_char(sl->slice_type), sl->mb_x, sl->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; + cbp = ff_h264_i_mb_type_info[mb_type].cbp; + sl->intra16x16_pred_mode = ff_h264_i_mb_type_info[mb_type].pred_mode; + mb_type = ff_h264_i_mb_type_info[mb_type].type; } - if(MB_FIELD(h)) + if (MB_FIELD(sl)) mb_type |= MB_TYPE_INTERLACED; - h->slice_table[ mb_xy ]= h->slice_num; + h->slice_table[mb_xy] = sl->slice_num; if(IS_INTRA_PCM(mb_type)){ - const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] * - h->sps.bit_depth_luma; + const int mb_size = ff_h264_mb_sizes[h->ps.sps->chroma_format_idc] * + h->ps.sps->bit_depth_luma; // We assume these blocks are very rare so we do not optimize it. - h->intra_pcm_ptr = align_get_bits(&h->gb); - if (get_bits_left(&h->gb) < mb_size) { + sl->intra_pcm_ptr = align_get_bits(&sl->gb); + if (get_bits_left(&sl->gb) < mb_size) { av_log(h->avctx, AV_LOG_ERROR, "Not enough data for an intra PCM block.\n"); return AVERROR_INVALIDDATA; } - skip_bits_long(&h->gb, mb_size); + skip_bits_long(&sl->gb, mb_size); // In deblocking, the quantizer is 0 h->cur_pic.qscale_table[mb_xy] = 0; @@ -780,8 +787,8 @@ decode_intra_mb: return 0; } - fill_decode_neighbors(h, mb_type); - fill_decode_caches(h, mb_type); + fill_decode_neighbors(h, sl, mb_type); + fill_decode_caches(h, sl, mb_type); //mb_pred if(IS_INTRA(mb_type)){ @@ -790,86 +797,89 @@ decode_intra_mb: if(IS_INTRA4x4(mb_type)){ int i; int di = 1; - if(dct8x8_allowed && get_bits1(&h->gb)){ + if(dct8x8_allowed && get_bits1(&sl->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); + int mode = pred_intra_mode(h, sl, i); - if(!get_bits1(&h->gb)){ - const int rem_mode= get_bits(&h->gb, 3); + if(!get_bits1(&sl->gb)){ + const int rem_mode= get_bits(&sl->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 ); + fill_rectangle(&sl->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1); else - h->intra4x4_pred_mode_cache[ scan8[i] ] = mode; + sl->intra4x4_pred_mode_cache[scan8[i]] = mode; } - write_back_intra_pred_mode(h); - if( ff_h264_check_intra4x4_pred_mode(h) < 0) + write_back_intra_pred_mode(h, sl); + if (ff_h264_check_intra4x4_pred_mode(sl->intra4x4_pred_mode_cache, h->avctx, + sl->top_samples_available, sl->left_samples_available) < 0) return -1; }else{ - h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode(h, h->intra16x16_pred_mode, 0); - if(h->intra16x16_pred_mode < 0) + sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available, + sl->left_samples_available, sl->intra16x16_pred_mode, 0); + if (sl->intra16x16_pred_mode < 0) return -1; } if(decode_chroma){ - pred_mode= ff_h264_check_intra_pred_mode(h, get_ue_golomb_31(&h->gb), 1); + pred_mode= ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available, + sl->left_samples_available, get_ue_golomb_31(&sl->gb), 1); if(pred_mode < 0) return -1; - h->chroma_pred_mode= pred_mode; + sl->chroma_pred_mode = pred_mode; } else { - h->chroma_pred_mode = DC_128_PRED8x8; + sl->chroma_pred_mode = DC_128_PRED8x8; } }else if(partition_count==4){ int i, j, sub_partition_count[4], list, ref[2][4]; - if(h->slice_type_nos == AV_PICTURE_TYPE_B){ + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { for(i=0; i<4; i++){ - h->sub_mb_type[i]= get_ue_golomb_31(&h->gb); - if(h->sub_mb_type[i] >=13){ - av_log(h->avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], h->mb_x, h->mb_y); + sl->sub_mb_type[i]= get_ue_golomb_31(&sl->gb); + if(sl->sub_mb_type[i] >=13){ + av_log(h->avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", sl->sub_mb_type[i], sl->mb_x, sl->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; + sub_partition_count[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].partition_count; + sl->sub_mb_type[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].type; } - if( IS_DIRECT(h->sub_mb_type[0]|h->sub_mb_type[1]|h->sub_mb_type[2]|h->sub_mb_type[3])) { - ff_h264_pred_direct_motion(h, &mb_type); - h->ref_cache[0][scan8[4]] = - h->ref_cache[1][scan8[4]] = - h->ref_cache[0][scan8[12]] = - h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; + if( IS_DIRECT(sl->sub_mb_type[0]|sl->sub_mb_type[1]|sl->sub_mb_type[2]|sl->sub_mb_type[3])) { + ff_h264_pred_direct_motion(h, sl, &mb_type); + sl->ref_cache[0][scan8[4]] = + sl->ref_cache[1][scan8[4]] = + sl->ref_cache[0][scan8[12]] = + sl->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; } }else{ - assert(h->slice_type_nos == AV_PICTURE_TYPE_P); //FIXME SP correct ? + assert(sl->slice_type_nos == AV_PICTURE_TYPE_P); //FIXME SP correct ? for(i=0; i<4; i++){ - h->sub_mb_type[i]= get_ue_golomb_31(&h->gb); - if(h->sub_mb_type[i] >=4){ - av_log(h->avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], h->mb_x, h->mb_y); + sl->sub_mb_type[i]= get_ue_golomb_31(&sl->gb); + if(sl->sub_mb_type[i] >=4){ + av_log(h->avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", sl->sub_mb_type[i], sl->mb_x, sl->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; + sub_partition_count[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].partition_count; + sl->sub_mb_type[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].type; } } - for(list=0; listlist_count; list++){ - int ref_count = IS_REF0(mb_type) ? 1 : h->ref_count[list] << MB_MBAFF(h); + for (list = 0; list < sl->list_count; list++) { + int ref_count = IS_REF0(mb_type) ? 1 : sl->ref_count[list] << MB_MBAFF(sl); 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(IS_DIRECT(sl->sub_mb_type[i])) continue; + if(IS_DIR(sl->sub_mb_type[i], 0, list)){ unsigned int tmp; if(ref_count == 1){ tmp= 0; }else if(ref_count == 2){ - tmp= get_bits1(&h->gb)^1; + tmp= get_bits1(&sl->gb)^1; }else{ - tmp= get_ue_golomb_31(&h->gb); + tmp= get_ue_golomb_31(&sl->gb); if(tmp>=ref_count){ av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", tmp); return -1; @@ -884,28 +894,28 @@ decode_intra_mb: } if(dct8x8_allowed) - dct8x8_allowed = get_dct8x8_allowed(h); + dct8x8_allowed = get_dct8x8_allowed(h, sl); - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<4; i++){ - if(IS_DIRECT(h->sub_mb_type[i])) { - h->ref_cache[list][ scan8[4*i] ] = h->ref_cache[list][ scan8[4*i]+1 ]; + if(IS_DIRECT(sl->sub_mb_type[i])) { + sl->ref_cache[list][ scan8[4*i] ] = sl->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]; + sl->ref_cache[list][ scan8[4*i] ]=sl->ref_cache[list][ scan8[4*i]+1 ]= + sl->ref_cache[list][ scan8[4*i]+8 ]=sl->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]; + if(IS_DIR(sl->sub_mb_type[i], 0, list)){ + const int sub_mb_type= sl->sub_mb_type[i]; const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1; for(j=0; jmv_cache[list][ scan8[index] ]; - pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my); - mx += get_se_golomb(&h->gb); - my += get_se_golomb(&h->gb); - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + int16_t (* mv_cache)[2]= &sl->mv_cache[list][ scan8[index] ]; + pred_motion(h, sl, index, block_width, list, sl->ref_cache[list][ scan8[index] ], &mx, &my); + mx += get_se_golomb(&sl->gb); + my += get_se_golomb(&sl->gb); + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); if(IS_SUB_8X8(sub_mb_type)){ mv_cache[ 1 ][0]= @@ -923,60 +933,60 @@ decode_intra_mb: mv_cache[ 0 ][1]= my; } }else{ - uint32_t *p= (uint32_t *)&h->mv_cache[list][ scan8[4*i] ][0]; + uint32_t *p= (uint32_t *)&sl->mv_cache[list][ scan8[4*i] ][0]; p[0] = p[1]= p[8] = p[9]= 0; } } } }else if(IS_DIRECT(mb_type)){ - ff_h264_pred_direct_motion(h, &mb_type); - dct8x8_allowed &= h->sps.direct_8x8_inference_flag; + ff_h264_pred_direct_motion(h, sl, &mb_type); + dct8x8_allowed &= h->ps.sps->direct_8x8_inference_flag; }else{ int list, mx, my, i; //FIXME we should set ref_idx_l? to 0 if we use that later ... if(IS_16X16(mb_type)){ - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { unsigned int val; if(IS_DIR(mb_type, 0, list)){ - int rc = h->ref_count[list] << MB_MBAFF(h); + int rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc == 1) { val= 0; } else if (rc == 2) { - val= get_bits1(&h->gb)^1; + val= get_bits1(&sl->gb)^1; }else{ - val= get_ue_golomb_31(&h->gb); + val= get_ue_golomb_31(&sl->gb); if (val >= rc) { av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); return -1; } } - fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, val, 1); + fill_rectangle(&sl->ref_cache[list][ scan8[0] ], 4, 4, 8, val, 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { if(IS_DIR(mb_type, 0, list)){ - pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mx, &my); - mx += get_se_golomb(&h->gb); - my += get_se_golomb(&h->gb); - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + pred_motion(h, sl, 0, 4, list, sl->ref_cache[list][ scan8[0] ], &mx, &my); + mx += get_se_golomb(&sl->gb); + my += get_se_golomb(&sl->gb); + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); - fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); + fill_rectangle(sl->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); } } } else if(IS_16X8(mb_type)){ - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ unsigned int val; if(IS_DIR(mb_type, i, list)){ - int rc = h->ref_count[list] << MB_MBAFF(h); + int rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc == 1) { val= 0; } else if (rc == 2) { - val= get_bits1(&h->gb)^1; + val= get_bits1(&sl->gb)^1; }else{ - val= get_ue_golomb_31(&h->gb); + val= get_ue_golomb_31(&sl->gb); if (val >= rc) { av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); return -1; @@ -984,37 +994,37 @@ decode_intra_mb: } }else val= LIST_NOT_USED&0xFF; - fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1); + fill_rectangle(&sl->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ unsigned int val; if(IS_DIR(mb_type, i, list)){ - pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mx, &my); - mx += get_se_golomb(&h->gb); - my += get_se_golomb(&h->gb); - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + pred_16x8_motion(h, sl, 8*i, list, sl->ref_cache[list][scan8[0] + 16*i], &mx, &my); + mx += get_se_golomb(&sl->gb); + my += get_se_golomb(&sl->gb); + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); val= pack16to32(mx,my); }else val=0; - fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 4); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 4); } } }else{ assert(IS_8X16(mb_type)); - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ unsigned int val; if(IS_DIR(mb_type, i, list)){ //FIXME optimize - int rc = h->ref_count[list] << MB_MBAFF(h); + int rc = sl->ref_count[list] << MB_MBAFF(sl); if (rc == 1) { val= 0; } else if (rc == 2) { - val= get_bits1(&h->gb)^1; + val= get_bits1(&sl->gb)^1; }else{ - val= get_ue_golomb_31(&h->gb); + val= get_ue_golomb_31(&sl->gb); if (val >= rc) { av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); return -1; @@ -1022,43 +1032,45 @@ decode_intra_mb: } }else val= LIST_NOT_USED&0xFF; - fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1); + fill_rectangle(&sl->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1); } } - for(list=0; listlist_count; list++){ + for (list = 0; list < sl->list_count; list++) { for(i=0; i<2; i++){ unsigned int val; if(IS_DIR(mb_type, i, list)){ - pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); - mx += get_se_golomb(&h->gb); - my += get_se_golomb(&h->gb); - tprintf(h->avctx, "final mv:%d %d\n", mx, my); + pred_8x16_motion(h, sl, i*4, list, sl->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); + mx += get_se_golomb(&sl->gb); + my += get_se_golomb(&sl->gb); + ff_tlog(h->avctx, "final mv:%d %d\n", mx, my); val= pack16to32(mx,my); }else val=0; - fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 4); + fill_rectangle(sl->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 4); } } } } if(IS_INTER(mb_type)) - write_back_motion(h, mb_type); + write_back_motion(h, sl, mb_type); if(!IS_INTRA16x16(mb_type)){ - cbp= get_ue_golomb(&h->gb); + cbp= get_ue_golomb(&sl->gb); if(decode_chroma){ if(cbp > 47){ - av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, h->mb_x, h->mb_y); + av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, sl->mb_x, sl->mb_y); return -1; } - if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp[cbp]; - else cbp= golomb_to_inter_cbp [cbp]; + if (IS_INTRA4x4(mb_type)) + cbp = ff_h264_golomb_to_intra4x4_cbp[cbp]; + else + cbp = ff_h264_golomb_to_inter_cbp[cbp]; }else{ if(cbp > 15){ - av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, h->mb_x, h->mb_y); + av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, sl->mb_x, sl->mb_y); return -1; } if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp_gray[cbp]; @@ -1067,9 +1079,9 @@ decode_intra_mb: } if(dct8x8_allowed && (cbp&15) && !IS_INTRA(mb_type)){ - mb_type |= MB_TYPE_8x8DCT*get_bits1(&h->gb); + mb_type |= MB_TYPE_8x8DCT*get_bits1(&sl->gb); } - h->cbp= + sl->cbp= h->cbp_table[mb_xy]= cbp; h->cur_pic.mb_type[mb_xy] = mb_type; @@ -1077,50 +1089,50 @@ decode_intra_mb: int i4x4, i8x8, chroma_idx; int dquant; int ret; - GetBitContext *gb= IS_INTRA(mb_type) ? h->intra_gb_ptr : h->inter_gb_ptr; + GetBitContext *gb = &sl->gb; const uint8_t *scan, *scan8x8; - const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8); + const int max_qp = 51 + 6 * (h->ps.sps->bit_depth_luma - 8); if(IS_INTERLACED(mb_type)){ - scan8x8= h->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; - scan= h->qscale ? h->field_scan : h->field_scan_q0; + scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; + scan = sl->qscale ? h->field_scan : h->field_scan_q0; }else{ - scan8x8= h->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; - scan= h->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + scan8x8 = sl->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; + scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; } - dquant= get_se_golomb(&h->gb); + dquant= get_se_golomb(&sl->gb); - h->qscale += dquant; + sl->qscale += dquant; - if(((unsigned)h->qscale) > max_qp){ - if(h->qscale<0) h->qscale+= max_qp+1; - else h->qscale-= max_qp+1; - if(((unsigned)h->qscale) > max_qp){ - av_log(h->avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, h->mb_x, h->mb_y); + if (((unsigned)sl->qscale) > max_qp){ + if (sl->qscale < 0) sl->qscale += max_qp + 1; + else sl->qscale -= max_qp+1; + if (((unsigned)sl->qscale) > max_qp){ + av_log(h->avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, sl->mb_x, sl->mb_y); return -1; } } - h->chroma_qp[0]= get_chroma_qp(h, 0, h->qscale); - h->chroma_qp[1]= get_chroma_qp(h, 1, h->qscale); + sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, sl->qscale); + sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, sl->qscale); - if( (ret = decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 0)) < 0 ){ + if ((ret = decode_luma_residual(h, sl, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 0)) < 0 ) { return -1; } h->cbp_table[mb_xy] |= ret << 12; if (CHROMA444(h)) { - if( decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 1) < 0 ){ + if (decode_luma_residual(h, sl, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 1) < 0 ) { return -1; } - if( decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 2) < 0 ){ + if (decode_luma_residual(h, sl, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 2) < 0 ) { return -1; } } else if (CHROMA422(h)) { if(cbp&0x30){ for(chroma_idx=0; chroma_idx<2; chroma_idx++) - if (decode_residual(h, gb, h->mb + ((256 + 16*16*chroma_idx) << pixel_shift), - CHROMA_DC_BLOCK_INDEX+chroma_idx, chroma422_dc_scan, + if (decode_residual(h, sl, gb, sl->mb + ((256 + 16*16*chroma_idx) << pixel_shift), + CHROMA_DC_BLOCK_INDEX + chroma_idx, ff_h264_chroma422_dc_scan, NULL, 8) < 0) { return -1; } @@ -1128,51 +1140,52 @@ decode_intra_mb: if(cbp&0x20){ for(chroma_idx=0; chroma_idx<2; chroma_idx++){ - const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]]; - int16_t *mb = h->mb + (16*(16 + 16*chroma_idx) << pixel_shift); + const uint32_t *qmul = h->ps.pps->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[chroma_idx]]; + int16_t *mb = sl->mb + (16*(16 + 16*chroma_idx) << pixel_shift); for (i8x8 = 0; i8x8 < 2; i8x8++) { for (i4x4 = 0; i4x4 < 4; i4x4++) { const int index = 16 + 16*chroma_idx + 8*i8x8 + i4x4; - if (decode_residual(h, gb, mb, index, scan + 1, qmul, 15) < 0) + if (decode_residual(h, sl, gb, mb, index, scan + 1, qmul, 15) < 0) return -1; mb += 16 << pixel_shift; } } } }else{ - fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); } } else /* yuv420 */ { if(cbp&0x30){ for(chroma_idx=0; chroma_idx<2; chroma_idx++) - if( decode_residual(h, gb, h->mb + ((256 + 16*16*chroma_idx) << pixel_shift), CHROMA_DC_BLOCK_INDEX+chroma_idx, chroma_dc_scan, NULL, 4) < 0){ + if (decode_residual(h, sl, gb, sl->mb + ((256 + 16 * 16 * chroma_idx) << pixel_shift), + CHROMA_DC_BLOCK_INDEX + chroma_idx, ff_h264_chroma_dc_scan, NULL, 4) < 0) { return -1; } } if(cbp&0x20){ for(chroma_idx=0; chroma_idx<2; chroma_idx++){ - const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]]; + const uint32_t *qmul = h->ps.pps->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[chroma_idx]]; for(i4x4=0; i4x4<4; i4x4++){ const int index= 16 + 16*chroma_idx + i4x4; - if( decode_residual(h, gb, h->mb + (16*index << pixel_shift), index, scan + 1, qmul, 15) < 0){ + if( decode_residual(h, sl, gb, sl->mb + (16*index << pixel_shift), index, scan + 1, qmul, 15) < 0){ return -1; } } } }else{ - fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); } } }else{ - fill_rectangle(&h->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); - fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); } - h->cur_pic.qscale_table[mb_xy] = h->qscale; - write_back_non_zero_count(h); + h->cur_pic.qscale_table[mb_xy] = sl->qscale; + write_back_non_zero_count(h, sl); return 0; } diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index f983898..7ec49b6 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -21,59 +21,63 @@ /** * @file - * H.264 / AVC / MPEG4 part10 direct mb/block decoding. + * H.264 / AVC / MPEG-4 part10 direct mb/block decoding. * @author Michael Niedermayer */ #include "internal.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" +#include "h264_ps.h" #include "mpegutils.h" #include "rectangle.h" #include "thread.h" #include -static int get_scale_factor(H264Context *const h, int poc, int poc1, int i) +static int get_scale_factor(H264SliceContext *sl, + int poc, int poc1, int i) { - int poc0 = h->ref_list[0][i].poc; - int td = av_clip(poc1 - poc0, -128, 127); - if (td == 0 || h->ref_list[0][i].long_ref) { + int poc0 = sl->ref_list[0][i].poc; + int td = av_clip_int8(poc1 - poc0); + if (td == 0 || sl->ref_list[0][i].parent->long_ref) { return 256; } else { - int tb = av_clip(poc - poc0, -128, 127); + int tb = av_clip_int8(poc - poc0); int tx = (16384 + (FFABS(td) >> 1)) / td; - return av_clip((tb * tx + 32) >> 6, -1024, 1023); + return av_clip_intp2((tb * tx + 32) >> 6, 10); } } -void ff_h264_direct_dist_scale_factor(H264Context *const h) +void ff_h264_direct_dist_scale_factor(const H264Context *const h, + H264SliceContext *sl) { const int poc = FIELD_PICTURE(h) ? h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD] : h->cur_pic_ptr->poc; - const int poc1 = h->ref_list[1][0].poc; + const int poc1 = sl->ref_list[1][0].poc; int i, field; if (FRAME_MBAFF(h)) for (field = 0; field < 2; field++) { const int poc = h->cur_pic_ptr->field_poc[field]; - const int poc1 = h->ref_list[1][0].field_poc[field]; - for (i = 0; i < 2 * h->ref_count[0]; i++) - h->dist_scale_factor_field[field][i ^ field] = - get_scale_factor(h, poc, poc1, i + 16); + const int poc1 = sl->ref_list[1][0].parent->field_poc[field]; + for (i = 0; i < 2 * sl->ref_count[0]; i++) + sl->dist_scale_factor_field[field][i ^ field] = + get_scale_factor(sl, poc, poc1, i + 16); } - for (i = 0; i < h->ref_count[0]; i++) - h->dist_scale_factor[i] = get_scale_factor(h, poc, poc1, i); + for (i = 0; i < sl->ref_count[0]; i++) + sl->dist_scale_factor[i] = get_scale_factor(sl, poc, poc1, i); } -static void fill_colmap(H264Context *h, int map[2][16 + 32], int list, +static void fill_colmap(const H264Context *h, H264SliceContext *sl, + int map[2][16 + 32], int list, int field, int colfield, int mbafi) { - H264Picture *const ref1 = &h->ref_list[1][0]; + H264Picture *const ref1 = sl->ref_list[1][0].parent; int j, old_ref, rfield; int start = mbafi ? 16 : 0; - int end = mbafi ? 16 + 2 * h->ref_count[0] : h->ref_count[0]; + int end = mbafi ? 16 + 2 * sl->ref_count[0] : sl->ref_count[0]; int interl = mbafi || h->picture_structure != PICT_FRAME; /* bogus; fills in for missing frames */ @@ -90,8 +94,8 @@ static void fill_colmap(H264Context *h, int map[2][16 + 32], int list, poc = (poc & ~3) + rfield + 1; for (j = start; j < end; j++) { - if (4 * h->ref_list[0][j].frame_num + - (h->ref_list[0][j].reference & 3) == poc) { + if (4 * sl->ref_list[0][j].parent->frame_num + + (sl->ref_list[0][j].reference & 3) == poc) { int cur_ref = mbafi ? (j - 16) ^ field : j; if (ref1->mbaff) map[list][2 * old_ref + (rfield ^ field) + 16] = cur_ref; @@ -104,19 +108,19 @@ static void fill_colmap(H264Context *h, int map[2][16 + 32], int list, } } -void ff_h264_direct_ref_list_init(H264Context *const h) +void ff_h264_direct_ref_list_init(const H264Context *const h, H264SliceContext *sl) { - H264Picture *const ref1 = &h->ref_list[1][0]; + H264Ref *const ref1 = &sl->ref_list[1][0]; H264Picture *const cur = h->cur_pic_ptr; int list, j, field; int sidx = (h->picture_structure & 1) ^ 1; int ref1sidx = (ref1->reference & 1) ^ 1; - for (list = 0; list < 2; list++) { - cur->ref_count[sidx][list] = h->ref_count[list]; - for (j = 0; j < h->ref_count[list]; j++) - cur->ref_poc[sidx][list][j] = 4 * h->ref_list[list][j].frame_num + - (h->ref_list[list][j].reference & 3); + for (list = 0; list < sl->list_count; list++) { + cur->ref_count[sidx][list] = sl->ref_count[list]; + for (j = 0; j < sl->ref_count[list]; j++) + cur->ref_poc[sidx][list][j] = 4 * sl->ref_list[list][j].parent->frame_num + + (sl->ref_list[list][j].reference & 3); } if (h->picture_structure == PICT_FRAME) { @@ -126,37 +130,41 @@ void ff_h264_direct_ref_list_init(H264Context *const h) cur->mbaff = FRAME_MBAFF(h); - h->col_fieldoff = 0; + sl->col_fieldoff = 0; + + if (sl->list_count != 2 || !sl->ref_count[1]) + return; + if (h->picture_structure == PICT_FRAME) { int cur_poc = h->cur_pic_ptr->poc; - int *col_poc = h->ref_list[1]->field_poc; - h->col_parity = (FFABS(col_poc[0] - cur_poc) >= - FFABS(col_poc[1] - cur_poc)); + int *col_poc = sl->ref_list[1][0].parent->field_poc; + sl->col_parity = (FFABS(col_poc[0] - cur_poc) >= + FFABS(col_poc[1] - cur_poc)); ref1sidx = - sidx = h->col_parity; + sidx = sl->col_parity; // FL -> FL & differ parity - } else if (!(h->picture_structure & h->ref_list[1][0].reference) && - !h->ref_list[1][0].mbaff) { - h->col_fieldoff = 2 * h->ref_list[1][0].reference - 3; + } else if (!(h->picture_structure & sl->ref_list[1][0].reference) && + !sl->ref_list[1][0].parent->mbaff) { + sl->col_fieldoff = 2 * sl->ref_list[1][0].reference - 3; } - if (h->slice_type_nos != AV_PICTURE_TYPE_B || h->direct_spatial_mv_pred) + if (sl->slice_type_nos != AV_PICTURE_TYPE_B || sl->direct_spatial_mv_pred) return; for (list = 0; list < 2; list++) { - fill_colmap(h, h->map_col_to_list0, list, sidx, ref1sidx, 0); + fill_colmap(h, sl, sl->map_col_to_list0, list, sidx, ref1sidx, 0); if (FRAME_MBAFF(h)) for (field = 0; field < 2; field++) - fill_colmap(h, h->map_col_to_list0_field[field], list, field, + fill_colmap(h, sl, sl->map_col_to_list0_field[field], list, field, field, 1); } } -static void await_reference_mb_row(H264Context *const h, H264Picture *ref, +static void await_reference_mb_row(const H264Context *const h, H264Ref *ref, int mb_y) { int ref_field = ref->reference - 1; - int ref_field_picture = ref->field_picture; + int ref_field_picture = ref->parent->field_picture; int ref_height = 16 * h->mb_height >> ref_field_picture; if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_FRAME)) @@ -165,17 +173,18 @@ static void await_reference_mb_row(H264Context *const h, H264Picture *ref, /* FIXME: It can be safe to access mb stuff * even if pixels aren't deblocked yet. */ - ff_thread_await_progress(&ref->tf, + ff_thread_await_progress(&ref->parent->tf, FFMIN(16 * mb_y >> ref_field_picture, ref_height - 1), ref_field_picture && ref_field); } -static void pred_spatial_direct_motion(H264Context *const h, int *mb_type) +static void pred_spatial_direct_motion(const H264Context *const h, H264SliceContext *sl, + int *mb_type) { int b8_stride = 2; int b4_stride = h->b_stride; - int mb_xy = h->mb_xy, mb_y = h->mb_y; + int mb_xy = sl->mb_xy, mb_y = sl->mb_y; int mb_type_col[2]; const int16_t (*l1mv0)[2], (*l1mv1)[2]; const int8_t *l1ref0, *l1ref1; @@ -186,23 +195,23 @@ static void pred_spatial_direct_motion(H264Context *const h, int *mb_type) int mv[2]; int list; - assert(h->ref_list[1][0].reference & 3); + assert(sl->ref_list[1][0].reference & 3); - await_reference_mb_row(h, &h->ref_list[1][0], - h->mb_y + !!IS_INTERLACED(*mb_type)); + await_reference_mb_row(h, &sl->ref_list[1][0], + sl->mb_y + !!IS_INTERLACED(*mb_type)); #define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16 | MB_TYPE_INTRA4x4 | \ MB_TYPE_INTRA16x16 | MB_TYPE_INTRA_PCM) /* ref = min(neighbors) */ for (list = 0; list < 2; list++) { - int left_ref = h->ref_cache[list][scan8[0] - 1]; - int top_ref = h->ref_cache[list][scan8[0] - 8]; - int refc = h->ref_cache[list][scan8[0] - 8 + 4]; - const int16_t *C = h->mv_cache[list][scan8[0] - 8 + 4]; + int left_ref = sl->ref_cache[list][scan8[0] - 1]; + int top_ref = sl->ref_cache[list][scan8[0] - 8]; + int refc = sl->ref_cache[list][scan8[0] - 8 + 4]; + const int16_t *C = sl->mv_cache[list][scan8[0] - 8 + 4]; if (refc == PART_NOT_AVAILABLE) { - refc = h->ref_cache[list][scan8[0] - 8 - 1]; - C = h->mv_cache[list][scan8[0] - 8 - 1]; + refc = sl->ref_cache[list][scan8[0] - 8 - 1]; + C = sl->mv_cache[list][scan8[0] - 8 - 1]; } ref[list] = FFMIN3((unsigned)left_ref, (unsigned)top_ref, @@ -210,8 +219,8 @@ static void pred_spatial_direct_motion(H264Context *const h, int *mb_type) if (ref[list] >= 0) { /* This is just pred_motion() but with the cases removed that * cannot happen for direct blocks. */ - const int16_t *const A = h->mv_cache[list][scan8[0] - 1]; - const int16_t *const B = h->mv_cache[list][scan8[0] - 8]; + const int16_t *const A = sl->mv_cache[list][scan8[0] - 1]; + const int16_t *const B = sl->mv_cache[list][scan8[0] - 8]; int match_count = (left_ref == ref[list]) + (top_ref == ref[list]) + @@ -246,33 +255,33 @@ static void pred_spatial_direct_motion(H264Context *const h, int *mb_type) } if (!(is_b8x8 | mv[0] | mv[1])) { - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); - fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); - fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); - fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4); + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); + fill_rectangle(&sl->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); + fill_rectangle(&sl->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); + fill_rectangle(&sl->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4); *mb_type = (*mb_type & ~(MB_TYPE_8x8 | MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_P1L0 | MB_TYPE_P1L1)) | MB_TYPE_16x16 | MB_TYPE_DIRECT2; return; } - if (IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL - mb_y = (h->mb_y & ~1) + h->col_parity; - mb_xy = h->mb_x + - ((h->mb_y & ~1) + h->col_parity) * h->mb_stride; + mb_y = (sl->mb_y & ~1) + sl->col_parity; + mb_xy = sl->mb_x + + ((sl->mb_y & ~1) + sl->col_parity) * h->mb_stride; b8_stride = 0; } else { - mb_y += h->col_fieldoff; - mb_xy += h->mb_stride * h->col_fieldoff; // non-zero for FL -> FL & differ parity + mb_y += sl->col_fieldoff; + mb_xy += h->mb_stride * sl->col_fieldoff; // non-zero for FL -> FL & differ parity } goto single_col; } else { // AFL/AFR/FR/FL -> AFR/FR if (IS_INTERLACED(*mb_type)) { // AFL /FL -> AFR/FR - mb_y = h->mb_y & ~1; - mb_xy = (h->mb_y & ~1) * h->mb_stride + h->mb_x; - mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; - mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + h->mb_stride]; + mb_y = sl->mb_y & ~1; + mb_xy = (sl->mb_y & ~1) * h->mb_stride + sl->mb_x; + mb_type_col[0] = sl->ref_list[1][0].parent->mb_type[mb_xy]; + mb_type_col[1] = sl->ref_list[1][0].parent->mb_type[mb_xy + h->mb_stride]; b8_stride = 2 + 4 * h->mb_stride; b4_stride *= 6; if (IS_INTERLACED(mb_type_col[0]) != @@ -292,7 +301,7 @@ static void pred_spatial_direct_motion(H264Context *const h, int *mb_type) } else { // AFR/FR -> AFR/FR single_col: mb_type_col[0] = - mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; + mb_type_col[1] = sl->ref_list[1][0].parent->mb_type[mb_xy]; sub_mb_type |= MB_TYPE_16x16 | MB_TYPE_DIRECT2; /* B_SUB_8x8 */ if (!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)) { @@ -302,7 +311,7 @@ single_col: *mb_type |= MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8 | MB_TYPE_8x16)); } else { - if (!h->sps.direct_8x8_inference_flag) { + if (!h->ps.sps->direct_8x8_inference_flag) { /* FIXME: Save sub mb types from previous frames (or derive * from MVs) so we know exactly what block size to use. */ sub_mb_type += (MB_TYPE_8x8 - MB_TYPE_16x16); /* B_SUB_4x4 */ @@ -312,14 +321,14 @@ single_col: } } - await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + await_reference_mb_row(h, &sl->ref_list[1][0], mb_y); - l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy[mb_xy]]; - l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy[mb_xy]]; - l1ref0 = &h->ref_list[1][0].ref_index[0][4 * mb_xy]; - l1ref1 = &h->ref_list[1][0].ref_index[1][4 * mb_xy]; + l1mv0 = &sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]]; + l1mv1 = &sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]]; + l1ref0 = &sl->ref_list[1][0].parent->ref_index[0][4 * mb_xy]; + l1ref1 = &sl->ref_list[1][0].parent->ref_index[1][4 * mb_xy]; if (!b8_stride) { - if (h->mb_y & 1) { + if (sl->mb_y & 1) { l1ref0 += 2; l1ref1 += 2; l1mv0 += 2 * b4_stride; @@ -336,15 +345,15 @@ single_col: int xy4 = x8 * 3 + y8 * b4_stride; int a, b; - if (is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + if (is_b8x8 && !IS_DIRECT(sl->sub_mb_type[i8])) continue; - h->sub_mb_type[i8] = sub_mb_type; + sl->sub_mb_type[i8] = sub_mb_type; - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, + fill_rectangle(&sl->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, + fill_rectangle(&sl->ref_cache[1][scan8[i8 * 4]], 2, 2, 8, (uint8_t)ref[1], 1); - if (!IS_INTRA(mb_type_col[y8]) && !h->ref_list[1][0].long_ref && + if (!IS_INTRA(mb_type_col[y8]) && !sl->ref_list[1][0].parent->long_ref && ((l1ref0[xy8] == 0 && FFABS(l1mv0[xy4][0]) <= 1 && FFABS(l1mv0[xy4][1]) <= 1) || @@ -363,8 +372,8 @@ single_col: a = mv[0]; b = mv[1]; } - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, a, 4); - fill_rectangle(&h->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, b, 4); + fill_rectangle(&sl->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, a, 4); + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, b, 4); } if (!is_b8x8 && !(n & 3)) *mb_type = (*mb_type & ~(MB_TYPE_8x8 | MB_TYPE_16x8 | MB_TYPE_8x16 | @@ -373,16 +382,16 @@ single_col: } else if (IS_16X16(*mb_type)) { int a, b; - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); - fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); - if (!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref && + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); + fill_rectangle(&sl->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); + if (!IS_INTRA(mb_type_col[0]) && !sl->ref_list[1][0].parent->long_ref && ((l1ref0[0] == 0 && FFABS(l1mv0[0][0]) <= 1 && FFABS(l1mv0[0][1]) <= 1) || (l1ref0[0] < 0 && !l1ref1[0] && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1 && - h->x264_build > 33U))) { + h->sei.unregistered.x264_build > 33U))) { a = b = 0; if (ref[0] > 0) a = mv[0]; @@ -392,41 +401,41 @@ single_col: a = mv[0]; b = mv[1]; } - fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, a, 4); - fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, b, 4); + fill_rectangle(&sl->mv_cache[0][scan8[0]], 4, 4, 8, a, 4); + fill_rectangle(&sl->mv_cache[1][scan8[0]], 4, 4, 8, b, 4); } else { int n = 0; for (i8 = 0; i8 < 4; i8++) { const int x8 = i8 & 1; const int y8 = i8 >> 1; - if (is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + if (is_b8x8 && !IS_DIRECT(sl->sub_mb_type[i8])) continue; - h->sub_mb_type[i8] = sub_mb_type; + sl->sub_mb_type[i8] = sub_mb_type; - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, mv[0], 4); - fill_rectangle(&h->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, mv[1], 4); - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, + fill_rectangle(&sl->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, mv[0], 4); + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, mv[1], 4); + fill_rectangle(&sl->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, + fill_rectangle(&sl->ref_cache[1][scan8[i8 * 4]], 2, 2, 8, (uint8_t)ref[1], 1); assert(b8_stride == 2); /* col_zero_flag */ - if (!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref && + if (!IS_INTRA(mb_type_col[0]) && !sl->ref_list[1][0].parent->long_ref && (l1ref0[i8] == 0 || (l1ref0[i8] < 0 && l1ref1[i8] == 0 && - h->x264_build > 33U))) { + h->sei.unregistered.x264_build > 33U))) { const int16_t (*l1mv)[2] = l1ref0[i8] == 0 ? l1mv0 : l1mv1; if (IS_SUB_8X8(sub_mb_type)) { const int16_t *mv_col = l1mv[x8 * 3 + y8 * 3 * b4_stride]; if (FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1) { if (ref[0] == 0) - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, + fill_rectangle(&sl->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, + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 4); n += 4; } @@ -437,14 +446,14 @@ single_col: (y8 * 2 + (i4 >> 1)) * b4_stride]; if (FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1) { if (ref[0] == 0) - AV_ZERO32(h->mv_cache[0][scan8[i8 * 4 + i4]]); + AV_ZERO32(sl->mv_cache[0][scan8[i8 * 4 + i4]]); if (ref[1] == 0) - AV_ZERO32(h->mv_cache[1][scan8[i8 * 4 + i4]]); + AV_ZERO32(sl->mv_cache[1][scan8[i8 * 4 + i4]]); m++; } } if (!(m & 3)) - h->sub_mb_type[i8] += MB_TYPE_16x16 - MB_TYPE_8x8; + sl->sub_mb_type[i8] += MB_TYPE_16x16 - MB_TYPE_8x8; n += m; } } @@ -456,11 +465,12 @@ single_col: } } -static void pred_temp_direct_motion(H264Context *const h, int *mb_type) +static void pred_temp_direct_motion(const H264Context *const h, H264SliceContext *sl, + int *mb_type) { int b8_stride = 2; int b4_stride = h->b_stride; - int mb_xy = h->mb_xy, mb_y = h->mb_y; + int mb_xy = sl->mb_xy, mb_y = sl->mb_y; int mb_type_col[2]; const int16_t (*l1mv0)[2], (*l1mv1)[2]; const int8_t *l1ref0, *l1ref1; @@ -468,28 +478,28 @@ static void pred_temp_direct_motion(H264Context *const h, int *mb_type) unsigned int sub_mb_type; int i8, i4; - assert(h->ref_list[1][0].reference & 3); + assert(sl->ref_list[1][0].reference & 3); - await_reference_mb_row(h, &h->ref_list[1][0], - h->mb_y + !!IS_INTERLACED(*mb_type)); + await_reference_mb_row(h, &sl->ref_list[1][0], + sl->mb_y + !!IS_INTERLACED(*mb_type)); - if (IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL - mb_y = (h->mb_y & ~1) + h->col_parity; - mb_xy = h->mb_x + - ((h->mb_y & ~1) + h->col_parity) * h->mb_stride; + mb_y = (sl->mb_y & ~1) + sl->col_parity; + mb_xy = sl->mb_x + + ((sl->mb_y & ~1) + sl->col_parity) * h->mb_stride; b8_stride = 0; } else { - mb_y += h->col_fieldoff; - mb_xy += h->mb_stride * h->col_fieldoff; // non-zero for FL -> FL & differ parity + mb_y += sl->col_fieldoff; + mb_xy += h->mb_stride * sl->col_fieldoff; // non-zero for FL -> FL & differ parity } goto single_col; } else { // AFL/AFR/FR/FL -> AFR/FR if (IS_INTERLACED(*mb_type)) { // AFL /FL -> AFR/FR - mb_y = h->mb_y & ~1; - mb_xy = h->mb_x + (h->mb_y & ~1) * h->mb_stride; - mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; - mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + h->mb_stride]; + mb_y = sl->mb_y & ~1; + mb_xy = sl->mb_x + (sl->mb_y & ~1) * h->mb_stride; + mb_type_col[0] = sl->ref_list[1][0].parent->mb_type[mb_xy]; + mb_type_col[1] = sl->ref_list[1][0].parent->mb_type[mb_xy + h->mb_stride]; b8_stride = 2 + 4 * h->mb_stride; b4_stride *= 6; if (IS_INTERLACED(mb_type_col[0]) != @@ -512,7 +522,7 @@ static void pred_temp_direct_motion(H264Context *const h, int *mb_type) } else { // AFR/FR -> AFR/FR single_col: mb_type_col[0] = - mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; + mb_type_col[1] = sl->ref_list[1][0].parent->mb_type[mb_xy]; sub_mb_type = MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT2; /* B_SUB_8x8 */ @@ -524,7 +534,7 @@ single_col: *mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8 | MB_TYPE_8x16)); } else { - if (!h->sps.direct_8x8_inference_flag) { + if (!h->ps.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 | @@ -535,14 +545,14 @@ single_col: } } - await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + await_reference_mb_row(h, &sl->ref_list[1][0], mb_y); - l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy[mb_xy]]; - l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy[mb_xy]]; - l1ref0 = &h->ref_list[1][0].ref_index[0][4 * mb_xy]; - l1ref1 = &h->ref_list[1][0].ref_index[1][4 * mb_xy]; + l1mv0 = &sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]]; + l1mv1 = &sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]]; + l1ref0 = &sl->ref_list[1][0].parent->ref_index[0][4 * mb_xy]; + l1ref1 = &sl->ref_list[1][0].parent->ref_index[1][4 * mb_xy]; if (!b8_stride) { - if (h->mb_y & 1) { + if (sl->mb_y & 1) { l1ref0 += 2; l1ref1 += 2; l1mv0 += 2 * b4_stride; @@ -551,21 +561,21 @@ single_col: } { - 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; + const int *map_col_to_list0[2] = { sl->map_col_to_list0[0], + sl->map_col_to_list0[1] }; + const int *dist_scale_factor = sl->dist_scale_factor; int ref_offset; if (FRAME_MBAFF(h) && IS_INTERLACED(*mb_type)) { - map_col_to_list0[0] = h->map_col_to_list0_field[h->mb_y & 1][0]; - map_col_to_list0[1] = h->map_col_to_list0_field[h->mb_y & 1][1]; - dist_scale_factor = h->dist_scale_factor_field[h->mb_y & 1]; + map_col_to_list0[0] = sl->map_col_to_list0_field[sl->mb_y & 1][0]; + map_col_to_list0[1] = sl->map_col_to_list0_field[sl->mb_y & 1][1]; + dist_scale_factor = sl->dist_scale_factor_field[sl->mb_y & 1]; } - ref_offset = (h->ref_list[1][0].mbaff << 4) & (mb_type_col[0] >> 3); + ref_offset = (sl->ref_list[1][0].parent->mbaff << 4) & (mb_type_col[0] >> 3); if (IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])) { int y_shift = 2 * !IS_INTERLACED(*mb_type); - assert(h->sps.direct_8x8_inference_flag); + assert(h->ps.sps->direct_8x8_inference_flag); for (i8 = 0; i8 < 4; i8++) { const int x8 = i8 & 1; @@ -573,15 +583,15 @@ single_col: int ref0, scale; const int16_t (*l1mv)[2] = l1mv0; - if (is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + if (is_b8x8 && !IS_DIRECT(sl->sub_mb_type[i8])) continue; - h->sub_mb_type[i8] = sub_mb_type; + sl->sub_mb_type[i8] = sub_mb_type; - fill_rectangle(&h->ref_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 1); + fill_rectangle(&sl->ref_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 1); if (IS_INTRA(mb_type_col[y8])) { - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 1); - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 4); - fill_rectangle(&h->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 4); + fill_rectangle(&sl->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 1); + fill_rectangle(&sl->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 4); + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 4); continue; } @@ -594,7 +604,7 @@ single_col: l1mv = l1mv1; } scale = dist_scale_factor[ref0]; - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, + fill_rectangle(&sl->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, ref0, 1); { @@ -602,9 +612,9 @@ single_col: 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, + fill_rectangle(&sl->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, + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, pack16to32(mx - mv_col[0], my - my_col), 4); } } @@ -616,7 +626,7 @@ single_col: if (IS_16X16(*mb_type)) { int ref, mv0, mv1; - fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1); if (IS_INTRA(mb_type_col[0])) { ref = mv0 = mv1 = 0; } else { @@ -631,9 +641,9 @@ single_col: mv0 = pack16to32(mv_l0[0], mv_l0[1]); mv1 = pack16to32(mv_l0[0] - mv_col[0], mv_l0[1] - mv_col[1]); } - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); - fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4); - fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4); + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(&sl->mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4); + fill_rectangle(&sl->mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4); } else { for (i8 = 0; i8 < 4; i8++) { const int x8 = i8 & 1; @@ -641,14 +651,14 @@ single_col: int ref0, scale; const int16_t (*l1mv)[2] = l1mv0; - if (is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + if (is_b8x8 && !IS_DIRECT(sl->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); + sl->sub_mb_type[i8] = sub_mb_type; + fill_rectangle(&sl->ref_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 1); if (IS_INTRA(mb_type_col[0])) { - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 1); - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 4); - fill_rectangle(&h->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 4); + fill_rectangle(&sl->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 1); + fill_rectangle(&sl->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, 0, 4); + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, 0, 4); continue; } @@ -662,24 +672,24 @@ single_col: } scale = dist_scale_factor[ref0]; - fill_rectangle(&h->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, + fill_rectangle(&sl->ref_cache[0][scan8[i8 * 4]], 2, 2, 8, ref0, 1); if (IS_SUB_8X8(sub_mb_type)) { const int16_t *mv_col = l1mv[x8 * 3 + y8 * 3 * b4_stride]; int mx = (scale * mv_col[0] + 128) >> 8; int my = (scale * mv_col[1] + 128) >> 8; - fill_rectangle(&h->mv_cache[0][scan8[i8 * 4]], 2, 2, 8, + fill_rectangle(&sl->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, + fill_rectangle(&sl->mv_cache[1][scan8[i8 * 4]], 2, 2, 8, pack16to32(mx - mv_col[0], my - mv_col[1]), 4); } else { for (i4 = 0; i4 < 4; i4++) { const int16_t *mv_col = l1mv[x8 * 2 + (i4 & 1) + (y8 * 2 + (i4 >> 1)) * b4_stride]; - int16_t *mv_l0 = h->mv_cache[0][scan8[i8 * 4 + i4]]; + int16_t *mv_l0 = sl->mv_cache[0][scan8[i8 * 4 + i4]]; mv_l0[0] = (scale * mv_col[0] + 128) >> 8; mv_l0[1] = (scale * mv_col[1] + 128) >> 8; - AV_WN32A(h->mv_cache[1][scan8[i8 * 4 + i4]], + AV_WN32A(sl->mv_cache[1][scan8[i8 * 4 + i4]], pack16to32(mv_l0[0] - mv_col[0], mv_l0[1] - mv_col[1])); } @@ -689,10 +699,11 @@ single_col: } } -void ff_h264_pred_direct_motion(H264Context *const h, int *mb_type) +void ff_h264_pred_direct_motion(const H264Context *const h, H264SliceContext *sl, + int *mb_type) { - if (h->direct_spatial_mv_pred) - pred_spatial_direct_motion(h, mb_type); + if (sl->direct_spatial_mv_pred) + pred_spatial_direct_motion(h, sl, mb_type); else - pred_temp_direct_motion(h, mb_type); + pred_temp_direct_motion(h, sl, mb_type); } diff --git a/libavcodec/h264_loopfilter.c b/libavcodec/h264_loopfilter.c index 717c225..5004074 100644 --- a/libavcodec/h264_loopfilter.c +++ b/libavcodec/h264_loopfilter.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 loop filter. + * H.264 / AVC / MPEG-4 part10 loop filter. * @author Michael Niedermayer */ @@ -29,7 +29,8 @@ #include "libavutil/intreadwrite.h" #include "internal.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" +#include "h264_ps.h" #include "mathops.h" #include "mpegutils.h" #include "rectangle.h" @@ -103,7 +104,7 @@ static const uint8_t tc0_table[52*3][4] = { static av_always_inline void filter_mb_edgev(uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, int a, int b, - H264Context *h, int intra) + const H264Context *h, int intra) { const unsigned int index_a = qp + a; const int alpha = alpha_table[index_a]; @@ -125,7 +126,7 @@ static av_always_inline void filter_mb_edgev(uint8_t *pix, int stride, static av_always_inline void filter_mb_edgecv(uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, int a, int b, - H264Context *h, int intra) + const H264Context *h, int intra) { const unsigned int index_a = qp + a; const int alpha = alpha_table[index_a]; @@ -144,7 +145,7 @@ static av_always_inline void filter_mb_edgecv(uint8_t *pix, int stride, } } -static av_always_inline void filter_mb_mbaff_edgev(H264Context *h, uint8_t *pix, +static av_always_inline void filter_mb_mbaff_edgev(const H264Context *h, uint8_t *pix, int stride, const int16_t bS[7], int bsi, int qp, int a, int b, @@ -167,7 +168,7 @@ static av_always_inline void filter_mb_mbaff_edgev(H264Context *h, uint8_t *pix, } } -static av_always_inline void filter_mb_mbaff_edgecv(H264Context *h, +static av_always_inline void filter_mb_mbaff_edgecv(const H264Context *h, uint8_t *pix, int stride, const int16_t bS[7], int bsi, int qp, int a, @@ -193,7 +194,7 @@ static av_always_inline void filter_mb_mbaff_edgecv(H264Context *h, static av_always_inline void filter_mb_edgeh(uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, int a, int b, - H264Context *h, int intra) + const H264Context *h, int intra) { const unsigned int index_a = qp + a; const int alpha = alpha_table[index_a]; @@ -215,7 +216,7 @@ static av_always_inline void filter_mb_edgeh(uint8_t *pix, int stride, static av_always_inline void filter_mb_edgech(uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, int a, int b, - H264Context *h, int intra) + const H264Context *h, int intra) { const unsigned int index_a = qp + a; const int alpha = alpha_table[index_a]; @@ -234,7 +235,8 @@ static av_always_inline void filter_mb_edgech(uint8_t *pix, int stride, } } -static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, +static av_always_inline void h264_filter_mb_fast_internal(const H264Context *h, + H264SliceContext *sl, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, @@ -243,25 +245,25 @@ static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, unsigned int uvlinesize, int pixel_shift) { - int chroma = !(CONFIG_GRAY && (h->flags&CODEC_FLAG_GRAY)); + int chroma = !(CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY)); int chroma444 = CHROMA444(h); int chroma422 = CHROMA422(h); - int mb_xy = h->mb_xy; - int left_type= h->left_type[LTOP]; - int top_type= h->top_type; + int mb_xy = sl->mb_xy; + int left_type = sl->left_type[LTOP]; + int top_type = sl->top_type; - int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8); - int a = 52 + h->slice_alpha_c0_offset - qp_bd_offset; - int b = 52 + h->slice_beta_offset - qp_bd_offset; + int qp_bd_offset = 6 * (h->ps.sps->bit_depth_luma - 8); + int a = 52 + sl->slice_alpha_c0_offset - qp_bd_offset; + int b = 52 + sl->slice_beta_offset - qp_bd_offset; int mb_type = h->cur_pic.mb_type[mb_xy]; int qp = h->cur_pic.qscale_table[mb_xy]; int qp0 = h->cur_pic.qscale_table[mb_xy - 1]; - int qp1 = h->cur_pic.qscale_table[h->top_mb_xy]; - int qpc = get_chroma_qp( h, 0, qp ); - int qpc0 = get_chroma_qp( h, 0, qp0 ); - int qpc1 = get_chroma_qp( h, 0, qp1 ); + int qp1 = h->cur_pic.qscale_table[sl->top_mb_xy]; + int qpc = get_chroma_qp(h->ps.pps, 0, qp); + int qpc0 = get_chroma_qp(h->ps.pps, 0, qp0); + int qpc1 = get_chroma_qp(h->ps.pps, 0, qp1); qp0 = (qp + qp0 + 1) >> 1; qp1 = (qp + qp1 + 1) >> 1; qpc0 = (qpc + qpc0 + 1) >> 1; @@ -359,7 +361,7 @@ static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, } else { LOCAL_ALIGNED_8(int16_t, bS, [2], [4][4]); int edges; - if( IS_8x8DCT(mb_type) && (h->cbp&7) == 7 && !chroma444 ) { + if( IS_8x8DCT(mb_type) && (sl->cbp&7) == 7 && !chroma444 ) { edges = 4; AV_WN64A(bS[0][0], 0x0002000200020002ULL); AV_WN64A(bS[0][2], 0x0002000200020002ULL); @@ -369,9 +371,9 @@ static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, int mask_edge1 = (3*(((5*mb_type)>>5)&1)) | (mb_type>>4); //(mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : (mb_type & MB_TYPE_16x8) ? 1 : 0; int mask_edge0 = 3*((mask_edge1>>1) & ((5*left_type)>>5)&1); // (mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) && (h->left_type[LTOP] & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : 0; int step = 1+(mb_type>>24); //IS_8x8DCT(mb_type) ? 2 : 1; - edges = 4 - 3*((mb_type>>3) & !(h->cbp & 15)); //(mb_type & MB_TYPE_16x16) && !(h->cbp & 15) ? 1 : 4; - h->h264dsp.h264_loop_filter_strength( bS, h->non_zero_count_cache, h->ref_cache, h->mv_cache, - h->list_count==2, edges, step, mask_edge0, mask_edge1, FIELD_PICTURE(h)); + edges = 4 - 3*((mb_type>>3) & !(sl->cbp & 15)); //(mb_type & MB_TYPE_16x16) && !(h->cbp & 15) ? 1 : 4; + h->h264dsp.h264_loop_filter_strength(bS, sl->non_zero_count_cache, sl->ref_cache, sl->mv_cache, + sl->list_count==2, edges, step, mask_edge0, mask_edge1, FIELD_PICTURE(h)); } if( IS_INTRA(left_type) ) AV_WN64A(bS[0][0], 0x0004000400040004ULL); @@ -415,66 +417,78 @@ static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, } } -void ff_h264_filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { +void ff_h264_filter_mb_fast(const H264Context *h, H264SliceContext *sl, + int mb_x, int mb_y, uint8_t *img_y, + uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize) +{ assert(!FRAME_MBAFF(h)); - if(!h->h264dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff) { - ff_h264_filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize); + if(!h->h264dsp.h264_loop_filter_strength || h->ps.pps->chroma_qp_diff) { + ff_h264_filter_mb(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize); return; } #if CONFIG_SMALL - h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, h->pixel_shift); + h264_filter_mb_fast_internal(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, h->pixel_shift); #else if(h->pixel_shift){ - h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 1); + h264_filter_mb_fast_internal(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 1); }else{ - h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 0); + h264_filter_mb_fast_internal(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 0); } #endif } -static int check_mv(H264Context *h, long b_idx, long bn_idx, int mvy_limit){ +static int check_mv(H264SliceContext *sl, long b_idx, long bn_idx, int mvy_limit) +{ int v; - v= h->ref_cache[0][b_idx] != h->ref_cache[0][bn_idx]; - if(!v && h->ref_cache[0][b_idx]!=-1) - v= h->mv_cache[0][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | - FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; + v = sl->ref_cache[0][b_idx] != sl->ref_cache[0][bn_idx]; + if (!v && sl->ref_cache[0][b_idx] != -1) + v = sl->mv_cache[0][b_idx][0] - sl->mv_cache[0][bn_idx][0] + 3 >= 7U | + FFABS(sl->mv_cache[0][b_idx][1] - sl->mv_cache[0][bn_idx][1]) >= mvy_limit; - if(h->list_count==2){ + if (sl->list_count == 2) { if(!v) - v = h->ref_cache[1][b_idx] != h->ref_cache[1][bn_idx] | - h->mv_cache[1][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | - FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit; + v = sl->ref_cache[1][b_idx] != sl->ref_cache[1][bn_idx] | + sl->mv_cache[1][b_idx][0] - sl->mv_cache[1][bn_idx][0] + 3 >= 7U | + FFABS(sl->mv_cache[1][b_idx][1] - sl->mv_cache[1][bn_idx][1]) >= mvy_limit; if(v){ - if(h->ref_cache[0][b_idx] != h->ref_cache[1][bn_idx] | - h->ref_cache[1][b_idx] != h->ref_cache[0][bn_idx]) + if (sl->ref_cache[0][b_idx] != sl->ref_cache[1][bn_idx] | + sl->ref_cache[1][b_idx] != sl->ref_cache[0][bn_idx]) return 1; return - h->mv_cache[0][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | - FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit | - h->mv_cache[1][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | - FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; + sl->mv_cache[0][b_idx][0] - sl->mv_cache[1][bn_idx][0] + 3 >= 7U | + FFABS(sl->mv_cache[0][b_idx][1] - sl->mv_cache[1][bn_idx][1]) >= mvy_limit | + sl->mv_cache[1][b_idx][0] - sl->mv_cache[0][bn_idx][0] + 3 >= 7U | + FFABS(sl->mv_cache[1][b_idx][1] - sl->mv_cache[0][bn_idx][1]) >= mvy_limit; } } return v; } -static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize, int mb_xy, int mb_type, int mvy_limit, int first_vertical_edge_done, int a, int b, int chroma, int dir) { +static av_always_inline void filter_mb_dir(const H264Context *h, H264SliceContext *sl, + int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize, + int mb_xy, int mb_type, int mvy_limit, + int first_vertical_edge_done, int a, int b, + int chroma, int dir) +{ int edge; int chroma_qp_avg[2]; int chroma444 = CHROMA444(h); int chroma422 = CHROMA422(h); - const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy; - const int mbm_type = dir == 0 ? h->left_type[LTOP] : h->top_type; + const int mbm_xy = dir == 0 ? mb_xy -1 : sl->top_mb_xy; + const int mbm_type = dir == 0 ? sl->left_type[LTOP] : sl->top_type; // how often to recheck mv-based bS when iterating between edges static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1}, {0,3,1,1,3,3,3,3}}; const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7]; - const int edges = mask_edge== 3 && !(h->cbp&15) ? 1 : 4; + const int edges = mask_edge== 3 && !(sl->cbp&15) ? 1 : 4; // how often to recheck mv-based bS when iterating along each edge const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)); @@ -500,26 +514,26 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u AV_WN64A(bS, 0x0003000300030003ULL); } else { if (!CABAC(h) && IS_8x8DCT(h->cur_pic.mb_type[mbn_xy])) { - bS[0]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+0]); - bS[1]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+1]); - bS[2]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+2]); - bS[3]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+3]); + bS[0]= 1+((h->cbp_table[mbn_xy] & 0x4000) || sl->non_zero_count_cache[scan8[0]+0]); + bS[1]= 1+((h->cbp_table[mbn_xy] & 0x4000) || sl->non_zero_count_cache[scan8[0]+1]); + bS[2]= 1+((h->cbp_table[mbn_xy] & 0x8000) || sl->non_zero_count_cache[scan8[0]+2]); + bS[3]= 1+((h->cbp_table[mbn_xy] & 0x8000) || sl->non_zero_count_cache[scan8[0]+3]); }else{ const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy] + 3*4; int i; for( i = 0; i < 4; i++ ) { - bS[i] = 1 + !!(h->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]); + bS[i] = 1 + !!(sl->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]); } } } // Do not use s->qscale as luma quantizer because it has not the same // value in IPCM macroblocks. qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbn_xy] + 1) >> 1; - tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize); - { int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } + ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize); + { int i; for (i = 0; i < 4; i++) ff_tlog(h->avctx, " bS[%d]:%d", i, bS[i]); ff_tlog(h->avctx, "\n"); } filter_mb_edgeh( &img_y[j*linesize], tmp_linesize, bS, qp, a, b, h, 0 ); - chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; - chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; + chroma_qp_avg[0] = (sl->chroma_qp[0] + get_chroma_qp(h->ps.pps, 0, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; + chroma_qp_avg[1] = (sl->chroma_qp[1] + get_chroma_qp(h->ps.pps, 1, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; if (chroma) { if (chroma444) { filter_mb_edgeh (&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], a, b, h, 0); @@ -552,7 +566,7 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u int b_idx= 8 + 4; int bn_idx= b_idx - (dir ? 8:1); - bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, 8 + 4, bn_idx, mvy_limit); + bS[0] = bS[1] = bS[2] = bS[3] = check_mv(sl, 8 + 4, bn_idx, mvy_limit); mv_done = 1; } else @@ -564,13 +578,13 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u int b_idx= 8 + 4 + x + 8*y; int bn_idx= b_idx - (dir ? 8:1); - if( h->non_zero_count_cache[b_idx] | - h->non_zero_count_cache[bn_idx] ) { + if (sl->non_zero_count_cache[b_idx] | + sl->non_zero_count_cache[bn_idx]) { bS[i] = 2; } else if(!mv_done) { - bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); + bS[i] = check_mv(sl, b_idx, bn_idx, mvy_limit); } } } @@ -580,9 +594,9 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u // value in IPCM macroblocks. if(bS[0]+bS[1]+bS[2]+bS[3]){ qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbm_xy] + 1) >> 1; - tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); - chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; - chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; + ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); + chroma_qp_avg[0] = (sl->chroma_qp[0] + get_chroma_qp(h->ps.pps, 0, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; + chroma_qp_avg[1] = (sl->chroma_qp[1] + get_chroma_qp(h->ps.pps, 1, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; if( dir == 0 ) { filter_mb_edgev( &img_y[0], linesize, bS, qp, a, b, h, 1 ); if (chroma) { @@ -633,7 +647,7 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u int b_idx= 8 + 4 + edge * (dir ? 8:1); int bn_idx= b_idx - (dir ? 8:1); - bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, b_idx, bn_idx, mvy_limit); + bS[0] = bS[1] = bS[2] = bS[3] = check_mv(sl, b_idx, bn_idx, mvy_limit); mv_done = 1; } else @@ -645,13 +659,13 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u int b_idx= 8 + 4 + x + 8*y; int bn_idx= b_idx - (dir ? 8:1); - if( h->non_zero_count_cache[b_idx] | - h->non_zero_count_cache[bn_idx] ) { + if (sl->non_zero_count_cache[b_idx] | + sl->non_zero_count_cache[bn_idx]) { bS[i] = 2; } else if(!mv_done) { - bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); + bS[i] = check_mv(sl, b_idx, bn_idx, mvy_limit); } } @@ -663,16 +677,16 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u // Do not use s->qscale as luma quantizer because it has not the same // value in IPCM macroblocks. qp = h->cur_pic.qscale_table[mb_xy]; - tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); + ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); if( dir == 0 ) { filter_mb_edgev( &img_y[4*edge << h->pixel_shift], linesize, bS, qp, a, b, h, 0 ); if (chroma) { if (chroma444) { - filter_mb_edgev ( &img_cb[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); - filter_mb_edgev ( &img_cr[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + filter_mb_edgev ( &img_cb[4*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0); + filter_mb_edgev ( &img_cr[4*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0); } else if( (edge&1) == 0 ) { - filter_mb_edgecv( &img_cb[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); - filter_mb_edgecv( &img_cr[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + filter_mb_edgecv( &img_cb[2*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0); + filter_mb_edgecv( &img_cr[2*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0); } } } else { @@ -680,18 +694,18 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u if (deblock_edge) filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0); if (chroma) { - filter_mb_edgech(&img_cb[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); - filter_mb_edgech(&img_cr[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + filter_mb_edgech(&img_cb[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0); + filter_mb_edgech(&img_cr[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0); } } else { filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0); if (chroma) { if (chroma444) { - filter_mb_edgeh (&img_cb[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); - filter_mb_edgeh (&img_cr[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + filter_mb_edgeh (&img_cb[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0); + filter_mb_edgeh (&img_cr[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0); } else if ((edge&1) == 0) { - filter_mb_edgech(&img_cb[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); - filter_mb_edgech(&img_cr[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + filter_mb_edgech(&img_cb[2*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0); + filter_mb_edgech(&img_cr[2*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0); } } } @@ -699,22 +713,25 @@ static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, u } } -void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { +void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl, + int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize) +{ const int mb_xy= mb_x + mb_y*h->mb_stride; const int mb_type = h->cur_pic.mb_type[mb_xy]; const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4; int first_vertical_edge_done = 0; - av_unused int dir; - int chroma = !(CONFIG_GRAY && (h->flags&CODEC_FLAG_GRAY)); - int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8); - int a = 52 + h->slice_alpha_c0_offset - qp_bd_offset; - int b = 52 + h->slice_beta_offset - qp_bd_offset; + int chroma = !(CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY)); + int qp_bd_offset = 6 * (h->ps.sps->bit_depth_luma - 8); + int a = 52 + sl->slice_alpha_c0_offset - qp_bd_offset; + int b = 52 + sl->slice_beta_offset - qp_bd_offset; if (FRAME_MBAFF(h) // and current and left pair do not have the same interlaced type - && IS_INTERLACED(mb_type^h->left_type[LTOP]) + && IS_INTERLACED(mb_type ^ sl->left_type[LTOP]) // and left mb is in available to us - && h->left_type[LTOP]) { + && sl->left_type[LTOP]) { /* First vertical edge is different in MBAFF frames * There are 8 different bS to compute and 2 different Qp */ @@ -739,18 +756,18 @@ void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint {3+4*0, 3+4*1, 3+4*2, 3+4*3, 3+4*0, 3+4*1, 3+4*2, 3+4*3}, } }; - const uint8_t *off= offset[MB_FIELD(h)][mb_y&1]; + const uint8_t *off= offset[MB_FIELD(sl)][mb_y&1]; for( i = 0; i < 8; i++ ) { - int j= MB_FIELD(h) ? i>>2 : i&1; - int mbn_xy = h->left_mb_xy[LEFT(j)]; - int mbn_type= h->left_type[LEFT(j)]; + int j= MB_FIELD(sl) ? i>>2 : i&1; + int mbn_xy = sl->left_mb_xy[LEFT(j)]; + int mbn_type = sl->left_type[LEFT(j)]; if( IS_INTRA( mbn_type ) ) bS[i] = 4; else{ - bS[i] = 1 + !!(h->non_zero_count_cache[12+8*(i>>1)] | - ((!h->pps.cabac && IS_8x8DCT(mbn_type)) ? - (h->cbp_table[mbn_xy] & (((MB_FIELD(h) ? (i&2) : (mb_y&1)) ? 8 : 2) << 12)) + bS[i] = 1 + !!(sl->non_zero_count_cache[12+8*(i>>1)] | + ((!h->ps.pps->cabac && IS_8x8DCT(mbn_type)) ? + (h->cbp_table[mbn_xy] & (((MB_FIELD(sl) ? (i&2) : (mb_y&1)) ? 8 : 2) << 12)) : h->non_zero_count[mbn_xy][ off[i] ])); } @@ -758,23 +775,23 @@ void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint } mb_qp = h->cur_pic.qscale_table[mb_xy]; - mbn0_qp = h->cur_pic.qscale_table[h->left_mb_xy[0]]; - mbn1_qp = h->cur_pic.qscale_table[h->left_mb_xy[1]]; + mbn0_qp = h->cur_pic.qscale_table[sl->left_mb_xy[0]]; + mbn1_qp = h->cur_pic.qscale_table[sl->left_mb_xy[1]]; qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1; - bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) + - get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1; - rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) + - get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1; + bqp[0] = (get_chroma_qp(h->ps.pps, 0, mb_qp) + + get_chroma_qp(h->ps.pps, 0, mbn0_qp) + 1) >> 1; + rqp[0] = (get_chroma_qp(h->ps.pps, 1, mb_qp) + + get_chroma_qp(h->ps.pps, 1, mbn0_qp) + 1) >> 1; qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1; - bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) + - get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1; - rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) + - get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1; + bqp[1] = (get_chroma_qp(h->ps.pps, 0, mb_qp) + + get_chroma_qp(h->ps.pps, 0, mbn1_qp) + 1 ) >> 1; + rqp[1] = (get_chroma_qp(h->ps.pps, 1, mb_qp) + + get_chroma_qp(h->ps.pps, 1, mbn1_qp) + 1 ) >> 1; /* Filter edge */ - tprintf(h->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize); - { int i; for (i = 0; i < 8; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } - if (MB_FIELD(h)) { + ff_tlog(h->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize); + { int i; for (i = 0; i < 8; i++) ff_tlog(h->avctx, " bS[%d]:%d", i, bS[i]); ff_tlog(h->avctx, "\n"); } + if (MB_FIELD(sl)) { filter_mb_mbaff_edgev ( h, img_y , linesize, bS , 1, qp [0], a, b, 1 ); filter_mb_mbaff_edgev ( h, img_y + 8* linesize, linesize, bS+4, 1, qp [1], a, b, 1 ); if (chroma){ @@ -815,10 +832,16 @@ void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint } #if CONFIG_SMALL - for( dir = 0; dir < 2; dir++ ) - filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, dir ? 0 : first_vertical_edge_done, a, b, chroma, dir); + { + int dir; + for (dir = 0; dir < 2; dir++) + filter_mb_dir(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, + uvlinesize, mb_xy, mb_type, mvy_limit, + dir ? 0 : first_vertical_edge_done, a, b, + chroma, dir); + } #else - filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, first_vertical_edge_done, a, b, chroma, 0); - filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, 0, a, b, chroma, 1); + filter_mb_dir(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, first_vertical_edge_done, a, b, chroma, 0); + filter_mb_dir(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, 0, a, b, chroma, 1); #endif } diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c index 61d68ab..f037bd5 100644 --- a/libavcodec/h264_mb.c +++ b/libavcodec/h264_mb.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 macroblock decoding + * H.264 / AVC / MPEG-4 part10 macroblock decoding */ #include @@ -31,15 +31,15 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" +#include "h264_ps.h" #include "qpeldsp.h" -#include "svq3.h" #include "thread.h" -static inline int get_lowest_part_list_y(H264Context *h, H264Picture *pic, int n, - int height, int y_offset, int list) +static inline int get_lowest_part_list_y(H264SliceContext *sl, + int n, int height, int y_offset, int list) { - int raw_my = h->mv_cache[list][scan8[n]][1]; + int raw_my = sl->mv_cache[list][scan8[n]][1]; int filter_height_up = (raw_my & 3) ? 2 : 0; int filter_height_down = (raw_my & 3) ? 3 : 0; int full_my = (raw_my >> 2) + y_offset; @@ -49,24 +49,25 @@ static inline int get_lowest_part_list_y(H264Context *h, H264Picture *pic, int n return FFMAX(abs(top), bottom); } -static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, +static inline void get_lowest_part_y(const H264Context *h, H264SliceContext *sl, + int refs[2][48], int n, int height, int y_offset, int list0, int list1, int *nrefs) { int my; - y_offset += 16 * (h->mb_y >> MB_FIELD(h)); + y_offset += 16 * (sl->mb_y >> MB_FIELD(sl)); if (list0) { - int ref_n = h->ref_cache[0][scan8[n]]; - H264Picture *ref = &h->ref_list[0][ref_n]; + int ref_n = sl->ref_cache[0][scan8[n]]; + H264Ref *ref = &sl->ref_list[0][ref_n]; // Error resilience puts the current picture in the ref list. // Don't try to wait on these as it will cause a deadlock. // Fields can wait on each other, though. - if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + if (ref->parent->tf.progress->data != h->cur_pic.tf.progress->data || (ref->reference & 3) != h->picture_structure) { - my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0); + my = get_lowest_part_list_y(sl, n, height, y_offset, 0); if (refs[0][ref_n] < 0) nrefs[0] += 1; refs[0][ref_n] = FFMAX(refs[0][ref_n], my); @@ -74,12 +75,12 @@ static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, } if (list1) { - int ref_n = h->ref_cache[1][scan8[n]]; - H264Picture *ref = &h->ref_list[1][ref_n]; + int ref_n = sl->ref_cache[1][scan8[n]]; + H264Ref *ref = &sl->ref_list[1][ref_n]; - if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + if (ref->parent->tf.progress->data != h->cur_pic.tf.progress->data || (ref->reference & 3) != h->picture_structure) { - my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1); + my = get_lowest_part_list_y(sl, n, height, y_offset, 1); if (refs[1][ref_n] < 0) nrefs[1] += 1; refs[1][ref_n] = FFMAX(refs[1][ref_n], my); @@ -90,11 +91,11 @@ static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, /** * Wait until all reference frames are available for MC operations. * - * @param h the H264 context + * @param h the H.264 context */ -static void await_references(H264Context *h) +static void await_references(const H264Context *h, H264SliceContext *sl) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; const int mb_type = h->cur_pic.mb_type[mb_xy]; int refs[2][48]; int nrefs[2] = { 0 }; @@ -103,17 +104,17 @@ static void await_references(H264Context *h) memset(refs, -1, sizeof(refs)); if (IS_16X16(mb_type)) { - get_lowest_part_y(h, refs, 0, 16, 0, + get_lowest_part_y(h, sl, refs, 0, 16, 0, IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); } else if (IS_16X8(mb_type)) { - get_lowest_part_y(h, refs, 0, 8, 0, + get_lowest_part_y(h, sl, refs, 0, 8, 0, IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, 8, 8, 8, + get_lowest_part_y(h, sl, refs, 8, 8, 8, IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); } else if (IS_8X16(mb_type)) { - get_lowest_part_y(h, refs, 0, 16, 0, + get_lowest_part_y(h, sl, refs, 0, 16, 0, IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, 4, 16, 0, + get_lowest_part_y(h, sl, refs, 4, 16, 0, IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); } else { int i; @@ -121,30 +122,30 @@ static void await_references(H264Context *h) assert(IS_8X8(mb_type)); for (i = 0; i < 4; i++) { - const int sub_mb_type = h->sub_mb_type[i]; + const int sub_mb_type = sl->sub_mb_type[i]; const int n = 4 * i; int y_offset = (i & 2) << 2; if (IS_SUB_8X8(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 8, y_offset, + get_lowest_part_y(h, sl, refs, n, 8, y_offset, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); } else if (IS_SUB_8X4(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 4, y_offset, + get_lowest_part_y(h, sl, refs, n, 4, y_offset, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, n + 2, 4, y_offset + 4, + get_lowest_part_y(h, sl, refs, n + 2, 4, y_offset + 4, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); } else if (IS_SUB_4X8(sub_mb_type)) { - get_lowest_part_y(h, refs, n, 8, y_offset, + get_lowest_part_y(h, sl, refs, n, 8, y_offset, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); - get_lowest_part_y(h, refs, n + 1, 8, y_offset, + get_lowest_part_y(h, sl, refs, n + 1, 8, y_offset, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); @@ -153,7 +154,7 @@ static void await_references(H264Context *h) assert(IS_SUB_4X4(sub_mb_type)); for (j = 0; j < 4; j++) { int sub_y_offset = y_offset + 2 * (j & 2); - get_lowest_part_y(h, refs, n + j, 4, sub_y_offset, + get_lowest_part_y(h, sl, refs, n + j, 4, sub_y_offset, IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs); @@ -162,37 +163,37 @@ static void await_references(H264Context *h) } } - for (list = h->list_count - 1; list >= 0; list--) + for (list = sl->list_count - 1; list >= 0; list--) for (ref = 0; ref < 48 && nrefs[list]; ref++) { int row = refs[list][ref]; if (row >= 0) { - H264Picture *ref_pic = &h->ref_list[list][ref]; + H264Ref *ref_pic = &sl->ref_list[list][ref]; int ref_field = ref_pic->reference - 1; - int ref_field_picture = ref_pic->field_picture; + int ref_field_picture = ref_pic->parent->field_picture; int pic_height = 16 * h->mb_height >> ref_field_picture; - row <<= MB_MBAFF(h); + row <<= MB_MBAFF(sl); nrefs[list]--; if (!FIELD_PICTURE(h) && ref_field_picture) { // frame referencing two fields - ff_thread_await_progress(&ref_pic->tf, + ff_thread_await_progress(&ref_pic->parent->tf, FFMIN((row >> 1) - !(row & 1), pic_height - 1), 1); - ff_thread_await_progress(&ref_pic->tf, + ff_thread_await_progress(&ref_pic->parent->tf, FFMIN((row >> 1), pic_height - 1), 0); } else if (FIELD_PICTURE(h) && !ref_field_picture) { // field referencing one field of a frame - ff_thread_await_progress(&ref_pic->tf, + ff_thread_await_progress(&ref_pic->parent->tf, FFMIN(row * 2 + ref_field, pic_height - 1), 0); } else if (FIELD_PICTURE(h)) { - ff_thread_await_progress(&ref_pic->tf, + ff_thread_await_progress(&ref_pic->parent->tf, FFMIN(row, pic_height - 1), ref_field); } else { - ff_thread_await_progress(&ref_pic->tf, + ff_thread_await_progress(&ref_pic->parent->tf, FFMIN(row, pic_height - 1), 0); } @@ -200,21 +201,22 @@ static void await_references(H264Context *h) } } -static av_always_inline void mc_dir_part(H264Context *h, H264Picture *pic, +static av_always_inline void mc_dir_part(const H264Context *h, H264SliceContext *sl, + H264Ref *pic, int n, int square, int height, int delta, int list, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int src_x_offset, int src_y_offset, - qpel_mc_func *qpix_op, + const qpel_mc_func *qpix_op, h264_chroma_mc_func chroma_op, int pixel_shift, int chroma_idc) { - const int mx = h->mv_cache[list][scan8[n]][0] + src_x_offset * 8; - int my = h->mv_cache[list][scan8[n]][1] + src_y_offset * 8; + const int mx = sl->mv_cache[list][scan8[n]][0] + src_x_offset * 8; + int my = sl->mv_cache[list][scan8[n]][1] + src_y_offset * 8; const int luma_xy = (mx & 3) + ((my & 3) << 2); - ptrdiff_t offset = ((mx >> 2) << pixel_shift) + (my >> 2) * h->mb_linesize; - uint8_t *src_y = pic->f.data[0] + offset; + ptrdiff_t offset = ((mx >> 2) << pixel_shift) + (my >> 2) * sl->mb_linesize; + uint8_t *src_y = pic->data[0] + offset; uint8_t *src_cb, *src_cr; int extra_width = 0; int extra_height = 0; @@ -222,7 +224,7 @@ static av_always_inline void mc_dir_part(H264Context *h, H264Picture *pic, const int full_mx = mx >> 2; const int full_my = my >> 2; const int pic_width = 16 * h->mb_width; - const int pic_height = 16 * h->mb_height >> MB_FIELD(h); + const int pic_height = 16 * h->mb_height >> MB_FIELD(sl); int ysh; if (mx & 7) @@ -234,119 +236,120 @@ static av_always_inline void mc_dir_part(H264Context *h, H264Picture *pic, full_my < 0 - extra_height || full_mx + 16 /*FIXME*/ > pic_width + extra_width || full_my + 16 /*FIXME*/ > pic_height + extra_height) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_y - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, + h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, + src_y - (2 << pixel_shift) - 2 * sl->mb_linesize, + sl->mb_linesize, sl->mb_linesize, 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, full_my - 2, pic_width, pic_height); - src_y = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + src_y = sl->edge_emu_buffer + (2 << pixel_shift) + 2 * sl->mb_linesize; emu = 1; } - qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); // FIXME try variable height perhaps? + qpix_op[luma_xy](dest_y, src_y, sl->mb_linesize); // FIXME try variable height perhaps? if (!square) - qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize); + qpix_op[luma_xy](dest_y + delta, src_y + delta, sl->mb_linesize); - if (CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY) + if (CONFIG_GRAY && h->flags & AV_CODEC_FLAG_GRAY) return; if (chroma_idc == 3 /* yuv444 */) { - src_cb = pic->f.data[1] + offset; + src_cb = pic->data[1] + offset; if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_cb - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, + h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, + src_cb - (2 << pixel_shift) - 2 * sl->mb_linesize, + sl->mb_linesize, sl->mb_linesize, 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, full_my - 2, pic_width, pic_height); - src_cb = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + src_cb = sl->edge_emu_buffer + (2 << pixel_shift) + 2 * sl->mb_linesize; } - qpix_op[luma_xy](dest_cb, src_cb, h->mb_linesize); // FIXME try variable height perhaps? + qpix_op[luma_xy](dest_cb, src_cb, sl->mb_linesize); // FIXME try variable height perhaps? if (!square) - qpix_op[luma_xy](dest_cb + delta, src_cb + delta, h->mb_linesize); + qpix_op[luma_xy](dest_cb + delta, src_cb + delta, sl->mb_linesize); - src_cr = pic->f.data[2] + offset; + src_cr = pic->data[2] + offset; if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, - src_cr - (2 << pixel_shift) - 2 * h->mb_linesize, - h->mb_linesize, h->mb_linesize, + h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, + src_cr - (2 << pixel_shift) - 2 * sl->mb_linesize, + sl->mb_linesize, sl->mb_linesize, 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, full_my - 2, pic_width, pic_height); - src_cr = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + src_cr = sl->edge_emu_buffer + (2 << pixel_shift) + 2 * sl->mb_linesize; } - qpix_op[luma_xy](dest_cr, src_cr, h->mb_linesize); // FIXME try variable height perhaps? + qpix_op[luma_xy](dest_cr, src_cr, sl->mb_linesize); // FIXME try variable height perhaps? if (!square) - qpix_op[luma_xy](dest_cr + delta, src_cr + delta, h->mb_linesize); + qpix_op[luma_xy](dest_cr + delta, src_cr + delta, sl->mb_linesize); return; } ysh = 3 - (chroma_idc == 2 /* yuv422 */); - if (chroma_idc == 1 /* yuv420 */ && MB_FIELD(h)) { + if (chroma_idc == 1 /* yuv420 */ && MB_FIELD(sl)) { // chroma offset when predicting from a field of opposite parity - my += 2 * ((h->mb_y & 1) - (pic->reference - 1)); + my += 2 * ((sl->mb_y & 1) - (pic->reference - 1)); emu |= (my >> 3) < 0 || (my >> 3) + 8 >= (pic_height >> 1); } - src_cb = pic->f.data[1] + ((mx >> 3) << pixel_shift) + - (my >> ysh) * h->mb_uvlinesize; - src_cr = pic->f.data[2] + ((mx >> 3) << pixel_shift) + - (my >> ysh) * h->mb_uvlinesize; + src_cb = pic->data[1] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * sl->mb_uvlinesize; + src_cr = pic->data[2] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * sl->mb_uvlinesize; if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, - h->mb_uvlinesize, h->mb_uvlinesize, + h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, src_cb, + sl->mb_uvlinesize, sl->mb_uvlinesize, 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); - src_cb = h->edge_emu_buffer; + src_cb = sl->edge_emu_buffer; } - chroma_op(dest_cb, src_cb, h->mb_uvlinesize, + chroma_op(dest_cb, src_cb, sl->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, - h->mb_uvlinesize, h->mb_uvlinesize, + h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, src_cr, + sl->mb_uvlinesize, sl->mb_uvlinesize, 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); - src_cr = h->edge_emu_buffer; + src_cr = sl->edge_emu_buffer; } - chroma_op(dest_cr, src_cr, h->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), + chroma_op(dest_cr, src_cr, sl->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); } -static av_always_inline void mc_part_std(H264Context *h, int n, int square, +static av_always_inline void mc_part_std(const H264Context *h, H264SliceContext *sl, + int n, int square, int height, int delta, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int x_offset, int y_offset, - qpel_mc_func *qpix_put, + const qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put, - qpel_mc_func *qpix_avg, + const qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg, int list0, int list1, int pixel_shift, int chroma_idc) { - qpel_mc_func *qpix_op = qpix_put; + const qpel_mc_func *qpix_op = qpix_put; h264_chroma_mc_func chroma_op = chroma_put; - dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; if (chroma_idc == 3 /* yuv444 */) { - dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; } else if (chroma_idc == 2 /* yuv422 */) { - dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * sl->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * sl->mb_uvlinesize; } else { /* yuv420 */ - dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cb += (x_offset << pixel_shift) + y_offset * sl->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * sl->mb_uvlinesize; } - x_offset += 8 * h->mb_x; - y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + x_offset += 8 * sl->mb_x; + y_offset += 8 * (sl->mb_y >> MB_FIELD(sl)); if (list0) { - H264Picture *ref = &h->ref_list[0][h->ref_cache[0][scan8[n]]]; - mc_dir_part(h, ref, n, square, height, delta, 0, + H264Ref *ref = &sl->ref_list[0][sl->ref_cache[0][scan8[n]]]; + mc_dir_part(h, sl, ref, n, square, height, delta, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_op, chroma_op, pixel_shift, chroma_idc); @@ -355,19 +358,20 @@ static av_always_inline void mc_part_std(H264Context *h, int n, int square, } if (list1) { - H264Picture *ref = &h->ref_list[1][h->ref_cache[1][scan8[n]]]; - mc_dir_part(h, ref, n, square, height, delta, 1, + H264Ref *ref = &sl->ref_list[1][sl->ref_cache[1][scan8[n]]]; + mc_dir_part(h, sl, ref, n, square, height, delta, 1, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_op, chroma_op, pixel_shift, chroma_idc); } } -static av_always_inline void mc_part_weighted(H264Context *h, int n, int square, +static av_always_inline void mc_part_weighted(const H264Context *h, H264SliceContext *sl, + int n, int square, int height, int delta, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int x_offset, int y_offset, - qpel_mc_func *qpix_put, + const qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put, h264_weight_func luma_weight_op, h264_weight_func chroma_weight_op, @@ -378,124 +382,126 @@ static av_always_inline void mc_part_weighted(H264Context *h, int n, int square, { int chroma_height; - dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; if (chroma_idc == 3 /* yuv444 */) { chroma_height = height; chroma_weight_avg = luma_weight_avg; chroma_weight_op = luma_weight_op; - dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; - dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * sl->mb_linesize; } else if (chroma_idc == 2 /* yuv422 */) { chroma_height = height; - dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * sl->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * sl->mb_uvlinesize; } else { /* yuv420 */ chroma_height = height >> 1; - dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; - dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cb += (x_offset << pixel_shift) + y_offset * sl->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * sl->mb_uvlinesize; } - x_offset += 8 * h->mb_x; - y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + x_offset += 8 * sl->mb_x; + y_offset += 8 * (sl->mb_y >> MB_FIELD(sl)); if (list0 && list1) { /* don't optimize for luma-only case, since B-frames usually * use implicit weights => chroma too. */ - uint8_t *tmp_cb = h->bipred_scratchpad; - uint8_t *tmp_cr = h->bipred_scratchpad + (16 << pixel_shift); - uint8_t *tmp_y = h->bipred_scratchpad + 16 * h->mb_uvlinesize; - int refn0 = h->ref_cache[0][scan8[n]]; - int refn1 = h->ref_cache[1][scan8[n]]; + uint8_t *tmp_cb = sl->bipred_scratchpad; + uint8_t *tmp_cr = sl->bipred_scratchpad + (16 << pixel_shift); + uint8_t *tmp_y = sl->bipred_scratchpad + 16 * sl->mb_uvlinesize; + int refn0 = sl->ref_cache[0][scan8[n]]; + int refn1 = sl->ref_cache[1][scan8[n]]; - mc_dir_part(h, &h->ref_list[0][refn0], n, square, height, delta, 0, + mc_dir_part(h, sl, &sl->ref_list[0][refn0], n, square, height, delta, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put, pixel_shift, chroma_idc); - mc_dir_part(h, &h->ref_list[1][refn1], n, square, height, delta, 1, + mc_dir_part(h, sl, &sl->ref_list[1][refn1], n, square, height, delta, 1, tmp_y, tmp_cb, tmp_cr, x_offset, y_offset, qpix_put, chroma_put, pixel_shift, chroma_idc); - if (h->use_weight == 2) { - int weight0 = h->implicit_weight[refn0][refn1][h->mb_y & 1]; + if (sl->pwt.use_weight == 2) { + int weight0 = sl->pwt.implicit_weight[refn0][refn1][sl->mb_y & 1]; int weight1 = 64 - weight0; - luma_weight_avg(dest_y, tmp_y, h->mb_linesize, + luma_weight_avg(dest_y, tmp_y, sl->mb_linesize, height, 5, weight0, weight1, 0); - chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, + chroma_weight_avg(dest_cb, tmp_cb, sl->mb_uvlinesize, chroma_height, 5, weight0, weight1, 0); - chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, + chroma_weight_avg(dest_cr, tmp_cr, sl->mb_uvlinesize, chroma_height, 5, weight0, weight1, 0); } else { - luma_weight_avg(dest_y, tmp_y, h->mb_linesize, height, - h->luma_log2_weight_denom, - h->luma_weight[refn0][0][0], - h->luma_weight[refn1][1][0], - h->luma_weight[refn0][0][1] + - h->luma_weight[refn1][1][1]); - chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn0][0][0][0], - h->chroma_weight[refn1][1][0][0], - h->chroma_weight[refn0][0][0][1] + - h->chroma_weight[refn1][1][0][1]); - chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn0][0][1][0], - h->chroma_weight[refn1][1][1][0], - h->chroma_weight[refn0][0][1][1] + - h->chroma_weight[refn1][1][1][1]); + luma_weight_avg(dest_y, tmp_y, sl->mb_linesize, height, + sl->pwt.luma_log2_weight_denom, + sl->pwt.luma_weight[refn0][0][0], + sl->pwt.luma_weight[refn1][1][0], + sl->pwt.luma_weight[refn0][0][1] + + sl->pwt.luma_weight[refn1][1][1]); + chroma_weight_avg(dest_cb, tmp_cb, sl->mb_uvlinesize, chroma_height, + sl->pwt.chroma_log2_weight_denom, + sl->pwt.chroma_weight[refn0][0][0][0], + sl->pwt.chroma_weight[refn1][1][0][0], + sl->pwt.chroma_weight[refn0][0][0][1] + + sl->pwt.chroma_weight[refn1][1][0][1]); + chroma_weight_avg(dest_cr, tmp_cr, sl->mb_uvlinesize, chroma_height, + sl->pwt.chroma_log2_weight_denom, + sl->pwt.chroma_weight[refn0][0][1][0], + sl->pwt.chroma_weight[refn1][1][1][0], + sl->pwt.chroma_weight[refn0][0][1][1] + + sl->pwt.chroma_weight[refn1][1][1][1]); } } else { int list = list1 ? 1 : 0; - int refn = h->ref_cache[list][scan8[n]]; - H264Picture *ref = &h->ref_list[list][refn]; - mc_dir_part(h, ref, n, square, height, delta, list, + int refn = sl->ref_cache[list][scan8[n]]; + H264Ref *ref = &sl->ref_list[list][refn]; + mc_dir_part(h, sl, ref, n, square, height, delta, list, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put, pixel_shift, chroma_idc); - luma_weight_op(dest_y, h->mb_linesize, height, - h->luma_log2_weight_denom, - h->luma_weight[refn][list][0], - h->luma_weight[refn][list][1]); - if (h->use_weight_chroma) { - chroma_weight_op(dest_cb, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn][list][0][0], - h->chroma_weight[refn][list][0][1]); - chroma_weight_op(dest_cr, h->mb_uvlinesize, chroma_height, - h->chroma_log2_weight_denom, - h->chroma_weight[refn][list][1][0], - h->chroma_weight[refn][list][1][1]); + luma_weight_op(dest_y, sl->mb_linesize, height, + sl->pwt.luma_log2_weight_denom, + sl->pwt.luma_weight[refn][list][0], + sl->pwt.luma_weight[refn][list][1]); + if (sl->pwt.use_weight_chroma) { + chroma_weight_op(dest_cb, sl->mb_uvlinesize, chroma_height, + sl->pwt.chroma_log2_weight_denom, + sl->pwt.chroma_weight[refn][list][0][0], + sl->pwt.chroma_weight[refn][list][0][1]); + chroma_weight_op(dest_cr, sl->mb_uvlinesize, chroma_height, + sl->pwt.chroma_log2_weight_denom, + sl->pwt.chroma_weight[refn][list][1][0], + sl->pwt.chroma_weight[refn][list][1][1]); } } } -static av_always_inline void prefetch_motion(H264Context *h, int list, - int pixel_shift, int chroma_idc) +static av_always_inline void prefetch_motion(const H264Context *h, H264SliceContext *sl, + int list, int pixel_shift, + int chroma_idc) { /* fetch pixels for estimated mv 4 macroblocks ahead * optimized for 64byte cache lines */ - const int refn = h->ref_cache[list][scan8[0]]; + const int refn = sl->ref_cache[list][scan8[0]]; if (refn >= 0) { - const int mx = (h->mv_cache[list][scan8[0]][0] >> 2) + 16 * h->mb_x + 8; - const int my = (h->mv_cache[list][scan8[0]][1] >> 2) + 16 * h->mb_y; - uint8_t **src = h->ref_list[list][refn].f.data; + const int mx = (sl->mv_cache[list][scan8[0]][0] >> 2) + 16 * sl->mb_x + 8; + const int my = (sl->mv_cache[list][scan8[0]][1] >> 2) + 16 * sl->mb_y; + uint8_t **src = sl->ref_list[list][refn].data; int off = (mx << pixel_shift) + - (my + (h->mb_x & 3) * 4) * h->mb_linesize + + (my + (sl->mb_x & 3) * 4) * sl->mb_linesize + (64 << pixel_shift); - h->vdsp.prefetch(src[0] + off, h->linesize, 4); + h->vdsp.prefetch(src[0] + off, sl->linesize, 4); if (chroma_idc == 3 /* yuv444 */) { - h->vdsp.prefetch(src[1] + off, h->linesize, 4); - h->vdsp.prefetch(src[2] + off, h->linesize, 4); + h->vdsp.prefetch(src[1] + off, sl->linesize, 4); + h->vdsp.prefetch(src[2] + off, sl->linesize, 4); } else { off = ((mx >> 1) << pixel_shift) + - ((my >> 1) + (h->mb_x & 7)) * h->uvlinesize + + ((my >> 1) + (sl->mb_x & 7)) * sl->uvlinesize + (64 << pixel_shift); h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); } } } -static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, +static av_always_inline void xchg_mb_border(const H264Context *h, H264SliceContext *sl, + uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int xchg, int chroma444, @@ -508,28 +514,28 @@ static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, uint8_t *top_border; if (!simple && FRAME_MBAFF(h)) { - if (h->mb_y & 1) { - if (!MB_MBAFF(h)) + if (sl->mb_y & 1) { + if (!MB_MBAFF(sl)) return; } else { - top_idx = MB_MBAFF(h) ? 0 : 1; + top_idx = MB_MBAFF(sl) ? 0 : 1; } } - if (h->deblocking_filter == 2) { - deblock_topleft = h->slice_table[h->mb_xy - 1 - h->mb_stride] == h->slice_num; - deblock_top = h->top_type; + if (sl->deblocking_filter == 2) { + deblock_topleft = h->slice_table[sl->mb_xy - 1 - h->mb_stride] == sl->slice_num; + deblock_top = sl->top_type; } else { - deblock_topleft = (h->mb_x > 0); - deblock_top = (h->mb_y > !!MB_FIELD(h)); + deblock_topleft = (sl->mb_x > 0); + deblock_top = (sl->mb_y > !!MB_FIELD(sl)); } src_y -= linesize + 1 + pixel_shift; src_cb -= uvlinesize + 1 + pixel_shift; src_cr -= uvlinesize + 1 + pixel_shift; - top_border_m1 = h->top_borders[top_idx][h->mb_x - 1]; - top_border = h->top_borders[top_idx][h->mb_x]; + top_border_m1 = sl->top_borders[top_idx][sl->mb_x - 1]; + top_border = sl->top_borders[top_idx][sl->mb_x]; #define XCHG(a, b, xchg) \ if (pixel_shift) { \ @@ -551,12 +557,12 @@ static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, } XCHG(top_border + (0 << pixel_shift), src_y + (1 << pixel_shift), xchg); XCHG(top_border + (8 << pixel_shift), src_y + (9 << pixel_shift), 1); - if (h->mb_x + 1 < h->mb_width) { - XCHG(h->top_borders[top_idx][h->mb_x + 1], + if (sl->mb_x + 1 < h->mb_width) { + XCHG(sl->top_borders[top_idx][sl->mb_x + 1], src_y + (17 << pixel_shift), 1); } } - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (simple || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { if (chroma444) { if (deblock_top) { if (deblock_topleft) { @@ -567,9 +573,9 @@ static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, XCHG(top_border + (24 << pixel_shift), src_cb + (9 << pixel_shift), 1); XCHG(top_border + (32 << pixel_shift), src_cr + (1 << pixel_shift), xchg); XCHG(top_border + (40 << pixel_shift), src_cr + (9 << pixel_shift), 1); - if (h->mb_x + 1 < h->mb_width) { - XCHG(h->top_borders[top_idx][h->mb_x + 1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1); - XCHG(h->top_borders[top_idx][h->mb_x + 1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1); + if (sl->mb_x + 1 < h->mb_width) { + XCHG(sl->top_borders[top_idx][sl->mb_x + 1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1); + XCHG(sl->top_borders[top_idx][sl->mb_x + 1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1); } } } else { @@ -603,19 +609,19 @@ static av_always_inline void dctcoef_set(int16_t *mb, int high_bit_depth, AV_WN16A(mb + index, value); } -static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, - int mb_type, int is_h264, - int simple, +static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h, + H264SliceContext *sl, + int mb_type, int simple, int transform_bypass, int pixel_shift, - int *block_offset, + const int *block_offset, int linesize, uint8_t *dest_y, int p) { void (*idct_add)(uint8_t *dst, int16_t *block, int stride); void (*idct_dc_add)(uint8_t *dst, int16_t *block, int stride); int i; - int qscale = p == 0 ? h->qscale : h->chroma_qp[p - 1]; + int qscale = p == 0 ? sl->qscale : sl->chroma_qp[p - 1]; block_offset += 16 * p; if (IS_INTRA4x4(mb_type)) { if (IS_8x8DCT(mb_type)) { @@ -628,18 +634,18 @@ static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, } for (i = 0; i < 16; i += 4) { uint8_t *const ptr = dest_y + block_offset[i]; - const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; - if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { - h->hpc.pred8x8l_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + const int dir = sl->intra4x4_pred_mode_cache[scan8[i]]; + if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) { + h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); } else { - const int nnz = h->non_zero_count_cache[scan8[i + p * 16]]; - h->hpc.pred8x8l[dir](ptr, (h->topleft_samples_available << i) & 0x8000, - (h->topright_samples_available << i) & 0x4000, linesize); + const int nnz = sl->non_zero_count_cache[scan8[i + p * 16]]; + h->hpc.pred8x8l[dir](ptr, (sl->topleft_samples_available << i) & 0x8000, + (sl->topright_samples_available << i) & 0x4000, linesize); if (nnz) { - if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + if (nnz == 1 && dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); else - idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + idct_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); } } } @@ -653,17 +659,17 @@ static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, } for (i = 0; i < 16; i++) { uint8_t *const ptr = dest_y + block_offset[i]; - const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; + const int dir = sl->intra4x4_pred_mode_cache[scan8[i]]; - if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { - h->hpc.pred4x4_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) { + h->hpc.pred4x4_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); } else { uint8_t *topright; int nnz, tr; uint64_t tr_high; if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { - const int topright_avail = (h->topright_samples_available << i) & 0x8000; - assert(h->mb_y || linesize <= block_offset[i]); + const int topright_avail = (sl->topright_samples_available << i) & 0x8000; + assert(sl->mb_y || linesize <= block_offset[i]); if (!topright_avail) { if (pixel_shift) { tr_high = ((uint16_t *)ptr)[3 - linesize / 2] * 0x0001000100010001ULL; @@ -678,52 +684,45 @@ static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, topright = NULL; h->hpc.pred4x4[dir](ptr, topright, linesize); - nnz = h->non_zero_count_cache[scan8[i + p * 16]]; + nnz = sl->non_zero_count_cache[scan8[i + p * 16]]; if (nnz) { - if (is_h264) { - if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - else - idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); - } else if (CONFIG_SVQ3_DECODER) - ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, qscale, 0); + if (nnz == 1 && dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); + else + idct_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); } } } } } else { - h->hpc.pred16x16[h->intra16x16_pred_mode](dest_y, linesize); - if (is_h264) { - if (h->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) { - if (!transform_bypass) - h->h264dsp.h264_luma_dc_dequant_idct(h->mb + (p * 256 << pixel_shift), - h->mb_luma_dc[p], - h->dequant4_coeff[p][qscale][0]); - else { - static const uint8_t dc_mapping[16] = { - 0 * 16, 1 * 16, 4 * 16, 5 * 16, - 2 * 16, 3 * 16, 6 * 16, 7 * 16, - 8 * 16, 9 * 16, 12 * 16, 13 * 16, - 10 * 16, 11 * 16, 14 * 16, 15 * 16 - }; - for (i = 0; i < 16; i++) - dctcoef_set(h->mb + (p * 256 << pixel_shift), - pixel_shift, dc_mapping[i], - dctcoef_get(h->mb_luma_dc[p], - pixel_shift, i)); - } + h->hpc.pred16x16[sl->intra16x16_pred_mode](dest_y, linesize); + if (sl->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) { + if (!transform_bypass) + h->h264dsp.h264_luma_dc_dequant_idct(sl->mb + (p * 256 << pixel_shift), + sl->mb_luma_dc[p], + h->ps.pps->dequant4_coeff[p][qscale][0]); + else { + static const uint8_t dc_mapping[16] = { + 0 * 16, 1 * 16, 4 * 16, 5 * 16, + 2 * 16, 3 * 16, 6 * 16, 7 * 16, + 8 * 16, 9 * 16, 12 * 16, 13 * 16, + 10 * 16, 11 * 16, 14 * 16, 15 * 16 + }; + for (i = 0; i < 16; i++) + dctcoef_set(sl->mb + (p * 256 << pixel_shift), + pixel_shift, dc_mapping[i], + dctcoef_get(sl->mb_luma_dc[p], + pixel_shift, i)); } - } else if (CONFIG_SVQ3_DECODER) - ff_svq3_luma_dc_dequant_idct_c(h->mb + p * 256, - h->mb_luma_dc[p], qscale); + } } } -static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, - int is_h264, int simple, +static av_always_inline void hl_decode_mb_idct_luma(const H264Context *h, H264SliceContext *sl, + int mb_type, int simple, int transform_bypass, int pixel_shift, - int *block_offset, + const int *block_offset, int linesize, uint8_t *dest_y, int p) { @@ -731,60 +730,50 @@ static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, int i; block_offset += 16 * p; if (!IS_INTRA4x4(mb_type)) { - if (is_h264) { - if (IS_INTRA16x16(mb_type)) { - if (transform_bypass) { - if (h->sps.profile_idc == 244 && - (h->intra16x16_pred_mode == VERT_PRED8x8 || - h->intra16x16_pred_mode == HOR_PRED8x8)) { - h->hpc.pred16x16_add[h->intra16x16_pred_mode](dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize); - } else { - for (i = 0; i < 16; i++) - if (h->non_zero_count_cache[scan8[i + p * 16]] || - dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) - h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i], - h->mb + (i * 16 + p * 256 << pixel_shift), - linesize); - } - } else { - h->h264dsp.h264_idct_add16intra(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); - } - } else if (h->cbp & 15) { - if (transform_bypass) { - const int di = IS_8x8DCT(mb_type) ? 4 : 1; - idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear - : h->h264dsp.h264_add_pixels4_clear; - for (i = 0; i < 16; i += di) - if (h->non_zero_count_cache[scan8[i + p * 16]]) - idct_add(dest_y + block_offset[i], - h->mb + (i * 16 + p * 256 << pixel_shift), - linesize); + if (IS_INTRA16x16(mb_type)) { + if (transform_bypass) { + if (h->ps.sps->profile_idc == 244 && + (sl->intra16x16_pred_mode == VERT_PRED8x8 || + sl->intra16x16_pred_mode == HOR_PRED8x8)) { + h->hpc.pred16x16_add[sl->intra16x16_pred_mode](dest_y, block_offset, + sl->mb + (p * 256 << pixel_shift), + linesize); } else { - if (IS_8x8DCT(mb_type)) - h->h264dsp.h264_idct8_add4(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); - else - h->h264dsp.h264_idct_add16(dest_y, block_offset, - h->mb + (p * 256 << pixel_shift), - linesize, - h->non_zero_count_cache + p * 5 * 8); + for (i = 0; i < 16; i++) + if (sl->non_zero_count_cache[scan8[i + p * 16]] || + dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256)) + h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i], + sl->mb + (i * 16 + p * 256 << pixel_shift), + linesize); } + } else { + h->h264dsp.h264_idct_add16intra(dest_y, block_offset, + sl->mb + (p * 256 << pixel_shift), + linesize, + sl->non_zero_count_cache + p * 5 * 8); + } + } else if (sl->cbp & 15) { + if (transform_bypass) { + const int di = IS_8x8DCT(mb_type) ? 4 : 1; + idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear + : h->h264dsp.h264_add_pixels4_clear; + for (i = 0; i < 16; i += di) + if (sl->non_zero_count_cache[scan8[i + p * 16]]) + idct_add(dest_y + block_offset[i], + sl->mb + (i * 16 + p * 256 << pixel_shift), + linesize); + } else { + if (IS_8x8DCT(mb_type)) + h->h264dsp.h264_idct8_add4(dest_y, block_offset, + sl->mb + (p * 256 << pixel_shift), + linesize, + sl->non_zero_count_cache + p * 5 * 8); + else + h->h264dsp.h264_idct_add16(dest_y, block_offset, + sl->mb + (p * 256 << pixel_shift), + linesize, + sl->non_zero_count_cache + p * 5 * 8); } - } else if (CONFIG_SVQ3_DECODER) { - for (i = 0; i < 16; i++) - if (h->non_zero_count_cache[scan8[i + p * 16]] || h->mb[i * 16 + p * 256]) { - // FIXME benchmark weird rule, & below - uint8_t *const ptr = dest_y + block_offset[i]; - ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, - h->qscale, IS_INTRA(mb_type) ? 1 : 0); - } } } } @@ -801,22 +790,22 @@ static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, #define SIMPLE 0 #include "h264_mb_template.c" -void ff_h264_hl_decode_mb(H264Context *h) +void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; const int mb_type = h->cur_pic.mb_type[mb_xy]; - int is_complex = CONFIG_SMALL || h->is_complex || - IS_INTRA_PCM(mb_type) || h->qscale == 0; + int is_complex = CONFIG_SMALL || sl->is_complex || + IS_INTRA_PCM(mb_type) || sl->qscale == 0; if (CHROMA444(h)) { if (is_complex || h->pixel_shift) - hl_decode_mb_444_complex(h); + hl_decode_mb_444_complex(h, sl); else - hl_decode_mb_444_simple_8(h); + hl_decode_mb_444_simple_8(h, sl); } else if (is_complex) { - hl_decode_mb_complex(h); + hl_decode_mb_complex(h, sl); } else if (h->pixel_shift) { - hl_decode_mb_simple_16(h); + hl_decode_mb_simple_16(h, sl); } else - hl_decode_mb_simple_8(h); + hl_decode_mb_simple_8(h, sl); } diff --git a/libavcodec/h264_mb_template.c b/libavcodec/h264_mb_template.c index 5b2917f..1f583df 100644 --- a/libavcodec/h264_mb_template.c +++ b/libavcodec/h264_mb_template.c @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "svq3.h" - #undef FUNC #undef PIXEL_SHIFT @@ -40,80 +38,78 @@ #define CHROMA_IDC 2 #include "h264_mc_template.c" -static av_noinline void FUNC(hl_decode_mb)(H264Context *h) +static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContext *sl) { - const int mb_x = h->mb_x; - const int mb_y = h->mb_y; - const int mb_xy = h->mb_xy; + const int mb_x = sl->mb_x; + const int mb_y = sl->mb_y; + const int mb_xy = sl->mb_xy; const int mb_type = h->cur_pic.mb_type[mb_xy]; uint8_t *dest_y, *dest_cb, *dest_cr; int linesize, uvlinesize /*dct_offset*/; int i, j; - int *block_offset = &h->block_offset[0]; - const int transform_bypass = !SIMPLE && (h->qscale == 0 && h->sps.transform_bypass); - /* is_h264 should always be true if SVQ3 is disabled. */ - const int is_h264 = !CONFIG_SVQ3_DECODER || SIMPLE || h->avctx->codec_id == AV_CODEC_ID_H264; + const int *block_offset = &h->block_offset[0]; + const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->ps.sps->transform_bypass); void (*idct_add)(uint8_t *dst, int16_t *block, int stride); const int block_h = 16 >> h->chroma_y_shift; const int chroma422 = CHROMA422(h); - dest_y = h->cur_pic.f.data[0] + ((mb_x << PIXEL_SHIFT) + mb_y * h->linesize) * 16; - dest_cb = h->cur_pic.f.data[1] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * h->uvlinesize * block_h; - dest_cr = h->cur_pic.f.data[2] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * h->uvlinesize * block_h; + dest_y = h->cur_pic.f->data[0] + ((mb_x << PIXEL_SHIFT) + mb_y * sl->linesize) * 16; + dest_cb = h->cur_pic.f->data[1] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * sl->uvlinesize * block_h; + dest_cr = h->cur_pic.f->data[2] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * sl->uvlinesize * block_h; - h->vdsp.prefetch(dest_y + (h->mb_x & 3) * 4 * h->linesize + (64 << PIXEL_SHIFT), h->linesize, 4); - h->vdsp.prefetch(dest_cb + (h->mb_x & 7) * h->uvlinesize + (64 << PIXEL_SHIFT), dest_cr - dest_cb, 2); + h->vdsp.prefetch(dest_y + (sl->mb_x & 3) * 4 * sl->linesize + (64 << PIXEL_SHIFT), sl->linesize, 4); + h->vdsp.prefetch(dest_cb + (sl->mb_x & 7) * sl->uvlinesize + (64 << PIXEL_SHIFT), dest_cr - dest_cb, 2); - h->list_counts[mb_xy] = h->list_count; + h->list_counts[mb_xy] = sl->list_count; - if (!SIMPLE && MB_FIELD(h)) { - linesize = h->mb_linesize = h->linesize * 2; - uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; + if (!SIMPLE && MB_FIELD(sl)) { + linesize = sl->mb_linesize = sl->linesize * 2; + uvlinesize = sl->mb_uvlinesize = sl->uvlinesize * 2; block_offset = &h->block_offset[48]; if (mb_y & 1) { // FIXME move out of this function? - dest_y -= h->linesize * 15; - dest_cb -= h->uvlinesize * (block_h - 1); - dest_cr -= h->uvlinesize * (block_h - 1); + dest_y -= sl->linesize * 15; + dest_cb -= sl->uvlinesize * (block_h - 1); + dest_cr -= sl->uvlinesize * (block_h - 1); } if (FRAME_MBAFF(h)) { int list; - for (list = 0; list < h->list_count; list++) { + for (list = 0; list < sl->list_count; list++) { if (!USES_LIST(mb_type, list)) continue; if (IS_16X16(mb_type)) { - int8_t *ref = &h->ref_cache[list][scan8[0]]; - fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (h->mb_y & 1), 1); + int8_t *ref = &sl->ref_cache[list][scan8[0]]; + fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (sl->mb_y & 1), 1); } else { for (i = 0; i < 16; i += 4) { - int ref = h->ref_cache[list][scan8[i]]; + int ref = sl->ref_cache[list][scan8[i]]; if (ref >= 0) - fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, - 8, (16 + ref) ^ (h->mb_y & 1), 1); + fill_rectangle(&sl->ref_cache[list][scan8[i]], 2, 2, + 8, (16 + ref) ^ (sl->mb_y & 1), 1); } } } } } else { - linesize = h->mb_linesize = h->linesize; - uvlinesize = h->mb_uvlinesize = h->uvlinesize; + linesize = sl->mb_linesize = sl->linesize; + uvlinesize = sl->mb_uvlinesize = sl->uvlinesize; // dct_offset = s->linesize * 16; } if (!SIMPLE && IS_INTRA_PCM(mb_type)) { if (PIXEL_SHIFT) { - const int bit_depth = h->sps.bit_depth_luma; + const int bit_depth = h->ps.sps->bit_depth_luma; int j; GetBitContext gb; - init_get_bits(&gb, h->intra_pcm_ptr, - ff_h264_mb_sizes[h->sps.chroma_format_idc] * bit_depth); + init_get_bits(&gb, sl->intra_pcm_ptr, + ff_h264_mb_sizes[h->ps.sps->chroma_format_idc] * bit_depth); for (i = 0; i < 16; i++) { uint16_t *tmp_y = (uint16_t *)(dest_y + i * linesize); for (j = 0; j < 16; j++) tmp_y[j] = get_bits(&gb, bit_depth); } - if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - if (!h->sps.chroma_format_idc) { + if (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { + if (!h->ps.sps->chroma_format_idc) { for (i = 0; i < block_h; i++) { uint16_t *tmp_cb = (uint16_t *)(dest_cb + i * uvlinesize); for (j = 0; j < 8; j++) @@ -139,16 +135,16 @@ static av_noinline void FUNC(hl_decode_mb)(H264Context *h) } } else { for (i = 0; i < 16; i++) - memcpy(dest_y + i * linesize, h->intra_pcm_ptr + i * 16, 16); - if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - if (!h->sps.chroma_format_idc) { + memcpy(dest_y + i * linesize, sl->intra_pcm_ptr + i * 16, 16); + if (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { + if (!h->ps.sps->chroma_format_idc) { for (i = 0; i < block_h; i++) { memset(dest_cb + i * uvlinesize, 128, 8); memset(dest_cr + i * uvlinesize, 128, 8); } } else { - const uint8_t *src_cb = h->intra_pcm_ptr + 256; - const uint8_t *src_cr = h->intra_pcm_ptr + 256 + block_h * 8; + const uint8_t *src_cb = sl->intra_pcm_ptr + 256; + const uint8_t *src_cr = sl->intra_pcm_ptr + 256 + block_h * 8; for (i = 0; i < block_h; i++) { memcpy(dest_cb + i * uvlinesize, src_cb + i * 8, 8); memcpy(dest_cr + i * uvlinesize, src_cr + i * 8, 8); @@ -158,109 +154,97 @@ static av_noinline void FUNC(hl_decode_mb)(H264Context *h) } } else { if (IS_INTRA(mb_type)) { - if (h->deblocking_filter) - xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + if (sl->deblocking_filter) + xchg_mb_border(h, sl, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1, 0, SIMPLE, PIXEL_SHIFT); - if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { - h->hpc.pred8x8[h->chroma_pred_mode](dest_cb, uvlinesize); - h->hpc.pred8x8[h->chroma_pred_mode](dest_cr, uvlinesize); + if (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { + h->hpc.pred8x8[sl->chroma_pred_mode](dest_cb, uvlinesize); + h->hpc.pred8x8[sl->chroma_pred_mode](dest_cr, uvlinesize); } - hl_decode_mb_predict_luma(h, mb_type, is_h264, SIMPLE, + hl_decode_mb_predict_luma(h, sl, mb_type, SIMPLE, transform_bypass, PIXEL_SHIFT, block_offset, linesize, dest_y, 0); - if (h->deblocking_filter) - xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + if (sl->deblocking_filter) + xchg_mb_border(h, sl, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0, 0, SIMPLE, PIXEL_SHIFT); - } else if (is_h264) { + } else { if (chroma422) { - FUNC(hl_motion_422)(h, dest_y, dest_cb, dest_cr, - h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + FUNC(hl_motion_422)(h, sl, dest_y, dest_cb, dest_cr, + h->h264qpel.put_h264_qpel_pixels_tab, + h->h264chroma.put_h264_chroma_pixels_tab, + h->h264qpel.avg_h264_qpel_pixels_tab, + h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } else { - FUNC(hl_motion_420)(h, dest_y, dest_cb, dest_cr, - h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + FUNC(hl_motion_420)(h, sl, dest_y, dest_cb, dest_cr, + h->h264qpel.put_h264_qpel_pixels_tab, + h->h264chroma.put_h264_chroma_pixels_tab, + h->h264qpel.avg_h264_qpel_pixels_tab, + h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } } - hl_decode_mb_idct_luma(h, mb_type, is_h264, SIMPLE, transform_bypass, + hl_decode_mb_idct_luma(h, sl, mb_type, SIMPLE, transform_bypass, PIXEL_SHIFT, block_offset, linesize, dest_y, 0); - if ((SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) && - (h->cbp & 0x30)) { + if ((SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) && + (sl->cbp & 0x30)) { uint8_t *dest[2] = { dest_cb, dest_cr }; if (transform_bypass) { - if (IS_INTRA(mb_type) && h->sps.profile_idc == 244 && - (h->chroma_pred_mode == VERT_PRED8x8 || - h->chroma_pred_mode == HOR_PRED8x8)) { - h->hpc.pred8x8_add[h->chroma_pred_mode](dest[0], + if (IS_INTRA(mb_type) && h->ps.sps->profile_idc == 244 && + (sl->chroma_pred_mode == VERT_PRED8x8 || + sl->chroma_pred_mode == HOR_PRED8x8)) { + h->hpc.pred8x8_add[sl->chroma_pred_mode](dest[0], block_offset + 16, - h->mb + (16 * 16 * 1 << PIXEL_SHIFT), + sl->mb + (16 * 16 * 1 << PIXEL_SHIFT), uvlinesize); - h->hpc.pred8x8_add[h->chroma_pred_mode](dest[1], + h->hpc.pred8x8_add[sl->chroma_pred_mode](dest[1], block_offset + 32, - h->mb + (16 * 16 * 2 << PIXEL_SHIFT), + sl->mb + (16 * 16 * 2 << PIXEL_SHIFT), uvlinesize); } else { idct_add = h->h264dsp.h264_add_pixels4_clear; for (j = 1; j < 3; j++) { for (i = j * 16; i < j * 16 + 4; i++) - if (h->non_zero_count_cache[scan8[i]] || - dctcoef_get(h->mb, PIXEL_SHIFT, i * 16)) + if (sl->non_zero_count_cache[scan8[i]] || + dctcoef_get(sl->mb, PIXEL_SHIFT, i * 16)) idct_add(dest[j - 1] + block_offset[i], - h->mb + (i * 16 << PIXEL_SHIFT), + sl->mb + (i * 16 << PIXEL_SHIFT), uvlinesize); if (chroma422) { for (i = j * 16 + 4; i < j * 16 + 8; i++) - if (h->non_zero_count_cache[scan8[i + 4]] || - dctcoef_get(h->mb, PIXEL_SHIFT, i * 16)) + if (sl->non_zero_count_cache[scan8[i + 4]] || + dctcoef_get(sl->mb, PIXEL_SHIFT, i * 16)) idct_add(dest[j - 1] + block_offset[i + 4], - h->mb + (i * 16 << PIXEL_SHIFT), + sl->mb + (i * 16 << PIXEL_SHIFT), uvlinesize); } } } } else { - if (is_h264) { - int qp[2]; - if (chroma422) { - qp[0] = h->chroma_qp[0] + 3; - qp[1] = h->chroma_qp[1] + 3; - } else { - qp[0] = h->chroma_qp[0]; - qp[1] = h->chroma_qp[1]; - } - if (h->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 0]]) - h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16 * 16 * 1 << PIXEL_SHIFT), - h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][qp[0]][0]); - if (h->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 1]]) - h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16 * 16 * 2 << PIXEL_SHIFT), - h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][qp[1]][0]); - h->h264dsp.h264_idct_add8(dest, block_offset, - h->mb, uvlinesize, - h->non_zero_count_cache); - } else if (CONFIG_SVQ3_DECODER) { - h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16 * 16 * 1, - h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][h->chroma_qp[0]][0]); - h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16 * 16 * 2, - h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][h->chroma_qp[1]][0]); - for (j = 1; j < 3; j++) { - for (i = j * 16; i < j * 16 + 4; i++) - if (h->non_zero_count_cache[scan8[i]] || h->mb[i * 16]) { - uint8_t *const ptr = dest[j - 1] + block_offset[i]; - ff_svq3_add_idct_c(ptr, h->mb + i * 16, - uvlinesize, - ff_h264_chroma_qp[0][h->qscale + 12] - 12, 2); - } - } + int qp[2]; + if (chroma422) { + qp[0] = sl->chroma_qp[0] + 3; + qp[1] = sl->chroma_qp[1] + 3; + } else { + qp[0] = sl->chroma_qp[0]; + qp[1] = sl->chroma_qp[1]; } + if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 0]]) + h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 1 << PIXEL_SHIFT), + h->ps.pps->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][qp[0]][0]); + if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 1]]) + h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 2 << PIXEL_SHIFT), + h->ps.pps->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][qp[1]][0]); + h->h264dsp.h264_idct_add8(dest, block_offset, + sl->mb, uvlinesize, + sl->non_zero_count_cache); } } } @@ -272,61 +256,61 @@ static av_noinline void FUNC(hl_decode_mb)(H264Context *h) #define CHROMA_IDC 3 #include "h264_mc_template.c" -static av_noinline void FUNC(hl_decode_mb_444)(H264Context *h) +static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceContext *sl) { - const int mb_x = h->mb_x; - const int mb_y = h->mb_y; - const int mb_xy = h->mb_xy; + const int mb_x = sl->mb_x; + const int mb_y = sl->mb_y; + const int mb_xy = sl->mb_xy; const int mb_type = h->cur_pic.mb_type[mb_xy]; uint8_t *dest[3]; int linesize; int i, j, p; - int *block_offset = &h->block_offset[0]; - const int transform_bypass = !SIMPLE && (h->qscale == 0 && h->sps.transform_bypass); - const int plane_count = (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) ? 3 : 1; + const int *block_offset = &h->block_offset[0]; + const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->ps.sps->transform_bypass); + const int plane_count = (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) ? 3 : 1; for (p = 0; p < plane_count; p++) { - dest[p] = h->cur_pic.f.data[p] + - ((mb_x << PIXEL_SHIFT) + mb_y * h->linesize) * 16; - h->vdsp.prefetch(dest[p] + (h->mb_x & 3) * 4 * h->linesize + (64 << PIXEL_SHIFT), - h->linesize, 4); + dest[p] = h->cur_pic.f->data[p] + + ((mb_x << PIXEL_SHIFT) + mb_y * sl->linesize) * 16; + h->vdsp.prefetch(dest[p] + (sl->mb_x & 3) * 4 * sl->linesize + (64 << PIXEL_SHIFT), + sl->linesize, 4); } - h->list_counts[mb_xy] = h->list_count; + h->list_counts[mb_xy] = sl->list_count; - if (!SIMPLE && MB_FIELD(h)) { - linesize = h->mb_linesize = h->mb_uvlinesize = h->linesize * 2; + if (!SIMPLE && MB_FIELD(sl)) { + linesize = sl->mb_linesize = sl->mb_uvlinesize = sl->linesize * 2; block_offset = &h->block_offset[48]; if (mb_y & 1) // FIXME move out of this function? for (p = 0; p < 3; p++) - dest[p] -= h->linesize * 15; + dest[p] -= sl->linesize * 15; if (FRAME_MBAFF(h)) { int list; - for (list = 0; list < h->list_count; list++) { + for (list = 0; list < sl->list_count; list++) { if (!USES_LIST(mb_type, list)) continue; if (IS_16X16(mb_type)) { - int8_t *ref = &h->ref_cache[list][scan8[0]]; - fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (h->mb_y & 1), 1); + int8_t *ref = &sl->ref_cache[list][scan8[0]]; + fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (sl->mb_y & 1), 1); } else { for (i = 0; i < 16; i += 4) { - int ref = h->ref_cache[list][scan8[i]]; + int ref = sl->ref_cache[list][scan8[i]]; if (ref >= 0) - fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, - 8, (16 + ref) ^ (h->mb_y & 1), 1); + fill_rectangle(&sl->ref_cache[list][scan8[i]], 2, 2, + 8, (16 + ref) ^ (sl->mb_y & 1), 1); } } } } } else { - linesize = h->mb_linesize = h->mb_uvlinesize = h->linesize; + linesize = sl->mb_linesize = sl->mb_uvlinesize = sl->linesize; } if (!SIMPLE && IS_INTRA_PCM(mb_type)) { if (PIXEL_SHIFT) { - const int bit_depth = h->sps.bit_depth_luma; + const int bit_depth = h->ps.sps->bit_depth_luma; GetBitContext gb; - init_get_bits(&gb, h->intra_pcm_ptr, 768 * bit_depth); + init_get_bits(&gb, sl->intra_pcm_ptr, 768 * bit_depth); for (p = 0; p < plane_count; p++) for (i = 0; i < 16; i++) { @@ -338,32 +322,34 @@ static av_noinline void FUNC(hl_decode_mb_444)(H264Context *h) for (p = 0; p < plane_count; p++) for (i = 0; i < 16; i++) memcpy(dest[p] + i * linesize, - h->intra_pcm_ptr + p * 256 + i * 16, 16); + sl->intra_pcm_ptr + p * 256 + i * 16, 16); } } else { if (IS_INTRA(mb_type)) { - if (h->deblocking_filter) - xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, + if (sl->deblocking_filter) + xchg_mb_border(h, sl, dest[0], dest[1], dest[2], linesize, linesize, 1, 1, SIMPLE, PIXEL_SHIFT); for (p = 0; p < plane_count; p++) - hl_decode_mb_predict_luma(h, mb_type, 1, SIMPLE, + hl_decode_mb_predict_luma(h, sl, mb_type, SIMPLE, transform_bypass, PIXEL_SHIFT, block_offset, linesize, dest[p], p); - if (h->deblocking_filter) - xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, + if (sl->deblocking_filter) + xchg_mb_border(h, sl, dest[0], dest[1], dest[2], linesize, linesize, 0, 1, SIMPLE, PIXEL_SHIFT); } else { - FUNC(hl_motion_444)(h, dest[0], dest[1], dest[2], - h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, - h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + FUNC(hl_motion_444)(h, sl, dest[0], dest[1], dest[2], + h->h264qpel.put_h264_qpel_pixels_tab, + h->h264chroma.put_h264_chroma_pixels_tab, + h->h264qpel.avg_h264_qpel_pixels_tab, + h->h264chroma.avg_h264_chroma_pixels_tab, h->h264dsp.weight_h264_pixels_tab, h->h264dsp.biweight_h264_pixels_tab); } for (p = 0; p < plane_count; p++) - hl_decode_mb_idct_luma(h, mb_type, 1, SIMPLE, transform_bypass, + hl_decode_mb_idct_luma(h, sl, mb_type, SIMPLE, transform_bypass, PIXEL_SHIFT, block_offset, linesize, dest[p], p); } diff --git a/libavcodec/h264_mc_template.c b/libavcodec/h264_mc_template.c index c085cc3..7e6f62f 100644 --- a/libavcodec/h264_mc_template.c +++ b/libavcodec/h264_mc_template.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "h264.h" +#include "h264dec.h" #undef MCFUNC @@ -34,70 +34,72 @@ #undef mc_part #define mc_part MCFUNC(mc_part) -static void mc_part(H264Context *h, int n, int square, +static void mc_part(const H264Context *h, H264SliceContext *sl, + int n, int square, int height, int delta, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int x_offset, int y_offset, - qpel_mc_func *qpix_put, + const qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put, - qpel_mc_func *qpix_avg, + const qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg, - h264_weight_func *weight_op, - h264_biweight_func *weight_avg, + const h264_weight_func *weight_op, + const h264_biweight_func *weight_avg, int list0, int list1) { - if ((h->use_weight == 2 && list0 && list1 && - (h->implicit_weight[h->ref_cache[0][scan8[n]]][h->ref_cache[1][scan8[n]]][h->mb_y & 1] != 32)) || - h->use_weight == 1) - mc_part_weighted(h, n, square, height, delta, dest_y, dest_cb, dest_cr, + if ((sl->pwt.use_weight == 2 && list0 && list1 && + (sl->pwt.implicit_weight[sl->ref_cache[0][scan8[n]]][sl->ref_cache[1][scan8[n]]][sl->mb_y & 1] != 32)) || + sl->pwt.use_weight == 1) + mc_part_weighted(h, sl, n, square, height, delta, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put, weight_op[0], weight_op[1], weight_avg[0], weight_avg[1], list0, list1, PIXEL_SHIFT, CHROMA_IDC); else - mc_part_std(h, n, square, height, delta, dest_y, dest_cb, dest_cr, + mc_part_std(h, sl, n, square, height, delta, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put, qpix_avg, chroma_avg, list0, list1, PIXEL_SHIFT, CHROMA_IDC); } -static void MCFUNC(hl_motion)(H264Context *h, uint8_t *dest_y, +static void MCFUNC(hl_motion)(const H264Context *h, H264SliceContext *sl, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - qpel_mc_func(*qpix_put)[16], - h264_chroma_mc_func(*chroma_put), - qpel_mc_func(*qpix_avg)[16], - h264_chroma_mc_func(*chroma_avg), - h264_weight_func *weight_op, - h264_biweight_func *weight_avg) + const qpel_mc_func(*qpix_put)[16], + const h264_chroma_mc_func(*chroma_put), + const qpel_mc_func(*qpix_avg)[16], + const h264_chroma_mc_func(*chroma_avg), + const h264_weight_func *weight_op, + const h264_biweight_func *weight_avg) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; const int mb_type = h->cur_pic.mb_type[mb_xy]; assert(IS_INTER(mb_type)); if (HAVE_THREADS && (h->avctx->active_thread_type & FF_THREAD_FRAME)) - await_references(h); - prefetch_motion(h, 0, PIXEL_SHIFT, CHROMA_IDC); + await_references(h, sl); + prefetch_motion(h, sl, 0, PIXEL_SHIFT, CHROMA_IDC); if (IS_16X16(mb_type)) { - mc_part(h, 0, 1, 16, 0, dest_y, dest_cb, dest_cr, 0, 0, + mc_part(h, sl, 0, 1, 16, 0, dest_y, dest_cb, dest_cr, 0, 0, qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0], weight_op, weight_avg, IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); } else if (IS_16X8(mb_type)) { - mc_part(h, 0, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 0, + mc_part(h, sl, 0, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 0, qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0], weight_op, weight_avg, IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); - mc_part(h, 8, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 4, + mc_part(h, sl, 8, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 4, qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0], weight_op, weight_avg, IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1)); } else if (IS_8X16(mb_type)) { - mc_part(h, 0, 0, 16, 8 * h->mb_linesize, dest_y, dest_cb, dest_cr, 0, 0, + mc_part(h, sl, 0, 0, 16, 8 * sl->mb_linesize, dest_y, dest_cb, dest_cr, 0, 0, qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], &weight_op[1], &weight_avg[1], IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); - mc_part(h, 4, 0, 16, 8 * h->mb_linesize, dest_y, dest_cb, dest_cr, 4, 0, + mc_part(h, sl, 4, 0, 16, 8 * sl->mb_linesize, dest_y, dest_cb, dest_cr, 4, 0, qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], &weight_op[1], &weight_avg[1], IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1)); @@ -107,35 +109,35 @@ static void MCFUNC(hl_motion)(H264Context *h, uint8_t *dest_y, assert(IS_8X8(mb_type)); for (i = 0; i < 4; i++) { - const int sub_mb_type = h->sub_mb_type[i]; + const int sub_mb_type = sl->sub_mb_type[i]; const int n = 4 * i; int x_offset = (i & 1) << 2; int y_offset = (i & 2) << 1; if (IS_SUB_8X8(sub_mb_type)) { - mc_part(h, n, 1, 8, 0, dest_y, dest_cb, dest_cr, + mc_part(h, sl, n, 1, 8, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], &weight_op[1], &weight_avg[1], IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); } else if (IS_SUB_8X4(sub_mb_type)) { - mc_part(h, n, 0, 4, 4 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, + mc_part(h, sl, n, 0, 4, 4 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1], &weight_op[1], &weight_avg[1], IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); - mc_part(h, n + 2, 0, 4, 4 << PIXEL_SHIFT, + mc_part(h, sl, n + 2, 0, 4, 4 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, x_offset, y_offset + 2, qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1], &weight_op[1], &weight_avg[1], IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); } else if (IS_SUB_4X8(sub_mb_type)) { - mc_part(h, n, 0, 8, 4 * h->mb_linesize, + mc_part(h, sl, n, 0, 8, 4 * sl->mb_linesize, dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], &weight_op[2], &weight_avg[2], IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); - mc_part(h, n + 1, 0, 8, 4 * h->mb_linesize, + mc_part(h, sl, n + 1, 0, 8, 4 * sl->mb_linesize, dest_y, dest_cb, dest_cr, x_offset + 2, y_offset, qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], &weight_op[2], &weight_avg[2], @@ -146,7 +148,7 @@ static void MCFUNC(hl_motion)(H264Context *h, uint8_t *dest_y, for (j = 0; j < 4; j++) { int sub_x_offset = x_offset + 2 * (j & 1); int sub_y_offset = y_offset + (j & 2); - mc_part(h, n + j, 1, 4, 0, + mc_part(h, sl, n + j, 1, 4, 0, dest_y, dest_cb, dest_cr, sub_x_offset, sub_y_offset, qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], &weight_op[2], &weight_avg[2], @@ -156,6 +158,6 @@ static void MCFUNC(hl_motion)(H264Context *h, uint8_t *dest_y, } } - prefetch_motion(h, 1, PIXEL_SHIFT, CHROMA_IDC); + prefetch_motion(h, sl, 1, PIXEL_SHIFT, CHROMA_IDC); } diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c index 3b212e5..c65aaeb 100644 --- a/libavcodec/h264_mp4toannexb_bsf.c +++ b/libavcodec/h264_mp4toannexb_bsf.c @@ -23,7 +23,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" + #include "avcodec.h" +#include "bsf.h" typedef struct H264BSFContext { uint8_t length_size; @@ -31,41 +33,39 @@ typedef struct H264BSFContext { int extradata_parsed; } H264BSFContext; -static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, +static int alloc_and_copy(AVPacket *out, const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size) { - uint32_t offset = *poutbuf_size; + uint32_t offset = out->size; uint8_t nal_header_size = offset ? 3 : 4; int err; - *poutbuf_size += sps_pps_size + in_size + nal_header_size; - if ((err = av_reallocp(poutbuf, - *poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) { - *poutbuf_size = 0; + err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size); + if (err < 0) return err; - } + if (sps_pps) - memcpy(*poutbuf + offset, sps_pps, sps_pps_size); - memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); + memcpy(out->data + offset, sps_pps, sps_pps_size); + memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size); if (!offset) { - AV_WB32(*poutbuf + sps_pps_size, 1); + AV_WB32(out->data + sps_pps_size, 1); } else { - (*poutbuf + offset + sps_pps_size)[0] = - (*poutbuf + offset + sps_pps_size)[1] = 0; - (*poutbuf + offset + sps_pps_size)[2] = 1; + (out->data + offset + sps_pps_size)[0] = + (out->data + offset + sps_pps_size)[1] = 0; + (out->data + offset + sps_pps_size)[2] = 1; } return 0; } -static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) +static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding) { uint16_t unit_size; uint64_t total_size = 0; uint8_t *out = NULL, unit_nb, sps_done = 0, sps_seen = 0, pps_seen = 0; - const uint8_t *extradata = avctx->extradata + 4; + const uint8_t *extradata = ctx->par_in->extradata + 4; static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size @@ -90,8 +90,8 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) unit_size = AV_RB16(extradata); total_size += unit_size + 4; if (total_size > INT_MAX - padding || - extradata + 2 + unit_size > avctx->extradata + - avctx->extradata_size) { + extradata + 2 + unit_size > ctx->par_in->extradata + + ctx->par_in->extradata_size) { av_free(out); return AVERROR(EINVAL); } @@ -109,103 +109,137 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) } if (out) - memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (!sps_seen) - av_log(avctx, AV_LOG_WARNING, + av_log(ctx, AV_LOG_WARNING, "Warning: SPS NALU missing or invalid. " "The resulting stream may not play.\n"); if (!pps_seen) - av_log(avctx, AV_LOG_WARNING, + av_log(ctx, AV_LOG_WARNING, "Warning: PPS NALU missing or invalid. " "The resulting stream may not play.\n"); - av_free(avctx->extradata); - avctx->extradata = out; - avctx->extradata_size = total_size; + av_freep(&ctx->par_out->extradata); + ctx->par_out->extradata = out; + ctx->par_out->extradata_size = total_size; return length_size; } -static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, - AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int keyframe) +static int h264_mp4toannexb_init(AVBSFContext *ctx) +{ + H264BSFContext *s = ctx->priv_data; + int extra_size = ctx->par_in->extradata_size; + int ret; + + /* retrieve sps and pps NAL units from extradata */ + if (!extra_size || + (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) || + (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) { + av_log(ctx, AV_LOG_VERBOSE, + "The input looks like it is Annex B already\n"); + } else if (extra_size >= 6) { + ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + return ret; + + s->length_size = ret; + s->first_idr = 1; + s->extradata_parsed = 1; + } else { + av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) { - H264BSFContext *ctx = bsfc->priv_data; + H264BSFContext *s = ctx->priv_data; + + AVPacket *in; uint8_t unit_type; int32_t nal_size; uint32_t cumul_size = 0; - const uint8_t *buf_end = buf + buf_size; + const uint8_t *buf; + const uint8_t *buf_end; + int buf_size; int ret = 0; + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + /* nothing to filter */ - if (!avctx->extradata || avctx->extradata_size < 6) { - *poutbuf = (uint8_t *)buf; - *poutbuf_size = buf_size; + if (!s->extradata_parsed) { + av_packet_move_ref(out, in); + av_packet_free(&in); return 0; } - /* retrieve sps and pps NAL units from extradata */ - if (!ctx->extradata_parsed) { - ret = h264_extradata_to_annexb(avctx, FF_INPUT_BUFFER_PADDING_SIZE); - if (ret < 0) - return ret; - ctx->length_size = ret; - ctx->first_idr = 1; - ctx->extradata_parsed = 1; - } + buf = in->data; + buf_size = in->size; + buf_end = in->data + in->size; - *poutbuf_size = 0; - *poutbuf = NULL; do { - if (buf + ctx->length_size > buf_end) + if (buf + s->length_size > buf_end) goto fail; - if (ctx->length_size == 1) { + if (s->length_size == 1) { nal_size = buf[0]; - } else if (ctx->length_size == 2) { + } else if (s->length_size == 2) { nal_size = AV_RB16(buf); } else nal_size = AV_RB32(buf); - buf += ctx->length_size; + buf += s->length_size; unit_type = *buf & 0x1f; if (buf + nal_size > buf_end || nal_size < 0) goto fail; /* prepend only to the first type 5 NAL unit of an IDR picture */ - if (ctx->first_idr && unit_type == 5) { - if (alloc_and_copy(poutbuf, poutbuf_size, - avctx->extradata, avctx->extradata_size, + if (s->first_idr && unit_type == 5) { + if (alloc_and_copy(out, + ctx->par_out->extradata, ctx->par_out->extradata_size, buf, nal_size) < 0) goto fail; - ctx->first_idr = 0; + s->first_idr = 0; } else { - if (alloc_and_copy(poutbuf, poutbuf_size, + if (alloc_and_copy(out, NULL, 0, buf, nal_size) < 0) goto fail; - if (!ctx->first_idr && unit_type == 1) - ctx->first_idr = 1; + if (!s->first_idr && unit_type == 1) + s->first_idr = 1; } buf += nal_size; - cumul_size += nal_size + ctx->length_size; + cumul_size += nal_size + s->length_size; } while (cumul_size < buf_size); - return 1; + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; fail: - av_freep(poutbuf); - *poutbuf_size = 0; - return AVERROR(EINVAL); + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + + return ret; } -AVBitStreamFilter ff_h264_mp4toannexb_bsf = { - "h264_mp4toannexb", - sizeof(H264BSFContext), - h264_mp4toannexb_filter, +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_H264, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_h264_mp4toannexb_bsf = { + .name = "h264_mp4toannexb", + .priv_data_size = sizeof(H264BSFContext), + .init = h264_mp4toannexb_init, + .filter = h264_mp4toannexb_filter, + .codec_ids = codec_ids, }; diff --git a/libavcodec/h264_mvpred.h b/libavcodec/h264_mvpred.h index f7c3887..83b1ea6 100644 --- a/libavcodec/h264_mvpred.h +++ b/libavcodec/h264_mvpred.h @@ -1,5 +1,5 @@ /* - * H.26L/H.264/AVC/JVT/14496-10/... motion vector predicion + * H.26L/H.264/AVC/JVT/14496-10/... motion vector prediction * Copyright (c) 2003 Michael Niedermayer * * This file is part of Libav. @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 motion vector predicion. + * H.264 / AVC / MPEG-4 part10 motion vector prediction. * @author Michael Niedermayer */ @@ -30,15 +30,16 @@ #include "internal.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" #include "mpegutils.h" #include -static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C, +static av_always_inline int fetch_diagonal_mv(const H264Context *h, H264SliceContext *sl, + const int16_t **C, int i, int list, int part_width) { - const int topright_ref = h->ref_cache[list][i - 8 + part_width]; + const int topright_ref = sl->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 */ @@ -49,38 +50,38 @@ static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C, if (!USES_LIST(mb_type, list)) \ return LIST_NOT_USED; \ mv = h->cur_pic_ptr->motion_val[list][h->mb2b_xy[xy] + 3 + y4 * h->b_stride]; \ - h->mv_cache[list][scan8[0] - 2][0] = mv[0]; \ - h->mv_cache[list][scan8[0] - 2][1] = mv[1] MV_OP; \ + sl->mv_cache[list][scan8[0] - 2][0] = mv[0]; \ + sl->mv_cache[list][scan8[0] - 2][1] = mv[1] MV_OP; \ return h->cur_pic_ptr->ref_index[list][4 * xy + 1 + (y4 & ~1)] REF_OP; if (topright_ref == PART_NOT_AVAILABLE && i >= scan8[0] + 8 && (i & 7) == 4 - && h->ref_cache[list][scan8[0] - 1] != PART_NOT_AVAILABLE) { + && sl->ref_cache[list][scan8[0] - 1] != PART_NOT_AVAILABLE) { const uint32_t *mb_types = h->cur_pic_ptr->mb_type; const int16_t *mv; - AV_ZERO32(h->mv_cache[list][scan8[0] - 2]); - *C = h->mv_cache[list][scan8[0] - 2]; + AV_ZERO32(sl->mv_cache[list][scan8[0] - 2]); + *C = sl->mv_cache[list][scan8[0] - 2]; - if (!MB_FIELD(h) && IS_INTERLACED(h->left_type[0])) { - SET_DIAG_MV(* 2, >> 1, h->left_mb_xy[0] + h->mb_stride, - (h->mb_y & 1) * 2 + (i >> 5)); + if (!MB_FIELD(sl) && IS_INTERLACED(sl->left_type[0])) { + SET_DIAG_MV(* 2, >> 1, sl->left_mb_xy[0] + h->mb_stride, + (sl->mb_y & 1) * 2 + (i >> 5)); } - if (MB_FIELD(h) && !IS_INTERLACED(h->left_type[0])) { + if (MB_FIELD(sl) && !IS_INTERLACED(sl->left_type[0])) { // left shift will turn LIST_NOT_USED into PART_NOT_AVAILABLE, but that's OK. - SET_DIAG_MV(/ 2, << 1, h->left_mb_xy[i >= 36], ((i >> 2)) & 3); + SET_DIAG_MV(/ 2, << 1, sl->left_mb_xy[i >= 36], ((i >> 2)) & 3); } } #undef SET_DIAG_MV } if (topright_ref != PART_NOT_AVAILABLE) { - *C = h->mv_cache[list][i - 8 + part_width]; + *C = sl->mv_cache[list][i - 8 + part_width]; return topright_ref; } else { - tprintf(h->avctx, "topright MV not available\n"); + ff_tlog(h->avctx, "topright MV not available\n"); - *C = h->mv_cache[list][i - 8 - 1]; - return h->ref_cache[list][i - 8 - 1]; + *C = sl->mv_cache[list][i - 8 - 1]; + return sl->ref_cache[list][i - 8 - 1]; } } @@ -91,15 +92,17 @@ static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C, * @param mx the x component of the predicted motion vector * @param my the y component of the predicted motion vector */ -static av_always_inline void pred_motion(H264Context *const h, int n, +static av_always_inline void pred_motion(const H264Context *const h, + H264SliceContext *sl, + 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 int top_ref = sl->ref_cache[list][index8 - 8]; + const int left_ref = sl->ref_cache[list][index8 - 1]; + const int16_t *const A = sl->mv_cache[list][index8 - 1]; + const int16_t *const B = sl->mv_cache[list][index8 - 8]; const int16_t *C; int diagonal_ref, match_count; @@ -113,9 +116,9 @@ static av_always_inline void pred_motion(H264Context *const h, int n, * . . . L . . . . */ - diagonal_ref = fetch_diagonal_mv(h, &C, index8, list, part_width); + diagonal_ref = fetch_diagonal_mv(h, sl, &C, index8, list, part_width); match_count = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref); - tprintf(h->avctx, "pred_motion match_count=%d\n", match_count); + ff_tlog(h->avctx, "pred_motion match_count=%d\n", match_count); if (match_count > 1) { //most common *mx = mid_pred(A[0], B[0], C[0]); *my = mid_pred(A[1], B[1], C[1]); @@ -142,10 +145,10 @@ static av_always_inline void pred_motion(H264Context *const h, int n, } } - tprintf(h->avctx, + ff_tlog(h->avctx, "pred_motion (%2d %2d %2d) (%2d %2d %2d) (%2d %2d %2d) -> (%2d %2d %2d) at %2d %2d %d list %d\n", top_ref, B[0], B[1], diagonal_ref, C[0], C[1], left_ref, - A[0], A[1], ref, *mx, *my, h->mb_x, h->mb_y, n, list); + A[0], A[1], ref, *mx, *my, sl->mb_x, sl->mb_y, n, list); } /** @@ -154,16 +157,17 @@ static av_always_inline void pred_motion(H264Context *const h, int n, * @param mx the x component of the predicted motion vector * @param my the y component of the predicted motion vector */ -static av_always_inline void pred_16x8_motion(H264Context *const h, +static av_always_inline void pred_16x8_motion(const H264Context *const h, + H264SliceContext *sl, 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]; + const int top_ref = sl->ref_cache[list][scan8[0] - 8]; + const int16_t *const B = sl->mv_cache[list][scan8[0] - 8]; - tprintf(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", - top_ref, B[0], B[1], h->mb_x, h->mb_y, n, list); + ff_tlog(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", + top_ref, B[0], B[1], sl->mb_x, sl->mb_y, n, list); if (top_ref == ref) { *mx = B[0]; @@ -171,11 +175,11 @@ static av_always_inline void pred_16x8_motion(H264Context *const h, 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]; + const int left_ref = sl->ref_cache[list][scan8[8] - 1]; + const int16_t *const A = sl->mv_cache[list][scan8[8] - 1]; - tprintf(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", - left_ref, A[0], A[1], h->mb_x, h->mb_y, n, list); + ff_tlog(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", + left_ref, A[0], A[1], sl->mb_x, sl->mb_y, n, list); if (left_ref == ref) { *mx = A[0]; @@ -185,7 +189,7 @@ static av_always_inline void pred_16x8_motion(H264Context *const h, } //RARE - pred_motion(h, n, 4, list, ref, mx, my); + pred_motion(h, sl, n, 4, list, ref, mx, my); } /** @@ -194,16 +198,17 @@ static av_always_inline void pred_16x8_motion(H264Context *const h, * @param mx the x component of the predicted motion vector * @param my the y component of the predicted motion vector */ -static av_always_inline void pred_8x16_motion(H264Context *const h, +static av_always_inline void pred_8x16_motion(const H264Context *const h, + H264SliceContext *sl, 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]; + const int left_ref = sl->ref_cache[list][scan8[0] - 1]; + const int16_t *const A = sl->mv_cache[list][scan8[0] - 1]; - tprintf(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", - left_ref, A[0], A[1], h->mb_x, h->mb_y, n, list); + ff_tlog(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", + left_ref, A[0], A[1], sl->mb_x, sl->mb_y, n, list); if (left_ref == ref) { *mx = A[0]; @@ -214,10 +219,10 @@ static av_always_inline void pred_8x16_motion(H264Context *const h, const int16_t *C; int diagonal_ref; - diagonal_ref = fetch_diagonal_mv(h, &C, scan8[4], list, 2); + diagonal_ref = fetch_diagonal_mv(h, sl, &C, scan8[4], list, 2); - tprintf(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", - diagonal_ref, C[0], C[1], h->mb_x, h->mb_y, n, list); + ff_tlog(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", + diagonal_ref, C[0], C[1], sl->mb_x, sl->mb_y, n, list); if (diagonal_ref == ref) { *mx = C[0]; @@ -227,12 +232,12 @@ static av_always_inline void pred_8x16_motion(H264Context *const h, } //RARE - pred_motion(h, n, 2, list, ref, mx, my); + pred_motion(h, sl, n, 2, list, ref, mx, my); } #define FIX_MV_MBAFF(type, refn, mvn, idx) \ if (FRAME_MBAFF(h)) { \ - if (MB_FIELD(h)) { \ + if (MB_FIELD(sl)) { \ if (!IS_INTERLACED(type)) { \ refn <<= 1; \ AV_COPY32(mvbuf[idx], mvn); \ @@ -249,7 +254,8 @@ static av_always_inline void pred_8x16_motion(H264Context *const h, } \ } -static av_always_inline void pred_pskip_motion(H264Context *const h) +static av_always_inline void pred_pskip_motion(const H264Context *const h, + H264SliceContext *sl) { DECLARE_ALIGNED(4, static const int16_t, zeromv)[2] = { 0 }; DECLARE_ALIGNED(4, int16_t, mvbuf)[3][2]; @@ -259,57 +265,57 @@ static av_always_inline void pred_pskip_motion(H264Context *const h) const int16_t *A, *B, *C; int b_stride = h->b_stride; - fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1); + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1); /* To avoid doing an entire fill_decode_caches, we inline the relevant * parts here. * FIXME: this is a partial duplicate of the logic in fill_decode_caches, * but it's faster this way. Is there a way to avoid this duplication? */ - if (USES_LIST(h->left_type[LTOP], 0)) { - left_ref = ref[4 * h->left_mb_xy[LTOP] + 1 + (h->left_block[0] & ~1)]; - A = mv[h->mb2b_xy[h->left_mb_xy[LTOP]] + 3 + b_stride * h->left_block[0]]; - FIX_MV_MBAFF(h->left_type[LTOP], left_ref, A, 0); + if (USES_LIST(sl->left_type[LTOP], 0)) { + left_ref = ref[4 * sl->left_mb_xy[LTOP] + 1 + (sl->left_block[0] & ~1)]; + A = mv[h->mb2b_xy[sl->left_mb_xy[LTOP]] + 3 + b_stride * sl->left_block[0]]; + FIX_MV_MBAFF(sl->left_type[LTOP], left_ref, A, 0); if (!(left_ref | AV_RN32A(A))) goto zeromv; - } else if (h->left_type[LTOP]) { + } else if (sl->left_type[LTOP]) { left_ref = LIST_NOT_USED; A = zeromv; } else { goto zeromv; } - if (USES_LIST(h->top_type, 0)) { - top_ref = ref[4 * h->top_mb_xy + 2]; - B = mv[h->mb2b_xy[h->top_mb_xy] + 3 * b_stride]; - FIX_MV_MBAFF(h->top_type, top_ref, B, 1); + if (USES_LIST(sl->top_type, 0)) { + top_ref = ref[4 * sl->top_mb_xy + 2]; + B = mv[h->mb2b_xy[sl->top_mb_xy] + 3 * b_stride]; + FIX_MV_MBAFF(sl->top_type, top_ref, B, 1); if (!(top_ref | AV_RN32A(B))) goto zeromv; - } else if (h->top_type) { + } else if (sl->top_type) { top_ref = LIST_NOT_USED; B = zeromv; } else { goto zeromv; } - tprintf(h->avctx, "pred_pskip: (%d) (%d) at %2d %2d\n", - top_ref, left_ref, h->mb_x, h->mb_y); + ff_tlog(h->avctx, "pred_pskip: (%d) (%d) at %2d %2d\n", + top_ref, left_ref, sl->mb_x, sl->mb_y); - if (USES_LIST(h->topright_type, 0)) { - diagonal_ref = ref[4 * h->topright_mb_xy + 2]; - C = mv[h->mb2b_xy[h->topright_mb_xy] + 3 * b_stride]; - FIX_MV_MBAFF(h->topright_type, diagonal_ref, C, 2); - } else if (h->topright_type) { + if (USES_LIST(sl->topright_type, 0)) { + diagonal_ref = ref[4 * sl->topright_mb_xy + 2]; + C = mv[h->mb2b_xy[sl->topright_mb_xy] + 3 * b_stride]; + FIX_MV_MBAFF(sl->topright_type, diagonal_ref, C, 2); + } else if (sl->topright_type) { diagonal_ref = LIST_NOT_USED; C = zeromv; } else { - if (USES_LIST(h->topleft_type, 0)) { - diagonal_ref = ref[4 * h->topleft_mb_xy + 1 + - (h->topleft_partition & 2)]; - C = mv[h->mb2b_xy[h->topleft_mb_xy] + 3 + b_stride + - (h->topleft_partition & 2 * b_stride)]; - FIX_MV_MBAFF(h->topleft_type, diagonal_ref, C, 2); - } else if (h->topleft_type) { + if (USES_LIST(sl->topleft_type, 0)) { + diagonal_ref = ref[4 * sl->topleft_mb_xy + 1 + + (sl->topleft_partition & 2)]; + C = mv[h->mb2b_xy[sl->topleft_mb_xy] + 3 + b_stride + + (sl->topleft_partition & 2 * b_stride)]; + FIX_MV_MBAFF(sl->topleft_type, diagonal_ref, C, 2); + } else if (sl->topleft_type) { diagonal_ref = LIST_NOT_USED; C = zeromv; } else { @@ -319,7 +325,7 @@ static av_always_inline void pred_pskip_motion(H264Context *const h) } match_count = !diagonal_ref + !top_ref + !left_ref; - tprintf(h->avctx, "pred_pskip_motion match_count=%d\n", match_count); + ff_tlog(h->avctx, "pred_pskip_motion match_count=%d\n", match_count); if (match_count > 1) { mx = mid_pred(A[0], B[0], C[0]); my = mid_pred(A[1], B[1], C[1]); @@ -339,17 +345,17 @@ static av_always_inline void pred_pskip_motion(H264Context *const h) my = mid_pred(A[1], B[1], C[1]); } - fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx, my), 4); + fill_rectangle(sl->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx, my), 4); return; zeromv: - fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); + fill_rectangle(sl->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); return; } -static void fill_decode_neighbors(H264Context *h, int mb_type) +static void fill_decode_neighbors(const H264Context *h, H264SliceContext *sl, int mb_type) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; static const uint8_t left_block_options[4][32] = { { 0, 1, 2, 3, 7, 10, 8, 11, 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, 3 + 3 * 4, 1 + 4 * 4, 1 + 8 * 4, 1 + 5 * 4, 1 + 9 * 4 }, @@ -358,9 +364,9 @@ static void fill_decode_neighbors(H264Context *h, int mb_type) { 0, 2, 0, 2, 7, 10, 7, 10, 3 + 0 * 4, 3 + 2 * 4, 3 + 0 * 4, 3 + 2 * 4, 1 + 4 * 4, 1 + 8 * 4, 1 + 4 * 4, 1 + 8 * 4 } }; - h->topleft_partition = -1; + sl->topleft_partition = -1; - top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); + top_xy = mb_xy - (h->mb_stride << MB_FIELD(sl)); /* Wow, what a mess, why didn't they simplify the interlacing & intra * stuff, I can't imagine that these complex rules are worth it. */ @@ -368,22 +374,22 @@ static void fill_decode_neighbors(H264Context *h, int mb_type) topleft_xy = top_xy - 1; topright_xy = top_xy + 1; left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; - h->left_block = left_block_options[0]; + sl->left_block = left_block_options[0]; if (FRAME_MBAFF(h)) { const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); const int curr_mb_field_flag = IS_INTERLACED(mb_type); - if (h->mb_y & 1) { + if (sl->mb_y & 1) { if (left_mb_field_flag != curr_mb_field_flag) { left_xy[LBOT] = left_xy[LTOP] = mb_xy - h->mb_stride - 1; if (curr_mb_field_flag) { left_xy[LBOT] += h->mb_stride; - h->left_block = left_block_options[3]; + sl->left_block = left_block_options[3]; } else { topleft_xy += h->mb_stride; /* take top left mv from the middle of the mb, as opposed * to all other modes which use the bottom right partition */ - h->topleft_partition = 0; - h->left_block = left_block_options[1]; + sl->topleft_partition = 0; + sl->left_block = left_block_options[1]; } } } else { @@ -395,129 +401,129 @@ static void fill_decode_neighbors(H264Context *h, int mb_type) if (left_mb_field_flag != curr_mb_field_flag) { if (curr_mb_field_flag) { left_xy[LBOT] += h->mb_stride; - h->left_block = left_block_options[3]; + sl->left_block = left_block_options[3]; } else { - h->left_block = left_block_options[2]; + sl->left_block = left_block_options[2]; } } } } - h->topleft_mb_xy = topleft_xy; - h->top_mb_xy = top_xy; - h->topright_mb_xy = topright_xy; - h->left_mb_xy[LTOP] = left_xy[LTOP]; - h->left_mb_xy[LBOT] = left_xy[LBOT]; + sl->topleft_mb_xy = topleft_xy; + sl->top_mb_xy = top_xy; + sl->topright_mb_xy = topright_xy; + sl->left_mb_xy[LTOP] = left_xy[LTOP]; + sl->left_mb_xy[LBOT] = left_xy[LBOT]; //FIXME do we need all in the context? - h->topleft_type = h->cur_pic.mb_type[topleft_xy]; - h->top_type = h->cur_pic.mb_type[top_xy]; - h->topright_type = h->cur_pic.mb_type[topright_xy]; - h->left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; - h->left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; + sl->topleft_type = h->cur_pic.mb_type[topleft_xy]; + sl->top_type = h->cur_pic.mb_type[top_xy]; + sl->topright_type = h->cur_pic.mb_type[topright_xy]; + sl->left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; + sl->left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; if (FMO) { - if (h->slice_table[topleft_xy] != h->slice_num) - h->topleft_type = 0; - if (h->slice_table[top_xy] != h->slice_num) - h->top_type = 0; - if (h->slice_table[left_xy[LTOP]] != h->slice_num) - h->left_type[LTOP] = h->left_type[LBOT] = 0; + if (h->slice_table[topleft_xy] != sl->slice_num) + sl->topleft_type = 0; + if (h->slice_table[top_xy] != sl->slice_num) + sl->top_type = 0; + if (h->slice_table[left_xy[LTOP]] != sl->slice_num) + sl->left_type[LTOP] = sl->left_type[LBOT] = 0; } else { - if (h->slice_table[topleft_xy] != h->slice_num) { - h->topleft_type = 0; - if (h->slice_table[top_xy] != h->slice_num) - h->top_type = 0; - if (h->slice_table[left_xy[LTOP]] != h->slice_num) - h->left_type[LTOP] = h->left_type[LBOT] = 0; + if (h->slice_table[topleft_xy] != sl->slice_num) { + sl->topleft_type = 0; + if (h->slice_table[top_xy] != sl->slice_num) + sl->top_type = 0; + if (h->slice_table[left_xy[LTOP]] != sl->slice_num) + sl->left_type[LTOP] = sl->left_type[LBOT] = 0; } } - if (h->slice_table[topright_xy] != h->slice_num) - h->topright_type = 0; + if (h->slice_table[topright_xy] != sl->slice_num) + sl->topright_type = 0; } -static void fill_decode_caches(H264Context *h, int mb_type) +static void fill_decode_caches(const H264Context *h, H264SliceContext *sl, int mb_type) { int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; int topleft_type, top_type, topright_type, left_type[LEFT_MBS]; - const uint8_t *left_block = h->left_block; + const uint8_t *left_block = sl->left_block; int i; uint8_t *nnz; uint8_t *nnz_cache; - topleft_xy = h->topleft_mb_xy; - top_xy = h->top_mb_xy; - topright_xy = h->topright_mb_xy; - left_xy[LTOP] = h->left_mb_xy[LTOP]; - left_xy[LBOT] = h->left_mb_xy[LBOT]; - topleft_type = h->topleft_type; - top_type = h->top_type; - topright_type = h->topright_type; - left_type[LTOP] = h->left_type[LTOP]; - left_type[LBOT] = h->left_type[LBOT]; + topleft_xy = sl->topleft_mb_xy; + top_xy = sl->top_mb_xy; + topright_xy = sl->topright_mb_xy; + left_xy[LTOP] = sl->left_mb_xy[LTOP]; + left_xy[LBOT] = sl->left_mb_xy[LBOT]; + topleft_type = sl->topleft_type; + top_type = sl->top_type; + topright_type = sl->topright_type; + left_type[LTOP] = sl->left_type[LTOP]; + left_type[LBOT] = sl->left_type[LBOT]; if (!IS_SKIP(mb_type)) { if (IS_INTRA(mb_type)) { - int type_mask = h->pps.constrained_intra_pred ? IS_INTRA(-1) : -1; - h->topleft_samples_available = - h->top_samples_available = - h->left_samples_available = 0xFFFF; - h->topright_samples_available = 0xEEEA; + int type_mask = h->ps.pps->constrained_intra_pred ? IS_INTRA(-1) : -1; + sl->topleft_samples_available = + sl->top_samples_available = + sl->left_samples_available = 0xFFFF; + sl->topright_samples_available = 0xEEEA; if (!(top_type & type_mask)) { - h->topleft_samples_available = 0xB3FF; - h->top_samples_available = 0x33FF; - h->topright_samples_available = 0x26EA; + sl->topleft_samples_available = 0xB3FF; + sl->top_samples_available = 0x33FF; + sl->topright_samples_available = 0x26EA; } if (IS_INTERLACED(mb_type) != IS_INTERLACED(left_type[LTOP])) { if (IS_INTERLACED(mb_type)) { if (!(left_type[LTOP] & type_mask)) { - h->topleft_samples_available &= 0xDFFF; - h->left_samples_available &= 0x5FFF; + sl->topleft_samples_available &= 0xDFFF; + sl->left_samples_available &= 0x5FFF; } if (!(left_type[LBOT] & type_mask)) { - h->topleft_samples_available &= 0xFF5F; - h->left_samples_available &= 0xFF5F; + sl->topleft_samples_available &= 0xFF5F; + sl->left_samples_available &= 0xFF5F; } } else { int left_typei = h->cur_pic.mb_type[left_xy[LTOP] + h->mb_stride]; assert(left_xy[LTOP] == left_xy[LBOT]); if (!((left_typei & type_mask) && (left_type[LTOP] & type_mask))) { - h->topleft_samples_available &= 0xDF5F; - h->left_samples_available &= 0x5F5F; + sl->topleft_samples_available &= 0xDF5F; + sl->left_samples_available &= 0x5F5F; } } } else { if (!(left_type[LTOP] & type_mask)) { - h->topleft_samples_available &= 0xDF5F; - h->left_samples_available &= 0x5F5F; + sl->topleft_samples_available &= 0xDF5F; + sl->left_samples_available &= 0x5F5F; } } if (!(topleft_type & type_mask)) - h->topleft_samples_available &= 0x7FFF; + sl->topleft_samples_available &= 0x7FFF; if (!(topright_type & type_mask)) - h->topright_samples_available &= 0xFBFF; + sl->topright_samples_available &= 0xFBFF; if (IS_INTRA4x4(mb_type)) { if (IS_INTRA4x4(top_type)) { - AV_COPY32(h->intra4x4_pred_mode_cache + 4 + 8 * 0, h->intra4x4_pred_mode + h->mb2br_xy[top_xy]); + AV_COPY32(sl->intra4x4_pred_mode_cache + 4 + 8 * 0, sl->intra4x4_pred_mode + h->mb2br_xy[top_xy]); } else { - h->intra4x4_pred_mode_cache[4 + 8 * 0] = - h->intra4x4_pred_mode_cache[5 + 8 * 0] = - h->intra4x4_pred_mode_cache[6 + 8 * 0] = - h->intra4x4_pred_mode_cache[7 + 8 * 0] = 2 - 3 * !(top_type & type_mask); + sl->intra4x4_pred_mode_cache[4 + 8 * 0] = + sl->intra4x4_pred_mode_cache[5 + 8 * 0] = + sl->intra4x4_pred_mode_cache[6 + 8 * 0] = + sl->intra4x4_pred_mode_cache[7 + 8 * 0] = 2 - 3 * !(top_type & type_mask); } for (i = 0; i < 2; i++) { if (IS_INTRA4x4(left_type[LEFT(i)])) { - int8_t *mode = h->intra4x4_pred_mode + h->mb2br_xy[left_xy[LEFT(i)]]; - h->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = mode[6 - left_block[0 + 2 * i]]; - h->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = mode[6 - left_block[1 + 2 * i]]; + int8_t *mode = sl->intra4x4_pred_mode + h->mb2br_xy[left_xy[LEFT(i)]]; + sl->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = mode[6 - left_block[0 + 2 * i]]; + sl->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = mode[6 - left_block[1 + 2 * i]]; } else { - h->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = - h->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = 2 - 3 * !(left_type[LEFT(i)] & type_mask); + sl->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = + sl->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = 2 - 3 * !(left_type[LEFT(i)] & type_mask); } } } @@ -533,7 +539,7 @@ static void fill_decode_caches(H264Context *h, int mb_type) */ /* FIXME: constraint_intra_pred & partitioning & nnz * (let us hope this is just a typo in the spec) */ - nnz_cache = h->non_zero_count_cache; + nnz_cache = sl->non_zero_count_cache; if (top_type) { nnz = h->non_zero_count[top_xy]; AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[4 * 3]); @@ -583,31 +589,31 @@ static void fill_decode_caches(H264Context *h, int mb_type) if (CABAC(h)) { // top_cbp if (top_type) - h->top_cbp = h->cbp_table[top_xy]; + sl->top_cbp = h->cbp_table[top_xy]; else - h->top_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; + sl->top_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; // left_cbp if (left_type[LTOP]) { - h->left_cbp = (h->cbp_table[left_xy[LTOP]] & 0x7F0) | + sl->left_cbp = (h->cbp_table[left_xy[LTOP]] & 0x7F0) | ((h->cbp_table[left_xy[LTOP]] >> (left_block[0] & (~1))) & 2) | (((h->cbp_table[left_xy[LBOT]] >> (left_block[2] & (~1))) & 2) << 2); } else { - h->left_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; + sl->left_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; } } } - if (IS_INTER(mb_type) || (IS_DIRECT(mb_type) && h->direct_spatial_mv_pred)) { + if (IS_INTER(mb_type) || (IS_DIRECT(mb_type) && sl->direct_spatial_mv_pred)) { int list; int b_stride = h->b_stride; - for (list = 0; list < h->list_count; list++) { - int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; + for (list = 0; list < sl->list_count; list++) { + int8_t *ref_cache = &sl->ref_cache[list][scan8[0]]; int8_t *ref = h->cur_pic.ref_index[list]; - int16_t(*mv_cache)[2] = &h->mv_cache[list][scan8[0]]; + int16_t(*mv_cache)[2] = &sl->mv_cache[list][scan8[0]]; int16_t(*mv)[2] = h->cur_pic.motion_val[list]; if (!USES_LIST(mb_type, list)) continue; - assert(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred)); + assert(!(IS_DIRECT(mb_type) && !sl->direct_spatial_mv_pred)); if (USES_LIST(top_type, list)) { const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; @@ -667,8 +673,8 @@ static void fill_decode_caches(H264Context *h, int mb_type) if (ref_cache[4 - 1 * 8] < 0) { if (USES_LIST(topleft_type, list)) { const int b_xy = h->mb2b_xy[topleft_xy] + 3 + b_stride + - (h->topleft_partition & 2 * b_stride); - const int b8_xy = 4 * topleft_xy + 1 + (h->topleft_partition & 2); + (sl->topleft_partition & 2 * b_stride); + const int b8_xy = 4 * topleft_xy + 1 + (sl->topleft_partition & 2); AV_COPY32(mv_cache[-1 - 1 * 8], mv[b_xy]); ref_cache[-1 - 1 * 8] = ref[b8_xy]; } else { @@ -682,8 +688,8 @@ static void fill_decode_caches(H264Context *h, int mb_type) continue; if (!(mb_type & (MB_TYPE_SKIP | MB_TYPE_DIRECT2))) { - uint8_t(*mvd_cache)[2] = &h->mvd_cache[list][scan8[0]]; - uint8_t(*mvd)[2] = h->mvd_table[list]; + uint8_t(*mvd_cache)[2] = &sl->mvd_cache[list][scan8[0]]; + uint8_t(*mvd)[2] = sl->mvd_table[list]; ref_cache[2 + 8 * 0] = ref_cache[2 + 8 * 2] = PART_NOT_AVAILABLE; AV_ZERO32(mv_cache[2 + 8 * 0]); @@ -714,8 +720,8 @@ static void fill_decode_caches(H264Context *h, int mb_type) } AV_ZERO16(mvd_cache[2 + 8 * 0]); AV_ZERO16(mvd_cache[2 + 8 * 2]); - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { - uint8_t *direct_cache = &h->direct_cache[scan8[0]]; + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { + uint8_t *direct_cache = &sl->direct_cache[scan8[0]]; uint8_t *direct_table = h->direct_table; fill_rectangle(direct_cache, 4, 4, 8, MB_TYPE_16x16 >> 1, 1); @@ -761,13 +767,13 @@ static void fill_decode_caches(H264Context *h, int mb_type) MAP_F2F(scan8[0] - 1 + 3 * 8, left_type[LBOT]) if (FRAME_MBAFF(h)) { - if (MB_FIELD(h)) { + if (MB_FIELD(sl)) { #define MAP_F2F(idx, mb_type) \ - if (!IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ - h->ref_cache[list][idx] <<= 1; \ - h->mv_cache[list][idx][1] /= 2; \ - h->mvd_cache[list][idx][1] >>= 1; \ + if (!IS_INTERLACED(mb_type) && sl->ref_cache[list][idx] >= 0) { \ + sl->ref_cache[list][idx] <<= 1; \ + sl->mv_cache[list][idx][1] /= 2; \ + sl->mvd_cache[list][idx][1] >>= 1; \ } MAP_MVS @@ -775,10 +781,10 @@ static void fill_decode_caches(H264Context *h, int mb_type) #undef MAP_F2F #define MAP_F2F(idx, mb_type) \ - if (IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ - h->ref_cache[list][idx] >>= 1; \ - h->mv_cache[list][idx][1] <<= 1; \ - h->mvd_cache[list][idx][1] <<= 1; \ + if (IS_INTERLACED(mb_type) && sl->ref_cache[list][idx] >= 0) { \ + sl->ref_cache[list][idx] >>= 1; \ + sl->mv_cache[list][idx][1] <<= 1; \ + sl->mvd_cache[list][idx][1] <<= 1; \ } MAP_MVS @@ -788,43 +794,43 @@ static void fill_decode_caches(H264Context *h, int mb_type) } } - h->neighbor_transform_size = !!IS_8x8DCT(top_type) + !!IS_8x8DCT(left_type[LTOP]); + sl->neighbor_transform_size = !!IS_8x8DCT(top_type) + !!IS_8x8DCT(left_type[LTOP]); } /** * decodes a P_SKIP or B_SKIP macroblock */ -static void av_unused decode_mb_skip(H264Context *h) +static void av_unused decode_mb_skip(const H264Context *h, H264SliceContext *sl) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; int mb_type = 0; memset(h->non_zero_count[mb_xy], 0, 48); - if (MB_FIELD(h)) + if (MB_FIELD(sl)) mb_type |= MB_TYPE_INTERLACED; - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { // just for fill_caches. pred_direct_motion will set the real mb_type mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 | MB_TYPE_SKIP; - if (h->direct_spatial_mv_pred) { - fill_decode_neighbors(h, mb_type); - fill_decode_caches(h, mb_type); //FIXME check what is needed and what not ... + if (sl->direct_spatial_mv_pred) { + fill_decode_neighbors(h, sl, mb_type); + fill_decode_caches(h, sl, mb_type); //FIXME check what is needed and what not ... } - ff_h264_pred_direct_motion(h, &mb_type); + ff_h264_pred_direct_motion(h, sl, &mb_type); mb_type |= MB_TYPE_SKIP; } else { mb_type |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_SKIP; - fill_decode_neighbors(h, mb_type); - pred_pskip_motion(h); + fill_decode_neighbors(h, sl, mb_type); + pred_pskip_motion(h, sl); } - write_back_motion(h, mb_type); + write_back_motion(h, sl, mb_type); h->cur_pic.mb_type[mb_xy] = mb_type; - h->cur_pic.qscale_table[mb_xy] = h->qscale; - h->slice_table[mb_xy] = h->slice_num; - h->prev_mb_skipped = 1; + h->cur_pic.qscale_table[mb_xy] = sl->qscale; + h->slice_table[mb_xy] = sl->slice_num; + sl->prev_mb_skipped = 1; } #endif /* AVCODEC_H264_MVPRED_H */ diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c new file mode 100644 index 0000000..d694558 --- /dev/null +++ b/libavcodec/h264_parse.c @@ -0,0 +1,488 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bytestream.h" +#include "get_bits.h" +#include "golomb.h" +#include "h264.h" +#include "h264dec.h" +#include "h264_parse.h" +#include "h264_ps.h" + +int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps, + const int *ref_count, int slice_type_nos, + H264PredWeightTable *pwt) +{ + int list, i, j; + int luma_def, chroma_def; + + pwt->use_weight = 0; + pwt->use_weight_chroma = 0; + pwt->luma_log2_weight_denom = get_ue_golomb(gb); + if (sps->chroma_format_idc) + pwt->chroma_log2_weight_denom = get_ue_golomb(gb); + luma_def = 1 << pwt->luma_log2_weight_denom; + chroma_def = 1 << pwt->chroma_log2_weight_denom; + + for (list = 0; list < 2; list++) { + pwt->luma_weight_flag[list] = 0; + pwt->chroma_weight_flag[list] = 0; + for (i = 0; i < ref_count[list]; i++) { + int luma_weight_flag, chroma_weight_flag; + + luma_weight_flag = get_bits1(gb); + if (luma_weight_flag) { + pwt->luma_weight[i][list][0] = get_se_golomb(gb); + pwt->luma_weight[i][list][1] = get_se_golomb(gb); + if (pwt->luma_weight[i][list][0] != luma_def || + pwt->luma_weight[i][list][1] != 0) { + pwt->use_weight = 1; + pwt->luma_weight_flag[list] = 1; + } + } else { + pwt->luma_weight[i][list][0] = luma_def; + pwt->luma_weight[i][list][1] = 0; + } + + if (sps->chroma_format_idc) { + chroma_weight_flag = get_bits1(gb); + if (chroma_weight_flag) { + int j; + for (j = 0; j < 2; j++) { + pwt->chroma_weight[i][list][j][0] = get_se_golomb(gb); + pwt->chroma_weight[i][list][j][1] = get_se_golomb(gb); + if (pwt->chroma_weight[i][list][j][0] != chroma_def || + pwt->chroma_weight[i][list][j][1] != 0) { + pwt->use_weight_chroma = 1; + pwt->chroma_weight_flag[list] = 1; + } + } + } else { + int j; + for (j = 0; j < 2; j++) { + pwt->chroma_weight[i][list][j][0] = chroma_def; + pwt->chroma_weight[i][list][j][1] = 0; + } + } + } + + // for MBAFF + pwt->luma_weight[16 + 2 * i][list][0] = pwt->luma_weight[16 + 2 * i + 1][list][0] = pwt->luma_weight[i][list][0]; + pwt->luma_weight[16 + 2 * i][list][1] = pwt->luma_weight[16 + 2 * i + 1][list][1] = pwt->luma_weight[i][list][1]; + for (j = 0; j < 2; j++) { + pwt->chroma_weight[16 + 2 * i][list][j][0] = pwt->chroma_weight[16 + 2 * i + 1][list][j][0] = pwt->chroma_weight[i][list][j][0]; + pwt->chroma_weight[16 + 2 * i][list][j][1] = pwt->chroma_weight[16 + 2 * i + 1][list][j][1] = pwt->chroma_weight[i][list][j][1]; + } + } + if (slice_type_nos != AV_PICTURE_TYPE_B) + break; + } + pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma; + return 0; +} + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra4x4_pred_mode(int8_t *pred_mode_cache, void *logctx, + int top_samples_available, int left_samples_available) +{ + 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 (!(top_samples_available & 0x8000)) { + for (i = 0; i < 4; i++) { + int status = top[pred_mode_cache[scan8[0] + i]]; + if (status < 0) { + av_log(logctx, AV_LOG_ERROR, + "top block unavailable for requested intra4x4 mode %d\n", + status); + return AVERROR_INVALIDDATA; + } else if (status) { + pred_mode_cache[scan8[0] + i] = status; + } + } + } + + if ((left_samples_available & 0x8888) != 0x8888) { + static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 }; + for (i = 0; i < 4; i++) + if (!(left_samples_available & mask[i])) { + int status = left[pred_mode_cache[scan8[0] + 8 * i]]; + if (status < 0) { + av_log(logctx, AV_LOG_ERROR, + "left block unavailable for requested intra4x4 mode %d\n", + status); + return AVERROR_INVALIDDATA; + } else if (status) { + pred_mode_cache[scan8[0] + 8 * i] = status; + } + } + } + + return 0; +} + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available, + int left_samples_available, + int mode, int is_chroma) +{ + static const int8_t top[4] = { LEFT_DC_PRED8x8, 1, -1, -1 }; + static const int8_t left[5] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 }; + + if (mode > 3U) { + av_log(logctx, AV_LOG_ERROR, + "out of range intra chroma pred mode\n"); + return AVERROR_INVALIDDATA; + } + + if (!(top_samples_available & 0x8000)) { + mode = top[mode]; + if (mode < 0) { + av_log(logctx, AV_LOG_ERROR, + "top block unavailable for requested intra mode\n"); + return AVERROR_INVALIDDATA; + } + } + + if ((left_samples_available & 0x8080) != 0x8080) { + mode = left[mode]; + if (is_chroma && (left_samples_available & 0x8080)) { + // mad cow disease mode, aka MBAFF + constrained_intra_pred + mode = ALZHEIMER_DC_L0T_PRED8x8 + + (!(left_samples_available & 0x8000)) + + 2 * (mode == DC_128_PRED8x8); + } + if (mode < 0) { + av_log(logctx, AV_LOG_ERROR, + "left block unavailable for requested intra mode\n"); + return AVERROR_INVALIDDATA; + } + } + + return mode; +} + +int ff_h264_parse_ref_count(int *plist_count, int ref_count[2], + GetBitContext *gb, const PPS *pps, + int slice_type_nos, int picture_structure) +{ + int list_count; + int num_ref_idx_active_override_flag, max_refs; + + // set defaults, might be overridden a few lines later + ref_count[0] = pps->ref_count[0]; + ref_count[1] = pps->ref_count[1]; + + if (slice_type_nos != AV_PICTURE_TYPE_I) { + num_ref_idx_active_override_flag = get_bits1(gb); + + if (num_ref_idx_active_override_flag) { + ref_count[0] = get_ue_golomb(gb) + 1; + if (ref_count[0] < 1) + goto fail; + if (slice_type_nos == AV_PICTURE_TYPE_B) { + ref_count[1] = get_ue_golomb(gb) + 1; + if (ref_count[1] < 1) + goto fail; + } + } + + if (slice_type_nos == AV_PICTURE_TYPE_B) + list_count = 2; + else + list_count = 1; + } else { + list_count = 0; + ref_count[0] = ref_count[1] = 0; + } + + max_refs = picture_structure == PICT_FRAME ? 16 : 32; + + if (ref_count[0] > max_refs || ref_count[1] > max_refs) + goto fail; + + *plist_count = list_count; + + return 0; +fail: + *plist_count = 0; + ref_count[0] = 0; + ref_count[1] = 0; + return AVERROR_INVALIDDATA; +} + +int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc, + const SPS *sps, H264POCContext *pc, + int picture_structure, int nal_ref_idc) +{ + const int max_frame_num = 1 << sps->log2_max_frame_num; + int field_poc[2]; + + pc->frame_num_offset = pc->prev_frame_num_offset; + if (pc->frame_num < pc->prev_frame_num) + pc->frame_num_offset += max_frame_num; + + if (sps->poc_type == 0) { + const int max_poc_lsb = 1 << sps->log2_max_poc_lsb; + + if (pc->poc_lsb < pc->prev_poc_lsb && + pc->prev_poc_lsb - pc->poc_lsb >= max_poc_lsb / 2) + pc->poc_msb = pc->prev_poc_msb + max_poc_lsb; + else if (pc->poc_lsb > pc->prev_poc_lsb && + pc->prev_poc_lsb - pc->poc_lsb < -max_poc_lsb / 2) + pc->poc_msb = pc->prev_poc_msb - max_poc_lsb; + else + pc->poc_msb = pc->prev_poc_msb; + field_poc[0] = + field_poc[1] = pc->poc_msb + pc->poc_lsb; + if (picture_structure == PICT_FRAME) + field_poc[1] += pc->delta_poc_bottom; + } else if (sps->poc_type == 1) { + int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc; + int i; + + if (sps->poc_cycle_length != 0) + abs_frame_num = pc->frame_num_offset + pc->frame_num; + else + abs_frame_num = 0; + + if (nal_ref_idc == 0 && abs_frame_num > 0) + abs_frame_num--; + + expected_delta_per_poc_cycle = 0; + for (i = 0; i < sps->poc_cycle_length; i++) + // FIXME integrate during sps parse + expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i]; + + if (abs_frame_num > 0) { + int poc_cycle_cnt = (abs_frame_num - 1) / sps->poc_cycle_length; + int frame_num_in_poc_cycle = (abs_frame_num - 1) % 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 + sps->offset_for_ref_frame[i]; + } else + expectedpoc = 0; + + if (nal_ref_idc == 0) + expectedpoc = expectedpoc + sps->offset_for_non_ref_pic; + + field_poc[0] = expectedpoc + pc->delta_poc[0]; + field_poc[1] = field_poc[0] + sps->offset_for_top_to_bottom_field; + + if (picture_structure == PICT_FRAME) + field_poc[1] += pc->delta_poc[1]; + } else { + int poc = 2 * (pc->frame_num_offset + pc->frame_num); + + if (!nal_ref_idc) + poc--; + + field_poc[0] = poc; + field_poc[1] = poc; + } + + if (picture_structure != PICT_BOTTOM_FIELD) + pic_field_poc[0] = field_poc[0]; + if (picture_structure != PICT_TOP_FIELD) + pic_field_poc[1] = field_poc[1]; + *pic_poc = FFMIN(pic_field_poc[0], pic_field_poc[1]); + + return 0; +} + +static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps, + int is_avc, void *logctx) +{ + H2645Packet pkt = { 0 }; + int i, ret = 0; + + ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264); + if (ret < 0) + goto fail; + + for (i = 0; i < pkt.nb_nals; i++) { + H2645NAL *nal = &pkt.nals[i]; + switch (nal->type) { + case H264_NAL_SPS: + ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps); + if (ret < 0) + goto fail; + break; + case H264_NAL_PPS: + ret = ff_h264_decode_picture_parameter_set(&nal->gb, logctx, ps, + nal->size_bits); + if (ret < 0) + goto fail; + break; + default: + av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n", + nal->type); + break; + } + } + +fail: + ff_h2645_packet_uninit(&pkt); + return ret; +} + +/* There are (invalid) samples in the wild with mp4-style extradata, where the + * parameter sets are stored unescaped (i.e. as RBSP). + * This function catches the parameter set decoding failure and tries again + * after escaping it */ +static int decode_extradata_ps_mp4(const uint8_t *buf, int buf_size, H264ParamSets *ps, + int err_recognition, void *logctx) +{ + int ret; + + ret = decode_extradata_ps(buf, buf_size, ps, 1, logctx); + if (ret < 0 && !(err_recognition & AV_EF_EXPLODE)) { + GetByteContext gbc; + PutByteContext pbc; + uint8_t *escaped_buf; + int escaped_buf_size; + + av_log(logctx, AV_LOG_WARNING, + "SPS decoding failure, trying again after escaping the NAL\n"); + + if (buf_size / 2 >= (INT16_MAX - AV_INPUT_BUFFER_PADDING_SIZE) / 3) + return AVERROR(ERANGE); + escaped_buf_size = buf_size * 3 / 2 + AV_INPUT_BUFFER_PADDING_SIZE; + escaped_buf = av_mallocz(escaped_buf_size); + if (!escaped_buf) + return AVERROR(ENOMEM); + + bytestream2_init(&gbc, buf, buf_size); + bytestream2_init_writer(&pbc, escaped_buf, escaped_buf_size); + + while (bytestream2_get_bytes_left(&gbc)) { + if (bytestream2_get_bytes_left(&gbc) >= 3 && + bytestream2_peek_be24(&gbc) <= 3) { + bytestream2_put_be24(&pbc, 3); + bytestream2_skip(&gbc, 2); + } else + bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc)); + } + + escaped_buf_size = bytestream2_tell_p(&pbc); + AV_WB16(escaped_buf, escaped_buf_size - 2); + + ret = decode_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx); + av_freep(&escaped_buf); + if (ret < 0) + return ret; + } + + return 0; +} + +int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps, + int *is_avc, int *nal_length_size, + int err_recognition, void *logctx) +{ + int ret; + + if (data[0] == 1) { + int i, cnt, nalsize; + const uint8_t *p = data; + + *is_avc = 1; + + if (size < 7) { + av_log(logctx, AV_LOG_ERROR, "avcC %d too short\n", size); + return AVERROR_INVALIDDATA; + } + + // Decode sps from avcC + cnt = *(p + 5) & 0x1f; // Number of sps + p += 6; + for (i = 0; i < cnt; i++) { + nalsize = AV_RB16(p) + 2; + if (p - data + nalsize > size) + return AVERROR_INVALIDDATA; + ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx); + if (ret < 0) { + av_log(logctx, AV_LOG_ERROR, + "Decoding sps %d from avcC failed\n", i); + return ret; + } + p += nalsize; + } + // Decode pps from avcC + cnt = *(p++); // Number of pps + for (i = 0; i < cnt; i++) { + nalsize = AV_RB16(p) + 2; + if (p - data + nalsize > size) + return AVERROR_INVALIDDATA; + ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx); + if (ret < 0) { + av_log(logctx, AV_LOG_ERROR, + "Decoding pps %d from avcC failed\n", i); + return ret; + } + p += nalsize; + } + // Store right nal length size that will be used to parse all other nals + *nal_length_size = (data[4] & 0x03) + 1; + } else { + *is_avc = 0; + ret = decode_extradata_ps(data, size, ps, 0, logctx); + if (ret < 0) + return ret; + } + return 0; +} + +/** + * Compute profile from profile_idc and constraint_set?_flags. + * + * @param sps SPS + * + * @return profile as defined by FF_PROFILE_H264_* + */ +int ff_h264_get_profile(const SPS *sps) +{ + int profile = sps->profile_idc; + + switch (sps->profile_idc) { + case FF_PROFILE_H264_BASELINE: + // constraint_set1_flag set to 1 + profile |= (sps->constraint_set_flags & 1 << 1) ? FF_PROFILE_H264_CONSTRAINED : 0; + break; + case FF_PROFILE_H264_HIGH_10: + case FF_PROFILE_H264_HIGH_422: + case FF_PROFILE_H264_HIGH_444_PREDICTIVE: + // constraint_set3_flag set to 1 + profile |= (sps->constraint_set_flags & 1 << 3) ? FF_PROFILE_H264_INTRA : 0; + break; + } + + return profile; +} diff --git a/libavcodec/h264_parse.h b/libavcodec/h264_parse.h new file mode 100644 index 0000000..5c6024d --- /dev/null +++ b/libavcodec/h264_parse.h @@ -0,0 +1,92 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 decoder/parser shared code + */ + +#ifndef AVCODEC_H264_PARSE_H +#define AVCODEC_H264_PARSE_H + +#include "get_bits.h" +#include "h264_ps.h" + +typedef struct H264PredWeightTable { + int use_weight; + int use_weight_chroma; + int luma_log2_weight_denom; + int chroma_log2_weight_denom; + int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag + int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + // The following 2 can be changed to int8_t but that causes a 10 CPU cycles speed loss + int luma_weight[48][2][2]; + int chroma_weight[48][2][2][2]; + int implicit_weight[48][48][2]; +} H264PredWeightTable; + +typedef struct H264POCContext { + 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 +} H264POCContext; + +int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps, + const int *ref_count, int slice_type_nos, + H264PredWeightTable *pwt); + +/** + * Check if the top & left blocks are available if needed & change the + * dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra4x4_pred_mode(int8_t *pred_mode_cache, void *logctx, + int top_samples_available, int left_samples_available); + +/** + * Check if the top & left blocks are available if needed & change the + * dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available, + int left_samples_available, + int mode, int is_chroma); + +int ff_h264_parse_ref_count(int *plist_count, int ref_count[2], + GetBitContext *gb, const PPS *pps, + int slice_type_nos, int picture_structure); + +int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc, + const SPS *sps, H264POCContext *poc, + int picture_structure, int nal_ref_idc); + +int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps, + int *is_avc, int *nal_length_size, + int err_recognition, void *logctx); + +/** + * compute profile from sps + */ +int ff_h264_get_profile(const SPS *sps); + +#endif /* AVCODEC_H264_PARSE_H */ diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 145dce3..b4da123 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -21,26 +21,49 @@ /** * @file - * H.264 / AVC / MPEG4 part10 parser. + * H.264 / AVC / MPEG-4 part10 parser. * @author Michael Niedermayer */ -#include "libavutil/attributes.h" -#include "parser.h" -#include "h264data.h" +#include +#include + +#include "libavutil/avutil.h" +#include "libavutil/error.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "get_bits.h" #include "golomb.h" +#include "h264.h" +#include "h264_sei.h" +#include "h264_ps.h" +#include "h264data.h" #include "internal.h" #include "mpegutils.h" +#include "parser.h" -#include +typedef struct H264ParseContext { + ParseContext pc; + H264ParamSets ps; + H264DSPContext h264dsp; + H264POCContext poc; + H264SEIContext sei; + int is_avc; + int nal_length_size; + int got_first; + int picture_structure; +} H264ParseContext; -static int h264_find_frame_end(H264Context *h, const uint8_t *buf, +static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, int buf_size) { int i; uint32_t state; - ParseContext *pc = &h->parse_context; + ParseContext *pc = &p->pc; // mb_addr= pc->mb_addr - 1; state = pc->state; if (state > 13) @@ -48,7 +71,7 @@ static int h264_find_frame_end(H264Context *h, const uint8_t *buf, for (i = 0; i < buf_size; i++) { if (state == 7) { - i += h->h264dsp.startcode_find_candidate(buf + i, buf_size - i); + i += p->h264dsp.startcode_find_candidate(buf + i, buf_size - i); if (i < buf_size) state = 2; } else if (state <= 2) { @@ -60,14 +83,14 @@ static int h264_find_frame_end(H264Context *h, const uint8_t *buf, state >>= 1; // 2->1, 1->0, 0->0 } else if (state <= 5) { int nalu_type = buf[i] & 0x1F; - if (nalu_type == NAL_SEI || nalu_type == NAL_SPS || - nalu_type == NAL_PPS || nalu_type == NAL_AUD) { + if (nalu_type == H264_NAL_SEI || nalu_type == H264_NAL_SPS || + nalu_type == H264_NAL_PPS || nalu_type == H264_NAL_AUD) { if (pc->frame_start_found) { i++; goto found; } - } else if (nalu_type == NAL_SLICE || nalu_type == NAL_DPA || - nalu_type == NAL_IDR_SLICE) { + } else if (nalu_type == H264_NAL_SLICE || nalu_type == H264_NAL_DPA || + nalu_type == H264_NAL_IDR_SLICE) { if (pc->frame_start_found) { state += 8; continue; @@ -76,6 +99,7 @@ static int h264_find_frame_end(H264Context *h, const uint8_t *buf, } state = 7; } else { + // first_mb_in_slice is 0, probably the first nal of a new slice if (buf[i] & 0x80) goto found; state = 7; @@ -90,38 +114,45 @@ found: return i - (state & 5); } -static int scan_mmco_reset(AVCodecParserContext *s) +static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb, + AVCodecContext *avctx) { - H264Context *h = s->priv_data; + H264PredWeightTable pwt; + int slice_type_nos = s->pict_type & 3; + H264ParseContext *p = s->priv_data; + int list_count, ref_count[2]; + - h->slice_type_nos = s->pict_type & 3; + if (p->ps.pps->redundant_pic_cnt_present) + get_ue_golomb(gb); // redundant_pic_count - if (h->pps.redundant_pic_cnt_present) - get_ue_golomb(&h->gb); // redundant_pic_count + if (slice_type_nos == AV_PICTURE_TYPE_B) + get_bits1(gb); // direct_spatial_mv_pred - if (ff_set_ref_count(h) < 0) + if (ff_h264_parse_ref_count(&list_count, ref_count, gb, p->ps.pps, + slice_type_nos, p->picture_structure) < 0) return AVERROR_INVALIDDATA; - if (h->slice_type_nos != AV_PICTURE_TYPE_I) { + if (slice_type_nos != AV_PICTURE_TYPE_I) { int list; - for (list = 0; list < h->list_count; list++) { - if (get_bits1(&h->gb)) { + for (list = 0; list < list_count; list++) { + if (get_bits1(gb)) { int index; for (index = 0; ; index++) { - unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(&h->gb); + unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(gb); if (reordering_of_pic_nums_idc < 3) - get_ue_golomb(&h->gb); + get_ue_golomb(gb); else if (reordering_of_pic_nums_idc > 3) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc %d\n", reordering_of_pic_nums_idc); return AVERROR_INVALIDDATA; } else break; - if (index >= h->ref_count[list]) { - av_log(h->avctx, AV_LOG_ERROR, + if (index >= ref_count[list]) { + av_log(avctx, AV_LOG_ERROR, "reference count %d overflow\n", index); return AVERROR_INVALIDDATA; } @@ -130,16 +161,17 @@ static int scan_mmco_reset(AVCodecParserContext *s) } } - if ((h->pps.weighted_pred && h->slice_type_nos == AV_PICTURE_TYPE_P) || - (h->pps.weighted_bipred_idc == 1 && h->slice_type_nos == AV_PICTURE_TYPE_B)) - ff_pred_weight_table(h); + if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) || + (p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos == AV_PICTURE_TYPE_B)) + ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos, + &pwt); - if (get_bits1(&h->gb)) { // adaptive_ref_pic_marking_mode_flag + if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag int i; for (i = 0; i < MAX_MMCO_COUNT; i++) { - MMCOOpcode opcode = get_ue_golomb_31(&h->gb); + MMCOOpcode opcode = get_ue_golomb_31(gb); if (opcode > (unsigned) MMCO_LONG) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); return AVERROR_INVALIDDATA; @@ -150,10 +182,10 @@ static int scan_mmco_reset(AVCodecParserContext *s) return 1; if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) - get_ue_golomb(&h->gb); + get_ue_golomb(gb); if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED || opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) - get_ue_golomb_31(&h->gb); + get_ue_golomb_31(gb); } } @@ -172,37 +204,40 @@ static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size) { - H264Context *h = s->priv_data; + H264ParseContext *p = s->priv_data; const uint8_t *buf_end = buf + buf_size; + + H2645NAL nal = { NULL }; + unsigned int pps_id; unsigned int slice_type; int state = -1, got_reset = 0; - const uint8_t *ptr; int field_poc[2]; + int ret; /* set some sane default values */ s->pict_type = AV_PICTURE_TYPE_I; s->key_frame = 0; s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN; - h->avctx = avctx; - ff_h264_reset_sei(h); + ff_h264_sei_uninit(&p->sei); if (!buf_size) return 0; for (;;) { - int src_length, dst_length, consumed; + const SPS *sps; + int src_length, consumed; buf = avpriv_find_start_code(buf, buf_end, &state); if (buf >= buf_end) break; --buf; src_length = buf_end - buf; switch (state & 0x1f) { - case NAL_SLICE: - case NAL_IDR_SLICE: + case H264_NAL_SLICE: + case H264_NAL_IDR_SLICE: // Do not walk the whole buffer just to decode slice header - if ((state & 0x1f) == NAL_IDR_SLICE || ((state >> 5) & 0x3) == 0) { + if ((state & 0x1f) == H264_NAL_IDR_SLICE || ((state >> 5) & 0x3) == 0) { /* IDR or disposable slice * No need to decode many bytes because MMCOs shall not be present. */ if (src_length > 60) @@ -214,120 +249,161 @@ static inline int parse_nal_units(AVCodecParserContext *s, } break; } - ptr = ff_h264_decode_nal(h, buf, &dst_length, &consumed, src_length); - if (!ptr || dst_length < 0) + + consumed = ff_h2645_extract_rbsp(buf, src_length, &nal); + if (consumed < 0) break; - init_get_bits(&h->gb, ptr, 8 * dst_length); - switch (h->nal_unit_type) { - case NAL_SPS: - ff_h264_decode_seq_parameter_set(h); + ret = init_get_bits(&nal.gb, nal.data, nal.size * 8); + if (ret < 0) + goto fail; + get_bits1(&nal.gb); + nal.ref_idc = get_bits(&nal.gb, 2); + nal.type = get_bits(&nal.gb, 5); + + switch (nal.type) { + case H264_NAL_SPS: + ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps); break; - case NAL_PPS: - ff_h264_decode_picture_parameter_set(h, h->gb.size_in_bits); + case H264_NAL_PPS: + ff_h264_decode_picture_parameter_set(&nal.gb, avctx, &p->ps, + nal.size_bits); break; - case NAL_SEI: - ff_h264_decode_sei(h); + case H264_NAL_SEI: + ff_h264_sei_decode(&p->sei, &nal.gb, &p->ps, avctx); break; - case NAL_IDR_SLICE: + case H264_NAL_IDR_SLICE: s->key_frame = 1; - h->prev_frame_num = 0; - h->prev_frame_num_offset = 0; - h->prev_poc_msb = - h->prev_poc_lsb = 0; + p->poc.prev_frame_num = 0; + p->poc.prev_frame_num_offset = 0; + p->poc.prev_poc_msb = + p->poc.prev_poc_lsb = 0; /* fall through */ - case NAL_SLICE: - get_ue_golomb(&h->gb); // skip first_mb_in_slice - slice_type = get_ue_golomb_31(&h->gb); - s->pict_type = golomb_to_pict_type[slice_type % 5]; - if (h->sei_recovery_frame_cnt >= 0) { + case H264_NAL_SLICE: + get_ue_golomb(&nal.gb); // skip first_mb_in_slice + slice_type = get_ue_golomb_31(&nal.gb); + s->pict_type = ff_h264_golomb_to_pict_type[slice_type % 5]; + if (p->sei.recovery_point.recovery_frame_cnt >= 0) { /* key frame, since recovery_frame_cnt is set */ s->key_frame = 1; } - pps_id = get_ue_golomb(&h->gb); + pps_id = get_ue_golomb(&nal.gb); if (pps_id >= MAX_PPS_COUNT) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); - return -1; + goto fail; } - if (!h->pps_buffers[pps_id]) { - av_log(h->avctx, AV_LOG_ERROR, + if (!p->ps.pps_list[pps_id]) { + av_log(avctx, AV_LOG_ERROR, "non-existing PPS %u referenced\n", pps_id); - return -1; + goto fail; + } + p->ps.pps = (const PPS*)p->ps.pps_list[pps_id]->data; + if (!p->ps.sps_list[p->ps.pps->sps_id]) { + av_log(avctx, AV_LOG_ERROR, + "non-existing SPS %u referenced\n", p->ps.pps->sps_id); + goto fail; + } + p->ps.sps = (SPS*)p->ps.sps_list[p->ps.pps->sps_id]->data; + + sps = p->ps.sps; + + p->poc.frame_num = get_bits(&nal.gb, sps->log2_max_frame_num); + + s->coded_width = 16 * sps->mb_width; + s->coded_height = 16 * sps->mb_height; + s->width = s->coded_width - (sps->crop_right + sps->crop_left); + s->height = s->coded_height - (sps->crop_top + sps->crop_bottom); + if (s->width <= 0 || s->height <= 0) { + s->width = s->coded_width; + s->height = s->coded_height; } - h->pps = *h->pps_buffers[pps_id]; - if (!h->sps_buffers[h->pps.sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", h->pps.sps_id); - return -1; + + switch (sps->bit_depth_luma) { + case 9: + if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P9; + else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P9; + else s->format = AV_PIX_FMT_YUV420P9; + break; + case 10: + if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P10; + else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P10; + else s->format = AV_PIX_FMT_YUV420P10; + break; + case 8: + if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P; + else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P; + else s->format = AV_PIX_FMT_YUV420P; + break; + default: + s->format = AV_PIX_FMT_NONE; } - h->sps = *h->sps_buffers[h->pps.sps_id]; - h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); - avctx->profile = ff_h264_get_profile(&h->sps); - avctx->level = h->sps.level_idc; + avctx->profile = ff_h264_get_profile(sps); + avctx->level = sps->level_idc; - if (h->sps.frame_mbs_only_flag) { - h->picture_structure = PICT_FRAME; + if (sps->frame_mbs_only_flag) { + p->picture_structure = PICT_FRAME; } else { - if (get_bits1(&h->gb)) { // field_pic_flag - h->picture_structure = PICT_TOP_FIELD + get_bits1(&h->gb); // bottom_field_flag + if (get_bits1(&nal.gb)) { // field_pic_flag + p->picture_structure = PICT_TOP_FIELD + get_bits1(&nal.gb); // bottom_field_flag } else { - h->picture_structure = PICT_FRAME; + p->picture_structure = PICT_FRAME; } } - if (h->nal_unit_type == NAL_IDR_SLICE) - get_ue_golomb(&h->gb); /* idr_pic_id */ - if (h->sps.poc_type == 0) { - h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb); + if (nal.type == H264_NAL_IDR_SLICE) + get_ue_golomb(&nal.gb); /* idr_pic_id */ + if (sps->poc_type == 0) { + p->poc.poc_lsb = get_bits(&nal.gb, sps->log2_max_poc_lsb); - if (h->pps.pic_order_present == 1 && - h->picture_structure == PICT_FRAME) - h->delta_poc_bottom = get_se_golomb(&h->gb); + if (p->ps.pps->pic_order_present == 1 && + p->picture_structure == PICT_FRAME) + p->poc.delta_poc_bottom = get_se_golomb(&nal.gb); } - if (h->sps.poc_type == 1 && - !h->sps.delta_pic_order_always_zero_flag) { - h->delta_poc[0] = get_se_golomb(&h->gb); + if (sps->poc_type == 1 && + !sps->delta_pic_order_always_zero_flag) { + p->poc.delta_poc[0] = get_se_golomb(&nal.gb); - if (h->pps.pic_order_present == 1 && - h->picture_structure == PICT_FRAME) - h->delta_poc[1] = get_se_golomb(&h->gb); + if (p->ps.pps->pic_order_present == 1 && + p->picture_structure == PICT_FRAME) + p->poc.delta_poc[1] = get_se_golomb(&nal.gb); } /* Decode POC of this picture. * The prev_ values needed for decoding POC of the next picture are not set here. */ field_poc[0] = field_poc[1] = INT_MAX; - ff_init_poc(h, field_poc, &s->output_picture_number); + ff_h264_init_poc(field_poc, &s->output_picture_number, sps, + &p->poc, p->picture_structure, nal.ref_idc); /* Continue parsing to check if MMCO_RESET is present. * FIXME: MMCO_RESET could appear in non-first slice. * Maybe, we should parse all undisposable non-IDR slice of this * picture until encountering MMCO_RESET in a slice of it. */ - if (h->nal_ref_idc && h->nal_unit_type != NAL_IDR_SLICE) { - got_reset = scan_mmco_reset(s); + if (nal.ref_idc && nal.type != H264_NAL_IDR_SLICE) { + got_reset = scan_mmco_reset(s, &nal.gb, avctx); if (got_reset < 0) - return got_reset; + goto fail; } /* Set up the prev_ values for decoding POC of the next picture. */ - h->prev_frame_num = got_reset ? 0 : h->frame_num; - h->prev_frame_num_offset = got_reset ? 0 : h->frame_num_offset; - if (h->nal_ref_idc != 0) { + p->poc.prev_frame_num = got_reset ? 0 : p->poc.frame_num; + p->poc.prev_frame_num_offset = got_reset ? 0 : p->poc.frame_num_offset; + if (nal.ref_idc != 0) { if (!got_reset) { - h->prev_poc_msb = h->poc_msb; - h->prev_poc_lsb = h->poc_lsb; + p->poc.prev_poc_msb = p->poc.poc_msb; + p->poc.prev_poc_lsb = p->poc.poc_lsb; } else { - h->prev_poc_msb = 0; - h->prev_poc_lsb = - h->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0]; + p->poc.prev_poc_msb = 0; + p->poc.prev_poc_lsb = + p->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0]; } } - if (h->sps.pic_struct_present_flag) { - switch (h->sei_pic_struct) { + if (sps->pic_struct_present_flag) { + switch (p->sei.picture_timing.pic_struct) { case SEI_PIC_STRUCT_TOP_FIELD: case SEI_PIC_STRUCT_BOTTOM_FIELD: s->repeat_pict = 0; @@ -348,17 +424,17 @@ static inline int parse_nal_units(AVCodecParserContext *s, s->repeat_pict = 5; break; default: - s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0; + s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; break; } } else { - s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0; + s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; } - if (h->picture_structure == PICT_FRAME) { + if (p->picture_structure == PICT_FRAME) { s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; - if (h->sps.pic_struct_present_flag) { - switch (h->sei_pic_struct) { + if (sps->pic_struct_present_flag) { + switch (p->sei.picture_timing.pic_struct) { case SEI_PIC_STRUCT_TOP_BOTTOM: case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: s->field_order = AV_FIELD_TT; @@ -380,19 +456,22 @@ static inline int parse_nal_units(AVCodecParserContext *s, s->field_order = AV_FIELD_PROGRESSIVE; } } else { - if (h->picture_structure == PICT_TOP_FIELD) + if (p->picture_structure == PICT_TOP_FIELD) s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD; else s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; s->field_order = AV_FIELD_UNKNOWN; } + av_freep(&nal.rbsp_buffer); return 0; /* no need to evaluate the rest */ } buf += consumed; } /* didn't find a picture! */ - av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n"); + av_log(avctx, AV_LOG_ERROR, "missing picture in access unit\n"); +fail: + av_freep(&nal.rbsp_buffer); return -1; } @@ -401,29 +480,23 @@ static int h264_parse(AVCodecParserContext *s, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { - H264Context *h = s->priv_data; - ParseContext *pc = &h->parse_context; + H264ParseContext *p = s->priv_data; + ParseContext *pc = &p->pc; int next; - if (!h->got_first) { - h->got_first = 1; + if (!p->got_first) { + p->got_first = 1; if (avctx->extradata_size) { - h->avctx = avctx; - // must be done like in the decoder. - // otherwise opening the parser, creating extradata, - // and then closing and opening again - // will cause has_b_frames to be always set. - // NB: estimate_timings_from_pts behaves exactly like this. - if (!avctx->has_b_frames) - h->low_delay = 1; - ff_h264_decode_extradata(h); + ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size, + &p->ps, &p->is_avc, &p->nal_length_size, + avctx->err_recognition, avctx); } } if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { next = buf_size; } else { - next = h264_find_frame_end(h, buf, buf_size); + next = h264_find_frame_end(p, buf, buf_size); if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { *poutbuf = NULL; @@ -433,16 +506,16 @@ static int h264_parse(AVCodecParserContext *s, if (next < 0 && next != END_NOT_FOUND) { assert(pc->last_index + next >= 0); - h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); // update state + h264_find_frame_end(p, &pc->buffer[pc->last_index + next], -next); // update state } } parse_nal_units(s, avctx, buf, buf_size); - if (h->sei_cpb_removal_delay >= 0) { - s->dts_sync_point = h->sei_buffering_period_present; - s->dts_ref_dts_delta = h->sei_cpb_removal_delay; - s->pts_dts_delta = h->sei_dpb_output_delay; + if (p->sei.picture_timing.cpb_removal_delay >= 0) { + s->dts_sync_point = p->sei.buffering_period.present; + s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay; + s->pts_dts_delta = p->sei.picture_timing.dpb_output_delay; } else { s->dts_sync_point = INT_MIN; s->dts_ref_dts_delta = INT_MIN; @@ -473,8 +546,10 @@ static int h264_split(AVCodecContext *avctx, * (state&0xFFFFFF1F) == 0x105) { * } */ - if ((state & 0xFFFFFF00) == 0x100 && (state & 0xFFFFFF1F) != 0x107 && - (state & 0xFFFFFF1F) != 0x108 && (state & 0xFFFFFF1F) != 0x109) { + if ((state & 0xFFFFFF00) == 0x100 && (state & 0xFFFFFF1F) != 0x106 && + (state & 0xFFFFFF1F) != 0x107 && (state & 0xFFFFFF1F) != 0x108 && + (state & 0xFFFFFF1F) != 0x109 && (state & 0xFFFFFF1F) != 0x10d && + (state & 0xFFFFFF1F) != 0x10f) { if (has_sps) { while (i > 4 && buf[i - 5] == 0) i--; @@ -487,29 +562,36 @@ static int h264_split(AVCodecContext *avctx, return 0; } -static void close(AVCodecParserContext *s) +static void h264_close(AVCodecParserContext *s) { - H264Context *h = s->priv_data; - ParseContext *pc = &h->parse_context; + H264ParseContext *p = s->priv_data; + ParseContext *pc = &p->pc; + int i; av_free(pc->buffer); - ff_h264_free_context(h); + + ff_h264_sei_uninit(&p->sei); + + for (i = 0; i < FF_ARRAY_ELEMS(p->ps.sps_list); i++) + av_buffer_unref(&p->ps.sps_list[i]); + + for (i = 0; i < FF_ARRAY_ELEMS(p->ps.pps_list); i++) + av_buffer_unref(&p->ps.pps_list[i]); } static av_cold int init(AVCodecParserContext *s) { - H264Context *h = s->priv_data; - h->thread_context[0] = h; - h->slice_context_count = 1; - ff_h264dsp_init(&h->h264dsp, 8, 1); + H264ParseContext *p = s->priv_data; + + ff_h264dsp_init(&p->h264dsp, 8, 1); return 0; } AVCodecParser ff_h264_parser = { .codec_ids = { AV_CODEC_ID_H264 }, - .priv_data_size = sizeof(H264Context), + .priv_data_size = sizeof(H264ParseContext), .parser_init = init, .parser_parse = h264_parse, - .parser_close = close, + .parser_close = h264_close, .split = h264_split, }; diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c index 1d7461b..24ba79d 100644 --- a/libavcodec/h264_picture.c +++ b/libavcodec/h264_picture.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 codec. + * H.264 / AVC / MPEG-4 part10 codec. * @author Michael Niedermayer */ @@ -33,11 +33,10 @@ #include "cabac_functions.h" #include "error_resilience.h" #include "avcodec.h" -#include "h264.h" +#include "h264dec.h" #include "h264data.h" #include "h264chroma.h" #include "h264_mvpred.h" -#include "golomb.h" #include "mathops.h" #include "mpegutils.h" #include "rectangle.h" @@ -48,7 +47,7 @@ void ff_h264_unref_picture(H264Context *h, H264Picture *pic) int off = offsetof(H264Picture, tf) + sizeof(pic->tf); int i; - if (!pic->f.buf[0]) + if (!pic->f || !pic->f->buf[0]) return; ff_thread_release_buffer(h->avctx, &pic->tf); @@ -68,11 +67,11 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src) { int ret, i; - av_assert0(!dst->f.buf[0]); - av_assert0(src->f.buf[0]); + av_assert0(!dst->f->buf[0]); + av_assert0(src->f->buf[0]); - src->tf.f = &src->f; - dst->tf.f = &dst->f; + src->tf.f = src->f; + dst->tf.f = dst->f; ret = ff_thread_ref_frame(&dst->tf, &src->tf); if (ret < 0) goto fail; @@ -113,7 +112,6 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src) dst->long_ref = src->long_ref; dst->mbaff = src->mbaff; dst->field_picture = src->field_picture; - dst->needs_realloc = src->needs_realloc; dst->reference = src->reference; dst->recovered = src->recovered; @@ -131,7 +129,7 @@ static void h264_set_erpic(ERPicture *dst, H264Picture *src) if (!src) return; - dst->f = &src->f; + dst->f = src->f; dst->tf = &src->tf; for (i = 0; i < 2; i++) { @@ -144,7 +142,7 @@ static void h264_set_erpic(ERPicture *dst, H264Picture *src) } #endif /* CONFIG_ERROR_RESILIENCE */ -int ff_h264_field_end(H264Context *h, int in_setup) +int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup) { AVCodecContext *const avctx = h->avctx; int err = 0; @@ -156,13 +154,12 @@ int ff_h264_field_end(H264Context *h, int in_setup) if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) { if (!h->droppable) { - err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); - h->prev_poc_msb = h->poc_msb; - h->prev_poc_lsb = h->poc_lsb; + err = ff_h264_execute_ref_pic_marking(h); + h->poc.prev_poc_msb = h->poc.poc_msb; + h->poc.prev_poc_lsb = h->poc.poc_lsb; } - h->prev_frame_num_offset = h->frame_num_offset; - h->prev_frame_num = h->frame_num; - h->outputed_poc = h->next_outputed_poc; + h->poc.prev_frame_num_offset = h->poc.frame_num_offset; + h->poc.prev_frame_num = h->poc.frame_num; } if (avctx->hwaccel) { @@ -184,19 +181,20 @@ int ff_h264_field_end(H264Context *h, int in_setup) * past end by one (callers fault) and resync_mb_y != 0 * causes problems for the first MB line, too. */ - if (!FIELD_PICTURE(h)) { - h264_set_erpic(&h->er.cur_pic, h->cur_pic_ptr); - h264_set_erpic(&h->er.last_pic, - h->ref_count[0] ? &h->ref_list[0][0] : NULL); - h264_set_erpic(&h->er.next_pic, - h->ref_count[1] ? &h->ref_list[1][0] : NULL); - ff_er_frame_end(&h->er); + if (!FIELD_PICTURE(h) && h->enable_er) { + h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr); + h264_set_erpic(&sl->er.last_pic, + sl->ref_count[0] ? sl->ref_list[0][0].parent : NULL); + h264_set_erpic(&sl->er.next_pic, + sl->ref_count[1] ? sl->ref_list[1][0].parent : NULL); + ff_er_frame_end(&sl->er); } #endif /* CONFIG_ERROR_RESILIENCE */ emms_c(); h->current_slice = 0; + h->field_started = 0; return err; } diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index ad284da..36902e8 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 parameter set decoding. + * H.264 / AVC / MPEG-4 part10 parameter set decoding. * @author Michael Niedermayer */ @@ -29,14 +29,17 @@ #include "libavutil/imgutils.h" #include "internal.h" +#include "mathops.h" #include "avcodec.h" -#include "h264.h" -#include "h264data.h" //FIXME FIXME FIXME (just for zigzag_scan) +#include "h264data.h" +#include "h264_ps.h" #include "golomb.h" #define MAX_LOG2_MAX_FRAME_NUM (12 + 4) #define MIN_LOG2_MAX_FRAME_NUM 4 +#define EXTENDED_SAR 255 + static const AVRational pixel_aspect[17] = { { 0, 1 }, { 1, 1 }, @@ -57,28 +60,6 @@ static const AVRational pixel_aspect[17] = { { 2, 1 }, }; -#define QP(qP, depth) ((qP) + 6 * ((depth) - 8)) - -#define CHROMA_QP_TABLE_END(d) \ - QP(0, d), QP(1, d), QP(2, d), QP(3, d), QP(4, d), QP(5, d), \ - QP(6, d), QP(7, d), QP(8, d), QP(9, d), QP(10, d), QP(11, d), \ - QP(12, d), QP(13, d), QP(14, d), QP(15, d), QP(16, d), QP(17, d), \ - QP(18, d), QP(19, d), QP(20, d), QP(21, d), QP(22, d), QP(23, d), \ - QP(24, d), QP(25, d), QP(26, d), QP(27, d), QP(28, d), QP(29, d), \ - QP(29, d), QP(30, d), QP(31, d), QP(32, d), QP(32, d), QP(33, d), \ - QP(34, d), QP(34, d), QP(35, d), QP(35, d), QP(36, d), QP(36, d), \ - QP(37, d), QP(37, d), QP(37, d), QP(38, d), QP(38, d), QP(38, d), \ - QP(39, d), QP(39, d), QP(39, d), QP(39, d) - -const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1] = { - { CHROMA_QP_TABLE_END(8) }, - { 0, 1, 2, 3, 4, 5, - CHROMA_QP_TABLE_END(9) }, - { 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, - CHROMA_QP_TABLE_END(10) }, -}; - static const uint8_t default_scaling4[2][16] = { { 6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42 }, @@ -105,47 +86,91 @@ static const uint8_t default_scaling8[2][64] = { 24, 25, 27, 28, 30, 32, 33, 35 } }; -static inline int decode_hrd_parameters(H264Context *h, SPS *sps) +/* maximum number of MBs in the DPB for a given level */ +static const int level_max_dpb_mbs[][2] = { + { 10, 396 }, + { 11, 900 }, + { 12, 2376 }, + { 13, 2376 }, + { 20, 2376 }, + { 21, 4752 }, + { 22, 8100 }, + { 30, 8100 }, + { 31, 18000 }, + { 32, 20480 }, + { 40, 32768 }, + { 41, 32768 }, + { 42, 34816 }, + { 50, 110400 }, + { 51, 184320 }, + { 52, 184320 }, +}; + +static void remove_pps(H264ParamSets *s, int id) +{ + if (s->pps_list[id] && s->pps == (const PPS*)s->pps_list[id]->data) + s->pps = NULL; + av_buffer_unref(&s->pps_list[id]); +} + +static void remove_sps(H264ParamSets *s, int id) +{ + int i; + if (s->sps_list[id]) { + if (s->sps == (SPS*)s->sps_list[id]->data) + s->sps = NULL; + + /* drop all PPS that depend on this SPS */ + for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) + if (s->pps_list[i] && ((PPS*)s->pps_list[i]->data)->sps_id == id) + remove_pps(s, i); + } + av_buffer_unref(&s->sps_list[id]); +} + +static inline int decode_hrd_parameters(GetBitContext *gb, AVCodecContext *avctx, + SPS *sps) { int cpb_count, i; - cpb_count = get_ue_golomb_31(&h->gb) + 1; + cpb_count = get_ue_golomb_31(gb) + 1; if (cpb_count > 32U) { - av_log(h->avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); + av_log(avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); return AVERROR_INVALIDDATA; } - get_bits(&h->gb, 4); /* bit_rate_scale */ - get_bits(&h->gb, 4); /* cpb_size_scale */ + get_bits(gb, 4); /* bit_rate_scale */ + get_bits(gb, 4); /* cpb_size_scale */ for (i = 0; i < cpb_count; i++) { - get_ue_golomb_long(&h->gb); /* bit_rate_value_minus1 */ - get_ue_golomb_long(&h->gb); /* cpb_size_value_minus1 */ - get_bits1(&h->gb); /* cbr_flag */ - } - sps->initial_cpb_removal_delay_length = get_bits(&h->gb, 5) + 1; - sps->cpb_removal_delay_length = get_bits(&h->gb, 5) + 1; - sps->dpb_output_delay_length = get_bits(&h->gb, 5) + 1; - sps->time_offset_length = get_bits(&h->gb, 5); + get_ue_golomb_long(gb); /* bit_rate_value_minus1 */ + get_ue_golomb_long(gb); /* cpb_size_value_minus1 */ + get_bits1(gb); /* cbr_flag */ + } + sps->initial_cpb_removal_delay_length = get_bits(gb, 5) + 1; + sps->cpb_removal_delay_length = get_bits(gb, 5) + 1; + sps->dpb_output_delay_length = get_bits(gb, 5) + 1; + sps->time_offset_length = get_bits(gb, 5); sps->cpb_cnt = cpb_count; return 0; } -static inline int decode_vui_parameters(H264Context *h, SPS *sps) +static inline int decode_vui_parameters(GetBitContext *gb, AVCodecContext *avctx, + SPS *sps) { int aspect_ratio_info_present_flag; unsigned int aspect_ratio_idc; - aspect_ratio_info_present_flag = get_bits1(&h->gb); + aspect_ratio_info_present_flag = get_bits1(gb); if (aspect_ratio_info_present_flag) { - aspect_ratio_idc = get_bits(&h->gb, 8); + aspect_ratio_idc = get_bits(gb, 8); if (aspect_ratio_idc == EXTENDED_SAR) { - sps->sar.num = get_bits(&h->gb, 16); - sps->sar.den = get_bits(&h->gb, 16); + sps->sar.num = get_bits(gb, 16); + sps->sar.den = get_bits(gb, 16); } else if (aspect_ratio_idc < FF_ARRAY_ELEMS(pixel_aspect)) { sps->sar = pixel_aspect[aspect_ratio_idc]; } else { - av_log(h->avctx, AV_LOG_ERROR, "illegal aspect ratio\n"); + av_log(avctx, AV_LOG_ERROR, "illegal aspect ratio\n"); return AVERROR_INVALIDDATA; } } else { @@ -153,19 +178,19 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps) sps->sar.den = 0; } - if (get_bits1(&h->gb)) /* overscan_info_present_flag */ - get_bits1(&h->gb); /* overscan_appropriate_flag */ + if (get_bits1(gb)) /* overscan_info_present_flag */ + get_bits1(gb); /* overscan_appropriate_flag */ - sps->video_signal_type_present_flag = get_bits1(&h->gb); + sps->video_signal_type_present_flag = get_bits1(gb); if (sps->video_signal_type_present_flag) { - get_bits(&h->gb, 3); /* video_format */ - sps->full_range = get_bits1(&h->gb); /* video_full_range_flag */ + get_bits(gb, 3); /* video_format */ + sps->full_range = get_bits1(gb); /* video_full_range_flag */ - sps->colour_description_present_flag = get_bits1(&h->gb); + sps->colour_description_present_flag = get_bits1(gb); if (sps->colour_description_present_flag) { - sps->color_primaries = get_bits(&h->gb, 8); /* colour_primaries */ - sps->color_trc = get_bits(&h->gb, 8); /* transfer_characteristics */ - sps->colorspace = get_bits(&h->gb, 8); /* matrix_coefficients */ + sps->color_primaries = get_bits(gb, 8); /* colour_primaries */ + sps->color_trc = get_bits(gb, 8); /* transfer_characteristics */ + sps->colorspace = get_bits(gb, 8); /* matrix_coefficients */ if (sps->color_primaries >= AVCOL_PRI_NB) sps->color_primaries = AVCOL_PRI_UNSPECIFIED; if (sps->color_trc >= AVCOL_TRC_NB) @@ -176,83 +201,83 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps) } /* chroma_location_info_present_flag */ - if (get_bits1(&h->gb)) { + if (get_bits1(gb)) { /* chroma_sample_location_type_top_field */ - h->avctx->chroma_sample_location = get_ue_golomb(&h->gb) + 1; - get_ue_golomb(&h->gb); /* chroma_sample_location_type_bottom_field */ + avctx->chroma_sample_location = get_ue_golomb(gb) + 1; + get_ue_golomb(gb); /* chroma_sample_location_type_bottom_field */ } - sps->timing_info_present_flag = get_bits1(&h->gb); + sps->timing_info_present_flag = get_bits1(gb); if (sps->timing_info_present_flag) { - sps->num_units_in_tick = get_bits_long(&h->gb, 32); - sps->time_scale = get_bits_long(&h->gb, 32); + sps->num_units_in_tick = get_bits_long(gb, 32); + sps->time_scale = get_bits_long(gb, 32); if (!sps->num_units_in_tick || !sps->time_scale) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "time_scale/num_units_in_tick invalid or unsupported (%"PRIu32"/%"PRIu32")\n", sps->time_scale, sps->num_units_in_tick); return AVERROR_INVALIDDATA; } - sps->fixed_frame_rate_flag = get_bits1(&h->gb); + sps->fixed_frame_rate_flag = get_bits1(gb); } - sps->nal_hrd_parameters_present_flag = get_bits1(&h->gb); + sps->nal_hrd_parameters_present_flag = get_bits1(gb); if (sps->nal_hrd_parameters_present_flag) - if (decode_hrd_parameters(h, sps) < 0) + if (decode_hrd_parameters(gb, avctx, sps) < 0) return AVERROR_INVALIDDATA; - sps->vcl_hrd_parameters_present_flag = get_bits1(&h->gb); + sps->vcl_hrd_parameters_present_flag = get_bits1(gb); if (sps->vcl_hrd_parameters_present_flag) - if (decode_hrd_parameters(h, sps) < 0) + if (decode_hrd_parameters(gb, avctx, sps) < 0) return AVERROR_INVALIDDATA; if (sps->nal_hrd_parameters_present_flag || sps->vcl_hrd_parameters_present_flag) - get_bits1(&h->gb); /* low_delay_hrd_flag */ - sps->pic_struct_present_flag = get_bits1(&h->gb); + get_bits1(gb); /* low_delay_hrd_flag */ + sps->pic_struct_present_flag = get_bits1(gb); - sps->bitstream_restriction_flag = get_bits1(&h->gb); + sps->bitstream_restriction_flag = get_bits1(gb); if (sps->bitstream_restriction_flag) { - get_bits1(&h->gb); /* motion_vectors_over_pic_boundaries_flag */ - get_ue_golomb(&h->gb); /* max_bytes_per_pic_denom */ - get_ue_golomb(&h->gb); /* max_bits_per_mb_denom */ - get_ue_golomb(&h->gb); /* log2_max_mv_length_horizontal */ - get_ue_golomb(&h->gb); /* log2_max_mv_length_vertical */ - sps->num_reorder_frames = get_ue_golomb(&h->gb); - get_ue_golomb(&h->gb); /*max_dec_frame_buffering*/ - - if (get_bits_left(&h->gb) < 0) { + get_bits1(gb); /* motion_vectors_over_pic_boundaries_flag */ + get_ue_golomb(gb); /* max_bytes_per_pic_denom */ + get_ue_golomb(gb); /* max_bits_per_mb_denom */ + get_ue_golomb(gb); /* log2_max_mv_length_horizontal */ + get_ue_golomb(gb); /* log2_max_mv_length_vertical */ + sps->num_reorder_frames = get_ue_golomb(gb); + get_ue_golomb(gb); /*max_dec_frame_buffering*/ + + if (get_bits_left(gb) < 0) { sps->num_reorder_frames = 0; sps->bitstream_restriction_flag = 0; } if (sps->num_reorder_frames > 16U /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "Clipping illegal num_reorder_frames %d\n", sps->num_reorder_frames); sps->num_reorder_frames = 16; return AVERROR_INVALIDDATA; } } - if (get_bits_left(&h->gb) < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "Overread VUI by %d bits\n", -get_bits_left(&h->gb)); + if (get_bits_left(gb) < 0) { + av_log(avctx, AV_LOG_ERROR, + "Overread VUI by %d bits\n", -get_bits_left(gb)); return AVERROR_INVALIDDATA; } return 0; } -static void decode_scaling_list(H264Context *h, uint8_t *factors, int size, +static void decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size, const uint8_t *jvt_list, const uint8_t *fallback_list) { int i, last = 8, next = 8; - const uint8_t *scan = size == 16 ? zigzag_scan : ff_zigzag_direct; - if (!get_bits1(&h->gb)) /* matrix not written, we use the predicted one */ + const uint8_t *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct; + if (!get_bits1(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(&h->gb)) & 0xff; + next = (last + get_se_golomb(gb)) & 0xff; if (!i && !next) { /* matrix not written, we use the preset one */ memcpy(factors, jvt_list, size * sizeof(uint8_t)); break; @@ -261,7 +286,7 @@ static void decode_scaling_list(H264Context *h, uint8_t *factors, int size, } } -static void decode_scaling_matrices(H264Context *h, SPS *sps, +static void decode_scaling_matrices(GetBitContext *gb, SPS *sps, PPS *pps, int is_sps, uint8_t(*scaling_matrix4)[16], uint8_t(*scaling_matrix8)[64]) @@ -273,54 +298,58 @@ static void decode_scaling_matrices(H264Context *h, SPS *sps, fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0], fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1] }; - if (get_bits1(&h->gb)) { + if (get_bits1(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 + decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]); // Intra, Y + decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr + decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb + decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]); // Inter, Y + decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr + decode_scaling_list(gb, 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(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y if (sps->chroma_format_idc == 3) { - decode_scaling_list(h, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr - decode_scaling_list(h, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb + decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr + decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb } - decode_scaling_list(h, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y + decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y if (sps->chroma_format_idc == 3) { - decode_scaling_list(h, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr - decode_scaling_list(h, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb + decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr + decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb } } } } -int ff_h264_decode_seq_parameter_set(H264Context *h) +int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, + H264ParamSets *ps) { + AVBufferRef *sps_buf; int profile_idc, level_idc, constraint_set_flags = 0; unsigned int sps_id; int i, log2_max_frame_num_minus4; SPS *sps; - profile_idc = get_bits(&h->gb, 8); - constraint_set_flags |= get_bits1(&h->gb) << 0; // constraint_set0_flag - constraint_set_flags |= get_bits1(&h->gb) << 1; // constraint_set1_flag - constraint_set_flags |= get_bits1(&h->gb) << 2; // constraint_set2_flag - constraint_set_flags |= get_bits1(&h->gb) << 3; // constraint_set3_flag - constraint_set_flags |= get_bits1(&h->gb) << 4; // constraint_set4_flag - constraint_set_flags |= get_bits1(&h->gb) << 5; // constraint_set5_flag - skip_bits(&h->gb, 2); // reserved_zero_2bits - level_idc = get_bits(&h->gb, 8); - sps_id = get_ue_golomb_31(&h->gb); + profile_idc = get_bits(gb, 8); + constraint_set_flags |= get_bits1(gb) << 0; // constraint_set0_flag + constraint_set_flags |= get_bits1(gb) << 1; // constraint_set1_flag + constraint_set_flags |= get_bits1(gb) << 2; // constraint_set2_flag + constraint_set_flags |= get_bits1(gb) << 3; // constraint_set3_flag + constraint_set_flags |= get_bits1(gb) << 4; // constraint_set4_flag + constraint_set_flags |= get_bits1(gb) << 5; // constraint_set5_flag + skip_bits(gb, 2); // reserved_zero_2bits + level_idc = get_bits(gb, 8); + sps_id = get_ue_golomb_31(gb); if (sps_id >= MAX_SPS_COUNT) { - av_log(h->avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id); + av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id); return AVERROR_INVALIDDATA; } - sps = av_mallocz(sizeof(SPS)); - if (!sps) + + sps_buf = av_buffer_allocz(sizeof(*sps)); + if (!sps_buf) return AVERROR(ENOMEM); + sps = (SPS*)sps_buf->data; sps->sps_id = sps_id; sps->time_offset_length = 24; @@ -343,23 +372,23 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->profile_idc == 128 || // Multiview High profile (MVC) sps->profile_idc == 138 || // Multiview Depth High profile (MVCD) sps->profile_idc == 144) { // old High444 profile - sps->chroma_format_idc = get_ue_golomb_31(&h->gb); + sps->chroma_format_idc = get_ue_golomb_31(gb); if (sps->chroma_format_idc > 3) { - avpriv_request_sample(h->avctx, "chroma_format_idc %u", + avpriv_request_sample(avctx, "chroma_format_idc %u", sps->chroma_format_idc); goto fail; } else if (sps->chroma_format_idc == 3) { - sps->residual_color_transform_flag = get_bits1(&h->gb); + sps->residual_color_transform_flag = get_bits1(gb); } - sps->bit_depth_luma = get_ue_golomb(&h->gb) + 8; - sps->bit_depth_chroma = get_ue_golomb(&h->gb) + 8; + sps->bit_depth_luma = get_ue_golomb(gb) + 8; + sps->bit_depth_chroma = get_ue_golomb(gb) + 8; if (sps->bit_depth_chroma != sps->bit_depth_luma) { - avpriv_request_sample(h->avctx, + avpriv_request_sample(avctx, "Different chroma and luma bit depth"); goto fail; } - sps->transform_bypass = get_bits1(&h->gb); - decode_scaling_matrices(h, sps, NULL, 1, + sps->transform_bypass = get_bits1(gb); + decode_scaling_matrices(gb, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8); } else { sps->chroma_format_idc = 1; @@ -367,85 +396,92 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->bit_depth_chroma = 8; } - log2_max_frame_num_minus4 = get_ue_golomb(&h->gb); + log2_max_frame_num_minus4 = get_ue_golomb(gb); if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 || log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "log2_max_frame_num_minus4 out of range (0-12): %d\n", log2_max_frame_num_minus4); goto fail; } sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4; - sps->poc_type = get_ue_golomb_31(&h->gb); + sps->poc_type = get_ue_golomb_31(gb); if (sps->poc_type == 0) { // FIXME #define - sps->log2_max_poc_lsb = get_ue_golomb(&h->gb) + 4; + sps->log2_max_poc_lsb = get_ue_golomb(gb) + 4; } else if (sps->poc_type == 1) { // FIXME #define - sps->delta_pic_order_always_zero_flag = get_bits1(&h->gb); - sps->offset_for_non_ref_pic = get_se_golomb(&h->gb); - sps->offset_for_top_to_bottom_field = get_se_golomb(&h->gb); - sps->poc_cycle_length = get_ue_golomb(&h->gb); + sps->delta_pic_order_always_zero_flag = get_bits1(gb); + sps->offset_for_non_ref_pic = get_se_golomb(gb); + sps->offset_for_top_to_bottom_field = get_se_golomb(gb); + sps->poc_cycle_length = get_ue_golomb(gb); if ((unsigned)sps->poc_cycle_length >= FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "poc_cycle_length overflow %d\n", sps->poc_cycle_length); goto fail; } for (i = 0; i < sps->poc_cycle_length; i++) - sps->offset_for_ref_frame[i] = get_se_golomb(&h->gb); + sps->offset_for_ref_frame[i] = get_se_golomb(gb); } else if (sps->poc_type != 2) { - av_log(h->avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type); + av_log(avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type); goto fail; } - sps->ref_frame_count = get_ue_golomb_31(&h->gb); - if (sps->ref_frame_count > H264_MAX_PICTURE_COUNT - 2 || - sps->ref_frame_count >= 32U) { - av_log(h->avctx, AV_LOG_ERROR, + sps->ref_frame_count = get_ue_golomb_31(gb); + if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) { + av_log(avctx, AV_LOG_ERROR, "too many reference frames %d\n", sps->ref_frame_count); goto fail; } - sps->gaps_in_frame_num_allowed_flag = get_bits1(&h->gb); - sps->mb_width = get_ue_golomb(&h->gb) + 1; - sps->mb_height = get_ue_golomb(&h->gb) + 1; + sps->gaps_in_frame_num_allowed_flag = get_bits1(gb); + sps->mb_width = get_ue_golomb(gb) + 1; + sps->mb_height = get_ue_golomb(gb) + 1; + + sps->frame_mbs_only_flag = get_bits1(gb); + + if (sps->mb_height >= INT_MAX / 2) { + av_log(avctx, AV_LOG_ERROR, "height overflow\n"); + goto fail; + } + sps->mb_height *= 2 - sps->frame_mbs_only_flag; + if ((unsigned)sps->mb_width >= INT_MAX / 16 || (unsigned)sps->mb_height >= INT_MAX / 16 || av_image_check_size(16 * sps->mb_width, - 16 * sps->mb_height, 0, h->avctx)) { - av_log(h->avctx, AV_LOG_ERROR, "mb_width/height overflow\n"); + 16 * sps->mb_height, 0, avctx)) { + av_log(avctx, AV_LOG_ERROR, "mb_width/height overflow\n"); goto fail; } - sps->frame_mbs_only_flag = get_bits1(&h->gb); if (!sps->frame_mbs_only_flag) - sps->mb_aff = get_bits1(&h->gb); + sps->mb_aff = get_bits1(gb); else sps->mb_aff = 0; - sps->direct_8x8_inference_flag = get_bits1(&h->gb); + sps->direct_8x8_inference_flag = get_bits1(gb); if (!sps->frame_mbs_only_flag && !sps->direct_8x8_inference_flag) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n"); goto fail; } #ifndef ALLOW_INTERLACE if (sps->mb_aff) - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "MBAFF support not included; enable it at compile-time.\n"); #endif - sps->crop = get_bits1(&h->gb); + sps->crop = get_bits1(gb); if (sps->crop) { - unsigned int crop_left = get_ue_golomb(&h->gb); - unsigned int crop_right = get_ue_golomb(&h->gb); - unsigned int crop_top = get_ue_golomb(&h->gb); - unsigned int crop_bottom = get_ue_golomb(&h->gb); + unsigned int crop_left = get_ue_golomb(gb); + unsigned int crop_right = get_ue_golomb(gb); + unsigned int crop_top = get_ue_golomb(gb); + unsigned int crop_bottom = get_ue_golomb(gb); - if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { - av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original " + if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { + av_log(avctx, AV_LOG_DEBUG, "discarding sps cropping, original " "values are l:%d r:%d t:%d b:%d\n", crop_left, crop_right, crop_top, crop_bottom); @@ -461,9 +497,9 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) int step_y = (2 - sps->frame_mbs_only_flag) << vsub; if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) && - !(h->avctx->flags & CODEC_FLAG_UNALIGNED)) { + !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8)); - av_log(h->avctx, AV_LOG_WARNING, + av_log(avctx, AV_LOG_WARNING, "Reducing left cropping to %d " "chroma samples to preserve alignment.\n", crop_left); @@ -475,8 +511,8 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) INT_MAX / step_y <= crop_top || INT_MAX / step_y - crop_top <= crop_bottom || 16 * sps->mb_height <= step_y * (crop_top + crop_bottom)) { - av_log(h->avctx, AV_LOG_WARNING, "Invalid crop parameters\n"); - if (h->avctx->err_recognition & AV_EF_EXPLODE) + av_log(avctx, AV_LOG_WARNING, "Invalid crop parameters\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) goto fail; crop_left = crop_right = crop_top = crop_bottom = 0; } @@ -494,19 +530,33 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->crop = 0; } - sps->vui_parameters_present_flag = get_bits1(&h->gb); + sps->vui_parameters_present_flag = get_bits1(gb); if (sps->vui_parameters_present_flag) { - int ret = decode_vui_parameters(h, sps); - if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE) + int ret = decode_vui_parameters(gb, avctx, sps); + if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) goto fail; } + /* if the maximum delay is not stored in the SPS, derive it based on the + * level */ + if (!sps->bitstream_restriction_flag && + (sps->ref_frame_count || avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)) { + sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + for (i = 0; i < FF_ARRAY_ELEMS(level_max_dpb_mbs); i++) { + if (level_max_dpb_mbs[i][0] == sps->level_idc) { + sps->num_reorder_frames = FFMIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), + sps->num_reorder_frames); + break; + } + } + } + if (!sps->sar.den) sps->sar.den = 1; - if (h->avctx->debug & FF_DEBUG_PICT_INFO) { + if (avctx->debug & FF_DEBUG_PICT_INFO) { static const char csp[4][5] = { "Gray", "420", "422", "444" }; - av_log(h->avctx, AV_LOG_DEBUG, + av_log(avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %"PRId32"/%"PRId32"\n", sps_id, sps->profile_idc, sps->level_idc, sps->poc_type, @@ -521,17 +571,93 @@ int ff_h264_decode_seq_parameter_set(H264Context *h) sps->timing_info_present_flag ? sps->num_units_in_tick : 0, sps->timing_info_present_flag ? sps->time_scale : 0); } - sps->new = 1; - av_free(h->sps_buffers[sps_id]); - h->sps_buffers[sps_id] = sps; - h->sps = *sps; + /* check if this is a repeat of an already parsed SPS, then keep the + * original one. + * otherwise drop all PPSes that depend on it */ + if (ps->sps_list[sps_id] && + !memcmp(ps->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) { + av_buffer_unref(&sps_buf); + } else { + remove_sps(ps, sps_id); + ps->sps_list[sps_id] = sps_buf; + } return 0; fail: - av_free(sps); - return -1; + av_buffer_unref(&sps_buf); + return AVERROR_INVALIDDATA; +} + +static void init_dequant8_coeff_table(PPS *pps, const SPS *sps) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (sps->bit_depth_luma - 8); + + for (i = 0; i < 6; i++) { + pps->dequant8_coeff[i] = pps->dequant8_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(pps->scaling_matrix8[j], pps->scaling_matrix8[i], + 64 * sizeof(uint8_t))) { + pps->dequant8_coeff[i] = pps->dequant8_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = ff_h264_quant_div6[q]; + int idx = ff_h264_quant_rem6[q]; + for (x = 0; x < 64; x++) + pps->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = + ((uint32_t)ff_h264_dequant8_coeff_init[idx][ff_h264_dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * + pps->scaling_matrix8[i][x]) << shift; + } + } +} + +static void init_dequant4_coeff_table(PPS *pps, const SPS *sps) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (sps->bit_depth_luma - 8); + for (i = 0; i < 6; i++) { + pps->dequant4_coeff[i] = pps->dequant4_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(pps->scaling_matrix4[j], pps->scaling_matrix4[i], + 16 * sizeof(uint8_t))) { + pps->dequant4_coeff[i] = pps->dequant4_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = ff_h264_quant_div6[q] + 2; + int idx = ff_h264_quant_rem6[q]; + for (x = 0; x < 16; x++) + pps->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = + ((uint32_t)ff_h264_dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * + pps->scaling_matrix4[i][x]) << shift; + } + } +} + +static void init_dequant_tables(PPS *pps, const SPS *sps) +{ + int i, x; + init_dequant4_coeff_table(pps, sps); + if (pps->transform_8x8_mode) + init_dequant8_coeff_table(pps, sps); + if (sps->transform_bypass) { + for (i = 0; i < 6; i++) + for (x = 0; x < 16; x++) + pps->dequant4_coeff[i][0][x] = 1 << 6; + if (pps->transform_8x8_mode) + for (i = 0; i < 6; i++) + for (x = 0; x < 64; x++) + pps->dequant8_coeff[i][0][x] = 1 << 6; + } } static void build_qp_table(PPS *pps, int t, int index, const int depth) @@ -543,116 +669,100 @@ static void build_qp_table(PPS *pps, int t, int index, const int depth) ff_h264_chroma_qp[depth - 8][av_clip(i + index, 0, max_qp)]; } -int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length) +int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx, + H264ParamSets *ps, int bit_length) { - unsigned int pps_id = get_ue_golomb(&h->gb); + AVBufferRef *pps_buf; + SPS *sps; + unsigned int pps_id = get_ue_golomb(gb); PPS *pps; - const int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8); + int qp_bd_offset; int bits_left; + int ret; if (pps_id >= MAX_PPS_COUNT) { - av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); + av_log(avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); return AVERROR_INVALIDDATA; - } else if (h->sps.bit_depth_luma > 10) { - av_log(h->avctx, AV_LOG_ERROR, - "Unimplemented luma bit depth=%d (max=10)\n", - h->sps.bit_depth_luma); - return AVERROR_PATCHWELCOME; } - pps = av_mallocz(sizeof(PPS)); - if (!pps) + pps_buf = av_buffer_allocz(sizeof(*pps)); + if (!pps_buf) return AVERROR(ENOMEM); - pps->sps_id = get_ue_golomb_31(&h->gb); + pps = (PPS*)pps_buf->data; + + pps->sps_id = get_ue_golomb_31(gb); if ((unsigned)pps->sps_id >= MAX_SPS_COUNT || - !h->sps_buffers[pps->sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, "sps_id %u out of range\n", pps->sps_id); + !ps->sps_list[pps->sps_id]) { + av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", pps->sps_id); + ret = AVERROR_INVALIDDATA; + goto fail; + } + sps = (SPS*)ps->sps_list[pps->sps_id]->data; + + if (sps->bit_depth_luma > 10) { + av_log(avctx, AV_LOG_ERROR, + "Unimplemented luma bit depth=%d (max=10)\n", + sps->bit_depth_luma); + ret = AVERROR_PATCHWELCOME; goto fail; } - pps->cabac = get_bits1(&h->gb); - pps->pic_order_present = get_bits1(&h->gb); - pps->slice_group_count = get_ue_golomb(&h->gb) + 1; + pps->cabac = get_bits1(gb); + pps->pic_order_present = get_bits1(gb); + pps->slice_group_count = get_ue_golomb(gb) + 1; if (pps->slice_group_count > 1) { - pps->mb_slice_group_map_type = get_ue_golomb(&h->gb); - av_log(h->avctx, AV_LOG_ERROR, "FMO not supported\n"); - switch (pps->mb_slice_group_map_type) { - case 0: -#if 0 - | for (i = 0; i <= num_slice_groups_minus1; i++) | | | - | run_length[i] |1 |ue(v) | -#endif - break; - case 2: -#if 0 - | for (i = 0; i < num_slice_groups_minus1; i++) { | | | - | top_left_mb[i] |1 |ue(v) | - | bottom_right_mb[i] |1 |ue(v) | - | } | | | -#endif - break; - case 3: - case 4: - case 5: -#if 0 - | slice_group_change_direction_flag |1 |u(1) | - | slice_group_change_rate_minus1 |1 |ue(v) | -#endif - break; - case 6: -#if 0 - | slice_group_id_cnt_minus1 |1 |ue(v) | - | for (i = 0; i <= slice_group_id_cnt_minus1; i++)| | | - | slice_group_id[i] |1 |u(v) | -#endif - break; - } + pps->mb_slice_group_map_type = get_ue_golomb(gb); + av_log(avctx, AV_LOG_ERROR, "FMO not supported\n"); } - pps->ref_count[0] = get_ue_golomb(&h->gb) + 1; - pps->ref_count[1] = get_ue_golomb(&h->gb) + 1; + pps->ref_count[0] = get_ue_golomb(gb) + 1; + pps->ref_count[1] = get_ue_golomb(gb) + 1; if (pps->ref_count[0] - 1 > 32 - 1 || pps->ref_count[1] - 1 > 32 - 1) { - av_log(h->avctx, AV_LOG_ERROR, "reference overflow (pps)\n"); + av_log(avctx, AV_LOG_ERROR, "reference overflow (pps)\n"); + ret = AVERROR_INVALIDDATA; goto fail; } - pps->weighted_pred = get_bits1(&h->gb); - pps->weighted_bipred_idc = get_bits(&h->gb, 2); - pps->init_qp = get_se_golomb(&h->gb) + 26 + qp_bd_offset; - pps->init_qs = get_se_golomb(&h->gb) + 26 + qp_bd_offset; - pps->chroma_qp_index_offset[0] = get_se_golomb(&h->gb); - pps->deblocking_filter_parameters_present = get_bits1(&h->gb); - pps->constrained_intra_pred = get_bits1(&h->gb); - pps->redundant_pic_cnt_present = get_bits1(&h->gb); + qp_bd_offset = 6 * (sps->bit_depth_luma - 8); + + pps->weighted_pred = get_bits1(gb); + pps->weighted_bipred_idc = get_bits(gb, 2); + pps->init_qp = get_se_golomb(gb) + 26 + qp_bd_offset; + pps->init_qs = get_se_golomb(gb) + 26 + qp_bd_offset; + pps->chroma_qp_index_offset[0] = get_se_golomb(gb); + pps->deblocking_filter_parameters_present = get_bits1(gb); + pps->constrained_intra_pred = get_bits1(gb); + pps->redundant_pic_cnt_present = get_bits1(gb); pps->transform_8x8_mode = 0; - // contents of sps/pps can change even if id doesn't, so reinit - h->dequant_coeff_pps = -1; - memcpy(pps->scaling_matrix4, h->sps_buffers[pps->sps_id]->scaling_matrix4, + memcpy(pps->scaling_matrix4, sps->scaling_matrix4, sizeof(pps->scaling_matrix4)); - memcpy(pps->scaling_matrix8, h->sps_buffers[pps->sps_id]->scaling_matrix8, + memcpy(pps->scaling_matrix8, sps->scaling_matrix8, sizeof(pps->scaling_matrix8)); - bits_left = bit_length - get_bits_count(&h->gb); + bits_left = bit_length - get_bits_count(gb); if (bits_left && (bits_left > 8 || - show_bits(&h->gb, bits_left) != 1 << (bits_left - 1))) { - pps->transform_8x8_mode = get_bits1(&h->gb); - decode_scaling_matrices(h, h->sps_buffers[pps->sps_id], pps, 0, + show_bits(gb, bits_left) != 1 << (bits_left - 1))) { + pps->transform_8x8_mode = get_bits1(gb); + decode_scaling_matrices(gb, sps, pps, 0, pps->scaling_matrix4, pps->scaling_matrix8); // second_chroma_qp_index_offset - pps->chroma_qp_index_offset[1] = get_se_golomb(&h->gb); + pps->chroma_qp_index_offset[1] = get_se_golomb(gb); } else { pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0]; } build_qp_table(pps, 0, pps->chroma_qp_index_offset[0], - h->sps.bit_depth_luma); + sps->bit_depth_luma); build_qp_table(pps, 1, pps->chroma_qp_index_offset[1], - h->sps.bit_depth_luma); + sps->bit_depth_luma); + + init_dequant_tables(pps, sps); + if (pps->chroma_qp_index_offset[0] != pps->chroma_qp_index_offset[1]) pps->chroma_qp_diff = 1; - if (h->avctx->debug & FF_DEBUG_PICT_INFO) { - av_log(h->avctx, AV_LOG_DEBUG, + if (avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(avctx, AV_LOG_DEBUG, "pps:%u sps:%u %s slice_groups:%d ref:%u/%u %s qp:%d/%d/%d/%d %s %s %s %s\n", pps_id, pps->sps_id, pps->cabac ? "CABAC" : "CAVLC", @@ -666,11 +776,12 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length) pps->transform_8x8_mode ? "8x8DCT" : ""); } - av_free(h->pps_buffers[pps_id]); - h->pps_buffers[pps_id] = pps; + remove_pps(ps, pps_id); + ps->pps_list[pps_id] = pps_buf; + return 0; fail: - av_free(pps); - return -1; + av_buffer_unref(&pps_buf); + return ret; } diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h new file mode 100644 index 0000000..9a32d93 --- /dev/null +++ b/libavcodec/h264_ps.h @@ -0,0 +1,155 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 parameter set handling + */ + +#ifndef AVCODEC_H264_PS_H +#define AVCODEC_H264_PS_H + +#include + +#include "libavutil/buffer.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "h264.h" + +#define MAX_SPS_COUNT 32 +#define MAX_PPS_COUNT 256 + +/** + * Sequence parameter set + */ +typedef struct SPS { + unsigned int sps_id; + int profile_idc; + int level_idc; + int chroma_format_idc; + int transform_bypass; ///< qpprime_y_zero_transform_bypass_flag + int log2_max_frame_num; ///< log2_max_frame_num_minus4 + 4 + int poc_type; ///< pic_order_cnt_type + int log2_max_poc_lsb; ///< log2_max_pic_order_cnt_lsb_minus4 + int delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + int poc_cycle_length; ///< num_ref_frames_in_pic_order_cnt_cycle + int ref_frame_count; ///< num_ref_frames + int gaps_in_frame_num_allowed_flag; + int mb_width; ///< pic_width_in_mbs_minus1 + 1 + ///< (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag) + int mb_height; + int frame_mbs_only_flag; + int mb_aff; ///< mb_adaptive_frame_field_flag + int direct_8x8_inference_flag; + int crop; ///< frame_cropping_flag + + /* those 4 are already in luma samples */ + unsigned int crop_left; ///< frame_cropping_rect_left_offset + unsigned int crop_right; ///< frame_cropping_rect_right_offset + unsigned int crop_top; ///< frame_cropping_rect_top_offset + unsigned int crop_bottom; ///< frame_cropping_rect_bottom_offset + int vui_parameters_present_flag; + AVRational sar; + int video_signal_type_present_flag; + int full_range; + int colour_description_present_flag; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; + int timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + int fixed_frame_rate_flag; + short offset_for_ref_frame[256]; // FIXME dyn aloc? + int bitstream_restriction_flag; + int num_reorder_frames; + int scaling_matrix_present; + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + int nal_hrd_parameters_present_flag; + int vcl_hrd_parameters_present_flag; + int pic_struct_present_flag; + int time_offset_length; + int cpb_cnt; ///< See H.264 E.1.2 + int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 + int cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 + int dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 + int bit_depth_luma; ///< bit_depth_luma_minus8 + 8 + int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 + int residual_color_transform_flag; ///< residual_colour_transform_flag + int constraint_set_flags; ///< constraint_set[0-3]_flag +} SPS; + +/** + * Picture parameter set + */ +typedef struct PPS { + unsigned int sps_id; + int cabac; ///< entropy_coding_mode_flag + int pic_order_present; ///< pic_order_present_flag + int slice_group_count; ///< num_slice_groups_minus1 + 1 + int mb_slice_group_map_type; + unsigned int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 + int weighted_pred; ///< weighted_pred_flag + int weighted_bipred_idc; + int init_qp; ///< pic_init_qp_minus26 + 26 + int init_qs; ///< pic_init_qs_minus26 + 26 + int chroma_qp_index_offset[2]; + int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag + int constrained_intra_pred; ///< constrained_intra_pred_flag + int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag + int transform_8x8_mode; ///< transform_8x8_mode_flag + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + uint8_t chroma_qp_table[2][64]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table + int chroma_qp_diff; + + uint32_t dequant4_buffer[6][QP_MAX_NUM + 1][16]; + uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64]; + uint32_t(*dequant4_coeff[6])[16]; + uint32_t(*dequant8_coeff[6])[64]; +} PPS; + +typedef struct H264ParamSets { + AVBufferRef *sps_list[MAX_SPS_COUNT]; + AVBufferRef *pps_list[MAX_PPS_COUNT]; + + /* currently active parameters sets */ + const PPS *pps; + // FIXME this should properly be const + SPS *sps; +} H264ParamSets; + +/** + * Decode SPS + */ +int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, + H264ParamSets *ps); + +/** + * Decode PPS + */ +int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx, + H264ParamSets *ps, int bit_length); + +#endif /* AVCODEC_H264_PS_H */ diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 03c1b9c..eff5991 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 reference picture handling. + * H.264 / AVC / MPEG-4 part10 reference picture handling. * @author Michael Niedermayer */ @@ -30,36 +30,40 @@ #include "internal.h" #include "avcodec.h" #include "h264.h" +#include "h264dec.h" #include "golomb.h" #include "mpegutils.h" #include -#define COPY_PICTURE(dst, src) \ -do {\ - *(dst) = *(src);\ - (dst)->f.extended_data = (dst)->f.data;\ - (dst)->tf.f = &(dst)->f;\ -} while (0) - - -static void pic_as_field(H264Picture *pic, const int parity){ +static void pic_as_field(H264Ref *pic, const int parity) +{ int i; - for (i = 0; i < 4; ++i) { + for (i = 0; i < FF_ARRAY_ELEMS(pic->data); ++i) { if (parity == PICT_BOTTOM_FIELD) - pic->f.data[i] += pic->f.linesize[i]; + pic->data[i] += pic->linesize[i]; pic->reference = parity; - pic->f.linesize[i] *= 2; + pic->linesize[i] *= 2; } - pic->poc= pic->field_poc[parity == PICT_BOTTOM_FIELD]; + pic->poc = pic->parent->field_poc[parity == PICT_BOTTOM_FIELD]; +} + +static void ref_from_h264pic(H264Ref *dst, H264Picture *src) +{ + memcpy(dst->data, src->f->data, sizeof(dst->data)); + memcpy(dst->linesize, src->f->linesize, sizeof(dst->linesize)); + dst->reference = src->reference; + dst->poc = src->poc; + dst->pic_id = src->pic_id; + dst->parent = src; } -static int split_field_copy(H264Picture *dest, H264Picture *src, int parity, int id_add) +static int split_field_copy(H264Ref *dest, H264Picture *src, int parity, int id_add) { int match = !!(src->reference & parity); if (match) { - COPY_PICTURE(dest, src); + ref_from_h264pic(dest, src); if (parity != PICT_FRAME) { pic_as_field(dest, parity); dest->pic_id *= 2; @@ -70,8 +74,8 @@ static int split_field_copy(H264Picture *dest, H264Picture *src, int parity, int return match; } -static int build_def_list(H264Picture *def, int def_len, - H264Picture **in, int len, int is_long, int sel) +static int build_def_list(H264Ref *def, int def_len, + H264Picture * const *in, int len, int is_long, int sel) { int i[2] = { 0 }; int index = 0; @@ -94,7 +98,8 @@ static int build_def_list(H264Picture *def, int def_len, return index; } -static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limit, int dir) +static int add_sorted(H264Picture **sorted, H264Picture * const *src, + int len, int limit, int dir) { int i, best_poc; int out_i = 0; @@ -116,11 +121,11 @@ static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limi return out_i; } -int ff_h264_fill_default_ref_list(H264Context *h) +static void h264_initialise_ref_list(const H264Context *h, H264SliceContext *sl) { int i, len; - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) { H264Picture *sorted[32]; int cur_poc, list; int lens[2]; @@ -135,59 +140,70 @@ int ff_h264_fill_default_ref_list(H264Context *h) len += add_sorted(sorted + len, h->short_ref, h->short_ref_count, cur_poc, 0 ^ list); assert(len <= 32); - len = build_def_list(h->default_ref_list[list], FF_ARRAY_ELEMS(h->default_ref_list[0]), + len = build_def_list(sl->ref_list[list], FF_ARRAY_ELEMS(sl->ref_list[0]), sorted, len, 0, h->picture_structure); - len += build_def_list(h->default_ref_list[list] + len, - FF_ARRAY_ELEMS(h->default_ref_list[0]) - len, + len += build_def_list(sl->ref_list[list] + len, + FF_ARRAY_ELEMS(sl->ref_list[0]) - len, h->long_ref, 16, 1, h->picture_structure); - if (len < h->ref_count[list]) - memset(&h->default_ref_list[list][len], 0, sizeof(H264Picture) * (h->ref_count[list] - len)); + if (len < sl->ref_count[list]) + memset(&sl->ref_list[list][len], 0, sizeof(H264Ref) * (sl->ref_count[list] - len)); lens[list] = len; } if (lens[0] == lens[1] && lens[1] > 1) { for (i = 0; i < lens[0] && - h->default_ref_list[0][i].f.buf[0]->buffer == - h->default_ref_list[1][i].f.buf[0]->buffer; i++); + sl->ref_list[0][i].parent->f->buf[0]->buffer == + sl->ref_list[1][i].parent->f->buf[0]->buffer; i++); if (i == lens[0]) { - H264Picture tmp; - COPY_PICTURE(&tmp, &h->default_ref_list[1][0]); - COPY_PICTURE(&h->default_ref_list[1][0], &h->default_ref_list[1][1]); - COPY_PICTURE(&h->default_ref_list[1][1], &tmp); + FFSWAP(H264Ref, sl->ref_list[1][0], sl->ref_list[1][1]); } } } else { - len = build_def_list(h->default_ref_list[0], FF_ARRAY_ELEMS(h->default_ref_list[0]), + len = build_def_list(sl->ref_list[0], FF_ARRAY_ELEMS(sl->ref_list[0]), h->short_ref, h->short_ref_count, 0, h->picture_structure); - len += build_def_list(h->default_ref_list[0] + len, - FF_ARRAY_ELEMS(h->default_ref_list[0]) - len, + len += build_def_list(sl->ref_list[0] + len, + FF_ARRAY_ELEMS(sl->ref_list[0]) - len, h-> long_ref, 16, 1, h->picture_structure); - if (len < h->ref_count[0]) - memset(&h->default_ref_list[0][len], 0, sizeof(H264Picture) * (h->ref_count[0] - len)); - } -#ifdef TRACE - for (i = 0; i < h->ref_count[0]; i++) { - tprintf(h->avctx, "List0: %s fn:%d 0x%p\n", - (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), - h->default_ref_list[0][i].pic_id, - h->default_ref_list[0][i].f.data[0]); + if (len < sl->ref_count[0]) + memset(&sl->ref_list[0][len], 0, sizeof(H264Ref) * (sl->ref_count[0] - len)); } - if (h->slice_type_nos == AV_PICTURE_TYPE_B) { - for (i = 0; i < h->ref_count[1]; i++) { - tprintf(h->avctx, "List1: %s fn:%d 0x%p\n", - (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), - h->default_ref_list[1][i].pic_id, - h->default_ref_list[1][i].f.data[0]); +} + +/** + * print short term list + */ +static void print_short_term(const H264Context *h) +{ + uint32_t i; + if (h->avctx->debug & FF_DEBUG_MMCO) { + av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n"); + for (i = 0; i < h->short_ref_count; i++) { + H264Picture *pic = h->short_ref[i]; + av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n", + i, pic->frame_num, pic->poc, pic->f->data[0]); } } -#endif - return 0; } -static void print_short_term(H264Context *h); -static void print_long_term(H264Context *h); +/** + * print long term list + */ +static void print_long_term(const H264Context *h) +{ + uint32_t i; + if (h->avctx->debug & FF_DEBUG_MMCO) { + av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n"); + for (i = 0; i < 16; i++) { + H264Picture *pic = h->long_ref[i]; + if (pic) { + av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n", + i, pic->frame_num, pic->poc, pic->f->data[0]); + } + } + } +} /** * Extract structure information about the picture described by pic_num in @@ -199,7 +215,7 @@ static void print_long_term(H264Context *h); * @return frame number (short term) or long term index of picture * described by pic_num */ -static int pic_num_extract(H264Context *h, int pic_num, int *structure) +static int pic_num_extract(const H264Context *h, int pic_num, int *structure) { *structure = h->picture_structure; if (FIELD_PICTURE(h)) { @@ -212,157 +228,178 @@ static int pic_num_extract(H264Context *h, int pic_num, int *structure) return pic_num; } -int ff_h264_decode_ref_pic_list_reordering(H264Context *h) +static void h264_fill_mbaff_ref_list(H264SliceContext *sl) { - int list, index, pic_structure, i; + int list, i, j; + for (list = 0; list < sl->list_count; list++) { + for (i = 0; i < sl->ref_count[list]; i++) { + H264Ref *frame = &sl->ref_list[list][i]; + H264Ref *field = &sl->ref_list[list][16 + 2 * i]; - print_short_term(h); - print_long_term(h); + field[0] = *frame; - for (list = 0; list < h->list_count; list++) { - for (i = 0; i < h->ref_count[list]; i++) - COPY_PICTURE(&h->ref_list[list][i], &h->default_ref_list[list][i]); + for (j = 0; j < 3; j++) + field[0].linesize[j] <<= 1; + field[0].reference = PICT_TOP_FIELD; + field[0].poc = field[0].parent->field_poc[0]; - if (get_bits1(&h->gb)) { // ref_pic_list_modification_flag_l[01] - int pred = h->curr_pic_num; + field[1] = field[0]; - for (index = 0; ; index++) { - unsigned int modification_of_pic_nums_idc = get_ue_golomb_31(&h->gb); - unsigned int pic_id; - int i; - H264Picture *ref = NULL; + for (j = 0; j < 3; j++) + field[1].data[j] += frame->parent->f->linesize[j]; + field[1].reference = PICT_BOTTOM_FIELD; + field[1].poc = field[1].parent->field_poc[1]; + } + } +} - if (modification_of_pic_nums_idc == 3) - break; +int ff_h264_build_ref_list(const H264Context *h, H264SliceContext *sl) +{ + int list, index, pic_structure; - if (index >= h->ref_count[list]) { - av_log(h->avctx, AV_LOG_ERROR, "reference count overflow\n"); - return -1; - } + print_short_term(h); + print_long_term(h); - switch (modification_of_pic_nums_idc) { - case 0: - case 1: { - const unsigned int abs_diff_pic_num = get_ue_golomb(&h->gb) + 1; - int frame_num; + h264_initialise_ref_list(h, sl); - if (abs_diff_pic_num > h->max_pic_num) { - av_log(h->avctx, AV_LOG_ERROR, - "abs_diff_pic_num overflow\n"); - return AVERROR_INVALIDDATA; - } + for (list = 0; list < sl->list_count; list++) { + int pred = sl->curr_pic_num; - if (modification_of_pic_nums_idc == 0) - pred -= abs_diff_pic_num; - else - pred += abs_diff_pic_num; - pred &= h->max_pic_num - 1; - - frame_num = pic_num_extract(h, pred, &pic_structure); - - for (i = h->short_ref_count - 1; i >= 0; i--) { - ref = h->short_ref[i]; - assert(ref->reference); - assert(!ref->long_ref); - if (ref->frame_num == frame_num && - (ref->reference & pic_structure)) - break; - } - if (i >= 0) - ref->pic_id = pred; - break; - } - case 2: { - int long_idx; - pic_id = get_ue_golomb(&h->gb); // long_term_pic_idx + for (index = 0; index < sl->nb_ref_modifications[list]; index++) { + unsigned int modification_of_pic_nums_idc = sl->ref_modifications[list][index].op; + unsigned int val = sl->ref_modifications[list][index].val; + unsigned int pic_id; + int i; + H264Picture *ref = NULL; - long_idx = pic_num_extract(h, pic_id, &pic_structure); + switch (modification_of_pic_nums_idc) { + case 0: + case 1: { + const unsigned int abs_diff_pic_num = val + 1; + int frame_num; - if (long_idx > 31) { - av_log(h->avctx, AV_LOG_ERROR, - "long_term_pic_idx overflow\n"); - return AVERROR_INVALIDDATA; - } - ref = h->long_ref[long_idx]; - assert(!(ref && !ref->reference)); - if (ref && (ref->reference & pic_structure)) { - ref->pic_id = pic_id; - assert(ref->long_ref); - i = 0; - } else { - i = -1; - } - break; - } - default: + if (abs_diff_pic_num > sl->max_pic_num) { av_log(h->avctx, AV_LOG_ERROR, - "illegal modification_of_pic_nums_idc %u\n", - modification_of_pic_nums_idc); + "abs_diff_pic_num overflow\n"); return AVERROR_INVALIDDATA; } - if (i < 0) { + if (modification_of_pic_nums_idc == 0) + pred -= abs_diff_pic_num; + else + pred += abs_diff_pic_num; + pred &= sl->max_pic_num - 1; + + frame_num = pic_num_extract(h, pred, &pic_structure); + + for (i = h->short_ref_count - 1; i >= 0; i--) { + ref = h->short_ref[i]; + assert(ref->reference); + assert(!ref->long_ref); + if (ref->frame_num == frame_num && + (ref->reference & pic_structure)) + break; + } + if (i >= 0) + ref->pic_id = pred; + break; + } + case 2: { + int long_idx; + pic_id = val; // long_term_pic_idx + + long_idx = pic_num_extract(h, pic_id, &pic_structure); + + if (long_idx > 31) { av_log(h->avctx, AV_LOG_ERROR, - "reference picture missing during reorder\n"); - memset(&h->ref_list[list][index], 0, sizeof(H264Picture)); // FIXME + "long_term_pic_idx overflow\n"); + return AVERROR_INVALIDDATA; + } + ref = h->long_ref[long_idx]; + assert(!(ref && !ref->reference)); + if (ref && (ref->reference & pic_structure)) { + ref->pic_id = pic_id; + assert(ref->long_ref); + i = 0; } else { - for (i = index; i + 1 < h->ref_count[list]; i++) { - if (ref->long_ref == h->ref_list[list][i].long_ref && - ref->pic_id == h->ref_list[list][i].pic_id) - break; - } - for (; i > index; i--) { - COPY_PICTURE(&h->ref_list[list][i], &h->ref_list[list][i - 1]); - } - COPY_PICTURE(&h->ref_list[list][index], ref); - if (FIELD_PICTURE(h)) { - pic_as_field(&h->ref_list[list][index], pic_structure); - } + i = -1; + } + break; + } + } + + if (i < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "reference picture missing during reorder\n"); + memset(&sl->ref_list[list][index], 0, sizeof(sl->ref_list[0][0])); // FIXME + } else { + for (i = index; i + 1 < sl->ref_count[list]; i++) { + if (sl->ref_list[list][i].parent && + ref->long_ref == sl->ref_list[list][i].parent->long_ref && + ref->pic_id == sl->ref_list[list][i].pic_id) + break; + } + for (; i > index; i--) { + sl->ref_list[list][i] = sl->ref_list[list][i - 1]; + } + ref_from_h264pic(&sl->ref_list[list][index], ref); + if (FIELD_PICTURE(h)) { + pic_as_field(&sl->ref_list[list][index], pic_structure); } } } } - for (list = 0; list < h->list_count; list++) { - for (index = 0; index < h->ref_count[list]; index++) { - if (!h->ref_list[list][index].f.buf[0]) { + for (list = 0; list < sl->list_count; list++) { + for (index = 0; index < sl->ref_count[list]; index++) { + if (!sl->ref_list[list][index].parent) { av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture\n"); - if (h->default_ref_list[list][0].f.buf[0]) - COPY_PICTURE(&h->ref_list[list][index], &h->default_ref_list[list][0]); + if (index == 0 || h->avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; else - return -1; + sl->ref_list[list][index] = sl->ref_list[list][index - 1]; } } } + if (FRAME_MBAFF(h)) + h264_fill_mbaff_ref_list(sl); + return 0; } -void ff_h264_fill_mbaff_ref_list(H264Context *h) +int ff_h264_decode_ref_pic_list_reordering(H264SliceContext *sl, void *logctx) { - int list, i, j; - for (list = 0; list < 2; list++) { //FIXME try list_count - for (i = 0; i < h->ref_count[list]; i++) { - H264Picture *frame = &h->ref_list[list][i]; - H264Picture *field = &h->ref_list[list][16 + 2 * i]; - COPY_PICTURE(field, frame); - for (j = 0; j < 3; j++) - field[0].f.linesize[j] <<= 1; - field[0].reference = PICT_TOP_FIELD; - field[0].poc = field[0].field_poc[0]; - COPY_PICTURE(field + 1, field); - for (j = 0; j < 3; j++) - field[1].f.data[j] += frame->f.linesize[j]; - field[1].reference = PICT_BOTTOM_FIELD; - field[1].poc = field[1].field_poc[1]; + int list, index; - h->luma_weight[16 + 2 * i][list][0] = h->luma_weight[16 + 2 * i + 1][list][0] = h->luma_weight[i][list][0]; - h->luma_weight[16 + 2 * i][list][1] = h->luma_weight[16 + 2 * i + 1][list][1] = h->luma_weight[i][list][1]; - for (j = 0; j < 2; j++) { - h->chroma_weight[16 + 2 * i][list][j][0] = h->chroma_weight[16 + 2 * i + 1][list][j][0] = h->chroma_weight[i][list][j][0]; - h->chroma_weight[16 + 2 * i][list][j][1] = h->chroma_weight[16 + 2 * i + 1][list][j][1] = h->chroma_weight[i][list][j][1]; + sl->nb_ref_modifications[0] = 0; + sl->nb_ref_modifications[1] = 0; + + for (list = 0; list < sl->list_count; list++) { + if (!get_bits1(&sl->gb)) // ref_pic_list_modification_flag_l[01] + continue; + + for (index = 0; ; index++) { + unsigned int op = get_ue_golomb_31(&sl->gb); + + if (op == 3) + break; + + if (index >= sl->ref_count[list]) { + av_log(logctx, AV_LOG_ERROR, "reference count overflow\n"); + return AVERROR_INVALIDDATA; + } else if (op > 2) { + av_log(logctx, AV_LOG_ERROR, + "illegal modification_of_pic_nums_idc %u\n", + op); + return AVERROR_INVALIDDATA; } + sl->ref_modifications[list][index].val = get_ue_golomb(&sl->gb); + sl->ref_modifications[list][index].op = op; + sl->nb_ref_modifications[list]++; } } + + return 0; } /** @@ -431,7 +468,6 @@ static void remove_short_at_index(H264Context *h, int i) } /** - * * @return the removed picture or NULL if an error occurs */ static H264Picture *remove_short(H264Context *h, int frame_num, int ref_mask) @@ -489,92 +525,48 @@ void ff_h264_remove_all_refs(H264Context *h) h->short_ref_count = 0; } -/** - * print short term list - */ -static void print_short_term(H264Context *h) +static void generate_sliding_window_mmcos(H264Context *h) { - uint32_t i; - if (h->avctx->debug & FF_DEBUG_MMCO) { - av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n"); - for (i = 0; i < h->short_ref_count; i++) { - H264Picture *pic = h->short_ref[i]; - av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n", - i, pic->frame_num, pic->poc, pic->f.data[0]); - } - } -} + MMCO *mmco = h->mmco; + int nb_mmco = 0; -/** - * print long term list - */ -static void print_long_term(H264Context *h) -{ - uint32_t i; - if (h->avctx->debug & FF_DEBUG_MMCO) { - av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n"); - for (i = 0; i < 16; i++) { - H264Picture *pic = h->long_ref[i]; - if (pic) { - av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n", - i, pic->frame_num, pic->poc, pic->f.data[0]); - } - } - } -} - -static int check_opcodes(MMCO *mmco1, MMCO *mmco2, int n_mmcos) -{ - int i; - - for (i = 0; i < n_mmcos; i++) { - if (mmco1[i].opcode != mmco2[i].opcode) - return -1; - } - - return 0; -} - -int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice) -{ - MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; - int mmco_index = 0, i = 0; - - assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count); + assert(h->long_ref_count + h->short_ref_count <= h->ps.sps->ref_frame_count); if (h->short_ref_count && - h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count && + h->long_ref_count + h->short_ref_count == h->ps.sps->ref_frame_count && !(FIELD_PICTURE(h) && !h->first_field && h->cur_pic_ptr->reference)) { mmco[0].opcode = MMCO_SHORT2UNUSED; mmco[0].short_pic_num = h->short_ref[h->short_ref_count - 1]->frame_num; - mmco_index = 1; + nb_mmco = 1; if (FIELD_PICTURE(h)) { mmco[0].short_pic_num *= 2; mmco[1].opcode = MMCO_SHORT2UNUSED; mmco[1].short_pic_num = mmco[0].short_pic_num + 1; - mmco_index = 2; + nb_mmco = 2; } } - if (first_slice) { - h->mmco_index = mmco_index; - } else if (!first_slice && mmco_index >= 0 && - (mmco_index != h->mmco_index || - (i = check_opcodes(h->mmco, mmco_temp, mmco_index)))) { - av_log(h->avctx, AV_LOG_ERROR, - "Inconsistent MMCO state between slices [%d, %d, %d]\n", - mmco_index, h->mmco_index, i); - return AVERROR_INVALIDDATA; - } - return 0; + h->nb_mmco = nb_mmco; } -int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) +int ff_h264_execute_ref_pic_marking(H264Context *h) { + MMCO *mmco = h->mmco; + int mmco_count; int i, av_uninit(j); int current_ref_assigned = 0, err = 0; H264Picture *av_uninit(pic); + if (!h->ps.sps) { + av_log(h->avctx, AV_LOG_ERROR, "SPS is unset\n"); + err = AVERROR_INVALIDDATA; + goto out; + } + + if (!h->explicit_ref_marking) + generate_sliding_window_mmcos(h); + mmco_count = h->nb_mmco; + if ((h->avctx->debug & FF_DEBUG_MMCO) && mmco_count == 0) av_log(h->avctx, AV_LOG_DEBUG, "no mmco here\n"); @@ -626,7 +618,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref long failure\n"); break; case MMCO_LONG: - // Comment below left from previous code as it is an interresting note. + // Comment below left from previous code as it is an interesting note. /* First field in pair is in short term list or * at a different long term index. * This is not allowed; see 7.4.3.3, notes 2 and 3. @@ -636,6 +628,15 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) if (h->short_ref[0] == h->cur_pic_ptr) remove_short_at_index(h, 0); + /* make sure the current picture is not already assigned as a long ref */ + if (h->cur_pic_ptr->long_ref) { + for (j = 0; j < FF_ARRAY_ELEMS(h->long_ref); j++) { + if (h->long_ref[j] == h->cur_pic_ptr) + remove_long(h, j, 0); + } + } + + if (h->long_ref[mmco[i].long_arg] != h->cur_pic_ptr) { remove_long(h, mmco[i].long_arg, 0); @@ -661,7 +662,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) for (j = 0; j < 16; j++) { remove_long(h, j, 0); } - h->frame_num = h->cur_pic_ptr->frame_num = 0; + h->poc.frame_num = h->cur_pic_ptr->frame_num = 0; h->mmco_reset = 1; h->cur_pic_ptr->mmco_reset = 1; break; @@ -703,7 +704,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) } if (h->long_ref_count + h->short_ref_count - - (h->short_ref[0] == h->cur_pic_ptr) > h->sps.ref_frame_count) { + (h->short_ref[0] == h->cur_pic_ptr) > h->ps.sps->ref_frame_count) { /* We have too many reference frames, probably due to corrupted * stream. Need to discard one frame. Prevents overrun of the @@ -712,7 +713,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) av_log(h->avctx, AV_LOG_ERROR, "number of reference frames (%d+%d) exceeds max (%d; probably " "corrupt input), discarding one\n", - h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count); + h->long_ref_count, h->short_ref_count, h->ps.sps->ref_frame_count); err = AVERROR_INVALIDDATA; if (h->long_ref_count && !h->short_ref_count) { @@ -730,42 +731,36 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) print_short_term(h); print_long_term(h); +out: return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0; } -int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, - int first_slice) +int ff_h264_decode_ref_pic_marking(H264SliceContext *sl, GetBitContext *gb, + const H2645NAL *nal, void *logctx) { - int i, ret; - MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; - int mmco_index = 0; + int i; + MMCO *mmco = sl->mmco; + int nb_mmco = 0; - if (h->nal_unit_type == NAL_IDR_SLICE) { // FIXME fields + if (nal->type == H264_NAL_IDR_SLICE) { // FIXME fields skip_bits1(gb); // broken_link if (get_bits1(gb)) { mmco[0].opcode = MMCO_LONG; mmco[0].long_arg = 0; - mmco_index = 1; + nb_mmco = 1; } + sl->explicit_ref_marking = 1; } else { - if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag + sl->explicit_ref_marking = get_bits1(gb); + if (sl->explicit_ref_marking) { for (i = 0; i < MAX_MMCO_COUNT; i++) { MMCOOpcode opcode = get_ue_golomb_31(gb); mmco[i].opcode = opcode; if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) { mmco[i].short_pic_num = - (h->curr_pic_num - get_ue_golomb(gb) - 1) & - (h->max_pic_num - 1); -#if 0 - if (mmco[i].short_pic_num >= h->short_ref_count || - !h->short_ref[mmco[i].short_pic_num]) { - av_log(s->avctx, AV_LOG_ERROR, - "illegal short ref in memory management control " - "operation %d\n", mmco); - return -1; - } -#endif + (sl->curr_pic_num - get_ue_golomb(gb) - 1) & + (sl->max_pic_num - 1); } if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED || opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) { @@ -773,8 +768,8 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, if (long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG && long_arg == 16) && - !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE(h)))) { - av_log(h->avctx, AV_LOG_ERROR, + !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE(sl)))) { + av_log(logctx, AV_LOG_ERROR, "illegal long ref in memory management control " "operation %d\n", opcode); return -1; @@ -783,7 +778,7 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, } if (opcode > (unsigned) MMCO_LONG) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(logctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); return -1; @@ -791,27 +786,11 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, if (opcode == MMCO_END) break; } - mmco_index = i; - } else { - if (first_slice) { - ret = ff_generate_sliding_window_mmcos(h, first_slice); - if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE) - return ret; - } - mmco_index = -1; + nb_mmco = i; } } - if (first_slice && mmco_index != -1) { - h->mmco_index = mmco_index; - } else if (!first_slice && mmco_index >= 0 && - (mmco_index != h->mmco_index || - check_opcodes(h->mmco, mmco_temp, mmco_index))) { - av_log(h->avctx, AV_LOG_ERROR, - "Inconsistent MMCO state between slices [%d, %d]\n", - mmco_index, h->mmco_index); - return AVERROR_INVALIDDATA; - } + sl->nb_mmco = nb_mmco; return 0; } diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 52ff2ff..7eef3ee 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -1,5 +1,5 @@ /* - * H.26L/H.264/AVC/JVT/14496-10/... sei decoding + * H.26L/H.264/AVC/JVT/14496-10/... SEI decoding * Copyright (c) 2003 Michael Niedermayer * * This file is part of Libav. @@ -21,266 +21,387 @@ /** * @file - * H.264 / AVC / MPEG4 part10 sei decoding. + * H.264 / AVC / MPEG-4 part10 SEI decoding. * @author Michael Niedermayer */ #include "avcodec.h" +#include "get_bits.h" #include "golomb.h" -#include "h264.h" +#include "h264_ps.h" +#include "h264_sei.h" #include "internal.h" static const uint8_t sei_num_clock_ts_table[9] = { 1, 1, 1, 2, 2, 3, 3, 2, 3 }; -void ff_h264_reset_sei(H264Context *h) +void ff_h264_sei_uninit(H264SEIContext *h) { - h->sei_recovery_frame_cnt = -1; - h->sei_dpb_output_delay = 0; - h->sei_cpb_removal_delay = -1; - h->sei_buffering_period_present = 0; - h->sei_frame_packing_present = 0; - h->sei_display_orientation_present = 0; + h->unregistered.x264_build = -1; + h->recovery_point.recovery_frame_cnt = -1; + + h->picture_timing.dpb_output_delay = 0; + h->picture_timing.cpb_removal_delay = -1; + + h->buffering_period.present = 0; + h->frame_packing.present = 0; + h->display_orientation.present = 0; + h->afd.present = 0; + + h->a53_caption.a53_caption_size = 0; + av_freep(&h->a53_caption.a53_caption); } -static int decode_picture_timing(H264Context *h) +static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb, + const SPS *sps, void *logctx) { - if (h->sps.nal_hrd_parameters_present_flag || - h->sps.vcl_hrd_parameters_present_flag) { - h->sei_cpb_removal_delay = get_bits(&h->gb, - h->sps.cpb_removal_delay_length); - h->sei_dpb_output_delay = get_bits(&h->gb, - h->sps.dpb_output_delay_length); + if (!sps) + return AVERROR_INVALIDDATA; + + if (sps->nal_hrd_parameters_present_flag || + sps->vcl_hrd_parameters_present_flag) { + h->cpb_removal_delay = get_bits(gb, sps->cpb_removal_delay_length); + h->dpb_output_delay = get_bits(gb, sps->dpb_output_delay_length); } - if (h->sps.pic_struct_present_flag) { + if (sps->pic_struct_present_flag) { unsigned int i, num_clock_ts; - h->sei_pic_struct = get_bits(&h->gb, 4); - h->sei_ct_type = 0; + h->pic_struct = get_bits(gb, 4); + h->ct_type = 0; - if (h->sei_pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING) + if (h->pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING) return AVERROR_INVALIDDATA; - num_clock_ts = sei_num_clock_ts_table[h->sei_pic_struct]; + num_clock_ts = sei_num_clock_ts_table[h->pic_struct]; for (i = 0; i < num_clock_ts; i++) { - if (get_bits(&h->gb, 1)) { /* clock_timestamp_flag */ + if (get_bits(gb, 1)) { /* clock_timestamp_flag */ unsigned int full_timestamp_flag; - h->sei_ct_type |= 1 << get_bits(&h->gb, 2); - skip_bits(&h->gb, 1); /* nuit_field_based_flag */ - skip_bits(&h->gb, 5); /* counting_type */ - full_timestamp_flag = get_bits(&h->gb, 1); - skip_bits(&h->gb, 1); /* discontinuity_flag */ - skip_bits(&h->gb, 1); /* cnt_dropped_flag */ - skip_bits(&h->gb, 8); /* n_frames */ + h->ct_type |= 1 << get_bits(gb, 2); + skip_bits(gb, 1); /* nuit_field_based_flag */ + skip_bits(gb, 5); /* counting_type */ + full_timestamp_flag = get_bits(gb, 1); + skip_bits(gb, 1); /* discontinuity_flag */ + skip_bits(gb, 1); /* cnt_dropped_flag */ + skip_bits(gb, 8); /* n_frames */ if (full_timestamp_flag) { - skip_bits(&h->gb, 6); /* seconds_value 0..59 */ - skip_bits(&h->gb, 6); /* minutes_value 0..59 */ - skip_bits(&h->gb, 5); /* hours_value 0..23 */ + skip_bits(gb, 6); /* seconds_value 0..59 */ + skip_bits(gb, 6); /* minutes_value 0..59 */ + skip_bits(gb, 5); /* hours_value 0..23 */ } else { - if (get_bits(&h->gb, 1)) { /* seconds_flag */ - skip_bits(&h->gb, 6); /* seconds_value range 0..59 */ - if (get_bits(&h->gb, 1)) { /* minutes_flag */ - skip_bits(&h->gb, 6); /* minutes_value 0..59 */ - if (get_bits(&h->gb, 1)) /* hours_flag */ - skip_bits(&h->gb, 5); /* hours_value 0..23 */ + if (get_bits(gb, 1)) { /* seconds_flag */ + skip_bits(gb, 6); /* seconds_value range 0..59 */ + if (get_bits(gb, 1)) { /* minutes_flag */ + skip_bits(gb, 6); /* minutes_value 0..59 */ + if (get_bits(gb, 1)) /* hours_flag */ + skip_bits(gb, 5); /* hours_value 0..23 */ } } } - if (h->sps.time_offset_length > 0) - skip_bits(&h->gb, - h->sps.time_offset_length); /* time_offset */ + if (sps->time_offset_length > 0) + skip_bits(gb, + sps->time_offset_length); /* time_offset */ } } - if (h->avctx->debug & FF_DEBUG_PICT_INFO) - av_log(h->avctx, AV_LOG_DEBUG, "ct_type:%X pic_struct:%d\n", - h->sei_ct_type, h->sei_pic_struct); + av_log(logctx, AV_LOG_DEBUG, "ct_type:%X pic_struct:%d\n", + h->ct_type, h->pic_struct); } return 0; } -static int decode_unregistered_user_data(H264Context *h, int size) +static int decode_registered_user_data_afd(H264SEIAFD *h, GetBitContext *gb, int size) { - uint8_t user_data[16 + 256]; + int flag; + + if (size-- < 1) + return AVERROR_INVALIDDATA; + skip_bits(gb, 1); // 0 + flag = get_bits(gb, 1); // active_format_flag + skip_bits(gb, 6); // reserved + + if (flag) { + if (size-- < 1) + return AVERROR_INVALIDDATA; + skip_bits(gb, 4); // reserved + h->active_format_description = get_bits(gb, 4); + h->present = 1; + } + + return 0; +} + +static int decode_registered_user_data_closed_caption(H264SEIA53Caption *h, + GetBitContext *gb, void *logctx, + int size) +{ + int flag; + int user_data_type_code; + int cc_count; + + if (size < 3) + return AVERROR(EINVAL); + + user_data_type_code = get_bits(gb, 8); + if (user_data_type_code == 0x3) { + skip_bits(gb, 1); // reserved + + flag = get_bits(gb, 1); // process_cc_data_flag + if (flag) { + skip_bits(gb, 1); // zero bit + cc_count = get_bits(gb, 5); + skip_bits(gb, 8); // reserved + size -= 2; + + if (cc_count && size >= cc_count * 3) { + const uint64_t new_size = (h->a53_caption_size + cc_count + * UINT64_C(3)); + int i, ret; + + if (new_size > INT_MAX) + return AVERROR(EINVAL); + + /* Allow merging of the cc data from two fields. */ + ret = av_reallocp(&h->a53_caption, new_size); + if (ret < 0) + return ret; + + for (i = 0; i < cc_count; i++) { + h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8); + h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8); + h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8); + } + + skip_bits(gb, 8); // marker_bits + } + } + } else { + int i; + avpriv_request_sample(logctx, "Subtitles with data type 0x%02x", + user_data_type_code); + for (i = 0; i < size - 1; i++) + skip_bits(gb, 8); + } + + return 0; +} + +static int decode_registered_user_data(H264SEIContext *h, GetBitContext *gb, + void *logctx, int size) +{ + uint32_t country_code; + uint32_t user_identifier; + + if (size < 7) + return AVERROR_INVALIDDATA; + size -= 7; + + country_code = get_bits(gb, 8); // itu_t_t35_country_code + if (country_code == 0xFF) { + skip_bits(gb, 8); // itu_t_t35_country_code_extension_byte + size--; + } + + /* itu_t_t35_payload_byte follows */ + skip_bits(gb, 8); // terminal provider code + skip_bits(gb, 8); // terminal provider oriented code + user_identifier = get_bits_long(gb, 32); + + switch (user_identifier) { + case MKBETAG('D', 'T', 'G', '1'): // afd_data + return decode_registered_user_data_afd(&h->afd, gb, size); + case MKBETAG('G', 'A', '9', '4'): // closed captions + return decode_registered_user_data_closed_caption(&h->a53_caption, gb, + logctx, size); + default: + skip_bits(gb, size * 8); + break; + } + + return 0; +} + +static int decode_unregistered_user_data(H264SEIUnregistered *h, GetBitContext *gb, + void *logctx, int size) +{ + uint8_t *user_data; int e, build, i; - if (size < 16) + if (size < 16 || size >= INT_MAX - 16) return AVERROR_INVALIDDATA; - for (i = 0; i < sizeof(user_data) - 1 && i < size; i++) - user_data[i] = get_bits(&h->gb, 8); + user_data = av_malloc(16 + size + 1); + if (!user_data) + return AVERROR(ENOMEM); + + for (i = 0; i < size + 16; i++) + user_data[i] = get_bits(gb, 8); user_data[i] = 0; e = sscanf(user_data + 16, "x264 - core %d", &build); if (e == 1 && build > 0) h->x264_build = build; - if (h->avctx->debug & FF_DEBUG_BUGS) - av_log(h->avctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data + 16); - - for (; i < size; i++) - skip_bits(&h->gb, 8); + if (strlen(user_data + 16) > 0) + av_log(logctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data + 16); + av_free(user_data); return 0; } -static int decode_recovery_point(H264Context *h) +static int decode_recovery_point(H264SEIRecoveryPoint *h, GetBitContext *gb) { - h->sei_recovery_frame_cnt = get_ue_golomb(&h->gb); + h->recovery_frame_cnt = get_ue_golomb(gb); /* 1b exact_match_flag, * 1b broken_link_flag, * 2b changing_slice_group_idc */ - skip_bits(&h->gb, 4); + skip_bits(gb, 4); return 0; } -static int decode_buffering_period(H264Context *h) +static int decode_buffering_period(H264SEIBufferingPeriod *h, GetBitContext *gb, + const H264ParamSets *ps, void *logctx) { unsigned int sps_id; int sched_sel_idx; SPS *sps; - sps_id = get_ue_golomb_31(&h->gb); - if (sps_id > 31 || !h->sps_buffers[sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, + sps_id = get_ue_golomb_31(gb); + if (sps_id > 31 || !ps->sps_list[sps_id]) { + av_log(logctx, AV_LOG_ERROR, "non-existing SPS %d referenced in buffering period\n", sps_id); return AVERROR_INVALIDDATA; } - sps = h->sps_buffers[sps_id]; + sps = (SPS*)ps->sps_list[sps_id]->data; // NOTE: This is really so duplicated in the standard... See H.264, D.1.1 if (sps->nal_hrd_parameters_present_flag) { for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { h->initial_cpb_removal_delay[sched_sel_idx] = - get_bits(&h->gb, sps->initial_cpb_removal_delay_length); + get_bits(gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset - skip_bits(&h->gb, sps->initial_cpb_removal_delay_length); + skip_bits(gb, sps->initial_cpb_removal_delay_length); } } if (sps->vcl_hrd_parameters_present_flag) { for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { h->initial_cpb_removal_delay[sched_sel_idx] = - get_bits(&h->gb, sps->initial_cpb_removal_delay_length); + get_bits(gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset - skip_bits(&h->gb, sps->initial_cpb_removal_delay_length); + skip_bits(gb, sps->initial_cpb_removal_delay_length); } } - h->sei_buffering_period_present = 1; + h->present = 1; return 0; } -static int decode_frame_packing_arrangement(H264Context *h) +static int decode_frame_packing_arrangement(H264SEIFramePacking *h, + GetBitContext *gb) { - get_ue_golomb(&h->gb); // frame_packing_arrangement_id - h->sei_frame_packing_present = !get_bits1(&h->gb); + get_ue_golomb(gb); // frame_packing_arrangement_id + h->present = !get_bits1(gb); - if (h->sei_frame_packing_present) { - h->frame_packing_arrangement_type = get_bits(&h->gb, 7); - h->quincunx_subsampling = get_bits1(&h->gb); - h->content_interpretation_type = get_bits(&h->gb, 6); + if (h->present) { + h->arrangement_type = get_bits(gb, 7); + h->quincunx_subsampling = get_bits1(gb); + h->content_interpretation_type = get_bits(gb, 6); // the following skips: spatial_flipping_flag, frame0_flipped_flag, // field_views_flag, current_frame_is_frame0_flag, // frame0_self_contained_flag, frame1_self_contained_flag - skip_bits(&h->gb, 6); + skip_bits(gb, 6); - if (!h->quincunx_subsampling && h->frame_packing_arrangement_type != 5) - skip_bits(&h->gb, 16); // frame[01]_grid_position_[xy] - skip_bits(&h->gb, 8); // frame_packing_arrangement_reserved_byte - get_ue_golomb(&h->gb); // frame_packing_arrangement_repetition_period + if (!h->quincunx_subsampling && h->arrangement_type != 5) + skip_bits(gb, 16); // frame[01]_grid_position_[xy] + skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte + get_ue_golomb(gb); // frame_packing_arrangement_repetition_period } - skip_bits1(&h->gb); // frame_packing_arrangement_extension_flag + skip_bits1(gb); // frame_packing_arrangement_extension_flag return 0; } -static int decode_display_orientation(H264Context *h) +static int decode_display_orientation(H264SEIDisplayOrientation *h, + GetBitContext *gb) { - h->sei_display_orientation_present = !get_bits1(&h->gb); + h->present = !get_bits1(gb); - if (h->sei_display_orientation_present) { - h->sei_hflip = get_bits1(&h->gb); // hor_flip - h->sei_vflip = get_bits1(&h->gb); // ver_flip + if (h->present) { + h->hflip = get_bits1(gb); // hor_flip + h->vflip = get_bits1(gb); // ver_flip - h->sei_anticlockwise_rotation = get_bits(&h->gb, 16); - get_ue_golomb(&h->gb); // display_orientation_repetition_period - skip_bits1(&h->gb); // display_orientation_extension_flag + h->anticlockwise_rotation = get_bits(gb, 16); + get_ue_golomb(gb); // display_orientation_repetition_period + skip_bits1(gb); // display_orientation_extension_flag } return 0; } -int ff_h264_decode_sei(H264Context *h) +int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, + const H264ParamSets *ps, void *logctx) { - while (get_bits_left(&h->gb) > 16) { + while (get_bits_left(gb) > 16) { int size = 0; int type = 0; int ret = 0; int last = 0; - while (get_bits_left(&h->gb) >= 8 && - (last = get_bits(&h->gb, 8)) == 255) { + while (get_bits_left(gb) >= 8 && + (last = get_bits(gb, 8)) == 255) { type += 255; } type += last; last = 0; - while (get_bits_left(&h->gb) >= 8 && - (last = get_bits(&h->gb, 8)) == 255) { + while (get_bits_left(gb) >= 8 && + (last = get_bits(gb, 8)) == 255) { size += 255; } size += last; - if (size > get_bits_left(&h->gb) / 8) { - av_log(h->avctx, AV_LOG_ERROR, "SEI type %d truncated at %d\n", - type, get_bits_left(&h->gb)); + if (size > get_bits_left(gb) / 8) { + av_log(logctx, AV_LOG_ERROR, "SEI type %d truncated at %d\n", + type, get_bits_left(gb)); return AVERROR_INVALIDDATA; } switch (type) { case SEI_TYPE_PIC_TIMING: // Picture timing SEI - ret = decode_picture_timing(h); - if (ret < 0) - return ret; + ret = decode_picture_timing(&h->picture_timing, gb, ps->sps, logctx); + break; + case SEI_TYPE_USER_DATA_REGISTERED: + ret = decode_registered_user_data(h, gb, logctx, size); break; case SEI_TYPE_USER_DATA_UNREGISTERED: - ret = decode_unregistered_user_data(h, size); - if (ret < 0) - return ret; + ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size); break; case SEI_TYPE_RECOVERY_POINT: - ret = decode_recovery_point(h); - if (ret < 0) - return ret; + ret = decode_recovery_point(&h->recovery_point, gb); break; case SEI_TYPE_BUFFERING_PERIOD: - ret = decode_buffering_period(h); - if (ret < 0) - return ret; + ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx); break; case SEI_TYPE_FRAME_PACKING: - ret = decode_frame_packing_arrangement(h); - if (ret < 0) - return ret; + ret = decode_frame_packing_arrangement(&h->frame_packing, gb); break; case SEI_TYPE_DISPLAY_ORIENTATION: - ret = decode_display_orientation(h); - if (ret < 0) - return ret; + ret = decode_display_orientation(&h->display_orientation, gb); break; default: - av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); - skip_bits(&h->gb, 8 * size); + av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); + skip_bits(gb, 8 * size); } + if (ret < 0) + return ret; // FIXME check bits here - align_get_bits(&h->gb); + align_get_bits(gb); } return 0; diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h new file mode 100644 index 0000000..58f5ecc --- /dev/null +++ b/libavcodec/h264_sei.h @@ -0,0 +1,137 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_H264_SEI_H +#define AVCODEC_H264_SEI_H + +#include "get_bits.h" + +/** + * SEI message types + */ +typedef enum { + SEI_TYPE_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) + SEI_TYPE_PIC_TIMING = 1, ///< picture timing + SEI_TYPE_USER_DATA_REGISTERED = 4, ///< registered user data as specified by Rec. ITU-T T.35 + SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data + SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) + SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement + SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation +} SEI_Type; + +/** + * pic_struct in picture timing SEI message + */ +typedef enum { + SEI_PIC_STRUCT_FRAME = 0, ///< 0: %frame + SEI_PIC_STRUCT_TOP_FIELD = 1, ///< 1: top field + SEI_PIC_STRUCT_BOTTOM_FIELD = 2, ///< 2: bottom field + SEI_PIC_STRUCT_TOP_BOTTOM = 3, ///< 3: top field, bottom field, in that order + SEI_PIC_STRUCT_BOTTOM_TOP = 4, ///< 4: bottom field, top field, in that order + SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, ///< 5: top field, bottom field, top field repeated, in that order + SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///< 6: bottom field, top field, bottom field repeated, in that order + SEI_PIC_STRUCT_FRAME_DOUBLING = 7, ///< 7: %frame doubling + SEI_PIC_STRUCT_FRAME_TRIPLING = 8 ///< 8: %frame tripling +} SEI_PicStructType; + +typedef struct H264SEIPictureTiming { + SEI_PicStructType pic_struct; + + /** + * Bit set of clock types for fields/frames in picture timing SEI message. + * For each found ct_type, appropriate bit is set (e.g., bit 1 for + * interlaced). + */ + int ct_type; + + /** + * dpb_output_delay in picture timing SEI message, see H.264 C.2.2 + */ + int dpb_output_delay; + + /** + * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2 + */ + int cpb_removal_delay; +} H264SEIPictureTiming; + +typedef struct H264SEIAFD { + int present; + uint8_t active_format_description; +} H264SEIAFD; + +typedef struct H264SEIA53Caption { + int a53_caption_size; + uint8_t *a53_caption; +} H264SEIA53Caption; + +typedef struct H264SEIUnregistered { + int x264_build; +} H264SEIUnregistered; + +typedef struct H264SEIRecoveryPoint { + /** + * recovery_frame_cnt + * + * Set to -1 if no recovery point SEI message found or to number of frames + * before playback synchronizes. Frames having recovery point are key + * frames. + */ + int recovery_frame_cnt; +} H264SEIRecoveryPoint; + +typedef struct H264SEIBufferingPeriod { + int present; ///< Buffering period SEI flag + int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs +} H264SEIBufferingPeriod; + +typedef struct H264SEIFramePacking { + int present; + int arrangement_type; + int content_interpretation_type; + int quincunx_subsampling; +} H264SEIFramePacking; + +typedef struct H264SEIDisplayOrientation { + int present; + int anticlockwise_rotation; + int hflip, vflip; +} H264SEIDisplayOrientation; + +typedef struct H264SEIContext { + H264SEIPictureTiming picture_timing; + H264SEIAFD afd; + H264SEIA53Caption a53_caption; + H264SEIUnregistered unregistered; + H264SEIRecoveryPoint recovery_point; + H264SEIBufferingPeriod buffering_period; + H264SEIFramePacking frame_packing; + H264SEIDisplayOrientation display_orientation; +} H264SEIContext; + +struct H264ParamSets; + +int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, + const struct H264ParamSets *ps, void *logctx); + +/** + * Reset SEI values at the beginning of the frame. + */ +void ff_h264_sei_uninit(H264SEIContext *h); + +#endif /* AVCODEC_H264_SEI_H */ diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c2c3e9f..db7628c 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -21,12 +21,14 @@ /** * @file - * H.264 / AVC / MPEG4 part10 codec. + * H.264 / AVC / MPEG-4 part10 codec. * @author Michael Niedermayer */ #include "libavutil/avassert.h" +#include "libavutil/display.h" #include "libavutil/imgutils.h" +#include "libavutil/stereo3d.h" #include "libavutil/timer.h" #include "internal.h" #include "cabac.h" @@ -34,28 +36,17 @@ #include "error_resilience.h" #include "avcodec.h" #include "h264.h" +#include "h264dec.h" #include "h264data.h" #include "h264chroma.h" #include "h264_mvpred.h" +#include "h264_ps.h" #include "golomb.h" #include "mathops.h" #include "mpegutils.h" #include "rectangle.h" #include "thread.h" - -static const uint8_t rem6[QP_MAX_NUM + 1] = { - 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, - 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, - 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, -}; - -static const uint8_t div6[QP_MAX_NUM + 1] = { - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, - 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, -}; - 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, @@ -121,93 +112,45 @@ static const uint8_t zigzag_scan8x8_cavlc[64] = { 5 + 5 * 8, 6 + 5 * 8, 6 + 6 * 8, 7 + 7 * 8, }; -static const uint8_t dequant4_coeff_init[6][3] = { - { 10, 13, 16 }, - { 11, 14, 18 }, - { 13, 16, 20 }, - { 14, 18, 23 }, - { 16, 20, 25 }, - { 18, 23, 29 }, -}; - -static const uint8_t dequant8_coeff_init_scan[16] = { - 0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1 -}; - -static const uint8_t dequant8_coeff_init[6][6] = { - { 20, 18, 32, 19, 25, 24 }, - { 22, 19, 35, 21, 28, 26 }, - { 26, 23, 42, 24, 33, 31 }, - { 28, 25, 45, 26, 35, 33 }, - { 32, 28, 51, 30, 40, 38 }, - { 36, 32, 58, 34, 46, 43 }, -}; - -static const enum AVPixelFormat h264_hwaccel_pixfmt_list_420[] = { -#if CONFIG_H264_DXVA2_HWACCEL - AV_PIX_FMT_DXVA2_VLD, -#endif -#if CONFIG_H264_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, -#endif -#if CONFIG_H264_VDA_HWACCEL - AV_PIX_FMT_VDA_VLD, - AV_PIX_FMT_VDA, -#endif -#if CONFIG_H264_VDPAU_HWACCEL - AV_PIX_FMT_VDPAU, -#endif - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE -}; - -static const enum AVPixelFormat h264_hwaccel_pixfmt_list_jpeg_420[] = { -#if CONFIG_H264_DXVA2_HWACCEL - AV_PIX_FMT_DXVA2_VLD, -#endif -#if CONFIG_H264_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, -#endif -#if CONFIG_H264_VDA_HWACCEL - AV_PIX_FMT_VDA_VLD, - AV_PIX_FMT_VDA, -#endif -#if CONFIG_H264_VDPAU_HWACCEL - AV_PIX_FMT_VDPAU, -#endif - AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_NONE -}; - - static void release_unused_pictures(H264Context *h, int remove_current) { int i; /* release non reference frames */ for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { - if (h->DPB[i].f.buf[0] && !h->DPB[i].reference && + if (h->DPB[i].f->buf[0] && !h->DPB[i].reference && (remove_current || &h->DPB[i] != h->cur_pic_ptr)) { ff_h264_unref_picture(h, &h->DPB[i]); } } } -static int alloc_scratch_buffers(H264Context *h, int linesize) +static int alloc_scratch_buffers(H264SliceContext *sl, int linesize) { + const H264Context *h = sl->h264; int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); - if (h->bipred_scratchpad) - return 0; - - h->bipred_scratchpad = av_malloc(16 * 6 * alloc_size); + av_fast_malloc(&sl->bipred_scratchpad, &sl->bipred_scratchpad_allocated, 16 * 6 * alloc_size); // edge emu needs blocksize + filter length - 1 - // (= 21x21 for h264) - h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 21); - - if (!h->bipred_scratchpad || !h->edge_emu_buffer) { - av_freep(&h->bipred_scratchpad); - av_freep(&h->edge_emu_buffer); + // (= 21x21 for H.264) + av_fast_malloc(&sl->edge_emu_buffer, &sl->edge_emu_buffer_allocated, alloc_size * 2 * 21); + + av_fast_malloc(&sl->top_borders[0], &sl->top_borders_allocated[0], + h->mb_width * 16 * 3 * sizeof(uint8_t) * 2); + av_fast_malloc(&sl->top_borders[1], &sl->top_borders_allocated[1], + h->mb_width * 16 * 3 * sizeof(uint8_t) * 2); + + if (!sl->bipred_scratchpad || !sl->edge_emu_buffer || + !sl->top_borders[0] || !sl->top_borders[1]) { + av_freep(&sl->bipred_scratchpad); + av_freep(&sl->edge_emu_buffer); + av_freep(&sl->top_borders[0]); + av_freep(&sl->top_borders[1]); + + sl->bipred_scratchpad_allocated = 0; + sl->edge_emu_buffer_allocated = 0; + sl->top_borders_allocated[0] = 0; + sl->top_borders_allocated[1] = 0; return AVERROR(ENOMEM); } @@ -245,17 +188,14 @@ static int alloc_picture(H264Context *h, H264Picture *pic) { int i, ret = 0; - av_assert0(!pic->f.data[0]); + av_assert0(!pic->f->data[0]); - pic->tf.f = &pic->f; + pic->tf.f = pic->f; ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); if (ret < 0) goto fail; - h->linesize = pic->f.linesize[0]; - h->uvlinesize = pic->f.linesize[1]; - if (h->avctx->hwaccel) { const AVHWAccel *hwaccel = h->avctx->hwaccel; av_assert0(!pic->hwaccel_picture_private); @@ -299,9 +239,7 @@ fail: static inline int pic_is_unused(H264Context *h, H264Picture *pic) { - if (!pic->f.buf[0]) - return 1; - if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) + if (!pic->f->buf[0]) return 1; return 0; } @@ -317,112 +255,39 @@ static int find_unused_picture(H264Context *h) if (i == H264_MAX_PICTURE_COUNT) return AVERROR_INVALIDDATA; - if (h->DPB[i].needs_realloc) { - h->DPB[i].needs_realloc = 0; - ff_h264_unref_picture(h, &h->DPB[i]); - } - return i; } - -static void init_dequant8_coeff_table(H264Context *h) +static int initialize_cur_frame(H264Context *h) { - int i, j, q, x; - const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); - - for (i = 0; i < 6; i++) { - h->dequant8_coeff[i] = h->dequant8_buffer[i]; - for (j = 0; j < i; j++) - if (!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i], - 64 * sizeof(uint8_t))) { - h->dequant8_coeff[i] = h->dequant8_buffer[j]; - break; - } - if (j < i) - continue; - - for (q = 0; q < max_qp + 1; q++) { - int shift = div6[q]; - int idx = rem6[q]; - for (x = 0; x < 64; x++) - h->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = - ((uint32_t)dequant8_coeff_init[idx][dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * - h->pps.scaling_matrix8[i][x]) << shift; - } - } -} + H264Picture *cur; + int ret; -static void init_dequant4_coeff_table(H264Context *h) -{ - int i, j, q, x; - const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); - for (i = 0; i < 6; i++) { - h->dequant4_coeff[i] = h->dequant4_buffer[i]; - for (j = 0; j < i; j++) - if (!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], - 16 * sizeof(uint8_t))) { - h->dequant4_coeff[i] = h->dequant4_buffer[j]; - break; - } - if (j < i) - continue; - - for (q = 0; q < max_qp + 1; q++) { - int shift = div6[q] + 2; - int idx = rem6[q]; - for (x = 0; x < 16; x++) - h->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = - ((uint32_t)dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * - h->pps.scaling_matrix4[i][x]) << shift; - } - } -} + release_unused_pictures(h, 1); + ff_h264_unref_picture(h, &h->cur_pic); + h->cur_pic_ptr = NULL; -void h264_init_dequant_tables(H264Context *h) -{ - int i, x; - init_dequant4_coeff_table(h); - if (h->pps.transform_8x8_mode) - init_dequant8_coeff_table(h); - if (h->sps.transform_bypass) { - for (i = 0; i < 6; i++) - for (x = 0; x < 16; x++) - h->dequant4_coeff[i][0][x] = 1 << 6; - if (h->pps.transform_8x8_mode) - for (i = 0; i < 6; i++) - for (x = 0; x < 64; x++) - h->dequant8_coeff[i][0][x] = 1 << 6; + ret = find_unused_picture(h); + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return ret; } -} + cur = &h->DPB[ret]; -/** - * Mimic alloc_tables(), but for every context thread. - */ -static void clone_tables(H264Context *dst, H264Context *src, int i) -{ - dst->intra4x4_pred_mode = src->intra4x4_pred_mode + i * 8 * 2 * src->mb_stride; - dst->non_zero_count = src->non_zero_count; - dst->slice_table = src->slice_table; - dst->cbp_table = src->cbp_table; - dst->mb2b_xy = src->mb2b_xy; - dst->mb2br_xy = src->mb2br_xy; - dst->chroma_pred_mode_table = src->chroma_pred_mode_table; - dst->mvd_table[0] = src->mvd_table[0] + i * 8 * 2 * src->mb_stride; - dst->mvd_table[1] = src->mvd_table[1] + i * 8 * 2 * src->mb_stride; - dst->direct_table = src->direct_table; - dst->list_counts = src->list_counts; - dst->DPB = src->DPB; - dst->cur_pic_ptr = src->cur_pic_ptr; - dst->cur_pic = src->cur_pic; - dst->bipred_scratchpad = NULL; - dst->edge_emu_buffer = NULL; - ff_h264_pred_init(&dst->hpc, src->avctx->codec_id, src->sps.bit_depth_luma, - src->sps.chroma_format_idc); + ret = alloc_picture(h, cur); + if (ret < 0) + return ret; + + ret = ff_h264_ref_picture(h, &h->cur_pic, cur); + if (ret < 0) + return ret; + h->cur_pic_ptr = cur; + + return 0; } #define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size)))) -#undef REBASE_PICTURE + #define REBASE_PICTURE(pic, new_ctx, old_ctx) \ ((pic && pic >= old_ctx->DPB && \ pic < old_ctx->DPB + H264_MAX_PICTURE_COUNT) ? \ @@ -443,59 +308,55 @@ static void copy_picture_range(H264Picture **to, H264Picture **from, int count, } } -static int copy_parameter_set(void **to, void **from, int count, int size) -{ - int i; - - for (i = 0; i < count; i++) { - if (to[i] && !from[i]) { - av_freep(&to[i]); - } else if (from[i] && !to[i]) { - to[i] = av_malloc(size); - if (!to[i]) - return AVERROR(ENOMEM); - } - - if (from[i]) - memcpy(to[i], from[i], size); - } - - return 0; -} - -#define copy_fields(to, from, start_field, end_field) \ - memcpy(&to->start_field, &from->start_field, \ - (char *)&to->end_field - (char *)&to->start_field) - -static int h264_slice_header_init(H264Context *h, int reinit); +static int h264_slice_header_init(H264Context *h); int ff_h264_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { H264Context *h = dst->priv_data, *h1 = src->priv_data; int inited = h->context_initialized, err = 0; - int context_reinitialized = 0; + int need_reinit = 0; int i, ret; if (dst == src || !h1->context_initialized) return 0; + if (!h1->ps.sps) + return AVERROR_INVALIDDATA; + if (inited && (h->width != h1->width || h->height != h1->height || h->mb_width != h1->mb_width || h->mb_height != h1->mb_height || - h->sps.bit_depth_luma != h1->sps.bit_depth_luma || - h->sps.chroma_format_idc != h1->sps.chroma_format_idc || - h->sps.colorspace != h1->sps.colorspace)) { + !h->ps.sps || + h->ps.sps->bit_depth_luma != h1->ps.sps->bit_depth_luma || + h->ps.sps->chroma_format_idc != h1->ps.sps->chroma_format_idc || + h->ps.sps->colorspace != h1->ps.sps->colorspace)) { + need_reinit = 1; + } - /* set bits_per_raw_sample to the previous value. the check for changed - * bit depth in h264_set_parameter_from_sps() uses it and sets it to - * the current value */ - h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + // SPS/PPS + for (i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) { + av_buffer_unref(&h->ps.sps_list[i]); + if (h1->ps.sps_list[i]) { + h->ps.sps_list[i] = av_buffer_ref(h1->ps.sps_list[i]); + if (!h->ps.sps_list[i]) + return AVERROR(ENOMEM); + } + } + for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) { + av_buffer_unref(&h->ps.pps_list[i]); + if (h1->ps.pps_list[i]) { + h->ps.pps_list[i] = av_buffer_ref(h1->ps.pps_list[i]); + if (!h->ps.pps_list[i]) + return AVERROR(ENOMEM); + } + } - av_freep(&h->bipred_scratchpad); + h->ps.sps = h1->ps.sps; + if (need_reinit || !inited) { h->width = h1->width; h->height = h1->height; h->mb_height = h1->mb_height; @@ -504,71 +365,15 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->mb_stride = h1->mb_stride; h->b_stride = h1->b_stride; - if ((err = h264_slice_header_init(h, 1)) < 0) { + if ((err = h264_slice_header_init(h)) < 0) { av_log(h->avctx, AV_LOG_ERROR, "h264_slice_header_init() failed"); return err; } - context_reinitialized = 1; - - /* update linesize on resize. The decoder doesn't - * necessarily call h264_frame_start in the new thread */ - h->linesize = h1->linesize; - h->uvlinesize = h1->uvlinesize; /* copy block_offset since frame_start may not be called */ memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset)); } - if (!inited) { - for (i = 0; i < MAX_SPS_COUNT; i++) - av_freep(h->sps_buffers + i); - - for (i = 0; i < MAX_PPS_COUNT; i++) - av_freep(h->pps_buffers + i); - - memcpy(h, h1, sizeof(*h1)); - memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); - memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); - memset(&h->er, 0, sizeof(h->er)); - memset(&h->mb, 0, sizeof(h->mb)); - memset(&h->mb_luma_dc, 0, sizeof(h->mb_luma_dc)); - memset(&h->mb_padding, 0, sizeof(h->mb_padding)); - h->context_initialized = 0; - - memset(&h->cur_pic, 0, sizeof(h->cur_pic)); - av_frame_unref(&h->cur_pic.f); - h->cur_pic.tf.f = &h->cur_pic.f; - - h->avctx = dst; - h->DPB = NULL; - h->qscale_table_pool = NULL; - h->mb_type_pool = NULL; - h->ref_index_pool = NULL; - h->motion_val_pool = NULL; - - ret = ff_h264_alloc_tables(h); - if (ret < 0) { - av_log(dst, AV_LOG_ERROR, "Could not allocate memory\n"); - return ret; - } - ret = ff_h264_context_init(h); - if (ret < 0) { - av_log(dst, AV_LOG_ERROR, "context_init() failed.\n"); - return ret; - } - - for (i = 0; i < 2; i++) { - h->rbsp_buffer[i] = NULL; - h->rbsp_buffer_size[i] = 0; - } - h->bipred_scratchpad = NULL; - h->edge_emu_buffer = NULL; - - h->thread_context[0] = h; - - h->context_initialized = 1; - } - h->avctx->coded_height = h1->avctx->coded_height; h->avctx->coded_width = h1->avctx->coded_width; h->avctx->width = h1->avctx->width; @@ -576,91 +381,63 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->coded_picture_number = h1->coded_picture_number; h->first_field = h1->first_field; h->picture_structure = h1->picture_structure; - h->qscale = h1->qscale; + h->mb_aff_frame = h1->mb_aff_frame; h->droppable = h1->droppable; - h->low_delay = h1->low_delay; for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { ff_h264_unref_picture(h, &h->DPB[i]); - if (h1->DPB[i].f.buf[0] && + if (h1->DPB[i].f->buf[0] && (ret = ff_h264_ref_picture(h, &h->DPB[i], &h1->DPB[i])) < 0) return ret; } h->cur_pic_ptr = REBASE_PICTURE(h1->cur_pic_ptr, h, h1); ff_h264_unref_picture(h, &h->cur_pic); - if (h1->cur_pic.f.buf[0]) { + if (h1->cur_pic.f->buf[0]) { ret = ff_h264_ref_picture(h, &h->cur_pic, &h1->cur_pic); if (ret < 0) return ret; } + h->enable_er = h1->enable_er; h->workaround_bugs = h1->workaround_bugs; - h->low_delay = h1->low_delay; h->droppable = h1->droppable; - /* frame_start may not be called for the next thread (if it's decoding - * a bottom field) so this has to be allocated here */ - err = alloc_scratch_buffers(h, h1->linesize); - if (err < 0) - return err; - // extradata/NAL handling h->is_avc = h1->is_avc; + h->nal_length_size = h1->nal_length_size; - // SPS/PPS - if ((ret = copy_parameter_set((void **)h->sps_buffers, - (void **)h1->sps_buffers, - MAX_SPS_COUNT, sizeof(SPS))) < 0) - return ret; - h->sps = h1->sps; - if ((ret = copy_parameter_set((void **)h->pps_buffers, - (void **)h1->pps_buffers, - MAX_PPS_COUNT, sizeof(PPS))) < 0) - return ret; - h->pps = h1->pps; - - // Dequantization matrices - // FIXME these are big - can they be only copied when PPS changes? - copy_fields(h, h1, dequant4_buffer, dequant4_coeff); - - for (i = 0; i < 6; i++) - h->dequant4_coeff[i] = h->dequant4_buffer[0] + - (h1->dequant4_coeff[i] - h1->dequant4_buffer[0]); + memcpy(&h->poc, &h1->poc, sizeof(h->poc)); - for (i = 0; i < 6; i++) - h->dequant8_coeff[i] = h->dequant8_buffer[0] + - (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]); + memcpy(h->short_ref, h1->short_ref, sizeof(h->short_ref)); + memcpy(h->long_ref, h1->long_ref, sizeof(h->long_ref)); + memcpy(h->delayed_pic, h1->delayed_pic, sizeof(h->delayed_pic)); + memcpy(h->last_pocs, h1->last_pocs, sizeof(h->last_pocs)); - h->dequant_coeff_pps = h1->dequant_coeff_pps; + h->next_outputed_poc = h1->next_outputed_poc; - // POC timing - copy_fields(h, h1, poc_lsb, redundant_pic_count); - - // reference lists - copy_fields(h, h1, short_ref, cabac_init_idc); + memcpy(h->mmco, h1->mmco, sizeof(h->mmco)); + h->nb_mmco = h1->nb_mmco; + h->mmco_reset = h1->mmco_reset; + h->explicit_ref_marking = h1->explicit_ref_marking; + h->long_ref_count = h1->long_ref_count; + h->short_ref_count = h1->short_ref_count; copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1); copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1); copy_picture_range(h->delayed_pic, h1->delayed_pic, MAX_DELAYED_PIC_COUNT + 2, h, h1); - h->last_slice_type = h1->last_slice_type; - - if (context_reinitialized) - ff_h264_set_parameter_from_sps(h); - if (!h->cur_pic_ptr) return 0; if (!h->droppable) { - err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); - h->prev_poc_msb = h->poc_msb; - h->prev_poc_lsb = h->poc_lsb; + err = ff_h264_execute_ref_pic_marking(h); + h->poc.prev_poc_msb = h->poc.poc_msb; + h->poc.prev_poc_lsb = h->poc.poc_lsb; } - h->prev_frame_num_offset = h->frame_num_offset; - h->prev_frame_num = h->frame_num; - h->outputed_poc = h->next_outputed_poc; + h->poc.prev_frame_num_offset = h->poc.frame_num_offset; + h->poc.prev_frame_num = h->poc.frame_num; h->recovery_frame = h1->recovery_frame; h->frame_recovered = h1->frame_recovered; @@ -674,61 +451,40 @@ static int h264_frame_start(H264Context *h) int i, ret; const int pixel_shift = h->pixel_shift; - release_unused_pictures(h, 1); - h->cur_pic_ptr = NULL; - - i = find_unused_picture(h); - if (i < 0) { - av_log(h->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - pic = &h->DPB[i]; + ret = initialize_cur_frame(h); + if (ret < 0) + return ret; + pic = h->cur_pic_ptr; pic->reference = h->droppable ? 0 : h->picture_structure; - pic->f.coded_picture_number = h->coded_picture_number++; + pic->f->coded_picture_number = h->coded_picture_number++; pic->field_picture = h->picture_structure != PICT_FRAME; + pic->frame_num = h->poc.frame_num; /* * Zero key_frame here; IDR markings per slice in frame or fields are ORed * in later. * See decode_nal_units(). */ - pic->f.key_frame = 0; + pic->f->key_frame = 0; pic->mmco_reset = 0; pic->recovered = 0; - if ((ret = alloc_picture(h, pic)) < 0) - return ret; - - h->cur_pic_ptr = pic; - ff_h264_unref_picture(h, &h->cur_pic); - if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0) - return ret; + pic->f->pict_type = h->slice_ctx[0].slice_type; - if (CONFIG_ERROR_RESILIENCE) - ff_er_frame_start(&h->er); - - assert(h->linesize && h->uvlinesize); + if (CONFIG_ERROR_RESILIENCE && h->enable_er) + ff_er_frame_start(&h->slice_ctx[0].er); for (i = 0; i < 16; i++) { - h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); - h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3); } for (i = 0; i < 16; i++) { h->block_offset[16 + i] = - h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3); h->block_offset[48 + 16 + i] = - h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f->linesize[1] * ((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? */ - for (i = 0; i < h->slice_context_count; i++) - if (h->thread_context[i]) { - ret = alloc_scratch_buffers(h->thread_context[i], h->linesize); - if (ret < 0) - return ret; - } - /* Some macroblocks can be accessed before they're available in case * of lost slices, MBAFF or threading. */ memset(h->slice_table, -1, @@ -742,14 +498,17 @@ static int h264_frame_start(H264Context *h) h->cur_pic_ptr->field_poc[0] = h->cur_pic_ptr->field_poc[1] = INT_MAX; - h->next_output_pic = NULL; + h->postpone_filter = 0; + + h->mb_aff_frame = h->ps.sps->mb_aff && (h->picture_structure == PICT_FRAME); assert(h->cur_pic_ptr->long_ref == 0); return 0; } -static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, +static av_always_inline void backup_mb_border(const H264Context *h, H264SliceContext *sl, + uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int simple) @@ -765,13 +524,13 @@ static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, src_cr -= uvlinesize; if (!simple && FRAME_MBAFF(h)) { - if (h->mb_y & 1) { - if (!MB_MBAFF(h)) { - top_border = h->top_borders[0][h->mb_x]; + if (sl->mb_y & 1) { + if (!MB_MBAFF(sl)) { + top_border = sl->top_borders[0][sl->mb_x]; AV_COPY128(top_border, src_y + 15 * linesize); if (pixel_shift) AV_COPY128(top_border + 16, src_y + 15 * linesize + 16); - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (simple || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { if (chroma444) { if (pixel_shift) { AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); @@ -801,20 +560,20 @@ static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, } } } - } else if (MB_MBAFF(h)) { + } else if (MB_MBAFF(sl)) { top_idx = 0; } else return; } - top_border = h->top_borders[top_idx][h->mb_x]; + top_border = sl->top_borders[top_idx][sl->mb_x]; /* There are two lines saved, the line above the top macroblock * of a pair, and the line above the bottom macroblock. */ AV_COPY128(top_border, src_y + 16 * linesize); if (pixel_shift) AV_COPY128(top_border + 16, src_y + 16 * linesize + 16); - if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (simple || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) { if (chroma444) { if (pixel_shift) { AV_COPY128(top_border + 32, src_cb + 16 * linesize); @@ -850,13 +609,13 @@ static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, * @param field 0/1 initialize the weight for interlaced MBAFF * -1 initializes the rest */ -static void implicit_weight_table(H264Context *h, int field) +static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, int field) { int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1; for (i = 0; i < 2; i++) { - h->luma_weight_flag[i] = 0; - h->chroma_weight_flag[i] = 0; + sl->pwt.luma_weight_flag[i] = 0; + sl->pwt.chroma_weight_flag[i] = 0; } if (field < 0) { @@ -865,36 +624,36 @@ static void implicit_weight_table(H264Context *h, int field) } else { cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure - 1]; } - if (h->ref_count[0] == 1 && h->ref_count[1] == 1 && !FRAME_MBAFF(h) && - h->ref_list[0][0].poc + h->ref_list[1][0].poc == 2 * cur_poc) { - h->use_weight = 0; - h->use_weight_chroma = 0; + if (sl->ref_count[0] == 1 && sl->ref_count[1] == 1 && !FRAME_MBAFF(h) && + sl->ref_list[0][0].poc + sl->ref_list[1][0].poc == 2 * cur_poc) { + sl->pwt.use_weight = 0; + sl->pwt.use_weight_chroma = 0; return; } ref_start = 0; - ref_count0 = h->ref_count[0]; - ref_count1 = h->ref_count[1]; + ref_count0 = sl->ref_count[0]; + ref_count1 = sl->ref_count[1]; } else { cur_poc = h->cur_pic_ptr->field_poc[field]; ref_start = 16; - ref_count0 = 16 + 2 * h->ref_count[0]; - ref_count1 = 16 + 2 * h->ref_count[1]; + ref_count0 = 16 + 2 * sl->ref_count[0]; + ref_count1 = 16 + 2 * sl->ref_count[1]; } - h->use_weight = 2; - h->use_weight_chroma = 2; - h->luma_log2_weight_denom = 5; - h->chroma_log2_weight_denom = 5; + sl->pwt.use_weight = 2; + sl->pwt.use_weight_chroma = 2; + sl->pwt.luma_log2_weight_denom = 5; + sl->pwt.chroma_log2_weight_denom = 5; for (ref0 = ref_start; ref0 < ref_count0; ref0++) { - int poc0 = h->ref_list[0][ref0].poc; + int poc0 = sl->ref_list[0][ref0].poc; for (ref1 = ref_start; ref1 < ref_count1; ref1++) { int w = 32; - if (!h->ref_list[0][ref0].long_ref && !h->ref_list[1][ref1].long_ref) { - int poc1 = h->ref_list[1][ref1].poc; - int td = av_clip(poc1 - poc0, -128, 127); + if (!sl->ref_list[0][ref0].parent->long_ref && !sl->ref_list[1][ref1].parent->long_ref) { + int poc1 = sl->ref_list[1][ref1].poc; + int td = av_clip_int8(poc1 - poc0); if (td) { - int tb = av_clip(cur_poc - poc0, -128, 127); + int tb = av_clip_int8(cur_poc - poc0); int tx = (16384 + (FFABS(td) >> 1)) / td; int dist_scale_factor = (tb * tx + 32) >> 8; if (dist_scale_factor >= -64 && dist_scale_factor <= 128) @@ -902,10 +661,10 @@ static void implicit_weight_table(H264Context *h, int field) } } if (field < 0) { - h->implicit_weight[ref0][ref1][0] = - h->implicit_weight[ref0][ref1][1] = w; + sl->pwt.implicit_weight[ref0][ref1][0] = + sl->pwt.implicit_weight[ref0][ref1][1] = w; } else { - h->implicit_weight[ref0][ref1][field] = w; + sl->pwt.implicit_weight[ref0][ref1][field] = w; } } } @@ -919,7 +678,7 @@ static void init_scan_tables(H264Context *h) int i; for (i = 0; i < 16; i++) { #define TRANSPOSE(x) (x >> 2) | ((x << 2) & 0xF) - h->zigzag_scan[i] = TRANSPOSE(zigzag_scan[i]); + h->zigzag_scan[i] = TRANSPOSE(ff_zigzag_scan[i]); h->field_scan[i] = TRANSPOSE(field_scan[i]); #undef TRANSPOSE } @@ -931,8 +690,8 @@ static void init_scan_tables(H264Context *h) h->field_scan8x8_cavlc[i] = TRANSPOSE(field_scan8x8_cavlc[i]); #undef TRANSPOSE } - if (h->sps.transform_bypass) { // FIXME same ugly - h->zigzag_scan_q0 = zigzag_scan; + if (h->ps.sps->transform_bypass) { // FIXME same ugly + h->zigzag_scan_q0 = ff_zigzag_scan; h->zigzag_scan8x8_q0 = ff_zigzag_direct; h->zigzag_scan8x8_cavlc_q0 = zigzag_scan8x8_cavlc; h->field_scan_q0 = field_scan; @@ -948,105 +707,98 @@ static void init_scan_tables(H264Context *h) } } -/** - * Replicate H264 "master" context to thread contexts. - */ -static int clone_slice(H264Context *dst, H264Context *src) -{ - memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset)); - dst->cur_pic_ptr = src->cur_pic_ptr; - dst->cur_pic = src->cur_pic; - dst->linesize = src->linesize; - dst->uvlinesize = src->uvlinesize; - dst->first_field = src->first_field; - - dst->prev_poc_msb = src->prev_poc_msb; - dst->prev_poc_lsb = src->prev_poc_lsb; - dst->prev_frame_num_offset = src->prev_frame_num_offset; - dst->prev_frame_num = src->prev_frame_num; - dst->short_ref_count = src->short_ref_count; - - memcpy(dst->short_ref, src->short_ref, sizeof(dst->short_ref)); - memcpy(dst->long_ref, src->long_ref, sizeof(dst->long_ref)); - memcpy(dst->default_ref_list, src->default_ref_list, sizeof(dst->default_ref_list)); - - memcpy(dst->dequant4_coeff, src->dequant4_coeff, sizeof(src->dequant4_coeff)); - memcpy(dst->dequant8_coeff, src->dequant8_coeff, sizeof(src->dequant8_coeff)); - - return 0; -} - static enum AVPixelFormat get_pixel_format(H264Context *h) { - enum AVPixelFormat pix_fmts[2]; +#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ + CONFIG_H264_D3D11VA_HWACCEL + \ + CONFIG_H264_VAAPI_HWACCEL + \ + (CONFIG_H264_VDA_HWACCEL * 2) + \ + CONFIG_H264_VDPAU_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; const enum AVPixelFormat *choices = pix_fmts; - pix_fmts[1] = AV_PIX_FMT_NONE; - - switch (h->sps.bit_depth_luma) { + switch (h->ps.sps->bit_depth_luma) { case 9: if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { - pix_fmts[0] = AV_PIX_FMT_GBRP9; + *fmt++ = AV_PIX_FMT_GBRP9; } else - pix_fmts[0] = AV_PIX_FMT_YUV444P9; + *fmt++ = AV_PIX_FMT_YUV444P9; } else if (CHROMA422(h)) - pix_fmts[0] = AV_PIX_FMT_YUV422P9; + *fmt++ = AV_PIX_FMT_YUV422P9; else - pix_fmts[0] = AV_PIX_FMT_YUV420P9; + *fmt++ = AV_PIX_FMT_YUV420P9; break; case 10: if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { - pix_fmts[0] = AV_PIX_FMT_GBRP10; + *fmt++ = AV_PIX_FMT_GBRP10; } else - pix_fmts[0] = AV_PIX_FMT_YUV444P10; + *fmt++ = AV_PIX_FMT_YUV444P10; } else if (CHROMA422(h)) - pix_fmts[0] = AV_PIX_FMT_YUV422P10; + *fmt++ = AV_PIX_FMT_YUV422P10; else - pix_fmts[0] = AV_PIX_FMT_YUV420P10; + *fmt++ = AV_PIX_FMT_YUV420P10; break; case 8: +#if CONFIG_H264_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) - pix_fmts[0] = AV_PIX_FMT_GBRP; + *fmt++ = AV_PIX_FMT_GBRP; else if (h->avctx->color_range == AVCOL_RANGE_JPEG) - pix_fmts[0] = AV_PIX_FMT_YUVJ444P; + *fmt++ = AV_PIX_FMT_YUVJ444P; else - pix_fmts[0] = AV_PIX_FMT_YUV444P; + *fmt++ = AV_PIX_FMT_YUV444P; } else if (CHROMA422(h)) { if (h->avctx->color_range == AVCOL_RANGE_JPEG) - pix_fmts[0] = AV_PIX_FMT_YUVJ422P; + *fmt++ = AV_PIX_FMT_YUVJ422P; else - pix_fmts[0] = AV_PIX_FMT_YUV422P; + *fmt++ = AV_PIX_FMT_YUV422P; } else { +#if CONFIG_H264_DXVA2_HWACCEL + *fmt++ = AV_PIX_FMT_DXVA2_VLD; +#endif +#if CONFIG_H264_D3D11VA_HWACCEL + *fmt++ = AV_PIX_FMT_D3D11VA_VLD; +#endif +#if CONFIG_H264_VAAPI_HWACCEL + *fmt++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_H264_VDA_HWACCEL + *fmt++ = AV_PIX_FMT_VDA_VLD; + *fmt++ = AV_PIX_FMT_VDA; +#endif if (h->avctx->codec->pix_fmts) choices = h->avctx->codec->pix_fmts; else if (h->avctx->color_range == AVCOL_RANGE_JPEG) - choices = h264_hwaccel_pixfmt_list_jpeg_420; + *fmt++ = AV_PIX_FMT_YUVJ420P; else - choices = h264_hwaccel_pixfmt_list_420; + *fmt++ = AV_PIX_FMT_YUV420P; } break; default: av_log(h->avctx, AV_LOG_ERROR, - "Unsupported bit depth %d\n", h->sps.bit_depth_luma); + "Unsupported bit depth %d\n", h->ps.sps->bit_depth_luma); return AVERROR_INVALIDDATA; } + *fmt = AV_PIX_FMT_NONE; + return ff_get_format(h->avctx, choices); } /* export coded and cropped frame dimensions to AVCodecContext */ static int init_dimensions(H264Context *h) { - int width = h->width - (h->sps.crop_right + h->sps.crop_left); - int height = h->height - (h->sps.crop_top + h->sps.crop_bottom); + SPS *sps = h->ps.sps; + int width = h->width - (sps->crop_right + sps->crop_left); + int height = h->height - (sps->crop_top + sps->crop_bottom); /* handle container cropping */ - if (!h->sps.crop && - FFALIGN(h->avctx->width, 16) == h->width && - FFALIGN(h->avctx->height, 16) == h->height) { + if (FFALIGN(h->avctx->width, 16) == FFALIGN(width, 16) && + FFALIGN(h->avctx->height, 16) == FFALIGN(height, 16)) { width = h->avctx->width; height = h->avctx->height; } @@ -1058,11 +810,11 @@ static int init_dimensions(H264Context *h) return AVERROR_INVALIDDATA; av_log(h->avctx, AV_LOG_WARNING, "Ignoring cropping information.\n"); - h->sps.crop_bottom = - h->sps.crop_top = - h->sps.crop_right = - h->sps.crop_left = - h->sps.crop = 0; + sps->crop_bottom = + sps->crop_top = + sps->crop_right = + sps->crop_left = + sps->crop = 0; width = h->width; height = h->height; @@ -1076,27 +828,25 @@ static int init_dimensions(H264Context *h) return 0; } -static int h264_slice_header_init(H264Context *h, int reinit) +static int h264_slice_header_init(H264Context *h) { - int nb_slices = (HAVE_THREADS && - h->avctx->active_thread_type & FF_THREAD_SLICE) ? - h->avctx->thread_count : 1; + const SPS *sps = h->ps.sps; int i, ret; - ff_set_sar(h->avctx, h->sps.sar); + ff_set_sar(h->avctx, sps->sar); av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt, &h->chroma_x_shift, &h->chroma_y_shift); - if (h->sps.timing_info_present_flag) { - int64_t den = h->sps.time_scale; - if (h->x264_build < 44U) + if (sps->timing_info_present_flag) { + int64_t den = sps->time_scale; + if (h->sei.unregistered.x264_build < 44U) den *= 2; - av_reduce(&h->avctx->time_base.num, &h->avctx->time_base.den, - h->sps.num_units_in_tick, den, 1 << 30); + av_reduce(&h->avctx->framerate.den, &h->avctx->framerate.num, + sps->num_units_in_tick, den, 1 << 30); } - if (reinit) - ff_h264_free_tables(h, 0); + ff_h264_free_tables(h); + h->first_field = 0; h->prev_interlaced_frame = 1; @@ -1107,67 +857,45 @@ static int h264_slice_header_init(H264Context *h, int reinit) return ret; } - if (nb_slices > H264_MAX_THREADS || (nb_slices > h->mb_height && h->mb_height)) { - int max_slices; - if (h->mb_height) - max_slices = FFMIN(H264_MAX_THREADS, h->mb_height); - else - max_slices = H264_MAX_THREADS; - av_log(h->avctx, AV_LOG_WARNING, "too many threads/slices %d," - " reducing to %d\n", nb_slices, max_slices); - nb_slices = max_slices; + if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 10) { + av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n", + sps->bit_depth_luma); + return AVERROR_INVALIDDATA; } - h->slice_context_count = nb_slices; + + h->avctx->bits_per_raw_sample = sps->bit_depth_luma; + h->pixel_shift = sps->bit_depth_luma > 8; + h->chroma_format_idc = sps->chroma_format_idc; + h->bit_depth_luma = sps->bit_depth_luma; + + ff_h264dsp_init(&h->h264dsp, sps->bit_depth_luma, + sps->chroma_format_idc); + ff_h264chroma_init(&h->h264chroma, sps->bit_depth_chroma); + ff_h264qpel_init(&h->h264qpel, sps->bit_depth_luma); + ff_h264_pred_init(&h->hpc, h->avctx->codec_id, sps->bit_depth_luma, + sps->chroma_format_idc); + ff_videodsp_init(&h->vdsp, sps->bit_depth_luma); if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) { - ret = ff_h264_context_init(h); + ret = ff_h264_slice_context_init(h, &h->slice_ctx[0]); if (ret < 0) { av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); return ret; } } else { - for (i = 1; i < h->slice_context_count; i++) { - H264Context *c; - c = h->thread_context[i] = av_mallocz(sizeof(H264Context)); - if (!c) - return AVERROR(ENOMEM); - c->avctx = h->avctx; - c->mecc = h->mecc; - c->vdsp = h->vdsp; - c->h264dsp = h->h264dsp; - c->h264qpel = h->h264qpel; - c->h264chroma = h->h264chroma; - c->sps = h->sps; - c->pps = h->pps; - c->pixel_shift = h->pixel_shift; - c->width = h->width; - c->height = h->height; - c->linesize = h->linesize; - c->uvlinesize = h->uvlinesize; - c->chroma_x_shift = h->chroma_x_shift; - c->chroma_y_shift = h->chroma_y_shift; - c->qscale = h->qscale; - c->droppable = h->droppable; - c->data_partitioning = h->data_partitioning; - c->low_delay = h->low_delay; - c->mb_width = h->mb_width; - c->mb_height = h->mb_height; - c->mb_stride = h->mb_stride; - c->mb_num = h->mb_num; - c->flags = h->flags; - c->workaround_bugs = h->workaround_bugs; - c->pict_type = h->pict_type; - - init_scan_tables(c); - clone_tables(c, h, i); - c->context_initialized = 1; - } + for (i = 0; i < h->nb_slice_ctx; i++) { + H264SliceContext *sl = &h->slice_ctx[i]; + + sl->h264 = h; + sl->intra4x4_pred_mode = h->intra4x4_pred_mode + i * 8 * 2 * h->mb_stride; + sl->mvd_table[0] = h->mvd_table[0] + i * 8 * 2 * h->mb_stride; + sl->mvd_table[1] = h->mvd_table[1] + i * 8 * 2 * h->mb_stride; - for (i = 0; i < h->slice_context_count; i++) - if ((ret = ff_h264_context_init(h->thread_context[i])) < 0) { + if ((ret = ff_h264_slice_context_init(h, sl)) < 0) { av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); return ret; } + } } h->context_initialized = 1; @@ -1175,129 +903,37 @@ static int h264_slice_header_init(H264Context *h, int reinit) return 0; } -/** - * Decode a slice header. - * This will (re)intialize the decoder and call h264_frame_start() as needed. - * - * @param h h264context - * @param h0 h264 master context (differs from 'h' when doing sliced based - * parallel decoding) - * - * @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded - */ -int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) +static int h264_init_ps(H264Context *h, const H264SliceContext *sl) { - unsigned int first_mb_in_slice; - unsigned int pps_id; - int ret; - unsigned int slice_type, tmp, i, j; - int default_ref_list_done = 0; - int last_pic_structure, last_pic_droppable; - int needs_reinit = 0; - int field_pic_flag, bottom_field_flag; - - h->qpel_put = h->h264qpel.put_h264_qpel_pixels_tab; - h->qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab; - - first_mb_in_slice = get_ue_golomb(&h->gb); - - if (first_mb_in_slice == 0) { // FIXME better field boundary detection - if (h0->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) { - ff_h264_field_end(h, 1); - } - - h0->current_slice = 0; - if (!h0->first_field) { - if (h->cur_pic_ptr && !h->droppable) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - } - h->cur_pic_ptr = NULL; - } - } - - slice_type = get_ue_golomb_31(&h->gb); - if (slice_type > 9) { - av_log(h->avctx, AV_LOG_ERROR, - "slice type %d too large at %d %d\n", - slice_type, h->mb_x, h->mb_y); - return AVERROR_INVALIDDATA; - } - if (slice_type > 4) { - slice_type -= 5; - h->slice_type_fixed = 1; - } else - h->slice_type_fixed = 0; - - slice_type = golomb_to_pict_type[slice_type]; - if (slice_type == AV_PICTURE_TYPE_I || - (h0->current_slice != 0 && slice_type == h0->last_slice_type)) { - default_ref_list_done = 1; - } - h->slice_type = slice_type; - h->slice_type_nos = slice_type & 3; - - if (h->nal_unit_type == NAL_IDR_SLICE && - h->slice_type_nos != AV_PICTURE_TYPE_I) { - av_log(h->avctx, AV_LOG_ERROR, "A non-intra slice in an IDR NAL unit.\n"); - return AVERROR_INVALIDDATA; - } - - // to make a few old functions happy, it's wrong though - h->pict_type = h->slice_type; - - pps_id = get_ue_golomb(&h->gb); - if (pps_id >= MAX_PPS_COUNT) { - av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); - return AVERROR_INVALIDDATA; - } - if (!h0->pps_buffers[pps_id]) { - av_log(h->avctx, AV_LOG_ERROR, - "non-existing PPS %u referenced\n", - pps_id); - return AVERROR_INVALIDDATA; - } - h->pps = *h0->pps_buffers[pps_id]; - - if (!h0->sps_buffers[h->pps.sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", - h->pps.sps_id); - return AVERROR_INVALIDDATA; - } - - if (h->pps.sps_id != h->sps.sps_id || - h0->sps_buffers[h->pps.sps_id]->new) { - h0->sps_buffers[h->pps.sps_id]->new = 0; + const SPS *sps; + int needs_reinit = 0, ret; - h->sps = *h0->sps_buffers[h->pps.sps_id]; + h->ps.pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; + if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { + h->ps.sps = (SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data; - if (h->bit_depth_luma != h->sps.bit_depth_luma || - h->chroma_format_idc != h->sps.chroma_format_idc) { - h->bit_depth_luma = h->sps.bit_depth_luma; - h->chroma_format_idc = h->sps.chroma_format_idc; + if (h->bit_depth_luma != h->ps.sps->bit_depth_luma || + h->chroma_format_idc != h->ps.sps->chroma_format_idc) needs_reinit = 1; - } - if ((ret = ff_h264_set_parameter_from_sps(h)) < 0) - return ret; } + sps = h->ps.sps; - h->avctx->profile = ff_h264_get_profile(&h->sps); - h->avctx->level = h->sps.level_idc; - h->avctx->refs = h->sps.ref_frame_count; + h->avctx->profile = ff_h264_get_profile(sps); + h->avctx->level = sps->level_idc; + h->avctx->refs = sps->ref_frame_count; - if (h->mb_width != h->sps.mb_width || - h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag)) + if (h->mb_width != sps->mb_width || + h->mb_height != sps->mb_height) needs_reinit = 1; - h->mb_width = h->sps.mb_width; - h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); + h->mb_width = sps->mb_width; + h->mb_height = sps->mb_height; h->mb_num = h->mb_width * h->mb_height; h->mb_stride = h->mb_width + 1; h->b_stride = h->mb_width * 4; - h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p + h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p h->width = 16 * h->mb_width; h->height = 16 * h->mb_height; @@ -1306,27 +942,27 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) if (ret < 0) return ret; - if (h->sps.video_signal_type_present_flag) { - h->avctx->color_range = h->sps.full_range ? AVCOL_RANGE_JPEG - : AVCOL_RANGE_MPEG; - if (h->sps.colour_description_present_flag) { - if (h->avctx->colorspace != h->sps.colorspace) + if (sps->video_signal_type_present_flag) { + h->avctx->color_range = sps->full_range ? AVCOL_RANGE_JPEG + : AVCOL_RANGE_MPEG; + if (sps->colour_description_present_flag) { + if (h->avctx->colorspace != sps->colorspace) needs_reinit = 1; - h->avctx->color_primaries = h->sps.color_primaries; - h->avctx->color_trc = h->sps.color_trc; - h->avctx->colorspace = h->sps.colorspace; + h->avctx->color_primaries = sps->color_primaries; + h->avctx->color_trc = sps->color_trc; + h->avctx->colorspace = sps->colorspace; } } - if (h->context_initialized && needs_reinit) { + if (!h->context_initialized || needs_reinit) { h->context_initialized = 0; - if (h != h0) { + if (sl != h->slice_ctx) { av_log(h->avctx, AV_LOG_ERROR, "changing width %d -> %d / height %d -> %d on " "slice %d\n", h->width, h->avctx->coded_width, h->height, h->avctx->coded_height, - h0->current_slice + 1); + h->current_slice + 1); return AVERROR_INVALIDDATA; } @@ -1336,446 +972,845 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) return ret; h->avctx->pix_fmt = ret; - av_log(h->avctx, AV_LOG_INFO, "Reinit context to %dx%d, " + av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, " "pix_fmt: %d\n", h->width, h->height, h->avctx->pix_fmt); - if ((ret = h264_slice_header_init(h, 1)) < 0) { + if ((ret = h264_slice_header_init(h)) < 0) { av_log(h->avctx, AV_LOG_ERROR, "h264_slice_header_init() failed\n"); return ret; } } - if (!h->context_initialized) { - if (h != h0) { - av_log(h->avctx, AV_LOG_ERROR, - "Cannot (re-)initialize context during parallel decoding.\n"); - return AVERROR_PATCHWELCOME; - } - if ((ret = get_pixel_format(h)) < 0) - return ret; - h->avctx->pix_fmt = ret; + return 0; +} - if ((ret = h264_slice_header_init(h, 0)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, - "h264_slice_header_init() failed\n"); - return ret; +static int h264_export_frame_props(H264Context *h) +{ + const SPS *sps = h->ps.sps; + H264Picture *cur = h->cur_pic_ptr; + + cur->f->interlaced_frame = 0; + cur->f->repeat_pict = 0; + + /* Signal interlacing information externally. */ + /* Prioritize picture timing SEI information over used + * decoding process if it exists. */ + + if (sps->pic_struct_present_flag) { + H264SEIPictureTiming *pt = &h->sei.picture_timing; + switch (pt->pic_struct) { + case SEI_PIC_STRUCT_FRAME: + break; + case SEI_PIC_STRUCT_TOP_FIELD: + case SEI_PIC_STRUCT_BOTTOM_FIELD: + cur->f->interlaced_frame = 1; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM: + case SEI_PIC_STRUCT_BOTTOM_TOP: + if (FIELD_OR_MBAFF_PICTURE(h)) + cur->f->interlaced_frame = 1; + else + // try to flag soft telecine progressive + cur->f->interlaced_frame = h->prev_interlaced_frame; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + /* Signal the possibility of telecined film externally + * (pic_struct 5,6). From these hints, let the applications + * decide if they apply deinterlacing. */ + cur->f->repeat_pict = 1; + break; + case SEI_PIC_STRUCT_FRAME_DOUBLING: + cur->f->repeat_pict = 2; + break; + case SEI_PIC_STRUCT_FRAME_TRIPLING: + cur->f->repeat_pict = 4; + break; } - } - if (h == h0 && h->dequant_coeff_pps != pps_id) { - h->dequant_coeff_pps = pps_id; - h264_init_dequant_tables(h); + if ((pt->ct_type & 3) && + pt->pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) + cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; + } else { + /* Derive interlacing flag from used decoding process. */ + cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); } + h->prev_interlaced_frame = cur->f->interlaced_frame; - h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); - - h->mb_mbaff = 0; - h->mb_aff_frame = 0; - last_pic_structure = h0->picture_structure; - last_pic_droppable = h0->droppable; - h->droppable = h->nal_ref_idc == 0; - if (h->sps.frame_mbs_only_flag) { - h->picture_structure = PICT_FRAME; + if (cur->field_poc[0] != cur->field_poc[1]) { + /* Derive top_field_first from field pocs. */ + cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1]; } else { - field_pic_flag = get_bits1(&h->gb); - if (field_pic_flag) { - bottom_field_flag = get_bits1(&h->gb); - h->picture_structure = PICT_TOP_FIELD + bottom_field_flag; + if (cur->f->interlaced_frame || sps->pic_struct_present_flag) { + /* Use picture timing SEI information. Even if it is a + * information of a past frame, better than nothing. */ + if (h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || + h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) + cur->f->top_field_first = 1; + else + cur->f->top_field_first = 0; } else { - h->picture_structure = PICT_FRAME; - h->mb_aff_frame = h->sps.mb_aff; + /* Most likely progressive */ + cur->f->top_field_first = 0; } } - h->mb_field_decoding_flag = h->picture_structure != PICT_FRAME; - if (h0->current_slice != 0) { - if (last_pic_structure != h->picture_structure || - last_pic_droppable != h->droppable) { - av_log(h->avctx, AV_LOG_ERROR, - "Changing field mode (%d -> %d) between slices is not allowed\n", - last_pic_structure, h->picture_structure); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_INVALIDDATA; - } else if (!h0->cur_pic_ptr) { - av_log(h->avctx, AV_LOG_ERROR, - "unset cur_pic_ptr on slice %d\n", - h0->current_slice + 1); - return AVERROR_INVALIDDATA; + if (h->sei.frame_packing.present && + h->sei.frame_packing.arrangement_type >= 0 && + h->sei.frame_packing.arrangement_type <= 6 && + h->sei.frame_packing.content_interpretation_type > 0 && + h->sei.frame_packing.content_interpretation_type < 3) { + H264SEIFramePacking *fp = &h->sei.frame_packing; + AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); + if (!stereo) + return AVERROR(ENOMEM); + + switch (fp->arrangement_type) { + case 0: + stereo->type = AV_STEREO3D_CHECKERBOARD; + break; + case 1: + stereo->type = AV_STEREO3D_COLUMNS; + break; + case 2: + stereo->type = AV_STEREO3D_LINES; + break; + case 3: + if (fp->quincunx_subsampling) + stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; + else + stereo->type = AV_STEREO3D_SIDEBYSIDE; + break; + case 4: + stereo->type = AV_STEREO3D_TOPBOTTOM; + break; + case 5: + stereo->type = AV_STEREO3D_FRAMESEQUENCE; + break; + case 6: + stereo->type = AV_STEREO3D_2D; + break; } - } else { - /* Shorten frame num gaps so we don't have to allocate reference - * frames just to throw them away */ - if (h->frame_num != h->prev_frame_num) { - int unwrap_prev_frame_num = h->prev_frame_num; - int max_frame_num = 1 << h->sps.log2_max_frame_num; - if (unwrap_prev_frame_num > h->frame_num) - unwrap_prev_frame_num -= max_frame_num; + if (fp->content_interpretation_type == 2) + stereo->flags = AV_STEREO3D_FLAG_INVERT; + } - if ((h->frame_num - unwrap_prev_frame_num) > h->sps.ref_frame_count) { - unwrap_prev_frame_num = (h->frame_num - h->sps.ref_frame_count) - 1; - if (unwrap_prev_frame_num < 0) - unwrap_prev_frame_num += max_frame_num; + if (h->sei.display_orientation.present && + (h->sei.display_orientation.anticlockwise_rotation || + h->sei.display_orientation.hflip || + h->sei.display_orientation.vflip)) { + H264SEIDisplayOrientation *o = &h->sei.display_orientation; + double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16); + AVFrameSideData *rotation = av_frame_new_side_data(cur->f, + AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (!rotation) + return AVERROR(ENOMEM); - h->prev_frame_num = unwrap_prev_frame_num; - } - } + av_display_rotation_set((int32_t *)rotation->data, angle); + av_display_matrix_flip((int32_t *)rotation->data, + o->hflip, o->vflip); + } - /* See if we have a decoded first field looking for a pair... - * Here, we're using that to see if we should mark previously - * decode frames as "finished". - * We have to do that before the "dummy" in-between frame allocation, - * since that can modify s->current_picture_ptr. */ - if (h0->first_field) { - assert(h0->cur_pic_ptr); - assert(h0->cur_pic_ptr->f.buf[0]); - assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); - - /* figure out if we have a complementary field pair */ - if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { - /* Previous field is unmatched. Don't display it, but let it - * remain for reference if marked as such. */ - if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_TOP_FIELD); - } + if (h->sei.afd.present) { + AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD, + sizeof(uint8_t)); + if (!sd) + return AVERROR(ENOMEM); + + *sd->data = h->sei.afd.active_format_description; + h->sei.afd.present = 0; + } + + if (h->sei.a53_caption.a53_caption) { + H264SEIA53Caption *a53 = &h->sei.a53_caption; + AVFrameSideData *sd = av_frame_new_side_data(cur->f, + AV_FRAME_DATA_A53_CC, + a53->a53_caption_size); + if (!sd) + return AVERROR(ENOMEM); + + memcpy(sd->data, a53->a53_caption, a53->a53_caption_size); + av_freep(&a53->a53_caption); + a53->a53_caption_size = 0; + } + + return 0; +} + +static int h264_select_output_frame(H264Context *h) +{ + const SPS *sps = h->ps.sps; + H264Picture *out = h->cur_pic_ptr; + H264Picture *cur = h->cur_pic_ptr; + int i, pics, out_of_order, out_idx; + int invalid = 0, cnt = 0; + int ret; + + if (sps->bitstream_restriction_flag || + h->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { + h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, sps->num_reorder_frames); + } + + pics = 0; + while (h->delayed_pic[pics]) + pics++; + + assert(pics <= MAX_DELAYED_PIC_COUNT); + + h->delayed_pic[pics++] = cur; + if (cur->reference == 0) + cur->reference = DELAYED_PIC_REF; + + /* Frame reordering. This code takes pictures from coding order and sorts + * them by their incremental POC value into display order. It supports POC + * gaps, MMCO reset codes and random resets. + * A "display group" can start either with a IDR frame (f.key_frame = 1), + * and/or can be closed down with a MMCO reset code. In sequences where + * there is no delay, we can't detect that (since the frame was already + * output to the user), so we also set h->mmco_reset to detect the MMCO + * reset code. + * FIXME: if we detect insufficient delays (as per h->avctx->has_b_frames), + * we increase the delay between input and output. All frames affected by + * the lag (e.g. those that should have been output before another frame + * that we already returned to the user) will be dropped. This is a bug + * that we will fix later. */ + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { + cnt += out->poc < h->last_pocs[i]; + invalid += out->poc == INT_MIN; + } + if (!h->mmco_reset && !cur->f->key_frame && + cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) { + h->mmco_reset = 2; + if (pics > 1) + h->delayed_pic[pics - 2]->mmco_reset = 2; + } + if (h->mmco_reset || cur->f->key_frame) { + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; + cnt = 0; + invalid = MAX_DELAYED_PIC_COUNT; + } + out = h->delayed_pic[0]; + out_idx = 0; + for (i = 1; i < MAX_DELAYED_PIC_COUNT && + h->delayed_pic[i] && + !h->delayed_pic[i - 1]->mmco_reset && + !h->delayed_pic[i]->f->key_frame; + i++) + if (h->delayed_pic[i]->poc < out->poc) { + out = h->delayed_pic[i]; + out_idx = i; + } + if (h->avctx->has_b_frames == 0 && + (h->delayed_pic[0]->f->key_frame || h->mmco_reset)) + h->next_outputed_poc = INT_MIN; + out_of_order = !out->f->key_frame && !h->mmco_reset && + (out->poc < h->next_outputed_poc); + + if (sps->bitstream_restriction_flag && + h->avctx->has_b_frames >= sps->num_reorder_frames) { + } else if (out_of_order && pics - 1 == h->avctx->has_b_frames && + h->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) { + if (invalid + cnt < MAX_DELAYED_PIC_COUNT) { + h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, cnt); + } + } else if (!h->avctx->has_b_frames && + ((h->next_outputed_poc != INT_MIN && + out->poc > h->next_outputed_poc + 2) || + cur->f->pict_type == AV_PICTURE_TYPE_B)) { + h->avctx->has_b_frames++; + } + + if (pics > h->avctx->has_b_frames) { + out->reference &= ~DELAYED_PIC_REF; + for (i = out_idx; h->delayed_pic[i]; i++) + h->delayed_pic[i] = h->delayed_pic[i + 1]; + } + memmove(h->last_pocs, &h->last_pocs[1], + sizeof(*h->last_pocs) * (MAX_DELAYED_PIC_COUNT - 1)); + h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = cur->poc; + if (!out_of_order && pics > h->avctx->has_b_frames) { + av_frame_unref(h->output_frame); + ret = av_frame_ref(h->output_frame, out->f); + if (ret < 0) + return ret; + + if (out->recovered) { + // We have reached an recovery point and all frames after it in + // display order are "recovered". + h->frame_recovered |= FRAME_RECOVERED_SEI; + } + out->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_SEI); + + if (!out->recovered) { + if (!(h->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT)) + av_frame_unref(h->output_frame); + else + h->output_frame->flags |= AV_FRAME_FLAG_CORRUPT; + } + + if (out->mmco_reset) { + if (out_idx > 0) { + h->next_outputed_poc = out->poc; + h->delayed_pic[out_idx - 1]->mmco_reset = out->mmco_reset; } else { - if (h0->cur_pic_ptr->frame_num != h->frame_num) { - /* This and previous field were reference, but had - * different frame_nums. Consider this field first in - * pair. Throw away previous field except for reference - * purposes. */ - if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { - ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_TOP_FIELD); - } - } else { - /* Second field in complementary pair */ - if (!((last_pic_structure == PICT_TOP_FIELD && - h->picture_structure == PICT_BOTTOM_FIELD) || - (last_pic_structure == PICT_BOTTOM_FIELD && - h->picture_structure == PICT_TOP_FIELD))) { - av_log(h->avctx, AV_LOG_ERROR, - "Invalid field mode combination %d/%d\n", - last_pic_structure, h->picture_structure); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_INVALIDDATA; - } else if (last_pic_droppable != h->droppable) { - avpriv_request_sample(h->avctx, - "Found reference and non-reference fields in the same frame, which"); - h->picture_structure = last_pic_structure; - h->droppable = last_pic_droppable; - return AVERROR_PATCHWELCOME; - } - } + h->next_outputed_poc = INT_MIN; + } + } else { + if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f->key_frame) { + h->next_outputed_poc = INT_MIN; + } else { + h->next_outputed_poc = out->poc; } } + h->mmco_reset = 0; + } else { + av_log(h->avctx, AV_LOG_DEBUG, "no picture\n"); + } - while (h->frame_num != h->prev_frame_num && - h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) { - H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL; - av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", - h->frame_num, h->prev_frame_num); - ret = h264_frame_start(h); - if (ret < 0) { - h0->first_field = 0; - return ret; - } + return 0; +} - h->prev_frame_num++; - h->prev_frame_num %= 1 << h->sps.log2_max_frame_num; - h->cur_pic_ptr->frame_num = h->prev_frame_num; - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); - ret = ff_generate_sliding_window_mmcos(h, 1); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - return ret; - ret = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - return ret; - /* Error concealment: If a ref is missing, copy the previous ref - * in its place. - * FIXME: Avoiding a memcpy would be nice, but ref handling makes - * many assumptions about there being no actual duplicates. - * FIXME: This does not copy padding for out-of-frame motion - * vectors. Given we are concealing a lost frame, this probably - * is not noticeable by comparison, but it should be fixed. */ - if (h->short_ref_count) { - if (prev) { - av_image_copy(h->short_ref[0]->f.data, - h->short_ref[0]->f.linesize, - (const uint8_t **)prev->f.data, - prev->f.linesize, - h->avctx->pix_fmt, - h->mb_width * 16, - h->mb_height * 16); - h->short_ref[0]->poc = prev->poc + 2; - } - h->short_ref[0]->frame_num = h->prev_frame_num; - } +/* This function is called right after decoding the slice header for a first + * slice in a field (or a frame). It decides whether we are decoding a new frame + * or a second field in a pair and does the necessary setup. + */ +static int h264_field_start(H264Context *h, const H264SliceContext *sl, + const H2645NAL *nal) +{ + const SPS *sps; + + int last_pic_structure, last_pic_droppable, ret; + + ret = h264_init_ps(h, sl); + if (ret < 0) + return ret; + + sps = h->ps.sps; + + last_pic_droppable = h->droppable; + last_pic_structure = h->picture_structure; + h->droppable = (nal->ref_idc == 0); + h->picture_structure = sl->picture_structure; + + h->poc.frame_num = sl->frame_num; + h->poc.poc_lsb = sl->poc_lsb; + h->poc.delta_poc_bottom = sl->delta_poc_bottom; + h->poc.delta_poc[0] = sl->delta_poc[0]; + h->poc.delta_poc[1] = sl->delta_poc[1]; + + /* Shorten frame num gaps so we don't have to allocate reference + * frames just to throw them away */ + if (h->poc.frame_num != h->poc.prev_frame_num) { + int unwrap_prev_frame_num = h->poc.prev_frame_num; + int max_frame_num = 1 << sps->log2_max_frame_num; + + if (unwrap_prev_frame_num > h->poc.frame_num) + unwrap_prev_frame_num -= max_frame_num; + + if ((h->poc.frame_num - unwrap_prev_frame_num) > sps->ref_frame_count) { + unwrap_prev_frame_num = (h->poc.frame_num - sps->ref_frame_count) - 1; + if (unwrap_prev_frame_num < 0) + unwrap_prev_frame_num += max_frame_num; + + h->poc.prev_frame_num = unwrap_prev_frame_num; } + } - /* See if we have a decoded first field looking for a pair... - * We're using that to see whether to continue decoding in that - * frame, or to allocate a new one. */ - if (h0->first_field) { - assert(h0->cur_pic_ptr); - assert(h0->cur_pic_ptr->f.buf[0]); - assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); - - /* figure out if we have a complementary field pair */ - if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { - /* Previous field is unmatched. Don't display it, but let it - * remain for reference if marked as such. */ - h0->cur_pic_ptr = NULL; - h0->first_field = FIELD_PICTURE(h); + /* See if we have a decoded first field looking for a pair... + * Here, we're using that to see if we should mark previously + * decode frames as "finished". + * We have to do that before the "dummy" in-between frame allocation, + * since that can modify s->current_picture_ptr. */ + if (h->first_field) { + assert(h->cur_pic_ptr); + assert(h->cur_pic_ptr->f->buf[0]); + assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF); + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { + /* Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. */ + if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } + } else { + if (h->cur_pic_ptr->frame_num != h->poc.frame_num) { + /* This and previous field were reference, but had + * different frame_nums. Consider this field first in + * pair. Throw away previous field except for reference + * purposes. */ + if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } } else { - if (h0->cur_pic_ptr->frame_num != h->frame_num) { - /* This and the previous field had different frame_nums. - * Consider this field first in pair. Throw away previous - * one except for reference purposes. */ - h0->first_field = 1; - h0->cur_pic_ptr = NULL; - } else { - /* Second field in complementary pair */ - h0->first_field = 0; + /* Second field in complementary pair */ + if (!((last_pic_structure == PICT_TOP_FIELD && + h->picture_structure == PICT_BOTTOM_FIELD) || + (last_pic_structure == PICT_BOTTOM_FIELD && + h->picture_structure == PICT_TOP_FIELD))) { + av_log(h->avctx, AV_LOG_ERROR, + "Invalid field mode combination %d/%d\n", + last_pic_structure, h->picture_structure); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_INVALIDDATA; + } else if (last_pic_droppable != h->droppable) { + avpriv_request_sample(h->avctx, + "Found reference and non-reference fields in the same frame, which"); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_PATCHWELCOME; } } - } else { - /* Frame or first field in a potentially complementary pair */ - h0->first_field = FIELD_PICTURE(h); + } + } + + while (h->poc.frame_num != h->poc.prev_frame_num && + h->poc.frame_num != (h->poc.prev_frame_num + 1) % (1 << sps->log2_max_frame_num)) { + H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL; + av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", + h->poc.frame_num, h->poc.prev_frame_num); + ret = initialize_cur_frame(h); + if (ret < 0) { + h->first_field = 0; + return ret; } - if (!FIELD_PICTURE(h) || h0->first_field) { - if (h264_frame_start(h) < 0) { - h0->first_field = 0; - return AVERROR_INVALIDDATA; + h->poc.prev_frame_num++; + h->poc.prev_frame_num %= 1 << sps->log2_max_frame_num; + h->cur_pic_ptr->frame_num = h->poc.prev_frame_num; + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); + + h->explicit_ref_marking = 0; + ret = ff_h264_execute_ref_pic_marking(h); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + /* Error concealment: If a ref is missing, copy the previous ref + * in its place. + * FIXME: Avoiding a memcpy would be nice, but ref handling makes + * many assumptions about there being no actual duplicates. + * FIXME: This does not copy padding for out-of-frame motion + * vectors. Given we are concealing a lost frame, this probably + * is not noticeable by comparison, but it should be fixed. */ + if (h->short_ref_count) { + if (prev && + h->short_ref[0]->f->width == prev->f->width && + h->short_ref[0]->f->height == prev->f->height && + h->short_ref[0]->f->format == prev->f->format) { + ff_thread_await_progress(&prev->tf, INT_MAX, 0); + if (prev->field_picture) + ff_thread_await_progress(&prev->tf, INT_MAX, 1); + av_image_copy(h->short_ref[0]->f->data, + h->short_ref[0]->f->linesize, + (const uint8_t **)prev->f->data, + prev->f->linesize, + prev->f->format, + h->mb_width * 16, + h->mb_height * 16); + h->short_ref[0]->poc = prev->poc + 2; } - } else { - release_unused_pictures(h, 0); + h->short_ref[0]->frame_num = h->poc.prev_frame_num; } } - if (h != h0 && (ret = clone_slice(h, h0)) < 0) - return ret; - h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup + /* See if we have a decoded first field looking for a pair... + * We're using that to see whether to continue decoding in that + * frame, or to allocate a new one. */ + if (h->first_field) { + assert(h->cur_pic_ptr); + assert(h->cur_pic_ptr->f->buf[0]); + assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF); - assert(h->mb_num == h->mb_width * h->mb_height); - if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || - first_mb_in_slice >= h->mb_num) { - av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); - return AVERROR_INVALIDDATA; + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { + /* Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. */ + h->cur_pic_ptr = NULL; + h->first_field = FIELD_PICTURE(h); + } else { + if (h->cur_pic_ptr->frame_num != h->poc.frame_num) { + /* This and the previous field had different frame_nums. + * Consider this field first in pair. Throw away previous + * one except for reference purposes. */ + h->first_field = 1; + h->cur_pic_ptr = NULL; + } else { + /* Second field in complementary pair */ + h->first_field = 0; + } + } + } else { + /* Frame or first field in a potentially complementary pair */ + h->first_field = FIELD_PICTURE(h); } - h->resync_mb_x = h->mb_x = first_mb_in_slice % h->mb_width; - h->resync_mb_y = h->mb_y = (first_mb_in_slice / h->mb_width) << - FIELD_OR_MBAFF_PICTURE(h); - if (h->picture_structure == PICT_BOTTOM_FIELD) - h->resync_mb_y = h->mb_y = h->mb_y + 1; - assert(h->mb_y < h->mb_height); - if (h->picture_structure == PICT_FRAME) { - h->curr_pic_num = h->frame_num; - h->max_pic_num = 1 << h->sps.log2_max_frame_num; + if (!FIELD_PICTURE(h) || h->first_field) { + if (h264_frame_start(h) < 0) { + h->first_field = 0; + return AVERROR_INVALIDDATA; + } } else { - h->curr_pic_num = 2 * h->frame_num + 1; - h->max_pic_num = 1 << (h->sps.log2_max_frame_num + 1); + release_unused_pictures(h, 0); } - if (h->nal_unit_type == NAL_IDR_SLICE) - get_ue_golomb(&h->gb); /* idr_pic_id */ + ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc, + h->ps.sps, &h->poc, h->picture_structure, nal->ref_idc); + + memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco)); + h->nb_mmco = sl->nb_mmco; + h->explicit_ref_marking = sl->explicit_ref_marking; - if (h->sps.poc_type == 0) { - h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb); + h->picture_idr = nal->type == H264_NAL_IDR_SLICE; - if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) - h->delta_poc_bottom = get_se_golomb(&h->gb); + if (h->sei.recovery_point.recovery_frame_cnt >= 0 && h->recovery_frame < 0) { + h->recovery_frame = (h->poc.frame_num + h->sei.recovery_point.recovery_frame_cnt) & + ((1 << h->ps.sps->log2_max_frame_num) - 1); } - if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) { - h->delta_poc[0] = get_se_golomb(&h->gb); + h->cur_pic_ptr->f->key_frame |= (nal->type == H264_NAL_IDR_SLICE) || + (h->sei.recovery_point.recovery_frame_cnt >= 0); - if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) - h->delta_poc[1] = get_se_golomb(&h->gb); + if (nal->type == H264_NAL_IDR_SLICE || h->recovery_frame == h->poc.frame_num) { + h->recovery_frame = -1; + h->cur_pic_ptr->recovered = 1; } + // If we have an IDR, all frames after it in decoded order are + // "recovered". + if (nal->type == H264_NAL_IDR_SLICE) + h->frame_recovered |= FRAME_RECOVERED_IDR; + h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR); - ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc); + /* Set the frame properties/side data. Only done for the second field in + * field coded frames, since some SEI information is present for each field + * and is merged by the SEI parsing code. */ + if (!FIELD_PICTURE(h) || !h->first_field) { + ret = h264_export_frame_props(h); + if (ret < 0) + return ret; - if (h->pps.redundant_pic_cnt_present) - h->redundant_pic_count = get_ue_golomb(&h->gb); + ret = h264_select_output_frame(h); + if (ret < 0) + return ret; + } - ret = ff_set_ref_count(h); - if (ret < 0) - return ret; - else if (ret == 1) - default_ref_list_done = 0; + if (h->avctx->hwaccel) { + ret = h->avctx->hwaccel->start_frame(h->avctx, NULL, 0); + if (ret < 0) + return ret; + } - if (!default_ref_list_done) - ff_h264_fill_default_ref_list(h); + return 0; +} - if (h->slice_type_nos != AV_PICTURE_TYPE_I) { - ret = ff_h264_decode_ref_pic_list_reordering(h); - if (ret < 0) { - h->ref_count[1] = h->ref_count[0] = 0; - return ret; - } +static int h264_slice_header_parse(H264SliceContext *sl, const H2645NAL *nal, + const H264ParamSets *ps, AVCodecContext *avctx) +{ + const SPS *sps; + const PPS *pps; + int ret; + unsigned int slice_type, tmp, i; + int field_pic_flag, bottom_field_flag, picture_structure; + + sl->first_mb_addr = get_ue_golomb(&sl->gb); + + slice_type = get_ue_golomb_31(&sl->gb); + if (slice_type > 9) { + av_log(avctx, AV_LOG_ERROR, + "slice type %d too large at %d\n", + slice_type, sl->first_mb_addr); + return AVERROR_INVALIDDATA; } + if (slice_type > 4) { + slice_type -= 5; + sl->slice_type_fixed = 1; + } else + sl->slice_type_fixed = 0; - if ((h->pps.weighted_pred && h->slice_type_nos == AV_PICTURE_TYPE_P) || - (h->pps.weighted_bipred_idc == 1 && - h->slice_type_nos == AV_PICTURE_TYPE_B)) - ff_pred_weight_table(h); - else if (h->pps.weighted_bipred_idc == 2 && - h->slice_type_nos == AV_PICTURE_TYPE_B) { - implicit_weight_table(h, -1); + slice_type = ff_h264_golomb_to_pict_type[slice_type]; + sl->slice_type = slice_type; + sl->slice_type_nos = slice_type & 3; + + if (nal->type == H264_NAL_IDR_SLICE && + sl->slice_type_nos != AV_PICTURE_TYPE_I) { + av_log(avctx, AV_LOG_ERROR, "A non-intra slice in an IDR NAL unit.\n"); + return AVERROR_INVALIDDATA; + } + + sl->pps_id = get_ue_golomb(&sl->gb); + if (sl->pps_id >= MAX_PPS_COUNT) { + av_log(avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id); + return AVERROR_INVALIDDATA; + } + if (!ps->pps_list[sl->pps_id]) { + av_log(avctx, AV_LOG_ERROR, + "non-existing PPS %u referenced\n", + sl->pps_id); + return AVERROR_INVALIDDATA; + } + pps = (const PPS*)ps->pps_list[sl->pps_id]->data; + + if (!ps->sps_list[pps->sps_id]) { + av_log(avctx, AV_LOG_ERROR, + "non-existing SPS %u referenced\n", pps->sps_id); + return AVERROR_INVALIDDATA; + } + sps = (const SPS*)ps->sps_list[pps->sps_id]->data; + + sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); + + sl->mb_mbaff = 0; + + if (sps->frame_mbs_only_flag) { + picture_structure = PICT_FRAME; } else { - h->use_weight = 0; - for (i = 0; i < 2; i++) { - h->luma_weight_flag[i] = 0; - h->chroma_weight_flag[i] = 0; + field_pic_flag = get_bits1(&sl->gb); + if (field_pic_flag) { + bottom_field_flag = get_bits1(&sl->gb); + picture_structure = PICT_TOP_FIELD + bottom_field_flag; + } else { + picture_structure = PICT_FRAME; } } + sl->picture_structure = picture_structure; + sl->mb_field_decoding_flag = picture_structure != PICT_FRAME; - // If frame-mt is enabled, only update mmco tables for the first slice - // in a field. Subsequent slices can temporarily clobber h->mmco_index - // or h->mmco, which will cause ref list mix-ups and decoding errors - // further down the line. This may break decoding if the first slice is - // corrupt, thus we only do this if frame-mt is enabled. - if (h->nal_ref_idc) { - ret = ff_h264_decode_ref_pic_marking(h0, &h->gb, - !(h->avctx->active_thread_type & FF_THREAD_FRAME) || - h0->current_slice == 0); - if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) - return AVERROR_INVALIDDATA; + if (picture_structure == PICT_FRAME) { + sl->curr_pic_num = sl->frame_num; + sl->max_pic_num = 1 << sps->log2_max_frame_num; + } else { + sl->curr_pic_num = 2 * sl->frame_num + 1; + sl->max_pic_num = 1 << (sps->log2_max_frame_num + 1); } - if (FRAME_MBAFF(h)) { - ff_h264_fill_mbaff_ref_list(h); + if (nal->type == H264_NAL_IDR_SLICE) + get_ue_golomb(&sl->gb); /* idr_pic_id */ - if (h->pps.weighted_bipred_idc == 2 && h->slice_type_nos == AV_PICTURE_TYPE_B) { - implicit_weight_table(h, 0); - implicit_weight_table(h, 1); - } + if (sps->poc_type == 0) { + sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb); + + if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) + sl->delta_poc_bottom = get_se_golomb(&sl->gb); } - if (h->slice_type_nos == AV_PICTURE_TYPE_B && !h->direct_spatial_mv_pred) - ff_h264_direct_dist_scale_factor(h); - ff_h264_direct_ref_list_init(h); + if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) { + sl->delta_poc[0] = get_se_golomb(&sl->gb); + + if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) + sl->delta_poc[1] = get_se_golomb(&sl->gb); + } + + sl->redundant_pic_count = 0; + if (pps->redundant_pic_cnt_present) + sl->redundant_pic_count = get_ue_golomb(&sl->gb); + + if (sl->slice_type_nos == AV_PICTURE_TYPE_B) + sl->direct_spatial_mv_pred = get_bits1(&sl->gb); + + ret = ff_h264_parse_ref_count(&sl->list_count, sl->ref_count, + &sl->gb, pps, sl->slice_type_nos, + picture_structure); + if (ret < 0) + return ret; + + if (sl->slice_type_nos != AV_PICTURE_TYPE_I) { + ret = ff_h264_decode_ref_pic_list_reordering(sl, avctx); + if (ret < 0) { + sl->ref_count[1] = sl->ref_count[0] = 0; + return ret; + } + } - if (h->slice_type_nos != AV_PICTURE_TYPE_I && h->pps.cabac) { - tmp = get_ue_golomb_31(&h->gb); + sl->pwt.use_weight = 0; + for (i = 0; i < 2; i++) { + sl->pwt.luma_weight_flag[i] = 0; + sl->pwt.chroma_weight_flag[i] = 0; + } + if ((pps->weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) || + (pps->weighted_bipred_idc == 1 && + sl->slice_type_nos == AV_PICTURE_TYPE_B)) + ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count, + sl->slice_type_nos, &sl->pwt); + + sl->explicit_ref_marking = 0; + if (nal->ref_idc) { + ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, avctx); + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + } + + if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) { + tmp = get_ue_golomb_31(&sl->gb); if (tmp > 2) { - av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp); + av_log(avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp); return AVERROR_INVALIDDATA; } - h->cabac_init_idc = tmp; + sl->cabac_init_idc = tmp; } - h->last_qscale_diff = 0; - tmp = h->pps.init_qp + get_se_golomb(&h->gb); - if (tmp > 51 + 6 * (h->sps.bit_depth_luma - 8)) { - av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); + sl->last_qscale_diff = 0; + tmp = pps->init_qp + get_se_golomb(&sl->gb); + if (tmp > 51 + 6 * (sps->bit_depth_luma - 8)) { + av_log(avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); return AVERROR_INVALIDDATA; } - h->qscale = tmp; - h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); + sl->qscale = tmp; + sl->chroma_qp[0] = get_chroma_qp(pps, 0, sl->qscale); + sl->chroma_qp[1] = get_chroma_qp(pps, 1, sl->qscale); // FIXME qscale / qp ... stuff - if (h->slice_type == AV_PICTURE_TYPE_SP) - get_bits1(&h->gb); /* sp_for_switch_flag */ - if (h->slice_type == AV_PICTURE_TYPE_SP || - h->slice_type == AV_PICTURE_TYPE_SI) - get_se_golomb(&h->gb); /* slice_qs_delta */ - - h->deblocking_filter = 1; - h->slice_alpha_c0_offset = 0; - h->slice_beta_offset = 0; - if (h->pps.deblocking_filter_parameters_present) { - tmp = get_ue_golomb_31(&h->gb); + if (sl->slice_type == AV_PICTURE_TYPE_SP) + get_bits1(&sl->gb); /* sp_for_switch_flag */ + if (sl->slice_type == AV_PICTURE_TYPE_SP || + sl->slice_type == AV_PICTURE_TYPE_SI) + get_se_golomb(&sl->gb); /* slice_qs_delta */ + + sl->deblocking_filter = 1; + sl->slice_alpha_c0_offset = 0; + sl->slice_beta_offset = 0; + if (pps->deblocking_filter_parameters_present) { + tmp = get_ue_golomb_31(&sl->gb); if (tmp > 2) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "deblocking_filter_idc %u out of range\n", tmp); return AVERROR_INVALIDDATA; } - h->deblocking_filter = tmp; - if (h->deblocking_filter < 2) - h->deblocking_filter ^= 1; // 1<->0 - - if (h->deblocking_filter) { - h->slice_alpha_c0_offset = get_se_golomb(&h->gb) * 2; - h->slice_beta_offset = get_se_golomb(&h->gb) * 2; - if (h->slice_alpha_c0_offset > 12 || - h->slice_alpha_c0_offset < -12 || - h->slice_beta_offset > 12 || - h->slice_beta_offset < -12) { - av_log(h->avctx, AV_LOG_ERROR, + sl->deblocking_filter = tmp; + if (sl->deblocking_filter < 2) + sl->deblocking_filter ^= 1; // 1<->0 + + if (sl->deblocking_filter) { + sl->slice_alpha_c0_offset = get_se_golomb(&sl->gb) * 2; + sl->slice_beta_offset = get_se_golomb(&sl->gb) * 2; + if (sl->slice_alpha_c0_offset > 12 || + sl->slice_alpha_c0_offset < -12 || + sl->slice_beta_offset > 12 || + sl->slice_beta_offset < -12) { + av_log(avctx, AV_LOG_ERROR, "deblocking filter parameters %d %d out of range\n", - h->slice_alpha_c0_offset, h->slice_beta_offset); + sl->slice_alpha_c0_offset, sl->slice_beta_offset); return AVERROR_INVALIDDATA; } } } + return 0; +} + +/* do all the per-slice initialization needed before we can start decoding the + * actual MBs */ +static int h264_slice_init(H264Context *h, H264SliceContext *sl, + const H2645NAL *nal) +{ + int i, j, ret = 0; + + if (h->current_slice > 0) { + if (h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) { + av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); + return AVERROR_INVALIDDATA; + } + + if (h->picture_structure != sl->picture_structure || + h->droppable != (nal->ref_idc == 0)) { + av_log(h->avctx, AV_LOG_ERROR, + "Changing field mode (%d -> %d) between slices is not allowed\n", + h->picture_structure, sl->picture_structure); + return AVERROR_INVALIDDATA; + } else if (!h->cur_pic_ptr) { + av_log(h->avctx, AV_LOG_ERROR, + "unset cur_pic_ptr on slice %d\n", + h->current_slice + 1); + return AVERROR_INVALIDDATA; + } + } + + if (h->picture_idr && nal->type != H264_NAL_IDR_SLICE) { + av_log(h->avctx, AV_LOG_ERROR, "Invalid mix of IDR and non-IDR slices\n"); + return AVERROR_INVALIDDATA; + } + + assert(h->mb_num == h->mb_width * h->mb_height); + if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || + sl->first_mb_addr >= h->mb_num) { + av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); + return AVERROR_INVALIDDATA; + } + sl->resync_mb_x = sl->mb_x = sl->first_mb_addr % h->mb_width; + sl->resync_mb_y = sl->mb_y = (sl->first_mb_addr / h->mb_width) << + FIELD_OR_MBAFF_PICTURE(h); + if (h->picture_structure == PICT_BOTTOM_FIELD) + sl->resync_mb_y = sl->mb_y = sl->mb_y + 1; + assert(sl->mb_y < h->mb_height); + + ret = ff_h264_build_ref_list(h, sl); + if (ret < 0) + return ret; + + if (h->ps.pps->weighted_bipred_idc == 2 && + sl->slice_type_nos == AV_PICTURE_TYPE_B) { + implicit_weight_table(h, sl, -1); + if (FRAME_MBAFF(h)) { + implicit_weight_table(h, sl, 0); + implicit_weight_table(h, sl, 1); + } + } + + if (sl->slice_type_nos == AV_PICTURE_TYPE_B && !sl->direct_spatial_mv_pred) + ff_h264_direct_dist_scale_factor(h, sl); + ff_h264_direct_ref_list_init(h, sl); + if (h->avctx->skip_loop_filter >= AVDISCARD_ALL || (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY && - h->slice_type_nos != AV_PICTURE_TYPE_I) || + sl->slice_type_nos != AV_PICTURE_TYPE_I) || (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR && - h->slice_type_nos == AV_PICTURE_TYPE_B) || + sl->slice_type_nos == AV_PICTURE_TYPE_B) || (h->avctx->skip_loop_filter >= AVDISCARD_NONREF && - h->nal_ref_idc == 0)) - h->deblocking_filter = 0; + nal->ref_idc == 0)) + sl->deblocking_filter = 0; - if (h->deblocking_filter == 1 && h0->max_contexts > 1) { - if (h->avctx->flags2 & CODEC_FLAG2_FAST) { + if (sl->deblocking_filter == 1 && h->nb_slice_ctx > 1) { + if (h->avctx->flags2 & AV_CODEC_FLAG2_FAST) { /* Cheat slightly for speed: * Do not bother to deblock across slices. */ - h->deblocking_filter = 2; + sl->deblocking_filter = 2; } else { - h0->max_contexts = 1; - if (!h0->single_decode_warning) { - av_log(h->avctx, AV_LOG_INFO, - "Cannot parallelize deblocking type 1, decoding such frames in sequential order\n"); - h0->single_decode_warning = 1; - } - if (h != h0) { - av_log(h->avctx, AV_LOG_ERROR, - "Deblocking switched inside frame.\n"); - return 1; - } + h->postpone_filter = 1; } } - h->qp_thresh = 15 - - FFMIN(h->slice_alpha_c0_offset, h->slice_beta_offset) - + sl->qp_thresh = 15 - + FFMIN(sl->slice_alpha_c0_offset, sl->slice_beta_offset) - FFMAX3(0, - h->pps.chroma_qp_index_offset[0], - h->pps.chroma_qp_index_offset[1]) + - 6 * (h->sps.bit_depth_luma - 8); + h->ps.pps->chroma_qp_index_offset[0], + h->ps.pps->chroma_qp_index_offset[1]) + + 6 * (h->ps.sps->bit_depth_luma - 8); - h0->last_slice_type = slice_type; - h->slice_num = ++h0->current_slice; - if (h->slice_num >= MAX_SLICES) { + sl->slice_num = ++h->current_slice; + if (sl->slice_num >= MAX_SLICES) { av_log(h->avctx, AV_LOG_ERROR, "Too many slices, increase MAX_SLICES and recompile\n"); } for (j = 0; j < 2; j++) { int id_list[16]; - int *ref2frm = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][j]; + int *ref2frm = h->ref2frm[sl->slice_num & (MAX_SLICES - 1)][j]; for (i = 0; i < 16; i++) { id_list[i] = 60; - if (j < h->list_count && i < h->ref_count[j] && - h->ref_list[j][i].f.buf[0]) { + if (j < sl->list_count && i < sl->ref_count[j] && + sl->ref_list[j][i].parent->f->buf[0]) { int k; - AVBuffer *buf = h->ref_list[j][i].f.buf[0]->buffer; + AVBuffer *buf = sl->ref_list[j][i].parent->f->buf[0]->buffer; for (k = 0; k < h->short_ref_count; k++) - if (h->short_ref[k]->f.buf[0]->buffer == buf) { + if (h->short_ref[k]->f->buf[0]->buffer == buf) { id_list[i] = k; break; } for (k = 0; k < h->long_ref_count; k++) - if (h->long_ref[k] && h->long_ref[k]->f.buf[0]->buffer == buf) { + if (h->long_ref[k] && h->long_ref[k]->f->buf[0]->buffer == buf) { id_list[i] = h->short_ref_count + k; break; } @@ -1785,41 +1820,110 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) ref2frm[0] = ref2frm[1] = -1; for (i = 0; i < 16; i++) - ref2frm[i + 2] = 4 * id_list[i] + (h->ref_list[j][i].reference & 3); + ref2frm[i + 2] = 4 * id_list[i] + (sl->ref_list[j][i].reference & 3); ref2frm[18 + 0] = ref2frm[18 + 1] = -1; for (i = 16; i < 48; i++) ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] + - (h->ref_list[j][i].reference & 3); + (sl->ref_list[j][i].reference & 3); } if (h->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(h->avctx, AV_LOG_DEBUG, - "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", - h->slice_num, + "slice:%d %s mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", + sl->slice_num, (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), - first_mb_in_slice, - av_get_picture_type_char(h->slice_type), - h->slice_type_fixed ? " fix" : "", - h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "", - pps_id, h->frame_num, + sl->mb_y * h->mb_width + sl->mb_x, + av_get_picture_type_char(sl->slice_type), + sl->slice_type_fixed ? " fix" : "", + nal->type == H264_NAL_IDR_SLICE ? " IDR" : "", + h->poc.frame_num, h->cur_pic_ptr->field_poc[0], h->cur_pic_ptr->field_poc[1], - h->ref_count[0], h->ref_count[1], - h->qscale, - h->deblocking_filter, - h->slice_alpha_c0_offset, h->slice_beta_offset, - h->use_weight, - h->use_weight == 1 && h->use_weight_chroma ? "c" : "", - h->slice_type == AV_PICTURE_TYPE_B ? (h->direct_spatial_mv_pred ? "SPAT" : "TEMP") : ""); + sl->ref_count[0], sl->ref_count[1], + sl->qscale, + sl->deblocking_filter, + sl->slice_alpha_c0_offset, sl->slice_beta_offset, + sl->pwt.use_weight, + sl->pwt.use_weight == 1 && sl->pwt.use_weight_chroma ? "c" : "", + sl->slice_type == AV_PICTURE_TYPE_B ? (sl->direct_spatial_mv_pred ? "SPAT" : "TEMP") : ""); + } + + return 0; +} + +int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal) +{ + H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued; + int ret; + + sl->gb = nal->gb; + + ret = h264_slice_header_parse(sl, nal, &h->ps, h->avctx); + if (ret < 0) + return ret; + + // discard redundant pictures + if (sl->redundant_pic_count > 0) + return 0; + + if (!h->setup_finished) { + if (sl->first_mb_addr == 0) { // FIXME better field boundary detection + // this slice starts a new field + // first decode any pending queued slices + if (h->nb_slice_ctx_queued) { + H264SliceContext tmp_ctx; + + ret = ff_h264_execute_decode_slices(h); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + + memcpy(&tmp_ctx, h->slice_ctx, sizeof(tmp_ctx)); + memcpy(h->slice_ctx, sl, sizeof(tmp_ctx)); + memcpy(sl, &tmp_ctx, sizeof(tmp_ctx)); + sl = h->slice_ctx; + } + + if (h->field_started) + ff_h264_field_end(h, sl, 1); + + h->current_slice = 0; + if (!h->first_field) { + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + h->cur_pic_ptr = NULL; + } + } + + if (h->current_slice == 0) { + ret = h264_field_start(h, sl, nal); + if (ret < 0) + return ret; + h->field_started = 1; + } + } + + ret = h264_slice_init(h, sl, nal); + if (ret < 0) + return ret; + + if ((h->avctx->skip_frame < AVDISCARD_NONREF || nal->ref_idc) && + (h->avctx->skip_frame < AVDISCARD_BIDIR || + sl->slice_type_nos != AV_PICTURE_TYPE_B) && + (h->avctx->skip_frame < AVDISCARD_NONKEY || + h->cur_pic_ptr->f->key_frame) && + h->avctx->skip_frame < AVDISCARD_ALL) { + h->nb_slice_ctx_queued++; } return 0; } -int ff_h264_get_slice_type(const H264Context *h) +int ff_h264_get_slice_type(const H264SliceContext *sl) { - switch (h->slice_type) { + switch (sl->slice_type) { case AV_PICTURE_TYPE_P: return 0; case AV_PICTURE_TYPE_B: @@ -1835,7 +1939,8 @@ int ff_h264_get_slice_type(const H264Context *h) } } -static av_always_inline void fill_filter_caches_inter(H264Context *h, +static av_always_inline void fill_filter_caches_inter(const H264Context *h, + H264SliceContext *sl, int mb_type, int top_xy, int left_xy[LEFT_MBS], int top_type, @@ -1843,18 +1948,18 @@ static av_always_inline void fill_filter_caches_inter(H264Context *h, int mb_xy, int list) { int b_stride = h->b_stride; - int16_t(*mv_dst)[2] = &h->mv_cache[list][scan8[0]]; - int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; + int16_t(*mv_dst)[2] = &sl->mv_cache[list][scan8[0]]; + int8_t *ref_cache = &sl->ref_cache[list][scan8[0]]; if (IS_INTER(mb_type) || IS_DIRECT(mb_type)) { if (USES_LIST(top_type, list)) { const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; const int b8_xy = 4 * top_xy + 2; - int (*ref2frm)[64] = h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2); + const int *ref2frm = &h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][list][(MB_MBAFF(sl) ? 20 : 2)]; AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]); ref_cache[0 - 1 * 8] = - ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]]; + ref_cache[1 - 1 * 8] = ref2frm[h->cur_pic.ref_index[list][b8_xy + 0]]; ref_cache[2 - 1 * 8] = - ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]]; + ref_cache[3 - 1 * 8] = ref2frm[h->cur_pic.ref_index[list][b8_xy + 1]]; } else { AV_ZERO128(mv_dst - 1 * 8); AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); @@ -1864,15 +1969,15 @@ static av_always_inline void fill_filter_caches_inter(H264Context *h, if (USES_LIST(left_type[LTOP], list)) { const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; const int b8_xy = 4 * left_xy[LTOP] + 1; - int (*ref2frm)[64] = h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2); + const int *ref2frm = &h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][list][(MB_MBAFF(sl) ? 20 : 2)]; AV_COPY32(mv_dst - 1 + 0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]); AV_COPY32(mv_dst - 1 + 8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]); AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]); AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]); ref_cache[-1 + 0] = - ref_cache[-1 + 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; + ref_cache[-1 + 8] = ref2frm[h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; ref_cache[-1 + 16] = - ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; + ref_cache[-1 + 24] = ref2frm[h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; } else { AV_ZERO32(mv_dst - 1 + 0); AV_ZERO32(mv_dst - 1 + 8); @@ -1897,9 +2002,9 @@ static av_always_inline void fill_filter_caches_inter(H264Context *h, { int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy]; - int (*ref2frm)[64] = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2); - uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101; - uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101; + const int *ref2frm = &h->ref2frm[sl->slice_num & (MAX_SLICES - 1)][list][(MB_MBAFF(sl) ? 20 : 2)]; + uint32_t ref01 = (pack16to32(ref2frm[ref[0]], ref2frm[ref[1]]) & 0x00FF00FF) * 0x0101; + uint32_t ref23 = (pack16to32(ref2frm[ref[2]], ref2frm[ref[3]]) & 0x00FF00FF) * 0x0101; AV_WN32A(&ref_cache[0 * 8], ref01); AV_WN32A(&ref_cache[1 * 8], ref01); AV_WN32A(&ref_cache[2 * 8], ref23); @@ -1907,7 +2012,7 @@ static av_always_inline void fill_filter_caches_inter(H264Context *h, } { - int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * h->mb_x + 4 * h->mb_y * b_stride]; + int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * sl->mb_x + 4 * sl->mb_y * b_stride]; AV_COPY128(mv_dst + 8 * 0, mv_src + 0 * b_stride); AV_COPY128(mv_dst + 8 * 1, mv_src + 1 * b_stride); AV_COPY128(mv_dst + 8 * 2, mv_src + 2 * b_stride); @@ -1916,27 +2021,23 @@ static av_always_inline void fill_filter_caches_inter(H264Context *h, } /** - * * @return non zero if the loop filter can be skipped */ -static int fill_filter_caches(H264Context *h, int mb_type) +static int fill_filter_caches(const H264Context *h, H264SliceContext *sl, int mb_type) { - const int mb_xy = h->mb_xy; + const int mb_xy = sl->mb_xy; int top_xy, left_xy[LEFT_MBS]; int top_type, left_type[LEFT_MBS]; uint8_t *nnz; uint8_t *nnz_cache; - top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); - - /* Wow, what a mess, why didn't they simplify the interlacing & intra - * stuff, I can't imagine that these complex rules are worth it. */ + top_xy = mb_xy - (h->mb_stride << MB_FIELD(sl)); left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; if (FRAME_MBAFF(h)) { const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); const int curr_mb_field_flag = IS_INTERLACED(mb_type); - if (h->mb_y & 1) { + if (sl->mb_y & 1) { if (left_mb_field_flag != curr_mb_field_flag) left_xy[LTOP] -= h->mb_stride; } else { @@ -1948,14 +2049,14 @@ static int fill_filter_caches(H264Context *h, int mb_type) } } - h->top_mb_xy = top_xy; - h->left_mb_xy[LTOP] = left_xy[LTOP]; - h->left_mb_xy[LBOT] = left_xy[LBOT]; + sl->top_mb_xy = top_xy; + sl->left_mb_xy[LTOP] = left_xy[LTOP]; + sl->left_mb_xy[LBOT] = left_xy[LBOT]; { /* For sufficiently low qp, filtering wouldn't do anything. * This is a conservative estimate: could also check beta_offset * and more accurate chroma_qp. */ - int qp_thresh = h->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice + int qp_thresh = sl->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice int qp = h->cur_pic.qscale_table[mb_xy]; if (qp <= qp_thresh && (left_xy[LTOP] < 0 || @@ -1975,10 +2076,10 @@ static int fill_filter_caches(H264Context *h, int mb_type) top_type = h->cur_pic.mb_type[top_xy]; left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; - if (h->deblocking_filter == 2) { - if (h->slice_table[top_xy] != h->slice_num) + if (sl->deblocking_filter == 2) { + if (h->slice_table[top_xy] != sl->slice_num) top_type = 0; - if (h->slice_table[left_xy[LBOT]] != h->slice_num) + if (h->slice_table[left_xy[LBOT]] != sl->slice_num) left_type[LTOP] = left_type[LBOT] = 0; } else { if (h->slice_table[top_xy] == 0xFFFF) @@ -1986,26 +2087,26 @@ static int fill_filter_caches(H264Context *h, int mb_type) if (h->slice_table[left_xy[LBOT]] == 0xFFFF) left_type[LTOP] = left_type[LBOT] = 0; } - h->top_type = top_type; - h->left_type[LTOP] = left_type[LTOP]; - h->left_type[LBOT] = left_type[LBOT]; + sl->top_type = top_type; + sl->left_type[LTOP] = left_type[LTOP]; + sl->left_type[LBOT] = left_type[LBOT]; if (IS_INTRA(mb_type)) return 0; - fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + fill_filter_caches_inter(h, sl, mb_type, top_xy, left_xy, top_type, left_type, mb_xy, 0); - if (h->list_count == 2) - fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + if (sl->list_count == 2) + fill_filter_caches_inter(h, sl, mb_type, top_xy, left_xy, top_type, left_type, mb_xy, 1); nnz = h->non_zero_count[mb_xy]; - nnz_cache = h->non_zero_count_cache; + nnz_cache = sl->non_zero_count_cache; AV_COPY32(&nnz_cache[4 + 8 * 1], &nnz[0]); AV_COPY32(&nnz_cache[4 + 8 * 2], &nnz[4]); AV_COPY32(&nnz_cache[4 + 8 * 3], &nnz[8]); AV_COPY32(&nnz_cache[4 + 8 * 4], &nnz[12]); - h->cbp = h->cbp_table[mb_xy]; + sl->cbp = h->cbp_table[mb_xy]; if (top_type) { nnz = h->non_zero_count[top_xy]; @@ -2022,7 +2123,7 @@ static int fill_filter_caches(H264Context *h, int mb_type) /* CAVLC 8x8dct requires NNZ values for residual decoding that differ * from what the loop filter needs */ - if (!CABAC(h) && h->pps.transform_8x8_mode) { + if (!CABAC(h) && h->ps.pps->transform_8x8_mode) { if (IS_8x8DCT(top_type)) { nnz_cache[4 + 8 * 0] = nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12; @@ -2042,118 +2143,119 @@ static int fill_filter_caches(H264Context *h, int mb_type) nnz_cache[scan8[0]] = nnz_cache[scan8[1]] = nnz_cache[scan8[2]] = - nnz_cache[scan8[3]] = (h->cbp & 0x1000) >> 12; + nnz_cache[scan8[3]] = (sl->cbp & 0x1000) >> 12; nnz_cache[scan8[0 + 4]] = nnz_cache[scan8[1 + 4]] = nnz_cache[scan8[2 + 4]] = - nnz_cache[scan8[3 + 4]] = (h->cbp & 0x2000) >> 12; + nnz_cache[scan8[3 + 4]] = (sl->cbp & 0x2000) >> 12; nnz_cache[scan8[0 + 8]] = nnz_cache[scan8[1 + 8]] = nnz_cache[scan8[2 + 8]] = - nnz_cache[scan8[3 + 8]] = (h->cbp & 0x4000) >> 12; + nnz_cache[scan8[3 + 8]] = (sl->cbp & 0x4000) >> 12; nnz_cache[scan8[0 + 12]] = nnz_cache[scan8[1 + 12]] = nnz_cache[scan8[2 + 12]] = - nnz_cache[scan8[3 + 12]] = (h->cbp & 0x8000) >> 12; + nnz_cache[scan8[3 + 12]] = (sl->cbp & 0x8000) >> 12; } } return 0; } -static void loop_filter(H264Context *h, int start_x, int end_x) +static void loop_filter(const H264Context *h, H264SliceContext *sl, int start_x, int end_x) { uint8_t *dest_y, *dest_cb, *dest_cr; int linesize, uvlinesize, mb_x, mb_y; - const int end_mb_y = h->mb_y + FRAME_MBAFF(h); - const int old_slice_type = h->slice_type; + const int end_mb_y = sl->mb_y + FRAME_MBAFF(h); + const int old_slice_type = sl->slice_type; const int pixel_shift = h->pixel_shift; const int block_h = 16 >> h->chroma_y_shift; - if (h->deblocking_filter) { + if (h->postpone_filter) + return; + + if (sl->deblocking_filter) { for (mb_x = start_x; mb_x < end_x; mb_x++) for (mb_y = end_mb_y - FRAME_MBAFF(h); mb_y <= end_mb_y; mb_y++) { int mb_xy, mb_type; - mb_xy = h->mb_xy = mb_x + mb_y * h->mb_stride; - h->slice_num = h->slice_table[mb_xy]; + mb_xy = sl->mb_xy = mb_x + mb_y * h->mb_stride; mb_type = h->cur_pic.mb_type[mb_xy]; - h->list_count = h->list_counts[mb_xy]; if (FRAME_MBAFF(h)) - h->mb_mbaff = - h->mb_field_decoding_flag = !!IS_INTERLACED(mb_type); - - h->mb_x = mb_x; - h->mb_y = mb_y; - dest_y = h->cur_pic.f.data[0] + - ((mb_x << pixel_shift) + mb_y * h->linesize) * 16; - dest_cb = h->cur_pic.f.data[1] + + sl->mb_mbaff = + sl->mb_field_decoding_flag = !!IS_INTERLACED(mb_type); + + sl->mb_x = mb_x; + sl->mb_y = mb_y; + dest_y = h->cur_pic.f->data[0] + + ((mb_x << pixel_shift) + mb_y * sl->linesize) * 16; + dest_cb = h->cur_pic.f->data[1] + (mb_x << pixel_shift) * (8 << CHROMA444(h)) + - mb_y * h->uvlinesize * block_h; - dest_cr = h->cur_pic.f.data[2] + + mb_y * sl->uvlinesize * block_h; + dest_cr = h->cur_pic.f->data[2] + (mb_x << pixel_shift) * (8 << CHROMA444(h)) + - mb_y * h->uvlinesize * block_h; + mb_y * sl->uvlinesize * block_h; // FIXME simplify above - if (MB_FIELD(h)) { - linesize = h->mb_linesize = h->linesize * 2; - uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; + if (MB_FIELD(sl)) { + linesize = sl->mb_linesize = sl->linesize * 2; + uvlinesize = sl->mb_uvlinesize = sl->uvlinesize * 2; if (mb_y & 1) { // FIXME move out of this function? - dest_y -= h->linesize * 15; - dest_cb -= h->uvlinesize * (block_h - 1); - dest_cr -= h->uvlinesize * (block_h - 1); + dest_y -= sl->linesize * 15; + dest_cb -= sl->uvlinesize * (block_h - 1); + dest_cr -= sl->uvlinesize * (block_h - 1); } } else { - linesize = h->mb_linesize = h->linesize; - uvlinesize = h->mb_uvlinesize = h->uvlinesize; + linesize = sl->mb_linesize = sl->linesize; + uvlinesize = sl->mb_uvlinesize = sl->uvlinesize; } - backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + backup_mb_border(h, sl, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0); - if (fill_filter_caches(h, mb_type)) + if (fill_filter_caches(h, sl, mb_type)) continue; - h->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]); + sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, h->cur_pic.qscale_table[mb_xy]); + sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, h->cur_pic.qscale_table[mb_xy]); if (FRAME_MBAFF(h)) { - ff_h264_filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, + ff_h264_filter_mb(h, sl, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize); } else { - ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, + ff_h264_filter_mb_fast(h, sl, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize); } } } - h->slice_type = old_slice_type; - h->mb_x = end_x; - h->mb_y = end_mb_y - FRAME_MBAFF(h); - h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); - h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); + sl->slice_type = old_slice_type; + sl->mb_x = end_x; + sl->mb_y = end_mb_y - FRAME_MBAFF(h); + sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, sl->qscale); + sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, sl->qscale); } -static void predict_field_decoding_flag(H264Context *h) +static void predict_field_decoding_flag(const H264Context *h, H264SliceContext *sl) { - const int mb_xy = h->mb_x + h->mb_y * h->mb_stride; - int mb_type = (h->slice_table[mb_xy - 1] == h->slice_num) ? + const int mb_xy = sl->mb_x + sl->mb_y * h->mb_stride; + int mb_type = (h->slice_table[mb_xy - 1] == sl->slice_num) ? h->cur_pic.mb_type[mb_xy - 1] : - (h->slice_table[mb_xy - h->mb_stride] == h->slice_num) ? + (h->slice_table[mb_xy - h->mb_stride] == sl->slice_num) ? h->cur_pic.mb_type[mb_xy - h->mb_stride] : 0; - h->mb_mbaff = h->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0; + sl->mb_mbaff = sl->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0; } /** * Draw edges and report progress for the last MB row. */ -static void decode_finish_row(H264Context *h) +static void decode_finish_row(const H264Context *h, H264SliceContext *sl) { - int top = 16 * (h->mb_y >> FIELD_PICTURE(h)); + int top = 16 * (sl->mb_y >> FIELD_PICTURE(h)); int pic_height = 16 * h->mb_height >> FIELD_PICTURE(h); int height = 16 << FRAME_MBAFF(h); int deblock_border = (16 + 4) << FRAME_MBAFF(h); - if (h->deblocking_filter) { + if (sl->deblocking_filter) { if ((top + height) >= pic_height) height += deblock_border; top -= deblock_border; @@ -2168,7 +2270,7 @@ static void decode_finish_row(H264Context *h) top = 0; } - ff_h264_draw_horiz_band(h, top, height); + ff_h264_draw_horiz_band(h, sl, top, height); if (h->droppable) return; @@ -2177,215 +2279,284 @@ static void decode_finish_row(H264Context *h) h->picture_structure == PICT_BOTTOM_FIELD); } -static void er_add_slice(H264Context *h, int startx, int starty, +static void er_add_slice(H264SliceContext *sl, + int startx, int starty, int endx, int endy, int status) { #if CONFIG_ERROR_RESILIENCE - ERContext *er = &h->er; + ERContext *er = &sl->er; + + if (!sl->h264->enable_er) + return; - er->ref_count = h->ref_count[0]; + er->ref_count = sl->ref_count[0]; ff_er_add_slice(er, startx, starty, endx, endy, status); #endif } static int decode_slice(struct AVCodecContext *avctx, void *arg) { - H264Context *h = *(void **)arg; - int lf_x_start = h->mb_x; + H264SliceContext *sl = arg; + const H264Context *h = sl->h264; + int lf_x_start = sl->mb_x; + int orig_deblock = sl->deblocking_filter; + int ret; + + sl->linesize = h->cur_pic_ptr->f->linesize[0]; + sl->uvlinesize = h->cur_pic_ptr->f->linesize[1]; + + ret = alloc_scratch_buffers(sl, sl->linesize); + if (ret < 0) + return ret; + + sl->mb_skip_run = -1; - h->mb_skip_run = -1; + if (h->postpone_filter) + sl->deblocking_filter = 0; - h->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || - avctx->codec_id != AV_CODEC_ID_H264 || - (CONFIG_GRAY && (h->flags & CODEC_FLAG_GRAY)); + sl->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || + (CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY)); - if (h->pps.cabac) { + if (h->ps.pps->cabac) { /* realign */ - align_get_bits(&h->gb); + align_get_bits(&sl->gb); /* init cabac */ - ff_init_cabac_decoder(&h->cabac, - h->gb.buffer + get_bits_count(&h->gb) / 8, - (get_bits_left(&h->gb) + 7) / 8); + ff_init_cabac_decoder(&sl->cabac, + sl->gb.buffer + get_bits_count(&sl->gb) / 8, + (get_bits_left(&sl->gb) + 7) / 8); - ff_h264_init_cabac_states(h); + ff_h264_init_cabac_states(h, sl); for (;;) { // START_TIMER - int ret = ff_h264_decode_mb_cabac(h); - int eos; + int ret, eos; + + if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) { + av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n", + sl->next_slice_idx); + return AVERROR_INVALIDDATA; + } + + ret = ff_h264_decode_mb_cabac(h, sl); // STOP_TIMER("decode_mb_cabac") if (ret >= 0) - ff_h264_hl_decode_mb(h); + ff_h264_hl_decode_mb(h, sl); // FIXME optimal? or let mb_decode decode 16x32 ? if (ret >= 0 && FRAME_MBAFF(h)) { - h->mb_y++; + sl->mb_y++; - ret = ff_h264_decode_mb_cabac(h); + ret = ff_h264_decode_mb_cabac(h, sl); if (ret >= 0) - ff_h264_hl_decode_mb(h); - h->mb_y--; + ff_h264_hl_decode_mb(h, sl); + sl->mb_y--; } - eos = get_cabac_terminate(&h->cabac); + eos = get_cabac_terminate(&sl->cabac); if ((h->workaround_bugs & FF_BUG_TRUNCATED) && - h->cabac.bytestream > h->cabac.bytestream_end + 2) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, - h->mb_y, ER_MB_END); - if (h->mb_x >= lf_x_start) - loop_filter(h, lf_x_start, h->mb_x + 1); - return 0; + sl->cabac.bytestream > sl->cabac.bytestream_end + 2) { + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x - 1, + sl->mb_y, ER_MB_END); + if (sl->mb_x >= lf_x_start) + loop_filter(h, sl, lf_x_start, sl->mb_x + 1); + goto finish; } - if (ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 2) { + if (ret < 0 || sl->cabac.bytestream > sl->cabac.bytestream_end + 2) { av_log(h->avctx, AV_LOG_ERROR, "error while decoding MB %d %d, bytestream %td\n", - h->mb_x, h->mb_y, - h->cabac.bytestream_end - h->cabac.bytestream); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); + sl->mb_x, sl->mb_y, + sl->cabac.bytestream_end - sl->cabac.bytestream); + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x, + sl->mb_y, ER_MB_ERROR); return AVERROR_INVALIDDATA; } - if (++h->mb_x >= h->mb_width) { - loop_filter(h, lf_x_start, h->mb_x); - h->mb_x = lf_x_start = 0; - decode_finish_row(h); - ++h->mb_y; + if (++sl->mb_x >= h->mb_width) { + loop_filter(h, sl, lf_x_start, sl->mb_x); + sl->mb_x = lf_x_start = 0; + decode_finish_row(h, sl); + ++sl->mb_y; if (FIELD_OR_MBAFF_PICTURE(h)) { - ++h->mb_y; - if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) - predict_field_decoding_flag(h); + ++sl->mb_y; + if (FRAME_MBAFF(h) && sl->mb_y < h->mb_height) + predict_field_decoding_flag(h, sl); } } - if (eos || h->mb_y >= h->mb_height) { - tprintf(h->avctx, "slice end %d %d\n", - get_bits_count(&h->gb), h->gb.size_in_bits); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, - h->mb_y, ER_MB_END); - if (h->mb_x > lf_x_start) - loop_filter(h, lf_x_start, h->mb_x); - return 0; + if (eos || sl->mb_y >= h->mb_height) { + ff_tlog(h->avctx, "slice end %d %d\n", + get_bits_count(&sl->gb), sl->gb.size_in_bits); + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x - 1, + sl->mb_y, ER_MB_END); + if (sl->mb_x > lf_x_start) + loop_filter(h, sl, lf_x_start, sl->mb_x); + goto finish; } } } else { for (;;) { - int ret = ff_h264_decode_mb_cavlc(h); + int ret; + + if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) { + av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n", + sl->next_slice_idx); + return AVERROR_INVALIDDATA; + } + + ret = ff_h264_decode_mb_cavlc(h, sl); if (ret >= 0) - ff_h264_hl_decode_mb(h); + ff_h264_hl_decode_mb(h, sl); // FIXME optimal? or let mb_decode decode 16x32 ? if (ret >= 0 && FRAME_MBAFF(h)) { - h->mb_y++; - ret = ff_h264_decode_mb_cavlc(h); + sl->mb_y++; + ret = ff_h264_decode_mb_cavlc(h, sl); if (ret >= 0) - ff_h264_hl_decode_mb(h); - h->mb_y--; + ff_h264_hl_decode_mb(h, sl); + sl->mb_y--; } if (ret < 0) { av_log(h->avctx, AV_LOG_ERROR, - "error while decoding MB %d %d\n", h->mb_x, h->mb_y); - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); + "error while decoding MB %d %d\n", sl->mb_x, sl->mb_y); + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x, + sl->mb_y, ER_MB_ERROR); return ret; } - if (++h->mb_x >= h->mb_width) { - loop_filter(h, lf_x_start, h->mb_x); - h->mb_x = lf_x_start = 0; - decode_finish_row(h); - ++h->mb_y; + if (++sl->mb_x >= h->mb_width) { + loop_filter(h, sl, lf_x_start, sl->mb_x); + sl->mb_x = lf_x_start = 0; + decode_finish_row(h, sl); + ++sl->mb_y; if (FIELD_OR_MBAFF_PICTURE(h)) { - ++h->mb_y; - if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) - predict_field_decoding_flag(h); + ++sl->mb_y; + if (FRAME_MBAFF(h) && sl->mb_y < h->mb_height) + predict_field_decoding_flag(h, sl); } - if (h->mb_y >= h->mb_height) { - tprintf(h->avctx, "slice end %d %d\n", - get_bits_count(&h->gb), h->gb.size_in_bits); + if (sl->mb_y >= h->mb_height) { + ff_tlog(h->avctx, "slice end %d %d\n", + get_bits_count(&sl->gb), sl->gb.size_in_bits); - if (get_bits_left(&h->gb) == 0) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x - 1, h->mb_y, ER_MB_END); + if (get_bits_left(&sl->gb) == 0) { + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, + sl->mb_x - 1, sl->mb_y, ER_MB_END); - return 0; + goto finish; } else { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x - 1, h->mb_y, ER_MB_END); + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, + sl->mb_x - 1, sl->mb_y, ER_MB_END); return AVERROR_INVALIDDATA; } } } - if (get_bits_left(&h->gb) <= 0 && h->mb_skip_run <= 0) { - tprintf(h->avctx, "slice end %d %d\n", - get_bits_count(&h->gb), h->gb.size_in_bits); + if (get_bits_left(&sl->gb) <= 0 && sl->mb_skip_run <= 0) { + ff_tlog(h->avctx, "slice end %d %d\n", + get_bits_count(&sl->gb), sl->gb.size_in_bits); - if (get_bits_left(&h->gb) == 0) { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, - h->mb_x - 1, h->mb_y, ER_MB_END); - if (h->mb_x > lf_x_start) - loop_filter(h, lf_x_start, h->mb_x); + if (get_bits_left(&sl->gb) == 0) { + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, + sl->mb_x - 1, sl->mb_y, ER_MB_END); + if (sl->mb_x > lf_x_start) + loop_filter(h, sl, lf_x_start, sl->mb_x); - return 0; + goto finish; } else { - er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, - h->mb_y, ER_MB_ERROR); + er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x, + sl->mb_y, ER_MB_ERROR); return AVERROR_INVALIDDATA; } } } } + +finish: + sl->deblocking_filter = orig_deblock; + return 0; } /** * Call decode_slice() for each context. * * @param h h264 master context - * @param context_count number of contexts to execute */ -int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count) +int ff_h264_execute_decode_slices(H264Context *h) { AVCodecContext *const avctx = h->avctx; - H264Context *hx; - int i; - - if (h->mb_y >= h->mb_height) { - av_log(h->avctx, AV_LOG_ERROR, - "Input contains more MB rows than the frame height.\n"); - return AVERROR_INVALIDDATA; - } + H264SliceContext *sl; + int context_count = h->nb_slice_ctx_queued; + int ret = 0; + int i, j; - if (h->avctx->hwaccel) + if (h->avctx->hwaccel || context_count < 1) return 0; if (context_count == 1) { - return decode_slice(avctx, &h); + + h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height; + h->postpone_filter = 0; + + ret = decode_slice(avctx, &h->slice_ctx[0]); + h->mb_y = h->slice_ctx[0].mb_y; + if (ret < 0) + goto finish; } else { - for (i = 1; i < context_count; i++) { - hx = h->thread_context[i]; - hx->er.error_count = 0; + for (i = 0; i < context_count; i++) { + int next_slice_idx = h->mb_width * h->mb_height; + int slice_idx; + + sl = &h->slice_ctx[i]; + sl->er.error_count = 0; + + /* make sure none of those slices overlap */ + slice_idx = sl->mb_y * h->mb_width + sl->mb_x; + for (j = 0; j < context_count; j++) { + H264SliceContext *sl2 = &h->slice_ctx[j]; + int slice_idx2 = sl2->mb_y * h->mb_width + sl2->mb_x; + + if (i == j || slice_idx2 < slice_idx) + continue; + next_slice_idx = FFMIN(next_slice_idx, slice_idx2); + } + sl->next_slice_idx = next_slice_idx; } - avctx->execute(avctx, decode_slice, h->thread_context, - NULL, context_count, sizeof(void *)); + avctx->execute(avctx, decode_slice, h->slice_ctx, + NULL, context_count, sizeof(h->slice_ctx[0])); /* pull back stuff from slices to master context */ - hx = h->thread_context[context_count - 1]; - h->mb_x = hx->mb_x; - h->mb_y = hx->mb_y; - h->droppable = hx->droppable; - h->picture_structure = hx->picture_structure; + sl = &h->slice_ctx[context_count - 1]; + h->mb_y = sl->mb_y; for (i = 1; i < context_count; i++) - h->er.error_count += h->thread_context[i]->er.error_count; + h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count; + + if (h->postpone_filter) { + h->postpone_filter = 0; + + for (i = 0; i < context_count; i++) { + int y_end, x_end; + + sl = &h->slice_ctx[i]; + y_end = FFMIN(sl->mb_y + 1, h->mb_height); + x_end = (sl->mb_y >= h->mb_height) ? h->mb_width : sl->mb_x; + + for (j = sl->resync_mb_y; j < y_end; j += 1 + FIELD_OR_MBAFF_PICTURE(h)) { + sl->mb_y = j; + loop_filter(h, sl, j > sl->resync_mb_y ? 0 : sl->resync_mb_x, + j == y_end - 1 ? x_end : h->mb_width); + } + } + } } - return 0; +finish: + h->nb_slice_ctx_queued = 0; + return ret; } diff --git a/libavcodec/h264addpx_template.c b/libavcodec/h264addpx_template.c index cdbfc67..e3adfe2 100644 --- a/libavcodec/h264addpx_template.c +++ b/libavcodec/h264addpx_template.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 DSP functions. + * H.264 / AVC / MPEG-4 part10 DSP functions. * @author Michael Niedermayer */ diff --git a/libavcodec/h264data.c b/libavcodec/h264data.c new file mode 100644 index 0000000..a2a4a47 --- /dev/null +++ b/libavcodec/h264data.c @@ -0,0 +1,206 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @brief + * H.264 / AVC / MPEG-4 part10 codec data table + * @author Michael Niedermayer + */ + +#include + +#include "libavutil/avutil.h" + +#include "avcodec.h" +#include "h264dec.h" +#include "h264data.h" + +const uint8_t ff_h264_golomb_to_pict_type[5] = { + AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI +}; + +const uint8_t ff_h264_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 +}; + +const uint8_t ff_h264_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 +}; + +const uint8_t ff_h264_chroma_dc_scan[4] = { + (0 + 0 * 2) * 16, (1 + 0 * 2) * 16, + (0 + 1 * 2) * 16, (1 + 1 * 2) * 16, +}; + +const uint8_t ff_h264_chroma422_dc_scan[8] = { + (0 + 0 * 2) * 16, (0 + 1 * 2) * 16, + (1 + 0 * 2) * 16, (0 + 2 * 2) * 16, + (0 + 3 * 2) * 16, (1 + 1 * 2) * 16, + (1 + 2 * 2) * 16, (1 + 3 * 2) * 16, +}; + +const IMbInfo ff_h264_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 }, +}; + +const PMbInfo ff_h264_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 }, +}; + +const PMbInfo ff_h264_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 }, +}; + +const PMbInfo ff_h264_b_mb_type_info[23] = { + { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, }, +}; + +const PMbInfo ff_h264_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, }, +}; + +const uint8_t ff_h264_dequant4_coeff_init[6][3] = { + { 10, 13, 16 }, + { 11, 14, 18 }, + { 13, 16, 20 }, + { 14, 18, 23 }, + { 16, 20, 25 }, + { 18, 23, 29 }, +}; + +const uint8_t ff_h264_dequant8_coeff_init_scan[16] = { + 0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1 +}; + +const uint8_t ff_h264_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 }, +}; + +const uint8_t ff_h264_quant_rem6[QP_MAX_NUM + 1] = { + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, +}; + +const uint8_t ff_h264_quant_div6[QP_MAX_NUM + 1] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, +}; + +#define QP(qP, depth) ((qP) + 6 * ((depth) - 8)) + +#define CHROMA_QP_TABLE_END(d) \ + QP(0, d), QP(1, d), QP(2, d), QP(3, d), QP(4, d), QP(5, d), \ + QP(6, d), QP(7, d), QP(8, d), QP(9, d), QP(10, d), QP(11, d), \ + QP(12, d), QP(13, d), QP(14, d), QP(15, d), QP(16, d), QP(17, d), \ + QP(18, d), QP(19, d), QP(20, d), QP(21, d), QP(22, d), QP(23, d), \ + QP(24, d), QP(25, d), QP(26, d), QP(27, d), QP(28, d), QP(29, d), \ + QP(29, d), QP(30, d), QP(31, d), QP(32, d), QP(32, d), QP(33, d), \ + QP(34, d), QP(34, d), QP(35, d), QP(35, d), QP(36, d), QP(36, d), \ + QP(37, d), QP(37, d), QP(37, d), QP(38, d), QP(38, d), QP(38, d), \ + QP(39, d), QP(39, d), QP(39, d), QP(39, d) + +const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1] = { + { CHROMA_QP_TABLE_END(8) }, + { 0, 1, 2, 3, 4, 5, + CHROMA_QP_TABLE_END(9) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + CHROMA_QP_TABLE_END(10) }, +}; diff --git a/libavcodec/h264data.h b/libavcodec/h264data.h index 6b40b39..f1284e6 100644 --- a/libavcodec/h264data.h +++ b/libavcodec/h264data.h @@ -1,7 +1,4 @@ /* - * H26L/H264/AVC/JVT/14496-10/... encoder/decoder - * Copyright (c) 2003 Michael Niedermayer - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -19,56 +16,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file - * @brief - * H264 / AVC / MPEG4 part10 codec data table - * @author Michael Niedermayer - */ - #ifndef AVCODEC_H264DATA_H #define AVCODEC_H264DATA_H #include -#include "libavutil/rational.h" -#include "h264.h" - -static const uint8_t golomb_to_pict_type[5] = { - AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I, - AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI -}; +#include "h264dec.h" -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 -}; +extern const uint8_t ff_h264_golomb_to_pict_type[5]; +extern const uint8_t ff_h264_golomb_to_intra4x4_cbp[48]; +extern const uint8_t ff_h264_golomb_to_inter_cbp[48]; -static const uint8_t golomb_to_inter_cbp[48] = { - 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, - 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46, - 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41 -}; - -static const uint8_t zigzag_scan[16] = { - 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 chroma_dc_scan[4] = { - (0 + 0 * 2) * 16, (1 + 0 * 2) * 16, - (0 + 1 * 2) * 16, (1 + 1 * 2) * 16, -}; - -static const uint8_t chroma422_dc_scan[8] = { - (0 + 0 * 2) * 16, (0 + 1 * 2) * 16, - (1 + 0 * 2) * 16, (0 + 2 * 2) * 16, - (0 + 3 * 2) * 16, (1 + 1 * 2) * 16, - (1 + 2 * 2) * 16, (1 + 3 * 2) * 16, -}; +extern const uint8_t ff_h264_chroma_dc_scan[4]; +extern const uint8_t ff_h264_chroma422_dc_scan[8]; typedef struct IMbInfo { uint16_t type; @@ -76,95 +36,24 @@ typedef struct IMbInfo { 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 }, -}; +extern const IMbInfo ff_h264_i_mb_type_info[26]; 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 }, -}; +extern const PMbInfo ff_h264_p_mb_type_info[5]; +extern const PMbInfo ff_h264_p_sub_mb_type_info[4]; +extern const PMbInfo ff_h264_b_mb_type_info[23]; +extern const PMbInfo ff_h264_b_sub_mb_type_info[13]; -static const PMbInfo b_mb_type_info[23] = { - { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, 1, }, - { MB_TYPE_16x16 | MB_TYPE_P0L0, 1, }, - { MB_TYPE_16x16 | MB_TYPE_P0L1, 1, }, - { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1, 1, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, - { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, }, -}; +extern const uint8_t ff_h264_dequant4_coeff_init[6][3]; +extern const uint8_t ff_h264_dequant8_coeff_init_scan[16]; +extern const uint8_t ff_h264_dequant8_coeff_init[6][6]; +extern const uint8_t ff_h264_quant_rem6[QP_MAX_NUM + 1]; +extern const uint8_t ff_h264_quant_div6[QP_MAX_NUM + 1]; -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, }, -}; +extern const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1]; #endif /* AVCODEC_H264DATA_H */ diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c new file mode 100644 index 0000000..d918fb9 --- /dev/null +++ b/libavcodec/h264dec.c @@ -0,0 +1,811 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 / AVC / MPEG-4 part10 codec. + * @author Michael Niedermayer + */ + +#include "libavutil/display.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/stereo3d.h" +#include "libavutil/timer.h" +#include "internal.h" +#include "bytestream.h" +#include "cabac.h" +#include "cabac_functions.h" +#include "error_resilience.h" +#include "avcodec.h" +#include "h264.h" +#include "h264dec.h" +#include "h2645_parse.h" +#include "h264data.h" +#include "h264chroma.h" +#include "h264_mvpred.h" +#include "h264_ps.h" +#include "golomb.h" +#include "mathops.h" +#include "me_cmp.h" +#include "mpegutils.h" +#include "profiles.h" +#include "rectangle.h" +#include "thread.h" + +#include + +const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 }; + +static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], + int mb_x, int mb_y, int mb_intra, int mb_skipped) +{ + H264Context *h = opaque; + H264SliceContext *sl = &h->slice_ctx[0]; + + sl->mb_x = mb_x; + sl->mb_y = mb_y; + sl->mb_xy = mb_x + mb_y * h->mb_stride; + memset(sl->non_zero_count_cache, 0, sizeof(sl->non_zero_count_cache)); + assert(ref >= 0); + /* FIXME: It is possible albeit uncommon that slice references + * differ between slices. We take the easy approach and ignore + * it for now. If this turns out to have any relevance in + * practice then correct remapping should be added. */ + if (ref >= sl->ref_count[0]) + ref = 0; + fill_rectangle(&h->cur_pic.ref_index[0][4 * sl->mb_xy], + 2, 2, 2, ref, 1); + fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(sl->mv_cache[0][scan8[0]], 4, 4, 8, + pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4); + assert(!FRAME_MBAFF(h)); + ff_h264_hl_decode_mb(h, &h->slice_ctx[0]); +} + +void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, + int y, int height) +{ + AVCodecContext *avctx = h->avctx; + const AVFrame *src = h->cur_pic.f; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int vshift = desc->log2_chroma_h; + const int field_pic = h->picture_structure != PICT_FRAME; + if (field_pic) { + height <<= 1; + y <<= 1; + } + + height = FFMIN(height, avctx->height - y); + + if (field_pic && h->first_field && !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) + return; + + if (avctx->draw_horiz_band) { + int offset[AV_NUM_DATA_POINTERS]; + int i; + + offset[0] = y * src->linesize[0]; + offset[1] = + offset[2] = (y >> vshift) * src->linesize[1]; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + + emms_c(); + + avctx->draw_horiz_band(avctx, src, offset, + y, h->picture_structure, height); + } +} + +void ff_h264_free_tables(H264Context *h) +{ + int i; + + av_freep(&h->intra4x4_pred_mode); + av_freep(&h->chroma_pred_mode_table); + av_freep(&h->cbp_table); + av_freep(&h->mvd_table[0]); + av_freep(&h->mvd_table[1]); + av_freep(&h->direct_table); + av_freep(&h->non_zero_count); + av_freep(&h->slice_table_base); + h->slice_table = NULL; + av_freep(&h->list_counts); + + av_freep(&h->mb2b_xy); + av_freep(&h->mb2br_xy); + + av_buffer_pool_uninit(&h->qscale_table_pool); + av_buffer_pool_uninit(&h->mb_type_pool); + av_buffer_pool_uninit(&h->motion_val_pool); + av_buffer_pool_uninit(&h->ref_index_pool); + + for (i = 0; i < h->nb_slice_ctx; i++) { + H264SliceContext *sl = &h->slice_ctx[i]; + + av_freep(&sl->dc_val_base); + av_freep(&sl->er.mb_index2xy); + av_freep(&sl->er.error_status_table); + av_freep(&sl->er.er_temp_buffer); + + av_freep(&sl->bipred_scratchpad); + av_freep(&sl->edge_emu_buffer); + av_freep(&sl->top_borders[0]); + av_freep(&sl->top_borders[1]); + + sl->bipred_scratchpad_allocated = 0; + sl->edge_emu_buffer_allocated = 0; + sl->top_borders_allocated[0] = 0; + sl->top_borders_allocated[1] = 0; + } +} + +int ff_h264_alloc_tables(H264Context *h) +{ + const int big_mb_num = h->mb_stride * (h->mb_height + 1); + const int row_mb_num = h->mb_stride * 2 * h->nb_slice_ctx; + int x, y; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->intra4x4_pred_mode, + row_mb_num * 8 * sizeof(uint8_t), fail) + h->slice_ctx[0].intra4x4_pred_mode = h->intra4x4_pred_mode; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->non_zero_count, + big_mb_num * 48 * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->slice_table_base, + (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->cbp_table, + big_mb_num * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->chroma_pred_mode_table, + big_mb_num * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[0], + 16 * row_mb_num * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[1], + 16 * row_mb_num * sizeof(uint8_t), fail); + h->slice_ctx[0].mvd_table[0] = h->mvd_table[0]; + h->slice_ctx[0].mvd_table[1] = h->mvd_table[1]; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->direct_table, + 4 * big_mb_num * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->list_counts, + big_mb_num * sizeof(uint8_t), fail) + + memset(h->slice_table_base, -1, + (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base)); + h->slice_table = h->slice_table_base + h->mb_stride * 2 + 1; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2b_xy, + big_mb_num * sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2br_xy, + big_mb_num * sizeof(uint32_t), fail); + for (y = 0; y < h->mb_height; y++) + for (x = 0; x < h->mb_width; x++) { + const int mb_xy = x + y * h->mb_stride; + const int b_xy = 4 * x + 4 * y * h->b_stride; + + h->mb2b_xy[mb_xy] = b_xy; + h->mb2br_xy[mb_xy] = 8 * (FMO ? mb_xy : (mb_xy % (2 * h->mb_stride))); + } + + return 0; + +fail: + ff_h264_free_tables(h); + return AVERROR(ENOMEM); +} + +/** + * Init context + * Allocate buffers which are not shared amongst multiple threads. + */ +int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) +{ + ERContext *er = &sl->er; + int mb_array_size = h->mb_height * h->mb_stride; + int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); + int c_size = h->mb_stride * (h->mb_height + 1); + int yc_size = y_size + 2 * c_size; + int x, y, i; + + sl->ref_cache[0][scan8[5] + 1] = + sl->ref_cache[0][scan8[7] + 1] = + sl->ref_cache[0][scan8[13] + 1] = + sl->ref_cache[1][scan8[5] + 1] = + sl->ref_cache[1][scan8[7] + 1] = + sl->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; + + if (CONFIG_ERROR_RESILIENCE) { + /* init ER */ + er->avctx = h->avctx; + er->decode_mb = h264_er_decode_mb; + er->opaque = h; + er->quarter_sample = 1; + + er->mb_num = h->mb_num; + er->mb_width = h->mb_width; + er->mb_height = h->mb_height; + er->mb_stride = h->mb_stride; + er->b8_stride = h->mb_width * 2 + 1; + + // error resilience code looks cleaner with this + FF_ALLOCZ_OR_GOTO(h->avctx, er->mb_index2xy, + (h->mb_num + 1) * sizeof(int), fail); + + for (y = 0; y < h->mb_height; y++) + for (x = 0; x < h->mb_width; x++) + er->mb_index2xy[x + y * h->mb_width] = x + y * h->mb_stride; + + er->mb_index2xy[h->mb_height * h->mb_width] = (h->mb_height - 1) * + h->mb_stride + h->mb_width; + + FF_ALLOCZ_OR_GOTO(h->avctx, er->error_status_table, + mb_array_size * sizeof(uint8_t), fail); + + FF_ALLOC_OR_GOTO(h->avctx, er->er_temp_buffer, + h->mb_height * h->mb_stride, fail); + + FF_ALLOCZ_OR_GOTO(h->avctx, sl->dc_val_base, + yc_size * sizeof(int16_t), fail); + er->dc_val[0] = sl->dc_val_base + h->mb_width * 2 + 2; + er->dc_val[1] = sl->dc_val_base + y_size + h->mb_stride + 1; + er->dc_val[2] = er->dc_val[1] + c_size; + for (i = 0; i < yc_size; i++) + sl->dc_val_base[i] = 1024; + } + + return 0; + +fail: + return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us +} + +static int h264_init_context(AVCodecContext *avctx, H264Context *h) +{ + int i; + + h->avctx = avctx; + + h->picture_structure = PICT_FRAME; + h->workaround_bugs = avctx->workaround_bugs; + h->flags = avctx->flags; + h->poc.prev_poc_msb = 1 << 16; + h->recovery_frame = -1; + h->frame_recovered = 0; + + h->next_outputed_poc = INT_MIN; + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; + + ff_h264_sei_uninit(&h->sei); + + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + + h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? avctx->thread_count : 1; + h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx)); + if (!h->slice_ctx) { + h->nb_slice_ctx = 0; + return AVERROR(ENOMEM); + } + + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { + h->DPB[i].f = av_frame_alloc(); + if (!h->DPB[i].f) + return AVERROR(ENOMEM); + } + + h->cur_pic.f = av_frame_alloc(); + if (!h->cur_pic.f) + return AVERROR(ENOMEM); + + h->output_frame = av_frame_alloc(); + if (!h->output_frame) + return AVERROR(ENOMEM); + + for (i = 0; i < h->nb_slice_ctx; i++) + h->slice_ctx[i].h264 = h; + + return 0; +} + +static av_cold int h264_decode_end(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int i; + + ff_h264_free_tables(h); + + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { + ff_h264_unref_picture(h, &h->DPB[i]); + av_frame_free(&h->DPB[i].f); + } + + h->cur_pic_ptr = NULL; + + av_freep(&h->slice_ctx); + h->nb_slice_ctx = 0; + + for (i = 0; i < MAX_SPS_COUNT; i++) + av_buffer_unref(&h->ps.sps_list[i]); + + for (i = 0; i < MAX_PPS_COUNT; i++) + av_buffer_unref(&h->ps.pps_list[i]); + + ff_h2645_packet_uninit(&h->pkt); + + ff_h264_unref_picture(h, &h->cur_pic); + av_frame_free(&h->cur_pic.f); + av_frame_free(&h->output_frame); + + return 0; +} + +static AVOnce h264_vlc_init = AV_ONCE_INIT; + +av_cold int ff_h264_decode_init(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int ret; + + ret = h264_init_context(avctx, h); + if (ret < 0) + return ret; + + ret = ff_thread_once(&h264_vlc_init, ff_h264_decode_init_vlc); + if (ret != 0) { + av_log(avctx, AV_LOG_ERROR, "pthread_once has failed."); + return AVERROR_UNKNOWN; + } + + if (avctx->ticks_per_frame == 1) + h->avctx->framerate.num *= 2; + avctx->ticks_per_frame = 2; + + if (avctx->extradata_size > 0 && avctx->extradata) { + ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size, + &h->ps, &h->is_avc, &h->nal_length_size, + avctx->err_recognition, avctx); + if (ret < 0) { + h264_decode_end(avctx); + return ret; + } + } + + if (h->ps.sps && h->ps.sps->bitstream_restriction_flag && + h->avctx->has_b_frames < h->ps.sps->num_reorder_frames) { + h->avctx->has_b_frames = h->ps.sps->num_reorder_frames; + } + + avctx->internal->allocate_progress = 1; + + if (h->enable_er) { + av_log(avctx, AV_LOG_WARNING, + "Error resilience is enabled. It is unsafe and unsupported and may crash. " + "Use it at your own risk\n"); + } + + return 0; +} + +static int decode_init_thread_copy(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int ret; + + if (!avctx->internal->is_copy) + return 0; + + memset(h, 0, sizeof(*h)); + + ret = h264_init_context(avctx, h); + if (ret < 0) + return ret; + + h->context_initialized = 0; + + return 0; +} + +/** + * instantaneous decoder refresh. + */ +static void idr(H264Context *h) +{ + ff_h264_remove_all_refs(h); + h->poc.prev_frame_num = + h->poc.prev_frame_num_offset = + h->poc.prev_poc_msb = + h->poc.prev_poc_lsb = 0; +} + +/* forget old pics after a seek */ +void ff_h264_flush_change(H264Context *h) +{ + int i; + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; + h->next_outputed_poc = INT_MIN; + h->prev_interlaced_frame = 1; + idr(h); + if (h->cur_pic_ptr) + h->cur_pic_ptr->reference = 0; + h->first_field = 0; + h->recovery_frame = -1; + h->frame_recovered = 0; +} + +/* forget old pics after a seek */ +static void flush_dpb(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int i; + + memset(h->delayed_pic, 0, sizeof(h->delayed_pic)); + + ff_h264_flush_change(h); + ff_h264_sei_uninit(&h->sei); + + for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) + ff_h264_unref_picture(h, &h->DPB[i]); + h->cur_pic_ptr = NULL; + ff_h264_unref_picture(h, &h->cur_pic); + + h->mb_y = 0; + + ff_h264_free_tables(h); + h->context_initialized = 0; +} + +static int get_last_needed_nal(H264Context *h) +{ + int nals_needed = 0; + int i, ret; + + for (i = 0; i < h->pkt.nb_nals; i++) { + H2645NAL *nal = &h->pkt.nals[i]; + GetBitContext gb; + + /* packets can sometimes contain multiple PPS/SPS, + * e.g. two PAFF field pictures in one packet, or a demuxer + * which splits NALs strangely if so, when frame threading we + * can't start the next thread until we've read all of them */ + switch (nal->type) { + case H264_NAL_SPS: + case H264_NAL_PPS: + nals_needed = i; + break; + case H264_NAL_DPA: + case H264_NAL_IDR_SLICE: + case H264_NAL_SLICE: + ret = init_get_bits8(&gb, nal->data + 1, nal->size - 1); + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, "Invalid zero-sized VCL NAL unit\n"); + if (h->avctx->err_recognition & AV_EF_EXPLODE) + return ret; + + break; + } + if (!get_ue_golomb(&gb)) + nals_needed = i; + } + } + + return nals_needed; +} + +static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) +{ + AVCodecContext *const avctx = h->avctx; + int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts + int i, ret = 0; + + if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) { + h->current_slice = 0; + h->field_started = 0; + if (!h->first_field) + h->cur_pic_ptr = NULL; + ff_h264_sei_uninit(&h->sei); + } + + ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc, + h->nal_length_size, avctx->codec_id); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error splitting the input into NAL units.\n"); + + /* There are samples in the wild with mp4-style extradata, but Annex B + * data in the packets. If we fail parsing the packet as mp4, try it again + * as Annex B. */ + if (h->is_avc && !(avctx->err_recognition & AV_EF_EXPLODE)) { + int err = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, 0, 0, + avctx->codec_id); + if (err >= 0) { + av_log(avctx, AV_LOG_WARNING, + "The stream seems to contain AVCC extradata with Annex B " + "formatted data, which is invalid."); + h->is_avc = 0; + ret = 0; + } + } + + if (ret < 0) + return ret; + } + + if (avctx->active_thread_type & FF_THREAD_FRAME) + nals_needed = get_last_needed_nal(h); + + for (i = 0; i < h->pkt.nb_nals; i++) { + H2645NAL *nal = &h->pkt.nals[i]; + int max_slice_ctx, err; + + if (avctx->skip_frame >= AVDISCARD_NONREF && + nal->ref_idc == 0 && nal->type != H264_NAL_SEI) + continue; + + // FIXME these should stop being context-global variables + h->nal_ref_idc = nal->ref_idc; + h->nal_unit_type = nal->type; + + err = 0; + switch (nal->type) { + case H264_NAL_IDR_SLICE: + idr(h); // FIXME ensure we don't lose some frames if there is reordering + case H264_NAL_SLICE: + if ((err = ff_h264_queue_decode_slice(h, nal))) + break; + + if (avctx->active_thread_type & FF_THREAD_FRAME && !h->avctx->hwaccel && + i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) { + ff_thread_finish_setup(avctx); + h->setup_finished = 1; + } + + max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx; + if (h->nb_slice_ctx_queued == max_slice_ctx) { + if (avctx->hwaccel) { + ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size); + h->nb_slice_ctx_queued = 0; + } else + ret = ff_h264_execute_decode_slices(h); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + goto end; + } + break; + case H264_NAL_DPA: + case H264_NAL_DPB: + case H264_NAL_DPC: + avpriv_request_sample(avctx, "data partitioning"); + ret = AVERROR(ENOSYS); + goto end; + break; + case H264_NAL_SEI: + ret = ff_h264_sei_decode(&h->sei, &nal->gb, &h->ps, avctx); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + goto end; + break; + case H264_NAL_SPS: + ret = ff_h264_decode_seq_parameter_set(&nal->gb, avctx, &h->ps); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + goto end; + break; + case H264_NAL_PPS: + ret = ff_h264_decode_picture_parameter_set(&nal->gb, avctx, &h->ps, + nal->size_bits); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + goto end; + break; + case H264_NAL_AUD: + case H264_NAL_END_SEQUENCE: + case H264_NAL_END_STREAM: + case H264_NAL_FILLER_DATA: + case H264_NAL_SPS_EXT: + case H264_NAL_AUXILIARY_SLICE: + break; + default: + av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n", + nal->type, nal->size_bits); + } + + if (err < 0) { + av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n"); + } + } + + ret = ff_h264_execute_decode_slices(h); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + goto end; + + ret = 0; +end: + /* clean up */ + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + + return (ret < 0) ? ret : buf_size; +} + +/** + * Return the number of bytes consumed for building the current frame. + */ +static int get_consumed_bytes(int pos, int buf_size) +{ + if (pos == 0) + pos = 1; // avoid infinite loops (I doubt that is needed but...) + if (pos + 10 > buf_size) + pos = buf_size; // oops ;) + + return pos; +} + +static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src) +{ + int i; + int ret = av_frame_ref(dst, src); + if (ret < 0) + return ret; + + if (!h->ps.sps || !h->ps.sps->crop) + return 0; + + for (i = 0; i < 3; i++) { + int hshift = (i > 0) ? h->chroma_x_shift : 0; + int vshift = (i > 0) ? h->chroma_y_shift : 0; + int off = ((h->ps.sps->crop_left >> hshift) << h->pixel_shift) + + (h->ps.sps->crop_top >> vshift) * dst->linesize[i]; + dst->data[i] += off; + } + return 0; +} + +static int h264_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + H264Context *h = avctx->priv_data; + AVFrame *pict = data; + int buf_index = 0; + int ret; + const uint8_t *new_extradata; + int new_extradata_size; + + h->flags = avctx->flags; + h->setup_finished = 0; + h->nb_slice_ctx_queued = 0; + + /* end of stream, output what is still in the buffers */ +out: + if (buf_size == 0) { + H264Picture *out; + int i, out_idx; + + h->cur_pic_ptr = NULL; + + // FIXME factorize this with the output code below + out = h->delayed_pic[0]; + out_idx = 0; + for (i = 1; + h->delayed_pic[i] && + !h->delayed_pic[i]->f->key_frame && + !h->delayed_pic[i]->mmco_reset; + i++) + if (h->delayed_pic[i]->poc < out->poc) { + out = h->delayed_pic[i]; + out_idx = i; + } + + for (i = out_idx; h->delayed_pic[i]; i++) + h->delayed_pic[i] = h->delayed_pic[i + 1]; + + if (out) { + ret = output_frame(h, pict, out->f); + if (ret < 0) + return ret; + *got_frame = 1; + } + + return buf_index; + } + + new_extradata_size = 0; + new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, + &new_extradata_size); + if (new_extradata_size > 0 && new_extradata) { + ret = ff_h264_decode_extradata(new_extradata, new_extradata_size, + &h->ps, &h->is_avc, &h->nal_length_size, + avctx->err_recognition, avctx); + if (ret < 0) + return ret; + } + + buf_index = decode_nal_units(h, buf, buf_size); + if (buf_index < 0) + return AVERROR_INVALIDDATA; + + if (!h->cur_pic_ptr && h->nal_unit_type == H264_NAL_END_SEQUENCE) { + buf_size = 0; + goto out; + } + + if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS) && !h->cur_pic_ptr) { + if (avctx->skip_frame >= AVDISCARD_NONREF) + return 0; + av_log(avctx, AV_LOG_ERROR, "no frame!\n"); + return AVERROR_INVALIDDATA; + } + + if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS) || + (h->mb_y >= h->mb_height && h->mb_height)) { + if (h->field_started) + ff_h264_field_end(h, &h->slice_ctx[0], 0); + + *got_frame = 0; + if (h->output_frame->buf[0]) { + ret = output_frame(h, pict, h->output_frame) ; + av_frame_unref(h->output_frame); + if (ret < 0) + return ret; + *got_frame = 1; + } + } + + assert(pict->buf[0] || !*got_frame); + + return get_consumed_bytes(buf_index, buf_size); +} + +#define OFFSET(x) offsetof(H264Context, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption h264_options[] = { + { "enable_er", "Enable error resilience on damaged frames (unsafe)", OFFSET(enable_er), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD }, + { NULL }, +}; + +static const AVClass h264_class = { + .class_name = "h264", + .item_name = av_default_item_name, + .option = h264_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_decoder = { + .name = "h264", + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(H264Context), + .init = ff_h264_decode_init, + .close = h264_decode_end, + .decode = h264_decode_frame, + .capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .flush = flush_dpb, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), + .profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), + .priv_class = &h264_class, +}; diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h new file mode 100644 index 0000000..2ffe4de --- /dev/null +++ b/libavcodec/h264dec.h @@ -0,0 +1,817 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * H.264 / AVC / MPEG-4 part10 codec. + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264DEC_H +#define AVCODEC_H264DEC_H + +#include "libavutil/buffer.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/thread.h" + +#include "cabac.h" +#include "error_resilience.h" +#include "h264_parse.h" +#include "h264_ps.h" +#include "h264_sei.h" +#include "h2645_parse.h" +#include "h264chroma.h" +#include "h264dsp.h" +#include "h264pred.h" +#include "h264qpel.h" +#include "internal.h" +#include "mpegutils.h" +#include "parser.h" +#include "qpeldsp.h" +#include "rectangle.h" +#include "videodsp.h" + +#define H264_MAX_PICTURE_COUNT 32 + +#define MAX_MMCO_COUNT 66 + +#define MAX_DELAYED_PIC_COUNT 16 + +/* Compiling in interlaced support reduces the speed + * of progressive decoding by about 2%. */ +#define ALLOW_INTERLACE + +#define FMO 0 + +/** + * The maximum number of slices supported by the decoder. + * must be a power of 2 + */ +#define MAX_SLICES 32 + +#ifdef ALLOW_INTERLACE +#define MB_MBAFF(h) h->mb_mbaff +#define MB_FIELD(h) h->mb_field_decoding_flag +#define FRAME_MBAFF(h) h->mb_aff_frame +#define FIELD_PICTURE(h) (h->picture_structure != PICT_FRAME) +#define LEFT_MBS 2 +#define LTOP 0 +#define LBOT 1 +#define LEFT(i) (i) +#else +#define MB_MBAFF(h) 0 +#define MB_FIELD(h) 0 +#define FRAME_MBAFF(h) 0 +#define FIELD_PICTURE(h) 0 +#undef IS_INTERLACED +#define IS_INTERLACED(mb_type) 0 +#define LEFT_MBS 1 +#define LTOP 0 +#define LBOT 0 +#define LEFT(i) 0 +#endif +#define FIELD_OR_MBAFF_PICTURE(h) (FRAME_MBAFF(h) || FIELD_PICTURE(h)) + +#ifndef CABAC +#define CABAC(h) h->ps.pps->cabac +#endif + +#define CHROMA422(h) (h->ps.sps->chroma_format_idc == 2) +#define CHROMA444(h) (h->ps.sps->chroma_format_idc == 3) + +#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit +#define MB_TYPE_8x8DCT 0x01000000 +#define IS_REF0(a) ((a) & MB_TYPE_REF0) +#define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT) + +/** + * Memory management control operation opcode. + */ +typedef enum MMCOOpcode { + MMCO_END = 0, + MMCO_SHORT2UNUSED, + MMCO_LONG2UNUSED, + MMCO_SHORT2LONG, + MMCO_SET_MAX_LONG, + MMCO_RESET, + MMCO_LONG, +} MMCOOpcode; + +/** + * Memory management control operation. + */ +typedef struct MMCO { + MMCOOpcode opcode; + int short_pic_num; ///< pic_num without wrapping (pic_num & max_pic_num) + int long_arg; ///< index, pic_num, or num long refs depending on opcode +} MMCO; + +typedef struct H264Picture { + AVFrame *f; + ThreadFrame tf; + + AVBufferRef *qscale_table_buf; + int8_t *qscale_table; + + AVBufferRef *motion_val_buf[2]; + int16_t (*motion_val[2])[2]; + + AVBufferRef *mb_type_buf; + uint32_t *mb_type; + + AVBufferRef *hwaccel_priv_buf; + void *hwaccel_picture_private; ///< hardware accelerator private data + + AVBufferRef *ref_index_buf[2]; + int8_t *ref_index[2]; + + int field_poc[2]; ///< top/bottom POC + int poc; ///< frame POC + int frame_num; ///< frame_num (raw frame_num from slice header) + int mmco_reset; /**< MMCO_RESET set this 1. Reordering code must + not mix pictures before and after MMCO_RESET. */ + int pic_id; /**< pic_num (short -> no wrap version of pic_num, + pic_num & max_pic_num; long -> long_pic_num) */ + int long_ref; ///< 1->long term reference 0->short term reference + int ref_poc[2][2][32]; ///< POCs of the frames used as reference (FIXME need per slice) + int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) + int mbaff; ///< 1 -> MBAFF frame 0-> not MBAFF + int field_picture; ///< whether or not picture was encoded in separate fields + + int reference; + int recovered; ///< picture at IDR or recovery point + recovery count +} H264Picture; + +typedef struct H264Ref { + uint8_t *data[3]; + int linesize[3]; + + int reference; + int poc; + int pic_id; + + H264Picture *parent; +} H264Ref; + +typedef struct H264SliceContext { + struct H264Context *h264; + GetBitContext gb; + ERContext er; + + int slice_num; + int slice_type; + int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) + int slice_type_fixed; + + int qscale; + int chroma_qp[2]; // QPc + int qp_thresh; ///< QP threshold to skip loopfilter + int last_qscale_diff; + + // deblock + int deblocking_filter; ///< disable_deblocking_filter_idc with 1 <-> 0 + int slice_alpha_c0_offset; + int slice_beta_offset; + + H264PredWeightTable pwt; + + int prev_mb_skipped; + int next_mb_skipped; + + int chroma_pred_mode; + int intra16x16_pred_mode; + + int8_t intra4x4_pred_mode_cache[5 * 8]; + int8_t(*intra4x4_pred_mode); + + int topleft_mb_xy; + int top_mb_xy; + int topright_mb_xy; + int left_mb_xy[LEFT_MBS]; + + int topleft_type; + int top_type; + int topright_type; + int left_type[LEFT_MBS]; + + const uint8_t *left_block; + int topleft_partition; + + unsigned int topleft_samples_available; + unsigned int top_samples_available; + unsigned int topright_samples_available; + unsigned int left_samples_available; + + ptrdiff_t linesize, uvlinesize; + ptrdiff_t mb_linesize; ///< may be equal to s->linesize or s->linesize * 2, for mbaff + ptrdiff_t mb_uvlinesize; + + int mb_x, mb_y; + int mb_xy; + int resync_mb_x; + int resync_mb_y; + unsigned int first_mb_addr; + // index of the first MB of the next slice + int next_slice_idx; + int mb_skip_run; + int is_complex; + + int picture_structure; + int mb_field_decoding_flag; + int mb_mbaff; ///< mb_aff_frame && mb_field_decoding_flag + + int redundant_pic_count; + + /** + * number of neighbors (top and/or left) that used 8x8 dct + */ + int neighbor_transform_size; + + int direct_spatial_mv_pred; + int col_parity; + int col_fieldoff; + + int cbp; + int top_cbp; + int left_cbp; + + int dist_scale_factor[32]; + int dist_scale_factor_field[2][32]; + int map_col_to_list0[2][16 + 32]; + int map_col_to_list0_field[2][2][16 + 32]; + + /** + * num_ref_idx_l0/1_active_minus1 + 1 + */ + unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode + unsigned int list_count; + H264Ref ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. + * Reordered version of default_ref_list + * according to picture reordering in slice header */ + struct { + uint8_t op; + uint8_t val; + } ref_modifications[2][32]; + int nb_ref_modifications[2]; + + unsigned int pps_id; + + const uint8_t *intra_pcm_ptr; + int16_t *dc_val_base; + + uint8_t *bipred_scratchpad; + uint8_t *edge_emu_buffer; + uint8_t (*top_borders[2])[(16 * 3) * 2]; + int bipred_scratchpad_allocated; + int edge_emu_buffer_allocated; + int top_borders_allocated[2]; + + /** + * non zero coeff count cache. + * is 64 if not available. + */ + DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; + + /** + * Motion vector cache. + */ + DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2]; + DECLARE_ALIGNED(8, int8_t, ref_cache)[2][5 * 8]; + DECLARE_ALIGNED(16, uint8_t, mvd_cache)[2][5 * 8][2]; + uint8_t direct_cache[5 * 8]; + + DECLARE_ALIGNED(8, uint16_t, sub_mb_type)[4]; + + ///< as a DCT coefficient is int32_t in high depth, we need to reserve twice the space. + DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2]; + DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2]; + ///< as mb is addressed by scantable[i] and scantable is uint8_t we can either + ///< check that i is not too large or ensure that there is some unused stuff after mb + int16_t mb_padding[256 * 2]; + + uint8_t (*mvd_table[2])[2]; + + /** + * Cabac + */ + CABACContext cabac; + uint8_t cabac_state[1024]; + int cabac_init_idc; + + MMCO mmco[MAX_MMCO_COUNT]; + int nb_mmco; + int explicit_ref_marking; + + int frame_num; + int poc_lsb; + int delta_poc_bottom; + int delta_poc[2]; + int curr_pic_num; + int max_pic_num; +} H264SliceContext; + +/** + * H264Context + */ +typedef struct H264Context { + const AVClass *class; + AVCodecContext *avctx; + VideoDSPContext vdsp; + H264DSPContext h264dsp; + H264ChromaContext h264chroma; + H264QpelContext h264qpel; + + H264Picture DPB[H264_MAX_PICTURE_COUNT]; + H264Picture *cur_pic_ptr; + H264Picture cur_pic; + + H264SliceContext *slice_ctx; + int nb_slice_ctx; + int nb_slice_ctx_queued; + + H2645Packet pkt; + + int pixel_shift; ///< 0 for 8-bit H.264, 1 for high-bit-depth H.264 + + /* coded dimensions -- 16 * mb w/h */ + int width, height; + int chroma_x_shift, chroma_y_shift; + + int droppable; + int coded_picture_number; + + int context_initialized; + int flags; + int workaround_bugs; + /* Set when slice threading is used and at least one slice uses deblocking + * mode 1 (i.e. across slice boundaries). Then we disable the loop filter + * during normal MB decoding and execute it serially at the end. + */ + int postpone_filter; + + /* + * Set to 1 when the current picture is IDR, 0 otherwise. + */ + int picture_idr; + + int8_t(*intra4x4_pred_mode); + H264PredContext hpc; + + uint8_t (*non_zero_count)[48]; + +#define LIST_NOT_USED -1 // FIXME rename? +#define PART_NOT_AVAILABLE -2 + + /** + * block_offset[ 0..23] for frame macroblocks + * block_offset[24..47] for field macroblocks + */ + int block_offset[2 * (16 * 3)]; + + uint32_t *mb2b_xy; // FIXME are these 4 a good idea? + uint32_t *mb2br_xy; + int b_stride; // FIXME use s->b4_stride + + uint16_t *slice_table; ///< slice_table_base + 2*mb_stride + 1 + + // interlacing specific flags + int mb_aff_frame; + int picture_structure; + int first_field; + + uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type + + /* 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; + + /* chroma_pred_mode for i4x4 or i16x16, else 0 */ + uint8_t *chroma_pred_mode_table; + uint8_t (*mvd_table[2])[2]; + uint8_t *direct_table; + + 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 mb_y; + int mb_height, mb_width; + int mb_stride; + int mb_num; + + // ============================================================= + // Things below are not used in the MB or more inner code + + int nal_ref_idc; + int nal_unit_type; + + /** + * Used to parse AVC variant of H.264 + */ + int is_avc; ///< this flag is != 0 if codec is avc1 + int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) + + int bit_depth_luma; ///< luma bit depth from sps to detect changes + int chroma_format_idc; ///< chroma format from sps to detect changes + + H264ParamSets ps; + + uint16_t *slice_table_base; + + H264POCContext poc; + + H264Picture *short_ref[32]; + H264Picture *long_ref[32]; + H264Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size? + int last_pocs[MAX_DELAYED_PIC_COUNT]; + int next_outputed_poc; + + /** + * memory management control operations buffer. + */ + MMCO mmco[MAX_MMCO_COUNT]; + int nb_mmco; + int mmco_reset; + int explicit_ref_marking; + + int long_ref_count; ///< number of actual long term references + int short_ref_count; ///< number of actual short term references + + /** + * @name Members for slice based multithreading + * @{ + */ + /** + * current slice number, used to initialize slice_num of each thread/context + */ + int current_slice; + + /** @} */ + + /** + * Complement sei_pic_struct + * SEI_PIC_STRUCT_TOP_BOTTOM and SEI_PIC_STRUCT_BOTTOM_TOP indicate interlaced frames. + * However, soft telecined frames may have these values. + * This is used in an attempt to flag soft telecine progressive. + */ + int prev_interlaced_frame; + + /** + * recovery_frame is the frame_num at which the next frame should + * be fully constructed. + * + * Set to -1 when not expecting a recovery point. + */ + int recovery_frame; + +/** + * We have seen an IDR, so all the following frames in coded order are correctly + * decodable. + */ +#define FRAME_RECOVERED_IDR (1 << 0) +/** + * Sufficient number of frames have been decoded since a SEI recovery point, + * so all the following frames in presentation order are correct. + */ +#define FRAME_RECOVERED_SEI (1 << 1) + + int frame_recovered; ///< Initial frame has been completely recovered + + /* for frame threading, this is set to 1 + * after finish_setup() has been called, so we cannot modify + * some context properties (which are supposed to stay constant between + * slices) anymore */ + int setup_finished; + + /* This is set to 1 if h264_field_start() has been called successfully, + * so all per-field state is properly initialized and we can decode + * the slice data */ + int field_started; + + AVFrame *output_frame; + + int enable_er; + + H264SEIContext sei; + + AVBufferPool *qscale_table_pool; + AVBufferPool *mb_type_pool; + AVBufferPool *motion_val_pool; + AVBufferPool *ref_index_pool; + int ref2frm[MAX_SLICES][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1 +} H264Context; + +extern const uint16_t ff_h264_mb_sizes[4]; + +/** + * Reconstruct bitstream slice_type. + */ +int ff_h264_get_slice_type(const H264SliceContext *sl); + +/** + * Allocate tables. + * needs width/height + */ +int ff_h264_alloc_tables(H264Context *h); + +int ff_h264_decode_ref_pic_list_reordering(H264SliceContext *sl, void *logctx); +int ff_h264_build_ref_list(const H264Context *h, H264SliceContext *sl); +void ff_h264_remove_all_refs(H264Context *h); + +/** + * Execute the reference picture marking (memory management control operations). + */ +int ff_h264_execute_ref_pic_marking(H264Context *h); + +int ff_h264_decode_ref_pic_marking(H264SliceContext *sl, GetBitContext *gb, + const H2645NAL *nal, void *logctx); + +void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl); +int ff_h264_decode_init(AVCodecContext *avctx); +void ff_h264_decode_init_vlc(void); + +/** + * Decode a macroblock + * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error + */ +int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl); + +/** + * Decode a CABAC coded macroblock + * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error + */ +int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl); + +void ff_h264_init_cabac_states(const H264Context *h, H264SliceContext *sl); + +void ff_h264_init_dequant_tables(H264Context *h); + +void ff_h264_direct_dist_scale_factor(const H264Context *const h, H264SliceContext *sl); +void ff_h264_direct_ref_list_init(const H264Context *const h, H264SliceContext *sl); +void ff_h264_pred_direct_motion(const H264Context *const h, H264SliceContext *sl, + int *mb_type); + +void ff_h264_filter_mb_fast(const H264Context *h, H264SliceContext *sl, int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize); +void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl, int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize); + +/* + * o-o o-o + * / / / + * o-o o-o + * ,---' + * o-o o-o + * / / / + * o-o o-o + */ + +/* Scan8 organization: + * 0 1 2 3 4 5 6 7 + * 0 DY y y y y y + * 1 y Y Y Y Y + * 2 y Y Y Y Y + * 3 y Y Y Y Y + * 4 y Y Y Y Y + * 5 DU u u u u u + * 6 u U U U U + * 7 u U U U U + * 8 u U U U U + * 9 u U U U U + * 10 DV v v v v v + * 11 v V V V V + * 12 v V V V V + * 13 v V V V V + * 14 v V V V V + * DY/DU/DV are for luma/chroma DC. + */ + +#define LUMA_DC_BLOCK_INDEX 48 +#define CHROMA_DC_BLOCK_INDEX 49 + +// This table must be here because scan8[constant] must be known at compiletime +static const uint8_t scan8[16 * 3 + 3] = { + 4 + 1 * 8, 5 + 1 * 8, 4 + 2 * 8, 5 + 2 * 8, + 6 + 1 * 8, 7 + 1 * 8, 6 + 2 * 8, 7 + 2 * 8, + 4 + 3 * 8, 5 + 3 * 8, 4 + 4 * 8, 5 + 4 * 8, + 6 + 3 * 8, 7 + 3 * 8, 6 + 4 * 8, 7 + 4 * 8, + 4 + 6 * 8, 5 + 6 * 8, 4 + 7 * 8, 5 + 7 * 8, + 6 + 6 * 8, 7 + 6 * 8, 6 + 7 * 8, 7 + 7 * 8, + 4 + 8 * 8, 5 + 8 * 8, 4 + 9 * 8, 5 + 9 * 8, + 6 + 8 * 8, 7 + 8 * 8, 6 + 9 * 8, 7 + 9 * 8, + 4 + 11 * 8, 5 + 11 * 8, 4 + 12 * 8, 5 + 12 * 8, + 6 + 11 * 8, 7 + 11 * 8, 6 + 12 * 8, 7 + 12 * 8, + 4 + 13 * 8, 5 + 13 * 8, 4 + 14 * 8, 5 + 14 * 8, + 6 + 13 * 8, 7 + 13 * 8, 6 + 14 * 8, 7 + 14 * 8, + 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 +}; + +static av_always_inline uint32_t pack16to32(int a, int b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFFFF) + (a << 16); +#else + return (a & 0xFFFF) + (b << 16); +#endif +} + +static av_always_inline uint16_t pack8to16(int a, int b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFF) + (a << 8); +#else + return (a & 0xFF) + (b << 8); +#endif +} + +/** + * Get the chroma qp. + */ +static av_always_inline int get_chroma_qp(const PPS *pps, int t, int qscale) +{ + return pps->chroma_qp_table[t][qscale]; +} + +/** + * Get the predicted intra4x4 prediction mode. + */ +static av_always_inline int pred_intra_mode(const H264Context *h, + H264SliceContext *sl, int n) +{ + const int index8 = scan8[n]; + const int left = sl->intra4x4_pred_mode_cache[index8 - 1]; + const int top = sl->intra4x4_pred_mode_cache[index8 - 8]; + const int min = FFMIN(left, top); + + ff_tlog(h->avctx, "mode:%d %d min:%d\n", left, top, min); + + if (min < 0) + return DC_PRED; + else + return min; +} + +static av_always_inline void write_back_intra_pred_mode(const H264Context *h, + H264SliceContext *sl) +{ + int8_t *i4x4 = sl->intra4x4_pred_mode + h->mb2br_xy[sl->mb_xy]; + int8_t *i4x4_cache = sl->intra4x4_pred_mode_cache; + + AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4); + i4x4[4] = i4x4_cache[7 + 8 * 3]; + i4x4[5] = i4x4_cache[7 + 8 * 2]; + i4x4[6] = i4x4_cache[7 + 8 * 1]; +} + +static av_always_inline void write_back_non_zero_count(const H264Context *h, + H264SliceContext *sl) +{ + const int mb_xy = sl->mb_xy; + uint8_t *nnz = h->non_zero_count[mb_xy]; + uint8_t *nnz_cache = sl->non_zero_count_cache; + + AV_COPY32(&nnz[ 0], &nnz_cache[4 + 8 * 1]); + AV_COPY32(&nnz[ 4], &nnz_cache[4 + 8 * 2]); + AV_COPY32(&nnz[ 8], &nnz_cache[4 + 8 * 3]); + AV_COPY32(&nnz[12], &nnz_cache[4 + 8 * 4]); + AV_COPY32(&nnz[16], &nnz_cache[4 + 8 * 6]); + AV_COPY32(&nnz[20], &nnz_cache[4 + 8 * 7]); + AV_COPY32(&nnz[32], &nnz_cache[4 + 8 * 11]); + AV_COPY32(&nnz[36], &nnz_cache[4 + 8 * 12]); + + if (!h->chroma_y_shift) { + AV_COPY32(&nnz[24], &nnz_cache[4 + 8 * 8]); + AV_COPY32(&nnz[28], &nnz_cache[4 + 8 * 9]); + AV_COPY32(&nnz[40], &nnz_cache[4 + 8 * 13]); + AV_COPY32(&nnz[44], &nnz_cache[4 + 8 * 14]); + } +} + +static av_always_inline void write_back_motion_list(const H264Context *h, + H264SliceContext *sl, + int b_stride, + int b_xy, int b8_xy, + int mb_type, int list) +{ + int16_t(*mv_dst)[2] = &h->cur_pic.motion_val[list][b_xy]; + int16_t(*mv_src)[2] = &sl->mv_cache[list][scan8[0]]; + AV_COPY128(mv_dst + 0 * b_stride, mv_src + 8 * 0); + AV_COPY128(mv_dst + 1 * b_stride, mv_src + 8 * 1); + AV_COPY128(mv_dst + 2 * b_stride, mv_src + 8 * 2); + AV_COPY128(mv_dst + 3 * b_stride, mv_src + 8 * 3); + if (CABAC(h)) { + uint8_t (*mvd_dst)[2] = &sl->mvd_table[list][FMO ? 8 * sl->mb_xy + : h->mb2br_xy[sl->mb_xy]]; + uint8_t(*mvd_src)[2] = &sl->mvd_cache[list][scan8[0]]; + if (IS_SKIP(mb_type)) { + AV_ZERO128(mvd_dst); + } else { + AV_COPY64(mvd_dst, mvd_src + 8 * 3); + AV_COPY16(mvd_dst + 3 + 3, mvd_src + 3 + 8 * 0); + AV_COPY16(mvd_dst + 3 + 2, mvd_src + 3 + 8 * 1); + AV_COPY16(mvd_dst + 3 + 1, mvd_src + 3 + 8 * 2); + } + } + + { + int8_t *ref_index = &h->cur_pic.ref_index[list][b8_xy]; + int8_t *ref_cache = sl->ref_cache[list]; + ref_index[0 + 0 * 2] = ref_cache[scan8[0]]; + ref_index[1 + 0 * 2] = ref_cache[scan8[4]]; + ref_index[0 + 1 * 2] = ref_cache[scan8[8]]; + ref_index[1 + 1 * 2] = ref_cache[scan8[12]]; + } +} + +static av_always_inline void write_back_motion(const H264Context *h, + H264SliceContext *sl, + int mb_type) +{ + const int b_stride = h->b_stride; + const int b_xy = 4 * sl->mb_x + 4 * sl->mb_y * h->b_stride; // try mb2b(8)_xy + const int b8_xy = 4 * sl->mb_xy; + + if (USES_LIST(mb_type, 0)) { + write_back_motion_list(h, sl, b_stride, b_xy, b8_xy, mb_type, 0); + } else { + fill_rectangle(&h->cur_pic.ref_index[0][b8_xy], + 2, 2, 2, (uint8_t)LIST_NOT_USED, 1); + } + if (USES_LIST(mb_type, 1)) + write_back_motion_list(h, sl, b_stride, b_xy, b8_xy, mb_type, 1); + + if (sl->slice_type_nos == AV_PICTURE_TYPE_B && CABAC(h)) { + if (IS_8X8(mb_type)) { + uint8_t *direct_table = &h->direct_table[4 * sl->mb_xy]; + direct_table[1] = sl->sub_mb_type[1] >> 1; + direct_table[2] = sl->sub_mb_type[2] >> 1; + direct_table[3] = sl->sub_mb_type[3] >> 1; + } + } +} + +static av_always_inline int get_dct8x8_allowed(const H264Context *h, H264SliceContext *sl) +{ + if (h->ps.sps->direct_8x8_inference_flag) + return !(AV_RN64A(sl->sub_mb_type) & + ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8) * + 0x0001000100010001ULL)); + else + return !(AV_RN64A(sl->sub_mb_type) & + ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8 | MB_TYPE_DIRECT2) * + 0x0001000100010001ULL)); +} + +int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup); + +int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src); +void ff_h264_unref_picture(H264Context *h, H264Picture *pic); + +int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl); + +void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height); + +/** + * Submit a slice for decoding. + * + * Parse the slice header, starting a new field/frame if necessary. If any + * slices are queued for the previous field, they are decoded. + */ +int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal); +int ff_h264_execute_decode_slices(H264Context *h); +int ff_h264_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src); + +void ff_h264_flush_change(H264Context *h); + +void ff_h264_free_tables(H264Context *h); + +#endif /* AVCODEC_H264DEC_H */ diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c index c8edbd0..684566b 100644 --- a/libavcodec/h264dsp.c +++ b/libavcodec/h264dsp.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 DSP functions. + * H.264 / AVC / MPEG-4 part10 DSP functions. * @author Michael Niedermayer */ diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h index c4be235..3a5b25b 100644 --- a/libavcodec/h264dsp.h +++ b/libavcodec/h264dsp.h @@ -70,7 +70,7 @@ typedef struct H264DSPContext { int stride, int alpha, int beta); void (*h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix /*align 8*/, int stride, int alpha, int beta); - // h264_loop_filter_strength: simd only. the C version is inlined in h264.c + // h264_loop_filter_strength: simd only. the C version is inlined in h264_loopfilter.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, diff --git a/libavcodec/h264dsp_template.c b/libavcodec/h264dsp_template.c index 3d99cfc..c2d1394 100644 --- a/libavcodec/h264dsp_template.c +++ b/libavcodec/h264dsp_template.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 DSP functions. + * H.264 / AVC / MPEG-4 part10 DSP functions. * @author Michael Niedermayer */ diff --git a/libavcodec/h264idct_template.c b/libavcodec/h264idct_template.c index 83c2a95..08a71cd 100644 --- a/libavcodec/h264idct_template.c +++ b/libavcodec/h264idct_template.c @@ -27,7 +27,7 @@ #include "bit_depth_template.c" #include "libavutil/common.h" -#include "h264.h" +#include "h264dec.h" #include "h264idct.h" void FUNCC(ff_h264_idct_add)(uint8_t *_dst, int16_t *_block, int stride) diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index b782a25..7627eb0 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 prediction functions. + * H.264 / AVC / MPEG-4 part10 prediction functions. * @author Michael Niedermayer */ @@ -547,7 +547,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred16x16[TOP_DC_PRED8x8 ]= FUNCC(pred16x16_top_dc , depth);\ h->pred16x16[DC_128_PRED8x8 ]= FUNCC(pred16x16_128_dc , depth);\ \ - /* special lossless h/v prediction for h264 */ \ + /* special lossless h/v prediction for H.264 */ \ h->pred4x4_add [VERT_PRED ]= FUNCC(pred4x4_vertical_add , depth);\ h->pred4x4_add [ HOR_PRED ]= FUNCC(pred4x4_horizontal_add , depth);\ h->pred8x8l_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_add , depth);\ @@ -574,6 +574,10 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, break; } - if (ARCH_ARM) ff_h264_pred_init_arm(h, codec_id, bit_depth, chroma_format_idc); - if (ARCH_X86) ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); + if (ARCH_AARCH64) + ff_h264_pred_init_aarch64(h, codec_id, bit_depth, chroma_format_idc); + if (ARCH_ARM) + ff_h264_pred_init_arm(h, codec_id, bit_depth, chroma_format_idc); + if (ARCH_X86) + ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); } diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 5c4ef17..60e7434 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 prediction functions. + * H.264 / AVC / MPEG-4 prediction functions. * @author Michael Niedermayer */ @@ -75,7 +75,7 @@ #define TOP_DC_PRED8x8 5 #define DC_128_PRED8x8 6 -// H264/SVQ3 (8x8) specific +// H.264/SVQ3 (8x8) specific #define ALZHEIMER_DC_L0T_PRED8x8 7 #define ALZHEIMER_DC_0LT_PRED8x8 8 #define ALZHEIMER_DC_L00_PRED8x8 9 @@ -111,6 +111,9 @@ typedef struct H264PredContext { void ff_h264_pred_init(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); +void ff_h264_pred_init_aarch64(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc); void ff_h264_pred_init_arm(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 48baec8..8492b2b 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 prediction functions. + * H.264 / AVC / MPEG-4 part10 prediction functions. * @author Michael Niedermayer */ diff --git a/libavcodec/h264qpel_template.c b/libavcodec/h264qpel_template.c index 7dd901c..e846ac9 100644 --- a/libavcodec/h264qpel_template.c +++ b/libavcodec/h264qpel_template.c @@ -378,7 +378,7 @@ static void FUNC(OPNAME ## h264_qpel16_hv_lowpass)(uint8_t *dst, int16_t *tmp, c }\ #define H264_MC(OPNAME, SIZE) \ -static av_unused void FUNCC(OPNAME ## h264_qpel ## SIZE ## _mc00)(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)\ +static void FUNCC(OPNAME ## h264_qpel ## SIZE ## _mc00)(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)\ {\ FUNCC(OPNAME ## pixels ## SIZE)(dst, src, stride, SIZE);\ }\ diff --git a/libavcodec/hap.c b/libavcodec/hap.c new file mode 100644 index 0000000..770142c --- /dev/null +++ b/libavcodec/hap.c @@ -0,0 +1,55 @@ +/* + * Vidvox Hap utility functions + * Copyright (C) 2015 Tom Butterworth + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Hap utilities + */ +#include "hap.h" + +int ff_hap_set_chunk_count(HapContext *ctx, int count, int first_in_frame) +{ + int ret = 0; + if (first_in_frame == 1 && ctx->chunk_count != count) { + int ret = av_reallocp_array(&ctx->chunks, count, sizeof(HapChunk)); + if (ret == 0) + ret = av_reallocp_array(&ctx->chunk_results, count, sizeof(int)); + if (ret < 0) { + ctx->chunk_count = 0; + } else { + ctx->chunk_count = count; + } + } else if (ctx->chunk_count != count) { + /* If this is not the first chunk count calculated for a frame and a + * different count has already been encountered, then reject the frame: + * each table in the Decode Instructions Container must describe the + * same number of chunks. */ + ret = AVERROR_INVALIDDATA; + } + return ret; +} + +av_cold void ff_hap_free_context(HapContext *ctx) +{ + av_freep(&ctx->tex_buf); + av_freep(&ctx->chunks); + av_freep(&ctx->chunk_results); +} diff --git a/libavcodec/hap.h b/libavcodec/hap.h new file mode 100644 index 0000000..9d847f7 --- /dev/null +++ b/libavcodec/hap.h @@ -0,0 +1,98 @@ +/* + * Vidvox Hap + * Copyright (C) 2015 Vittorio Giovara + * Copyright (C) 2015 Tom Butterworth + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HAP_H +#define AVCODEC_HAP_H + +#include + +#include "libavutil/opt.h" + +#include "bytestream.h" +#include "texturedsp.h" + +enum HapTextureFormat { + HAP_FMT_RGBDXT1 = 0x0B, + HAP_FMT_RGBADXT5 = 0x0E, + HAP_FMT_YCOCGDXT5 = 0x0F, +}; + +enum HapCompressor { + HAP_COMP_NONE = 0xA0, + HAP_COMP_SNAPPY = 0xB0, + HAP_COMP_COMPLEX = 0xC0, +}; + +enum HapSectionType { + HAP_ST_DECODE_INSTRUCTIONS = 0x01, + HAP_ST_COMPRESSOR_TABLE = 0x02, + HAP_ST_SIZE_TABLE = 0x03, + HAP_ST_OFFSET_TABLE = 0x04, +}; + +typedef struct HapChunk { + enum HapCompressor compressor; + int compressed_offset; + size_t compressed_size; + int uncompressed_offset; + size_t uncompressed_size; +} HapChunk; + +typedef struct HapContext { + AVClass *class; + + TextureDSPContext dxtc; + GetByteContext gbc; + + enum HapTextureFormat opt_tex_fmt; /* Texture type (encoder only) */ + int opt_chunk_count; /* User-requested chunk count (encoder only) */ + + int chunk_count; + HapChunk *chunks; + int *chunk_results; /* Results from threaded operations */ + + int tex_rat; /* Compression ratio */ + const uint8_t *tex_data; /* Compressed texture */ + uint8_t *tex_buf; /* Buffer for compressed texture */ + size_t tex_size; /* Size of the compressed texture */ + + size_t max_snappy; /* Maximum compressed size for snappy buffer */ + + int slice_count; /* Number of slices for threaded operations */ + + /* Pointer to the selected compress or decompress function */ + int (*tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); +} HapContext; + +/* + * Set the number of chunks in the frame. Returns 0 on success or an error if: + * - first_in_frame is 0 and the number of chunks has changed + * - any other error occurs + */ +int ff_hap_set_chunk_count(HapContext *ctx, int count, int first_in_frame); + +/* + * Free resources associated with the context + */ +av_cold void ff_hap_free_context(HapContext *ctx); + +#endif /* AVCODEC_HAP_H */ diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c new file mode 100644 index 0000000..8f5365b --- /dev/null +++ b/libavcodec/hapdec.c @@ -0,0 +1,430 @@ +/* + * Vidvox Hap decoder + * Copyright (C) 2015 Vittorio Giovara + * Copyright (C) 2015 Tom Butterworth + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Hap decoder + * + * Fourcc: Hap1, Hap5, HapY + * + * https://github.com/Vidvox/hap/blob/master/documentation/HapVideoDRAFT.md + */ + +#include + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "hap.h" +#include "internal.h" +#include "memory.h" +#include "snappy.h" +#include "texturedsp.h" +#include "thread.h" + +/* The first three bytes are the size of the section past the header, or zero + * if the length is stored in the next long word. The fourth byte in the first + * long word indicates the type of the current section. */ +static int parse_section_header(GetByteContext *gbc, int *section_size, + enum HapSectionType *section_type) +{ + if (bytestream2_get_bytes_left(gbc) < 4) + return AVERROR_INVALIDDATA; + + *section_size = bytestream2_get_le24(gbc); + *section_type = bytestream2_get_byte(gbc); + + if (*section_size == 0) { + if (bytestream2_get_bytes_left(gbc) < 4) + return AVERROR_INVALIDDATA; + + *section_size = bytestream2_get_le32(gbc); + } + + if (*section_size > bytestream2_get_bytes_left(gbc)) + return AVERROR_INVALIDDATA; + else + return 0; +} + +static int hap_parse_decode_instructions(HapContext *ctx, int size) +{ + GetByteContext *gbc = &ctx->gbc; + int section_size; + enum HapSectionType section_type; + int is_first_table = 1, had_offsets = 0, had_compressors = 0, had_sizes = 0; + int i, ret; + + while (size > 0) { + int stream_remaining = bytestream2_get_bytes_left(gbc); + ret = parse_section_header(gbc, §ion_size, §ion_type); + if (ret != 0) + return ret; + + size -= stream_remaining - bytestream2_get_bytes_left(gbc); + + switch (section_type) { + case HAP_ST_COMPRESSOR_TABLE: + ret = ff_hap_set_chunk_count(ctx, section_size, is_first_table); + if (ret != 0) + return ret; + for (i = 0; i < section_size; i++) { + ctx->chunks[i].compressor = bytestream2_get_byte(gbc) << 4; + } + had_compressors = 1; + is_first_table = 0; + break; + case HAP_ST_SIZE_TABLE: + ret = ff_hap_set_chunk_count(ctx, section_size / 4, is_first_table); + if (ret != 0) + return ret; + for (i = 0; i < section_size / 4; i++) { + ctx->chunks[i].compressed_size = bytestream2_get_le32(gbc); + } + had_sizes = 1; + is_first_table = 0; + break; + case HAP_ST_OFFSET_TABLE: + ret = ff_hap_set_chunk_count(ctx, section_size / 4, is_first_table); + if (ret != 0) + return ret; + for (i = 0; i < section_size / 4; i++) { + ctx->chunks[i].compressed_offset = bytestream2_get_le32(gbc); + } + had_offsets = 1; + is_first_table = 0; + break; + default: + break; + } + size -= section_size; + } + + if (!had_sizes || !had_compressors) + return AVERROR_INVALIDDATA; + + /* The offsets table is optional. If not present than calculate offsets by + * summing the sizes of preceding chunks. */ + if (!had_offsets) { + size_t running_size = 0; + for (i = 0; i < ctx->chunk_count; i++) { + ctx->chunks[i].compressed_offset = running_size; + running_size += ctx->chunks[i].compressed_size; + } + } + + return 0; +} + +static int hap_can_use_tex_in_place(HapContext *ctx) +{ + int i; + size_t running_offset = 0; + for (i = 0; i < ctx->chunk_count; i++) { + if (ctx->chunks[i].compressed_offset != running_offset + || ctx->chunks[i].compressor != HAP_COMP_NONE) + return 0; + running_offset += ctx->chunks[i].compressed_size; + } + return 1; +} + +static int hap_parse_frame_header(AVCodecContext *avctx) +{ + HapContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + int section_size; + enum HapSectionType section_type; + const char *compressorstr; + int i, ret; + + ret = parse_section_header(gbc, §ion_size, §ion_type); + if (ret != 0) + return ret; + + if ((avctx->codec_tag == MKTAG('H','a','p','1') && (section_type & 0x0F) != HAP_FMT_RGBDXT1) || + (avctx->codec_tag == MKTAG('H','a','p','5') && (section_type & 0x0F) != HAP_FMT_RGBADXT5) || + (avctx->codec_tag == MKTAG('H','a','p','Y') && (section_type & 0x0F) != HAP_FMT_YCOCGDXT5)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid texture format %#04x.\n", section_type & 0x0F); + return AVERROR_INVALIDDATA; + } + + switch (section_type & 0xF0) { + case HAP_COMP_NONE: + case HAP_COMP_SNAPPY: + ret = ff_hap_set_chunk_count(ctx, 1, 1); + if (ret == 0) { + ctx->chunks[0].compressor = section_type & 0xF0; + ctx->chunks[0].compressed_offset = 0; + ctx->chunks[0].compressed_size = section_size; + } + if (ctx->chunks[0].compressor == HAP_COMP_NONE) { + compressorstr = "none"; + } else { + compressorstr = "snappy"; + } + break; + case HAP_COMP_COMPLEX: + ret = parse_section_header(gbc, §ion_size, §ion_type); + if (ret == 0 && section_type != HAP_ST_DECODE_INSTRUCTIONS) + ret = AVERROR_INVALIDDATA; + if (ret == 0) + ret = hap_parse_decode_instructions(ctx, section_size); + compressorstr = "complex"; + break; + default: + ret = AVERROR_INVALIDDATA; + break; + } + + if (ret != 0) + return ret; + + /* Check the frame is valid and read the uncompressed chunk sizes */ + ctx->tex_size = 0; + for (i = 0; i < ctx->chunk_count; i++) { + HapChunk *chunk = &ctx->chunks[i]; + + /* Check the compressed buffer is valid */ + if (chunk->compressed_offset + chunk->compressed_size > bytestream2_get_bytes_left(gbc)) + return AVERROR_INVALIDDATA; + + /* Chunks are unpacked sequentially, ctx->tex_size is the uncompressed + * size thus far */ + chunk->uncompressed_offset = ctx->tex_size; + + /* Fill out uncompressed size */ + if (chunk->compressor == HAP_COMP_SNAPPY) { + GetByteContext gbc_tmp; + int64_t uncompressed_size; + bytestream2_init(&gbc_tmp, gbc->buffer + chunk->compressed_offset, + chunk->compressed_size); + uncompressed_size = ff_snappy_peek_uncompressed_length(&gbc_tmp); + if (uncompressed_size < 0) { + return uncompressed_size; + } + chunk->uncompressed_size = uncompressed_size; + } else if (chunk->compressor == HAP_COMP_NONE) { + chunk->uncompressed_size = chunk->compressed_size; + } else { + return AVERROR_INVALIDDATA; + } + ctx->tex_size += chunk->uncompressed_size; + } + + av_log(avctx, AV_LOG_DEBUG, "%s compressor\n", compressorstr); + + return ret; +} + +static int decompress_chunks_thread(AVCodecContext *avctx, void *arg, + int chunk_nb, int thread_nb) +{ + HapContext *ctx = avctx->priv_data; + + HapChunk *chunk = &ctx->chunks[chunk_nb]; + GetByteContext gbc; + uint8_t *dst = ctx->tex_buf + chunk->uncompressed_offset; + + bytestream2_init(&gbc, ctx->gbc.buffer + chunk->compressed_offset, chunk->compressed_size); + + if (chunk->compressor == HAP_COMP_SNAPPY) { + int ret; + int64_t uncompressed_size = ctx->tex_size; + + /* Uncompress the frame */ + ret = ff_snappy_uncompress(&gbc, dst, &uncompressed_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Snappy uncompress error\n"); + return ret; + } + } else if (chunk->compressor == HAP_COMP_NONE) { + bytestream2_get_buffer(&gbc, dst, chunk->compressed_size); + } + + return 0; +} + +static int decompress_texture_thread(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + HapContext *ctx = avctx->priv_data; + AVFrame *frame = arg; + const uint8_t *d = ctx->tex_data; + int w_block = avctx->coded_width / TEXTURE_BLOCK_W; + int h_block = avctx->coded_height / TEXTURE_BLOCK_H; + int x, y; + int start_slice, end_slice; + int base_blocks_per_slice = h_block / ctx->slice_count; + int remainder_blocks = h_block % ctx->slice_count; + + /* When the frame height (in blocks) doesn't divide evenly between the + * number of slices, spread the remaining blocks evenly between the first + * operations */ + start_slice = slice * base_blocks_per_slice; + /* Add any extra blocks (one per slice) that have been added before this slice */ + start_slice += FFMIN(slice, remainder_blocks); + + end_slice = start_slice + base_blocks_per_slice; + /* Add an extra block if there are still remainder blocks to be accounted for */ + if (slice < remainder_blocks) + end_slice++; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_fun(p + x * 16, frame->linesize[0], + d + (off + x) * ctx->tex_rat); + } + } + + return 0; +} + +static int hap_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + HapContext *ctx = avctx->priv_data; + ThreadFrame tframe; + int ret, i; + + bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size); + + /* Check for section header */ + ret = hap_parse_frame_header(avctx); + if (ret < 0) + return ret; + + /* Get the output frame ready to receive data */ + tframe.f = data; + ret = ff_thread_get_buffer(avctx, &tframe, 0); + if (ret < 0) + return ret; + ff_thread_finish_setup(avctx); + + /* Unpack the DXT texture */ + if (hap_can_use_tex_in_place(ctx)) { + /* Only DXTC texture compression in a contiguous block */ + ctx->tex_data = ctx->gbc.buffer; + } else { + /* Perform the second-stage decompression */ + ret = av_reallocp(&ctx->tex_buf, ctx->tex_size); + if (ret < 0) + return ret; + + avctx->execute2(avctx, decompress_chunks_thread, NULL, + ctx->chunk_results, ctx->chunk_count); + + for (i = 0; i < ctx->chunk_count; i++) { + if (ctx->chunk_results[i] < 0) + return ctx->chunk_results[i]; + } + + ctx->tex_data = ctx->tex_buf; + } + + /* Use the decompress function on the texture, one block per thread */ + avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); + + /* Frame is ready to be output */ + tframe.f->pict_type = AV_PICTURE_TYPE_I; + tframe.f->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int hap_init(AVCodecContext *avctx) +{ + HapContext *ctx = avctx->priv_data; + const char *texture_name; + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid video size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + /* Since codec is based on 4x4 blocks, size is aligned to 4 */ + avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W); + avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H); + + /* Technically only one mode has alpha, but 32 bits are easier to handle */ + avctx->pix_fmt = AV_PIX_FMT_RGBA; + + ff_texturedsp_init(&ctx->dxtc); + + switch (avctx->codec_tag) { + case MKTAG('H','a','p','1'): + texture_name = "DXT1"; + ctx->tex_rat = 8; + ctx->tex_fun = ctx->dxtc.dxt1_block; + break; + case MKTAG('H','a','p','5'): + texture_name = "DXT5"; + ctx->tex_rat = 16; + ctx->tex_fun = ctx->dxtc.dxt5_block; + break; + case MKTAG('H','a','p','Y'): + texture_name = "DXT5-YCoCg-scaled"; + ctx->tex_rat = 16; + ctx->tex_fun = ctx->dxtc.dxt5ys_block; + break; + default: + return AVERROR_DECODER_NOT_FOUND; + } + + av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name); + + ctx->slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / TEXTURE_BLOCK_H); + + return 0; +} + +static av_cold int hap_close(AVCodecContext *avctx) +{ + HapContext *ctx = avctx->priv_data; + + ff_hap_free_context(ctx); + + return 0; +} + +AVCodec ff_hap_decoder = { + .name = "hap", + .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HAP, + .init = hap_init, + .decode = hap_decode, + .close = hap_close, + .priv_data_size = sizeof(HapContext), + .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c new file mode 100644 index 0000000..9ebad4a --- /dev/null +++ b/libavcodec/hapenc.c @@ -0,0 +1,334 @@ +/* + * Vidvox Hap encoder + * Copyright (C) 2015 Vittorio Giovara + * Copyright (C) 2015 Tom Butterworth + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Hap encoder + * + * Fourcc: Hap1, Hap5, HapY + * + * https://github.com/Vidvox/hap/blob/master/documentation/HapVideoDRAFT.md + */ + +#include +#include "snappy-c.h" + +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "hap.h" +#include "internal.h" +#include "texturedsp.h" + +#define HAP_MAX_CHUNKS 64 + +enum HapHeaderLength { + /* Short header: four bytes with a 24 bit size value */ + HAP_HDR_SHORT = 4, + /* Long header: eight bytes with a 32 bit size value */ + HAP_HDR_LONG = 8, +}; + +static void compress_texture(AVCodecContext *avctx, const AVFrame *f) +{ + HapContext *ctx = avctx->priv_data; + uint8_t *out = ctx->tex_buf; + int i, j; + + for (j = 0; j < avctx->height; j += 4) { + for (i = 0; i < avctx->width; i += 4) { + uint8_t *p = f->data[0] + i * 4 + j * f->linesize[0]; + const int step = ctx->tex_fun(out, f->linesize[0], p); + out += step; + } + } +} + +/* section_length does not include the header */ +static void hap_write_section_header(PutByteContext *pbc, + enum HapHeaderLength header_length, + int section_length, + enum HapSectionType section_type) +{ + /* The first three bytes are the length of the section (not including the + * header) or zero if using an eight-byte header. + * For an eight-byte header, the length is in the last four bytes. + * The fourth byte stores the section type. */ + bytestream2_put_le24(pbc, header_length == HAP_HDR_LONG ? 0 : section_length); + bytestream2_put_byte(pbc, section_type); + + if (header_length == HAP_HDR_LONG) { + bytestream2_put_le32(pbc, section_length); + } +} + +static int hap_compress_frame(AVCodecContext *avctx, uint8_t *dst) +{ + HapContext *ctx = avctx->priv_data; + int i, final_size = 0; + + for (i = 0; i < ctx->chunk_count; i++) { + HapChunk *chunk = &ctx->chunks[i]; + uint8_t *chunk_src, *chunk_dst; + int ret; + + if (i == 0) { + chunk->compressed_offset = 0; + } else { + chunk->compressed_offset = ctx->chunks[i-1].compressed_offset + + ctx->chunks[i-1].compressed_size; + } + chunk->uncompressed_size = ctx->tex_size / ctx->chunk_count; + chunk->uncompressed_offset = i * chunk->uncompressed_size; + chunk->compressed_size = ctx->max_snappy; + chunk_src = ctx->tex_buf + chunk->uncompressed_offset; + chunk_dst = dst + chunk->compressed_offset; + + /* Compress with snappy too, write directly on packet buffer. */ + ret = snappy_compress(chunk_src, chunk->uncompressed_size, + chunk_dst, &chunk->compressed_size); + if (ret != SNAPPY_OK) { + av_log(avctx, AV_LOG_ERROR, "Snappy compress error.\n"); + return AVERROR_BUG; + } + + /* If there is no gain from snappy, just use the raw texture. */ + if (chunk->compressed_size >= chunk->uncompressed_size) { + av_log(avctx, AV_LOG_VERBOSE, + "Snappy buffer bigger than uncompressed (%lu >= %lu bytes).\n", + chunk->compressed_size, chunk->uncompressed_size); + memcpy(chunk_dst, chunk_src, chunk->uncompressed_size); + chunk->compressor = HAP_COMP_NONE; + chunk->compressed_size = chunk->uncompressed_size; + } else { + chunk->compressor = HAP_COMP_SNAPPY; + } + + final_size += chunk->compressed_size; + } + + return final_size; +} + +static int hap_decode_instructions_length(HapContext *ctx) +{ + /* Second-Stage Compressor Table (one byte per entry) + * + Chunk Size Table (four bytes per entry) + * + headers for both sections (short versions) + * = chunk_count + (4 * chunk_count) + 4 + 4 */ + return (5 * ctx->chunk_count) + 8; +} + +static int hap_header_length(HapContext *ctx) +{ + /* Top section header (long version) */ + int length = HAP_HDR_LONG; + + if (ctx->chunk_count > 1) { + /* Decode Instructions header (short) + Decode Instructions Container */ + length += HAP_HDR_SHORT + hap_decode_instructions_length(ctx); + } + + return length; +} + +static void hap_write_frame_header(HapContext *ctx, uint8_t *dst, int frame_length) +{ + PutByteContext pbc; + int i; + + bytestream2_init_writer(&pbc, dst, frame_length); + if (ctx->chunk_count == 1) { + /* Write a simple header */ + hap_write_section_header(&pbc, HAP_HDR_LONG, frame_length - 8, + ctx->chunks[0].compressor | ctx->opt_tex_fmt); + } else { + /* Write a complex header with Decode Instructions Container */ + hap_write_section_header(&pbc, HAP_HDR_LONG, frame_length - 8, + HAP_COMP_COMPLEX | ctx->opt_tex_fmt); + hap_write_section_header(&pbc, HAP_HDR_SHORT, hap_decode_instructions_length(ctx), + HAP_ST_DECODE_INSTRUCTIONS); + hap_write_section_header(&pbc, HAP_HDR_SHORT, ctx->chunk_count, + HAP_ST_COMPRESSOR_TABLE); + + for (i = 0; i < ctx->chunk_count; i++) { + bytestream2_put_byte(&pbc, ctx->chunks[i].compressor >> 4); + } + + hap_write_section_header(&pbc, HAP_HDR_SHORT, ctx->chunk_count * 4, + HAP_ST_SIZE_TABLE); + + for (i = 0; i < ctx->chunk_count; i++) { + bytestream2_put_le32(&pbc, ctx->chunks[i].compressed_size); + } + } +} + +static int hap_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + HapContext *ctx = avctx->priv_data; + int header_length = hap_header_length(ctx); + int final_data_size, ret; + int pktsize = FFMAX(ctx->tex_size, ctx->max_snappy * ctx->chunk_count) + header_length; + + /* Allocate maximum size packet, shrink later. */ + ret = ff_alloc_packet(pkt, pktsize); + if (ret < 0) + return ret; + + /* DXTC compression. */ + compress_texture(avctx, frame); + + /* Compress (using Snappy) the frame */ + final_data_size = hap_compress_frame(avctx, pkt->data + header_length); + if (final_data_size < 0) + return final_data_size; + + /* Write header at the start. */ + hap_write_frame_header(ctx, pkt->data, final_data_size + header_length); + + av_shrink_packet(pkt, final_data_size + header_length); + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int hap_init(AVCodecContext *avctx) +{ + HapContext *ctx = avctx->priv_data; + int ratio; + int corrected_chunk_count; + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid video size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + if (avctx->width % 4 || avctx->height % 4) { + av_log(avctx, AV_LOG_ERROR, "Video size %dx%d is not multiple of 4.\n", + avctx->width, avctx->height); + return AVERROR_INVALIDDATA; + } + + ff_texturedspenc_init(&ctx->dxtc); + + switch (ctx->opt_tex_fmt) { + case HAP_FMT_RGBDXT1: + ratio = 8; + avctx->codec_tag = MKTAG('H', 'a', 'p', '1'); + avctx->bits_per_coded_sample = 24; + ctx->tex_fun = ctx->dxtc.dxt1_block; + break; + case HAP_FMT_RGBADXT5: + ratio = 4; + avctx->codec_tag = MKTAG('H', 'a', 'p', '5'); + avctx->bits_per_coded_sample = 32; + ctx->tex_fun = ctx->dxtc.dxt5_block; + break; + case HAP_FMT_YCOCGDXT5: + ratio = 4; + avctx->codec_tag = MKTAG('H', 'a', 'p', 'Y'); + avctx->bits_per_coded_sample = 24; + ctx->tex_fun = ctx->dxtc.dxt5ys_block; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid format %02X\n", ctx->opt_tex_fmt); + return AVERROR_INVALIDDATA; + } + + /* Texture compression ratio is constant, so can we computer + * beforehand the final size of the uncompressed buffer. */ + ctx->tex_size = FFALIGN(avctx->width, TEXTURE_BLOCK_W) * + FFALIGN(avctx->height, TEXTURE_BLOCK_H) * 4 / ratio; + + /* Round the chunk count to divide evenly on DXT block edges */ + corrected_chunk_count = av_clip(ctx->opt_chunk_count, 1, HAP_MAX_CHUNKS); + while ((ctx->tex_size / (64 / ratio)) % corrected_chunk_count != 0) { + corrected_chunk_count--; + } + if (corrected_chunk_count != ctx->opt_chunk_count) { + av_log(avctx, AV_LOG_INFO, "%d chunks requested but %d used.\n", + ctx->opt_chunk_count, corrected_chunk_count); + } + ret = ff_hap_set_chunk_count(ctx, corrected_chunk_count, 1); + if (ret != 0) + return ret; + + ctx->max_snappy = snappy_max_compressed_length(ctx->tex_size / corrected_chunk_count); + + ctx->tex_buf = av_malloc(ctx->tex_size); + if (!ctx->tex_buf) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int hap_close(AVCodecContext *avctx) +{ + HapContext *ctx = avctx->priv_data; + + ff_hap_free_context(ctx); + + return 0; +} + +#define OFFSET(x) offsetof(HapContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "format", NULL, OFFSET(opt_tex_fmt), AV_OPT_TYPE_INT, { .i64 = HAP_FMT_RGBDXT1 }, HAP_FMT_RGBDXT1, HAP_FMT_YCOCGDXT5, FLAGS, "format" }, + { "hap", "Hap 1 (DXT1 textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_RGBDXT1 }, 0, 0, FLAGS, "format" }, + { "hap_alpha", "Hap Alpha (DXT5 textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_RGBADXT5 }, 0, 0, FLAGS, "format" }, + { "hap_q", "Hap Q (DXT5-YCoCg textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_YCOCGDXT5 }, 0, 0, FLAGS, "format" }, + { "chunks", "chunk count", OFFSET(opt_chunk_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, HAP_MAX_CHUNKS, FLAGS, }, + { NULL }, +}; + +static const AVClass hapenc_class = { + .class_name = "Hap encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_hap_encoder = { + .name = "hap", + .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HAP, + .priv_data_size = sizeof(HapContext), + .priv_class = &hapenc_class, + .init = hap_init, + .encode2 = hap_encode, + .close = hap_close, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE, + }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 21d437c..e168d7e 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -37,10 +37,11 @@ #include "cabac_functions.h" #include "golomb.h" #include "hevc.h" +#include "profiles.h" -const uint8_t ff_hevc_qpel_extra_before[4] = { 0, 3, 3, 2 }; -const uint8_t ff_hevc_qpel_extra_after[4] = { 0, 3, 4, 4 }; -const uint8_t ff_hevc_qpel_extra[4] = { 0, 6, 7, 6 }; +const uint8_t ff_hevc_qpel_extra_before[4] = { 0, 3, 3, 3 }; +const uint8_t ff_hevc_qpel_extra_after[4] = { 0, 4, 4, 4 }; +const uint8_t ff_hevc_qpel_extra[4] = { 0, 7, 7, 7 }; static const uint8_t scan_1x1[1] = { 0 }; @@ -82,20 +83,6 @@ static const uint8_t diag_scan2x2_inv[2][2] = { { 1, 3, }, }; -const uint8_t ff_hevc_diag_scan4x4_x[16] = { - 0, 0, 1, 0, - 1, 2, 0, 1, - 2, 3, 1, 2, - 3, 2, 3, 3, -}; - -const uint8_t ff_hevc_diag_scan4x4_y[16] = { - 0, 1, 0, 2, - 1, 0, 3, 2, - 1, 0, 3, 2, - 1, 3, 2, 3, -}; - static const uint8_t diag_scan4x4_inv[4][4] = { { 0, 2, 5, 9, }, { 1, 4, 8, 12, }, @@ -103,44 +90,6 @@ static const uint8_t diag_scan4x4_inv[4][4] = { { 6, 10, 13, 15, }, }; -const uint8_t ff_hevc_diag_scan8x8_x[64] = { - 0, 0, 1, 0, - 1, 2, 0, 1, - 2, 3, 0, 1, - 2, 3, 4, 0, - 1, 2, 3, 4, - 5, 0, 1, 2, - 3, 4, 5, 6, - 0, 1, 2, 3, - 4, 5, 6, 7, - 1, 2, 3, 4, - 5, 6, 7, 2, - 3, 4, 5, 6, - 7, 3, 4, 5, - 6, 7, 4, 5, - 6, 7, 5, 6, - 7, 6, 7, 7, -}; - -const uint8_t ff_hevc_diag_scan8x8_y[64] = { - 0, 1, 0, 2, - 1, 0, 3, 2, - 1, 0, 4, 3, - 2, 1, 0, 5, - 4, 3, 2, 1, - 0, 6, 5, 4, - 3, 2, 1, 0, - 7, 6, 5, 4, - 3, 2, 1, 0, - 7, 6, 5, 4, - 3, 2, 1, 7, - 6, 5, 4, 3, - 2, 7, 6, 5, - 4, 3, 7, 6, - 5, 4, 7, 6, - 5, 7, 6, 7, -}; - static const uint8_t diag_scan8x8_inv[8][8] = { { 0, 2, 5, 9, 14, 20, 27, 35, }, { 1, 4, 8, 13, 19, 26, 34, 42, }, @@ -251,10 +200,10 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) uint8_t luma_weight_l1_flag[16]; uint8_t chroma_weight_l1_flag[16]; - s->sh.luma_log2_weight_denom = av_clip_c(get_ue_golomb_long(gb), 0, 7); - if (s->sps->chroma_format_idc != 0) { + s->sh.luma_log2_weight_denom = av_clip(get_ue_golomb_long(gb), 0, 7); + if (s->ps.sps->chroma_format_idc != 0) { int delta = get_se_golomb(gb); - s->sh.chroma_log2_weight_denom = av_clip_c(s->sh.luma_log2_weight_denom + delta, 0, 7); + s->sh.chroma_log2_weight_denom = av_clip(s->sh.luma_log2_weight_denom + delta, 0, 7); } for (i = 0; i < s->sh.nb_refs[L0]; i++) { @@ -264,7 +213,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) s->sh.luma_offset_l0[i] = 0; } } - if (s->sps->chroma_format_idc != 0) { // FIXME: invert "if" and "for" + if (s->ps.sps->chroma_format_idc != 0) { // FIXME: invert "if" and "for" for (i = 0; i < s->sh.nb_refs[L0]; i++) chroma_weight_l0_flag[i] = get_bits1(gb); } else { @@ -282,7 +231,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) int delta_chroma_weight_l0 = get_se_golomb(gb); int delta_chroma_offset_l0 = get_se_golomb(gb); s->sh.chroma_weight_l0[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l0; - s->sh.chroma_offset_l0[i][j] = av_clip_c((delta_chroma_offset_l0 - ((128 * s->sh.chroma_weight_l0[i][j]) + s->sh.chroma_offset_l0[i][j] = av_clip((delta_chroma_offset_l0 - ((128 * s->sh.chroma_weight_l0[i][j]) >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); } } else { @@ -300,7 +249,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) s->sh.luma_offset_l1[i] = 0; } } - if (s->sps->chroma_format_idc != 0) { + if (s->ps.sps->chroma_format_idc != 0) { for (i = 0; i < s->sh.nb_refs[L1]; i++) chroma_weight_l1_flag[i] = get_bits1(gb); } else { @@ -318,7 +267,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) int delta_chroma_weight_l1 = get_se_golomb(gb); int delta_chroma_offset_l1 = get_se_golomb(gb); s->sh.chroma_weight_l1[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l1; - s->sh.chroma_offset_l1[i][j] = av_clip_c((delta_chroma_offset_l1 - ((128 * s->sh.chroma_weight_l1[i][j]) + s->sh.chroma_offset_l1[i][j] = av_clip((delta_chroma_offset_l1 - ((128 * s->sh.chroma_weight_l1[i][j]) >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); } } else { @@ -333,7 +282,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) { - const HEVCSPS *sps = s->sps; + const HEVCSPS *sps = s->ps.sps; int max_poc_lsb = 1 << sps->log2_max_poc_lsb; int prev_delta_msb = 0; unsigned int nb_sps = 0, nb_sh; @@ -383,46 +332,103 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) return 0; } -static int set_sps(HEVCContext *s, const HEVCSPS *sps) +static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps, + const HEVCSPS *sps) { - int ret; + const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data; unsigned int num = 0, den = 0; - pic_arrays_free(s); - ret = pic_arrays_init(s, sps); - if (ret < 0) - goto fail; - - s->avctx->coded_width = sps->width; - s->avctx->coded_height = sps->height; - s->avctx->width = sps->output_width; - s->avctx->height = sps->output_height; - s->avctx->pix_fmt = sps->pix_fmt; - s->avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; + avctx->pix_fmt = sps->pix_fmt; + avctx->coded_width = sps->width; + avctx->coded_height = sps->height; + avctx->width = sps->output_width; + avctx->height = sps->output_height; + avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; + avctx->profile = sps->ptl.general_ptl.profile_idc; + avctx->level = sps->ptl.general_ptl.level_idc; - ff_set_sar(s->avctx, sps->vui.sar); + ff_set_sar(avctx, sps->vui.sar); if (sps->vui.video_signal_type_present_flag) - s->avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG - : AVCOL_RANGE_MPEG; + avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG + : AVCOL_RANGE_MPEG; else - s->avctx->color_range = AVCOL_RANGE_MPEG; + avctx->color_range = AVCOL_RANGE_MPEG; if (sps->vui.colour_description_present_flag) { - s->avctx->color_primaries = sps->vui.colour_primaries; - s->avctx->color_trc = sps->vui.transfer_characteristic; - s->avctx->colorspace = sps->vui.matrix_coeffs; + avctx->color_primaries = sps->vui.colour_primaries; + avctx->color_trc = sps->vui.transfer_characteristic; + avctx->colorspace = sps->vui.matrix_coeffs; } else { - s->avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; - s->avctx->color_trc = AVCOL_TRC_UNSPECIFIED; - s->avctx->colorspace = AVCOL_SPC_UNSPECIFIED; + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + avctx->colorspace = AVCOL_SPC_UNSPECIFIED; + } + + if (vps->vps_timing_info_present_flag) { + num = vps->vps_num_units_in_tick; + den = vps->vps_time_scale; + } else if (sps->vui.vui_timing_info_present_flag) { + num = sps->vui.vui_num_units_in_tick; + den = sps->vui.vui_time_scale; } + if (num != 0 && den != 0) + av_reduce(&avctx->framerate.den, &avctx->framerate.num, + num, den, 1 << 30); +} + +static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) +{ + #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; + + if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P || + sps->pix_fmt == AV_PIX_FMT_YUV420P10) { +#if CONFIG_HEVC_DXVA2_HWACCEL + *fmt++ = AV_PIX_FMT_DXVA2_VLD; +#endif + } + if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P) { +#if CONFIG_HEVC_D3D11VA_HWACCEL + *fmt++ = AV_PIX_FMT_D3D11VA_VLD; +#endif +#if CONFIG_HEVC_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif + } + + *fmt++ = sps->pix_fmt; + *fmt = AV_PIX_FMT_NONE; + + return ff_get_format(s->avctx, pix_fmts); +} + +static int set_sps(HEVCContext *s, const HEVCSPS *sps, + enum AVPixelFormat pix_fmt) +{ + int ret; + + pic_arrays_free(s); + s->ps.sps = NULL; + s->ps.vps = NULL; + + if (!sps) + return 0; + + ret = pic_arrays_init(s, sps); + if (ret < 0) + goto fail; + + export_stream_params(s->avctx, &s->ps, sps); + + s->avctx->pix_fmt = pix_fmt; + ff_hevc_pred_init(&s->hpc, sps->bit_depth); ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth); ff_videodsp_init (&s->vdsp, sps->bit_depth); - if (sps->sao_enabled) { + if (sps->sao_enabled && !s->avctx->hwaccel) { av_frame_unref(s->tmp_frame); ret = ff_get_buffer(s->avctx, s->tmp_frame, AV_GET_BUFFER_FLAG_REF); if (ret < 0) @@ -430,26 +436,14 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps) s->frame = s->tmp_frame; } - s->sps = sps; - s->vps = (HEVCVPS*) s->vps_list[s->sps->vps_id]->data; - - if (s->vps->vps_timing_info_present_flag) { - num = s->vps->vps_num_units_in_tick; - den = s->vps->vps_time_scale; - } else if (sps->vui.vui_timing_info_present_flag) { - num = sps->vui.vui_num_units_in_tick; - den = sps->vui.vui_time_scale; - } - - if (num != 0 && den != 0) - av_reduce(&s->avctx->time_base.num, &s->avctx->time_base.den, - num, den, 1 << 30); + s->ps.sps = sps; + s->ps.vps = (HEVCVPS*) s->ps.vps_list[s->ps.sps->vps_id]->data; return 0; fail: pic_arrays_free(s); - s->sps = NULL; + s->ps.sps = NULL; return ret; } @@ -471,22 +465,28 @@ static int hls_slice_header(HEVCContext *s) sh->no_output_of_prior_pics_flag = get_bits1(gb); sh->pps_id = get_ue_golomb_long(gb); - if (sh->pps_id >= MAX_PPS_COUNT || !s->pps_list[sh->pps_id]) { + if (sh->pps_id >= MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id); return AVERROR_INVALIDDATA; } if (!sh->first_slice_in_pic_flag && - s->pps != (HEVCPPS*)s->pps_list[sh->pps_id]->data) { + s->ps.pps != (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data) { av_log(s->avctx, AV_LOG_ERROR, "PPS changed between slices.\n"); return AVERROR_INVALIDDATA; } - s->pps = (HEVCPPS*)s->pps_list[sh->pps_id]->data; + s->ps.pps = (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data; - if (s->sps != (HEVCSPS*)s->sps_list[s->pps->sps_id]->data) { - s->sps = (HEVCSPS*)s->sps_list[s->pps->sps_id]->data; + if (s->ps.sps != (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data) { + const HEVCSPS *sps = (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data; + enum AVPixelFormat pix_fmt; ff_hevc_clear_refs(s); - ret = set_sps(s, s->sps); + + pix_fmt = get_format(s, sps); + if (pix_fmt < 0) + return pix_fmt; + + ret = set_sps(s, sps, pix_fmt); if (ret < 0) return ret; @@ -494,20 +494,17 @@ static int hls_slice_header(HEVCContext *s) s->max_ra = INT_MAX; } - s->avctx->profile = s->sps->ptl.general_ptl.profile_idc; - s->avctx->level = s->sps->ptl.general_ptl.level_idc; - sh->dependent_slice_segment_flag = 0; if (!sh->first_slice_in_pic_flag) { int slice_address_length; - if (s->pps->dependent_slice_segments_enabled_flag) + if (s->ps.pps->dependent_slice_segments_enabled_flag) sh->dependent_slice_segment_flag = get_bits1(gb); - slice_address_length = av_ceil_log2(s->sps->ctb_width * - s->sps->ctb_height); - sh->slice_segment_addr = get_bits(gb, slice_address_length); - if (sh->slice_segment_addr >= s->sps->ctb_width * s->sps->ctb_height) { + slice_address_length = av_ceil_log2(s->ps.sps->ctb_width * + s->ps.sps->ctb_height); + sh->slice_segment_addr = slice_address_length ? get_bits(gb, slice_address_length) : 0; + if (sh->slice_segment_addr >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) { av_log(s->avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n", sh->slice_segment_addr); @@ -527,7 +524,7 @@ static int hls_slice_header(HEVCContext *s) if (!sh->dependent_slice_segment_flag) { s->slice_initialized = 0; - for (i = 0; i < s->pps->num_extra_slice_header_bits; i++) + for (i = 0; i < s->ps.pps->num_extra_slice_header_bits; i++) skip_bits(gb, 1); // slice_reserved_undetermined_flag[] sh->slice_type = get_ue_golomb_long(gb); @@ -545,16 +542,16 @@ static int hls_slice_header(HEVCContext *s) // when flag is not present, picture is inferred to be output sh->pic_output_flag = 1; - if (s->pps->output_flag_present_flag) + if (s->ps.pps->output_flag_present_flag) sh->pic_output_flag = get_bits1(gb); - if (s->sps->separate_colour_plane_flag) + if (s->ps.sps->separate_colour_plane_flag) sh->colour_plane_id = get_bits(gb, 2); if (!IS_IDR(s)) { - int short_term_ref_pic_set_sps_flag, poc; + int poc, pos; - sh->pic_order_cnt_lsb = get_bits(gb, s->sps->log2_max_poc_lsb); + sh->pic_order_cnt_lsb = get_bits(gb, s->ps.sps->log2_max_poc_lsb); poc = ff_hevc_compute_poc(s, sh->pic_order_cnt_lsb); if (!sh->first_slice_in_pic_flag && poc != s->poc) { av_log(s->avctx, AV_LOG_WARNING, @@ -565,9 +562,10 @@ static int hls_slice_header(HEVCContext *s) } s->poc = poc; - short_term_ref_pic_set_sps_flag = get_bits1(gb); - if (!short_term_ref_pic_set_sps_flag) { - ret = ff_hevc_decode_short_term_rps(s, &sh->slice_rps, s->sps, 1); + sh->short_term_ref_pic_set_sps_flag = get_bits1(gb); + pos = get_bits_left(gb); + if (!sh->short_term_ref_pic_set_sps_flag) { + ret = ff_hevc_decode_short_term_rps(gb, s->avctx, &sh->slice_rps, s->ps.sps, 1); if (ret < 0) return ret; @@ -575,24 +573,27 @@ static int hls_slice_header(HEVCContext *s) } else { int numbits, rps_idx; - if (!s->sps->nb_st_rps) { + if (!s->ps.sps->nb_st_rps) { av_log(s->avctx, AV_LOG_ERROR, "No ref lists in the SPS.\n"); return AVERROR_INVALIDDATA; } - numbits = av_ceil_log2(s->sps->nb_st_rps); + numbits = av_ceil_log2(s->ps.sps->nb_st_rps); rps_idx = numbits > 0 ? get_bits(gb, numbits) : 0; - sh->short_term_rps = &s->sps->st_rps[rps_idx]; + sh->short_term_rps = &s->ps.sps->st_rps[rps_idx]; } + sh->short_term_ref_pic_set_size = pos - get_bits_left(gb); + pos = get_bits_left(gb); ret = decode_lt_rps(s, &sh->long_term_rps, gb); if (ret < 0) { av_log(s->avctx, AV_LOG_WARNING, "Invalid long term RPS.\n"); if (s->avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; } + sh->long_term_ref_pic_set_size = pos - get_bits_left(gb); - if (s->sps->sps_temporal_mvp_enabled_flag) + if (s->ps.sps->sps_temporal_mvp_enabled_flag) sh->slice_temporal_mvp_enabled_flag = get_bits1(gb); else sh->slice_temporal_mvp_enabled_flag = 0; @@ -612,7 +613,7 @@ static int hls_slice_header(HEVCContext *s) s->nal_unit_type != NAL_RASL_R) s->pocTid0 = s->poc; - if (s->sps->sao_enabled) { + if (s->ps.sps->sao_enabled) { sh->slice_sample_adaptive_offset_flag[0] = get_bits1(gb); sh->slice_sample_adaptive_offset_flag[1] = sh->slice_sample_adaptive_offset_flag[2] = get_bits1(gb); @@ -626,9 +627,9 @@ static int hls_slice_header(HEVCContext *s) if (sh->slice_type == P_SLICE || sh->slice_type == B_SLICE) { int nb_refs; - sh->nb_refs[L0] = s->pps->num_ref_idx_l0_default_active; + sh->nb_refs[L0] = s->ps.pps->num_ref_idx_l0_default_active; if (sh->slice_type == B_SLICE) - sh->nb_refs[L1] = s->pps->num_ref_idx_l1_default_active; + sh->nb_refs[L1] = s->ps.pps->num_ref_idx_l1_default_active; if (get_bits1(gb)) { // num_ref_idx_active_override_flag sh->nb_refs[L0] = get_ue_golomb_long(gb) + 1; @@ -649,7 +650,7 @@ static int hls_slice_header(HEVCContext *s) return AVERROR_INVALIDDATA; } - if (s->pps->lists_modification_present_flag && nb_refs > 1) { + if (s->ps.pps->lists_modification_present_flag && nb_refs > 1) { sh->rpl_modification_flag[0] = get_bits1(gb); if (sh->rpl_modification_flag[0]) { for (i = 0; i < sh->nb_refs[L0]; i++) @@ -667,7 +668,7 @@ static int hls_slice_header(HEVCContext *s) if (sh->slice_type == B_SLICE) sh->mvd_l1_zero_flag = get_bits1(gb); - if (s->pps->cabac_init_present_flag) + if (s->ps.pps->cabac_init_present_flag) sh->cabac_init_flag = get_bits1(gb); else sh->cabac_init_flag = 0; @@ -689,8 +690,8 @@ static int hls_slice_header(HEVCContext *s) } } - if ((s->pps->weighted_pred_flag && sh->slice_type == P_SLICE) || - (s->pps->weighted_bipred_flag && sh->slice_type == B_SLICE)) { + if ((s->ps.pps->weighted_pred_flag && sh->slice_type == P_SLICE) || + (s->ps.pps->weighted_bipred_flag && sh->slice_type == B_SLICE)) { pred_weight_table(s, gb); } @@ -705,7 +706,7 @@ static int hls_slice_header(HEVCContext *s) sh->slice_qp_delta = get_se_golomb(gb); - if (s->pps->pic_slice_level_chroma_qp_offsets_present_flag) { + if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) { sh->slice_cb_qp_offset = get_se_golomb(gb); sh->slice_cr_qp_offset = get_se_golomb(gb); } else { @@ -713,10 +714,10 @@ static int hls_slice_header(HEVCContext *s) sh->slice_cr_qp_offset = 0; } - if (s->pps->deblocking_filter_control_present_flag) { + if (s->ps.pps->deblocking_filter_control_present_flag) { int deblocking_filter_override_flag = 0; - if (s->pps->deblocking_filter_override_enabled_flag) + if (s->ps.pps->deblocking_filter_override_enabled_flag) deblocking_filter_override_flag = get_bits1(gb); if (deblocking_filter_override_flag) { @@ -726,9 +727,9 @@ static int hls_slice_header(HEVCContext *s) sh->tc_offset = get_se_golomb(gb) * 2; } } else { - sh->disable_deblocking_filter_flag = s->pps->disable_dbf; - sh->beta_offset = s->pps->beta_offset; - sh->tc_offset = s->pps->tc_offset; + sh->disable_deblocking_filter_flag = s->ps.pps->disable_dbf; + sh->beta_offset = s->ps.pps->beta_offset; + sh->tc_offset = s->ps.pps->tc_offset; } } else { sh->disable_deblocking_filter_flag = 0; @@ -736,13 +737,13 @@ static int hls_slice_header(HEVCContext *s) sh->tc_offset = 0; } - if (s->pps->seq_loop_filter_across_slices_enabled_flag && + if (s->ps.pps->seq_loop_filter_across_slices_enabled_flag && (sh->slice_sample_adaptive_offset_flag[0] || sh->slice_sample_adaptive_offset_flag[1] || !sh->disable_deblocking_filter_flag)) { sh->slice_loop_filter_across_slices_enabled_flag = get_bits1(gb); } else { - sh->slice_loop_filter_across_slices_enabled_flag = s->pps->seq_loop_filter_across_slices_enabled_flag; + sh->slice_loop_filter_across_slices_enabled_flag = s->ps.pps->seq_loop_filter_across_slices_enabled_flag; } } else if (!s->slice_initialized) { av_log(s->avctx, AV_LOG_ERROR, "Independent slice segment missing.\n"); @@ -750,7 +751,7 @@ static int hls_slice_header(HEVCContext *s) } sh->num_entry_point_offsets = 0; - if (s->pps->tiles_enabled_flag || s->pps->entropy_coding_sync_enabled_flag) { + if (s->ps.pps->tiles_enabled_flag || s->ps.pps->entropy_coding_sync_enabled_flag) { sh->num_entry_point_offsets = get_ue_golomb_long(gb); if (sh->num_entry_point_offsets > 0) { int offset_len = get_ue_golomb_long(gb) + 1; @@ -760,21 +761,21 @@ static int hls_slice_header(HEVCContext *s) } } - if (s->pps->slice_header_extension_present_flag) { + if (s->ps.pps->slice_header_extension_present_flag) { unsigned int length = get_ue_golomb_long(gb); for (i = 0; i < length; i++) skip_bits(gb, 8); // slice_header_extension_data_byte } // Inferred parameters - sh->slice_qp = 26 + s->pps->pic_init_qp_minus26 + sh->slice_qp_delta; + sh->slice_qp = 26 + s->ps.pps->pic_init_qp_minus26 + sh->slice_qp_delta; if (sh->slice_qp > 51 || - sh->slice_qp < -s->sps->qp_bd_offset) { + sh->slice_qp < -s->ps.sps->qp_bd_offset) { av_log(s->avctx, AV_LOG_ERROR, "The slice_qp %d is outside the valid range " "[%d, 51].\n", sh->slice_qp, - -s->sps->qp_bd_offset); + -s->ps.sps->qp_bd_offset); return AVERROR_INVALIDDATA; } @@ -787,16 +788,16 @@ static int hls_slice_header(HEVCContext *s) s->HEVClc.first_qp_group = !s->sh.dependent_slice_segment_flag; - if (!s->pps->cu_qp_delta_enabled_flag) - s->HEVClc.qp_y = FFUMOD(s->sh.slice_qp + 52 + 2 * s->sps->qp_bd_offset, - 52 + s->sps->qp_bd_offset) - s->sps->qp_bd_offset; + if (!s->ps.pps->cu_qp_delta_enabled_flag) + s->HEVClc.qp_y = FFUMOD(s->sh.slice_qp + 52 + 2 * s->ps.sps->qp_bd_offset, + 52 + s->ps.sps->qp_bd_offset) - s->ps.sps->qp_bd_offset; s->slice_initialized = 1; return 0; } -#define CTB(tab, x, y) ((tab)[(y) * s->sps->ctb_width + (x)]) +#define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)]) #define SET_SAO(elem, value) \ do { \ @@ -815,7 +816,7 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) HEVCLocalContext *lc = &s->HEVClc; int sao_merge_left_flag = 0; int sao_merge_up_flag = 0; - int shift = s->sps->bit_depth - FFMIN(s->sps->bit_depth, 10); + int shift = s->ps.sps->bit_depth - FFMIN(s->ps.sps->bit_depth, 10); SAOParams *sao = &CTB(s->sao, rx, ry); int c_idx, i; @@ -905,16 +906,16 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, const uint8_t *scan_x_cg, *scan_y_cg, *scan_x_off, *scan_y_off; ptrdiff_t stride = s->frame->linesize[c_idx]; - int hshift = s->sps->hshift[c_idx]; - int vshift = s->sps->vshift[c_idx]; + int hshift = s->ps.sps->hshift[c_idx]; + int vshift = s->ps.sps->vshift[c_idx]; uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride + - ((x0 >> hshift) << s->sps->pixel_shift)]; - DECLARE_ALIGNED(16, int16_t, coeffs[MAX_TB_SIZE * MAX_TB_SIZE]) = { 0 }; + ((x0 >> hshift) << s->ps.sps->pixel_shift)]; + DECLARE_ALIGNED(32, int16_t, coeffs[MAX_TB_SIZE * MAX_TB_SIZE]) = { 0 }; DECLARE_ALIGNED(8, uint8_t, significant_coeff_group_flag[8][8]) = { { 0 } }; int trafo_size = 1 << log2_trafo_size; int i, qp, shift, add, scale, scale_m; - const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 }; + static const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 }; const uint8_t *scale_matrix; uint8_t dc_scale; @@ -938,16 +939,16 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, int qp_y = lc->qp_y; if (c_idx == 0) { - qp = qp_y + s->sps->qp_bd_offset; + qp = qp_y + s->ps.sps->qp_bd_offset; } else { int qp_i, offset; if (c_idx == 1) - offset = s->pps->cb_qp_offset + s->sh.slice_cb_qp_offset; + offset = s->ps.pps->cb_qp_offset + s->sh.slice_cb_qp_offset; else - offset = s->pps->cr_qp_offset + s->sh.slice_cr_qp_offset; + offset = s->ps.pps->cr_qp_offset + s->sh.slice_cr_qp_offset; - qp_i = av_clip_c(qp_y + offset, -s->sps->qp_bd_offset, 57); + qp_i = av_clip(qp_y + offset, -s->ps.sps->qp_bd_offset, 57); if (qp_i < 30) qp = qp_i; else if (qp_i > 43) @@ -955,18 +956,18 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, else qp = qp_c[qp_i - 30]; - qp += s->sps->qp_bd_offset; + qp += s->ps.sps->qp_bd_offset; } - shift = s->sps->bit_depth + log2_trafo_size - 5; + shift = s->ps.sps->bit_depth + log2_trafo_size - 5; add = 1 << (shift - 1); scale = level_scale[rem6[qp]] << (div6[qp]); scale_m = 16; // default when no custom scaling lists. dc_scale = 16; - if (s->sps->scaling_list_enable_flag) { - const ScalingList *sl = s->pps->scaling_list_data_present_flag ? - &s->pps->scaling_list : &s->sps->scaling_list; + if (s->ps.sps->scaling_list_enable_flag) { + const ScalingList *sl = s->ps.pps->scaling_list_data_present_flag ? + &s->ps.pps->scaling_list : &s->ps.sps->scaling_list; int matrix_id = lc->cu.pred_mode != MODE_INTRA; if (log2_trafo_size != 5) @@ -978,7 +979,7 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, } } - if (s->pps->transform_skip_enabled_flag && + if (s->ps.pps->transform_skip_enabled_flag && !lc->cu.cu_transquant_bypass_flag && log2_trafo_size == 2) { transform_skip_flag = ff_hevc_transform_skip_flag_decode(s, c_idx); @@ -1162,7 +1163,7 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, if (first_greater1_coeff_idx != -1) { coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += ff_hevc_coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set); } - if (!s->pps->sign_data_hiding_flag || !sign_hidden) { + if (!s->ps.pps->sign_data_hiding_flag || !sign_hidden) { coeff_sign_flag = ff_hevc_coeff_sign_flag(s, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag); } else { coeff_sign_flag = ff_hevc_coeff_sign_flag(s, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1)); @@ -1180,7 +1181,7 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, if ((trans_coeff_level) > (3 * (1 << c_rice_param))) c_rice_param = FFMIN(c_rice_param + 1, 4); } - if (s->pps->sign_data_hiding_flag && sign_hidden) { + if (s->ps.pps->sign_data_hiding_flag && sign_hidden) { sum_abs += trans_coeff_level; if (n == first_nz_pos_in_cg && ((sum_abs & 1) == 1)) trans_coeff_level = -trans_coeff_level; @@ -1189,7 +1190,7 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, trans_coeff_level = -trans_coeff_level; coeff_sign_flag <<= 1; if (!lc->cu.cu_transquant_bypass_flag) { - if (s->sps->scaling_list_enable_flag) { + if (s->ps.sps->scaling_list_enable_flag) { if (y_c || x_c || log2_trafo_size < 4) { int pos; switch (log2_trafo_size) { @@ -1217,24 +1218,35 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, } } - if (lc->cu.cu_transquant_bypass_flag) { - s->hevcdsp.transquant_bypass[log2_trafo_size - 2](dst, coeffs, stride); - } else { + if (!lc->cu.cu_transquant_bypass_flag) { if (transform_skip_flag) - s->hevcdsp.transform_skip(dst, coeffs, stride); + s->hevcdsp.dequant(coeffs); else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) - s->hevcdsp.transform_4x4_luma_add(dst, coeffs, stride); - else - s->hevcdsp.transform_add[log2_trafo_size - 2](dst, coeffs, stride); + s->hevcdsp.transform_4x4_luma(coeffs); + else { + int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y); + if (max_xy == 0) + s->hevcdsp.idct_dc[log2_trafo_size - 2](coeffs); + else { + int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4; + if (max_xy < 4) + col_limit = FFMIN(4, col_limit); + else if (max_xy < 8) + col_limit = FFMIN(8, col_limit); + else if (max_xy < 12) + col_limit = FFMIN(24, col_limit); + s->hevcdsp.idct[log2_trafo_size - 2](coeffs, col_limit); + } + } } + s->hevcdsp.add_residual[log2_trafo_size - 2](dst, coeffs, stride); } static int hls_transform_unit(HEVCContext *s, int x0, int y0, int xBase, int yBase, int cb_xBase, int cb_yBase, int log2_cb_size, int log2_trafo_size, - int trafo_depth, int blk_idx, - int cbf_luma, int cbf_cb, int cbf_cr) + int blk_idx, int cbf_luma, int cbf_cb, int cbf_cr) { HEVCLocalContext *lc = &s->HEVClc; @@ -1244,12 +1256,12 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); if (log2_trafo_size > 2) { - trafo_size = trafo_size << (s->sps->hshift[1] - 1); + trafo_size = trafo_size << (s->ps.sps->hshift[1] - 1); ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 1); s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 2); } else if (blk_idx == 3) { - trafo_size = trafo_size << s->sps->hshift[1]; + trafo_size = trafo_size << s->ps.sps->hshift[1]; ff_hevc_set_neighbour_available(s, xBase, yBase, trafo_size, trafo_size); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); @@ -1261,21 +1273,21 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, int scan_idx = SCAN_DIAG; int scan_idx_c = SCAN_DIAG; - if (s->pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) { + if (s->ps.pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) { lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s); if (lc->tu.cu_qp_delta != 0) if (ff_hevc_cu_qp_delta_sign_flag(s) == 1) lc->tu.cu_qp_delta = -lc->tu.cu_qp_delta; lc->tu.is_cu_qp_delta_coded = 1; - if (lc->tu.cu_qp_delta < -(26 + s->sps->qp_bd_offset / 2) || - lc->tu.cu_qp_delta > (25 + s->sps->qp_bd_offset / 2)) { + if (lc->tu.cu_qp_delta < -(26 + s->ps.sps->qp_bd_offset / 2) || + lc->tu.cu_qp_delta > (25 + s->ps.sps->qp_bd_offset / 2)) { av_log(s->avctx, AV_LOG_ERROR, "The cu_qp_delta %d is outside the valid range " "[%d, %d].\n", lc->tu.cu_qp_delta, - -(26 + s->sps->qp_bd_offset / 2), - (25 + s->sps->qp_bd_offset / 2)); + -(26 + s->ps.sps->qp_bd_offset / 2), + (25 + s->ps.sps->qp_bd_offset / 2)); return AVERROR_INVALIDDATA; } @@ -1320,11 +1332,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, static void set_deblocking_bypass(HEVCContext *s, int x0, int y0, int log2_cb_size) { int cb_size = 1 << log2_cb_size; - int log2_min_pu_size = s->sps->log2_min_pu_size; + int log2_min_pu_size = s->ps.sps->log2_min_pu_size; - int min_pu_width = s->sps->min_pu_width; - int x_end = FFMIN(x0 + cb_size, s->sps->width); - int y_end = FFMIN(y0 + cb_size, s->sps->height); + int min_pu_width = s->ps.sps->min_pu_width; + int x_end = FFMIN(x0 + cb_size, s->ps.sps->width); + int y_end = FFMIN(y0 + cb_size, s->ps.sps->height); int i, j; for (j = (y0 >> log2_min_pu_size); j < (y_end >> log2_min_pu_size); j++) @@ -1349,18 +1361,18 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[0]; } - if (log2_trafo_size <= s->sps->log2_max_trafo_size && - log2_trafo_size > s->sps->log2_min_tb_size && + if (log2_trafo_size <= s->ps.sps->log2_max_trafo_size && + log2_trafo_size > s->ps.sps->log2_min_tb_size && trafo_depth < lc->cu.max_trafo_depth && !(lc->cu.intra_split_flag && trafo_depth == 0)) { split_transform_flag = ff_hevc_split_transform_flag_decode(s, log2_trafo_size); } else { - int inter_split = s->sps->max_transform_hierarchy_depth_inter == 0 && + int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 && lc->cu.pred_mode == MODE_INTER && lc->cu.part_mode != PART_2Nx2N && trafo_depth == 0; - split_transform_flag = log2_trafo_size > s->sps->log2_max_trafo_size || + split_transform_flag = log2_trafo_size > s->ps.sps->log2_max_trafo_size || (lc->cu.intra_split_flag && trafo_depth == 0) || inter_split; } @@ -1395,9 +1407,9 @@ do { #undef SUBDIVIDE } else { - int min_tu_size = 1 << s->sps->log2_min_tb_size; - int log2_min_tu_size = s->sps->log2_min_tb_size; - int min_tu_width = s->sps->min_tb_width; + int min_tu_size = 1 << s->ps.sps->log2_min_tb_size; + int log2_min_tu_size = s->ps.sps->log2_min_tb_size; + int min_tu_width = s->ps.sps->min_tb_width; int cbf_luma = 1; if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 || @@ -1405,7 +1417,7 @@ do { cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth); ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase, - log2_cb_size, log2_trafo_size, trafo_depth, + log2_cb_size, log2_trafo_size, blk_idx, cbf_luma, cbf_cb, cbf_cr); if (ret < 0) return ret; @@ -1421,7 +1433,7 @@ do { } if (!s->sh.disable_deblocking_filter_flag) { ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size); - if (s->pps->transquant_bypass_enable_flag && + if (s->ps.pps->transquant_bypass_enable_flag && lc->cu.cu_transquant_bypass_flag) set_deblocking_bypass(s, x0, y0, log2_trafo_size); } @@ -1436,13 +1448,13 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) GetBitContext gb; int cb_size = 1 << log2_cb_size; int stride0 = s->frame->linesize[0]; - uint8_t *dst0 = &s->frame->data[0][y0 * stride0 + (x0 << s->sps->pixel_shift)]; + uint8_t *dst0 = &s->frame->data[0][y0 * stride0 + (x0 << s->ps.sps->pixel_shift)]; int stride1 = s->frame->linesize[1]; - uint8_t *dst1 = &s->frame->data[1][(y0 >> s->sps->vshift[1]) * stride1 + ((x0 >> s->sps->hshift[1]) << s->sps->pixel_shift)]; + uint8_t *dst1 = &s->frame->data[1][(y0 >> s->ps.sps->vshift[1]) * stride1 + ((x0 >> s->ps.sps->hshift[1]) << s->ps.sps->pixel_shift)]; int stride2 = s->frame->linesize[2]; - uint8_t *dst2 = &s->frame->data[2][(y0 >> s->sps->vshift[2]) * stride2 + ((x0 >> s->sps->hshift[2]) << s->sps->pixel_shift)]; + uint8_t *dst2 = &s->frame->data[2][(y0 >> s->ps.sps->vshift[2]) * stride2 + ((x0 >> s->ps.sps->hshift[2]) << s->ps.sps->pixel_shift)]; - int length = cb_size * cb_size * s->sps->pcm.bit_depth + ((cb_size * cb_size) >> 1) * s->sps->pcm.bit_depth_chroma; + int length = cb_size * cb_size * s->ps.sps->pcm.bit_depth + ((cb_size * cb_size) >> 1) * s->ps.sps->pcm.bit_depth_chroma; const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3); int ret; @@ -1453,9 +1465,9 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) if (ret < 0) return ret; - s->hevcdsp.put_pcm(dst0, stride0, cb_size, &gb, s->sps->pcm.bit_depth); - s->hevcdsp.put_pcm(dst1, stride1, cb_size / 2, &gb, s->sps->pcm.bit_depth_chroma); - s->hevcdsp.put_pcm(dst2, stride2, cb_size / 2, &gb, s->sps->pcm.bit_depth_chroma); + s->hevcdsp.put_pcm(dst0, stride0, cb_size, &gb, s->ps.sps->pcm.bit_depth); + s->hevcdsp.put_pcm(dst1, stride1, cb_size / 2, &gb, s->ps.sps->pcm.bit_depth_chroma); + s->hevcdsp.put_pcm(dst2, stride2, cb_size / 2, &gb, s->ps.sps->pcm.bit_depth_chroma); return 0; } @@ -1498,13 +1510,13 @@ static void hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size) */ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride, AVFrame *ref, const Mv *mv, int x_off, int y_off, - int block_w, int block_h) + int block_w, int block_h, int pred_idx) { HEVCLocalContext *lc = &s->HEVClc; uint8_t *src = ref->data[0]; ptrdiff_t srcstride = ref->linesize[0]; - int pic_width = s->sps->width; - int pic_height = s->sps->height; + int pic_width = s->ps.sps->width; + int pic_height = s->ps.sps->height; int mx = mv->x & 3; int my = mv->y & 3; @@ -1513,15 +1525,15 @@ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride, x_off += mv->x >> 2; y_off += mv->y >> 2; - src += y_off * srcstride + (x_off << s->sps->pixel_shift); + src += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift)); if (x_off < extra_left || y_off < extra_top || x_off >= pic_width - block_w - ff_hevc_qpel_extra_after[mx] || y_off >= pic_height - block_h - ff_hevc_qpel_extra_after[my]) { - const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift; - int offset = extra_top * srcstride + (extra_left << s->sps->pixel_shift); + const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; + int offset = extra_top * srcstride + (extra_left << s->ps.sps->pixel_shift); int buf_offset = extra_top * - edge_emu_stride + (extra_left << s->sps->pixel_shift); + edge_emu_stride + (extra_left << s->ps.sps->pixel_shift); s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src - offset, edge_emu_stride, srcstride, @@ -1532,8 +1544,8 @@ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride, src = lc->edge_emu_buffer + buf_offset; srcstride = edge_emu_stride; } - s->hevcdsp.put_hevc_qpel[my][mx](dst, dststride, src, srcstride, block_w, - block_h, lc->mc_buffer); + s->hevcdsp.put_hevc_qpel[!!my][!!mx][pred_idx](dst, dststride, src, srcstride, + block_h, mx, my, lc->mc_buffer); } /** @@ -1552,34 +1564,34 @@ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride, */ static void chroma_mc(HEVCContext *s, int16_t *dst1, int16_t *dst2, ptrdiff_t dststride, AVFrame *ref, const Mv *mv, - int x_off, int y_off, int block_w, int block_h) + int x_off, int y_off, int block_w, int block_h, int pred_idx) { HEVCLocalContext *lc = &s->HEVClc; uint8_t *src1 = ref->data[1]; uint8_t *src2 = ref->data[2]; ptrdiff_t src1stride = ref->linesize[1]; ptrdiff_t src2stride = ref->linesize[2]; - int pic_width = s->sps->width >> 1; - int pic_height = s->sps->height >> 1; + int pic_width = s->ps.sps->width >> 1; + int pic_height = s->ps.sps->height >> 1; int mx = mv->x & 7; int my = mv->y & 7; x_off += mv->x >> 3; y_off += mv->y >> 3; - src1 += y_off * src1stride + (x_off << s->sps->pixel_shift); - src2 += y_off * src2stride + (x_off << s->sps->pixel_shift); + src1 += y_off * src1stride + (x_off * (1 << s->ps.sps->pixel_shift)); + src2 += y_off * src2stride + (x_off * (1 << s->ps.sps->pixel_shift)); if (x_off < EPEL_EXTRA_BEFORE || y_off < EPEL_EXTRA_AFTER || x_off >= pic_width - block_w - EPEL_EXTRA_AFTER || y_off >= pic_height - block_h - EPEL_EXTRA_AFTER) { - const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift; - int offset1 = EPEL_EXTRA_BEFORE * (src1stride + (1 << s->sps->pixel_shift)); + const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; + int offset1 = EPEL_EXTRA_BEFORE * (src1stride + (1 << s->ps.sps->pixel_shift)); int buf_offset1 = EPEL_EXTRA_BEFORE * - (edge_emu_stride + (1 << s->sps->pixel_shift)); - int offset2 = EPEL_EXTRA_BEFORE * (src2stride + (1 << s->sps->pixel_shift)); + (edge_emu_stride + (1 << s->ps.sps->pixel_shift)); + int offset2 = EPEL_EXTRA_BEFORE * (src2stride + (1 << s->ps.sps->pixel_shift)); int buf_offset2 = EPEL_EXTRA_BEFORE * - (edge_emu_stride + (1 << s->sps->pixel_shift)); + (edge_emu_stride + (1 << s->ps.sps->pixel_shift)); s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src1 - offset1, edge_emu_stride, src1stride, @@ -1590,8 +1602,8 @@ static void chroma_mc(HEVCContext *s, int16_t *dst1, int16_t *dst2, src1 = lc->edge_emu_buffer + buf_offset1; src1stride = edge_emu_stride; - s->hevcdsp.put_hevc_epel[!!my][!!mx](dst1, dststride, src1, src1stride, - block_w, block_h, mx, my, lc->mc_buffer); + s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst1, dststride, src1, src1stride, + block_h, mx, my, lc->mc_buffer); s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src2 - offset2, edge_emu_stride, src2stride, @@ -1602,16 +1614,13 @@ static void chroma_mc(HEVCContext *s, int16_t *dst1, int16_t *dst2, src2 = lc->edge_emu_buffer + buf_offset2; src2stride = edge_emu_stride; - s->hevcdsp.put_hevc_epel[!!my][!!mx](dst2, dststride, src2, src2stride, - block_w, block_h, mx, my, - lc->mc_buffer); + s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst2, dststride, src2, src2stride, + block_h, mx, my, lc->mc_buffer); } else { - s->hevcdsp.put_hevc_epel[!!my][!!mx](dst1, dststride, src1, src1stride, - block_w, block_h, mx, my, - lc->mc_buffer); - s->hevcdsp.put_hevc_epel[!!my][!!mx](dst2, dststride, src2, src2stride, - block_w, block_h, mx, my, - lc->mc_buffer); + s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst1, dststride, src1, src1stride, + block_h, mx, my, lc->mc_buffer); + s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst2, dststride, src2, src2stride, + block_h, mx, my, lc->mc_buffer); } } @@ -1622,120 +1631,108 @@ static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref, ff_thread_await_progress(&ref->tf, y, 0); } +static void hevc_luma_mv_mpv_mode(HEVCContext *s, int x0, int y0, int nPbW, + int nPbH, int log2_cb_size, int part_idx, + int merge_idx, MvField *mv) +{ + HEVCLocalContext *lc = &s->HEVClc; + enum InterPredIdc inter_pred_idc = PRED_L0; + int mvp_flag; + + ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH); + if (s->sh.slice_type == B_SLICE) + inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH); + + if (inter_pred_idc != PRED_L1) { + if (s->sh.nb_refs[L0]) + mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]); + + mv->pred_flag[0] = 1; + hls_mvd_coding(s, x0, y0, 0); + mvp_flag = ff_hevc_mvp_lx_flag_decode(s); + ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, + part_idx, merge_idx, mv, mvp_flag, 0); + mv->mv[0].x += lc->pu.mvd.x; + mv->mv[0].y += lc->pu.mvd.y; + } + + if (inter_pred_idc != PRED_L0) { + if (s->sh.nb_refs[L1]) + mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]); + + if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) { + AV_ZERO32(&lc->pu.mvd); + } else { + hls_mvd_coding(s, x0, y0, 1); + } + + mv->pred_flag[1] = 1; + mvp_flag = ff_hevc_mvp_lx_flag_decode(s); + ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, + part_idx, merge_idx, mv, mvp_flag, 1); + mv->mv[1].x += lc->pu.mvd.x; + mv->mv[1].y += lc->pu.mvd.y; + } +} + static void hls_prediction_unit(HEVCContext *s, int x0, int y0, int nPbW, int nPbH, int log2_cb_size, int partIdx) { + static const int pred_indices[] = { + [4] = 0, [8] = 1, [12] = 2, [16] = 3, [24] = 4, [32] = 5, [48] = 6, [64] = 7, + }; + const int pred_idx = pred_indices[nPbW]; + #define POS(c_idx, x, y) \ - &s->frame->data[c_idx][((y) >> s->sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \ - (((x) >> s->sps->hshift[c_idx]) << s->sps->pixel_shift)] + &s->frame->data[c_idx][((y) >> s->ps.sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \ + (((x) >> s->ps.sps->hshift[c_idx]) << s->ps.sps->pixel_shift)] HEVCLocalContext *lc = &s->HEVClc; int merge_idx = 0; struct MvField current_mv = {{{ 0 }}}; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; MvField *tab_mvf = s->ref->tab_mvf; RefPicList *refPicList = s->ref->refPicList; HEVCFrame *ref0, *ref1; - int tmpstride = MAX_PB_SIZE; + int tmpstride = MAX_PB_SIZE * sizeof(int16_t); uint8_t *dst0 = POS(0, x0, y0); uint8_t *dst1 = POS(1, x0, y0); uint8_t *dst2 = POS(2, x0, y0); - int log2_min_cb_size = s->sps->log2_min_cb_size; - int min_cb_width = s->sps->min_cb_width; + int log2_min_cb_size = s->ps.sps->log2_min_cb_size; + int min_cb_width = s->ps.sps->min_cb_width; int x_cb = x0 >> log2_min_cb_size; int y_cb = y0 >> log2_min_cb_size; - int ref_idx[2]; - int mvp_flag[2]; int x_pu, y_pu; int i, j; - if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) { + int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb); + + if (!skip_flag) + lc->pu.merge_flag = ff_hevc_merge_flag_decode(s); + + if (skip_flag || lc->pu.merge_flag) { if (s->sh.max_num_merge_cand > 1) merge_idx = ff_hevc_merge_idx_decode(s); else merge_idx = 0; - ff_hevc_luma_mv_merge_mode(s, x0, y0, - 1 << log2_cb_size, - 1 << log2_cb_size, - log2_cb_size, partIdx, - merge_idx, ¤t_mv); - x_pu = x0 >> s->sps->log2_min_pu_size; - y_pu = y0 >> s->sps->log2_min_pu_size; - - for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; - } else { /* MODE_INTER */ - lc->pu.merge_flag = ff_hevc_merge_flag_decode(s); - if (lc->pu.merge_flag) { - if (s->sh.max_num_merge_cand > 1) - merge_idx = ff_hevc_merge_idx_decode(s); - else - merge_idx = 0; - - ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, - partIdx, merge_idx, ¤t_mv); - x_pu = x0 >> s->sps->log2_min_pu_size; - y_pu = y0 >> s->sps->log2_min_pu_size; - - for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; - } else { - enum InterPredIdc inter_pred_idc = PRED_L0; - ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH); - if (s->sh.slice_type == B_SLICE) - inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH); - - if (inter_pred_idc != PRED_L1) { - if (s->sh.nb_refs[L0]) { - ref_idx[0] = ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]); - current_mv.ref_idx[0] = ref_idx[0]; - } - current_mv.pred_flag[0] = 1; - hls_mvd_coding(s, x0, y0, 0); - mvp_flag[0] = ff_hevc_mvp_lx_flag_decode(s); - ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, - partIdx, merge_idx, ¤t_mv, - mvp_flag[0], 0); - current_mv.mv[0].x += lc->pu.mvd.x; - current_mv.mv[0].y += lc->pu.mvd.y; - } - - if (inter_pred_idc != PRED_L0) { - if (s->sh.nb_refs[L1]) { - ref_idx[1] = ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]); - current_mv.ref_idx[1] = ref_idx[1]; - } - - if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) { - AV_ZERO32(&lc->pu.mvd); - } else { - hls_mvd_coding(s, x0, y0, 1); - } - - current_mv.pred_flag[1] = 1; - mvp_flag[1] = ff_hevc_mvp_lx_flag_decode(s); - ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, - partIdx, merge_idx, ¤t_mv, - mvp_flag[1], 1); - current_mv.mv[1].x += lc->pu.mvd.x; - current_mv.mv[1].y += lc->pu.mvd.y; - } + ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, + partIdx, merge_idx, ¤t_mv); + } else { + hevc_luma_mv_mpv_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, + partIdx, merge_idx, ¤t_mv); + } - x_pu = x0 >> s->sps->log2_min_pu_size; - y_pu = y0 >> s->sps->log2_min_pu_size; + x_pu = x0 >> s->ps.sps->log2_min_pu_size; + y_pu = y0 >> s->ps.sps->log2_min_pu_size; - for(j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) - for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) - tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; - } - } + for (j = 0; j < nPbH >> s->ps.sps->log2_min_pu_size; j++) + for (i = 0; i < nPbW >> s->ps.sps->log2_min_pu_size; i++) + tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; if (current_mv.pred_flag[0]) { ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; @@ -1755,129 +1752,121 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); luma_mc(s, tmp, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0, y0, nPbW, nPbH); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred(s->sh.luma_log2_weight_denom, - s->sh.luma_weight_l0[current_mv.ref_idx[0]], - s->sh.luma_offset_l0[current_mv.ref_idx[0]], - dst0, s->frame->linesize[0], tmp, - tmpstride, nPbW, nPbH); + ¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred[pred_idx](s->sh.luma_log2_weight_denom, + s->sh.luma_weight_l0[current_mv.ref_idx[0]], + s->sh.luma_offset_l0[current_mv.ref_idx[0]], + dst0, s->frame->linesize[0], tmp, + tmpstride, nPbH); } else { - s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp, tmpstride, nPbW, nPbH); + s->hevcdsp.put_unweighted_pred[pred_idx](dst0, s->frame->linesize[0], tmp, tmpstride, nPbH); } chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], - s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0], - dst1, s->frame->linesize[1], tmp, tmpstride, - nPbW / 2, nPbH / 2); - s->hevcdsp.weighted_pred(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], - s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1], - dst2, s->frame->linesize[2], tmp2, tmpstride, - nPbW / 2, nPbH / 2); + ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], + s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0], + dst1, s->frame->linesize[1], tmp, tmpstride, + nPbH / 2); + s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], + s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1], + dst2, s->frame->linesize[2], tmp2, tmpstride, + nPbH / 2); } else { - s->hevcdsp.put_unweighted_pred(dst1, s->frame->linesize[1], tmp, tmpstride, nPbW/2, nPbH/2); - s->hevcdsp.put_unweighted_pred(dst2, s->frame->linesize[2], tmp2, tmpstride, nPbW/2, nPbH/2); + s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmpstride, nPbH / 2); + s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2); } } else if (!current_mv.pred_flag[0] && current_mv.pred_flag[1]) { DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); - if (!ref1) - return; - luma_mc(s, tmp, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0, y0, nPbW, nPbH); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred(s->sh.luma_log2_weight_denom, - s->sh.luma_weight_l1[current_mv.ref_idx[1]], - s->sh.luma_offset_l1[current_mv.ref_idx[1]], - dst0, s->frame->linesize[0], tmp, tmpstride, - nPbW, nPbH); + ¤t_mv.mv[1], x0, y0, nPbW, nPbH, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred[pred_idx](s->sh.luma_log2_weight_denom, + s->sh.luma_weight_l1[current_mv.ref_idx[1]], + s->sh.luma_offset_l1[current_mv.ref_idx[1]], + dst0, s->frame->linesize[0], tmp, tmpstride, + nPbH); } else { - s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp, tmpstride, nPbW, nPbH); + s->hevcdsp.put_unweighted_pred[pred_idx](dst0, s->frame->linesize[0], tmp, tmpstride, nPbH); } chroma_mc(s, tmp, tmp2, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0/2, y0/2, nPbW/2, nPbH/2); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], - s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0], - dst1, s->frame->linesize[1], tmp, tmpstride, nPbW/2, nPbH/2); - s->hevcdsp.weighted_pred(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], - s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1], - dst2, s->frame->linesize[2], tmp2, tmpstride, nPbW/2, nPbH/2); + ¤t_mv.mv[1], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], + s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0], + dst1, s->frame->linesize[1], tmp, tmpstride, nPbH/2); + s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], + s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1], + dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH/2); } else { - s->hevcdsp.put_unweighted_pred(dst1, s->frame->linesize[1], tmp, tmpstride, nPbW/2, nPbH/2); - s->hevcdsp.put_unweighted_pred(dst2, s->frame->linesize[2], tmp2, tmpstride, nPbW/2, nPbH/2); + s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmpstride, nPbH / 2); + s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2); } } else if (current_mv.pred_flag[0] && current_mv.pred_flag[1]) { DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); DECLARE_ALIGNED(16, int16_t, tmp3[MAX_PB_SIZE * MAX_PB_SIZE]); DECLARE_ALIGNED(16, int16_t, tmp4[MAX_PB_SIZE * MAX_PB_SIZE]); - HEVCFrame *ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; - HEVCFrame *ref1 = refPicList[1].ref[current_mv.ref_idx[1]]; - - if (!ref0 || !ref1) - return; luma_mc(s, tmp, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0, y0, nPbW, nPbH); + ¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx); luma_mc(s, tmp2, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0, y0, nPbW, nPbH); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred_avg(s->sh.luma_log2_weight_denom, - s->sh.luma_weight_l0[current_mv.ref_idx[0]], - s->sh.luma_weight_l1[current_mv.ref_idx[1]], - s->sh.luma_offset_l0[current_mv.ref_idx[0]], - s->sh.luma_offset_l1[current_mv.ref_idx[1]], - dst0, s->frame->linesize[0], - tmp, tmp2, tmpstride, nPbW, nPbH); + ¤t_mv.mv[1], x0, y0, nPbW, nPbH, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred_avg[pred_idx](s->sh.luma_log2_weight_denom, + s->sh.luma_weight_l0[current_mv.ref_idx[0]], + s->sh.luma_weight_l1[current_mv.ref_idx[1]], + s->sh.luma_offset_l0[current_mv.ref_idx[0]], + s->sh.luma_offset_l1[current_mv.ref_idx[1]], + dst0, s->frame->linesize[0], + tmp, tmp2, tmpstride, nPbH); } else { - s->hevcdsp.put_weighted_pred_avg(dst0, s->frame->linesize[0], - tmp, tmp2, tmpstride, nPbW, nPbH); + s->hevcdsp.put_unweighted_pred_avg[pred_idx](dst0, s->frame->linesize[0], + tmp, tmp2, tmpstride, nPbH); } chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame, - ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2); + ¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx); chroma_mc(s, tmp3, tmp4, tmpstride, ref1->frame, - ¤t_mv.mv[1], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2); - - if ((s->sh.slice_type == P_SLICE && s->pps->weighted_pred_flag) || - (s->sh.slice_type == B_SLICE && s->pps->weighted_bipred_flag)) { - s->hevcdsp.weighted_pred_avg(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], - s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], - s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0], - s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0], - dst1, s->frame->linesize[1], tmp, tmp3, - tmpstride, nPbW / 2, nPbH / 2); - s->hevcdsp.weighted_pred_avg(s->sh.chroma_log2_weight_denom, - s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], - s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], - s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1], - s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1], - dst2, s->frame->linesize[2], tmp2, tmp4, - tmpstride, nPbW / 2, nPbH / 2); + ¤t_mv.mv[1], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx); + + if ((s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || + (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag)) { + s->hevcdsp.weighted_pred_avg_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], + s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0], + s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0], + dst1, s->frame->linesize[1], tmp, tmp3, + tmpstride, nPbH / 2); + s->hevcdsp.weighted_pred_avg_chroma[pred_idx](s->sh.chroma_log2_weight_denom, + s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], + s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], + s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1], + s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1], + dst2, s->frame->linesize[2], tmp2, tmp4, + tmpstride, nPbH / 2); } else { - s->hevcdsp.put_weighted_pred_avg(dst1, s->frame->linesize[1], tmp, tmp3, tmpstride, nPbW/2, nPbH/2); - s->hevcdsp.put_weighted_pred_avg(dst2, s->frame->linesize[2], tmp2, tmp4, tmpstride, nPbW/2, nPbH/2); + s->hevcdsp.put_unweighted_pred_avg_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmp3, tmpstride, nPbH/2); + s->hevcdsp.put_unweighted_pred_avg_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmp4, tmpstride, nPbH/2); } } } @@ -1889,19 +1878,19 @@ static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size, int prev_intra_luma_pred_flag) { HEVCLocalContext *lc = &s->HEVClc; - int x_pu = x0 >> s->sps->log2_min_pu_size; - int y_pu = y0 >> s->sps->log2_min_pu_size; - int min_pu_width = s->sps->min_pu_width; - int size_in_pus = pu_size >> s->sps->log2_min_pu_size; - int x0b = x0 & ((1 << s->sps->log2_ctb_size) - 1); - int y0b = y0 & ((1 << s->sps->log2_ctb_size) - 1); + int x_pu = x0 >> s->ps.sps->log2_min_pu_size; + int y_pu = y0 >> s->ps.sps->log2_min_pu_size; + int min_pu_width = s->ps.sps->min_pu_width; + int size_in_pus = pu_size >> s->ps.sps->log2_min_pu_size; + int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1); int cand_up = (lc->ctb_up_flag || y0b) ? s->tab_ipm[(y_pu - 1) * min_pu_width + x_pu] : INTRA_DC; int cand_left = (lc->ctb_left_flag || x0b) ? s->tab_ipm[y_pu * min_pu_width + x_pu - 1] : INTRA_DC; - int y_ctb = (y0 >> (s->sps->log2_ctb_size)) << (s->sps->log2_ctb_size); + int y_ctb = (y0 >> (s->ps.sps->log2_ctb_size)) << (s->ps.sps->log2_ctb_size); MvField *tab_mvf = s->ref->tab_mvf; int intra_pred_mode; @@ -1976,13 +1965,13 @@ static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size, static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0, int log2_cb_size, int ct_depth) { - int length = (1 << log2_cb_size) >> s->sps->log2_min_cb_size; - int x_cb = x0 >> s->sps->log2_min_cb_size; - int y_cb = y0 >> s->sps->log2_min_cb_size; + int length = (1 << log2_cb_size) >> s->ps.sps->log2_min_cb_size; + int x_cb = x0 >> s->ps.sps->log2_min_cb_size; + int y_cb = y0 >> s->ps.sps->log2_min_cb_size; int y; for (y = 0; y < length; y++) - memset(&s->tab_ct_depth[(y_cb + y) * s->sps->min_cb_width + x_cb], + memset(&s->tab_ct_depth[(y_cb + y) * s->ps.sps->min_cb_width + x_cb], ct_depth, length); } @@ -2032,11 +2021,11 @@ static void intra_prediction_unit_default_value(HEVCContext *s, { HEVCLocalContext *lc = &s->HEVClc; int pb_size = 1 << log2_cb_size; - int size_in_pus = pb_size >> s->sps->log2_min_pu_size; - int min_pu_width = s->sps->min_pu_width; + int size_in_pus = pb_size >> s->ps.sps->log2_min_pu_size; + int min_pu_width = s->ps.sps->min_pu_width; MvField *tab_mvf = s->ref->tab_mvf; - int x_pu = x0 >> s->sps->log2_min_pu_size; - int y_pu = y0 >> s->sps->log2_min_pu_size; + int x_pu = x0 >> s->ps.sps->log2_min_pu_size; + int y_pu = y0 >> s->ps.sps->log2_min_pu_size; int j, k; if (size_in_pus == 0) @@ -2052,25 +2041,23 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) { int cb_size = 1 << log2_cb_size; HEVCLocalContext *lc = &s->HEVClc; - int log2_min_cb_size = s->sps->log2_min_cb_size; + int log2_min_cb_size = s->ps.sps->log2_min_cb_size; int length = cb_size >> log2_min_cb_size; - int min_cb_width = s->sps->min_cb_width; + int min_cb_width = s->ps.sps->min_cb_width; int x_cb = x0 >> log2_min_cb_size; int y_cb = y0 >> log2_min_cb_size; int x, y, ret; lc->cu.x = x0; lc->cu.y = y0; - lc->cu.rqt_root_cbf = 1; lc->cu.pred_mode = MODE_INTRA; lc->cu.part_mode = PART_2Nx2N; lc->cu.intra_split_flag = 0; - lc->cu.pcm_flag = 0; SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0; for (x = 0; x < 4; x++) lc->pu.intra_pred_mode[x] = 1; - if (s->pps->transquant_bypass_enable_flag) { + if (s->ps.pps->transquant_bypass_enable_flag) { lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(s); if (lc->cu.cu_transquant_bypass_flag) set_deblocking_bypass(s, x0, y0, log2_cb_size); @@ -2080,7 +2067,6 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) if (s->sh.slice_type != I_SLICE) { uint8_t skip_flag = ff_hevc_skip_flag_decode(s, x0, y0, x_cb, y_cb); - lc->cu.pred_mode = MODE_SKIP; x = y_cb * min_cb_width + x_cb; for (y = 0; y < length; y++) { memset(&s->skip_flag[x], skip_flag, length); @@ -2096,25 +2082,27 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) if (!s->sh.disable_deblocking_filter_flag) ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); } else { + int pcm_flag = 0; + if (s->sh.slice_type != I_SLICE) lc->cu.pred_mode = ff_hevc_pred_mode_decode(s); if (lc->cu.pred_mode != MODE_INTRA || - log2_cb_size == s->sps->log2_min_cb_size) { + log2_cb_size == s->ps.sps->log2_min_cb_size) { lc->cu.part_mode = ff_hevc_part_mode_decode(s, log2_cb_size); lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN && lc->cu.pred_mode == MODE_INTRA; } if (lc->cu.pred_mode == MODE_INTRA) { - if (lc->cu.part_mode == PART_2Nx2N && s->sps->pcm_enabled_flag && - log2_cb_size >= s->sps->pcm.log2_min_pcm_cb_size && - log2_cb_size <= s->sps->pcm.log2_max_pcm_cb_size) { - lc->cu.pcm_flag = ff_hevc_pcm_flag_decode(s); + if (lc->cu.part_mode == PART_2Nx2N && s->ps.sps->pcm_enabled_flag && + log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size && + log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size) { + pcm_flag = ff_hevc_pcm_flag_decode(s); } - if (lc->cu.pcm_flag) { + if (pcm_flag) { intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); ret = hls_pcm_sample(s, x0, y0, log2_cb_size); - if (s->sps->pcm.loop_filter_disable_flag) + if (s->ps.sps->pcm.loop_filter_disable_flag) set_deblocking_bypass(s, x0, y0, log2_cb_size); if (ret < 0) @@ -2161,15 +2149,17 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) } } - if (!lc->cu.pcm_flag) { + if (!pcm_flag) { + int rqt_root_cbf = 1; + if (lc->cu.pred_mode != MODE_INTRA && !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) { - lc->cu.rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s); + rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s); } - if (lc->cu.rqt_root_cbf) { + if (rqt_root_cbf) { lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ? - s->sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag : - s->sps->max_transform_hierarchy_depth_inter; + s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag : + s->ps.sps->max_transform_hierarchy_depth_inter; ret = hls_transform_tree(s, x0, y0, x0, y0, x0, y0, log2_cb_size, log2_cb_size, 0, 0, 0, 0); @@ -2182,7 +2172,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) } } - if (s->pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0) + if (s->ps.pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0) ff_hevc_set_qPy(s, x0, y0, x0, y0, log2_cb_size); x = y_cb * min_cb_width + x_cb; @@ -2204,15 +2194,15 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, int split_cu; lc->ct.depth = cb_depth; - if (x0 + cb_size <= s->sps->width && - y0 + cb_size <= s->sps->height && - log2_cb_size > s->sps->log2_min_cb_size) { + if (x0 + cb_size <= s->ps.sps->width && + y0 + cb_size <= s->ps.sps->height && + log2_cb_size > s->ps.sps->log2_min_cb_size) { split_cu = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0); } else { - split_cu = (log2_cb_size > s->sps->log2_min_cb_size); + split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size); } - if (s->pps->cu_qp_delta_enabled_flag && - log2_cb_size >= s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth) { + if (s->ps.pps->cu_qp_delta_enabled_flag && + log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth) { lc->tu.is_cu_qp_delta_coded = 0; lc->tu.cu_qp_delta = 0; } @@ -2227,7 +2217,7 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, #define SUBDIVIDE(x, y) \ do { \ - if (x < s->sps->width && y < s->sps->height) { \ + if (x < s->ps.sps->width && y < s->ps.sps->height) { \ int ret = hls_coding_quadtree(s, x, y, log2_cb_size, cb_depth);\ if (ret < 0) \ return ret; \ @@ -2251,77 +2241,77 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, int ctb_addr_ts) { HEVCLocalContext *lc = &s->HEVClc; - int ctb_size = 1 << s->sps->log2_ctb_size; - int ctb_addr_rs = s->pps->ctb_addr_ts_to_rs[ctb_addr_ts]; + int ctb_size = 1 << s->ps.sps->log2_ctb_size; + int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; int ctb_addr_in_slice = ctb_addr_rs - s->sh.slice_addr; s->tab_slice_address[ctb_addr_rs] = s->sh.slice_addr; - if (s->pps->entropy_coding_sync_enabled_flag) { + if (s->ps.pps->entropy_coding_sync_enabled_flag) { if (x_ctb == 0 && (y_ctb & (ctb_size - 1)) == 0) lc->first_qp_group = 1; - lc->end_of_tiles_x = s->sps->width; - } else if (s->pps->tiles_enabled_flag) { - if (ctb_addr_ts && s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[ctb_addr_ts - 1]) { - int idxX = s->pps->col_idxX[x_ctb >> s->sps->log2_ctb_size]; + lc->end_of_tiles_x = s->ps.sps->width; + } else if (s->ps.pps->tiles_enabled_flag) { + if (ctb_addr_ts && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) { + int idxX = s->ps.pps->col_idxX[x_ctb >> s->ps.sps->log2_ctb_size]; lc->start_of_tiles_x = x_ctb; - lc->end_of_tiles_x = x_ctb + (s->pps->column_width[idxX] << s->sps->log2_ctb_size); + lc->end_of_tiles_x = x_ctb + (s->ps.pps->column_width[idxX] << s->ps.sps->log2_ctb_size); lc->first_qp_group = 1; } } else { - lc->end_of_tiles_x = s->sps->width; + lc->end_of_tiles_x = s->ps.sps->width; } - lc->end_of_tiles_y = FFMIN(y_ctb + ctb_size, s->sps->height); + lc->end_of_tiles_y = FFMIN(y_ctb + ctb_size, s->ps.sps->height); lc->boundary_flags = 0; - if (s->pps->tiles_enabled_flag) { - if (x_ctb > 0 && s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs - 1]]) + if (s->ps.pps->tiles_enabled_flag) { + if (x_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - 1]]) lc->boundary_flags |= BOUNDARY_LEFT_TILE; if (x_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - 1]) lc->boundary_flags |= BOUNDARY_LEFT_SLICE; - if (y_ctb > 0 && s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->sps->ctb_width]]) + if (y_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]]) lc->boundary_flags |= BOUNDARY_UPPER_TILE; - if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - s->sps->ctb_width]) + if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - s->ps.sps->ctb_width]) lc->boundary_flags |= BOUNDARY_UPPER_SLICE; } else { - if (!ctb_addr_in_slice > 0) + if (!ctb_addr_in_slice) lc->boundary_flags |= BOUNDARY_LEFT_SLICE; - if (ctb_addr_in_slice < s->sps->ctb_width) + if (ctb_addr_in_slice < s->ps.sps->ctb_width) lc->boundary_flags |= BOUNDARY_UPPER_SLICE; } lc->ctb_left_flag = ((x_ctb > 0) && (ctb_addr_in_slice > 0) && !(lc->boundary_flags & BOUNDARY_LEFT_TILE)); - lc->ctb_up_flag = ((y_ctb > 0) && (ctb_addr_in_slice >= s->sps->ctb_width) && !(lc->boundary_flags & BOUNDARY_UPPER_TILE)); - lc->ctb_up_right_flag = ((y_ctb > 0) && (ctb_addr_in_slice+1 >= s->sps->ctb_width) && (s->pps->tile_id[ctb_addr_ts] == s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs+1 - s->sps->ctb_width]])); - lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->sps->ctb_width) && (s->pps->tile_id[ctb_addr_ts] == s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->sps->ctb_width]])); + lc->ctb_up_flag = ((y_ctb > 0) && (ctb_addr_in_slice >= s->ps.sps->ctb_width) && !(lc->boundary_flags & BOUNDARY_UPPER_TILE)); + lc->ctb_up_right_flag = ((y_ctb > 0) && (ctb_addr_in_slice+1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs+1 - s->ps.sps->ctb_width]])); + lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]])); } static int hls_slice_data(HEVCContext *s) { - int ctb_size = 1 << s->sps->log2_ctb_size; + int ctb_size = 1 << s->ps.sps->log2_ctb_size; int more_data = 1; int x_ctb = 0; int y_ctb = 0; - int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; + int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; int ret; - while (more_data && ctb_addr_ts < s->sps->ctb_size) { - int ctb_addr_rs = s->pps->ctb_addr_ts_to_rs[ctb_addr_ts]; + while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) { + int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; - x_ctb = (ctb_addr_rs % ((s->sps->width + ctb_size - 1) >> s->sps->log2_ctb_size)) << s->sps->log2_ctb_size; - y_ctb = (ctb_addr_rs / ((s->sps->width + ctb_size - 1) >> s->sps->log2_ctb_size)) << s->sps->log2_ctb_size; + x_ctb = (ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; + y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts); ff_hevc_cabac_init(s, ctb_addr_ts); - hls_sao_param(s, x_ctb >> s->sps->log2_ctb_size, y_ctb >> s->sps->log2_ctb_size); + hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size); s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset; s->deblock[ctb_addr_rs].tc_offset = s->sh.tc_offset; s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; - ret = hls_coding_quadtree(s, x_ctb, y_ctb, s->sps->log2_ctb_size, 0); + ret = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); if (ret < 0) return ret; more_data = !ff_hevc_end_of_slice_flag_decode(s); @@ -2331,55 +2321,29 @@ static int hls_slice_data(HEVCContext *s) ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size); } - if (x_ctb + ctb_size >= s->sps->width && - y_ctb + ctb_size >= s->sps->height) + if (x_ctb + ctb_size >= s->ps.sps->width && + y_ctb + ctb_size >= s->ps.sps->height) ff_hevc_hls_filter(s, x_ctb, y_ctb); return ctb_addr_ts; } -/** - * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, - * 0 if the unit should be skipped, 1 otherwise - */ -static int hls_nal_unit(HEVCContext *s) -{ - GetBitContext *gb = &s->HEVClc.gb; - int nuh_layer_id; - - if (get_bits1(gb) != 0) - return AVERROR_INVALIDDATA; - - s->nal_unit_type = get_bits(gb, 6); - - nuh_layer_id = get_bits(gb, 6); - s->temporal_id = get_bits(gb, 3) - 1; - if (s->temporal_id < 0) - return AVERROR_INVALIDDATA; - - av_log(s->avctx, AV_LOG_DEBUG, - "nal_unit_type: %d, nuh_layer_id: %dtemporal_id: %d\n", - s->nal_unit_type, nuh_layer_id, s->temporal_id); - - return nuh_layer_id == 0; -} - static void restore_tqb_pixels(HEVCContext *s) { - int min_pu_size = 1 << s->sps->log2_min_pu_size; + int min_pu_size = 1 << s->ps.sps->log2_min_pu_size; int x, y, c_idx; for (c_idx = 0; c_idx < 3; c_idx++) { ptrdiff_t stride = s->frame->linesize[c_idx]; - int hshift = s->sps->hshift[c_idx]; - int vshift = s->sps->vshift[c_idx]; - for (y = 0; y < s->sps->min_pu_height; y++) { - for (x = 0; x < s->sps->min_pu_width; x++) { - if (s->is_pcm[y * s->sps->min_pu_width + x]) { + int hshift = s->ps.sps->hshift[c_idx]; + int vshift = s->ps.sps->vshift[c_idx]; + for (y = 0; y < s->ps.sps->min_pu_height; y++) { + for (x = 0; x < s->ps.sps->min_pu_width; x++) { + if (s->is_pcm[y * s->ps.sps->min_pu_width + x]) { int n; int len = min_pu_size >> hshift; - uint8_t *src = &s->frame->data[c_idx][((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)]; - uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)]; + uint8_t *src = &s->frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)]; + uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)]; for (n = 0; n < (min_pu_size >> vshift); n++) { memcpy(dst, src, len); src += stride; @@ -2447,17 +2411,17 @@ static int hevc_frame_start(HEVCContext *s) memset(s->horizontal_bs, 0, 2 * s->bs_width * (s->bs_height + 1)); memset(s->vertical_bs, 0, 2 * s->bs_width * (s->bs_height + 1)); - memset(s->cbf_luma, 0, s->sps->min_tb_width * s->sps->min_tb_height); - memset(s->is_pcm, 0, s->sps->min_pu_width * s->sps->min_pu_height); + memset(s->cbf_luma, 0, s->ps.sps->min_tb_width * s->ps.sps->min_tb_height); + memset(s->is_pcm, 0, s->ps.sps->min_pu_width * s->ps.sps->min_pu_height); lc->start_of_tiles_x = 0; s->is_decoded = 0; s->first_nal_type = s->nal_unit_type; - if (s->pps->tiles_enabled_flag) - lc->end_of_tiles_x = s->pps->column_width[0] << s->sps->log2_ctb_size; + if (s->ps.pps->tiles_enabled_flag) + lc->end_of_tiles_x = s->ps.pps->column_width[0] << s->ps.sps->log2_ctb_size; - ret = ff_hevc_set_new_ref(s, s->sps->sao_enabled ? &s->sao_frame : &s->frame, + ret = ff_hevc_set_new_ref(s, s->ps.sps->sao_enabled ? &s->sao_frame : &s->frame, s->poc); if (ret < 0) goto fail; @@ -2485,42 +2449,35 @@ static int hevc_frame_start(HEVCContext *s) fail: if (s->ref) - ff_thread_report_progress(&s->ref->tf, INT_MAX, 0); + ff_hevc_unref_frame(s, s->ref, ~0); s->ref = NULL; return ret; } -static int decode_nal_unit(HEVCContext *s, const uint8_t *nal, int length) +static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) { HEVCLocalContext *lc = &s->HEVClc; GetBitContext *gb = &lc->gb; int ctb_addr_ts, ret; - ret = init_get_bits8(gb, nal, length); - if (ret < 0) - return ret; - - ret = hls_nal_unit(s); - if (ret < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", - s->nal_unit_type); - goto fail; - } else if (!ret) - return 0; + *gb = nal->gb; + s->nal_unit_type = nal->type; + s->temporal_id = nal->temporal_id; switch (s->nal_unit_type) { case NAL_VPS: - ret = ff_hevc_decode_nal_vps(s); + ret = ff_hevc_decode_nal_vps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; case NAL_SPS: - ret = ff_hevc_decode_nal_sps(s); + ret = ff_hevc_decode_nal_sps(gb, s->avctx, &s->ps, + s->apply_defdispwin); if (ret < 0) goto fail; break; case NAL_PPS: - ret = ff_hevc_decode_nal_pps(s); + ret = ff_hevc_decode_nal_pps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; @@ -2594,18 +2551,30 @@ static int decode_nal_unit(HEVCContext *s, const uint8_t *nal, int length) } } - ctb_addr_ts = hls_slice_data(s); - if (ctb_addr_ts >= (s->sps->ctb_width * s->sps->ctb_height)) { - s->is_decoded = 1; - if ((s->pps->transquant_bypass_enable_flag || - (s->sps->pcm.loop_filter_disable_flag && s->sps->pcm_enabled_flag)) && - s->sps->sao_enabled) - restore_tqb_pixels(s); + if (s->sh.first_slice_in_pic_flag && s->avctx->hwaccel) { + ret = s->avctx->hwaccel->start_frame(s->avctx, NULL, 0); + if (ret < 0) + goto fail; } - if (ctb_addr_ts < 0) { - ret = ctb_addr_ts; - goto fail; + if (s->avctx->hwaccel) { + ret = s->avctx->hwaccel->decode_slice(s->avctx, nal->raw_data, nal->raw_size); + if (ret < 0) + goto fail; + } else { + ctb_addr_ts = hls_slice_data(s); + if (ctb_addr_ts >= (s->ps.sps->ctb_width * s->ps.sps->ctb_height)) { + s->is_decoded = 1; + if ((s->ps.pps->transquant_bypass_enable_flag || + (s->ps.sps->pcm.loop_filter_disable_flag && s->ps.sps->pcm_enabled_flag)) && + s->ps.sps->sao_enabled) + restore_tqb_pixels(s); + } + + if (ctb_addr_ts < 0) { + ret = ctb_addr_ts; + goto fail; + } } break; case NAL_EOS_NUT: @@ -2628,181 +2597,32 @@ fail: return 0; } -/* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication - * between these functions would be nice. */ -static int extract_rbsp(const uint8_t *src, int length, - HEVCNAL *nal) -{ - int i, si, di; - uint8_t *dst; - -#define STARTCODE_TEST \ - if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ - if (src[i + 2] != 3) { \ - /* startcode, so we must be past the end */ \ - length = i; \ - } \ - break; \ - } -#if HAVE_FAST_UNALIGNED -#define FIND_FIRST_ZERO \ - if (i > 0 && !src[i]) \ - i--; \ - while (src[i]) \ - i++ -#if HAVE_FAST_64BIT - for (i = 0; i + 1 < length; i += 9) { - if (!((~AV_RN64A(src + i) & - (AV_RN64A(src + i) - 0x0100010001000101ULL)) & - 0x8000800080008080ULL)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 7; - } -#else - for (i = 0; i + 1 < length; i += 5) { - if (!((~AV_RN32A(src + i) & - (AV_RN32A(src + i) - 0x01000101U)) & - 0x80008080U)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 3; - } -#endif /* HAVE_FAST_64BIT */ -#else - for (i = 0; i + 1 < length; i += 2) { - if (src[i]) - continue; - if (i > 0 && src[i - 1] == 0) - i--; - STARTCODE_TEST; - } -#endif /* HAVE_FAST_UNALIGNED */ - - if (i >= length - 1) { // no escaped 0 - nal->data = src; - nal->size = length; - return length; - } - - av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size, - length + FF_INPUT_BUFFER_PADDING_SIZE); - if (!nal->rbsp_buffer) - return AVERROR(ENOMEM); - - dst = nal->rbsp_buffer; - - memcpy(dst, src, i); - si = di = i; - while (si + 2 < length) { - // remove escapes (very rare 1:2^22) - if (src[si + 2] > 3) { - dst[di++] = src[si++]; - dst[di++] = src[si++]; - } else if (src[si] == 0 && src[si + 1] == 0) { - if (src[si + 2] == 3) { // escape - dst[di++] = 0; - dst[di++] = 0; - si += 3; - - continue; - } else // next start code - goto nsc; - } - - dst[di++] = src[si++]; - } - while (si < length) - dst[di++] = src[si++]; - -nsc: - memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE); - - nal->data = dst; - nal->size = di; - return si; -} - static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) { - int i, consumed, ret = 0; + int i, ret = 0; s->ref = NULL; s->eos = 0; /* split the input packet into NAL units, so we know the upper bound on the * number of slices in the frame */ - s->nb_nals = 0; - while (length >= 4) { - HEVCNAL *nal; - int extract_length = 0; - - if (s->is_nalff) { - int i; - for (i = 0; i < s->nal_length_size; i++) - extract_length = (extract_length << 8) | buf[i]; - buf += s->nal_length_size; - length -= s->nal_length_size; - - if (extract_length > length) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n"); - ret = AVERROR_INVALIDDATA; - goto fail; - } - } else { - if (buf[2] == 0) { - length--; - buf++; - continue; - } - if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { - ret = AVERROR_INVALIDDATA; - goto fail; - } - - buf += 3; - length -= 3; - extract_length = length; - } - - if (s->nals_allocated < s->nb_nals + 1) { - int new_size = s->nals_allocated + 1; - HEVCNAL *tmp = av_realloc_array(s->nals, new_size, sizeof(*tmp)); - if (!tmp) { - ret = AVERROR(ENOMEM); - goto fail; - } - s->nals = tmp; - memset(s->nals + s->nals_allocated, 0, - (new_size - s->nals_allocated) * sizeof(*tmp)); - s->nals_allocated = new_size; - } - nal = &s->nals[s->nb_nals++]; - - consumed = extract_rbsp(buf, extract_length, nal); - if (consumed < 0) { - ret = consumed; - goto fail; - } - - ret = init_get_bits8(&s->HEVClc.gb, nal->data, nal->size); - if (ret < 0) - goto fail; - hls_nal_unit(s); + ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff, + s->nal_length_size, s->avctx->codec_id); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Error splitting the input into NAL units.\n"); + return ret; + } - if (s->nal_unit_type == NAL_EOB_NUT || - s->nal_unit_type == NAL_EOS_NUT) + for (i = 0; i < s->pkt.nb_nals; i++) { + if (s->pkt.nals[i].type == NAL_EOB_NUT || + s->pkt.nals[i].type == NAL_EOS_NUT) s->eos = 1; - - buf += consumed; - length -= consumed; } - /* parse the NAL units */ - for (i = 0; i < s->nb_nals; i++) { - int ret = decode_nal_unit(s, s->nals[i].data, s->nals[i].size); + /* decode the NAL units */ + for (i = 0; i < s->pkt.nb_nals; i++) { + ret = decode_nal_unit(s, &s->pkt.nals[i]); if (ret < 0) { av_log(s->avctx, AV_LOG_WARNING, "Error parsing NAL unit #%d.\n", i); @@ -2833,7 +2653,7 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) if (!desc) return AVERROR(EINVAL); - pixel_shift = desc->comp[0].depth_minus1 > 7; + pixel_shift = desc->comp[0].depth > 8; av_log(s->avctx, AV_LOG_DEBUG, "Verifying checksum for frame with POC %d: ", s->poc); @@ -2910,13 +2730,19 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, if (ret < 0) return ret; - /* verify the SEI checksum */ - if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && - s->is_md5) { - ret = verify_md5(s, s->ref->frame); - if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { - ff_hevc_unref_frame(s, s->ref, ~0); - return ret; + if (avctx->hwaccel) { + if (s->ref && avctx->hwaccel->end_frame(avctx) < 0) + av_log(avctx, AV_LOG_ERROR, + "hardware accelerator failed to decode picture\n"); + } else { + /* verify the SEI checksum */ + if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && + s->is_md5) { + ret = verify_md5(s, s->ref->frame); + if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { + ff_hevc_unref_frame(s, s->ref, ~0); + return ret; + } } } s->is_md5 = 0; @@ -2960,6 +2786,13 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src) dst->flags = src->flags; dst->sequence = src->sequence; + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + return 0; fail: ff_hevc_unref_frame(s, dst, ~0); @@ -2983,17 +2816,14 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) av_frame_free(&s->DPB[i].frame); } - for (i = 0; i < FF_ARRAY_ELEMS(s->vps_list); i++) - av_buffer_unref(&s->vps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(s->sps_list); i++) - av_buffer_unref(&s->sps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) - av_buffer_unref(&s->pps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) + av_buffer_unref(&s->ps.vps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) + av_buffer_unref(&s->ps.sps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) + av_buffer_unref(&s->ps.pps_list[i]); - for (i = 0; i < s->nals_allocated; i++) - av_freep(&s->nals[i].rbsp_buffer); - av_freep(&s->nals); - s->nals_allocated = 0; + ff_h2645_packet_uninit(&s->pkt); return 0; } @@ -3059,35 +2889,35 @@ static int hevc_update_thread_context(AVCodecContext *dst, } } - for (i = 0; i < FF_ARRAY_ELEMS(s->vps_list); i++) { - av_buffer_unref(&s->vps_list[i]); - if (s0->vps_list[i]) { - s->vps_list[i] = av_buffer_ref(s0->vps_list[i]); - if (!s->vps_list[i]) + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) { + av_buffer_unref(&s->ps.vps_list[i]); + if (s0->ps.vps_list[i]) { + s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]); + if (!s->ps.vps_list[i]) return AVERROR(ENOMEM); } } - for (i = 0; i < FF_ARRAY_ELEMS(s->sps_list); i++) { - av_buffer_unref(&s->sps_list[i]); - if (s0->sps_list[i]) { - s->sps_list[i] = av_buffer_ref(s0->sps_list[i]); - if (!s->sps_list[i]) + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { + av_buffer_unref(&s->ps.sps_list[i]); + if (s0->ps.sps_list[i]) { + s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]); + if (!s->ps.sps_list[i]) return AVERROR(ENOMEM); } } - for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) { - av_buffer_unref(&s->pps_list[i]); - if (s0->pps_list[i]) { - s->pps_list[i] = av_buffer_ref(s0->pps_list[i]); - if (!s->pps_list[i]) + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) { + av_buffer_unref(&s->ps.pps_list[i]); + if (s0->ps.pps_list[i]) { + s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]); + if (!s->ps.pps_list[i]) return AVERROR(ENOMEM); } } - if (s->sps != s0->sps) - ret = set_sps(s, s0->sps); + if (s->ps.sps != s0->ps.sps) + ret = set_sps(s, s0->ps.sps, src->pix_fmt); s->seq_decode = s0->seq_decode; s->seq_output = s0->seq_output; @@ -3109,7 +2939,7 @@ static int hevc_decode_extradata(HEVCContext *s) { AVCodecContext *avctx = s->avctx; GetByteContext gb; - int ret; + int ret, i; bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); @@ -3166,6 +2996,16 @@ static int hevc_decode_extradata(HEVCContext *s) if (ret < 0) return ret; } + + /* export stream parameters from the first SPS */ + for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { + if (s->ps.sps_list[i]) { + const HEVCSPS *sps = (const HEVCSPS*)s->ps.sps_list[i]->data; + export_stream_params(s->avctx, &s->ps, sps); + break; + } + } + return 0; } @@ -3174,8 +3014,6 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; int ret; - ff_init_cabac_states(); - avctx->internal->allocate_progress = 1; ret = hevc_init_context(avctx); @@ -3217,13 +3055,6 @@ static void hevc_decode_flush(AVCodecContext *avctx) #define OFFSET(x) offsetof(HEVCContext, x) #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) -static const AVProfile profiles[] = { - { FF_PROFILE_HEVC_MAIN, "Main" }, - { FF_PROFILE_HEVC_MAIN_10, "Main 10" }, - { FF_PROFILE_HEVC_MAIN_STILL_PICTURE, "Main Still Picture" }, - { FF_PROFILE_UNKNOWN }, -}; - static const AVOption options[] = { { "apply_defdispwin", "Apply default display window from VUI", OFFSET(apply_defdispwin), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, PAR }, @@ -3250,7 +3081,7 @@ AVCodec ff_hevc_decoder = { .flush = hevc_decode_flush, .update_thread_context = hevc_update_thread_context, .init_thread_copy = hevc_init_thread_copy, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | - CODEC_CAP_FRAME_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(profiles), + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_FRAME_THREADS, + .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), }; diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index aa84cdc..d15af71 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -33,6 +33,7 @@ #include "bswapdsp.h" #include "cabac.h" #include "get_bits.h" +#include "h2645_parse.h" #include "hevcdsp.h" #include "internal.h" #include "thread.h" @@ -262,6 +263,7 @@ enum ScanType { typedef struct ShortTermRPS { unsigned int num_negative_pics; int num_delta_pocs; + int rps_idx_num_delta_pocs; int32_t delta_poc[32]; uint8_t used[32]; } ShortTermRPS; @@ -525,6 +527,17 @@ typedef struct HEVCPPS { int *min_tb_addr_zs; ///< MinTbAddrZS } HEVCPPS; +typedef struct HEVCParamSets { + AVBufferRef *vps_list[MAX_VPS_COUNT]; + AVBufferRef *sps_list[MAX_SPS_COUNT]; + AVBufferRef *pps_list[MAX_PPS_COUNT]; + + /* currently active parameter sets */ + const HEVCVPS *vps; + const HEVCSPS *sps; + const HEVCPPS *pps; +} HEVCParamSets; + typedef struct SliceHeader { unsigned int pps_id; @@ -543,8 +556,11 @@ typedef struct SliceHeader { uint8_t colour_plane_id; ///< RPS coded in the slice header itself is stored here + int short_term_ref_pic_set_sps_flag; + int short_term_ref_pic_set_size; ShortTermRPS slice_rps; const ShortTermRPS *short_term_rps; + int long_term_ref_pic_set_size; LongTermRPS long_term_rps; unsigned int list_entry_lx[2][32]; @@ -605,10 +621,6 @@ typedef struct CodingUnit { enum PredMode pred_mode; ///< PredMode enum PartMode part_mode; ///< PartMode - uint8_t rqt_root_cbf; - - uint8_t pcm_flag; - // Inferred parameters uint8_t intra_split_flag; ///< IntraSplitFlag uint8_t max_trafo_depth; ///< MaxTrafoDepth @@ -678,6 +690,9 @@ typedef struct HEVCFrame { AVBufferRef *rpl_tab_buf; AVBufferRef *rpl_buf; + AVBufferRef *hwaccel_priv_buf; + void *hwaccel_picture_private; + /** * A sequence counter, so that old frames are output first * after a POC reset @@ -690,14 +705,6 @@ typedef struct HEVCFrame { uint8_t flags; } HEVCFrame; -typedef struct HEVCNAL { - uint8_t *rbsp_buffer; - int rbsp_buffer_size; - - int size; - const uint8_t *data; -} HEVCNAL; - struct HEVCContext; typedef struct HEVCPredContext { @@ -713,7 +720,7 @@ typedef struct HEVCPredContext { } HEVCPredContext; typedef struct HEVCLocalContext { - DECLARE_ALIGNED(16, int16_t, mc_buffer[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]); + DECLARE_ALIGNED(16, int16_t, mc_buffer[(MAX_PB_SIZE + 24) * MAX_PB_SIZE]); uint8_t cabac_state[HEVC_CONTEXTS]; uint8_t first_qp_group; @@ -765,12 +772,7 @@ typedef struct HEVCContext { AVFrame *tmp_frame; AVFrame *output_frame; - const HEVCVPS *vps; - const HEVCSPS *sps; - const HEVCPPS *pps; - AVBufferRef *vps_list[MAX_VPS_COUNT]; - AVBufferRef *sps_list[MAX_SPS_COUNT]; - AVBufferRef *pps_list[MAX_PPS_COUNT]; + HEVCParamSets ps; AVBufferPool *tab_mvf_pool; AVBufferPool *rpl_tab_pool; @@ -828,9 +830,7 @@ typedef struct HEVCContext { uint16_t seq_decode; uint16_t seq_output; - HEVCNAL *nals; - int nb_nals; - int nals_allocated; + H2645Packet pkt; // type of the first VCL NAL of the current frame enum NALUnitType first_nal_type; @@ -859,11 +859,27 @@ typedef struct HEVCContext { int sei_hflip, sei_vflip; } HEVCContext; -int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, - const HEVCSPS *sps, int is_slice_header); -int ff_hevc_decode_nal_vps(HEVCContext *s); -int ff_hevc_decode_nal_sps(HEVCContext *s); -int ff_hevc_decode_nal_pps(HEVCContext *s); +int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, + ShortTermRPS *rps, const HEVCSPS *sps, int is_slice_header); + +/** + * Parse the SPS from the bitstream into the provided HEVCSPS struct. + * + * @param sps_id the SPS id will be written here + * @param apply_defdispwin if set 1, the default display window from the VUI + * will be applied to the video dimensions + * @param vps_list if non-NULL, this function will validate that the SPS refers + * to an existing VPS + */ +int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, + int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx); + +int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps); +int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps, int apply_defdispwin); +int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps); int ff_hevc_decode_nal_sei(HEVCContext *s); /** @@ -985,6 +1001,9 @@ void ff_hevc_pps_free(HEVCPPS **ppps); void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth); +int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id, + uint8_t *buf, int buf_size); + extern const uint8_t ff_hevc_qpel_extra_before[4]; extern const uint8_t ff_hevc_qpel_extra_after[4]; extern const uint8_t ff_hevc_qpel_extra[4]; diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index ff55b02..b01808f 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -27,7 +27,7 @@ #include "cabac_functions.h" #include "hevc.h" -#define CABAC_MAX_BIN 100 +#define CABAC_MAX_BIN 31 /** * number of bin by SyntaxElement. @@ -325,10 +325,10 @@ static const uint8_t init_values[3][HEVC_CONTEXTS] = { void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts) { - if (s->pps->entropy_coding_sync_enabled_flag && - (ctb_addr_ts % s->sps->ctb_width == 2 || - (s->sps->ctb_width == 2 && - ctb_addr_ts % s->sps->ctb_width == 0))) { + if (s->ps.pps->entropy_coding_sync_enabled_flag && + (ctb_addr_ts % s->ps.sps->ctb_width == 2 || + (s->ps.sps->ctb_width == 2 && + ctb_addr_ts % s->ps.sps->ctb_width == 0))) { memcpy(s->cabac_state, s->HEVClc.cabac_state, HEVC_CONTEXTS); } } @@ -365,7 +365,7 @@ static void cabac_init_state(HEVCContext *s) int init_value = init_values[init_type][i]; int m = (init_value >> 4) * 5 - 45; int n = ((init_value & 15) << 3) - 16; - int pre = 2 * (((m * av_clip_c(s->sh.slice_qp, 0, 51)) >> 4) + n) - 127; + int pre = 2 * (((m * av_clip(s->sh.slice_qp, 0, 51)) >> 4) + n) - 127; pre ^= pre >> 31; if (pre > 124) @@ -376,34 +376,34 @@ static void cabac_init_state(HEVCContext *s) void ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts) { - if (ctb_addr_ts == s->pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) { + if (ctb_addr_ts == s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) { cabac_init_decoder(s); if (s->sh.dependent_slice_segment_flag == 0 || - (s->pps->tiles_enabled_flag && - s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[ctb_addr_ts - 1])) + (s->ps.pps->tiles_enabled_flag && + s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1])) cabac_init_state(s); if (!s->sh.first_slice_in_pic_flag && - s->pps->entropy_coding_sync_enabled_flag) { - if (ctb_addr_ts % s->sps->ctb_width == 0) { - if (s->sps->ctb_width == 1) + s->ps.pps->entropy_coding_sync_enabled_flag) { + if (ctb_addr_ts % s->ps.sps->ctb_width == 0) { + if (s->ps.sps->ctb_width == 1) cabac_init_state(s); else if (s->sh.dependent_slice_segment_flag == 1) load_states(s); } } } else { - if (s->pps->tiles_enabled_flag && - s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[ctb_addr_ts - 1]) { + if (s->ps.pps->tiles_enabled_flag && + s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) { cabac_reinit(&s->HEVClc); cabac_init_state(s); } - if (s->pps->entropy_coding_sync_enabled_flag) { - if (ctb_addr_ts % s->sps->ctb_width == 0) { + if (s->ps.pps->entropy_coding_sync_enabled_flag) { + if (ctb_addr_ts % s->ps.sps->ctb_width == 0) { get_cabac_terminate(&s->HEVClc.cc); cabac_reinit(&s->HEVClc); - if (s->sps->ctb_width == 1) + if (s->ps.sps->ctb_width == 1) cabac_init_state(s); else load_states(s); @@ -442,7 +442,7 @@ int ff_hevc_sao_band_position_decode(HEVCContext *s) int ff_hevc_sao_offset_abs_decode(HEVCContext *s) { int i = 0; - int length = (1 << (FFMIN(s->sps->bit_depth, 10) - 5)) - 1; + int length = (1 << (FFMIN(s->ps.sps->bit_depth, 10) - 5)) - 1; while (i < length && get_cabac_bypass(&s->HEVClc.cc)) i++; @@ -473,10 +473,10 @@ int ff_hevc_cu_transquant_bypass_flag_decode(HEVCContext *s) int ff_hevc_skip_flag_decode(HEVCContext *s, int x0, int y0, int x_cb, int y_cb) { - int min_cb_width = s->sps->min_cb_width; + int min_cb_width = s->ps.sps->min_cb_width; int inc = 0; - int x0b = x0 & ((1 << s->sps->log2_ctb_size) - 1); - int y0b = y0 & ((1 << s->sps->log2_ctb_size) - 1); + int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1); if (s->HEVClc.ctb_left_flag || x0b) inc = !!SAMPLE_CTB(s->skip_flag, x_cb - 1, y_cb); @@ -524,15 +524,15 @@ int ff_hevc_pred_mode_decode(HEVCContext *s) int ff_hevc_split_coding_unit_flag_decode(HEVCContext *s, int ct_depth, int x0, int y0) { int inc = 0, depth_left = 0, depth_top = 0; - int x0b = x0 & ((1 << s->sps->log2_ctb_size) - 1); - int y0b = y0 & ((1 << s->sps->log2_ctb_size) - 1); - int x_cb = x0 >> s->sps->log2_min_cb_size; - int y_cb = y0 >> s->sps->log2_min_cb_size; + int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int x_cb = x0 >> s->ps.sps->log2_min_cb_size; + int y_cb = y0 >> s->ps.sps->log2_min_cb_size; if (s->HEVClc.ctb_left_flag || x0b) - depth_left = s->tab_ct_depth[(y_cb) * s->sps->min_cb_width + x_cb - 1]; + depth_left = s->tab_ct_depth[(y_cb) * s->ps.sps->min_cb_width + x_cb - 1]; if (s->HEVClc.ctb_up_flag || y0b) - depth_top = s->tab_ct_depth[(y_cb - 1) * s->sps->min_cb_width + x_cb]; + depth_top = s->tab_ct_depth[(y_cb - 1) * s->ps.sps->min_cb_width + x_cb]; inc += (depth_left > ct_depth); inc += (depth_top > ct_depth); @@ -544,7 +544,7 @@ int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size) { if (GET_CABAC(elem_offset[PART_MODE])) // 1 return PART_2Nx2N; - if (log2_cb_size == s->sps->log2_min_cb_size) { + if (log2_cb_size == s->ps.sps->log2_min_cb_size) { if (s->HEVClc.cu.pred_mode == MODE_INTRA) // 0 return PART_NxN; if (GET_CABAC(elem_offset[PART_MODE] + 1)) // 01 @@ -556,7 +556,7 @@ int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size) return PART_NxN; // 000 } - if (!s->sps->amp_enabled_flag) { + if (!s->ps.sps->amp_enabled_flag) { if (GET_CABAC(elem_offset[PART_MODE] + 1)) // 01 return PART_2NxN; return PART_Nx2N; diff --git a/libavcodec/hevc_data.c b/libavcodec/hevc_data.c new file mode 100644 index 0000000..f4b6096 --- /dev/null +++ b/libavcodec/hevc_data.c @@ -0,0 +1,75 @@ +/* + * HEVC shared tables + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "hevc.h" + +const uint8_t ff_hevc_diag_scan4x4_x[16] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 1, 2, + 3, 2, 3, 3, +}; + +const uint8_t ff_hevc_diag_scan4x4_y[16] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 3, 2, + 1, 3, 2, 3, +}; + +const uint8_t ff_hevc_diag_scan8x8_x[64] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 0, 1, + 2, 3, 4, 0, + 1, 2, 3, 4, + 5, 0, 1, 2, + 3, 4, 5, 6, + 0, 1, 2, 3, + 4, 5, 6, 7, + 1, 2, 3, 4, + 5, 6, 7, 2, + 3, 4, 5, 6, + 7, 3, 4, 5, + 6, 7, 4, 5, + 6, 7, 5, 6, + 7, 6, 7, 7, +}; + +const uint8_t ff_hevc_diag_scan8x8_y[64] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 4, 3, + 2, 1, 0, 5, + 4, 3, 2, 1, + 0, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 7, + 6, 5, 4, 3, + 2, 7, 6, 5, + 4, 3, 7, 6, + 5, 4, 7, 6, + 5, 7, 6, 7, +}; diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 91a1e1f..39ac4ee 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -26,7 +26,6 @@ #include "libavutil/internal.h" #include "cabac_functions.h" -#include "golomb.h" #include "hevc.h" #define LUMA 0 @@ -54,11 +53,11 @@ static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset) // slice qp offset is not used for deblocking if (c_idx == 1) - offset = s->pps->cb_qp_offset; + offset = s->ps.pps->cb_qp_offset; else - offset = s->pps->cr_qp_offset; + offset = s->ps.pps->cr_qp_offset; - qp_i = av_clip_c(qp_y + offset, 0, 57); + qp_i = av_clip(qp_y + offset, 0, 57); if (qp_i < 30) qp = qp_i; else if (qp_i > 43) @@ -66,7 +65,7 @@ static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset) else qp = qp_c[qp_i - 30]; - idxt = av_clip_c(qp + DEFAULT_INTRA_TC_OFFSET + tc_offset, 0, 53); + idxt = av_clip(qp + DEFAULT_INTRA_TC_OFFSET + tc_offset, 0, 53); return tctable[idxt]; } @@ -74,15 +73,15 @@ static int get_qPy_pred(HEVCContext *s, int xC, int yC, int xBase, int yBase, int log2_cb_size) { HEVCLocalContext *lc = &s->HEVClc; - int ctb_size_mask = (1 << s->sps->log2_ctb_size) - 1; - int MinCuQpDeltaSizeMask = (1 << (s->sps->log2_ctb_size - - s->pps->diff_cu_qp_delta_depth)) - 1; + int ctb_size_mask = (1 << s->ps.sps->log2_ctb_size) - 1; + int MinCuQpDeltaSizeMask = (1 << (s->ps.sps->log2_ctb_size - + s->ps.pps->diff_cu_qp_delta_depth)) - 1; int xQgBase = xBase - (xBase & MinCuQpDeltaSizeMask); int yQgBase = yBase - (yBase & MinCuQpDeltaSizeMask); - int min_cb_width = s->sps->min_cb_width; - int min_cb_height = s->sps->min_cb_height; - int x_cb = xQgBase >> s->sps->log2_min_cb_size; - int y_cb = yQgBase >> s->sps->log2_min_cb_size; + int min_cb_width = s->ps.sps->min_cb_width; + int min_cb_height = s->ps.sps->min_cb_height; + int x_cb = xQgBase >> s->ps.sps->log2_min_cb_size; + int y_cb = yQgBase >> s->ps.sps->log2_min_cb_size; int availableA = (xBase & ctb_size_mask) && (xQgBase & ctb_size_mask); int availableB = (yBase & ctb_size_mask) && @@ -95,8 +94,8 @@ static int get_qPy_pred(HEVCContext *s, int xC, int yC, qPy_pred = s->sh.slice_qp; } else { qPy_pred = lc->qp_y; - if (log2_cb_size < s->sps->log2_ctb_size - - s->pps->diff_cu_qp_delta_depth) { + if (log2_cb_size < s->ps.sps->log2_ctb_size - + s->ps.pps->diff_cu_qp_delta_depth) { static const int offsetX[8][8] = { { -1, 1, 3, 1, 7, 1, 3, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, @@ -117,19 +116,19 @@ static int get_qPy_pred(HEVCContext *s, int xC, int yC, { 1, 0, 3, 2, 5, 4, 7, 6 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }; - int xC0b = (xC - (xC & ctb_size_mask)) >> s->sps->log2_min_cb_size; - int yC0b = (yC - (yC & ctb_size_mask)) >> s->sps->log2_min_cb_size; - int idxX = (xQgBase & ctb_size_mask) >> s->sps->log2_min_cb_size; - int idxY = (yQgBase & ctb_size_mask) >> s->sps->log2_min_cb_size; - int idx_mask = ctb_size_mask >> s->sps->log2_min_cb_size; + int xC0b = (xC - (xC & ctb_size_mask)) >> s->ps.sps->log2_min_cb_size; + int yC0b = (yC - (yC & ctb_size_mask)) >> s->ps.sps->log2_min_cb_size; + int idxX = (xQgBase & ctb_size_mask) >> s->ps.sps->log2_min_cb_size; + int idxY = (yQgBase & ctb_size_mask) >> s->ps.sps->log2_min_cb_size; + int idx_mask = ctb_size_mask >> s->ps.sps->log2_min_cb_size; int x, y; x = FFMIN(xC0b + offsetX[idxX][idxY], min_cb_width - 1); y = FFMIN(yC0b + (offsetY[idxX][idxY] & idx_mask), min_cb_height - 1); - if (xC0b == (lc->start_of_tiles_x >> s->sps->log2_min_cb_size) && + if (xC0b == (lc->start_of_tiles_x >> s->ps.sps->log2_min_cb_size) && offsetX[idxX][idxY] == -1) { - x = (lc->end_of_tiles_x >> s->sps->log2_min_cb_size) - 1; + x = (lc->end_of_tiles_x >> s->ps.sps->log2_min_cb_size) - 1; y = yC0b - 1; } qPy_pred = s->qp_y_tab[y * min_cb_width + x]; @@ -157,7 +156,7 @@ void ff_hevc_set_qPy(HEVCContext *s, int xC, int yC, int qp_y = get_qPy_pred(s, xC, yC, xBase, yBase, log2_cb_size); if (s->HEVClc.tu.cu_qp_delta != 0) { - int off = s->sps->qp_bd_offset; + int off = s->ps.sps->qp_bd_offset; s->HEVClc.qp_y = FFUMOD(qp_y + s->HEVClc.tu.cu_qp_delta + 52 + 2 * off, 52 + off) - off; } else @@ -166,10 +165,10 @@ void ff_hevc_set_qPy(HEVCContext *s, int xC, int yC, static int get_qPy(HEVCContext *s, int xC, int yC) { - int log2_min_cb_size = s->sps->log2_min_cb_size; + int log2_min_cb_size = s->ps.sps->log2_min_cb_size; int x = xC >> log2_min_cb_size; int y = yC >> log2_min_cb_size; - return s->qp_y_tab[x + y * s->sps->min_cb_width]; + return s->qp_y_tab[x + y * s->ps.sps->min_cb_width]; } static void copy_CTB(uint8_t *dst, uint8_t *src, @@ -184,7 +183,7 @@ static void copy_CTB(uint8_t *dst, uint8_t *src, } } -#define CTB(tab, x, y) ((tab)[(y) * s->sps->ctb_width + (x)]) +#define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)]) static void sao_filter_CTB(HEVCContext *s, int x, int y) { @@ -196,30 +195,30 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) SAOParams *sao[4]; int classes[4]; int x_shift = 0, y_shift = 0; - int x_ctb = x >> s->sps->log2_ctb_size; - int y_ctb = y >> s->sps->log2_ctb_size; - int ctb_addr_rs = y_ctb * s->sps->ctb_width + x_ctb; - int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[ctb_addr_rs]; + int x_ctb = x >> s->ps.sps->log2_ctb_size; + int y_ctb = y >> s->ps.sps->log2_ctb_size; + int ctb_addr_rs = y_ctb * s->ps.sps->ctb_width + x_ctb; + int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs]; // flags indicating unfilterable edges uint8_t vert_edge[] = { 0, 0, 0, 0 }; uint8_t horiz_edge[] = { 0, 0, 0, 0 }; uint8_t diag_edge[] = { 0, 0, 0, 0 }; uint8_t lfase[3]; // current, above, left - uint8_t no_tile_filter = s->pps->tiles_enabled_flag && - !s->pps->loop_filter_across_tiles_enabled_flag; + uint8_t no_tile_filter = s->ps.pps->tiles_enabled_flag && + !s->ps.pps->loop_filter_across_tiles_enabled_flag; uint8_t left_tile_edge = 0, up_tile_edge = 0; sao[0] = &CTB(s->sao, x_ctb, y_ctb); edges[0] = x_ctb == 0; edges[1] = y_ctb == 0; - edges[2] = x_ctb == s->sps->ctb_width - 1; - edges[3] = y_ctb == s->sps->ctb_height - 1; + edges[2] = x_ctb == s->ps.sps->ctb_width - 1; + edges[3] = y_ctb == s->ps.sps->ctb_height - 1; lfase[0] = CTB(s->filter_slice_edges, x_ctb, y_ctb); classes[0] = 0; if (!edges[0]) { - left_tile_edge = no_tile_filter && s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs-1]]; + left_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1]]; sao[class] = &CTB(s->sao, x_ctb - 1, y_ctb); vert_edge[0] = (!lfase[0] && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb)) || left_tile_edge; vert_edge[2] = vert_edge[0]; @@ -230,7 +229,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) } if (!edges[1]) { - up_tile_edge = no_tile_filter && s->pps->tile_id[ctb_addr_ts] != s->pps->tile_id[s->pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->sps->ctb_width]]; + up_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]]; sao[class] = &CTB(s->sao, x_ctb, y_ctb - 1); horiz_edge[0] = (!lfase[0] && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) || up_tile_edge; horiz_edge[1] = horiz_edge[0]; @@ -275,18 +274,18 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) int x0 = x >> chroma; int y0 = y >> chroma; int stride = s->frame->linesize[c_idx]; - int ctb_size = (1 << (s->sps->log2_ctb_size)) >> s->sps->hshift[c_idx]; + int ctb_size = (1 << (s->ps.sps->log2_ctb_size)) >> s->ps.sps->hshift[c_idx]; int width = FFMIN(ctb_size, - (s->sps->width >> s->sps->hshift[c_idx]) - x0); + (s->ps.sps->width >> s->ps.sps->hshift[c_idx]) - x0); int height = FFMIN(ctb_size, - (s->sps->height >> s->sps->vshift[c_idx]) - y0); + (s->ps.sps->height >> s->ps.sps->vshift[c_idx]) - y0); - uint8_t *src = &s->frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)]; - uint8_t *dst = &s->sao_frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)]; - int offset = (y_shift >> chroma) * stride + ((x_shift >> chroma) << s->sps->pixel_shift); + uint8_t *src = &s->frame->data[c_idx][y0 * stride + (x0 << s->ps.sps->pixel_shift)]; + uint8_t *dst = &s->sao_frame->data[c_idx][y0 * stride + (x0 << s->ps.sps->pixel_shift)]; + int offset = (y_shift >> chroma) * stride + ((x_shift >> chroma) << s->ps.sps->pixel_shift); copy_CTB(dst - offset, src - offset, - (edges[2] ? width + (x_shift >> chroma) : width) << s->sps->pixel_shift, + (edges[2] ? width + (x_shift >> chroma) : width) << s->ps.sps->pixel_shift, (edges[3] ? height + (y_shift >> chroma) : height), stride); for (class_index = 0; class_index < class; class_index++) { @@ -316,7 +315,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) static int get_pcm(HEVCContext *s, int x, int y) { - int log2_min_pu_size = s->sps->log2_min_pu_size; + int log2_min_pu_size = s->ps.sps->log2_min_pu_size; int x_pu, y_pu; if (x < 0 || y < 0) @@ -325,9 +324,9 @@ static int get_pcm(HEVCContext *s, int x, int y) x_pu = x >> log2_min_pu_size; y_pu = y >> log2_min_pu_size; - if (x_pu >= s->sps->min_pu_width || y_pu >= s->sps->min_pu_height) + if (x_pu >= s->ps.sps->min_pu_width || y_pu >= s->ps.sps->min_pu_height) return 2; - return s->is_pcm[y_pu * s->sps->min_pu_width + x_pu]; + return s->is_pcm[y_pu * s->ps.sps->min_pu_width + x_pu]; } #define TC_CALC(qp, bs) \ @@ -343,16 +342,16 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) uint8_t no_p[2] = { 0 }; uint8_t no_q[2] = { 0 }; - int log2_ctb_size = s->sps->log2_ctb_size; + int log2_ctb_size = s->ps.sps->log2_ctb_size; int ctb_size = 1 << log2_ctb_size; int ctb = (x0 >> log2_ctb_size) + - (y0 >> log2_ctb_size) * s->sps->ctb_width; + (y0 >> log2_ctb_size) * s->ps.sps->ctb_width; int cur_tc_offset = s->deblock[ctb].tc_offset; int cur_beta_offset = s->deblock[ctb].beta_offset; int tc_offset, left_tc_offset, beta_offset, left_beta_offset; - int pcmf = (s->sps->pcm_enabled_flag && - s->sps->pcm.loop_filter_disable_flag) || - s->pps->transquant_bypass_enable_flag; + int pcmf = (s->ps.sps->pcm_enabled_flag && + s->ps.sps->pcm.loop_filter_disable_flag) || + s->ps.pps->transquant_bypass_enable_flag; if (x0) { left_tc_offset = s->deblock[ctb - 1].tc_offset; @@ -360,11 +359,11 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) } x_end = x0 + ctb_size; - if (x_end > s->sps->width) - x_end = s->sps->width; + if (x_end > s->ps.sps->width) + x_end = s->ps.sps->width; y_end = y0 + ctb_size; - if (y_end > s->sps->height) - y_end = s->sps->height; + if (y_end > s->ps.sps->height) + y_end = s->ps.sps->height; tc_offset = cur_tc_offset; beta_offset = cur_beta_offset; @@ -381,7 +380,7 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) tc[0] = bs0 ? TC_CALC(qp, bs0) : 0; tc[1] = bs1 ? TC_CALC(qp, bs1) : 0; - src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->sps->pixel_shift)]; + src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->ps.sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x - 1, y); no_p[1] = get_pcm(s, x - 1, y + 4); @@ -410,7 +409,7 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) c_tc[0] = (bs0 == 2) ? chroma_tc(s, qp0, chroma, tc_offset) : 0; c_tc[1] = (bs1 == 2) ? chroma_tc(s, qp1, chroma, tc_offset) : 0; - src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->sps->pixel_shift)]; + src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->ps.sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x - 1, y); no_p[1] = get_pcm(s, x - 1, y + 8); @@ -429,7 +428,7 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) } // horizontal filtering luma - if (x_end != s->sps->width) + if (x_end != s->ps.sps->width) x_end -= 8; for (y = y0 ? y0 : 8; y < y_end; y += 8) { for (x = x0 ? x0 - 8 : 0; x < x_end; x += 8) { @@ -444,7 +443,7 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) beta = betatable[av_clip(qp + beta_offset, 0, MAX_QP)]; tc[0] = bs0 ? TC_CALC(qp, bs0) : 0; tc[1] = bs1 ? TC_CALC(qp, bs1) : 0; - src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->sps->pixel_shift)]; + src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->ps.sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x, y - 1); no_p[1] = get_pcm(s, x + 4, y - 1); @@ -486,7 +485,7 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) tc_offset = x >= x0 ? cur_tc_offset : left_tc_offset; c_tc[0] = bs0 == 2 ? chroma_tc(s, qp0, chroma, tc_offset) : 0; c_tc[1] = bs1 == 2 ? chroma_tc(s, qp1, chroma, cur_tc_offset) : 0; - src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->sps->pixel_shift)]; + src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->ps.sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x, y - 1); no_p[1] = get_pcm(s, x + 8, y - 1); @@ -588,10 +587,10 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, { HEVCLocalContext *lc = &s->HEVClc; MvField *tab_mvf = s->ref->tab_mvf; - int log2_min_pu_size = s->sps->log2_min_pu_size; - int log2_min_tu_size = s->sps->log2_min_tb_size; - int min_pu_width = s->sps->min_pu_width; - int min_tu_width = s->sps->min_tb_width; + int log2_min_pu_size = s->ps.sps->log2_min_pu_size; + int log2_min_tu_size = s->ps.sps->log2_min_tb_size; + int min_pu_width = s->ps.sps->min_pu_width; + int min_tu_width = s->ps.sps->min_tb_width; int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width + (x0 >> log2_min_pu_size)].is_intra; int boundary_upper, boundary_left; @@ -601,10 +600,10 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, if (boundary_upper && ((!s->sh.slice_loop_filter_across_slices_enabled_flag && lc->boundary_flags & BOUNDARY_UPPER_SLICE && - (y0 % (1 << s->sps->log2_ctb_size)) == 0) || - (!s->pps->loop_filter_across_tiles_enabled_flag && + (y0 % (1 << s->ps.sps->log2_ctb_size)) == 0) || + (!s->ps.pps->loop_filter_across_tiles_enabled_flag && lc->boundary_flags & BOUNDARY_UPPER_TILE && - (y0 % (1 << s->sps->log2_ctb_size)) == 0))) + (y0 % (1 << s->ps.sps->log2_ctb_size)) == 0))) boundary_upper = 0; if (boundary_upper) { @@ -633,7 +632,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, } // bs for TU internal horizontal PU boundaries - if (log2_trafo_size > s->sps->log2_min_pu_size && !is_intra) { + if (log2_trafo_size > s->ps.sps->log2_min_pu_size && !is_intra) { RefPicList *rpl = s->ref->refPicList; for (j = 8; j < (1 << log2_trafo_size); j += 8) { @@ -663,10 +662,10 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, if (boundary_left && ((!s->sh.slice_loop_filter_across_slices_enabled_flag && lc->boundary_flags & BOUNDARY_LEFT_SLICE && - (x0 % (1 << s->sps->log2_ctb_size)) == 0) || - (!s->pps->loop_filter_across_tiles_enabled_flag && + (x0 % (1 << s->ps.sps->log2_ctb_size)) == 0) || + (!s->ps.pps->loop_filter_across_tiles_enabled_flag && lc->boundary_flags & BOUNDARY_LEFT_TILE && - (x0 % (1 << s->sps->log2_ctb_size)) == 0))) + (x0 % (1 << s->ps.sps->log2_ctb_size)) == 0))) boundary_left = 0; if (boundary_left) { @@ -729,7 +728,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, void ff_hevc_hls_filter(HEVCContext *s, int x, int y) { deblocking_filter_CTB(s, x, y); - if (s->sps->sao_enabled) + if (s->ps.sps->sao_enabled) sao_filter_CTB(s, x, y); } @@ -737,10 +736,10 @@ void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size) { if (y_ctb && x_ctb) ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb - ctb_size); - if (y_ctb && x_ctb >= s->sps->width - ctb_size) { + if (y_ctb && x_ctb >= s->ps.sps->width - ctb_size) { ff_hevc_hls_filter(s, x_ctb, y_ctb - ctb_size); ff_thread_report_progress(&s->ref->tf, y_ctb - ctb_size, 0); } - if (x_ctb && y_ctb >= s->sps->height - ctb_size) + if (x_ctb && y_ctb >= s->ps.sps->height - ctb_size) ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb); } diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c new file mode 100644 index 0000000..8d7ac58 --- /dev/null +++ b/libavcodec/hevc_mp4toannexb_bsf.c @@ -0,0 +1,195 @@ +/* + * HEVC MP4 to Annex B byte stream format filter + * copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "bsf.h" +#include "bytestream.h" +#include "hevc.h" + +#define MIN_HEVCC_LENGTH 23 + +typedef struct HEVCBSFContext { + uint8_t length_size; + int extradata_parsed; +} HEVCBSFContext; + +static int hevc_extradata_to_annexb(AVBSFContext *ctx) +{ + GetByteContext gb; + int length_size, num_arrays, i, j; + int ret = 0; + + uint8_t *new_extradata = NULL; + size_t new_extradata_size = 0;; + + bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size); + + bytestream2_skip(&gb, 21); + length_size = (bytestream2_get_byte(&gb) & 3) + 1; + num_arrays = bytestream2_get_byte(&gb); + + for (i = 0; i < num_arrays; i++) { + int type = bytestream2_get_byte(&gb) & 0x3f; + int cnt = bytestream2_get_be16(&gb); + + if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS || + type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) { + av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n", + type); + ret = AVERROR_INVALIDDATA; + goto fail; + } + + for (j = 0; j < cnt; j++) { + int nalu_len = bytestream2_get_be16(&gb); + + if (4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + goto fail; + + AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode + bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len); + new_extradata_size += 4 + nalu_len; + memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + } + + av_freep(&ctx->par_out->extradata); + ctx->par_out->extradata = new_extradata; + ctx->par_out->extradata_size = new_extradata_size; + + if (!new_extradata_size) + av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); + + return length_size; +fail: + av_freep(&new_extradata); + return ret; +} + +static int hevc_mp4toannexb_init(AVBSFContext *ctx) +{ + HEVCBSFContext *s = ctx->priv_data; + int ret; + + if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH || + AV_RB24(ctx->par_in->extradata) == 1 || + AV_RB32(ctx->par_in->extradata) == 1) { + av_log(ctx, AV_LOG_VERBOSE, + "The input looks like it is Annex B already\n"); + } else { + ret = hevc_extradata_to_annexb(ctx); + if (ret < 0) + return ret; + s->length_size = ret; + s->extradata_parsed = 1; + } + + return 0; +} + +static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) +{ + HEVCBSFContext *s = ctx->priv_data; + AVPacket *in; + GetByteContext gb; + + int got_irap = 0; + int i, ret = 0; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (!s->extradata_parsed) { + av_packet_move_ref(out, in); + av_packet_free(&in); + return 0; + } + + bytestream2_init(&gb, in->data, in->size); + + while (bytestream2_get_bytes_left(&gb)) { + uint32_t nalu_size = 0; + int nalu_type; + int is_irap, add_extradata, extra_size, prev_size; + + for (i = 0; i < s->length_size; i++) + nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); + + nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; + + /* prepend extradata to IRAP frames */ + is_irap = nalu_type >= 16 && nalu_type <= 23; + add_extradata = is_irap && !got_irap; + extra_size = add_extradata * ctx->par_out->extradata_size; + got_irap |= is_irap; + + if (SIZE_MAX - nalu_size < 4 || + SIZE_MAX - 4 - nalu_size < extra_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + prev_size = out->size; + + ret = av_grow_packet(out, 4 + nalu_size + extra_size); + if (ret < 0) + goto fail; + + if (add_extradata) + memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size); + AV_WB32(out->data + prev_size + extra_size, 1); + bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size); + } + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + + return ret; +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = { + .name = "hevc_mp4toannexb", + .priv_data_size = sizeof(HEVCBSFContext), + .init = hevc_mp4toannexb_init, + .filter = hevc_mp4toannexb_filter, + .codec_ids = codec_ids, +}; diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c index 721eb3a..446b83a 100644 --- a/libavcodec/hevc_mvs.c +++ b/libavcodec/hevc_mvs.c @@ -42,17 +42,17 @@ void ff_hevc_set_neighbour_available(HEVCContext *s, int x0, int y0, int nPbW, int nPbH) { HEVCLocalContext *lc = &s->HEVClc; - int x0b = x0 & ((1 << s->sps->log2_ctb_size) - 1); - int y0b = y0 & ((1 << s->sps->log2_ctb_size) - 1); + int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1); lc->na.cand_up = (lc->ctb_up_flag || y0b); lc->na.cand_left = (lc->ctb_left_flag || x0b); lc->na.cand_up_left = (!x0b && !y0b) ? lc->ctb_up_left_flag : lc->na.cand_left && lc->na.cand_up; lc->na.cand_up_right_sap = - ((x0b + nPbW) == (1 << s->sps->log2_ctb_size)) ? + ((x0b + nPbW) == (1 << s->ps.sps->log2_ctb_size)) ? lc->ctb_up_right_flag && !y0b : lc->na.cand_up; lc->na.cand_up_right = - ((x0b + nPbW) == (1 << s->sps->log2_ctb_size) ? + ((x0b + nPbW) == (1 << s->ps.sps->log2_ctb_size) ? lc->ctb_up_right_flag && !y0b : lc->na.cand_up ) && (x0 + nPbW) < lc->end_of_tiles_x; lc->na.cand_bottom_left = ((y0 + nPbH) >= lc->end_of_tiles_y) ? 0 : lc->na.cand_left; @@ -65,18 +65,18 @@ static int z_scan_block_avail(HEVCContext *s, int xCurr, int yCurr, int xN, int yN) { #define MIN_TB_ADDR_ZS(x, y) \ - s->pps->min_tb_addr_zs[(y) * s->sps->min_tb_width + (x)] - int Curr = MIN_TB_ADDR_ZS(xCurr >> s->sps->log2_min_tb_size, - yCurr >> s->sps->log2_min_tb_size); + s->ps.pps->min_tb_addr_zs[(y) * s->ps.sps->min_tb_width + (x)] + int Curr = MIN_TB_ADDR_ZS(xCurr >> s->ps.sps->log2_min_tb_size, + yCurr >> s->ps.sps->log2_min_tb_size); int N; if (xN < 0 || yN < 0 || - xN >= s->sps->width || - yN >= s->sps->height) + xN >= s->ps.sps->width || + yN >= s->ps.sps->height) return 0; - N = MIN_TB_ADDR_ZS(xN >> s->sps->log2_min_tb_size, - yN >> s->sps->log2_min_tb_size); + N = MIN_TB_ADDR_ZS(xN >> s->ps.sps->log2_min_tb_size, + yN >> s->ps.sps->log2_min_tb_size); return N <= Curr; } @@ -109,10 +109,10 @@ static int check_prediction_block_available(HEVCContext *s, int log2_cb_size, return z_scan_block_avail(s, x0, y0, xA1, yA1); } -//check if the two luma locations belong to the same mostion estimation region +//check if the two luma locations belong to the same motion estimation region static int isDiffMER(HEVCContext *s, int xN, int yN, int xP, int yP) { - uint8_t plevel = s->pps->log2_parallel_merge_level; + uint8_t plevel = s->ps.pps->log2_parallel_merge_level; return xN >> plevel == xP >> plevel && yN >> plevel == yP >> plevel; @@ -141,13 +141,13 @@ static av_always_inline void mv_scale(Mv *dst, Mv *src, int td, int tb) { int tx, scale_factor; - td = av_clip_int8_c(td); - tb = av_clip_int8_c(tb); + td = av_clip_int8(td); + tb = av_clip_int8(tb); tx = (0x4000 + abs(td / 2)) / td; - scale_factor = av_clip_c((tb * tx + 32) >> 6, -4096, 4095); - dst->x = av_clip_int16_c((scale_factor * src->x + 127 + + scale_factor = av_clip((tb * tx + 32) >> 6, -4096, 4095); + dst->x = av_clip_int16((scale_factor * src->x + 127 + (scale_factor * src->x < 0)) >> 8); - dst->y = av_clip_int16_c((scale_factor * src->y + 127 + + dst->y = av_clip_int16((scale_factor * src->y + 127 + (scale_factor * src->y < 0)) >> 8); } @@ -251,7 +251,7 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, MvField *tab_mvf; MvField temp_col; int x, y, x_pu, y_pu; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; int availableFlagLXCol = 0; int colPic; @@ -270,14 +270,14 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, y = y0 + nPbH; if (tab_mvf && - (y0 >> s->sps->log2_ctb_size) == (y >> s->sps->log2_ctb_size) && - y < s->sps->height && - x < s->sps->width) { + (y0 >> s->ps.sps->log2_ctb_size) == (y >> s->ps.sps->log2_ctb_size) && + y < s->ps.sps->height && + x < s->ps.sps->width) { x &= ~15; y &= ~15; ff_thread_await_progress(&ref->tf, y, 0); - x_pu = x >> s->sps->log2_min_pu_size; - y_pu = y >> s->sps->log2_min_pu_size; + x_pu = x >> s->ps.sps->log2_min_pu_size; + y_pu = y >> s->ps.sps->log2_min_pu_size; temp_col = TAB_MVF(x_pu, y_pu); availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS; } @@ -289,8 +289,8 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, x &= ~15; y &= ~15; ff_thread_await_progress(&ref->tf, y, 0); - x_pu = x >> s->sps->log2_min_pu_size; - y_pu = y >> s->sps->log2_min_pu_size; + x_pu = x >> s->ps.sps->log2_min_pu_size; + y_pu = y >> s->ps.sps->log2_min_pu_size; temp_col = TAB_MVF(x_pu, y_pu); availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS; } @@ -322,7 +322,7 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, RefPicList *refPicList = s->ref->refPicList; MvField *tab_mvf = s->ref->tab_mvf; - const int min_pu_width = s->sps->min_pu_width; + const int min_pu_width = s->ps.sps->min_pu_width; const int cand_bottom_left = lc->na.cand_bottom_left; const int cand_left = lc->na.cand_left; @@ -332,28 +332,28 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, const int xA1 = x0 - 1; const int yA1 = y0 + nPbH - 1; - const int xA1_pu = xA1 >> s->sps->log2_min_pu_size; - const int yA1_pu = yA1 >> s->sps->log2_min_pu_size; + const int xA1_pu = xA1 >> s->ps.sps->log2_min_pu_size; + const int yA1_pu = yA1 >> s->ps.sps->log2_min_pu_size; const int xB1 = x0 + nPbW - 1; const int yB1 = y0 - 1; - const int xB1_pu = xB1 >> s->sps->log2_min_pu_size; - const int yB1_pu = yB1 >> s->sps->log2_min_pu_size; + const int xB1_pu = xB1 >> s->ps.sps->log2_min_pu_size; + const int yB1_pu = yB1 >> s->ps.sps->log2_min_pu_size; const int xB0 = x0 + nPbW; const int yB0 = y0 - 1; - const int xB0_pu = xB0 >> s->sps->log2_min_pu_size; - const int yB0_pu = yB0 >> s->sps->log2_min_pu_size; + const int xB0_pu = xB0 >> s->ps.sps->log2_min_pu_size; + const int yB0_pu = yB0 >> s->ps.sps->log2_min_pu_size; const int xA0 = x0 - 1; const int yA0 = y0 + nPbH; - const int xA0_pu = xA0 >> s->sps->log2_min_pu_size; - const int yA0_pu = yA0 >> s->sps->log2_min_pu_size; + const int xA0_pu = xA0 >> s->ps.sps->log2_min_pu_size; + const int yA0_pu = yA0 >> s->ps.sps->log2_min_pu_size; const int xB2 = x0 - 1; const int yB2 = y0 - 1; - const int xB2_pu = xB2 >> s->sps->log2_min_pu_size; - const int yB2_pu = yB2 >> s->sps->log2_min_pu_size; + const int xB2_pu = xB2 >> s->ps.sps->log2_min_pu_size; + const int yB2_pu = yB2 >> s->ps.sps->log2_min_pu_size; const int nb_refs = (s->sh.slice_type == P_SLICE) ? s->sh.nb_refs[0] : FFMIN(s->sh.nb_refs[0], s->sh.nb_refs[1]); @@ -470,7 +470,7 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, // temporal motion vector candidate if (s->sh.slice_temporal_mvp_enabled_flag && nb_merge_cand < s->sh.max_num_merge_cand) { - Mv mv_l0_col, mv_l1_col; + Mv mv_l0_col = { 0 }, mv_l1_col = { 0 }; int available_l0 = temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH, 0, &mv_l0_col, 0); int available_l1 = (s->sh.slice_type == B_SLICE) ? @@ -554,7 +554,7 @@ void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW, int nPbH2 = nPbH; HEVCLocalContext *lc = &s->HEVClc; - if (s->pps->log2_parallel_merge_level > 2 && nCS == 8) { + if (s->ps.pps->log2_parallel_merge_level > 2 && nCS == 8) { singleMCLFlag = 1; x0 = lc->cu.x; y0 = lc->cu.y; @@ -599,7 +599,7 @@ static int mv_mp_mode_mx(HEVCContext *s, int x, int y, int pred_flag_index, Mv *mv, int ref_idx_curr, int ref_idx) { MvField *tab_mvf = s->ref->tab_mvf; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; RefPicList *refPicList = s->ref->refPicList; @@ -615,7 +615,7 @@ static int mv_mp_mode_mx_lt(HEVCContext *s, int x, int y, int pred_flag_index, Mv *mv, int ref_idx_curr, int ref_idx) { MvField *tab_mvf = s->ref->tab_mvf; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; RefPicList *refPicList = s->ref->refPicList; int currIsLongTerm = refPicList[ref_idx_curr].isLongTerm[ref_idx]; @@ -653,7 +653,7 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, int availableFlagLXA0 = 0; int availableFlagLXB0 = 0; int numMVPCandLX = 0; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; int xA0, yA0; int xA0_pu, yA0_pu; @@ -681,15 +681,15 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, int ref_idx = 0; int pred_flag_index_l0; int pred_flag_index_l1; - int x0b = x0 & ((1 << s->sps->log2_ctb_size) - 1); - int y0b = y0 & ((1 << s->sps->log2_ctb_size) - 1); + int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1); + int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1); int cand_up = (lc->ctb_up_flag || y0b); int cand_left = (lc->ctb_left_flag || x0b); int cand_up_left = (!x0b && !y0b) ? lc->ctb_up_left_flag : cand_left && cand_up; int cand_up_right = - (x0b + nPbW == (1 << s->sps->log2_ctb_size) || + (x0b + nPbW == (1 << s->ps.sps->log2_ctb_size) || x0 + nPbW >= lc->end_of_tiles_x) ? lc->ctb_up_right_flag && !y0b : cand_up; int cand_bottom_left = (y0 + nPbH >= lc->end_of_tiles_y) ? 0 : cand_left; @@ -702,16 +702,16 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, // left bottom spatial candidate xA0 = x0 - 1; yA0 = y0 + nPbH; - xA0_pu = xA0 >> s->sps->log2_min_pu_size; - yA0_pu = yA0 >> s->sps->log2_min_pu_size; + xA0_pu = xA0 >> s->ps.sps->log2_min_pu_size; + yA0_pu = yA0 >> s->ps.sps->log2_min_pu_size; is_available_a0 = PRED_BLOCK_AVAILABLE(A0) && AVAILABLE(cand_bottom_left, A0); //left spatial merge candidate xA1 = x0 - 1; yA1 = y0 + nPbH - 1; - xA1_pu = xA1 >> s->sps->log2_min_pu_size; - yA1_pu = yA1 >> s->sps->log2_min_pu_size; + xA1_pu = xA1 >> s->ps.sps->log2_min_pu_size; + yA1_pu = yA1 >> s->ps.sps->log2_min_pu_size; is_available_a1 = AVAILABLE(cand_left, A1); if (is_available_a0 || is_available_a1) @@ -750,8 +750,8 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, // above right spatial merge candidate xB0 = x0 + nPbW; yB0 = y0 - 1; - xB0_pu = xB0 >> s->sps->log2_min_pu_size; - yB0_pu = yB0 >> s->sps->log2_min_pu_size; + xB0_pu = xB0 >> s->ps.sps->log2_min_pu_size; + yB0_pu = yB0 >> s->ps.sps->log2_min_pu_size; is_available_b0 = PRED_BLOCK_AVAILABLE(B0) && AVAILABLE(cand_up_right, B0); @@ -765,8 +765,8 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, // above spatial merge candidate xB1 = x0 + nPbW - 1; yB1 = y0 - 1; - xB1_pu = xB1 >> s->sps->log2_min_pu_size; - yB1_pu = yB1 >> s->sps->log2_min_pu_size; + xB1_pu = xB1 >> s->ps.sps->log2_min_pu_size; + yB1_pu = yB1 >> s->ps.sps->log2_min_pu_size; is_available_b1 = AVAILABLE(cand_up, B1); @@ -781,8 +781,8 @@ void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, // above left spatial merge candidate xB2 = x0 - 1; yB2 = y0 - 1; - xB2_pu = xB2 >> s->sps->log2_min_pu_size; - yB2_pu = yB2 >> s->sps->log2_min_pu_size; + xB2_pu = xB2 >> s->ps.sps->log2_min_pu_size; + yB2_pu = yB2 >> s->ps.sps->log2_min_pu_size; is_available_b2 = AVAILABLE(cand_up_left, B2); if (is_available_b2) { diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index ac2c6f5..dc5fffc 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -22,11 +22,101 @@ #include "libavutil/common.h" -#include "parser.h" +#include "golomb.h" #include "hevc.h" +#include "h2645_parse.h" +#include "parser.h" #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes +#define IS_IRAP_NAL(nal) (nal->type >= 16 && nal->type <= 23) + +typedef struct HEVCParserContext { + ParseContext pc; + + H2645Packet pkt; + HEVCParamSets ps; + + int parsed_extradata; +} HEVCParserContext; + +static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, + AVCodecContext *avctx) +{ + HEVCParserContext *ctx = s->priv_data; + GetBitContext *gb = &nal->gb; + + HEVCPPS *pps; + HEVCSPS *sps; + unsigned int pps_id; + + get_bits1(gb); // first slice in pic + if (IS_IRAP_NAL(nal)) + get_bits1(gb); // no output of prior pics + + pps_id = get_ue_golomb_long(gb); + if (pps_id >= MAX_PPS_COUNT || !ctx->ps.pps_list[pps_id]) { + av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); + return AVERROR_INVALIDDATA; + } + pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data; + sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data; + + /* export the stream parameters */ + s->coded_width = sps->width; + s->coded_height = sps->height; + s->width = sps->output_width; + s->height = sps->output_height; + s->format = sps->pix_fmt; + avctx->profile = sps->ptl.general_ptl.profile_idc; + avctx->level = sps->ptl.general_ptl.level_idc; + + /* ignore the rest for now*/ + + return 0; +} + +static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + HEVCParserContext *ctx = s->priv_data; + int ret, i; + + ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0, + AV_CODEC_ID_HEVC); + if (ret < 0) + return ret; + + for (i = 0; i < ctx->pkt.nb_nals; i++) { + H2645NAL *nal = &ctx->pkt.nals[i]; + + /* ignore everything except parameter sets and VCL NALUs */ + switch (nal->type) { + case NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, avctx, &ctx->ps); break; + case NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, avctx, &ctx->ps, 1); break; + case NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, avctx, &ctx->ps); break; + case NAL_TRAIL_R: + case NAL_TRAIL_N: + case NAL_TSA_N: + case NAL_TSA_R: + case NAL_STSA_N: + case NAL_STSA_R: + case NAL_BLA_W_LP: + case NAL_BLA_W_RADL: + case NAL_BLA_N_LP: + case NAL_IDR_W_RADL: + case NAL_IDR_N_LP: + case NAL_CRA_NUT: + case NAL_RADL_N: + case NAL_RADL_R: + case NAL_RASL_N: + case NAL_RASL_R: hevc_parse_slice_header(s, nal, avctx); break; + } + } + + return 0; +} + /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or END_NOT_FOUND @@ -34,8 +124,9 @@ static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, int buf_size) { + HEVCParserContext *ctx = s->priv_data; + ParseContext *pc = &ctx->pc; int i; - ParseContext *pc = s->priv_data; for (i = 0; i < buf_size; i++) { int nut; @@ -76,7 +167,14 @@ static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size) { int next; - ParseContext *pc = s->priv_data; + + HEVCParserContext *ctx = s->priv_data; + ParseContext *pc = &ctx->pc; + + if (avctx->extradata && !ctx->parsed_extradata) { + parse_nal_units(s, avctx->extradata, avctx->extradata_size, avctx); + ctx->parsed_extradata = 1; + } if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { next = buf_size; @@ -89,6 +187,8 @@ static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx, } } + parse_nal_units(s, buf, buf_size, avctx); + *poutbuf = buf; *poutbuf_size = buf_size; return next; @@ -116,10 +216,27 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size) return 0; } +static void hevc_parser_close(AVCodecParserContext *s) +{ + HEVCParserContext *ctx = s->priv_data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.vps_list); i++) + av_buffer_unref(&ctx->ps.vps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.sps_list); i++) + av_buffer_unref(&ctx->ps.sps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.pps_list); i++) + av_buffer_unref(&ctx->ps.pps_list[i]); + + ff_h2645_packet_uninit(&ctx->pkt); + + av_freep(&ctx->pc.buffer); +} + AVCodecParser ff_hevc_parser = { .codec_ids = { AV_CODEC_ID_HEVC }, - .priv_data_size = sizeof(ParseContext), + .priv_data_size = sizeof(HEVCParserContext), .parser_parse = hevc_parse, - .parser_close = ff_parse_close, + .parser_close = hevc_parser_close, .split = hevc_split, }; diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index db658be..5c249d8 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -70,10 +70,45 @@ static const AVRational vui_sar[] = { { 2, 1 }, }; -int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, - const HEVCSPS *sps, int is_slice_header) +static void remove_pps(HEVCParamSets *s, int id) +{ + if (s->pps_list[id] && s->pps == (const HEVCPPS*)s->pps_list[id]->data) + s->pps = NULL; + av_buffer_unref(&s->pps_list[id]); +} + +static void remove_sps(HEVCParamSets *s, int id) +{ + int i; + if (s->sps_list[id]) { + if (s->sps == (const HEVCSPS*)s->sps_list[id]->data) + s->sps = NULL; + + /* drop all PPS that depend on this SPS */ + for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) + if (s->pps_list[i] && ((HEVCPPS*)s->pps_list[i]->data)->sps_id == id) + remove_pps(s, i); + } + av_buffer_unref(&s->sps_list[id]); +} + +static void remove_vps(HEVCParamSets *s, int id) +{ + int i; + if (s->vps_list[id]) { + if (s->vps == (const HEVCVPS*)s->vps_list[id]->data) + s->vps = NULL; + + for (i = 0; i < FF_ARRAY_ELEMS(s->sps_list); i++) + if (s->sps_list[i] && ((HEVCSPS*)s->sps_list[i]->data)->vps_id == id) + remove_sps(s, i); + } + av_buffer_unref(&s->vps_list[id]); +} + +int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, + ShortTermRPS *rps, const HEVCSPS *sps, int is_slice_header) { - HEVCLocalContext *lc = &s->HEVClc; uint8_t rps_predict = 0; int delta_poc; int k0 = 0; @@ -81,8 +116,6 @@ int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, int k = 0; int i; - GetBitContext *gb = &lc->gb; - if (rps != sps->st_rps && sps->nb_st_rps) rps_predict = get_bits1(gb); @@ -95,12 +128,13 @@ int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, if (is_slice_header) { unsigned int delta_idx = get_ue_golomb_long(gb) + 1; if (delta_idx > sps->nb_st_rps) { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "Invalid value of delta_idx in slice header RPS: %d > %d.\n", delta_idx, sps->nb_st_rps); return AVERROR_INVALIDDATA; } rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; + rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; } else rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; @@ -167,7 +201,7 @@ int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, if (rps->num_negative_pics >= MAX_REFS || nb_positive_pics >= MAX_REFS) { - av_log(s->avctx, AV_LOG_ERROR, "Too many refs in a short term RPS.\n"); + av_log(avctx, AV_LOG_ERROR, "Too many refs in a short term RPS.\n"); return AVERROR_INVALIDDATA; } @@ -193,25 +227,29 @@ int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, } -static void decode_profile_tier_level(HEVCContext *s, PTLCommon *ptl) +static void decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx, + PTLCommon *ptl) { int i; - GetBitContext *gb = &s->HEVClc.gb; ptl->profile_space = get_bits(gb, 2); ptl->tier_flag = get_bits1(gb); ptl->profile_idc = get_bits(gb, 5); if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN) - av_log(s->avctx, AV_LOG_DEBUG, "Main profile bitstream\n"); + av_log(avctx, AV_LOG_DEBUG, "Main profile bitstream\n"); else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_10) - av_log(s->avctx, AV_LOG_DEBUG, "Main 10 profile bitstream\n"); + av_log(avctx, AV_LOG_DEBUG, "Main 10 profile bitstream\n"); else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_STILL_PICTURE) - av_log(s->avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n"); + av_log(avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n"); else - av_log(s->avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); + av_log(avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); - for (i = 0; i < 32; i++) + for (i = 0; i < 32; i++) { ptl->profile_compatibility_flag[i] = get_bits1(gb); + + if (ptl->profile_idc == 0 && i > 0 && ptl->profile_compatibility_flag[i]) + ptl->profile_idc = i; + } ptl->progressive_source_flag = get_bits1(gb); ptl->interlaced_source_flag = get_bits1(gb); ptl->non_packed_constraint_flag = get_bits1(gb); @@ -222,11 +260,11 @@ static void decode_profile_tier_level(HEVCContext *s, PTLCommon *ptl) skip_bits(gb, 12); // XXX_reserved_zero_44bits[32..43] } -static void parse_ptl(HEVCContext *s, PTL *ptl, int max_num_sub_layers) +static void parse_ptl(GetBitContext *gb, AVCodecContext *avctx, + PTL *ptl, int max_num_sub_layers) { int i; - GetBitContext *gb = &s->HEVClc.gb; - decode_profile_tier_level(s, &ptl->general_ptl); + decode_profile_tier_level(gb, avctx, &ptl->general_ptl); ptl->general_ptl.level_idc = get_bits(gb, 8); for (i = 0; i < max_num_sub_layers - 1; i++) { @@ -238,16 +276,15 @@ static void parse_ptl(HEVCContext *s, PTL *ptl, int max_num_sub_layers) skip_bits(gb, 2); // reserved_zero_2bits[i] for (i = 0; i < max_num_sub_layers - 1; i++) { if (ptl->sub_layer_profile_present_flag[i]) - decode_profile_tier_level(s, &ptl->sub_layer_ptl[i]); + decode_profile_tier_level(gb, avctx, &ptl->sub_layer_ptl[i]); if (ptl->sub_layer_level_present_flag[i]) ptl->sub_layer_ptl[i].level_idc = get_bits(gb, 8); } } -static void decode_sublayer_hrd(HEVCContext *s, unsigned int nb_cpb, +static void decode_sublayer_hrd(GetBitContext *gb, unsigned int nb_cpb, int subpic_params_present) { - GetBitContext *gb = &s->HEVClc.gb; int i; for (i = 0; i < nb_cpb; i++) { @@ -262,10 +299,9 @@ static void decode_sublayer_hrd(HEVCContext *s, unsigned int nb_cpb, } } -static void decode_hrd(HEVCContext *s, int common_inf_present, +static void decode_hrd(GetBitContext *gb, int common_inf_present, int max_sublayers) { - GetBitContext *gb = &s->HEVClc.gb; int nal_params_present = 0, vcl_params_present = 0; int subpic_params_present = 0; int i; @@ -313,16 +349,16 @@ static void decode_hrd(HEVCContext *s, int common_inf_present, nb_cpb = get_ue_golomb_long(gb) + 1; if (nal_params_present) - decode_sublayer_hrd(s, nb_cpb, subpic_params_present); + decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); if (vcl_params_present) - decode_sublayer_hrd(s, nb_cpb, subpic_params_present); + decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); } } -int ff_hevc_decode_nal_vps(HEVCContext *s) +int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps) { int i,j; - GetBitContext *gb = &s->HEVClc.gb; int vps_id = 0; HEVCVPS *vps; AVBufferRef *vps_buf = av_buffer_allocz(sizeof(*vps)); @@ -331,16 +367,16 @@ int ff_hevc_decode_nal_vps(HEVCContext *s) return AVERROR(ENOMEM); vps = (HEVCVPS*)vps_buf->data; - av_log(s->avctx, AV_LOG_DEBUG, "Decoding VPS\n"); + av_log(avctx, AV_LOG_DEBUG, "Decoding VPS\n"); vps_id = get_bits(gb, 4); if (vps_id >= MAX_VPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", vps_id); + av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", vps_id); goto err; } if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits - av_log(s->avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); + av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); goto err; } @@ -349,17 +385,17 @@ int ff_hevc_decode_nal_vps(HEVCContext *s) vps->vps_temporal_id_nesting_flag = get_bits1(gb); if (get_bits(gb, 16) != 0xffff) { // vps_reserved_ffff_16bits - av_log(s->avctx, AV_LOG_ERROR, "vps_reserved_ffff_16bits is not 0xffff\n"); + av_log(avctx, AV_LOG_ERROR, "vps_reserved_ffff_16bits is not 0xffff\n"); goto err; } if (vps->vps_max_sub_layers > MAX_SUB_LAYERS) { - av_log(s->avctx, AV_LOG_ERROR, "vps_max_sub_layers out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "vps_max_sub_layers out of range: %d\n", vps->vps_max_sub_layers); goto err; } - parse_ptl(s, &vps->ptl, vps->vps_max_sub_layers); + parse_ptl(gb, avctx, &vps->ptl, vps->vps_max_sub_layers); vps->vps_sub_layer_ordering_info_present_flag = get_bits1(gb); @@ -370,14 +406,14 @@ int ff_hevc_decode_nal_vps(HEVCContext *s) vps->vps_max_latency_increase[i] = get_ue_golomb_long(gb) - 1; if (vps->vps_max_dec_pic_buffering[i] > MAX_DPB_SIZE) { - av_log(s->avctx, AV_LOG_ERROR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n", vps->vps_max_dec_pic_buffering[i] - 1); goto err; } if (vps->vps_num_reorder_pics[i] > vps->vps_max_dec_pic_buffering[i] - 1) { - av_log(s->avctx, AV_LOG_WARNING, "vps_max_num_reorder_pics out of range: %d\n", + av_log(avctx, AV_LOG_WARNING, "vps_max_num_reorder_pics out of range: %d\n", vps->vps_num_reorder_pics[i]); - if (s->avctx->err_recognition & AV_EF_EXPLODE) + if (avctx->err_recognition & AV_EF_EXPLODE) goto err; } } @@ -402,13 +438,19 @@ int ff_hevc_decode_nal_vps(HEVCContext *s) get_ue_golomb_long(gb); // hrd_layer_set_idx if (i) common_inf_present = get_bits1(gb); - decode_hrd(s, common_inf_present, vps->vps_max_sub_layers); + decode_hrd(gb, common_inf_present, vps->vps_max_sub_layers); } } get_bits1(gb); /* vps_extension_flag */ - av_buffer_unref(&s->vps_list[vps_id]); - s->vps_list[vps_id] = vps_buf; + if (ps->vps_list[vps_id] && + !memcmp(ps->vps_list[vps_id]->data, vps_buf->data, vps_buf->size)) { + av_buffer_unref(&vps_buf); + } else { + remove_vps(ps, vps_id); + ps->vps_list[vps_id] = vps_buf; + } + return 0; err: @@ -416,13 +458,13 @@ err: return AVERROR_INVALIDDATA; } -static void decode_vui(HEVCContext *s, HEVCSPS *sps) +static void decode_vui(GetBitContext *gb, AVCodecContext *avctx, + int apply_defdispwin, HEVCSPS *sps) { VUI *vui = &sps->vui; - GetBitContext *gb = &s->HEVClc.gb; int sar_present; - av_log(s->avctx, AV_LOG_DEBUG, "Decoding VUI\n"); + av_log(avctx, AV_LOG_DEBUG, "Decoding VUI\n"); sar_present = get_bits1(gb); if (sar_present) { @@ -433,7 +475,7 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) vui->sar.num = get_bits(gb, 16); vui->sar.den = get_bits(gb, 16); } else - av_log(s->avctx, AV_LOG_WARNING, + av_log(avctx, AV_LOG_WARNING, "Unknown SAR index: %u.\n", sar_idx); } @@ -481,9 +523,9 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) vui->def_disp_win.top_offset = get_ue_golomb_long(gb) * 2; vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) * 2; - if (s->apply_defdispwin && - s->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { - av_log(s->avctx, AV_LOG_DEBUG, + if (apply_defdispwin && + avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { + av_log(avctx, AV_LOG_DEBUG, "discarding vui default display window, " "original values are l:%u r:%u t:%u b:%u\n", vui->def_disp_win.left_offset, @@ -507,7 +549,7 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); vui->vui_hrd_parameters_present_flag = get_bits1(gb); if (vui->vui_hrd_parameters_present_flag) - decode_hrd(s, 1, sps->max_sub_layers); + decode_hrd(gb, 1, sps->max_sub_layers); } vui->bitstream_restriction_flag = get_bits1(gb); @@ -549,9 +591,8 @@ static void set_default_scaling_list_data(ScalingList *sl) memcpy(sl->sl[3][1], default_scaling_list_inter, 64); } -static int scaling_list_data(HEVCContext *s, ScalingList *sl) +static int scaling_list_data(GetBitContext *gb, AVCodecContext *avctx, ScalingList *sl) { - GetBitContext *gb = &s->HEVClc.gb; uint8_t scaling_list_pred_mode_flag[4][6]; int32_t scaling_list_dc_coef[2][6]; int size_id, matrix_id, i, pos; @@ -566,7 +607,7 @@ static int scaling_list_data(HEVCContext *s, ScalingList *sl) if (delta) { // Copy from previous array. if (matrix_id < delta) { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "Invalid delta in scaling list data: %d.\n", delta); return AVERROR_INVALIDDATA; } @@ -606,36 +647,57 @@ static int scaling_list_data(HEVCContext *s, ScalingList *sl) return 0; } -int ff_hevc_decode_nal_sps(HEVCContext *s) +static int map_pixel_format(AVCodecContext *avctx, HEVCSPS *sps) { const AVPixFmtDescriptor *desc; - GetBitContext *gb = &s->HEVClc.gb; + if (sps->chroma_format_idc == 1) { + switch (sps->bit_depth) { + case 8: sps->pix_fmt = AV_PIX_FMT_YUV420P; break; + case 9: sps->pix_fmt = AV_PIX_FMT_YUV420P9; break; + case 10: sps->pix_fmt = AV_PIX_FMT_YUV420P10; break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", + sps->bit_depth); + return AVERROR_PATCHWELCOME; + } + } else { + av_log(avctx, AV_LOG_ERROR, + "non-4:2:0 support is currently unspecified.\n"); + return AVERROR_PATCHWELCOME; + } + + desc = av_pix_fmt_desc_get(sps->pix_fmt); + if (!desc) + return AVERROR(EINVAL); + + sps->hshift[0] = sps->vshift[0] = 0; + sps->hshift[2] = sps->hshift[1] = desc->log2_chroma_w; + sps->vshift[2] = sps->vshift[1] = desc->log2_chroma_h; + + sps->pixel_shift = sps->bit_depth > 8; + + return 0; +} + +int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, + int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx) +{ int ret = 0; - unsigned int sps_id = 0; int log2_diff_max_min_transform_block_size; int bit_depth_chroma, start, vui_present, sublayer_ordering_info; int i; - HEVCSPS *sps; - AVBufferRef *sps_buf = av_buffer_allocz(sizeof(*sps)); - - if (!sps_buf) - return AVERROR(ENOMEM); - sps = (HEVCSPS*)sps_buf->data; - - av_log(s->avctx, AV_LOG_DEBUG, "Decoding SPS\n"); - // Coded parameters sps->vps_id = get_bits(gb, 4); if (sps->vps_id >= MAX_VPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", sps->vps_id); + av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", sps->vps_id); ret = AVERROR_INVALIDDATA; goto err; } - if (!s->vps_list[sps->vps_id]) { - av_log(s->avctx, AV_LOG_ERROR, "VPS %d does not exist\n", + if (vps_list && !vps_list[sps->vps_id]) { + av_log(avctx, AV_LOG_ERROR, "VPS %d does not exist\n", sps->vps_id); ret = AVERROR_INVALIDDATA; goto err; @@ -643,7 +705,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->max_sub_layers = get_bits(gb, 3) + 1; if (sps->max_sub_layers > MAX_SUB_LAYERS) { - av_log(s->avctx, AV_LOG_ERROR, "sps_max_sub_layers out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "sps_max_sub_layers out of range: %d\n", sps->max_sub_layers); ret = AVERROR_INVALIDDATA; goto err; @@ -651,18 +713,19 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) skip_bits1(gb); // temporal_id_nesting_flag - parse_ptl(s, &sps->ptl, sps->max_sub_layers); + parse_ptl(gb, avctx, &sps->ptl, sps->max_sub_layers); - sps_id = get_ue_golomb_long(gb); - if (sps_id >= MAX_SPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", sps_id); + *sps_id = get_ue_golomb_long(gb); + if (*sps_id >= MAX_SPS_COUNT) { + av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", *sps_id); ret = AVERROR_INVALIDDATA; goto err; } sps->chroma_format_idc = get_ue_golomb_long(gb); if (sps->chroma_format_idc != 1) { - avpriv_report_missing_feature(s->avctx, "chroma_format_idc != 1\n"); + avpriv_report_missing_feature(avctx, "chroma_format_idc %d", + sps->chroma_format_idc); ret = AVERROR_PATCHWELCOME; goto err; } @@ -673,7 +736,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->width = get_ue_golomb_long(gb); sps->height = get_ue_golomb_long(gb); if ((ret = av_image_check_size(sps->width, - sps->height, 0, s->avctx)) < 0) + sps->height, 0, avctx)) < 0) goto err; if (get_bits1(gb)) { // pic_conformance_flag @@ -683,8 +746,8 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->pic_conf_win.top_offset = get_ue_golomb_long(gb) * 2; sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) * 2; - if (s->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { - av_log(s->avctx, AV_LOG_DEBUG, + if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { + av_log(avctx, AV_LOG_DEBUG, "discarding sps conformance window, " "original values are l:%u r:%u t:%u b:%u\n", sps->pic_conf_win.left_offset, @@ -703,7 +766,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->bit_depth = get_ue_golomb_long(gb) + 8; bit_depth_chroma = get_ue_golomb_long(gb) + 8; if (bit_depth_chroma != sps->bit_depth) { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "Luma bit depth (%d) is different from chroma bit depth (%d), " "this is unsupported.\n", sps->bit_depth, bit_depth_chroma); @@ -711,38 +774,14 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) goto err; } - if (sps->chroma_format_idc == 1) { - switch (sps->bit_depth) { - case 8: sps->pix_fmt = AV_PIX_FMT_YUV420P; break; - case 9: sps->pix_fmt = AV_PIX_FMT_YUV420P9; break; - case 10: sps->pix_fmt = AV_PIX_FMT_YUV420P10; break; - default: - av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", - sps->bit_depth); - ret = AVERROR_PATCHWELCOME; - goto err; - } - } else { - av_log(s->avctx, AV_LOG_ERROR, - "non-4:2:0 support is currently unspecified.\n"); - return AVERROR_PATCHWELCOME; - } - desc = av_pix_fmt_desc_get(sps->pix_fmt); - if (!desc) { - ret = AVERROR(EINVAL); + ret = map_pixel_format(avctx, sps); + if (ret < 0) goto err; - } - - sps->hshift[0] = sps->vshift[0] = 0; - sps->hshift[2] = sps->hshift[1] = desc->log2_chroma_w; - sps->vshift[2] = sps->vshift[1] = desc->log2_chroma_h; - - sps->pixel_shift = sps->bit_depth > 8; sps->log2_max_poc_lsb = get_ue_golomb_long(gb) + 4; if (sps->log2_max_poc_lsb > 16) { - av_log(s->avctx, AV_LOG_ERROR, "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", + av_log(avctx, AV_LOG_ERROR, "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", sps->log2_max_poc_lsb - 4); ret = AVERROR_INVALIDDATA; goto err; @@ -755,15 +794,15 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->temporal_layer[i].num_reorder_pics = get_ue_golomb_long(gb); sps->temporal_layer[i].max_latency_increase = get_ue_golomb_long(gb) - 1; if (sps->temporal_layer[i].max_dec_pic_buffering > MAX_DPB_SIZE) { - av_log(s->avctx, AV_LOG_ERROR, "sps_max_dec_pic_buffering_minus1 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "sps_max_dec_pic_buffering_minus1 out of range: %d\n", sps->temporal_layer[i].max_dec_pic_buffering - 1); ret = AVERROR_INVALIDDATA; goto err; } if (sps->temporal_layer[i].num_reorder_pics > sps->temporal_layer[i].max_dec_pic_buffering - 1) { - av_log(s->avctx, AV_LOG_WARNING, "sps_max_num_reorder_pics out of range: %d\n", + av_log(avctx, AV_LOG_WARNING, "sps_max_num_reorder_pics out of range: %d\n", sps->temporal_layer[i].num_reorder_pics); - if (s->avctx->err_recognition & AV_EF_EXPLODE || + if (avctx->err_recognition & AV_EF_EXPLODE || sps->temporal_layer[i].num_reorder_pics > MAX_DPB_SIZE - 1) { ret = AVERROR_INVALIDDATA; goto err; @@ -788,7 +827,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->log2_min_tb_size; if (sps->log2_min_tb_size >= sps->log2_min_cb_size) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid value for log2_min_tb_size"); + av_log(avctx, AV_LOG_ERROR, "Invalid value for log2_min_tb_size"); ret = AVERROR_INVALIDDATA; goto err; } @@ -800,7 +839,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) set_default_scaling_list_data(&sps->scaling_list); if (get_bits1(gb)) { - ret = scaling_list_data(s, &sps->scaling_list); + ret = scaling_list_data(gb, avctx, &sps->scaling_list); if (ret < 0) goto err; } @@ -817,7 +856,7 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->pcm.log2_max_pcm_cb_size = sps->pcm.log2_min_pcm_cb_size + get_ue_golomb_long(gb); if (sps->pcm.bit_depth > sps->bit_depth) { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "PCM bit depth (%d) is greater than normal bit depth (%d)\n", sps->pcm.bit_depth, sps->bit_depth); ret = AVERROR_INVALIDDATA; @@ -829,13 +868,13 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->nb_st_rps = get_ue_golomb_long(gb); if (sps->nb_st_rps > MAX_SHORT_TERM_RPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n", + av_log(avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n", sps->nb_st_rps); ret = AVERROR_INVALIDDATA; goto err; } for (i = 0; i < sps->nb_st_rps; i++) { - if ((ret = ff_hevc_decode_short_term_rps(s, &sps->st_rps[i], + if ((ret = ff_hevc_decode_short_term_rps(gb, avctx, &sps->st_rps[i], sps, 0)) < 0) goto err; } @@ -854,19 +893,19 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->vui.sar = (AVRational){0, 1}; vui_present = get_bits1(gb); if (vui_present) - decode_vui(s, sps); + decode_vui(gb, avctx, apply_defdispwin, sps); skip_bits1(gb); // sps_extension_flag - if (s->apply_defdispwin) { + if (apply_defdispwin) { sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; sps->output_window.right_offset += sps->vui.def_disp_win.right_offset; sps->output_window.top_offset += sps->vui.def_disp_win.top_offset; sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset; } if (sps->output_window.left_offset & (0x1F >> (sps->pixel_shift)) && - !(s->avctx->flags & CODEC_FLAG_UNALIGNED)) { + !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { sps->output_window.left_offset &= ~(0x1F >> (sps->pixel_shift)); - av_log(s->avctx, AV_LOG_WARNING, "Reducing left output window to %d " + av_log(avctx, AV_LOG_WARNING, "Reducing left output window to %d " "chroma samples to preserve alignment.\n", sps->output_window.left_offset); } @@ -875,13 +914,13 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) sps->output_height = sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset); if (sps->output_width <= 0 || sps->output_height <= 0) { - av_log(s->avctx, AV_LOG_WARNING, "Invalid visible frame dimensions: %dx%d.\n", + av_log(avctx, AV_LOG_WARNING, "Invalid visible frame dimensions: %dx%d.\n", sps->output_width, sps->output_height); - if (s->avctx->err_recognition & AV_EF_EXPLODE) { + if (avctx->err_recognition & AV_EF_EXPLODE) { ret = AVERROR_INVALIDDATA; goto err; } - av_log(s->avctx, AV_LOG_WARNING, + av_log(avctx, AV_LOG_WARNING, "Displaying the whole video surface.\n"); sps->output_window.left_offset = sps->output_window.right_offset = @@ -911,33 +950,61 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) if (sps->width & ((1 << sps->log2_min_cb_size) - 1) || sps->height & ((1 << sps->log2_min_cb_size) - 1)) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid coded frame dimensions.\n"); + av_log(avctx, AV_LOG_ERROR, "Invalid coded frame dimensions.\n"); goto err; } if (sps->log2_ctb_size > MAX_LOG2_CTB_SIZE) { - av_log(s->avctx, AV_LOG_ERROR, "CTB size out of range: 2^%d\n", sps->log2_ctb_size); + av_log(avctx, AV_LOG_ERROR, "CTB size out of range: 2^%d\n", sps->log2_ctb_size); goto err; } if (sps->max_transform_hierarchy_depth_inter > sps->log2_ctb_size - sps->log2_min_tb_size) { - av_log(s->avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_inter out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_inter out of range: %d\n", sps->max_transform_hierarchy_depth_inter); goto err; } if (sps->max_transform_hierarchy_depth_intra > sps->log2_ctb_size - sps->log2_min_tb_size) { - av_log(s->avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_intra out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_intra out of range: %d\n", sps->max_transform_hierarchy_depth_intra); goto err; } if (sps->log2_max_trafo_size > FFMIN(sps->log2_ctb_size, 5)) { - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "max transform block size out of range: %d\n", sps->log2_max_trafo_size); goto err; } - if (s->avctx->debug & FF_DEBUG_BITSTREAM) { - av_log(s->avctx, AV_LOG_DEBUG, + return 0; + +err: + return ret < 0 ? ret : AVERROR_INVALIDDATA; +} + +int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps, int apply_defdispwin) +{ + HEVCSPS *sps; + AVBufferRef *sps_buf = av_buffer_allocz(sizeof(*sps)); + unsigned int sps_id; + int ret; + + if (!sps_buf) + return AVERROR(ENOMEM); + sps = (HEVCSPS*)sps_buf->data; + + av_log(avctx, AV_LOG_DEBUG, "Decoding SPS\n"); + + ret = ff_hevc_parse_sps(sps, gb, &sps_id, + apply_defdispwin, + ps->vps_list, avctx); + if (ret < 0) { + av_buffer_unref(&sps_buf); + return ret; + } + + if (avctx->debug & FF_DEBUG_BITSTREAM) { + av_log(avctx, AV_LOG_DEBUG, "Parsed SPS: id %d; coded wxh: %dx%d; " "cropped wxh: %dx%d; pix_fmt: %s.\n", sps_id, sps->width, sps->height, @@ -948,23 +1015,15 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) /* check if this is a repeat of an already parsed SPS, then keep the * original one. * otherwise drop all PPSes that depend on it */ - if (s->sps_list[sps_id] && - !memcmp(s->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) { + if (ps->sps_list[sps_id] && + !memcmp(ps->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) { av_buffer_unref(&sps_buf); } else { - for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) { - if (s->pps_list[i] && ((HEVCPPS*)s->pps_list[i]->data)->sps_id == sps_id) - av_buffer_unref(&s->pps_list[i]); - } - av_buffer_unref(&s->sps_list[sps_id]); - s->sps_list[sps_id] = sps_buf; + remove_sps(ps, sps_id); + ps->sps_list[sps_id] = sps_buf; } return 0; - -err: - av_buffer_unref(&sps_buf); - return ret; } static void hevc_pps_free(void *opaque, uint8_t *data) @@ -985,14 +1044,139 @@ static void hevc_pps_free(void *opaque, uint8_t *data) av_freep(&pps); } -int ff_hevc_decode_nal_pps(HEVCContext *s) +static inline int setup_pps(AVCodecContext *avctx, GetBitContext *gb, + HEVCPPS *pps, HEVCSPS *sps) { - GetBitContext *gb = &s->HEVClc.gb; - HEVCSPS *sps = NULL; + int log2_diff; int pic_area_in_ctbs, pic_area_in_min_tbs; - int log2_diff_ctb_min_tb_size; int i, j, x, y, ctb_addr_rs, tile_id; - int ret = 0; + + // Inferred parameters + pps->col_bd = av_malloc_array(pps->num_tile_columns + 1, sizeof(*pps->col_bd)); + pps->row_bd = av_malloc_array(pps->num_tile_rows + 1, sizeof(*pps->row_bd)); + pps->col_idxX = av_malloc_array(sps->ctb_width, sizeof(*pps->col_idxX)); + if (!pps->col_bd || !pps->row_bd || !pps->col_idxX) + return AVERROR(ENOMEM); + + if (pps->uniform_spacing_flag) { + if (!pps->column_width) { + pps->column_width = av_malloc_array(pps->num_tile_columns, sizeof(*pps->column_width)); + pps->row_height = av_malloc_array(pps->num_tile_rows, sizeof(*pps->row_height)); + } + if (!pps->column_width || !pps->row_height) + return AVERROR(ENOMEM); + + for (i = 0; i < pps->num_tile_columns; i++) { + pps->column_width[i] = ((i + 1) * sps->ctb_width) / pps->num_tile_columns - + (i * sps->ctb_width) / pps->num_tile_columns; + } + + for (i = 0; i < pps->num_tile_rows; i++) { + pps->row_height[i] = ((i + 1) * sps->ctb_height) / pps->num_tile_rows - + (i * sps->ctb_height) / pps->num_tile_rows; + } + } + + pps->col_bd[0] = 0; + for (i = 0; i < pps->num_tile_columns; i++) + pps->col_bd[i + 1] = pps->col_bd[i] + pps->column_width[i]; + + pps->row_bd[0] = 0; + for (i = 0; i < pps->num_tile_rows; i++) + pps->row_bd[i + 1] = pps->row_bd[i] + pps->row_height[i]; + + for (i = 0, j = 0; i < sps->ctb_width; i++) { + if (i > pps->col_bd[j]) + j++; + pps->col_idxX[i] = j; + } + + /** + * 6.5 + */ + pic_area_in_ctbs = sps->ctb_width * sps->ctb_height; + pic_area_in_min_tbs = sps->min_tb_width * sps->min_tb_height; + + pps->ctb_addr_rs_to_ts = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_rs_to_ts)); + pps->ctb_addr_ts_to_rs = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_ts_to_rs)); + pps->tile_id = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->tile_id)); + pps->min_tb_addr_zs = av_malloc_array(pic_area_in_min_tbs, sizeof(*pps->min_tb_addr_zs)); + if (!pps->ctb_addr_rs_to_ts || !pps->ctb_addr_ts_to_rs || + !pps->tile_id || !pps->min_tb_addr_zs) { + return AVERROR(ENOMEM); + } + + for (ctb_addr_rs = 0; ctb_addr_rs < pic_area_in_ctbs; ctb_addr_rs++) { + int tb_x = ctb_addr_rs % sps->ctb_width; + int tb_y = ctb_addr_rs / sps->ctb_width; + int tile_x = 0; + int tile_y = 0; + int val = 0; + + for (i = 0; i < pps->num_tile_columns; i++) { + if (tb_x < pps->col_bd[i + 1]) { + tile_x = i; + break; + } + } + + for (i = 0; i < pps->num_tile_rows; i++) { + if (tb_y < pps->row_bd[i + 1]) { + tile_y = i; + break; + } + } + + for (i = 0; i < tile_x; i++) + val += pps->row_height[tile_y] * pps->column_width[i]; + for (i = 0; i < tile_y; i++) + val += sps->ctb_width * pps->row_height[i]; + + val += (tb_y - pps->row_bd[tile_y]) * pps->column_width[tile_x] + + tb_x - pps->col_bd[tile_x]; + + pps->ctb_addr_rs_to_ts[ctb_addr_rs] = val; + pps->ctb_addr_ts_to_rs[val] = ctb_addr_rs; + } + + for (j = 0, tile_id = 0; j < pps->num_tile_rows; j++) + for (i = 0; i < pps->num_tile_columns; i++, tile_id++) + for (y = pps->row_bd[j]; y < pps->row_bd[j + 1]; y++) + for (x = pps->col_bd[i]; x < pps->col_bd[i + 1]; x++) + pps->tile_id[pps->ctb_addr_rs_to_ts[y * sps->ctb_width + x]] = tile_id; + + pps->tile_pos_rs = av_malloc_array(tile_id, sizeof(*pps->tile_pos_rs)); + if (!pps->tile_pos_rs) + return AVERROR(ENOMEM); + + for (j = 0; j < pps->num_tile_rows; j++) + for (i = 0; i < pps->num_tile_columns; i++) + pps->tile_pos_rs[j * pps->num_tile_columns + i] = + pps->row_bd[j] * sps->ctb_width + pps->col_bd[i]; + + log2_diff = sps->log2_ctb_size - sps->log2_min_tb_size; + for (y = 0; y < sps->min_tb_height; y++) { + for (x = 0; x < sps->min_tb_width; x++) { + int tb_x = x >> log2_diff; + int tb_y = y >> log2_diff; + int rs = sps->ctb_width * tb_y + tb_x; + int val = pps->ctb_addr_rs_to_ts[rs] << (log2_diff * 2); + for (i = 0; i < log2_diff; i++) { + int m = 1 << i; + val += (m & x ? m * m : 0) + (m & y ? 2 * m * m : 0); + } + pps->min_tb_addr_zs[y * sps->min_tb_width + x] = val; + } + } + + return 0; +} + +int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, + HEVCParamSets *ps) +{ + HEVCSPS *sps = NULL; + int i, ret = 0; unsigned int pps_id = 0; AVBufferRef *pps_buf; @@ -1008,7 +1192,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) return AVERROR(ENOMEM); } - av_log(s->avctx, AV_LOG_DEBUG, "Decoding PPS\n"); + av_log(avctx, AV_LOG_DEBUG, "Decoding PPS\n"); // Default values pps->loop_filter_across_tiles_enabled_flag = 1; @@ -1022,22 +1206,22 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) // Coded parameters pps_id = get_ue_golomb_long(gb); if (pps_id >= MAX_PPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); + av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); ret = AVERROR_INVALIDDATA; goto err; } pps->sps_id = get_ue_golomb_long(gb); if (pps->sps_id >= MAX_SPS_COUNT) { - av_log(s->avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", pps->sps_id); + av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", pps->sps_id); ret = AVERROR_INVALIDDATA; goto err; } - if (!s->sps_list[pps->sps_id]) { - av_log(s->avctx, AV_LOG_ERROR, "SPS %u does not exist.\n", pps->sps_id); + if (!ps->sps_list[pps->sps_id]) { + av_log(avctx, AV_LOG_ERROR, "SPS %u does not exist.\n", pps->sps_id); ret = AVERROR_INVALIDDATA; goto err; } - sps = (HEVCSPS *)s->sps_list[pps->sps_id]->data; + sps = (HEVCSPS *)ps->sps_list[pps->sps_id]->data; pps->dependent_slice_segments_enabled_flag = get_bits1(gb); pps->output_flag_present_flag = get_bits1(gb); @@ -1062,14 +1246,14 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->cb_qp_offset = get_se_golomb(gb); if (pps->cb_qp_offset < -12 || pps->cb_qp_offset > 12) { - av_log(s->avctx, AV_LOG_ERROR, "pps_cb_qp_offset out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "pps_cb_qp_offset out of range: %d\n", pps->cb_qp_offset); ret = AVERROR_INVALIDDATA; goto err; } pps->cr_qp_offset = get_se_golomb(gb); if (pps->cr_qp_offset < -12 || pps->cr_qp_offset > 12) { - av_log(s->avctx, AV_LOG_ERROR, "pps_cr_qp_offset out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "pps_cr_qp_offset out of range: %d\n", pps->cr_qp_offset); ret = AVERROR_INVALIDDATA; goto err; @@ -1088,14 +1272,14 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->num_tile_rows = get_ue_golomb_long(gb) + 1; if (pps->num_tile_columns == 0 || pps->num_tile_columns >= sps->width) { - av_log(s->avctx, AV_LOG_ERROR, "num_tile_columns_minus1 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "num_tile_columns_minus1 out of range: %d\n", pps->num_tile_columns - 1); ret = AVERROR_INVALIDDATA; goto err; } if (pps->num_tile_rows == 0 || pps->num_tile_rows >= sps->height) { - av_log(s->avctx, AV_LOG_ERROR, "num_tile_rows_minus1 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "num_tile_rows_minus1 out of range: %d\n", pps->num_tile_rows - 1); ret = AVERROR_INVALIDDATA; goto err; @@ -1116,7 +1300,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) sum += pps->column_width[i]; } if (sum >= sps->ctb_width) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid tile widths.\n"); + av_log(avctx, AV_LOG_ERROR, "Invalid tile widths.\n"); ret = AVERROR_INVALIDDATA; goto err; } @@ -1128,7 +1312,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) sum += pps->row_height[i]; } if (sum >= sps->ctb_height) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid tile heights.\n"); + av_log(avctx, AV_LOG_ERROR, "Invalid tile heights.\n"); ret = AVERROR_INVALIDDATA; goto err; } @@ -1147,13 +1331,13 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->beta_offset = get_se_golomb(gb) * 2; pps->tc_offset = get_se_golomb(gb) * 2; if (pps->beta_offset/2 < -6 || pps->beta_offset/2 > 6) { - av_log(s->avctx, AV_LOG_ERROR, "pps_beta_offset_div2 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "pps_beta_offset_div2 out of range: %d\n", pps->beta_offset/2); ret = AVERROR_INVALIDDATA; goto err; } if (pps->tc_offset/2 < -6 || pps->tc_offset/2 > 6) { - av_log(s->avctx, AV_LOG_ERROR, "pps_tc_offset_div2 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "pps_tc_offset_div2 out of range: %d\n", pps->tc_offset/2); ret = AVERROR_INVALIDDATA; goto err; @@ -1164,14 +1348,14 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->scaling_list_data_present_flag = get_bits1(gb); if (pps->scaling_list_data_present_flag) { set_default_scaling_list_data(&pps->scaling_list); - ret = scaling_list_data(s, &pps->scaling_list); + ret = scaling_list_data(gb, avctx, &pps->scaling_list); if (ret < 0) goto err; } pps->lists_modification_present_flag = get_bits1(gb); pps->log2_parallel_merge_level = get_ue_golomb_long(gb) + 2; if (pps->log2_parallel_merge_level > sps->log2_ctb_size) { - av_log(s->avctx, AV_LOG_ERROR, "log2_parallel_merge_level_minus2 out of range: %d\n", + av_log(avctx, AV_LOG_ERROR, "log2_parallel_merge_level_minus2 out of range: %d\n", pps->log2_parallel_merge_level - 2); ret = AVERROR_INVALIDDATA; goto err; @@ -1180,133 +1364,12 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->slice_header_extension_present_flag = get_bits1(gb); skip_bits1(gb); // pps_extension_flag - // Inferred parameters - pps->col_bd = av_malloc_array(pps->num_tile_columns + 1, sizeof(*pps->col_bd)); - pps->row_bd = av_malloc_array(pps->num_tile_rows + 1, sizeof(*pps->row_bd)); - pps->col_idxX = av_malloc_array(sps->ctb_width, sizeof(*pps->col_idxX)); - if (!pps->col_bd || !pps->row_bd || !pps->col_idxX) { - ret = AVERROR(ENOMEM); - goto err; - } - - if (pps->uniform_spacing_flag) { - if (!pps->column_width) { - pps->column_width = av_malloc_array(pps->num_tile_columns, sizeof(*pps->column_width)); - pps->row_height = av_malloc_array(pps->num_tile_rows, sizeof(*pps->row_height)); - } - if (!pps->column_width || !pps->row_height) { - ret = AVERROR(ENOMEM); - goto err; - } - - for (i = 0; i < pps->num_tile_columns; i++) { - pps->column_width[i] = ((i + 1) * sps->ctb_width) / pps->num_tile_columns - - (i * sps->ctb_width) / pps->num_tile_columns; - } - - for (i = 0; i < pps->num_tile_rows; i++) { - pps->row_height[i] = ((i + 1) * sps->ctb_height) / pps->num_tile_rows - - (i * sps->ctb_height) / pps->num_tile_rows; - } - } - - pps->col_bd[0] = 0; - for (i = 0; i < pps->num_tile_columns; i++) - pps->col_bd[i + 1] = pps->col_bd[i] + pps->column_width[i]; - - pps->row_bd[0] = 0; - for (i = 0; i < pps->num_tile_rows; i++) - pps->row_bd[i + 1] = pps->row_bd[i] + pps->row_height[i]; - - for (i = 0, j = 0; i < sps->ctb_width; i++) { - if (i > pps->col_bd[j]) - j++; - pps->col_idxX[i] = j; - } - - /** - * 6.5 - */ - pic_area_in_ctbs = sps->ctb_width * sps->ctb_height; - pic_area_in_min_tbs = sps->min_tb_width * sps->min_tb_height; - - pps->ctb_addr_rs_to_ts = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_rs_to_ts)); - pps->ctb_addr_ts_to_rs = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_ts_to_rs)); - pps->tile_id = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->tile_id)); - pps->min_tb_addr_zs = av_malloc_array(pic_area_in_min_tbs, sizeof(*pps->min_tb_addr_zs)); - if (!pps->ctb_addr_rs_to_ts || !pps->ctb_addr_ts_to_rs || - !pps->tile_id || !pps->min_tb_addr_zs) { - ret = AVERROR(ENOMEM); - goto err; - } - - for (ctb_addr_rs = 0; ctb_addr_rs < pic_area_in_ctbs; ctb_addr_rs++) { - int tb_x = ctb_addr_rs % sps->ctb_width; - int tb_y = ctb_addr_rs / sps->ctb_width; - int tile_x = 0; - int tile_y = 0; - int val = 0; - - for (i = 0; i < pps->num_tile_columns; i++) { - if (tb_x < pps->col_bd[i + 1]) { - tile_x = i; - break; - } - } - - for (i = 0; i < pps->num_tile_rows; i++) { - if (tb_y < pps->row_bd[i + 1]) { - tile_y = i; - break; - } - } - - for (i = 0; i < tile_x; i++) - val += pps->row_height[tile_y] * pps->column_width[i]; - for (i = 0; i < tile_y; i++) - val += sps->ctb_width * pps->row_height[i]; - - val += (tb_y - pps->row_bd[tile_y]) * pps->column_width[tile_x] + - tb_x - pps->col_bd[tile_x]; - - pps->ctb_addr_rs_to_ts[ctb_addr_rs] = val; - pps->ctb_addr_ts_to_rs[val] = ctb_addr_rs; - } - - for (j = 0, tile_id = 0; j < pps->num_tile_rows; j++) - for (i = 0; i < pps->num_tile_columns; i++, tile_id++) - for (y = pps->row_bd[j]; y < pps->row_bd[j + 1]; y++) - for (x = pps->col_bd[i]; x < pps->col_bd[i + 1]; x++) - pps->tile_id[pps->ctb_addr_rs_to_ts[y * sps->ctb_width + x]] = tile_id; - - pps->tile_pos_rs = av_malloc_array(tile_id, sizeof(*pps->tile_pos_rs)); - if (!pps->tile_pos_rs) { - ret = AVERROR(ENOMEM); + ret = setup_pps(avctx, gb, pps, sps); + if (ret < 0) goto err; - } - - for (j = 0; j < pps->num_tile_rows; j++) - for (i = 0; i < pps->num_tile_columns; i++) - pps->tile_pos_rs[j * pps->num_tile_columns + i] = pps->row_bd[j] * sps->ctb_width + pps->col_bd[i]; - - log2_diff_ctb_min_tb_size = sps->log2_ctb_size - sps->log2_min_tb_size; - for (y = 0; y < sps->min_tb_height; y++) { - for (x = 0; x < sps->min_tb_width; x++) { - int tb_x = x >> log2_diff_ctb_min_tb_size; - int tb_y = y >> log2_diff_ctb_min_tb_size; - int ctb_addr_rs = sps->ctb_width * tb_y + tb_x; - int val = pps->ctb_addr_rs_to_ts[ctb_addr_rs] << - (log2_diff_ctb_min_tb_size * 2); - for (i = 0; i < log2_diff_ctb_min_tb_size; i++) { - int m = 1 << i; - val += (m & x ? m * m : 0) + (m & y ? 2 * m * m : 0); - } - pps->min_tb_addr_zs[y * sps->min_tb_width + x] = val; - } - } - av_buffer_unref(&s->pps_list[pps_id]); - s->pps_list[pps_id] = pps_buf; + remove_pps(ps, pps_id); + ps->pps_list[pps_id] = pps_buf; return 0; diff --git a/libavcodec/hevc_ps_enc.c b/libavcodec/hevc_ps_enc.c new file mode 100644 index 0000000..007a132 --- /dev/null +++ b/libavcodec/hevc_ps_enc.c @@ -0,0 +1,116 @@ +/* + * HEVC Parameter Set encoding + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "golomb.h" +#include "hevc.h" +#include "put_bits.h" + +static void write_ptl_layer(PutBitContext *pb, PTLCommon *ptl) +{ + int i; + + put_bits(pb, 2, ptl->profile_space); + put_bits(pb, 1, ptl->tier_flag); + put_bits(pb, 5, ptl->profile_idc); + for (i = 0; i < 32; i++) + put_bits(pb, 1, ptl->profile_compatibility_flag[i]); + put_bits(pb, 1, ptl->progressive_source_flag); + put_bits(pb, 1, ptl->interlaced_source_flag); + put_bits(pb, 1, ptl->non_packed_constraint_flag); + put_bits(pb, 1, ptl->frame_only_constraint_flag); + put_bits32(pb, 0); // reserved + put_bits(pb, 12, 0); // reserved +} + +static void write_ptl(PutBitContext *pb, PTL *ptl, int max_num_sub_layers) +{ + int i; + + write_ptl_layer(pb, &ptl->general_ptl); + put_bits(pb, 8, ptl->general_ptl.level_idc); + + for (i = 0; i < max_num_sub_layers - 1; i++) { + put_bits(pb, 1, ptl->sub_layer_profile_present_flag[i]); + put_bits(pb, 1, ptl->sub_layer_level_present_flag[i]); + } + + if (max_num_sub_layers > 1) + for (i = max_num_sub_layers - 1; i < 8; i++) + put_bits(pb, 2, 0); // reserved + + for (i = 0; i < max_num_sub_layers - 1; i++) { + if (ptl->sub_layer_profile_present_flag[i]) + write_ptl_layer(pb, &ptl->sub_layer_ptl[i]); + if (ptl->sub_layer_level_present_flag[i]) + put_bits(pb, 8, ptl->sub_layer_ptl[i].level_idc); + } +} + +int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id, + uint8_t *buf, int buf_size) +{ + PutBitContext pb; + int i; + + init_put_bits(&pb, buf, buf_size); + put_bits(&pb, 4, id); + put_bits(&pb, 2, 3); // reserved + put_bits(&pb, 6, vps->vps_max_layers - 1); + put_bits(&pb, 3, vps->vps_max_sub_layers - 1); + put_bits(&pb, 1, vps->vps_temporal_id_nesting_flag); + put_bits(&pb, 16, 0xffff); // reserved + + write_ptl(&pb, &vps->ptl, vps->vps_max_sub_layers); + + put_bits(&pb, 1, vps->vps_sub_layer_ordering_info_present_flag); + for (i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_layers - 1; + i < vps->vps_max_sub_layers; i++) { + set_ue_golomb(&pb, vps->vps_max_dec_pic_buffering[i] - 1); + set_ue_golomb(&pb, vps->vps_num_reorder_pics[i]); + set_ue_golomb(&pb, vps->vps_max_latency_increase[i] + 1); + } + + put_bits(&pb, 6, vps->vps_max_layer_id); + set_ue_golomb(&pb, vps->vps_num_layer_sets - 1); + + // writing layer_id_included_flag not supported + if (vps->vps_num_layer_sets > 1) + return AVERROR_PATCHWELCOME; + + put_bits(&pb, 1, vps->vps_timing_info_present_flag); + if (vps->vps_timing_info_present_flag) { + put_bits32(&pb, vps->vps_num_units_in_tick); + put_bits32(&pb, vps->vps_time_scale); + put_bits(&pb, 1, vps->vps_poc_proportional_to_timing_flag); + if (vps->vps_poc_proportional_to_timing_flag) + set_ue_golomb(&pb, vps->vps_num_ticks_poc_diff_one - 1); + + // writing HRD parameters not supported + if (vps->vps_num_hrd_parameters) + return AVERROR_PATCHWELCOME; + } + + put_bits(&pb, 1, 0); // extension flag + + put_bits(&pb, 1, 1); // stop bit + avpriv_align_put_bits(&pb); + + return put_bits_count(&pb) / 8; +} diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 658ead7..b51f259 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/pixdesc.h" #include "internal.h" @@ -46,16 +47,19 @@ void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) frame->refPicList = NULL; frame->collocated_ref = NULL; + + av_buffer_unref(&frame->hwaccel_priv_buf); + frame->hwaccel_picture_private = NULL; } } RefPicList *ff_hevc_get_ref_list(HEVCContext *s, HEVCFrame *ref, int x0, int y0) { - int x_cb = x0 >> s->sps->log2_ctb_size; - int y_cb = y0 >> s->sps->log2_ctb_size; - int pic_width_cb = (s->sps->width + (1 << s->sps->log2_ctb_size) - 1) >> - s->sps->log2_ctb_size; - int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb]; + int x_cb = x0 >> s->ps.sps->log2_ctb_size; + int y_cb = y0 >> s->ps.sps->log2_ctb_size; + int pic_width_cb = (s->ps.sps->width + (1 << s->ps.sps->log2_ctb_size) - 1) >> + s->ps.sps->log2_ctb_size; + int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb]; return (RefPicList *)ref->rpl_tab[ctb_addr_ts]; } @@ -88,7 +92,7 @@ static HEVCFrame *alloc_frame(HEVCContext *s) if (ret < 0) return NULL; - frame->rpl_buf = av_buffer_allocz(s->nb_nals * sizeof(RefPicListTab)); + frame->rpl_buf = av_buffer_allocz(s->pkt.nb_nals * sizeof(RefPicListTab)); if (!frame->rpl_buf) goto fail; @@ -101,10 +105,21 @@ static HEVCFrame *alloc_frame(HEVCContext *s) if (!frame->rpl_tab_buf) goto fail; frame->rpl_tab = (RefPicListTab **)frame->rpl_tab_buf->data; - frame->ctb_count = s->sps->ctb_width * s->sps->ctb_height; + frame->ctb_count = s->ps.sps->ctb_width * s->ps.sps->ctb_height; for (j = 0; j < frame->ctb_count; j++) frame->rpl_tab[j] = (RefPicListTab *)frame->rpl_buf->data; + if (s->avctx->hwaccel) { + const AVHWAccel *hwaccel = s->avctx->hwaccel; + av_assert0(!frame->hwaccel_picture_private); + if (hwaccel->frame_priv_data_size) { + frame->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + if (!frame->hwaccel_priv_buf) + goto fail; + frame->hwaccel_picture_private = frame->hwaccel_priv_buf->data; + } + } + return frame; fail: @@ -146,7 +161,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc) ref->poc = poc; ref->sequence = s->seq_decode; - ref->window = s->sps->output_window; + ref->window = s->ps.sps->output_window; return 0; } @@ -171,8 +186,8 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) } /* wait for more frames before output */ - if (!flush && s->seq_output == s->seq_decode && s->sps && - nb_output <= s->sps->temporal_layer[s->sps->max_sub_layers - 1].num_reorder_pics) + if (!flush && s->seq_output == s->seq_decode && s->ps.sps && + nb_output <= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].num_reorder_pics) return 0; if (nb_output) { @@ -183,7 +198,7 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) if (!desc) return AVERROR_BUG; - pixel_shift = desc->comp[0].depth_minus1 > 7; + pixel_shift = desc->comp[0].depth > 8; ret = av_frame_ref(out, frame->frame); ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); @@ -215,7 +230,7 @@ static int init_slice_rpl(HEVCContext *s) { HEVCFrame *frame = s->ref; int ctb_count = frame->ctb_count; - int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; + int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; int i; if (s->slice_idx >= frame->rpl_buf->size / sizeof(RefPicListTab)) @@ -302,7 +317,7 @@ int ff_hevc_slice_rpl(HEVCContext *s) static HEVCFrame *find_ref_idx(HEVCContext *s, int poc) { int i; - int LtMask = (1 << s->sps->log2_max_poc_lsb) - 1; + int LtMask = (1 << s->ps.sps->log2_max_poc_lsb) - 1; for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { HEVCFrame *ref = &s->DPB[i]; @@ -340,17 +355,19 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc) if (!frame) return NULL; - if (!s->sps->pixel_shift) { - for (i = 0; frame->frame->buf[i]; i++) - memset(frame->frame->buf[i]->data, 1 << (s->sps->bit_depth - 1), - frame->frame->buf[i]->size); - } else { - for (i = 0; frame->frame->data[i]; i++) - for (y = 0; y < (s->sps->height >> s->sps->vshift[i]); y++) - for (x = 0; x < (s->sps->width >> s->sps->hshift[i]); x++) { - AV_WN16(frame->frame->data[i] + y * frame->frame->linesize[i] + 2 * x, - 1 << (s->sps->bit_depth - 1)); - } + if (!s->avctx->hwaccel) { + if (!s->ps.sps->pixel_shift) { + for (i = 0; frame->frame->buf[i]; i++) + memset(frame->frame->buf[i]->data, 1 << (s->ps.sps->bit_depth - 1), + frame->frame->buf[i]->size); + } else { + for (i = 0; frame->frame->data[i]; i++) + for (y = 0; y < (s->ps.sps->height >> s->ps.sps->vshift[i]); y++) + for (x = 0; x < (s->ps.sps->width >> s->ps.sps->hshift[i]); x++) { + AV_WN16(frame->frame->data[i] + y * frame->frame->linesize[i] + 2 * x, + 1 << (s->ps.sps->bit_depth - 1)); + } + } } frame->poc = poc; @@ -390,7 +407,7 @@ int ff_hevc_frame_rps(HEVCContext *s) const ShortTermRPS *short_rps = s->sh.short_term_rps; const LongTermRPS *long_rps = &s->sh.long_term_rps; RefPicList *rps = s->rps; - int i, ret; + int i, ret = 0; if (!short_rps) { rps[0].nb_refs = rps[1].nb_refs = 0; @@ -424,7 +441,7 @@ int ff_hevc_frame_rps(HEVCContext *s) ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF); if (ret < 0) - return ret; + goto fail; } /* add the long refs */ @@ -434,19 +451,20 @@ int ff_hevc_frame_rps(HEVCContext *s) ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF); if (ret < 0) - return ret; + goto fail; } +fail: /* release any frames that are now unused */ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) ff_hevc_unref_frame(s, &s->DPB[i], 0); - return 0; + return ret; } int ff_hevc_compute_poc(HEVCContext *s, int poc_lsb) { - int max_poc_lsb = 1 << s->sps->log2_max_poc_lsb; + int max_poc_lsb = 1 << s->ps.sps->log2_max_poc_lsb; int prev_poc_lsb = s->pocTid0 % max_poc_lsb; int prev_poc_msb = s->pocTid0 - prev_poc_lsb; int poc_msb; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 978a0e3..17cef67 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -25,7 +25,35 @@ #include "golomb.h" #include "hevc.h" -static void decode_nal_sei_decoded_picture_hash(HEVCContext *s) +enum HEVC_SEI_TYPE { + SEI_TYPE_BUFFERING_PERIOD = 0, + SEI_TYPE_PICTURE_TIMING = 1, + SEI_TYPE_PAN_SCAN_RECT = 2, + SEI_TYPE_FILLER_PAYLOAD = 3, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, + SEI_TYPE_USER_DATA_UNREGISTERED = 5, + SEI_TYPE_RECOVERY_POINT = 6, + SEI_TYPE_SCENE_INFO = 9, + SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, + SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, + SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, + SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, + SEI_TYPE_POST_FILTER_HINT = 22, + SEI_TYPE_TONE_MAPPING_INFO = 23, + SEI_TYPE_FRAME_PACKING = 45, + SEI_TYPE_DISPLAY_ORIENTATION = 47, + SEI_TYPE_SOP_DESCRIPTION = 128, + SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, + SEI_TYPE_DECODING_UNIT_INFO = 130, + SEI_TYPE_TEMPORAL_LEVEL0_INDEX = 131, + SEI_TYPE_DECODED_PICTURE_HASH = 132, + SEI_TYPE_SCALABLE_NESTING = 133, + SEI_TYPE_REGION_REFRESH_INFO = 134, + SEI_TYPE_MASTERING_DISPLAY_INFO = 137, + SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, +}; + +static int decode_nal_sei_decoded_picture_hash(HEVCContext *s) { int cIdx, i; GetBitContext *gb = &s->HEVClc.gb; @@ -44,9 +72,10 @@ static void decode_nal_sei_decoded_picture_hash(HEVCContext *s) skip_bits(gb, 32); } } + return 0; } -static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) +static int decode_nal_sei_frame_packing_arrangement(HEVCContext *s) { GetBitContext *gb = &s->HEVClc.gb; @@ -66,12 +95,13 @@ static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) if (!s->quincunx_subsampling && s->frame_packing_arrangement_type != 5) skip_bits(gb, 16); // frame[01]_grid_position_[xy] skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte - skip_bits1(gb); // frame_packing_arrangement_persistance_flag + skip_bits1(gb); // frame_packing_arrangement_persistence_flag } skip_bits1(gb); // upsampled_aspect_ratio_flag + return 0; } -static void decode_nal_sei_display_orientation(HEVCContext *s) +static int decode_nal_sei_display_orientation(HEVCContext *s) { GetBitContext *gb = &s->HEVClc.gb; @@ -84,6 +114,40 @@ static void decode_nal_sei_display_orientation(HEVCContext *s) s->sei_anticlockwise_rotation = get_bits(gb, 16); skip_bits1(gb); // display_orientation_persistence_flag } + + return 0; +} + +static int decode_nal_sei_prefix(HEVCContext *s, int type, int size) +{ + GetBitContext *gb = &s->HEVClc.gb; + + switch (type) { + case 256: // Mismatched value from HM 8.1 + return decode_nal_sei_decoded_picture_hash(s); + case SEI_TYPE_FRAME_PACKING: + return decode_nal_sei_frame_packing_arrangement(s); + case SEI_TYPE_DISPLAY_ORIENTATION: + return decode_nal_sei_display_orientation(s); + default: + av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); + skip_bits_long(gb, 8 * size); + return 0; + } +} + +static int decode_nal_sei_suffix(HEVCContext *s, int type, int size) +{ + GetBitContext *gb = &s->HEVClc.gb; + + switch (type) { + case SEI_TYPE_DECODED_PICTURE_HASH: + return decode_nal_sei_decoded_picture_hash(s); + default: + av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); + skip_bits_long(gb, 8 * size); + return 0; + } } static int decode_nal_sei_message(HEVCContext *s) @@ -105,23 +169,9 @@ static int decode_nal_sei_message(HEVCContext *s) payload_size += byte; } if (s->nal_unit_type == NAL_SEI_PREFIX) { - if (payload_type == 256) - decode_nal_sei_decoded_picture_hash(s); - else if (payload_type == 45) - decode_nal_sei_frame_packing_arrangement(s); - else if (payload_type == 47) - decode_nal_sei_display_orientation(s); - else { - av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); - skip_bits(gb, 8 * payload_size); - } + return decode_nal_sei_prefix(s, payload_type, payload_size); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ - if (payload_type == 132) - decode_nal_sei_decoded_picture_hash(s); - else { - av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", payload_type); - skip_bits(gb, 8 * payload_size); - } + return decode_nal_sei_suffix(s, payload_type, payload_size); } return 0; } diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index 0abee9b..7c19198 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -89,7 +89,7 @@ static const int8_t transform[32][32] = { 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4 }, }; -DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters[7][16]) = { +DECLARE_ALIGNED(16, const int16_t, ff_hevc_epel_coeffs[7][16]) = { { -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2 }, { -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2 }, { -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4 }, @@ -99,6 +99,28 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters[7][16]) = { { -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2 }, }; +DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_coeffs8[7][16]) = { + { -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2 }, + { -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2 }, + { -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4 }, + { -4, 36, 36, -4, -4, 36, 36, -4, -4, 36, 36, -4, -4, 36, 36, -4 }, + { -4, 28, 46, -6, -4, 28, 46, -6, -4, 28, 46, -6, -4, 28, 46, -6 }, + { -2, 16, 54, -4, -2, 16, 54, -4, -2, 16, 54, -4, -2, 16, 54, -4 }, + { -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2 }, +}; + +DECLARE_ALIGNED(16, const int16_t, ff_hevc_qpel_coeffs[3][8]) = { + { -1, 4, -10, 58, 17, -5, 1, 0 }, + { -1, 4, -11, 40, 40, -11, 4, -1 }, + { 0, 1, -5, 17, 58, -10, 4, -1 }, +}; + +DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_coeffs8[3][16]) = { + { -1, 4, -10, 58, 17, -5, 1, 0, -1, 4, -10, 58, 17, -5, 1, 0 }, + { -1, 4, -11, 40, 40, -11, 4, -1, -1, 4, -11, 40, 40, -11, 4, -1 }, + { 0, 1, -5, 17, 58, -10, 4, -1, 0, 1, -5, 17, 58, -10, 4, -1 }, +}; + #define BIT_DEPTH 8 #include "hevcdsp_template.c" #undef BIT_DEPTH @@ -116,19 +138,47 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) #undef FUNC #define FUNC(a, depth) a ## _ ## depth +#define QPEL_FUNC(i, width, depth) \ + hevcdsp->put_hevc_qpel[0][0][i] = FUNC(put_hevc_qpel_pixels_ ## width, depth); \ + hevcdsp->put_hevc_qpel[0][1][i] = FUNC(put_hevc_qpel_h_ ## width, depth); \ + hevcdsp->put_hevc_qpel[1][0][i] = FUNC(put_hevc_qpel_v_ ## width, depth); \ + hevcdsp->put_hevc_qpel[1][1][i] = FUNC(put_hevc_qpel_hv_ ## width, depth); \ + +#define EPEL_FUNC(i, width, depth) \ + hevcdsp->put_hevc_epel[0][0][i] = FUNC(put_hevc_epel_pixels_ ## width, depth); \ + hevcdsp->put_hevc_epel[0][1][i] = FUNC(put_hevc_epel_h_ ## width, depth); \ + hevcdsp->put_hevc_epel[1][0][i] = FUNC(put_hevc_epel_v_ ## width, depth); \ + hevcdsp->put_hevc_epel[1][1][i] = FUNC(put_hevc_epel_hv_ ## width, depth); \ + +#define PRED_FUNC(i, width, depth) \ + hevcdsp->put_unweighted_pred[i] = FUNC(put_unweighted_pred_ ## width, depth); \ + hevcdsp->put_unweighted_pred_avg[i] = FUNC(put_unweighted_pred_avg_ ## width, depth); \ + hevcdsp->weighted_pred[i] = FUNC(put_weighted_pred_ ## width, depth); \ + hevcdsp->weighted_pred_avg[i] = FUNC(put_weighted_pred_avg_ ## width, depth); \ + +#define PRED_FUNC_CHROMA(i, width, depth) \ + hevcdsp->put_unweighted_pred_chroma[i] = FUNC(put_unweighted_pred_ ## width, depth); \ + hevcdsp->put_unweighted_pred_avg_chroma[i] = FUNC(put_unweighted_pred_avg_ ## width, depth); \ + hevcdsp->weighted_pred_chroma[i] = FUNC(put_weighted_pred_ ## width, depth); \ + hevcdsp->weighted_pred_avg_chroma[i] = FUNC(put_weighted_pred_avg_ ## width, depth); \ + #define HEVC_DSP(depth) \ hevcdsp->put_pcm = FUNC(put_pcm, depth); \ - hevcdsp->transquant_bypass[0] = FUNC(transquant_bypass4x4, depth); \ - hevcdsp->transquant_bypass[1] = FUNC(transquant_bypass8x8, depth); \ - hevcdsp->transquant_bypass[2] = FUNC(transquant_bypass16x16, depth); \ - hevcdsp->transquant_bypass[3] = FUNC(transquant_bypass32x32, depth); \ - hevcdsp->transform_skip = FUNC(transform_skip, depth); \ - hevcdsp->transform_4x4_luma_add = FUNC(transform_4x4_luma_add, depth); \ - hevcdsp->transform_add[0] = FUNC(transform_4x4_add, depth); \ - hevcdsp->transform_add[1] = FUNC(transform_8x8_add, depth); \ - hevcdsp->transform_add[2] = FUNC(transform_16x16_add, depth); \ - hevcdsp->transform_add[3] = FUNC(transform_32x32_add, depth); \ + hevcdsp->add_residual[0] = FUNC(add_residual4x4, depth); \ + hevcdsp->add_residual[1] = FUNC(add_residual8x8, depth); \ + hevcdsp->add_residual[2] = FUNC(add_residual16x16, depth); \ + hevcdsp->add_residual[3] = FUNC(add_residual32x32, depth); \ + hevcdsp->dequant = FUNC(dequant, depth); \ + hevcdsp->transform_4x4_luma = FUNC(transform_4x4_luma, depth); \ + hevcdsp->idct[0] = FUNC(idct_4x4, depth); \ + hevcdsp->idct[1] = FUNC(idct_8x8, depth); \ + hevcdsp->idct[2] = FUNC(idct_16x16, depth); \ + hevcdsp->idct[3] = FUNC(idct_32x32, depth); \ \ + hevcdsp->idct_dc[0] = FUNC(idct_4x4_dc, depth); \ + hevcdsp->idct_dc[1] = FUNC(idct_8x8_dc, depth); \ + hevcdsp->idct_dc[2] = FUNC(idct_16x16_dc, depth); \ + hevcdsp->idct_dc[3] = FUNC(idct_32x32_dc, depth); \ hevcdsp->sao_band_filter[0] = FUNC(sao_band_filter_0, depth); \ hevcdsp->sao_band_filter[1] = FUNC(sao_band_filter_1, depth); \ hevcdsp->sao_band_filter[2] = FUNC(sao_band_filter_2, depth); \ @@ -139,33 +189,40 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) hevcdsp->sao_edge_filter[2] = FUNC(sao_edge_filter_2, depth); \ hevcdsp->sao_edge_filter[3] = FUNC(sao_edge_filter_3, depth); \ \ - hevcdsp->put_hevc_qpel[0][0] = FUNC(put_hevc_qpel_pixels, depth); \ - hevcdsp->put_hevc_qpel[0][1] = FUNC(put_hevc_qpel_h1, depth); \ - hevcdsp->put_hevc_qpel[0][2] = FUNC(put_hevc_qpel_h2, depth); \ - hevcdsp->put_hevc_qpel[0][3] = FUNC(put_hevc_qpel_h3, depth); \ - hevcdsp->put_hevc_qpel[1][0] = FUNC(put_hevc_qpel_v1, depth); \ - hevcdsp->put_hevc_qpel[1][1] = FUNC(put_hevc_qpel_h1v1, depth); \ - hevcdsp->put_hevc_qpel[1][2] = FUNC(put_hevc_qpel_h2v1, depth); \ - hevcdsp->put_hevc_qpel[1][3] = FUNC(put_hevc_qpel_h3v1, depth); \ - hevcdsp->put_hevc_qpel[2][0] = FUNC(put_hevc_qpel_v2, depth); \ - hevcdsp->put_hevc_qpel[2][1] = FUNC(put_hevc_qpel_h1v2, depth); \ - hevcdsp->put_hevc_qpel[2][2] = FUNC(put_hevc_qpel_h2v2, depth); \ - hevcdsp->put_hevc_qpel[2][3] = FUNC(put_hevc_qpel_h3v2, depth); \ - hevcdsp->put_hevc_qpel[3][0] = FUNC(put_hevc_qpel_v3, depth); \ - hevcdsp->put_hevc_qpel[3][1] = FUNC(put_hevc_qpel_h1v3, depth); \ - hevcdsp->put_hevc_qpel[3][2] = FUNC(put_hevc_qpel_h2v3, depth); \ - hevcdsp->put_hevc_qpel[3][3] = FUNC(put_hevc_qpel_h3v3, depth); \ - \ - hevcdsp->put_hevc_epel[0][0] = FUNC(put_hevc_epel_pixels, depth); \ - hevcdsp->put_hevc_epel[0][1] = FUNC(put_hevc_epel_h, depth); \ - hevcdsp->put_hevc_epel[1][0] = FUNC(put_hevc_epel_v, depth); \ - hevcdsp->put_hevc_epel[1][1] = FUNC(put_hevc_epel_hv, depth); \ + QPEL_FUNC(0, 4, depth); \ + QPEL_FUNC(1, 8, depth); \ + QPEL_FUNC(2, 12, depth); \ + QPEL_FUNC(3, 16, depth); \ + QPEL_FUNC(4, 24, depth); \ + QPEL_FUNC(5, 32, depth); \ + QPEL_FUNC(6, 48, depth); \ + QPEL_FUNC(7, 64, depth); \ \ - hevcdsp->put_unweighted_pred = FUNC(put_unweighted_pred, depth); \ - hevcdsp->put_weighted_pred_avg = FUNC(put_weighted_pred_avg, depth); \ + EPEL_FUNC(0, 2, depth); \ + EPEL_FUNC(1, 4, depth); \ + EPEL_FUNC(2, 6, depth); \ + EPEL_FUNC(3, 8, depth); \ + EPEL_FUNC(4, 12, depth); \ + EPEL_FUNC(5, 16, depth); \ + EPEL_FUNC(6, 24, depth); \ + EPEL_FUNC(7, 32, depth); \ \ - hevcdsp->weighted_pred = FUNC(weighted_pred, depth); \ - hevcdsp->weighted_pred_avg = FUNC(weighted_pred_avg, depth); \ + PRED_FUNC(0, 4, depth); \ + PRED_FUNC(1, 8, depth); \ + PRED_FUNC(2, 12, depth); \ + PRED_FUNC(3, 16, depth); \ + PRED_FUNC(4, 24, depth); \ + PRED_FUNC(5, 32, depth); \ + PRED_FUNC(6, 48, depth); \ + PRED_FUNC(7, 64, depth); \ + PRED_FUNC_CHROMA(0, 2, depth); \ + PRED_FUNC_CHROMA(1, 4, depth); \ + PRED_FUNC_CHROMA(2, 6, depth); \ + PRED_FUNC_CHROMA(3, 8, depth); \ + PRED_FUNC_CHROMA(4, 12, depth); \ + PRED_FUNC_CHROMA(5, 16, depth); \ + PRED_FUNC_CHROMA(6, 24, depth); \ + PRED_FUNC_CHROMA(7, 32, depth); \ \ hevcdsp->hevc_h_loop_filter_luma = FUNC(hevc_h_loop_filter_luma, depth); \ hevcdsp->hevc_v_loop_filter_luma = FUNC(hevc_v_loop_filter_luma, depth); \ diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h index aad96db..199e5a9 100644 --- a/libavcodec/hevcdsp.h +++ b/libavcodec/hevcdsp.h @@ -42,13 +42,12 @@ typedef struct HEVCDSPContext { void (*put_pcm)(uint8_t *dst, ptrdiff_t stride, int size, GetBitContext *gb, int pcm_bit_depth); - void (*transquant_bypass[4])(uint8_t *dst, int16_t *coeffs, - ptrdiff_t stride); + void (*add_residual[4])(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride); - void (*transform_skip)(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride); - void (*transform_4x4_luma_add)(uint8_t *dst, int16_t *coeffs, - ptrdiff_t stride); - void (*transform_add[4])(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride); + void (*dequant)(int16_t *coeffs); + void (*transform_4x4_luma)(int16_t *coeffs); + void (*idct[4])(int16_t *coeffs, int col_limit); + void (*idct_dc[4])(int16_t *coeffs); void (*sao_band_filter[4])(uint8_t *dst, uint8_t *src, ptrdiff_t stride, struct SAOParams *sao, int *borders, @@ -58,25 +57,37 @@ typedef struct HEVCDSPContext { int height, int c_idx, uint8_t vert_edge, uint8_t horiz_edge, uint8_t diag_edge); - void (*put_hevc_qpel[4][4])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, - ptrdiff_t srcstride, int width, int height, - int16_t *mcbuffer); - void (*put_hevc_epel[2][2])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, - ptrdiff_t srcstride, int width, int height, - int mx, int my, int16_t *mcbuffer); - - void (*put_unweighted_pred)(uint8_t *dst, ptrdiff_t dststride, int16_t *src, - ptrdiff_t srcstride, int width, int height); - void (*put_weighted_pred_avg)(uint8_t *dst, ptrdiff_t dststride, - int16_t *src1, int16_t *src2, - ptrdiff_t srcstride, int width, int height); - void (*weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, - uint8_t *dst, ptrdiff_t dststride, int16_t *src, - ptrdiff_t srcstride, int width, int height); - void (*weighted_pred_avg)(uint8_t denom, int16_t wl0Flag, int16_t wl1Flag, - int16_t ol0Flag, int16_t ol1Flag, uint8_t *dst, - ptrdiff_t dststride, int16_t *src1, int16_t *src2, - ptrdiff_t srcstride, int width, int height); + void (*put_hevc_qpel[2][2][8])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, + int mx, int my, int16_t *mcbuffer); + void (*put_hevc_epel[2][2][8])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, + int mx, int my, int16_t *mcbuffer); + + void (*put_unweighted_pred[8])(uint8_t *dst, ptrdiff_t dststride, int16_t *src, + ptrdiff_t srcstride, int height); + void (*put_unweighted_pred_chroma[8])(uint8_t *dst, ptrdiff_t dststride, int16_t *src, + ptrdiff_t srcstride, int height); + void (*put_unweighted_pred_avg[8])(uint8_t *dst, ptrdiff_t dststride, + int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, int height); + void (*put_unweighted_pred_avg_chroma[8])(uint8_t *dst, ptrdiff_t dststride, + int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, int height); + void (*weighted_pred[8])(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, + uint8_t *dst, ptrdiff_t dststride, int16_t *src, + ptrdiff_t srcstride, int height); + void (*weighted_pred_chroma[8])(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, + uint8_t *dst, ptrdiff_t dststride, int16_t *src, + ptrdiff_t srcstride, int height); + void (*weighted_pred_avg[8])(uint8_t denom, int16_t wl0Flag, int16_t wl1Flag, + int16_t ol0Flag, int16_t ol1Flag, uint8_t *dst, + ptrdiff_t dststride, int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, int height); + void (*weighted_pred_avg_chroma[8])(uint8_t denom, int16_t wl0Flag, int16_t wl1Flag, + int16_t ol0Flag, int16_t ol1Flag, uint8_t *dst, + ptrdiff_t dststride, int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, int height); void (*hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride, int beta, int *tc, @@ -106,6 +117,9 @@ void ff_hevc_dsp_init(HEVCDSPContext *hpc, int bit_depth); void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth); -extern const int8_t ff_hevc_epel_filters[7][16]; +extern const int16_t ff_hevc_epel_coeffs[7][16]; +extern const int8_t ff_hevc_epel_coeffs8[7][16]; +extern const int16_t ff_hevc_qpel_coeffs[3][8]; +extern const int8_t ff_hevc_qpel_coeffs8[3][16]; #endif /* AVCODEC_HEVCDSP_H */ diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 8dcc83d..076b251 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -40,78 +40,49 @@ static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size, } } -static void FUNC(transquant_bypass4x4)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static av_always_inline void FUNC(add_residual)(uint8_t *_dst, int16_t *res, + ptrdiff_t stride, int size) { int x, y; pixel *dst = (pixel *)_dst; stride /= sizeof(pixel); - for (y = 0; y < 4; y++) { - for (x = 0; x < 4; x++) { - dst[x] = av_clip_pixel(dst[x] + *coeffs); - coeffs++; + for (y = 0; y < size; y++) { + for (x = 0; x < size; x++) { + dst[x] = av_clip_pixel(dst[x] + *res); + res++; } dst += stride; } } -static void FUNC(transquant_bypass8x8)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static void FUNC(add_residual4x4)(uint8_t *_dst, int16_t *res, + ptrdiff_t stride) { - int x, y; - pixel *dst = (pixel *)_dst; - - stride /= sizeof(pixel); - - for (y = 0; y < 8; y++) { - for (x = 0; x < 8; x++) { - dst[x] = av_clip_pixel(dst[x] + *coeffs); - coeffs++; - } - dst += stride; - } + FUNC(add_residual)(_dst, res, stride, 4); } -static void FUNC(transquant_bypass16x16)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static void FUNC(add_residual8x8)(uint8_t *_dst, int16_t *res, + ptrdiff_t stride) { - int x, y; - pixel *dst = (pixel *)_dst; - - stride /= sizeof(pixel); - - for (y = 0; y < 16; y++) { - for (x = 0; x < 16; x++) { - dst[x] = av_clip_pixel(dst[x] + *coeffs); - coeffs++; - } - dst += stride; - } + FUNC(add_residual)(_dst, res, stride, 8); } -static void FUNC(transquant_bypass32x32)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static void FUNC(add_residual16x16)(uint8_t *_dst, int16_t *res, + ptrdiff_t stride) { - int x, y; - pixel *dst = (pixel *)_dst; - - stride /= sizeof(pixel); + FUNC(add_residual)(_dst, res, stride, 16); +} - for (y = 0; y < 32; y++) { - for (x = 0; x < 32; x++) { - dst[x] = av_clip_pixel(dst[x] + *coeffs); - coeffs++; - } - dst += stride; - } +static void FUNC(add_residual32x32)(uint8_t *_dst, int16_t *res, + ptrdiff_t stride) +{ + FUNC(add_residual)(_dst, res, stride, 32); } -static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static void FUNC(dequant)(int16_t *coeffs) { - pixel *dst = (pixel *)_dst; int shift = 13 - BIT_DEPTH; #if BIT_DEPTH <= 13 int offset = 1 << (shift - 1); @@ -120,19 +91,14 @@ static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs, #endif int x, y; - stride /= sizeof(pixel); - for (y = 0; y < 4 * 4; y += 4) { for (x = 0; x < 4; x++) - dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift)); - dst += stride; + coeffs[y + x] = (coeffs[y + x] + offset) >> shift; } } #define SET(dst, x) (dst) = (x) #define SCALE(dst, x) (dst) = av_clip_int16(((x) + add) >> shift) -#define ADD_AND_SCALE(dst, x) \ - (dst) = av_clip_pixel((dst) + av_clip_int16(((x) + add) >> shift)) #define TR_4x4_LUMA(dst, src, step, assign) \ do { \ @@ -149,17 +115,13 @@ static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs, assign(dst[3 * step], 55 * c0 + 29 * c2 - c3); \ } while (0) -static void FUNC(transform_4x4_luma_add)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) +static void FUNC(transform_4x4_luma)(int16_t *coeffs) { int i; - pixel *dst = (pixel *)_dst; int shift = 7; int add = 1 << (shift - 1); int16_t *src = coeffs; - stride /= sizeof(pixel); - for (i = 0; i < 4; i++) { TR_4x4_LUMA(src, src, 4, SCALE); src++; @@ -168,15 +130,14 @@ static void FUNC(transform_4x4_luma_add)(uint8_t *_dst, int16_t *coeffs, shift = 20 - BIT_DEPTH; add = 1 << (shift - 1); for (i = 0; i < 4; i++) { - TR_4x4_LUMA(dst, coeffs, 1, ADD_AND_SCALE); + TR_4x4_LUMA(coeffs, coeffs, 1, SCALE); coeffs += 4; - dst += stride; } } #undef TR_4x4_LUMA -#define TR_4(dst, src, dstep, sstep, assign) \ +#define TR_4(dst, src, dstep, sstep, assign, end) \ do { \ const int e0 = transform[8 * 0][0] * src[0 * sstep] + \ transform[8 * 2][0] * src[2 * sstep]; \ @@ -193,40 +154,15 @@ static void FUNC(transform_4x4_luma_add)(uint8_t *_dst, int16_t *coeffs, assign(dst[3 * dstep], e0 - o0); \ } while (0) -static void FUNC(transform_4x4_add)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) -{ - int i; - pixel *dst = (pixel *)_dst; - int shift = 7; - int add = 1 << (shift - 1); - int16_t *src = coeffs; - - stride /= sizeof(pixel); - - for (i = 0; i < 4; i++) { - TR_4(src, src, 4, 4, SCALE); - src++; - } - - shift = 20 - BIT_DEPTH; - add = 1 << (shift - 1); - for (i = 0; i < 4; i++) { - TR_4(dst, coeffs, 1, 1, ADD_AND_SCALE); - coeffs += 4; - dst += stride; - } -} - -#define TR_8(dst, src, dstep, sstep, assign) \ +#define TR_8(dst, src, dstep, sstep, assign, end) \ do { \ int i, j; \ int e_8[4]; \ int o_8[4] = { 0 }; \ for (i = 0; i < 4; i++) \ - for (j = 1; j < 8; j += 2) \ + for (j = 1; j < end; j += 2) \ o_8[i] += transform[4 * j][i] * src[j * sstep]; \ - TR_4(e_8, src, 1, 2 * sstep, SET); \ + TR_4(e_8, src, 1, 2 * sstep, SET, 4); \ \ for (i = 0; i < 4; i++) { \ assign(dst[i * dstep], e_8[i] + o_8[i]); \ @@ -234,15 +170,15 @@ static void FUNC(transform_4x4_add)(uint8_t *_dst, int16_t *coeffs, } \ } while (0) -#define TR_16(dst, src, dstep, sstep, assign) \ +#define TR_16(dst, src, dstep, sstep, assign, end) \ do { \ int i, j; \ int e_16[8]; \ int o_16[8] = { 0 }; \ for (i = 0; i < 8; i++) \ - for (j = 1; j < 16; j += 2) \ + for (j = 1; j < end; j += 2) \ o_16[i] += transform[2 * j][i] * src[j * sstep]; \ - TR_8(e_16, src, 1, 2 * sstep, SET); \ + TR_8(e_16, src, 1, 2 * sstep, SET, 8); \ \ for (i = 0; i < 8; i++) { \ assign(dst[i * dstep], e_16[i] + o_16[i]); \ @@ -250,15 +186,15 @@ static void FUNC(transform_4x4_add)(uint8_t *_dst, int16_t *coeffs, } \ } while (0) -#define TR_32(dst, src, dstep, sstep, assign) \ +#define TR_32(dst, src, dstep, sstep, assign, end) \ do { \ int i, j; \ int e_32[16]; \ int o_32[16] = { 0 }; \ for (i = 0; i < 16; i++) \ - for (j = 1; j < 32; j += 2) \ + for (j = 1; j < end; j += 2) \ o_32[i] += transform[j][i] * src[j * sstep]; \ - TR_16(e_32, src, 1, 2 * sstep, SET); \ + TR_16(e_32, src, 1, 2 * sstep, SET, end / 2); \ \ for (i = 0; i < 16; i++) { \ assign(dst[i * dstep], e_32[i] + o_32[i]); \ @@ -266,82 +202,70 @@ static void FUNC(transform_4x4_add)(uint8_t *_dst, int16_t *coeffs, } \ } while (0) - - -static void FUNC(transform_8x8_add)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) -{ - int i; - pixel *dst = (pixel *)_dst; - int shift = 7; - int add = 1 << (shift - 1); - int16_t *src = coeffs; - - stride /= sizeof(pixel); - - for (i = 0; i < 8; i++) { - TR_8(src, src, 8, 8, SCALE); - src++; - } - - shift = 20 - BIT_DEPTH; - add = 1 << (shift - 1); - for (i = 0; i < 8; i++) { - TR_8(dst, coeffs, 1, 1, ADD_AND_SCALE); - coeffs += 8; - dst += stride; - } +#define IDCT_VAR4(H) \ + int limit2 = FFMIN(col_limit + 4, H) +#define IDCT_VAR8(H) \ + int limit = FFMIN(col_limit, H); \ + int limit2 = FFMIN(col_limit + 4, H) +#define IDCT_VAR16(H) IDCT_VAR8(H) +#define IDCT_VAR32(H) IDCT_VAR8(H) + +#define IDCT(H) \ +static void FUNC(idct_ ## H ## x ## H )(int16_t *coeffs, \ + int col_limit) \ +{ \ + int i; \ + int shift = 7; \ + int add = 1 << (shift - 1); \ + int16_t *src = coeffs; \ + IDCT_VAR ## H(H); \ + \ + for (i = 0; i < H; i++) { \ + TR_ ## H(src, src, H, H, SCALE, limit2); \ + if (limit2 < H && i%4 == 0 && !!i) \ + limit2 -= 4; \ + src++; \ + } \ + \ + shift = 20 - BIT_DEPTH; \ + add = 1 << (shift - 1); \ + for (i = 0; i < H; i++) { \ + TR_ ## H(coeffs, coeffs, 1, 1, SCALE, limit); \ + coeffs += H; \ + } \ } -static void FUNC(transform_16x16_add)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) -{ - int i; - pixel *dst = (pixel *)_dst; - int shift = 7; - int add = 1 << (shift - 1); - int16_t *src = coeffs; - - stride /= sizeof(pixel); - - for (i = 0; i < 16; i++) { - TR_16(src, src, 16, 16, SCALE); - src++; - } - - shift = 20 - BIT_DEPTH; - add = 1 << (shift - 1); - for (i = 0; i < 16; i++) { - TR_16(dst, coeffs, 1, 1, ADD_AND_SCALE); - coeffs += 16; - dst += stride; - } +#define IDCT_DC(H) \ +static void FUNC(idct_ ## H ## x ## H ## _dc)(int16_t *coeffs) \ +{ \ + int i, j; \ + int shift = 14 - BIT_DEPTH; \ + int add = 1 << (shift - 1); \ + int coeff = (((coeffs[0] + 1) >> 1) + add) >> shift; \ + \ + for (j = 0; j < H; j++) { \ + for (i = 0; i < H; i++) { \ + coeffs[i + j * H] = coeff; \ + } \ + } \ } -static void FUNC(transform_32x32_add)(uint8_t *_dst, int16_t *coeffs, - ptrdiff_t stride) -{ - int i; - pixel *dst = (pixel *)_dst; - int shift = 7; - int add = 1 << (shift - 1); - int16_t *src = coeffs; - - stride /= sizeof(pixel); +IDCT( 4) +IDCT( 8) +IDCT(16) +IDCT(32) +IDCT_DC( 4) +IDCT_DC( 8) +IDCT_DC(16) +IDCT_DC(32) +#undef TR_4 +#undef TR_8 +#undef TR_16 +#undef TR_32 - for (i = 0; i < 32; i++) { - TR_32(src, src, 32, 32, SCALE); - src++; - } - src = coeffs; - shift = 20 - BIT_DEPTH; - add = 1 << (shift - 1); - for (i = 0; i < 32; i++) { - TR_32(dst, coeffs, 1, 1, ADD_AND_SCALE); - coeffs += 32; - dst += stride; - } -} +#undef SET +#undef SCALE +#undef ADD_AND_SCALE static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride, SAOParams *sao, @@ -796,20 +720,22 @@ static void FUNC(sao_edge_filter_3)(uint8_t *_dst, uint8_t *_src, #undef SET #undef SCALE -#undef ADD_AND_SCALE #undef TR_4 #undef TR_8 #undef TR_16 #undef TR_32 -static void FUNC(put_hevc_qpel_pixels)(int16_t *dst, ptrdiff_t dststride, - uint8_t *_src, ptrdiff_t _srcstride, - int width, int height, int16_t* mcbuffer) +static av_always_inline void +FUNC(put_hevc_qpel_pixels)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int width, int height, int mx, int my, + int16_t* mcbuffer) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); + dststride /= sizeof(*dst); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = src[x] << (14 - BIT_DEPTH); @@ -857,6 +783,7 @@ static void FUNC(put_hevc_qpel_h ## H)(int16_t *dst, ptrdiff_t dststride, \ pixel *src = (pixel*)_src; \ ptrdiff_t srcstride = _srcstride / sizeof(pixel); \ \ + dststride /= sizeof(*dst); \ for (y = 0; y < height; y++) { \ for (x = 0; x < width; x++) \ dst[x] = QPEL_FILTER_ ## H(src, 1) >> (BIT_DEPTH - 8); \ @@ -875,6 +802,7 @@ static void FUNC(put_hevc_qpel_v ## V)(int16_t *dst, ptrdiff_t dststride, \ pixel *src = (pixel*)_src; \ ptrdiff_t srcstride = _srcstride / sizeof(pixel); \ \ + dststride /= sizeof(*dst); \ for (y = 0; y < height; y++) { \ for (x = 0; x < width; x++) \ dst[x] = QPEL_FILTER_ ## V(src, srcstride) >> (BIT_DEPTH - 8); \ @@ -898,6 +826,7 @@ static void FUNC(put_hevc_qpel_h ## H ## v ## V)(int16_t *dst, \ int16_t tmp_array[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]; \ int16_t *tmp = tmp_array; \ \ + dststride /= sizeof(*dst); \ src -= ff_hevc_qpel_extra_before[V] * srcstride; \ \ for (y = 0; y < height + ff_hevc_qpel_extra[V]; y++) { \ @@ -933,15 +862,90 @@ PUT_HEVC_QPEL_HV(3, 1) PUT_HEVC_QPEL_HV(3, 2) PUT_HEVC_QPEL_HV(3, 3) -static void FUNC(put_hevc_epel_pixels)(int16_t *dst, ptrdiff_t dststride, - uint8_t *_src, ptrdiff_t _srcstride, - int width, int height, int mx, int my, - int16_t* mcbuffer) +#define QPEL(W) \ +static void FUNC(put_hevc_qpel_pixels_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + FUNC(put_hevc_qpel_pixels)(dst, dststride, src, srcstride, W, height, \ + mx, my, mcbuffer); \ +} \ + \ +static void FUNC(put_hevc_qpel_h_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + if (mx == 1) \ + FUNC(put_hevc_qpel_h1)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else if (mx == 2) \ + FUNC(put_hevc_qpel_h2)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else \ + FUNC(put_hevc_qpel_h3)(dst, dststride, src, srcstride, W, height, mcbuffer); \ +} \ + \ +static void FUNC(put_hevc_qpel_v_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + if (my == 1) \ + FUNC(put_hevc_qpel_v1)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else if (my == 2) \ + FUNC(put_hevc_qpel_v2)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else \ + FUNC(put_hevc_qpel_v3)(dst, dststride, src, srcstride, W, height, mcbuffer); \ +} \ + \ +static void FUNC(put_hevc_qpel_hv_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + if (my == 1) { \ + if (mx == 1) \ + FUNC(put_hevc_qpel_h1v1)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else if (mx == 2) \ + FUNC(put_hevc_qpel_h2v1)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else \ + FUNC(put_hevc_qpel_h3v1)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + } else if (my == 2) { \ + if (mx == 1) \ + FUNC(put_hevc_qpel_h1v2)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else if (mx == 2) \ + FUNC(put_hevc_qpel_h2v2)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else \ + FUNC(put_hevc_qpel_h3v2)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + } else { \ + if (mx == 1) \ + FUNC(put_hevc_qpel_h1v3)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else if (mx == 2) \ + FUNC(put_hevc_qpel_h2v3)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + else \ + FUNC(put_hevc_qpel_h3v3)(dst, dststride, src, srcstride, W, height, mcbuffer); \ + } \ +} + +QPEL(64) +QPEL(48) +QPEL(32) +QPEL(24) +QPEL(16) +QPEL(12) +QPEL(8) +QPEL(4) + +static inline void FUNC(put_hevc_epel_pixels)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int width, int height, int mx, int my, + int16_t* mcbuffer) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); + dststride /= sizeof(*dst); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = src[x] << (14 - BIT_DEPTH); @@ -956,19 +960,20 @@ static void FUNC(put_hevc_epel_pixels)(int16_t *dst, ptrdiff_t dststride, filter_2 * src[x + stride] + \ filter_3 * src[x + 2 * stride]) -static void FUNC(put_hevc_epel_h)(int16_t *dst, ptrdiff_t dststride, - uint8_t *_src, ptrdiff_t _srcstride, - int width, int height, int mx, int my, - int16_t* mcbuffer) +static inline void FUNC(put_hevc_epel_h)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int width, int height, int mx, int my, + int16_t* mcbuffer) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); - const int8_t *filter = ff_hevc_epel_filters[mx - 1]; + const int16_t *filter = ff_hevc_epel_coeffs[mx - 1]; int8_t filter_0 = filter[0]; int8_t filter_1 = filter[1]; int8_t filter_2 = filter[2]; int8_t filter_3 = filter[3]; + dststride /= sizeof(*dst); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); @@ -977,20 +982,21 @@ static void FUNC(put_hevc_epel_h)(int16_t *dst, ptrdiff_t dststride, } } -static void FUNC(put_hevc_epel_v)(int16_t *dst, ptrdiff_t dststride, - uint8_t *_src, ptrdiff_t _srcstride, - int width, int height, int mx, int my, - int16_t* mcbuffer) +static inline void FUNC(put_hevc_epel_v)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int width, int height, int mx, int my, + int16_t* mcbuffer) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); - const int8_t *filter = ff_hevc_epel_filters[my - 1]; + const int16_t *filter = ff_hevc_epel_coeffs[my - 1]; int8_t filter_0 = filter[0]; int8_t filter_1 = filter[1]; int8_t filter_2 = filter[2]; int8_t filter_3 = filter[3]; + dststride /= sizeof(*dst); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8); @@ -999,16 +1005,16 @@ static void FUNC(put_hevc_epel_v)(int16_t *dst, ptrdiff_t dststride, } } -static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride, - uint8_t *_src, ptrdiff_t _srcstride, - int width, int height, int mx, int my, - int16_t* mcbuffer) +static inline void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride, + uint8_t *_src, ptrdiff_t _srcstride, + int width, int height, int mx, int my, + int16_t* mcbuffer) { int x, y; pixel *src = (pixel *)_src; ptrdiff_t srcstride = _srcstride / sizeof(pixel); - const int8_t *filter_h = ff_hevc_epel_filters[mx - 1]; - const int8_t *filter_v = ff_hevc_epel_filters[my - 1]; + const int16_t *filter_h = ff_hevc_epel_coeffs[mx - 1]; + const int16_t *filter_v = ff_hevc_epel_coeffs[my - 1]; int8_t filter_0 = filter_h[0]; int8_t filter_1 = filter_h[1]; int8_t filter_2 = filter_h[2]; @@ -1016,6 +1022,7 @@ static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride, int16_t tmp_array[(MAX_PB_SIZE + 3) * MAX_PB_SIZE]; int16_t *tmp = tmp_array; + dststride /= sizeof(*dst); src -= EPEL_EXTRA_BEFORE * srcstride; for (y = 0; y < height + EPEL_EXTRA; y++) { @@ -1038,9 +1045,53 @@ static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride, } } -static void FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride, - int16_t *src, ptrdiff_t srcstride, - int width, int height) +#define EPEL(W) \ +static void FUNC(put_hevc_epel_pixels_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + FUNC(put_hevc_epel_pixels)(dst, dststride, src, srcstride, \ + W, height, mx, my, mcbuffer); \ +} \ +static void FUNC(put_hevc_epel_h_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + FUNC(put_hevc_epel_h)(dst, dststride, src, srcstride, \ + W, height, mx, my, mcbuffer); \ +} \ +static void FUNC(put_hevc_epel_v_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + FUNC(put_hevc_epel_v)(dst, dststride, src, srcstride, \ + W, height, mx, my, mcbuffer); \ +} \ +static void FUNC(put_hevc_epel_hv_ ## W)(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, \ + int16_t *mcbuffer) \ +{ \ + FUNC(put_hevc_epel_hv)(dst, dststride, src, srcstride, \ + W, height, mx, my, mcbuffer); \ +} + +EPEL(32) +EPEL(24) +EPEL(16) +EPEL(12) +EPEL(8) +EPEL(6) +EPEL(4) +EPEL(2) + +static av_always_inline void +FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride, + int16_t *src, ptrdiff_t srcstride, + int width, int height) { int x, y; pixel *dst = (pixel *)_dst; @@ -1052,6 +1103,7 @@ static void FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride, #else int offset = 0; #endif + srcstride /= sizeof(*src); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel((src[x] + offset) >> shift); @@ -1060,10 +1112,11 @@ static void FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride, } } -static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride, - int16_t *src1, int16_t *src2, - ptrdiff_t srcstride, - int width, int height) +static av_always_inline void +FUNC(put_unweighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride, + int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, + int width, int height) { int x, y; pixel *dst = (pixel *)_dst; @@ -1076,6 +1129,7 @@ static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride, int offset = 0; #endif + srcstride /= sizeof(*src1); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel((src1[x] + src2[x] + offset) >> shift); @@ -1085,10 +1139,11 @@ static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride, } } -static void FUNC(weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, - uint8_t *_dst, ptrdiff_t _dststride, - int16_t *src, ptrdiff_t srcstride, - int width, int height) +static av_always_inline void +FUNC(weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, + uint8_t *_dst, ptrdiff_t _dststride, + int16_t *src, ptrdiff_t srcstride, + int width, int height) { int shift, log2Wd, wx, ox, x, y, offset; pixel *dst = (pixel *)_dst; @@ -1100,6 +1155,7 @@ static void FUNC(weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, wx = wlxFlag; ox = olxFlag * (1 << (BIT_DEPTH - 8)); + srcstride /= sizeof(*src); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { if (log2Wd >= 1) { @@ -1113,13 +1169,14 @@ static void FUNC(weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag, } } -static void FUNC(weighted_pred_avg)(uint8_t denom, - int16_t wl0Flag, int16_t wl1Flag, - int16_t ol0Flag, int16_t ol1Flag, - uint8_t *_dst, ptrdiff_t _dststride, - int16_t *src1, int16_t *src2, - ptrdiff_t srcstride, - int width, int height) +static av_always_inline void +FUNC(weighted_pred_avg)(uint8_t denom, + int16_t wl0Flag, int16_t wl1Flag, + int16_t ol0Flag, int16_t ol1Flag, + uint8_t *_dst, ptrdiff_t _dststride, + int16_t *src1, int16_t *src2, + ptrdiff_t srcstride, + int width, int height) { int shift, log2Wd, w0, w1, o0, o1, x, y; pixel *dst = (pixel *)_dst; @@ -1132,6 +1189,7 @@ static void FUNC(weighted_pred_avg)(uint8_t denom, o0 = ol0Flag * (1 << (BIT_DEPTH - 8)); o1 = ol1Flag * (1 << (BIT_DEPTH - 8)); + srcstride /= sizeof(*src1); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel((src1[x] * w0 + src2[x] * w1 + @@ -1142,6 +1200,47 @@ static void FUNC(weighted_pred_avg)(uint8_t denom, } } +#define PUT_PRED(w) \ +static void FUNC(put_unweighted_pred_ ## w)(uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, \ + int height) \ +{ \ + FUNC(put_unweighted_pred)(dst, dststride, src, srcstride, w, height); \ +} \ +static void FUNC(put_unweighted_pred_avg_ ## w)(uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src1, int16_t *src2, \ + ptrdiff_t srcstride, int height) \ +{ \ + FUNC(put_unweighted_pred_avg)(dst, dststride, src1, src2, srcstride, w, height); \ +} \ +static void FUNC(put_weighted_pred_ ## w)(uint8_t denom, int16_t weight, int16_t offset, \ + uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, int height) \ +{ \ + FUNC(weighted_pred)(denom, weight, offset, \ + dst, dststride, src, srcstride, w, height); \ +} \ +static void FUNC(put_weighted_pred_avg_ ## w)(uint8_t denom, int16_t weight0, int16_t weight1, \ + int16_t offset0, int16_t offset1, \ + uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src1, int16_t *src2, \ + ptrdiff_t srcstride, int height) \ +{ \ + FUNC(weighted_pred_avg)(denom, weight0, weight1, offset0, offset1, \ + dst, dststride, src1, src2, srcstride, w, height); \ +} + +PUT_PRED(64) +PUT_PRED(48) +PUT_PRED(32) +PUT_PRED(24) +PUT_PRED(16) +PUT_PRED(12) +PUT_PRED(8) +PUT_PRED(6) +PUT_PRED(4) +PUT_PRED(2) + // line zero #define P3 pix[-4 * xstride] #define P2 pix[-3 * xstride] diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c index 53b9c59..039882b 100644 --- a/libavcodec/hevcpred_template.c +++ b/libavcodec/hevcpred_template.c @@ -32,7 +32,7 @@ static av_always_inline void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int c_idx) { #define PU(x) \ - ((x) >> s->sps->log2_min_pu_size) + ((x) >> s->ps.sps->log2_min_pu_size) #define MVF(x, y) \ (s->ref->tab_mvf[(x) + (y) * min_pu_width]) #define MVF_PU(x, y) \ @@ -40,7 +40,7 @@ static av_always_inline void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, #define IS_INTRA(x, y) \ MVF_PU(x, y).is_intra #define MIN_TB_ADDR_ZS(x, y) \ - s->pps->min_tb_addr_zs[(y) * s->sps->min_tb_width + (x)] + s->ps.pps->min_tb_addr_zs[(y) * s->ps.sps->min_tb_width + (x)] #define EXTEND(ptr, val, len) \ do { \ @@ -70,21 +70,21 @@ do { \ ptr[i] = ptr[i - 1] HEVCLocalContext *lc = &s->HEVClc; int i; - int hshift = s->sps->hshift[c_idx]; - int vshift = s->sps->vshift[c_idx]; + int hshift = s->ps.sps->hshift[c_idx]; + int vshift = s->ps.sps->vshift[c_idx]; int size = (1 << log2_size); int size_in_luma = size << hshift; - int size_in_tbs = size_in_luma >> s->sps->log2_min_tb_size; + int size_in_tbs = size_in_luma >> s->ps.sps->log2_min_tb_size; int x = x0 >> hshift; int y = y0 >> vshift; - int x_tb = x0 >> s->sps->log2_min_tb_size; - int y_tb = y0 >> s->sps->log2_min_tb_size; + int x_tb = x0 >> s->ps.sps->log2_min_tb_size; + int y_tb = y0 >> s->ps.sps->log2_min_tb_size; int cur_tb_addr = MIN_TB_ADDR_ZS(x_tb, y_tb); ptrdiff_t stride = s->frame->linesize[c_idx] / sizeof(pixel); pixel *src = (pixel*)s->frame->data[c_idx] + x + y * stride; - int min_pu_width = s->sps->min_pu_width; + int min_pu_width = s->ps.sps->min_pu_width; enum IntraPredMode mode = c_idx ? lc->pu.intra_pred_mode_c : lc->tu.cur_intra_pred_mode; @@ -105,21 +105,21 @@ do { \ int cand_up = lc->na.cand_up; int cand_up_right = lc->na.cand_up_right && cur_tb_addr > MIN_TB_ADDR_ZS(x_tb + size_in_tbs, y_tb - 1); - int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma, s->sps->height) - + int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma, s->ps.sps->height) - (y0 + size_in_luma)) >> vshift; - int top_right_size = (FFMIN(x0 + 2 * size_in_luma, s->sps->width) - + int top_right_size = (FFMIN(x0 + 2 * size_in_luma, s->ps.sps->width) - (x0 + size_in_luma)) >> hshift; - if (s->pps->constrained_intra_pred_flag == 1) { + if (s->ps.pps->constrained_intra_pred_flag == 1) { int size_in_luma_pu = PU(size_in_luma); - int on_pu_edge_x = !(x0 & ((1 << s->sps->log2_min_pu_size) - 1)); - int on_pu_edge_y = !(y0 & ((1 << s->sps->log2_min_pu_size) - 1)); + int on_pu_edge_x = !(x0 & ((1 << s->ps.sps->log2_min_pu_size) - 1)); + int on_pu_edge_y = !(y0 & ((1 << s->ps.sps->log2_min_pu_size) - 1)); if (!size_in_luma_pu) size_in_luma_pu++; if (cand_bottom_left == 1 && on_pu_edge_x) { int x_left_pu = PU(x0 - 1); int y_bottom_pu = PU(y0 + size_in_luma); - int max = FFMIN(size_in_luma_pu, s->sps->min_pu_height - y_bottom_pu); + int max = FFMIN(size_in_luma_pu, s->ps.sps->min_pu_height - y_bottom_pu); cand_bottom_left = 0; for (i = 0; i < max; i++) cand_bottom_left |= MVF(x_left_pu, y_bottom_pu + i).is_intra; @@ -127,7 +127,7 @@ do { \ if (cand_left == 1 && on_pu_edge_x) { int x_left_pu = PU(x0 - 1); int y_left_pu = PU(y0); - int max = FFMIN(size_in_luma_pu, s->sps->min_pu_height - y_left_pu); + int max = FFMIN(size_in_luma_pu, s->ps.sps->min_pu_height - y_left_pu); cand_left = 0; for (i = 0; i < max; i++) cand_left |= MVF(x_left_pu, y_left_pu + i).is_intra; @@ -140,7 +140,7 @@ do { \ if (cand_up == 1 && on_pu_edge_y) { int x_top_pu = PU(x0); int y_top_pu = PU(y0 - 1); - int max = FFMIN(size_in_luma_pu, s->sps->min_pu_width - x_top_pu); + int max = FFMIN(size_in_luma_pu, s->ps.sps->min_pu_width - x_top_pu); cand_up = 0; for (i = 0; i < max; i++) cand_up |= MVF(x_top_pu + i, y_top_pu).is_intra; @@ -148,7 +148,7 @@ do { \ if (cand_up_right == 1 && on_pu_edge_y) { int y_top_pu = PU(y0 - 1); int x_right_pu = PU(x0 + size_in_luma); - int max = FFMIN(size_in_luma_pu, s->sps->min_pu_width - x_right_pu); + int max = FFMIN(size_in_luma_pu, s->ps.sps->min_pu_width - x_right_pu); cand_up_right = 0; for (i = 0; i < max; i++) cand_up_right |= MVF(x_right_pu + i, y_top_pu).is_intra; @@ -179,20 +179,20 @@ do { \ size - top_right_size); } - if (s->pps->constrained_intra_pred_flag == 1) { + if (s->ps.pps->constrained_intra_pred_flag == 1) { if (cand_bottom_left || cand_left || cand_up_left || cand_up || cand_up_right) { - int size_max_x = x0 + ((2 * size) << hshift) < s->sps->width ? - 2 * size : (s->sps->width - x0) >> hshift; - int size_max_y = y0 + ((2 * size) << vshift) < s->sps->height ? - 2 * size : (s->sps->height - y0) >> vshift; + int size_max_x = x0 + ((2 * size) << hshift) < s->ps.sps->width ? + 2 * size : (s->ps.sps->width - x0) >> hshift; + int size_max_y = y0 + ((2 * size) << vshift) < s->ps.sps->height ? + 2 * size : (s->ps.sps->height - y0) >> vshift; int j = size + (cand_bottom_left? bottom_left_size: 0) -1; if (!cand_up_right) { - size_max_x = x0 + ((size) << hshift) < s->sps->width ? - size : (s->sps->width - x0) >> hshift; + size_max_x = x0 + ((size) << hshift) < s->ps.sps->width ? + size : (s->ps.sps->width - x0) >> hshift; } if (!cand_bottom_left) { - size_max_y = y0 + (( size) << vshift) < s->sps->height ? - size : (s->sps->height - y0) >> vshift; + size_max_y = y0 + (( size) << vshift) < s->ps.sps->height ? + size : (s->ps.sps->height - y0) >> vshift; } if (cand_bottom_left || cand_left || cand_up_left) { while (j > -1 && !IS_INTRA(-1, j)) @@ -284,7 +284,7 @@ do { \ FFABS((int)mode - 10)); if (min_dist_vert_hor > intra_hor_ver_dist_thresh[log2_size - 3]) { int threshold = 1 << (BIT_DEPTH - 5); - if (s->sps->sps_strong_intra_smoothing_enable_flag && + if (s->ps.sps->sps_strong_intra_smoothing_enable_flag && log2_size == 5 && FFABS(top[-1] + top[63] - 2 * top[31]) < threshold && FFABS(left[-1] + left[63] - 2 * left[31]) < threshold) { diff --git a/libavcodec/hnm4video.c b/libavcodec/hnm4video.c index 4220202..1dc6ed3 100644 --- a/libavcodec/hnm4video.c +++ b/libavcodec/hnm4video.c @@ -37,8 +37,8 @@ typedef struct Hnm4VideoContext { uint8_t version; - uint16_t width; - uint16_t height; + int width; + int height; uint8_t *current; uint8_t *previous; uint8_t *buffer1; @@ -461,5 +461,5 @@ AVCodec ff_hnm4_video_decoder = { .init = hnm_decode_init, .close = hnm_decode_end, .decode = hnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/hpeldsp.h b/libavcodec/hpeldsp.h index 7ffed1a..62dee68 100644 --- a/libavcodec/hpeldsp.h +++ b/libavcodec/hpeldsp.h @@ -69,15 +69,17 @@ typedef struct HpelDSPContext { /** * Halfpel motion compensation with no rounding (a+b)>>1. - * this is an array[2][4] of motion compensation functions for 2 + * this is an array[4][4] of motion compensation functions for 2 * horizontal blocksizes (8,16) and the 4 halfpel positions
* *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] * @param block destination where the result is stored * @param pixels source * @param line_size number of bytes in a horizontal line of block * @param h height + * @note The size is kept at [4][4] to match the above pixel_tabs and avoid + * out of bounds reads in the motion estimation code. */ - op_pixels_func put_no_rnd_pixels_tab[2][4]; + op_pixels_func put_no_rnd_pixels_tab[4][4]; /** * Halfpel motion compensation with no rounding (a+b)>>1. diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c new file mode 100644 index 0000000..98bd596 --- /dev/null +++ b/libavcodec/hq_hqa.c @@ -0,0 +1,391 @@ +/* + * Canopus HQ/HQA decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "canopus.h" +#include "get_bits.h" +#include "internal.h" + +#include "hq_hqa.h" +#include "hq_hqadsp.h" + +/* HQ/HQA slices are a set of macroblocks belonging to a frame, and + * they usually form a pseudorandom pattern (probably because it is + * nicer to display on partial decode). + * + * For HQA it just happens that each slice is on every 8th macroblock, + * but they can be on any frame width like + * X.......X. + * ......X... + * ....X..... + * ..X....... + * etc. + * + * The original decoder has special handling for edge macroblocks, + * while lavc simply aligns coded_width and coded_height. + */ + +static inline void put_blocks(HQContext *c, AVFrame *pic, + int plane, int x, int y, int ilace, + int16_t *block0, int16_t *block1) +{ + uint8_t *p = pic->data[plane] + x; + + c->hqhqadsp.idct_put(p + y * pic->linesize[plane], + pic->linesize[plane] << ilace, block0); + c->hqhqadsp.idct_put(p + (y + (ilace ? 1 : 8)) * pic->linesize[plane], + pic->linesize[plane] << ilace, block1); +} + +static int hq_decode_block(HQContext *c, GetBitContext *gb, int16_t block[64], + int qsel, int is_chroma, int is_hqa) +{ + const int32_t *q; + int val, pos = 1; + + memset(block, 0, 64 * sizeof(*block)); + + if (!is_hqa) { + block[0] = get_sbits(gb, 9) << 6; + q = ff_hq_quants[qsel][is_chroma][get_bits(gb, 2)]; + } else { + q = ff_hq_quants[qsel][is_chroma][get_bits(gb, 2)]; + block[0] = get_sbits(gb, 9) << 6; + } + + for (;;) { + val = get_vlc2(gb, c->hq_ac_vlc.table, 9, 2); + if (val < 0) + return AVERROR_INVALIDDATA; + + pos += ff_hq_ac_skips[val]; + if (pos >= 64) + break; + block[ff_zigzag_direct[pos]] = (ff_hq_ac_syms[val] * q[pos]) >> 12; + pos++; + } + + return 0; +} + +static int hq_decode_mb(HQContext *c, AVFrame *pic, + GetBitContext *gb, int x, int y) +{ + int qgroup, flag; + int i, ret; + + qgroup = get_bits(gb, 4); + flag = get_bits1(gb); + + for (i = 0; i < 8; i++) { + ret = hq_decode_block(c, gb, c->block[i], qgroup, i >= 4, 0); + if (ret < 0) + return ret; + } + + put_blocks(c, pic, 0, x, y, flag, c->block[0], c->block[2]); + put_blocks(c, pic, 0, x + 8, y, flag, c->block[1], c->block[3]); + put_blocks(c, pic, 2, x >> 1, y, flag, c->block[4], c->block[5]); + put_blocks(c, pic, 1, x >> 1, y, flag, c->block[6], c->block[7]); + + return 0; +} + +static int hq_decode_frame(HQContext *ctx, AVFrame *pic, + int prof_num, size_t data_size) +{ + const HQProfile *profile; + GetBitContext gb; + const uint8_t *perm, *src = ctx->gbc.buffer; + uint32_t slice_off[21]; + int slice, start_off, next_off, i, ret; + + if (prof_num >= NUM_HQ_PROFILES) { + profile = &ff_hq_profile[0]; + avpriv_request_sample(ctx->avctx, "HQ Profile %d", prof_num); + } else { + profile = &ff_hq_profile[prof_num]; + av_log(ctx->avctx, AV_LOG_VERBOSE, "HQ Profile %d\n", prof_num); + } + + ctx->avctx->coded_width = FFALIGN(profile->width, 16); + ctx->avctx->coded_height = FFALIGN(profile->height, 16); + ctx->avctx->width = profile->width; + ctx->avctx->height = profile->height; + ctx->avctx->bits_per_raw_sample = 8; + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + ret = ff_get_buffer(ctx->avctx, pic, 0); + if (ret < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); + return ret; + } + + /* Offsets are stored from CUV position, so adjust them accordingly. */ + for (i = 0; i < profile->num_slices + 1; i++) + slice_off[i] = bytestream2_get_be24(&ctx->gbc) - 4; + + next_off = 0; + for (slice = 0; slice < profile->num_slices; slice++) { + start_off = next_off; + next_off = profile->tab_h * (slice + 1) / profile->num_slices; + perm = profile->perm_tab + start_off * profile->tab_w * 2; + + if (slice_off[slice] < (profile->num_slices + 1) * 3 || + slice_off[slice] >= slice_off[slice + 1] || + slice_off[slice + 1] > data_size) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Invalid slice size %zu.\n", data_size); + break; + } + init_get_bits(&gb, src + slice_off[slice], + (slice_off[slice + 1] - slice_off[slice]) * 8); + + for (i = 0; i < (next_off - start_off) * profile->tab_w; i++) { + ret = hq_decode_mb(ctx, pic, &gb, perm[0] * 16, perm[1] * 16); + if (ret < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Error decoding macroblock %d at slice %d.\n", i, slice); + return ret; + } + perm += 2; + } + } + + return 0; +} + +static int hqa_decode_mb(HQContext *c, AVFrame *pic, int qgroup, + GetBitContext *gb, int x, int y) +{ + int flag = 0; + int i, ret, cbp; + + cbp = get_vlc2(gb, c->hqa_cbp_vlc.table, 5, 1); + + for (i = 0; i < 12; i++) + memset(c->block[i], 0, sizeof(*c->block)); + for (i = 0; i < 12; i++) + c->block[i][0] = -128 * (1 << 6); + + if (cbp) { + flag = get_bits1(gb); + + cbp |= cbp << 4; + if (cbp & 0x3) + cbp |= 0x500; + if (cbp & 0xC) + cbp |= 0xA00; + for (i = 0; i < 12; i++) { + if (!(cbp & (1 << i))) + continue; + ret = hq_decode_block(c, gb, c->block[i], qgroup, i >= 8, 1); + if (ret < 0) + return ret; + } + } + + put_blocks(c, pic, 3, x, y, flag, c->block[ 0], c->block[ 2]); + put_blocks(c, pic, 3, x + 8, y, flag, c->block[ 1], c->block[ 3]); + put_blocks(c, pic, 0, x, y, flag, c->block[ 4], c->block[ 6]); + put_blocks(c, pic, 0, x + 8, y, flag, c->block[ 5], c->block[ 7]); + put_blocks(c, pic, 2, x >> 1, y, flag, c->block[ 8], c->block[ 9]); + put_blocks(c, pic, 1, x >> 1, y, flag, c->block[10], c->block[11]); + + return 0; +} + +static int hqa_decode_slice(HQContext *ctx, AVFrame *pic, GetBitContext *gb, + int quant, int slice_no, int w, int h) +{ + int i, j, off; + int ret; + + for (i = 0; i < h; i += 16) { + off = (slice_no * 16 + i * 3) & 0x70; + for (j = off; j < w; j += 128) { + ret = hqa_decode_mb(ctx, pic, quant, gb, j, i); + if (ret < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Error decoding macroblock at %dx%d.\n", i, j); + return ret; + } + } + } + + return 0; +} + +static int hqa_decode_frame(HQContext *ctx, AVFrame *pic, size_t data_size) +{ + GetBitContext gb; + const int num_slices = 8; + uint32_t slice_off[9]; + int i, slice, ret; + int width, height, quant; + const uint8_t *src = ctx->gbc.buffer; + + width = bytestream2_get_be16(&ctx->gbc); + height = bytestream2_get_be16(&ctx->gbc); + + ctx->avctx->coded_width = FFALIGN(width, 16); + ctx->avctx->coded_height = FFALIGN(height, 16); + ctx->avctx->width = width; + ctx->avctx->height = height; + ctx->avctx->bits_per_raw_sample = 8; + ctx->avctx->pix_fmt = AV_PIX_FMT_YUVA422P; + + av_log(ctx->avctx, AV_LOG_VERBOSE, "HQA Profile\n"); + + quant = bytestream2_get_byte(&ctx->gbc); + bytestream2_skip(&ctx->gbc, 3); + if (quant >= NUM_HQ_QUANTS) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Invalid quantization matrix %d.\n", quant); + return AVERROR_INVALIDDATA; + } + + ret = ff_get_buffer(ctx->avctx, pic, 0); + if (ret < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); + return ret; + } + + /* Offsets are stored from HQA1 position, so adjust them accordingly. */ + for (i = 0; i < num_slices + 1; i++) + slice_off[i] = bytestream2_get_be32(&ctx->gbc) - 4; + + for (slice = 0; slice < num_slices; slice++) { + if (slice_off[slice] < (num_slices + 1) * 3 || + slice_off[slice] >= slice_off[slice + 1] || + slice_off[slice + 1] > data_size) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Invalid slice size %zu.\n", data_size); + break; + } + init_get_bits(&gb, src + slice_off[slice], + (slice_off[slice + 1] - slice_off[slice]) * 8); + + ret = hqa_decode_slice(ctx, pic, &gb, quant, slice, width, height); + if (ret < 0) + return ret; + } + + return 0; +} + +static int hq_hqa_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + HQContext *ctx = avctx->priv_data; + AVFrame *pic = data; + uint32_t info_tag; + unsigned int data_size; + int tag, ret; + + bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size); + if (bytestream2_get_bytes_left(&ctx->gbc) < 4 + 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + info_tag = bytestream2_peek_le32(&ctx->gbc); + if (info_tag == MKTAG('I', 'N', 'F', 'O')) { + int info_size; + bytestream2_skip(&ctx->gbc, 4); + info_size = bytestream2_get_le32(&ctx->gbc); + if (bytestream2_get_bytes_left(&ctx->gbc) < info_size) { + av_log(avctx, AV_LOG_ERROR, "Invalid INFO size (%d).\n", info_size); + return AVERROR_INVALIDDATA; + } + ff_canopus_parse_info_tag(avctx, ctx->gbc.buffer, info_size); + + bytestream2_skip(&ctx->gbc, info_size); + } + + data_size = bytestream2_get_bytes_left(&ctx->gbc); + if (data_size < 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n", data_size); + return AVERROR_INVALIDDATA; + } + + /* HQ defines dimensions and number of slices, and thus slice traversal + * order. HQA has no size constraint and a fixed number of slices, so it + * needs a separate scheme for it. */ + tag = bytestream2_get_le32(&ctx->gbc); + if ((tag & 0x00FFFFFF) == (MKTAG('U', 'V', 'C', ' ') & 0x00FFFFFF)) { + ret = hq_decode_frame(ctx, pic, tag >> 24, data_size); + } else if (tag == MKTAG('H', 'Q', 'A', '1')) { + ret = hqa_decode_frame(ctx, pic, data_size); + } else { + av_log(avctx, AV_LOG_ERROR, "Not a HQ/HQA frame.\n"); + return AVERROR_INVALIDDATA; + } + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error decoding frame.\n"); + return ret; + } + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int hq_hqa_decode_init(AVCodecContext *avctx) +{ + HQContext *ctx = avctx->priv_data; + ctx->avctx = avctx; + + ff_hqdsp_init(&ctx->hqhqadsp); + + return ff_hq_init_vlcs(ctx); +} + +static av_cold int hq_hqa_decode_close(AVCodecContext *avctx) +{ + HQContext *ctx = avctx->priv_data; + + ff_free_vlc(&ctx->hq_ac_vlc); + ff_free_vlc(&ctx->hqa_cbp_vlc); + + return 0; +} + +AVCodec ff_hq_hqa_decoder = { + .name = "hq_hqa", + .long_name = NULL_IF_CONFIG_SMALL("Canopus HQ/HQA"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HQ_HQA, + .priv_data_size = sizeof(HQContext), + .init = hq_hqa_decode_init, + .decode = hq_hqa_decode_frame, + .close = hq_hqa_decode_close, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/hq_hqa.h b/libavcodec/hq_hqa.h new file mode 100644 index 0000000..1fa9975 --- /dev/null +++ b/libavcodec/hq_hqa.h @@ -0,0 +1,60 @@ +/* + * Canopus HQ/HQA decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HQ_HQA_H +#define AVCODEC_HQ_HQA_H + +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "hq_hqadsp.h" +#include "vlc.h" + +#define NUM_HQ_AC_ENTRIES 746 +#define NUM_HQ_PROFILES 22 +#define NUM_HQ_QUANTS 16 + +typedef struct HQContext { + AVCodecContext *avctx; + HQDSPContext hqhqadsp; + GetByteContext gbc; + + VLC hq_ac_vlc; + VLC hqa_cbp_vlc; + DECLARE_ALIGNED(16, int16_t, block)[12][64]; +} HQContext; + +typedef struct HQProfile { + const uint8_t *perm_tab; + int width, height; + int num_slices; + int tab_w, tab_h; +} HQProfile; + +extern const int32_t * const ff_hq_quants[16][2][4]; +extern const HQProfile ff_hq_profile[NUM_HQ_PROFILES]; + +extern const uint8_t ff_hq_ac_skips[NUM_HQ_AC_ENTRIES]; +extern const int16_t ff_hq_ac_syms [NUM_HQ_AC_ENTRIES]; + +int ff_hq_init_vlcs(HQContext *c); + +#endif /* AVCODEC_HQ_HQA_H */ diff --git a/libavcodec/hq_hqadata.c b/libavcodec/hq_hqadata.c new file mode 100644 index 0000000..23fefc1 --- /dev/null +++ b/libavcodec/hq_hqadata.c @@ -0,0 +1,8377 @@ +/* + * Canopus HQ/HQA decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hq_hqa.h" + +#define MAT_SIZE 64 + +static const uint8_t cbp_vlc_bits[16] = { + 0x04, 0x1C, 0x1D, 0x09, 0x1E, 0x0B, 0x1B, 0x08, + 0x1F, 0x1A, 0x0C, 0x07, 0x0A, 0x06, 0x05, 0x00, +}; + +static const uint8_t cbp_vlc_lens[16] = { + 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2, +}; + +static const int32_t qmat00[MAT_SIZE] = { + 0x0040000, 0x000B18B, 0x00058C5, 0x000B1B1, 0x00082D3, 0x000B1B1, + 0x000A953, 0x000827B, 0x00104F7, 0x000A953, 0x0009000, 0x000EADD, + 0x001037B, 0x000756E, 0x0009000, 0x000776D, 0x000696A, 0x000E987, + 0x000E987, 0x000D2D4, 0x000776D, 0x0016BAF, 0x0014B4C, 0x001A21A, + 0x001BA75, 0x001A21A, 0x000A5A6, 0x000B5D8, 0x000611E, 0x000811D, + 0x00150B6, 0x00181B0, 0x00181B0, 0x00150B6, 0x0020474, 0x0018477, + 0x0022710, 0x001FD1E, 0x001366C, 0x0015000, 0x001366C, 0x000FE8F, + 0x00044E2, 0x0008A6D, 0x000EA30, 0x0010E47, 0x0010E47, 0x001D460, + 0x00229B2, 0x001FCB2, 0x0019FA3, 0x000D94C, 0x000CFD2, 0x0007F2D, + 0x000DEED, 0x0014D5E, 0x0029ABD, 0x0037BB5, 0x002D16B, 0x001FECE, + 0x000B45B, 0x0011521, 0x0022A42, 0x0012B9C, +}; + +static const int32_t qmat01[MAT_SIZE] = { + 0x0040000, 0x000B18B, 0x00058C5, 0x000B1B1, 0x00082D3, 0x000B1B1, + 0x000EB2D, 0x000B53A, 0x0016A73, 0x000EB2D, 0x000D000, 0x0014632, + 0x0016314, 0x000A319, 0x000D000, 0x000A36D, 0x0009041, 0x0014BDA, + 0x0014BDA, 0x0012081, 0x000A36D, 0x0016BAF, 0x0014B4C, 0x001A21A, + 0x001BA75, 0x001A21A, 0x000A5A6, 0x000B5D8, 0x000611E, 0x000811D, + 0x00150B6, 0x00181B0, 0x00181B0, 0x00150B6, 0x0020474, 0x0018477, + 0x0045A60, 0x004058C, 0x0026CD9, 0x002A000, 0x0026CD9, 0x00202C6, + 0x0008B4C, 0x00114D9, 0x001D977, 0x0021C8F, 0x0021C8F, 0x003B2EF, + 0x0045365, 0x007FD2A, 0x00675E5, 0x0036A1F, 0x0033AF3, 0x001FF4B, + 0x001C010, 0x0029E24, 0x0053C47, 0x007003E, 0x005A9C7, 0x004024C, + 0x0016A72, 0x0022A42, 0x0045485, 0x0025738, +}; + +static const int32_t qmat02[MAT_SIZE] = { + 0x0040000, 0x0016315, 0x000B18B, 0x0016363, 0x00105A6, 0x0016363, + 0x00152A7, 0x00104F7, 0x00209EE, 0x00152A7, 0x0012000, 0x001D5B9, + 0x00206F6, 0x000EADD, 0x0012000, 0x000EEDA, 0x000D2D4, 0x001D30D, + 0x001D30D, 0x001A5A9, 0x000EEDA, 0x002D75E, 0x0029698, 0x0034433, + 0x00374EB, 0x0034433, 0x0014B4C, 0x0016BAF, 0x000C23C, 0x001023A, + 0x002A16C, 0x0030360, 0x0030360, 0x002A16C, 0x00408E9, 0x00308EF, + 0x0044E21, 0x003FA3C, 0x0026CD9, 0x002A000, 0x0026CD9, 0x001FD1E, + 0x00089C4, 0x00114D9, 0x001D460, 0x0021C8F, 0x0021C8F, 0x003A8C0, + 0x0045365, 0x003F964, 0x0033F47, 0x001B297, 0x0019FA3, 0x000FE59, + 0x001BDDA, 0x0029ABD, 0x0053579, 0x006F76A, 0x005A2D7, 0x003FD9D, + 0x00168B6, 0x0022A42, 0x0045485, 0x0025738, +}; + +static const int32_t qmat03[MAT_SIZE] = { + 0x0040000, 0x0016315, 0x000B18B, 0x0016363, 0x00105A6, 0x0016363, + 0x001D65A, 0x0016A73, 0x002D4E7, 0x001D65A, 0x001A000, 0x0028C65, + 0x002C628, 0x0014632, 0x001A000, 0x00146D9, 0x0012081, 0x00297B5, + 0x00297B5, 0x0024102, 0x00146D9, 0x002D75E, 0x0029698, 0x0034433, + 0x00374EB, 0x0034433, 0x0014B4C, 0x0016BAF, 0x000C23C, 0x001023A, + 0x002A16C, 0x0030360, 0x0030360, 0x002A16C, 0x00408E9, 0x00308EF, + 0x008B4C0, 0x0080B18, 0x004D9B2, 0x0054000, 0x004D9B2, 0x004058C, + 0x0011698, 0x00229B2, 0x003B2EF, 0x004391E, 0x004391E, 0x00765DD, + 0x008A6CA, 0x00FFA54, 0x00CEBCA, 0x006D43E, 0x00675E5, 0x003FE95, + 0x003801F, 0x0053C47, 0x00A788E, 0x00E007C, 0x00B538D, 0x0080498, + 0x002D4E3, 0x0045485, 0x008A90A, 0x004AE71, +}; + +static const int32_t qmat04[MAT_SIZE] = { + 0x0040000, 0x00214A0, 0x0010A50, 0x0021514, 0x0018879, 0x0021514, + 0x001FBFA, 0x0018772, 0x0030EE5, 0x001FBFA, 0x001B000, 0x002C096, + 0x0030A71, 0x001604B, 0x001B000, 0x0016647, 0x0013C3F, 0x002BC94, + 0x002BC94, 0x002787D, 0x0016647, 0x004430D, 0x003E1E4, 0x004E64D, + 0x0052F60, 0x004E64D, 0x001F0F2, 0x0022187, 0x001235A, 0x0018357, + 0x003F223, 0x0048510, 0x0048510, 0x003F223, 0x0060D5D, 0x0048D66, + 0x0067531, 0x005F75A, 0x003A345, 0x003F000, 0x003A345, 0x002FBAD, + 0x000CEA6, 0x0019F46, 0x002BE90, 0x0032AD6, 0x0032AD6, 0x0057D20, + 0x0067D17, 0x005F616, 0x004DEEA, 0x0028BE3, 0x0026F75, 0x0017D86, + 0x0029CC8, 0x003E81B, 0x007D036, 0x00A731F, 0x0087442, 0x005FC6B, + 0x0021D11, 0x0033F64, 0x0067EC7, 0x00382D5, +}; + +static const int32_t qmat05[MAT_SIZE] = { + 0x0040000, 0x00214A0, 0x0010A50, 0x0021514, 0x0018879, 0x0021514, + 0x002C186, 0x0021FAD, 0x0043F5A, 0x002C186, 0x0027000, 0x003D297, + 0x004293C, 0x001E94C, 0x0027000, 0x001EA46, 0x001B0C2, 0x003E38F, + 0x003E38F, 0x0036183, 0x001EA46, 0x004430D, 0x003E1E4, 0x004E64D, + 0x0052F60, 0x004E64D, 0x001F0F2, 0x0022187, 0x001235A, 0x0018357, + 0x003F223, 0x0048510, 0x0048510, 0x003F223, 0x0060D5D, 0x0048D66, + 0x00D0F1F, 0x00C10A4, 0x007468B, 0x007E000, 0x007468B, 0x0060852, + 0x001A1E4, 0x0033E8C, 0x0058C66, 0x00655AD, 0x00655AD, 0x00B18CC, + 0x00CFA2F, 0x017F77F, 0x01361B0, 0x00A3E5C, 0x009B0D8, 0x005FDE0, + 0x005402F, 0x007DA6B, 0x00FB4D5, 0x01500BA, 0x010FD54, 0x00C06E5, + 0x0043F55, 0x0067EC7, 0x00CFD8F, 0x00705A9, +}; + +static const int32_t qmat06[MAT_SIZE] = { + 0x0040000, 0x002C62A, 0x0016315, 0x002C6C5, 0x0020B4C, 0x002C6C5, + 0x002A54E, 0x00209EE, 0x00413DC, 0x002A54E, 0x0024000, 0x003AB73, + 0x0040DEC, 0x001D5B9, 0x0024000, 0x001DDB4, 0x001A5A9, 0x003A61B, + 0x003A61B, 0x0034B52, 0x001DDB4, 0x005AEBC, 0x0052D2F, 0x0068867, + 0x006E9D6, 0x0068867, 0x0029698, 0x002D75E, 0x0018477, 0x0020474, + 0x00542D9, 0x00606C0, 0x00606C0, 0x00542D9, 0x00811D1, 0x00611DE, + 0x0089C42, 0x007F478, 0x004D9B2, 0x0054000, 0x004D9B2, 0x003FA3C, + 0x0011388, 0x00229B2, 0x003A8C0, 0x004391E, 0x004391E, 0x0075180, + 0x008A6CA, 0x007F2C9, 0x0067E8E, 0x003652F, 0x0033F47, 0x001FCB2, + 0x0037BB5, 0x0053579, 0x00A6AF3, 0x00DEED4, 0x00B45AE, 0x007FB39, + 0x002D16B, 0x0045485, 0x008A90A, 0x004AE71, +}; + +static const int32_t qmat07[MAT_SIZE] = { + 0x0040000, 0x002C62A, 0x0016315, 0x002C6C5, 0x0020B4C, 0x002C6C5, + 0x003ACB3, 0x002D4E7, 0x005A9CE, 0x003ACB3, 0x0034000, 0x00518CA, + 0x0058C50, 0x0028C65, 0x0034000, 0x0028DB3, 0x0024102, 0x0052F69, + 0x0052F69, 0x0048204, 0x0028DB3, 0x005AEBC, 0x0052D2F, 0x0068867, + 0x006E9D6, 0x0068867, 0x0029698, 0x002D75E, 0x0018477, 0x0020474, + 0x00542D9, 0x00606C0, 0x00606C0, 0x00542D9, 0x00811D1, 0x00611DE, + 0x011697F, 0x0101631, 0x009B363, 0x00A8000, 0x009B363, 0x0080B18, + 0x0022D30, 0x0045365, 0x00765DD, 0x008723C, 0x008723C, 0x00ECBBB, + 0x0114D94, 0x01FF4A9, 0x019D795, 0x00DA87B, 0x00CEBCA, 0x007FD2A, + 0x007003E, 0x00A788E, 0x014F11C, 0x01C00F8, 0x016A71B, 0x0100931, + 0x005A9C7, 0x008A90A, 0x0115214, 0x0095CE2, +}; + +static const int32_t qmat08[MAT_SIZE] = { + 0x0040000, 0x00377B5, 0x001BBDA, 0x0037876, 0x0028E1E, 0x0037876, + 0x0034EA1, 0x0028C69, 0x00518D3, 0x0034EA1, 0x002D000, 0x004964F, + 0x0051167, 0x0024B28, 0x002D000, 0x0025521, 0x0020F13, 0x0048FA1, + 0x0048FA1, 0x0041E26, 0x0025521, 0x0071A6B, 0x006787B, 0x0082A80, + 0x008A44B, 0x0082A80, 0x0033C3E, 0x0038D36, 0x001E595, 0x0028591, + 0x006938F, 0x0078870, 0x0078870, 0x006938F, 0x00A1646, 0x0079655, + 0x00AC352, 0x009F196, 0x006101E, 0x0069000, 0x006101E, 0x004F8CB, + 0x001586A, 0x002B41F, 0x00492F0, 0x0054765, 0x0054765, 0x00925E0, + 0x00AD07C, 0x009EF7B, 0x0081E31, 0x0043E7A, 0x0040F19, 0x0027BDF, + 0x0045AA2, 0x00682D8, 0x00D05B0, 0x0116A89, 0x00E1719, 0x009FA07, + 0x00385C6, 0x00569A6, 0x00AD34C, 0x005DA0D, +}; + +static const int32_t qmat09[MAT_SIZE] = { + 0x0040000, 0x00377B5, 0x001BBDA, 0x0037876, 0x0028E1E, 0x0037876, + 0x00497E0, 0x0038A21, 0x0071441, 0x00497E0, 0x0041000, 0x0065EFC, + 0x006EF64, 0x0032F7E, 0x0041000, 0x003311F, 0x002D143, 0x0067B44, + 0x0067B44, 0x005A285, 0x003311F, 0x0071A6B, 0x006787B, 0x0082A80, + 0x008A44B, 0x0082A80, 0x0033C3E, 0x0038D36, 0x001E595, 0x0028591, + 0x006938F, 0x0078870, 0x0078870, 0x006938F, 0x00A1646, 0x0079655, + 0x015C3DF, 0x0141BBD, 0x00C203C, 0x00D2000, 0x00C203C, 0x00A0DDE, + 0x002B87C, 0x005683E, 0x0093F55, 0x00A8ECA, 0x00A8ECA, 0x0127EA9, + 0x015A0F9, 0x027F1D3, 0x0204D7A, 0x011129A, 0x01026BD, 0x009FC75, + 0x008C04E, 0x00D16B2, 0x01A2D64, 0x0230136, 0x01C50E1, 0x0140B7D, + 0x0071438, 0x00AD34C, 0x015A699, 0x00BB41A, +}; + +static const int32_t qmat0A[MAT_SIZE] = { + 0x0040000, 0x004293F, 0x00214A0, 0x0042A28, 0x00310F1, 0x0042A28, + 0x003F7F5, 0x0030EE5, 0x0061DCA, 0x003F7F5, 0x0036000, 0x005812C, + 0x00614E2, 0x002C096, 0x0036000, 0x002CC8E, 0x002787D, 0x0057928, + 0x0057928, 0x004F0FB, 0x002CC8E, 0x008861A, 0x007C3C7, 0x009CC9A, + 0x00A5EC1, 0x009CC9A, 0x003E1E4, 0x004430D, 0x00246B3, 0x00306AF, + 0x007E445, 0x0090A20, 0x0090A20, 0x007E445, 0x00C1ABA, 0x0091ACC, + 0x00CEA63, 0x00BEEB4, 0x007468B, 0x007E000, 0x007468B, 0x005F75A, + 0x0019D4C, 0x0033E8C, 0x0057D20, 0x00655AD, 0x00655AD, 0x00AFA40, + 0x00CFA2F, 0x00BEC2D, 0x009BDD5, 0x00517C6, 0x004DEEA, 0x002FB0B, + 0x005398F, 0x007D036, 0x00FA06C, 0x014E63E, 0x010E885, 0x00BF8D6, + 0x0043A21, 0x0067EC7, 0x00CFD8F, 0x00705A9, +}; + +static const int32_t qmat0B[MAT_SIZE] = { + 0x0040000, 0x004293F, 0x00214A0, 0x0042A28, 0x00310F1, 0x0042A28, + 0x005830D, 0x0043F5A, 0x0087EB5, 0x005830D, 0x004E000, 0x007A52F, + 0x0085278, 0x003D297, 0x004E000, 0x003D48C, 0x0036183, 0x007C71E, + 0x007C71E, 0x006C307, 0x003D48C, 0x008861A, 0x007C3C7, 0x009CC9A, + 0x00A5EC1, 0x009CC9A, 0x003E1E4, 0x004430D, 0x00246B3, 0x00306AF, + 0x007E445, 0x0090A20, 0x0090A20, 0x007E445, 0x00C1ABA, 0x0091ACC, + 0x01A1E3F, 0x0182149, 0x00E8D15, 0x00FC000, 0x00E8D15, 0x00C10A4, + 0x00343C8, 0x0067D17, 0x00B18CC, 0x00CAB59, 0x00CAB59, 0x0163198, + 0x019F45E, 0x02FEEFD, 0x026C35F, 0x0147CB9, 0x01361B0, 0x00BFBBF, + 0x00A805D, 0x00FB4D5, 0x01F69AB, 0x02A0174, 0x021FAA8, 0x0180DC9, + 0x0087EAA, 0x00CFD8F, 0x019FB1E, 0x00E0B52, +}; + +static const int32_t qmat0C[MAT_SIZE] = { + 0x0040000, 0x004DACA, 0x0026D65, 0x004DBD9, 0x00393C4, 0x004DBD9, + 0x004A148, 0x0039160, 0x00722C1, 0x004A148, 0x003F000, 0x0066C09, + 0x007185D, 0x0033604, 0x003F000, 0x00343FB, 0x002E1E8, 0x00662AF, + 0x00662AF, 0x005C3CF, 0x00343FB, 0x009F1C9, 0x0090F13, 0x00B6EB3, + 0x00C1936, 0x00B6EB3, 0x0048789, 0x004F8E5, 0x002A7D1, 0x00387CC, + 0x00934FB, 0x00A8BCF, 0x00A8BCF, 0x00934FB, 0x00E1F2E, 0x00A9F44, + 0x00F1173, 0x00DEBD1, 0x0087CF7, 0x0093000, 0x0087CF7, 0x006F5E9, + 0x001E22E, 0x003C8F8, 0x0066750, 0x00763F4, 0x00763F4, 0x00CCEA0, + 0x00F23E1, 0x00DE8DF, 0x00B5D78, 0x005F111, 0x005AEBC, 0x0037A38, + 0x006187D, 0x0091D95, 0x0123B29, 0x01861F3, 0x013B9F0, 0x00DF7A4, + 0x004EE7C, 0x00793E9, 0x00F27D1, 0x0083145, +}; + +static const int32_t qmat0D[MAT_SIZE] = { + 0x0040000, 0x004DACA, 0x0026D65, 0x004DBD9, 0x00393C4, 0x004DBD9, + 0x0066E3A, 0x004F494, 0x009E928, 0x0066E3A, 0x005B000, 0x008EB61, + 0x009B58C, 0x00475B1, 0x005B000, 0x00477F9, 0x003F1C4, 0x00912F8, + 0x00912F8, 0x007E388, 0x00477F9, 0x009F1C9, 0x0090F13, 0x00B6EB3, + 0x00C1936, 0x00B6EB3, 0x0048789, 0x004F8E5, 0x002A7D1, 0x00387CC, + 0x00934FB, 0x00A8BCF, 0x00A8BCF, 0x00934FB, 0x00E1F2E, 0x00A9F44, + 0x01E789E, 0x01C26D5, 0x010F9EE, 0x0126000, 0x010F9EE, 0x00E136B, + 0x003CF14, 0x00791F1, 0x00CF243, 0x00EC7E8, 0x00EC7E8, 0x019E487, + 0x01E47C3, 0x037EC27, 0x02D3944, 0x017E6D8, 0x0169CA2, 0x00DFB0A, + 0x00C406D, 0x01252F9, 0x024A5F2, 0x03101B2, 0x027A46F, 0x01C1016, + 0x009E91C, 0x00F27D1, 0x01E4FA3, 0x010628B, +}; + +static const int32_t qmat0E[MAT_SIZE] = { + 0x0040000, 0x0058C54, 0x002C62A, 0x0058D8A, 0x0041697, 0x0058D8A, + 0x0054A9C, 0x00413DC, 0x00827B8, 0x0054A9C, 0x0048000, 0x00756E5, + 0x0081BD8, 0x003AB73, 0x0048000, 0x003BB68, 0x0034B52, 0x0074C35, + 0x0074C35, 0x00696A4, 0x003BB68, 0x00B5D78, 0x00A5A5F, 0x00D10CD, + 0x00DD3AB, 0x00D10CD, 0x0052D2F, 0x005AEBC, 0x00308EF, 0x00408E9, + 0x00A85B1, 0x00C0D7F, 0x00C0D7F, 0x00A85B1, 0x01023A3, 0x00C23BB, + 0x0113883, 0x00FE8EF, 0x009B363, 0x00A8000, 0x009B363, 0x007F478, + 0x0022710, 0x0045365, 0x0075180, 0x008723C, 0x008723C, 0x00EA300, + 0x0114D94, 0x00FE591, 0x00CFD1C, 0x006CA5D, 0x0067E8E, 0x003F964, + 0x006F76A, 0x00A6AF3, 0x014D5E6, 0x01BDDA8, 0x0168B5C, 0x00FF672, + 0x005A2D7, 0x008A90A, 0x0115214, 0x0095CE2, +}; + +static const int32_t qmat0F[MAT_SIZE] = { + 0x0040000, 0x0058C54, 0x002C62A, 0x0058D8A, 0x0041697, 0x0058D8A, + 0x0075967, 0x005A9CE, 0x00B539C, 0x0075967, 0x0068000, 0x00A3194, + 0x00B18A0, 0x00518CA, 0x0068000, 0x0051B65, 0x0048204, 0x00A5ED3, + 0x00A5ED3, 0x0090409, 0x0051B65, 0x00B5D78, 0x00A5A5F, 0x00D10CD, + 0x00DD3AB, 0x00D10CD, 0x0052D2F, 0x005AEBC, 0x00308EF, 0x00408E9, + 0x00A85B1, 0x00C0D7F, 0x00C0D7F, 0x00A85B1, 0x01023A3, 0x00C23BB, + 0x022D2FE, 0x0202C61, 0x01366C7, 0x0150000, 0x01366C7, 0x0101631, + 0x0045A60, 0x008A6CA, 0x00ECBBB, 0x010E477, 0x010E477, 0x01D9776, + 0x0229B27, 0x03FE951, 0x033AF2A, 0x01B50F6, 0x019D795, 0x00FFA54, + 0x00E007C, 0x014F11C, 0x029E239, 0x03801F0, 0x02D4E36, 0x0201262, + 0x00B538D, 0x0115214, 0x022A428, 0x012B9C3, +}; + +static const int32_t qmat10[MAT_SIZE] = { + 0x0040000, 0x006EF69, 0x00377B5, 0x006F0ED, 0x0051C3D, 0x006F0ED, + 0x0069D43, 0x00518D3, 0x00A31A6, 0x0069D43, 0x005A000, 0x0092C9F, + 0x00A22CD, 0x004964F, 0x005A000, 0x004AA42, 0x0041E26, 0x0091F43, + 0x0091F43, 0x0083C4D, 0x004AA42, 0x00E34D6, 0x00CF0F6, 0x0105500, + 0x0114896, 0x0105500, 0x006787B, 0x0071A6B, 0x003CB2A, 0x0050B23, + 0x00D271E, 0x00F10DF, 0x00F10DF, 0x00D271E, 0x0142C8B, 0x00F2CAA, + 0x01586A4, 0x013E32B, 0x00C203C, 0x00D2000, 0x00C203C, 0x009F196, + 0x002B0D5, 0x005683E, 0x00925E0, 0x00A8ECA, 0x00A8ECA, 0x0124BC0, + 0x015A0F9, 0x013DEF5, 0x0103C63, 0x0087CF4, 0x0081E31, 0x004F7BD, + 0x008B544, 0x00D05B0, 0x01A0B5F, 0x022D511, 0x01C2E32, 0x013F40F, + 0x0070B8D, 0x00AD34C, 0x015A699, 0x00BB41A, +}; + +static const int32_t qmat11[MAT_SIZE] = { + 0x0040000, 0x006EF69, 0x00377B5, 0x006F0ED, 0x0051C3D, 0x006F0ED, + 0x0092FC0, 0x0071441, 0x00E2883, 0x0092FC0, 0x0082000, 0x00CBDF9, + 0x00DDEC8, 0x0065EFC, 0x0082000, 0x006623F, 0x005A285, 0x00CF687, + 0x00CF687, 0x00B450B, 0x006623F, 0x00E34D6, 0x00CF0F6, 0x0105500, + 0x0114896, 0x0105500, 0x006787B, 0x0071A6B, 0x003CB2A, 0x0050B23, + 0x00D271E, 0x00F10DF, 0x00F10DF, 0x00D271E, 0x0142C8B, 0x00F2CAA, + 0x02B87BE, 0x028377A, 0x0184078, 0x01A4000, 0x0184078, 0x0141BBD, + 0x00570F8, 0x00AD07C, 0x0127EA9, 0x0151D95, 0x0151D95, 0x024FD53, + 0x02B41F1, 0x04FE3A6, 0x0409AF4, 0x0222534, 0x0204D7A, 0x013F8E9, + 0x011809B, 0x01A2D64, 0x0345AC7, 0x046026C, 0x038A1C3, 0x02816FA, + 0x00E2871, 0x015A699, 0x02B4D32, 0x0176834, +}; + +static const int32_t qmat12[MAT_SIZE] = { + 0x0040000, 0x008527E, 0x004293F, 0x0085450, 0x00621E3, 0x0085450, + 0x007EFEA, 0x0061DCA, 0x00C3B94, 0x007EFEA, 0x006C000, 0x00B0258, + 0x00C29C3, 0x005812C, 0x006C000, 0x005991C, 0x004F0FB, 0x00AF250, + 0x00AF250, 0x009E1F6, 0x005991C, 0x0110C35, 0x00F878E, 0x0139934, + 0x014BD81, 0x0139934, 0x007C3C7, 0x008861A, 0x0048D66, 0x0060D5D, + 0x00FC88A, 0x012143F, 0x012143F, 0x00FC88A, 0x0183574, 0x0123599, + 0x019D4C5, 0x017DD67, 0x00E8D15, 0x00FC000, 0x00E8D15, 0x00BEEB4, + 0x0033A99, 0x0067D17, 0x00AFA40, 0x00CAB59, 0x00CAB59, 0x015F480, + 0x019F45E, 0x017D85A, 0x0137BAA, 0x00A2F8C, 0x009BDD5, 0x005F616, + 0x00A731F, 0x00FA06C, 0x01F40D9, 0x029CC7B, 0x021D109, 0x017F1AB, + 0x0087442, 0x00CFD8F, 0x019FB1E, 0x00E0B52, +}; + +static const int32_t qmat13[MAT_SIZE] = { + 0x0040000, 0x008527E, 0x004293F, 0x0085450, 0x00621E3, 0x0085450, + 0x00B061A, 0x0087EB5, 0x010FD69, 0x00B061A, 0x009C000, 0x00F4A5E, + 0x010A4F0, 0x007A52F, 0x009C000, 0x007A918, 0x006C307, 0x00F8E3C, + 0x00F8E3C, 0x00D860D, 0x007A918, 0x0110C35, 0x00F878E, 0x0139934, + 0x014BD81, 0x0139934, 0x007C3C7, 0x008861A, 0x0048D66, 0x0060D5D, + 0x00FC88A, 0x012143F, 0x012143F, 0x00FC88A, 0x0183574, 0x0123599, + 0x0343C7D, 0x0304292, 0x01D1A2A, 0x01F8000, 0x01D1A2A, 0x0182149, + 0x0068790, 0x00CFA2F, 0x0163198, 0x01956B3, 0x01956B3, 0x02C6330, + 0x033E8BB, 0x05FDDFA, 0x04D86BE, 0x028F971, 0x026C35F, 0x017F77F, + 0x01500BA, 0x01F69AB, 0x03ED355, 0x05402E9, 0x043F550, 0x0301B93, + 0x010FD54, 0x019FB1E, 0x033F63C, 0x01C16A5, +}; + +static const int32_t qmat14[MAT_SIZE] = { + 0x0040000, 0x009B593, 0x004DACA, 0x009B7B2, 0x0072789, 0x009B7B2, + 0x0094291, 0x00722C1, 0x00E4582, 0x0094291, 0x007E000, 0x00CD812, + 0x00E30B9, 0x0066C09, 0x007E000, 0x00687F5, 0x005C3CF, 0x00CC55D, + 0x00CC55D, 0x00B879F, 0x00687F5, 0x013E393, 0x0121E26, 0x016DD67, + 0x018326C, 0x016DD67, 0x0090F13, 0x009F1C9, 0x0054FA2, 0x0070F97, + 0x01269F7, 0x015179F, 0x015179F, 0x01269F7, 0x01C3E5D, 0x0153E87, + 0x01E22E6, 0x01BD7A3, 0x010F9EE, 0x0126000, 0x010F9EE, 0x00DEBD1, + 0x003C45D, 0x00791F1, 0x00CCEA0, 0x00EC7E8, 0x00EC7E8, 0x0199D41, + 0x01E47C3, 0x01BD1BE, 0x016BAF1, 0x00BE223, 0x00B5D78, 0x006F46F, + 0x00C30F9, 0x0123B29, 0x0247652, 0x030C3E5, 0x02773E0, 0x01BEF48, + 0x009DCF8, 0x00F27D1, 0x01E4FA3, 0x010628B, +}; + +static const int32_t qmat15[MAT_SIZE] = { + 0x0040000, 0x009B593, 0x004DACA, 0x009B7B2, 0x0072789, 0x009B7B2, + 0x00CDC74, 0x009E928, 0x013D250, 0x00CDC74, 0x00B6000, 0x011D6C3, + 0x0136B18, 0x008EB61, 0x00B6000, 0x008EFF2, 0x007E388, 0x01225F0, + 0x01225F0, 0x00FC70F, 0x008EFF2, 0x013E393, 0x0121E26, 0x016DD67, + 0x018326C, 0x016DD67, 0x0090F13, 0x009F1C9, 0x0054FA2, 0x0070F97, + 0x01269F7, 0x015179F, 0x015179F, 0x01269F7, 0x01C3E5D, 0x0153E87, + 0x03CF13D, 0x0384DAA, 0x021F3DC, 0x024C000, 0x021F3DC, 0x01C26D5, + 0x0079E28, 0x00F23E1, 0x019E487, 0x01D8FD0, 0x01D8FD0, 0x033C90E, + 0x03C8F85, 0x06FD84F, 0x05A7289, 0x02FCDAF, 0x02D3944, 0x01BF614, + 0x01880D9, 0x024A5F2, 0x0494BE4, 0x0620365, 0x04F48DE, 0x038202B, + 0x013D237, 0x01E4FA3, 0x03C9F46, 0x020C516, +}; + +static const int32_t qmat16[MAT_SIZE] = { + 0x0040000, 0x00B18A8, 0x0058C54, 0x00B1B15, 0x0082D2E, 0x00B1B15, + 0x00A9538, 0x00827B8, 0x0104F6F, 0x00A9538, 0x0090000, 0x00EADCB, + 0x01037AF, 0x00756E5, 0x0090000, 0x00776CF, 0x00696A4, 0x00E986B, + 0x00E986B, 0x00D2D48, 0x00776CF, 0x016BAF1, 0x014B4BD, 0x01A219A, + 0x01BA757, 0x01A219A, 0x00A5A5F, 0x00B5D78, 0x00611DE, 0x00811D1, + 0x0150B63, 0x0181AFF, 0x0181AFF, 0x0150B63, 0x0204745, 0x0184776, + 0x0227107, 0x01FD1DF, 0x01366C7, 0x0150000, 0x01366C7, 0x00FE8EF, + 0x0044E21, 0x008A6CA, 0x00EA300, 0x010E477, 0x010E477, 0x01D4601, + 0x0229B27, 0x01FCB22, 0x019FA38, 0x00D94BA, 0x00CFD1C, 0x007F2C9, + 0x00DEED4, 0x014D5E6, 0x029ABCC, 0x037BB4F, 0x02D16B7, 0x01FECE4, + 0x00B45AE, 0x0115214, 0x022A428, 0x012B9C3, +}; + +static const int32_t qmat17[MAT_SIZE] = { + 0x0040000, 0x00B18A8, 0x0058C54, 0x00B1B15, 0x0082D2E, 0x00B1B15, + 0x00EB2CD, 0x00B539C, 0x016A737, 0x00EB2CD, 0x00D0000, 0x0146328, + 0x0163140, 0x00A3194, 0x00D0000, 0x00A36CB, 0x0090409, 0x014BDA5, + 0x014BDA5, 0x0120812, 0x00A36CB, 0x016BAF1, 0x014B4BD, 0x01A219A, + 0x01BA757, 0x01A219A, 0x00A5A5F, 0x00B5D78, 0x00611DE, 0x00811D1, + 0x0150B63, 0x0181AFF, 0x0181AFF, 0x0150B63, 0x0204745, 0x0184776, + 0x045A5FD, 0x04058C2, 0x026CD8D, 0x02A0000, 0x026CD8D, 0x0202C61, + 0x008B4C0, 0x0114D94, 0x01D9776, 0x021C8EE, 0x021C8EE, 0x03B2EEB, + 0x045364F, 0x07FD2A3, 0x0675E53, 0x036A1ED, 0x033AF2A, 0x01FF4A9, + 0x01C00F8, 0x029E239, 0x053C472, 0x07003E1, 0x05A9C6B, 0x04024C4, + 0x016A71B, 0x022A428, 0x0454850, 0x0257386, +}; + +static const int32_t qmat18[MAT_SIZE] = { + 0x0040000, 0x00C7BBD, 0x0063DDF, 0x00C7E77, 0x00932D4, 0x00C7E77, + 0x00BE7DF, 0x0092CAF, 0x012595D, 0x00BE7DF, 0x00A2000, 0x0108384, + 0x0123EA5, 0x00841C2, 0x00A2000, 0x00865A9, 0x0076978, 0x0106B78, + 0x0106B78, 0x00ED2F1, 0x00865A9, 0x019924F, 0x0174B55, 0x01D65CD, + 0x01F1C42, 0x01D65CD, 0x00BA5AB, 0x00CC927, 0x006D419, 0x009140C, + 0x017ACCF, 0x01B1E5F, 0x01B1E5F, 0x017ACCF, 0x024502E, 0x01B5065, + 0x026BF28, 0x023CC1B, 0x015D3A0, 0x017A000, 0x015D3A0, 0x011E60D, + 0x004D7E5, 0x009BBA3, 0x0107760, 0x0130106, 0x0130106, 0x020EEC1, + 0x026EE8C, 0x023C486, 0x01D397F, 0x00F4751, 0x00E9CBF, 0x008F122, + 0x00FACAE, 0x01770A2, 0x02EE145, 0x03EB2B9, 0x032B98E, 0x023EA81, + 0x00CAE64, 0x0137C56, 0x026F8AD, 0x01510FC, +}; + +static const int32_t qmat19[MAT_SIZE] = { + 0x0040000, 0x00C7BBD, 0x0063DDF, 0x00C7E77, 0x00932D4, 0x00C7E77, + 0x0108927, 0x00CBE0F, 0x0197C1E, 0x0108927, 0x00EA000, 0x016EF8D, + 0x018F768, 0x00B77C6, 0x00EA000, 0x00B7DA4, 0x00A248A, 0x017555A, + 0x017555A, 0x0144914, 0x00B7DA4, 0x019924F, 0x0174B55, 0x01D65CD, + 0x01F1C42, 0x01D65CD, 0x00BA5AB, 0x00CC927, 0x006D419, 0x009140C, + 0x017ACCF, 0x01B1E5F, 0x01B1E5F, 0x017ACCF, 0x024502E, 0x01B5065, + 0x04E5ABC, 0x04863DB, 0x02BA73F, 0x02F4000, 0x02BA73F, 0x02431ED, + 0x009CB58, 0x0137746, 0x0214A64, 0x026020C, 0x026020C, 0x04294C8, + 0x04DDD19, 0x08FCCF7, 0x0744A1D, 0x03D762A, 0x03A250F, 0x023F33E, + 0x01F8117, 0x02F1E80, 0x05E3D00, 0x07E045D, 0x065EFF9, 0x048295C, + 0x0197BFE, 0x026F8AD, 0x04DF15A, 0x02A21F7, +}; + +static const int32_t qmat1A[MAT_SIZE] = { + 0x0040000, 0x00DDED2, 0x006EF69, 0x00DE1DA, 0x00A387A, 0x00DE1DA, + 0x00D3A86, 0x00A31A6, 0x014634B, 0x00D3A86, 0x00B4000, 0x012593E, + 0x014459B, 0x0092C9F, 0x00B4000, 0x0095483, 0x0083C4D, 0x0123E85, + 0x0123E85, 0x010789A, 0x0095483, 0x01C69AD, 0x019E1ED, 0x020AA01, + 0x022912D, 0x020AA01, 0x00CF0F6, 0x00E34D6, 0x0079655, 0x00A1646, + 0x01A4E3C, 0x01E21BE, 0x01E21BE, 0x01A4E3C, 0x0285917, 0x01E5954, + 0x02B0D48, 0x027C656, 0x0184078, 0x01A4000, 0x0184078, 0x013E32B, + 0x00561A9, 0x00AD07C, 0x0124BC0, 0x0151D95, 0x0151D95, 0x0249781, + 0x02B41F1, 0x027BDEB, 0x02078C6, 0x010F9E9, 0x0103C63, 0x009EF7B, + 0x0116A89, 0x01A0B5F, 0x03416BE, 0x045AA23, 0x0385C65, 0x027E81E, + 0x00E1719, 0x015A699, 0x02B4D32, 0x0176834, +}; + +static const int32_t qmat1B[MAT_SIZE] = { + 0x0040000, 0x00DDED2, 0x006EF69, 0x00DE1DA, 0x00A387A, 0x00DE1DA, + 0x0125F81, 0x00E2883, 0x01C5105, 0x0125F81, 0x0104000, 0x0197BF2, + 0x01BBD90, 0x00CBDF9, 0x0104000, 0x00CC47E, 0x00B450B, 0x019ED0E, + 0x019ED0E, 0x0168A16, 0x00CC47E, 0x01C69AD, 0x019E1ED, 0x020AA01, + 0x022912D, 0x020AA01, 0x00CF0F6, 0x00E34D6, 0x0079655, 0x00A1646, + 0x01A4E3C, 0x01E21BE, 0x01E21BE, 0x01A4E3C, 0x0285917, 0x01E5954, + 0x0570F7C, 0x0506EF3, 0x03080F1, 0x0348000, 0x03080F1, 0x028377A, + 0x00AE1EF, 0x015A0F9, 0x024FD53, 0x02A3B2A, 0x02A3B2A, 0x049FAA6, + 0x05683E3, 0x09FC74C, 0x08135E8, 0x0444A68, 0x0409AF4, 0x027F1D3, + 0x0230136, 0x0345AC7, 0x068B58E, 0x08C04D9, 0x0714386, 0x0502DF5, + 0x01C50E1, 0x02B4D32, 0x0569A64, 0x02ED068, +}; + +static const int32_t qmat1C[MAT_SIZE] = { + 0x0040000, 0x00F41E7, 0x007A0F4, 0x00F453D, 0x00B3E20, 0x00F453D, + 0x00E8D2D, 0x00B369D, 0x0166D39, 0x00E8D2D, 0x00C6000, 0x0142EF7, + 0x0164C91, 0x00A177B, 0x00C6000, 0x00A435D, 0x0090F21, 0x0141193, + 0x0141193, 0x0121E43, 0x00A435D, 0x01F410B, 0x01C7884, 0x023EE34, + 0x0260617, 0x023EE34, 0x00E3C42, 0x00FA086, 0x0085891, 0x00B1880, + 0x01CEFA8, 0x021251E, 0x021251E, 0x01CEFA8, 0x02C6200, 0x0216242, + 0x02F5B69, 0x02BC092, 0x01AAD51, 0x01CE000, 0x01AAD51, 0x015E049, + 0x005EB6D, 0x00BE556, 0x0142020, 0x0173A24, 0x0173A24, 0x0284041, + 0x02F9556, 0x02BB74F, 0x023B80D, 0x012AC80, 0x011DC06, 0x00AEDD4, + 0x0132863, 0x01CA61C, 0x0394C38, 0x04CA18D, 0x03DFF3C, 0x02BE5BA, + 0x00F7FCF, 0x017D0DB, 0x02FA1B7, 0x019BF6C, +}; + +static const int32_t qmat1D[MAT_SIZE] = { + 0x0040000, 0x00F41E7, 0x007A0F4, 0x00F453D, 0x00B3E20, 0x00F453D, + 0x01435DA, 0x00F92F6, 0x01F25EC, 0x01435DA, 0x011E000, 0x01C0857, + 0x01E83B8, 0x00E042B, 0x011E000, 0x00E0B57, 0x00C658C, 0x01C84C3, + 0x01C84C3, 0x018CB18, 0x00E0B57, 0x01F410B, 0x01C7884, 0x023EE34, + 0x0260617, 0x023EE34, 0x00E3C42, 0x00FA086, 0x0085891, 0x00B1880, + 0x01CEFA8, 0x021251E, 0x021251E, 0x01CEFA8, 0x02C6200, 0x0216242, + 0x05FC43B, 0x0587A0B, 0x0355AA3, 0x039C000, 0x0355AA3, 0x02C3D06, + 0x00BF887, 0x017CAAB, 0x028B042, 0x02E7447, 0x02E7447, 0x0516083, + 0x05F2AAD, 0x0AFC1A0, 0x08E21B2, 0x04B1EA5, 0x04710D9, 0x02BF068, + 0x0268155, 0x039970E, 0x0732E1D, 0x09A0555, 0x07C9713, 0x058328D, + 0x01F25C5, 0x02FA1B7, 0x05F436E, 0x0337ED9, +}; + +static const int32_t qmat1E[MAT_SIZE] = { + 0x0040000, 0x010A4FD, 0x008527E, 0x010A89F, 0x00C43C5, 0x010A89F, + 0x00FDFD3, 0x00C3B94, 0x0187727, 0x00FDFD3, 0x00D8000, 0x01604B0, + 0x0185387, 0x00B0258, 0x00D8000, 0x00B3237, 0x009E1F6, 0x015E4A0, + 0x015E4A0, 0x013C3EC, 0x00B3237, 0x0221869, 0x01F0F1C, 0x0273267, + 0x0297B02, 0x0273267, 0x00F878E, 0x0110C35, 0x0091ACC, 0x00C1ABA, + 0x01F9114, 0x024287E, 0x024287E, 0x01F9114, 0x0306AE8, 0x0246B31, + 0x033A98A, 0x02FBACE, 0x01D1A2A, 0x01F8000, 0x01D1A2A, 0x017DD67, + 0x0067531, 0x00CFA2F, 0x015F480, 0x01956B3, 0x01956B3, 0x02BE901, + 0x033E8BB, 0x02FB0B3, 0x026F754, 0x0145F17, 0x0137BAA, 0x00BEC2D, + 0x014E63E, 0x01F40D9, 0x03E81B1, 0x05398F7, 0x043A213, 0x02FE357, + 0x010E885, 0x019FB1E, 0x033F63C, 0x01C16A5, +}; + +static const int32_t qmat1F[MAT_SIZE] = { + 0x0040000, 0x010A4FD, 0x008527E, 0x010A89F, 0x00C43C5, 0x010A89F, + 0x0160C34, 0x010FD69, 0x021FAD3, 0x0160C34, 0x0138000, 0x01E94BC, + 0x02149E1, 0x00F4A5E, 0x0138000, 0x00F5230, 0x00D860D, 0x01F1C78, + 0x01F1C78, 0x01B0C1A, 0x00F5230, 0x0221869, 0x01F0F1C, 0x0273267, + 0x0297B02, 0x0273267, 0x00F878E, 0x0110C35, 0x0091ACC, 0x00C1ABA, + 0x01F9114, 0x024287E, 0x024287E, 0x01F9114, 0x0306AE8, 0x0246B31, + 0x06878FB, 0x0608524, 0x03A3454, 0x03F0000, 0x03A3454, 0x0304292, + 0x00D0F1F, 0x019F45E, 0x02C6330, 0x032AD65, 0x032AD65, 0x058C661, + 0x067D176, 0x0BFBBF4, 0x09B0D7D, 0x051F2E3, 0x04D86BE, 0x02FEEFD, + 0x02A0174, 0x03ED355, 0x07DA6AB, 0x0A805D1, 0x087EAA1, 0x0603726, + 0x021FAA8, 0x033F63C, 0x067EC78, 0x0382D4A, +}; + +static const int32_t qmat20[MAT_SIZE] = { + 0x0040000, 0x0136B27, 0x009B593, 0x0136F64, 0x00E4F11, 0x0136F64, + 0x0128521, 0x00E4582, 0x01C8B03, 0x0128521, 0x00FC000, 0x019B023, + 0x01C6172, 0x00CD812, 0x00FC000, 0x00D0FEB, 0x00B879F, 0x0198ABB, + 0x0198ABB, 0x0170F3E, 0x00D0FEB, 0x027C725, 0x0243C4B, 0x02DBACE, + 0x03064D8, 0x02DBACE, 0x0121E26, 0x013E393, 0x00A9F44, 0x00E1F2E, + 0x024D3ED, 0x02A2F3E, 0x02A2F3E, 0x024D3ED, 0x0387CBA, 0x02A7D0F, + 0x03C45CC, 0x037AF46, 0x021F3DC, 0x024C000, 0x021F3DC, 0x01BD7A3, + 0x00788B9, 0x00F23E1, 0x0199D41, 0x01D8FD0, 0x01D8FD0, 0x0333A81, + 0x03C8F85, 0x037A37C, 0x02D75E2, 0x017C446, 0x016BAF1, 0x00DE8DF, + 0x01861F3, 0x0247652, 0x048ECA4, 0x06187CA, 0x04EE7C1, 0x037DE90, + 0x013B9F0, 0x01E4FA3, 0x03C9F46, 0x020C516, +}; + +static const int32_t qmat21[MAT_SIZE] = { + 0x0040000, 0x0136B27, 0x009B593, 0x0136F64, 0x00E4F11, 0x0136F64, + 0x019B8E7, 0x013D250, 0x027A4A1, 0x019B8E7, 0x016C000, 0x023AD86, + 0x026D631, 0x011D6C3, 0x016C000, 0x011DFE3, 0x00FC70F, 0x0244BE1, + 0x0244BE1, 0x01F8E1F, 0x011DFE3, 0x027C725, 0x0243C4B, 0x02DBACE, + 0x03064D8, 0x02DBACE, 0x0121E26, 0x013E393, 0x00A9F44, 0x00E1F2E, + 0x024D3ED, 0x02A2F3E, 0x02A2F3E, 0x024D3ED, 0x0387CBA, 0x02A7D0F, + 0x079E27A, 0x0709B54, 0x043E7B8, 0x0498000, 0x043E7B8, 0x0384DAA, + 0x00F3C4F, 0x01E47C3, 0x033C90E, 0x03B1FA1, 0x03B1FA1, 0x067921B, + 0x0791F0A, 0x0DFB09D, 0x0B4E511, 0x05F9B5E, 0x05A7289, 0x037EC27, + 0x03101B2, 0x0494BE4, 0x09297C7, 0x0C406C9, 0x09E91BC, 0x0704057, + 0x027A46F, 0x03C9F46, 0x0793E8C, 0x0418A2B, +}; + +static const int32_t qmat22[MAT_SIZE] = { + 0x0040000, 0x0163151, 0x00B18A8, 0x0163629, 0x0105A5D, 0x0163629, + 0x0152A6F, 0x0104F6F, 0x0209EDF, 0x0152A6F, 0x0120000, 0x01D5B96, + 0x0206F5E, 0x00EADCB, 0x0120000, 0x00EED9F, 0x00D2D48, 0x01D30D5, + 0x01D30D5, 0x01A5A90, 0x00EED9F, 0x02D75E2, 0x029697B, 0x0344334, + 0x0374EAE, 0x0344334, 0x014B4BD, 0x016BAF1, 0x00C23BB, 0x01023A3, + 0x02A16C6, 0x03035FE, 0x03035FE, 0x02A16C6, 0x0408E8B, 0x0308EEC, + 0x044E20D, 0x03FA3BE, 0x026CD8D, 0x02A0000, 0x026CD8D, 0x01FD1DF, + 0x0089C42, 0x0114D94, 0x01D4601, 0x021C8EE, 0x021C8EE, 0x03A8C01, + 0x045364F, 0x03F9644, 0x033F46F, 0x01B2974, 0x019FA38, 0x00FE591, + 0x01BDDA8, 0x029ABCC, 0x0535797, 0x06F769E, 0x05A2D6E, 0x03FD9C9, + 0x0168B5C, 0x022A428, 0x0454850, 0x0257386, +}; + +static const int32_t qmat23[MAT_SIZE] = { + 0x0040000, 0x0163151, 0x00B18A8, 0x0163629, 0x0105A5D, 0x0163629, + 0x01D659B, 0x016A737, 0x02D4E6E, 0x01D659B, 0x01A0000, 0x028C650, + 0x02C6281, 0x0146328, 0x01A0000, 0x0146D96, 0x0120812, 0x0297B4A, + 0x0297B4A, 0x0241023, 0x0146D96, 0x02D75E2, 0x029697B, 0x0344334, + 0x0374EAE, 0x0344334, 0x014B4BD, 0x016BAF1, 0x00C23BB, 0x01023A3, + 0x02A16C6, 0x03035FE, 0x03035FE, 0x02A16C6, 0x0408E8B, 0x0308EEC, + 0x08B4BF9, 0x080B185, 0x04D9B1B, 0x0540000, 0x04D9B1B, 0x04058C2, + 0x011697F, 0x0229B27, 0x03B2EEB, 0x04391DC, 0x04391DC, 0x0765DD6, + 0x08A6C9E, 0x0FFA546, 0x0CEBCA6, 0x06D43D9, 0x0675E53, 0x03FE951, + 0x03801F0, 0x053C472, 0x0A788E4, 0x0E007C1, 0x0B538D6, 0x0804988, + 0x02D4E36, 0x0454850, 0x08A90A0, 0x04AE70D, +}; + +static const int32_t qmat24[MAT_SIZE] = { + 0x0040000, 0x018F77B, 0x00C7BBD, 0x018FCEF, 0x01265A8, 0x018FCEF, + 0x017CFBD, 0x012595D, 0x024B2BB, 0x017CFBD, 0x0144000, 0x0210708, + 0x0247D4A, 0x0108384, 0x0144000, 0x010CB53, 0x00ED2F1, 0x020D6F0, + 0x020D6F0, 0x01DA5E2, 0x010CB53, 0x033249E, 0x02E96AA, 0x03ACB9B, + 0x03E3883, 0x03ACB9B, 0x0174B55, 0x019924F, 0x00DA832, 0x0122817, + 0x02F599F, 0x0363CBD, 0x0363CBD, 0x02F599F, 0x048A05C, 0x036A0CA, + 0x04D7E4F, 0x0479835, 0x02BA73F, 0x02F4000, 0x02BA73F, 0x023CC1B, + 0x009AFCA, 0x0137746, 0x020EEC1, 0x026020C, 0x026020C, 0x041DD81, + 0x04DDD19, 0x047890D, 0x03A72FD, 0x01E8EA3, 0x01D397F, 0x011E243, + 0x01F595C, 0x02EE145, 0x05DC28A, 0x07D6572, 0x065731C, 0x047D502, + 0x0195CC7, 0x026F8AD, 0x04DF15A, 0x02A21F7, +}; + +static const int32_t qmat25[MAT_SIZE] = { + 0x0040000, 0x018F77B, 0x00C7BBD, 0x018FCEF, 0x01265A8, 0x018FCEF, + 0x021124E, 0x0197C1E, 0x032F83C, 0x021124E, 0x01D4000, 0x02DDF1A, + 0x031EED1, 0x016EF8D, 0x01D4000, 0x016FB49, 0x0144914, 0x02EAAB3, + 0x02EAAB3, 0x0289228, 0x016FB49, 0x033249E, 0x02E96AA, 0x03ACB9B, + 0x03E3883, 0x03ACB9B, 0x0174B55, 0x019924F, 0x00DA832, 0x0122817, + 0x02F599F, 0x0363CBD, 0x0363CBD, 0x02F599F, 0x048A05C, 0x036A0CA, + 0x09CB578, 0x090C7B6, 0x0574E7E, 0x05E8000, 0x0574E7E, 0x04863DB, + 0x01396AF, 0x026EE8C, 0x04294C8, 0x04C0418, 0x04C0418, 0x0852991, + 0x09BBA32, 0x11F99EF, 0x0E8943B, 0x07AEC54, 0x0744A1D, 0x047E67C, + 0x03F022E, 0x05E3D00, 0x0BC7A00, 0x0FC08BA, 0x0CBDFF1, 0x09052B9, + 0x032F7FC, 0x04DF15A, 0x09BE2B4, 0x05443EE, +}; + +static const int32_t qmat26[MAT_SIZE] = { + 0x0040000, 0x01BBDA5, 0x00DDED2, 0x01BC3B4, 0x01470F4, 0x01BC3B4, + 0x01A750B, 0x014634B, 0x028C697, 0x01A750B, 0x0168000, 0x024B27B, + 0x0288B36, 0x012593E, 0x0168000, 0x012A906, 0x010789A, 0x0247D0B, + 0x0247D0B, 0x020F134, 0x012A906, 0x038D35A, 0x033C3D9, 0x0415402, + 0x0452259, 0x0415402, 0x019E1ED, 0x01C69AD, 0x00F2CAA, 0x0142C8B, + 0x0349C77, 0x03C437D, 0x03C437D, 0x0349C77, 0x050B22E, 0x03CB2A7, + 0x0561A91, 0x04F8CAD, 0x03080F1, 0x0348000, 0x03080F1, 0x027C656, + 0x00AC352, 0x015A0F9, 0x0249781, 0x02A3B2A, 0x02A3B2A, 0x0492F02, + 0x05683E3, 0x04F7BD5, 0x040F18B, 0x021F3D1, 0x02078C6, 0x013DEF5, + 0x022D511, 0x03416BE, 0x0682D7D, 0x08B5446, 0x070B8CA, 0x04FD03B, + 0x01C2E32, 0x02B4D32, 0x0569A64, 0x02ED068, +}; + +static const int32_t qmat27[MAT_SIZE] = { + 0x0040000, 0x01BBDA5, 0x00DDED2, 0x01BC3B4, 0x01470F4, 0x01BC3B4, + 0x024BF01, 0x01C5105, 0x038A20A, 0x024BF01, 0x0208000, 0x032F7E4, + 0x0377B21, 0x0197BF2, 0x0208000, 0x01988FB, 0x0168A16, 0x033DA1D, + 0x033DA1D, 0x02D142C, 0x01988FB, 0x038D35A, 0x033C3D9, 0x0415402, + 0x0452259, 0x0415402, 0x019E1ED, 0x01C69AD, 0x00F2CAA, 0x0142C8B, + 0x0349C77, 0x03C437D, 0x03C437D, 0x0349C77, 0x050B22E, 0x03CB2A7, + 0x0AE1EF7, 0x0A0DDE6, 0x06101E2, 0x0690000, 0x06101E2, 0x0506EF3, + 0x015C3DF, 0x02B41F1, 0x049FAA6, 0x0547653, 0x0547653, 0x093F54C, + 0x0AD07C5, 0x13F8E97, 0x1026BD0, 0x08894CF, 0x08135E8, 0x04FE3A6, + 0x046026C, 0x068B58E, 0x0D16B1D, 0x11809B2, 0x0E2870C, 0x0A05BEA, + 0x038A1C3, 0x0569A64, 0x0AD34C8, 0x05DA0D0, +}; + +static const int32_t qmat28[MAT_SIZE] = { + 0x0040000, 0x01E83CF, 0x00F41E7, 0x01E8A79, 0x0167C3F, 0x01E8A79, + 0x01D1A59, 0x0166D39, 0x02CDA72, 0x01D1A59, 0x018C000, 0x0285DEE, + 0x02C9921, 0x0142EF7, 0x018C000, 0x01486BA, 0x0121E43, 0x0282325, + 0x0282325, 0x0243C86, 0x01486BA, 0x03E8216, 0x038F109, 0x047DC68, + 0x04C0C2F, 0x047DC68, 0x01C7884, 0x01F410B, 0x010B121, 0x0163100, + 0x039DF50, 0x0424A3D, 0x0424A3D, 0x039DF50, 0x058C3FF, 0x042C485, + 0x05EB6D3, 0x0578125, 0x0355AA3, 0x039C000, 0x0355AA3, 0x02BC092, + 0x00BD6DA, 0x017CAAB, 0x0284041, 0x02E7447, 0x02E7447, 0x0508082, + 0x05F2AAD, 0x0576E9E, 0x0477019, 0x0255900, 0x023B80D, 0x015DBA7, + 0x02650C6, 0x0394C38, 0x0729870, 0x0994319, 0x07BFE78, 0x057CB74, + 0x01EFF9E, 0x02FA1B7, 0x05F436E, 0x0337ED9, +}; + +static const int32_t qmat29[MAT_SIZE] = { + 0x0040000, 0x01E83CF, 0x00F41E7, 0x01E8A79, 0x0167C3F, 0x01E8A79, + 0x0286BB5, 0x01F25EC, 0x03E4BD8, 0x0286BB5, 0x023C000, 0x03810AE, + 0x03D0771, 0x01C0857, 0x023C000, 0x01C16AE, 0x018CB18, 0x0390986, + 0x0390986, 0x0319630, 0x01C16AE, 0x03E8216, 0x038F109, 0x047DC68, + 0x04C0C2F, 0x047DC68, 0x01C7884, 0x01F410B, 0x010B121, 0x0163100, + 0x039DF50, 0x0424A3D, 0x0424A3D, 0x039DF50, 0x058C3FF, 0x042C485, + 0x0BF8876, 0x0B0F417, 0x06AB545, 0x0738000, 0x06AB545, 0x0587A0B, + 0x017F10F, 0x02F9556, 0x0516083, 0x05CE88F, 0x05CE88F, 0x0A2C106, + 0x0BE5559, 0x15F8340, 0x11C4364, 0x0963D4B, 0x08E21B2, 0x057E0D0, + 0x04D02AB, 0x0732E1D, 0x0E65C39, 0x1340AAA, 0x0F92E27, 0x0B0651B, + 0x03E4B8A, 0x05F436E, 0x0BE86DC, 0x066FDB2, +}; + +static const int32_t qmat2A[MAT_SIZE] = { + 0x0040000, 0x02149F9, 0x010A4FD, 0x021513E, 0x018878B, 0x021513E, + 0x01FBFA7, 0x0187727, 0x030EE4E, 0x01FBFA7, 0x01B0000, 0x02C0961, + 0x030A70D, 0x01604B0, 0x01B0000, 0x016646E, 0x013C3EC, 0x02BC940, + 0x02BC940, 0x02787D8, 0x016646E, 0x04430D2, 0x03E1E38, 0x04E64CF, + 0x052F604, 0x04E64CF, 0x01F0F1C, 0x0221869, 0x0123599, 0x0183574, + 0x03F2229, 0x04850FC, 0x04850FC, 0x03F2229, 0x060D5D0, 0x048D662, + 0x0675314, 0x05F759C, 0x03A3454, 0x03F0000, 0x03A3454, 0x02FBACE, + 0x00CEA63, 0x019F45E, 0x02BE901, 0x032AD65, 0x032AD65, 0x057D202, + 0x067D176, 0x05F6166, 0x04DEEA7, 0x028BE2E, 0x026F754, 0x017D85A, + 0x029CC7B, 0x03E81B1, 0x07D0363, 0x0A731ED, 0x0874425, 0x05FC6AD, + 0x021D109, 0x033F63C, 0x067EC78, 0x0382D4A, +}; + +static const int32_t qmat2B[MAT_SIZE] = { + 0x0040000, 0x02149F9, 0x010A4FD, 0x021513E, 0x018878B, 0x021513E, + 0x02C1868, 0x021FAD3, 0x043F5A6, 0x02C1868, 0x0270000, 0x03D2978, + 0x04293C1, 0x01E94BC, 0x0270000, 0x01EA461, 0x01B0C1A, 0x03E38EF, + 0x03E38EF, 0x0361835, 0x01EA461, 0x04430D2, 0x03E1E38, 0x04E64CF, + 0x052F604, 0x04E64CF, 0x01F0F1C, 0x0221869, 0x0123599, 0x0183574, + 0x03F2229, 0x04850FC, 0x04850FC, 0x03F2229, 0x060D5D0, 0x048D662, + 0x0D0F1F6, 0x0C10A47, 0x07468A8, 0x07E0000, 0x07468A8, 0x0608524, + 0x01A1E3F, 0x033E8BB, 0x058C661, 0x0655ACA, 0x0655ACA, 0x0B18CC1, + 0x0CFA2ED, 0x17F77E9, 0x1361AF9, 0x0A3E5C6, 0x09B0D7D, 0x05FDDFA, + 0x05402E9, 0x07DA6AB, 0x0FB4D56, 0x1500BA2, 0x10FD541, 0x0C06E4C, + 0x043F550, 0x067EC78, 0x0CFD8F0, 0x0705A93, +}; + +static const int32_t qmat2C[MAT_SIZE] = { + 0x0040000, 0x0241023, 0x0120812, 0x0241803, 0x01A92D7, 0x0241803, + 0x02264F5, 0x01A8115, 0x035022A, 0x02264F5, 0x01D4000, 0x02FB4D3, + 0x034B4F9, 0x017DA6A, 0x01D4000, 0x0184222, 0x0156995, 0x02F6F5B, + 0x02F6F5B, 0x02AD32A, 0x0184222, 0x049DF8E, 0x0434B67, 0x054ED35, + 0x059DFDA, 0x054ED35, 0x021A5B4, 0x024EFC7, 0x013BA10, 0x01A39E8, + 0x0446502, 0x04E57BC, 0x04E57BC, 0x0446502, 0x068E7A2, 0x04EE840, + 0x06FEF56, 0x0676A14, 0x03F0E06, 0x0444000, 0x03F0E06, 0x033B50A, + 0x00DFDEB, 0x01C1E10, 0x02F91C1, 0x036E683, 0x036E683, 0x05F2382, + 0x0707840, 0x067542F, 0x0546D35, 0x02C235D, 0x02A369B, 0x019D50C, + 0x02D4830, 0x043B72B, 0x0876E56, 0x0B520C1, 0x09289D3, 0x067C1E6, + 0x024A275, 0x0384AC1, 0x0709582, 0x03CDBBA, +}; + +static const int32_t qmat2D[MAT_SIZE] = { + 0x0040000, 0x0241023, 0x0120812, 0x0241803, 0x01A92D7, 0x0241803, + 0x02FC51B, 0x024CFBA, 0x0499F73, 0x02FC51B, 0x02A4000, 0x0424242, + 0x0482011, 0x0212121, 0x02A4000, 0x0213214, 0x01D4D1D, 0x0436858, + 0x0436858, 0x03A9A39, 0x0213214, 0x049DF8E, 0x0434B67, 0x054ED35, + 0x059DFDA, 0x054ED35, 0x021A5B4, 0x024EFC7, 0x013BA10, 0x01A39E8, + 0x0446502, 0x04E57BC, 0x04E57BC, 0x0446502, 0x068E7A2, 0x04EE840, + 0x0E25B75, 0x0D12078, 0x07E1C0C, 0x0888000, 0x07E1C0C, 0x068903C, + 0x01C4B6F, 0x0383C20, 0x0602C3E, 0x06DCD06, 0x06DCD06, 0x0C0587C, + 0x0E0F081, 0x19F6C92, 0x14FF28E, 0x0B18E41, 0x0A7F947, 0x067DB24, + 0x05B0327, 0x0881F39, 0x1103E72, 0x16C0C9A, 0x1267C5C, 0x0D0777D, + 0x0499F17, 0x0709582, 0x0E12B04, 0x079B775, +}; + +static const int32_t qmat2E[MAT_SIZE] = { + 0x0040000, 0x026D64D, 0x0136B27, 0x026DEC9, 0x01C9E22, 0x026DEC9, + 0x0250A43, 0x01C8B03, 0x0391606, 0x0250A43, 0x01F8000, 0x0336046, + 0x038C2E5, 0x019B023, 0x01F8000, 0x01A1FD6, 0x0170F3E, 0x0331575, + 0x0331575, 0x02E1E7C, 0x01A1FD6, 0x04F8E4B, 0x0487897, 0x05B759C, + 0x060C9B0, 0x05B759C, 0x0243C4B, 0x027C725, 0x0153E87, 0x01C3E5D, + 0x049A7DA, 0x0545E7C, 0x0545E7C, 0x049A7DA, 0x070F973, 0x054FA1D, + 0x0788B98, 0x06F5E8C, 0x043E7B8, 0x0498000, 0x043E7B8, 0x037AF46, + 0x00F1173, 0x01E47C3, 0x0333A81, 0x03B1FA1, 0x03B1FA1, 0x0667502, + 0x0791F0A, 0x06F46F7, 0x05AEBC3, 0x02F888B, 0x02D75E2, 0x01BD1BE, + 0x030C3E5, 0x048ECA4, 0x091D948, 0x0C30F95, 0x09DCF81, 0x06FBD20, + 0x02773E0, 0x03C9F46, 0x0793E8C, 0x0418A2B, +}; + +static const int32_t qmat2F[MAT_SIZE] = { + 0x0040000, 0x026D64D, 0x0136B27, 0x026DEC9, 0x01C9E22, 0x026DEC9, + 0x03371CF, 0x027A4A1, 0x04F4941, 0x03371CF, 0x02D8000, 0x0475B0C, + 0x04DAC61, 0x023AD86, 0x02D8000, 0x023BFC6, 0x01F8E1F, 0x04897C2, + 0x04897C2, 0x03F1C3D, 0x023BFC6, 0x04F8E4B, 0x0487897, 0x05B759C, + 0x060C9B0, 0x05B759C, 0x0243C4B, 0x027C725, 0x0153E87, 0x01C3E5D, + 0x049A7DA, 0x0545E7C, 0x0545E7C, 0x049A7DA, 0x070F973, 0x054FA1D, + 0x0F3C4F4, 0x0E136A9, 0x087CF6F, 0x0930000, 0x087CF6F, 0x0709B54, + 0x01E789E, 0x03C8F85, 0x067921B, 0x0763F41, 0x0763F41, 0x0CF2437, + 0x0F23E14, 0x1BF613A, 0x169CA23, 0x0BF36BC, 0x0B4E511, 0x06FD84F, + 0x0620365, 0x09297C7, 0x1252F8F, 0x1880D93, 0x13D2377, 0x0E080AE, + 0x04F48DE, 0x0793E8C, 0x0F27D18, 0x0831457, +}; + +static const int32_t qmat30[MAT_SIZE] = { + 0x0040000, 0x02C62A1, 0x0163151, 0x02C6C53, 0x020B4B9, 0x02C6C53, + 0x02A54DF, 0x0209EDF, 0x0413DBE, 0x02A54DF, 0x0240000, 0x03AB72B, + 0x040DEBC, 0x01D5B96, 0x0240000, 0x01DDB3E, 0x01A5A90, 0x03A61AB, + 0x03A61AB, 0x034B520, 0x01DDB3E, 0x05AEBC3, 0x052D2F5, 0x0688669, + 0x06E9D5B, 0x0688669, 0x029697B, 0x02D75E2, 0x0184776, 0x0204745, + 0x0542D8C, 0x0606BFB, 0x0606BFB, 0x0542D8C, 0x0811D16, 0x0611DD8, + 0x089C41B, 0x07F477B, 0x04D9B1B, 0x0540000, 0x04D9B1B, 0x03FA3BE, + 0x0113883, 0x0229B27, 0x03A8C01, 0x04391DC, 0x04391DC, 0x0751803, + 0x08A6C9E, 0x07F2C88, 0x067E8DF, 0x03652E8, 0x033F46F, 0x01FCB22, + 0x037BB4F, 0x0535797, 0x0A6AF2E, 0x0DEED3C, 0x0B45ADD, 0x07FB392, + 0x02D16B7, 0x0454850, 0x08A90A0, 0x04AE70D, +}; + +static const int32_t qmat31[MAT_SIZE] = { + 0x0040000, 0x02C62A1, 0x0163151, 0x02C6C53, 0x020B4B9, 0x02C6C53, + 0x03ACB35, 0x02D4E6E, 0x05A9CDD, 0x03ACB35, 0x0340000, 0x0518CA0, + 0x058C501, 0x028C650, 0x0340000, 0x028DB2C, 0x0241023, 0x052F694, + 0x052F694, 0x0482046, 0x028DB2C, 0x05AEBC3, 0x052D2F5, 0x0688669, + 0x06E9D5B, 0x0688669, 0x029697B, 0x02D75E2, 0x0184776, 0x0204745, + 0x0542D8C, 0x0606BFB, 0x0606BFB, 0x0542D8C, 0x0811D16, 0x0611DD8, + 0x11697F2, 0x101630A, 0x09B3636, 0x0A80000, 0x09B3636, 0x080B185, + 0x022D2FE, 0x045364F, 0x0765DD6, 0x08723B8, 0x08723B8, 0x0ECBBAC, + 0x114D93C, 0x1FF4A8C, 0x19D794C, 0x0DA87B2, 0x0CEBCA6, 0x07FD2A3, + 0x07003E1, 0x0A788E4, 0x14F11C8, 0x1C00F83, 0x16A71AD, 0x1009310, + 0x05A9C6B, 0x08A90A0, 0x1152140, 0x095CE1A, +}; + +static const int32_t qmat32[MAT_SIZE] = { + 0x0040000, 0x031EEF6, 0x018F77B, 0x031F9DD, 0x024CB50, 0x031F9DD, + 0x02F9F7A, 0x024B2BB, 0x0496575, 0x02F9F7A, 0x0288000, 0x0420E11, + 0x048FA94, 0x0210708, 0x0288000, 0x02196A5, 0x01DA5E2, 0x041ADE0, + 0x041ADE0, 0x03B4BC4, 0x02196A5, 0x066493B, 0x05D2D54, 0x0759736, + 0x07C7107, 0x0759736, 0x02E96AA, 0x033249E, 0x01B5065, 0x024502E, + 0x05EB33D, 0x06C797A, 0x06C797A, 0x05EB33D, 0x09140B9, 0x06D4193, + 0x09AFC9E, 0x08F306A, 0x0574E7E, 0x05E8000, 0x0574E7E, 0x0479835, + 0x0135F94, 0x026EE8C, 0x041DD81, 0x04C0418, 0x04C0418, 0x083BB03, + 0x09BBA32, 0x08F1219, 0x074E5FB, 0x03D1D45, 0x03A72FD, 0x023C486, + 0x03EB2B9, 0x05DC28A, 0x0BB8514, 0x0FACAE4, 0x0CAE638, 0x08FAA04, + 0x032B98E, 0x04DF15A, 0x09BE2B4, 0x05443EE, +}; + +static const int32_t qmat33[MAT_SIZE] = { + 0x0040000, 0x031EEF6, 0x018F77B, 0x031F9DD, 0x024CB50, 0x031F9DD, + 0x042249C, 0x032F83C, 0x065F078, 0x042249C, 0x03A8000, 0x05BBE34, + 0x063DDA2, 0x02DDF1A, 0x03A8000, 0x02DF691, 0x0289228, 0x05D5567, + 0x05D5567, 0x051244F, 0x02DF691, 0x066493B, 0x05D2D54, 0x0759736, + 0x07C7107, 0x0759736, 0x02E96AA, 0x033249E, 0x01B5065, 0x024502E, + 0x05EB33D, 0x06C797A, 0x06C797A, 0x05EB33D, 0x09140B9, 0x06D4193, + 0x1396AF0, 0x1218F6B, 0x0AE9CFD, 0x0BD0000, 0x0AE9CFD, 0x090C7B6, + 0x0272D5E, 0x04DDD19, 0x0852991, 0x098082F, 0x098082F, 0x10A5322, + 0x1377463, 0x23F33DD, 0x1D12876, 0x0F5D8A9, 0x0E8943B, 0x08FCCF7, + 0x07E045D, 0x0BC7A00, 0x178F401, 0x1F81173, 0x197BFE2, 0x120A572, + 0x065EFF9, 0x09BE2B4, 0x137C568, 0x0A887DD, +}; + +static const int32_t qmat34[MAT_SIZE] = { + 0x0040000, 0x0377B4A, 0x01BBDA5, 0x0378768, 0x028E1E8, 0x0378768, + 0x034EA16, 0x028C697, 0x0518D2D, 0x034EA16, 0x02D0000, 0x04964F6, + 0x051166B, 0x024B27B, 0x02D0000, 0x025520D, 0x020F134, 0x048FA15, + 0x048FA15, 0x041E268, 0x025520D, 0x071A6B4, 0x06787B3, 0x082A803, + 0x08A44B2, 0x082A803, 0x033C3D9, 0x038D35A, 0x01E5954, 0x0285917, + 0x06938EF, 0x07886FA, 0x07886FA, 0x06938EF, 0x0A1645B, 0x079654E, + 0x0AC3522, 0x09F195A, 0x06101E2, 0x0690000, 0x06101E2, 0x04F8CAD, + 0x01586A4, 0x02B41F1, 0x0492F02, 0x0547653, 0x0547653, 0x0925E03, + 0x0AD07C5, 0x09EF7AA, 0x081E317, 0x043E7A2, 0x040F18B, 0x027BDEB, + 0x045AA23, 0x0682D7D, 0x0D05AFA, 0x116A88B, 0x0E17194, 0x09FA076, + 0x0385C65, 0x0569A64, 0x0AD34C8, 0x05DA0D0, +}; + +static const int32_t qmat35[MAT_SIZE] = { + 0x0040000, 0x0377B4A, 0x01BBDA5, 0x0378768, 0x028E1E8, 0x0378768, + 0x0497E02, 0x038A20A, 0x0714414, 0x0497E02, 0x0410000, 0x065EFC8, + 0x06EF642, 0x032F7E4, 0x0410000, 0x03311F7, 0x02D142C, 0x067B439, + 0x067B439, 0x05A2858, 0x03311F7, 0x071A6B4, 0x06787B3, 0x082A803, + 0x08A44B2, 0x082A803, 0x033C3D9, 0x038D35A, 0x01E5954, 0x0285917, + 0x06938EF, 0x07886FA, 0x07886FA, 0x06938EF, 0x0A1645B, 0x079654E, + 0x15C3DEF, 0x141BBCC, 0x0C203C3, 0x0D20000, 0x0C203C3, 0x0A0DDE6, + 0x02B87BE, 0x05683E3, 0x093F54C, 0x0A8ECA7, 0x0A8ECA7, 0x127EA97, + 0x15A0F8B, 0x27F1D2F, 0x204D79F, 0x111299F, 0x1026BD0, 0x09FC74C, + 0x08C04D9, 0x0D16B1D, 0x1A2D63A, 0x2301364, 0x1C50E18, 0x140B7D4, + 0x0714386, 0x0AD34C8, 0x15A6990, 0x0BB41A0, +}; + +static const int32_t qmat36[MAT_SIZE] = { + 0x0040000, 0x03D079E, 0x01E83CF, 0x03D14F2, 0x02CF87F, 0x03D14F2, + 0x03A34B2, 0x02CDA72, 0x059B4E5, 0x03A34B2, 0x0318000, 0x050BBDC, + 0x0593243, 0x0285DEE, 0x0318000, 0x0290D75, 0x0243C86, 0x050464B, + 0x050464B, 0x048790C, 0x0290D75, 0x07D042C, 0x071E211, 0x08FB8D0, + 0x098185E, 0x08FB8D0, 0x038F109, 0x03E8216, 0x0216242, 0x02C6200, + 0x073BEA0, 0x0849479, 0x0849479, 0x073BEA0, 0x0B187FE, 0x0858909, + 0x0BD6DA5, 0x0AF0249, 0x06AB545, 0x0738000, 0x06AB545, 0x0578125, + 0x017ADB5, 0x02F9556, 0x0508082, 0x05CE88F, 0x05CE88F, 0x0A10104, + 0x0BE5559, 0x0AEDD3B, 0x08EE032, 0x04AB1FF, 0x0477019, 0x02BB74F, + 0x04CA18D, 0x0729870, 0x0E530E0, 0x1328633, 0x0F7FCEF, 0x0AF96E8, + 0x03DFF3C, 0x05F436E, 0x0BE86DC, 0x066FDB2, +}; + +static const int32_t qmat37[MAT_SIZE] = { + 0x0040000, 0x03D079E, 0x01E83CF, 0x03D14F2, 0x02CF87F, 0x03D14F2, + 0x050D769, 0x03E4BD8, 0x07C97B0, 0x050D769, 0x0478000, 0x070215C, + 0x07A0EE2, 0x03810AE, 0x0478000, 0x0382D5C, 0x0319630, 0x072130C, + 0x072130C, 0x0632C61, 0x0382D5C, 0x07D042C, 0x071E211, 0x08FB8D0, + 0x098185E, 0x08FB8D0, 0x038F109, 0x03E8216, 0x0216242, 0x02C6200, + 0x073BEA0, 0x0849479, 0x0849479, 0x073BEA0, 0x0B187FE, 0x0858909, + 0x17F10ED, 0x161E82D, 0x0D56A8A, 0x0E70000, 0x0D56A8A, 0x0B0F417, + 0x02FE21E, 0x05F2AAD, 0x0A2C106, 0x0B9D11E, 0x0B9D11E, 0x145820D, + 0x17CAAB2, 0x2BF0680, 0x23886C9, 0x12C7A95, 0x11C4364, 0x0AFC1A0, + 0x09A0555, 0x0E65C39, 0x1CCB873, 0x2681554, 0x1F25C4D, 0x160CA36, + 0x07C9713, 0x0BE86DC, 0x17D0DB8, 0x0CDFB63, +}; + +static const int32_t qmat38[MAT_SIZE] = { + 0x0040000, 0x04293F2, 0x02149F9, 0x042A27C, 0x0310F16, 0x042A27C, + 0x03F7F4E, 0x030EE4E, 0x061DC9D, 0x03F7F4E, 0x0360000, 0x05812C1, + 0x0614E1A, 0x02C0961, 0x0360000, 0x02CC8DC, 0x02787D8, 0x0579280, + 0x0579280, 0x04F0FAF, 0x02CC8DC, 0x08861A5, 0x07C3C70, 0x09CC99D, + 0x0A5EC09, 0x09CC99D, 0x03E1E38, 0x04430D2, 0x0246B31, 0x0306AE8, + 0x07E4452, 0x090A1F9, 0x090A1F9, 0x07E4452, 0x0C1ABA1, 0x091ACC4, + 0x0CEA628, 0x0BEEB39, 0x07468A8, 0x07E0000, 0x07468A8, 0x05F759C, + 0x019D4C5, 0x033E8BB, 0x057D202, 0x0655ACA, 0x0655ACA, 0x0AFA404, + 0x0CFA2ED, 0x0BEC2CC, 0x09BDD4E, 0x0517C5D, 0x04DEEA7, 0x02FB0B3, + 0x05398F7, 0x07D0363, 0x0FA06C5, 0x14E63DA, 0x10E884B, 0x0BF8D5B, + 0x043A213, 0x067EC78, 0x0CFD8F0, 0x0705A93, +}; + +static const int32_t qmat39[MAT_SIZE] = { + 0x0040000, 0x04293F2, 0x02149F9, 0x042A27C, 0x0310F16, 0x042A27C, + 0x05830D0, 0x043F5A6, 0x087EB4B, 0x05830D0, 0x04E0000, 0x07A52F0, + 0x0852782, 0x03D2978, 0x04E0000, 0x03D48C2, 0x0361835, 0x07C71DE, + 0x07C71DE, 0x06C3069, 0x03D48C2, 0x08861A5, 0x07C3C70, 0x09CC99D, + 0x0A5EC09, 0x09CC99D, 0x03E1E38, 0x04430D2, 0x0246B31, 0x0306AE8, + 0x07E4452, 0x090A1F9, 0x090A1F9, 0x07E4452, 0x0C1ABA1, 0x091ACC4, + 0x1A1E3EB, 0x182148F, 0x0E8D151, 0x0FC0000, 0x0E8D151, 0x0C10A47, + 0x0343C7D, 0x067D176, 0x0B18CC1, 0x0CAB595, 0x0CAB595, 0x1631982, + 0x19F45DA, 0x2FEEFD2, 0x26C35F2, 0x147CB8C, 0x1361AF9, 0x0BFBBF4, + 0x0A805D1, 0x0FB4D56, 0x1F69AAC, 0x2A01744, 0x21FAA83, 0x180DC98, + 0x087EAA1, 0x0CFD8F0, 0x19FB1E0, 0x0E0B527, +}; + +static const int32_t qmat3A[MAT_SIZE] = { + 0x0040000, 0x0482046, 0x0241023, 0x0483007, 0x03525AD, 0x0483007, + 0x044C9EA, 0x035022A, 0x06A0454, 0x044C9EA, 0x03A8000, 0x05F69A7, + 0x06969F2, 0x02FB4D3, 0x03A8000, 0x0308444, 0x02AD32A, 0x05EDEB5, + 0x05EDEB5, 0x055A653, 0x0308444, 0x093BF1D, 0x08696CF, 0x0A9DA6A, + 0x0B3BFB4, 0x0A9DA6A, 0x0434B67, 0x049DF8E, 0x0277420, 0x03473D1, + 0x088CA03, 0x09CAF78, 0x09CAF78, 0x088CA03, 0x0D1CF44, 0x09DD07F, + 0x0DFDEAC, 0x0CED428, 0x07E1C0C, 0x0888000, 0x07E1C0C, 0x0676A14, + 0x01BFBD5, 0x0383C20, 0x05F2382, 0x06DCD06, 0x06DCD06, 0x0BE4704, + 0x0E0F081, 0x0CEA85D, 0x0A8DA6A, 0x05846BA, 0x0546D35, 0x033AA17, + 0x05A9060, 0x0876E56, 0x10EDCAB, 0x16A4182, 0x12513A7, 0x0CF83CD, + 0x04944EA, 0x0709582, 0x0E12B04, 0x079B775, +}; + +static const int32_t qmat3B[MAT_SIZE] = { + 0x0040000, 0x0482046, 0x0241023, 0x0483007, 0x03525AD, 0x0483007, + 0x05F8A36, 0x0499F73, 0x0933EE7, 0x05F8A36, 0x0548000, 0x0848484, + 0x0904022, 0x0424242, 0x0548000, 0x0426427, 0x03A9A39, 0x086D0B1, + 0x086D0B1, 0x0753472, 0x0426427, 0x093BF1D, 0x08696CF, 0x0A9DA6A, + 0x0B3BFB4, 0x0A9DA6A, 0x0434B67, 0x049DF8E, 0x0277420, 0x03473D1, + 0x088CA03, 0x09CAF78, 0x09CAF78, 0x088CA03, 0x0D1CF44, 0x09DD07F, + 0x1C4B6EA, 0x1A240F0, 0x0FC3818, 0x1110000, 0x0FC3818, 0x0D12078, + 0x03896DD, 0x0707840, 0x0C0587C, 0x0DB9A0C, 0x0DB9A0C, 0x180B0F8, + 0x1C1E101, 0x33ED923, 0x29FE51C, 0x1631C82, 0x14FF28E, 0x0CFB649, + 0x0B6064D, 0x1103E72, 0x2207CE5, 0x2D81935, 0x24CF8B9, 0x1A0EEFA, + 0x0933E2E, 0x0E12B04, 0x1C25608, 0x0F36EEA, +}; + +static const int32_t qmat3C[MAT_SIZE] = { + 0x0040000, 0x04DAC9A, 0x026D64D, 0x04DBD91, 0x0393C44, 0x04DBD91, + 0x04A1486, 0x0391606, 0x0722C0C, 0x04A1486, 0x03F0000, 0x066C08C, + 0x07185C9, 0x0336046, 0x03F0000, 0x0343FAC, 0x02E1E7C, 0x0662AEB, + 0x0662AEB, 0x05C3CF7, 0x0343FAC, 0x09F1C95, 0x090F12D, 0x0B6EB37, + 0x0C19360, 0x0B6EB37, 0x0487897, 0x04F8E4B, 0x02A7D0F, 0x0387CBA, + 0x0934FB5, 0x0A8BCF7, 0x0A8BCF7, 0x0934FB5, 0x0E1F2E6, 0x0A9F43A, + 0x0F1172F, 0x0DEBD17, 0x087CF6F, 0x0930000, 0x087CF6F, 0x06F5E8C, + 0x01E22E6, 0x03C8F85, 0x0667502, 0x0763F41, 0x0763F41, 0x0CCEA05, + 0x0F23E14, 0x0DE8DEE, 0x0B5D786, 0x05F1117, 0x05AEBC3, 0x037A37C, + 0x06187CA, 0x091D948, 0x123B291, 0x1861F29, 0x13B9F02, 0x0DF7A3F, + 0x04EE7C1, 0x0793E8C, 0x0F27D18, 0x0831457, +}; + +static const int32_t qmat3D[MAT_SIZE] = { + 0x0040000, 0x04DAC9A, 0x026D64D, 0x04DBD91, 0x0393C44, 0x04DBD91, + 0x066E39D, 0x04F4941, 0x09E9282, 0x066E39D, 0x05B0000, 0x08EB618, + 0x09B58C2, 0x0475B0C, 0x05B0000, 0x0477F8D, 0x03F1C3D, 0x0912F83, + 0x0912F83, 0x07E387B, 0x0477F8D, 0x09F1C95, 0x090F12D, 0x0B6EB37, + 0x0C19360, 0x0B6EB37, 0x0487897, 0x04F8E4B, 0x02A7D0F, 0x0387CBA, + 0x0934FB5, 0x0A8BCF7, 0x0A8BCF7, 0x0934FB5, 0x0E1F2E6, 0x0A9F43A, + 0x1E789E8, 0x1C26D51, 0x10F9EDE, 0x1260000, 0x10F9EDE, 0x0E136A9, + 0x03CF13D, 0x0791F0A, 0x0CF2437, 0x0EC7E83, 0x0EC7E83, 0x19E486D, + 0x1E47C29, 0x37EC275, 0x2D39446, 0x17E6D78, 0x169CA23, 0x0DFB09D, + 0x0C406C9, 0x1252F8F, 0x24A5F1E, 0x3101B25, 0x27A46EE, 0x1C1015C, + 0x09E91BC, 0x0F27D18, 0x1E4FA30, 0x10628AD, +}; + +static const int32_t qmat3E[MAT_SIZE] = { + 0x0040000, 0x058C543, 0x02C62A1, 0x058D8A6, 0x0416973, 0x058D8A6, + 0x054A9BD, 0x0413DBE, 0x0827B7B, 0x054A9BD, 0x0480000, 0x0756E57, + 0x081BD78, 0x03AB72B, 0x0480000, 0x03BB67B, 0x034B520, 0x074C355, + 0x074C355, 0x0696A3F, 0x03BB67B, 0x0B5D786, 0x0A5A5EB, 0x0D10CD2, + 0x0DD3AB7, 0x0D10CD2, 0x052D2F5, 0x05AEBC3, 0x0308EEC, 0x0408E8B, + 0x0A85B18, 0x0C0D7F6, 0x0C0D7F6, 0x0A85B18, 0x1023A2C, 0x0C23BB1, + 0x1138836, 0x0FE8EF6, 0x09B3636, 0x0A80000, 0x09B3636, 0x07F477B, + 0x0227107, 0x045364F, 0x0751803, 0x08723B8, 0x08723B8, 0x0EA3005, + 0x114D93C, 0x0FE5910, 0x0CFD1BE, 0x06CA5D1, 0x067E8DF, 0x03F9644, + 0x06F769E, 0x0A6AF2E, 0x14D5E5C, 0x1BDDA78, 0x168B5B9, 0x0FF6724, + 0x05A2D6E, 0x08A90A0, 0x1152140, 0x095CE1A, +}; + +static const int32_t qmat3F[MAT_SIZE] = { + 0x0040000, 0x058C543, 0x02C62A1, 0x058D8A6, 0x0416973, 0x058D8A6, + 0x075966A, 0x05A9CDD, 0x0B539BA, 0x075966A, 0x0680000, 0x0A31940, + 0x0B18A03, 0x0518CA0, 0x0680000, 0x051B658, 0x0482046, 0x0A5ED28, + 0x0A5ED28, 0x090408D, 0x051B658, 0x0B5D786, 0x0A5A5EB, 0x0D10CD2, + 0x0DD3AB7, 0x0D10CD2, 0x052D2F5, 0x05AEBC3, 0x0308EEC, 0x0408E8B, + 0x0A85B18, 0x0C0D7F6, 0x0C0D7F6, 0x0A85B18, 0x1023A2C, 0x0C23BB1, + 0x22D2FE4, 0x202C614, 0x1366C6C, 0x1500000, 0x1366C6C, 0x101630A, + 0x045A5FD, 0x08A6C9E, 0x0ECBBAC, 0x10E4771, 0x10E4771, 0x1D97758, + 0x229B278, 0x3FE9518, 0x33AF299, 0x1B50F65, 0x19D794C, 0x0FFA546, + 0x0E007C1, 0x14F11C8, 0x29E2390, 0x3801F06, 0x2D4E359, 0x2012620, + 0x0B538D6, 0x1152140, 0x22A4280, 0x12B9C33, +}; + +static const int32_t qmat40[MAT_SIZE] = { + 0x0040000, 0x063DDEB, 0x031EEF6, 0x063F3BB, 0x04996A1, 0x063F3BB, + 0x05F3EF5, 0x0496575, 0x092CAEB, 0x05F3EF5, 0x0510000, 0x0841C22, + 0x091F527, 0x0420E11, 0x0510000, 0x0432D4B, 0x03B4BC4, 0x0835BC0, + 0x0835BC0, 0x0769787, 0x0432D4B, 0x0CC9277, 0x0BA5AA8, 0x0EB2E6C, + 0x0F8E20D, 0x0EB2E6C, 0x05D2D54, 0x066493B, 0x036A0CA, 0x048A05C, + 0x0BD667B, 0x0D8F2F5, 0x0D8F2F5, 0x0BD667B, 0x1228171, 0x0DA8327, + 0x135F93D, 0x11E60D5, 0x0AE9CFD, 0x0BD0000, 0x0AE9CFD, 0x08F306A, + 0x026BF28, 0x04DDD19, 0x083BB03, 0x098082F, 0x098082F, 0x1077606, + 0x1377463, 0x11E2432, 0x0E9CBF6, 0x07A3A8B, 0x074E5FB, 0x047890D, + 0x07D6572, 0x0BB8514, 0x1770A28, 0x1F595C7, 0x195CC70, 0x11F5408, + 0x065731C, 0x09BE2B4, 0x137C568, 0x0A887DD, +}; + +static const int32_t qmat41[MAT_SIZE] = { + 0x0040000, 0x063DDEB, 0x031EEF6, 0x063F3BB, 0x04996A1, 0x063F3BB, + 0x0844938, 0x065F078, 0x0CBE0F1, 0x0844938, 0x0750000, 0x0B77C68, + 0x0C7BB43, 0x05BBE34, 0x0750000, 0x05BED23, 0x051244F, 0x0BAAACD, + 0x0BAAACD, 0x0A2489E, 0x05BED23, 0x0CC9277, 0x0BA5AA8, 0x0EB2E6C, + 0x0F8E20D, 0x0EB2E6C, 0x05D2D54, 0x066493B, 0x036A0CA, 0x048A05C, + 0x0BD667B, 0x0D8F2F5, 0x0D8F2F5, 0x0BD667B, 0x1228171, 0x0DA8327, + 0x272D5E1, 0x2431ED6, 0x15D39F9, 0x17A0000, 0x15D39F9, 0x1218F6B, + 0x04E5ABC, 0x09BBA32, 0x10A5322, 0x130105F, 0x130105F, 0x214A643, + 0x26EE8C7, 0x47E67BB, 0x3A250EC, 0x1EBB151, 0x1D12876, 0x11F99EF, + 0x0FC08BA, 0x178F401, 0x2F1E802, 0x3F022E7, 0x32F7FC4, 0x2414AE4, + 0x0CBDFF1, 0x137C568, 0x26F8AD0, 0x1510FBA, +}; + +static const int32_t qmat42[MAT_SIZE] = { + 0x0040000, 0x06EF693, 0x0377B4A, 0x06F0ECF, 0x051C3CF, 0x06F0ECF, + 0x069D42D, 0x0518D2D, 0x0A31A5A, 0x069D42D, 0x05A0000, 0x092C9ED, + 0x0A22CD6, 0x04964F6, 0x05A0000, 0x04AA41A, 0x041E268, 0x091F42B, + 0x091F42B, 0x083C4CF, 0x04AA41A, 0x0E34D68, 0x0CF0F65, 0x1055006, + 0x1148964, 0x1055006, 0x06787B3, 0x071A6B4, 0x03CB2A7, 0x050B22E, + 0x0D271DE, 0x0F10DF4, 0x0F10DF4, 0x0D271DE, 0x142C8B7, 0x0F2CA9D, + 0x1586A43, 0x13E32B4, 0x0C203C3, 0x0D20000, 0x0C203C3, 0x09F195A, + 0x02B0D48, 0x05683E3, 0x0925E03, 0x0A8ECA7, 0x0A8ECA7, 0x124BC06, + 0x15A0F8B, 0x13DEF54, 0x103C62D, 0x087CF45, 0x081E317, 0x04F7BD5, + 0x08B5446, 0x0D05AFA, 0x1A0B5F3, 0x22D5116, 0x1C2E328, 0x13F40EC, + 0x070B8CA, 0x0AD34C8, 0x15A6990, 0x0BB41A0, +}; + +static const int32_t qmat43[MAT_SIZE] = { + 0x0040000, 0x06EF693, 0x0377B4A, 0x06F0ECF, 0x051C3CF, 0x06F0ECF, + 0x092FC05, 0x0714414, 0x0E28828, 0x092FC05, 0x0820000, 0x0CBDF90, + 0x0DDEC84, 0x065EFC8, 0x0820000, 0x06623EE, 0x05A2858, 0x0CF6872, + 0x0CF6872, 0x0B450B0, 0x06623EE, 0x0E34D68, 0x0CF0F65, 0x1055006, + 0x1148964, 0x1055006, 0x06787B3, 0x071A6B4, 0x03CB2A7, 0x050B22E, + 0x0D271DE, 0x0F10DF4, 0x0F10DF4, 0x0D271DE, 0x142C8B7, 0x0F2CA9D, + 0x2B87BDD, 0x2837799, 0x1840787, 0x1A40000, 0x1840787, 0x141BBCC, + 0x0570F7C, 0x0AD07C5, 0x127EA97, 0x151D94D, 0x151D94D, 0x24FD52E, + 0x2B41F16, 0x4FE3A5E, 0x409AF3F, 0x222533E, 0x204D79F, 0x13F8E97, + 0x11809B2, 0x1A2D63A, 0x345AC74, 0x46026C7, 0x38A1C30, 0x2816FA7, + 0x0E2870C, 0x15A6990, 0x2B4D320, 0x1768340, +}; + +static const int32_t qmat44[MAT_SIZE] = { + 0x0040000, 0x07A0F3C, 0x03D079E, 0x07A29E4, 0x059F0FE, 0x07A29E4, + 0x0746964, 0x059B4E5, 0x0B369CA, 0x0746964, 0x0630000, 0x0A177B8, + 0x0B26485, 0x050BBDC, 0x0630000, 0x0521AE9, 0x048790C, 0x0A08C95, + 0x0A08C95, 0x090F217, 0x0521AE9, 0x0FA0858, 0x0E3C423, 0x11F71A0, + 0x13030BB, 0x11F71A0, 0x071E211, 0x07D042C, 0x042C485, 0x058C3FF, + 0x0E77D40, 0x10928F2, 0x10928F2, 0x0E77D40, 0x1630FFC, 0x10B1213, + 0x17ADB4A, 0x15E0492, 0x0D56A8A, 0x0E70000, 0x0D56A8A, 0x0AF0249, + 0x02F5B69, 0x05F2AAD, 0x0A10104, 0x0B9D11E, 0x0B9D11E, 0x1420207, + 0x17CAAB2, 0x15DBA76, 0x11DC065, 0x09563FF, 0x08EE032, 0x0576E9E, + 0x0994319, 0x0E530E0, 0x1CA61BF, 0x2650C65, 0x1EFF9DF, 0x15F2DD1, + 0x07BFE78, 0x0BE86DC, 0x17D0DB8, 0x0CDFB63, +}; + +static const int32_t qmat45[MAT_SIZE] = { + 0x0040000, 0x07A0F3C, 0x03D079E, 0x07A29E4, 0x059F0FE, 0x07A29E4, + 0x0A1AED2, 0x07C97B0, 0x0F92F5F, 0x0A1AED2, 0x08F0000, 0x0E042B8, + 0x0F41DC4, 0x070215C, 0x08F0000, 0x0705AB9, 0x0632C61, 0x0E42617, + 0x0E42617, 0x0C658C1, 0x0705AB9, 0x0FA0858, 0x0E3C423, 0x11F71A0, + 0x13030BB, 0x11F71A0, 0x071E211, 0x07D042C, 0x042C485, 0x058C3FF, + 0x0E77D40, 0x10928F2, 0x10928F2, 0x0E77D40, 0x1630FFC, 0x10B1213, + 0x2FE21DA, 0x2C3D05B, 0x1AAD514, 0x1CE0000, 0x1AAD514, 0x161E82D, + 0x05FC43B, 0x0BE5559, 0x145820D, 0x173A23B, 0x173A23B, 0x28B0419, + 0x2F95565, 0x57E0D01, 0x4710D92, 0x258F52A, 0x23886C9, 0x15F8340, + 0x1340AAA, 0x1CCB873, 0x39970E6, 0x4D02AA8, 0x3E4B89B, 0x2C1946B, + 0x0F92E27, 0x17D0DB8, 0x2FA1B6F, 0x19BF6C7, +}; + +static const int32_t qmat46[MAT_SIZE] = { + 0x0040000, 0x08527E4, 0x04293F2, 0x08544F9, 0x0621E2C, 0x08544F9, + 0x07EFE9C, 0x061DC9D, 0x0C3B939, 0x07EFE9C, 0x06C0000, 0x0B02582, + 0x0C29C34, 0x05812C1, 0x06C0000, 0x05991B9, 0x04F0FAF, 0x0AF2500, + 0x0AF2500, 0x09E1F5F, 0x05991B9, 0x110C349, 0x0F878E0, 0x139933B, + 0x14BD812, 0x139933B, 0x07C3C70, 0x08861A5, 0x048D662, 0x060D5D0, + 0x0FC88A3, 0x12143F1, 0x12143F1, 0x0FC88A3, 0x1835742, 0x1235989, + 0x19D4C51, 0x17DD671, 0x0E8D151, 0x0FC0000, 0x0E8D151, 0x0BEEB39, + 0x033A98A, 0x067D176, 0x0AFA404, 0x0CAB595, 0x0CAB595, 0x15F4808, + 0x19F45DA, 0x17D8598, 0x137BA9D, 0x0A2F8B9, 0x09BDD4E, 0x05F6166, + 0x0A731ED, 0x0FA06C5, 0x1F40D8B, 0x29CC7B4, 0x21D1096, 0x17F1AB5, + 0x0874425, 0x0CFD8F0, 0x19FB1E0, 0x0E0B527, +}; + +static const int32_t qmat47[MAT_SIZE] = { + 0x0040000, 0x08527E4, 0x04293F2, 0x08544F9, 0x0621E2C, 0x08544F9, + 0x0B061A0, 0x087EB4B, 0x10FD696, 0x0B061A0, 0x09C0000, 0x0F4A5E0, + 0x10A4F04, 0x07A52F0, 0x09C0000, 0x07A9184, 0x06C3069, 0x0F8E3BC, + 0x0F8E3BC, 0x0D860D3, 0x07A9184, 0x110C349, 0x0F878E0, 0x139933B, + 0x14BD812, 0x139933B, 0x07C3C70, 0x08861A5, 0x048D662, 0x060D5D0, + 0x0FC88A3, 0x12143F1, 0x12143F1, 0x0FC88A3, 0x1835742, 0x1235989, + 0x343C7D6, 0x304291D, 0x1D1A2A2, 0x1F80000, 0x1D1A2A2, 0x182148F, + 0x06878FB, 0x0CFA2ED, 0x1631982, 0x1956B29, 0x1956B29, 0x2C63305, + 0x33E8BB4, 0x5FDDFA4, 0x4D86BE5, 0x28F9717, 0x26C35F2, 0x17F77E9, + 0x1500BA2, 0x1F69AAC, 0x3ED3558, 0x5402E89, 0x43F5506, 0x301B92F, + 0x10FD541, 0x19FB1E0, 0x33F63BF, 0x1C16A4D, +}; + +static const int32_t qmat48[MAT_SIZE] = { + 0x0040000, 0x090408D, 0x0482046, 0x090600E, 0x06A4B5A, 0x090600E, + 0x08993D3, 0x06A0454, 0x0D408A9, 0x08993D3, 0x0750000, 0x0BED34D, + 0x0D2D3E3, 0x05F69A7, 0x0750000, 0x0610888, 0x055A653, 0x0BDBD6A, + 0x0BDBD6A, 0x0AB4CA7, 0x0610888, 0x1277E3A, 0x10D2D9D, 0x153B4D5, + 0x1677F69, 0x153B4D5, 0x08696CF, 0x093BF1D, 0x04EE840, 0x068E7A2, + 0x1119406, 0x1395EF0, 0x1395EF0, 0x1119406, 0x1A39E87, 0x13BA0FF, + 0x1BFBD57, 0x19DA850, 0x0FC3818, 0x1110000, 0x0FC3818, 0x0CED428, + 0x037F7AB, 0x0707840, 0x0BE4704, 0x0DB9A0C, 0x0DB9A0C, 0x17C8E08, + 0x1C1E101, 0x19D50BB, 0x151B4D4, 0x0B08D73, 0x0A8DA6A, 0x067542F, + 0x0B520C1, 0x10EDCAB, 0x21DB956, 0x2D48303, 0x24A274D, 0x19F079A, + 0x09289D3, 0x0E12B04, 0x1C25608, 0x0F36EEA, +}; + +static const int32_t qmat49[MAT_SIZE] = { + 0x0040000, 0x090408D, 0x0482046, 0x090600E, 0x06A4B5A, 0x090600E, + 0x0BF146D, 0x0933EE7, 0x1267DCE, 0x0BF146D, 0x0A90000, 0x1090908, + 0x1208045, 0x0848484, 0x0A90000, 0x084C84F, 0x0753472, 0x10DA161, + 0x10DA161, 0x0EA68E4, 0x084C84F, 0x1277E3A, 0x10D2D9D, 0x153B4D5, + 0x1677F69, 0x153B4D5, 0x08696CF, 0x093BF1D, 0x04EE840, 0x068E7A2, + 0x1119406, 0x1395EF0, 0x1395EF0, 0x1119406, 0x1A39E87, 0x13BA0FF, + 0x3896DD3, 0x34481E0, 0x1F8702F, 0x2220000, 0x1F8702F, 0x1A240F0, + 0x0712DBA, 0x0E0F081, 0x180B0F8, 0x1B73417, 0x1B73417, 0x30161F0, + 0x383C203, 0x67DB247, 0x53FCA38, 0x2C63904, 0x29FE51C, 0x19F6C92, + 0x16C0C9A, 0x2207CE5, 0x440F9CA, 0x5B0326A, 0x499F171, 0x341DDF3, + 0x1267C5C, 0x1C25608, 0x384AC0F, 0x1E6DDD4, +}; + +static const int32_t qmat4A[MAT_SIZE] = { + 0x0040000, 0x09B5935, 0x04DAC9A, 0x09B7B22, 0x0727888, 0x09B7B22, + 0x094290B, 0x0722C0C, 0x0E45818, 0x094290B, 0x07E0000, 0x0CD8118, + 0x0E30B92, 0x066C08C, 0x07E0000, 0x0687F58, 0x05C3CF7, 0x0CC55D5, + 0x0CC55D5, 0x0B879EF, 0x0687F58, 0x13E392B, 0x121E25B, 0x16DD66F, + 0x18326C0, 0x16DD66F, 0x090F12D, 0x09F1C95, 0x054FA1D, 0x070F973, + 0x1269F69, 0x15179EF, 0x15179EF, 0x1269F69, 0x1C3E5CD, 0x153E875, + 0x1E22E5E, 0x1BD7A2F, 0x10F9EDE, 0x1260000, 0x10F9EDE, 0x0DEBD17, + 0x03C45CC, 0x0791F0A, 0x0CCEA05, 0x0EC7E83, 0x0EC7E83, 0x199D409, + 0x1E47C29, 0x1BD1BDD, 0x16BAF0C, 0x0BE222D, 0x0B5D786, 0x06F46F7, + 0x0C30F95, 0x123B291, 0x2476522, 0x30C3E52, 0x2773E04, 0x1BEF47E, + 0x09DCF81, 0x0F27D18, 0x1E4FA30, 0x10628AD, +}; + +static const int32_t qmat4B[MAT_SIZE] = { + 0x0040000, 0x09B5935, 0x04DAC9A, 0x09B7B22, 0x0727888, 0x09B7B22, + 0x0CDC73A, 0x09E9282, 0x13D2505, 0x0CDC73A, 0x0B60000, 0x11D6C30, + 0x136B185, 0x08EB618, 0x0B60000, 0x08EFF19, 0x07E387B, 0x1225F06, + 0x1225F06, 0x0FC70F6, 0x08EFF19, 0x13E392B, 0x121E25B, 0x16DD66F, + 0x18326C0, 0x16DD66F, 0x090F12D, 0x09F1C95, 0x054FA1D, 0x070F973, + 0x1269F69, 0x15179EF, 0x15179EF, 0x1269F69, 0x1C3E5CD, 0x153E875, + 0x3CF13D0, 0x384DAA2, 0x21F3DBD, 0x24C0000, 0x21F3DBD, 0x1C26D51, + 0x079E27A, 0x0F23E14, 0x19E486D, 0x1D8FD05, 0x1D8FD05, 0x33C90DB, + 0x3C8F852, 0x6FD84EA, 0x5A7288B, 0x2FCDAF0, 0x2D39446, 0x1BF613A, + 0x1880D93, 0x24A5F1E, 0x494BE3C, 0x620364A, 0x4F48DDC, 0x38202B7, + 0x13D2377, 0x1E4FA30, 0x3C9F45F, 0x20C515A, +}; + +static const int32_t qmat4C[MAT_SIZE] = { + 0x0040000, 0x1208119, 0x090408D, 0x120C01B, 0x0D496B4, 0x120C01B, + 0x11327A7, 0x0D408A9, 0x1A81151, 0x11327A7, 0x0EA0000, 0x17DA69B, + 0x1A5A7C7, 0x0BED34D, 0x0EA0000, 0x0C21110, 0x0AB4CA7, 0x17B7AD5, + 0x17B7AD5, 0x156994E, 0x0C21110, 0x24EFC74, 0x21A5B3B, 0x2A769A9, + 0x2CEFED2, 0x2A769A9, 0x10D2D9D, 0x1277E3A, 0x09DD07F, 0x0D1CF44, + 0x223280D, 0x272BDE0, 0x272BDE0, 0x223280D, 0x3473D0E, 0x27741FE, + 0x37F7AAF, 0x33B50A0, 0x1F8702F, 0x2220000, 0x1F8702F, 0x19DA850, + 0x06FEF56, 0x0E0F081, 0x17C8E08, 0x1B73417, 0x1B73417, 0x2F91C11, + 0x383C203, 0x33AA175, 0x2A369A9, 0x1611AE6, 0x151B4D4, 0x0CEA85D, + 0x16A4182, 0x21DB956, 0x43B72AC, 0x5A90607, 0x4944E9A, 0x33E0F34, + 0x12513A7, 0x1C25608, 0x384AC0F, 0x1E6DDD4, +}; + +static const int32_t qmat4D[MAT_SIZE] = { + 0x0040000, 0x1208119, 0x090408D, 0x120C01B, 0x0D496B4, 0x120C01B, + 0x17E28DA, 0x1267DCE, 0x24CFB9B, 0x17E28DA, 0x1520000, 0x2121210, + 0x2410089, 0x1090908, 0x1520000, 0x109909D, 0x0EA68E4, 0x21B42C3, + 0x21B42C3, 0x1D4D1C9, 0x109909D, 0x24EFC74, 0x21A5B3B, 0x2A769A9, + 0x2CEFED2, 0x2A769A9, 0x10D2D9D, 0x1277E3A, 0x09DD07F, 0x0D1CF44, + 0x223280D, 0x272BDE0, 0x272BDE0, 0x223280D, 0x3473D0E, 0x27741FE, + 0x712DBA6, 0x68903C0, 0x3F0E05F, 0x4440000, 0x3F0E05F, 0x34481E0, + 0x0E25B75, 0x1C1E101, 0x30161F0, 0x36E682F, 0x36E682F, 0x602C3DF, + 0x7078406, 0xCFB648E, 0xA7F9470, 0x58C7207, 0x53FCA38, 0x33ED923, + 0x2D81935, 0x440F9CA, 0x881F394, 0xB6064D3, 0x933E2E2, 0x683BBE7, + 0x24CF8B9, 0x384AC0F, 0x709581F, 0x3CDBBA7, +}; + +const int32_t *const ff_hq_quants[NUM_HQ_QUANTS][2][4] = { + { { qmat00, qmat02, qmat06, qmat0E }, { qmat01, qmat03, qmat07, qmat0F } }, + { { qmat02, qmat06, qmat0E, qmat16 }, { qmat03, qmat07, qmat0F, qmat17 } }, + { { qmat04, qmat0A, qmat12, qmat1E }, { qmat05, qmat0B, qmat13, qmat1F } }, + { { qmat06, qmat0E, qmat16, qmat22 }, { qmat07, qmat0F, qmat17, qmat23 } }, + { { qmat08, qmat10, qmat1A, qmat26 }, { qmat09, qmat11, qmat1B, qmat27 } }, + { { qmat0A, qmat12, qmat1E, qmat2A }, { qmat0B, qmat13, qmat1F, qmat2B } }, + { { qmat0C, qmat14, qmat20, qmat2E }, { qmat0D, qmat15, qmat21, qmat2F } }, + { { qmat0E, qmat16, qmat22, qmat30 }, { qmat0F, qmat17, qmat23, qmat31 } }, + { { qmat16, qmat22, qmat30, qmat3E }, { qmat17, qmat23, qmat31, qmat3F } }, + { { qmat18, qmat24, qmat32, qmat40 }, { qmat19, qmat25, qmat33, qmat41 } }, + { { qmat1A, qmat26, qmat34, qmat42 }, { qmat1B, qmat27, qmat35, qmat43 } }, + { { qmat1C, qmat28, qmat36, qmat44 }, { qmat1D, qmat29, qmat37, qmat45 } }, + { { qmat1E, qmat2A, qmat38, qmat46 }, { qmat1F, qmat2B, qmat39, qmat47 } }, + { { qmat20, qmat2E, qmat3C, qmat4A }, { qmat21, qmat2F, qmat3D, qmat4B } }, + { { qmat2C, qmat3A, qmat48, qmat4C }, { qmat2D, qmat3B, qmat49, qmat4D } }, + { { qmat3A, qmat48, qmat4C, qmat4C }, { qmat3B, qmat49, qmat4D, qmat4D } }, +}; + +const uint8_t ff_hq_ac_bits[NUM_HQ_AC_ENTRIES] = { + 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 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, 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, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +}; + +const uint16_t ff_hq_ac_codes[NUM_HQ_AC_ENTRIES] = { + 0x0000, 0x0001, 0x0004, 0x0005, 0x0006, 0x000E, 0x000F, 0x0010, + 0x0011, 0x0012, 0x0013, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, + 0x002D, 0x002E, 0x002F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, + 0x0065, 0x0066, 0x0067, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, + 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, + 0x00DD, 0x00DE, 0x00DF, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, + 0x01C5, 0x01C6, 0x01C7, 0x01C8, 0x01C9, 0x01CA, 0x01CB, 0x01CC, + 0x01CD, 0x01CE, 0x01CF, 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, + 0x01D5, 0x01D6, 0x01D7, 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, + 0x01DD, 0x01DE, 0x01DF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, + 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, + 0x03CD, 0x03CE, 0x03CF, 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, + 0x03D5, 0x03D6, 0x03D7, 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, + 0x03DD, 0x03DE, 0x03DF, 0x07C0, 0x07C1, 0x07C2, 0x07C3, 0x07C4, + 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC, + 0x07CD, 0x07CE, 0x07CF, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, 0x0FA4, + 0x0FA5, 0x0FA6, 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, + 0x0FAD, 0x0FAE, 0x0FAF, 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, + 0x1F65, 0x1F66, 0x1F67, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, + 0x1F6D, 0x1F6E, 0x1F6F, 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, + 0x1F75, 0x1F76, 0x1F77, 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, + 0x1F7D, 0x1F7E, 0x1F7F, 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, 0xFE00, 0xFE02, 0xFE03, 0xFE04, 0xFE05, + 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, + 0xFE0E, 0xFE0F, 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, + 0xFE16, 0xFE17, 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, + 0xFE1E, 0xFE1F, 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, + 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, + 0xFE2E, 0xFE2F, 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, + 0xFE36, 0xFE37, 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, + 0xFE3E, 0xFE3F, 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, + 0xFE46, 0xFE47, 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, + 0xFE4E, 0xFE4F, 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, + 0xFE56, 0xFE57, 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, + 0xFE5E, 0xFE5F, 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, + 0xFE66, 0xFE67, 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, + 0xFE6E, 0xFE6F, 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, + 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, + 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, + 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, + 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, + 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, + 0xFE9E, 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, + 0xFEA6, 0xFEA7, 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, + 0xFEAE, 0xFEAF, 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, + 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, + 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, + 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, + 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, + 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, + 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, + 0xFEE6, 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, + 0xFEEE, 0xFEEF, 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, + 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, + 0xFEFE, 0xFEFF, 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, + 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, + 0xFF0E, 0xFF0F, 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, + 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, + 0xFF1E, 0xFF1F, 0xFF20, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, + 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, + 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, + 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, + 0xFF3E, 0xFF3F, 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, + 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, + 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, + 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, + 0xFF5E, 0xFF5F, 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, + 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, + 0xFF6E, 0xFF6F, 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, + 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, + 0xFF7E, 0xFF7F, 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, + 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, + 0xFF8E, 0xFF8F, 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, + 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, + 0xFF9E, 0xFF9F, 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, + 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, + 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, + 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, + 0xFFBE, 0xFFBF, 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, + 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, + 0xFFCE, 0xFFCF, 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, + 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, + 0xFFDE, 0xFFDF, 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, + 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, + 0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, + 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, + 0xFFFE, 0xFFFF, +}; + +const uint8_t ff_hq_ac_skips[NUM_HQ_AC_ENTRIES] = { + 0, 0, 0, 0, 64, 1, 1, 0, 0, 0, 0, 2, 2, 1, 1, 0, + 0, 0, 0, 3, 3, 4, 4, 0, 0, 0, 0, 5, 5, 6, 6, 2, + 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 7, 7, 8, 8, 9, + 9, 10, 10, 3, 3, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 12, 12, 13, + 13, 14, 14, 5, 5, 6, 6, 3, 3, 4, 4, 2, 2, 2, 2, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 3, 3, 3, + 3, 2, 2, 1, 1, 1, 1, 1, 1, 0, 1, 6, 6, 4, 4, 3, + 3, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 7, 7, 8, 8, 9, + 9, 10, 10, 7, 7, 8, 8, 4, 4, 3, 3, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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 int16_t ff_hq_ac_syms[NUM_HQ_AC_ENTRIES] = { + 1, -1, 2, -2, 0, 1, -1, 3, + -3, 4, -4, 1, -1, 2, -2, 5, + -5, 6, -6, 1, -1, 1, -1, 7, + -7, 8, -8, 1, -1, 1, -1, 2, + -2, 3, -3, 4, -4, 9, -9, 10, + -10, 11, -11, 1, -1, 1, -1, 1, + -1, 1, -1, 2, -2, 2, -2, 3, + -3, 5, -5, 6, -6, 7, -7, 12, + -12, 13, -13, 14, -14, 15, -15, 16, + -16, 17, -17, 1, -1, 1, -1, 1, + -1, 1, -1, 2, -2, 2, -2, 3, + -3, 3, -3, 4, -4, 5, -5, 8, + -8, 18, -18, 19, -19, 20, -20, 21, + -21, 22, -22, 3, -3, 4, -4, 5, + -5, 6, -6, 9, -9, 10, -10, 11, + -11, 0, 0, 3, -3, 4, -4, 6, + -6, 12, -12, 13, -13, 14, -14, 0, + 0, 0, 0, 2, -2, 2, -2, 2, + -2, 2, -2, 3, -3, 3, -3, 5, + -5, 7, -7, 7, -7, 8, -8, 9, + -9, 10, -10, 11, -11, 15, -15, 16, + -16, 17, -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, -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, 32, -32, 33, -33, 34, -34, + 35, -35, 36, -36, 37, -37, 38, -38, + 39, -39, 40, -40, 41, -41, 42, -42, + 43, -43, 44, -44, 45, -45, 46, -46, + 47, -47, 48, -48, 49, -49, 50, -50, + 51, -51, 52, -52, 53, -53, 54, -54, + 55, -55, 56, -56, 57, -57, 58, -58, + 59, -59, 60, -60, 61, -61, 62, -62, + 63, -63, 64, -64, 65, -65, 66, -66, + 67, -67, 68, -68, 69, -69, 70, -70, + 71, -71, 72, -72, 73, -73, 74, -74, + 75, -75, 76, -76, 77, -77, 78, -78, + 79, -79, 80, -80, 81, -81, 82, -82, + 83, -83, 84, -84, 85, -85, 86, -86, + 87, -87, 88, -88, 89, -89, 90, -90, + 91, -91, 92, -92, 93, -93, 94, -94, + 95, -95, 96, -96, 97, -97, 98, -98, + 99, -99, 100, -100, 101, -101, 102, -102, + 103, -103, 104, -104, 105, -105, 106, -106, + 107, -107, 108, -108, 109, -109, 110, -110, + 111, -111, 112, -112, 113, -113, 114, -114, + 115, -115, 116, -116, 117, -117, 118, -118, + 119, -119, 120, -120, 121, -121, 122, -122, + 123, -123, 124, -124, 125, -125, 126, -126, + 127, -127, 128, -128, 129, -129, 130, -130, + 131, -131, 132, -132, 133, -133, 134, -134, + 135, -135, 136, -136, 137, -137, 138, -138, + 139, -139, 140, -140, 141, -141, 142, -142, + 143, -143, 144, -144, 145, -145, 146, -146, + 147, -147, 148, -148, 149, -149, 150, -150, + 151, -151, 152, -152, 153, -153, 154, -154, + 155, -155, 156, -156, 157, -157, 158, -158, + 159, -159, 160, -160, 161, -161, 162, -162, + 163, -163, 164, -164, 165, -165, 166, -166, + 167, -167, 168, -168, 169, -169, 170, -170, + 171, -171, 172, -172, 173, -173, 174, -174, + 175, -175, 176, -176, 177, -177, 178, -178, + 179, -179, 180, -180, 181, -181, 182, -182, + 183, -183, 184, -184, 185, -185, 186, -186, + 187, -187, 188, -188, 189, -189, 190, -190, + 191, -191, 192, -192, 193, -193, 194, -194, + 195, -195, 196, -196, 197, -197, 198, -198, + 199, -199, 200, -200, 201, -201, 202, -202, + 203, -203, 204, -204, 205, -205, 206, -206, + 207, -207, 208, -208, 209, -209, 210, -210, + 211, -211, 212, -212, 213, -213, 214, -214, + 215, -215, 216, -216, 217, -217, 218, -218, + 219, -219, 220, -220, 221, -221, 222, -222, + 223, -223, 224, -224, 225, -225, 226, -226, + 227, -227, 228, -228, 229, -229, 230, -230, + 231, -231, 232, -232, 233, -233, 234, -234, + 235, -235, 236, -236, 237, -237, 238, -238, + 239, -239, 240, -240, 241, -241, 242, -242, + 243, -243, 244, -244, 245, -245, 246, -246, + 247, -247, 248, -248, 249, -249, 250, -250, + 251, -251, 252, -252, 253, -253, 254, -254, + 255, -255, +}; + +/* tables section - one per supported profile */ +static const uint8_t hq_tab_01[] = { + 0, 0, 12, 3, 20, 0, 28, 3, 40, 0, 0, 10, 15, 6, 20, + 10, 35, 6, 40, 10, 7, 13, 15, 16, 23, 13, 35, 16, 39, 13, + 7, 23, 10, 19, 23, 23, 27, 20, 39, 23, 2, 26, 10, 29, 22, + 26, 27, 24, 42, 26, 1, 0, 11, 3, 21, 0, 27, 3, 41, 0, + 1, 10, 16, 6, 21, 10, 35, 7, 41, 10, 6, 13, 16, 16, 22, + 13, 35, 17, 38, 13, 6, 23, 9, 19, 22, 23, 28, 20, 38, 23, + 3, 26, 9, 29, 23, 26, 28, 24, 43, 26, 2, 0, 10, 3, 22, + 0, 27, 4, 42, 0, 2, 10, 17, 6, 22, 10, 34, 7, 42, 10, + 5, 13, 17, 16, 21, 13, 34, 17, 37, 13, 5, 23, 9, 20, 21, + 23, 29, 20, 37, 23, 4, 26, 9, 24, 24, 26, 29, 24, 44, 26, + 3, 0, 9, 3, 23, 0, 28, 4, 43, 0, 3, 10, 17, 7, 23, + 10, 33, 7, 43, 10, 4, 13, 17, 17, 20, 13, 33, 17, 36, 13, + 4, 23, 10, 20, 20, 23, 30, 20, 36, 23, 5, 26, 10, 24, 25, + 26, 30, 24, 44, 27, 4, 0, 9, 4, 24, 0, 29, 4, 44, 0, + 4, 10, 16, 7, 24, 10, 32, 7, 44, 10, 3, 13, 16, 17, 19, + 13, 32, 17, 36, 14, 3, 23, 11, 20, 19, 23, 31, 20, 36, 18, + 6, 26, 11, 24, 26, 26, 31, 24, 43, 27, 5, 0, 10, 4, 25, + 0, 30, 4, 44, 1, 5, 10, 15, 7, 25, 10, 31, 7, 44, 11, + 2, 13, 15, 17, 18, 13, 31, 17, 37, 14, 2, 23, 12, 20, 18, + 23, 32, 20, 37, 18, 7, 26, 12, 24, 26, 27, 32, 24, 42, 27, + 6, 0, 11, 4, 26, 0, 31, 4, 43, 1, 6, 10, 14, 7, 26, + 10, 30, 7, 43, 11, 1, 13, 14, 17, 18, 14, 30, 17, 38, 14, + 1, 23, 13, 20, 18, 18, 33, 20, 38, 18, 8, 26, 13, 24, 25, + 27, 33, 24, 41, 27, 7, 0, 12, 4, 26, 1, 32, 4, 42, 1, + 7, 10, 13, 7, 26, 11, 29, 7, 42, 11, 0, 13, 13, 17, 19, + 14, 29, 17, 39, 14, 0, 23, 14, 20, 19, 18, 34, 20, 39, 18, + 8, 27, 14, 24, 24, 27, 34, 24, 40, 27, 8, 0, 13, 4, 25, + 1, 33, 4, 41, 1, 8, 10, 12, 7, 25, 11, 28, 7, 41, 11, + 0, 14, 12, 17, 20, 14, 28, 17, 40, 14, 0, 18, 15, 20, 20, + 18, 35, 20, 40, 18, 7, 27, 15, 24, 23, 27, 35, 24, 39, 27, + 8, 1, 14, 4, 24, 1, 34, 4, 40, 1, 8, 11, 11, 7, 24, + 11, 27, 7, 40, 11, 1, 14, 11, 17, 21, 14, 27, 17, 41, 14, + 1, 18, 16, 20, 21, 18, 35, 21, 41, 18, 6, 27, 16, 24, 22, + 27, 35, 25, 38, 27, 7, 1, 15, 4, 23, 1, 35, 4, 39, 1, + 7, 11, 10, 7, 23, 11, 27, 8, 39, 11, 2, 14, 10, 17, 22, + 14, 27, 12, 42, 14, 2, 18, 17, 20, 22, 18, 34, 21, 42, 18, + 5, 27, 17, 24, 21, 27, 34, 25, 37, 27, 6, 1, 16, 4, 22, + 1, 35, 5, 38, 1, 6, 11, 9, 7, 22, 11, 28, 8, 38, 11, + 3, 14, 9, 17, 23, 14, 28, 12, 43, 14, 3, 18, 17, 21, 23, + 18, 33, 21, 43, 18, 4, 27, 17, 25, 20, 27, 33, 25, 36, 27, + 5, 1, 17, 4, 21, 1, 34, 5, 37, 1, 5, 11, 9, 8, 21, + 11, 29, 8, 37, 11, 4, 14, 9, 12, 24, 14, 29, 12, 44, 14, + 4, 18, 16, 21, 24, 18, 32, 21, 44, 18, 3, 27, 16, 25, 19, + 27, 32, 25, 36, 28, 4, 1, 17, 5, 20, 1, 33, 5, 36, 1, + 4, 11, 10, 8, 20, 11, 30, 8, 36, 11, 5, 14, 10, 12, 25, + 14, 30, 12, 44, 15, 5, 18, 15, 21, 25, 18, 31, 21, 44, 19, + 2, 27, 15, 25, 18, 27, 31, 25, 37, 28, 3, 1, 16, 5, 19, + 1, 32, 5, 36, 2, 3, 11, 11, 8, 19, 11, 31, 8, 36, 6, + 6, 14, 11, 12, 26, 14, 31, 12, 43, 15, 6, 18, 14, 21, 26, + 18, 30, 21, 43, 19, 1, 27, 14, 25, 18, 28, 30, 25, 38, 28, + 2, 1, 15, 5, 18, 1, 31, 5, 37, 2, 2, 11, 12, 8, 18, + 11, 32, 8, 37, 6, 7, 14, 12, 12, 26, 15, 32, 12, 42, 15, + 7, 18, 13, 21, 26, 19, 29, 21, 42, 19, 0, 27, 13, 25, 19, + 28, 29, 25, 39, 28, 1, 1, 14, 5, 18, 2, 30, 5, 38, 2, + 1, 11, 13, 8, 18, 6, 33, 8, 38, 6, 8, 14, 13, 12, 25, + 15, 33, 12, 41, 15, 8, 18, 12, 21, 25, 19, 28, 21, 41, 19, + 0, 28, 12, 25, 20, 28, 28, 25, 40, 28, 0, 1, 13, 5, 19, + 2, 29, 5, 39, 2, 0, 11, 14, 8, 19, 6, 34, 8, 39, 6, + 8, 15, 14, 12, 24, 15, 34, 12, 40, 15, 8, 19, 11, 21, 24, + 19, 27, 21, 40, 19, 1, 28, 11, 25, 21, 28, 27, 25, 41, 28, + 0, 2, 12, 5, 20, 2, 28, 5, 40, 2, 0, 6, 15, 8, 20, + 6, 35, 8, 40, 6, 7, 15, 15, 12, 23, 15, 35, 12, 39, 15, + 7, 19, 10, 21, 23, 19, 27, 22, 39, 19, 2, 28, 10, 25, 22, + 28, 27, 26, 42, 28, 1, 2, 11, 5, 21, 2, 27, 5, 41, 2, + 1, 6, 16, 8, 21, 6, 35, 9, 41, 6, 6, 15, 16, 12, 22, + 15, 35, 13, 38, 15, 6, 19, 9, 21, 22, 19, 28, 22, 38, 19, + 3, 28, 9, 25, 23, 28, 28, 26, 43, 28, 2, 2, 10, 5, 22, + 2, 27, 0, 42, 2, 2, 6, 17, 8, 22, 6, 34, 9, 42, 6, + 5, 15, 17, 12, 21, 15, 34, 13, 37, 15, 5, 19, 9, 22, 21, + 19, 29, 22, 37, 19, 4, 28, 9, 26, 24, 28, 29, 26, 44, 28, + 3, 2, 9, 5, 23, 2, 28, 0, 43, 2, 3, 6, 17, 9, 23, + 6, 33, 9, 43, 6, 4, 15, 17, 13, 20, 15, 33, 13, 36, 15, + 4, 19, 10, 22, 20, 19, 30, 22, 36, 19, 5, 28, 10, 26, 25, + 28, 30, 26, 44, 29, 4, 2, 9, 0, 24, 2, 29, 0, 44, 2, + 4, 6, 16, 9, 24, 6, 32, 9, 44, 6, 3, 15, 16, 13, 19, + 15, 32, 13, 36, 16, 3, 19, 11, 22, 19, 19, 31, 22, 36, 20, + 6, 28, 11, 26, 26, 28, 31, 26, 43, 29, 5, 2, 10, 0, 25, + 2, 30, 0, 44, 3, 5, 6, 15, 9, 25, 6, 31, 9, 44, 7, + 2, 15, 15, 13, 18, 15, 31, 13, 37, 16, 2, 19, 12, 22, 18, + 19, 32, 22, 37, 20, 7, 28, 12, 26, 26, 29, 32, 26, 42, 29, + 6, 2, 11, 0, 26, 2, 31, 0, 43, 3, 6, 6, 14, 9, 26, + 6, 30, 9, 43, 7, 1, 15, 14, 13, 18, 16, 30, 13, 38, 16, + 1, 19, 13, 22, 18, 20, 33, 22, 38, 20, 8, 28, 13, 26, 25, + 29, 33, 26, 41, 29, 7, 2, 12, 0, 26, 3, 32, 0, 42, 3, + 7, 6, 13, 9, 26, 7, 29, 9, 42, 7, 0, 15, 13, 13, 19, + 16, 29, 13, 39, 16, 0, 19, 14, 22, 19, 20, 34, 22, 39, 20, + 8, 29, 14, 26, 24, 29, 34, 26, 40, 29, 8, 2, 13, 0, 25, + 3, 33, 0, 41, 3, 8, 6, 12, 9, 25, 7, 28, 9, 41, 7, + 0, 16, 12, 13, 20, 16, 28, 13, 40, 16, 0, 20, 15, 22, 20, + 20, 35, 22, 40, 20, 7, 29, 15, 26, 23, 29, 35, 26, 39, 29, + 8, 3, 14, 0, 24, 3, 34, 0, 40, 3, 8, 7, 11, 9, 24, + 7, 27, 9, 40, 7, 1, 16, 11, 13, 21, 16, 27, 13, 41, 16, + 1, 20, 16, 22, 21, 20, 35, 23, 41, 20, 6, 29, 16, 26, 22, + 29, 35, 27, 38, 29, 7, 3, 15, 0, 23, 3, 35, 0, 39, 3, + 7, 7, 10, 9, 23, 7, 27, 10, 39, 7, 2, 16, 10, 13, 22, + 16, 27, 14, 42, 16, 2, 20, 17, 22, 22, 20, 34, 23, 42, 20, + 5, 29, 17, 26, 21, 29, 34, 27, 37, 29, 6, 3, 16, 0, 22, + 3, 35, 1, 38, 3, 6, 7, 9, 9, 22, 7, 28, 10, 38, 7, + 3, 16, 9, 13, 23, 16, 28, 14, 43, 16, 3, 20, 17, 23, 23, + 20, 33, 23, 43, 20, 4, 29, 17, 27, 20, 29, 33, 27, 36, 29, + 5, 3, 17, 0, 21, 3, 34, 1, 37, 3, 5, 7, 9, 10, 21, + 7, 29, 10, 37, 7, 4, 16, 9, 14, 24, 16, 29, 14, 44, 16, + 4, 20, 16, 23, 24, 20, 32, 23, 44, 20, 3, 29, 16, 27, 19, + 29, 32, 27, 36, 24, 4, 3, 17, 1, 20, 3, 33, 1, 36, 3, + 4, 7, 10, 10, 20, 7, 30, 10, 36, 7, 5, 16, 10, 14, 25, + 16, 30, 14, 44, 17, 5, 20, 15, 23, 25, 20, 31, 23, 44, 21, + 2, 29, 15, 27, 18, 29, 31, 27, 37, 24, 3, 3, 16, 1, 19, + 3, 32, 1, 36, 4, 3, 7, 11, 10, 19, 7, 31, 10, 36, 8, + 6, 16, 11, 14, 26, 16, 31, 14, 43, 17, 6, 20, 14, 23, 26, + 20, 30, 23, 43, 21, 1, 29, 14, 27, 18, 24, 30, 27, 38, 24, + 2, 3, 15, 1, 18, 3, 31, 1, 37, 4, 2, 7, 12, 10, 18, + 7, 32, 10, 37, 8, 7, 16, 12, 14, 26, 17, 32, 14, 42, 17, + 7, 20, 13, 23, 26, 21, 29, 23, 42, 21, 0, 29, 13, 27, 19, + 24, 29, 27, 39, 24, 1, 3, 14, 1, 18, 4, 30, 1, 38, 4, + 1, 7, 13, 10, 18, 8, 33, 10, 38, 8, 8, 16, 13, 14, 25, + 17, 33, 14, 41, 17, 8, 20, 12, 23, 25, 21, 28, 23, 41, 21, + 0, 24, 12, 27, 20, 24, 28, 27, 40, 24, 0, 3, 13, 1, 19, + 4, 29, 1, 39, 4, 0, 7, 14, 10, 19, 8, 34, 10, 39, 8, + 8, 17, 14, 14, 24, 17, 34, 14, 40, 17, 8, 21, 11, 23, 24, + 21, 27, 23, 40, 21, 1, 24, 11, 27, 21, 24, 27, 27, 41, 24, + 0, 4, 12, 1, 20, 4, 28, 1, 40, 4, 0, 8, 15, 10, 20, + 8, 35, 10, 40, 8, 7, 17, 15, 14, 23, 17, 35, 14, 39, 17, + 7, 21, 10, 23, 23, 21, 27, 18, 39, 21, 2, 24, 10, 27, 22, + 24, 27, 28, 42, 24, 1, 4, 11, 1, 21, 4, 27, 1, 41, 4, + 1, 8, 16, 10, 21, 8, 35, 11, 41, 8, 6, 17, 16, 14, 22, + 17, 35, 15, 38, 17, 6, 21, 9, 23, 22, 21, 28, 18, 38, 21, + 3, 24, 9, 27, 23, 24, 28, 28, 43, 24, 2, 4, 10, 1, 22, + 4, 27, 2, 42, 4, 2, 8, 17, 10, 22, 8, 34, 11, 42, 8, + 5, 17, 17, 14, 21, 17, 34, 15, 37, 17, 5, 21, 9, 18, 21, + 21, 29, 18, 37, 21, 4, 24, 9, 28, 24, 24, 29, 28, 44, 24, + 3, 4, 9, 1, 23, 4, 28, 2, 43, 4, 3, 8, 17, 11, 23, + 8, 33, 11, 43, 8, 4, 17, 17, 15, 20, 17, 33, 15, 36, 17, + 4, 21, 10, 18, 20, 21, 30, 18, 36, 21, 5, 24, 10, 28, 25, + 24, 30, 28, 44, 25, 4, 4, 9, 2, 24, 4, 29, 2, 44, 4, + 4, 8, 16, 11, 24, 8, 32, 11, 44, 8, 3, 17, 16, 15, 19, + 17, 32, 15, 36, 12, 3, 21, 11, 18, 19, 21, 31, 18, 36, 22, + 6, 24, 11, 28, 26, 24, 31, 28, 43, 25, 5, 4, 10, 2, 25, + 4, 30, 2, 44, 5, 5, 8, 15, 11, 25, 8, 31, 11, 44, 9, + 2, 17, 15, 15, 18, 17, 31, 15, 37, 12, 2, 21, 12, 18, 18, + 21, 32, 18, 37, 22, 7, 24, 12, 28, 26, 25, 32, 28, 42, 25, + 6, 4, 11, 2, 26, 4, 31, 2, 43, 5, 6, 8, 14, 11, 26, + 8, 30, 11, 43, 9, 1, 17, 14, 15, 18, 12, 30, 15, 38, 12, + 1, 21, 13, 18, 18, 22, 33, 18, 38, 22, 8, 24, 13, 28, 25, + 25, 33, 28, 41, 25, 7, 4, 12, 2, 26, 5, 32, 2, 42, 5, + 7, 8, 13, 11, 26, 9, 29, 11, 42, 9, 0, 17, 13, 15, 19, + 12, 29, 15, 39, 12, 0, 21, 14, 18, 19, 22, 34, 18, 39, 22, + 8, 25, 14, 28, 24, 25, 34, 28, 40, 25, 8, 4, 13, 2, 25, + 5, 33, 2, 41, 5, 8, 8, 12, 11, 25, 9, 28, 11, 41, 9, + 0, 12, 12, 15, 20, 12, 28, 15, 40, 12, 0, 22, 15, 18, 20, + 22, 35, 18, 40, 22, 7, 25, 15, 28, 23, 25, 35, 28, 39, 25, + 8, 5, 14, 2, 24, 5, 34, 2, 40, 5, 8, 9, 11, 11, 24, + 9, 27, 11, 40, 9, 1, 12, 11, 15, 21, 12, 27, 15, 41, 12, + 1, 22, 16, 18, 21, 22, 35, 19, 41, 22, 6, 25, 16, 28, 22, + 25, 35, 29, 38, 25, 7, 5, 15, 2, 23, 5, 35, 2, 39, 5, + 7, 9, 10, 11, 23, 9, 27, 6, 39, 9, 2, 12, 10, 15, 22, + 12, 27, 16, 42, 12, 2, 22, 17, 18, 22, 22, 34, 19, 42, 22, + 5, 25, 17, 28, 21, 25, 34, 29, 37, 25, 6, 5, 16, 2, 22, + 5, 35, 3, 38, 5, 6, 9, 9, 11, 22, 9, 28, 6, 38, 9, + 3, 12, 9, 15, 23, 12, 28, 16, 43, 12, 3, 22, 17, 19, 23, + 22, 33, 19, 43, 22, 4, 25, 17, 29, 20, 25, 33, 29, 36, 25, + 5, 5, 17, 2, 21, 5, 34, 3, 37, 5, 5, 9, 9, 6, 21, + 9, 29, 6, 37, 9, 4, 12, 9, 16, 24, 12, 29, 16, 44, 12, + 4, 22, 16, 19, 24, 22, 32, 19, 44, 22, 3, 25, 16, 29, 19, + 25, 32, 29, 36, 26, 4, 5, 17, 3, 20, 5, 33, 3, 36, 5, + 4, 9, 10, 6, 20, 9, 30, 6, 36, 9, 5, 12, 10, 16, 25, + 12, 30, 16, 44, 13, 5, 22, 15, 19, 25, 22, 31, 19, 44, 23, + 2, 25, 15, 29, 18, 25, 31, 29, 37, 26, 3, 5, 16, 3, 19, + 5, 32, 3, 36, 0, 3, 9, 11, 6, 19, 9, 31, 6, 36, 10, + 6, 12, 11, 16, 26, 12, 31, 16, 43, 13, 6, 22, 14, 19, 26, + 22, 30, 19, 43, 23, 1, 25, 14, 29, 18, 26, 30, 29, 38, 26, + 2, 5, 15, 3, 18, 5, 31, 3, 37, 0, 2, 9, 12, 6, 18, + 9, 32, 6, 37, 10, 7, 12, 12, 16, 26, 13, 32, 16, 42, 13, + 7, 22, 13, 19, 26, 23, 29, 19, 42, 23, 0, 25, 13, 29, 19, + 26, 29, 29, 39, 26, 1, 5, 14, 3, 18, 0, 30, 3, 38, 0, + 1, 9, 13, 6, 18, 10, 33, 6, 38, 10, 8, 12, 13, 16, 25, + 13, 33, 16, 41, 13, 8, 22, 12, 19, 25, 23, 28, 19, 41, 23, + 0, 26, 12, 29, 20, 26, 28, 29, 40, 26, 0, 5, 13, 3, 19, + 0, 29, 3, 39, 0, 0, 9, 14, 6, 19, 10, 34, 6, 39, 10, + 8, 13, 14, 16, 24, 13, 34, 16, 40, 13, 8, 23, 11, 19, 24, + 23, 27, 19, 40, 23, 1, 26, 11, 29, 21, 26, 27, 29, 41, 26, +}; + +static const uint8_t hq_tab_02[] = { + 0, 0, 12, 5, 20, 0, 28, 5, 40, 0, 3, 16, 17, 11, 23, + 16, 33, 11, 43, 16, 1, 21, 14, 27, 18, 22, 30, 27, 38, 22, + 1, 0, 11, 5, 21, 0, 27, 5, 41, 0, 4, 16, 16, 11, 24, + 16, 32, 11, 44, 16, 0, 21, 13, 27, 19, 22, 29, 27, 39, 22, + 2, 0, 10, 5, 22, 0, 27, 6, 42, 0, 5, 16, 15, 11, 25, + 16, 31, 11, 44, 17, 0, 22, 12, 27, 20, 22, 28, 27, 40, 22, + 3, 0, 9, 5, 23, 0, 28, 6, 43, 0, 6, 16, 14, 11, 26, + 16, 30, 11, 43, 17, 1, 22, 11, 27, 21, 22, 27, 27, 41, 22, + 4, 0, 9, 6, 24, 0, 29, 6, 44, 0, 7, 16, 13, 11, 26, + 17, 29, 11, 42, 17, 2, 22, 10, 27, 22, 22, 27, 28, 42, 22, + 5, 0, 10, 6, 25, 0, 30, 6, 44, 1, 8, 16, 12, 11, 25, + 17, 28, 11, 41, 17, 3, 22, 9, 27, 23, 22, 28, 28, 43, 22, + 6, 0, 11, 6, 26, 0, 31, 6, 43, 1, 8, 17, 11, 11, 24, + 17, 27, 11, 40, 17, 4, 22, 9, 28, 24, 22, 29, 28, 44, 22, + 7, 0, 12, 6, 26, 1, 32, 6, 42, 1, 7, 17, 10, 11, 23, + 17, 27, 12, 39, 17, 5, 22, 10, 28, 25, 22, 30, 28, 44, 23, + 8, 0, 13, 6, 25, 1, 33, 6, 41, 1, 6, 17, 9, 11, 22, + 17, 28, 12, 38, 17, 6, 22, 11, 28, 26, 22, 31, 28, 43, 23, + 8, 1, 14, 6, 24, 1, 34, 6, 40, 1, 5, 17, 9, 12, 21, + 17, 29, 12, 37, 17, 7, 22, 12, 28, 26, 23, 32, 28, 42, 23, + 7, 1, 15, 6, 23, 1, 35, 6, 39, 1, 4, 17, 10, 12, 20, + 17, 30, 12, 36, 17, 8, 22, 13, 28, 25, 23, 33, 28, 41, 23, + 6, 1, 16, 6, 22, 1, 35, 7, 38, 1, 3, 17, 11, 12, 19, + 17, 31, 12, 36, 18, 8, 23, 14, 28, 24, 23, 34, 28, 40, 23, + 5, 1, 17, 6, 21, 1, 34, 7, 37, 1, 2, 17, 12, 12, 18, + 17, 32, 12, 37, 18, 7, 23, 15, 28, 23, 23, 35, 28, 39, 23, + 4, 1, 17, 7, 20, 1, 33, 7, 36, 1, 1, 17, 13, 12, 18, + 18, 33, 12, 38, 18, 6, 23, 16, 28, 22, 23, 35, 29, 38, 23, + 3, 1, 16, 7, 19, 1, 32, 7, 36, 2, 0, 17, 14, 12, 19, + 18, 34, 12, 39, 18, 5, 23, 17, 28, 21, 23, 34, 29, 37, 23, + 2, 1, 15, 7, 18, 1, 31, 7, 37, 2, 0, 18, 15, 12, 20, + 18, 35, 12, 40, 18, 4, 23, 17, 29, 20, 23, 33, 29, 36, 23, + 1, 1, 14, 7, 18, 2, 30, 7, 38, 2, 1, 18, 16, 12, 21, + 18, 35, 13, 41, 18, 3, 23, 16, 29, 19, 23, 32, 29, 36, 24, + 0, 1, 13, 7, 19, 2, 29, 7, 39, 2, 2, 18, 17, 12, 22, + 18, 34, 13, 42, 18, 2, 23, 15, 29, 18, 23, 31, 29, 37, 24, + 0, 2, 12, 7, 20, 2, 28, 7, 40, 2, 3, 18, 17, 13, 23, + 18, 33, 13, 43, 18, 1, 23, 14, 29, 18, 24, 30, 29, 38, 24, + 1, 2, 11, 7, 21, 2, 27, 7, 41, 2, 4, 18, 16, 13, 24, + 18, 32, 13, 44, 18, 0, 23, 13, 29, 19, 24, 29, 29, 39, 24, + 2, 2, 10, 7, 22, 2, 27, 8, 42, 2, 5, 18, 15, 13, 25, + 18, 31, 13, 44, 19, 0, 24, 12, 29, 20, 24, 28, 29, 40, 24, + 3, 2, 9, 7, 23, 2, 28, 8, 43, 2, 6, 18, 14, 13, 26, + 18, 30, 13, 43, 19, 1, 24, 11, 29, 21, 24, 27, 29, 41, 24, + 4, 2, 9, 8, 24, 2, 29, 8, 44, 2, 7, 18, 13, 13, 26, + 19, 29, 13, 42, 19, 2, 24, 10, 29, 22, 24, 27, 30, 42, 24, + 5, 2, 10, 8, 25, 2, 30, 8, 44, 3, 8, 18, 12, 13, 25, + 19, 28, 13, 41, 19, 3, 24, 9, 29, 23, 24, 28, 30, 43, 24, + 6, 2, 11, 8, 26, 2, 31, 8, 43, 3, 8, 19, 11, 13, 24, + 19, 27, 13, 40, 19, 4, 24, 9, 30, 24, 24, 29, 30, 44, 24, + 7, 2, 12, 8, 26, 3, 32, 8, 42, 3, 7, 19, 10, 13, 23, + 19, 27, 14, 39, 19, 5, 24, 10, 30, 25, 24, 30, 30, 44, 25, + 8, 2, 13, 8, 25, 3, 33, 8, 41, 3, 6, 19, 9, 13, 22, + 19, 28, 14, 38, 19, 6, 24, 11, 30, 26, 24, 31, 30, 43, 25, + 8, 3, 14, 8, 24, 3, 34, 8, 40, 3, 5, 19, 9, 14, 21, + 19, 29, 14, 37, 19, 7, 24, 12, 30, 26, 25, 32, 30, 42, 25, + 7, 3, 15, 8, 23, 3, 35, 8, 39, 3, 4, 19, 10, 14, 20, + 19, 30, 14, 36, 19, 8, 24, 13, 30, 25, 25, 33, 30, 41, 25, + 6, 3, 16, 8, 22, 3, 35, 9, 38, 3, 3, 19, 11, 14, 19, + 19, 31, 14, 36, 20, 8, 25, 14, 30, 24, 25, 34, 30, 40, 25, + 5, 3, 17, 8, 21, 3, 34, 9, 37, 3, 2, 19, 12, 14, 18, + 19, 32, 14, 37, 20, 7, 25, 15, 30, 23, 25, 35, 30, 39, 25, + 4, 3, 17, 9, 20, 3, 33, 9, 36, 3, 1, 19, 13, 14, 18, + 20, 33, 14, 38, 20, 6, 25, 16, 30, 22, 25, 33, 20, 38, 25, + 3, 3, 16, 9, 19, 3, 32, 9, 36, 4, 0, 19, 14, 14, 19, + 20, 34, 14, 39, 20, 5, 25, 17, 30, 21, 25, 34, 20, 37, 25, + 2, 3, 15, 9, 18, 3, 31, 9, 37, 4, 0, 20, 15, 14, 20, + 20, 35, 14, 40, 20, 4, 25, 15, 20, 20, 25, 35, 20, 36, 25, + 1, 3, 14, 9, 18, 4, 30, 9, 38, 4, 1, 20, 16, 14, 21, + 20, 35, 15, 41, 20, 3, 25, 16, 20, 19, 25, 35, 21, 36, 26, + 0, 3, 13, 9, 19, 4, 29, 9, 39, 4, 2, 20, 17, 14, 22, + 20, 34, 15, 39, 10, 2, 25, 17, 20, 18, 25, 34, 21, 37, 26, + 0, 4, 12, 9, 20, 4, 28, 9, 40, 4, 3, 20, 17, 15, 23, + 20, 33, 15, 40, 10, 1, 25, 17, 21, 18, 26, 33, 21, 38, 26, + 1, 4, 11, 9, 21, 4, 27, 9, 41, 4, 4, 20, 16, 15, 21, + 10, 32, 15, 41, 10, 0, 25, 16, 21, 19, 26, 32, 21, 39, 26, + 2, 4, 10, 9, 22, 4, 27, 10, 42, 4, 5, 20, 15, 15, 22, + 10, 31, 15, 42, 10, 0, 26, 15, 21, 20, 26, 31, 21, 40, 26, + 3, 4, 9, 9, 23, 4, 28, 10, 43, 4, 3, 10, 14, 15, 23, + 10, 30, 15, 43, 10, 1, 26, 14, 21, 21, 26, 30, 21, 41, 26, + 4, 4, 9, 10, 24, 4, 29, 10, 44, 4, 4, 10, 13, 15, 24, + 10, 29, 15, 44, 10, 2, 26, 13, 21, 22, 26, 29, 21, 42, 26, + 5, 4, 10, 10, 25, 4, 27, 0, 44, 5, 5, 10, 12, 15, 25, + 10, 28, 15, 44, 11, 3, 26, 12, 21, 23, 26, 28, 21, 43, 26, + 6, 4, 11, 10, 26, 4, 28, 0, 43, 5, 6, 10, 11, 15, 26, + 10, 27, 15, 43, 11, 4, 26, 11, 21, 24, 26, 27, 21, 44, 26, + 7, 4, 9, 0, 26, 5, 29, 0, 42, 5, 7, 10, 10, 15, 26, + 11, 27, 16, 42, 11, 5, 26, 10, 21, 25, 26, 27, 22, 44, 27, + 8, 4, 10, 0, 25, 5, 30, 0, 41, 5, 8, 10, 9, 15, 25, + 11, 28, 16, 41, 11, 6, 26, 9, 21, 26, 26, 28, 22, 43, 27, + 8, 5, 11, 0, 24, 5, 31, 0, 40, 5, 8, 11, 9, 16, 24, + 11, 29, 16, 40, 11, 7, 26, 9, 22, 26, 27, 29, 22, 42, 27, + 7, 5, 12, 0, 23, 5, 32, 0, 39, 5, 7, 11, 10, 16, 23, + 11, 30, 16, 39, 11, 8, 26, 10, 22, 25, 27, 30, 22, 41, 27, + 6, 5, 13, 0, 22, 5, 33, 0, 38, 5, 6, 11, 11, 16, 22, + 11, 31, 16, 38, 11, 8, 27, 11, 22, 24, 27, 31, 22, 40, 27, + 5, 5, 14, 0, 21, 5, 34, 0, 37, 5, 5, 11, 12, 16, 21, + 11, 32, 16, 37, 11, 7, 27, 12, 22, 23, 27, 32, 22, 39, 27, + 4, 5, 15, 0, 20, 5, 35, 0, 36, 5, 4, 11, 13, 16, 20, + 11, 33, 16, 36, 11, 6, 27, 13, 22, 22, 27, 33, 22, 38, 27, + 3, 5, 16, 0, 19, 5, 35, 1, 36, 6, 3, 11, 14, 16, 19, + 11, 34, 16, 36, 12, 5, 27, 14, 22, 21, 27, 34, 22, 37, 27, + 2, 5, 17, 0, 18, 5, 34, 1, 37, 6, 2, 11, 15, 16, 18, + 11, 35, 16, 37, 12, 4, 27, 15, 22, 20, 27, 35, 22, 36, 27, + 1, 5, 17, 1, 18, 6, 33, 1, 38, 6, 1, 11, 16, 16, 18, + 12, 35, 17, 38, 12, 3, 27, 16, 22, 19, 27, 35, 23, 36, 28, + 0, 5, 16, 1, 19, 6, 32, 1, 39, 6, 0, 11, 17, 16, 19, + 12, 34, 17, 39, 12, 2, 27, 17, 22, 18, 27, 34, 23, 37, 28, + 0, 6, 15, 1, 20, 6, 31, 1, 40, 6, 0, 12, 17, 17, 20, + 12, 33, 17, 40, 12, 1, 27, 17, 23, 18, 28, 33, 23, 38, 28, + 1, 6, 14, 1, 21, 6, 30, 1, 41, 6, 1, 12, 16, 17, 21, + 12, 32, 17, 41, 12, 0, 27, 16, 23, 19, 28, 32, 23, 39, 28, + 2, 6, 13, 1, 22, 6, 29, 1, 42, 6, 2, 12, 15, 17, 22, + 12, 31, 17, 42, 12, 0, 28, 15, 23, 20, 28, 31, 23, 40, 28, + 3, 6, 12, 1, 23, 6, 28, 1, 43, 6, 3, 12, 14, 17, 23, + 12, 30, 17, 43, 12, 1, 28, 14, 23, 21, 28, 30, 23, 41, 28, + 4, 6, 11, 1, 24, 6, 27, 1, 44, 6, 4, 12, 13, 17, 24, + 12, 29, 17, 44, 12, 2, 28, 13, 23, 22, 28, 29, 23, 42, 28, + 5, 6, 10, 1, 25, 6, 27, 2, 44, 7, 5, 12, 12, 17, 25, + 12, 28, 17, 44, 13, 3, 28, 12, 23, 23, 28, 28, 23, 43, 28, + 6, 6, 9, 1, 26, 6, 28, 2, 43, 7, 6, 12, 11, 17, 26, + 12, 27, 17, 43, 13, 4, 28, 11, 23, 24, 28, 27, 23, 44, 28, + 7, 6, 9, 2, 26, 7, 29, 2, 42, 7, 7, 12, 10, 17, 26, + 13, 27, 18, 42, 13, 5, 28, 10, 23, 25, 28, 27, 24, 44, 29, + 8, 6, 10, 2, 25, 7, 30, 2, 41, 7, 8, 12, 9, 17, 25, + 13, 28, 18, 41, 13, 6, 28, 9, 23, 26, 28, 28, 24, 43, 29, + 8, 7, 11, 2, 24, 7, 31, 2, 40, 7, 8, 13, 9, 18, 24, + 13, 29, 18, 40, 13, 7, 28, 9, 24, 26, 29, 29, 24, 42, 29, + 7, 7, 12, 2, 23, 7, 32, 2, 39, 7, 7, 13, 10, 18, 23, + 13, 30, 18, 39, 13, 8, 28, 10, 24, 25, 29, 30, 24, 41, 29, + 6, 7, 13, 2, 22, 7, 33, 2, 38, 7, 6, 13, 11, 18, 22, + 13, 31, 18, 38, 13, 8, 29, 11, 24, 24, 29, 31, 24, 40, 29, + 5, 7, 14, 2, 21, 7, 34, 2, 37, 7, 5, 13, 12, 18, 21, + 13, 32, 18, 37, 13, 7, 29, 12, 24, 23, 29, 32, 24, 39, 29, + 4, 7, 15, 2, 20, 7, 35, 2, 36, 7, 4, 13, 13, 18, 20, + 13, 33, 18, 36, 13, 6, 29, 13, 24, 22, 29, 33, 24, 38, 29, + 3, 7, 16, 2, 19, 7, 35, 3, 36, 8, 3, 13, 14, 18, 19, + 13, 34, 18, 36, 14, 5, 29, 14, 24, 21, 29, 34, 24, 37, 29, + 2, 7, 17, 2, 18, 7, 34, 3, 37, 8, 2, 13, 15, 18, 18, + 13, 35, 18, 37, 14, 4, 29, 15, 24, 20, 29, 35, 24, 36, 29, + 1, 7, 17, 3, 18, 8, 33, 3, 38, 8, 1, 13, 16, 18, 18, + 14, 35, 19, 38, 14, 3, 29, 16, 24, 19, 29, 35, 25, 36, 30, + 0, 7, 16, 3, 19, 8, 32, 3, 39, 8, 0, 13, 17, 18, 19, + 14, 34, 19, 39, 14, 2, 29, 17, 24, 18, 29, 34, 25, 37, 30, + 0, 8, 15, 3, 20, 8, 31, 3, 40, 8, 0, 14, 17, 19, 20, + 14, 33, 19, 40, 14, 1, 29, 17, 25, 18, 30, 33, 25, 38, 30, + 1, 8, 14, 3, 21, 8, 30, 3, 41, 8, 1, 14, 16, 19, 21, + 14, 32, 19, 41, 14, 0, 29, 16, 25, 19, 30, 32, 25, 39, 30, + 2, 8, 13, 3, 22, 8, 29, 3, 42, 8, 2, 14, 15, 19, 22, + 14, 31, 19, 42, 14, 0, 30, 15, 25, 20, 30, 31, 25, 40, 30, + 3, 8, 12, 3, 23, 8, 28, 3, 43, 8, 3, 14, 14, 19, 23, + 14, 30, 19, 43, 14, 1, 30, 14, 25, 21, 30, 30, 25, 41, 30, + 4, 8, 11, 3, 24, 8, 27, 3, 44, 8, 4, 14, 13, 19, 24, + 14, 29, 19, 44, 14, 2, 30, 13, 25, 22, 30, 29, 25, 42, 30, + 5, 8, 10, 3, 25, 8, 27, 4, 44, 9, 5, 14, 12, 19, 25, + 14, 28, 19, 44, 15, 3, 30, 12, 25, 23, 30, 28, 25, 43, 30, + 6, 8, 9, 3, 26, 8, 28, 4, 43, 9, 6, 14, 11, 19, 26, + 14, 27, 19, 43, 15, 4, 30, 11, 25, 24, 30, 27, 25, 44, 30, + 7, 8, 9, 4, 26, 9, 29, 4, 42, 9, 7, 14, 10, 19, 26, + 15, 27, 20, 42, 15, 5, 30, 10, 25, 25, 30, 27, 26, 42, 20, + 8, 8, 10, 4, 25, 9, 30, 4, 41, 9, 8, 14, 9, 19, 25, + 15, 28, 20, 41, 15, 6, 30, 9, 25, 26, 30, 28, 26, 43, 20, + 8, 9, 11, 4, 24, 9, 31, 4, 40, 9, 8, 15, 9, 20, 24, + 15, 29, 20, 40, 15, 7, 30, 9, 26, 24, 20, 29, 26, 44, 20, + 7, 9, 12, 4, 23, 9, 32, 4, 39, 9, 7, 15, 10, 20, 23, + 15, 30, 20, 39, 15, 8, 30, 10, 26, 25, 20, 30, 26, 44, 21, + 6, 9, 13, 4, 22, 9, 33, 4, 38, 9, 6, 15, 11, 20, 22, + 15, 31, 20, 38, 15, 6, 20, 11, 26, 26, 20, 31, 26, 43, 21, + 5, 9, 14, 4, 21, 9, 34, 4, 37, 9, 5, 15, 12, 20, 21, + 15, 32, 20, 37, 15, 7, 20, 12, 26, 26, 21, 32, 26, 42, 21, + 4, 9, 15, 4, 20, 9, 35, 4, 36, 9, 4, 15, 13, 20, 20, + 15, 30, 10, 36, 15, 8, 20, 13, 26, 25, 21, 33, 26, 41, 21, + 3, 9, 16, 4, 19, 9, 35, 5, 36, 10, 3, 15, 14, 20, 19, + 15, 31, 10, 36, 16, 8, 21, 14, 26, 24, 21, 34, 26, 40, 21, + 2, 9, 17, 4, 18, 9, 34, 5, 37, 10, 2, 15, 12, 10, 18, + 15, 32, 10, 37, 16, 7, 21, 15, 26, 23, 21, 35, 26, 39, 21, + 1, 9, 17, 5, 18, 10, 33, 5, 38, 10, 1, 15, 13, 10, 18, + 16, 33, 10, 38, 16, 6, 21, 16, 26, 22, 21, 35, 27, 38, 21, + 0, 9, 16, 5, 19, 10, 32, 5, 36, 0, 0, 15, 14, 10, 19, + 16, 34, 10, 39, 16, 5, 21, 17, 26, 21, 21, 34, 27, 37, 21, + 0, 10, 15, 5, 20, 10, 31, 5, 37, 0, 0, 16, 15, 10, 20, + 16, 35, 10, 40, 16, 4, 21, 17, 27, 20, 21, 33, 27, 36, 21, + 1, 10, 14, 5, 18, 0, 30, 5, 38, 0, 1, 16, 16, 10, 21, + 16, 35, 11, 41, 16, 3, 21, 16, 27, 19, 21, 32, 27, 36, 22, + 2, 10, 13, 5, 19, 0, 29, 5, 39, 0, 2, 16, 17, 10, 22, + 16, 34, 11, 42, 16, 2, 21, 15, 27, 18, 21, 31, 27, 37, 22, + 0, 0, +}; + +static const uint8_t hq_tab_03[] = { + 0, 0, 14, 4, 20, 0, 34, 4, 40, 0, 8, 14, 15, 9, 24, + 14, 35, 9, 40, 14, 7, 19, 11, 23, 23, 19, 27, 23, 39, 19, + 1, 33, 10, 28, 21, 33, 27, 29, 41, 33, 1, 0, 15, 4, 21, + 0, 35, 4, 41, 0, 7, 14, 16, 9, 23, 14, 35, 10, 39, 14, + 6, 19, 10, 23, 22, 19, 27, 24, 38, 19, 2, 33, 9, 28, 22, + 33, 28, 29, 42, 33, 2, 0, 16, 4, 22, 0, 35, 5, 42, 0, + 6, 14, 17, 9, 22, 14, 34, 10, 38, 14, 5, 19, 9, 23, 21, + 19, 28, 24, 37, 19, 3, 33, 9, 29, 23, 33, 29, 29, 43, 33, + 3, 0, 17, 4, 23, 0, 34, 5, 43, 0, 5, 14, 17, 10, 21, + 14, 33, 10, 37, 14, 4, 19, 9, 24, 20, 19, 29, 24, 36, 19, + 4, 33, 10, 29, 24, 33, 30, 29, 44, 33, 4, 0, 17, 5, 24, + 0, 33, 5, 44, 0, 4, 14, 16, 10, 20, 14, 32, 10, 36, 14, + 3, 19, 10, 24, 19, 19, 30, 24, 36, 20, 5, 33, 11, 29, 25, + 33, 31, 29, 44, 34, 5, 0, 16, 5, 25, 0, 32, 5, 44, 1, + 3, 14, 15, 10, 19, 14, 31, 10, 36, 15, 2, 19, 11, 24, 18, + 19, 31, 24, 37, 20, 6, 33, 12, 29, 26, 33, 32, 29, 43, 34, + 6, 0, 15, 5, 26, 0, 31, 5, 43, 1, 2, 14, 14, 10, 18, + 14, 30, 10, 37, 15, 1, 19, 12, 24, 18, 20, 32, 24, 38, 20, + 7, 33, 13, 29, 26, 34, 33, 29, 42, 34, 7, 0, 14, 5, 26, + 1, 30, 5, 42, 1, 1, 14, 13, 10, 18, 15, 29, 10, 38, 15, + 0, 19, 13, 24, 19, 20, 33, 24, 39, 20, 8, 33, 14, 29, 25, + 34, 34, 29, 41, 34, 8, 0, 13, 5, 25, 1, 29, 5, 41, 1, + 0, 14, 12, 10, 19, 15, 28, 10, 39, 15, 0, 20, 14, 24, 20, + 20, 34, 24, 40, 20, 8, 34, 15, 29, 24, 34, 35, 29, 40, 34, + 8, 1, 12, 5, 24, 1, 28, 5, 40, 1, 0, 15, 11, 10, 20, + 15, 27, 10, 40, 15, 1, 20, 15, 24, 21, 20, 35, 24, 41, 20, + 7, 34, 16, 29, 23, 34, 35, 30, 39, 34, 7, 1, 11, 5, 23, + 1, 27, 5, 39, 1, 1, 15, 10, 10, 21, 15, 27, 11, 41, 15, + 2, 20, 16, 24, 22, 20, 35, 25, 42, 20, 6, 34, 17, 29, 22, + 34, 34, 30, 38, 34, 6, 1, 10, 5, 22, 1, 27, 6, 38, 1, + 2, 15, 9, 10, 22, 15, 28, 11, 42, 15, 3, 20, 17, 24, 23, + 20, 34, 25, 43, 20, 5, 34, 17, 30, 21, 34, 33, 30, 37, 34, + 5, 1, 9, 5, 21, 1, 28, 6, 37, 1, 3, 15, 9, 11, 23, + 15, 29, 11, 43, 15, 4, 20, 17, 25, 24, 20, 33, 25, 44, 20, + 4, 34, 16, 30, 20, 34, 32, 30, 36, 34, 4, 1, 9, 6, 20, + 1, 29, 6, 36, 1, 4, 15, 10, 11, 24, 15, 30, 11, 44, 15, + 5, 20, 16, 25, 25, 20, 32, 25, 44, 21, 3, 34, 15, 30, 19, + 34, 31, 30, 36, 35, 3, 1, 10, 6, 19, 1, 30, 6, 36, 2, + 5, 15, 11, 11, 25, 15, 31, 11, 44, 16, 6, 20, 15, 25, 26, + 20, 31, 25, 43, 21, 2, 34, 14, 30, 18, 34, 30, 30, 37, 35, + 2, 1, 11, 6, 18, 1, 31, 6, 37, 2, 6, 15, 12, 11, 26, + 15, 32, 11, 43, 16, 7, 20, 14, 25, 26, 21, 30, 25, 42, 21, + 1, 34, 13, 30, 18, 35, 29, 30, 38, 35, 1, 1, 12, 6, 18, + 2, 32, 6, 38, 2, 7, 15, 13, 11, 26, 16, 33, 11, 42, 16, + 8, 20, 13, 25, 25, 21, 29, 25, 41, 21, 0, 34, 12, 30, 19, + 35, 28, 30, 39, 35, 0, 1, 13, 6, 19, 2, 33, 6, 39, 2, + 8, 15, 14, 11, 25, 16, 34, 11, 41, 16, 8, 21, 12, 25, 24, + 21, 28, 25, 40, 21, 0, 35, 11, 30, 20, 35, 27, 30, 40, 35, + 0, 2, 14, 6, 20, 2, 34, 6, 40, 2, 8, 16, 15, 11, 24, + 16, 35, 11, 40, 16, 7, 21, 11, 25, 23, 21, 27, 25, 39, 21, + 1, 35, 10, 30, 21, 35, 27, 31, 41, 35, 1, 2, 15, 6, 21, + 2, 35, 6, 41, 2, 7, 16, 16, 11, 23, 16, 35, 12, 39, 16, + 6, 21, 10, 25, 22, 21, 27, 26, 38, 21, 2, 35, 9, 30, 22, + 35, 28, 31, 42, 35, 2, 2, 16, 6, 22, 2, 35, 7, 42, 2, + 6, 16, 17, 11, 22, 16, 34, 12, 38, 16, 5, 21, 9, 25, 21, + 21, 28, 26, 37, 21, 3, 35, 9, 31, 23, 35, 29, 31, 43, 35, + 3, 2, 17, 6, 23, 2, 34, 7, 43, 2, 5, 16, 17, 12, 21, + 16, 33, 12, 37, 16, 4, 21, 9, 26, 20, 21, 29, 26, 36, 21, + 4, 35, 10, 31, 24, 35, 30, 31, 44, 35, 4, 2, 17, 7, 24, + 2, 33, 7, 44, 2, 4, 16, 16, 12, 20, 16, 32, 12, 36, 16, + 3, 21, 10, 26, 19, 21, 30, 26, 36, 22, 5, 35, 11, 31, 25, + 35, 31, 31, 36, 27, 5, 2, 16, 7, 25, 2, 32, 7, 44, 3, + 3, 16, 15, 12, 19, 16, 31, 12, 36, 17, 2, 21, 11, 26, 18, + 21, 31, 26, 37, 22, 6, 35, 12, 31, 26, 35, 32, 31, 37, 27, + 6, 2, 15, 7, 26, 2, 31, 7, 43, 3, 2, 16, 14, 12, 18, + 16, 30, 12, 37, 17, 1, 21, 12, 26, 18, 22, 32, 26, 38, 22, + 7, 35, 13, 31, 18, 27, 33, 31, 38, 27, 7, 2, 14, 7, 26, + 3, 30, 7, 42, 3, 1, 16, 13, 12, 18, 17, 29, 12, 38, 17, + 0, 21, 13, 26, 19, 22, 33, 26, 39, 22, 8, 35, 14, 31, 19, + 27, 34, 31, 39, 27, 8, 2, 13, 7, 25, 3, 29, 7, 41, 3, + 0, 16, 12, 12, 19, 17, 28, 12, 39, 17, 0, 22, 14, 26, 20, + 22, 34, 26, 40, 22, 0, 27, 15, 31, 20, 27, 35, 31, 40, 27, + 8, 3, 12, 7, 24, 3, 28, 7, 40, 3, 0, 17, 11, 12, 20, + 17, 27, 12, 40, 17, 1, 22, 15, 26, 21, 22, 35, 26, 41, 22, + 1, 27, 16, 31, 21, 27, 35, 32, 41, 27, 7, 3, 11, 7, 23, + 3, 27, 7, 39, 3, 1, 17, 10, 12, 21, 17, 27, 13, 41, 17, + 2, 22, 16, 26, 22, 22, 27, 18, 42, 22, 2, 27, 17, 31, 22, + 27, 34, 32, 42, 27, 6, 3, 10, 7, 22, 3, 27, 8, 38, 3, + 2, 17, 9, 12, 22, 17, 28, 13, 42, 17, 3, 22, 17, 26, 23, + 22, 28, 18, 43, 22, 3, 27, 17, 32, 23, 27, 33, 32, 43, 27, + 5, 3, 9, 7, 21, 3, 28, 8, 37, 3, 3, 17, 9, 13, 23, + 17, 29, 13, 43, 17, 4, 22, 9, 18, 24, 22, 29, 18, 44, 22, + 4, 27, 16, 32, 24, 27, 32, 32, 44, 27, 4, 3, 9, 8, 20, + 3, 29, 8, 36, 3, 4, 17, 10, 13, 24, 17, 30, 13, 44, 17, + 5, 22, 10, 18, 25, 22, 30, 18, 44, 23, 5, 27, 15, 32, 25, + 27, 31, 32, 44, 28, 3, 3, 10, 8, 19, 3, 30, 8, 36, 4, + 5, 17, 11, 13, 25, 17, 31, 13, 36, 9, 6, 22, 11, 18, 26, + 22, 31, 18, 43, 23, 6, 27, 14, 32, 26, 27, 30, 32, 43, 28, + 2, 3, 11, 8, 18, 3, 31, 8, 37, 4, 6, 17, 12, 13, 26, + 17, 32, 13, 37, 9, 7, 22, 12, 18, 26, 23, 32, 18, 42, 23, + 7, 27, 13, 32, 26, 28, 29, 32, 42, 28, 1, 3, 12, 8, 18, + 4, 32, 8, 38, 4, 7, 17, 13, 13, 18, 9, 33, 13, 38, 9, + 8, 22, 13, 18, 25, 23, 33, 18, 41, 23, 8, 27, 12, 32, 25, + 28, 28, 32, 41, 28, 0, 3, 13, 8, 19, 4, 33, 8, 39, 4, + 8, 17, 14, 13, 19, 9, 34, 13, 39, 9, 8, 23, 14, 18, 24, + 23, 34, 18, 40, 23, 8, 28, 11, 32, 24, 28, 27, 32, 40, 28, + 0, 4, 14, 8, 20, 4, 34, 8, 40, 4, 0, 9, 15, 13, 20, + 9, 35, 13, 40, 9, 7, 23, 15, 18, 23, 23, 35, 18, 39, 23, + 7, 28, 10, 32, 23, 28, 27, 33, 39, 28, 1, 4, 15, 8, 21, + 4, 35, 8, 41, 4, 1, 9, 16, 13, 21, 9, 35, 14, 41, 9, + 6, 23, 16, 18, 22, 23, 35, 19, 38, 23, 6, 28, 9, 32, 22, + 28, 28, 33, 38, 28, 2, 4, 16, 8, 22, 4, 27, 0, 42, 4, + 2, 9, 17, 13, 22, 9, 34, 14, 42, 9, 5, 23, 17, 18, 21, + 23, 34, 19, 37, 23, 5, 28, 9, 33, 21, 28, 29, 33, 37, 28, + 3, 4, 17, 8, 23, 4, 28, 0, 43, 4, 3, 9, 17, 14, 23, + 9, 33, 14, 43, 9, 4, 23, 17, 19, 20, 23, 33, 19, 36, 23, + 4, 28, 10, 33, 20, 28, 30, 33, 36, 28, 4, 4, 9, 0, 24, + 4, 29, 0, 44, 4, 4, 9, 16, 14, 24, 9, 32, 14, 44, 9, + 3, 23, 16, 19, 19, 23, 32, 19, 36, 24, 3, 28, 11, 33, 19, + 28, 31, 33, 36, 29, 5, 4, 10, 0, 25, 4, 30, 0, 44, 5, + 5, 9, 15, 14, 25, 9, 31, 14, 44, 10, 2, 23, 15, 19, 18, + 23, 31, 19, 37, 24, 2, 28, 12, 33, 18, 28, 32, 33, 37, 29, + 6, 4, 11, 0, 26, 4, 31, 0, 43, 5, 6, 9, 14, 14, 26, + 9, 30, 14, 43, 10, 1, 23, 14, 19, 18, 24, 30, 19, 38, 24, + 1, 28, 13, 33, 18, 29, 33, 33, 38, 29, 7, 4, 12, 0, 26, + 5, 32, 0, 42, 5, 7, 9, 13, 14, 26, 10, 29, 14, 42, 10, + 0, 23, 13, 19, 19, 24, 29, 19, 39, 24, 0, 28, 14, 33, 19, + 29, 34, 33, 39, 29, 8, 4, 13, 0, 25, 5, 33, 0, 41, 5, + 8, 9, 12, 14, 25, 10, 28, 14, 41, 10, 0, 24, 12, 19, 20, + 24, 28, 19, 40, 24, 0, 29, 15, 33, 20, 29, 35, 33, 40, 29, + 8, 5, 14, 0, 24, 5, 34, 0, 40, 5, 8, 10, 11, 14, 24, + 10, 27, 14, 40, 10, 1, 24, 11, 19, 21, 24, 27, 19, 41, 24, + 1, 29, 16, 33, 21, 29, 35, 34, 41, 29, 7, 5, 15, 0, 23, + 5, 35, 0, 39, 5, 7, 10, 10, 14, 23, 10, 27, 15, 39, 10, + 2, 24, 10, 19, 22, 24, 27, 20, 42, 24, 2, 29, 17, 33, 22, + 29, 34, 34, 42, 29, 6, 5, 16, 0, 22, 5, 35, 1, 38, 5, + 6, 10, 9, 14, 22, 10, 28, 15, 38, 10, 3, 24, 9, 19, 23, + 24, 28, 20, 43, 24, 3, 29, 17, 34, 23, 29, 33, 34, 43, 29, + 5, 5, 17, 0, 21, 5, 34, 1, 37, 5, 5, 10, 9, 15, 21, + 10, 29, 15, 37, 10, 4, 24, 9, 20, 24, 24, 29, 20, 44, 24, + 4, 29, 16, 34, 24, 29, 32, 34, 44, 29, 4, 5, 17, 1, 20, + 5, 33, 1, 36, 5, 4, 10, 10, 15, 20, 10, 30, 15, 36, 10, + 5, 24, 10, 20, 25, 24, 30, 20, 44, 25, 5, 29, 15, 34, 25, + 29, 31, 34, 44, 30, 3, 5, 16, 1, 19, 5, 32, 1, 36, 6, + 3, 10, 11, 15, 19, 10, 31, 15, 36, 11, 6, 24, 11, 20, 26, + 24, 31, 20, 43, 25, 6, 29, 14, 34, 26, 29, 30, 34, 43, 30, + 2, 5, 15, 1, 18, 5, 31, 1, 37, 6, 2, 10, 12, 15, 18, + 10, 32, 15, 37, 11, 7, 24, 12, 20, 26, 25, 32, 20, 42, 25, + 7, 29, 13, 34, 26, 30, 29, 34, 42, 30, 1, 5, 14, 1, 18, + 6, 30, 1, 38, 6, 1, 10, 13, 15, 18, 11, 33, 15, 38, 11, + 8, 24, 13, 20, 25, 25, 33, 20, 41, 25, 8, 29, 12, 34, 25, + 30, 28, 34, 41, 30, 0, 5, 13, 1, 19, 6, 29, 1, 39, 6, + 0, 10, 14, 15, 19, 11, 34, 15, 39, 11, 8, 25, 14, 20, 24, + 25, 34, 20, 40, 25, 8, 30, 11, 34, 24, 30, 27, 34, 40, 30, + 0, 6, 12, 1, 20, 6, 28, 1, 40, 6, 0, 11, 15, 15, 20, + 11, 35, 15, 40, 11, 7, 25, 15, 20, 23, 25, 35, 20, 39, 25, + 7, 30, 10, 34, 23, 30, 27, 35, 39, 30, 1, 6, 11, 1, 21, + 6, 27, 1, 41, 6, 1, 11, 16, 15, 21, 11, 35, 16, 41, 11, + 6, 25, 16, 20, 22, 25, 35, 21, 38, 25, 6, 30, 9, 34, 22, + 30, 28, 35, 38, 30, 2, 6, 10, 1, 22, 6, 27, 2, 42, 6, + 2, 11, 17, 15, 22, 11, 34, 16, 42, 11, 5, 25, 17, 20, 21, + 25, 34, 21, 37, 25, 5, 30, 9, 35, 21, 30, 29, 35, 37, 30, + 3, 6, 9, 1, 23, 6, 28, 2, 43, 6, 3, 11, 17, 16, 23, + 11, 33, 16, 43, 11, 4, 25, 17, 21, 20, 25, 33, 21, 36, 25, + 4, 30, 10, 35, 20, 30, 30, 35, 36, 30, 4, 6, 9, 2, 24, + 6, 29, 2, 44, 6, 4, 11, 16, 16, 24, 11, 32, 16, 44, 11, + 3, 25, 16, 21, 19, 25, 32, 21, 36, 26, 3, 30, 11, 35, 19, + 30, 31, 35, 36, 31, 5, 6, 10, 2, 25, 6, 30, 2, 44, 7, + 5, 11, 15, 16, 25, 11, 31, 16, 44, 12, 2, 25, 15, 21, 18, + 25, 31, 21, 37, 26, 2, 30, 12, 35, 18, 30, 32, 35, 37, 31, + 6, 6, 11, 2, 26, 6, 31, 2, 43, 7, 6, 11, 14, 16, 26, + 11, 30, 16, 43, 12, 1, 25, 14, 21, 18, 26, 30, 21, 38, 26, + 1, 30, 13, 35, 18, 31, 33, 35, 38, 31, 7, 6, 12, 2, 26, + 7, 32, 2, 42, 7, 7, 11, 13, 16, 26, 12, 29, 16, 42, 12, + 0, 25, 13, 21, 19, 26, 29, 21, 39, 26, 0, 30, 14, 35, 19, + 31, 34, 35, 39, 31, 8, 6, 13, 2, 25, 7, 33, 2, 41, 7, + 8, 11, 12, 16, 25, 12, 28, 16, 41, 12, 0, 26, 12, 21, 20, + 26, 28, 21, 40, 26, 0, 31, 15, 35, 20, 31, 35, 35, 40, 31, + 8, 7, 14, 2, 24, 7, 34, 2, 40, 7, 8, 12, 11, 16, 24, + 12, 27, 16, 40, 12, 1, 26, 11, 21, 21, 26, 27, 21, 41, 26, + 1, 31, 16, 35, 21, 31, 27, 27, 41, 31, 7, 7, 15, 2, 23, + 7, 35, 2, 39, 7, 7, 12, 10, 16, 23, 12, 27, 17, 39, 12, + 2, 26, 10, 21, 22, 26, 27, 22, 42, 26, 2, 31, 17, 35, 22, + 31, 28, 27, 42, 31, 6, 7, 16, 2, 22, 7, 35, 3, 38, 7, + 6, 12, 9, 16, 22, 12, 28, 17, 38, 12, 3, 26, 9, 21, 23, + 26, 28, 22, 43, 26, 3, 31, 9, 27, 23, 31, 29, 27, 43, 31, + 5, 7, 17, 2, 21, 7, 34, 3, 37, 7, 5, 12, 9, 17, 21, + 12, 29, 17, 37, 12, 4, 26, 9, 22, 24, 26, 29, 22, 44, 26, + 4, 31, 10, 27, 24, 31, 30, 27, 44, 31, 4, 7, 17, 3, 20, + 7, 33, 3, 36, 7, 4, 12, 10, 17, 20, 12, 30, 17, 36, 12, + 5, 26, 10, 22, 25, 26, 30, 22, 36, 18, 5, 31, 11, 27, 25, + 31, 31, 27, 44, 32, 3, 7, 16, 3, 19, 7, 32, 3, 36, 8, + 3, 12, 11, 17, 19, 12, 31, 17, 36, 13, 6, 26, 11, 22, 26, + 26, 31, 22, 37, 18, 6, 31, 12, 27, 26, 31, 32, 27, 43, 32, + 2, 7, 15, 3, 18, 7, 31, 3, 37, 8, 2, 12, 12, 17, 18, + 12, 32, 17, 37, 13, 7, 26, 12, 22, 18, 18, 32, 22, 38, 18, + 7, 31, 13, 27, 26, 32, 33, 27, 42, 32, 1, 7, 14, 3, 18, + 8, 30, 3, 38, 8, 1, 12, 13, 17, 18, 13, 33, 17, 38, 13, + 8, 26, 13, 22, 19, 18, 33, 22, 39, 18, 8, 31, 14, 27, 25, + 32, 34, 27, 41, 32, 0, 7, 13, 3, 19, 8, 29, 3, 39, 8, + 0, 12, 14, 17, 19, 13, 34, 17, 39, 13, 0, 18, 14, 22, 20, + 18, 34, 22, 40, 18, 8, 32, 15, 27, 24, 32, 35, 27, 40, 32, + 0, 8, 12, 3, 20, 8, 28, 3, 40, 8, 0, 13, 15, 17, 20, + 13, 35, 17, 40, 13, 1, 18, 15, 22, 21, 18, 35, 22, 41, 18, + 7, 32, 16, 27, 23, 32, 35, 28, 39, 32, 1, 8, 11, 3, 21, + 8, 27, 3, 41, 8, 1, 13, 16, 17, 21, 13, 27, 9, 41, 13, + 2, 18, 16, 22, 22, 18, 35, 23, 42, 18, 6, 32, 17, 27, 22, + 32, 34, 28, 38, 32, 2, 8, 10, 3, 22, 8, 27, 4, 42, 8, + 2, 13, 17, 17, 22, 13, 28, 9, 42, 13, 3, 18, 17, 22, 23, + 18, 34, 23, 43, 18, 5, 32, 17, 28, 21, 32, 33, 28, 37, 32, + 3, 8, 9, 3, 23, 8, 28, 4, 43, 8, 3, 13, 9, 9, 23, + 13, 29, 9, 43, 13, 4, 18, 17, 23, 24, 18, 33, 23, 44, 18, + 4, 32, 16, 28, 20, 32, 32, 28, 36, 32, 4, 8, 9, 4, 24, + 8, 29, 4, 44, 8, 4, 13, 10, 9, 24, 13, 30, 9, 44, 13, + 5, 18, 16, 23, 25, 18, 32, 23, 44, 19, 3, 32, 15, 28, 19, + 32, 31, 28, 36, 33, 5, 8, 10, 4, 25, 8, 30, 4, 36, 0, + 5, 13, 11, 9, 25, 13, 31, 9, 44, 14, 6, 18, 15, 23, 26, + 18, 31, 23, 43, 19, 2, 32, 14, 28, 18, 32, 30, 28, 37, 33, + 6, 8, 11, 4, 26, 8, 31, 4, 37, 0, 6, 13, 12, 9, 26, + 13, 32, 9, 43, 14, 7, 18, 14, 23, 26, 19, 30, 23, 42, 19, + 1, 32, 13, 28, 18, 33, 29, 28, 38, 33, 7, 8, 12, 4, 18, + 0, 32, 4, 38, 0, 7, 13, 13, 9, 26, 14, 33, 9, 42, 14, + 8, 18, 13, 23, 25, 19, 29, 23, 41, 19, 0, 32, 12, 28, 19, + 33, 28, 28, 39, 33, 8, 8, 13, 4, 19, 0, 33, 4, 39, 0, + 8, 13, 14, 9, 25, 14, 34, 9, 41, 14, 8, 19, 12, 23, 24, + 19, 28, 23, 40, 19, 0, 33, 11, 28, 20, 33, 27, 28, 40, 33, +}; + +static const uint8_t hq_tab_04[] = { + 0, 0, 19, 4, 26, 0, 45, 4, 52, 0, 11, 13, 18, 9, 34, + 14, 44, 9, 56, 14, 10, 18, 18, 23, 35, 19, 40, 23, 57, 19, + 2, 32, 19, 28, 24, 32, 41, 28, 49, 33, 3, 37, 15, 42, 25, + 37, 41, 42, 48, 38, 1, 0, 20, 4, 27, 0, 46, 4, 53, 0, + 11, 14, 19, 9, 33, 14, 45, 9, 55, 14, 11, 18, 17, 23, 34, + 19, 39, 23, 56, 19, 1, 32, 18, 28, 24, 33, 40, 28, 50, 33, + 2, 37, 16, 42, 24, 37, 42, 42, 49, 38, 2, 0, 21, 4, 28, + 0, 47, 4, 54, 0, 10, 14, 20, 9, 32, 14, 46, 9, 54, 14, + 11, 19, 16, 23, 33, 19, 38, 23, 55, 19, 0, 32, 17, 28, 25, + 33, 39, 28, 51, 33, 1, 37, 17, 42, 24, 38, 43, 42, 50, 38, + 3, 0, 22, 4, 29, 0, 47, 5, 55, 0, 9, 14, 21, 9, 31, + 14, 47, 9, 53, 14, 10, 19, 15, 23, 32, 19, 37, 23, 54, 19, + 0, 33, 16, 28, 26, 33, 38, 28, 52, 33, 0, 37, 18, 42, 25, + 38, 44, 42, 51, 38, 4, 0, 23, 4, 30, 0, 46, 5, 56, 0, + 8, 14, 22, 9, 30, 14, 47, 10, 52, 14, 9, 19, 14, 23, 31, + 19, 36, 23, 53, 19, 1, 33, 15, 28, 27, 33, 37, 28, 53, 33, + 0, 38, 19, 42, 26, 38, 45, 42, 52, 38, 5, 0, 23, 5, 31, + 0, 45, 5, 57, 0, 7, 14, 23, 9, 29, 14, 46, 10, 51, 14, + 8, 19, 13, 23, 30, 19, 36, 24, 52, 19, 2, 33, 14, 28, 28, + 33, 36, 28, 54, 33, 1, 38, 20, 42, 27, 38, 46, 42, 53, 38, + 6, 0, 22, 5, 32, 0, 44, 5, 58, 0, 6, 14, 23, 10, 28, + 14, 45, 10, 50, 14, 7, 19, 12, 23, 29, 19, 37, 24, 51, 19, + 3, 33, 13, 28, 29, 33, 36, 29, 55, 33, 2, 38, 21, 42, 28, + 38, 47, 42, 54, 38, 7, 0, 21, 5, 33, 0, 43, 5, 59, 0, + 5, 14, 22, 10, 27, 14, 44, 10, 49, 14, 6, 19, 12, 24, 28, + 19, 38, 24, 50, 19, 4, 33, 12, 28, 30, 33, 37, 29, 56, 33, + 3, 38, 22, 42, 29, 38, 47, 43, 55, 38, 8, 0, 20, 5, 34, + 0, 42, 5, 59, 1, 4, 14, 21, 10, 26, 14, 43, 10, 48, 14, + 5, 19, 13, 24, 27, 19, 39, 24, 49, 19, 5, 33, 12, 29, 31, + 33, 38, 29, 57, 33, 4, 38, 23, 42, 30, 38, 46, 43, 56, 38, + 9, 0, 19, 5, 35, 0, 41, 5, 58, 1, 3, 14, 20, 10, 25, + 14, 42, 10, 48, 15, 4, 19, 14, 24, 26, 19, 40, 24, 48, 19, + 6, 33, 13, 29, 32, 33, 39, 29, 58, 33, 5, 38, 23, 43, 31, + 38, 45, 43, 57, 38, 10, 0, 18, 5, 35, 1, 40, 5, 57, 1, + 2, 14, 19, 10, 24, 14, 41, 10, 49, 15, 3, 19, 15, 24, 25, + 19, 41, 24, 48, 20, 7, 33, 14, 29, 33, 33, 40, 29, 59, 33, + 6, 38, 22, 43, 32, 38, 44, 43, 58, 38, 11, 0, 17, 5, 34, + 1, 39, 5, 56, 1, 1, 14, 18, 10, 24, 15, 40, 10, 50, 15, + 2, 19, 16, 24, 24, 19, 42, 24, 49, 20, 8, 33, 15, 29, 34, + 33, 41, 29, 59, 34, 7, 38, 21, 43, 33, 38, 43, 43, 59, 38, + 11, 1, 16, 5, 33, 1, 38, 5, 55, 1, 0, 14, 17, 10, 25, + 15, 39, 10, 51, 15, 1, 19, 17, 24, 24, 20, 43, 24, 50, 20, + 9, 33, 16, 29, 35, 33, 42, 29, 58, 34, 8, 38, 20, 43, 34, + 38, 42, 43, 59, 39, 10, 1, 15, 5, 32, 1, 37, 5, 54, 1, + 0, 15, 16, 10, 26, 15, 38, 10, 52, 15, 0, 19, 18, 24, 25, + 20, 44, 24, 51, 20, 10, 33, 17, 29, 35, 34, 43, 29, 57, 34, + 9, 38, 19, 43, 35, 38, 41, 43, 58, 39, 9, 1, 14, 5, 31, + 1, 36, 5, 53, 1, 1, 15, 15, 10, 27, 15, 37, 10, 53, 15, + 0, 20, 19, 24, 26, 20, 45, 24, 52, 20, 11, 33, 18, 29, 34, + 34, 44, 29, 56, 34, 10, 38, 18, 43, 35, 39, 40, 43, 57, 39, + 8, 1, 13, 5, 30, 1, 36, 6, 52, 1, 2, 15, 14, 10, 28, + 15, 36, 10, 54, 15, 1, 20, 20, 24, 27, 20, 46, 24, 53, 20, + 11, 34, 19, 29, 33, 34, 45, 29, 55, 34, 11, 38, 17, 43, 34, + 39, 39, 43, 56, 39, 7, 1, 12, 5, 29, 1, 37, 6, 51, 1, + 3, 15, 13, 10, 29, 15, 36, 11, 55, 15, 2, 20, 21, 24, 28, + 20, 47, 24, 54, 20, 10, 34, 20, 29, 32, 34, 46, 29, 54, 34, + 11, 39, 16, 43, 33, 39, 38, 43, 55, 39, 6, 1, 12, 6, 28, + 1, 38, 6, 50, 1, 4, 15, 12, 10, 30, 15, 37, 11, 56, 15, + 3, 20, 22, 24, 29, 20, 47, 25, 55, 20, 9, 34, 21, 29, 31, + 34, 47, 29, 53, 34, 10, 39, 15, 43, 32, 39, 37, 43, 54, 39, + 5, 1, 13, 6, 27, 1, 39, 6, 49, 1, 5, 15, 12, 11, 31, + 15, 38, 11, 57, 15, 4, 20, 23, 24, 30, 20, 46, 25, 56, 20, + 8, 34, 22, 29, 30, 34, 47, 30, 52, 34, 9, 39, 14, 43, 31, + 39, 36, 43, 53, 39, 4, 1, 14, 6, 26, 1, 40, 6, 48, 1, + 6, 15, 13, 11, 32, 15, 39, 11, 58, 15, 5, 20, 23, 25, 31, + 20, 45, 25, 57, 20, 7, 34, 23, 29, 29, 34, 46, 30, 51, 34, + 8, 39, 13, 43, 30, 39, 36, 44, 52, 39, 3, 1, 15, 6, 25, + 1, 41, 6, 48, 2, 7, 15, 14, 11, 33, 15, 40, 11, 59, 15, + 6, 20, 22, 25, 32, 20, 44, 25, 58, 20, 6, 34, 23, 30, 28, + 34, 45, 30, 50, 34, 7, 39, 12, 43, 29, 39, 37, 44, 51, 39, + 2, 1, 16, 6, 24, 1, 42, 6, 49, 2, 8, 15, 15, 11, 34, + 15, 41, 11, 59, 16, 7, 20, 21, 25, 33, 20, 43, 25, 59, 20, + 5, 34, 22, 30, 27, 34, 44, 30, 49, 34, 6, 39, 12, 44, 28, + 39, 38, 44, 50, 39, 1, 1, 17, 6, 24, 2, 43, 6, 50, 2, + 9, 15, 16, 11, 35, 15, 42, 11, 58, 16, 8, 20, 20, 25, 34, + 20, 42, 25, 59, 21, 4, 34, 21, 30, 26, 34, 43, 30, 48, 34, + 5, 39, 13, 44, 27, 39, 39, 44, 49, 39, 0, 1, 18, 6, 25, + 2, 44, 6, 51, 2, 10, 15, 17, 11, 35, 16, 43, 11, 57, 16, + 9, 20, 19, 25, 35, 20, 41, 25, 58, 21, 3, 34, 20, 30, 25, + 34, 42, 30, 48, 35, 4, 39, 14, 44, 26, 39, 40, 44, 48, 39, + 0, 2, 19, 6, 26, 2, 45, 6, 52, 2, 11, 15, 18, 11, 34, + 16, 44, 11, 56, 16, 10, 20, 18, 25, 35, 21, 40, 25, 57, 21, + 2, 34, 19, 30, 24, 34, 41, 30, 49, 35, 3, 39, 15, 44, 25, + 39, 41, 44, 48, 40, 1, 2, 20, 6, 27, 2, 46, 6, 53, 2, + 11, 16, 19, 11, 33, 16, 45, 11, 55, 16, 11, 20, 17, 25, 34, + 21, 39, 25, 56, 21, 1, 34, 18, 30, 24, 35, 40, 30, 50, 35, + 2, 39, 16, 44, 24, 39, 42, 44, 49, 40, 2, 2, 21, 6, 28, + 2, 47, 6, 54, 2, 10, 16, 20, 11, 32, 16, 46, 11, 54, 16, + 11, 21, 16, 25, 33, 21, 38, 25, 55, 21, 0, 34, 17, 30, 25, + 35, 39, 30, 51, 35, 1, 39, 17, 44, 24, 40, 43, 44, 50, 40, + 3, 2, 22, 6, 29, 2, 47, 7, 55, 2, 9, 16, 21, 11, 31, + 16, 47, 11, 53, 16, 10, 21, 15, 25, 32, 21, 37, 25, 54, 21, + 0, 35, 16, 30, 26, 35, 38, 30, 52, 35, 0, 39, 18, 44, 25, + 40, 44, 44, 51, 40, 4, 2, 23, 6, 30, 2, 46, 7, 56, 2, + 8, 16, 22, 11, 30, 16, 47, 12, 52, 16, 9, 21, 14, 25, 31, + 21, 36, 25, 53, 21, 1, 35, 15, 30, 27, 35, 37, 30, 53, 35, + 0, 40, 19, 44, 26, 40, 45, 44, 52, 40, 5, 2, 23, 7, 31, + 2, 45, 7, 57, 2, 7, 16, 23, 11, 29, 16, 46, 12, 51, 16, + 8, 21, 13, 25, 30, 21, 36, 26, 52, 21, 2, 35, 14, 30, 28, + 35, 36, 30, 54, 35, 1, 40, 20, 44, 27, 40, 46, 44, 53, 40, + 6, 2, 22, 7, 32, 2, 44, 7, 58, 2, 6, 16, 23, 12, 28, + 16, 45, 12, 50, 16, 7, 21, 12, 25, 29, 21, 37, 26, 51, 21, + 3, 35, 13, 30, 29, 35, 36, 31, 55, 35, 2, 40, 21, 44, 28, + 40, 47, 44, 54, 40, 7, 2, 21, 7, 33, 2, 43, 7, 59, 2, + 5, 16, 22, 12, 27, 16, 44, 12, 49, 16, 6, 21, 12, 26, 28, + 21, 38, 26, 50, 21, 4, 35, 12, 30, 30, 35, 37, 31, 56, 35, + 3, 40, 22, 44, 29, 40, 36, 36, 55, 40, 8, 2, 20, 7, 34, + 2, 42, 7, 59, 3, 4, 16, 21, 12, 26, 16, 43, 12, 48, 16, + 5, 21, 13, 26, 27, 21, 39, 26, 49, 21, 5, 35, 12, 31, 31, + 35, 38, 31, 57, 35, 4, 40, 23, 44, 30, 40, 37, 36, 56, 40, + 9, 2, 19, 7, 35, 2, 41, 7, 58, 3, 3, 16, 20, 12, 25, + 16, 42, 12, 48, 17, 4, 21, 14, 26, 26, 21, 40, 26, 48, 21, + 6, 35, 13, 31, 32, 35, 39, 31, 58, 35, 5, 40, 12, 36, 31, + 40, 38, 36, 57, 40, 10, 2, 18, 7, 35, 3, 40, 7, 57, 3, + 2, 16, 19, 12, 24, 16, 41, 12, 49, 17, 3, 21, 15, 26, 25, + 21, 41, 26, 48, 22, 7, 35, 14, 31, 33, 35, 40, 31, 59, 35, + 6, 40, 13, 36, 32, 40, 39, 36, 58, 40, 11, 2, 17, 7, 34, + 3, 39, 7, 56, 3, 1, 16, 18, 12, 24, 17, 40, 12, 50, 17, + 2, 21, 16, 26, 24, 21, 42, 26, 49, 22, 8, 35, 15, 31, 34, + 35, 41, 31, 48, 27, 7, 40, 14, 36, 33, 40, 40, 36, 59, 40, + 11, 3, 16, 7, 33, 3, 38, 7, 55, 3, 0, 16, 17, 12, 25, + 17, 39, 12, 51, 17, 1, 21, 17, 26, 24, 22, 43, 26, 50, 22, + 9, 35, 16, 31, 35, 35, 42, 31, 49, 27, 8, 40, 15, 36, 34, + 40, 41, 36, 59, 41, 10, 3, 15, 7, 32, 3, 37, 7, 54, 3, + 0, 17, 16, 12, 26, 17, 38, 12, 52, 17, 0, 21, 18, 26, 25, + 22, 44, 26, 51, 22, 10, 35, 17, 31, 24, 27, 43, 31, 50, 27, + 9, 40, 16, 36, 35, 40, 42, 36, 58, 41, 9, 3, 14, 7, 31, + 3, 36, 7, 53, 3, 1, 17, 15, 12, 27, 17, 37, 12, 53, 17, + 0, 22, 19, 26, 26, 22, 45, 26, 52, 22, 11, 35, 18, 31, 25, + 27, 44, 31, 51, 27, 10, 40, 17, 36, 35, 41, 43, 36, 57, 41, + 8, 3, 13, 7, 30, 3, 36, 8, 52, 3, 2, 17, 14, 12, 28, + 17, 36, 12, 54, 17, 1, 22, 20, 26, 27, 22, 46, 26, 53, 22, + 0, 27, 19, 31, 26, 27, 45, 31, 52, 27, 11, 40, 18, 36, 34, + 41, 44, 36, 56, 41, 7, 3, 12, 7, 29, 3, 37, 8, 51, 3, + 3, 17, 13, 12, 29, 17, 36, 13, 55, 17, 2, 22, 21, 26, 28, + 22, 47, 26, 54, 22, 1, 27, 20, 31, 27, 27, 46, 31, 53, 27, + 11, 41, 19, 36, 33, 41, 45, 36, 55, 41, 6, 3, 12, 8, 28, + 3, 38, 8, 50, 3, 4, 17, 12, 12, 30, 17, 37, 13, 56, 17, + 3, 22, 22, 26, 29, 22, 36, 18, 55, 22, 2, 27, 21, 31, 28, + 27, 47, 31, 54, 27, 10, 41, 20, 36, 32, 41, 46, 36, 54, 41, + 5, 3, 13, 8, 27, 3, 39, 8, 49, 3, 5, 17, 12, 13, 31, + 17, 38, 13, 57, 17, 4, 22, 23, 26, 30, 22, 37, 18, 56, 22, + 3, 27, 22, 31, 29, 27, 47, 32, 55, 27, 9, 41, 21, 36, 31, + 41, 47, 36, 53, 41, 4, 3, 14, 8, 26, 3, 40, 8, 48, 3, + 6, 17, 13, 13, 32, 17, 39, 13, 58, 17, 5, 22, 12, 18, 31, + 22, 38, 18, 57, 22, 4, 27, 23, 31, 30, 27, 46, 32, 56, 27, + 8, 41, 22, 36, 30, 41, 47, 37, 52, 41, 3, 3, 15, 8, 25, + 3, 41, 8, 48, 4, 7, 17, 14, 13, 33, 17, 40, 13, 59, 17, + 6, 22, 13, 18, 32, 22, 39, 18, 58, 22, 5, 27, 23, 32, 31, + 27, 45, 32, 57, 27, 7, 41, 23, 36, 29, 41, 46, 37, 51, 41, + 2, 3, 16, 8, 24, 3, 42, 8, 49, 4, 8, 17, 15, 13, 34, + 17, 41, 13, 48, 9, 7, 22, 14, 18, 33, 22, 40, 18, 59, 22, + 6, 27, 22, 32, 32, 27, 44, 32, 58, 27, 6, 41, 23, 37, 28, + 41, 45, 37, 50, 41, 1, 3, 17, 8, 24, 4, 43, 8, 50, 4, + 9, 17, 16, 13, 35, 17, 42, 13, 49, 9, 8, 22, 15, 18, 34, + 22, 41, 18, 59, 23, 7, 27, 21, 32, 33, 27, 43, 32, 59, 27, + 5, 41, 22, 37, 27, 41, 44, 37, 49, 41, 0, 3, 18, 8, 25, + 4, 44, 8, 51, 4, 10, 17, 17, 13, 24, 9, 43, 13, 50, 9, + 9, 22, 16, 18, 35, 22, 42, 18, 58, 23, 8, 27, 20, 32, 34, + 27, 42, 32, 59, 28, 4, 41, 21, 37, 26, 41, 43, 37, 48, 41, + 0, 4, 19, 8, 26, 4, 45, 8, 52, 4, 11, 17, 18, 13, 25, + 9, 44, 13, 51, 9, 10, 22, 17, 18, 35, 23, 43, 18, 57, 23, + 9, 27, 19, 32, 35, 27, 41, 32, 58, 28, 3, 41, 20, 37, 25, + 41, 42, 37, 48, 42, 1, 4, 20, 8, 27, 4, 46, 8, 53, 4, + 0, 9, 19, 13, 26, 9, 45, 13, 52, 9, 11, 22, 18, 18, 34, + 23, 44, 18, 56, 23, 10, 27, 18, 32, 35, 28, 40, 32, 57, 28, + 2, 41, 19, 37, 24, 41, 41, 37, 49, 42, 2, 4, 21, 8, 28, + 4, 47, 8, 54, 4, 1, 9, 20, 13, 27, 9, 46, 13, 53, 9, + 11, 23, 19, 18, 33, 23, 45, 18, 55, 23, 11, 27, 17, 32, 34, + 28, 39, 32, 56, 28, 1, 41, 18, 37, 24, 42, 40, 37, 50, 42, + 3, 4, 22, 8, 29, 4, 36, 0, 55, 4, 2, 9, 21, 13, 28, + 9, 47, 13, 54, 9, 10, 23, 20, 18, 32, 23, 46, 18, 54, 23, + 11, 28, 16, 32, 33, 28, 38, 32, 55, 28, 0, 41, 17, 37, 25, + 42, 39, 37, 51, 42, 4, 4, 23, 8, 30, 4, 37, 0, 56, 4, + 3, 9, 22, 13, 29, 9, 47, 14, 55, 9, 9, 23, 21, 18, 31, + 23, 47, 18, 53, 23, 10, 28, 15, 32, 32, 28, 37, 32, 54, 28, + 0, 42, 16, 37, 26, 42, 38, 37, 52, 42, 5, 4, 12, 0, 31, + 4, 38, 0, 57, 4, 4, 9, 23, 13, 30, 9, 46, 14, 56, 9, + 8, 23, 22, 18, 30, 23, 47, 19, 52, 23, 9, 28, 14, 32, 31, + 28, 36, 32, 53, 28, 1, 42, 15, 37, 27, 42, 37, 37, 53, 42, + 6, 4, 13, 0, 32, 4, 39, 0, 58, 4, 5, 9, 23, 14, 31, + 9, 45, 14, 57, 9, 7, 23, 23, 18, 29, 23, 46, 19, 51, 23, + 8, 28, 13, 32, 30, 28, 36, 33, 52, 28, 2, 42, 14, 37, 28, + 42, 36, 37, 54, 42, 7, 4, 14, 0, 33, 4, 40, 0, 59, 4, + 6, 9, 22, 14, 32, 9, 44, 14, 58, 9, 6, 23, 23, 19, 28, + 23, 45, 19, 50, 23, 7, 28, 12, 32, 29, 28, 37, 33, 51, 28, + 3, 42, 13, 37, 29, 42, 36, 38, 55, 42, 8, 4, 15, 0, 34, + 4, 41, 0, 59, 5, 7, 9, 21, 14, 33, 9, 43, 14, 59, 9, + 5, 23, 22, 19, 27, 23, 44, 19, 49, 23, 6, 28, 12, 33, 28, + 28, 38, 33, 50, 28, 4, 42, 12, 37, 30, 42, 37, 38, 56, 42, + 9, 4, 16, 0, 35, 4, 42, 0, 58, 5, 8, 9, 20, 14, 34, + 9, 42, 14, 59, 10, 4, 23, 21, 19, 26, 23, 43, 19, 48, 23, + 5, 28, 13, 33, 27, 28, 39, 33, 49, 28, 5, 42, 12, 38, 31, + 42, 38, 38, 57, 42, 10, 4, 17, 0, 35, 5, 43, 0, 57, 5, + 9, 9, 19, 14, 35, 9, 41, 14, 58, 10, 3, 23, 20, 19, 25, + 23, 42, 19, 48, 24, 4, 28, 14, 33, 26, 28, 40, 33, 48, 28, + 6, 42, 13, 38, 32, 42, 39, 38, 58, 42, 11, 4, 18, 0, 34, + 5, 44, 0, 56, 5, 10, 9, 18, 14, 35, 10, 40, 14, 57, 10, + 2, 23, 19, 19, 24, 23, 41, 19, 49, 24, 3, 28, 15, 33, 25, + 28, 41, 33, 48, 29, 7, 42, 14, 38, 33, 42, 40, 38, 59, 42, + 11, 5, 19, 0, 33, 5, 45, 0, 55, 5, 11, 9, 17, 14, 34, + 10, 39, 14, 56, 10, 1, 23, 18, 19, 24, 24, 40, 19, 50, 24, + 2, 28, 16, 33, 24, 28, 42, 33, 49, 29, 8, 42, 15, 38, 34, + 42, 41, 38, 59, 43, 10, 5, 20, 0, 32, 5, 46, 0, 54, 5, + 11, 10, 16, 14, 33, 10, 38, 14, 55, 10, 0, 23, 17, 19, 25, + 24, 39, 19, 51, 24, 1, 28, 17, 33, 24, 29, 43, 33, 50, 29, + 9, 42, 16, 38, 35, 42, 42, 38, 58, 43, 9, 5, 21, 0, 31, + 5, 47, 0, 53, 5, 10, 10, 15, 14, 32, 10, 37, 14, 54, 10, + 0, 24, 16, 19, 26, 24, 38, 19, 52, 24, 0, 28, 18, 33, 25, + 29, 44, 33, 51, 29, 10, 42, 17, 38, 35, 43, 43, 38, 57, 43, + 8, 5, 22, 0, 30, 5, 47, 1, 52, 5, 9, 10, 14, 14, 31, + 10, 36, 14, 53, 10, 1, 24, 15, 19, 27, 24, 37, 19, 53, 24, + 0, 29, 19, 33, 26, 29, 45, 33, 52, 29, 11, 42, 18, 38, 34, + 43, 44, 38, 56, 43, 7, 5, 23, 0, 29, 5, 46, 1, 51, 5, + 8, 10, 13, 14, 30, 10, 36, 15, 52, 10, 2, 24, 14, 19, 28, + 24, 36, 19, 54, 24, 1, 29, 20, 33, 27, 29, 46, 33, 53, 29, + 11, 43, 19, 38, 33, 43, 45, 38, 55, 43, 6, 5, 23, 1, 28, + 5, 45, 1, 50, 5, 7, 10, 12, 14, 29, 10, 37, 15, 51, 10, + 3, 24, 13, 19, 29, 24, 36, 20, 55, 24, 2, 29, 21, 33, 28, + 29, 47, 33, 54, 29, 10, 43, 20, 38, 32, 43, 46, 38, 54, 43, + 5, 5, 22, 1, 27, 5, 44, 1, 49, 5, 6, 10, 12, 15, 28, + 10, 38, 15, 50, 10, 4, 24, 12, 19, 30, 24, 37, 20, 56, 24, + 3, 29, 22, 33, 29, 29, 47, 34, 55, 29, 9, 43, 21, 38, 31, + 43, 47, 38, 53, 43, 4, 5, 21, 1, 26, 5, 43, 1, 48, 5, + 5, 10, 13, 15, 27, 10, 39, 15, 49, 10, 5, 24, 12, 20, 31, + 24, 38, 20, 57, 24, 4, 29, 23, 33, 30, 29, 46, 34, 56, 29, + 8, 43, 22, 38, 30, 43, 47, 39, 52, 43, 3, 5, 20, 1, 25, + 5, 42, 1, 48, 6, 4, 10, 14, 15, 26, 10, 40, 15, 48, 10, + 6, 24, 13, 20, 32, 24, 39, 20, 58, 24, 5, 29, 23, 34, 31, + 29, 45, 34, 57, 29, 7, 43, 23, 38, 29, 43, 46, 39, 51, 43, + 2, 5, 19, 1, 24, 5, 41, 1, 49, 6, 3, 10, 15, 15, 25, + 10, 41, 15, 48, 11, 7, 24, 14, 20, 33, 24, 40, 20, 59, 24, + 6, 29, 22, 34, 32, 29, 44, 34, 58, 29, 6, 43, 23, 39, 28, + 43, 45, 39, 50, 43, 1, 5, 18, 1, 24, 6, 40, 1, 50, 6, + 2, 10, 16, 15, 24, 10, 42, 15, 49, 11, 8, 24, 15, 20, 34, + 24, 41, 20, 59, 25, 7, 29, 21, 34, 33, 29, 43, 34, 59, 29, + 5, 43, 22, 39, 27, 43, 44, 39, 49, 43, 0, 5, 17, 1, 25, + 6, 39, 1, 51, 6, 1, 10, 17, 15, 24, 11, 43, 15, 50, 11, + 9, 24, 16, 20, 35, 24, 42, 20, 58, 25, 8, 29, 20, 34, 34, + 29, 42, 34, 59, 30, 4, 43, 21, 39, 26, 43, 43, 39, 48, 43, + 0, 6, 16, 1, 26, 6, 38, 1, 52, 6, 0, 10, 18, 15, 25, + 11, 44, 15, 51, 11, 10, 24, 17, 20, 35, 25, 43, 20, 57, 25, + 9, 29, 19, 34, 35, 29, 41, 34, 58, 30, 3, 43, 20, 39, 25, + 43, 42, 39, 48, 44, 1, 6, 15, 1, 27, 6, 37, 1, 53, 6, + 0, 11, 19, 15, 26, 11, 45, 15, 52, 11, 11, 24, 18, 20, 34, + 25, 44, 20, 56, 25, 10, 29, 18, 34, 35, 30, 40, 34, 57, 30, + 2, 43, 19, 39, 24, 43, 41, 39, 49, 44, 2, 6, 14, 1, 28, + 6, 36, 1, 54, 6, 1, 11, 20, 15, 27, 11, 46, 15, 53, 11, + 11, 25, 19, 20, 33, 25, 45, 20, 55, 25, 11, 29, 17, 34, 34, + 30, 39, 34, 56, 30, 1, 43, 18, 39, 24, 44, 40, 39, 50, 44, + 3, 6, 13, 1, 29, 6, 36, 2, 55, 6, 2, 11, 21, 15, 28, + 11, 47, 15, 54, 11, 10, 25, 20, 20, 32, 25, 46, 20, 54, 25, + 11, 30, 16, 34, 33, 30, 38, 34, 55, 30, 0, 43, 17, 39, 25, + 44, 39, 39, 51, 44, 4, 6, 12, 1, 30, 6, 37, 2, 56, 6, + 3, 11, 22, 15, 29, 11, 47, 16, 55, 11, 9, 25, 21, 20, 31, + 25, 47, 20, 53, 25, 10, 30, 15, 34, 32, 30, 37, 34, 54, 30, + 0, 44, 16, 39, 26, 44, 38, 39, 52, 44, 5, 6, 12, 2, 31, + 6, 38, 2, 57, 6, 4, 11, 23, 15, 30, 11, 46, 16, 56, 11, + 8, 25, 22, 20, 30, 25, 47, 21, 52, 25, 9, 30, 14, 34, 31, + 30, 36, 34, 53, 30, 1, 44, 15, 39, 27, 44, 37, 39, 53, 44, + 6, 6, 13, 2, 32, 6, 39, 2, 58, 6, 5, 11, 23, 16, 31, + 11, 45, 16, 57, 11, 7, 25, 23, 20, 29, 25, 46, 21, 51, 25, + 8, 30, 13, 34, 30, 30, 36, 35, 52, 30, 2, 44, 14, 39, 28, + 44, 36, 39, 54, 44, 7, 6, 14, 2, 33, 6, 40, 2, 59, 6, + 6, 11, 22, 16, 32, 11, 44, 16, 58, 11, 6, 25, 23, 21, 28, + 25, 45, 21, 50, 25, 7, 30, 12, 34, 29, 30, 37, 35, 51, 30, + 3, 44, 13, 39, 29, 44, 36, 40, 55, 44, 8, 6, 15, 2, 34, + 6, 41, 2, 59, 7, 7, 11, 21, 16, 33, 11, 43, 16, 59, 11, + 5, 25, 22, 21, 27, 25, 44, 21, 49, 25, 6, 30, 12, 35, 28, + 30, 38, 35, 50, 30, 4, 44, 12, 39, 30, 44, 37, 40, 56, 44, + 9, 6, 16, 2, 35, 6, 42, 2, 58, 7, 8, 11, 20, 16, 34, + 11, 42, 16, 59, 12, 4, 25, 21, 21, 26, 25, 43, 21, 48, 25, + 5, 30, 13, 35, 27, 30, 39, 35, 49, 30, 5, 44, 12, 40, 31, + 44, 38, 40, 57, 44, 10, 6, 17, 2, 35, 7, 43, 2, 57, 7, + 9, 11, 19, 16, 35, 11, 41, 16, 58, 12, 3, 25, 20, 21, 25, + 25, 42, 21, 48, 26, 4, 30, 14, 35, 26, 30, 40, 35, 48, 30, + 6, 44, 13, 40, 32, 44, 39, 40, 58, 44, 11, 6, 18, 2, 34, + 7, 44, 2, 56, 7, 10, 11, 18, 16, 35, 12, 40, 16, 57, 12, + 2, 25, 19, 21, 24, 25, 41, 21, 49, 26, 3, 30, 15, 35, 25, + 30, 41, 35, 48, 31, 7, 44, 14, 40, 33, 44, 40, 40, 59, 44, + 11, 7, 19, 2, 33, 7, 45, 2, 55, 7, 11, 11, 17, 16, 34, + 12, 39, 16, 56, 12, 1, 25, 18, 21, 24, 26, 40, 21, 50, 26, + 2, 30, 16, 35, 24, 30, 42, 35, 49, 31, 8, 44, 15, 40, 34, + 44, 41, 40, 48, 36, 10, 7, 20, 2, 32, 7, 46, 2, 54, 7, + 11, 12, 16, 16, 33, 12, 38, 16, 55, 12, 0, 25, 17, 21, 25, + 26, 39, 21, 51, 26, 1, 30, 17, 35, 24, 31, 43, 35, 50, 31, + 9, 44, 16, 40, 35, 44, 42, 40, 49, 36, 9, 7, 21, 2, 31, + 7, 47, 2, 53, 7, 10, 12, 15, 16, 32, 12, 37, 16, 54, 12, + 0, 26, 16, 21, 26, 26, 38, 21, 52, 26, 0, 30, 18, 35, 25, + 31, 44, 35, 51, 31, 10, 44, 17, 40, 24, 36, 43, 40, 50, 36, + 8, 7, 22, 2, 30, 7, 47, 3, 52, 7, 9, 12, 14, 16, 31, + 12, 36, 16, 53, 12, 1, 26, 15, 21, 27, 26, 37, 21, 53, 26, + 0, 31, 19, 35, 26, 31, 45, 35, 52, 31, 11, 44, 18, 40, 25, + 36, 44, 40, 51, 36, 7, 7, 23, 2, 29, 7, 46, 3, 51, 7, + 8, 12, 13, 16, 30, 12, 36, 17, 52, 12, 2, 26, 14, 21, 28, + 26, 36, 21, 54, 26, 1, 31, 20, 35, 27, 31, 46, 35, 53, 31, + 0, 36, 19, 40, 26, 36, 45, 40, 52, 36, 6, 7, 23, 3, 28, + 7, 45, 3, 50, 7, 7, 12, 12, 16, 29, 12, 37, 17, 51, 12, + 3, 26, 13, 21, 29, 26, 36, 22, 55, 26, 2, 31, 21, 35, 28, + 31, 47, 35, 54, 31, 1, 36, 20, 40, 27, 36, 46, 40, 53, 36, + 5, 7, 22, 3, 27, 7, 44, 3, 49, 7, 6, 12, 12, 17, 28, + 12, 38, 17, 50, 12, 4, 26, 12, 21, 30, 26, 37, 22, 56, 26, + 3, 31, 22, 35, 29, 31, 36, 27, 55, 31, 2, 36, 21, 40, 28, + 36, 47, 40, 54, 36, 4, 7, 21, 3, 26, 7, 43, 3, 48, 7, + 5, 12, 13, 17, 27, 12, 39, 17, 49, 12, 5, 26, 12, 22, 31, + 26, 38, 22, 57, 26, 4, 31, 23, 35, 30, 31, 37, 27, 56, 31, + 3, 36, 22, 40, 29, 36, 47, 41, 55, 36, 3, 7, 20, 3, 25, + 7, 42, 3, 48, 8, 4, 12, 14, 17, 26, 12, 40, 17, 48, 12, + 6, 26, 13, 22, 32, 26, 39, 22, 58, 26, 5, 31, 12, 27, 31, + 31, 38, 27, 57, 31, 4, 36, 23, 40, 30, 36, 46, 41, 56, 36, + 2, 7, 19, 3, 24, 7, 41, 3, 49, 8, 3, 12, 15, 17, 25, + 12, 41, 17, 48, 13, 7, 26, 14, 22, 33, 26, 40, 22, 59, 26, + 6, 31, 13, 27, 32, 31, 39, 27, 58, 31, 5, 36, 23, 41, 31, + 36, 45, 41, 57, 36, 1, 7, 18, 3, 24, 8, 40, 3, 50, 8, + 2, 12, 16, 17, 24, 12, 42, 17, 49, 13, 8, 26, 15, 22, 34, + 26, 41, 22, 48, 18, 7, 31, 14, 27, 33, 31, 40, 27, 59, 31, + 6, 36, 22, 41, 32, 36, 44, 41, 58, 36, 0, 7, 17, 3, 25, + 8, 39, 3, 51, 8, 1, 12, 17, 17, 24, 13, 43, 17, 50, 13, + 9, 26, 16, 22, 35, 26, 42, 22, 49, 18, 8, 31, 15, 27, 34, + 31, 41, 27, 59, 32, 7, 36, 21, 41, 33, 36, 43, 41, 59, 36, + 0, 8, 16, 3, 26, 8, 38, 3, 52, 8, 0, 12, 18, 17, 25, + 13, 44, 17, 51, 13, 10, 26, 17, 22, 24, 18, 43, 22, 50, 18, + 9, 31, 16, 27, 35, 31, 42, 27, 58, 32, 8, 36, 20, 41, 34, + 36, 42, 41, 59, 37, 1, 8, 15, 3, 27, 8, 37, 3, 53, 8, + 0, 13, 19, 17, 26, 13, 45, 17, 52, 13, 11, 26, 18, 22, 25, + 18, 44, 22, 51, 18, 10, 31, 17, 27, 35, 32, 43, 27, 57, 32, + 9, 36, 19, 41, 35, 36, 41, 41, 58, 37, 2, 8, 14, 3, 28, + 8, 36, 3, 54, 8, 1, 13, 20, 17, 27, 13, 46, 17, 53, 13, + 0, 18, 19, 22, 26, 18, 45, 22, 52, 18, 11, 31, 18, 27, 34, + 32, 44, 27, 56, 32, 10, 36, 18, 41, 35, 37, 40, 41, 57, 37, + 3, 8, 13, 3, 29, 8, 36, 4, 55, 8, 2, 13, 21, 17, 28, + 13, 47, 17, 54, 13, 1, 18, 20, 22, 27, 18, 46, 22, 53, 18, + 11, 32, 19, 27, 33, 32, 45, 27, 55, 32, 11, 36, 17, 41, 34, + 37, 39, 41, 56, 37, 4, 8, 12, 3, 30, 8, 37, 4, 56, 8, + 3, 13, 22, 17, 29, 13, 36, 9, 55, 13, 2, 18, 21, 22, 28, + 18, 47, 22, 54, 18, 10, 32, 20, 27, 32, 32, 46, 27, 54, 32, + 11, 37, 16, 41, 33, 37, 38, 41, 55, 37, 5, 8, 12, 4, 31, + 8, 38, 4, 57, 8, 4, 13, 23, 17, 30, 13, 37, 9, 56, 13, + 3, 18, 22, 22, 29, 18, 47, 23, 55, 18, 9, 32, 21, 27, 31, + 32, 47, 27, 53, 32, 10, 37, 15, 41, 32, 37, 37, 41, 54, 37, + 6, 8, 13, 4, 32, 8, 39, 4, 58, 8, 5, 13, 12, 9, 31, + 13, 38, 9, 57, 13, 4, 18, 23, 22, 30, 18, 46, 23, 56, 18, + 8, 32, 22, 27, 30, 32, 47, 28, 52, 32, 9, 37, 14, 41, 31, + 37, 36, 41, 53, 37, 7, 8, 14, 4, 33, 8, 40, 4, 59, 8, + 6, 13, 13, 9, 32, 13, 39, 9, 58, 13, 5, 18, 23, 23, 31, + 18, 45, 23, 57, 18, 7, 32, 23, 27, 29, 32, 46, 28, 51, 32, + 8, 37, 13, 41, 30, 37, 36, 42, 52, 37, 8, 8, 15, 4, 34, + 8, 41, 4, 48, 0, 7, 13, 14, 9, 33, 13, 40, 9, 59, 13, + 6, 18, 22, 23, 32, 18, 44, 23, 58, 18, 6, 32, 23, 28, 28, + 32, 45, 28, 50, 32, 7, 37, 12, 41, 29, 37, 37, 42, 51, 37, + 9, 8, 16, 4, 35, 8, 42, 4, 49, 0, 8, 13, 15, 9, 34, + 13, 41, 9, 59, 14, 7, 18, 21, 23, 33, 18, 43, 23, 59, 18, + 5, 32, 22, 28, 27, 32, 44, 28, 49, 32, 6, 37, 12, 42, 28, + 37, 38, 42, 50, 37, 10, 8, 17, 4, 24, 0, 43, 4, 50, 0, + 9, 13, 16, 9, 35, 13, 42, 9, 58, 14, 8, 18, 20, 23, 34, + 18, 42, 23, 59, 19, 4, 32, 21, 28, 26, 32, 43, 28, 48, 32, + 5, 37, 13, 42, 27, 37, 39, 42, 49, 37, 11, 8, 18, 4, 25, + 0, 44, 4, 51, 0, 10, 13, 17, 9, 35, 14, 43, 9, 57, 14, + 9, 18, 19, 23, 35, 18, 41, 23, 58, 19, 3, 32, 20, 28, 25, + 32, 42, 28, 48, 33, 4, 37, 14, 42, 26, 37, 40, 42, 48, 37, +}; + +static const uint8_t hq_tab_05[] = { + 0, 0, 25, 4, 34, 0, 59, 4, 68, 0, 13, 13, 22, 9, 47, + 13, 56, 9, 78, 14, 10, 18, 28, 23, 44, 18, 58, 23, 78, 18, + 8, 32, 31, 28, 38, 32, 61, 28, 68, 32, 11, 37, 18, 41, 41, + 37, 48, 41, 71, 37, 1, 0, 26, 4, 35, 0, 60, 4, 69, 0, + 14, 13, 23, 9, 47, 14, 57, 9, 77, 14, 11, 18, 27, 23, 45, + 18, 57, 23, 79, 18, 7, 32, 30, 28, 37, 32, 60, 28, 67, 32, + 10, 37, 17, 41, 40, 37, 48, 42, 70, 37, 2, 0, 27, 4, 36, + 0, 61, 4, 70, 0, 15, 13, 24, 9, 46, 14, 58, 9, 76, 14, + 12, 18, 26, 23, 46, 18, 56, 23, 79, 19, 6, 32, 29, 28, 36, + 32, 59, 28, 66, 32, 9, 37, 16, 41, 39, 37, 49, 42, 69, 37, + 3, 0, 28, 4, 37, 0, 62, 4, 71, 0, 15, 14, 25, 9, 45, + 14, 59, 9, 75, 14, 13, 18, 25, 23, 47, 18, 55, 23, 78, 19, + 5, 32, 28, 28, 35, 32, 58, 28, 65, 32, 8, 37, 16, 42, 38, + 37, 50, 42, 68, 37, 4, 0, 29, 4, 38, 0, 63, 4, 72, 0, + 14, 14, 26, 9, 44, 14, 60, 9, 74, 14, 14, 18, 24, 23, 47, + 19, 54, 23, 77, 19, 4, 32, 27, 28, 34, 32, 57, 28, 64, 32, + 7, 37, 17, 42, 37, 37, 51, 42, 67, 37, 5, 0, 30, 4, 39, + 0, 63, 5, 73, 0, 13, 14, 27, 9, 43, 14, 61, 9, 73, 14, + 15, 18, 23, 23, 46, 19, 53, 23, 76, 19, 3, 32, 26, 28, 33, + 32, 56, 28, 64, 33, 6, 37, 18, 42, 36, 37, 52, 42, 66, 37, + 6, 0, 31, 4, 40, 0, 62, 5, 74, 0, 12, 14, 28, 9, 42, + 14, 62, 9, 72, 14, 15, 19, 22, 23, 45, 19, 52, 23, 75, 19, + 2, 32, 25, 28, 32, 32, 55, 28, 65, 33, 5, 37, 19, 42, 35, + 37, 53, 42, 65, 37, 7, 0, 31, 5, 41, 0, 61, 5, 75, 0, + 11, 14, 29, 9, 41, 14, 63, 9, 71, 14, 14, 19, 21, 23, 44, + 19, 51, 23, 74, 19, 1, 32, 24, 28, 32, 33, 54, 28, 66, 33, + 4, 37, 20, 42, 34, 37, 54, 42, 64, 37, 8, 0, 30, 5, 42, + 0, 60, 5, 76, 0, 10, 14, 30, 9, 40, 14, 63, 10, 70, 14, + 13, 19, 20, 23, 43, 19, 50, 23, 73, 19, 0, 32, 23, 28, 33, + 33, 53, 28, 67, 33, 3, 37, 21, 42, 33, 37, 55, 42, 64, 38, + 9, 0, 29, 5, 43, 0, 59, 5, 77, 0, 9, 14, 31, 9, 39, + 14, 62, 10, 69, 14, 12, 19, 19, 23, 42, 19, 49, 23, 72, 19, + 0, 33, 22, 28, 34, 33, 52, 28, 68, 33, 2, 37, 22, 42, 32, + 37, 56, 42, 65, 38, 10, 0, 28, 5, 44, 0, 58, 5, 78, 0, + 8, 14, 31, 10, 38, 14, 61, 10, 68, 14, 11, 19, 18, 23, 41, + 19, 48, 23, 71, 19, 1, 33, 21, 28, 35, 33, 51, 28, 69, 33, + 1, 37, 23, 42, 32, 38, 57, 42, 66, 38, 11, 0, 27, 5, 45, + 0, 57, 5, 79, 0, 7, 14, 30, 10, 37, 14, 60, 10, 67, 14, + 10, 19, 17, 23, 40, 19, 48, 24, 70, 19, 2, 33, 20, 28, 36, + 33, 50, 28, 70, 33, 0, 37, 24, 42, 33, 38, 58, 42, 67, 38, + 12, 0, 26, 5, 46, 0, 56, 5, 79, 1, 6, 14, 29, 10, 36, + 14, 59, 10, 66, 14, 9, 19, 16, 23, 39, 19, 49, 24, 69, 19, + 3, 33, 19, 28, 37, 33, 49, 28, 71, 33, 0, 38, 25, 42, 34, + 38, 59, 42, 68, 38, 13, 0, 25, 5, 47, 0, 55, 5, 78, 1, + 5, 14, 28, 10, 35, 14, 58, 10, 65, 14, 8, 19, 16, 24, 38, + 19, 50, 24, 68, 19, 4, 33, 18, 28, 38, 33, 48, 28, 72, 33, + 1, 38, 26, 42, 35, 38, 60, 42, 69, 38, 14, 0, 24, 5, 47, + 1, 54, 5, 77, 1, 4, 14, 27, 10, 34, 14, 57, 10, 64, 14, + 7, 19, 17, 24, 37, 19, 51, 24, 67, 19, 5, 33, 17, 28, 39, + 33, 48, 29, 73, 33, 2, 38, 27, 42, 36, 38, 61, 42, 70, 38, + 15, 0, 23, 5, 46, 1, 53, 5, 76, 1, 3, 14, 26, 10, 33, + 14, 56, 10, 64, 15, 6, 19, 18, 24, 36, 19, 52, 24, 66, 19, + 6, 33, 16, 28, 40, 33, 49, 29, 74, 33, 3, 38, 28, 42, 37, + 38, 62, 42, 71, 38, 15, 1, 22, 5, 45, 1, 52, 5, 75, 1, + 2, 14, 25, 10, 32, 14, 55, 10, 65, 15, 5, 19, 19, 24, 35, + 19, 53, 24, 65, 19, 7, 33, 16, 29, 41, 33, 50, 29, 75, 33, + 4, 38, 29, 42, 38, 38, 63, 42, 72, 38, 14, 1, 21, 5, 44, + 1, 51, 5, 74, 1, 1, 14, 24, 10, 32, 15, 54, 10, 66, 15, + 4, 19, 20, 24, 34, 19, 54, 24, 64, 19, 8, 33, 17, 29, 42, + 33, 51, 29, 76, 33, 5, 38, 30, 42, 39, 38, 63, 43, 73, 38, + 13, 1, 20, 5, 43, 1, 50, 5, 73, 1, 0, 14, 23, 10, 33, + 15, 53, 10, 67, 15, 3, 19, 21, 24, 33, 19, 55, 24, 64, 20, + 9, 33, 18, 29, 43, 33, 52, 29, 77, 33, 6, 38, 31, 42, 40, + 38, 62, 43, 74, 38, 12, 1, 19, 5, 42, 1, 49, 5, 72, 1, + 0, 15, 22, 10, 34, 15, 52, 10, 68, 15, 2, 19, 22, 24, 32, + 19, 56, 24, 65, 20, 10, 33, 19, 29, 44, 33, 53, 29, 78, 33, + 7, 38, 31, 43, 41, 38, 61, 43, 75, 38, 11, 1, 18, 5, 41, + 1, 48, 5, 71, 1, 1, 15, 21, 10, 35, 15, 51, 10, 69, 15, + 1, 19, 23, 24, 32, 20, 57, 24, 66, 20, 11, 33, 20, 29, 45, + 33, 54, 29, 79, 33, 8, 38, 30, 43, 42, 38, 60, 43, 76, 38, + 10, 1, 17, 5, 40, 1, 48, 6, 70, 1, 2, 15, 20, 10, 36, + 15, 50, 10, 70, 15, 0, 19, 24, 24, 33, 20, 58, 24, 67, 20, + 12, 33, 21, 29, 46, 33, 55, 29, 79, 34, 9, 38, 29, 43, 43, + 38, 59, 43, 77, 38, 9, 1, 16, 5, 39, 1, 49, 6, 69, 1, + 3, 15, 19, 10, 37, 15, 49, 10, 71, 15, 0, 20, 25, 24, 34, + 20, 59, 24, 68, 20, 13, 33, 22, 29, 47, 33, 56, 29, 78, 34, + 10, 38, 28, 43, 44, 38, 58, 43, 78, 38, 8, 1, 16, 6, 38, + 1, 50, 6, 68, 1, 4, 15, 18, 10, 38, 15, 48, 10, 72, 15, + 1, 20, 26, 24, 35, 20, 60, 24, 69, 20, 14, 33, 23, 29, 47, + 34, 57, 29, 77, 34, 11, 38, 27, 43, 45, 38, 57, 43, 79, 38, + 7, 1, 17, 6, 37, 1, 51, 6, 67, 1, 5, 15, 17, 10, 39, + 15, 48, 11, 73, 15, 2, 20, 27, 24, 36, 20, 61, 24, 70, 20, + 15, 33, 24, 29, 46, 34, 58, 29, 76, 34, 12, 38, 26, 43, 46, + 38, 56, 43, 79, 39, 6, 1, 18, 6, 36, 1, 52, 6, 66, 1, + 6, 15, 16, 10, 40, 15, 49, 11, 74, 15, 3, 20, 28, 24, 37, + 20, 62, 24, 71, 20, 15, 34, 25, 29, 45, 34, 59, 29, 75, 34, + 13, 38, 25, 43, 47, 38, 55, 43, 78, 39, 5, 1, 19, 6, 35, + 1, 53, 6, 65, 1, 7, 15, 16, 11, 41, 15, 50, 11, 75, 15, + 4, 20, 29, 24, 38, 20, 63, 24, 72, 20, 14, 34, 26, 29, 44, + 34, 60, 29, 74, 34, 14, 38, 24, 43, 47, 39, 54, 43, 77, 39, + 4, 1, 20, 6, 34, 1, 54, 6, 64, 1, 8, 15, 17, 11, 42, + 15, 51, 11, 76, 15, 5, 20, 30, 24, 39, 20, 63, 25, 73, 20, + 13, 34, 27, 29, 43, 34, 61, 29, 73, 34, 15, 38, 23, 43, 46, + 39, 53, 43, 76, 39, 3, 1, 21, 6, 33, 1, 55, 6, 64, 2, + 9, 15, 18, 11, 43, 15, 52, 11, 77, 15, 6, 20, 31, 24, 40, + 20, 62, 25, 74, 20, 12, 34, 28, 29, 42, 34, 62, 29, 72, 34, + 15, 39, 22, 43, 45, 39, 52, 43, 75, 39, 2, 1, 22, 6, 32, + 1, 56, 6, 65, 2, 10, 15, 19, 11, 44, 15, 53, 11, 78, 15, + 7, 20, 31, 25, 41, 20, 61, 25, 75, 20, 11, 34, 29, 29, 41, + 34, 63, 29, 71, 34, 14, 39, 21, 43, 44, 39, 51, 43, 74, 39, + 1, 1, 23, 6, 32, 2, 57, 6, 66, 2, 11, 15, 20, 11, 45, + 15, 54, 11, 79, 15, 8, 20, 30, 25, 42, 20, 60, 25, 76, 20, + 10, 34, 30, 29, 40, 34, 63, 30, 70, 34, 13, 39, 20, 43, 43, + 39, 50, 43, 73, 39, 0, 1, 24, 6, 33, 2, 58, 6, 67, 2, + 12, 15, 21, 11, 46, 15, 55, 11, 79, 16, 9, 20, 29, 25, 43, + 20, 59, 25, 77, 20, 9, 34, 31, 29, 39, 34, 62, 30, 69, 34, + 12, 39, 19, 43, 42, 39, 49, 43, 72, 39, 0, 2, 25, 6, 34, + 2, 59, 6, 68, 2, 13, 15, 22, 11, 47, 15, 56, 11, 78, 16, + 10, 20, 28, 25, 44, 20, 58, 25, 78, 20, 8, 34, 31, 30, 38, + 34, 61, 30, 68, 34, 11, 39, 18, 43, 41, 39, 48, 43, 71, 39, + 1, 2, 26, 6, 35, 2, 60, 6, 69, 2, 14, 15, 23, 11, 47, + 16, 57, 11, 77, 16, 11, 20, 27, 25, 45, 20, 57, 25, 79, 20, + 7, 34, 30, 30, 37, 34, 60, 30, 67, 34, 10, 39, 17, 43, 40, + 39, 48, 44, 70, 39, 2, 2, 27, 6, 36, 2, 61, 6, 70, 2, + 15, 15, 24, 11, 46, 16, 58, 11, 76, 16, 12, 20, 26, 25, 46, + 20, 56, 25, 79, 21, 6, 34, 29, 30, 36, 34, 59, 30, 66, 34, + 9, 39, 16, 43, 39, 39, 49, 44, 69, 39, 3, 2, 28, 6, 37, + 2, 62, 6, 71, 2, 15, 16, 25, 11, 45, 16, 59, 11, 75, 16, + 13, 20, 25, 25, 47, 20, 55, 25, 78, 21, 5, 34, 28, 30, 35, + 34, 58, 30, 65, 34, 8, 39, 16, 44, 38, 39, 50, 44, 68, 39, + 4, 2, 29, 6, 38, 2, 63, 6, 72, 2, 14, 16, 26, 11, 44, + 16, 60, 11, 74, 16, 14, 20, 24, 25, 47, 21, 54, 25, 77, 21, + 4, 34, 27, 30, 34, 34, 57, 30, 64, 34, 7, 39, 17, 44, 37, + 39, 51, 44, 67, 39, 5, 2, 30, 6, 39, 2, 63, 7, 73, 2, + 13, 16, 27, 11, 43, 16, 61, 11, 73, 16, 15, 20, 23, 25, 46, + 21, 53, 25, 76, 21, 3, 34, 26, 30, 33, 34, 56, 30, 64, 35, + 6, 39, 18, 44, 36, 39, 52, 44, 66, 39, 6, 2, 31, 6, 40, + 2, 62, 7, 74, 2, 12, 16, 28, 11, 42, 16, 62, 11, 72, 16, + 15, 21, 22, 25, 45, 21, 52, 25, 75, 21, 2, 34, 25, 30, 32, + 34, 55, 30, 65, 35, 5, 39, 19, 44, 35, 39, 53, 44, 65, 39, + 7, 2, 31, 7, 41, 2, 61, 7, 75, 2, 11, 16, 29, 11, 41, + 16, 63, 11, 71, 16, 14, 21, 21, 25, 44, 21, 51, 25, 74, 21, + 1, 34, 24, 30, 32, 35, 54, 30, 66, 35, 4, 39, 20, 44, 34, + 39, 54, 44, 64, 39, 8, 2, 30, 7, 42, 2, 60, 7, 76, 2, + 10, 16, 30, 11, 40, 16, 63, 12, 70, 16, 13, 21, 20, 25, 43, + 21, 50, 25, 73, 21, 0, 34, 23, 30, 33, 35, 53, 30, 67, 35, + 3, 39, 21, 44, 33, 39, 55, 44, 64, 40, 9, 2, 29, 7, 43, + 2, 59, 7, 77, 2, 9, 16, 31, 11, 39, 16, 62, 12, 69, 16, + 12, 21, 19, 25, 42, 21, 49, 25, 72, 21, 0, 35, 22, 30, 34, + 35, 52, 30, 68, 35, 2, 39, 22, 44, 32, 39, 56, 44, 65, 40, + 10, 2, 28, 7, 44, 2, 58, 7, 78, 2, 8, 16, 31, 12, 38, + 16, 61, 12, 68, 16, 11, 21, 18, 25, 41, 21, 48, 25, 71, 21, + 1, 35, 21, 30, 35, 35, 51, 30, 69, 35, 1, 39, 23, 44, 32, + 40, 57, 44, 66, 40, 11, 2, 27, 7, 45, 2, 57, 7, 79, 2, + 7, 16, 30, 12, 37, 16, 60, 12, 67, 16, 10, 21, 17, 25, 40, + 21, 48, 26, 70, 21, 2, 35, 20, 30, 36, 35, 50, 30, 70, 35, + 0, 39, 24, 44, 33, 40, 58, 44, 67, 40, 12, 2, 26, 7, 46, + 2, 56, 7, 79, 3, 6, 16, 29, 12, 36, 16, 59, 12, 66, 16, + 9, 21, 16, 25, 39, 21, 49, 26, 69, 21, 3, 35, 19, 30, 37, + 35, 49, 30, 71, 35, 0, 40, 25, 44, 34, 40, 59, 44, 68, 40, + 13, 2, 25, 7, 47, 2, 55, 7, 78, 3, 5, 16, 28, 12, 35, + 16, 58, 12, 65, 16, 8, 21, 16, 26, 38, 21, 50, 26, 68, 21, + 4, 35, 18, 30, 38, 35, 48, 30, 72, 35, 1, 40, 26, 44, 35, + 40, 60, 44, 69, 40, 14, 2, 24, 7, 47, 3, 54, 7, 77, 3, + 4, 16, 27, 12, 34, 16, 57, 12, 64, 16, 7, 21, 17, 26, 37, + 21, 51, 26, 67, 21, 5, 35, 17, 30, 39, 35, 48, 31, 73, 35, + 2, 40, 27, 44, 36, 40, 61, 44, 70, 40, 15, 2, 23, 7, 46, + 3, 53, 7, 76, 3, 3, 16, 26, 12, 33, 16, 56, 12, 64, 17, + 6, 21, 18, 26, 36, 21, 52, 26, 66, 21, 6, 35, 16, 30, 40, + 35, 49, 31, 74, 35, 3, 40, 28, 44, 37, 40, 62, 44, 71, 40, + 15, 3, 22, 7, 45, 3, 52, 7, 75, 3, 2, 16, 25, 12, 32, + 16, 55, 12, 65, 17, 5, 21, 19, 26, 35, 21, 53, 26, 65, 21, + 7, 35, 16, 31, 41, 35, 50, 31, 75, 35, 4, 40, 29, 44, 38, + 40, 63, 44, 72, 40, 14, 3, 21, 7, 44, 3, 51, 7, 74, 3, + 1, 16, 24, 12, 32, 17, 54, 12, 66, 17, 4, 21, 20, 26, 34, + 21, 54, 26, 64, 21, 8, 35, 17, 31, 42, 35, 51, 31, 76, 35, + 5, 40, 30, 44, 39, 40, 48, 36, 73, 40, 13, 3, 20, 7, 43, + 3, 50, 7, 73, 3, 0, 16, 23, 12, 33, 17, 53, 12, 67, 17, + 3, 21, 21, 26, 33, 21, 55, 26, 64, 22, 9, 35, 18, 31, 43, + 35, 52, 31, 77, 35, 6, 40, 31, 44, 40, 40, 49, 36, 74, 40, + 12, 3, 19, 7, 42, 3, 49, 7, 72, 3, 0, 17, 22, 12, 34, + 17, 52, 12, 68, 17, 2, 21, 22, 26, 32, 21, 56, 26, 65, 22, + 10, 35, 19, 31, 44, 35, 53, 31, 78, 35, 7, 40, 16, 36, 41, + 40, 50, 36, 75, 40, 11, 3, 18, 7, 41, 3, 48, 7, 71, 3, + 1, 17, 21, 12, 35, 17, 51, 12, 69, 17, 1, 21, 23, 26, 32, + 22, 57, 26, 66, 22, 11, 35, 20, 31, 45, 35, 54, 31, 79, 35, + 8, 40, 17, 36, 42, 40, 51, 36, 76, 40, 10, 3, 17, 7, 40, + 3, 48, 8, 70, 3, 2, 17, 20, 12, 36, 17, 50, 12, 70, 17, + 0, 21, 24, 26, 33, 22, 58, 26, 67, 22, 12, 35, 21, 31, 46, + 35, 55, 31, 64, 27, 9, 40, 18, 36, 43, 40, 52, 36, 77, 40, + 9, 3, 16, 7, 39, 3, 49, 8, 69, 3, 3, 17, 19, 12, 37, + 17, 49, 12, 71, 17, 0, 22, 25, 26, 34, 22, 59, 26, 68, 22, + 13, 35, 22, 31, 47, 35, 56, 31, 65, 27, 10, 40, 19, 36, 44, + 40, 53, 36, 78, 40, 8, 3, 16, 8, 38, 3, 50, 8, 68, 3, + 4, 17, 18, 12, 38, 17, 48, 12, 72, 17, 1, 22, 26, 26, 35, + 22, 60, 26, 69, 22, 14, 35, 23, 31, 32, 27, 57, 31, 66, 27, + 11, 40, 20, 36, 45, 40, 54, 36, 79, 40, 7, 3, 17, 8, 37, + 3, 51, 8, 67, 3, 5, 17, 17, 12, 39, 17, 48, 13, 73, 17, + 2, 22, 27, 26, 36, 22, 61, 26, 70, 22, 15, 35, 24, 31, 33, + 27, 58, 31, 67, 27, 12, 40, 21, 36, 46, 40, 55, 36, 79, 41, + 6, 3, 18, 8, 36, 3, 52, 8, 66, 3, 6, 17, 16, 12, 40, + 17, 49, 13, 74, 17, 3, 22, 28, 26, 37, 22, 62, 26, 71, 22, + 0, 27, 25, 31, 34, 27, 59, 31, 68, 27, 13, 40, 22, 36, 47, + 40, 56, 36, 78, 41, 5, 3, 19, 8, 35, 3, 53, 8, 65, 3, + 7, 17, 16, 13, 41, 17, 50, 13, 75, 17, 4, 22, 29, 26, 38, + 22, 63, 26, 72, 22, 1, 27, 26, 31, 35, 27, 60, 31, 69, 27, + 14, 40, 23, 36, 47, 41, 57, 36, 77, 41, 4, 3, 20, 8, 34, + 3, 54, 8, 64, 3, 8, 17, 17, 13, 42, 17, 51, 13, 76, 17, + 5, 22, 30, 26, 39, 22, 48, 18, 73, 22, 2, 27, 27, 31, 36, + 27, 61, 31, 70, 27, 15, 40, 24, 36, 46, 41, 58, 36, 76, 41, + 3, 3, 21, 8, 33, 3, 55, 8, 64, 4, 9, 17, 18, 13, 43, + 17, 52, 13, 77, 17, 6, 22, 31, 26, 40, 22, 49, 18, 74, 22, + 3, 27, 28, 31, 37, 27, 62, 31, 71, 27, 15, 41, 25, 36, 45, + 41, 59, 36, 75, 41, 2, 3, 22, 8, 32, 3, 56, 8, 65, 4, + 10, 17, 19, 13, 44, 17, 53, 13, 78, 17, 7, 22, 16, 18, 41, + 22, 50, 18, 75, 22, 4, 27, 29, 31, 38, 27, 63, 31, 72, 27, + 14, 41, 26, 36, 44, 41, 60, 36, 74, 41, 1, 3, 23, 8, 32, + 4, 57, 8, 66, 4, 11, 17, 20, 13, 45, 17, 54, 13, 79, 17, + 8, 22, 17, 18, 42, 22, 51, 18, 76, 22, 5, 27, 30, 31, 39, + 27, 63, 32, 73, 27, 13, 41, 27, 36, 43, 41, 61, 36, 73, 41, + 0, 3, 24, 8, 33, 4, 58, 8, 67, 4, 12, 17, 21, 13, 46, + 17, 55, 13, 64, 9, 9, 22, 18, 18, 43, 22, 52, 18, 77, 22, + 6, 27, 31, 31, 40, 27, 62, 32, 74, 27, 12, 41, 28, 36, 42, + 41, 62, 36, 72, 41, 0, 4, 25, 8, 34, 4, 59, 8, 68, 4, + 13, 17, 22, 13, 47, 17, 56, 13, 65, 9, 10, 22, 19, 18, 44, + 22, 53, 18, 78, 22, 7, 27, 31, 32, 41, 27, 61, 32, 75, 27, + 11, 41, 29, 36, 41, 41, 63, 36, 71, 41, 1, 4, 26, 8, 35, + 4, 60, 8, 69, 4, 14, 17, 23, 13, 32, 9, 57, 13, 66, 9, + 11, 22, 20, 18, 45, 22, 54, 18, 79, 22, 8, 27, 30, 32, 42, + 27, 60, 32, 76, 27, 10, 41, 30, 36, 40, 41, 63, 37, 70, 41, + 2, 4, 27, 8, 36, 4, 61, 8, 70, 4, 15, 17, 24, 13, 33, + 9, 58, 13, 67, 9, 12, 22, 21, 18, 46, 22, 55, 18, 79, 23, + 9, 27, 29, 32, 43, 27, 59, 32, 77, 27, 9, 41, 31, 36, 39, + 41, 62, 37, 69, 41, 3, 4, 28, 8, 37, 4, 62, 8, 71, 4, + 0, 9, 25, 13, 34, 9, 59, 13, 68, 9, 13, 22, 22, 18, 47, + 22, 56, 18, 78, 23, 10, 27, 28, 32, 44, 27, 58, 32, 78, 27, + 8, 41, 31, 37, 38, 41, 61, 37, 68, 41, 4, 4, 29, 8, 38, + 4, 63, 8, 72, 4, 1, 9, 26, 13, 35, 9, 60, 13, 69, 9, + 14, 22, 23, 18, 47, 23, 57, 18, 77, 23, 11, 27, 27, 32, 45, + 27, 57, 32, 79, 27, 7, 41, 30, 37, 37, 41, 60, 37, 67, 41, + 5, 4, 30, 8, 39, 4, 48, 0, 73, 4, 2, 9, 27, 13, 36, + 9, 61, 13, 70, 9, 15, 22, 24, 18, 46, 23, 58, 18, 76, 23, + 12, 27, 26, 32, 46, 27, 56, 32, 79, 28, 6, 41, 29, 37, 36, + 41, 59, 37, 66, 41, 6, 4, 31, 8, 40, 4, 49, 0, 74, 4, + 3, 9, 28, 13, 37, 9, 62, 13, 71, 9, 15, 23, 25, 18, 45, + 23, 59, 18, 75, 23, 13, 27, 25, 32, 47, 27, 55, 32, 78, 28, + 5, 41, 28, 37, 35, 41, 58, 37, 65, 41, 7, 4, 16, 0, 41, + 4, 50, 0, 75, 4, 4, 9, 29, 13, 38, 9, 63, 13, 72, 9, + 14, 23, 26, 18, 44, 23, 60, 18, 74, 23, 14, 27, 24, 32, 47, + 28, 54, 32, 77, 28, 4, 41, 27, 37, 34, 41, 57, 37, 64, 41, + 8, 4, 17, 0, 42, 4, 51, 0, 76, 4, 5, 9, 30, 13, 39, + 9, 63, 14, 73, 9, 13, 23, 27, 18, 43, 23, 61, 18, 73, 23, + 15, 27, 23, 32, 46, 28, 53, 32, 76, 28, 3, 41, 26, 37, 33, + 41, 56, 37, 64, 42, 9, 4, 18, 0, 43, 4, 52, 0, 77, 4, + 6, 9, 31, 13, 40, 9, 62, 14, 74, 9, 12, 23, 28, 18, 42, + 23, 62, 18, 72, 23, 15, 28, 22, 32, 45, 28, 52, 32, 75, 28, + 2, 41, 25, 37, 32, 41, 55, 37, 65, 42, 10, 4, 19, 0, 44, + 4, 53, 0, 78, 4, 7, 9, 31, 14, 41, 9, 61, 14, 75, 9, + 11, 23, 29, 18, 41, 23, 63, 18, 71, 23, 14, 28, 21, 32, 44, + 28, 51, 32, 74, 28, 1, 41, 24, 37, 32, 42, 54, 37, 66, 42, + 11, 4, 20, 0, 45, 4, 54, 0, 79, 4, 8, 9, 30, 14, 42, + 9, 60, 14, 76, 9, 10, 23, 30, 18, 40, 23, 63, 19, 70, 23, + 13, 28, 20, 32, 43, 28, 50, 32, 73, 28, 0, 41, 23, 37, 33, + 42, 53, 37, 67, 42, 12, 4, 21, 0, 46, 4, 55, 0, 79, 5, + 9, 9, 29, 14, 43, 9, 59, 14, 77, 9, 9, 23, 31, 18, 39, + 23, 62, 19, 69, 23, 12, 28, 19, 32, 42, 28, 49, 32, 72, 28, + 0, 42, 22, 37, 34, 42, 52, 37, 68, 42, 13, 4, 22, 0, 47, + 4, 56, 0, 78, 5, 10, 9, 28, 14, 44, 9, 58, 14, 78, 9, + 8, 23, 31, 19, 38, 23, 61, 19, 68, 23, 11, 28, 18, 32, 41, + 28, 48, 32, 71, 28, 1, 42, 21, 37, 35, 42, 51, 37, 69, 42, + 14, 4, 23, 0, 47, 5, 57, 0, 77, 5, 11, 9, 27, 14, 45, + 9, 57, 14, 79, 9, 7, 23, 30, 19, 37, 23, 60, 19, 67, 23, + 10, 28, 17, 32, 40, 28, 48, 33, 70, 28, 2, 42, 20, 37, 36, + 42, 50, 37, 70, 42, 15, 4, 24, 0, 46, 5, 58, 0, 76, 5, + 12, 9, 26, 14, 46, 9, 56, 14, 79, 10, 6, 23, 29, 19, 36, + 23, 59, 19, 66, 23, 9, 28, 16, 32, 39, 28, 49, 33, 69, 28, + 3, 42, 19, 37, 37, 42, 49, 37, 71, 42, 15, 5, 25, 0, 45, + 5, 59, 0, 75, 5, 13, 9, 25, 14, 47, 9, 55, 14, 78, 10, + 5, 23, 28, 19, 35, 23, 58, 19, 65, 23, 8, 28, 16, 33, 38, + 28, 50, 33, 68, 28, 4, 42, 18, 37, 38, 42, 48, 37, 72, 42, + 14, 5, 26, 0, 44, 5, 60, 0, 74, 5, 14, 9, 24, 14, 47, + 10, 54, 14, 77, 10, 4, 23, 27, 19, 34, 23, 57, 19, 64, 23, + 7, 28, 17, 33, 37, 28, 51, 33, 67, 28, 5, 42, 17, 37, 39, + 42, 48, 38, 73, 42, 13, 5, 27, 0, 43, 5, 61, 0, 73, 5, + 15, 9, 23, 14, 46, 10, 53, 14, 76, 10, 3, 23, 26, 19, 33, + 23, 56, 19, 64, 24, 6, 28, 18, 33, 36, 28, 52, 33, 66, 28, + 6, 42, 16, 37, 40, 42, 49, 38, 74, 42, 12, 5, 28, 0, 42, + 5, 62, 0, 72, 5, 15, 10, 22, 14, 45, 10, 52, 14, 75, 10, + 2, 23, 25, 19, 32, 23, 55, 19, 65, 24, 5, 28, 19, 33, 35, + 28, 53, 33, 65, 28, 7, 42, 16, 38, 41, 42, 50, 38, 75, 42, + 11, 5, 29, 0, 41, 5, 63, 0, 71, 5, 14, 10, 21, 14, 44, + 10, 51, 14, 74, 10, 1, 23, 24, 19, 32, 24, 54, 19, 66, 24, + 4, 28, 20, 33, 34, 28, 54, 33, 64, 28, 8, 42, 17, 38, 42, + 42, 51, 38, 76, 42, 10, 5, 30, 0, 40, 5, 63, 1, 70, 5, + 13, 10, 20, 14, 43, 10, 50, 14, 73, 10, 0, 23, 23, 19, 33, + 24, 53, 19, 67, 24, 3, 28, 21, 33, 33, 28, 55, 33, 64, 29, + 9, 42, 18, 38, 43, 42, 52, 38, 77, 42, 9, 5, 31, 0, 39, + 5, 62, 1, 69, 5, 12, 10, 19, 14, 42, 10, 49, 14, 72, 10, + 0, 24, 22, 19, 34, 24, 52, 19, 68, 24, 2, 28, 22, 33, 32, + 28, 56, 33, 65, 29, 10, 42, 19, 38, 44, 42, 53, 38, 78, 42, + 8, 5, 31, 1, 38, 5, 61, 1, 68, 5, 11, 10, 18, 14, 41, + 10, 48, 14, 71, 10, 1, 24, 21, 19, 35, 24, 51, 19, 69, 24, + 1, 28, 23, 33, 32, 29, 57, 33, 66, 29, 11, 42, 20, 38, 45, + 42, 54, 38, 79, 42, 7, 5, 30, 1, 37, 5, 60, 1, 67, 5, + 10, 10, 17, 14, 40, 10, 48, 15, 70, 10, 2, 24, 20, 19, 36, + 24, 50, 19, 70, 24, 0, 28, 24, 33, 33, 29, 58, 33, 67, 29, + 12, 42, 21, 38, 46, 42, 55, 38, 79, 43, 6, 5, 29, 1, 36, + 5, 59, 1, 66, 5, 9, 10, 16, 14, 39, 10, 49, 15, 69, 10, + 3, 24, 19, 19, 37, 24, 49, 19, 71, 24, 0, 29, 25, 33, 34, + 29, 59, 33, 68, 29, 13, 42, 22, 38, 47, 42, 56, 38, 78, 43, + 5, 5, 28, 1, 35, 5, 58, 1, 65, 5, 8, 10, 16, 15, 38, + 10, 50, 15, 68, 10, 4, 24, 18, 19, 38, 24, 48, 19, 72, 24, + 1, 29, 26, 33, 35, 29, 60, 33, 69, 29, 14, 42, 23, 38, 47, + 43, 57, 38, 77, 43, 4, 5, 27, 1, 34, 5, 57, 1, 64, 5, + 7, 10, 17, 15, 37, 10, 51, 15, 67, 10, 5, 24, 17, 19, 39, + 24, 48, 20, 73, 24, 2, 29, 27, 33, 36, 29, 61, 33, 70, 29, + 15, 42, 24, 38, 46, 43, 58, 38, 76, 43, 3, 5, 26, 1, 33, + 5, 56, 1, 64, 6, 6, 10, 18, 15, 36, 10, 52, 15, 66, 10, + 6, 24, 16, 19, 40, 24, 49, 20, 74, 24, 3, 29, 28, 33, 37, + 29, 62, 33, 71, 29, 15, 43, 25, 38, 45, 43, 59, 38, 75, 43, + 2, 5, 25, 1, 32, 5, 55, 1, 65, 6, 5, 10, 19, 15, 35, + 10, 53, 15, 65, 10, 7, 24, 16, 20, 41, 24, 50, 20, 75, 24, + 4, 29, 29, 33, 38, 29, 63, 33, 72, 29, 14, 43, 26, 38, 44, + 43, 60, 38, 74, 43, 1, 5, 24, 1, 32, 6, 54, 1, 66, 6, + 4, 10, 20, 15, 34, 10, 54, 15, 64, 10, 8, 24, 17, 20, 42, + 24, 51, 20, 76, 24, 5, 29, 30, 33, 39, 29, 63, 34, 73, 29, + 13, 43, 27, 38, 43, 43, 61, 38, 73, 43, 0, 5, 23, 1, 33, + 6, 53, 1, 67, 6, 3, 10, 21, 15, 33, 10, 55, 15, 64, 11, + 9, 24, 18, 20, 43, 24, 52, 20, 77, 24, 6, 29, 31, 33, 40, + 29, 62, 34, 74, 29, 12, 43, 28, 38, 42, 43, 62, 38, 72, 43, + 0, 6, 22, 1, 34, 6, 52, 1, 68, 6, 2, 10, 22, 15, 32, + 10, 56, 15, 65, 11, 10, 24, 19, 20, 44, 24, 53, 20, 78, 24, + 7, 29, 31, 34, 41, 29, 61, 34, 75, 29, 11, 43, 29, 38, 41, + 43, 63, 38, 71, 43, 1, 6, 21, 1, 35, 6, 51, 1, 69, 6, + 1, 10, 23, 15, 32, 11, 57, 15, 66, 11, 11, 24, 20, 20, 45, + 24, 54, 20, 79, 24, 8, 29, 30, 34, 42, 29, 60, 34, 76, 29, + 10, 43, 30, 38, 40, 43, 63, 39, 70, 43, 2, 6, 20, 1, 36, + 6, 50, 1, 70, 6, 0, 10, 24, 15, 33, 11, 58, 15, 67, 11, + 12, 24, 21, 20, 46, 24, 55, 20, 79, 25, 9, 29, 29, 34, 43, + 29, 59, 34, 77, 29, 9, 43, 31, 38, 39, 43, 62, 39, 69, 43, + 3, 6, 19, 1, 37, 6, 49, 1, 71, 6, 0, 11, 25, 15, 34, + 11, 59, 15, 68, 11, 13, 24, 22, 20, 47, 24, 56, 20, 78, 25, + 10, 29, 28, 34, 44, 29, 58, 34, 78, 29, 8, 43, 31, 39, 38, + 43, 61, 39, 68, 43, 4, 6, 18, 1, 38, 6, 48, 1, 72, 6, + 1, 11, 26, 15, 35, 11, 60, 15, 69, 11, 14, 24, 23, 20, 47, + 25, 57, 20, 77, 25, 11, 29, 27, 34, 45, 29, 57, 34, 79, 29, + 7, 43, 30, 39, 37, 43, 60, 39, 67, 43, 5, 6, 17, 1, 39, + 6, 48, 2, 73, 6, 2, 11, 27, 15, 36, 11, 61, 15, 70, 11, + 15, 24, 24, 20, 46, 25, 58, 20, 76, 25, 12, 29, 26, 34, 46, + 29, 56, 34, 79, 30, 6, 43, 29, 39, 36, 43, 59, 39, 66, 43, + 6, 6, 16, 1, 40, 6, 49, 2, 74, 6, 3, 11, 28, 15, 37, + 11, 62, 15, 71, 11, 15, 25, 25, 20, 45, 25, 59, 20, 75, 25, + 13, 29, 25, 34, 47, 29, 55, 34, 78, 30, 5, 43, 28, 39, 35, + 43, 58, 39, 65, 43, 7, 6, 16, 2, 41, 6, 50, 2, 75, 6, + 4, 11, 29, 15, 38, 11, 63, 15, 72, 11, 14, 25, 26, 20, 44, + 25, 60, 20, 74, 25, 14, 29, 24, 34, 47, 30, 54, 34, 77, 30, + 4, 43, 27, 39, 34, 43, 57, 39, 64, 43, 8, 6, 17, 2, 42, + 6, 51, 2, 76, 6, 5, 11, 30, 15, 39, 11, 63, 16, 73, 11, + 13, 25, 27, 20, 43, 25, 61, 20, 73, 25, 15, 29, 23, 34, 46, + 30, 53, 34, 76, 30, 3, 43, 26, 39, 33, 43, 56, 39, 64, 44, + 9, 6, 18, 2, 43, 6, 52, 2, 77, 6, 6, 11, 31, 15, 40, + 11, 62, 16, 74, 11, 12, 25, 28, 20, 42, 25, 62, 20, 72, 25, + 15, 30, 22, 34, 45, 30, 52, 34, 75, 30, 2, 43, 25, 39, 32, + 43, 55, 39, 65, 44, 10, 6, 19, 2, 44, 6, 53, 2, 78, 6, + 7, 11, 31, 16, 41, 11, 61, 16, 75, 11, 11, 25, 29, 20, 41, + 25, 63, 20, 71, 25, 14, 30, 21, 34, 44, 30, 51, 34, 74, 30, + 1, 43, 24, 39, 32, 44, 54, 39, 66, 44, 11, 6, 20, 2, 45, + 6, 54, 2, 79, 6, 8, 11, 30, 16, 42, 11, 60, 16, 76, 11, + 10, 25, 30, 20, 40, 25, 63, 21, 70, 25, 13, 30, 20, 34, 43, + 30, 50, 34, 73, 30, 0, 43, 23, 39, 33, 44, 53, 39, 67, 44, + 12, 6, 21, 2, 46, 6, 55, 2, 79, 7, 9, 11, 29, 16, 43, + 11, 59, 16, 77, 11, 9, 25, 31, 20, 39, 25, 62, 21, 69, 25, + 12, 30, 19, 34, 42, 30, 49, 34, 72, 30, 0, 44, 22, 39, 34, + 44, 52, 39, 68, 44, 13, 6, 22, 2, 47, 6, 56, 2, 78, 7, + 10, 11, 28, 16, 44, 11, 58, 16, 78, 11, 8, 25, 31, 21, 38, + 25, 61, 21, 68, 25, 11, 30, 18, 34, 41, 30, 48, 34, 71, 30, + 1, 44, 21, 39, 35, 44, 51, 39, 69, 44, 14, 6, 23, 2, 47, + 7, 57, 2, 77, 7, 11, 11, 27, 16, 45, 11, 57, 16, 79, 11, + 7, 25, 30, 21, 37, 25, 60, 21, 67, 25, 10, 30, 17, 34, 40, + 30, 48, 35, 70, 30, 2, 44, 20, 39, 36, 44, 50, 39, 70, 44, + 15, 6, 24, 2, 46, 7, 58, 2, 76, 7, 12, 11, 26, 16, 46, + 11, 56, 16, 79, 12, 6, 25, 29, 21, 36, 25, 59, 21, 66, 25, + 9, 30, 16, 34, 39, 30, 49, 35, 69, 30, 3, 44, 19, 39, 37, + 44, 49, 39, 71, 44, 15, 7, 25, 2, 45, 7, 59, 2, 75, 7, + 13, 11, 25, 16, 47, 11, 55, 16, 78, 12, 5, 25, 28, 21, 35, + 25, 58, 21, 65, 25, 8, 30, 16, 35, 38, 30, 50, 35, 68, 30, + 4, 44, 18, 39, 38, 44, 48, 39, 72, 44, 14, 7, 26, 2, 44, + 7, 60, 2, 74, 7, 14, 11, 24, 16, 47, 12, 54, 16, 77, 12, + 4, 25, 27, 21, 34, 25, 57, 21, 64, 25, 7, 30, 17, 35, 37, + 30, 51, 35, 67, 30, 5, 44, 17, 39, 39, 44, 48, 40, 73, 44, + 13, 7, 27, 2, 43, 7, 61, 2, 73, 7, 15, 11, 23, 16, 46, + 12, 53, 16, 76, 12, 3, 25, 26, 21, 33, 25, 56, 21, 64, 26, + 6, 30, 18, 35, 36, 30, 52, 35, 66, 30, 6, 44, 16, 39, 40, + 44, 49, 40, 74, 44, 12, 7, 28, 2, 42, 7, 62, 2, 72, 7, + 15, 12, 22, 16, 45, 12, 52, 16, 75, 12, 2, 25, 25, 21, 32, + 25, 55, 21, 65, 26, 5, 30, 19, 35, 35, 30, 53, 35, 65, 30, + 7, 44, 16, 40, 41, 44, 50, 40, 75, 44, 11, 7, 29, 2, 41, + 7, 63, 2, 71, 7, 14, 12, 21, 16, 44, 12, 51, 16, 74, 12, + 1, 25, 24, 21, 32, 26, 54, 21, 66, 26, 4, 30, 20, 35, 34, + 30, 54, 35, 64, 30, 8, 44, 17, 40, 42, 44, 51, 40, 76, 44, + 10, 7, 30, 2, 40, 7, 63, 3, 70, 7, 13, 12, 20, 16, 43, + 12, 50, 16, 73, 12, 0, 25, 23, 21, 33, 26, 53, 21, 67, 26, + 3, 30, 21, 35, 33, 30, 55, 35, 64, 31, 9, 44, 18, 40, 43, + 44, 52, 40, 77, 44, 9, 7, 31, 2, 39, 7, 62, 3, 69, 7, + 12, 12, 19, 16, 42, 12, 49, 16, 72, 12, 0, 26, 22, 21, 34, + 26, 52, 21, 68, 26, 2, 30, 22, 35, 32, 30, 56, 35, 65, 31, + 10, 44, 19, 40, 44, 44, 53, 40, 78, 44, 8, 7, 31, 3, 38, + 7, 61, 3, 68, 7, 11, 12, 18, 16, 41, 12, 48, 16, 71, 12, + 1, 26, 21, 21, 35, 26, 51, 21, 69, 26, 1, 30, 23, 35, 32, + 31, 57, 35, 66, 31, 11, 44, 20, 40, 45, 44, 54, 40, 79, 44, + 7, 7, 30, 3, 37, 7, 60, 3, 67, 7, 10, 12, 17, 16, 40, + 12, 48, 17, 70, 12, 2, 26, 20, 21, 36, 26, 50, 21, 70, 26, + 0, 30, 24, 35, 33, 31, 58, 35, 67, 31, 12, 44, 21, 40, 46, + 44, 55, 40, 64, 36, 6, 7, 29, 3, 36, 7, 59, 3, 66, 7, + 9, 12, 16, 16, 39, 12, 49, 17, 69, 12, 3, 26, 19, 21, 37, + 26, 49, 21, 71, 26, 0, 31, 25, 35, 34, 31, 59, 35, 68, 31, + 13, 44, 22, 40, 47, 44, 56, 40, 65, 36, 5, 7, 28, 3, 35, + 7, 58, 3, 65, 7, 8, 12, 16, 17, 38, 12, 50, 17, 68, 12, + 4, 26, 18, 21, 38, 26, 48, 21, 72, 26, 1, 31, 26, 35, 35, + 31, 60, 35, 69, 31, 14, 44, 23, 40, 32, 36, 57, 40, 66, 36, + 4, 7, 27, 3, 34, 7, 57, 3, 64, 7, 7, 12, 17, 17, 37, + 12, 51, 17, 67, 12, 5, 26, 17, 21, 39, 26, 48, 22, 73, 26, + 2, 31, 27, 35, 36, 31, 61, 35, 70, 31, 15, 44, 24, 40, 33, + 36, 58, 40, 67, 36, 3, 7, 26, 3, 33, 7, 56, 3, 64, 8, + 6, 12, 18, 17, 36, 12, 52, 17, 66, 12, 6, 26, 16, 21, 40, + 26, 49, 22, 74, 26, 3, 31, 28, 35, 37, 31, 62, 35, 71, 31, + 0, 36, 25, 40, 34, 36, 59, 40, 68, 36, 2, 7, 25, 3, 32, + 7, 55, 3, 65, 8, 5, 12, 19, 17, 35, 12, 53, 17, 65, 12, + 7, 26, 16, 22, 41, 26, 50, 22, 75, 26, 4, 31, 29, 35, 38, + 31, 63, 35, 72, 31, 1, 36, 26, 40, 35, 36, 60, 40, 69, 36, + 1, 7, 24, 3, 32, 8, 54, 3, 66, 8, 4, 12, 20, 17, 34, + 12, 54, 17, 64, 12, 8, 26, 17, 22, 42, 26, 51, 22, 76, 26, + 5, 31, 30, 35, 39, 31, 48, 27, 73, 31, 2, 36, 27, 40, 36, + 36, 61, 40, 70, 36, 0, 7, 23, 3, 33, 8, 53, 3, 67, 8, + 3, 12, 21, 17, 33, 12, 55, 17, 64, 13, 9, 26, 18, 22, 43, + 26, 52, 22, 77, 26, 6, 31, 31, 35, 40, 31, 49, 27, 74, 31, + 3, 36, 28, 40, 37, 36, 62, 40, 71, 36, 0, 8, 22, 3, 34, + 8, 52, 3, 68, 8, 2, 12, 22, 17, 32, 12, 56, 17, 65, 13, + 10, 26, 19, 22, 44, 26, 53, 22, 78, 26, 7, 31, 16, 27, 41, + 31, 50, 27, 75, 31, 4, 36, 29, 40, 38, 36, 63, 40, 72, 36, + 1, 8, 21, 3, 35, 8, 51, 3, 69, 8, 1, 12, 23, 17, 32, + 13, 57, 17, 66, 13, 11, 26, 20, 22, 45, 26, 54, 22, 79, 26, + 8, 31, 17, 27, 42, 31, 51, 27, 76, 31, 5, 36, 30, 40, 39, + 36, 63, 41, 73, 36, 2, 8, 20, 3, 36, 8, 50, 3, 70, 8, + 0, 12, 24, 17, 33, 13, 58, 17, 67, 13, 12, 26, 21, 22, 46, + 26, 55, 22, 64, 18, 9, 31, 18, 27, 43, 31, 52, 27, 77, 31, + 6, 36, 31, 40, 40, 36, 62, 41, 74, 36, 3, 8, 19, 3, 37, + 8, 49, 3, 71, 8, 0, 13, 25, 17, 34, 13, 59, 17, 68, 13, + 13, 26, 22, 22, 47, 26, 56, 22, 65, 18, 10, 31, 19, 27, 44, + 31, 53, 27, 78, 31, 7, 36, 31, 41, 41, 36, 61, 41, 75, 36, + 4, 8, 18, 3, 38, 8, 48, 3, 72, 8, 1, 13, 26, 17, 35, + 13, 60, 17, 69, 13, 14, 26, 23, 22, 32, 18, 57, 22, 66, 18, + 11, 31, 20, 27, 45, 31, 54, 27, 79, 31, 8, 36, 30, 41, 42, + 36, 60, 41, 76, 36, 5, 8, 17, 3, 39, 8, 48, 4, 73, 8, + 2, 13, 27, 17, 36, 13, 61, 17, 70, 13, 15, 26, 24, 22, 33, + 18, 58, 22, 67, 18, 12, 31, 21, 27, 46, 31, 55, 27, 79, 32, + 9, 36, 29, 41, 43, 36, 59, 41, 77, 36, 6, 8, 16, 3, 40, + 8, 49, 4, 74, 8, 3, 13, 28, 17, 37, 13, 62, 17, 71, 13, + 0, 18, 25, 22, 34, 18, 59, 22, 68, 18, 13, 31, 22, 27, 47, + 31, 56, 27, 78, 32, 10, 36, 28, 41, 44, 36, 58, 41, 78, 36, + 7, 8, 16, 4, 41, 8, 50, 4, 75, 8, 4, 13, 29, 17, 38, + 13, 63, 17, 72, 13, 1, 18, 26, 22, 35, 18, 60, 22, 69, 18, + 14, 31, 23, 27, 47, 32, 57, 27, 77, 32, 11, 36, 27, 41, 45, + 36, 57, 41, 79, 36, 8, 8, 17, 4, 42, 8, 51, 4, 76, 8, + 5, 13, 30, 17, 39, 13, 48, 9, 73, 13, 2, 18, 27, 22, 36, + 18, 61, 22, 70, 18, 15, 31, 24, 27, 46, 32, 58, 27, 76, 32, + 12, 36, 26, 41, 46, 36, 56, 41, 79, 37, 9, 8, 18, 4, 43, + 8, 52, 4, 77, 8, 6, 13, 31, 17, 40, 13, 49, 9, 74, 13, + 3, 18, 28, 22, 37, 18, 62, 22, 71, 18, 15, 32, 25, 27, 45, + 32, 59, 27, 75, 32, 13, 36, 25, 41, 47, 36, 55, 41, 78, 37, + 10, 8, 19, 4, 44, 8, 53, 4, 78, 8, 7, 13, 16, 9, 41, + 13, 50, 9, 75, 13, 4, 18, 29, 22, 38, 18, 63, 22, 72, 18, + 14, 32, 26, 27, 44, 32, 60, 27, 74, 32, 14, 36, 24, 41, 47, + 37, 54, 41, 77, 37, 11, 8, 20, 4, 45, 8, 54, 4, 79, 8, + 8, 13, 17, 9, 42, 13, 51, 9, 76, 13, 5, 18, 30, 22, 39, + 18, 63, 23, 73, 18, 13, 32, 27, 27, 43, 32, 61, 27, 73, 32, + 15, 36, 23, 41, 46, 37, 53, 41, 76, 37, 12, 8, 21, 4, 46, + 8, 55, 4, 64, 0, 9, 13, 18, 9, 43, 13, 52, 9, 77, 13, + 6, 18, 31, 22, 40, 18, 62, 23, 74, 18, 12, 32, 28, 27, 42, + 32, 62, 27, 72, 32, 15, 37, 22, 41, 45, 37, 52, 41, 75, 37, + 13, 8, 22, 4, 47, 8, 56, 4, 65, 0, 10, 13, 19, 9, 44, + 13, 53, 9, 78, 13, 7, 18, 31, 23, 41, 18, 61, 23, 75, 18, + 11, 32, 29, 27, 41, 32, 63, 27, 71, 32, 14, 37, 21, 41, 44, + 37, 51, 41, 74, 37, 14, 8, 23, 4, 32, 0, 57, 4, 66, 0, + 11, 13, 20, 9, 45, 13, 54, 9, 79, 13, 8, 18, 30, 23, 42, + 18, 60, 23, 76, 18, 10, 32, 30, 27, 40, 32, 63, 28, 70, 32, + 13, 37, 20, 41, 43, 37, 50, 41, 73, 37, 15, 8, 24, 4, 33, + 0, 58, 4, 67, 0, 12, 13, 21, 9, 46, 13, 55, 9, 79, 14, + 9, 18, 29, 23, 43, 18, 59, 23, 77, 18, 9, 32, 31, 27, 39, + 32, 62, 28, 69, 32, 12, 37, 19, 41, 42, 37, 49, 41, 72, 37, +}; + +static const uint8_t hq_tab_06[] = { + 0, 0, 25, 8, 34, 0, 59, 8, 68, 0, 13, 25, 22, 17, 47, + 25, 56, 17, 78, 26, 10, 34, 28, 43, 44, 34, 58, 43, 78, 34, + 8, 60, 31, 52, 38, 60, 61, 52, 68, 60, 1, 0, 26, 8, 35, + 0, 60, 8, 69, 0, 14, 25, 23, 17, 47, 26, 57, 17, 77, 26, + 11, 34, 27, 43, 45, 34, 57, 43, 79, 34, 7, 60, 30, 52, 37, + 60, 60, 52, 67, 60, 2, 0, 27, 8, 36, 0, 61, 8, 70, 0, + 15, 25, 24, 17, 46, 26, 58, 17, 76, 26, 12, 34, 26, 43, 46, + 34, 56, 43, 79, 35, 6, 60, 29, 52, 36, 60, 59, 52, 66, 60, + 3, 0, 28, 8, 37, 0, 62, 8, 71, 0, 15, 26, 25, 17, 45, + 26, 59, 17, 75, 26, 13, 34, 25, 43, 47, 34, 55, 43, 78, 35, + 5, 60, 28, 52, 35, 60, 58, 52, 65, 60, 4, 0, 29, 8, 38, + 0, 63, 8, 72, 0, 14, 26, 26, 17, 44, 26, 60, 17, 74, 26, + 14, 34, 24, 43, 47, 35, 54, 43, 77, 35, 4, 60, 27, 52, 34, + 60, 57, 52, 64, 60, 5, 0, 30, 8, 39, 0, 63, 9, 73, 0, + 13, 26, 27, 17, 43, 26, 61, 17, 73, 26, 15, 34, 23, 43, 46, + 35, 53, 43, 76, 35, 3, 60, 26, 52, 33, 60, 56, 52, 64, 61, + 6, 0, 31, 8, 40, 0, 62, 9, 74, 0, 12, 26, 28, 17, 42, + 26, 62, 17, 72, 26, 15, 35, 22, 43, 45, 35, 52, 43, 75, 35, + 2, 60, 25, 52, 32, 60, 55, 52, 65, 61, 7, 0, 31, 9, 41, + 0, 61, 9, 75, 0, 11, 26, 29, 17, 41, 26, 63, 17, 71, 26, + 14, 35, 21, 43, 44, 35, 51, 43, 74, 35, 1, 60, 24, 52, 32, + 61, 54, 52, 66, 61, 8, 0, 30, 9, 42, 0, 60, 9, 76, 0, + 10, 26, 30, 17, 40, 26, 63, 18, 70, 26, 13, 35, 20, 43, 43, + 35, 50, 43, 73, 35, 0, 60, 23, 52, 33, 61, 53, 52, 67, 61, + 9, 0, 29, 9, 43, 0, 59, 9, 77, 0, 9, 26, 31, 17, 39, + 26, 62, 18, 69, 26, 12, 35, 19, 43, 42, 35, 49, 43, 72, 35, + 0, 61, 22, 52, 34, 61, 52, 52, 68, 61, 10, 0, 28, 9, 44, + 0, 58, 9, 78, 0, 8, 26, 31, 18, 38, 26, 61, 18, 68, 26, + 11, 35, 18, 43, 41, 35, 48, 43, 71, 35, 1, 61, 21, 52, 35, + 61, 51, 52, 69, 61, 11, 0, 27, 9, 45, 0, 57, 9, 79, 0, + 7, 26, 30, 18, 37, 26, 60, 18, 67, 26, 10, 35, 17, 43, 40, + 35, 48, 44, 70, 35, 2, 61, 20, 52, 36, 61, 50, 52, 70, 61, + 12, 0, 26, 9, 46, 0, 56, 9, 79, 1, 6, 26, 29, 18, 36, + 26, 59, 18, 66, 26, 9, 35, 16, 43, 39, 35, 49, 44, 69, 35, + 3, 61, 19, 52, 37, 61, 49, 52, 71, 61, 13, 0, 25, 9, 47, + 0, 55, 9, 78, 1, 5, 26, 28, 18, 35, 26, 58, 18, 65, 26, + 8, 35, 16, 44, 38, 35, 50, 44, 68, 35, 4, 61, 18, 52, 38, + 61, 48, 52, 72, 61, 14, 0, 24, 9, 47, 1, 54, 9, 77, 1, + 4, 26, 27, 18, 34, 26, 57, 18, 64, 26, 7, 35, 17, 44, 37, + 35, 51, 44, 67, 35, 5, 61, 17, 52, 39, 61, 48, 53, 73, 61, + 15, 0, 23, 9, 46, 1, 53, 9, 76, 1, 3, 26, 26, 18, 33, + 26, 56, 18, 64, 27, 6, 35, 18, 44, 36, 35, 52, 44, 66, 35, + 6, 61, 16, 52, 40, 61, 49, 53, 74, 61, 15, 1, 22, 9, 45, + 1, 52, 9, 75, 1, 2, 26, 25, 18, 32, 26, 55, 18, 65, 27, + 5, 35, 19, 44, 35, 35, 53, 44, 65, 35, 7, 61, 16, 53, 41, + 61, 50, 53, 75, 61, 14, 1, 21, 9, 44, 1, 51, 9, 74, 1, + 1, 26, 24, 18, 32, 27, 54, 18, 66, 27, 4, 35, 20, 44, 34, + 35, 54, 44, 64, 35, 8, 61, 17, 53, 42, 61, 51, 53, 76, 61, + 13, 1, 20, 9, 43, 1, 50, 9, 73, 1, 0, 26, 23, 18, 33, + 27, 53, 18, 67, 27, 3, 35, 21, 44, 33, 35, 55, 44, 64, 36, + 9, 61, 18, 53, 43, 61, 52, 53, 77, 61, 12, 1, 19, 9, 42, + 1, 49, 9, 72, 1, 0, 27, 22, 18, 34, 27, 52, 18, 68, 27, + 2, 35, 22, 44, 32, 35, 56, 44, 65, 36, 10, 61, 19, 53, 44, + 61, 53, 53, 78, 61, 11, 1, 18, 9, 41, 1, 48, 9, 71, 1, + 1, 27, 21, 18, 35, 27, 51, 18, 69, 27, 1, 35, 23, 44, 32, + 36, 57, 44, 66, 36, 11, 61, 20, 53, 45, 61, 54, 53, 79, 61, + 10, 1, 17, 9, 40, 1, 48, 10, 70, 1, 2, 27, 20, 18, 36, + 27, 50, 18, 70, 27, 0, 35, 24, 44, 33, 36, 58, 44, 67, 36, + 12, 61, 21, 53, 46, 61, 55, 53, 79, 62, 9, 1, 16, 9, 39, + 1, 49, 10, 69, 1, 3, 27, 19, 18, 37, 27, 49, 18, 71, 27, + 0, 36, 25, 44, 34, 36, 59, 44, 68, 36, 13, 61, 22, 53, 47, + 61, 56, 53, 78, 62, 8, 1, 16, 10, 38, 1, 50, 10, 68, 1, + 4, 27, 18, 18, 38, 27, 48, 18, 72, 27, 1, 36, 26, 44, 35, + 36, 60, 44, 69, 36, 14, 61, 23, 53, 47, 62, 57, 53, 77, 62, + 7, 1, 17, 10, 37, 1, 51, 10, 67, 1, 5, 27, 17, 18, 39, + 27, 48, 19, 73, 27, 2, 36, 27, 44, 36, 36, 61, 44, 70, 36, + 15, 61, 24, 53, 46, 62, 58, 53, 76, 62, 6, 1, 18, 10, 36, + 1, 52, 10, 66, 1, 6, 27, 16, 18, 40, 27, 49, 19, 74, 27, + 3, 36, 28, 44, 37, 36, 62, 44, 71, 36, 15, 62, 25, 53, 45, + 62, 59, 53, 75, 62, 5, 1, 19, 10, 35, 1, 53, 10, 65, 1, + 7, 27, 16, 19, 41, 27, 50, 19, 75, 27, 4, 36, 29, 44, 38, + 36, 63, 44, 72, 36, 14, 62, 26, 53, 44, 62, 60, 53, 74, 62, + 4, 1, 20, 10, 34, 1, 54, 10, 64, 1, 8, 27, 17, 19, 42, + 27, 51, 19, 76, 27, 5, 36, 30, 44, 39, 36, 63, 45, 73, 36, + 13, 62, 27, 53, 43, 62, 61, 53, 73, 62, 3, 1, 21, 10, 33, + 1, 55, 10, 64, 2, 9, 27, 18, 19, 43, 27, 52, 19, 77, 27, + 6, 36, 31, 44, 40, 36, 62, 45, 74, 36, 12, 62, 28, 53, 42, + 62, 62, 53, 72, 62, 2, 1, 22, 10, 32, 1, 56, 10, 65, 2, + 10, 27, 19, 19, 44, 27, 53, 19, 78, 27, 7, 36, 31, 45, 41, + 36, 61, 45, 75, 36, 11, 62, 29, 53, 41, 62, 63, 53, 71, 62, + 1, 1, 23, 10, 32, 2, 57, 10, 66, 2, 11, 27, 20, 19, 45, + 27, 54, 19, 79, 27, 8, 36, 30, 45, 42, 36, 60, 45, 76, 36, + 10, 62, 30, 53, 40, 62, 63, 54, 70, 62, 0, 1, 24, 10, 33, + 2, 58, 10, 67, 2, 12, 27, 21, 19, 46, 27, 55, 19, 79, 28, + 9, 36, 29, 45, 43, 36, 59, 45, 77, 36, 9, 62, 31, 53, 39, + 62, 62, 54, 69, 62, 0, 2, 25, 10, 34, 2, 59, 10, 68, 2, + 13, 27, 22, 19, 47, 27, 56, 19, 78, 28, 10, 36, 28, 45, 44, + 36, 58, 45, 78, 36, 8, 62, 31, 54, 38, 62, 61, 54, 68, 62, + 1, 2, 26, 10, 35, 2, 60, 10, 69, 2, 14, 27, 23, 19, 47, + 28, 57, 19, 77, 28, 11, 36, 27, 45, 45, 36, 57, 45, 79, 36, + 7, 62, 30, 54, 37, 62, 60, 54, 67, 62, 2, 2, 27, 10, 36, + 2, 61, 10, 70, 2, 15, 27, 24, 19, 46, 28, 58, 19, 76, 28, + 12, 36, 26, 45, 46, 36, 56, 45, 79, 37, 6, 62, 29, 54, 36, + 62, 59, 54, 66, 62, 3, 2, 28, 10, 37, 2, 62, 10, 71, 2, + 15, 28, 25, 19, 45, 28, 59, 19, 75, 28, 13, 36, 25, 45, 47, + 36, 55, 45, 78, 37, 5, 62, 28, 54, 35, 62, 58, 54, 65, 62, + 4, 2, 29, 10, 38, 2, 63, 10, 72, 2, 14, 28, 26, 19, 44, + 28, 60, 19, 74, 28, 14, 36, 24, 45, 47, 37, 54, 45, 77, 37, + 4, 62, 27, 54, 34, 62, 57, 54, 64, 62, 5, 2, 30, 10, 39, + 2, 63, 11, 73, 2, 13, 28, 27, 19, 43, 28, 61, 19, 73, 28, + 15, 36, 23, 45, 46, 37, 53, 45, 76, 37, 3, 62, 26, 54, 33, + 62, 56, 54, 64, 63, 6, 2, 31, 10, 40, 2, 62, 11, 74, 2, + 12, 28, 28, 19, 42, 28, 62, 19, 72, 28, 15, 37, 22, 45, 45, + 37, 52, 45, 75, 37, 2, 62, 25, 54, 32, 62, 55, 54, 65, 63, + 7, 2, 31, 11, 41, 2, 61, 11, 75, 2, 11, 28, 29, 19, 41, + 28, 63, 19, 71, 28, 14, 37, 21, 45, 44, 37, 51, 45, 74, 37, + 1, 62, 24, 54, 32, 63, 54, 54, 66, 63, 8, 2, 30, 11, 42, + 2, 60, 11, 76, 2, 10, 28, 30, 19, 40, 28, 63, 20, 70, 28, + 13, 37, 20, 45, 43, 37, 50, 45, 73, 37, 0, 62, 23, 54, 33, + 63, 53, 54, 67, 63, 9, 2, 29, 11, 43, 2, 59, 11, 77, 2, + 9, 28, 31, 19, 39, 28, 62, 20, 69, 28, 12, 37, 19, 45, 42, + 37, 49, 45, 72, 37, 0, 63, 22, 54, 34, 63, 52, 54, 68, 63, + 10, 2, 28, 11, 44, 2, 58, 11, 78, 2, 8, 28, 31, 20, 38, + 28, 61, 20, 68, 28, 11, 37, 18, 45, 41, 37, 48, 45, 71, 37, + 1, 63, 21, 54, 35, 63, 51, 54, 69, 63, 11, 2, 27, 11, 45, + 2, 57, 11, 79, 2, 7, 28, 30, 20, 37, 28, 60, 20, 67, 28, + 10, 37, 17, 45, 40, 37, 48, 46, 70, 37, 2, 63, 20, 54, 36, + 63, 50, 54, 70, 63, 12, 2, 26, 11, 46, 2, 56, 11, 79, 3, + 6, 28, 29, 20, 36, 28, 59, 20, 66, 28, 9, 37, 16, 45, 39, + 37, 49, 46, 69, 37, 3, 63, 19, 54, 37, 63, 49, 54, 71, 63, + 13, 2, 25, 11, 47, 2, 55, 11, 78, 3, 5, 28, 28, 20, 35, + 28, 58, 20, 65, 28, 8, 37, 16, 46, 38, 37, 50, 46, 68, 37, + 4, 63, 18, 54, 38, 63, 48, 54, 72, 63, 14, 2, 24, 11, 47, + 3, 54, 11, 77, 3, 4, 28, 27, 20, 34, 28, 57, 20, 64, 28, + 7, 37, 17, 46, 37, 37, 51, 46, 67, 37, 5, 63, 17, 54, 39, + 63, 48, 55, 73, 63, 15, 2, 23, 11, 46, 3, 53, 11, 76, 3, + 3, 28, 26, 20, 33, 28, 56, 20, 64, 29, 6, 37, 18, 46, 36, + 37, 52, 46, 66, 37, 6, 63, 16, 54, 40, 63, 49, 55, 74, 63, + 15, 3, 22, 11, 45, 3, 52, 11, 75, 3, 2, 28, 25, 20, 32, + 28, 55, 20, 65, 29, 5, 37, 19, 46, 35, 37, 53, 46, 65, 37, + 7, 63, 16, 55, 41, 63, 50, 55, 75, 63, 14, 3, 21, 11, 44, + 3, 51, 11, 74, 3, 1, 28, 24, 20, 32, 29, 54, 20, 66, 29, + 4, 37, 20, 46, 34, 37, 54, 46, 64, 37, 8, 63, 17, 55, 42, + 63, 51, 55, 76, 63, 13, 3, 20, 11, 43, 3, 50, 11, 73, 3, + 0, 28, 23, 20, 33, 29, 53, 20, 67, 29, 3, 37, 21, 46, 33, + 37, 55, 46, 64, 38, 9, 63, 18, 55, 43, 63, 52, 55, 77, 63, + 12, 3, 19, 11, 42, 3, 49, 11, 72, 3, 0, 29, 22, 20, 34, + 29, 52, 20, 68, 29, 2, 37, 22, 46, 32, 37, 56, 46, 65, 38, + 10, 63, 19, 55, 44, 63, 53, 55, 78, 63, 11, 3, 18, 11, 41, + 3, 48, 11, 71, 3, 1, 29, 21, 20, 35, 29, 51, 20, 69, 29, + 1, 37, 23, 46, 32, 38, 57, 46, 66, 38, 11, 63, 20, 55, 45, + 63, 54, 55, 79, 63, 10, 3, 17, 11, 40, 3, 48, 12, 70, 3, + 2, 29, 20, 20, 36, 29, 50, 20, 70, 29, 0, 37, 24, 46, 33, + 38, 58, 46, 67, 38, 12, 63, 21, 55, 46, 63, 55, 55, 79, 64, + 9, 3, 16, 11, 39, 3, 49, 12, 69, 3, 3, 29, 19, 20, 37, + 29, 49, 20, 71, 29, 0, 38, 25, 46, 34, 38, 59, 46, 68, 38, + 13, 63, 22, 55, 47, 63, 56, 55, 78, 64, 8, 3, 16, 12, 38, + 3, 50, 12, 68, 3, 4, 29, 18, 20, 38, 29, 48, 20, 72, 29, + 1, 38, 26, 46, 35, 38, 60, 46, 69, 38, 14, 63, 23, 55, 47, + 64, 57, 55, 77, 64, 7, 3, 17, 12, 37, 3, 51, 12, 67, 3, + 5, 29, 17, 20, 39, 29, 48, 21, 73, 29, 2, 38, 27, 46, 36, + 38, 61, 46, 70, 38, 15, 63, 24, 55, 46, 64, 58, 55, 76, 64, + 6, 3, 18, 12, 36, 3, 52, 12, 66, 3, 6, 29, 16, 20, 40, + 29, 49, 21, 74, 29, 3, 38, 28, 46, 37, 38, 62, 46, 71, 38, + 15, 64, 25, 55, 45, 64, 59, 55, 75, 64, 5, 3, 19, 12, 35, + 3, 53, 12, 65, 3, 7, 29, 16, 21, 41, 29, 50, 21, 75, 29, + 4, 38, 29, 46, 38, 38, 63, 46, 72, 38, 14, 64, 26, 55, 44, + 64, 60, 55, 74, 64, 4, 3, 20, 12, 34, 3, 54, 12, 64, 3, + 8, 29, 17, 21, 42, 29, 51, 21, 76, 29, 5, 38, 30, 46, 39, + 38, 63, 47, 73, 38, 13, 64, 27, 55, 43, 64, 61, 55, 73, 64, + 3, 3, 21, 12, 33, 3, 55, 12, 64, 4, 9, 29, 18, 21, 43, + 29, 52, 21, 77, 29, 6, 38, 31, 46, 40, 38, 62, 47, 74, 38, + 12, 64, 28, 55, 42, 64, 62, 55, 72, 64, 2, 3, 22, 12, 32, + 3, 56, 12, 65, 4, 10, 29, 19, 21, 44, 29, 53, 21, 78, 29, + 7, 38, 31, 47, 41, 38, 61, 47, 75, 38, 11, 64, 29, 55, 41, + 64, 63, 55, 71, 64, 1, 3, 23, 12, 32, 4, 57, 12, 66, 4, + 11, 29, 20, 21, 45, 29, 54, 21, 79, 29, 8, 38, 30, 47, 42, + 38, 60, 47, 76, 38, 10, 64, 30, 55, 40, 64, 63, 56, 70, 64, + 0, 3, 24, 12, 33, 4, 58, 12, 67, 4, 12, 29, 21, 21, 46, + 29, 55, 21, 79, 30, 9, 38, 29, 47, 43, 38, 59, 47, 77, 38, + 9, 64, 31, 55, 39, 64, 62, 56, 69, 64, 0, 4, 25, 12, 34, + 4, 59, 12, 68, 4, 13, 29, 22, 21, 47, 29, 56, 21, 78, 30, + 10, 38, 28, 47, 44, 38, 58, 47, 78, 38, 8, 64, 31, 56, 38, + 64, 61, 56, 68, 64, 1, 4, 26, 12, 35, 4, 60, 12, 69, 4, + 14, 29, 23, 21, 47, 30, 57, 21, 77, 30, 11, 38, 27, 47, 45, + 38, 57, 47, 79, 38, 7, 64, 30, 56, 37, 64, 60, 56, 67, 64, + 2, 4, 27, 12, 36, 4, 61, 12, 70, 4, 15, 29, 24, 21, 46, + 30, 58, 21, 76, 30, 12, 38, 26, 47, 46, 38, 56, 47, 79, 39, + 6, 64, 29, 56, 36, 64, 59, 56, 66, 64, 3, 4, 28, 12, 37, + 4, 62, 12, 71, 4, 15, 30, 25, 21, 45, 30, 59, 21, 75, 30, + 13, 38, 25, 47, 47, 38, 55, 47, 78, 39, 5, 64, 28, 56, 35, + 64, 58, 56, 65, 64, 4, 4, 29, 12, 38, 4, 63, 12, 72, 4, + 14, 30, 26, 21, 44, 30, 60, 21, 74, 30, 14, 38, 24, 47, 47, + 39, 54, 47, 77, 39, 4, 64, 27, 56, 34, 64, 57, 56, 64, 64, + 5, 4, 30, 12, 39, 4, 63, 13, 73, 4, 13, 30, 27, 21, 43, + 30, 61, 21, 73, 30, 15, 38, 23, 47, 46, 39, 53, 47, 76, 39, + 3, 64, 26, 56, 33, 64, 56, 56, 64, 65, 6, 4, 31, 12, 40, + 4, 62, 13, 74, 4, 12, 30, 28, 21, 42, 30, 62, 21, 72, 30, + 15, 39, 22, 47, 45, 39, 52, 47, 75, 39, 2, 64, 25, 56, 32, + 64, 55, 56, 65, 65, 7, 4, 31, 13, 41, 4, 61, 13, 75, 4, + 11, 30, 29, 21, 41, 30, 63, 21, 71, 30, 14, 39, 21, 47, 44, + 39, 51, 47, 74, 39, 1, 64, 24, 56, 32, 65, 54, 56, 66, 65, + 8, 4, 30, 13, 42, 4, 60, 13, 76, 4, 10, 30, 30, 21, 40, + 30, 63, 22, 70, 30, 13, 39, 20, 47, 43, 39, 50, 47, 73, 39, + 0, 64, 23, 56, 33, 65, 53, 56, 67, 65, 9, 4, 29, 13, 43, + 4, 59, 13, 77, 4, 9, 30, 31, 21, 39, 30, 62, 22, 69, 30, + 12, 39, 19, 47, 42, 39, 49, 47, 72, 39, 0, 65, 22, 56, 34, + 65, 52, 56, 68, 65, 10, 4, 28, 13, 44, 4, 58, 13, 78, 4, + 8, 30, 31, 22, 38, 30, 61, 22, 68, 30, 11, 39, 18, 47, 41, + 39, 48, 47, 71, 39, 1, 65, 21, 56, 35, 65, 51, 56, 69, 65, + 11, 4, 27, 13, 45, 4, 57, 13, 79, 4, 7, 30, 30, 22, 37, + 30, 60, 22, 67, 30, 10, 39, 17, 47, 40, 39, 48, 48, 70, 39, + 2, 65, 20, 56, 36, 65, 50, 56, 70, 65, 12, 4, 26, 13, 46, + 4, 56, 13, 79, 5, 6, 30, 29, 22, 36, 30, 59, 22, 66, 30, + 9, 39, 16, 47, 39, 39, 49, 48, 69, 39, 3, 65, 19, 56, 37, + 65, 49, 56, 71, 65, 13, 4, 25, 13, 47, 4, 55, 13, 78, 5, + 5, 30, 28, 22, 35, 30, 58, 22, 65, 30, 8, 39, 16, 48, 38, + 39, 50, 48, 68, 39, 4, 65, 18, 56, 38, 65, 48, 56, 72, 65, + 14, 4, 24, 13, 47, 5, 54, 13, 77, 5, 4, 30, 27, 22, 34, + 30, 57, 22, 64, 30, 7, 39, 17, 48, 37, 39, 51, 48, 67, 39, + 5, 65, 17, 56, 39, 65, 48, 57, 73, 65, 15, 4, 23, 13, 46, + 5, 53, 13, 76, 5, 3, 30, 26, 22, 33, 30, 56, 22, 64, 31, + 6, 39, 18, 48, 36, 39, 52, 48, 66, 39, 6, 65, 16, 56, 40, + 65, 49, 57, 74, 65, 15, 5, 22, 13, 45, 5, 52, 13, 75, 5, + 2, 30, 25, 22, 32, 30, 55, 22, 65, 31, 5, 39, 19, 48, 35, + 39, 53, 48, 65, 39, 7, 65, 16, 57, 41, 65, 50, 57, 75, 65, + 14, 5, 21, 13, 44, 5, 51, 13, 74, 5, 1, 30, 24, 22, 32, + 31, 54, 22, 66, 31, 4, 39, 20, 48, 34, 39, 54, 48, 64, 39, + 8, 65, 17, 57, 42, 65, 51, 57, 76, 65, 13, 5, 20, 13, 43, + 5, 50, 13, 73, 5, 0, 30, 23, 22, 33, 31, 53, 22, 67, 31, + 3, 39, 21, 48, 33, 39, 55, 48, 64, 40, 9, 65, 18, 57, 43, + 65, 52, 57, 77, 65, 12, 5, 19, 13, 42, 5, 49, 13, 72, 5, + 0, 31, 22, 22, 34, 31, 52, 22, 68, 31, 2, 39, 22, 48, 32, + 39, 56, 48, 65, 40, 10, 65, 19, 57, 44, 65, 53, 57, 78, 65, + 11, 5, 18, 13, 41, 5, 48, 13, 71, 5, 1, 31, 21, 22, 35, + 31, 51, 22, 69, 31, 1, 39, 23, 48, 32, 40, 57, 48, 66, 40, + 11, 65, 20, 57, 45, 65, 54, 57, 79, 65, 10, 5, 17, 13, 40, + 5, 48, 14, 70, 5, 2, 31, 20, 22, 36, 31, 50, 22, 70, 31, + 0, 39, 24, 48, 33, 40, 58, 48, 67, 40, 12, 65, 21, 57, 46, + 65, 55, 57, 79, 66, 9, 5, 16, 13, 39, 5, 49, 14, 69, 5, + 3, 31, 19, 22, 37, 31, 49, 22, 71, 31, 0, 40, 25, 48, 34, + 40, 59, 48, 68, 40, 13, 65, 22, 57, 47, 65, 56, 57, 78, 66, + 8, 5, 16, 14, 38, 5, 50, 14, 68, 5, 4, 31, 18, 22, 38, + 31, 48, 22, 72, 31, 1, 40, 26, 48, 35, 40, 60, 48, 69, 40, + 14, 65, 23, 57, 47, 66, 57, 57, 77, 66, 7, 5, 17, 14, 37, + 5, 51, 14, 67, 5, 5, 31, 17, 22, 39, 31, 48, 23, 73, 31, + 2, 40, 27, 48, 36, 40, 61, 48, 70, 40, 15, 65, 24, 57, 46, + 66, 58, 57, 76, 66, 6, 5, 18, 14, 36, 5, 52, 14, 66, 5, + 6, 31, 16, 22, 40, 31, 49, 23, 74, 31, 3, 40, 28, 48, 37, + 40, 62, 48, 71, 40, 15, 66, 25, 57, 45, 66, 59, 57, 75, 66, + 5, 5, 19, 14, 35, 5, 53, 14, 65, 5, 7, 31, 16, 23, 41, + 31, 50, 23, 75, 31, 4, 40, 29, 48, 38, 40, 63, 48, 72, 40, + 14, 66, 26, 57, 44, 66, 60, 57, 74, 66, 4, 5, 20, 14, 34, + 5, 54, 14, 64, 5, 8, 31, 17, 23, 42, 31, 51, 23, 76, 31, + 5, 40, 30, 48, 39, 40, 63, 49, 73, 40, 13, 66, 27, 57, 43, + 66, 61, 57, 73, 66, 3, 5, 21, 14, 33, 5, 55, 14, 64, 6, + 9, 31, 18, 23, 43, 31, 52, 23, 77, 31, 6, 40, 31, 48, 40, + 40, 62, 49, 74, 40, 12, 66, 28, 57, 42, 66, 62, 57, 72, 66, + 2, 5, 22, 14, 32, 5, 56, 14, 65, 6, 10, 31, 19, 23, 44, + 31, 53, 23, 78, 31, 7, 40, 31, 49, 41, 40, 61, 49, 75, 40, + 11, 66, 29, 57, 41, 66, 63, 57, 71, 66, 1, 5, 23, 14, 32, + 6, 57, 14, 66, 6, 11, 31, 20, 23, 45, 31, 54, 23, 79, 31, + 8, 40, 30, 49, 42, 40, 60, 49, 76, 40, 10, 66, 30, 57, 40, + 66, 63, 58, 70, 66, 0, 5, 24, 14, 33, 6, 58, 14, 67, 6, + 12, 31, 21, 23, 46, 31, 55, 23, 79, 32, 9, 40, 29, 49, 43, + 40, 59, 49, 77, 40, 9, 66, 31, 57, 39, 66, 62, 58, 69, 66, + 0, 6, 25, 14, 34, 6, 59, 14, 68, 6, 13, 31, 22, 23, 47, + 31, 56, 23, 78, 32, 10, 40, 28, 49, 44, 40, 58, 49, 78, 40, + 8, 66, 31, 58, 38, 66, 61, 58, 68, 66, 1, 6, 26, 14, 35, + 6, 60, 14, 69, 6, 14, 31, 23, 23, 47, 32, 57, 23, 77, 32, + 11, 40, 27, 49, 45, 40, 57, 49, 79, 40, 7, 66, 30, 58, 37, + 66, 60, 58, 67, 66, 2, 6, 27, 14, 36, 6, 61, 14, 70, 6, + 15, 31, 24, 23, 46, 32, 58, 23, 76, 32, 12, 40, 26, 49, 46, + 40, 56, 49, 79, 41, 6, 66, 29, 58, 36, 66, 59, 58, 66, 66, + 3, 6, 28, 14, 37, 6, 62, 14, 71, 6, 15, 32, 25, 23, 45, + 32, 59, 23, 75, 32, 13, 40, 25, 49, 47, 40, 55, 49, 78, 41, + 5, 66, 28, 58, 35, 66, 58, 58, 65, 66, 4, 6, 29, 14, 38, + 6, 63, 14, 72, 6, 14, 32, 26, 23, 44, 32, 60, 23, 74, 32, + 14, 40, 24, 49, 47, 41, 54, 49, 77, 41, 4, 66, 27, 58, 34, + 66, 57, 58, 64, 66, 5, 6, 30, 14, 39, 6, 63, 15, 73, 6, + 13, 32, 27, 23, 43, 32, 61, 23, 73, 32, 15, 40, 23, 49, 46, + 41, 53, 49, 76, 41, 3, 66, 26, 58, 33, 66, 56, 58, 64, 67, + 6, 6, 31, 14, 40, 6, 62, 15, 74, 6, 12, 32, 28, 23, 42, + 32, 62, 23, 72, 32, 15, 41, 22, 49, 45, 41, 52, 49, 75, 41, + 2, 66, 25, 58, 32, 66, 55, 58, 65, 67, 7, 6, 31, 15, 41, + 6, 61, 15, 75, 6, 11, 32, 29, 23, 41, 32, 63, 23, 71, 32, + 14, 41, 21, 49, 44, 41, 51, 49, 74, 41, 1, 66, 24, 58, 32, + 67, 54, 58, 66, 67, 8, 6, 30, 15, 42, 6, 60, 15, 76, 6, + 10, 32, 30, 23, 40, 32, 63, 24, 70, 32, 13, 41, 20, 49, 43, + 41, 50, 49, 73, 41, 0, 66, 23, 58, 33, 67, 53, 58, 67, 67, + 9, 6, 29, 15, 43, 6, 59, 15, 77, 6, 9, 32, 31, 23, 39, + 32, 62, 24, 69, 32, 12, 41, 19, 49, 42, 41, 49, 49, 72, 41, + 0, 67, 22, 58, 34, 67, 52, 58, 68, 67, 10, 6, 28, 15, 44, + 6, 58, 15, 78, 6, 8, 32, 31, 24, 38, 32, 61, 24, 68, 32, + 11, 41, 18, 49, 41, 41, 48, 49, 71, 41, 1, 67, 21, 58, 35, + 67, 51, 58, 69, 67, 11, 6, 27, 15, 45, 6, 57, 15, 79, 6, + 7, 32, 30, 24, 37, 32, 60, 24, 67, 32, 10, 41, 17, 49, 40, + 41, 48, 50, 70, 41, 2, 67, 20, 58, 36, 67, 50, 58, 70, 67, + 12, 6, 26, 15, 46, 6, 56, 15, 79, 7, 6, 32, 29, 24, 36, + 32, 59, 24, 66, 32, 9, 41, 16, 49, 39, 41, 49, 50, 69, 41, + 3, 67, 19, 58, 37, 67, 49, 58, 71, 67, 13, 6, 25, 15, 47, + 6, 55, 15, 78, 7, 5, 32, 28, 24, 35, 32, 58, 24, 65, 32, + 8, 41, 16, 50, 38, 41, 50, 50, 68, 41, 4, 67, 18, 58, 38, + 67, 48, 58, 72, 67, 14, 6, 24, 15, 47, 7, 54, 15, 77, 7, + 4, 32, 27, 24, 34, 32, 57, 24, 64, 32, 7, 41, 17, 50, 37, + 41, 51, 50, 67, 41, 5, 67, 17, 58, 39, 67, 48, 59, 73, 67, + 15, 6, 23, 15, 46, 7, 53, 15, 76, 7, 3, 32, 26, 24, 33, + 32, 56, 24, 64, 33, 6, 41, 18, 50, 36, 41, 52, 50, 66, 41, + 6, 67, 16, 58, 40, 67, 49, 59, 74, 67, 15, 7, 22, 15, 45, + 7, 52, 15, 75, 7, 2, 32, 25, 24, 32, 32, 55, 24, 65, 33, + 5, 41, 19, 50, 35, 41, 53, 50, 65, 41, 7, 67, 16, 59, 41, + 67, 50, 59, 75, 67, 14, 7, 21, 15, 44, 7, 51, 15, 74, 7, + 1, 32, 24, 24, 32, 33, 54, 24, 66, 33, 4, 41, 20, 50, 34, + 41, 54, 50, 64, 41, 8, 67, 17, 59, 42, 67, 51, 59, 76, 67, + 13, 7, 20, 15, 43, 7, 50, 15, 73, 7, 0, 32, 23, 24, 33, + 33, 53, 24, 67, 33, 3, 41, 21, 50, 33, 41, 55, 50, 64, 42, + 9, 67, 18, 59, 43, 67, 52, 59, 77, 67, 12, 7, 19, 15, 42, + 7, 49, 15, 72, 7, 0, 33, 22, 24, 34, 33, 52, 24, 68, 33, + 2, 41, 22, 50, 32, 41, 56, 50, 65, 42, 10, 67, 19, 59, 44, + 67, 53, 59, 78, 67, 11, 7, 18, 15, 41, 7, 48, 15, 71, 7, + 1, 33, 21, 24, 35, 33, 51, 24, 69, 33, 1, 41, 23, 50, 32, + 42, 57, 50, 66, 42, 11, 67, 20, 59, 45, 67, 54, 59, 79, 67, + 10, 7, 17, 15, 40, 7, 48, 16, 70, 7, 2, 33, 20, 24, 36, + 33, 50, 24, 70, 33, 0, 41, 24, 50, 33, 42, 58, 50, 67, 42, + 12, 67, 21, 59, 46, 67, 55, 59, 64, 51, 9, 7, 16, 15, 39, + 7, 49, 16, 69, 7, 3, 33, 19, 24, 37, 33, 49, 24, 71, 33, + 0, 42, 25, 50, 34, 42, 59, 50, 68, 42, 13, 67, 22, 59, 47, + 67, 56, 59, 65, 51, 8, 7, 16, 16, 38, 7, 50, 16, 68, 7, + 4, 33, 18, 24, 38, 33, 48, 24, 72, 33, 1, 42, 26, 50, 35, + 42, 60, 50, 69, 42, 14, 67, 23, 59, 32, 51, 57, 59, 66, 51, + 7, 7, 17, 16, 37, 7, 51, 16, 67, 7, 5, 33, 17, 24, 39, + 33, 48, 25, 73, 33, 2, 42, 27, 50, 36, 42, 61, 50, 70, 42, + 15, 67, 24, 59, 33, 51, 58, 59, 67, 51, 6, 7, 18, 16, 36, + 7, 52, 16, 66, 7, 6, 33, 16, 24, 40, 33, 49, 25, 74, 33, + 3, 42, 28, 50, 37, 42, 62, 50, 71, 42, 0, 51, 25, 59, 34, + 51, 59, 59, 68, 51, 5, 7, 19, 16, 35, 7, 53, 16, 65, 7, + 7, 33, 16, 25, 41, 33, 50, 25, 75, 33, 4, 42, 29, 50, 38, + 42, 63, 50, 72, 42, 1, 51, 26, 59, 35, 51, 60, 59, 69, 51, + 4, 7, 20, 16, 34, 7, 54, 16, 64, 7, 8, 33, 17, 25, 42, + 33, 51, 25, 76, 33, 5, 42, 30, 50, 39, 42, 48, 34, 73, 42, + 2, 51, 27, 59, 36, 51, 61, 59, 70, 51, 3, 7, 21, 16, 33, + 7, 55, 16, 64, 8, 9, 33, 18, 25, 43, 33, 52, 25, 77, 33, + 6, 42, 31, 50, 40, 42, 49, 34, 74, 42, 3, 51, 28, 59, 37, + 51, 62, 59, 71, 51, 2, 7, 22, 16, 32, 7, 56, 16, 65, 8, + 10, 33, 19, 25, 44, 33, 53, 25, 78, 33, 7, 42, 16, 34, 41, + 42, 50, 34, 75, 42, 4, 51, 29, 59, 38, 51, 63, 59, 72, 51, + 1, 7, 23, 16, 32, 8, 57, 16, 66, 8, 11, 33, 20, 25, 45, + 33, 54, 25, 79, 33, 8, 42, 17, 34, 42, 42, 51, 34, 76, 42, + 5, 51, 30, 59, 39, 51, 63, 60, 73, 51, 0, 7, 24, 16, 33, + 8, 58, 16, 67, 8, 12, 33, 21, 25, 46, 33, 55, 25, 64, 17, + 9, 42, 18, 34, 43, 42, 52, 34, 77, 42, 6, 51, 31, 59, 40, + 51, 62, 60, 74, 51, 0, 8, 25, 16, 34, 8, 59, 16, 68, 8, + 13, 33, 22, 25, 47, 33, 56, 25, 65, 17, 10, 42, 19, 34, 44, + 42, 53, 34, 78, 42, 7, 51, 31, 60, 41, 51, 61, 60, 75, 51, + 1, 8, 26, 16, 35, 8, 60, 16, 69, 8, 14, 33, 23, 25, 32, + 17, 57, 25, 66, 17, 11, 42, 20, 34, 45, 42, 54, 34, 79, 42, + 8, 51, 30, 60, 42, 51, 60, 60, 76, 51, 2, 8, 27, 16, 36, + 8, 61, 16, 70, 8, 15, 33, 24, 25, 33, 17, 58, 25, 67, 17, + 12, 42, 21, 34, 46, 42, 55, 34, 79, 43, 9, 51, 29, 60, 43, + 51, 59, 60, 77, 51, 3, 8, 28, 16, 37, 8, 62, 16, 71, 8, + 0, 17, 25, 25, 34, 17, 59, 25, 68, 17, 13, 42, 22, 34, 47, + 42, 56, 34, 78, 43, 10, 51, 28, 60, 44, 51, 58, 60, 78, 51, + 4, 8, 29, 16, 38, 8, 63, 16, 72, 8, 1, 17, 26, 25, 35, + 17, 60, 25, 69, 17, 14, 42, 23, 34, 47, 43, 57, 34, 77, 43, + 11, 51, 27, 60, 45, 51, 57, 60, 79, 51, 5, 8, 30, 16, 39, + 8, 48, 0, 73, 8, 2, 17, 27, 25, 36, 17, 61, 25, 70, 17, + 15, 42, 24, 34, 46, 43, 58, 34, 76, 43, 12, 51, 26, 60, 46, + 51, 56, 60, 79, 52, 6, 8, 31, 16, 40, 8, 49, 0, 74, 8, + 3, 17, 28, 25, 37, 17, 62, 25, 71, 17, 15, 43, 25, 34, 45, + 43, 59, 34, 75, 43, 13, 51, 25, 60, 47, 51, 55, 60, 78, 52, + 7, 8, 16, 0, 41, 8, 50, 0, 75, 8, 4, 17, 29, 25, 38, + 17, 63, 25, 72, 17, 14, 43, 26, 34, 44, 43, 60, 34, 74, 43, + 14, 51, 24, 60, 47, 52, 54, 60, 77, 52, 8, 8, 17, 0, 42, + 8, 51, 0, 76, 8, 5, 17, 30, 25, 39, 17, 63, 26, 73, 17, + 13, 43, 27, 34, 43, 43, 61, 34, 73, 43, 15, 51, 23, 60, 46, + 52, 53, 60, 76, 52, 9, 8, 18, 0, 43, 8, 52, 0, 77, 8, + 6, 17, 31, 25, 40, 17, 62, 26, 74, 17, 12, 43, 28, 34, 42, + 43, 62, 34, 72, 43, 15, 52, 22, 60, 45, 52, 52, 60, 75, 52, + 10, 8, 19, 0, 44, 8, 53, 0, 78, 8, 7, 17, 31, 26, 41, + 17, 61, 26, 75, 17, 11, 43, 29, 34, 41, 43, 63, 34, 71, 43, + 14, 52, 21, 60, 44, 52, 51, 60, 74, 52, 11, 8, 20, 0, 45, + 8, 54, 0, 79, 8, 8, 17, 30, 26, 42, 17, 60, 26, 76, 17, + 10, 43, 30, 34, 40, 43, 63, 35, 70, 43, 13, 52, 20, 60, 43, + 52, 50, 60, 73, 52, 12, 8, 21, 0, 46, 8, 55, 0, 79, 9, + 9, 17, 29, 26, 43, 17, 59, 26, 77, 17, 9, 43, 31, 34, 39, + 43, 62, 35, 69, 43, 12, 52, 19, 60, 42, 52, 49, 60, 72, 52, + 13, 8, 22, 0, 47, 8, 56, 0, 78, 9, 10, 17, 28, 26, 44, + 17, 58, 26, 78, 17, 8, 43, 31, 35, 38, 43, 61, 35, 68, 43, + 11, 52, 18, 60, 41, 52, 48, 60, 71, 52, 14, 8, 23, 0, 47, + 9, 57, 0, 77, 9, 11, 17, 27, 26, 45, 17, 57, 26, 79, 17, + 7, 43, 30, 35, 37, 43, 60, 35, 67, 43, 10, 52, 17, 60, 40, + 52, 48, 61, 70, 52, 15, 8, 24, 0, 46, 9, 58, 0, 76, 9, + 12, 17, 26, 26, 46, 17, 56, 26, 79, 18, 6, 43, 29, 35, 36, + 43, 59, 35, 66, 43, 9, 52, 16, 60, 39, 52, 49, 61, 69, 52, + 15, 9, 25, 0, 45, 9, 59, 0, 75, 9, 13, 17, 25, 26, 47, + 17, 55, 26, 78, 18, 5, 43, 28, 35, 35, 43, 58, 35, 65, 43, + 8, 52, 16, 61, 38, 52, 50, 61, 68, 52, 14, 9, 26, 0, 44, + 9, 60, 0, 74, 9, 14, 17, 24, 26, 47, 18, 54, 26, 77, 18, + 4, 43, 27, 35, 34, 43, 57, 35, 64, 43, 7, 52, 17, 61, 37, + 52, 51, 61, 67, 52, 13, 9, 27, 0, 43, 9, 61, 0, 73, 9, + 15, 17, 23, 26, 46, 18, 53, 26, 76, 18, 3, 43, 26, 35, 33, + 43, 56, 35, 64, 44, 6, 52, 18, 61, 36, 52, 52, 61, 66, 52, + 12, 9, 28, 0, 42, 9, 62, 0, 72, 9, 15, 18, 22, 26, 45, + 18, 52, 26, 75, 18, 2, 43, 25, 35, 32, 43, 55, 35, 65, 44, + 5, 52, 19, 61, 35, 52, 53, 61, 65, 52, 11, 9, 29, 0, 41, + 9, 63, 0, 71, 9, 14, 18, 21, 26, 44, 18, 51, 26, 74, 18, + 1, 43, 24, 35, 32, 44, 54, 35, 66, 44, 4, 52, 20, 61, 34, + 52, 54, 61, 64, 52, 10, 9, 30, 0, 40, 9, 63, 1, 70, 9, + 13, 18, 20, 26, 43, 18, 50, 26, 73, 18, 0, 43, 23, 35, 33, + 44, 53, 35, 67, 44, 3, 52, 21, 61, 33, 52, 55, 61, 64, 53, + 9, 9, 31, 0, 39, 9, 62, 1, 69, 9, 12, 18, 19, 26, 42, + 18, 49, 26, 72, 18, 0, 44, 22, 35, 34, 44, 52, 35, 68, 44, + 2, 52, 22, 61, 32, 52, 56, 61, 65, 53, 8, 9, 31, 1, 38, + 9, 61, 1, 68, 9, 11, 18, 18, 26, 41, 18, 48, 26, 71, 18, + 1, 44, 21, 35, 35, 44, 51, 35, 69, 44, 1, 52, 23, 61, 32, + 53, 57, 61, 66, 53, 7, 9, 30, 1, 37, 9, 60, 1, 67, 9, + 10, 18, 17, 26, 40, 18, 48, 27, 70, 18, 2, 44, 20, 35, 36, + 44, 50, 35, 70, 44, 0, 52, 24, 61, 33, 53, 58, 61, 67, 53, + 6, 9, 29, 1, 36, 9, 59, 1, 66, 9, 9, 18, 16, 26, 39, + 18, 49, 27, 69, 18, 3, 44, 19, 35, 37, 44, 49, 35, 71, 44, + 0, 53, 25, 61, 34, 53, 59, 61, 68, 53, 5, 9, 28, 1, 35, + 9, 58, 1, 65, 9, 8, 18, 16, 27, 38, 18, 50, 27, 68, 18, + 4, 44, 18, 35, 38, 44, 48, 35, 72, 44, 1, 53, 26, 61, 35, + 53, 60, 61, 69, 53, 4, 9, 27, 1, 34, 9, 57, 1, 64, 9, + 7, 18, 17, 27, 37, 18, 51, 27, 67, 18, 5, 44, 17, 35, 39, + 44, 48, 36, 73, 44, 2, 53, 27, 61, 36, 53, 61, 61, 70, 53, + 3, 9, 26, 1, 33, 9, 56, 1, 64, 10, 6, 18, 18, 27, 36, + 18, 52, 27, 66, 18, 6, 44, 16, 35, 40, 44, 49, 36, 74, 44, + 3, 53, 28, 61, 37, 53, 62, 61, 71, 53, 2, 9, 25, 1, 32, + 9, 55, 1, 65, 10, 5, 18, 19, 27, 35, 18, 53, 27, 65, 18, + 7, 44, 16, 36, 41, 44, 50, 36, 75, 44, 4, 53, 29, 61, 38, + 53, 63, 61, 72, 53, 1, 9, 24, 1, 32, 10, 54, 1, 66, 10, + 4, 18, 20, 27, 34, 18, 54, 27, 64, 18, 8, 44, 17, 36, 42, + 44, 51, 36, 76, 44, 5, 53, 30, 61, 39, 53, 63, 62, 73, 53, + 0, 9, 23, 1, 33, 10, 53, 1, 67, 10, 3, 18, 21, 27, 33, + 18, 55, 27, 64, 19, 9, 44, 18, 36, 43, 44, 52, 36, 77, 44, + 6, 53, 31, 61, 40, 53, 62, 62, 74, 53, 0, 10, 22, 1, 34, + 10, 52, 1, 68, 10, 2, 18, 22, 27, 32, 18, 56, 27, 65, 19, + 10, 44, 19, 36, 44, 44, 53, 36, 78, 44, 7, 53, 31, 62, 41, + 53, 61, 62, 75, 53, 1, 10, 21, 1, 35, 10, 51, 1, 69, 10, + 1, 18, 23, 27, 32, 19, 57, 27, 66, 19, 11, 44, 20, 36, 45, + 44, 54, 36, 79, 44, 8, 53, 30, 62, 42, 53, 60, 62, 76, 53, + 2, 10, 20, 1, 36, 10, 50, 1, 70, 10, 0, 18, 24, 27, 33, + 19, 58, 27, 67, 19, 12, 44, 21, 36, 46, 44, 55, 36, 79, 45, + 9, 53, 29, 62, 43, 53, 59, 62, 77, 53, 3, 10, 19, 1, 37, + 10, 49, 1, 71, 10, 0, 19, 25, 27, 34, 19, 59, 27, 68, 19, + 13, 44, 22, 36, 47, 44, 56, 36, 78, 45, 10, 53, 28, 62, 44, + 53, 58, 62, 78, 53, 4, 10, 18, 1, 38, 10, 48, 1, 72, 10, + 1, 19, 26, 27, 35, 19, 60, 27, 69, 19, 14, 44, 23, 36, 47, + 45, 57, 36, 77, 45, 11, 53, 27, 62, 45, 53, 57, 62, 79, 53, + 5, 10, 17, 1, 39, 10, 48, 2, 73, 10, 2, 19, 27, 27, 36, + 19, 61, 27, 70, 19, 15, 44, 24, 36, 46, 45, 58, 36, 76, 45, + 12, 53, 26, 62, 46, 53, 56, 62, 79, 54, 6, 10, 16, 1, 40, + 10, 49, 2, 74, 10, 3, 19, 28, 27, 37, 19, 62, 27, 71, 19, + 15, 45, 25, 36, 45, 45, 59, 36, 75, 45, 13, 53, 25, 62, 47, + 53, 55, 62, 78, 54, 7, 10, 16, 2, 41, 10, 50, 2, 75, 10, + 4, 19, 29, 27, 38, 19, 63, 27, 72, 19, 14, 45, 26, 36, 44, + 45, 60, 36, 74, 45, 14, 53, 24, 62, 47, 54, 54, 62, 77, 54, + 8, 10, 17, 2, 42, 10, 51, 2, 76, 10, 5, 19, 30, 27, 39, + 19, 63, 28, 73, 19, 13, 45, 27, 36, 43, 45, 61, 36, 73, 45, + 15, 53, 23, 62, 46, 54, 53, 62, 76, 54, 9, 10, 18, 2, 43, + 10, 52, 2, 77, 10, 6, 19, 31, 27, 40, 19, 62, 28, 74, 19, + 12, 45, 28, 36, 42, 45, 62, 36, 72, 45, 15, 54, 22, 62, 45, + 54, 52, 62, 75, 54, 10, 10, 19, 2, 44, 10, 53, 2, 78, 10, + 7, 19, 31, 28, 41, 19, 61, 28, 75, 19, 11, 45, 29, 36, 41, + 45, 63, 36, 71, 45, 14, 54, 21, 62, 44, 54, 51, 62, 74, 54, + 11, 10, 20, 2, 45, 10, 54, 2, 79, 10, 8, 19, 30, 28, 42, + 19, 60, 28, 76, 19, 10, 45, 30, 36, 40, 45, 63, 37, 70, 45, + 13, 54, 20, 62, 43, 54, 50, 62, 73, 54, 12, 10, 21, 2, 46, + 10, 55, 2, 79, 11, 9, 19, 29, 28, 43, 19, 59, 28, 77, 19, + 9, 45, 31, 36, 39, 45, 62, 37, 69, 45, 12, 54, 19, 62, 42, + 54, 49, 62, 72, 54, 13, 10, 22, 2, 47, 10, 56, 2, 78, 11, + 10, 19, 28, 28, 44, 19, 58, 28, 78, 19, 8, 45, 31, 37, 38, + 45, 61, 37, 68, 45, 11, 54, 18, 62, 41, 54, 48, 62, 71, 54, + 14, 10, 23, 2, 47, 11, 57, 2, 77, 11, 11, 19, 27, 28, 45, + 19, 57, 28, 79, 19, 7, 45, 30, 37, 37, 45, 60, 37, 67, 45, + 10, 54, 17, 62, 40, 54, 48, 63, 70, 54, 15, 10, 24, 2, 46, + 11, 58, 2, 76, 11, 12, 19, 26, 28, 46, 19, 56, 28, 79, 20, + 6, 45, 29, 37, 36, 45, 59, 37, 66, 45, 9, 54, 16, 62, 39, + 54, 49, 63, 69, 54, 15, 11, 25, 2, 45, 11, 59, 2, 75, 11, + 13, 19, 25, 28, 47, 19, 55, 28, 78, 20, 5, 45, 28, 37, 35, + 45, 58, 37, 65, 45, 8, 54, 16, 63, 38, 54, 50, 63, 68, 54, + 14, 11, 26, 2, 44, 11, 60, 2, 74, 11, 14, 19, 24, 28, 47, + 20, 54, 28, 77, 20, 4, 45, 27, 37, 34, 45, 57, 37, 64, 45, + 7, 54, 17, 63, 37, 54, 51, 63, 67, 54, 13, 11, 27, 2, 43, + 11, 61, 2, 73, 11, 15, 19, 23, 28, 46, 20, 53, 28, 76, 20, + 3, 45, 26, 37, 33, 45, 56, 37, 64, 46, 6, 54, 18, 63, 36, + 54, 52, 63, 66, 54, 12, 11, 28, 2, 42, 11, 62, 2, 72, 11, + 15, 20, 22, 28, 45, 20, 52, 28, 75, 20, 2, 45, 25, 37, 32, + 45, 55, 37, 65, 46, 5, 54, 19, 63, 35, 54, 53, 63, 65, 54, + 11, 11, 29, 2, 41, 11, 63, 2, 71, 11, 14, 20, 21, 28, 44, + 20, 51, 28, 74, 20, 1, 45, 24, 37, 32, 46, 54, 37, 66, 46, + 4, 54, 20, 63, 34, 54, 54, 63, 64, 54, 10, 11, 30, 2, 40, + 11, 63, 3, 70, 11, 13, 20, 20, 28, 43, 20, 50, 28, 73, 20, + 0, 45, 23, 37, 33, 46, 53, 37, 67, 46, 3, 54, 21, 63, 33, + 54, 55, 63, 64, 55, 9, 11, 31, 2, 39, 11, 62, 3, 69, 11, + 12, 20, 19, 28, 42, 20, 49, 28, 72, 20, 0, 46, 22, 37, 34, + 46, 52, 37, 68, 46, 2, 54, 22, 63, 32, 54, 56, 63, 65, 55, + 8, 11, 31, 3, 38, 11, 61, 3, 68, 11, 11, 20, 18, 28, 41, + 20, 48, 28, 71, 20, 1, 46, 21, 37, 35, 46, 51, 37, 69, 46, + 1, 54, 23, 63, 32, 55, 57, 63, 66, 55, 7, 11, 30, 3, 37, + 11, 60, 3, 67, 11, 10, 20, 17, 28, 40, 20, 48, 29, 70, 20, + 2, 46, 20, 37, 36, 46, 50, 37, 70, 46, 0, 54, 24, 63, 33, + 55, 58, 63, 67, 55, 6, 11, 29, 3, 36, 11, 59, 3, 66, 11, + 9, 20, 16, 28, 39, 20, 49, 29, 69, 20, 3, 46, 19, 37, 37, + 46, 49, 37, 71, 46, 0, 55, 25, 63, 34, 55, 59, 63, 68, 55, + 5, 11, 28, 3, 35, 11, 58, 3, 65, 11, 8, 20, 16, 29, 38, + 20, 50, 29, 68, 20, 4, 46, 18, 37, 38, 46, 48, 37, 72, 46, + 1, 55, 26, 63, 35, 55, 60, 63, 69, 55, 4, 11, 27, 3, 34, + 11, 57, 3, 64, 11, 7, 20, 17, 29, 37, 20, 51, 29, 67, 20, + 5, 46, 17, 37, 39, 46, 48, 38, 73, 46, 2, 55, 27, 63, 36, + 55, 61, 63, 70, 55, 3, 11, 26, 3, 33, 11, 56, 3, 64, 12, + 6, 20, 18, 29, 36, 20, 52, 29, 66, 20, 6, 46, 16, 37, 40, + 46, 49, 38, 74, 46, 3, 55, 28, 63, 37, 55, 62, 63, 71, 55, + 2, 11, 25, 3, 32, 11, 55, 3, 65, 12, 5, 20, 19, 29, 35, + 20, 53, 29, 65, 20, 7, 46, 16, 38, 41, 46, 50, 38, 75, 46, + 4, 55, 29, 63, 38, 55, 63, 63, 72, 55, 1, 11, 24, 3, 32, + 12, 54, 3, 66, 12, 4, 20, 20, 29, 34, 20, 54, 29, 64, 20, + 8, 46, 17, 38, 42, 46, 51, 38, 76, 46, 5, 55, 30, 63, 39, + 55, 63, 64, 73, 55, 0, 11, 23, 3, 33, 12, 53, 3, 67, 12, + 3, 20, 21, 29, 33, 20, 55, 29, 64, 21, 9, 46, 18, 38, 43, + 46, 52, 38, 77, 46, 6, 55, 31, 63, 40, 55, 62, 64, 74, 55, + 0, 12, 22, 3, 34, 12, 52, 3, 68, 12, 2, 20, 22, 29, 32, + 20, 56, 29, 65, 21, 10, 46, 19, 38, 44, 46, 53, 38, 78, 46, + 7, 55, 31, 64, 41, 55, 61, 64, 75, 55, 1, 12, 21, 3, 35, + 12, 51, 3, 69, 12, 1, 20, 23, 29, 32, 21, 57, 29, 66, 21, + 11, 46, 20, 38, 45, 46, 54, 38, 79, 46, 8, 55, 30, 64, 42, + 55, 60, 64, 76, 55, 2, 12, 20, 3, 36, 12, 50, 3, 70, 12, + 0, 20, 24, 29, 33, 21, 58, 29, 67, 21, 12, 46, 21, 38, 46, + 46, 55, 38, 79, 47, 9, 55, 29, 64, 43, 55, 59, 64, 77, 55, + 3, 12, 19, 3, 37, 12, 49, 3, 71, 12, 0, 21, 25, 29, 34, + 21, 59, 29, 68, 21, 13, 46, 22, 38, 47, 46, 56, 38, 78, 47, + 10, 55, 28, 64, 44, 55, 58, 64, 78, 55, 4, 12, 18, 3, 38, + 12, 48, 3, 72, 12, 1, 21, 26, 29, 35, 21, 60, 29, 69, 21, + 14, 46, 23, 38, 47, 47, 57, 38, 77, 47, 11, 55, 27, 64, 45, + 55, 57, 64, 79, 55, 5, 12, 17, 3, 39, 12, 48, 4, 73, 12, + 2, 21, 27, 29, 36, 21, 61, 29, 70, 21, 15, 46, 24, 38, 46, + 47, 58, 38, 76, 47, 12, 55, 26, 64, 46, 55, 56, 64, 79, 56, + 6, 12, 16, 3, 40, 12, 49, 4, 74, 12, 3, 21, 28, 29, 37, + 21, 62, 29, 71, 21, 15, 47, 25, 38, 45, 47, 59, 38, 75, 47, + 13, 55, 25, 64, 47, 55, 55, 64, 78, 56, 7, 12, 16, 4, 41, + 12, 50, 4, 75, 12, 4, 21, 29, 29, 38, 21, 63, 29, 72, 21, + 14, 47, 26, 38, 44, 47, 60, 38, 74, 47, 14, 55, 24, 64, 47, + 56, 54, 64, 77, 56, 8, 12, 17, 4, 42, 12, 51, 4, 76, 12, + 5, 21, 30, 29, 39, 21, 63, 30, 73, 21, 13, 47, 27, 38, 43, + 47, 61, 38, 73, 47, 15, 55, 23, 64, 46, 56, 53, 64, 76, 56, + 9, 12, 18, 4, 43, 12, 52, 4, 77, 12, 6, 21, 31, 29, 40, + 21, 62, 30, 74, 21, 12, 47, 28, 38, 42, 47, 62, 38, 72, 47, + 15, 56, 22, 64, 45, 56, 52, 64, 75, 56, 10, 12, 19, 4, 44, + 12, 53, 4, 78, 12, 7, 21, 31, 30, 41, 21, 61, 30, 75, 21, + 11, 47, 29, 38, 41, 47, 63, 38, 71, 47, 14, 56, 21, 64, 44, + 56, 51, 64, 74, 56, 11, 12, 20, 4, 45, 12, 54, 4, 79, 12, + 8, 21, 30, 30, 42, 21, 60, 30, 76, 21, 10, 47, 30, 38, 40, + 47, 63, 39, 70, 47, 13, 56, 20, 64, 43, 56, 50, 64, 73, 56, + 12, 12, 21, 4, 46, 12, 55, 4, 79, 13, 9, 21, 29, 30, 43, + 21, 59, 30, 77, 21, 9, 47, 31, 38, 39, 47, 62, 39, 69, 47, + 12, 56, 19, 64, 42, 56, 49, 64, 72, 56, 13, 12, 22, 4, 47, + 12, 56, 4, 78, 13, 10, 21, 28, 30, 44, 21, 58, 30, 78, 21, + 8, 47, 31, 39, 38, 47, 61, 39, 68, 47, 11, 56, 18, 64, 41, + 56, 48, 64, 71, 56, 14, 12, 23, 4, 47, 13, 57, 4, 77, 13, + 11, 21, 27, 30, 45, 21, 57, 30, 79, 21, 7, 47, 30, 39, 37, + 47, 60, 39, 67, 47, 10, 56, 17, 64, 40, 56, 48, 65, 70, 56, + 15, 12, 24, 4, 46, 13, 58, 4, 76, 13, 12, 21, 26, 30, 46, + 21, 56, 30, 79, 22, 6, 47, 29, 39, 36, 47, 59, 39, 66, 47, + 9, 56, 16, 64, 39, 56, 49, 65, 69, 56, 15, 13, 25, 4, 45, + 13, 59, 4, 75, 13, 13, 21, 25, 30, 47, 21, 55, 30, 78, 22, + 5, 47, 28, 39, 35, 47, 58, 39, 65, 47, 8, 56, 16, 65, 38, + 56, 50, 65, 68, 56, 14, 13, 26, 4, 44, 13, 60, 4, 74, 13, + 14, 21, 24, 30, 47, 22, 54, 30, 77, 22, 4, 47, 27, 39, 34, + 47, 57, 39, 64, 47, 7, 56, 17, 65, 37, 56, 51, 65, 67, 56, + 13, 13, 27, 4, 43, 13, 61, 4, 73, 13, 15, 21, 23, 30, 46, + 22, 53, 30, 76, 22, 3, 47, 26, 39, 33, 47, 56, 39, 64, 48, + 6, 56, 18, 65, 36, 56, 52, 65, 66, 56, 12, 13, 28, 4, 42, + 13, 62, 4, 72, 13, 15, 22, 22, 30, 45, 22, 52, 30, 75, 22, + 2, 47, 25, 39, 32, 47, 55, 39, 65, 48, 5, 56, 19, 65, 35, + 56, 53, 65, 65, 56, 11, 13, 29, 4, 41, 13, 63, 4, 71, 13, + 14, 22, 21, 30, 44, 22, 51, 30, 74, 22, 1, 47, 24, 39, 32, + 48, 54, 39, 66, 48, 4, 56, 20, 65, 34, 56, 54, 65, 64, 56, + 10, 13, 30, 4, 40, 13, 63, 5, 70, 13, 13, 22, 20, 30, 43, + 22, 50, 30, 73, 22, 0, 47, 23, 39, 33, 48, 53, 39, 67, 48, + 3, 56, 21, 65, 33, 56, 55, 65, 64, 57, 9, 13, 31, 4, 39, + 13, 62, 5, 69, 13, 12, 22, 19, 30, 42, 22, 49, 30, 72, 22, + 0, 48, 22, 39, 34, 48, 52, 39, 68, 48, 2, 56, 22, 65, 32, + 56, 56, 65, 65, 57, 8, 13, 31, 5, 38, 13, 61, 5, 68, 13, + 11, 22, 18, 30, 41, 22, 48, 30, 71, 22, 1, 48, 21, 39, 35, + 48, 51, 39, 69, 48, 1, 56, 23, 65, 32, 57, 57, 65, 66, 57, + 7, 13, 30, 5, 37, 13, 60, 5, 67, 13, 10, 22, 17, 30, 40, + 22, 48, 31, 70, 22, 2, 48, 20, 39, 36, 48, 50, 39, 70, 48, + 0, 56, 24, 65, 33, 57, 58, 65, 67, 57, 6, 13, 29, 5, 36, + 13, 59, 5, 66, 13, 9, 22, 16, 30, 39, 22, 49, 31, 69, 22, + 3, 48, 19, 39, 37, 48, 49, 39, 71, 48, 0, 57, 25, 65, 34, + 57, 59, 65, 68, 57, 5, 13, 28, 5, 35, 13, 58, 5, 65, 13, + 8, 22, 16, 31, 38, 22, 50, 31, 68, 22, 4, 48, 18, 39, 38, + 48, 48, 39, 72, 48, 1, 57, 26, 65, 35, 57, 60, 65, 69, 57, + 4, 13, 27, 5, 34, 13, 57, 5, 64, 13, 7, 22, 17, 31, 37, + 22, 51, 31, 67, 22, 5, 48, 17, 39, 39, 48, 48, 40, 73, 48, + 2, 57, 27, 65, 36, 57, 61, 65, 70, 57, 3, 13, 26, 5, 33, + 13, 56, 5, 64, 14, 6, 22, 18, 31, 36, 22, 52, 31, 66, 22, + 6, 48, 16, 39, 40, 48, 49, 40, 74, 48, 3, 57, 28, 65, 37, + 57, 62, 65, 71, 57, 2, 13, 25, 5, 32, 13, 55, 5, 65, 14, + 5, 22, 19, 31, 35, 22, 53, 31, 65, 22, 7, 48, 16, 40, 41, + 48, 50, 40, 75, 48, 4, 57, 29, 65, 38, 57, 63, 65, 72, 57, + 1, 13, 24, 5, 32, 14, 54, 5, 66, 14, 4, 22, 20, 31, 34, + 22, 54, 31, 64, 22, 8, 48, 17, 40, 42, 48, 51, 40, 76, 48, + 5, 57, 30, 65, 39, 57, 63, 66, 73, 57, 0, 13, 23, 5, 33, + 14, 53, 5, 67, 14, 3, 22, 21, 31, 33, 22, 55, 31, 64, 23, + 9, 48, 18, 40, 43, 48, 52, 40, 77, 48, 6, 57, 31, 65, 40, + 57, 62, 66, 74, 57, 0, 14, 22, 5, 34, 14, 52, 5, 68, 14, + 2, 22, 22, 31, 32, 22, 56, 31, 65, 23, 10, 48, 19, 40, 44, + 48, 53, 40, 78, 48, 7, 57, 31, 66, 41, 57, 61, 66, 75, 57, + 1, 14, 21, 5, 35, 14, 51, 5, 69, 14, 1, 22, 23, 31, 32, + 23, 57, 31, 66, 23, 11, 48, 20, 40, 45, 48, 54, 40, 79, 48, + 8, 57, 30, 66, 42, 57, 60, 66, 76, 57, 2, 14, 20, 5, 36, + 14, 50, 5, 70, 14, 0, 22, 24, 31, 33, 23, 58, 31, 67, 23, + 12, 48, 21, 40, 46, 48, 55, 40, 79, 49, 9, 57, 29, 66, 43, + 57, 59, 66, 77, 57, 3, 14, 19, 5, 37, 14, 49, 5, 71, 14, + 0, 23, 25, 31, 34, 23, 59, 31, 68, 23, 13, 48, 22, 40, 47, + 48, 56, 40, 78, 49, 10, 57, 28, 66, 44, 57, 58, 66, 78, 57, + 4, 14, 18, 5, 38, 14, 48, 5, 72, 14, 1, 23, 26, 31, 35, + 23, 60, 31, 69, 23, 14, 48, 23, 40, 47, 49, 57, 40, 77, 49, + 11, 57, 27, 66, 45, 57, 57, 66, 79, 57, 5, 14, 17, 5, 39, + 14, 48, 6, 73, 14, 2, 23, 27, 31, 36, 23, 61, 31, 70, 23, + 15, 48, 24, 40, 46, 49, 58, 40, 76, 49, 12, 57, 26, 66, 46, + 57, 56, 66, 79, 58, 6, 14, 16, 5, 40, 14, 49, 6, 74, 14, + 3, 23, 28, 31, 37, 23, 62, 31, 71, 23, 15, 49, 25, 40, 45, + 49, 59, 40, 75, 49, 13, 57, 25, 66, 47, 57, 55, 66, 78, 58, + 7, 14, 16, 6, 41, 14, 50, 6, 75, 14, 4, 23, 29, 31, 38, + 23, 63, 31, 72, 23, 14, 49, 26, 40, 44, 49, 60, 40, 74, 49, + 14, 57, 24, 66, 47, 58, 54, 66, 77, 58, 8, 14, 17, 6, 42, + 14, 51, 6, 76, 14, 5, 23, 30, 31, 39, 23, 63, 32, 73, 23, + 13, 49, 27, 40, 43, 49, 61, 40, 73, 49, 15, 57, 23, 66, 46, + 58, 53, 66, 76, 58, 9, 14, 18, 6, 43, 14, 52, 6, 77, 14, + 6, 23, 31, 31, 40, 23, 62, 32, 74, 23, 12, 49, 28, 40, 42, + 49, 62, 40, 72, 49, 15, 58, 22, 66, 45, 58, 52, 66, 75, 58, + 10, 14, 19, 6, 44, 14, 53, 6, 78, 14, 7, 23, 31, 32, 41, + 23, 61, 32, 75, 23, 11, 49, 29, 40, 41, 49, 63, 40, 71, 49, + 14, 58, 21, 66, 44, 58, 51, 66, 74, 58, 11, 14, 20, 6, 45, + 14, 54, 6, 79, 14, 8, 23, 30, 32, 42, 23, 60, 32, 76, 23, + 10, 49, 30, 40, 40, 49, 63, 41, 70, 49, 13, 58, 20, 66, 43, + 58, 50, 66, 73, 58, 12, 14, 21, 6, 46, 14, 55, 6, 79, 15, + 9, 23, 29, 32, 43, 23, 59, 32, 77, 23, 9, 49, 31, 40, 39, + 49, 62, 41, 69, 49, 12, 58, 19, 66, 42, 58, 49, 66, 72, 58, + 13, 14, 22, 6, 47, 14, 56, 6, 78, 15, 10, 23, 28, 32, 44, + 23, 58, 32, 78, 23, 8, 49, 31, 41, 38, 49, 61, 41, 68, 49, + 11, 58, 18, 66, 41, 58, 48, 66, 71, 58, 14, 14, 23, 6, 47, + 15, 57, 6, 77, 15, 11, 23, 27, 32, 45, 23, 57, 32, 79, 23, + 7, 49, 30, 41, 37, 49, 60, 41, 67, 49, 10, 58, 17, 66, 40, + 58, 48, 67, 70, 58, 15, 14, 24, 6, 46, 15, 58, 6, 76, 15, + 12, 23, 26, 32, 46, 23, 56, 32, 79, 24, 6, 49, 29, 41, 36, + 49, 59, 41, 66, 49, 9, 58, 16, 66, 39, 58, 49, 67, 69, 58, + 15, 15, 25, 6, 45, 15, 59, 6, 75, 15, 13, 23, 25, 32, 47, + 23, 55, 32, 78, 24, 5, 49, 28, 41, 35, 49, 58, 41, 65, 49, + 8, 58, 16, 67, 38, 58, 50, 67, 68, 58, 14, 15, 26, 6, 44, + 15, 60, 6, 74, 15, 14, 23, 24, 32, 47, 24, 54, 32, 77, 24, + 4, 49, 27, 41, 34, 49, 57, 41, 64, 49, 7, 58, 17, 67, 37, + 58, 51, 67, 67, 58, 13, 15, 27, 6, 43, 15, 61, 6, 73, 15, + 15, 23, 23, 32, 46, 24, 53, 32, 76, 24, 3, 49, 26, 41, 33, + 49, 56, 41, 64, 50, 6, 58, 18, 67, 36, 58, 52, 67, 66, 58, + 12, 15, 28, 6, 42, 15, 62, 6, 72, 15, 15, 24, 22, 32, 45, + 24, 52, 32, 75, 24, 2, 49, 25, 41, 32, 49, 55, 41, 65, 50, + 5, 58, 19, 67, 35, 58, 53, 67, 65, 58, 11, 15, 29, 6, 41, + 15, 63, 6, 71, 15, 14, 24, 21, 32, 44, 24, 51, 32, 74, 24, + 1, 49, 24, 41, 32, 50, 54, 41, 66, 50, 4, 58, 20, 67, 34, + 58, 54, 67, 64, 58, 10, 15, 30, 6, 40, 15, 63, 7, 70, 15, + 13, 24, 20, 32, 43, 24, 50, 32, 73, 24, 0, 49, 23, 41, 33, + 50, 53, 41, 67, 50, 3, 58, 21, 67, 33, 58, 55, 67, 64, 59, + 9, 15, 31, 6, 39, 15, 62, 7, 69, 15, 12, 24, 19, 32, 42, + 24, 49, 32, 72, 24, 0, 50, 22, 41, 34, 50, 52, 41, 68, 50, + 2, 58, 22, 67, 32, 58, 56, 67, 65, 59, 8, 15, 31, 7, 38, + 15, 61, 7, 68, 15, 11, 24, 18, 32, 41, 24, 48, 32, 71, 24, + 1, 50, 21, 41, 35, 50, 51, 41, 69, 50, 1, 58, 23, 67, 32, + 59, 57, 67, 66, 59, 7, 15, 30, 7, 37, 15, 60, 7, 67, 15, + 10, 24, 17, 32, 40, 24, 48, 33, 70, 24, 2, 50, 20, 41, 36, + 50, 50, 41, 70, 50, 0, 58, 24, 67, 33, 59, 58, 67, 67, 59, + 6, 15, 29, 7, 36, 15, 59, 7, 66, 15, 9, 24, 16, 32, 39, + 24, 49, 33, 69, 24, 3, 50, 19, 41, 37, 50, 49, 41, 71, 50, + 0, 59, 25, 67, 34, 59, 59, 67, 68, 59, 5, 15, 28, 7, 35, + 15, 58, 7, 65, 15, 8, 24, 16, 33, 38, 24, 50, 33, 68, 24, + 4, 50, 18, 41, 38, 50, 48, 41, 72, 50, 1, 59, 26, 67, 35, + 59, 60, 67, 69, 59, 4, 15, 27, 7, 34, 15, 57, 7, 64, 15, + 7, 24, 17, 33, 37, 24, 51, 33, 67, 24, 5, 50, 17, 41, 39, + 50, 48, 42, 73, 50, 2, 59, 27, 67, 36, 59, 61, 67, 70, 59, + 3, 15, 26, 7, 33, 15, 56, 7, 64, 16, 6, 24, 18, 33, 36, + 24, 52, 33, 66, 24, 6, 50, 16, 41, 40, 50, 49, 42, 74, 50, + 3, 59, 28, 67, 37, 59, 62, 67, 71, 59, 2, 15, 25, 7, 32, + 15, 55, 7, 65, 16, 5, 24, 19, 33, 35, 24, 53, 33, 65, 24, + 7, 50, 16, 42, 41, 50, 50, 42, 75, 50, 4, 59, 29, 67, 38, + 59, 63, 67, 72, 59, 1, 15, 24, 7, 32, 16, 54, 7, 66, 16, + 4, 24, 20, 33, 34, 24, 54, 33, 64, 24, 8, 50, 17, 42, 42, + 50, 51, 42, 76, 50, 5, 59, 30, 67, 39, 59, 48, 51, 73, 59, + 0, 15, 23, 7, 33, 16, 53, 7, 67, 16, 3, 24, 21, 33, 33, + 24, 55, 33, 64, 25, 9, 50, 18, 42, 43, 50, 52, 42, 77, 50, + 6, 59, 31, 67, 40, 59, 49, 51, 74, 59, 0, 16, 22, 7, 34, + 16, 52, 7, 68, 16, 2, 24, 22, 33, 32, 24, 56, 33, 65, 25, + 10, 50, 19, 42, 44, 50, 53, 42, 78, 50, 7, 59, 16, 51, 41, + 59, 50, 51, 75, 59, 1, 16, 21, 7, 35, 16, 51, 7, 69, 16, + 1, 24, 23, 33, 32, 25, 57, 33, 66, 25, 11, 50, 20, 42, 45, + 50, 54, 42, 79, 50, 8, 59, 17, 51, 42, 59, 51, 51, 76, 59, + 2, 16, 20, 7, 36, 16, 50, 7, 70, 16, 0, 24, 24, 33, 33, + 25, 58, 33, 67, 25, 12, 50, 21, 42, 46, 50, 55, 42, 64, 34, + 9, 59, 18, 51, 43, 59, 52, 51, 77, 59, 3, 16, 19, 7, 37, + 16, 49, 7, 71, 16, 0, 25, 25, 33, 34, 25, 59, 33, 68, 25, + 13, 50, 22, 42, 47, 50, 56, 42, 65, 34, 10, 59, 19, 51, 44, + 59, 53, 51, 78, 59, 4, 16, 18, 7, 38, 16, 48, 7, 72, 16, + 1, 25, 26, 33, 35, 25, 60, 33, 69, 25, 14, 50, 23, 42, 32, + 34, 57, 42, 66, 34, 11, 59, 20, 51, 45, 59, 54, 51, 79, 59, + 5, 16, 17, 7, 39, 16, 48, 8, 73, 16, 2, 25, 27, 33, 36, + 25, 61, 33, 70, 25, 15, 50, 24, 42, 33, 34, 58, 42, 67, 34, + 12, 59, 21, 51, 46, 59, 55, 51, 79, 60, 6, 16, 16, 7, 40, + 16, 49, 8, 74, 16, 3, 25, 28, 33, 37, 25, 62, 33, 71, 25, + 0, 34, 25, 42, 34, 34, 59, 42, 68, 34, 13, 59, 22, 51, 47, + 59, 56, 51, 78, 60, 7, 16, 16, 8, 41, 16, 50, 8, 75, 16, + 4, 25, 29, 33, 38, 25, 63, 33, 72, 25, 1, 34, 26, 42, 35, + 34, 60, 42, 69, 34, 14, 59, 23, 51, 47, 60, 57, 51, 77, 60, + 8, 16, 17, 8, 42, 16, 51, 8, 76, 16, 5, 25, 30, 33, 39, + 25, 48, 17, 73, 25, 2, 34, 27, 42, 36, 34, 61, 42, 70, 34, + 15, 59, 24, 51, 46, 60, 58, 51, 76, 60, 9, 16, 18, 8, 43, + 16, 52, 8, 77, 16, 6, 25, 31, 33, 40, 25, 49, 17, 74, 25, + 3, 34, 28, 42, 37, 34, 62, 42, 71, 34, 15, 60, 25, 51, 45, + 60, 59, 51, 75, 60, 10, 16, 19, 8, 44, 16, 53, 8, 78, 16, + 7, 25, 16, 17, 41, 25, 50, 17, 75, 25, 4, 34, 29, 42, 38, + 34, 63, 42, 72, 34, 14, 60, 26, 51, 44, 60, 60, 51, 74, 60, + 11, 16, 20, 8, 45, 16, 54, 8, 79, 16, 8, 25, 17, 17, 42, + 25, 51, 17, 76, 25, 5, 34, 30, 42, 39, 34, 63, 43, 73, 34, + 13, 60, 27, 51, 43, 60, 61, 51, 73, 60, 12, 16, 21, 8, 46, + 16, 55, 8, 64, 0, 9, 25, 18, 17, 43, 25, 52, 17, 77, 25, + 6, 34, 31, 42, 40, 34, 62, 43, 74, 34, 12, 60, 28, 51, 42, + 60, 62, 51, 72, 60, 13, 16, 22, 8, 47, 16, 56, 8, 65, 0, + 10, 25, 19, 17, 44, 25, 53, 17, 78, 25, 7, 34, 31, 43, 41, + 34, 61, 43, 75, 34, 11, 60, 29, 51, 41, 60, 63, 51, 71, 60, + 14, 16, 23, 8, 32, 0, 57, 8, 66, 0, 11, 25, 20, 17, 45, + 25, 54, 17, 79, 25, 8, 34, 30, 43, 42, 34, 60, 43, 76, 34, + 10, 60, 30, 51, 40, 60, 63, 52, 70, 60, 15, 16, 24, 8, 33, + 0, 58, 8, 67, 0, 12, 25, 21, 17, 46, 25, 55, 17, 79, 26, + 9, 34, 29, 43, 43, 34, 59, 43, 77, 34, 9, 60, 31, 51, 39, + 60, 62, 52, 69, 60, +}; + +static const uint8_t hq_tab_07[] = { + 0, 0, 23, 8, 32, 0, 55, 8, 64, 0, 87, 8, 13, 25, 22, + 17, 44, 26, 54, 17, 72, 26, 86, 17, 12, 34, 24, 43, 44, 34, + 52, 43, 73, 35, 80, 43, 4, 60, 25, 52, 32, 60, 53, 52, 60, + 60, 81, 52, 1, 0, 24, 8, 33, 0, 56, 8, 65, 0, 88, 8, + 14, 25, 23, 17, 43, 26, 55, 17, 71, 26, 87, 17, 13, 34, 23, + 43, 44, 35, 51, 43, 72, 35, 79, 43, 3, 60, 24, 52, 31, 60, + 52, 52, 60, 61, 80, 52, 2, 0, 25, 8, 34, 0, 57, 8, 66, + 0, 89, 8, 14, 26, 24, 17, 42, 26, 56, 17, 70, 26, 88, 17, + 14, 34, 22, 43, 43, 35, 50, 43, 71, 35, 78, 43, 2, 60, 23, + 52, 30, 60, 51, 52, 61, 61, 79, 52, 3, 0, 26, 8, 35, 0, + 58, 8, 67, 0, 89, 9, 13, 26, 25, 17, 41, 26, 57, 17, 69, + 26, 89, 17, 14, 35, 21, 43, 42, 35, 49, 43, 70, 35, 77, 43, + 1, 60, 22, 52, 30, 61, 50, 52, 62, 61, 78, 52, 4, 0, 27, + 8, 36, 0, 59, 8, 68, 0, 88, 9, 12, 26, 26, 17, 40, 26, + 58, 17, 68, 26, 89, 18, 13, 35, 20, 43, 41, 35, 48, 43, 69, + 35, 76, 43, 0, 60, 21, 52, 31, 61, 49, 52, 63, 61, 77, 52, + 5, 0, 28, 8, 37, 0, 59, 9, 69, 0, 87, 9, 11, 26, 27, + 17, 39, 26, 59, 17, 67, 26, 88, 18, 12, 35, 19, 43, 40, 35, + 47, 43, 68, 35, 75, 43, 0, 61, 20, 52, 32, 61, 48, 52, 64, + 61, 76, 52, 6, 0, 29, 8, 38, 0, 58, 9, 70, 0, 86, 9, + 10, 26, 28, 17, 38, 26, 59, 18, 66, 26, 87, 18, 11, 35, 18, + 43, 39, 35, 46, 43, 67, 35, 75, 44, 1, 61, 19, 52, 33, 61, + 47, 52, 65, 61, 75, 52, 7, 0, 29, 9, 39, 0, 57, 9, 71, + 0, 85, 9, 9, 26, 29, 17, 37, 26, 58, 18, 65, 26, 86, 18, + 10, 35, 17, 43, 38, 35, 45, 43, 66, 35, 76, 44, 2, 61, 18, + 52, 34, 61, 46, 52, 66, 61, 75, 53, 8, 0, 28, 9, 40, 0, + 56, 9, 72, 0, 84, 9, 8, 26, 29, 18, 36, 26, 57, 18, 64, + 26, 85, 18, 9, 35, 16, 43, 37, 35, 45, 44, 65, 35, 77, 44, + 3, 61, 17, 52, 35, 61, 45, 52, 67, 61, 76, 53, 9, 0, 27, + 9, 41, 0, 55, 9, 73, 0, 83, 9, 7, 26, 28, 18, 35, 26, + 56, 18, 63, 26, 84, 18, 8, 35, 15, 43, 36, 35, 46, 44, 64, + 35, 78, 44, 4, 61, 16, 52, 36, 61, 45, 53, 68, 61, 77, 53, + 10, 0, 26, 9, 42, 0, 54, 9, 74, 0, 82, 9, 6, 26, 27, + 18, 34, 26, 55, 18, 62, 26, 83, 18, 7, 35, 15, 44, 35, 35, + 47, 44, 63, 35, 79, 44, 5, 61, 15, 52, 37, 61, 46, 53, 69, + 61, 78, 53, 11, 0, 25, 9, 43, 0, 53, 9, 74, 1, 81, 9, + 5, 26, 26, 18, 33, 26, 54, 18, 61, 26, 82, 18, 6, 35, 16, + 44, 34, 35, 48, 44, 62, 35, 80, 44, 6, 61, 15, 53, 38, 61, + 47, 53, 70, 61, 79, 53, 12, 0, 24, 9, 44, 0, 52, 9, 73, + 1, 80, 9, 4, 26, 25, 18, 32, 26, 53, 18, 60, 26, 81, 18, + 5, 35, 17, 44, 33, 35, 49, 44, 61, 35, 81, 44, 7, 61, 16, + 53, 39, 61, 48, 53, 71, 61, 80, 53, 13, 0, 23, 9, 44, 1, + 51, 9, 72, 1, 79, 9, 3, 26, 24, 18, 31, 26, 52, 18, 60, + 27, 80, 18, 4, 35, 18, 44, 32, 35, 50, 44, 60, 35, 82, 44, + 8, 61, 17, 53, 40, 61, 49, 53, 72, 61, 81, 53, 14, 0, 22, + 9, 43, 1, 50, 9, 71, 1, 78, 9, 2, 26, 23, 18, 30, 26, + 51, 18, 61, 27, 79, 18, 3, 35, 19, 44, 31, 35, 51, 44, 60, + 36, 83, 44, 9, 61, 18, 53, 41, 61, 50, 53, 73, 61, 82, 53, + 14, 1, 21, 9, 42, 1, 49, 9, 70, 1, 77, 9, 1, 26, 22, + 18, 30, 27, 50, 18, 62, 27, 78, 18, 2, 35, 20, 44, 30, 35, + 52, 44, 61, 36, 84, 44, 10, 61, 19, 53, 42, 61, 51, 53, 74, + 61, 83, 53, 13, 1, 20, 9, 41, 1, 48, 9, 69, 1, 76, 9, + 0, 26, 21, 18, 31, 27, 49, 18, 63, 27, 77, 18, 1, 35, 21, + 44, 30, 36, 53, 44, 62, 36, 85, 44, 11, 61, 20, 53, 43, 61, + 52, 53, 74, 62, 84, 53, 12, 1, 19, 9, 40, 1, 47, 9, 68, + 1, 75, 9, 0, 27, 20, 18, 32, 27, 48, 18, 64, 27, 76, 18, + 0, 35, 22, 44, 31, 36, 54, 44, 63, 36, 86, 44, 12, 61, 21, + 53, 44, 61, 53, 53, 73, 62, 85, 53, 11, 1, 18, 9, 39, 1, + 46, 9, 67, 1, 75, 10, 1, 27, 19, 18, 33, 27, 47, 18, 65, + 27, 75, 18, 0, 36, 23, 44, 32, 36, 55, 44, 64, 36, 87, 44, + 13, 61, 22, 53, 44, 62, 54, 53, 72, 62, 86, 53, 10, 1, 17, + 9, 38, 1, 45, 9, 66, 1, 76, 10, 2, 27, 18, 18, 34, 27, + 46, 18, 66, 27, 75, 19, 1, 36, 24, 44, 33, 36, 56, 44, 65, + 36, 88, 44, 14, 61, 23, 53, 43, 62, 55, 53, 71, 62, 87, 53, + 9, 1, 16, 9, 37, 1, 45, 10, 65, 1, 77, 10, 3, 27, 17, + 18, 35, 27, 45, 18, 67, 27, 76, 19, 2, 36, 25, 44, 34, 36, + 57, 44, 66, 36, 89, 44, 14, 62, 24, 53, 42, 62, 56, 53, 70, + 62, 88, 53, 8, 1, 15, 9, 36, 1, 46, 10, 64, 1, 78, 10, + 4, 27, 16, 18, 36, 27, 45, 19, 68, 27, 77, 19, 3, 36, 26, + 44, 35, 36, 58, 44, 67, 36, 89, 45, 13, 62, 25, 53, 41, 62, + 57, 53, 69, 62, 89, 53, 7, 1, 15, 10, 35, 1, 47, 10, 63, + 1, 79, 10, 5, 27, 15, 18, 37, 27, 46, 19, 69, 27, 78, 19, + 4, 36, 27, 44, 36, 36, 59, 44, 68, 36, 88, 45, 12, 62, 26, + 53, 40, 62, 58, 53, 68, 62, 89, 54, 6, 1, 16, 10, 34, 1, + 48, 10, 62, 1, 80, 10, 6, 27, 15, 19, 38, 27, 47, 19, 70, + 27, 79, 19, 5, 36, 28, 44, 37, 36, 59, 45, 69, 36, 87, 45, + 11, 62, 27, 53, 39, 62, 59, 53, 67, 62, 88, 54, 5, 1, 17, + 10, 33, 1, 49, 10, 61, 1, 81, 10, 7, 27, 16, 19, 39, 27, + 48, 19, 71, 27, 80, 19, 6, 36, 29, 44, 38, 36, 58, 45, 70, + 36, 86, 45, 10, 62, 28, 53, 38, 62, 59, 54, 66, 62, 87, 54, + 4, 1, 18, 10, 32, 1, 50, 10, 60, 1, 82, 10, 8, 27, 17, + 19, 40, 27, 49, 19, 72, 27, 81, 19, 7, 36, 29, 45, 39, 36, + 57, 45, 71, 36, 85, 45, 9, 62, 29, 53, 37, 62, 58, 54, 65, + 62, 86, 54, 3, 1, 19, 10, 31, 1, 51, 10, 60, 2, 83, 10, + 9, 27, 18, 19, 41, 27, 50, 19, 73, 27, 82, 19, 8, 36, 28, + 45, 40, 36, 56, 45, 72, 36, 84, 45, 8, 62, 29, 54, 36, 62, + 57, 54, 64, 62, 85, 54, 2, 1, 20, 10, 30, 1, 52, 10, 61, + 2, 84, 10, 10, 27, 19, 19, 42, 27, 51, 19, 74, 27, 83, 19, + 9, 36, 27, 45, 41, 36, 55, 45, 73, 36, 83, 45, 7, 62, 28, + 54, 35, 62, 56, 54, 63, 62, 84, 54, 1, 1, 21, 10, 30, 2, + 53, 10, 62, 2, 85, 10, 11, 27, 20, 19, 43, 27, 52, 19, 74, + 28, 84, 19, 10, 36, 26, 45, 42, 36, 54, 45, 74, 36, 82, 45, + 6, 62, 27, 54, 34, 62, 55, 54, 62, 62, 83, 54, 0, 1, 22, + 10, 31, 2, 54, 10, 63, 2, 86, 10, 12, 27, 21, 19, 44, 27, + 53, 19, 73, 28, 85, 19, 11, 36, 25, 45, 43, 36, 53, 45, 74, + 37, 81, 45, 5, 62, 26, 54, 33, 62, 54, 54, 61, 62, 82, 54, + 0, 2, 23, 10, 32, 2, 55, 10, 64, 2, 87, 10, 13, 27, 22, + 19, 44, 28, 54, 19, 72, 28, 86, 19, 12, 36, 24, 45, 44, 36, + 52, 45, 73, 37, 80, 45, 4, 62, 25, 54, 32, 62, 53, 54, 60, + 62, 81, 54, 1, 2, 24, 10, 33, 2, 56, 10, 65, 2, 88, 10, + 14, 27, 23, 19, 43, 28, 55, 19, 71, 28, 87, 19, 13, 36, 23, + 45, 44, 37, 51, 45, 72, 37, 79, 45, 3, 62, 24, 54, 31, 62, + 52, 54, 60, 63, 80, 54, 2, 2, 25, 10, 34, 2, 57, 10, 66, + 2, 89, 10, 14, 28, 24, 19, 42, 28, 56, 19, 70, 28, 88, 19, + 14, 36, 22, 45, 43, 37, 50, 45, 71, 37, 78, 45, 2, 62, 23, + 54, 30, 62, 51, 54, 61, 63, 79, 54, 3, 2, 26, 10, 35, 2, + 58, 10, 67, 2, 89, 11, 13, 28, 25, 19, 41, 28, 57, 19, 69, + 28, 89, 19, 14, 37, 21, 45, 42, 37, 49, 45, 70, 37, 77, 45, + 1, 62, 22, 54, 30, 63, 50, 54, 62, 63, 78, 54, 4, 2, 27, + 10, 36, 2, 59, 10, 68, 2, 88, 11, 12, 28, 26, 19, 40, 28, + 58, 19, 68, 28, 89, 20, 13, 37, 20, 45, 41, 37, 48, 45, 69, + 37, 76, 45, 0, 62, 21, 54, 31, 63, 49, 54, 63, 63, 77, 54, + 5, 2, 28, 10, 37, 2, 59, 11, 69, 2, 87, 11, 11, 28, 27, + 19, 39, 28, 59, 19, 67, 28, 88, 20, 12, 37, 19, 45, 40, 37, + 47, 45, 68, 37, 75, 45, 0, 63, 20, 54, 32, 63, 48, 54, 64, + 63, 76, 54, 6, 2, 29, 10, 38, 2, 58, 11, 70, 2, 86, 11, + 10, 28, 28, 19, 38, 28, 59, 20, 66, 28, 87, 20, 11, 37, 18, + 45, 39, 37, 46, 45, 67, 37, 75, 46, 1, 63, 19, 54, 33, 63, + 47, 54, 65, 63, 75, 54, 7, 2, 29, 11, 39, 2, 57, 11, 71, + 2, 85, 11, 9, 28, 29, 19, 37, 28, 58, 20, 65, 28, 86, 20, + 10, 37, 17, 45, 38, 37, 45, 45, 66, 37, 76, 46, 2, 63, 18, + 54, 34, 63, 46, 54, 66, 63, 75, 55, 8, 2, 28, 11, 40, 2, + 56, 11, 72, 2, 84, 11, 8, 28, 29, 20, 36, 28, 57, 20, 64, + 28, 85, 20, 9, 37, 16, 45, 37, 37, 45, 46, 65, 37, 77, 46, + 3, 63, 17, 54, 35, 63, 45, 54, 67, 63, 76, 55, 9, 2, 27, + 11, 41, 2, 55, 11, 73, 2, 83, 11, 7, 28, 28, 20, 35, 28, + 56, 20, 63, 28, 84, 20, 8, 37, 15, 45, 36, 37, 46, 46, 64, + 37, 78, 46, 4, 63, 16, 54, 36, 63, 45, 55, 68, 63, 77, 55, + 10, 2, 26, 11, 42, 2, 54, 11, 74, 2, 82, 11, 6, 28, 27, + 20, 34, 28, 55, 20, 62, 28, 83, 20, 7, 37, 15, 46, 35, 37, + 47, 46, 63, 37, 79, 46, 5, 63, 15, 54, 37, 63, 46, 55, 69, + 63, 78, 55, 11, 2, 25, 11, 43, 2, 53, 11, 74, 3, 81, 11, + 5, 28, 26, 20, 33, 28, 54, 20, 61, 28, 82, 20, 6, 37, 16, + 46, 34, 37, 48, 46, 62, 37, 80, 46, 6, 63, 15, 55, 38, 63, + 47, 55, 70, 63, 79, 55, 12, 2, 24, 11, 44, 2, 52, 11, 73, + 3, 80, 11, 4, 28, 25, 20, 32, 28, 53, 20, 60, 28, 81, 20, + 5, 37, 17, 46, 33, 37, 49, 46, 61, 37, 81, 46, 7, 63, 16, + 55, 39, 63, 48, 55, 71, 63, 80, 55, 13, 2, 23, 11, 44, 3, + 51, 11, 72, 3, 79, 11, 3, 28, 24, 20, 31, 28, 52, 20, 60, + 29, 80, 20, 4, 37, 18, 46, 32, 37, 50, 46, 60, 37, 82, 46, + 8, 63, 17, 55, 40, 63, 49, 55, 72, 63, 81, 55, 14, 2, 22, + 11, 43, 3, 50, 11, 71, 3, 78, 11, 2, 28, 23, 20, 30, 28, + 51, 20, 61, 29, 79, 20, 3, 37, 19, 46, 31, 37, 51, 46, 60, + 38, 83, 46, 9, 63, 18, 55, 41, 63, 50, 55, 73, 63, 82, 55, + 14, 3, 21, 11, 42, 3, 49, 11, 70, 3, 77, 11, 1, 28, 22, + 20, 30, 29, 50, 20, 62, 29, 78, 20, 2, 37, 20, 46, 30, 37, + 52, 46, 61, 38, 84, 46, 10, 63, 19, 55, 42, 63, 51, 55, 74, + 63, 83, 55, 13, 3, 20, 11, 41, 3, 48, 11, 69, 3, 76, 11, + 0, 28, 21, 20, 31, 29, 49, 20, 63, 29, 77, 20, 1, 37, 21, + 46, 30, 38, 53, 46, 62, 38, 85, 46, 11, 63, 20, 55, 43, 63, + 52, 55, 74, 64, 84, 55, 12, 3, 19, 11, 40, 3, 47, 11, 68, + 3, 75, 11, 0, 29, 20, 20, 32, 29, 48, 20, 64, 29, 76, 20, + 0, 37, 22, 46, 31, 38, 54, 46, 63, 38, 86, 46, 12, 63, 21, + 55, 44, 63, 53, 55, 73, 64, 85, 55, 11, 3, 18, 11, 39, 3, + 46, 11, 67, 3, 75, 12, 1, 29, 19, 20, 33, 29, 47, 20, 65, + 29, 75, 20, 0, 38, 23, 46, 32, 38, 55, 46, 64, 38, 87, 46, + 13, 63, 22, 55, 44, 64, 54, 55, 72, 64, 86, 55, 10, 3, 17, + 11, 38, 3, 45, 11, 66, 3, 76, 12, 2, 29, 18, 20, 34, 29, + 46, 20, 66, 29, 75, 21, 1, 38, 24, 46, 33, 38, 56, 46, 65, + 38, 88, 46, 14, 63, 23, 55, 43, 64, 55, 55, 71, 64, 87, 55, + 9, 3, 16, 11, 37, 3, 45, 12, 65, 3, 77, 12, 3, 29, 17, + 20, 35, 29, 45, 20, 67, 29, 76, 21, 2, 38, 25, 46, 34, 38, + 57, 46, 66, 38, 89, 46, 14, 64, 24, 55, 42, 64, 56, 55, 70, + 64, 88, 55, 8, 3, 15, 11, 36, 3, 46, 12, 64, 3, 78, 12, + 4, 29, 16, 20, 36, 29, 45, 21, 68, 29, 77, 21, 3, 38, 26, + 46, 35, 38, 58, 46, 67, 38, 89, 47, 13, 64, 25, 55, 41, 64, + 57, 55, 69, 64, 89, 55, 7, 3, 15, 12, 35, 3, 47, 12, 63, + 3, 79, 12, 5, 29, 15, 20, 37, 29, 46, 21, 69, 29, 78, 21, + 4, 38, 27, 46, 36, 38, 59, 46, 68, 38, 88, 47, 12, 64, 26, + 55, 40, 64, 58, 55, 68, 64, 89, 56, 6, 3, 16, 12, 34, 3, + 48, 12, 62, 3, 80, 12, 6, 29, 15, 21, 38, 29, 47, 21, 70, + 29, 79, 21, 5, 38, 28, 46, 37, 38, 59, 47, 69, 38, 87, 47, + 11, 64, 27, 55, 39, 64, 59, 55, 67, 64, 88, 56, 5, 3, 17, + 12, 33, 3, 49, 12, 61, 3, 81, 12, 7, 29, 16, 21, 39, 29, + 48, 21, 71, 29, 80, 21, 6, 38, 29, 46, 38, 38, 58, 47, 70, + 38, 86, 47, 10, 64, 28, 55, 38, 64, 59, 56, 66, 64, 87, 56, + 4, 3, 18, 12, 32, 3, 50, 12, 60, 3, 82, 12, 8, 29, 17, + 21, 40, 29, 49, 21, 72, 29, 81, 21, 7, 38, 29, 47, 39, 38, + 57, 47, 71, 38, 85, 47, 9, 64, 29, 55, 37, 64, 58, 56, 65, + 64, 86, 56, 3, 3, 19, 12, 31, 3, 51, 12, 60, 4, 83, 12, + 9, 29, 18, 21, 41, 29, 50, 21, 73, 29, 82, 21, 8, 38, 28, + 47, 40, 38, 56, 47, 72, 38, 84, 47, 8, 64, 29, 56, 36, 64, + 57, 56, 64, 64, 85, 56, 2, 3, 20, 12, 30, 3, 52, 12, 61, + 4, 84, 12, 10, 29, 19, 21, 42, 29, 51, 21, 74, 29, 83, 21, + 9, 38, 27, 47, 41, 38, 55, 47, 73, 38, 83, 47, 7, 64, 28, + 56, 35, 64, 56, 56, 63, 64, 84, 56, 1, 3, 21, 12, 30, 4, + 53, 12, 62, 4, 85, 12, 11, 29, 20, 21, 43, 29, 52, 21, 74, + 30, 84, 21, 10, 38, 26, 47, 42, 38, 54, 47, 74, 38, 82, 47, + 6, 64, 27, 56, 34, 64, 55, 56, 62, 64, 83, 56, 0, 3, 22, + 12, 31, 4, 54, 12, 63, 4, 86, 12, 12, 29, 21, 21, 44, 29, + 53, 21, 73, 30, 85, 21, 11, 38, 25, 47, 43, 38, 53, 47, 74, + 39, 81, 47, 5, 64, 26, 56, 33, 64, 54, 56, 61, 64, 82, 56, + 0, 4, 23, 12, 32, 4, 55, 12, 64, 4, 87, 12, 13, 29, 22, + 21, 44, 30, 54, 21, 72, 30, 86, 21, 12, 38, 24, 47, 44, 38, + 52, 47, 73, 39, 80, 47, 4, 64, 25, 56, 32, 64, 53, 56, 60, + 64, 81, 56, 1, 4, 24, 12, 33, 4, 56, 12, 65, 4, 88, 12, + 14, 29, 23, 21, 43, 30, 55, 21, 71, 30, 87, 21, 13, 38, 23, + 47, 44, 39, 51, 47, 72, 39, 79, 47, 3, 64, 24, 56, 31, 64, + 52, 56, 60, 65, 80, 56, 2, 4, 25, 12, 34, 4, 57, 12, 66, + 4, 89, 12, 14, 30, 24, 21, 42, 30, 56, 21, 70, 30, 88, 21, + 14, 38, 22, 47, 43, 39, 50, 47, 71, 39, 78, 47, 2, 64, 23, + 56, 30, 64, 51, 56, 61, 65, 79, 56, 3, 4, 26, 12, 35, 4, + 58, 12, 67, 4, 89, 13, 13, 30, 25, 21, 41, 30, 57, 21, 69, + 30, 89, 21, 14, 39, 21, 47, 42, 39, 49, 47, 70, 39, 77, 47, + 1, 64, 22, 56, 30, 65, 50, 56, 62, 65, 78, 56, 4, 4, 27, + 12, 36, 4, 59, 12, 68, 4, 88, 13, 12, 30, 26, 21, 40, 30, + 58, 21, 68, 30, 89, 22, 13, 39, 20, 47, 41, 39, 48, 47, 69, + 39, 76, 47, 0, 64, 21, 56, 31, 65, 49, 56, 63, 65, 77, 56, + 5, 4, 28, 12, 37, 4, 59, 13, 69, 4, 87, 13, 11, 30, 27, + 21, 39, 30, 59, 21, 67, 30, 88, 22, 12, 39, 19, 47, 40, 39, + 47, 47, 68, 39, 75, 47, 0, 65, 20, 56, 32, 65, 48, 56, 64, + 65, 76, 56, 6, 4, 29, 12, 38, 4, 58, 13, 70, 4, 86, 13, + 10, 30, 28, 21, 38, 30, 59, 22, 66, 30, 87, 22, 11, 39, 18, + 47, 39, 39, 46, 47, 67, 39, 75, 48, 1, 65, 19, 56, 33, 65, + 47, 56, 65, 65, 75, 56, 7, 4, 29, 13, 39, 4, 57, 13, 71, + 4, 85, 13, 9, 30, 29, 21, 37, 30, 58, 22, 65, 30, 86, 22, + 10, 39, 17, 47, 38, 39, 45, 47, 66, 39, 76, 48, 2, 65, 18, + 56, 34, 65, 46, 56, 66, 65, 75, 57, 8, 4, 28, 13, 40, 4, + 56, 13, 72, 4, 84, 13, 8, 30, 29, 22, 36, 30, 57, 22, 64, + 30, 85, 22, 9, 39, 16, 47, 37, 39, 45, 48, 65, 39, 77, 48, + 3, 65, 17, 56, 35, 65, 45, 56, 67, 65, 76, 57, 9, 4, 27, + 13, 41, 4, 55, 13, 73, 4, 83, 13, 7, 30, 28, 22, 35, 30, + 56, 22, 63, 30, 84, 22, 8, 39, 15, 47, 36, 39, 46, 48, 64, + 39, 78, 48, 4, 65, 16, 56, 36, 65, 45, 57, 68, 65, 77, 57, + 10, 4, 26, 13, 42, 4, 54, 13, 74, 4, 82, 13, 6, 30, 27, + 22, 34, 30, 55, 22, 62, 30, 83, 22, 7, 39, 15, 48, 35, 39, + 47, 48, 63, 39, 79, 48, 5, 65, 15, 56, 37, 65, 46, 57, 69, + 65, 78, 57, 11, 4, 25, 13, 43, 4, 53, 13, 74, 5, 81, 13, + 5, 30, 26, 22, 33, 30, 54, 22, 61, 30, 82, 22, 6, 39, 16, + 48, 34, 39, 48, 48, 62, 39, 80, 48, 6, 65, 15, 57, 38, 65, + 47, 57, 70, 65, 79, 57, 12, 4, 24, 13, 44, 4, 52, 13, 73, + 5, 80, 13, 4, 30, 25, 22, 32, 30, 53, 22, 60, 30, 81, 22, + 5, 39, 17, 48, 33, 39, 49, 48, 61, 39, 81, 48, 7, 65, 16, + 57, 39, 65, 48, 57, 71, 65, 80, 57, 13, 4, 23, 13, 44, 5, + 51, 13, 72, 5, 79, 13, 3, 30, 24, 22, 31, 30, 52, 22, 60, + 31, 80, 22, 4, 39, 18, 48, 32, 39, 50, 48, 60, 39, 82, 48, + 8, 65, 17, 57, 40, 65, 49, 57, 72, 65, 81, 57, 14, 4, 22, + 13, 43, 5, 50, 13, 71, 5, 78, 13, 2, 30, 23, 22, 30, 30, + 51, 22, 61, 31, 79, 22, 3, 39, 19, 48, 31, 39, 51, 48, 60, + 40, 83, 48, 9, 65, 18, 57, 41, 65, 50, 57, 73, 65, 82, 57, + 14, 5, 21, 13, 42, 5, 49, 13, 70, 5, 77, 13, 1, 30, 22, + 22, 30, 31, 50, 22, 62, 31, 78, 22, 2, 39, 20, 48, 30, 39, + 52, 48, 61, 40, 84, 48, 10, 65, 19, 57, 42, 65, 51, 57, 74, + 65, 83, 57, 13, 5, 20, 13, 41, 5, 48, 13, 69, 5, 76, 13, + 0, 30, 21, 22, 31, 31, 49, 22, 63, 31, 77, 22, 1, 39, 21, + 48, 30, 40, 53, 48, 62, 40, 85, 48, 11, 65, 20, 57, 43, 65, + 52, 57, 74, 66, 84, 57, 12, 5, 19, 13, 40, 5, 47, 13, 68, + 5, 75, 13, 0, 31, 20, 22, 32, 31, 48, 22, 64, 31, 76, 22, + 0, 39, 22, 48, 31, 40, 54, 48, 63, 40, 86, 48, 12, 65, 21, + 57, 44, 65, 53, 57, 73, 66, 85, 57, 11, 5, 18, 13, 39, 5, + 46, 13, 67, 5, 75, 14, 1, 31, 19, 22, 33, 31, 47, 22, 65, + 31, 75, 22, 0, 40, 23, 48, 32, 40, 55, 48, 64, 40, 87, 48, + 13, 65, 22, 57, 44, 66, 54, 57, 72, 66, 86, 57, 10, 5, 17, + 13, 38, 5, 45, 13, 66, 5, 76, 14, 2, 31, 18, 22, 34, 31, + 46, 22, 66, 31, 75, 23, 1, 40, 24, 48, 33, 40, 56, 48, 65, + 40, 88, 48, 14, 65, 23, 57, 43, 66, 55, 57, 71, 66, 87, 57, + 9, 5, 16, 13, 37, 5, 45, 14, 65, 5, 77, 14, 3, 31, 17, + 22, 35, 31, 45, 22, 67, 31, 76, 23, 2, 40, 25, 48, 34, 40, + 57, 48, 66, 40, 89, 48, 14, 66, 24, 57, 42, 66, 56, 57, 70, + 66, 88, 57, 8, 5, 15, 13, 36, 5, 46, 14, 64, 5, 78, 14, + 4, 31, 16, 22, 36, 31, 45, 23, 68, 31, 77, 23, 3, 40, 26, + 48, 35, 40, 58, 48, 67, 40, 89, 49, 13, 66, 25, 57, 41, 66, + 57, 57, 69, 66, 89, 57, 7, 5, 15, 14, 35, 5, 47, 14, 63, + 5, 79, 14, 5, 31, 15, 22, 37, 31, 46, 23, 69, 31, 78, 23, + 4, 40, 27, 48, 36, 40, 59, 48, 68, 40, 88, 49, 12, 66, 26, + 57, 40, 66, 58, 57, 68, 66, 89, 58, 6, 5, 16, 14, 34, 5, + 48, 14, 62, 5, 80, 14, 6, 31, 15, 23, 38, 31, 47, 23, 70, + 31, 79, 23, 5, 40, 28, 48, 37, 40, 59, 49, 69, 40, 87, 49, + 11, 66, 27, 57, 39, 66, 59, 57, 67, 66, 88, 58, 5, 5, 17, + 14, 33, 5, 49, 14, 61, 5, 81, 14, 7, 31, 16, 23, 39, 31, + 48, 23, 71, 31, 80, 23, 6, 40, 29, 48, 38, 40, 58, 49, 70, + 40, 86, 49, 10, 66, 28, 57, 38, 66, 59, 58, 66, 66, 87, 58, + 4, 5, 18, 14, 32, 5, 50, 14, 60, 5, 82, 14, 8, 31, 17, + 23, 40, 31, 49, 23, 72, 31, 81, 23, 7, 40, 29, 49, 39, 40, + 57, 49, 71, 40, 85, 49, 9, 66, 29, 57, 37, 66, 58, 58, 65, + 66, 86, 58, 3, 5, 19, 14, 31, 5, 51, 14, 60, 6, 83, 14, + 9, 31, 18, 23, 41, 31, 50, 23, 73, 31, 82, 23, 8, 40, 28, + 49, 40, 40, 56, 49, 72, 40, 84, 49, 8, 66, 29, 58, 36, 66, + 57, 58, 64, 66, 85, 58, 2, 5, 20, 14, 30, 5, 52, 14, 61, + 6, 84, 14, 10, 31, 19, 23, 42, 31, 51, 23, 74, 31, 83, 23, + 9, 40, 27, 49, 41, 40, 55, 49, 73, 40, 83, 49, 7, 66, 28, + 58, 35, 66, 56, 58, 63, 66, 84, 58, 1, 5, 21, 14, 30, 6, + 53, 14, 62, 6, 85, 14, 11, 31, 20, 23, 43, 31, 52, 23, 74, + 32, 84, 23, 10, 40, 26, 49, 42, 40, 54, 49, 74, 40, 82, 49, + 6, 66, 27, 58, 34, 66, 55, 58, 62, 66, 83, 58, 0, 5, 22, + 14, 31, 6, 54, 14, 63, 6, 86, 14, 12, 31, 21, 23, 44, 31, + 53, 23, 73, 32, 85, 23, 11, 40, 25, 49, 43, 40, 53, 49, 74, + 41, 81, 49, 5, 66, 26, 58, 33, 66, 54, 58, 61, 66, 82, 58, + 0, 6, 23, 14, 32, 6, 55, 14, 64, 6, 87, 14, 13, 31, 22, + 23, 44, 32, 54, 23, 72, 32, 86, 23, 12, 40, 24, 49, 44, 40, + 52, 49, 73, 41, 80, 49, 4, 66, 25, 58, 32, 66, 53, 58, 60, + 66, 81, 58, 1, 6, 24, 14, 33, 6, 56, 14, 65, 6, 88, 14, + 14, 31, 23, 23, 43, 32, 55, 23, 71, 32, 87, 23, 13, 40, 23, + 49, 44, 41, 51, 49, 72, 41, 79, 49, 3, 66, 24, 58, 31, 66, + 52, 58, 60, 67, 80, 58, 2, 6, 25, 14, 34, 6, 57, 14, 66, + 6, 89, 14, 14, 32, 24, 23, 42, 32, 56, 23, 70, 32, 88, 23, + 14, 40, 22, 49, 43, 41, 50, 49, 71, 41, 78, 49, 2, 66, 23, + 58, 30, 66, 51, 58, 61, 67, 79, 58, 3, 6, 26, 14, 35, 6, + 58, 14, 67, 6, 89, 15, 13, 32, 25, 23, 41, 32, 57, 23, 69, + 32, 89, 23, 14, 41, 21, 49, 42, 41, 49, 49, 70, 41, 77, 49, + 1, 66, 22, 58, 30, 67, 50, 58, 62, 67, 78, 58, 4, 6, 27, + 14, 36, 6, 59, 14, 68, 6, 88, 15, 12, 32, 26, 23, 40, 32, + 58, 23, 68, 32, 89, 24, 13, 41, 20, 49, 41, 41, 48, 49, 69, + 41, 76, 49, 0, 66, 21, 58, 31, 67, 49, 58, 63, 67, 77, 58, + 5, 6, 28, 14, 37, 6, 59, 15, 69, 6, 87, 15, 11, 32, 27, + 23, 39, 32, 59, 23, 67, 32, 88, 24, 12, 41, 19, 49, 40, 41, + 47, 49, 68, 41, 75, 49, 0, 67, 20, 58, 32, 67, 48, 58, 64, + 67, 76, 58, 6, 6, 29, 14, 38, 6, 58, 15, 70, 6, 86, 15, + 10, 32, 28, 23, 38, 32, 59, 24, 66, 32, 87, 24, 11, 41, 18, + 49, 39, 41, 46, 49, 67, 41, 75, 50, 1, 67, 19, 58, 33, 67, + 47, 58, 65, 67, 75, 58, 7, 6, 29, 15, 39, 6, 57, 15, 71, + 6, 85, 15, 9, 32, 29, 23, 37, 32, 58, 24, 65, 32, 86, 24, + 10, 41, 17, 49, 38, 41, 45, 49, 66, 41, 76, 50, 2, 67, 18, + 58, 34, 67, 46, 58, 66, 67, 75, 59, 8, 6, 28, 15, 40, 6, + 56, 15, 72, 6, 84, 15, 8, 32, 29, 24, 36, 32, 57, 24, 64, + 32, 85, 24, 9, 41, 16, 49, 37, 41, 45, 50, 65, 41, 77, 50, + 3, 67, 17, 58, 35, 67, 45, 58, 67, 67, 76, 59, 9, 6, 27, + 15, 41, 6, 55, 15, 73, 6, 83, 15, 7, 32, 28, 24, 35, 32, + 56, 24, 63, 32, 84, 24, 8, 41, 15, 49, 36, 41, 46, 50, 64, + 41, 78, 50, 4, 67, 16, 58, 36, 67, 45, 59, 68, 67, 77, 59, + 10, 6, 26, 15, 42, 6, 54, 15, 74, 6, 82, 15, 6, 32, 27, + 24, 34, 32, 55, 24, 62, 32, 83, 24, 7, 41, 15, 50, 35, 41, + 47, 50, 63, 41, 79, 50, 5, 67, 15, 58, 37, 67, 46, 59, 69, + 67, 78, 59, 11, 6, 25, 15, 43, 6, 53, 15, 74, 7, 81, 15, + 5, 32, 26, 24, 33, 32, 54, 24, 61, 32, 82, 24, 6, 41, 16, + 50, 34, 41, 48, 50, 62, 41, 80, 50, 6, 67, 15, 59, 38, 67, + 47, 59, 70, 67, 79, 59, 12, 6, 24, 15, 44, 6, 52, 15, 73, + 7, 80, 15, 4, 32, 25, 24, 32, 32, 53, 24, 60, 32, 81, 24, + 5, 41, 17, 50, 33, 41, 49, 50, 61, 41, 81, 50, 7, 67, 16, + 59, 39, 67, 48, 59, 71, 67, 80, 59, 13, 6, 23, 15, 44, 7, + 51, 15, 72, 7, 79, 15, 3, 32, 24, 24, 31, 32, 52, 24, 60, + 33, 80, 24, 4, 41, 18, 50, 32, 41, 50, 50, 60, 41, 82, 50, + 8, 67, 17, 59, 40, 67, 49, 59, 72, 67, 81, 59, 14, 6, 22, + 15, 43, 7, 50, 15, 71, 7, 78, 15, 2, 32, 23, 24, 30, 32, + 51, 24, 61, 33, 79, 24, 3, 41, 19, 50, 31, 41, 51, 50, 60, + 42, 83, 50, 9, 67, 18, 59, 41, 67, 50, 59, 73, 67, 82, 59, + 14, 7, 21, 15, 42, 7, 49, 15, 70, 7, 77, 15, 1, 32, 22, + 24, 30, 33, 50, 24, 62, 33, 78, 24, 2, 41, 20, 50, 30, 41, + 52, 50, 61, 42, 84, 50, 10, 67, 19, 59, 42, 67, 51, 59, 74, + 67, 83, 59, 13, 7, 20, 15, 41, 7, 48, 15, 69, 7, 76, 15, + 0, 32, 21, 24, 31, 33, 49, 24, 63, 33, 77, 24, 1, 41, 21, + 50, 30, 42, 53, 50, 62, 42, 85, 50, 11, 67, 20, 59, 43, 67, + 52, 59, 60, 51, 84, 59, 12, 7, 19, 15, 40, 7, 47, 15, 68, + 7, 75, 15, 0, 33, 20, 24, 32, 33, 48, 24, 64, 33, 76, 24, + 0, 41, 22, 50, 31, 42, 54, 50, 63, 42, 86, 50, 12, 67, 21, + 59, 44, 67, 53, 59, 61, 51, 85, 59, 11, 7, 18, 15, 39, 7, + 46, 15, 67, 7, 75, 16, 1, 33, 19, 24, 33, 33, 47, 24, 65, + 33, 75, 24, 0, 42, 23, 50, 32, 42, 55, 50, 64, 42, 87, 50, + 13, 67, 22, 59, 30, 51, 54, 59, 62, 51, 86, 59, 10, 7, 17, + 15, 38, 7, 45, 15, 66, 7, 76, 16, 2, 33, 18, 24, 34, 33, + 46, 24, 66, 33, 75, 25, 1, 42, 24, 50, 33, 42, 56, 50, 65, + 42, 88, 50, 14, 67, 23, 59, 31, 51, 55, 59, 63, 51, 87, 59, + 9, 7, 16, 15, 37, 7, 45, 16, 65, 7, 77, 16, 3, 33, 17, + 24, 35, 33, 45, 24, 67, 33, 76, 25, 2, 42, 25, 50, 34, 42, + 57, 50, 66, 42, 89, 50, 0, 51, 24, 59, 32, 51, 56, 59, 64, + 51, 88, 59, 8, 7, 15, 15, 36, 7, 46, 16, 64, 7, 78, 16, + 4, 33, 16, 24, 36, 33, 45, 25, 68, 33, 77, 25, 3, 42, 26, + 50, 35, 42, 58, 50, 67, 42, 75, 34, 1, 51, 25, 59, 33, 51, + 57, 59, 65, 51, 89, 59, 7, 7, 15, 16, 35, 7, 47, 16, 63, + 7, 79, 16, 5, 33, 15, 24, 37, 33, 46, 25, 69, 33, 78, 25, + 4, 42, 27, 50, 36, 42, 59, 50, 68, 42, 76, 34, 2, 51, 26, + 59, 34, 51, 58, 59, 66, 51, 89, 60, 6, 7, 16, 16, 34, 7, + 48, 16, 62, 7, 80, 16, 6, 33, 15, 25, 38, 33, 47, 25, 70, + 33, 79, 25, 5, 42, 28, 50, 37, 42, 45, 34, 69, 42, 77, 34, + 3, 51, 27, 59, 35, 51, 59, 59, 67, 51, 88, 60, 5, 7, 17, + 16, 33, 7, 49, 16, 61, 7, 81, 16, 7, 33, 16, 25, 39, 33, + 48, 25, 71, 33, 80, 25, 6, 42, 29, 50, 38, 42, 46, 34, 70, + 42, 78, 34, 4, 51, 28, 59, 36, 51, 59, 60, 68, 51, 87, 60, + 4, 7, 18, 16, 32, 7, 50, 16, 60, 7, 82, 16, 8, 33, 17, + 25, 40, 33, 49, 25, 72, 33, 81, 25, 7, 42, 15, 34, 39, 42, + 47, 34, 71, 42, 79, 34, 5, 51, 29, 59, 37, 51, 58, 60, 69, + 51, 86, 60, 3, 7, 19, 16, 31, 7, 51, 16, 60, 8, 83, 16, + 9, 33, 18, 25, 41, 33, 50, 25, 73, 33, 82, 25, 8, 42, 16, + 34, 40, 42, 48, 34, 72, 42, 80, 34, 6, 51, 29, 60, 38, 51, + 57, 60, 70, 51, 85, 60, 2, 7, 20, 16, 30, 7, 52, 16, 61, + 8, 84, 16, 10, 33, 19, 25, 42, 33, 51, 25, 74, 33, 83, 25, + 9, 42, 17, 34, 41, 42, 49, 34, 73, 42, 81, 34, 7, 51, 28, + 60, 39, 51, 56, 60, 71, 51, 84, 60, 1, 7, 21, 16, 30, 8, + 53, 16, 62, 8, 85, 16, 11, 33, 20, 25, 43, 33, 52, 25, 60, + 17, 84, 25, 10, 42, 18, 34, 42, 42, 50, 34, 74, 42, 82, 34, + 8, 51, 27, 60, 40, 51, 55, 60, 72, 51, 83, 60, 0, 7, 22, + 16, 31, 8, 54, 16, 63, 8, 86, 16, 12, 33, 21, 25, 44, 33, + 53, 25, 61, 17, 85, 25, 11, 42, 19, 34, 43, 42, 51, 34, 74, + 43, 83, 34, 9, 51, 26, 60, 41, 51, 54, 60, 73, 51, 82, 60, + 0, 8, 23, 16, 32, 8, 55, 16, 64, 8, 87, 16, 13, 33, 22, + 25, 30, 17, 54, 25, 62, 17, 86, 25, 12, 42, 20, 34, 44, 42, + 52, 34, 73, 43, 84, 34, 10, 51, 25, 60, 42, 51, 53, 60, 74, + 51, 81, 60, 1, 8, 24, 16, 33, 8, 56, 16, 65, 8, 88, 16, + 14, 33, 23, 25, 31, 17, 55, 25, 63, 17, 87, 25, 13, 42, 21, + 34, 44, 43, 53, 34, 72, 43, 85, 34, 11, 51, 24, 60, 43, 51, + 52, 60, 74, 52, 80, 60, 2, 8, 25, 16, 34, 8, 57, 16, 66, + 8, 89, 16, 0, 17, 24, 25, 32, 17, 56, 25, 64, 17, 88, 25, + 14, 42, 22, 34, 43, 43, 54, 34, 71, 43, 86, 34, 12, 51, 23, + 60, 44, 51, 51, 60, 73, 52, 79, 60, 3, 8, 26, 16, 35, 8, + 58, 16, 67, 8, 75, 0, 1, 17, 25, 25, 33, 17, 57, 25, 65, + 17, 89, 25, 14, 43, 23, 34, 42, 43, 55, 34, 70, 43, 87, 34, + 13, 51, 22, 60, 44, 52, 50, 60, 72, 52, 78, 60, 4, 8, 27, + 16, 36, 8, 59, 16, 68, 8, 76, 0, 2, 17, 26, 25, 34, 17, + 58, 25, 66, 17, 89, 26, 13, 43, 24, 34, 41, 43, 56, 34, 69, + 43, 88, 34, 14, 51, 21, 60, 43, 52, 49, 60, 71, 52, 77, 60, + 5, 8, 28, 16, 37, 8, 45, 0, 69, 8, 77, 0, 3, 17, 27, + 25, 35, 17, 59, 25, 67, 17, 88, 26, 12, 43, 25, 34, 40, 43, + 57, 34, 68, 43, 89, 34, 14, 52, 20, 60, 42, 52, 48, 60, 70, + 52, 76, 60, 6, 8, 29, 16, 38, 8, 46, 0, 70, 8, 78, 0, + 4, 17, 28, 25, 36, 17, 59, 26, 68, 17, 87, 26, 11, 43, 26, + 34, 39, 43, 58, 34, 67, 43, 89, 35, 13, 52, 19, 60, 41, 52, + 47, 60, 69, 52, 75, 60, 7, 8, 15, 0, 39, 8, 47, 0, 71, + 8, 79, 0, 5, 17, 29, 25, 37, 17, 58, 26, 69, 17, 86, 26, + 10, 43, 27, 34, 38, 43, 59, 34, 66, 43, 88, 35, 12, 52, 18, + 60, 40, 52, 46, 60, 68, 52, 75, 61, 8, 8, 16, 0, 40, 8, + 48, 0, 72, 8, 80, 0, 6, 17, 29, 26, 38, 17, 57, 26, 70, + 17, 85, 26, 9, 43, 28, 34, 37, 43, 59, 35, 65, 43, 87, 35, + 11, 52, 17, 60, 39, 52, 45, 60, 67, 52, 76, 61, 9, 8, 17, + 0, 41, 8, 49, 0, 73, 8, 81, 0, 7, 17, 28, 26, 39, 17, + 56, 26, 71, 17, 84, 26, 8, 43, 29, 34, 36, 43, 58, 35, 64, + 43, 86, 35, 10, 52, 16, 60, 38, 52, 45, 61, 66, 52, 77, 61, + 10, 8, 18, 0, 42, 8, 50, 0, 74, 8, 82, 0, 8, 17, 27, + 26, 40, 17, 55, 26, 72, 17, 83, 26, 7, 43, 29, 35, 35, 43, + 57, 35, 63, 43, 85, 35, 9, 52, 15, 60, 37, 52, 46, 61, 65, + 52, 78, 61, 11, 8, 19, 0, 43, 8, 51, 0, 74, 9, 83, 0, + 9, 17, 26, 26, 41, 17, 54, 26, 73, 17, 82, 26, 6, 43, 28, + 35, 34, 43, 56, 35, 62, 43, 84, 35, 8, 52, 15, 61, 36, 52, + 47, 61, 64, 52, 79, 61, 12, 8, 20, 0, 44, 8, 52, 0, 73, + 9, 84, 0, 10, 17, 25, 26, 42, 17, 53, 26, 74, 17, 81, 26, + 5, 43, 27, 35, 33, 43, 55, 35, 61, 43, 83, 35, 7, 52, 16, + 61, 35, 52, 48, 61, 63, 52, 80, 61, 13, 8, 21, 0, 44, 9, + 53, 0, 72, 9, 85, 0, 11, 17, 24, 26, 43, 17, 52, 26, 74, + 18, 80, 26, 4, 43, 26, 35, 32, 43, 54, 35, 60, 43, 82, 35, + 6, 52, 17, 61, 34, 52, 49, 61, 62, 52, 81, 61, 14, 8, 22, + 0, 43, 9, 54, 0, 71, 9, 86, 0, 12, 17, 23, 26, 44, 17, + 51, 26, 73, 18, 79, 26, 3, 43, 25, 35, 31, 43, 53, 35, 60, + 44, 81, 35, 5, 52, 18, 61, 33, 52, 50, 61, 61, 52, 82, 61, + 14, 9, 23, 0, 42, 9, 55, 0, 70, 9, 87, 0, 13, 17, 22, + 26, 44, 18, 50, 26, 72, 18, 78, 26, 2, 43, 24, 35, 30, 43, + 52, 35, 61, 44, 80, 35, 4, 52, 19, 61, 32, 52, 51, 61, 60, + 52, 83, 61, 13, 9, 24, 0, 41, 9, 56, 0, 69, 9, 88, 0, + 14, 17, 21, 26, 43, 18, 49, 26, 71, 18, 77, 26, 1, 43, 23, + 35, 30, 44, 51, 35, 62, 44, 79, 35, 3, 52, 20, 61, 31, 52, + 52, 61, 60, 53, 84, 61, 12, 9, 25, 0, 40, 9, 57, 0, 68, + 9, 89, 0, 14, 18, 20, 26, 42, 18, 48, 26, 70, 18, 76, 26, + 0, 43, 22, 35, 31, 44, 50, 35, 63, 44, 78, 35, 2, 52, 21, + 61, 30, 52, 53, 61, 61, 53, 85, 61, 11, 9, 26, 0, 39, 9, + 58, 0, 67, 9, 89, 1, 13, 18, 19, 26, 41, 18, 47, 26, 69, + 18, 75, 26, 0, 44, 21, 35, 32, 44, 49, 35, 64, 44, 77, 35, + 1, 52, 22, 61, 30, 53, 54, 61, 62, 53, 86, 61, 10, 9, 27, + 0, 38, 9, 59, 0, 66, 9, 88, 1, 12, 18, 18, 26, 40, 18, + 46, 26, 68, 18, 75, 27, 1, 44, 20, 35, 33, 44, 48, 35, 65, + 44, 76, 35, 0, 52, 23, 61, 31, 53, 55, 61, 63, 53, 87, 61, + 9, 9, 28, 0, 37, 9, 59, 1, 65, 9, 87, 1, 11, 18, 17, + 26, 39, 18, 45, 26, 67, 18, 76, 27, 2, 44, 19, 35, 34, 44, + 47, 35, 66, 44, 75, 35, 0, 53, 24, 61, 32, 53, 56, 61, 64, + 53, 88, 61, 8, 9, 29, 0, 36, 9, 58, 1, 64, 9, 86, 1, + 10, 18, 16, 26, 38, 18, 45, 27, 66, 18, 77, 27, 3, 44, 18, + 35, 35, 44, 46, 35, 67, 44, 75, 36, 1, 53, 25, 61, 33, 53, + 57, 61, 65, 53, 89, 61, 7, 9, 29, 1, 35, 9, 57, 1, 63, + 9, 85, 1, 9, 18, 15, 26, 37, 18, 46, 27, 65, 18, 78, 27, + 4, 44, 17, 35, 36, 44, 45, 35, 68, 44, 76, 36, 2, 53, 26, + 61, 34, 53, 58, 61, 66, 53, 89, 62, 6, 9, 28, 1, 34, 9, + 56, 1, 62, 9, 84, 1, 8, 18, 15, 27, 36, 18, 47, 27, 64, + 18, 79, 27, 5, 44, 16, 35, 37, 44, 45, 36, 69, 44, 77, 36, + 3, 53, 27, 61, 35, 53, 59, 61, 67, 53, 88, 62, 5, 9, 27, + 1, 33, 9, 55, 1, 61, 9, 83, 1, 7, 18, 16, 27, 35, 18, + 48, 27, 63, 18, 80, 27, 6, 44, 15, 35, 38, 44, 46, 36, 70, + 44, 78, 36, 4, 53, 28, 61, 36, 53, 59, 62, 68, 53, 87, 62, + 4, 9, 26, 1, 32, 9, 54, 1, 60, 9, 82, 1, 6, 18, 17, + 27, 34, 18, 49, 27, 62, 18, 81, 27, 7, 44, 15, 36, 39, 44, + 47, 36, 71, 44, 79, 36, 5, 53, 29, 61, 37, 53, 58, 62, 69, + 53, 86, 62, 3, 9, 25, 1, 31, 9, 53, 1, 60, 10, 81, 1, + 5, 18, 18, 27, 33, 18, 50, 27, 61, 18, 82, 27, 8, 44, 16, + 36, 40, 44, 48, 36, 72, 44, 80, 36, 6, 53, 29, 62, 38, 53, + 57, 62, 70, 53, 85, 62, 2, 9, 24, 1, 30, 9, 52, 1, 61, + 10, 80, 1, 4, 18, 19, 27, 32, 18, 51, 27, 60, 18, 83, 27, + 9, 44, 17, 36, 41, 44, 49, 36, 73, 44, 81, 36, 7, 53, 28, + 62, 39, 53, 56, 62, 71, 53, 84, 62, 1, 9, 23, 1, 30, 10, + 51, 1, 62, 10, 79, 1, 3, 18, 20, 27, 31, 18, 52, 27, 60, + 19, 84, 27, 10, 44, 18, 36, 42, 44, 50, 36, 74, 44, 82, 36, + 8, 53, 27, 62, 40, 53, 55, 62, 72, 53, 83, 62, 0, 9, 22, + 1, 31, 10, 50, 1, 63, 10, 78, 1, 2, 18, 21, 27, 30, 18, + 53, 27, 61, 19, 85, 27, 11, 44, 19, 36, 43, 44, 51, 36, 74, + 45, 83, 36, 9, 53, 26, 62, 41, 53, 54, 62, 73, 53, 82, 62, + 0, 10, 21, 1, 32, 10, 49, 1, 64, 10, 77, 1, 1, 18, 22, + 27, 30, 19, 54, 27, 62, 19, 86, 27, 12, 44, 20, 36, 44, 44, + 52, 36, 73, 45, 84, 36, 10, 53, 25, 62, 42, 53, 53, 62, 74, + 53, 81, 62, 1, 10, 20, 1, 33, 10, 48, 1, 65, 10, 76, 1, + 0, 18, 23, 27, 31, 19, 55, 27, 63, 19, 87, 27, 13, 44, 21, + 36, 44, 45, 53, 36, 72, 45, 85, 36, 11, 53, 24, 62, 43, 53, + 52, 62, 74, 54, 80, 62, 2, 10, 19, 1, 34, 10, 47, 1, 66, + 10, 75, 1, 0, 19, 24, 27, 32, 19, 56, 27, 64, 19, 88, 27, + 14, 44, 22, 36, 43, 45, 54, 36, 71, 45, 86, 36, 12, 53, 23, + 62, 44, 53, 51, 62, 73, 54, 79, 62, 3, 10, 18, 1, 35, 10, + 46, 1, 67, 10, 75, 2, 1, 19, 25, 27, 33, 19, 57, 27, 65, + 19, 89, 27, 14, 45, 23, 36, 42, 45, 55, 36, 70, 45, 87, 36, + 13, 53, 22, 62, 44, 54, 50, 62, 72, 54, 78, 62, 4, 10, 17, + 1, 36, 10, 45, 1, 68, 10, 76, 2, 2, 19, 26, 27, 34, 19, + 58, 27, 66, 19, 89, 28, 13, 45, 24, 36, 41, 45, 56, 36, 69, + 45, 88, 36, 14, 53, 21, 62, 43, 54, 49, 62, 71, 54, 77, 62, + 5, 10, 16, 1, 37, 10, 45, 2, 69, 10, 77, 2, 3, 19, 27, + 27, 35, 19, 59, 27, 67, 19, 88, 28, 12, 45, 25, 36, 40, 45, + 57, 36, 68, 45, 89, 36, 14, 54, 20, 62, 42, 54, 48, 62, 70, + 54, 76, 62, 6, 10, 15, 1, 38, 10, 46, 2, 70, 10, 78, 2, + 4, 19, 28, 27, 36, 19, 59, 28, 68, 19, 87, 28, 11, 45, 26, + 36, 39, 45, 58, 36, 67, 45, 89, 37, 13, 54, 19, 62, 41, 54, + 47, 62, 69, 54, 75, 62, 7, 10, 15, 2, 39, 10, 47, 2, 71, + 10, 79, 2, 5, 19, 29, 27, 37, 19, 58, 28, 69, 19, 86, 28, + 10, 45, 27, 36, 38, 45, 59, 36, 66, 45, 88, 37, 12, 54, 18, + 62, 40, 54, 46, 62, 68, 54, 75, 63, 8, 10, 16, 2, 40, 10, + 48, 2, 72, 10, 80, 2, 6, 19, 29, 28, 38, 19, 57, 28, 70, + 19, 85, 28, 9, 45, 28, 36, 37, 45, 59, 37, 65, 45, 87, 37, + 11, 54, 17, 62, 39, 54, 45, 62, 67, 54, 76, 63, 9, 10, 17, + 2, 41, 10, 49, 2, 73, 10, 81, 2, 7, 19, 28, 28, 39, 19, + 56, 28, 71, 19, 84, 28, 8, 45, 29, 36, 36, 45, 58, 37, 64, + 45, 86, 37, 10, 54, 16, 62, 38, 54, 45, 63, 66, 54, 77, 63, + 10, 10, 18, 2, 42, 10, 50, 2, 74, 10, 82, 2, 8, 19, 27, + 28, 40, 19, 55, 28, 72, 19, 83, 28, 7, 45, 29, 37, 35, 45, + 57, 37, 63, 45, 85, 37, 9, 54, 15, 62, 37, 54, 46, 63, 65, + 54, 78, 63, 11, 10, 19, 2, 43, 10, 51, 2, 74, 11, 83, 2, + 9, 19, 26, 28, 41, 19, 54, 28, 73, 19, 82, 28, 6, 45, 28, + 37, 34, 45, 56, 37, 62, 45, 84, 37, 8, 54, 15, 63, 36, 54, + 47, 63, 64, 54, 79, 63, 12, 10, 20, 2, 44, 10, 52, 2, 73, + 11, 84, 2, 10, 19, 25, 28, 42, 19, 53, 28, 74, 19, 81, 28, + 5, 45, 27, 37, 33, 45, 55, 37, 61, 45, 83, 37, 7, 54, 16, + 63, 35, 54, 48, 63, 63, 54, 80, 63, 13, 10, 21, 2, 44, 11, + 53, 2, 72, 11, 85, 2, 11, 19, 24, 28, 43, 19, 52, 28, 74, + 20, 80, 28, 4, 45, 26, 37, 32, 45, 54, 37, 60, 45, 82, 37, + 6, 54, 17, 63, 34, 54, 49, 63, 62, 54, 81, 63, 14, 10, 22, + 2, 43, 11, 54, 2, 71, 11, 86, 2, 12, 19, 23, 28, 44, 19, + 51, 28, 73, 20, 79, 28, 3, 45, 25, 37, 31, 45, 53, 37, 60, + 46, 81, 37, 5, 54, 18, 63, 33, 54, 50, 63, 61, 54, 82, 63, + 14, 11, 23, 2, 42, 11, 55, 2, 70, 11, 87, 2, 13, 19, 22, + 28, 44, 20, 50, 28, 72, 20, 78, 28, 2, 45, 24, 37, 30, 45, + 52, 37, 61, 46, 80, 37, 4, 54, 19, 63, 32, 54, 51, 63, 60, + 54, 83, 63, 13, 11, 24, 2, 41, 11, 56, 2, 69, 11, 88, 2, + 14, 19, 21, 28, 43, 20, 49, 28, 71, 20, 77, 28, 1, 45, 23, + 37, 30, 46, 51, 37, 62, 46, 79, 37, 3, 54, 20, 63, 31, 54, + 52, 63, 60, 55, 84, 63, 12, 11, 25, 2, 40, 11, 57, 2, 68, + 11, 89, 2, 14, 20, 20, 28, 42, 20, 48, 28, 70, 20, 76, 28, + 0, 45, 22, 37, 31, 46, 50, 37, 63, 46, 78, 37, 2, 54, 21, + 63, 30, 54, 53, 63, 61, 55, 85, 63, 11, 11, 26, 2, 39, 11, + 58, 2, 67, 11, 89, 3, 13, 20, 19, 28, 41, 20, 47, 28, 69, + 20, 75, 28, 0, 46, 21, 37, 32, 46, 49, 37, 64, 46, 77, 37, + 1, 54, 22, 63, 30, 55, 54, 63, 62, 55, 86, 63, 10, 11, 27, + 2, 38, 11, 59, 2, 66, 11, 88, 3, 12, 20, 18, 28, 40, 20, + 46, 28, 68, 20, 75, 29, 1, 46, 20, 37, 33, 46, 48, 37, 65, + 46, 76, 37, 0, 54, 23, 63, 31, 55, 55, 63, 63, 55, 87, 63, + 9, 11, 28, 2, 37, 11, 59, 3, 65, 11, 87, 3, 11, 20, 17, + 28, 39, 20, 45, 28, 67, 20, 76, 29, 2, 46, 19, 37, 34, 46, + 47, 37, 66, 46, 75, 37, 0, 55, 24, 63, 32, 55, 56, 63, 64, + 55, 88, 63, 8, 11, 29, 2, 36, 11, 58, 3, 64, 11, 86, 3, + 10, 20, 16, 28, 38, 20, 45, 29, 66, 20, 77, 29, 3, 46, 18, + 37, 35, 46, 46, 37, 67, 46, 75, 38, 1, 55, 25, 63, 33, 55, + 57, 63, 65, 55, 89, 63, 7, 11, 29, 3, 35, 11, 57, 3, 63, + 11, 85, 3, 9, 20, 15, 28, 37, 20, 46, 29, 65, 20, 78, 29, + 4, 46, 17, 37, 36, 46, 45, 37, 68, 46, 76, 38, 2, 55, 26, + 63, 34, 55, 58, 63, 66, 55, 89, 64, 6, 11, 28, 3, 34, 11, + 56, 3, 62, 11, 84, 3, 8, 20, 15, 29, 36, 20, 47, 29, 64, + 20, 79, 29, 5, 46, 16, 37, 37, 46, 45, 38, 69, 46, 77, 38, + 3, 55, 27, 63, 35, 55, 59, 63, 67, 55, 88, 64, 5, 11, 27, + 3, 33, 11, 55, 3, 61, 11, 83, 3, 7, 20, 16, 29, 35, 20, + 48, 29, 63, 20, 80, 29, 6, 46, 15, 37, 38, 46, 46, 38, 70, + 46, 78, 38, 4, 55, 28, 63, 36, 55, 59, 64, 68, 55, 87, 64, + 4, 11, 26, 3, 32, 11, 54, 3, 60, 11, 82, 3, 6, 20, 17, + 29, 34, 20, 49, 29, 62, 20, 81, 29, 7, 46, 15, 38, 39, 46, + 47, 38, 71, 46, 79, 38, 5, 55, 29, 63, 37, 55, 58, 64, 69, + 55, 86, 64, 3, 11, 25, 3, 31, 11, 53, 3, 60, 12, 81, 3, + 5, 20, 18, 29, 33, 20, 50, 29, 61, 20, 82, 29, 8, 46, 16, + 38, 40, 46, 48, 38, 72, 46, 80, 38, 6, 55, 29, 64, 38, 55, + 57, 64, 70, 55, 85, 64, 2, 11, 24, 3, 30, 11, 52, 3, 61, + 12, 80, 3, 4, 20, 19, 29, 32, 20, 51, 29, 60, 20, 83, 29, + 9, 46, 17, 38, 41, 46, 49, 38, 73, 46, 81, 38, 7, 55, 28, + 64, 39, 55, 56, 64, 71, 55, 84, 64, 1, 11, 23, 3, 30, 12, + 51, 3, 62, 12, 79, 3, 3, 20, 20, 29, 31, 20, 52, 29, 60, + 21, 84, 29, 10, 46, 18, 38, 42, 46, 50, 38, 74, 46, 82, 38, + 8, 55, 27, 64, 40, 55, 55, 64, 72, 55, 83, 64, 0, 11, 22, + 3, 31, 12, 50, 3, 63, 12, 78, 3, 2, 20, 21, 29, 30, 20, + 53, 29, 61, 21, 85, 29, 11, 46, 19, 38, 43, 46, 51, 38, 74, + 47, 83, 38, 9, 55, 26, 64, 41, 55, 54, 64, 73, 55, 82, 64, + 0, 12, 21, 3, 32, 12, 49, 3, 64, 12, 77, 3, 1, 20, 22, + 29, 30, 21, 54, 29, 62, 21, 86, 29, 12, 46, 20, 38, 44, 46, + 52, 38, 73, 47, 84, 38, 10, 55, 25, 64, 42, 55, 53, 64, 74, + 55, 81, 64, 1, 12, 20, 3, 33, 12, 48, 3, 65, 12, 76, 3, + 0, 20, 23, 29, 31, 21, 55, 29, 63, 21, 87, 29, 13, 46, 21, + 38, 44, 47, 53, 38, 72, 47, 85, 38, 11, 55, 24, 64, 43, 55, + 52, 64, 74, 56, 80, 64, 2, 12, 19, 3, 34, 12, 47, 3, 66, + 12, 75, 3, 0, 21, 24, 29, 32, 21, 56, 29, 64, 21, 88, 29, + 14, 46, 22, 38, 43, 47, 54, 38, 71, 47, 86, 38, 12, 55, 23, + 64, 44, 55, 51, 64, 73, 56, 79, 64, 3, 12, 18, 3, 35, 12, + 46, 3, 67, 12, 75, 4, 1, 21, 25, 29, 33, 21, 57, 29, 65, + 21, 89, 29, 14, 47, 23, 38, 42, 47, 55, 38, 70, 47, 87, 38, + 13, 55, 22, 64, 44, 56, 50, 64, 72, 56, 78, 64, 4, 12, 17, + 3, 36, 12, 45, 3, 68, 12, 76, 4, 2, 21, 26, 29, 34, 21, + 58, 29, 66, 21, 89, 30, 13, 47, 24, 38, 41, 47, 56, 38, 69, + 47, 88, 38, 14, 55, 21, 64, 43, 56, 49, 64, 71, 56, 77, 64, + 5, 12, 16, 3, 37, 12, 45, 4, 69, 12, 77, 4, 3, 21, 27, + 29, 35, 21, 59, 29, 67, 21, 88, 30, 12, 47, 25, 38, 40, 47, + 57, 38, 68, 47, 89, 38, 14, 56, 20, 64, 42, 56, 48, 64, 70, + 56, 76, 64, 6, 12, 15, 3, 38, 12, 46, 4, 70, 12, 78, 4, + 4, 21, 28, 29, 36, 21, 59, 30, 68, 21, 87, 30, 11, 47, 26, + 38, 39, 47, 58, 38, 67, 47, 89, 39, 13, 56, 19, 64, 41, 56, + 47, 64, 69, 56, 75, 64, 7, 12, 15, 4, 39, 12, 47, 4, 71, + 12, 79, 4, 5, 21, 29, 29, 37, 21, 58, 30, 69, 21, 86, 30, + 10, 47, 27, 38, 38, 47, 59, 38, 66, 47, 88, 39, 12, 56, 18, + 64, 40, 56, 46, 64, 68, 56, 75, 65, 8, 12, 16, 4, 40, 12, + 48, 4, 72, 12, 80, 4, 6, 21, 29, 30, 38, 21, 57, 30, 70, + 21, 85, 30, 9, 47, 28, 38, 37, 47, 59, 39, 65, 47, 87, 39, + 11, 56, 17, 64, 39, 56, 45, 64, 67, 56, 76, 65, 9, 12, 17, + 4, 41, 12, 49, 4, 73, 12, 81, 4, 7, 21, 28, 30, 39, 21, + 56, 30, 71, 21, 84, 30, 8, 47, 29, 38, 36, 47, 58, 39, 64, + 47, 86, 39, 10, 56, 16, 64, 38, 56, 45, 65, 66, 56, 77, 65, + 10, 12, 18, 4, 42, 12, 50, 4, 74, 12, 82, 4, 8, 21, 27, + 30, 40, 21, 55, 30, 72, 21, 83, 30, 7, 47, 29, 39, 35, 47, + 57, 39, 63, 47, 85, 39, 9, 56, 15, 64, 37, 56, 46, 65, 65, + 56, 78, 65, 11, 12, 19, 4, 43, 12, 51, 4, 74, 13, 83, 4, + 9, 21, 26, 30, 41, 21, 54, 30, 73, 21, 82, 30, 6, 47, 28, + 39, 34, 47, 56, 39, 62, 47, 84, 39, 8, 56, 15, 65, 36, 56, + 47, 65, 64, 56, 79, 65, 12, 12, 20, 4, 44, 12, 52, 4, 73, + 13, 84, 4, 10, 21, 25, 30, 42, 21, 53, 30, 74, 21, 81, 30, + 5, 47, 27, 39, 33, 47, 55, 39, 61, 47, 83, 39, 7, 56, 16, + 65, 35, 56, 48, 65, 63, 56, 80, 65, 13, 12, 21, 4, 44, 13, + 53, 4, 72, 13, 85, 4, 11, 21, 24, 30, 43, 21, 52, 30, 74, + 22, 80, 30, 4, 47, 26, 39, 32, 47, 54, 39, 60, 47, 82, 39, + 6, 56, 17, 65, 34, 56, 49, 65, 62, 56, 81, 65, 14, 12, 22, + 4, 43, 13, 54, 4, 71, 13, 86, 4, 12, 21, 23, 30, 44, 21, + 51, 30, 73, 22, 79, 30, 3, 47, 25, 39, 31, 47, 53, 39, 60, + 48, 81, 39, 5, 56, 18, 65, 33, 56, 50, 65, 61, 56, 82, 65, + 14, 13, 23, 4, 42, 13, 55, 4, 70, 13, 87, 4, 13, 21, 22, + 30, 44, 22, 50, 30, 72, 22, 78, 30, 2, 47, 24, 39, 30, 47, + 52, 39, 61, 48, 80, 39, 4, 56, 19, 65, 32, 56, 51, 65, 60, + 56, 83, 65, 13, 13, 24, 4, 41, 13, 56, 4, 69, 13, 88, 4, + 14, 21, 21, 30, 43, 22, 49, 30, 71, 22, 77, 30, 1, 47, 23, + 39, 30, 48, 51, 39, 62, 48, 79, 39, 3, 56, 20, 65, 31, 56, + 52, 65, 60, 57, 84, 65, 12, 13, 25, 4, 40, 13, 57, 4, 68, + 13, 89, 4, 14, 22, 20, 30, 42, 22, 48, 30, 70, 22, 76, 30, + 0, 47, 22, 39, 31, 48, 50, 39, 63, 48, 78, 39, 2, 56, 21, + 65, 30, 56, 53, 65, 61, 57, 85, 65, 11, 13, 26, 4, 39, 13, + 58, 4, 67, 13, 89, 5, 13, 22, 19, 30, 41, 22, 47, 30, 69, + 22, 75, 30, 0, 48, 21, 39, 32, 48, 49, 39, 64, 48, 77, 39, + 1, 56, 22, 65, 30, 57, 54, 65, 62, 57, 86, 65, 10, 13, 27, + 4, 38, 13, 59, 4, 66, 13, 88, 5, 12, 22, 18, 30, 40, 22, + 46, 30, 68, 22, 75, 31, 1, 48, 20, 39, 33, 48, 48, 39, 65, + 48, 76, 39, 0, 56, 23, 65, 31, 57, 55, 65, 63, 57, 87, 65, + 9, 13, 28, 4, 37, 13, 59, 5, 65, 13, 87, 5, 11, 22, 17, + 30, 39, 22, 45, 30, 67, 22, 76, 31, 2, 48, 19, 39, 34, 48, + 47, 39, 66, 48, 75, 39, 0, 57, 24, 65, 32, 57, 56, 65, 64, + 57, 88, 65, 8, 13, 29, 4, 36, 13, 58, 5, 64, 13, 86, 5, + 10, 22, 16, 30, 38, 22, 45, 31, 66, 22, 77, 31, 3, 48, 18, + 39, 35, 48, 46, 39, 67, 48, 75, 40, 1, 57, 25, 65, 33, 57, + 57, 65, 65, 57, 89, 65, 7, 13, 29, 5, 35, 13, 57, 5, 63, + 13, 85, 5, 9, 22, 15, 30, 37, 22, 46, 31, 65, 22, 78, 31, + 4, 48, 17, 39, 36, 48, 45, 39, 68, 48, 76, 40, 2, 57, 26, + 65, 34, 57, 58, 65, 66, 57, 89, 66, 6, 13, 28, 5, 34, 13, + 56, 5, 62, 13, 84, 5, 8, 22, 15, 31, 36, 22, 47, 31, 64, + 22, 79, 31, 5, 48, 16, 39, 37, 48, 45, 40, 69, 48, 77, 40, + 3, 57, 27, 65, 35, 57, 59, 65, 67, 57, 88, 66, 5, 13, 27, + 5, 33, 13, 55, 5, 61, 13, 83, 5, 7, 22, 16, 31, 35, 22, + 48, 31, 63, 22, 80, 31, 6, 48, 15, 39, 38, 48, 46, 40, 70, + 48, 78, 40, 4, 57, 28, 65, 36, 57, 59, 66, 68, 57, 87, 66, + 4, 13, 26, 5, 32, 13, 54, 5, 60, 13, 82, 5, 6, 22, 17, + 31, 34, 22, 49, 31, 62, 22, 81, 31, 7, 48, 15, 40, 39, 48, + 47, 40, 71, 48, 79, 40, 5, 57, 29, 65, 37, 57, 58, 66, 69, + 57, 86, 66, 3, 13, 25, 5, 31, 13, 53, 5, 60, 14, 81, 5, + 5, 22, 18, 31, 33, 22, 50, 31, 61, 22, 82, 31, 8, 48, 16, + 40, 40, 48, 48, 40, 72, 48, 80, 40, 6, 57, 29, 66, 38, 57, + 57, 66, 70, 57, 85, 66, 2, 13, 24, 5, 30, 13, 52, 5, 61, + 14, 80, 5, 4, 22, 19, 31, 32, 22, 51, 31, 60, 22, 83, 31, + 9, 48, 17, 40, 41, 48, 49, 40, 73, 48, 81, 40, 7, 57, 28, + 66, 39, 57, 56, 66, 71, 57, 84, 66, 1, 13, 23, 5, 30, 14, + 51, 5, 62, 14, 79, 5, 3, 22, 20, 31, 31, 22, 52, 31, 60, + 23, 84, 31, 10, 48, 18, 40, 42, 48, 50, 40, 74, 48, 82, 40, + 8, 57, 27, 66, 40, 57, 55, 66, 72, 57, 83, 66, 0, 13, 22, + 5, 31, 14, 50, 5, 63, 14, 78, 5, 2, 22, 21, 31, 30, 22, + 53, 31, 61, 23, 85, 31, 11, 48, 19, 40, 43, 48, 51, 40, 74, + 49, 83, 40, 9, 57, 26, 66, 41, 57, 54, 66, 73, 57, 82, 66, + 0, 14, 21, 5, 32, 14, 49, 5, 64, 14, 77, 5, 1, 22, 22, + 31, 30, 23, 54, 31, 62, 23, 86, 31, 12, 48, 20, 40, 44, 48, + 52, 40, 73, 49, 84, 40, 10, 57, 25, 66, 42, 57, 53, 66, 74, + 57, 81, 66, 1, 14, 20, 5, 33, 14, 48, 5, 65, 14, 76, 5, + 0, 22, 23, 31, 31, 23, 55, 31, 63, 23, 87, 31, 13, 48, 21, + 40, 44, 49, 53, 40, 72, 49, 85, 40, 11, 57, 24, 66, 43, 57, + 52, 66, 74, 58, 80, 66, 2, 14, 19, 5, 34, 14, 47, 5, 66, + 14, 75, 5, 0, 23, 24, 31, 32, 23, 56, 31, 64, 23, 88, 31, + 14, 48, 22, 40, 43, 49, 54, 40, 71, 49, 86, 40, 12, 57, 23, + 66, 44, 57, 51, 66, 73, 58, 79, 66, 3, 14, 18, 5, 35, 14, + 46, 5, 67, 14, 75, 6, 1, 23, 25, 31, 33, 23, 57, 31, 65, + 23, 89, 31, 14, 49, 23, 40, 42, 49, 55, 40, 70, 49, 87, 40, + 13, 57, 22, 66, 44, 58, 50, 66, 72, 58, 78, 66, 4, 14, 17, + 5, 36, 14, 45, 5, 68, 14, 76, 6, 2, 23, 26, 31, 34, 23, + 58, 31, 66, 23, 89, 32, 13, 49, 24, 40, 41, 49, 56, 40, 69, + 49, 88, 40, 14, 57, 21, 66, 43, 58, 49, 66, 71, 58, 77, 66, + 5, 14, 16, 5, 37, 14, 45, 6, 69, 14, 77, 6, 3, 23, 27, + 31, 35, 23, 59, 31, 67, 23, 88, 32, 12, 49, 25, 40, 40, 49, + 57, 40, 68, 49, 89, 40, 14, 58, 20, 66, 42, 58, 48, 66, 70, + 58, 76, 66, 6, 14, 15, 5, 38, 14, 46, 6, 70, 14, 78, 6, + 4, 23, 28, 31, 36, 23, 59, 32, 68, 23, 87, 32, 11, 49, 26, + 40, 39, 49, 58, 40, 67, 49, 89, 41, 13, 58, 19, 66, 41, 58, + 47, 66, 69, 58, 75, 66, 7, 14, 15, 6, 39, 14, 47, 6, 71, + 14, 79, 6, 5, 23, 29, 31, 37, 23, 58, 32, 69, 23, 86, 32, + 10, 49, 27, 40, 38, 49, 59, 40, 66, 49, 88, 41, 12, 58, 18, + 66, 40, 58, 46, 66, 68, 58, 75, 67, 8, 14, 16, 6, 40, 14, + 48, 6, 72, 14, 80, 6, 6, 23, 29, 32, 38, 23, 57, 32, 70, + 23, 85, 32, 9, 49, 28, 40, 37, 49, 59, 41, 65, 49, 87, 41, + 11, 58, 17, 66, 39, 58, 45, 66, 67, 58, 76, 67, 9, 14, 17, + 6, 41, 14, 49, 6, 73, 14, 81, 6, 7, 23, 28, 32, 39, 23, + 56, 32, 71, 23, 84, 32, 8, 49, 29, 40, 36, 49, 58, 41, 64, + 49, 86, 41, 10, 58, 16, 66, 38, 58, 45, 67, 66, 58, 77, 67, + 10, 14, 18, 6, 42, 14, 50, 6, 74, 14, 82, 6, 8, 23, 27, + 32, 40, 23, 55, 32, 72, 23, 83, 32, 7, 49, 29, 41, 35, 49, + 57, 41, 63, 49, 85, 41, 9, 58, 15, 66, 37, 58, 46, 67, 65, + 58, 78, 67, 11, 14, 19, 6, 43, 14, 51, 6, 74, 15, 83, 6, + 9, 23, 26, 32, 41, 23, 54, 32, 73, 23, 82, 32, 6, 49, 28, + 41, 34, 49, 56, 41, 62, 49, 84, 41, 8, 58, 15, 67, 36, 58, + 47, 67, 64, 58, 79, 67, 12, 14, 20, 6, 44, 14, 52, 6, 73, + 15, 84, 6, 10, 23, 25, 32, 42, 23, 53, 32, 74, 23, 81, 32, + 5, 49, 27, 41, 33, 49, 55, 41, 61, 49, 83, 41, 7, 58, 16, + 67, 35, 58, 48, 67, 63, 58, 80, 67, 13, 14, 21, 6, 44, 15, + 53, 6, 72, 15, 85, 6, 11, 23, 24, 32, 43, 23, 52, 32, 74, + 24, 80, 32, 4, 49, 26, 41, 32, 49, 54, 41, 60, 49, 82, 41, + 6, 58, 17, 67, 34, 58, 49, 67, 62, 58, 81, 67, 14, 14, 22, + 6, 43, 15, 54, 6, 71, 15, 86, 6, 12, 23, 23, 32, 44, 23, + 51, 32, 73, 24, 79, 32, 3, 49, 25, 41, 31, 49, 53, 41, 60, + 50, 81, 41, 5, 58, 18, 67, 33, 58, 50, 67, 61, 58, 82, 67, + 14, 15, 23, 6, 42, 15, 55, 6, 70, 15, 87, 6, 13, 23, 22, + 32, 44, 24, 50, 32, 72, 24, 78, 32, 2, 49, 24, 41, 30, 49, + 52, 41, 61, 50, 80, 41, 4, 58, 19, 67, 32, 58, 51, 67, 60, + 58, 83, 67, 13, 15, 24, 6, 41, 15, 56, 6, 69, 15, 88, 6, + 14, 23, 21, 32, 43, 24, 49, 32, 71, 24, 77, 32, 1, 49, 23, + 41, 30, 50, 51, 41, 62, 50, 79, 41, 3, 58, 20, 67, 31, 58, + 52, 67, 60, 59, 84, 67, 12, 15, 25, 6, 40, 15, 57, 6, 68, + 15, 89, 6, 14, 24, 20, 32, 42, 24, 48, 32, 70, 24, 76, 32, + 0, 49, 22, 41, 31, 50, 50, 41, 63, 50, 78, 41, 2, 58, 21, + 67, 30, 58, 53, 67, 61, 59, 85, 67, 11, 15, 26, 6, 39, 15, + 58, 6, 67, 15, 89, 7, 13, 24, 19, 32, 41, 24, 47, 32, 69, + 24, 75, 32, 0, 50, 21, 41, 32, 50, 49, 41, 64, 50, 77, 41, + 1, 58, 22, 67, 30, 59, 54, 67, 62, 59, 86, 67, 10, 15, 27, + 6, 38, 15, 59, 6, 66, 15, 88, 7, 12, 24, 18, 32, 40, 24, + 46, 32, 68, 24, 75, 33, 1, 50, 20, 41, 33, 50, 48, 41, 65, + 50, 76, 41, 0, 58, 23, 67, 31, 59, 55, 67, 63, 59, 87, 67, + 9, 15, 28, 6, 37, 15, 59, 7, 65, 15, 87, 7, 11, 24, 17, + 32, 39, 24, 45, 32, 67, 24, 76, 33, 2, 50, 19, 41, 34, 50, + 47, 41, 66, 50, 75, 41, 0, 59, 24, 67, 32, 59, 56, 67, 64, + 59, 88, 67, 8, 15, 29, 6, 36, 15, 58, 7, 64, 15, 86, 7, + 10, 24, 16, 32, 38, 24, 45, 33, 66, 24, 77, 33, 3, 50, 18, + 41, 35, 50, 46, 41, 67, 50, 75, 42, 1, 59, 25, 67, 33, 59, + 57, 67, 65, 59, 89, 67, 7, 15, 29, 7, 35, 15, 57, 7, 63, + 15, 85, 7, 9, 24, 15, 32, 37, 24, 46, 33, 65, 24, 78, 33, + 4, 50, 17, 41, 36, 50, 45, 41, 68, 50, 76, 42, 2, 59, 26, + 67, 34, 59, 58, 67, 66, 59, 75, 51, 6, 15, 28, 7, 34, 15, + 56, 7, 62, 15, 84, 7, 8, 24, 15, 33, 36, 24, 47, 33, 64, + 24, 79, 33, 5, 50, 16, 41, 37, 50, 45, 42, 69, 50, 77, 42, + 3, 59, 27, 67, 35, 59, 59, 67, 67, 59, 76, 51, 5, 15, 27, + 7, 33, 15, 55, 7, 61, 15, 83, 7, 7, 24, 16, 33, 35, 24, + 48, 33, 63, 24, 80, 33, 6, 50, 15, 41, 38, 50, 46, 42, 70, + 50, 78, 42, 4, 59, 28, 67, 36, 59, 45, 51, 68, 59, 77, 51, + 4, 15, 26, 7, 32, 15, 54, 7, 60, 15, 82, 7, 6, 24, 17, + 33, 34, 24, 49, 33, 62, 24, 81, 33, 7, 50, 15, 42, 39, 50, + 47, 42, 71, 50, 79, 42, 5, 59, 29, 67, 37, 59, 46, 51, 69, + 59, 78, 51, 3, 15, 25, 7, 31, 15, 53, 7, 60, 16, 81, 7, + 5, 24, 18, 33, 33, 24, 50, 33, 61, 24, 82, 33, 8, 50, 16, + 42, 40, 50, 48, 42, 72, 50, 80, 42, 6, 59, 15, 51, 38, 59, + 47, 51, 70, 59, 79, 51, 2, 15, 24, 7, 30, 15, 52, 7, 61, + 16, 80, 7, 4, 24, 19, 33, 32, 24, 51, 33, 60, 24, 83, 33, + 9, 50, 17, 42, 41, 50, 49, 42, 73, 50, 81, 42, 7, 59, 16, + 51, 39, 59, 48, 51, 71, 59, 80, 51, 1, 15, 23, 7, 30, 16, + 51, 7, 62, 16, 79, 7, 3, 24, 20, 33, 31, 24, 52, 33, 60, + 25, 84, 33, 10, 50, 18, 42, 42, 50, 50, 42, 74, 50, 82, 42, + 8, 59, 17, 51, 40, 59, 49, 51, 72, 59, 81, 51, 0, 15, 22, + 7, 31, 16, 50, 7, 63, 16, 78, 7, 2, 24, 21, 33, 30, 24, + 53, 33, 61, 25, 85, 33, 11, 50, 19, 42, 43, 50, 51, 42, 60, + 34, 83, 42, 9, 59, 18, 51, 41, 59, 50, 51, 73, 59, 82, 51, + 0, 16, 21, 7, 32, 16, 49, 7, 64, 16, 77, 7, 1, 24, 22, + 33, 30, 25, 54, 33, 62, 25, 86, 33, 12, 50, 20, 42, 44, 50, + 52, 42, 61, 34, 84, 42, 10, 59, 19, 51, 42, 59, 51, 51, 74, + 59, 83, 51, 1, 16, 20, 7, 33, 16, 48, 7, 65, 16, 76, 7, + 0, 24, 23, 33, 31, 25, 55, 33, 63, 25, 87, 33, 13, 50, 21, + 42, 30, 34, 53, 42, 62, 34, 85, 42, 11, 59, 20, 51, 43, 59, + 52, 51, 74, 60, 84, 51, 2, 16, 19, 7, 34, 16, 47, 7, 66, + 16, 75, 7, 0, 25, 24, 33, 32, 25, 56, 33, 64, 25, 88, 33, + 14, 50, 22, 42, 31, 34, 54, 42, 63, 34, 86, 42, 12, 59, 21, + 51, 44, 59, 53, 51, 73, 60, 85, 51, 3, 16, 18, 7, 35, 16, + 46, 7, 67, 16, 75, 8, 1, 25, 25, 33, 33, 25, 57, 33, 65, + 25, 89, 33, 0, 34, 23, 42, 32, 34, 55, 42, 64, 34, 87, 42, + 13, 59, 22, 51, 44, 60, 54, 51, 72, 60, 86, 51, 4, 16, 17, + 7, 36, 16, 45, 7, 68, 16, 76, 8, 2, 25, 26, 33, 34, 25, + 58, 33, 66, 25, 75, 17, 1, 34, 24, 42, 33, 34, 56, 42, 65, + 34, 88, 42, 14, 59, 23, 51, 43, 60, 55, 51, 71, 60, 87, 51, + 5, 16, 16, 7, 37, 16, 45, 8, 69, 16, 77, 8, 3, 25, 27, + 33, 35, 25, 59, 33, 67, 25, 76, 17, 2, 34, 25, 42, 34, 34, + 57, 42, 66, 34, 89, 42, 14, 60, 24, 51, 42, 60, 56, 51, 70, + 60, 88, 51, 6, 16, 15, 7, 38, 16, 46, 8, 70, 16, 78, 8, + 4, 25, 28, 33, 36, 25, 45, 17, 68, 25, 77, 17, 3, 34, 26, + 42, 35, 34, 58, 42, 67, 34, 89, 43, 13, 60, 25, 51, 41, 60, + 57, 51, 69, 60, 89, 51, 7, 16, 15, 8, 39, 16, 47, 8, 71, + 16, 79, 8, 5, 25, 29, 33, 37, 25, 46, 17, 69, 25, 78, 17, + 4, 34, 27, 42, 36, 34, 59, 42, 68, 34, 88, 43, 12, 60, 26, + 51, 40, 60, 58, 51, 68, 60, 89, 52, 8, 16, 16, 8, 40, 16, + 48, 8, 72, 16, 80, 8, 6, 25, 15, 17, 38, 25, 47, 17, 70, + 25, 79, 17, 5, 34, 28, 42, 37, 34, 59, 43, 69, 34, 87, 43, + 11, 60, 27, 51, 39, 60, 59, 51, 67, 60, 88, 52, 9, 16, 17, + 8, 41, 16, 49, 8, 73, 16, 81, 8, 7, 25, 16, 17, 39, 25, + 48, 17, 71, 25, 80, 17, 6, 34, 29, 42, 38, 34, 58, 43, 70, + 34, 86, 43, 10, 60, 28, 51, 38, 60, 59, 52, 66, 60, 87, 52, + 10, 16, 18, 8, 42, 16, 50, 8, 74, 16, 82, 8, 8, 25, 17, + 17, 40, 25, 49, 17, 72, 25, 81, 17, 7, 34, 29, 43, 39, 34, + 57, 43, 71, 34, 85, 43, 9, 60, 29, 51, 37, 60, 58, 52, 65, + 60, 86, 52, 11, 16, 19, 8, 43, 16, 51, 8, 60, 0, 83, 8, + 9, 25, 18, 17, 41, 25, 50, 17, 73, 25, 82, 17, 8, 34, 28, + 43, 40, 34, 56, 43, 72, 34, 84, 43, 8, 60, 29, 52, 36, 60, + 57, 52, 64, 60, 85, 52, 12, 16, 20, 8, 44, 16, 52, 8, 61, + 0, 84, 8, 10, 25, 19, 17, 42, 25, 51, 17, 74, 25, 83, 17, + 9, 34, 27, 43, 41, 34, 55, 43, 73, 34, 83, 43, 7, 60, 28, + 52, 35, 60, 56, 52, 63, 60, 84, 52, 13, 16, 21, 8, 30, 0, + 53, 8, 62, 0, 85, 8, 11, 25, 20, 17, 43, 25, 52, 17, 74, + 26, 84, 17, 10, 34, 26, 43, 42, 34, 54, 43, 74, 34, 82, 43, + 6, 60, 27, 52, 34, 60, 55, 52, 62, 60, 83, 52, 14, 16, 22, + 8, 31, 0, 54, 8, 63, 0, 86, 8, 12, 25, 21, 17, 44, 25, + 53, 17, 73, 26, 85, 17, 11, 34, 25, 43, 43, 34, 53, 43, 74, + 35, 81, 43, 5, 60, 26, 52, 33, 60, 54, 52, 61, 60, 82, 52, +}; + +static const uint8_t hq_tab_08[] = { + 0, 0, 31, 8, 42, 0, 73, 8, 84, 0, 115, 8, 16, 25, 27, + 17, 58, 25, 69, 17, 99, 26, 111, 17, 12, 34, 36, 43, 54, 34, + 74, 43, 96, 34, 112, 43, 11, 60, 39, 51, 49, 60, 78, 52, 87, + 60, 116, 52, 1, 0, 32, 8, 43, 0, 74, 8, 85, 0, 116, 8, + 17, 25, 28, 17, 59, 25, 70, 17, 98, 26, 112, 17, 13, 34, 35, + 43, 55, 34, 73, 43, 97, 34, 111, 43, 10, 60, 39, 52, 48, 60, + 77, 52, 86, 60, 115, 52, 2, 0, 33, 8, 44, 0, 75, 8, 86, + 0, 117, 8, 18, 25, 29, 17, 59, 26, 71, 17, 97, 26, 113, 17, + 14, 34, 34, 43, 56, 34, 72, 43, 98, 34, 110, 43, 9, 60, 38, + 52, 47, 60, 76, 52, 85, 60, 114, 52, 3, 0, 34, 8, 45, 0, + 76, 8, 87, 0, 118, 8, 19, 25, 30, 17, 58, 26, 72, 17, 96, + 26, 114, 17, 15, 34, 33, 43, 57, 34, 71, 43, 99, 34, 109, 43, + 8, 60, 37, 52, 46, 60, 75, 52, 84, 60, 113, 52, 4, 0, 35, + 8, 46, 0, 77, 8, 88, 0, 119, 8, 19, 26, 31, 17, 57, 26, + 73, 17, 95, 26, 115, 17, 16, 34, 32, 43, 58, 34, 70, 43, 99, + 35, 108, 43, 7, 60, 36, 52, 45, 60, 74, 52, 83, 60, 112, 52, + 5, 0, 36, 8, 47, 0, 78, 8, 89, 0, 119, 9, 18, 26, 32, + 17, 56, 26, 74, 17, 94, 26, 116, 17, 17, 34, 31, 43, 59, 34, + 69, 43, 98, 35, 107, 43, 6, 60, 35, 52, 44, 60, 73, 52, 82, + 60, 111, 52, 6, 0, 37, 8, 48, 0, 79, 8, 90, 0, 118, 9, + 17, 26, 33, 17, 55, 26, 75, 17, 93, 26, 117, 17, 18, 34, 30, + 43, 59, 35, 68, 43, 97, 35, 106, 43, 5, 60, 34, 52, 43, 60, + 72, 52, 81, 60, 110, 52, 7, 0, 38, 8, 49, 0, 79, 9, 91, + 0, 117, 9, 16, 26, 34, 17, 54, 26, 76, 17, 92, 26, 118, 17, + 19, 34, 29, 43, 58, 35, 67, 43, 96, 35, 105, 43, 4, 60, 33, + 52, 42, 60, 71, 52, 80, 60, 109, 52, 8, 0, 39, 8, 50, 0, + 78, 9, 92, 0, 116, 9, 15, 26, 35, 17, 53, 26, 77, 17, 91, + 26, 119, 17, 19, 35, 28, 43, 57, 35, 66, 43, 95, 35, 104, 43, + 3, 60, 32, 52, 41, 60, 70, 52, 80, 61, 108, 52, 9, 0, 39, + 9, 51, 0, 77, 9, 93, 0, 115, 9, 14, 26, 36, 17, 52, 26, + 78, 17, 90, 26, 119, 18, 18, 35, 27, 43, 56, 35, 65, 43, 94, + 35, 103, 43, 2, 60, 31, 52, 40, 60, 69, 52, 81, 61, 107, 52, + 10, 0, 38, 9, 52, 0, 76, 9, 94, 0, 114, 9, 13, 26, 37, + 17, 51, 26, 79, 17, 89, 26, 118, 18, 17, 35, 26, 43, 55, 35, + 64, 43, 93, 35, 102, 43, 1, 60, 30, 52, 40, 61, 68, 52, 82, + 61, 106, 52, 11, 0, 37, 9, 53, 0, 75, 9, 95, 0, 113, 9, + 12, 26, 38, 17, 50, 26, 79, 18, 88, 26, 117, 18, 16, 35, 25, + 43, 54, 35, 63, 43, 92, 35, 101, 43, 0, 60, 29, 52, 41, 61, + 67, 52, 83, 61, 105, 52, 12, 0, 36, 9, 54, 0, 74, 9, 96, + 0, 112, 9, 11, 26, 39, 17, 49, 26, 78, 18, 87, 26, 116, 18, + 15, 35, 24, 43, 53, 35, 62, 43, 91, 35, 100, 43, 0, 61, 28, + 52, 42, 61, 66, 52, 84, 61, 104, 52, 13, 0, 35, 9, 55, 0, + 73, 9, 97, 0, 111, 9, 10, 26, 39, 18, 48, 26, 77, 18, 86, + 26, 115, 18, 14, 35, 23, 43, 52, 35, 61, 43, 90, 35, 100, 44, + 1, 61, 27, 52, 43, 61, 65, 52, 85, 61, 103, 52, 14, 0, 34, + 9, 56, 0, 72, 9, 98, 0, 110, 9, 9, 26, 38, 18, 47, 26, + 76, 18, 85, 26, 114, 18, 13, 35, 22, 43, 51, 35, 60, 43, 89, + 35, 101, 44, 2, 61, 26, 52, 44, 61, 64, 52, 86, 61, 102, 52, + 15, 0, 33, 9, 57, 0, 71, 9, 99, 0, 109, 9, 8, 26, 37, + 18, 46, 26, 75, 18, 84, 26, 113, 18, 12, 35, 21, 43, 50, 35, + 60, 44, 88, 35, 102, 44, 3, 61, 25, 52, 45, 61, 63, 52, 87, + 61, 101, 52, 16, 0, 32, 9, 58, 0, 70, 9, 99, 1, 108, 9, + 7, 26, 36, 18, 45, 26, 74, 18, 83, 26, 112, 18, 11, 35, 20, + 43, 49, 35, 61, 44, 87, 35, 103, 44, 4, 61, 24, 52, 46, 61, + 62, 52, 88, 61, 100, 52, 17, 0, 31, 9, 59, 0, 69, 9, 98, + 1, 107, 9, 6, 26, 35, 18, 44, 26, 73, 18, 82, 26, 111, 18, + 10, 35, 20, 44, 48, 35, 62, 44, 86, 35, 104, 44, 5, 61, 23, + 52, 47, 61, 61, 52, 89, 61, 100, 53, 18, 0, 30, 9, 59, 1, + 68, 9, 97, 1, 106, 9, 5, 26, 34, 18, 43, 26, 72, 18, 81, + 26, 110, 18, 9, 35, 21, 44, 47, 35, 63, 44, 85, 35, 105, 44, + 6, 61, 22, 52, 48, 61, 60, 52, 90, 61, 101, 53, 19, 0, 29, + 9, 58, 1, 67, 9, 96, 1, 105, 9, 4, 26, 33, 18, 42, 26, + 71, 18, 80, 26, 109, 18, 8, 35, 22, 44, 46, 35, 64, 44, 84, + 35, 106, 44, 7, 61, 21, 52, 49, 61, 60, 53, 91, 61, 102, 53, + 19, 1, 28, 9, 57, 1, 66, 9, 95, 1, 104, 9, 3, 26, 32, + 18, 41, 26, 70, 18, 80, 27, 108, 18, 7, 35, 23, 44, 45, 35, + 65, 44, 83, 35, 107, 44, 8, 61, 20, 52, 50, 61, 61, 53, 92, + 61, 103, 53, 18, 1, 27, 9, 56, 1, 65, 9, 94, 1, 103, 9, + 2, 26, 31, 18, 40, 26, 69, 18, 81, 27, 107, 18, 6, 35, 24, + 44, 44, 35, 66, 44, 82, 35, 108, 44, 9, 61, 20, 53, 51, 61, + 62, 53, 93, 61, 104, 53, 17, 1, 26, 9, 55, 1, 64, 9, 93, + 1, 102, 9, 1, 26, 30, 18, 40, 27, 68, 18, 82, 27, 106, 18, + 5, 35, 25, 44, 43, 35, 67, 44, 81, 35, 109, 44, 10, 61, 21, + 53, 52, 61, 63, 53, 94, 61, 105, 53, 16, 1, 25, 9, 54, 1, + 63, 9, 92, 1, 101, 9, 0, 26, 29, 18, 41, 27, 67, 18, 83, + 27, 105, 18, 4, 35, 26, 44, 42, 35, 68, 44, 80, 35, 110, 44, + 11, 61, 22, 53, 53, 61, 64, 53, 95, 61, 106, 53, 15, 1, 24, + 9, 53, 1, 62, 9, 91, 1, 100, 9, 0, 27, 28, 18, 42, 27, + 66, 18, 84, 27, 104, 18, 3, 35, 27, 44, 41, 35, 69, 44, 80, + 36, 111, 44, 12, 61, 23, 53, 54, 61, 65, 53, 96, 61, 107, 53, + 14, 1, 23, 9, 52, 1, 61, 9, 90, 1, 100, 10, 1, 27, 27, + 18, 43, 27, 65, 18, 85, 27, 103, 18, 2, 35, 28, 44, 40, 35, + 70, 44, 81, 36, 112, 44, 13, 61, 24, 53, 55, 61, 66, 53, 97, + 61, 108, 53, 13, 1, 22, 9, 51, 1, 60, 9, 89, 1, 101, 10, + 2, 27, 26, 18, 44, 27, 64, 18, 86, 27, 102, 18, 1, 35, 29, + 44, 40, 36, 71, 44, 82, 36, 113, 44, 14, 61, 25, 53, 56, 61, + 67, 53, 98, 61, 109, 53, 12, 1, 21, 9, 50, 1, 60, 10, 88, + 1, 102, 10, 3, 27, 25, 18, 45, 27, 63, 18, 87, 27, 101, 18, + 0, 35, 30, 44, 41, 36, 72, 44, 83, 36, 114, 44, 15, 61, 26, + 53, 57, 61, 68, 53, 99, 61, 110, 53, 11, 1, 20, 9, 49, 1, + 61, 10, 87, 1, 103, 10, 4, 27, 24, 18, 46, 27, 62, 18, 88, + 27, 100, 18, 0, 36, 31, 44, 42, 36, 73, 44, 84, 36, 115, 44, + 16, 61, 27, 53, 58, 61, 69, 53, 99, 62, 111, 53, 10, 1, 20, + 10, 48, 1, 62, 10, 86, 1, 104, 10, 5, 27, 23, 18, 47, 27, + 61, 18, 89, 27, 100, 19, 1, 36, 32, 44, 43, 36, 74, 44, 85, + 36, 116, 44, 17, 61, 28, 53, 59, 61, 70, 53, 98, 62, 112, 53, + 9, 1, 21, 10, 47, 1, 63, 10, 85, 1, 105, 10, 6, 27, 22, + 18, 48, 27, 60, 18, 90, 27, 101, 19, 2, 36, 33, 44, 44, 36, + 75, 44, 86, 36, 117, 44, 18, 61, 29, 53, 59, 62, 71, 53, 97, + 62, 113, 53, 8, 1, 22, 10, 46, 1, 64, 10, 84, 1, 106, 10, + 7, 27, 21, 18, 49, 27, 60, 19, 91, 27, 102, 19, 3, 36, 34, + 44, 45, 36, 76, 44, 87, 36, 118, 44, 19, 61, 30, 53, 58, 62, + 72, 53, 96, 62, 114, 53, 7, 1, 23, 10, 45, 1, 65, 10, 83, + 1, 107, 10, 8, 27, 20, 18, 50, 27, 61, 19, 92, 27, 103, 19, + 4, 36, 35, 44, 46, 36, 77, 44, 88, 36, 119, 44, 19, 62, 31, + 53, 57, 62, 73, 53, 95, 62, 115, 53, 6, 1, 24, 10, 44, 1, + 66, 10, 82, 1, 108, 10, 9, 27, 20, 19, 51, 27, 62, 19, 93, + 27, 104, 19, 5, 36, 36, 44, 47, 36, 78, 44, 89, 36, 119, 45, + 18, 62, 32, 53, 56, 62, 74, 53, 94, 62, 116, 53, 5, 1, 25, + 10, 43, 1, 67, 10, 81, 1, 109, 10, 10, 27, 21, 19, 52, 27, + 63, 19, 94, 27, 105, 19, 6, 36, 37, 44, 48, 36, 79, 44, 90, + 36, 118, 45, 17, 62, 33, 53, 55, 62, 75, 53, 93, 62, 117, 53, + 4, 1, 26, 10, 42, 1, 68, 10, 80, 1, 110, 10, 11, 27, 22, + 19, 53, 27, 64, 19, 95, 27, 106, 19, 7, 36, 38, 44, 49, 36, + 79, 45, 91, 36, 117, 45, 16, 62, 34, 53, 54, 62, 76, 53, 92, + 62, 118, 53, 3, 1, 27, 10, 41, 1, 69, 10, 80, 2, 111, 10, + 12, 27, 23, 19, 54, 27, 65, 19, 96, 27, 107, 19, 8, 36, 39, + 44, 50, 36, 78, 45, 92, 36, 116, 45, 15, 62, 35, 53, 53, 62, + 77, 53, 91, 62, 119, 53, 2, 1, 28, 10, 40, 1, 70, 10, 81, + 2, 112, 10, 13, 27, 24, 19, 55, 27, 66, 19, 97, 27, 108, 19, + 9, 36, 39, 45, 51, 36, 77, 45, 93, 36, 115, 45, 14, 62, 36, + 53, 52, 62, 78, 53, 90, 62, 119, 54, 1, 1, 29, 10, 40, 2, + 71, 10, 82, 2, 113, 10, 14, 27, 25, 19, 56, 27, 67, 19, 98, + 27, 109, 19, 10, 36, 38, 45, 52, 36, 76, 45, 94, 36, 114, 45, + 13, 62, 37, 53, 51, 62, 79, 53, 89, 62, 118, 54, 0, 1, 30, + 10, 41, 2, 72, 10, 83, 2, 114, 10, 15, 27, 26, 19, 57, 27, + 68, 19, 99, 27, 110, 19, 11, 36, 37, 45, 53, 36, 75, 45, 95, + 36, 113, 45, 12, 62, 38, 53, 50, 62, 79, 54, 88, 62, 117, 54, + 0, 2, 31, 10, 42, 2, 73, 10, 84, 2, 115, 10, 16, 27, 27, + 19, 58, 27, 69, 19, 99, 28, 111, 19, 12, 36, 36, 45, 54, 36, + 74, 45, 96, 36, 112, 45, 11, 62, 39, 53, 49, 62, 78, 54, 87, + 62, 116, 54, 1, 2, 32, 10, 43, 2, 74, 10, 85, 2, 116, 10, + 17, 27, 28, 19, 59, 27, 70, 19, 98, 28, 112, 19, 13, 36, 35, + 45, 55, 36, 73, 45, 97, 36, 111, 45, 10, 62, 39, 54, 48, 62, + 77, 54, 86, 62, 115, 54, 2, 2, 33, 10, 44, 2, 75, 10, 86, + 2, 117, 10, 18, 27, 29, 19, 59, 28, 71, 19, 97, 28, 113, 19, + 14, 36, 34, 45, 56, 36, 72, 45, 98, 36, 110, 45, 9, 62, 38, + 54, 47, 62, 76, 54, 85, 62, 114, 54, 3, 2, 34, 10, 45, 2, + 76, 10, 87, 2, 118, 10, 19, 27, 30, 19, 58, 28, 72, 19, 96, + 28, 114, 19, 15, 36, 33, 45, 57, 36, 71, 45, 99, 36, 109, 45, + 8, 62, 37, 54, 46, 62, 75, 54, 84, 62, 113, 54, 4, 2, 35, + 10, 46, 2, 77, 10, 88, 2, 119, 10, 19, 28, 31, 19, 57, 28, + 73, 19, 95, 28, 115, 19, 16, 36, 32, 45, 58, 36, 70, 45, 99, + 37, 108, 45, 7, 62, 36, 54, 45, 62, 74, 54, 83, 62, 112, 54, + 5, 2, 36, 10, 47, 2, 78, 10, 89, 2, 119, 11, 18, 28, 32, + 19, 56, 28, 74, 19, 94, 28, 116, 19, 17, 36, 31, 45, 59, 36, + 69, 45, 98, 37, 107, 45, 6, 62, 35, 54, 44, 62, 73, 54, 82, + 62, 111, 54, 6, 2, 37, 10, 48, 2, 79, 10, 90, 2, 118, 11, + 17, 28, 33, 19, 55, 28, 75, 19, 93, 28, 117, 19, 18, 36, 30, + 45, 59, 37, 68, 45, 97, 37, 106, 45, 5, 62, 34, 54, 43, 62, + 72, 54, 81, 62, 110, 54, 7, 2, 38, 10, 49, 2, 79, 11, 91, + 2, 117, 11, 16, 28, 34, 19, 54, 28, 76, 19, 92, 28, 118, 19, + 19, 36, 29, 45, 58, 37, 67, 45, 96, 37, 105, 45, 4, 62, 33, + 54, 42, 62, 71, 54, 80, 62, 109, 54, 8, 2, 39, 10, 50, 2, + 78, 11, 92, 2, 116, 11, 15, 28, 35, 19, 53, 28, 77, 19, 91, + 28, 119, 19, 19, 37, 28, 45, 57, 37, 66, 45, 95, 37, 104, 45, + 3, 62, 32, 54, 41, 62, 70, 54, 80, 63, 108, 54, 9, 2, 39, + 11, 51, 2, 77, 11, 93, 2, 115, 11, 14, 28, 36, 19, 52, 28, + 78, 19, 90, 28, 119, 20, 18, 37, 27, 45, 56, 37, 65, 45, 94, + 37, 103, 45, 2, 62, 31, 54, 40, 62, 69, 54, 81, 63, 107, 54, + 10, 2, 38, 11, 52, 2, 76, 11, 94, 2, 114, 11, 13, 28, 37, + 19, 51, 28, 79, 19, 89, 28, 118, 20, 17, 37, 26, 45, 55, 37, + 64, 45, 93, 37, 102, 45, 1, 62, 30, 54, 40, 63, 68, 54, 82, + 63, 106, 54, 11, 2, 37, 11, 53, 2, 75, 11, 95, 2, 113, 11, + 12, 28, 38, 19, 50, 28, 79, 20, 88, 28, 117, 20, 16, 37, 25, + 45, 54, 37, 63, 45, 92, 37, 101, 45, 0, 62, 29, 54, 41, 63, + 67, 54, 83, 63, 105, 54, 12, 2, 36, 11, 54, 2, 74, 11, 96, + 2, 112, 11, 11, 28, 39, 19, 49, 28, 78, 20, 87, 28, 116, 20, + 15, 37, 24, 45, 53, 37, 62, 45, 91, 37, 100, 45, 0, 63, 28, + 54, 42, 63, 66, 54, 84, 63, 104, 54, 13, 2, 35, 11, 55, 2, + 73, 11, 97, 2, 111, 11, 10, 28, 39, 20, 48, 28, 77, 20, 86, + 28, 115, 20, 14, 37, 23, 45, 52, 37, 61, 45, 90, 37, 100, 46, + 1, 63, 27, 54, 43, 63, 65, 54, 85, 63, 103, 54, 14, 2, 34, + 11, 56, 2, 72, 11, 98, 2, 110, 11, 9, 28, 38, 20, 47, 28, + 76, 20, 85, 28, 114, 20, 13, 37, 22, 45, 51, 37, 60, 45, 89, + 37, 101, 46, 2, 63, 26, 54, 44, 63, 64, 54, 86, 63, 102, 54, + 15, 2, 33, 11, 57, 2, 71, 11, 99, 2, 109, 11, 8, 28, 37, + 20, 46, 28, 75, 20, 84, 28, 113, 20, 12, 37, 21, 45, 50, 37, + 60, 46, 88, 37, 102, 46, 3, 63, 25, 54, 45, 63, 63, 54, 87, + 63, 101, 54, 16, 2, 32, 11, 58, 2, 70, 11, 99, 3, 108, 11, + 7, 28, 36, 20, 45, 28, 74, 20, 83, 28, 112, 20, 11, 37, 20, + 45, 49, 37, 61, 46, 87, 37, 103, 46, 4, 63, 24, 54, 46, 63, + 62, 54, 88, 63, 100, 54, 17, 2, 31, 11, 59, 2, 69, 11, 98, + 3, 107, 11, 6, 28, 35, 20, 44, 28, 73, 20, 82, 28, 111, 20, + 10, 37, 20, 46, 48, 37, 62, 46, 86, 37, 104, 46, 5, 63, 23, + 54, 47, 63, 61, 54, 89, 63, 100, 55, 18, 2, 30, 11, 59, 3, + 68, 11, 97, 3, 106, 11, 5, 28, 34, 20, 43, 28, 72, 20, 81, + 28, 110, 20, 9, 37, 21, 46, 47, 37, 63, 46, 85, 37, 105, 46, + 6, 63, 22, 54, 48, 63, 60, 54, 90, 63, 101, 55, 19, 2, 29, + 11, 58, 3, 67, 11, 96, 3, 105, 11, 4, 28, 33, 20, 42, 28, + 71, 20, 80, 28, 109, 20, 8, 37, 22, 46, 46, 37, 64, 46, 84, + 37, 106, 46, 7, 63, 21, 54, 49, 63, 60, 55, 91, 63, 102, 55, + 19, 3, 28, 11, 57, 3, 66, 11, 95, 3, 104, 11, 3, 28, 32, + 20, 41, 28, 70, 20, 80, 29, 108, 20, 7, 37, 23, 46, 45, 37, + 65, 46, 83, 37, 107, 46, 8, 63, 20, 54, 50, 63, 61, 55, 92, + 63, 103, 55, 18, 3, 27, 11, 56, 3, 65, 11, 94, 3, 103, 11, + 2, 28, 31, 20, 40, 28, 69, 20, 81, 29, 107, 20, 6, 37, 24, + 46, 44, 37, 66, 46, 82, 37, 108, 46, 9, 63, 20, 55, 51, 63, + 62, 55, 93, 63, 104, 55, 17, 3, 26, 11, 55, 3, 64, 11, 93, + 3, 102, 11, 1, 28, 30, 20, 40, 29, 68, 20, 82, 29, 106, 20, + 5, 37, 25, 46, 43, 37, 67, 46, 81, 37, 109, 46, 10, 63, 21, + 55, 52, 63, 63, 55, 94, 63, 105, 55, 16, 3, 25, 11, 54, 3, + 63, 11, 92, 3, 101, 11, 0, 28, 29, 20, 41, 29, 67, 20, 83, + 29, 105, 20, 4, 37, 26, 46, 42, 37, 68, 46, 80, 37, 110, 46, + 11, 63, 22, 55, 53, 63, 64, 55, 95, 63, 106, 55, 15, 3, 24, + 11, 53, 3, 62, 11, 91, 3, 100, 11, 0, 29, 28, 20, 42, 29, + 66, 20, 84, 29, 104, 20, 3, 37, 27, 46, 41, 37, 69, 46, 80, + 38, 111, 46, 12, 63, 23, 55, 54, 63, 65, 55, 96, 63, 107, 55, + 14, 3, 23, 11, 52, 3, 61, 11, 90, 3, 100, 12, 1, 29, 27, + 20, 43, 29, 65, 20, 85, 29, 103, 20, 2, 37, 28, 46, 40, 37, + 70, 46, 81, 38, 112, 46, 13, 63, 24, 55, 55, 63, 66, 55, 97, + 63, 108, 55, 13, 3, 22, 11, 51, 3, 60, 11, 89, 3, 101, 12, + 2, 29, 26, 20, 44, 29, 64, 20, 86, 29, 102, 20, 1, 37, 29, + 46, 40, 38, 71, 46, 82, 38, 113, 46, 14, 63, 25, 55, 56, 63, + 67, 55, 98, 63, 109, 55, 12, 3, 21, 11, 50, 3, 60, 12, 88, + 3, 102, 12, 3, 29, 25, 20, 45, 29, 63, 20, 87, 29, 101, 20, + 0, 37, 30, 46, 41, 38, 72, 46, 83, 38, 114, 46, 15, 63, 26, + 55, 57, 63, 68, 55, 99, 63, 110, 55, 11, 3, 20, 11, 49, 3, + 61, 12, 87, 3, 103, 12, 4, 29, 24, 20, 46, 29, 62, 20, 88, + 29, 100, 20, 0, 38, 31, 46, 42, 38, 73, 46, 84, 38, 115, 46, + 16, 63, 27, 55, 58, 63, 69, 55, 99, 64, 111, 55, 10, 3, 20, + 12, 48, 3, 62, 12, 86, 3, 104, 12, 5, 29, 23, 20, 47, 29, + 61, 20, 89, 29, 100, 21, 1, 38, 32, 46, 43, 38, 74, 46, 85, + 38, 116, 46, 17, 63, 28, 55, 59, 63, 70, 55, 98, 64, 112, 55, + 9, 3, 21, 12, 47, 3, 63, 12, 85, 3, 105, 12, 6, 29, 22, + 20, 48, 29, 60, 20, 90, 29, 101, 21, 2, 38, 33, 46, 44, 38, + 75, 46, 86, 38, 117, 46, 18, 63, 29, 55, 59, 64, 71, 55, 97, + 64, 113, 55, 8, 3, 22, 12, 46, 3, 64, 12, 84, 3, 106, 12, + 7, 29, 21, 20, 49, 29, 60, 21, 91, 29, 102, 21, 3, 38, 34, + 46, 45, 38, 76, 46, 87, 38, 118, 46, 19, 63, 30, 55, 58, 64, + 72, 55, 96, 64, 114, 55, 7, 3, 23, 12, 45, 3, 65, 12, 83, + 3, 107, 12, 8, 29, 20, 20, 50, 29, 61, 21, 92, 29, 103, 21, + 4, 38, 35, 46, 46, 38, 77, 46, 88, 38, 119, 46, 19, 64, 31, + 55, 57, 64, 73, 55, 95, 64, 115, 55, 6, 3, 24, 12, 44, 3, + 66, 12, 82, 3, 108, 12, 9, 29, 20, 21, 51, 29, 62, 21, 93, + 29, 104, 21, 5, 38, 36, 46, 47, 38, 78, 46, 89, 38, 119, 47, + 18, 64, 32, 55, 56, 64, 74, 55, 94, 64, 116, 55, 5, 3, 25, + 12, 43, 3, 67, 12, 81, 3, 109, 12, 10, 29, 21, 21, 52, 29, + 63, 21, 94, 29, 105, 21, 6, 38, 37, 46, 48, 38, 79, 46, 90, + 38, 118, 47, 17, 64, 33, 55, 55, 64, 75, 55, 93, 64, 117, 55, + 4, 3, 26, 12, 42, 3, 68, 12, 80, 3, 110, 12, 11, 29, 22, + 21, 53, 29, 64, 21, 95, 29, 106, 21, 7, 38, 38, 46, 49, 38, + 79, 47, 91, 38, 117, 47, 16, 64, 34, 55, 54, 64, 76, 55, 92, + 64, 118, 55, 3, 3, 27, 12, 41, 3, 69, 12, 80, 4, 111, 12, + 12, 29, 23, 21, 54, 29, 65, 21, 96, 29, 107, 21, 8, 38, 39, + 46, 50, 38, 78, 47, 92, 38, 116, 47, 15, 64, 35, 55, 53, 64, + 77, 55, 91, 64, 119, 55, 2, 3, 28, 12, 40, 3, 70, 12, 81, + 4, 112, 12, 13, 29, 24, 21, 55, 29, 66, 21, 97, 29, 108, 21, + 9, 38, 39, 47, 51, 38, 77, 47, 93, 38, 115, 47, 14, 64, 36, + 55, 52, 64, 78, 55, 90, 64, 119, 56, 1, 3, 29, 12, 40, 4, + 71, 12, 82, 4, 113, 12, 14, 29, 25, 21, 56, 29, 67, 21, 98, + 29, 109, 21, 10, 38, 38, 47, 52, 38, 76, 47, 94, 38, 114, 47, + 13, 64, 37, 55, 51, 64, 79, 55, 89, 64, 118, 56, 0, 3, 30, + 12, 41, 4, 72, 12, 83, 4, 114, 12, 15, 29, 26, 21, 57, 29, + 68, 21, 99, 29, 110, 21, 11, 38, 37, 47, 53, 38, 75, 47, 95, + 38, 113, 47, 12, 64, 38, 55, 50, 64, 79, 56, 88, 64, 117, 56, + 0, 4, 31, 12, 42, 4, 73, 12, 84, 4, 115, 12, 16, 29, 27, + 21, 58, 29, 69, 21, 99, 30, 111, 21, 12, 38, 36, 47, 54, 38, + 74, 47, 96, 38, 112, 47, 11, 64, 39, 55, 49, 64, 78, 56, 87, + 64, 116, 56, 1, 4, 32, 12, 43, 4, 74, 12, 85, 4, 116, 12, + 17, 29, 28, 21, 59, 29, 70, 21, 98, 30, 112, 21, 13, 38, 35, + 47, 55, 38, 73, 47, 97, 38, 111, 47, 10, 64, 39, 56, 48, 64, + 77, 56, 86, 64, 115, 56, 2, 4, 33, 12, 44, 4, 75, 12, 86, + 4, 117, 12, 18, 29, 29, 21, 59, 30, 71, 21, 97, 30, 113, 21, + 14, 38, 34, 47, 56, 38, 72, 47, 98, 38, 110, 47, 9, 64, 38, + 56, 47, 64, 76, 56, 85, 64, 114, 56, 3, 4, 34, 12, 45, 4, + 76, 12, 87, 4, 118, 12, 19, 29, 30, 21, 58, 30, 72, 21, 96, + 30, 114, 21, 15, 38, 33, 47, 57, 38, 71, 47, 99, 38, 109, 47, + 8, 64, 37, 56, 46, 64, 75, 56, 84, 64, 113, 56, 4, 4, 35, + 12, 46, 4, 77, 12, 88, 4, 119, 12, 19, 30, 31, 21, 57, 30, + 73, 21, 95, 30, 115, 21, 16, 38, 32, 47, 58, 38, 70, 47, 99, + 39, 108, 47, 7, 64, 36, 56, 45, 64, 74, 56, 83, 64, 112, 56, + 5, 4, 36, 12, 47, 4, 78, 12, 89, 4, 119, 13, 18, 30, 32, + 21, 56, 30, 74, 21, 94, 30, 116, 21, 17, 38, 31, 47, 59, 38, + 69, 47, 98, 39, 107, 47, 6, 64, 35, 56, 44, 64, 73, 56, 82, + 64, 111, 56, 6, 4, 37, 12, 48, 4, 79, 12, 90, 4, 118, 13, + 17, 30, 33, 21, 55, 30, 75, 21, 93, 30, 117, 21, 18, 38, 30, + 47, 59, 39, 68, 47, 97, 39, 106, 47, 5, 64, 34, 56, 43, 64, + 72, 56, 81, 64, 110, 56, 7, 4, 38, 12, 49, 4, 79, 13, 91, + 4, 117, 13, 16, 30, 34, 21, 54, 30, 76, 21, 92, 30, 118, 21, + 19, 38, 29, 47, 58, 39, 67, 47, 96, 39, 105, 47, 4, 64, 33, + 56, 42, 64, 71, 56, 80, 64, 109, 56, 8, 4, 39, 12, 50, 4, + 78, 13, 92, 4, 116, 13, 15, 30, 35, 21, 53, 30, 77, 21, 91, + 30, 119, 21, 19, 39, 28, 47, 57, 39, 66, 47, 95, 39, 104, 47, + 3, 64, 32, 56, 41, 64, 70, 56, 80, 65, 108, 56, 9, 4, 39, + 13, 51, 4, 77, 13, 93, 4, 115, 13, 14, 30, 36, 21, 52, 30, + 78, 21, 90, 30, 119, 22, 18, 39, 27, 47, 56, 39, 65, 47, 94, + 39, 103, 47, 2, 64, 31, 56, 40, 64, 69, 56, 81, 65, 107, 56, + 10, 4, 38, 13, 52, 4, 76, 13, 94, 4, 114, 13, 13, 30, 37, + 21, 51, 30, 79, 21, 89, 30, 118, 22, 17, 39, 26, 47, 55, 39, + 64, 47, 93, 39, 102, 47, 1, 64, 30, 56, 40, 65, 68, 56, 82, + 65, 106, 56, 11, 4, 37, 13, 53, 4, 75, 13, 95, 4, 113, 13, + 12, 30, 38, 21, 50, 30, 79, 22, 88, 30, 117, 22, 16, 39, 25, + 47, 54, 39, 63, 47, 92, 39, 101, 47, 0, 64, 29, 56, 41, 65, + 67, 56, 83, 65, 105, 56, 12, 4, 36, 13, 54, 4, 74, 13, 96, + 4, 112, 13, 11, 30, 39, 21, 49, 30, 78, 22, 87, 30, 116, 22, + 15, 39, 24, 47, 53, 39, 62, 47, 91, 39, 100, 47, 0, 65, 28, + 56, 42, 65, 66, 56, 84, 65, 104, 56, 13, 4, 35, 13, 55, 4, + 73, 13, 97, 4, 111, 13, 10, 30, 39, 22, 48, 30, 77, 22, 86, + 30, 115, 22, 14, 39, 23, 47, 52, 39, 61, 47, 90, 39, 100, 48, + 1, 65, 27, 56, 43, 65, 65, 56, 85, 65, 103, 56, 14, 4, 34, + 13, 56, 4, 72, 13, 98, 4, 110, 13, 9, 30, 38, 22, 47, 30, + 76, 22, 85, 30, 114, 22, 13, 39, 22, 47, 51, 39, 60, 47, 89, + 39, 101, 48, 2, 65, 26, 56, 44, 65, 64, 56, 86, 65, 102, 56, + 15, 4, 33, 13, 57, 4, 71, 13, 99, 4, 109, 13, 8, 30, 37, + 22, 46, 30, 75, 22, 84, 30, 113, 22, 12, 39, 21, 47, 50, 39, + 60, 48, 88, 39, 102, 48, 3, 65, 25, 56, 45, 65, 63, 56, 87, + 65, 101, 56, 16, 4, 32, 13, 58, 4, 70, 13, 99, 5, 108, 13, + 7, 30, 36, 22, 45, 30, 74, 22, 83, 30, 112, 22, 11, 39, 20, + 47, 49, 39, 61, 48, 87, 39, 103, 48, 4, 65, 24, 56, 46, 65, + 62, 56, 88, 65, 100, 56, 17, 4, 31, 13, 59, 4, 69, 13, 98, + 5, 107, 13, 6, 30, 35, 22, 44, 30, 73, 22, 82, 30, 111, 22, + 10, 39, 20, 48, 48, 39, 62, 48, 86, 39, 104, 48, 5, 65, 23, + 56, 47, 65, 61, 56, 89, 65, 100, 57, 18, 4, 30, 13, 59, 5, + 68, 13, 97, 5, 106, 13, 5, 30, 34, 22, 43, 30, 72, 22, 81, + 30, 110, 22, 9, 39, 21, 48, 47, 39, 63, 48, 85, 39, 105, 48, + 6, 65, 22, 56, 48, 65, 60, 56, 90, 65, 101, 57, 19, 4, 29, + 13, 58, 5, 67, 13, 96, 5, 105, 13, 4, 30, 33, 22, 42, 30, + 71, 22, 80, 30, 109, 22, 8, 39, 22, 48, 46, 39, 64, 48, 84, + 39, 106, 48, 7, 65, 21, 56, 49, 65, 60, 57, 91, 65, 102, 57, + 19, 5, 28, 13, 57, 5, 66, 13, 95, 5, 104, 13, 3, 30, 32, + 22, 41, 30, 70, 22, 80, 31, 108, 22, 7, 39, 23, 48, 45, 39, + 65, 48, 83, 39, 107, 48, 8, 65, 20, 56, 50, 65, 61, 57, 92, + 65, 103, 57, 18, 5, 27, 13, 56, 5, 65, 13, 94, 5, 103, 13, + 2, 30, 31, 22, 40, 30, 69, 22, 81, 31, 107, 22, 6, 39, 24, + 48, 44, 39, 66, 48, 82, 39, 108, 48, 9, 65, 20, 57, 51, 65, + 62, 57, 93, 65, 104, 57, 17, 5, 26, 13, 55, 5, 64, 13, 93, + 5, 102, 13, 1, 30, 30, 22, 40, 31, 68, 22, 82, 31, 106, 22, + 5, 39, 25, 48, 43, 39, 67, 48, 81, 39, 109, 48, 10, 65, 21, + 57, 52, 65, 63, 57, 94, 65, 105, 57, 16, 5, 25, 13, 54, 5, + 63, 13, 92, 5, 101, 13, 0, 30, 29, 22, 41, 31, 67, 22, 83, + 31, 105, 22, 4, 39, 26, 48, 42, 39, 68, 48, 80, 39, 110, 48, + 11, 65, 22, 57, 53, 65, 64, 57, 95, 65, 106, 57, 15, 5, 24, + 13, 53, 5, 62, 13, 91, 5, 100, 13, 0, 31, 28, 22, 42, 31, + 66, 22, 84, 31, 104, 22, 3, 39, 27, 48, 41, 39, 69, 48, 80, + 40, 111, 48, 12, 65, 23, 57, 54, 65, 65, 57, 96, 65, 107, 57, + 14, 5, 23, 13, 52, 5, 61, 13, 90, 5, 100, 14, 1, 31, 27, + 22, 43, 31, 65, 22, 85, 31, 103, 22, 2, 39, 28, 48, 40, 39, + 70, 48, 81, 40, 112, 48, 13, 65, 24, 57, 55, 65, 66, 57, 97, + 65, 108, 57, 13, 5, 22, 13, 51, 5, 60, 13, 89, 5, 101, 14, + 2, 31, 26, 22, 44, 31, 64, 22, 86, 31, 102, 22, 1, 39, 29, + 48, 40, 40, 71, 48, 82, 40, 113, 48, 14, 65, 25, 57, 56, 65, + 67, 57, 98, 65, 109, 57, 12, 5, 21, 13, 50, 5, 60, 14, 88, + 5, 102, 14, 3, 31, 25, 22, 45, 31, 63, 22, 87, 31, 101, 22, + 0, 39, 30, 48, 41, 40, 72, 48, 83, 40, 114, 48, 15, 65, 26, + 57, 57, 65, 68, 57, 99, 65, 110, 57, 11, 5, 20, 13, 49, 5, + 61, 14, 87, 5, 103, 14, 4, 31, 24, 22, 46, 31, 62, 22, 88, + 31, 100, 22, 0, 40, 31, 48, 42, 40, 73, 48, 84, 40, 115, 48, + 16, 65, 27, 57, 58, 65, 69, 57, 99, 66, 111, 57, 10, 5, 20, + 14, 48, 5, 62, 14, 86, 5, 104, 14, 5, 31, 23, 22, 47, 31, + 61, 22, 89, 31, 100, 23, 1, 40, 32, 48, 43, 40, 74, 48, 85, + 40, 116, 48, 17, 65, 28, 57, 59, 65, 70, 57, 98, 66, 112, 57, + 9, 5, 21, 14, 47, 5, 63, 14, 85, 5, 105, 14, 6, 31, 22, + 22, 48, 31, 60, 22, 90, 31, 101, 23, 2, 40, 33, 48, 44, 40, + 75, 48, 86, 40, 117, 48, 18, 65, 29, 57, 59, 66, 71, 57, 97, + 66, 113, 57, 8, 5, 22, 14, 46, 5, 64, 14, 84, 5, 106, 14, + 7, 31, 21, 22, 49, 31, 60, 23, 91, 31, 102, 23, 3, 40, 34, + 48, 45, 40, 76, 48, 87, 40, 118, 48, 19, 65, 30, 57, 58, 66, + 72, 57, 96, 66, 114, 57, 7, 5, 23, 14, 45, 5, 65, 14, 83, + 5, 107, 14, 8, 31, 20, 22, 50, 31, 61, 23, 92, 31, 103, 23, + 4, 40, 35, 48, 46, 40, 77, 48, 88, 40, 119, 48, 19, 66, 31, + 57, 57, 66, 73, 57, 95, 66, 115, 57, 6, 5, 24, 14, 44, 5, + 66, 14, 82, 5, 108, 14, 9, 31, 20, 23, 51, 31, 62, 23, 93, + 31, 104, 23, 5, 40, 36, 48, 47, 40, 78, 48, 89, 40, 119, 49, + 18, 66, 32, 57, 56, 66, 74, 57, 94, 66, 116, 57, 5, 5, 25, + 14, 43, 5, 67, 14, 81, 5, 109, 14, 10, 31, 21, 23, 52, 31, + 63, 23, 94, 31, 105, 23, 6, 40, 37, 48, 48, 40, 79, 48, 90, + 40, 118, 49, 17, 66, 33, 57, 55, 66, 75, 57, 93, 66, 117, 57, + 4, 5, 26, 14, 42, 5, 68, 14, 80, 5, 110, 14, 11, 31, 22, + 23, 53, 31, 64, 23, 95, 31, 106, 23, 7, 40, 38, 48, 49, 40, + 79, 49, 91, 40, 117, 49, 16, 66, 34, 57, 54, 66, 76, 57, 92, + 66, 118, 57, 3, 5, 27, 14, 41, 5, 69, 14, 80, 6, 111, 14, + 12, 31, 23, 23, 54, 31, 65, 23, 96, 31, 107, 23, 8, 40, 39, + 48, 50, 40, 78, 49, 92, 40, 116, 49, 15, 66, 35, 57, 53, 66, + 77, 57, 91, 66, 119, 57, 2, 5, 28, 14, 40, 5, 70, 14, 81, + 6, 112, 14, 13, 31, 24, 23, 55, 31, 66, 23, 97, 31, 108, 23, + 9, 40, 39, 49, 51, 40, 77, 49, 93, 40, 115, 49, 14, 66, 36, + 57, 52, 66, 78, 57, 90, 66, 119, 58, 1, 5, 29, 14, 40, 6, + 71, 14, 82, 6, 113, 14, 14, 31, 25, 23, 56, 31, 67, 23, 98, + 31, 109, 23, 10, 40, 38, 49, 52, 40, 76, 49, 94, 40, 114, 49, + 13, 66, 37, 57, 51, 66, 79, 57, 89, 66, 118, 58, 0, 5, 30, + 14, 41, 6, 72, 14, 83, 6, 114, 14, 15, 31, 26, 23, 57, 31, + 68, 23, 99, 31, 110, 23, 11, 40, 37, 49, 53, 40, 75, 49, 95, + 40, 113, 49, 12, 66, 38, 57, 50, 66, 79, 58, 88, 66, 117, 58, + 0, 6, 31, 14, 42, 6, 73, 14, 84, 6, 115, 14, 16, 31, 27, + 23, 58, 31, 69, 23, 99, 32, 111, 23, 12, 40, 36, 49, 54, 40, + 74, 49, 96, 40, 112, 49, 11, 66, 39, 57, 49, 66, 78, 58, 87, + 66, 116, 58, 1, 6, 32, 14, 43, 6, 74, 14, 85, 6, 116, 14, + 17, 31, 28, 23, 59, 31, 70, 23, 98, 32, 112, 23, 13, 40, 35, + 49, 55, 40, 73, 49, 97, 40, 111, 49, 10, 66, 39, 58, 48, 66, + 77, 58, 86, 66, 115, 58, 2, 6, 33, 14, 44, 6, 75, 14, 86, + 6, 117, 14, 18, 31, 29, 23, 59, 32, 71, 23, 97, 32, 113, 23, + 14, 40, 34, 49, 56, 40, 72, 49, 98, 40, 110, 49, 9, 66, 38, + 58, 47, 66, 76, 58, 85, 66, 114, 58, 3, 6, 34, 14, 45, 6, + 76, 14, 87, 6, 118, 14, 19, 31, 30, 23, 58, 32, 72, 23, 96, + 32, 114, 23, 15, 40, 33, 49, 57, 40, 71, 49, 99, 40, 109, 49, + 8, 66, 37, 58, 46, 66, 75, 58, 84, 66, 113, 58, 4, 6, 35, + 14, 46, 6, 77, 14, 88, 6, 119, 14, 19, 32, 31, 23, 57, 32, + 73, 23, 95, 32, 115, 23, 16, 40, 32, 49, 58, 40, 70, 49, 99, + 41, 108, 49, 7, 66, 36, 58, 45, 66, 74, 58, 83, 66, 112, 58, + 5, 6, 36, 14, 47, 6, 78, 14, 89, 6, 119, 15, 18, 32, 32, + 23, 56, 32, 74, 23, 94, 32, 116, 23, 17, 40, 31, 49, 59, 40, + 69, 49, 98, 41, 107, 49, 6, 66, 35, 58, 44, 66, 73, 58, 82, + 66, 111, 58, 6, 6, 37, 14, 48, 6, 79, 14, 90, 6, 118, 15, + 17, 32, 33, 23, 55, 32, 75, 23, 93, 32, 117, 23, 18, 40, 30, + 49, 59, 41, 68, 49, 97, 41, 106, 49, 5, 66, 34, 58, 43, 66, + 72, 58, 81, 66, 110, 58, 7, 6, 38, 14, 49, 6, 79, 15, 91, + 6, 117, 15, 16, 32, 34, 23, 54, 32, 76, 23, 92, 32, 118, 23, + 19, 40, 29, 49, 58, 41, 67, 49, 96, 41, 105, 49, 4, 66, 33, + 58, 42, 66, 71, 58, 80, 66, 109, 58, 8, 6, 39, 14, 50, 6, + 78, 15, 92, 6, 116, 15, 15, 32, 35, 23, 53, 32, 77, 23, 91, + 32, 119, 23, 19, 41, 28, 49, 57, 41, 66, 49, 95, 41, 104, 49, + 3, 66, 32, 58, 41, 66, 70, 58, 80, 67, 108, 58, 9, 6, 39, + 15, 51, 6, 77, 15, 93, 6, 115, 15, 14, 32, 36, 23, 52, 32, + 78, 23, 90, 32, 119, 24, 18, 41, 27, 49, 56, 41, 65, 49, 94, + 41, 103, 49, 2, 66, 31, 58, 40, 66, 69, 58, 81, 67, 107, 58, + 10, 6, 38, 15, 52, 6, 76, 15, 94, 6, 114, 15, 13, 32, 37, + 23, 51, 32, 79, 23, 89, 32, 118, 24, 17, 41, 26, 49, 55, 41, + 64, 49, 93, 41, 102, 49, 1, 66, 30, 58, 40, 67, 68, 58, 82, + 67, 106, 58, 11, 6, 37, 15, 53, 6, 75, 15, 95, 6, 113, 15, + 12, 32, 38, 23, 50, 32, 79, 24, 88, 32, 117, 24, 16, 41, 25, + 49, 54, 41, 63, 49, 92, 41, 101, 49, 0, 66, 29, 58, 41, 67, + 67, 58, 83, 67, 105, 58, 12, 6, 36, 15, 54, 6, 74, 15, 96, + 6, 112, 15, 11, 32, 39, 23, 49, 32, 78, 24, 87, 32, 116, 24, + 15, 41, 24, 49, 53, 41, 62, 49, 91, 41, 100, 49, 0, 67, 28, + 58, 42, 67, 66, 58, 84, 67, 104, 58, 13, 6, 35, 15, 55, 6, + 73, 15, 97, 6, 111, 15, 10, 32, 39, 24, 48, 32, 77, 24, 86, + 32, 115, 24, 14, 41, 23, 49, 52, 41, 61, 49, 90, 41, 100, 50, + 1, 67, 27, 58, 43, 67, 65, 58, 85, 67, 103, 58, 14, 6, 34, + 15, 56, 6, 72, 15, 98, 6, 110, 15, 9, 32, 38, 24, 47, 32, + 76, 24, 85, 32, 114, 24, 13, 41, 22, 49, 51, 41, 60, 49, 89, + 41, 101, 50, 2, 67, 26, 58, 44, 67, 64, 58, 86, 67, 102, 58, + 15, 6, 33, 15, 57, 6, 71, 15, 99, 6, 109, 15, 8, 32, 37, + 24, 46, 32, 75, 24, 84, 32, 113, 24, 12, 41, 21, 49, 50, 41, + 60, 50, 88, 41, 102, 50, 3, 67, 25, 58, 45, 67, 63, 58, 87, + 67, 101, 58, 16, 6, 32, 15, 58, 6, 70, 15, 99, 7, 108, 15, + 7, 32, 36, 24, 45, 32, 74, 24, 83, 32, 112, 24, 11, 41, 20, + 49, 49, 41, 61, 50, 87, 41, 103, 50, 4, 67, 24, 58, 46, 67, + 62, 58, 88, 67, 100, 58, 17, 6, 31, 15, 59, 6, 69, 15, 98, + 7, 107, 15, 6, 32, 35, 24, 44, 32, 73, 24, 82, 32, 111, 24, + 10, 41, 20, 50, 48, 41, 62, 50, 86, 41, 104, 50, 5, 67, 23, + 58, 47, 67, 61, 58, 89, 67, 100, 59, 18, 6, 30, 15, 59, 7, + 68, 15, 97, 7, 106, 15, 5, 32, 34, 24, 43, 32, 72, 24, 81, + 32, 110, 24, 9, 41, 21, 50, 47, 41, 63, 50, 85, 41, 105, 50, + 6, 67, 22, 58, 48, 67, 60, 58, 90, 67, 101, 59, 19, 6, 29, + 15, 58, 7, 67, 15, 96, 7, 105, 15, 4, 32, 33, 24, 42, 32, + 71, 24, 80, 32, 109, 24, 8, 41, 22, 50, 46, 41, 64, 50, 84, + 41, 106, 50, 7, 67, 21, 58, 49, 67, 60, 59, 91, 67, 102, 59, + 19, 7, 28, 15, 57, 7, 66, 15, 95, 7, 104, 15, 3, 32, 32, + 24, 41, 32, 70, 24, 80, 33, 108, 24, 7, 41, 23, 50, 45, 41, + 65, 50, 83, 41, 107, 50, 8, 67, 20, 58, 50, 67, 61, 59, 92, + 67, 103, 59, 18, 7, 27, 15, 56, 7, 65, 15, 94, 7, 103, 15, + 2, 32, 31, 24, 40, 32, 69, 24, 81, 33, 107, 24, 6, 41, 24, + 50, 44, 41, 66, 50, 82, 41, 108, 50, 9, 67, 20, 59, 51, 67, + 62, 59, 93, 67, 104, 59, 17, 7, 26, 15, 55, 7, 64, 15, 93, + 7, 102, 15, 1, 32, 30, 24, 40, 33, 68, 24, 82, 33, 106, 24, + 5, 41, 25, 50, 43, 41, 67, 50, 81, 41, 109, 50, 10, 67, 21, + 59, 52, 67, 63, 59, 94, 67, 105, 59, 16, 7, 25, 15, 54, 7, + 63, 15, 92, 7, 101, 15, 0, 32, 29, 24, 41, 33, 67, 24, 83, + 33, 105, 24, 4, 41, 26, 50, 42, 41, 68, 50, 80, 41, 110, 50, + 11, 67, 22, 59, 53, 67, 64, 59, 95, 67, 106, 59, 15, 7, 24, + 15, 53, 7, 62, 15, 91, 7, 100, 15, 0, 33, 28, 24, 42, 33, + 66, 24, 84, 33, 104, 24, 3, 41, 27, 50, 41, 41, 69, 50, 80, + 42, 111, 50, 12, 67, 23, 59, 54, 67, 65, 59, 96, 67, 107, 59, + 14, 7, 23, 15, 52, 7, 61, 15, 90, 7, 100, 16, 1, 33, 27, + 24, 43, 33, 65, 24, 85, 33, 103, 24, 2, 41, 28, 50, 40, 41, + 70, 50, 81, 42, 112, 50, 13, 67, 24, 59, 55, 67, 66, 59, 97, + 67, 108, 59, 13, 7, 22, 15, 51, 7, 60, 15, 89, 7, 101, 16, + 2, 33, 26, 24, 44, 33, 64, 24, 86, 33, 102, 24, 1, 41, 29, + 50, 40, 42, 71, 50, 82, 42, 113, 50, 14, 67, 25, 59, 56, 67, + 67, 59, 98, 67, 109, 59, 12, 7, 21, 15, 50, 7, 60, 16, 88, + 7, 102, 16, 3, 33, 25, 24, 45, 33, 63, 24, 87, 33, 101, 24, + 0, 41, 30, 50, 41, 42, 72, 50, 83, 42, 114, 50, 15, 67, 26, + 59, 57, 67, 68, 59, 99, 67, 110, 59, 11, 7, 20, 15, 49, 7, + 61, 16, 87, 7, 103, 16, 4, 33, 24, 24, 46, 33, 62, 24, 88, + 33, 100, 24, 0, 42, 31, 50, 42, 42, 73, 50, 84, 42, 115, 50, + 16, 67, 27, 59, 58, 67, 69, 59, 80, 51, 111, 59, 10, 7, 20, + 16, 48, 7, 62, 16, 86, 7, 104, 16, 5, 33, 23, 24, 47, 33, + 61, 24, 89, 33, 100, 25, 1, 42, 32, 50, 43, 42, 74, 50, 85, + 42, 116, 50, 17, 67, 28, 59, 59, 67, 70, 59, 81, 51, 112, 59, + 9, 7, 21, 16, 47, 7, 63, 16, 85, 7, 105, 16, 6, 33, 22, + 24, 48, 33, 60, 24, 90, 33, 101, 25, 2, 42, 33, 50, 44, 42, + 75, 50, 86, 42, 117, 50, 18, 67, 29, 59, 40, 51, 71, 59, 82, + 51, 113, 59, 8, 7, 22, 16, 46, 7, 64, 16, 84, 7, 106, 16, + 7, 33, 21, 24, 49, 33, 60, 25, 91, 33, 102, 25, 3, 42, 34, + 50, 45, 42, 76, 50, 87, 42, 118, 50, 19, 67, 30, 59, 41, 51, + 72, 59, 83, 51, 114, 59, 7, 7, 23, 16, 45, 7, 65, 16, 83, + 7, 107, 16, 8, 33, 20, 24, 50, 33, 61, 25, 92, 33, 103, 25, + 4, 42, 35, 50, 46, 42, 77, 50, 88, 42, 119, 50, 0, 51, 31, + 59, 42, 51, 73, 59, 84, 51, 115, 59, 6, 7, 24, 16, 44, 7, + 66, 16, 82, 7, 108, 16, 9, 33, 20, 25, 51, 33, 62, 25, 93, + 33, 104, 25, 5, 42, 36, 50, 47, 42, 78, 50, 89, 42, 100, 34, + 1, 51, 32, 59, 43, 51, 74, 59, 85, 51, 116, 59, 5, 7, 25, + 16, 43, 7, 67, 16, 81, 7, 109, 16, 10, 33, 21, 25, 52, 33, + 63, 25, 94, 33, 105, 25, 6, 42, 37, 50, 48, 42, 79, 50, 90, + 42, 101, 34, 2, 51, 33, 59, 44, 51, 75, 59, 86, 51, 117, 59, + 4, 7, 26, 16, 42, 7, 68, 16, 80, 7, 110, 16, 11, 33, 22, + 25, 53, 33, 64, 25, 95, 33, 106, 25, 7, 42, 38, 50, 49, 42, + 60, 34, 91, 42, 102, 34, 3, 51, 34, 59, 45, 51, 76, 59, 87, + 51, 118, 59, 3, 7, 27, 16, 41, 7, 69, 16, 80, 8, 111, 16, + 12, 33, 23, 25, 54, 33, 65, 25, 96, 33, 107, 25, 8, 42, 39, + 50, 50, 42, 61, 34, 92, 42, 103, 34, 4, 51, 35, 59, 46, 51, + 77, 59, 88, 51, 119, 59, 2, 7, 28, 16, 40, 7, 70, 16, 81, + 8, 112, 16, 13, 33, 24, 25, 55, 33, 66, 25, 97, 33, 108, 25, + 9, 42, 20, 34, 51, 42, 62, 34, 93, 42, 104, 34, 5, 51, 36, + 59, 47, 51, 78, 59, 89, 51, 119, 60, 1, 7, 29, 16, 40, 8, + 71, 16, 82, 8, 113, 16, 14, 33, 25, 25, 56, 33, 67, 25, 98, + 33, 109, 25, 10, 42, 21, 34, 52, 42, 63, 34, 94, 42, 105, 34, + 6, 51, 37, 59, 48, 51, 79, 59, 90, 51, 118, 60, 0, 7, 30, + 16, 41, 8, 72, 16, 83, 8, 114, 16, 15, 33, 26, 25, 57, 33, + 68, 25, 99, 33, 110, 25, 11, 42, 22, 34, 53, 42, 64, 34, 95, + 42, 106, 34, 7, 51, 38, 59, 49, 51, 79, 60, 91, 51, 117, 60, + 0, 8, 31, 16, 42, 8, 73, 16, 84, 8, 115, 16, 16, 33, 27, + 25, 58, 33, 69, 25, 80, 17, 111, 25, 12, 42, 23, 34, 54, 42, + 65, 34, 96, 42, 107, 34, 8, 51, 39, 59, 50, 51, 78, 60, 92, + 51, 116, 60, 1, 8, 32, 16, 43, 8, 74, 16, 85, 8, 116, 16, + 17, 33, 28, 25, 59, 33, 70, 25, 81, 17, 112, 25, 13, 42, 24, + 34, 55, 42, 66, 34, 97, 42, 108, 34, 9, 51, 39, 60, 51, 51, + 77, 60, 93, 51, 115, 60, 2, 8, 33, 16, 44, 8, 75, 16, 86, + 8, 117, 16, 18, 33, 29, 25, 40, 17, 71, 25, 82, 17, 113, 25, + 14, 42, 25, 34, 56, 42, 67, 34, 98, 42, 109, 34, 10, 51, 38, + 60, 52, 51, 76, 60, 94, 51, 114, 60, 3, 8, 34, 16, 45, 8, + 76, 16, 87, 8, 118, 16, 19, 33, 30, 25, 41, 17, 72, 25, 83, + 17, 114, 25, 15, 42, 26, 34, 57, 42, 68, 34, 99, 42, 110, 34, + 11, 51, 37, 60, 53, 51, 75, 60, 95, 51, 113, 60, 4, 8, 35, + 16, 46, 8, 77, 16, 88, 8, 119, 16, 0, 17, 31, 25, 42, 17, + 73, 25, 84, 17, 115, 25, 16, 42, 27, 34, 58, 42, 69, 34, 99, + 43, 111, 34, 12, 51, 36, 60, 54, 51, 74, 60, 96, 51, 112, 60, + 5, 8, 36, 16, 47, 8, 78, 16, 89, 8, 100, 0, 1, 17, 32, + 25, 43, 17, 74, 25, 85, 17, 116, 25, 17, 42, 28, 34, 59, 42, + 70, 34, 98, 43, 112, 34, 13, 51, 35, 60, 55, 51, 73, 60, 97, + 51, 111, 60, 6, 8, 37, 16, 48, 8, 79, 16, 90, 8, 101, 0, + 2, 17, 33, 25, 44, 17, 75, 25, 86, 17, 117, 25, 18, 42, 29, + 34, 59, 43, 71, 34, 97, 43, 113, 34, 14, 51, 34, 60, 56, 51, + 72, 60, 98, 51, 110, 60, 7, 8, 38, 16, 49, 8, 60, 0, 91, + 8, 102, 0, 3, 17, 34, 25, 45, 17, 76, 25, 87, 17, 118, 25, + 19, 42, 30, 34, 58, 43, 72, 34, 96, 43, 114, 34, 15, 51, 33, + 60, 57, 51, 71, 60, 99, 51, 109, 60, 8, 8, 39, 16, 50, 8, + 61, 0, 92, 8, 103, 0, 4, 17, 35, 25, 46, 17, 77, 25, 88, + 17, 119, 25, 19, 43, 31, 34, 57, 43, 73, 34, 95, 43, 115, 34, + 16, 51, 32, 60, 58, 51, 70, 60, 99, 52, 108, 60, 9, 8, 20, + 0, 51, 8, 62, 0, 93, 8, 104, 0, 5, 17, 36, 25, 47, 17, + 78, 25, 89, 17, 119, 26, 18, 43, 32, 34, 56, 43, 74, 34, 94, + 43, 116, 34, 17, 51, 31, 60, 59, 51, 69, 60, 98, 52, 107, 60, + 10, 8, 21, 0, 52, 8, 63, 0, 94, 8, 105, 0, 6, 17, 37, + 25, 48, 17, 79, 25, 90, 17, 118, 26, 17, 43, 33, 34, 55, 43, + 75, 34, 93, 43, 117, 34, 18, 51, 30, 60, 59, 52, 68, 60, 97, + 52, 106, 60, 11, 8, 22, 0, 53, 8, 64, 0, 95, 8, 106, 0, + 7, 17, 38, 25, 49, 17, 79, 26, 91, 17, 117, 26, 16, 43, 34, + 34, 54, 43, 76, 34, 92, 43, 118, 34, 19, 51, 29, 60, 58, 52, + 67, 60, 96, 52, 105, 60, 12, 8, 23, 0, 54, 8, 65, 0, 96, + 8, 107, 0, 8, 17, 39, 25, 50, 17, 78, 26, 92, 17, 116, 26, + 15, 43, 35, 34, 53, 43, 77, 34, 91, 43, 119, 34, 19, 52, 28, + 60, 57, 52, 66, 60, 95, 52, 104, 60, 13, 8, 24, 0, 55, 8, + 66, 0, 97, 8, 108, 0, 9, 17, 39, 26, 51, 17, 77, 26, 93, + 17, 115, 26, 14, 43, 36, 34, 52, 43, 78, 34, 90, 43, 119, 35, + 18, 52, 27, 60, 56, 52, 65, 60, 94, 52, 103, 60, 14, 8, 25, + 0, 56, 8, 67, 0, 98, 8, 109, 0, 10, 17, 38, 26, 52, 17, + 76, 26, 94, 17, 114, 26, 13, 43, 37, 34, 51, 43, 79, 34, 89, + 43, 118, 35, 17, 52, 26, 60, 55, 52, 64, 60, 93, 52, 102, 60, + 15, 8, 26, 0, 57, 8, 68, 0, 99, 8, 110, 0, 11, 17, 37, + 26, 53, 17, 75, 26, 95, 17, 113, 26, 12, 43, 38, 34, 50, 43, + 79, 35, 88, 43, 117, 35, 16, 52, 25, 60, 54, 52, 63, 60, 92, + 52, 101, 60, 16, 8, 27, 0, 58, 8, 69, 0, 99, 9, 111, 0, + 12, 17, 36, 26, 54, 17, 74, 26, 96, 17, 112, 26, 11, 43, 39, + 34, 49, 43, 78, 35, 87, 43, 116, 35, 15, 52, 24, 60, 53, 52, + 62, 60, 91, 52, 100, 60, 17, 8, 28, 0, 59, 8, 70, 0, 98, + 9, 112, 0, 13, 17, 35, 26, 55, 17, 73, 26, 97, 17, 111, 26, + 10, 43, 39, 35, 48, 43, 77, 35, 86, 43, 115, 35, 14, 52, 23, + 60, 52, 52, 61, 60, 90, 52, 100, 61, 18, 8, 29, 0, 59, 9, + 71, 0, 97, 9, 113, 0, 14, 17, 34, 26, 56, 17, 72, 26, 98, + 17, 110, 26, 9, 43, 38, 35, 47, 43, 76, 35, 85, 43, 114, 35, + 13, 52, 22, 60, 51, 52, 60, 60, 89, 52, 101, 61, 19, 8, 30, + 0, 58, 9, 72, 0, 96, 9, 114, 0, 15, 17, 33, 26, 57, 17, + 71, 26, 99, 17, 109, 26, 8, 43, 37, 35, 46, 43, 75, 35, 84, + 43, 113, 35, 12, 52, 21, 60, 50, 52, 60, 61, 88, 52, 102, 61, + 19, 9, 31, 0, 57, 9, 73, 0, 95, 9, 115, 0, 16, 17, 32, + 26, 58, 17, 70, 26, 99, 18, 108, 26, 7, 43, 36, 35, 45, 43, + 74, 35, 83, 43, 112, 35, 11, 52, 20, 60, 49, 52, 61, 61, 87, + 52, 103, 61, 18, 9, 32, 0, 56, 9, 74, 0, 94, 9, 116, 0, + 17, 17, 31, 26, 59, 17, 69, 26, 98, 18, 107, 26, 6, 43, 35, + 35, 44, 43, 73, 35, 82, 43, 111, 35, 10, 52, 20, 61, 48, 52, + 62, 61, 86, 52, 104, 61, 17, 9, 33, 0, 55, 9, 75, 0, 93, + 9, 117, 0, 18, 17, 30, 26, 59, 18, 68, 26, 97, 18, 106, 26, + 5, 43, 34, 35, 43, 43, 72, 35, 81, 43, 110, 35, 9, 52, 21, + 61, 47, 52, 63, 61, 85, 52, 105, 61, 16, 9, 34, 0, 54, 9, + 76, 0, 92, 9, 118, 0, 19, 17, 29, 26, 58, 18, 67, 26, 96, + 18, 105, 26, 4, 43, 33, 35, 42, 43, 71, 35, 80, 43, 109, 35, + 8, 52, 22, 61, 46, 52, 64, 61, 84, 52, 106, 61, 15, 9, 35, + 0, 53, 9, 77, 0, 91, 9, 119, 0, 19, 18, 28, 26, 57, 18, + 66, 26, 95, 18, 104, 26, 3, 43, 32, 35, 41, 43, 70, 35, 80, + 44, 108, 35, 7, 52, 23, 61, 45, 52, 65, 61, 83, 52, 107, 61, + 14, 9, 36, 0, 52, 9, 78, 0, 90, 9, 119, 1, 18, 18, 27, + 26, 56, 18, 65, 26, 94, 18, 103, 26, 2, 43, 31, 35, 40, 43, + 69, 35, 81, 44, 107, 35, 6, 52, 24, 61, 44, 52, 66, 61, 82, + 52, 108, 61, 13, 9, 37, 0, 51, 9, 79, 0, 89, 9, 118, 1, + 17, 18, 26, 26, 55, 18, 64, 26, 93, 18, 102, 26, 1, 43, 30, + 35, 40, 44, 68, 35, 82, 44, 106, 35, 5, 52, 25, 61, 43, 52, + 67, 61, 81, 52, 109, 61, 12, 9, 38, 0, 50, 9, 79, 1, 88, + 9, 117, 1, 16, 18, 25, 26, 54, 18, 63, 26, 92, 18, 101, 26, + 0, 43, 29, 35, 41, 44, 67, 35, 83, 44, 105, 35, 4, 52, 26, + 61, 42, 52, 68, 61, 80, 52, 110, 61, 11, 9, 39, 0, 49, 9, + 78, 1, 87, 9, 116, 1, 15, 18, 24, 26, 53, 18, 62, 26, 91, + 18, 100, 26, 0, 44, 28, 35, 42, 44, 66, 35, 84, 44, 104, 35, + 3, 52, 27, 61, 41, 52, 69, 61, 80, 53, 111, 61, 10, 9, 39, + 1, 48, 9, 77, 1, 86, 9, 115, 1, 14, 18, 23, 26, 52, 18, + 61, 26, 90, 18, 100, 27, 1, 44, 27, 35, 43, 44, 65, 35, 85, + 44, 103, 35, 2, 52, 28, 61, 40, 52, 70, 61, 81, 53, 112, 61, + 9, 9, 38, 1, 47, 9, 76, 1, 85, 9, 114, 1, 13, 18, 22, + 26, 51, 18, 60, 26, 89, 18, 101, 27, 2, 44, 26, 35, 44, 44, + 64, 35, 86, 44, 102, 35, 1, 52, 29, 61, 40, 53, 71, 61, 82, + 53, 113, 61, 8, 9, 37, 1, 46, 9, 75, 1, 84, 9, 113, 1, + 12, 18, 21, 26, 50, 18, 60, 27, 88, 18, 102, 27, 3, 44, 25, + 35, 45, 44, 63, 35, 87, 44, 101, 35, 0, 52, 30, 61, 41, 53, + 72, 61, 83, 53, 114, 61, 7, 9, 36, 1, 45, 9, 74, 1, 83, + 9, 112, 1, 11, 18, 20, 26, 49, 18, 61, 27, 87, 18, 103, 27, + 4, 44, 24, 35, 46, 44, 62, 35, 88, 44, 100, 35, 0, 53, 31, + 61, 42, 53, 73, 61, 84, 53, 115, 61, 6, 9, 35, 1, 44, 9, + 73, 1, 82, 9, 111, 1, 10, 18, 20, 27, 48, 18, 62, 27, 86, + 18, 104, 27, 5, 44, 23, 35, 47, 44, 61, 35, 89, 44, 100, 36, + 1, 53, 32, 61, 43, 53, 74, 61, 85, 53, 116, 61, 5, 9, 34, + 1, 43, 9, 72, 1, 81, 9, 110, 1, 9, 18, 21, 27, 47, 18, + 63, 27, 85, 18, 105, 27, 6, 44, 22, 35, 48, 44, 60, 35, 90, + 44, 101, 36, 2, 53, 33, 61, 44, 53, 75, 61, 86, 53, 117, 61, + 4, 9, 33, 1, 42, 9, 71, 1, 80, 9, 109, 1, 8, 18, 22, + 27, 46, 18, 64, 27, 84, 18, 106, 27, 7, 44, 21, 35, 49, 44, + 60, 36, 91, 44, 102, 36, 3, 53, 34, 61, 45, 53, 76, 61, 87, + 53, 118, 61, 3, 9, 32, 1, 41, 9, 70, 1, 80, 10, 108, 1, + 7, 18, 23, 27, 45, 18, 65, 27, 83, 18, 107, 27, 8, 44, 20, + 35, 50, 44, 61, 36, 92, 44, 103, 36, 4, 53, 35, 61, 46, 53, + 77, 61, 88, 53, 119, 61, 2, 9, 31, 1, 40, 9, 69, 1, 81, + 10, 107, 1, 6, 18, 24, 27, 44, 18, 66, 27, 82, 18, 108, 27, + 9, 44, 20, 36, 51, 44, 62, 36, 93, 44, 104, 36, 5, 53, 36, + 61, 47, 53, 78, 61, 89, 53, 119, 62, 1, 9, 30, 1, 40, 10, + 68, 1, 82, 10, 106, 1, 5, 18, 25, 27, 43, 18, 67, 27, 81, + 18, 109, 27, 10, 44, 21, 36, 52, 44, 63, 36, 94, 44, 105, 36, + 6, 53, 37, 61, 48, 53, 79, 61, 90, 53, 118, 62, 0, 9, 29, + 1, 41, 10, 67, 1, 83, 10, 105, 1, 4, 18, 26, 27, 42, 18, + 68, 27, 80, 18, 110, 27, 11, 44, 22, 36, 53, 44, 64, 36, 95, + 44, 106, 36, 7, 53, 38, 61, 49, 53, 79, 62, 91, 53, 117, 62, + 0, 10, 28, 1, 42, 10, 66, 1, 84, 10, 104, 1, 3, 18, 27, + 27, 41, 18, 69, 27, 80, 19, 111, 27, 12, 44, 23, 36, 54, 44, + 65, 36, 96, 44, 107, 36, 8, 53, 39, 61, 50, 53, 78, 62, 92, + 53, 116, 62, 1, 10, 27, 1, 43, 10, 65, 1, 85, 10, 103, 1, + 2, 18, 28, 27, 40, 18, 70, 27, 81, 19, 112, 27, 13, 44, 24, + 36, 55, 44, 66, 36, 97, 44, 108, 36, 9, 53, 39, 62, 51, 53, + 77, 62, 93, 53, 115, 62, 2, 10, 26, 1, 44, 10, 64, 1, 86, + 10, 102, 1, 1, 18, 29, 27, 40, 19, 71, 27, 82, 19, 113, 27, + 14, 44, 25, 36, 56, 44, 67, 36, 98, 44, 109, 36, 10, 53, 38, + 62, 52, 53, 76, 62, 94, 53, 114, 62, 3, 10, 25, 1, 45, 10, + 63, 1, 87, 10, 101, 1, 0, 18, 30, 27, 41, 19, 72, 27, 83, + 19, 114, 27, 15, 44, 26, 36, 57, 44, 68, 36, 99, 44, 110, 36, + 11, 53, 37, 62, 53, 53, 75, 62, 95, 53, 113, 62, 4, 10, 24, + 1, 46, 10, 62, 1, 88, 10, 100, 1, 0, 19, 31, 27, 42, 19, + 73, 27, 84, 19, 115, 27, 16, 44, 27, 36, 58, 44, 69, 36, 99, + 45, 111, 36, 12, 53, 36, 62, 54, 53, 74, 62, 96, 53, 112, 62, + 5, 10, 23, 1, 47, 10, 61, 1, 89, 10, 100, 2, 1, 19, 32, + 27, 43, 19, 74, 27, 85, 19, 116, 27, 17, 44, 28, 36, 59, 44, + 70, 36, 98, 45, 112, 36, 13, 53, 35, 62, 55, 53, 73, 62, 97, + 53, 111, 62, 6, 10, 22, 1, 48, 10, 60, 1, 90, 10, 101, 2, + 2, 19, 33, 27, 44, 19, 75, 27, 86, 19, 117, 27, 18, 44, 29, + 36, 59, 45, 71, 36, 97, 45, 113, 36, 14, 53, 34, 62, 56, 53, + 72, 62, 98, 53, 110, 62, 7, 10, 21, 1, 49, 10, 60, 2, 91, + 10, 102, 2, 3, 19, 34, 27, 45, 19, 76, 27, 87, 19, 118, 27, + 19, 44, 30, 36, 58, 45, 72, 36, 96, 45, 114, 36, 15, 53, 33, + 62, 57, 53, 71, 62, 99, 53, 109, 62, 8, 10, 20, 1, 50, 10, + 61, 2, 92, 10, 103, 2, 4, 19, 35, 27, 46, 19, 77, 27, 88, + 19, 119, 27, 19, 45, 31, 36, 57, 45, 73, 36, 95, 45, 115, 36, + 16, 53, 32, 62, 58, 53, 70, 62, 99, 54, 108, 62, 9, 10, 20, + 2, 51, 10, 62, 2, 93, 10, 104, 2, 5, 19, 36, 27, 47, 19, + 78, 27, 89, 19, 119, 28, 18, 45, 32, 36, 56, 45, 74, 36, 94, + 45, 116, 36, 17, 53, 31, 62, 59, 53, 69, 62, 98, 54, 107, 62, + 10, 10, 21, 2, 52, 10, 63, 2, 94, 10, 105, 2, 6, 19, 37, + 27, 48, 19, 79, 27, 90, 19, 118, 28, 17, 45, 33, 36, 55, 45, + 75, 36, 93, 45, 117, 36, 18, 53, 30, 62, 59, 54, 68, 62, 97, + 54, 106, 62, 11, 10, 22, 2, 53, 10, 64, 2, 95, 10, 106, 2, + 7, 19, 38, 27, 49, 19, 79, 28, 91, 19, 117, 28, 16, 45, 34, + 36, 54, 45, 76, 36, 92, 45, 118, 36, 19, 53, 29, 62, 58, 54, + 67, 62, 96, 54, 105, 62, 12, 10, 23, 2, 54, 10, 65, 2, 96, + 10, 107, 2, 8, 19, 39, 27, 50, 19, 78, 28, 92, 19, 116, 28, + 15, 45, 35, 36, 53, 45, 77, 36, 91, 45, 119, 36, 19, 54, 28, + 62, 57, 54, 66, 62, 95, 54, 104, 62, 13, 10, 24, 2, 55, 10, + 66, 2, 97, 10, 108, 2, 9, 19, 39, 28, 51, 19, 77, 28, 93, + 19, 115, 28, 14, 45, 36, 36, 52, 45, 78, 36, 90, 45, 119, 37, + 18, 54, 27, 62, 56, 54, 65, 62, 94, 54, 103, 62, 14, 10, 25, + 2, 56, 10, 67, 2, 98, 10, 109, 2, 10, 19, 38, 28, 52, 19, + 76, 28, 94, 19, 114, 28, 13, 45, 37, 36, 51, 45, 79, 36, 89, + 45, 118, 37, 17, 54, 26, 62, 55, 54, 64, 62, 93, 54, 102, 62, + 15, 10, 26, 2, 57, 10, 68, 2, 99, 10, 110, 2, 11, 19, 37, + 28, 53, 19, 75, 28, 95, 19, 113, 28, 12, 45, 38, 36, 50, 45, + 79, 37, 88, 45, 117, 37, 16, 54, 25, 62, 54, 54, 63, 62, 92, + 54, 101, 62, 16, 10, 27, 2, 58, 10, 69, 2, 99, 11, 111, 2, + 12, 19, 36, 28, 54, 19, 74, 28, 96, 19, 112, 28, 11, 45, 39, + 36, 49, 45, 78, 37, 87, 45, 116, 37, 15, 54, 24, 62, 53, 54, + 62, 62, 91, 54, 100, 62, 17, 10, 28, 2, 59, 10, 70, 2, 98, + 11, 112, 2, 13, 19, 35, 28, 55, 19, 73, 28, 97, 19, 111, 28, + 10, 45, 39, 37, 48, 45, 77, 37, 86, 45, 115, 37, 14, 54, 23, + 62, 52, 54, 61, 62, 90, 54, 100, 63, 18, 10, 29, 2, 59, 11, + 71, 2, 97, 11, 113, 2, 14, 19, 34, 28, 56, 19, 72, 28, 98, + 19, 110, 28, 9, 45, 38, 37, 47, 45, 76, 37, 85, 45, 114, 37, + 13, 54, 22, 62, 51, 54, 60, 62, 89, 54, 101, 63, 19, 10, 30, + 2, 58, 11, 72, 2, 96, 11, 114, 2, 15, 19, 33, 28, 57, 19, + 71, 28, 99, 19, 109, 28, 8, 45, 37, 37, 46, 45, 75, 37, 84, + 45, 113, 37, 12, 54, 21, 62, 50, 54, 60, 63, 88, 54, 102, 63, + 19, 11, 31, 2, 57, 11, 73, 2, 95, 11, 115, 2, 16, 19, 32, + 28, 58, 19, 70, 28, 99, 20, 108, 28, 7, 45, 36, 37, 45, 45, + 74, 37, 83, 45, 112, 37, 11, 54, 20, 62, 49, 54, 61, 63, 87, + 54, 103, 63, 18, 11, 32, 2, 56, 11, 74, 2, 94, 11, 116, 2, + 17, 19, 31, 28, 59, 19, 69, 28, 98, 20, 107, 28, 6, 45, 35, + 37, 44, 45, 73, 37, 82, 45, 111, 37, 10, 54, 20, 63, 48, 54, + 62, 63, 86, 54, 104, 63, 17, 11, 33, 2, 55, 11, 75, 2, 93, + 11, 117, 2, 18, 19, 30, 28, 59, 20, 68, 28, 97, 20, 106, 28, + 5, 45, 34, 37, 43, 45, 72, 37, 81, 45, 110, 37, 9, 54, 21, + 63, 47, 54, 63, 63, 85, 54, 105, 63, 16, 11, 34, 2, 54, 11, + 76, 2, 92, 11, 118, 2, 19, 19, 29, 28, 58, 20, 67, 28, 96, + 20, 105, 28, 4, 45, 33, 37, 42, 45, 71, 37, 80, 45, 109, 37, + 8, 54, 22, 63, 46, 54, 64, 63, 84, 54, 106, 63, 15, 11, 35, + 2, 53, 11, 77, 2, 91, 11, 119, 2, 19, 20, 28, 28, 57, 20, + 66, 28, 95, 20, 104, 28, 3, 45, 32, 37, 41, 45, 70, 37, 80, + 46, 108, 37, 7, 54, 23, 63, 45, 54, 65, 63, 83, 54, 107, 63, + 14, 11, 36, 2, 52, 11, 78, 2, 90, 11, 119, 3, 18, 20, 27, + 28, 56, 20, 65, 28, 94, 20, 103, 28, 2, 45, 31, 37, 40, 45, + 69, 37, 81, 46, 107, 37, 6, 54, 24, 63, 44, 54, 66, 63, 82, + 54, 108, 63, 13, 11, 37, 2, 51, 11, 79, 2, 89, 11, 118, 3, + 17, 20, 26, 28, 55, 20, 64, 28, 93, 20, 102, 28, 1, 45, 30, + 37, 40, 46, 68, 37, 82, 46, 106, 37, 5, 54, 25, 63, 43, 54, + 67, 63, 81, 54, 109, 63, 12, 11, 38, 2, 50, 11, 79, 3, 88, + 11, 117, 3, 16, 20, 25, 28, 54, 20, 63, 28, 92, 20, 101, 28, + 0, 45, 29, 37, 41, 46, 67, 37, 83, 46, 105, 37, 4, 54, 26, + 63, 42, 54, 68, 63, 80, 54, 110, 63, 11, 11, 39, 2, 49, 11, + 78, 3, 87, 11, 116, 3, 15, 20, 24, 28, 53, 20, 62, 28, 91, + 20, 100, 28, 0, 46, 28, 37, 42, 46, 66, 37, 84, 46, 104, 37, + 3, 54, 27, 63, 41, 54, 69, 63, 80, 55, 111, 63, 10, 11, 39, + 3, 48, 11, 77, 3, 86, 11, 115, 3, 14, 20, 23, 28, 52, 20, + 61, 28, 90, 20, 100, 29, 1, 46, 27, 37, 43, 46, 65, 37, 85, + 46, 103, 37, 2, 54, 28, 63, 40, 54, 70, 63, 81, 55, 112, 63, + 9, 11, 38, 3, 47, 11, 76, 3, 85, 11, 114, 3, 13, 20, 22, + 28, 51, 20, 60, 28, 89, 20, 101, 29, 2, 46, 26, 37, 44, 46, + 64, 37, 86, 46, 102, 37, 1, 54, 29, 63, 40, 55, 71, 63, 82, + 55, 113, 63, 8, 11, 37, 3, 46, 11, 75, 3, 84, 11, 113, 3, + 12, 20, 21, 28, 50, 20, 60, 29, 88, 20, 102, 29, 3, 46, 25, + 37, 45, 46, 63, 37, 87, 46, 101, 37, 0, 54, 30, 63, 41, 55, + 72, 63, 83, 55, 114, 63, 7, 11, 36, 3, 45, 11, 74, 3, 83, + 11, 112, 3, 11, 20, 20, 28, 49, 20, 61, 29, 87, 20, 103, 29, + 4, 46, 24, 37, 46, 46, 62, 37, 88, 46, 100, 37, 0, 55, 31, + 63, 42, 55, 73, 63, 84, 55, 115, 63, 6, 11, 35, 3, 44, 11, + 73, 3, 82, 11, 111, 3, 10, 20, 20, 29, 48, 20, 62, 29, 86, + 20, 104, 29, 5, 46, 23, 37, 47, 46, 61, 37, 89, 46, 100, 38, + 1, 55, 32, 63, 43, 55, 74, 63, 85, 55, 116, 63, 5, 11, 34, + 3, 43, 11, 72, 3, 81, 11, 110, 3, 9, 20, 21, 29, 47, 20, + 63, 29, 85, 20, 105, 29, 6, 46, 22, 37, 48, 46, 60, 37, 90, + 46, 101, 38, 2, 55, 33, 63, 44, 55, 75, 63, 86, 55, 117, 63, + 4, 11, 33, 3, 42, 11, 71, 3, 80, 11, 109, 3, 8, 20, 22, + 29, 46, 20, 64, 29, 84, 20, 106, 29, 7, 46, 21, 37, 49, 46, + 60, 38, 91, 46, 102, 38, 3, 55, 34, 63, 45, 55, 76, 63, 87, + 55, 118, 63, 3, 11, 32, 3, 41, 11, 70, 3, 80, 12, 108, 3, + 7, 20, 23, 29, 45, 20, 65, 29, 83, 20, 107, 29, 8, 46, 20, + 37, 50, 46, 61, 38, 92, 46, 103, 38, 4, 55, 35, 63, 46, 55, + 77, 63, 88, 55, 119, 63, 2, 11, 31, 3, 40, 11, 69, 3, 81, + 12, 107, 3, 6, 20, 24, 29, 44, 20, 66, 29, 82, 20, 108, 29, + 9, 46, 20, 38, 51, 46, 62, 38, 93, 46, 104, 38, 5, 55, 36, + 63, 47, 55, 78, 63, 89, 55, 119, 64, 1, 11, 30, 3, 40, 12, + 68, 3, 82, 12, 106, 3, 5, 20, 25, 29, 43, 20, 67, 29, 81, + 20, 109, 29, 10, 46, 21, 38, 52, 46, 63, 38, 94, 46, 105, 38, + 6, 55, 37, 63, 48, 55, 79, 63, 90, 55, 118, 64, 0, 11, 29, + 3, 41, 12, 67, 3, 83, 12, 105, 3, 4, 20, 26, 29, 42, 20, + 68, 29, 80, 20, 110, 29, 11, 46, 22, 38, 53, 46, 64, 38, 95, + 46, 106, 38, 7, 55, 38, 63, 49, 55, 79, 64, 91, 55, 117, 64, + 0, 12, 28, 3, 42, 12, 66, 3, 84, 12, 104, 3, 3, 20, 27, + 29, 41, 20, 69, 29, 80, 21, 111, 29, 12, 46, 23, 38, 54, 46, + 65, 38, 96, 46, 107, 38, 8, 55, 39, 63, 50, 55, 78, 64, 92, + 55, 116, 64, 1, 12, 27, 3, 43, 12, 65, 3, 85, 12, 103, 3, + 2, 20, 28, 29, 40, 20, 70, 29, 81, 21, 112, 29, 13, 46, 24, + 38, 55, 46, 66, 38, 97, 46, 108, 38, 9, 55, 39, 64, 51, 55, + 77, 64, 93, 55, 115, 64, 2, 12, 26, 3, 44, 12, 64, 3, 86, + 12, 102, 3, 1, 20, 29, 29, 40, 21, 71, 29, 82, 21, 113, 29, + 14, 46, 25, 38, 56, 46, 67, 38, 98, 46, 109, 38, 10, 55, 38, + 64, 52, 55, 76, 64, 94, 55, 114, 64, 3, 12, 25, 3, 45, 12, + 63, 3, 87, 12, 101, 3, 0, 20, 30, 29, 41, 21, 72, 29, 83, + 21, 114, 29, 15, 46, 26, 38, 57, 46, 68, 38, 99, 46, 110, 38, + 11, 55, 37, 64, 53, 55, 75, 64, 95, 55, 113, 64, 4, 12, 24, + 3, 46, 12, 62, 3, 88, 12, 100, 3, 0, 21, 31, 29, 42, 21, + 73, 29, 84, 21, 115, 29, 16, 46, 27, 38, 58, 46, 69, 38, 99, + 47, 111, 38, 12, 55, 36, 64, 54, 55, 74, 64, 96, 55, 112, 64, + 5, 12, 23, 3, 47, 12, 61, 3, 89, 12, 100, 4, 1, 21, 32, + 29, 43, 21, 74, 29, 85, 21, 116, 29, 17, 46, 28, 38, 59, 46, + 70, 38, 98, 47, 112, 38, 13, 55, 35, 64, 55, 55, 73, 64, 97, + 55, 111, 64, 6, 12, 22, 3, 48, 12, 60, 3, 90, 12, 101, 4, + 2, 21, 33, 29, 44, 21, 75, 29, 86, 21, 117, 29, 18, 46, 29, + 38, 59, 47, 71, 38, 97, 47, 113, 38, 14, 55, 34, 64, 56, 55, + 72, 64, 98, 55, 110, 64, 7, 12, 21, 3, 49, 12, 60, 4, 91, + 12, 102, 4, 3, 21, 34, 29, 45, 21, 76, 29, 87, 21, 118, 29, + 19, 46, 30, 38, 58, 47, 72, 38, 96, 47, 114, 38, 15, 55, 33, + 64, 57, 55, 71, 64, 99, 55, 109, 64, 8, 12, 20, 3, 50, 12, + 61, 4, 92, 12, 103, 4, 4, 21, 35, 29, 46, 21, 77, 29, 88, + 21, 119, 29, 19, 47, 31, 38, 57, 47, 73, 38, 95, 47, 115, 38, + 16, 55, 32, 64, 58, 55, 70, 64, 99, 56, 108, 64, 9, 12, 20, + 4, 51, 12, 62, 4, 93, 12, 104, 4, 5, 21, 36, 29, 47, 21, + 78, 29, 89, 21, 119, 30, 18, 47, 32, 38, 56, 47, 74, 38, 94, + 47, 116, 38, 17, 55, 31, 64, 59, 55, 69, 64, 98, 56, 107, 64, + 10, 12, 21, 4, 52, 12, 63, 4, 94, 12, 105, 4, 6, 21, 37, + 29, 48, 21, 79, 29, 90, 21, 118, 30, 17, 47, 33, 38, 55, 47, + 75, 38, 93, 47, 117, 38, 18, 55, 30, 64, 59, 56, 68, 64, 97, + 56, 106, 64, 11, 12, 22, 4, 53, 12, 64, 4, 95, 12, 106, 4, + 7, 21, 38, 29, 49, 21, 79, 30, 91, 21, 117, 30, 16, 47, 34, + 38, 54, 47, 76, 38, 92, 47, 118, 38, 19, 55, 29, 64, 58, 56, + 67, 64, 96, 56, 105, 64, 12, 12, 23, 4, 54, 12, 65, 4, 96, + 12, 107, 4, 8, 21, 39, 29, 50, 21, 78, 30, 92, 21, 116, 30, + 15, 47, 35, 38, 53, 47, 77, 38, 91, 47, 119, 38, 19, 56, 28, + 64, 57, 56, 66, 64, 95, 56, 104, 64, 13, 12, 24, 4, 55, 12, + 66, 4, 97, 12, 108, 4, 9, 21, 39, 30, 51, 21, 77, 30, 93, + 21, 115, 30, 14, 47, 36, 38, 52, 47, 78, 38, 90, 47, 119, 39, + 18, 56, 27, 64, 56, 56, 65, 64, 94, 56, 103, 64, 14, 12, 25, + 4, 56, 12, 67, 4, 98, 12, 109, 4, 10, 21, 38, 30, 52, 21, + 76, 30, 94, 21, 114, 30, 13, 47, 37, 38, 51, 47, 79, 38, 89, + 47, 118, 39, 17, 56, 26, 64, 55, 56, 64, 64, 93, 56, 102, 64, + 15, 12, 26, 4, 57, 12, 68, 4, 99, 12, 110, 4, 11, 21, 37, + 30, 53, 21, 75, 30, 95, 21, 113, 30, 12, 47, 38, 38, 50, 47, + 79, 39, 88, 47, 117, 39, 16, 56, 25, 64, 54, 56, 63, 64, 92, + 56, 101, 64, 16, 12, 27, 4, 58, 12, 69, 4, 99, 13, 111, 4, + 12, 21, 36, 30, 54, 21, 74, 30, 96, 21, 112, 30, 11, 47, 39, + 38, 49, 47, 78, 39, 87, 47, 116, 39, 15, 56, 24, 64, 53, 56, + 62, 64, 91, 56, 100, 64, 17, 12, 28, 4, 59, 12, 70, 4, 98, + 13, 112, 4, 13, 21, 35, 30, 55, 21, 73, 30, 97, 21, 111, 30, + 10, 47, 39, 39, 48, 47, 77, 39, 86, 47, 115, 39, 14, 56, 23, + 64, 52, 56, 61, 64, 90, 56, 100, 65, 18, 12, 29, 4, 59, 13, + 71, 4, 97, 13, 113, 4, 14, 21, 34, 30, 56, 21, 72, 30, 98, + 21, 110, 30, 9, 47, 38, 39, 47, 47, 76, 39, 85, 47, 114, 39, + 13, 56, 22, 64, 51, 56, 60, 64, 89, 56, 101, 65, 19, 12, 30, + 4, 58, 13, 72, 4, 96, 13, 114, 4, 15, 21, 33, 30, 57, 21, + 71, 30, 99, 21, 109, 30, 8, 47, 37, 39, 46, 47, 75, 39, 84, + 47, 113, 39, 12, 56, 21, 64, 50, 56, 60, 65, 88, 56, 102, 65, + 19, 13, 31, 4, 57, 13, 73, 4, 95, 13, 115, 4, 16, 21, 32, + 30, 58, 21, 70, 30, 99, 22, 108, 30, 7, 47, 36, 39, 45, 47, + 74, 39, 83, 47, 112, 39, 11, 56, 20, 64, 49, 56, 61, 65, 87, + 56, 103, 65, 18, 13, 32, 4, 56, 13, 74, 4, 94, 13, 116, 4, + 17, 21, 31, 30, 59, 21, 69, 30, 98, 22, 107, 30, 6, 47, 35, + 39, 44, 47, 73, 39, 82, 47, 111, 39, 10, 56, 20, 65, 48, 56, + 62, 65, 86, 56, 104, 65, 17, 13, 33, 4, 55, 13, 75, 4, 93, + 13, 117, 4, 18, 21, 30, 30, 59, 22, 68, 30, 97, 22, 106, 30, + 5, 47, 34, 39, 43, 47, 72, 39, 81, 47, 110, 39, 9, 56, 21, + 65, 47, 56, 63, 65, 85, 56, 105, 65, 16, 13, 34, 4, 54, 13, + 76, 4, 92, 13, 118, 4, 19, 21, 29, 30, 58, 22, 67, 30, 96, + 22, 105, 30, 4, 47, 33, 39, 42, 47, 71, 39, 80, 47, 109, 39, + 8, 56, 22, 65, 46, 56, 64, 65, 84, 56, 106, 65, 15, 13, 35, + 4, 53, 13, 77, 4, 91, 13, 119, 4, 19, 22, 28, 30, 57, 22, + 66, 30, 95, 22, 104, 30, 3, 47, 32, 39, 41, 47, 70, 39, 80, + 48, 108, 39, 7, 56, 23, 65, 45, 56, 65, 65, 83, 56, 107, 65, + 14, 13, 36, 4, 52, 13, 78, 4, 90, 13, 119, 5, 18, 22, 27, + 30, 56, 22, 65, 30, 94, 22, 103, 30, 2, 47, 31, 39, 40, 47, + 69, 39, 81, 48, 107, 39, 6, 56, 24, 65, 44, 56, 66, 65, 82, + 56, 108, 65, 13, 13, 37, 4, 51, 13, 79, 4, 89, 13, 118, 5, + 17, 22, 26, 30, 55, 22, 64, 30, 93, 22, 102, 30, 1, 47, 30, + 39, 40, 48, 68, 39, 82, 48, 106, 39, 5, 56, 25, 65, 43, 56, + 67, 65, 81, 56, 109, 65, 12, 13, 38, 4, 50, 13, 79, 5, 88, + 13, 117, 5, 16, 22, 25, 30, 54, 22, 63, 30, 92, 22, 101, 30, + 0, 47, 29, 39, 41, 48, 67, 39, 83, 48, 105, 39, 4, 56, 26, + 65, 42, 56, 68, 65, 80, 56, 110, 65, 11, 13, 39, 4, 49, 13, + 78, 5, 87, 13, 116, 5, 15, 22, 24, 30, 53, 22, 62, 30, 91, + 22, 100, 30, 0, 48, 28, 39, 42, 48, 66, 39, 84, 48, 104, 39, + 3, 56, 27, 65, 41, 56, 69, 65, 80, 57, 111, 65, 10, 13, 39, + 5, 48, 13, 77, 5, 86, 13, 115, 5, 14, 22, 23, 30, 52, 22, + 61, 30, 90, 22, 100, 31, 1, 48, 27, 39, 43, 48, 65, 39, 85, + 48, 103, 39, 2, 56, 28, 65, 40, 56, 70, 65, 81, 57, 112, 65, + 9, 13, 38, 5, 47, 13, 76, 5, 85, 13, 114, 5, 13, 22, 22, + 30, 51, 22, 60, 30, 89, 22, 101, 31, 2, 48, 26, 39, 44, 48, + 64, 39, 86, 48, 102, 39, 1, 56, 29, 65, 40, 57, 71, 65, 82, + 57, 113, 65, 8, 13, 37, 5, 46, 13, 75, 5, 84, 13, 113, 5, + 12, 22, 21, 30, 50, 22, 60, 31, 88, 22, 102, 31, 3, 48, 25, + 39, 45, 48, 63, 39, 87, 48, 101, 39, 0, 56, 30, 65, 41, 57, + 72, 65, 83, 57, 114, 65, 7, 13, 36, 5, 45, 13, 74, 5, 83, + 13, 112, 5, 11, 22, 20, 30, 49, 22, 61, 31, 87, 22, 103, 31, + 4, 48, 24, 39, 46, 48, 62, 39, 88, 48, 100, 39, 0, 57, 31, + 65, 42, 57, 73, 65, 84, 57, 115, 65, 6, 13, 35, 5, 44, 13, + 73, 5, 82, 13, 111, 5, 10, 22, 20, 31, 48, 22, 62, 31, 86, + 22, 104, 31, 5, 48, 23, 39, 47, 48, 61, 39, 89, 48, 100, 40, + 1, 57, 32, 65, 43, 57, 74, 65, 85, 57, 116, 65, 5, 13, 34, + 5, 43, 13, 72, 5, 81, 13, 110, 5, 9, 22, 21, 31, 47, 22, + 63, 31, 85, 22, 105, 31, 6, 48, 22, 39, 48, 48, 60, 39, 90, + 48, 101, 40, 2, 57, 33, 65, 44, 57, 75, 65, 86, 57, 117, 65, + 4, 13, 33, 5, 42, 13, 71, 5, 80, 13, 109, 5, 8, 22, 22, + 31, 46, 22, 64, 31, 84, 22, 106, 31, 7, 48, 21, 39, 49, 48, + 60, 40, 91, 48, 102, 40, 3, 57, 34, 65, 45, 57, 76, 65, 87, + 57, 118, 65, 3, 13, 32, 5, 41, 13, 70, 5, 80, 14, 108, 5, + 7, 22, 23, 31, 45, 22, 65, 31, 83, 22, 107, 31, 8, 48, 20, + 39, 50, 48, 61, 40, 92, 48, 103, 40, 4, 57, 35, 65, 46, 57, + 77, 65, 88, 57, 119, 65, 2, 13, 31, 5, 40, 13, 69, 5, 81, + 14, 107, 5, 6, 22, 24, 31, 44, 22, 66, 31, 82, 22, 108, 31, + 9, 48, 20, 40, 51, 48, 62, 40, 93, 48, 104, 40, 5, 57, 36, + 65, 47, 57, 78, 65, 89, 57, 119, 66, 1, 13, 30, 5, 40, 14, + 68, 5, 82, 14, 106, 5, 5, 22, 25, 31, 43, 22, 67, 31, 81, + 22, 109, 31, 10, 48, 21, 40, 52, 48, 63, 40, 94, 48, 105, 40, + 6, 57, 37, 65, 48, 57, 79, 65, 90, 57, 118, 66, 0, 13, 29, + 5, 41, 14, 67, 5, 83, 14, 105, 5, 4, 22, 26, 31, 42, 22, + 68, 31, 80, 22, 110, 31, 11, 48, 22, 40, 53, 48, 64, 40, 95, + 48, 106, 40, 7, 57, 38, 65, 49, 57, 79, 66, 91, 57, 117, 66, + 0, 14, 28, 5, 42, 14, 66, 5, 84, 14, 104, 5, 3, 22, 27, + 31, 41, 22, 69, 31, 80, 23, 111, 31, 12, 48, 23, 40, 54, 48, + 65, 40, 96, 48, 107, 40, 8, 57, 39, 65, 50, 57, 78, 66, 92, + 57, 116, 66, 1, 14, 27, 5, 43, 14, 65, 5, 85, 14, 103, 5, + 2, 22, 28, 31, 40, 22, 70, 31, 81, 23, 112, 31, 13, 48, 24, + 40, 55, 48, 66, 40, 97, 48, 108, 40, 9, 57, 39, 66, 51, 57, + 77, 66, 93, 57, 115, 66, 2, 14, 26, 5, 44, 14, 64, 5, 86, + 14, 102, 5, 1, 22, 29, 31, 40, 23, 71, 31, 82, 23, 113, 31, + 14, 48, 25, 40, 56, 48, 67, 40, 98, 48, 109, 40, 10, 57, 38, + 66, 52, 57, 76, 66, 94, 57, 114, 66, 3, 14, 25, 5, 45, 14, + 63, 5, 87, 14, 101, 5, 0, 22, 30, 31, 41, 23, 72, 31, 83, + 23, 114, 31, 15, 48, 26, 40, 57, 48, 68, 40, 99, 48, 110, 40, + 11, 57, 37, 66, 53, 57, 75, 66, 95, 57, 113, 66, 4, 14, 24, + 5, 46, 14, 62, 5, 88, 14, 100, 5, 0, 23, 31, 31, 42, 23, + 73, 31, 84, 23, 115, 31, 16, 48, 27, 40, 58, 48, 69, 40, 99, + 49, 111, 40, 12, 57, 36, 66, 54, 57, 74, 66, 96, 57, 112, 66, + 5, 14, 23, 5, 47, 14, 61, 5, 89, 14, 100, 6, 1, 23, 32, + 31, 43, 23, 74, 31, 85, 23, 116, 31, 17, 48, 28, 40, 59, 48, + 70, 40, 98, 49, 112, 40, 13, 57, 35, 66, 55, 57, 73, 66, 97, + 57, 111, 66, 6, 14, 22, 5, 48, 14, 60, 5, 90, 14, 101, 6, + 2, 23, 33, 31, 44, 23, 75, 31, 86, 23, 117, 31, 18, 48, 29, + 40, 59, 49, 71, 40, 97, 49, 113, 40, 14, 57, 34, 66, 56, 57, + 72, 66, 98, 57, 110, 66, 7, 14, 21, 5, 49, 14, 60, 6, 91, + 14, 102, 6, 3, 23, 34, 31, 45, 23, 76, 31, 87, 23, 118, 31, + 19, 48, 30, 40, 58, 49, 72, 40, 96, 49, 114, 40, 15, 57, 33, + 66, 57, 57, 71, 66, 99, 57, 109, 66, 8, 14, 20, 5, 50, 14, + 61, 6, 92, 14, 103, 6, 4, 23, 35, 31, 46, 23, 77, 31, 88, + 23, 119, 31, 19, 49, 31, 40, 57, 49, 73, 40, 95, 49, 115, 40, + 16, 57, 32, 66, 58, 57, 70, 66, 99, 58, 108, 66, 9, 14, 20, + 6, 51, 14, 62, 6, 93, 14, 104, 6, 5, 23, 36, 31, 47, 23, + 78, 31, 89, 23, 119, 32, 18, 49, 32, 40, 56, 49, 74, 40, 94, + 49, 116, 40, 17, 57, 31, 66, 59, 57, 69, 66, 98, 58, 107, 66, + 10, 14, 21, 6, 52, 14, 63, 6, 94, 14, 105, 6, 6, 23, 37, + 31, 48, 23, 79, 31, 90, 23, 118, 32, 17, 49, 33, 40, 55, 49, + 75, 40, 93, 49, 117, 40, 18, 57, 30, 66, 59, 58, 68, 66, 97, + 58, 106, 66, 11, 14, 22, 6, 53, 14, 64, 6, 95, 14, 106, 6, + 7, 23, 38, 31, 49, 23, 79, 32, 91, 23, 117, 32, 16, 49, 34, + 40, 54, 49, 76, 40, 92, 49, 118, 40, 19, 57, 29, 66, 58, 58, + 67, 66, 96, 58, 105, 66, 12, 14, 23, 6, 54, 14, 65, 6, 96, + 14, 107, 6, 8, 23, 39, 31, 50, 23, 78, 32, 92, 23, 116, 32, + 15, 49, 35, 40, 53, 49, 77, 40, 91, 49, 119, 40, 19, 58, 28, + 66, 57, 58, 66, 66, 95, 58, 104, 66, 13, 14, 24, 6, 55, 14, + 66, 6, 97, 14, 108, 6, 9, 23, 39, 32, 51, 23, 77, 32, 93, + 23, 115, 32, 14, 49, 36, 40, 52, 49, 78, 40, 90, 49, 119, 41, + 18, 58, 27, 66, 56, 58, 65, 66, 94, 58, 103, 66, 14, 14, 25, + 6, 56, 14, 67, 6, 98, 14, 109, 6, 10, 23, 38, 32, 52, 23, + 76, 32, 94, 23, 114, 32, 13, 49, 37, 40, 51, 49, 79, 40, 89, + 49, 118, 41, 17, 58, 26, 66, 55, 58, 64, 66, 93, 58, 102, 66, + 15, 14, 26, 6, 57, 14, 68, 6, 99, 14, 110, 6, 11, 23, 37, + 32, 53, 23, 75, 32, 95, 23, 113, 32, 12, 49, 38, 40, 50, 49, + 79, 41, 88, 49, 117, 41, 16, 58, 25, 66, 54, 58, 63, 66, 92, + 58, 101, 66, 16, 14, 27, 6, 58, 14, 69, 6, 99, 15, 111, 6, + 12, 23, 36, 32, 54, 23, 74, 32, 96, 23, 112, 32, 11, 49, 39, + 40, 49, 49, 78, 41, 87, 49, 116, 41, 15, 58, 24, 66, 53, 58, + 62, 66, 91, 58, 100, 66, 17, 14, 28, 6, 59, 14, 70, 6, 98, + 15, 112, 6, 13, 23, 35, 32, 55, 23, 73, 32, 97, 23, 111, 32, + 10, 49, 39, 41, 48, 49, 77, 41, 86, 49, 115, 41, 14, 58, 23, + 66, 52, 58, 61, 66, 90, 58, 100, 67, 18, 14, 29, 6, 59, 15, + 71, 6, 97, 15, 113, 6, 14, 23, 34, 32, 56, 23, 72, 32, 98, + 23, 110, 32, 9, 49, 38, 41, 47, 49, 76, 41, 85, 49, 114, 41, + 13, 58, 22, 66, 51, 58, 60, 66, 89, 58, 101, 67, 19, 14, 30, + 6, 58, 15, 72, 6, 96, 15, 114, 6, 15, 23, 33, 32, 57, 23, + 71, 32, 99, 23, 109, 32, 8, 49, 37, 41, 46, 49, 75, 41, 84, + 49, 113, 41, 12, 58, 21, 66, 50, 58, 60, 67, 88, 58, 102, 67, + 19, 15, 31, 6, 57, 15, 73, 6, 95, 15, 115, 6, 16, 23, 32, + 32, 58, 23, 70, 32, 99, 24, 108, 32, 7, 49, 36, 41, 45, 49, + 74, 41, 83, 49, 112, 41, 11, 58, 20, 66, 49, 58, 61, 67, 87, + 58, 103, 67, 18, 15, 32, 6, 56, 15, 74, 6, 94, 15, 116, 6, + 17, 23, 31, 32, 59, 23, 69, 32, 98, 24, 107, 32, 6, 49, 35, + 41, 44, 49, 73, 41, 82, 49, 111, 41, 10, 58, 20, 67, 48, 58, + 62, 67, 86, 58, 104, 67, 17, 15, 33, 6, 55, 15, 75, 6, 93, + 15, 117, 6, 18, 23, 30, 32, 59, 24, 68, 32, 97, 24, 106, 32, + 5, 49, 34, 41, 43, 49, 72, 41, 81, 49, 110, 41, 9, 58, 21, + 67, 47, 58, 63, 67, 85, 58, 105, 67, 16, 15, 34, 6, 54, 15, + 76, 6, 92, 15, 118, 6, 19, 23, 29, 32, 58, 24, 67, 32, 96, + 24, 105, 32, 4, 49, 33, 41, 42, 49, 71, 41, 80, 49, 109, 41, + 8, 58, 22, 67, 46, 58, 64, 67, 84, 58, 106, 67, 15, 15, 35, + 6, 53, 15, 77, 6, 91, 15, 119, 6, 19, 24, 28, 32, 57, 24, + 66, 32, 95, 24, 104, 32, 3, 49, 32, 41, 41, 49, 70, 41, 80, + 50, 108, 41, 7, 58, 23, 67, 45, 58, 65, 67, 83, 58, 107, 67, + 14, 15, 36, 6, 52, 15, 78, 6, 90, 15, 119, 7, 18, 24, 27, + 32, 56, 24, 65, 32, 94, 24, 103, 32, 2, 49, 31, 41, 40, 49, + 69, 41, 81, 50, 107, 41, 6, 58, 24, 67, 44, 58, 66, 67, 82, + 58, 108, 67, 13, 15, 37, 6, 51, 15, 79, 6, 89, 15, 118, 7, + 17, 24, 26, 32, 55, 24, 64, 32, 93, 24, 102, 32, 1, 49, 30, + 41, 40, 50, 68, 41, 82, 50, 106, 41, 5, 58, 25, 67, 43, 58, + 67, 67, 81, 58, 109, 67, 12, 15, 38, 6, 50, 15, 79, 7, 88, + 15, 117, 7, 16, 24, 25, 32, 54, 24, 63, 32, 92, 24, 101, 32, + 0, 49, 29, 41, 41, 50, 67, 41, 83, 50, 105, 41, 4, 58, 26, + 67, 42, 58, 68, 67, 80, 58, 110, 67, 11, 15, 39, 6, 49, 15, + 78, 7, 87, 15, 116, 7, 15, 24, 24, 32, 53, 24, 62, 32, 91, + 24, 100, 32, 0, 50, 28, 41, 42, 50, 66, 41, 84, 50, 104, 41, + 3, 58, 27, 67, 41, 58, 69, 67, 80, 59, 111, 67, 10, 15, 39, + 7, 48, 15, 77, 7, 86, 15, 115, 7, 14, 24, 23, 32, 52, 24, + 61, 32, 90, 24, 100, 33, 1, 50, 27, 41, 43, 50, 65, 41, 85, + 50, 103, 41, 2, 58, 28, 67, 40, 58, 70, 67, 81, 59, 112, 67, + 9, 15, 38, 7, 47, 15, 76, 7, 85, 15, 114, 7, 13, 24, 22, + 32, 51, 24, 60, 32, 89, 24, 101, 33, 2, 50, 26, 41, 44, 50, + 64, 41, 86, 50, 102, 41, 1, 58, 29, 67, 40, 59, 71, 67, 82, + 59, 113, 67, 8, 15, 37, 7, 46, 15, 75, 7, 84, 15, 113, 7, + 12, 24, 21, 32, 50, 24, 60, 33, 88, 24, 102, 33, 3, 50, 25, + 41, 45, 50, 63, 41, 87, 50, 101, 41, 0, 58, 30, 67, 41, 59, + 72, 67, 83, 59, 114, 67, 7, 15, 36, 7, 45, 15, 74, 7, 83, + 15, 112, 7, 11, 24, 20, 32, 49, 24, 61, 33, 87, 24, 103, 33, + 4, 50, 24, 41, 46, 50, 62, 41, 88, 50, 100, 41, 0, 59, 31, + 67, 42, 59, 73, 67, 84, 59, 115, 67, 6, 15, 35, 7, 44, 15, + 73, 7, 82, 15, 111, 7, 10, 24, 20, 33, 48, 24, 62, 33, 86, + 24, 104, 33, 5, 50, 23, 41, 47, 50, 61, 41, 89, 50, 100, 42, + 1, 59, 32, 67, 43, 59, 74, 67, 85, 59, 116, 67, 5, 15, 34, + 7, 43, 15, 72, 7, 81, 15, 110, 7, 9, 24, 21, 33, 47, 24, + 63, 33, 85, 24, 105, 33, 6, 50, 22, 41, 48, 50, 60, 41, 90, + 50, 101, 42, 2, 59, 33, 67, 44, 59, 75, 67, 86, 59, 117, 67, + 4, 15, 33, 7, 42, 15, 71, 7, 80, 15, 109, 7, 8, 24, 22, + 33, 46, 24, 64, 33, 84, 24, 106, 33, 7, 50, 21, 41, 49, 50, + 60, 42, 91, 50, 102, 42, 3, 59, 34, 67, 45, 59, 76, 67, 87, + 59, 118, 67, 3, 15, 32, 7, 41, 15, 70, 7, 80, 16, 108, 7, + 7, 24, 23, 33, 45, 24, 65, 33, 83, 24, 107, 33, 8, 50, 20, + 41, 50, 50, 61, 42, 92, 50, 103, 42, 4, 59, 35, 67, 46, 59, + 77, 67, 88, 59, 119, 67, 2, 15, 31, 7, 40, 15, 69, 7, 81, + 16, 107, 7, 6, 24, 24, 33, 44, 24, 66, 33, 82, 24, 108, 33, + 9, 50, 20, 42, 51, 50, 62, 42, 93, 50, 104, 42, 5, 59, 36, + 67, 47, 59, 78, 67, 89, 59, 100, 51, 1, 15, 30, 7, 40, 16, + 68, 7, 82, 16, 106, 7, 5, 24, 25, 33, 43, 24, 67, 33, 81, + 24, 109, 33, 10, 50, 21, 42, 52, 50, 63, 42, 94, 50, 105, 42, + 6, 59, 37, 67, 48, 59, 79, 67, 90, 59, 101, 51, 0, 15, 29, + 7, 41, 16, 67, 7, 83, 16, 105, 7, 4, 24, 26, 33, 42, 24, + 68, 33, 80, 24, 110, 33, 11, 50, 22, 42, 53, 50, 64, 42, 95, + 50, 106, 42, 7, 59, 38, 67, 49, 59, 60, 51, 91, 59, 102, 51, + 0, 16, 28, 7, 42, 16, 66, 7, 84, 16, 104, 7, 3, 24, 27, + 33, 41, 24, 69, 33, 80, 25, 111, 33, 12, 50, 23, 42, 54, 50, + 65, 42, 96, 50, 107, 42, 8, 59, 39, 67, 50, 59, 61, 51, 92, + 59, 103, 51, 1, 16, 27, 7, 43, 16, 65, 7, 85, 16, 103, 7, + 2, 24, 28, 33, 40, 24, 70, 33, 81, 25, 112, 33, 13, 50, 24, + 42, 55, 50, 66, 42, 97, 50, 108, 42, 9, 59, 20, 51, 51, 59, + 62, 51, 93, 59, 104, 51, 2, 16, 26, 7, 44, 16, 64, 7, 86, + 16, 102, 7, 1, 24, 29, 33, 40, 25, 71, 33, 82, 25, 113, 33, + 14, 50, 25, 42, 56, 50, 67, 42, 98, 50, 109, 42, 10, 59, 21, + 51, 52, 59, 63, 51, 94, 59, 105, 51, 3, 16, 25, 7, 45, 16, + 63, 7, 87, 16, 101, 7, 0, 24, 30, 33, 41, 25, 72, 33, 83, + 25, 114, 33, 15, 50, 26, 42, 57, 50, 68, 42, 99, 50, 110, 42, + 11, 59, 22, 51, 53, 59, 64, 51, 95, 59, 106, 51, 4, 16, 24, + 7, 46, 16, 62, 7, 88, 16, 100, 7, 0, 25, 31, 33, 42, 25, + 73, 33, 84, 25, 115, 33, 16, 50, 27, 42, 58, 50, 69, 42, 80, + 34, 111, 42, 12, 59, 23, 51, 54, 59, 65, 51, 96, 59, 107, 51, + 5, 16, 23, 7, 47, 16, 61, 7, 89, 16, 100, 8, 1, 25, 32, + 33, 43, 25, 74, 33, 85, 25, 116, 33, 17, 50, 28, 42, 59, 50, + 70, 42, 81, 34, 112, 42, 13, 59, 24, 51, 55, 59, 66, 51, 97, + 59, 108, 51, 6, 16, 22, 7, 48, 16, 60, 7, 90, 16, 101, 8, + 2, 25, 33, 33, 44, 25, 75, 33, 86, 25, 117, 33, 18, 50, 29, + 42, 40, 34, 71, 42, 82, 34, 113, 42, 14, 59, 25, 51, 56, 59, + 67, 51, 98, 59, 109, 51, 7, 16, 21, 7, 49, 16, 60, 8, 91, + 16, 102, 8, 3, 25, 34, 33, 45, 25, 76, 33, 87, 25, 118, 33, + 19, 50, 30, 42, 41, 34, 72, 42, 83, 34, 114, 42, 15, 59, 26, + 51, 57, 59, 68, 51, 99, 59, 110, 51, 8, 16, 20, 7, 50, 16, + 61, 8, 92, 16, 103, 8, 4, 25, 35, 33, 46, 25, 77, 33, 88, + 25, 119, 33, 0, 34, 31, 42, 42, 34, 73, 42, 84, 34, 115, 42, + 16, 59, 27, 51, 58, 59, 69, 51, 99, 60, 111, 51, 9, 16, 20, + 8, 51, 16, 62, 8, 93, 16, 104, 8, 5, 25, 36, 33, 47, 25, + 78, 33, 89, 25, 100, 17, 1, 34, 32, 42, 43, 34, 74, 42, 85, + 34, 116, 42, 17, 59, 28, 51, 59, 59, 70, 51, 98, 60, 112, 51, + 10, 16, 21, 8, 52, 16, 63, 8, 94, 16, 105, 8, 6, 25, 37, + 33, 48, 25, 79, 33, 90, 25, 101, 17, 2, 34, 33, 42, 44, 34, + 75, 42, 86, 34, 117, 42, 18, 59, 29, 51, 59, 60, 71, 51, 97, + 60, 113, 51, 11, 16, 22, 8, 53, 16, 64, 8, 95, 16, 106, 8, + 7, 25, 38, 33, 49, 25, 60, 17, 91, 25, 102, 17, 3, 34, 34, + 42, 45, 34, 76, 42, 87, 34, 118, 42, 19, 59, 30, 51, 58, 60, + 72, 51, 96, 60, 114, 51, 12, 16, 23, 8, 54, 16, 65, 8, 96, + 16, 107, 8, 8, 25, 39, 33, 50, 25, 61, 17, 92, 25, 103, 17, + 4, 34, 35, 42, 46, 34, 77, 42, 88, 34, 119, 42, 19, 60, 31, + 51, 57, 60, 73, 51, 95, 60, 115, 51, 13, 16, 24, 8, 55, 16, + 66, 8, 97, 16, 108, 8, 9, 25, 20, 17, 51, 25, 62, 17, 93, + 25, 104, 17, 5, 34, 36, 42, 47, 34, 78, 42, 89, 34, 119, 43, + 18, 60, 32, 51, 56, 60, 74, 51, 94, 60, 116, 51, 14, 16, 25, + 8, 56, 16, 67, 8, 98, 16, 109, 8, 10, 25, 21, 17, 52, 25, + 63, 17, 94, 25, 105, 17, 6, 34, 37, 42, 48, 34, 79, 42, 90, + 34, 118, 43, 17, 60, 33, 51, 55, 60, 75, 51, 93, 60, 117, 51, + 15, 16, 26, 8, 57, 16, 68, 8, 99, 16, 110, 8, 11, 25, 22, + 17, 53, 25, 64, 17, 95, 25, 106, 17, 7, 34, 38, 42, 49, 34, + 79, 43, 91, 34, 117, 43, 16, 60, 34, 51, 54, 60, 76, 51, 92, + 60, 118, 51, 16, 16, 27, 8, 58, 16, 69, 8, 80, 0, 111, 8, + 12, 25, 23, 17, 54, 25, 65, 17, 96, 25, 107, 17, 8, 34, 39, + 42, 50, 34, 78, 43, 92, 34, 116, 43, 15, 60, 35, 51, 53, 60, + 77, 51, 91, 60, 119, 51, 17, 16, 28, 8, 59, 16, 70, 8, 81, + 0, 112, 8, 13, 25, 24, 17, 55, 25, 66, 17, 97, 25, 108, 17, + 9, 34, 39, 43, 51, 34, 77, 43, 93, 34, 115, 43, 14, 60, 36, + 51, 52, 60, 78, 51, 90, 60, 119, 52, 18, 16, 29, 8, 40, 0, + 71, 8, 82, 0, 113, 8, 14, 25, 25, 17, 56, 25, 67, 17, 98, + 25, 109, 17, 10, 34, 38, 43, 52, 34, 76, 43, 94, 34, 114, 43, + 13, 60, 37, 51, 51, 60, 79, 51, 89, 60, 118, 52, 19, 16, 30, + 8, 41, 0, 72, 8, 83, 0, 114, 8, 15, 25, 26, 17, 57, 25, + 68, 17, 99, 25, 110, 17, 11, 34, 37, 43, 53, 34, 75, 43, 95, + 34, 113, 43, 12, 60, 38, 51, 50, 60, 79, 52, 88, 60, 117, 52, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint8_t hq_tab_09[] = { + 0, 0, 10, 3, 18, 0, 24, 3, 36, 0, 1, 10, 14, 6, 19, + 10, 31, 7, 37, 10, 5, 13, 15, 16, 19, 13, 30, 17, 33, 13, + 4, 23, 8, 20, 18, 23, 26, 20, 32, 23, 4, 26, 9, 24, 22, + 26, 27, 24, 39, 27, 1, 0, 9, 3, 19, 0, 24, 4, 37, 0, + 2, 10, 15, 6, 20, 10, 30, 7, 38, 10, 4, 13, 15, 17, 18, + 13, 29, 17, 32, 13, 3, 23, 9, 20, 17, 23, 27, 20, 32, 18, + 5, 26, 10, 24, 23, 26, 28, 24, 38, 27, 2, 0, 8, 3, 20, + 0, 25, 4, 38, 0, 3, 10, 15, 7, 21, 10, 29, 7, 39, 10, + 3, 13, 14, 17, 17, 13, 28, 17, 32, 14, 2, 23, 10, 20, 16, + 23, 28, 20, 33, 18, 6, 26, 11, 24, 23, 27, 29, 24, 37, 27, + 3, 0, 8, 4, 21, 0, 26, 4, 39, 0, 4, 10, 14, 7, 22, + 10, 28, 7, 39, 11, 2, 13, 13, 17, 16, 13, 27, 17, 33, 14, + 1, 23, 11, 20, 16, 18, 29, 20, 34, 18, 7, 26, 12, 24, 22, + 27, 30, 24, 36, 27, 4, 0, 9, 4, 22, 0, 27, 4, 39, 1, + 5, 10, 13, 7, 23, 10, 27, 7, 38, 11, 1, 13, 12, 17, 16, + 14, 26, 17, 34, 14, 0, 23, 12, 20, 17, 18, 30, 20, 35, 18, + 7, 27, 13, 24, 21, 27, 31, 24, 35, 27, 5, 0, 10, 4, 23, + 0, 28, 4, 38, 1, 6, 10, 12, 7, 23, 11, 26, 7, 37, 11, + 0, 13, 11, 17, 17, 14, 25, 17, 35, 14, 0, 18, 13, 20, 18, + 18, 31, 20, 36, 18, 6, 27, 14, 24, 20, 27, 31, 25, 34, 27, + 6, 0, 11, 4, 23, 1, 29, 4, 37, 1, 7, 10, 11, 7, 22, + 11, 25, 7, 36, 11, 0, 14, 10, 17, 18, 14, 24, 17, 36, 14, + 1, 18, 14, 20, 19, 18, 31, 21, 37, 18, 5, 27, 15, 24, 19, + 27, 30, 25, 33, 27, 7, 0, 12, 4, 22, 1, 30, 4, 36, 1, + 7, 11, 10, 7, 21, 11, 24, 7, 35, 11, 1, 14, 9, 17, 19, + 14, 24, 12, 37, 14, 2, 18, 15, 20, 20, 18, 30, 21, 38, 18, + 4, 27, 15, 25, 18, 27, 29, 25, 32, 27, 7, 1, 13, 4, 21, + 1, 31, 4, 35, 1, 6, 11, 9, 7, 20, 11, 24, 8, 34, 11, + 2, 14, 8, 17, 20, 14, 25, 12, 38, 14, 3, 18, 15, 21, 21, + 18, 29, 21, 39, 18, 3, 27, 14, 25, 17, 27, 28, 25, 32, 28, + 6, 1, 14, 4, 20, 1, 31, 5, 34, 1, 5, 11, 8, 7, 19, + 11, 25, 8, 33, 11, 3, 14, 8, 12, 21, 14, 26, 12, 39, 14, + 4, 18, 14, 21, 22, 18, 28, 21, 39, 19, 2, 27, 13, 25, 16, + 27, 27, 25, 33, 28, 5, 1, 15, 4, 19, 1, 30, 5, 33, 1, + 4, 11, 8, 8, 18, 11, 26, 8, 32, 11, 4, 14, 9, 12, 22, + 14, 27, 12, 39, 15, 5, 18, 13, 21, 23, 18, 27, 21, 38, 19, + 1, 27, 12, 25, 16, 28, 26, 25, 34, 28, 4, 1, 15, 5, 18, + 1, 29, 5, 32, 1, 3, 11, 9, 8, 17, 11, 27, 8, 32, 6, + 5, 14, 10, 12, 23, 14, 28, 12, 38, 15, 6, 18, 12, 21, 23, + 19, 26, 21, 37, 19, 0, 27, 11, 25, 17, 28, 25, 25, 35, 28, + 3, 1, 14, 5, 17, 1, 28, 5, 32, 2, 2, 11, 10, 8, 16, + 11, 28, 8, 33, 6, 6, 14, 11, 12, 23, 15, 29, 12, 37, 15, + 7, 18, 11, 21, 22, 19, 25, 21, 36, 19, 0, 28, 10, 25, 18, + 28, 24, 25, 36, 28, 2, 1, 13, 5, 16, 1, 27, 5, 33, 2, + 1, 11, 11, 8, 16, 6, 29, 8, 34, 6, 7, 14, 12, 12, 22, + 15, 30, 12, 36, 15, 7, 19, 10, 21, 21, 19, 24, 21, 35, 19, + 1, 28, 9, 25, 19, 28, 24, 26, 37, 28, 1, 1, 12, 5, 16, + 2, 26, 5, 34, 2, 0, 11, 12, 8, 17, 6, 30, 8, 35, 6, + 7, 15, 13, 12, 21, 15, 31, 12, 35, 15, 6, 19, 9, 21, 20, + 19, 24, 22, 34, 19, 2, 28, 8, 25, 20, 28, 25, 26, 38, 28, + 0, 1, 11, 5, 17, 2, 25, 5, 35, 2, 0, 6, 13, 8, 18, + 6, 31, 8, 36, 6, 6, 15, 14, 12, 20, 15, 31, 13, 34, 15, + 5, 19, 8, 21, 19, 19, 25, 22, 33, 19, 3, 28, 8, 26, 21, + 28, 26, 26, 39, 28, 0, 2, 10, 5, 18, 2, 24, 5, 36, 2, + 1, 6, 14, 8, 19, 6, 31, 9, 37, 6, 5, 15, 15, 12, 19, + 15, 30, 13, 33, 15, 4, 19, 8, 22, 18, 19, 26, 22, 32, 19, + 4, 28, 9, 26, 22, 28, 27, 26, 39, 29, 1, 2, 9, 5, 19, + 2, 24, 0, 37, 2, 2, 6, 15, 8, 20, 6, 30, 9, 38, 6, + 4, 15, 15, 13, 18, 15, 29, 13, 32, 15, 3, 19, 9, 22, 17, + 19, 27, 22, 32, 20, 5, 28, 10, 26, 23, 28, 28, 26, 38, 29, + 2, 2, 8, 5, 20, 2, 25, 0, 38, 2, 3, 6, 15, 9, 21, + 6, 29, 9, 39, 6, 3, 15, 14, 13, 17, 15, 28, 13, 32, 16, + 2, 19, 10, 22, 16, 19, 28, 22, 33, 20, 6, 28, 11, 26, 23, + 29, 29, 26, 37, 29, 3, 2, 8, 0, 21, 2, 26, 0, 39, 2, + 4, 6, 14, 9, 22, 6, 28, 9, 39, 7, 2, 15, 13, 13, 16, + 15, 27, 13, 33, 16, 1, 19, 11, 22, 16, 20, 29, 22, 34, 20, + 7, 28, 12, 26, 22, 29, 30, 26, 36, 29, 4, 2, 9, 0, 22, + 2, 27, 0, 39, 3, 5, 6, 13, 9, 23, 6, 27, 9, 38, 7, + 1, 15, 12, 13, 16, 16, 26, 13, 34, 16, 0, 19, 12, 22, 17, + 20, 30, 22, 35, 20, 7, 29, 13, 26, 21, 29, 31, 26, 35, 29, + 5, 2, 10, 0, 23, 2, 28, 0, 38, 3, 6, 6, 12, 9, 23, + 7, 26, 9, 37, 7, 0, 15, 11, 13, 17, 16, 25, 13, 35, 16, + 0, 20, 13, 22, 18, 20, 31, 22, 36, 20, 6, 29, 14, 26, 20, + 29, 31, 27, 34, 29, 6, 2, 11, 0, 23, 3, 29, 0, 37, 3, + 7, 6, 11, 9, 22, 7, 25, 9, 36, 7, 0, 16, 10, 13, 18, + 16, 24, 13, 36, 16, 1, 20, 14, 22, 19, 20, 31, 23, 37, 20, + 5, 29, 15, 26, 19, 29, 30, 27, 33, 29, 7, 2, 12, 0, 22, + 3, 30, 0, 36, 3, 7, 7, 10, 9, 21, 7, 24, 9, 35, 7, + 1, 16, 9, 13, 19, 16, 24, 14, 37, 16, 2, 20, 15, 22, 20, + 20, 30, 23, 38, 20, 4, 29, 15, 27, 18, 29, 29, 27, 32, 29, + 7, 3, 13, 0, 21, 3, 31, 0, 35, 3, 6, 7, 9, 9, 20, + 7, 24, 10, 34, 7, 2, 16, 8, 13, 20, 16, 25, 14, 38, 16, + 3, 20, 15, 23, 21, 20, 29, 23, 39, 20, 3, 29, 14, 27, 17, + 29, 28, 27, 32, 24, 6, 3, 14, 0, 20, 3, 31, 1, 34, 3, + 5, 7, 8, 9, 19, 7, 25, 10, 33, 7, 3, 16, 8, 14, 21, + 16, 26, 14, 39, 16, 4, 20, 14, 23, 22, 20, 28, 23, 39, 21, + 2, 29, 13, 27, 16, 29, 27, 27, 33, 24, 5, 3, 15, 0, 19, + 3, 30, 1, 33, 3, 4, 7, 8, 10, 18, 7, 26, 10, 32, 7, + 4, 16, 9, 14, 22, 16, 27, 14, 39, 17, 5, 20, 13, 23, 23, + 20, 27, 23, 38, 21, 1, 29, 12, 27, 16, 24, 26, 27, 34, 24, + 4, 3, 15, 1, 18, 3, 29, 1, 32, 3, 3, 7, 9, 10, 17, + 7, 27, 10, 32, 8, 5, 16, 10, 14, 23, 16, 28, 14, 38, 17, + 6, 20, 12, 23, 23, 21, 26, 23, 37, 21, 0, 29, 11, 27, 17, + 24, 25, 27, 35, 24, 3, 3, 14, 1, 17, 3, 28, 1, 32, 4, + 2, 7, 10, 10, 16, 7, 28, 10, 33, 8, 6, 16, 11, 14, 23, + 17, 29, 14, 37, 17, 7, 20, 11, 23, 22, 21, 25, 23, 36, 21, + 0, 24, 10, 27, 18, 24, 24, 27, 36, 24, 2, 3, 13, 1, 16, + 3, 27, 1, 33, 4, 1, 7, 11, 10, 16, 8, 29, 10, 34, 8, + 7, 16, 12, 14, 22, 17, 30, 14, 36, 17, 7, 21, 10, 23, 21, + 21, 24, 23, 35, 21, 1, 24, 9, 27, 19, 24, 24, 28, 37, 24, + 1, 3, 12, 1, 16, 4, 26, 1, 34, 4, 0, 7, 12, 10, 17, + 8, 30, 10, 35, 8, 7, 17, 13, 14, 21, 17, 31, 14, 35, 17, + 6, 21, 9, 23, 20, 21, 24, 18, 34, 21, 2, 24, 8, 27, 20, + 24, 25, 28, 38, 24, 0, 3, 11, 1, 17, 4, 25, 1, 35, 4, + 0, 8, 13, 10, 18, 8, 31, 10, 36, 8, 6, 17, 14, 14, 20, + 17, 31, 15, 34, 17, 5, 21, 8, 23, 19, 21, 25, 18, 33, 21, + 3, 24, 8, 28, 21, 24, 26, 28, 39, 24, 0, 4, 10, 1, 18, + 4, 24, 1, 36, 4, 1, 8, 14, 10, 19, 8, 31, 11, 37, 8, + 5, 17, 15, 14, 19, 17, 30, 15, 33, 17, 4, 21, 8, 18, 18, + 21, 26, 18, 32, 21, 4, 24, 9, 28, 22, 24, 27, 28, 39, 25, + 1, 4, 9, 1, 19, 4, 24, 2, 37, 4, 2, 8, 15, 10, 20, + 8, 30, 11, 38, 8, 4, 17, 15, 15, 18, 17, 29, 15, 32, 17, + 3, 21, 9, 18, 17, 21, 27, 18, 32, 22, 5, 24, 10, 28, 23, + 24, 28, 28, 38, 25, 2, 4, 8, 1, 20, 4, 25, 2, 38, 4, + 3, 8, 15, 11, 21, 8, 29, 11, 39, 8, 3, 17, 14, 15, 17, + 17, 28, 15, 32, 12, 2, 21, 10, 18, 16, 21, 28, 18, 33, 22, + 6, 24, 11, 28, 23, 25, 29, 28, 37, 25, 3, 4, 8, 2, 21, + 4, 26, 2, 39, 4, 4, 8, 14, 11, 22, 8, 28, 11, 39, 9, + 2, 17, 13, 15, 16, 17, 27, 15, 33, 12, 1, 21, 11, 18, 16, + 22, 29, 18, 34, 22, 7, 24, 12, 28, 22, 25, 30, 28, 36, 25, + 4, 4, 9, 2, 22, 4, 27, 2, 39, 5, 5, 8, 13, 11, 23, + 8, 27, 11, 38, 9, 1, 17, 12, 15, 16, 12, 26, 15, 34, 12, + 0, 21, 12, 18, 17, 22, 30, 18, 35, 22, 7, 25, 13, 28, 21, + 25, 31, 28, 35, 25, 5, 4, 10, 2, 23, 4, 28, 2, 38, 5, + 6, 8, 12, 11, 23, 9, 26, 11, 37, 9, 0, 17, 11, 15, 17, + 12, 25, 15, 35, 12, 0, 22, 13, 18, 18, 22, 31, 18, 36, 22, + 6, 25, 14, 28, 20, 25, 31, 29, 34, 25, 6, 4, 11, 2, 23, + 5, 29, 2, 37, 5, 7, 8, 11, 11, 22, 9, 25, 11, 36, 9, + 0, 12, 10, 15, 18, 12, 24, 15, 36, 12, 1, 22, 14, 18, 19, + 22, 31, 19, 37, 22, 5, 25, 15, 28, 19, 25, 30, 29, 33, 25, + 7, 4, 12, 2, 22, 5, 30, 2, 36, 5, 7, 9, 10, 11, 21, + 9, 24, 11, 35, 9, 1, 12, 9, 15, 19, 12, 24, 16, 37, 12, + 2, 22, 15, 18, 20, 22, 30, 19, 38, 22, 4, 25, 15, 29, 18, + 25, 29, 29, 32, 25, 7, 5, 13, 2, 21, 5, 31, 2, 35, 5, + 6, 9, 9, 11, 20, 9, 24, 6, 34, 9, 2, 12, 8, 15, 20, + 12, 25, 16, 38, 12, 3, 22, 15, 19, 21, 22, 29, 19, 39, 22, + 3, 25, 14, 29, 17, 25, 28, 29, 32, 26, 6, 5, 14, 2, 20, + 5, 31, 3, 34, 5, 5, 9, 8, 11, 19, 9, 25, 6, 33, 9, + 3, 12, 8, 16, 21, 12, 26, 16, 39, 12, 4, 22, 14, 19, 22, + 22, 28, 19, 39, 23, 2, 25, 13, 29, 16, 25, 27, 29, 33, 26, + 5, 5, 15, 2, 19, 5, 30, 3, 33, 5, 4, 9, 8, 6, 18, + 9, 26, 6, 32, 9, 4, 12, 9, 16, 22, 12, 27, 16, 39, 13, + 5, 22, 13, 19, 23, 22, 27, 19, 38, 23, 1, 25, 12, 29, 16, + 26, 26, 29, 34, 26, 4, 5, 15, 3, 18, 5, 29, 3, 32, 5, + 3, 9, 9, 6, 17, 9, 27, 6, 32, 10, 5, 12, 10, 16, 23, + 12, 28, 16, 38, 13, 6, 22, 12, 19, 23, 23, 26, 19, 37, 23, + 0, 25, 11, 29, 17, 26, 25, 29, 35, 26, 3, 5, 14, 3, 17, + 5, 28, 3, 32, 0, 2, 9, 10, 6, 16, 9, 28, 6, 33, 10, + 6, 12, 11, 16, 23, 13, 29, 16, 37, 13, 7, 22, 11, 19, 22, + 23, 25, 19, 36, 23, 0, 26, 10, 29, 18, 26, 24, 29, 36, 26, + 2, 5, 13, 3, 16, 5, 27, 3, 33, 0, 1, 9, 11, 6, 16, + 10, 29, 6, 34, 10, 7, 12, 12, 16, 22, 13, 30, 16, 36, 13, + 7, 23, 10, 19, 21, 23, 24, 19, 35, 23, 1, 26, 9, 29, 19, + 26, 24, 24, 37, 26, 1, 5, 12, 3, 16, 0, 26, 3, 34, 0, + 0, 9, 12, 6, 17, 10, 30, 6, 35, 10, 7, 13, 13, 16, 21, + 13, 31, 16, 35, 13, 6, 23, 9, 19, 20, 23, 24, 20, 34, 23, + 2, 26, 8, 29, 20, 26, 25, 24, 38, 26, 0, 5, 11, 3, 17, + 0, 25, 3, 35, 0, 0, 10, 13, 6, 18, 10, 31, 6, 36, 10, + 6, 13, 14, 16, 20, 13, 31, 17, 34, 13, 5, 23, 8, 19, 19, + 23, 25, 20, 33, 23, 3, 26, 8, 24, 21, 26, 26, 24, 39, 26, +}; + +static const uint8_t hq_tab_10[] = { + 0, 0, 4, 1, 10, 0, 13, 2, 19, 1, 0, 5, 6, 4, 10, + 3, 15, 5, 16, 3, 2, 8, 6, 7, 8, 6, 12, 7, 18, 6, + 2, 11, 4, 10, 8, 11, 14, 10, 18, 9, 0, 14, 7, 12, 10, + 14, 14, 13, 16, 12, 1, 0, 4, 2, 11, 0, 14, 2, 18, 1, + 3, 3, 7, 4, 9, 3, 14, 5, 16, 4, 3, 8, 5, 7, 9, + 6, 12, 8, 19, 6, 1, 11, 5, 10, 11, 9, 15, 10, 17, 9, + 1, 14, 7, 13, 11, 14, 13, 13, 17, 12, 2, 0, 5, 2, 11, + 1, 15, 2, 17, 1, 2, 3, 7, 5, 8, 3, 13, 5, 17, 4, + 0, 6, 4, 7, 10, 6, 13, 8, 19, 7, 0, 11, 6, 10, 10, + 9, 15, 11, 16, 9, 2, 14, 6, 13, 8, 12, 12, 13, 18, 12, + 3, 0, 6, 2, 10, 1, 12, 0, 16, 1, 1, 3, 6, 5, 8, + 4, 12, 5, 18, 4, 1, 6, 4, 8, 11, 6, 14, 8, 18, 7, + 3, 9, 7, 10, 9, 9, 14, 11, 16, 10, 3, 14, 5, 13, 9, + 12, 12, 14, 19, 12, 3, 1, 7, 2, 9, 1, 13, 0, 16, 2, + 0, 3, 5, 5, 9, 4, 15, 3, 19, 4, 2, 6, 5, 8, 11, + 7, 15, 8, 17, 7, 2, 9, 7, 11, 8, 9, 13, 11, 17, 10, + 0, 12, 4, 13, 10, 12, 13, 14, 19, 13, 2, 1, 4, 0, 8, + 1, 14, 0, 17, 2, 0, 4, 4, 5, 10, 4, 14, 3, 19, 5, + 3, 6, 6, 8, 10, 7, 12, 6, 16, 7, 1, 9, 6, 11, 8, + 10, 12, 11, 18, 10, 1, 12, 4, 14, 11, 12, 14, 14, 18, 13, + 1, 1, 5, 0, 8, 2, 15, 0, 18, 2, 1, 4, 7, 3, 11, + 4, 13, 3, 18, 5, 3, 7, 7, 8, 9, 7, 13, 6, 16, 8, + 0, 9, 5, 11, 9, 10, 15, 9, 19, 10, 2, 12, 5, 14, 11, + 13, 15, 14, 17, 13, 0, 1, 6, 0, 9, 2, 15, 1, 19, 2, + 2, 4, 6, 3, 11, 5, 12, 3, 17, 5, 2, 7, 4, 6, 8, + 7, 14, 6, 17, 8, 0, 10, 4, 11, 10, 10, 14, 9, 19, 11, + 3, 12, 6, 14, 10, 13, 12, 12, 16, 13, 0, 2, 7, 0, 10, + 2, 14, 1, 16, 0, 3, 4, 5, 3, 10, 5, 12, 4, 16, 5, + 1, 7, 5, 6, 8, 8, 15, 6, 18, 8, 1, 10, 7, 9, 11, + 10, 13, 9, 18, 11, 3, 13, 7, 14, 9, 13, 13, 12, 16, 14, + 1, 2, 7, 1, 11, 2, 13, 1, 17, 0, 3, 5, 4, 3, 9, + 5, 13, 4, 19, 3, 0, 7, 6, 6, 9, 8, 15, 7, 19, 8, + 2, 10, 6, 9, 11, 11, 12, 9, 17, 11, 2, 13, 4, 12, 8, + 13, 14, 12, 17, 14, 2, 2, 6, 1, 8, 0, 12, 1, 18, 0, + 2, 5, 4, 4, 8, 5, 14, 4, 18, 3, 0, 8, 7, 6, 10, + 8, 14, 7, 16, 6, 3, 10, 5, 9, 10, 11, 12, 10, 16, 11, + 1, 13, 5, 12, 8, 14, 15, 12, 18, 14, 3, 2, 5, 1, 9, + 0, 12, 2, 19, 0, 1, 5, 5, 4, 11, 3, 15, 4, 17, 3, + 1, 8, 7, 7, 11, 8, 13, 7, 17, 6, 3, 11, 4, 9, 9, + 11, 13, 10, 19, 9, 0, 13, 6, 12, 9, 14, 15, 13, 19, 14, +}; + +static const uint8_t hq_tab_11[] = { + 0, 0, 3, 3, 5, 1, 6, 0, 8, 2, 1, 5, 3, 7, 4, + 6, 6, 4, 9, 7, 1, 0, 2, 3, 4, 1, 7, 0, 9, 2, + 0, 5, 2, 7, 5, 6, 7, 4, 8, 7, 1, 1, 2, 0, 4, + 2, 7, 1, 9, 3, 0, 6, 2, 4, 5, 7, 7, 5, 8, 4, + 0, 1, 3, 0, 5, 2, 6, 1, 8, 3, 1, 6, 3, 4, 4, + 7, 6, 5, 9, 4, 0, 2, 3, 1, 5, 3, 6, 2, 8, 0, + 1, 7, 3, 5, 4, 4, 6, 6, 9, 5, 1, 2, 2, 1, 4, + 3, 7, 2, 9, 0, 0, 7, 2, 5, 5, 4, 7, 6, 8, 5, + 1, 3, 2, 2, 4, 0, 7, 3, 9, 1, 0, 4, 2, 6, 5, + 5, 7, 7, 8, 6, 0, 3, 3, 2, 5, 0, 6, 3, 8, 1, + 1, 4, 3, 6, 4, 5, 6, 7, 9, 6, +}; + +static const uint8_t hq_tab_12[] = { + 0, 0, 13, 3, 22, 0, 31, 3, 44, 0, 3, 11, 12, 8, 21, + 11, 34, 8, 40, 12, 2, 16, 11, 19, 24, 16, 30, 20, 46, 16, + 1, 27, 14, 24, 20, 28, 36, 24, 42, 28, 4, 32, 10, 36, 26, + 32, 32, 36, 48, 32, 1, 0, 12, 3, 23, 0, 30, 3, 45, 0, + 2, 11, 13, 8, 20, 11, 35, 8, 41, 12, 3, 16, 10, 19, 25, + 16, 31, 20, 47, 16, 0, 27, 15, 24, 21, 28, 37, 24, 43, 28, + 5, 32, 11, 36, 27, 32, 33, 36, 49, 32, 2, 0, 11, 3, 24, + 0, 30, 4, 46, 0, 1, 11, 14, 8, 20, 12, 36, 8, 42, 12, + 4, 16, 10, 20, 26, 16, 32, 20, 48, 16, 0, 28, 16, 24, 22, + 28, 38, 24, 44, 28, 6, 32, 12, 36, 28, 32, 34, 36, 49, 33, + 3, 0, 10, 3, 25, 0, 31, 4, 47, 0, 0, 11, 15, 8, 21, + 12, 37, 8, 43, 12, 5, 16, 11, 20, 27, 16, 33, 20, 49, 16, + 1, 28, 17, 24, 23, 28, 39, 24, 45, 28, 7, 32, 13, 36, 29, + 32, 35, 36, 48, 33, 4, 0, 10, 4, 26, 0, 32, 4, 48, 0, + 0, 12, 16, 8, 22, 12, 38, 8, 44, 12, 6, 16, 12, 20, 28, + 16, 34, 20, 49, 17, 2, 28, 18, 24, 24, 28, 39, 25, 46, 28, + 8, 32, 14, 36, 29, 33, 36, 36, 47, 33, 5, 0, 11, 4, 27, + 0, 33, 4, 49, 0, 1, 12, 17, 8, 23, 12, 39, 8, 45, 12, + 7, 16, 13, 20, 29, 16, 35, 20, 48, 17, 3, 28, 19, 24, 25, + 28, 38, 25, 47, 28, 9, 32, 15, 36, 28, 33, 37, 36, 46, 33, + 6, 0, 12, 4, 28, 0, 34, 4, 49, 1, 2, 12, 18, 8, 24, + 12, 39, 9, 46, 12, 8, 16, 14, 20, 29, 17, 36, 20, 47, 17, + 4, 28, 19, 25, 26, 28, 37, 25, 48, 28, 9, 33, 16, 36, 27, + 33, 38, 36, 45, 33, 7, 0, 13, 4, 29, 0, 35, 4, 48, 1, + 3, 12, 19, 8, 25, 12, 38, 9, 47, 12, 9, 16, 15, 20, 28, + 17, 37, 20, 46, 17, 5, 28, 18, 25, 27, 28, 36, 25, 49, 28, + 8, 33, 17, 36, 26, 33, 39, 36, 44, 33, 8, 0, 14, 4, 29, + 1, 36, 4, 47, 1, 4, 12, 19, 9, 26, 12, 37, 9, 48, 12, + 9, 17, 16, 20, 27, 17, 38, 20, 45, 17, 6, 28, 17, 25, 28, + 28, 35, 25, 49, 29, 7, 33, 18, 36, 25, 33, 39, 37, 43, 33, + 9, 0, 15, 4, 28, 1, 37, 4, 46, 1, 5, 12, 18, 9, 27, + 12, 36, 9, 49, 12, 8, 17, 17, 20, 26, 17, 39, 20, 44, 17, + 7, 28, 16, 25, 29, 28, 34, 25, 48, 29, 6, 33, 19, 36, 24, + 33, 38, 37, 42, 33, 9, 1, 16, 4, 27, 1, 38, 4, 45, 1, + 6, 12, 17, 9, 28, 12, 35, 9, 49, 13, 7, 17, 18, 20, 25, + 17, 39, 21, 43, 17, 8, 28, 15, 25, 29, 29, 33, 25, 47, 29, + 5, 33, 19, 37, 23, 33, 37, 37, 41, 33, 8, 1, 17, 4, 26, + 1, 39, 4, 44, 1, 7, 12, 16, 9, 29, 12, 34, 9, 48, 13, + 6, 17, 19, 20, 24, 17, 38, 21, 42, 17, 9, 28, 14, 25, 28, + 29, 32, 25, 46, 29, 4, 33, 18, 37, 22, 33, 36, 37, 40, 33, + 7, 1, 18, 4, 25, 1, 39, 5, 43, 1, 8, 12, 15, 9, 29, + 13, 33, 9, 47, 13, 5, 17, 19, 21, 23, 17, 37, 21, 41, 17, + 9, 29, 13, 25, 27, 29, 31, 25, 45, 29, 3, 33, 17, 37, 21, + 33, 35, 37, 40, 34, 6, 1, 19, 4, 24, 1, 38, 5, 42, 1, + 9, 12, 14, 9, 28, 13, 32, 9, 46, 13, 4, 17, 18, 21, 22, + 17, 36, 21, 40, 17, 8, 29, 12, 25, 26, 29, 30, 25, 44, 29, + 2, 33, 16, 37, 20, 33, 34, 37, 41, 34, 5, 1, 19, 5, 23, + 1, 37, 5, 41, 1, 9, 13, 13, 9, 27, 13, 31, 9, 45, 13, + 3, 17, 17, 21, 21, 17, 35, 21, 40, 18, 7, 29, 11, 25, 25, + 29, 30, 26, 43, 29, 1, 33, 15, 37, 20, 34, 33, 37, 42, 34, + 4, 1, 18, 5, 22, 1, 36, 5, 40, 1, 8, 13, 12, 9, 26, + 13, 30, 9, 44, 13, 2, 17, 16, 21, 20, 17, 34, 21, 41, 18, + 6, 29, 10, 25, 24, 29, 31, 26, 42, 29, 0, 33, 14, 37, 21, + 34, 32, 37, 43, 34, 3, 1, 17, 5, 21, 1, 35, 5, 40, 2, + 7, 13, 11, 9, 25, 13, 30, 10, 43, 13, 1, 17, 15, 21, 20, + 18, 33, 21, 42, 18, 5, 29, 10, 26, 23, 29, 32, 26, 41, 29, + 0, 34, 13, 37, 22, 34, 31, 37, 44, 34, 2, 1, 16, 5, 20, + 1, 34, 5, 41, 2, 6, 13, 10, 9, 24, 13, 31, 10, 42, 13, + 0, 17, 14, 21, 21, 18, 32, 21, 43, 18, 4, 29, 11, 26, 22, + 29, 33, 26, 40, 29, 1, 34, 12, 37, 23, 34, 30, 37, 45, 34, + 1, 1, 15, 5, 20, 2, 33, 5, 42, 2, 5, 13, 10, 10, 23, + 13, 32, 10, 41, 13, 0, 18, 13, 21, 22, 18, 31, 21, 44, 18, + 3, 29, 12, 26, 21, 29, 34, 26, 40, 30, 2, 34, 11, 37, 24, + 34, 34, 30, 46, 34, 0, 1, 14, 5, 21, 2, 32, 5, 43, 2, + 4, 13, 11, 10, 22, 13, 33, 10, 40, 13, 1, 18, 12, 21, 23, + 18, 30, 21, 45, 18, 2, 29, 13, 26, 20, 29, 35, 26, 41, 30, + 3, 34, 10, 37, 25, 34, 35, 30, 47, 34, 0, 2, 13, 5, 22, + 2, 31, 5, 44, 2, 3, 13, 12, 10, 21, 13, 34, 10, 40, 14, + 2, 18, 11, 21, 24, 18, 30, 22, 46, 18, 1, 29, 14, 26, 20, + 30, 36, 26, 42, 30, 4, 34, 14, 30, 26, 34, 36, 30, 48, 34, + 1, 2, 12, 5, 23, 2, 30, 5, 45, 2, 2, 13, 13, 10, 20, + 13, 35, 10, 41, 14, 3, 18, 10, 21, 25, 18, 31, 22, 47, 18, + 0, 29, 15, 26, 21, 30, 37, 26, 43, 30, 5, 34, 15, 30, 27, + 34, 37, 30, 49, 34, 2, 2, 11, 5, 24, 2, 30, 6, 46, 2, + 1, 13, 14, 10, 20, 14, 36, 10, 42, 14, 4, 18, 10, 22, 26, + 18, 32, 22, 48, 18, 0, 30, 16, 26, 22, 30, 38, 26, 48, 22, + 6, 34, 16, 30, 28, 34, 38, 30, 49, 35, 3, 2, 10, 5, 25, + 2, 31, 6, 47, 2, 0, 13, 15, 10, 21, 14, 37, 10, 43, 14, + 5, 18, 11, 22, 27, 18, 33, 22, 49, 18, 1, 30, 17, 26, 23, + 30, 39, 26, 49, 22, 7, 34, 17, 30, 29, 34, 39, 30, 48, 35, + 4, 2, 10, 6, 26, 2, 32, 6, 48, 2, 0, 14, 16, 10, 22, + 14, 38, 10, 44, 14, 6, 18, 12, 22, 28, 18, 34, 22, 49, 19, + 2, 30, 18, 26, 28, 22, 39, 27, 49, 23, 8, 34, 18, 30, 29, + 35, 39, 31, 47, 35, 5, 2, 11, 6, 27, 2, 33, 6, 49, 2, + 1, 14, 17, 10, 23, 14, 39, 10, 45, 14, 7, 18, 13, 22, 29, + 18, 35, 22, 48, 19, 3, 30, 19, 26, 29, 22, 38, 27, 48, 23, + 9, 34, 19, 30, 28, 35, 38, 31, 46, 35, 6, 2, 12, 6, 28, + 2, 34, 6, 49, 3, 2, 14, 18, 10, 24, 14, 39, 11, 46, 14, + 8, 18, 14, 22, 29, 19, 36, 22, 47, 19, 8, 22, 19, 27, 29, + 23, 37, 27, 47, 23, 9, 35, 19, 31, 27, 35, 37, 31, 45, 35, + 7, 2, 13, 6, 29, 2, 35, 6, 48, 3, 3, 14, 19, 10, 25, + 14, 38, 11, 47, 14, 9, 18, 15, 22, 28, 19, 37, 22, 46, 19, + 9, 22, 18, 27, 28, 23, 36, 27, 46, 23, 8, 35, 18, 31, 26, + 35, 36, 31, 44, 35, 8, 2, 14, 6, 29, 3, 36, 6, 47, 3, + 4, 14, 19, 11, 26, 14, 37, 11, 48, 14, 9, 19, 16, 22, 27, + 19, 37, 15, 45, 19, 9, 23, 17, 27, 27, 23, 35, 27, 45, 23, + 7, 35, 17, 31, 25, 35, 35, 31, 43, 35, 9, 2, 15, 6, 28, + 3, 37, 6, 46, 3, 5, 14, 18, 11, 27, 14, 36, 11, 49, 14, + 8, 19, 17, 22, 26, 19, 36, 15, 44, 19, 8, 23, 16, 27, 26, + 23, 34, 27, 44, 23, 6, 35, 16, 31, 24, 35, 34, 31, 42, 35, + 9, 3, 16, 6, 27, 3, 38, 6, 45, 3, 6, 14, 17, 11, 28, + 14, 35, 11, 49, 15, 7, 19, 17, 15, 25, 19, 35, 15, 43, 19, + 7, 23, 15, 27, 25, 23, 33, 27, 43, 23, 5, 35, 15, 31, 23, + 35, 33, 31, 41, 35, 8, 3, 17, 6, 26, 3, 39, 6, 44, 3, + 7, 14, 16, 11, 29, 14, 34, 11, 48, 15, 6, 19, 16, 15, 24, + 19, 34, 15, 42, 19, 6, 23, 14, 27, 24, 23, 32, 27, 42, 23, + 4, 35, 14, 31, 22, 35, 32, 31, 40, 35, 7, 3, 18, 6, 25, + 3, 39, 7, 43, 3, 8, 14, 15, 11, 29, 15, 33, 11, 43, 7, + 5, 19, 15, 15, 23, 19, 33, 15, 41, 19, 5, 23, 13, 27, 23, + 23, 31, 27, 41, 23, 3, 35, 13, 31, 21, 35, 31, 31, 40, 36, + 6, 3, 19, 6, 24, 3, 38, 7, 42, 3, 9, 14, 14, 11, 28, + 15, 32, 11, 42, 7, 4, 19, 14, 15, 22, 19, 32, 15, 40, 19, + 4, 23, 12, 27, 22, 23, 30, 27, 40, 23, 2, 35, 12, 31, 20, + 35, 30, 31, 41, 36, 5, 3, 19, 7, 23, 3, 37, 7, 41, 3, + 9, 15, 13, 11, 23, 7, 31, 11, 41, 7, 3, 19, 13, 15, 21, + 19, 31, 15, 40, 20, 3, 23, 11, 27, 21, 23, 30, 28, 40, 24, + 1, 35, 11, 31, 20, 36, 30, 32, 42, 36, 4, 3, 18, 7, 22, + 3, 36, 7, 40, 3, 8, 15, 12, 11, 22, 7, 30, 11, 40, 7, + 2, 19, 12, 15, 20, 19, 30, 15, 41, 20, 2, 23, 10, 27, 20, + 23, 31, 28, 41, 24, 0, 35, 10, 31, 21, 36, 31, 32, 43, 36, + 3, 3, 17, 7, 21, 3, 35, 7, 40, 4, 3, 7, 11, 11, 21, + 7, 30, 12, 40, 8, 1, 19, 11, 15, 20, 20, 30, 16, 42, 20, + 1, 23, 10, 28, 20, 24, 32, 28, 42, 24, 0, 36, 10, 32, 22, + 36, 32, 32, 44, 36, 2, 3, 16, 7, 20, 3, 34, 7, 41, 4, + 2, 7, 10, 11, 20, 7, 31, 12, 41, 8, 0, 19, 10, 15, 21, + 20, 31, 16, 43, 20, 0, 23, 11, 28, 21, 24, 33, 28, 43, 24, + 1, 36, 11, 32, 23, 36, 33, 32, 45, 36, 1, 3, 15, 7, 20, + 4, 30, 0, 42, 4, 1, 7, 10, 12, 20, 8, 32, 12, 42, 8, + 0, 20, 10, 16, 22, 20, 32, 16, 44, 20, 0, 24, 12, 28, 22, + 24, 34, 28, 44, 24, 2, 36, 12, 32, 24, 36, 34, 32, 46, 36, + 0, 3, 14, 7, 21, 4, 31, 0, 43, 4, 0, 7, 11, 12, 21, + 8, 33, 12, 43, 8, 1, 20, 11, 16, 23, 20, 33, 16, 45, 20, + 1, 24, 13, 28, 23, 24, 35, 28, 45, 24, 3, 36, 13, 32, 25, + 36, 35, 32, 47, 36, 0, 4, 10, 0, 22, 4, 32, 0, 44, 4, + 0, 8, 12, 12, 22, 8, 34, 12, 44, 8, 2, 20, 12, 16, 24, + 20, 34, 16, 46, 20, 2, 24, 14, 28, 24, 24, 36, 28, 46, 24, + 4, 36, 14, 32, 26, 36, 36, 32, 48, 36, 1, 4, 11, 0, 23, + 4, 33, 0, 45, 4, 1, 8, 13, 12, 23, 8, 35, 12, 45, 8, + 3, 20, 13, 16, 25, 20, 35, 16, 47, 20, 3, 24, 15, 28, 25, + 24, 37, 28, 47, 24, 5, 36, 15, 32, 27, 36, 37, 32, 49, 36, + 2, 4, 12, 0, 24, 4, 34, 0, 46, 4, 2, 8, 14, 12, 24, + 8, 36, 12, 46, 8, 4, 20, 14, 16, 26, 20, 36, 16, 48, 20, + 4, 24, 16, 28, 26, 24, 38, 28, 48, 24, 6, 36, 16, 32, 28, + 36, 38, 32, 49, 37, 3, 4, 13, 0, 25, 4, 35, 0, 47, 4, + 3, 8, 15, 12, 25, 8, 37, 12, 47, 8, 5, 20, 15, 16, 27, + 20, 37, 16, 49, 20, 5, 24, 17, 28, 27, 24, 39, 28, 49, 24, + 7, 36, 17, 32, 29, 36, 39, 32, 48, 37, 4, 4, 14, 0, 26, + 4, 36, 0, 48, 4, 4, 8, 16, 12, 26, 8, 38, 12, 48, 8, + 6, 20, 16, 16, 28, 20, 38, 16, 49, 21, 6, 24, 18, 28, 28, + 24, 39, 29, 49, 25, 8, 36, 18, 32, 29, 37, 39, 33, 47, 37, + 5, 4, 15, 0, 27, 4, 37, 0, 49, 4, 5, 8, 17, 12, 27, + 8, 39, 12, 49, 8, 7, 20, 17, 16, 29, 20, 39, 16, 48, 21, + 7, 24, 19, 28, 29, 24, 38, 29, 48, 25, 9, 36, 19, 32, 28, + 37, 38, 33, 46, 37, 6, 4, 16, 0, 28, 4, 38, 0, 49, 5, + 6, 8, 18, 12, 28, 8, 39, 13, 49, 9, 8, 20, 18, 16, 29, + 21, 39, 17, 47, 21, 8, 24, 19, 29, 29, 25, 37, 29, 47, 25, + 9, 37, 19, 33, 27, 37, 37, 33, 45, 37, 7, 4, 17, 0, 29, + 4, 39, 0, 48, 5, 7, 8, 19, 12, 29, 8, 38, 13, 48, 9, + 9, 20, 19, 16, 28, 21, 38, 17, 46, 21, 9, 24, 18, 29, 28, + 25, 36, 29, 46, 25, 8, 37, 18, 33, 26, 37, 36, 33, 44, 37, + 8, 4, 18, 0, 29, 5, 39, 1, 47, 5, 8, 8, 19, 13, 29, + 9, 37, 13, 47, 9, 9, 21, 19, 17, 27, 21, 37, 17, 45, 21, + 9, 25, 17, 29, 27, 25, 35, 29, 45, 25, 7, 37, 17, 33, 25, + 37, 35, 33, 43, 37, 9, 4, 19, 0, 28, 5, 38, 1, 46, 5, + 9, 8, 18, 13, 28, 9, 36, 13, 46, 9, 8, 21, 18, 17, 26, + 21, 36, 17, 44, 21, 8, 25, 16, 29, 26, 25, 34, 29, 44, 25, + 6, 37, 16, 33, 24, 37, 34, 33, 42, 37, 9, 5, 19, 1, 27, + 5, 37, 1, 45, 5, 9, 9, 17, 13, 27, 9, 35, 13, 45, 9, + 7, 21, 17, 17, 25, 21, 35, 17, 43, 21, 7, 25, 15, 29, 25, + 25, 33, 29, 43, 25, 5, 37, 15, 33, 23, 37, 33, 33, 41, 37, + 8, 5, 18, 1, 26, 5, 36, 1, 44, 5, 8, 9, 16, 13, 26, + 9, 34, 13, 44, 9, 6, 21, 16, 17, 24, 21, 34, 17, 42, 21, + 6, 25, 14, 29, 24, 25, 32, 29, 42, 25, 4, 37, 14, 33, 22, + 37, 32, 33, 40, 37, 7, 5, 17, 1, 25, 5, 35, 1, 43, 5, + 7, 9, 15, 13, 25, 9, 33, 13, 43, 9, 5, 21, 15, 17, 23, + 21, 33, 17, 41, 21, 5, 25, 13, 29, 23, 25, 31, 29, 41, 25, + 3, 37, 13, 33, 21, 37, 31, 33, 44, 30, 6, 5, 16, 1, 24, + 5, 34, 1, 42, 5, 6, 9, 14, 13, 24, 9, 32, 13, 42, 9, + 4, 21, 14, 17, 22, 21, 32, 17, 40, 21, 4, 25, 12, 29, 22, + 25, 30, 29, 40, 25, 2, 37, 12, 33, 20, 37, 30, 33, 45, 30, + 5, 5, 15, 1, 23, 5, 33, 1, 41, 5, 5, 9, 13, 13, 23, + 9, 31, 13, 41, 9, 3, 21, 13, 17, 21, 21, 31, 17, 40, 22, + 3, 25, 11, 29, 21, 25, 30, 30, 40, 26, 1, 37, 11, 33, 24, + 30, 30, 34, 46, 30, 4, 5, 14, 1, 22, 5, 32, 1, 40, 5, + 4, 9, 12, 13, 22, 9, 30, 13, 40, 9, 2, 21, 12, 17, 20, + 21, 30, 17, 41, 22, 2, 25, 10, 29, 20, 25, 31, 30, 41, 26, + 0, 37, 10, 33, 25, 30, 31, 34, 47, 30, 3, 5, 13, 1, 21, + 5, 31, 1, 40, 6, 3, 9, 11, 13, 21, 9, 30, 14, 40, 10, + 1, 21, 11, 17, 20, 22, 30, 18, 42, 22, 1, 25, 10, 30, 20, + 26, 32, 30, 42, 26, 4, 30, 10, 34, 26, 30, 32, 34, 48, 30, + 2, 5, 12, 1, 20, 5, 30, 1, 41, 6, 2, 9, 10, 13, 20, + 9, 31, 14, 41, 10, 0, 21, 10, 17, 21, 22, 31, 18, 43, 22, + 0, 25, 11, 30, 21, 26, 33, 30, 43, 26, 5, 30, 11, 34, 27, + 30, 33, 34, 49, 30, 1, 5, 11, 1, 20, 6, 30, 2, 42, 6, + 1, 9, 10, 14, 20, 10, 32, 14, 42, 10, 0, 22, 10, 18, 22, + 22, 32, 18, 44, 22, 0, 26, 12, 30, 22, 26, 38, 22, 44, 26, + 6, 30, 12, 34, 28, 30, 34, 34, 49, 31, 0, 5, 10, 1, 21, + 6, 31, 2, 43, 6, 0, 9, 11, 14, 21, 10, 33, 14, 43, 10, + 1, 22, 11, 18, 23, 22, 33, 18, 45, 22, 1, 26, 13, 30, 23, + 26, 39, 22, 45, 26, 7, 30, 13, 34, 29, 30, 35, 34, 48, 31, + 0, 6, 10, 2, 22, 6, 32, 2, 44, 6, 0, 10, 12, 14, 22, + 10, 34, 14, 44, 10, 2, 22, 12, 18, 24, 22, 34, 18, 46, 22, + 2, 26, 18, 22, 24, 26, 39, 23, 46, 26, 8, 30, 14, 34, 29, + 31, 36, 34, 47, 31, 1, 6, 11, 2, 23, 6, 33, 2, 45, 6, + 1, 10, 13, 14, 23, 10, 35, 14, 45, 10, 3, 22, 13, 18, 25, + 22, 35, 18, 47, 22, 3, 26, 19, 22, 25, 26, 38, 23, 47, 26, + 9, 30, 15, 34, 28, 31, 37, 34, 46, 31, 2, 6, 12, 2, 24, + 6, 34, 2, 46, 6, 2, 10, 14, 14, 24, 10, 36, 14, 46, 10, + 4, 22, 14, 18, 26, 22, 36, 18, 47, 15, 4, 26, 19, 23, 26, + 26, 37, 23, 48, 26, 9, 31, 16, 34, 27, 31, 38, 34, 45, 31, + 3, 6, 13, 2, 25, 6, 35, 2, 47, 6, 3, 10, 15, 14, 25, + 10, 37, 14, 47, 10, 5, 22, 15, 18, 27, 22, 37, 18, 46, 15, + 5, 26, 18, 23, 27, 26, 36, 23, 49, 26, 8, 31, 17, 34, 26, + 31, 39, 34, 44, 31, 4, 6, 14, 2, 26, 6, 36, 2, 48, 6, + 4, 10, 16, 14, 26, 10, 38, 14, 48, 10, 6, 22, 16, 18, 27, + 15, 38, 18, 45, 15, 6, 26, 17, 23, 28, 26, 35, 23, 49, 27, + 7, 31, 18, 34, 25, 31, 39, 35, 43, 31, 5, 6, 15, 2, 27, + 6, 37, 2, 49, 6, 5, 10, 17, 14, 27, 10, 39, 14, 49, 10, + 7, 22, 17, 18, 26, 15, 39, 18, 44, 15, 7, 26, 16, 23, 29, + 26, 34, 23, 48, 27, 6, 31, 19, 34, 24, 31, 38, 35, 42, 31, + 6, 6, 16, 2, 28, 6, 38, 2, 49, 7, 6, 10, 18, 14, 28, + 10, 39, 15, 49, 11, 7, 15, 18, 18, 25, 15, 39, 19, 43, 15, + 8, 26, 15, 23, 29, 27, 33, 23, 47, 27, 5, 31, 19, 35, 23, + 31, 37, 35, 41, 31, 7, 6, 17, 2, 29, 6, 39, 2, 48, 7, + 7, 10, 19, 14, 29, 10, 38, 15, 48, 11, 6, 15, 19, 18, 24, + 15, 38, 19, 42, 15, 9, 26, 14, 23, 28, 27, 32, 23, 46, 27, + 4, 31, 18, 35, 22, 31, 36, 35, 40, 31, 8, 6, 18, 2, 29, + 7, 39, 3, 47, 7, 8, 10, 19, 15, 29, 11, 33, 7, 47, 11, + 5, 15, 19, 19, 23, 15, 37, 19, 41, 15, 9, 27, 13, 23, 27, + 27, 31, 23, 45, 27, 3, 31, 17, 35, 21, 31, 35, 35, 40, 32, + 9, 6, 19, 2, 28, 7, 38, 3, 46, 7, 9, 10, 18, 15, 28, + 11, 32, 7, 46, 11, 4, 15, 18, 19, 22, 15, 36, 19, 40, 15, + 8, 27, 12, 23, 26, 27, 30, 23, 44, 27, 2, 31, 16, 35, 20, + 31, 34, 35, 41, 32, 9, 7, 19, 3, 27, 7, 37, 3, 45, 7, + 9, 11, 13, 7, 27, 11, 31, 7, 45, 11, 3, 15, 17, 19, 21, + 15, 35, 19, 40, 16, 7, 27, 11, 23, 25, 27, 30, 24, 43, 27, + 1, 31, 15, 35, 20, 32, 33, 35, 42, 32, 8, 7, 18, 3, 26, + 7, 36, 3, 44, 7, 8, 11, 12, 7, 26, 11, 30, 7, 44, 11, + 2, 15, 16, 19, 20, 15, 34, 19, 41, 16, 6, 27, 10, 23, 24, + 27, 31, 24, 42, 27, 0, 31, 14, 35, 21, 32, 32, 35, 43, 32, + 7, 7, 17, 3, 25, 7, 35, 3, 40, 0, 7, 11, 11, 7, 25, + 11, 30, 8, 43, 11, 1, 15, 15, 19, 20, 16, 33, 19, 42, 16, + 5, 27, 10, 24, 23, 27, 32, 24, 41, 27, 0, 32, 13, 35, 22, + 32, 31, 35, 44, 32, 6, 7, 16, 3, 24, 7, 34, 3, 41, 0, + 6, 11, 10, 7, 24, 11, 31, 8, 42, 11, 0, 15, 14, 19, 21, + 16, 32, 19, 43, 16, 4, 27, 11, 24, 22, 27, 33, 24, 40, 27, + 1, 32, 12, 35, 23, 32, 30, 35, 45, 32, 5, 7, 15, 3, 20, + 0, 33, 3, 42, 0, 5, 11, 10, 8, 23, 11, 32, 8, 41, 11, + 0, 16, 13, 19, 22, 16, 31, 19, 44, 16, 3, 27, 12, 24, 21, + 27, 34, 24, 40, 28, 2, 32, 11, 35, 24, 32, 30, 36, 46, 32, + 4, 7, 14, 3, 21, 0, 32, 3, 43, 0, 4, 11, 11, 8, 22, + 11, 33, 8, 40, 11, 1, 16, 12, 19, 23, 16, 30, 19, 45, 16, + 2, 27, 13, 24, 20, 27, 35, 24, 41, 28, 3, 32, 10, 35, 25, + 32, 31, 36, 47, 32, +}; + +static const uint8_t hq_tab_13[] = { + 0, 0, 15, 1, 7, 4, 18, 3, 4, 6, 11, 7, 10, 11, 14, + 9, 8, 12, 14, 14, 6, 17, 11, 16, 9, 19, 18, 20, 2, 23, + 15, 22, 5, 25, 11, 24, 9, 27, 19, 28, 1, 0, 14, 1, 8, + 4, 17, 3, 5, 6, 11, 8, 9, 11, 13, 9, 9, 12, 15, 14, + 5, 17, 12, 16, 8, 19, 19, 20, 1, 23, 16, 22, 4, 25, 12, + 24, 8, 27, 20, 28, 2, 0, 13, 1, 9, 4, 16, 3, 6, 6, + 12, 8, 8, 11, 12, 9, 10, 12, 16, 14, 4, 17, 13, 16, 7, + 19, 20, 20, 0, 23, 17, 22, 3, 25, 13, 24, 7, 27, 21, 28, + 3, 0, 12, 1, 10, 4, 15, 3, 7, 6, 13, 8, 7, 11, 11, + 9, 10, 13, 17, 14, 3, 17, 14, 16, 6, 19, 21, 20, 10, 21, + 18, 22, 2, 25, 14, 24, 6, 27, 21, 29, 4, 0, 11, 1, 10, + 5, 14, 3, 8, 6, 14, 8, 6, 11, 11, 10, 9, 13, 18, 14, + 2, 17, 15, 16, 5, 19, 11, 18, 9, 21, 19, 22, 1, 25, 15, + 24, 5, 27, 20, 29, 5, 0, 11, 2, 9, 5, 13, 3, 9, 6, + 15, 8, 5, 11, 12, 10, 8, 13, 19, 14, 1, 17, 16, 16, 4, + 19, 12, 18, 8, 21, 20, 22, 0, 25, 16, 24, 4, 27, 19, 29, + 6, 0, 12, 2, 8, 5, 12, 3, 10, 6, 16, 8, 4, 11, 13, + 10, 7, 13, 20, 14, 0, 17, 17, 16, 3, 19, 13, 18, 7, 21, + 21, 22, 0, 26, 17, 24, 3, 27, 18, 29, 7, 0, 13, 2, 7, + 5, 11, 3, 10, 7, 17, 8, 3, 11, 14, 10, 6, 13, 21, 14, + 10, 15, 18, 16, 2, 19, 14, 18, 6, 21, 21, 23, 1, 26, 18, + 24, 2, 27, 17, 29, 8, 0, 14, 2, 6, 5, 11, 4, 9, 7, + 18, 8, 2, 11, 15, 10, 5, 13, 11, 12, 9, 15, 19, 16, 1, + 19, 15, 18, 5, 21, 20, 23, 2, 26, 19, 24, 1, 27, 16, 29, + 9, 0, 15, 2, 5, 5, 12, 4, 8, 7, 19, 8, 1, 11, 16, + 10, 4, 13, 12, 12, 8, 15, 20, 16, 0, 19, 16, 18, 4, 21, + 19, 23, 3, 26, 20, 24, 0, 27, 15, 29, 10, 0, 16, 2, 4, + 5, 13, 4, 7, 7, 20, 8, 0, 11, 17, 10, 3, 13, 13, 12, + 7, 15, 21, 16, 0, 20, 17, 18, 3, 21, 18, 23, 4, 26, 21, + 24, 0, 28, 14, 29, 10, 1, 17, 2, 3, 5, 14, 4, 6, 7, + 21, 8, 10, 9, 18, 10, 2, 13, 14, 12, 6, 15, 21, 17, 1, + 20, 18, 18, 2, 21, 17, 23, 5, 26, 21, 25, 1, 28, 13, 29, + 9, 1, 18, 2, 2, 5, 15, 4, 5, 7, 11, 6, 9, 9, 19, + 10, 1, 13, 15, 12, 5, 15, 20, 17, 2, 20, 19, 18, 1, 21, + 16, 23, 6, 26, 20, 25, 2, 28, 12, 29, 8, 1, 19, 2, 1, + 5, 16, 4, 4, 7, 12, 6, 8, 9, 20, 10, 0, 13, 16, 12, + 4, 15, 19, 17, 3, 20, 20, 18, 0, 21, 15, 23, 7, 26, 19, + 25, 3, 28, 11, 29, 7, 1, 20, 2, 0, 5, 17, 4, 3, 7, + 13, 6, 7, 9, 21, 10, 0, 14, 17, 12, 3, 15, 18, 17, 4, + 20, 21, 18, 0, 22, 14, 23, 8, 26, 18, 25, 4, 28, 21, 27, + 6, 1, 21, 2, 10, 3, 18, 4, 2, 7, 14, 6, 6, 9, 21, + 11, 1, 14, 18, 12, 2, 15, 17, 17, 5, 20, 21, 19, 1, 22, + 13, 23, 9, 26, 17, 25, 5, 28, 20, 27, 5, 1, 11, 0, 9, + 3, 19, 4, 1, 7, 15, 6, 5, 9, 20, 11, 2, 14, 19, 12, + 1, 15, 16, 17, 6, 20, 20, 19, 2, 22, 12, 23, 10, 26, 16, + 25, 6, 28, 19, 27, 4, 1, 12, 0, 8, 3, 20, 4, 0, 7, + 16, 6, 4, 9, 19, 11, 3, 14, 20, 12, 0, 15, 15, 17, 7, + 20, 19, 19, 3, 22, 11, 23, 0, 24, 15, 25, 7, 28, 18, 27, + 3, 1, 13, 0, 7, 3, 21, 4, 0, 8, 17, 6, 3, 9, 18, + 11, 4, 14, 21, 12, 0, 16, 14, 17, 8, 20, 18, 19, 4, 22, + 21, 21, 1, 24, 14, 25, 8, 28, 17, 27, 2, 1, 14, 0, 6, + 3, 21, 5, 1, 8, 18, 6, 2, 9, 17, 11, 5, 14, 21, 13, + 1, 16, 13, 17, 9, 20, 17, 19, 5, 22, 20, 21, 2, 24, 13, + 25, 9, 28, 16, 27, 1, 1, 15, 0, 5, 3, 20, 5, 2, 8, + 19, 6, 1, 9, 16, 11, 6, 14, 20, 13, 2, 16, 12, 17, 10, + 20, 16, 19, 6, 22, 19, 21, 3, 24, 12, 25, 10, 28, 15, 27, + 0, 1, 16, 0, 4, 3, 19, 5, 3, 8, 20, 6, 0, 9, 15, + 11, 7, 14, 19, 13, 3, 16, 11, 17, 0, 18, 15, 19, 7, 22, + 18, 21, 4, 24, 11, 25, 10, 29, 14, 27, 0, 2, 17, 0, 3, + 3, 18, 5, 4, 8, 21, 6, 0, 10, 14, 11, 8, 14, 18, 13, + 4, 16, 21, 15, 1, 18, 14, 19, 8, 22, 17, 21, 5, 24, 11, + 26, 9, 29, 13, 27, 1, 2, 18, 0, 2, 3, 17, 5, 5, 8, + 21, 7, 1, 10, 13, 11, 9, 14, 17, 13, 5, 16, 20, 15, 2, + 18, 13, 19, 9, 22, 16, 21, 6, 24, 12, 26, 8, 29, 12, 27, + 2, 2, 19, 0, 1, 3, 16, 5, 6, 8, 20, 7, 2, 10, 12, + 11, 10, 14, 16, 13, 6, 16, 19, 15, 3, 18, 12, 19, 10, 22, + 15, 21, 7, 24, 13, 26, 7, 29, 11, 27, 3, 2, 20, 0, 0, + 3, 15, 5, 7, 8, 19, 7, 3, 10, 11, 11, 0, 12, 15, 13, + 7, 16, 18, 15, 4, 18, 11, 19, 10, 23, 14, 21, 8, 24, 14, + 26, 6, 29, 11, 28, 4, 2, 21, 0, 0, 4, 14, 5, 8, 8, + 18, 7, 4, 10, 21, 9, 1, 12, 14, 13, 8, 16, 17, 15, 5, + 18, 11, 20, 9, 23, 13, 21, 9, 24, 15, 26, 5, 29, 12, 28, + 5, 2, 21, 1, 1, 4, 13, 5, 9, 8, 17, 7, 5, 10, 20, + 9, 2, 12, 13, 13, 9, 16, 16, 15, 6, 18, 12, 20, 8, 23, + 12, 21, 10, 24, 16, 26, 4, 29, 13, 28, 6, 2, 20, 1, 2, + 4, 12, 5, 10, 8, 16, 7, 6, 10, 19, 9, 3, 12, 12, 13, + 10, 16, 15, 15, 7, 18, 13, 20, 7, 23, 11, 21, 10, 25, 17, + 26, 3, 29, 14, 28, 7, 2, 19, 1, 3, 4, 11, 5, 0, 6, + 15, 7, 7, 10, 18, 9, 4, 12, 11, 13, 10, 17, 14, 15, 8, + 18, 14, 20, 6, 23, 11, 22, 9, 25, 18, 26, 2, 29, 15, 28, + 8, 2, 18, 1, 4, 4, 21, 3, 1, 6, 14, 7, 8, 10, 17, + 9, 5, 12, 11, 14, 9, 17, 13, 15, 9, 18, 15, 20, 5, 23, + 12, 22, 8, 25, 19, 26, 1, 29, 16, 28, 9, 2, 17, 1, 5, + 4, 20, 3, 2, 6, 13, 7, 9, 10, 16, 9, 6, 12, 12, 14, + 8, 17, 12, 15, 10, 18, 16, 20, 4, 23, 13, 22, 7, 25, 20, + 26, 0, 29, 17, 28, 10, 2, 16, 1, 6, 4, 19, 3, 3, 6, + 12, 7, 10, 10, 15, 9, 7, 12, 13, 14, 7, 17, 11, 15, 10, + 19, 17, 20, 3, 23, 14, 22, 6, 25, 21, 26, 10, 27, 18, 28, +}; + +static const uint8_t hq_tab_14[] = { + 0, 0, 17, 0, 0, 2, 14, 1, 9, 3, 14, 3, 9, 5, 19, + 4, 2, 6, 19, 6, 9, 6, 12, 7, 7, 9, 16, 8, 0, 9, + 15, 9, 10, 11, 15, 11, 10, 13, 18, 12, 1, 14, 18, 14, 1, + 0, 18, 0, 1, 2, 13, 1, 8, 3, 13, 3, 8, 5, 20, 4, + 3, 6, 16, 5, 10, 6, 11, 7, 6, 9, 17, 8, 0, 10, 14, + 9, 9, 11, 14, 11, 9, 13, 19, 12, 2, 14, 19, 14, 2, 0, + 19, 0, 2, 2, 12, 1, 7, 3, 12, 3, 7, 5, 21, 4, 4, + 6, 15, 5, 10, 7, 11, 8, 5, 9, 18, 8, 1, 10, 13, 9, + 8, 11, 13, 11, 8, 13, 20, 12, 3, 14, 20, 14, 3, 0, 20, + 0, 3, 2, 11, 1, 6, 3, 11, 3, 6, 5, 21, 5, 5, 6, + 14, 5, 9, 7, 12, 8, 2, 8, 19, 8, 2, 10, 12, 9, 7, + 11, 12, 11, 7, 13, 21, 12, 4, 14, 21, 14, 4, 0, 21, 0, + 4, 2, 11, 2, 5, 3, 11, 4, 1, 4, 20, 5, 6, 6, 13, + 5, 8, 7, 20, 6, 3, 8, 20, 8, 3, 10, 11, 9, 6, 11, + 11, 11, 6, 13, 21, 13, 5, 14, 14, 13, 5, 0, 21, 1, 5, + 2, 12, 2, 4, 3, 19, 2, 2, 4, 19, 5, 7, 6, 12, 5, + 7, 7, 21, 6, 4, 8, 21, 8, 4, 10, 11, 10, 5, 11, 11, + 12, 5, 13, 20, 13, 6, 14, 13, 13, 6, 0, 20, 1, 6, 2, + 13, 2, 3, 3, 20, 2, 3, 4, 18, 5, 8, 6, 11, 5, 6, + 7, 21, 7, 5, 8, 21, 9, 5, 10, 12, 10, 4, 11, 12, 12, + 4, 13, 19, 13, 7, 14, 12, 13, 7, 0, 19, 1, 7, 2, 14, + 2, 2, 3, 21, 2, 4, 4, 17, 5, 5, 5, 11, 6, 5, 7, + 20, 7, 6, 8, 20, 9, 6, 10, 13, 10, 3, 11, 13, 12, 3, + 12, 18, 13, 8, 14, 11, 13, 8, 0, 18, 1, 6, 1, 15, 2, + 1, 3, 21, 3, 5, 4, 12, 4, 4, 5, 12, 6, 4, 7, 19, + 7, 7, 8, 19, 9, 7, 10, 14, 10, 2, 11, 21, 10, 4, 12, + 17, 13, 9, 14, 11, 14, 9, 0, 11, 0, 5, 1, 16, 2, 0, + 3, 20, 3, 6, 4, 13, 4, 3, 5, 13, 6, 3, 7, 18, 7, + 8, 8, 18, 9, 8, 10, 15, 10, 1, 11, 21, 11, 5, 12, 16, + 13, 10, 14, 12, 14, 10, 0, 12, 0, 4, 1, 17, 2, 0, 4, + 19, 3, 7, 4, 14, 4, 2, 5, 14, 6, 2, 7, 17, 7, 9, + 8, 17, 9, 9, 10, 16, 10, 0, 11, 20, 11, 6, 12, 15, 13, + 3, 13, 13, 14, 10, 1, 13, 0, 3, 1, 18, 2, 8, 2, 18, + 3, 8, 4, 15, 4, 1, 5, 15, 6, 1, 7, 16, 7, 10, 8, + 16, 9, 4, 9, 17, 10, 0, 12, 19, 11, 7, 12, 14, 12, 2, + 13, 14, 14, 9, 1, 14, 0, 2, 1, 17, 1, 9, 2, 17, 3, + 9, 4, 16, 4, 0, 5, 16, 6, 0, 7, 15, 7, 10, 9, 13, + 8, 3, 9, 18, 10, 1, 12, 18, 11, 8, 12, 15, 12, 1, 13, + 15, 14, 8, 1, 15, 0, 1, 1, 16, 1, 10, 2, 16, 3, 10, + 4, 17, 4, 0, 6, 17, 6, 0, 8, 14, 7, 9, 9, 14, 8, + 2, 9, 19, 10, 2, 12, 17, 11, 9, 12, 16, 12, 0, 13, 16, + 14, 7, 1, 16, 0, 0, 1, 15, 1, 10, 3, 15, 3, 10, 5, + 18, 4, 1, 6, 18, 6, 1, 8, 13, 7, 8, 9, 15, 8, 1, + 9, 20, 10, 10, 10, 16, 11, 10, 12, 17, 12, 0, 14, 17, 14, +}; + +static const uint8_t hq_tab_15[] = { + 0, 0, 15, 1, 3, 3, 14, 2, 4, 4, 11, 5, 0, 6, 18, + 6, 8, 8, 14, 8, 4, 10, 21, 11, 9, 13, 18, 12, 8, 14, + 17, 15, 5, 17, 21, 17, 1, 0, 14, 1, 2, 3, 15, 2, 5, + 4, 11, 4, 1, 6, 19, 6, 9, 8, 15, 8, 5, 10, 20, 11, + 8, 13, 19, 12, 9, 14, 16, 15, 4, 17, 20, 17, 2, 0, 13, + 1, 1, 3, 16, 2, 6, 4, 12, 4, 2, 6, 20, 6, 10, 8, + 16, 8, 6, 10, 19, 11, 7, 13, 20, 12, 10, 14, 15, 15, 3, + 17, 19, 17, 3, 0, 12, 1, 0, 3, 17, 2, 7, 4, 13, 4, + 3, 6, 21, 6, 10, 9, 17, 8, 7, 10, 18, 11, 6, 13, 21, + 12, 10, 15, 14, 15, 2, 17, 18, 17, 4, 0, 11, 1, 0, 2, + 18, 2, 8, 4, 14, 4, 4, 6, 21, 7, 9, 9, 18, 8, 8, + 10, 17, 11, 5, 13, 21, 13, 9, 15, 13, 15, 1, 17, 17, 17, + 5, 0, 11, 0, 1, 2, 19, 2, 9, 4, 15, 4, 5, 6, 20, + 7, 8, 9, 19, 8, 9, 10, 16, 11, 4, 13, 20, 13, 8, 15, + 12, 15, 0, 17, 16, 17, 6, 0, 12, 0, 2, 2, 20, 2, 10, + 4, 16, 4, 6, 6, 19, 7, 7, 9, 20, 8, 10, 10, 15, 11, + 3, 13, 19, 13, 7, 15, 11, 15, 0, 16, 15, 17, 7, 0, 13, + 0, 3, 2, 21, 2, 10, 5, 17, 4, 7, 6, 18, 7, 6, 9, + 21, 8, 10, 11, 14, 11, 2, 13, 18, 13, 6, 15, 11, 14, 1, + 16, 14, 17, 8, 0, 14, 0, 4, 2, 21, 3, 9, 5, 18, 4, + 8, 6, 17, 7, 5, 9, 21, 9, 9, 11, 13, 11, 1, 13, 17, + 13, 5, 15, 12, 14, 2, 16, 13, 17, 9, 0, 15, 0, 5, 2, + 20, 3, 8, 5, 19, 4, 9, 6, 16, 7, 4, 9, 20, 9, 8, + 11, 12, 11, 0, 13, 16, 13, 4, 15, 13, 14, 3, 16, 12, 17, + 10, 0, 16, 0, 6, 2, 19, 3, 7, 5, 20, 4, 10, 6, 15, + 7, 3, 9, 19, 9, 7, 11, 11, 11, 0, 12, 15, 13, 3, 15, + 14, 14, 4, 16, 11, 17, 10, 1, 17, 0, 7, 2, 18, 3, 6, + 5, 21, 4, 10, 7, 14, 7, 2, 9, 18, 9, 6, 11, 11, 10, + 1, 12, 14, 13, 2, 15, 15, 14, 5, 16, 11, 16, 9, 1, 18, + 0, 8, 2, 17, 3, 5, 5, 21, 5, 9, 7, 13, 7, 1, 9, + 17, 9, 5, 11, 12, 10, 2, 12, 13, 13, 1, 15, 16, 14, 6, + 16, 12, 16, 8, 1, 19, 0, 9, 2, 16, 3, 4, 5, 20, 5, + 8, 7, 12, 7, 0, 9, 16, 9, 4, 11, 13, 10, 3, 12, 12, + 13, 0, 15, 17, 14, 7, 16, 13, 16, 7, 1, 20, 0, 10, 2, + 15, 3, 3, 5, 19, 5, 7, 7, 11, 7, 0, 8, 15, 9, 3, + 11, 14, 10, 4, 12, 11, 13, 0, 14, 18, 14, 8, 16, 14, 16, + 6, 1, 21, 0, 10, 3, 14, 3, 2, 5, 18, 5, 6, 7, 11, + 6, 1, 8, 14, 9, 2, 11, 15, 10, 5, 12, 11, 12, 1, 14, + 19, 14, 9, 16, 15, 16, 5, 1, 21, 1, 9, 3, 13, 3, 1, + 5, 17, 5, 5, 7, 12, 6, 2, 8, 13, 9, 1, 11, 16, 10, + 6, 12, 12, 12, 2, 14, 20, 14, 10, 16, 16, 16, 4, 1, 20, + 1, 8, 3, 12, 3, 0, 5, 16, 5, 4, 7, 13, 6, 3, 8, + 12, 9, 0, 11, 17, 10, 7, 12, 13, 12, 3, 14, 21, 14, 10, + 17, 17, 16, 3, 1, 19, 1, 7, 3, 11, 3, 0, 4, 15, 5, + 3, 7, 14, 6, 4, 8, 11, 9, 0, 10, 18, 10, 8, 12, 14, + 12, 4, 14, 21, 15, 9, 17, 18, 16, 2, 1, 18, 1, 6, 3, + 11, 2, 1, 4, 14, 5, 2, 7, 15, 6, 5, 8, 11, 8, 1, + 10, 19, 10, 9, 12, 15, 12, 5, 14, 20, 15, 8, 17, 19, 16, + 1, 1, 17, 1, 5, 3, 12, 2, 2, 4, 13, 5, 1, 7, 16, + 6, 6, 8, 12, 8, 2, 10, 20, 10, 10, 12, 16, 12, 6, 14, + 19, 15, 7, 17, 20, 16, 0, 1, 16, 1, 4, 3, 13, 2, 3, + 4, 12, 5, 0, 7, 17, 6, 7, 8, 13, 8, 3, 10, 21, 10, + 10, 13, 17, 12, 7, 14, 18, 15, 6, 17, 21, 16, +}; + +static const uint8_t hq_tab_16[] = { + 0, 0, 4, 1, 2, 2, 2, 3, 4, 4, 0, 5, 6, 6, 9, + 7, 8, 8, 1, 0, 3, 1, 3, 2, 1, 3, 5, 4, 10, 5, + 7, 6, 8, 7, 9, 8, 2, 0, 2, 1, 4, 2, 0, 3, 6, + 4, 9, 5, 8, 6, 7, 7, 10, 8, 3, 0, 1, 1, 5, 2, + 10, 3, 7, 4, 8, 5, 9, 6, 6, 7, 0, 8, 4, 0, 0, + 1, 6, 2, 9, 3, 8, 4, 7, 5, 10, 6, 5, 7, 1, 8, + 5, 0, 10, 1, 7, 2, 8, 3, 9, 4, 6, 5, 0, 6, 4, + 7, 2, 8, 6, 0, 9, 1, 8, 2, 7, 3, 10, 4, 5, 5, + 1, 6, 3, 7, 3, 8, 7, 0, 8, 1, 9, 2, 6, 3, 0, + 4, 4, 5, 2, 6, 2, 7, 4, 8, 8, 0, 7, 1, 10, 2, + 5, 3, 1, 4, 3, 5, 3, 6, 1, 7, 5, 8, 9, 0, 6, + 1, 0, 2, 4, 3, 2, 4, 2, 5, 4, 6, 0, 7, 6, 8, + 10, 0, 5, 1, 1, 2, 3, 3, 3, 4, 1, 5, 5, 6, 10, + 7, 7, 8, 0, 0, +}; + +static const uint8_t hq_tab_17[] = { + 0, 0, 25, 8, 34, 0, 59, 8, 68, 0, 13, 24, 22, 16, 47, + 24, 56, 16, 78, 25, 10, 32, 28, 41, 44, 32, 58, 41, 78, 32, + 8, 57, 31, 49, 38, 57, 61, 49, 68, 57, 1, 0, 26, 8, 35, + 0, 60, 8, 69, 0, 14, 24, 23, 16, 47, 25, 57, 16, 77, 25, + 11, 32, 27, 41, 45, 32, 57, 41, 79, 32, 7, 57, 30, 49, 37, + 57, 60, 49, 67, 57, 2, 0, 27, 8, 36, 0, 61, 8, 70, 0, + 15, 24, 24, 16, 46, 25, 58, 16, 76, 25, 12, 32, 26, 41, 46, + 32, 56, 41, 79, 33, 6, 57, 29, 49, 36, 57, 59, 49, 66, 57, + 3, 0, 28, 8, 37, 0, 62, 8, 71, 0, 15, 25, 25, 16, 45, + 25, 59, 16, 75, 25, 13, 32, 25, 41, 47, 32, 55, 41, 78, 33, + 5, 57, 28, 49, 35, 57, 58, 49, 65, 57, 4, 0, 29, 8, 38, + 0, 63, 8, 72, 0, 14, 25, 26, 16, 44, 25, 60, 16, 74, 25, + 14, 32, 24, 41, 47, 33, 54, 41, 77, 33, 4, 57, 27, 49, 34, + 57, 57, 49, 64, 57, 5, 0, 30, 8, 39, 0, 63, 9, 73, 0, + 13, 25, 27, 16, 43, 25, 61, 16, 73, 25, 15, 32, 23, 41, 46, + 33, 53, 41, 76, 33, 3, 57, 26, 49, 33, 57, 56, 49, 64, 58, + 6, 0, 31, 8, 40, 0, 62, 9, 74, 0, 12, 25, 28, 16, 42, + 25, 62, 16, 72, 25, 15, 33, 22, 41, 45, 33, 52, 41, 75, 33, + 2, 57, 25, 49, 32, 57, 55, 49, 65, 58, 7, 0, 31, 9, 41, + 0, 61, 9, 75, 0, 11, 25, 29, 16, 41, 25, 63, 16, 71, 25, + 14, 33, 21, 41, 44, 33, 51, 41, 74, 33, 1, 57, 24, 49, 32, + 58, 54, 49, 66, 58, 8, 0, 30, 9, 42, 0, 60, 9, 76, 0, + 10, 25, 30, 16, 40, 25, 63, 17, 70, 25, 13, 33, 20, 41, 43, + 33, 50, 41, 73, 33, 0, 57, 23, 49, 33, 58, 53, 49, 67, 58, + 9, 0, 29, 9, 43, 0, 59, 9, 77, 0, 9, 25, 31, 16, 39, + 25, 62, 17, 69, 25, 12, 33, 19, 41, 42, 33, 49, 41, 72, 33, + 0, 58, 22, 49, 34, 58, 52, 49, 68, 58, 10, 0, 28, 9, 44, + 0, 58, 9, 78, 0, 8, 25, 31, 17, 38, 25, 61, 17, 68, 25, + 11, 33, 18, 41, 41, 33, 48, 41, 71, 33, 1, 58, 21, 49, 35, + 58, 51, 49, 69, 58, 11, 0, 27, 9, 45, 0, 57, 9, 79, 0, + 7, 25, 30, 17, 37, 25, 60, 17, 67, 25, 10, 33, 17, 41, 40, + 33, 48, 42, 70, 33, 2, 58, 20, 49, 36, 58, 50, 49, 70, 58, + 12, 0, 26, 9, 46, 0, 56, 9, 79, 1, 6, 25, 29, 17, 36, + 25, 59, 17, 66, 25, 9, 33, 16, 41, 39, 33, 49, 42, 69, 33, + 3, 58, 19, 49, 37, 58, 49, 49, 71, 58, 13, 0, 25, 9, 47, + 0, 55, 9, 78, 1, 5, 25, 28, 17, 35, 25, 58, 17, 65, 25, + 8, 33, 16, 42, 38, 33, 50, 42, 68, 33, 4, 58, 18, 49, 38, + 58, 48, 49, 72, 58, 14, 0, 24, 9, 47, 1, 54, 9, 77, 1, + 4, 25, 27, 17, 34, 25, 57, 17, 64, 25, 7, 33, 17, 42, 37, + 33, 51, 42, 67, 33, 5, 58, 17, 49, 39, 58, 48, 50, 73, 58, + 15, 0, 23, 9, 46, 1, 53, 9, 76, 1, 3, 25, 26, 17, 33, + 25, 56, 17, 64, 26, 6, 33, 18, 42, 36, 33, 52, 42, 66, 33, + 6, 58, 16, 49, 40, 58, 49, 50, 74, 58, 15, 1, 22, 9, 45, + 1, 52, 9, 75, 1, 2, 25, 25, 17, 32, 25, 55, 17, 65, 26, + 5, 33, 19, 42, 35, 33, 53, 42, 65, 33, 7, 58, 16, 50, 41, + 58, 50, 50, 75, 58, 14, 1, 21, 9, 44, 1, 51, 9, 74, 1, + 1, 25, 24, 17, 32, 26, 54, 17, 66, 26, 4, 33, 20, 42, 34, + 33, 54, 42, 64, 33, 8, 58, 17, 50, 42, 58, 51, 50, 76, 58, + 13, 1, 20, 9, 43, 1, 50, 9, 73, 1, 0, 25, 23, 17, 33, + 26, 53, 17, 67, 26, 3, 33, 21, 42, 33, 33, 55, 42, 64, 34, + 9, 58, 18, 50, 43, 58, 52, 50, 77, 58, 12, 1, 19, 9, 42, + 1, 49, 9, 72, 1, 0, 26, 22, 17, 34, 26, 52, 17, 68, 26, + 2, 33, 22, 42, 32, 33, 56, 42, 65, 34, 10, 58, 19, 50, 44, + 58, 53, 50, 78, 58, 11, 1, 18, 9, 41, 1, 48, 9, 71, 1, + 1, 26, 21, 17, 35, 26, 51, 17, 69, 26, 1, 33, 23, 42, 32, + 34, 57, 42, 66, 34, 11, 58, 20, 50, 45, 58, 54, 50, 79, 58, + 10, 1, 17, 9, 40, 1, 48, 10, 70, 1, 2, 26, 20, 17, 36, + 26, 50, 17, 70, 26, 0, 33, 24, 42, 33, 34, 58, 42, 67, 34, + 12, 58, 21, 50, 46, 58, 55, 50, 79, 59, 9, 1, 16, 9, 39, + 1, 49, 10, 69, 1, 3, 26, 19, 17, 37, 26, 49, 17, 71, 26, + 0, 34, 25, 42, 34, 34, 59, 42, 68, 34, 13, 58, 22, 50, 47, + 58, 56, 50, 78, 59, 8, 1, 16, 10, 38, 1, 50, 10, 68, 1, + 4, 26, 18, 17, 38, 26, 48, 17, 72, 26, 1, 34, 26, 42, 35, + 34, 60, 42, 69, 34, 14, 58, 23, 50, 47, 59, 57, 50, 77, 59, + 7, 1, 17, 10, 37, 1, 51, 10, 67, 1, 5, 26, 17, 17, 39, + 26, 48, 18, 73, 26, 2, 34, 27, 42, 36, 34, 61, 42, 70, 34, + 15, 58, 24, 50, 46, 59, 58, 50, 76, 59, 6, 1, 18, 10, 36, + 1, 52, 10, 66, 1, 6, 26, 16, 17, 40, 26, 49, 18, 74, 26, + 3, 34, 28, 42, 37, 34, 62, 42, 71, 34, 15, 59, 25, 50, 45, + 59, 59, 50, 75, 59, 5, 1, 19, 10, 35, 1, 53, 10, 65, 1, + 7, 26, 16, 18, 41, 26, 50, 18, 75, 26, 4, 34, 29, 42, 38, + 34, 63, 42, 72, 34, 14, 59, 26, 50, 44, 59, 60, 50, 74, 59, + 4, 1, 20, 10, 34, 1, 54, 10, 64, 1, 8, 26, 17, 18, 42, + 26, 51, 18, 76, 26, 5, 34, 30, 42, 39, 34, 63, 43, 73, 34, + 13, 59, 27, 50, 43, 59, 61, 50, 73, 59, 3, 1, 21, 10, 33, + 1, 55, 10, 64, 2, 9, 26, 18, 18, 43, 26, 52, 18, 77, 26, + 6, 34, 31, 42, 40, 34, 62, 43, 74, 34, 12, 59, 28, 50, 42, + 59, 62, 50, 72, 59, 2, 1, 22, 10, 32, 1, 56, 10, 65, 2, + 10, 26, 19, 18, 44, 26, 53, 18, 78, 26, 7, 34, 31, 43, 41, + 34, 61, 43, 75, 34, 11, 59, 29, 50, 41, 59, 63, 50, 71, 59, + 1, 1, 23, 10, 32, 2, 57, 10, 66, 2, 11, 26, 20, 18, 45, + 26, 54, 18, 79, 26, 8, 34, 30, 43, 42, 34, 60, 43, 76, 34, + 10, 59, 30, 50, 40, 59, 63, 51, 70, 59, 0, 1, 24, 10, 33, + 2, 58, 10, 67, 2, 12, 26, 21, 18, 46, 26, 55, 18, 79, 27, + 9, 34, 29, 43, 43, 34, 59, 43, 77, 34, 9, 59, 31, 50, 39, + 59, 62, 51, 69, 59, 0, 2, 25, 10, 34, 2, 59, 10, 68, 2, + 13, 26, 22, 18, 47, 26, 56, 18, 78, 27, 10, 34, 28, 43, 44, + 34, 58, 43, 78, 34, 8, 59, 31, 51, 38, 59, 61, 51, 68, 59, + 1, 2, 26, 10, 35, 2, 60, 10, 69, 2, 14, 26, 23, 18, 47, + 27, 57, 18, 77, 27, 11, 34, 27, 43, 45, 34, 57, 43, 79, 34, + 7, 59, 30, 51, 37, 59, 60, 51, 67, 59, 2, 2, 27, 10, 36, + 2, 61, 10, 70, 2, 15, 26, 24, 18, 46, 27, 58, 18, 76, 27, + 12, 34, 26, 43, 46, 34, 56, 43, 79, 35, 6, 59, 29, 51, 36, + 59, 59, 51, 66, 59, 3, 2, 28, 10, 37, 2, 62, 10, 71, 2, + 15, 27, 25, 18, 45, 27, 59, 18, 75, 27, 13, 34, 25, 43, 47, + 34, 55, 43, 78, 35, 5, 59, 28, 51, 35, 59, 58, 51, 65, 59, + 4, 2, 29, 10, 38, 2, 63, 10, 72, 2, 14, 27, 26, 18, 44, + 27, 60, 18, 74, 27, 14, 34, 24, 43, 47, 35, 54, 43, 77, 35, + 4, 59, 27, 51, 34, 59, 57, 51, 64, 59, 5, 2, 30, 10, 39, + 2, 63, 11, 73, 2, 13, 27, 27, 18, 43, 27, 61, 18, 73, 27, + 15, 34, 23, 43, 46, 35, 53, 43, 76, 35, 3, 59, 26, 51, 33, + 59, 56, 51, 64, 60, 6, 2, 31, 10, 40, 2, 62, 11, 74, 2, + 12, 27, 28, 18, 42, 27, 62, 18, 72, 27, 15, 35, 22, 43, 45, + 35, 52, 43, 75, 35, 2, 59, 25, 51, 32, 59, 55, 51, 65, 60, + 7, 2, 31, 11, 41, 2, 61, 11, 75, 2, 11, 27, 29, 18, 41, + 27, 63, 18, 71, 27, 14, 35, 21, 43, 44, 35, 51, 43, 74, 35, + 1, 59, 24, 51, 32, 60, 54, 51, 66, 60, 8, 2, 30, 11, 42, + 2, 60, 11, 76, 2, 10, 27, 30, 18, 40, 27, 63, 19, 70, 27, + 13, 35, 20, 43, 43, 35, 50, 43, 73, 35, 0, 59, 23, 51, 33, + 60, 53, 51, 67, 60, 9, 2, 29, 11, 43, 2, 59, 11, 77, 2, + 9, 27, 31, 18, 39, 27, 62, 19, 69, 27, 12, 35, 19, 43, 42, + 35, 49, 43, 72, 35, 0, 60, 22, 51, 34, 60, 52, 51, 68, 60, + 10, 2, 28, 11, 44, 2, 58, 11, 78, 2, 8, 27, 31, 19, 38, + 27, 61, 19, 68, 27, 11, 35, 18, 43, 41, 35, 48, 43, 71, 35, + 1, 60, 21, 51, 35, 60, 51, 51, 69, 60, 11, 2, 27, 11, 45, + 2, 57, 11, 79, 2, 7, 27, 30, 19, 37, 27, 60, 19, 67, 27, + 10, 35, 17, 43, 40, 35, 48, 44, 70, 35, 2, 60, 20, 51, 36, + 60, 50, 51, 70, 60, 12, 2, 26, 11, 46, 2, 56, 11, 79, 3, + 6, 27, 29, 19, 36, 27, 59, 19, 66, 27, 9, 35, 16, 43, 39, + 35, 49, 44, 69, 35, 3, 60, 19, 51, 37, 60, 49, 51, 71, 60, + 13, 2, 25, 11, 47, 2, 55, 11, 78, 3, 5, 27, 28, 19, 35, + 27, 58, 19, 65, 27, 8, 35, 16, 44, 38, 35, 50, 44, 68, 35, + 4, 60, 18, 51, 38, 60, 48, 51, 72, 60, 14, 2, 24, 11, 47, + 3, 54, 11, 77, 3, 4, 27, 27, 19, 34, 27, 57, 19, 64, 27, + 7, 35, 17, 44, 37, 35, 51, 44, 67, 35, 5, 60, 17, 51, 39, + 60, 48, 52, 73, 60, 15, 2, 23, 11, 46, 3, 53, 11, 76, 3, + 3, 27, 26, 19, 33, 27, 56, 19, 64, 28, 6, 35, 18, 44, 36, + 35, 52, 44, 66, 35, 6, 60, 16, 51, 40, 60, 49, 52, 74, 60, + 15, 3, 22, 11, 45, 3, 52, 11, 75, 3, 2, 27, 25, 19, 32, + 27, 55, 19, 65, 28, 5, 35, 19, 44, 35, 35, 53, 44, 65, 35, + 7, 60, 16, 52, 41, 60, 50, 52, 75, 60, 14, 3, 21, 11, 44, + 3, 51, 11, 74, 3, 1, 27, 24, 19, 32, 28, 54, 19, 66, 28, + 4, 35, 20, 44, 34, 35, 54, 44, 64, 35, 8, 60, 17, 52, 42, + 60, 51, 52, 76, 60, 13, 3, 20, 11, 43, 3, 50, 11, 73, 3, + 0, 27, 23, 19, 33, 28, 53, 19, 67, 28, 3, 35, 21, 44, 33, + 35, 55, 44, 64, 36, 9, 60, 18, 52, 43, 60, 52, 52, 77, 60, + 12, 3, 19, 11, 42, 3, 49, 11, 72, 3, 0, 28, 22, 19, 34, + 28, 52, 19, 68, 28, 2, 35, 22, 44, 32, 35, 56, 44, 65, 36, + 10, 60, 19, 52, 44, 60, 53, 52, 78, 60, 11, 3, 18, 11, 41, + 3, 48, 11, 71, 3, 1, 28, 21, 19, 35, 28, 51, 19, 69, 28, + 1, 35, 23, 44, 32, 36, 57, 44, 66, 36, 11, 60, 20, 52, 45, + 60, 54, 52, 79, 60, 10, 3, 17, 11, 40, 3, 48, 12, 70, 3, + 2, 28, 20, 19, 36, 28, 50, 19, 70, 28, 0, 35, 24, 44, 33, + 36, 58, 44, 67, 36, 12, 60, 21, 52, 46, 60, 55, 52, 79, 61, + 9, 3, 16, 11, 39, 3, 49, 12, 69, 3, 3, 28, 19, 19, 37, + 28, 49, 19, 71, 28, 0, 36, 25, 44, 34, 36, 59, 44, 68, 36, + 13, 60, 22, 52, 47, 60, 56, 52, 78, 61, 8, 3, 16, 12, 38, + 3, 50, 12, 68, 3, 4, 28, 18, 19, 38, 28, 48, 19, 72, 28, + 1, 36, 26, 44, 35, 36, 60, 44, 69, 36, 14, 60, 23, 52, 47, + 61, 57, 52, 77, 61, 7, 3, 17, 12, 37, 3, 51, 12, 67, 3, + 5, 28, 17, 19, 39, 28, 48, 20, 73, 28, 2, 36, 27, 44, 36, + 36, 61, 44, 70, 36, 15, 60, 24, 52, 46, 61, 58, 52, 76, 61, + 6, 3, 18, 12, 36, 3, 52, 12, 66, 3, 6, 28, 16, 19, 40, + 28, 49, 20, 74, 28, 3, 36, 28, 44, 37, 36, 62, 44, 71, 36, + 15, 61, 25, 52, 45, 61, 59, 52, 75, 61, 5, 3, 19, 12, 35, + 3, 53, 12, 65, 3, 7, 28, 16, 20, 41, 28, 50, 20, 75, 28, + 4, 36, 29, 44, 38, 36, 63, 44, 72, 36, 14, 61, 26, 52, 44, + 61, 60, 52, 74, 61, 4, 3, 20, 12, 34, 3, 54, 12, 64, 3, + 8, 28, 17, 20, 42, 28, 51, 20, 76, 28, 5, 36, 30, 44, 39, + 36, 63, 45, 73, 36, 13, 61, 27, 52, 43, 61, 61, 52, 73, 61, + 3, 3, 21, 12, 33, 3, 55, 12, 64, 4, 9, 28, 18, 20, 43, + 28, 52, 20, 77, 28, 6, 36, 31, 44, 40, 36, 62, 45, 74, 36, + 12, 61, 28, 52, 42, 61, 62, 52, 72, 61, 2, 3, 22, 12, 32, + 3, 56, 12, 65, 4, 10, 28, 19, 20, 44, 28, 53, 20, 78, 28, + 7, 36, 31, 45, 41, 36, 61, 45, 75, 36, 11, 61, 29, 52, 41, + 61, 63, 52, 71, 61, 1, 3, 23, 12, 32, 4, 57, 12, 66, 4, + 11, 28, 20, 20, 45, 28, 54, 20, 79, 28, 8, 36, 30, 45, 42, + 36, 60, 45, 76, 36, 10, 61, 30, 52, 40, 61, 63, 53, 70, 61, + 0, 3, 24, 12, 33, 4, 58, 12, 67, 4, 12, 28, 21, 20, 46, + 28, 55, 20, 79, 29, 9, 36, 29, 45, 43, 36, 59, 45, 77, 36, + 9, 61, 31, 52, 39, 61, 62, 53, 69, 61, 0, 4, 25, 12, 34, + 4, 59, 12, 68, 4, 13, 28, 22, 20, 47, 28, 56, 20, 78, 29, + 10, 36, 28, 45, 44, 36, 58, 45, 78, 36, 8, 61, 31, 53, 38, + 61, 61, 53, 68, 61, 1, 4, 26, 12, 35, 4, 60, 12, 69, 4, + 14, 28, 23, 20, 47, 29, 57, 20, 77, 29, 11, 36, 27, 45, 45, + 36, 57, 45, 79, 36, 7, 61, 30, 53, 37, 61, 60, 53, 67, 61, + 2, 4, 27, 12, 36, 4, 61, 12, 70, 4, 15, 28, 24, 20, 46, + 29, 58, 20, 76, 29, 12, 36, 26, 45, 46, 36, 56, 45, 79, 37, + 6, 61, 29, 53, 36, 61, 59, 53, 66, 61, 3, 4, 28, 12, 37, + 4, 62, 12, 71, 4, 15, 29, 25, 20, 45, 29, 59, 20, 75, 29, + 13, 36, 25, 45, 47, 36, 55, 45, 78, 37, 5, 61, 28, 53, 35, + 61, 58, 53, 65, 61, 4, 4, 29, 12, 38, 4, 63, 12, 72, 4, + 14, 29, 26, 20, 44, 29, 60, 20, 74, 29, 14, 36, 24, 45, 47, + 37, 54, 45, 77, 37, 4, 61, 27, 53, 34, 61, 57, 53, 64, 61, + 5, 4, 30, 12, 39, 4, 63, 13, 73, 4, 13, 29, 27, 20, 43, + 29, 61, 20, 73, 29, 15, 36, 23, 45, 46, 37, 53, 45, 76, 37, + 3, 61, 26, 53, 33, 61, 56, 53, 64, 62, 6, 4, 31, 12, 40, + 4, 62, 13, 74, 4, 12, 29, 28, 20, 42, 29, 62, 20, 72, 29, + 15, 37, 22, 45, 45, 37, 52, 45, 75, 37, 2, 61, 25, 53, 32, + 61, 55, 53, 65, 62, 7, 4, 31, 13, 41, 4, 61, 13, 75, 4, + 11, 29, 29, 20, 41, 29, 63, 20, 71, 29, 14, 37, 21, 45, 44, + 37, 51, 45, 74, 37, 1, 61, 24, 53, 32, 62, 54, 53, 66, 62, + 8, 4, 30, 13, 42, 4, 60, 13, 76, 4, 10, 29, 30, 20, 40, + 29, 63, 21, 70, 29, 13, 37, 20, 45, 43, 37, 50, 45, 73, 37, + 0, 61, 23, 53, 33, 62, 53, 53, 67, 62, 9, 4, 29, 13, 43, + 4, 59, 13, 77, 4, 9, 29, 31, 20, 39, 29, 62, 21, 69, 29, + 12, 37, 19, 45, 42, 37, 49, 45, 72, 37, 0, 62, 22, 53, 34, + 62, 52, 53, 68, 62, 10, 4, 28, 13, 44, 4, 58, 13, 78, 4, + 8, 29, 31, 21, 38, 29, 61, 21, 68, 29, 11, 37, 18, 45, 41, + 37, 48, 45, 71, 37, 1, 62, 21, 53, 35, 62, 51, 53, 69, 62, + 11, 4, 27, 13, 45, 4, 57, 13, 79, 4, 7, 29, 30, 21, 37, + 29, 60, 21, 67, 29, 10, 37, 17, 45, 40, 37, 48, 46, 70, 37, + 2, 62, 20, 53, 36, 62, 50, 53, 70, 62, 12, 4, 26, 13, 46, + 4, 56, 13, 79, 5, 6, 29, 29, 21, 36, 29, 59, 21, 66, 29, + 9, 37, 16, 45, 39, 37, 49, 46, 69, 37, 3, 62, 19, 53, 37, + 62, 49, 53, 71, 62, 13, 4, 25, 13, 47, 4, 55, 13, 78, 5, + 5, 29, 28, 21, 35, 29, 58, 21, 65, 29, 8, 37, 16, 46, 38, + 37, 50, 46, 68, 37, 4, 62, 18, 53, 38, 62, 48, 53, 72, 62, + 14, 4, 24, 13, 47, 5, 54, 13, 77, 5, 4, 29, 27, 21, 34, + 29, 57, 21, 64, 29, 7, 37, 17, 46, 37, 37, 51, 46, 67, 37, + 5, 62, 17, 53, 39, 62, 48, 54, 73, 62, 15, 4, 23, 13, 46, + 5, 53, 13, 76, 5, 3, 29, 26, 21, 33, 29, 56, 21, 64, 30, + 6, 37, 18, 46, 36, 37, 52, 46, 66, 37, 6, 62, 16, 53, 40, + 62, 49, 54, 74, 62, 15, 5, 22, 13, 45, 5, 52, 13, 75, 5, + 2, 29, 25, 21, 32, 29, 55, 21, 65, 30, 5, 37, 19, 46, 35, + 37, 53, 46, 65, 37, 7, 62, 16, 54, 41, 62, 50, 54, 75, 62, + 14, 5, 21, 13, 44, 5, 51, 13, 74, 5, 1, 29, 24, 21, 32, + 30, 54, 21, 66, 30, 4, 37, 20, 46, 34, 37, 54, 46, 64, 37, + 8, 62, 17, 54, 42, 62, 51, 54, 76, 62, 13, 5, 20, 13, 43, + 5, 50, 13, 73, 5, 0, 29, 23, 21, 33, 30, 53, 21, 67, 30, + 3, 37, 21, 46, 33, 37, 55, 46, 64, 38, 9, 62, 18, 54, 43, + 62, 52, 54, 77, 62, 12, 5, 19, 13, 42, 5, 49, 13, 72, 5, + 0, 30, 22, 21, 34, 30, 52, 21, 68, 30, 2, 37, 22, 46, 32, + 37, 56, 46, 65, 38, 10, 62, 19, 54, 44, 62, 53, 54, 78, 62, + 11, 5, 18, 13, 41, 5, 48, 13, 71, 5, 1, 30, 21, 21, 35, + 30, 51, 21, 69, 30, 1, 37, 23, 46, 32, 38, 57, 46, 66, 38, + 11, 62, 20, 54, 45, 62, 54, 54, 79, 62, 10, 5, 17, 13, 40, + 5, 48, 14, 70, 5, 2, 30, 20, 21, 36, 30, 50, 21, 70, 30, + 0, 37, 24, 46, 33, 38, 58, 46, 67, 38, 12, 62, 21, 54, 46, + 62, 55, 54, 79, 63, 9, 5, 16, 13, 39, 5, 49, 14, 69, 5, + 3, 30, 19, 21, 37, 30, 49, 21, 71, 30, 0, 38, 25, 46, 34, + 38, 59, 46, 68, 38, 13, 62, 22, 54, 47, 62, 56, 54, 78, 63, + 8, 5, 16, 14, 38, 5, 50, 14, 68, 5, 4, 30, 18, 21, 38, + 30, 48, 21, 72, 30, 1, 38, 26, 46, 35, 38, 60, 46, 69, 38, + 14, 62, 23, 54, 47, 63, 57, 54, 77, 63, 7, 5, 17, 14, 37, + 5, 51, 14, 67, 5, 5, 30, 17, 21, 39, 30, 48, 22, 73, 30, + 2, 38, 27, 46, 36, 38, 61, 46, 70, 38, 15, 62, 24, 54, 46, + 63, 58, 54, 76, 63, 6, 5, 18, 14, 36, 5, 52, 14, 66, 5, + 6, 30, 16, 21, 40, 30, 49, 22, 74, 30, 3, 38, 28, 46, 37, + 38, 62, 46, 71, 38, 15, 63, 25, 54, 45, 63, 59, 54, 75, 63, + 5, 5, 19, 14, 35, 5, 53, 14, 65, 5, 7, 30, 16, 22, 41, + 30, 50, 22, 75, 30, 4, 38, 29, 46, 38, 38, 63, 46, 72, 38, + 14, 63, 26, 54, 44, 63, 60, 54, 74, 63, 4, 5, 20, 14, 34, + 5, 54, 14, 64, 5, 8, 30, 17, 22, 42, 30, 51, 22, 76, 30, + 5, 38, 30, 46, 39, 38, 63, 47, 73, 38, 13, 63, 27, 54, 43, + 63, 61, 54, 73, 63, 3, 5, 21, 14, 33, 5, 55, 14, 64, 6, + 9, 30, 18, 22, 43, 30, 52, 22, 77, 30, 6, 38, 31, 46, 40, + 38, 62, 47, 74, 38, 12, 63, 28, 54, 42, 63, 62, 54, 72, 63, + 2, 5, 22, 14, 32, 5, 56, 14, 65, 6, 10, 30, 19, 22, 44, + 30, 53, 22, 78, 30, 7, 38, 31, 47, 41, 38, 61, 47, 75, 38, + 11, 63, 29, 54, 41, 63, 63, 54, 71, 63, 1, 5, 23, 14, 32, + 6, 57, 14, 66, 6, 11, 30, 20, 22, 45, 30, 54, 22, 79, 30, + 8, 38, 30, 47, 42, 38, 60, 47, 76, 38, 10, 63, 30, 54, 40, + 63, 63, 55, 70, 63, 0, 5, 24, 14, 33, 6, 58, 14, 67, 6, + 12, 30, 21, 22, 46, 30, 55, 22, 79, 31, 9, 38, 29, 47, 43, + 38, 59, 47, 77, 38, 9, 63, 31, 54, 39, 63, 62, 55, 69, 63, + 0, 6, 25, 14, 34, 6, 59, 14, 68, 6, 13, 30, 22, 22, 47, + 30, 56, 22, 78, 31, 10, 38, 28, 47, 44, 38, 58, 47, 78, 38, + 8, 63, 31, 55, 38, 63, 61, 55, 68, 63, 1, 6, 26, 14, 35, + 6, 60, 14, 69, 6, 14, 30, 23, 22, 47, 31, 57, 22, 77, 31, + 11, 38, 27, 47, 45, 38, 57, 47, 79, 38, 7, 63, 30, 55, 37, + 63, 60, 55, 67, 63, 2, 6, 27, 14, 36, 6, 61, 14, 70, 6, + 15, 30, 24, 22, 46, 31, 58, 22, 76, 31, 12, 38, 26, 47, 46, + 38, 56, 47, 79, 39, 6, 63, 29, 55, 36, 63, 59, 55, 66, 63, + 3, 6, 28, 14, 37, 6, 62, 14, 71, 6, 15, 31, 25, 22, 45, + 31, 59, 22, 75, 31, 13, 38, 25, 47, 47, 38, 55, 47, 78, 39, + 5, 63, 28, 55, 35, 63, 58, 55, 65, 63, 4, 6, 29, 14, 38, + 6, 63, 14, 72, 6, 14, 31, 26, 22, 44, 31, 60, 22, 74, 31, + 14, 38, 24, 47, 47, 39, 54, 47, 77, 39, 4, 63, 27, 55, 34, + 63, 57, 55, 64, 63, 5, 6, 30, 14, 39, 6, 63, 15, 73, 6, + 13, 31, 27, 22, 43, 31, 61, 22, 73, 31, 15, 38, 23, 47, 46, + 39, 53, 47, 76, 39, 3, 63, 26, 55, 33, 63, 56, 55, 64, 48, + 6, 6, 31, 14, 40, 6, 62, 15, 74, 6, 12, 31, 28, 22, 42, + 31, 62, 22, 72, 31, 15, 39, 22, 47, 45, 39, 52, 47, 75, 39, + 2, 63, 25, 55, 32, 63, 55, 55, 65, 48, 7, 6, 31, 15, 41, + 6, 61, 15, 75, 6, 11, 31, 29, 22, 41, 31, 63, 22, 71, 31, + 14, 39, 21, 47, 44, 39, 51, 47, 74, 39, 1, 63, 24, 55, 32, + 48, 54, 55, 66, 48, 8, 6, 30, 15, 42, 6, 60, 15, 76, 6, + 10, 31, 30, 22, 40, 31, 63, 23, 70, 31, 13, 39, 20, 47, 43, + 39, 50, 47, 73, 39, 0, 63, 23, 55, 33, 48, 53, 55, 67, 48, + 9, 6, 29, 15, 43, 6, 59, 15, 77, 6, 9, 31, 31, 22, 39, + 31, 62, 23, 69, 31, 12, 39, 19, 47, 42, 39, 49, 47, 72, 39, + 0, 48, 22, 55, 34, 48, 52, 55, 68, 48, 10, 6, 28, 15, 44, + 6, 58, 15, 78, 6, 8, 31, 31, 23, 38, 31, 61, 23, 68, 31, + 11, 39, 18, 47, 41, 39, 48, 47, 71, 39, 1, 48, 21, 55, 35, + 48, 51, 55, 69, 48, 11, 6, 27, 15, 45, 6, 57, 15, 79, 6, + 7, 31, 30, 23, 37, 31, 60, 23, 67, 31, 10, 39, 17, 47, 40, + 39, 48, 32, 70, 39, 2, 48, 20, 55, 36, 48, 50, 55, 70, 48, + 12, 6, 26, 15, 46, 6, 56, 15, 79, 7, 6, 31, 29, 23, 36, + 31, 59, 23, 66, 31, 9, 39, 16, 47, 39, 39, 49, 32, 69, 39, + 3, 48, 19, 55, 37, 48, 49, 55, 71, 48, 13, 6, 25, 15, 47, + 6, 55, 15, 78, 7, 5, 31, 28, 23, 35, 31, 58, 23, 65, 31, + 8, 39, 16, 32, 38, 39, 50, 32, 68, 39, 4, 48, 18, 55, 38, + 48, 48, 55, 72, 48, 14, 6, 24, 15, 47, 7, 54, 15, 77, 7, + 4, 31, 27, 23, 34, 31, 57, 23, 64, 31, 7, 39, 17, 32, 37, + 39, 51, 32, 67, 39, 5, 48, 17, 55, 39, 48, 48, 56, 73, 48, + 15, 6, 23, 15, 46, 7, 53, 15, 76, 7, 3, 31, 26, 23, 33, + 31, 56, 23, 64, 16, 6, 39, 18, 32, 36, 39, 52, 32, 66, 39, + 6, 48, 16, 55, 40, 48, 49, 56, 74, 48, 15, 7, 22, 15, 45, + 7, 52, 15, 75, 7, 2, 31, 25, 23, 32, 31, 55, 23, 65, 16, + 5, 39, 19, 32, 35, 39, 53, 32, 65, 39, 7, 48, 16, 56, 41, + 48, 50, 56, 75, 48, 14, 7, 21, 15, 44, 7, 51, 15, 74, 7, + 1, 31, 24, 23, 32, 16, 54, 23, 66, 16, 4, 39, 20, 32, 34, + 39, 54, 32, 64, 39, 8, 48, 17, 56, 42, 48, 51, 56, 76, 48, + 13, 7, 20, 15, 43, 7, 50, 15, 73, 7, 0, 31, 23, 23, 33, + 16, 53, 23, 67, 16, 3, 39, 21, 32, 33, 39, 55, 32, 64, 40, + 9, 48, 18, 56, 43, 48, 52, 56, 77, 48, 12, 7, 19, 15, 42, + 7, 49, 15, 72, 7, 0, 16, 22, 23, 34, 16, 52, 23, 68, 16, + 2, 39, 22, 32, 32, 39, 56, 32, 65, 40, 10, 48, 19, 56, 44, + 48, 53, 56, 78, 48, 11, 7, 18, 15, 41, 7, 48, 15, 71, 7, + 1, 16, 21, 23, 35, 16, 51, 23, 69, 16, 1, 39, 23, 32, 32, + 40, 57, 32, 66, 40, 11, 48, 20, 56, 45, 48, 54, 56, 79, 48, + 10, 7, 17, 15, 40, 7, 48, 0, 70, 7, 2, 16, 20, 23, 36, + 16, 50, 23, 70, 16, 0, 39, 24, 32, 33, 40, 58, 32, 67, 40, + 12, 48, 21, 56, 46, 48, 55, 56, 79, 49, 9, 7, 16, 15, 39, + 7, 49, 0, 69, 7, 3, 16, 19, 23, 37, 16, 49, 23, 71, 16, + 0, 40, 25, 32, 34, 40, 59, 32, 68, 40, 13, 48, 22, 56, 47, + 48, 56, 56, 78, 49, 8, 7, 16, 0, 38, 7, 50, 0, 68, 7, + 4, 16, 18, 23, 38, 16, 48, 23, 72, 16, 1, 40, 26, 32, 35, + 40, 60, 32, 69, 40, 14, 48, 23, 56, 47, 49, 57, 56, 77, 49, + 7, 7, 17, 0, 37, 7, 51, 0, 67, 7, 5, 16, 17, 23, 39, + 16, 48, 24, 73, 16, 2, 40, 27, 32, 36, 40, 61, 32, 70, 40, + 15, 48, 24, 56, 46, 49, 58, 56, 76, 49, 6, 7, 18, 0, 36, + 7, 52, 0, 66, 7, 6, 16, 16, 23, 40, 16, 49, 24, 74, 16, + 3, 40, 28, 32, 37, 40, 62, 32, 71, 40, 15, 49, 25, 56, 45, + 49, 59, 56, 75, 49, 5, 7, 19, 0, 35, 7, 53, 0, 65, 7, + 7, 16, 16, 24, 41, 16, 50, 24, 75, 16, 4, 40, 29, 32, 38, + 40, 63, 32, 72, 40, 14, 49, 26, 56, 44, 49, 60, 56, 74, 49, + 4, 7, 20, 0, 34, 7, 54, 0, 64, 7, 8, 16, 17, 24, 42, + 16, 51, 24, 76, 16, 5, 40, 30, 32, 39, 40, 63, 33, 73, 40, + 13, 49, 27, 56, 43, 49, 61, 56, 73, 49, 3, 7, 21, 0, 33, + 7, 55, 0, 64, 8, 9, 16, 18, 24, 43, 16, 52, 24, 77, 16, + 6, 40, 31, 32, 40, 40, 62, 33, 74, 40, 12, 49, 28, 56, 42, + 49, 62, 56, 72, 49, 2, 7, 22, 0, 32, 7, 56, 0, 65, 8, + 10, 16, 19, 24, 44, 16, 53, 24, 78, 16, 7, 40, 31, 33, 41, + 40, 61, 33, 75, 40, 11, 49, 29, 56, 41, 49, 63, 56, 71, 49, + 1, 7, 23, 0, 32, 8, 57, 0, 66, 8, 11, 16, 20, 24, 45, + 16, 54, 24, 79, 16, 8, 40, 30, 33, 42, 40, 60, 33, 76, 40, + 10, 49, 30, 56, 40, 49, 63, 57, 70, 49, 0, 7, 24, 0, 33, + 8, 58, 0, 67, 8, 12, 16, 21, 24, 46, 16, 55, 24, 79, 17, + 9, 40, 29, 33, 43, 40, 59, 33, 77, 40, 9, 49, 31, 56, 39, + 49, 62, 57, 69, 49, 0, 8, 25, 0, 34, 8, 59, 0, 68, 8, + 13, 16, 22, 24, 47, 16, 56, 24, 78, 17, 10, 40, 28, 33, 44, + 40, 58, 33, 78, 40, 8, 49, 31, 57, 38, 49, 61, 57, 68, 49, + 1, 8, 26, 0, 35, 8, 60, 0, 69, 8, 14, 16, 23, 24, 47, + 17, 57, 24, 77, 17, 11, 40, 27, 33, 45, 40, 57, 33, 79, 40, + 7, 49, 30, 57, 37, 49, 60, 57, 67, 49, 2, 8, 27, 0, 36, + 8, 61, 0, 70, 8, 15, 16, 24, 24, 46, 17, 58, 24, 76, 17, + 12, 40, 26, 33, 46, 40, 56, 33, 79, 41, 6, 49, 29, 57, 36, + 49, 59, 57, 66, 49, 3, 8, 28, 0, 37, 8, 62, 0, 71, 8, + 15, 17, 25, 24, 45, 17, 59, 24, 75, 17, 13, 40, 25, 33, 47, + 40, 55, 33, 78, 41, 5, 49, 28, 57, 35, 49, 58, 57, 65, 49, + 4, 8, 29, 0, 38, 8, 63, 0, 72, 8, 14, 17, 26, 24, 44, + 17, 60, 24, 74, 17, 14, 40, 24, 33, 47, 41, 54, 33, 77, 41, + 4, 49, 27, 57, 34, 49, 57, 57, 64, 49, 5, 8, 30, 0, 39, + 8, 63, 1, 73, 8, 13, 17, 27, 24, 43, 17, 61, 24, 73, 17, + 15, 40, 23, 33, 46, 41, 53, 33, 76, 41, 3, 49, 26, 57, 33, + 49, 56, 57, 64, 50, 6, 8, 31, 0, 40, 8, 62, 1, 74, 8, + 12, 17, 28, 24, 42, 17, 62, 24, 72, 17, 15, 41, 22, 33, 45, + 41, 52, 33, 75, 41, 2, 49, 25, 57, 32, 49, 55, 57, 65, 50, + 7, 8, 31, 1, 41, 8, 61, 1, 75, 8, 11, 17, 29, 24, 41, + 17, 63, 24, 71, 17, 14, 41, 21, 33, 44, 41, 51, 33, 74, 41, + 1, 49, 24, 57, 32, 50, 54, 57, 66, 50, 8, 8, 30, 1, 42, + 8, 60, 1, 76, 8, 10, 17, 30, 24, 40, 17, 63, 25, 70, 17, + 13, 41, 20, 33, 43, 41, 50, 33, 73, 41, 0, 49, 23, 57, 33, + 50, 53, 57, 67, 50, 9, 8, 29, 1, 43, 8, 59, 1, 77, 8, + 9, 17, 31, 24, 39, 17, 62, 25, 69, 17, 12, 41, 19, 33, 42, + 41, 49, 33, 72, 41, 0, 50, 22, 57, 34, 50, 52, 57, 68, 50, + 10, 8, 28, 1, 44, 8, 58, 1, 78, 8, 8, 17, 31, 25, 38, + 17, 61, 25, 68, 17, 11, 41, 18, 33, 41, 41, 48, 33, 71, 41, + 1, 50, 21, 57, 35, 50, 51, 57, 69, 50, 11, 8, 27, 1, 45, + 8, 57, 1, 79, 8, 7, 17, 30, 25, 37, 17, 60, 25, 67, 17, + 10, 41, 17, 33, 40, 41, 48, 34, 70, 41, 2, 50, 20, 57, 36, + 50, 50, 57, 70, 50, 12, 8, 26, 1, 46, 8, 56, 1, 79, 9, + 6, 17, 29, 25, 36, 17, 59, 25, 66, 17, 9, 41, 16, 33, 39, + 41, 49, 34, 69, 41, 3, 50, 19, 57, 37, 50, 49, 57, 71, 50, + 13, 8, 25, 1, 47, 8, 55, 1, 78, 9, 5, 17, 28, 25, 35, + 17, 58, 25, 65, 17, 8, 41, 16, 34, 38, 41, 50, 34, 68, 41, + 4, 50, 18, 57, 38, 50, 48, 57, 72, 50, 14, 8, 24, 1, 47, + 9, 54, 1, 77, 9, 4, 17, 27, 25, 34, 17, 57, 25, 64, 17, + 7, 41, 17, 34, 37, 41, 51, 34, 67, 41, 5, 50, 17, 57, 39, + 50, 48, 58, 73, 50, 15, 8, 23, 1, 46, 9, 53, 1, 76, 9, + 3, 17, 26, 25, 33, 17, 56, 25, 64, 18, 6, 41, 18, 34, 36, + 41, 52, 34, 66, 41, 6, 50, 16, 57, 40, 50, 49, 58, 74, 50, + 15, 9, 22, 1, 45, 9, 52, 1, 75, 9, 2, 17, 25, 25, 32, + 17, 55, 25, 65, 18, 5, 41, 19, 34, 35, 41, 53, 34, 65, 41, + 7, 50, 16, 58, 41, 50, 50, 58, 75, 50, 14, 9, 21, 1, 44, + 9, 51, 1, 74, 9, 1, 17, 24, 25, 32, 18, 54, 25, 66, 18, + 4, 41, 20, 34, 34, 41, 54, 34, 64, 41, 8, 50, 17, 58, 42, + 50, 51, 58, 76, 50, 13, 9, 20, 1, 43, 9, 50, 1, 73, 9, + 0, 17, 23, 25, 33, 18, 53, 25, 67, 18, 3, 41, 21, 34, 33, + 41, 55, 34, 64, 42, 9, 50, 18, 58, 43, 50, 52, 58, 77, 50, + 12, 9, 19, 1, 42, 9, 49, 1, 72, 9, 0, 18, 22, 25, 34, + 18, 52, 25, 68, 18, 2, 41, 22, 34, 32, 41, 56, 34, 65, 42, + 10, 50, 19, 58, 44, 50, 53, 58, 78, 50, 11, 9, 18, 1, 41, + 9, 48, 1, 71, 9, 1, 18, 21, 25, 35, 18, 51, 25, 69, 18, + 1, 41, 23, 34, 32, 42, 57, 34, 66, 42, 11, 50, 20, 58, 45, + 50, 54, 58, 79, 50, 10, 9, 17, 1, 40, 9, 48, 2, 70, 9, + 2, 18, 20, 25, 36, 18, 50, 25, 70, 18, 0, 41, 24, 34, 33, + 42, 58, 34, 67, 42, 12, 50, 21, 58, 46, 50, 55, 58, 79, 51, + 9, 9, 16, 1, 39, 9, 49, 2, 69, 9, 3, 18, 19, 25, 37, + 18, 49, 25, 71, 18, 0, 42, 25, 34, 34, 42, 59, 34, 68, 42, + 13, 50, 22, 58, 47, 50, 56, 58, 78, 51, 8, 9, 16, 2, 38, + 9, 50, 2, 68, 9, 4, 18, 18, 25, 38, 18, 48, 25, 72, 18, + 1, 42, 26, 34, 35, 42, 60, 34, 69, 42, 14, 50, 23, 58, 47, + 51, 57, 58, 77, 51, 7, 9, 17, 2, 37, 9, 51, 2, 67, 9, + 5, 18, 17, 25, 39, 18, 48, 26, 73, 18, 2, 42, 27, 34, 36, + 42, 61, 34, 70, 42, 15, 50, 24, 58, 46, 51, 58, 58, 76, 51, + 6, 9, 18, 2, 36, 9, 52, 2, 66, 9, 6, 18, 16, 25, 40, + 18, 49, 26, 74, 18, 3, 42, 28, 34, 37, 42, 62, 34, 71, 42, + 15, 51, 25, 58, 45, 51, 59, 58, 75, 51, 5, 9, 19, 2, 35, + 9, 53, 2, 65, 9, 7, 18, 16, 26, 41, 18, 50, 26, 75, 18, + 4, 42, 29, 34, 38, 42, 63, 34, 72, 42, 14, 51, 26, 58, 44, + 51, 60, 58, 74, 51, 4, 9, 20, 2, 34, 9, 54, 2, 64, 9, + 8, 18, 17, 26, 42, 18, 51, 26, 76, 18, 5, 42, 30, 34, 39, + 42, 63, 35, 73, 42, 13, 51, 27, 58, 43, 51, 61, 58, 73, 51, + 3, 9, 21, 2, 33, 9, 55, 2, 64, 10, 9, 18, 18, 26, 43, + 18, 52, 26, 77, 18, 6, 42, 31, 34, 40, 42, 62, 35, 74, 42, + 12, 51, 28, 58, 42, 51, 62, 58, 72, 51, 2, 9, 22, 2, 32, + 9, 56, 2, 65, 10, 10, 18, 19, 26, 44, 18, 53, 26, 78, 18, + 7, 42, 31, 35, 41, 42, 61, 35, 75, 42, 11, 51, 29, 58, 41, + 51, 63, 58, 71, 51, 1, 9, 23, 2, 32, 10, 57, 2, 66, 10, + 11, 18, 20, 26, 45, 18, 54, 26, 79, 18, 8, 42, 30, 35, 42, + 42, 60, 35, 76, 42, 10, 51, 30, 58, 40, 51, 63, 59, 70, 51, + 0, 9, 24, 2, 33, 10, 58, 2, 67, 10, 12, 18, 21, 26, 46, + 18, 55, 26, 79, 19, 9, 42, 29, 35, 43, 42, 59, 35, 77, 42, + 9, 51, 31, 58, 39, 51, 62, 59, 69, 51, 0, 10, 25, 2, 34, + 10, 59, 2, 68, 10, 13, 18, 22, 26, 47, 18, 56, 26, 78, 19, + 10, 42, 28, 35, 44, 42, 58, 35, 78, 42, 8, 51, 31, 59, 38, + 51, 61, 59, 68, 51, 1, 10, 26, 2, 35, 10, 60, 2, 69, 10, + 14, 18, 23, 26, 47, 19, 57, 26, 77, 19, 11, 42, 27, 35, 45, + 42, 57, 35, 79, 42, 7, 51, 30, 59, 37, 51, 60, 59, 67, 51, + 2, 10, 27, 2, 36, 10, 61, 2, 70, 10, 15, 18, 24, 26, 46, + 19, 58, 26, 76, 19, 12, 42, 26, 35, 46, 42, 56, 35, 79, 43, + 6, 51, 29, 59, 36, 51, 59, 59, 66, 51, 3, 10, 28, 2, 37, + 10, 62, 2, 71, 10, 15, 19, 25, 26, 45, 19, 59, 26, 75, 19, + 13, 42, 25, 35, 47, 42, 55, 35, 78, 43, 5, 51, 28, 59, 35, + 51, 58, 59, 65, 51, 4, 10, 29, 2, 38, 10, 63, 2, 72, 10, + 14, 19, 26, 26, 44, 19, 60, 26, 74, 19, 14, 42, 24, 35, 47, + 43, 54, 35, 77, 43, 4, 51, 27, 59, 34, 51, 57, 59, 64, 51, + 5, 10, 30, 2, 39, 10, 63, 3, 73, 10, 13, 19, 27, 26, 43, + 19, 61, 26, 73, 19, 15, 42, 23, 35, 46, 43, 53, 35, 76, 43, + 3, 51, 26, 59, 33, 51, 56, 59, 64, 52, 6, 10, 31, 2, 40, + 10, 62, 3, 74, 10, 12, 19, 28, 26, 42, 19, 62, 26, 72, 19, + 15, 43, 22, 35, 45, 43, 52, 35, 75, 43, 2, 51, 25, 59, 32, + 51, 55, 59, 65, 52, 7, 10, 31, 3, 41, 10, 61, 3, 75, 10, + 11, 19, 29, 26, 41, 19, 63, 26, 71, 19, 14, 43, 21, 35, 44, + 43, 51, 35, 74, 43, 1, 51, 24, 59, 32, 52, 54, 59, 66, 52, + 8, 10, 30, 3, 42, 10, 60, 3, 76, 10, 10, 19, 30, 26, 40, + 19, 63, 27, 70, 19, 13, 43, 20, 35, 43, 43, 50, 35, 73, 43, + 0, 51, 23, 59, 33, 52, 53, 59, 67, 52, 9, 10, 29, 3, 43, + 10, 59, 3, 77, 10, 9, 19, 31, 26, 39, 19, 62, 27, 69, 19, + 12, 43, 19, 35, 42, 43, 49, 35, 72, 43, 0, 52, 22, 59, 34, + 52, 52, 59, 68, 52, 10, 10, 28, 3, 44, 10, 58, 3, 78, 10, + 8, 19, 31, 27, 38, 19, 61, 27, 68, 19, 11, 43, 18, 35, 41, + 43, 48, 35, 71, 43, 1, 52, 21, 59, 35, 52, 51, 59, 69, 52, + 11, 10, 27, 3, 45, 10, 57, 3, 79, 10, 7, 19, 30, 27, 37, + 19, 60, 27, 67, 19, 10, 43, 17, 35, 40, 43, 48, 36, 70, 43, + 2, 52, 20, 59, 36, 52, 50, 59, 70, 52, 12, 10, 26, 3, 46, + 10, 56, 3, 79, 11, 6, 19, 29, 27, 36, 19, 59, 27, 66, 19, + 9, 43, 16, 35, 39, 43, 49, 36, 69, 43, 3, 52, 19, 59, 37, + 52, 49, 59, 71, 52, 13, 10, 25, 3, 47, 10, 55, 3, 78, 11, + 5, 19, 28, 27, 35, 19, 58, 27, 65, 19, 8, 43, 16, 36, 38, + 43, 50, 36, 68, 43, 4, 52, 18, 59, 38, 52, 48, 59, 72, 52, + 14, 10, 24, 3, 47, 11, 54, 3, 77, 11, 4, 19, 27, 27, 34, + 19, 57, 27, 64, 19, 7, 43, 17, 36, 37, 43, 51, 36, 67, 43, + 5, 52, 17, 59, 39, 52, 48, 60, 73, 52, 15, 10, 23, 3, 46, + 11, 53, 3, 76, 11, 3, 19, 26, 27, 33, 19, 56, 27, 64, 20, + 6, 43, 18, 36, 36, 43, 52, 36, 66, 43, 6, 52, 16, 59, 40, + 52, 49, 60, 74, 52, 15, 11, 22, 3, 45, 11, 52, 3, 75, 11, + 2, 19, 25, 27, 32, 19, 55, 27, 65, 20, 5, 43, 19, 36, 35, + 43, 53, 36, 65, 43, 7, 52, 16, 60, 41, 52, 50, 60, 75, 52, + 14, 11, 21, 3, 44, 11, 51, 3, 74, 11, 1, 19, 24, 27, 32, + 20, 54, 27, 66, 20, 4, 43, 20, 36, 34, 43, 54, 36, 64, 43, + 8, 52, 17, 60, 42, 52, 51, 60, 76, 52, 13, 11, 20, 3, 43, + 11, 50, 3, 73, 11, 0, 19, 23, 27, 33, 20, 53, 27, 67, 20, + 3, 43, 21, 36, 33, 43, 55, 36, 64, 44, 9, 52, 18, 60, 43, + 52, 52, 60, 77, 52, 12, 11, 19, 3, 42, 11, 49, 3, 72, 11, + 0, 20, 22, 27, 34, 20, 52, 27, 68, 20, 2, 43, 22, 36, 32, + 43, 56, 36, 65, 44, 10, 52, 19, 60, 44, 52, 53, 60, 78, 52, + 11, 11, 18, 3, 41, 11, 48, 3, 71, 11, 1, 20, 21, 27, 35, + 20, 51, 27, 69, 20, 1, 43, 23, 36, 32, 44, 57, 36, 66, 44, + 11, 52, 20, 60, 45, 52, 54, 60, 79, 52, 10, 11, 17, 3, 40, + 11, 48, 4, 70, 11, 2, 20, 20, 27, 36, 20, 50, 27, 70, 20, + 0, 43, 24, 36, 33, 44, 58, 36, 67, 44, 12, 52, 21, 60, 46, + 52, 55, 60, 79, 53, 9, 11, 16, 3, 39, 11, 49, 4, 69, 11, + 3, 20, 19, 27, 37, 20, 49, 27, 71, 20, 0, 44, 25, 36, 34, + 44, 59, 36, 68, 44, 13, 52, 22, 60, 47, 52, 56, 60, 78, 53, + 8, 11, 16, 4, 38, 11, 50, 4, 68, 11, 4, 20, 18, 27, 38, + 20, 48, 27, 72, 20, 1, 44, 26, 36, 35, 44, 60, 36, 69, 44, + 14, 52, 23, 60, 47, 53, 57, 60, 77, 53, 7, 11, 17, 4, 37, + 11, 51, 4, 67, 11, 5, 20, 17, 27, 39, 20, 48, 28, 73, 20, + 2, 44, 27, 36, 36, 44, 61, 36, 70, 44, 15, 52, 24, 60, 46, + 53, 58, 60, 76, 53, 6, 11, 18, 4, 36, 11, 52, 4, 66, 11, + 6, 20, 16, 27, 40, 20, 49, 28, 74, 20, 3, 44, 28, 36, 37, + 44, 62, 36, 71, 44, 15, 53, 25, 60, 45, 53, 59, 60, 75, 53, + 5, 11, 19, 4, 35, 11, 53, 4, 65, 11, 7, 20, 16, 28, 41, + 20, 50, 28, 75, 20, 4, 44, 29, 36, 38, 44, 63, 36, 72, 44, + 14, 53, 26, 60, 44, 53, 60, 60, 74, 53, 4, 11, 20, 4, 34, + 11, 54, 4, 64, 11, 8, 20, 17, 28, 42, 20, 51, 28, 76, 20, + 5, 44, 30, 36, 39, 44, 63, 37, 73, 44, 13, 53, 27, 60, 43, + 53, 61, 60, 73, 53, 3, 11, 21, 4, 33, 11, 55, 4, 64, 12, + 9, 20, 18, 28, 43, 20, 52, 28, 77, 20, 6, 44, 31, 36, 40, + 44, 62, 37, 74, 44, 12, 53, 28, 60, 42, 53, 62, 60, 72, 53, + 2, 11, 22, 4, 32, 11, 56, 4, 65, 12, 10, 20, 19, 28, 44, + 20, 53, 28, 78, 20, 7, 44, 31, 37, 41, 44, 61, 37, 75, 44, + 11, 53, 29, 60, 41, 53, 63, 60, 71, 53, 1, 11, 23, 4, 32, + 12, 57, 4, 66, 12, 11, 20, 20, 28, 45, 20, 54, 28, 79, 20, + 8, 44, 30, 37, 42, 44, 60, 37, 76, 44, 10, 53, 30, 60, 40, + 53, 63, 61, 70, 53, 0, 11, 24, 4, 33, 12, 58, 4, 67, 12, + 12, 20, 21, 28, 46, 20, 55, 28, 79, 21, 9, 44, 29, 37, 43, + 44, 59, 37, 77, 44, 9, 53, 31, 60, 39, 53, 62, 61, 69, 53, + 0, 12, 25, 4, 34, 12, 59, 4, 68, 12, 13, 20, 22, 28, 47, + 20, 56, 28, 78, 21, 10, 44, 28, 37, 44, 44, 58, 37, 78, 44, + 8, 53, 31, 61, 38, 53, 61, 61, 68, 53, 1, 12, 26, 4, 35, + 12, 60, 4, 69, 12, 14, 20, 23, 28, 47, 21, 57, 28, 77, 21, + 11, 44, 27, 37, 45, 44, 57, 37, 79, 44, 7, 53, 30, 61, 37, + 53, 60, 61, 67, 53, 2, 12, 27, 4, 36, 12, 61, 4, 70, 12, + 15, 20, 24, 28, 46, 21, 58, 28, 76, 21, 12, 44, 26, 37, 46, + 44, 56, 37, 79, 45, 6, 53, 29, 61, 36, 53, 59, 61, 66, 53, + 3, 12, 28, 4, 37, 12, 62, 4, 71, 12, 15, 21, 25, 28, 45, + 21, 59, 28, 75, 21, 13, 44, 25, 37, 47, 44, 55, 37, 78, 45, + 5, 53, 28, 61, 35, 53, 58, 61, 65, 53, 4, 12, 29, 4, 38, + 12, 63, 4, 72, 12, 14, 21, 26, 28, 44, 21, 60, 28, 74, 21, + 14, 44, 24, 37, 47, 45, 54, 37, 77, 45, 4, 53, 27, 61, 34, + 53, 57, 61, 64, 53, 5, 12, 30, 4, 39, 12, 63, 5, 73, 12, + 13, 21, 27, 28, 43, 21, 61, 28, 73, 21, 15, 44, 23, 37, 46, + 45, 53, 37, 76, 45, 3, 53, 26, 61, 33, 53, 56, 61, 64, 54, + 6, 12, 31, 4, 40, 12, 62, 5, 74, 12, 12, 21, 28, 28, 42, + 21, 62, 28, 72, 21, 15, 45, 22, 37, 45, 45, 52, 37, 75, 45, + 2, 53, 25, 61, 32, 53, 55, 61, 65, 54, 7, 12, 31, 5, 41, + 12, 61, 5, 75, 12, 11, 21, 29, 28, 41, 21, 63, 28, 71, 21, + 14, 45, 21, 37, 44, 45, 51, 37, 74, 45, 1, 53, 24, 61, 32, + 54, 54, 61, 66, 54, 8, 12, 30, 5, 42, 12, 60, 5, 76, 12, + 10, 21, 30, 28, 40, 21, 63, 29, 70, 21, 13, 45, 20, 37, 43, + 45, 50, 37, 73, 45, 0, 53, 23, 61, 33, 54, 53, 61, 67, 54, + 9, 12, 29, 5, 43, 12, 59, 5, 77, 12, 9, 21, 31, 28, 39, + 21, 62, 29, 69, 21, 12, 45, 19, 37, 42, 45, 49, 37, 72, 45, + 0, 54, 22, 61, 34, 54, 52, 61, 68, 54, 10, 12, 28, 5, 44, + 12, 58, 5, 78, 12, 8, 21, 31, 29, 38, 21, 61, 29, 68, 21, + 11, 45, 18, 37, 41, 45, 48, 37, 71, 45, 1, 54, 21, 61, 35, + 54, 51, 61, 69, 54, 11, 12, 27, 5, 45, 12, 57, 5, 79, 12, + 7, 21, 30, 29, 37, 21, 60, 29, 67, 21, 10, 45, 17, 37, 40, + 45, 48, 38, 70, 45, 2, 54, 20, 61, 36, 54, 50, 61, 70, 54, + 12, 12, 26, 5, 46, 12, 56, 5, 79, 13, 6, 21, 29, 29, 36, + 21, 59, 29, 66, 21, 9, 45, 16, 37, 39, 45, 49, 38, 69, 45, + 3, 54, 19, 61, 37, 54, 49, 61, 71, 54, 13, 12, 25, 5, 47, + 12, 55, 5, 78, 13, 5, 21, 28, 29, 35, 21, 58, 29, 65, 21, + 8, 45, 16, 38, 38, 45, 50, 38, 68, 45, 4, 54, 18, 61, 38, + 54, 48, 61, 72, 54, 14, 12, 24, 5, 47, 13, 54, 5, 77, 13, + 4, 21, 27, 29, 34, 21, 57, 29, 64, 21, 7, 45, 17, 38, 37, + 45, 51, 38, 67, 45, 5, 54, 17, 61, 39, 54, 48, 62, 73, 54, + 15, 12, 23, 5, 46, 13, 53, 5, 76, 13, 3, 21, 26, 29, 33, + 21, 56, 29, 64, 22, 6, 45, 18, 38, 36, 45, 52, 38, 66, 45, + 6, 54, 16, 61, 40, 54, 49, 62, 74, 54, 15, 13, 22, 5, 45, + 13, 52, 5, 75, 13, 2, 21, 25, 29, 32, 21, 55, 29, 65, 22, + 5, 45, 19, 38, 35, 45, 53, 38, 65, 45, 7, 54, 16, 62, 41, + 54, 50, 62, 75, 54, 14, 13, 21, 5, 44, 13, 51, 5, 74, 13, + 1, 21, 24, 29, 32, 22, 54, 29, 66, 22, 4, 45, 20, 38, 34, + 45, 54, 38, 64, 45, 8, 54, 17, 62, 42, 54, 51, 62, 76, 54, + 13, 13, 20, 5, 43, 13, 50, 5, 73, 13, 0, 21, 23, 29, 33, + 22, 53, 29, 67, 22, 3, 45, 21, 38, 33, 45, 55, 38, 64, 46, + 9, 54, 18, 62, 43, 54, 52, 62, 77, 54, 12, 13, 19, 5, 42, + 13, 49, 5, 72, 13, 0, 22, 22, 29, 34, 22, 52, 29, 68, 22, + 2, 45, 22, 38, 32, 45, 56, 38, 65, 46, 10, 54, 19, 62, 44, + 54, 53, 62, 78, 54, 11, 13, 18, 5, 41, 13, 48, 5, 71, 13, + 1, 22, 21, 29, 35, 22, 51, 29, 69, 22, 1, 45, 23, 38, 32, + 46, 57, 38, 66, 46, 11, 54, 20, 62, 45, 54, 54, 62, 79, 54, + 10, 13, 17, 5, 40, 13, 48, 6, 70, 13, 2, 22, 20, 29, 36, + 22, 50, 29, 70, 22, 0, 45, 24, 38, 33, 46, 58, 38, 67, 46, + 12, 54, 21, 62, 46, 54, 55, 62, 79, 55, 9, 13, 16, 5, 39, + 13, 49, 6, 69, 13, 3, 22, 19, 29, 37, 22, 49, 29, 71, 22, + 0, 46, 25, 38, 34, 46, 59, 38, 68, 46, 13, 54, 22, 62, 47, + 54, 56, 62, 78, 55, 8, 13, 16, 6, 38, 13, 50, 6, 68, 13, + 4, 22, 18, 29, 38, 22, 48, 29, 72, 22, 1, 46, 26, 38, 35, + 46, 60, 38, 69, 46, 14, 54, 23, 62, 47, 55, 57, 62, 77, 55, + 7, 13, 17, 6, 37, 13, 51, 6, 67, 13, 5, 22, 17, 29, 39, + 22, 48, 30, 73, 22, 2, 46, 27, 38, 36, 46, 61, 38, 70, 46, + 15, 54, 24, 62, 46, 55, 58, 62, 76, 55, 6, 13, 18, 6, 36, + 13, 52, 6, 66, 13, 6, 22, 16, 29, 40, 22, 49, 30, 74, 22, + 3, 46, 28, 38, 37, 46, 62, 38, 71, 46, 15, 55, 25, 62, 45, + 55, 59, 62, 75, 55, 5, 13, 19, 6, 35, 13, 53, 6, 65, 13, + 7, 22, 16, 30, 41, 22, 50, 30, 75, 22, 4, 46, 29, 38, 38, + 46, 63, 38, 72, 46, 14, 55, 26, 62, 44, 55, 60, 62, 74, 55, + 4, 13, 20, 6, 34, 13, 54, 6, 64, 13, 8, 22, 17, 30, 42, + 22, 51, 30, 76, 22, 5, 46, 30, 38, 39, 46, 63, 39, 73, 46, + 13, 55, 27, 62, 43, 55, 61, 62, 73, 55, 3, 13, 21, 6, 33, + 13, 55, 6, 64, 14, 9, 22, 18, 30, 43, 22, 52, 30, 77, 22, + 6, 46, 31, 38, 40, 46, 62, 39, 74, 46, 12, 55, 28, 62, 42, + 55, 62, 62, 72, 55, 2, 13, 22, 6, 32, 13, 56, 6, 65, 14, + 10, 22, 19, 30, 44, 22, 53, 30, 78, 22, 7, 46, 31, 39, 41, + 46, 61, 39, 75, 46, 11, 55, 29, 62, 41, 55, 63, 62, 71, 55, + 1, 13, 23, 6, 32, 14, 57, 6, 66, 14, 11, 22, 20, 30, 45, + 22, 54, 30, 79, 22, 8, 46, 30, 39, 42, 46, 60, 39, 76, 46, + 10, 55, 30, 62, 40, 55, 63, 63, 70, 55, 0, 13, 24, 6, 33, + 14, 58, 6, 67, 14, 12, 22, 21, 30, 46, 22, 55, 30, 79, 23, + 9, 46, 29, 39, 43, 46, 59, 39, 77, 46, 9, 55, 31, 62, 39, + 55, 62, 63, 69, 55, 0, 14, 25, 6, 34, 14, 59, 6, 68, 14, + 13, 22, 22, 30, 47, 22, 56, 30, 78, 23, 10, 46, 28, 39, 44, + 46, 58, 39, 78, 46, 8, 55, 31, 63, 38, 55, 61, 63, 68, 55, + 1, 14, 26, 6, 35, 14, 60, 6, 69, 14, 14, 22, 23, 30, 47, + 23, 57, 30, 77, 23, 11, 46, 27, 39, 45, 46, 57, 39, 79, 46, + 7, 55, 30, 63, 37, 55, 60, 63, 67, 55, 2, 14, 27, 6, 36, + 14, 61, 6, 70, 14, 15, 22, 24, 30, 46, 23, 58, 30, 76, 23, + 12, 46, 26, 39, 46, 46, 56, 39, 79, 47, 6, 55, 29, 63, 36, + 55, 59, 63, 66, 55, 3, 14, 28, 6, 37, 14, 62, 6, 71, 14, + 15, 23, 25, 30, 45, 23, 59, 30, 75, 23, 13, 46, 25, 39, 47, + 46, 55, 39, 78, 47, 5, 55, 28, 63, 35, 55, 58, 63, 65, 55, + 4, 14, 29, 6, 38, 14, 63, 6, 72, 14, 14, 23, 26, 30, 44, + 23, 60, 30, 74, 23, 14, 46, 24, 39, 47, 47, 54, 39, 77, 47, + 4, 55, 27, 63, 34, 55, 57, 63, 64, 55, 5, 14, 30, 6, 39, + 14, 63, 7, 73, 14, 13, 23, 27, 30, 43, 23, 61, 30, 73, 23, + 15, 46, 23, 39, 46, 47, 53, 39, 76, 47, 3, 55, 26, 63, 33, + 55, 56, 63, 64, 56, 6, 14, 31, 6, 40, 14, 62, 7, 74, 14, + 12, 23, 28, 30, 42, 23, 62, 30, 72, 23, 15, 47, 22, 39, 45, + 47, 52, 39, 75, 47, 2, 55, 25, 63, 32, 55, 55, 63, 65, 56, + 7, 14, 31, 7, 41, 14, 61, 7, 75, 14, 11, 23, 29, 30, 41, + 23, 63, 30, 71, 23, 14, 47, 21, 39, 44, 47, 51, 39, 74, 47, + 1, 55, 24, 63, 32, 56, 54, 63, 66, 56, 8, 14, 30, 7, 42, + 14, 60, 7, 76, 14, 10, 23, 30, 30, 40, 23, 63, 31, 70, 23, + 13, 47, 20, 39, 43, 47, 50, 39, 73, 47, 0, 55, 23, 63, 33, + 56, 53, 63, 67, 56, 9, 14, 29, 7, 43, 14, 59, 7, 77, 14, + 9, 23, 31, 30, 39, 23, 62, 31, 69, 23, 12, 47, 19, 39, 42, + 47, 49, 39, 72, 47, 0, 56, 22, 63, 34, 56, 52, 63, 68, 56, + 10, 14, 28, 7, 44, 14, 58, 7, 78, 14, 8, 23, 31, 31, 38, + 23, 61, 31, 68, 23, 11, 47, 18, 39, 41, 47, 48, 39, 71, 47, + 1, 56, 21, 63, 35, 56, 51, 63, 69, 56, 11, 14, 27, 7, 45, + 14, 57, 7, 79, 14, 7, 23, 30, 31, 37, 23, 60, 31, 67, 23, + 10, 47, 17, 39, 40, 47, 48, 40, 70, 47, 2, 56, 20, 63, 36, + 56, 50, 63, 70, 56, 12, 14, 26, 7, 46, 14, 56, 7, 79, 15, + 6, 23, 29, 31, 36, 23, 59, 31, 66, 23, 9, 47, 16, 39, 39, + 47, 49, 40, 69, 47, 3, 56, 19, 63, 37, 56, 49, 63, 71, 56, + 13, 14, 25, 7, 47, 14, 55, 7, 78, 15, 5, 23, 28, 31, 35, + 23, 58, 31, 65, 23, 8, 47, 16, 40, 38, 47, 50, 40, 68, 47, + 4, 56, 18, 63, 38, 56, 48, 63, 72, 56, 14, 14, 24, 7, 47, + 15, 54, 7, 77, 15, 4, 23, 27, 31, 34, 23, 57, 31, 64, 23, + 7, 47, 17, 40, 37, 47, 51, 40, 67, 47, 5, 56, 17, 63, 39, + 56, 48, 48, 73, 56, 15, 14, 23, 7, 46, 15, 53, 7, 76, 15, + 3, 23, 26, 31, 33, 23, 56, 31, 64, 24, 6, 47, 18, 40, 36, + 47, 52, 40, 66, 47, 6, 56, 16, 63, 40, 56, 49, 48, 74, 56, + 15, 15, 22, 7, 45, 15, 52, 7, 75, 15, 2, 23, 25, 31, 32, + 23, 55, 31, 65, 24, 5, 47, 19, 40, 35, 47, 53, 40, 65, 47, + 7, 56, 16, 48, 41, 56, 50, 48, 75, 56, 14, 15, 21, 7, 44, + 15, 51, 7, 74, 15, 1, 23, 24, 31, 32, 24, 54, 31, 66, 24, + 4, 47, 20, 40, 34, 47, 54, 40, 64, 47, 8, 56, 17, 48, 42, + 56, 51, 48, 76, 56, 13, 15, 20, 7, 43, 15, 50, 7, 73, 15, + 0, 23, 23, 31, 33, 24, 53, 31, 67, 24, 3, 47, 21, 40, 33, + 47, 55, 40, 64, 32, 9, 56, 18, 48, 43, 56, 52, 48, 77, 56, + 12, 15, 19, 7, 42, 15, 49, 7, 72, 15, 0, 24, 22, 31, 34, + 24, 52, 31, 68, 24, 2, 47, 22, 40, 32, 47, 56, 40, 65, 32, + 10, 56, 19, 48, 44, 56, 53, 48, 78, 56, 11, 15, 18, 7, 41, + 15, 48, 7, 71, 15, 1, 24, 21, 31, 35, 24, 51, 31, 69, 24, + 1, 47, 23, 40, 32, 32, 57, 40, 66, 32, 11, 56, 20, 48, 45, + 56, 54, 48, 79, 56, 10, 15, 17, 7, 40, 15, 48, 8, 70, 15, + 2, 24, 20, 31, 36, 24, 50, 31, 70, 24, 0, 47, 24, 40, 33, + 32, 58, 40, 67, 32, 12, 56, 21, 48, 46, 56, 55, 48, 79, 57, + 9, 15, 16, 7, 39, 15, 49, 8, 69, 15, 3, 24, 19, 31, 37, + 24, 49, 31, 71, 24, 0, 32, 25, 40, 34, 32, 59, 40, 68, 32, + 13, 56, 22, 48, 47, 56, 56, 48, 78, 57, 8, 15, 16, 8, 38, + 15, 50, 8, 68, 15, 4, 24, 18, 31, 38, 24, 48, 31, 72, 24, + 1, 32, 26, 40, 35, 32, 60, 40, 69, 32, 14, 56, 23, 48, 47, + 57, 57, 48, 77, 57, 7, 15, 17, 8, 37, 15, 51, 8, 67, 15, + 5, 24, 17, 31, 39, 24, 48, 16, 73, 24, 2, 32, 27, 40, 36, + 32, 61, 40, 70, 32, 15, 56, 24, 48, 46, 57, 58, 48, 76, 57, + 6, 15, 18, 8, 36, 15, 52, 8, 66, 15, 6, 24, 16, 31, 40, + 24, 49, 16, 74, 24, 3, 32, 28, 40, 37, 32, 62, 40, 71, 32, + 15, 57, 25, 48, 45, 57, 59, 48, 75, 57, 5, 15, 19, 8, 35, + 15, 53, 8, 65, 15, 7, 24, 16, 16, 41, 24, 50, 16, 75, 24, + 4, 32, 29, 40, 38, 32, 63, 40, 72, 32, 14, 57, 26, 48, 44, + 57, 60, 48, 74, 57, 4, 15, 20, 8, 34, 15, 54, 8, 64, 15, + 8, 24, 17, 16, 42, 24, 51, 16, 76, 24, 5, 32, 30, 40, 39, + 32, 63, 41, 73, 32, 13, 57, 27, 48, 43, 57, 61, 48, 73, 57, + 3, 15, 21, 8, 33, 15, 55, 8, 64, 0, 9, 24, 18, 16, 43, + 24, 52, 16, 77, 24, 6, 32, 31, 40, 40, 32, 62, 41, 74, 32, + 12, 57, 28, 48, 42, 57, 62, 48, 72, 57, 2, 15, 22, 8, 32, + 15, 56, 8, 65, 0, 10, 24, 19, 16, 44, 24, 53, 16, 78, 24, + 7, 32, 31, 41, 41, 32, 61, 41, 75, 32, 11, 57, 29, 48, 41, + 57, 63, 48, 71, 57, 1, 15, 23, 8, 32, 0, 57, 8, 66, 0, + 11, 24, 20, 16, 45, 24, 54, 16, 79, 24, 8, 32, 30, 41, 42, + 32, 60, 41, 76, 32, 10, 57, 30, 48, 40, 57, 63, 49, 70, 57, + 0, 15, 24, 8, 33, 0, 58, 8, 67, 0, 12, 24, 21, 16, 46, + 24, 55, 16, 79, 25, 9, 32, 29, 41, 43, 32, 59, 41, 77, 32, + 9, 57, 31, 48, 39, 57, 62, 49, 69, 57, +}; + +static const uint8_t hq_tab_18[] = { + 0, 0, 25, 6, 34, 0, 59, 6, 68, 0, 13, 18, 22, 12, 47, + 18, 56, 12, 78, 19, 10, 24, 28, 31, 44, 24, 58, 31, 78, 24, + 8, 43, 31, 37, 38, 43, 61, 37, 68, 43, 11, 49, 18, 55, 41, + 49, 48, 55, 71, 49, 1, 0, 26, 6, 35, 0, 60, 6, 69, 0, + 14, 18, 23, 12, 47, 19, 57, 12, 77, 19, 11, 24, 27, 31, 45, + 24, 57, 31, 79, 24, 7, 43, 30, 37, 37, 43, 60, 37, 67, 43, + 10, 49, 17, 55, 40, 49, 48, 56, 70, 49, 2, 0, 27, 6, 36, + 0, 61, 6, 70, 0, 15, 18, 24, 12, 46, 19, 58, 12, 76, 19, + 12, 24, 26, 31, 46, 24, 56, 31, 79, 25, 6, 43, 29, 37, 36, + 43, 59, 37, 66, 43, 9, 49, 16, 55, 39, 49, 49, 56, 69, 49, + 3, 0, 28, 6, 37, 0, 62, 6, 71, 0, 15, 19, 25, 12, 45, + 19, 59, 12, 75, 19, 13, 24, 25, 31, 47, 24, 55, 31, 78, 25, + 5, 43, 28, 37, 35, 43, 58, 37, 65, 43, 8, 49, 16, 56, 38, + 49, 50, 56, 68, 49, 4, 0, 29, 6, 38, 0, 63, 6, 72, 0, + 14, 19, 26, 12, 44, 19, 60, 12, 74, 19, 14, 24, 24, 31, 47, + 25, 54, 31, 77, 25, 4, 43, 27, 37, 34, 43, 57, 37, 64, 43, + 7, 49, 17, 56, 37, 49, 51, 56, 67, 49, 5, 0, 30, 6, 39, + 0, 63, 7, 73, 0, 13, 19, 27, 12, 43, 19, 61, 12, 73, 19, + 15, 24, 23, 31, 46, 25, 53, 31, 76, 25, 3, 43, 26, 37, 33, + 43, 56, 37, 64, 44, 6, 49, 18, 56, 36, 49, 52, 56, 66, 49, + 6, 0, 31, 6, 40, 0, 62, 7, 74, 0, 12, 19, 28, 12, 42, + 19, 62, 12, 72, 19, 15, 25, 22, 31, 45, 25, 52, 31, 75, 25, + 2, 43, 25, 37, 32, 43, 55, 37, 65, 44, 5, 49, 19, 56, 35, + 49, 53, 56, 65, 49, 7, 0, 31, 7, 41, 0, 61, 7, 75, 0, + 11, 19, 29, 12, 41, 19, 63, 12, 71, 19, 14, 25, 21, 31, 44, + 25, 51, 31, 74, 25, 1, 43, 24, 37, 32, 44, 54, 37, 66, 44, + 4, 49, 20, 56, 34, 49, 54, 56, 64, 49, 8, 0, 30, 7, 42, + 0, 60, 7, 76, 0, 10, 19, 30, 12, 40, 19, 63, 13, 70, 19, + 13, 25, 20, 31, 43, 25, 50, 31, 73, 25, 0, 43, 23, 37, 33, + 44, 53, 37, 67, 44, 3, 49, 21, 56, 33, 49, 55, 56, 64, 50, + 9, 0, 29, 7, 43, 0, 59, 7, 77, 0, 9, 19, 31, 12, 39, + 19, 62, 13, 69, 19, 12, 25, 19, 31, 42, 25, 49, 31, 72, 25, + 0, 44, 22, 37, 34, 44, 52, 37, 68, 44, 2, 49, 22, 56, 32, + 49, 56, 56, 65, 50, 10, 0, 28, 7, 44, 0, 58, 7, 78, 0, + 8, 19, 31, 13, 38, 19, 61, 13, 68, 19, 11, 25, 18, 31, 41, + 25, 48, 31, 71, 25, 1, 44, 21, 37, 35, 44, 51, 37, 69, 44, + 1, 49, 23, 56, 32, 50, 57, 56, 66, 50, 11, 0, 27, 7, 45, + 0, 57, 7, 79, 0, 7, 19, 30, 13, 37, 19, 60, 13, 67, 19, + 10, 25, 17, 31, 40, 25, 48, 32, 70, 25, 2, 44, 20, 37, 36, + 44, 50, 37, 70, 44, 0, 49, 24, 56, 33, 50, 58, 56, 67, 50, + 12, 0, 26, 7, 46, 0, 56, 7, 79, 1, 6, 19, 29, 13, 36, + 19, 59, 13, 66, 19, 9, 25, 16, 31, 39, 25, 49, 32, 69, 25, + 3, 44, 19, 37, 37, 44, 49, 37, 71, 44, 0, 50, 25, 56, 34, + 50, 59, 56, 68, 50, 13, 0, 25, 7, 47, 0, 55, 7, 78, 1, + 5, 19, 28, 13, 35, 19, 58, 13, 65, 19, 8, 25, 16, 32, 38, + 25, 50, 32, 68, 25, 4, 44, 18, 37, 38, 44, 48, 37, 72, 44, + 1, 50, 26, 56, 35, 50, 60, 56, 69, 50, 14, 0, 24, 7, 47, + 1, 54, 7, 77, 1, 4, 19, 27, 13, 34, 19, 57, 13, 64, 19, + 7, 25, 17, 32, 37, 25, 51, 32, 67, 25, 5, 44, 17, 37, 39, + 44, 48, 38, 73, 44, 2, 50, 27, 56, 36, 50, 61, 56, 70, 50, + 15, 0, 23, 7, 46, 1, 53, 7, 76, 1, 3, 19, 26, 13, 33, + 19, 56, 13, 64, 20, 6, 25, 18, 32, 36, 25, 52, 32, 66, 25, + 6, 44, 16, 37, 40, 44, 49, 38, 74, 44, 3, 50, 28, 56, 37, + 50, 62, 56, 71, 50, 15, 1, 22, 7, 45, 1, 52, 7, 75, 1, + 2, 19, 25, 13, 32, 19, 55, 13, 65, 20, 5, 25, 19, 32, 35, + 25, 53, 32, 65, 25, 7, 44, 16, 38, 41, 44, 50, 38, 75, 44, + 4, 50, 29, 56, 38, 50, 63, 56, 72, 50, 14, 1, 21, 7, 44, + 1, 51, 7, 74, 1, 1, 19, 24, 13, 32, 20, 54, 13, 66, 20, + 4, 25, 20, 32, 34, 25, 54, 32, 64, 25, 8, 44, 17, 38, 42, + 44, 51, 38, 76, 44, 5, 50, 30, 56, 39, 50, 63, 57, 73, 50, + 13, 1, 20, 7, 43, 1, 50, 7, 73, 1, 0, 19, 23, 13, 33, + 20, 53, 13, 67, 20, 3, 25, 21, 32, 33, 25, 55, 32, 64, 26, + 9, 44, 18, 38, 43, 44, 52, 38, 77, 44, 6, 50, 31, 56, 40, + 50, 62, 57, 74, 50, 12, 1, 19, 7, 42, 1, 49, 7, 72, 1, + 0, 20, 22, 13, 34, 20, 52, 13, 68, 20, 2, 25, 22, 32, 32, + 25, 56, 32, 65, 26, 10, 44, 19, 38, 44, 44, 53, 38, 78, 44, + 7, 50, 31, 57, 41, 50, 61, 57, 75, 50, 11, 1, 18, 7, 41, + 1, 48, 7, 71, 1, 1, 20, 21, 13, 35, 20, 51, 13, 69, 20, + 1, 25, 23, 32, 32, 26, 57, 32, 66, 26, 11, 44, 20, 38, 45, + 44, 54, 38, 79, 44, 8, 50, 30, 57, 42, 50, 60, 57, 76, 50, + 10, 1, 17, 7, 40, 1, 48, 8, 70, 1, 2, 20, 20, 13, 36, + 20, 50, 13, 70, 20, 0, 25, 24, 32, 33, 26, 58, 32, 67, 26, + 12, 44, 21, 38, 46, 44, 55, 38, 79, 45, 9, 50, 29, 57, 43, + 50, 59, 57, 77, 50, 9, 1, 16, 7, 39, 1, 49, 8, 69, 1, + 3, 20, 19, 13, 37, 20, 49, 13, 71, 20, 0, 26, 25, 32, 34, + 26, 59, 32, 68, 26, 13, 44, 22, 38, 47, 44, 56, 38, 78, 45, + 10, 50, 28, 57, 44, 50, 58, 57, 78, 50, 8, 1, 16, 8, 38, + 1, 50, 8, 68, 1, 4, 20, 18, 13, 38, 20, 48, 13, 72, 20, + 1, 26, 26, 32, 35, 26, 60, 32, 69, 26, 14, 44, 23, 38, 47, + 45, 57, 38, 77, 45, 11, 50, 27, 57, 45, 50, 57, 57, 79, 50, + 7, 1, 17, 8, 37, 1, 51, 8, 67, 1, 5, 20, 17, 13, 39, + 20, 48, 14, 73, 20, 2, 26, 27, 32, 36, 26, 61, 32, 70, 26, + 15, 44, 24, 38, 46, 45, 58, 38, 76, 45, 12, 50, 26, 57, 46, + 50, 56, 57, 79, 51, 6, 1, 18, 8, 36, 1, 52, 8, 66, 1, + 6, 20, 16, 13, 40, 20, 49, 14, 74, 20, 3, 26, 28, 32, 37, + 26, 62, 32, 71, 26, 15, 45, 25, 38, 45, 45, 59, 38, 75, 45, + 13, 50, 25, 57, 47, 50, 55, 57, 78, 51, 5, 1, 19, 8, 35, + 1, 53, 8, 65, 1, 7, 20, 16, 14, 41, 20, 50, 14, 75, 20, + 4, 26, 29, 32, 38, 26, 63, 32, 72, 26, 14, 45, 26, 38, 44, + 45, 60, 38, 74, 45, 14, 50, 24, 57, 47, 51, 54, 57, 77, 51, + 4, 1, 20, 8, 34, 1, 54, 8, 64, 1, 8, 20, 17, 14, 42, + 20, 51, 14, 76, 20, 5, 26, 30, 32, 39, 26, 63, 33, 73, 26, + 13, 45, 27, 38, 43, 45, 61, 38, 73, 45, 15, 50, 23, 57, 46, + 51, 53, 57, 76, 51, 3, 1, 21, 8, 33, 1, 55, 8, 64, 2, + 9, 20, 18, 14, 43, 20, 52, 14, 77, 20, 6, 26, 31, 32, 40, + 26, 62, 33, 74, 26, 12, 45, 28, 38, 42, 45, 62, 38, 72, 45, + 15, 51, 22, 57, 45, 51, 52, 57, 75, 51, 2, 1, 22, 8, 32, + 1, 56, 8, 65, 2, 10, 20, 19, 14, 44, 20, 53, 14, 78, 20, + 7, 26, 31, 33, 41, 26, 61, 33, 75, 26, 11, 45, 29, 38, 41, + 45, 63, 38, 71, 45, 14, 51, 21, 57, 44, 51, 51, 57, 74, 51, + 1, 1, 23, 8, 32, 2, 57, 8, 66, 2, 11, 20, 20, 14, 45, + 20, 54, 14, 79, 20, 8, 26, 30, 33, 42, 26, 60, 33, 76, 26, + 10, 45, 30, 38, 40, 45, 63, 39, 70, 45, 13, 51, 20, 57, 43, + 51, 50, 57, 73, 51, 0, 1, 24, 8, 33, 2, 58, 8, 67, 2, + 12, 20, 21, 14, 46, 20, 55, 14, 79, 21, 9, 26, 29, 33, 43, + 26, 59, 33, 77, 26, 9, 45, 31, 38, 39, 45, 62, 39, 69, 45, + 12, 51, 19, 57, 42, 51, 49, 57, 72, 51, 0, 2, 25, 8, 34, + 2, 59, 8, 68, 2, 13, 20, 22, 14, 47, 20, 56, 14, 78, 21, + 10, 26, 28, 33, 44, 26, 58, 33, 78, 26, 8, 45, 31, 39, 38, + 45, 61, 39, 68, 45, 11, 51, 18, 57, 41, 51, 48, 57, 71, 51, + 1, 2, 26, 8, 35, 2, 60, 8, 69, 2, 14, 20, 23, 14, 47, + 21, 57, 14, 77, 21, 11, 26, 27, 33, 45, 26, 57, 33, 79, 26, + 7, 45, 30, 39, 37, 45, 60, 39, 67, 45, 10, 51, 17, 57, 40, + 51, 48, 58, 70, 51, 2, 2, 27, 8, 36, 2, 61, 8, 70, 2, + 15, 20, 24, 14, 46, 21, 58, 14, 76, 21, 12, 26, 26, 33, 46, + 26, 56, 33, 79, 27, 6, 45, 29, 39, 36, 45, 59, 39, 66, 45, + 9, 51, 16, 57, 39, 51, 49, 58, 69, 51, 3, 2, 28, 8, 37, + 2, 62, 8, 71, 2, 15, 21, 25, 14, 45, 21, 59, 14, 75, 21, + 13, 26, 25, 33, 47, 26, 55, 33, 78, 27, 5, 45, 28, 39, 35, + 45, 58, 39, 65, 45, 8, 51, 16, 58, 38, 51, 50, 58, 68, 51, + 4, 2, 29, 8, 38, 2, 63, 8, 72, 2, 14, 21, 26, 14, 44, + 21, 60, 14, 74, 21, 14, 26, 24, 33, 47, 27, 54, 33, 77, 27, + 4, 45, 27, 39, 34, 45, 57, 39, 64, 45, 7, 51, 17, 58, 37, + 51, 51, 58, 67, 51, 5, 2, 30, 8, 39, 2, 63, 9, 73, 2, + 13, 21, 27, 14, 43, 21, 61, 14, 73, 21, 15, 26, 23, 33, 46, + 27, 53, 33, 76, 27, 3, 45, 26, 39, 33, 45, 56, 39, 64, 46, + 6, 51, 18, 58, 36, 51, 52, 58, 66, 51, 6, 2, 31, 8, 40, + 2, 62, 9, 74, 2, 12, 21, 28, 14, 42, 21, 62, 14, 72, 21, + 15, 27, 22, 33, 45, 27, 52, 33, 75, 27, 2, 45, 25, 39, 32, + 45, 55, 39, 65, 46, 5, 51, 19, 58, 35, 51, 53, 58, 65, 51, + 7, 2, 31, 9, 41, 2, 61, 9, 75, 2, 11, 21, 29, 14, 41, + 21, 63, 14, 71, 21, 14, 27, 21, 33, 44, 27, 51, 33, 74, 27, + 1, 45, 24, 39, 32, 46, 54, 39, 66, 46, 4, 51, 20, 58, 34, + 51, 54, 58, 64, 51, 8, 2, 30, 9, 42, 2, 60, 9, 76, 2, + 10, 21, 30, 14, 40, 21, 63, 15, 70, 21, 13, 27, 20, 33, 43, + 27, 50, 33, 73, 27, 0, 45, 23, 39, 33, 46, 53, 39, 67, 46, + 3, 51, 21, 58, 33, 51, 55, 58, 64, 52, 9, 2, 29, 9, 43, + 2, 59, 9, 77, 2, 9, 21, 31, 14, 39, 21, 62, 15, 69, 21, + 12, 27, 19, 33, 42, 27, 49, 33, 72, 27, 0, 46, 22, 39, 34, + 46, 52, 39, 68, 46, 2, 51, 22, 58, 32, 51, 56, 58, 65, 52, + 10, 2, 28, 9, 44, 2, 58, 9, 78, 2, 8, 21, 31, 15, 38, + 21, 61, 15, 68, 21, 11, 27, 18, 33, 41, 27, 48, 33, 71, 27, + 1, 46, 21, 39, 35, 46, 51, 39, 69, 46, 1, 51, 23, 58, 32, + 52, 57, 58, 66, 52, 11, 2, 27, 9, 45, 2, 57, 9, 79, 2, + 7, 21, 30, 15, 37, 21, 60, 15, 67, 21, 10, 27, 17, 33, 40, + 27, 48, 34, 70, 27, 2, 46, 20, 39, 36, 46, 50, 39, 70, 46, + 0, 51, 24, 58, 33, 52, 58, 58, 67, 52, 12, 2, 26, 9, 46, + 2, 56, 9, 79, 3, 6, 21, 29, 15, 36, 21, 59, 15, 66, 21, + 9, 27, 16, 33, 39, 27, 49, 34, 69, 27, 3, 46, 19, 39, 37, + 46, 49, 39, 71, 46, 0, 52, 25, 58, 34, 52, 59, 58, 68, 52, + 13, 2, 25, 9, 47, 2, 55, 9, 78, 3, 5, 21, 28, 15, 35, + 21, 58, 15, 65, 21, 8, 27, 16, 34, 38, 27, 50, 34, 68, 27, + 4, 46, 18, 39, 38, 46, 48, 39, 72, 46, 1, 52, 26, 58, 35, + 52, 60, 58, 69, 52, 14, 2, 24, 9, 47, 3, 54, 9, 77, 3, + 4, 21, 27, 15, 34, 21, 57, 15, 64, 21, 7, 27, 17, 34, 37, + 27, 51, 34, 67, 27, 5, 46, 17, 39, 39, 46, 48, 40, 73, 46, + 2, 52, 27, 58, 36, 52, 61, 58, 70, 52, 15, 2, 23, 9, 46, + 3, 53, 9, 76, 3, 3, 21, 26, 15, 33, 21, 56, 15, 64, 22, + 6, 27, 18, 34, 36, 27, 52, 34, 66, 27, 6, 46, 16, 39, 40, + 46, 49, 40, 74, 46, 3, 52, 28, 58, 37, 52, 62, 58, 71, 52, + 15, 3, 22, 9, 45, 3, 52, 9, 75, 3, 2, 21, 25, 15, 32, + 21, 55, 15, 65, 22, 5, 27, 19, 34, 35, 27, 53, 34, 65, 27, + 7, 46, 16, 40, 41, 46, 50, 40, 75, 46, 4, 52, 29, 58, 38, + 52, 63, 58, 72, 52, 14, 3, 21, 9, 44, 3, 51, 9, 74, 3, + 1, 21, 24, 15, 32, 22, 54, 15, 66, 22, 4, 27, 20, 34, 34, + 27, 54, 34, 64, 27, 8, 46, 17, 40, 42, 46, 51, 40, 76, 46, + 5, 52, 30, 58, 39, 52, 63, 59, 73, 52, 13, 3, 20, 9, 43, + 3, 50, 9, 73, 3, 0, 21, 23, 15, 33, 22, 53, 15, 67, 22, + 3, 27, 21, 34, 33, 27, 55, 34, 64, 28, 9, 46, 18, 40, 43, + 46, 52, 40, 77, 46, 6, 52, 31, 58, 40, 52, 62, 59, 74, 52, + 12, 3, 19, 9, 42, 3, 49, 9, 72, 3, 0, 22, 22, 15, 34, + 22, 52, 15, 68, 22, 2, 27, 22, 34, 32, 27, 56, 34, 65, 28, + 10, 46, 19, 40, 44, 46, 53, 40, 78, 46, 7, 52, 31, 59, 41, + 52, 61, 59, 75, 52, 11, 3, 18, 9, 41, 3, 48, 9, 71, 3, + 1, 22, 21, 15, 35, 22, 51, 15, 69, 22, 1, 27, 23, 34, 32, + 28, 57, 34, 66, 28, 11, 46, 20, 40, 45, 46, 54, 40, 79, 46, + 8, 52, 30, 59, 42, 52, 60, 59, 76, 52, 10, 3, 17, 9, 40, + 3, 48, 10, 70, 3, 2, 22, 20, 15, 36, 22, 50, 15, 70, 22, + 0, 27, 24, 34, 33, 28, 58, 34, 67, 28, 12, 46, 21, 40, 46, + 46, 55, 40, 79, 47, 9, 52, 29, 59, 43, 52, 59, 59, 77, 52, + 9, 3, 16, 9, 39, 3, 49, 10, 69, 3, 3, 22, 19, 15, 37, + 22, 49, 15, 71, 22, 0, 28, 25, 34, 34, 28, 59, 34, 68, 28, + 13, 46, 22, 40, 47, 46, 56, 40, 78, 47, 10, 52, 28, 59, 44, + 52, 58, 59, 78, 52, 8, 3, 16, 10, 38, 3, 50, 10, 68, 3, + 4, 22, 18, 15, 38, 22, 48, 15, 72, 22, 1, 28, 26, 34, 35, + 28, 60, 34, 69, 28, 14, 46, 23, 40, 47, 47, 57, 40, 77, 47, + 11, 52, 27, 59, 45, 52, 57, 59, 79, 52, 7, 3, 17, 10, 37, + 3, 51, 10, 67, 3, 5, 22, 17, 15, 39, 22, 48, 16, 73, 22, + 2, 28, 27, 34, 36, 28, 61, 34, 70, 28, 15, 46, 24, 40, 46, + 47, 58, 40, 76, 47, 12, 52, 26, 59, 46, 52, 56, 59, 79, 53, + 6, 3, 18, 10, 36, 3, 52, 10, 66, 3, 6, 22, 16, 15, 40, + 22, 49, 16, 74, 22, 3, 28, 28, 34, 37, 28, 62, 34, 71, 28, + 15, 47, 25, 40, 45, 47, 59, 40, 75, 47, 13, 52, 25, 59, 47, + 52, 55, 59, 78, 53, 5, 3, 19, 10, 35, 3, 53, 10, 65, 3, + 7, 22, 16, 16, 41, 22, 50, 16, 75, 22, 4, 28, 29, 34, 38, + 28, 63, 34, 72, 28, 14, 47, 26, 40, 44, 47, 60, 40, 74, 47, + 14, 52, 24, 59, 47, 53, 54, 59, 77, 53, 4, 3, 20, 10, 34, + 3, 54, 10, 64, 3, 8, 22, 17, 16, 42, 22, 51, 16, 76, 22, + 5, 28, 30, 34, 39, 28, 63, 35, 73, 28, 13, 47, 27, 40, 43, + 47, 61, 40, 73, 47, 15, 52, 23, 59, 46, 53, 53, 59, 76, 53, + 3, 3, 21, 10, 33, 3, 55, 10, 64, 4, 9, 22, 18, 16, 43, + 22, 52, 16, 77, 22, 6, 28, 31, 34, 40, 28, 62, 35, 74, 28, + 12, 47, 28, 40, 42, 47, 62, 40, 72, 47, 15, 53, 22, 59, 45, + 53, 52, 59, 75, 53, 2, 3, 22, 10, 32, 3, 56, 10, 65, 4, + 10, 22, 19, 16, 44, 22, 53, 16, 78, 22, 7, 28, 31, 35, 41, + 28, 61, 35, 75, 28, 11, 47, 29, 40, 41, 47, 63, 40, 71, 47, + 14, 53, 21, 59, 44, 53, 51, 59, 74, 53, 1, 3, 23, 10, 32, + 4, 57, 10, 66, 4, 11, 22, 20, 16, 45, 22, 54, 16, 79, 22, + 8, 28, 30, 35, 42, 28, 60, 35, 76, 28, 10, 47, 30, 40, 40, + 47, 63, 41, 70, 47, 13, 53, 20, 59, 43, 53, 50, 59, 73, 53, + 0, 3, 24, 10, 33, 4, 58, 10, 67, 4, 12, 22, 21, 16, 46, + 22, 55, 16, 79, 23, 9, 28, 29, 35, 43, 28, 59, 35, 77, 28, + 9, 47, 31, 40, 39, 47, 62, 41, 69, 47, 12, 53, 19, 59, 42, + 53, 49, 59, 72, 53, 0, 4, 25, 10, 34, 4, 59, 10, 68, 4, + 13, 22, 22, 16, 47, 22, 56, 16, 78, 23, 10, 28, 28, 35, 44, + 28, 58, 35, 78, 28, 8, 47, 31, 41, 38, 47, 61, 41, 68, 47, + 11, 53, 18, 59, 41, 53, 48, 59, 71, 53, 1, 4, 26, 10, 35, + 4, 60, 10, 69, 4, 14, 22, 23, 16, 47, 23, 57, 16, 77, 23, + 11, 28, 27, 35, 45, 28, 57, 35, 79, 28, 7, 47, 30, 41, 37, + 47, 60, 41, 67, 47, 10, 53, 17, 59, 40, 53, 48, 48, 70, 53, + 2, 4, 27, 10, 36, 4, 61, 10, 70, 4, 15, 22, 24, 16, 46, + 23, 58, 16, 76, 23, 12, 28, 26, 35, 46, 28, 56, 35, 79, 29, + 6, 47, 29, 41, 36, 47, 59, 41, 66, 47, 9, 53, 16, 59, 39, + 53, 49, 48, 69, 53, 3, 4, 28, 10, 37, 4, 62, 10, 71, 4, + 15, 23, 25, 16, 45, 23, 59, 16, 75, 23, 13, 28, 25, 35, 47, + 28, 55, 35, 78, 29, 5, 47, 28, 41, 35, 47, 58, 41, 65, 47, + 8, 53, 16, 48, 38, 53, 50, 48, 68, 53, 4, 4, 29, 10, 38, + 4, 63, 10, 72, 4, 14, 23, 26, 16, 44, 23, 60, 16, 74, 23, + 14, 28, 24, 35, 47, 29, 54, 35, 77, 29, 4, 47, 27, 41, 34, + 47, 57, 41, 64, 47, 7, 53, 17, 48, 37, 53, 51, 48, 67, 53, + 5, 4, 30, 10, 39, 4, 63, 11, 73, 4, 13, 23, 27, 16, 43, + 23, 61, 16, 73, 23, 15, 28, 23, 35, 46, 29, 53, 35, 76, 29, + 3, 47, 26, 41, 33, 47, 56, 41, 64, 36, 6, 53, 18, 48, 36, + 53, 52, 48, 66, 53, 6, 4, 31, 10, 40, 4, 62, 11, 74, 4, + 12, 23, 28, 16, 42, 23, 62, 16, 72, 23, 15, 29, 22, 35, 45, + 29, 52, 35, 75, 29, 2, 47, 25, 41, 32, 47, 55, 41, 65, 36, + 5, 53, 19, 48, 35, 53, 53, 48, 65, 53, 7, 4, 31, 11, 41, + 4, 61, 11, 75, 4, 11, 23, 29, 16, 41, 23, 63, 16, 71, 23, + 14, 29, 21, 35, 44, 29, 51, 35, 74, 29, 1, 47, 24, 41, 32, + 36, 54, 41, 66, 36, 4, 53, 20, 48, 34, 53, 54, 48, 64, 53, + 8, 4, 30, 11, 42, 4, 60, 11, 76, 4, 10, 23, 30, 16, 40, + 23, 63, 17, 70, 23, 13, 29, 20, 35, 43, 29, 50, 35, 73, 29, + 0, 47, 23, 41, 33, 36, 53, 41, 67, 36, 3, 53, 21, 48, 33, + 53, 55, 48, 64, 54, 9, 4, 29, 11, 43, 4, 59, 11, 77, 4, + 9, 23, 31, 16, 39, 23, 62, 17, 69, 23, 12, 29, 19, 35, 42, + 29, 49, 35, 72, 29, 0, 36, 22, 41, 34, 36, 52, 41, 68, 36, + 2, 53, 22, 48, 32, 53, 56, 48, 65, 54, 10, 4, 28, 11, 44, + 4, 58, 11, 78, 4, 8, 23, 31, 17, 38, 23, 61, 17, 68, 23, + 11, 29, 18, 35, 41, 29, 48, 35, 71, 29, 1, 36, 21, 41, 35, + 36, 51, 41, 69, 36, 1, 53, 23, 48, 32, 54, 57, 48, 66, 54, + 11, 4, 27, 11, 45, 4, 57, 11, 79, 4, 7, 23, 30, 17, 37, + 23, 60, 17, 67, 23, 10, 29, 17, 35, 40, 29, 48, 24, 70, 29, + 2, 36, 20, 41, 36, 36, 50, 41, 70, 36, 0, 53, 24, 48, 33, + 54, 58, 48, 67, 54, 12, 4, 26, 11, 46, 4, 56, 11, 79, 5, + 6, 23, 29, 17, 36, 23, 59, 17, 66, 23, 9, 29, 16, 35, 39, + 29, 49, 24, 69, 29, 3, 36, 19, 41, 37, 36, 49, 41, 71, 36, + 0, 54, 25, 48, 34, 54, 59, 48, 68, 54, 13, 4, 25, 11, 47, + 4, 55, 11, 78, 5, 5, 23, 28, 17, 35, 23, 58, 17, 65, 23, + 8, 29, 16, 24, 38, 29, 50, 24, 68, 29, 4, 36, 18, 41, 38, + 36, 48, 41, 72, 36, 1, 54, 26, 48, 35, 54, 60, 48, 69, 54, + 14, 4, 24, 11, 47, 5, 54, 11, 77, 5, 4, 23, 27, 17, 34, + 23, 57, 17, 64, 23, 7, 29, 17, 24, 37, 29, 51, 24, 67, 29, + 5, 36, 17, 41, 39, 36, 48, 42, 73, 36, 2, 54, 27, 48, 36, + 54, 61, 48, 70, 54, 15, 4, 23, 11, 46, 5, 53, 11, 76, 5, + 3, 23, 26, 17, 33, 23, 56, 17, 64, 12, 6, 29, 18, 24, 36, + 29, 52, 24, 66, 29, 6, 36, 16, 41, 40, 36, 49, 42, 74, 36, + 3, 54, 28, 48, 37, 54, 62, 48, 71, 54, 15, 5, 22, 11, 45, + 5, 52, 11, 75, 5, 2, 23, 25, 17, 32, 23, 55, 17, 65, 12, + 5, 29, 19, 24, 35, 29, 53, 24, 65, 29, 7, 36, 16, 42, 41, + 36, 50, 42, 75, 36, 4, 54, 29, 48, 38, 54, 63, 48, 72, 54, + 14, 5, 21, 11, 44, 5, 51, 11, 74, 5, 1, 23, 24, 17, 32, + 12, 54, 17, 66, 12, 4, 29, 20, 24, 34, 29, 54, 24, 64, 29, + 8, 36, 17, 42, 42, 36, 51, 42, 76, 36, 5, 54, 30, 48, 39, + 54, 63, 49, 73, 54, 13, 5, 20, 11, 43, 5, 50, 11, 73, 5, + 0, 23, 23, 17, 33, 12, 53, 17, 67, 12, 3, 29, 21, 24, 33, + 29, 55, 24, 64, 30, 9, 36, 18, 42, 43, 36, 52, 42, 77, 36, + 6, 54, 31, 48, 40, 54, 62, 49, 74, 54, 12, 5, 19, 11, 42, + 5, 49, 11, 72, 5, 0, 12, 22, 17, 34, 12, 52, 17, 68, 12, + 2, 29, 22, 24, 32, 29, 56, 24, 65, 30, 10, 36, 19, 42, 44, + 36, 53, 42, 78, 36, 7, 54, 31, 49, 41, 54, 61, 49, 75, 54, + 11, 5, 18, 11, 41, 5, 48, 11, 71, 5, 1, 12, 21, 17, 35, + 12, 51, 17, 69, 12, 1, 29, 23, 24, 32, 30, 57, 24, 66, 30, + 11, 36, 20, 42, 45, 36, 54, 42, 79, 36, 8, 54, 30, 49, 42, + 54, 60, 49, 76, 54, 10, 5, 17, 11, 40, 5, 48, 0, 70, 5, + 2, 12, 20, 17, 36, 12, 50, 17, 70, 12, 0, 29, 24, 24, 33, + 30, 58, 24, 67, 30, 12, 36, 21, 42, 46, 36, 55, 42, 79, 37, + 9, 54, 29, 49, 43, 54, 59, 49, 77, 54, 9, 5, 16, 11, 39, + 5, 49, 0, 69, 5, 3, 12, 19, 17, 37, 12, 49, 17, 71, 12, + 0, 30, 25, 24, 34, 30, 59, 24, 68, 30, 13, 36, 22, 42, 47, + 36, 56, 42, 78, 37, 10, 54, 28, 49, 44, 54, 58, 49, 78, 54, + 8, 5, 16, 0, 38, 5, 50, 0, 68, 5, 4, 12, 18, 17, 38, + 12, 48, 17, 72, 12, 1, 30, 26, 24, 35, 30, 60, 24, 69, 30, + 14, 36, 23, 42, 47, 37, 57, 42, 77, 37, 11, 54, 27, 49, 45, + 54, 57, 49, 79, 54, 7, 5, 17, 0, 37, 5, 51, 0, 67, 5, + 5, 12, 17, 17, 39, 12, 48, 18, 73, 12, 2, 30, 27, 24, 36, + 30, 61, 24, 70, 30, 15, 36, 24, 42, 46, 37, 58, 42, 76, 37, + 12, 54, 26, 49, 46, 54, 56, 49, 79, 55, 6, 5, 18, 0, 36, + 5, 52, 0, 66, 5, 6, 12, 16, 17, 40, 12, 49, 18, 74, 12, + 3, 30, 28, 24, 37, 30, 62, 24, 71, 30, 15, 37, 25, 42, 45, + 37, 59, 42, 75, 37, 13, 54, 25, 49, 47, 54, 55, 49, 78, 55, + 5, 5, 19, 0, 35, 5, 53, 0, 65, 5, 7, 12, 16, 18, 41, + 12, 50, 18, 75, 12, 4, 30, 29, 24, 38, 30, 63, 24, 72, 30, + 14, 37, 26, 42, 44, 37, 60, 42, 74, 37, 14, 54, 24, 49, 47, + 55, 54, 49, 77, 55, 4, 5, 20, 0, 34, 5, 54, 0, 64, 5, + 8, 12, 17, 18, 42, 12, 51, 18, 76, 12, 5, 30, 30, 24, 39, + 30, 63, 25, 73, 30, 13, 37, 27, 42, 43, 37, 61, 42, 73, 37, + 15, 54, 23, 49, 46, 55, 53, 49, 76, 55, 3, 5, 21, 0, 33, + 5, 55, 0, 64, 6, 9, 12, 18, 18, 43, 12, 52, 18, 77, 12, + 6, 30, 31, 24, 40, 30, 62, 25, 74, 30, 12, 37, 28, 42, 42, + 37, 62, 42, 72, 37, 15, 55, 22, 49, 45, 55, 52, 49, 75, 55, + 2, 5, 22, 0, 32, 5, 56, 0, 65, 6, 10, 12, 19, 18, 44, + 12, 53, 18, 78, 12, 7, 30, 31, 25, 41, 30, 61, 25, 75, 30, + 11, 37, 29, 42, 41, 37, 63, 42, 71, 37, 14, 55, 21, 49, 44, + 55, 51, 49, 74, 55, 1, 5, 23, 0, 32, 6, 57, 0, 66, 6, + 11, 12, 20, 18, 45, 12, 54, 18, 79, 12, 8, 30, 30, 25, 42, + 30, 60, 25, 76, 30, 10, 37, 30, 42, 40, 37, 63, 43, 70, 37, + 13, 55, 20, 49, 43, 55, 50, 49, 73, 55, 0, 5, 24, 0, 33, + 6, 58, 0, 67, 6, 12, 12, 21, 18, 46, 12, 55, 18, 79, 13, + 9, 30, 29, 25, 43, 30, 59, 25, 77, 30, 9, 37, 31, 42, 39, + 37, 62, 43, 69, 37, 12, 55, 19, 49, 42, 55, 49, 49, 72, 55, + 0, 6, 25, 0, 34, 6, 59, 0, 68, 6, 13, 12, 22, 18, 47, + 12, 56, 18, 78, 13, 10, 30, 28, 25, 44, 30, 58, 25, 78, 30, + 8, 37, 31, 43, 38, 37, 61, 43, 68, 37, 11, 55, 18, 49, 41, + 55, 48, 49, 71, 55, 1, 6, 26, 0, 35, 6, 60, 0, 69, 6, + 14, 12, 23, 18, 47, 13, 57, 18, 77, 13, 11, 30, 27, 25, 45, + 30, 57, 25, 79, 30, 7, 37, 30, 43, 37, 37, 60, 43, 67, 37, + 10, 55, 17, 49, 40, 55, 48, 50, 70, 55, 2, 6, 27, 0, 36, + 6, 61, 0, 70, 6, 15, 12, 24, 18, 46, 13, 58, 18, 76, 13, + 12, 30, 26, 25, 46, 30, 56, 25, 79, 31, 6, 37, 29, 43, 36, + 37, 59, 43, 66, 37, 9, 55, 16, 49, 39, 55, 49, 50, 69, 55, + 3, 6, 28, 0, 37, 6, 62, 0, 71, 6, 15, 13, 25, 18, 45, + 13, 59, 18, 75, 13, 13, 30, 25, 25, 47, 30, 55, 25, 78, 31, + 5, 37, 28, 43, 35, 37, 58, 43, 65, 37, 8, 55, 16, 50, 38, + 55, 50, 50, 68, 55, 4, 6, 29, 0, 38, 6, 63, 0, 72, 6, + 14, 13, 26, 18, 44, 13, 60, 18, 74, 13, 14, 30, 24, 25, 47, + 31, 54, 25, 77, 31, 4, 37, 27, 43, 34, 37, 57, 43, 64, 37, + 7, 55, 17, 50, 37, 55, 51, 50, 67, 55, 5, 6, 30, 0, 39, + 6, 63, 1, 73, 6, 13, 13, 27, 18, 43, 13, 61, 18, 73, 13, + 15, 30, 23, 25, 46, 31, 53, 25, 76, 31, 3, 37, 26, 43, 33, + 37, 56, 43, 64, 38, 6, 55, 18, 50, 36, 55, 52, 50, 66, 55, + 6, 6, 31, 0, 40, 6, 62, 1, 74, 6, 12, 13, 28, 18, 42, + 13, 62, 18, 72, 13, 15, 31, 22, 25, 45, 31, 52, 25, 75, 31, + 2, 37, 25, 43, 32, 37, 55, 43, 65, 38, 5, 55, 19, 50, 35, + 55, 53, 50, 65, 55, 7, 6, 31, 1, 41, 6, 61, 1, 75, 6, + 11, 13, 29, 18, 41, 13, 63, 18, 71, 13, 14, 31, 21, 25, 44, + 31, 51, 25, 74, 31, 1, 37, 24, 43, 32, 38, 54, 43, 66, 38, + 4, 55, 20, 50, 34, 55, 54, 50, 64, 55, 8, 6, 30, 1, 42, + 6, 60, 1, 76, 6, 10, 13, 30, 18, 40, 13, 63, 19, 70, 13, + 13, 31, 20, 25, 43, 31, 50, 25, 73, 31, 0, 37, 23, 43, 33, + 38, 53, 43, 67, 38, 3, 55, 21, 50, 33, 55, 55, 50, 64, 56, + 9, 6, 29, 1, 43, 6, 59, 1, 77, 6, 9, 13, 31, 18, 39, + 13, 62, 19, 69, 13, 12, 31, 19, 25, 42, 31, 49, 25, 72, 31, + 0, 38, 22, 43, 34, 38, 52, 43, 68, 38, 2, 55, 22, 50, 32, + 55, 56, 50, 65, 56, 10, 6, 28, 1, 44, 6, 58, 1, 78, 6, + 8, 13, 31, 19, 38, 13, 61, 19, 68, 13, 11, 31, 18, 25, 41, + 31, 48, 25, 71, 31, 1, 38, 21, 43, 35, 38, 51, 43, 69, 38, + 1, 55, 23, 50, 32, 56, 57, 50, 66, 56, 11, 6, 27, 1, 45, + 6, 57, 1, 79, 6, 7, 13, 30, 19, 37, 13, 60, 19, 67, 13, + 10, 31, 17, 25, 40, 31, 48, 26, 70, 31, 2, 38, 20, 43, 36, + 38, 50, 43, 70, 38, 0, 55, 24, 50, 33, 56, 58, 50, 67, 56, + 12, 6, 26, 1, 46, 6, 56, 1, 79, 7, 6, 13, 29, 19, 36, + 13, 59, 19, 66, 13, 9, 31, 16, 25, 39, 31, 49, 26, 69, 31, + 3, 38, 19, 43, 37, 38, 49, 43, 71, 38, 0, 56, 25, 50, 34, + 56, 59, 50, 68, 56, 13, 6, 25, 1, 47, 6, 55, 1, 78, 7, + 5, 13, 28, 19, 35, 13, 58, 19, 65, 13, 8, 31, 16, 26, 38, + 31, 50, 26, 68, 31, 4, 38, 18, 43, 38, 38, 48, 43, 72, 38, + 1, 56, 26, 50, 35, 56, 60, 50, 69, 56, 14, 6, 24, 1, 47, + 7, 54, 1, 77, 7, 4, 13, 27, 19, 34, 13, 57, 19, 64, 13, + 7, 31, 17, 26, 37, 31, 51, 26, 67, 31, 5, 38, 17, 43, 39, + 38, 48, 44, 73, 38, 2, 56, 27, 50, 36, 56, 61, 50, 70, 56, + 15, 6, 23, 1, 46, 7, 53, 1, 76, 7, 3, 13, 26, 19, 33, + 13, 56, 19, 64, 14, 6, 31, 18, 26, 36, 31, 52, 26, 66, 31, + 6, 38, 16, 43, 40, 38, 49, 44, 74, 38, 3, 56, 28, 50, 37, + 56, 62, 50, 71, 56, 15, 7, 22, 1, 45, 7, 52, 1, 75, 7, + 2, 13, 25, 19, 32, 13, 55, 19, 65, 14, 5, 31, 19, 26, 35, + 31, 53, 26, 65, 31, 7, 38, 16, 44, 41, 38, 50, 44, 75, 38, + 4, 56, 29, 50, 38, 56, 63, 50, 72, 56, 14, 7, 21, 1, 44, + 7, 51, 1, 74, 7, 1, 13, 24, 19, 32, 14, 54, 19, 66, 14, + 4, 31, 20, 26, 34, 31, 54, 26, 64, 31, 8, 38, 17, 44, 42, + 38, 51, 44, 76, 38, 5, 56, 30, 50, 39, 56, 63, 51, 73, 56, + 13, 7, 20, 1, 43, 7, 50, 1, 73, 7, 0, 13, 23, 19, 33, + 14, 53, 19, 67, 14, 3, 31, 21, 26, 33, 31, 55, 26, 64, 32, + 9, 38, 18, 44, 43, 38, 52, 44, 77, 38, 6, 56, 31, 50, 40, + 56, 62, 51, 74, 56, 12, 7, 19, 1, 42, 7, 49, 1, 72, 7, + 0, 14, 22, 19, 34, 14, 52, 19, 68, 14, 2, 31, 22, 26, 32, + 31, 56, 26, 65, 32, 10, 38, 19, 44, 44, 38, 53, 44, 78, 38, + 7, 56, 31, 51, 41, 56, 61, 51, 75, 56, 11, 7, 18, 1, 41, + 7, 48, 1, 71, 7, 1, 14, 21, 19, 35, 14, 51, 19, 69, 14, + 1, 31, 23, 26, 32, 32, 57, 26, 66, 32, 11, 38, 20, 44, 45, + 38, 54, 44, 79, 38, 8, 56, 30, 51, 42, 56, 60, 51, 76, 56, + 10, 7, 17, 1, 40, 7, 48, 2, 70, 7, 2, 14, 20, 19, 36, + 14, 50, 19, 70, 14, 0, 31, 24, 26, 33, 32, 58, 26, 67, 32, + 12, 38, 21, 44, 46, 38, 55, 44, 79, 39, 9, 56, 29, 51, 43, + 56, 59, 51, 77, 56, 9, 7, 16, 1, 39, 7, 49, 2, 69, 7, + 3, 14, 19, 19, 37, 14, 49, 19, 71, 14, 0, 32, 25, 26, 34, + 32, 59, 26, 68, 32, 13, 38, 22, 44, 47, 38, 56, 44, 78, 39, + 10, 56, 28, 51, 44, 56, 58, 51, 78, 56, 8, 7, 16, 2, 38, + 7, 50, 2, 68, 7, 4, 14, 18, 19, 38, 14, 48, 19, 72, 14, + 1, 32, 26, 26, 35, 32, 60, 26, 69, 32, 14, 38, 23, 44, 47, + 39, 57, 44, 77, 39, 11, 56, 27, 51, 45, 56, 57, 51, 79, 56, + 7, 7, 17, 2, 37, 7, 51, 2, 67, 7, 5, 14, 17, 19, 39, + 14, 48, 20, 73, 14, 2, 32, 27, 26, 36, 32, 61, 26, 70, 32, + 15, 38, 24, 44, 46, 39, 58, 44, 76, 39, 12, 56, 26, 51, 46, + 56, 56, 51, 79, 57, 6, 7, 18, 2, 36, 7, 52, 2, 66, 7, + 6, 14, 16, 19, 40, 14, 49, 20, 74, 14, 3, 32, 28, 26, 37, + 32, 62, 26, 71, 32, 15, 39, 25, 44, 45, 39, 59, 44, 75, 39, + 13, 56, 25, 51, 47, 56, 55, 51, 78, 57, 5, 7, 19, 2, 35, + 7, 53, 2, 65, 7, 7, 14, 16, 20, 41, 14, 50, 20, 75, 14, + 4, 32, 29, 26, 38, 32, 63, 26, 72, 32, 14, 39, 26, 44, 44, + 39, 60, 44, 74, 39, 14, 56, 24, 51, 47, 57, 54, 51, 77, 57, + 4, 7, 20, 2, 34, 7, 54, 2, 64, 7, 8, 14, 17, 20, 42, + 14, 51, 20, 76, 14, 5, 32, 30, 26, 39, 32, 63, 27, 73, 32, + 13, 39, 27, 44, 43, 39, 61, 44, 73, 39, 15, 56, 23, 51, 46, + 57, 53, 51, 76, 57, 3, 7, 21, 2, 33, 7, 55, 2, 64, 8, + 9, 14, 18, 20, 43, 14, 52, 20, 77, 14, 6, 32, 31, 26, 40, + 32, 62, 27, 74, 32, 12, 39, 28, 44, 42, 39, 62, 44, 72, 39, + 15, 57, 22, 51, 45, 57, 52, 51, 75, 57, 2, 7, 22, 2, 32, + 7, 56, 2, 65, 8, 10, 14, 19, 20, 44, 14, 53, 20, 78, 14, + 7, 32, 31, 27, 41, 32, 61, 27, 75, 32, 11, 39, 29, 44, 41, + 39, 63, 44, 71, 39, 14, 57, 21, 51, 44, 57, 51, 51, 74, 57, + 1, 7, 23, 2, 32, 8, 57, 2, 66, 8, 11, 14, 20, 20, 45, + 14, 54, 20, 79, 14, 8, 32, 30, 27, 42, 32, 60, 27, 76, 32, + 10, 39, 30, 44, 40, 39, 63, 45, 70, 39, 13, 57, 20, 51, 43, + 57, 50, 51, 73, 57, 0, 7, 24, 2, 33, 8, 58, 2, 67, 8, + 12, 14, 21, 20, 46, 14, 55, 20, 79, 15, 9, 32, 29, 27, 43, + 32, 59, 27, 77, 32, 9, 39, 31, 44, 39, 39, 62, 45, 69, 39, + 12, 57, 19, 51, 42, 57, 49, 51, 72, 57, 0, 8, 25, 2, 34, + 8, 59, 2, 68, 8, 13, 14, 22, 20, 47, 14, 56, 20, 78, 15, + 10, 32, 28, 27, 44, 32, 58, 27, 78, 32, 8, 39, 31, 45, 38, + 39, 61, 45, 68, 39, 11, 57, 18, 51, 41, 57, 48, 51, 71, 57, + 1, 8, 26, 2, 35, 8, 60, 2, 69, 8, 14, 14, 23, 20, 47, + 15, 57, 20, 77, 15, 11, 32, 27, 27, 45, 32, 57, 27, 79, 32, + 7, 39, 30, 45, 37, 39, 60, 45, 67, 39, 10, 57, 17, 51, 40, + 57, 48, 52, 70, 57, 2, 8, 27, 2, 36, 8, 61, 2, 70, 8, + 15, 14, 24, 20, 46, 15, 58, 20, 76, 15, 12, 32, 26, 27, 46, + 32, 56, 27, 79, 33, 6, 39, 29, 45, 36, 39, 59, 45, 66, 39, + 9, 57, 16, 51, 39, 57, 49, 52, 69, 57, 3, 8, 28, 2, 37, + 8, 62, 2, 71, 8, 15, 15, 25, 20, 45, 15, 59, 20, 75, 15, + 13, 32, 25, 27, 47, 32, 55, 27, 78, 33, 5, 39, 28, 45, 35, + 39, 58, 45, 65, 39, 8, 57, 16, 52, 38, 57, 50, 52, 68, 57, + 4, 8, 29, 2, 38, 8, 63, 2, 72, 8, 14, 15, 26, 20, 44, + 15, 60, 20, 74, 15, 14, 32, 24, 27, 47, 33, 54, 27, 77, 33, + 4, 39, 27, 45, 34, 39, 57, 45, 64, 39, 7, 57, 17, 52, 37, + 57, 51, 52, 67, 57, 5, 8, 30, 2, 39, 8, 63, 3, 73, 8, + 13, 15, 27, 20, 43, 15, 61, 20, 73, 15, 15, 32, 23, 27, 46, + 33, 53, 27, 76, 33, 3, 39, 26, 45, 33, 39, 56, 45, 64, 40, + 6, 57, 18, 52, 36, 57, 52, 52, 66, 57, 6, 8, 31, 2, 40, + 8, 62, 3, 74, 8, 12, 15, 28, 20, 42, 15, 62, 20, 72, 15, + 15, 33, 22, 27, 45, 33, 52, 27, 75, 33, 2, 39, 25, 45, 32, + 39, 55, 45, 65, 40, 5, 57, 19, 52, 35, 57, 53, 52, 65, 57, + 7, 8, 31, 3, 41, 8, 61, 3, 75, 8, 11, 15, 29, 20, 41, + 15, 63, 20, 71, 15, 14, 33, 21, 27, 44, 33, 51, 27, 74, 33, + 1, 39, 24, 45, 32, 40, 54, 45, 66, 40, 4, 57, 20, 52, 34, + 57, 54, 52, 64, 57, 8, 8, 30, 3, 42, 8, 60, 3, 76, 8, + 10, 15, 30, 20, 40, 15, 63, 21, 70, 15, 13, 33, 20, 27, 43, + 33, 50, 27, 73, 33, 0, 39, 23, 45, 33, 40, 53, 45, 67, 40, + 3, 57, 21, 52, 33, 57, 55, 52, 64, 58, 9, 8, 29, 3, 43, + 8, 59, 3, 77, 8, 9, 15, 31, 20, 39, 15, 62, 21, 69, 15, + 12, 33, 19, 27, 42, 33, 49, 27, 72, 33, 0, 40, 22, 45, 34, + 40, 52, 45, 68, 40, 2, 57, 22, 52, 32, 57, 56, 52, 65, 58, + 10, 8, 28, 3, 44, 8, 58, 3, 78, 8, 8, 15, 31, 21, 38, + 15, 61, 21, 68, 15, 11, 33, 18, 27, 41, 33, 48, 27, 71, 33, + 1, 40, 21, 45, 35, 40, 51, 45, 69, 40, 1, 57, 23, 52, 32, + 58, 57, 52, 66, 58, 11, 8, 27, 3, 45, 8, 57, 3, 79, 8, + 7, 15, 30, 21, 37, 15, 60, 21, 67, 15, 10, 33, 17, 27, 40, + 33, 48, 28, 70, 33, 2, 40, 20, 45, 36, 40, 50, 45, 70, 40, + 0, 57, 24, 52, 33, 58, 58, 52, 67, 58, 12, 8, 26, 3, 46, + 8, 56, 3, 79, 9, 6, 15, 29, 21, 36, 15, 59, 21, 66, 15, + 9, 33, 16, 27, 39, 33, 49, 28, 69, 33, 3, 40, 19, 45, 37, + 40, 49, 45, 71, 40, 0, 58, 25, 52, 34, 58, 59, 52, 68, 58, + 13, 8, 25, 3, 47, 8, 55, 3, 78, 9, 5, 15, 28, 21, 35, + 15, 58, 21, 65, 15, 8, 33, 16, 28, 38, 33, 50, 28, 68, 33, + 4, 40, 18, 45, 38, 40, 48, 45, 72, 40, 1, 58, 26, 52, 35, + 58, 60, 52, 69, 58, 14, 8, 24, 3, 47, 9, 54, 3, 77, 9, + 4, 15, 27, 21, 34, 15, 57, 21, 64, 15, 7, 33, 17, 28, 37, + 33, 51, 28, 67, 33, 5, 40, 17, 45, 39, 40, 48, 46, 73, 40, + 2, 58, 27, 52, 36, 58, 61, 52, 70, 58, 15, 8, 23, 3, 46, + 9, 53, 3, 76, 9, 3, 15, 26, 21, 33, 15, 56, 21, 64, 16, + 6, 33, 18, 28, 36, 33, 52, 28, 66, 33, 6, 40, 16, 45, 40, + 40, 49, 46, 74, 40, 3, 58, 28, 52, 37, 58, 62, 52, 71, 58, + 15, 9, 22, 3, 45, 9, 52, 3, 75, 9, 2, 15, 25, 21, 32, + 15, 55, 21, 65, 16, 5, 33, 19, 28, 35, 33, 53, 28, 65, 33, + 7, 40, 16, 46, 41, 40, 50, 46, 75, 40, 4, 58, 29, 52, 38, + 58, 63, 52, 72, 58, 14, 9, 21, 3, 44, 9, 51, 3, 74, 9, + 1, 15, 24, 21, 32, 16, 54, 21, 66, 16, 4, 33, 20, 28, 34, + 33, 54, 28, 64, 33, 8, 40, 17, 46, 42, 40, 51, 46, 76, 40, + 5, 58, 30, 52, 39, 58, 63, 53, 73, 58, 13, 9, 20, 3, 43, + 9, 50, 3, 73, 9, 0, 15, 23, 21, 33, 16, 53, 21, 67, 16, + 3, 33, 21, 28, 33, 33, 55, 28, 64, 34, 9, 40, 18, 46, 43, + 40, 52, 46, 77, 40, 6, 58, 31, 52, 40, 58, 62, 53, 74, 58, + 12, 9, 19, 3, 42, 9, 49, 3, 72, 9, 0, 16, 22, 21, 34, + 16, 52, 21, 68, 16, 2, 33, 22, 28, 32, 33, 56, 28, 65, 34, + 10, 40, 19, 46, 44, 40, 53, 46, 78, 40, 7, 58, 31, 53, 41, + 58, 61, 53, 75, 58, 11, 9, 18, 3, 41, 9, 48, 3, 71, 9, + 1, 16, 21, 21, 35, 16, 51, 21, 69, 16, 1, 33, 23, 28, 32, + 34, 57, 28, 66, 34, 11, 40, 20, 46, 45, 40, 54, 46, 79, 40, + 8, 58, 30, 53, 42, 58, 60, 53, 76, 58, 10, 9, 17, 3, 40, + 9, 48, 4, 70, 9, 2, 16, 20, 21, 36, 16, 50, 21, 70, 16, + 0, 33, 24, 28, 33, 34, 58, 28, 67, 34, 12, 40, 21, 46, 46, + 40, 55, 46, 79, 41, 9, 58, 29, 53, 43, 58, 59, 53, 77, 58, + 9, 9, 16, 3, 39, 9, 49, 4, 69, 9, 3, 16, 19, 21, 37, + 16, 49, 21, 71, 16, 0, 34, 25, 28, 34, 34, 59, 28, 68, 34, + 13, 40, 22, 46, 47, 40, 56, 46, 78, 41, 10, 58, 28, 53, 44, + 58, 58, 53, 78, 58, 8, 9, 16, 4, 38, 9, 50, 4, 68, 9, + 4, 16, 18, 21, 38, 16, 48, 21, 72, 16, 1, 34, 26, 28, 35, + 34, 60, 28, 69, 34, 14, 40, 23, 46, 47, 41, 57, 46, 77, 41, + 11, 58, 27, 53, 45, 58, 57, 53, 79, 58, 7, 9, 17, 4, 37, + 9, 51, 4, 67, 9, 5, 16, 17, 21, 39, 16, 48, 22, 73, 16, + 2, 34, 27, 28, 36, 34, 61, 28, 70, 34, 15, 40, 24, 46, 46, + 41, 58, 46, 76, 41, 12, 58, 26, 53, 46, 58, 56, 53, 79, 59, + 6, 9, 18, 4, 36, 9, 52, 4, 66, 9, 6, 16, 16, 21, 40, + 16, 49, 22, 74, 16, 3, 34, 28, 28, 37, 34, 62, 28, 71, 34, + 15, 41, 25, 46, 45, 41, 59, 46, 75, 41, 13, 58, 25, 53, 47, + 58, 55, 53, 78, 59, 5, 9, 19, 4, 35, 9, 53, 4, 65, 9, + 7, 16, 16, 22, 41, 16, 50, 22, 75, 16, 4, 34, 29, 28, 38, + 34, 63, 28, 72, 34, 14, 41, 26, 46, 44, 41, 60, 46, 74, 41, + 14, 58, 24, 53, 47, 59, 54, 53, 77, 59, 4, 9, 20, 4, 34, + 9, 54, 4, 64, 9, 8, 16, 17, 22, 42, 16, 51, 22, 76, 16, + 5, 34, 30, 28, 39, 34, 63, 29, 73, 34, 13, 41, 27, 46, 43, + 41, 61, 46, 73, 41, 15, 58, 23, 53, 46, 59, 53, 53, 76, 59, + 3, 9, 21, 4, 33, 9, 55, 4, 64, 10, 9, 16, 18, 22, 43, + 16, 52, 22, 77, 16, 6, 34, 31, 28, 40, 34, 62, 29, 74, 34, + 12, 41, 28, 46, 42, 41, 62, 46, 72, 41, 15, 59, 22, 53, 45, + 59, 52, 53, 75, 59, 2, 9, 22, 4, 32, 9, 56, 4, 65, 10, + 10, 16, 19, 22, 44, 16, 53, 22, 78, 16, 7, 34, 31, 29, 41, + 34, 61, 29, 75, 34, 11, 41, 29, 46, 41, 41, 63, 46, 71, 41, + 14, 59, 21, 53, 44, 59, 51, 53, 74, 59, 1, 9, 23, 4, 32, + 10, 57, 4, 66, 10, 11, 16, 20, 22, 45, 16, 54, 22, 79, 16, + 8, 34, 30, 29, 42, 34, 60, 29, 76, 34, 10, 41, 30, 46, 40, + 41, 63, 47, 70, 41, 13, 59, 20, 53, 43, 59, 50, 53, 73, 59, + 0, 9, 24, 4, 33, 10, 58, 4, 67, 10, 12, 16, 21, 22, 46, + 16, 55, 22, 79, 17, 9, 34, 29, 29, 43, 34, 59, 29, 77, 34, + 9, 41, 31, 46, 39, 41, 62, 47, 69, 41, 12, 59, 19, 53, 42, + 59, 49, 53, 72, 59, 0, 10, 25, 4, 34, 10, 59, 4, 68, 10, + 13, 16, 22, 22, 47, 16, 56, 22, 78, 17, 10, 34, 28, 29, 44, + 34, 58, 29, 78, 34, 8, 41, 31, 47, 38, 41, 61, 47, 68, 41, + 11, 59, 18, 53, 41, 59, 48, 53, 71, 59, 1, 10, 26, 4, 35, + 10, 60, 4, 69, 10, 14, 16, 23, 22, 47, 17, 57, 22, 77, 17, + 11, 34, 27, 29, 45, 34, 57, 29, 79, 34, 7, 41, 30, 47, 37, + 41, 60, 47, 67, 41, 10, 59, 17, 53, 40, 59, 48, 54, 70, 59, + 2, 10, 27, 4, 36, 10, 61, 4, 70, 10, 15, 16, 24, 22, 46, + 17, 58, 22, 76, 17, 12, 34, 26, 29, 46, 34, 56, 29, 79, 35, + 6, 41, 29, 47, 36, 41, 59, 47, 66, 41, 9, 59, 16, 53, 39, + 59, 49, 54, 69, 59, 3, 10, 28, 4, 37, 10, 62, 4, 71, 10, + 15, 17, 25, 22, 45, 17, 59, 22, 75, 17, 13, 34, 25, 29, 47, + 34, 55, 29, 78, 35, 5, 41, 28, 47, 35, 41, 58, 47, 65, 41, + 8, 59, 16, 54, 38, 59, 50, 54, 68, 59, 4, 10, 29, 4, 38, + 10, 63, 4, 72, 10, 14, 17, 26, 22, 44, 17, 60, 22, 74, 17, + 14, 34, 24, 29, 47, 35, 54, 29, 77, 35, 4, 41, 27, 47, 34, + 41, 57, 47, 64, 41, 7, 59, 17, 54, 37, 59, 51, 54, 67, 59, + 5, 10, 30, 4, 39, 10, 63, 5, 73, 10, 13, 17, 27, 22, 43, + 17, 61, 22, 73, 17, 15, 34, 23, 29, 46, 35, 53, 29, 76, 35, + 3, 41, 26, 47, 33, 41, 56, 47, 64, 42, 6, 59, 18, 54, 36, + 59, 52, 54, 66, 59, 6, 10, 31, 4, 40, 10, 62, 5, 74, 10, + 12, 17, 28, 22, 42, 17, 62, 22, 72, 17, 15, 35, 22, 29, 45, + 35, 52, 29, 75, 35, 2, 41, 25, 47, 32, 41, 55, 47, 65, 42, + 5, 59, 19, 54, 35, 59, 53, 54, 65, 59, 7, 10, 31, 5, 41, + 10, 61, 5, 75, 10, 11, 17, 29, 22, 41, 17, 63, 22, 71, 17, + 14, 35, 21, 29, 44, 35, 51, 29, 74, 35, 1, 41, 24, 47, 32, + 42, 54, 47, 66, 42, 4, 59, 20, 54, 34, 59, 54, 54, 64, 59, + 8, 10, 30, 5, 42, 10, 60, 5, 76, 10, 10, 17, 30, 22, 40, + 17, 63, 23, 70, 17, 13, 35, 20, 29, 43, 35, 50, 29, 73, 35, + 0, 41, 23, 47, 33, 42, 53, 47, 67, 42, 3, 59, 21, 54, 33, + 59, 55, 54, 64, 48, 9, 10, 29, 5, 43, 10, 59, 5, 77, 10, + 9, 17, 31, 22, 39, 17, 62, 23, 69, 17, 12, 35, 19, 29, 42, + 35, 49, 29, 72, 35, 0, 42, 22, 47, 34, 42, 52, 47, 68, 42, + 2, 59, 22, 54, 32, 59, 56, 54, 65, 48, 10, 10, 28, 5, 44, + 10, 58, 5, 78, 10, 8, 17, 31, 23, 38, 17, 61, 23, 68, 17, + 11, 35, 18, 29, 41, 35, 48, 29, 71, 35, 1, 42, 21, 47, 35, + 42, 51, 47, 69, 42, 1, 59, 23, 54, 32, 48, 57, 54, 66, 48, + 11, 10, 27, 5, 45, 10, 57, 5, 79, 10, 7, 17, 30, 23, 37, + 17, 60, 23, 67, 17, 10, 35, 17, 29, 40, 35, 48, 30, 70, 35, + 2, 42, 20, 47, 36, 42, 50, 47, 70, 42, 0, 59, 24, 54, 33, + 48, 58, 54, 67, 48, 12, 10, 26, 5, 46, 10, 56, 5, 79, 11, + 6, 17, 29, 23, 36, 17, 59, 23, 66, 17, 9, 35, 16, 29, 39, + 35, 49, 30, 69, 35, 3, 42, 19, 47, 37, 42, 49, 47, 71, 42, + 0, 48, 25, 54, 34, 48, 59, 54, 68, 48, 13, 10, 25, 5, 47, + 10, 55, 5, 78, 11, 5, 17, 28, 23, 35, 17, 58, 23, 65, 17, + 8, 35, 16, 30, 38, 35, 50, 30, 68, 35, 4, 42, 18, 47, 38, + 42, 48, 47, 72, 42, 1, 48, 26, 54, 35, 48, 60, 54, 69, 48, + 14, 10, 24, 5, 47, 11, 54, 5, 77, 11, 4, 17, 27, 23, 34, + 17, 57, 23, 64, 17, 7, 35, 17, 30, 37, 35, 51, 30, 67, 35, + 5, 42, 17, 47, 39, 42, 48, 36, 73, 42, 2, 48, 27, 54, 36, + 48, 61, 54, 70, 48, 15, 10, 23, 5, 46, 11, 53, 5, 76, 11, + 3, 17, 26, 23, 33, 17, 56, 23, 64, 18, 6, 35, 18, 30, 36, + 35, 52, 30, 66, 35, 6, 42, 16, 47, 40, 42, 49, 36, 74, 42, + 3, 48, 28, 54, 37, 48, 62, 54, 71, 48, 15, 11, 22, 5, 45, + 11, 52, 5, 75, 11, 2, 17, 25, 23, 32, 17, 55, 23, 65, 18, + 5, 35, 19, 30, 35, 35, 53, 30, 65, 35, 7, 42, 16, 36, 41, + 42, 50, 36, 75, 42, 4, 48, 29, 54, 38, 48, 63, 54, 72, 48, + 14, 11, 21, 5, 44, 11, 51, 5, 74, 11, 1, 17, 24, 23, 32, + 18, 54, 23, 66, 18, 4, 35, 20, 30, 34, 35, 54, 30, 64, 35, + 8, 42, 17, 36, 42, 42, 51, 36, 76, 42, 5, 48, 30, 54, 39, + 48, 63, 55, 73, 48, 13, 11, 20, 5, 43, 11, 50, 5, 73, 11, + 0, 17, 23, 23, 33, 18, 53, 23, 67, 18, 3, 35, 21, 30, 33, + 35, 55, 30, 64, 24, 9, 42, 18, 36, 43, 42, 52, 36, 77, 42, + 6, 48, 31, 54, 40, 48, 62, 55, 74, 48, 12, 11, 19, 5, 42, + 11, 49, 5, 72, 11, 0, 18, 22, 23, 34, 18, 52, 23, 68, 18, + 2, 35, 22, 30, 32, 35, 56, 30, 65, 24, 10, 42, 19, 36, 44, + 42, 53, 36, 78, 42, 7, 48, 31, 55, 41, 48, 61, 55, 75, 48, + 11, 11, 18, 5, 41, 11, 48, 5, 71, 11, 1, 18, 21, 23, 35, + 18, 51, 23, 69, 18, 1, 35, 23, 30, 32, 24, 57, 30, 66, 24, + 11, 42, 20, 36, 45, 42, 54, 36, 79, 42, 8, 48, 30, 55, 42, + 48, 60, 55, 76, 48, 10, 11, 17, 5, 40, 11, 48, 6, 70, 11, + 2, 18, 20, 23, 36, 18, 50, 23, 70, 18, 0, 35, 24, 30, 33, + 24, 58, 30, 67, 24, 12, 42, 21, 36, 46, 42, 55, 36, 79, 43, + 9, 48, 29, 55, 43, 48, 59, 55, 77, 48, 9, 11, 16, 5, 39, + 11, 49, 6, 69, 11, 3, 18, 19, 23, 37, 18, 49, 23, 71, 18, + 0, 24, 25, 30, 34, 24, 59, 30, 68, 24, 13, 42, 22, 36, 47, + 42, 56, 36, 78, 43, 10, 48, 28, 55, 44, 48, 58, 55, 78, 48, + 8, 11, 16, 6, 38, 11, 50, 6, 68, 11, 4, 18, 18, 23, 38, + 18, 48, 23, 72, 18, 1, 24, 26, 30, 35, 24, 60, 30, 69, 24, + 14, 42, 23, 36, 47, 43, 57, 36, 77, 43, 11, 48, 27, 55, 45, + 48, 57, 55, 79, 48, 7, 11, 17, 6, 37, 11, 51, 6, 67, 11, + 5, 18, 17, 23, 39, 18, 48, 12, 73, 18, 2, 24, 27, 30, 36, + 24, 61, 30, 70, 24, 15, 42, 24, 36, 46, 43, 58, 36, 76, 43, + 12, 48, 26, 55, 46, 48, 56, 55, 79, 49, 6, 11, 18, 6, 36, + 11, 52, 6, 66, 11, 6, 18, 16, 23, 40, 18, 49, 12, 74, 18, + 3, 24, 28, 30, 37, 24, 62, 30, 71, 24, 15, 43, 25, 36, 45, + 43, 59, 36, 75, 43, 13, 48, 25, 55, 47, 48, 55, 55, 78, 49, + 5, 11, 19, 6, 35, 11, 53, 6, 65, 11, 7, 18, 16, 12, 41, + 18, 50, 12, 75, 18, 4, 24, 29, 30, 38, 24, 63, 30, 72, 24, + 14, 43, 26, 36, 44, 43, 60, 36, 74, 43, 14, 48, 24, 55, 47, + 49, 54, 55, 77, 49, 4, 11, 20, 6, 34, 11, 54, 6, 64, 11, + 8, 18, 17, 12, 42, 18, 51, 12, 76, 18, 5, 24, 30, 30, 39, + 24, 63, 31, 73, 24, 13, 43, 27, 36, 43, 43, 61, 36, 73, 43, + 15, 48, 23, 55, 46, 49, 53, 55, 76, 49, 3, 11, 21, 6, 33, + 11, 55, 6, 64, 0, 9, 18, 18, 12, 43, 18, 52, 12, 77, 18, + 6, 24, 31, 30, 40, 24, 62, 31, 74, 24, 12, 43, 28, 36, 42, + 43, 62, 36, 72, 43, 15, 49, 22, 55, 45, 49, 52, 55, 75, 49, + 2, 11, 22, 6, 32, 11, 56, 6, 65, 0, 10, 18, 19, 12, 44, + 18, 53, 12, 78, 18, 7, 24, 31, 31, 41, 24, 61, 31, 75, 24, + 11, 43, 29, 36, 41, 43, 63, 36, 71, 43, 14, 49, 21, 55, 44, + 49, 51, 55, 74, 49, 1, 11, 23, 6, 32, 0, 57, 6, 66, 0, + 11, 18, 20, 12, 45, 18, 54, 12, 79, 18, 8, 24, 30, 31, 42, + 24, 60, 31, 76, 24, 10, 43, 30, 36, 40, 43, 63, 37, 70, 43, + 13, 49, 20, 55, 43, 49, 50, 55, 73, 49, 0, 11, 24, 6, 33, + 0, 58, 6, 67, 0, 12, 18, 21, 12, 46, 18, 55, 12, 79, 19, + 9, 24, 29, 31, 43, 24, 59, 31, 77, 24, 9, 43, 31, 36, 39, + 43, 62, 37, 69, 43, 12, 49, 19, 55, 42, 49, 49, 55, 72, 49, +}; + +static const uint8_t hq_tab_19[] = { + 0, 0, 25, 4, 34, 0, 59, 4, 12, 12, 21, 8, 46, 12, 55, + 8, 8, 16, 30, 21, 42, 16, 60, 21, 11, 29, 29, 24, 41, 29, + 63, 24, 15, 33, 22, 37, 45, 33, 52, 37, 3, 45, 26, 41, 33, + 45, 56, 41, 1, 0, 26, 4, 35, 0, 60, 4, 13, 12, 22, 8, + 47, 12, 56, 8, 9, 16, 29, 21, 43, 16, 59, 21, 10, 29, 30, + 24, 40, 29, 63, 25, 14, 33, 21, 37, 44, 33, 51, 37, 2, 45, + 25, 41, 32, 45, 55, 41, 2, 0, 27, 4, 36, 0, 61, 4, 14, + 12, 23, 8, 47, 13, 57, 8, 10, 16, 28, 21, 44, 16, 58, 21, + 9, 29, 31, 24, 39, 29, 62, 25, 13, 33, 20, 37, 43, 33, 50, + 37, 1, 45, 24, 41, 32, 46, 54, 41, 3, 0, 28, 4, 37, 0, + 62, 4, 15, 12, 24, 8, 46, 13, 58, 8, 11, 16, 27, 21, 45, + 16, 57, 21, 8, 29, 31, 25, 38, 29, 61, 25, 12, 33, 19, 37, + 42, 33, 49, 37, 0, 45, 23, 41, 33, 46, 53, 41, 4, 0, 29, + 4, 38, 0, 63, 4, 15, 13, 25, 8, 45, 13, 59, 8, 12, 16, + 26, 21, 46, 16, 56, 21, 7, 29, 30, 25, 37, 29, 60, 25, 11, + 33, 18, 37, 41, 33, 48, 37, 0, 46, 22, 41, 34, 46, 52, 41, + 5, 0, 30, 4, 39, 0, 63, 5, 14, 13, 26, 8, 44, 13, 60, + 8, 13, 16, 25, 21, 47, 16, 55, 21, 6, 29, 29, 25, 36, 29, + 59, 25, 10, 33, 17, 37, 40, 33, 48, 38, 1, 46, 21, 41, 35, + 46, 51, 41, 6, 0, 31, 4, 40, 0, 62, 5, 13, 13, 27, 8, + 43, 13, 61, 8, 14, 16, 24, 21, 47, 17, 54, 21, 5, 29, 28, + 25, 35, 29, 58, 25, 9, 33, 16, 37, 39, 33, 49, 38, 2, 46, + 20, 41, 36, 46, 50, 41, 7, 0, 31, 5, 41, 0, 61, 5, 12, + 13, 28, 8, 42, 13, 62, 8, 15, 16, 23, 21, 46, 17, 53, 21, + 4, 29, 27, 25, 34, 29, 57, 25, 8, 33, 16, 38, 38, 33, 50, + 38, 3, 46, 19, 41, 37, 46, 49, 41, 8, 0, 30, 5, 42, 0, + 60, 5, 11, 13, 29, 8, 41, 13, 63, 8, 15, 17, 22, 21, 45, + 17, 52, 21, 3, 29, 26, 25, 33, 29, 56, 25, 7, 33, 17, 38, + 37, 33, 51, 38, 4, 46, 18, 41, 38, 46, 48, 41, 9, 0, 29, + 5, 43, 0, 59, 5, 10, 13, 30, 8, 40, 13, 63, 9, 14, 17, + 21, 21, 44, 17, 51, 21, 2, 29, 25, 25, 32, 29, 55, 25, 6, + 33, 18, 38, 36, 33, 52, 38, 5, 46, 17, 41, 39, 46, 48, 42, + 10, 0, 28, 5, 44, 0, 58, 5, 9, 13, 31, 8, 39, 13, 62, + 9, 13, 17, 20, 21, 43, 17, 50, 21, 1, 29, 24, 25, 32, 30, + 54, 25, 5, 33, 19, 38, 35, 33, 53, 38, 6, 46, 16, 41, 40, + 46, 49, 42, 11, 0, 27, 5, 45, 0, 57, 5, 8, 13, 31, 9, + 38, 13, 61, 9, 12, 17, 19, 21, 42, 17, 49, 21, 0, 29, 23, + 25, 33, 30, 53, 25, 4, 33, 20, 38, 34, 33, 54, 38, 7, 46, + 16, 42, 41, 46, 50, 42, 12, 0, 26, 5, 46, 0, 56, 5, 7, + 13, 30, 9, 37, 13, 60, 9, 11, 17, 18, 21, 41, 17, 48, 21, + 0, 30, 22, 25, 34, 30, 52, 25, 3, 33, 21, 38, 33, 33, 55, + 38, 8, 46, 17, 42, 42, 46, 51, 42, 13, 0, 25, 5, 47, 0, + 55, 5, 6, 13, 29, 9, 36, 13, 59, 9, 10, 17, 17, 21, 40, + 17, 48, 22, 1, 30, 21, 25, 35, 30, 51, 25, 2, 33, 22, 38, + 32, 33, 56, 38, 9, 46, 18, 42, 43, 46, 52, 42, 14, 0, 24, + 5, 47, 1, 54, 5, 5, 13, 28, 9, 35, 13, 58, 9, 9, 17, + 16, 21, 39, 17, 49, 22, 2, 30, 20, 25, 36, 30, 50, 25, 1, + 33, 23, 38, 32, 34, 57, 38, 10, 46, 19, 42, 44, 46, 53, 42, + 15, 0, 23, 5, 46, 1, 53, 5, 4, 13, 27, 9, 34, 13, 57, + 9, 8, 17, 16, 22, 38, 17, 50, 22, 3, 30, 19, 25, 37, 30, + 49, 25, 0, 33, 24, 38, 33, 34, 58, 38, 11, 46, 20, 42, 45, + 46, 54, 42, 15, 1, 22, 5, 45, 1, 52, 5, 3, 13, 26, 9, + 33, 13, 56, 9, 7, 17, 17, 22, 37, 17, 51, 22, 4, 30, 18, + 25, 38, 30, 48, 25, 0, 34, 25, 38, 34, 34, 59, 38, 12, 46, + 21, 42, 46, 46, 55, 42, 14, 1, 21, 5, 44, 1, 51, 5, 2, + 13, 25, 9, 32, 13, 55, 9, 6, 17, 18, 22, 36, 17, 52, 22, + 5, 30, 17, 25, 39, 30, 48, 26, 1, 34, 26, 38, 35, 34, 60, + 38, 13, 46, 22, 42, 47, 46, 56, 42, 13, 1, 20, 5, 43, 1, + 50, 5, 1, 13, 24, 9, 32, 14, 54, 9, 5, 17, 19, 22, 35, + 17, 53, 22, 6, 30, 16, 25, 40, 30, 49, 26, 2, 34, 27, 38, + 36, 34, 61, 38, 14, 46, 23, 42, 47, 47, 57, 42, 12, 1, 19, + 5, 42, 1, 49, 5, 0, 13, 23, 9, 33, 14, 53, 9, 4, 17, + 20, 22, 34, 17, 54, 22, 7, 30, 16, 26, 41, 30, 50, 26, 3, + 34, 28, 38, 37, 34, 62, 38, 15, 46, 24, 42, 46, 47, 58, 42, + 11, 1, 18, 5, 41, 1, 48, 5, 0, 14, 22, 9, 34, 14, 52, + 9, 3, 17, 21, 22, 33, 17, 55, 22, 8, 30, 17, 26, 42, 30, + 51, 26, 4, 34, 29, 38, 38, 34, 63, 38, 15, 47, 25, 42, 45, + 47, 59, 42, 10, 1, 17, 5, 40, 1, 48, 6, 1, 14, 21, 9, + 35, 14, 51, 9, 2, 17, 22, 22, 32, 17, 56, 22, 9, 30, 18, + 26, 43, 30, 52, 26, 5, 34, 30, 38, 39, 34, 63, 39, 14, 47, + 26, 42, 44, 47, 60, 42, 9, 1, 16, 5, 39, 1, 49, 6, 2, + 14, 20, 9, 36, 14, 50, 9, 1, 17, 23, 22, 32, 18, 57, 22, + 10, 30, 19, 26, 44, 30, 53, 26, 6, 34, 31, 38, 40, 34, 62, + 39, 13, 47, 27, 42, 43, 47, 61, 42, 8, 1, 16, 6, 38, 1, + 50, 6, 3, 14, 19, 9, 37, 14, 49, 9, 0, 17, 24, 22, 33, + 18, 58, 22, 11, 30, 20, 26, 45, 30, 54, 26, 7, 34, 31, 39, + 41, 34, 61, 39, 12, 47, 28, 42, 42, 47, 62, 42, 7, 1, 17, + 6, 37, 1, 51, 6, 4, 14, 18, 9, 38, 14, 48, 9, 0, 18, + 25, 22, 34, 18, 59, 22, 12, 30, 21, 26, 46, 30, 55, 26, 8, + 34, 30, 39, 42, 34, 60, 39, 11, 47, 29, 42, 41, 47, 63, 42, + 6, 1, 18, 6, 36, 1, 52, 6, 5, 14, 17, 9, 39, 14, 48, + 10, 1, 18, 26, 22, 35, 18, 60, 22, 13, 30, 22, 26, 47, 30, + 56, 26, 9, 34, 29, 39, 43, 34, 59, 39, 10, 47, 30, 42, 40, + 47, 63, 43, 5, 1, 19, 6, 35, 1, 53, 6, 6, 14, 16, 9, + 40, 14, 49, 10, 2, 18, 27, 22, 36, 18, 61, 22, 14, 30, 23, + 26, 47, 31, 57, 26, 10, 34, 28, 39, 44, 34, 58, 39, 9, 47, + 31, 42, 39, 47, 62, 43, 4, 1, 20, 6, 34, 1, 54, 6, 7, + 14, 16, 10, 41, 14, 50, 10, 3, 18, 28, 22, 37, 18, 62, 22, + 15, 30, 24, 26, 46, 31, 58, 26, 11, 34, 27, 39, 45, 34, 57, + 39, 8, 47, 31, 43, 38, 47, 61, 43, 3, 1, 21, 6, 33, 1, + 55, 6, 8, 14, 17, 10, 42, 14, 51, 10, 4, 18, 29, 22, 38, + 18, 63, 22, 15, 31, 25, 26, 45, 31, 59, 26, 12, 34, 26, 39, + 46, 34, 56, 39, 7, 47, 30, 43, 37, 47, 60, 43, 2, 1, 22, + 6, 32, 1, 56, 6, 9, 14, 18, 10, 43, 14, 52, 10, 5, 18, + 30, 22, 39, 18, 63, 23, 14, 31, 26, 26, 44, 31, 60, 26, 13, + 34, 25, 39, 47, 34, 55, 39, 6, 47, 29, 43, 36, 47, 59, 43, + 1, 1, 23, 6, 32, 2, 57, 6, 10, 14, 19, 10, 44, 14, 53, + 10, 6, 18, 31, 22, 40, 18, 62, 23, 13, 31, 27, 26, 43, 31, + 61, 26, 14, 34, 24, 39, 47, 35, 54, 39, 5, 47, 28, 43, 35, + 47, 58, 43, 0, 1, 24, 6, 33, 2, 58, 6, 11, 14, 20, 10, + 45, 14, 54, 10, 7, 18, 31, 23, 41, 18, 61, 23, 12, 31, 28, + 26, 42, 31, 62, 26, 15, 34, 23, 39, 46, 35, 53, 39, 4, 47, + 27, 43, 34, 47, 57, 43, 0, 2, 25, 6, 34, 2, 59, 6, 12, + 14, 21, 10, 46, 14, 55, 10, 8, 18, 30, 23, 42, 18, 60, 23, + 11, 31, 29, 26, 41, 31, 63, 26, 15, 35, 22, 39, 45, 35, 52, + 39, 3, 47, 26, 43, 33, 47, 56, 43, 1, 2, 26, 6, 35, 2, + 60, 6, 13, 14, 22, 10, 47, 14, 56, 10, 9, 18, 29, 23, 43, + 18, 59, 23, 10, 31, 30, 26, 40, 31, 63, 27, 14, 35, 21, 39, + 44, 35, 51, 39, 2, 47, 25, 43, 32, 47, 55, 43, 2, 2, 27, + 6, 36, 2, 61, 6, 14, 14, 23, 10, 47, 15, 57, 10, 10, 18, + 28, 23, 44, 18, 58, 23, 9, 31, 31, 26, 39, 31, 62, 27, 13, + 35, 20, 39, 43, 35, 50, 39, 1, 47, 24, 43, 32, 40, 54, 43, + 3, 2, 28, 6, 37, 2, 62, 6, 15, 14, 24, 10, 46, 15, 58, + 10, 11, 18, 27, 23, 45, 18, 57, 23, 8, 31, 31, 27, 38, 31, + 61, 27, 12, 35, 19, 39, 42, 35, 49, 39, 0, 47, 23, 43, 33, + 40, 53, 43, 4, 2, 29, 6, 38, 2, 63, 6, 15, 15, 25, 10, + 45, 15, 59, 10, 12, 18, 26, 23, 46, 18, 56, 23, 7, 31, 30, + 27, 37, 31, 60, 27, 11, 35, 18, 39, 41, 35, 48, 39, 0, 40, + 22, 43, 34, 40, 52, 43, 5, 2, 30, 6, 39, 2, 63, 7, 14, + 15, 26, 10, 44, 15, 60, 10, 13, 18, 25, 23, 47, 18, 55, 23, + 6, 31, 29, 27, 36, 31, 59, 27, 10, 35, 17, 39, 40, 35, 48, + 32, 1, 40, 21, 43, 35, 40, 51, 43, 6, 2, 31, 6, 40, 2, + 62, 7, 13, 15, 27, 10, 43, 15, 61, 10, 14, 18, 24, 23, 47, + 19, 54, 23, 5, 31, 28, 27, 35, 31, 58, 27, 9, 35, 16, 39, + 39, 35, 49, 32, 2, 40, 20, 43, 36, 40, 50, 43, 7, 2, 31, + 7, 41, 2, 61, 7, 12, 15, 28, 10, 42, 15, 62, 10, 15, 18, + 23, 23, 46, 19, 53, 23, 4, 31, 27, 27, 34, 31, 57, 27, 8, + 35, 16, 32, 38, 35, 50, 32, 3, 40, 19, 43, 37, 40, 49, 43, + 8, 2, 30, 7, 42, 2, 60, 7, 11, 15, 29, 10, 41, 15, 63, + 10, 15, 19, 22, 23, 45, 19, 52, 23, 3, 31, 26, 27, 33, 31, + 56, 27, 7, 35, 17, 32, 37, 35, 51, 32, 4, 40, 18, 43, 38, + 40, 48, 43, 9, 2, 29, 7, 43, 2, 59, 7, 10, 15, 30, 10, + 40, 15, 63, 11, 14, 19, 21, 23, 44, 19, 51, 23, 2, 31, 25, + 27, 32, 31, 55, 27, 6, 35, 18, 32, 36, 35, 52, 32, 5, 40, + 17, 43, 39, 40, 48, 44, 10, 2, 28, 7, 44, 2, 58, 7, 9, + 15, 31, 10, 39, 15, 62, 11, 13, 19, 20, 23, 43, 19, 50, 23, + 1, 31, 24, 27, 32, 24, 54, 27, 5, 35, 19, 32, 35, 35, 53, + 32, 6, 40, 16, 43, 40, 40, 49, 44, 11, 2, 27, 7, 45, 2, + 57, 7, 8, 15, 31, 11, 38, 15, 61, 11, 12, 19, 19, 23, 42, + 19, 49, 23, 0, 31, 23, 27, 33, 24, 53, 27, 4, 35, 20, 32, + 34, 35, 54, 32, 7, 40, 16, 44, 41, 40, 50, 44, 12, 2, 26, + 7, 46, 2, 56, 7, 7, 15, 30, 11, 37, 15, 60, 11, 11, 19, + 18, 23, 41, 19, 48, 23, 0, 24, 22, 27, 34, 24, 52, 27, 3, + 35, 21, 32, 33, 35, 55, 32, 8, 40, 17, 44, 42, 40, 51, 44, + 13, 2, 25, 7, 47, 2, 55, 7, 6, 15, 29, 11, 36, 15, 59, + 11, 10, 19, 17, 23, 40, 19, 48, 16, 1, 24, 21, 27, 35, 24, + 51, 27, 2, 35, 22, 32, 32, 35, 56, 32, 9, 40, 18, 44, 43, + 40, 52, 44, 14, 2, 24, 7, 47, 3, 54, 7, 5, 15, 28, 11, + 35, 15, 58, 11, 9, 19, 16, 23, 39, 19, 49, 16, 2, 24, 20, + 27, 36, 24, 50, 27, 1, 35, 23, 32, 32, 36, 57, 32, 10, 40, + 19, 44, 44, 40, 53, 44, 15, 2, 23, 7, 46, 3, 53, 7, 4, + 15, 27, 11, 34, 15, 57, 11, 8, 19, 16, 16, 38, 19, 50, 16, + 3, 24, 19, 27, 37, 24, 49, 27, 0, 35, 24, 32, 33, 36, 58, + 32, 11, 40, 20, 44, 45, 40, 54, 44, 15, 3, 22, 7, 45, 3, + 52, 7, 3, 15, 26, 11, 33, 15, 56, 11, 7, 19, 17, 16, 37, + 19, 51, 16, 4, 24, 18, 27, 38, 24, 48, 27, 0, 36, 25, 32, + 34, 36, 59, 32, 12, 40, 21, 44, 46, 40, 55, 44, 14, 3, 21, + 7, 44, 3, 51, 7, 2, 15, 25, 11, 32, 15, 55, 11, 6, 19, + 18, 16, 36, 19, 52, 16, 5, 24, 17, 27, 39, 24, 48, 28, 1, + 36, 26, 32, 35, 36, 60, 32, 13, 40, 22, 44, 47, 40, 56, 44, + 13, 3, 20, 7, 43, 3, 50, 7, 1, 15, 24, 11, 32, 8, 54, + 11, 5, 19, 19, 16, 35, 19, 53, 16, 6, 24, 16, 27, 40, 24, + 49, 28, 2, 36, 27, 32, 36, 36, 61, 32, 14, 40, 23, 44, 47, + 41, 57, 44, 12, 3, 19, 7, 42, 3, 49, 7, 0, 15, 23, 11, + 33, 8, 53, 11, 4, 19, 20, 16, 34, 19, 54, 16, 7, 24, 16, + 28, 41, 24, 50, 28, 3, 36, 28, 32, 37, 36, 62, 32, 15, 40, + 24, 44, 46, 41, 58, 44, 11, 3, 18, 7, 41, 3, 48, 7, 0, + 8, 22, 11, 34, 8, 52, 11, 3, 19, 21, 16, 33, 19, 55, 16, + 8, 24, 17, 28, 42, 24, 51, 28, 4, 36, 29, 32, 38, 36, 63, + 32, 15, 41, 25, 44, 45, 41, 59, 44, 10, 3, 17, 7, 40, 3, + 48, 0, 1, 8, 21, 11, 35, 8, 51, 11, 2, 19, 22, 16, 32, + 19, 56, 16, 9, 24, 18, 28, 43, 24, 52, 28, 5, 36, 30, 32, + 39, 36, 63, 33, 14, 41, 26, 44, 44, 41, 60, 44, 9, 3, 16, + 7, 39, 3, 49, 0, 2, 8, 20, 11, 36, 8, 50, 11, 1, 19, + 23, 16, 32, 20, 57, 16, 10, 24, 19, 28, 44, 24, 53, 28, 6, + 36, 31, 32, 40, 36, 62, 33, 13, 41, 27, 44, 43, 41, 61, 44, + 8, 3, 16, 0, 38, 3, 50, 0, 3, 8, 19, 11, 37, 8, 49, + 11, 0, 19, 24, 16, 33, 20, 58, 16, 11, 24, 20, 28, 45, 24, + 54, 28, 7, 36, 31, 33, 41, 36, 61, 33, 12, 41, 28, 44, 42, + 41, 62, 44, 7, 3, 17, 0, 37, 3, 51, 0, 4, 8, 18, 11, + 38, 8, 48, 11, 0, 20, 25, 16, 34, 20, 59, 16, 12, 24, 21, + 28, 46, 24, 55, 28, 8, 36, 30, 33, 42, 36, 60, 33, 11, 41, + 29, 44, 41, 41, 63, 44, 6, 3, 18, 0, 36, 3, 52, 0, 5, + 8, 17, 11, 39, 8, 48, 12, 1, 20, 26, 16, 35, 20, 60, 16, + 13, 24, 22, 28, 47, 24, 56, 28, 9, 36, 29, 33, 43, 36, 59, + 33, 10, 41, 30, 44, 40, 41, 63, 45, 5, 3, 19, 0, 35, 3, + 53, 0, 6, 8, 16, 11, 40, 8, 49, 12, 2, 20, 27, 16, 36, + 20, 61, 16, 14, 24, 23, 28, 47, 25, 57, 28, 10, 36, 28, 33, + 44, 36, 58, 33, 9, 41, 31, 44, 39, 41, 62, 45, 4, 3, 20, + 0, 34, 3, 54, 0, 7, 8, 16, 12, 41, 8, 50, 12, 3, 20, + 28, 16, 37, 20, 62, 16, 15, 24, 24, 28, 46, 25, 58, 28, 11, + 36, 27, 33, 45, 36, 57, 33, 8, 41, 31, 45, 38, 41, 61, 45, + 3, 3, 21, 0, 33, 3, 55, 0, 8, 8, 17, 12, 42, 8, 51, + 12, 4, 20, 29, 16, 38, 20, 63, 16, 15, 25, 25, 28, 45, 25, + 59, 28, 12, 36, 26, 33, 46, 36, 56, 33, 7, 41, 30, 45, 37, + 41, 60, 45, 2, 3, 22, 0, 32, 3, 56, 0, 9, 8, 18, 12, + 43, 8, 52, 12, 5, 20, 30, 16, 39, 20, 63, 17, 14, 25, 26, + 28, 44, 25, 60, 28, 13, 36, 25, 33, 47, 36, 55, 33, 6, 41, + 29, 45, 36, 41, 59, 45, 1, 3, 23, 0, 32, 4, 57, 0, 10, + 8, 19, 12, 44, 8, 53, 12, 6, 20, 31, 16, 40, 20, 62, 17, + 13, 25, 27, 28, 43, 25, 61, 28, 14, 36, 24, 33, 47, 37, 54, + 33, 5, 41, 28, 45, 35, 41, 58, 45, 0, 3, 24, 0, 33, 4, + 58, 0, 11, 8, 20, 12, 45, 8, 54, 12, 7, 20, 31, 17, 41, + 20, 61, 17, 12, 25, 28, 28, 42, 25, 62, 28, 15, 36, 23, 33, + 46, 37, 53, 33, 4, 41, 27, 45, 34, 41, 57, 45, 0, 4, 25, + 0, 34, 4, 59, 0, 12, 8, 21, 12, 46, 8, 55, 12, 8, 20, + 30, 17, 42, 20, 60, 17, 11, 25, 29, 28, 41, 25, 63, 28, 15, + 37, 22, 33, 45, 37, 52, 33, 3, 41, 26, 45, 33, 41, 56, 45, + 1, 4, 26, 0, 35, 4, 60, 0, 13, 8, 22, 12, 47, 8, 56, + 12, 9, 20, 29, 17, 43, 20, 59, 17, 10, 25, 30, 28, 40, 25, + 63, 29, 14, 37, 21, 33, 44, 37, 51, 33, 2, 41, 25, 45, 32, + 41, 55, 45, 2, 4, 27, 0, 36, 4, 61, 0, 14, 8, 23, 12, + 47, 9, 57, 12, 10, 20, 28, 17, 44, 20, 58, 17, 9, 25, 31, + 28, 39, 25, 62, 29, 13, 37, 20, 33, 43, 37, 50, 33, 1, 41, + 24, 45, 32, 42, 54, 45, 3, 4, 28, 0, 37, 4, 62, 0, 15, + 8, 24, 12, 46, 9, 58, 12, 11, 20, 27, 17, 45, 20, 57, 17, + 8, 25, 31, 29, 38, 25, 61, 29, 12, 37, 19, 33, 42, 37, 49, + 33, 0, 41, 23, 45, 33, 42, 53, 45, 4, 4, 29, 0, 38, 4, + 63, 0, 15, 9, 25, 12, 45, 9, 59, 12, 12, 20, 26, 17, 46, + 20, 56, 17, 7, 25, 30, 29, 37, 25, 60, 29, 11, 37, 18, 33, + 41, 37, 48, 33, 0, 42, 22, 45, 34, 42, 52, 45, 5, 4, 30, + 0, 39, 4, 63, 1, 14, 9, 26, 12, 44, 9, 60, 12, 13, 20, + 25, 17, 47, 20, 55, 17, 6, 25, 29, 29, 36, 25, 59, 29, 10, + 37, 17, 33, 40, 37, 48, 34, 1, 42, 21, 45, 35, 42, 51, 45, + 6, 4, 31, 0, 40, 4, 62, 1, 13, 9, 27, 12, 43, 9, 61, + 12, 14, 20, 24, 17, 47, 21, 54, 17, 5, 25, 28, 29, 35, 25, + 58, 29, 9, 37, 16, 33, 39, 37, 49, 34, 2, 42, 20, 45, 36, + 42, 50, 45, 7, 4, 31, 1, 41, 4, 61, 1, 12, 9, 28, 12, + 42, 9, 62, 12, 15, 20, 23, 17, 46, 21, 53, 17, 4, 25, 27, + 29, 34, 25, 57, 29, 8, 37, 16, 34, 38, 37, 50, 34, 3, 42, + 19, 45, 37, 42, 49, 45, 8, 4, 30, 1, 42, 4, 60, 1, 11, + 9, 29, 12, 41, 9, 63, 12, 15, 21, 22, 17, 45, 21, 52, 17, + 3, 25, 26, 29, 33, 25, 56, 29, 7, 37, 17, 34, 37, 37, 51, + 34, 4, 42, 18, 45, 38, 42, 48, 45, 9, 4, 29, 1, 43, 4, + 59, 1, 10, 9, 30, 12, 40, 9, 63, 13, 14, 21, 21, 17, 44, + 21, 51, 17, 2, 25, 25, 29, 32, 25, 55, 29, 6, 37, 18, 34, + 36, 37, 52, 34, 5, 42, 17, 45, 39, 42, 48, 46, 10, 4, 28, + 1, 44, 4, 58, 1, 9, 9, 31, 12, 39, 9, 62, 13, 13, 21, + 20, 17, 43, 21, 50, 17, 1, 25, 24, 29, 32, 26, 54, 29, 5, + 37, 19, 34, 35, 37, 53, 34, 6, 42, 16, 45, 40, 42, 49, 46, + 11, 4, 27, 1, 45, 4, 57, 1, 8, 9, 31, 13, 38, 9, 61, + 13, 12, 21, 19, 17, 42, 21, 49, 17, 0, 25, 23, 29, 33, 26, + 53, 29, 4, 37, 20, 34, 34, 37, 54, 34, 7, 42, 16, 46, 41, + 42, 50, 46, 12, 4, 26, 1, 46, 4, 56, 1, 7, 9, 30, 13, + 37, 9, 60, 13, 11, 21, 18, 17, 41, 21, 48, 17, 0, 26, 22, + 29, 34, 26, 52, 29, 3, 37, 21, 34, 33, 37, 55, 34, 8, 42, + 17, 46, 42, 42, 51, 46, 13, 4, 25, 1, 47, 4, 55, 1, 6, + 9, 29, 13, 36, 9, 59, 13, 10, 21, 17, 17, 40, 21, 48, 18, + 1, 26, 21, 29, 35, 26, 51, 29, 2, 37, 22, 34, 32, 37, 56, + 34, 9, 42, 18, 46, 43, 42, 52, 46, 14, 4, 24, 1, 47, 5, + 54, 1, 5, 9, 28, 13, 35, 9, 58, 13, 9, 21, 16, 17, 39, + 21, 49, 18, 2, 26, 20, 29, 36, 26, 50, 29, 1, 37, 23, 34, + 32, 38, 57, 34, 10, 42, 19, 46, 44, 42, 53, 46, 15, 4, 23, + 1, 46, 5, 53, 1, 4, 9, 27, 13, 34, 9, 57, 13, 8, 21, + 16, 18, 38, 21, 50, 18, 3, 26, 19, 29, 37, 26, 49, 29, 0, + 37, 24, 34, 33, 38, 58, 34, 11, 42, 20, 46, 45, 42, 54, 46, + 15, 5, 22, 1, 45, 5, 52, 1, 3, 9, 26, 13, 33, 9, 56, + 13, 7, 21, 17, 18, 37, 21, 51, 18, 4, 26, 18, 29, 38, 26, + 48, 29, 0, 38, 25, 34, 34, 38, 59, 34, 12, 42, 21, 46, 46, + 42, 55, 46, 14, 5, 21, 1, 44, 5, 51, 1, 2, 9, 25, 13, + 32, 9, 55, 13, 6, 21, 18, 18, 36, 21, 52, 18, 5, 26, 17, + 29, 39, 26, 48, 30, 1, 38, 26, 34, 35, 38, 60, 34, 13, 42, + 22, 46, 47, 42, 56, 46, 13, 5, 20, 1, 43, 5, 50, 1, 1, + 9, 24, 13, 32, 10, 54, 13, 5, 21, 19, 18, 35, 21, 53, 18, + 6, 26, 16, 29, 40, 26, 49, 30, 2, 38, 27, 34, 36, 38, 61, + 34, 14, 42, 23, 46, 47, 43, 57, 46, 12, 5, 19, 1, 42, 5, + 49, 1, 0, 9, 23, 13, 33, 10, 53, 13, 4, 21, 20, 18, 34, + 21, 54, 18, 7, 26, 16, 30, 41, 26, 50, 30, 3, 38, 28, 34, + 37, 38, 62, 34, 15, 42, 24, 46, 46, 43, 58, 46, 11, 5, 18, + 1, 41, 5, 48, 1, 0, 10, 22, 13, 34, 10, 52, 13, 3, 21, + 21, 18, 33, 21, 55, 18, 8, 26, 17, 30, 42, 26, 51, 30, 4, + 38, 29, 34, 38, 38, 63, 34, 15, 43, 25, 46, 45, 43, 59, 46, + 10, 5, 17, 1, 40, 5, 48, 2, 1, 10, 21, 13, 35, 10, 51, + 13, 2, 21, 22, 18, 32, 21, 56, 18, 9, 26, 18, 30, 43, 26, + 52, 30, 5, 38, 30, 34, 39, 38, 63, 35, 14, 43, 26, 46, 44, + 43, 60, 46, 9, 5, 16, 1, 39, 5, 49, 2, 2, 10, 20, 13, + 36, 10, 50, 13, 1, 21, 23, 18, 32, 22, 57, 18, 10, 26, 19, + 30, 44, 26, 53, 30, 6, 38, 31, 34, 40, 38, 62, 35, 13, 43, + 27, 46, 43, 43, 61, 46, 8, 5, 16, 2, 38, 5, 50, 2, 3, + 10, 19, 13, 37, 10, 49, 13, 0, 21, 24, 18, 33, 22, 58, 18, + 11, 26, 20, 30, 45, 26, 54, 30, 7, 38, 31, 35, 41, 38, 61, + 35, 12, 43, 28, 46, 42, 43, 62, 46, 7, 5, 17, 2, 37, 5, + 51, 2, 4, 10, 18, 13, 38, 10, 48, 13, 0, 22, 25, 18, 34, + 22, 59, 18, 12, 26, 21, 30, 46, 26, 55, 30, 8, 38, 30, 35, + 42, 38, 60, 35, 11, 43, 29, 46, 41, 43, 63, 46, 6, 5, 18, + 2, 36, 5, 52, 2, 5, 10, 17, 13, 39, 10, 48, 14, 1, 22, + 26, 18, 35, 22, 60, 18, 13, 26, 22, 30, 47, 26, 56, 30, 9, + 38, 29, 35, 43, 38, 59, 35, 10, 43, 30, 46, 40, 43, 63, 47, + 5, 5, 19, 2, 35, 5, 53, 2, 6, 10, 16, 13, 40, 10, 49, + 14, 2, 22, 27, 18, 36, 22, 61, 18, 14, 26, 23, 30, 47, 27, + 57, 30, 10, 38, 28, 35, 44, 38, 58, 35, 9, 43, 31, 46, 39, + 43, 62, 47, 4, 5, 20, 2, 34, 5, 54, 2, 7, 10, 16, 14, + 41, 10, 50, 14, 3, 22, 28, 18, 37, 22, 62, 18, 15, 26, 24, + 30, 46, 27, 58, 30, 11, 38, 27, 35, 45, 38, 57, 35, 8, 43, + 31, 47, 38, 43, 61, 47, 3, 5, 21, 2, 33, 5, 55, 2, 8, + 10, 17, 14, 42, 10, 51, 14, 4, 22, 29, 18, 38, 22, 63, 18, + 15, 27, 25, 30, 45, 27, 59, 30, 12, 38, 26, 35, 46, 38, 56, + 35, 7, 43, 30, 47, 37, 43, 60, 47, 2, 5, 22, 2, 32, 5, + 56, 2, 9, 10, 18, 14, 43, 10, 52, 14, 5, 22, 30, 18, 39, + 22, 63, 19, 14, 27, 26, 30, 44, 27, 60, 30, 13, 38, 25, 35, + 47, 38, 55, 35, 6, 43, 29, 47, 36, 43, 59, 47, 1, 5, 23, + 2, 32, 6, 57, 2, 10, 10, 19, 14, 44, 10, 53, 14, 6, 22, + 31, 18, 40, 22, 62, 19, 13, 27, 27, 30, 43, 27, 61, 30, 14, + 38, 24, 35, 47, 39, 54, 35, 5, 43, 28, 47, 35, 43, 58, 47, + 0, 5, 24, 2, 33, 6, 58, 2, 11, 10, 20, 14, 45, 10, 54, + 14, 7, 22, 31, 19, 41, 22, 61, 19, 12, 27, 28, 30, 42, 27, + 62, 30, 15, 38, 23, 35, 46, 39, 53, 35, 4, 43, 27, 47, 34, + 43, 57, 47, 0, 6, 25, 2, 34, 6, 59, 2, 12, 10, 21, 14, + 46, 10, 55, 14, 8, 22, 30, 19, 42, 22, 60, 19, 11, 27, 29, + 30, 41, 27, 63, 30, 15, 39, 22, 35, 45, 39, 52, 35, 3, 43, + 26, 47, 33, 43, 56, 47, 1, 6, 26, 2, 35, 6, 60, 2, 13, + 10, 22, 14, 47, 10, 56, 14, 9, 22, 29, 19, 43, 22, 59, 19, + 10, 27, 30, 30, 40, 27, 63, 31, 14, 39, 21, 35, 44, 39, 51, + 35, 2, 43, 25, 47, 32, 43, 55, 47, 2, 6, 27, 2, 36, 6, + 61, 2, 14, 10, 23, 14, 47, 11, 57, 14, 10, 22, 28, 19, 44, + 22, 58, 19, 9, 27, 31, 30, 39, 27, 62, 31, 13, 39, 20, 35, + 43, 39, 50, 35, 1, 43, 24, 47, 32, 44, 54, 47, 3, 6, 28, + 2, 37, 6, 62, 2, 15, 10, 24, 14, 46, 11, 58, 14, 11, 22, + 27, 19, 45, 22, 57, 19, 8, 27, 31, 31, 38, 27, 61, 31, 12, + 39, 19, 35, 42, 39, 49, 35, 0, 43, 23, 47, 33, 44, 53, 47, + 4, 6, 29, 2, 38, 6, 63, 2, 15, 11, 25, 14, 45, 11, 59, + 14, 12, 22, 26, 19, 46, 22, 56, 19, 7, 27, 30, 31, 37, 27, + 60, 31, 11, 39, 18, 35, 41, 39, 48, 35, 0, 44, 22, 47, 34, + 44, 52, 47, 5, 6, 30, 2, 39, 6, 63, 3, 14, 11, 26, 14, + 44, 11, 60, 14, 13, 22, 25, 19, 47, 22, 55, 19, 6, 27, 29, + 31, 36, 27, 59, 31, 10, 39, 17, 35, 40, 39, 48, 36, 1, 44, + 21, 47, 35, 44, 51, 47, 6, 6, 31, 2, 40, 6, 62, 3, 13, + 11, 27, 14, 43, 11, 61, 14, 14, 22, 24, 19, 47, 23, 54, 19, + 5, 27, 28, 31, 35, 27, 58, 31, 9, 39, 16, 35, 39, 39, 49, + 36, 2, 44, 20, 47, 36, 44, 50, 47, 7, 6, 31, 3, 41, 6, + 61, 3, 12, 11, 28, 14, 42, 11, 62, 14, 15, 22, 23, 19, 46, + 23, 53, 19, 4, 27, 27, 31, 34, 27, 57, 31, 8, 39, 16, 36, + 38, 39, 50, 36, 3, 44, 19, 47, 37, 44, 49, 47, 8, 6, 30, + 3, 42, 6, 60, 3, 11, 11, 29, 14, 41, 11, 63, 14, 15, 23, + 22, 19, 45, 23, 52, 19, 3, 27, 26, 31, 33, 27, 56, 31, 7, + 39, 17, 36, 37, 39, 51, 36, 4, 44, 18, 47, 38, 44, 48, 47, + 9, 6, 29, 3, 43, 6, 59, 3, 10, 11, 30, 14, 40, 11, 63, + 15, 14, 23, 21, 19, 44, 23, 51, 19, 2, 27, 25, 31, 32, 27, + 55, 31, 6, 39, 18, 36, 36, 39, 52, 36, 5, 44, 17, 47, 39, + 44, 48, 40, 10, 6, 28, 3, 44, 6, 58, 3, 9, 11, 31, 14, + 39, 11, 62, 15, 13, 23, 20, 19, 43, 23, 50, 19, 1, 27, 24, + 31, 32, 28, 54, 31, 5, 39, 19, 36, 35, 39, 53, 36, 6, 44, + 16, 47, 40, 44, 49, 40, 11, 6, 27, 3, 45, 6, 57, 3, 8, + 11, 31, 15, 38, 11, 61, 15, 12, 23, 19, 19, 42, 23, 49, 19, + 0, 27, 23, 31, 33, 28, 53, 31, 4, 39, 20, 36, 34, 39, 54, + 36, 7, 44, 16, 40, 41, 44, 50, 40, 12, 6, 26, 3, 46, 6, + 56, 3, 7, 11, 30, 15, 37, 11, 60, 15, 11, 23, 18, 19, 41, + 23, 48, 19, 0, 28, 22, 31, 34, 28, 52, 31, 3, 39, 21, 36, + 33, 39, 55, 36, 8, 44, 17, 40, 42, 44, 51, 40, 13, 6, 25, + 3, 47, 6, 55, 3, 6, 11, 29, 15, 36, 11, 59, 15, 10, 23, + 17, 19, 40, 23, 48, 20, 1, 28, 21, 31, 35, 28, 51, 31, 2, + 39, 22, 36, 32, 39, 56, 36, 9, 44, 18, 40, 43, 44, 52, 40, + 14, 6, 24, 3, 47, 7, 54, 3, 5, 11, 28, 15, 35, 11, 58, + 15, 9, 23, 16, 19, 39, 23, 49, 20, 2, 28, 20, 31, 36, 28, + 50, 31, 1, 39, 23, 36, 32, 32, 57, 36, 10, 44, 19, 40, 44, + 44, 53, 40, 15, 6, 23, 3, 46, 7, 53, 3, 4, 11, 27, 15, + 34, 11, 57, 15, 8, 23, 16, 20, 38, 23, 50, 20, 3, 28, 19, + 31, 37, 28, 49, 31, 0, 39, 24, 36, 33, 32, 58, 36, 11, 44, + 20, 40, 45, 44, 54, 40, 15, 7, 22, 3, 45, 7, 52, 3, 3, + 11, 26, 15, 33, 11, 56, 15, 7, 23, 17, 20, 37, 23, 51, 20, + 4, 28, 18, 31, 38, 28, 48, 31, 0, 32, 25, 36, 34, 32, 59, + 36, 12, 44, 21, 40, 46, 44, 55, 40, 14, 7, 21, 3, 44, 7, + 51, 3, 2, 11, 25, 15, 32, 11, 55, 15, 6, 23, 18, 20, 36, + 23, 52, 20, 5, 28, 17, 31, 39, 28, 48, 24, 1, 32, 26, 36, + 35, 32, 60, 36, 13, 44, 22, 40, 47, 44, 56, 40, 13, 7, 20, + 3, 43, 7, 50, 3, 1, 11, 24, 15, 32, 12, 54, 15, 5, 23, + 19, 20, 35, 23, 53, 20, 6, 28, 16, 31, 40, 28, 49, 24, 2, + 32, 27, 36, 36, 32, 61, 36, 14, 44, 23, 40, 47, 45, 57, 40, + 12, 7, 19, 3, 42, 7, 49, 3, 0, 11, 23, 15, 33, 12, 53, + 15, 4, 23, 20, 20, 34, 23, 54, 20, 7, 28, 16, 24, 41, 28, + 50, 24, 3, 32, 28, 36, 37, 32, 62, 36, 15, 44, 24, 40, 46, + 45, 58, 40, 11, 7, 18, 3, 41, 7, 48, 3, 0, 12, 22, 15, + 34, 12, 52, 15, 3, 23, 21, 20, 33, 23, 55, 20, 8, 28, 17, + 24, 42, 28, 51, 24, 4, 32, 29, 36, 38, 32, 63, 36, 15, 45, + 25, 40, 45, 45, 59, 40, 10, 7, 17, 3, 40, 7, 48, 4, 1, + 12, 21, 15, 35, 12, 51, 15, 2, 23, 22, 20, 32, 23, 56, 20, + 9, 28, 18, 24, 43, 28, 52, 24, 5, 32, 30, 36, 39, 32, 63, + 37, 14, 45, 26, 40, 44, 45, 60, 40, 9, 7, 16, 3, 39, 7, + 49, 4, 2, 12, 20, 15, 36, 12, 50, 15, 1, 23, 23, 20, 32, + 16, 57, 20, 10, 28, 19, 24, 44, 28, 53, 24, 6, 32, 31, 36, + 40, 32, 62, 37, 13, 45, 27, 40, 43, 45, 61, 40, 8, 7, 16, + 4, 38, 7, 50, 4, 3, 12, 19, 15, 37, 12, 49, 15, 0, 23, + 24, 20, 33, 16, 58, 20, 11, 28, 20, 24, 45, 28, 54, 24, 7, + 32, 31, 37, 41, 32, 61, 37, 12, 45, 28, 40, 42, 45, 62, 40, + 7, 7, 17, 4, 37, 7, 51, 4, 4, 12, 18, 15, 38, 12, 48, + 15, 0, 16, 25, 20, 34, 16, 59, 20, 12, 28, 21, 24, 46, 28, + 55, 24, 8, 32, 30, 37, 42, 32, 60, 37, 11, 45, 29, 40, 41, + 45, 63, 40, 6, 7, 18, 4, 36, 7, 52, 4, 5, 12, 17, 15, + 39, 12, 48, 8, 1, 16, 26, 20, 35, 16, 60, 20, 13, 28, 22, + 24, 47, 28, 56, 24, 9, 32, 29, 37, 43, 32, 59, 37, 10, 45, + 30, 40, 40, 45, 63, 41, 5, 7, 19, 4, 35, 7, 53, 4, 6, + 12, 16, 15, 40, 12, 49, 8, 2, 16, 27, 20, 36, 16, 61, 20, + 14, 28, 23, 24, 47, 29, 57, 24, 10, 32, 28, 37, 44, 32, 58, + 37, 9, 45, 31, 40, 39, 45, 62, 41, 4, 7, 20, 4, 34, 7, + 54, 4, 7, 12, 16, 8, 41, 12, 50, 8, 3, 16, 28, 20, 37, + 16, 62, 20, 15, 28, 24, 24, 46, 29, 58, 24, 11, 32, 27, 37, + 45, 32, 57, 37, 8, 45, 31, 41, 38, 45, 61, 41, 3, 7, 21, + 4, 33, 7, 55, 4, 8, 12, 17, 8, 42, 12, 51, 8, 4, 16, + 29, 20, 38, 16, 63, 20, 15, 29, 25, 24, 45, 29, 59, 24, 12, + 32, 26, 37, 46, 32, 56, 37, 7, 45, 30, 41, 37, 45, 60, 41, + 2, 7, 22, 4, 32, 7, 56, 4, 9, 12, 18, 8, 43, 12, 52, + 8, 5, 16, 30, 20, 39, 16, 63, 21, 14, 29, 26, 24, 44, 29, + 60, 24, 13, 32, 25, 37, 47, 32, 55, 37, 6, 45, 29, 41, 36, + 45, 59, 41, 1, 7, 23, 4, 32, 0, 57, 4, 10, 12, 19, 8, + 44, 12, 53, 8, 6, 16, 31, 20, 40, 16, 62, 21, 13, 29, 27, + 24, 43, 29, 61, 24, 14, 32, 24, 37, 47, 33, 54, 37, 5, 45, + 28, 41, 35, 45, 58, 41, 0, 7, 24, 4, 33, 0, 58, 4, 11, + 12, 20, 8, 45, 12, 54, 8, 7, 16, 31, 21, 41, 16, 61, 21, + 12, 29, 28, 24, 42, 29, 62, 24, 15, 32, 23, 37, 46, 33, 53, + 37, 4, 45, 27, 41, 34, 45, 57, 41, +}; + +static const uint8_t hq_tab_20[] = { + 0, 0, 15, 3, 24, 0, 35, 3, 1, 9, 16, 6, 22, 10, 40, + 6, 8, 12, 14, 16, 32, 12, 38, 16, 6, 22, 19, 19, 30, 22, + 39, 19, 5, 25, 21, 29, 25, 25, 41, 29, 1, 0, 14, 3, 25, + 0, 34, 3, 0, 9, 17, 6, 23, 10, 41, 6, 9, 12, 15, 16, + 32, 13, 39, 16, 7, 22, 18, 19, 31, 22, 38, 19, 4, 25, 20, + 29, 24, 25, 40, 29, 2, 0, 13, 3, 26, 0, 33, 3, 0, 10, + 18, 6, 24, 10, 42, 6, 10, 12, 16, 16, 31, 13, 40, 16, 8, + 22, 17, 19, 32, 22, 37, 19, 3, 25, 19, 29, 23, 25, 39, 29, + 3, 0, 12, 3, 27, 0, 33, 4, 1, 10, 19, 6, 25, 10, 43, + 6, 10, 13, 17, 16, 30, 13, 41, 16, 9, 22, 16, 19, 32, 23, + 36, 19, 2, 25, 18, 29, 22, 25, 38, 29, 4, 0, 11, 3, 28, + 0, 34, 4, 2, 10, 20, 6, 26, 10, 43, 7, 9, 13, 18, 16, + 29, 13, 42, 16, 10, 22, 15, 19, 31, 23, 35, 19, 1, 25, 17, + 29, 22, 26, 37, 29, 5, 0, 11, 4, 29, 0, 35, 4, 3, 10, + 21, 6, 27, 10, 42, 7, 8, 13, 19, 16, 28, 13, 43, 16, 10, + 23, 14, 19, 30, 23, 34, 19, 0, 25, 16, 29, 23, 26, 36, 29, + 6, 0, 12, 4, 30, 0, 36, 4, 4, 10, 21, 7, 28, 10, 41, + 7, 7, 13, 20, 16, 27, 13, 43, 17, 9, 23, 13, 19, 29, 23, + 33, 19, 0, 26, 15, 29, 24, 26, 35, 29, 7, 0, 13, 4, 31, + 0, 37, 4, 5, 10, 20, 7, 29, 10, 40, 7, 6, 13, 21, 16, + 26, 13, 42, 17, 8, 23, 12, 19, 28, 23, 33, 20, 1, 26, 14, + 29, 25, 26, 34, 29, 8, 0, 14, 4, 32, 0, 38, 4, 6, 10, + 19, 7, 30, 10, 39, 7, 5, 13, 21, 17, 25, 13, 41, 17, 7, + 23, 11, 19, 27, 23, 34, 20, 2, 26, 13, 29, 26, 26, 33, 29, + 9, 0, 15, 4, 32, 1, 39, 4, 7, 10, 18, 7, 31, 10, 38, + 7, 4, 13, 20, 17, 24, 13, 40, 17, 6, 23, 11, 20, 26, 23, + 35, 20, 3, 26, 12, 29, 27, 26, 33, 24, 10, 0, 16, 4, 31, + 1, 40, 4, 8, 10, 17, 7, 32, 10, 37, 7, 3, 13, 19, 17, + 23, 13, 39, 17, 5, 23, 12, 20, 25, 23, 36, 20, 4, 26, 11, + 29, 28, 26, 34, 24, 10, 1, 17, 4, 30, 1, 41, 4, 9, 10, + 16, 7, 32, 11, 36, 7, 2, 13, 18, 17, 22, 13, 38, 17, 4, + 23, 13, 20, 24, 23, 37, 20, 5, 26, 11, 24, 29, 26, 35, 24, + 9, 1, 18, 4, 29, 1, 42, 4, 10, 10, 15, 7, 31, 11, 35, + 7, 1, 13, 17, 17, 22, 14, 37, 17, 3, 23, 14, 20, 23, 23, + 38, 20, 6, 26, 12, 24, 30, 26, 36, 24, 8, 1, 19, 4, 28, + 1, 43, 4, 10, 11, 14, 7, 30, 11, 34, 7, 0, 13, 16, 17, + 23, 14, 36, 17, 2, 23, 15, 20, 22, 23, 39, 20, 7, 26, 13, + 24, 31, 26, 37, 24, 7, 1, 20, 4, 27, 1, 43, 5, 9, 11, + 13, 7, 29, 11, 33, 7, 0, 14, 15, 17, 24, 14, 35, 17, 1, + 23, 16, 20, 22, 18, 40, 20, 8, 26, 14, 24, 32, 26, 38, 24, + 6, 1, 21, 4, 26, 1, 42, 5, 8, 11, 12, 7, 28, 11, 33, + 8, 1, 14, 14, 17, 25, 14, 34, 17, 0, 23, 17, 20, 23, 18, + 41, 20, 9, 26, 15, 24, 32, 27, 39, 24, 5, 1, 21, 5, 25, + 1, 41, 5, 7, 11, 11, 7, 27, 11, 34, 8, 2, 14, 13, 17, + 26, 14, 33, 17, 0, 18, 18, 20, 24, 18, 42, 20, 10, 26, 16, + 24, 31, 27, 40, 24, 4, 1, 20, 5, 24, 1, 40, 5, 6, 11, + 11, 8, 26, 11, 35, 8, 3, 14, 12, 17, 27, 14, 33, 12, 1, + 18, 19, 20, 25, 18, 43, 20, 10, 27, 17, 24, 30, 27, 41, 24, + 3, 1, 19, 5, 23, 1, 39, 5, 5, 11, 12, 8, 25, 11, 36, + 8, 4, 14, 11, 17, 28, 14, 34, 12, 2, 18, 20, 20, 26, 18, + 43, 21, 9, 27, 18, 24, 29, 27, 42, 24, 2, 1, 18, 5, 22, + 1, 38, 5, 4, 11, 13, 8, 24, 11, 37, 8, 5, 14, 11, 12, + 29, 14, 35, 12, 3, 18, 21, 20, 27, 18, 42, 21, 8, 27, 19, + 24, 28, 27, 43, 24, 1, 1, 17, 5, 22, 2, 37, 5, 3, 11, + 14, 8, 23, 11, 38, 8, 6, 14, 12, 12, 30, 14, 36, 12, 4, + 18, 21, 21, 28, 18, 41, 21, 7, 27, 20, 24, 27, 27, 43, 25, + 0, 1, 16, 5, 23, 2, 36, 5, 2, 11, 15, 8, 22, 11, 39, + 8, 7, 14, 13, 12, 31, 14, 37, 12, 5, 18, 20, 21, 29, 18, + 40, 21, 6, 27, 21, 24, 26, 27, 42, 25, 0, 2, 15, 5, 24, + 2, 35, 5, 1, 11, 16, 8, 22, 6, 40, 8, 8, 14, 14, 12, + 32, 14, 38, 12, 6, 18, 19, 21, 30, 18, 39, 21, 5, 27, 21, + 25, 25, 27, 41, 25, 1, 2, 14, 5, 25, 2, 34, 5, 0, 11, + 17, 8, 23, 6, 41, 8, 9, 14, 15, 12, 32, 15, 39, 12, 7, + 18, 18, 21, 31, 18, 38, 21, 4, 27, 20, 25, 24, 27, 40, 25, + 2, 2, 13, 5, 26, 2, 33, 5, 0, 6, 18, 8, 24, 6, 42, + 8, 10, 14, 16, 12, 31, 15, 40, 12, 8, 18, 17, 21, 32, 18, + 37, 21, 3, 27, 19, 25, 23, 27, 39, 25, 3, 2, 12, 5, 27, + 2, 33, 0, 1, 6, 19, 8, 25, 6, 43, 8, 10, 15, 17, 12, + 30, 15, 41, 12, 9, 18, 16, 21, 32, 19, 36, 21, 2, 27, 18, + 25, 22, 27, 38, 25, 4, 2, 11, 5, 28, 2, 34, 0, 2, 6, + 20, 8, 26, 6, 43, 9, 9, 15, 18, 12, 29, 15, 42, 12, 10, + 18, 15, 21, 31, 19, 35, 21, 1, 27, 17, 25, 22, 28, 37, 25, + 5, 2, 11, 0, 29, 2, 35, 0, 3, 6, 21, 8, 27, 6, 42, + 9, 8, 15, 19, 12, 28, 15, 43, 12, 10, 19, 14, 21, 30, 19, + 34, 21, 0, 27, 16, 25, 23, 28, 36, 25, 6, 2, 12, 0, 30, + 2, 36, 0, 4, 6, 21, 9, 28, 6, 41, 9, 7, 15, 20, 12, + 27, 15, 43, 13, 9, 19, 13, 21, 29, 19, 33, 21, 0, 28, 15, + 25, 24, 28, 35, 25, 7, 2, 13, 0, 31, 2, 37, 0, 5, 6, + 20, 9, 29, 6, 40, 9, 6, 15, 21, 12, 26, 15, 42, 13, 8, + 19, 12, 21, 28, 19, 33, 22, 1, 28, 14, 25, 25, 28, 34, 25, + 8, 2, 14, 0, 32, 2, 38, 0, 6, 6, 19, 9, 30, 6, 39, + 9, 5, 15, 21, 13, 25, 15, 41, 13, 7, 19, 11, 21, 27, 19, + 34, 22, 2, 28, 13, 25, 26, 28, 33, 25, 9, 2, 15, 0, 32, + 3, 39, 0, 7, 6, 18, 9, 31, 6, 38, 9, 4, 15, 20, 13, + 24, 15, 40, 13, 6, 19, 11, 22, 26, 19, 35, 22, 3, 28, 12, + 25, 27, 28, 33, 26, 10, 2, 16, 0, 31, 3, 40, 0, 8, 6, + 17, 9, 32, 6, 37, 9, 3, 15, 19, 13, 23, 15, 39, 13, 5, + 19, 12, 22, 25, 19, 36, 22, 4, 28, 11, 25, 28, 28, 34, 26, + 10, 3, 17, 0, 30, 3, 41, 0, 9, 6, 16, 9, 32, 7, 36, + 9, 2, 15, 18, 13, 22, 15, 38, 13, 4, 19, 13, 22, 24, 19, + 37, 22, 5, 28, 11, 26, 29, 28, 35, 26, 9, 3, 18, 0, 29, + 3, 42, 0, 10, 6, 15, 9, 31, 7, 35, 9, 1, 15, 17, 13, + 22, 16, 37, 13, 3, 19, 14, 22, 23, 19, 38, 22, 6, 28, 12, + 26, 30, 28, 36, 26, 8, 3, 19, 0, 28, 3, 43, 0, 10, 7, + 14, 9, 30, 7, 34, 9, 0, 15, 16, 13, 23, 16, 36, 13, 2, + 19, 15, 22, 22, 19, 39, 22, 7, 28, 13, 26, 31, 28, 37, 26, + 7, 3, 20, 0, 27, 3, 43, 1, 9, 7, 13, 9, 29, 7, 33, + 9, 0, 16, 15, 13, 24, 16, 35, 13, 1, 19, 16, 22, 22, 20, + 40, 22, 8, 28, 14, 26, 32, 28, 38, 26, 6, 3, 21, 0, 26, + 3, 42, 1, 8, 7, 12, 9, 28, 7, 33, 10, 1, 16, 14, 13, + 25, 16, 34, 13, 0, 19, 17, 22, 23, 20, 41, 22, 9, 28, 15, + 26, 32, 29, 39, 26, 5, 3, 21, 1, 25, 3, 41, 1, 7, 7, + 11, 9, 27, 7, 34, 10, 2, 16, 13, 13, 26, 16, 33, 13, 0, + 20, 18, 22, 24, 20, 42, 22, 10, 28, 16, 26, 31, 29, 40, 26, + 4, 3, 20, 1, 24, 3, 40, 1, 6, 7, 11, 10, 26, 7, 35, + 10, 3, 16, 12, 13, 27, 16, 33, 14, 1, 20, 19, 22, 25, 20, + 43, 22, 10, 29, 17, 26, 30, 29, 41, 26, 3, 3, 19, 1, 23, + 3, 39, 1, 5, 7, 12, 10, 25, 7, 36, 10, 4, 16, 11, 13, + 28, 16, 34, 14, 2, 20, 20, 22, 26, 20, 43, 23, 9, 29, 18, + 26, 29, 29, 42, 26, 2, 3, 18, 1, 22, 3, 38, 1, 4, 7, + 13, 10, 24, 7, 37, 10, 5, 16, 11, 14, 29, 16, 35, 14, 3, + 20, 21, 22, 27, 20, 42, 23, 8, 29, 19, 26, 28, 29, 43, 26, + 1, 3, 17, 1, 22, 4, 37, 1, 3, 7, 14, 10, 23, 7, 38, + 10, 6, 16, 12, 14, 30, 16, 36, 14, 4, 20, 21, 23, 28, 20, + 41, 23, 7, 29, 20, 26, 27, 29, 43, 27, 0, 3, 16, 1, 23, + 4, 36, 1, 2, 7, 15, 10, 22, 7, 39, 10, 7, 16, 13, 14, + 31, 16, 37, 14, 5, 20, 20, 23, 29, 20, 40, 23, 6, 29, 21, + 26, 26, 29, 42, 27, 0, 4, 15, 1, 24, 4, 35, 1, 1, 7, + 16, 10, 22, 8, 40, 10, 8, 16, 14, 14, 32, 16, 38, 14, 6, + 20, 19, 23, 30, 20, 39, 23, 5, 29, 21, 27, 25, 29, 41, 27, + 1, 4, 14, 1, 25, 4, 34, 1, 0, 7, 17, 10, 23, 8, 41, + 10, 9, 16, 15, 14, 32, 17, 39, 14, 7, 20, 18, 23, 31, 20, + 38, 23, 4, 29, 20, 27, 24, 29, 40, 27, 2, 4, 13, 1, 26, + 4, 33, 1, 0, 8, 18, 10, 24, 8, 42, 10, 10, 16, 16, 14, + 31, 17, 40, 14, 8, 20, 17, 23, 32, 20, 37, 23, 3, 29, 19, + 27, 23, 29, 39, 27, 3, 4, 12, 1, 27, 4, 33, 2, 1, 8, + 19, 10, 25, 8, 43, 10, 10, 17, 17, 14, 30, 17, 41, 14, 9, + 20, 16, 23, 32, 21, 36, 23, 2, 29, 18, 27, 22, 29, 38, 27, + 4, 4, 11, 1, 28, 4, 34, 2, 2, 8, 20, 10, 26, 8, 43, + 11, 9, 17, 18, 14, 29, 17, 42, 14, 10, 20, 15, 23, 31, 21, + 35, 23, 1, 29, 17, 27, 22, 24, 37, 27, 5, 4, 11, 2, 29, + 4, 35, 2, 3, 8, 21, 10, 27, 8, 42, 11, 8, 17, 19, 14, + 28, 17, 43, 14, 10, 21, 14, 23, 30, 21, 34, 23, 0, 29, 16, + 27, 23, 24, 36, 27, 6, 4, 12, 2, 30, 4, 36, 2, 4, 8, + 21, 11, 28, 8, 41, 11, 7, 17, 20, 14, 27, 17, 43, 15, 9, + 21, 13, 23, 29, 21, 33, 23, 0, 24, 15, 27, 24, 24, 35, 27, + 7, 4, 13, 2, 31, 4, 37, 2, 5, 8, 20, 11, 29, 8, 40, + 11, 6, 17, 21, 14, 26, 17, 42, 15, 8, 21, 12, 23, 28, 21, + 33, 18, 1, 24, 14, 27, 25, 24, 34, 27, 8, 4, 14, 2, 32, + 4, 38, 2, 6, 8, 19, 11, 30, 8, 39, 11, 5, 17, 21, 15, + 25, 17, 41, 15, 7, 21, 11, 23, 27, 21, 34, 18, 2, 24, 13, + 27, 26, 24, 33, 27, 9, 4, 15, 2, 32, 5, 39, 2, 7, 8, + 18, 11, 31, 8, 38, 11, 4, 17, 20, 15, 24, 17, 40, 15, 6, + 21, 11, 18, 26, 21, 35, 18, 3, 24, 12, 27, 27, 24, 33, 28, + 10, 4, 16, 2, 31, 5, 40, 2, 8, 8, 17, 11, 32, 8, 37, + 11, 3, 17, 19, 15, 23, 17, 39, 15, 5, 21, 12, 18, 25, 21, + 36, 18, 4, 24, 11, 27, 28, 24, 34, 28, 10, 5, 17, 2, 30, + 5, 41, 2, 9, 8, 16, 11, 32, 9, 36, 11, 2, 17, 18, 15, + 22, 17, 38, 15, 4, 21, 13, 18, 24, 21, 37, 18, 5, 24, 11, + 28, 29, 24, 35, 28, 9, 5, 18, 2, 29, 5, 42, 2, 10, 8, + 15, 11, 31, 9, 35, 11, 1, 17, 17, 15, 22, 12, 37, 15, 3, + 21, 14, 18, 23, 21, 38, 18, 6, 24, 12, 28, 30, 24, 36, 28, + 8, 5, 19, 2, 28, 5, 43, 2, 10, 9, 14, 11, 30, 9, 34, + 11, 0, 17, 16, 15, 23, 12, 36, 15, 2, 21, 15, 18, 22, 21, + 39, 18, 7, 24, 13, 28, 31, 24, 37, 28, 7, 5, 20, 2, 27, + 5, 43, 3, 9, 9, 13, 11, 29, 9, 33, 11, 0, 12, 15, 15, + 24, 12, 35, 15, 1, 21, 16, 18, 22, 22, 40, 18, 8, 24, 14, + 28, 32, 24, 38, 28, 6, 5, 21, 2, 26, 5, 42, 3, 8, 9, + 12, 11, 28, 9, 33, 6, 1, 12, 14, 15, 25, 12, 34, 15, 0, + 21, 17, 18, 23, 22, 41, 18, 9, 24, 15, 28, 32, 25, 39, 28, + 5, 5, 21, 3, 25, 5, 41, 3, 7, 9, 11, 11, 27, 9, 34, + 6, 2, 12, 13, 15, 26, 12, 33, 15, 0, 22, 18, 18, 24, 22, + 42, 18, 10, 24, 16, 28, 31, 25, 40, 28, 4, 5, 20, 3, 24, + 5, 40, 3, 6, 9, 11, 6, 26, 9, 35, 6, 3, 12, 12, 15, + 27, 12, 33, 16, 1, 22, 19, 18, 25, 22, 43, 18, 10, 25, 17, + 28, 30, 25, 41, 28, 3, 5, 19, 3, 23, 5, 39, 3, 5, 9, + 12, 6, 25, 9, 36, 6, 4, 12, 11, 15, 28, 12, 34, 16, 2, + 22, 20, 18, 26, 22, 43, 19, 9, 25, 18, 28, 29, 25, 42, 28, + 2, 5, 18, 3, 22, 5, 38, 3, 4, 9, 13, 6, 24, 9, 37, + 6, 5, 12, 11, 16, 29, 12, 35, 16, 3, 22, 21, 18, 27, 22, + 42, 19, 8, 25, 19, 28, 28, 25, 43, 28, 1, 5, 17, 3, 22, + 0, 37, 3, 3, 9, 14, 6, 23, 9, 38, 6, 6, 12, 12, 16, + 30, 12, 36, 16, 4, 22, 21, 19, 28, 22, 41, 19, 7, 25, 20, + 28, 27, 25, 43, 29, 0, 5, 16, 3, 23, 0, 36, 3, 2, 9, + 15, 6, 22, 9, 39, 6, 7, 12, 13, 16, 31, 12, 37, 16, 5, + 22, 20, 19, 29, 22, 40, 19, 6, 25, 21, 28, 26, 25, 42, 29, +}; + +static const uint8_t hq_tab_21[] = { + 0, 0, 15, 3, 24, 0, 35, 3, 1, 9, 16, 6, 22, 10, 40, + 6, 8, 12, 14, 16, 32, 12, 38, 16, 6, 22, 19, 19, 30, 22, + 39, 19, 5, 25, 21, 29, 25, 25, 41, 29, 7, 35, 11, 31, 27, + 35, 34, 32, 1, 0, 14, 3, 25, 0, 34, 3, 0, 9, 17, 6, + 23, 10, 41, 6, 9, 12, 15, 16, 32, 13, 39, 16, 7, 22, 18, + 19, 31, 22, 38, 19, 4, 25, 20, 29, 24, 25, 40, 29, 6, 35, + 11, 32, 26, 35, 35, 32, 2, 0, 13, 3, 26, 0, 33, 3, 0, + 10, 18, 6, 24, 10, 42, 6, 10, 12, 16, 16, 31, 13, 40, 16, + 8, 22, 17, 19, 32, 22, 37, 19, 3, 25, 19, 29, 23, 25, 39, + 29, 5, 35, 12, 32, 25, 35, 36, 32, 3, 0, 12, 3, 27, 0, + 33, 4, 1, 10, 19, 6, 25, 10, 43, 6, 10, 13, 17, 16, 30, + 13, 41, 16, 9, 22, 16, 19, 32, 23, 36, 19, 2, 25, 18, 29, + 22, 25, 38, 29, 4, 35, 13, 32, 24, 35, 37, 32, 4, 0, 11, + 3, 28, 0, 34, 4, 2, 10, 20, 6, 26, 10, 43, 7, 9, 13, + 18, 16, 29, 13, 42, 16, 10, 22, 15, 19, 31, 23, 35, 19, 1, + 25, 17, 29, 22, 26, 37, 29, 3, 35, 14, 32, 23, 35, 38, 32, + 5, 0, 11, 4, 29, 0, 35, 4, 3, 10, 21, 6, 27, 10, 42, + 7, 8, 13, 19, 16, 28, 13, 43, 16, 10, 23, 14, 19, 30, 23, + 34, 19, 0, 25, 16, 29, 23, 26, 36, 29, 2, 35, 15, 32, 22, + 35, 39, 32, 6, 0, 12, 4, 30, 0, 36, 4, 4, 10, 21, 7, + 28, 10, 41, 7, 7, 13, 20, 16, 27, 13, 43, 17, 9, 23, 13, + 19, 29, 23, 33, 19, 0, 26, 15, 29, 24, 26, 35, 29, 1, 35, + 16, 32, 22, 30, 40, 32, 7, 0, 13, 4, 31, 0, 37, 4, 5, + 10, 20, 7, 29, 10, 40, 7, 6, 13, 21, 16, 26, 13, 42, 17, + 8, 23, 12, 19, 28, 23, 33, 20, 1, 26, 14, 29, 25, 26, 34, + 29, 0, 35, 17, 32, 23, 30, 41, 32, 8, 0, 14, 4, 32, 0, + 38, 4, 6, 10, 19, 7, 30, 10, 39, 7, 5, 13, 21, 17, 25, + 13, 41, 17, 7, 23, 11, 19, 27, 23, 34, 20, 2, 26, 13, 29, + 26, 26, 33, 29, 0, 30, 18, 32, 24, 30, 42, 32, 9, 0, 15, + 4, 32, 1, 39, 4, 7, 10, 18, 7, 31, 10, 38, 7, 4, 13, + 20, 17, 24, 13, 40, 17, 6, 23, 11, 20, 26, 23, 35, 20, 3, + 26, 12, 29, 27, 26, 33, 24, 1, 30, 19, 32, 25, 30, 43, 32, + 10, 0, 16, 4, 31, 1, 40, 4, 8, 10, 17, 7, 32, 10, 37, + 7, 3, 13, 19, 17, 23, 13, 39, 17, 5, 23, 12, 20, 25, 23, + 36, 20, 4, 26, 11, 29, 28, 26, 34, 24, 2, 30, 20, 32, 26, + 30, 43, 33, 10, 1, 17, 4, 30, 1, 41, 4, 9, 10, 16, 7, + 32, 11, 36, 7, 2, 13, 18, 17, 22, 13, 38, 17, 4, 23, 13, + 20, 24, 23, 37, 20, 5, 26, 11, 24, 29, 26, 35, 24, 3, 30, + 21, 32, 27, 30, 42, 33, 9, 1, 18, 4, 29, 1, 42, 4, 10, + 10, 15, 7, 31, 11, 35, 7, 1, 13, 17, 17, 22, 14, 37, 17, + 3, 23, 14, 20, 23, 23, 38, 20, 6, 26, 12, 24, 30, 26, 36, + 24, 4, 30, 21, 33, 28, 30, 41, 33, 8, 1, 19, 4, 28, 1, + 43, 4, 10, 11, 14, 7, 30, 11, 34, 7, 0, 13, 16, 17, 23, + 14, 36, 17, 2, 23, 15, 20, 22, 23, 39, 20, 7, 26, 13, 24, + 31, 26, 37, 24, 5, 30, 20, 33, 29, 30, 40, 33, 7, 1, 20, + 4, 27, 1, 43, 5, 9, 11, 13, 7, 29, 11, 33, 7, 0, 14, + 15, 17, 24, 14, 35, 17, 1, 23, 16, 20, 22, 18, 40, 20, 8, + 26, 14, 24, 32, 26, 38, 24, 6, 30, 19, 33, 30, 30, 39, 33, + 6, 1, 21, 4, 26, 1, 42, 5, 8, 11, 12, 7, 28, 11, 33, + 8, 1, 14, 14, 17, 25, 14, 34, 17, 0, 23, 17, 20, 23, 18, + 41, 20, 9, 26, 15, 24, 32, 27, 39, 24, 7, 30, 18, 33, 31, + 30, 38, 33, 5, 1, 21, 5, 25, 1, 41, 5, 7, 11, 11, 7, + 27, 11, 34, 8, 2, 14, 13, 17, 26, 14, 33, 17, 0, 18, 18, + 20, 24, 18, 42, 20, 10, 26, 16, 24, 31, 27, 40, 24, 8, 30, + 17, 33, 32, 30, 37, 33, 4, 1, 20, 5, 24, 1, 40, 5, 6, + 11, 11, 8, 26, 11, 35, 8, 3, 14, 12, 17, 27, 14, 33, 12, + 1, 18, 19, 20, 25, 18, 43, 20, 10, 27, 17, 24, 30, 27, 41, + 24, 9, 30, 16, 33, 32, 31, 36, 33, 3, 1, 19, 5, 23, 1, + 39, 5, 5, 11, 12, 8, 25, 11, 36, 8, 4, 14, 11, 17, 28, + 14, 34, 12, 2, 18, 20, 20, 26, 18, 43, 21, 9, 27, 18, 24, + 29, 27, 42, 24, 10, 30, 15, 33, 31, 31, 35, 33, 2, 1, 18, + 5, 22, 1, 38, 5, 4, 11, 13, 8, 24, 11, 37, 8, 5, 14, + 11, 12, 29, 14, 35, 12, 3, 18, 21, 20, 27, 18, 42, 21, 8, + 27, 19, 24, 28, 27, 43, 24, 10, 31, 14, 33, 30, 31, 34, 33, + 1, 1, 17, 5, 22, 2, 37, 5, 3, 11, 14, 8, 23, 11, 38, + 8, 6, 14, 12, 12, 30, 14, 36, 12, 4, 18, 21, 21, 28, 18, + 41, 21, 7, 27, 20, 24, 27, 27, 43, 25, 9, 31, 13, 33, 29, + 31, 33, 33, 0, 1, 16, 5, 23, 2, 36, 5, 2, 11, 15, 8, + 22, 11, 39, 8, 7, 14, 13, 12, 31, 14, 37, 12, 5, 18, 20, + 21, 29, 18, 40, 21, 6, 27, 21, 24, 26, 27, 42, 25, 8, 31, + 12, 33, 28, 31, 33, 34, 0, 2, 15, 5, 24, 2, 35, 5, 1, + 11, 16, 8, 22, 6, 40, 8, 8, 14, 14, 12, 32, 14, 38, 12, + 6, 18, 19, 21, 30, 18, 39, 21, 5, 27, 21, 25, 25, 27, 41, + 25, 7, 31, 11, 33, 27, 31, 34, 34, 1, 2, 14, 5, 25, 2, + 34, 5, 0, 11, 17, 8, 23, 6, 41, 8, 9, 14, 15, 12, 32, + 15, 39, 12, 7, 18, 18, 21, 31, 18, 38, 21, 4, 27, 20, 25, + 24, 27, 40, 25, 6, 31, 11, 34, 26, 31, 35, 34, 2, 2, 13, + 5, 26, 2, 33, 5, 0, 6, 18, 8, 24, 6, 42, 8, 10, 14, + 16, 12, 31, 15, 40, 12, 8, 18, 17, 21, 32, 18, 37, 21, 3, + 27, 19, 25, 23, 27, 39, 25, 5, 31, 12, 34, 25, 31, 36, 34, + 3, 2, 12, 5, 27, 2, 33, 0, 1, 6, 19, 8, 25, 6, 43, + 8, 10, 15, 17, 12, 30, 15, 41, 12, 9, 18, 16, 21, 32, 19, + 36, 21, 2, 27, 18, 25, 22, 27, 38, 25, 4, 31, 13, 34, 24, + 31, 37, 34, 4, 2, 11, 5, 28, 2, 34, 0, 2, 6, 20, 8, + 26, 6, 43, 9, 9, 15, 18, 12, 29, 15, 42, 12, 10, 18, 15, + 21, 31, 19, 35, 21, 1, 27, 17, 25, 22, 28, 37, 25, 3, 31, + 14, 34, 23, 31, 38, 34, 5, 2, 11, 0, 29, 2, 35, 0, 3, + 6, 21, 8, 27, 6, 42, 9, 8, 15, 19, 12, 28, 15, 43, 12, + 10, 19, 14, 21, 30, 19, 34, 21, 0, 27, 16, 25, 23, 28, 36, + 25, 2, 31, 15, 34, 22, 31, 39, 34, 6, 2, 12, 0, 30, 2, + 36, 0, 4, 6, 21, 9, 28, 6, 41, 9, 7, 15, 20, 12, 27, + 15, 43, 13, 9, 19, 13, 21, 29, 19, 33, 21, 0, 28, 15, 25, + 24, 28, 35, 25, 1, 31, 16, 34, 22, 32, 40, 34, 7, 2, 13, + 0, 31, 2, 37, 0, 5, 6, 20, 9, 29, 6, 40, 9, 6, 15, + 21, 12, 26, 15, 42, 13, 8, 19, 12, 21, 28, 19, 33, 22, 1, + 28, 14, 25, 25, 28, 34, 25, 0, 31, 17, 34, 23, 32, 41, 34, + 8, 2, 14, 0, 32, 2, 38, 0, 6, 6, 19, 9, 30, 6, 39, + 9, 5, 15, 21, 13, 25, 15, 41, 13, 7, 19, 11, 21, 27, 19, + 34, 22, 2, 28, 13, 25, 26, 28, 33, 25, 0, 32, 18, 34, 24, + 32, 42, 34, 9, 2, 15, 0, 32, 3, 39, 0, 7, 6, 18, 9, + 31, 6, 38, 9, 4, 15, 20, 13, 24, 15, 40, 13, 6, 19, 11, + 22, 26, 19, 35, 22, 3, 28, 12, 25, 27, 28, 33, 26, 1, 32, + 19, 34, 25, 32, 43, 34, 10, 2, 16, 0, 31, 3, 40, 0, 8, + 6, 17, 9, 32, 6, 37, 9, 3, 15, 19, 13, 23, 15, 39, 13, + 5, 19, 12, 22, 25, 19, 36, 22, 4, 28, 11, 25, 28, 28, 34, + 26, 2, 32, 20, 34, 26, 32, 43, 35, 10, 3, 17, 0, 30, 3, + 41, 0, 9, 6, 16, 9, 32, 7, 36, 9, 2, 15, 18, 13, 22, + 15, 38, 13, 4, 19, 13, 22, 24, 19, 37, 22, 5, 28, 11, 26, + 29, 28, 35, 26, 3, 32, 21, 34, 27, 32, 42, 35, 9, 3, 18, + 0, 29, 3, 42, 0, 10, 6, 15, 9, 31, 7, 35, 9, 1, 15, + 17, 13, 22, 16, 37, 13, 3, 19, 14, 22, 23, 19, 38, 22, 6, + 28, 12, 26, 30, 28, 36, 26, 4, 32, 21, 35, 28, 32, 41, 35, + 8, 3, 19, 0, 28, 3, 43, 0, 10, 7, 14, 9, 30, 7, 34, + 9, 0, 15, 16, 13, 23, 16, 36, 13, 2, 19, 15, 22, 22, 19, + 39, 22, 7, 28, 13, 26, 31, 28, 37, 26, 5, 32, 20, 35, 29, + 32, 40, 35, 7, 3, 20, 0, 27, 3, 43, 1, 9, 7, 13, 9, + 29, 7, 33, 9, 0, 16, 15, 13, 24, 16, 35, 13, 1, 19, 16, + 22, 22, 20, 40, 22, 8, 28, 14, 26, 32, 28, 38, 26, 6, 32, + 19, 35, 30, 32, 39, 35, 6, 3, 21, 0, 26, 3, 42, 1, 8, + 7, 12, 9, 28, 7, 33, 10, 1, 16, 14, 13, 25, 16, 34, 13, + 0, 19, 17, 22, 23, 20, 41, 22, 9, 28, 15, 26, 32, 29, 39, + 26, 7, 32, 18, 35, 31, 32, 38, 35, 5, 3, 21, 1, 25, 3, + 41, 1, 7, 7, 11, 9, 27, 7, 34, 10, 2, 16, 13, 13, 26, + 16, 33, 13, 0, 20, 18, 22, 24, 20, 42, 22, 10, 28, 16, 26, + 31, 29, 40, 26, 8, 32, 17, 35, 32, 32, 37, 35, 4, 3, 20, + 1, 24, 3, 40, 1, 6, 7, 11, 10, 26, 7, 35, 10, 3, 16, + 12, 13, 27, 16, 33, 14, 1, 20, 19, 22, 25, 20, 43, 22, 10, + 29, 17, 26, 30, 29, 41, 26, 9, 32, 16, 35, 32, 33, 36, 35, + 3, 3, 19, 1, 23, 3, 39, 1, 5, 7, 12, 10, 25, 7, 36, + 10, 4, 16, 11, 13, 28, 16, 34, 14, 2, 20, 20, 22, 26, 20, + 43, 23, 9, 29, 18, 26, 29, 29, 42, 26, 10, 32, 15, 35, 31, + 33, 35, 35, 2, 3, 18, 1, 22, 3, 38, 1, 4, 7, 13, 10, + 24, 7, 37, 10, 5, 16, 11, 14, 29, 16, 35, 14, 3, 20, 21, + 22, 27, 20, 42, 23, 8, 29, 19, 26, 28, 29, 43, 26, 10, 33, + 14, 35, 30, 33, 34, 35, 1, 3, 17, 1, 22, 4, 37, 1, 3, + 7, 14, 10, 23, 7, 38, 10, 6, 16, 12, 14, 30, 16, 36, 14, + 4, 20, 21, 23, 28, 20, 41, 23, 7, 29, 20, 26, 27, 29, 43, + 27, 9, 33, 13, 35, 29, 33, 33, 35, 0, 3, 16, 1, 23, 4, + 36, 1, 2, 7, 15, 10, 22, 7, 39, 10, 7, 16, 13, 14, 31, + 16, 37, 14, 5, 20, 20, 23, 29, 20, 40, 23, 6, 29, 21, 26, + 26, 29, 42, 27, 8, 33, 12, 35, 28, 33, 33, 30, 0, 4, 15, + 1, 24, 4, 35, 1, 1, 7, 16, 10, 22, 8, 40, 10, 8, 16, + 14, 14, 32, 16, 38, 14, 6, 20, 19, 23, 30, 20, 39, 23, 5, + 29, 21, 27, 25, 29, 41, 27, 7, 33, 11, 35, 27, 33, 34, 30, + 1, 4, 14, 1, 25, 4, 34, 1, 0, 7, 17, 10, 23, 8, 41, + 10, 9, 16, 15, 14, 32, 17, 39, 14, 7, 20, 18, 23, 31, 20, + 38, 23, 4, 29, 20, 27, 24, 29, 40, 27, 6, 33, 11, 30, 26, + 33, 35, 30, 2, 4, 13, 1, 26, 4, 33, 1, 0, 8, 18, 10, + 24, 8, 42, 10, 10, 16, 16, 14, 31, 17, 40, 14, 8, 20, 17, + 23, 32, 20, 37, 23, 3, 29, 19, 27, 23, 29, 39, 27, 5, 33, + 12, 30, 25, 33, 36, 30, 3, 4, 12, 1, 27, 4, 33, 2, 1, + 8, 19, 10, 25, 8, 43, 10, 10, 17, 17, 14, 30, 17, 41, 14, + 9, 20, 16, 23, 32, 21, 36, 23, 2, 29, 18, 27, 22, 29, 38, + 27, 4, 33, 13, 30, 24, 33, 37, 30, 4, 4, 11, 1, 28, 4, + 34, 2, 2, 8, 20, 10, 26, 8, 43, 11, 9, 17, 18, 14, 29, + 17, 42, 14, 10, 20, 15, 23, 31, 21, 35, 23, 1, 29, 17, 27, + 22, 24, 37, 27, 3, 33, 14, 30, 23, 33, 38, 30, 5, 4, 11, + 2, 29, 4, 35, 2, 3, 8, 21, 10, 27, 8, 42, 11, 8, 17, + 19, 14, 28, 17, 43, 14, 10, 21, 14, 23, 30, 21, 34, 23, 0, + 29, 16, 27, 23, 24, 36, 27, 2, 33, 15, 30, 22, 33, 39, 30, + 6, 4, 12, 2, 30, 4, 36, 2, 4, 8, 21, 11, 28, 8, 41, + 11, 7, 17, 20, 14, 27, 17, 43, 15, 9, 21, 13, 23, 29, 21, + 33, 23, 0, 24, 15, 27, 24, 24, 35, 27, 1, 33, 16, 30, 22, + 34, 40, 30, 7, 4, 13, 2, 31, 4, 37, 2, 5, 8, 20, 11, + 29, 8, 40, 11, 6, 17, 21, 14, 26, 17, 42, 15, 8, 21, 12, + 23, 28, 21, 33, 18, 1, 24, 14, 27, 25, 24, 34, 27, 0, 33, + 17, 30, 23, 34, 41, 30, 8, 4, 14, 2, 32, 4, 38, 2, 6, + 8, 19, 11, 30, 8, 39, 11, 5, 17, 21, 15, 25, 17, 41, 15, + 7, 21, 11, 23, 27, 21, 34, 18, 2, 24, 13, 27, 26, 24, 33, + 27, 0, 34, 18, 30, 24, 34, 42, 30, 9, 4, 15, 2, 32, 5, + 39, 2, 7, 8, 18, 11, 31, 8, 38, 11, 4, 17, 20, 15, 24, + 17, 40, 15, 6, 21, 11, 18, 26, 21, 35, 18, 3, 24, 12, 27, + 27, 24, 33, 28, 1, 34, 19, 30, 25, 34, 43, 30, 10, 4, 16, + 2, 31, 5, 40, 2, 8, 8, 17, 11, 32, 8, 37, 11, 3, 17, + 19, 15, 23, 17, 39, 15, 5, 21, 12, 18, 25, 21, 36, 18, 4, + 24, 11, 27, 28, 24, 34, 28, 2, 34, 20, 30, 26, 34, 43, 31, + 10, 5, 17, 2, 30, 5, 41, 2, 9, 8, 16, 11, 32, 9, 36, + 11, 2, 17, 18, 15, 22, 17, 38, 15, 4, 21, 13, 18, 24, 21, + 37, 18, 5, 24, 11, 28, 29, 24, 35, 28, 3, 34, 21, 30, 27, + 34, 42, 31, 9, 5, 18, 2, 29, 5, 42, 2, 10, 8, 15, 11, + 31, 9, 35, 11, 1, 17, 17, 15, 22, 12, 37, 15, 3, 21, 14, + 18, 23, 21, 38, 18, 6, 24, 12, 28, 30, 24, 36, 28, 4, 34, + 21, 31, 28, 34, 41, 31, 8, 5, 19, 2, 28, 5, 43, 2, 10, + 9, 14, 11, 30, 9, 34, 11, 0, 17, 16, 15, 23, 12, 36, 15, + 2, 21, 15, 18, 22, 21, 39, 18, 7, 24, 13, 28, 31, 24, 37, + 28, 5, 34, 20, 31, 29, 34, 40, 31, 7, 5, 20, 2, 27, 5, + 43, 3, 9, 9, 13, 11, 29, 9, 33, 11, 0, 12, 15, 15, 24, + 12, 35, 15, 1, 21, 16, 18, 22, 22, 40, 18, 8, 24, 14, 28, + 32, 24, 38, 28, 6, 34, 19, 31, 30, 34, 39, 31, 6, 5, 21, + 2, 26, 5, 42, 3, 8, 9, 12, 11, 28, 9, 33, 6, 1, 12, + 14, 15, 25, 12, 34, 15, 0, 21, 17, 18, 23, 22, 41, 18, 9, + 24, 15, 28, 32, 25, 39, 28, 7, 34, 18, 31, 31, 34, 38, 31, + 5, 5, 21, 3, 25, 5, 41, 3, 7, 9, 11, 11, 27, 9, 34, + 6, 2, 12, 13, 15, 26, 12, 33, 15, 0, 22, 18, 18, 24, 22, + 42, 18, 10, 24, 16, 28, 31, 25, 40, 28, 8, 34, 17, 31, 32, + 34, 37, 31, 4, 5, 20, 3, 24, 5, 40, 3, 6, 9, 11, 6, + 26, 9, 35, 6, 3, 12, 12, 15, 27, 12, 33, 16, 1, 22, 19, + 18, 25, 22, 43, 18, 10, 25, 17, 28, 30, 25, 41, 28, 9, 34, + 16, 31, 32, 35, 36, 31, 3, 5, 19, 3, 23, 5, 39, 3, 5, + 9, 12, 6, 25, 9, 36, 6, 4, 12, 11, 15, 28, 12, 34, 16, + 2, 22, 20, 18, 26, 22, 43, 19, 9, 25, 18, 28, 29, 25, 42, + 28, 10, 34, 15, 31, 31, 35, 35, 31, 2, 5, 18, 3, 22, 5, + 38, 3, 4, 9, 13, 6, 24, 9, 37, 6, 5, 12, 11, 16, 29, + 12, 35, 16, 3, 22, 21, 18, 27, 22, 42, 19, 8, 25, 19, 28, + 28, 25, 43, 28, 10, 35, 14, 31, 30, 35, 34, 31, 1, 5, 17, + 3, 22, 0, 37, 3, 3, 9, 14, 6, 23, 9, 38, 6, 6, 12, + 12, 16, 30, 12, 36, 16, 4, 22, 21, 19, 28, 22, 41, 19, 7, + 25, 20, 28, 27, 25, 43, 29, 9, 35, 13, 31, 29, 35, 33, 31, + 0, 5, 16, 3, 23, 0, 36, 3, 2, 9, 15, 6, 22, 9, 39, + 6, 7, 12, 13, 16, 31, 12, 37, 16, 5, 22, 20, 19, 29, 22, + 40, 19, 6, 25, 21, 28, 26, 25, 42, 29, 8, 35, 12, 31, 28, + 35, 33, 32, +}; + +/* List of profiles, order is important */ +const HQProfile ff_hq_profile[NUM_HQ_PROFILES] = { + { hq_tab_11, 160, 120, 8, 10, 8 }, // case 0 (default) = case 11 + { hq_tab_01, 720, 480, 8, 25, 54 }, + { hq_tab_02, 720, 486, 8, 15, 93 }, + { hq_tab_03, 720, 576, 8, 20, 81 }, + { hq_tab_04, 960, 720, 12, 25, 108 }, + { hq_tab_05, 1280, 720, 16, 25, 144 }, + { hq_tab_06, 1280, 1080, 16, 20, 272 }, + { hq_tab_07, 1440, 1080, 16, 24, 255 }, + { hq_tab_08, 1920, 1080, 20, 24, 340 }, + { hq_tab_09, 640, 480, 8, 25, 48 }, + { hq_tab_10, 320, 240, 8, 25, 12 }, + { hq_tab_11, 160, 120, 8, 10, 8 }, + { hq_tab_12, 800, 600, 8, 25, 76 }, + { hq_tab_13, 352, 480, 8, 20, 33 }, + { hq_tab_14, 352, 240, 8, 22, 15 }, + { hq_tab_15, 352, 288, 8, 18, 22 }, + { hq_tab_16, 176, 144, 8, 9, 11 }, + { hq_tab_17, 1280, 1024, 16, 20, 256 }, + { hq_tab_18, 1280, 960, 16, 25, 192 }, + { hq_tab_19, 1024, 768, 16, 24, 128 }, + { hq_tab_20, 704, 480, 8, 20, 66 }, + { hq_tab_21, 704, 576, 8, 24, 66 }, +}; + +av_cold int ff_hq_init_vlcs(HQContext *c) +{ + int ret = init_vlc(&c->hqa_cbp_vlc, 5, FF_ARRAY_ELEMS(cbp_vlc_lens), + cbp_vlc_lens, 1, 1, cbp_vlc_bits, 1, 1, 0); + if (ret < 0) + return ret; + + return init_vlc(&c->hq_ac_vlc, 9, NUM_HQ_AC_ENTRIES, + ff_hq_ac_bits, 1, 1, ff_hq_ac_codes, 2, 2, 0); +} diff --git a/libavcodec/hq_hqadsp.c b/libavcodec/hq_hqadsp.c new file mode 100644 index 0000000..93fc067 --- /dev/null +++ b/libavcodec/hq_hqadsp.c @@ -0,0 +1,130 @@ +/* + * Canopus HQ/HQA decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/common.h" + +#include "hq_hqadsp.h" + +#define FIX_1_082 17734 +#define FIX_1_847 30274 +#define FIX_1_414 23170 +#define FIX_2_613 21407 // divided by two to fit the range + +#define IDCTMUL(a, b) ((a) * (b) >> 16) + +static inline void idct_row(int16_t *blk) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmpA; + int tmpB, tmpC, tmpD, tmpE, tmpF, tmp10, tmp11, tmp12, tmp13, tmp14; + + tmp0 = blk[5] - blk[3]; + tmp1 = blk[5] + blk[3]; + tmp2 = blk[1] - blk[7]; + tmp3 = blk[1] + blk[7]; + tmp4 = tmp3 - tmp1; + tmp5 = IDCTMUL(tmp0 + tmp2, FIX_1_847); + tmp6 = IDCTMUL(tmp2, FIX_1_082) - tmp5; + tmp7 = tmp5 - IDCTMUL(tmp0, FIX_2_613) * 2; + tmp8 = tmp3 + tmp1; + tmp9 = tmp7 * 4 - tmp8; + tmpA = IDCTMUL(tmp4, FIX_1_414) * 4 - tmp9; + tmpB = tmp6 * 4 + tmpA; + tmpC = blk[2] + blk[6]; + tmpD = blk[2] - blk[6]; + tmpE = blk[0] - blk[4]; + tmpF = blk[0] + blk[4]; + + tmp10 = IDCTMUL(tmpD, FIX_1_414) * 4 - tmpC; + tmp11 = tmpE - tmp10; + tmp12 = tmpF - tmpC; + tmp13 = tmpE + tmp10; + tmp14 = tmpF + tmpC; + + blk[0] = tmp14 + tmp8; + blk[1] = tmp13 + tmp9; + blk[2] = tmp11 + tmpA; + blk[3] = tmp12 - tmpB; + blk[4] = tmp12 + tmpB; + blk[5] = tmp11 - tmpA; + blk[6] = tmp13 - tmp9; + blk[7] = tmp14 - tmp8; +} + +static inline void idct_col(int16_t *blk) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmpA; + int tmpB, tmpC, tmpD, tmpE, tmpF, tmp10, tmp11, tmp12, tmp13, tmp14; + + tmp0 = blk[5 * 8] - blk[3 * 8]; + tmp1 = blk[5 * 8] + blk[3 * 8]; + tmp2 = blk[1 * 8] * 2 - (blk[7 * 8] >> 2); + tmp3 = blk[1 * 8] * 2 + (blk[7 * 8] >> 2); + tmp4 = tmp3 - tmp1; + tmp5 = IDCTMUL(tmp0 + tmp2, FIX_1_847); + tmp6 = IDCTMUL(tmp2, FIX_1_082) - tmp5; + tmp7 = tmp5 - IDCTMUL(tmp0, FIX_2_613) * 2; + tmp8 = (tmp3 + tmp1) >> 1; + tmp9 = tmp7 * 2 - tmp8; + tmpA = IDCTMUL(tmp4, FIX_1_414) * 2 - tmp9; + tmpB = tmp6 * 2 + tmpA; + tmpC = blk[2 * 8] + (blk[6 * 8] >> 1) >> 1; + tmpD = blk[2 * 8] - (blk[6 * 8] >> 1); + tmpE = (blk[0 * 8] >> 1) - (blk[4 * 8] >> 1) + 0x2020; + tmpF = (blk[0 * 8] >> 1) + (blk[4 * 8] >> 1) + 0x2020; + + tmp10 = IDCTMUL(tmpD, FIX_1_414) * 2 - tmpC; + tmp11 = tmpE - tmp10; + tmp12 = tmpF - tmpC; + tmp13 = tmpE + tmp10; + tmp14 = tmpF + tmpC; + + blk[0 * 8] = (tmp14 + tmp8) >> 6; + blk[1 * 8] = (tmp13 + tmp9) >> 6; + blk[2 * 8] = (tmp11 + tmpA) >> 6; + blk[3 * 8] = (tmp12 - tmpB) >> 6; + blk[4 * 8] = (tmp12 + tmpB) >> 6; + blk[5 * 8] = (tmp11 - tmpA) >> 6; + blk[6 * 8] = (tmp13 - tmp9) >> 6; + blk[7 * 8] = (tmp14 - tmp8) >> 6; +} + +static void hq_idct_put(uint8_t *dst, int stride, int16_t *block) +{ + int i, j; + + for (i = 0; i < 8; i++) + idct_row(block + i * 8); + for (i = 0; i < 8; i++) + idct_col(block + i); + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) + dst[j] = av_clip_uint8(block[j + i * 8]); + dst += stride; + } +} + +av_cold void ff_hqdsp_init(HQDSPContext *c) +{ + c->idct_put = hq_idct_put; +} diff --git a/libavcodec/hq_hqadsp.h b/libavcodec/hq_hqadsp.h new file mode 100644 index 0000000..22b1e61 --- /dev/null +++ b/libavcodec/hq_hqadsp.h @@ -0,0 +1,38 @@ +/* + * Canopus HQ/HQA decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * HQ/HQA variant of AAN IDCT + * It differs from the standard AAN IDCT in precision and in the second stage. + */ + +#ifndef AVCODEC_HQ_HQADSP_H +#define AVCODEC_HQ_HQADSP_H + +#include + +typedef struct HQDSPContext { + void (*idct_put)(uint8_t *dst, int stride, int16_t *block); +} HQDSPContext; + +void ff_hqdsp_init(HQDSPContext *c); + +#endif /* AVCODEC_HQ_HQADSP_H */ diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c new file mode 100644 index 0000000..7411d3f --- /dev/null +++ b/libavcodec/hqx.c @@ -0,0 +1,544 @@ +/* + * Canopus HQX decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "canopus.h" +#include "get_bits.h" +#include "internal.h" + +#include "hqx.h" +#include "hqxdsp.h" + +/* HQX has four modes - 422, 444, 422alpha and 444alpha - all 12-bit */ +enum HQXFormat { + HQX_422 = 0, + HQX_444, + HQX_422A, + HQX_444A, +}; + +#define HQX_HEADER_SIZE 59 + +/* macroblock selects a group of 4 possible quants and + * a block can use any of those four quantisers + * one column is powers of 2, the other one is powers of 2 * 3, + * then there is the special one, powers of 2 * 5 */ +static const int hqx_quants[16][4] = { + { 0x1, 0x2, 0x4, 0x8 }, { 0x1, 0x3, 0x6, 0xC }, + { 0x2, 0x4, 0x8, 0x10 }, { 0x3, 0x6, 0xC, 0x18 }, + { 0x4, 0x8, 0x10, 0x20 }, { 0x6, 0xC, 0x18, 0x30 }, + { 0x8, 0x10, 0x20, 0x40 }, + { 0xA, 0x14, 0x28, 0x50 }, + { 0xC, 0x18, 0x30, 0x60 }, + { 0x10, 0x20, 0x40, 0x80 }, { 0x18, 0x30, 0x60, 0xC0 }, + { 0x20, 0x40, 0x80, 0x100 }, { 0x30, 0x60, 0xC0, 0x180 }, + { 0x40, 0x80, 0x100, 0x200 }, { 0x60, 0xC0, 0x180, 0x300 }, + { 0x80, 0x100, 0x200, 0x400 } +}; + +static const uint8_t hqx_quant_luma[64] = { + 16, 16, 16, 19, 19, 19, 42, 44, + 16, 16, 19, 19, 19, 38, 43, 45, + 16, 19, 19, 19, 40, 41, 45, 48, + 19, 19, 19, 40, 41, 42, 46, 49, + 19, 19, 40, 41, 42, 43, 48, 101, + 19, 38, 41, 42, 43, 44, 98, 104, + 42, 43, 45, 46, 48, 98, 109, 116, + 44, 45, 48, 49, 101, 104, 116, 123, +}; + +static const uint8_t hqx_quant_chroma[64] = { + 16, 16, 19, 25, 26, 26, 42, 44, + 16, 19, 25, 25, 26, 38, 43, 91, + 19, 25, 26, 27, 40, 41, 91, 96, + 25, 25, 27, 40, 41, 84, 93, 197, + 26, 26, 40, 41, 84, 86, 191, 203, + 26, 38, 41, 84, 86, 177, 197, 209, + 42, 43, 91, 93, 191, 197, 219, 232, + 44, 91, 96, 197, 203, 209, 232, 246, +}; + +static inline void put_blocks(HQXContext *ctx, int plane, + int x, int y, int ilace, + int16_t *block0, int16_t *block1, + const uint8_t *quant) +{ + int fields = ilace ? 2 : 1; + int lsize = ctx->pic->linesize[plane]; + uint8_t *p = ctx->pic->data[plane] + x * 2; + + ctx->hqxdsp.idct_put((uint16_t *)(p + y * lsize), + lsize * fields, block0, quant); + ctx->hqxdsp.idct_put((uint16_t *)(p + (y + (ilace ? 1 : 8)) * lsize), + lsize * fields, block1, quant); +} + +static inline void hqx_get_ac(GetBitContext *gb, const HQXAC *ac, + int *run, int *lev) +{ + int val; + + val = show_bits(gb, ac->lut_bits); + if (ac->lut[val].bits == -1) { + GetBitContext gb2 = *gb; + skip_bits(&gb2, ac->lut_bits); + val = ac->lut[val].lev + show_bits(&gb2, ac->extra_bits); + } + *run = ac->lut[val].run; + *lev = ac->lut[val].lev; + skip_bits(gb, ac->lut[val].bits); +} + +static int decode_block(GetBitContext *gb, VLC *vlc, + const int *quants, int dcb, + int16_t block[64], int *last_dc) +{ + int q, dc; + int ac_idx; + int run, lev, pos = 1; + + memset(block, 0, 64 * sizeof(*block)); + dc = get_vlc2(gb, vlc->table, HQX_DC_VLC_BITS, 2); + if (dc < 0) + return AVERROR_INVALIDDATA; + *last_dc += dc; + + block[0] = sign_extend(*last_dc << (12 - dcb), 12); + + q = quants[get_bits(gb, 2)]; + if (q >= 128) + ac_idx = HQX_AC_Q128; + else if (q >= 64) + ac_idx = HQX_AC_Q64; + else if (q >= 32) + ac_idx = HQX_AC_Q32; + else if (q >= 16) + ac_idx = HQX_AC_Q16; + else if (q >= 8) + ac_idx = HQX_AC_Q8; + else + ac_idx = HQX_AC_Q0; + + do { + hqx_get_ac(gb, &ff_hqx_ac[ac_idx], &run, &lev); + pos += run; + if (pos >= 64) + break; + block[ff_zigzag_direct[pos++]] = lev * q; + } while (pos < 64); + + return 0; +} + +static int hqx_decode_422(HQXContext *ctx, int slice_no, int x, int y) +{ + HQXSlice *slice = &ctx->slice[slice_no]; + GetBitContext *gb = &slice->gb; + const int *quants; + int flag; + int last_dc; + int i, ret; + + if (ctx->interlaced) + flag = get_bits1(gb); + else + flag = 0; + + quants = hqx_quants[get_bits(gb, 4)]; + + for (i = 0; i < 8; i++) { + int vlc_index = ctx->dcb - 9; + if (i == 0 || i == 4 || i == 6) + last_dc = 0; + ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, + ctx->dcb, slice->block[i], &last_dc); + if (ret < 0) + return ret; + } + + put_blocks(ctx, 0, x, y, flag, slice->block[0], slice->block[2], hqx_quant_luma); + put_blocks(ctx, 0, x + 8, y, flag, slice->block[1], slice->block[3], hqx_quant_luma); + put_blocks(ctx, 2, x >> 1, y, flag, slice->block[4], slice->block[5], hqx_quant_chroma); + put_blocks(ctx, 1, x >> 1, y, flag, slice->block[6], slice->block[7], hqx_quant_chroma); + + return 0; +} + +static int hqx_decode_422a(HQXContext *ctx, int slice_no, int x, int y) +{ + HQXSlice *slice = &ctx->slice[slice_no]; + GetBitContext *gb = &slice->gb; + const int *quants; + int flag = 0; + int last_dc; + int i, ret; + int cbp; + + cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); + + for (i = 0; i < 12; i++) + memset(slice->block[i], 0, sizeof(**slice->block) * 64); + for (i = 0; i < 12; i++) + slice->block[i][0] = -0x800; + if (cbp) { + if (ctx->interlaced) + flag = get_bits1(gb); + + quants = hqx_quants[get_bits(gb, 4)]; + + cbp |= cbp << 4; // alpha CBP + if (cbp & 0x3) // chroma CBP - top + cbp |= 0x500; + if (cbp & 0xC) // chroma CBP - bottom + cbp |= 0xA00; + for (i = 0; i < 12; i++) { + if (i == 0 || i == 4 || i == 8 || i == 10) + last_dc = 0; + if (cbp & (1 << i)) { + int vlc_index = ctx->dcb - 9; + ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, + ctx->dcb, slice->block[i], &last_dc); + if (ret < 0) + return ret; + } + } + } + + put_blocks(ctx, 3, x, y, flag, slice->block[ 0], slice->block[ 2], hqx_quant_luma); + put_blocks(ctx, 3, x + 8, y, flag, slice->block[ 1], slice->block[ 3], hqx_quant_luma); + put_blocks(ctx, 0, x, y, flag, slice->block[ 4], slice->block[ 6], hqx_quant_luma); + put_blocks(ctx, 0, x + 8, y, flag, slice->block[ 5], slice->block[ 7], hqx_quant_luma); + put_blocks(ctx, 2, x >> 1, y, flag, slice->block[ 8], slice->block[ 9], hqx_quant_chroma); + put_blocks(ctx, 1, x >> 1, y, flag, slice->block[10], slice->block[11], hqx_quant_chroma); + + return 0; +} + +static int hqx_decode_444(HQXContext *ctx, int slice_no, int x, int y) +{ + HQXSlice *slice = &ctx->slice[slice_no]; + GetBitContext *gb = &slice->gb; + const int *quants; + int flag; + int last_dc; + int i, ret; + + if (ctx->interlaced) + flag = get_bits1(gb); + else + flag = 0; + + quants = hqx_quants[get_bits(gb, 4)]; + + for (i = 0; i < 12; i++) { + int vlc_index = ctx->dcb - 9; + if (i == 0 || i == 4 || i == 8) + last_dc = 0; + ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, + ctx->dcb, slice->block[i], &last_dc); + if (ret < 0) + return ret; + } + + put_blocks(ctx, 0, x, y, flag, slice->block[0], slice->block[ 2], hqx_quant_luma); + put_blocks(ctx, 0, x + 8, y, flag, slice->block[1], slice->block[ 3], hqx_quant_luma); + put_blocks(ctx, 2, x, y, flag, slice->block[4], slice->block[ 6], hqx_quant_chroma); + put_blocks(ctx, 2, x + 8, y, flag, slice->block[5], slice->block[ 7], hqx_quant_chroma); + put_blocks(ctx, 1, x, y, flag, slice->block[8], slice->block[10], hqx_quant_chroma); + put_blocks(ctx, 1, x + 8, y, flag, slice->block[9], slice->block[11], hqx_quant_chroma); + + return 0; +} + +static int hqx_decode_444a(HQXContext *ctx, int slice_no, int x, int y) +{ + HQXSlice *slice = &ctx->slice[slice_no]; + GetBitContext *gb = &slice->gb; + const int *quants; + int flag = 0; + int last_dc; + int i, ret; + int cbp; + + cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); + + for (i = 0; i < 16; i++) + memset(slice->block[i], 0, sizeof(**slice->block) * 64); + for (i = 0; i < 16; i++) + slice->block[i][0] = -0x800; + if (cbp) { + if (ctx->interlaced) + flag = get_bits1(gb); + + quants = hqx_quants[get_bits(gb, 4)]; + + cbp |= cbp << 4; // alpha CBP + cbp |= cbp << 8; // chroma CBP + for (i = 0; i < 16; i++) { + if (i == 0 || i == 4 || i == 8 || i == 12) + last_dc = 0; + if (cbp & (1 << i)) { + int vlc_index = ctx->dcb - 9; + ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants, + ctx->dcb, slice->block[i], &last_dc); + if (ret < 0) + return ret; + } + } + } + + put_blocks(ctx, 3, x, y, flag, slice->block[ 0], slice->block[ 2], hqx_quant_luma); + put_blocks(ctx, 3, x + 8, y, flag, slice->block[ 1], slice->block[ 3], hqx_quant_luma); + put_blocks(ctx, 0, x, y, flag, slice->block[ 4], slice->block[ 6], hqx_quant_luma); + put_blocks(ctx, 0, x + 8, y, flag, slice->block[ 5], slice->block[ 7], hqx_quant_luma); + put_blocks(ctx, 2, x, y, flag, slice->block[ 8], slice->block[10], hqx_quant_chroma); + put_blocks(ctx, 2, x + 8, y, flag, slice->block[ 9], slice->block[11], hqx_quant_chroma); + put_blocks(ctx, 1, x, y, flag, slice->block[12], slice->block[14], hqx_quant_chroma); + put_blocks(ctx, 1, x + 8, y, flag, slice->block[13], slice->block[15], hqx_quant_chroma); + + return 0; +} + +static const int shuffle_16[16] = { + 0, 5, 11, 14, 2, 7, 9, 13, 1, 4, 10, 15, 3, 6, 8, 12 +}; + +static int decode_slice(HQXContext *ctx, int slice_no) +{ + int mb_w = (ctx->width + 15) >> 4; + int mb_h = (ctx->height + 15) >> 4; + int grp_w = (mb_w + 4) / 5; + int grp_h = (mb_h + 4) / 5; + int grp_h_edge = grp_w * (mb_w / grp_w); + int grp_v_edge = grp_h * (mb_h / grp_h); + int grp_v_rest = mb_w - grp_h_edge; + int grp_h_rest = mb_h - grp_v_edge; + int num_mbs = mb_w * mb_h; + int num_tiles = (num_mbs + 479) / 480; + int std_tile_blocks = num_mbs / (16 * num_tiles); + int g_tile = slice_no * num_tiles; + int blk_addr, loc_addr, mb_x, mb_y, pos, loc_row, i; + int tile_blocks, tile_limit, tile_no; + + for (tile_no = 0; tile_no < num_tiles; tile_no++, g_tile++) { + tile_blocks = std_tile_blocks; + tile_limit = -1; + if (g_tile < num_mbs - std_tile_blocks * 16 * num_tiles) { + tile_limit = num_mbs / (16 * num_tiles); + tile_blocks++; + } + for (i = 0; i < tile_blocks; i++) { + if (i == tile_limit) + blk_addr = g_tile + 16 * num_tiles * i; + else + blk_addr = tile_no + 16 * num_tiles * i + + num_tiles * shuffle_16[(i + slice_no) & 0xF]; + loc_row = grp_h * (blk_addr / (grp_h * mb_w)); + loc_addr = blk_addr % (grp_h * mb_w); + if (loc_row >= grp_v_edge) { + mb_x = grp_w * (loc_addr / (grp_h_rest * grp_w)); + pos = loc_addr % (grp_h_rest * grp_w); + } else { + mb_x = grp_w * (loc_addr / (grp_h * grp_w)); + pos = loc_addr % (grp_h * grp_w); + } + if (mb_x >= grp_h_edge) { + mb_x += pos % grp_v_rest; + mb_y = loc_row + (pos / grp_v_rest); + } else { + mb_x += pos % grp_w; + mb_y = loc_row + (pos / grp_w); + } + ctx->decode_func(ctx, slice_no, mb_x * 16, mb_y * 16); + } + } + + return 0; +} + +static int decode_slice_thread(AVCodecContext *avctx, void *arg, + int slice_no, int threadnr) +{ + HQXContext *ctx = avctx->priv_data; + uint32_t *slice_off = ctx->slice_off; + int ret; + + if (slice_off[slice_no] < HQX_HEADER_SIZE || + slice_off[slice_no] >= slice_off[slice_no + 1] || + slice_off[slice_no + 1] > ctx->data_size) { + av_log(avctx, AV_LOG_ERROR, "Invalid slice size %d.\n", ctx->data_size); + return AVERROR_INVALIDDATA; + } + + ret = init_get_bits8(&ctx->slice[slice_no].gb, + ctx->src + slice_off[slice_no], + slice_off[slice_no + 1] - slice_off[slice_no]); + if (ret < 0) + return ret; + + return decode_slice(ctx, slice_no); +} + +static int hqx_decode_frame(AVCodecContext *avctx, void *data, + int *got_picture_ptr, AVPacket *avpkt) +{ + HQXContext *ctx = avctx->priv_data; + uint8_t *src = avpkt->data; + uint32_t info_tag; + int data_start; + int i, ret; + + if (avpkt->size < 4 + 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small %d.\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + info_tag = AV_RL32(src); + if (info_tag == MKTAG('I', 'N', 'F', 'O')) { + unsigned info_offset = AV_RL32(src + 4); + if (info_offset > INT_MAX || info_offset + 8 > avpkt->size) { + av_log(avctx, AV_LOG_ERROR, + "Invalid INFO header offset: 0x%08"PRIX32" is too large.\n", + info_offset); + return AVERROR_INVALIDDATA; + } + ff_canopus_parse_info_tag(avctx, src + 8, info_offset); + + info_offset += 8; + src += info_offset; + } + + data_start = src - avpkt->data; + ctx->data_size = avpkt->size - data_start; + ctx->src = src; + ctx->pic = data; + + if (ctx->data_size < HQX_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Frame too small.\n"); + return AVERROR_INVALIDDATA; + } + + if (src[0] != 'H' || src[1] != 'Q') { + av_log(avctx, AV_LOG_ERROR, "Not an HQX frame.\n"); + return AVERROR_INVALIDDATA; + } + ctx->interlaced = !(src[2] & 0x80); + ctx->format = src[2] & 7; + ctx->dcb = (src[3] & 3) + 8; + ctx->width = AV_RB16(src + 4); + ctx->height = AV_RB16(src + 6); + for (i = 0; i < 17; i++) + ctx->slice_off[i] = AV_RB24(src + 8 + i * 3); + + if (ctx->dcb == 8) { + av_log(avctx, AV_LOG_ERROR, "Invalid DC precision %d.\n", ctx->dcb); + return AVERROR_INVALIDDATA; + } + ret = av_image_check_size(ctx->width, ctx->height, 0, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid stored dimenstions %dx%d.\n", + ctx->width, ctx->height); + return AVERROR_INVALIDDATA; + } + + avctx->coded_width = FFALIGN(ctx->width, 16); + avctx->coded_height = FFALIGN(ctx->height, 16); + avctx->width = ctx->width; + avctx->height = ctx->height; + avctx->bits_per_raw_sample = 10; + + switch (ctx->format) { + case HQX_422: + avctx->pix_fmt = AV_PIX_FMT_YUV422P16; + ctx->decode_func = hqx_decode_422; + break; + case HQX_444: + avctx->pix_fmt = AV_PIX_FMT_YUV444P16; + ctx->decode_func = hqx_decode_444; + break; + case HQX_422A: + avctx->pix_fmt = AV_PIX_FMT_YUVA422P16; + ctx->decode_func = hqx_decode_422a; + break; + case HQX_444A: + avctx->pix_fmt = AV_PIX_FMT_YUVA444P16; + ctx->decode_func = hqx_decode_444a; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid format: %d.\n", ctx->format); + return AVERROR_INVALIDDATA; + } + + ret = ff_get_buffer(avctx, ctx->pic, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); + return ret; + } + + avctx->execute2(avctx, decode_slice_thread, NULL, NULL, 16); + + ctx->pic->key_frame = 1; + ctx->pic->pict_type = AV_PICTURE_TYPE_I; + + *got_picture_ptr = 1; + + return avpkt->size; +} + +static av_cold int hqx_decode_close(AVCodecContext *avctx) +{ + int i; + HQXContext *ctx = avctx->priv_data; + + ff_free_vlc(&ctx->cbp_vlc); + for (i = 0; i < 3; i++) { + ff_free_vlc(&ctx->dc_vlc[i]); + } + + return 0; +} + +static av_cold int hqx_decode_init(AVCodecContext *avctx) +{ + HQXContext *ctx = avctx->priv_data; + + ff_hqxdsp_init(&ctx->hqxdsp); + + return ff_hqx_init_vlcs(ctx); +} + +AVCodec ff_hqx_decoder = { + .name = "hqx", + .long_name = NULL_IF_CONFIG_SMALL("Canopus HQX"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HQX, + .priv_data_size = sizeof(HQXContext), + .init = hqx_decode_init, + .decode = hqx_decode_frame, + .close = hqx_decode_close, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/hqx.h b/libavcodec/hqx.h new file mode 100644 index 0000000..7f32971 --- /dev/null +++ b/libavcodec/hqx.h @@ -0,0 +1,86 @@ +/* + * Canopus HQX decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HQX_H +#define AVCODEC_HQX_H + +#include + +#include "libavutil/frame.h" +#include "libavutil/mem.h" +#include "get_bits.h" +#include "hqxdsp.h" + +enum HQXACMode { + HQX_AC_Q0 = 0, + HQX_AC_Q8, + HQX_AC_Q16, + HQX_AC_Q32, + HQX_AC_Q64, + HQX_AC_Q128, + NUM_HQX_AC +}; + +typedef struct HQXLUT { + int16_t lev; + uint8_t run; + int8_t bits; +} HQXLUT; + +typedef struct HQXAC { + int lut_bits, extra_bits; + const HQXLUT *lut; +} HQXAC; + +struct HQXContext; + +typedef int (*mb_decode_func)(struct HQXContext *ctx, + int slice_no, int x, int y); + +typedef struct HQXSlice { + GetBitContext gb; + DECLARE_ALIGNED(16, int16_t, block)[16][64]; +} HQXSlice; + +typedef struct HQXContext { + HQXDSPContext hqxdsp; + HQXSlice slice[16]; + + AVFrame *pic; + mb_decode_func decode_func; + + int format, dcb, width, height; + int interlaced; + + uint8_t *src; + unsigned int data_size; + uint32_t slice_off[17]; + + VLC cbp_vlc; + VLC dc_vlc[3]; +} HQXContext; + +#define HQX_DC_VLC_BITS 9 + +extern const HQXAC ff_hqx_ac[NUM_HQX_AC]; + +int ff_hqx_init_vlcs(HQXContext *ctx); + +#endif /* AVCODEC_HQX_H */ diff --git a/libavcodec/hqxdsp.c b/libavcodec/hqxdsp.c new file mode 100644 index 0000000..2a02299 --- /dev/null +++ b/libavcodec/hqxdsp.c @@ -0,0 +1,131 @@ +/* + * HQX DSP routines + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" + +#include "hqxdsp.h" + +static inline void idct_col(int16_t *blk, const uint8_t *quant) +{ + int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB, tC, tD, tE, tF; + int t10, t11, t12, t13; + int s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = (int) blk[0 * 8] * quant[0 * 8]; + s1 = (int) blk[1 * 8] * quant[1 * 8]; + s2 = (int) blk[2 * 8] * quant[2 * 8]; + s3 = (int) blk[3 * 8] * quant[3 * 8]; + s4 = (int) blk[4 * 8] * quant[4 * 8]; + s5 = (int) blk[5 * 8] * quant[5 * 8]; + s6 = (int) blk[6 * 8] * quant[6 * 8]; + s7 = (int) blk[7 * 8] * quant[7 * 8]; + + t0 = (s3 * 19266 + s5 * 12873) >> 15; + t1 = (s5 * 19266 - s3 * 12873) >> 15; + t2 = ((s7 * 4520 + s1 * 22725) >> 15) - t0; + t3 = ((s1 * 4520 - s7 * 22725) >> 15) - t1; + t4 = t0 * 2 + t2; + t5 = t1 * 2 + t3; + t6 = t2 - t3; + t7 = t3 * 2 + t6; + t8 = (t6 * 11585) >> 14; + t9 = (t7 * 11585) >> 14; + tA = (s2 * 8867 - s6 * 21407) >> 14; + tB = (s6 * 8867 + s2 * 21407) >> 14; + tC = (s0 >> 1) - (s4 >> 1); + tD = (s4 >> 1) * 2 + tC; + tE = tC - (tA >> 1); + tF = tD - (tB >> 1); + t10 = tF - t5; + t11 = tE - t8; + t12 = tE + (tA >> 1) * 2 - t9; + t13 = tF + (tB >> 1) * 2 - t4; + + blk[0 * 8] = t13 + t4 * 2; + blk[1 * 8] = t12 + t9 * 2; + blk[2 * 8] = t11 + t8 * 2; + blk[3 * 8] = t10 + t5 * 2; + blk[4 * 8] = t10; + blk[5 * 8] = t11; + blk[6 * 8] = t12; + blk[7 * 8] = t13; +} + +static inline void idct_row(int16_t *blk) +{ + int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB, tC, tD, tE, tF; + int t10, t11, t12, t13; + + t0 = (blk[3] * 19266 + blk[5] * 12873) >> 14; + t1 = (blk[5] * 19266 - blk[3] * 12873) >> 14; + t2 = ((blk[7] * 4520 + blk[1] * 22725) >> 14) - t0; + t3 = ((blk[1] * 4520 - blk[7] * 22725) >> 14) - t1; + t4 = t0 * 2 + t2; + t5 = t1 * 2 + t3; + t6 = t2 - t3; + t7 = t3 * 2 + t6; + t8 = (t6 * 11585) >> 14; + t9 = (t7 * 11585) >> 14; + tA = (blk[2] * 8867 - blk[6] * 21407) >> 14; + tB = (blk[6] * 8867 + blk[2] * 21407) >> 14; + tC = blk[0] - blk[4]; + tD = blk[4] * 2 + tC; + tE = tC - tA; + tF = tD - tB; + t10 = tF - t5; + t11 = tE - t8; + t12 = tE + tA * 2 - t9; + t13 = tF + tB * 2 - t4; + + blk[0] = (t13 + t4 * 2 + 4) >> 3; + blk[1] = (t12 + t9 * 2 + 4) >> 3; + blk[2] = (t11 + t8 * 2 + 4) >> 3; + blk[3] = (t10 + t5 * 2 + 4) >> 3; + blk[4] = (t10 + 4) >> 3; + blk[5] = (t11 + 4) >> 3; + blk[6] = (t12 + 4) >> 3; + blk[7] = (t13 + 4) >> 3; +} + +static void hqx_idct_put(uint16_t *dst, ptrdiff_t stride, + int16_t *block, const uint8_t *quant) +{ + int i, j; + + for (i = 0; i < 8; i++) + idct_col(block + i, quant + i); + for (i = 0; i < 8; i++) + idct_row(block + i * 8); + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + int v = av_clip(block[j + i * 8] + 0x800, 0, 0xFFF); + dst[j] = (v << 4) | (v >> 8); + } + dst += stride >> 1; + } +} + +av_cold void ff_hqxdsp_init(HQXDSPContext *c) +{ + c->idct_put = hqx_idct_put; +} diff --git a/libavcodec/hqxdsp.h b/libavcodec/hqxdsp.h new file mode 100644 index 0000000..2cd2a8e --- /dev/null +++ b/libavcodec/hqxdsp.h @@ -0,0 +1,39 @@ +/* + * HQX DSP routines + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * HQX DSP routines + */ + +#ifndef AVCODEC_HQXDSP_H +#define AVCODEC_HQXDSP_H + +#include +#include + +typedef struct HQXDSPContext { + void (*idct_put)(uint16_t *dst, ptrdiff_t stride, + int16_t *block, const uint8_t *quant); +} HQXDSPContext; + +void ff_hqxdsp_init(HQXDSPContext *c); + +#endif /* AVCODEC_HQXDSP_H */ diff --git a/libavcodec/hqxvlc.c b/libavcodec/hqxvlc.c new file mode 100644 index 0000000..d185e86 --- /dev/null +++ b/libavcodec/hqxvlc.c @@ -0,0 +1,2163 @@ +/* + * Canopus HQX decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hqx.h" + +static const uint8_t cbp_vlc_bits[16] = { + 0x04, 0x1C, 0x1D, 0x09, 0x1E, 0x0B, 0x1B, 0x08, + 0x1F, 0x1A, 0x0C, 0x07, 0x0A, 0x06, 0x05, 0x00, +}; + +static const uint8_t cbp_vlc_lens[16] = { + 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2, +}; + +static const uint16_t dc9_vlc_bits[512] = { + 0x0010, 0x0008, 0x0022, 0x0024, 0x0026, 0x0028, 0x002A, 0x002C, + 0x002E, 0x0030, 0x0032, 0x0034, 0x0074, 0x0076, 0x0078, 0x007A, + 0x007C, 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, + 0x000E, 0x0050, 0x0052, 0x0054, 0x0056, 0x0058, 0x005A, 0x005C, + 0x005E, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002A, 0x002C, + 0x002E, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038, 0x003A, 0x003C, + 0x003E, 0x00C0, 0x00C2, 0x00C4, 0x00C6, 0x00C8, 0x00CA, 0x00CC, + 0x00CE, 0x00D0, 0x00D2, 0x00D4, 0x00D6, 0x00D8, 0x00DA, 0x00DC, + 0x00DE, 0x01C0, 0x01C2, 0x01C4, 0x01C6, 0x01C8, 0x01CA, 0x01CC, + 0x01CE, 0x01D0, 0x01D2, 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, + 0x01DE, 0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E8, 0x01EA, 0x01EC, + 0x01EE, 0x01F0, 0x01F2, 0x01F4, 0x01F6, 0x01F8, 0x01FA, 0x01FC, + 0x01FE, 0x06C0, 0x06C2, 0x06C4, 0x06C6, 0x06C8, 0x06CA, 0x06CC, + 0x06CE, 0x06D0, 0x06D2, 0x06D4, 0x06D6, 0x06D8, 0x06DA, 0x06DC, + 0x06DE, 0x06E0, 0x06E2, 0x06E4, 0x06E6, 0x06E8, 0x06EA, 0x06EC, + 0x06EE, 0x06F0, 0x06F2, 0x06F4, 0x06F6, 0x06F8, 0x06FA, 0x06FC, + 0x06FE, 0x0E00, 0x0E02, 0x0E04, 0x0E06, 0x0E08, 0x0E0A, 0x0E0C, + 0x0E0E, 0x0E10, 0x0E12, 0x0E14, 0x0E16, 0x0E18, 0x0E1A, 0x0E1C, + 0x0E1E, 0x0E20, 0x0E22, 0x0E24, 0x0E26, 0x0E28, 0x0E2A, 0x0E2C, + 0x0E2E, 0x0E30, 0x0E32, 0x0E34, 0x0E36, 0x0E38, 0x0E3A, 0x0E3C, + 0x0E3E, 0x0E40, 0x0E42, 0x0E44, 0x0E46, 0x0E48, 0x0E4A, 0x0E4C, + 0x0E4E, 0x0E50, 0x0E52, 0x0E54, 0x0E56, 0x0E58, 0x0E5A, 0x0E5C, + 0x0E5E, 0x0E60, 0x0E62, 0x0E64, 0x0E66, 0x0E68, 0x0E6A, 0x0E6C, + 0x0E6E, 0x0E70, 0x0E72, 0x0E74, 0x0E76, 0x0E78, 0x0E7A, 0x0E7C, + 0x0E7E, 0x1F80, 0x1F82, 0x1F84, 0x1F86, 0x1F88, 0x1F8A, 0x1F8C, + 0x1F8E, 0x1F90, 0x1F92, 0x1F94, 0x1F96, 0x1F98, 0x1F9A, 0x1F9C, + 0x1F9E, 0x1FA0, 0x1FA2, 0x1FA4, 0x1FA6, 0x1FA8, 0x1FAA, 0x1FAC, + 0x1FAE, 0x1FB0, 0x1FB2, 0x1FB4, 0x1FB6, 0x1FB8, 0x1FBA, 0x1FBC, + 0x1FBE, 0x1FC0, 0x1FC2, 0x1FC4, 0x1FC6, 0x1FC8, 0x1FCA, 0x1FCC, + 0x1FCE, 0x1FD0, 0x1FD2, 0x1FD4, 0x1FD6, 0x1FD8, 0x1FDA, 0x1FDC, + 0x1FDE, 0x1FE0, 0x1FE2, 0x1FE4, 0x1FE6, 0x1FE8, 0x1FEA, 0x1FEC, + 0x1FEE, 0x1FF0, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FF8, 0x1FFA, 0x1FFC, + 0x0FFF, 0x1FFD, 0x1FFB, 0x1FF9, 0x1FF7, 0x1FF5, 0x1FF3, 0x1FF1, + 0x1FEF, 0x1FED, 0x1FEB, 0x1FE9, 0x1FE7, 0x1FE5, 0x1FE3, 0x1FE1, + 0x1FDF, 0x1FDD, 0x1FDB, 0x1FD9, 0x1FD7, 0x1FD5, 0x1FD3, 0x1FD1, + 0x1FCF, 0x1FCD, 0x1FCB, 0x1FC9, 0x1FC7, 0x1FC5, 0x1FC3, 0x1FC1, + 0x1FBF, 0x1FBD, 0x1FBB, 0x1FB9, 0x1FB7, 0x1FB5, 0x1FB3, 0x1FB1, + 0x1FAF, 0x1FAD, 0x1FAB, 0x1FA9, 0x1FA7, 0x1FA5, 0x1FA3, 0x1FA1, + 0x1F9F, 0x1F9D, 0x1F9B, 0x1F99, 0x1F97, 0x1F95, 0x1F93, 0x1F91, + 0x1F8F, 0x1F8D, 0x1F8B, 0x1F89, 0x1F87, 0x1F85, 0x1F83, 0x1F81, + 0x0E7F, 0x0E7D, 0x0E7B, 0x0E79, 0x0E77, 0x0E75, 0x0E73, 0x0E71, + 0x0E6F, 0x0E6D, 0x0E6B, 0x0E69, 0x0E67, 0x0E65, 0x0E63, 0x0E61, + 0x0E5F, 0x0E5D, 0x0E5B, 0x0E59, 0x0E57, 0x0E55, 0x0E53, 0x0E51, + 0x0E4F, 0x0E4D, 0x0E4B, 0x0E49, 0x0E47, 0x0E45, 0x0E43, 0x0E41, + 0x0E3F, 0x0E3D, 0x0E3B, 0x0E39, 0x0E37, 0x0E35, 0x0E33, 0x0E31, + 0x0E2F, 0x0E2D, 0x0E2B, 0x0E29, 0x0E27, 0x0E25, 0x0E23, 0x0E21, + 0x0E1F, 0x0E1D, 0x0E1B, 0x0E19, 0x0E17, 0x0E15, 0x0E13, 0x0E11, + 0x0E0F, 0x0E0D, 0x0E0B, 0x0E09, 0x0E07, 0x0E05, 0x0E03, 0x0E01, + 0x06FF, 0x06FD, 0x06FB, 0x06F9, 0x06F7, 0x06F5, 0x06F3, 0x06F1, + 0x06EF, 0x06ED, 0x06EB, 0x06E9, 0x06E7, 0x06E5, 0x06E3, 0x06E1, + 0x06DF, 0x06DD, 0x06DB, 0x06D9, 0x06D7, 0x06D5, 0x06D3, 0x06D1, + 0x06CF, 0x06CD, 0x06CB, 0x06C9, 0x06C7, 0x06C5, 0x06C3, 0x06C1, + 0x01FF, 0x01FD, 0x01FB, 0x01F9, 0x01F7, 0x01F5, 0x01F3, 0x01F1, + 0x01EF, 0x01ED, 0x01EB, 0x01E9, 0x01E7, 0x01E5, 0x01E3, 0x01E1, + 0x01DF, 0x01DD, 0x01DB, 0x01D9, 0x01D7, 0x01D5, 0x01D3, 0x01D1, + 0x01CF, 0x01CD, 0x01CB, 0x01C9, 0x01C7, 0x01C5, 0x01C3, 0x01C1, + 0x00DF, 0x00DD, 0x00DB, 0x00D9, 0x00D7, 0x00D5, 0x00D3, 0x00D1, + 0x00CF, 0x00CD, 0x00CB, 0x00C9, 0x00C7, 0x00C5, 0x00C3, 0x00C1, + 0x003F, 0x003D, 0x003B, 0x0039, 0x0037, 0x0035, 0x0033, 0x0031, + 0x002F, 0x002D, 0x002B, 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, + 0x005F, 0x005D, 0x005B, 0x0059, 0x0057, 0x0055, 0x0053, 0x0051, + 0x000F, 0x000D, 0x000B, 0x0009, 0x0007, 0x0005, 0x0003, 0x0001, + 0x007D, 0x007B, 0x0079, 0x0077, 0x0075, 0x0035, 0x0033, 0x0031, + 0x002F, 0x002D, 0x002B, 0x0029, 0x0027, 0x0025, 0x0023, 0x0009, +}; + +static const uint8_t dc9_vlc_lens[512] = { + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 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, 10, 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, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 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, + 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, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 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, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, +}; + +static const uint16_t dc10_vlc_bits[1024] = { + 0x0014, 0x002A, 0x002C, 0x002E, 0x0064, 0x0066, 0x0068, 0x006A, + 0x006C, 0x006E, 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007A, + 0x007C, 0x0040, 0x0042, 0x0044, 0x0046, 0x0048, 0x004A, 0x004C, + 0x004E, 0x0050, 0x0052, 0x0054, 0x0056, 0x0058, 0x005A, 0x005C, + 0x005E, 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, + 0x000E, 0x0010, 0x0012, 0x0014, 0x0016, 0x0018, 0x001A, 0x001C, + 0x001E, 0x00C0, 0x00C2, 0x00C4, 0x00C6, 0x00C8, 0x00CA, 0x00CC, + 0x00CE, 0x00D0, 0x00D2, 0x00D4, 0x00D6, 0x00D8, 0x00DA, 0x00DC, + 0x00DE, 0x0040, 0x0042, 0x0044, 0x0046, 0x0048, 0x004A, 0x004C, + 0x004E, 0x0050, 0x0052, 0x0054, 0x0056, 0x0058, 0x005A, 0x005C, + 0x005E, 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006A, 0x006C, + 0x006E, 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007A, 0x007C, + 0x007E, 0x01C0, 0x01C2, 0x01C4, 0x01C6, 0x01C8, 0x01CA, 0x01CC, + 0x01CE, 0x01D0, 0x01D2, 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, + 0x01DE, 0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E8, 0x01EA, 0x01EC, + 0x01EE, 0x01F0, 0x01F2, 0x01F4, 0x01F6, 0x01F8, 0x01FA, 0x01FC, + 0x01FE, 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, + 0x040E, 0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, + 0x041E, 0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, + 0x042E, 0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, + 0x043E, 0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, + 0x044E, 0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, + 0x045E, 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, + 0x046E, 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x047C, + 0x047E, 0x0C00, 0x0C02, 0x0C04, 0x0C06, 0x0C08, 0x0C0A, 0x0C0C, + 0x0C0E, 0x0C10, 0x0C12, 0x0C14, 0x0C16, 0x0C18, 0x0C1A, 0x0C1C, + 0x0C1E, 0x0C20, 0x0C22, 0x0C24, 0x0C26, 0x0C28, 0x0C2A, 0x0C2C, + 0x0C2E, 0x0C30, 0x0C32, 0x0C34, 0x0C36, 0x0C38, 0x0C3A, 0x0C3C, + 0x0C3E, 0x0C40, 0x0C42, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4C, + 0x0C4E, 0x0C50, 0x0C52, 0x0C54, 0x0C56, 0x0C58, 0x0C5A, 0x0C5C, + 0x0C5E, 0x0C60, 0x0C62, 0x0C64, 0x0C66, 0x0C68, 0x0C6A, 0x0C6C, + 0x0C6E, 0x0C70, 0x0C72, 0x0C74, 0x0C76, 0x0C78, 0x0C7A, 0x0C7C, + 0x0C7E, 0x0900, 0x0902, 0x0904, 0x0906, 0x0908, 0x090A, 0x090C, + 0x090E, 0x0910, 0x0912, 0x0914, 0x0916, 0x0918, 0x091A, 0x091C, + 0x091E, 0x0920, 0x0922, 0x0924, 0x0926, 0x0928, 0x092A, 0x092C, + 0x092E, 0x0930, 0x0932, 0x0934, 0x0936, 0x0938, 0x093A, 0x093C, + 0x093E, 0x0940, 0x0942, 0x0944, 0x0946, 0x0948, 0x094A, 0x094C, + 0x094E, 0x0950, 0x0952, 0x0954, 0x0956, 0x0958, 0x095A, 0x095C, + 0x095E, 0x0960, 0x0962, 0x0964, 0x0966, 0x0968, 0x096A, 0x096C, + 0x096E, 0x0970, 0x0972, 0x0974, 0x0976, 0x0978, 0x097A, 0x097C, + 0x097E, 0x0980, 0x0982, 0x0984, 0x0986, 0x0988, 0x098A, 0x098C, + 0x098E, 0x0990, 0x0992, 0x0994, 0x0996, 0x0998, 0x099A, 0x099C, + 0x099E, 0x09A0, 0x09A2, 0x09A4, 0x09A6, 0x09A8, 0x09AA, 0x09AC, + 0x09AE, 0x09B0, 0x09B2, 0x09B4, 0x09B6, 0x09B8, 0x09BA, 0x09BC, + 0x09BE, 0x09C0, 0x09C2, 0x09C4, 0x09C6, 0x09C8, 0x09CA, 0x09CC, + 0x09CE, 0x09D0, 0x09D2, 0x09D4, 0x09D6, 0x09D8, 0x09DA, 0x09DC, + 0x09DE, 0x09E0, 0x09E2, 0x09E4, 0x09E6, 0x09E8, 0x09EA, 0x09EC, + 0x09EE, 0x09F0, 0x09F2, 0x09F4, 0x09F6, 0x09F8, 0x09FA, 0x09FC, + 0x09FE, 0x3F00, 0x3F02, 0x3F04, 0x3F06, 0x3F08, 0x3F0A, 0x3F0C, + 0x3F0E, 0x3F10, 0x3F12, 0x3F14, 0x3F16, 0x3F18, 0x3F1A, 0x3F1C, + 0x3F1E, 0x3F20, 0x3F22, 0x3F24, 0x3F26, 0x3F28, 0x3F2A, 0x3F2C, + 0x3F2E, 0x3F30, 0x3F32, 0x3F34, 0x3F36, 0x3F38, 0x3F3A, 0x3F3C, + 0x3F3E, 0x3F40, 0x3F42, 0x3F44, 0x3F46, 0x3F48, 0x3F4A, 0x3F4C, + 0x3F4E, 0x3F50, 0x3F52, 0x3F54, 0x3F56, 0x3F58, 0x3F5A, 0x3F5C, + 0x3F5E, 0x3F60, 0x3F62, 0x3F64, 0x3F66, 0x3F68, 0x3F6A, 0x3F6C, + 0x3F6E, 0x3F70, 0x3F72, 0x3F74, 0x3F76, 0x3F78, 0x3F7A, 0x3F7C, + 0x3F7E, 0x3F80, 0x3F82, 0x3F84, 0x3F86, 0x3F88, 0x3F8A, 0x3F8C, + 0x3F8E, 0x3F90, 0x3F92, 0x3F94, 0x3F96, 0x3F98, 0x3F9A, 0x3F9C, + 0x3F9E, 0x3FA0, 0x3FA2, 0x3FA4, 0x3FA6, 0x3FA8, 0x3FAA, 0x3FAC, + 0x3FAE, 0x3FB0, 0x3FB2, 0x3FB4, 0x3FB6, 0x3FB8, 0x3FBA, 0x3FBC, + 0x3FBE, 0x3FC0, 0x3FC2, 0x3FC4, 0x3FC6, 0x3FC8, 0x3FCA, 0x3FCC, + 0x3FCE, 0x3FD0, 0x3FD2, 0x3FD4, 0x3FD6, 0x3FD8, 0x3FDA, 0x3FDC, + 0x3FDE, 0x3FE0, 0x3FE2, 0x3FE4, 0x3FE6, 0x3FE8, 0x3FEA, 0x3FEC, + 0x3FEE, 0x3FF0, 0x3FF2, 0x3FF4, 0x3FF6, 0x3FF8, 0x3FFA, 0x3FFC, + 0x1FFF, 0x3FFD, 0x3FFB, 0x3FF9, 0x3FF7, 0x3FF5, 0x3FF3, 0x3FF1, + 0x3FEF, 0x3FED, 0x3FEB, 0x3FE9, 0x3FE7, 0x3FE5, 0x3FE3, 0x3FE1, + 0x3FDF, 0x3FDD, 0x3FDB, 0x3FD9, 0x3FD7, 0x3FD5, 0x3FD3, 0x3FD1, + 0x3FCF, 0x3FCD, 0x3FCB, 0x3FC9, 0x3FC7, 0x3FC5, 0x3FC3, 0x3FC1, + 0x3FBF, 0x3FBD, 0x3FBB, 0x3FB9, 0x3FB7, 0x3FB5, 0x3FB3, 0x3FB1, + 0x3FAF, 0x3FAD, 0x3FAB, 0x3FA9, 0x3FA7, 0x3FA5, 0x3FA3, 0x3FA1, + 0x3F9F, 0x3F9D, 0x3F9B, 0x3F99, 0x3F97, 0x3F95, 0x3F93, 0x3F91, + 0x3F8F, 0x3F8D, 0x3F8B, 0x3F89, 0x3F87, 0x3F85, 0x3F83, 0x3F81, + 0x3F7F, 0x3F7D, 0x3F7B, 0x3F79, 0x3F77, 0x3F75, 0x3F73, 0x3F71, + 0x3F6F, 0x3F6D, 0x3F6B, 0x3F69, 0x3F67, 0x3F65, 0x3F63, 0x3F61, + 0x3F5F, 0x3F5D, 0x3F5B, 0x3F59, 0x3F57, 0x3F55, 0x3F53, 0x3F51, + 0x3F4F, 0x3F4D, 0x3F4B, 0x3F49, 0x3F47, 0x3F45, 0x3F43, 0x3F41, + 0x3F3F, 0x3F3D, 0x3F3B, 0x3F39, 0x3F37, 0x3F35, 0x3F33, 0x3F31, + 0x3F2F, 0x3F2D, 0x3F2B, 0x3F29, 0x3F27, 0x3F25, 0x3F23, 0x3F21, + 0x3F1F, 0x3F1D, 0x3F1B, 0x3F19, 0x3F17, 0x3F15, 0x3F13, 0x3F11, + 0x3F0F, 0x3F0D, 0x3F0B, 0x3F09, 0x3F07, 0x3F05, 0x3F03, 0x3F01, + 0x09FF, 0x09FD, 0x09FB, 0x09F9, 0x09F7, 0x09F5, 0x09F3, 0x09F1, + 0x09EF, 0x09ED, 0x09EB, 0x09E9, 0x09E7, 0x09E5, 0x09E3, 0x09E1, + 0x09DF, 0x09DD, 0x09DB, 0x09D9, 0x09D7, 0x09D5, 0x09D3, 0x09D1, + 0x09CF, 0x09CD, 0x09CB, 0x09C9, 0x09C7, 0x09C5, 0x09C3, 0x09C1, + 0x09BF, 0x09BD, 0x09BB, 0x09B9, 0x09B7, 0x09B5, 0x09B3, 0x09B1, + 0x09AF, 0x09AD, 0x09AB, 0x09A9, 0x09A7, 0x09A5, 0x09A3, 0x09A1, + 0x099F, 0x099D, 0x099B, 0x0999, 0x0997, 0x0995, 0x0993, 0x0991, + 0x098F, 0x098D, 0x098B, 0x0989, 0x0987, 0x0985, 0x0983, 0x0981, + 0x097F, 0x097D, 0x097B, 0x0979, 0x0977, 0x0975, 0x0973, 0x0971, + 0x096F, 0x096D, 0x096B, 0x0969, 0x0967, 0x0965, 0x0963, 0x0961, + 0x095F, 0x095D, 0x095B, 0x0959, 0x0957, 0x0955, 0x0953, 0x0951, + 0x094F, 0x094D, 0x094B, 0x0949, 0x0947, 0x0945, 0x0943, 0x0941, + 0x093F, 0x093D, 0x093B, 0x0939, 0x0937, 0x0935, 0x0933, 0x0931, + 0x092F, 0x092D, 0x092B, 0x0929, 0x0927, 0x0925, 0x0923, 0x0921, + 0x091F, 0x091D, 0x091B, 0x0919, 0x0917, 0x0915, 0x0913, 0x0911, + 0x090F, 0x090D, 0x090B, 0x0909, 0x0907, 0x0905, 0x0903, 0x0901, + 0x0C7F, 0x0C7D, 0x0C7B, 0x0C79, 0x0C77, 0x0C75, 0x0C73, 0x0C71, + 0x0C6F, 0x0C6D, 0x0C6B, 0x0C69, 0x0C67, 0x0C65, 0x0C63, 0x0C61, + 0x0C5F, 0x0C5D, 0x0C5B, 0x0C59, 0x0C57, 0x0C55, 0x0C53, 0x0C51, + 0x0C4F, 0x0C4D, 0x0C4B, 0x0C49, 0x0C47, 0x0C45, 0x0C43, 0x0C41, + 0x0C3F, 0x0C3D, 0x0C3B, 0x0C39, 0x0C37, 0x0C35, 0x0C33, 0x0C31, + 0x0C2F, 0x0C2D, 0x0C2B, 0x0C29, 0x0C27, 0x0C25, 0x0C23, 0x0C21, + 0x0C1F, 0x0C1D, 0x0C1B, 0x0C19, 0x0C17, 0x0C15, 0x0C13, 0x0C11, + 0x0C0F, 0x0C0D, 0x0C0B, 0x0C09, 0x0C07, 0x0C05, 0x0C03, 0x0C01, + 0x047F, 0x047D, 0x047B, 0x0479, 0x0477, 0x0475, 0x0473, 0x0471, + 0x046F, 0x046D, 0x046B, 0x0469, 0x0467, 0x0465, 0x0463, 0x0461, + 0x045F, 0x045D, 0x045B, 0x0459, 0x0457, 0x0455, 0x0453, 0x0451, + 0x044F, 0x044D, 0x044B, 0x0449, 0x0447, 0x0445, 0x0443, 0x0441, + 0x043F, 0x043D, 0x043B, 0x0439, 0x0437, 0x0435, 0x0433, 0x0431, + 0x042F, 0x042D, 0x042B, 0x0429, 0x0427, 0x0425, 0x0423, 0x0421, + 0x041F, 0x041D, 0x041B, 0x0419, 0x0417, 0x0415, 0x0413, 0x0411, + 0x040F, 0x040D, 0x040B, 0x0409, 0x0407, 0x0405, 0x0403, 0x0401, + 0x01FF, 0x01FD, 0x01FB, 0x01F9, 0x01F7, 0x01F5, 0x01F3, 0x01F1, + 0x01EF, 0x01ED, 0x01EB, 0x01E9, 0x01E7, 0x01E5, 0x01E3, 0x01E1, + 0x01DF, 0x01DD, 0x01DB, 0x01D9, 0x01D7, 0x01D5, 0x01D3, 0x01D1, + 0x01CF, 0x01CD, 0x01CB, 0x01C9, 0x01C7, 0x01C5, 0x01C3, 0x01C1, + 0x007F, 0x007D, 0x007B, 0x0079, 0x0077, 0x0075, 0x0073, 0x0071, + 0x006F, 0x006D, 0x006B, 0x0069, 0x0067, 0x0065, 0x0063, 0x0061, + 0x005F, 0x005D, 0x005B, 0x0059, 0x0057, 0x0055, 0x0053, 0x0051, + 0x004F, 0x004D, 0x004B, 0x0049, 0x0047, 0x0045, 0x0043, 0x0041, + 0x00DF, 0x00DD, 0x00DB, 0x00D9, 0x00D7, 0x00D5, 0x00D3, 0x00D1, + 0x00CF, 0x00CD, 0x00CB, 0x00C9, 0x00C7, 0x00C5, 0x00C3, 0x00C1, + 0x001F, 0x001D, 0x001B, 0x0019, 0x0017, 0x0015, 0x0013, 0x0011, + 0x000F, 0x000D, 0x000B, 0x0009, 0x0007, 0x0005, 0x0003, 0x0001, + 0x005F, 0x005D, 0x005B, 0x0059, 0x0057, 0x0055, 0x0053, 0x0051, + 0x004F, 0x004D, 0x004B, 0x0049, 0x0047, 0x0045, 0x0043, 0x0041, + 0x007D, 0x007B, 0x0079, 0x0077, 0x0075, 0x0073, 0x0071, 0x006F, + 0x006D, 0x006B, 0x0069, 0x0067, 0x0065, 0x002F, 0x002D, 0x002B, +}; + +static const uint8_t dc10_vlc_lens[1024] = { + 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 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, 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, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 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, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 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, 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, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, +}; + +static const uint16_t dc11_vlc_bits[2048] = { + 0x0032, 0x0066, 0x0068, 0x006A, 0x006C, 0x006E, 0x0070, 0x0072, + 0x0074, 0x00F0, 0x00F2, 0x00F4, 0x00F6, 0x00F8, 0x00FA, 0x00FC, + 0x00FE, 0x0040, 0x0042, 0x0044, 0x0046, 0x0048, 0x004A, 0x004C, + 0x004E, 0x0050, 0x0052, 0x0054, 0x0056, 0x0058, 0x005A, 0x005C, + 0x005E, 0x00C0, 0x00C2, 0x00C4, 0x00C6, 0x00C8, 0x00CA, 0x00CC, + 0x00CE, 0x00D0, 0x00D2, 0x00D4, 0x00D6, 0x00D8, 0x00DA, 0x00DC, + 0x00DE, 0x00E0, 0x00E2, 0x00E4, 0x00E6, 0x00E8, 0x00EA, 0x00EC, + 0x00EE, 0x00F0, 0x00F2, 0x00F4, 0x00F6, 0x00F8, 0x00FA, 0x00FC, + 0x00FE, 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, + 0x000E, 0x0010, 0x0012, 0x0014, 0x0016, 0x0018, 0x001A, 0x001C, + 0x001E, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002A, 0x002C, + 0x002E, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038, 0x003A, 0x003C, + 0x003E, 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, + 0x020E, 0x0210, 0x0212, 0x0214, 0x0216, 0x0218, 0x021A, 0x021C, + 0x021E, 0x0220, 0x0222, 0x0224, 0x0226, 0x0228, 0x022A, 0x022C, + 0x022E, 0x0230, 0x0232, 0x0234, 0x0236, 0x0238, 0x023A, 0x023C, + 0x023E, 0x0080, 0x0082, 0x0084, 0x0086, 0x0088, 0x008A, 0x008C, + 0x008E, 0x0090, 0x0092, 0x0094, 0x0096, 0x0098, 0x009A, 0x009C, + 0x009E, 0x00A0, 0x00A2, 0x00A4, 0x00A6, 0x00A8, 0x00AA, 0x00AC, + 0x00AE, 0x00B0, 0x00B2, 0x00B4, 0x00B6, 0x00B8, 0x00BA, 0x00BC, + 0x00BE, 0x00C0, 0x00C2, 0x00C4, 0x00C6, 0x00C8, 0x00CA, 0x00CC, + 0x00CE, 0x00D0, 0x00D2, 0x00D4, 0x00D6, 0x00D8, 0x00DA, 0x00DC, + 0x00DE, 0x00E0, 0x00E2, 0x00E4, 0x00E6, 0x00E8, 0x00EA, 0x00EC, + 0x00EE, 0x00F0, 0x00F2, 0x00F4, 0x00F6, 0x00F8, 0x00FA, 0x00FC, + 0x00FE, 0x0480, 0x0482, 0x0484, 0x0486, 0x0488, 0x048A, 0x048C, + 0x048E, 0x0490, 0x0492, 0x0494, 0x0496, 0x0498, 0x049A, 0x049C, + 0x049E, 0x04A0, 0x04A2, 0x04A4, 0x04A6, 0x04A8, 0x04AA, 0x04AC, + 0x04AE, 0x04B0, 0x04B2, 0x04B4, 0x04B6, 0x04B8, 0x04BA, 0x04BC, + 0x04BE, 0x04C0, 0x04C2, 0x04C4, 0x04C6, 0x04C8, 0x04CA, 0x04CC, + 0x04CE, 0x04D0, 0x04D2, 0x04D4, 0x04D6, 0x04D8, 0x04DA, 0x04DC, + 0x04DE, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA, 0x04EC, + 0x04EE, 0x04F0, 0x04F2, 0x04F4, 0x04F6, 0x04F8, 0x04FA, 0x04FC, + 0x04FE, 0x0A00, 0x0A02, 0x0A04, 0x0A06, 0x0A08, 0x0A0A, 0x0A0C, + 0x0A0E, 0x0A10, 0x0A12, 0x0A14, 0x0A16, 0x0A18, 0x0A1A, 0x0A1C, + 0x0A1E, 0x0A20, 0x0A22, 0x0A24, 0x0A26, 0x0A28, 0x0A2A, 0x0A2C, + 0x0A2E, 0x0A30, 0x0A32, 0x0A34, 0x0A36, 0x0A38, 0x0A3A, 0x0A3C, + 0x0A3E, 0x0A40, 0x0A42, 0x0A44, 0x0A46, 0x0A48, 0x0A4A, 0x0A4C, + 0x0A4E, 0x0A50, 0x0A52, 0x0A54, 0x0A56, 0x0A58, 0x0A5A, 0x0A5C, + 0x0A5E, 0x0A60, 0x0A62, 0x0A64, 0x0A66, 0x0A68, 0x0A6A, 0x0A6C, + 0x0A6E, 0x0A70, 0x0A72, 0x0A74, 0x0A76, 0x0A78, 0x0A7A, 0x0A7C, + 0x0A7E, 0x0A80, 0x0A82, 0x0A84, 0x0A86, 0x0A88, 0x0A8A, 0x0A8C, + 0x0A8E, 0x0A90, 0x0A92, 0x0A94, 0x0A96, 0x0A98, 0x0A9A, 0x0A9C, + 0x0A9E, 0x0AA0, 0x0AA2, 0x0AA4, 0x0AA6, 0x0AA8, 0x0AAA, 0x0AAC, + 0x0AAE, 0x0AB0, 0x0AB2, 0x0AB4, 0x0AB6, 0x0AB8, 0x0ABA, 0x0ABC, + 0x0ABE, 0x0AC0, 0x0AC2, 0x0AC4, 0x0AC6, 0x0AC8, 0x0ACA, 0x0ACC, + 0x0ACE, 0x0AD0, 0x0AD2, 0x0AD4, 0x0AD6, 0x0AD8, 0x0ADA, 0x0ADC, + 0x0ADE, 0x0AE0, 0x0AE2, 0x0AE4, 0x0AE6, 0x0AE8, 0x0AEA, 0x0AEC, + 0x0AEE, 0x0AF0, 0x0AF2, 0x0AF4, 0x0AF6, 0x0AF8, 0x0AFA, 0x0AFC, + 0x0AFE, 0x1800, 0x1802, 0x1804, 0x1806, 0x1808, 0x180A, 0x180C, + 0x180E, 0x1810, 0x1812, 0x1814, 0x1816, 0x1818, 0x181A, 0x181C, + 0x181E, 0x1820, 0x1822, 0x1824, 0x1826, 0x1828, 0x182A, 0x182C, + 0x182E, 0x1830, 0x1832, 0x1834, 0x1836, 0x1838, 0x183A, 0x183C, + 0x183E, 0x1840, 0x1842, 0x1844, 0x1846, 0x1848, 0x184A, 0x184C, + 0x184E, 0x1850, 0x1852, 0x1854, 0x1856, 0x1858, 0x185A, 0x185C, + 0x185E, 0x1860, 0x1862, 0x1864, 0x1866, 0x1868, 0x186A, 0x186C, + 0x186E, 0x1870, 0x1872, 0x1874, 0x1876, 0x1878, 0x187A, 0x187C, + 0x187E, 0x1880, 0x1882, 0x1884, 0x1886, 0x1888, 0x188A, 0x188C, + 0x188E, 0x1890, 0x1892, 0x1894, 0x1896, 0x1898, 0x189A, 0x189C, + 0x189E, 0x18A0, 0x18A2, 0x18A4, 0x18A6, 0x18A8, 0x18AA, 0x18AC, + 0x18AE, 0x18B0, 0x18B2, 0x18B4, 0x18B6, 0x18B8, 0x18BA, 0x18BC, + 0x18BE, 0x18C0, 0x18C2, 0x18C4, 0x18C6, 0x18C8, 0x18CA, 0x18CC, + 0x18CE, 0x18D0, 0x18D2, 0x18D4, 0x18D6, 0x18D8, 0x18DA, 0x18DC, + 0x18DE, 0x18E0, 0x18E2, 0x18E4, 0x18E6, 0x18E8, 0x18EA, 0x18EC, + 0x18EE, 0x18F0, 0x18F2, 0x18F4, 0x18F6, 0x18F8, 0x18FA, 0x18FC, + 0x18FE, 0x1600, 0x1602, 0x1604, 0x1606, 0x1608, 0x160A, 0x160C, + 0x160E, 0x1610, 0x1612, 0x1614, 0x1616, 0x1618, 0x161A, 0x161C, + 0x161E, 0x1620, 0x1622, 0x1624, 0x1626, 0x1628, 0x162A, 0x162C, + 0x162E, 0x1630, 0x1632, 0x1634, 0x1636, 0x1638, 0x163A, 0x163C, + 0x163E, 0x1640, 0x1642, 0x1644, 0x1646, 0x1648, 0x164A, 0x164C, + 0x164E, 0x1650, 0x1652, 0x1654, 0x1656, 0x1658, 0x165A, 0x165C, + 0x165E, 0x1660, 0x1662, 0x1664, 0x1666, 0x1668, 0x166A, 0x166C, + 0x166E, 0x1670, 0x1672, 0x1674, 0x1676, 0x1678, 0x167A, 0x167C, + 0x167E, 0x1680, 0x1682, 0x1684, 0x1686, 0x1688, 0x168A, 0x168C, + 0x168E, 0x1690, 0x1692, 0x1694, 0x1696, 0x1698, 0x169A, 0x169C, + 0x169E, 0x16A0, 0x16A2, 0x16A4, 0x16A6, 0x16A8, 0x16AA, 0x16AC, + 0x16AE, 0x16B0, 0x16B2, 0x16B4, 0x16B6, 0x16B8, 0x16BA, 0x16BC, + 0x16BE, 0x16C0, 0x16C2, 0x16C4, 0x16C6, 0x16C8, 0x16CA, 0x16CC, + 0x16CE, 0x16D0, 0x16D2, 0x16D4, 0x16D6, 0x16D8, 0x16DA, 0x16DC, + 0x16DE, 0x16E0, 0x16E2, 0x16E4, 0x16E6, 0x16E8, 0x16EA, 0x16EC, + 0x16EE, 0x16F0, 0x16F2, 0x16F4, 0x16F6, 0x16F8, 0x16FA, 0x16FC, + 0x16FE, 0x1700, 0x1702, 0x1704, 0x1706, 0x1708, 0x170A, 0x170C, + 0x170E, 0x1710, 0x1712, 0x1714, 0x1716, 0x1718, 0x171A, 0x171C, + 0x171E, 0x1720, 0x1722, 0x1724, 0x1726, 0x1728, 0x172A, 0x172C, + 0x172E, 0x1730, 0x1732, 0x1734, 0x1736, 0x1738, 0x173A, 0x173C, + 0x173E, 0x1740, 0x1742, 0x1744, 0x1746, 0x1748, 0x174A, 0x174C, + 0x174E, 0x1750, 0x1752, 0x1754, 0x1756, 0x1758, 0x175A, 0x175C, + 0x175E, 0x1760, 0x1762, 0x1764, 0x1766, 0x1768, 0x176A, 0x176C, + 0x176E, 0x1770, 0x1772, 0x1774, 0x1776, 0x1778, 0x177A, 0x177C, + 0x177E, 0x1780, 0x1782, 0x1784, 0x1786, 0x1788, 0x178A, 0x178C, + 0x178E, 0x1790, 0x1792, 0x1794, 0x1796, 0x1798, 0x179A, 0x179C, + 0x179E, 0x17A0, 0x17A2, 0x17A4, 0x17A6, 0x17A8, 0x17AA, 0x17AC, + 0x17AE, 0x17B0, 0x17B2, 0x17B4, 0x17B6, 0x17B8, 0x17BA, 0x17BC, + 0x17BE, 0x17C0, 0x17C2, 0x17C4, 0x17C6, 0x17C8, 0x17CA, 0x17CC, + 0x17CE, 0x17D0, 0x17D2, 0x17D4, 0x17D6, 0x17D8, 0x17DA, 0x17DC, + 0x17DE, 0x17E0, 0x17E2, 0x17E4, 0x17E6, 0x17E8, 0x17EA, 0x17EC, + 0x17EE, 0x17F0, 0x17F2, 0x17F4, 0x17F6, 0x17F8, 0x17FA, 0x17FC, + 0x17FE, 0x7600, 0x7602, 0x7604, 0x7606, 0x7608, 0x760A, 0x760C, + 0x760E, 0x7610, 0x7612, 0x7614, 0x7616, 0x7618, 0x761A, 0x761C, + 0x761E, 0x7620, 0x7622, 0x7624, 0x7626, 0x7628, 0x762A, 0x762C, + 0x762E, 0x7630, 0x7632, 0x7634, 0x7636, 0x7638, 0x763A, 0x763C, + 0x763E, 0x7640, 0x7642, 0x7644, 0x7646, 0x7648, 0x764A, 0x764C, + 0x764E, 0x7650, 0x7652, 0x7654, 0x7656, 0x7658, 0x765A, 0x765C, + 0x765E, 0x7660, 0x7662, 0x7664, 0x7666, 0x7668, 0x766A, 0x766C, + 0x766E, 0x7670, 0x7672, 0x7674, 0x7676, 0x7678, 0x767A, 0x767C, + 0x767E, 0x7680, 0x7682, 0x7684, 0x7686, 0x7688, 0x768A, 0x768C, + 0x768E, 0x7690, 0x7692, 0x7694, 0x7696, 0x7698, 0x769A, 0x769C, + 0x769E, 0x76A0, 0x76A2, 0x76A4, 0x76A6, 0x76A8, 0x76AA, 0x76AC, + 0x76AE, 0x76B0, 0x76B2, 0x76B4, 0x76B6, 0x76B8, 0x76BA, 0x76BC, + 0x76BE, 0x76C0, 0x76C2, 0x76C4, 0x76C6, 0x76C8, 0x76CA, 0x76CC, + 0x76CE, 0x76D0, 0x76D2, 0x76D4, 0x76D6, 0x76D8, 0x76DA, 0x76DC, + 0x76DE, 0x76E0, 0x76E2, 0x76E4, 0x76E6, 0x76E8, 0x76EA, 0x76EC, + 0x76EE, 0x76F0, 0x76F2, 0x76F4, 0x76F6, 0x76F8, 0x76FA, 0x76FC, + 0x76FE, 0x7700, 0x7702, 0x7704, 0x7706, 0x7708, 0x770A, 0x770C, + 0x770E, 0x7710, 0x7712, 0x7714, 0x7716, 0x7718, 0x771A, 0x771C, + 0x771E, 0x7720, 0x7722, 0x7724, 0x7726, 0x7728, 0x772A, 0x772C, + 0x772E, 0x7730, 0x7732, 0x7734, 0x7736, 0x7738, 0x773A, 0x773C, + 0x773E, 0x7740, 0x7742, 0x7744, 0x7746, 0x7748, 0x774A, 0x774C, + 0x774E, 0x7750, 0x7752, 0x7754, 0x7756, 0x7758, 0x775A, 0x775C, + 0x775E, 0x7760, 0x7762, 0x7764, 0x7766, 0x7768, 0x776A, 0x776C, + 0x776E, 0x7770, 0x7772, 0x7774, 0x7776, 0x7778, 0x777A, 0x777C, + 0x777E, 0x7780, 0x7782, 0x7784, 0x7786, 0x7788, 0x778A, 0x778C, + 0x778E, 0x7790, 0x7792, 0x7794, 0x7796, 0x7798, 0x779A, 0x779C, + 0x779E, 0x77A0, 0x77A2, 0x77A4, 0x77A6, 0x77A8, 0x77AA, 0x77AC, + 0x77AE, 0x77B0, 0x77B2, 0x77B4, 0x77B6, 0x77B8, 0x77BA, 0x77BC, + 0x77BE, 0x77C0, 0x77C2, 0x77C4, 0x77C6, 0x77C8, 0x77CA, 0x77CC, + 0x77CE, 0x77D0, 0x77D2, 0x77D4, 0x77D6, 0x77D8, 0x77DA, 0x77DC, + 0x77DE, 0x77E0, 0x77E2, 0x77E4, 0x77E6, 0x77E8, 0x77EA, 0x77EC, + 0x77EE, 0x77F0, 0x77F2, 0x77F4, 0x77F6, 0x77F8, 0x77FA, 0x77FC, + 0x3BFF, 0x77FD, 0x77FB, 0x77F9, 0x77F7, 0x77F5, 0x77F3, 0x77F1, + 0x77EF, 0x77ED, 0x77EB, 0x77E9, 0x77E7, 0x77E5, 0x77E3, 0x77E1, + 0x77DF, 0x77DD, 0x77DB, 0x77D9, 0x77D7, 0x77D5, 0x77D3, 0x77D1, + 0x77CF, 0x77CD, 0x77CB, 0x77C9, 0x77C7, 0x77C5, 0x77C3, 0x77C1, + 0x77BF, 0x77BD, 0x77BB, 0x77B9, 0x77B7, 0x77B5, 0x77B3, 0x77B1, + 0x77AF, 0x77AD, 0x77AB, 0x77A9, 0x77A7, 0x77A5, 0x77A3, 0x77A1, + 0x779F, 0x779D, 0x779B, 0x7799, 0x7797, 0x7795, 0x7793, 0x7791, + 0x778F, 0x778D, 0x778B, 0x7789, 0x7787, 0x7785, 0x7783, 0x7781, + 0x777F, 0x777D, 0x777B, 0x7779, 0x7777, 0x7775, 0x7773, 0x7771, + 0x776F, 0x776D, 0x776B, 0x7769, 0x7767, 0x7765, 0x7763, 0x7761, + 0x775F, 0x775D, 0x775B, 0x7759, 0x7757, 0x7755, 0x7753, 0x7751, + 0x774F, 0x774D, 0x774B, 0x7749, 0x7747, 0x7745, 0x7743, 0x7741, + 0x773F, 0x773D, 0x773B, 0x7739, 0x7737, 0x7735, 0x7733, 0x7731, + 0x772F, 0x772D, 0x772B, 0x7729, 0x7727, 0x7725, 0x7723, 0x7721, + 0x771F, 0x771D, 0x771B, 0x7719, 0x7717, 0x7715, 0x7713, 0x7711, + 0x770F, 0x770D, 0x770B, 0x7709, 0x7707, 0x7705, 0x7703, 0x7701, + 0x76FF, 0x76FD, 0x76FB, 0x76F9, 0x76F7, 0x76F5, 0x76F3, 0x76F1, + 0x76EF, 0x76ED, 0x76EB, 0x76E9, 0x76E7, 0x76E5, 0x76E3, 0x76E1, + 0x76DF, 0x76DD, 0x76DB, 0x76D9, 0x76D7, 0x76D5, 0x76D3, 0x76D1, + 0x76CF, 0x76CD, 0x76CB, 0x76C9, 0x76C7, 0x76C5, 0x76C3, 0x76C1, + 0x76BF, 0x76BD, 0x76BB, 0x76B9, 0x76B7, 0x76B5, 0x76B3, 0x76B1, + 0x76AF, 0x76AD, 0x76AB, 0x76A9, 0x76A7, 0x76A5, 0x76A3, 0x76A1, + 0x769F, 0x769D, 0x769B, 0x7699, 0x7697, 0x7695, 0x7693, 0x7691, + 0x768F, 0x768D, 0x768B, 0x7689, 0x7687, 0x7685, 0x7683, 0x7681, + 0x767F, 0x767D, 0x767B, 0x7679, 0x7677, 0x7675, 0x7673, 0x7671, + 0x766F, 0x766D, 0x766B, 0x7669, 0x7667, 0x7665, 0x7663, 0x7661, + 0x765F, 0x765D, 0x765B, 0x7659, 0x7657, 0x7655, 0x7653, 0x7651, + 0x764F, 0x764D, 0x764B, 0x7649, 0x7647, 0x7645, 0x7643, 0x7641, + 0x763F, 0x763D, 0x763B, 0x7639, 0x7637, 0x7635, 0x7633, 0x7631, + 0x762F, 0x762D, 0x762B, 0x7629, 0x7627, 0x7625, 0x7623, 0x7621, + 0x761F, 0x761D, 0x761B, 0x7619, 0x7617, 0x7615, 0x7613, 0x7611, + 0x760F, 0x760D, 0x760B, 0x7609, 0x7607, 0x7605, 0x7603, 0x7601, + 0x17FF, 0x17FD, 0x17FB, 0x17F9, 0x17F7, 0x17F5, 0x17F3, 0x17F1, + 0x17EF, 0x17ED, 0x17EB, 0x17E9, 0x17E7, 0x17E5, 0x17E3, 0x17E1, + 0x17DF, 0x17DD, 0x17DB, 0x17D9, 0x17D7, 0x17D5, 0x17D3, 0x17D1, + 0x17CF, 0x17CD, 0x17CB, 0x17C9, 0x17C7, 0x17C5, 0x17C3, 0x17C1, + 0x17BF, 0x17BD, 0x17BB, 0x17B9, 0x17B7, 0x17B5, 0x17B3, 0x17B1, + 0x17AF, 0x17AD, 0x17AB, 0x17A9, 0x17A7, 0x17A5, 0x17A3, 0x17A1, + 0x179F, 0x179D, 0x179B, 0x1799, 0x1797, 0x1795, 0x1793, 0x1791, + 0x178F, 0x178D, 0x178B, 0x1789, 0x1787, 0x1785, 0x1783, 0x1781, + 0x177F, 0x177D, 0x177B, 0x1779, 0x1777, 0x1775, 0x1773, 0x1771, + 0x176F, 0x176D, 0x176B, 0x1769, 0x1767, 0x1765, 0x1763, 0x1761, + 0x175F, 0x175D, 0x175B, 0x1759, 0x1757, 0x1755, 0x1753, 0x1751, + 0x174F, 0x174D, 0x174B, 0x1749, 0x1747, 0x1745, 0x1743, 0x1741, + 0x173F, 0x173D, 0x173B, 0x1739, 0x1737, 0x1735, 0x1733, 0x1731, + 0x172F, 0x172D, 0x172B, 0x1729, 0x1727, 0x1725, 0x1723, 0x1721, + 0x171F, 0x171D, 0x171B, 0x1719, 0x1717, 0x1715, 0x1713, 0x1711, + 0x170F, 0x170D, 0x170B, 0x1709, 0x1707, 0x1705, 0x1703, 0x1701, + 0x16FF, 0x16FD, 0x16FB, 0x16F9, 0x16F7, 0x16F5, 0x16F3, 0x16F1, + 0x16EF, 0x16ED, 0x16EB, 0x16E9, 0x16E7, 0x16E5, 0x16E3, 0x16E1, + 0x16DF, 0x16DD, 0x16DB, 0x16D9, 0x16D7, 0x16D5, 0x16D3, 0x16D1, + 0x16CF, 0x16CD, 0x16CB, 0x16C9, 0x16C7, 0x16C5, 0x16C3, 0x16C1, + 0x16BF, 0x16BD, 0x16BB, 0x16B9, 0x16B7, 0x16B5, 0x16B3, 0x16B1, + 0x16AF, 0x16AD, 0x16AB, 0x16A9, 0x16A7, 0x16A5, 0x16A3, 0x16A1, + 0x169F, 0x169D, 0x169B, 0x1699, 0x1697, 0x1695, 0x1693, 0x1691, + 0x168F, 0x168D, 0x168B, 0x1689, 0x1687, 0x1685, 0x1683, 0x1681, + 0x167F, 0x167D, 0x167B, 0x1679, 0x1677, 0x1675, 0x1673, 0x1671, + 0x166F, 0x166D, 0x166B, 0x1669, 0x1667, 0x1665, 0x1663, 0x1661, + 0x165F, 0x165D, 0x165B, 0x1659, 0x1657, 0x1655, 0x1653, 0x1651, + 0x164F, 0x164D, 0x164B, 0x1649, 0x1647, 0x1645, 0x1643, 0x1641, + 0x163F, 0x163D, 0x163B, 0x1639, 0x1637, 0x1635, 0x1633, 0x1631, + 0x162F, 0x162D, 0x162B, 0x1629, 0x1627, 0x1625, 0x1623, 0x1621, + 0x161F, 0x161D, 0x161B, 0x1619, 0x1617, 0x1615, 0x1613, 0x1611, + 0x160F, 0x160D, 0x160B, 0x1609, 0x1607, 0x1605, 0x1603, 0x1601, + 0x18FF, 0x18FD, 0x18FB, 0x18F9, 0x18F7, 0x18F5, 0x18F3, 0x18F1, + 0x18EF, 0x18ED, 0x18EB, 0x18E9, 0x18E7, 0x18E5, 0x18E3, 0x18E1, + 0x18DF, 0x18DD, 0x18DB, 0x18D9, 0x18D7, 0x18D5, 0x18D3, 0x18D1, + 0x18CF, 0x18CD, 0x18CB, 0x18C9, 0x18C7, 0x18C5, 0x18C3, 0x18C1, + 0x18BF, 0x18BD, 0x18BB, 0x18B9, 0x18B7, 0x18B5, 0x18B3, 0x18B1, + 0x18AF, 0x18AD, 0x18AB, 0x18A9, 0x18A7, 0x18A5, 0x18A3, 0x18A1, + 0x189F, 0x189D, 0x189B, 0x1899, 0x1897, 0x1895, 0x1893, 0x1891, + 0x188F, 0x188D, 0x188B, 0x1889, 0x1887, 0x1885, 0x1883, 0x1881, + 0x187F, 0x187D, 0x187B, 0x1879, 0x1877, 0x1875, 0x1873, 0x1871, + 0x186F, 0x186D, 0x186B, 0x1869, 0x1867, 0x1865, 0x1863, 0x1861, + 0x185F, 0x185D, 0x185B, 0x1859, 0x1857, 0x1855, 0x1853, 0x1851, + 0x184F, 0x184D, 0x184B, 0x1849, 0x1847, 0x1845, 0x1843, 0x1841, + 0x183F, 0x183D, 0x183B, 0x1839, 0x1837, 0x1835, 0x1833, 0x1831, + 0x182F, 0x182D, 0x182B, 0x1829, 0x1827, 0x1825, 0x1823, 0x1821, + 0x181F, 0x181D, 0x181B, 0x1819, 0x1817, 0x1815, 0x1813, 0x1811, + 0x180F, 0x180D, 0x180B, 0x1809, 0x1807, 0x1805, 0x1803, 0x1801, + 0x0AFF, 0x0AFD, 0x0AFB, 0x0AF9, 0x0AF7, 0x0AF5, 0x0AF3, 0x0AF1, + 0x0AEF, 0x0AED, 0x0AEB, 0x0AE9, 0x0AE7, 0x0AE5, 0x0AE3, 0x0AE1, + 0x0ADF, 0x0ADD, 0x0ADB, 0x0AD9, 0x0AD7, 0x0AD5, 0x0AD3, 0x0AD1, + 0x0ACF, 0x0ACD, 0x0ACB, 0x0AC9, 0x0AC7, 0x0AC5, 0x0AC3, 0x0AC1, + 0x0ABF, 0x0ABD, 0x0ABB, 0x0AB9, 0x0AB7, 0x0AB5, 0x0AB3, 0x0AB1, + 0x0AAF, 0x0AAD, 0x0AAB, 0x0AA9, 0x0AA7, 0x0AA5, 0x0AA3, 0x0AA1, + 0x0A9F, 0x0A9D, 0x0A9B, 0x0A99, 0x0A97, 0x0A95, 0x0A93, 0x0A91, + 0x0A8F, 0x0A8D, 0x0A8B, 0x0A89, 0x0A87, 0x0A85, 0x0A83, 0x0A81, + 0x0A7F, 0x0A7D, 0x0A7B, 0x0A79, 0x0A77, 0x0A75, 0x0A73, 0x0A71, + 0x0A6F, 0x0A6D, 0x0A6B, 0x0A69, 0x0A67, 0x0A65, 0x0A63, 0x0A61, + 0x0A5F, 0x0A5D, 0x0A5B, 0x0A59, 0x0A57, 0x0A55, 0x0A53, 0x0A51, + 0x0A4F, 0x0A4D, 0x0A4B, 0x0A49, 0x0A47, 0x0A45, 0x0A43, 0x0A41, + 0x0A3F, 0x0A3D, 0x0A3B, 0x0A39, 0x0A37, 0x0A35, 0x0A33, 0x0A31, + 0x0A2F, 0x0A2D, 0x0A2B, 0x0A29, 0x0A27, 0x0A25, 0x0A23, 0x0A21, + 0x0A1F, 0x0A1D, 0x0A1B, 0x0A19, 0x0A17, 0x0A15, 0x0A13, 0x0A11, + 0x0A0F, 0x0A0D, 0x0A0B, 0x0A09, 0x0A07, 0x0A05, 0x0A03, 0x0A01, + 0x04FF, 0x04FD, 0x04FB, 0x04F9, 0x04F7, 0x04F5, 0x04F3, 0x04F1, + 0x04EF, 0x04ED, 0x04EB, 0x04E9, 0x04E7, 0x04E5, 0x04E3, 0x04E1, + 0x04DF, 0x04DD, 0x04DB, 0x04D9, 0x04D7, 0x04D5, 0x04D3, 0x04D1, + 0x04CF, 0x04CD, 0x04CB, 0x04C9, 0x04C7, 0x04C5, 0x04C3, 0x04C1, + 0x04BF, 0x04BD, 0x04BB, 0x04B9, 0x04B7, 0x04B5, 0x04B3, 0x04B1, + 0x04AF, 0x04AD, 0x04AB, 0x04A9, 0x04A7, 0x04A5, 0x04A3, 0x04A1, + 0x049F, 0x049D, 0x049B, 0x0499, 0x0497, 0x0495, 0x0493, 0x0491, + 0x048F, 0x048D, 0x048B, 0x0489, 0x0487, 0x0485, 0x0483, 0x0481, + 0x00FF, 0x00FD, 0x00FB, 0x00F9, 0x00F7, 0x00F5, 0x00F3, 0x00F1, + 0x00EF, 0x00ED, 0x00EB, 0x00E9, 0x00E7, 0x00E5, 0x00E3, 0x00E1, + 0x00DF, 0x00DD, 0x00DB, 0x00D9, 0x00D7, 0x00D5, 0x00D3, 0x00D1, + 0x00CF, 0x00CD, 0x00CB, 0x00C9, 0x00C7, 0x00C5, 0x00C3, 0x00C1, + 0x00BF, 0x00BD, 0x00BB, 0x00B9, 0x00B7, 0x00B5, 0x00B3, 0x00B1, + 0x00AF, 0x00AD, 0x00AB, 0x00A9, 0x00A7, 0x00A5, 0x00A3, 0x00A1, + 0x009F, 0x009D, 0x009B, 0x0099, 0x0097, 0x0095, 0x0093, 0x0091, + 0x008F, 0x008D, 0x008B, 0x0089, 0x0087, 0x0085, 0x0083, 0x0081, + 0x023F, 0x023D, 0x023B, 0x0239, 0x0237, 0x0235, 0x0233, 0x0231, + 0x022F, 0x022D, 0x022B, 0x0229, 0x0227, 0x0225, 0x0223, 0x0221, + 0x021F, 0x021D, 0x021B, 0x0219, 0x0217, 0x0215, 0x0213, 0x0211, + 0x020F, 0x020D, 0x020B, 0x0209, 0x0207, 0x0205, 0x0203, 0x0201, + 0x003F, 0x003D, 0x003B, 0x0039, 0x0037, 0x0035, 0x0033, 0x0031, + 0x002F, 0x002D, 0x002B, 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, + 0x001F, 0x001D, 0x001B, 0x0019, 0x0017, 0x0015, 0x0013, 0x0011, + 0x000F, 0x000D, 0x000B, 0x0009, 0x0007, 0x0005, 0x0003, 0x0001, + 0x00FF, 0x00FD, 0x00FB, 0x00F9, 0x00F7, 0x00F5, 0x00F3, 0x00F1, + 0x00EF, 0x00ED, 0x00EB, 0x00E9, 0x00E7, 0x00E5, 0x00E3, 0x00E1, + 0x00DF, 0x00DD, 0x00DB, 0x00D9, 0x00D7, 0x00D5, 0x00D3, 0x00D1, + 0x00CF, 0x00CD, 0x00CB, 0x00C9, 0x00C7, 0x00C5, 0x00C3, 0x00C1, + 0x005F, 0x005D, 0x005B, 0x0059, 0x0057, 0x0055, 0x0053, 0x0051, + 0x004F, 0x004D, 0x004B, 0x0049, 0x0047, 0x0045, 0x0043, 0x0041, + 0x00FF, 0x00FD, 0x00FB, 0x00F9, 0x00F7, 0x00F5, 0x00F3, 0x00F1, + 0x0075, 0x0073, 0x0071, 0x006F, 0x006D, 0x006B, 0x0069, 0x0067, +}; + +static const uint8_t dc11_vlc_lens[2048] = { + 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, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 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, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 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, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 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, + 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 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, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 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, 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, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, +}; + +#define RPT_2(a, b, c) { a, b, c }, { a, b, c } +#define RPT_4(a, b, c) RPT_2( a, b, c), RPT_2( a, b, c) +#define RPT_8(a, b, c) RPT_4( a, b, c), RPT_4( a, b, c) +#define RPT_16(a, b, c) RPT_8( a, b, c), RPT_8( a, b, c) +#define RPT_32(a, b, c) RPT_16( a, b, c), RPT_16( a, b, c) +#define RPT_64(a, b, c) RPT_32( a, b, c), RPT_32( a, b, c) +#define RPT_128(a, b, c) RPT_64( a, b, c), RPT_64( a, b, c) +#define RPT_256(a, b, c) RPT_128(a, b, c), RPT_128(a, b, c) +#define RPT_512(a, b, c) RPT_256(a, b, c), RPT_256(a, b, c) +#define RPT_1024(a, b, c) RPT_512(a, b, c), RPT_512(a, b, c) + +static const HQXLUT ac0_lut[] = { + RPT_64 ( 1, 0, 4 ), RPT_64 ( -1, 0, 4 ), + RPT_64 ( 2, 0, 4 ), RPT_64 ( -2, 0, 4 ), + RPT_32 ( 3, 0, 5 ), RPT_32 ( -3, 0, 5 ), + RPT_32 ( 4, 0, 5 ), RPT_32 ( -4, 0, 5 ), + RPT_32 ( 1, 1, 5 ), RPT_32 ( -1, 1, 5 ), + RPT_16 ( 5, 0, 6 ), RPT_16 ( -5, 0, 6 ), + RPT_16 ( 6, 0, 6 ), RPT_16 ( -6, 0, 6 ), + RPT_16 ( 7, 0, 6 ), RPT_16 ( -7, 0, 6 ), + RPT_16 ( 8, 0, 6 ), RPT_16 ( -8, 0, 6 ), + { 1024, 0, -1 }, { 1056, 0, -1 }, { 1088, 0, -1 }, { 1120, 0, -1 }, + { 1152, 0, -1 }, { 1184, 0, -1 }, { 1216, 0, -1 }, { 1248, 0, -1 }, + { 1280, 0, -1 }, { 1312, 0, -1 }, { 1344, 0, -1 }, { 1376, 0, -1 }, + { 1408, 0, -1 }, { 1440, 0, -1 }, { 1472, 0, -1 }, { 1504, 0, -1 }, + { 1536, 0, -1 }, { 1568, 0, -1 }, { 1600, 0, -1 }, { 1632, 0, -1 }, + { 1664, 0, -1 }, { 1696, 0, -1 }, { 1728, 0, -1 }, { 1760, 0, -1 }, + { 1792, 0, -1 }, { 1824, 0, -1 }, { 1856, 0, -1 }, { 1888, 0, -1 }, + { 1920, 0, -1 }, { 1952, 0, -1 }, { 1984, 0, -1 }, { 2016, 0, -1 }, + RPT_32 ( 0, 64, 5 ), RPT_8 ( 9, 0, 7 ), + RPT_8 ( -9, 0, 7 ), RPT_8 ( 10, 0, 7 ), + RPT_8 ( -10, 0, 7 ), RPT_8 ( 11, 0, 7 ), + RPT_8 ( -11, 0, 7 ), RPT_8 ( 12, 0, 7 ), + RPT_8 ( -12, 0, 7 ), RPT_8 ( 13, 0, 7 ), + RPT_8 ( -13, 0, 7 ), RPT_8 ( 14, 0, 7 ), + RPT_8 ( -14, 0, 7 ), RPT_8 ( 2, 1, 7 ), + RPT_8 ( -2, 1, 7 ), RPT_8 ( 1, 2, 7 ), + RPT_8 ( -1, 2, 7 ), RPT_4 ( 15, 0, 8 ), + RPT_4 ( -15, 0, 8 ), RPT_4 ( 16, 0, 8 ), + RPT_4 ( -16, 0, 8 ), RPT_4 ( 17, 0, 8 ), + RPT_4 ( -17, 0, 8 ), RPT_4 ( 18, 0, 8 ), + RPT_4 ( -18, 0, 8 ), RPT_4 ( 19, 0, 8 ), + RPT_4 ( -19, 0, 8 ), RPT_4 ( 20, 0, 8 ), + RPT_4 ( -20, 0, 8 ), RPT_4 ( 21, 0, 8 ), + RPT_4 ( -21, 0, 8 ), RPT_4 ( 3, 1, 8 ), + RPT_4 ( -3, 1, 8 ), RPT_4 ( 4, 1, 8 ), + RPT_4 ( -4, 1, 8 ), RPT_4 ( 1, 3, 8 ), + RPT_4 ( -1, 3, 8 ), RPT_4 ( 1, 4, 8 ), + RPT_4 ( -1, 4, 8 ), RPT_4 ( 0, 0, 8 ), + RPT_2 ( 22, 0, 9 ), RPT_2 ( -22, 0, 9 ), + RPT_2 ( 23, 0, 9 ), RPT_2 ( -23, 0, 9 ), + RPT_2 ( 24, 0, 9 ), RPT_2 ( -24, 0, 9 ), + RPT_2 ( 25, 0, 9 ), RPT_2 ( -25, 0, 9 ), + RPT_2 ( 26, 0, 9 ), RPT_2 ( -26, 0, 9 ), + RPT_2 ( 27, 0, 9 ), RPT_2 ( -27, 0, 9 ), + RPT_2 ( 28, 0, 9 ), RPT_2 ( -28, 0, 9 ), + RPT_2 ( 29, 0, 9 ), RPT_2 ( -29, 0, 9 ), + RPT_2 ( 30, 0, 9 ), RPT_2 ( -30, 0, 9 ), + RPT_2 ( 31, 0, 9 ), RPT_2 ( -31, 0, 9 ), + RPT_2 ( 32, 0, 9 ), RPT_2 ( -32, 0, 9 ), + RPT_2 ( 33, 0, 9 ), RPT_2 ( -33, 0, 9 ), + RPT_2 ( 5, 1, 9 ), RPT_2 ( -5, 1, 9 ), + RPT_2 ( 6, 1, 9 ), RPT_2 ( -6, 1, 9 ), + RPT_2 ( 2, 2, 9 ), RPT_2 ( -2, 2, 9 ), + RPT_2 ( 1, 5, 9 ), RPT_2 ( -1, 5, 9 ), + RPT_2 ( 1, 6, 9 ), RPT_2 ( -1, 6, 9 ), + { 34, 0, 10 }, { -34, 0, 10 }, { 35, 0, 10 }, { -35, 0, 10 }, + { 36, 0, 10 }, { -36, 0, 10 }, { 37, 0, 10 }, { -37, 0, 10 }, + { 38, 0, 10 }, { -38, 0, 10 }, { 39, 0, 10 }, { -39, 0, 10 }, + { 40, 0, 10 }, { -40, 0, 10 }, { 41, 0, 10 }, { -41, 0, 10 }, + { 42, 0, 10 }, { -42, 0, 10 }, { 43, 0, 10 }, { -43, 0, 10 }, + { 44, 0, 10 }, { -44, 0, 10 }, { 45, 0, 10 }, { -45, 0, 10 }, + { 46, 0, 10 }, { -46, 0, 10 }, { 47, 0, 10 }, { -47, 0, 10 }, + { 48, 0, 10 }, { -48, 0, 10 }, { 49, 0, 10 }, { -49, 0, 10 }, + { 50, 0, 10 }, { -50, 0, 10 }, RPT_2 ( 0, 1, 9 ), + { 7, 1, 10 }, { -7, 1, 10 }, { 8, 1, 10 }, { -8, 1, 10 }, + { 9, 1, 10 }, { -9, 1, 10 }, { 10, 1, 10 }, { -10, 1, 10 }, + RPT_2 ( 0, 2, 9 ), { 3, 2, 10 }, { -3, 2, 10 }, + RPT_2 ( 0, 3, 9 ), { 2, 3, 10 }, { -2, 3, 10 }, + { 1, 7, 10 }, { -1, 7, 10 }, { 1, 8, 10 }, { -1, 8, 10 }, + { 2048, 0, -1 }, { 2080, 0, -1 }, { 2112, 0, -1 }, { 2144, 0, -1 }, + { 2176, 0, -1 }, { 2208, 0, -1 }, { 2240, 0, -1 }, { 2272, 0, -1 }, + { 2304, 0, -1 }, { 2336, 0, -1 }, { 2368, 0, -1 }, { 2400, 0, -1 }, + { 2432, 0, -1 }, { 2464, 0, -1 }, { 2496, 0, -1 }, { 2528, 0, -1 }, + { 2560, 0, -1 }, { 2592, 0, -1 }, { 2624, 0, -1 }, { 2656, 0, -1 }, + { 2688, 0, -1 }, { 2720, 0, -1 }, { 2752, 0, -1 }, { 0, 4, 10 }, + { 2784, 0, -1 }, { 0, 5, 10 }, { 0, 6, 10 }, { 2816, 0, -1 }, + { 2848, 0, -1 }, { 2880, 0, -1 }, { 2912, 0, -1 }, { 2944, 0, -1 }, + { 2976, 0, -1 }, { 3008, 0, -1 }, { 3040, 0, -1 }, { 3072, 0, -1 }, + { 3104, 0, -1 }, { 3136, 0, -1 }, { 3168, 0, -1 }, { 3200, 0, -1 }, + RPT_4 ( 0, 0, 13 ), RPT_2 ( 1, 0, 14 ), + RPT_2 ( -1, 0, 14 ), RPT_2 ( 2, 0, 14 ), + RPT_2 ( -2, 0, 14 ), RPT_2 ( 3, 0, 14 ), + RPT_2 ( -3, 0, 14 ), RPT_2 ( 4, 0, 14 ), + RPT_2 ( -4, 0, 14 ), RPT_2 ( 5, 0, 14 ), + RPT_2 ( -5, 0, 14 ), RPT_2 ( 6, 0, 14 ), + RPT_2 ( -6, 0, 14 ), RPT_2 ( 7, 0, 14 ), + RPT_2 ( -7, 0, 14 ), RPT_2 ( 8, 0, 14 ), + RPT_2 ( -8, 0, 14 ), RPT_2 ( 9, 0, 14 ), + RPT_2 ( -9, 0, 14 ), RPT_2 ( 10, 0, 14 ), + RPT_2 ( -10, 0, 14 ), RPT_2 ( 11, 0, 14 ), + RPT_2 ( -11, 0, 14 ), RPT_2 ( 12, 0, 14 ), + RPT_2 ( -12, 0, 14 ), RPT_2 ( 13, 0, 14 ), + RPT_2 ( -13, 0, 14 ), RPT_2 ( 14, 0, 14 ), + RPT_2 ( -14, 0, 14 ), RPT_2 ( 15, 0, 14 ), + RPT_2 ( -15, 0, 14 ), RPT_2 ( 16, 0, 14 ), + RPT_2 ( -16, 0, 14 ), RPT_2 ( 17, 0, 14 ), + RPT_2 ( -17, 0, 14 ), RPT_2 ( 18, 0, 14 ), + RPT_2 ( -18, 0, 14 ), RPT_2 ( 19, 0, 14 ), + RPT_2 ( -19, 0, 14 ), RPT_2 ( 20, 0, 14 ), + RPT_2 ( -20, 0, 14 ), RPT_2 ( 21, 0, 14 ), + RPT_2 ( -21, 0, 14 ), RPT_2 ( 22, 0, 14 ), + RPT_2 ( -22, 0, 14 ), RPT_2 ( 23, 0, 14 ), + RPT_2 ( -23, 0, 14 ), RPT_2 ( 24, 0, 14 ), + RPT_2 ( -24, 0, 14 ), RPT_2 ( 25, 0, 14 ), + RPT_2 ( -25, 0, 14 ), RPT_2 ( 26, 0, 14 ), + RPT_2 ( -26, 0, 14 ), RPT_2 ( 27, 0, 14 ), + RPT_2 ( -27, 0, 14 ), RPT_2 ( 28, 0, 14 ), + RPT_2 ( -28, 0, 14 ), RPT_2 ( 29, 0, 14 ), + RPT_2 ( -29, 0, 14 ), RPT_2 ( 30, 0, 14 ), + RPT_2 ( -30, 0, 14 ), RPT_2 ( 31, 0, 14 ), + RPT_2 ( -31, 0, 14 ), RPT_2 ( 32, 0, 14 ), + RPT_2 ( -32, 0, 14 ), RPT_2 ( 33, 0, 14 ), + RPT_2 ( -33, 0, 14 ), RPT_2 ( 34, 0, 14 ), + RPT_2 ( -34, 0, 14 ), RPT_2 ( 35, 0, 14 ), + RPT_2 ( -35, 0, 14 ), RPT_2 ( 36, 0, 14 ), + RPT_2 ( -36, 0, 14 ), RPT_2 ( 37, 0, 14 ), + RPT_2 ( -37, 0, 14 ), RPT_2 ( 38, 0, 14 ), + RPT_2 ( -38, 0, 14 ), RPT_2 ( 39, 0, 14 ), + RPT_2 ( -39, 0, 14 ), RPT_2 ( 40, 0, 14 ), + RPT_2 ( -40, 0, 14 ), RPT_2 ( 41, 0, 14 ), + RPT_2 ( -41, 0, 14 ), RPT_2 ( 42, 0, 14 ), + RPT_2 ( -42, 0, 14 ), RPT_2 ( 43, 0, 14 ), + RPT_2 ( -43, 0, 14 ), RPT_2 ( 44, 0, 14 ), + RPT_2 ( -44, 0, 14 ), RPT_2 ( 45, 0, 14 ), + RPT_2 ( -45, 0, 14 ), RPT_2 ( 46, 0, 14 ), + RPT_2 ( -46, 0, 14 ), RPT_2 ( 47, 0, 14 ), + RPT_2 ( -47, 0, 14 ), RPT_2 ( 48, 0, 14 ), + RPT_2 ( -48, 0, 14 ), RPT_2 ( 49, 0, 14 ), + RPT_2 ( -49, 0, 14 ), RPT_2 ( 50, 0, 14 ), + RPT_2 ( -50, 0, 14 ), RPT_2 ( 51, 0, 14 ), + RPT_2 ( -51, 0, 14 ), RPT_2 ( 52, 0, 14 ), + RPT_2 ( -52, 0, 14 ), RPT_2 ( 53, 0, 14 ), + RPT_2 ( -53, 0, 14 ), RPT_2 ( 54, 0, 14 ), + RPT_2 ( -54, 0, 14 ), RPT_2 ( 55, 0, 14 ), + RPT_2 ( -55, 0, 14 ), RPT_2 ( 56, 0, 14 ), + RPT_2 ( -56, 0, 14 ), RPT_2 ( 57, 0, 14 ), + RPT_2 ( -57, 0, 14 ), RPT_2 ( 58, 0, 14 ), + RPT_2 ( -58, 0, 14 ), RPT_2 ( 59, 0, 14 ), + RPT_2 ( -59, 0, 14 ), RPT_2 ( 60, 0, 14 ), + RPT_2 ( -60, 0, 14 ), RPT_2 ( 61, 0, 14 ), + RPT_2 ( -61, 0, 14 ), RPT_2 ( 62, 0, 14 ), + RPT_2 ( -62, 0, 14 ), RPT_2 ( 63, 0, 14 ), + RPT_2 ( -63, 0, 14 ), RPT_2 ( 64, 0, 14 ), + RPT_2 ( -64, 0, 14 ), RPT_2 ( 65, 0, 14 ), + RPT_2 ( -65, 0, 14 ), RPT_2 ( 66, 0, 14 ), + RPT_2 ( -66, 0, 14 ), RPT_2 ( 67, 0, 14 ), + RPT_2 ( -67, 0, 14 ), RPT_2 ( 68, 0, 14 ), + RPT_2 ( -68, 0, 14 ), RPT_2 ( 69, 0, 14 ), + RPT_2 ( -69, 0, 14 ), RPT_2 ( 70, 0, 14 ), + RPT_2 ( -70, 0, 14 ), RPT_2 ( 71, 0, 14 ), + RPT_2 ( -71, 0, 14 ), RPT_2 ( 72, 0, 14 ), + RPT_2 ( -72, 0, 14 ), RPT_2 ( 73, 0, 14 ), + RPT_2 ( -73, 0, 14 ), RPT_2 ( 74, 0, 14 ), + RPT_2 ( -74, 0, 14 ), RPT_2 ( 75, 0, 14 ), + RPT_2 ( -75, 0, 14 ), RPT_2 ( 76, 0, 14 ), + RPT_2 ( -76, 0, 14 ), RPT_2 ( 77, 0, 14 ), + RPT_2 ( -77, 0, 14 ), RPT_2 ( 78, 0, 14 ), + RPT_2 ( -78, 0, 14 ), RPT_2 ( 79, 0, 14 ), + RPT_2 ( -79, 0, 14 ), RPT_2 ( 80, 0, 14 ), + RPT_2 ( -80, 0, 14 ), RPT_2 ( 81, 0, 14 ), + RPT_2 ( -81, 0, 14 ), RPT_2 ( 82, 0, 14 ), + RPT_2 ( -82, 0, 14 ), RPT_2 ( 83, 0, 14 ), + RPT_2 ( -83, 0, 14 ), RPT_2 ( 84, 0, 14 ), + RPT_2 ( -84, 0, 14 ), RPT_2 ( 85, 0, 14 ), + RPT_2 ( -85, 0, 14 ), RPT_2 ( 86, 0, 14 ), + RPT_2 ( -86, 0, 14 ), RPT_2 ( 87, 0, 14 ), + RPT_2 ( -87, 0, 14 ), RPT_2 ( 88, 0, 14 ), + RPT_2 ( -88, 0, 14 ), RPT_2 ( 89, 0, 14 ), + RPT_2 ( -89, 0, 14 ), RPT_2 ( 90, 0, 14 ), + RPT_2 ( -90, 0, 14 ), RPT_2 ( 91, 0, 14 ), + RPT_2 ( -91, 0, 14 ), RPT_2 ( 92, 0, 14 ), + RPT_2 ( -92, 0, 14 ), RPT_2 ( 93, 0, 14 ), + RPT_2 ( -93, 0, 14 ), RPT_2 ( 94, 0, 14 ), + RPT_2 ( -94, 0, 14 ), RPT_2 ( 95, 0, 14 ), + RPT_2 ( -95, 0, 14 ), RPT_2 ( 96, 0, 14 ), + RPT_2 ( -96, 0, 14 ), RPT_2 ( 97, 0, 14 ), + RPT_2 ( -97, 0, 14 ), RPT_2 ( 98, 0, 14 ), + RPT_2 ( -98, 0, 14 ), RPT_2 ( 99, 0, 14 ), + RPT_2 ( -99, 0, 14 ), RPT_2 ( 100, 0, 14 ), + RPT_2 (-100, 0, 14 ), RPT_2 ( 101, 0, 14 ), + RPT_2 (-101, 0, 14 ), RPT_2 ( 102, 0, 14 ), + RPT_2 (-102, 0, 14 ), RPT_2 ( 103, 0, 14 ), + RPT_2 (-103, 0, 14 ), RPT_2 ( 104, 0, 14 ), + RPT_2 (-104, 0, 14 ), RPT_2 ( 105, 0, 14 ), + RPT_2 (-105, 0, 14 ), RPT_2 ( 106, 0, 14 ), + RPT_2 (-106, 0, 14 ), RPT_2 ( 107, 0, 14 ), + RPT_2 (-107, 0, 14 ), RPT_2 ( 108, 0, 14 ), + RPT_2 (-108, 0, 14 ), RPT_2 ( 109, 0, 14 ), + RPT_2 (-109, 0, 14 ), RPT_2 ( 110, 0, 14 ), + RPT_2 (-110, 0, 14 ), RPT_2 ( 111, 0, 14 ), + RPT_2 (-111, 0, 14 ), RPT_2 ( 112, 0, 14 ), + RPT_2 (-112, 0, 14 ), RPT_2 ( 113, 0, 14 ), + RPT_2 (-113, 0, 14 ), RPT_2 ( 114, 0, 14 ), + RPT_2 (-114, 0, 14 ), RPT_2 ( 115, 0, 14 ), + RPT_2 (-115, 0, 14 ), RPT_2 ( 116, 0, 14 ), + RPT_2 (-116, 0, 14 ), RPT_2 ( 117, 0, 14 ), + RPT_2 (-117, 0, 14 ), RPT_2 ( 118, 0, 14 ), + RPT_2 (-118, 0, 14 ), RPT_2 ( 119, 0, 14 ), + RPT_2 (-119, 0, 14 ), RPT_2 ( 120, 0, 14 ), + RPT_2 (-120, 0, 14 ), RPT_2 ( 121, 0, 14 ), + RPT_2 (-121, 0, 14 ), RPT_2 ( 122, 0, 14 ), + RPT_2 (-122, 0, 14 ), RPT_2 ( 123, 0, 14 ), + RPT_2 (-123, 0, 14 ), RPT_2 ( 124, 0, 14 ), + RPT_2 (-124, 0, 14 ), RPT_2 ( 125, 0, 14 ), + RPT_2 (-125, 0, 14 ), RPT_2 ( 126, 0, 14 ), + RPT_2 (-126, 0, 14 ), RPT_2 ( 127, 0, 14 ), + RPT_2 (-127, 0, 14 ), RPT_2 ( 128, 0, 14 ), + RPT_2 (-128, 0, 14 ), RPT_2 ( 129, 0, 14 ), + RPT_2 (-129, 0, 14 ), RPT_2 ( 130, 0, 14 ), + RPT_2 (-130, 0, 14 ), RPT_2 ( 131, 0, 14 ), + RPT_2 (-131, 0, 14 ), RPT_2 ( 132, 0, 14 ), + RPT_2 (-132, 0, 14 ), RPT_2 ( 133, 0, 14 ), + RPT_2 (-133, 0, 14 ), RPT_2 ( 134, 0, 14 ), + RPT_2 (-134, 0, 14 ), RPT_2 ( 135, 0, 14 ), + RPT_2 (-135, 0, 14 ), RPT_2 ( 136, 0, 14 ), + RPT_2 (-136, 0, 14 ), RPT_2 ( 137, 0, 14 ), + RPT_2 (-137, 0, 14 ), RPT_2 ( 138, 0, 14 ), + RPT_2 (-138, 0, 14 ), RPT_2 ( 139, 0, 14 ), + RPT_2 (-139, 0, 14 ), RPT_2 ( 140, 0, 14 ), + RPT_2 (-140, 0, 14 ), RPT_2 ( 141, 0, 14 ), + RPT_2 (-141, 0, 14 ), RPT_2 ( 142, 0, 14 ), + RPT_2 (-142, 0, 14 ), RPT_2 ( 143, 0, 14 ), + RPT_2 (-143, 0, 14 ), RPT_2 ( 144, 0, 14 ), + RPT_2 (-144, 0, 14 ), RPT_2 ( 145, 0, 14 ), + RPT_2 (-145, 0, 14 ), RPT_2 ( 146, 0, 14 ), + RPT_2 (-146, 0, 14 ), RPT_2 ( 147, 0, 14 ), + RPT_2 (-147, 0, 14 ), RPT_2 ( 148, 0, 14 ), + RPT_2 (-148, 0, 14 ), RPT_2 ( 149, 0, 14 ), + RPT_2 (-149, 0, 14 ), RPT_2 ( 150, 0, 14 ), + RPT_2 (-150, 0, 14 ), RPT_2 ( 151, 0, 14 ), + RPT_2 (-151, 0, 14 ), RPT_2 ( 152, 0, 14 ), + RPT_2 (-152, 0, 14 ), RPT_2 ( 153, 0, 14 ), + RPT_2 (-153, 0, 14 ), RPT_2 ( 154, 0, 14 ), + RPT_2 (-154, 0, 14 ), RPT_2 ( 155, 0, 14 ), + RPT_2 (-155, 0, 14 ), RPT_2 ( 156, 0, 14 ), + RPT_2 (-156, 0, 14 ), RPT_2 ( 157, 0, 14 ), + RPT_2 (-157, 0, 14 ), RPT_2 ( 158, 0, 14 ), + RPT_2 (-158, 0, 14 ), RPT_2 ( 159, 0, 14 ), + RPT_2 (-159, 0, 14 ), RPT_2 ( 160, 0, 14 ), + RPT_2 (-160, 0, 14 ), RPT_2 ( 161, 0, 14 ), + RPT_2 (-161, 0, 14 ), RPT_2 ( 162, 0, 14 ), + RPT_2 (-162, 0, 14 ), RPT_2 ( 163, 0, 14 ), + RPT_2 (-163, 0, 14 ), RPT_2 ( 164, 0, 14 ), + RPT_2 (-164, 0, 14 ), RPT_2 ( 165, 0, 14 ), + RPT_2 (-165, 0, 14 ), RPT_2 ( 166, 0, 14 ), + RPT_2 (-166, 0, 14 ), RPT_2 ( 167, 0, 14 ), + RPT_2 (-167, 0, 14 ), RPT_2 ( 168, 0, 14 ), + RPT_2 (-168, 0, 14 ), RPT_2 ( 169, 0, 14 ), + RPT_2 (-169, 0, 14 ), RPT_2 ( 170, 0, 14 ), + RPT_2 (-170, 0, 14 ), RPT_2 ( 171, 0, 14 ), + RPT_2 (-171, 0, 14 ), RPT_2 ( 172, 0, 14 ), + RPT_2 (-172, 0, 14 ), RPT_2 ( 173, 0, 14 ), + RPT_2 (-173, 0, 14 ), RPT_2 ( 174, 0, 14 ), + RPT_2 (-174, 0, 14 ), RPT_2 ( 175, 0, 14 ), + RPT_2 (-175, 0, 14 ), RPT_2 ( 176, 0, 14 ), + RPT_2 (-176, 0, 14 ), RPT_2 ( 177, 0, 14 ), + RPT_2 (-177, 0, 14 ), RPT_2 ( 178, 0, 14 ), + RPT_2 (-178, 0, 14 ), RPT_2 ( 179, 0, 14 ), + RPT_2 (-179, 0, 14 ), RPT_2 ( 180, 0, 14 ), + RPT_2 (-180, 0, 14 ), RPT_2 ( 181, 0, 14 ), + RPT_2 (-181, 0, 14 ), RPT_2 ( 182, 0, 14 ), + RPT_2 (-182, 0, 14 ), RPT_2 ( 183, 0, 14 ), + RPT_2 (-183, 0, 14 ), RPT_2 ( 184, 0, 14 ), + RPT_2 (-184, 0, 14 ), RPT_2 ( 185, 0, 14 ), + RPT_2 (-185, 0, 14 ), RPT_2 ( 186, 0, 14 ), + RPT_2 (-186, 0, 14 ), RPT_2 ( 187, 0, 14 ), + RPT_2 (-187, 0, 14 ), RPT_2 ( 188, 0, 14 ), + RPT_2 (-188, 0, 14 ), RPT_2 ( 189, 0, 14 ), + RPT_2 (-189, 0, 14 ), RPT_2 ( 190, 0, 14 ), + RPT_2 (-190, 0, 14 ), RPT_2 ( 191, 0, 14 ), + RPT_2 (-191, 0, 14 ), RPT_2 ( 192, 0, 14 ), + RPT_2 (-192, 0, 14 ), RPT_2 ( 193, 0, 14 ), + RPT_2 (-193, 0, 14 ), RPT_2 ( 194, 0, 14 ), + RPT_2 (-194, 0, 14 ), RPT_2 ( 195, 0, 14 ), + RPT_2 (-195, 0, 14 ), RPT_2 ( 196, 0, 14 ), + RPT_2 (-196, 0, 14 ), RPT_2 ( 197, 0, 14 ), + RPT_2 (-197, 0, 14 ), RPT_2 ( 198, 0, 14 ), + RPT_2 (-198, 0, 14 ), RPT_2 ( 199, 0, 14 ), + RPT_2 (-199, 0, 14 ), RPT_2 ( 200, 0, 14 ), + RPT_2 (-200, 0, 14 ), RPT_2 ( 201, 0, 14 ), + RPT_2 (-201, 0, 14 ), RPT_2 ( 202, 0, 14 ), + RPT_2 (-202, 0, 14 ), RPT_2 ( 203, 0, 14 ), + RPT_2 (-203, 0, 14 ), RPT_2 ( 204, 0, 14 ), + RPT_2 (-204, 0, 14 ), RPT_2 ( 205, 0, 14 ), + RPT_2 (-205, 0, 14 ), RPT_2 ( 206, 0, 14 ), + RPT_2 (-206, 0, 14 ), RPT_2 ( 207, 0, 14 ), + RPT_2 (-207, 0, 14 ), RPT_2 ( 208, 0, 14 ), + RPT_2 (-208, 0, 14 ), RPT_2 ( 209, 0, 14 ), + RPT_2 (-209, 0, 14 ), RPT_2 ( 210, 0, 14 ), + RPT_2 (-210, 0, 14 ), RPT_2 ( 211, 0, 14 ), + RPT_2 (-211, 0, 14 ), RPT_2 ( 212, 0, 14 ), + RPT_2 (-212, 0, 14 ), RPT_2 ( 213, 0, 14 ), + RPT_2 (-213, 0, 14 ), RPT_2 ( 214, 0, 14 ), + RPT_2 (-214, 0, 14 ), RPT_2 ( 215, 0, 14 ), + RPT_2 (-215, 0, 14 ), RPT_2 ( 216, 0, 14 ), + RPT_2 (-216, 0, 14 ), RPT_2 ( 217, 0, 14 ), + RPT_2 (-217, 0, 14 ), RPT_2 ( 218, 0, 14 ), + RPT_2 (-218, 0, 14 ), RPT_2 ( 219, 0, 14 ), + RPT_2 (-219, 0, 14 ), RPT_2 ( 220, 0, 14 ), + RPT_2 (-220, 0, 14 ), RPT_2 ( 221, 0, 14 ), + RPT_2 (-221, 0, 14 ), RPT_2 ( 222, 0, 14 ), + RPT_2 (-222, 0, 14 ), RPT_2 ( 223, 0, 14 ), + RPT_2 (-223, 0, 14 ), RPT_2 ( 224, 0, 14 ), + RPT_2 (-224, 0, 14 ), RPT_2 ( 225, 0, 14 ), + RPT_2 (-225, 0, 14 ), RPT_2 ( 226, 0, 14 ), + RPT_2 (-226, 0, 14 ), RPT_2 ( 227, 0, 14 ), + RPT_2 (-227, 0, 14 ), RPT_2 ( 228, 0, 14 ), + RPT_2 (-228, 0, 14 ), RPT_2 ( 229, 0, 14 ), + RPT_2 (-229, 0, 14 ), RPT_2 ( 230, 0, 14 ), + RPT_2 (-230, 0, 14 ), RPT_2 ( 231, 0, 14 ), + RPT_2 (-231, 0, 14 ), RPT_2 ( 232, 0, 14 ), + RPT_2 (-232, 0, 14 ), RPT_2 ( 233, 0, 14 ), + RPT_2 (-233, 0, 14 ), RPT_2 ( 234, 0, 14 ), + RPT_2 (-234, 0, 14 ), RPT_2 ( 235, 0, 14 ), + RPT_2 (-235, 0, 14 ), RPT_2 ( 236, 0, 14 ), + RPT_2 (-236, 0, 14 ), RPT_2 ( 237, 0, 14 ), + RPT_2 (-237, 0, 14 ), RPT_2 ( 238, 0, 14 ), + RPT_2 (-238, 0, 14 ), RPT_2 ( 239, 0, 14 ), + RPT_2 (-239, 0, 14 ), RPT_2 ( 240, 0, 14 ), + RPT_2 (-240, 0, 14 ), RPT_2 ( 241, 0, 14 ), + RPT_2 (-241, 0, 14 ), RPT_2 ( 242, 0, 14 ), + RPT_2 (-242, 0, 14 ), RPT_2 ( 243, 0, 14 ), + RPT_2 (-243, 0, 14 ), RPT_2 ( 244, 0, 14 ), + RPT_2 (-244, 0, 14 ), RPT_2 ( 245, 0, 14 ), + RPT_2 (-245, 0, 14 ), RPT_2 ( 246, 0, 14 ), + RPT_2 (-246, 0, 14 ), RPT_2 ( 247, 0, 14 ), + RPT_2 (-247, 0, 14 ), RPT_2 ( 248, 0, 14 ), + RPT_2 (-248, 0, 14 ), RPT_2 ( 249, 0, 14 ), + RPT_2 (-249, 0, 14 ), RPT_2 ( 250, 0, 14 ), + RPT_2 (-250, 0, 14 ), RPT_2 ( 251, 0, 14 ), + RPT_2 (-251, 0, 14 ), RPT_2 ( 252, 0, 14 ), + RPT_2 (-252, 0, 14 ), RPT_2 ( 253, 0, 14 ), + RPT_2 (-253, 0, 14 ), RPT_2 ( 254, 0, 14 ), + RPT_2 (-254, 0, 14 ), RPT_2 ( 255, 0, 14 ), + RPT_2 (-255, 0, 14 ), { 0, 0, 15 }, { 0, 1, 15 }, + { 0, 2, 15 }, { 0, 3, 15 }, { 0, 4, 15 }, { 0, 5, 15 }, + { 0, 6, 15 }, { 0, 7, 15 }, { 0, 8, 15 }, { 0, 9, 15 }, + { 0, 10, 15 }, { 0, 11, 15 }, { 0, 12, 15 }, { 0, 13, 15 }, + { 0, 14, 15 }, { 0, 15, 15 }, { 0, 16, 15 }, { 0, 17, 15 }, + { 0, 18, 15 }, { 0, 19, 15 }, { 0, 20, 15 }, { 0, 21, 15 }, + { 0, 22, 15 }, { 0, 23, 15 }, { 0, 24, 15 }, { 0, 25, 15 }, + { 0, 26, 15 }, { 0, 27, 15 }, { 0, 28, 15 }, { 0, 29, 15 }, + { 0, 30, 15 }, { 0, 31, 15 }, { 0, 32, 15 }, { 0, 33, 15 }, + { 0, 34, 15 }, { 0, 35, 15 }, { 0, 36, 15 }, { 0, 37, 15 }, + { 0, 38, 15 }, { 0, 39, 15 }, { 0, 40, 15 }, { 0, 41, 15 }, + { 0, 42, 15 }, { 0, 43, 15 }, { 0, 44, 15 }, { 0, 45, 15 }, + { 0, 46, 15 }, { 0, 47, 15 }, { 0, 48, 15 }, { 0, 49, 15 }, + { 0, 50, 15 }, { 0, 51, 15 }, { 0, 52, 15 }, { 0, 53, 15 }, + { 0, 54, 15 }, { 0, 55, 15 }, { 0, 56, 15 }, { 0, 57, 15 }, + { 0, 58, 15 }, { 0, 59, 15 }, { 0, 60, 15 }, { 0, 61, 15 }, + { 0, 62, 15 }, { 0, 63, 15 }, RPT_16 ( 51, 0, 11 ), + RPT_16 ( -51, 0, 11 ), RPT_16 ( 52, 0, 11 ), + RPT_16 ( -52, 0, 11 ), RPT_16 ( 53, 0, 11 ), + RPT_16 ( -53, 0, 11 ), RPT_16 ( 54, 0, 11 ), + RPT_16 ( -54, 0, 11 ), RPT_16 ( 55, 0, 11 ), + RPT_16 ( -55, 0, 11 ), RPT_16 ( 56, 0, 11 ), + RPT_16 ( -56, 0, 11 ), RPT_16 ( 57, 0, 11 ), + RPT_16 ( -57, 0, 11 ), RPT_16 ( 58, 0, 11 ), + RPT_16 ( -58, 0, 11 ), RPT_16 ( 59, 0, 11 ), + RPT_16 ( -59, 0, 11 ), RPT_16 ( 60, 0, 11 ), + RPT_16 ( -60, 0, 11 ), RPT_16 ( 61, 0, 11 ), + RPT_16 ( -61, 0, 11 ), RPT_16 ( 62, 0, 11 ), + RPT_16 ( -62, 0, 11 ), RPT_16 ( 63, 0, 11 ), + RPT_16 ( -63, 0, 11 ), RPT_16 ( 11, 1, 11 ), + RPT_16 ( -11, 1, 11 ), RPT_16 ( 12, 1, 11 ), + RPT_16 ( -12, 1, 11 ), RPT_16 ( 13, 1, 11 ), + RPT_16 ( -13, 1, 11 ), RPT_16 ( 14, 1, 11 ), + RPT_16 ( -14, 1, 11 ), RPT_16 ( 4, 2, 11 ), + RPT_16 ( -4, 2, 11 ), RPT_16 ( 5, 2, 11 ), + RPT_16 ( -5, 2, 11 ), RPT_16 ( 6, 2, 11 ), + RPT_16 ( -6, 2, 11 ), RPT_16 ( 3, 3, 11 ), + RPT_16 ( -3, 3, 11 ), RPT_16 ( 2, 4, 11 ), + RPT_16 ( -2, 4, 11 ), RPT_16 ( 1, 9, 11 ), + RPT_16 ( -1, 9, 11 ), RPT_16 ( 1, 10, 11 ), + RPT_16 ( -1, 10, 11 ), RPT_8 ( 15, 1, 12 ), + RPT_8 ( -15, 1, 12 ), RPT_8 ( 16, 1, 12 ), + RPT_8 ( -16, 1, 12 ), RPT_8 ( 17, 1, 12 ), + RPT_8 ( -17, 1, 12 ), RPT_8 ( 18, 1, 12 ), + RPT_8 ( -18, 1, 12 ), RPT_8 ( 7, 2, 12 ), + RPT_8 ( -7, 2, 12 ), RPT_8 ( 8, 2, 12 ), + RPT_8 ( -8, 2, 12 ), RPT_8 ( 9, 2, 12 ), + RPT_8 ( -9, 2, 12 ), RPT_8 ( 10, 2, 12 ), + RPT_8 ( -10, 2, 12 ), RPT_8 ( 4, 3, 12 ), + RPT_8 ( -4, 3, 12 ), RPT_8 ( 5, 3, 12 ), + RPT_8 ( -5, 3, 12 ), RPT_8 ( 6, 3, 12 ), + RPT_8 ( -6, 3, 12 ), RPT_8 ( 2, 5, 12 ), + RPT_8 ( -2, 5, 12 ), RPT_16 ( 0, 7, 11 ), + RPT_16 ( 0, 8, 11 ), RPT_16 ( 0, 9, 11 ), + RPT_16 ( 0, 10, 11 ), RPT_8 ( 1, 11, 12 ), + RPT_8 ( -1, 11, 12 ), RPT_8 ( 1, 12, 12 ), + RPT_8 ( -1, 12, 12 ), RPT_8 ( 1, 13, 12 ), + RPT_8 ( -1, 13, 12 ), RPT_8 ( 1, 14, 12 ), + RPT_8 ( -1, 14, 12 ), RPT_4 ( 19, 1, 13 ), + RPT_4 ( -19, 1, 13 ), RPT_4 ( 20, 1, 13 ), + RPT_4 ( -20, 1, 13 ), RPT_4 ( 3, 4, 13 ), + RPT_4 ( -3, 4, 13 ), RPT_4 ( 2, 6, 13 ), + RPT_4 ( -2, 6, 13 ), +}; + +static const HQXLUT ac8_lut[] = { + RPT_128 ( 1, 0, 4 ), RPT_128 ( -1, 0, 4 ), + RPT_128 ( 2, 0, 4 ), RPT_128 ( -2, 0, 4 ), + RPT_64 ( 3, 0, 5 ), RPT_64 ( -3, 0, 5 ), + RPT_64 ( 4, 0, 5 ), RPT_64 ( -4, 0, 5 ), + RPT_128 ( 0, 64, 4 ), RPT_32 ( 5, 0, 6 ), + RPT_32 ( -5, 0, 6 ), RPT_32 ( 6, 0, 6 ), + RPT_32 ( -6, 0, 6 ), RPT_32 ( 7, 0, 6 ), + RPT_32 ( -7, 0, 6 ), RPT_32 ( 8, 0, 6 ), + RPT_32 ( -8, 0, 6 ), RPT_32 ( 1, 1, 6 ), + RPT_32 ( -1, 1, 6 ), RPT_32 ( 2, 1, 6 ), + RPT_32 ( -2, 1, 6 ), RPT_16 ( 9, 0, 7 ), + RPT_16 ( -9, 0, 7 ), RPT_16 ( 10, 0, 7 ), + RPT_16 ( -10, 0, 7 ), RPT_16 ( 11, 0, 7 ), + RPT_16 ( -11, 0, 7 ), RPT_16 ( 12, 0, 7 ), + RPT_16 ( -12, 0, 7 ), RPT_16 ( 3, 1, 7 ), + RPT_16 ( -3, 1, 7 ), RPT_16 ( 4, 1, 7 ), + RPT_16 ( -4, 1, 7 ), RPT_16 ( 1, 2, 7 ), + RPT_16 ( -1, 2, 7 ), { 2048, 0, -1 }, { 2112, 0, -1 }, + { 2176, 0, -1 }, { 2240, 0, -1 }, { 2304, 0, -1 }, { 2368, 0, -1 }, + { 2432, 0, -1 }, { 2496, 0, -1 }, { 2560, 0, -1 }, { 2624, 0, -1 }, + { 2688, 0, -1 }, { 2752, 0, -1 }, { 2816, 0, -1 }, { 2880, 0, -1 }, + { 2944, 0, -1 }, { 3008, 0, -1 }, { 3072, 0, -1 }, { 3136, 0, -1 }, + { 3200, 0, -1 }, { 3264, 0, -1 }, { 3328, 0, -1 }, { 3392, 0, -1 }, + { 3456, 0, -1 }, { 3520, 0, -1 }, { 3584, 0, -1 }, { 3648, 0, -1 }, + { 3712, 0, -1 }, { 3776, 0, -1 }, { 3840, 0, -1 }, { 3904, 0, -1 }, + { 3968, 0, -1 }, { 4032, 0, -1 }, RPT_8 ( 13, 0, 8 ), + RPT_8 ( -13, 0, 8 ), RPT_8 ( 14, 0, 8 ), + RPT_8 ( -14, 0, 8 ), RPT_8 ( 15, 0, 8 ), + RPT_8 ( -15, 0, 8 ), RPT_8 ( 16, 0, 8 ), + RPT_8 ( -16, 0, 8 ), RPT_8 ( 17, 0, 8 ), + RPT_8 ( -17, 0, 8 ), RPT_8 ( 18, 0, 8 ), + RPT_8 ( -18, 0, 8 ), RPT_8 ( 5, 1, 8 ), + RPT_8 ( -5, 1, 8 ), RPT_8 ( 6, 1, 8 ), + RPT_8 ( -6, 1, 8 ), RPT_8 ( 2, 2, 8 ), + RPT_8 ( -2, 2, 8 ), RPT_8 ( 1, 3, 8 ), + RPT_8 ( -1, 3, 8 ), RPT_8 ( 0, 0, 8 ), + RPT_4 ( 19, 0, 9 ), RPT_4 ( -19, 0, 9 ), + RPT_4 ( 20, 0, 9 ), RPT_4 ( -20, 0, 9 ), + RPT_4 ( 21, 0, 9 ), RPT_4 ( -21, 0, 9 ), + RPT_4 ( 22, 0, 9 ), RPT_4 ( -22, 0, 9 ), + RPT_4 ( 23, 0, 9 ), RPT_4 ( -23, 0, 9 ), + RPT_4 ( 24, 0, 9 ), RPT_4 ( -24, 0, 9 ), + RPT_4 ( 25, 0, 9 ), RPT_4 ( -25, 0, 9 ), + RPT_4 ( 7, 1, 9 ), RPT_4 ( -7, 1, 9 ), + RPT_4 ( 8, 1, 9 ), RPT_4 ( -8, 1, 9 ), + RPT_4 ( 3, 2, 9 ), RPT_4 ( -3, 2, 9 ), + RPT_4 ( 2, 3, 9 ), RPT_4 ( -2, 3, 9 ), + RPT_4 ( 1, 4, 9 ), RPT_4 ( -1, 4, 9 ), + RPT_4 ( 1, 5, 9 ), RPT_4 ( -1, 5, 9 ), + RPT_2 ( 26, 0, 10 ), RPT_2 ( -26, 0, 10 ), + RPT_2 ( 27, 0, 10 ), RPT_2 ( -27, 0, 10 ), + RPT_2 ( 28, 0, 10 ), RPT_2 ( -28, 0, 10 ), + RPT_2 ( 29, 0, 10 ), RPT_2 ( -29, 0, 10 ), + RPT_2 ( 30, 0, 10 ), RPT_2 ( -30, 0, 10 ), + RPT_2 ( 31, 0, 10 ), RPT_2 ( -31, 0, 10 ), + RPT_2 ( 32, 0, 10 ), RPT_2 ( -32, 0, 10 ), + RPT_2 ( 33, 0, 10 ), RPT_2 ( -33, 0, 10 ), + RPT_2 ( 34, 0, 10 ), RPT_2 ( -34, 0, 10 ), + RPT_2 ( 35, 0, 10 ), RPT_2 ( -35, 0, 10 ), + RPT_2 ( 36, 0, 10 ), RPT_2 ( -36, 0, 10 ), + RPT_4 ( 0, 1, 9 ), RPT_2 ( 9, 1, 10 ), + RPT_2 ( -9, 1, 10 ), RPT_2 ( 10, 1, 10 ), + RPT_2 ( -10, 1, 10 ), RPT_2 ( 11, 1, 10 ), + RPT_2 ( -11, 1, 10 ), RPT_2 ( 12, 1, 10 ), + RPT_2 ( -12, 1, 10 ), RPT_4 ( 0, 2, 9 ), + RPT_2 ( 4, 2, 10 ), RPT_2 ( -4, 2, 10 ), + RPT_2 ( 5, 2, 10 ), RPT_2 ( -5, 2, 10 ), + RPT_2 ( 6, 2, 10 ), RPT_2 ( -6, 2, 10 ), + RPT_4 ( 0, 3, 9 ), RPT_2 ( 3, 3, 10 ), + RPT_2 ( -3, 3, 10 ), RPT_2 ( 4, 3, 10 ), + RPT_2 ( -4, 3, 10 ), RPT_4 ( 0, 4, 9 ), + RPT_2 ( 2, 4, 10 ), RPT_2 ( -2, 4, 10 ), + RPT_4 ( 0, 5, 9 ), RPT_2 ( 1, 6, 10 ), + RPT_2 ( -1, 6, 10 ), RPT_2 ( 1, 7, 10 ), + RPT_2 ( -1, 7, 10 ), RPT_2 ( 1, 8, 10 ), + RPT_2 ( -1, 8, 10 ), { 37, 0, 11 }, { -37, 0, 11 }, + { 38, 0, 11 }, { -38, 0, 11 }, { 39, 0, 11 }, { -39, 0, 11 }, + { 40, 0, 11 }, { -40, 0, 11 }, { 41, 0, 11 }, { -41, 0, 11 }, + { 42, 0, 11 }, { -42, 0, 11 }, { 43, 0, 11 }, { -43, 0, 11 }, + { 44, 0, 11 }, { -44, 0, 11 }, { 45, 0, 11 }, { -45, 0, 11 }, + { 46, 0, 11 }, { -46, 0, 11 }, { 47, 0, 11 }, { -47, 0, 11 }, + { 48, 0, 11 }, { -48, 0, 11 }, { 13, 1, 11 }, { -13, 1, 11 }, + { 14, 1, 11 }, { -14, 1, 11 }, { 15, 1, 11 }, { -15, 1, 11 }, + { 16, 1, 11 }, { -16, 1, 11 }, { 7, 2, 11 }, { -7, 2, 11 }, + { 8, 2, 11 }, { -8, 2, 11 }, { 5, 3, 11 }, { -5, 3, 11 }, + { 6, 3, 11 }, { -6, 3, 11 }, { 3, 4, 11 }, { -3, 4, 11 }, + { 4, 4, 11 }, { -4, 4, 11 }, { 2, 5, 11 }, { -2, 5, 11 }, + RPT_2 ( 0, 6, 10 ), { 2, 6, 11 }, { -2, 6, 11 }, + RPT_2 ( 0, 7, 10 ), RPT_2 ( 0, 8, 10 ), + RPT_2 ( 0, 9, 10 ), { 1, 9, 11 }, { -1, 9, 11 }, + { 1, 10, 11 }, { -1, 10, 11 }, { 1, 11, 11 }, { -1, 11, 11 }, + { 1, 12, 11 }, { -1, 12, 11 }, { 4096, 0, -1 }, { 4160, 0, -1 }, + { 4224, 0, -1 }, { 4288, 0, -1 }, { 4352, 0, -1 }, { 4416, 0, -1 }, + { 4480, 0, -1 }, { 4544, 0, -1 }, { 4608, 0, -1 }, { 4672, 0, -1 }, + { 4736, 0, -1 }, { 4800, 0, -1 }, { 4864, 0, -1 }, { 4928, 0, -1 }, + { 4992, 0, -1 }, { 5056, 0, -1 }, { 5120, 0, -1 }, { 5184, 0, -1 }, + { 5248, 0, -1 }, { 5312, 0, -1 }, { 5376, 0, -1 }, { 5440, 0, -1 }, + { 5504, 0, -1 }, { 5568, 0, -1 }, { 5632, 0, -1 }, { 5696, 0, -1 }, + { 5760, 0, -1 }, { 5824, 0, -1 }, { 5888, 0, -1 }, { 5952, 0, -1 }, + { 6016, 0, -1 }, { 6080, 0, -1 }, { 6144, 0, -1 }, { 6208, 0, -1 }, + { 6272, 0, -1 }, { 6336, 0, -1 }, { 6400, 0, -1 }, { 6464, 0, -1 }, + { 6528, 0, -1 }, { 6592, 0, -1 }, { 0, 10, 11 }, { 6656, 0, -1 }, + { 0, 11, 11 }, { 0, 12, 11 }, { 0, 13, 11 }, { 6720, 0, -1 }, + { 6784, 0, -1 }, { 6848, 0, -1 }, { 6912, 0, -1 }, { 6976, 0, -1 }, + { 7040, 0, -1 }, { 7104, 0, -1 }, { 7168, 0, -1 }, { 7232, 0, -1 }, + { 7296, 0, -1 }, { 7360, 0, -1 }, { 7424, 0, -1 }, { 7488, 0, -1 }, + { 7552, 0, -1 }, { 7616, 0, -1 }, RPT_8 ( 0, 0, 14 ), + RPT_4 ( 1, 0, 15 ), RPT_4 ( -1, 0, 15 ), + RPT_4 ( 2, 0, 15 ), RPT_4 ( -2, 0, 15 ), + RPT_4 ( 3, 0, 15 ), RPT_4 ( -3, 0, 15 ), + RPT_4 ( 4, 0, 15 ), RPT_4 ( -4, 0, 15 ), + RPT_4 ( 5, 0, 15 ), RPT_4 ( -5, 0, 15 ), + RPT_4 ( 6, 0, 15 ), RPT_4 ( -6, 0, 15 ), + RPT_4 ( 7, 0, 15 ), RPT_4 ( -7, 0, 15 ), + RPT_4 ( 8, 0, 15 ), RPT_4 ( -8, 0, 15 ), + RPT_4 ( 9, 0, 15 ), RPT_4 ( -9, 0, 15 ), + RPT_4 ( 10, 0, 15 ), RPT_4 ( -10, 0, 15 ), + RPT_4 ( 11, 0, 15 ), RPT_4 ( -11, 0, 15 ), + RPT_4 ( 12, 0, 15 ), RPT_4 ( -12, 0, 15 ), + RPT_4 ( 13, 0, 15 ), RPT_4 ( -13, 0, 15 ), + RPT_4 ( 14, 0, 15 ), RPT_4 ( -14, 0, 15 ), + RPT_4 ( 15, 0, 15 ), RPT_4 ( -15, 0, 15 ), + RPT_4 ( 16, 0, 15 ), RPT_4 ( -16, 0, 15 ), + RPT_4 ( 17, 0, 15 ), RPT_4 ( -17, 0, 15 ), + RPT_4 ( 18, 0, 15 ), RPT_4 ( -18, 0, 15 ), + RPT_4 ( 19, 0, 15 ), RPT_4 ( -19, 0, 15 ), + RPT_4 ( 20, 0, 15 ), RPT_4 ( -20, 0, 15 ), + RPT_4 ( 21, 0, 15 ), RPT_4 ( -21, 0, 15 ), + RPT_4 ( 22, 0, 15 ), RPT_4 ( -22, 0, 15 ), + RPT_4 ( 23, 0, 15 ), RPT_4 ( -23, 0, 15 ), + RPT_4 ( 24, 0, 15 ), RPT_4 ( -24, 0, 15 ), + RPT_4 ( 25, 0, 15 ), RPT_4 ( -25, 0, 15 ), + RPT_4 ( 26, 0, 15 ), RPT_4 ( -26, 0, 15 ), + RPT_4 ( 27, 0, 15 ), RPT_4 ( -27, 0, 15 ), + RPT_4 ( 28, 0, 15 ), RPT_4 ( -28, 0, 15 ), + RPT_4 ( 29, 0, 15 ), RPT_4 ( -29, 0, 15 ), + RPT_4 ( 30, 0, 15 ), RPT_4 ( -30, 0, 15 ), + RPT_4 ( 31, 0, 15 ), RPT_4 ( -31, 0, 15 ), + RPT_4 ( 32, 0, 15 ), RPT_4 ( -32, 0, 15 ), + RPT_4 ( 33, 0, 15 ), RPT_4 ( -33, 0, 15 ), + RPT_4 ( 34, 0, 15 ), RPT_4 ( -34, 0, 15 ), + RPT_4 ( 35, 0, 15 ), RPT_4 ( -35, 0, 15 ), + RPT_4 ( 36, 0, 15 ), RPT_4 ( -36, 0, 15 ), + RPT_4 ( 37, 0, 15 ), RPT_4 ( -37, 0, 15 ), + RPT_4 ( 38, 0, 15 ), RPT_4 ( -38, 0, 15 ), + RPT_4 ( 39, 0, 15 ), RPT_4 ( -39, 0, 15 ), + RPT_4 ( 40, 0, 15 ), RPT_4 ( -40, 0, 15 ), + RPT_4 ( 41, 0, 15 ), RPT_4 ( -41, 0, 15 ), + RPT_4 ( 42, 0, 15 ), RPT_4 ( -42, 0, 15 ), + RPT_4 ( 43, 0, 15 ), RPT_4 ( -43, 0, 15 ), + RPT_4 ( 44, 0, 15 ), RPT_4 ( -44, 0, 15 ), + RPT_4 ( 45, 0, 15 ), RPT_4 ( -45, 0, 15 ), + RPT_4 ( 46, 0, 15 ), RPT_4 ( -46, 0, 15 ), + RPT_4 ( 47, 0, 15 ), RPT_4 ( -47, 0, 15 ), + RPT_4 ( 48, 0, 15 ), RPT_4 ( -48, 0, 15 ), + RPT_4 ( 49, 0, 15 ), RPT_4 ( -49, 0, 15 ), + RPT_4 ( 50, 0, 15 ), RPT_4 ( -50, 0, 15 ), + RPT_4 ( 51, 0, 15 ), RPT_4 ( -51, 0, 15 ), + RPT_4 ( 52, 0, 15 ), RPT_4 ( -52, 0, 15 ), + RPT_4 ( 53, 0, 15 ), RPT_4 ( -53, 0, 15 ), + RPT_4 ( 54, 0, 15 ), RPT_4 ( -54, 0, 15 ), + RPT_4 ( 55, 0, 15 ), RPT_4 ( -55, 0, 15 ), + RPT_4 ( 56, 0, 15 ), RPT_4 ( -56, 0, 15 ), + RPT_4 ( 57, 0, 15 ), RPT_4 ( -57, 0, 15 ), + RPT_4 ( 58, 0, 15 ), RPT_4 ( -58, 0, 15 ), + RPT_4 ( 59, 0, 15 ), RPT_4 ( -59, 0, 15 ), + RPT_4 ( 60, 0, 15 ), RPT_4 ( -60, 0, 15 ), + RPT_4 ( 61, 0, 15 ), RPT_4 ( -61, 0, 15 ), + RPT_4 ( 62, 0, 15 ), RPT_4 ( -62, 0, 15 ), + RPT_4 ( 63, 0, 15 ), RPT_4 ( -63, 0, 15 ), + RPT_4 ( 64, 0, 15 ), RPT_4 ( -64, 0, 15 ), + RPT_4 ( 65, 0, 15 ), RPT_4 ( -65, 0, 15 ), + RPT_4 ( 66, 0, 15 ), RPT_4 ( -66, 0, 15 ), + RPT_4 ( 67, 0, 15 ), RPT_4 ( -67, 0, 15 ), + RPT_4 ( 68, 0, 15 ), RPT_4 ( -68, 0, 15 ), + RPT_4 ( 69, 0, 15 ), RPT_4 ( -69, 0, 15 ), + RPT_4 ( 70, 0, 15 ), RPT_4 ( -70, 0, 15 ), + RPT_4 ( 71, 0, 15 ), RPT_4 ( -71, 0, 15 ), + RPT_4 ( 72, 0, 15 ), RPT_4 ( -72, 0, 15 ), + RPT_4 ( 73, 0, 15 ), RPT_4 ( -73, 0, 15 ), + RPT_4 ( 74, 0, 15 ), RPT_4 ( -74, 0, 15 ), + RPT_4 ( 75, 0, 15 ), RPT_4 ( -75, 0, 15 ), + RPT_4 ( 76, 0, 15 ), RPT_4 ( -76, 0, 15 ), + RPT_4 ( 77, 0, 15 ), RPT_4 ( -77, 0, 15 ), + RPT_4 ( 78, 0, 15 ), RPT_4 ( -78, 0, 15 ), + RPT_4 ( 79, 0, 15 ), RPT_4 ( -79, 0, 15 ), + RPT_4 ( 80, 0, 15 ), RPT_4 ( -80, 0, 15 ), + RPT_4 ( 81, 0, 15 ), RPT_4 ( -81, 0, 15 ), + RPT_4 ( 82, 0, 15 ), RPT_4 ( -82, 0, 15 ), + RPT_4 ( 83, 0, 15 ), RPT_4 ( -83, 0, 15 ), + RPT_4 ( 84, 0, 15 ), RPT_4 ( -84, 0, 15 ), + RPT_4 ( 85, 0, 15 ), RPT_4 ( -85, 0, 15 ), + RPT_4 ( 86, 0, 15 ), RPT_4 ( -86, 0, 15 ), + RPT_4 ( 87, 0, 15 ), RPT_4 ( -87, 0, 15 ), + RPT_4 ( 88, 0, 15 ), RPT_4 ( -88, 0, 15 ), + RPT_4 ( 89, 0, 15 ), RPT_4 ( -89, 0, 15 ), + RPT_4 ( 90, 0, 15 ), RPT_4 ( -90, 0, 15 ), + RPT_4 ( 91, 0, 15 ), RPT_4 ( -91, 0, 15 ), + RPT_4 ( 92, 0, 15 ), RPT_4 ( -92, 0, 15 ), + RPT_4 ( 93, 0, 15 ), RPT_4 ( -93, 0, 15 ), + RPT_4 ( 94, 0, 15 ), RPT_4 ( -94, 0, 15 ), + RPT_4 ( 95, 0, 15 ), RPT_4 ( -95, 0, 15 ), + RPT_4 ( 96, 0, 15 ), RPT_4 ( -96, 0, 15 ), + RPT_4 ( 97, 0, 15 ), RPT_4 ( -97, 0, 15 ), + RPT_4 ( 98, 0, 15 ), RPT_4 ( -98, 0, 15 ), + RPT_4 ( 99, 0, 15 ), RPT_4 ( -99, 0, 15 ), + RPT_4 ( 100, 0, 15 ), RPT_4 (-100, 0, 15 ), + RPT_4 ( 101, 0, 15 ), RPT_4 (-101, 0, 15 ), + RPT_4 ( 102, 0, 15 ), RPT_4 (-102, 0, 15 ), + RPT_4 ( 103, 0, 15 ), RPT_4 (-103, 0, 15 ), + RPT_4 ( 104, 0, 15 ), RPT_4 (-104, 0, 15 ), + RPT_4 ( 105, 0, 15 ), RPT_4 (-105, 0, 15 ), + RPT_4 ( 106, 0, 15 ), RPT_4 (-106, 0, 15 ), + RPT_4 ( 107, 0, 15 ), RPT_4 (-107, 0, 15 ), + RPT_4 ( 108, 0, 15 ), RPT_4 (-108, 0, 15 ), + RPT_4 ( 109, 0, 15 ), RPT_4 (-109, 0, 15 ), + RPT_4 ( 110, 0, 15 ), RPT_4 (-110, 0, 15 ), + RPT_4 ( 111, 0, 15 ), RPT_4 (-111, 0, 15 ), + RPT_4 ( 112, 0, 15 ), RPT_4 (-112, 0, 15 ), + RPT_4 ( 113, 0, 15 ), RPT_4 (-113, 0, 15 ), + RPT_4 ( 114, 0, 15 ), RPT_4 (-114, 0, 15 ), + RPT_4 ( 115, 0, 15 ), RPT_4 (-115, 0, 15 ), + RPT_4 ( 116, 0, 15 ), RPT_4 (-116, 0, 15 ), + RPT_4 ( 117, 0, 15 ), RPT_4 (-117, 0, 15 ), + RPT_4 ( 118, 0, 15 ), RPT_4 (-118, 0, 15 ), + RPT_4 ( 119, 0, 15 ), RPT_4 (-119, 0, 15 ), + RPT_4 ( 120, 0, 15 ), RPT_4 (-120, 0, 15 ), + RPT_4 ( 121, 0, 15 ), RPT_4 (-121, 0, 15 ), + RPT_4 ( 122, 0, 15 ), RPT_4 (-122, 0, 15 ), + RPT_4 ( 123, 0, 15 ), RPT_4 (-123, 0, 15 ), + RPT_4 ( 124, 0, 15 ), RPT_4 (-124, 0, 15 ), + RPT_4 ( 125, 0, 15 ), RPT_4 (-125, 0, 15 ), + RPT_4 ( 126, 0, 15 ), RPT_4 (-126, 0, 15 ), + RPT_4 ( 127, 0, 15 ), RPT_4 (-127, 0, 15 ), + RPT_4 ( 128, 0, 15 ), RPT_4 (-128, 0, 15 ), + RPT_4 ( 129, 0, 15 ), RPT_4 (-129, 0, 15 ), + RPT_4 ( 130, 0, 15 ), RPT_4 (-130, 0, 15 ), + RPT_4 ( 131, 0, 15 ), RPT_4 (-131, 0, 15 ), + RPT_4 ( 132, 0, 15 ), RPT_4 (-132, 0, 15 ), + RPT_4 ( 133, 0, 15 ), RPT_4 (-133, 0, 15 ), + RPT_4 ( 134, 0, 15 ), RPT_4 (-134, 0, 15 ), + RPT_4 ( 135, 0, 15 ), RPT_4 (-135, 0, 15 ), + RPT_4 ( 136, 0, 15 ), RPT_4 (-136, 0, 15 ), + RPT_4 ( 137, 0, 15 ), RPT_4 (-137, 0, 15 ), + RPT_4 ( 138, 0, 15 ), RPT_4 (-138, 0, 15 ), + RPT_4 ( 139, 0, 15 ), RPT_4 (-139, 0, 15 ), + RPT_4 ( 140, 0, 15 ), RPT_4 (-140, 0, 15 ), + RPT_4 ( 141, 0, 15 ), RPT_4 (-141, 0, 15 ), + RPT_4 ( 142, 0, 15 ), RPT_4 (-142, 0, 15 ), + RPT_4 ( 143, 0, 15 ), RPT_4 (-143, 0, 15 ), + RPT_4 ( 144, 0, 15 ), RPT_4 (-144, 0, 15 ), + RPT_4 ( 145, 0, 15 ), RPT_4 (-145, 0, 15 ), + RPT_4 ( 146, 0, 15 ), RPT_4 (-146, 0, 15 ), + RPT_4 ( 147, 0, 15 ), RPT_4 (-147, 0, 15 ), + RPT_4 ( 148, 0, 15 ), RPT_4 (-148, 0, 15 ), + RPT_4 ( 149, 0, 15 ), RPT_4 (-149, 0, 15 ), + RPT_4 ( 150, 0, 15 ), RPT_4 (-150, 0, 15 ), + RPT_4 ( 151, 0, 15 ), RPT_4 (-151, 0, 15 ), + RPT_4 ( 152, 0, 15 ), RPT_4 (-152, 0, 15 ), + RPT_4 ( 153, 0, 15 ), RPT_4 (-153, 0, 15 ), + RPT_4 ( 154, 0, 15 ), RPT_4 (-154, 0, 15 ), + RPT_4 ( 155, 0, 15 ), RPT_4 (-155, 0, 15 ), + RPT_4 ( 156, 0, 15 ), RPT_4 (-156, 0, 15 ), + RPT_4 ( 157, 0, 15 ), RPT_4 (-157, 0, 15 ), + RPT_4 ( 158, 0, 15 ), RPT_4 (-158, 0, 15 ), + RPT_4 ( 159, 0, 15 ), RPT_4 (-159, 0, 15 ), + RPT_4 ( 160, 0, 15 ), RPT_4 (-160, 0, 15 ), + RPT_4 ( 161, 0, 15 ), RPT_4 (-161, 0, 15 ), + RPT_4 ( 162, 0, 15 ), RPT_4 (-162, 0, 15 ), + RPT_4 ( 163, 0, 15 ), RPT_4 (-163, 0, 15 ), + RPT_4 ( 164, 0, 15 ), RPT_4 (-164, 0, 15 ), + RPT_4 ( 165, 0, 15 ), RPT_4 (-165, 0, 15 ), + RPT_4 ( 166, 0, 15 ), RPT_4 (-166, 0, 15 ), + RPT_4 ( 167, 0, 15 ), RPT_4 (-167, 0, 15 ), + RPT_4 ( 168, 0, 15 ), RPT_4 (-168, 0, 15 ), + RPT_4 ( 169, 0, 15 ), RPT_4 (-169, 0, 15 ), + RPT_4 ( 170, 0, 15 ), RPT_4 (-170, 0, 15 ), + RPT_4 ( 171, 0, 15 ), RPT_4 (-171, 0, 15 ), + RPT_4 ( 172, 0, 15 ), RPT_4 (-172, 0, 15 ), + RPT_4 ( 173, 0, 15 ), RPT_4 (-173, 0, 15 ), + RPT_4 ( 174, 0, 15 ), RPT_4 (-174, 0, 15 ), + RPT_4 ( 175, 0, 15 ), RPT_4 (-175, 0, 15 ), + RPT_4 ( 176, 0, 15 ), RPT_4 (-176, 0, 15 ), + RPT_4 ( 177, 0, 15 ), RPT_4 (-177, 0, 15 ), + RPT_4 ( 178, 0, 15 ), RPT_4 (-178, 0, 15 ), + RPT_4 ( 179, 0, 15 ), RPT_4 (-179, 0, 15 ), + RPT_4 ( 180, 0, 15 ), RPT_4 (-180, 0, 15 ), + RPT_4 ( 181, 0, 15 ), RPT_4 (-181, 0, 15 ), + RPT_4 ( 182, 0, 15 ), RPT_4 (-182, 0, 15 ), + RPT_4 ( 183, 0, 15 ), RPT_4 (-183, 0, 15 ), + RPT_4 ( 184, 0, 15 ), RPT_4 (-184, 0, 15 ), + RPT_4 ( 185, 0, 15 ), RPT_4 (-185, 0, 15 ), + RPT_4 ( 186, 0, 15 ), RPT_4 (-186, 0, 15 ), + RPT_4 ( 187, 0, 15 ), RPT_4 (-187, 0, 15 ), + RPT_4 ( 188, 0, 15 ), RPT_4 (-188, 0, 15 ), + RPT_4 ( 189, 0, 15 ), RPT_4 (-189, 0, 15 ), + RPT_4 ( 190, 0, 15 ), RPT_4 (-190, 0, 15 ), + RPT_4 ( 191, 0, 15 ), RPT_4 (-191, 0, 15 ), + RPT_4 ( 192, 0, 15 ), RPT_4 (-192, 0, 15 ), + RPT_4 ( 193, 0, 15 ), RPT_4 (-193, 0, 15 ), + RPT_4 ( 194, 0, 15 ), RPT_4 (-194, 0, 15 ), + RPT_4 ( 195, 0, 15 ), RPT_4 (-195, 0, 15 ), + RPT_4 ( 196, 0, 15 ), RPT_4 (-196, 0, 15 ), + RPT_4 ( 197, 0, 15 ), RPT_4 (-197, 0, 15 ), + RPT_4 ( 198, 0, 15 ), RPT_4 (-198, 0, 15 ), + RPT_4 ( 199, 0, 15 ), RPT_4 (-199, 0, 15 ), + RPT_4 ( 200, 0, 15 ), RPT_4 (-200, 0, 15 ), + RPT_4 ( 201, 0, 15 ), RPT_4 (-201, 0, 15 ), + RPT_4 ( 202, 0, 15 ), RPT_4 (-202, 0, 15 ), + RPT_4 ( 203, 0, 15 ), RPT_4 (-203, 0, 15 ), + RPT_4 ( 204, 0, 15 ), RPT_4 (-204, 0, 15 ), + RPT_4 ( 205, 0, 15 ), RPT_4 (-205, 0, 15 ), + RPT_4 ( 206, 0, 15 ), RPT_4 (-206, 0, 15 ), + RPT_4 ( 207, 0, 15 ), RPT_4 (-207, 0, 15 ), + RPT_4 ( 208, 0, 15 ), RPT_4 (-208, 0, 15 ), + RPT_4 ( 209, 0, 15 ), RPT_4 (-209, 0, 15 ), + RPT_4 ( 210, 0, 15 ), RPT_4 (-210, 0, 15 ), + RPT_4 ( 211, 0, 15 ), RPT_4 (-211, 0, 15 ), + RPT_4 ( 212, 0, 15 ), RPT_4 (-212, 0, 15 ), + RPT_4 ( 213, 0, 15 ), RPT_4 (-213, 0, 15 ), + RPT_4 ( 214, 0, 15 ), RPT_4 (-214, 0, 15 ), + RPT_4 ( 215, 0, 15 ), RPT_4 (-215, 0, 15 ), + RPT_4 ( 216, 0, 15 ), RPT_4 (-216, 0, 15 ), + RPT_4 ( 217, 0, 15 ), RPT_4 (-217, 0, 15 ), + RPT_4 ( 218, 0, 15 ), RPT_4 (-218, 0, 15 ), + RPT_4 ( 219, 0, 15 ), RPT_4 (-219, 0, 15 ), + RPT_4 ( 220, 0, 15 ), RPT_4 (-220, 0, 15 ), + RPT_4 ( 221, 0, 15 ), RPT_4 (-221, 0, 15 ), + RPT_4 ( 222, 0, 15 ), RPT_4 (-222, 0, 15 ), + RPT_4 ( 223, 0, 15 ), RPT_4 (-223, 0, 15 ), + RPT_4 ( 224, 0, 15 ), RPT_4 (-224, 0, 15 ), + RPT_4 ( 225, 0, 15 ), RPT_4 (-225, 0, 15 ), + RPT_4 ( 226, 0, 15 ), RPT_4 (-226, 0, 15 ), + RPT_4 ( 227, 0, 15 ), RPT_4 (-227, 0, 15 ), + RPT_4 ( 228, 0, 15 ), RPT_4 (-228, 0, 15 ), + RPT_4 ( 229, 0, 15 ), RPT_4 (-229, 0, 15 ), + RPT_4 ( 230, 0, 15 ), RPT_4 (-230, 0, 15 ), + RPT_4 ( 231, 0, 15 ), RPT_4 (-231, 0, 15 ), + RPT_4 ( 232, 0, 15 ), RPT_4 (-232, 0, 15 ), + RPT_4 ( 233, 0, 15 ), RPT_4 (-233, 0, 15 ), + RPT_4 ( 234, 0, 15 ), RPT_4 (-234, 0, 15 ), + RPT_4 ( 235, 0, 15 ), RPT_4 (-235, 0, 15 ), + RPT_4 ( 236, 0, 15 ), RPT_4 (-236, 0, 15 ), + RPT_4 ( 237, 0, 15 ), RPT_4 (-237, 0, 15 ), + RPT_4 ( 238, 0, 15 ), RPT_4 (-238, 0, 15 ), + RPT_4 ( 239, 0, 15 ), RPT_4 (-239, 0, 15 ), + RPT_4 ( 240, 0, 15 ), RPT_4 (-240, 0, 15 ), + RPT_4 ( 241, 0, 15 ), RPT_4 (-241, 0, 15 ), + RPT_4 ( 242, 0, 15 ), RPT_4 (-242, 0, 15 ), + RPT_4 ( 243, 0, 15 ), RPT_4 (-243, 0, 15 ), + RPT_4 ( 244, 0, 15 ), RPT_4 (-244, 0, 15 ), + RPT_4 ( 245, 0, 15 ), RPT_4 (-245, 0, 15 ), + RPT_4 ( 246, 0, 15 ), RPT_4 (-246, 0, 15 ), + RPT_4 ( 247, 0, 15 ), RPT_4 (-247, 0, 15 ), + RPT_4 ( 248, 0, 15 ), RPT_4 (-248, 0, 15 ), + RPT_4 ( 249, 0, 15 ), RPT_4 (-249, 0, 15 ), + RPT_4 ( 250, 0, 15 ), RPT_4 (-250, 0, 15 ), + RPT_4 ( 251, 0, 15 ), RPT_4 (-251, 0, 15 ), + RPT_4 ( 252, 0, 15 ), RPT_4 (-252, 0, 15 ), + RPT_4 ( 253, 0, 15 ), RPT_4 (-253, 0, 15 ), + RPT_4 ( 254, 0, 15 ), RPT_4 (-254, 0, 15 ), + RPT_4 ( 255, 0, 15 ), RPT_4 (-255, 0, 15 ), + RPT_32 ( 49, 0, 12 ), RPT_32 ( -49, 0, 12 ), + RPT_32 ( 50, 0, 12 ), RPT_32 ( -50, 0, 12 ), + RPT_32 ( 51, 0, 12 ), RPT_32 ( -51, 0, 12 ), + RPT_32 ( 52, 0, 12 ), RPT_32 ( -52, 0, 12 ), + RPT_32 ( 53, 0, 12 ), RPT_32 ( -53, 0, 12 ), + RPT_32 ( 54, 0, 12 ), RPT_32 ( -54, 0, 12 ), + RPT_32 ( 55, 0, 12 ), RPT_32 ( -55, 0, 12 ), + RPT_32 ( 56, 0, 12 ), RPT_32 ( -56, 0, 12 ), + RPT_32 ( 57, 0, 12 ), RPT_32 ( -57, 0, 12 ), + RPT_32 ( 58, 0, 12 ), RPT_32 ( -58, 0, 12 ), + RPT_32 ( 59, 0, 12 ), RPT_32 ( -59, 0, 12 ), + RPT_32 ( 60, 0, 12 ), RPT_32 ( -60, 0, 12 ), + RPT_32 ( 61, 0, 12 ), RPT_32 ( -61, 0, 12 ), + RPT_32 ( 62, 0, 12 ), RPT_32 ( -62, 0, 12 ), + RPT_32 ( 63, 0, 12 ), RPT_32 ( -63, 0, 12 ), + RPT_32 ( 17, 1, 12 ), RPT_32 ( -17, 1, 12 ), + RPT_32 ( 18, 1, 12 ), RPT_32 ( -18, 1, 12 ), + RPT_32 ( 19, 1, 12 ), RPT_32 ( -19, 1, 12 ), + RPT_32 ( 20, 1, 12 ), RPT_32 ( -20, 1, 12 ), + RPT_32 ( 21, 1, 12 ), RPT_32 ( -21, 1, 12 ), + RPT_32 ( 22, 1, 12 ), RPT_32 ( -22, 1, 12 ), + RPT_32 ( 23, 1, 12 ), RPT_32 ( -23, 1, 12 ), + RPT_32 ( 24, 1, 12 ), RPT_32 ( -24, 1, 12 ), + RPT_32 ( 9, 2, 12 ), RPT_32 ( -9, 2, 12 ), + RPT_32 ( 10, 2, 12 ), RPT_32 ( -10, 2, 12 ), + RPT_32 ( 11, 2, 12 ), RPT_32 ( -11, 2, 12 ), + RPT_32 ( 12, 2, 12 ), RPT_32 ( -12, 2, 12 ), + RPT_32 ( 7, 3, 12 ), RPT_32 ( -7, 3, 12 ), + RPT_32 ( 8, 3, 12 ), RPT_32 ( -8, 3, 12 ), + RPT_32 ( 5, 4, 12 ), RPT_32 ( -5, 4, 12 ), + RPT_32 ( 6, 4, 12 ), RPT_32 ( -6, 4, 12 ), + RPT_32 ( 3, 5, 12 ), RPT_32 ( -3, 5, 12 ), + RPT_32 ( 4, 5, 12 ), RPT_32 ( -4, 5, 12 ), + RPT_32 ( 5, 5, 12 ), RPT_32 ( -5, 5, 12 ), + RPT_32 ( 6, 5, 12 ), RPT_32 ( -6, 5, 12 ), + RPT_32 ( 3, 6, 12 ), RPT_32 ( -3, 6, 12 ), + RPT_32 ( 4, 6, 12 ), RPT_32 ( -4, 6, 12 ), + RPT_32 ( 2, 7, 12 ), RPT_32 ( -2, 7, 12 ), + RPT_32 ( 2, 8, 12 ), RPT_32 ( -2, 8, 12 ), + RPT_32 ( 2, 9, 12 ), RPT_32 ( -2, 9, 12 ), + RPT_32 ( 2, 10, 12 ), RPT_32 ( -2, 10, 12 ), + RPT_32 ( 1, 13, 12 ), RPT_32 ( -1, 13, 12 ), + RPT_32 ( 1, 14, 12 ), RPT_32 ( -1, 14, 12 ), + { 0, 0, 17 }, { 0, 1, 17 }, { 0, 2, 17 }, { 0, 3, 17 }, + { 0, 4, 17 }, { 0, 5, 17 }, { 0, 6, 17 }, { 0, 7, 17 }, + { 0, 8, 17 }, { 0, 9, 17 }, { 0, 10, 17 }, { 0, 11, 17 }, + { 0, 12, 17 }, { 0, 13, 17 }, { 0, 14, 17 }, { 0, 15, 17 }, + { 0, 16, 17 }, { 0, 17, 17 }, { 0, 18, 17 }, { 0, 19, 17 }, + { 0, 20, 17 }, { 0, 21, 17 }, { 0, 22, 17 }, { 0, 23, 17 }, + { 0, 24, 17 }, { 0, 25, 17 }, { 0, 26, 17 }, { 0, 27, 17 }, + { 0, 28, 17 }, { 0, 29, 17 }, { 0, 30, 17 }, { 0, 31, 17 }, + { 0, 32, 17 }, { 0, 33, 17 }, { 0, 34, 17 }, { 0, 35, 17 }, + { 0, 36, 17 }, { 0, 37, 17 }, { 0, 38, 17 }, { 0, 39, 17 }, + { 0, 40, 17 }, { 0, 41, 17 }, { 0, 42, 17 }, { 0, 43, 17 }, + { 0, 44, 17 }, { 0, 45, 17 }, { 0, 46, 17 }, { 0, 47, 17 }, + { 0, 48, 17 }, { 0, 49, 17 }, { 0, 50, 17 }, { 0, 51, 17 }, + { 0, 52, 17 }, { 0, 53, 17 }, { 0, 54, 17 }, { 0, 55, 17 }, + { 0, 56, 17 }, { 0, 57, 17 }, { 0, 58, 17 }, { 0, 59, 17 }, + { 0, 60, 17 }, { 0, 61, 17 }, { 0, 62, 17 }, { 0, 63, 17 }, + RPT_16 ( 25, 1, 13 ), RPT_16 ( -25, 1, 13 ), + RPT_16 ( 26, 1, 13 ), RPT_16 ( -26, 1, 13 ), + RPT_16 ( 27, 1, 13 ), RPT_16 ( -27, 1, 13 ), + RPT_16 ( 28, 1, 13 ), RPT_16 ( -28, 1, 13 ), + RPT_16 ( 29, 1, 13 ), RPT_16 ( -29, 1, 13 ), + RPT_16 ( 30, 1, 13 ), RPT_16 ( -30, 1, 13 ), + RPT_16 ( 31, 1, 13 ), RPT_16 ( -31, 1, 13 ), + RPT_16 ( 32, 1, 13 ), RPT_16 ( -32, 1, 13 ), + RPT_16 ( 13, 2, 13 ), RPT_16 ( -13, 2, 13 ), + RPT_16 ( 14, 2, 13 ), RPT_16 ( -14, 2, 13 ), + RPT_16 ( 15, 2, 13 ), RPT_16 ( -15, 2, 13 ), + RPT_16 ( 16, 2, 13 ), RPT_16 ( -16, 2, 13 ), + RPT_16 ( 9, 3, 13 ), RPT_16 ( -9, 3, 13 ), + RPT_16 ( 10, 3, 13 ), RPT_16 ( -10, 3, 13 ), + RPT_16 ( 11, 3, 13 ), RPT_16 ( -11, 3, 13 ), + RPT_16 ( 7, 4, 13 ), RPT_16 ( -7, 4, 13 ), + RPT_16 ( 3, 7, 13 ), RPT_16 ( -3, 7, 13 ), + RPT_16 ( 4, 7, 13 ), RPT_16 ( -4, 7, 13 ), + RPT_16 ( 3, 8, 13 ), RPT_16 ( -3, 8, 13 ), + RPT_16 ( 4, 8, 13 ), RPT_16 ( -4, 8, 13 ), + RPT_16 ( 3, 9, 13 ), RPT_16 ( -3, 9, 13 ), + RPT_16 ( 2, 11, 13 ), RPT_16 ( -2, 11, 13 ), + RPT_16 ( 2, 12, 13 ), RPT_16 ( -2, 12, 13 ), + RPT_32 ( 0, 14, 12 ), +}; + +static const HQXLUT ac16_lut[] = { + RPT_256 ( 1, 0, 3 ), RPT_256 ( -1, 0, 3 ), + RPT_128 ( 2, 0, 4 ), RPT_128 ( -2, 0, 4 ), + RPT_64 ( 3, 0, 5 ), RPT_64 ( -3, 0, 5 ), + RPT_64 ( 4, 0, 5 ), RPT_64 ( -4, 0, 5 ), + RPT_64 ( 1, 1, 5 ), RPT_64 ( -1, 1, 5 ), + RPT_128 ( 0, 64, 4 ), RPT_32 ( 5, 0, 6 ), + RPT_32 ( -5, 0, 6 ), RPT_32 ( 6, 0, 6 ), + RPT_32 ( -6, 0, 6 ), RPT_32 ( 2, 1, 6 ), + RPT_32 ( -2, 1, 6 ), RPT_32 ( 1, 2, 6 ), + RPT_32 ( -1, 2, 6 ), RPT_16 ( 7, 0, 7 ), + RPT_16 ( -7, 0, 7 ), RPT_16 ( 8, 0, 7 ), + RPT_16 ( -8, 0, 7 ), RPT_16 ( 9, 0, 7 ), + RPT_16 ( -9, 0, 7 ), RPT_16 ( 3, 1, 7 ), + RPT_16 ( -3, 1, 7 ), RPT_16 ( 1, 3, 7 ), + RPT_16 ( -1, 3, 7 ), RPT_16 ( 1, 4, 7 ), + RPT_16 ( -1, 4, 7 ), RPT_8 ( 10, 0, 8 ), + RPT_8 ( -10, 0, 8 ), RPT_8 ( 11, 0, 8 ), + RPT_8 ( -11, 0, 8 ), RPT_8 ( 12, 0, 8 ), + RPT_8 ( -12, 0, 8 ), RPT_8 ( 4, 1, 8 ), + RPT_8 ( -4, 1, 8 ), RPT_8 ( 2, 2, 8 ), + RPT_8 ( -2, 2, 8 ), RPT_8 ( 1, 5, 8 ), + RPT_8 ( -1, 5, 8 ), RPT_8 ( 1, 6, 8 ), + RPT_8 ( -1, 6, 8 ), RPT_4 ( 13, 0, 9 ), + RPT_4 ( -13, 0, 9 ), RPT_4 ( 14, 0, 9 ), + RPT_4 ( -14, 0, 9 ), RPT_4 ( 15, 0, 9 ), + RPT_4 ( -15, 0, 9 ), RPT_4 ( 16, 0, 9 ), + RPT_4 ( -16, 0, 9 ), RPT_4 ( 17, 0, 9 ), + RPT_4 ( -17, 0, 9 ), RPT_4 ( 5, 1, 9 ), + RPT_4 ( -5, 1, 9 ), RPT_4 ( 2, 3, 9 ), + RPT_4 ( -2, 3, 9 ), RPT_4 ( 1, 7, 9 ), + RPT_4 ( -1, 7, 9 ), RPT_4 ( 1, 8, 9 ), + RPT_4 ( -1, 8, 9 ), RPT_4 ( 1, 9, 9 ), + RPT_4 ( -1, 9, 9 ), RPT_4 ( 1, 10, 9 ), + RPT_4 ( -1, 10, 9 ), RPT_4 ( 0, 0, 9 ), + RPT_2 ( 18, 0, 10 ), RPT_2 ( -18, 0, 10 ), + RPT_2 ( 19, 0, 10 ), RPT_2 ( -19, 0, 10 ), + RPT_2 ( 20, 0, 10 ), RPT_2 ( -20, 0, 10 ), + RPT_2 ( 21, 0, 10 ), RPT_2 ( -21, 0, 10 ), + RPT_2 ( 22, 0, 10 ), RPT_2 ( -22, 0, 10 ), + RPT_2 ( 6, 1, 10 ), RPT_2 ( -6, 1, 10 ), + RPT_2 ( 7, 1, 10 ), RPT_2 ( -7, 1, 10 ), + RPT_2 ( 3, 2, 10 ), RPT_2 ( -3, 2, 10 ), + RPT_2 ( 2, 4, 10 ), RPT_2 ( -2, 4, 10 ), + RPT_2 ( 2, 5, 10 ), RPT_2 ( -2, 5, 10 ), + RPT_2 ( 1, 11, 10 ), RPT_2 ( -1, 11, 10 ), + RPT_2 ( 1, 12, 10 ), RPT_2 ( -1, 12, 10 ), + RPT_2 ( 1, 13, 10 ), RPT_2 ( -1, 13, 10 ), + { 2048, 0, -1 }, { 2112, 0, -1 }, { 2176, 0, -1 }, { 2240, 0, -1 }, + { 2304, 0, -1 }, { 2368, 0, -1 }, { 2432, 0, -1 }, { 2496, 0, -1 }, + { 23, 0, 11 }, { -23, 0, 11 }, { 24, 0, 11 }, { -24, 0, 11 }, + { 25, 0, 11 }, { -25, 0, 11 }, { 26, 0, 11 }, { -26, 0, 11 }, + { 27, 0, 11 }, { -27, 0, 11 }, { 28, 0, 11 }, { -28, 0, 11 }, + { 8, 1, 11 }, { -8, 1, 11 }, { 9, 1, 11 }, { -9, 1, 11 }, + { 4, 2, 11 }, { -4, 2, 11 }, { 3, 3, 11 }, { -3, 3, 11 }, + { 3, 4, 11 }, { -3, 4, 11 }, { 2, 6, 11 }, { -2, 6, 11 }, + { 2, 7, 11 }, { -2, 7, 11 }, { 2560, 0, -1 }, { 2624, 0, -1 }, + { 2688, 0, -1 }, { 2752, 0, -1 }, { 2816, 0, -1 }, { 2880, 0, -1 }, + { 2944, 0, -1 }, { 0, 1, 11 }, { 3008, 0, -1 }, { 3072, 0, -1 }, + { 3136, 0, -1 }, { 0, 2, 11 }, { 3200, 0, -1 }, { 0, 3, 11 }, + { 3264, 0, -1 }, { 3328, 0, -1 }, { 3392, 0, -1 }, { 3456, 0, -1 }, + { 3520, 0, -1 }, { 3584, 0, -1 }, { 3648, 0, -1 }, { 3712, 0, -1 }, + { 3776, 0, -1 }, { 3840, 0, -1 }, { 3904, 0, -1 }, { 3968, 0, -1 }, + { 4032, 0, -1 }, { 4096, 0, -1 }, { 4160, 0, -1 }, { 4224, 0, -1 }, + RPT_4 ( 0, 0, 15 ), RPT_4 ( 0, 1, 15 ), + RPT_4 ( 0, 2, 15 ), RPT_4 ( 0, 3, 15 ), + RPT_4 ( 0, 4, 15 ), RPT_4 ( 0, 5, 15 ), + RPT_4 ( 0, 6, 15 ), RPT_4 ( 0, 7, 15 ), + RPT_4 ( 0, 8, 15 ), RPT_4 ( 0, 9, 15 ), + RPT_4 ( 0, 10, 15 ), RPT_4 ( 0, 11, 15 ), + RPT_4 ( 0, 12, 15 ), RPT_4 ( 0, 13, 15 ), + RPT_4 ( 0, 14, 15 ), RPT_4 ( 0, 15, 15 ), + RPT_4 ( 0, 16, 15 ), RPT_4 ( 0, 17, 15 ), + RPT_4 ( 0, 18, 15 ), RPT_4 ( 0, 19, 15 ), + RPT_4 ( 0, 20, 15 ), RPT_4 ( 0, 21, 15 ), + RPT_4 ( 0, 22, 15 ), RPT_4 ( 0, 23, 15 ), + RPT_4 ( 0, 24, 15 ), RPT_4 ( 0, 25, 15 ), + RPT_4 ( 0, 26, 15 ), RPT_4 ( 0, 27, 15 ), + RPT_4 ( 0, 28, 15 ), RPT_4 ( 0, 29, 15 ), + RPT_4 ( 0, 30, 15 ), RPT_4 ( 0, 31, 15 ), + RPT_4 ( 0, 32, 15 ), RPT_4 ( 0, 33, 15 ), + RPT_4 ( 0, 34, 15 ), RPT_4 ( 0, 35, 15 ), + RPT_4 ( 0, 36, 15 ), RPT_4 ( 0, 37, 15 ), + RPT_4 ( 0, 38, 15 ), RPT_4 ( 0, 39, 15 ), + RPT_4 ( 0, 40, 15 ), RPT_4 ( 0, 41, 15 ), + RPT_4 ( 0, 42, 15 ), RPT_4 ( 0, 43, 15 ), + RPT_4 ( 0, 44, 15 ), RPT_4 ( 0, 45, 15 ), + RPT_4 ( 0, 46, 15 ), RPT_4 ( 0, 47, 15 ), + RPT_4 ( 0, 48, 15 ), RPT_4 ( 0, 49, 15 ), + RPT_4 ( 0, 50, 15 ), RPT_4 ( 0, 51, 15 ), + RPT_4 ( 0, 52, 15 ), RPT_4 ( 0, 53, 15 ), + RPT_4 ( 0, 54, 15 ), RPT_4 ( 0, 55, 15 ), + RPT_4 ( 0, 56, 15 ), RPT_4 ( 0, 57, 15 ), + RPT_4 ( 0, 58, 15 ), RPT_4 ( 0, 59, 15 ), + RPT_4 ( 0, 60, 15 ), RPT_4 ( 0, 61, 15 ), + RPT_4 ( 0, 62, 15 ), RPT_4 ( 0, 63, 15 ), + RPT_2 ( 0, 0, 16 ), { 1, 0, 17 }, { -1, 0, 17 }, + { 2, 0, 17 }, { -2, 0, 17 }, { 3, 0, 17 }, { -3, 0, 17 }, + { 4, 0, 17 }, { -4, 0, 17 }, { 5, 0, 17 }, { -5, 0, 17 }, + { 6, 0, 17 }, { -6, 0, 17 }, { 7, 0, 17 }, { -7, 0, 17 }, + { 8, 0, 17 }, { -8, 0, 17 }, { 9, 0, 17 }, { -9, 0, 17 }, + { 10, 0, 17 }, { -10, 0, 17 }, { 11, 0, 17 }, { -11, 0, 17 }, + { 12, 0, 17 }, { -12, 0, 17 }, { 13, 0, 17 }, { -13, 0, 17 }, + { 14, 0, 17 }, { -14, 0, 17 }, { 15, 0, 17 }, { -15, 0, 17 }, + { 16, 0, 17 }, { -16, 0, 17 }, { 17, 0, 17 }, { -17, 0, 17 }, + { 18, 0, 17 }, { -18, 0, 17 }, { 19, 0, 17 }, { -19, 0, 17 }, + { 20, 0, 17 }, { -20, 0, 17 }, { 21, 0, 17 }, { -21, 0, 17 }, + { 22, 0, 17 }, { -22, 0, 17 }, { 23, 0, 17 }, { -23, 0, 17 }, + { 24, 0, 17 }, { -24, 0, 17 }, { 25, 0, 17 }, { -25, 0, 17 }, + { 26, 0, 17 }, { -26, 0, 17 }, { 27, 0, 17 }, { -27, 0, 17 }, + { 28, 0, 17 }, { -28, 0, 17 }, { 29, 0, 17 }, { -29, 0, 17 }, + { 30, 0, 17 }, { -30, 0, 17 }, { 31, 0, 17 }, { -31, 0, 17 }, + { 32, 0, 17 }, { -32, 0, 17 }, { 33, 0, 17 }, { -33, 0, 17 }, + { 34, 0, 17 }, { -34, 0, 17 }, { 35, 0, 17 }, { -35, 0, 17 }, + { 36, 0, 17 }, { -36, 0, 17 }, { 37, 0, 17 }, { -37, 0, 17 }, + { 38, 0, 17 }, { -38, 0, 17 }, { 39, 0, 17 }, { -39, 0, 17 }, + { 40, 0, 17 }, { -40, 0, 17 }, { 41, 0, 17 }, { -41, 0, 17 }, + { 42, 0, 17 }, { -42, 0, 17 }, { 43, 0, 17 }, { -43, 0, 17 }, + { 44, 0, 17 }, { -44, 0, 17 }, { 45, 0, 17 }, { -45, 0, 17 }, + { 46, 0, 17 }, { -46, 0, 17 }, { 47, 0, 17 }, { -47, 0, 17 }, + { 48, 0, 17 }, { -48, 0, 17 }, { 49, 0, 17 }, { -49, 0, 17 }, + { 50, 0, 17 }, { -50, 0, 17 }, { 51, 0, 17 }, { -51, 0, 17 }, + { 52, 0, 17 }, { -52, 0, 17 }, { 53, 0, 17 }, { -53, 0, 17 }, + { 54, 0, 17 }, { -54, 0, 17 }, { 55, 0, 17 }, { -55, 0, 17 }, + { 56, 0, 17 }, { -56, 0, 17 }, { 57, 0, 17 }, { -57, 0, 17 }, + { 58, 0, 17 }, { -58, 0, 17 }, { 59, 0, 17 }, { -59, 0, 17 }, + { 60, 0, 17 }, { -60, 0, 17 }, { 61, 0, 17 }, { -61, 0, 17 }, + { 62, 0, 17 }, { -62, 0, 17 }, { 63, 0, 17 }, { -63, 0, 17 }, + { 64, 0, 17 }, { -64, 0, 17 }, { 65, 0, 17 }, { -65, 0, 17 }, + { 66, 0, 17 }, { -66, 0, 17 }, { 67, 0, 17 }, { -67, 0, 17 }, + { 68, 0, 17 }, { -68, 0, 17 }, { 69, 0, 17 }, { -69, 0, 17 }, + { 70, 0, 17 }, { -70, 0, 17 }, { 71, 0, 17 }, { -71, 0, 17 }, + { 72, 0, 17 }, { -72, 0, 17 }, { 73, 0, 17 }, { -73, 0, 17 }, + { 74, 0, 17 }, { -74, 0, 17 }, { 75, 0, 17 }, { -75, 0, 17 }, + { 76, 0, 17 }, { -76, 0, 17 }, { 77, 0, 17 }, { -77, 0, 17 }, + { 78, 0, 17 }, { -78, 0, 17 }, { 79, 0, 17 }, { -79, 0, 17 }, + { 80, 0, 17 }, { -80, 0, 17 }, { 81, 0, 17 }, { -81, 0, 17 }, + { 82, 0, 17 }, { -82, 0, 17 }, { 83, 0, 17 }, { -83, 0, 17 }, + { 84, 0, 17 }, { -84, 0, 17 }, { 85, 0, 17 }, { -85, 0, 17 }, + { 86, 0, 17 }, { -86, 0, 17 }, { 87, 0, 17 }, { -87, 0, 17 }, + { 88, 0, 17 }, { -88, 0, 17 }, { 89, 0, 17 }, { -89, 0, 17 }, + { 90, 0, 17 }, { -90, 0, 17 }, { 91, 0, 17 }, { -91, 0, 17 }, + { 92, 0, 17 }, { -92, 0, 17 }, { 93, 0, 17 }, { -93, 0, 17 }, + { 94, 0, 17 }, { -94, 0, 17 }, { 95, 0, 17 }, { -95, 0, 17 }, + { 96, 0, 17 }, { -96, 0, 17 }, { 97, 0, 17 }, { -97, 0, 17 }, + { 98, 0, 17 }, { -98, 0, 17 }, { 99, 0, 17 }, { -99, 0, 17 }, + { 100, 0, 17 }, { -100, 0, 17 }, { 101, 0, 17 }, { -101, 0, 17 }, + { 102, 0, 17 }, { -102, 0, 17 }, { 103, 0, 17 }, { -103, 0, 17 }, + { 104, 0, 17 }, { -104, 0, 17 }, { 105, 0, 17 }, { -105, 0, 17 }, + { 106, 0, 17 }, { -106, 0, 17 }, { 107, 0, 17 }, { -107, 0, 17 }, + { 108, 0, 17 }, { -108, 0, 17 }, { 109, 0, 17 }, { -109, 0, 17 }, + { 110, 0, 17 }, { -110, 0, 17 }, { 111, 0, 17 }, { -111, 0, 17 }, + { 112, 0, 17 }, { -112, 0, 17 }, { 113, 0, 17 }, { -113, 0, 17 }, + { 114, 0, 17 }, { -114, 0, 17 }, { 115, 0, 17 }, { -115, 0, 17 }, + { 116, 0, 17 }, { -116, 0, 17 }, { 117, 0, 17 }, { -117, 0, 17 }, + { 118, 0, 17 }, { -118, 0, 17 }, { 119, 0, 17 }, { -119, 0, 17 }, + { 120, 0, 17 }, { -120, 0, 17 }, { 121, 0, 17 }, { -121, 0, 17 }, + { 122, 0, 17 }, { -122, 0, 17 }, { 123, 0, 17 }, { -123, 0, 17 }, + { 124, 0, 17 }, { -124, 0, 17 }, { 125, 0, 17 }, { -125, 0, 17 }, + { 126, 0, 17 }, { -126, 0, 17 }, { 127, 0, 17 }, { -127, 0, 17 }, + RPT_32 ( 29, 0, 12 ), RPT_32 ( -29, 0, 12 ), + RPT_32 ( 30, 0, 12 ), RPT_32 ( -30, 0, 12 ), + RPT_32 ( 31, 0, 12 ), RPT_32 ( -31, 0, 12 ), + RPT_32 ( 32, 0, 12 ), RPT_32 ( -32, 0, 12 ), + RPT_32 ( 33, 0, 12 ), RPT_32 ( -33, 0, 12 ), + RPT_32 ( 34, 0, 12 ), RPT_32 ( -34, 0, 12 ), + RPT_32 ( 35, 0, 12 ), RPT_32 ( -35, 0, 12 ), + RPT_32 ( 10, 1, 12 ), RPT_32 ( -10, 1, 12 ), + RPT_32 ( 11, 1, 12 ), RPT_32 ( -11, 1, 12 ), + RPT_32 ( 12, 1, 12 ), RPT_32 ( -12, 1, 12 ), + RPT_32 ( 5, 2, 12 ), RPT_32 ( -5, 2, 12 ), + RPT_32 ( 4, 3, 12 ), RPT_32 ( -4, 3, 12 ), + RPT_32 ( 3, 5, 12 ), RPT_32 ( -3, 5, 12 ), + RPT_32 ( 2, 8, 12 ), RPT_32 ( -2, 8, 12 ), + RPT_32 ( 2, 9, 12 ), RPT_32 ( -2, 9, 12 ), + RPT_32 ( 1, 14, 12 ), RPT_32 ( -1, 14, 12 ), + RPT_32 ( 1, 15, 12 ), RPT_32 ( -1, 15, 12 ), + RPT_16 ( 36, 0, 13 ), RPT_16 ( -36, 0, 13 ), + RPT_16 ( 37, 0, 13 ), RPT_16 ( -37, 0, 13 ), + RPT_16 ( 38, 0, 13 ), RPT_16 ( -38, 0, 13 ), + RPT_16 ( 39, 0, 13 ), RPT_16 ( -39, 0, 13 ), + RPT_16 ( 40, 0, 13 ), RPT_16 ( -40, 0, 13 ), + RPT_16 ( 13, 1, 13 ), RPT_16 ( -13, 1, 13 ), + RPT_16 ( 14, 1, 13 ), RPT_16 ( -14, 1, 13 ), + RPT_16 ( 15, 1, 13 ), RPT_16 ( -15, 1, 13 ), + RPT_16 ( 6, 2, 13 ), RPT_16 ( -6, 2, 13 ), + RPT_16 ( 7, 2, 13 ), RPT_16 ( -7, 2, 13 ), + RPT_16 ( 5, 3, 13 ), RPT_16 ( -5, 3, 13 ), + RPT_32 ( 0, 4, 12 ), RPT_16 ( 4, 4, 13 ), + RPT_16 ( -4, 4, 13 ), RPT_32 ( 0, 5, 12 ), + RPT_32 ( 0, 6, 12 ), RPT_16 ( 3, 6, 13 ), + RPT_16 ( -3, 6, 13 ), RPT_32 ( 0, 7, 12 ), + RPT_16 ( 3, 7, 13 ), RPT_16 ( -3, 7, 13 ), + RPT_16 ( 2, 10, 13 ), RPT_16 ( -2, 10, 13 ), + RPT_16 ( 1, 16, 13 ), RPT_16 ( -1, 16, 13 ), +}; + +static const HQXLUT ac32_lut[] = { + RPT_256 ( 1, 0, 3 ), RPT_256 ( -1, 0, 3 ), + RPT_128 ( 2, 0, 4 ), RPT_128 ( -2, 0, 4 ), + RPT_256 ( 0, 64, 3 ), RPT_64 ( 3, 0, 5 ), + RPT_64 ( -3, 0, 5 ), RPT_64 ( 1, 1, 5 ), + RPT_64 ( -1, 1, 5 ), RPT_32 ( 4, 0, 6 ), + RPT_32 ( -4, 0, 6 ), RPT_32 ( 5, 0, 6 ), + RPT_32 ( -5, 0, 6 ), RPT_32 ( 2, 1, 6 ), + RPT_32 ( -2, 1, 6 ), RPT_32 ( 1, 2, 6 ), + RPT_32 ( -1, 2, 6 ), RPT_32 ( 1, 3, 6 ), + RPT_32 ( -1, 3, 6 ), RPT_16 ( 6, 0, 7 ), + RPT_16 ( -6, 0, 7 ), RPT_16 ( 7, 0, 7 ), + RPT_16 ( -7, 0, 7 ), RPT_16 ( 3, 1, 7 ), + RPT_16 ( -3, 1, 7 ), RPT_16 ( 1, 4, 7 ), + RPT_16 ( -1, 4, 7 ), RPT_16 ( 1, 5, 7 ), + RPT_16 ( -1, 5, 7 ), RPT_8 ( 8, 0, 8 ), + RPT_8 ( -8, 0, 8 ), RPT_8 ( 9, 0, 8 ), + RPT_8 ( -9, 0, 8 ), RPT_8 ( 10, 0, 8 ), + RPT_8 ( -10, 0, 8 ), RPT_8 ( 4, 1, 8 ), + RPT_8 ( -4, 1, 8 ), RPT_8 ( 2, 2, 8 ), + RPT_8 ( -2, 2, 8 ), RPT_8 ( 1, 6, 8 ), + RPT_8 ( -1, 6, 8 ), RPT_8 ( 1, 7, 8 ), + RPT_8 ( -1, 7, 8 ), RPT_8 ( 1, 8, 8 ), + RPT_8 ( -1, 8, 8 ), RPT_4 ( 11, 0, 9 ), + RPT_4 ( -11, 0, 9 ), RPT_4 ( 12, 0, 9 ), + RPT_4 ( -12, 0, 9 ), RPT_4 ( 13, 0, 9 ), + RPT_4 ( -13, 0, 9 ), RPT_4 ( 5, 1, 9 ), + RPT_4 ( -5, 1, 9 ), RPT_4 ( 2, 3, 9 ), + RPT_4 ( -2, 3, 9 ), RPT_4 ( 1, 9, 9 ), + RPT_4 ( -1, 9, 9 ), RPT_4 ( 1, 10, 9 ), + RPT_4 ( -1, 10, 9 ), RPT_2 ( 14, 0, 10 ), + RPT_2 ( -14, 0, 10 ), RPT_2 ( 15, 0, 10 ), + RPT_2 ( -15, 0, 10 ), RPT_2 ( 16, 0, 10 ), + RPT_2 ( -16, 0, 10 ), RPT_2 ( 6, 1, 10 ), + RPT_2 ( -6, 1, 10 ), RPT_2 ( 7, 1, 10 ), + RPT_2 ( -7, 1, 10 ), RPT_2 ( 3, 2, 10 ), + RPT_2 ( -3, 2, 10 ), RPT_2 ( 3, 3, 10 ), + RPT_2 ( -3, 3, 10 ), RPT_2 ( 2, 4, 10 ), + RPT_2 ( -2, 4, 10 ), RPT_2 ( 2, 5, 10 ), + RPT_2 ( -2, 5, 10 ), RPT_2 ( 1, 11, 10 ), + RPT_2 ( -1, 11, 10 ), RPT_2 ( 1, 12, 10 ), + RPT_2 ( -1, 12, 10 ), RPT_2 ( 1, 13, 10 ), + RPT_2 ( -1, 13, 10 ), { 2048, 0, -1 }, { 2112, 0, -1 }, + { 2176, 0, -1 }, { 2240, 0, -1 }, RPT_2 ( 0, 0, 10 ), + { 17, 0, 11 }, { -17, 0, 11 }, { 18, 0, 11 }, { -18, 0, 11 }, + { 19, 0, 11 }, { -19, 0, 11 }, { 20, 0, 11 }, { -20, 0, 11 }, + { 8, 1, 11 }, { -8, 1, 11 }, { 9, 1, 11 }, { -9, 1, 11 }, + { 4, 2, 11 }, { -4, 2, 11 }, { 3, 4, 11 }, { -3, 4, 11 }, + { 2, 6, 11 }, { -2, 6, 11 }, { 2, 7, 11 }, { -2, 7, 11 }, + { 2, 8, 11 }, { -2, 8, 11 }, { 1, 14, 11 }, { -1, 14, 11 }, + { 2304, 0, -1 }, { 2368, 0, -1 }, { 2432, 0, -1 }, { 2496, 0, -1 }, + { 2560, 0, -1 }, { 0, 1, 11 }, { 2624, 0, -1 }, { 2688, 0, -1 }, + { 0, 2, 11 }, { 2752, 0, -1 }, { 2816, 0, -1 }, { 0, 3, 11 }, + { 2880, 0, -1 }, { 0, 4, 11 }, { 2944, 0, -1 }, { 3008, 0, -1 }, + { 3072, 0, -1 }, { 3136, 0, -1 }, { 3200, 0, -1 }, { 3264, 0, -1 }, + { 3328, 0, -1 }, { 3392, 0, -1 }, { 3456, 0, -1 }, { 3520, 0, -1 }, + { 3584, 0, -1 }, { 3648, 0, -1 }, RPT_4 ( 0, 0, 15 ), + RPT_4 ( 0, 1, 15 ), RPT_4 ( 0, 2, 15 ), + RPT_4 ( 0, 3, 15 ), RPT_4 ( 0, 4, 15 ), + RPT_4 ( 0, 5, 15 ), RPT_4 ( 0, 6, 15 ), + RPT_4 ( 0, 7, 15 ), RPT_4 ( 0, 8, 15 ), + RPT_4 ( 0, 9, 15 ), RPT_4 ( 0, 10, 15 ), + RPT_4 ( 0, 11, 15 ), RPT_4 ( 0, 12, 15 ), + RPT_4 ( 0, 13, 15 ), RPT_4 ( 0, 14, 15 ), + RPT_4 ( 0, 15, 15 ), RPT_4 ( 0, 16, 15 ), + RPT_4 ( 0, 17, 15 ), RPT_4 ( 0, 18, 15 ), + RPT_4 ( 0, 19, 15 ), RPT_4 ( 0, 20, 15 ), + RPT_4 ( 0, 21, 15 ), RPT_4 ( 0, 22, 15 ), + RPT_4 ( 0, 23, 15 ), RPT_4 ( 0, 24, 15 ), + RPT_4 ( 0, 25, 15 ), RPT_4 ( 0, 26, 15 ), + RPT_4 ( 0, 27, 15 ), RPT_4 ( 0, 28, 15 ), + RPT_4 ( 0, 29, 15 ), RPT_4 ( 0, 30, 15 ), + RPT_4 ( 0, 31, 15 ), RPT_4 ( 0, 32, 15 ), + RPT_4 ( 0, 33, 15 ), RPT_4 ( 0, 34, 15 ), + RPT_4 ( 0, 35, 15 ), RPT_4 ( 0, 36, 15 ), + RPT_4 ( 0, 37, 15 ), RPT_4 ( 0, 38, 15 ), + RPT_4 ( 0, 39, 15 ), RPT_4 ( 0, 40, 15 ), + RPT_4 ( 0, 41, 15 ), RPT_4 ( 0, 42, 15 ), + RPT_4 ( 0, 43, 15 ), RPT_4 ( 0, 44, 15 ), + RPT_4 ( 0, 45, 15 ), RPT_4 ( 0, 46, 15 ), + RPT_4 ( 0, 47, 15 ), RPT_4 ( 0, 48, 15 ), + RPT_4 ( 0, 49, 15 ), RPT_4 ( 0, 50, 15 ), + RPT_4 ( 0, 51, 15 ), RPT_4 ( 0, 52, 15 ), + RPT_4 ( 0, 53, 15 ), RPT_4 ( 0, 54, 15 ), + RPT_4 ( 0, 55, 15 ), RPT_4 ( 0, 56, 15 ), + RPT_4 ( 0, 57, 15 ), RPT_4 ( 0, 58, 15 ), + RPT_4 ( 0, 59, 15 ), RPT_4 ( 0, 60, 15 ), + RPT_4 ( 0, 61, 15 ), RPT_4 ( 0, 62, 15 ), + RPT_4 ( 0, 63, 15 ), RPT_2 ( 0, 0, 16 ), + { 1, 0, 17 }, { -1, 0, 17 }, { 2, 0, 17 }, { -2, 0, 17 }, + { 3, 0, 17 }, { -3, 0, 17 }, { 4, 0, 17 }, { -4, 0, 17 }, + { 5, 0, 17 }, { -5, 0, 17 }, { 6, 0, 17 }, { -6, 0, 17 }, + { 7, 0, 17 }, { -7, 0, 17 }, { 8, 0, 17 }, { -8, 0, 17 }, + { 9, 0, 17 }, { -9, 0, 17 }, { 10, 0, 17 }, { -10, 0, 17 }, + { 11, 0, 17 }, { -11, 0, 17 }, { 12, 0, 17 }, { -12, 0, 17 }, + { 13, 0, 17 }, { -13, 0, 17 }, { 14, 0, 17 }, { -14, 0, 17 }, + { 15, 0, 17 }, { -15, 0, 17 }, { 16, 0, 17 }, { -16, 0, 17 }, + { 17, 0, 17 }, { -17, 0, 17 }, { 18, 0, 17 }, { -18, 0, 17 }, + { 19, 0, 17 }, { -19, 0, 17 }, { 20, 0, 17 }, { -20, 0, 17 }, + { 21, 0, 17 }, { -21, 0, 17 }, { 22, 0, 17 }, { -22, 0, 17 }, + { 23, 0, 17 }, { -23, 0, 17 }, { 24, 0, 17 }, { -24, 0, 17 }, + { 25, 0, 17 }, { -25, 0, 17 }, { 26, 0, 17 }, { -26, 0, 17 }, + { 27, 0, 17 }, { -27, 0, 17 }, { 28, 0, 17 }, { -28, 0, 17 }, + { 29, 0, 17 }, { -29, 0, 17 }, { 30, 0, 17 }, { -30, 0, 17 }, + { 31, 0, 17 }, { -31, 0, 17 }, { 32, 0, 17 }, { -32, 0, 17 }, + { 33, 0, 17 }, { -33, 0, 17 }, { 34, 0, 17 }, { -34, 0, 17 }, + { 35, 0, 17 }, { -35, 0, 17 }, { 36, 0, 17 }, { -36, 0, 17 }, + { 37, 0, 17 }, { -37, 0, 17 }, { 38, 0, 17 }, { -38, 0, 17 }, + { 39, 0, 17 }, { -39, 0, 17 }, { 40, 0, 17 }, { -40, 0, 17 }, + { 41, 0, 17 }, { -41, 0, 17 }, { 42, 0, 17 }, { -42, 0, 17 }, + { 43, 0, 17 }, { -43, 0, 17 }, { 44, 0, 17 }, { -44, 0, 17 }, + { 45, 0, 17 }, { -45, 0, 17 }, { 46, 0, 17 }, { -46, 0, 17 }, + { 47, 0, 17 }, { -47, 0, 17 }, { 48, 0, 17 }, { -48, 0, 17 }, + { 49, 0, 17 }, { -49, 0, 17 }, { 50, 0, 17 }, { -50, 0, 17 }, + { 51, 0, 17 }, { -51, 0, 17 }, { 52, 0, 17 }, { -52, 0, 17 }, + { 53, 0, 17 }, { -53, 0, 17 }, { 54, 0, 17 }, { -54, 0, 17 }, + { 55, 0, 17 }, { -55, 0, 17 }, { 56, 0, 17 }, { -56, 0, 17 }, + { 57, 0, 17 }, { -57, 0, 17 }, { 58, 0, 17 }, { -58, 0, 17 }, + { 59, 0, 17 }, { -59, 0, 17 }, { 60, 0, 17 }, { -60, 0, 17 }, + { 61, 0, 17 }, { -61, 0, 17 }, { 62, 0, 17 }, { -62, 0, 17 }, + { 63, 0, 17 }, { -63, 0, 17 }, RPT_32 ( 21, 0, 12 ), + RPT_32 ( -21, 0, 12 ), RPT_32 ( 22, 0, 12 ), + RPT_32 ( -22, 0, 12 ), RPT_32 ( 23, 0, 12 ), + RPT_32 ( -23, 0, 12 ), RPT_32 ( 10, 1, 12 ), + RPT_32 ( -10, 1, 12 ), RPT_32 ( 11, 1, 12 ), + RPT_32 ( -11, 1, 12 ), RPT_32 ( 5, 2, 12 ), + RPT_32 ( -5, 2, 12 ), RPT_32 ( 6, 2, 12 ), + RPT_32 ( -6, 2, 12 ), RPT_32 ( 4, 3, 12 ), + RPT_32 ( -4, 3, 12 ), RPT_32 ( 3, 5, 12 ), + RPT_32 ( -3, 5, 12 ), RPT_32 ( 3, 6, 12 ), + RPT_32 ( -3, 6, 12 ), RPT_32 ( 2, 9, 12 ), + RPT_32 ( -2, 9, 12 ), RPT_32 ( 1, 15, 12 ), + RPT_32 ( -1, 15, 12 ), RPT_16 ( 24, 0, 13 ), + RPT_16 ( -24, 0, 13 ), RPT_16 ( 25, 0, 13 ), + RPT_16 ( -25, 0, 13 ), RPT_16 ( 26, 0, 13 ), + RPT_16 ( -26, 0, 13 ), RPT_16 ( 12, 1, 13 ), + RPT_16 ( -12, 1, 13 ), RPT_16 ( 13, 1, 13 ), + RPT_16 ( -13, 1, 13 ), RPT_16 ( 5, 3, 13 ), + RPT_16 ( -5, 3, 13 ), RPT_16 ( 4, 4, 13 ), + RPT_16 ( -4, 4, 13 ), RPT_32 ( 0, 5, 12 ), + RPT_16 ( 4, 5, 13 ), RPT_16 ( -4, 5, 13 ), + RPT_32 ( 0, 6, 12 ), RPT_32 ( 0, 7, 12 ), + RPT_16 ( 3, 7, 13 ), RPT_16 ( -3, 7, 13 ), + RPT_32 ( 0, 8, 12 ), RPT_16 ( 3, 8, 13 ), + RPT_16 ( -3, 8, 13 ), RPT_32 ( 0, 9, 12 ), + RPT_16 ( 1, 16, 13 ), RPT_16 ( -1, 16, 13 ), +}; + +static const HQXLUT ac64_lut[] = { + RPT_512 ( 1, 0, 3 ), RPT_512 ( -1, 0, 3 ), + RPT_1024( 0, 64, 2 ), RPT_256 ( 2, 0, 4 ), + RPT_256 ( -2, 0, 4 ), RPT_128 ( 3, 0, 5 ), + RPT_128 ( -3, 0, 5 ), RPT_128 ( 1, 1, 5 ), + RPT_128 ( -1, 1, 5 ), RPT_64 ( 4, 0, 6 ), + RPT_64 ( -4, 0, 6 ), RPT_64 ( 2, 1, 6 ), + RPT_64 ( -2, 1, 6 ), RPT_64 ( 1, 2, 6 ), + RPT_64 ( -1, 2, 6 ), RPT_32 ( 5, 0, 7 ), + RPT_32 ( -5, 0, 7 ), RPT_32 ( 1, 3, 7 ), + RPT_32 ( -1, 3, 7 ), RPT_32 ( 1, 4, 7 ), + RPT_32 ( -1, 4, 7 ), RPT_16 ( 6, 0, 8 ), + RPT_16 ( -6, 0, 8 ), RPT_16 ( 3, 1, 8 ), + RPT_16 ( -3, 1, 8 ), RPT_16 ( 2, 2, 8 ), + RPT_16 ( -2, 2, 8 ), RPT_16 ( 1, 5, 8 ), + RPT_16 ( -1, 5, 8 ), RPT_16 ( 1, 6, 8 ), + RPT_16 ( -1, 6, 8 ), RPT_16 ( 1, 7, 8 ), + RPT_16 ( -1, 7, 8 ), RPT_8 ( 7, 0, 9 ), + RPT_8 ( -7, 0, 9 ), RPT_8 ( 8, 0, 9 ), + RPT_8 ( -8, 0, 9 ), RPT_8 ( 4, 1, 9 ), + RPT_8 ( -4, 1, 9 ), RPT_8 ( 2, 3, 9 ), + RPT_8 ( -2, 3, 9 ), RPT_8 ( 1, 8, 9 ), + RPT_8 ( -1, 8, 9 ), RPT_8 ( 1, 9, 9 ), + RPT_8 ( -1, 9, 9 ), RPT_4 ( 9, 0, 10 ), + RPT_4 ( -9, 0, 10 ), RPT_4 ( 10, 0, 10 ), + RPT_4 ( -10, 0, 10 ), RPT_4 ( 5, 1, 10 ), + RPT_4 ( -5, 1, 10 ), RPT_4 ( 3, 2, 10 ), + RPT_4 ( -3, 2, 10 ), RPT_4 ( 2, 4, 10 ), + RPT_4 ( -2, 4, 10 ), RPT_4 ( 2, 5, 10 ), + RPT_4 ( -2, 5, 10 ), RPT_4 ( 1, 10, 10 ), + RPT_4 ( -1, 10, 10 ), RPT_4 ( 1, 11, 10 ), + RPT_4 ( -1, 11, 10 ), { 4096, 0, -1 }, { 4128, 0, -1 }, + { 4160, 0, -1 }, { 4192, 0, -1 }, { 4224, 0, -1 }, { 4256, 0, -1 }, + { 4288, 0, -1 }, { 4320, 0, -1 }, RPT_4 ( 0, 0, 10 ), + RPT_2 ( 11, 0, 11 ), RPT_2 ( -11, 0, 11 ), + RPT_2 ( 12, 0, 11 ), RPT_2 ( -12, 0, 11 ), + RPT_2 ( 6, 1, 11 ), RPT_2 ( -6, 1, 11 ), + RPT_2 ( 7, 1, 11 ), RPT_2 ( -7, 1, 11 ), + RPT_2 ( 3, 3, 11 ), RPT_2 ( -3, 3, 11 ), + RPT_2 ( 3, 4, 11 ), RPT_2 ( -3, 4, 11 ), + RPT_2 ( 3, 5, 11 ), RPT_2 ( -3, 5, 11 ), + RPT_2 ( 2, 6, 11 ), RPT_2 ( -2, 6, 11 ), + RPT_2 ( 2, 7, 11 ), RPT_2 ( -2, 7, 11 ), + RPT_2 ( 1, 12, 11 ), RPT_2 ( -1, 12, 11 ), + RPT_2 ( 1, 13, 11 ), RPT_2 ( -1, 13, 11 ), + RPT_2 ( 1, 14, 11 ), RPT_2 ( -1, 14, 11 ), + { 13, 0, 12 }, { -13, 0, 12 }, { 14, 0, 12 }, { -14, 0, 12 }, + RPT_2 ( 0, 1, 11 ), { 8, 1, 12 }, { -8, 1, 12 }, + { 4, 2, 12 }, { -4, 2, 12 }, { 4, 3, 12 }, { -4, 3, 12 }, + { 2, 8, 12 }, { -2, 8, 12 }, { 2, 9, 12 }, { -2, 9, 12 }, + { 1, 15, 12 }, { -1, 15, 12 }, { 4352, 0, -1 }, { 4384, 0, -1 }, + { 4416, 0, -1 }, { 4448, 0, -1 }, { 4480, 0, -1 }, { 0, 2, 12 }, + { 4512, 0, -1 }, { 0, 3, 12 }, { 4544, 0, -1 }, { 0, 4, 12 }, + { 4576, 0, -1 }, { 0, 5, 12 }, { 4608, 0, -1 }, { 0, 6, 12 }, + { 4640, 0, -1 }, { 4672, 0, -1 }, { 4704, 0, -1 }, { 4736, 0, -1 }, + RPT_4 ( 0, 0, 15 ), RPT_4 ( 0, 1, 15 ), + RPT_4 ( 0, 2, 15 ), RPT_4 ( 0, 3, 15 ), + RPT_4 ( 0, 4, 15 ), RPT_4 ( 0, 5, 15 ), + RPT_4 ( 0, 6, 15 ), RPT_4 ( 0, 7, 15 ), + RPT_4 ( 0, 8, 15 ), RPT_4 ( 0, 9, 15 ), + RPT_4 ( 0, 10, 15 ), RPT_4 ( 0, 11, 15 ), + RPT_4 ( 0, 12, 15 ), RPT_4 ( 0, 13, 15 ), + RPT_4 ( 0, 14, 15 ), RPT_4 ( 0, 15, 15 ), + RPT_4 ( 0, 16, 15 ), RPT_4 ( 0, 17, 15 ), + RPT_4 ( 0, 18, 15 ), RPT_4 ( 0, 19, 15 ), + RPT_4 ( 0, 20, 15 ), RPT_4 ( 0, 21, 15 ), + RPT_4 ( 0, 22, 15 ), RPT_4 ( 0, 23, 15 ), + RPT_4 ( 0, 24, 15 ), RPT_4 ( 0, 25, 15 ), + RPT_4 ( 0, 26, 15 ), RPT_4 ( 0, 27, 15 ), + RPT_4 ( 0, 28, 15 ), RPT_4 ( 0, 29, 15 ), + RPT_4 ( 0, 30, 15 ), RPT_4 ( 0, 31, 15 ), + RPT_4 ( 0, 32, 15 ), RPT_4 ( 0, 33, 15 ), + RPT_4 ( 0, 34, 15 ), RPT_4 ( 0, 35, 15 ), + RPT_4 ( 0, 36, 15 ), RPT_4 ( 0, 37, 15 ), + RPT_4 ( 0, 38, 15 ), RPT_4 ( 0, 39, 15 ), + RPT_4 ( 0, 40, 15 ), RPT_4 ( 0, 41, 15 ), + RPT_4 ( 0, 42, 15 ), RPT_4 ( 0, 43, 15 ), + RPT_4 ( 0, 44, 15 ), RPT_4 ( 0, 45, 15 ), + RPT_4 ( 0, 46, 15 ), RPT_4 ( 0, 47, 15 ), + RPT_4 ( 0, 48, 15 ), RPT_4 ( 0, 49, 15 ), + RPT_4 ( 0, 50, 15 ), RPT_4 ( 0, 51, 15 ), + RPT_4 ( 0, 52, 15 ), RPT_4 ( 0, 53, 15 ), + RPT_4 ( 0, 54, 15 ), RPT_4 ( 0, 55, 15 ), + RPT_4 ( 0, 56, 15 ), RPT_4 ( 0, 57, 15 ), + RPT_4 ( 0, 58, 15 ), RPT_4 ( 0, 59, 15 ), + RPT_4 ( 0, 60, 15 ), RPT_4 ( 0, 61, 15 ), + RPT_4 ( 0, 62, 15 ), RPT_4 ( 0, 63, 15 ), + RPT_2 ( 0, 0, 16 ), { 1, 0, 17 }, { -1, 0, 17 }, + { 2, 0, 17 }, { -2, 0, 17 }, { 3, 0, 17 }, { -3, 0, 17 }, + { 4, 0, 17 }, { -4, 0, 17 }, { 5, 0, 17 }, { -5, 0, 17 }, + { 6, 0, 17 }, { -6, 0, 17 }, { 7, 0, 17 }, { -7, 0, 17 }, + { 8, 0, 17 }, { -8, 0, 17 }, { 9, 0, 17 }, { -9, 0, 17 }, + { 10, 0, 17 }, { -10, 0, 17 }, { 11, 0, 17 }, { -11, 0, 17 }, + { 12, 0, 17 }, { -12, 0, 17 }, { 13, 0, 17 }, { -13, 0, 17 }, + { 14, 0, 17 }, { -14, 0, 17 }, { 15, 0, 17 }, { -15, 0, 17 }, + { 16, 0, 17 }, { -16, 0, 17 }, { 17, 0, 17 }, { -17, 0, 17 }, + { 18, 0, 17 }, { -18, 0, 17 }, { 19, 0, 17 }, { -19, 0, 17 }, + { 20, 0, 17 }, { -20, 0, 17 }, { 21, 0, 17 }, { -21, 0, 17 }, + { 22, 0, 17 }, { -22, 0, 17 }, { 23, 0, 17 }, { -23, 0, 17 }, + { 24, 0, 17 }, { -24, 0, 17 }, { 25, 0, 17 }, { -25, 0, 17 }, + { 26, 0, 17 }, { -26, 0, 17 }, { 27, 0, 17 }, { -27, 0, 17 }, + { 28, 0, 17 }, { -28, 0, 17 }, { 29, 0, 17 }, { -29, 0, 17 }, + { 30, 0, 17 }, { -30, 0, 17 }, { 31, 0, 17 }, { -31, 0, 17 }, + RPT_16 ( 15, 0, 13 ), RPT_16 ( -15, 0, 13 ), + RPT_16 ( 9, 1, 13 ), RPT_16 ( -9, 1, 13 ), + RPT_16 ( 10, 1, 13 ), RPT_16 ( -10, 1, 13 ), + RPT_16 ( 5, 2, 13 ), RPT_16 ( -5, 2, 13 ), + RPT_16 ( 5, 3, 13 ), RPT_16 ( -5, 3, 13 ), + RPT_16 ( 4, 4, 13 ), RPT_16 ( -4, 4, 13 ), + RPT_16 ( 4, 5, 13 ), RPT_16 ( -4, 5, 13 ), + RPT_16 ( 3, 6, 13 ), RPT_16 ( -3, 6, 13 ), + RPT_16 ( 3, 7, 13 ), RPT_16 ( -3, 7, 13 ), + RPT_16 ( 1, 16, 13 ), RPT_16 ( -1, 16, 13 ), + RPT_16 ( 1, 17, 13 ), RPT_16 ( -1, 17, 13 ), +}; + +static const HQXLUT ac128_lut[] = { + RPT_256 ( 1, 0, 3 ), RPT_256 ( -1, 0, 3 ), + RPT_512 ( 0, 64, 2 ), RPT_128 ( 1, 1, 4 ), + RPT_128 ( -1, 1, 4 ), RPT_64 ( 2, 0, 5 ), + RPT_64 ( -2, 0, 5 ), RPT_32 ( 3, 0, 6 ), + RPT_32 ( -3, 0, 6 ), RPT_32 ( 2, 1, 6 ), + RPT_32 ( -2, 1, 6 ), RPT_32 ( 1, 2, 6 ), + RPT_32 ( -1, 2, 6 ), RPT_32 ( 1, 3, 6 ), + RPT_32 ( -1, 3, 6 ), RPT_32 ( 1, 4, 6 ), + RPT_32 ( -1, 4, 6 ), RPT_16 ( 4, 0, 7 ), + RPT_16 ( -4, 0, 7 ), RPT_16 ( 1, 5, 7 ), + RPT_16 ( -1, 5, 7 ), RPT_16 ( 1, 6, 7 ), + RPT_16 ( -1, 6, 7 ), RPT_16 ( 1, 7, 7 ), + RPT_16 ( -1, 7, 7 ), RPT_8 ( 5, 0, 8 ), + RPT_8 ( -5, 0, 8 ), RPT_8 ( 3, 1, 8 ), + RPT_8 ( -3, 1, 8 ), RPT_8 ( 2, 2, 8 ), + RPT_8 ( -2, 2, 8 ), RPT_8 ( 2, 3, 8 ), + RPT_8 ( -2, 3, 8 ), RPT_8 ( 1, 8, 8 ), + RPT_8 ( -1, 8, 8 ), RPT_8 ( 1, 9, 8 ), + RPT_8 ( -1, 9, 8 ), RPT_4 ( 6, 0, 9 ), + RPT_4 ( -6, 0, 9 ), RPT_4 ( 4, 1, 9 ), + RPT_4 ( -4, 1, 9 ), RPT_4 ( 2, 4, 9 ), + RPT_4 ( -2, 4, 9 ), RPT_4 ( 2, 5, 9 ), + RPT_4 ( -2, 5, 9 ), RPT_4 ( 1, 10, 9 ), + RPT_4 ( -1, 10, 9 ), RPT_2 ( 7, 0, 10 ), + RPT_2 ( -7, 0, 10 ), RPT_2 ( 5, 1, 10 ), + RPT_2 ( -5, 1, 10 ), RPT_2 ( 3, 2, 10 ), + RPT_2 ( -3, 2, 10 ), RPT_2 ( 3, 3, 10 ), + RPT_2 ( -3, 3, 10 ), RPT_2 ( 2, 6, 10 ), + RPT_2 ( -2, 6, 10 ), { 2048, 0, -1 }, { 2112, 0, -1 }, + { 2176, 0, -1 }, { 2240, 0, -1 }, { 6, 1, 11 }, { -6, 1, 11 }, + { 7, 1, 11 }, { -7, 1, 11 }, { 3, 4, 11 }, { -3, 4, 11 }, + { 3, 5, 11 }, { -3, 5, 11 }, { 2, 7, 11 }, { -2, 7, 11 }, + { 2, 8, 11 }, { -2, 8, 11 }, { 2, 9, 11 }, { -2, 9, 11 }, + { 1, 11, 11 }, { -1, 11, 11 }, { 1, 12, 11 }, { -1, 12, 11 }, + { 1, 13, 11 }, { -1, 13, 11 }, { 0, 0, 11 }, { 2304, 0, -1 }, + { 2368, 0, -1 }, { 2432, 0, -1 }, { 2496, 0, -1 }, { 2560, 0, -1 }, + { 2624, 0, -1 }, { 2688, 0, -1 }, { 2752, 0, -1 }, { 2816, 0, -1 }, + { 2880, 0, -1 }, { 2944, 0, -1 }, RPT_4 ( 0, 0, 15 ), + RPT_4 ( 0, 1, 15 ), RPT_4 ( 0, 2, 15 ), + RPT_4 ( 0, 3, 15 ), RPT_4 ( 0, 4, 15 ), + RPT_4 ( 0, 5, 15 ), RPT_4 ( 0, 6, 15 ), + RPT_4 ( 0, 7, 15 ), RPT_4 ( 0, 8, 15 ), + RPT_4 ( 0, 9, 15 ), RPT_4 ( 0, 10, 15 ), + RPT_4 ( 0, 11, 15 ), RPT_4 ( 0, 12, 15 ), + RPT_4 ( 0, 13, 15 ), RPT_4 ( 0, 14, 15 ), + RPT_4 ( 0, 15, 15 ), RPT_4 ( 0, 16, 15 ), + RPT_4 ( 0, 17, 15 ), RPT_4 ( 0, 18, 15 ), + RPT_4 ( 0, 19, 15 ), RPT_4 ( 0, 20, 15 ), + RPT_4 ( 0, 21, 15 ), RPT_4 ( 0, 22, 15 ), + RPT_4 ( 0, 23, 15 ), RPT_4 ( 0, 24, 15 ), + RPT_4 ( 0, 25, 15 ), RPT_4 ( 0, 26, 15 ), + RPT_4 ( 0, 27, 15 ), RPT_4 ( 0, 28, 15 ), + RPT_4 ( 0, 29, 15 ), RPT_4 ( 0, 30, 15 ), + RPT_4 ( 0, 31, 15 ), RPT_4 ( 0, 32, 15 ), + RPT_4 ( 0, 33, 15 ), RPT_4 ( 0, 34, 15 ), + RPT_4 ( 0, 35, 15 ), RPT_4 ( 0, 36, 15 ), + RPT_4 ( 0, 37, 15 ), RPT_4 ( 0, 38, 15 ), + RPT_4 ( 0, 39, 15 ), RPT_4 ( 0, 40, 15 ), + RPT_4 ( 0, 41, 15 ), RPT_4 ( 0, 42, 15 ), + RPT_4 ( 0, 43, 15 ), RPT_4 ( 0, 44, 15 ), + RPT_4 ( 0, 45, 15 ), RPT_4 ( 0, 46, 15 ), + RPT_4 ( 0, 47, 15 ), RPT_4 ( 0, 48, 15 ), + RPT_4 ( 0, 49, 15 ), RPT_4 ( 0, 50, 15 ), + RPT_4 ( 0, 51, 15 ), RPT_4 ( 0, 52, 15 ), + RPT_4 ( 0, 53, 15 ), RPT_4 ( 0, 54, 15 ), + RPT_4 ( 0, 55, 15 ), RPT_4 ( 0, 56, 15 ), + RPT_4 ( 0, 57, 15 ), RPT_4 ( 0, 58, 15 ), + RPT_4 ( 0, 59, 15 ), RPT_4 ( 0, 60, 15 ), + RPT_4 ( 0, 61, 15 ), RPT_4 ( 0, 62, 15 ), + RPT_4 ( 0, 63, 15 ), RPT_32 ( 8, 0, 12 ), + RPT_32 ( -8, 0, 12 ), RPT_32 ( 9, 0, 12 ), + RPT_32 ( -9, 0, 12 ), RPT_32 ( 8, 1, 12 ), + RPT_32 ( -8, 1, 12 ), RPT_32 ( 4, 2, 12 ), + RPT_32 ( -4, 2, 12 ), RPT_32 ( 4, 3, 12 ), + RPT_32 ( -4, 3, 12 ), RPT_32 ( 3, 6, 12 ), + RPT_32 ( -3, 6, 12 ), RPT_32 ( 1, 14, 12 ), + RPT_32 ( -1, 14, 12 ), RPT_32 ( 1, 15, 12 ), + RPT_32 ( -1, 15, 12 ), RPT_32 ( 1, 16, 12 ), + RPT_32 ( -1, 16, 12 ), RPT_32 ( 0, 1, 12 ), + RPT_32 ( 0, 2, 12 ), RPT_32 ( 0, 3, 12 ), + RPT_2 ( 0, 0, 16 ), { 1, 0, 17 }, { -1, 0, 17 }, + { 2, 0, 17 }, { -2, 0, 17 }, { 3, 0, 17 }, { -3, 0, 17 }, + { 4, 0, 17 }, { -4, 0, 17 }, { 5, 0, 17 }, { -5, 0, 17 }, + { 6, 0, 17 }, { -6, 0, 17 }, { 7, 0, 17 }, { -7, 0, 17 }, + { 8, 0, 17 }, { -8, 0, 17 }, { 9, 0, 17 }, { -9, 0, 17 }, + { 10, 0, 17 }, { -10, 0, 17 }, { 11, 0, 17 }, { -11, 0, 17 }, + { 12, 0, 17 }, { -12, 0, 17 }, { 13, 0, 17 }, { -13, 0, 17 }, + { 14, 0, 17 }, { -14, 0, 17 }, { 15, 0, 17 }, { -15, 0, 17 }, +}; + +const HQXAC ff_hqx_ac[NUM_HQX_AC] = { + { 10, 5, ac0_lut }, + { 11, 6, ac8_lut }, + { 11, 6, ac16_lut }, + { 11, 6, ac32_lut }, + { 12, 5, ac64_lut }, + { 11, 6, ac128_lut }, +}; + +#define INIT_DC_TABLE(idx, name) \ + do { \ + ret = init_vlc(&ctx->dc_vlc[idx], HQX_DC_VLC_BITS, \ + FF_ARRAY_ELEMS(name ## _vlc_lens), \ + name ## _vlc_lens, 1, 1, \ + name ## _vlc_bits, 2, 2, 0); \ + if (ret < 0) \ + return ret; \ + } while (0) + +av_cold int ff_hqx_init_vlcs(HQXContext *ctx) +{ + int ret = init_vlc(&ctx->cbp_vlc, 5, FF_ARRAY_ELEMS(cbp_vlc_lens), + cbp_vlc_lens, 1, 1, cbp_vlc_bits, 1, 1, 0); + if (ret < 0) + return ret; + + INIT_DC_TABLE(0, dc9); + INIT_DC_TABLE(1, dc10); + INIT_DC_TABLE(2, dc11); + + return 0; +} diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c index dec2197..3b15aa2 100644 --- a/libavcodec/huffman.c +++ b/libavcodec/huffman.c @@ -26,14 +26,16 @@ #include +#include"libavutil/common.h" + #include "avcodec.h" -#include "get_bits.h" #include "huffman.h" +#include "vlc.h" /* symbol for Huffman tree node */ #define HNODE -1 -typedef struct { +typedef struct HeapElem { uint64_t val; int name; } HeapElem; @@ -114,7 +116,7 @@ static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, } } -static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags) +static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits) { int no_zero_count = !(flags & FF_HUFFMAN_FLAG_ZERO_COUNT); uint32_t bits[256]; @@ -124,7 +126,7 @@ static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags) get_tree_codes(bits, lens, xlat, nodes, head, 0, 0, &pos, no_zero_count); - return ff_init_vlc_sparse(vlc, 9, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); + return ff_init_vlc_sparse(vlc, nb_bits, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); } @@ -132,7 +134,7 @@ static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags) * nodes size must be 2*nb_codes * first nb_codes nodes.count must be set */ -int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, +int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, int nb_bits, Node *nodes, HuffCmp cmp, int flags) { int i, j; @@ -169,7 +171,7 @@ int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, } cur_node++; } - if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags) < 0) { + if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags, nb_bits) < 0) { av_log(avctx, AV_LOG_ERROR, "Error building tree\n"); return -1; } diff --git a/libavcodec/huffman.h b/libavcodec/huffman.h index 043e6e3..87cbe4b 100644 --- a/libavcodec/huffman.h +++ b/libavcodec/huffman.h @@ -27,7 +27,7 @@ #define AVCODEC_HUFFMAN_H #include "avcodec.h" -#include "get_bits.h" +#include "vlc.h" typedef struct Node { int16_t sym; @@ -37,9 +37,10 @@ typedef struct Node { #define FF_HUFFMAN_FLAG_HNODE_FIRST 0x01 #define FF_HUFFMAN_FLAG_ZERO_COUNT 0x02 +#define FF_HUFFMAN_BITS 10 typedef int (*HuffCmp)(const void *va, const void *vb); -int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, +int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, int nb_bits, Node *nodes, HuffCmp cmp, int flags); void ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats); diff --git a/libavcodec/huffyuv.h b/libavcodec/huffyuv.h index aed1537..a4a83b9 100644 --- a/libavcodec/huffyuv.h +++ b/libavcodec/huffyuv.h @@ -59,6 +59,7 @@ typedef enum Predictor { } Predictor; typedef struct HYuvContext { + const AVClass *class; AVCodecContext *avctx; Predictor predictor; GetBitContext gb; diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 1ad81f7..12eca26 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -35,14 +35,14 @@ #include "thread.h" #define classic_shift_luma_table_size 42 -static const unsigned char classic_shift_luma[classic_shift_luma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { +static const unsigned char classic_shift_luma[classic_shift_luma_table_size + AV_INPUT_BUFFER_PADDING_SIZE] = { 34, 36, 35, 69, 135, 232, 9, 16, 10, 24, 11, 23, 12, 16, 13, 10, 14, 8, 15, 8, 16, 8, 17, 20, 16, 10, 207, 206, 205, 236, 11, 8, 10, 21, 9, 23, 8, 8, 199, 70, 69, 68, 0 }; #define classic_shift_chroma_table_size 59 -static const unsigned char classic_shift_chroma[classic_shift_chroma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { +static const unsigned char classic_shift_chroma[classic_shift_chroma_table_size + AV_INPUT_BUFFER_PADDING_SIZE] = { 66, 36, 37, 38, 39, 40, 41, 75, 76, 77, 110, 239, 144, 81, 82, 83, 84, 85, 118, 183, 56, 57, 88, 89, 56, 89, 154, 57, 58, 57, 26, 141, 57, 56, 58, 57, 58, 57, 184, 119, 214, 245, 116, 83, 82, 49, 80, 79, @@ -511,11 +511,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, av_fast_malloc(&s->bitstream_buffer, &s->bitstream_buffer_size, - buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->bitstream_buffer) return AVERROR(ENOMEM); - memset(s->bitstream_buffer + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(s->bitstream_buffer + buf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, (const uint32_t *) buf, buf_size / 4); @@ -571,7 +571,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, decode_422_bitstream(s, width - 2); lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0], width - 2, lefty); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu); leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv); } @@ -604,14 +604,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, decode_422_bitstream(s, width); lefty = s->hdsp.add_hfyu_left_pred(ydst, s->temp[0], width, lefty); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { leftu = s->hdsp.add_hfyu_left_pred(udst, s->temp[1], width2, leftu); leftv = s->hdsp.add_hfyu_left_pred(vdst, s->temp[2], width2, leftv); } if (s->predictor == PLANE) { if (cy > s->interlaced) { s->hdsp.add_bytes(ydst, ydst - fake_ystride, width); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { s->hdsp.add_bytes(udst, udst - fake_ustride, width2); s->hdsp.add_bytes(vdst, vdst - fake_vstride, width2); } @@ -626,7 +626,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, decode_422_bitstream(s, width - 2); lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0], width - 2, lefty); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu); leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv); } @@ -638,7 +638,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, decode_422_bitstream(s, width); lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + p->linesize[0], s->temp[0], width, lefty); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + p->linesize[2], s->temp[1], width2, leftu); leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + p->linesize[1], s->temp[2], width2, leftv); } @@ -650,7 +650,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, decode_422_bitstream(s, 4); lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + fake_ystride, s->temp[0], 4, lefty); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + fake_ustride, s->temp[1], 2, leftu); leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + fake_vstride, s->temp[2], 2, leftv); } @@ -661,7 +661,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->hdsp.add_hfyu_median_pred(p->data[0] + fake_ystride + 4, p->data[0] + 4, s->temp[0], width - 4, &lefty, &lefttopy); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { lefttopu = p->data[1][1]; lefttopv = p->data[2][1]; s->hdsp.add_hfyu_median_pred(p->data[1] + fake_ustride + 2, p->data[1] + 2, s->temp[1], width2 - 2, &leftu, &lefttopu); @@ -696,7 +696,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->hdsp.add_hfyu_median_pred(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); - if (!(s->flags & CODEC_FLAG_GRAY)) { + if (!(s->flags & AV_CODEC_FLAG_GRAY)) { s->hdsp.add_hfyu_median_pred(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu); s->hdsp.add_hfyu_median_pred(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv); } @@ -792,8 +792,8 @@ AVCodec ff_huffyuv_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; @@ -807,8 +807,8 @@ AVCodec ff_ffvhuff_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #endif /* CONFIG_FFVHUFF_DECODER */ diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index 47fe2a5..a6ffd24 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -26,10 +26,13 @@ * huffyuv encoder */ +#include "libavutil/opt.h" + #include "avcodec.h" #include "huffyuv.h" #include "huffman.h" #include "huffyuvencdsp.h" +#include "internal.h" #include "put_bits.h" static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, @@ -153,12 +156,21 @@ static av_cold int encode_init(AVCodecContext *avctx) avctx->stats_out = av_mallocz(1024*30); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132 s->version = 2; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) + if (!avctx->extradata || !avctx->stats_out) return AVERROR(ENOMEM); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->context_model == 1) + s->context = avctx->context_model; +FF_ENABLE_DEPRECATION_WARNINGS +#endif switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: @@ -181,17 +193,21 @@ static av_cold int encode_init(AVCodecContext *avctx) } avctx->bits_per_coded_sample = s->bitstream_bpp; s->decorrelate = s->bitstream_bpp >= 24; - s->predictor = avctx->prediction_method; - s->interlaced = avctx->flags&CODEC_FLAG_INTERLACED_ME ? 1 : 0; - if (avctx->context_model == 1) { - s->context = avctx->context_model; - if (s->flags & (CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)) { +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->prediction_method) + s->predictor = avctx->prediction_method; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + s->interlaced = avctx->flags & AV_CODEC_FLAG_INTERLACED_ME ? 1 : 0; + if (s->context) { + if (s->flags & (AV_CODEC_FLAG_PASS1 | AV_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 == AV_CODEC_ID_HUFFYUV) { if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { @@ -200,12 +216,14 @@ static av_cold int encode_init(AVCodecContext *avctx) "vcodec=ffvhuff or format=422p\n"); return -1; } - if (avctx->context_model) { +#if FF_API_PRIVATE_OPT + if (s->context) { av_log(avctx, AV_LOG_ERROR, "Error: per-frame huffman tables are not supported " "by huffyuv; use vcodec=ffvhuff\n"); return -1; } +#endif if (s->interlaced != ( s->height > 288 )) av_log(avctx, AV_LOG_INFO, "using huffyuv 2.2.0 or newer interlacing flag\n"); @@ -304,7 +322,7 @@ static int encode_422_bitstream(HYuvContext *s, int offset, int count) count /= 2; - if (s->flags & CODEC_FLAG_PASS1) { + if (s->flags & AV_CODEC_FLAG_PASS1) { for(i = 0; i < count; i++) { LOAD4; s->stats[0][y0]++; @@ -313,7 +331,7 @@ static int encode_422_bitstream(HYuvContext *s, int offset, int count) s->stats[2][v0]++; } } - if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT) + if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) return 0; if (s->context) { for (i = 0; i < count; i++) { @@ -360,13 +378,13 @@ static int encode_gray_bitstream(HYuvContext *s, int count) count /= 2; - if (s->flags & CODEC_FLAG_PASS1) { + if (s->flags & AV_CODEC_FLAG_PASS1) { for (i = 0; i < count; i++) { LOAD2; STAT2; } } - if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT) + if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) return 0; if (s->context) { @@ -414,13 +432,13 @@ static inline int encode_bgra_bitstream(HYuvContext *s, int count, int planes) if (planes == 4) \ put_bits(&s->pb, s->len[2][a], s->bits[2][a]); - if ((s->flags & CODEC_FLAG_PASS1) && - (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)) { + if ((s->flags & AV_CODEC_FLAG_PASS1) && + (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)) { for (i = 0; i < count; i++) { LOAD_GBRA; STAT_BGRA; } - } else if (s->context || (s->flags & CODEC_FLAG_PASS1)) { + } else if (s->context || (s->flags & AV_CODEC_FLAG_PASS1)) { for (i = 0; i < count; i++) { LOAD_GBRA; STAT_BGRA; @@ -449,7 +467,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int i, j, size = 0, ret; if (!pkt->data && - (ret = av_new_packet(pkt, width * height * 3 * 4 + FF_MIN_BUFFER_SIZE)) < 0) { + (ret = av_new_packet(pkt, width * height * 3 * 4 + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n"); return ret; } @@ -641,7 +659,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, put_bits(&s->pb, 15, 0); size /= 4; - if ((s->flags&CODEC_FLAG_PASS1) && (s->picture_number & 31) == 0) { + if ((s->flags & AV_CODEC_FLAG_PASS1) && (s->picture_number & 31) == 0) { int j; char *p = avctx->stats_out; char *end = p + 1024*30; @@ -656,7 +674,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } } else avctx->stats_out[0] = '\0'; - if (!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)) { + if (!(s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT)) { flush_put_bits(&s->pb); s->bdsp.bswap_buf((uint32_t *) pkt->data, (uint32_t *) pkt->data, size); } @@ -679,17 +697,40 @@ static av_cold int encode_end(AVCodecContext *avctx) av_freep(&avctx->extradata); av_freep(&avctx->stats_out); - av_frame_free(&avctx->coded_frame); - return 0; } +#define OFFSET(x) offsetof(HYuvContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +#define HUFF_CLASS(variant) \ +static const AVClass variant ## _class = { \ + .class_name = # variant, \ + .item_name = av_default_item_name, \ + .option = variant ## _options, \ + .version = LIBAVUTIL_VERSION_INT, \ +} + +#define FF_HUFFYUV_COMMON_OPTS \ +{ "pred", "Prediction method", OFFSET(predictor), AV_OPT_TYPE_INT, { .i64 = LEFT }, LEFT, MEDIAN, VE, "pred" }, \ + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LEFT }, INT_MIN, INT_MAX, VE, "pred" }, \ + { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PLANE }, INT_MIN, INT_MAX, VE, "pred" }, \ + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MEDIAN }, INT_MIN, INT_MAX, VE, "pred" } + +static const AVOption huffyuv_options[] = { + FF_HUFFYUV_COMMON_OPTS, + { NULL}, +}; + +HUFF_CLASS(huffyuv); + AVCodec ff_huffyuv_encoder = { .name = "huffyuv", .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HUFFYUV, .priv_data_size = sizeof(HYuvContext), + .priv_class = &huffyuv_class, .init = encode_init, .encode2 = encode_frame, .close = encode_end, @@ -697,15 +738,26 @@ AVCodec ff_huffyuv_encoder = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; #if CONFIG_FFVHUFF_ENCODER +static const AVOption ffhuffyuv_options[] = { + FF_HUFFYUV_COMMON_OPTS, + { "context", "Set per-frame huffman tables", OFFSET(context), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL } +}; + +HUFF_CLASS(ffhuffyuv); + AVCodec ff_ffvhuff_encoder = { .name = "ffvhuff", .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_FFVHUFF, .priv_data_size = sizeof(HYuvContext), + .priv_class = &ffhuffyuv_class, .init = encode_init, .encode2 = encode_frame, .close = encode_end, @@ -713,5 +765,7 @@ AVCodec ff_ffvhuff_encoder = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c index 70c98d6..67dcf1c 100644 --- a/libavcodec/idcinvideo.c +++ b/libavcodec/idcinvideo.c @@ -1,6 +1,6 @@ /* * id Quake II CIN Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -56,8 +56,7 @@ #define HUF_TOKENS 256 #define PALETTE_COUNT 256 -typedef struct -{ +typedef struct hnode { int count; unsigned char used; int children[2]; @@ -248,5 +247,5 @@ AVCodec ff_idcin_decoder = { .priv_data_size = sizeof(IdcinContext), .init = idcin_decode_init, .decode = idcin_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 6beb2b2..a9b8727 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -79,6 +79,9 @@ av_cold void ff_init_scantable_permutation(uint8_t *idct_permutation, } } +void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); +void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); + static void put_pixels_clamped_c(const int16_t *block, uint8_t *restrict pixels, int line_size) { @@ -141,18 +144,6 @@ static void add_pixels_clamped_c(const int16_t *block, uint8_t *restrict pixels, } } -static void jref_idct_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct(block); - put_pixels_clamped_c(block, dest, line_size); -} - -static void jref_idct_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_j_rev_dct(block); - add_pixels_clamped_c(block, dest, line_size); -} - av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) { const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; @@ -163,15 +154,17 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->idct = ff_simple_idct_10; c->perm_type = FF_IDCT_PERM_NONE; } else if (avctx->idct_algo == FF_IDCT_INT) { - c->idct_put = jref_idct_put; - c->idct_add = jref_idct_add; + c->idct_put = ff_jref_idct_put; + c->idct_add = ff_jref_idct_add; c->idct = ff_j_rev_dct; c->perm_type = FF_IDCT_PERM_LIBMPEG2; +#if CONFIG_FAANIDCT } else if (avctx->idct_algo == FF_IDCT_FAAN) { c->idct_put = ff_faanidct_put; c->idct_add = ff_faanidct_add; c->idct = ff_faanidct; c->perm_type = FF_IDCT_PERM_NONE; +#endif /* CONFIG_FAANIDCT */ } else { // accurate/default c->idct_put = ff_simple_idct_put_8; c->idct_add = ff_simple_idct_add_8; @@ -183,6 +176,9 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; c->add_pixels_clamped = add_pixels_clamped_c; + ff_put_pixels_clamped = c->put_pixels_clamped; + ff_add_pixels_clamped = c->add_pixels_clamped; + if (ARCH_ARM) ff_idctdsp_init_arm(c, avctx, high_bit_depth); if (ARCH_PPC) diff --git a/libavcodec/idctdsp.h b/libavcodec/idctdsp.h index b88cc82..c49a4ca 100644 --- a/libavcodec/idctdsp.h +++ b/libavcodec/idctdsp.h @@ -95,6 +95,9 @@ typedef struct IDCTDSPContext { enum idct_permutation_type perm_type; } IDCTDSPContext; +extern void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); +extern void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); + void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx); void ff_idctdsp_init_arm(IDCTDSPContext *c, AVCodecContext *avctx, diff --git a/libavcodec/iff.c b/libavcodec/iff.c index 112c2ca..a186e31 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -28,12 +28,12 @@ #include #include "libavutil/imgutils.h" + #include "bytestream.h" #include "avcodec.h" -#include "get_bits.h" #include "internal.h" -typedef struct { +typedef struct IffContext { AVFrame *frame; int planesize; uint8_t * planebuf; @@ -172,7 +172,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx))) return err; s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary - s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE); + s->planebuf = av_malloc(s->planesize + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->planebuf) return AVERROR(ENOMEM); @@ -382,7 +382,7 @@ AVCodec ff_iff_ilbm_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame_ilbm, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; AVCodec ff_iff_byterun1_decoder = { @@ -394,5 +394,5 @@ AVCodec ff_iff_byterun1_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame_byterun1, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/iirfilter.c b/libavcodec/iirfilter.c index 40a543d..442c837 100644 --- a/libavcodec/iirfilter.c +++ b/libavcodec/iirfilter.c @@ -24,27 +24,29 @@ * different IIR filters implementation */ -#include "iirfilter.h" #include + #include "libavutil/attributes.h" #include "libavutil/common.h" +#include "iirfilter.h" + /** * IIR filter global parameters */ -typedef struct FFIIRFilterCoeffs{ +typedef struct FFIIRFilterCoeffs { int order; float gain; int *cx; float *cy; -}FFIIRFilterCoeffs; +} FFIIRFilterCoeffs; /** * IIR filter state */ -typedef struct FFIIRFilterState{ +typedef struct FFIIRFilterState { float x[1]; -}FFIIRFilterState; +} FFIIRFilterState; /// maximum supported filter order #define MAXORDER 30 @@ -61,51 +63,50 @@ static av_cold int butterworth_init_coeffs(void *avc, if (filt_mode != FF_FILTER_MODE_LOWPASS) { av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports " - "low-pass filter mode\n"); + "low-pass filter mode\n"); return -1; } if (order & 1) { av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports " - "even filter orders\n"); + "even filter orders\n"); return -1; } wa = 2 * tan(M_PI * 0.5 * cutoff_ratio); c->cx[0] = 1; - for(i = 1; i < (order >> 1) + 1; i++) + for (i = 1; i < (order >> 1) + 1; i++) c->cx[i] = c->cx[i - 1] * (order - i + 1LL) / i; p[0][0] = 1.0; p[0][1] = 0.0; - for(i = 1; i <= order; i++) + for (i = 1; i <= order; i++) p[i][0] = p[i][1] = 0.0; - for(i = 0; i < order; i++){ + for (i = 0; i < order; i++) { double zp[2]; double th = (i + (order >> 1) + 0.5) * M_PI / order; double a_re, a_im, c_re, c_im; zp[0] = cos(th) * wa; zp[1] = sin(th) * wa; - a_re = zp[0] + 2.0; - c_re = zp[0] - 2.0; - a_im = - c_im = zp[1]; + a_re = zp[0] + 2.0; + c_re = zp[0] - 2.0; + a_im = + c_im = zp[1]; zp[0] = (a_re * c_re + a_im * c_im) / (c_re * c_re + c_im * c_im); zp[1] = (a_im * c_re - a_re * c_im) / (c_re * c_re + c_im * c_im); - for(j = order; j >= 1; j--) - { - a_re = p[j][0]; - a_im = p[j][1]; - p[j][0] = a_re*zp[0] - a_im*zp[1] + p[j-1][0]; - p[j][1] = a_re*zp[1] + a_im*zp[0] + p[j-1][1]; + for (j = order; j >= 1; j--) { + a_re = p[j][0]; + a_im = p[j][1]; + p[j][0] = a_re * zp[0] - a_im * zp[1] + p[j - 1][0]; + p[j][1] = a_re * zp[1] + a_im * zp[0] + p[j - 1][1]; } - a_re = p[0][0]*zp[0] - p[0][1]*zp[1]; - p[0][1] = p[0][0]*zp[1] + p[0][1]*zp[0]; + a_re = p[0][0] * zp[0] - p[0][1] * zp[1]; + p[0][1] = p[0][0] * zp[1] + p[0][1] * zp[0]; p[0][0] = a_re; } c->gain = p[order][0]; - for(i = 0; i < order; i++){ + for (i = 0; i < order; i++) { c->gain += p[i][0]; c->cy[i] = (-p[i][0] * p[order][0] + -p[i][1] * p[order][1]) / (p[order][0] * p[order][0] + p[order][1] * p[order][1]); @@ -125,7 +126,7 @@ static av_cold int biquad_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c, if (filt_mode != FF_FILTER_MODE_HIGHPASS && filt_mode != FF_FILTER_MODE_LOWPASS) { av_log(avc, AV_LOG_ERROR, "Biquad filter currently only supports " - "high-pass and low-pass filter modes\n"); + "high-pass and low-pass filter modes\n"); return -1; } if (order != 2) { @@ -158,11 +159,11 @@ static av_cold int biquad_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c, return 0; } -av_cold struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc, - enum IIRFilterType filt_type, - enum IIRFilterMode filt_mode, - int order, float cutoff_ratio, - float stopband, float ripple) +av_cold struct FFIIRFilterCoeffs *ff_iir_filter_init_coeffs(void *avc, + enum IIRFilterType filt_type, + enum IIRFilterMode filt_mode, + int order, float cutoff_ratio, + float stopband, float ripple) { FFIIRFilterCoeffs *c; int ret = 0; @@ -170,12 +171,12 @@ av_cold struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc, if (order <= 0 || order > MAXORDER || cutoff_ratio >= 1.0) return NULL; - FF_ALLOCZ_OR_GOTO(avc, c, sizeof(FFIIRFilterCoeffs), - init_fail); - FF_ALLOC_OR_GOTO (avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1), - init_fail); - FF_ALLOC_OR_GOTO (avc, c->cy, sizeof(c->cy[0]) * order, + FF_ALLOCZ_OR_GOTO(avc, c, sizeof(FFIIRFilterCoeffs), init_fail); + FF_ALLOC_OR_GOTO(avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1), + init_fail); + FF_ALLOC_OR_GOTO(avc, c->cy, sizeof(c->cy[0]) * order, + init_fail); c->order = order; switch (filt_type) { @@ -200,9 +201,9 @@ init_fail: return NULL; } -av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order) +av_cold struct FFIIRFilterState *ff_iir_filter_init_state(int order) { - FFIIRFilterState* s = av_mallocz(sizeof(FFIIRFilterState) + sizeof(s->x[0]) * (order - 1)); + FFIIRFilterState *s = av_mallocz(sizeof(FFIIRFilterState) + sizeof(s->x[0]) * (order - 1)); return s; } @@ -210,17 +211,19 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order) #define CONV_FLT(dest, source) dest = source; -#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt) \ - in = *src0 * c->gain \ - + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1] \ - + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3]; \ - res = (s->x[i0] + in )*1 \ - + (s->x[i1] + s->x[i3])*4 \ - + s->x[i2] *6; \ - CONV_##fmt(*dst0, res) \ - s->x[i0] = in; \ - src0 += sstep; \ - dst0 += dstep; +#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt) \ + in = *src0 * c->gain + \ + c->cy[0] * s->x[i0] + \ + c->cy[1] * s->x[i1] + \ + c->cy[2] * s->x[i2] + \ + c->cy[3] * s->x[i3]; \ + res = (s->x[i0] + in) * 1 + \ + (s->x[i1] + s->x[i3]) * 4 + \ + s->x[i2] * 6; \ + CONV_ ## fmt(*dst0, res) \ + s->x[i0] = in; \ + src0 += sstep; \ + dst0 += dstep; #define FILTER_BW_O4(type, fmt) { \ int i; \ @@ -243,17 +246,17 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order) int j; \ float in, res; \ in = *src0 * c->gain; \ - for(j = 0; j < c->order; j++) \ + for (j = 0; j < c->order; j++) \ in += c->cy[j] * s->x[j]; \ res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1]; \ - for(j = 1; j < c->order >> 1; j++) \ + for (j = 1; j < c->order >> 1; j++) \ res += (s->x[j] + s->x[c->order - j]) * c->cx[j]; \ - for(j = 0; j < c->order - 1; j++) \ + for (j = 0; j < c->order - 1; j++) \ s->x[j] = s->x[j + 1]; \ - CONV_##fmt(*dst0, res) \ + CONV_ ## fmt(*dst0, res) \ s->x[c->order - 1] = in; \ - src0 += sstep; \ - dst0 += dstep; \ + src0 += sstep; \ + dst0 += dstep; \ } \ } @@ -265,11 +268,11 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order) float in = *src0 * c->gain + \ s->x[0] * c->cy[0] + \ s->x[1] * c->cy[1]; \ - CONV_##fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1]) \ + CONV_ ## fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1]) \ s->x[0] = s->x[1]; \ s->x[1] = in; \ - src0 += sstep; \ - dst0 += dstep; \ + src0 += sstep; \ + dst0 += dstep; \ } \ } @@ -306,42 +309,9 @@ av_cold void ff_iir_filter_free_state(struct FFIIRFilterState *state) av_cold void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs *coeffs) { - if(coeffs){ + if (coeffs) { av_free(coeffs->cx); av_free(coeffs->cy); } av_free(coeffs); } - -#ifdef TEST -#include - -#define FILT_ORDER 4 -#define SIZE 1024 -int main(void) -{ - struct FFIIRFilterCoeffs *fcoeffs = NULL; - struct FFIIRFilterState *fstate = NULL; - float cutoff_coeff = 0.4; - int16_t x[SIZE], y[SIZE]; - int i; - - fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH, - FF_FILTER_MODE_LOWPASS, FILT_ORDER, - cutoff_coeff, 0.0, 0.0); - fstate = ff_iir_filter_init_state(FILT_ORDER); - - for (i = 0; i < SIZE; i++) { - x[i] = lrint(0.75 * INT16_MAX * sin(0.5*M_PI*i*i/SIZE)); - } - - ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1); - - for (i = 0; i < SIZE; i++) - printf("%6d %6d\n", x[i], y[i]); - - ff_iir_filter_free_coeffs(fcoeffs); - ff_iir_filter_free_state(fstate); - return 0; -} -#endif /* TEST */ diff --git a/libavcodec/imc.c b/libavcodec/imc.c index 26fbcd4..9a6912d 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -27,7 +27,6 @@ * A mdct based codec using a 256 points large transform * divided into 32 bands with some mix of scale factors. * Only mono is supported. - * */ @@ -70,7 +69,7 @@ typedef struct IMCChannel { 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 skipFlagCount[BANDS]; ///< skipped coefficients per band int skipFlags[COEFFS]; ///< skip coefficient decoding or not int codewords[COEFFS]; ///< raw codewords read from bitstream @@ -79,7 +78,7 @@ typedef struct IMCChannel { int decoder_reset; } IMCChannel; -typedef struct { +typedef struct IMCContext { IMCChannel chctx[2]; /** MDCT tables */ @@ -247,7 +246,7 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) return ret; } ff_bswapdsp_init(&q->bdsp); - avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&q->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; @@ -411,7 +410,7 @@ static void imc_decode_level_coefficients_raw(IMCContext *q, int *levlCoeffBuf, pos = q->coef0_pos; flcoeffs1[pos] = 20000.0 / pow (2, levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125 - flcoeffs2[pos] = log2f(flcoeffs1[0]); + flcoeffs2[pos] = log2f(flcoeffs1[pos]); tmp = flcoeffs1[pos]; tmp2 = flcoeffs2[pos]; @@ -783,7 +782,7 @@ static int imc_get_coeffs(IMCContext *q, IMCChannel *chctx) cw = 0; if (get_bits_count(&q->gb) + cw_len > 512) { - av_dlog(NULL, "Band %i coeff %i cw_len %i\n", i, j, cw_len); + ff_dlog(NULL, "Band %i coeff %i cw_len %i\n", i, j, cw_len); return AVERROR_INVALIDDATA; } @@ -997,7 +996,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, IMCContext *q = avctx->priv_data; - LOCAL_ALIGNED_16(uint16_t, buf16, [(IMC_BLOCK_SIZE + FF_INPUT_BUFFER_PADDING_SIZE) / 2]); + LOCAL_ALIGNED_16(uint16_t, buf16, [(IMC_BLOCK_SIZE + AV_INPUT_BUFFER_PADDING_SIZE) / 2]); if (buf_size < IMC_BLOCK_SIZE * avctx->channels) { av_log(avctx, AV_LOG_ERROR, "frame too small!\n"); @@ -1054,7 +1053,7 @@ AVCodec ff_imc_decoder = { .init = imc_decode_init, .close = imc_decode_close, .decode = imc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; @@ -1068,7 +1067,7 @@ AVCodec ff_iac_decoder = { .init = imc_decode_init, .close = imc_decode_close, .decode = imc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/opus_imdct.c b/libavcodec/imdct15.c similarity index 91% rename from libavcodec/opus_imdct.c rename to libavcodec/imdct15.c index 38674ed..e02e9ce 100644 --- a/libavcodec/opus_imdct.c +++ b/libavcodec/imdct15.c @@ -33,8 +33,8 @@ #include "libavutil/common.h" #include "avfft.h" +#include "imdct15.h" #include "opus.h" -#include "opus_imdct.h" // minimal iMDCT size to make SIMD opts easier #define CELT_MIN_IMDCT_SIZE 120 @@ -66,9 +66,9 @@ do { \ (d).im = -ri + ir; \ } while (0) -av_cold void ff_celt_imdct_uninit(CeltIMDCTContext **ps) +av_cold void ff_imdct15_uninit(IMDCT15Context **ps) { - CeltIMDCTContext *s = *ps; + IMDCT15Context *s = *ps; int i; if (!s) @@ -84,12 +84,12 @@ av_cold void ff_celt_imdct_uninit(CeltIMDCTContext **ps) av_freep(ps); } -static void celt_imdct_half(CeltIMDCTContext *s, float *dst, const float *src, - ptrdiff_t stride, float scale); +static void imdct15_half(IMDCT15Context *s, float *dst, const float *src, + ptrdiff_t stride, float scale); -av_cold int ff_celt_imdct_init(CeltIMDCTContext **ps, int N) +av_cold int ff_imdct15_init(IMDCT15Context **ps, int N) { - CeltIMDCTContext *s; + IMDCT15Context *s; int len2 = 15 * (1 << N); int len = 2 * len2; int i, j; @@ -134,16 +134,17 @@ av_cold int ff_celt_imdct_init(CeltIMDCTContext **ps, int N) for (j = 15; j < 19; j++) s->exptab[0][j] = s->exptab[0][j - 15]; - s->imdct_half = celt_imdct_half; + s->imdct_half = imdct15_half; if (ARCH_AARCH64) - ff_celt_imdct_init_aarch64(s); + ff_imdct15_init_aarch64(s); *ps = s; return 0; + fail: - ff_celt_imdct_uninit(&s); + ff_imdct15_uninit(&s); return AVERROR(ENOMEM); } @@ -180,7 +181,8 @@ static void fft5(FFTComplex *out, const FFTComplex *in, ptrdiff_t stride) out[4].im = in[0].im + z[0][3].im + z[1][2].im + z[2][1].im + z[3][0].im; } -static void fft15(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in, ptrdiff_t stride) +static void fft15(IMDCT15Context *s, FFTComplex *out, const FFTComplex *in, + ptrdiff_t stride) { const FFTComplex *exptab = s->exptab[0]; FFTComplex tmp[5]; @@ -215,7 +217,7 @@ static void fft15(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in, pt /* * FFT of the length 15 * (2^N) */ -static void fft_calc(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in, +static void fft_calc(IMDCT15Context *s, FFTComplex *out, const FFTComplex *in, int N, ptrdiff_t stride) { if (N) { @@ -241,8 +243,8 @@ static void fft_calc(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in, fft15(s, out, in, stride); } -static void celt_imdct_half(CeltIMDCTContext *s, float *dst, const float *src, - ptrdiff_t stride, float scale) +static void imdct15_half(IMDCT15Context *s, float *dst, const float *src, + ptrdiff_t stride, float scale) { FFTComplex *z = (FFTComplex *)dst; const int len8 = s->len4 / 2; diff --git a/libavcodec/opus_imdct.h b/libavcodec/imdct15.h similarity index 74% rename from libavcodec/opus_imdct.h rename to libavcodec/imdct15.h index d4bff9a..ed3f003 100644 --- a/libavcodec/opus_imdct.h +++ b/libavcodec/imdct15.h @@ -16,14 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_OPUS_IMDCT_H -#define AVCODEC_OPUS_IMDCT_H +#ifndef AVCODEC_IMDCT15_H +#define AVCODEC_IMDCT15_H #include #include "avfft.h" -typedef struct CeltIMDCTContext { +typedef struct IMDCT15Context { int fft_n; int len2; int len4; @@ -37,21 +37,21 @@ typedef struct CeltIMDCTContext { /** * Calculate the middle half of the iMDCT */ - void (*imdct_half)(struct CeltIMDCTContext *s, float *dst, const float *src, + void (*imdct_half)(struct IMDCT15Context *s, float *dst, const float *src, ptrdiff_t src_stride, float scale); -} CeltIMDCTContext; +} IMDCT15Context; /** * Init an iMDCT of the length 2 * 15 * (2^N) */ -int ff_celt_imdct_init(CeltIMDCTContext **s, int N); +int ff_imdct15_init(IMDCT15Context **s, int N); /** * Free an iMDCT. */ -void ff_celt_imdct_uninit(CeltIMDCTContext **s); +void ff_imdct15_uninit(IMDCT15Context **s); -void ff_celt_imdct_init_aarch64(CeltIMDCTContext *s); +void ff_imdct15_init_aarch64(IMDCT15Context *s); -#endif /* AVCODEC_OPUS_IMDCT_H */ +#endif /* AVCODEC_IMDCT15_H */ diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 365dc54..4667a4f 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -24,27 +24,23 @@ * misc image conversion routines */ -/* TODO: - * - write 'ffimg' program to test all the image related stuff - * - move all api to slice based system - * - integrate deinterlacing, postprocessing and scaling in the conversion process - */ - #include "avcodec.h" -#include "imgconvert.h" #include "internal.h" #include "mathops.h" #include "libavutil/colorspace.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" +#include "libavutil/internal.h" #include "libavutil/imgutils.h" +#if FF_API_GETCHROMA void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); *h_shift = desc->log2_chroma_w; *v_shift = desc->log2_chroma_h; } +#endif static int is_gray(const AVPixFmtDescriptor *desc) { @@ -67,7 +63,7 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, return 0; for (i = 0; i < nb_components; i++) - if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1) + if (src_desc->comp[i].depth > dst_desc->comp[i].depth) loss |= FF_LOSS_DEPTH; if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w || @@ -78,7 +74,7 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, loss |= FF_LOSS_COLORSPACE; if (has_alpha && !(dst_desc->flags & AV_PIX_FMT_FLAG_ALPHA) && - (dst_desc->flags & AV_PIX_FMT_FLAG_ALPHA)) + (src_desc->flags & AV_PIX_FMT_FLAG_ALPHA)) loss |= FF_LOSS_ALPHA; if (dst_pix_fmt == AV_PIX_FMT_PAL8 && !is_gray(src_desc)) @@ -159,92 +155,8 @@ enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list, return dst_pix_fmt; } -/* 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; - } -} - +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS /* return true if yuv planar */ static inline int is_yuv_planar(const AVPixFmtDescriptor *desc) { @@ -336,171 +248,5 @@ int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, return 0; } -#if FF_API_DEINTERLACE - -#if HAVE_MMX_EXTERNAL -#define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx -#define deinterlace_line ff_deinterlace_line_mmx -#else -#define deinterlace_line_inplace deinterlace_line_inplace_c -#define deinterlace_line deinterlace_line_c - -/* filter parameters: [-1 4 2 4 -1] // 8 */ -static void deinterlace_line_c(uint8_t *dst, - const uint8_t *lum_m4, const uint8_t *lum_m3, - const uint8_t *lum_m2, const uint8_t *lum_m1, - const uint8_t *lum, - int size) -{ - const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; - int sum; - - for(;size > 0;size--) { - sum = -lum_m4[0]; - sum += lum_m3[0] << 2; - sum += lum_m2[0] << 1; - sum += lum_m1[0] << 2; - sum += -lum[0]; - dst[0] = cm[(sum + 4) >> 3]; - lum_m4++; - lum_m3++; - lum_m2++; - lum_m1++; - lum++; - dst++; - } -} - -static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3, - uint8_t *lum_m2, uint8_t *lum_m1, - uint8_t *lum, int size) -{ - const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; - int sum; - - for(;size > 0;size--) { - sum = -lum_m4[0]; - sum += lum_m3[0] << 2; - sum += lum_m2[0] << 1; - lum_m4[0]=lum_m2[0]; - sum += lum_m1[0] << 2; - sum += -lum[0]; - lum_m2[0] = cm[(sum + 4) >> 3]; - lum_m4++; - lum_m3++; - lum_m2++; - lum_m1++; - lum++; - } -} -#endif /* !HAVE_MMX_EXTERNAL */ - -/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The - top field is copied as is, but the bottom field is deinterlaced - against the top field. */ -static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, - const uint8_t *src1, int src_wrap, - int width, int height) -{ - const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; - int y; - - src_m2 = src1; - src_m1 = src1; - src_0=&src_m1[src_wrap]; - src_p1=&src_0[src_wrap]; - src_p2=&src_p1[src_wrap]; - for(y=0;y<(height-2);y+=2) { - memcpy(dst,src_m1,width); - dst += dst_wrap; - deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width); - src_m2 = src_0; - src_m1 = src_p1; - src_0 = src_p2; - src_p1 += 2*src_wrap; - src_p2 += 2*src_wrap; - dst += dst_wrap; - } - memcpy(dst,src_m1,width); - dst += dst_wrap; - /* do last line */ - deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width); -} - -static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, - int width, int height) -{ - uint8_t *src_m1, *src_0, *src_p1, *src_p2; - int y; - uint8_t *buf; - buf = av_malloc(width); - - src_m1 = src1; - memcpy(buf,src_m1,width); - src_0=&src_m1[src_wrap]; - src_p1=&src_0[src_wrap]; - src_p2=&src_p1[src_wrap]; - for(y=0;y<(height-2);y+=2) { - deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width); - src_m1 = src_p1; - src_0 = src_p2; - src_p1 += 2*src_wrap; - src_p2 += 2*src_wrap; - } - /* do last line */ - deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width); - av_free(buf); -} - -int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, - enum AVPixelFormat pix_fmt, int width, int height) -{ - int i; - - if (pix_fmt != AV_PIX_FMT_YUV420P && - pix_fmt != AV_PIX_FMT_YUVJ420P && - pix_fmt != AV_PIX_FMT_YUV422P && - pix_fmt != AV_PIX_FMT_YUVJ422P && - pix_fmt != AV_PIX_FMT_YUV444P && - pix_fmt != AV_PIX_FMT_YUV411P && - pix_fmt != AV_PIX_FMT_GRAY8) - return -1; - if ((width & 3) != 0 || (height & 3) != 0) - return -1; - - for(i=0;i<3;i++) { - if (i == 1) { - switch(pix_fmt) { - case AV_PIX_FMT_YUVJ420P: - case AV_PIX_FMT_YUV420P: - width >>= 1; - height >>= 1; - break; - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUVJ422P: - width >>= 1; - break; - case AV_PIX_FMT_YUV411P: - width >>= 2; - break; - default: - break; - } - if (pix_fmt == AV_PIX_FMT_GRAY8) { - break; - } - } - if (src == dst) { - deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], - width, height); - } else { - deinterlace_bottom_field(dst->data[i],dst->linesize[i], - src->data[i], src->linesize[i], - width, height); - } - } - emms_c(); - return 0; -} - -#endif /* FF_API_DEINTERLACE */ +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* FF_API_AVPICTURE */ diff --git a/libavcodec/imgconvert.h b/libavcodec/imgconvert.h deleted file mode 100644 index 56d89b2..0000000 --- a/libavcodec/imgconvert.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_IMGCONVERT_H -#define AVCODEC_IMGCONVERT_H - -#include - -#include "version.h" - -#if FF_API_DEINTERLACE - -void ff_deinterlace_line_mmx(uint8_t *dst, - const uint8_t *lum_m4, const uint8_t *lum_m3, - const uint8_t *lum_m2, const uint8_t *lum_m1, - const uint8_t *lum, - int size); - -void ff_deinterlace_line_inplace_mmx(const uint8_t *lum_m4, - const uint8_t *lum_m3, - const uint8_t *lum_m2, - const uint8_t *lum_m1, - const uint8_t *lum, int size); - -#endif /* FF_API_DEINTERLACE */ - -/* 1/2^n downscaling functions */ -void ff_shrink22(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); -void ff_shrink44(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); -void ff_shrink88(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); - -#endif /* AVCODEC_IMGCONVERT_H */ diff --git a/libavcodec/imx_dump_header_bsf.c b/libavcodec/imx_dump_header_bsf.c index 5f5493f..71bda02 100644 --- a/libavcodec/imx_dump_header_bsf.c +++ b/libavcodec/imx_dump_header_bsf.c @@ -26,34 +26,51 @@ */ #include "avcodec.h" +#include "bsf.h" #include "bytestream.h" -static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe) +static int imx_dump_header(AVBSFContext *ctx, AVPacket *out) { /* MXF essence element key */ static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }; - uint8_t *poutbufp; - - if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) { - av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n"); - return 0; - } - - *poutbuf = av_malloc(buf_size + 20 + FF_INPUT_BUFFER_PADDING_SIZE); - poutbufp = *poutbuf; - bytestream_put_buffer(&poutbufp, imx_header, 16); - bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */ - bytestream_put_be24(&poutbufp, buf_size); - bytestream_put_buffer(&poutbufp, buf, buf_size); - *poutbuf_size = poutbufp - *poutbuf; - return 1; + + AVPacket *in; + int ret = 0; + uint8_t *out_buf; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + ret = av_new_packet(out, in->size + 20); + if (ret < 0) + goto fail; + + out_buf = out->data; + + bytestream_put_buffer(&out_buf, imx_header, 16); + bytestream_put_byte(&out_buf, 0x83); /* KLV BER long form */ + bytestream_put_be24(&out_buf, in->size); + bytestream_put_buffer(&out_buf, in->data, in->size); + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; } -AVBitStreamFilter ff_imx_dump_header_bsf = { - "imxdump", - 0, - imx_dump_header, +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_imx_dump_header_bsf = { + .name = "imxdump", + .filter = imx_dump_header, + .codec_ids = codec_ids, }; diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c index 4221e9e..3154e23 100644 --- a/libavcodec/indeo2.c +++ b/libavcodec/indeo2.c @@ -24,8 +24,9 @@ * Intel Indeo 2 decoder. */ -#define BITSTREAM_READER_LE #include "libavutil/attributes.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "indeo2data.h" @@ -148,6 +149,7 @@ static int ir2_decode_frame(AVCodecContext *avctx, AVFrame *picture = data; AVFrame * const p = s->picture; int start, ret; + int ltab, ctab; if ((ret = ff_reget_buffer(avctx, p)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); @@ -171,34 +173,36 @@ static int ir2_decode_frame(AVCodecContext *avctx, init_get_bits(&s->gb, buf + start, (buf_size - start) * 8); + ltab = buf[0x22] & 3; + ctab = buf[0x22] >> 2; if (s->decode_delta) { /* intraframe */ if ((ret = ir2_decode_plane(s, avctx->width, avctx->height, p->data[0], p->linesize[0], - ir2_luma_table)) < 0) + ir2_delta_table[ltab])) < 0) return ret; /* swapped U and V */ if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, p->data[2], p->linesize[2], - ir2_luma_table)) < 0) + ir2_delta_table[ctab])) < 0) return ret; if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, p->data[1], p->linesize[1], - ir2_luma_table)) < 0) + ir2_delta_table[ctab])) < 0) return ret; } else { /* interframe */ if ((ret = ir2_decode_plane_inter(s, avctx->width, avctx->height, p->data[0], p->linesize[0], - ir2_luma_table)) < 0) + ir2_delta_table[ltab])) < 0) return ret; /* swapped U and V */ if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, p->data[2], p->linesize[2], - ir2_luma_table)) < 0) + ir2_delta_table[ctab])) < 0) return ret; if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, p->data[1], p->linesize[1], - ir2_luma_table)) < 0) + ir2_delta_table[ctab])) < 0) return ret; } @@ -256,5 +260,5 @@ AVCodec ff_indeo2_decoder = { .init = ir2_decode_init, .close = ir2_decode_end, .decode = ir2_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/indeo2data.h b/libavcodec/indeo2data.h index ed8d83c..3d7411d 100644 --- a/libavcodec/indeo2data.h +++ b/libavcodec/indeo2data.h @@ -26,116 +26,173 @@ #define IR2_CODES 143 static const uint16_t ir2_codes[IR2_CODES][2] = { -#ifdef BITSTREAM_READER_LE -{0x0000, 3}, {0x0004, 3}, {0x0006, 3}, {0x0001, 5}, -{0x0009, 5}, {0x0019, 5}, {0x000D, 5}, {0x001D, 5}, -{0x0023, 6}, {0x0013, 6}, {0x0033, 6}, {0x000B, 6}, -{0x002B, 6}, {0x001B, 6}, {0x0007, 8}, {0x0087, 8}, -{0x0027, 8}, {0x00A7, 8}, {0x0067, 8}, {0x00E7, 8}, -{0x0097, 8}, {0x0057, 8}, {0x0037, 8}, {0x00B7, 8}, -{0x00F7, 8}, {0x000F, 9}, {0x008F, 9}, {0x018F, 9}, -{0x014F, 9}, {0x00CF, 9}, {0x002F, 9}, {0x012F, 9}, -{0x01AF, 9}, {0x006F, 9}, {0x00EF, 9}, {0x01EF, 9}, -{0x001F, 10}, {0x021F, 10}, {0x011F, 10}, {0x031F, 10}, -{0x009F, 10}, {0x029F, 10}, {0x019F, 10}, {0x039F, 10}, -{0x005F, 10}, {0x025F, 10}, {0x015F, 10}, {0x035F, 10}, -{0x00DF, 10}, {0x02DF, 10}, {0x01DF, 10}, {0x03DF, 10}, -{0x003F, 13}, {0x103F, 13}, {0x083F, 13}, {0x183F, 13}, -{0x043F, 13}, {0x143F, 13}, {0x0C3F, 13}, {0x1C3F, 13}, -{0x023F, 13}, {0x123F, 13}, {0x0A3F, 13}, {0x1A3F, 13}, -{0x063F, 13}, {0x163F, 13}, {0x0E3F, 13}, {0x1E3F, 13}, -{0x013F, 13}, {0x113F, 13}, {0x093F, 13}, {0x193F, 13}, -{0x053F, 13}, {0x153F, 13}, {0x0D3F, 13}, {0x1D3F, 13}, -{0x033F, 13}, {0x133F, 13}, {0x0B3F, 13}, {0x1B3F, 13}, -{0x073F, 13}, {0x173F, 13}, {0x0F3F, 13}, {0x1F3F, 13}, -{0x00BF, 13}, {0x10BF, 13}, {0x08BF, 13}, {0x18BF, 13}, -{0x04BF, 13}, {0x14BF, 13}, {0x0CBF, 13}, {0x1CBF, 13}, -{0x02BF, 13}, {0x12BF, 13}, {0x0ABF, 13}, {0x1ABF, 13}, -{0x06BF, 13}, {0x16BF, 13}, {0x0EBF, 13}, {0x1EBF, 13}, -{0x01BF, 13}, {0x11BF, 13}, {0x09BF, 13}, {0x19BF, 13}, -{0x05BF, 13}, {0x15BF, 13}, {0x0DBF, 13}, {0x1DBF, 13}, -{0x03BF, 13}, {0x13BF, 13}, {0x0BBF, 13}, {0x1BBF, 13}, -{0x07BF, 13}, {0x17BF, 13}, {0x0FBF, 13}, {0x1FBF, 13}, -{0x007F, 14}, {0x207F, 14}, {0x107F, 14}, {0x307F, 14}, -{0x087F, 14}, {0x287F, 14}, {0x187F, 14}, {0x387F, 14}, -{0x047F, 14}, {0x247F, 14}, {0x147F, 14}, {0x0002, 3}, -{0x0011, 5}, {0x0005, 5}, {0x0015, 5}, {0x0003, 6}, -{0x003B, 6}, {0x0047, 8}, {0x00C7, 8}, {0x0017, 8}, -{0x00D7, 8}, {0x0077, 8}, {0x010F, 9}, {0x004F, 9}, -{0x01CF, 9}, {0x00AF, 9}, {0x016F, 9}, -#else - {0x0000, 3}, {0x0001, 3}, {0x0003, 3}, {0x0010, 5}, - {0x0012, 5}, {0x0013, 5}, {0x0016, 5}, {0x0017, 5}, - {0x0031, 6}, {0x0032, 6}, {0x0033, 6}, {0x0034, 6}, - {0x0035, 6}, {0x0036, 6}, {0x00E0, 8}, {0x00E1, 8}, - {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, {0x00E7, 8}, - {0x00E9, 8}, {0x00EA, 8}, {0x00EC, 8}, {0x00ED, 8}, - {0x00EF, 8}, {0x01E0, 9}, {0x01E2, 9}, {0x01E3, 9}, - {0x01E5, 9}, {0x01E6, 9}, {0x01E8, 9}, {0x01E9, 9}, - {0x01EB, 9}, {0x01EC, 9}, {0x01EE, 9}, {0x01EF, 9}, - {0x03E0, 10}, {0x03E1, 10}, {0x03E2, 10}, {0x03E3, 10}, - {0x03E4, 10}, {0x03E5, 10}, {0x03E6, 10}, {0x03E7, 10}, - {0x03E8, 10}, {0x03E9, 10}, {0x03EA, 10}, {0x03EB, 10}, - {0x03EC, 10}, {0x03ED, 10}, {0x03EE, 10}, {0x03EF, 10}, - {0x1F80, 13}, {0x1F81, 13}, {0x1F82, 13}, {0x1F83, 13}, - {0x1F84, 13}, {0x1F85, 13}, {0x1F86, 13}, {0x1F87, 13}, - {0x1F88, 13}, {0x1F89, 13}, {0x1F8A, 13}, {0x1F8B, 13}, - {0x1F8C, 13}, {0x1F8D, 13}, {0x1F8E, 13}, {0x1F8F, 13}, - {0x1F90, 13}, {0x1F91, 13}, {0x1F92, 13}, {0x1F93, 13}, - {0x1F94, 13}, {0x1F95, 13}, {0x1F96, 13}, {0x1F97, 13}, - {0x1F98, 13}, {0x1F99, 13}, {0x1F9A, 13}, {0x1F9B, 13}, - {0x1F9C, 13}, {0x1F9D, 13}, {0x1F9E, 13}, {0x1F9F, 13}, - {0x1FA0, 13}, {0x1FA1, 13}, {0x1FA2, 13}, {0x1FA3, 13}, - {0x1FA4, 13}, {0x1FA5, 13}, {0x1FA6, 13}, {0x1FA7, 13}, - {0x1FA8, 13}, {0x1FA9, 13}, {0x1FAA, 13}, {0x1FAB, 13}, - {0x1FAC, 13}, {0x1FAD, 13}, {0x1FAE, 13}, {0x1FAF, 13}, - {0x1FB0, 13}, {0x1FB1, 13}, {0x1FB2, 13}, {0x1FB3, 13}, - {0x1FB4, 13}, {0x1FB5, 13}, {0x1FB6, 13}, {0x1FB7, 13}, - {0x1FB8, 13}, {0x1FB9, 13}, {0x1FBA, 13}, {0x1FBB, 13}, - {0x1FBC, 13}, {0x1FBD, 13}, {0x1FBE, 13}, {0x1FBF, 13}, - {0x3F80, 14}, {0x3F81, 14}, {0x3F82, 14}, {0x3F83, 14}, - {0x3F84, 14}, {0x3F85, 14}, {0x3F86, 14}, {0x3F87, 14}, - {0x3F88, 14}, {0x3F89, 14}, {0x3F8A, 14}, {0x0002, 3}, - {0x0011, 5}, {0x0014, 5}, {0x0015, 5}, {0x0030, 6}, - {0x0037, 6}, {0x00E2, 8}, {0x00E3, 8}, {0x00E8, 8}, - {0x00EB, 8}, {0x00EE, 8}, {0x01E1, 9}, {0x01E4, 9}, - {0x01E7, 9}, {0x01EA, 9}, {0x01ED, 9} -#endif + { 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 }, }; -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 +static const uint8_t ir2_delta_table[4][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, }, + { 0x80, 0x80, 0x85, 0x85, 0x7B, 0x7B, 0x7E, 0x87, + 0x82, 0x79, 0x87, 0x7E, 0x79, 0x82, 0x8F, 0x8F, + 0x71, 0x71, 0x84, 0x8F, 0x7C, 0x71, 0x8F, 0x84, + 0x71, 0x7C, 0x75, 0x8B, 0x8B, 0x75, 0x8B, 0x75, + 0x75, 0x8B, 0x8E, 0x9A, 0x72, 0x66, 0x9A, 0x8E, + 0x66, 0x72, 0x7B, 0x93, 0x85, 0x6D, 0x93, 0x7B, + 0x6D, 0x85, 0x9B, 0x9B, 0x65, 0x65, 0x82, 0x9D, + 0x7E, 0x63, 0x9D, 0x82, 0x63, 0x7E, 0x9B, 0xA8, + 0x65, 0x58, 0xA8, 0x9B, 0x58, 0x65, 0xA9, 0xA9, + 0x57, 0x57, 0x8D, 0xAA, 0x73, 0x56, 0xAA, 0x8D, + 0x56, 0x73, 0x6E, 0x99, 0x92, 0x67, 0x99, 0x6E, + 0x67, 0x92, 0x76, 0xA2, 0x8A, 0x5E, 0xA2, 0x76, + 0x5E, 0x8A, 0x7F, 0xAF, 0x81, 0x51, 0xAF, 0x7F, + 0x51, 0x81, 0xAB, 0xBA, 0x55, 0x46, 0xBA, 0xAB, + 0x46, 0x55, 0x9A, 0xBB, 0x66, 0x45, 0xBB, 0x9A, + 0x45, 0x66, 0xBB, 0xBB, 0x45, 0x45, 0x60, 0xA0, + 0xA0, 0x60, 0xA0, 0x60, 0x60, 0xA0, 0x8B, 0xBE, + 0x75, 0x42, 0xBE, 0x8B, 0x42, 0x75, 0x66, 0xAA, + 0x9A, 0x56, 0xAA, 0x66, 0x56, 0x9A, 0x70, 0xB5, + 0x90, 0x4B, 0xB5, 0x70, 0x4B, 0x90, 0xBE, 0xCF, + 0x42, 0x31, 0xCF, 0xBE, 0x31, 0x42, 0xAB, 0xD0, + 0x55, 0x30, 0xD0, 0xAB, 0x30, 0x55, 0xD1, 0xD1, + 0x2F, 0x2F, 0x9A, 0xD3, 0x66, 0x2D, 0xD3, 0x9A, + 0x2D, 0x66, 0x7B, 0xC5, 0x85, 0x3B, 0xC5, 0x7B, + 0x3B, 0x85, 0x54, 0xB4, 0xAC, 0x4C, 0xB4, 0x54, + 0x4C, 0xAC, 0x5E, 0xBE, 0xA2, 0x42, 0xBE, 0x5E, + 0x42, 0xA2, 0x87, 0xD8, 0x79, 0x28, 0xD8, 0x87, + 0x28, 0x79, 0xC0, 0xE8, 0x40, 0x18, 0xE8, 0xC0, + 0x18, 0x40, 0xD5, 0xE8, 0x2B, 0x18, 0xE8, 0xD5, + 0x18, 0x2B, 0xAB, 0xE9, 0x55, 0x17, 0xE9, 0xAB, + 0x17, 0x55, 0x68, 0xCD, 0x98, 0x33, 0xCD, 0x68, + 0x33, 0x98, 0xEA, 0xEA, 0x16, 0x16, 0x80, 0x80, }, + { 0x80, 0x80, 0x86, 0x86, 0x7A, 0x7A, 0x7E, 0x88, + 0x82, 0x78, 0x88, 0x7E, 0x78, 0x82, 0x92, 0x92, + 0x6E, 0x6E, 0x85, 0x92, 0x7B, 0x6E, 0x92, 0x85, + 0x6E, 0x7B, 0x73, 0x8D, 0x8D, 0x73, 0x8D, 0x73, + 0x73, 0x8D, 0x91, 0x9E, 0x6F, 0x62, 0x9E, 0x91, + 0x62, 0x6F, 0x79, 0x97, 0x87, 0x69, 0x97, 0x79, + 0x69, 0x87, 0xA0, 0xA0, 0x60, 0x60, 0x83, 0xA2, + 0x7D, 0x5E, 0xA2, 0x83, 0x5E, 0x7D, 0xA0, 0xB0, + 0x60, 0x50, 0xB0, 0xA0, 0x50, 0x60, 0xB1, 0xB1, + 0x4F, 0x4F, 0x8F, 0xB2, 0x71, 0x4E, 0xB2, 0x8F, + 0x4E, 0x71, 0x6B, 0x9E, 0x95, 0x62, 0x9E, 0x6B, + 0x62, 0x95, 0x74, 0xA9, 0x8C, 0x57, 0xA9, 0x74, + 0x57, 0x8C, 0x7F, 0xB8, 0x81, 0x48, 0xB8, 0x7F, + 0x48, 0x81, 0xB4, 0xC5, 0x4C, 0x3B, 0xC5, 0xB4, + 0x3B, 0x4C, 0x9F, 0xC6, 0x61, 0x3A, 0xC6, 0x9F, + 0x3A, 0x61, 0xC6, 0xC6, 0x3A, 0x3A, 0x59, 0xA7, + 0xA7, 0x59, 0xA7, 0x59, 0x59, 0xA7, 0x8D, 0xCA, + 0x73, 0x36, 0xCA, 0x8D, 0x36, 0x73, 0x61, 0xB2, + 0x9F, 0x4E, 0xB2, 0x61, 0x4E, 0x9F, 0x6D, 0xBF, + 0x93, 0x41, 0xBF, 0x6D, 0x41, 0x93, 0xCA, 0xDF, + 0x36, 0x21, 0xDF, 0xCA, 0x21, 0x36, 0xB3, 0xDF, + 0x4D, 0x21, 0xDF, 0xB3, 0x21, 0x4D, 0xE1, 0xE1, + 0x1F, 0x1F, 0x9F, 0xE3, 0x61, 0x1D, 0xE3, 0x9F, + 0x1D, 0x61, 0x7A, 0xD3, 0x86, 0x2D, 0xD3, 0x7A, + 0x2D, 0x86, 0x4C, 0xBE, 0xB4, 0x42, 0xBE, 0x4C, + 0x42, 0xB4, 0x57, 0xCA, 0xA9, 0x36, 0xCA, 0x57, + 0x36, 0xA9, 0x88, 0xE9, 0x78, 0x17, 0xE9, 0x88, + 0x17, 0x78, 0xCC, 0xFB, 0x34, 0x05, 0xFB, 0xCC, + 0x05, 0x34, 0xE6, 0xFB, 0x1A, 0x05, 0xFB, 0xE6, + 0x05, 0x1A, 0xB4, 0xFD, 0x4C, 0x03, 0xFD, 0xB4, + 0x03, 0x4C, 0x63, 0xDC, 0x9D, 0x24, 0xDC, 0x63, + 0x24, 0x9D, 0xFE, 0xFE, 0x02, 0x02, 0x80, 0x80, }, + { 0x80, 0x80, 0x87, 0x87, 0x79, 0x79, 0x7E, 0x89, + 0x82, 0x77, 0x89, 0x7E, 0x77, 0x82, 0x95, 0x95, + 0x6B, 0x6B, 0x86, 0x96, 0x7A, 0x6A, 0x96, 0x86, + 0x6A, 0x7A, 0x70, 0x90, 0x90, 0x70, 0x90, 0x70, + 0x70, 0x90, 0x94, 0xA4, 0x6C, 0x5C, 0xA4, 0x94, + 0x5C, 0x6C, 0x78, 0x9B, 0x88, 0x65, 0x9B, 0x78, + 0x65, 0x88, 0xA6, 0xA6, 0x5A, 0x5A, 0x83, 0xA9, + 0x7D, 0x57, 0xA9, 0x83, 0x57, 0x7D, 0xA6, 0xB9, + 0x5A, 0x47, 0xB9, 0xA6, 0x47, 0x5A, 0xBA, 0xBA, + 0x46, 0x46, 0x92, 0xBC, 0x6E, 0x44, 0xBC, 0x92, + 0x44, 0x6E, 0x67, 0xA3, 0x99, 0x5D, 0xA3, 0x67, + 0x5D, 0x99, 0x72, 0xB0, 0x8E, 0x50, 0xB0, 0x72, + 0x50, 0x8E, 0x7F, 0xC3, 0x81, 0x3D, 0xC3, 0x7F, + 0x3D, 0x81, 0xBE, 0xD2, 0x42, 0x2E, 0xD2, 0xBE, + 0x2E, 0x42, 0xA5, 0xD4, 0x5B, 0x2C, 0xD4, 0xA5, + 0x2C, 0x5B, 0xD4, 0xD4, 0x2C, 0x2C, 0x52, 0xAE, + 0xAE, 0x52, 0xAE, 0x52, 0x52, 0xAE, 0x8F, 0xD8, + 0x71, 0x28, 0xD8, 0x8F, 0x28, 0x71, 0x5B, 0xBB, + 0xA5, 0x45, 0xBB, 0x5B, 0x45, 0xA5, 0x69, 0xCB, + 0x97, 0x35, 0xCB, 0x69, 0x35, 0x97, 0xD8, 0xF0, + 0x28, 0x10, 0xF0, 0xD8, 0x10, 0x28, 0xBD, 0xF1, + 0x43, 0x0F, 0xF1, 0xBD, 0x0F, 0x43, 0xF3, 0xF3, + 0x0D, 0x0D, 0xA5, 0xF6, 0x5B, 0x0A, 0xF6, 0xA5, + 0x0A, 0x5B, 0x78, 0xE2, 0x88, 0x1E, 0xE2, 0x78, + 0x1E, 0x88, 0x42, 0xC9, 0xBE, 0x37, 0xC9, 0x42, + 0x37, 0xBE, 0x4F, 0xD8, 0xB1, 0x28, 0xD8, 0x4F, + 0x28, 0xB1, 0x8A, 0xFD, 0x76, 0x03, 0xFD, 0x8A, + 0x03, 0x76, 0xDB, 0xFF, 0x25, 0x01, 0xFF, 0xDB, + 0x01, 0x25, 0xF9, 0xFF, 0x07, 0x01, 0xFF, 0xF9, + 0x01, 0x07, 0xBE, 0xFF, 0x42, 0x01, 0xFF, 0xBE, + 0x01, 0x42, 0x5E, 0xED, 0xA2, 0x13, 0xED, 0x5E, + 0x13, 0xA2, 0xFF, 0xFF, 0x01, 0x01, 0x80, 0x80, }, }; #endif /* AVCODEC_INDEO2DATA_H */ diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index f74ac42..f222a06 100644 --- a/libavcodec/indeo3.c +++ b/libavcodec/indeo3.c @@ -52,7 +52,7 @@ enum { /* Some constants for parsing frame bitstream flags. */ -#define BS_8BIT_PEL (1 << 1) ///< 8bit pixel bitdepth indicator +#define BS_8BIT_PEL (1 << 1) ///< 8-bit pixel bitdepth indicator #define BS_KEYFRAME (1 << 2) ///< intra frame indicator #define BS_MV_Y_HALF (1 << 4) ///< vertical mv halfpel resolution indicator #define BS_MV_X_HALF (1 << 5) ///< horizontal mv halfpel resolution indicator @@ -307,7 +307,7 @@ static inline uint32_t replicate32(uint32_t a) { } -/* Fill n lines with 64bit pixel value pix */ +/* Fill n lines with 64-bit pixel value pix */ static inline void fill_64(uint8_t *dst, const uint64_t pix, int32_t n, int32_t row_offset) { @@ -928,7 +928,7 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, if (width != ctx->width || height != ctx->height) { int res; - av_dlog(avctx, "Frame dimensions changed!\n"); + ff_dlog(avctx, "Frame dimensions changed!\n"); if (width < 16 || width > 640 || height < 16 || height > 480 || @@ -1134,5 +1134,5 @@ AVCodec ff_indeo3_decoder = { .init = decode_init, .close = decode_close, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/indeo3data.h b/libavcodec/indeo3data.h index 28c9bb6..41a29e5 100644 --- a/libavcodec/indeo3data.h +++ b/libavcodec/indeo3data.h @@ -234,13 +234,13 @@ /** - * Pack two delta values (a,b) into one 16bit word + * Pack two delta values (a,b) into one 16-bit word * according with endianness of the host machine. */ #if HAVE_BIGENDIAN -#define PD(a,b) (((a) << 8) + (b)) +#define PD(a,b) (((a) * (1 << 8)) + (b)) #else -#define PD(a,b) (((b) << 8) + (a)) +#define PD(a,b) (((b) * (1 << 8)) + (a)) #endif /** @@ -281,13 +281,13 @@ static const int16_t delta_tab_3_5[79] = { TAB_3_5 }; #undef PD /** - * Pack four delta values (a,a,b,b) into one 32bit word + * Pack four delta values (a,a,b,b) into one 32-bit word * according with endianness of the host machine. */ #if HAVE_BIGENDIAN -#define PD(a,b) (((a) << 24) + ((a) << 16) + ((b) << 8) + (b)) +#define PD(a,b) (((a) * (1 << 24)) + ((a) * (1 << 16)) + ((b) * (1 << 8)) + (b)) #else -#define PD(a,b) (((b) << 24) + ((b) << 16) + ((a) << 8) + (a)) +#define PD(a,b) (((b) * (1 << 24)) + ((b) * (1 << 16)) + ((a) * (1 << 8)) + (a)) #endif /* diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c index 35f266e..ab42e7b 100644 --- a/libavcodec/indeo4.c +++ b/libavcodec/indeo4.c @@ -30,9 +30,10 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" -#include "ivi_dsp.h" -#include "ivi_common.h" #include "indeo4data.h" +#include "internal.h" +#include "ivi.h" +#include "ivi_dsp.h" #define IVI4_PIC_SIZE_ESC 7 @@ -118,17 +119,10 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) return AVERROR_INVALIDDATA; } -#if IVI4_STREAM_ANALYSER if (ctx->frame_type == IVI4_FRAMETYPE_BIDIR) ctx->has_b_frames = 1; -#endif - ctx->transp_status = get_bits1(&ctx->gb); -#if IVI4_STREAM_ANALYSER - if (ctx->transp_status) { - ctx->has_transp = 1; - } -#endif + ctx->has_transp = get_bits1(&ctx->gb); /* unknown bit: Mac decoder ignores this bit, XANIM returns error */ if (get_bits1(&ctx->gb)) { @@ -140,7 +134,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) /* null frames don't contain anything else so we just return */ if (ctx->frame_type >= IVI4_FRAMETYPE_NULL_FIRST) { - av_dlog(avctx, "Null frame encountered!\n"); + ff_dlog(avctx, "Null frame encountered!\n"); return 0; } @@ -149,7 +143,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) /* we don't do that because Indeo 4 videos can be decoded anyway */ if (get_bits1(&ctx->gb)) { skip_bits_long(&ctx->gb, 32); - av_dlog(avctx, "Password-protected clip!\n"); + ff_dlog(avctx, "Password-protected clip!\n"); } pic_size_indx = get_bits(&ctx->gb, 3); @@ -162,12 +156,10 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) } /* Decode tile dimensions. */ - if (get_bits1(&ctx->gb)) { + ctx->uses_tiling = get_bits1(&ctx->gb); + if (ctx->uses_tiling) { pic_conf.tile_height = scale_tile_size(pic_conf.pic_height, get_bits(&ctx->gb, 4)); pic_conf.tile_width = scale_tile_size(pic_conf.pic_width, get_bits(&ctx->gb, 4)); -#if IVI4_STREAM_ANALYSER - ctx->uses_tiling = 1; -#endif } else { pic_conf.tile_height = pic_conf.pic_height; pic_conf.tile_width = pic_conf.pic_width; @@ -243,7 +235,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) /* skip picture header extension if any */ while (get_bits1(&ctx->gb)) { - av_dlog(avctx, "Pic hdr extension encountered!\n"); + ff_dlog(avctx, "Pic hdr extension encountered!\n"); skip_bits(&ctx->gb, 8); } @@ -292,10 +284,8 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, band->is_halfpel); return AVERROR_INVALIDDATA; } -#if IVI4_STREAM_ANALYSER if (!band->is_halfpel) ctx->uses_fullpel = 1; -#endif band->checksum_present = get_bits1(&ctx->gb); if (band->checksum_present) @@ -327,10 +317,8 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, return AVERROR_PATCHWELCOME; } -#if IVI4_STREAM_ANALYSER if ((transform_id >= 0 && transform_id <= 2) || transform_id == 10) ctx->uses_haar = 1; -#endif band->inv_transform = transforms[transform_id].inv_trans; band->dc_transform = transforms[transform_id].dc_trans; @@ -639,6 +627,7 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->is_nonnull_frame = is_nonnull_frame; ctx->is_indeo4 = 1; + ctx->show_indeo4_info = 1; ctx->dst_buf = 0; ctx->ref_buf = 1; @@ -660,5 +649,5 @@ AVCodec ff_indeo4_decoder = { .init = decode_init, .close = ff_ivi_decode_close, .decode = ff_ivi_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/indeo4data.h b/libavcodec/indeo4data.h index 8311c68..be7c413 100644 --- a/libavcodec/indeo4data.h +++ b/libavcodec/indeo4data.h @@ -29,8 +29,7 @@ #include -#include "ivi_common.h" -#include "mathops.h" +#include "ivi.h" /** * standard picture dimensions diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index 5a112f9..bed9153 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -30,8 +30,8 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" +#include "ivi.h" #include "ivi_dsp.h" -#include "ivi_common.h" #include "indeo5data.h" /** @@ -657,5 +657,5 @@ AVCodec ff_indeo5_decoder = { .init = decode_init, .close = ff_ivi_decode_close, .decode = ff_ivi_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index e34da5c..cd1971f 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -18,8 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" +#include "mpegvideodata.h" /* don't understand why they choose a different header ! */ int ff_intel_h263_decode_picture_header(MpegEncContext *s) @@ -42,8 +44,8 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) return -1; /* marker */ } if (get_bits1(&s->gb) != 0) { - av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n"); - return -1; /* h263 id */ + av_log(s->avctx, AV_LOG_ERROR, "Bad H.263 id\n"); + return -1; /* H.263 id */ } skip_bits1(&s->gb); /* split screen off */ skip_bits1(&s->gb); /* camera off */ @@ -51,7 +53,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) format = get_bits(&s->gb, 3); if (format == 0 || format == 6) { - av_log(s->avctx, AV_LOG_ERROR, "Intel H263 free format not supported\n"); + av_log(s->avctx, AV_LOG_ERROR, "Intel H.263 free format not supported\n"); return -1; } s->h263_plus = 0; @@ -76,7 +78,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) } else { format = get_bits(&s->gb, 3); if(format == 0 || format == 7){ - av_log(s->avctx, AV_LOG_ERROR, "Wrong Intel H263 format\n"); + av_log(s->avctx, AV_LOG_ERROR, "Wrong Intel H.263 format\n"); return -1; } if(get_bits(&s->gb, 2)) @@ -137,7 +139,7 @@ AVCodec ff_h263i_decoder = { .init = ff_h263_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE diff --git a/libavcodec/internal.h b/libavcodec/internal.h index a68d613..4bde09a 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -33,6 +33,44 @@ #include "avcodec.h" #include "config.h" +/** + * The codec does not modify any global variables in the init function, + * allowing to call the init function without locking any global mutexes. + */ +#define FF_CODEC_CAP_INIT_THREADSAFE (1 << 0) +/** + * The codec allows calling the close function for deallocation even if + * the init function returned a failure. Without this capability flag, a + * codec does such cleanup internally when returning failures from the + * init function and does not expect the close function to be called at + * all. + */ +#define FF_CODEC_CAP_INIT_CLEANUP (1 << 1) +/** + * Decoders marked with FF_CODEC_CAP_SETS_PKT_DTS want to set + * AVFrame.pkt_dts manually. If the flag is set, utils.c won't overwrite + * this field. If it's unset, utils.c tries to guess the pkt_dts field + * from the input AVPacket. + */ +#define FF_CODEC_CAP_SETS_PKT_DTS (1 << 2) + +#ifdef DEBUG +# define ff_dlog(ctx, ...) av_log(ctx, AV_LOG_DEBUG, __VA_ARGS__) +#else +# define ff_dlog(ctx, ...) do { } while (0) +#endif + +#ifdef TRACE +# define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) +#else +# define ff_tlog(ctx, ...) do { } while (0) +#endif + + +#if !FF_API_QUANT_BIAS +#define FF_DEFAULT_QUANT_BIAS 999999 +#endif + #define FF_SANE_NB_CHANNELS 63U #define FF_SIGNBIT(x) (x >> CHAR_BIT * sizeof(x) - 1) @@ -102,6 +140,19 @@ typedef struct AVCodecInternal { * hwaccel-specific private data */ void *hwaccel_priv_data; + + /** + * checks API usage: after codec draining, flush is required to resume operation + */ + int draining; + + /** + * buffers for using new encode/decode API through legacy API + */ + AVPacket *buffer_pkt; + int buffer_pkt_valid; // encoding: packet without data can be valid + AVFrame *buffer_frame; + int draining_done; } AVCodecInternal; struct AVCodecDefault { @@ -125,7 +176,7 @@ int avpriv_unlock_avformat(void); * This value was chosen such that every bit of the buffer is * addressable by a 32-bit signed integer as used by get_bits. */ -#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE) +#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - AV_INPUT_BUFFER_PADDING_SIZE) /** * Check AVPacket size and/or allocate data. @@ -202,4 +253,9 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); */ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); +/** + * Add a CPB properties side data to an encoding context. + */ +AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index af7aa13..e0d1e91 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -1,6 +1,6 @@ /* * Interplay MVE Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -38,11 +38,11 @@ #include #include +#define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" -#include "hpeldsp.h" -#define BITSTREAM_READER_LE #include "get_bits.h" +#include "hpeldsp.h" #include "internal.h" #define PALETTE_COUNT 256 @@ -118,7 +118,7 @@ static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s, AVFrame *frame) y = 8 + ((B - 56) / 29); } - av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, s->second_last_frame, frame, x, y); } @@ -144,7 +144,7 @@ static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame) y = -( 8 + ((B - 56) / 29)); } - av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, frame, frame, x, y); } @@ -165,7 +165,7 @@ static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame) x = -8 + BL; y = -8 + BH; - av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + ff_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); return copy_from(s, s->last_frame, frame, x, y); } @@ -178,7 +178,7 @@ static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame) x = bytestream2_get_byte(&s->stream_ptr); y = bytestream2_get_byte(&s->stream_ptr); - av_dlog(NULL, " motion bytes = %d, %d\n", x, y); + ff_dlog(NULL, " motion bytes = %d, %d\n", x, y); return copy_from(s, s->last_frame, frame, x, y); } @@ -528,7 +528,7 @@ static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s, AVFrame *frame) x = bytestream2_get_byte(&s->stream_ptr); y = bytestream2_get_byte(&s->stream_ptr); - av_dlog(NULL, " motion bytes = %d, %d\n", x, y); + ff_dlog(NULL, " motion bytes = %d, %d\n", x, y); return copy_from(s, s->second_last_frame, frame, x, y); } @@ -903,7 +903,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) for (x = 0; x < s->avctx->width; x += 8) { opcode = get_bits(&gb, 4); - av_dlog(s->avctx, + ff_dlog(s->avctx, " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n", x, y, opcode, bytestream2_tell(&s->stream_ptr)); @@ -1020,5 +1020,5 @@ AVCodec ff_interplay_video_decoder = { .init = ipvideo_decode_init, .close = ipvideo_decode_end, .decode = ipvideo_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, }; diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c index 303b926..eb4c1ef 100644 --- a/libavcodec/intrax8.c +++ b/libavcodec/intrax8.c @@ -22,16 +22,16 @@ */ #include "avcodec.h" -#include "error_resilience.h" #include "get_bits.h" #include "idctdsp.h" -#include "mpegvideo.h" #include "msmpeg4data.h" #include "intrax8huf.h" #include "intrax8.h" #include "intrax8dsp.h" +#include "mpegutils.h" -#define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits) +#define MAX_TABLE_DEPTH(table_bits, max_bits) \ + ((max_bits + table_bits - 1) / table_bits) #define DC_VLC_BITS 9 #define AC_VLC_BITS 9 @@ -41,15 +41,16 @@ #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS) #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS) -static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select] -static VLC j_dc_vlc[2][8]; //[quant], [select] -static VLC j_orient_vlc[2][4]; //[quant], [select] +static VLC j_ac_vlc[2][2][8]; // [quant < 13], [intra / inter], [select] +static VLC j_dc_vlc[2][8]; // [quant], [select] +static VLC j_orient_vlc[2][4]; // [quant], [select] -static av_cold void x8_vlc_init(void){ +static av_cold int x8_vlc_init(void) +{ int i; int offset = 0; int sizeidx = 0; - static const uint16_t sizes[8*4 + 8*2 + 2 + 4] = { + static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = { 576, 548, 582, 618, 546, 616, 560, 642, 584, 582, 704, 664, 512, 544, 656, 640, 512, 648, 582, 566, 532, 614, 596, 648, @@ -58,735 +59,784 @@ static av_cold void x8_vlc_init(void){ 528, 528, 526, 528, 536, 528, 526, 544, 544, 512, 512, 528, 528, 544, 512, 544, - 128, 128, 128, 128, 128, 128}; + 128, 128, 128, 128, 128, 128, + }; static VLC_TYPE table[28150][2]; -#define init_ac_vlc(dst,src) \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, \ - AC_VLC_BITS,77, \ - &src[1],4,2, \ - &src[0],4,2, \ - INIT_VLC_USE_NEW_STATIC) -//set ac tables - for(i=0;i<8;i++){ - init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] ); - init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] ); - init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] ); - init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] ); +// set ac tables +#define init_ac_vlc(dst, src) \ + do { \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2, \ + INIT_VLC_USE_NEW_STATIC); \ + } while(0) + + for (i = 0; i < 8; i++) { + init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]); + init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]); + init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]); + init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]); } #undef init_ac_vlc -//set dc tables -#define init_dc_vlc(dst,src) \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, \ - DC_VLC_BITS,34, \ - &src[1],4,2, \ - &src[0],4,2, \ - INIT_VLC_USE_NEW_STATIC); - for(i=0;i<8;i++){ - init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); - init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]); +// set dc tables +#define init_dc_vlc(dst, src) \ + do { \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2, \ + INIT_VLC_USE_NEW_STATIC); \ + } while(0) + + for (i = 0; i < 8; i++) { + init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); + init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]); } #undef init_dc_vlc -//set orient tables -#define init_or_vlc(dst,src) \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, \ - OR_VLC_BITS,12, \ - &src[1],4,2, \ - &src[0],4,2, \ - INIT_VLC_USE_NEW_STATIC); - for(i=0;i<2;i++){ - init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); - } - for(i=0;i<4;i++){ - init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0]) +// set orient tables +#define init_or_vlc(dst, src) \ + do { \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2, \ + INIT_VLC_USE_NEW_STATIC); \ + } while(0) + + for (i = 0; i < 2; i++) + init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); + for (i = 0; i < 4; i++) + init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]); +#undef init_or_vlc + + if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) { + av_log(NULL, AV_LOG_ERROR, "table size %zd does not match needed %i\n", + sizeof(table) / sizeof(VLC_TYPE) / 2, offset); + return AVERROR_INVALIDDATA; } - if (offset != sizeof(table)/sizeof(VLC_TYPE)/2) - av_log(NULL, AV_LOG_ERROR, "table size %i does not match needed %i\n", (int)(sizeof(table)/sizeof(VLC_TYPE)/2), offset); + + return 0; } -#undef init_or_vlc -static void x8_reset_vlc_tables(IntraX8Context * w){ - memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc)); - memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc)); - w->j_orient_vlc=NULL; +static void x8_reset_vlc_tables(IntraX8Context *w) +{ + memset(w->j_dc_vlc, 0, sizeof(w->j_dc_vlc)); + memset(w->j_ac_vlc, 0, sizeof(w->j_ac_vlc)); + w->j_orient_vlc = NULL; } -static inline void x8_select_ac_table(IntraX8Context * const w , int mode){ - MpegEncContext * const s= w->s; +static inline void x8_select_ac_table(IntraX8Context *const w, int mode) +{ int table_index; - assert(mode<4); + assert(mode < 4); + + if (w->j_ac_vlc[mode]) + return; - if( w->j_ac_vlc[mode] ) return; + table_index = get_bits(w->gb, 3); + // 2 modes use same tables + w->j_ac_vlc[mode] = &j_ac_vlc[w->quant < 13][mode >> 1][table_index]; - table_index = get_bits(&s->gb, 3); - w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables assert(w->j_ac_vlc[mode]); } -static inline int x8_get_orient_vlc(IntraX8Context * w){ - MpegEncContext * const s= w->s; - int table_index; - - if(!w->j_orient_vlc ){ - table_index = get_bits(&s->gb, 1+(w->quant<13) ); - w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index]; +static inline int x8_get_orient_vlc(IntraX8Context *w) +{ + if (!w->j_orient_vlc) { + int table_index = get_bits(w->gb, 1 + (w->quant < 13)); + w->j_orient_vlc = &j_orient_vlc[w->quant < 13][table_index]; } assert(w->j_orient_vlc); assert(w->j_orient_vlc->table); - return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); + return get_vlc2(w->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); } -#define extra_bits(eb) (eb) -#define extra_run (0xFF<<8) -#define extra_level (0x00<<8) -#define run_offset(r) ((r)<<16) -#define level_offset(l) ((l)<<24) -static const uint32_t ac_decode_table[]={ - /*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0), - /*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0), - /*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), - /*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), - - /*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0), - /*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), - - /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), - /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8), - /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12), - /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16), - /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24), - - /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), - /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), - - /*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0), - /*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0), - /*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0), - /*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0), - /*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0), - /*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0), - - /*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), - /*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), - /*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), - - /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), - /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8), - /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16), - - /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), - /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), +#define extra_bits(eb) (eb) // 3 bits +#define extra_run (0xFF << 8) // 1 bit +#define extra_level (0x00 << 8) // 1 bit +#define run_offset(r) ((r) << 16) // 6 bits +#define level_offset(l) ((l) << 24) // 5 bits +static const uint32_t ac_decode_table[] = { + /* 46 */ extra_bits(3) | extra_run | run_offset(16) | level_offset(0), + /* 47 */ extra_bits(3) | extra_run | run_offset(24) | level_offset(0), + /* 48 */ extra_bits(2) | extra_run | run_offset(4) | level_offset(1), + /* 49 */ extra_bits(3) | extra_run | run_offset(8) | level_offset(1), + + /* 50 */ extra_bits(5) | extra_run | run_offset(32) | level_offset(0), + /* 51 */ extra_bits(4) | extra_run | run_offset(16) | level_offset(1), + + /* 52 */ extra_bits(2) | extra_level | run_offset(0) | level_offset(4), + /* 53 */ extra_bits(2) | extra_level | run_offset(0) | level_offset(8), + /* 54 */ extra_bits(2) | extra_level | run_offset(0) | level_offset(12), + /* 55 */ extra_bits(3) | extra_level | run_offset(0) | level_offset(16), + /* 56 */ extra_bits(3) | extra_level | run_offset(0) | level_offset(24), + + /* 57 */ extra_bits(2) | extra_level | run_offset(1) | level_offset(3), + /* 58 */ extra_bits(3) | extra_level | run_offset(1) | level_offset(7), + + /* 59 */ extra_bits(2) | extra_run | run_offset(16) | level_offset(0), + /* 60 */ extra_bits(2) | extra_run | run_offset(20) | level_offset(0), + /* 61 */ extra_bits(2) | extra_run | run_offset(24) | level_offset(0), + /* 62 */ extra_bits(2) | extra_run | run_offset(28) | level_offset(0), + /* 63 */ extra_bits(4) | extra_run | run_offset(32) | level_offset(0), + /* 64 */ extra_bits(4) | extra_run | run_offset(48) | level_offset(0), + + /* 65 */ extra_bits(2) | extra_run | run_offset(4) | level_offset(1), + /* 66 */ extra_bits(3) | extra_run | run_offset(8) | level_offset(1), + /* 67 */ extra_bits(4) | extra_run | run_offset(16) | level_offset(1), + + /* 68 */ extra_bits(2) | extra_level | run_offset(0) | level_offset(4), + /* 69 */ extra_bits(3) | extra_level | run_offset(0) | level_offset(8), + /* 70 */ extra_bits(4) | extra_level | run_offset(0) | level_offset(16), + + /* 71 */ extra_bits(2) | extra_level | run_offset(1) | level_offset(3), + /* 72 */ extra_bits(3) | extra_level | run_offset(1) | level_offset(7), }; -//extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits; #undef extra_bits #undef extra_run #undef extra_level #undef run_offset #undef level_offset -static void x8_get_ac_rlf(IntraX8Context * const w, const int mode, - int * const run, int * const level, int * const final){ - MpegEncContext * const s= w->s; - int i,e; +static void x8_get_ac_rlf(IntraX8Context *const w, const int mode, + int *const run, int *const level, int *const final) +{ + int i, e; -// x8_select_ac_table(w,mode); - i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); +// x8_select_ac_table(w, mode); + i = get_vlc2(w->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); - if(i<46){ //[0-45] - int t,l; - if(i<0){ - (*level)=(*final)=//prevent 'may be used unilitialized' - (*run)=64;//this would cause error exit in the ac loop + if (i < 46) { // [0-45] + int t, l; + if (i < 0) { + *level = + *final = // prevent 'may be used uninitialized' + *run = 64; // this would cause error exit in the ac loop return; } - (*final) = t = (i>22); - i-=23*t; -/* - i== 0-15 r=0-15 l=0 ;r=i& %01111 - i==16-19 r=0-3 l=1 ;r=i& %00011 - i==20-21 r=0-1 l=2 ;r=i& %00001 - i==22 r=0 l=3 ;r=i& %00000 -l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 -t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */ - l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/ - t=(0x01030F>>(l<<3)); - - (*run) = i&t; - (*level) = l; - }else if(i<73){//[46-72] + /* + * i == 0-15 r = 0-15 l = 0; r = i & %01111 + * i == 16-19 r = 0-3 l = 1; r = i & %00011 + * i == 20-21 r = 0-1 l = 2; r = i & %00001 + * i == 22 r = 0 l = 3; r = i & %00000 + */ + + *final = + t = i > 22; + i -= 23 * t; + + /* l = lut_l[i / 2] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 }[i >> 1]; + * 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 */ + l = (0xE50000 >> (i & 0x1E)) & 3; // 0x1E or ~1 or (i >> 1 << 1) + + /* t = lut_mask[l] = { 0x0f, 0x03, 0x01, 0x00 }[l]; + * as i < 256 the higher bits do not matter */ + t = 0x01030F >> (l << 3); + + *run = i & t; + *level = l; + } else if (i < 73) { // [46-72] uint32_t sm; uint32_t mask; - i-=46; - sm=ac_decode_table[i]; - - e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits - mask=sm&0xff;sm>>=8; //1bit - - (*run) =(sm&0xff) + (e&( mask));//6bits - (*level)=(sm>>8) + (e&(~mask));//5bits - (*final)=i>(58-46); - }else if(i<75){//[73-74] - static const uint8_t crazy_mix_runlevel[32]={ - 0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63, - 0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83, - 0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64, - 0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84}; - - (*final)=!(i&1); - e=get_bits(&s->gb,5);//get the extra bits - (*run) =crazy_mix_runlevel[e]>>4; - (*level)=crazy_mix_runlevel[e]&0x0F; - }else{ - (*level)=get_bits( &s->gb, 7-3*(i&1)); - (*run) =get_bits( &s->gb, 6); - (*final)=get_bits1(&s->gb); + i -= 46; + sm = ac_decode_table[i]; + + e = get_bits(w->gb, sm & 0xF); + sm >>= 8; // 3 bits + mask = sm & 0xff; + sm >>= 8; // 1 bit + + *run = (sm & 0xff) + (e & mask); // 6 bits + *level = (sm >> 8) + (e & ~mask); // 5 bits + *final = i > (58 - 46); + } else if (i < 75) { // [73-74] + static const uint8_t crazy_mix_runlevel[32] = { + 0x22, 0x32, 0x33, 0x53, 0x23, 0x42, 0x43, 0x63, + 0x24, 0x52, 0x34, 0x73, 0x25, 0x62, 0x44, 0x83, + 0x26, 0x72, 0x35, 0x54, 0x27, 0x82, 0x45, 0x64, + 0x28, 0x92, 0x36, 0x74, 0x29, 0xa2, 0x46, 0x84, + }; + + *final = !(i & 1); + e = get_bits(w->gb, 5); // get the extra bits + *run = crazy_mix_runlevel[e] >> 4; + *level = crazy_mix_runlevel[e] & 0x0F; + } else { + *level = get_bits(w->gb, 7 - 3 * (i & 1)); + *run = get_bits(w->gb, 6); + *final = get_bits1(w->gb); } return; } -//static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 }; -static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193}; +/* static const uint8_t dc_extra_sbits[] = { + * 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + * }; */ +static const uint8_t dc_index_offset[] = { + 0, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, +}; -static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){ - MpegEncContext * const s= w->s; - int i,e,c; +static int x8_get_dc_rlf(IntraX8Context *const w, const int mode, + int *const level, int *const final) +{ + int i, e, c; - assert(mode<3); - if( !w->j_dc_vlc[mode] ) { - int table_index; - table_index = get_bits(&s->gb, 3); - //4 modes, same table - w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index]; + assert(mode < 3); + if (!w->j_dc_vlc[mode]) { + int table_index = get_bits(w->gb, 3); + // 4 modes, same table + w->j_dc_vlc[mode] = &j_dc_vlc[w->quant < 13][table_index]; } assert(w->j_dc_vlc); assert(w->j_dc_vlc[mode]->table); - i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); + i = get_vlc2(w->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); - /*(i>=17) {i-=17;final=1;}*/ - c= i>16; - (*final)=c; - i-=17*c; + /* (i >= 17) { i -= 17; final =1; } */ + c = i > 16; + *final = c; + i -= 17 * c; - if(i<=0){ - (*level)=0; + if (i <= 0) { + *level = 0; return -i; } - c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[] - c-=c>1; + c = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[] + c -= c > 1; - e=get_bits(&s->gb,c);//get the extra bits - i=dc_index_offset[i]+(e>>1); + e = get_bits(w->gb, c); // get the extra bits + i = dc_index_offset[i] + (e >> 1); - e= -(e & 1);//0,0xffffff - (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1) + e = -(e & 1); // 0, 0xffffff + *level = (i ^ e) - e; // (i ^ 0) - 0, (i ^ 0xff) - (-1) return 0; } -//end of huffman -static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){ - MpegEncContext * const s= w->s; +// end of huffman + +static int x8_setup_spatial_predictor(IntraX8Context *const w, const int chroma) +{ int range; int sum; int quant; - w->dsp.setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, - s->current_picture.f->linesize[chroma>0], + w->dsp.setup_spatial_compensation(w->dest[chroma], w->scratchpad, + w->frame->linesize[chroma > 0], &range, &sum, w->edges); - if(chroma){ - w->orient=w->chroma_orient; - quant=w->quant_dc_chroma; - }else{ - quant=w->quant; + if (chroma) { + w->orient = w->chroma_orient; + quant = w->quant_dc_chroma; + } else { + quant = w->quant; } - w->flat_dc=0; - if(range < quant || range < 3){ - w->orient=0; - if(range < 3){//yep you read right, a +-1 idct error may break decoding! - w->flat_dc=1; - sum+=9; - w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899 + w->flat_dc = 0; + if (range < quant || range < 3) { + w->orient = 0; + + // yep you read right, a +-1 idct error may break decoding! + if (range < 3) { + w->flat_dc = 1; + sum += 9; + // ((1 << 17) + 9) / (8 + 8 + 1 + 2) = 6899 + w->predicted_dc = sum * 6899 >> 17; } } - if(chroma) + if (chroma) return 0; assert(w->orient < 3); - if(range < 2*w->quant){ - if( (w->edges&3) == 0){ - if(w->orient==1) w->orient=11; - if(w->orient==2) w->orient=10; - }else{ - w->orient=0; + if (range < 2 * w->quant) { + if ((w->edges & 3) == 0) { + if (w->orient == 1) + w->orient = 11; + if (w->orient == 2) + w->orient = 10; + } else { + w->orient = 0; } - w->raw_orient=0; - }else{ - static const uint8_t prediction_table[3][12]={ - {0,8,4, 10,11, 2,6,9,1,3,5,7}, - {4,0,8, 11,10, 3,5,2,6,9,1,7}, - {8,0,4, 10,11, 1,7,2,6,9,3,5} + w->raw_orient = 0; + } else { + static const uint8_t prediction_table[3][12] = { + { 0, 8, 4, 10, 11, 2, 6, 9, 1, 3, 5, 7 }, + { 4, 0, 8, 11, 10, 3, 5, 2, 6, 9, 1, 7 }, + { 8, 0, 4, 10, 11, 1, 7, 2, 6, 9, 3, 5 }, }; - w->raw_orient=x8_get_orient_vlc(w); - if(w->raw_orient<0) return -1; - assert(w->raw_orient < 12 ); - assert(w->orient<3); - w->orient=prediction_table[w->orient][w->raw_orient]; + w->raw_orient = x8_get_orient_vlc(w); + if (w->raw_orient < 0) + return -1; + assert(w->raw_orient < 12); + assert(w->orient < 3); + w->orient = prediction_table[w->orient][w->raw_orient]; } return 0; } -static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){ - MpegEncContext * const s= w->s; - - w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8); +static void x8_update_predictions(IntraX8Context *const w, const int orient, + const int est_run) +{ + w->prediction_table[w->mb_x * 2 + (w->mb_y & 1)] = (est_run << 2) + 1 * (orient == 4) + 2 * (orient == 8); /* - y=2n+0 ->//0 2 4 - y=2n+1 ->//1 3 5 -*/ + * y = 2n + 0 -> // 0 2 4 + * y = 2n + 1 -> // 1 3 5 + */ } -static void x8_get_prediction_chroma(IntraX8Context * const w){ - MpegEncContext * const s= w->s; - - w->edges = 1*( !(s->mb_x>>1) ); - w->edges|= 2*( !(s->mb_y>>1) ); - w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd - w->raw_orient=0; - if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC - w->chroma_orient=4<<((0xCC>>w->edges)&1); +static void x8_get_prediction_chroma(IntraX8Context *const w) +{ + w->edges = 1 * !(w->mb_x >> 1); + w->edges |= 2 * !(w->mb_y >> 1); + w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); // mb_x for chroma would always be odd + + w->raw_orient = 0; + // lut_co[8] = {inv,4,8,8, inv,4,8,8} <- => {1,1,0,0;1,1,0,0} => 0xCC + if (w->edges & 3) { + w->chroma_orient = 4 << ((0xCC >> w->edges) & 1); return; } - w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)] + // block[x - 1][y | 1 - 1)] + w->chroma_orient = (w->prediction_table[2 * w->mb_x - 2] & 0x03) << 2; } -static void x8_get_prediction(IntraX8Context * const w){ - MpegEncContext * const s= w->s; - int a,b,c,i; - - w->edges = 1*( !s->mb_x ); - w->edges|= 2*( !s->mb_y ); - w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) ); - - switch(w->edges&3){ - case 0: - break; - case 1: - //take the one from the above block[0][y-1] - w->est_run = w->prediction_table[!(s->mb_y&1)]>>2; - w->orient = 1; - return; - case 2: - //take the one from the previous block[x-1][0] - w->est_run = w->prediction_table[2*s->mb_x-2]>>2; - w->orient = 2; - return; - case 3: - w->est_run = 16; - w->orient = 0; - return; +static void x8_get_prediction(IntraX8Context *const w) +{ + int a, b, c, i; + + w->edges = 1 * !w->mb_x; + w->edges |= 2 * !w->mb_y; + w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); + + switch (w->edges & 3) { + case 0: + break; + case 1: + // take the one from the above block[0][y - 1] + w->est_run = w->prediction_table[!(w->mb_y & 1)] >> 2; + w->orient = 1; + return; + case 2: + // take the one from the previous block[x - 1][0] + w->est_run = w->prediction_table[2 * w->mb_x - 2] >> 2; + w->orient = 2; + return; + case 3: + w->est_run = 16; + w->orient = 0; + return; } - //no edge cases - b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1] - a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ] - c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1] + // no edge cases + b = w->prediction_table[2 * w->mb_x + !(w->mb_y & 1)]; // block[x ][y - 1] + a = w->prediction_table[2 * w->mb_x - 2 + (w->mb_y & 1)]; // block[x - 1][y ] + c = w->prediction_table[2 * w->mb_x - 2 + !(w->mb_y & 1)]; // block[x - 1][y - 1] - w->est_run = FFMIN(b,a); + w->est_run = FFMIN(b, a); /* This condition has nothing to do with w->edges, even if it looks - similar it would trigger if e.g. x=3;y=2; - I guess somebody wrote something wrong and it became standard. */ - if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); - w->est_run>>=2; - - a&=3; - b&=3; - c&=3; - - i=( 0xFFEAF4C4>>(2*b+8*a) )&3; - if(i!=3) w->orient=i; - else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3; + * similar it would trigger if e.g. x = 3; y = 2; + * I guess somebody wrote something wrong and it became standard. */ + if ((w->mb_x & w->mb_y) != 0) + w->est_run = FFMIN(c, w->est_run); + w->est_run >>= 2; + + a &= 3; + b &= 3; + c &= 3; + + i = (0xFFEAF4C4 >> (2 * b + 8 * a)) & 3; + if (i != 3) + w->orient = i; + else + w->orient = (0xFFEAD8 >> (2 * c + 8 * (w->quant > 12))) & 3; /* -lut1[b][a]={ -->{0, 1, 0, pad}, - {0, 1, X, pad}, - {2, 2, 2, pad}} - pad 2 2 2; pad X 1 0; pad 0 1 0 <- --> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4 - -lut2[q>12][c]={ - ->{0,2,1,pad}, - {2,2,2,pad}} - pad 2 2 2; pad 1 2 0 <- --> 11 10'10 10 '11 01'10 00=>0xEAD8 -*/ + * lut1[b][a] = { + * ->{ 0, 1, 0, pad }, + * { 0, 1, X, pad }, + * { 2, 2, 2, pad } + * } + * pad 2 2 2; + * pad X 1 0; + * pad 0 1 0 <- + * -> 11 10 '10 10 '11 11'01 00 '11 00'01 00 => 0xEAF4C4 + * + * lut2[q>12][c] = { + * ->{ 0, 2, 1, pad}, + * { 2, 2, 2, pad} + * } + * pad 2 2 2; + * pad 1 2 0 <- + * -> 11 10'10 10 '11 01'10 00 => 0xEAD8 + */ } - -static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ - MpegEncContext * const s= w->s; +static void x8_ac_compensation(IntraX8Context *const w, const int direction, + const int dc_level) +{ int t; -#define B(x, y) s->block[0][s->idsp.idct_permutation[(x) + (y) * 8]] +#define B(x, y) w->block[0][w->idsp.idct_permutation[(x) + (y) * 8]] #define T(x) ((x) * dc_level + 0x8000) >> 16; - switch(direction){ + switch (direction) { case 0: - t = T(3811);//h - B(1,0) -= t; - B(0,1) -= t; - - t = T(487);//e - B(2,0) -= t; - B(0,2) -= t; - - t = T(506);//f - B(3,0) -= t; - B(0,3) -= t; - - t = T(135);//c - B(4,0) -= t; - B(0,4) -= t; - B(2,1) += t; - B(1,2) += t; - B(3,1) += t; - B(1,3) += t; - - t = T(173);//d - B(5,0) -= t; - B(0,5) -= t; - - t = T(61);//b - B(6,0) -= t; - B(0,6) -= t; - B(5,1) += t; - B(1,5) += t; - - t = T(42); //a - B(7,0) -= t; - B(0,7) -= t; - B(4,1) += t; - B(1,4) += t; - B(4,4) += t; - - t = T(1084);//g - B(1,1) += t; - - s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); + t = T(3811); // h + B(1, 0) -= t; + B(0, 1) -= t; + + t = T(487); // e + B(2, 0) -= t; + B(0, 2) -= t; + + t = T(506); // f + B(3, 0) -= t; + B(0, 3) -= t; + + t = T(135); // c + B(4, 0) -= t; + B(0, 4) -= t; + B(2, 1) += t; + B(1, 2) += t; + B(3, 1) += t; + B(1, 3) += t; + + t = T(173); // d + B(5, 0) -= t; + B(0, 5) -= t; + + t = T(61); // b + B(6, 0) -= t; + B(0, 6) -= t; + B(5, 1) += t; + B(1, 5) += t; + + t = T(42); // a + B(7, 0) -= t; + B(0, 7) -= t; + B(4, 1) += t; + B(1, 4) += t; + B(4, 4) += t; + + t = T(1084); // g + B(1, 1) += t; + + w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8); break; case 1: - B(0,1) -= T(6269); - B(0,3) -= T( 708); - B(0,5) -= T( 172); - B(0,7) -= T( 73); + B(0, 1) -= T(6269); + B(0, 3) -= T(708); + B(0, 5) -= T(172); + B(0, 7) -= T(73); - s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); + w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8); break; case 2: - B(1,0) -= T(6269); - B(3,0) -= T( 708); - B(5,0) -= T( 172); - B(7,0) -= T( 73); + B(1, 0) -= T(6269); + B(3, 0) -= T(708); + B(5, 0) -= T(172); + B(7, 0) -= T(73); - s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); + w->block_last_index[0] = FFMAX(w->block_last_index[0], 7); break; } #undef B #undef T } -static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ +static void dsp_x8_put_solidcolor(const uint8_t pix, uint8_t *dst, + const int linesize) +{ int k; - for(k=0;k<8;k++){ - memset(dst,pix,8); - dst+=linesize; + for (k = 0; k < 8; k++) { + memset(dst, pix, 8); + dst += linesize; } } static const int16_t quant_table[64] = { - 256, 256, 256, 256, 256, 256, 259, 262, - 265, 269, 272, 275, 278, 282, 285, 288, - 292, 295, 299, 303, 306, 310, 314, 317, - 321, 325, 329, 333, 337, 341, 345, 349, - 353, 358, 362, 366, 371, 375, 379, 384, - 389, 393, 398, 403, 408, 413, 417, 422, - 428, 433, 438, 443, 448, 454, 459, 465, - 470, 476, 482, 488, 493, 499, 505, 511 + 256, 256, 256, 256, 256, 256, 259, 262, + 265, 269, 272, 275, 278, 282, 285, 288, + 292, 295, 299, 303, 306, 310, 314, 317, + 321, 325, 329, 333, 337, 341, 345, 349, + 353, 358, 362, 366, 371, 375, 379, 384, + 389, 393, 398, 403, 408, 413, 417, 422, + 428, 433, 438, 443, 448, 454, 459, 465, + 470, 476, 482, 488, 493, 499, 505, 511, }; -static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ - MpegEncContext * const s= w->s; - - uint8_t * scantable; - int final,run,level; - int ac_mode,dc_mode,est_run,dc_level; - int pos,n; +static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma) +{ + uint8_t *scantable; + int final, run, level; + int ac_mode, dc_mode, est_run, dc_level; + int pos, n; int zeros_only; int use_quant_matrix; int sign; - assert(w->orient<12); - s->bdsp.clear_block(s->block[0]); - - if(chroma){ - dc_mode=2; - }else{ - dc_mode=!!w->est_run;//0,1 - } - - if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; - n=0; - zeros_only=0; - if(!final){//decode ac - use_quant_matrix=w->use_quant_matrix; - if(chroma){ + assert(w->orient < 12); + w->bdsp.clear_block(w->block[0]); + + if (chroma) + dc_mode = 2; + else + dc_mode = !!w->est_run; // 0, 1 + + if (x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) + return -1; + n = 0; + zeros_only = 0; + if (!final) { // decode ac + use_quant_matrix = w->use_quant_matrix; + if (chroma) { ac_mode = 1; - est_run = 64;//not used - }else{ - if (w->raw_orient < 3){ + est_run = 64; // not used + } else { + if (w->raw_orient < 3) use_quant_matrix = 0; - } - if(w->raw_orient > 4){ + + if (w->raw_orient > 4) { ac_mode = 0; est_run = 64; - }else{ - if(w->est_run > 1){ + } else { + if (w->est_run > 1) { ac_mode = 2; - est_run=w->est_run; - }else{ + est_run = w->est_run; + } else { ac_mode = 3; est_run = 64; } } } - x8_select_ac_table(w,ac_mode); - /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- - -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ - scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; - pos=0; + x8_select_ac_table(w, ac_mode); + /* scantable_selector[12] = { 0, 2, 0, 1, 1, 1, 0, 2, 2, 0, 1, 2 }; <- + * -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 => 0x928548 */ + scantable = w->scantable[(0x928548 >> (2 * w->orient)) & 3].permutated; + pos = 0; do { n++; - if( n >= est_run ){ - ac_mode=3; - x8_select_ac_table(w,3); + if (n >= est_run) { + ac_mode = 3; + x8_select_ac_table(w, 3); } - x8_get_ac_rlf(w,ac_mode,&run,&level,&final); + x8_get_ac_rlf(w, ac_mode, &run, &level, &final); - pos+=run+1; - if(pos>63){ - //this also handles vlc error in x8_get_ac_rlf + pos += run + 1; + if (pos > 63) { + // this also handles vlc error in x8_get_ac_rlf return -1; } - level= (level+1) * w->dquant; - level+= w->qsum; + level = (level + 1) * w->dquant; + level += w->qsum; - sign = - get_bits1(&s->gb); + sign = -get_bits1(w->gb); level = (level ^ sign) - sign; - if(use_quant_matrix){ - level = (level*quant_table[pos])>>8; - } - s->block[0][ scantable[pos] ]=level; - }while(!final); + if (use_quant_matrix) + level = (level * quant_table[pos]) >> 8; + + w->block[0][scantable[pos]] = level; + } while (!final); - s->block_last_index[0]=pos; - }else{//DC only - s->block_last_index[0]=0; - if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] - int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: - w->divide_quant_dc_chroma; - int32_t dc_quant = !chroma ? w->quant: - w->quant_dc_chroma; + w->block_last_index[0] = pos; + } else { // DC only + w->block_last_index[0] = 0; + if (w->flat_dc && ((unsigned) (dc_level + 1)) < 3) { // [-1; 1] + int32_t divide_quant = !chroma ? w->divide_quant_dc_luma + : w->divide_quant_dc_chroma; + int32_t dc_quant = !chroma ? w->quant + : w->quant_dc_chroma; - //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding - dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; + // original intent dc_level += predicted_dc/quant; + // but it got lost somewhere in the rounding + dc_level += (w->predicted_dc * divide_quant + (1 << 12)) >> 13; - dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), - s->dest[chroma], s->current_picture.f->linesize[!!chroma]); + dsp_x8_put_solidcolor(av_clip_uint8((dc_level * dc_quant + 4) >> 3), + w->dest[chroma], + w->frame->linesize[!!chroma]); goto block_placed; } - zeros_only = (dc_level == 0); - } - if(!chroma){ - s->block[0][0] = dc_level*w->quant; - }else{ - s->block[0][0] = dc_level*w->quant_dc_chroma; + zeros_only = dc_level == 0; } + if (!chroma) + w->block[0][0] = dc_level * w->quant; + else + w->block[0][0] = dc_level * w->quant_dc_chroma; - //there is !zero_only check in the original, but dc_level check is enough - if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ + // there is !zero_only check in the original, but dc_level check is enough + if ((unsigned int) (dc_level + 1) >= 3 && (w->edges & 3) != 3) { int direction; - /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- - -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ - direction= (0x6A017C>>(w->orient*2))&3; - if (direction != 3){ - x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] + /* ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 }; <- + * -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 => 0x6A017C */ + direction = (0x6A017C >> (w->orient * 2)) & 3; + if (direction != 3) { + // modify block_last[] + x8_ac_compensation(w, direction, w->block[0][0]); } } - if(w->flat_dc){ - dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.f->linesize[!!chroma]); - }else{ - w->dsp.spatial_compensation[w->orient]( s->edge_emu_buffer, - s->dest[chroma], - s->current_picture.f->linesize[!!chroma] ); + if (w->flat_dc) { + dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma], + w->frame->linesize[!!chroma]); + } else { + w->dsp.spatial_compensation[w->orient](w->scratchpad, + w->dest[chroma], + w->frame->linesize[!!chroma]); } - if(!zeros_only) - s->idsp.idct_add(s->dest[chroma], - s->current_picture.f->linesize[!!chroma], - s->block[0]); + if (!zeros_only) + w->idsp.idct_add(w->dest[chroma], + w->frame->linesize[!!chroma], + w->block[0]); block_placed: + if (!chroma) + x8_update_predictions(w, w->orient, n); - if(!chroma){ - x8_update_predictions(w,w->orient,n); - } - - if(s->loop_filter){ - uint8_t* ptr = s->dest[chroma]; - int linesize = s->current_picture.f->linesize[!!chroma]; + if (w->loopfilter) { + uint8_t *ptr = w->dest[chroma]; + int linesize = w->frame->linesize[!!chroma]; - if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ + if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4))) w->dsp.h_loop_filter(ptr, linesize, w->quant); - } - if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ + + if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8))) w->dsp.v_loop_filter(ptr, linesize, w->quant); - } } return 0; } -static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_* -//not s->linesize as this would be wrong for field pics -//not that IntraX8 has interlacing support ;) - const int linesize = s->current_picture.f->linesize[0]; - const int uvlinesize = s->current_picture.f->linesize[1]; - - s->dest[0] = s->current_picture.f->data[0]; - s->dest[1] = s->current_picture.f->data[1]; - s->dest[2] = s->current_picture.f->data[2]; - - s->dest[0] += s->mb_y * linesize << 3; - s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows - s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2; +// FIXME maybe merge with ff_* +static void x8_init_block_index(IntraX8Context *w, AVFrame *frame) +{ + // not parent codec linesize as this would be wrong for field pics + // not that IntraX8 has interlacing support ;) + const int linesize = frame->linesize[0]; + const int uvlinesize = frame->linesize[1]; + + w->dest[0] = frame->data[0]; + w->dest[1] = frame->data[1]; + w->dest[2] = frame->data[2]; + + w->dest[0] += w->mb_y * linesize << 3; + // chroma blocks are on add rows + w->dest[1] += (w->mb_y & ~1) * uvlinesize << 2; + w->dest[2] += (w->mb_y & ~1) * uvlinesize << 2; } -/** - * Initialize IntraX8 frame decoder. - * Requires valid MpegEncContext with valid s->mb_width before calling. - * @param w pointer to IntraX8Context - * @param s pointer to MpegEncContext of the parent codec - */ -av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ - - w->s=s; - x8_vlc_init(); - assert(s->mb_width>0); - w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb - - ff_init_scantable(s->idsp.idct_permutation, &w->scantable[0], ff_wmv1_scantable[0]); - ff_init_scantable(s->idsp.idct_permutation, &w->scantable[1], ff_wmv1_scantable[2]); - ff_init_scantable(s->idsp.idct_permutation, &w->scantable[2], ff_wmv1_scantable[3]); +av_cold int ff_intrax8_common_init(AVCodecContext *avctx, + IntraX8Context *w, IDCTDSPContext *idsp, + int16_t (*block)[64], + int block_last_index[12], + int mb_width, int mb_height) +{ + int ret = x8_vlc_init(); + if (ret < 0) + return ret; + + w->avctx = avctx; + w->idsp = *idsp; + w->mb_width = mb_width; + w->mb_height = mb_height; + w->block = block; + w->block_last_index = block_last_index; + + // two rows, 2 blocks per cannon mb + w->prediction_table = av_mallocz(w->mb_width * 2 * 2); + if (!w->prediction_table) + return AVERROR(ENOMEM); + + ff_init_scantable(w->idsp.idct_permutation, &w->scantable[0], + ff_wmv1_scantable[0]); + ff_init_scantable(w->idsp.idct_permutation, &w->scantable[1], + ff_wmv1_scantable[2]); + ff_init_scantable(w->idsp.idct_permutation, &w->scantable[2], + ff_wmv1_scantable[3]); ff_intrax8dsp_init(&w->dsp); + ff_blockdsp_init(&w->bdsp, avctx); + + return 0; } -/** - * Destroy IntraX8 frame structure. - * @param w pointer to IntraX8Context - */ -av_cold void ff_intrax8_common_end(IntraX8Context * w) +av_cold void ff_intrax8_common_end(IntraX8Context *w) { av_freep(&w->prediction_table); } -/** - * Decode single IntraX8 frame. - * The parent codec must fill s->loopfilter and s->gb (bitstream). - * The parent codec must call ff_mpv_frame_start(), ff_er_frame_start() before calling this function. - * The parent codec must call ff_er_frame_end(), ff_mpv_frame_end() after calling this function. - * This function does not use ff_mpv_decode_mb(). - * @param w pointer to IntraX8Context - * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. - * @param quant_offset offset away from zero - */ -int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ - MpegEncContext * const s= w->s; +int ff_intrax8_decode_picture(IntraX8Context *const w, Picture *pict, + GetBitContext *gb, int *mb_x, int *mb_y, + int dquant, int quant_offset, + int loopfilter, int lowdelay) +{ int mb_xy; - assert(s); - w->use_quant_matrix = get_bits1(&s->gb); + w->gb = gb; w->dquant = dquant; w->quant = dquant >> 1; w->qsum = quant_offset; + w->frame = pict->f; + w->loopfilter = loopfilter; + w->use_quant_matrix = get_bits1(w->gb); - w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; - if(w->quant < 5){ - w->quant_dc_chroma = w->quant; + w->mb_x = *mb_x; + w->mb_y = *mb_y; + + w->divide_quant_dc_luma = ((1 << 16) + (w->quant >> 1)) / w->quant; + if (w->quant < 5) { + w->quant_dc_chroma = w->quant; w->divide_quant_dc_chroma = w->divide_quant_dc_luma; - }else{ - w->quant_dc_chroma = w->quant+((w->quant+3)>>3); - w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; + } else { + w->quant_dc_chroma = w->quant + ((w->quant + 3) >> 3); + w->divide_quant_dc_chroma = ((1 << 16) + (w->quant_dc_chroma >> 1)) / w->quant_dc_chroma; } x8_reset_vlc_tables(w); - s->resync_mb_x=0; - s->resync_mb_y=0; - - for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ - x8_init_block_index(s); - mb_xy=(s->mb_y>>1)*s->mb_stride; - - for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ + for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) { + x8_init_block_index(w, w->frame); + mb_xy = (w->mb_y >> 1) * (w->mb_width + 1); + for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) { x8_get_prediction(w); - if(x8_setup_spatial_predictor(w,0)) goto error; - if(x8_decode_intra_mb(w,0)) goto error; + if (x8_setup_spatial_predictor(w, 0)) + goto error; + if (x8_decode_intra_mb(w, 0)) + goto error; - if( s->mb_x & s->mb_y & 1 ){ + if (w->mb_x & w->mb_y & 1) { x8_get_prediction_chroma(w); - /*when setting up chroma, no vlc is read, - so no error condition can be reached*/ - x8_setup_spatial_predictor(w,1); - if(x8_decode_intra_mb(w,1)) goto error; + /* when setting up chroma, no vlc is read, + * so no error condition can be reached */ + x8_setup_spatial_predictor(w, 1); + if (x8_decode_intra_mb(w, 1)) + goto error; - x8_setup_spatial_predictor(w,2); - if(x8_decode_intra_mb(w,2)) goto error; + x8_setup_spatial_predictor(w, 2); + if (x8_decode_intra_mb(w, 2)) + goto error; - s->dest[1]+= 8; - s->dest[2]+= 8; + w->dest[1] += 8; + w->dest[2] += 8; - /*emulate MB info in the relevant tables*/ - s->mbskip_table [mb_xy]=0; - s->mbintra_table[mb_xy]=1; - s->current_picture.qscale_table[mb_xy] = w->quant; + pict->qscale_table[mb_xy] = w->quant; mb_xy++; } - s->dest[0]+= 8; - } - if(s->mb_y&1){ - ff_mpeg_draw_horiz_band(s, (s->mb_y-1)*8, 16); + w->dest[0] += 8; } + if (w->mb_y & 1) + ff_draw_horiz_band(w->avctx, w->frame, w->frame, + (w->mb_y - 1) * 8, 16, + PICT_FRAME, 0, lowdelay); } error: - ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, - (s->mb_x>>1)-1, (s->mb_y>>1)-1, - ER_MB_END ); + *mb_x = w->mb_x; + *mb_y = w->mb_y; + return 0; } diff --git a/libavcodec/intrax8.h b/libavcodec/intrax8.h index 6967317..ad172b1 100644 --- a/libavcodec/intrax8.h +++ b/libavcodec/intrax8.h @@ -19,30 +19,45 @@ #ifndef AVCODEC_INTRAX8_H #define AVCODEC_INTRAX8_H +#include "blockdsp.h" #include "get_bits.h" -#include "mpegvideo.h" +#include "idctdsp.h" #include "intrax8dsp.h" +#include "mpegpicture.h" typedef struct IntraX8Context { - VLC * j_ac_vlc[4];//they point to the static j_mb_vlc - VLC * j_orient_vlc; - VLC * j_dc_vlc[3]; + VLC *j_ac_vlc[4]; // they point to the static j_mb_vlc + VLC *j_orient_vlc; + VLC *j_dc_vlc[3]; int use_quant_matrix; -//set by ff_intrax8_common_init - uint8_t * prediction_table;//2*(mb_w*2) + + // set by ff_intrax8_common_init + uint8_t *prediction_table; // 2 * (mb_w * 2) ScanTable scantable[3]; -//set by the caller codec - MpegEncContext * s; + AVCodecContext *avctx; + int *block_last_index; ///< last nonzero coefficient in block + int16_t (*block)[64]; + + // set by the caller codec IntraX8DSPContext dsp; + IDCTDSPContext idsp; + BlockDSPContext bdsp; int quant; int dquant; int qsum; -//calculated per frame + int loopfilter; + AVFrame *frame; + GetBitContext *gb; + + // calculated per frame int quant_dc_chroma; int divide_quant_dc_luma; int divide_quant_dc_chroma; -//changed per block + uint8_t *dest[3]; + uint8_t scratchpad[42]; // size of the block is fixed (8x8 plus padding) + + // changed per block int edges; int flat_dc; int predicted_dc; @@ -50,10 +65,49 @@ typedef struct IntraX8Context { int chroma_orient; int orient; int est_run; + + // block props + int mb_x, mb_y; + int mb_width, mb_height; } IntraX8Context; -void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s); -void ff_intrax8_common_end(IntraX8Context * w); -int ff_intrax8_decode_picture(IntraX8Context * w, int quant, int halfpq); +/** + * Initialize IntraX8 frame decoder. + * @param avctx pointer to AVCodecContext + * @param w pointer to IntraX8Context + * @param idsp pointer to IDCTDSPContext + * @param block pointer to block array + * @param block_last_index pointer to index array + * @param mb_width macroblock width + * @param mb_height macroblock height + * @return 0 on success, a negative AVERROR value on error + */ +int ff_intrax8_common_init(AVCodecContext *avctx, + IntraX8Context *w, IDCTDSPContext *idsp, + int16_t (*block)[64], + int block_last_index[12], + int mb_width, int mb_height); + +/** + * Destroy IntraX8 frame structure. + * @param w pointer to IntraX8Context + */ +void ff_intrax8_common_end(IntraX8Context *w); + +/** + * Decode single IntraX8 frame. + * @param w pointer to IntraX8Context + * @param pict the output Picture containing an AVFrame + * @param gb open bitstream reader + * @param mb_x pointer to the x coordinate of the current macroblock + * @param mb_y pointer to the y coordinate of the current macroblock + * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. + * @param quant_offset offset away from zero + * @param loopfilter enable filter after decoding a block + */ +int ff_intrax8_decode_picture(IntraX8Context *w, Picture *pict, + GetBitContext *gb, int *mb_x, int *mb_y, + int quant, int halfpq, + int loopfilter, int lowdelay); #endif /* AVCODEC_INTRAX8_H */ diff --git a/libavcodec/intrax8dsp.c b/libavcodec/intrax8dsp.c index 1115945..108cfe3 100644 --- a/libavcodec/intrax8dsp.c +++ b/libavcodec/intrax8dsp.c @@ -17,7 +17,7 @@ */ /** -* @file + * @file *@brief IntraX8 frame subdecoder image manipulation routines */ @@ -25,27 +25,27 @@ #include "libavutil/common.h" /* -area positions, #3 is 1 pixel only, other are 8 pixels - |66666666| - 3|44444444|55555555| -- -+--------+--------+ -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -1 2|XXXXXXXX| -^-start -*/ + * area positions, #3 is 1 pixel only, other are 8 pixels + * |66666666| + * 3|44444444|55555555| + * - -+--------+--------+ + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * 1 2|XXXXXXXX| + * ^-start + */ #define area1 (0) #define area2 (8) -#define area3 (8+8) -#define area4 (8+8+1) -#define area5 (8+8+1+8) -#define area6 (8+8+1+16) +#define area3 (8 + 8) +#define area4 (8 + 8 + 1) +#define area5 (8 + 8 + 1 + 8) +#define area6 (8 + 8 + 1 + 16) /** Collect statistics and prepare the edge pixels required by the other spatial compensation functions. @@ -61,372 +61,404 @@ area positions, #3 is 1 pixel only, other are 8 pixels 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6; note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas; 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5; -*/ -static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize, - int * range, int * psum, int edges){ - uint8_t * ptr; +-*/ +static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, + int linesize, int *range, int *psum, + int edges) +{ + uint8_t *ptr; int sum; int i; - int min_pix,max_pix; + int min_pix, max_pix; uint8_t c; - if((edges&3)==3){ - *psum=0x80*(8+1+8+2); - *range=0; - memset(dst,0x80,16+1+16+8); - //this triggers flat_dc for sure. - //flat_dc avoids all (other) prediction modes, but requires dc_level decoding. + if ((edges & 3) == 3) { + *psum = 0x80 * (8 + 1 + 8 + 2); + *range = 0; + memset(dst, 0x80, 16 + 1 + 16 + 8); + /* this triggers flat_dc for sure. flat_dc avoids all (other) + * prediction modes, but requires dc_level decoding. */ return; } - min_pix=256; - max_pix=-1; + min_pix = 256; + max_pix = -1; - sum=0; + sum = 0; - if(!(edges&1)){//(mb_x!=0)//there is previous block on this row - ptr=src-1;//left column, area 2 - for(i=7;i>=0;i--){ - c=*(ptr-1);//area1, same mb as area2, no need to check - dst[area1+i]=c; - c=*(ptr); + if (!(edges & 1)) { // (mb_x != 0) // there is previous block on this row + ptr = src - 1; // left column, area 2 + for (i = 7; i >= 0; i--) { + c = *(ptr - 1); // area1, same mb as area2, no need to check + dst[area1 + i] = c; + c = *ptr; - sum+=c; - min_pix=FFMIN(min_pix,c); - max_pix=FFMAX(max_pix,c); - dst[area2+i]=c; + sum += c; + min_pix = FFMIN(min_pix, c); + max_pix = FFMAX(max_pix, c); + dst[area2 + i] = c; - ptr+=linesize; + ptr += linesize; } } - if(!(edges&2)){ //(mb_y!=0)//there is row above - ptr=src-linesize;//top line - for(i=0;i<8;i++){ - c=*(ptr+i); - sum+=c; - min_pix=FFMIN(min_pix, c); - max_pix=FFMAX(max_pix, c); + if (!(edges & 2)) { // (mb_y != 0) // there is row above + ptr = src - linesize; // top line + for (i = 0; i < 8; i++) { + c = *(ptr + i); + sum += c; + min_pix = FFMIN(min_pix, c); + max_pix = FFMAX(max_pix, c); } - if(edges&4){//last block on the row? - memset(dst+area5,c,8);//set with last pixel fr - memcpy(dst+area4, ptr, 8); - }else{ - memcpy(dst+area4, ptr, 16);//both area4 and 5 + if (edges & 4) { // last block on the row? + memset(dst + area5, c, 8); // set with last pixel fr + memcpy(dst + area4, ptr, 8); + } else { + memcpy(dst + area4, ptr, 16); // both area4 and 5 } - memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block + // area6 always present in the above block + memcpy(dst + area6, ptr - linesize, 8); } - //now calculate the stuff we need - if(edges&3){//mb_x==0 || mb_y==0){ - int avg=(sum+4)>>3; - if(edges&1){ //(mb_x==0) {//implies mb_y!=0 - memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged - }else{//implies y==0 x!=0 - memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6 - } - sum+=avg*9; - }else{ - uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column - dst[area3]=c; - sum+=c; - //edge pixel is not part of min/max + // now calculate the stuff we need + if (edges & 3) { // mb_x ==0 || mb_y == 0) { + int avg = (sum + 4) >> 3; + + if (edges & 1) // (mb_x == 0) { // implies mb_y !=0 + memset(dst + area1, avg, 8 + 8 + 1); // areas 1, 2, 3 are averaged + else // implies y == 0 x != 0 + memset(dst + area3, avg, 1 + 16 + 8); // areas 3, 4, 5, 6 + + sum += avg * 9; + } else { + // the edge pixel, in the top line and left column + uint8_t c = *(src - 1 - linesize); + dst[area3] = c; + sum += c; + // edge pixel is not part of min/max } - (*range) = max_pix - min_pix; - sum += *(dst+area5) + *(dst+area5+1); - *psum = sum; + *range = max_pix - min_pix; + sum += *(dst + area5) + *(dst + area5 + 1); + *psum = sum; } - -static const uint16_t zero_prediction_weights[64*2] = { - 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72, - 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97, - 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132, - 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180, - 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231, - 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288, - 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390, - 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499 +static const uint16_t zero_prediction_weights[64 * 2] = { + 640, 640, 669, 480, 708, 354, 748, 257, + 792, 198, 760, 143, 808, 101, 772, 72, + 480, 669, 537, 537, 598, 416, 661, 316, + 719, 250, 707, 185, 768, 134, 745, 97, + 354, 708, 416, 598, 488, 488, 564, 388, + 634, 317, 642, 241, 716, 179, 706, 132, + 257, 748, 316, 661, 388, 564, 469, 469, + 543, 395, 571, 311, 655, 238, 660, 180, + 198, 792, 250, 719, 317, 634, 395, 543, + 469, 469, 507, 380, 597, 299, 616, 231, + 161, 855, 206, 788, 266, 710, 340, 623, + 411, 548, 455, 455, 548, 366, 576, 288, + 122, 972, 159, 914, 211, 842, 276, 758, + 341, 682, 389, 584, 483, 483, 520, 390, + 110, 1172, 144, 1107, 193, 1028, 254, 932, + 317, 846, 366, 731, 458, 611, 499, 499, }; -static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){ - int i,j; - int x,y; - unsigned int p;//power divided by 2 +static void spatial_compensation_0(uint8_t *src, uint8_t *dst, int linesize) +{ + int i, j; + int x, y; + unsigned int p; // power divided by 2 int a; uint16_t left_sum[2][8] = { { 0 } }; uint16_t top_sum[2][8] = { { 0 } }; - for(i=0;i<8;i++){ - a=src[area2+7-i]<<4; - for(j=0;j<8;j++){ - p=abs(i-j); - left_sum[p&1][j]+= a>>(p>>1); + for (i = 0; i < 8; i++) { + a = src[area2 + 7 - i] << 4; + for (j = 0; j < 8; j++) { + p = abs(i - j); + left_sum[p & 1][j] += a >> (p >> 1); } } - for(i=0;i<8;i++){ - a=src[area4+i]<<4; - for(j=0;j<8;j++){ - p=abs(i-j); - top_sum[p&1][j]+= a>>(p>>1); + for (i = 0; i < 8; i++) { + a = src[area4 + i] << 4; + for (j = 0; j < 8; j++) { + p = abs(i - j); + top_sum[p & 1][j] += a >> (p >> 1); } } - for(;i<10;i++){ - a=src[area4+i]<<4; - for(j=5;j<8;j++){ - p=abs(i-j); - top_sum[p&1][j]+= a>>(p>>1); + for (; i < 10; i++) { + a = src[area4 + i] << 4; + for (j = 5; j < 8; j++) { + p = abs(i - j); + top_sum[p & 1][j] += a >> (p >> 1); } } - for(;i<12;i++){ - a=src[area4+i]<<4; - for(j=7;j<8;j++){ - p=abs(i-j); - top_sum[p&1][j]+= a>>(p>>1); + for (; i < 12; i++) { + a = src[area4 + i] << 4; + for (j = 7; j < 8; j++) { + p = abs(i - j); + top_sum[p & 1][j] += a >> (p >> 1); } } - for(i=0;i<8;i++){ - top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2 - left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8; + for (i = 0; i < 8; i++) { + top_sum[0][i] += (top_sum[1][i] * 181 + 128) >> 8; // 181 is sqrt(2)/2 + left_sum[0][i] += (left_sum[1][i] * 181 + 128) >> 8; } - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x] = ( - (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] + - (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] + - 0x8000 - )>>16; - } - dst+=linesize; + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = ((uint32_t) top_sum[0][x] * zero_prediction_weights[y * 16 + x * 2 + 0] + + (uint32_t) left_sum[0][y] * zero_prediction_weights[y * 16 + x * 2 + 1] + + 0x8000) >> 16; + dst += linesize; } } -static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ]; - } - dst+=linesize; +static void spatial_compensation_1(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = src[area4 + FFMIN(2 * y + x + 2, 15)]; + dst += linesize; } } -static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=src[area4 +1+y+x]; - } - dst+=linesize; +static void spatial_compensation_2(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = src[area4 + 1 + y + x]; + dst += linesize; } } -static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=src[area4 +((y+1)>>1)+x]; - } - dst+=linesize; +static void spatial_compensation_3(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = src[area4 + ((y + 1) >> 1) + x]; + dst += linesize; } } -static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1; - } - dst+=linesize; +static void spatial_compensation_4(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = (src[area4 + x] + src[area6 + x] + 1) >> 1; + dst += linesize; } } -static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - if(2*x-y<0){ - dst[x]=src[area2+9+2*x-y]; - }else{ - dst[x]=src[area4 +x-((y+1)>>1)]; - } + +static void spatial_compensation_5(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + if (2 * x - y < 0) + dst[x] = src[area2 + 9 + 2 * x - y]; + else + dst[x] = src[area4 + x - ((y + 1) >> 1)]; } - dst+=linesize; + dst += linesize; } } -static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=src[area3+x-y]; - } - dst+=linesize; +static void spatial_compensation_6(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = src[area3 + x - y]; + dst += linesize; } } -static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - if(x-2*y>0){ - dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1; - }else{ - dst[x]=src[area2+8-y +(x>>1)]; - } + +static void spatial_compensation_7(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + if (x - 2 * y > 0) + dst[x] = (src[area3 - 1 + x - 2 * y] + src[area3 + x - 2 * y] + 1) >> 1; + else + dst[x] = src[area2 + 8 - y + (x >> 1)]; } - dst+=linesize; + dst += linesize; } } -static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1; - } - dst+=linesize; +static void spatial_compensation_8(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = (src[area1 + 7 - y] + src[area2 + 7 - y] + 1) >> 1; + dst += linesize; } } -static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=src[area2+6-FFMIN(x+y,6)]; - } - dst+=linesize; +static void spatial_compensation_9(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = src[area2 + 6 - FFMIN(x + y, 6)]; + dst += linesize; } } -static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3; - } - dst+=linesize; +static void spatial_compensation_10(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = (src[area2 + 7 - y] * (8 - x) + src[area4 + x] * x + 4) >> 3; + dst += linesize; } } -static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){ - int x,y; - for(y=0;y<8;y++){ - for(x=0;x<8;x++){ - dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3; - } - dst+=linesize; +static void spatial_compensation_11(uint8_t *src, uint8_t *dst, int linesize) +{ + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + dst[x] = (src[area2 + 7 - y] * y + src[area4 + x] * (8 - y) + 4) >> 3; + dst += linesize; } } -static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){ - int i,t; - int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9; - int ql=(quant+10)>>3; - - for(i=0; i<8; i++,ptr+=b_stride){ - p0=ptr[-5*a_stride]; - p1=ptr[-4*a_stride]; - p2=ptr[-3*a_stride]; - p3=ptr[-2*a_stride]; - p4=ptr[-1*a_stride]; - p5=ptr[ 0 ]; - p6=ptr[ 1*a_stride]; - p7=ptr[ 2*a_stride]; - p8=ptr[ 3*a_stride]; - p9=ptr[ 4*a_stride]; - - t= - (FFABS(p1-p2) <= ql) + - (FFABS(p2-p3) <= ql) + - (FFABS(p3-p4) <= ql) + - (FFABS(p4-p5) <= ql); - if(t>0){//You need at least 1 to be able to reach a total score of 6. - t+= - (FFABS(p5-p6) <= ql) + - (FFABS(p6-p7) <= ql) + - (FFABS(p7-p8) <= ql) + - (FFABS(p8-p9) <= ql) + - (FFABS(p0-p1) <= ql); - if(t>=6){ - int min,max; - - min=max=p1; - min=FFMIN(min,p3); max=FFMAX(max,p3); - min=FFMIN(min,p5); max=FFMAX(max,p5); - min=FFMIN(min,p8); max=FFMAX(max,p8); - if(max-min<2*quant){//early stop - min=FFMIN(min,p2); max=FFMAX(max,p2); - min=FFMIN(min,p4); max=FFMAX(max,p4); - min=FFMIN(min,p6); max=FFMAX(max,p6); - min=FFMIN(min,p7); max=FFMAX(max,p7); - if(max-min<2*quant){ - ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3; - ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3; - ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3; - ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3; +static void x8_loop_filter(uint8_t *ptr, const int a_stride, const int b_stride, int quant) +{ + int i, t; + int p0, p1, p2, p3, p4, p5, p6, p7, p8, p9; + int ql = (quant + 10) >> 3; + + for (i = 0; i < 8; i++, ptr += b_stride) { + p0 = ptr[-5 * a_stride]; + p1 = ptr[-4 * a_stride]; + p2 = ptr[-3 * a_stride]; + p3 = ptr[-2 * a_stride]; + p4 = ptr[-1 * a_stride]; + p5 = ptr[0]; + p6 = ptr[1 * a_stride]; + p7 = ptr[2 * a_stride]; + p8 = ptr[3 * a_stride]; + p9 = ptr[4 * a_stride]; + + t = (FFABS(p1 - p2) <= ql) + + (FFABS(p2 - p3) <= ql) + + (FFABS(p3 - p4) <= ql) + + (FFABS(p4 - p5) <= ql); + + // You need at least 1 to be able to reach a total score of 6. + if (t > 0) { + t += (FFABS(p5 - p6) <= ql) + + (FFABS(p6 - p7) <= ql) + + (FFABS(p7 - p8) <= ql) + + (FFABS(p8 - p9) <= ql) + + (FFABS(p0 - p1) <= ql); + if (t >= 6) { + int min, max; + + min = max = p1; + min = FFMIN(min, p3); + max = FFMAX(max, p3); + min = FFMIN(min, p5); + max = FFMAX(max, p5); + min = FFMIN(min, p8); + max = FFMAX(max, p8); + if (max - min < 2 * quant) { // early stop + min = FFMIN(min, p2); + max = FFMAX(max, p2); + min = FFMIN(min, p4); + max = FFMAX(max, p4); + min = FFMIN(min, p6); + max = FFMAX(max, p6); + min = FFMIN(min, p7); + max = FFMAX(max, p7); + if (max - min < 2 * quant) { + ptr[-2 * a_stride] = (4 * p2 + 3 * p3 + 1 * p7 + 4) >> 3; + ptr[-1 * a_stride] = (3 * p2 + 3 * p4 + 2 * p7 + 4) >> 3; + ptr[0] = (2 * p2 + 3 * p5 + 3 * p7 + 4) >> 3; + ptr[1 * a_stride] = (1 * p2 + 3 * p6 + 4 * p7 + 4) >> 3; continue; - }; + } } } } { - int x,x0,x1,x2; + int x, x0, x1, x2; int m; - x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3; - if(FFABS(x0) < quant){ - x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3; - x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3; + x0 = (2 * p3 - 5 * p4 + 5 * p5 - 2 * p6 + 4) >> 3; + if (FFABS(x0) < quant) { + x1 = (2 * p1 - 5 * p2 + 5 * p3 - 2 * p4 + 4) >> 3; + x2 = (2 * p5 - 5 * p6 + 5 * p7 - 2 * p8 + 4) >> 3; - x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) ); - m=p4-p5; + x = FFABS(x0) - FFMIN(FFABS(x1), FFABS(x2)); + m = p4 - p5; - if( x > 0 && (m^x0) <0){ + if (x > 0 && (m ^ x0) < 0) { int32_t sign; - sign=m>>31; - m=(m^sign)-sign;//abs(m) - m>>=1; + sign = m >> 31; + m = (m ^ sign) - sign; // abs(m) + m >>= 1; - x=(5*x)>>3; + x = 5 * x >> 3; - if(x>m) x=m; + if (x > m) + x = m; - x=(x^sign)-sign; + x = (x ^ sign) - sign; - ptr[-1*a_stride] -= x; - ptr[ 0] += x; + ptr[-1 * a_stride] -= x; + ptr[0] += x; } } } } } -static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){ +static void x8_h_loop_filter(uint8_t *src, int stride, int qscale) +{ x8_loop_filter(src, stride, 1, qscale); } -static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){ +static void x8_v_loop_filter(uint8_t *src, int stride, int qscale) +{ x8_loop_filter(src, 1, stride, qscale); } av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp) { - dsp->h_loop_filter=x8_h_loop_filter; - dsp->v_loop_filter=x8_v_loop_filter; - dsp->setup_spatial_compensation=x8_setup_spatial_compensation; - dsp->spatial_compensation[0]=spatial_compensation_0; - dsp->spatial_compensation[1]=spatial_compensation_1; - dsp->spatial_compensation[2]=spatial_compensation_2; - dsp->spatial_compensation[3]=spatial_compensation_3; - dsp->spatial_compensation[4]=spatial_compensation_4; - dsp->spatial_compensation[5]=spatial_compensation_5; - dsp->spatial_compensation[6]=spatial_compensation_6; - dsp->spatial_compensation[7]=spatial_compensation_7; - dsp->spatial_compensation[8]=spatial_compensation_8; - dsp->spatial_compensation[9]=spatial_compensation_9; - dsp->spatial_compensation[10]=spatial_compensation_10; - dsp->spatial_compensation[11]=spatial_compensation_11; + dsp->h_loop_filter = x8_h_loop_filter; + dsp->v_loop_filter = x8_v_loop_filter; + dsp->setup_spatial_compensation = x8_setup_spatial_compensation; + dsp->spatial_compensation[0] = spatial_compensation_0; + dsp->spatial_compensation[1] = spatial_compensation_1; + dsp->spatial_compensation[2] = spatial_compensation_2; + dsp->spatial_compensation[3] = spatial_compensation_3; + dsp->spatial_compensation[4] = spatial_compensation_4; + dsp->spatial_compensation[5] = spatial_compensation_5; + dsp->spatial_compensation[6] = spatial_compensation_6; + dsp->spatial_compensation[7] = spatial_compensation_7; + dsp->spatial_compensation[8] = spatial_compensation_8; + dsp->spatial_compensation[9] = spatial_compensation_9; + dsp->spatial_compensation[10] = spatial_compensation_10; + dsp->spatial_compensation[11] = spatial_compensation_11; } diff --git a/libavcodec/intrax8dsp.h b/libavcodec/intrax8dsp.h index 5c3cc4a..4ba1a0b 100644 --- a/libavcodec/intrax8dsp.h +++ b/libavcodec/intrax8dsp.h @@ -25,9 +25,9 @@ typedef struct IntraX8DSPContext { void (*v_loop_filter)(uint8_t *src, int stride, int qscale); void (*h_loop_filter)(uint8_t *src, int stride, int qscale); - void (*spatial_compensation[12])(uint8_t *src , uint8_t *dst, int linesize); + void (*spatial_compensation[12])(uint8_t *src, uint8_t *dst, int linesize); void (*setup_spatial_compensation)(uint8_t *src, uint8_t *dst, int linesize, - int *range, int *sum, int edges); + int *range, int *sum, int edges); } IntraX8DSPContext; void ff_intrax8dsp_init(IntraX8DSPContext *dsp); diff --git a/libavcodec/intrax8huf.h b/libavcodec/intrax8huf.h index 6bf01f3..684fdb7 100644 --- a/libavcodec/intrax8huf.h +++ b/libavcodec/intrax8huf.h @@ -21,897 +21,940 @@ #include - -static const uint16_t x8_orient_lowquant_table[4][12][2]={ - {//0 - {0x0000, 1}, {0x0004, 3}, {0x0005, 3}, {0x000C, 4}, - {0x000D, 4}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6}, - {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, - },{//1 - {0x0000, 5}, {0x0001, 5}, {0x0002, 5}, {0x0001, 2}, - {0x0002, 2}, {0x0002, 4}, {0x0003, 5}, {0x0006, 3}, - {0x0003, 4}, {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, - },{//2 - {0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3}, - {0x0006, 3}, {0x0038, 6}, {0x0039, 6}, {0x001D, 5}, - {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, - },{//3 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0001, 2}, - {0x0002, 2}, {0x0018, 5}, {0x0019, 5}, {0x000D, 4}, - {0x001C, 5}, {0x001D, 5}, {0x001E, 5}, {0x001F, 5}, - } +static const uint16_t x8_orient_lowquant_table[4][12][2] = { + { // 0 + { 0x0000, 1 }, { 0x0004, 3 }, { 0x0005, 3 }, { 0x000C, 4 }, + { 0x000D, 4 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 }, + { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, + }, + { // 1 + { 0x0000, 5 }, { 0x0001, 5 }, { 0x0002, 5 }, { 0x0001, 2 }, + { 0x0002, 2 }, { 0x0002, 4 }, { 0x0003, 5 }, { 0x0006, 3 }, + { 0x0003, 4 }, { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, + }, + { // 2 + { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 }, + { 0x0006, 3 }, { 0x0038, 6 }, { 0x0039, 6 }, { 0x001D, 5 }, + { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, + }, + { // 3 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0001, 2 }, + { 0x0002, 2 }, { 0x0018, 5 }, { 0x0019, 5 }, { 0x000D, 4 }, + { 0x001C, 5 }, { 0x001D, 5 }, { 0x001E, 5 }, { 0x001F, 5 }, + }, }; -static const uint16_t x8_orient_highquant_table[2][12][2]={ - {//0 - {0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3}, - {0x0006, 3}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6}, - {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, - },{//1 - {0x0000, 1}, {0x0002, 2}, {0x0006, 3}, {0x001C, 5}, - {0x001D, 5}, {0x0078, 7}, {0x003D, 6}, {0x0079, 7}, - {0x007C, 7}, {0x007D, 7}, {0x007E, 7}, {0x007F, 7}, - } +static const uint16_t x8_orient_highquant_table[2][12][2] = { + { // 0 + { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 }, + { 0x0006, 3 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 }, + { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, + }, + { // 1 + { 0x0000, 1 }, { 0x0002, 2 }, { 0x0006, 3 }, { 0x001C, 5 }, + { 0x001D, 5 }, { 0x0078, 7 }, { 0x003D, 6 }, { 0x0079, 7 }, + { 0x007C, 7 }, { 0x007D, 7 }, { 0x007E, 7 }, { 0x007F, 7 }, + }, }; #define MAX_OR_VLC_BITS 7 - -static const uint16_t x8_dc_lowquant_table[8][34][2]={ - {//0 - {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5}, - {0x0005, 5}, {0x0006, 5}, {0x000E, 6}, {0x000F, 6}, - {0x0040, 8}, {0x0041, 8}, {0x0840, 13}, {0x0841, 13}, - {0x0842, 13}, {0x0843, 13}, {0x0844, 13}, {0x0845, 13}, - {0x0846, 13}, {0x0002, 2}, {0x0003, 2}, {0x0003, 3}, - {0x0005, 4}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8}, - {0x0085, 9}, {0x0847, 13}, {0x0848, 13}, {0x0849, 13}, - {0x084A, 13}, {0x084B, 13}, {0x084C, 13}, {0x084D, 13}, - {0x084E, 13}, {0x084F, 13}, - },{//1 - {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, - {0x0006, 4}, {0x0004, 3}, {0x0007, 4}, {0x0005, 3}, - {0x000C, 4}, {0x000D, 4}, {0x001C, 5}, {0x003A, 6}, - {0x01D8, 9}, {0x01D9, 9}, {0x1DA0, 13}, {0x1DA1, 13}, - {0x1DA2, 13}, {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, - {0x0077, 7}, {0x01DB, 9}, {0x007E, 7}, {0x00FE, 8}, - {0x01FE, 9}, {0x1DA3, 13}, {0x1DA4, 13}, {0x1DA5, 13}, - {0x0ED3, 12}, {0x0ED4, 12}, {0x01FF, 9}, {0x0ED5, 12}, - {0x0ED6, 12}, {0x0ED7, 12}, - },{//2 - {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, - {0x0006, 4}, {0x0007, 4}, {0x0008, 4}, {0x0009, 4}, - {0x0028, 6}, {0x0029, 6}, {0x0054, 7}, {0x0055, 7}, - {0x0AC0, 12}, {0x0AC1, 12}, {0x0AC2, 12}, {0x0AC3, 12}, - {0x0AC4, 12}, {0x000B, 4}, {0x0006, 3}, {0x000E, 4}, - {0x001E, 5}, {0x003E, 6}, {0x003F, 6}, {0x0057, 7}, - {0x00AD, 8}, {0x0AC5, 12}, {0x0AC6, 12}, {0x0AC7, 12}, - {0x0AC8, 12}, {0x0AC9, 12}, {0x0ACA, 12}, {0x0ACB, 12}, - {0x0566, 11}, {0x0567, 11}, - },{//3 - {0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3}, - {0x0005, 3}, {0x0006, 3}, {0x0001, 4}, {0x000E, 4}, - {0x003C, 6}, {0x003D, 6}, {0x007C, 7}, {0x00FA, 8}, - {0x3EC0, 14}, {0x3EC1, 14}, {0x3EC2, 14}, {0x3EC3, 14}, - {0x1F62, 13}, {0x01F7, 9}, {0x007E, 7}, {0x00FE, 8}, - {0x00FF, 8}, {0x1F63, 13}, {0x1F64, 13}, {0x1F65, 13}, - {0x1F66, 13}, {0x1F67, 13}, {0x1F68, 13}, {0x1F69, 13}, - {0x1F6A, 13}, {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, - {0x1F6E, 13}, {0x1F6F, 13}, - },{//4 - {0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, - {0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7}, - {0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7}, - {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7}, - {0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7}, - {0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, - {0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, - {0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, - {0x001E, 7}, {0x001F, 7}, - },{//5 - {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0008, 6}, - {0x0009, 6}, {0x000A, 6}, {0x0016, 7}, {0x000C, 6}, - {0x0017, 7}, {0x000D, 6}, {0x0038, 8}, {0x001D, 7}, - {0x0039, 8}, {0x0780, 13}, {0x0781, 13}, {0x0782, 13}, - {0x0783, 13}, {0x0002, 3}, {0x0001, 1}, {0x0003, 3}, - {0x001F, 7}, {0x003D, 8}, {0x0079, 9}, {0x0784, 13}, - {0x0785, 13}, {0x0786, 13}, {0x0787, 13}, {0x0788, 13}, - {0x0789, 13}, {0x078A, 13}, {0x078B, 13}, {0x078C, 13}, - {0x078D, 13}, {0x03C7, 12}, - },{//6 - {0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3}, - {0x0001, 4}, {0x000A, 4}, {0x0016, 5}, {0x002E, 6}, - {0x005E, 7}, {0x005F, 7}, {0x00C0, 8}, {0x3040, 14}, - {0x3041, 14}, {0x0305, 10}, {0x0183, 9}, {0x3042, 14}, - {0x3043, 14}, {0x000D, 4}, {0x0007, 3}, {0x0019, 5}, - {0x0031, 6}, {0x00C2, 8}, {0x00C3, 8}, {0x3044, 14}, - {0x3045, 14}, {0x3046, 14}, {0x3047, 14}, {0x3048, 14}, - {0x3049, 14}, {0x304A, 14}, {0x304B, 14}, {0x304C, 14}, - {0x304D, 14}, {0x1827, 13}, - },{//7 - {0x0000, 6}, {0x0001, 6}, {0x0002, 6}, {0x0006, 7}, - {0x0007, 7}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6}, - {0x000E, 7}, {0x001E, 8}, {0x001F, 8}, {0x0040, 9}, - {0x0082, 10}, {0x0830, 14}, {0x0831, 14}, {0x0832, 14}, - {0x0833, 14}, {0x0001, 1}, {0x0001, 2}, {0x0003, 4}, - {0x0005, 5}, {0x0009, 6}, {0x0011, 7}, {0x0021, 8}, - {0x0834, 14}, {0x0835, 14}, {0x0836, 14}, {0x0837, 14}, - {0x0838, 14}, {0x0839, 14}, {0x083A, 14}, {0x083B, 14}, - {0x041E, 13}, {0x041F, 13}, - } +static const uint16_t x8_dc_lowquant_table[8][34][2] = { + { // 0 + { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0004, 5 }, + { 0x0005, 5 }, { 0x0006, 5 }, { 0x000E, 6 }, { 0x000F, 6 }, + { 0x0040, 8 }, { 0x0041, 8 }, { 0x0840, 13 }, { 0x0841, 13 }, + { 0x0842, 13 }, { 0x0843, 13 }, { 0x0844, 13 }, { 0x0845, 13 }, + { 0x0846, 13 }, { 0x0002, 2 }, { 0x0003, 2 }, { 0x0003, 3 }, + { 0x0005, 4 }, { 0x0009, 5 }, { 0x0011, 6 }, { 0x0043, 8 }, + { 0x0085, 9 }, { 0x0847, 13 }, { 0x0848, 13 }, { 0x0849, 13 }, + { 0x084A, 13 }, { 0x084B, 13 }, { 0x084C, 13 }, { 0x084D, 13 }, + { 0x084E, 13 }, { 0x084F, 13 }, + }, + { // 1 + { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, + { 0x0006, 4 }, { 0x0004, 3 }, { 0x0007, 4 }, { 0x0005, 3 }, + { 0x000C, 4 }, { 0x000D, 4 }, { 0x001C, 5 }, { 0x003A, 6 }, + { 0x01D8, 9 }, { 0x01D9, 9 }, { 0x1DA0, 13 }, { 0x1DA1, 13 }, + { 0x1DA2, 13 }, { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, + { 0x0077, 7 }, { 0x01DB, 9 }, { 0x007E, 7 }, { 0x00FE, 8 }, + { 0x01FE, 9 }, { 0x1DA3, 13 }, { 0x1DA4, 13 }, { 0x1DA5, 13 }, + { 0x0ED3, 12 }, { 0x0ED4, 12 }, { 0x01FF, 9 }, { 0x0ED5, 12 }, + { 0x0ED6, 12 }, { 0x0ED7, 12 }, + }, + { // 2 + { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, + { 0x0006, 4 }, { 0x0007, 4 }, { 0x0008, 4 }, { 0x0009, 4 }, + { 0x0028, 6 }, { 0x0029, 6 }, { 0x0054, 7 }, { 0x0055, 7 }, + { 0x0AC0, 12 }, { 0x0AC1, 12 }, { 0x0AC2, 12 }, { 0x0AC3, 12 }, + { 0x0AC4, 12 }, { 0x000B, 4 }, { 0x0006, 3 }, { 0x000E, 4 }, + { 0x001E, 5 }, { 0x003E, 6 }, { 0x003F, 6 }, { 0x0057, 7 }, + { 0x00AD, 8 }, { 0x0AC5, 12 }, { 0x0AC6, 12 }, { 0x0AC7, 12 }, + { 0x0AC8, 12 }, { 0x0AC9, 12 }, { 0x0ACA, 12 }, { 0x0ACB, 12 }, + { 0x0566, 11 }, { 0x0567, 11 }, + }, + { // 3 + { 0x0000, 4 }, { 0x0001, 2 }, { 0x0001, 3 }, { 0x0004, 3 }, + { 0x0005, 3 }, { 0x0006, 3 }, { 0x0001, 4 }, { 0x000E, 4 }, + { 0x003C, 6 }, { 0x003D, 6 }, { 0x007C, 7 }, { 0x00FA, 8 }, + { 0x3EC0, 14 }, { 0x3EC1, 14 }, { 0x3EC2, 14 }, { 0x3EC3, 14 }, + { 0x1F62, 13 }, { 0x01F7, 9 }, { 0x007E, 7 }, { 0x00FE, 8 }, + { 0x00FF, 8 }, { 0x1F63, 13 }, { 0x1F64, 13 }, { 0x1F65, 13 }, + { 0x1F66, 13 }, { 0x1F67, 13 }, { 0x1F68, 13 }, { 0x1F69, 13 }, + { 0x1F6A, 13 }, { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 }, + { 0x1F6E, 13 }, { 0x1F6F, 13 }, + }, + { // 4 + { 0x0000, 7 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, + { 0x0004, 7 }, { 0x0005, 7 }, { 0x0006, 7 }, { 0x0007, 7 }, + { 0x0008, 7 }, { 0x0009, 7 }, { 0x000A, 7 }, { 0x000B, 7 }, + { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, { 0x000F, 7 }, + { 0x0010, 7 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0011, 7 }, + { 0x0012, 7 }, { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, + { 0x0016, 7 }, { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, + { 0x001A, 7 }, { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, + { 0x001E, 7 }, { 0x001F, 7 }, + }, + { // 5 + { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0008, 6 }, + { 0x0009, 6 }, { 0x000A, 6 }, { 0x0016, 7 }, { 0x000C, 6 }, + { 0x0017, 7 }, { 0x000D, 6 }, { 0x0038, 8 }, { 0x001D, 7 }, + { 0x0039, 8 }, { 0x0780, 13 }, { 0x0781, 13 }, { 0x0782, 13 }, + { 0x0783, 13 }, { 0x0002, 3 }, { 0x0001, 1 }, { 0x0003, 3 }, + { 0x001F, 7 }, { 0x003D, 8 }, { 0x0079, 9 }, { 0x0784, 13 }, + { 0x0785, 13 }, { 0x0786, 13 }, { 0x0787, 13 }, { 0x0788, 13 }, + { 0x0789, 13 }, { 0x078A, 13 }, { 0x078B, 13 }, { 0x078C, 13 }, + { 0x078D, 13 }, { 0x03C7, 12 }, + }, + { // 6 + { 0x0000, 4 }, { 0x0001, 2 }, { 0x0001, 3 }, { 0x0004, 3 }, + { 0x0001, 4 }, { 0x000A, 4 }, { 0x0016, 5 }, { 0x002E, 6 }, + { 0x005E, 7 }, { 0x005F, 7 }, { 0x00C0, 8 }, { 0x3040, 14 }, + { 0x3041, 14 }, { 0x0305, 10 }, { 0x0183, 9 }, { 0x3042, 14 }, + { 0x3043, 14 }, { 0x000D, 4 }, { 0x0007, 3 }, { 0x0019, 5 }, + { 0x0031, 6 }, { 0x00C2, 8 }, { 0x00C3, 8 }, { 0x3044, 14 }, + { 0x3045, 14 }, { 0x3046, 14 }, { 0x3047, 14 }, { 0x3048, 14 }, + { 0x3049, 14 }, { 0x304A, 14 }, { 0x304B, 14 }, { 0x304C, 14 }, + { 0x304D, 14 }, { 0x1827, 13 }, + }, + { // 7 + { 0x0000, 6 }, { 0x0001, 6 }, { 0x0002, 6 }, { 0x0006, 7 }, + { 0x0007, 7 }, { 0x0004, 6 }, { 0x0005, 6 }, { 0x0006, 6 }, + { 0x000E, 7 }, { 0x001E, 8 }, { 0x001F, 8 }, { 0x0040, 9 }, + { 0x0082, 10 }, { 0x0830, 14 }, { 0x0831, 14 }, { 0x0832, 14 }, + { 0x0833, 14 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0003, 4 }, + { 0x0005, 5 }, { 0x0009, 6 }, { 0x0011, 7 }, { 0x0021, 8 }, + { 0x0834, 14 }, { 0x0835, 14 }, { 0x0836, 14 }, { 0x0837, 14 }, + { 0x0838, 14 }, { 0x0839, 14 }, { 0x083A, 14 }, { 0x083B, 14 }, + { 0x041E, 13 }, { 0x041F, 13 }, + }, }; -static const uint16_t x8_dc_highquant_table[8][34][2]={ - {//0 - {0x0000, 5}, {0x0001, 4}, {0x0002, 4}, {0x0001, 5}, - {0x0006, 5}, {0x0004, 4}, {0x0007, 5}, {0x000A, 5}, - {0x002C, 7}, {0x002D, 7}, {0x05C0, 12}, {0x05C1, 12}, - {0x05C2, 12}, {0x05C3, 12}, {0x05C4, 12}, {0x05C5, 12}, - {0x05C6, 12}, {0x0003, 3}, {0x0002, 2}, {0x0006, 3}, - {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x002F, 7}, - {0x005D, 8}, {0x05C7, 12}, {0x05C8, 12}, {0x05C9, 12}, - {0x05CA, 12}, {0x05CB, 12}, {0x05CC, 12}, {0x05CD, 12}, - {0x05CE, 12}, {0x05CF, 12}, - },{//1 - {0x0000, 3}, {0x0001, 3}, {0x0002, 3}, {0x0006, 4}, - {0x0007, 4}, {0x0004, 3}, {0x000A, 4}, {0x000B, 4}, - {0x0030, 6}, {0x0062, 7}, {0x0063, 7}, {0x0640, 11}, - {0x0641, 11}, {0x0642, 11}, {0x0643, 11}, {0x0644, 11}, - {0x0645, 11}, {0x0033, 6}, {0x000D, 4}, {0x001C, 5}, - {0x001D, 5}, {0x003C, 6}, {0x001F, 5}, {0x0065, 7}, - {0x007A, 7}, {0x0646, 11}, {0x007B, 7}, {0x0647, 11}, - {0x0648, 11}, {0x0649, 11}, {0x064A, 11}, {0x064B, 11}, - {0x0326, 10}, {0x0327, 10}, - },{//2 - {0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0004, 7}, - {0x0003, 6}, {0x0005, 7}, {0x0010, 8}, {0x0011, 8}, - {0x0240, 13}, {0x0241, 13}, {0x0242, 13}, {0x0243, 13}, - {0x0244, 13}, {0x0245, 13}, {0x0246, 13}, {0x0247, 13}, - {0x0124, 12}, {0x0001, 1}, {0x0001, 2}, {0x0001, 3}, - {0x0003, 5}, {0x0005, 6}, {0x0013, 8}, {0x0125, 12}, - {0x0126, 12}, {0x0127, 12}, {0x0128, 12}, {0x0129, 12}, - {0x012A, 12}, {0x012B, 12}, {0x012C, 12}, {0x012D, 12}, - {0x012E, 12}, {0x012F, 12}, - },{//3 - {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, - {0x0006, 4}, {0x0004, 3}, {0x0005, 3}, {0x0006, 3}, - {0x000E, 5}, {0x000F, 5}, {0x0070, 7}, {0x0710, 11}, - {0x0711, 11}, {0x0712, 11}, {0x0713, 11}, {0x0714, 11}, - {0x0715, 11}, {0x001D, 5}, {0x0072, 7}, {0x003C, 6}, - {0x003D, 6}, {0x0073, 7}, {0x007C, 7}, {0x007D, 7}, - {0x007E, 7}, {0x0716, 11}, {0x0717, 11}, {0x0718, 11}, - {0x007F, 7}, {0x0719, 11}, {0x071A, 11}, {0x071B, 11}, - {0x038E, 10}, {0x038F, 10}, - },{//4 - {0x0000, 8}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, - {0x0002, 9}, {0x0008, 8}, {0x0003, 9}, {0x0240, 14}, - {0x0241, 14}, {0x0242, 14}, {0x0243, 14}, {0x0244, 14}, - {0x0245, 14}, {0x0246, 14}, {0x0247, 14}, {0x0124, 13}, - {0x0125, 13}, {0x0001, 2}, {0x0001, 1}, {0x0001, 3}, - {0x0001, 4}, {0x0003, 6}, {0x0005, 7}, {0x0013, 9}, - {0x0126, 13}, {0x0127, 13}, {0x0128, 13}, {0x0129, 13}, - {0x012A, 13}, {0x012B, 13}, {0x012C, 13}, {0x012D, 13}, - {0x012E, 13}, {0x012F, 13}, - },{//5 - {0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0002, 6}, - {0x0003, 6}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6}, - {0x0007, 6}, {0x0008, 6}, {0x0009, 6}, {0x000A, 6}, - {0x000B, 6}, {0x000C, 6}, {0x000D, 6}, {0x000E, 6}, - {0x000F, 6}, {0x0010, 6}, {0x0011, 6}, {0x0012, 6}, - {0x0013, 6}, {0x0014, 6}, {0x0015, 6}, {0x0016, 6}, - {0x0017, 6}, {0x0018, 6}, {0x0019, 6}, {0x0001, 1}, - {0x001A, 6}, {0x001B, 6}, {0x001C, 6}, {0x001D, 6}, - {0x001E, 6}, {0x001F, 6}, - },{//6 - {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5}, - {0x000A, 6}, {0x0006, 5}, {0x000B, 6}, {0x000E, 6}, - {0x003C, 8}, {0x003D, 8}, {0x07C0, 13}, {0x07C1, 13}, - {0x07C2, 13}, {0x07C3, 13}, {0x07C4, 13}, {0x07C5, 13}, - {0x07C6, 13}, {0x0001, 2}, {0x0002, 2}, {0x0006, 3}, - {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x003F, 8}, - {0x007D, 9}, {0x07C7, 13}, {0x07C8, 13}, {0x07C9, 13}, - {0x07CA, 13}, {0x07CB, 13}, {0x07CC, 13}, {0x07CD, 13}, - {0x07CE, 13}, {0x07CF, 13}, - },{//7 - {0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, - {0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7}, - {0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7}, - {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7}, - {0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7}, - {0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, - {0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, - {0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, - {0x001E, 7}, {0x001F, 7}, - } +static const uint16_t x8_dc_highquant_table[8][34][2] = { + { // 0 + { 0x0000, 5 }, { 0x0001, 4 }, { 0x0002, 4 }, { 0x0001, 5 }, + { 0x0006, 5 }, { 0x0004, 4 }, { 0x0007, 5 }, { 0x000A, 5 }, + { 0x002C, 7 }, { 0x002D, 7 }, { 0x05C0, 12 }, { 0x05C1, 12 }, + { 0x05C2, 12 }, { 0x05C3, 12 }, { 0x05C4, 12 }, { 0x05C5, 12 }, + { 0x05C6, 12 }, { 0x0003, 3 }, { 0x0002, 2 }, { 0x0006, 3 }, + { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, { 0x002F, 7 }, + { 0x005D, 8 }, { 0x05C7, 12 }, { 0x05C8, 12 }, { 0x05C9, 12 }, + { 0x05CA, 12 }, { 0x05CB, 12 }, { 0x05CC, 12 }, { 0x05CD, 12 }, + { 0x05CE, 12 }, { 0x05CF, 12 }, + }, + { // 1 + { 0x0000, 3 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0006, 4 }, + { 0x0007, 4 }, { 0x0004, 3 }, { 0x000A, 4 }, { 0x000B, 4 }, + { 0x0030, 6 }, { 0x0062, 7 }, { 0x0063, 7 }, { 0x0640, 11 }, + { 0x0641, 11 }, { 0x0642, 11 }, { 0x0643, 11 }, { 0x0644, 11 }, + { 0x0645, 11 }, { 0x0033, 6 }, { 0x000D, 4 }, { 0x001C, 5 }, + { 0x001D, 5 }, { 0x003C, 6 }, { 0x001F, 5 }, { 0x0065, 7 }, + { 0x007A, 7 }, { 0x0646, 11 }, { 0x007B, 7 }, { 0x0647, 11 }, + { 0x0648, 11 }, { 0x0649, 11 }, { 0x064A, 11 }, { 0x064B, 11 }, + { 0x0326, 10 }, { 0x0327, 10 }, + }, + { // 2 + { 0x0000, 7 }, { 0x0001, 7 }, { 0x0001, 6 }, { 0x0004, 7 }, + { 0x0003, 6 }, { 0x0005, 7 }, { 0x0010, 8 }, { 0x0011, 8 }, + { 0x0240, 13 }, { 0x0241, 13 }, { 0x0242, 13 }, { 0x0243, 13 }, + { 0x0244, 13 }, { 0x0245, 13 }, { 0x0246, 13 }, { 0x0247, 13 }, + { 0x0124, 12 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0001, 3 }, + { 0x0003, 5 }, { 0x0005, 6 }, { 0x0013, 8 }, { 0x0125, 12 }, + { 0x0126, 12 }, { 0x0127, 12 }, { 0x0128, 12 }, { 0x0129, 12 }, + { 0x012A, 12 }, { 0x012B, 12 }, { 0x012C, 12 }, { 0x012D, 12 }, + { 0x012E, 12 }, { 0x012F, 12 }, + }, + { // 3 + { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, + { 0x0006, 4 }, { 0x0004, 3 }, { 0x0005, 3 }, { 0x0006, 3 }, + { 0x000E, 5 }, { 0x000F, 5 }, { 0x0070, 7 }, { 0x0710, 11 }, + { 0x0711, 11 }, { 0x0712, 11 }, { 0x0713, 11 }, { 0x0714, 11 }, + { 0x0715, 11 }, { 0x001D, 5 }, { 0x0072, 7 }, { 0x003C, 6 }, + { 0x003D, 6 }, { 0x0073, 7 }, { 0x007C, 7 }, { 0x007D, 7 }, + { 0x007E, 7 }, { 0x0716, 11 }, { 0x0717, 11 }, { 0x0718, 11 }, + { 0x007F, 7 }, { 0x0719, 11 }, { 0x071A, 11 }, { 0x071B, 11 }, + { 0x038E, 10 }, { 0x038F, 10 }, + }, + { // 4 + { 0x0000, 8 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, + { 0x0002, 9 }, { 0x0008, 8 }, { 0x0003, 9 }, { 0x0240, 14 }, + { 0x0241, 14 }, { 0x0242, 14 }, { 0x0243, 14 }, { 0x0244, 14 }, + { 0x0245, 14 }, { 0x0246, 14 }, { 0x0247, 14 }, { 0x0124, 13 }, + { 0x0125, 13 }, { 0x0001, 2 }, { 0x0001, 1 }, { 0x0001, 3 }, + { 0x0001, 4 }, { 0x0003, 6 }, { 0x0005, 7 }, { 0x0013, 9 }, + { 0x0126, 13 }, { 0x0127, 13 }, { 0x0128, 13 }, { 0x0129, 13 }, + { 0x012A, 13 }, { 0x012B, 13 }, { 0x012C, 13 }, { 0x012D, 13 }, + { 0x012E, 13 }, { 0x012F, 13 }, + }, + { // 5 + { 0x0000, 7 }, { 0x0001, 7 }, { 0x0001, 6 }, { 0x0002, 6 }, + { 0x0003, 6 }, { 0x0004, 6 }, { 0x0005, 6 }, { 0x0006, 6 }, + { 0x0007, 6 }, { 0x0008, 6 }, { 0x0009, 6 }, { 0x000A, 6 }, + { 0x000B, 6 }, { 0x000C, 6 }, { 0x000D, 6 }, { 0x000E, 6 }, + { 0x000F, 6 }, { 0x0010, 6 }, { 0x0011, 6 }, { 0x0012, 6 }, + { 0x0013, 6 }, { 0x0014, 6 }, { 0x0015, 6 }, { 0x0016, 6 }, + { 0x0017, 6 }, { 0x0018, 6 }, { 0x0019, 6 }, { 0x0001, 1 }, + { 0x001A, 6 }, { 0x001B, 6 }, { 0x001C, 6 }, { 0x001D, 6 }, + { 0x001E, 6 }, { 0x001F, 6 }, + }, + { // 6 + { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0004, 5 }, + { 0x000A, 6 }, { 0x0006, 5 }, { 0x000B, 6 }, { 0x000E, 6 }, + { 0x003C, 8 }, { 0x003D, 8 }, { 0x07C0, 13 }, { 0x07C1, 13 }, + { 0x07C2, 13 }, { 0x07C3, 13 }, { 0x07C4, 13 }, { 0x07C5, 13 }, + { 0x07C6, 13 }, { 0x0001, 2 }, { 0x0002, 2 }, { 0x0006, 3 }, + { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, { 0x003F, 8 }, + { 0x007D, 9 }, { 0x07C7, 13 }, { 0x07C8, 13 }, { 0x07C9, 13 }, + { 0x07CA, 13 }, { 0x07CB, 13 }, { 0x07CC, 13 }, { 0x07CD, 13 }, + { 0x07CE, 13 }, { 0x07CF, 13 }, + }, + { // 7 + { 0x0000, 7 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, + { 0x0004, 7 }, { 0x0005, 7 }, { 0x0006, 7 }, { 0x0007, 7 }, + { 0x0008, 7 }, { 0x0009, 7 }, { 0x000A, 7 }, { 0x000B, 7 }, + { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, { 0x000F, 7 }, + { 0x0010, 7 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0011, 7 }, + { 0x0012, 7 }, { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, + { 0x0016, 7 }, { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, + { 0x001A, 7 }, { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, + { 0x001E, 7 }, { 0x001F, 7 }, + }, }; #define MAX_DC_VLC_BITS 14 - -static const uint16_t x8_ac0_lowquant_table[8][77][2]={ - {//0 - {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, - {0x001E, 6}, {0x003E, 7}, {0x003F, 7}, {0x0040, 7}, - {0x0104, 9}, {0x0083, 8}, {0x0084, 8}, {0x0085, 8}, - {0x020A, 10}, {0x020B, 10}, {0x0218, 10}, {0x0219, 10}, - {0x0009, 4}, {0x0044, 7}, {0x010D, 9}, {0x021C, 10}, - {0x0023, 6}, {0x0045, 7}, {0x0050, 7}, {0x000B, 4}, - {0x000C, 4}, {0x0015, 5}, {0x001A, 5}, {0x001B, 5}, - {0x0029, 6}, {0x0038, 6}, {0x0039, 6}, {0x003A, 6}, - {0x0051, 7}, {0x0076, 7}, {0x0077, 7}, {0x0078, 7}, - {0x0079, 7}, {0x007A, 7}, {0x007B, 7}, {0x00F8, 8}, - {0x010F, 9}, {0x021D, 10}, {0x3E40, 14}, {0x3E41, 14}, - {0x3E42, 14}, {0x3E43, 14}, {0x03E5, 10}, {0x3E44, 14}, - {0x01F3, 9}, {0x3E45, 14}, {0x3E46, 14}, {0x3E47, 14}, - {0x00FA, 8}, {0x3E48, 14}, {0x3E49, 14}, {0x3E4A, 14}, - {0x3E4B, 14}, {0x03EC, 10}, {0x3E4C, 14}, {0x007E, 7}, - {0x00FE, 8}, {0x00FF, 8}, {0x01F7, 9}, {0x3E4D, 14}, - {0x3E4E, 14}, {0x3E4F, 14}, {0x3ED0, 14}, {0x3ED1, 14}, - {0x3ED2, 14}, {0x3ED3, 14}, {0x3ED4, 14}, {0x3ED5, 14}, - {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, {0x1F6E, 13}, - {0x1F6F, 13}, - },{//1 - {0x0000, 3}, {0x0004, 5}, {0x0014, 7}, {0x000B, 6}, - {0x000C, 6}, {0x002A, 8}, {0x002B, 8}, {0x0034, 8}, - {0x0D40, 14}, {0x0D41, 14}, {0x001B, 7}, {0x0D42, 14}, - {0x0D43, 14}, {0x0D44, 14}, {0x0D45, 14}, {0x0D46, 14}, - {0x000E, 6}, {0x003C, 8}, {0x0D47, 14}, {0x003D, 8}, - {0x0D48, 14}, {0x0D49, 14}, {0x0D4A, 14}, {0x0001, 2}, - {0x0004, 3}, {0x0014, 5}, {0x000B, 4}, {0x000C, 4}, - {0x000D, 4}, {0x002A, 6}, {0x001F, 7}, {0x0056, 7}, - {0x0057, 7}, {0x0070, 7}, {0x00E2, 8}, {0x0072, 7}, - {0x003A, 6}, {0x003B, 6}, {0x003C, 6}, {0x003D, 6}, - {0x00E3, 8}, {0x0D4B, 14}, {0x00E6, 8}, {0x00E7, 8}, - {0x00F8, 8}, {0x0D4C, 14}, {0x0D4D, 14}, {0x0D4E, 14}, - {0x00F9, 8}, {0x0D4F, 14}, {0x0D50, 14}, {0x0D51, 14}, - {0x06A9, 13}, {0x06AA, 13}, {0x06AB, 13}, {0x06AC, 13}, - {0x06AD, 13}, {0x06AE, 13}, {0x06AF, 13}, {0x003F, 6}, - {0x06B0, 13}, {0x06B1, 13}, {0x06B2, 13}, {0x06B3, 13}, - {0x06B4, 13}, {0x007D, 7}, {0x06B5, 13}, {0x06B6, 13}, - {0x06B7, 13}, {0x06B8, 13}, {0x06B9, 13}, {0x06BA, 13}, - {0x06BB, 13}, {0x06BC, 13}, {0x06BD, 13}, {0x06BE, 13}, - {0x06BF, 13}, - },{//2 - {0x0000, 2}, {0x0002, 3}, {0x0003, 3}, {0x0008, 4}, - {0x0012, 5}, {0x0013, 5}, {0x0028, 6}, {0x0029, 6}, - {0x0054, 7}, {0x0055, 7}, {0x0056, 7}, {0x00AE, 8}, - {0x00AF, 8}, {0x00B0, 8}, {0x0162, 9}, {0x02C6, 10}, - {0x000C, 4}, {0x002D, 6}, {0x00B2, 8}, {0x0166, 9}, - {0x002E, 6}, {0x0167, 9}, {0x00BC, 8}, {0x001A, 5}, - {0x0036, 6}, {0x0037, 6}, {0x0038, 6}, {0x005F, 7}, - {0x0072, 7}, {0x0073, 7}, {0x0074, 7}, {0x0075, 7}, - {0x0076, 7}, {0x0077, 7}, {0x0078, 7}, {0x0079, 7}, - {0x007A, 7}, {0x007B, 7}, {0x00BD, 8}, {0xB1C0, 16}, - {0xB1C1, 16}, {0x58E1, 15}, {0x0B1D, 12}, {0x58E2, 15}, - {0x58E3, 15}, {0x58E4, 15}, {0x00F8, 8}, {0x03E4, 10}, - {0x01F3, 9}, {0x0B1E, 12}, {0x58E5, 15}, {0x58E6, 15}, - {0x00FA, 8}, {0x58E7, 15}, {0x58F8, 15}, {0x58F9, 15}, - {0x58FA, 15}, {0x01F6, 9}, {0x58FB, 15}, {0x007E, 7}, - {0x00FE, 8}, {0x00FF, 8}, {0x07CA, 11}, {0x0F96, 12}, - {0x58FC, 15}, {0x58FD, 15}, {0x58FE, 15}, {0x58FF, 15}, - {0x7CB8, 15}, {0x7CB9, 15}, {0x7CBA, 15}, {0x7CBB, 15}, - {0x7CBC, 15}, {0x01F7, 9}, {0x7CBD, 15}, {0x7CBE, 15}, - {0x7CBF, 15}, - },{//3 - {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, - {0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7}, - {0x0045, 7}, {0x008C, 8}, {0x008D, 8}, {0x011C, 9}, - {0x011D, 9}, {0x011E, 9}, {0x023E, 10}, {0x023F, 10}, - {0x0005, 3}, {0x0012, 5}, {0x004C, 7}, {0x004D, 7}, - {0x000C, 4}, {0x004E, 7}, {0x001A, 5}, {0x0036, 6}, - {0x004F, 7}, {0x006E, 7}, {0x006F, 7}, {0x00E0, 8}, - {0x00E1, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8}, - {0x00E5, 8}, {0x01CC, 9}, {0x00E7, 8}, {0x00E8, 8}, - {0x00E9, 8}, {0x01CD, 9}, {0x0750, 11}, {0x03A9, 10}, - {0x0751, 11}, {0x7540, 15}, {0x03AB, 10}, {0x7541, 15}, - {0x7542, 15}, {0x7543, 15}, {0x01D6, 9}, {0x0755, 11}, - {0x0076, 7}, {0x0EA9, 12}, {0x7544, 15}, {0x7545, 15}, - {0x001E, 5}, {0x0077, 7}, {0x00F8, 8}, {0x03AE, 10}, - {0x075E, 11}, {0x007D, 7}, {0x03E4, 10}, {0x00FC, 8}, - {0x00FD, 8}, {0x03E5, 10}, {0x03E6, 10}, {0x0EBE, 12}, - {0x7546, 15}, {0x07CE, 11}, {0x7547, 15}, {0x75F8, 15}, - {0x75F9, 15}, {0x75FA, 15}, {0x75FB, 15}, {0x75FC, 15}, - {0x75FD, 15}, {0x007F, 7}, {0x3AFF, 14}, {0x0F9E, 12}, - {0x0F9F, 12}, - },{//4 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x002A, 7}, - {0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x005D, 8}, - {0x005E, 8}, {0x00BE, 9}, {0x00BF, 9}, {0x0060, 8}, - {0x0007, 4}, {0x000D, 5}, {0x0019, 6}, {0x0020, 6}, - {0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x0014, 5}, - {0x002A, 6}, {0x002B, 6}, {0x002C, 6}, {0x002D, 6}, - {0x002E, 6}, {0x002F, 6}, {0x0030, 6}, {0x0031, 7}, - {0x0062, 7}, {0x0063, 7}, {0x0064, 7}, {0x0065, 7}, - {0x0066, 7}, {0x0061, 8}, {0x0670, 11}, {0x0068, 7}, - {0x0069, 7}, {0x00CF, 8}, {0x019D, 9}, {0x01A8, 9}, - {0x01A9, 9}, {0x0339, 10}, {0x01AA, 9}, {0x0356, 10}, - {0x0036, 6}, {0x00D6, 8}, {0x6710, 15}, {0x6711, 15}, - {0x000E, 4}, {0x006E, 7}, {0x01AE, 9}, {0x6712, 15}, - {0x6713, 15}, {0x003C, 6}, {0x0357, 10}, {0x006F, 7}, - {0x00F4, 8}, {0x00F5, 8}, {0x035E, 10}, {0x01EC, 9}, - {0x6714, 15}, {0x01ED, 9}, {0x035F, 10}, {0x03DC, 10}, - {0x03DD, 10}, {0x6715, 15}, {0x338B, 14}, {0x338C, 14}, - {0x338D, 14}, {0x001F, 5}, {0x01EF, 9}, {0x338E, 14}, - {0x338F, 14}, - },{//5 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, - {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8}, - {0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x036C, 11}, - {0x006E, 8}, {0x01B7, 10}, {0x036D, 11}, {0x3780, 15}, - {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7}, - {0x000A, 4}, {0x002C, 6}, {0x0017, 5}, {0x002D, 6}, - {0x003F, 7}, {0x00C0, 8}, {0x0061, 7}, {0x00C1, 8}, - {0x0062, 7}, {0x00C6, 8}, {0x0064, 7}, {0x00C7, 8}, - {0x00CA, 8}, {0x00DF, 9}, {0x0196, 9}, {0x0197, 9}, - {0x0198, 9}, {0x0199, 9}, {0x0379, 11}, {0x019A, 9}, - {0x01BD, 10}, {0x066C, 11}, {0x3781, 15}, {0x0337, 10}, - {0x066D, 11}, {0x0670, 11}, {0x0339, 10}, {0x0671, 11}, - {0x0034, 6}, {0x00CF, 8}, {0x3782, 15}, {0x3783, 15}, - {0x000E, 4}, {0x001B, 5}, {0x006A, 7}, {0x006B, 7}, - {0x019D, 9}, {0x003C, 6}, {0x00F4, 8}, {0x00F5, 8}, - {0x03D8, 10}, {0x07B2, 11}, {0x3784, 15}, {0x03DA, 10}, - {0x3785, 15}, {0x03DB, 10}, {0x03DC, 10}, {0x3786, 15}, - {0x3787, 15}, {0x1BC4, 14}, {0x1BC5, 14}, {0x1BC6, 14}, - {0x1BC7, 14}, {0x001F, 5}, {0x03DD, 10}, {0x07B3, 11}, - {0x01EF, 9}, - },{//6 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, - {0x0017, 6}, {0x0060, 8}, {0x00C2, 9}, {0x0186, 10}, - {0x0187, 10}, {0x00C4, 9}, {0x3140, 15}, {0x3141, 15}, - {0x018B, 10}, {0x3142, 15}, {0x018C, 10}, {0x3143, 15}, - {0x0007, 4}, {0x000D, 5}, {0x0064, 8}, {0x0065, 8}, - {0x0010, 5}, {0x00C7, 9}, {0x0066, 8}, {0x0005, 3}, - {0x0006, 3}, {0x0009, 4}, {0x0011, 5}, {0x0038, 6}, - {0x0039, 6}, {0x0074, 7}, {0x0075, 7}, {0x0076, 7}, - {0x0067, 8}, {0x00EE, 8}, {0x01DE, 9}, {0x00F0, 8}, - {0x018D, 10}, {0x3144, 15}, {0x01DF, 9}, {0x003D, 6}, - {0x003E, 6}, {0x01E2, 9}, {0x03C6, 10}, {0x00F2, 8}, - {0x00F3, 8}, {0x03C7, 10}, {0x3145, 15}, {0x3146, 15}, - {0x01F8, 9}, {0x3147, 15}, {0x3148, 15}, {0x3149, 15}, - {0x00FD, 8}, {0x314A, 15}, {0x314B, 15}, {0x314C, 15}, - {0x314D, 15}, {0x01F9, 9}, {0x314E, 15}, {0x01FC, 9}, - {0x314F, 15}, {0x3150, 15}, {0x3151, 15}, {0x3152, 15}, - {0x3153, 15}, {0x03FA, 10}, {0x03FB, 10}, {0x3154, 15}, - {0x3155, 15}, {0x3156, 15}, {0x3157, 15}, {0x3158, 15}, - {0x3159, 15}, {0x00FF, 8}, {0x18AD, 14}, {0x18AE, 14}, - {0x18AF, 14}, - },{//7 - {0x0000, 4}, {0x0080, 11}, {0x0081, 11}, {0x0082, 11}, - {0x0083, 11}, {0x0084, 11}, {0x0085, 11}, {0x0086, 11}, - {0x0087, 11}, {0x0088, 11}, {0x0089, 11}, {0x008A, 11}, - {0x008B, 11}, {0x008C, 11}, {0x008D, 11}, {0x008E, 11}, - {0x008F, 11}, {0x0048, 10}, {0x0049, 10}, {0x004A, 10}, - {0x004B, 10}, {0x004C, 10}, {0x004D, 10}, {0x0001, 1}, - {0x0001, 2}, {0x004E, 10}, {0x0002, 4}, {0x0003, 4}, - {0x004F, 10}, {0x0050, 10}, {0x0051, 10}, {0x0052, 10}, - {0x0053, 10}, {0x0054, 10}, {0x0055, 10}, {0x0056, 10}, - {0x0057, 10}, {0x0058, 10}, {0x0059, 10}, {0x005A, 10}, - {0x005B, 10}, {0x005C, 10}, {0x005D, 10}, {0x005E, 10}, - {0x005F, 10}, {0x0060, 10}, {0x0061, 10}, {0x0062, 10}, - {0x0063, 10}, {0x0064, 10}, {0x0065, 10}, {0x0066, 10}, - {0x0067, 10}, {0x0068, 10}, {0x0069, 10}, {0x006A, 10}, - {0x006B, 10}, {0x006C, 10}, {0x006D, 10}, {0x006E, 10}, - {0x006F, 10}, {0x0070, 10}, {0x0071, 10}, {0x0072, 10}, - {0x0073, 10}, {0x0074, 10}, {0x0075, 10}, {0x0076, 10}, - {0x0077, 10}, {0x0078, 10}, {0x0079, 10}, {0x007A, 10}, - {0x007B, 10}, {0x007C, 10}, {0x007D, 10}, {0x007E, 10}, - {0x007F, 10}, - } +static const uint16_t x8_ac0_lowquant_table[8][77][2] = { + { // 0 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, + { 0x001E, 6 }, { 0x003E, 7 }, { 0x003F, 7 }, { 0x0040, 7 }, + { 0x0104, 9 }, { 0x0083, 8 }, { 0x0084, 8 }, { 0x0085, 8 }, + { 0x020A, 10 }, { 0x020B, 10 }, { 0x0218, 10 }, { 0x0219, 10 }, + { 0x0009, 4 }, { 0x0044, 7 }, { 0x010D, 9 }, { 0x021C, 10 }, + { 0x0023, 6 }, { 0x0045, 7 }, { 0x0050, 7 }, { 0x000B, 4 }, + { 0x000C, 4 }, { 0x0015, 5 }, { 0x001A, 5 }, { 0x001B, 5 }, + { 0x0029, 6 }, { 0x0038, 6 }, { 0x0039, 6 }, { 0x003A, 6 }, + { 0x0051, 7 }, { 0x0076, 7 }, { 0x0077, 7 }, { 0x0078, 7 }, + { 0x0079, 7 }, { 0x007A, 7 }, { 0x007B, 7 }, { 0x00F8, 8 }, + { 0x010F, 9 }, { 0x021D, 10 }, { 0x3E40, 14 }, { 0x3E41, 14 }, + { 0x3E42, 14 }, { 0x3E43, 14 }, { 0x03E5, 10 }, { 0x3E44, 14 }, + { 0x01F3, 9 }, { 0x3E45, 14 }, { 0x3E46, 14 }, { 0x3E47, 14 }, + { 0x00FA, 8 }, { 0x3E48, 14 }, { 0x3E49, 14 }, { 0x3E4A, 14 }, + { 0x3E4B, 14 }, { 0x03EC, 10 }, { 0x3E4C, 14 }, { 0x007E, 7 }, + { 0x00FE, 8 }, { 0x00FF, 8 }, { 0x01F7, 9 }, { 0x3E4D, 14 }, + { 0x3E4E, 14 }, { 0x3E4F, 14 }, { 0x3ED0, 14 }, { 0x3ED1, 14 }, + { 0x3ED2, 14 }, { 0x3ED3, 14 }, { 0x3ED4, 14 }, { 0x3ED5, 14 }, + { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 }, { 0x1F6E, 13 }, + { 0x1F6F, 13 }, + }, + { // 1 + { 0x0000, 3 }, { 0x0004, 5 }, { 0x0014, 7 }, { 0x000B, 6 }, + { 0x000C, 6 }, { 0x002A, 8 }, { 0x002B, 8 }, { 0x0034, 8 }, + { 0x0D40, 14 }, { 0x0D41, 14 }, { 0x001B, 7 }, { 0x0D42, 14 }, + { 0x0D43, 14 }, { 0x0D44, 14 }, { 0x0D45, 14 }, { 0x0D46, 14 }, + { 0x000E, 6 }, { 0x003C, 8 }, { 0x0D47, 14 }, { 0x003D, 8 }, + { 0x0D48, 14 }, { 0x0D49, 14 }, { 0x0D4A, 14 }, { 0x0001, 2 }, + { 0x0004, 3 }, { 0x0014, 5 }, { 0x000B, 4 }, { 0x000C, 4 }, + { 0x000D, 4 }, { 0x002A, 6 }, { 0x001F, 7 }, { 0x0056, 7 }, + { 0x0057, 7 }, { 0x0070, 7 }, { 0x00E2, 8 }, { 0x0072, 7 }, + { 0x003A, 6 }, { 0x003B, 6 }, { 0x003C, 6 }, { 0x003D, 6 }, + { 0x00E3, 8 }, { 0x0D4B, 14 }, { 0x00E6, 8 }, { 0x00E7, 8 }, + { 0x00F8, 8 }, { 0x0D4C, 14 }, { 0x0D4D, 14 }, { 0x0D4E, 14 }, + { 0x00F9, 8 }, { 0x0D4F, 14 }, { 0x0D50, 14 }, { 0x0D51, 14 }, + { 0x06A9, 13 }, { 0x06AA, 13 }, { 0x06AB, 13 }, { 0x06AC, 13 }, + { 0x06AD, 13 }, { 0x06AE, 13 }, { 0x06AF, 13 }, { 0x003F, 6 }, + { 0x06B0, 13 }, { 0x06B1, 13 }, { 0x06B2, 13 }, { 0x06B3, 13 }, + { 0x06B4, 13 }, { 0x007D, 7 }, { 0x06B5, 13 }, { 0x06B6, 13 }, + { 0x06B7, 13 }, { 0x06B8, 13 }, { 0x06B9, 13 }, { 0x06BA, 13 }, + { 0x06BB, 13 }, { 0x06BC, 13 }, { 0x06BD, 13 }, { 0x06BE, 13 }, + { 0x06BF, 13 }, + }, + { // 2 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0003, 3 }, { 0x0008, 4 }, + { 0x0012, 5 }, { 0x0013, 5 }, { 0x0028, 6 }, { 0x0029, 6 }, + { 0x0054, 7 }, { 0x0055, 7 }, { 0x0056, 7 }, { 0x00AE, 8 }, + { 0x00AF, 8 }, { 0x00B0, 8 }, { 0x0162, 9 }, { 0x02C6, 10 }, + { 0x000C, 4 }, { 0x002D, 6 }, { 0x00B2, 8 }, { 0x0166, 9 }, + { 0x002E, 6 }, { 0x0167, 9 }, { 0x00BC, 8 }, { 0x001A, 5 }, + { 0x0036, 6 }, { 0x0037, 6 }, { 0x0038, 6 }, { 0x005F, 7 }, + { 0x0072, 7 }, { 0x0073, 7 }, { 0x0074, 7 }, { 0x0075, 7 }, + { 0x0076, 7 }, { 0x0077, 7 }, { 0x0078, 7 }, { 0x0079, 7 }, + { 0x007A, 7 }, { 0x007B, 7 }, { 0x00BD, 8 }, { 0xB1C0, 16 }, + { 0xB1C1, 16 }, { 0x58E1, 15 }, { 0x0B1D, 12 }, { 0x58E2, 15 }, + { 0x58E3, 15 }, { 0x58E4, 15 }, { 0x00F8, 8 }, { 0x03E4, 10 }, + { 0x01F3, 9 }, { 0x0B1E, 12 }, { 0x58E5, 15 }, { 0x58E6, 15 }, + { 0x00FA, 8 }, { 0x58E7, 15 }, { 0x58F8, 15 }, { 0x58F9, 15 }, + { 0x58FA, 15 }, { 0x01F6, 9 }, { 0x58FB, 15 }, { 0x007E, 7 }, + { 0x00FE, 8 }, { 0x00FF, 8 }, { 0x07CA, 11 }, { 0x0F96, 12 }, + { 0x58FC, 15 }, { 0x58FD, 15 }, { 0x58FE, 15 }, { 0x58FF, 15 }, + { 0x7CB8, 15 }, { 0x7CB9, 15 }, { 0x7CBA, 15 }, { 0x7CBB, 15 }, + { 0x7CBC, 15 }, { 0x01F7, 9 }, { 0x7CBD, 15 }, { 0x7CBE, 15 }, + { 0x7CBF, 15 }, + }, + { // 3 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, + { 0x000F, 5 }, { 0x0020, 6 }, { 0x0021, 6 }, { 0x0044, 7 }, + { 0x0045, 7 }, { 0x008C, 8 }, { 0x008D, 8 }, { 0x011C, 9 }, + { 0x011D, 9 }, { 0x011E, 9 }, { 0x023E, 10 }, { 0x023F, 10 }, + { 0x0005, 3 }, { 0x0012, 5 }, { 0x004C, 7 }, { 0x004D, 7 }, + { 0x000C, 4 }, { 0x004E, 7 }, { 0x001A, 5 }, { 0x0036, 6 }, + { 0x004F, 7 }, { 0x006E, 7 }, { 0x006F, 7 }, { 0x00E0, 8 }, + { 0x00E1, 8 }, { 0x00E2, 8 }, { 0x00E3, 8 }, { 0x00E4, 8 }, + { 0x00E5, 8 }, { 0x01CC, 9 }, { 0x00E7, 8 }, { 0x00E8, 8 }, + { 0x00E9, 8 }, { 0x01CD, 9 }, { 0x0750, 11 }, { 0x03A9, 10 }, + { 0x0751, 11 }, { 0x7540, 15 }, { 0x03AB, 10 }, { 0x7541, 15 }, + { 0x7542, 15 }, { 0x7543, 15 }, { 0x01D6, 9 }, { 0x0755, 11 }, + { 0x0076, 7 }, { 0x0EA9, 12 }, { 0x7544, 15 }, { 0x7545, 15 }, + { 0x001E, 5 }, { 0x0077, 7 }, { 0x00F8, 8 }, { 0x03AE, 10 }, + { 0x075E, 11 }, { 0x007D, 7 }, { 0x03E4, 10 }, { 0x00FC, 8 }, + { 0x00FD, 8 }, { 0x03E5, 10 }, { 0x03E6, 10 }, { 0x0EBE, 12 }, + { 0x7546, 15 }, { 0x07CE, 11 }, { 0x7547, 15 }, { 0x75F8, 15 }, + { 0x75F9, 15 }, { 0x75FA, 15 }, { 0x75FB, 15 }, { 0x75FC, 15 }, + { 0x75FD, 15 }, { 0x007F, 7 }, { 0x3AFF, 14 }, { 0x0F9E, 12 }, + { 0x0F9F, 12 }, + }, + { // 4 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0012, 6 }, { 0x0013, 6 }, { 0x0014, 6 }, { 0x002A, 7 }, + { 0x0016, 6 }, { 0x002B, 7 }, { 0x005C, 8 }, { 0x005D, 8 }, + { 0x005E, 8 }, { 0x00BE, 9 }, { 0x00BF, 9 }, { 0x0060, 8 }, + { 0x0007, 4 }, { 0x000D, 5 }, { 0x0019, 6 }, { 0x0020, 6 }, + { 0x0009, 4 }, { 0x0021, 6 }, { 0x0011, 5 }, { 0x0014, 5 }, + { 0x002A, 6 }, { 0x002B, 6 }, { 0x002C, 6 }, { 0x002D, 6 }, + { 0x002E, 6 }, { 0x002F, 6 }, { 0x0030, 6 }, { 0x0031, 7 }, + { 0x0062, 7 }, { 0x0063, 7 }, { 0x0064, 7 }, { 0x0065, 7 }, + { 0x0066, 7 }, { 0x0061, 8 }, { 0x0670, 11 }, { 0x0068, 7 }, + { 0x0069, 7 }, { 0x00CF, 8 }, { 0x019D, 9 }, { 0x01A8, 9 }, + { 0x01A9, 9 }, { 0x0339, 10 }, { 0x01AA, 9 }, { 0x0356, 10 }, + { 0x0036, 6 }, { 0x00D6, 8 }, { 0x6710, 15 }, { 0x6711, 15 }, + { 0x000E, 4 }, { 0x006E, 7 }, { 0x01AE, 9 }, { 0x6712, 15 }, + { 0x6713, 15 }, { 0x003C, 6 }, { 0x0357, 10 }, { 0x006F, 7 }, + { 0x00F4, 8 }, { 0x00F5, 8 }, { 0x035E, 10 }, { 0x01EC, 9 }, + { 0x6714, 15 }, { 0x01ED, 9 }, { 0x035F, 10 }, { 0x03DC, 10 }, + { 0x03DD, 10 }, { 0x6715, 15 }, { 0x338B, 14 }, { 0x338C, 14 }, + { 0x338D, 14 }, { 0x001F, 5 }, { 0x01EF, 9 }, { 0x338E, 14 }, + { 0x338F, 14 }, + }, + { // 5 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, + { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x006A, 8 }, + { 0x006B, 8 }, { 0x006C, 8 }, { 0x00DA, 9 }, { 0x036C, 11 }, + { 0x006E, 8 }, { 0x01B7, 10 }, { 0x036D, 11 }, { 0x3780, 15 }, + { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x003E, 7 }, + { 0x000A, 4 }, { 0x002C, 6 }, { 0x0017, 5 }, { 0x002D, 6 }, + { 0x003F, 7 }, { 0x00C0, 8 }, { 0x0061, 7 }, { 0x00C1, 8 }, + { 0x0062, 7 }, { 0x00C6, 8 }, { 0x0064, 7 }, { 0x00C7, 8 }, + { 0x00CA, 8 }, { 0x00DF, 9 }, { 0x0196, 9 }, { 0x0197, 9 }, + { 0x0198, 9 }, { 0x0199, 9 }, { 0x0379, 11 }, { 0x019A, 9 }, + { 0x01BD, 10 }, { 0x066C, 11 }, { 0x3781, 15 }, { 0x0337, 10 }, + { 0x066D, 11 }, { 0x0670, 11 }, { 0x0339, 10 }, { 0x0671, 11 }, + { 0x0034, 6 }, { 0x00CF, 8 }, { 0x3782, 15 }, { 0x3783, 15 }, + { 0x000E, 4 }, { 0x001B, 5 }, { 0x006A, 7 }, { 0x006B, 7 }, + { 0x019D, 9 }, { 0x003C, 6 }, { 0x00F4, 8 }, { 0x00F5, 8 }, + { 0x03D8, 10 }, { 0x07B2, 11 }, { 0x3784, 15 }, { 0x03DA, 10 }, + { 0x3785, 15 }, { 0x03DB, 10 }, { 0x03DC, 10 }, { 0x3786, 15 }, + { 0x3787, 15 }, { 0x1BC4, 14 }, { 0x1BC5, 14 }, { 0x1BC6, 14 }, + { 0x1BC7, 14 }, { 0x001F, 5 }, { 0x03DD, 10 }, { 0x07B3, 11 }, + { 0x01EF, 9 }, + }, + { // 6 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, + { 0x0017, 6 }, { 0x0060, 8 }, { 0x00C2, 9 }, { 0x0186, 10 }, + { 0x0187, 10 }, { 0x00C4, 9 }, { 0x3140, 15 }, { 0x3141, 15 }, + { 0x018B, 10 }, { 0x3142, 15 }, { 0x018C, 10 }, { 0x3143, 15 }, + { 0x0007, 4 }, { 0x000D, 5 }, { 0x0064, 8 }, { 0x0065, 8 }, + { 0x0010, 5 }, { 0x00C7, 9 }, { 0x0066, 8 }, { 0x0005, 3 }, + { 0x0006, 3 }, { 0x0009, 4 }, { 0x0011, 5 }, { 0x0038, 6 }, + { 0x0039, 6 }, { 0x0074, 7 }, { 0x0075, 7 }, { 0x0076, 7 }, + { 0x0067, 8 }, { 0x00EE, 8 }, { 0x01DE, 9 }, { 0x00F0, 8 }, + { 0x018D, 10 }, { 0x3144, 15 }, { 0x01DF, 9 }, { 0x003D, 6 }, + { 0x003E, 6 }, { 0x01E2, 9 }, { 0x03C6, 10 }, { 0x00F2, 8 }, + { 0x00F3, 8 }, { 0x03C7, 10 }, { 0x3145, 15 }, { 0x3146, 15 }, + { 0x01F8, 9 }, { 0x3147, 15 }, { 0x3148, 15 }, { 0x3149, 15 }, + { 0x00FD, 8 }, { 0x314A, 15 }, { 0x314B, 15 }, { 0x314C, 15 }, + { 0x314D, 15 }, { 0x01F9, 9 }, { 0x314E, 15 }, { 0x01FC, 9 }, + { 0x314F, 15 }, { 0x3150, 15 }, { 0x3151, 15 }, { 0x3152, 15 }, + { 0x3153, 15 }, { 0x03FA, 10 }, { 0x03FB, 10 }, { 0x3154, 15 }, + { 0x3155, 15 }, { 0x3156, 15 }, { 0x3157, 15 }, { 0x3158, 15 }, + { 0x3159, 15 }, { 0x00FF, 8 }, { 0x18AD, 14 }, { 0x18AE, 14 }, + { 0x18AF, 14 }, + }, + { // 7 + { 0x0000, 4 }, { 0x0080, 11 }, { 0x0081, 11 }, { 0x0082, 11 }, + { 0x0083, 11 }, { 0x0084, 11 }, { 0x0085, 11 }, { 0x0086, 11 }, + { 0x0087, 11 }, { 0x0088, 11 }, { 0x0089, 11 }, { 0x008A, 11 }, + { 0x008B, 11 }, { 0x008C, 11 }, { 0x008D, 11 }, { 0x008E, 11 }, + { 0x008F, 11 }, { 0x0048, 10 }, { 0x0049, 10 }, { 0x004A, 10 }, + { 0x004B, 10 }, { 0x004C, 10 }, { 0x004D, 10 }, { 0x0001, 1 }, + { 0x0001, 2 }, { 0x004E, 10 }, { 0x0002, 4 }, { 0x0003, 4 }, + { 0x004F, 10 }, { 0x0050, 10 }, { 0x0051, 10 }, { 0x0052, 10 }, + { 0x0053, 10 }, { 0x0054, 10 }, { 0x0055, 10 }, { 0x0056, 10 }, + { 0x0057, 10 }, { 0x0058, 10 }, { 0x0059, 10 }, { 0x005A, 10 }, + { 0x005B, 10 }, { 0x005C, 10 }, { 0x005D, 10 }, { 0x005E, 10 }, + { 0x005F, 10 }, { 0x0060, 10 }, { 0x0061, 10 }, { 0x0062, 10 }, + { 0x0063, 10 }, { 0x0064, 10 }, { 0x0065, 10 }, { 0x0066, 10 }, + { 0x0067, 10 }, { 0x0068, 10 }, { 0x0069, 10 }, { 0x006A, 10 }, + { 0x006B, 10 }, { 0x006C, 10 }, { 0x006D, 10 }, { 0x006E, 10 }, + { 0x006F, 10 }, { 0x0070, 10 }, { 0x0071, 10 }, { 0x0072, 10 }, + { 0x0073, 10 }, { 0x0074, 10 }, { 0x0075, 10 }, { 0x0076, 10 }, + { 0x0077, 10 }, { 0x0078, 10 }, { 0x0079, 10 }, { 0x007A, 10 }, + { 0x007B, 10 }, { 0x007C, 10 }, { 0x007D, 10 }, { 0x007E, 10 }, + { 0x007F, 10 }, + }, }; -static const uint16_t x8_ac0_highquant_table[8][77][2]={ - {//0 - {0x0000, 3}, {0x0002, 4}, {0x000C, 6}, {0x000D, 6}, - {0x001C, 7}, {0x000F, 6}, {0x1D00, 15}, {0x003B, 8}, - {0x1D01, 15}, {0x0075, 9}, {0x1D02, 15}, {0x0080, 9}, - {0x1D03, 15}, {0x1D04, 15}, {0x1D05, 15}, {0x0E83, 14}, - {0x0009, 5}, {0x0011, 6}, {0x0081, 9}, {0x0082, 9}, - {0x0021, 7}, {0x0028, 7}, {0x0083, 9}, {0x0002, 2}, - {0x0003, 3}, {0x000C, 4}, {0x000D, 4}, {0x000B, 5}, - {0x0015, 6}, {0x0052, 8}, {0x0070, 7}, {0x0039, 6}, - {0x0071, 7}, {0x0053, 8}, {0x0E84, 14}, {0x0074, 7}, - {0x0075, 7}, {0x0076, 7}, {0x01DC, 9}, {0x001E, 5}, - {0x003E, 6}, {0x01DD, 9}, {0x00EF, 8}, {0x01F8, 9}, - {0x01F9, 9}, {0x0E85, 14}, {0x0E86, 14}, {0x0E87, 14}, - {0x00FD, 8}, {0x0E88, 14}, {0x0E89, 14}, {0x0E8A, 14}, - {0x0E8B, 14}, {0x0E8C, 14}, {0x0E8D, 14}, {0x0E8E, 14}, - {0x0E8F, 14}, {0x0E90, 14}, {0x0E91, 14}, {0x01FC, 9}, - {0x0E92, 14}, {0x0E93, 14}, {0x0E94, 14}, {0x0E95, 14}, - {0x0E96, 14}, {0x0E97, 14}, {0x01FD, 9}, {0x0E98, 14}, - {0x01FE, 9}, {0x0E99, 14}, {0x0E9A, 14}, {0x0E9B, 14}, - {0x0E9C, 14}, {0x01FF, 9}, {0x0E9D, 14}, {0x0E9E, 14}, - {0x0E9F, 14}, - },{//1 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x0015, 6}, - {0x002C, 7}, {0x005A, 8}, {0x005B, 8}, {0x005C, 8}, - {0x005D, 8}, {0x1780, 14}, {0x0179, 10}, {0x017A, 10}, - {0x0006, 4}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7}, - {0x0010, 5}, {0x0022, 6}, {0x0012, 5}, {0x000A, 4}, - {0x0013, 5}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6}, - {0x002F, 6}, {0x0030, 6}, {0x0031, 6}, {0x003F, 7}, - {0x005F, 8}, {0x00C8, 8}, {0x0065, 7}, {0x0066, 7}, - {0x0067, 7}, {0x0068, 7}, {0x00C9, 8}, {0x0069, 7}, - {0x006A, 7}, {0x00D6, 8}, {0x00D7, 8}, {0x00D8, 8}, - {0x1781, 14}, {0x017B, 10}, {0x01B2, 9}, {0x1782, 14}, - {0x001C, 5}, {0x01B3, 9}, {0x1783, 14}, {0x1784, 14}, - {0x001D, 5}, {0x00DA, 8}, {0x1785, 14}, {0x1786, 14}, - {0x1787, 14}, {0x0037, 6}, {0x00DB, 8}, {0x0078, 7}, - {0x00F2, 8}, {0x01E6, 9}, {0x00F4, 8}, {0x1788, 14}, - {0x1789, 14}, {0x00F5, 8}, {0x01E7, 9}, {0x178A, 14}, - {0x178B, 14}, {0x178C, 14}, {0x178D, 14}, {0x01EC, 9}, - {0x178E, 14}, {0x001F, 5}, {0x00F7, 8}, {0x01ED, 9}, - {0x178F, 14}, - },{//2 - {0x0000, 4}, {0x0002, 5}, {0x0180, 12}, {0x0181, 12}, - {0x0182, 12}, {0x0183, 12}, {0x0184, 12}, {0x0185, 12}, - {0x0186, 12}, {0x0187, 12}, {0x0188, 12}, {0x0189, 12}, - {0x00C5, 11}, {0x00C6, 11}, {0x00C7, 11}, {0x00C8, 11}, - {0x00C9, 11}, {0x00CA, 11}, {0x00CB, 11}, {0x00CC, 11}, - {0x00CD, 11}, {0x00CE, 11}, {0x00CF, 11}, {0x0001, 1}, - {0x0001, 2}, {0x0004, 5}, {0x0005, 5}, {0x0006, 5}, - {0x00D0, 11}, {0x00D1, 11}, {0x00D2, 11}, {0x00D3, 11}, - {0x00D4, 11}, {0x00D5, 11}, {0x00D6, 11}, {0x00D7, 11}, - {0x00D8, 11}, {0x00D9, 11}, {0x00DA, 11}, {0x0007, 5}, - {0x00DB, 11}, {0x00DC, 11}, {0x00DD, 11}, {0x00DE, 11}, - {0x00DF, 11}, {0x00E0, 11}, {0x00E1, 11}, {0x00E2, 11}, - {0x00E3, 11}, {0x00E4, 11}, {0x00E5, 11}, {0x00E6, 11}, - {0x00E7, 11}, {0x00E8, 11}, {0x00E9, 11}, {0x00EA, 11}, - {0x00EB, 11}, {0x00EC, 11}, {0x00ED, 11}, {0x00EE, 11}, - {0x00EF, 11}, {0x00F0, 11}, {0x00F1, 11}, {0x00F2, 11}, - {0x00F3, 11}, {0x00F4, 11}, {0x00F5, 11}, {0x00F6, 11}, - {0x00F7, 11}, {0x00F8, 11}, {0x00F9, 11}, {0x00FA, 11}, - {0x00FB, 11}, {0x00FC, 11}, {0x00FD, 11}, {0x00FE, 11}, - {0x00FF, 11}, - },{//3 - {0x0000, 8}, {0x0001, 8}, {0x0002, 8}, {0x0003, 8}, - {0x0004, 8}, {0x0005, 8}, {0x0006, 8}, {0x0007, 8}, - {0x0008, 8}, {0x0009, 8}, {0x000A, 8}, {0x000B, 8}, - {0x000C, 8}, {0x000D, 8}, {0x000E, 8}, {0x000F, 8}, - {0x0010, 8}, {0x0011, 8}, {0x0012, 8}, {0x0013, 8}, - {0x0014, 8}, {0x0015, 8}, {0x0016, 8}, {0x0001, 1}, - {0x0017, 8}, {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, - {0x000F, 7}, {0x0010, 7}, {0x0011, 7}, {0x0012, 7}, - {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, {0x0016, 7}, - {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, {0x001A, 7}, - {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, {0x001E, 7}, - {0x001F, 7}, {0x0020, 7}, {0x0021, 7}, {0x0022, 7}, - {0x0023, 7}, {0x0024, 7}, {0x0025, 7}, {0x0026, 7}, - {0x0027, 7}, {0x0028, 7}, {0x0029, 7}, {0x002A, 7}, - {0x002B, 7}, {0x002C, 7}, {0x002D, 7}, {0x002E, 7}, - {0x002F, 7}, {0x0030, 7}, {0x0031, 7}, {0x0032, 7}, - {0x0033, 7}, {0x0034, 7}, {0x0035, 7}, {0x0036, 7}, - {0x0037, 7}, {0x0038, 7}, {0x0039, 7}, {0x003A, 7}, - {0x003B, 7}, {0x003C, 7}, {0x003D, 7}, {0x003E, 7}, - {0x003F, 7}, - },{//4 - {0x0000, 9}, {0x0001, 9}, {0x0002, 9}, {0x0003, 9}, - {0x0004, 9}, {0x0005, 9}, {0x0006, 9}, {0x0007, 9}, - {0x0008, 9}, {0x0009, 9}, {0x000A, 9}, {0x000B, 9}, - {0x000C, 9}, {0x000D, 9}, {0x000E, 9}, {0x000F, 9}, - {0x0010, 9}, {0x0011, 9}, {0x0012, 9}, {0x0013, 9}, - {0x0014, 9}, {0x0015, 9}, {0x000B, 8}, {0x0001, 2}, - {0x0001, 1}, {0x000C, 8}, {0x000D, 8}, {0x000E, 8}, - {0x000F, 8}, {0x0010, 8}, {0x0011, 8}, {0x0012, 8}, - {0x0013, 8}, {0x0014, 8}, {0x0015, 8}, {0x0016, 8}, - {0x0017, 8}, {0x0018, 8}, {0x0019, 8}, {0x001A, 8}, - {0x001B, 8}, {0x001C, 8}, {0x001D, 8}, {0x001E, 8}, - {0x001F, 8}, {0x0020, 8}, {0x0021, 8}, {0x0022, 8}, - {0x0023, 8}, {0x0024, 8}, {0x0025, 8}, {0x0026, 8}, - {0x0027, 8}, {0x0028, 8}, {0x0029, 8}, {0x002A, 8}, - {0x002B, 8}, {0x002C, 8}, {0x002D, 8}, {0x002E, 8}, - {0x002F, 8}, {0x0030, 8}, {0x0031, 8}, {0x0032, 8}, - {0x0033, 8}, {0x0034, 8}, {0x0035, 8}, {0x0036, 8}, - {0x0037, 8}, {0x0038, 8}, {0x0039, 8}, {0x003A, 8}, - {0x003B, 8}, {0x003C, 8}, {0x003D, 8}, {0x003E, 8}, - {0x003F, 8}, - },{//5 - {0x0000, 10}, {0x0001, 10}, {0x0002, 10}, {0x0003, 10}, - {0x0004, 10}, {0x0005, 10}, {0x0006, 10}, {0x0007, 10}, - {0x0008, 10}, {0x0009, 10}, {0x000A, 10}, {0x000B, 10}, - {0x000C, 10}, {0x000D, 10}, {0x000E, 10}, {0x000F, 10}, - {0x0010, 10}, {0x0011, 10}, {0x0012, 10}, {0x0013, 10}, - {0x000A, 9}, {0x000B, 9}, {0x000C, 9}, {0x0001, 1}, - {0x0001, 3}, {0x000D, 9}, {0x000E, 9}, {0x0001, 2}, - {0x000F, 9}, {0x0010, 9}, {0x0011, 9}, {0x0012, 9}, - {0x0013, 9}, {0x0014, 9}, {0x0015, 9}, {0x0016, 9}, - {0x0017, 9}, {0x0018, 9}, {0x0019, 9}, {0x001A, 9}, - {0x001B, 9}, {0x001C, 9}, {0x001D, 9}, {0x001E, 9}, - {0x001F, 9}, {0x0020, 9}, {0x0021, 9}, {0x0022, 9}, - {0x0023, 9}, {0x0024, 9}, {0x0025, 9}, {0x0026, 9}, - {0x0027, 9}, {0x0028, 9}, {0x0029, 9}, {0x002A, 9}, - {0x002B, 9}, {0x002C, 9}, {0x002D, 9}, {0x002E, 9}, - {0x002F, 9}, {0x0030, 9}, {0x0031, 9}, {0x0032, 9}, - {0x0033, 9}, {0x0034, 9}, {0x0035, 9}, {0x0036, 9}, - {0x0037, 9}, {0x0038, 9}, {0x0039, 9}, {0x003A, 9}, - {0x003B, 9}, {0x003C, 9}, {0x003D, 9}, {0x003E, 9}, - {0x003F, 9}, - },{//6 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, - {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8}, - {0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x00DB, 9}, - {0x01B8, 10}, {0x00DD, 9}, {0x01B9, 10}, {0x3780, 15}, - {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x001F, 6}, - {0x000A, 4}, {0x0058, 7}, {0x0017, 5}, {0x0018, 5}, - {0x0059, 7}, {0x005A, 7}, {0x005B, 7}, {0x00C8, 8}, - {0x0065, 7}, {0x0066, 7}, {0x00C9, 8}, {0x00CE, 8}, - {0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8}, - {0x00D3, 8}, {0x00DF, 9}, {0x00D4, 8}, {0x00D5, 8}, - {0x00D6, 8}, {0x01AE, 9}, {0x3781, 15}, {0x01BD, 10}, - {0x035E, 10}, {0x035F, 10}, {0x3782, 15}, {0x0360, 10}, - {0x0037, 6}, {0x01B1, 9}, {0x3783, 15}, {0x3784, 15}, - {0x000E, 4}, {0x003C, 6}, {0x0361, 10}, {0x3785, 15}, - {0x1BC3, 14}, {0x003D, 6}, {0x00D9, 8}, {0x1BC4, 14}, - {0x0368, 10}, {0x1BC5, 14}, {0x1BC6, 14}, {0x1BC7, 14}, - {0x1BC8, 14}, {0x00DB, 8}, {0x0369, 10}, {0x036A, 10}, - {0x1BC9, 14}, {0x1BCA, 14}, {0x1BCB, 14}, {0x1BCC, 14}, - {0x1BCD, 14}, {0x001F, 5}, {0x036B, 10}, {0x1BCE, 14}, - {0x1BCF, 14}, - },{//7 - {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, - {0x0010, 6}, {0x0044, 8}, {0x0023, 7}, {0x0012, 6}, - {0x0026, 7}, {0x08A0, 13}, {0x004E, 8}, {0x004F, 8}, - {0x08A1, 13}, {0x08A2, 13}, {0x08A3, 13}, {0x0050, 8}, - {0x0006, 4}, {0x000B, 5}, {0x0029, 7}, {0x0015, 6}, - {0x001C, 6}, {0x003A, 7}, {0x001E, 6}, {0x0004, 3}, - {0x0014, 5}, {0x0015, 5}, {0x000B, 4}, {0x001F, 6}, - {0x0030, 6}, {0x0031, 6}, {0x0019, 5}, {0x0051, 8}, - {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, {0x0037, 6}, - {0x0076, 8}, {0x0077, 8}, {0x0070, 7}, {0x001D, 5}, - {0x0071, 7}, {0x0072, 7}, {0x08A4, 13}, {0x0073, 7}, - {0x00F0, 8}, {0x08A5, 13}, {0x08A6, 13}, {0x08A7, 13}, - {0x0079, 7}, {0x007A, 7}, {0x08A8, 13}, {0x08A9, 13}, - {0x00F1, 8}, {0x08AA, 13}, {0x08AB, 13}, {0x08AC, 13}, - {0x08AD, 13}, {0x00F6, 8}, {0x08AE, 13}, {0x007C, 7}, - {0x00F7, 8}, {0x08AF, 13}, {0x08B0, 13}, {0x08B1, 13}, - {0x08B2, 13}, {0x00FA, 8}, {0x08B3, 13}, {0x08B4, 13}, - {0x08B5, 13}, {0x08B6, 13}, {0x08B7, 13}, {0x00FB, 8}, - {0x045C, 12}, {0x003F, 6}, {0x045D, 12}, {0x045E, 12}, - {0x045F, 12}, - } +static const uint16_t x8_ac0_highquant_table[8][77][2] = { + { // 0 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x000C, 6 }, { 0x000D, 6 }, + { 0x001C, 7 }, { 0x000F, 6 }, { 0x1D00, 15 }, { 0x003B, 8 }, + { 0x1D01, 15 }, { 0x0075, 9 }, { 0x1D02, 15 }, { 0x0080, 9 }, + { 0x1D03, 15 }, { 0x1D04, 15 }, { 0x1D05, 15 }, { 0x0E83, 14 }, + { 0x0009, 5 }, { 0x0011, 6 }, { 0x0081, 9 }, { 0x0082, 9 }, + { 0x0021, 7 }, { 0x0028, 7 }, { 0x0083, 9 }, { 0x0002, 2 }, + { 0x0003, 3 }, { 0x000C, 4 }, { 0x000D, 4 }, { 0x000B, 5 }, + { 0x0015, 6 }, { 0x0052, 8 }, { 0x0070, 7 }, { 0x0039, 6 }, + { 0x0071, 7 }, { 0x0053, 8 }, { 0x0E84, 14 }, { 0x0074, 7 }, + { 0x0075, 7 }, { 0x0076, 7 }, { 0x01DC, 9 }, { 0x001E, 5 }, + { 0x003E, 6 }, { 0x01DD, 9 }, { 0x00EF, 8 }, { 0x01F8, 9 }, + { 0x01F9, 9 }, { 0x0E85, 14 }, { 0x0E86, 14 }, { 0x0E87, 14 }, + { 0x00FD, 8 }, { 0x0E88, 14 }, { 0x0E89, 14 }, { 0x0E8A, 14 }, + { 0x0E8B, 14 }, { 0x0E8C, 14 }, { 0x0E8D, 14 }, { 0x0E8E, 14 }, + { 0x0E8F, 14 }, { 0x0E90, 14 }, { 0x0E91, 14 }, { 0x01FC, 9 }, + { 0x0E92, 14 }, { 0x0E93, 14 }, { 0x0E94, 14 }, { 0x0E95, 14 }, + { 0x0E96, 14 }, { 0x0E97, 14 }, { 0x01FD, 9 }, { 0x0E98, 14 }, + { 0x01FE, 9 }, { 0x0E99, 14 }, { 0x0E9A, 14 }, { 0x0E9B, 14 }, + { 0x0E9C, 14 }, { 0x01FF, 9 }, { 0x0E9D, 14 }, { 0x0E9E, 14 }, + { 0x0E9F, 14 }, + }, + { // 1 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0012, 6 }, { 0x0013, 6 }, { 0x0014, 6 }, { 0x0015, 6 }, + { 0x002C, 7 }, { 0x005A, 8 }, { 0x005B, 8 }, { 0x005C, 8 }, + { 0x005D, 8 }, { 0x1780, 14 }, { 0x0179, 10 }, { 0x017A, 10 }, + { 0x0006, 4 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x003E, 7 }, + { 0x0010, 5 }, { 0x0022, 6 }, { 0x0012, 5 }, { 0x000A, 4 }, + { 0x0013, 5 }, { 0x0016, 5 }, { 0x0023, 6 }, { 0x002E, 6 }, + { 0x002F, 6 }, { 0x0030, 6 }, { 0x0031, 6 }, { 0x003F, 7 }, + { 0x005F, 8 }, { 0x00C8, 8 }, { 0x0065, 7 }, { 0x0066, 7 }, + { 0x0067, 7 }, { 0x0068, 7 }, { 0x00C9, 8 }, { 0x0069, 7 }, + { 0x006A, 7 }, { 0x00D6, 8 }, { 0x00D7, 8 }, { 0x00D8, 8 }, + { 0x1781, 14 }, { 0x017B, 10 }, { 0x01B2, 9 }, { 0x1782, 14 }, + { 0x001C, 5 }, { 0x01B3, 9 }, { 0x1783, 14 }, { 0x1784, 14 }, + { 0x001D, 5 }, { 0x00DA, 8 }, { 0x1785, 14 }, { 0x1786, 14 }, + { 0x1787, 14 }, { 0x0037, 6 }, { 0x00DB, 8 }, { 0x0078, 7 }, + { 0x00F2, 8 }, { 0x01E6, 9 }, { 0x00F4, 8 }, { 0x1788, 14 }, + { 0x1789, 14 }, { 0x00F5, 8 }, { 0x01E7, 9 }, { 0x178A, 14 }, + { 0x178B, 14 }, { 0x178C, 14 }, { 0x178D, 14 }, { 0x01EC, 9 }, + { 0x178E, 14 }, { 0x001F, 5 }, { 0x00F7, 8 }, { 0x01ED, 9 }, + { 0x178F, 14 }, + }, + { // 2 + { 0x0000, 4 }, { 0x0002, 5 }, { 0x0180, 12 }, { 0x0181, 12 }, + { 0x0182, 12 }, { 0x0183, 12 }, { 0x0184, 12 }, { 0x0185, 12 }, + { 0x0186, 12 }, { 0x0187, 12 }, { 0x0188, 12 }, { 0x0189, 12 }, + { 0x00C5, 11 }, { 0x00C6, 11 }, { 0x00C7, 11 }, { 0x00C8, 11 }, + { 0x00C9, 11 }, { 0x00CA, 11 }, { 0x00CB, 11 }, { 0x00CC, 11 }, + { 0x00CD, 11 }, { 0x00CE, 11 }, { 0x00CF, 11 }, { 0x0001, 1 }, + { 0x0001, 2 }, { 0x0004, 5 }, { 0x0005, 5 }, { 0x0006, 5 }, + { 0x00D0, 11 }, { 0x00D1, 11 }, { 0x00D2, 11 }, { 0x00D3, 11 }, + { 0x00D4, 11 }, { 0x00D5, 11 }, { 0x00D6, 11 }, { 0x00D7, 11 }, + { 0x00D8, 11 }, { 0x00D9, 11 }, { 0x00DA, 11 }, { 0x0007, 5 }, + { 0x00DB, 11 }, { 0x00DC, 11 }, { 0x00DD, 11 }, { 0x00DE, 11 }, + { 0x00DF, 11 }, { 0x00E0, 11 }, { 0x00E1, 11 }, { 0x00E2, 11 }, + { 0x00E3, 11 }, { 0x00E4, 11 }, { 0x00E5, 11 }, { 0x00E6, 11 }, + { 0x00E7, 11 }, { 0x00E8, 11 }, { 0x00E9, 11 }, { 0x00EA, 11 }, + { 0x00EB, 11 }, { 0x00EC, 11 }, { 0x00ED, 11 }, { 0x00EE, 11 }, + { 0x00EF, 11 }, { 0x00F0, 11 }, { 0x00F1, 11 }, { 0x00F2, 11 }, + { 0x00F3, 11 }, { 0x00F4, 11 }, { 0x00F5, 11 }, { 0x00F6, 11 }, + { 0x00F7, 11 }, { 0x00F8, 11 }, { 0x00F9, 11 }, { 0x00FA, 11 }, + { 0x00FB, 11 }, { 0x00FC, 11 }, { 0x00FD, 11 }, { 0x00FE, 11 }, + { 0x00FF, 11 }, + }, + { // 3 + { 0x0000, 8 }, { 0x0001, 8 }, { 0x0002, 8 }, { 0x0003, 8 }, + { 0x0004, 8 }, { 0x0005, 8 }, { 0x0006, 8 }, { 0x0007, 8 }, + { 0x0008, 8 }, { 0x0009, 8 }, { 0x000A, 8 }, { 0x000B, 8 }, + { 0x000C, 8 }, { 0x000D, 8 }, { 0x000E, 8 }, { 0x000F, 8 }, + { 0x0010, 8 }, { 0x0011, 8 }, { 0x0012, 8 }, { 0x0013, 8 }, + { 0x0014, 8 }, { 0x0015, 8 }, { 0x0016, 8 }, { 0x0001, 1 }, + { 0x0017, 8 }, { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, + { 0x000F, 7 }, { 0x0010, 7 }, { 0x0011, 7 }, { 0x0012, 7 }, + { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, { 0x0016, 7 }, + { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, { 0x001A, 7 }, + { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, { 0x001E, 7 }, + { 0x001F, 7 }, { 0x0020, 7 }, { 0x0021, 7 }, { 0x0022, 7 }, + { 0x0023, 7 }, { 0x0024, 7 }, { 0x0025, 7 }, { 0x0026, 7 }, + { 0x0027, 7 }, { 0x0028, 7 }, { 0x0029, 7 }, { 0x002A, 7 }, + { 0x002B, 7 }, { 0x002C, 7 }, { 0x002D, 7 }, { 0x002E, 7 }, + { 0x002F, 7 }, { 0x0030, 7 }, { 0x0031, 7 }, { 0x0032, 7 }, + { 0x0033, 7 }, { 0x0034, 7 }, { 0x0035, 7 }, { 0x0036, 7 }, + { 0x0037, 7 }, { 0x0038, 7 }, { 0x0039, 7 }, { 0x003A, 7 }, + { 0x003B, 7 }, { 0x003C, 7 }, { 0x003D, 7 }, { 0x003E, 7 }, + { 0x003F, 7 }, + }, + { // 4 + { 0x0000, 9 }, { 0x0001, 9 }, { 0x0002, 9 }, { 0x0003, 9 }, + { 0x0004, 9 }, { 0x0005, 9 }, { 0x0006, 9 }, { 0x0007, 9 }, + { 0x0008, 9 }, { 0x0009, 9 }, { 0x000A, 9 }, { 0x000B, 9 }, + { 0x000C, 9 }, { 0x000D, 9 }, { 0x000E, 9 }, { 0x000F, 9 }, + { 0x0010, 9 }, { 0x0011, 9 }, { 0x0012, 9 }, { 0x0013, 9 }, + { 0x0014, 9 }, { 0x0015, 9 }, { 0x000B, 8 }, { 0x0001, 2 }, + { 0x0001, 1 }, { 0x000C, 8 }, { 0x000D, 8 }, { 0x000E, 8 }, + { 0x000F, 8 }, { 0x0010, 8 }, { 0x0011, 8 }, { 0x0012, 8 }, + { 0x0013, 8 }, { 0x0014, 8 }, { 0x0015, 8 }, { 0x0016, 8 }, + { 0x0017, 8 }, { 0x0018, 8 }, { 0x0019, 8 }, { 0x001A, 8 }, + { 0x001B, 8 }, { 0x001C, 8 }, { 0x001D, 8 }, { 0x001E, 8 }, + { 0x001F, 8 }, { 0x0020, 8 }, { 0x0021, 8 }, { 0x0022, 8 }, + { 0x0023, 8 }, { 0x0024, 8 }, { 0x0025, 8 }, { 0x0026, 8 }, + { 0x0027, 8 }, { 0x0028, 8 }, { 0x0029, 8 }, { 0x002A, 8 }, + { 0x002B, 8 }, { 0x002C, 8 }, { 0x002D, 8 }, { 0x002E, 8 }, + { 0x002F, 8 }, { 0x0030, 8 }, { 0x0031, 8 }, { 0x0032, 8 }, + { 0x0033, 8 }, { 0x0034, 8 }, { 0x0035, 8 }, { 0x0036, 8 }, + { 0x0037, 8 }, { 0x0038, 8 }, { 0x0039, 8 }, { 0x003A, 8 }, + { 0x003B, 8 }, { 0x003C, 8 }, { 0x003D, 8 }, { 0x003E, 8 }, + { 0x003F, 8 }, + }, + { // 5 + { 0x0000, 10 }, { 0x0001, 10 }, { 0x0002, 10 }, { 0x0003, 10 }, + { 0x0004, 10 }, { 0x0005, 10 }, { 0x0006, 10 }, { 0x0007, 10 }, + { 0x0008, 10 }, { 0x0009, 10 }, { 0x000A, 10 }, { 0x000B, 10 }, + { 0x000C, 10 }, { 0x000D, 10 }, { 0x000E, 10 }, { 0x000F, 10 }, + { 0x0010, 10 }, { 0x0011, 10 }, { 0x0012, 10 }, { 0x0013, 10 }, + { 0x000A, 9 }, { 0x000B, 9 }, { 0x000C, 9 }, { 0x0001, 1 }, + { 0x0001, 3 }, { 0x000D, 9 }, { 0x000E, 9 }, { 0x0001, 2 }, + { 0x000F, 9 }, { 0x0010, 9 }, { 0x0011, 9 }, { 0x0012, 9 }, + { 0x0013, 9 }, { 0x0014, 9 }, { 0x0015, 9 }, { 0x0016, 9 }, + { 0x0017, 9 }, { 0x0018, 9 }, { 0x0019, 9 }, { 0x001A, 9 }, + { 0x001B, 9 }, { 0x001C, 9 }, { 0x001D, 9 }, { 0x001E, 9 }, + { 0x001F, 9 }, { 0x0020, 9 }, { 0x0021, 9 }, { 0x0022, 9 }, + { 0x0023, 9 }, { 0x0024, 9 }, { 0x0025, 9 }, { 0x0026, 9 }, + { 0x0027, 9 }, { 0x0028, 9 }, { 0x0029, 9 }, { 0x002A, 9 }, + { 0x002B, 9 }, { 0x002C, 9 }, { 0x002D, 9 }, { 0x002E, 9 }, + { 0x002F, 9 }, { 0x0030, 9 }, { 0x0031, 9 }, { 0x0032, 9 }, + { 0x0033, 9 }, { 0x0034, 9 }, { 0x0035, 9 }, { 0x0036, 9 }, + { 0x0037, 9 }, { 0x0038, 9 }, { 0x0039, 9 }, { 0x003A, 9 }, + { 0x003B, 9 }, { 0x003C, 9 }, { 0x003D, 9 }, { 0x003E, 9 }, + { 0x003F, 9 }, + }, + { // 6 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, + { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x006A, 8 }, + { 0x006B, 8 }, { 0x006C, 8 }, { 0x00DA, 9 }, { 0x00DB, 9 }, + { 0x01B8, 10 }, { 0x00DD, 9 }, { 0x01B9, 10 }, { 0x3780, 15 }, + { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x001F, 6 }, + { 0x000A, 4 }, { 0x0058, 7 }, { 0x0017, 5 }, { 0x0018, 5 }, + { 0x0059, 7 }, { 0x005A, 7 }, { 0x005B, 7 }, { 0x00C8, 8 }, + { 0x0065, 7 }, { 0x0066, 7 }, { 0x00C9, 8 }, { 0x00CE, 8 }, + { 0x00CF, 8 }, { 0x00D0, 8 }, { 0x00D1, 8 }, { 0x00D2, 8 }, + { 0x00D3, 8 }, { 0x00DF, 9 }, { 0x00D4, 8 }, { 0x00D5, 8 }, + { 0x00D6, 8 }, { 0x01AE, 9 }, { 0x3781, 15 }, { 0x01BD, 10 }, + { 0x035E, 10 }, { 0x035F, 10 }, { 0x3782, 15 }, { 0x0360, 10 }, + { 0x0037, 6 }, { 0x01B1, 9 }, { 0x3783, 15 }, { 0x3784, 15 }, + { 0x000E, 4 }, { 0x003C, 6 }, { 0x0361, 10 }, { 0x3785, 15 }, + { 0x1BC3, 14 }, { 0x003D, 6 }, { 0x00D9, 8 }, { 0x1BC4, 14 }, + { 0x0368, 10 }, { 0x1BC5, 14 }, { 0x1BC6, 14 }, { 0x1BC7, 14 }, + { 0x1BC8, 14 }, { 0x00DB, 8 }, { 0x0369, 10 }, { 0x036A, 10 }, + { 0x1BC9, 14 }, { 0x1BCA, 14 }, { 0x1BCB, 14 }, { 0x1BCC, 14 }, + { 0x1BCD, 14 }, { 0x001F, 5 }, { 0x036B, 10 }, { 0x1BCE, 14 }, + { 0x1BCF, 14 }, + }, + { // 7 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, + { 0x0010, 6 }, { 0x0044, 8 }, { 0x0023, 7 }, { 0x0012, 6 }, + { 0x0026, 7 }, { 0x08A0, 13 }, { 0x004E, 8 }, { 0x004F, 8 }, + { 0x08A1, 13 }, { 0x08A2, 13 }, { 0x08A3, 13 }, { 0x0050, 8 }, + { 0x0006, 4 }, { 0x000B, 5 }, { 0x0029, 7 }, { 0x0015, 6 }, + { 0x001C, 6 }, { 0x003A, 7 }, { 0x001E, 6 }, { 0x0004, 3 }, + { 0x0014, 5 }, { 0x0015, 5 }, { 0x000B, 4 }, { 0x001F, 6 }, + { 0x0030, 6 }, { 0x0031, 6 }, { 0x0019, 5 }, { 0x0051, 8 }, + { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, { 0x0037, 6 }, + { 0x0076, 8 }, { 0x0077, 8 }, { 0x0070, 7 }, { 0x001D, 5 }, + { 0x0071, 7 }, { 0x0072, 7 }, { 0x08A4, 13 }, { 0x0073, 7 }, + { 0x00F0, 8 }, { 0x08A5, 13 }, { 0x08A6, 13 }, { 0x08A7, 13 }, + { 0x0079, 7 }, { 0x007A, 7 }, { 0x08A8, 13 }, { 0x08A9, 13 }, + { 0x00F1, 8 }, { 0x08AA, 13 }, { 0x08AB, 13 }, { 0x08AC, 13 }, + { 0x08AD, 13 }, { 0x00F6, 8 }, { 0x08AE, 13 }, { 0x007C, 7 }, + { 0x00F7, 8 }, { 0x08AF, 13 }, { 0x08B0, 13 }, { 0x08B1, 13 }, + { 0x08B2, 13 }, { 0x00FA, 8 }, { 0x08B3, 13 }, { 0x08B4, 13 }, + { 0x08B5, 13 }, { 0x08B6, 13 }, { 0x08B7, 13 }, { 0x00FB, 8 }, + { 0x045C, 12 }, { 0x003F, 6 }, { 0x045D, 12 }, { 0x045E, 12 }, + { 0x045F, 12 }, + }, }; -static const uint16_t x8_ac1_lowquant_table[8][77][2]={ - {//0 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x004E, 8}, - {0x004F, 8}, {0x00A8, 9}, {0x0152, 10}, {0x00AA, 9}, - {0x00AB, 9}, {0x00AC, 9}, {0x2A60, 15}, {0x02A7, 11}, - {0x0006, 4}, {0x000B, 5}, {0x001C, 6}, {0x003A, 7}, - {0x000F, 5}, {0x003B, 7}, {0x0010, 5}, {0x0005, 3}, - {0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5}, - {0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0070, 7}, - {0x0057, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8}, - {0x00E5, 8}, {0x00AD, 9}, {0x0398, 10}, {0x003A, 6}, - {0x0076, 7}, {0x00E7, 8}, {0x00EE, 8}, {0x00EF, 8}, - {0x0732, 11}, {0x039A, 10}, {0x0733, 11}, {0x2A61, 15}, - {0x0078, 7}, {0x1531, 14}, {0x1532, 14}, {0x1533, 14}, - {0x003D, 6}, {0x039B, 10}, {0x1534, 14}, {0x1535, 14}, - {0x1536, 14}, {0x0079, 7}, {0x1537, 14}, {0x00F8, 8}, - {0x01F2, 9}, {0x07CC, 11}, {0x03E7, 10}, {0x07CD, 11}, - {0x3E80, 14}, {0x00FB, 8}, {0x03E9, 10}, {0x3E81, 14}, - {0x3E82, 14}, {0x3E83, 14}, {0x3E84, 14}, {0x3E85, 14}, - {0x3E86, 14}, {0x003F, 6}, {0x01F5, 9}, {0x07D1, 11}, - {0x3E87, 14}, - },{//1 - {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, - {0x001E, 6}, {0x001F, 6}, {0x0040, 7}, {0x0082, 8}, - {0x0083, 8}, {0x0084, 8}, {0x010A, 9}, {0x010B, 9}, - {0x0430, 11}, {0x0431, 11}, {0x0432, 11}, {0x0433, 11}, - {0x0005, 3}, {0x0011, 5}, {0x0024, 6}, {0x004A, 7}, - {0x000C, 4}, {0x0026, 6}, {0x000D, 4}, {0x0087, 8}, - {0x010D, 9}, {0x0258, 10}, {0x012D, 9}, {0x0259, 10}, - {0x025C, 10}, {0x0974, 12}, {0x025E, 10}, {0x025F, 10}, - {0x0270, 10}, {0x0271, 10}, {0x04BB, 11}, {0x0975, 12}, - {0x0272, 10}, {0x09CC, 12}, {0x09CD, 12}, {0x4E70, 15}, - {0x4E71, 15}, {0x4E72, 15}, {0x4E73, 15}, {0x273A, 14}, - {0x273B, 14}, {0x273C, 14}, {0x04E8, 11}, {0x04E9, 11}, - {0x009E, 8}, {0x0275, 10}, {0x09D8, 12}, {0x273D, 14}, - {0x000E, 4}, {0x003C, 6}, {0x007A, 7}, {0x009F, 8}, - {0x0277, 10}, {0x003E, 6}, {0x00F6, 8}, {0x04ED, 11}, - {0x03DC, 10}, {0x273E, 14}, {0x07BA, 11}, {0x09D9, 12}, - {0x273F, 14}, {0x3DD8, 14}, {0x3DD9, 14}, {0x3DDA, 14}, - {0x3DDB, 14}, {0x3DDC, 14}, {0x3DDD, 14}, {0x3DDE, 14}, - {0x3DDF, 14}, {0x003F, 6}, {0x07BC, 11}, {0x07BD, 11}, - {0x03DF, 10}, - },{//2 - {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6}, - {0x001E, 7}, {0x003E, 8}, {0x003F, 8}, {0x0040, 8}, - {0x0104, 10}, {0x0083, 9}, {0x0105, 10}, {0x0108, 10}, - {0x4240, 16}, {0x010A, 10}, {0x010B, 10}, {0x4241, 16}, - {0x0003, 3}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8}, - {0x0004, 3}, {0x000A, 5}, {0x000A, 4}, {0x002C, 7}, - {0x00B4, 9}, {0x00B5, 9}, {0x00B6, 9}, {0x00B7, 9}, - {0x00B8, 9}, {0x0172, 10}, {0x0173, 10}, {0x0174, 10}, - {0x0175, 10}, {0x0176, 10}, {0x0177, 10}, {0x00BC, 9}, - {0x017A, 10}, {0x0213, 11}, {0x4242, 16}, {0x017B, 10}, - {0x02F8, 11}, {0x017D, 10}, {0x02F9, 11}, {0x017E, 10}, - {0x4243, 16}, {0x02FE, 11}, {0x2122, 15}, {0x2123, 15}, - {0x0058, 7}, {0x0164, 9}, {0x2124, 15}, {0x2125, 15}, - {0x0006, 3}, {0x000E, 4}, {0x002D, 6}, {0x002E, 6}, - {0x00B3, 8}, {0x001E, 5}, {0x005E, 7}, {0x2126, 15}, - {0x2127, 15}, {0x2128, 15}, {0x2129, 15}, {0x02FF, 11}, - {0x212A, 15}, {0x0594, 11}, {0x0595, 11}, {0x0596, 11}, - {0x212B, 15}, {0x212C, 15}, {0x212D, 15}, {0x212E, 15}, - {0x212F, 15}, {0x001F, 5}, {0x0597, 11}, {0x00BE, 8}, - {0x00BF, 8}, - },{//3 - {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x0007, 4}, - {0x0010, 5}, {0x0011, 5}, {0x0024, 6}, {0x0025, 6}, - {0x0026, 6}, {0x0027, 6}, {0x0050, 7}, {0x0051, 7}, - {0x00A4, 8}, {0x00A5, 8}, {0x00A6, 8}, {0x014E, 9}, - {0x000B, 4}, {0x002A, 6}, {0x0056, 7}, {0x014F, 9}, - {0x0030, 6}, {0x00AE, 8}, {0x0062, 7}, {0x0032, 6}, - {0x0033, 6}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, - {0x0063, 7}, {0x006E, 7}, {0x006F, 7}, {0x0070, 7}, - {0x0071, 7}, {0x0072, 7}, {0x0073, 7}, {0x0074, 7}, - {0x00AF, 8}, {0x00EA, 8}, {0x01D6, 9}, {0x075C, 11}, - {0x03AF, 10}, {0x75D0, 15}, {0x75D1, 15}, {0x75D2, 15}, - {0x75D3, 15}, {0x75D4, 15}, {0x0076, 7}, {0x00EE, 8}, - {0x00EF, 8}, {0x0EBB, 12}, {0x01E0, 9}, {0x75D5, 15}, - {0x0079, 7}, {0x01E1, 9}, {0x75D6, 15}, {0x75D7, 15}, - {0x7880, 15}, {0x00F4, 8}, {0x0789, 11}, {0x003E, 6}, - {0x007B, 7}, {0x00F5, 8}, {0x00FC, 8}, {0x007F, 7}, - {0x01E3, 9}, {0x078A, 11}, {0x078B, 11}, {0x7881, 15}, - {0x7882, 15}, {0x7883, 15}, {0x3C42, 14}, {0x3C43, 14}, - {0x3C44, 14}, {0x00FD, 8}, {0x3C45, 14}, {0x3C46, 14}, - {0x3C47, 14}, - },{//4 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, - {0x0017, 6}, {0x0030, 7}, {0x0031, 7}, {0x0064, 8}, - {0x0065, 8}, {0x0066, 8}, {0x00CE, 9}, {0x00CF, 9}, - {0x01A0, 10}, {0x01A1, 10}, {0x1A20, 14}, {0x0689, 12}, - {0x0004, 3}, {0x000E, 5}, {0x001B, 6}, {0x0035, 7}, - {0x000A, 4}, {0x001E, 6}, {0x0016, 5}, {0x0017, 5}, - {0x001F, 6}, {0x0030, 6}, {0x0031, 6}, {0x0064, 7}, - {0x0065, 7}, {0x0069, 8}, {0x0066, 7}, {0x00CE, 8}, - {0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8}, - {0x01A6, 9}, {0x01A3, 10}, {0x034E, 10}, {0x006A, 7}, - {0x00D6, 8}, {0x01AE, 9}, {0x01AF, 9}, {0x034F, 10}, - {0x0345, 11}, {0x01B0, 9}, {0x01B1, 9}, {0x0364, 10}, - {0x006D, 7}, {0x00DC, 8}, {0x0D94, 12}, {0x0D95, 12}, - {0x000E, 4}, {0x003C, 6}, {0x00DD, 8}, {0x00DE, 8}, - {0x01B3, 9}, {0x003D, 6}, {0x00DF, 8}, {0x01F0, 9}, - {0x03E2, 10}, {0x03E3, 10}, {0x06CB, 11}, {0x03E4, 10}, - {0x07CA, 11}, {0x01F3, 9}, {0x01F4, 9}, {0x07CB, 11}, - {0x07D4, 11}, {0x1A21, 14}, {0x1A22, 14}, {0x07D5, 11}, - {0x1A23, 14}, {0x003F, 6}, {0x01F6, 9}, {0x01F7, 9}, - {0x03EB, 10}, - },{//5 - {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, - {0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7}, - {0x0045, 7}, {0x0046, 7}, {0x008E, 8}, {0x008F, 8}, - {0x0090, 8}, {0x0122, 9}, {0x0246, 10}, {0x0124, 9}, - {0x0005, 3}, {0x0013, 5}, {0x004A, 7}, {0x0093, 8}, - {0x0018, 5}, {0x004B, 7}, {0x0032, 6}, {0x001A, 5}, - {0x0033, 6}, {0x006C, 7}, {0x006D, 7}, {0x006E, 7}, - {0x00DE, 8}, {0x00DF, 8}, {0x0070, 7}, {0x00E2, 8}, - {0x00E3, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, - {0x00E7, 8}, {0x0125, 9}, {0x01D0, 9}, {0x048E, 11}, - {0x091E, 12}, {0x091F, 12}, {0x7440, 15}, {0x1D11, 13}, - {0x7441, 15}, {0x7442, 15}, {0x00E9, 8}, {0x01D4, 9}, - {0x00EB, 8}, {0x03A3, 10}, {0x01D5, 9}, {0x1D12, 13}, - {0x001E, 5}, {0x0076, 7}, {0x01DC, 9}, {0x01DD, 9}, - {0x7443, 15}, {0x007C, 7}, {0x0745, 11}, {0x00EF, 8}, - {0x00FA, 8}, {0x00FB, 8}, {0x01F8, 9}, {0x00FD, 8}, - {0x07E4, 11}, {0x0FCA, 12}, {0x1D13, 13}, {0x7E58, 15}, - {0x7E59, 15}, {0x7E5A, 15}, {0x7E5B, 15}, {0x7E5C, 15}, - {0x7E5D, 15}, {0x007F, 7}, {0x3F2F, 14}, {0x07E6, 11}, - {0x07E7, 11}, - },{//6 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0009, 5}, {0x0014, 6}, {0x0015, 6}, {0x002C, 7}, - {0x005A, 8}, {0x005B, 8}, {0x005C, 8}, {0x00BA, 9}, - {0x00BB, 9}, {0x00BC, 9}, {0x02F4, 11}, {0x05EA, 12}, - {0x0003, 3}, {0x0010, 5}, {0x0022, 6}, {0x0046, 7}, - {0x0009, 4}, {0x0028, 6}, {0x0015, 5}, {0x000B, 4}, - {0x0018, 5}, {0x0029, 6}, {0x0032, 6}, {0x0047, 7}, - {0x0066, 7}, {0x0067, 7}, {0x0068, 7}, {0x0069, 7}, - {0x006A, 7}, {0x005F, 8}, {0x00D6, 8}, {0x00D7, 8}, - {0x01B0, 9}, {0x00D9, 8}, {0x017B, 10}, {0x006D, 7}, - {0x00DC, 8}, {0x01B1, 9}, {0x06E8, 11}, {0x01BB, 9}, - {0x0375, 10}, {0x05EB, 12}, {0x01BC, 9}, {0x6E90, 15}, - {0x0038, 6}, {0x0072, 7}, {0x6E91, 15}, {0x6E92, 15}, - {0x001D, 5}, {0x0073, 7}, {0x01BD, 9}, {0x06F8, 11}, - {0x6E93, 15}, {0x003C, 6}, {0x01BF, 9}, {0x00F4, 8}, - {0x01EA, 9}, {0x037D, 10}, {0x03D6, 10}, {0x06F9, 11}, - {0x6E94, 15}, {0x00F6, 8}, {0x01EE, 9}, {0x6E95, 15}, - {0x6E96, 15}, {0x6E97, 15}, {0x374C, 14}, {0x374D, 14}, - {0x374E, 14}, {0x001F, 5}, {0x03D7, 10}, {0x01EF, 9}, - {0x374F, 14}, - },{//7 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, - {0x002E, 7}, {0x002F, 7}, {0x0060, 8}, {0x0061, 8}, - {0x00C4, 9}, {0x00C5, 9}, {0x00C6, 9}, {0x018E, 10}, - {0x31E0, 15}, {0x31E1, 15}, {0x31E2, 15}, {0x31E3, 15}, - {0x0004, 3}, {0x000D, 5}, {0x0019, 6}, {0x0038, 7}, - {0x000A, 4}, {0x001D, 6}, {0x000B, 4}, {0x0072, 8}, - {0x0073, 8}, {0x00F0, 9}, {0x01E2, 10}, {0x00F2, 9}, - {0x01E3, 10}, {0x00F3, 9}, {0x01E8, 10}, {0x01E9, 10}, - {0x31E4, 15}, {0x01EA, 10}, {0x031F, 11}, {0x03D6, 11}, - {0x31E5, 15}, {0x01EC, 10}, {0x31E6, 15}, {0x00F7, 9}, - {0x03D7, 11}, {0x31E7, 15}, {0x31E8, 15}, {0x03DA, 11}, - {0x03DB, 11}, {0x31E9, 15}, {0x03E0, 11}, {0x31EA, 15}, - {0x003F, 7}, {0x01F1, 10}, {0x31EB, 15}, {0x31EC, 15}, - {0x0006, 3}, {0x001C, 5}, {0x0074, 7}, {0x0075, 7}, - {0x00F9, 9}, {0x001E, 5}, {0x0076, 7}, {0x00FA, 9}, - {0x03E1, 11}, {0x31ED, 15}, {0x18F7, 14}, {0x1F60, 14}, - {0x1F61, 14}, {0x01DC, 9}, {0x01DD, 9}, {0x1F62, 14}, - {0x1F63, 14}, {0x1F64, 14}, {0x1F65, 14}, {0x1F66, 14}, - {0x1F67, 14}, {0x001F, 5}, {0x03ED, 11}, {0x00EF, 8}, - {0x01F7, 10}, - } +static const uint16_t x8_ac1_lowquant_table[8][77][2] = { + { // 0 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0012, 6 }, { 0x0026, 7 }, { 0x0014, 6 }, { 0x004E, 8 }, + { 0x004F, 8 }, { 0x00A8, 9 }, { 0x0152, 10 }, { 0x00AA, 9 }, + { 0x00AB, 9 }, { 0x00AC, 9 }, { 0x2A60, 15 }, { 0x02A7, 11 }, + { 0x0006, 4 }, { 0x000B, 5 }, { 0x001C, 6 }, { 0x003A, 7 }, + { 0x000F, 5 }, { 0x003B, 7 }, { 0x0010, 5 }, { 0x0005, 3 }, + { 0x0009, 4 }, { 0x0011, 5 }, { 0x0018, 5 }, { 0x0019, 5 }, + { 0x001A, 5 }, { 0x0036, 6 }, { 0x0037, 6 }, { 0x0070, 7 }, + { 0x0057, 8 }, { 0x00E2, 8 }, { 0x00E3, 8 }, { 0x00E4, 8 }, + { 0x00E5, 8 }, { 0x00AD, 9 }, { 0x0398, 10 }, { 0x003A, 6 }, + { 0x0076, 7 }, { 0x00E7, 8 }, { 0x00EE, 8 }, { 0x00EF, 8 }, + { 0x0732, 11 }, { 0x039A, 10 }, { 0x0733, 11 }, { 0x2A61, 15 }, + { 0x0078, 7 }, { 0x1531, 14 }, { 0x1532, 14 }, { 0x1533, 14 }, + { 0x003D, 6 }, { 0x039B, 10 }, { 0x1534, 14 }, { 0x1535, 14 }, + { 0x1536, 14 }, { 0x0079, 7 }, { 0x1537, 14 }, { 0x00F8, 8 }, + { 0x01F2, 9 }, { 0x07CC, 11 }, { 0x03E7, 10 }, { 0x07CD, 11 }, + { 0x3E80, 14 }, { 0x00FB, 8 }, { 0x03E9, 10 }, { 0x3E81, 14 }, + { 0x3E82, 14 }, { 0x3E83, 14 }, { 0x3E84, 14 }, { 0x3E85, 14 }, + { 0x3E86, 14 }, { 0x003F, 6 }, { 0x01F5, 9 }, { 0x07D1, 11 }, + { 0x3E87, 14 }, + }, + { // 1 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, + { 0x001E, 6 }, { 0x001F, 6 }, { 0x0040, 7 }, { 0x0082, 8 }, + { 0x0083, 8 }, { 0x0084, 8 }, { 0x010A, 9 }, { 0x010B, 9 }, + { 0x0430, 11 }, { 0x0431, 11 }, { 0x0432, 11 }, { 0x0433, 11 }, + { 0x0005, 3 }, { 0x0011, 5 }, { 0x0024, 6 }, { 0x004A, 7 }, + { 0x000C, 4 }, { 0x0026, 6 }, { 0x000D, 4 }, { 0x0087, 8 }, + { 0x010D, 9 }, { 0x0258, 10 }, { 0x012D, 9 }, { 0x0259, 10 }, + { 0x025C, 10 }, { 0x0974, 12 }, { 0x025E, 10 }, { 0x025F, 10 }, + { 0x0270, 10 }, { 0x0271, 10 }, { 0x04BB, 11 }, { 0x0975, 12 }, + { 0x0272, 10 }, { 0x09CC, 12 }, { 0x09CD, 12 }, { 0x4E70, 15 }, + { 0x4E71, 15 }, { 0x4E72, 15 }, { 0x4E73, 15 }, { 0x273A, 14 }, + { 0x273B, 14 }, { 0x273C, 14 }, { 0x04E8, 11 }, { 0x04E9, 11 }, + { 0x009E, 8 }, { 0x0275, 10 }, { 0x09D8, 12 }, { 0x273D, 14 }, + { 0x000E, 4 }, { 0x003C, 6 }, { 0x007A, 7 }, { 0x009F, 8 }, + { 0x0277, 10 }, { 0x003E, 6 }, { 0x00F6, 8 }, { 0x04ED, 11 }, + { 0x03DC, 10 }, { 0x273E, 14 }, { 0x07BA, 11 }, { 0x09D9, 12 }, + { 0x273F, 14 }, { 0x3DD8, 14 }, { 0x3DD9, 14 }, { 0x3DDA, 14 }, + { 0x3DDB, 14 }, { 0x3DDC, 14 }, { 0x3DDD, 14 }, { 0x3DDE, 14 }, + { 0x3DDF, 14 }, { 0x003F, 6 }, { 0x07BC, 11 }, { 0x07BD, 11 }, + { 0x03DF, 10 }, + }, + { // 2 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x000E, 6 }, + { 0x001E, 7 }, { 0x003E, 8 }, { 0x003F, 8 }, { 0x0040, 8 }, + { 0x0104, 10 }, { 0x0083, 9 }, { 0x0105, 10 }, { 0x0108, 10 }, + { 0x4240, 16 }, { 0x010A, 10 }, { 0x010B, 10 }, { 0x4241, 16 }, + { 0x0003, 3 }, { 0x0009, 5 }, { 0x0011, 6 }, { 0x0043, 8 }, + { 0x0004, 3 }, { 0x000A, 5 }, { 0x000A, 4 }, { 0x002C, 7 }, + { 0x00B4, 9 }, { 0x00B5, 9 }, { 0x00B6, 9 }, { 0x00B7, 9 }, + { 0x00B8, 9 }, { 0x0172, 10 }, { 0x0173, 10 }, { 0x0174, 10 }, + { 0x0175, 10 }, { 0x0176, 10 }, { 0x0177, 10 }, { 0x00BC, 9 }, + { 0x017A, 10 }, { 0x0213, 11 }, { 0x4242, 16 }, { 0x017B, 10 }, + { 0x02F8, 11 }, { 0x017D, 10 }, { 0x02F9, 11 }, { 0x017E, 10 }, + { 0x4243, 16 }, { 0x02FE, 11 }, { 0x2122, 15 }, { 0x2123, 15 }, + { 0x0058, 7 }, { 0x0164, 9 }, { 0x2124, 15 }, { 0x2125, 15 }, + { 0x0006, 3 }, { 0x000E, 4 }, { 0x002D, 6 }, { 0x002E, 6 }, + { 0x00B3, 8 }, { 0x001E, 5 }, { 0x005E, 7 }, { 0x2126, 15 }, + { 0x2127, 15 }, { 0x2128, 15 }, { 0x2129, 15 }, { 0x02FF, 11 }, + { 0x212A, 15 }, { 0x0594, 11 }, { 0x0595, 11 }, { 0x0596, 11 }, + { 0x212B, 15 }, { 0x212C, 15 }, { 0x212D, 15 }, { 0x212E, 15 }, + { 0x212F, 15 }, { 0x001F, 5 }, { 0x0597, 11 }, { 0x00BE, 8 }, + { 0x00BF, 8 }, + }, + { // 3 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x0007, 4 }, + { 0x0010, 5 }, { 0x0011, 5 }, { 0x0024, 6 }, { 0x0025, 6 }, + { 0x0026, 6 }, { 0x0027, 6 }, { 0x0050, 7 }, { 0x0051, 7 }, + { 0x00A4, 8 }, { 0x00A5, 8 }, { 0x00A6, 8 }, { 0x014E, 9 }, + { 0x000B, 4 }, { 0x002A, 6 }, { 0x0056, 7 }, { 0x014F, 9 }, + { 0x0030, 6 }, { 0x00AE, 8 }, { 0x0062, 7 }, { 0x0032, 6 }, + { 0x0033, 6 }, { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, + { 0x0063, 7 }, { 0x006E, 7 }, { 0x006F, 7 }, { 0x0070, 7 }, + { 0x0071, 7 }, { 0x0072, 7 }, { 0x0073, 7 }, { 0x0074, 7 }, + { 0x00AF, 8 }, { 0x00EA, 8 }, { 0x01D6, 9 }, { 0x075C, 11 }, + { 0x03AF, 10 }, { 0x75D0, 15 }, { 0x75D1, 15 }, { 0x75D2, 15 }, + { 0x75D3, 15 }, { 0x75D4, 15 }, { 0x0076, 7 }, { 0x00EE, 8 }, + { 0x00EF, 8 }, { 0x0EBB, 12 }, { 0x01E0, 9 }, { 0x75D5, 15 }, + { 0x0079, 7 }, { 0x01E1, 9 }, { 0x75D6, 15 }, { 0x75D7, 15 }, + { 0x7880, 15 }, { 0x00F4, 8 }, { 0x0789, 11 }, { 0x003E, 6 }, + { 0x007B, 7 }, { 0x00F5, 8 }, { 0x00FC, 8 }, { 0x007F, 7 }, + { 0x01E3, 9 }, { 0x078A, 11 }, { 0x078B, 11 }, { 0x7881, 15 }, + { 0x7882, 15 }, { 0x7883, 15 }, { 0x3C42, 14 }, { 0x3C43, 14 }, + { 0x3C44, 14 }, { 0x00FD, 8 }, { 0x3C45, 14 }, { 0x3C46, 14 }, + { 0x3C47, 14 }, + }, + { // 4 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, + { 0x0017, 6 }, { 0x0030, 7 }, { 0x0031, 7 }, { 0x0064, 8 }, + { 0x0065, 8 }, { 0x0066, 8 }, { 0x00CE, 9 }, { 0x00CF, 9 }, + { 0x01A0, 10 }, { 0x01A1, 10 }, { 0x1A20, 14 }, { 0x0689, 12 }, + { 0x0004, 3 }, { 0x000E, 5 }, { 0x001B, 6 }, { 0x0035, 7 }, + { 0x000A, 4 }, { 0x001E, 6 }, { 0x0016, 5 }, { 0x0017, 5 }, + { 0x001F, 6 }, { 0x0030, 6 }, { 0x0031, 6 }, { 0x0064, 7 }, + { 0x0065, 7 }, { 0x0069, 8 }, { 0x0066, 7 }, { 0x00CE, 8 }, + { 0x00CF, 8 }, { 0x00D0, 8 }, { 0x00D1, 8 }, { 0x00D2, 8 }, + { 0x01A6, 9 }, { 0x01A3, 10 }, { 0x034E, 10 }, { 0x006A, 7 }, + { 0x00D6, 8 }, { 0x01AE, 9 }, { 0x01AF, 9 }, { 0x034F, 10 }, + { 0x0345, 11 }, { 0x01B0, 9 }, { 0x01B1, 9 }, { 0x0364, 10 }, + { 0x006D, 7 }, { 0x00DC, 8 }, { 0x0D94, 12 }, { 0x0D95, 12 }, + { 0x000E, 4 }, { 0x003C, 6 }, { 0x00DD, 8 }, { 0x00DE, 8 }, + { 0x01B3, 9 }, { 0x003D, 6 }, { 0x00DF, 8 }, { 0x01F0, 9 }, + { 0x03E2, 10 }, { 0x03E3, 10 }, { 0x06CB, 11 }, { 0x03E4, 10 }, + { 0x07CA, 11 }, { 0x01F3, 9 }, { 0x01F4, 9 }, { 0x07CB, 11 }, + { 0x07D4, 11 }, { 0x1A21, 14 }, { 0x1A22, 14 }, { 0x07D5, 11 }, + { 0x1A23, 14 }, { 0x003F, 6 }, { 0x01F6, 9 }, { 0x01F7, 9 }, + { 0x03EB, 10 }, + }, + { // 5 + { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, + { 0x000F, 5 }, { 0x0020, 6 }, { 0x0021, 6 }, { 0x0044, 7 }, + { 0x0045, 7 }, { 0x0046, 7 }, { 0x008E, 8 }, { 0x008F, 8 }, + { 0x0090, 8 }, { 0x0122, 9 }, { 0x0246, 10 }, { 0x0124, 9 }, + { 0x0005, 3 }, { 0x0013, 5 }, { 0x004A, 7 }, { 0x0093, 8 }, + { 0x0018, 5 }, { 0x004B, 7 }, { 0x0032, 6 }, { 0x001A, 5 }, + { 0x0033, 6 }, { 0x006C, 7 }, { 0x006D, 7 }, { 0x006E, 7 }, + { 0x00DE, 8 }, { 0x00DF, 8 }, { 0x0070, 7 }, { 0x00E2, 8 }, + { 0x00E3, 8 }, { 0x00E4, 8 }, { 0x00E5, 8 }, { 0x00E6, 8 }, + { 0x00E7, 8 }, { 0x0125, 9 }, { 0x01D0, 9 }, { 0x048E, 11 }, + { 0x091E, 12 }, { 0x091F, 12 }, { 0x7440, 15 }, { 0x1D11, 13 }, + { 0x7441, 15 }, { 0x7442, 15 }, { 0x00E9, 8 }, { 0x01D4, 9 }, + { 0x00EB, 8 }, { 0x03A3, 10 }, { 0x01D5, 9 }, { 0x1D12, 13 }, + { 0x001E, 5 }, { 0x0076, 7 }, { 0x01DC, 9 }, { 0x01DD, 9 }, + { 0x7443, 15 }, { 0x007C, 7 }, { 0x0745, 11 }, { 0x00EF, 8 }, + { 0x00FA, 8 }, { 0x00FB, 8 }, { 0x01F8, 9 }, { 0x00FD, 8 }, + { 0x07E4, 11 }, { 0x0FCA, 12 }, { 0x1D13, 13 }, { 0x7E58, 15 }, + { 0x7E59, 15 }, { 0x7E5A, 15 }, { 0x7E5B, 15 }, { 0x7E5C, 15 }, + { 0x7E5D, 15 }, { 0x007F, 7 }, { 0x3F2F, 14 }, { 0x07E6, 11 }, + { 0x07E7, 11 }, + }, + { // 6 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0009, 5 }, { 0x0014, 6 }, { 0x0015, 6 }, { 0x002C, 7 }, + { 0x005A, 8 }, { 0x005B, 8 }, { 0x005C, 8 }, { 0x00BA, 9 }, + { 0x00BB, 9 }, { 0x00BC, 9 }, { 0x02F4, 11 }, { 0x05EA, 12 }, + { 0x0003, 3 }, { 0x0010, 5 }, { 0x0022, 6 }, { 0x0046, 7 }, + { 0x0009, 4 }, { 0x0028, 6 }, { 0x0015, 5 }, { 0x000B, 4 }, + { 0x0018, 5 }, { 0x0029, 6 }, { 0x0032, 6 }, { 0x0047, 7 }, + { 0x0066, 7 }, { 0x0067, 7 }, { 0x0068, 7 }, { 0x0069, 7 }, + { 0x006A, 7 }, { 0x005F, 8 }, { 0x00D6, 8 }, { 0x00D7, 8 }, + { 0x01B0, 9 }, { 0x00D9, 8 }, { 0x017B, 10 }, { 0x006D, 7 }, + { 0x00DC, 8 }, { 0x01B1, 9 }, { 0x06E8, 11 }, { 0x01BB, 9 }, + { 0x0375, 10 }, { 0x05EB, 12 }, { 0x01BC, 9 }, { 0x6E90, 15 }, + { 0x0038, 6 }, { 0x0072, 7 }, { 0x6E91, 15 }, { 0x6E92, 15 }, + { 0x001D, 5 }, { 0x0073, 7 }, { 0x01BD, 9 }, { 0x06F8, 11 }, + { 0x6E93, 15 }, { 0x003C, 6 }, { 0x01BF, 9 }, { 0x00F4, 8 }, + { 0x01EA, 9 }, { 0x037D, 10 }, { 0x03D6, 10 }, { 0x06F9, 11 }, + { 0x6E94, 15 }, { 0x00F6, 8 }, { 0x01EE, 9 }, { 0x6E95, 15 }, + { 0x6E96, 15 }, { 0x6E97, 15 }, { 0x374C, 14 }, { 0x374D, 14 }, + { 0x374E, 14 }, { 0x001F, 5 }, { 0x03D7, 10 }, { 0x01EF, 9 }, + { 0x374F, 14 }, + }, + { // 7 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, + { 0x002E, 7 }, { 0x002F, 7 }, { 0x0060, 8 }, { 0x0061, 8 }, + { 0x00C4, 9 }, { 0x00C5, 9 }, { 0x00C6, 9 }, { 0x018E, 10 }, + { 0x31E0, 15 }, { 0x31E1, 15 }, { 0x31E2, 15 }, { 0x31E3, 15 }, + { 0x0004, 3 }, { 0x000D, 5 }, { 0x0019, 6 }, { 0x0038, 7 }, + { 0x000A, 4 }, { 0x001D, 6 }, { 0x000B, 4 }, { 0x0072, 8 }, + { 0x0073, 8 }, { 0x00F0, 9 }, { 0x01E2, 10 }, { 0x00F2, 9 }, + { 0x01E3, 10 }, { 0x00F3, 9 }, { 0x01E8, 10 }, { 0x01E9, 10 }, + { 0x31E4, 15 }, { 0x01EA, 10 }, { 0x031F, 11 }, { 0x03D6, 11 }, + { 0x31E5, 15 }, { 0x01EC, 10 }, { 0x31E6, 15 }, { 0x00F7, 9 }, + { 0x03D7, 11 }, { 0x31E7, 15 }, { 0x31E8, 15 }, { 0x03DA, 11 }, + { 0x03DB, 11 }, { 0x31E9, 15 }, { 0x03E0, 11 }, { 0x31EA, 15 }, + { 0x003F, 7 }, { 0x01F1, 10 }, { 0x31EB, 15 }, { 0x31EC, 15 }, + { 0x0006, 3 }, { 0x001C, 5 }, { 0x0074, 7 }, { 0x0075, 7 }, + { 0x00F9, 9 }, { 0x001E, 5 }, { 0x0076, 7 }, { 0x00FA, 9 }, + { 0x03E1, 11 }, { 0x31ED, 15 }, { 0x18F7, 14 }, { 0x1F60, 14 }, + { 0x1F61, 14 }, { 0x01DC, 9 }, { 0x01DD, 9 }, { 0x1F62, 14 }, + { 0x1F63, 14 }, { 0x1F64, 14 }, { 0x1F65, 14 }, { 0x1F66, 14 }, + { 0x1F67, 14 }, { 0x001F, 5 }, { 0x03ED, 11 }, { 0x00EF, 8 }, + { 0x01F7, 10 }, + }, }; -static const uint16_t x8_ac1_highquant_table[8][77][2]={ - {//0 - {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, - {0x0008, 5}, {0x0009, 5}, {0x0014, 6}, {0x002A, 7}, - {0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x002F, 7}, - {0x0030, 7}, {0x005D, 8}, {0x0062, 8}, {0x00C6, 9}, - {0x0007, 4}, {0x0019, 6}, {0x001A, 6}, {0x0036, 7}, - {0x0010, 5}, {0x006E, 8}, {0x0022, 6}, {0x0009, 4}, - {0x000A, 4}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6}, - {0x002F, 6}, {0x0030, 6}, {0x0062, 7}, {0x0063, 7}, - {0x0064, 7}, {0x0065, 7}, {0x0066, 7}, {0x0067, 7}, - {0x0068, 7}, {0x0069, 7}, {0x006A, 7}, {0x006B, 7}, - {0x006C, 7}, {0x00C7, 9}, {0x00DE, 9}, {0x00DF, 9}, - {0x06D0, 11}, {0x01B5, 9}, {0x0037, 6}, {0x00DB, 8}, - {0x001C, 5}, {0x0074, 7}, {0x01D4, 9}, {0x01D5, 9}, - {0x0076, 7}, {0x0369, 10}, {0x3688, 14}, {0x3689, 14}, - {0x368A, 14}, {0x0077, 7}, {0x03AC, 10}, {0x0078, 7}, - {0x00F2, 8}, {0x01D7, 9}, {0x00F3, 8}, {0x007A, 7}, - {0x368B, 14}, {0x007B, 7}, {0x007C, 7}, {0x03AD, 10}, - {0x03E8, 10}, {0x368C, 14}, {0x368D, 14}, {0x03E9, 10}, - {0x368E, 14}, {0x003F, 6}, {0x01F5, 9}, {0x00FB, 8}, - {0x368F, 14}, - },{//1 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, - {0x0018, 6}, {0x0032, 7}, {0x0033, 7}, {0x0034, 7}, - {0x006A, 8}, {0x00D6, 9}, {0x00D7, 9}, {0x00D8, 9}, - {0x00D9, 9}, {0x3680, 15}, {0x01B5, 10}, {0x0369, 11}, - {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x0037, 7}, - {0x000A, 4}, {0x0016, 5}, {0x000C, 4}, {0x001F, 6}, - {0x005C, 7}, {0x005D, 7}, {0x00BC, 8}, {0x00BD, 8}, - {0x005F, 7}, {0x00D0, 8}, {0x00DB, 9}, {0x00D1, 8}, - {0x01A4, 9}, {0x01A5, 9}, {0x01A6, 9}, {0x01A7, 9}, - {0x0350, 10}, {0x06A2, 11}, {0x06A3, 11}, {0x01A9, 9}, - {0x01AA, 9}, {0x06AC, 11}, {0x3681, 15}, {0x0357, 10}, - {0x3682, 15}, {0x3683, 15}, {0x3684, 15}, {0x3685, 15}, - {0x0036, 6}, {0x00D6, 8}, {0x3686, 15}, {0x3687, 15}, - {0x000E, 4}, {0x006E, 7}, {0x00D7, 8}, {0x06AD, 11}, - {0x3688, 15}, {0x001E, 5}, {0x00DE, 8}, {0x06F8, 11}, - {0x037D, 10}, {0x3689, 15}, {0x368A, 15}, {0x368B, 15}, - {0x368C, 15}, {0x01BF, 9}, {0x368D, 15}, {0x1B47, 14}, - {0x37C8, 14}, {0x37C9, 14}, {0x37CA, 14}, {0x37CB, 14}, - {0x37CC, 14}, {0x001F, 5}, {0x37CD, 14}, {0x37CE, 14}, - {0x37CF, 14}, - },{//2 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x0027, 7}, - {0x00A8, 9}, {0x00A9, 9}, {0x0055, 8}, {0x2B00, 15}, - {0x00AD, 9}, {0x2B01, 15}, {0x2B02, 15}, {0x2B03, 15}, - {0x0003, 3}, {0x000B, 5}, {0x0040, 7}, {0x0041, 7}, - {0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x000A, 4}, - {0x000B, 4}, {0x0018, 5}, {0x0032, 6}, {0x0033, 6}, - {0x0034, 6}, {0x0035, 6}, {0x006C, 7}, {0x0057, 8}, - {0x006D, 7}, {0x00DC, 8}, {0x0159, 10}, {0x00DD, 8}, - {0x01BC, 9}, {0x037A, 10}, {0x037B, 10}, {0x0038, 6}, - {0x0072, 7}, {0x01BE, 9}, {0x01BF, 9}, {0x00E6, 8}, - {0x039C, 10}, {0x01CF, 9}, {0x2B04, 15}, {0x2B05, 15}, - {0x0074, 7}, {0x01D4, 9}, {0x2B06, 15}, {0x2B07, 15}, - {0x001E, 5}, {0x00EB, 8}, {0x1584, 14}, {0x1585, 14}, - {0x1586, 14}, {0x003B, 6}, {0x01D5, 9}, {0x01F0, 9}, - {0x039D, 10}, {0x03E2, 10}, {0x1587, 14}, {0x1588, 14}, - {0x1589, 14}, {0x00F9, 8}, {0x158A, 14}, {0x158B, 14}, - {0x03E3, 10}, {0x158C, 14}, {0x158D, 14}, {0x01F4, 9}, - {0x158E, 14}, {0x003F, 6}, {0x00FB, 8}, {0x01F5, 9}, - {0x158F, 14}, - },{//3 - {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, - {0x0010, 6}, {0x0011, 6}, {0x0024, 7}, {0x0025, 7}, - {0x0013, 6}, {0x0014, 6}, {0x002A, 7}, {0x002B, 7}, - {0x00B0, 9}, {0x00B1, 9}, {0x002D, 7}, {0x0059, 8}, - {0x000C, 5}, {0x0017, 6}, {0x00D0, 9}, {0x0035, 7}, - {0x001B, 6}, {0x0038, 7}, {0x0039, 7}, {0x0004, 3}, - {0x0005, 3}, {0x000F, 5}, {0x0018, 5}, {0x001D, 6}, - {0x0032, 6}, {0x0033, 6}, {0x0068, 7}, {0x0069, 7}, - {0x0069, 8}, {0x00D4, 8}, {0x00D5, 8}, {0x00D6, 8}, - {0x006C, 7}, {0x0037, 6}, {0x006D, 7}, {0x0070, 7}, - {0x0039, 6}, {0x00D7, 8}, {0x00D1, 9}, {0x3880, 14}, - {0x3881, 14}, {0x3882, 14}, {0x0074, 7}, {0x01C5, 9}, - {0x0075, 7}, {0x00E3, 8}, {0x3883, 14}, {0x3884, 14}, - {0x00EC, 8}, {0x3885, 14}, {0x1C43, 13}, {0x1C44, 13}, - {0x1C45, 13}, {0x00ED, 8}, {0x1C46, 13}, {0x003C, 6}, - {0x0077, 7}, {0x01E8, 9}, {0x003E, 6}, {0x007B, 7}, - {0x1C47, 13}, {0x007E, 7}, {0x007F, 7}, {0x1C48, 13}, - {0x1C49, 13}, {0x1C4A, 13}, {0x1C4B, 13}, {0x1C4C, 13}, - {0x1C4D, 13}, {0x00F5, 8}, {0x1C4E, 13}, {0x01E9, 9}, - {0x1C4F, 13}, - },{//4 - {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, - {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x0035, 7}, - {0x0036, 7}, {0x006E, 8}, {0x00DE, 9}, {0x00DF, 9}, - {0x01C0, 10}, {0x01C1, 10}, {0x01C2, 10}, {0x3860, 15}, - {0x0004, 3}, {0x000F, 5}, {0x001D, 6}, {0x0039, 7}, - {0x000A, 4}, {0x002C, 6}, {0x002D, 6}, {0x000C, 4}, - {0x0017, 5}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, - {0x006E, 7}, {0x006F, 7}, {0x0070, 7}, {0x0071, 7}, - {0x0071, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, - {0x00E7, 8}, {0x00E8, 8}, {0x03A4, 10}, {0x0075, 7}, - {0x00EC, 8}, {0x01D3, 9}, {0x01DA, 9}, {0x03A5, 10}, - {0x03B6, 10}, {0x070D, 12}, {0x03B7, 10}, {0x070E, 12}, - {0x003C, 6}, {0x00EE, 8}, {0x3861, 15}, {0x3862, 15}, - {0x003D, 6}, {0x01DE, 9}, {0x3863, 15}, {0x3864, 15}, - {0x3865, 15}, {0x007C, 7}, {0x070F, 12}, {0x03BE, 10}, - {0x03BF, 10}, {0x3866, 15}, {0x0FA0, 12}, {0x07D1, 11}, - {0x3867, 15}, {0x00FB, 8}, {0x01F5, 9}, {0x7D08, 15}, - {0x0FA4, 12}, {0x7D09, 15}, {0x7D0A, 15}, {0x7D0B, 15}, - {0x3E86, 14}, {0x003F, 6}, {0x0FA5, 12}, {0x07D3, 11}, - {0x3E87, 14}, - },{//5 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0009, 5}, {0x0014, 6}, {0x002A, 7}, {0x0056, 8}, - {0x02B8, 11}, {0x00AF, 9}, {0x02B9, 11}, {0x015D, 10}, - {0x02C0, 11}, {0x2C10, 15}, {0x2C11, 15}, {0x2C12, 15}, - {0x0006, 4}, {0x000E, 5}, {0x0017, 6}, {0x002D, 7}, - {0x000F, 5}, {0x0040, 7}, {0x0021, 6}, {0x0005, 3}, - {0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5}, - {0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0041, 7}, - {0x0059, 8}, {0x00E0, 8}, {0x00E1, 8}, {0x0071, 7}, - {0x00E4, 8}, {0x00B1, 9}, {0x02C2, 11}, {0x001D, 5}, - {0x0073, 7}, {0x00E5, 8}, {0x00F0, 8}, {0x0079, 7}, - {0x03C4, 10}, {0x01E3, 9}, {0x01E8, 9}, {0x2C13, 15}, - {0x007B, 7}, {0x2C14, 15}, {0x2C15, 15}, {0x2C16, 15}, - {0x007C, 7}, {0x02C3, 11}, {0x2C17, 15}, {0x160C, 14}, - {0x160D, 14}, {0x007D, 7}, {0x160E, 14}, {0x01E9, 9}, - {0x03C5, 10}, {0x03D4, 10}, {0x01EB, 9}, {0x160F, 14}, - {0x3D50, 14}, {0x00FC, 8}, {0x07AB, 11}, {0x3D51, 14}, - {0x3D52, 14}, {0x3D53, 14}, {0x3D54, 14}, {0x01FA, 9}, - {0x3D55, 14}, {0x007F, 7}, {0x01FB, 9}, {0x3D56, 14}, - {0x3D57, 14}, - },{//6 - {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, - {0x0009, 5}, {0x000A, 5}, {0x000B, 5}, {0x0018, 6}, - {0x0032, 7}, {0x000D, 5}, {0x0033, 7}, {0x0E00, 13}, - {0x0039, 7}, {0x0E01, 13}, {0x003A, 7}, {0x0E02, 13}, - {0x0008, 4}, {0x001E, 6}, {0x003B, 7}, {0x003E, 7}, - {0x0012, 5}, {0x003F, 7}, {0x0013, 5}, {0x0028, 6}, - {0x0029, 6}, {0x0054, 7}, {0x002B, 6}, {0x0055, 7}, - {0x0058, 7}, {0x0E03, 13}, {0x0059, 7}, {0x005A, 7}, - {0x0E04, 13}, {0x0E05, 13}, {0x0703, 12}, {0x005B, 7}, - {0x005C, 7}, {0x0704, 12}, {0x0705, 12}, {0x005D, 7}, - {0x0706, 12}, {0x0707, 12}, {0x0708, 12}, {0x0709, 12}, - {0x070A, 12}, {0x070B, 12}, {0x0018, 5}, {0x002F, 6}, - {0x000D, 4}, {0x0019, 5}, {0x070C, 12}, {0x0070, 7}, - {0x001D, 5}, {0x070D, 12}, {0x070E, 12}, {0x070F, 12}, - {0x0710, 12}, {0x0039, 6}, {0x0711, 12}, {0x003C, 6}, - {0x0712, 12}, {0x0713, 12}, {0x0714, 12}, {0x0715, 12}, - {0x0716, 12}, {0x003D, 6}, {0x0717, 12}, {0x0718, 12}, - {0x0719, 12}, {0x071A, 12}, {0x071B, 12}, {0x071C, 12}, - {0x071D, 12}, {0x001F, 5}, {0x071E, 12}, {0x0071, 7}, - {0x071F, 12}, - },{//7 - {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6}, - {0x000F, 6}, {0x0040, 8}, {0x0041, 8}, {0x0042, 8}, - {0x0218, 11}, {0x2190, 15}, {0x2191, 15}, {0x2192, 15}, - {0x2193, 15}, {0x2194, 15}, {0x2195, 15}, {0x2196, 15}, - {0x0005, 4}, {0x0011, 6}, {0x0024, 7}, {0x0087, 9}, - {0x000C, 5}, {0x004A, 8}, {0x004B, 8}, {0x0002, 2}, - {0x0006, 3}, {0x000D, 5}, {0x000E, 5}, {0x000F, 5}, - {0x0013, 6}, {0x0038, 6}, {0x00E4, 8}, {0x00E5, 8}, - {0x01CC, 9}, {0x00E7, 8}, {0x0074, 7}, {0x00EA, 8}, - {0x01CD, 9}, {0x021A, 11}, {0x2197, 15}, {0x001E, 5}, - {0x0076, 7}, {0x00EB, 8}, {0x01DC, 9}, {0x00EF, 8}, - {0x01DD, 9}, {0x01F0, 9}, {0x2198, 15}, {0x2199, 15}, - {0x00F9, 8}, {0x03E2, 10}, {0x219A, 15}, {0x219B, 15}, - {0x00FA, 8}, {0x219C, 15}, {0x219D, 15}, {0x219E, 15}, - {0x219F, 15}, {0x01F6, 9}, {0x21B0, 15}, {0x00FC, 8}, - {0x01F7, 9}, {0x21B1, 15}, {0x21B2, 15}, {0x21B3, 15}, - {0x21B4, 15}, {0x01FA, 9}, {0x21B5, 15}, {0x21B6, 15}, - {0x21B7, 15}, {0x21B8, 15}, {0x21B9, 15}, {0x03E3, 10}, - {0x10DD, 14}, {0x007F, 7}, {0x01FB, 9}, {0x10DE, 14}, - {0x10DF, 14}, - } +static const uint16_t x8_ac1_highquant_table[8][77][2] = { + { // 0 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, + { 0x0008, 5 }, { 0x0009, 5 }, { 0x0014, 6 }, { 0x002A, 7 }, + { 0x0016, 6 }, { 0x002B, 7 }, { 0x005C, 8 }, { 0x002F, 7 }, + { 0x0030, 7 }, { 0x005D, 8 }, { 0x0062, 8 }, { 0x00C6, 9 }, + { 0x0007, 4 }, { 0x0019, 6 }, { 0x001A, 6 }, { 0x0036, 7 }, + { 0x0010, 5 }, { 0x006E, 8 }, { 0x0022, 6 }, { 0x0009, 4 }, + { 0x000A, 4 }, { 0x0016, 5 }, { 0x0023, 6 }, { 0x002E, 6 }, + { 0x002F, 6 }, { 0x0030, 6 }, { 0x0062, 7 }, { 0x0063, 7 }, + { 0x0064, 7 }, { 0x0065, 7 }, { 0x0066, 7 }, { 0x0067, 7 }, + { 0x0068, 7 }, { 0x0069, 7 }, { 0x006A, 7 }, { 0x006B, 7 }, + { 0x006C, 7 }, { 0x00C7, 9 }, { 0x00DE, 9 }, { 0x00DF, 9 }, + { 0x06D0, 11 }, { 0x01B5, 9 }, { 0x0037, 6 }, { 0x00DB, 8 }, + { 0x001C, 5 }, { 0x0074, 7 }, { 0x01D4, 9 }, { 0x01D5, 9 }, + { 0x0076, 7 }, { 0x0369, 10 }, { 0x3688, 14 }, { 0x3689, 14 }, + { 0x368A, 14 }, { 0x0077, 7 }, { 0x03AC, 10 }, { 0x0078, 7 }, + { 0x00F2, 8 }, { 0x01D7, 9 }, { 0x00F3, 8 }, { 0x007A, 7 }, + { 0x368B, 14 }, { 0x007B, 7 }, { 0x007C, 7 }, { 0x03AD, 10 }, + { 0x03E8, 10 }, { 0x368C, 14 }, { 0x368D, 14 }, { 0x03E9, 10 }, + { 0x368E, 14 }, { 0x003F, 6 }, { 0x01F5, 9 }, { 0x00FB, 8 }, + { 0x368F, 14 }, + }, + { // 1 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, + { 0x0018, 6 }, { 0x0032, 7 }, { 0x0033, 7 }, { 0x0034, 7 }, + { 0x006A, 8 }, { 0x00D6, 9 }, { 0x00D7, 9 }, { 0x00D8, 9 }, + { 0x00D9, 9 }, { 0x3680, 15 }, { 0x01B5, 10 }, { 0x0369, 11 }, + { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x0037, 7 }, + { 0x000A, 4 }, { 0x0016, 5 }, { 0x000C, 4 }, { 0x001F, 6 }, + { 0x005C, 7 }, { 0x005D, 7 }, { 0x00BC, 8 }, { 0x00BD, 8 }, + { 0x005F, 7 }, { 0x00D0, 8 }, { 0x00DB, 9 }, { 0x00D1, 8 }, + { 0x01A4, 9 }, { 0x01A5, 9 }, { 0x01A6, 9 }, { 0x01A7, 9 }, + { 0x0350, 10 }, { 0x06A2, 11 }, { 0x06A3, 11 }, { 0x01A9, 9 }, + { 0x01AA, 9 }, { 0x06AC, 11 }, { 0x3681, 15 }, { 0x0357, 10 }, + { 0x3682, 15 }, { 0x3683, 15 }, { 0x3684, 15 }, { 0x3685, 15 }, + { 0x0036, 6 }, { 0x00D6, 8 }, { 0x3686, 15 }, { 0x3687, 15 }, + { 0x000E, 4 }, { 0x006E, 7 }, { 0x00D7, 8 }, { 0x06AD, 11 }, + { 0x3688, 15 }, { 0x001E, 5 }, { 0x00DE, 8 }, { 0x06F8, 11 }, + { 0x037D, 10 }, { 0x3689, 15 }, { 0x368A, 15 }, { 0x368B, 15 }, + { 0x368C, 15 }, { 0x01BF, 9 }, { 0x368D, 15 }, { 0x1B47, 14 }, + { 0x37C8, 14 }, { 0x37C9, 14 }, { 0x37CA, 14 }, { 0x37CB, 14 }, + { 0x37CC, 14 }, { 0x001F, 5 }, { 0x37CD, 14 }, { 0x37CE, 14 }, + { 0x37CF, 14 }, + }, + { // 2 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0012, 6 }, { 0x0026, 7 }, { 0x0014, 6 }, { 0x0027, 7 }, + { 0x00A8, 9 }, { 0x00A9, 9 }, { 0x0055, 8 }, { 0x2B00, 15 }, + { 0x00AD, 9 }, { 0x2B01, 15 }, { 0x2B02, 15 }, { 0x2B03, 15 }, + { 0x0003, 3 }, { 0x000B, 5 }, { 0x0040, 7 }, { 0x0041, 7 }, + { 0x0009, 4 }, { 0x0021, 6 }, { 0x0011, 5 }, { 0x000A, 4 }, + { 0x000B, 4 }, { 0x0018, 5 }, { 0x0032, 6 }, { 0x0033, 6 }, + { 0x0034, 6 }, { 0x0035, 6 }, { 0x006C, 7 }, { 0x0057, 8 }, + { 0x006D, 7 }, { 0x00DC, 8 }, { 0x0159, 10 }, { 0x00DD, 8 }, + { 0x01BC, 9 }, { 0x037A, 10 }, { 0x037B, 10 }, { 0x0038, 6 }, + { 0x0072, 7 }, { 0x01BE, 9 }, { 0x01BF, 9 }, { 0x00E6, 8 }, + { 0x039C, 10 }, { 0x01CF, 9 }, { 0x2B04, 15 }, { 0x2B05, 15 }, + { 0x0074, 7 }, { 0x01D4, 9 }, { 0x2B06, 15 }, { 0x2B07, 15 }, + { 0x001E, 5 }, { 0x00EB, 8 }, { 0x1584, 14 }, { 0x1585, 14 }, + { 0x1586, 14 }, { 0x003B, 6 }, { 0x01D5, 9 }, { 0x01F0, 9 }, + { 0x039D, 10 }, { 0x03E2, 10 }, { 0x1587, 14 }, { 0x1588, 14 }, + { 0x1589, 14 }, { 0x00F9, 8 }, { 0x158A, 14 }, { 0x158B, 14 }, + { 0x03E3, 10 }, { 0x158C, 14 }, { 0x158D, 14 }, { 0x01F4, 9 }, + { 0x158E, 14 }, { 0x003F, 6 }, { 0x00FB, 8 }, { 0x01F5, 9 }, + { 0x158F, 14 }, + }, + { // 3 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, + { 0x0010, 6 }, { 0x0011, 6 }, { 0x0024, 7 }, { 0x0025, 7 }, + { 0x0013, 6 }, { 0x0014, 6 }, { 0x002A, 7 }, { 0x002B, 7 }, + { 0x00B0, 9 }, { 0x00B1, 9 }, { 0x002D, 7 }, { 0x0059, 8 }, + { 0x000C, 5 }, { 0x0017, 6 }, { 0x00D0, 9 }, { 0x0035, 7 }, + { 0x001B, 6 }, { 0x0038, 7 }, { 0x0039, 7 }, { 0x0004, 3 }, + { 0x0005, 3 }, { 0x000F, 5 }, { 0x0018, 5 }, { 0x001D, 6 }, + { 0x0032, 6 }, { 0x0033, 6 }, { 0x0068, 7 }, { 0x0069, 7 }, + { 0x0069, 8 }, { 0x00D4, 8 }, { 0x00D5, 8 }, { 0x00D6, 8 }, + { 0x006C, 7 }, { 0x0037, 6 }, { 0x006D, 7 }, { 0x0070, 7 }, + { 0x0039, 6 }, { 0x00D7, 8 }, { 0x00D1, 9 }, { 0x3880, 14 }, + { 0x3881, 14 }, { 0x3882, 14 }, { 0x0074, 7 }, { 0x01C5, 9 }, + { 0x0075, 7 }, { 0x00E3, 8 }, { 0x3883, 14 }, { 0x3884, 14 }, + { 0x00EC, 8 }, { 0x3885, 14 }, { 0x1C43, 13 }, { 0x1C44, 13 }, + { 0x1C45, 13 }, { 0x00ED, 8 }, { 0x1C46, 13 }, { 0x003C, 6 }, + { 0x0077, 7 }, { 0x01E8, 9 }, { 0x003E, 6 }, { 0x007B, 7 }, + { 0x1C47, 13 }, { 0x007E, 7 }, { 0x007F, 7 }, { 0x1C48, 13 }, + { 0x1C49, 13 }, { 0x1C4A, 13 }, { 0x1C4B, 13 }, { 0x1C4C, 13 }, + { 0x1C4D, 13 }, { 0x00F5, 8 }, { 0x1C4E, 13 }, { 0x01E9, 9 }, + { 0x1C4F, 13 }, + }, + { // 4 + { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, + { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x0035, 7 }, + { 0x0036, 7 }, { 0x006E, 8 }, { 0x00DE, 9 }, { 0x00DF, 9 }, + { 0x01C0, 10 }, { 0x01C1, 10 }, { 0x01C2, 10 }, { 0x3860, 15 }, + { 0x0004, 3 }, { 0x000F, 5 }, { 0x001D, 6 }, { 0x0039, 7 }, + { 0x000A, 4 }, { 0x002C, 6 }, { 0x002D, 6 }, { 0x000C, 4 }, + { 0x0017, 5 }, { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, + { 0x006E, 7 }, { 0x006F, 7 }, { 0x0070, 7 }, { 0x0071, 7 }, + { 0x0071, 8 }, { 0x00E4, 8 }, { 0x00E5, 8 }, { 0x00E6, 8 }, + { 0x00E7, 8 }, { 0x00E8, 8 }, { 0x03A4, 10 }, { 0x0075, 7 }, + { 0x00EC, 8 }, { 0x01D3, 9 }, { 0x01DA, 9 }, { 0x03A5, 10 }, + { 0x03B6, 10 }, { 0x070D, 12 }, { 0x03B7, 10 }, { 0x070E, 12 }, + { 0x003C, 6 }, { 0x00EE, 8 }, { 0x3861, 15 }, { 0x3862, 15 }, + { 0x003D, 6 }, { 0x01DE, 9 }, { 0x3863, 15 }, { 0x3864, 15 }, + { 0x3865, 15 }, { 0x007C, 7 }, { 0x070F, 12 }, { 0x03BE, 10 }, + { 0x03BF, 10 }, { 0x3866, 15 }, { 0x0FA0, 12 }, { 0x07D1, 11 }, + { 0x3867, 15 }, { 0x00FB, 8 }, { 0x01F5, 9 }, { 0x7D08, 15 }, + { 0x0FA4, 12 }, { 0x7D09, 15 }, { 0x7D0A, 15 }, { 0x7D0B, 15 }, + { 0x3E86, 14 }, { 0x003F, 6 }, { 0x0FA5, 12 }, { 0x07D3, 11 }, + { 0x3E87, 14 }, + }, + { // 5 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0009, 5 }, { 0x0014, 6 }, { 0x002A, 7 }, { 0x0056, 8 }, + { 0x02B8, 11 }, { 0x00AF, 9 }, { 0x02B9, 11 }, { 0x015D, 10 }, + { 0x02C0, 11 }, { 0x2C10, 15 }, { 0x2C11, 15 }, { 0x2C12, 15 }, + { 0x0006, 4 }, { 0x000E, 5 }, { 0x0017, 6 }, { 0x002D, 7 }, + { 0x000F, 5 }, { 0x0040, 7 }, { 0x0021, 6 }, { 0x0005, 3 }, + { 0x0009, 4 }, { 0x0011, 5 }, { 0x0018, 5 }, { 0x0019, 5 }, + { 0x001A, 5 }, { 0x0036, 6 }, { 0x0037, 6 }, { 0x0041, 7 }, + { 0x0059, 8 }, { 0x00E0, 8 }, { 0x00E1, 8 }, { 0x0071, 7 }, + { 0x00E4, 8 }, { 0x00B1, 9 }, { 0x02C2, 11 }, { 0x001D, 5 }, + { 0x0073, 7 }, { 0x00E5, 8 }, { 0x00F0, 8 }, { 0x0079, 7 }, + { 0x03C4, 10 }, { 0x01E3, 9 }, { 0x01E8, 9 }, { 0x2C13, 15 }, + { 0x007B, 7 }, { 0x2C14, 15 }, { 0x2C15, 15 }, { 0x2C16, 15 }, + { 0x007C, 7 }, { 0x02C3, 11 }, { 0x2C17, 15 }, { 0x160C, 14 }, + { 0x160D, 14 }, { 0x007D, 7 }, { 0x160E, 14 }, { 0x01E9, 9 }, + { 0x03C5, 10 }, { 0x03D4, 10 }, { 0x01EB, 9 }, { 0x160F, 14 }, + { 0x3D50, 14 }, { 0x00FC, 8 }, { 0x07AB, 11 }, { 0x3D51, 14 }, + { 0x3D52, 14 }, { 0x3D53, 14 }, { 0x3D54, 14 }, { 0x01FA, 9 }, + { 0x3D55, 14 }, { 0x007F, 7 }, { 0x01FB, 9 }, { 0x3D56, 14 }, + { 0x3D57, 14 }, + }, + { // 6 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, + { 0x0009, 5 }, { 0x000A, 5 }, { 0x000B, 5 }, { 0x0018, 6 }, + { 0x0032, 7 }, { 0x000D, 5 }, { 0x0033, 7 }, { 0x0E00, 13 }, + { 0x0039, 7 }, { 0x0E01, 13 }, { 0x003A, 7 }, { 0x0E02, 13 }, + { 0x0008, 4 }, { 0x001E, 6 }, { 0x003B, 7 }, { 0x003E, 7 }, + { 0x0012, 5 }, { 0x003F, 7 }, { 0x0013, 5 }, { 0x0028, 6 }, + { 0x0029, 6 }, { 0x0054, 7 }, { 0x002B, 6 }, { 0x0055, 7 }, + { 0x0058, 7 }, { 0x0E03, 13 }, { 0x0059, 7 }, { 0x005A, 7 }, + { 0x0E04, 13 }, { 0x0E05, 13 }, { 0x0703, 12 }, { 0x005B, 7 }, + { 0x005C, 7 }, { 0x0704, 12 }, { 0x0705, 12 }, { 0x005D, 7 }, + { 0x0706, 12 }, { 0x0707, 12 }, { 0x0708, 12 }, { 0x0709, 12 }, + { 0x070A, 12 }, { 0x070B, 12 }, { 0x0018, 5 }, { 0x002F, 6 }, + { 0x000D, 4 }, { 0x0019, 5 }, { 0x070C, 12 }, { 0x0070, 7 }, + { 0x001D, 5 }, { 0x070D, 12 }, { 0x070E, 12 }, { 0x070F, 12 }, + { 0x0710, 12 }, { 0x0039, 6 }, { 0x0711, 12 }, { 0x003C, 6 }, + { 0x0712, 12 }, { 0x0713, 12 }, { 0x0714, 12 }, { 0x0715, 12 }, + { 0x0716, 12 }, { 0x003D, 6 }, { 0x0717, 12 }, { 0x0718, 12 }, + { 0x0719, 12 }, { 0x071A, 12 }, { 0x071B, 12 }, { 0x071C, 12 }, + { 0x071D, 12 }, { 0x001F, 5 }, { 0x071E, 12 }, { 0x0071, 7 }, + { 0x071F, 12 }, + }, + { // 7 + { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x000E, 6 }, + { 0x000F, 6 }, { 0x0040, 8 }, { 0x0041, 8 }, { 0x0042, 8 }, + { 0x0218, 11 }, { 0x2190, 15 }, { 0x2191, 15 }, { 0x2192, 15 }, + { 0x2193, 15 }, { 0x2194, 15 }, { 0x2195, 15 }, { 0x2196, 15 }, + { 0x0005, 4 }, { 0x0011, 6 }, { 0x0024, 7 }, { 0x0087, 9 }, + { 0x000C, 5 }, { 0x004A, 8 }, { 0x004B, 8 }, { 0x0002, 2 }, + { 0x0006, 3 }, { 0x000D, 5 }, { 0x000E, 5 }, { 0x000F, 5 }, + { 0x0013, 6 }, { 0x0038, 6 }, { 0x00E4, 8 }, { 0x00E5, 8 }, + { 0x01CC, 9 }, { 0x00E7, 8 }, { 0x0074, 7 }, { 0x00EA, 8 }, + { 0x01CD, 9 }, { 0x021A, 11 }, { 0x2197, 15 }, { 0x001E, 5 }, + { 0x0076, 7 }, { 0x00EB, 8 }, { 0x01DC, 9 }, { 0x00EF, 8 }, + { 0x01DD, 9 }, { 0x01F0, 9 }, { 0x2198, 15 }, { 0x2199, 15 }, + { 0x00F9, 8 }, { 0x03E2, 10 }, { 0x219A, 15 }, { 0x219B, 15 }, + { 0x00FA, 8 }, { 0x219C, 15 }, { 0x219D, 15 }, { 0x219E, 15 }, + { 0x219F, 15 }, { 0x01F6, 9 }, { 0x21B0, 15 }, { 0x00FC, 8 }, + { 0x01F7, 9 }, { 0x21B1, 15 }, { 0x21B2, 15 }, { 0x21B3, 15 }, + { 0x21B4, 15 }, { 0x01FA, 9 }, { 0x21B5, 15 }, { 0x21B6, 15 }, + { 0x21B7, 15 }, { 0x21B8, 15 }, { 0x21B9, 15 }, { 0x03E3, 10 }, + { 0x10DD, 14 }, { 0x007F, 7 }, { 0x01FB, 9 }, { 0x10DE, 14 }, + { 0x10DF, 14 }, + }, }; #define MAX_AC_VLC_BITS 16 diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index dd705c7..9199f5c 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -1,7 +1,7 @@ /* - * ITU H263 bitstream decoder + * ITU H.263 bitstream decoder * Copyright (c) 2000,2001 Fabrice Bellard - * H263+ support. + * H.263+ support. * Copyright (c) 2001 Juan J. Sierralta P * Copyright (c) 2002-2004 Michael Niedermayer * @@ -24,7 +24,7 @@ /** * @file - * h263 decoder. + * H.263 decoder. */ #include @@ -36,11 +36,15 @@ #include "avcodec.h" #include "mpegvideo.h" #include "h263.h" +#include "h263data.h" +#include "internal.h" #include "mathops.h" #include "mpegutils.h" #include "unary.h" #include "flv.h" +#include "rv10.h" #include "mpeg4video.h" +#include "mpegvideodata.h" // The defines below define the number of bits that are read at once for // reading vlc values. Changing these may improve speed and data cache needs @@ -82,7 +86,7 @@ void ff_h263_show_pict_info(MpegEncContext *s){ s->modified_quant ? " MQ" : "", s->loop_filter ? " LOOP" : "", s->h263_slice_structured ? " SS" : "", - s->avctx->time_base.den, s->avctx->time_base.num + s->avctx->framerate.num, s->avctx->framerate.den ); } } @@ -119,8 +123,8 @@ av_cold void ff_h263_decode_init_vlc(void) INIT_VLC_STATIC(&mv_vlc, MV_VLC_BITS, 33, &ff_mvtab[0][1], 2, 1, &ff_mvtab[0][0], 2, 1, 538); - ff_init_rl(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); - ff_init_rl(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + ff_rl_init(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); + ff_rl_init(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); INIT_VLC_RL(ff_h263_rl_inter, 554); INIT_VLC_RL(ff_rl_intra_aic, 554); INIT_VLC_STATIC(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15, @@ -136,12 +140,12 @@ 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; + 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; } @@ -294,7 +298,7 @@ int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code) if (!s->h263_long_vectors) { val = sign_extend(val, 5 + f_code); } else { - /* horrible h263 long vector mode */ + /* horrible H.263 long vector mode */ if (pred < -31 && val < -63) val += 64; if (pred > 32 && val > 63) @@ -324,7 +328,7 @@ static int h263p_decode_umotion(MpegEncContext * s, int pred) code >>= 1; code = (sign) ? (pred - code) : (pred + code); - av_dlog(s->avctx,"H.263+ UMV Motion = %d\n", code); + ff_dlog(s->avctx,"H.263+ UMV Motion = %d\n", code); return code; } @@ -457,8 +461,7 @@ static int h263_decode_block(MpegEncContext * s, int16_t * block, } } else if (s->mb_intra) { /* DC coef */ - if(s->codec_id == AV_CODEC_ID_RV10){ -#if CONFIG_RV10_DECODER + if (CONFIG_RV10_DECODER && s->codec_id == AV_CODEC_ID_RV10) { if (s->rv10_version == 3 && s->pict_type == AV_PICTURE_TYPE_I) { int component, diff; component = (n <= 3 ? 0 : n - 4 + 1); @@ -478,12 +481,11 @@ static int h263_decode_block(MpegEncContext * s, int16_t * block, if (level == 255) level = 128; } -#endif }else{ level = get_bits(&s->gb, 8); if((level&0x7F) == 0){ av_log(s->avctx, AV_LOG_ERROR, "illegal dc %d at %d %d\n", level, s->mb_x, s->mb_y); - if(s->err_recognition & AV_EF_BITSTREAM) + if (s->avctx->err_recognition & AV_EF_BITSTREAM) return -1; } if (level == 255) @@ -864,7 +866,7 @@ end: return SLICE_OK; } -/* most is hardcoded. should extend to handle all h263 streams */ +/* Most is hardcoded; should extend to handle all H.263 streams. */ int ff_h263_decode_picture_header(MpegEncContext *s) { int format, width, height, i, ret; @@ -898,8 +900,8 @@ int ff_h263_decode_picture_header(MpegEncContext *s) return -1; } if (get_bits1(&s->gb) != 0) { - av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n"); - return -1; /* h263 id */ + av_log(s->avctx, AV_LOG_ERROR, "Bad H.263 id\n"); + return -1; /* H.263 id */ } skip_bits1(&s->gb); /* split screen off */ skip_bits1(&s->gb); /* camera off */ @@ -924,7 +926,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) 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"); + av_log(s->avctx, AV_LOG_ERROR, "H.263 SAC not supported\n"); return -1; /* SAC: off */ } s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ @@ -937,7 +939,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) s->width = width; s->height = height; s->avctx->sample_aspect_ratio= (AVRational){12,11}; - s->avctx->time_base= (AVRational){1001, 30000}; + s->avctx->framerate = (AVRational){ 30000, 1001 }; } else { int ufep; @@ -949,7 +951,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) if (ufep == 1) { /* OPPTYPE */ format = get_bits(&s->gb, 3); - av_dlog(s->avctx, "ufep=1, format: %d\n", format); + ff_dlog(s->avctx, "ufep=1, format: %d\n", format); s->custom_pcf= get_bits1(&s->gb); s->umvplus = get_bits1(&s->gb); /* Unrestricted Motion Vector */ if (get_bits1(&s->gb) != 0) { @@ -1000,7 +1002,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) if (format == 6) { /* Custom Picture Format (CPFMT) */ s->aspect_ratio_info = get_bits(&s->gb, 4); - av_dlog(s->avctx, "aspect: %d\n", s->aspect_ratio_info); + ff_dlog(s->avctx, "aspect: %d\n", s->aspect_ratio_info); /* aspect ratios: 0 - forbidden 1 - 1:1 @@ -1013,9 +1015,9 @@ int ff_h263_decode_picture_header(MpegEncContext *s) width = (get_bits(&s->gb, 9) + 1) * 4; skip_bits1(&s->gb); height = get_bits(&s->gb, 9) * 4; - av_dlog(s->avctx, "\nH.263+ Custom picture: %dx%d\n",width,height); + ff_dlog(s->avctx, "\nH.263+ Custom picture: %dx%d\n",width,height); if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { - /* aspected dimensions */ + /* expected dimensions */ s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 8); s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 8); }else{ @@ -1033,18 +1035,18 @@ int ff_h263_decode_picture_header(MpegEncContext *s) 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){ + s->avctx->framerate.num = 1800000; + s->avctx->framerate.den = 1000 + get_bits1(&s->gb); + s->avctx->framerate.den *= get_bits(&s->gb, 7); + if(s->avctx->framerate.den == 0){ av_log(s, AV_LOG_ERROR, "zero framerate\n"); return -1; } - gcd= av_gcd(s->avctx->time_base.den, s->avctx->time_base.num); - s->avctx->time_base.den /= gcd; - s->avctx->time_base.num /= gcd; + gcd= av_gcd(s->avctx->framerate.den, s->avctx->framerate.num); + s->avctx->framerate.den /= gcd; + s->avctx->framerate.num /= gcd; }else{ - s->avctx->time_base= (AVRational){1001, 30000}; + s->avctx->framerate = (AVRational){ 30000, 1001 }; } } diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 5f15b2f..313f5f3 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -1,7 +1,7 @@ /* - * ITU H263 bitstream encoder + * ITU H.263 bitstream encoder * Copyright (c) 2000,2001 Fabrice Bellard - * H263+ support. + * H.263+ support. * Copyright (c) 2001 Juan J. Sierralta P * Copyright (c) 2002-2004 Michael Niedermayer * @@ -24,7 +24,7 @@ /** * @file - * h263 bitstream encoder. + * H.263 bitstream encoder. */ #include @@ -32,10 +32,11 @@ #include "libavutil/attributes.h" #include "avcodec.h" #include "mpegvideo.h" +#include "mpegvideodata.h" #include "h263.h" +#include "h263data.h" #include "mathops.h" #include "mpegutils.h" -#include "unary.h" #include "flv.h" #include "mpeg4video.h" #include "internal.h" @@ -133,7 +134,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) put_sbits(&s->pb, 8, temp_ref); /* TemporalReference */ put_bits(&s->pb, 1, 1); /* marker */ - put_bits(&s->pb, 1, 0); /* h263 id */ + put_bits(&s->pb, 1, 0); /* H.263 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 */ @@ -149,7 +150,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) 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, 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 { @@ -268,7 +269,7 @@ void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line) } /** - * modify qscale so that encoding is acually possible in h263 (limit difference to -2..2) + * modify qscale so that encoding is actually possible in H.263 (limit difference to -2..2) */ void ff_clean_h263_qscales(MpegEncContext *s){ int i; @@ -459,7 +460,7 @@ void ff_h263_encode_mb(MpegEncContext * s, 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 interleaved_stats = s->avctx->flags & AV_CODEC_FLAG_PASS1; if (!s->mb_intra) { /* compute cbp */ @@ -772,15 +773,15 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) if (!done) { done = 1; - ff_init_rl(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); - ff_init_rl(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + ff_rl_init(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); + ff_rl_init(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); init_uni_h263_rl_tab(&ff_rl_intra_aic, NULL, uni_h263_intra_aic_rl_len); init_uni_h263_rl_tab(&ff_h263_rl_inter , NULL, uni_h263_inter_rl_len); init_mv_penalty_and_fcode(s); } - s->me.mv_penalty= mv_penalty; //FIXME exact table for msmpeg4 & h263p + s->me.mv_penalty= mv_penalty; // FIXME exact table for MSMPEG4 & H.263+ 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; @@ -790,7 +791,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) } s->ac_esc_length= 7+1+6+8; - // use fcodes >1 only for mpeg4 & h263 & h263p FIXME + // use fcodes >1 only for MPEG-4 & H.263 & H.263+ FIXME switch(s->codec_id){ case AV_CODEC_ID_MPEG4: s->fcode_tab= fcode_tab; @@ -806,7 +807,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) s->max_qcoeff= 127; } break; - //Note for mpeg4 & h263 the dc-scale table will be set per frame as needed later + // Note for MPEG-4 & H.263 the dc-scale table will be set per frame as needed later case AV_CODEC_ID_FLV1: if (s->h263_flv > 1) { s->min_qcoeff= -1023; diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi.c similarity index 98% rename from libavcodec/ivi_common.c rename to libavcodec/ivi.c index 7c4d53e..8a59777 100644 --- a/libavcodec/ivi_common.c +++ b/libavcodec/ivi.c @@ -28,14 +28,15 @@ #include -#define BITSTREAM_READER_LE #include "libavutil/attributes.h" #include "libavutil/timer.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" -#include "ivi_common.h" +#include "ivi.h" #include "ivi_dsp.h" /** @@ -563,7 +564,7 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, pos = band->scan[scan_pos]; if (!val) - av_dlog(avctx, "Val = 0 encountered!\n"); + ff_dlog(avctx, "Val = 0 encountered!\n"); q = (base_tab[pos] * quant) >> 9; if (q > 1) @@ -964,7 +965,7 @@ static int decode_band(IVI45DecContext *ctx, (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3)); if (result < 0) break; - av_dlog(avctx, "Empty tile encountered!\n"); + ff_dlog(avctx, "Empty tile encountered!\n"); } else { tile->data_size = ivi_dec_tile_data_size(&ctx->gb); if (!tile->data_size) { @@ -1054,7 +1055,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } if (ctx->gop_flags & IVI5_IS_PROTECTED) { - avpriv_report_missing_feature(avctx, "Password-protected clip!\n"); + avpriv_report_missing_feature(avctx, "Password-protected clip"); return AVERROR_PATCHWELCOME; } @@ -1133,6 +1134,22 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } + if (ctx->show_indeo4_info) { + if (ctx->is_scalable) + av_log(avctx, AV_LOG_DEBUG, "This video uses scalability mode\n"); + if (ctx->uses_tiling) + av_log(avctx, AV_LOG_DEBUG, "This video uses local decoding\n"); + if (ctx->has_b_frames) + av_log(avctx, AV_LOG_DEBUG, "This video contains B-frames\n"); + if (ctx->has_transp) + av_log(avctx, AV_LOG_DEBUG, "Transparency mode is enabled\n"); + if (ctx->uses_haar) + av_log(avctx, AV_LOG_DEBUG, "This video uses Haar transform\n"); + if (ctx->uses_fullpel) + av_log(avctx, AV_LOG_DEBUG, "This video uses fullpel motion vectors\n"); + ctx->show_indeo4_info = 0; + } + return buf_size; } @@ -1148,23 +1165,6 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx) if (ctx->mb_vlc.cust_tab.table) ff_free_vlc(&ctx->mb_vlc.cust_tab); -#if IVI4_STREAM_ANALYSER - if (ctx->is_indeo4) { - if (ctx->is_scalable) - av_log(avctx, AV_LOG_ERROR, "This video uses scalability mode!\n"); - if (ctx->uses_tiling) - av_log(avctx, AV_LOG_ERROR, "This video uses local decoding!\n"); - if (ctx->has_b_frames) - av_log(avctx, AV_LOG_ERROR, "This video contains B-frames!\n"); - if (ctx->has_transp) - av_log(avctx, AV_LOG_ERROR, "Transparency mode is enabled!\n"); - if (ctx->uses_haar) - av_log(avctx, AV_LOG_ERROR, "This video uses Haar transform!\n"); - if (ctx->uses_fullpel) - av_log(avctx, AV_LOG_ERROR, "This video uses fullpel motion vectors!\n"); - } -#endif - av_frame_free(&ctx->p_frame); return 0; diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi.h similarity index 98% rename from libavcodec/ivi_common.h rename to libavcodec/ivi.h index e2cc593..9b4824b 100644 --- a/libavcodec/ivi_common.h +++ b/libavcodec/ivi.h @@ -26,8 +26,8 @@ * Indeo5 decoders. */ -#ifndef AVCODEC_IVI_COMMON_H -#define AVCODEC_IVI_COMMON_H +#ifndef AVCODEC_IVI_H +#define AVCODEC_IVI_H #include "avcodec.h" #include "get_bits.h" @@ -47,7 +47,6 @@ enum { }; #define IVI_VLC_BITS 13 ///< max number of bits of the ivi's huffman codes -#define IVI4_STREAM_ANALYSER 0 #define IVI5_IS_PROTECTED 0x20 /** @@ -219,7 +218,6 @@ typedef struct IVI45DecContext { int prev_frame_type; ///< frame type of the previous frame uint32_t data_size; ///< size of the frame data in bytes from picture header int is_scalable; - int transp_status; ///< transparency mode status: 1 - enabled const uint8_t *frame_data; ///< input frame data pointer int inter_scal; ///< signals a sequence of scalable inter frames uint32_t frame_size; ///< frame size in bytes @@ -249,13 +247,12 @@ typedef struct IVI45DecContext { uint8_t gop_flags; uint32_t lock_word; -#if IVI4_STREAM_ANALYSER + int show_indeo4_info; uint8_t has_b_frames; - uint8_t has_transp; + uint8_t has_transp; ///< transparency mode status: 1 - enabled uint8_t uses_tiling; uint8_t uses_haar; uint8_t uses_fullpel; -#endif int (*decode_pic_hdr) (struct IVI45DecContext *ctx, AVCodecContext *avctx); int (*decode_band_hdr) (struct IVI45DecContext *ctx, IVIBandDesc *band, AVCodecContext *avctx); @@ -340,4 +337,4 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt); int ff_ivi_decode_close(AVCodecContext *avctx); -#endif /* AVCODEC_IVI_COMMON_H */ +#endif /* AVCODEC_IVI_H */ diff --git a/libavcodec/ivi_dsp.c b/libavcodec/ivi_dsp.c index ecc49b3..9b74f73 100644 --- a/libavcodec/ivi_dsp.c +++ b/libavcodec/ivi_dsp.c @@ -22,12 +22,12 @@ /** * @file - * DSP functions (inverse transforms, motion compensation, wavelet recompostions) + * DSP functions (inverse transforms, motion compensation, wavelet recompositions) * for Indeo Video Interactive codecs. */ #include "avcodec.h" -#include "ivi_common.h" +#include "ivi.h" #include "ivi_dsp.h" void ff_ivi_recompose53(const IVIPlaneDesc *plane, uint8_t *dst, @@ -542,8 +542,8 @@ void ff_ivi_inverse_slant_8x8(const int32_t *in, int16_t *out, uint32_t pitch, c } else dst[0] = dst[8] = dst[16] = dst[24] = dst[32] = dst[40] = dst[48] = dst[56] = 0; - src++; - dst++; + src++; + dst++; } #undef COMPENSATE @@ -582,8 +582,8 @@ void ff_ivi_inverse_slant_4x4(const int32_t *in, int16_t *out, uint32_t pitch, c } else dst[0] = dst[4] = dst[8] = dst[12] = 0; - src++; - dst++; + src++; + dst++; } #undef COMPENSATE diff --git a/libavcodec/ivi_dsp.h b/libavcodec/ivi_dsp.h index 11c2f5c..ac9dcbc 100644 --- a/libavcodec/ivi_dsp.h +++ b/libavcodec/ivi_dsp.h @@ -22,15 +22,16 @@ /** * @file - * DSP functions (inverse transforms, motion compensations, wavelet recompostion) + * DSP functions (inverse transforms, motion compensations, wavelet recomposition) * for Indeo Video Interactive codecs. */ #ifndef AVCODEC_IVI_DSP_H #define AVCODEC_IVI_DSP_H -#include "avcodec.h" -#include "ivi_common.h" +#include + +#include "ivi.h" /** * 5/3 wavelet recomposition filter for Indeo5 diff --git a/libavcodec/jfdctint_template.c b/libavcodec/jfdctint_template.c index c6a1638..67fb77b 100644 --- a/libavcodec/jfdctint_template.c +++ b/libavcodec/jfdctint_template.c @@ -69,12 +69,7 @@ #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 /* @@ -216,8 +211,8 @@ static av_always_inline void FUNC(row_fdct)(int16_t *data) tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - dataptr[0] = (int16_t) ((tmp10 + tmp11) << PASS1_BITS); - dataptr[4] = (int16_t) ((tmp10 - tmp11) << PASS1_BITS); + dataptr[0] = (int16_t) ((tmp10 + tmp11) * (1 << PASS1_BITS)); + dataptr[4] = (int16_t) ((tmp10 - tmp11) * (1 << PASS1_BITS)); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[2] = (int16_t) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index fadb5cb..ef5ffa6 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -195,13 +195,246 @@ void ff_jpeg2000_set_significance(Jpeg2000T1Context *t1, int x, int y, static const uint8_t lut_gain[2][4] = { { 0, 0, 0, 0 }, { 0, 1, 1, 2 } }; +static void init_band_stepsize(AVCodecContext *avctx, + Jpeg2000Band *band, + Jpeg2000CodingStyle *codsty, + Jpeg2000QuantStyle *qntsty, + int bandno, int gbandno, int reslevelno, + int cbps) +{ + /* TODO: Implementation of quantization step not finished, + * see ISO/IEC 15444-1:2002 E.1 and A.6.4. */ + switch (qntsty->quantsty) { + uint8_t gain; + int numbps; + case JPEG2000_QSTY_NONE: + /* TODO: to verify. No quantization in this case */ + band->f_stepsize = 1; + break; + case JPEG2000_QSTY_SI: + /*TODO: Compute formula to implement. */ + numbps = cbps + + lut_gain[codsty->transform == FF_DWT53][bandno + (reslevelno > 0)]; + band->f_stepsize = SHL(2048 + qntsty->mant[gbandno], + 2 + numbps - qntsty->expn[gbandno]); + break; + case JPEG2000_QSTY_SE: + /* Exponent quantization step. + * Formula: + * delta_b = 2 ^ (R_b - expn_b) * (1 + (mant_b / 2 ^ 11)) + * R_b = R_I + log2 (gain_b ) + * see ISO/IEC 15444-1:2002 E.1.1 eqn. E-3 and E-4 */ + /* TODO/WARN: value of log2 (gain_b ) not taken into account + * but it works (compared to OpenJPEG). Why? + * Further investigation needed. */ + gain = cbps; + band->f_stepsize = pow(2.0, gain - qntsty->expn[gbandno]); + band->f_stepsize *= qntsty->mant[gbandno] / 2048.0 + 1.0; + break; + default: + band->f_stepsize = 0; + av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n"); + break; + } + /* FIXME: In OpenJPEG code stespize = stepsize * 0.5. Why? + * If not set output of entropic decoder is not correct. */ + if (!av_codec_is_encoder(avctx->codec)) + band->f_stepsize *= 0.5; + + band->i_stepsize = band->f_stepsize * (1 << 16); +} + +static int init_prec(Jpeg2000Band *band, + Jpeg2000ResLevel *reslevel, + Jpeg2000Component *comp, + int precno, int bandno, int reslevelno, + int log2_band_prec_width, + int log2_band_prec_height) +{ + Jpeg2000Prec *prec = band->prec + precno; + int nb_codeblocks, cblkno; + + /* TODO: Explain formula for JPEG200 DCINEMA. */ + /* TODO: Verify with previous count of codeblocks per band */ + + /* Compute P_x0 */ + prec->coord[0][0] = (precno % reslevel->num_precincts_x) * + (1 << log2_band_prec_width); + prec->coord[0][0] = FFMAX(prec->coord[0][0], band->coord[0][0]); + + /* Compute P_y0 */ + prec->coord[1][0] = (precno / reslevel->num_precincts_x) * + (1 << log2_band_prec_height); + prec->coord[1][0] = FFMAX(prec->coord[1][0], band->coord[1][0]); + + /* Compute P_x1 */ + prec->coord[0][1] = prec->coord[0][0] + + (1 << log2_band_prec_width); + prec->coord[0][1] = FFMIN(prec->coord[0][1], band->coord[0][1]); + + /* Compute P_y1 */ + prec->coord[1][1] = prec->coord[1][0] + + (1 << log2_band_prec_height); + prec->coord[1][1] = FFMIN(prec->coord[1][1], band->coord[1][1]); + + prec->nb_codeblocks_width = + ff_jpeg2000_ceildivpow2(prec->coord[0][1] - + prec->coord[0][0], + band->log2_cblk_width); + prec->nb_codeblocks_height = + ff_jpeg2000_ceildivpow2(prec->coord[1][1] - + prec->coord[1][0], + band->log2_cblk_height); + + /* Tag trees initialization */ + prec->cblkincl = + ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width, + prec->nb_codeblocks_height); + if (!prec->cblkincl) + return AVERROR(ENOMEM); + + prec->zerobits = + ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width, + prec->nb_codeblocks_height); + if (!prec->zerobits) + return AVERROR(ENOMEM); + + nb_codeblocks = prec->nb_codeblocks_width * prec->nb_codeblocks_height; + prec->cblk = av_mallocz_array(nb_codeblocks, sizeof(*prec->cblk)); + if (!prec->cblk) + return AVERROR(ENOMEM); + for (cblkno = 0; cblkno < nb_codeblocks; cblkno++) { + Jpeg2000Cblk *cblk = prec->cblk + cblkno; + uint16_t Cx0, Cy0; + + /* Compute coordinates of codeblocks */ + /* Compute Cx0*/ + Cx0 = (prec->coord[0][0] >> band->log2_cblk_width) << band->log2_cblk_width; + Cx0 = Cx0 + ((cblkno % prec->nb_codeblocks_width) << band->log2_cblk_width); + cblk->coord[0][0] = FFMAX(Cx0, prec->coord[0][0]); + + /* Compute Cy0*/ + Cy0 = (prec->coord[1][0] >> band->log2_cblk_height) << band->log2_cblk_height; + Cy0 = Cy0 + ((cblkno / prec->nb_codeblocks_width) << band->log2_cblk_height); + cblk->coord[1][0] = FFMAX(Cy0, prec->coord[1][0]); + + /* Compute Cx1 */ + cblk->coord[0][1] = FFMIN(Cx0 + (1 << band->log2_cblk_width), + prec->coord[0][1]); + + /* Compute Cy1 */ + cblk->coord[1][1] = FFMIN(Cy0 + (1 << band->log2_cblk_height), + prec->coord[1][1]); + /* Update code-blocks coordinates according sub-band position */ + if ((bandno + !!reslevelno) & 1) { + cblk->coord[0][0] += comp->reslevel[reslevelno-1].coord[0][1] - + comp->reslevel[reslevelno-1].coord[0][0]; + cblk->coord[0][1] += comp->reslevel[reslevelno-1].coord[0][1] - + comp->reslevel[reslevelno-1].coord[0][0]; + } + if ((bandno + !!reslevelno) & 2) { + cblk->coord[1][0] += comp->reslevel[reslevelno-1].coord[1][1] - + comp->reslevel[reslevelno-1].coord[1][0]; + cblk->coord[1][1] += comp->reslevel[reslevelno-1].coord[1][1] - + comp->reslevel[reslevelno-1].coord[1][0]; + } + + cblk->zero = 0; + cblk->lblock = 3; + cblk->length = 0; + cblk->lengthinc = 0; + cblk->npasses = 0; + } + + return 0; +} + +static int init_band(AVCodecContext *avctx, + Jpeg2000ResLevel *reslevel, + Jpeg2000Component *comp, + Jpeg2000CodingStyle *codsty, + Jpeg2000QuantStyle *qntsty, + int bandno, int gbandno, int reslevelno, + int cbps, int dx, int dy) +{ + Jpeg2000Band *band = reslevel->band + bandno; + uint8_t log2_band_prec_width, log2_band_prec_height; + int declvl = codsty->nreslevels - reslevelno; // N_L -r see ISO/IEC 15444-1:2002 B.5 + int precno; + int nb_precincts; + int i, j, ret; + + init_band_stepsize(avctx, band, codsty, qntsty, bandno, gbandno, reslevelno, cbps); + + + /* computation of tbx_0, tbx_1, tby_0, tby_1 + * see ISO/IEC 15444-1:2002 B.5 eq. B-15 and tbl B.1 + * codeblock width and height is computed for + * DCI JPEG 2000 codeblock_width = codeblock_width = 32 = 2 ^ 5 */ + if (reslevelno == 0) { + /* for reslevelno = 0, only one band, x0_b = y0_b = 0 */ + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + band->coord[i][j] = + ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0], + declvl - 1); + log2_band_prec_width = reslevel->log2_prec_width; + log2_band_prec_height = reslevel->log2_prec_height; + /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ + band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, + reslevel->log2_prec_width); + band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, + reslevel->log2_prec_height); + } else { + /* 3 bands x0_b = 1 y0_b = 0; x0_b = 0 y0_b = 1; x0_b = y0_b = 1 */ + /* x0_b and y0_b are computed with ((bandno + 1 >> i) & 1) */ + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + /* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */ + band->coord[i][j] = + ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0] - + (((bandno + 1 >> i) & 1) << declvl - 1), + declvl); + /* TODO: Manage case of 3 band offsets here or + * in coding/decoding function? */ + + /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ + band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, + reslevel->log2_prec_width - 1); + band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, + reslevel->log2_prec_height - 1); + + log2_band_prec_width = reslevel->log2_prec_width - 1; + log2_band_prec_height = reslevel->log2_prec_height - 1; + } + + for (j = 0; j < 2; j++) + band->coord[0][j] = ff_jpeg2000_ceildiv(band->coord[0][j], dx); + for (j = 0; j < 2; j++) + band->coord[1][j] = ff_jpeg2000_ceildiv(band->coord[1][j], dy); + + nb_precincts = reslevel->num_precincts_x * reslevel->num_precincts_y; + band->prec = av_mallocz_array(nb_precincts, sizeof(*band->prec)); + if (!band->prec) + return AVERROR(ENOMEM); + + for (precno = 0; precno < nb_precincts; precno++) { + ret = init_prec(band, reslevel, comp, + precno, bandno, reslevelno, + log2_band_prec_width, log2_band_prec_height); + if (ret < 0) + return ret; + } + + return 0; +} + int ff_jpeg2000_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, Jpeg2000QuantStyle *qntsty, int cbps, int dx, int dy, AVCodecContext *avctx) { - uint8_t log2_band_prec_width, log2_band_prec_height; int reslevelno, bandno, gbandno = 0, ret, i, j; uint32_t csize; @@ -254,7 +487,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp, else reslevel->nbands = 3; - /* Number of precincts wich span the tile for resolution level reslevelno + /* Number of precincts which span the tile for resolution level reslevelno * see B.6 in ISO/IEC 15444-1:2002 eq. B-16 * num_precincts_x = |- trx_1 / 2 ^ log2_prec_width) -| - (trx_0 / 2 ^ log2_prec_width) * num_precincts_y = |- try_1 / 2 ^ log2_prec_width) -| - (try_0 / 2 ^ log2_prec_width) @@ -282,201 +515,12 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp, return AVERROR(ENOMEM); for (bandno = 0; bandno < reslevel->nbands; bandno++, gbandno++) { - Jpeg2000Band *band = reslevel->band + bandno; - int cblkno, precno; - int nb_precincts; - - /* TODO: Implementation of quantization step not finished, - * see ISO/IEC 15444-1:2002 E.1 and A.6.4. */ - switch (qntsty->quantsty) { - uint8_t gain; - int numbps; - case JPEG2000_QSTY_NONE: - /* TODO: to verify. No quantization in this case */ - band->f_stepsize = 1; - break; - case JPEG2000_QSTY_SI: - /*TODO: Compute formula to implement. */ - numbps = cbps + - lut_gain[codsty->transform == FF_DWT53][bandno + (reslevelno > 0)]; - band->f_stepsize = SHL(2048 + qntsty->mant[gbandno], - 2 + numbps - qntsty->expn[gbandno]); - break; - case JPEG2000_QSTY_SE: - /* Exponent quantization step. - * Formula: - * delta_b = 2 ^ (R_b - expn_b) * (1 + (mant_b / 2 ^ 11)) - * R_b = R_I + log2 (gain_b ) - * see ISO/IEC 15444-1:2002 E.1.1 eqn. E-3 and E-4 */ - /* TODO/WARN: value of log2 (gain_b ) not taken into account - * but it works (compared to OpenJPEG). Why? - * Further investigation needed. */ - gain = cbps; - band->f_stepsize = pow(2.0, gain - qntsty->expn[gbandno]); - band->f_stepsize *= qntsty->mant[gbandno] / 2048.0 + 1.0; - break; - default: - band->f_stepsize = 0; - av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n"); - break; - } - /* FIXME: In openjepg code stespize = stepsize * 0.5. Why? - * If not set output of entropic decoder is not correct. */ - if (!av_codec_is_encoder(avctx->codec)) - band->f_stepsize *= 0.5; - - band->i_stepsize = band->f_stepsize * (1 << 16); - - /* computation of tbx_0, tbx_1, tby_0, tby_1 - * see ISO/IEC 15444-1:2002 B.5 eq. B-15 and tbl B.1 - * codeblock width and height is computed for - * DCI JPEG 2000 codeblock_width = codeblock_width = 32 = 2 ^ 5 */ - if (reslevelno == 0) { - /* for reslevelno = 0, only one band, x0_b = y0_b = 0 */ - for (i = 0; i < 2; i++) - for (j = 0; j < 2; j++) - band->coord[i][j] = - ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0], - declvl - 1); - log2_band_prec_width = reslevel->log2_prec_width; - log2_band_prec_height = reslevel->log2_prec_height; - /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ - band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, - reslevel->log2_prec_width); - band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, - reslevel->log2_prec_height); - } else { - /* 3 bands x0_b = 1 y0_b = 0; x0_b = 0 y0_b = 1; x0_b = y0_b = 1 */ - /* x0_b and y0_b are computed with ((bandno + 1 >> i) & 1) */ - for (i = 0; i < 2; i++) - for (j = 0; j < 2; j++) - /* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */ - band->coord[i][j] = - ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0] - - (((bandno + 1 >> i) & 1) << declvl - 1), - declvl); - /* TODO: Manage case of 3 band offsets here or - * in coding/decoding function? */ - - /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ - band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, - reslevel->log2_prec_width - 1); - band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, - reslevel->log2_prec_height - 1); - - log2_band_prec_width = reslevel->log2_prec_width - 1; - log2_band_prec_height = reslevel->log2_prec_height - 1; - } - - for (j = 0; j < 2; j++) - band->coord[0][j] = ff_jpeg2000_ceildiv(band->coord[0][j], dx); - for (j = 0; j < 2; j++) - band->coord[1][j] = ff_jpeg2000_ceildiv(band->coord[1][j], dy); - - band->prec = av_mallocz_array(reslevel->num_precincts_x * - reslevel->num_precincts_y, - sizeof(*band->prec)); - if (!band->prec) - return AVERROR(ENOMEM); - - nb_precincts = reslevel->num_precincts_x * reslevel->num_precincts_y; - - for (precno = 0; precno < nb_precincts; precno++) { - Jpeg2000Prec *prec = band->prec + precno; - - /* TODO: Explain formula for JPEG200 DCINEMA. */ - /* TODO: Verify with previous count of codeblocks per band */ - - /* Compute P_x0 */ - prec->coord[0][0] = (precno % reslevel->num_precincts_x) * - (1 << log2_band_prec_width); - prec->coord[0][0] = FFMAX(prec->coord[0][0], band->coord[0][0]); - - /* Compute P_y0 */ - prec->coord[1][0] = (precno / reslevel->num_precincts_x) * - (1 << log2_band_prec_height); - prec->coord[1][0] = FFMAX(prec->coord[1][0], band->coord[1][0]); - - /* Compute P_x1 */ - prec->coord[0][1] = prec->coord[0][0] + - (1 << log2_band_prec_width); - prec->coord[0][1] = FFMIN(prec->coord[0][1], band->coord[0][1]); - - /* Compute P_y1 */ - prec->coord[1][1] = prec->coord[1][0] + - (1 << log2_band_prec_height); - prec->coord[1][1] = FFMIN(prec->coord[1][1], band->coord[1][1]); - - prec->nb_codeblocks_width = - ff_jpeg2000_ceildivpow2(prec->coord[0][1] - - prec->coord[0][0], - band->log2_cblk_width); - prec->nb_codeblocks_height = - ff_jpeg2000_ceildivpow2(prec->coord[1][1] - - prec->coord[1][0], - band->log2_cblk_height); - - /* Tag trees initialization */ - prec->cblkincl = - ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width, - prec->nb_codeblocks_height); - if (!prec->cblkincl) - return AVERROR(ENOMEM); - - prec->zerobits = - ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width, - prec->nb_codeblocks_height); - if (!prec->zerobits) - return AVERROR(ENOMEM); - - prec->cblk = av_mallocz_array(prec->nb_codeblocks_width * - prec->nb_codeblocks_height, - sizeof(*prec->cblk)); - if (!prec->cblk) - return AVERROR(ENOMEM); - for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) { - Jpeg2000Cblk *cblk = prec->cblk + cblkno; - uint16_t Cx0, Cy0; - - /* Compute coordinates of codeblocks */ - /* Compute Cx0*/ - Cx0 = (prec->coord[0][0] >> band->log2_cblk_width) << band->log2_cblk_width; - Cx0 = Cx0 + ((cblkno % prec->nb_codeblocks_width) << band->log2_cblk_width); - cblk->coord[0][0] = FFMAX(Cx0, prec->coord[0][0]); - - /* Compute Cy0*/ - Cy0 = (prec->coord[1][0] >> band->log2_cblk_height) << band->log2_cblk_height; - Cy0 = Cy0 + ((cblkno / prec->nb_codeblocks_width) << band->log2_cblk_height); - cblk->coord[1][0] = FFMAX(Cy0, prec->coord[1][0]); - - /* Compute Cx1 */ - cblk->coord[0][1] = FFMIN(Cx0 + (1 << band->log2_cblk_width), - prec->coord[0][1]); - - /* Compute Cy1 */ - cblk->coord[1][1] = FFMIN(Cy0 + (1 << band->log2_cblk_height), - prec->coord[1][1]); - /* Update code-blocks coordinates according sub-band position */ - if ((bandno + !!reslevelno) & 1) { - cblk->coord[0][0] += comp->reslevel[reslevelno-1].coord[0][1] - - comp->reslevel[reslevelno-1].coord[0][0]; - cblk->coord[0][1] += comp->reslevel[reslevelno-1].coord[0][1] - - comp->reslevel[reslevelno-1].coord[0][0]; - } - if ((bandno + !!reslevelno) & 2) { - cblk->coord[1][0] += comp->reslevel[reslevelno-1].coord[1][1] - - comp->reslevel[reslevelno-1].coord[1][0]; - cblk->coord[1][1] += comp->reslevel[reslevelno-1].coord[1][1] - - comp->reslevel[reslevelno-1].coord[1][0]; - } - - cblk->zero = 0; - cblk->lblock = 3; - cblk->length = 0; - cblk->lengthinc = 0; - cblk->npasses = 0; - } - } + ret = init_band(avctx, reslevel, + comp, codsty, qntsty, + bandno, gbandno, reslevelno, + cbps, dx, dy); + if (ret < 0) + return ret; } } return 0; diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index aed9b2b..deab1e8 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -35,6 +35,8 @@ #include "internal.h" #include "thread.h" #include "jpeg2000.h" +#include "jpeg2000dsp.h" +#include "profiles.h" #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -85,6 +87,7 @@ typedef struct Jpeg2000DecoderContext { int16_t curtileno; Jpeg2000Tile *tile; + Jpeg2000DSPContext dsp; /*options parameters*/ int reduction_factor; @@ -311,7 +314,7 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) } c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type /* set integer 9/7 DWT in case of BITEXACT flag */ - if ((s->avctx->flags & CODEC_FLAG_BITEXACT) && (c->transform == FF_DWT97)) + if ((s->avctx->flags & AV_CODEC_FLAG_BITEXACT) && (c->transform == FF_DWT97)) c->transform = FF_DWT97_INT; if (c->csty & JPEG2000_CSTY_PREC) { @@ -730,85 +733,103 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, return 0; } -static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) +static int decode_pgod_lrcp(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) { - int ret = 0; int layno, reslevelno, compno, precno, ok_reslevel; - int x, y; - - s->bit_index = 8; - switch (tile->codsty[0].prog_order) { - case JPEG2000_PGOD_LRCP: - for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { - ok_reslevel = 1; - for (reslevelno = 0; ok_reslevel; reslevelno++) { - ok_reslevel = 0; - for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000CodingStyle *codsty = tile->codsty + compno; - Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; - if (reslevelno < codsty->nreslevels) { - Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel + - reslevelno; - ok_reslevel = 1; - for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) - if ((ret = jpeg2000_decode_packet(s, - codsty, rlevel, - precno, layno, - qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), - qntsty->nguardbits)) < 0) - return ret; - } + int ret; + + for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { + ok_reslevel = 1; + for (reslevelno = 0; ok_reslevel; reslevelno++) { + ok_reslevel = 0; + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; + if (reslevelno < codsty->nreslevels) { + Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel + + reslevelno; + ok_reslevel = 1; + for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) + if ((ret = jpeg2000_decode_packet(s, + codsty, rlevel, + precno, layno, + qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), + qntsty->nguardbits)) < 0) + return ret; } } } - break; + } - case JPEG2000_PGOD_CPRL: - for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000CodingStyle *codsty = tile->codsty + compno; - Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; + return 0; +} + +static int decode_pgod_cprl(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) +{ + int layno, reslevelno, compno, precno; + int ret, x, y; - /* Set bit stream buffer address according to tile-part. - * For DCinema one tile-part per component, so can be - * indexed by component. */ - s->g = tile->tile_part[compno].tpg; + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; + + /* Set bit stream buffer address according to tile-part. + * For DCinema one tile-part per component, so can be + * indexed by component. */ + s->g = tile->tile_part[compno].tpg; + /* Position loop (y axis) + * TODO: Automate computing of step 256. + * Fixed here, but to be computed before entering here. */ + for (y = 0; y < s->height; y += 256) { /* Position loop (y axis) - * TODO: Automate computing of step 256. + * TODO: automate computing of step 256. * Fixed here, but to be computed before entering here. */ - for (y = 0; y < s->height; y += 256) { - /* Position loop (y axis) - * TODO: automate computing of step 256. - * Fixed here, but to be computed before entering here. */ - for (x = 0; x < s->width; x += 256) { - for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { - uint16_t prcx, prcy; - uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r - Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel + reslevelno; - - if (!((y % (1 << (rlevel->log2_prec_height + reducedresno)) == 0) || - (y == 0))) // TODO: 2nd condition simplified as try0 always =0 for dcinema - continue; - - if (!((x % (1 << (rlevel->log2_prec_width + reducedresno)) == 0) || - (x == 0))) // TODO: 2nd condition simplified as try0 always =0 for dcinema - continue; - - // check if a precinct exists - prcx = ff_jpeg2000_ceildivpow2(x, reducedresno) >> rlevel->log2_prec_width; - prcy = ff_jpeg2000_ceildivpow2(y, reducedresno) >> rlevel->log2_prec_height; - precno = prcx + rlevel->num_precincts_x * prcy; - for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { - if ((ret = jpeg2000_decode_packet(s, codsty, rlevel, - precno, layno, - qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), - qntsty->nguardbits)) < 0) - return ret; - } + for (x = 0; x < s->width; x += 256) { + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { + uint16_t prcx, prcy; + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel + reslevelno; + + if (!((y % (1 << (rlevel->log2_prec_height + reducedresno)) == 0) || + (y == 0))) // TODO: 2nd condition simplified as try0 always =0 for dcinema + continue; + + if (!((x % (1 << (rlevel->log2_prec_width + reducedresno)) == 0) || + (x == 0))) // TODO: 2nd condition simplified as try0 always =0 for dcinema + continue; + + // check if a precinct exists + prcx = ff_jpeg2000_ceildivpow2(x, reducedresno) >> rlevel->log2_prec_width; + prcy = ff_jpeg2000_ceildivpow2(y, reducedresno) >> rlevel->log2_prec_height; + precno = prcx + rlevel->num_precincts_x * prcy; + for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { + if ((ret = jpeg2000_decode_packet(s, codsty, rlevel, + precno, layno, + qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), + qntsty->nguardbits)) < 0) + return ret; } } } } + } + + return 0; +} + +static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) +{ + int ret = 0; + + s->bit_index = 8; + switch (tile->codsty[0].prog_order) { + case JPEG2000_PGOD_LRCP: + ret = decode_pgod_lrcp(s, tile); + break; + + case JPEG2000_PGOD_CPRL: + ret = decode_pgod_cprl(s, tile); break; case JPEG2000_PGOD_RLCP: @@ -1041,79 +1062,29 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk, } } -/* Inverse ICT parameters in float and integer. - * int value = (float value) * (1<<16) */ -static const float f_ict_params[4] = { - 1.402f, - 0.34413f, - 0.71414f, - 1.772f -}; -static const int i_ict_params[4] = { - 91881, - 22553, - 46802, - 116130 -}; - -static void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) +static inline void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) { int i, csize = 1; - int32_t *src[3], i0, i1, i2; - float *srcf[3], i0f, i1f, i2f; + void *src[3]; for (i = 0; i < 3; i++) if (tile->codsty[0].transform == FF_DWT97) - srcf[i] = tile->comp[i].f_data; + src[i] = tile->comp[i].f_data; else - src [i] = tile->comp[i].i_data; + src[i] = tile->comp[i].i_data; for (i = 0; i < 2; i++) csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0]; - switch (tile->codsty[0].transform) { - case FF_DWT97: - for (i = 0; i < csize; i++) { - i0f = *srcf[0] + (f_ict_params[0] * *srcf[2]); - i1f = *srcf[0] - (f_ict_params[1] * *srcf[1]) - - (f_ict_params[2] * *srcf[2]); - i2f = *srcf[0] + (f_ict_params[3] * *srcf[1]); - *srcf[0]++ = i0f; - *srcf[1]++ = i1f; - *srcf[2]++ = i2f; - } - break; - case FF_DWT97_INT: - for (i = 0; i < csize; i++) { - i0 = *src[0] + (((i_ict_params[0] * *src[2]) + (1 << 15)) >> 16); - i1 = *src[0] - (((i_ict_params[1] * *src[1]) + (1 << 15)) >> 16) - - (((i_ict_params[2] * *src[2]) + (1 << 15)) >> 16); - i2 = *src[0] + (((i_ict_params[3] * *src[1]) + (1 << 15)) >> 16); - *src[0]++ = i0; - *src[1]++ = i1; - *src[2]++ = i2; - } - break; - case FF_DWT53: - for (i = 0; i < csize; i++) { - i1 = *src[0] - (*src[2] + *src[1] >> 2); - i0 = i1 + *src[2]; - i2 = i1 + *src[1]; - *src[0]++ = i0; - *src[1]++ = i1; - *src[2]++ = i2; - } - break; - } + + s->dsp.mct_decode[tile->codsty[0].transform](src[0], src[1], src[2], csize); } -static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, - AVFrame *picture) +static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) { + Jpeg2000T1Context t1; + int compno, reslevelno, bandno; - int x, y; - uint8_t *line; - Jpeg2000T1Context t1; /* Loop on tile components */ for (compno = 0; compno < s->ncomponents; compno++) { @@ -1139,7 +1110,9 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, Jpeg2000Prec *prec = band->prec + precno; /* Loop on codeblocks */ - for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) { + for (cblkno = 0; + cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; + cblkno++) { int x, y; Jpeg2000Cblk *cblk = prec->cblk + cblkno; decode_cblk(s, codsty, &t1, cblk, @@ -1162,90 +1135,76 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, /* inverse DWT */ ff_dwt_decode(&comp->dwt, codsty->transform == FF_DWT97 ? (void*)comp->f_data : (void*)comp->i_data); } /*end comp */ +} + +#define WRITE_FRAME(D, PIXEL) \ + static inline void write_frame_ ## D(Jpeg2000DecoderContext * s, Jpeg2000Tile * tile, \ + AVFrame * picture) \ + { \ + int linesize = picture->linesize[0] / sizeof(PIXEL); \ + int compno; \ + int x, y; \ + \ + for (compno = 0; compno < s->ncomponents; compno++) { \ + Jpeg2000Component *comp = tile->comp + compno; \ + Jpeg2000CodingStyle *codsty = tile->codsty + compno; \ + PIXEL *line; \ + float *datap = comp->f_data; \ + int32_t *i_datap = comp->i_data; \ + int cbps = s->cbps[compno]; \ + int w = tile->comp[compno].coord[0][1] - s->image_offset_x; \ + \ + y = tile->comp[compno].coord[1][0] - s->image_offset_y; \ + line = (PIXEL *)picture->data[0] + y * linesize; \ + for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) { \ + PIXEL *dst; \ + \ + x = tile->comp[compno].coord[0][0] - s->image_offset_x; \ + dst = line + x * s->ncomponents + compno; \ + \ + if (codsty->transform == FF_DWT97) { \ + for (; x < w; x += s->cdx[compno]) { \ + int val = lrintf(*datap) + (1 << (cbps - 1)); \ + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ \ + val = av_clip(val, 0, (1 << cbps) - 1); \ + *dst = val << (8 * sizeof(PIXEL) - cbps); \ + datap++; \ + dst += s->ncomponents; \ + } \ + } else { \ + for (; x < w; x += s->cdx[compno]) { \ + int val = *i_datap + (1 << (cbps - 1)); \ + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ \ + val = av_clip(val, 0, (1 << cbps) - 1); \ + *dst = val << (8 * sizeof(PIXEL) - cbps); \ + i_datap++; \ + dst += s->ncomponents; \ + } \ + } \ + line += linesize; \ + } \ + } \ + \ + } + +WRITE_FRAME(8, uint8_t) +WRITE_FRAME(16, uint16_t) + +#undef WRITE_FRAME + +static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, + AVFrame *picture) +{ + tile_codeblocks(s, tile); /* inverse MCT transformation */ if (tile->codsty[0].mct) mct_decode(s, tile); if (s->precision <= 8) { - for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000Component *comp = tile->comp + compno; - Jpeg2000CodingStyle *codsty = tile->codsty + compno; - float *datap = comp->f_data; - int32_t *i_datap = comp->i_data; - int cbps = s->cbps[compno]; - int w = tile->comp[compno].coord[0][1] - s->image_offset_x; - - y = tile->comp[compno].coord[1][0] - s->image_offset_y; - line = picture->data[0] + y * picture->linesize[0]; - for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) { - uint8_t *dst; - - x = tile->comp[compno].coord[0][0] - s->image_offset_x; - dst = line + x * s->ncomponents + compno; - - if (codsty->transform == FF_DWT97) { - for (; x < w; x += s->cdx[compno]) { - int val = lrintf(*datap) + (1 << (cbps - 1)); - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - val = av_clip(val, 0, (1 << cbps) - 1); - *dst = val << (8 - cbps); - datap++; - dst += s->ncomponents; - } - } else { - for (; x < w; x += s->cdx[compno]) { - int val = *i_datap + (1 << (cbps - 1)); - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - val = av_clip(val, 0, (1 << cbps) - 1); - *dst = val << (8 - cbps); - i_datap++; - dst += s->ncomponents; - } - } - line += picture->linesize[0]; - } - } + write_frame_8(s, tile, picture); } else { - for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000Component *comp = tile->comp + compno; - Jpeg2000CodingStyle *codsty = tile->codsty + compno; - float *datap = comp->f_data; - int32_t *i_datap = comp->i_data; - uint16_t *linel; - int cbps = s->cbps[compno]; - int w = tile->comp[compno].coord[0][1] - s->image_offset_x; - - y = tile->comp[compno].coord[1][0] - s->image_offset_y; - linel = (uint16_t *)picture->data[0] + y * (picture->linesize[0] >> 1); - for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) { - uint16_t *dst; - x = tile->comp[compno].coord[0][0] - s->image_offset_x; - dst = linel + (x * s->ncomponents + compno); - if (codsty->transform == FF_DWT97) { - for (; x < w; x += s-> cdx[compno]) { - int val = lrintf(*datap) + (1 << (cbps - 1)); - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - val = av_clip(val, 0, (1 << cbps) - 1); - /* align 12 bit values in little-endian mode */ - *dst = val << (16 - cbps); - datap++; - dst += s->ncomponents; - } - } else { - for (; x < w; x += s-> cdx[compno]) { - int val = *i_datap + (1 << (cbps - 1)); - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - val = av_clip(val, 0, (1 << cbps) - 1); - /* align 12 bit values in little-endian mode */ - *dst = val << (16 - cbps); - i_datap++; - dst += s->ncomponents; - } - } - linel += picture->linesize[0] >> 1; - } - } + write_frame_16(s, tile, picture); } return 0; @@ -1336,6 +1295,10 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) properties = s->tile[s->curtileno].properties; } break; + case JPEG2000_PLT: + // the PLT marker is ignored + case JPEG2000_PLM: + // the PLM marker is ignored case JPEG2000_COM: // the comment is ignored bytestream2_skip(&s->g, len - 2); @@ -1406,6 +1369,15 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) return 0; } +static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) +{ + Jpeg2000DecoderContext *s = avctx->priv_data; + + ff_jpeg2000dsp_init(&s->dsp); + + return 0; +} + static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -1486,15 +1458,6 @@ static const AVOption options[] = { { NULL }, }; -static const AVProfile profiles[] = { - { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0, "JPEG 2000 codestream restriction 0" }, - { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1, "JPEG 2000 codestream restriction 1" }, - { FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION, "JPEG 2000 no codestream restrictions" }, - { FF_PROFILE_JPEG2000_DCINEMA_2K, "JPEG 2000 digital cinema 2K" }, - { FF_PROFILE_JPEG2000_DCINEMA_4K, "JPEG 2000 digital cinema 4K" }, - { FF_PROFILE_UNKNOWN }, -}; - static const AVClass class = { .class_name = "jpeg2000", .item_name = av_default_item_name, @@ -1507,10 +1470,11 @@ AVCodec ff_jpeg2000_decoder = { .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_JPEG2000, - .capabilities = CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(Jpeg2000DecoderContext), .init_static_data = jpeg2000_init_static_data, + .init = jpeg2000_decode_init, .decode = jpeg2000_decode_frame, .priv_class = &class, - .profiles = NULL_IF_CONFIG_SMALL(profiles) + .profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles) }; diff --git a/libavcodec/jpeg2000dsp.c b/libavcodec/jpeg2000dsp.c new file mode 100644 index 0000000..6e04c3a --- /dev/null +++ b/libavcodec/jpeg2000dsp.c @@ -0,0 +1,98 @@ +/* + * JPEG 2000 DSP functions + * Copyright (c) 2007 Kamil Nowosad + * Copyright (c) 2013 Nicolas Bertrand + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "jpeg2000dsp.h" + +/* Inverse ICT parameters in float and integer. + * int value = (float value) * (1<<16) */ +static const float f_ict_params[4] = { + 1.402f, + 0.34413f, + 0.71414f, + 1.772f +}; + +static const int i_ict_params[4] = { + 91881, + 22553, + 46802, + 116130 +}; + +static void ict_float(void *_src0, void *_src1, void *_src2, int csize) +{ + float *src0 = _src0, *src1 = _src1, *src2 = _src2; + float i0f, i1f, i2f; + int i; + + for (i = 0; i < csize; i++) { + i0f = *src0 + (f_ict_params[0] * *src2); + i1f = *src0 - (f_ict_params[1] * *src1) + - (f_ict_params[2] * *src2); + i2f = *src0 + (f_ict_params[3] * *src1); + *src0++ = i0f; + *src1++ = i1f; + *src2++ = i2f; + } +} + +static void ict_int(void *_src0, void *_src1, void *_src2, int csize) +{ + int32_t *src0 = _src0, *src1 = _src1, *src2 = _src2; + int32_t i0, i1, i2; + int i; + + for (i = 0; i < csize; i++) { + i0 = *src0 + (((i_ict_params[0] * *src2) + (1 << 15)) >> 16); + i1 = *src0 - (((i_ict_params[1] * *src1) + (1 << 15)) >> 16) + - (((i_ict_params[2] * *src2) + (1 << 15)) >> 16); + i2 = *src0 + (((i_ict_params[3] * *src1) + (1 << 15)) >> 16); + *src0++ = i0; + *src1++ = i1; + *src2++ = i2; + } +} + +static void rct_int(void *_src0, void *_src1, void *_src2, int csize) +{ + int32_t *src0 = _src0, *src1 = _src1, *src2 = _src2; + int32_t i0, i1, i2; + int i; + + for (i = 0; i < csize; i++) { + i1 = *src0 - (*src2 + *src1 >> 2); + i0 = i1 + *src2; + i2 = i1 + *src1; + *src0++ = i0; + *src1++ = i1; + *src2++ = i2; + } +} + +av_cold void ff_jpeg2000dsp_init(Jpeg2000DSPContext *c) +{ + c->mct_decode[FF_DWT97] = ict_float; + c->mct_decode[FF_DWT53] = rct_int; + c->mct_decode[FF_DWT97_INT] = ict_int; +} diff --git a/libavcodec/jpeg2000dsp.h b/libavcodec/jpeg2000dsp.h new file mode 100644 index 0000000..45a32c0 --- /dev/null +++ b/libavcodec/jpeg2000dsp.h @@ -0,0 +1,35 @@ +/* + * JPEG 2000 DSP functions + * Copyright (c) 2007 Kamil Nowosad + * Copyright (c) 2013 Nicolas Bertrand + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_JPEG2000DSP_H +#define AVCODEC_JPEG2000DSP_H + +#include +#include "jpeg2000dwt.h" + +typedef struct Jpeg2000DSPContext { + void (*mct_decode[FF_DWT_NB])(void *src0, void *src1, void *src2, int csize); +} Jpeg2000DSPContext; + +void ff_jpeg2000dsp_init(Jpeg2000DSPContext *c); + +#endif /* AVCODEC_JPEG2000DSP_H */ diff --git a/libavcodec/jpeg2000dwt.h b/libavcodec/jpeg2000dwt.h index 9aaa18b..f08340d 100644 --- a/libavcodec/jpeg2000dwt.h +++ b/libavcodec/jpeg2000dwt.h @@ -34,7 +34,8 @@ enum DWTType { FF_DWT97, FF_DWT53, - FF_DWT97_INT + FF_DWT97_INT, + FF_DWT_NB }; typedef struct DWTContext { diff --git a/libavcodec/jpegls.c b/libavcodec/jpegls.c index 52a4500..19d461f 100644 --- a/libavcodec/jpegls.c +++ b/libavcodec/jpegls.c @@ -25,6 +25,7 @@ * JPEG-LS common code. */ +#include "internal.h" #include "jpegls.h" void ff_jpegls_init_state(JLSState *state) @@ -98,5 +99,5 @@ void ff_jpegls_reset_coding_parameters(JLSState *s, int reset_all) if (s->reset == 0 || reset_all) s->reset = 64; - av_dlog(NULL, "[JPEG-LS RESET] T=%i,%i,%i\n", s->T1, s->T2, s->T3); + ff_dlog(NULL, "[JPEG-LS RESET] T=%i,%i,%i\n", s->T1, s->T2, s->T3); } diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index df72ca3..9f8ccec 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "get_bits.h" #include "golomb.h" +#include "internal.h" #include "mathops.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -76,7 +77,7 @@ int ff_jpegls_decode_lse(MJpegDecodeContext *s) av_log(s->avctx, AV_LOG_ERROR, "invalid id %d\n", id); return AVERROR_INVALIDDATA; } - av_dlog(s->avctx, "ID=%i, T=%i,%i,%i\n", id, s->t1, s->t2, s->t3); + ff_dlog(s->avctx, "ID=%i, T=%i,%i,%i\n", id, s->t1, s->t2, s->t3); return 0; } @@ -277,10 +278,16 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int off = 0, stride = 1, width, shift, ret = 0; zero = av_mallocz(s->picture_ptr->linesize[0]); + if (!zero) + return AVERROR(ENOMEM); last = zero; cur = s->picture_ptr->data[0]; state = av_mallocz(sizeof(JLSState)); + if (!state) { + av_free(zero); + return AVERROR(ENOMEM); + } /* initialize JPEG-LS state from JPEG parameters */ state->near = near; state->bpp = (s->bits < 2) ? 2 : s->bits; @@ -297,13 +304,13 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, else shift = point_transform + (16 - s->bits); - av_dlog(s->avctx, + ff_dlog(s->avctx, "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_dlog(s->avctx, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n", + ff_dlog(s->avctx, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n", ilv, point_transform, s->bits, s->cur_scan); if (ilv == 0) { /* separate planes */ if (s->cur_scan > s->nb_components) { @@ -395,5 +402,6 @@ AVCodec ff_jpegls_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = ff_mjpeg_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index 3af6412..cb9b71e 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -31,8 +31,15 @@ #include "internal.h" #include "mathops.h" #include "mjpeg.h" +#include "mjpegenc.h" #include "jpegls.h" +typedef struct JPEGLSContext { + AVClass *class; + + int pred; +} JPEGLSContext; + /** * Encode error from regular symbol */ @@ -248,15 +255,25 @@ static void ls_store_lse(JLSState *state, PutBitContext *pb) static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { + JPEGLSContext *ctx = avctx->priv_data; const AVFrame *const p = pict; - const int near = avctx->prediction_method; PutBitContext pb, pb2; GetBitContext gb; - uint8_t *buf2, *zero, *cur, *last; + uint8_t *buf2 = NULL; + uint8_t *zero = NULL; + uint8_t *cur = NULL; + uint8_t *last = NULL; JLSState *state; int i, size, ret; int comps; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->prediction_method) + ctx->pred = avctx->prediction_method; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_GRAY16) comps = 1; @@ -264,12 +281,14 @@ static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, comps = 3; if ((ret = ff_alloc_packet(pkt, avctx->width * avctx->height * comps * 4 + - FF_MIN_BUFFER_SIZE)) < 0) { + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } buf2 = av_malloc(pkt->size); + if (!buf2) + goto memfail; init_put_bits(&pb, pkt->data, pkt->size); init_put_bits(&pb2, buf2, pkt->size); @@ -295,21 +314,26 @@ static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, put_bits(&pb, 8, i); // component ID put_bits(&pb, 8, 0); // mapping index: none } - put_bits(&pb, 8, near); + put_bits(&pb, 8, ctx->pred); 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)); + if (!state) + goto memfail; + /* initialize JPEG-LS state from JPEG parameters */ - state->near = near; + state->near = ctx->pred; state->bpp = (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8; ff_jpegls_reset_coding_parameters(state, 0); ff_jpegls_init_state(state); ls_store_lse(state, &pb); - zero = av_mallocz(p->linesize[0]); - last = zero; + zero = last = av_mallocz(p->linesize[0]); + if (!zero) + goto memfail; + cur = p->data[0]; if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) { int t = 0; @@ -359,11 +383,11 @@ static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, } } - av_free(zero); - av_free(state); + av_freep(&zero); + av_freep(&state); /* the specification says that after doing 0xff escaping unused bits in - * the last byte must be set to 0, so just append 7 "optional" zero-bits + * the last byte must be set to 0, so just append 7 "optional" zero bits * to avoid special-casing. */ put_bits(&pb2, 7, 0); size = put_bits_count(&pb2); @@ -381,7 +405,7 @@ static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, } } avpriv_align_put_bits(&pb); - av_free(buf2); + av_freep(&buf2); /* End of image */ put_marker(&pb, EOI); @@ -393,22 +417,23 @@ static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; -} -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; +memfail: + av_packet_unref(pkt); + av_freep(&buf2); + av_freep(&state); + av_freep(&zero); + return AVERROR(ENOMEM); } static av_cold int encode_init_ls(AVCodecContext *ctx) { - ctx->coded_frame = av_frame_alloc(); - if (!ctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS ctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; ctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (ctx->pix_fmt != AV_PIX_FMT_GRAY8 && ctx->pix_fmt != AV_PIX_FMT_GRAY16 && @@ -421,17 +446,38 @@ static av_cold int encode_init_ls(AVCodecContext *ctx) return 0; } +#define OFFSET(x) offsetof(JPEGLSContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE, "pred" }, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, + { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, + + { NULL}, +}; + +static const AVClass jpegls_class = { + .class_name = "jpegls", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_jpegls_encoder = { .name = "jpegls", .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_JPEGLS, + .priv_data_size = sizeof(JPEGLSContext), + .priv_class = &jpegls_class, .init = encode_init_ls, - .close = encode_close, .encode2 = encode_picture_ls, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mjpeg.c b/libavcodec/jpegtables.c similarity index 99% rename from libavcodec/mjpeg.c rename to libavcodec/jpegtables.c index a353851..ce2bae2 100644 --- a/libavcodec/mjpeg.c +++ b/libavcodec/jpegtables.c @@ -30,7 +30,7 @@ * MJPEG encoder and decoder. */ -#include "mjpeg.h" +#include "jpegtables.h" #if 0 diff --git a/libavcodec/jpegtables.h b/libavcodec/jpegtables.h new file mode 100644 index 0000000..1a909be --- /dev/null +++ b/libavcodec/jpegtables.h @@ -0,0 +1,43 @@ +/* + * JPEG-related tables + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_JPEGTABLES_H +#define AVCODEC_JPEGTABLES_H + +#include + +#include "libavutil/internal.h" + +extern av_export const uint8_t avpriv_mjpeg_bits_dc_luminance[]; +extern av_export const uint8_t avpriv_mjpeg_val_dc[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_ac_luminance[]; +extern av_export const uint8_t avpriv_mjpeg_val_ac_luminance[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; +extern av_export const uint8_t avpriv_mjpeg_val_ac_chrominance[]; + +void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, + const uint8_t *bits_table, + const uint8_t *val_table); + +#endif /* AVCODEC_JPEGTABLES_H */ diff --git a/libavcodec/jrevdct.c b/libavcodec/jrevdct.c index e6846a1..96a884a 100644 --- a/libavcodec/jrevdct.c +++ b/libavcodec/jrevdct.c @@ -63,7 +63,9 @@ */ #include "libavutil/common.h" + #include "dct.h" +#include "idctdsp.h" #define EIGHT_BIT_SAMPLES @@ -249,8 +251,8 @@ void ff_j_rev_dct(DCTBLOCK data) /* AC terms all zero */ if (d0) { /* Compute a 32 bit value to assign. */ - int16_t dcval = (int16_t) (d0 << PASS1_BITS); - register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000); + int16_t dcval = (int16_t) (d0 * (1 << PASS1_BITS)); + register int v = (dcval & 0xffff) | ((dcval * (1 << 16)) & 0xffff0000); idataptr[0] = v; idataptr[1] = v; @@ -272,8 +274,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -284,8 +286,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = MULTIPLY(-d6, FIX_1_306562965); tmp3 = MULTIPLY(d6, FIX_0_541196100); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -298,8 +300,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = MULTIPLY(d2, FIX_0_541196100); tmp3 = MULTIPLY(d2, FIX_1_306562965); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -307,8 +309,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp12 = tmp1 - tmp2; } else { /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = (d0 + d4) << CONST_BITS; - tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + tmp10 = tmp13 = (d0 + d4) * CONST_SCALE; + tmp11 = tmp12 = (d0 - d4) * CONST_SCALE; } } @@ -618,8 +620,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -630,8 +632,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = MULTIPLY(-d6, FIX_1_306562965); tmp3 = MULTIPLY(d6, FIX_0_541196100); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -644,8 +646,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp2 = MULTIPLY(d2, FIX_0_541196100); tmp3 = MULTIPLY(d2, FIX_1_306562965); - tmp0 = (d0 + d4) << CONST_BITS; - tmp1 = (d0 - d4) << CONST_BITS; + tmp0 = (d0 + d4) * CONST_SCALE; + tmp1 = (d0 - d4) * CONST_SCALE; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; @@ -653,8 +655,8 @@ void ff_j_rev_dct(DCTBLOCK data) tmp12 = tmp1 - tmp2; } else { /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = (d0 + d4) << CONST_BITS; - tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + tmp10 = tmp13 = (d0 + d4) * CONST_SCALE; + tmp11 = tmp12 = (d0 - d4) * CONST_SCALE; } } @@ -940,3 +942,15 @@ void ff_j_rev_dct(DCTBLOCK data) dataptr++; /* advance pointer to next column */ } } + +void ff_jref_idct_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct(block); + ff_put_pixels_clamped(block, dest, line_size); +} + +void ff_jref_idct_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct(block); + ff_add_pixels_clamped(block, dest, line_size); +} diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index 2a7aa10..c532b75 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -228,5 +228,5 @@ AVCodec ff_jv_decoder = { .init = decode_init, .close = decode_close, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/kgv1dec.c b/libavcodec/kgv1dec.c index d58e775..0bf322e 100644 --- a/libavcodec/kgv1dec.c +++ b/libavcodec/kgv1dec.c @@ -30,7 +30,7 @@ #include "avcodec.h" #include "internal.h" -typedef struct { +typedef struct KgvContext { AVCodecContext *avctx; uint16_t *frame_buffer; uint16_t *last_frame_buffer; @@ -196,5 +196,5 @@ AVCodec ff_kgv1_decoder = { .close = decode_end, .decode = decode_frame, .flush = decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c index 5da8bb2..ca6b79f 100644 --- a/libavcodec/kmvc.c +++ b/libavcodec/kmvc.c @@ -406,5 +406,5 @@ AVCodec ff_kmvc_decoder = { .priv_data_size = sizeof(KmvcContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c index e9b0098..55e10bc 100644 --- a/libavcodec/lagarith.c +++ b/libavcodec/lagarith.c @@ -59,11 +59,11 @@ typedef struct LagarithContext { } LagarithContext; /** - * Compute the 52bit mantissa of 1/(double)denom. + * Compute the 52-bit mantissa of 1/(double)denom. * This crazy format uses floats in an entropy coder and we have to match x86 * rounding exactly, thus ordinary floats aren't portable enough. * @param denom denominator - * @return 52bit mantissa + * @return 52-bit mantissa * @see softfloat_mul */ static uint64_t softfloat_reciprocal(uint32_t denom) @@ -80,9 +80,9 @@ static uint64_t softfloat_reciprocal(uint32_t denom) /** * (uint32_t)(x*f), where f has the given mantissa, and exponent 0 * Used in combination with softfloat_reciprocal computes x/(double)denom. - * @param x 32bit integer factor + * @param x 32-bit integer factor * @param mantissa mantissa of f with exponent 0 - * @return 32bit integer value (x*f) + * @return 32-bit integer value (x*f) * @see softfloat_reciprocal */ static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa) @@ -226,7 +226,7 @@ static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1, int *left_top) { /* This is almost identical to add_hfyu_median_pred in huffyuvdsp.h. - * However the &0xFF on the gradient predictor yealds incorrect output + * However the &0xFF on the gradient predictor yields incorrect output * for lagarith. */ int i; @@ -703,5 +703,5 @@ AVCodec ff_lagarith_decoder = { .init = lag_decode_init, .close = lag_decode_end, .decode = lag_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff --git a/libavcodec/lagarithrac.c b/libavcodec/lagarithrac.c index edfb18f..f9e4e5c 100644 --- a/libavcodec/lagarithrac.c +++ b/libavcodec/lagarithrac.c @@ -45,7 +45,7 @@ void ff_lag_rac_init(lag_rac *l, GetBitContext *gb, int length) l->range = 0x80; l->low = *l->bytestream >> 1; - l->hash_shift = FFMAX(l->scale - 8, 0); + l->hash_shift = FFMAX(l->scale, 8) - 8; for (i = j = 0; i < 256; i++) { unsigned r = i << l->hash_shift; diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index 9c60697..ba608f9 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -35,7 +35,6 @@ * http://www.pcisys.net/~melanson/codecs * * Supports: BGR24 (RGB 24bpp) - * */ #include @@ -51,9 +50,6 @@ #include #endif -/* - * Decoder context - */ typedef struct LclDecContext { // Image type int imgtype; @@ -151,11 +147,6 @@ static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, i #endif -/* - * - * Decode a frame - * - */ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { AVFrame *frame = data; @@ -459,11 +450,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return buf_size; } -/* - * - * Init lcl decoder - * - */ static av_cold int decode_init(AVCodecContext *avctx) { LclDecContext * const c = avctx->priv_data; @@ -607,11 +593,6 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -/* - * - * Uninit lcl decoder - * - */ static av_cold int decode_end(AVCodecContext *avctx) { LclDecContext * const c = avctx->priv_data; @@ -635,7 +616,7 @@ AVCodec ff_mszh_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -649,6 +630,6 @@ AVCodec ff_zlib_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c index 878d1e1..2e00807 100644 --- a/libavcodec/lclenc.c +++ b/libavcodec/lclenc.c @@ -35,22 +35,19 @@ * http://www.pcisys.net/~melanson/codecs * * Supports: BGR24 (RGB 24bpp) - * */ #include #include #include "avcodec.h" +#include "internal.h" #include "lcl.h" #include "libavutil/internal.h" #include "libavutil/mem.h" #include -/* - * Decoder context - */ typedef struct LclEncContext { AVCodecContext *avctx; @@ -64,11 +61,6 @@ typedef struct LclEncContext { z_stream zstream; } LclEncContext; -/* - * - * Encode a frame - * - */ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { @@ -119,11 +111,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -/* - * - * Init lcl encoder - * - */ static av_cold int encode_init(AVCodecContext *avctx) { LclEncContext *c = avctx->priv_data; @@ -134,13 +121,15 @@ static av_cold int encode_init(AVCodecContext *avctx) assert(avctx->width && avctx->height); avctx->extradata= av_mallocz(8); - - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) + if (!avctx->extradata) return AVERROR(ENOMEM); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif // Will be user settable someday c->compression = 6; @@ -164,17 +153,12 @@ static av_cold int encode_init(AVCodecContext *avctx) zret = deflateInit(&c->zstream, c->compression); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Deflate init error: %d\n", zret); - return 1; + return AVERROR_UNKNOWN; } return 0; } -/* - * - * Uninit lcl encoder - * - */ static av_cold int encode_end(AVCodecContext *avctx) { LclEncContext *c = avctx->priv_data; @@ -182,8 +166,6 @@ static av_cold int encode_end(AVCodecContext *avctx) av_freep(&avctx->extradata); deflateEnd(&c->zstream); - av_frame_free(&avctx->coded_frame); - return 0; } @@ -197,4 +179,6 @@ AVCodec ff_zlib_encoder = { .encode2 = encode_frame, .close = encode_end, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/libavcodec.v b/libavcodec/libavcodec.v index bf14807..f1d5e5b 100644 --- a/libavcodec/libavcodec.v +++ b/libavcodec/libavcodec.v @@ -1,4 +1,6 @@ -LIBAVCODEC_$MAJOR { - global: av*; - local: *; +LIBAVCODEC_MAJOR { + global: + av*; + local: + *; }; diff --git a/libavcodec/libdcadec.c b/libavcodec/libdcadec.c new file mode 100644 index 0000000..b88f807 --- /dev/null +++ b/libavcodec/libdcadec.c @@ -0,0 +1,205 @@ +/* + * libdcadec decoder wrapper + * Copyright (C) 2015 Hendrik Leppkes + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "dca.h" +#include "dca_syncwords.h" +#include "internal.h" + +typedef struct DCADecContext { + struct dcadec_context *ctx; + uint8_t *buffer; + int buffer_size; +} DCADecContext; + +static int dcadec_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + DCADecContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret, i, k; + int **samples, nsamples, channel_mask, sample_rate, bits_per_sample, profile; + uint32_t mrk; + uint8_t *input = avpkt->data; + int input_size = avpkt->size; + + /* convert bytestream syntax to RAW BE format if required */ + if (input_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Input size too small\n"); + return AVERROR_INVALIDDATA; + } + mrk = AV_RB32(input); + if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) { + s->buffer = av_fast_realloc(s->buffer, &s->buffer_size, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->buffer) + return AVERROR(ENOMEM); + + if ((ret = ff_dca_convert_bitstream(avpkt->data, avpkt->size, s->buffer, s->buffer_size)) < 0) + return ret; + + input = s->buffer; + input_size = ret; + } + + if ((ret = dcadec_context_parse(s->ctx, input, input_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "dcadec_context_parse() failed: %d (%s)\n", -ret, dcadec_strerror(ret)); + return AVERROR_UNKNOWN; + } + if ((ret = dcadec_context_filter(s->ctx, &samples, &nsamples, &channel_mask, + &sample_rate, &bits_per_sample, &profile)) < 0) { + av_log(avctx, AV_LOG_ERROR, "dcadec_context_filter() failed: %d (%s)\n", -ret, dcadec_strerror(ret)); + return AVERROR_UNKNOWN; + } + + avctx->channels = av_get_channel_layout_nb_channels(channel_mask); + avctx->channel_layout = channel_mask; + avctx->sample_rate = sample_rate; + + if (bits_per_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + else if (bits_per_sample <= 24) + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + else { + av_log(avctx, AV_LOG_ERROR, "Unsupported number of bits per sample: %d\n", + bits_per_sample); + return AVERROR(ENOSYS); + } + + avctx->bits_per_raw_sample = bits_per_sample; + + switch (profile) { + case DCADEC_PROFILE_DS: + avctx->profile = FF_PROFILE_DTS; + break; + case DCADEC_PROFILE_DS_96_24: + avctx->profile = FF_PROFILE_DTS_96_24; + break; + case DCADEC_PROFILE_DS_ES: + avctx->profile = FF_PROFILE_DTS_ES; + break; + case DCADEC_PROFILE_HD_HRA: + avctx->profile = FF_PROFILE_DTS_HD_HRA; + break; + case DCADEC_PROFILE_HD_MA: + avctx->profile = FF_PROFILE_DTS_HD_MA; + break; + case DCADEC_PROFILE_EXPRESS: + avctx->profile = FF_PROFILE_DTS_EXPRESS; + break; + case DCADEC_PROFILE_UNKNOWN: + default: + avctx->profile = FF_PROFILE_UNKNOWN; + break; + } + + /* bitrate is only meaningful if there are no HD extensions, as they distort the bitrate */ + if (profile == DCADEC_PROFILE_DS || profile == DCADEC_PROFILE_DS_96_24 || profile == DCADEC_PROFILE_DS_ES) { + struct dcadec_core_info *info = dcadec_context_get_core_info(s->ctx); + avctx->bit_rate = info->bit_rate; + dcadec_context_free_core_info(info); + } else + avctx->bit_rate = 0; + + frame->nb_samples = nsamples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (i = 0; i < avctx->channels; i++) { + if (frame->format == AV_SAMPLE_FMT_S16P) { + int16_t *plane = (int16_t *)frame->extended_data[i]; + for (k = 0; k < nsamples; k++) + plane[k] = samples[i][k]; + } else { + int32_t *plane = (int32_t *)frame->extended_data[i]; + int shift = 32 - bits_per_sample; + for (k = 0; k < nsamples; k++) + plane[k] = samples[i][k] << shift; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +static av_cold void dcadec_flush(AVCodecContext *avctx) +{ + DCADecContext *s = avctx->priv_data; + dcadec_context_clear(s->ctx); +} + +static av_cold int dcadec_close(AVCodecContext *avctx) +{ + DCADecContext *s = avctx->priv_data; + + dcadec_context_destroy(s->ctx); + s->ctx = NULL; + + av_freep(&s->buffer); + + return 0; +} + +static av_cold int dcadec_init(AVCodecContext *avctx) +{ + DCADecContext *s = avctx->priv_data; + + s->ctx = dcadec_context_create(0); + if (!s->ctx) + return AVERROR(ENOMEM); + + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + avctx->bits_per_raw_sample = 24; + + return 0; +} + +static const AVProfile profiles[] = { + { FF_PROFILE_DTS, "DTS" }, + { FF_PROFILE_DTS_ES, "DTS-ES" }, + { FF_PROFILE_DTS_96_24, "DTS 96/24" }, + { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, + { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, + { FF_PROFILE_DTS_EXPRESS, "DTS Express" }, + { FF_PROFILE_UNKNOWN }, +}; + +AVCodec ff_libdcadec_decoder = { + .name = "libdcadec", + .long_name = NULL_IF_CONFIG_SMALL("dcadec DCA decoder"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DTS, + .priv_data_size = sizeof(DCADecContext), + .init = dcadec_init, + .decode = dcadec_decode_frame, + .close = dcadec_close, + .flush = dcadec_flush, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .profiles = NULL_IF_CONFIG_SMALL(profiles), +}; diff --git a/libavcodec/libfaac.c b/libavcodec/libfaac.c index 9b5b11a..5cdbe27 100644 --- a/libavcodec/libfaac.c +++ b/libavcodec/libfaac.c @@ -118,7 +118,7 @@ static av_cold int Faac_encode_init(AVCodecContext *avctx) faac_cfg->allowMidside = 1; faac_cfg->bitRate = avctx->bit_rate / avctx->channels; faac_cfg->bandWidth = avctx->cutoff; - if(avctx->flags & CODEC_FLAG_QSCALE) { + if(avctx->flags & AV_CODEC_FLAG_QSCALE) { faac_cfg->bitRate = 0; faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA; } @@ -132,14 +132,14 @@ static av_cold int Faac_encode_init(AVCodecContext *avctx) /* Set decoder specific info */ avctx->extradata_size = 0; - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { unsigned char *buffer = NULL; unsigned long decoder_specific_info_size; if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer, &decoder_specific_info_size)) { - avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_malloc(decoder_specific_info_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { ret = AVERROR(ENOMEM); goto error; @@ -157,7 +157,7 @@ static av_cold int Faac_encode_init(AVCodecContext *avctx) goto error; } - avctx->delay = FAAC_DELAY_SAMPLES; + avctx->initial_padding = FAAC_DELAY_SAMPLES; ff_af_queue_init(avctx, &s->afq); return 0; @@ -232,7 +232,7 @@ AVCodec ff_libfaac_encoder = { .init = Faac_encode_init, .encode2 = Faac_encode_frame, .close = Faac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .profiles = NULL_IF_CONFIG_SMALL(profiles), diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index 27e5712..cdf7a05 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -25,6 +25,12 @@ #include "avcodec.h" #include "internal.h" +/* The version macro is introduced the same time as the setting enum was + * changed, so this check should suffice. */ +#ifndef AACDECODER_LIB_VL0 +#define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS +#endif + enum ConcealMethod { CONCEAL_METHOD_SPECTRAL_MUTING = 0, CONCEAL_METHOD_NOISE_SUBSTITUTION = 1, @@ -35,10 +41,22 @@ enum ConcealMethod { typedef struct FDKAACDecContext { const AVClass *class; HANDLE_AACDECODER handle; - int initialized; + uint8_t *decoder_buffer; + int decoder_buffer_size; + uint8_t *anc_buffer; enum ConcealMethod conceal_method; + int drc_level; + int drc_boost; + int drc_heavy; + int drc_cut; + int level_limit; } FDKAACDecContext; + +#define DMX_ANC_BUFFSIZE 128 +#define DECODER_MAX_CHANNELS 8 +#define DECODER_BUFFSIZE 2048 * sizeof(INT_PCM) + #define OFFSET(x) offsetof(FDKAACDecContext, x) #define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption fdk_aac_dec_options[] = { @@ -46,6 +64,17 @@ static const AVOption fdk_aac_dec_options[] = { { "spectral", "Spectral muting", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_SPECTRAL_MUTING }, INT_MIN, INT_MAX, AD, "conceal" }, { "noise", "Noise Substitution", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_NOISE_SUBSTITUTION }, INT_MIN, INT_MAX, AD, "conceal" }, { "energy", "Energy Interpolation", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_ENERGY_INTERPOLATION }, INT_MIN, INT_MAX, AD, "conceal" }, + { "drc_boost", "Dynamic Range Control: boost, where [0] is none and [127] is max boost", + OFFSET(drc_boost), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, + { "drc_cut", "Dynamic Range Control: attenuation factor, where [0] is none and [127] is max compression", + OFFSET(drc_cut), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, + { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB", + OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, + { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", + OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, +#ifdef AACDECODER_LIB_VL0 + { "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD }, +#endif { NULL } }; @@ -57,7 +86,7 @@ static int get_stream_info(AVCodecContext *avctx) { FDKAACDecContext *s = avctx->priv_data; CStreamInfo *info = aacDecoder_GetStreamInfo(s->handle); - int channel_counts[9] = { 0 }; + int channel_counts[0x24] = { 0 }; int i, ch_error = 0; uint64_t ch_layout = 0; @@ -75,7 +104,7 @@ static int get_stream_info(AVCodecContext *avctx) for (i = 0; i < info->numChannels; i++) { AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i]; - if (ctype <= ACT_NONE || ctype > ACT_TOP) { + if (ctype <= ACT_NONE || ctype >= FF_ARRAY_ELEMS(channel_counts)) { av_log(avctx, AV_LOG_WARNING, "unknown channel type\n"); break; } @@ -170,6 +199,8 @@ static av_cold int fdk_aac_decode_close(AVCodecContext *avctx) if (s->handle) aacDecoder_Close(s->handle); + av_free(s->decoder_buffer); + av_free(s->anc_buffer); return 0; } @@ -199,8 +230,83 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) return AVERROR_UNKNOWN; } + if (avctx->request_channel_layout > 0 && + avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) { + int downmix_channels = -1; + + switch (avctx->request_channel_layout) { + case AV_CH_LAYOUT_STEREO: + case AV_CH_LAYOUT_STEREO_DOWNMIX: + downmix_channels = 2; + break; + case AV_CH_LAYOUT_MONO: + downmix_channels = 1; + break; + default: + av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); + break; + } + + if (downmix_channels != -1) { + if (aacDecoder_SetParam(s->handle, AAC_PCM_MAX_OUTPUT_CHANNELS, + downmix_channels) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_WARNING, "Unable to set output channels in the decoder\n"); + } else { + s->anc_buffer = av_malloc(DMX_ANC_BUFFSIZE); + if (!s->anc_buffer) { + av_log(avctx, AV_LOG_ERROR, "Unable to allocate ancillary buffer for the decoder\n"); + return AVERROR(ENOMEM); + } + if (aacDecoder_AncDataInit(s->handle, s->anc_buffer, DMX_ANC_BUFFSIZE)) { + av_log(avctx, AV_LOG_ERROR, "Unable to register downmix ancillary buffer in the decoder\n"); + return AVERROR_UNKNOWN; + } + } + } + } + + if (s->drc_boost != -1) { + if (aacDecoder_SetParam(s->handle, AAC_DRC_BOOST_FACTOR, s->drc_boost) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set DRC boost factor in the decoder\n"); + return AVERROR_UNKNOWN; + } + } + + if (s->drc_cut != -1) { + if (aacDecoder_SetParam(s->handle, AAC_DRC_ATTENUATION_FACTOR, s->drc_cut) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set DRC attenuation factor in the decoder\n"); + return AVERROR_UNKNOWN; + } + } + + if (s->drc_level != -1) { + if (aacDecoder_SetParam(s->handle, AAC_DRC_REFERENCE_LEVEL, s->drc_level) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set DRC reference level in the decoder\n"); + return AVERROR_UNKNOWN; + } + } + + if (s->drc_heavy != -1) { + if (aacDecoder_SetParam(s->handle, AAC_DRC_HEAVY_COMPRESSION, s->drc_heavy) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set DRC heavy compression in the decoder\n"); + return AVERROR_UNKNOWN; + } + } + +#ifdef AACDECODER_LIB_VL0 + if (aacDecoder_SetParam(s->handle, AAC_PCM_LIMITER_ENABLE, s->level_limit) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set in signal level limiting in the decoder\n"); + return AVERROR_UNKNOWN; + } +#endif + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + s->decoder_buffer_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; + s->decoder_buffer = av_malloc(s->decoder_buffer_size); + if (!s->decoder_buffer) + return AVERROR(ENOMEM); + return 0; } @@ -212,8 +318,6 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, int ret; AAC_DECODER_ERROR err; UINT valid = avpkt->size; - uint8_t *buf, *tmpptr = NULL; - int buf_size; err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); if (err != AAC_DEC_OK) { @@ -221,23 +325,7 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - if (s->initialized) { - frame->nb_samples = avctx->frame_size; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "ff_get_buffer() failed\n"); - return ret; - } - buf = frame->extended_data[0]; - buf_size = avctx->channels * frame->nb_samples * - av_get_bytes_per_sample(avctx->sample_fmt); - } else { - buf_size = 50 * 1024; - buf = tmpptr = av_malloc(buf_size); - if (!buf) - return AVERROR(ENOMEM); - } - - err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) buf, buf_size, 0); + err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size, 0); if (err == AAC_DEC_NOT_ENOUGH_BITS) { ret = avpkt->size - valid; goto end; @@ -249,29 +337,22 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, goto end; } - if (!s->initialized) { - if ((ret = get_stream_info(avctx)) < 0) - goto end; - s->initialized = 1; - frame->nb_samples = avctx->frame_size; - } + if ((ret = get_stream_info(avctx)) < 0) + goto end; + frame->nb_samples = avctx->frame_size; - if (tmpptr) { - frame->nb_samples = avctx->frame_size; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "ff_get_buffer() failed\n"); - goto end; - } - memcpy(frame->extended_data[0], tmpptr, - avctx->channels * avctx->frame_size * - av_get_bytes_per_sample(avctx->sample_fmt)); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "ff_get_buffer() failed\n"); + goto end; } + memcpy(frame->extended_data[0], s->decoder_buffer, + avctx->channels * avctx->frame_size * + av_get_bytes_per_sample(avctx->sample_fmt)); *got_frame_ptr = 1; ret = avpkt->size - valid; end: - av_free(tmpptr); return ret; } @@ -298,6 +379,8 @@ AVCodec ff_libfdk_aac_decoder = { .decode = fdk_aac_decode_frame, .close = fdk_aac_decode_close, .flush = fdk_aac_decode_flush, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_CHANNEL_CONF, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_class = &fdk_aac_dec_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 34717d4..2cea58f 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -184,7 +184,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) goto error; } - if (avctx->flags & CODEC_FLAG_QSCALE || s->vbr) { + if (avctx->flags & AV_CODEC_FLAG_QSCALE || s->vbr) { int mode = s->vbr ? s->vbr : avctx->global_quality; if (mode < 1 || mode > 5) { av_log(avctx, AV_LOG_WARNING, @@ -224,7 +224,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Choose bitstream format - if global header is requested, use * raw access units, otherwise use ADTS. */ if ((err = aacEncoder_SetParam(s->handle, AACENC_TRANSMUX, - avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 0 : s->latm ? 10 : 2)) != AACENC_OK) { + avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? 0 : s->latm ? 10 : 2)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set the transmux format: %s\n", aac_get_error(err)); goto error; @@ -243,7 +243,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) * if using mp4 mode (raw access units, with global header) and * implicit signaling if using ADTS. */ if (s->signaling < 0) - s->signaling = avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 2 : 0; + s->signaling = avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER ? 2 : 0; if ((err = aacEncoder_SetParam(s->handle, AACENC_SIGNALING_MODE, s->signaling)) != AACENC_OK) { @@ -286,13 +286,13 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) } avctx->frame_size = info.frameLength; - avctx->delay = info.encoderDelay; + avctx->initial_padding = info.encoderDelay; ff_af_queue_init(avctx, &s->afq); - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { avctx->extradata_size = info.confSize; avctx->extradata = av_mallocz(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { ret = AVERROR(ENOMEM); goto error; @@ -419,7 +419,7 @@ AVCodec ff_libfdk_aac_encoder = { .init = aac_encode_init, .encode2 = aac_encode_frame, .close = aac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .priv_class = &aac_enc_class, diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index da95cc7..4c21ff6 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -134,7 +134,7 @@ AVCodec ff_libgsm_decoder = { .close = libgsm_decode_close, .decode = libgsm_decode_frame, .flush = libgsm_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; AVCodec ff_libgsm_ms_decoder = { @@ -147,5 +147,5 @@ AVCodec ff_libgsm_ms_decoder = { .close = libgsm_decode_close, .decode = libgsm_decode_frame, .flush = libgsm_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index af693bd..a5b2f3a 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -95,8 +95,7 @@ static int ilbc_decode_frame(AVCodecContext *avctx, void *data, return ret; } - WebRtcIlbcfix_DecodeImpl((WebRtc_Word16*) frame->data[0], - (const WebRtc_UWord16*) buf, &s->decoder, 1); + WebRtcIlbcfix_DecodeImpl((int16_t *) frame->data[0], (const uint16_t *) buf, &s->decoder, 1); *got_frame_ptr = 1; @@ -111,7 +110,7 @@ AVCodec ff_libilbc_decoder = { .priv_data_size = sizeof(ILBCDecContext), .init = ilbc_decode_init, .decode = ilbc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .priv_class = &ilbc_dec_class, }; @@ -168,7 +167,7 @@ static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return ret; } - WebRtcIlbcfix_EncodeImpl((WebRtc_UWord16*) avpkt->data, (const WebRtc_Word16*) frame->data[0], &s->encoder); + WebRtcIlbcfix_EncodeImpl((uint16_t *) avpkt->data, (const int16_t *) frame->data[0], &s->encoder); avpkt->size = s->encoder.no_of_bytes; *got_packet_ptr = 1; diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c new file mode 100644 index 0000000..19122e0 --- /dev/null +++ b/libavcodec/libkvazaar.c @@ -0,0 +1,300 @@ +/* + * libkvazaar encoder + * + * Copyright (c) 2015 Tampere University of Technology + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/dict.h" +#include "libavutil/error.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" + +typedef struct LibkvazaarContext { + const AVClass *class; + + const kvz_api *api; + kvz_encoder *encoder; + kvz_config *config; + + char *kvz_params; +} LibkvazaarContext; + +static av_cold int libkvazaar_init(AVCodecContext *avctx) +{ + LibkvazaarContext *const ctx = avctx->priv_data; + const kvz_api *const api = ctx->api = kvz_api_get(8); + kvz_config *cfg = NULL; + kvz_encoder *enc = NULL; + + if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(avctx, AV_LOG_ERROR, + "Set -strict experimental to use this encoder.\n"); + return AVERROR_EXPERIMENTAL; + } + + /* Kvazaar requires width and height to be multiples of eight. */ + if (avctx->width % 8 || avctx->height % 8) { + av_log(avctx, AV_LOG_ERROR, + "Video dimensions are not a multiple of 8 (%dx%d).\n", + avctx->width, avctx->height); + return AVERROR(ENOSYS); + } + + ctx->config = cfg = api->config_alloc(); + if (!cfg) { + av_log(avctx, AV_LOG_ERROR, + "Could not allocate kvazaar config structure.\n"); + return AVERROR(ENOMEM); + } + + if (!api->config_init(cfg)) { + av_log(avctx, AV_LOG_ERROR, + "Could not initialize kvazaar config structure.\n"); + return AVERROR_BUG; + } + + cfg->width = avctx->width; + cfg->height = avctx->height; + + cfg->framerate_num = avctx->time_base.den; + cfg->framerate_denom = avctx->time_base.num * avctx->ticks_per_frame; + cfg->target_bitrate = avctx->bit_rate; + cfg->vui.sar_width = avctx->sample_aspect_ratio.num; + cfg->vui.sar_height = avctx->sample_aspect_ratio.den; + + if (ctx->kvz_params) { + AVDictionary *dict = NULL; + if (!av_dict_parse_string(&dict, ctx->kvz_params, "=", ",", 0)) { + AVDictionaryEntry *entry = NULL; + while ((entry = av_dict_get(dict, "", entry, AV_DICT_IGNORE_SUFFIX))) { + if (!api->config_parse(cfg, entry->key, entry->value)) { + av_log(avctx, AV_LOG_WARNING, "Invalid option: %s=%s.\n", + entry->key, entry->value); + } + } + av_dict_free(&dict); + } + } + + ctx->encoder = enc = api->encoder_open(cfg); + if (!enc) { + av_log(avctx, AV_LOG_ERROR, "Could not open kvazaar encoder.\n"); + return AVERROR_BUG; + } + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + kvz_data_chunk *data_out = NULL; + kvz_data_chunk *chunk = NULL; + uint32_t len_out; + uint8_t *p; + + if (!api->encoder_headers(enc, &data_out, &len_out)) + return AVERROR(ENOMEM); + + avctx->extradata = p = av_mallocz(len_out + AV_INPUT_BUFFER_PADDING_SIZE); + if (!p) { + ctx->api->chunk_free(data_out); + return AVERROR(ENOMEM); + } + + avctx->extradata_size = len_out; + + for (chunk = data_out; chunk != NULL; chunk = chunk->next) { + memcpy(p, chunk->data, chunk->len); + p += chunk->len; + } + + ctx->api->chunk_free(data_out); + } + + return 0; +} + +static av_cold int libkvazaar_close(AVCodecContext *avctx) +{ + LibkvazaarContext *ctx = avctx->priv_data; + + if (ctx->api) { + ctx->api->encoder_close(ctx->encoder); + ctx->api->config_destroy(ctx->config); + } + + if (avctx->extradata) + av_freep(&avctx->extradata); + + return 0; +} + +static int libkvazaar_encode(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + LibkvazaarContext *ctx = avctx->priv_data; + kvz_picture *input_pic = NULL; + kvz_picture *recon_pic = NULL; + kvz_frame_info frame_info; + kvz_data_chunk *data_out = NULL; + uint32_t len_out = 0; + int retval = 0; + + if (frame) { + if (frame->width != ctx->config->width || + frame->height != ctx->config->height) { + av_log(avctx, AV_LOG_ERROR, + "Changing video dimensions during encoding is not supported. " + "(changed from %dx%d to %dx%d)\n", + ctx->config->width, ctx->config->height, + frame->width, frame->height); + retval = AVERROR_INVALIDDATA; + goto done; + } + + if (frame->format != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, + "Changing pixel format during encoding is not supported. " + "(changed from %s to %s)\n", + av_get_pix_fmt_name(avctx->pix_fmt), + av_get_pix_fmt_name(frame->format)); + retval = AVERROR_INVALIDDATA; + goto done; + } + + // Allocate input picture for kvazaar. + input_pic = ctx->api->picture_alloc(frame->width, frame->height); + if (!input_pic) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate picture.\n"); + retval = AVERROR(ENOMEM); + goto done; + } + + // Copy pixels from frame to input_pic. + { + int dst_linesizes[4] = { + frame->width, + frame->width / 2, + frame->width / 2, + 0 + }; + av_image_copy(input_pic->data, dst_linesizes, + frame->data, frame->linesize, + frame->format, frame->width, frame->height); + } + + input_pic->pts = frame->pts; + } + + retval = ctx->api->encoder_encode(ctx->encoder, + input_pic, + &data_out, &len_out, + &recon_pic, NULL, + &frame_info); + if (!retval) { + av_log(avctx, AV_LOG_ERROR, "Failed to encode frame.\n"); + retval = AVERROR_INVALIDDATA; + goto done; + } + + if (data_out) { + kvz_data_chunk *chunk = NULL; + uint64_t written = 0; + + retval = ff_alloc_packet(avpkt, len_out); + if (retval < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); + goto done; + } + + for (chunk = data_out; chunk != NULL; chunk = chunk->next) { + memcpy(avpkt->data + written, chunk->data, chunk->len); + written += chunk->len; + } + + avpkt->pts = recon_pic->pts; + avpkt->dts = recon_pic->dts; + avpkt->flags = 0; + // IRAP VCL NAL unit types span the range + // [BLA_W_LP (16), RSV_IRAP_VCL23 (23)]. + if (frame_info.nal_unit_type >= KVZ_NAL_BLA_W_LP && + frame_info.nal_unit_type <= KVZ_NAL_RSV_IRAP_VCL23) { + avpkt->flags |= AV_PKT_FLAG_KEY; + } + + *got_packet_ptr = 1; + } + +done: + ctx->api->picture_free(input_pic); + ctx->api->picture_free(recon_pic); + ctx->api->chunk_free(data_out); + return retval; +} + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +#define OFFSET(x) offsetof(LibkvazaarContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "kvazaar-params", "Set kvazaar parameters as a comma-separated list of key=value pairs.", + OFFSET(kvz_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, + + { NULL }, +}; + +static const AVClass class = { + .class_name = "libkvazaar", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { NULL }, +}; + +AVCodec ff_libkvazaar_encoder = { + .name = "libkvazaar", + .long_name = NULL_IF_CONFIG_SMALL("libkvazaar H.265 / HEVC"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = pix_fmts, + + .priv_class = &class, + .priv_data_size = sizeof(LibkvazaarContext), + .defaults = defaults, + + .init = libkvazaar_init, + .encode2 = libkvazaar_encode, + .close = libkvazaar_close, + + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index b7a323a..e4d0e00 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -61,7 +61,7 @@ static int realloc_buffer(LAMEContext *s) if (!s->buffer || s->buffer_size - s->buffer_index < BUFFER_SIZE) { int new_size = s->buffer_index + 2 * BUFFER_SIZE, err; - av_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size, + ff_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size, new_size); if ((err = av_reallocp(&s->buffer, new_size)) < 0) { s->buffer_size = s->buffer_index = 0; @@ -111,7 +111,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) lame_set_quality(s->gfp, avctx->compression_level); /* rate control */ - if (avctx->flags & CODEC_FLAG_QSCALE) { // VBR + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { // VBR lame_set_VBR(s->gfp, vbr_default); lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA); } else { @@ -137,7 +137,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) } /* get encoder delay */ - avctx->delay = lame_get_encoder_delay(s->gfp) + 528 + 1; + avctx->initial_padding = lame_get_encoder_delay(s->gfp) + 528 + 1; ff_af_queue_init(avctx, &s->afq); avctx->frame_size = lame_get_framesize(s->gfp); @@ -159,7 +159,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) if (ret < 0) goto error; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); return 0; error: @@ -239,16 +239,17 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (s->buffer_index < 4) return 0; h = AV_RB32(s->buffer); - if (ff_mpa_check_header(h) < 0) { + + ret = avpriv_mpegaudio_decode_header(&hdr, h); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Invalid mp3 header at start of buffer\n"); return AVERROR_BUG; - } - if (avpriv_mpegaudio_decode_header(&hdr, h)) { + } else if (ret) { av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); return -1; } len = hdr.frame_size; - av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, + ff_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, s->buffer_index); if (len <= s->buffer_index) { if ((ret = ff_alloc_packet(avpkt, len))) { @@ -303,7 +304,7 @@ AVCodec ff_libmp3lame_encoder = { .init = mp3lame_encode_init, .encode2 = mp3lame_encode_frame, .close = mp3lame_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16P, diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index 6b45959..27ab7d2 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -1,6 +1,6 @@ /* * AMR Audio decoder stub - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" @@ -98,7 +100,7 @@ static int amr_nb_decode_frame(AVCodecContext *avctx, void *data, enum Mode dec_mode; int packet_size, ret; - av_dlog(avctx, "amr_decode_frame buf=%p buf_size=%d frame_count=%d!!\n", + ff_dlog(avctx, "amr_decode_frame buf=%p buf_size=%d frame_count=%d!!\n", buf, buf_size, avctx->frame_number); /* get output buffer */ @@ -112,13 +114,13 @@ static int amr_nb_decode_frame(AVCodecContext *avctx, void *data, 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", + av_log(avctx, AV_LOG_ERROR, "AMR frame too short (%d, should be %d)\n", buf_size, packet_size); return AVERROR_INVALIDDATA; } - av_dlog(avctx, "packet_size=%d buf= 0x%X %X %X %X\n", - packet_size, buf[0], buf[1], buf[2], buf[3]); + ff_dlog(avctx, "packet_size=%d buf= 0x%"PRIx8" %"PRIx8" %"PRIx8" %"PRIx8"\n", + packet_size, buf[0], buf[1], buf[2], buf[3]); /* call decoder */ Decoder_Interface_Decode(s->dec_state, buf, (short *)frame->data[0], 0); @@ -136,7 +138,7 @@ AVCodec ff_libopencore_amrnb_decoder = { .init = amr_nb_decode_init, .close = amr_nb_decode_close, .decode = amr_nb_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif /* CONFIG_LIBOPENCORE_AMRNB_DECODER */ @@ -150,7 +152,7 @@ typedef struct AMR_bitrates { /* Match desired bitrate */ static int get_bitrate_mode(int bitrate, void *log_ctx) { - /* make the correspondance between bitrate and mode */ + /* make the correspondence between bitrate and mode */ static const AMR_bitrates rates[] = { { 4750, MR475 }, { 5150, MR515 }, { 5900, MR59 }, { 6700, MR67 }, { 7400, MR74 }, { 7950, MR795 }, { 10200, MR102 }, { 12200, MR122 } @@ -200,13 +202,12 @@ static av_cold int amr_nb_encode_init(AVCodecContext *avctx) } avctx->frame_size = 160; - avctx->delay = 50; + avctx->initial_padding = 50; ff_af_queue_init(avctx, &s->afq); s->enc_state = Encoder_Interface_init(s->enc_dtx); if (!s->enc_state) { av_log(avctx, AV_LOG_ERROR, "Encoder_Interface_init error\n"); - av_freep(&avctx->coded_frame); return -1; } @@ -250,7 +251,7 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return AVERROR(ENOMEM); memcpy(flush_buf, samples, frame->nb_samples * sizeof(*flush_buf)); samples = flush_buf; - if (frame->nb_samples < avctx->frame_size - avctx->delay) + if (frame->nb_samples < avctx->frame_size - avctx->initial_padding) s->enc_last_frame = -1; } if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) { @@ -269,8 +270,8 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, written = Encoder_Interface_Encode(s->enc_state, s->enc_mode, samples, avpkt->data, 0); - av_dlog(avctx, "amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n", - written, s->enc_mode, frame[0]); + ff_dlog(avctx, "amr_nb_encode_frame encoded %d bytes, bitrate %d, first byte was %#02"PRIx8"\n", + written, s->enc_mode, *frame->data[0]); /* Get the next frame pts/duration */ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, @@ -291,7 +292,7 @@ AVCodec ff_libopencore_amrnb_encoder = { .init = amr_nb_encode_init, .encode2 = amr_nb_encode_frame, .close = amr_nb_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .priv_class = &class, @@ -345,7 +346,7 @@ static int amr_wb_decode_frame(AVCodecContext *avctx, void *data, 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", + av_log(avctx, AV_LOG_ERROR, "AMR frame too short (%d, should be %d)\n", buf_size, packet_size + 1); return AVERROR_INVALIDDATA; } @@ -374,7 +375,7 @@ AVCodec ff_libopencore_amrwb_decoder = { .init = amr_wb_decode_init, .close = amr_wb_decode_close, .decode = amr_wb_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */ diff --git a/libavcodec/libopenh264.c b/libavcodec/libopenh264.c new file mode 100644 index 0000000..6252cfd --- /dev/null +++ b/libavcodec/libopenh264.c @@ -0,0 +1,62 @@ +/* + * OpenH264 shared utils + * Copyright (C) 2014 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/log.h" + +#include "libopenh264.h" + +// Convert libopenh264 log level to equivalent libav log level. +static int libopenh264_to_libav_log_level(int libopenh264_log_level) +{ + if (libopenh264_log_level >= WELS_LOG_DETAIL) return AV_LOG_TRACE; + else if (libopenh264_log_level >= WELS_LOG_DEBUG) return AV_LOG_DEBUG; + else if (libopenh264_log_level >= WELS_LOG_INFO) return AV_LOG_VERBOSE; + else if (libopenh264_log_level >= WELS_LOG_WARNING) return AV_LOG_WARNING; + else if (libopenh264_log_level >= WELS_LOG_ERROR) return AV_LOG_ERROR; + else return AV_LOG_QUIET; +} + +void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg) +{ + // The message will be logged only if the requested EQUIVALENT libav log level is + // less than or equal to the current libav log level. + int equiv_libav_log_level = libopenh264_to_libav_log_level(level); + av_log(ctx, equiv_libav_log_level, "%s\n", msg); +} + +int ff_libopenh264_check_version(void *logctx) +{ + // Mingw GCC < 4.7 on x86_32 uses an incorrect/buggy ABI for the WelsGetCodecVersion + // function (for functions returning larger structs), thus skip the check in those + // configurations. +#if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7) + OpenH264Version libver = WelsGetCodecVersion(); + if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) { + av_log(logctx, AV_LOG_ERROR, "Incorrect library version loaded\n"); + return AVERROR(EINVAL); + } +#endif + return 0; +} diff --git a/libavcodec/libopenh264.h b/libavcodec/libopenh264.h new file mode 100644 index 0000000..7c69481 --- /dev/null +++ b/libavcodec/libopenh264.h @@ -0,0 +1,39 @@ +/* + * OpenH264 shared utils + * Copyright (C) 2014 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LIBOPENH264_H +#define AVCODEC_LIBOPENH264_H + +#define OPENH264_VER_AT_LEAST(maj, min) \ + ((OPENH264_MAJOR > (maj)) || \ + (OPENH264_MAJOR == (maj) && OPENH264_MINOR >= (min))) + +// This function will be provided to the libopenh264 library. The function will be called +// when libopenh264 wants to log a message (error, warning, info, etc.). The signature for +// this function (defined in .../codec/api/svc/codec_api.h) is: +// +// typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string); + +void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg); + +int ff_libopenh264_check_version(void *logctx); + +#endif /* AVCODEC_LIBOPENH264_H */ diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c new file mode 100644 index 0000000..cc18f24 --- /dev/null +++ b/libavcodec/libopenh264dec.c @@ -0,0 +1,242 @@ +/* + * OpenH264 video decoder + * Copyright (C) 2016 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/fifo.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "libopenh264.h" + +typedef struct SVCContext { + ISVCDecoder *decoder; + AVBSFContext *bsf; + AVFifoBuffer *packet_fifo; + AVPacket pkt_filtered; +} SVCContext; + +static av_cold int svc_decode_close(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + AVPacket pkt; + + if (s->decoder) + WelsDestroyDecoder(s->decoder); + + while (s->packet_fifo && av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { + av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + + av_bsf_free(&s->bsf); + av_packet_unref(&s->pkt_filtered); + av_fifo_free(s->packet_fifo); + + return 0; +} + +static av_cold int svc_decode_init(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + SDecodingParam param = { 0 }; + int err; + int log_level; + WelsTraceCallback callback_function; + + if ((err = ff_libopenh264_check_version(avctx)) < 0) + return err; + + s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); + if (!s->packet_fifo) + return AVERROR(ENOMEM); + + if (WelsCreateDecoder(&s->decoder)) { + av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); + return AVERROR_UNKNOWN; + } + + // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. + log_level = WELS_LOG_DETAIL; + callback_function = ff_libopenh264_trace_callback; + (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_LEVEL, &log_level); + (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); + (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx); + +#if !OPENH264_VER_AT_LEAST(1, 6) + param.eOutputColorFormat = videoFormatI420; +#endif + param.eEcActiveIdc = ERROR_CON_DISABLE; + param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; + + if ((*s->decoder)->Initialize(s->decoder, ¶m) != cmResultSuccess) { + av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); + return AVERROR_UNKNOWN; + } + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + return 0; +} + +static int init_bsf(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + const AVBitStreamFilter *filter; + int ret; + + if (s->bsf) + return 0; + + // If the input stream already is annex b, this BSF only passes the + // packets through unchanged. + filter = av_bsf_get_by_name("h264_mp4toannexb"); + if (!filter) + return AVERROR_BUG; + + ret = av_bsf_alloc(filter, &s->bsf); + if (ret < 0) + return ret; + + ret = avcodec_parameters_from_context(s->bsf->par_in, avctx); + if (ret < 0) + return ret; + + s->bsf->time_base_in = avctx->time_base; + + ret = av_bsf_init(s->bsf); + if (ret < 0) + return ret; + + return ret; +} + +static int svc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + SVCContext *s = avctx->priv_data; + SBufferInfo info = { 0 }; + uint8_t* ptrs[3]; + int linesize[3]; + AVFrame *avframe = data; + int ret; + DECODING_STATE state; + + if ((ret = init_bsf(avctx)) < 0) + return ret; + + if (avpkt->size) { + AVPacket input_ref = { 0 }; + if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { + ret = av_fifo_realloc2(s->packet_fifo, + av_fifo_size(s->packet_fifo) + sizeof(input_ref)); + if (ret < 0) + return ret; + } + + ret = av_packet_ref(&input_ref, avpkt); + if (ret < 0) + return ret; + av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + } + + while (!*got_frame) { + /* prepare the input data -- convert to Annex B if needed */ + if (s->pkt_filtered.size <= 0) { + AVPacket input_ref; + + /* no more data */ + if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) + return avpkt->size ? avpkt->size : 0; + + av_packet_unref(&s->pkt_filtered); + + av_fifo_generic_read(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + ret = av_bsf_send_packet(s->bsf, &input_ref); + if (ret < 0) { + av_packet_unref(&input_ref); + return ret; + } + + ret = av_bsf_receive_packet(s->bsf, &s->pkt_filtered); + if (ret < 0) + av_packet_move_ref(&s->pkt_filtered, &input_ref); + else + av_packet_unref(&input_ref); + } + + state = (*s->decoder)->DecodeFrame2(s->decoder, s->pkt_filtered.data, s->pkt_filtered.size, ptrs, &info); + s->pkt_filtered.size = 0; + if (state != dsErrorFree) { + av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n"); + return AVERROR_UNKNOWN; + } + if (info.iBufferStatus != 1) { + av_log(avctx, AV_LOG_DEBUG, "No frame produced\n"); + continue; + } + + ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight); + // The decoder doesn't (currently) support decoding into a user + // provided buffer, so do a copy instead. + if (ff_get_buffer(avctx, avframe, 0) < 0) { + av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); + return AVERROR(ENOMEM); + } + + linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; + linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; + av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); + + avframe->pts = s->pkt_filtered.pts; + avframe->pkt_dts = s->pkt_filtered.dts; +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS + avframe->pkt_pts = s->pkt_filtered.pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + *got_frame = 1; + } + return avpkt->size; +} + +AVCodec ff_libopenh264_decoder = { + .name = "libopenh264", + .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(SVCContext), + .init = svc_decode_init, + .decode = svc_decode_frame, + .close = svc_decode_close, + // The decoder doesn't currently support B-frames, and the decoder's API + // doesn't support reordering/delay, but the BSF could incur delay. + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c new file mode 100644 index 0000000..a09b7cf --- /dev/null +++ b/libavcodec/libopenh264enc.c @@ -0,0 +1,301 @@ +/* + * OpenH264 video encoder + * Copyright (C) 2014 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" + +#include "avcodec.h" +#include "internal.h" +#include "libopenh264.h" + +#if !OPENH264_VER_AT_LEAST(1, 6) +#define SM_SIZELIMITED_SLICE SM_DYN_SLICE +#endif + +typedef struct SVCContext { + const AVClass *av_class; + ISVCEncoder *encoder; + int slice_mode; + int loopfilter; + char *profile; + int max_nal_size; + int skip_frames; + int skipped; + int cabac; +} SVCContext; + +#define OFFSET(x) offsetof(SVCContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +#if OPENH264_VER_AT_LEAST(1, 6) + { "slice_mode", "Slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" }, +#else + { "slice_mode", "Slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" }, +#endif + { "fixed", "A fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" }, +#if OPENH264_VER_AT_LEAST(1, 6) + { "dyn", "Size limited (compatibility name)", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" }, + { "sizelimited", "Size limited", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" }, +#else + { "rowmb", "One slice per row of macroblocks", 0, AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0, VE, "slice_mode" }, + { "auto", "Automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" }, + { "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" }, +#endif + { "loopfilter", "Enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "profile", "Set profile restrictions", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, + { "max_nal_size", "Set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + { "allow_skip_frames", "Allow skipping frames to hit the target bitrate", OFFSET(skip_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "cabac", "Enable cabac", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL } +}; + +static const AVClass class = { + "libopenh264enc", av_default_item_name, options, LIBAVUTIL_VERSION_INT +}; + +static av_cold int svc_encode_close(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + + if (s->encoder) + WelsDestroySVCEncoder(s->encoder); + if (s->skipped > 0) + av_log(avctx, AV_LOG_WARNING, "%d frames skipped\n", s->skipped); + return 0; +} + +static av_cold int svc_encode_init(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + SEncParamExt param = { 0 }; + int err; + int log_level; + WelsTraceCallback callback_function; + AVCPBProperties *props; + + if ((err = ff_libopenh264_check_version(avctx)) < 0) + return err; + + if (WelsCreateSVCEncoder(&s->encoder)) { + av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); + return AVERROR_UNKNOWN; + } + + // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. + log_level = WELS_LOG_DETAIL; + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level); + + // Set the logging callback function to one that uses av_log() (see implementation above). + callback_function = (WelsTraceCallback) ff_libopenh264_trace_callback; + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); + + // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log(). + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx); + + (*s->encoder)->GetDefaultParams(s->encoder, ¶m); + +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (!s->cabac) + s->cabac = avctx->coder_type == FF_CODER_TYPE_AC; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + param.fMaxFrameRate = avctx->time_base.den / avctx->time_base.num; + param.iPicWidth = avctx->width; + param.iPicHeight = avctx->height; + param.iTargetBitrate = avctx->bit_rate; + param.iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate); + param.iRCMode = RC_QUALITY_MODE; + param.iTemporalLayerNum = 1; + param.iSpatialLayerNum = 1; + param.bEnableDenoise = 0; + param.bEnableBackgroundDetection = 1; + param.bEnableAdaptiveQuant = 1; + param.bEnableFrameSkip = s->skip_frames; + param.bEnableLongTermReference = 0; + param.iLtrMarkPeriod = 30; + param.uiIntraPeriod = avctx->gop_size; +#if OPENH264_VER_AT_LEAST(1, 4) + param.eSpsPpsIdStrategy = CONSTANT_ID; +#else + param.bEnableSpsPpsIdAddition = 0; +#endif + param.bPrefixNalAddingCtrl = 0; + param.iLoopFilterDisableIdc = !s->loopfilter; + param.iEntropyCodingModeFlag = 0; + param.iMultipleThreadIdc = avctx->thread_count; + if (s->profile && !strcmp(s->profile, "main")) + param.iEntropyCodingModeFlag = 1; + else if (!s->profile && s->cabac) + param.iEntropyCodingModeFlag = 1; + + param.sSpatialLayers[0].iVideoWidth = param.iPicWidth; + param.sSpatialLayers[0].iVideoHeight = param.iPicHeight; + param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate; + param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate; + param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate; + + if ((avctx->slices > 1) && (s->max_nal_size)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid combination -slices %d and -max_nal_size %d.\n", + avctx->slices, s->max_nal_size); + return AVERROR(EINVAL); + } + + if (avctx->slices > 1) + s->slice_mode = SM_FIXEDSLCNUM_SLICE; + + if (s->max_nal_size) + s->slice_mode = SM_SIZELIMITED_SLICE; + +#if OPENH264_VER_AT_LEAST(1, 6) + param.sSpatialLayers[0].sSliceArgument.uiSliceMode = s->slice_mode; + param.sSpatialLayers[0].sSliceArgument.uiSliceNum = avctx->slices; +#else + param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode; + param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices; +#endif + + if (s->slice_mode == SM_SIZELIMITED_SLICE) { + if (s->max_nal_size){ + param.uiMaxNalSize = s->max_nal_size; +#if OPENH264_VER_AT_LEAST(1, 6) + param.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; +#else + param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; +#endif + } else { + av_log(avctx, AV_LOG_ERROR, "Invalid -max_nal_size, " + "specify a valid max_nal_size to use -slice_mode dyn\n"); + return AVERROR(EINVAL); + } + } + + if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { + av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); + return AVERROR_UNKNOWN; + } + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + SFrameBSInfo fbi = { 0 }; + int i, size = 0; + (*s->encoder)->EncodeParameterSets(s->encoder, &fbi); + for (i = 0; i < fbi.sLayerInfo[0].iNalCount; i++) + size += fbi.sLayerInfo[0].pNalLengthInByte[i]; + avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = size; + memcpy(avctx->extradata, fbi.sLayerInfo[0].pBsBuf, size); + } + + props = ff_add_cpb_side_data(avctx); + if (!props) + return AVERROR(ENOMEM); + props->max_bitrate = param.iMaxBitrate; + props->avg_bitrate = param.iTargetBitrate; + + return 0; +} + +static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet) +{ + SVCContext *s = avctx->priv_data; + SFrameBSInfo fbi = { 0 }; + int i, ret; + int encoded; + SSourcePicture sp = { 0 }; + int size = 0, layer, first_layer = 0; + int layer_size[MAX_LAYER_NUM_OF_FRAME] = { 0 }; + + sp.iColorFormat = videoFormatI420; + for (i = 0; i < 3; i++) { + sp.iStride[i] = frame->linesize[i]; + sp.pData[i] = frame->data[i]; + } + sp.iPicWidth = avctx->width; + sp.iPicHeight = avctx->height; + + encoded = (*s->encoder)->EncodeFrame(s->encoder, &sp, &fbi); + if (encoded != cmResultSuccess) { + av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed\n"); + return AVERROR_UNKNOWN; + } + if (fbi.eFrameType == videoFrameTypeSkip) { + s->skipped++; + av_log(avctx, AV_LOG_DEBUG, "frame skipped\n"); + return 0; + } + first_layer = 0; + // Normal frames are returned with one single layer, while IDR + // frames have two layers, where the first layer contains the SPS/PPS. + // If using global headers, don't include the SPS/PPS in the returned + // packet - thus, only return one layer. + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) + first_layer = fbi.iLayerNum - 1; + + for (layer = first_layer; layer < fbi.iLayerNum; layer++) { + for (i = 0; i < fbi.sLayerInfo[layer].iNalCount; i++) + layer_size[layer] += fbi.sLayerInfo[layer].pNalLengthInByte[i]; + size += layer_size[layer]; + } + av_log(avctx, AV_LOG_DEBUG, "%d slices\n", fbi.sLayerInfo[fbi.iLayerNum - 1].iNalCount); + + if ((ret = ff_alloc_packet(avpkt, size))) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); + return ret; + } + size = 0; + for (layer = first_layer; layer < fbi.iLayerNum; layer++) { + memcpy(avpkt->data + size, fbi.sLayerInfo[layer].pBsBuf, layer_size[layer]); + size += layer_size[layer]; + } + avpkt->pts = frame->pts; + if (fbi.eFrameType == videoFrameTypeIDR) + avpkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +AVCodec ff_libopenh264_encoder = { + .name = "libopenh264", + .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(SVCContext), + .init = svc_encode_init, + .encode2 = svc_encode_frame, + .close = svc_encode_close, + .capabilities = AV_CODEC_CAP_AUTO_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .priv_class = &class, +}; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index c7697a5..401ea9b 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -74,7 +74,7 @@ static const enum AVPixelFormat any_pix_fmts[] = { RGB_PIXEL_FORMATS, GRAY_PIXEL_FORMATS, YUV_PIXEL_FORMATS, XYZ_PIXEL_FORMATS }; -typedef struct { +typedef struct LibOpenJPEGContext { AVClass *class; opj_dparameters_t dec_params; int lowres; @@ -94,22 +94,22 @@ static int libopenjpeg_matches_pix_fmt(const opj_image_t *img, switch (desc->nb_components) { case 4: match = match && - desc->comp[3].depth_minus1 + 1 >= img->comps[3].prec && + desc->comp[3].depth >= img->comps[3].prec && 1 == img->comps[3].dx && 1 == img->comps[3].dy; case 3: match = match && - desc->comp[2].depth_minus1 + 1 >= img->comps[2].prec && + desc->comp[2].depth >= img->comps[2].prec && 1 << desc->log2_chroma_w == img->comps[2].dx && 1 << desc->log2_chroma_h == img->comps[2].dy; case 2: match = match && - desc->comp[1].depth_minus1 + 1 >= img->comps[1].prec && + desc->comp[1].depth >= img->comps[1].prec && 1 << desc->log2_chroma_w == img->comps[1].dx && 1 << desc->log2_chroma_h == img->comps[1].dy; case 1: match = match && - desc->comp[0].depth_minus1 + 1 >= img->comps[0].prec && + desc->comp[0].depth >= img->comps[0].prec && 1 == img->comps[0].dx && 1 == img->comps[0].dy; default: @@ -365,7 +365,7 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, } desc = av_pix_fmt_desc_get(avctx->pix_fmt); - pixel_size = desc->comp[0].step_minus1 + 1; + pixel_size = desc->comp[0].step; ispacked = libopenjpeg_ispacked(avctx->pix_fmt); switch (pixel_size) { @@ -436,6 +436,6 @@ AVCodec ff_libopenjpeg_decoder = { .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_decode_init, .decode = libopenjpeg_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_class = &class, }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 2c2109f..d1af021 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -34,7 +34,7 @@ #include "avcodec.h" #include "internal.h" -typedef struct { +typedef struct LibOpenJPEGContext { AVClass *avclass; opj_image_t *image; opj_cparameters_t enc_params; @@ -131,8 +131,8 @@ static opj_image_t *libopenjpeg_create_image(AVCodecContext *avctx, } for (i = 0; i < numcomps; i++) { - cmptparm[i].prec = desc->comp[i].depth_minus1 + 1; - cmptparm[i].bpp = desc->comp[i].depth_minus1 + 1; + cmptparm[i].prec = desc->comp[i].depth; + cmptparm[i].bpp = desc->comp[i].depth; cmptparm[i].sgnd = 0; cmptparm[i].dx = sub_dx[i]; cmptparm[i].dy = sub_dy[i]; @@ -169,12 +169,6 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); - goto fail; - } - ctx->image = libopenjpeg_create_image(avctx, &ctx->enc_params); if (!ctx->image) { av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); @@ -191,7 +185,6 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) fail: av_freep(&ctx->compress); - av_freep(&avctx->coded_frame); return err; } @@ -371,7 +364,6 @@ static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) opj_destroy_compress(ctx->compress); opj_image_destroy(ctx->image); - av_freep(&avctx->coded_frame); return 0; } diff --git a/libavcodec/libopus.c b/libavcodec/libopus.c index b511415..9a0d5b0 100644 --- a/libavcodec/libopus.c +++ b/libavcodec/libopus.c @@ -2,20 +2,20 @@ * libopus encoder/decoder common code * Copyright (c) 2012 Nicolas George * - * This file is part of libav. + * This file is part of Libav. * - * libav is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * libav is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with libav; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavcodec/libopus.h b/libavcodec/libopus.h index b08257d..2334c84 100644 --- a/libavcodec/libopus.h +++ b/libavcodec/libopus.h @@ -2,20 +2,20 @@ * libopus encoder/decoder common code * Copyright (c) 2012 Nicolas George * - * This file is part of libav. + * This file is part of Libav. * - * libav is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * libav is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with libav; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 398450f..75eaf9b 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -22,8 +22,8 @@ #include #include -#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" + #include "avcodec.h" #include "internal.h" #include "vorbis.h" @@ -42,6 +42,12 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; uint8_t mapping_arr[8] = { 0, 1 }, *mapping; + if (avc->channels <= 0) { + av_log(avc, AV_LOG_WARNING, + "Invalid number of channels %d, defaulting to stereo\n", avc->channels); + avc->channels = 2; + } + avc->sample_rate = 48000; avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; @@ -73,7 +79,7 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; int ch; - /* Remap channels from vorbis order to libav order */ + /* Remap channels from Vorbis order to libav order */ for (ch = 0; ch < avc->channels; ch++) mapping_arr[ch] = mapping[vorbis_offset[ch]]; mapping = mapping_arr; @@ -160,7 +166,7 @@ AVCodec ff_libopus_decoder = { .close = libopus_decode_close, .decode = libopus_decode, .flush = libopus_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 8f75466..1fb597b 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -2,20 +2,20 @@ * Opus encoder using libopus * Copyright (c) 2012 Nathan Caldwell * - * This file is part of libav. + * This file is part of Libav. * - * libav is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * libav is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with libav; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -87,7 +87,7 @@ static void libopus_write_header(AVCodecContext *avctx, int stream_count, bytestream_put_buffer(&p, "OpusHead", 8); bytestream_put_byte(&p, 1); /* Version */ bytestream_put_byte(&p, channels); - bytestream_put_le16(&p, avctx->delay); /* Lookahead samples at 48kHz */ + bytestream_put_le16(&p, avctx->initial_padding); /* Lookahead samples at 48kHz */ bytestream_put_le32(&p, avctx->sample_rate); /* Original sample rate */ bytestream_put_le16(&p, 0); /* Gain of 0dB is recommended. */ @@ -262,7 +262,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx) } header_size = 19 + (avctx->channels > 2 ? 2 + avctx->channels : 0); - avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_malloc(header_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata.\n"); ret = AVERROR(ENOMEM); @@ -278,7 +278,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx) goto fail; } - ret = opus_multistream_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&avctx->delay)); + ret = opus_multistream_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&avctx->initial_padding)); if (ret != OPUS_OK) av_log(avctx, AV_LOG_WARNING, "Unable to get number of lookahead samples: %s\n", @@ -309,7 +309,9 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, int ret; if (frame) { - ff_af_queue_add(&opus->afq, frame); + ret = ff_af_queue_add(&opus->afq, frame); + if (ret < 0) + return ret; if (frame->nb_samples < opus->opts.packet_size) { audio = opus->samples; memcpy(audio, frame->data[0], frame->nb_samples * sample_size); @@ -411,7 +413,7 @@ AVCodec ff_libopus_encoder = { .init = libopus_encode_init, .encode2 = libopus_encode, .close = libopus_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/libschroedinger.c b/libavcodec/libschroedinger.c index fc9188c..16e0fe8 100644 --- a/libavcodec/libschroedinger.c +++ b/libavcodec/libschroedinger.c @@ -26,6 +26,7 @@ #include "libavutil/attributes.h" #include "libavutil/mem.h" #include "libschroedinger.h" +#include "internal.h" static const SchroVideoFormatInfo ff_schro_video_format_info[] = { { 640, 480, 24000, 1001}, @@ -167,19 +168,14 @@ int ff_get_schro_frame_format (SchroChromaFormat schro_pix_fmt, static void free_schro_frame(SchroFrame *frame, void *priv) { - AVPicture *p_pic = priv; - - if (!p_pic) - return; - - avpicture_free(p_pic); - av_freep(&p_pic); + AVFrame *p_pic = priv; + av_frame_free(&p_pic); } SchroFrame *ff_create_schro_frame(AVCodecContext *avctx, SchroFrameFormat schro_frame_fmt) { - AVPicture *p_pic; + AVFrame *p_pic; SchroFrame *p_frame; int y_width, uv_width; int y_height, uv_height; @@ -190,8 +186,15 @@ SchroFrame *ff_create_schro_frame(AVCodecContext *avctx, uv_width = y_width >> (SCHRO_FRAME_FORMAT_H_SHIFT(schro_frame_fmt)); uv_height = y_height >> (SCHRO_FRAME_FORMAT_V_SHIFT(schro_frame_fmt)); - p_pic = av_mallocz(sizeof(AVPicture)); - avpicture_alloc(p_pic, avctx->pix_fmt, y_width, y_height); + p_pic = av_frame_alloc(); + if (!p_pic) + return NULL; + + if (ff_get_buffer(avctx, p_pic, AV_GET_BUFFER_FLAG_REF) < 0) { + av_frame_free(&p_pic); + av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); + return NULL; + } p_frame = schro_frame_new(); p_frame->format = schro_frame_fmt; diff --git a/libavcodec/libschroedingerdec.c b/libavcodec/libschroedingerdec.c index 7e258e3..f173f92 100644 --- a/libavcodec/libschroedingerdec.c +++ b/libavcodec/libschroedingerdec.c @@ -37,10 +37,6 @@ #include "internal.h" #include "libschroedinger.h" -#undef NDEBUG -#include - - #include #include #include @@ -199,8 +195,8 @@ static void libschroedinger_handle_first_access_unit(AVCodecContext *avctx) return; } - avctx->time_base.den = p_schro_params->format->frame_rate_numerator; - avctx->time_base.num = p_schro_params->format->frame_rate_denominator; + avctx->framerate.num = p_schro_params->format->frame_rate_numerator; + avctx->framerate.den = p_schro_params->format->frame_rate_denominator; } static int libschroedinger_decode_frame(AVCodecContext *avctx, @@ -271,6 +267,8 @@ static int libschroedinger_decode_frame(AVCodecContext *avctx, /* Decoder needs a frame - create one and push it in. */ frame = ff_create_schro_frame(avctx, p_schro_params->frame_format); + if (!frame) + return AVERROR(ENOMEM); schro_decoder_add_output_picture(decoder, frame); break; @@ -328,7 +326,12 @@ static int libschroedinger_decode_frame(AVCodecContext *avctx, framewithpts->frame->components[2].length); /* Fill frame with current buffer data from Schroedinger. */ - avframe->pkt_pts = framewithpts->pts; + avframe->pts = framewithpts->pts; +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS + avframe->pkt_pts = avframe->pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif avframe->linesize[0] = framewithpts->frame->components[0].stride; avframe->linesize[1] = framewithpts->frame->components[1].stride; avframe->linesize[2] = framewithpts->frame->components[2].stride; @@ -385,6 +388,6 @@ AVCodec ff_libschroedinger_decoder = { .init = libschroedinger_decode_init, .close = libschroedinger_decode_close, .decode = libschroedinger_decode_frame, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .flush = libschroedinger_flush, }; diff --git a/libavcodec/libschroedingerenc.c b/libavcodec/libschroedingerenc.c index 3dc1481..bf03cb7 100644 --- a/libavcodec/libschroedingerenc.c +++ b/libavcodec/libschroedingerenc.c @@ -32,6 +32,9 @@ #include #include "libavutil/attributes.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + #include "avcodec.h" #include "internal.h" #include "libschroedinger.h" @@ -69,6 +72,9 @@ typedef struct SchroEncoderParams { /* counter for frames submitted to encoder, used as dts */ int64_t dts; + + /** enable noarith */ + int noarith; } SchroEncoderParams; /** @@ -154,22 +160,24 @@ static av_cold int libschroedinger_encode_init(AVCodecContext *avctx) p_schro_params->format->frame_rate_numerator = avctx->time_base.den; p_schro_params->format->frame_rate_denominator = avctx->time_base.num; - p_schro_params->frame_size = avpicture_get_size(avctx->pix_fmt, - avctx->width, - avctx->height); - - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); + p_schro_params->frame_size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, + avctx->height, 1); if (!avctx->gop_size) { schro_encoder_setting_set_double(p_schro_params->encoder, "gop_structure", SCHRO_ENCODER_GOP_INTRA_ONLY); - if (avctx->coder_type == FF_CODER_TYPE_VLC) - schro_encoder_setting_set_double(p_schro_params->encoder, - "enable_noarith", 1); +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type != FF_CODER_TYPE_VLC) + p_schro_params->noarith = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + schro_encoder_setting_set_double(p_schro_params->encoder, + "enable_noarith", + p_schro_params->noarith); } else { schro_encoder_setting_set_double(p_schro_params->encoder, "au_distance", avctx->gop_size); @@ -178,7 +186,7 @@ static av_cold int libschroedinger_encode_init(AVCodecContext *avctx) } /* FIXME - Need to handle SCHRO_ENCODER_RATE_CONTROL_LOW_DELAY. */ - if (avctx->flags & CODEC_FLAG_QSCALE) { + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { if (!avctx->global_quality) { /* lossless coding */ schro_encoder_setting_set_double(p_schro_params->encoder, @@ -205,14 +213,14 @@ static av_cold int libschroedinger_encode_init(AVCodecContext *avctx) "bitrate", avctx->bit_rate); } - if (avctx->flags & CODEC_FLAG_INTERLACED_ME) + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) /* All material can be coded as interlaced or progressive irrespective of the type of source material. */ schro_encoder_setting_set_double(p_schro_params->encoder, "interlaced_coding", 1); schro_encoder_setting_set_double(p_schro_params->encoder, "open_gop", - !(avctx->flags & CODEC_FLAG_CLOSED_GOP)); + !(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)); /* FIXME: Signal range hardcoded to 8-bit data until both libschroedinger * and libdirac support other bit-depth data. */ @@ -237,17 +245,17 @@ static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avctx, const AVFrame *frame) { SchroEncoderParams *p_schro_params = avctx->priv_data; - SchroFrame *in_frame; - /* Input line size may differ from what the codec supports. Especially - * when transcoding from one format to another. So use avpicture_layout - * to copy the frame. */ - in_frame = ff_create_schro_frame(avctx, p_schro_params->frame_format); - - if (in_frame) - avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, - avctx->width, avctx->height, - in_frame->components[0].data, - p_schro_params->frame_size); + SchroFrame *in_frame = ff_create_schro_frame(avctx, + p_schro_params->frame_format); + + if (in_frame) { + /* Copy input data to SchroFrame buffers (they match the ones + * referenced by the AVFrame stored in priv) */ + if (av_frame_copy(in_frame->priv, frame) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to copy input data\n"); + return NULL; + } + } return in_frame; } @@ -283,6 +291,8 @@ static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } else { /* Allocate frame data to schro input buffer. */ SchroFrame *in_frame = libschroedinger_frame_from_data(avctx, frame); + if (!in_frame) + return AVERROR(ENOMEM); /* Load next frame. */ schro_encoder_push_frame(encoder, in_frame); } @@ -331,6 +341,8 @@ static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* Create output frame. */ p_frame_output = av_mallocz(sizeof(FFSchroEncodedFrame)); + if (!p_frame_output) + return AVERROR(ENOMEM); /* Set output data. */ p_frame_output->size = p_schro_params->enc_buf_size; p_frame_output->p_encbuf = p_schro_params->enc_buf; @@ -339,7 +351,7 @@ static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, p_frame_output->key_frame = 1; /* Parse the coded frame number from the bitstream. Bytes 14 - * through 17 represesent the frame number. */ + * through 17 represent the frame number. */ p_frame_output->frame_num = AV_RB32(enc_buf->data + 13); ff_schro_queue_push_back(&p_schro_params->enc_frame_queue, @@ -384,12 +396,16 @@ static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } memcpy(pkt->data, p_frame_output->p_encbuf, p_frame_output->size); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = p_frame_output->key_frame; + avctx->coded_frame->pts = p_frame_output->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* Use the frame number of the encoded frame as the pts. It is OK to * do so since Dirac is a constant frame rate codec. It expects input * to be of constant frame rate. */ - pkt->pts = - avctx->coded_frame->pts = p_frame_output->frame_num; + pkt->pts = p_frame_output->frame_num; pkt->dts = p_schro_params->dts++; enc_size = p_frame_output->size; @@ -433,11 +449,23 @@ static int libschroedinger_encode_close(AVCodecContext *avctx) /* Free the video format structure. */ av_freep(&p_schro_params->format); - av_frame_free(&avctx->coded_frame); - return 0; } +#define OFFSET(x) offsetof(SchroEncoderParams, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "noarith", "Enable noarith", OFFSET(noarith), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + + { NULL }, +}; + +static const AVClass libschroedinger_class = { + .class_name = "libschroedinger", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_libschroedinger_encoder = { .name = "libschroedinger", @@ -445,10 +473,11 @@ AVCodec ff_libschroedinger_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DIRAC, .priv_data_size = sizeof(SchroEncoderParams), + .priv_class = &libschroedinger_class, .init = libschroedinger_encode_init, .encode2 = libschroedinger_encode_frame, .close = libschroedinger_encode_close, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index d00696e..949a934 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -28,7 +28,7 @@ #include "avcodec.h" #include "internal.h" -typedef struct { +typedef struct LibSpeexContext { SpeexBits bits; SpeexStereoState stereo; void *dec_state; @@ -178,5 +178,5 @@ AVCodec ff_libspeex_decoder = { .close = libspeex_decode_close, .decode = libspeex_decode_frame, .flush = libspeex_decode_flush, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index 651d7ac..f3a31e9 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -40,7 +40,7 @@ * used to set the encoding mode. * * Rate Control - * VBR mode is turned on by setting CODEC_FLAG_QSCALE in avctx->flags. + * VBR mode is turned on by setting AV_CODEC_FLAG_QSCALE in avctx->flags. * avctx->global_quality is used to set the encoding quality. * For CBR mode, avctx->bit_rate can be used to set the constant bitrate. * Alternatively, the 'cbr_quality' option can be set from 0 to 10 to set @@ -92,7 +92,7 @@ #include "internal.h" #include "audio_frame_queue.h" -typedef struct { +typedef struct LibSpeexEncContext { AVClass *class; ///< AVClass for private options SpeexBits bits; ///< libspeex bitwriter context SpeexHeader header; ///< libspeex header struct @@ -176,7 +176,7 @@ static av_cold int encode_init(AVCodecContext *avctx) speex_init_header(&s->header, avctx->sample_rate, avctx->channels, mode); /* rate control method and parameters */ - if (avctx->flags & CODEC_FLAG_QSCALE) { + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { /* VBR */ s->header.vbr = 1; s->vad = 1; /* VAD is always implicitly activated for VBR */ @@ -215,7 +215,7 @@ static av_cold int encode_init(AVCodecContext *avctx) if (s->vad) speex_encoder_ctl(s->enc_state, SPEEX_SET_VAD, &s->vad); - /* Activiting Discontinuous Transmission */ + /* Activating Discontinuous Transmission */ if (s->dtx) { speex_encoder_ctl(s->enc_state, SPEEX_SET_DTX, &s->dtx); if (!(s->abr || s->vad || s->header.vbr)) @@ -235,7 +235,7 @@ static av_cold int encode_init(AVCodecContext *avctx) s->header.frames_per_packet = s->frames_per_packet; /* set encoding delay */ - speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &avctx->delay); + speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &avctx->initial_padding); ff_af_queue_init(avctx, &s->afq); /* create header packet bytes from header struct */ @@ -243,8 +243,8 @@ static av_cold int encode_init(AVCodecContext *avctx) below with speex_header_free() */ header_data = speex_header_to_packet(&s->header, &header_size); - /* allocate extradata and coded_frame */ - avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE); + /* allocate extradata */ + avctx->extradata = av_malloc(header_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { speex_header_free(header_data); speex_encoder_destroy(s->enc_state); @@ -357,7 +357,7 @@ AVCodec ff_libspeex_encoder = { .init = encode_init, .encode2 = encode_frame, .close = encode_close, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index 75b0a16..b329ed3 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -101,6 +101,8 @@ static int get_stats(AVCodecContext *avctx, int eos) if (!eos) { h->stats = av_fast_realloc(h->stats, &h->stats_size, h->stats_offset + bytes); + if (!h->stats) + return AVERROR(ENOMEM); memcpy(h->stats + h->stats_offset, buf, bytes); h->stats_offset += bytes; } else { @@ -108,6 +110,8 @@ static int get_stats(AVCodecContext *avctx, int eos) // libtheora generates a summary header at the end memcpy(h->stats, buf, bytes); avctx->stats_out = av_malloc(b64_size); + if (!avctx->stats_out) + return AVERROR(ENOMEM); av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset); } return 0; @@ -131,6 +135,8 @@ static int submit_stats(AVCodecContext *avctx) } h->stats_size = strlen(avctx->stats_in) * 3/4; h->stats = av_malloc(h->stats_size); + if (!h->stats) + return AVERROR(ENOMEM); h->stats_size = av_base64_decode(h->stats, avctx->stats_in, h->stats_size); } while (h->stats_size - h->stats_offset > 0) { @@ -201,7 +207,7 @@ static av_cold int encode_init(AVCodecContext* avc_context) av_pix_fmt_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); - if (avc_context->flags & CODEC_FLAG_QSCALE) { + if (avc_context->flags & AV_CODEC_FLAG_QSCALE) { /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 Theora accepts a quality parameter p, which is: * 0 <= p <=63 @@ -232,10 +238,10 @@ static av_cold int encode_init(AVCodecContext* avc_context) } // need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers - if (avc_context->flags & CODEC_FLAG_PASS1) { + if (avc_context->flags & AV_CODEC_FLAG_PASS1) { if (get_stats(avc_context, 0)) return -1; - } else if (avc_context->flags & CODEC_FLAG_PASS2) { + } else if (avc_context->flags & AV_CODEC_FLAG_PASS2) { if (submit_stats(avc_context)) return -1; } @@ -244,7 +250,7 @@ static av_cold int encode_init(AVCodecContext* avc_context) Output first header packet consisting of theora header, comment, and tables. - Each one is prefixed with a 16bit size, then they + Each one is prefixed with a 16-bit size, then they are concatenated together into libavcodec's extradata. */ offset = 0; @@ -258,9 +264,6 @@ static av_cold int encode_init(AVCodecContext* avc_context) th_comment_clear(&t_comment); - /* Set up the output AVFrame */ - avc_context->coded_frame = av_frame_alloc(); - return 0; } @@ -275,7 +278,7 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, // EOS, finish and get 1st pass stats if applicable if (!frame) { th_encode_packetout(h->t_state, 1, &o_packet); - if (avc_context->flags & CODEC_FLAG_PASS1) + if (avc_context->flags & AV_CODEC_FLAG_PASS1) if (get_stats(avc_context, 1)) return -1; return 0; @@ -289,7 +292,7 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, t_yuv_buffer[i].data = frame->data[i]; } - if (avc_context->flags & CODEC_FLAG_PASS2) + if (avc_context->flags & AV_CODEC_FLAG_PASS2) if (submit_stats(avc_context)) return -1; @@ -312,7 +315,7 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, return -1; } - if (avc_context->flags & CODEC_FLAG_PASS1) + if (avc_context->flags & AV_CODEC_FLAG_PASS1) if (get_stats(avc_context, 0)) return -1; @@ -340,8 +343,12 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, // HACK: assumes no encoder delay, this is true until libtheora becomes // multithreaded (which will be disabled unless explicitly requested) pkt->pts = pkt->dts = frame->pts; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); - if (avc_context->coded_frame->key_frame) +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (!(o_packet.granulepos & h->keyframe_mask)) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -354,7 +361,6 @@ static av_cold int encode_close(AVCodecContext* avc_context) th_encode_free(h->t_state); av_freep(&h->stats); - av_freep(&avc_context->coded_frame); av_freep(&avc_context->stats_out); av_freep(&avc_context->extradata); avc_context->extradata_size = 0; @@ -372,7 +378,7 @@ AVCodec ff_libtheora_encoder = { .init = encode_init, .close = encode_close, .encode2 = encode_frame, - .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary + .capabilities = AV_CODEC_CAP_DELAY, // needed to get the statsfile summary .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c index 7f7b2f7..714c30a 100644 --- a/libavcodec/libtwolame.c +++ b/libavcodec/libtwolame.c @@ -60,7 +60,7 @@ static av_cold int twolame_encode_init(AVCodecContext *avctx) int ret; avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME; - avctx->delay = 512 - 32 + 1; + avctx->initial_padding = 512 - 32 + 1; s->glopts = twolame_init(); if (!s->glopts) @@ -77,7 +77,7 @@ static av_cold int twolame_encode_init(AVCodecContext *avctx) twolame_set_num_channels(s->glopts, avctx->channels); twolame_set_in_samplerate(s->glopts, avctx->sample_rate); twolame_set_out_samplerate(s->glopts, avctx->sample_rate); - if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { + if (avctx->flags & AV_CODEC_FLAG_QSCALE || !avctx->bit_rate) { twolame_set_VBR(s->glopts, TRUE); twolame_set_VBR_level(s->glopts, avctx->global_quality / (float) FF_QP2LAMBDA); @@ -151,7 +151,7 @@ static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (frame) { avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); } else { avpkt->pts = s->next_pts; } @@ -207,7 +207,7 @@ AVCodec ff_libtwolame_encoder = { .init = twolame_encode_init, .encode2 = twolame_encode_frame, .close = twolame_encode_close, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, .defaults = twolame_defaults, .priv_class = &twolame_class, .sample_fmts = (const enum AVSampleFormat[]) { diff --git a/libavcodec/libvo-aacenc.c b/libavcodec/libvo-aacenc.c index 9450792..876ef4c 100644 --- a/libavcodec/libvo-aacenc.c +++ b/libavcodec/libvo-aacenc.c @@ -61,7 +61,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) int index, ret; avctx->frame_size = FRAME_SIZE; - avctx->delay = ENC_DELAY; + avctx->initial_padding = ENC_DELAY; s->last_frame = 2; ff_af_queue_init(avctx, &s->afq); @@ -85,7 +85,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) params.sampleRate = avctx->sample_rate; params.bitRate = avctx->bit_rate; params.nChannels = avctx->channels; - params.adtsUsed = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER); + params.adtsUsed = !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER); if (s->codec_api.SetParam(s->handle, VO_PID_AAC_ENCPARAM, ¶ms) != VO_ERR_NONE) { av_log(avctx, AV_LOG_ERROR, "Unable to set encoding parameters\n"); @@ -102,10 +102,10 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) ret = AVERROR(ENOSYS); goto error; } - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { avctx->extradata_size = 2; avctx->extradata = av_mallocz(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { ret = AVERROR(ENOMEM); goto error; @@ -188,7 +188,7 @@ AVCodec ff_libvo_aacenc_encoder = { .init = aac_encode_init, .encode2 = aac_encode_frame, .close = aac_encode_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index b255ba5..5fc904c 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -1,6 +1,6 @@ /* * AMR Audio encoder stub - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -51,7 +51,7 @@ static const AVClass class = { static int get_wb_bitrate_mode(int bitrate, void *log_ctx) { - /* make the correspondance between bitrate and mode */ + /* make the correspondence between bitrate and mode */ static const int rates[] = { 6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850 }; int i, best = -1, min_diff = 0; @@ -93,7 +93,7 @@ static av_cold int amr_wb_encode_init(AVCodecContext *avctx) s->last_bitrate = avctx->bit_rate; avctx->frame_size = 320; - avctx->delay = 80; + avctx->initial_padding = 80; s->state = E_IF_init(); @@ -131,7 +131,7 @@ static int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); avpkt->size = size; *got_packet_ptr = 1; diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c index 4b4caaa..86c1ed6 100644 --- a/libavcodec/libvorbis.c +++ b/libavcodec/libvorbis.c @@ -58,7 +58,7 @@ typedef struct LibvorbisContext { vorbis_comment vc; /**< VorbisComment info */ ogg_packet op; /**< ogg packet */ double iblock; /**< impulse block bias option */ - VorbisParseContext vp; /**< parse context to get durations */ + AVVorbisParseContext *vp; /**< parse context to get durations */ AudioFrameQueue afq; /**< frame queue for timestamps */ } LibvorbisContext; @@ -91,14 +91,14 @@ static av_cold int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx) double cfreq; int ret; - if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { + if (avctx->flags & AV_CODEC_FLAG_QSCALE || !avctx->bit_rate) { /* variable bitrate * NOTE: we use the oggenc range of -1 to 10 for global_quality for * user convenience, but libvorbis uses -0.1 to 1.0. */ float q = avctx->global_quality / (float)FF_QP2LAMBDA; /* default to 3 if the user did not set quality or bitrate */ - if (!(avctx->flags & CODEC_FLAG_QSCALE)) + if (!(avctx->flags & AV_CODEC_FLAG_QSCALE)) q = 3.0; if ((ret = vorbis_encode_setup_vbr(vi, avctx->channels, avctx->sample_rate, @@ -163,6 +163,8 @@ static av_cold int libvorbis_encode_close(AVCodecContext *avctx) ff_af_queue_close(&s->afq); av_freep(&avctx->extradata); + av_vorbis_parse_free(&s->vp); + return 0; } @@ -204,7 +206,7 @@ static av_cold int libvorbis_encode_init(AVCodecContext *avctx) xiph_len(header_comm.bytes) + header_code.bytes; p = avctx->extradata = av_malloc(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!p) { ret = AVERROR(ENOMEM); goto error; @@ -221,7 +223,8 @@ static av_cold int libvorbis_encode_init(AVCodecContext *avctx) offset += header_code.bytes; assert(offset == avctx->extradata_size); - if ((ret = avpriv_vorbis_parse_extradata(avctx, &s->vp)) < 0) { + s->vp = av_vorbis_parse_init(avctx->extradata, avctx->extradata_size); + if (!s->vp) { av_log(avctx, AV_LOG_ERROR, "invalid extradata\n"); return ret; } @@ -318,12 +321,12 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos); - duration = avpriv_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size); + duration = av_vorbis_parse_frame(s->vp, avpkt->data, avpkt->size); if (duration > 0) { /* we do not know encoder delay until we get the first packet from * libvorbis, so we have to update the AudioFrameQueue counts */ - if (!avctx->delay) { - avctx->delay = duration; + if (!avctx->initial_padding) { + avctx->initial_padding = duration; s->afq.remaining_delay += duration; s->afq.remaining_samples += duration; } @@ -343,7 +346,7 @@ AVCodec ff_libvorbis_encoder = { .init = libvorbis_encode_init, .encode2 = libvorbis_encode_frame, .close = libvorbis_encode_close, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &class, diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c index 20f4484..49f966d 100644 --- a/libavcodec/libvpx.c +++ b/libavcodec/libvpx.c @@ -22,14 +22,58 @@ #include "libvpx.h" -int ff_vp9_check_experimental(AVCodecContext *avctx) +enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img) { - if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL && - (vpx_codec_version_major() < 1 || - (vpx_codec_version_major() == 1 && vpx_codec_version_minor() < 3))) { - av_log(avctx, AV_LOG_ERROR, - "Non-experimental support of VP9 requires libvpx >= 1.3.0\n"); - return AVERROR_EXPERIMENTAL; + switch (img) { + case VPX_IMG_FMT_RGB24: return AV_PIX_FMT_RGB24; + case VPX_IMG_FMT_RGB565: return AV_PIX_FMT_RGB565BE; + case VPX_IMG_FMT_RGB555: return AV_PIX_FMT_RGB555BE; + case VPX_IMG_FMT_UYVY: return AV_PIX_FMT_UYVY422; + case VPX_IMG_FMT_YUY2: return AV_PIX_FMT_YUYV422; + case VPX_IMG_FMT_YVYU: return AV_PIX_FMT_YVYU422; + case VPX_IMG_FMT_BGR24: return AV_PIX_FMT_BGR24; + case VPX_IMG_FMT_ARGB: return AV_PIX_FMT_ARGB; + case VPX_IMG_FMT_ARGB_LE: return AV_PIX_FMT_BGRA; + case VPX_IMG_FMT_RGB565_LE: return AV_PIX_FMT_RGB565LE; + case VPX_IMG_FMT_RGB555_LE: return AV_PIX_FMT_RGB555LE; + case VPX_IMG_FMT_I420: return AV_PIX_FMT_YUV420P; + case VPX_IMG_FMT_I422: return AV_PIX_FMT_YUV422P; + case VPX_IMG_FMT_I444: return AV_PIX_FMT_YUV444P; + case VPX_IMG_FMT_444A: return AV_PIX_FMT_YUVA444P; +#if VPX_IMAGE_ABI_VERSION >= 3 + case VPX_IMG_FMT_I440: return AV_PIX_FMT_YUV440P; + case VPX_IMG_FMT_I42016: return AV_PIX_FMT_YUV420P16BE; + case VPX_IMG_FMT_I42216: return AV_PIX_FMT_YUV422P16BE; + case VPX_IMG_FMT_I44416: return AV_PIX_FMT_YUV444P16BE; +#endif + default: return AV_PIX_FMT_NONE; + } +} + +vpx_img_fmt_t ff_vpx_pixfmt_to_imgfmt(enum AVPixelFormat pix) +{ + switch (pix) { + case AV_PIX_FMT_RGB24: return VPX_IMG_FMT_RGB24; + case AV_PIX_FMT_RGB565BE: return VPX_IMG_FMT_RGB565; + case AV_PIX_FMT_RGB555BE: return VPX_IMG_FMT_RGB555; + case AV_PIX_FMT_UYVY422: return VPX_IMG_FMT_UYVY; + case AV_PIX_FMT_YUYV422: return VPX_IMG_FMT_YUY2; + case AV_PIX_FMT_YVYU422: return VPX_IMG_FMT_YVYU; + case AV_PIX_FMT_BGR24: return VPX_IMG_FMT_BGR24; + case AV_PIX_FMT_ARGB: return VPX_IMG_FMT_ARGB; + case AV_PIX_FMT_BGRA: return VPX_IMG_FMT_ARGB_LE; + case AV_PIX_FMT_RGB565LE: return VPX_IMG_FMT_RGB565_LE; + case AV_PIX_FMT_RGB555LE: return VPX_IMG_FMT_RGB555_LE; + case AV_PIX_FMT_YUV420P: return VPX_IMG_FMT_I420; + case AV_PIX_FMT_YUV422P: return VPX_IMG_FMT_I422; + case AV_PIX_FMT_YUV444P: return VPX_IMG_FMT_I444; + case AV_PIX_FMT_YUVA444P: return VPX_IMG_FMT_444A; +#if VPX_IMAGE_ABI_VERSION >= 3 + case AV_PIX_FMT_YUV440P: return VPX_IMG_FMT_I440; + case AV_PIX_FMT_YUV420P16BE: return VPX_IMG_FMT_I42016; + case AV_PIX_FMT_YUV422P16BE: return VPX_IMG_FMT_I42216; + case AV_PIX_FMT_YUV444P16BE: return VPX_IMG_FMT_I44416; +#endif + default: return VPX_IMG_FMT_NONE; } - return 0; } diff --git a/libavcodec/libvpx.h b/libavcodec/libvpx.h index cb1ed09..b437f37 100644 --- a/libavcodec/libvpx.h +++ b/libavcodec/libvpx.h @@ -21,8 +21,11 @@ #ifndef AVCODEC_LIBVPX_H #define AVCODEC_LIBVPX_H +#include + #include "avcodec.h" -int ff_vp9_check_experimental(AVCodecContext *avctx); +enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img); +vpx_img_fmt_t ff_vpx_pixfmt_to_imgfmt(enum AVPixelFormat pix); #endif /* AVCODEC_LIBVPX_H */ diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 6052207..6d3b29f 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -56,7 +56,6 @@ static av_cold int vpx_init(AVCodecContext *avctx, return AVERROR(EINVAL); } - avctx->pix_fmt = AV_PIX_FMT_YUV420P; return 0; } @@ -82,7 +81,8 @@ static int vp8_decode(AVCodecContext *avctx, } if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) { - if (img->fmt != VPX_IMG_FMT_I420) { + avctx->pix_fmt = ff_vpx_imgfmt_to_pixfmt(img->fmt); + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n", img->fmt); return AVERROR_INVALIDDATA; @@ -97,8 +97,18 @@ static int vp8_decode(AVCodecContext *avctx, } if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) return ret; - av_image_copy(picture->data, picture->linesize, img->planes, + av_image_copy(picture->data, picture->linesize, (const uint8_t **) img->planes, img->stride, avctx->pix_fmt, img->d_w, img->d_h); +#if VPX_IMAGE_ABI_VERSION >= 4 + switch (img->range) { + case VPX_CR_STUDIO_RANGE: + picture->color_range = AVCOL_RANGE_MPEG; + break; + case VPX_CR_FULL_RANGE: + picture->color_range = AVCOL_RANGE_JPEG; + break; + } +#endif *got_frame = 1; } return avpkt->size; @@ -126,16 +136,13 @@ AVCodec ff_libvpx_vp8_decoder = { .init = vp8_init, .close = vp8_free, .decode = vp8_decode, - .capabilities = CODEC_CAP_AUTO_THREADS | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, }; #endif /* CONFIG_LIBVPX_VP8_DECODER */ #if CONFIG_LIBVPX_VP9_DECODER static av_cold int vp9_init(AVCodecContext *avctx) { - int ret; - if ((ret = ff_vp9_check_experimental(avctx))) - return ret; return vpx_init(avctx, &vpx_codec_vp9_dx_algo); } @@ -148,6 +155,6 @@ AVCodec ff_libvpx_vp9_decoder = { .init = vp9_init, .close = vp8_free, .decode = vp8_decode, - .capabilities = CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_AUTO_THREADS, }; #endif /* CONFIG_LIBVPX_VP9_DECODER */ diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 0323885..bb4c98f 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -66,27 +66,22 @@ typedef struct VP8EncoderContext { int lag_in_frames; int error_resilient; int crf; + int static_thresh; + int drop_threshold; + int noise_sensitivity; } VP8Context; /** String mappings for enum vp8e_enc_control_id */ static const char *const ctlidstr[] = { - [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY", - [VP8E_UPD_REFERENCE] = "VP8E_UPD_REFERENCE", - [VP8E_USE_REFERENCE] = "VP8E_USE_REFERENCE", - [VP8E_SET_ROI_MAP] = "VP8E_SET_ROI_MAP", - [VP8E_SET_ACTIVEMAP] = "VP8E_SET_ACTIVEMAP", - [VP8E_SET_SCALEMODE] = "VP8E_SET_SCALEMODE", + [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", + [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", + [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", + [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", - [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", - [VP8E_GET_LAST_QUANTIZER] = "VP8E_GET_LAST_QUANTIZER", - [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", - [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", - [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", - [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", }; static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) @@ -209,7 +204,6 @@ static av_cold int vp8_free(AVCodecContext *avctx) vpx_codec_destroy(&ctx->encoder); av_freep(&ctx->twopass_stats.buf); - av_freep(&avctx->coded_frame); av_freep(&avctx->stats_out); free_frame_list(ctx->coded_frame_list); return 0; @@ -219,7 +213,8 @@ static av_cold int vpx_init(AVCodecContext *avctx, const struct vpx_codec_iface *iface) { VP8Context *ctx = avctx->priv_data; - struct vpx_codec_enc_cfg enccfg; + struct vpx_codec_enc_cfg enccfg = { 0 }; + AVCPBProperties *cpb_props; int res; av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); @@ -241,9 +236,9 @@ static av_cold int vpx_init(AVCodecContext *avctx, if (ctx->lag_in_frames >= 0) enccfg.g_lag_in_frames = ctx->lag_in_frames; - if (avctx->flags & CODEC_FLAG_PASS1) + if (avctx->flags & AV_CODEC_FLAG_PASS1) enccfg.g_pass = VPX_RC_FIRST_PASS; - else if (avctx->flags & CODEC_FLAG_PASS2) + else if (avctx->flags & AV_CODEC_FLAG_PASS2) enccfg.g_pass = VPX_RC_LAST_PASS; else enccfg.g_pass = VPX_RC_ONE_PASS; @@ -264,7 +259,14 @@ static av_cold int vpx_init(AVCodecContext *avctx, enccfg.rc_min_quantizer = avctx->qmin; if (avctx->qmax > 0) enccfg.rc_max_quantizer = avctx->qmax; - enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; + +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->frame_skip_threshold) + ctx->drop_threshold = avctx->frame_skip_threshold; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + enccfg.rc_dropframe_thresh = ctx->drop_threshold; //0-100 (0 => CBR, 100 => VBR) enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); @@ -320,8 +322,12 @@ static av_cold int vpx_init(AVCodecContext *avctx, /* 0-3: For non-zero values the encoder increasingly optimizes for reduced complexity playback on low powered devices at the expense of encode quality. */ - if (avctx->profile != FF_PROFILE_UNKNOWN) - enccfg.g_profile = avctx->profile; + if (avctx->profile != FF_PROFILE_UNKNOWN) + enccfg.g_profile = avctx->profile; + else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) + avctx->profile = enccfg.g_profile = FF_PROFILE_VP9_0; + else + avctx->profile = enccfg.g_profile = FF_PROFILE_VP9_1; enccfg.g_error_resilient = ctx->error_resilient; @@ -345,21 +351,45 @@ static av_cold int vpx_init(AVCodecContext *avctx, codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength); if (ctx->arnr_type >= 0) codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type); - codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); - codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); - codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold); + + if (CONFIG_LIBVPX_VP8_ENCODER && iface == &vpx_codec_vp8_cx_algo) { +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->noise_reduction) + ctx->noise_sensitivity = avctx->noise_reduction; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, ctx->noise_sensitivity); + codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); + } +#if FF_API_MPV_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->mb_threshold) { + av_log(avctx, AV_LOG_WARNING, "The mb_threshold option is deprecated, " + "use the static-thresh private option instead.\n"); + ctx->static_thresh = avctx->mb_threshold; + } + FF_ENABLE_DEPRECATION_WARNINGS +#endif + codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, ctx->static_thresh); codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); //provide dummy value to initialize wrapper, values will be updated each _encode() - vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, - (unsigned char*)1); + vpx_img_wrap(&ctx->rawimg, ff_vpx_pixfmt_to_imgfmt(avctx->pix_fmt), + avctx->width, avctx->height, 1, (unsigned char *)1); - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); - vp8_free(avctx); + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) return AVERROR(ENOMEM); + + if (enccfg.rc_end_usage == VPX_CBR || + enccfg.g_pass != VPX_RC_ONE_PASS) { + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->min_bitrate = avctx->rc_min_rate; + cpb_props->avg_bitrate = avctx->bit_rate; } + cpb_props->buffer_size = avctx->rc_buffer_size; + return 0; } @@ -381,20 +411,33 @@ static inline void cx_pktcpy(struct FrameListData *dst, * @return a negative AVERROR on error */ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, - AVPacket *pkt, AVFrame *coded_frame) + AVPacket *pkt) { int ret = ff_alloc_packet(pkt, cx_frame->sz); if (ret >= 0) { memcpy(pkt->data, cx_frame->buf, pkt->size); - pkt->pts = pkt->dts = cx_frame->pts; - coded_frame->pts = cx_frame->pts; - coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); - - if (coded_frame->key_frame) { - coded_frame->pict_type = AV_PICTURE_TYPE_I; - pkt->flags |= AV_PKT_FLAG_KEY; - } else - coded_frame->pict_type = AV_PICTURE_TYPE_P; + pkt->pts = pkt->dts = cx_frame->pts; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pts = cx_frame->pts; + avctx->coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (!!(cx_frame->flags & VPX_FRAME_IS_KEY)) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + pkt->flags |= AV_PKT_FLAG_KEY; + } else { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } } else { av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %zu.\n", cx_frame->sz); @@ -411,8 +454,7 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, * @return AVERROR(EINVAL) on output size error * @return AVERROR(ENOMEM) on coded frame queue data allocation error */ -static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, - AVFrame *coded_frame) +static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) { VP8Context *ctx = avctx->priv_data; const struct vpx_codec_cx_pkt *pkt; @@ -422,7 +464,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, if (ctx->coded_frame_list) { struct FrameListData *cx_frame = ctx->coded_frame_list; /* return the leading frame if we've already begun queueing */ - size = storeframe(avctx, cx_frame, pkt_out, coded_frame); + size = storeframe(avctx, cx_frame, pkt_out); if (size < 0) return size; ctx->coded_frame_list = cx_frame->next; @@ -441,7 +483,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, provided a frame for output */ assert(!ctx->coded_frame_list); cx_pktcpy(&cx_frame, pkt); - size = storeframe(avctx, &cx_frame, pkt_out, coded_frame); + size = storeframe(avctx, &cx_frame, pkt_out); if (size < 0) return size; } else { @@ -460,6 +502,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, av_log(avctx, AV_LOG_ERROR, "Data buffer alloc (%zu bytes) failed\n", cx_frame->sz); + av_freep(&cx_frame); return AVERROR(ENOMEM); } memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); @@ -481,7 +524,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, stats->sz += pkt->data.twopass_stats.sz; break; } - case VPX_CODEC_PSNR_PKT: //FIXME add support for CODEC_FLAG_PSNR + case VPX_CODEC_PSNR_PKT: //FIXME add support for AV_CODEC_FLAG_PSNR case VPX_CODEC_CUSTOM_PKT: //ignore unsupported/unrecognized packet types break; @@ -509,6 +552,16 @@ static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; timestamp = frame->pts; +#if VPX_IMAGE_ABI_VERSION >= 4 + switch (frame->color_range) { + case AVCOL_RANGE_MPEG: + rawimg->range = VPX_CR_STUDIO_RANGE; + break; + case AVCOL_RANGE_JPEG: + rawimg->range = VPX_CR_FULL_RANGE; + break; + } +#endif if (frame->pict_type == AV_PICTURE_TYPE_I) flags |= VPX_EFLAG_FORCE_KF; } @@ -519,9 +572,9 @@ static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, log_encoder_error(avctx, "Error encoding frame"); return AVERROR_INVALIDDATA; } - coded_size = queue_frames(avctx, pkt, avctx->coded_frame); + coded_size = queue_frames(avctx, pkt); - if (!frame && avctx->flags & CODEC_FLAG_PASS1) { + if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) { unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); avctx->stats_out = av_malloc(b64_size); @@ -565,6 +618,9 @@ static const AVOption options[] = { " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, #endif { "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE }, + { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + { "drop-threshold", "Frame drop threshold", offsetof(VP8Context, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE }, + { "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE}, { NULL } }; @@ -598,7 +654,7 @@ AVCodec ff_libvpx_vp8_encoder = { .init = vp8_init, .encode2 = vp8_encode, .close = vp8_free, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class_vp8, .defaults = defaults, @@ -608,9 +664,6 @@ AVCodec ff_libvpx_vp8_encoder = { #if CONFIG_LIBVPX_VP9_ENCODER static av_cold int vp9_init(AVCodecContext *avctx) { - int ret; - if ((ret = ff_vp9_check_experimental(avctx))) - return ret; return vpx_init(avctx, &vpx_codec_vp9_cx_algo); } @@ -621,6 +674,14 @@ static const AVClass class_vp9 = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVProfile profiles[] = { + { FF_PROFILE_VP9_0, "Profile 0" }, + { FF_PROFILE_VP9_1, "Profile 1" }, + { FF_PROFILE_VP9_2, "Profile 2" }, + { FF_PROFILE_VP9_3, "Profile 3" }, + { FF_PROFILE_UNKNOWN }, +}; + AVCodec ff_libvpx_vp9_encoder = { .name = "libvpx-vp9", .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), @@ -630,8 +691,17 @@ AVCodec ff_libvpx_vp9_encoder = { .init = vp9_init, .encode2 = vp8_encode, .close = vp8_free, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, +#if VPX_IMAGE_ABI_VERSION >= 3 + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV440P, +#endif + AV_PIX_FMT_NONE, + }, + .profiles = NULL_IF_CONFIG_SMALL(profiles), .priv_class = &class_vp9, .defaults = defaults, }; diff --git a/libavcodec/libwavpackenc.c b/libavcodec/libwavpackenc.c index 34ec013..1455d91 100644 --- a/libavcodec/libwavpackenc.c +++ b/libavcodec/libwavpackenc.c @@ -188,7 +188,7 @@ AVCodec ff_libwavpack_encoder = { .init = wavpack_encode_init, .encode2 = wavpack_encode_frame, .close = wavpack_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c index b981f48..ef311b7 100644 --- a/libavcodec/libwebpenc.c +++ b/libavcodec/libwebpenc.c @@ -231,7 +231,11 @@ static int libwebp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, *got_packet = 1; end: +#if (WEBP_ENCODER_ABI_VERSION > 0x0203) + WebPMemoryWriterClear(&mw); +#else free(mw.mem); /* must use free() according to libwebp documentation */ +#endif WebPPictureFree(pic); av_freep(&pic); av_frame_free(&alt_frame); diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 6388b6c..fddf1b3 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -76,6 +76,14 @@ typedef struct X264Context { int slice_max_size; char *stats; int nal_hrd; + int motion_est; + int forced_idr; + int coder; + int b_frame_strategy; + int chroma_offset; + int scenechange_threshold; + int noise_reduction; + char *x264_params; } X264Context; @@ -128,6 +136,103 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, return 1; } +static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) +{ + X264Context *x4 = ctx->priv_data; + AVFrameSideData *side_data; + + + if (x4->params.b_tff != frame->top_field_first) { + x4->params.b_tff = frame->top_field_first; + x264_encoder_reconfig(x4->enc, &x4->params); + } + if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den || + x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { + x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; + x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + if (x4->params.rc.i_vbv_buffer_size != ctx->rc_buffer_size / 1000 || + x4->params.rc.i_vbv_max_bitrate != ctx->rc_max_rate / 1000) { + x4->params.rc.i_vbv_buffer_size = ctx->rc_buffer_size / 1000; + x4->params.rc.i_vbv_max_bitrate = ctx->rc_max_rate / 1000; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + if (x4->params.rc.i_rc_method == X264_RC_ABR && + x4->params.rc.i_bitrate != ctx->bit_rate / 1000) { + x4->params.rc.i_bitrate = ctx->bit_rate / 1000; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + if (x4->crf >= 0 && + x4->params.rc.i_rc_method == X264_RC_CRF && + x4->params.rc.f_rf_constant != x4->crf) { + x4->params.rc.f_rf_constant = x4->crf; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + if (x4->params.rc.i_rc_method == X264_RC_CQP && + x4->params.rc.i_qp_constant != x4->cqp) { + x4->params.rc.i_qp_constant = x4->cqp; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + if (x4->crf_max >= 0 && + x4->params.rc.f_rf_constant_max != x4->crf_max) { + x4->params.rc.f_rf_constant_max = x4->crf_max; + x264_encoder_reconfig(x4->enc, &x4->params); + } + + side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_STEREO3D); + if (side_data) { + AVStereo3D *stereo = (AVStereo3D *)side_data->data; + int fpa_type; + + switch (stereo->type) { + case AV_STEREO3D_CHECKERBOARD: + fpa_type = 0; + break; + case AV_STEREO3D_COLUMNS: + fpa_type = 1; + break; + case AV_STEREO3D_LINES: + fpa_type = 2; + break; + case AV_STEREO3D_SIDEBYSIDE: + fpa_type = 3; + break; + case AV_STEREO3D_TOPBOTTOM: + fpa_type = 4; + break; + case AV_STEREO3D_FRAMESEQUENCE: + fpa_type = 5; + break; +#if X264_BUILD >= 145 + case AV_STEREO3D_2D: + fpa_type = 6; + break; +#endif + default: + fpa_type = -1; + break; + } + + /* Inverted mode is not supported by x264 */ + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) { + av_log(ctx, AV_LOG_WARNING, + "Ignoring unsupported inverted stereo value %d\n", fpa_type); + fpa_type = -1; + } + + if (fpa_type != x4->params.i_frame_packing) { + x4->params.i_frame_packing = fpa_type; + x264_encoder_reconfig(x4->enc, &x4->params); + } + } +} + static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -135,7 +240,6 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x264_nal_t *nal; int nnal, i, ret; x264_picture_t pic_out; - AVFrameSideData *side_data; x264_picture_init( &x4->pic ); x4->pic.img.i_csp = x4->params.i_csp; @@ -150,101 +254,38 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } x4->pic.i_pts = frame->pts; - x4->pic.i_type = - frame->pict_type == AV_PICTURE_TYPE_I ? X264_TYPE_KEYFRAME : - frame->pict_type == AV_PICTURE_TYPE_P ? X264_TYPE_P : - frame->pict_type == AV_PICTURE_TYPE_B ? X264_TYPE_B : - X264_TYPE_AUTO; - if (x4->params.b_tff != frame->top_field_first) { - x4->params.b_tff = frame->top_field_first; - x264_encoder_reconfig(x4->enc, &x4->params); - } - if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den || - x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { - x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; - x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; - x264_encoder_reconfig(x4->enc, &x4->params); - } - if (x4->params.rc.i_vbv_buffer_size != ctx->rc_buffer_size / 1000 || - x4->params.rc.i_vbv_max_bitrate != ctx->rc_max_rate / 1000) { - x4->params.rc.i_vbv_buffer_size = ctx->rc_buffer_size / 1000; - x4->params.rc.i_vbv_max_bitrate = ctx->rc_max_rate / 1000; - x264_encoder_reconfig(x4->enc, &x4->params); - } - - if (x4->params.rc.i_rc_method == X264_RC_ABR && - x4->params.rc.i_bitrate != ctx->bit_rate / 1000) { - x4->params.rc.i_bitrate = ctx->bit_rate / 1000; - x264_encoder_reconfig(x4->enc, &x4->params); - } - - if (x4->crf >= 0 && - x4->params.rc.i_rc_method == X264_RC_CRF && - x4->params.rc.f_rf_constant != x4->crf) { - x4->params.rc.f_rf_constant = x4->crf; - x264_encoder_reconfig(x4->enc, &x4->params); - } - - if (x4->params.rc.i_rc_method == X264_RC_CQP && - x4->params.rc.i_qp_constant != x4->cqp) { - x4->params.rc.i_qp_constant = x4->cqp; - x264_encoder_reconfig(x4->enc, &x4->params); - } - - if (x4->crf_max >= 0 && - x4->params.rc.f_rf_constant_max != x4->crf_max) { - x4->params.rc.f_rf_constant_max = x4->crf_max; - x264_encoder_reconfig(x4->enc, &x4->params); - } - - side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_STEREO3D); - if (side_data) { - AVStereo3D *stereo = (AVStereo3D *)side_data->data; - int fpa_type; - - switch (stereo->type) { - case AV_STEREO3D_CHECKERBOARD: - fpa_type = 0; - break; - case AV_STEREO3D_COLUMNS: - fpa_type = 1; - break; - case AV_STEREO3D_LINES: - fpa_type = 2; - break; - case AV_STEREO3D_SIDEBYSIDE: - fpa_type = 3; - break; - case AV_STEREO3D_TOPBOTTOM: - fpa_type = 4; - break; - case AV_STEREO3D_FRAMESEQUENCE: - fpa_type = 5; - break; - default: - fpa_type = -1; - break; - } - - if (fpa_type != x4->params.i_frame_packing) { - x4->params.i_frame_packing = fpa_type; - x264_encoder_reconfig(x4->enc, &x4->params); - } + switch (frame->pict_type) { + case AV_PICTURE_TYPE_I: + x4->pic.i_type = x4->forced_idr ? X264_TYPE_IDR + : X264_TYPE_KEYFRAME; + break; + case AV_PICTURE_TYPE_P: + x4->pic.i_type = X264_TYPE_P; + break; + case AV_PICTURE_TYPE_B: + x4->pic.i_type = X264_TYPE_B; + break; + default: + x4->pic.i_type = X264_TYPE_AUTO; + break; } + reconfig_encoder(ctx, frame); } do { if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0) - return -1; + return AVERROR_UNKNOWN; ret = encode_nals(ctx, pkt, nal, nnal); if (ret < 0) - return -1; + return ret; } while (!ret && !frame && x264_encoder_delayed_frames(x4->enc)); pkt->pts = pic_out.i_pts; pkt->dts = pic_out.i_dts; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS switch (pic_out.i_type) { case X264_TYPE_IDR: case X264_TYPE_I: @@ -258,10 +299,23 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, ctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; break; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe; - if (ret) + if (ret) { + uint8_t *sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS ctx->coded_frame->quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } *got_packet = ret; return 0; @@ -272,12 +326,12 @@ static av_cold int X264_close(AVCodecContext *avctx) X264Context *x4 = avctx->priv_data; av_freep(&avctx->extradata); - av_free(x4->sei); + av_freep(&x4->sei); - if (x4->enc) + if (x4->enc) { x264_encoder_close(x4->enc); - - av_frame_free(&avctx->coded_frame); + x4->enc = NULL; + } return 0; } @@ -290,13 +344,18 @@ static int convert_pix_fmt(enum AVPixelFormat pix_fmt) case AV_PIX_FMT_YUV420P9: case AV_PIX_FMT_YUV420P10: return X264_CSP_I420; case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUVJ422P: case AV_PIX_FMT_YUV422P10: return X264_CSP_I422; case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUVJ444P: case AV_PIX_FMT_YUV444P9: case AV_PIX_FMT_YUV444P10: return X264_CSP_I444; case AV_PIX_FMT_NV12: return X264_CSP_NV12; case AV_PIX_FMT_NV16: case AV_PIX_FMT_NV20: return X264_CSP_NV16; +#ifdef X264_CSP_NV21 + case AV_PIX_FMT_NV21: return X264_CSP_NV21; +#endif }; return 0; } @@ -310,10 +369,18 @@ static int convert_pix_fmt(enum AVPixelFormat pix_fmt) static av_cold int X264_init(AVCodecContext *avctx) { X264Context *x4 = avctx->priv_data; - + AVCPBProperties *cpb_props; + +#if CONFIG_LIBX262_ENCODER + if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + x4->params.b_mpeg2 = 1; + x264_param_default_mpeg2(&x4->params); + } else +#else x264_param_default(&x4->params); +#endif - x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; + x4->params.b_deblocking_filter = avctx->flags & AV_CODEC_FLAG_LOOP_FILTER; if (x4->preset || x4->tune) if (x264_param_default_preset(&x4->params, x4->preset, x4->tune) < 0) { @@ -335,8 +402,8 @@ static av_cold int X264_init(AVCodecContext *avctx) } 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_write = avctx->flags & AV_CODEC_FLAG_PASS1; + if (avctx->flags & AV_CODEC_FLAG_PASS2) { x4->params.rc.b_stat_read = 1; } else { if (x4->crf >= 0) { @@ -360,25 +427,30 @@ static av_cold int X264_init(AVCodecContext *avctx) if (avctx->i_quant_factor > 0) 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; - - if (avctx->me_method == ME_EPZS) - x4->params.analyse.i_me_method = X264_ME_DIA; - else if (avctx->me_method == ME_HEX) - x4->params.analyse.i_me_method = X264_ME_HEX; - else if (avctx->me_method == ME_UMH) - x4->params.analyse.i_me_method = X264_ME_UMH; - else if (avctx->me_method == ME_FULL) - x4->params.analyse.i_me_method = X264_ME_ESA; - else if (avctx->me_method == ME_TESA) - x4->params.analyse.i_me_method = X264_ME_TESA; + +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->chromaoffset >= 0) + x4->chroma_offset = avctx->chromaoffset; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (x4->chroma_offset >= 0) + x4->params.analyse.i_chroma_qp_offset = x4->chroma_offset; if (avctx->gop_size >= 0) x4->params.i_keyint_max = avctx->gop_size; if (avctx->max_b_frames >= 0) x4->params.i_bframe = avctx->max_b_frames; + +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->scenechange_threshold >= 0) - x4->params.i_scenecut_threshold = avctx->scenechange_threshold; + x4->scenechange_threshold = avctx->scenechange_threshold; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (x4->scenechange_threshold >= 0) + x4->params.i_scenecut_threshold = x4->scenechange_threshold; + if (avctx->qmin >= 0) x4->params.rc.i_qp_min = avctx->qmin; if (avctx->qmax >= 0) @@ -395,16 +467,30 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.analyse.i_trellis = avctx->trellis; if (avctx->me_range >= 0) x4->params.analyse.i_me_range = avctx->me_range; +#if FF_API_PRIVATE_OPT + FF_DISABLE_DEPRECATION_WARNINGS if (avctx->noise_reduction >= 0) - x4->params.analyse.i_noise_reduction = avctx->noise_reduction; + x4->noise_reduction = avctx->noise_reduction; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (x4->noise_reduction >= 0) + x4->params.analyse.i_noise_reduction = x4->noise_reduction; if (avctx->me_subpel_quality >= 0) x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->b_frame_strategy >= 0) - x4->params.i_bframe_adaptive = avctx->b_frame_strategy; + x4->b_frame_strategy = avctx->b_frame_strategy; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->keyint_min >= 0) x4->params.i_keyint_min = avctx->keyint_min; +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->coder_type >= 0) - x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC; + x4->coder = avctx->coder_type == FF_CODER_TYPE_AC; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->me_cmp >= 0) x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; @@ -461,6 +547,31 @@ static av_cold int X264_init(AVCodecContext *avctx) if (x4->nal_hrd >= 0) x4->params.i_nal_hrd = x4->nal_hrd; + if (x4->motion_est >= 0) { + x4->params.analyse.i_me_method = x4->motion_est; +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS + } else { + if (avctx->me_method == ME_EPZS) + x4->params.analyse.i_me_method = X264_ME_DIA; + else if (avctx->me_method == ME_HEX) + x4->params.analyse.i_me_method = X264_ME_HEX; + else if (avctx->me_method == ME_UMH) + x4->params.analyse.i_me_method = X264_ME_UMH; + else if (avctx->me_method == ME_FULL) + x4->params.analyse.i_me_method = X264_ME_ESA; + else if (avctx->me_method == ME_TESA) + x4->params.analyse.i_me_method = X264_ME_TESA; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } + + if (x4->coder >= 0) + x4->params.b_cabac = x4->coder; + + if (x4->b_frame_strategy >= 0) + x4->params.i_bframe_adaptive = x4->b_frame_strategy; + if (x4->profile) if (x264_param_apply_profile(&x4->params, x4->profile) < 0) { av_log(avctx, AV_LOG_ERROR, "Error setting profile %s.\n", x4->profile); @@ -474,22 +585,29 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.i_fps_num = x4->params.i_timebase_den = avctx->time_base.den; x4->params.i_fps_den = x4->params.i_timebase_num = avctx->time_base.num; - x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; + x4->params.analyse.b_psnr = avctx->flags & AV_CODEC_FLAG_PSNR; x4->params.i_threads = avctx->thread_count; if (avctx->thread_type) x4->params.b_sliced_threads = avctx->thread_type == FF_THREAD_SLICE; - x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT; + x4->params.b_interlaced = avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT; - x4->params.b_open_gop = !(avctx->flags & CODEC_FLAG_CLOSED_GOP); + x4->params.b_open_gop = !(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); x4->params.i_slice_count = avctx->slices; x4->params.vui.b_fullrange = avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ444P || avctx->color_range == AVCOL_RANGE_JPEG; - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) + // x264 validates the values internally + x4->params.vui.i_colorprim = avctx->color_primaries; + x4->params.vui.i_transfer = avctx->color_trc; + x4->params.vui.i_colmatrix = avctx->colorspace; + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) x4->params.b_repeat_headers = 0; if (x4->x264_params) { @@ -518,19 +636,17 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->enc = x264_encoder_open(&x4->params); if (!x4->enc) - return -1; + return AVERROR_UNKNOWN; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { x264_nal_t *nal; uint8_t *p; int nnal, s, i; s = x264_encoder_headers(x4->enc, &nal, &nnal); - avctx->extradata = p = av_malloc(s); + avctx->extradata = p = av_mallocz(s + AV_INPUT_BUFFER_PADDING_SIZE); + if (!p) + return AVERROR(ENOMEM); for (i = 0; i < nnal; i++) { /* Don't put the SEI in extradata. */ @@ -538,6 +654,8 @@ static av_cold int X264_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_INFO, "%s\n", nal[i].p_payload+25); x4->sei_size = nal[i].i_payload; x4->sei = av_malloc(x4->sei_size); + if (!x4->sei) + return AVERROR(ENOMEM); memcpy(x4->sei, nal[i].p_payload, nal[i].i_payload); continue; } @@ -547,6 +665,13 @@ static av_cold int X264_init(AVCodecContext *avctx) avctx->extradata_size = p - avctx->extradata; } + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); + cpb_props->buffer_size = x4->params.rc.i_vbv_buffer_size * 1000; + cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000; + cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000; + return 0; } @@ -554,9 +679,14 @@ static const enum AVPixelFormat pix_fmts_8bit[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NV12, AV_PIX_FMT_NV16, +#ifdef X264_CSP_NV21 + AV_PIX_FMT_NV21, +#endif AV_PIX_FMT_NONE }; static const enum AVPixelFormat pix_fmts_9bit[] = { @@ -634,17 +764,26 @@ static const AVOption options[] = { { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_NONE}, INT_MIN, INT_MAX, VE, "nal-hrd" }, { "vbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_VBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, { "cbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_CBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, + { "motion-est", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, X264_ME_TESA, VE, "motion-est"}, + { "dia", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_DIA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "hex", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_HEX }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "umh", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_UMH }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "esa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_ESA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "tesa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_TESA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "forced-idr", "If forwarding iframes, require them to be IDR frames.", OFFSET(forced_idr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "coder", "Coder type", OFFSET(coder), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "coder" }, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "coder" }, + { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" }, + { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" }, + { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 2, VE }, + { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, + { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, + { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, + { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { NULL }, }; -static const AVClass class = { - .class_name = "libx264", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - static const AVCodecDefault x264_defaults[] = { { "b", "0" }, { "bf", "-1" }, @@ -656,15 +795,25 @@ static const AVCodecDefault x264_defaults[] = { { "qblur", "-1" }, { "qcomp", "-1" }, { "refs", "-1" }, +#if FF_API_PRIVATE_OPT { "sc_threshold", "-1" }, +#endif { "trellis", "-1" }, +#if FF_API_PRIVATE_OPT { "nr", "-1" }, +#endif { "me_range", "-1" }, +#if FF_API_MOTION_EST { "me_method", "-1" }, +#endif { "subq", "-1" }, +#if FF_API_PRIVATE_OPT { "b_strategy", "-1" }, +#endif { "keyint_min", "-1" }, +#if FF_API_CODER_TYPE { "coder", "-1" }, +#endif { "cmp", "-1" }, { "threads", AV_STRINGIFY(X264_THREADS_AUTO) }, { "thread_type", "0" }, @@ -673,6 +822,14 @@ static const AVCodecDefault x264_defaults[] = { { NULL }, }; +#if CONFIG_LIBX264_ENCODER +static const AVClass class = { + .class_name = "libx264", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_libx264_encoder = { .name = "libx264", .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), @@ -682,8 +839,37 @@ AVCodec ff_libx264_encoder = { .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .priv_class = &class, .defaults = x264_defaults, .init_static_data = X264_init_static, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; +#endif + +#if CONFIG_LIBX262_ENCODER +static const AVClass X262_class = { + .class_name = "libx262", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libx262_encoder = { + .name = "libx262", + .long_name = NULL_IF_CONFIG_SMALL("libx262 MPEG2VIDEO"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(X264Context), + .init = X264_init, + .encode2 = X264_frame, + .close = X264_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .priv_class = &X262_class, + .defaults = x264_defaults, + .pix_fmts = pix_fmts_8bit, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; +#endif diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 026f6ff..f5d3d0f 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -25,6 +25,7 @@ #endif #include +#include #include "libavutil/internal.h" #include "libavutil/common.h" @@ -38,7 +39,9 @@ typedef struct libx265Context { x265_encoder *encoder; x265_param *params; + const x265_api *api; + float crf; char *preset; char *tune; char *x265_opts; @@ -63,12 +66,10 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx) { libx265Context *ctx = avctx->priv_data; - av_frame_free(&avctx->coded_frame); - - x265_param_free(ctx->params); + ctx->api->param_free(ctx->params); if (ctx->encoder) - x265_encoder_close(ctx->encoder); + ctx->api->encoder_close(ctx->encoder); return 0; } @@ -76,10 +77,10 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx) static av_cold int libx265_encode_init(AVCodecContext *avctx) { libx265Context *ctx = avctx->priv_data; - x265_nal *nal; - char sar[12]; - int sar_num, sar_den; - int nnal; + + ctx->api = x265_api_get(av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth); + if (!ctx->api) + ctx->api = x265_api_get(0); if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL && !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w) { @@ -89,20 +90,27 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) return AVERROR(ENOSYS); } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); - return AVERROR(ENOMEM); - } - - ctx->params = x265_param_alloc(); + ctx->params = ctx->api->param_alloc(); if (!ctx->params) { av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n"); return AVERROR(ENOMEM); } - if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n"); + if (ctx->api->param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) { + int i; + + av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", ctx->preset, ctx->tune); + av_log(avctx, AV_LOG_INFO, "Possible presets:"); + for (i = 0; x265_preset_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x265_preset_names[i]); + + av_log(avctx, AV_LOG_INFO, "\n"); + av_log(avctx, AV_LOG_INFO, "Possible tunes:"); + for (i = 0; x265_tune_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x265_tune_names[i]); + + av_log(avctx, AV_LOG_INFO, "\n"); + return AVERROR(EINVAL); } @@ -111,13 +119,33 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->fpsDenom = avctx->time_base.num * avctx->ticks_per_frame; ctx->params->sourceWidth = avctx->width; ctx->params->sourceHeight = avctx->height; + ctx->params->bEnablePsnr = !!(avctx->flags & AV_CODEC_FLAG_PSNR); + + if ((avctx->color_primaries <= AVCOL_PRI_BT2020 && + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) || + (avctx->color_trc <= AVCOL_TRC_BT2020_12 && + avctx->color_trc != AVCOL_TRC_UNSPECIFIED) || + (avctx->colorspace <= AVCOL_SPC_BT2020_CL && + avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) { + + ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; + ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; + + // x265 validates the parameters internally + ctx->params->vui.colorPrimaries = avctx->color_primaries; + ctx->params->vui.transferCharacteristics = avctx->color_trc; + ctx->params->vui.matrixCoeffs = avctx->colorspace; + } if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { + char sar[12]; + int sar_num, sar_den; + av_reduce(&sar_num, &sar_den, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 65535); snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); - if (x265_param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { + if (ctx->api->param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); return AVERROR_INVALIDDATA; } @@ -138,12 +166,20 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) break; } - if (avctx->bit_rate > 0) { + if (ctx->crf >= 0) { + char crf[6]; + + snprintf(crf, sizeof(crf), "%2.2f", ctx->crf); + if (ctx->api->param_parse(ctx->params, "crf", crf) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid crf: %2.2f.\n", ctx->crf); + return AVERROR(EINVAL); + } + } else if (avctx->bit_rate > 0) { ctx->params->rc.bitrate = avctx->bit_rate / 1000; ctx->params->rc.rateControlMode = X265_RC_ABR; } - if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER)) + if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) ctx->params->bRepeatHeaders = 1; if (ctx->x265_opts) { @@ -152,7 +188,7 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) { while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { - int parse_ret = x265_param_parse(ctx->params, en->key, en->value); + int parse_ret = ctx->api->param_parse(ctx->params, en->key, en->value); switch (parse_ret) { case X265_PARAM_BAD_NAME: @@ -171,22 +207,25 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) } } - ctx->encoder = x265_encoder_open(ctx->params); + ctx->encoder = ctx->api->encoder_open(ctx->params); if (!ctx->encoder) { av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); libx265_encode_close(avctx); return AVERROR_INVALIDDATA; } - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { - avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal); + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + x265_nal *nal; + int nnal; + + avctx->extradata_size = ctx->api->encoder_headers(ctx->encoder, &nal, &nnal); if (avctx->extradata_size <= 0) { av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); libx265_encode_close(avctx); return AVERROR_INVALIDDATA; } - avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); @@ -205,7 +244,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { libx265Context *ctx = avctx->priv_data; x265_picture x265pic; - x265_picture x265pic_out = { { 0 } }; + x265_picture x265pic_out = { 0 }; x265_nal *nal; uint8_t *dst; int payload = 0; @@ -213,7 +252,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int ret; int i; - x265_picture_init(ctx->params, &x265pic); + ctx->api->picture_init(ctx->params, &x265pic); if (pic) { for (i = 0; i < 3; i++) { @@ -222,11 +261,16 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } x265pic.pts = pic->pts; - x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1; + x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth; + + x265pic.sliceType = pic->pict_type == AV_PICTURE_TYPE_I ? X265_TYPE_I : + pic->pict_type == AV_PICTURE_TYPE_P ? X265_TYPE_P : + pic->pict_type == AV_PICTURE_TYPE_B ? X265_TYPE_B : + X265_TYPE_AUTO; } - ret = x265_encoder_encode(ctx->encoder, &nal, &nnal, - pic ? &x265pic : NULL, &x265pic_out); + ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, + pic ? &x265pic : NULL, &x265pic_out); if (ret < 0) return AVERROR_UNKNOWN; @@ -254,6 +298,23 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, pkt->pts = x265pic_out.pts; pkt->dts = x265pic_out.dts; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + switch (x265pic_out.sliceType) { + case X265_TYPE_IDR: + case X265_TYPE_I: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + break; + case X265_TYPE_P: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; + break; + case X265_TYPE_B: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; + break; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + *got_packet = 1; return 0; } @@ -286,6 +347,7 @@ static av_cold void libx265_encode_init_csp(AVCodec *codec) #define OFFSET(x) offsetof(libx265Context, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { + { "crf", "set the x265 crf", OFFSET(crf), AV_OPT_TYPE_FLOAT, { .dbl = -1 }, -1, FLT_MAX, VE }, { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, @@ -299,6 +361,11 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVCodecDefault x265_defaults[] = { + { "b", "0" }, + { NULL }, +}; + AVCodec ff_libx265_encoder = { .name = "libx265", .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), @@ -310,5 +377,6 @@ AVCodec ff_libx265_encoder = { .close = libx265_encode_close, .priv_data_size = sizeof(libx265Context), .priv_class = &class, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .defaults = x265_defaults, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, }; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 7a74e36..b7a6c41 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -53,8 +53,13 @@ typedef struct XavsContext { int direct_pred; int aud; int fast_pskip; + int motion_est; int mbtree; int mixed_refs; + int b_frame_strategy; + int chroma_offset; + int scenechange_threshold; + int noise_reduction; int64_t *pts_buffer; int out_frame_count; @@ -80,7 +85,7 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, { XavsContext *x4 = ctx->priv_data; uint8_t *p; - int i, s, ret, size = x4->sei_size + FF_MIN_BUFFER_SIZE; + int i, s, ret, size = x4->sei_size + AV_INPUT_BUFFER_MIN_SIZE; if (!nnal) return 0; @@ -119,6 +124,7 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, xavs_nal_t *nal; int nnal, i, ret; xavs_picture_t pic_out; + uint8_t *sd; x4->pic.img.i_csp = XAVS_CSP_I420; x4->pic.img.i_plane = 3; @@ -160,7 +166,11 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pts = pic_out.i_pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->pts = pic_out.i_pts; if (avctx->has_b_frames) { if (!x4->out_frame_count) @@ -170,6 +180,8 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, } else pkt->dts = pkt->pts; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS switch (pic_out.i_type) { case XAVS_TYPE_IDR: case XAVS_TYPE_I: @@ -183,15 +195,30 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; break; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* There is no IDR frame in AVS JiZhun */ /* Sequence header is used as a flag */ if (pic_out.i_type == XAVS_TYPE_I) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->flags |= AV_PKT_FLAG_KEY; } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; x4->out_frame_count++; *got_packet = ret; @@ -209,8 +236,6 @@ static av_cold int XAVS_close(AVCodecContext *avctx) if (x4->enc) xavs_encoder_close(x4->enc); - av_frame_free(&avctx->coded_frame); - return 0; } @@ -230,8 +255,8 @@ static av_cold int XAVS_init(AVCodecContext *avctx) } 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_write = avctx->flags & AV_CODEC_FLAG_PASS1; + if (avctx->flags & AV_CODEC_FLAG_PASS2) { x4->params.rc.b_stat_read = 1; } else { if (x4->crf >= 0) { @@ -251,6 +276,8 @@ static av_cold int XAVS_init(AVCodecContext *avctx) x4->params.analyse.i_direct_mv_pred = x4->direct_pred; if (x4->fast_pskip >= 0) x4->params.analyse.b_fast_pskip = x4->fast_pskip; + if (x4->motion_est >= 0) + x4->params.analyse.i_me_method = x4->motion_est; if (x4->mixed_refs >= 0) x4->params.analyse.b_mixed_references = x4->mixed_refs; if (x4->b_bias != INT_MIN) @@ -258,11 +285,44 @@ static av_cold int XAVS_init(AVCodecContext *avctx) if (x4->cplxblur >= 0) x4->params.rc.f_complexity_blur = x4->cplxblur; +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS + if (x4->motion_est < 0) { + switch (avctx->me_method) { + case ME_EPZS: + x4->params.analyse.i_me_method = XAVS_ME_DIA; + break; + case ME_HEX: + x4->params.analyse.i_me_method = XAVS_ME_HEX; + break; + case ME_UMH: + x4->params.analyse.i_me_method = XAVS_ME_UMH; + break; + case ME_FULL: + x4->params.analyse.i_me_method = XAVS_ME_ESA; + break; + case ME_TESA: + x4->params.analyse.i_me_method = XAVS_ME_TESA; + break; + default: + x4->params.analyse.i_me_method = XAVS_ME_HEX; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + x4->params.i_bframe = avctx->max_b_frames; /* cabac is not included in AVS JiZhun Profile */ x4->params.b_cabac = 0; - x4->params.i_bframe_adaptive = avctx->b_frame_strategy; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->b_frame_strategy) + x4->b_frame_strategy = avctx->b_frame_strategy; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + x4->params.i_bframe_adaptive = x4->b_frame_strategy; avctx->has_b_frames = !!avctx->max_b_frames; @@ -272,9 +332,16 @@ static av_cold int XAVS_init(AVCodecContext *avctx) 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; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->scenechange_threshold) + x4->scenechange_threshold = avctx->scenechange_threshold; +FF_ENABLE_DEPRECATION_WARNINGS +#endif - // x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; + x4->params.i_scenecut_threshold = x4->scenechange_threshold; + + // x4->params.b_deblocking_filter = avctx->flags & AV_CODEC_FLAG_LOOP_FILTER; x4->params.rc.i_qp_min = avctx->qmin; x4->params.rc.i_qp_max = avctx->qmax; @@ -294,41 +361,30 @@ static av_cold int XAVS_init(AVCodecContext *avctx) x4->params.i_fps_den = avctx->time_base.num; x4->params.analyse.inter = XAVS_ANALYSE_I8x8 |XAVS_ANALYSE_PSUB16x16| XAVS_ANALYSE_BSUB16x16; - switch (avctx->me_method) { - case ME_EPZS: - x4->params.analyse.i_me_method = XAVS_ME_DIA; - break; - case ME_HEX: - x4->params.analyse.i_me_method = XAVS_ME_HEX; - break; - case ME_UMH: - x4->params.analyse.i_me_method = XAVS_ME_UMH; - break; - case ME_FULL: - x4->params.analyse.i_me_method = XAVS_ME_ESA; - break; - case ME_TESA: - x4->params.analyse.i_me_method = XAVS_ME_TESA; - break; - default: - x4->params.analyse.i_me_method = XAVS_ME_HEX; - } - x4->params.analyse.i_me_range = avctx->me_range; x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; /* AVS P2 only enables 8x8 transform */ - x4->params.analyse.b_transform_8x8 = 1; //avctx->flags2 & CODEC_FLAG2_8X8DCT; + x4->params.analyse.b_transform_8x8 = 1; //avctx->flags2 & AV_CODEC_FLAG2_8X8DCT; x4->params.analyse.i_trellis = avctx->trellis; - x4->params.analyse.i_noise_reduction = avctx->noise_reduction; + +#if FF_API_PRIVATE_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->noise_reduction >= 0) + x4->noise_reduction = avctx->noise_reduction; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + + x4->params.analyse.i_noise_reduction = x4->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->bit_rate > 0) + x4->params.rc.f_rate_tolerance = + (float)avctx->bit_rate_tolerance / avctx->bit_rate; if ((avctx->rc_buffer_size) && (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { @@ -341,14 +397,22 @@ static av_cold int XAVS_init(AVCodecContext *avctx) /* what is the RC method we are now using? Default NO */ x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor); x4->params.rc.f_pb_factor = avctx->b_quant_factor; - x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset; - x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->chromaoffset) + x4->chroma_offset = avctx->chromaoffset; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + x4->params.analyse.i_chroma_qp_offset = x4->chroma_offset; + + x4->params.analyse.b_psnr = avctx->flags & AV_CODEC_FLAG_PSNR; x4->params.i_log_level = XAVS_LOG_DEBUG; x4->params.i_threads = avctx->thread_count; - x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT; + x4->params.b_interlaced = avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT; - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) x4->params.b_repeat_headers = 0; x4->enc = xavs_encoder_open(&x4->params); @@ -358,13 +422,9 @@ static av_cold int XAVS_init(AVCodecContext *avctx) if (!(x4->pts_buffer = av_mallocz((avctx->max_b_frames+1) * sizeof(*x4->pts_buffer)))) return AVERROR(ENOMEM); - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - /* TAG: Do we have GLOBAL HEADER in AVS */ /* We Have PPS and SPS in AVS */ - if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { xavs_nal_t *nal; int nnal, s, i, size; uint8_t *p; @@ -407,6 +467,17 @@ static const AVOption options[] = { { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 1, VE}, { "mixed-refs", "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE }, { "fast-pskip", NULL, OFFSET(fast_pskip), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 1, VE}, + { "motion-est", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, XAVS_ME_TESA, VE, "motion-est"}, + { "dia", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_DIA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "hex", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_HEX }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "umh", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_UMH }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "esa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_ESA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "tesa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_TESA }, INT_MIN, INT_MAX, VE, "motion-est" }, + { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, VE}, + { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE}, + { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE}, + { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE}, + { NULL }, }; @@ -431,7 +502,7 @@ AVCodec ff_libxavs_encoder = { .init = XAVS_init, .encode2 = XAVS_frame, .close = XAVS_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = xavs_defaults, diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index ad650dd..9cbe9c1 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -1,5 +1,5 @@ /* - * Interface to xvidcore for mpeg4 encoding + * Interface to xvidcore for MPEG-4 encoding * Copyright (c) 2004 Adam Thayer * * This file is part of Libav. @@ -25,21 +25,29 @@ * @author Adam Thayer (krevnik@comcast.net) */ -#include +#include +#include #include -#include "avcodec.h" +#include + #include "libavutil/cpu.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" #include "libxvid.h" -#include "mpegvideo.h" +#include "mpegutils.h" /** * Buffer management macros. */ -#define BUFFER_SIZE 1024 -#define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x)) -#define BUFFER_CAT(x) (&((x)[strlen(x)])) +#define BUFFER_SIZE 1024 +#define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x)) +#define BUFFER_CAT(x) (&((x)[strlen(x)])) /** * Structure for the private Xvid context. @@ -65,16 +73,22 @@ struct xvid_context { int ssim; /**< SSIM information display mode */ int ssim_acc; /**< SSIM accuracy. 0: accurate. 4: fast. */ int gmc; + int me_quality; /**< Motion estimation quality. 0: fast 6: best. */ + int mpeg_quant; /**< Quantization type. 0: H.263, 1: MPEG */ }; /** * Structure for the private first-pass plugin. */ struct xvid_ff_pass1 { - int version; /**< Xvid version */ + int version; /**< Xvid version */ struct xvid_context *context; /**< Pointer to private context */ }; +static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *picture, int *got_packet); + + /* * Xvid 2-Pass Kludge Section * @@ -92,9 +106,9 @@ struct xvid_ff_pass1 { * @param handle Private context handle * @return Returns XVID_ERR_xxxx on failure, or 0 on success. */ -static int xvid_ff_2pass_create(xvid_plg_create_t * param, - void ** handle) { - struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; +static int xvid_ff_2pass_create(xvid_plg_create_t *param, void **handle) +{ + struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *) param->param; char *log = x->context->twopassbuffer; /* Do a quick bounds check */ @@ -105,12 +119,12 @@ static int xvid_ff_2pass_create(xvid_plg_create_t * param, /* This is because we can safely prevent a buffer overflow */ log[0] = 0; snprintf(log, BUFFER_REMAINING(log), - "# avconv 2-pass log file, using xvid codec\n"); + "# avconv 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)); + "# 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; @@ -120,11 +134,12 @@ static int xvid_ff_2pass_create(xvid_plg_create_t * param, * Destroy the two-pass plugin context. * * @param ref Context pointer for the plugin - * @param param Destrooy context + * @param param Destroy context * @return Returns 0, success guaranteed */ static int xvid_ff_2pass_destroy(struct xvid_context *ref, - xvid_plg_destroy_t *param) { + 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) @@ -140,35 +155,36 @@ static int xvid_ff_2pass_destroy(struct xvid_context *ref, * @return Returns 0, success guaranteed */ static int xvid_ff_2pass_before(struct xvid_context *ref, - xvid_plg_data_t *param) { + 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 ) + 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_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_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; + 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; @@ -183,7 +199,8 @@ static int xvid_ff_2pass_before(struct xvid_context *ref, * @return Returns XVID_ERR_xxxx on failure, or 0 on success */ static int xvid_ff_2pass_after(struct xvid_context *ref, - xvid_plg_data_t *param) { + xvid_plg_data_t *param) +{ char *log = ref->twopassbuffer; const char *frame_types = " ipbs"; char frame_type; @@ -193,16 +210,16 @@ static int xvid_ff_2pass_after(struct xvid_context *ref, return XVID_ERR_FAIL; /* Convert the type given to us into a character */ - if( param->type < 5 && param->type > 0 ) { + if (param->type < 5 && param->type > 0) frame_type = frame_types[param->type]; - } else { + 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); + "%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; } @@ -220,25 +237,20 @@ static int xvid_ff_2pass_after(struct xvid_context *ref, */ static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) { - switch( cmd ) { - case XVID_PLG_INFO: - case XVID_PLG_FRAME: - return 0; - - case XVID_PLG_BEFORE: - return xvid_ff_2pass_before(ref, p1); - - case XVID_PLG_CREATE: - return xvid_ff_2pass_create(p1, p2); - - case XVID_PLG_AFTER: - return xvid_ff_2pass_after(ref, p1); - - case XVID_PLG_DESTROY: - return xvid_ff_2pass_destroy(ref, p1); - - default: - return XVID_ERR_FAIL; + 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; } } @@ -255,31 +267,33 @@ static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) * @param frame_len Length of encoded frame data * @return Returns new length of frame data */ -static int xvid_strip_vol_header(AVCodecContext *avctx, - AVPacket *pkt, - unsigned int header_len, - unsigned int frame_len) { +static int xvid_strip_vol_header(AVCodecContext *avctx, AVPacket *pkt, + unsigned int header_len, + unsigned int frame_len) +{ int vo_len = 0, i; - for( i = 0; i < header_len - 3; i++ ) { - if( pkt->data[i] == 0x00 && - pkt->data[i+1] == 0x00 && - pkt->data[i+2] == 0x01 && - pkt->data[i+3] == 0xB6 ) { + for (i = 0; i < header_len - 3; i++) { + if (pkt->data[i] == 0x00 && + pkt->data[i + 1] == 0x00 && + pkt->data[i + 2] == 0x01 && + pkt->data[i + 3] == 0xB6) { vo_len = i; break; } } - if( vo_len > 0 ) { + if (vo_len > 0) { /* We need to store the header, so extract it */ if (!avctx->extradata) { avctx->extradata = av_malloc(vo_len); + if (!avctx->extradata) + return AVERROR(ENOMEM); memcpy(avctx->extradata, pkt->data, vo_len); avctx->extradata_size = vo_len; } /* Less dangerous now, memmove properly copies the two - chunks of overlapping data */ + * chunks of overlapping data */ memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); pkt->size = frame_len - vo_len; } @@ -306,114 +320,132 @@ static void xvid_correct_framerate(AVCodecContext *avctx) fbase = avctx->time_base.num; gcd = av_gcd(frate, fbase); - if( gcd > 1 ) { + if (gcd > 1) { frate /= gcd; fbase /= gcd; } - if( frate <= 65000 && fbase <= 65000 ) { + if (frate <= 65000 && fbase <= 65000) { avctx->time_base.den = frate; avctx->time_base.num = fbase; return; } - fps = (float)frate / (float)fbase; + 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 = (int) est_fps; + if (est_fps > (int) est_fps) { est_frate = (est_frate + 1) * 1000; - est_fbase = (int)roundf((float)est_frate / est_fps); + est_fbase = (int) roundf((float) est_frate / est_fps); } else est_fbase = 1; gcd = av_gcd(est_frate, est_fbase); - if( gcd > 1 ) { + if (gcd > 1) { est_frate /= gcd; est_fbase /= gcd; } - if( fbase > est_fbase ) { + 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)); + "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", + est_fps, (((est_fps - fps) / fps) * 100.0)); } else { avctx->time_base.den = frate; avctx->time_base.num = fbase; } } -static av_cold int xvid_encode_init(AVCodecContext *avctx) { +static av_cold int xvid_encode_init(AVCodecContext *avctx) +{ int xerr, i; int xvid_flags = avctx->flags; struct xvid_context *x = avctx->priv_data; uint16_t *intra, *inter; int fd; - xvid_plugin_single_t single = { 0 }; - struct xvid_ff_pass1 rc2pass1 = { 0 }; - xvid_plugin_2pass2_t rc2pass2 = { 0 }; + xvid_plugin_single_t single = { 0 }; + struct xvid_ff_pass1 rc2pass1 = { 0 }; + xvid_plugin_2pass2_t rc2pass2 = { 0 }; xvid_plugin_lumimasking_t masking_l = { 0 }; /* For lumi masking */ xvid_plugin_lumimasking_t masking_v = { 0 }; /* For variance AQ */ - xvid_plugin_ssim_t ssim = { 0 }; - xvid_gbl_init_t xvid_gbl_init = { 0 }; - xvid_enc_create_t xvid_enc_create = { 0 }; + xvid_plugin_ssim_t ssim = { 0 }; + xvid_gbl_init_t xvid_gbl_init = { 0 }; + xvid_enc_create_t xvid_enc_create = { 0 }; xvid_enc_plugin_t plugins[7]; /* Bring in VOP flags from avconv command-line */ x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */ - if( xvid_flags & CODEC_FLAG_4MV ) + if (xvid_flags & AV_CODEC_FLAG_4MV) x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */ - if( avctx->trellis - ) + if (avctx->trellis) x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */ - if( xvid_flags & CODEC_FLAG_AC_PRED ) + if (xvid_flags & AV_CODEC_FLAG_AC_PRED) x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */ - if( xvid_flags & CODEC_FLAG_GRAY ) + if (xvid_flags & AV_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; + switch (x->me_quality) { + case 6: + case 5: + x->me_flags |= XVID_ME_EXTSEARCH16 | + XVID_ME_EXTSEARCH8; + case 4: + case 3: + x->me_flags |= XVID_ME_ADVANCEDDIAMOND8 | + XVID_ME_HALFPELREFINE8 | + XVID_ME_CHROMA_PVOP | + XVID_ME_CHROMA_BVOP; + case 2: + case 1: + x->me_flags |= XVID_ME_ADVANCEDDIAMOND16 | + XVID_ME_HALFPELREFINE16; +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS + break; + default: + 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; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif } /* 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; + 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 avconv command-line */ @@ -425,17 +457,17 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { x->vol_flags = 0; if (x->gmc) { x->vol_flags |= XVID_VOL_GMC; - x->me_flags |= XVID_ME_GME_REFINE; + x->me_flags |= XVID_ME_GME_REFINE; } - if( xvid_flags & CODEC_FLAG_QPEL ) { + if (xvid_flags & AV_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_QUARTERPELREFINE16; + if (x->vop_flags & XVID_VOP_INTER4V) x->me_flags |= XVID_ME_QUARTERPELREFINE8; } - xvid_gbl_init.version = XVID_VERSION; - xvid_gbl_init.debug = 0; + xvid_gbl_init.version = XVID_VERSION; + xvid_gbl_init.debug = 0; xvid_gbl_init.cpu_flags = 0; /* Initialize */ @@ -445,77 +477,78 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { 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_enc_create.width = + x->xsize = avctx->width; + xvid_enc_create.height = + x->ysize = avctx->height; /* Xvid can determine the proper profile to use */ /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */ /* We don't use zones */ - xvid_enc_create.zones = NULL; + xvid_enc_create.zones = NULL; xvid_enc_create.num_zones = 0; xvid_enc_create.num_threads = avctx->thread_count; - xvid_enc_create.plugins = plugins; + xvid_enc_create.plugins = plugins; xvid_enc_create.num_plugins = 0; /* Initialize Buffers */ - x->twopassbuffer = NULL; + x->twopassbuffer = NULL; x->old_twopassbuffer = NULL; - x->twopassfile = NULL; + x->twopassfile = NULL; - if( xvid_flags & CODEC_FLAG_PASS1 ) { - rc2pass1.version = XVID_VERSION; - rc2pass1.context = x; - x->twopassbuffer = av_malloc(BUFFER_SIZE); + if (xvid_flags & AV_CODEC_FLAG_PASS1) { + rc2pass1.version = XVID_VERSION; + rc2pass1.context = x; + x->twopassbuffer = av_malloc(BUFFER_SIZE); x->old_twopassbuffer = av_malloc(BUFFER_SIZE); if (!x->twopassbuffer || !x->old_twopassbuffer) { av_log(avctx, AV_LOG_ERROR, - "Xvid: Cannot allocate 2-pass log buffers\n"); - return -1; + "Xvid: Cannot allocate 2-pass log buffers\n"); + return AVERROR(ENOMEM); } - x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0; + x->twopassbuffer[0] = + x->old_twopassbuffer[0] = 0; - plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass; + 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 ) { + } else if (xvid_flags & AV_CODEC_FLAG_PASS2) { rc2pass2.version = XVID_VERSION; rc2pass2.bitrate = avctx->bit_rate; fd = ff_tempfile("xvidff.", &x->twopassfile); - if( fd == -1 ) { - av_log(avctx, AV_LOG_ERROR, - "Xvid: Cannot write 2-pass pipe\n"); - return -1; + if (fd < 0) { + av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write 2-pass pipe\n"); + return fd; } if (!avctx->stats_in) { av_log(avctx, AV_LOG_ERROR, - "Xvid: No 2-pass information loaded for second pass\n"); - return -1; + "Xvid: No 2-pass information loaded for second pass\n"); + return AVERROR_INVALIDDATA; } - if( strlen(avctx->stats_in) > - write(fd, avctx->stats_in, strlen(avctx->stats_in)) ) { + 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; + av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write to 2-pass pipe\n"); + return AVERROR(EIO); } close(fd); - rc2pass2.filename = x->twopassfile; - plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2; + 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) ) { + } else if (!(xvid_flags & AV_CODEC_FLAG_QSCALE)) { /* Single Pass Bitrate Control! */ single.version = XVID_VERSION; single.bitrate = avctx->bit_rate; - plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single; plugins[xvid_enc_create.num_plugins].param = &single; xvid_enc_create.num_plugins++; } @@ -531,19 +564,19 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { /* Luminance Masking */ if (x->lumi_aq) { - masking_l.method = 0; + masking_l.method = 0; plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking; /* The old behavior is that when avctx->lumi_masking is specified, * plugins[...].param = NULL. Trying to keep the old behavior here. */ - plugins[xvid_enc_create.num_plugins].param = avctx->lumi_masking ? NULL - : &masking_l; - xvid_enc_create.num_plugins++; + plugins[xvid_enc_create.num_plugins].param = + avctx->lumi_masking ? NULL : &masking_l; + xvid_enc_create.num_plugins++; } /* Variance AQ */ if (x->variance_aq) { - masking_v.method = 1; + masking_v.method = 1; plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking; plugins[xvid_enc_create.num_plugins].param = &masking_v; xvid_enc_create.num_plugins++; @@ -551,11 +584,11 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { /* SSIM */ if (x->ssim) { - plugins[xvid_enc_create.num_plugins].func = xvid_plugin_ssim; - ssim.b_printstat = x->ssim == 2; - ssim.acc = x->ssim_acc; - ssim.cpu_flags = xvid_gbl_init.cpu_flags; - ssim.b_visualize = 0; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_ssim; + ssim.b_printstat = x->ssim == 2; + ssim.acc = x->ssim_acc; + ssim.cpu_flags = xvid_gbl_init.cpu_flags; + ssim.b_visualize = 0; plugins[xvid_enc_create.num_plugins].param = &ssim; xvid_enc_create.num_plugins++; } @@ -564,14 +597,16 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { 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 ) + 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; + if (xvid_flags & AV_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; @@ -581,68 +616,116 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) { 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]; - } + x->intra_matrix = + x->inter_matrix = NULL; + +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->mpeg_quant) + x->mpeg_quant = avctx->mpeg_quant; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (x->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); + if (!x->intra_matrix) + return AVERROR(ENOMEM); + } else + intra = NULL; + if (avctx->inter_matrix) { + inter = avctx->inter_matrix; + x->inter_matrix = av_malloc(sizeof(unsigned char) * 64); + if (!x->inter_matrix) + return AVERROR(ENOMEM); + } 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 = 0; + if (xvid_flags & AV_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 = NULL; avctx->extradata_size = 0; - if( xvid_flags & CODEC_FLAG_GLOBAL_HEADER ) { - /* In this case, we are claiming to be MPEG4 */ + if (xvid_flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + /* In this case, we are claiming to be MPEG-4 */ x->quicktime_format = 1; - avctx->codec_id = AV_CODEC_ID_MPEG4; + avctx->codec_id = AV_CODEC_ID_MPEG4; } else { /* We are claiming to be Xvid */ x->quicktime_format = 0; - if(!avctx->codec_tag) + if (!avctx->codec_tag) avctx->codec_tag = AV_RL32("xvid"); } /* Bframes */ - xvid_enc_create.max_bframes = avctx->max_b_frames; + 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; + 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; + + /* Encode a dummy frame to get the extradata immediately */ + if (x->quicktime_format) { + AVFrame *picture; + AVPacket packet; + int got_packet, ret; + + av_init_packet(&packet); + + picture = av_frame_alloc(); + if (!picture) + return AVERROR(ENOMEM); + + xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); + if (xerr) { + av_frame_free(&picture); + av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n"); + return AVERROR_UNKNOWN; + } + x->encoder_handle = xvid_enc_create.handle; + + picture->width = avctx->width; + picture->height = avctx->height; + picture->format = avctx->pix_fmt; + + if ((ret = av_frame_get_buffer(picture, 32)) < 0) { + xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); + av_frame_free(&picture); + return ret; + } + + ret = xvid_encode_frame(avctx, &packet, picture, &got_packet); + if (!ret && got_packet) + av_packet_unref(&packet); + av_frame_free(&picture); + xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); + } /* Create encoder context */ xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); - if( xerr ) { + 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 = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); + x->encoder_handle = xvid_enc_create.handle; return 0; } @@ -651,17 +734,16 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *picture, int *got_packet) { int xerr, i, ret, user_packet = !!pkt->data; - char *tmp; struct xvid_context *x = avctx->priv_data; - AVFrame *p = avctx->coded_frame; - int mb_width = (avctx->width + 15) / 16; - int mb_height = (avctx->height + 15) / 16; + int mb_width = (avctx->width + 15) / 16; + int mb_height = (avctx->height + 15) / 16; + char *tmp; xvid_enc_frame_t xvid_enc_frame = { 0 }; xvid_enc_stats_t xvid_enc_stats = { 0 }; if (!user_packet && - (ret = av_new_packet(pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0) { + (ret = av_new_packet(pkt, mb_width * mb_height * MAX_MB_BYTES + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } @@ -675,27 +757,28 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, xvid_enc_frame.length = pkt->size; /* Initialize input image fields */ - if( avctx->pix_fmt != AV_PIX_FMT_YUV420P ) { - av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420p not supported\n"); + if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { + av_log(avctx, AV_LOG_ERROR, + "Xvid: Color spaces other than 420P not supported\n"); return -1; } xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */ - for( i = 0; i < 4; i++ ) { - xvid_enc_frame.input.plane[i] = picture->data[i]; + 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_enc_frame.motion = x->me_flags; + xvid_enc_frame.type = picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP : picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP : picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP : - XVID_TYPE_AUTO; + XVID_TYPE_AUTO; /* Pixel aspect ratio setting */ if (avctx->sample_aspect_ratio.num < 1 || avctx->sample_aspect_ratio.num > 255 || @@ -704,13 +787,15 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); return -1; } - xvid_enc_frame.par = XVID_PAR_EXT; + xvid_enc_frame.par = XVID_PAR_EXT; xvid_enc_frame.par_width = avctx->sample_aspect_ratio.num; xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den; /* Quant Setting */ - if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA; - else xvid_enc_frame.quant = 0; + 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; @@ -718,58 +803,82 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* Encode */ xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE, - &xvid_enc_frame, &xvid_enc_stats); + &xvid_enc_frame, &xvid_enc_stats); /* Two-pass log buffer swapping */ avctx->stats_out = NULL; - if( x->twopassbuffer ) { - tmp = x->old_twopassbuffer; + 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 ) { + x->twopassbuffer = tmp; + x->twopassbuffer[0] = 0; + if (x->old_twopassbuffer[0] != 0) { avctx->stats_out = x->old_twopassbuffer; } } if (xerr > 0) { + uint8_t *sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = xvid_enc_stats.quant * FF_QP2LAMBDA; + *got_packet = 1; - p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; - if( xvid_enc_stats.type == XVID_TYPE_PVOP ) - p->pict_type = AV_PICTURE_TYPE_P; - else if( xvid_enc_stats.type == XVID_TYPE_BVOP ) - p->pict_type = AV_PICTURE_TYPE_B; - else if( xvid_enc_stats.type == XVID_TYPE_SVOP ) - p->pict_type = AV_PICTURE_TYPE_S; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; + if (xvid_enc_stats.type == XVID_TYPE_PVOP) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; + else if (xvid_enc_stats.type == XVID_TYPE_BVOP) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; + else if (xvid_enc_stats.type == XVID_TYPE_SVOP) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_S; else - p->pict_type = AV_PICTURE_TYPE_I; - if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) { - p->key_frame = 1; - pkt->flags |= AV_PKT_FLAG_KEY; - if( x->quicktime_format ) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (xvid_enc_frame.out_flags & XVID_KEYFRAME) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + pkt->flags |= AV_PKT_FLAG_KEY; + if (x->quicktime_format) return xvid_strip_vol_header(avctx, pkt, - xvid_enc_stats.hlength, xerr); - } else - p->key_frame = 0; + xvid_enc_stats.hlength, xerr); + } else { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->key_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } pkt->size = xerr; return 0; } else { if (!user_packet) - av_free_packet(pkt); + av_packet_unref(pkt); if (!xerr) return 0; - av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr); - return -1; + av_log(avctx, AV_LOG_ERROR, + "Xvid: Encoding Error Occurred: %i\n", xerr); + return xerr; } } -static av_cold int xvid_encode_close(AVCodecContext *avctx) { +static av_cold int xvid_encode_close(AVCodecContext *avctx) +{ struct xvid_context *x = avctx->priv_data; - xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); + if (x->encoder_handle) { + xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); + x->encoder_handle = NULL; + } av_freep(&avctx->extradata); if (x->twopassbuffer) { @@ -786,14 +895,16 @@ static av_cold int xvid_encode_close(AVCodecContext *avctx) { #define OFFSET(x) offsetof(struct xvid_context, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "lumi_aq", "Luminance masking AQ", OFFSET(lumi_aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, - { "variance_aq", "Variance AQ", OFFSET(variance_aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, - { "ssim", "Show SSIM information to stdout", OFFSET(ssim), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE, "ssim" }, - { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "ssim" }, - { "avg", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "ssim" }, - { "frame", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "ssim" }, - { "ssim_acc", "SSIM accuracy", OFFSET(ssim_acc), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, VE }, - { "gmc", "use GMC", OFFSET(gmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "lumi_aq", "Luminance masking AQ", OFFSET(lumi_aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "variance_aq", "Variance AQ", OFFSET(variance_aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "ssim", "Show SSIM information to stdout", OFFSET(ssim), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE, "ssim" }, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "ssim" }, + { "avg", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "ssim" }, + { "frame", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "ssim" }, + { "ssim_acc", "SSIM accuracy", OFFSET(ssim_acc), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, VE }, + { "gmc", "use GMC", OFFSET(gmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "me_quality", "Motion estimation quality", OFFSET(me_quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 6, VE }, + { "mpeg_quant", "Use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { NULL }, }; @@ -813,6 +924,8 @@ AVCodec ff_libxvid_encoder = { .init = xvid_encode_init, .encode2 = xvid_encode_frame, .close = xvid_encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &xvid_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/libxvid.h b/libavcodec/libxvid.h index 413d353..4535898 100644 --- a/libavcodec/libxvid.h +++ b/libavcodec/libxvid.h @@ -26,7 +26,13 @@ * common functions for use with the Xvid wrappers */ - int ff_tempfile(const char *prefix, char **filename); +struct MpegEncContext; + +/* rate control */ +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_LIBXVID_H */ diff --git a/libavcodec/libxvid_rc.c b/libavcodec/libxvid_rc.c index a17a776..26f3c49 100644 --- a/libavcodec/libxvid_rc.c +++ b/libavcodec/libxvid_rc.c @@ -21,38 +21,38 @@ */ #include "config.h" -#include -#include + #if !HAVE_MKSTEMP #include #endif +#include +#include #include "libavutil/attributes.h" #include "libavutil/internal.h" + #include "avcodec.h" #include "libxvid.h" #include "mpegvideo.h" -#undef NDEBUG -#include - /* Wrapper to work around the lack of mkstemp() on mingw. * Also, tries to create file in /tmp first, if possible. * *prefix can be a character constant; *filename will be allocated internally. * @return file descriptor of opened file (or -1 on error) * and opened file name in **filename. */ -int ff_tempfile(const char *prefix, char **filename) { - int fd=-1; +int ff_tempfile(const char *prefix, char **filename) +{ + int fd = -1; #if !HAVE_MKSTEMP *filename = tempnam(".", prefix); #else size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */ - *filename = av_malloc(len); + *filename = av_malloc(len); #endif /* -----common section-----*/ if (!(*filename)) { av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n"); - return -1; + return AVERROR(ENOMEM); } #if !HAVE_MKSTEMP fd = avpriv_open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444); @@ -67,7 +67,7 @@ int ff_tempfile(const char *prefix, char **filename) { /* -----common section-----*/ if (fd < 0) { av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename); - return -1; + return AVERROR(EIO); } return fd; /* success */ } @@ -79,94 +79,105 @@ av_cold int ff_xvid_rate_control_init(MpegEncContext *s) xvid_plg_create_t xvid_plg_create = { 0 }; xvid_plugin_2pass2_t xvid_2pass2 = { 0 }; - fd=ff_tempfile("xvidrc.", &tmp_name); - if (fd == -1) { + fd = ff_tempfile("xvidrc.", &tmp_name); + if (fd < 0) { av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n"); - return -1; + return fd; } - for(i=0; irc_context.num_entries; i++){ + 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]; + 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); + 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); write(fd, tmp, strlen(tmp)); } close(fd); - xvid_2pass2.version= XVID_MAKE_VERSION(1,1,0); - xvid_2pass2.filename= tmp_name; - xvid_2pass2.bitrate= s->avctx->bit_rate; - xvid_2pass2.vbv_size= s->avctx->rc_buffer_size; - xvid_2pass2.vbv_maxrate= s->avctx->rc_max_rate; - xvid_2pass2.vbv_initial= s->avctx->rc_initial_buffer_occupancy; + xvid_2pass2.version = XVID_MAKE_VERSION(1, 1, 0); + xvid_2pass2.filename = tmp_name; + xvid_2pass2.bitrate = s->avctx->bit_rate; + xvid_2pass2.vbv_size = s->avctx->rc_buffer_size; + xvid_2pass2.vbv_maxrate = s->avctx->rc_max_rate; + xvid_2pass2.vbv_initial = s->avctx->rc_initial_buffer_occupancy; - xvid_plg_create.version= XVID_MAKE_VERSION(1,1,0); - xvid_plg_create.fbase= s->avctx->time_base.den; - xvid_plg_create.fincr= s->avctx->time_base.num; - xvid_plg_create.param= &xvid_2pass2; + 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){ + 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){ +float ff_xvid_rate_estimate_qscale(MpegEncContext *s, int dry_run) +{ xvid_plg_data_t xvid_plg_data = { 0 }; - xvid_plg_data.version= XVID_MAKE_VERSION(1,1,0); - xvid_plg_data.width = s->width; - xvid_plg_data.height= s->height; - xvid_plg_data.mb_width = s->mb_width; - xvid_plg_data.mb_height= s->mb_height; - xvid_plg_data.fbase= s->avctx->time_base.den; - xvid_plg_data.fincr= s->avctx->time_base.num; - xvid_plg_data.min_quant[0]= s->avctx->qmin; - xvid_plg_data.min_quant[1]= s->avctx->qmin; - xvid_plg_data.min_quant[2]= s->avctx->qmin; //FIXME i/b factor & offset - xvid_plg_data.max_quant[0]= s->avctx->qmax; - xvid_plg_data.max_quant[1]= s->avctx->qmax; - xvid_plg_data.max_quant[2]= s->avctx->qmax; //FIXME i/b factor & offset - xvid_plg_data.bquant_offset = 0; // 100 * s->avctx->b_quant_offset; - xvid_plg_data.bquant_ratio = 100; // * s->avctx->b_quant_factor; - - if(!s->rc_context.dry_run_qscale){ - if(s->picture_number){ - xvid_plg_data.length= - xvid_plg_data.stats.length= (s->frame_bits + 7)/8; - xvid_plg_data.frame_num= s->rc_context.last_picture_number; - xvid_plg_data.quant= s->qscale; - - xvid_plg_data.type= s->last_pict_type; - if(xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_AFTER, &xvid_plg_data, NULL)){ - av_log(s->avctx, AV_LOG_ERROR, "xvid_plugin_2pass2(handle, XVID_PLG_AFTER, ...) FAILED\n"); + xvid_plg_data.version = XVID_MAKE_VERSION(1, 1, 0); + xvid_plg_data.width = s->width; + xvid_plg_data.height = s->height; + xvid_plg_data.mb_width = s->mb_width; + xvid_plg_data.mb_height = s->mb_height; + xvid_plg_data.fbase = s->avctx->time_base.den; + xvid_plg_data.fincr = s->avctx->time_base.num; + xvid_plg_data.min_quant[0] = s->avctx->qmin; + xvid_plg_data.min_quant[1] = s->avctx->qmin; + xvid_plg_data.min_quant[2] = s->avctx->qmin; // FIXME i/b factor & offset + xvid_plg_data.max_quant[0] = s->avctx->qmax; + xvid_plg_data.max_quant[1] = s->avctx->qmax; + xvid_plg_data.max_quant[2] = s->avctx->qmax; // FIXME i/b factor & offset + xvid_plg_data.bquant_offset = 0; // 100 * s->avctx->b_quant_offset; + xvid_plg_data.bquant_ratio = 100; // * s->avctx->b_quant_factor; + + if (!s->rc_context.dry_run_qscale) { + if (s->picture_number) { + xvid_plg_data.length = + xvid_plg_data.stats.length = (s->frame_bits + 7) / 8; + xvid_plg_data.frame_num = s->rc_context.last_picture_number; + xvid_plg_data.quant = s->qscale; + xvid_plg_data.type = s->last_pict_type; + if (xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, + XVID_PLG_AFTER, &xvid_plg_data, NULL)) { + av_log(s->avctx, AV_LOG_ERROR, + "xvid_plugin_2pass2(handle, XVID_PLG_AFTER, ...) FAILED\n"); return -1; } } - s->rc_context.last_picture_number= - xvid_plg_data.frame_num= s->picture_number; - xvid_plg_data.quant= 0; - if(xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_BEFORE, &xvid_plg_data, NULL)){ - av_log(s->avctx, AV_LOG_ERROR, "xvid_plugin_2pass2(handle, XVID_PLG_BEFORE, ...) FAILED\n"); + 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; + s->rc_context.dry_run_qscale = xvid_plg_data.quant; } - xvid_plg_data.quant= s->rc_context.dry_run_qscale; - if(!dry_run) - s->rc_context.dry_run_qscale= 0; - - if(s->pict_type == AV_PICTURE_TYPE_B) //FIXME this is not exactly identical to xvid - return xvid_plg_data.quant * FF_QP2LAMBDA * s->avctx->b_quant_factor + s->avctx->b_quant_offset; + xvid_plg_data.quant = s->rc_context.dry_run_qscale; + if (!dry_run) + s->rc_context.dry_run_qscale = 0; + + // FIXME this is not exactly identical to Xvid + if (s->pict_type == AV_PICTURE_TYPE_B) + 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; } @@ -175,5 +186,6 @@ av_cold 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); + xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_DESTROY, + &xvid_plg_destroy, NULL); } diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index fbb024b..b6d73a4 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -37,12 +37,13 @@ #include "avcodec.h" #include "idctdsp.h" #include "internal.h" +#include "jpegtables.h" #include "mjpegenc_common.h" -#include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" typedef struct LJpegEncContext { + AVClass *class; IDCTDSPContext idsp; ScanTable scantable; uint16_t matrix[64]; @@ -56,6 +57,7 @@ typedef struct LJpegEncContext { uint8_t huff_size_dc_chrominance[12]; uint16_t (*scratch)[4]; + int pred; } LJpegEncContext; static int ljpeg_encode_bgr(AVCodecContext *avctx, PutBitContext *pb, @@ -66,15 +68,21 @@ static int ljpeg_encode_bgr(AVCodecContext *avctx, PutBitContext *pb, const int height = frame->height; const int linesize = frame->linesize[0]; uint16_t (*buffer)[4] = s->scratch; - const int predictor = avctx->prediction_method+1; int left[3], top[3], topleft[3]; int x, y, i; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->prediction_method) + s->pred = avctx->prediction_method + 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + 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; + const int modified_predictor = y ? s->pred : 1; uint8_t *ptr = frame->data[0] + (linesize * y); if (pb->buf_end - pb->buf - (put_bits_count(pb) >> 3) < width * 3 * 3) { @@ -181,12 +189,18 @@ static inline void ljpeg_encode_yuv_mb(LJpegEncContext *s, PutBitContext *pb, static int ljpeg_encode_yuv(AVCodecContext *avctx, PutBitContext *pb, const AVFrame *frame) { - const int predictor = avctx->prediction_method + 1; LJpegEncContext *s = avctx->priv_data; const int mb_width = (avctx->width + s->hsample[0] - 1) / s->hsample[0]; const int mb_height = (avctx->height + s->vsample[0] - 1) / s->vsample[0]; int mb_x, mb_y; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->prediction_method) + s->pred = avctx->prediction_method + 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + for (mb_y = 0; mb_y < mb_height; mb_y++) { if (pb->buf_end - pb->buf - (put_bits_count(pb) >> 3) < mb_width * 4 * 3 * s->hsample[0] * s->vsample[0]) { @@ -195,7 +209,7 @@ static int ljpeg_encode_yuv(AVCodecContext *avctx, PutBitContext *pb, } for (mb_x = 0; mb_x < mb_width; mb_x++) - ljpeg_encode_yuv_mb(s, pb, frame, predictor, mb_x, mb_y); + ljpeg_encode_yuv_mb(s, pb, frame, s->pred, mb_x, mb_y); } return 0; @@ -210,7 +224,7 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const int height = avctx->height; const int mb_width = (width + s->hsample[0] - 1) / s->hsample[0]; const int mb_height = (height + s->vsample[0] - 1) / s->vsample[0]; - int max_pkt_size = FF_MIN_BUFFER_SIZE; + int max_pkt_size = AV_INPUT_BUFFER_MIN_SIZE; int ret, header_bits; if (avctx->pix_fmt == AV_PIX_FMT_BGR24) @@ -227,7 +241,7 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, init_put_bits(&pb, pkt->data, pkt->size); ff_mjpeg_encode_picture_header(avctx, &pb, &s->scantable, - s->matrix); + s->pred, s->matrix); header_bits = put_bits_count(&pb); @@ -254,7 +268,6 @@ static av_cold int ljpeg_encode_close(AVCodecContext *avctx) { LJpegEncContext *s = avctx->priv_data; - av_frame_free(&avctx->coded_frame); av_freep(&s->scratch); return 0; @@ -276,12 +289,12 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->scratch = av_malloc_array(avctx->width + 1, sizeof(*s->scratch)); @@ -317,12 +330,31 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) return 0; } +#define OFFSET(x) offsetof(LJpegEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, + { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, + + { NULL}, +}; + +static const AVClass ljpeg_class = { + .class_name = "ljpeg", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_ljpeg_encoder = { .name = "ljpeg", .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_LJPEG, .priv_data_size = sizeof(LJpegEncContext), + .priv_class = &ljpeg_class, .init = ljpeg_encode_init, .encode2 = ljpeg_encode_frame, .close = ljpeg_encode_close, diff --git a/libavcodec/loco.c b/libavcodec/loco.c index 6be081d..f25ef61 100644 --- a/libavcodec/loco.c +++ b/libavcodec/loco.c @@ -323,5 +323,5 @@ AVCodec ff_loco_decoder = { .priv_data_size = sizeof(LOCOContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c index fbd1bdf..1482e57 100644 --- a/libavcodec/lpc.c +++ b/libavcodec/lpc.c @@ -174,7 +174,7 @@ int ff_lpc_calc_coefs(LPCContext *s, int omethod, int max_shift, int zero_shift) { double autoc[MAX_LPC_ORDER+1]; - double ref[MAX_LPC_ORDER]; + double ref[MAX_LPC_ORDER] = { 0 }; double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER]; int i, j, pass = 0; int opt_order; diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h index c41a1f8..642854c 100644 --- a/libavcodec/lpc.h +++ b/libavcodec/lpc.h @@ -152,7 +152,7 @@ static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, int normalize) { int i, j; - LPC_TYPE err; + LPC_TYPE err = 0; LPC_TYPE *lpc_last = lpc; if (normalize) diff --git a/libavcodec/lsp.c b/libavcodec/lsp.c index 8a05aed..982c87e 100644 --- a/libavcodec/lsp.c +++ b/libavcodec/lsp.c @@ -32,7 +32,7 @@ void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, in { int i, j; - /* sort lsfq in ascending order. float bubble agorithm, + /* sort lsfq in ascending order. float bubble algorithm, O(n) if data already sorted, O(n^2) - otherwise */ for(i=0; i=0 && lsfq[j] > lsfq[j+1]; j--) diff --git a/libavcodec/lsp.h b/libavcodec/lsp.h index 4b95567..1f9481c 100644 --- a/libavcodec/lsp.h +++ b/libavcodec/lsp.h @@ -102,7 +102,7 @@ void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd * @param lp_half_order half the number of the amount of LPCs to be * reconstructed, need to be smaller or equal to MAX_LP_HALF_ORDER * - * @note buffers should have a minimux size of 2*lp_half_order elements. + * @note buffers should have a minimum size of 2*lp_half_order elements. * * TIA/EIA/IS-733 2.4.3.3.5 */ diff --git a/libavcodec/lzf.c b/libavcodec/lzf.c new file mode 100644 index 0000000..35b932b --- /dev/null +++ b/libavcodec/lzf.c @@ -0,0 +1,90 @@ +/* + * lzf decompression algorithm + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * lzf decompression + * + * LZF is a fast compression/decompression algorithm that takes very little + * code space and working memory, ideal for real-time and block compression. + * + * https://en.wikibooks.org/wiki/Data_Compression/Dictionary_compression#LZF + */ + +#include "libavutil/mem.h" + +#include "bytestream.h" +#include "lzf.h" + +#define LZF_LITERAL_MAX (1 << 5) +#define LZF_LONG_BACKREF 7 + 2 + +int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, int64_t *size) +{ + int ret = 0; + uint8_t *p = *buf; + int64_t len = 0; + + while (bytestream2_get_bytes_left(gb) > 2) { + uint8_t s = bytestream2_get_byte(gb); + + if (s < LZF_LITERAL_MAX) { + s++; + if (s > *size - len) { + *size += *size /2; + ret = av_reallocp(buf, *size); + if (ret < 0) + return ret; + } + + bytestream2_get_buffer(gb, p, s); + p += s; + len += s; + } else { + int l = 2 + (s >> 5); + int off = ((s & 0x1f) << 8) + 1; + + if (l == LZF_LONG_BACKREF) + l += bytestream2_get_byte(gb); + + off += bytestream2_get_byte(gb); + + if (off > len) + return AVERROR_INVALIDDATA; + + if (l > *size - len) { + *size += *size / 2; + ret = av_reallocp(buf, *size); + if (ret < 0) + return ret; + } + + av_memcpy_backptr(p, off, l); + + p += l; + len += l; + } + } + + *size = len; + + return 0; +} diff --git a/libavcodec/lzf.h b/libavcodec/lzf.h new file mode 100644 index 0000000..4951f25 --- /dev/null +++ b/libavcodec/lzf.h @@ -0,0 +1,29 @@ +/* + * lzf decompression algorithm + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LZF_H +#define AVCODEC_LZF_H + +#include "bytestream.h" + +int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, int64_t *size); + +#endif /* AVCODEC_LZF_H */ diff --git a/libavcodec/mace.c b/libavcodec/mace.c index 25c6b70..c6eddc0 100644 --- a/libavcodec/mace.c +++ b/libavcodec/mace.c @@ -287,7 +287,7 @@ AVCodec ff_mace3_decoder = { .priv_data_size = sizeof(MACEContext), .init = mace_decode_init, .decode = mace_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; @@ -300,7 +300,7 @@ AVCodec ff_mace6_decoder = { .priv_data_size = sizeof(MACEContext), .init = mace_decode_init, .decode = mace_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c new file mode 100644 index 0000000..310ead4 --- /dev/null +++ b/libavcodec/magicyuv.c @@ -0,0 +1,480 @@ +/* + * MagicYUV decoder + * Copyright (c) 2016 Paul B Mahol + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "../libavutil/pixdesc.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "huffyuvdsp.h" +#include "internal.h" +#include "thread.h" + +typedef struct Slice { + uint32_t start; + uint32_t size; +} Slice; + +typedef enum Prediction { + LEFT = 1, + GRADIENT, + MEDIAN, +} Prediction; + +typedef struct HuffEntry { + uint8_t sym; + uint8_t len; + uint32_t code; +} HuffEntry; + +typedef struct MagicYUVContext { + AVFrame *p; + int slice_height; + int nb_slices; + int planes; // number of encoded planes in bitstream + int decorrelate; // postprocessing work + int interlaced; // video is interlaced + uint8_t *buf; // pointer to AVPacket->data + int hshift[4]; + int vshift[4]; + Slice *slices[4]; // slice bitstream positions for each plane + unsigned int slices_size[4]; // slice sizes for each plane + uint8_t len[4][256]; // table of code lengths for each plane + VLC vlc[4]; // VLC for each plane + HuffYUVDSPContext hdsp; +} MagicYUVContext; + +static int huff_cmp_len(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return (aa->len - bb->len) * 256 + aa->sym - bb->sym; +} + +static int huff_build(VLC *vlc, uint8_t *len) +{ + HuffEntry he[256]; + uint32_t codes[256]; + uint8_t bits[256]; + uint8_t syms[256]; + uint32_t code; + int i; + + for (i = 0; i < 256; i++) { + he[i].sym = 255 - i; + he[i].len = len[i]; + } + qsort(he, 256, sizeof(HuffEntry), huff_cmp_len); + + code = 1; + for (i = 255; i >= 0; i--) { + codes[i] = code >> (32 - he[i].len); + bits[i] = he[i].len; + syms[i] = he[i].sym; + code += 0x80000000u >> (he[i].len - 1); + } + + ff_free_vlc(vlc); + return ff_init_vlc_sparse(vlc, FFMIN(he[255].len, 12), 256, + bits, sizeof(*bits), sizeof(*bits), + codes, sizeof(*codes), sizeof(*codes), + syms, sizeof(*syms), sizeof(*syms), 0); +} + +static int magy_decode_slice(AVCodecContext *avctx, void *tdata, + int j, int threadnr) +{ + MagicYUVContext *s = avctx->priv_data; + int interlaced = s->interlaced; + AVFrame *p = s->p; + int i, k, x; + GetBitContext gb; + uint8_t *dst; + + for (i = 0; i < s->planes; i++) { + int left, lefttop, top; + int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->height - j * s->slice_height), s->vshift[i]); + int width = AV_CEIL_RSHIFT(avctx->width, s->hshift[i]); + int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); + ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced); + ptrdiff_t stride = p->linesize[i]; + int flags, pred; + int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start, + s->slices[i][j].size); + + if (ret < 0) + return ret; + + flags = get_bits(&gb, 8); + pred = get_bits(&gb, 8); + + dst = p->data[i] + j * sheight * stride; + if (flags & 1) { + for (k = 0; k < height; k++) { + for (x = 0; x < width; x++) + dst[x] = get_bits(&gb, 8); + + dst += stride; + } + } else { + for (k = 0; k < height; k++) { + for (x = 0; x < width; x++) { + int pix; + if (get_bits_left(&gb) <= 0) + return AVERROR_INVALIDDATA; + + pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3); + if (pix < 0) + return AVERROR_INVALIDDATA; + + dst[x] = 255 - pix; + } + dst += stride; + } + } + + switch (pred) { + case LEFT: + dst = p->data[i] + j * sheight * stride; + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + dst += stride; + if (interlaced) { + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + dst += stride; + } + for (k = 1 + interlaced; k < height; k++) { + s->hdsp.add_hfyu_left_pred(dst, dst, width, dst[-fake_stride]); + dst += stride; + } + break; + case GRADIENT: + dst = p->data[i] + j * sheight * stride; + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + left = lefttop = 0; + dst += stride; + if (interlaced) { + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + left = lefttop = 0; + dst += stride; + } + for (k = 1 + interlaced; k < height; k++) { + top = dst[-fake_stride]; + left = top + dst[0]; + dst[0] = left; + for (x = 1; x < width; x++) { + top = dst[x - fake_stride]; + lefttop = dst[x - (fake_stride + 1)]; + left += top - lefttop + dst[x]; + dst[x] = left; + } + dst += stride; + } + break; + case MEDIAN: + dst = p->data[i] + j * sheight * stride; + lefttop = left = dst[0]; + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + dst += stride; + if (interlaced) { + lefttop = left = dst[0]; + s->hdsp.add_hfyu_left_pred(dst, dst, width, 0); + dst += stride; + } + for (k = 1 + interlaced; k < height; k++) { + s->hdsp.add_hfyu_median_pred(dst, dst - fake_stride, + dst, width, &left, &lefttop); + lefttop = left = dst[0]; + dst += stride; + } + break; + default: + avpriv_request_sample(avctx, "Unknown prediction: %d", pred); + } + } + + if (s->decorrelate) { + int height = FFMIN(s->slice_height, avctx->height - j * s->slice_height); + int width = avctx->width; + uint8_t *b = p->data[0] + j * s->slice_height * p->linesize[0]; + uint8_t *g = p->data[1] + j * s->slice_height * p->linesize[1]; + uint8_t *r = p->data[2] + j * s->slice_height * p->linesize[2]; + + for (i = 0; i < height; i++) { + s->hdsp.add_bytes(b, g, width); + s->hdsp.add_bytes(r, g, width); + b += p->linesize[0]; + g += p->linesize[1]; + r += p->linesize[2]; + } + } + + return 0; +} + +static int magy_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + MagicYUVContext *s = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *p = data; + GetByteContext gbyte; + GetBitContext gbit; + uint32_t first_offset, offset, next_offset, header_size, slice_width; + int width, height, format, version, table_size; + int ret, i, j, k; + + bytestream2_init(&gbyte, avpkt->data, avpkt->size); + if (bytestream2_get_le32(&gbyte) != MKTAG('M', 'A', 'G', 'Y')) + return AVERROR_INVALIDDATA; + + header_size = bytestream2_get_le32(&gbyte); + if (header_size < 32 || header_size >= avpkt->size) { + av_log(avctx, AV_LOG_ERROR, + "header or packet too small %"PRIu32"\n", header_size); + return AVERROR_INVALIDDATA; + } + + version = bytestream2_get_byte(&gbyte); + if (version != 7) { + avpriv_request_sample(avctx, "Version %d", version); + return AVERROR_PATCHWELCOME; + } + + s->hshift[1] = + s->vshift[1] = + s->hshift[2] = + s->vshift[2] = 0; + s->decorrelate = 0; + + format = bytestream2_get_byte(&gbyte); + switch (format) { + case 0x65: + avctx->pix_fmt = AV_PIX_FMT_GBRP; + s->decorrelate = 1; + break; + case 0x66: + avctx->pix_fmt = AV_PIX_FMT_GBRAP; + s->decorrelate = 1; + break; + case 0x67: + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + break; + case 0x68: + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + s->hshift[1] = + s->hshift[2] = 1; + break; + case 0x69: + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + s->hshift[1] = + s->vshift[1] = + s->hshift[2] = + s->vshift[2] = 1; + break; + case 0x6a: + avctx->pix_fmt = AV_PIX_FMT_YUVA444P; + break; + case 0x6b: + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + break; + default: + avpriv_request_sample(avctx, "Format 0x%X", format); + return AVERROR_PATCHWELCOME; + } + s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); + + bytestream2_skip(&gbyte, 2); + s->interlaced = !!(bytestream2_get_byte(&gbyte) & 2); + bytestream2_skip(&gbyte, 3); + + width = bytestream2_get_le32(&gbyte); + height = bytestream2_get_le32(&gbyte); + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + + slice_width = bytestream2_get_le32(&gbyte); + if (slice_width != width) { + avpriv_request_sample(avctx, "Slice width %"PRIu32, slice_width); + return AVERROR_PATCHWELCOME; + } + s->slice_height = bytestream2_get_le32(&gbyte); + if (s->slice_height <= 0 || s->slice_height > INT_MAX - height) { + av_log(avctx, AV_LOG_ERROR, + "invalid slice height: %d\n", s->slice_height); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbyte, 4); + + s->nb_slices = (height + s->slice_height - 1) / s->slice_height; + if (s->nb_slices > INT_MAX / sizeof(Slice)) { + av_log(avctx, AV_LOG_ERROR, + "invalid number of slices: %d\n", s->nb_slices); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < s->planes; i++) { + av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice)); + if (!s->slices[i]) + return AVERROR(ENOMEM); + + offset = bytestream2_get_le32(&gbyte); + if (offset >= avpkt->size - header_size) + return AVERROR_INVALIDDATA; + + if (i == 0) + first_offset = offset; + + for (j = 0; j < s->nb_slices - 1; j++) { + s->slices[i][j].start = offset + header_size; + + next_offset = bytestream2_get_le32(&gbyte); + if (next_offset <= offset || next_offset >= avpkt->size - header_size) + return AVERROR_INVALIDDATA; + + s->slices[i][j].size = next_offset - offset; + offset = next_offset; + } + + s->slices[i][j].start = offset + header_size; + s->slices[i][j].size = avpkt->size - s->slices[i][j].start; + } + + if (bytestream2_get_byte(&gbyte) != s->planes) + return AVERROR_INVALIDDATA; + + bytestream2_skip(&gbyte, s->nb_slices * s->planes); + + table_size = header_size + first_offset - bytestream2_tell(&gbyte); + if (table_size < 2) + return AVERROR_INVALIDDATA; + + ret = init_get_bits8(&gbit, avpkt->data + bytestream2_tell(&gbyte), table_size); + if (ret < 0) + return ret; + + memset(s->len, 0, sizeof(s->len)); + j = i = 0; + while (get_bits_left(&gbit) >= 8) { + int b = get_bits(&gbit, 4); + int x = get_bits(&gbit, 4); + int l = get_bitsz(&gbit, b) + 1; + + for (k = 0; k < l; k++) + if (j + k < 256) + s->len[i][j + k] = x; + + j += l; + if (j == 256) { + j = 0; + if (huff_build(&s->vlc[i], s->len[i])) { + av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); + return AVERROR_INVALIDDATA; + } + i++; + if (i == s->planes) { + break; + } + } else if (j > 256) { + return AVERROR_INVALIDDATA; + } + } + + if (i != s->planes) { + av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n"); + return AVERROR_INVALIDDATA; + } + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + s->buf = avpkt->data; + s->p = p; + avctx->execute2(avctx, magy_decode_slice, NULL, NULL, s->nb_slices); + + if (avctx->pix_fmt == AV_PIX_FMT_GBRP || + avctx->pix_fmt == AV_PIX_FMT_GBRAP) { + FFSWAP(uint8_t*, p->data[0], p->data[1]); + FFSWAP(int, p->linesize[0], p->linesize[1]); + } + + *got_frame = 1; + + return avpkt->size; +} + +#if HAVE_THREADS +static int magy_init_thread_copy(AVCodecContext *avctx) +{ + MagicYUVContext *s = avctx->priv_data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) { + s->slices[i] = NULL; + s->slices_size[i] = 0; + } + + return 0; +} +#endif + +static av_cold int magy_decode_init(AVCodecContext *avctx) +{ + MagicYUVContext *s = avctx->priv_data; + ff_huffyuvdsp_init(&s->hdsp); + return 0; +} + +static av_cold int magy_decode_end(AVCodecContext *avctx) +{ + MagicYUVContext * const s = avctx->priv_data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) { + av_freep(&s->slices[i]); + s->slices_size[i] = 0; + ff_free_vlc(&s->vlc[i]); + } + + return 0; +} + +AVCodec ff_magicyuv_decoder = { + .name = "magicyuv", + .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MAGICYUV, + .priv_data_size = sizeof(MagicYUVContext), + .init = magy_decode_init, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(magy_init_thread_copy), + .close = magy_decode_end, + .decode = magy_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/mathops.h b/libavcodec/mathops.h index 7af13e1..0afc82a 100644 --- a/libavcodec/mathops.h +++ b/libavcodec/mathops.h @@ -34,6 +34,7 @@ extern const uint8_t ff_reverse[256]; extern const uint8_t ff_sqrt_tab[256]; extern const uint8_t ff_crop_tab[256 + 2 * MAX_NEG_CROP]; extern const uint8_t ff_zigzag_direct[64]; +extern const uint8_t ff_zigzag_scan[16]; #if ARCH_ARM # include "arm/mathops.h" @@ -98,15 +99,6 @@ static av_always_inline unsigned UMULH(unsigned a, unsigned b){ #define mid_pred mid_pred static inline av_const int mid_pred(int a, int b, int c) { -#if 0 - int t= (a-b)&((a-b)>>31); - a-=t; - b+=t; - b-= (b-c)&((b-c)>>31); - b+= (a-b)&((a-b)>>31); - - return b; -#else if(a>b){ if(c>b){ if(c>a) b=a; @@ -119,7 +111,6 @@ static inline av_const int mid_pred(int a, int b, int c) } } return b; -#endif } #endif diff --git a/libavcodec/mathtables.c b/libavcodec/mathtables.c index 47695bc..d198225 100644 --- a/libavcodec/mathtables.c +++ b/libavcodec/mathtables.c @@ -122,3 +122,10 @@ const uint8_t ff_zigzag_direct[64] = { 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; + +const uint8_t ff_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, +}; diff --git a/libavcodec/mdct_template.c b/libavcodec/mdct_template.c index bad890e..5b3a6ff 100644 --- a/libavcodec/mdct_template.c +++ b/libavcodec/mdct_template.c @@ -56,6 +56,26 @@ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale) if (ff_fft_init(s, s->mdct_bits - 2, inverse) < 0) goto fail; + s->imdct_calc = ff_imdct_calc_c; + s->imdct_half = ff_imdct_half_c; + s->mdct_calc = ff_mdct_calc_c; + +#if FFT_FLOAT + if (ARCH_AARCH64) + ff_mdct_init_aarch64(s); + if (ARCH_ARM) + ff_mdct_init_arm(s); + if (ARCH_PPC) + ff_mdct_init_ppc(s); + if (ARCH_X86) + ff_mdct_init_x86(s); + s->mdct_calcw = s->mdct_calc; +#else + s->mdct_calcw = ff_mdct_calcw_c; + if (ARCH_ARM) + ff_mdct_fixed_init_arm(s); +#endif + s->tcos = av_malloc(n/2 * sizeof(FFTSample)); if (!s->tcos) goto fail; diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 2a779c1..4b6056e 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -30,7 +30,6 @@ #include "avcodec.h" #include "blockdsp.h" #include "idctdsp.h" -#include "mpegvideo.h" #include "mpeg12.h" #include "thread.h" @@ -130,7 +129,7 @@ static inline int mdec_decode_block_intra(MDECContext *a, int16_t *block, int n) static inline int decode_mb(MDECContext *a, int16_t block[6][64]) { int i, ret; - const int block_index[6] = { 5, 4, 0, 1, 2, 3 }; + static const int block_index[6] = { 5, 4, 0, 1, 2, 3 }; a->bdsp.clear_blocks(block[0]); @@ -158,7 +157,7 @@ static inline void idct_put(MDECContext *a, AVFrame *frame, int mb_x, int mb_y) a->idsp.idct_put(dest_y + 8 * linesize, linesize, block[2]); a->idsp.idct_put(dest_y + 8 * linesize + 8, linesize, block[3]); - if (!(a->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(a->avctx->flags & AV_CODEC_FLAG_GRAY)) { a->idsp.idct_put(dest_cb, frame->linesize[1], block[4]); a->idsp.idct_put(dest_cr, frame->linesize[2], block[5]); } @@ -181,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx, frame.f->pict_type = AV_PICTURE_TYPE_I; frame.f->key_frame = 1; - av_fast_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + av_fast_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!a->bitstream_buffer) return AVERROR(ENOMEM); for (i = 0; i < buf_size; i += 2) { @@ -263,6 +262,6 @@ AVCodec ff_mdec_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy) }; diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c index 9fcc937..eb98a72 100644 --- a/libavcodec/me_cmp.c +++ b/libavcodec/me_cmp.c @@ -27,7 +27,7 @@ uint32_t ff_square_tab[512] = { 0, }; static int sse4_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; uint32_t *sq = ff_square_tab + 256; @@ -37,14 +37,14 @@ static int sse4_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, s += sq[pix1[1] - pix2[1]]; s += sq[pix1[2] - pix2[2]]; s += sq[pix1[3] - pix2[3]]; - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } return s; } static int sse8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; uint32_t *sq = ff_square_tab + 256; @@ -58,14 +58,14 @@ static int sse8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, s += sq[pix1[5] - pix2[5]]; s += sq[pix1[6] - pix2[6]]; s += sq[pix1[7] - pix2[7]]; - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } return s; } static int sse16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; uint32_t *sq = ff_square_tab + 256; @@ -88,8 +88,8 @@ static int sse16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, s += sq[pix1[14] - pix2[14]]; s += sq[pix1[15] - pix2[15]]; - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } return s; } @@ -107,7 +107,7 @@ static int sum_abs_dctelem_c(int16_t *block) #define avg4(a, b, c, d) ((a + b + c + d + 2) >> 2) static inline int pix_abs16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; @@ -128,14 +128,14 @@ static inline int pix_abs16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, s += abs(pix1[13] - pix2[13]); s += abs(pix1[14] - pix2[14]); s += abs(pix1[15] - pix2[15]); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } return s; } static int pix_abs16_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; @@ -156,17 +156,17 @@ static int pix_abs16_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; } return s; } static int pix_abs16_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg2(pix2[0], pix3[0])); @@ -185,18 +185,18 @@ static int pix_abs16_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; + pix3 += stride; } return s; } static int pix_abs16_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1])); @@ -215,15 +215,15 @@ static int pix_abs16_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; + pix3 += stride; } return s; } static inline int pix_abs8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; @@ -236,14 +236,14 @@ static inline int pix_abs8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, s += abs(pix1[5] - pix2[5]); s += abs(pix1[6] - pix2[6]); s += abs(pix1[7] - pix2[7]); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } return s; } static int pix_abs8_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; @@ -256,17 +256,17 @@ static int pix_abs8_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; } return s; } static int pix_abs8_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg2(pix2[0], pix3[0])); @@ -277,18 +277,18 @@ static int pix_abs8_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; + pix3 += stride; } return s; } static int pix_abs8_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int s = 0, i; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1])); @@ -299,14 +299,15 @@ static int pix_abs8_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, 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; + pix1 += stride; + pix2 += stride; + pix3 += stride; } return s; } -static int nsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int h) +static int nsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, + ptrdiff_t stride, int h) { int score1 = 0, score2 = 0, x, y; @@ -330,7 +331,8 @@ static int nsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int return score1 + FFABS(score2) * 8; } -static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int h) +static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, + ptrdiff_t stride, int h) { int score1 = 0, score2 = 0, x, y; @@ -355,7 +357,7 @@ static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int } static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b, - int stride, int h) + ptrdiff_t stride, int h) { return 0; } @@ -430,7 +432,7 @@ void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type) #define BUTTERFLYA(x, y) (FFABS((x) + (y)) + FFABS((x) - (y))) static int hadamard8_diff8x8_c(MpegEncContext *s, uint8_t *dst, - uint8_t *src, int stride, int h) + uint8_t *src, ptrdiff_t stride, int h) { int i, temp[64], sum = 0; @@ -482,7 +484,7 @@ static int hadamard8_diff8x8_c(MpegEncContext *s, uint8_t *dst, } static int hadamard8_intra8x8_c(MpegEncContext *s, uint8_t *src, - uint8_t *dummy, int stride, int h) + uint8_t *dummy, ptrdiff_t stride, int h) { int i, temp[64], sum = 0; @@ -534,7 +536,7 @@ static int hadamard8_intra8x8_c(MpegEncContext *s, uint8_t *src, } static int dct_sad8x8_c(MpegEncContext *s, uint8_t *src1, - uint8_t *src2, int stride, int h) + uint8_t *src2, ptrdiff_t stride, int h) { LOCAL_ALIGNED_16(int16_t, temp, [64]); @@ -575,7 +577,7 @@ static int dct_sad8x8_c(MpegEncContext *s, uint8_t *src1, } static int dct264_sad8x8_c(MpegEncContext *s, uint8_t *src1, - uint8_t *src2, int stride, int h) + uint8_t *src2, ptrdiff_t stride, int h) { int16_t dct[8][8]; int i, sum = 0; @@ -600,7 +602,7 @@ static int dct264_sad8x8_c(MpegEncContext *s, uint8_t *src1, #endif static int dct_max8x8_c(MpegEncContext *s, uint8_t *src1, - uint8_t *src2, int stride, int h) + uint8_t *src2, ptrdiff_t stride, int h) { LOCAL_ALIGNED_16(int16_t, temp, [64]); int sum = 0, i; @@ -617,7 +619,7 @@ static int dct_max8x8_c(MpegEncContext *s, uint8_t *src1, } static int quant_psnr8x8_c(MpegEncContext *s, uint8_t *src1, - uint8_t *src2, int stride, int h) + uint8_t *src2, ptrdiff_t stride, int h) { LOCAL_ALIGNED_16(int16_t, temp, [64 * 2]); int16_t *const bak = temp + 64; @@ -642,7 +644,7 @@ static int quant_psnr8x8_c(MpegEncContext *s, uint8_t *src1, } static int rd8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, - int stride, int h) + ptrdiff_t stride, int h) { const uint8_t *scantable = s->intra_scantable.permutated; LOCAL_ALIGNED_16(int16_t, temp, [64]); @@ -719,7 +721,7 @@ static int rd8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, } static int bit8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, - int stride, int h) + ptrdiff_t stride, int h) { const uint8_t *scantable = s->intra_scantable.permutated; LOCAL_ALIGNED_16(int16_t, temp, [64]); @@ -782,7 +784,7 @@ static int bit8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2, #define VSAD_INTRA(size) \ static int vsad_intra ## size ## _c(MpegEncContext *c, \ uint8_t *s, uint8_t *dummy, \ - int stride, int h) \ + ptrdiff_t stride, int h) \ { \ int score = 0, x, y; \ \ @@ -802,7 +804,7 @@ VSAD_INTRA(8) VSAD_INTRA(16) static int vsad16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, - int stride, int h) + ptrdiff_t stride, int h) { int score = 0, x, y; @@ -820,7 +822,7 @@ static int vsad16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, #define VSSE_INTRA(size) \ static int vsse_intra ## size ## _c(MpegEncContext *c, \ uint8_t *s, uint8_t *dummy, \ - int stride, int h) \ + ptrdiff_t stride, int h) \ { \ int score = 0, x, y; \ \ @@ -840,7 +842,7 @@ VSSE_INTRA(8) VSSE_INTRA(16) static int vsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, - int stride, int h) + ptrdiff_t stride, int h) { int score = 0, x, y; @@ -856,7 +858,7 @@ static int vsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, #define WRAPPER8_16_SQ(name8, name16) \ static int name16(MpegEncContext *s, uint8_t *dst, uint8_t *src, \ - int stride, int h) \ + ptrdiff_t stride, int h) \ { \ int score = 0; \ \ diff --git a/libavcodec/me_cmp.h b/libavcodec/me_cmp.h index 05ae30b..725f9b2 100644 --- a/libavcodec/me_cmp.h +++ b/libavcodec/me_cmp.h @@ -33,7 +33,8 @@ struct MpegEncContext; * width < 8 are neither used nor implemented. */ typedef int (*me_cmp_func)(struct MpegEncContext *c, uint8_t *blk1 /* align width (8 or 16) */, - uint8_t *blk2 /* align 1 */, int line_size, int h); + uint8_t *blk2 /* align 1 */, ptrdiff_t stride, + int h); typedef struct MECmpContext { int (*sum_abs_dctelem)(int16_t *block /* align 16 */); diff --git a/libavcodec/metasound.c b/libavcodec/metasound.c index dd9ffe0..a3b210e 100644 --- a/libavcodec/metasound.c +++ b/libavcodec/metasound.c @@ -25,12 +25,13 @@ #include #include -#define BITSTREAM_READER_LE #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" -#include "get_bits.h" #include "fft.h" +#include "get_bits.h" #include "internal.h" #include "lsp.h" #include "sinewin.h" @@ -383,7 +384,7 @@ AVCodec ff_metasound_decoder = { .init = metasound_decode_init, .close = ff_twinvq_decode_close, .decode = ff_twinvq_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c index 88ee5d3..d7723a8 100644 --- a/libavcodec/mimic.c +++ b/libavcodec/mimic.c @@ -35,7 +35,7 @@ #define MIMIC_HEADER_SIZE 20 -typedef struct { +typedef struct MimicContext { AVCodecContext *avctx; int num_vblocks[3]; @@ -48,7 +48,6 @@ typedef struct { int prev_index; ThreadFrame frames [16]; - AVPicture flipped_ptrs[16]; DECLARE_ALIGNED(16, int16_t, dct_block)[64]; @@ -177,8 +176,6 @@ static int mimic_decode_update_thread_context(AVCodecContext *avctx, const AVCod dst->cur_index = src->next_cur_index; dst->prev_index = src->next_prev_index; - memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs)); - for (i = 0; i < FF_ARRAY_ELEMS(dst->frames); i++) { ff_thread_release_buffer(avctx, &dst->frames[i]); if (src->frames[i].f->data[0]) { @@ -281,9 +278,9 @@ static int decode(MimicContext *ctx, int quality, int num_coeffs, const int is_chroma = !!plane; const int qscale = av_clip(10000 - quality, is_chroma ? 1000 : 2000, 10000) << 2; - const int stride = ctx->flipped_ptrs[ctx->cur_index ].linesize[plane]; - const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane]; - uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane]; + const int stride = ctx->frames[ctx->cur_index ].f->linesize[plane]; + const uint8_t *src = ctx->frames[ctx->prev_index].f->data[plane]; + uint8_t *dst = ctx->frames[ctx->cur_index ].f->data[plane]; for (y = 0; y < ctx->num_vblocks[plane]; y++) { for (x = 0; x < ctx->num_hblocks[plane]; x++) { @@ -306,13 +303,13 @@ static int decode(MimicContext *ctx, int quality, int num_coeffs, } else { unsigned int backref = get_bits(&ctx->gb, 4); int index = (ctx->cur_index + backref) & 15; - uint8_t *p = ctx->flipped_ptrs[index].data[0]; + uint8_t *p = ctx->frames[index].f->data[0]; if (index != ctx->cur_index && p) { ff_thread_await_progress(&ctx->frames[index], cur_row, 0); p += src - - ctx->flipped_ptrs[ctx->prev_index].data[plane]; + ctx->frames[ctx->prev_index].f->data[plane]; ctx->hdsp.put_pixels_tab[1][0](dst, p, stride, 8); } else { av_log(ctx->avctx, AV_LOG_ERROR, @@ -339,17 +336,18 @@ static int decode(MimicContext *ctx, int quality, int num_coeffs, } /** - * Flip the buffer upside-down and put it in the YVU order to match the + * Flip the buffer upside-down and put it in the YVU order to revert the * way Mimic encodes frames. */ -static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVFrame *src) +static void flip_swap_frame(AVFrame *f) { int i; - dst->data[0] = src->data[0] + ( ctx->avctx->height - 1) * src->linesize[0]; - dst->data[1] = src->data[2] + ((ctx->avctx->height >> 1) - 1) * src->linesize[2]; - dst->data[2] = src->data[1] + ((ctx->avctx->height >> 1) - 1) * src->linesize[1]; + uint8_t *data_1 = f->data[1]; + f->data[0] = f->data[0] + ( f->height - 1) * f->linesize[0]; + f->data[1] = f->data[2] + ((f->height >> 1) - 1) * f->linesize[2]; + f->data[2] = data_1 + ((f->height >> 1) - 1) * f->linesize[1]; for (i = 0; i < 3; i++) - dst->linesize[i] = -src->linesize[i]; + f->linesize[i] *= -1; } static int mimic_decode_frame(AVCodecContext *avctx, void *data, @@ -394,8 +392,8 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, avctx->height = height; avctx->pix_fmt = AV_PIX_FMT_YUV420P; for (i = 0; i < 3; i++) { - ctx->num_vblocks[i] = -((-height) >> (3 + !!i)); - ctx->num_hblocks[i] = width >> (3 + !!i); + ctx->num_vblocks[i] = AV_CEIL_RSHIFT(height, 3 + !!i); + ctx->num_hblocks[i] = width >> (3 + !!i); } } else if (width != ctx->avctx->width || height != ctx->avctx->height) { avpriv_request_sample(avctx, "Resolution changing"); @@ -419,9 +417,6 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, ctx->next_prev_index = ctx->cur_index; ctx->next_cur_index = (ctx->cur_index - 1) & 15; - prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index], - ctx->frames[ctx->cur_index].f); - ff_thread_finish_setup(avctx); av_fast_padded_malloc(&ctx->swap_buf, &ctx->swap_buf_size, swap_buf_size); @@ -436,22 +431,20 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, res = decode(ctx, quality, num_coeffs, !is_pframe); ff_thread_report_progress(&ctx->frames[ctx->cur_index], INT_MAX, 0); if (res < 0) { - if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); - return res; - } + return res; } if ((res = av_frame_ref(data, ctx->frames[ctx->cur_index].f)) < 0) return res; *got_frame = 1; + flip_swap_frame(data); + ctx->prev_index = ctx->next_prev_index; ctx->cur_index = ctx->next_cur_index; - /* Only release frames that aren't used for backreferences anymore */ - ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); - return buf_size; } @@ -480,7 +473,7 @@ AVCodec ff_mimic_decoder = { .init = mimic_decode_init, .close = mimic_decode_end, .decode = mimic_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context), .init_thread_copy = ONLY_IF_THREADS_ENABLED(mimic_init_thread_copy), }; diff --git a/libavcodec/mips/mathops.h b/libavcodec/mips/mathops.h index dd80f68..573d325 100644 --- a/libavcodec/mips/mathops.h +++ b/libavcodec/mips/mathops.h @@ -28,13 +28,16 @@ #if HAVE_INLINE_ASM #if HAVE_LOONGSON +#if ARCH_MIPS64 static inline av_const int64_t MAC64(int64_t d, int a, int b) { int64_t m; - __asm__ ("dmult.g %1, %2, %3 \n\t" - "daddu %0, %0, %1 \n\t" - : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); + __asm__ ("dmult %2, %3 \n\t" + "mflo %1 \n\t" + "daddu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b) + : "hi", "lo"); return d; } #define MAC64(d, a, b) ((d) = MAC64(d, a, b)) @@ -42,23 +45,23 @@ static inline av_const int64_t MAC64(int64_t d, int a, int b) static inline av_const int64_t MLS64(int64_t d, int a, int b) { int64_t m; - __asm__ ("dmult.g %1, %2, %3 \n\t" - "dsubu %0, %0, %1 \n\t" - : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); + __asm__ ("dmult %2, %3 \n\t" + "mflo %1 \n\t" + "dsubu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b) + : "hi", "lo"); return d; } #define MLS64(d, a, b) ((d) = MLS64(d, a, b)) -#elif ARCH_MIPS64 +#else static inline av_const int64_t MAC64(int64_t d, int a, int b) { int64_t m; - __asm__ ("dmult %2, %3 \n\t" - "mflo %1 \n\t" - "daddu %0, %0, %1 \n\t" - : "+r"(d), "=&r"(m) : "r"(a), "r"(b) - : "hi", "lo"); + __asm__ ("dmult.g %1, %2, %3 \n\t" + "daddu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); return d; } #define MAC64(d, a, b) ((d) = MAC64(d, a, b)) @@ -66,17 +69,17 @@ static inline av_const int64_t MAC64(int64_t d, int a, int b) static inline av_const int64_t MLS64(int64_t d, int a, int b) { int64_t m; - __asm__ ("dmult %2, %3 \n\t" - "mflo %1 \n\t" - "dsubu %0, %0, %1 \n\t" - : "+r"(d), "=&r"(m) : "r"(a), "r"(b) - : "hi", "lo"); + __asm__ ("dmult.g %1, %2, %3 \n\t" + "dsubu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); return d; } #define MLS64(d, a, b) ((d) = MLS64(d, a, b)) #endif +#endif /* HAVE_LOONGSON */ + #endif /* HAVE_INLINE_ASM */ #endif /* AVCODEC_MIPS_MATHOPS_H */ diff --git a/libavcodec/mjpeg.h b/libavcodec/mjpeg.h index bd3b1e8..1ebe283 100644 --- a/libavcodec/mjpeg.h +++ b/libavcodec/mjpeg.h @@ -33,13 +33,8 @@ #ifndef AVCODEC_MJPEG_H #define AVCODEC_MJPEG_H -#include "libavutil/internal.h" - -#include "avcodec.h" -#include "put_bits.h" - /* JPEG marker codes */ -typedef enum { +enum JpegMarker { /* start of frame */ SOF0 = 0xc0, /* baseline */ SOF1 = 0xc1, /* extended sequential, huffman */ @@ -118,13 +113,7 @@ typedef enum { TEM = 0x01, /* temporary private use for arithmetic coding */ /* 0x02 -> 0xbf reserved */ -} JPEG_MARKER; - -static inline void put_marker(PutBitContext *p, int code) -{ - put_bits(p, 8, 0xff); - put_bits(p, 8, code); -} +}; #define PREDICT(ret, topleft, top, left, predictor)\ switch(predictor){\ @@ -138,19 +127,4 @@ static inline void put_marker(PutBitContext *p, int code) case 7: ret= (left + top)>>1; break;\ } -extern av_export const uint8_t avpriv_mjpeg_bits_dc_luminance[]; -extern av_export const uint8_t avpriv_mjpeg_val_dc[]; - -extern av_export const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; - -extern av_export const uint8_t avpriv_mjpeg_bits_ac_luminance[]; -extern av_export const uint8_t avpriv_mjpeg_val_ac_luminance[]; - -extern av_export const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; -extern av_export const uint8_t avpriv_mjpeg_val_ac_chrominance[]; - -void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, - const uint8_t *bits_table, - const uint8_t *val_table); - #endif /* AVCODEC_MJPEG_H */ diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index 59734c9..eec3469 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -30,7 +30,8 @@ #include "libavutil/mem.h" #include "avcodec.h" -#include "mjpeg.h" +#include "bsf.h" +#include "jpegtables.h" static const uint8_t jpeg_header[] = { 0xff, 0xd8, // SOI @@ -75,42 +76,56 @@ static uint8_t *append_dht_segment(uint8_t *buf) return buf; } -static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc, - AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int keyframe) +static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out) { + AVPacket *in; + int ret = 0; int input_skip, output_size; - uint8_t *output, *out; + uint8_t *output; - if (buf_size < 12) { - av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); - return AVERROR_INVALIDDATA; + ret = ff_bsf_get_packet(ctx, &in); + + if (in->size < 12) { + av_log(ctx, AV_LOG_ERROR, "input is truncated\n"); + ret = AVERROR_INVALIDDATA; + goto fail; } - if (memcmp("AVI1", buf + 6, 4)) { - av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n"); - return AVERROR_INVALIDDATA; + if (memcmp("AVI1", in->data + 6, 4)) { + av_log(ctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n"); + ret = AVERROR_INVALIDDATA; + goto fail; } - input_skip = (buf[4] << 8) + buf[5] + 4; - if (buf_size < input_skip) { - av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); - return AVERROR_INVALIDDATA; + + input_skip = (in->data[4] << 8) + in->data[5] + 4; + if (in->size < input_skip) { + av_log(ctx, AV_LOG_ERROR, "input is truncated\n"); + ret = AVERROR_INVALIDDATA; + goto fail; } - output_size = buf_size - input_skip + + output_size = in->size - input_skip + sizeof(jpeg_header) + dht_segment_size; - output = out = av_malloc(output_size); - if (!output) - return AVERROR(ENOMEM); - out = append(out, jpeg_header, sizeof(jpeg_header)); - out = append_dht_segment(out); - out = append(out, buf + input_skip, buf_size - input_skip); - *poutbuf = output; - *poutbuf_size = output_size; - return 1; + ret = av_new_packet(out, output_size); + if (ret < 0) + goto fail; + + output = out->data; + + output = append(output, jpeg_header, sizeof(jpeg_header)); + output = append_dht_segment(output); + output = append(output, in->data + input_skip, in->size - input_skip); + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; } -AVBitStreamFilter ff_mjpeg2jpeg_bsf = { +const AVBitStreamFilter ff_mjpeg2jpeg_bsf = { .name = "mjpeg2jpeg", .filter = mjpeg2jpeg_filter, }; diff --git a/libavcodec/mjpega_dump_header_bsf.c b/libavcodec/mjpega_dump_header_bsf.c index ed32d5a..b3ce26a 100644 --- a/libavcodec/mjpega_dump_header_bsf.c +++ b/libavcodec/mjpega_dump_header_bsf.c @@ -26,69 +26,83 @@ */ #include "avcodec.h" +#include "bsf.h" #include "bytestream.h" #include "mjpeg.h" -static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe) +static int mjpega_dump_header(AVBSFContext *ctx, AVPacket *out) { - uint8_t *poutbufp; + AVPacket *in; + uint8_t *out_buf; unsigned dqt = 0, dht = 0, sof0 = 0; - int i; + int ret = 0, i; - if (avctx->codec_id != AV_CODEC_ID_MJPEG) { - av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n"); - return 0; - } + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + ret = av_new_packet(out, in->size + 44); + if (ret < 0) + goto fail; + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; - *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 */ + out_buf = out->data; + bytestream_put_byte(&out_buf, 0xff); + bytestream_put_byte(&out_buf, SOI); + bytestream_put_byte(&out_buf, 0xff); + bytestream_put_byte(&out_buf, APP1); + bytestream_put_be16(&out_buf, 42); /* size */ + bytestream_put_be32(&out_buf, 0); + bytestream_put_buffer(&out_buf, "mjpg", 4); + bytestream_put_be32(&out_buf, in->size + 44); /* field size */ + bytestream_put_be32(&out_buf, in->size + 44); /* pad field size */ + bytestream_put_be32(&out_buf, 0); /* next ptr */ - for (i = 0; i < buf_size - 1; i++) { - if (buf[i] == 0xff) { - switch (buf[i + 1]) { + for (i = 0; i < in->size - 1; i++) { + if (in->data[i] == 0xff) { + switch (in->data[i + 1]) { case DQT: dqt = i + 46; break; case DHT: dht = i + 46; break; case SOF0: sof0 = i + 46; break; case SOS: - bytestream_put_be32(&poutbufp, dqt); /* quant off */ - bytestream_put_be32(&poutbufp, dht); /* huff off */ - bytestream_put_be32(&poutbufp, sof0); /* image off */ - bytestream_put_be32(&poutbufp, i + 46); /* scan off */ - bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */ - bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */ - *poutbuf_size = poutbufp - *poutbuf; - return 1; + bytestream_put_be32(&out_buf, dqt); /* quant off */ + bytestream_put_be32(&out_buf, dht); /* huff off */ + bytestream_put_be32(&out_buf, sof0); /* image off */ + bytestream_put_be32(&out_buf, i + 46); /* scan off */ + bytestream_put_be32(&out_buf, i + 46 + AV_RB16(in->data + i + 2)); /* data off */ + bytestream_put_buffer(&out_buf, in->data + 2, in->size - 2); /* skip already written SOI */ + + out->size = out_buf - out->data; + av_packet_free(&in); + return 0; case APP1: - if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) { - av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n"); - memcpy(*poutbuf, buf, buf_size); - *poutbuf_size = buf_size; - return 1; + if (i + 8 < in->size && AV_RL32(in->data + i + 8) == AV_RL32("mjpg")) { + av_log(ctx, AV_LOG_ERROR, "bitstream already formatted\n"); + av_packet_unref(out); + av_packet_move_ref(out, in); + av_packet_free(&in); + return 0; } } } } - av_freep(poutbuf); - av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); - return 0; + av_log(ctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); +fail: + av_packet_unref(out); + av_packet_free(&in); + return AVERROR_INVALIDDATA; } -AVBitStreamFilter ff_mjpega_dump_header_bsf = { - "mjpegadump", - 0, - mjpega_dump_header, +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_mjpega_dump_header_bsf = { + .name = "mjpegadump", + .filter = mjpega_dump_header, + .codec_ids = codec_ids, }; diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index 66cf2d4..3775aa3 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -27,6 +27,7 @@ #include #include "avcodec.h" +#include "internal.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -160,5 +161,6 @@ AVCodec ff_mjpegb_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = mjpegb_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 9118df6..221153d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -38,9 +38,11 @@ #include "blockdsp.h" #include "idctdsp.h" #include "internal.h" +#include "jpegtables.h" #include "mjpeg.h" #include "mjpegdec.h" #include "jpeglsdec.h" +#include "put_bits.h" static int build_vlc(VLC *vlc, const uint8_t *bits_table, @@ -138,9 +140,9 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s) len = get_bits(&s->gb, 16) - 2; while (len >= 65) { - /* only 8 bit precision handled */ + /* only 8-bit precision handled */ if (get_bits(&s->gb, 4) != 0) { - av_log(s->avctx, AV_LOG_ERROR, "dqt: 16bit precision\n"); + av_log(s->avctx, AV_LOG_ERROR, "dqt: 16-bit precision\n"); return -1; } index = get_bits(&s->gb, 4); @@ -153,7 +155,7 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s) s->quant_matrixes[index][j] = get_bits(&s->gb, 8); } - // XXX FIXME finetune, and perhaps add dc too + // XXX FIXME fine-tune, and perhaps add dc too s->qscale[index] = FFMAX(s->quant_matrixes[index][s->scantable.permutated[1]], s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1; av_log(s->avctx, AV_LOG_DEBUG, "qscale[%d]: %d\n", @@ -401,7 +403,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) for (i = 0; i < 3; i++) s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced; - av_dlog(s->avctx, "%d %d %d %d %d %d\n", + ff_dlog(s->avctx, "%d %d %d %d %d %d\n", s->width, s->height, s->linesize[0], s->linesize[1], s->interlaced, s->avctx->height); @@ -914,8 +916,8 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, return AVERROR_INVALIDDATA; } } - av_dlog(s->avctx, "mb: %d %d processed\n", mb_y, mb_x); - av_dlog(s->avctx, "%d %d %d %d %d %d %d %d \n", + ff_dlog(s->avctx, "mb: %d %d processed\n", mb_y, mb_x); + ff_dlog(s->avctx, "%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8); if (++x == h) { @@ -970,7 +972,9 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height); if (!Al) { - s->coefs_finished[c] |= (1LL << (se + 1)) - (1LL << ss); + // s->coefs_finished is a bitmask for coefficients coded + // ss and se are parameters telling start and end coefficients + s->coefs_finished[c] |= (~0ULL >> (63 - (se - ss))) << ss; last_scan = !~s->coefs_finished[c]; } @@ -1103,6 +1107,12 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, for (i = s->mjpb_skiptosod; i > 0; i--) skip_bits(&s->gb, 8); + if (s->lossless && s->rgb && nb_components != 3) { + avpriv_request_sample(s->avctx, + "Lossless RGB image without 3 components"); + return AVERROR_PATCHWELCOME; + } + next_field: for (i = 0; i < nb_components; i++) s->last_dc[i] = 1024; @@ -1149,7 +1159,7 @@ next_field: GetBitContext bak = s->gb; align_get_bits(&bak); if (show_bits(&bak, 16) == 0xFFD1) { - av_dlog(s->avctx, "AVRn interlaced picture marker found\n"); + ff_dlog(s->avctx, "AVRn interlaced picture marker found\n"); s->gb = bak; skip_bits(&s->gb, 16); s->bottom_field ^= 1; @@ -1211,17 +1221,9 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) s->bottom_field = 1; else if (i == 1) s->bottom_field = 0; -#if 0 - skip_bits(&s->gb, 8); - skip_bits(&s->gb, 32); - skip_bits(&s->gb, 32); - len -= 10; -#endif goto out; } -// len -= 2; - if (id == AV_RL32("JFIF")) { int t_w, t_h, v1, v2; skip_bits(&s->gb, 8); /* the trailing zero-byte */ @@ -1267,9 +1269,9 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) 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? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ switch (get_bits(&s->gb, 8)) { case 1: s->rgb = 1; @@ -1293,16 +1295,6 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) len -= 4; /* Apple MJPEG-A */ if (id == AV_RL32("mjpg")) { -#if 0 - skip_bits(&s->gb, 32); /* field size */ - skip_bits(&s->gb, 32); /* pad field size */ - skip_bits(&s->gb, 32); /* next off */ - skip_bits(&s->gb, 32); /* quant off */ - skip_bits(&s->gb, 32); /* huff off */ - skip_bits(&s->gb, 32); /* image off */ - skip_bits(&s->gb, 32); /* scan off */ - skip_bits(&s->gb, 32); /* data off */ -#endif if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n"); } @@ -1323,30 +1315,31 @@ static int mjpeg_decode_com(MJpegDecodeContext *s) { int len = get_bits(&s->gb, 16); if (len >= 2 && 8 * len - 16 <= get_bits_left(&s->gb)) { + int i; 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 (!cbuf) + return AVERROR(ENOMEM); - 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; - } else if (!strcmp(cbuf, "CS=ITU601")) - s->cs_itu601 = 1; - else if ((len > 20 && !strncmp(cbuf, "Intel(R) JPEG Library", 21)) || - (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20))) - s->flipped = 1; - - av_free(cbuf); - } + 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; + } else if (!strcmp(cbuf, "CS=ITU601")) + s->cs_itu601 = 1; + else if ((len > 20 && !strncmp(cbuf, "Intel(R) JPEG Library", 21)) || + (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20))) + s->flipped = 1; + + av_free(cbuf); } return 0; @@ -1377,7 +1370,7 @@ static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end) } val = -1; found: - av_dlog(NULL, "find_marker skipped %d bytes\n", skipped); + ff_dlog(NULL, "find_marker skipped %d bytes\n", skipped); *pbuf_ptr = buf_ptr; return val; } @@ -1418,7 +1411,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s, *unescaped_buf_ptr = s->buffer; *unescaped_buf_size = dst - s->buffer; memset(s->buffer + *unescaped_buf_size, 0, - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", (buf_end - *buf_ptr) - (dst - s->buffer)); @@ -1461,7 +1454,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s, *unescaped_buf_ptr = dst; *unescaped_buf_size = (bit_count + 7) >> 3; memset(s->buffer + *unescaped_buf_size, 0, - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); } else { *unescaped_buf_ptr = *buf_ptr; *unescaped_buf_size = buf_end - *buf_ptr; @@ -1521,8 +1514,11 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, else if (start_code >= APP0 && start_code <= APP15) mjpeg_decode_app(s); /* Comment */ - else if (start_code == COM) - mjpeg_decode_com(s); + else if (start_code == COM) { + ret = mjpeg_decode_com(s); + if (ret < 0) + return ret; + } if (!CONFIG_JPEGLS_DECODER && (start_code == SOF48 || start_code == LSE)) { @@ -1719,8 +1715,9 @@ AVCodec ff_mjpeg_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = ff_mjpeg_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .priv_class = &mjpegdec_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; AVCodec ff_thp_decoder = { @@ -1732,5 +1729,6 @@ AVCodec ff_thp_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = ff_mjpeg_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index aa4703a..b80a47b 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -68,7 +68,7 @@ typedef struct MJpegDecodeContext { int maxval; int near; ///< near lossless bound (si 0 for lossless) int t1,t2,t3; - int reset; ///< context halfing intervall ?rename + int reset; ///< context halfing interval ?rename int width, height; int mb_width, mb_height; diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 8ac5cfe..8291113 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -30,11 +30,10 @@ * MJPEG encoder. */ -#include - #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "jpegtables.h" #include "mjpegenc_common.h" #include "mpegvideo.h" #include "mjpeg.h" @@ -136,7 +135,7 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); } -void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]) +void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[8][64]) { int i; for(i=0;i<5;i++) { @@ -153,12 +152,31 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]) s->i_tex_bits += get_bits_diff(s); } +#define OFFSET(x) offsetof(MpegEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, + { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, + + { NULL}, +}; + +static const AVClass mjpeg_class = { + .class_name = "mjpeg", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_mjpeg_encoder = { .name = "mjpeg", .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MJPEG, .priv_data_size = sizeof(MpegEncContext), + .priv_class = &mjpeg_class, .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 6054db1..bbb0f0e 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -35,10 +35,12 @@ #include +#include "mjpeg.h" #include "mpegvideo.h" +#include "put_bits.h" typedef struct MJpegContext { - uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chrom, for easier addressing + uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chroma, for easier addressing uint16_t huff_code_dc_luminance[12]; uint8_t huff_size_dc_chrominance[12]; uint16_t huff_code_dc_chrominance[12]; @@ -49,8 +51,14 @@ typedef struct MJpegContext { uint16_t huff_code_ac_chrominance[256]; } MJpegContext; +static inline void put_marker(PutBitContext *p, enum JpegMarker code) +{ + put_bits(p, 8, 0xff); + put_bits(p, 8, code); +} + int ff_mjpeg_encode_init(MpegEncContext *s); void ff_mjpeg_encode_close(MpegEncContext *s); -void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]); +void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[8][64]); #endif /* AVCODEC_MJPEGENC_H */ diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 9373e4a..2262de6 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -27,7 +27,9 @@ #include "avcodec.h" #include "idctdsp.h" +#include "jpegtables.h" #include "put_bits.h" +#include "mjpegenc.h" #include "mjpegenc_common.h" #include "mjpeg.h" @@ -108,7 +110,7 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) } /* comment */ - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { put_marker(p, COM); flush_put_bits(p); ptr = put_bits_ptr(p); @@ -132,7 +134,7 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) } void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, - ScanTable *intra_scantable, + ScanTable *intra_scantable, int pred, uint16_t intra_matrix[64]) { int chroma_h_shift, chroma_v_shift; @@ -215,7 +217,7 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, put_bits(pb, 4, 1); /* DC huffman table index */ put_bits(pb, 4, lossless ? 0 : 1); /* AC huffman table index */ - put_bits(pb, 8, lossless ? avctx->prediction_method + 1 : 0); /* Ss (not used) */ + put_bits(pb, 8, lossless ? pred : 0); /* Ss (not used) */ switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_bits(pb, 8, 63); break; /* Se (not used) */ diff --git a/libavcodec/mjpegenc_common.h b/libavcodec/mjpegenc_common.h index b48911e..9b5933e 100644 --- a/libavcodec/mjpegenc_common.h +++ b/libavcodec/mjpegenc_common.h @@ -28,7 +28,7 @@ #include "put_bits.h" void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, - ScanTable *intra_scantable, + ScanTable *intra_scantable, int pred, uint16_t intra_matrix[64]); void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits); void ff_mjpeg_encode_stuffing(PutBitContext *pbc); diff --git a/libavcodec/mlp.h b/libavcodec/mlp.h index 5a4ee5f..8a1584e 100644 --- a/libavcodec/mlp.h +++ b/libavcodec/mlp.h @@ -45,7 +45,7 @@ /** Maximum number of substreams that can be decoded. * MLP's limit is 2. TrueHD supports at least up to 3. */ -#define MAX_SUBSTREAMS 3 +#define MAX_SUBSTREAMS 4 /** which multiple of 48000 the maximum sample rate is */ #define MAX_RATEFACTOR 4 diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 075227f..e8fb4f5 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -119,6 +119,23 @@ static uint64_t truehd_layout(int chanmap) return layout; } +static int ff_mlp_get_major_sync_size(const uint8_t * buf, int bufsize) +{ + int has_extension, extensions = 0; + int size = 28; + if (bufsize < 28) + return -1; + + if (AV_RB32(buf) == 0xf8726fba) { + has_extension = buf[25] & 1; + if (has_extension) { + extensions = buf[26] >> 4; + size += 2 + extensions * 2; + } + } + return size; +} + /** Read a major sync info header - contains high level information about * the stream - sample rate, channel arrangement etc. Most of this * information is not actually necessary for decoding, only for playback. @@ -127,18 +144,19 @@ static uint64_t truehd_layout(int chanmap) int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) { - int ratebits, channel_arrangement; + int ratebits, channel_arrangement, header_size; uint16_t checksum; assert(get_bits_count(gb) == 0); - if (gb->size_in_bits < 28 << 3) { + header_size = ff_mlp_get_major_sync_size(gb->buffer, gb->size_in_bits >> 3); + if (header_size < 0 || gb->size_in_bits < header_size << 3) { av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n"); return -1; } - checksum = ff_mlp_checksum16(gb->buffer, 26); - if (checksum != AV_RL16(gb->buffer+26)) { + checksum = ff_mlp_checksum16(gb->buffer, header_size - 2); + if (checksum != AV_RL16(gb->buffer+header_size-2)) { av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); return AVERROR_INVALIDDATA; } @@ -147,6 +165,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) return AVERROR_INVALIDDATA; mh->stream_type = get_bits(gb, 8); + mh->header_size = header_size; if (mh->stream_type == 0xbb) { mh->group1_bits = mlp_quants[get_bits(gb, 4)]; @@ -197,7 +216,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) mh->num_substreams = get_bits(gb, 4); - skip_bits_long(gb, 4 + 11 * 8); + skip_bits_long(gb, 4 + (header_size - 17) * 8); return 0; } @@ -326,15 +345,6 @@ static int mlp_parse(AVCodecParserContext *s, if (mh.stream_type == 0xbb) { /* MLP stream */ -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->request_channels > 0 && avctx->request_channels <= 2 && - mh.num_substreams > 1) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - } else -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (avctx->request_channel_layout && (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == avctx->request_channel_layout && @@ -347,19 +357,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->request_channels > 0 && avctx->request_channels <= 2 && - mh.num_substreams > 1) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - } else if (avctx->request_channels > 0 && - avctx->request_channels <= mh.channels_thd_stream1) { - avctx->channels = mh.channels_thd_stream1; - avctx->channel_layout = mh.channel_layout_thd_stream1; - } else -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (avctx->request_channel_layout && (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == avctx->request_channel_layout && diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h index 7530fac..8a2ae13 100644 --- a/libavcodec/mlp_parser.h +++ b/libavcodec/mlp_parser.h @@ -32,6 +32,7 @@ typedef struct MLPHeaderInfo { int stream_type; ///< 0xBB for MLP, 0xBA for TrueHD + int header_size; ///< Size of the major sync header, in bytes int group1_bits; ///< The bit depth of the first substream int group2_bits; ///< Bit depth of the second substream (MLP only) @@ -39,9 +40,9 @@ typedef struct MLPHeaderInfo int group1_samplerate; ///< Sample rate of first substream int group2_samplerate; ///< Sample rate of second substream (MLP only) - int channel_modifier_thd_stream0; ///< Channel modifier for substream 0 of TrueHD sreams ("2-channel presentation") - int channel_modifier_thd_stream1; ///< Channel modifier for substream 1 of TrueHD sreams ("6-channel presentation") - int channel_modifier_thd_stream2; ///< Channel modifier for substream 2 of TrueHD sreams ("8-channel presentation") + int channel_modifier_thd_stream0; ///< Channel modifier for substream 0 of TrueHD streams ("2-channel presentation") + int channel_modifier_thd_stream1; ///< Channel modifier for substream 1 of TrueHD streams ("6-channel presentation") + int channel_modifier_thd_stream2; ///< Channel modifier for substream 2 of TrueHD streams ("8-channel presentation") int channels_mlp; ///< Channel count for MLP streams int channels_thd_stream1; ///< Channel count for substream 1 of TrueHD streams ("6-channel presentation") diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 6baf4c1..8cfeea6 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -132,6 +132,9 @@ typedef struct MLPDecodeContext { /// Current access unit being read has a major sync. int is_major_sync_unit; + /// Size of the major sync unit, in bytes + int major_sync_header_size; + /// Set if a valid major sync block has been read. Otherwise no decoding is possible. uint8_t params_valid; @@ -346,11 +349,15 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) return AVERROR_PATCHWELCOME; } + m->major_sync_header_size = mh.header_size; + m->access_unit_size = mh.access_unit_size; m->access_unit_size_pow2 = mh.access_unit_size_pow2; m->num_substreams = mh.num_substreams; - m->max_decoded_substream = m->num_substreams - 1; + + /* limit to decoding 3 substreams, as the 4th is used by Dolby Atmos for non-audio data */ + m->max_decoded_substream = FFMIN(m->num_substreams - 1, 2); m->avctx->sample_rate = mh.group1_samplerate; m->avctx->frame_size = mh.access_unit_size; @@ -502,19 +509,6 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, s->max_channel = max_channel; s->max_matrix_channel = max_matrix_channel; -#if FF_API_REQUEST_CHANNELS -FF_DISABLE_DEPRECATION_WARNINGS - if (m->avctx->request_channels > 0 && - m->avctx->request_channels <= s->max_channel + 1 && - m->max_decoded_substream > substr) { - av_log(m->avctx, AV_LOG_DEBUG, - "Extracting %d-channel downmix from substream %d. " - "Further substreams will be skipped.\n", - s->max_channel + 1, substr); - m->max_decoded_substream = substr; - } else -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (m->avctx->request_channel_layout && (s->ch_layout & m->avctx->request_channel_layout) == m->avctx->request_channel_layout && m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, @@ -552,7 +546,7 @@ FF_ENABLE_DEPRECATION_WARNINGS ch_assign = av_get_channel_layout_channel_index(s->ch_layout, channel); } - if (ch_assign > s->max_matrix_channel) { + if (ch_assign < 0 || ch_assign > s->max_matrix_channel) { avpriv_request_sample(m->avctx, "Assignment of matrix channel %d to invalid output channel %d", ch, ch_assign); @@ -584,7 +578,7 @@ FF_ENABLE_DEPRECATION_WARNINGS /* Default audio coding is 24-bit raw PCM. */ cp->huff_offset = 0; - cp->sign_huff_offset = (-1) << 23; + cp->sign_huff_offset = -(1 << 23); cp->codebook = 0; cp->huff_lsbs = 24; } @@ -1105,7 +1099,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, if (read_major_sync(m, &gb) < 0) goto error; m->is_major_sync_unit = 1; - header_size += 28; + header_size += m->major_sync_header_size; } if (!m->params_valid) { @@ -1278,7 +1272,7 @@ AVCodec ff_mlp_decoder = { .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #if CONFIG_TRUEHD_DECODER @@ -1290,6 +1284,6 @@ AVCodec ff_truehd_decoder = { .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif /* CONFIG_TRUEHD_DECODER */ diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c new file mode 100644 index 0000000..69258a2 --- /dev/null +++ b/libavcodec/mmaldec.c @@ -0,0 +1,845 @@ +/* + * MMAL Video Decoder + * Copyright (c) 2015 Rodger Combs + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * MMAL Video Decoder + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/atomic.h" +#include "libavutil/avassert.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/log.h" + +typedef struct FFBufferEntry { + AVBufferRef *ref; + void *data; + size_t length; + int64_t pts, dts; + int flags; + struct FFBufferEntry *next; +} FFBufferEntry; + +// MMAL_POOL_T destroys all of its MMAL_BUFFER_HEADER_Ts. If we want correct +// refcounting for AVFrames, we can free the MMAL_POOL_T only after all AVFrames +// have been unreferenced. +typedef struct FFPoolRef { + volatile int refcount; + MMAL_POOL_T *pool; +} FFPoolRef; + +typedef struct FFBufferRef { + MMAL_BUFFER_HEADER_T *buffer; + FFPoolRef *pool; +} FFBufferRef; + +typedef struct MMALDecodeContext { + AVClass *av_class; + int extra_buffers; + int extra_decoder_buffers; + + MMAL_COMPONENT_T *decoder; + MMAL_QUEUE_T *queue_decoded_frames; + MMAL_POOL_T *pool_in; + FFPoolRef *pool_out; + + // Waiting input packets. Because the libavcodec API requires decoding and + // returning packets in lockstep, it can happen that queue_decoded_frames + // contains almost all surfaces - then the decoder input queue can quickly + // fill up and won't accept new input either. Without consuming input, the + // libavcodec API can't return new frames, and we have a logical deadlock. + // This is avoided by queuing such buffers here. + FFBufferEntry *waiting_buffers, *waiting_buffers_tail; + + int64_t packets_sent; + volatile int packets_buffered; + int64_t frames_output; + int eos_received; + int eos_sent; + int extradata_sent; +} MMALDecodeContext; + +// Assume decoder is guaranteed to produce output after at least this many +// packets (where each packet contains 1 frame). +#define MAX_DELAYED_FRAMES 16 + +static void ffmmal_poolref_unref(FFPoolRef *ref) +{ + if (ref && avpriv_atomic_int_add_and_fetch(&ref->refcount, -1) == 0) { + mmal_pool_destroy(ref->pool); + av_free(ref); + } +} + +static void ffmmal_release_frame(void *opaque, uint8_t *data) +{ + FFBufferRef *ref = (void *)data; + + mmal_buffer_header_release(ref->buffer); + ffmmal_poolref_unref(ref->pool); + + av_free(ref); +} + +// Setup frame with a new reference to buffer. The buffer must have been +// allocated from the given pool. +static int ffmmal_set_ref(AVFrame *frame, FFPoolRef *pool, + MMAL_BUFFER_HEADER_T *buffer) +{ + FFBufferRef *ref = av_mallocz(sizeof(*ref)); + if (!ref) + return AVERROR(ENOMEM); + + ref->pool = pool; + ref->buffer = buffer; + + frame->buf[0] = av_buffer_create((void *)ref, sizeof(*ref), + ffmmal_release_frame, NULL, + AV_BUFFER_FLAG_READONLY); + if (!frame->buf[0]) { + av_free(ref); + return AVERROR(ENOMEM); + } + + avpriv_atomic_int_add_and_fetch(&ref->pool->refcount, 1); + mmal_buffer_header_acquire(buffer); + + frame->format = AV_PIX_FMT_MMAL; + frame->data[3] = (uint8_t *)ref->buffer; + return 0; +} + +static void ffmmal_stop_decoder(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_COMPONENT_T *decoder = ctx->decoder; + MMAL_BUFFER_HEADER_T *buffer; + + mmal_port_disable(decoder->input[0]); + mmal_port_disable(decoder->output[0]); + mmal_port_disable(decoder->control); + + mmal_port_flush(decoder->input[0]); + mmal_port_flush(decoder->output[0]); + mmal_port_flush(decoder->control); + + while ((buffer = mmal_queue_get(ctx->queue_decoded_frames))) + mmal_buffer_header_release(buffer); + + while (ctx->waiting_buffers) { + FFBufferEntry *buffer = ctx->waiting_buffers; + + ctx->waiting_buffers = buffer->next; + + if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) + avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, -1); + + av_buffer_unref(&buffer->ref); + av_free(buffer); + } + ctx->waiting_buffers_tail = NULL; + + av_assert0(avpriv_atomic_int_get(&ctx->packets_buffered) == 0); + + ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = ctx->extradata_sent = 0; +} + +static av_cold int ffmmal_close_decoder(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + + if (ctx->decoder) + ffmmal_stop_decoder(avctx); + + mmal_component_destroy(ctx->decoder); + ctx->decoder = NULL; + mmal_queue_destroy(ctx->queue_decoded_frames); + mmal_pool_destroy(ctx->pool_in); + ffmmal_poolref_unref(ctx->pool_out); + + mmal_vc_deinit(); + + return 0; +} + +static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ + AVCodecContext *avctx = (AVCodecContext*)port->userdata; + MMALDecodeContext *ctx = avctx->priv_data; + + if (!buffer->cmd) { + FFBufferEntry *entry = buffer->user_data; + av_buffer_unref(&entry->ref); + if (entry->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) + avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, -1); + av_free(entry); + } + mmal_buffer_header_release(buffer); +} + +static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ + AVCodecContext *avctx = (AVCodecContext*)port->userdata; + MMALDecodeContext *ctx = avctx->priv_data; + + mmal_queue_put(ctx->queue_decoded_frames, buffer); +} + +static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ + AVCodecContext *avctx = (AVCodecContext*)port->userdata; + MMAL_STATUS_T status; + + if (buffer->cmd == MMAL_EVENT_ERROR) { + status = *(uint32_t *)buffer->data; + av_log(avctx, AV_LOG_ERROR, "MMAL error %d on control port\n", (int)status); + } else { + char s[20]; + av_get_codec_tag_string(s, sizeof(s), buffer->cmd); + av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on control port\n", s); + } + + mmal_buffer_header_release(buffer); +} + +// Feed free output buffers to the decoder. +static int ffmmal_fill_output_port(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_BUFFER_HEADER_T *buffer; + MMAL_STATUS_T status; + + if (!ctx->pool_out) + return AVERROR_UNKNOWN; // format change code failed with OOM previously + + while ((buffer = mmal_queue_get(ctx->pool_out->pool->queue))) { + if ((status = mmal_port_send_buffer(ctx->decoder->output[0], buffer))) { + mmal_buffer_header_release(buffer); + av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending output buffer.\n", (int)status); + return AVERROR_UNKNOWN; + } + } + + return 0; +} + +static enum AVColorSpace ffmmal_csp_to_av_csp(MMAL_FOURCC_T fourcc) +{ + switch (fourcc) { + case MMAL_COLOR_SPACE_BT470_2_BG: + case MMAL_COLOR_SPACE_BT470_2_M: + case MMAL_COLOR_SPACE_ITUR_BT601: return AVCOL_SPC_BT470BG; + case MMAL_COLOR_SPACE_ITUR_BT709: return AVCOL_SPC_BT709; + case MMAL_COLOR_SPACE_FCC: return AVCOL_SPC_FCC; + case MMAL_COLOR_SPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M; + default: return AVCOL_SPC_UNSPECIFIED; + } +} + +static int ffmal_update_format(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_STATUS_T status; + int ret = 0; + MMAL_COMPONENT_T *decoder = ctx->decoder; + MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; + + ffmmal_poolref_unref(ctx->pool_out); + if (!(ctx->pool_out = av_mallocz(sizeof(*ctx->pool_out)))) { + ret = AVERROR(ENOMEM); + goto fail; + } + ctx->pool_out->refcount = 1; + + if (!format_out) + goto fail; + + if ((status = mmal_port_parameter_set_uint32(decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS, ctx->extra_buffers))) + goto fail; + + if ((status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0))) + goto fail; + + if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { + format_out->encoding = MMAL_ENCODING_OPAQUE; + } else { + format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420; + } + + if ((status = mmal_port_format_commit(decoder->output[0]))) + goto fail; + + if ((ret = ff_set_dimensions(avctx, format_out->es->video.crop.x + format_out->es->video.crop.width, + format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0) + goto fail; + + if (format_out->es->video.par.num && format_out->es->video.par.den) { + avctx->sample_aspect_ratio.num = format_out->es->video.par.num; + avctx->sample_aspect_ratio.den = format_out->es->video.par.den; + } + + avctx->colorspace = ffmmal_csp_to_av_csp(format_out->es->video.color_space); + + decoder->output[0]->buffer_size = + FFMAX(decoder->output[0]->buffer_size_min, decoder->output[0]->buffer_size_recommended); + decoder->output[0]->buffer_num = + FFMAX(decoder->output[0]->buffer_num_min, decoder->output[0]->buffer_num_recommended) + ctx->extra_buffers; + ctx->pool_out->pool = mmal_pool_create(decoder->output[0]->buffer_num, + decoder->output[0]->buffer_size); + if (!ctx->pool_out->pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; + +fail: + return ret < 0 ? ret : AVERROR_UNKNOWN; +} + +static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_STATUS_T status; + MMAL_ES_FORMAT_T *format_in; + MMAL_COMPONENT_T *decoder; + char tmp[32]; + int ret = 0; + + bcm_host_init(); + + if (mmal_vc_init()) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); + return AVERROR(ENOSYS); + } + + if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) + return ret; + + avctx->pix_fmt = ret; + + if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) + goto fail; + + decoder = ctx->decoder; + + format_in = decoder->input[0]->format; + format_in->type = MMAL_ES_TYPE_VIDEO; + switch (avctx->codec_id) { + case AV_CODEC_ID_MPEG2VIDEO: + format_in->encoding = MMAL_ENCODING_MP2V; + break; + case AV_CODEC_ID_VC1: + format_in->encoding = MMAL_ENCODING_WVC1; + break; + case AV_CODEC_ID_H264: + default: + format_in->encoding = MMAL_ENCODING_H264; + break; + } + format_in->es->video.width = FFALIGN(avctx->width, 32); + format_in->es->video.height = FFALIGN(avctx->height, 16); + format_in->es->video.crop.width = avctx->width; + format_in->es->video.crop.height = avctx->height; + format_in->es->video.frame_rate.num = 24000; + format_in->es->video.frame_rate.den = 1001; + format_in->es->video.par.num = avctx->sample_aspect_ratio.num; + format_in->es->video.par.den = avctx->sample_aspect_ratio.den; + format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; + + av_get_codec_tag_string(tmp, sizeof(tmp), format_in->encoding); + av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", tmp); + +#if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS + if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS, + -1 - ctx->extra_decoder_buffers)) { + av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n"); + } +#endif + + if ((status = mmal_port_format_commit(decoder->input[0]))) + goto fail; + + decoder->input[0]->buffer_num = + FFMAX(decoder->input[0]->buffer_num_min, 20); + decoder->input[0]->buffer_size = + FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); + ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); + if (!ctx->pool_in) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if ((ret = ffmal_update_format(avctx)) < 0) + goto fail; + + ctx->queue_decoded_frames = mmal_queue_create(); + if (!ctx->queue_decoded_frames) + goto fail; + + decoder->input[0]->userdata = (void*)avctx; + decoder->output[0]->userdata = (void*)avctx; + decoder->control->userdata = (void*)avctx; + + if ((status = mmal_port_enable(decoder->control, control_port_cb))) + goto fail; + if ((status = mmal_port_enable(decoder->input[0], input_callback))) + goto fail; + if ((status = mmal_port_enable(decoder->output[0], output_callback))) + goto fail; + + if ((status = mmal_component_enable(decoder))) + goto fail; + + return 0; + +fail: + ffmmal_close_decoder(avctx); + return ret < 0 ? ret : AVERROR_UNKNOWN; +} + +static void ffmmal_flush(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_COMPONENT_T *decoder = ctx->decoder; + MMAL_STATUS_T status; + + ffmmal_stop_decoder(avctx); + + if ((status = mmal_port_enable(decoder->control, control_port_cb))) + goto fail; + if ((status = mmal_port_enable(decoder->input[0], input_callback))) + goto fail; + if ((status = mmal_port_enable(decoder->output[0], output_callback))) + goto fail; + + return; + +fail: + av_log(avctx, AV_LOG_ERROR, "MMAL flush error: %i\n", (int)status); +} + +// Split packets and add them to the waiting_buffers list. We don't queue them +// immediately, because it can happen that the decoder is temporarily blocked +// (due to us not reading/returning enough output buffers) and won't accept +// new input. (This wouldn't be an issue if MMAL input buffers always were +// complete frames - then the input buffer just would have to be big enough.) +// If is_extradata is set, send it as MMAL_BUFFER_HEADER_FLAG_CONFIG. +static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, + int is_extradata) +{ + MMALDecodeContext *ctx = avctx->priv_data; + AVBufferRef *buf = NULL; + int size = 0; + uint8_t *data = (uint8_t *)""; + uint8_t *start; + int ret = 0; + + if (avpkt->size) { + if (avpkt->buf) { + buf = av_buffer_ref(avpkt->buf); + size = avpkt->size; + data = avpkt->data; + } else { + buf = av_buffer_alloc(avpkt->size); + if (buf) { + memcpy(buf->data, avpkt->data, avpkt->size); + size = buf->size; + data = buf->data; + } + } + if (!buf) { + ret = AVERROR(ENOMEM); + goto done; + } + if (!is_extradata) + ctx->packets_sent++; + } else { + if (ctx->eos_sent) + goto done; + if (!ctx->packets_sent) { + // Short-cut the flush logic to avoid upsetting MMAL. + ctx->eos_sent = 1; + ctx->eos_received = 1; + goto done; + } + } + + start = data; + + do { + FFBufferEntry *buffer = av_mallocz(sizeof(*buffer)); + if (!buffer) { + ret = AVERROR(ENOMEM); + goto done; + } + + buffer->data = data; + buffer->length = FFMIN(size, ctx->decoder->input[0]->buffer_size); + + if (is_extradata) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG; + + if (data == start) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START; + + data += buffer->length; + size -= buffer->length; + + buffer->pts = avpkt->pts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->pts; + buffer->dts = avpkt->dts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->dts; + + if (!size) { + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; + avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, 1); + } + + if (!buffer->length) { + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS; + ctx->eos_sent = 1; + } + + if (buf) { + buffer->ref = av_buffer_ref(buf); + if (!buffer->ref) { + av_free(buffer); + ret = AVERROR(ENOMEM); + goto done; + } + } + + // Insert at end of the list + if (!ctx->waiting_buffers) + ctx->waiting_buffers = buffer; + if (ctx->waiting_buffers_tail) + ctx->waiting_buffers_tail->next = buffer; + ctx->waiting_buffers_tail = buffer; + } while (size); + +done: + av_buffer_unref(&buf); + return ret; +} + +// Move prepared/split packets from waiting_buffers to the MMAL decoder. +static int ffmmal_fill_input_port(AVCodecContext *avctx) +{ + MMALDecodeContext *ctx = avctx->priv_data; + + while (ctx->waiting_buffers) { + MMAL_BUFFER_HEADER_T *mbuffer; + FFBufferEntry *buffer; + MMAL_STATUS_T status; + + mbuffer = mmal_queue_get(ctx->pool_in->queue); + if (!mbuffer) + return 0; + + buffer = ctx->waiting_buffers; + + mmal_buffer_header_reset(mbuffer); + mbuffer->cmd = 0; + mbuffer->pts = buffer->pts; + mbuffer->dts = buffer->dts; + mbuffer->flags = buffer->flags; + mbuffer->data = buffer->data; + mbuffer->length = buffer->length; + mbuffer->user_data = buffer; + mbuffer->alloc_size = ctx->decoder->input[0]->buffer_size; + + // Remove from start of the list + ctx->waiting_buffers = buffer->next; + if (ctx->waiting_buffers_tail == buffer) + ctx->waiting_buffers_tail = NULL; + + if ((status = mmal_port_send_buffer(ctx->decoder->input[0], mbuffer))) { + mmal_buffer_header_release(mbuffer); + av_buffer_unref(&buffer->ref); + if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) + avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, -1); + av_free(buffer); + } + + if (status) { + av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending input\n", (int)status); + return AVERROR_UNKNOWN; + } + } + + return 0; +} + +static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, + MMAL_BUFFER_HEADER_T *buffer) +{ + MMALDecodeContext *ctx = avctx->priv_data; + int ret = 0; + + if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { + if (!ctx->pool_out) + return AVERROR_UNKNOWN; // format change code failed with OOM previously + + if ((ret = ff_decode_frame_props(avctx, frame)) < 0) + goto done; + + if ((ret = ffmmal_set_ref(frame, ctx->pool_out, buffer)) < 0) + goto done; + } else { + int w = FFALIGN(avctx->width, 32); + int h = FFALIGN(avctx->height, 16); + uint8_t *src[4]; + int linesize[4]; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + goto done; + + av_image_fill_arrays(src, linesize, + buffer->data + buffer->type->video.offset[0], + avctx->pix_fmt, w, h, 1); + av_image_copy(frame->data, frame->linesize, src, linesize, + avctx->pix_fmt, avctx->width, avctx->height); + } + + frame->pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts; +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pts = frame->pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->pkt_dts = AV_NOPTS_VALUE; + +done: + return ret; +} + +// Fetch a decoded buffer and place it into the frame parameter. +static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame) +{ + MMALDecodeContext *ctx = avctx->priv_data; + MMAL_BUFFER_HEADER_T *buffer = NULL; + MMAL_STATUS_T status = 0; + int ret = 0; + + if (ctx->eos_received) + goto done; + + while (1) { + // To ensure decoding in lockstep with a constant delay between fed packets + // and output frames, we always wait until an output buffer is available. + // Except during start we don't know after how many input packets the decoder + // is going to return the first buffer, and we can't distinguish decoder + // being busy from decoder waiting for input. So just poll at the start and + // keep feeding new data to the buffer. + // We are pretty sure the decoder will produce output if we sent more input + // frames than what a H.264 decoder could logically delay. This avoids too + // excessive buffering. + // We also wait if we sent eos, but didn't receive it yet (think of decoding + // stream with a very low number of frames). + if (avpriv_atomic_int_get(&ctx->packets_buffered) > MAX_DELAYED_FRAMES || + (ctx->packets_sent && ctx->eos_sent)) { + // MMAL will ignore broken input packets, which means the frame we + // expect here may never arrive. Dealing with this correctly is + // complicated, so here's a hack to avoid that it freezes forever + // in this unlikely situation. + buffer = mmal_queue_timedwait(ctx->queue_decoded_frames, 100); + if (!buffer) { + av_log(avctx, AV_LOG_ERROR, "Did not get output frame from MMAL.\n"); + ret = AVERROR_UNKNOWN; + goto done; + } + } else { + buffer = mmal_queue_get(ctx->queue_decoded_frames); + if (!buffer) + goto done; + } + + ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS); + if (ctx->eos_received) + goto done; + + if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { + MMAL_COMPONENT_T *decoder = ctx->decoder; + MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer); + MMAL_BUFFER_HEADER_T *stale_buffer; + + av_log(avctx, AV_LOG_INFO, "Changing output format.\n"); + + if ((status = mmal_port_disable(decoder->output[0]))) + goto done; + + while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames))) + mmal_buffer_header_release(stale_buffer); + + mmal_format_copy(decoder->output[0]->format, ev->format); + + if ((ret = ffmal_update_format(avctx)) < 0) + goto done; + + if ((status = mmal_port_enable(decoder->output[0], output_callback))) + goto done; + + if ((ret = ffmmal_fill_output_port(avctx)) < 0) + goto done; + + if ((ret = ffmmal_fill_input_port(avctx)) < 0) + goto done; + + mmal_buffer_header_release(buffer); + continue; + } else if (buffer->cmd) { + char s[20]; + av_get_codec_tag_string(s, sizeof(s), buffer->cmd); + av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", s); + goto done; + } else if (buffer->length == 0) { + // Unused output buffer that got drained after format change. + mmal_buffer_header_release(buffer); + continue; + } + + ctx->frames_output++; + + if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0) + goto done; + + *got_frame = 1; + break; + } + +done: + if (buffer) + mmal_buffer_header_release(buffer); + if (status && ret >= 0) + ret = AVERROR_UNKNOWN; + return ret; +} + +static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + MMALDecodeContext *ctx = avctx->priv_data; + AVFrame *frame = data; + int ret = 0; + + if (avctx->extradata_size && !ctx->extradata_sent) { + AVPacket pkt = {0}; + av_init_packet(&pkt); + pkt.data = avctx->extradata; + pkt.size = avctx->extradata_size; + ctx->extradata_sent = 1; + if ((ret = ffmmal_add_packet(avctx, &pkt, 1)) < 0) + return ret; + } + + if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) + return ret; + + if ((ret = ffmmal_fill_input_port(avctx)) < 0) + return ret; + + if ((ret = ffmmal_fill_output_port(avctx)) < 0) + return ret; + + if ((ret = ffmmal_read_frame(avctx, frame, got_frame)) < 0) + return ret; + + // ffmmal_read_frame() can block for a while. Since the decoder is + // asynchronous, it's a good idea to fill the ports again. + + if ((ret = ffmmal_fill_output_port(avctx)) < 0) + return ret; + + if ((ret = ffmmal_fill_input_port(avctx)) < 0) + return ret; + + return ret; +} + +AVHWAccel ff_h264_mmal_hwaccel = { + .name = "h264_mmal", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_MMAL, +}; + +AVHWAccel ff_mpeg2_mmal_hwaccel = { + .name = "mpeg2_mmal", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_MMAL, +}; + +AVHWAccel ff_vc1_mmal_hwaccel = { + .name = "vc1_mmal", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_MMAL, +}; + +static const AVOption options[]={ + {"extra_buffers", "extra buffers", offsetof(MMALDecodeContext, extra_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, + {"extra_decoder_buffers", "extra MMAL internal buffered frames", offsetof(MMALDecodeContext, extra_decoder_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, + {NULL} +}; + +#define FFMMAL_DEC_CLASS(NAME) \ + static const AVClass ffmmal_##NAME##_dec_class = { \ + .class_name = "mmal_" #NAME "_dec", \ + .option = options, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; + +#define FFMMAL_DEC(NAME, ID) \ + FFMMAL_DEC_CLASS(NAME) \ + AVCodec ff_##NAME##_mmal_decoder = { \ + .name = #NAME "_mmal", \ + .long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ + .type = AVMEDIA_TYPE_VIDEO, \ + .id = ID, \ + .priv_data_size = sizeof(MMALDecodeContext), \ + .init = ffmmal_init_decoder, \ + .close = ffmmal_close_decoder, \ + .decode = ffmmal_decode, \ + .flush = ffmmal_flush, \ + .priv_class = &ffmmal_##NAME##_dec_class, \ + .capabilities = AV_CODEC_CAP_DELAY, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ + AV_PIX_FMT_YUV420P, \ + AV_PIX_FMT_NONE}, \ + }; + +FFMMAL_DEC(h264, AV_CODEC_ID_H264) +FFMMAL_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO) +FFMMAL_DEC(vc1, AV_CODEC_ID_VC1) diff --git a/libavcodec/mmvideo.c b/libavcodec/mmvideo.c index 25124a3..0736630 100644 --- a/libavcodec/mmvideo.c +++ b/libavcodec/mmvideo.c @@ -99,7 +99,8 @@ static int mm_decode_intra(MmContext * s, int half_horiz, int half_vert) while (bytestream2_get_bytes_left(&s->gb) > 0) { int run_length, color; - if (y >= s->avctx->height) + // writes one more line when half_vert is true + if (y >= s->avctx->height + !!half_vert) return 0; color = bytestream2_get_byte(&s->gb); @@ -113,6 +114,9 @@ static int mm_decode_intra(MmContext * s, int half_horiz, int half_vert) if (half_horiz) run_length *=2; + if (s->avctx->width - x < run_length) + return AVERROR_INVALIDDATA; + if (color) { memset(s->frame->data[0] + y*s->frame->linesize[0] + x, color, run_length); if (half_vert) @@ -248,5 +252,5 @@ AVCodec ff_mmvideo_decoder = { .init = mm_decode_init, .close = mm_decode_end, .decode = mm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 21d2c04..1c0116c 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -32,7 +32,9 @@ #include #include "avcodec.h" +#include "internal.h" #include "mathops.h" +#include "motion_est.h" #include "mpegutils.h" #include "mpegvideo.h" @@ -100,7 +102,7 @@ static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3 } static int get_flags(MotionEstContext *c, int direct, int chroma){ - return ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0) + return ((c->avctx->flags&AV_CODEC_FLAG_QPEL) ? FLAG_QPEL : 0) + (direct ? FLAG_DIRECT : 0) + (chroma ? FLAG_CHROMA : 0); } @@ -200,7 +202,7 @@ static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int 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 + // FIXME x/y wrong, but MPEG-4 qpel is sick anyway, we should drop as much of it as possible in favor for H.264 } }else{ c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h); @@ -290,7 +292,7 @@ static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, #include "motion_est_template.c" static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b, - int stride, int h) + ptrdiff_t stride, int h) { return 0; } @@ -307,12 +309,25 @@ int ff_init_me(MpegEncContext *s){ av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n"); return -1; } - if (s->me_method != ME_ZERO && - s->me_method != ME_EPZS && - s->me_method != ME_X1) { - av_log(s->avctx, AV_LOG_ERROR, "me_method is only allowed to be set to zero and epzs; for hex,umh,full and others see dia_size\n"); - return -1; + +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS + if (s->motion_est == FF_ME_EPZS) { + if (s->me_method == ME_ZERO) + s->motion_est = FF_ME_ZERO; + else if (s->me_method == ME_EPZS) + s->motion_est = FF_ME_EPZS; + else if (s->me_method == ME_X1) + s->motion_est = FF_ME_XONE; + else { + av_log(s->avctx, AV_LOG_ERROR, + "me_method is only allowed to be set to zero and epzs; " + "for hex,umh,full and others see dia_size\n"); + return -1; + } } +FF_ENABLE_DEPRECATION_WARNINGS +#endif c->avctx= s->avctx; @@ -330,7 +345,7 @@ int ff_init_me(MpegEncContext *s){ 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){ + if (s->avctx->flags & AV_CODEC_FLAG_QPEL) { c->sub_motion_search= qpel_motion_search; c->qpel_avg = s->qdsp.avg_qpel_pixels_tab; if (s->no_rounding) @@ -532,7 +547,7 @@ static inline void get_limits(MpegEncContext *s, int x, int y) 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 + // Search range of H.261 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; @@ -861,7 +876,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, { MotionEstContext * const c= &s->me; uint8_t *pix, *ppix; - int sum, mx, my, dmin; + int sum, mx = 0, my = 0, dmin = 0; int varc; ///< the variance of the block (sum of squared (p[y][x]-average)) int vard; ///< sum of squared differences with the estimated motion vector int P[10][2]; @@ -893,52 +908,43 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8; c->mb_var_sum_temp += (varc+128)>>8; - switch(s->me_method) { - case ME_ZERO: - default: - mx = 0; - my = 0; - dmin = 0; - break; - case ME_X1: - case ME_EPZS: - { - const int mot_stride = s->b8_stride; - const int mot_xy = s->block_index[0]; - - P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0]; - P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1]; - - if(P_LEFT[0] > (c->xmax<xmax<first_slice_line) { - P_TOP[0] = s->current_picture.motion_val[0][mot_xy - mot_stride ][0]; - P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1]; - P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][0]; - P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][1]; - if(P_TOP[1] > (c->ymax<ymax<xmin<xmin< (c->ymax<ymax<motion_est != FF_ME_ZERO) { + const int mot_stride = s->b8_stride; + const int mot_xy = s->block_index[0]; - 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_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(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]; - } + 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 { /* MPEG-1 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 */ @@ -949,27 +955,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8; c->mc_mb_var_sum_temp += (vard+128)>>8; - if(mb_type){ - int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100); - int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; - c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); - - if(mb_type == CANDIDATE_MB_TYPE_INTER){ - c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); - set_p_mv_tables(s, mx, my, 1); - }else{ - mx <<=shift; - my <<=shift; - } - if(mb_type == CANDIDATE_MB_TYPE_INTER4V){ - h263_mv4_search(s, mx, my, shift); - - set_p_mv_tables(s, mx, my, 0); - } - if(mb_type == CANDIDATE_MB_TYPE_INTER_I){ - interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1); - } - }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){ + 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); @@ -987,7 +973,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, mx <<=shift; my <<=shift; } - if((s->flags&CODEC_FLAG_4MV) + if ((s->avctx->flags & AV_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; @@ -995,7 +981,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, set_p_mv_tables(s, mx, my, 0); }else set_p_mv_tables(s, mx, my, 1); - if((s->flags&CODEC_FLAG_INTERLACED_ME) + if ((s->avctx->flags & AV_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; @@ -1008,7 +994,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip) dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1); - if((s->flags&CODEC_FLAG_4MV) + if ((s->avctx->flags & AV_CODEC_FLAG_4MV) && !c->skip && varc>50<<8 && vard>10<<8){ int dmin4= h263_mv4_search(s, mx, my, shift); if(dmin4 < dmin){ @@ -1016,7 +1002,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, dmin=dmin4; } } - if((s->flags&CODEC_FLAG_INTERLACED_ME) + if ((s->avctx->flags & AV_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){ @@ -1118,7 +1104,7 @@ static int 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 mx = 0, my = 0, dmin = 0; int P[10][2]; const int shift= 1+s->quarter_sample; const int mot_stride = s->mb_stride; @@ -1133,15 +1119,7 @@ static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y, get_limits(s, 16*mb_x, 16*mb_y); - switch(s->me_method) { - case ME_ZERO: - default: - mx = 0; - my = 0; - dmin = 0; - break; - case ME_X1: - case ME_EPZS: + if (s->motion_est != FF_ME_ZERO) { P_LEFT[0] = mv_table[mot_xy - 1][0]; P_LEFT[1] = mv_table[mot_xy - 1][1]; @@ -1170,8 +1148,6 @@ static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y, } 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); @@ -1530,7 +1506,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, dmin= direct_search(s, mb_x, mb_y); else dmin= INT_MAX; -//FIXME penalty stuff for non mpeg4 +// FIXME penalty stuff for non-MPEG-4 c->skip=0; fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) + 3 * penalty_factor; @@ -1538,13 +1514,13 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, c->skip=0; bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) + 2 * penalty_factor; - av_dlog(s, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); + ff_dlog(s, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); c->skip=0; fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor; - av_dlog(s, "%d %d %d %d\n", dmin, fmin, bmin, fbmin); + ff_dlog(s, "%d %d %d %d\n", dmin, fmin, bmin, fbmin); - if(s->flags & CODEC_FLAG_INTERLACED_ME){ + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { //FIXME mb type penalty c->skip=0; c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV; @@ -1610,7 +1586,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, /* 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){ + if (s->motion_est != FF_ME_ZERO) { 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; @@ -1675,7 +1651,7 @@ void ff_fix_long_p_mvs(MpegEncContext * s) if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range; - if(s->flags&CODEC_FLAG_4MV){ + if (s->avctx->flags & AV_CODEC_FLAG_4MV) { const int wrap= s->b8_stride; /* clip / convert to intra 8x8 type MVs */ @@ -1708,7 +1684,6 @@ void ff_fix_long_p_mvs(MpegEncContext * s) } /** - * * @param truncate 1 for truncation, 0 for using intra */ void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select, diff --git a/libavcodec/motion_est.h b/libavcodec/motion_est.h new file mode 100644 index 0000000..3b63972 --- /dev/null +++ b/libavcodec/motion_est.h @@ -0,0 +1,130 @@ +/* + * Motion estimation + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MOTIONEST_H +#define AVCODEC_MOTIONEST_H + +#include + +#include "avcodec.h" +#include "hpeldsp.h" +#include "qpeldsp.h" + +struct MpegEncContext; + +#define MAX_MV 2048 +#define ME_MAP_SIZE 64 + +#define FF_ME_ZERO 0 +#define FF_ME_EPZS 1 +#define FF_ME_XONE 2 + +/** + * Motion estimation context. + */ +typedef struct MotionEstContext { + AVCodecContext *avctx; + int skip; ///< set if ME is skipped for the current MB + int co_located_mv[4][2]; ///< mv from last P-frame for direct mode ME + int direct_basis_mv[4][2]; + uint8_t *scratchpad; /**< data area for the ME algo, so that + * the ME does not need to malloc/free. */ + uint8_t *best_mb; + uint8_t *temp_mb[2]; + uint8_t *temp; + int best_bits; + uint32_t *map; ///< map to avoid duplicate evaluations + uint32_t *score_map; ///< map to store the scores + unsigned map_generation; + int pre_penalty_factor; + int penalty_factor; /**< an estimate of the bits required to + * code a given mv value, e.g. (1,0) takes + * more bits than (0,0). We have to + * estimate whether any reduction in + * residual is worth the extra bits. */ + int sub_penalty_factor; + int mb_penalty_factor; + int flags; + int sub_flags; + int mb_flags; + int pre_pass; ///< = 1 for the pre pass + int dia_size; + int xmin; + int xmax; + int ymin; + int ymax; + int pred_x; + int pred_y; + uint8_t *src[4][4]; + uint8_t *ref[4][4]; + int stride; + int uvstride; + /* temp variables for picture complexity calculation */ + int mc_mb_var_sum_temp; + int mb_var_sum_temp; + int scene_change_score; + + 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]; ///< bit amount 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; + +static inline int ff_h263_round_chroma(int x) +{ + //FIXME static or not? + static const uint8_t h263_chroma_roundtab[16] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, + }; + return h263_chroma_roundtab[x & 0xf] + (x >> 3); +} + +int ff_init_me(struct MpegEncContext *s); + +void ff_estimate_p_frame_motion(struct MpegEncContext *s, int mb_x, int mb_y); +void ff_estimate_b_frame_motion(struct MpegEncContext *s, int mb_x, int mb_y); + +int ff_pre_estimate_p_frame_motion(struct MpegEncContext *s, + int mb_x, int mb_y); + +int ff_epzs_motion_search(struct MpegEncContext *s, int *mx_ptr, int *my_ptr, + int P[10][2], int src_index, int ref_index, + int16_t (*last_mv)[2], int ref_mv_scale, int size, + int h); + +int ff_get_mb_score(struct MpegEncContext *s, int mx, int my, int src_index, + int ref_index, int size, int h, int add_rate); + +int ff_get_best_fcode(struct MpegEncContext *s, + int16_t (*mv_table)[2], int type); + +void ff_fix_long_p_mvs(struct MpegEncContext *s); +void ff_fix_long_mvs(struct MpegEncContext *s, uint8_t *field_select_table, + int field_select, int16_t (*mv_table)[2], int f_code, + int type, int truncate); + +#endif /* AVCODEC_MOTIONEST_H */ diff --git a/libavcodec/motion_est_template.c b/libavcodec/motion_est_template.c index 01936c6..c655e19 100644 --- a/libavcodec/motion_est_template.c +++ b/libavcodec/motion_est_template.c @@ -416,7 +416,7 @@ if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, const int shift= 1+qpel;\ static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -432,7 +432,7 @@ static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, { /* ensure that the best point is in the MAP as h/qpel refinement needs it */ const unsigned key = (best[1]<me; @@ -499,7 +499,7 @@ static int funny_diamond_search(MpegEncContext * s, int *best, int dmin, } static int hex_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags, int dia_size) { MotionEstContext * const c= &s->me; @@ -533,7 +533,7 @@ static int hex_search(MpegEncContext * s, int *best, int dmin, } static int l2s_dia_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -571,7 +571,7 @@ static int l2s_dia_search(MpegEncContext * s, int *best, int dmin, } static int umh_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -618,7 +618,7 @@ static int umh_search(MpegEncContext * s, int *best, int dmin, } static int full_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -681,7 +681,7 @@ static int full_search(MpegEncContext * s, int *best, int dmin, #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 src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -704,7 +704,8 @@ static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, 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; + if ((key & (-(1 << (2 * ME_MAP_MV_BITS)))) != map_generation) + continue; minima[j].height= score_map[i]; minima[j].x= key & ((1<>=ME_MAP_MV_BITS; @@ -758,7 +759,7 @@ static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, 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 + // ensure that the reference 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) @@ -768,7 +769,7 @@ static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, } static int var_diamond_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags) { MotionEstContext * const c= &s->me; @@ -829,7 +830,7 @@ static int var_diamond_search(MpegEncContext * s, int *best, int dmin, } static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin, - int src_index, int ref_index, int const penalty_factor, + int src_index, int ref_index, const int penalty_factor, int size, int h, int flags){ MotionEstContext * const c= &s->me; if(c->dia_size==-1) @@ -871,7 +872,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int unsigned map_generation; int penalty_factor; const int ref_mv_stride= s->mb_stride; //pass as arg FIXME - const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME + const int ref_mv_xy = s->mb_x + s->mb_y * ref_mv_stride; // add to last_mv before passing FIXME me_cmp_func cmpf, chroma_cmpf; LOAD_COMMON @@ -972,7 +973,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int return dmin; } -//this function is dedicated to the braindamaged gcc +//this function is dedicated to the brain damaged gcc 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, diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index da2727f..a18541b 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -212,13 +212,13 @@ static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y) p = mp_get_yuv_from_rgb(mp, x - 1, y); } else { p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb)); - p.y = av_clip(p.y, 0, 31); + p.y = av_clip_uintp2(p.y, 5); if ((x & 3) == 0) { if ((y & 3) == 0) { p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb)); - p.v = av_clip(p.v, -32, 31); + p.v = av_clip_intp2(p.v, 5); p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb)); - p.u = av_clip(p.u, -32, 31); + p.u = av_clip_intp2(p.u, 5); mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p; } else { p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v; @@ -242,12 +242,12 @@ static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb) p = mp_get_yuv_from_rgb(mp, 0, y); } else { p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb)); - p.y = av_clip(p.y, 0, 31); + p.y = av_clip_uintp2(p.y, 5); if ((y & 3) == 0) { p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb)); - p.v = av_clip(p.v, -32, 31); + p.v = av_clip_intp2(p.v, 5); p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb)); - p.u = av_clip(p.u, -32, 31); + p.u = av_clip_intp2(p.u, 5); } mp->vpt[y] = p; mp_set_rgb_from_yuv(mp, 0, y, &p); @@ -274,14 +274,14 @@ static int mp_decode_frame(AVCodecContext *avctx, } /* le32 bitstream msb first */ - av_fast_malloc(&mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + av_fast_malloc(&mp->bswapbuf, &mp->bswapbuf_size, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!mp->bswapbuf) return AVERROR(ENOMEM); mp->bdsp.bswap_buf((uint32_t *) mp->bswapbuf, (const uint32_t *) buf, buf_size / 4); if (buf_size & 3) memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3); - memset(mp->bswapbuf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(mp->bswapbuf + buf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&gb, mp->bswapbuf, buf_size * 8); memset(mp->changes_map, 0, avctx->width * avctx->height); @@ -331,5 +331,5 @@ AVCodec ff_motionpixels_decoder = { .init = mp_decode_init, .close = mp_decode_end, .decode = mp_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/motionpixels_tablegen.c b/libavcodec/motionpixels_tablegen.c index 410b76f..2f0df3c 100644 --- a/libavcodec/motionpixels_tablegen.c +++ b/libavcodec/motionpixels_tablegen.c @@ -1,5 +1,5 @@ /* - * Generate a header file for hardcoded motionpixels RGB to YUV table + * Generate a header file for hardcoded motion pixels RGB to YUV table * * Copyright (c) 2009 Reimar Döffinger * diff --git a/libavcodec/motionpixels_tablegen.h b/libavcodec/motionpixels_tablegen.h index e6c32c7..2d0c0ff 100644 --- a/libavcodec/motionpixels_tablegen.h +++ b/libavcodec/motionpixels_tablegen.h @@ -1,5 +1,5 @@ /* - * Header file for hardcoded motionpixels RGB to YUV table + * Header file for hardcoded motion pixels RGB to YUV table * * Copyright (c) 2009 Reimar Döffinger * diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c index 506750f..fc6b236 100644 --- a/libavcodec/movsub_bsf.c +++ b/libavcodec/movsub_bsf.c @@ -21,37 +21,79 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "bsf.h" +static int text2movsub(AVBSFContext *ctx, AVPacket *out) +{ + AVPacket *in; + int ret = 0; -static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe){ - if (buf_size > 0xffff) return 0; - *poutbuf_size = buf_size + 2; - *poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE); - AV_WB16(*poutbuf, buf_size); - memcpy(*poutbuf + 2, buf, buf_size); - return 1; + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (in->size > 0xffff) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + ret = av_new_packet(out, in->size + 2); + if (ret < 0) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + + AV_WB16(out->data, in->size); + memcpy(out->data + 2, in->data, in->size); + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; } -AVBitStreamFilter ff_text2movsub_bsf={ - "text2movsub", - 0, - text2movsub, +const AVBitStreamFilter ff_text2movsub_bsf = { + .name = "text2movsub", + .filter = text2movsub, }; -static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe){ - if (buf_size < 2) return 0; - *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf)); - *poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(*poutbuf, buf + 2, *poutbuf_size); - return 1; +static int mov2textsub(AVBSFContext *ctx, AVPacket *out) +{ + AVPacket *in; + int ret = 0; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (in->size < 2) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data))); + if (ret < 0) + goto fail; + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + + memcpy(out->data, in->data + 2, out->size); + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; } -AVBitStreamFilter ff_mov2textsub_bsf={ - "mov2textsub", - 0, - mov2textsub, +const AVBitStreamFilter ff_mov2textsub_bsf = { + .name = "mov2textsub", + .filter = mov2textsub, }; diff --git a/libavcodec/mpc.c b/libavcodec/mpc.c index 763ea2c..88f7226 100644 --- a/libavcodec/mpc.c +++ b/libavcodec/mpc.c @@ -28,7 +28,6 @@ #include "libavutil/attributes.h" #include "avcodec.h" -#include "get_bits.h" #include "mpegaudiodsp.h" #include "mpegaudio.h" diff --git a/libavcodec/mpc.h b/libavcodec/mpc.h index cdf49c1..39b8d63 100644 --- a/libavcodec/mpc.h +++ b/libavcodec/mpc.h @@ -30,9 +30,9 @@ #define AVCODEC_MPC_H #include "libavutil/lfg.h" + #include "avcodec.h" #include "bswapdsp.h" -#include "get_bits.h" #include "mpegaudio.h" #include "mpegaudiodsp.h" @@ -52,7 +52,6 @@ typedef struct Band { typedef struct MPCContext { BswapDSPContext bdsp; MPADSPContext mpadsp; - GetBitContext gb; int IS, MSS, gapless; int lastframelen; int maxbands, last_max_band; diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index 2185aec..28b5192 100644 --- a/libavcodec/mpc7.c +++ b/libavcodec/mpc7.c @@ -337,7 +337,7 @@ AVCodec ff_mpc7_decoder = { .close = mpc7_decode_close, .decode = mpc7_decode_frame, .flush = mpc7_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index ee05a93..84dbb61 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -434,7 +434,7 @@ AVCodec ff_mpc8_decoder = { .init = mpc8_decode_init, .decode = mpc8_decode_frame, .flush = mpc8_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index be5227f..c0c680d 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -32,6 +32,7 @@ #include "error_resilience.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpegvideodata.h" #include "bytestream.h" #include "thread.h" @@ -164,8 +165,8 @@ av_cold void ff_mpeg12_init_vlcs(void) INIT_VLC_STATIC(&ff_mb_btype_vlc, MB_BTYPE_VLC_BITS, 11, &table_mb_btype[0][1], 2, 1, &table_mb_btype[0][0], 2, 1, 64); - ff_init_rl(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); - ff_init_rl(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); + ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); INIT_2D_VLC_RL(ff_rl_mpeg1, 680); INIT_2D_VLC_RL(ff_rl_mpeg2, 674); @@ -235,3 +236,91 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, pc->state = state; return END_NOT_FOUND; } + +#define MAX_INDEX (64 - 1) + +int ff_mpeg1_decode_block_intra(GetBitContext *gb, + const uint16_t *quant_matrix, + uint8_t *const scantable, int last_dc[3], + int16_t *block, int index, int qscale) +{ + int dc, diff, i = 0, component; + RLTable *rl = &ff_rl_mpeg1; + + /* DC coefficient */ + component = index <= 3 ? 0 : index - 4 + 1; + + diff = decode_dc(gb, component); + if (diff >= 0xffff) + return AVERROR_INVALIDDATA; + + dc = last_dc[component]; + dc += diff; + last_dc[component] = dc; + + block[0] = dc * quant_matrix[0]; + + { + OPEN_READER(re, gb); + /* now quantify & encode AC coefficients */ + while (1) { + int level, run, j; + + UPDATE_CACHE(re, gb); + GET_RL_VLC(level, run, re, gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + i += run; + if (i > MAX_INDEX) + break; + + j = scantable[i]; + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level - 1) | 1; + level = (level ^ SHOW_SBITS(re, gb, 1)) - + SHOW_SBITS(re, gb, 1); + LAST_SKIP_BITS(re, gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, gb, 6) + 1; + LAST_SKIP_BITS(re, gb, 6); + UPDATE_CACHE(re, gb); + level = SHOW_SBITS(re, gb, 8); + SKIP_BITS(re, gb, 8); + + if (level == -128) { + level = SHOW_UBITS(re, gb, 8) - 256; + LAST_SKIP_BITS(re, gb, 8); + } else if (level == 0) { + level = SHOW_UBITS(re, gb, 8); + LAST_SKIP_BITS(re, gb, 8); + } + + i += run; + if (i > MAX_INDEX) + break; + + 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; + } + } + + block[j] = level; + } + CLOSE_READER(re, gb); + } + + if (i > MAX_INDEX) + i = AVERROR_INVALIDDATA; + + return i; +} diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h index 9132dc3..17f0b78 100644 --- a/libavcodec/mpeg12.h +++ b/libavcodec/mpeg12.h @@ -1,5 +1,5 @@ /* - * MPEG1/2 common code + * MPEG-1/2 common code * Copyright (c) 2007 Aurelien Jacobs * * This file is part of Libav. @@ -22,29 +22,12 @@ #ifndef AVCODEC_MPEG12_H #define AVCODEC_MPEG12_H +#include "mpeg12vlc.h" #include "mpegvideo.h" -#define DC_VLC_BITS 9 -#define MV_VLC_BITS 9 -#define TEX_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 - -extern VLC ff_dc_lum_vlc; -extern VLC ff_dc_chroma_vlc; -extern VLC ff_mbincr_vlc; -extern VLC ff_mb_ptype_vlc; -extern VLC ff_mb_btype_vlc; -extern VLC ff_mb_pat_vlc; -extern VLC ff_mv_vlc; - extern uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; void ff_mpeg12_common_init(MpegEncContext *s); -void ff_mpeg12_init_vlcs(void); static inline int decode_dc(GetBitContext *gb, int component) { @@ -67,8 +50,18 @@ static inline int decode_dc(GetBitContext *gb, int component) return diff; } -int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n); +int ff_mpeg1_decode_block_intra(GetBitContext *gb, + const uint16_t *quant_matrix, + uint8_t *const scantable, int last_dc[3], + int16_t *block, int index, int qscale); + void ff_mpeg1_clean_buffers(MpegEncContext *s); int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s); +void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], + int motion_x, int motion_y); +void ff_mpeg1_encode_init(MpegEncContext *s); +void ff_mpeg1_encode_slice_header(MpegEncContext *s); + #endif /* AVCODEC_MPEG12_H */ diff --git a/libavcodec/mpeg12data.c b/libavcodec/mpeg12data.c index ccc3d2d..acb2bc3 100644 --- a/libavcodec/mpeg12data.c +++ b/libavcodec/mpeg12data.c @@ -1,5 +1,5 @@ /* - * MPEG1/2 tables + * MPEG-1/2 tables * copyright (c) 2000,2001 Fabrice Bellard * copyright (c) 2002-2004 Michael Niedermayer * @@ -22,7 +22,7 @@ /** * @file - * MPEG1/2 tables. + * MPEG-1/2 tables. */ #include "mpeg12data.h" @@ -305,26 +305,6 @@ const uint8_t ff_mpeg12_mbMotionVectorTable[17][2] = { { 0xc, 10 }, }; -const AVRational ff_mpeg12_frame_rate_tab[16] = { - { 0, 0}, - {24000, 1001}, - { 24, 1}, - { 25, 1}, - {30000, 1001}, - { 30, 1}, - { 50, 1}, - {60000, 1001}, - { 60, 1}, - // Xing's 15fps: (9) - { 15, 1}, - // libmpeg3's "Unofficial economy rates": (10-13) - { 5, 1}, - { 10, 1}, - { 12, 1}, - { 15, 1}, - { 0, 0}, -}; - const float ff_mpeg1_aspect[16]={ 0.0000, 1.0000, diff --git a/libavcodec/mpeg12data.h b/libavcodec/mpeg12data.h index 633a291..c6750b8 100644 --- a/libavcodec/mpeg12data.h +++ b/libavcodec/mpeg12data.h @@ -1,5 +1,5 @@ /* - * MPEG1/2 tables + * MPEG-1/2 tables * copyright (c) 2000,2001 Fabrice Bellard * copyright (c) 2002-2004 Michael Niedermayer * @@ -22,7 +22,7 @@ /** * @file - * MPEG1/2 tables. + * MPEG-1/2 tables. */ #ifndef AVCODEC_MPEG12DATA_H diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 93e3900..afdd652 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -41,6 +41,8 @@ #include "mpeg12data.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodata.h" +#include "profiles.h" #include "thread.h" #include "version.h" #include "xvmc_internal.h" @@ -126,96 +128,16 @@ static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred) return sign_extend(val, 5 + shift); } +#define MAX_INDEX (64 - 1) #define check_scantable_index(ctx, x) \ do { \ - if ((x) > 63) { \ + if ((x) > MAX_INDEX) { \ av_log(ctx->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", \ ctx->mb_x, ctx->mb_y); \ return AVERROR_INVALIDDATA; \ } \ } while (0) -static inline int mpeg1_decode_block_intra(MpegEncContext *s, - int16_t *block, int n) -{ - int level, dc, diff, i, j, run; - int component; - RLTable *rl = &ff_rl_mpeg1; - uint8_t *const scantable = s->intra_scantable.permutated; - const uint16_t *quant_matrix = s->intra_matrix; - const int qscale = s->qscale; - - /* DC coefficient */ - component = (n <= 3 ? 0 : n - 4 + 1); - diff = decode_dc(&s->gb, component); - if (diff >= 0xffff) - return -1; - dc = s->last_dc[component]; - dc += diff; - s->last_dc[component] = dc; - block[0] = dc * quant_matrix[0]; - av_dlog(s->avctx, "dc=%d diff=%d\n", dc, diff); - i = 0; - { - OPEN_READER(re, &s->gb); - /* now quantify & encode AC coefficients */ - for (;;) { - UPDATE_CACHE(re, &s->gb); - GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], - TEX_VLC_BITS, 2, 0); - - if (level == 127) { - break; - } else if (level != 0) { - i += run; - check_scantable_index(s, i); - 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; - check_scantable_index(s, i); - 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; - } - } - - block[j] = level; - } - CLOSE_READER(re, &s->gb); - } - s->block_last_index[n] = i; - return 0; -} - -int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n) -{ - return mpeg1_decode_block_intra(s, block, n); -} - static inline int mpeg1_decode_block_inter(MpegEncContext *s, int16_t *block, int n) { @@ -248,7 +170,8 @@ static inline int mpeg1_decode_block_inter(MpegEncContext *s, if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; level = (level - 1) | 1; @@ -270,7 +193,8 @@ static inline int mpeg1_decode_block_inter(MpegEncContext *s, SKIP_BITS(re, &s->gb, 8); } i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = -level; @@ -292,6 +216,9 @@ end: LAST_SKIP_BITS(re, &s->gb, 2); CLOSE_READER(re, &s->gb); } + + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -328,7 +255,8 @@ static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = ((level * 2 + 1) * qscale) >> 1; level = (level - 1) | 1; @@ -350,7 +278,8 @@ static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, SKIP_BITS(re, &s->gb, 8); } i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = -level; @@ -372,6 +301,9 @@ end: LAST_SKIP_BITS(re, &s->gb, 2); CLOSE_READER(re, &s->gb); } + + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -417,7 +349,8 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - @@ -432,7 +365,8 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, SKIP_BITS(re, &s->gb, 12); i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = ((-level * 2 + 1) * qscale * quant_matrix[j]) >> 5; @@ -454,6 +388,8 @@ end: } block[63] ^= (mismatch & 1); + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -487,7 +423,8 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = ((level * 2 + 1) * qscale) >> 1; level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - @@ -502,7 +439,8 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, SKIP_BITS(re, &s->gb, 12); i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = ((-level * 2 + 1) * qscale) >> 1; @@ -520,6 +458,9 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, end: LAST_SKIP_BITS(re, &s->gb, 2); CLOSE_READER(re, &s->gb); + + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -545,12 +486,12 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s, } diff = decode_dc(&s->gb, component); if (diff >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; dc = s->last_dc[component]; dc += diff; s->last_dc[component] = dc; block[0] = dc << (3 - s->intra_dc_precision); - av_dlog(s->avctx, "dc=%d\n", block[0]); + ff_dlog(s->avctx, "dc=%d\n", block[0]); mismatch = block[0] ^ 1; i = 0; if (s->intra_vlc_format) @@ -570,7 +511,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s, break; } else if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = (level * qscale * quant_matrix[j]) >> 4; level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - @@ -584,7 +526,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s, level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = (-level * qscale * quant_matrix[j]) >> 4; @@ -601,6 +544,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s, } block[63] ^= mismatch & 1; + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -625,7 +570,7 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, } diff = decode_dc(&s->gb, component); if (diff >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; dc = s->last_dc[component]; dc += diff; s->last_dc[component] = dc; @@ -648,7 +593,8 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, break; } else if (level != 0) { i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; level = (level * qscale * quant_matrix[j]) >> 4; level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - @@ -662,7 +608,8 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); i += run; - check_scantable_index(s, i); + if (i > MAX_INDEX) + break; j = scantable[i]; if (level < 0) { level = (-level * qscale * quant_matrix[j]) >> 4; @@ -677,6 +624,8 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, CLOSE_READER(re, &s->gb); } + check_scantable_index(s, i); + s->block_last_index[n] = i; return 0; } @@ -711,8 +660,9 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) { int i, j, k, cbp, val, mb_type, motion_type; const int mb_block_count = 4 + (1 << s->chroma_format); + int ret; - av_dlog(s->avctx, "decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y); + ff_dlog(s->avctx, "decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y); assert(s->mb_skipped == 0); @@ -730,7 +680,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) // FIXME not sure if this is allowed in MPEG at all mb_type = s->current_picture.mb_type[s->mb_width + (s->mb_y - 1) * s->mb_stride - 1]; if (IS_INTRA(mb_type)) - return -1; + return AVERROR_INVALIDDATA; 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)); @@ -748,9 +698,9 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) 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", + "Invalid mb type in I-frame at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } mb_type = MB_TYPE_QUANT | MB_TYPE_INTRA; } else { @@ -761,8 +711,8 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) mb_type = get_vlc2(&s->gb, ff_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; + "Invalid mb type in P-frame at %d %d\n", s->mb_x, s->mb_y); + return AVERROR_INVALIDDATA; } mb_type = ptype2mb_type[mb_type]; break; @@ -770,13 +720,13 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) mb_type = get_vlc2(&s->gb, ff_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; + "Invalid mb type in B-frame at %d %d\n", s->mb_x, s->mb_y); + return AVERROR_INVALIDDATA; } mb_type = btype2mb_type[mb_type]; break; } - av_dlog(s->avctx, "mb_type=%x\n", mb_type); + ff_dlog(s->avctx, "mb_type=%x\n", mb_type); // motion_type = 0; /* avoid warning */ if (IS_INTRA(mb_type)) { s->bdsp.clear_blocks(s->block[0]); @@ -822,18 +772,29 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif /* FF_API_XVMC */ if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - if (s->flags2 & CODEC_FLAG2_FAST) { + if (s->avctx->flags2 & AV_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; + if ((ret = mpeg2_decode_block_intra(s, *s->pblocks[i], i)) < 0) + return ret; } } else { - for (i = 0; i < 6; i++) - if (mpeg1_decode_block_intra(s, *s->pblocks[i], i) < 0) - return -1; + for (i = 0; i < 6; i++) { + ret = ff_mpeg1_decode_block_intra(&s->gb, + s->intra_matrix, + s->intra_scantable.permutated, + s->last_dc, *s->pblocks[i], + i, s->qscale); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", + s->mb_x, s->mb_y); + return ret; + } + + s->block_last_index[i] = ret; + } } } else { if (mb_type & MB_TYPE_ZERO_MV) { @@ -876,7 +837,7 @@ FF_ENABLE_DEPRECATION_WARNINGS /* motion vectors */ s->mv_dir = (mb_type >> 13) & 3; - av_dlog(s->avctx, "motion_type=%d\n", motion_type); + ff_dlog(s->avctx, "motion_type=%d\n", motion_type); switch (motion_type) { case MT_FRAME: /* or MT_16X8 */ if (s->picture_structure == PICT_FRAME) { @@ -933,12 +894,12 @@ FF_ENABLE_DEPRECATION_WARNINGS s->last_mv[i][j][0]); s->last_mv[i][j][0] = val; s->mv[i][j][0] = val; - av_dlog(s->avctx, "fmx=%d\n", val); + ff_dlog(s->avctx, "fmx=%d\n", val); val = mpeg_decode_motion(s, s->mpeg_f_code[i][1], s->last_mv[i][j][1] >> 1); s->last_mv[i][j][1] = val << 1; s->mv[i][j][1] = val; - av_dlog(s->avctx, "fmy=%d\n", val); + ff_dlog(s->avctx, "fmy=%d\n", val); } } } @@ -1011,7 +972,7 @@ FF_ENABLE_DEPRECATION_WARNINGS default: av_log(s->avctx, AV_LOG_ERROR, "00 motion_type at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } @@ -1028,7 +989,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (cbp <= 0) { av_log(s->avctx, AV_LOG_ERROR, "invalid cbp at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } #if FF_API_XVMC @@ -1040,7 +1001,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif /* FF_API_XVMC */ if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - if (s->flags2 & CODEC_FLAG2_FAST) { + if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { for (i = 0; i < 6; i++) { if (cbp & 32) mpeg2_fast_decode_block_non_intra(s, *s->pblocks[i], i); @@ -1053,8 +1014,8 @@ FF_ENABLE_DEPRECATION_WARNINGS 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; + if ((ret = mpeg2_decode_block_non_intra(s, *s->pblocks[i], i)) < 0) + return ret; } else { s->block_last_index[i] = -1; } @@ -1062,7 +1023,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } } else { - if (s->flags2 & CODEC_FLAG2_FAST) { + if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { for (i = 0; i < 6; i++) { if (cbp & 32) mpeg1_fast_decode_block_inter(s, *s->pblocks[i], i); @@ -1073,8 +1034,8 @@ FF_ENABLE_DEPRECATION_WARNINGS } else { for (i = 0; i < 6; i++) { if (cbp & 32) { - if (mpeg1_decode_block_inter(s, *s->pblocks[i], i) < 0) - return -1; + if ((ret = mpeg1_decode_block_inter(s, *s->pblocks[i], i)) < 0) + return ret; } else { s->block_last_index[i] = -1; } @@ -1101,8 +1062,6 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx) ff_mpv_decode_defaults(s2); s->mpeg_enc_ctx.avctx = avctx; - s->mpeg_enc_ctx.flags = avctx->flags; - s->mpeg_enc_ctx.flags2 = avctx->flags2; /* we need some permutation to store matrices, * until the decoder sets the real permutation. */ @@ -1138,8 +1097,11 @@ static int mpeg_decode_update_thread_context(AVCodecContext *avctx, if (err) return err; - if (!ctx->mpeg_enc_ctx_allocated) - memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext)); + if (!ctx->mpeg_enc_ctx_allocated) { + // copy the whole context after the initial MpegEncContext structure + memcpy(ctx, ctx_from, sizeof(*ctx)); + memset(&ctx->mpeg_enc_ctx, 0, sizeof(ctx->mpeg_enc_ctx)); + } if (!(s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)) s->picture_number++; @@ -1171,8 +1133,11 @@ static const enum AVPixelFormat mpeg12_hwaccel_pixfmt_list_420[] = { #if CONFIG_MPEG2_DXVA2_HWACCEL AV_PIX_FMT_DXVA2_VLD, #endif +#if CONFIG_MPEG2_D3D11VA_HWACCEL + AV_PIX_FMT_D3D11VA_VLD, +#endif #if CONFIG_MPEG2_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, + AV_PIX_FMT_VAAPI, #endif #if CONFIG_MPEG1_VDPAU_HWACCEL | CONFIG_MPEG2_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, @@ -1238,9 +1203,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) s->parse_context = pc; } - if ((s->width == 0) || (s->height == 0)) - return -2; - ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; @@ -1257,15 +1219,14 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { // MPEG-1 fps - avctx->time_base.den = ff_mpeg12_frame_rate_tab[s->frame_rate_index].num; - avctx->time_base.num = ff_mpeg12_frame_rate_tab[s->frame_rate_index].den; + avctx->framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; // MPEG-1 aspect avctx->sample_aspect_ratio = av_d2q(1.0 / ff_mpeg1_aspect[s->aspect_ratio_info], 255); avctx->ticks_per_frame = 1; } else { // MPEG-2 // MPEG-2 fps - av_reduce(&s->avctx->time_base.den, - &s->avctx->time_base.num, + av_reduce(&s->avctx->framerate.num, + &s->avctx->framerate.den, ff_mpeg12_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num * 2, ff_mpeg12_frame_rate_tab[s->frame_rate_index].den * s1->frame_rate_ext.den, 1 << 30); @@ -1296,10 +1257,10 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) // res_change_ffmpeg_aspect.ts 4/3 225/44 ->4/3 // widescreen-issue562.mpg 4/3 16/9 -> 16/9 // s->avctx->sample_aspect_ratio = av_mul_q(s->avctx->sample_aspect_ratio, (AVRational) {s->width, s->height}); - av_dlog(avctx, "A %d/%d\n", + ff_dlog(avctx, "A %d/%d\n", ff_mpeg2_aspect[s->aspect_ratio_info].num, ff_mpeg2_aspect[s->aspect_ratio_info].den); - av_dlog(avctx, "B %d/%d\n", s->avctx->sample_aspect_ratio.num, + ff_dlog(avctx, "B %d/%d\n", s->avctx->sample_aspect_ratio.num, s->avctx->sample_aspect_ratio.den); } } else { @@ -1325,8 +1286,8 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) memcpy(old_permutation, s->idsp.idct_permutation, 64 * sizeof(uint8_t)); ff_mpv_idct_init(s); - if (ff_mpv_common_init(s) < 0) - return -2; + if ((ret = ff_mpv_common_init(s)) < 0) + return ret; quant_matrix_rebuild(s->intra_matrix, old_permutation, s->idsp.idct_permutation); quant_matrix_rebuild(s->inter_matrix, old_permutation, s->idsp.idct_permutation); @@ -1350,7 +1311,7 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, const uint8_t *buf, 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; + return AVERROR_INVALIDDATA; vbv_delay = get_bits(&s->gb, 16); if (s->pict_type == AV_PICTURE_TYPE_P || @@ -1358,7 +1319,7 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, const uint8_t *buf, s->full_pel[0] = get_bits1(&s->gb); f_code = get_bits(&s->gb, 3); if (f_code == 0 && (avctx->err_recognition & AV_EF_BITSTREAM)) - return -1; + return AVERROR_INVALIDDATA; s->mpeg_f_code[0][0] = f_code; s->mpeg_f_code[0][1] = f_code; } @@ -1366,7 +1327,7 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, const uint8_t *buf, s->full_pel[1] = get_bits1(&s->gb); f_code = get_bits(&s->gb, 3); if (f_code == 0 && (avctx->err_recognition & AV_EF_BITSTREAM)) - return -1; + return AVERROR_INVALIDDATA; s->mpeg_f_code[1][0] = f_code; s->mpeg_f_code[1][1] = f_code; } @@ -1397,19 +1358,28 @@ static void mpeg_decode_sequence_extension(Mpeg1Context *s1) 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; + + bit_rate_ext = get_bits(&s->gb, 12) << 18; + if (bit_rate_ext < INT_MAX / 400 && + bit_rate_ext * 400 < INT_MAX - s->bit_rate) { + s->bit_rate += bit_rate_ext * 400; + } else { + av_log(s->avctx, AV_LOG_WARNING, "Invalid bit rate extension value: %d\n", + bit_rate_ext >> 18); + s->bit_rate = 0; + } + 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) + if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) s->low_delay = 1; s1->frame_rate_ext.num = get_bits(&s->gb, 2) + 1; s1->frame_rate_ext.den = get_bits(&s->gb, 5) + 1; - av_dlog(s->avctx, "sequence extension\n"); + ff_dlog(s->avctx, "sequence extension\n"); s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; if (s->avctx->debug & FF_DEBUG_PICT_INFO) @@ -1487,7 +1457,7 @@ static int load_matrix(MpegEncContext *s, uint16_t matrix0[64], int v = get_bits(&s->gb, 8); if (v == 0) { av_log(s->avctx, AV_LOG_ERROR, "matrix damaged\n"); - return -1; + return AVERROR_INVALIDDATA; } if (intra && i == 0 && v != 8) { av_log(s->avctx, AV_LOG_ERROR, "intra matrix invalid, ignoring\n"); @@ -1502,7 +1472,7 @@ static int load_matrix(MpegEncContext *s, uint16_t matrix0[64], static void mpeg_decode_quant_matrix_extension(MpegEncContext *s) { - av_dlog(s->avctx, "matrix extension\n"); + ff_dlog(s->avctx, "matrix extension\n"); if (get_bits1(&s->gb)) load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); @@ -1566,10 +1536,8 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) av_log(s->avctx, AV_LOG_WARNING, "invalid frame_pred_frame_dct\n"); 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); } @@ -1583,28 +1551,34 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) } /* composite display not parsed */ - av_dlog(s->avctx, "intra_dc_precision=%d\n", s->intra_dc_precision); - av_dlog(s->avctx, "picture_structure=%d\n", s->picture_structure); - av_dlog(s->avctx, "top field first=%d\n", s->top_field_first); - av_dlog(s->avctx, "repeat first field=%d\n", s->repeat_first_field); - av_dlog(s->avctx, "conceal=%d\n", s->concealment_motion_vectors); - av_dlog(s->avctx, "intra_vlc_format=%d\n", s->intra_vlc_format); - av_dlog(s->avctx, "alternate_scan=%d\n", s->alternate_scan); - av_dlog(s->avctx, "frame_pred_frame_dct=%d\n", s->frame_pred_frame_dct); - av_dlog(s->avctx, "progressive_frame=%d\n", s->progressive_frame); + ff_dlog(s->avctx, "intra_dc_precision=%d\n", s->intra_dc_precision); + ff_dlog(s->avctx, "picture_structure=%d\n", s->picture_structure); + ff_dlog(s->avctx, "top field first=%d\n", s->top_field_first); + ff_dlog(s->avctx, "repeat first field=%d\n", s->repeat_first_field); + ff_dlog(s->avctx, "conceal=%d\n", s->concealment_motion_vectors); + ff_dlog(s->avctx, "intra_vlc_format=%d\n", s->intra_vlc_format); + ff_dlog(s->avctx, "alternate_scan=%d\n", s->alternate_scan); + ff_dlog(s->avctx, "frame_pred_frame_dct=%d\n", s->frame_pred_frame_dct); + ff_dlog(s->avctx, "progressive_frame=%d\n", s->progressive_frame); } static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) { AVCodecContext *avctx = s->avctx; Mpeg1Context *s1 = (Mpeg1Context *) s; + int ret; + + if (s->picture_structure == PICT_FRAME) + s->first_field = 0; + else + s->first_field ^= 1; /* start frame decoding */ if (s->first_field || s->picture_structure == PICT_FRAME) { AVFrameSideData *pan_scan; - if (ff_mpv_frame_start(s, avctx) < 0) - return -1; + if ((ret = ff_mpv_frame_start(s, avctx)) < 0) + return ret; ff_mpeg_er_frame_start(s); @@ -1664,7 +1638,7 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) if (!s->current_picture_ptr) { av_log(s->avctx, AV_LOG_ERROR, "first field missing\n"); - return -1; + return AVERROR_INVALIDDATA; } if (s->avctx->hwaccel && @@ -1683,8 +1657,8 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) } if (avctx->hwaccel) { - if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0) - return -1; + if ((ret = avctx->hwaccel->start_frame(avctx, buf, buf_size)) < 0) + return ret; } #if FF_API_XVMC @@ -1714,6 +1688,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, { AVCodecContext *avctx = s->avctx; const int field_pic = s->picture_structure != PICT_FRAME; + int ret; s->resync_mb_x = s->resync_mb_y = -1; @@ -1729,7 +1704,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, if (s->qscale == 0) { av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n"); - return -1; + return AVERROR_INVALIDDATA; } /* extra slice info */ @@ -1746,7 +1721,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, MBINCR_VLC_BITS, 2); if (code < 0) { av_log(s->avctx, AV_LOG_ERROR, "first mb_incr damaged\n"); - return -1; + return AVERROR_INVALIDDATA; } if (code >= 33) { if (code == 33) @@ -1761,7 +1736,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, if (s->mb_x >= (unsigned) s->mb_width) { av_log(s->avctx, AV_LOG_ERROR, "initial skip overflow\n"); - return -1; + return AVERROR_INVALIDDATA; } if (avctx->hwaccel) { @@ -1812,8 +1787,8 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif /* FF_API_XVMC */ - if (mpeg_decode_mb(s, s->block) < 0) - return -1; + if ((ret = mpeg_decode_mb(s, s->block)) < 0) + return ret; // Note motion_val is normally NULL unless we want to extract the MVs. if (s->current_picture.motion_val[0] && !s->encoding) { @@ -1880,7 +1855,7 @@ FF_ENABLE_DEPRECATION_WARNINGS ((avctx->err_recognition & AV_EF_BUFFER) && left > 8)) { av_log(avctx, AV_LOG_ERROR, "end mismatch left=%d %0X\n", left, show_bits(&s->gb, FFMIN(left, 23))); - return -1; + return AVERROR_INVALIDDATA; } else goto eos; } @@ -1897,7 +1872,7 @@ FF_ENABLE_DEPRECATION_WARNINGS MBINCR_VLC_BITS, 2); if (code < 0) { av_log(s->avctx, AV_LOG_ERROR, "mb incr damaged\n"); - return -1; + return AVERROR_INVALIDDATA; } if (code >= 33) { if (code == 33) { @@ -1905,7 +1880,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } 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; + return AVERROR_INVALIDDATA; } goto eos; /* end of slice */ } @@ -1919,8 +1894,8 @@ FF_ENABLE_DEPRECATION_WARNINGS int i; if (s->pict_type == AV_PICTURE_TYPE_I) { av_log(s->avctx, AV_LOG_ERROR, - "skipped MB in I frame at %d %d\n", s->mb_x, s->mb_y); - return -1; + "skipped MB in I-frame at %d %d\n", s->mb_x, s->mb_y); + return AVERROR_INVALIDDATA; } /* skip mb */ @@ -1950,7 +1925,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } eos: // end of slice *buf += (get_bits_count(&s->gb) - 1) / 8; - av_dlog(s, "y %d %d %d %d\n", s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y); + ff_dlog(s, "y %d %d %d %d\n", s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y); return 0; } @@ -1969,7 +1944,7 @@ static int slice_decode_thread(AVCodecContext *c, void *arg) ret = mpeg_decode_slice(s, mb_y, &buf, s->gb.buffer_end - buf); emms_c(); - av_dlog(c, "ret:%d resync:%d/%d mb:%d/%d ts:%d/%d ec:%d\n", + ff_dlog(c, "ret:%d resync:%d/%d mb:%d/%d ts:%d/%d ec:%d\n", ret, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, s->start_mb_y, s->end_mb_y, s->er.error_count); if (ret < 0) { @@ -1994,7 +1969,7 @@ static int slice_decode_thread(AVCodecContext *c, void *arg) if (s->picture_structure == PICT_BOTTOM_FIELD) mb_y++; if (mb_y < 0 || mb_y >= s->end_mb_y) - return -1; + return AVERROR_INVALIDDATA; } } @@ -2077,14 +2052,19 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (s->aspect_ratio_info == 0) { av_log(avctx, AV_LOG_ERROR, "aspect ratio has forbidden 0 value\n"); if (avctx->err_recognition & AV_EF_BITSTREAM) - return -1; + return AVERROR_INVALIDDATA; } s->frame_rate_index = get_bits(&s->gb, 4); - if (s->frame_rate_index == 0 || s->frame_rate_index > 13) - return -1; + if (s->frame_rate_index == 0 || s->frame_rate_index > 13) { + av_log(avctx, AV_LOG_WARNING, + "frame_rate_index %d is invalid\n", s->frame_rate_index); + return AVERROR_INVALIDDATA; + } s->bit_rate = get_bits(&s->gb, 18) * 400; - if (get_bits1(&s->gb) == 0) /* marker */ - return -1; + if (get_bits1(&s->gb) == 0) { /* marker */ + av_log(avctx, AV_LOG_ERROR, "Marker in sequence header missing\n"); + return AVERROR_INVALIDDATA; + } s->width = width; s->height = height; @@ -2115,7 +2095,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (show_bits(&s->gb, 23) != 0) { av_log(s->avctx, AV_LOG_ERROR, "sequence header damaged\n"); - return -1; + return AVERROR_INVALIDDATA; } /* We set MPEG-2 parameters so that it emulates MPEG-1. */ @@ -2127,7 +2107,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; s->out_format = FMT_MPEG1; - if (s->flags & CODEC_FLAG_LOW_DELAY) + if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) s->low_delay = 1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) @@ -2141,7 +2121,7 @@ static int vcr2_init_sequence(AVCodecContext *avctx) { Mpeg1Context *s1 = avctx->priv_data; MpegEncContext *s = &s1->mpeg_enc_ctx; - int i, v; + int i, v, ret; /* start new MPEG-1 context decoding */ s->out_format = FMT_MPEG1; @@ -2164,8 +2144,8 @@ static int vcr2_init_sequence(AVCodecContext *avctx) avctx->idct_algo = FF_IDCT_SIMPLE; ff_mpv_idct_init(s); - if (ff_mpv_common_init(s) < 0) - return -1; + if ((ret = ff_mpv_common_init(s)) < 0) + return ret; s1->mpeg_enc_ctx_allocated = 1; for (i = 0; i < 64; i++) { @@ -2215,7 +2195,7 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, int cc_count = 0; int i; // There is a caption count field in the data, but it is often - // incorect. So count the number of captions present. + // incorrect. So count the number of captions present. for (i = 5; i + 6 <= buf_size && ((p[i] & 0xfe) == 0xfe); i += 6) cc_count++; // Transform the DVD format into A53 Part 4 format @@ -2498,7 +2478,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, if (mb_y >= s2->mb_height) { av_log(s2->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", mb_y, s2->mb_height); - return -1; + return AVERROR_INVALIDDATA; } if (!s2->last_picture_ptr) { @@ -2549,8 +2529,8 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, if (s->first_slice) { skip_frame = 0; s->first_slice = 0; - if (mpeg_field_start(s2, buf, buf_size) < 0) - return -1; + if ((ret = mpeg_field_start(s2, buf, buf_size)) < 0) + return ret; } if (!s2->current_picture_ptr) { av_log(avctx, AV_LOG_ERROR, @@ -2610,7 +2590,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, Mpeg1Context *s = avctx->priv_data; AVFrame *picture = data; MpegEncContext *s2 = &s->mpeg_enc_ctx; - av_dlog(avctx, "fill_buffer\n"); + ff_dlog(avctx, "fill_buffer\n"); if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == SEQ_END_CODE)) { /* special case for last picture */ @@ -2626,7 +2606,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } - if (s2->flags & CODEC_FLAG_TRUNCATED) { + if (s2->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { int next = ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size, NULL); @@ -2671,18 +2651,6 @@ static av_cold int mpeg_decode_end(AVCodecContext *avctx) return 0; } -static const AVProfile mpeg2_video_profiles[] = { - { FF_PROFILE_MPEG2_422, "4:2:2" }, - { FF_PROFILE_MPEG2_HIGH, "High" }, - { FF_PROFILE_MPEG2_SS, "Spatially Scalable" }, - { FF_PROFILE_MPEG2_SNR_SCALABLE, "SNR Scalable" }, - { FF_PROFILE_MPEG2_MAIN, "Main" }, - { FF_PROFILE_MPEG2_SIMPLE, "Simple" }, - { FF_PROFILE_RESERVED, "Reserved" }, - { FF_PROFILE_RESERVED, "Reserved" }, - { FF_PROFILE_UNKNOWN }, -}; - AVCodec ff_mpeg1video_decoder = { .name = "mpeg1video", .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), @@ -2692,9 +2660,9 @@ AVCodec ff_mpeg1video_decoder = { .init = mpeg_decode_init, .close = mpeg_decode_end, .decode = mpeg_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | - CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | - CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_SLICE_THREADS, .flush = flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context) }; @@ -2708,11 +2676,11 @@ AVCodec ff_mpeg2video_decoder = { .init = mpeg_decode_init, .close = mpeg_decode_end, .decode = mpeg_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | - CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | - CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_SLICE_THREADS, .flush = flush, - .profiles = NULL_IF_CONFIG_SMALL(mpeg2_video_profiles), + .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), }; #if FF_API_XVMC @@ -2724,7 +2692,7 @@ static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx) if (!(avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) return -1; if (!(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { - av_dlog(avctx, "mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n"); + ff_dlog(avctx, "mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n"); } mpeg_decode_init(avctx); @@ -2743,8 +2711,9 @@ AVCodec ff_mpeg_xvmc_decoder = { .init = mpeg_mc_decode_init, .close = mpeg_decode_end, .decode = mpeg_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | - CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL | + AV_CODEC_CAP_DELAY, .flush = flush, }; diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 3376f10..103f3aa 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -1,5 +1,5 @@ /* - * MPEG1/2 encoder + * MPEG-1/2 encoder * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * @@ -22,7 +22,7 @@ /** * @file - * MPEG1/2 encoder + * MPEG-1/2 encoder */ #include @@ -136,12 +136,12 @@ static av_cold int encode_init(AVCodecContext *avctx) 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", + av_log(avctx, AV_LOG_ERROR, "MPEG-1/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", + "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n", avctx->time_base.den, avctx->time_base.num); } } @@ -182,6 +182,13 @@ static av_cold int encode_init(AVCodecContext *avctx) return -1; } +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->timecode_frame_start) + s->timecode_frame_start = avctx->timecode_frame_start; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + return 0; } @@ -207,7 +214,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) if (s->current_picture.f->key_frame) { AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; - /* mpeg1 header repeated every gop */ + /* MPEG-1 header repeated every GOP */ put_header(s, SEQ_START_CODE); put_sbits(&s->pb, 12, s->width); @@ -307,7 +314,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) * fake MPEG frame rate in case of low frame rate */ fps = (framerate.num + framerate.den / 2) / framerate.den; time_code = s->current_picture_ptr->f->coded_picture_number + - s->avctx->timecode_frame_start; + s->timecode_frame_start; s->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; if (s->drop_frame_timecode) { @@ -324,7 +331,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) 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, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) || s->intra_only); put_bits(&s->pb, 1, 0); // broken link } } @@ -368,7 +375,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) AVFrameSideData *side_data; mpeg1_encode_sequence_header(s); - /* mpeg1 picture header */ + /* MPEG-1 picture header */ put_header(s, PICTURE_START_CODE); /* temporal reference */ @@ -546,7 +553,8 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) static inline void encode_dc(MpegEncContext *s, int diff, int component) { - if (((unsigned) (diff + 255)) >= 511) { + unsigned int diff_u = diff + 255; + if (diff_u >= 511) { int index; if (diff < 0) { @@ -657,7 +665,7 @@ next_coef: } static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, - int16_t block[6][64], + int16_t block[8][64], int motion_x, int motion_y, int mb_block_count) { @@ -934,7 +942,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, } } -void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[6][64], +void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y) { if (s->chroma_format == CHROMA_420) @@ -955,8 +963,8 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) int i; done = 1; - ff_init_rl(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); - ff_init_rl(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); + ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); for (i = 0; i < 64; i++) { mpeg1_max_level[0][i] = ff_rl_mpeg1.max_level[0][i]; @@ -1049,7 +1057,9 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) { "drop_frame_timecode", "Timecode is in drop frame format.", \ OFFSET(drop_frame_timecode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ { "scan_offset", "Reserve space for SVCD scan offset user data.", \ - OFFSET(scan_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + OFFSET(scan_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ + { "timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", \ + OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, VE}, \ static const AVOption mpeg1_options[] = { COMMON_OPTS @@ -1088,7 +1098,7 @@ AVCodec ff_mpeg1video_encoder = { .supported_framerates = ff_mpeg12_frame_rate_tab + 1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .priv_class = &mpeg1_class, }; @@ -1105,6 +1115,6 @@ AVCodec ff_mpeg2video_encoder = { .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .priv_class = &mpeg2_class, }; diff --git a/libavcodec/mpeg12framerate.c b/libavcodec/mpeg12framerate.c new file mode 100644 index 0000000..b11dd5e --- /dev/null +++ b/libavcodec/mpeg12framerate.c @@ -0,0 +1,39 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/rational.h" + +const AVRational ff_mpeg12_frame_rate_tab[16] = { + { 0, 0}, + {24000, 1001}, + { 24, 1}, + { 25, 1}, + {30000, 1001}, + { 30, 1}, + { 50, 1}, + {60000, 1001}, + { 60, 1}, + // Xing's 15fps: (9) + { 15, 1}, + // libmpeg3's "Unofficial economy rates": (10-13) + { 5, 1}, + { 10, 1}, + { 12, 1}, + { 15, 1}, + { 0, 0}, +}; diff --git a/libavcodec/mpeg12vlc.h b/libavcodec/mpeg12vlc.h new file mode 100644 index 0000000..90f8135 --- /dev/null +++ b/libavcodec/mpeg12vlc.h @@ -0,0 +1,52 @@ +/* + * MPEG-1/2 VLC + * copyright (c) 2000,2001 Fabrice Bellard + * copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * MPEG-1/2 VLC. + */ + +#ifndef AVCODEC_MPEG12VLC_H +#define AVCODEC_MPEG12VLC_H + +#include "vlc.h" + +#define DC_VLC_BITS 9 +#define MV_VLC_BITS 9 +#define TEX_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 + +extern VLC ff_dc_lum_vlc; +extern VLC ff_dc_chroma_vlc; +extern VLC ff_mbincr_vlc; +extern VLC ff_mb_ptype_vlc; +extern VLC ff_mb_btype_vlc; +extern VLC ff_mb_pat_vlc; +extern VLC ff_mv_vlc; + +void ff_mpeg12_init_vlcs(void); + +#endif /* AVCODEC_MPEG12VLC_H */ diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index e71122d..2eef220 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -38,6 +38,7 @@ typedef struct MPEG4AudioConfig { int ext_chan_config; int channels; int ps; ///< -1 implicit, 1 presence + int frame_length_short; } MPEG4AudioConfig; extern av_export const int avpriv_mpeg4audio_sample_rates[16]; diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h index 87bb539..b428a5e 100644 --- a/libavcodec/mpeg4data.h +++ b/libavcodec/mpeg4data.h @@ -1,6 +1,6 @@ /* * copyright (c) 2000,2001 Fabrice Bellard - * H263+ support + * H.263+ support * copyright (c) 2002-2004 Michael Niedermayer * * This file is part of Libav. @@ -22,7 +22,7 @@ /** * @file - * mpeg4 tables. + * MPEG-4 tables. */ #ifndef AVCODEC_MPEG4DATA_H @@ -31,7 +31,7 @@ #include #include "mpegvideo.h" -/* dc encoding for mpeg4 */ +/* dc encoding for MPEG-4 */ const uint8_t ff_mpeg4_DCtab_lum[13][2] = { {3,3}, {3,2}, {2,2}, {2,3}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, diff --git a/libavcodec/mpeg4video.c b/libavcodec/mpeg4video.c index 84fa26b..b60cd4f 100644 --- a/libavcodec/mpeg4video.c +++ b/libavcodec/mpeg4video.c @@ -1,5 +1,5 @@ /* - * MPEG4 decoder / encoder common code. + * MPEG-4 decoder / encoder common code * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2010 Michael Niedermayer * @@ -51,23 +51,13 @@ void ff_mpeg4_clean_buffers(MpegEncContext *s) 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)); + // we can't clear the MVs as they might be needed by a B-frame s->last_mv[0][0][0] = s->last_mv[0][0][1] = s->last_mv[1][0][0] = @@ -77,7 +67,7 @@ void ff_mpeg4_clean_buffers(MpegEncContext *s) #define tab_size ((signed)FF_ARRAY_ELEMS(s->direct_scale_mv[0])) #define tab_bias (tab_size / 2) -// used by mpeg4 and rv10 decoder +// used by MPEG-4 and rv10 decoder void ff_mpeg4_init_direct_mv(MpegEncContext *s) { int i; diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 22d6d59..4a4995e 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -1,5 +1,5 @@ /* - * MPEG4 encoder/decoder internal header. + * MPEG-4 encoder/decoder internal header. * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2010 Michael Niedermayer * @@ -102,7 +102,7 @@ typedef struct Mpeg4DecContext { int cplx_estimation_trash_b; } Mpeg4DecContext; -/* dc encoding for mpeg4 */ +/* dc encoding for MPEG-4 */ extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; @@ -151,7 +151,6 @@ void ff_mpeg4_init_direct_mv(MpegEncContext *s); int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size); /** - * * @return the mb_type */ int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my); @@ -223,7 +222,7 @@ static inline int ff_mpeg4_pred_dc(MpegEncContext *s, int n, int level, } else { level += pred; ret = level; - if (s->err_recognition & AV_EF_BITSTREAM) { + if (s->avctx->err_recognition & AV_EF_BITSTREAM) { if (level < 0) { av_log(s->avctx, AV_LOG_ERROR, "dc<0 at %dx%d\n", s->mb_x, s->mb_y); diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index 246bb9c..e2203f9 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -1,5 +1,5 @@ /* - * MPEG4 Video frame extraction + * MPEG-4 video frame extraction * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2003 Michael Niedermayer * diff --git a/libavcodec/mpeg4video_parser.h b/libavcodec/mpeg4video_parser.h index 0f56e7f..030a276 100644 --- a/libavcodec/mpeg4video_parser.h +++ b/libavcodec/mpeg4video_parser.h @@ -1,5 +1,5 @@ /* - * MPEG4 video parser prototypes + * MPEG-4 video parser prototypes * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2003 Michael Niedermayer * diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 863dd29..efd0f22 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1,5 +1,5 @@ /* - * MPEG4 decoder. + * MPEG-4 decoder * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2010 Michael Niedermayer * @@ -25,8 +25,10 @@ #include "internal.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodata.h" #include "mpeg4video.h" #include "h263.h" +#include "profiles.h" #include "thread.h" #include "xvididct.h" @@ -49,6 +51,15 @@ static const int mb_type_b_map[4] = { MB_TYPE_L0 | MB_TYPE_16x16, }; +static inline int check_marker(AVCodecContext *avctx, GetBitContext *s, const char *msg) +{ + int bit = get_bits1(s); + if (!bit) + av_log(avctx, AV_LOG_INFO, "Marker bit missing %s\n", msg); + + return bit; +} + /** * Predict the ac. * @param n block index (0-3 are luma, 4-5 are chroma) @@ -175,6 +186,10 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g if (w <= 0 || h <= 0) return AVERROR_INVALIDDATA; + /* the decoder was not properly initialized and we cannot continue */ + if (sprite_trajectory.table == NULL) + return AVERROR_INVALIDDATA; + for (i = 0; i < ctx->num_sprite_warping_points; i++) { int length; int x = 0, y = 0; @@ -200,7 +215,7 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g while ((1 << alpha) < w) alpha++; while ((1 << beta) < h) - beta++; /* typo in the mpeg4 std for the definition of w' and h' */ + beta++; /* typo in the MPEG-4 std for the definition of w' and h' */ w2 = 1 << alpha; h2 = 1 << beta; @@ -223,7 +238,7 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g /* 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 + /* This is mostly identical to the MPEG-4 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 @@ -435,9 +450,9 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) while (get_bits1(&s->gb) != 0) time_incr++; - check_marker(&s->gb, "before time_increment in video packed header"); + check_marker(s->avctx, &s->gb, "before time_increment in video packed header"); skip_bits(&s->gb, ctx->time_increment_bits); /* time_increment */ - check_marker(&s->gb, "before vop_coding_type in video packed header"); + check_marker(s->avctx, &s->gb, "before vop_coding_type in video packed header"); skip_bits(&s->gb, 2); /* vop coding type */ // FIXME not rect stuff here @@ -563,7 +578,7 @@ static inline int mpeg4_decode_dc(MpegEncContext *s, int n, int *dir_ptr) if (code > 8) { if (get_bits1(&s->gb) == 0) { /* marker */ - if (s->err_recognition & AV_EF_BITSTREAM) { + if (s->avctx->err_recognition & AV_EF_BITSTREAM) { av_log(s->avctx, AV_LOG_ERROR, "dc marker bit missing\n"); return -1; } @@ -1099,7 +1114,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, level = level * qmul - qadd; if ((unsigned)(level + 2048) > 4095) { - if (s->err_recognition & AV_EF_BITSTREAM) { + if (s->avctx->err_recognition & AV_EF_BITSTREAM) { if (level > 2560 || level < -2560) { av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc, qp=%d\n", @@ -1417,7 +1432,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) ff_thread_await_progress(&s->next_picture_ptr->tf, s->mb_y, 0); } - /* if we skipped it in the future P Frame than skip it now too */ + /* 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) { @@ -1707,7 +1722,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) } } else { /* is setting low delay flag only once the smartest thing to do? - * low delay detection won't be overriden. */ + * low delay detection will not be overridden. */ if (s->picture_number == 0) s->low_delay = 0; } @@ -1720,25 +1735,24 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) skip_bits(gb, 4); /* video_object_layer_shape_extension */ } - check_marker(gb, "before time_increment_resolution"); + check_marker(s->avctx, gb, "before time_increment_resolution"); - s->avctx->time_base.den = get_bits(gb, 16); - if (!s->avctx->time_base.den) { - av_log(s->avctx, AV_LOG_ERROR, "time_base.den==0\n"); - s->avctx->time_base.num = 0; + s->avctx->framerate.num = get_bits(gb, 16); + if (!s->avctx->framerate.num) { + av_log(s->avctx, AV_LOG_ERROR, "framerate==0\n"); return -1; } - ctx->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1; + ctx->time_increment_bits = av_log2(s->avctx->framerate.num - 1) + 1; if (ctx->time_increment_bits < 1) ctx->time_increment_bits = 1; - check_marker(gb, "before fixed_vop_rate"); + check_marker(s->avctx, gb, "before fixed_vop_rate"); if (get_bits1(gb) != 0) /* fixed_vop_rate */ - s->avctx->time_base.num = get_bits(gb, ctx->time_increment_bits); + s->avctx->framerate.den = get_bits(gb, ctx->time_increment_bits); else - s->avctx->time_base.num = 1; + s->avctx->framerate.den = 1; ctx->t_frame = 0; @@ -1764,7 +1778,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) s->interlaced_dct = 0; if (!get_bits1(gb) && (s->avctx->debug & FF_DEBUG_PICT_INFO)) av_log(s->avctx, AV_LOG_INFO, /* OBMC Disable */ - "MPEG4 OBMC not supported (very likely buggy encoder)\n"); + "MPEG-4 OBMC not supported (very likely buggy encoder)\n"); if (vo_ver_id == 1) ctx->vol_sprite_usage = get_bits1(gb); /* vol_sprite_usage */ else @@ -1891,7 +1905,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_cae */ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* inter_cae */ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* no_update */ - ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* upampling */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* upsampling */ } if (!get_bits1(gb)) { ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_blocks */ @@ -1899,7 +1913,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* inter4v_blocks */ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* not coded blocks */ } - if (!check_marker(gb, "in complexity estimation part 1")) { + if (!check_marker(s->avctx, gb, "in complexity estimation part 1")) { skip_bits_long(gb, pos - get_bits_count(gb)); goto no_cplx_est; } @@ -1917,7 +1931,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel2 */ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel4 */ } - if (!check_marker(gb, "in complexity estimation part 2")) { + if (!check_marker(s->avctx, gb, "in complexity estimation part 2")) { skip_bits_long(gb, pos - get_bits_count(gb)); goto no_cplx_est; } @@ -2021,7 +2035,7 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb) s->divx_packed = e == 3 && last == 'p'; if (s->divx_packed && !ctx->showed_packed_warning) { av_log(s->avctx, AV_LOG_WARNING, - "Invalid and inefficient vfw-avi packed B frames detected\n"); + "Invalid and inefficient vfw-avi packed B-frames detected\n"); ctx->showed_packed_warning = 1; } } @@ -2048,8 +2062,7 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb) ctx->xvid_build = build; if (ctx->xvid_build == -1 && ctx->divx_version == -1 && ctx->lavc_build == -1) { - if (s->stream_codec_tag == AV_RL32("XVID") || - s->codec_tag == AV_RL32("XVID") || + if (s->codec_tag == AV_RL32("XVID") || s->codec_tag == AV_RL32("XVIX") || s->codec_tag == AV_RL32("RMP4") || s->codec_tag == AV_RL32("ZMP4") || @@ -2068,7 +2081,7 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb) } if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0) - ff_xvididct_init(&s->idsp, s->avctx); + ff_xvid_idct_init(&s->idsp, s->avctx); return 0; } @@ -2080,8 +2093,8 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* pict type: I = 0 , P = 1 */ if (s->pict_type == AV_PICTURE_TYPE_B && s->low_delay && - ctx->vol_control_parameters == 0 && !(s->flags & CODEC_FLAG_LOW_DELAY)) { - av_log(s->avctx, AV_LOG_ERROR, "low_delay flag incorrectly, clearing it\n"); + ctx->vol_control_parameters == 0 && !(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY)) { + av_log(s->avctx, AV_LOG_ERROR, "low_delay flag set incorrectly, clearing it\n"); s->low_delay = 0; } @@ -2095,13 +2108,11 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) while (get_bits1(gb) != 0) time_incr++; - check_marker(gb, "before time_increment"); + check_marker(s->avctx, gb, "before time_increment"); if (ctx->time_increment_bits == 0 || !(show_bits(gb, ctx->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"); - + /* Headers seem incomplete; try to guess time_increment_bits. */ for (ctx->time_increment_bits = 1; ctx->time_increment_bits < 16; ctx->time_increment_bits++) { @@ -2113,9 +2124,6 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) } else if ((show_bits(gb, ctx->time_increment_bits + 5) & 0x1F) == 0x18) break; } - - av_log(s->avctx, AV_LOG_ERROR, - "my guess is %d bits ;)\n", ctx->time_increment_bits); } if (IS_3IV1) @@ -2126,24 +2134,24 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) if (s->pict_type != AV_PICTURE_TYPE_B) { s->last_time_base = s->time_base; s->time_base += time_incr; - s->time = s->time_base * s->avctx->time_base.den + time_increment; + s->time = s->time_base * s->avctx->framerate.num + time_increment; if (s->workaround_bugs & FF_BUG_UMP4) { if (s->time < s->last_non_b_time) { /* header is not mpeg-4-compatible, broken encoder, * trying to workaround */ s->time_base++; - s->time += s->avctx->time_base.den; + s->time += s->avctx->framerate.num; } } 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->time = (s->last_time_base + time_incr) * s->avctx->framerate.num + time_increment; s->pb_time = s->pp_time - (s->last_non_b_time - s->time); if (s->pp_time <= s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time <= 0) { - /* messed up order, maybe after seeking? skipping current b-frame */ + /* messed up order, maybe after seeking? skipping current B-frame */ return FRAME_SKIPPED; } ff_mpeg4_init_direct_mv(s); @@ -2162,7 +2170,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) } } - check_marker(gb, "before vop_coded"); + check_marker(s->avctx, gb, "before vop_coded"); /* vop coded */ if (get_bits1(gb) != 1) { @@ -2242,7 +2250,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) 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"); + "Error, header damaged or not MPEG-4 header (qscale=0)\n"); return -1; // makes no sense to continue, as there is nothing left from the image then } @@ -2250,7 +2258,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) 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"); + "Error, header damaged or not MPEG-4 header (f_code=0)\n"); return -1; // makes no sense to continue, as there is nothing left from the image then } } else @@ -2290,7 +2298,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) } } /* detect buggy encoders which don't set the low_delay flag - * (divx4/xvid/opendivx). Note we cannot detect divx5 without b-frames + * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames * easily (although it's buggy too) */ if (s->vo_type == 0 && ctx->vol_control_parameters == 0 && ctx->divx_version == -1 && s->picture_number == 0) { @@ -2313,7 +2321,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) } /** - * Decode mpeg4 headers. + * Decode MPEG-4 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 @@ -2427,7 +2435,7 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) } end: - if (s->flags & CODEC_FLAG_LOW_DELAY) + if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) s->low_delay = 1; s->avctx->has_b_frames = !s->low_delay; @@ -2496,7 +2504,7 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size) Mpeg4DecContext *ctx = avctx->priv_data; MpegEncContext *s = &ctx->m; - /* divx 5.01+ bistream reorder stuff */ + /* divx 5.01+ bitstream reorder stuff */ if (s->divx_packed) { int current_pos = get_bits_count(&s->gb) >> 3; int startcode_found = 0; @@ -2522,7 +2530,7 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size) av_fast_malloc(&s->bitstream_buffer, &s->allocated_bitstream_buffer_size, buf_size - current_pos + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->bitstream_buffer) return AVERROR(ENOMEM); memcpy(s->bitstream_buffer, buf + current_pos, @@ -2547,7 +2555,7 @@ static int mpeg4_update_thread_context(AVCodecContext *dst, return ret; if (CONFIG_MPEG4_DECODER && !init && s1->xvid_build >= 0) - ff_xvididct_init(&s->m.idsp, dst); + ff_xvid_idct_init(&s->m.idsp, dst); s->shape = s1->shape; s->time_increment_bits = s1->time_increment_bits; @@ -2574,9 +2582,9 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!done) { done = 1; - ff_init_rl(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); - ff_init_rl(&ff_rvlc_rl_inter, ff_mpeg4_static_rl_table_store[1]); - ff_init_rl(&ff_rvlc_rl_intra, ff_mpeg4_static_rl_table_store[2]); + ff_rl_init(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); + ff_rl_init(&ff_rvlc_rl_inter, ff_mpeg4_static_rl_table_store[1]); + ff_rl_init(&ff_rvlc_rl_intra, ff_mpeg4_static_rl_table_store[2]); INIT_VLC_RL(ff_mpeg4_rl_intra, 554); INIT_VLC_RL(ff_rvlc_rl_inter, 1072); INIT_VLC_RL(ff_rvlc_rl_intra, 1072); @@ -2595,7 +2603,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } s->h263_pred = 1; - s->low_delay = 0; /* default, might be overriden in the vol header during header parsing */ + s->low_delay = 0; /* default, might be overridden in the vol header during header parsing */ s->decode_mb = mpeg4_decode_mb; ctx->time_increment_bits = 4; /* default value for broken headers */ @@ -2605,25 +2613,6 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static const AVProfile mpeg4_video_profiles[] = { - { FF_PROFILE_MPEG4_SIMPLE, "Simple Profile" }, - { FF_PROFILE_MPEG4_SIMPLE_SCALABLE, "Simple Scalable Profile" }, - { FF_PROFILE_MPEG4_CORE, "Core Profile" }, - { FF_PROFILE_MPEG4_MAIN, "Main Profile" }, - { FF_PROFILE_MPEG4_N_BIT, "N-bit Profile" }, - { FF_PROFILE_MPEG4_SCALABLE_TEXTURE, "Scalable Texture Profile" }, - { FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION, "Simple Face Animation Profile" }, - { FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE, "Basic Animated Texture Profile" }, - { FF_PROFILE_MPEG4_HYBRID, "Hybrid Profile" }, - { FF_PROFILE_MPEG4_ADVANCED_REAL_TIME, "Advanced Real Time Simple Profile" }, - { FF_PROFILE_MPEG4_CORE_SCALABLE, "Code Scalable Profile" }, - { FF_PROFILE_MPEG4_ADVANCED_CODING, "Advanced Coding Profile" }, - { FF_PROFILE_MPEG4_ADVANCED_CORE, "Advanced Core Profile" }, - { FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE, "Advanced Scalable Texture Profile" }, - { FF_PROFILE_MPEG4_SIMPLE_STUDIO, "Simple Studio Profile" }, - { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, "Advanced Simple Profile" }, -}; - AVCodec ff_mpeg4_decoder = { .name = "mpeg4", .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), @@ -2633,11 +2622,11 @@ AVCodec ff_mpeg4_decoder = { .init = decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | - CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, - .profiles = NULL_IF_CONFIG_SMALL(mpeg4_video_profiles), + .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context), }; diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index e9bc85f..8815ba8 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1,5 +1,5 @@ /* - * MPEG4 encoder. + * MPEG-4 encoder * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2010 Michael Niedermayer * @@ -29,7 +29,7 @@ #include "mpeg4video.h" /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC - * differences in mpeg4. Unified in the sense that the specification specifies + * differences in MPEG-4. Unified in the sense that the specification specifies * this encoding in several steps. */ static uint8_t uni_DCtab_lum_len[512]; static uint8_t uni_DCtab_chrom_len[512]; @@ -47,7 +47,7 @@ static uint8_t uni_mpeg4_inter_rl_len[64 * 64 * 2 * 2]; //#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 +/* MPEG-4 * inter * max level: 24/6 * max run: 53/63 @@ -120,7 +120,7 @@ static inline void restore_ac_coeffs(MpegEncContext *s, int16_t block[6][64], } /** - * Return the optimal value (0 or 1) for the ac_pred element for the given MB in mpeg4. + * Return the optimal value (0 or 1) for the ac_pred element for the given MB in MPEG-4. * This function will also update s->block_last_index and s->ac_val. * @param[in,out] block MB coefficients, these will be updated if 1 is returned * @param[in] dir ac prediction direction for each 8x8 block @@ -208,7 +208,7 @@ static inline int decide_ac_pred(MpegEncContext *s, int16_t block[6][64], } /** - * modify mb_type & qscale so that encoding is acually possible in mpeg4 + * modify mb_type & qscale so that encoding is actually possible in MPEG-4 */ void ff_clean_mpeg4_qscales(MpegEncContext *s) { @@ -220,7 +220,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s) if (s->pict_type == AV_PICTURE_TYPE_B) { int odd = 0; /* ok, come on, this isn't funny anymore, there's more code for - * handling this mpeg4 mess than for the actual adaptive quantization */ + * handling this MPEG-4 mess than for the actual adaptive quantization */ for (i = 0; i < s->mb_num; i++) { int mb_xy = s->mb_index2xy[i]; @@ -256,7 +256,6 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s) */ static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n) { -#if 1 /* DC will overflow if level is outside the [-255,255] range. */ level += 256; if (n < 4) { @@ -266,33 +265,6 @@ static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n) /* chrominance */ put_bits(s, uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level]); } -#else - int size, v; - /* find number of bits */ - size = 0; - v = abs(level); - while (v) { - v >>= 1; - size++; - } - - if (n < 4) { - /* luminance */ - put_bits(&s->pb, ff_mpeg4_DCtab_lum[size][1], ff_mpeg4_DCtab_lum[size][0]); - } else { - /* chrominance */ - put_bits(&s->pb, ff_mpeg4_DCtab_chrom[size][1], ff_mpeg4_DCtab_chrom[size][0]); - } - - /* encode remaining bits */ - if (size > 0) { - if (level < 0) - level = (-level) ^ ((1 << size) - 1); - put_bits(&s->pb, size, level); - if (size > 8) - put_bits(&s->pb, 1, 1); - } -#endif } static inline int mpeg4_get_dc_length(int level, int n) @@ -318,7 +290,7 @@ static inline void mpeg4_encode_block(MpegEncContext *s, 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 */ + /* MPEG-4 based DC predictor */ mpeg4_encode_dc(dc_pb, intra_dc, n); if (last_index < 1) return; @@ -378,7 +350,7 @@ static int mpeg4_get_block_length(MpegEncContext *s, int len = 0; if (s->mb_intra) { // Note gcc (3.2.1 at least) will optimize this away - /* mpeg4 based DC predictor */ + /* MPEG-4 based DC predictor */ len += mpeg4_get_dc_length(intra_dc, n); if (last_index < 1) return len; @@ -430,7 +402,7 @@ static inline void mpeg4_encode_blocks(MpegEncContext *s, int16_t block[6][64], int i; if (scan_table) { - if (s->flags2 & CODEC_FLAG2_NO_OUTPUT) { + if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { for (i = 0; i < 6; i++) skip_put_bits(&s->pb, mpeg4_get_block_length(s, block[i], i, @@ -442,7 +414,7 @@ static inline void mpeg4_encode_blocks(MpegEncContext *s, int16_t block[6][64], intra_dc[i], scan_table[i], dc_pb, ac_pb); } } else { - if (s->flags2 & CODEC_FLAG2_NO_OUTPUT) { + if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { for (i = 0; i < 6; i++) skip_put_bits(&s->pb, mpeg4_get_block_length(s, block[i], i, 0, @@ -507,7 +479,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], PutBitContext *const pb2 = s->data_partitioning ? &s->pb2 : &s->pb; PutBitContext *const tex_pb = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B ? &s->tex_pb : &s->pb; PutBitContext *const dc_pb = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_I ? &s->pb2 : &s->pb; - const int interleaved_stats = (s->flags & CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0; + const int interleaved_stats = (s->avctx->flags & AV_CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0; if (!s->mb_intra) { int i, cbp; @@ -529,7 +501,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], assert((s->dquant & 1) == 0); assert(mb_type >= 0); - /* nothing to do if this MB was skipped in the next P Frame */ + /* 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] = @@ -659,7 +631,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], 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 + /* 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) { @@ -822,7 +794,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], 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) { + if (s->avctx->flags & AV_CODEC_FLAG_AC_PRED) { s->ac_pred = decide_ac_pred(s, block, dir, scan_table, zigzag_last_index); } else { for (i = 0; i < 6; i++) @@ -876,7 +848,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], } /** - * add mpeg4 stuffing bits (01...1) + * add MPEG-4 stuffing bits (01...1) */ void ff_mpeg4_stuffing(PutBitContext *pbc) { @@ -923,7 +895,7 @@ static void mpeg4_encode_gop_header(MpegEncContext *s) 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, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)); put_bits(&s->pb, 1, 0); // broken link == NO s->last_time_base = time / s->avctx->time_base.den; @@ -1045,7 +1017,7 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, put_bits(&s->pb, 2, 0); /* 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)*/ + put_bits(&s->pb, 1, s->mpeg_quant); /* quant type = (0 = H.263 style) */ if (s->mpeg_quant) { ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); @@ -1069,21 +1041,21 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, ff_mpeg4_stuffing(&s->pb); /* user data */ - if (!(s->flags & CODEC_FLAG_BITEXACT)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) { put_bits(&s->pb, 16, 0); put_bits(&s->pb, 16, 0x1B2); /* user_data */ avpriv_put_string(&s->pb, LIBAVCODEC_IDENT, 0); } } -/* write mpeg4 VOP header */ +/* write MPEG-4 VOP header */ void ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number) { int time_incr; int time_div, time_mod; if (s->pict_type == AV_PICTURE_TYPE_I) { - if (!(s->flags & CODEC_FLAG_GLOBAL_HEADER)) { + if (!(s->avctx->flags & AV_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 @@ -1295,7 +1267,7 @@ static av_cold int encode_init(AVCodecContext *avctx) init_uni_dc_tab(); - ff_init_rl(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); + ff_rl_init(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len); init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len); @@ -1312,7 +1284,7 @@ static av_cold int encode_init(AVCodecContext *avctx) 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) { + if (s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { s->avctx->extradata = av_malloc(1024); init_put_bits(&s->pb, s->avctx->extradata, 1024); @@ -1404,6 +1376,6 @@ AVCodec ff_mpeg4_encoder = { .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .priv_class = &mpeg4enc_class, }; diff --git a/libavcodec/mpeg_er.c b/libavcodec/mpeg_er.c index 7a1b6b2..9410b27 100644 --- a/libavcodec/mpeg_er.c +++ b/libavcodec/mpeg_er.c @@ -57,3 +57,74 @@ void ff_mpeg_er_frame_start(MpegEncContext *s) ff_er_frame_start(er); } + +static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], int mb_x, int mb_y, + int mb_intra, int mb_skipped) +{ + MpegEncContext *s = opaque; + + s->mv_dir = mv_dir; + s->mv_type = mv_type; + s->mb_intra = mb_intra; + s->mb_skipped = mb_skipped; + s->mb_x = mb_x; + s->mb_y = mb_y; + memcpy(s->mv, mv, sizeof(*mv)); + + ff_init_block_index(s); + ff_update_block_index(s); + + s->bdsp.clear_blocks(s->block[0]); + + s->dest[0] = s->current_picture.f->data[0] + + s->mb_y * 16 * s->linesize + + s->mb_x * 16; + s->dest[1] = s->current_picture.f->data[1] + + s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize + + s->mb_x * (16 >> s->chroma_x_shift); + s->dest[2] = s->current_picture.f->data[2] + + s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize + + s->mb_x * (16 >> s->chroma_x_shift); + + if (ref) + av_log(s->avctx, AV_LOG_DEBUG, + "Interlaced error concealment is not fully implemented\n"); + ff_mpv_decode_mb(s, s->block); +} + +int ff_mpeg_er_init(MpegEncContext *s) +{ + ERContext *er = &s->er; + int mb_array_size = s->mb_height * s->mb_stride; + int i; + + er->avctx = s->avctx; + + er->mb_index2xy = s->mb_index2xy; + er->mb_num = s->mb_num; + er->mb_width = s->mb_width; + er->mb_height = s->mb_height; + er->mb_stride = s->mb_stride; + er->b8_stride = s->b8_stride; + + er->er_temp_buffer = av_malloc(s->mb_height * s->mb_stride); + er->error_status_table = av_mallocz(mb_array_size); + if (!er->er_temp_buffer || !er->error_status_table) + goto fail; + + er->mbskip_table = s->mbskip_table; + er->mbintra_table = s->mbintra_table; + + for (i = 0; i < FF_ARRAY_ELEMS(s->dc_val); i++) + er->dc_val[i] = s->dc_val[i]; + + er->decode_mb = mpeg_er_decode_mb; + er->opaque = s; + + return 0; +fail: + av_freep(&er->er_temp_buffer); + av_freep(&er->error_status_table); + return AVERROR(ENOMEM); +} diff --git a/libavcodec/mpeg_er.h b/libavcodec/mpeg_er.h index 1968184..ca1ea90 100644 --- a/libavcodec/mpeg_er.h +++ b/libavcodec/mpeg_er.h @@ -21,6 +21,7 @@ #include "mpegvideo.h" +int ff_mpeg_er_init(MpegEncContext *s); void ff_mpeg_er_frame_start(MpegEncContext *s); #endif /* AVCODEC_MPEG_ER_H */ diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c index 58ea452..c44c024 100644 --- a/libavcodec/mpegaudio_parser.c +++ b/libavcodec/mpegaudio_parser.c @@ -63,10 +63,11 @@ static int mpegaudio_parse(AVCodecParserContext *s1, }else{ while(icodec_id; state= (state<<8) + buf[i++]; - ret = avpriv_mpa_decode_header(avctx, state, &sr, &channels, &frame_size, &bit_rate); + ret = ff_mpa_decode_header(avctx, state, &sr, &channels, &frame_size, &bit_rate); if (ret < 4) { if (i > 4) s->header_count = -2; @@ -86,6 +87,16 @@ static int mpegaudio_parse(AVCodecParserContext *s1, avctx->bit_rate += (bit_rate - avctx->bit_rate) / s->header_count; } } + + if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) { + s->frame_size = 0; + next = buf_size; + } else if (codec_id == AV_CODEC_ID_MP3ADU) { + avpriv_report_missing_feature(avctx, + "MP3ADU full parser"); + return AVERROR_PATCHWELCOME; + } + break; } } @@ -106,7 +117,7 @@ static int mpegaudio_parse(AVCodecParserContext *s1, AVCodecParser ff_mpegaudio_parser = { - .codec_ids = { AV_CODEC_ID_MP1, AV_CODEC_ID_MP2, AV_CODEC_ID_MP3 }, + .codec_ids = { AV_CODEC_ID_MP1, AV_CODEC_ID_MP2, AV_CODEC_ID_MP3, AV_CODEC_ID_MP3ADU }, .priv_data_size = sizeof(MpegAudioParseContext), .parser_parse = mpegaudio_parse, .parser_close = ff_parse_close, diff --git a/libavcodec/mpegaudiodec_fixed.c b/libavcodec/mpegaudiodec_fixed.c index 6f21b0c..2db1e18 100644 --- a/libavcodec/mpegaudiodec_fixed.c +++ b/libavcodec/mpegaudiodec_fixed.c @@ -47,7 +47,7 @@ AVCodec ff_mp1_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, @@ -63,7 +63,7 @@ AVCodec ff_mp2_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, @@ -79,7 +79,7 @@ AVCodec ff_mp3_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, @@ -95,7 +95,7 @@ AVCodec ff_mp3adu_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame_adu, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, @@ -112,7 +112,7 @@ AVCodec ff_mp3on4_decoder = { .init = decode_init_mp3on4, .close = decode_close_mp3on4, .decode = decode_frame_mp3on4, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush_mp3on4, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/mpegaudiodec_float.c b/libavcodec/mpegaudiodec_float.c index 3a76055..7bdfd90 100644 --- a/libavcodec/mpegaudiodec_float.c +++ b/libavcodec/mpegaudiodec_float.c @@ -47,7 +47,7 @@ AVCodec ff_mp1float_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, @@ -63,7 +63,7 @@ AVCodec ff_mp2float_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, @@ -79,7 +79,7 @@ AVCodec ff_mp3float_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, @@ -95,7 +95,7 @@ AVCodec ff_mp3adufloat_decoder = { .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame_adu, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, @@ -112,7 +112,7 @@ AVCodec ff_mp3on4float_decoder = { .init = decode_init_mp3on4, .close = decode_close_mp3on4, .decode = decode_frame_mp3on4, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = flush_mp3on4, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c index e9c7850..9bfba6f 100644 --- a/libavcodec/mpegaudiodec_template.c +++ b/libavcodec/mpegaudiodec_template.c @@ -70,6 +70,7 @@ typedef struct MPADecodeContext { MPA_DECODE_HEADER uint8_t last_buf[LAST_BUF_SIZE]; int last_buf_size; + int extrasize; /* next header (used in free format parsing) */ uint32_t free_format_next_header; GetBitContext gb; @@ -273,7 +274,7 @@ static av_cold void decode_init_static(void) scale_factor_mult[i][0] = MULLx(norm, FIXR(1.0 * 2.0), FRAC_BITS); scale_factor_mult[i][1] = MULLx(norm, FIXR(0.7937005259 * 2.0), FRAC_BITS); scale_factor_mult[i][2] = MULLx(norm, FIXR(0.6299605249 * 2.0), FRAC_BITS); - av_dlog(NULL, "%d: norm=%x s=%x %x %x\n", i, norm, + ff_dlog(NULL, "%d: norm=%x s=%x %x %x\n", i, norm, scale_factor_mult[i][0], scale_factor_mult[i][1], scale_factor_mult[i][2]); @@ -375,7 +376,7 @@ static av_cold void decode_init_static(void) k = i & 1; is_table_lsf[j][k ^ 1][i] = FIXR(f); is_table_lsf[j][k ][i] = FIXR(1.0); - av_dlog(NULL, "is_table_lsf %d %d: %f %f\n", + ff_dlog(NULL, "is_table_lsf %d %d: %f %f\n", i, j, (float) is_table_lsf[j][0][i], (float) is_table_lsf[j][1][i]); } @@ -412,7 +413,7 @@ static av_cold int decode_init(AVCodecContext * avctx) s->avctx = avctx; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); ff_mpadsp_init(&s->mpadsp); if (avctx->request_sample_fmt == OUT_FMT && @@ -563,7 +564,7 @@ static int mp_decode_layer2(MPADecodeContext *s) else bound = sblimit; - av_dlog(s->avctx, "bound=%d sblimit=%d\n", bound, sblimit); + ff_dlog(s->avctx, "bound=%d sblimit=%d\n", bound, sblimit); /* sanity check */ if (bound > sblimit) @@ -795,19 +796,13 @@ static void exponents_from_scale_factors(MPADecodeContext *s, GranuleDef *g, } } -/* handle n = 0 too */ -static inline int get_bitsz(GetBitContext *s, int n) -{ - return n ? get_bits(s, n) : 0; -} - - static void switch_buffer(MPADecodeContext *s, int *pos, int *end_pos, int *end_pos2) { - if (s->in_gb.buffer && *pos >= s->gb.size_in_bits) { + if (s->in_gb.buffer && *pos >= s->gb.size_in_bits - s->extrasize * 8) { s->gb = s->in_gb; s->in_gb.buffer = NULL; + s->extrasize = 0; assert((get_bits_count(&s->gb) & 7) == 0); skip_bits_long(&s->gb, *pos - *end_pos); *end_pos2 = @@ -839,7 +834,7 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g, int i; int last_pos, bits_left; VLC *vlc; - int end_pos = FFMIN(end_pos2, s->gb.size_in_bits); + int end_pos = FFMIN(end_pos2, s->gb.size_in_bits - s->extrasize * 8); /* low frequencies (called big values) */ s_index = 0; @@ -882,7 +877,7 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g, exponent= exponents[s_index]; - av_dlog(s->avctx, "region=%d n=%d x=%d y=%d exp=%d\n", + ff_dlog(s->avctx, "region=%d n=%d x=%d y=%d exp=%d\n", i, g->region_size[i] - j, x, y, exponent); if (y & 16) { x = y >> 5; @@ -948,7 +943,7 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g, last_pos = pos; code = get_vlc2(&s->gb, vlc->table, vlc->bits, 1); - av_dlog(s->avctx, "t=%d code=%d\n", g->count1table_select, code); + ff_dlog(s->avctx, "t=%d code=%d\n", g->count1table_select, code); g->sb_hybrid[s_index+0] = g->sb_hybrid[s_index+1] = g->sb_hybrid[s_index+2] = @@ -1300,7 +1295,7 @@ static int mp_decode_layer3(MPADecodeContext *s) for (gr = 0; gr < nb_granules; gr++) { for (ch = 0; ch < s->nb_channels; ch++) { - av_dlog(s->avctx, "gr=%d ch=%d: side_info\n", gr, ch); + ff_dlog(s->avctx, "gr=%d ch=%d: side_info\n", gr, ch); g = &s->granules[ch][gr]; g->part2_3_length = get_bits(&s->gb, 12); g->big_values = get_bits(&s->gb, 9); @@ -1341,7 +1336,7 @@ static int mp_decode_layer3(MPADecodeContext *s) /* compute huffman coded region sizes */ region_address1 = get_bits(&s->gb, 4); region_address2 = get_bits(&s->gb, 3); - av_dlog(s->avctx, "region1=%d region2=%d\n", + ff_dlog(s->avctx, "region1=%d region2=%d\n", region_address1, region_address2); init_long_region(s, g, region_address1, region_address2); } @@ -1353,7 +1348,7 @@ static int mp_decode_layer3(MPADecodeContext *s) g->preflag = get_bits1(&s->gb); g->scalefac_scale = get_bits1(&s->gb); g->count1table_select = get_bits1(&s->gb); - av_dlog(s->avctx, "block_type=%d switch_point=%d\n", + ff_dlog(s->avctx, "block_type=%d switch_point=%d\n", g->block_type, g->switch_point); } } @@ -1361,19 +1356,16 @@ static int mp_decode_layer3(MPADecodeContext *s) if (!s->adu_mode) { int skip; const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3); - int extrasize = av_clip(get_bits_left(&s->gb) >> 3, 0, - FFMAX(0, LAST_BUF_SIZE - s->last_buf_size)); + s->extrasize = av_clip((get_bits_left(&s->gb) >> 3) - s->extrasize, 0, + FFMAX(0, LAST_BUF_SIZE - s->last_buf_size)); assert((get_bits_count(&s->gb) & 7) == 0); /* now we get bits from the main_data_begin offset */ - av_dlog(s->avctx, "seekback:%d, lastbuf:%d\n", + ff_dlog(s->avctx, "seekback:%d, lastbuf:%d\n", main_data_begin, s->last_buf_size); - memcpy(s->last_buf + s->last_buf_size, ptr, extrasize); + memcpy(s->last_buf + s->last_buf_size, ptr, s->extrasize); s->in_gb = s->gb; - init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8); -#if !UNCHECKED_BITSTREAM_READER - s->gb.size_in_bits_plus8 += extrasize * 8; -#endif + init_get_bits(&s->gb, s->last_buf, (s->last_buf_size + s->extrasize) * 8); s->last_buf_size <<= 3; for (gr = 0; gr < nb_granules && (s->last_buf_size >> 3) < main_data_begin; gr++) { for (ch = 0; ch < s->nb_channels; ch++) { @@ -1384,15 +1376,17 @@ static int mp_decode_layer3(MPADecodeContext *s) } } skip = s->last_buf_size - 8 * main_data_begin; - if (skip >= s->gb.size_in_bits && s->in_gb.buffer) { - skip_bits_long(&s->in_gb, skip - s->gb.size_in_bits); + if (skip >= s->gb.size_in_bits - s->extrasize * 8 && s->in_gb.buffer) { + skip_bits_long(&s->in_gb, skip - s->gb.size_in_bits + s->extrasize * 8); s->gb = s->in_gb; s->in_gb.buffer = NULL; + s->extrasize = 0; } else { skip_bits_long(&s->gb, skip); } } else { gr = 0; + s->extrasize = 0; } for (; gr < nb_granules; gr++) { @@ -1404,10 +1398,10 @@ static int mp_decode_layer3(MPADecodeContext *s) uint8_t *sc; int slen, slen1, slen2; - /* MPEG1 scale factors */ + /* MPEG-1 scale factors */ slen1 = slen_table[0][g->scalefac_compress]; slen2 = slen_table[1][g->scalefac_compress]; - av_dlog(s->avctx, "slen1=%d slen2=%d\n", slen1, slen2); + ff_dlog(s->avctx, "slen1=%d slen2=%d\n", slen1, slen2); if (g->block_type == 2) { n = g->switch_point ? 17 : 18; j = 0; @@ -1560,7 +1554,7 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples, s->last_buf_size=0; if (s->in_gb.buffer) { align_get_bits(&s->gb); - i = get_bits_left(&s->gb)>>3; + i = (get_bits_left(&s->gb) >> 3) - s->extrasize; 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; @@ -1568,12 +1562,12 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples, av_log(s->avctx, AV_LOG_ERROR, "invalid old backstep %d\n", i); s->gb = s->in_gb; s->in_gb.buffer = NULL; + s->extrasize = 0; } align_get_bits(&s->gb); assert((get_bits_count(&s->gb) & 7) == 0); - i = get_bits_left(&s->gb) >> 3; - + i = (get_bits_left(&s->gb) >> 3) - s->extrasize; if (i < 0 || i > BACKSTEP_SIZE || nb_frames < 0) { if (i < 0) av_log(s->avctx, AV_LOG_ERROR, "invalid new backstep %d\n", i); @@ -1631,12 +1625,12 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, return AVERROR_INVALIDDATA; header = AV_RB32(buf); - if (ff_mpa_check_header(header) < 0) { + + ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Header missing\n"); return AVERROR_INVALIDDATA; - } - - if (avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) { + } else if (ret == 1) { /* free format: prepare to compute frame size */ s->frame_size = -1; return AVERROR_INVALIDDATA; @@ -1647,13 +1641,6 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, if (!avctx->bit_rate) avctx->bit_rate = s->bit_rate; - if (s->frame_size <= 0 || s->frame_size > buf_size) { - av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); - return AVERROR_INVALIDDATA; - } else if (s->frame_size < buf_size) { - buf_size= s->frame_size; - } - s->frame = data; ret = mp_decode_frame(s, NULL, buf, buf_size); @@ -1713,12 +1700,11 @@ static int decode_frame_adu(AVCodecContext *avctx, void *data, // Get header and restore sync word header = AV_RB32(buf) | 0xffe00000; - if (ff_mpa_check_header(header) < 0) { // Bad header, discard frame + ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n"); - return AVERROR_INVALIDDATA; + return ret; } - - avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header); /* update codec info */ avctx->sample_rate = s->sample_rate; avctx->channels = s->nb_channels; @@ -1910,11 +1896,10 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, } header = (AV_RB32(buf) & 0x000fffff) | s->syncword; // patch header - if (ff_mpa_check_header(header) < 0) // Bad header, discard block + ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)m, header); + if (ret < 0) // Bad header, discard block break; - avpriv_mpegaudio_decode_header((MPADecodeHeader *)m, header); - if (ch + m->nb_channels > avctx->channels || s->coff[fr] + m->nb_channels > avctx->channels) { av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec " diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index 25e7319..a315965 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -27,6 +27,7 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "internal.h" #include "mpegaudio.h" #include "mpegaudiodata.h" #include "mpegaudiodecheader.h" @@ -36,6 +37,12 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) { int sample_rate, frame_size, mpeg25, padding; int sample_rate_index, bitrate_index; + int ret; + + ret = ff_mpa_check_header(header); + if (ret < 0) + return ret; + if (header & (1<<20)) { s->lsf = (header & (1<<19)) ? 0 : 1; mpeg25 = 0; @@ -94,31 +101,29 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) } #if defined(DEBUG) - av_dlog(NULL, "layer%d, %d Hz, %d kbits/s, ", + ff_dlog(NULL, "layer%d, %d Hz, %d kbits/s, ", s->layer, s->sample_rate, s->bit_rate); if (s->nb_channels == 2) { if (s->layer == 3) { if (s->mode_ext & MODE_EXT_MS_STEREO) - av_dlog(NULL, "ms-"); + ff_dlog(NULL, "ms-"); if (s->mode_ext & MODE_EXT_I_STEREO) - av_dlog(NULL, "i-"); + ff_dlog(NULL, "i-"); } - av_dlog(NULL, "stereo"); + ff_dlog(NULL, "stereo"); } else { - av_dlog(NULL, "mono"); + ff_dlog(NULL, "mono"); } - av_dlog(NULL, "\n"); + ff_dlog(NULL, "\n"); #endif return 0; } -int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) +int ff_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, + int *channels, int *frame_size, int *bit_rate) { MPADecodeHeader s1, *s = &s1; - if (ff_mpa_check_header(head) != 0) - return -1; - if (avpriv_mpegaudio_decode_header(s, head) != 0) { return -1; } @@ -134,7 +139,8 @@ int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_r break; default: case 3: - avctx->codec_id = AV_CODEC_ID_MP3; + if (avctx->codec_id != AV_CODEC_ID_MP3ADU) + avctx->codec_id = AV_CODEC_ID_MP3; if (s->lsf) *frame_size = 576; else @@ -147,3 +153,10 @@ int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_r *bit_rate = s->bit_rate; return s->frame_size; } + +#if LIBAVCODEC_VERSION_MAJOR < 57 +int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) +{ + return ff_mpa_decode_header(avctx, head, sample_rate, channels, frame_size, bit_rate); +} +#endif diff --git a/libavcodec/mpegaudiodecheader.h b/libavcodec/mpegaudiodecheader.h index 764e8ab..089a508 100644 --- a/libavcodec/mpegaudiodecheader.h +++ b/libavcodec/mpegaudiodecheader.h @@ -52,9 +52,14 @@ typedef struct MPADecodeHeader { that the frame size must be computed externally */ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header); -/* useful helper to get mpeg audio stream infos. Return -1 if error in +/* useful helper to get MPEG audio stream info. Return -1 if error in header, otherwise the coded frame size in bytes */ +int ff_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, + int *channels, int *frame_size, int *bitrate); + +#if LIBAVCODEC_VERSION_MAJOR < 57 int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bitrate); +#endif /* fast header check for resync */ static inline int ff_mpa_check_header(uint32_t header){ diff --git a/libavcodec/mpegaudioenc.c b/libavcodec/mpegaudioenc.c index 51a6f5b..2be8b7f 100644 --- a/libavcodec/mpegaudioenc.c +++ b/libavcodec/mpegaudioenc.c @@ -84,7 +84,7 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) bitrate = bitrate / 1000; s->nb_channels = channels; avctx->frame_size = MPA_FRAME_SIZE; - avctx->delay = 512 - 32 + 1; + avctx->initial_padding = 512 - 32 + 1; /* encoding freq */ s->lsf = 0; @@ -129,7 +129,7 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) s->sblimit = ff_mpa_sblimit_table[table]; s->alloc_table = ff_mpa_alloc_tables[table]; - av_dlog(avctx, "%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n", + ff_dlog(avctx, "%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n", bitrate, freq, s->frame_size, table, s->frame_frac_incr); for(i=0;inb_channels;i++) @@ -394,7 +394,7 @@ static void compute_scale_factors(MpegAudioContext *s, index = 62; /* value 63 is not allowed */ } - av_dlog(NULL, "%2d:%d in=%x %x %d\n", + ff_dlog(NULL, "%2d:%d in=%x %x %d\n", j, i, vmax, s->scale_factor_table[index], index); /* store the scale factor */ assert(index >=0 && index <= 63); @@ -463,7 +463,7 @@ static void compute_scale_factors(MpegAudioContext *s, code = 0; /* kill warning */ } - av_dlog(NULL, "%d: %2d %2d %2d %d %d -> %d\n", j, + ff_dlog(NULL, "%d: %2d %2d %2d %d %d -> %d\n", j, sf[0], sf[1], sf[2], d1, d2, code); scale_code[j] = code; sf += 3; @@ -540,7 +540,7 @@ static void compute_bit_allocation(MpegAudioContext *s, } if (max_sb < 0) break; - av_dlog(NULL, "current=%d max=%d max_sb=%d max_ch=%d alloc=%d\n", + ff_dlog(NULL, "current=%d max=%d max_sb=%d max_ch=%d alloc=%d\n", current_frame_size, max_frame_size, max_sb, max_ch, bit_alloc[max_ch][max_sb]); @@ -583,7 +583,7 @@ static void compute_bit_allocation(MpegAudioContext *s, } /* - * Output the mpeg audio layer 2 frame. Note how the code is small + * Output the MPEG audio layer 2 frame. Note how the code is small * compared to other encoders :-) */ static void encode_frame(MpegAudioContext *s, @@ -598,7 +598,7 @@ static void encode_frame(MpegAudioContext *s, /* header */ put_bits(p, 12, 0xfff); - put_bits(p, 1, 1 - s->lsf); /* 1 = mpeg1 ID, 0 = mpeg2 lsf ID */ + put_bits(p, 1, 1 - s->lsf); /* 1 = MPEG-1 ID, 0 = MPEG-2 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); @@ -735,7 +735,7 @@ static int MPA_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, encode_frame(s, bit_alloc, padding); if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); avpkt->size = put_bits_count(&s->pb) / 8; *got_packet_ptr = 1; diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c new file mode 100644 index 0000000..1d9544b --- /dev/null +++ b/libavcodec/mpegpicture.c @@ -0,0 +1,427 @@ +/* + * Mpeg video formats-related picture management functions + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +#include "avcodec.h" +#include "motion_est.h" +#include "mpegpicture.h" +#include "mpegutils.h" + +static int make_tables_writable(Picture *pic) +{ + int ret, i; +#define MAKE_WRITABLE(table) \ +do {\ + if (pic->table &&\ + (ret = av_buffer_make_writable(&pic->table)) < 0)\ + return ret;\ +} while (0) + + MAKE_WRITABLE(mb_var_buf); + MAKE_WRITABLE(mc_mb_var_buf); + MAKE_WRITABLE(mb_mean_buf); + MAKE_WRITABLE(mbskip_table_buf); + MAKE_WRITABLE(qscale_table_buf); + MAKE_WRITABLE(mb_type_buf); + + for (i = 0; i < 2; i++) { + MAKE_WRITABLE(motion_val_buf[i]); + MAKE_WRITABLE(ref_index_buf[i]); + } + + return 0; +} + +int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, + ScratchpadContext *sc, int linesize) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); + + // edge emu needs blocksize + filter length - 1 + // (= 17x17 for halfpel / 21x21 for H.264) + // VC-1 computes luma and chroma simultaneously and needs 19X19 + 9x9 + // at uvlinesize. It supports only YUV420 so 24x24 is enough + // linesize * interlaced * MBsize + FF_ALLOCZ_OR_GOTO(avctx, sc->edge_emu_buffer, alloc_size * 2 * 24, + fail); + + FF_ALLOCZ_OR_GOTO(avctx, me->scratchpad, alloc_size * 2 * 16 * 3, + fail) + me->temp = me->scratchpad; + sc->rd_scratchpad = me->scratchpad; + sc->b_scratchpad = me->scratchpad; + sc->obmc_scratchpad = me->scratchpad + 16; + + return 0; +fail: + av_freep(&sc->edge_emu_buffer); + return AVERROR(ENOMEM); +} + +/** + * Allocate a frame buffer + */ +static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic, + MotionEstContext *me, ScratchpadContext *sc, + int chroma_x_shift, int chroma_y_shift, + int linesize, int uvlinesize) +{ + int edges_needed = av_codec_is_encoder(avctx->codec); + int r, ret; + + pic->tf.f = pic->f; + if (avctx->codec_id != AV_CODEC_ID_WMV3IMAGE && + avctx->codec_id != AV_CODEC_ID_VC1IMAGE && + avctx->codec_id != AV_CODEC_ID_MSS2) { + if (edges_needed) { + pic->f->width = avctx->width + 2 * EDGE_WIDTH; + pic->f->height = avctx->height + 2 * EDGE_WIDTH; + } + + r = ff_thread_get_buffer(avctx, &pic->tf, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + } else { + pic->f->width = avctx->width; + pic->f->height = avctx->height; + pic->f->format = avctx->pix_fmt; + r = avcodec_default_get_buffer2(avctx, pic->f, 0); + } + + if (r < 0 || !pic->f->buf[0]) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed (%d %p)\n", + r, pic->f->data[0]); + return -1; + } + + if (edges_needed) { + int i; + for (i = 0; pic->f->data[i]; i++) { + int offset = (EDGE_WIDTH >> (i ? chroma_y_shift : 0)) * + pic->f->linesize[i] + + (EDGE_WIDTH >> (i ? chroma_x_shift : 0)); + pic->f->data[i] += offset; + } + pic->f->width = avctx->width; + pic->f->height = avctx->height; + } + + if (avctx->hwaccel) { + assert(!pic->hwaccel_picture_private); + if (avctx->hwaccel->frame_priv_data_size) { + pic->hwaccel_priv_buf = av_buffer_allocz(avctx->hwaccel->frame_priv_data_size); + if (!pic->hwaccel_priv_buf) { + av_log(avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n"); + return -1; + } + pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; + } + } + + if (linesize && (linesize != pic->f->linesize[0] || + uvlinesize != pic->f->linesize[1])) { + av_log(avctx, AV_LOG_ERROR, + "get_buffer() failed (stride changed)\n"); + ff_mpeg_unref_picture(avctx, pic); + return -1; + } + + if (pic->f->linesize[1] != pic->f->linesize[2]) { + av_log(avctx, AV_LOG_ERROR, + "get_buffer() failed (uv stride mismatch)\n"); + ff_mpeg_unref_picture(avctx, pic); + return -1; + } + + if (!sc->edge_emu_buffer && + (ret = ff_mpeg_framesize_alloc(avctx, me, sc, + pic->f->linesize[0])) < 0) { + av_log(avctx, AV_LOG_ERROR, + "get_buffer() failed to allocate context scratch buffers.\n"); + ff_mpeg_unref_picture(avctx, pic); + return ret; + } + + return 0; +} + +static int alloc_picture_tables(Picture *pic, int encoding, int out_format, + int mb_stride, int mb_height, int b8_stride) +{ + const int big_mb_num = mb_stride * (mb_height + 1) + 1; + const int mb_array_size = mb_stride * mb_height; + const int b8_array_size = b8_stride * mb_height * 2; + int i; + + + pic->mbskip_table_buf = av_buffer_allocz(mb_array_size + 2); + pic->qscale_table_buf = av_buffer_allocz(big_mb_num + mb_stride); + pic->mb_type_buf = av_buffer_allocz((big_mb_num + mb_stride) * + sizeof(uint32_t)); + if (!pic->mbskip_table_buf || !pic->qscale_table_buf || !pic->mb_type_buf) + return AVERROR(ENOMEM); + + if (encoding) { + pic->mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mc_mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mb_mean_buf = av_buffer_allocz(mb_array_size); + if (!pic->mb_var_buf || !pic->mc_mb_var_buf || !pic->mb_mean_buf) + return AVERROR(ENOMEM); + } + + if (out_format == FMT_H263 || encoding) { + int mv_size = 2 * (b8_array_size + 4) * sizeof(int16_t); + int ref_index_size = 4 * mb_array_size; + + for (i = 0; mv_size && i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_allocz(mv_size); + pic->ref_index_buf[i] = av_buffer_allocz(ref_index_size); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) + return AVERROR(ENOMEM); + } + } + + return 0; +} + +/** + * Allocate a Picture. + * The pixels are allocated/set by calling get_buffer() if shared = 0 + */ +int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me, + ScratchpadContext *sc, int shared, int encoding, + int chroma_x_shift, int chroma_y_shift, int out_format, + int mb_stride, int mb_height, int b8_stride, + ptrdiff_t *linesize, ptrdiff_t *uvlinesize) +{ + int i, ret; + + if (shared) { + assert(pic->f->data[0]); + pic->shared = 1; + } else { + assert(!pic->f->buf[0]); + if (alloc_frame_buffer(avctx, pic, me, sc, + chroma_x_shift, chroma_y_shift, + *linesize, *uvlinesize) < 0) + return -1; + + *linesize = pic->f->linesize[0]; + *uvlinesize = pic->f->linesize[1]; + } + + if (!pic->qscale_table_buf) + ret = alloc_picture_tables(pic, encoding, out_format, + mb_stride, mb_height, b8_stride); + else + ret = make_tables_writable(pic); + if (ret < 0) + goto fail; + + if (encoding) { + pic->mb_var = (uint16_t*)pic->mb_var_buf->data; + pic->mc_mb_var = (uint16_t*)pic->mc_mb_var_buf->data; + pic->mb_mean = pic->mb_mean_buf->data; + } + + pic->mbskip_table = pic->mbskip_table_buf->data; + pic->qscale_table = pic->qscale_table_buf->data + 2 * mb_stride + 1; + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * mb_stride + 1; + + if (pic->motion_val_buf[0]) { + for (i = 0; i < 2; i++) { + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + } + + return 0; +fail: + av_log(avctx, AV_LOG_ERROR, "Error allocating a picture.\n"); + ff_mpeg_unref_picture(avctx, pic); + ff_free_picture_tables(pic); + return AVERROR(ENOMEM); +} + +/** + * Deallocate a picture. + */ +void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *pic) +{ + pic->tf.f = pic->f; + /* WM Image / Screen codecs allocate internal buffers with different + * dimensions / colorspaces; ignore user-defined callbacks for these. */ + if (avctx->codec_id != AV_CODEC_ID_WMV3IMAGE && + avctx->codec_id != AV_CODEC_ID_VC1IMAGE && + avctx->codec_id != AV_CODEC_ID_MSS2) + ff_thread_release_buffer(avctx, &pic->tf); + else if (pic->f) + av_frame_unref(pic->f); + + av_buffer_unref(&pic->hwaccel_priv_buf); + + if (pic->needs_realloc) + ff_free_picture_tables(pic); +} + +int ff_update_picture_tables(Picture *dst, Picture *src) +{ + int i; + +#define UPDATE_TABLE(table) \ +do { \ + if (src->table && \ + (!dst->table || dst->table->buffer != src->table->buffer)) { \ + av_buffer_unref(&dst->table); \ + dst->table = av_buffer_ref(src->table); \ + if (!dst->table) { \ + ff_free_picture_tables(dst); \ + return AVERROR(ENOMEM); \ + } \ + } \ +} while (0) + + UPDATE_TABLE(mb_var_buf); + UPDATE_TABLE(mc_mb_var_buf); + UPDATE_TABLE(mb_mean_buf); + UPDATE_TABLE(mbskip_table_buf); + UPDATE_TABLE(qscale_table_buf); + UPDATE_TABLE(mb_type_buf); + for (i = 0; i < 2; i++) { + UPDATE_TABLE(motion_val_buf[i]); + UPDATE_TABLE(ref_index_buf[i]); + } + + dst->mb_var = src->mb_var; + dst->mc_mb_var = src->mc_mb_var; + dst->mb_mean = src->mb_mean; + dst->mbskip_table = src->mbskip_table; + dst->qscale_table = src->qscale_table; + dst->mb_type = src->mb_type; + for (i = 0; i < 2; i++) { + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + return 0; +} + +int ff_mpeg_ref_picture(AVCodecContext *avctx, Picture *dst, Picture *src) +{ + int ret; + + av_assert0(!dst->f->buf[0]); + av_assert0(src->f->buf[0]); + + src->tf.f = src->f; + dst->tf.f = dst->f; + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + ret = ff_update_picture_tables(dst, src); + if (ret < 0) + goto fail; + + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + dst->field_picture = src->field_picture; + dst->mb_var_sum = src->mb_var_sum; + dst->mc_mb_var_sum = src->mc_mb_var_sum; + dst->b_frame_score = src->b_frame_score; + dst->needs_realloc = src->needs_realloc; + dst->reference = src->reference; + dst->shared = src->shared; + + memcpy(dst->encoding_error, src->encoding_error, + sizeof(dst->encoding_error)); + + return 0; +fail: + ff_mpeg_unref_picture(avctx, dst); + return ret; +} + +static inline int pic_is_unused(Picture *pic) +{ + if (!pic->f->buf[0]) + return 1; + if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) + return 1; + return 0; +} + +static int find_unused_picture(Picture *picture, int shared) +{ + int i; + + if (shared) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!picture[i].f->buf[0]) + return i; + } + } else { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (pic_is_unused(&picture[i])) + return i; + } + } + + return AVERROR_INVALIDDATA; +} + +int ff_find_unused_picture(AVCodecContext *avctx, Picture *picture, int shared) +{ + int ret = find_unused_picture(picture, shared); + + if (ret >= 0 && ret < MAX_PICTURE_COUNT) { + if (picture[ret].needs_realloc) { + picture[ret].needs_realloc = 0; + ff_free_picture_tables(&picture[ret]); + ff_mpeg_unref_picture(avctx, &picture[ret]); + } + } + return ret; +} + +void ff_free_picture_tables(Picture *pic) +{ + int i; + + av_buffer_unref(&pic->mb_var_buf); + av_buffer_unref(&pic->mc_mb_var_buf); + av_buffer_unref(&pic->mb_mean_buf); + av_buffer_unref(&pic->mbskip_table_buf); + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); + + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } +} diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h new file mode 100644 index 0000000..115c288 --- /dev/null +++ b/libavcodec/mpegpicture.h @@ -0,0 +1,111 @@ +/* + * Mpeg video formats-related defines and utility functions + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGPICTURE_H +#define AVCODEC_MPEGPICTURE_H + +#include + +#include "libavutil/frame.h" + +#include "avcodec.h" +#include "motion_est.h" +#include "thread.h" + +#define MAX_PICTURE_COUNT 32 +#define EDGE_WIDTH 16 + +typedef struct ScratchpadContext { + uint8_t *edge_emu_buffer; ///< temporary buffer for if MVs point to out-of-frame data + uint8_t *rd_scratchpad; ///< scratchpad for rate distortion mb decision + uint8_t *obmc_scratchpad; + uint8_t *b_scratchpad; ///< scratchpad used for writing into write only buffers +} ScratchpadContext; + +/** + * Picture. + */ +typedef struct Picture { + struct AVFrame *f; + ThreadFrame tf; + + AVBufferRef *qscale_table_buf; + int8_t *qscale_table; + + AVBufferRef *motion_val_buf[2]; + int16_t (*motion_val[2])[2]; + + AVBufferRef *mb_type_buf; + uint32_t *mb_type; ///< types and macros are defined in mpegutils.h + + AVBufferRef *mbskip_table_buf; + uint8_t *mbskip_table; + + AVBufferRef *ref_index_buf[2]; + int8_t *ref_index[2]; + + AVBufferRef *mb_var_buf; + uint16_t *mb_var; ///< Table for MB variances + + AVBufferRef *mc_mb_var_buf; + uint16_t *mc_mb_var; ///< Table for motion compensated MB variances + + AVBufferRef *mb_mean_buf; + uint8_t *mb_mean; ///< Table for MB luminance + + AVBufferRef *hwaccel_priv_buf; + void *hwaccel_picture_private; ///< Hardware accelerator private data + + int field_picture; ///< whether or not the picture was encoded in separate fields + + int mb_var_sum; ///< sum of MB variance for current frame + int mc_mb_var_sum; ///< motion compensated MB variance for current frame + + int b_frame_score; /* */ + int needs_realloc; ///< Picture needs to be reallocated (eg due to a frame size change) + + int reference; + int shared; + + uint64_t encoding_error[4]; +} Picture; + +/** + * Allocate a Picture. + * The pixels are allocated/set by calling get_buffer() if shared = 0. + */ +int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me, + ScratchpadContext *sc, int shared, int encoding, + int chroma_x_shift, int chroma_y_shift, int out_format, + int mb_stride, int mb_height, int b8_stride, + ptrdiff_t *linesize, ptrdiff_t *uvlinesize); + +int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, + ScratchpadContext *sc, int linesize); + +int ff_mpeg_ref_picture(AVCodecContext *avctx, Picture *dst, Picture *src); +void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *picture); + +void ff_free_picture_tables(Picture *pic); +int ff_update_picture_tables(Picture *dst, Picture *src); + +int ff_find_unused_picture(AVCodecContext *avctx, Picture *picture, int shared); + +#endif /* AVCODEC_MPEGPICTURE_H */ diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h index 9446724..60f9712 100644 --- a/libavcodec/mpegutils.h +++ b/libavcodec/mpegutils.h @@ -28,6 +28,10 @@ #include "avcodec.h" #include "version.h" +/** + * Return value for header parsers if frame is not coded. + * */ +#define FRAME_SKIPPED 100 /* picture type */ #define PICT_TOP_FIELD 1 @@ -40,6 +44,8 @@ */ #define DELAYED_PIC_REF 4 +#define MAX_MB_BYTES (30 * 16 * 16 * 3 / 8 + 120) +#define MAX_FCODE 7 /* MB types */ #if !FF_API_MB_TYPE @@ -114,6 +120,15 @@ #define CANDIDATE_MB_TYPE_DIRECT0 (1 << 12) +#define INPLACE_OFFSET 16 + +enum OutputFormat { + FMT_MPEG1, + FMT_H261, + FMT_H263, + FMT_MJPEG, +}; + /** * Draw a horizontal band if supported. @@ -124,4 +139,4 @@ void ff_draw_horiz_band(AVCodecContext *avctx, AVFrame *cur, AVFrame *last, int y, int h, int picture_structure, int first_field, int low_delay); -#endif /* AVCODEC_PICTTYPE_H */ +#endif /* AVCODEC_MPEGUTILS_H */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index c60389b..379b690 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -37,98 +37,18 @@ #include "idctdsp.h" #include "internal.h" #include "mathops.h" +#include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodata.h" #include "mjpegenc.h" #include "msmpeg4.h" #include "qpeldsp.h" #include "xvmc_internal.h" #include "thread.h" +#include "wmv2.h" #include -static const uint8_t ff_default_chroma_qscale_table[32] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 -}; - -const uint8_t ff_mpeg1_dc_scale_table[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -}; - -static const uint8_t mpeg2_dc_scale_table1[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, -}; - -static const uint8_t mpeg2_dc_scale_table2[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -}; - -static const uint8_t mpeg2_dc_scale_table3[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; - -const uint8_t *const ff_mpeg2_dc_scale_table[4] = { - ff_mpeg1_dc_scale_table, - mpeg2_dc_scale_table1, - mpeg2_dc_scale_table2, - mpeg2_dc_scale_table3, -}; - -const 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, -}; - static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, int16_t *block, int n, int qscale) { @@ -141,7 +61,7 @@ static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, block[0] = block[0] * s->y_dc_scale; else block[0] = block[0] * s->c_dc_scale; - /* XXX: only mpeg1 */ + /* XXX: only MPEG-1 */ quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; @@ -347,39 +267,11 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s, } } -static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, - int (*mv)[2][4][2], - int mb_x, int mb_y, int mb_intra, int mb_skipped) -{ - MpegEncContext *s = opaque; - - s->mv_dir = mv_dir; - s->mv_type = mv_type; - s->mb_intra = mb_intra; - s->mb_skipped = mb_skipped; - s->mb_x = mb_x; - s->mb_y = mb_y; - memcpy(s->mv, mv, sizeof(*mv)); - - ff_init_block_index(s); - ff_update_block_index(s); - - s->bdsp.clear_blocks(s->block[0]); - - s->dest[0] = s->current_picture.f->data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16; - s->dest[1] = s->current_picture.f->data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); - s->dest[2] = s->current_picture.f->data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); - - assert(ref == 0); - ff_mpv_decode_mb(s, s->block); -} - /* init common dct for both encoder and decoder */ static av_cold int dct_init(MpegEncContext *s) { ff_blockdsp_init(&s->bdsp, s->avctx); ff_hpeldsp_init(&s->hdsp, s->avctx->flags); - ff_me_cmp_init(&s->mecc, s->avctx); ff_mpegvideodsp_init(&s->mdsp); ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample); @@ -388,7 +280,7 @@ static av_cold int dct_init(MpegEncContext *s) 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) + if (s->avctx->flags & AV_CODEC_FLAG_BITEXACT) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; @@ -423,358 +315,12 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s) ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } -static int frame_size_alloc(MpegEncContext *s, int linesize) -{ - int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); - - // edge emu needs blocksize + filter length - 1 - // (= 17x17 for halfpel / 21x21 for h264) - // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9 - // at uvlinesize. It supports only YUV420 so 24x24 is enough - // linesize * interlaced * MBsize - FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 2 * 24, - fail); - - FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 2 * 16 * 3, - fail) - s->me.temp = s->me.scratchpad; - s->rd_scratchpad = s->me.scratchpad; - s->b_scratchpad = s->me.scratchpad; - s->obmc_scratchpad = s->me.scratchpad + 16; - - return 0; -fail: - av_freep(&s->edge_emu_buffer); - return AVERROR(ENOMEM); -} - -/** - * Allocate a frame buffer - */ -static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) -{ - int edges_needed = av_codec_is_encoder(s->avctx->codec); - int r, ret; - - pic->tf.f = pic->f; - if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && - s->codec_id != AV_CODEC_ID_VC1IMAGE && - s->codec_id != AV_CODEC_ID_MSS2) { - if (edges_needed) { - pic->f->width = s->avctx->width + 2 * EDGE_WIDTH; - pic->f->height = s->avctx->height + 2 * EDGE_WIDTH; - } - - r = ff_thread_get_buffer(s->avctx, &pic->tf, - pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); - } else { - pic->f->width = s->avctx->width; - pic->f->height = s->avctx->height; - pic->f->format = s->avctx->pix_fmt; - r = avcodec_default_get_buffer2(s->avctx, pic->f, 0); - } - - if (r < 0 || !pic->f->buf[0]) { - av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %p)\n", - r, pic->f->data[0]); - return -1; - } - - if (edges_needed) { - int i; - for (i = 0; pic->f->data[i]; i++) { - int offset = (EDGE_WIDTH >> (i ? s->chroma_y_shift : 0)) * - pic->f->linesize[i] + - (EDGE_WIDTH >> (i ? s->chroma_x_shift : 0)); - pic->f->data[i] += offset; - } - pic->f->width = s->avctx->width; - pic->f->height = s->avctx->height; - } - - if (s->avctx->hwaccel) { - assert(!pic->hwaccel_picture_private); - if (s->avctx->hwaccel->frame_priv_data_size) { - pic->hwaccel_priv_buf = av_buffer_allocz(s->avctx->hwaccel->frame_priv_data_size); - if (!pic->hwaccel_priv_buf) { - av_log(s->avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n"); - return -1; - } - pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; - } - } - - if (s->linesize && (s->linesize != pic->f->linesize[0] || - s->uvlinesize != pic->f->linesize[1])) { - av_log(s->avctx, AV_LOG_ERROR, - "get_buffer() failed (stride changed)\n"); - ff_mpeg_unref_picture(s, pic); - return -1; - } - - if (pic->f->linesize[1] != pic->f->linesize[2]) { - av_log(s->avctx, AV_LOG_ERROR, - "get_buffer() failed (uv stride mismatch)\n"); - ff_mpeg_unref_picture(s, pic); - return -1; - } - - if (!s->edge_emu_buffer && - (ret = frame_size_alloc(s, pic->f->linesize[0])) < 0) { - av_log(s->avctx, AV_LOG_ERROR, - "get_buffer() failed to allocate context scratch buffers.\n"); - ff_mpeg_unref_picture(s, pic); - return ret; - } - - return 0; -} - -void ff_free_picture_tables(Picture *pic) -{ - int i; - - av_buffer_unref(&pic->mb_var_buf); - av_buffer_unref(&pic->mc_mb_var_buf); - av_buffer_unref(&pic->mb_mean_buf); - av_buffer_unref(&pic->mbskip_table_buf); - av_buffer_unref(&pic->qscale_table_buf); - av_buffer_unref(&pic->mb_type_buf); - - for (i = 0; i < 2; i++) { - av_buffer_unref(&pic->motion_val_buf[i]); - av_buffer_unref(&pic->ref_index_buf[i]); - } -} - -static int alloc_picture_tables(MpegEncContext *s, Picture *pic) -{ - const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; - const int mb_array_size = s->mb_stride * s->mb_height; - const int b8_array_size = s->b8_stride * s->mb_height * 2; - int i; - - - pic->mbskip_table_buf = av_buffer_allocz(mb_array_size + 2); - pic->qscale_table_buf = av_buffer_allocz(big_mb_num + s->mb_stride); - pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * - sizeof(uint32_t)); - if (!pic->mbskip_table_buf || !pic->qscale_table_buf || !pic->mb_type_buf) - return AVERROR(ENOMEM); - - if (s->encoding) { - pic->mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); - pic->mc_mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); - pic->mb_mean_buf = av_buffer_allocz(mb_array_size); - if (!pic->mb_var_buf || !pic->mc_mb_var_buf || !pic->mb_mean_buf) - return AVERROR(ENOMEM); - } - - if (s->out_format == FMT_H263 || s->encoding) { - int mv_size = 2 * (b8_array_size + 4) * sizeof(int16_t); - int ref_index_size = 4 * mb_array_size; - - for (i = 0; mv_size && i < 2; i++) { - pic->motion_val_buf[i] = av_buffer_allocz(mv_size); - pic->ref_index_buf[i] = av_buffer_allocz(ref_index_size); - if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) - return AVERROR(ENOMEM); - } - } - - return 0; -} - -static int make_tables_writable(Picture *pic) -{ - int ret, i; -#define MAKE_WRITABLE(table) \ -do {\ - if (pic->table &&\ - (ret = av_buffer_make_writable(&pic->table)) < 0)\ - return ret;\ -} while (0) - - MAKE_WRITABLE(mb_var_buf); - MAKE_WRITABLE(mc_mb_var_buf); - MAKE_WRITABLE(mb_mean_buf); - MAKE_WRITABLE(mbskip_table_buf); - MAKE_WRITABLE(qscale_table_buf); - MAKE_WRITABLE(mb_type_buf); - - for (i = 0; i < 2; i++) { - MAKE_WRITABLE(motion_val_buf[i]); - MAKE_WRITABLE(ref_index_buf[i]); - } - - return 0; -} - -/** - * Allocate a Picture. - * The pixels are allocated/set by calling get_buffer() if shared = 0 - */ -int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) -{ - int i, ret; - - if (shared) { - assert(pic->f->data[0]); - pic->shared = 1; - } else { - assert(!pic->f->buf[0]); - - if (alloc_frame_buffer(s, pic) < 0) - return -1; - - s->linesize = pic->f->linesize[0]; - s->uvlinesize = pic->f->linesize[1]; - } - - if (!pic->qscale_table_buf) - ret = alloc_picture_tables(s, pic); - else - ret = make_tables_writable(pic); - if (ret < 0) - goto fail; - - if (s->encoding) { - pic->mb_var = (uint16_t*)pic->mb_var_buf->data; - pic->mc_mb_var = (uint16_t*)pic->mc_mb_var_buf->data; - pic->mb_mean = pic->mb_mean_buf->data; - } - - pic->mbskip_table = pic->mbskip_table_buf->data; - pic->qscale_table = pic->qscale_table_buf->data + 2 * s->mb_stride + 1; - pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1; - - if (pic->motion_val_buf[0]) { - for (i = 0; i < 2; i++) { - pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; - pic->ref_index[i] = pic->ref_index_buf[i]->data; - } - } - - return 0; -fail: - av_log(s->avctx, AV_LOG_ERROR, "Error allocating a picture.\n"); - ff_mpeg_unref_picture(s, pic); - ff_free_picture_tables(pic); - return AVERROR(ENOMEM); -} - -/** - * Deallocate a picture. - */ -void ff_mpeg_unref_picture(MpegEncContext *s, Picture *pic) -{ - int off = offsetof(Picture, mb_mean) + sizeof(pic->mb_mean); - - pic->tf.f = pic->f; - /* WM Image / Screen codecs allocate internal buffers with different - * dimensions / colorspaces; ignore user-defined callbacks for these. */ - if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && - s->codec_id != AV_CODEC_ID_VC1IMAGE && - s->codec_id != AV_CODEC_ID_MSS2) - ff_thread_release_buffer(s->avctx, &pic->tf); - else if (pic->f) - av_frame_unref(pic->f); - - av_buffer_unref(&pic->hwaccel_priv_buf); - - if (pic->needs_realloc) - ff_free_picture_tables(pic); - - memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); -} - -static int update_picture_tables(Picture *dst, Picture *src) -{ - int i; - -#define UPDATE_TABLE(table)\ -do {\ - if (src->table &&\ - (!dst->table || dst->table->buffer != src->table->buffer)) {\ - av_buffer_unref(&dst->table);\ - dst->table = av_buffer_ref(src->table);\ - if (!dst->table) {\ - ff_free_picture_tables(dst);\ - return AVERROR(ENOMEM);\ - }\ - }\ -} while (0) - - UPDATE_TABLE(mb_var_buf); - UPDATE_TABLE(mc_mb_var_buf); - UPDATE_TABLE(mb_mean_buf); - UPDATE_TABLE(mbskip_table_buf); - UPDATE_TABLE(qscale_table_buf); - UPDATE_TABLE(mb_type_buf); - for (i = 0; i < 2; i++) { - UPDATE_TABLE(motion_val_buf[i]); - UPDATE_TABLE(ref_index_buf[i]); - } - - dst->mb_var = src->mb_var; - dst->mc_mb_var = src->mc_mb_var; - dst->mb_mean = src->mb_mean; - dst->mbskip_table = src->mbskip_table; - dst->qscale_table = src->qscale_table; - dst->mb_type = src->mb_type; - for (i = 0; i < 2; i++) { - dst->motion_val[i] = src->motion_val[i]; - dst->ref_index[i] = src->ref_index[i]; - } - - return 0; -} - -int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src) -{ - int ret; - - av_assert0(!dst->f->buf[0]); - av_assert0(src->f->buf[0]); - - src->tf.f = src->f; - dst->tf.f = dst->f; - ret = ff_thread_ref_frame(&dst->tf, &src->tf); - if (ret < 0) - goto fail; - - ret = update_picture_tables(dst, src); - if (ret < 0) - goto fail; - - if (src->hwaccel_picture_private) { - dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); - if (!dst->hwaccel_priv_buf) - goto fail; - dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; - } - - dst->field_picture = src->field_picture; - dst->mb_var_sum = src->mb_var_sum; - dst->mc_mb_var_sum = src->mc_mb_var_sum; - dst->b_frame_score = src->b_frame_score; - dst->needs_realloc = src->needs_realloc; - dst->reference = src->reference; - dst->shared = src->shared; - - return 0; -fail: - ff_mpeg_unref_picture(s, dst); - return ret; -} - -static void exchange_uv(MpegEncContext *s) +static int alloc_picture(MpegEncContext *s, Picture *pic, int shared) { - int16_t (*tmp)[64]; - - tmp = s->pblocks[4]; - s->pblocks[4] = s->pblocks[5]; - s->pblocks[5] = tmp; + return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, shared, 0, + s->chroma_x_shift, s->chroma_y_shift, s->out_format, + s->mb_stride, s->mb_height, s->b8_stride, + &s->linesize, &s->uvlinesize); } static int init_duplicate_context(MpegEncContext *s) @@ -784,19 +330,19 @@ static int init_duplicate_context(MpegEncContext *s) int yc_size = y_size + 2 * c_size; int i; - s->edge_emu_buffer = + s->sc.edge_emu_buffer = s->me.scratchpad = s->me.temp = - s->rd_scratchpad = - s->b_scratchpad = - s->obmc_scratchpad = NULL; + s->sc.rd_scratchpad = + s->sc.b_scratchpad = + s->sc.obmc_scratchpad = NULL; if (s->encoding) { FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map, ME_MAP_SIZE * sizeof(uint32_t), fail) FF_ALLOCZ_OR_GOTO(s->avctx, s->me.score_map, ME_MAP_SIZE * sizeof(uint32_t), fail) - if (s->avctx->noise_reduction) { + if (s->noise_reduction) { FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_error_sum, 2 * 64 * sizeof(int), fail) } @@ -807,8 +353,13 @@ static int init_duplicate_context(MpegEncContext *s) for (i = 0; i < 12; i++) { s->pblocks[i] = &s->block[i]; } - if (s->avctx->codec_tag == AV_RL32("VCR2")) - exchange_uv(s); + if (s->avctx->codec_tag == AV_RL32("VCR2")) { + // exchange uv + int16_t (*tmp)[64]; + tmp = s->pblocks[4]; + s->pblocks[4] = s->pblocks[5]; + s->pblocks[5] = tmp; + } if (s->out_format == FMT_H263) { /* ac values */ @@ -829,12 +380,12 @@ static void free_duplicate_context(MpegEncContext *s) if (!s) return; - av_freep(&s->edge_emu_buffer); + av_freep(&s->sc.edge_emu_buffer); av_freep(&s->me.scratchpad); s->me.temp = - s->rd_scratchpad = - s->b_scratchpad = - s->obmc_scratchpad = NULL; + s->sc.rd_scratchpad = + s->sc.b_scratchpad = + s->sc.obmc_scratchpad = NULL; av_freep(&s->dct_error_sum); av_freep(&s->me.map); @@ -847,12 +398,12 @@ static void free_duplicate_context(MpegEncContext *s) static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) { #define COPY(a) bak->a = src->a - COPY(edge_emu_buffer); + COPY(sc.edge_emu_buffer); COPY(me.scratchpad); COPY(me.temp); - COPY(rd_scratchpad); - COPY(b_scratchpad); - COPY(obmc_scratchpad); + COPY(sc.rd_scratchpad); + COPY(sc.b_scratchpad); + COPY(sc.obmc_scratchpad); COPY(me.map); COPY(me.score_map); COPY(blocks); @@ -883,10 +434,16 @@ int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) for (i = 0; i < 12; i++) { dst->pblocks[i] = &dst->block[i]; } - if (dst->avctx->codec_tag == AV_RL32("VCR2")) - exchange_uv(dst); - if (!dst->edge_emu_buffer && - (ret = frame_size_alloc(dst, dst->linesize)) < 0) { + if (dst->avctx->codec_tag == AV_RL32("VCR2")) { + // exchange uv + int16_t (*tmp)[64]; + tmp = dst->pblocks[4]; + dst->pblocks[4] = dst->pblocks[5]; + dst->pblocks[5] = tmp; + } + if (!dst->sc.edge_emu_buffer && + (ret = ff_mpeg_framesize_alloc(dst->avctx, &dst->me, + &dst->sc, dst->linesize)) < 0) { av_log(dst->avctx, AV_LOG_ERROR, "failed to allocate context " "scratch buffers.\n"); return ret; @@ -908,6 +465,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, // FIXME can parameters change on I-frames? // in that case dst may need a reinit if (!s->context_initialized) { + int err; memcpy(s, s1, sizeof(MpegEncContext)); s->avctx = dst; @@ -915,7 +473,8 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; ff_mpv_idct_init(s); - ff_mpv_common_init(s); + if ((err = ff_mpv_common_init(s)) < 0) + return err; } if (s->height != s1->height || s->width != s1->width || s->context_reinit) { @@ -936,19 +495,19 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, s->picture_number = s1->picture_number; for (i = 0; i < MAX_PICTURE_COUNT; i++) { - ff_mpeg_unref_picture(s, &s->picture[i]); + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); if (s1->picture[i].f->buf[0] && - (ret = ff_mpeg_ref_picture(s, &s->picture[i], &s1->picture[i])) < 0) + (ret = ff_mpeg_ref_picture(s->avctx, &s->picture[i], &s1->picture[i])) < 0) return ret; } #define UPDATE_PICTURE(pic)\ do {\ - ff_mpeg_unref_picture(s, &s->pic);\ + ff_mpeg_unref_picture(s->avctx, &s->pic);\ if (s1->pic.f->buf[0])\ - ret = ff_mpeg_ref_picture(s, &s->pic, &s1->pic);\ + ret = ff_mpeg_ref_picture(s->avctx, &s->pic, &s1->pic);\ else\ - ret = update_picture_tables(&s->pic, &s1->pic);\ + ret = ff_update_picture_tables(&s->pic, &s1->pic);\ if (ret < 0)\ return ret;\ } while (0) @@ -957,6 +516,11 @@ do {\ UPDATE_PICTURE(last_picture); UPDATE_PICTURE(next_picture); +#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ + ((pic && pic >= old_ctx->picture && \ + pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ + &new_ctx->picture[pic - old_ctx->picture] : NULL) + s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); @@ -965,7 +529,7 @@ do {\ s->next_p_frame_damaged = s1->next_p_frame_damaged; s->workaround_bugs = s1->workaround_bugs; - // MPEG4 timing info + // MPEG-4 timing info memcpy(&s->last_time_base, &s1->last_time_base, (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) - (char *) &s1->last_time_base); @@ -980,21 +544,22 @@ do {\ if (s1->bitstream_buffer) { if (s1->bitstream_buffer_size + - FF_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) + AV_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) av_fast_malloc(&s->bitstream_buffer, &s->allocated_bitstream_buffer_size, s1->allocated_bitstream_buffer_size); - s->bitstream_buffer_size = s1->bitstream_buffer_size; + s->bitstream_buffer_size = s1->bitstream_buffer_size; memcpy(s->bitstream_buffer, s1->bitstream_buffer, s1->bitstream_buffer_size); memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); } - // linesize dependend scratch buffer allocation - if (!s->edge_emu_buffer) + // linesize-dependent scratch buffer allocation + if (!s->sc.edge_emu_buffer) if (s1->linesize) { - if (frame_size_alloc(s, s1->linesize) < 0) { + if (ff_mpeg_framesize_alloc(s->avctx, &s->me, + &s->sc, s1->linesize) < 0) { av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " "scratch buffers.\n"); return AVERROR(ENOMEM); @@ -1005,7 +570,7 @@ do {\ return AVERROR_BUG; } - // MPEG2/interlacing info + // MPEG-2/interlacing info memcpy(&s->progressive_sequence, &s1->progressive_sequence, (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); @@ -1052,43 +617,6 @@ void ff_mpv_decode_defaults(MpegEncContext *s) ff_mpv_common_defaults(s); } -static int init_er(MpegEncContext *s) -{ - ERContext *er = &s->er; - int mb_array_size = s->mb_height * s->mb_stride; - int i; - - er->avctx = s->avctx; - er->mecc = &s->mecc; - - er->mb_index2xy = s->mb_index2xy; - er->mb_num = s->mb_num; - er->mb_width = s->mb_width; - er->mb_height = s->mb_height; - er->mb_stride = s->mb_stride; - er->b8_stride = s->b8_stride; - - er->er_temp_buffer = av_malloc(s->mb_height * s->mb_stride); - er->error_status_table = av_mallocz(mb_array_size); - if (!er->er_temp_buffer || !er->error_status_table) - goto fail; - - er->mbskip_table = s->mbskip_table; - er->mbintra_table = s->mbintra_table; - - for (i = 0; i < FF_ARRAY_ELEMS(s->dc_val); i++) - er->dc_val[i] = s->dc_val[i]; - - er->decode_mb = mpeg_er_decode_mb; - er->opaque = s; - - return 0; -fail: - av_freep(&er->er_temp_buffer); - av_freep(&er->error_status_table); - return AVERROR(ENOMEM); -} - /** * Initialize and allocates MpegEncContext fields dependent on the resolution. */ @@ -1102,7 +630,7 @@ static int init_context_frame(MpegEncContext *s) mb_array_size = s->mb_height * s->mb_stride; mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; - /* set default edge pos, will be overriden + /* set default edge pos, will be overridden * in decode_header if needed */ s->h_edge_pos = s->mb_width * 16; s->v_edge_pos = s->mb_height * 16; @@ -1121,7 +649,7 @@ static int init_context_frame(MpegEncContext *s) yc_size = y_size + 2 * c_size; FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), - fail); // error ressilience code looks cleaner with this + fail); // error resilience 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; @@ -1167,7 +695,7 @@ static int init_context_frame(MpegEncContext *s) } if (s->codec_id == AV_CODEC_ID_MPEG4 || - (s->flags & CODEC_FLAG_INTERLACED_ME)) { + (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { /* interlaced direct mode decoding tables */ for (i = 0; i < 2; i++) { int j, k; @@ -1221,9 +749,9 @@ static int init_context_frame(MpegEncContext *s) /* init macroblock skip table */ FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); - // Note the + 1 is for a quicker mpeg4 slice_end detection + // Note the + 1 is for a quicker MPEG-4 slice_end detection - return init_er(s); + return ff_mpeg_er_init(s); fail: return AVERROR(ENOMEM); } @@ -1270,9 +798,6 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) dct_init(s); - s->flags = s->avctx->flags; - s->flags2 = s->avctx->flags2; - /* set chroma shifts */ av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &s->chroma_x_shift, @@ -1281,8 +806,6 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) /* convert fourcc to upper case */ s->codec_tag = avpriv_toupper4(s->avctx->codec_tag); - s->stream_codec_tag = avpriv_toupper4(s->avctx->stream_codec_tag); - FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, MAX_PICTURE_COUNT * sizeof(Picture), fail); for (i = 0; i < MAX_PICTURE_COUNT; i++) { @@ -1327,10 +850,10 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) for (i = 0; i < nb_slices; i++) { if (init_duplicate_context(s->thread_context[i]) < 0) goto fail; - s->thread_context[i]->start_mb_y = - (s->mb_height * (i) + nb_slices / 2) / nb_slices; - s->thread_context[i]->end_mb_y = - (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; } } else { if (init_duplicate_context(s) < 0) @@ -1352,7 +875,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) * Is used during resolution changes to avoid a full reinitialization of the * codec. */ -static int free_context_frame(MpegEncContext *s) +static void free_context_frame(MpegEncContext *s) { int i, j, k; @@ -1398,8 +921,6 @@ static int free_context_frame(MpegEncContext *s) av_freep(&s->bits_tab); s->linesize = s->uvlinesize = 0; - - return 0; } int ff_mpv_common_frame_size_change(MpegEncContext *s) @@ -1416,8 +937,7 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s) } else free_duplicate_context(s); - if ((err = free_context_frame(s)) < 0) - return err; + free_context_frame(s); if (s->picture) for (i = 0; i < MAX_PICTURE_COUNT; i++) { @@ -1435,8 +955,8 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s) s->mb_height = (s->height + 15) / 16; if ((s->width || s->height) && - av_image_check_size(s->width, s->height, 0, s->avctx)) - return AVERROR_INVALIDDATA; + (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) + goto fail; if ((err = init_context_frame(s))) goto fail; @@ -1452,12 +972,12 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s) } for (i = 0; i < nb_slices; i++) { - if (init_duplicate_context(s->thread_context[i]) < 0) + if ((err = init_duplicate_context(s->thread_context[i])) < 0) goto fail; - s->thread_context[i]->start_mb_y = - (s->mb_height * (i) + nb_slices / 2) / nb_slices; - s->thread_context[i]->end_mb_y = - (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; } } else { if (init_duplicate_context(s) < 0) @@ -1498,22 +1018,22 @@ void ff_mpv_common_end(MpegEncContext *s) if (s->picture) { for (i = 0; i < MAX_PICTURE_COUNT; i++) { ff_free_picture_tables(&s->picture[i]); - ff_mpeg_unref_picture(s, &s->picture[i]); + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); av_frame_free(&s->picture[i].f); } } av_freep(&s->picture); ff_free_picture_tables(&s->last_picture); - ff_mpeg_unref_picture(s, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); av_frame_free(&s->last_picture.f); ff_free_picture_tables(&s->current_picture); - ff_mpeg_unref_picture(s, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->current_picture); av_frame_free(&s->current_picture.f); ff_free_picture_tables(&s->next_picture); - ff_mpeg_unref_picture(s, &s->next_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); av_frame_free(&s->next_picture.f); ff_free_picture_tables(&s->new_picture); - ff_mpeg_unref_picture(s, &s->new_picture); + ff_mpeg_unref_picture(s->avctx, &s->new_picture); av_frame_free(&s->new_picture.f); free_context_frame(s); @@ -1525,151 +1045,6 @@ void ff_mpv_common_end(MpegEncContext *s) s->linesize = s->uvlinesize = 0; } -av_cold void ff_init_rl(RLTable *rl, - uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) -{ - int8_t max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1]; - uint8_t index_run[MAX_RUN + 1]; - int last, run, level, start, end, i; - - /* If table is static, we can quit if rl->max_level[0] is not NULL */ - if (static_store && rl->max_level[0]) - return; - - /* compute max_level[], max_run[] and index_run[] */ - for (last = 0; last < 2; last++) { - if (last == 0) { - start = 0; - end = rl->last; - } else { - start = rl->last; - end = rl->n; - } - - memset(max_level, 0, MAX_RUN + 1); - memset(max_run, 0, MAX_LEVEL + 1); - memset(index_run, rl->n, MAX_RUN + 1); - for (i = start; i < end; i++) { - run = rl->table_run[i]; - level = rl->table_level[i]; - if (index_run[run] == rl->n) - index_run[run] = i; - if (level > max_level[run]) - max_level[run] = level; - if (run > max_run[level]) - max_run[level] = run; - } - if (static_store) - rl->max_level[last] = static_store[last]; - else - rl->max_level[last] = av_malloc(MAX_RUN + 1); - memcpy(rl->max_level[last], max_level, MAX_RUN + 1); - if (static_store) - rl->max_run[last] = static_store[last] + MAX_RUN + 1; - else - rl->max_run[last] = av_malloc(MAX_LEVEL + 1); - memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); - if (static_store) - rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; - else - rl->index_run[last] = av_malloc(MAX_RUN + 1); - memcpy(rl->index_run[last], index_run, MAX_RUN + 1); - } -} - -av_cold void ff_init_vlc_rl(RLTable *rl) -{ - int i, q; - - for (q = 0; q < 32; q++) { - int qmul = q * 2; - int qadd = (q - 1) | 1; - - if (q == 0) { - qmul = 1; - qadd = 0; - } - for (i = 0; i < rl->vlc.table_size; i++) { - int code = rl->vlc.table[i][0]; - int len = rl->vlc.table[i][1]; - int level, run; - - if (len == 0) { // illegal code - run = 66; - level = MAX_LEVEL; - } else if (len < 0) { // more bits needed - run = 0; - level = code; - } else { - if (code == rl->n) { // esc - run = 66; - level = 0; - } else { - run = rl->table_run[code] + 1; - level = rl->table_level[code] * qmul + qadd; - if (code >= rl->last) run += 192; - } - } - rl->rl_vlc[q][i].len = len; - rl->rl_vlc[q][i].level = level; - rl->rl_vlc[q][i].run = run; - } - } -} - -static void release_unused_pictures(MpegEncContext *s) -{ - int i; - - /* release non reference frames */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (!s->picture[i].reference) - ff_mpeg_unref_picture(s, &s->picture[i]); - } -} - -static inline int pic_is_unused(MpegEncContext *s, Picture *pic) -{ - if (!pic->f->buf[0]) - return 1; - if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) - return 1; - return 0; -} - -static int find_unused_picture(MpegEncContext *s, int shared) -{ - int i; - - if (shared) { - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (!s->picture[i].f->buf[0]) - return i; - } - } else { - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (pic_is_unused(s, &s->picture[i])) - return i; - } - } - - return AVERROR_INVALIDDATA; -} - -int ff_find_unused_picture(MpegEncContext *s, int shared) -{ - int ret = find_unused_picture(s, shared); - - if (ret >= 0 && ret < MAX_PICTURE_COUNT) { - if (s->picture[ret].needs_realloc) { - s->picture[ret].needs_realloc = 0; - ff_free_picture_tables(&s->picture[ret]); - ff_mpeg_unref_picture(s, &s->picture[ret]); - } - } - return ret; -} - /** * generic function called after decoding * the header and before a frame is decoded. @@ -1684,32 +1059,33 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f->buf[0]) { - ff_mpeg_unref_picture(s, s->last_picture_ptr); + ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); } /* release forgotten pictures */ - /* if (mpeg124/h263) */ + /* if (MPEG-124 / H.263) */ for (i = 0; i < MAX_PICTURE_COUNT; i++) { if (&s->picture[i] != s->last_picture_ptr && &s->picture[i] != s->next_picture_ptr && s->picture[i].reference && !s->picture[i].needs_realloc) { - if (!(avctx->active_thread_type & FF_THREAD_FRAME)) - av_log(avctx, AV_LOG_ERROR, - "releasing zombie picture\n"); - ff_mpeg_unref_picture(s, &s->picture[i]); + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); } } - ff_mpeg_unref_picture(s, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->current_picture); - release_unused_pictures(s); + /* release non reference frames */ + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference) + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + } if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) { // we already have a unused image // (maybe it was set before reading the header) pic = s->current_picture_ptr; } else { - i = ff_find_unused_picture(s, 0); + i = ff_find_unused_picture(s->avctx, s->picture, 0); if (i < 0) { av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); return i; @@ -1725,7 +1101,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) pic->f->coded_picture_number = s->coded_picture_number++; - if (ff_alloc_picture(s, pic, 0) < 0) + if (alloc_picture(s, pic, 0) < 0) return -1; s->current_picture_ptr = pic; @@ -1742,11 +1118,11 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; s->current_picture_ptr->f->pict_type = s->pict_type; - // if (s->flags && CODEC_FLAG_QSCALE) + // if (s->avctx->flags && AV_CODEC_FLAG_QSCALE) // s->current_picture_ptr->quality = s->new_picture_ptr->quality; s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; - if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, s->current_picture_ptr)) < 0) return ret; @@ -1755,7 +1131,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) if (!s->droppable) s->next_picture_ptr = s->current_picture_ptr; } - av_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", + ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, @@ -1776,7 +1152,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) "allocate dummy last picture for field based first keyframe\n"); /* Allocate a dummy frame */ - i = ff_find_unused_picture(s, 0); + i = ff_find_unused_picture(s->avctx, s->picture, 0); if (i < 0) { av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); return i; @@ -1786,7 +1162,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->last_picture_ptr->reference = 3; s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_I; - if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0) { + if (alloc_picture(s, s->last_picture_ptr, 0) < 0) { s->last_picture_ptr = NULL; return -1; } @@ -1806,7 +1182,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) && s->pict_type == AV_PICTURE_TYPE_B) { /* Allocate a dummy frame */ - i = ff_find_unused_picture(s, 0); + i = ff_find_unused_picture(s->avctx, s->picture, 0); if (i < 0) { av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); return i; @@ -1816,7 +1192,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->next_picture_ptr->reference = 3; s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_I; - if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { + if (alloc_picture(s, s->next_picture_ptr, 0) < 0) { s->next_picture_ptr = NULL; return -1; } @@ -1825,16 +1201,16 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) } if (s->last_picture_ptr) { - ff_mpeg_unref_picture(s, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); if (s->last_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s, &s->last_picture, + (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, s->last_picture_ptr)) < 0) return ret; } if (s->next_picture_ptr) { - ff_mpeg_unref_picture(s, &s->next_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); if (s->next_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s, &s->next_picture, + (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, s->next_picture_ptr)) < 0) return ret; } @@ -1859,11 +1235,9 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) } } - s->err_recognition = avctx->err_recognition; - /* set dequantizer, we can't do it during init as - * it might change for mpeg4 and we can't do it in the header - * decode as init is not called for mpeg4 there yet */ + * it might change for MPEG-4 and we can't do it in the header + * decode as init is not called for MPEG-4 there yet */ if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; @@ -2007,7 +1381,7 @@ void ff_print_debug_info(MpegEncContext *s, Picture *p) /** * find the lowest MB row referenced in the MVs */ -int ff_mpv_lowest_referenced_row(MpegEncContext *s, int dir) +static int lowest_referenced_row(MpegEncContext *s, int dir) { int my_max = INT_MIN, my_min = INT_MAX, qpel_shift = !s->quarter_sample; int my, off, i, mvs; @@ -2156,7 +1530,9 @@ FF_ENABLE_DEPRECATION_WARNINGS else if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) s->mbintra_table[mb_xy]=1; - if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { //FIXME precalc + if ((s->avctx->flags & AV_CODEC_FLAG_PSNR) || + !(s->encoding && (s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && + s->avctx->mb_decision != FF_MB_DECISION_RD)) { // FIXME precalc uint8_t *dest_y, *dest_cb, *dest_cr; int dct_linesize, dct_offset; op_pixels_func (*op_pix)[4]; @@ -2190,9 +1566,9 @@ FF_ENABLE_DEPRECATION_WARNINGS 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; + dest_y = s->sc.b_scratchpad; + dest_cb= s->sc.b_scratchpad+16*linesize; + dest_cr= s->sc.b_scratchpad+32*linesize; } if (!s->mb_intra) { @@ -2203,12 +1579,12 @@ FF_ENABLE_DEPRECATION_WARNINGS if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { if (s->mv_dir & MV_DIR_FORWARD) { ff_thread_await_progress(&s->last_picture_ptr->tf, - ff_mpv_lowest_referenced_row(s, 0), + lowest_referenced_row(s, 0), 0); } if (s->mv_dir & MV_DIR_BACKWARD) { ff_thread_await_progress(&s->next_picture_ptr->tf, - ff_mpv_lowest_referenced_row(s, 1), + lowest_referenced_row(s, 1), 0); } } @@ -2245,7 +1621,7 @@ FF_ENABLE_DEPRECATION_WARNINGS add_dequant_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); add_dequant_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale); - if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if (!CONFIG_GRAY || !(s->avctx->flags & AV_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); @@ -2264,7 +1640,7 @@ FF_ENABLE_DEPRECATION_WARNINGS add_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize); add_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize); - if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if (!CONFIG_GRAY || !(s->avctx->flags & AV_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); @@ -2297,7 +1673,7 @@ FF_ENABLE_DEPRECATION_WARNINGS put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); put_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale); - if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if (!CONFIG_GRAY || !(s->avctx->flags & AV_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); @@ -2316,7 +1692,7 @@ FF_ENABLE_DEPRECATION_WARNINGS s->idsp.idct_put(dest_y + dct_offset, dct_linesize, block[2]); s->idsp.idct_put(dest_y + dct_offset + block_size, dct_linesize, block[3]); - if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { if(s->chroma_y_shift){ s->idsp.idct_put(dest_cb, uvlinesize, block[4]); s->idsp.idct_put(dest_cr, uvlinesize, block[5]); @@ -2378,9 +1754,9 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1; //block_index is not used by mpeg2, so it is not affected by chroma_format - s->dest[0] = s->current_picture.f->data[0] + ((s->mb_x - 1) << mb_size); - s->dest[1] = s->current_picture.f->data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); - s->dest[2] = s->current_picture.f->data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); + s->dest[0] = s->current_picture.f->data[0] + (s->mb_x - 1) * (1 << mb_size); + s->dest[1] = s->current_picture.f->data[1] + (s->mb_x - 1) * (1 << (mb_size - s->chroma_x_shift)); + s->dest[2] = s->current_picture.f->data[2] + (s->mb_x - 1) * (1 << (mb_size - s->chroma_x_shift)); if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME)) { @@ -2397,35 +1773,6 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename } } -/** - * Permute an 8x8 block. - * @param block the block which will be permuted according to the given permutation vector - * @param permutation the permutation vector - * @param last the last non zero coefficient in scantable order, used to speed the permutation up - * @param scantable the used scantable, this is only used to speed the permutation up, the block is not - * (inverse) permutated to scantable order! - */ -void ff_block_permute(int16_t *block, uint8_t *permutation, const uint8_t *scantable, int last) -{ - int i; - int16_t temp[64]; - - if(last<=0) return; - //if(permutation[1]==1) return; //FIXME it is ok but not clean and might fail for some permutations - - for(i=0; i<=last; i++){ - const int j= scantable[i]; - temp[j]= block[j]; - block[j]=0; - } - - for(i=0; i<=last; i++){ - const int j= scantable[i]; - const int perm_j= permutation[j]; - block[perm_j]= temp[j]; - } -} - void ff_mpeg_flush(AVCodecContext *avctx){ int i; MpegEncContext *s = avctx->priv_data; @@ -2434,12 +1781,12 @@ void ff_mpeg_flush(AVCodecContext *avctx){ return; for (i = 0; i < MAX_PICTURE_COUNT; i++) - ff_mpeg_unref_picture(s, &s->picture[i]); + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; - ff_mpeg_unref_picture(s, &s->current_picture); - ff_mpeg_unref_picture(s, &s->last_picture); - ff_mpeg_unref_picture(s, &s->next_picture); + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); s->mb_x= s->mb_y= 0; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index c69751e..932a6f2 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -28,6 +28,8 @@ #ifndef AVCODEC_MPEGVIDEO_H #define AVCODEC_MPEGVIDEO_H +#include + #include "avcodec.h" #include "blockdsp.h" #include "error_resilience.h" @@ -36,47 +38,28 @@ #include "h263dsp.h" #include "hpeldsp.h" #include "idctdsp.h" +#include "internal.h" #include "me_cmp.h" +#include "motion_est.h" +#include "mpegpicture.h" #include "mpegvideodsp.h" #include "mpegvideoencdsp.h" #include "pixblockdsp.h" #include "put_bits.h" #include "ratecontrol.h" #include "parser.h" +#include "mpegutils.h" #include "mpeg12data.h" #include "qpeldsp.h" -#include "rl.h" #include "thread.h" #include "videodsp.h" #include "libavutil/opt.h" -#define FRAME_SKIPPED 100 ///< return value for header parsers if frame is not coded - -enum OutputFormat { - FMT_MPEG1, - FMT_H261, - FMT_H263, - FMT_MJPEG, -}; - -#define MAX_FCODE 7 -#define MAX_MV 2048 - #define MAX_THREADS 16 -#define MAX_PICTURE_COUNT 32 - #define MAX_B_FRAMES 16 -#define ME_MAP_SIZE 64 - -#define MAX_MB_BYTES (30*16*16*3/8 + 120) - -#define INPLACE_OFFSET 16 - -#define EDGE_WIDTH 16 - /* Start codes. */ #define SEQ_END_CODE 0x000001b7 #define SEQ_START_CODE 0x000001b3 @@ -87,117 +70,6 @@ enum OutputFormat { #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 -/* encoding scans */ -extern const uint8_t ff_alternate_horizontal_scan[64]; -extern const uint8_t ff_alternate_vertical_scan[64]; - -struct MpegEncContext; - -/** - * Picture. - */ -typedef struct Picture{ - struct AVFrame *f; - ThreadFrame tf; - - AVBufferRef *qscale_table_buf; - int8_t *qscale_table; - - AVBufferRef *motion_val_buf[2]; - int16_t (*motion_val[2])[2]; - - AVBufferRef *mb_type_buf; - uint32_t *mb_type; ///< types and macros are defined in mpegutils.h - - AVBufferRef *mbskip_table_buf; - uint8_t *mbskip_table; - - AVBufferRef *ref_index_buf[2]; - int8_t *ref_index[2]; - - AVBufferRef *mb_var_buf; - uint16_t *mb_var; ///< Table for MB variances - - AVBufferRef *mc_mb_var_buf; - uint16_t *mc_mb_var; ///< Table for motion compensated MB variances - - AVBufferRef *mb_mean_buf; - uint8_t *mb_mean; ///< Table for MB luminance - - AVBufferRef *hwaccel_priv_buf; - /** - * hardware accelerator private data - */ - void *hwaccel_picture_private; - - int field_picture; ///< whether or not the picture was encoded in separate fields - - int mb_var_sum; ///< sum of MB variance for current frame - int mc_mb_var_sum; ///< motion compensated MB variance for current frame - - int b_frame_score; /* */ - int needs_realloc; ///< Picture needs to be reallocated (eg due to a frame size change) - - int reference; - int shared; -} Picture; - -/** - * Motion estimation context. - */ -typedef struct MotionEstContext{ - AVCodecContext *avctx; - int skip; ///< set if ME is skipped for the current MB - int co_located_mv[4][2]; ///< mv from last P-frame for direct mode ME - int direct_basis_mv[4][2]; - uint8_t *scratchpad; ///< data area for the ME algo, so that the ME does not need to malloc/free - uint8_t *best_mb; - uint8_t *temp_mb[2]; - uint8_t *temp; - int best_bits; - uint32_t *map; ///< map to avoid duplicate evaluations - uint32_t *score_map; ///< map to store the scores - unsigned map_generation; - int pre_penalty_factor; - int penalty_factor; /**< an estimate of the bits required to - code a given mv value, e.g. (1,0) takes - more bits than (0,0). We have to - estimate whether any reduction in - residual is worth the extra bits. */ - int sub_penalty_factor; - int mb_penalty_factor; - int flags; - int sub_flags; - int mb_flags; - int pre_pass; ///< = 1 for the pre pass - int dia_size; - int xmin; - int xmax; - int ymin; - int ymax; - int pred_x; - int pred_y; - uint8_t *src[4][4]; - uint8_t *ref[4][4]; - int stride; - int uvstride; - /* temp variables for picture complexity calculation */ - int mc_mb_var_sum_temp; - int mb_var_sum_temp; - int scene_change_score; -/* cmp, chroma_cmp;*/ - op_pixels_func (*hpel_put)[4]; - op_pixels_func (*hpel_avg)[4]; - qpel_mc_func (*qpel_put)[16]; - qpel_mc_func (*qpel_avg)[16]; - uint8_t (*mv_penalty)[MAX_MV*2+1]; ///< amount of bits needed to encode a MV - uint8_t *current_mv_penalty; - int (*sub_motion_search)(struct MpegEncContext * s, - int *mx_ptr, int *my_ptr, int dmin, - int src_index, int ref_index, - int size, int h); -}MotionEstContext; - /** * MpegEncContext. */ @@ -207,16 +79,16 @@ typedef struct MpegEncContext { int y_dc_scale, c_dc_scale; int ac_pred; int block_last_index[12]; ///< last non zero coefficient in block - int h263_aic; ///< Advanded INTRA Coding (AIC) + int h263_aic; ///< Advanced INTRA Coding (AIC) /* scantables */ - ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage + ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce the cache usage ScanTable intra_scantable; ScanTable intra_h_scantable; ScanTable intra_v_scantable; /* WARNING: changes above this line require updates to hardcoded - * offsets used in asm. */ + * offsets used in ASM. */ struct AVCodecContext *avctx; /* the following parameters must be initialized before encoding */ @@ -225,25 +97,22 @@ typedef struct MpegEncContext { int intra_only; ///< if true, only intra pictures are generated int bit_rate; ///< wanted bit rate enum OutputFormat out_format; ///< output format - int h263_pred; ///< use mpeg4/h263 ac/dc predictions - int pb_frame; ///< PB frame mode (0 = none, 1 = base, 2 = improved) + int h263_pred; ///< use MPEG-4/H.263 ac/dc predictions + int pb_frame; ///< PB-frame mode (0 = none, 1 = base, 2 = improved) /* the following codec id fields are deprecated in favor of codec_id */ - int h263_plus; ///< h263 plus headers - int h263_flv; ///< use flv h263 header + int h263_plus; ///< H.263+ headers + int h263_flv; ///< use flv H.263 header enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ int fixed_qscale; ///< fixed qscale if non zero int encoding; ///< true if we are encoding (vs decoding) - int flags; ///< AVCodecContext.flags (HQ, MV4, ...) - int flags2; ///< AVCodecContext.flags2 - int max_b_frames; ///< max number of b-frames for encoding + int 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 strict_std_compliance; ///< strictly follow the std (MPEG-4, ...) int workaround_bugs; ///< workaround bugs in encoders which cannot be detected automatically int codec_tag; ///< internal codec_tag upper case converted from avctx codec_tag - int stream_codec_tag; ///< internal stream_codec_tag upper case converted from avctx stream_codec_tag /* the following fields are managed internally by the encoder */ /* sequence parameters */ @@ -261,7 +130,7 @@ typedef struct MpegEncContext { ptrdiff_t 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 + Picture **reordered_input_picture; ///< pointer to the next pictures in coded order for encoding int64_t user_specified_pts; ///< last non-zero pts from AVFrame which was passed into avcodec_encode_video2() /** @@ -308,37 +177,35 @@ typedef struct MpegEncContext { Picture *last_picture_ptr; ///< pointer to the previous picture. Picture *next_picture_ptr; ///< pointer to the next picture (for bidir pred) Picture *current_picture_ptr; ///< pointer to the current picture - int last_dc[3]; ///< last DC values for MPEG1 + int last_dc[3]; ///< last DC values for MPEG-1 int16_t *dc_val_base; - int16_t *dc_val[3]; ///< used for mpeg4 DC prediction, all 3 arrays must be continuous + int16_t *dc_val[3]; ///< used for MPEG-4 DC prediction, all 3 arrays must be continuous const uint8_t *y_dc_scale_table; ///< qscale -> y_dc_scale table const uint8_t *c_dc_scale_table; ///< qscale -> c_dc_scale table - const uint8_t *chroma_qscale_table; ///< qscale -> chroma_qscale (h263) + const uint8_t *chroma_qscale_table; ///< qscale -> chroma_qscale (H.263) 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 + int16_t (*ac_val[3])[16]; ///< used for for MPEG-4 AC prediction, all 3 arrays must be continuous int mb_skipped; ///< MUST BE SET only during DECODING uint8_t *mbskip_table; /**< used to avoid copy if macroblock skipped (for black regions for example) - and used for b-frame encoding & decoding (contains skip table of next P Frame) */ + and used for B-frame encoding & decoding (contains skip table of next P-frame) */ uint8_t *mbintra_table; ///< used to avoid setting {ac, dc, cbp}-pred stuff to zero on inter MB decoding uint8_t *cbp_table; ///< used to store cbp, ac_pred for partitioned decoding uint8_t *pred_dir_table; ///< used to store pred_dir for partitioned decoding - uint8_t *edge_emu_buffer; ///< temporary buffer for if MVs point to out-of-frame data - uint8_t *rd_scratchpad; ///< scratchpad for rate distortion mb decision - uint8_t *obmc_scratchpad; - uint8_t *b_scratchpad; ///< scratchpad used for writing into write only buffers + + ScratchpadContext sc; int qscale; ///< QP int chroma_qscale; ///< chroma QP - unsigned int lambda; ///< lagrange multipler used in rate distortion + unsigned int lambda; ///< Lagrange multiplier 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; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... int last_pict_type; //FIXME removes - int last_non_b_pict_type; ///< used for mpeg4 gmc b-frames & ratecontrol + int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol int droppable; int frame_rate_index; int last_lambda_for[5]; ///< last lambda for a specific pict type @@ -346,7 +213,7 @@ typedef struct MpegEncContext { /* motion compensation */ int unrestricted_mv; ///< mv can point outside of the coded picture - int h263_long_vectors; ///< use horrible h263v1 long vector mode + int h263_long_vectors; ///< use horrible H.263v1 long vector mode BlockDSPContext bdsp; FDCTDSPContext fdsp; @@ -360,7 +227,7 @@ typedef struct MpegEncContext { VideoDSPContext vdsp; H263DSPContext h263dsp; int f_code; ///< forward MV resolution - int b_code; ///< backward MV resolution for B Frames (mpeg4) + int b_code; ///< backward MV resolution for B-frames (MPEG-4) int16_t (*p_mv_table_base)[2]; int16_t (*b_forw_mv_table_base)[2]; int16_t (*b_back_mv_table_base)[2]; @@ -369,24 +236,29 @@ typedef struct MpegEncContext { 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 + 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]); +#if FF_API_MOTION_EST int me_method; ///< ME algorithm +#endif + int motion_est; ///< ME algorithm + int me_penalty_compensation; + int me_pre; ///< prepass for motion estimation int mv_dir; #define MV_DIR_FORWARD 1 #define MV_DIR_BACKWARD 2 -#define MV_DIRECT 4 ///< bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4) +#define MV_DIRECT 4 ///< bidirectional mode where the difference equals the MV of the last P/S/I-Frame (MPEG-4) 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_8X8 1 ///< 4 vectors (H.263, MPEG-4 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 @@ -397,14 +269,14 @@ typedef struct MpegEncContext { */ 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 + int last_mv[2][2][2]; ///< last MV, used for MV prediction in MPEG-1 & B-frame MPEG-4 uint8_t *fcode_tab; ///< smallest fcode needed for each MV int16_t direct_scale_mv[2][64]; ///< precomputed to avoid divisions in ff_mpeg4_set_direct_mv MotionEstContext me; - int no_rounding; /**< apply no rounding to motion compensation (MPEG4, msmpeg4, ...) - for b-frames rounding mode is always 0 */ + int no_rounding; /**< apply no rounding to motion compensation (MPEG-4, msmpeg4, ...) + for B-frames rounding mode is always 0 */ /* macroblock layer */ int mb_x, mb_y; @@ -473,8 +345,7 @@ typedef struct MpegEncContext { int resync_mb_y; ///< y position of last resync marker GetBitContext last_resync_gb; ///< used to search for the next resync marker int mb_num_left; ///< number of MBs left in this video packet (for partitioned Slices only) - int next_p_frame_damaged; ///< set if the next p frame is damaged, to avoid showing trashed b frames - int err_recognition; + int next_p_frame_damaged; ///< set if the next p frame is damaged, to avoid showing trashed B-frames ParseContext parse_context; @@ -485,9 +356,10 @@ typedef struct MpegEncContext { int prev_mb_info, last_mb_info; uint8_t *mb_info_ptr; int mb_info_size; + int rc_strategy; /* H.263+ specific */ - int umvplus; ///< == H263+ && unrestricted_mv + int umvplus; ///< == H.263+ && unrestricted_mv int h263_aic_dir; ///< AIC direction: 0 = left, 1 = top int h263_slice_structured; int alt_inter_vlc; ///< alternative inter vlc @@ -495,7 +367,7 @@ typedef struct MpegEncContext { int loop_filter; int custom_pcf; - /* mpeg4 specific */ + /* MPEG-4 specific */ ///< number of bits to represent the fractional part of time (encoder only) int time_increment_bits; int last_time_base; @@ -516,12 +388,12 @@ typedef struct MpegEncContext { int sprite_warping_accuracy; int data_partitioning; ///< data partitioning flag from header int partitioned_frame; ///< is current frame partitioned - int low_delay; ///< no reordering needed / has no b-frames + int low_delay; ///< no reordering needed / has no B-frames int vo_type; PutBitContext tex_pb; ///< used for data partitioned VOPs PutBitContext pb2; ///< used for data partitioned VOPs int mpeg_quant; - int padding_bug_score; ///< used to detect the VERY common padding bug in MPEG4 + int padding_bug_score; ///< used to detect the VERY common padding bug in MPEG-4 /* divx specific, used to workaround (many) bugs in divx5 */ int divx_packed; @@ -535,6 +407,7 @@ typedef struct MpegEncContext { /* MJPEG specific */ struct MJpegContext *mjpeg_ctx; + int pred; /* MSMPEG4 specific */ int mv_table_index; @@ -543,7 +416,7 @@ typedef struct MpegEncContext { 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 first_slice_line; ///< used in MPEG-4 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; @@ -557,9 +430,9 @@ typedef struct MpegEncContext { /* 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 + /* MPEG-1 specific */ + int gop_picture_number; ///< index of the first picture of a GOP based on fake_pic_num & MPEG-1 specific + int last_mv_dir; ///< last mv_dir, used for B-frame encoding uint8_t *vbv_delay_ptr; ///< pointer to vbv_delay in the bitstream /* MPEG-2-specific - I wished not to have to support this mess. */ @@ -569,11 +442,13 @@ typedef struct MpegEncContext { // picture structure defines are loaded from mpegutils.h int picture_structure; + int64_t timecode_frame_start; ///< GOP timecode frame start number, in non drop frame format int intra_dc_precision; int frame_pred_frame_dct; int top_field_first; int concealment_motion_vectors; int q_scale_type; + int brd_scale; int intra_vlc_format; int alternate_scan; int repeat_first_field; @@ -593,12 +468,13 @@ typedef struct MpegEncContext { /* RTP specific */ int rtp_mode; + int rtp_payload_size; uint8_t *ptr_lastgob; int16_t (*pblocks[12])[64]; int16_t (*block)[64]; ///< points to one of the following blocks - int16_t (*blocks)[8][64]; // for HQ mode we need to keep the best block + int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block int (*decode_mb)(struct MpegEncContext *s, int16_t block[6][64]); // used by some codecs to avoid a switch() #define SLICE_OK 0 #define SLICE_ERROR -1 @@ -617,9 +493,9 @@ typedef struct MpegEncContext { int16_t *block/*align 16*/, int n, int qscale); void (*dct_unquantize_h263_inter)(struct MpegEncContext *s, int16_t *block/*align 16*/, int n, int qscale); - void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both) + void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both) int16_t *block/*align 16*/, int n, int qscale); - void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both) + void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both) int16_t *block/*align 16*/, int n, int qscale); int (*dct_quantize)(struct MpegEncContext *s, int16_t *block/*align 16*/, int n, int qscale, int *overflow); int (*fast_dct_quantize)(struct MpegEncContext *s, int16_t *block/*align 16*/, int n, int qscale, int *overflow); @@ -628,6 +504,20 @@ typedef struct MpegEncContext { int mpv_flags; ///< flags set by private options int quantizer_noise_shaping; + /** + * ratecontrol qmin qmax limiting method + * 0-> clipping, 1-> use a nice continuous function to limit qscale within qmin/qmax. + */ + float rc_qsquish; + float rc_qmod_amp; + int rc_qmod_freq; + float rc_initial_cplx; + float rc_buffer_aggressivity; + float border_masking; + int lmin, lmax; + + char *rc_eq; + /* temp buffers for rate control */ float *cplx_tab, *bits_tab; @@ -641,12 +531,18 @@ typedef struct MpegEncContext { /* temporary frames used by b_frame_strategy = 2 */ AVFrame *tmp_frames[MAX_B_FRAMES + 2]; -} MpegEncContext; + int b_frame_strategy; + int b_sensitivity; + + /* frame skip options for encoding */ + int frame_skip_threshold; + int frame_skip_factor; + int frame_skip_exp; + int frame_skip_cmp; -#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ - ((pic && pic >= old_ctx->picture && \ - pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ - &new_ctx->picture[pic - old_ctx->picture] : NULL) + int scenechange_threshold; + int noise_reduction; +} MpegEncContext; /* mpegvideo_enc common options */ #define FF_MPV_FLAG_SKIP_RD 0x0001 @@ -656,9 +552,26 @@ typedef struct MpegEncContext { #define FF_MPV_FLAG_NAQ 0x0010 #define FF_MPV_FLAG_MV0 0x0020 +#define FF_MPV_OPT_CMP_FUNC \ +{ "sad", "Sum of absolute differences, fast", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "sse", "Sum of squared errors", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "satd", "Sum of absolute Hadamard transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SATD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dct", "Sum of absolute DCT transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "psnr", "Sum of squared quantization errors, low quality", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_PSNR }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "bit", "Number of bits needed for the block", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_BIT }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "rd", "Rate distortion optimal, slow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_RD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "zero", "Zero", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_ZERO }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "vsad", "Sum of absolute vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "vsse", "Sum of squared vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "nsse", "Noise preserving sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_NSSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dct264", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT264 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" } + #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) #define FF_MPV_COMMON_OPTS \ +FF_MPV_OPT_CMP_FUNC, \ { "mpv_flags", "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\ { "skip_rd", "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_SKIP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ { "strict_gop", "Strictly enforce gop size", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ @@ -672,18 +585,44 @@ typedef struct MpegEncContext { FF_MPV_OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ { "quantizer_noise_shaping", NULL, FF_MPV_OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ { "error_rate", "Simulate errors in the bitstream to test error concealment.", \ - FF_MPV_OFFSET(error_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, + FF_MPV_OFFSET(error_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ +{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", \ + FF_MPV_OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0, 99, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_amp", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_freq", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " \ + "defined in the section 'Expression Evaluation', the following functions are available: " \ + "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " \ + "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", \ + FF_MPV_OFFSET(rc_eq), AV_OPT_TYPE_STRING, .flags = FF_MPV_OPT_FLAGS }, \ +{"rc_init_cplx", "initial complexity for 1-pass encoding", FF_MPV_OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_buf_aggressivity", "currently useless", FF_MPV_OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"lmin", "minimum Lagrange factor (VBR)", FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"ibias", "intra quant bias", FF_MPV_OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"pbias", "inter quant bias", FF_MPV_OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"rc_strategy", "ratecontrol method", FF_MPV_OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS }, \ +{"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{"b_strategy", "Strategy to choose between I/P/B-frames", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \ +{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, \ +{"skip_threshold", "Frame skip threshold", FF_MPV_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_factor", "Frame skip factor", FF_MPV_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_exp", "Frame skip exponent", FF_MPV_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_cmp", "Frame skip compare function", FF_MPV_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{"sc_threshold", "Scene change threshold", FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mpeg_quant", "Use MPEG quantizers instead of H.263", FF_MPV_OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS }, \ +{"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ extern const AVOption ff_mpv_generic_options[]; -#define FF_MPV_GENERIC_CLASS(name) \ -static const AVClass name ## _class = {\ - .class_name = #name " encoder",\ - .item_name = av_default_item_name,\ - .option = ff_mpv_generic_options,\ - .version = LIBAVUTIL_VERSION_INT,\ -}; - /** * Set the given MpegEncContext to common defaults (same for encoding * and decoding). The changed fields will not depend upon the prior @@ -707,8 +646,6 @@ void ff_mpv_report_decode_progress(MpegEncContext *s); int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx); void ff_mpv_frame_end(MpegEncContext *s); -int ff_mpv_lowest_referenced_row(MpegEncContext *s, int dir); - int ff_mpv_encode_init(AVCodecContext *avctx); void ff_mpv_encode_init_x86(MpegEncContext *s); @@ -721,8 +658,7 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h); void ff_mpeg_flush(AVCodecContext *avctx); void ff_print_debug_info(MpegEncContext *s, Picture *p); 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, int16_t *block); + int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src); int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); void ff_set_qscale(MpegEncContext * s, int qscale); @@ -741,18 +677,6 @@ void ff_mpv_motion(MpegEncContext *s, op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16]); -/** - * Allocate a Picture. - * The pixels are allocated/set by calling get_buffer() if shared = 0. - */ -int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared); - -/** - * permute block according to permuatation. - * @param last last non zero element in scantable order - */ -void ff_block_permute(int16_t *block, uint8_t *permutation, const uint8_t *scantable, int last); - static inline void ff_update_block_index(MpegEncContext *s){ const int block_size = 8; @@ -776,75 +700,4 @@ static inline int get_bits_diff(MpegEncContext *s){ return bits - last; } -static inline int ff_h263_round_chroma(int x){ - static const uint8_t h263_chroma_roundtab[16] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, - }; - return h263_chroma_roundtab[x & 0xf] + (x >> 3); -} - -/* motion_est.c */ -void ff_estimate_p_frame_motion(MpegEncContext * s, - int mb_x, int mb_y); -void ff_estimate_b_frame_motion(MpegEncContext * s, - int mb_x, int mb_y); -int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type); -void ff_fix_long_p_mvs(MpegEncContext * s); -void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select, - int16_t (*mv_table)[2], int f_code, int type, int truncate); -int ff_init_me(MpegEncContext *s); -int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int mb_x, int mb_y); -int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr, - int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], - int ref_mv_scale, int size, int h); -int ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index, - int ref_index, int size, int h, int add_rate); - -/* mpeg12.c */ -extern const uint8_t ff_mpeg1_dc_scale_table[128]; -extern const uint8_t * const ff_mpeg2_dc_scale_table[4]; - -void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_mpeg1_encode_mb(MpegEncContext *s, - int16_t block[6][64], - int motion_x, int motion_y); -void ff_mpeg1_encode_init(MpegEncContext *s); -void ff_mpeg1_encode_slice_header(MpegEncContext *s); - -extern const uint8_t ff_aic_dc_scale_table[32]; -extern const uint8_t ff_h263_chroma_qscale_table[32]; - -/* rv10.c */ -int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number); -int ff_rv_decode_dc(MpegEncContext *s, int n); -void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number); - - -/* msmpeg4.c */ -void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number); -void ff_msmpeg4_encode_ext_header(MpegEncContext * s); -void ff_msmpeg4_encode_mb(MpegEncContext * s, - int16_t block[6][64], - int motion_x, int motion_y); -int ff_msmpeg4_decode_picture_header(MpegEncContext * s); -int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size); -int ff_msmpeg4_decode_init(AVCodecContext *avctx); -void ff_msmpeg4_encode_init(MpegEncContext *s); -int ff_wmv2_decode_picture_header(MpegEncContext * s); -int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s); -void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr); -void ff_mspel_motion(MpegEncContext *s, - uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - uint8_t **ref_picture, op_pixels_func (*pix_op)[4], - int motion_x, int motion_y, int h); -int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); -void ff_wmv2_encode_mb(MpegEncContext * s, - int16_t block[6][64], - int motion_x, int motion_y); - -int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src); -void ff_mpeg_unref_picture(MpegEncContext *s, Picture *picture); -void ff_free_picture_tables(Picture *pic); - #endif /* AVCODEC_MPEGVIDEO_H */ diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index bbb4422..d738d06 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -40,8 +40,10 @@ #include "idctdsp.h" #include "mpeg12.h" #include "mpegvideo.h" +#include "mpegvideodata.h" #include "h261.h" #include "h263.h" +#include "h263data.h" #include "mjpegenc_common.h" #include "mathops.h" #include "mpegutils.h" @@ -56,6 +58,9 @@ #include "mpeg4video.h" #include "internal.h" #include "bytestream.h" +#include "wmv2.h" +#include "rv10.h" +#include "libxvid.h" #include #define QUANT_BIAS_SHIFT 8 @@ -89,46 +94,46 @@ void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], for (qscale = qmin; qscale <= qmax; qscale++) { int i; if (fdsp->fdct == ff_jpeg_fdct_islow_8 || - fdsp->fdct == ff_jpeg_fdct_islow_10 || - fdsp->fdct == ff_faandct) { +#if CONFIG_FAANDCT + fdsp->fdct == ff_faandct || +#endif /* CONFIG_FAANDCT */ + fdsp->fdct == ff_jpeg_fdct_islow_10) { for (i = 0; i < 64; i++) { const int j = s->idsp.idct_permutation[i]; + int64_t den = (int64_t) qscale * quant_matrix[j]; /* 16 <= qscale * quant_matrix[i] <= 7905 * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] * 19952 <= x <= 249205026 * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026 * 3444240 >= (1 << 36) / (x) >= 275 */ - qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / - (qscale * quant_matrix[j])); + qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / den); } } else if (fdsp->fdct == ff_fdct_ifast) { for (i = 0; i < 64; i++) { const int j = s->idsp.idct_permutation[i]; + int64_t den = ff_aanscales[i] * (int64_t) qscale * quant_matrix[j]; /* 16 <= qscale * quant_matrix[i] <= 7905 * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] * 19952 <= x <= 249205026 * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026 * 3444240 >= (1 << 36) / (x) >= 275 */ - qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 14)) / - (ff_aanscales[i] * qscale * - quant_matrix[j])); + qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 14)) / den); } } else { for (i = 0; i < 64; i++) { const int j = s->idsp.idct_permutation[i]; + int64_t den = (int64_t) qscale * quant_matrix[j]; /* We can safely suppose that 16 <= quant_matrix[i] <= 255 * Assume x = qscale * quant_matrix[i] * So 16 <= x <= 7905 * so (1 << 19) / 16 >= (1 << 19) / (x) >= (1 << 19) / 7905 * so 32768 >= (1 << 19) / (x) >= 67 */ - qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / - (qscale * quant_matrix[j])); + qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / den); //qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / // (qscale * quant_matrix[i]); - qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / - (qscale * quant_matrix[j]); + qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / den; if (qmat16[qscale][0][i] == 0 || qmat16[qscale][0][i] == 128 * 256) @@ -237,6 +242,7 @@ static void mpv_encode_defaults(MpegEncContext *s) av_cold int ff_mpv_encode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; + AVCPBProperties *cpb_props; int i, ret, format_supported; mpv_encode_defaults(s); @@ -289,6 +295,17 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) break; } +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->rtp_payload_size) + s->rtp_payload_size = avctx->rtp_payload_size; + if (avctx->me_penalty_compensation) + s->me_penalty_compensation = avctx->me_penalty_compensation; + if (avctx->pre_me) + s->me_pre = avctx->pre_me; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + s->bit_rate = avctx->bit_rate; s->width = avctx->width; s->height = avctx->height; @@ -300,8 +317,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } s->gop_size = avctx->gop_size; s->avctx = avctx; - s->flags = avctx->flags; - s->flags2 = avctx->flags2; if (avctx->max_b_frames > MAX_B_FRAMES) { av_log(avctx, AV_LOG_ERROR, "Too many B-frames requested, maximum " "is %d.\n", MAX_B_FRAMES); @@ -309,9 +324,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->max_b_frames = avctx->max_b_frames; s->codec_id = avctx->codec->id; s->strict_std_compliance = avctx->strict_std_compliance; - s->quarter_sample = (avctx->flags & CODEC_FLAG_QPEL) != 0; - s->mpeg_quant = avctx->mpeg_quant; - s->rtp_mode = !!avctx->rtp_payload_size; + s->quarter_sample = (avctx->flags & AV_CODEC_FLAG_QPEL) != 0; + s->rtp_mode = !!s->rtp_payload_size; s->intra_dc_precision = avctx->intra_dc_precision; s->user_specified_pts = AV_NOPTS_VALUE; @@ -322,21 +336,32 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->intra_only = 0; } +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS s->me_method = avctx->me_method; +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* Fixed QSCALE */ - s->fixed_qscale = !!(avctx->flags & CODEC_FLAG_QSCALE); + s->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); + +#if FF_API_MPV_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->border_masking != 0.0) + s->border_masking = avctx->border_masking; + FF_ENABLE_DEPRECATION_WARNINGS +#endif 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->border_masking || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) && !s->fixed_qscale; - s->loop_filter = !!(s->flags & CODEC_FLAG_LOOP_FILTER); + s->loop_filter = !!(s->avctx->flags & AV_CODEC_FLAG_LOOP_FILTER); if (avctx->rc_max_rate && !avctx->rc_buffer_size) { av_log(avctx, AV_LOG_ERROR, @@ -393,7 +418,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) "specified vbv buffer is too large for the given bitrate!\n"); } - if ((s->flags & CODEC_FLAG_4MV) && s->codec_id != AV_CODEC_ID_MPEG4 && + if ((s->avctx->flags & AV_CODEC_FLAG_4MV) && s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_H263 && s->codec_id != AV_CODEC_ID_H263P && s->codec_id != AV_CODEC_ID_FLV1) { av_log(avctx, AV_LOG_ERROR, "4MV not supported by codec\n"); @@ -415,7 +440,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_MPEG1VIDEO && s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { - av_log(avctx, AV_LOG_ERROR, "b frames not supported by codec\n"); + av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n"); return -1; } @@ -430,12 +455,19 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return -1; } - if ((s->flags & (CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME)) && + if ((s->avctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME)) && s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codec\n"); return -1; } +#if FF_API_PRIVATE_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->mpeg_quant) + s->mpeg_quant = avctx->mpeg_quant; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + // FIXME mpeg2 uses that too if (s->mpeg_quant && s->codec_id != AV_CODEC_ID_MPEG4) { av_log(avctx, AV_LOG_ERROR, @@ -454,15 +486,22 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return -1; } - if (s->avctx->scenechange_threshold < 1000000000 && - (s->flags & CODEC_FLAG_CLOSED_GOP)) { +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->scenechange_threshold) + s->scenechange_threshold = avctx->scenechange_threshold; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (s->scenechange_threshold < 1000000000 && + (s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { av_log(avctx, AV_LOG_ERROR, "closed gop with scene change detection are not supported yet, " "set threshold to 1000000000\n"); return -1; } - if (s->flags & CODEC_FLAG_LOW_DELAY) { + if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) { if (s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { av_log(avctx, AV_LOG_ERROR, "low delay forcing is only available for mpeg2\n"); @@ -470,7 +509,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } if (s->max_b_frames != 0) { av_log(avctx, AV_LOG_ERROR, - "b frames cannot be used with low delay\n"); + "B-frames cannot be used with low delay\n"); return -1; } } @@ -483,6 +522,12 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } } + if (avctx->slices > 1 && + (avctx->codec_id == AV_CODEC_ID_FLV1 || avctx->codec_id == AV_CODEC_ID_H261)) { + av_log(avctx, AV_LOG_ERROR, "Multiple slices are not supported by this codec\n"); + return AVERROR(EINVAL); + } + if (s->avctx->thread_count > 1 && s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_MPEG1VIDEO && @@ -500,25 +545,24 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) 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->mb_threshold >= i) { - av_log(avctx, AV_LOG_ERROR, "mb_threshold too large, max is %d\n", - i - 1); - return -1; - } +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->b_frame_strategy) + s->b_frame_strategy = avctx->b_frame_strategy; + if (avctx->b_sensitivity != 40) + s->b_sensitivity = avctx->b_sensitivity; +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (avctx->b_frame_strategy && (avctx->flags & CODEC_FLAG_PASS2)) { + if (s->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) { av_log(avctx, AV_LOG_INFO, "notice: b_frame_strategy only affects the first pass\n"); - avctx->b_frame_strategy = 0; + s->b_frame_strategy = 0; } i = av_gcd(avctx->time_base.den, avctx->time_base.num); @@ -540,10 +584,14 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->inter_quant_bias = -(1 << (QUANT_BIAS_SHIFT - 2)); } +#if FF_API_QUANT_BIAS +FF_DISABLE_DEPRECATION_WARNINGS 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; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->codec_id == AV_CODEC_ID_MPEG4 && s->avctx->time_base.den > (1 << 16) - 1) { @@ -559,12 +607,12 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) switch (avctx->codec->id) { case AV_CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; - s->low_delay = !!(s->flags & CODEC_FLAG_LOW_DELAY); + s->low_delay = !!(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY); avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); break; case AV_CODEC_ID_MPEG2VIDEO: s->out_format = FMT_MPEG1; - s->low_delay = !!(s->flags & CODEC_FLAG_LOW_DELAY); + s->low_delay = !!(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY); avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); s->rtp_mode = 1; break; @@ -590,6 +638,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->out_format = FMT_H261; avctx->delay = 0; s->low_delay = 1; + s->rtp_mode = 0; /* Sliced encoding not supported */ break; case AV_CODEC_ID_H263: if (!CONFIG_H263_ENCODER) @@ -611,9 +660,9 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->out_format = FMT_H263; s->h263_plus = 1; /* Fx */ - s->h263_aic = (avctx->flags & CODEC_FLAG_AC_PRED) ? 1 : 0; + s->h263_aic = (avctx->flags & AV_CODEC_FLAG_AC_PRED) ? 1 : 0; s->modified_quant = s->h263_aic; - s->loop_filter = (avctx->flags & CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + s->loop_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; s->unrestricted_mv = s->obmc || s->loop_filter || s->umvplus; /* /Fx */ @@ -690,13 +739,20 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return -1; } +#if FF_API_PRIVATE_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->noise_reduction) + s->noise_reduction = avctx->noise_reduction; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + avctx->has_b_frames = !s->low_delay; s->encoding = 1; s->progressive_frame = - s->progressive_sequence = !(avctx->flags & (CODEC_FLAG_INTERLACED_DCT | - CODEC_FLAG_INTERLACED_ME) || + s->progressive_sequence = !(avctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | + AV_CODEC_FLAG_INTERLACED_ME) || s->alternate_scan); /* init */ @@ -713,8 +769,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ff_pixblockdsp_init(&s->pdsp, avctx); ff_qpeldsp_init(&s->qdsp); - s->avctx->coded_frame = s->current_picture.f; - if (s->msmpeg4_version) { FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, 2 * 2 * (MAX_LEVEL + 1) * @@ -731,7 +785,8 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture *), fail); - if (s->avctx->noise_reduction) { + + if (s->noise_reduction) { FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), fail); } @@ -749,17 +804,38 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if ((CONFIG_H263P_ENCODER || CONFIG_RV20_ENCODER) && s->modified_quant) s->chroma_qscale_table = ff_h263_chroma_qscale_table; + if (s->slice_context_count > 1) { + s->rtp_mode = 1; + + if (avctx->codec_id == AV_CODEC_ID_H263 || avctx->codec_id == AV_CODEC_ID_H263P) + s->h263_slice_structured = 1; + } + s->quant_precision = 5; +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->frame_skip_threshold) + s->frame_skip_threshold = avctx->frame_skip_threshold; + if (avctx->frame_skip_factor) + s->frame_skip_factor = avctx->frame_skip_factor; + if (avctx->frame_skip_exp) + s->frame_skip_exp = avctx->frame_skip_exp; + if (avctx->frame_skip_cmp != FF_CMP_DCTMAX) + s->frame_skip_cmp = avctx->frame_skip_cmp; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + ff_set_cmp(&s->mecc, s->mecc.ildct_cmp, s->avctx->ildct_cmp); - ff_set_cmp(&s->mecc, s->mecc.frame_skip_cmp, s->avctx->frame_skip_cmp); + ff_set_cmp(&s->mecc, s->mecc.frame_skip_cmp, s->frame_skip_cmp); if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) ff_h261_encode_init(s); if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) ff_h263_encode_init(s); if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) - ff_msmpeg4_encode_init(s); + if ((ret = ff_msmpeg4_encode_init(s)) < 0) + return ret; if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) && s->out_format == FMT_MPEG1) ff_mpeg1_encode_init(s); @@ -775,7 +851,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->intra_matrix[j] = s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; } else { - /* mpeg1/2 */ + /* MPEG-1/2 */ s->intra_matrix[j] = ff_mpeg1_default_intra_matrix[i]; s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; } @@ -796,9 +872,28 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) 31, 0); } +#if FF_API_RC_STRATEGY +FF_DISABLE_DEPRECATION_WARNINGS + if (!s->rc_strategy) + s->rc_strategy = s->avctx->rc_strategy; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (ff_rate_control_init(s) < 0) return -1; + if ((s->avctx->flags & AV_CODEC_FLAG_PASS2) && s->rc_strategy == 1) { +#if CONFIG_LIBXVID + ret = ff_xvid_rate_control_init(s); +#else + ret = AVERROR(ENOSYS); + av_log(s->avctx, AV_LOG_ERROR, + "Xvid ratecontrol requires libavcodec compiled with Xvid support.\n"); +#endif + if (ret < 0) + return ret; + } + #if FF_API_ERROR_RATE FF_DISABLE_DEPRECATION_WARNINGS if (avctx->error_rate) @@ -820,15 +915,51 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) FF_ENABLE_DEPRECATION_WARNINGS #endif - if (avctx->b_frame_strategy == 2) { +#if FF_API_MPV_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->rc_qsquish != 0.0) + s->rc_qsquish = avctx->rc_qsquish; + if (avctx->rc_qmod_amp != 0.0) + s->rc_qmod_amp = avctx->rc_qmod_amp; + if (avctx->rc_qmod_freq) + s->rc_qmod_freq = avctx->rc_qmod_freq; + if (avctx->rc_buffer_aggressivity != 1.0) + s->rc_buffer_aggressivity = avctx->rc_buffer_aggressivity; + if (avctx->rc_initial_cplx != 0.0) + s->rc_initial_cplx = avctx->rc_initial_cplx; + if (avctx->lmin) + s->lmin = avctx->lmin; + if (avctx->lmax) + s->lmax = avctx->lmax; + + if (avctx->rc_eq) { + av_freep(&s->rc_eq); + s->rc_eq = av_strdup(avctx->rc_eq); + if (!s->rc_eq) + return AVERROR(ENOMEM); + } + FF_ENABLE_DEPRECATION_WARNINGS +#endif + +#if FF_API_PRIVATE_OPT + FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->brd_scale) + s->brd_scale = avctx->brd_scale; + + if (avctx->prediction_method) + s->pred = avctx->prediction_method + 1; + FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (s->b_frame_strategy == 2) { for (i = 0; i < s->max_b_frames + 2; i++) { s->tmp_frames[i] = av_frame_alloc(); if (!s->tmp_frames[i]) return AVERROR(ENOMEM); s->tmp_frames[i]->format = AV_PIX_FMT_YUV420P; - s->tmp_frames[i]->width = s->width >> avctx->brd_scale; - s->tmp_frames[i]->height = s->height >> avctx->brd_scale; + s->tmp_frames[i]->width = s->width >> s->brd_scale; + s->tmp_frames[i]->height = s->height >> s->brd_scale; ret = av_frame_get_buffer(s->tmp_frames[i], 32); if (ret < 0) @@ -836,6 +967,14 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } } + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->min_bitrate = avctx->rc_min_rate; + cpb_props->avg_bitrate = avctx->bit_rate; + cpb_props->buffer_size = avctx->rc_buffer_size; + return 0; fail: ff_mpv_encode_end(avctx); @@ -848,6 +987,10 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) int i; ff_rate_control_uninit(s); +#if CONFIG_LIBXVID + if ((avctx->flags & AV_CODEC_FLAG_PASS2) && s->rc_strategy == 1) + ff_xvid_rate_control_uninit(s); +#endif ff_mpv_common_end(s); if (CONFIG_MJPEG_ENCODER && @@ -860,7 +1003,7 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) av_frame_free(&s->tmp_frames[i]); ff_free_picture_tables(&s->new_picture); - ff_mpeg_unref_picture(s, &s->new_picture); + ff_mpeg_unref_picture(s->avctx, &s->new_picture); av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); @@ -913,14 +1056,22 @@ static int get_intra_count(MpegEncContext *s, uint8_t *src, return acc; } +static int alloc_picture(MpegEncContext *s, Picture *pic, int shared) +{ + return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, shared, 1, + s->chroma_x_shift, s->chroma_y_shift, s->out_format, + s->mb_stride, s->mb_height, s->b8_stride, + &s->linesize, &s->uvlinesize); +} static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) { Picture *pic = NULL; int64_t pts; int i, display_picture_number = 0, ret; - const int encoding_delay = s->max_b_frames ? s->max_b_frames : - (s->low_delay ? 0 : 1); + int encoding_delay = s->max_b_frames ? s->max_b_frames + : (s->low_delay ? 0 : 1); + int flush_offset = 1; int direct = 1; if (pic_arg) { @@ -954,46 +1105,34 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) pts = display_picture_number; } } - } - if (pic_arg) { - if (!pic_arg->buf[0]); - direct = 0; - if (pic_arg->linesize[0] != s->linesize) + if (!pic_arg->buf[0] || + pic_arg->linesize[0] != s->linesize || + pic_arg->linesize[1] != s->uvlinesize || + pic_arg->linesize[2] != s->uvlinesize) direct = 0; - if (pic_arg->linesize[1] != s->uvlinesize) - direct = 0; - if (pic_arg->linesize[2] != s->uvlinesize) + if ((s->width & 15) || (s->height & 15)) direct = 0; - av_dlog(s->avctx, "%d %d %td %td\n", pic_arg->linesize[0], + ff_dlog(s->avctx, "%d %d %td %td\n", pic_arg->linesize[0], pic_arg->linesize[1], s->linesize, s->uvlinesize); - if (direct) { - i = ff_find_unused_picture(s, 1); - if (i < 0) - return i; + i = ff_find_unused_picture(s->avctx, s->picture, direct); + if (i < 0) + return i; - pic = &s->picture[i]; - pic->reference = 3; + pic = &s->picture[i]; + pic->reference = 3; + if (direct) { if ((ret = av_frame_ref(pic->f, pic_arg)) < 0) return ret; - if (ff_alloc_picture(s, pic, 1) < 0) { - return -1; - } - } else { - i = ff_find_unused_picture(s, 0); - if (i < 0) - return i; - - pic = &s->picture[i]; - pic->reference = 3; - - if (ff_alloc_picture(s, pic, 0) < 0) { - return -1; - } + } + ret = alloc_picture(s, pic, direct); + if (ret < 0) + return ret; + if (!direct) { if (pic->f->data[0] + INPLACE_OFFSET == pic_arg->data[0] && pic->f->data[1] + INPLACE_OFFSET == pic_arg->data[1] && pic->f->data[2] + INPLACE_OFFSET == pic_arg->data[2]) { @@ -1020,12 +1159,21 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) if (src_stride == dst_stride) memcpy(dst, src, src_stride * h); else { - while (h--) { - memcpy(dst, src, w); - dst += dst_stride; + int h2 = h; + uint8_t *dst2 = dst; + while (h2--) { + memcpy(dst2, src, w); + dst2 += dst_stride; src += src_stride; } } + if ((s->width & 15) || (s->height & 15)) { + s->mpvencdsp.draw_edges(dst, dst_stride, + w, h, + 16 >> h_shift, + 16 >> v_shift, + EDGE_BOTTOM); + } } } } @@ -1034,12 +1182,23 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) return ret; pic->f->display_picture_number = display_picture_number; - pic->f->pts = pts; // we set this here to avoid modifiying pic_arg + pic->f->pts = pts; // we set this here to avoid modifying pic_arg + } else { + /* Flushing: When we have not received enough input frames, + * ensure s->input_picture[0] contains the first picture */ + for (flush_offset = 0; flush_offset < encoding_delay + 1; flush_offset++) + if (s->input_picture[flush_offset]) + break; + + if (flush_offset <= 1) + flush_offset = 1; + else + encoding_delay = encoding_delay - flush_offset + 1; } /* shift buffer entries */ - for (i = 1; i < MAX_PICTURE_COUNT /*s->encoding_delay + 1*/; i++) - s->input_picture[i - 1] = s->input_picture[i]; + for (i = flush_offset; i < MAX_PICTURE_COUNT /*s->encoding_delay + 1*/; i++) + s->input_picture[i - flush_offset] = s->input_picture[i]; s->input_picture[encoding_delay] = (Picture*) pic; @@ -1062,7 +1221,7 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) uint8_t *rptr = ref->f->data[plane] + 8 * (x + y * stride); int v = s->mecc.frame_skip_cmp[1](s, dptr, rptr, stride, 8); - switch (s->avctx->frame_skip_exp) { + switch (s->frame_skip_exp) { case 0: score = FFMAX(score, v); break; case 1: score += FFABS(v); break; case 2: score += v * v; break; @@ -1076,9 +1235,9 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) if (score) score64 = score; - if (score64 < s->avctx->frame_skip_threshold) + if (score64 < s->frame_skip_threshold) return 1; - if (score64 < ((s->avctx->frame_skip_factor * (int64_t)s->lambda) >> 8)) + if (score64 < ((s->frame_skip_factor * (int64_t) s->lambda) >> 8)) return 1; return 0; } @@ -1094,7 +1253,7 @@ static int encode_frame(AVCodecContext *c, AVFrame *frame) return ret; ret = pkt.size; - av_free_packet(&pkt); + av_packet_unref(&pkt); return ret; } @@ -1102,11 +1261,13 @@ static int estimate_best_b_count(MpegEncContext *s) { AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); AVCodecContext *c = avcodec_alloc_context3(NULL); - const int scale = s->avctx->brd_scale; + const int scale = s->brd_scale; int i, j, out_size, p_lambda, b_lambda, lambda2; int64_t best_rd = INT64_MAX; int best_b_count = -1; + if (!c) + return AVERROR(ENOMEM); assert(scale >= 0 && scale <= 3); //emms_c(); @@ -1121,8 +1282,8 @@ static int estimate_best_b_count(MpegEncContext *s) c->width = s->width >> scale; c->height = s->height >> scale; - c->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR; - c->flags |= s->avctx->flags & CODEC_FLAG_QPEL; + c->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_PSNR; + c->flags |= s->avctx->flags & AV_CODEC_FLAG_QPEL; c->mb_decision = s->avctx->mb_decision; c->me_cmp = s->avctx->me_cmp; c->mb_cmp = s->avctx->mb_cmp; @@ -1206,8 +1367,7 @@ static int estimate_best_b_count(MpegEncContext *s) } } - avcodec_close(c); - av_freep(&c); + avcodec_free_context(&c); return best_b_count; } @@ -1229,12 +1389,12 @@ static int select_input_picture(MpegEncContext *s) s->reordered_input_picture[0]->f->coded_picture_number = s->coded_picture_number++; } else { - int b_frames; + int b_frames = 0; - if (s->avctx->frame_skip_threshold || s->avctx->frame_skip_factor) { + if (s->frame_skip_threshold || s->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 + // FIXME check that the gop check above is +-1 correct av_frame_unref(s->input_picture[0]->f); emms_c(); @@ -1244,7 +1404,7 @@ static int select_input_picture(MpegEncContext *s) } } - if (s->flags & CODEC_FLAG_PASS2) { + if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { for (i = 0; i < s->max_b_frames + 1; i++) { int pict_num = s->input_picture[0]->f->display_picture_number + i; @@ -1260,11 +1420,11 @@ static int select_input_picture(MpegEncContext *s) } } - if (s->avctx->b_frame_strategy == 0) { + if (s->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) { + } else if (s->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) { @@ -1278,7 +1438,7 @@ static int select_input_picture(MpegEncContext *s) for (i = 0; i < s->max_b_frames + 1; i++) { if (!s->input_picture[i] || s->input_picture[i]->b_frame_score - 1 > - s->mb_num / s->avctx->b_sensitivity) + s->mb_num / s->b_sensitivity) break; } @@ -1288,11 +1448,8 @@ static int select_input_picture(MpegEncContext *s) for (i = 0; i < b_frames + 1; i++) { s->input_picture[i]->b_frame_score = 0; } - } else if (s->avctx->b_frame_strategy == 2) { + } else if (s->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(); @@ -1305,7 +1462,7 @@ static int select_input_picture(MpegEncContext *s) if (s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_B && b_frames == s->max_b_frames) { av_log(s->avctx, AV_LOG_ERROR, - "warning, too many b frames in a row\n"); + "warning, too many B-frames in a row\n"); } if (s->picture_in_gop_number + b_frames >= s->gop_size) { @@ -1313,13 +1470,13 @@ static int select_input_picture(MpegEncContext *s) 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) + if (s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) b_frames = 0; s->input_picture[b_frames]->f->pict_type = AV_PICTURE_TYPE_I; } } - if ((s->flags & CODEC_FLAG_CLOSED_GOP) && b_frames && + if ((s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) && b_frames && s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_I) b_frames--; @@ -1338,27 +1495,28 @@ static int select_input_picture(MpegEncContext *s) } } no_output_pic: + ff_mpeg_unref_picture(s->avctx, &s->new_picture); + if (s->reordered_input_picture[0]) { s->reordered_input_picture[0]->reference = s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_B ? 3 : 0; - ff_mpeg_unref_picture(s, &s->new_picture); - if ((ret = ff_mpeg_ref_picture(s, &s->new_picture, s->reordered_input_picture[0]))) + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->new_picture, s->reordered_input_picture[0]))) return ret; if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) { - // input is a shared pix, so we can't modifiy it -> alloc a new + // input is a shared pix, so we can't modify it -> allocate a new // one & ensure that the shared one is reuseable Picture *pic; - int i = ff_find_unused_picture(s, 0); + int i = ff_find_unused_picture(s->avctx, s->picture, 0); if (i < 0) return i; pic = &s->picture[i]; pic->reference = s->reordered_input_picture[0]->reference; - if (ff_alloc_picture(s, pic, 0) < 0) { + if (alloc_picture(s, pic, 0) < 0) { return -1; } @@ -1378,14 +1536,12 @@ no_output_pic: s->new_picture.f->data[i] += INPLACE_OFFSET; } } - ff_mpeg_unref_picture(s, &s->current_picture); - if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, s->current_picture_ptr)) < 0) return ret; s->picture_number = s->new_picture.f->display_picture_number; - } else { - ff_mpeg_unref_picture(s, &s->new_picture); } return 0; } @@ -1429,12 +1585,21 @@ static void frame_end(MpegEncContext *s) /* release non-reference frames */ for (i = 0; i < MAX_PICTURE_COUNT; i++) { if (!s->picture[i].reference) - ff_mpeg_unref_picture(s, &s->picture[i]); + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); } } - s->avctx->coded_frame = s->current_picture_ptr->f; - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_copy_props(s->avctx->coded_frame, s->current_picture.f); +FF_ENABLE_DEPRECATION_WARNINGS +#endif +#if FF_API_ERROR_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + memcpy(s->current_picture.f->error, s->current_picture.encoding_error, + sizeof(s->current_picture.encoding_error)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } static void update_noise_reduction(MpegEncContext *s) @@ -1450,7 +1615,7 @@ static void update_noise_reduction(MpegEncContext *s) } for (i = 0; i < 64; i++) { - s->dct_offset[intra][i] = (s->avctx->noise_reduction * + s->dct_offset[intra][i] = (s->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i] / 2) / (s->dct_error_sum[intra][i] + 1); @@ -1466,14 +1631,14 @@ static int frame_start(MpegEncContext *s) if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f->buf[0]) { - ff_mpeg_unref_picture(s, s->last_picture_ptr); + ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); } s->current_picture_ptr->f->pict_type = s->pict_type; s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; - ff_mpeg_unref_picture(s, &s->current_picture); - if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, s->current_picture_ptr)) < 0) return ret; @@ -1484,16 +1649,16 @@ static int frame_start(MpegEncContext *s) } if (s->last_picture_ptr) { - ff_mpeg_unref_picture(s, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); if (s->last_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s, &s->last_picture, + (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, s->last_picture_ptr)) < 0) return ret; } if (s->next_picture_ptr) { - ff_mpeg_unref_picture(s, &s->next_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); if (s->next_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s, &s->next_picture, + (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, s->next_picture_ptr)) < 0) return ret; } @@ -1523,13 +1688,35 @@ static int frame_start(MpegEncContext *s) } if (s->dct_error_sum) { - assert(s->avctx->noise_reduction && s->encoding); + assert(s->noise_reduction && s->encoding); update_noise_reduction(s); } return 0; } +static void write_pass1_stats(MpegEncContext *s) +{ + snprintf(s->avctx->stats_out, 256, + "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d " + "fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d " + "hbits:%d;\n", + s->current_picture_ptr->f->display_picture_number, + s->current_picture_ptr->f->coded_picture_number, + s->pict_type, + s->current_picture.f->quality, + s->i_tex_bits, + s->p_tex_bits, + s->mv_bits, + s->misc_bits, + s->f_code, + s->b_code, + s->current_picture.mc_mb_var_sum, + s->current_picture.mb_var_sum, + s->i_count, s->skip_count, + s->header_bits); +} + int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic_arg, int *got_packet) { @@ -1548,6 +1735,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, /* output? */ if (s->new_picture.f->data[0]) { + uint8_t *sd; if (!pkt->data && (ret = ff_alloc_packet(pkt, s->mb_width*s->mb_height*MAX_MB_BYTES)) < 0) return ret; @@ -1577,6 +1765,8 @@ vbv_retry: if (encode_picture(s, s->picture_number) < 0) return -1; +#if FF_API_STAT_BITS +FF_DISABLE_DEPRECATION_WARNINGS avctx->header_bits = s->header_bits; avctx->mv_bits = s->mv_bits; avctx->misc_bits = s->misc_bits; @@ -1586,9 +1776,17 @@ vbv_retry: // FIXME f/b_count in avctx avctx->p_count = s->mb_num - s->i_count - s->skip_count; avctx->skip_count = s->skip_count; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame_end(s); + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = s->current_picture.f->quality; + if (CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG) ff_mjpeg_encode_picture_trailer(&s->pb, s->header_bits); @@ -1597,7 +1795,7 @@ vbv_retry: int max_size = rcc->buffer_index * avctx->rc_max_available_vbv_use; if (put_bits_count(&s->pb) > max_size && - s->lambda < s->avctx->lmax) { + s->lambda < s->lmax) { s->next_lambda = FFMAX(s->lambda + 1, s->lambda * (s->qscale + 1) / s->qscale); if (s->adaptive_quant) { @@ -1630,18 +1828,18 @@ vbv_retry: assert(s->avctx->rc_max_rate); } - if (s->flags & CODEC_FLAG_PASS1) - ff_write_pass1_stats(s); + if (s->avctx->flags & AV_CODEC_FLAG_PASS1) + write_pass1_stats(s); for (i = 0; i < 4; i++) { - s->current_picture_ptr->f->error[i] = s->current_picture.f->error[i]; - avctx->error[i] += s->current_picture_ptr->f->error[i]; + s->current_picture_ptr->encoding_error[i] = s->current_picture.encoding_error[i]; + avctx->error[i] += s->current_picture_ptr->encoding_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)); + if (s->avctx->flags & AV_CODEC_FLAG_PASS1) + assert(put_bits_count(&s->pb) == s->header_bits + s->mv_bits + + s->misc_bits + s->i_tex_bits + + s->p_tex_bits); flush_put_bits(&s->pb); s->frame_bits = put_bits_count(&s->pb); @@ -1675,12 +1873,15 @@ vbv_retry: s->frame_bits = put_bits_count(&s->pb); } - /* update mpeg1/2 vbv_delay for CBR */ + /* update MPEG-1/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) { + AVCPBProperties *props; + size_t props_size; + int vbv_delay, min_delay; double inbits = s->avctx->rc_max_rate * av_q2d(s->avctx->time_base); @@ -1707,10 +1908,32 @@ vbv_retry: s->vbv_delay_ptr[1] = vbv_delay >> 5; s->vbv_delay_ptr[2] &= 0x07; s->vbv_delay_ptr[2] |= vbv_delay << 3; + + props = av_cpb_properties_alloc(&props_size); + if (!props) + return AVERROR(ENOMEM); + props->vbv_delay = vbv_delay * 300; + + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_CPB_PROPERTIES, + (uint8_t*)props, props_size); + if (ret < 0) { + av_freep(&props); + return ret; + } + +#if FF_API_VBV_DELAY +FF_DISABLE_DEPRECATION_WARNINGS avctx->vbv_delay = vbv_delay * 300; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } s->total_bits += s->frame_bits; +#if FF_API_STAT_BITS +FF_DISABLE_DEPRECATION_WARNINGS avctx->frame_bits = s->frame_bits; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + pkt->pts = s->current_picture.f->pts; if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { @@ -1907,7 +2130,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, (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; + uint8_t *ebuf = s->sc.edge_emu_buffer + 32; s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, wrap_y, 16, 16, mb_x * 16, mb_y * 16, @@ -1926,7 +2149,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } if (s->mb_intra) { - if (s->flags & CODEC_FLAG_INTERLACED_DCT) { + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { int progressive_score, interlaced_score; s->interlaced_dct = 0; @@ -1955,7 +2178,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, s->pdsp.get_pixels(s->block[2], ptr_y + dct_offset, wrap_y); s->pdsp.get_pixels(s->block[3], ptr_y + dct_offset + 8, wrap_y); - if (s->flags & CODEC_FLAG_GRAY) { + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { skip_dct[4] = 1; skip_dct[5] = 1; } else { @@ -1998,7 +2221,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, op_pix, op_qpix); } - if (s->flags & CODEC_FLAG_INTERLACED_DCT) { + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { int progressive_score, interlaced_score; s->interlaced_dct = 0; @@ -2035,7 +2258,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, s->pdsp.diff_pixels(s->block[3], ptr_y + dct_offset + 8, dest_y + dct_offset + 8, wrap_y); - if (s->flags & CODEC_FLAG_GRAY) { + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { skip_dct[4] = 1; skip_dct[5] = 1; } else { @@ -2145,7 +2368,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } } - if ((s->flags & CODEC_FLAG_GRAY) && s->mb_intra) { + if ((s->avctx->flags & AV_CODEC_FLAG_GRAY) && s->mb_intra) { s->block_last_index[4] = s->block_last_index[5] = 0; s->block[4][0] = @@ -2219,7 +2442,7 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop? - /* mpeg1 */ + /* MPEG-1 */ d->mb_skip_run= s->mb_skip_run; for(i=0; i<3; i++) d->last_dc[i] = s->last_dc[i]; @@ -2248,7 +2471,7 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext * memcpy(d->mv, s->mv, 2*4*2*sizeof(int)); memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop? - /* mpeg1 */ + /* MPEG-1 */ d->mb_skip_run= s->mb_skip_run; for(i=0; i<3; i++) d->last_dc[i] = s->last_dc[i]; @@ -2299,9 +2522,9 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE 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; + s->dest[0] = s->sc.rd_scratchpad; + s->dest[1] = s->sc.rd_scratchpad + 16*s->linesize; + s->dest[2] = s->sc.rd_scratchpad + 16*s->linesize + 8; assert(s->linesize >= 32); //FIXME } @@ -2457,7 +2680,7 @@ static void write_slice_end(MpegEncContext *s){ avpriv_align_put_bits(&s->pb); flush_put_bits(&s->pb); - if((s->flags&CODEC_FLAG_PASS1) && !s->partitioned_frame) + if ((s->avctx->flags & AV_CODEC_FLAG_PASS1) && !s->partitioned_frame) s->misc_bits+= get_bits_diff(s); } @@ -2506,10 +2729,10 @@ static void update_mb_info(MpegEncContext *s, int startcode) static int encode_thread(AVCodecContext *c, void *arg){ MpegEncContext *s= *(void**)arg; - int mb_x, mb_y, pdif = 0; + int mb_x, mb_y; int chr_h= 16>>s->chroma_y_shift; int i, j; - MpegEncContext best_s, backup_s; + MpegEncContext best_s = { 0 }, 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]; @@ -2536,7 +2759,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ /* note: quant matrix value (8) is implied here */ s->last_dc[i] = 128 << s->intra_dc_precision; - s->current_picture.f->error[i] = 0; + s->current_picture.encoding_error[i] = 0; } s->mb_skip_run = 0; memset(s->last_mv, 0, sizeof(s->last_mv)); @@ -2548,7 +2771,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ case AV_CODEC_ID_H263P: case AV_CODEC_ID_FLV1: if (CONFIG_H263_ENCODER) - s->gob_index = ff_h263_get_gob_height(s); + s->gob_index = H263_GOB_HEIGHT(s->height); break; case AV_CODEC_ID_MPEG4: if(CONFIG_MPEG4_ENCODER && s->partitioned_frame) @@ -2602,7 +2825,9 @@ static int encode_thread(AVCodecContext *c, void *arg){ 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; + is_gob_start = s->rtp_payload_size && + current_packet_size >= s->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; @@ -2641,10 +2866,14 @@ static int encode_thread(AVCodecContext *c, void *arg){ } } +#if FF_API_RTP_CALLBACK +FF_DISABLE_DEPRECATION_WARNINGS 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); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif update_mb_info(s, 1); switch(s->codec_id){ @@ -2668,7 +2897,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ break; } - if(s->flags&CODEC_FLAG_PASS1){ + if (s->avctx->flags & AV_CODEC_FLAG_PASS1) { int bits= put_bits_count(&s->pb); s->misc_bits+= bits - s->last_bits; s->last_bits= bits; @@ -2953,9 +3182,9 @@ static int encode_thread(AVCodecContext *c, void *arg){ ff_h263_update_motion_val(s); if(next_block==0){ //FIXME 16 vs linesize16 - s->hdsp.put_pixels_tab[0][0](s->dest[0], s->rd_scratchpad , s->linesize ,16); - s->hdsp.put_pixels_tab[1][0](s->dest[1], s->rd_scratchpad + 16*s->linesize , s->uvlinesize, 8); - s->hdsp.put_pixels_tab[1][0](s->dest[2], s->rd_scratchpad + 16*s->linesize + 8, s->uvlinesize, 8); + s->hdsp.put_pixels_tab[0][0](s->dest[0], s->sc.rd_scratchpad , s->linesize ,16); + s->hdsp.put_pixels_tab[1][0](s->dest[1], s->sc.rd_scratchpad + 16*s->linesize , s->uvlinesize, 8); + s->hdsp.put_pixels_tab[1][0](s->dest[2], s->sc.rd_scratchpad + 16*s->linesize + 8, s->uvlinesize, 8); } if(s->avctx->mb_decision == FF_MB_DECISION_BITS) @@ -3081,26 +3310,26 @@ static int encode_thread(AVCodecContext *c, void *arg){ ff_mpv_decode_mb(s, s->block); } - /* clean the MV table in IPS frames for direct mode in B frames */ + /* 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){ + if (s->avctx->flags & AV_CODEC_FLAG_PSNR) { int w= 16; int h= 16; if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; - s->current_picture.f->error[0] += sse( + s->current_picture.encoding_error[0] += sse( s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize); - s->current_picture.f->error[1] += sse( + s->current_picture.encoding_error[1] += sse( s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[1], w>>1, h>>s->chroma_y_shift, s->uvlinesize); - s->current_picture.f->error[2] += sse( + s->current_picture.encoding_error[2] += sse( s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[2], w>>1, h>>s->chroma_y_shift, s->uvlinesize); } @@ -3108,7 +3337,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ if(CONFIG_H263_ENCODER && s->out_format == FMT_H263) ff_h263_loop_filter(s); } - av_dlog(s->avctx, "MB %d %d bits\n", + ff_dlog(s->avctx, "MB %d %d bits\n", s->mb_x + s->mb_y * s->mb_stride, put_bits_count(&s->pb)); } } @@ -3119,14 +3348,18 @@ static int encode_thread(AVCodecContext *c, void *arg){ write_slice_end(s); +#if FF_API_RTP_CALLBACK +FF_DISABLE_DEPRECATION_WARNINGS /* Send the last GOB if RTP */ if (s->avctx->rtp_callback) { int number_mb = (mb_y - s->resync_mb_y)*s->mb_width - s->resync_mb_x; - pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob; + int pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob; /* Call the RTP callback to send the last GOB */ emms_c(); s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, pdif, number_mb); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -3153,11 +3386,11 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) MERGE(misc_bits); MERGE(er.error_count); MERGE(padding_bug_score); - MERGE(current_picture.f->error[0]); - MERGE(current_picture.f->error[1]); - MERGE(current_picture.f->error[2]); + MERGE(current_picture.encoding_error[0]); + MERGE(current_picture.encoding_error[1]); + MERGE(current_picture.encoding_error[2]); - if(dst->avctx->noise_reduction){ + if (dst->noise_reduction){ for(i=0; i<64; i++){ MERGE(dct_error_sum[0][i]); MERGE(dct_error_sum[1][i]); @@ -3176,8 +3409,15 @@ static int estimate_qp(MpegEncContext *s, int dry_run){ s->current_picture.f->quality = s->next_lambda; if(!dry_run) s->next_lambda= 0; } else if (!s->fixed_qscale) { + int quality; +#if CONFIG_LIBXVID + if ((s->avctx->flags & AV_CODEC_FLAG_PASS2) && s->rc_strategy == 1) + quality = ff_xvid_rate_estimate_qscale(s, dry_run); + else +#endif + quality = ff_rate_estimate_qscale(s, dry_run); s->current_picture_ptr->f->quality = - s->current_picture.f->quality = ff_rate_estimate_qscale(s, dry_run); + s->current_picture.f->quality = quality; if (s->current_picture.f->quality < 0) return -1; } @@ -3233,7 +3473,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) 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 */ + /* we need to initialize some time vars before we can encode B-frames */ // RAL: Condition added for MPEG1VIDEO if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->msmpeg4_version)) set_frame_distances(s); @@ -3252,11 +3492,11 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->no_rounding ^= 1; } - if(s->flags & CODEC_FLAG_PASS2){ + if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { if (estimate_qp(s,1) < 0) return -1; ff_get_2pass_fcode(s); - }else if(!(s->flags & CODEC_FLAG_QSCALE)){ + } else if (!(s->avctx->flags & AV_CODEC_FLAG_QSCALE)) { if(s->pict_type==AV_PICTURE_TYPE_B) s->lambda= s->last_lambda_for[s->pict_type]; else @@ -3276,10 +3516,11 @@ static int encode_picture(MpegEncContext *s, int picture_number) /* Estimate motion for every MB */ if(s->pict_type != AV_PICTURE_TYPE_I){ - s->lambda = (s->lambda * s->avctx->me_penalty_compensation + 128)>>8; - s->lambda2= (s->lambda2* (int64_t)s->avctx->me_penalty_compensation + 128)>>8; + s->lambda = (s->lambda * s->me_penalty_compensation + 128) >> 8; + s->lambda2 = (s->lambda2 * (int64_t) s->me_penalty_compensation + 128) >> 8; if (s->pict_type != AV_PICTURE_TYPE_B) { - if((s->avctx->pre_me && s->last_non_b_pict_type==AV_PICTURE_TYPE_I) || s->avctx->pre_me==2){ + if ((s->me_pre && s->last_non_b_pict_type == AV_PICTURE_TYPE_I) || + s->me_pre == 2) { s->avctx->execute(s->avctx, pre_estimate_motion_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); } } @@ -3302,11 +3543,12 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->current_picture. mb_var_sum= s->current_picture_ptr-> mb_var_sum= s->me. mb_var_sum_temp; emms_c(); - if(s->me.scene_change_score > s->avctx->scenechange_threshold && s->pict_type == AV_PICTURE_TYPE_P){ + if (s->me.scene_change_score > s->scenechange_threshold && + s->pict_type == AV_PICTURE_TYPE_P) { s->pict_type= AV_PICTURE_TYPE_I; for(i=0; imb_stride*s->mb_height; i++) s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; - av_dlog(s, "Scene change detected, encoding as I Frame %d %d\n", + ff_dlog(s, "Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); } @@ -3314,7 +3556,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) if(s->pict_type==AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) { s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); - if(s->flags & CODEC_FLAG_INTERLACED_ME){ + if (s->avctx->flags & AV_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); @@ -3323,7 +3565,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) 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){ + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { int j; for(i=0; i<2; i++){ for(j=0; j<2; j++) @@ -3348,7 +3590,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) 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){ + if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { int dir, j; for(dir=0; dir<2; dir++){ for(i=0; i<2; i++){ @@ -3367,7 +3609,9 @@ static int encode_picture(MpegEncContext *s, int picture_number) if (estimate_qp(s, 0) < 0) return -1; - if(s->qscale < 3 && s->max_qcoeff<=128 && s->pict_type==AV_PICTURE_TYPE_I && !(s->flags & CODEC_FLAG_QSCALE)) + if (s->qscale < 3 && s->max_qcoeff <= 128 && + s->pict_type == AV_PICTURE_TYPE_I && + !(s->avctx->flags & AV_CODEC_FLAG_QSCALE)) s->qscale= 3; //reduce clipping problems if (s->out_format == FMT_MJPEG) { @@ -3399,7 +3643,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) case FMT_MJPEG: if (CONFIG_MJPEG_ENCODER) ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->intra_matrix); + s->pred, s->intra_matrix); break; case FMT_H261: if (CONFIG_H261_ENCODER) @@ -3604,7 +3848,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, if(s->out_format == FMT_H263){ unquant_coeff= alevel*qmul + qadd; - }else{ //MPEG1 + } else { // MPEG-1 j = s->idsp.idct_permutation[scantable[i]]; // FIXME: optimize if(s->mb_intra){ unquant_coeff = (int)( alevel * qscale * s->intra_matrix[j]) >> 3; @@ -3674,7 +3918,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, 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 + // Note: there is a vlc code in MPEG-4 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) @@ -3694,7 +3938,8 @@ static int dct_quantize_trellis_c(MpegEncContext *s, 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 (i) + score += lambda * 2; // FIXME more exact? if(score < last_score){ last_score= score; @@ -3725,7 +3970,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s, if(s->out_format == FMT_H263){ unquant_coeff= (alevel*qmul + qadd)>>3; - }else{ //MPEG1 + } else { // MPEG-1 unquant_coeff = ((( alevel << 1) + 1) * qscale * ((int) s->inter_matrix[0])) >> 4; unquant_coeff = (unquant_coeff - 1) | 1; } @@ -3848,7 +4093,7 @@ static int messed_sign=0; #endif dc += (1<<(RECON_SHIFT-1)); for(i=0; i<64; i++){ - rem[i]= dc - (orig[i]<idsp.perm_type != FF_IDCT_PERM_NONE) - ff_block_permute(block, s->idsp.idct_permutation, - scantable, last_non_zero); + block_permute(block, s->idsp.idct_permutation, + scantable, last_non_zero); return last_non_zero; } @@ -4293,12 +4574,17 @@ AVCodec ff_h263p_encoder = { .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, - .capabilities = CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &h263p_class, }; -FF_MPV_GENERIC_CLASS(msmpeg4v2) +static const AVClass msmpeg4v2_class = { + .class_name = "msmpeg4v2 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_msmpeg4v2_encoder = { .name = "msmpeg4v2", @@ -4313,7 +4599,12 @@ AVCodec ff_msmpeg4v2_encoder = { .priv_class = &msmpeg4v2_class, }; -FF_MPV_GENERIC_CLASS(msmpeg4v3) +static const AVClass msmpeg4v3_class = { + .class_name = "msmpeg4v3 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_msmpeg4v3_encoder = { .name = "msmpeg4", @@ -4328,7 +4619,12 @@ AVCodec ff_msmpeg4v3_encoder = { .priv_class = &msmpeg4v3_class, }; -FF_MPV_GENERIC_CLASS(wmv1) +static const AVClass wmv1_class = { + .class_name = "wmv1 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_wmv1_encoder = { .name = "wmv1", diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index f33db34..8074dba 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -31,6 +31,7 @@ #include "mjpegenc.h" #include "msmpeg4.h" #include "qpeldsp.h" +#include "wmv2.h" #include static void gmc1_motion(MpegEncContext *s, @@ -62,12 +63,12 @@ static void gmc1_motion(MpegEncContext *s, if ((unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) || (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, linesize, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } if ((motion_x | motion_y) & 7) { @@ -86,7 +87,7 @@ static void gmc1_motion(MpegEncContext *s, } } - if (CONFIG_GRAY && s->flags & CODEC_FLAG_GRAY) + if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY) return; motion_x = s->sprite_offset[1][0]; @@ -106,12 +107,12 @@ static void gmc1_motion(MpegEncContext *s, ptr = ref_picture[1] + offset; if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - 9, 0) || (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - 9, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, uvlinesize, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; emu = 1; } s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8, @@ -119,12 +120,12 @@ static void gmc1_motion(MpegEncContext *s, ptr = ref_picture[2] + offset; if (emu) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, uvlinesize, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x & 15, motion_y & 15, 128 - s->no_rounding); @@ -163,7 +164,7 @@ static void gmc_motion(MpegEncContext *s, a + 1, (1 << (2 * a + 1)) - s->no_rounding, s->h_edge_pos, s->v_edge_pos); - if (CONFIG_GRAY && s->flags & CODEC_FLAG_GRAY) + if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY) return; ox = s->sprite_offset[1][0] + s->sprite_delta[0][0] * s->mb_x * 8 + @@ -212,12 +213,12 @@ static inline int hpel_motion(MpegEncContext *s, if (s->unrestricted_mv) { if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 1) - 8, 0) || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 1) - 8, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src, s->linesize, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos); - src = s->edge_emu_buffer; + src = s->sc.edge_emu_buffer; emu = 1; } } @@ -226,6 +227,38 @@ static inline int hpel_motion(MpegEncContext *s, } static av_always_inline +void emulated_edge_mc(MpegEncContext *s, + int src_x, int src_y, + int uvsrc_x, int uvsrc_y, + int field_based, + uint8_t **ptr_y, + uint8_t **ptr_cb, + uint8_t **ptr_cr) +{ + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, *ptr_y, + s->linesize, s->linesize, + 17, 17 + field_based, + src_x, src_y * (1 << field_based), + s->h_edge_pos, s->v_edge_pos); + *ptr_y = s->sc.edge_emu_buffer; + if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + uint8_t *uvbuf = s->sc.edge_emu_buffer + 18 * s->linesize; + s->vdsp.emulated_edge_mc(uvbuf, *ptr_cb, + s->uvlinesize, s->uvlinesize, + 9, 9 + field_based, + uvsrc_x, uvsrc_y * (1 << field_based), + s->h_edge_pos >> 1, s->v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, *ptr_cr, + s->uvlinesize, s->uvlinesize, + 9, 9 + field_based, + uvsrc_x, uvsrc_y * (1 << field_based), + s->h_edge_pos >> 1, s->v_edge_pos >> 1); + *ptr_cb = uvbuf; + *ptr_cr = uvbuf + 16; + } +} + +static av_always_inline void mpeg_motion_internal(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, @@ -246,13 +279,6 @@ void mpeg_motion_internal(MpegEncContext *s, uvsrc_x, uvsrc_y, v_edge_pos; ptrdiff_t uvlinesize, linesize; -#if 0 - if (s->quarter_sample) { - motion_x >>= 1; - motion_y >>= 1; - } -#endif - v_edge_pos = s->v_edge_pos >> field_based; linesize = s->current_picture.f->linesize[0] << field_based; uvlinesize = s->current_picture.f->linesize[1] << field_based; @@ -317,27 +343,8 @@ void mpeg_motion_internal(MpegEncContext *s, src_y); return; } - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, - s->linesize, 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 (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { - uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize; - s->vdsp.emulated_edge_mc(uvbuf, ptr_cb, - s->uvlinesize, s->uvlinesize, - 9, 9 + field_based, - uvsrc_x, uvsrc_y << field_based, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, - s->uvlinesize, 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; - } + emulated_edge_mc(s, src_x, src_y, uvsrc_x, uvsrc_y, field_based, + &ptr_y, &ptr_cb, &ptr_cr); } /* FIXME use this for field pix too instead of the obnoxious hack which @@ -356,7 +363,7 @@ void mpeg_motion_internal(MpegEncContext *s, pix_op[0][dxy](dest_y, ptr_y, linesize, h); - if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + if (!CONFIG_GRAY || !(s->avctx->flags & AV_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] @@ -475,7 +482,7 @@ static inline void obmc_motion(MpegEncContext *s, 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) + + ptr[i] = s->sc.obmc_scratchpad + 8 * (i & 1) + s->linesize * 8 * (i >> 1); hpel_motion(s, ptr[i], src, src_x, src_y, pix_op, mv[i][0], mv[i][1]); @@ -538,27 +545,8 @@ static inline void qpel_motion(MpegEncContext *s, if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 3) - 16, 0) || (unsigned)src_y > FFMAX(v_edge_pos - (motion_y & 3) - h, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, - s->linesize, 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 (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { - uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize; - s->vdsp.emulated_edge_mc(uvbuf, ptr_cb, - s->uvlinesize, s->uvlinesize, - 9, 9 + field_based, - uvsrc_x, uvsrc_y << field_based, - s->h_edge_pos >> 1, s->v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, - s->uvlinesize, 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; - } + emulated_edge_mc(s, src_x, src_y, uvsrc_x, uvsrc_y, field_based, + &ptr_y, &ptr_cb, &ptr_cr); } if (!field_based) @@ -580,14 +568,14 @@ static inline void qpel_motion(MpegEncContext *s, qpix_op[1][dxy](dest_y, ptr_y, linesize); qpix_op[1][dxy](dest_y + 8, ptr_y + 8, linesize); } - if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1); pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1); } } /** - * h263 chroma 4mv motion compensation. + * H.263 chroma 4mv motion compensation. */ static void chroma_4mv_motion(MpegEncContext *s, uint8_t *dest_cb, uint8_t *dest_cr, @@ -621,22 +609,22 @@ static void chroma_4mv_motion(MpegEncContext *s, ptr = ref_picture[1] + offset; if ((unsigned)src_x > FFMAX((s->h_edge_pos >> 1) - (dxy & 1) - 8, 0) || (unsigned)src_y > FFMAX((s->v_edge_pos >> 1) - (dxy >> 1) - 8, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, s->uvlinesize, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; emu = 1; } pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8); ptr = ref_picture[2] + offset; if (emu) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, s->uvlinesize, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8); } @@ -736,7 +724,7 @@ static inline void apply_obmc(MpegEncContext *s, mx += mv[0][0]; my += mv[0][1]; } - if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) + if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); @@ -779,13 +767,13 @@ static inline void apply_8x8(MpegEncContext *s, ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 3) - 8, 0) || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 3) - 8, 0)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, s->linesize, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos); - ptr = s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; qpix_op[1][dxy](dest, ptr, s->linesize); @@ -809,7 +797,7 @@ static inline void apply_8x8(MpegEncContext *s, } } - if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) + if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); } diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index bec1b36..500d124 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -1,5 +1,5 @@ /* - * MPEG1 / MPEG2 video parser + * MPEG-1 / MPEG-2 video parser * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * @@ -44,6 +44,8 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, int top_field_first, repeat_first_field, progressive_frame; int horiz_size_ext, vert_size_ext, bit_rate_ext; int did_set_size=0; + int chroma_format; + enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; //FIXME replace the crap with get_bits() s->repeat_pict = 0; @@ -65,9 +67,9 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, ff_set_dimensions(avctx, pc->width, pc->height); did_set_size=1; } + pix_fmt = AV_PIX_FMT_YUV420P; frame_rate_index = buf[3] & 0xf; - pc->frame_rate.den = avctx->time_base.den = ff_mpeg12_frame_rate_tab[frame_rate_index].num; - pc->frame_rate.num = avctx->time_base.num = ff_mpeg12_frame_rate_tab[frame_rate_index].den; + pc->frame_rate = avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_index]; avctx->bit_rate = ((buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6))*400; avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; } @@ -86,13 +88,27 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, pc->progressive_sequence = buf[1] & (1 << 3); avctx->has_b_frames= !(buf[5] >> 7); + chroma_format = (buf[1] >> 1) & 3; + switch (chroma_format) { + case 1: pix_fmt = AV_PIX_FMT_YUV420P; break; + case 2: pix_fmt = AV_PIX_FMT_YUV422P; break; + case 3: pix_fmt = AV_PIX_FMT_YUV444P; break; + } + pc->width |=(horiz_size_ext << 12); pc->height |=( vert_size_ext << 12); - avctx->bit_rate += (bit_rate_ext << 18) * 400; + + bit_rate_ext <<= 18; + if (bit_rate_ext < INT_MAX / 400 && + bit_rate_ext * 400 < INT_MAX - avctx->bit_rate) { + avctx->bit_rate += bit_rate_ext * 400; + } else + avctx->bit_rate = 0; + if(did_set_size) ff_set_dimensions(avctx, pc->width, pc->height); - avctx->time_base.den = pc->frame_rate.den * (frame_rate_ext_n + 1) * 2; - avctx->time_base.num = pc->frame_rate.num * (frame_rate_ext_d + 1); + avctx->framerate.num = pc->frame_rate.num * (frame_rate_ext_n + 1) * 2; + avctx->framerate.den = pc->frame_rate.den * (frame_rate_ext_d + 1); avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; } break; @@ -139,6 +155,19 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, } } the_end: ; + + if (pix_fmt != AV_PIX_FMT_NONE) { + s->format = pix_fmt; + s->width = pc->width; + s->height = pc->height; + s->coded_width = FFALIGN(pc->width, 16); + s->coded_height = FFALIGN(pc->height, 16); + } + +#if FF_API_AVCTX_TIMEBASE + if (avctx->framerate.num) + avctx->time_base = av_inv_q(avctx->framerate); +#endif } static int mpegvideo_parse(AVCodecParserContext *s, @@ -166,7 +195,7 @@ static int mpegvideo_parse(AVCodecParserContext *s, to have the full timing information. The time take by this function should be negligible for uncorrupted streams */ mpegvideo_extract_headers(s, avctx, buf, buf_size); - av_dlog(NULL, "pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", + ff_dlog(NULL, "pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", s->pict_type, (double)avctx->time_base.den / avctx->time_base.num, s->repeat_pict); *poutbuf = buf; diff --git a/libavcodec/mpegvideo_xvmc.c b/libavcodec/mpegvideo_xvmc.c index fb2dd80..b7de79c 100644 --- a/libavcodec/mpegvideo_xvmc.c +++ b/libavcodec/mpegvideo_xvmc.c @@ -285,7 +285,7 @@ void ff_xvmc_decode_mb(MpegEncContext *s) cbp++; } - if (s->flags & CODEC_FLAG_GRAY) { + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { if (s->mb_intra) { // intra frames are always full chroma blocks for (i = 4; i < blocks_per_mb; i++) { memset(s->pblocks[i], 0, sizeof(*s->pblocks[i])); // so we need to clear them diff --git a/libavcodec/mpegvideodata.c b/libavcodec/mpegvideodata.c new file mode 100644 index 0000000..f27dd90 --- /dev/null +++ b/libavcodec/mpegvideodata.c @@ -0,0 +1,102 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +const uint8_t ff_default_chroma_qscale_table[32] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; + +const uint8_t ff_mpeg1_dc_scale_table[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const uint8_t mpeg2_dc_scale_table1[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const uint8_t mpeg2_dc_scale_table2[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t mpeg2_dc_scale_table3[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +const uint8_t *const ff_mpeg2_dc_scale_table[4] = { + ff_mpeg1_dc_scale_table, + mpeg2_dc_scale_table1, + mpeg2_dc_scale_table2, + mpeg2_dc_scale_table3, +}; + +const 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, +}; diff --git a/libavcodec/mpegvideodata.h b/libavcodec/mpegvideodata.h new file mode 100644 index 0000000..d3ace23 --- /dev/null +++ b/libavcodec/mpegvideodata.h @@ -0,0 +1,33 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGVIDEODATA_H +#define AVCODEC_MPEGVIDEODATA_H + +#include + +/* 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_mpeg1_dc_scale_table[128]; +extern const uint8_t * const ff_mpeg2_dc_scale_table[4]; + +extern const uint8_t ff_default_chroma_qscale_table[32]; + +#endif /* AVCODEC_MPEGVIDEODATA_H */ diff --git a/libavcodec/mpegvideoencdsp.c b/libavcodec/mpegvideoencdsp.c index 109bbe5..279d233 100644 --- a/libavcodec/mpegvideoencdsp.c +++ b/libavcodec/mpegvideoencdsp.c @@ -24,7 +24,6 @@ #include "libavutil/attributes.h" #include "libavutil/imgutils.h" #include "avcodec.h" -#include "imgconvert.h" #include "me_cmp.h" #include "mpegvideoencdsp.h" @@ -85,16 +84,6 @@ static int pix_norm1_c(uint8_t *pix, int line_size) for (i = 0; i < 16; i++) { for (j = 0; j < 16; j += 8) { -#if 0 - s += sq[pix[0]]; - s += sq[pix[1]]; - s += sq[pix[2]]; - s += sq[pix[3]]; - s += sq[pix[4]]; - s += sq[pix[5]]; - s += sq[pix[6]]; - s += sq[pix[7]]; -#else #if HAVE_FAST_64BIT register uint64_t x = *(uint64_t *) pix; s += sq[x & 0xff]; @@ -117,7 +106,6 @@ static int pix_norm1_c(uint8_t *pix, int line_size) s += sq[(x >> 16) & 0xff]; s += sq[(x >> 24) & 0xff]; #endif -#endif pix += 8; } pix += line_size - 16; @@ -153,6 +141,93 @@ static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); } +/* 2x2 -> 1x1 */ +static void 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 */ +static void 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 */ +static void 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; + } +} + av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, AVCodecContext *avctx) { @@ -160,9 +235,9 @@ av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, c->add_8x8basis = add_8x8basis_c; c->shrink[0] = av_image_copy_plane; - c->shrink[1] = ff_shrink22; - c->shrink[2] = ff_shrink44; - c->shrink[3] = ff_shrink88; + c->shrink[1] = shrink22; + c->shrink[2] = shrink44; + c->shrink[3] = shrink88; c->pix_sum = pix_sum_c; c->pix_norm1 = pix_norm1_c; diff --git a/libavcodec/mqc.h b/libavcodec/mqc.h index a65433e..6326192 100644 --- a/libavcodec/mqc.h +++ b/libavcodec/mqc.h @@ -50,7 +50,7 @@ typedef struct MqcState { /** * Initialize MQ-decoder. * @param mqc MQ decoder state - * @param bp byte poiter + * @param bp byte pointer */ void ff_mqc_initdec(MqcState *mqc, uint8_t *bp); @@ -58,7 +58,7 @@ void ff_mqc_initdec(MqcState *mqc, uint8_t *bp); * MQ decoder. * @param mqc MQ decoder state * @param cxstate Context - * @return Decision (0 ot 1) + * @return Decision (0 to 1) */ int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate); diff --git a/libavcodec/msgsmdec.c b/libavcodec/msgsmdec.c index be5062a..92b5ae6 100644 --- a/libavcodec/msgsmdec.c +++ b/libavcodec/msgsmdec.c @@ -21,8 +21,9 @@ #define BITSTREAM_READER_LE #include "avcodec.h" -#include "msgsmdec.h" #include "gsm.h" +#include "msgsmdec.h" + #include "gsmdec_template.c" int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 95b5c93..3ab3bd5 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -35,17 +35,18 @@ #include "h263.h" #include "mpeg4video.h" #include "msmpeg4data.h" +#include "mpegvideodata.h" #include "vc1data.h" /* - * You can also call this codec : MPEG4 with a twist ! + * You can also call this codec: MPEG-4 with a twist! * * TODO: * - (encoding) select best mv table (two choices) * - (encoding) select best vlc/dc table */ -/* This table is practically identical to the one from h263 +/* This table is practically identical to the one from H.263 * except that it is inverted. */ static av_cold void init_h263_dc_for_msmpeg4(void) { @@ -66,7 +67,7 @@ static av_cold void init_h263_dc_for_msmpeg4(void) else l= level; - /* luminance h263 */ + /* luminance H.263 */ uni_code= ff_mpeg4_DCtab_lum[size][0]; uni_len = ff_mpeg4_DCtab_lum[size][1]; uni_code ^= (1<> 1)), scale); } #endif - /* XXX: WARNING: they did not choose the same test as MPEG4. This + /* XXX: WARNING: they did not choose the same test as MPEG-4. This is very important ! */ if(s->msmpeg4_version>3){ if(s->inter_intra_pred){ diff --git a/libavcodec/msmpeg4.h b/libavcodec/msmpeg4.h index 0a8ecd9..e57ae66 100644 --- a/libavcodec/msmpeg4.h +++ b/libavcodec/msmpeg4.h @@ -49,12 +49,22 @@ void ff_msmpeg4_handle_slices(MpegEncContext *s); void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr); + +int ff_msmpeg4_encode_init(MpegEncContext *s); +void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_msmpeg4_encode_ext_header(MpegEncContext *s); +void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], + int motion_x, int motion_y); + +int ff_msmpeg4_decode_init(AVCodecContext *avctx); +int ff_msmpeg4_decode_picture_header(MpegEncContext *s); +int ff_msmpeg4_decode_ext_header(MpegEncContext *s, int buf_size); int ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, int n, int coded, const uint8_t *scan_table); int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, int16_t **dc_val_ptr, int *dir_ptr); -int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); + #define CONFIG_MSMPEG4_DECODER (CONFIG_MSMPEG4V1_DECODER || \ CONFIG_MSMPEG4V2_DECODER || \ diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index cf291af..6bc0520 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -41,1959 +41,1921 @@ VLC ff_msmp4_dc_chroma_vlc[2]; /* intra picture macroblock coded block pattern */ const uint16_t ff_msmp4_mb_i_table[64][2] = { -{ 0x1, 1 },{ 0x17, 6 },{ 0x9, 5 },{ 0x5, 5 }, -{ 0x6, 5 },{ 0x47, 9 },{ 0x20, 7 },{ 0x10, 7 }, -{ 0x2, 5 },{ 0x7c, 9 },{ 0x3a, 7 },{ 0x1d, 7 }, -{ 0x2, 6 },{ 0xec, 9 },{ 0x77, 8 },{ 0x0, 8 }, -{ 0x3, 5 },{ 0xb7, 9 },{ 0x2c, 7 },{ 0x13, 7 }, -{ 0x1, 6 },{ 0x168, 10 },{ 0x46, 8 },{ 0x3f, 8 }, -{ 0x1e, 6 },{ 0x712, 13 },{ 0xb5, 9 },{ 0x42, 8 }, -{ 0x22, 7 },{ 0x1c5, 11 },{ 0x11e, 10 },{ 0x87, 9 }, -{ 0x6, 4 },{ 0x3, 9 },{ 0x1e, 7 },{ 0x1c, 6 }, -{ 0x12, 7 },{ 0x388, 12 },{ 0x44, 9 },{ 0x70, 9 }, -{ 0x1f, 6 },{ 0x23e, 11 },{ 0x39, 8 },{ 0x8e, 9 }, -{ 0x1, 7 },{ 0x1c6, 11 },{ 0xb6, 9 },{ 0x45, 9 }, -{ 0x14, 6 },{ 0x23f, 11 },{ 0x7d, 9 },{ 0x18, 9 }, -{ 0x7, 7 },{ 0x1c7, 11 },{ 0x86, 9 },{ 0x19, 9 }, -{ 0x15, 6 },{ 0x1db, 10 },{ 0x2, 9 },{ 0x46, 9 }, -{ 0xd, 8 },{ 0x713, 13 },{ 0x1da, 10 },{ 0x169, 10 }, + { 0x1, 1 }, { 0x17, 6 }, { 0x9, 5 }, { 0x5, 5 }, + { 0x6, 5 }, { 0x47, 9 }, { 0x20, 7 }, { 0x10, 7 }, + { 0x2, 5 }, { 0x7c, 9 }, { 0x3a, 7 }, { 0x1d, 7 }, + { 0x2, 6 }, { 0xec, 9 }, { 0x77, 8 }, { 0x0, 8 }, + { 0x3, 5 }, { 0xb7, 9 }, { 0x2c, 7 }, { 0x13, 7 }, + { 0x1, 6 }, { 0x168, 10 }, { 0x46, 8 }, { 0x3f, 8 }, + { 0x1e, 6 }, { 0x712, 13 }, { 0xb5, 9 }, { 0x42, 8 }, + { 0x22, 7 }, { 0x1c5, 11 }, { 0x11e, 10 }, { 0x87, 9 }, + { 0x6, 4 }, { 0x3, 9 }, { 0x1e, 7 }, { 0x1c, 6 }, + { 0x12, 7 }, { 0x388, 12 }, { 0x44, 9 }, { 0x70, 9 }, + { 0x1f, 6 }, { 0x23e, 11 }, { 0x39, 8 }, { 0x8e, 9 }, + { 0x1, 7 }, { 0x1c6, 11 }, { 0xb6, 9 }, { 0x45, 9 }, + { 0x14, 6 }, { 0x23f, 11 }, { 0x7d, 9 }, { 0x18, 9 }, + { 0x7, 7 }, { 0x1c7, 11 }, { 0x86, 9 }, { 0x19, 9 }, + { 0x15, 6 }, { 0x1db, 10 }, { 0x2, 9 }, { 0x46, 9 }, + { 0xd, 8 }, { 0x713, 13 }, { 0x1da, 10 }, { 0x169, 10 }, }; /* non intra picture macroblock coded block pattern + mb type */ const uint32_t ff_table_mb_non_intra[128][2] = { -{ 0x40, 7 },{ 0x13c9, 13 },{ 0x9fd, 12 },{ 0x1fc, 15 }, -{ 0x9fc, 12 },{ 0xa83, 18 },{ 0x12d34, 17 },{ 0x83bc, 16 }, -{ 0x83a, 12 },{ 0x7f8, 17 },{ 0x3fd, 16 },{ 0x3ff, 16 }, -{ 0x79, 13 },{ 0xa82, 18 },{ 0x969d, 16 },{ 0x2a4, 16 }, -{ 0x978, 12 },{ 0x543, 17 },{ 0x41df, 15 },{ 0x7f9, 17 }, -{ 0x12f3, 13 },{ 0x25a6b, 18 },{ 0x25ef9, 18 },{ 0x3fa, 16 }, -{ 0x20ee, 14 },{ 0x969ab, 20 },{ 0x969c, 16 },{ 0x25ef8, 18 }, -{ 0x12d2, 13 },{ 0xa85, 18 },{ 0x969e, 16 },{ 0x4bc8, 15 }, -{ 0x3d, 12 },{ 0x12f7f, 17 },{ 0x2a2, 16 },{ 0x969f, 16 }, -{ 0x25ee, 14 },{ 0x12d355, 21 },{ 0x12f7d, 17 },{ 0x12f7e, 17 }, -{ 0x9e5, 12 },{ 0xa81, 18 },{ 0x4b4d4, 19 },{ 0x83bd, 16 }, -{ 0x78, 13 },{ 0x969b, 16 },{ 0x3fe, 16 },{ 0x2a5, 16 }, -{ 0x7e, 13 },{ 0xa80, 18 },{ 0x2a3, 16 },{ 0x3fb, 16 }, -{ 0x1076, 13 },{ 0xa84, 18 },{ 0x153, 15 },{ 0x4bc9, 15 }, -{ 0x55, 13 },{ 0x12d354, 21 },{ 0x4bde, 15 },{ 0x25e5, 14 }, -{ 0x25b, 10 },{ 0x4b4c, 15 },{ 0x96b, 12 },{ 0x96a, 12 }, -{ 0x1, 2 },{ 0x0, 7 },{ 0x26, 6 },{ 0x12b, 9 }, -{ 0x7, 3 },{ 0x20f, 10 },{ 0x4, 9 },{ 0x28, 12 }, -{ 0x6, 3 },{ 0x20a, 10 },{ 0x128, 9 },{ 0x2b, 12 }, -{ 0x11, 5 },{ 0x1b, 11 },{ 0x13a, 9 },{ 0x4ff, 11 }, -{ 0x3, 4 },{ 0x277, 10 },{ 0x106, 9 },{ 0x839, 12 }, -{ 0xb, 4 },{ 0x27b, 10 },{ 0x12c, 9 },{ 0x4bf, 11 }, -{ 0x9, 6 },{ 0x35, 12 },{ 0x27e, 10 },{ 0x13c8, 13 }, -{ 0x1, 6 },{ 0x4aa, 11 },{ 0x208, 10 },{ 0x29, 12 }, -{ 0x1, 4 },{ 0x254, 10 },{ 0x12e, 9 },{ 0x838, 12 }, -{ 0x24, 6 },{ 0x4f3, 11 },{ 0x276, 10 },{ 0x12f6, 13 }, -{ 0x1, 5 },{ 0x27a, 10 },{ 0x13e, 9 },{ 0x3e, 12 }, -{ 0x8, 6 },{ 0x413, 11 },{ 0xc, 10 },{ 0x4be, 11 }, -{ 0x14, 5 },{ 0x412, 11 },{ 0x253, 10 },{ 0x97a, 12 }, -{ 0x21, 6 },{ 0x4ab, 11 },{ 0x20b, 10 },{ 0x34, 12 }, -{ 0x15, 5 },{ 0x278, 10 },{ 0x252, 10 },{ 0x968, 12 }, -{ 0x5, 5 },{ 0xb, 10 },{ 0x9c, 8 },{ 0xe, 10 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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, + 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 8, 8, 8, 9, 9, 9, + 10, 10, 10, 11, 11, 11, 12, 12, + 12, 13, 13, 13, 14, 14, 15, 15, + 16, 17, 18, 19, 20, 0, 0, 0, + 0, 1, 1, 1, 1, 2, 2, 2, + 3, 3, 3, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, }; /* vlc table 1, for intra chroma and P macroblocks */ static const uint16_t table1_vlc[149][2] = { -{ 0x4, 3 },{ 0x14, 5 },{ 0x17, 7 },{ 0x7f, 8 }, -{ 0x154, 9 },{ 0x1f2, 10 },{ 0xbf, 11 },{ 0x65, 12 }, -{ 0xaaa, 12 },{ 0x630, 13 },{ 0x1597, 13 },{ 0x3b7, 14 }, -{ 0x2b22, 14 },{ 0xbe6, 15 },{ 0xb, 4 },{ 0x37, 7 }, -{ 0x62, 9 },{ 0x7, 11 },{ 0x166, 12 },{ 0xce, 13 }, -{ 0x1590, 13 },{ 0x5f6, 14 },{ 0xbe7, 15 },{ 0x7, 5 }, -{ 0x6d, 8 },{ 0x3, 11 },{ 0x31f, 12 },{ 0x5f2, 14 }, -{ 0x2, 6 },{ 0x61, 9 },{ 0x55, 12 },{ 0x1df, 14 }, -{ 0x1a, 6 },{ 0x1e, 10 },{ 0xac9, 12 },{ 0x2b23, 14 }, -{ 0x1e, 6 },{ 0x1f, 10 },{ 0xac3, 12 },{ 0x2b2b, 14 }, -{ 0x6, 7 },{ 0x4, 11 },{ 0x2f8, 13 },{ 0x19, 7 }, -{ 0x6, 11 },{ 0x63d, 13 },{ 0x57, 7 },{ 0x182, 11 }, -{ 0x2aa2, 14 },{ 0x4, 8 },{ 0x180, 11 },{ 0x59c, 14 }, -{ 0x7d, 8 },{ 0x164, 12 },{ 0x76d, 15 },{ 0x2, 9 }, -{ 0x18d, 11 },{ 0x1581, 13 },{ 0xad, 8 },{ 0x60, 12 }, -{ 0xc67, 14 },{ 0x1c, 9 },{ 0xee, 13 },{ 0x3, 9 }, -{ 0x2cf, 13 },{ 0xd9, 9 },{ 0x1580, 13 },{ 0x2, 11 }, -{ 0x183, 11 },{ 0x57, 12 },{ 0x61, 12 },{ 0x31, 11 }, -{ 0x66, 12 },{ 0x631, 13 },{ 0x632, 13 },{ 0xac, 13 }, -{ 0x31d, 12 },{ 0x76, 12 },{ 0x3a, 11 },{ 0x165, 12 }, -{ 0xc66, 14 },{ 0x3, 2 },{ 0x54, 7 },{ 0x2ab, 10 }, -{ 0x16, 13 },{ 0x5f7, 14 },{ 0x5, 4 },{ 0xf8, 9 }, -{ 0xaa9, 12 },{ 0x5f, 15 },{ 0x4, 4 },{ 0x1c, 10 }, -{ 0x1550, 13 },{ 0x4, 5 },{ 0x77, 11 },{ 0x76c, 15 }, -{ 0xe, 5 },{ 0xa, 12 },{ 0xc, 5 },{ 0x562, 11 }, -{ 0x4, 6 },{ 0x31c, 12 },{ 0x6, 6 },{ 0xc8, 13 }, -{ 0xd, 6 },{ 0x1da, 13 },{ 0x7, 6 },{ 0xc9, 13 }, -{ 0x1, 7 },{ 0x2e, 14 },{ 0x14, 7 },{ 0x1596, 13 }, -{ 0xa, 7 },{ 0xac2, 12 },{ 0x16, 7 },{ 0x15b, 14 }, -{ 0x15, 7 },{ 0x15a, 14 },{ 0xf, 8 },{ 0x5e, 15 }, -{ 0x7e, 8 },{ 0xab, 8 },{ 0x2d, 9 },{ 0xd8, 9 }, -{ 0xb, 9 },{ 0x14, 10 },{ 0x2b3, 10 },{ 0x1f3, 10 }, -{ 0x3a, 10 },{ 0x0, 10 },{ 0x58, 10 },{ 0x2e, 9 }, -{ 0x5e, 10 },{ 0x563, 11 },{ 0xec, 12 },{ 0x54, 12 }, -{ 0xac1, 12 },{ 0x1556, 13 },{ 0x2fa, 13 },{ 0x181, 11 }, -{ 0x1557, 13 },{ 0x59d, 14 },{ 0x2aa3, 14 },{ 0x2b2a, 14 }, -{ 0x1de, 14 },{ 0x63c, 13 },{ 0xcf, 13 },{ 0x1594, 13 }, -{ 0xd, 9 }, + { 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, + 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, + 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 }, + { 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, + 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, + 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 }, + { 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, + 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, + 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, }; RLTable ff_rl_table[NB_RL_TABLES] = { /* intra luminance tables */ /* low motion */ - { - 132, - 85, - table0_vlc, - table0_run, - table0_level, - }, + { 132, + 85, + table0_vlc, + table0_run, + table0_level, }, /* high motion */ - { - 185, - 119, - table2_vlc, - table2_run, - table2_level, - }, + { 185, + 119, + table2_vlc, + table2_run, + table2_level, }, /* mid-rate */ - { - 102, - 67, - ff_mpeg4_intra_vlc, - ff_mpeg4_intra_run, - ff_mpeg4_intra_level, - }, + { 102, + 67, + ff_mpeg4_intra_vlc, + ff_mpeg4_intra_run, + ff_mpeg4_intra_level, }, /* intra chrominance / non intra tables */ /* low motion inter */ - { - 148, - 81, - table1_vlc, - table1_run, - table1_level, - }, + { 148, + 81, + table1_vlc, + table1_run, + table1_level, }, /* high motion inter */ - { - 168, - 99, - table4_vlc, - table4_run, - table4_level, - }, + { 168, + 99, + table4_vlc, + table4_run, + table4_level, }, /* mid rate inter */ - { - 102, - 58, - ff_inter_vlc, - ff_inter_run, - ff_inter_level, - }, + { 102, + 58, + ff_inter_vlc, + ff_inter_run, + ff_inter_level, }, }; /* motion vector table 0 */ static const uint16_t table0_mv_code[1100] = { - 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001, - 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f, - 0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b, - 0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048, - 0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c, - 0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2, - 0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5, - 0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090, - 0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133, - 0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b, - 0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359, - 0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d, - 0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e, - 0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3, - 0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8, - 0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688, - 0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0, - 0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079, - 0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b, - 0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e, - 0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d, - 0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942, - 0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983, - 0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17, - 0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d, - 0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421, - 0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572, - 0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996, - 0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33, - 0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7, - 0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff, - 0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273, - 0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0, - 0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2, - 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca, - 0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a, - 0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8, - 0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2, - 0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837, - 0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c, - 0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4, - 0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, - 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, - 0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459, - 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461, - 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469, - 0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3, - 0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb, - 0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, - 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, - 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, - 0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, - 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, - 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, - 0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561, - 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, - 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571, - 0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f, - 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, - 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, - 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, - 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f, - 0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb, - 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3, - 0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb, - 0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343, - 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, - 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, - 0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a, - 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92, - 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a, - 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2, - 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa, - 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2, - 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba, - 0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c, - 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34, - 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c, - 0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84, - 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c, - 0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94, - 0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c, - 0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4, - 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac, - 0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4, - 0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc, - 0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4, - 0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04, - 0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, - 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, - 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, - 0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000, - 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, - 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, - 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, - 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, - 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, - 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, - 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, - 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, - 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, - 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, - 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, - 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, - 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, - 0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, - 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, - 0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c, - 0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4, - 0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc, - 0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44, - 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c, - 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54, - 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c, - 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64, - 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c, - 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74, - 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c, - 0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84, - 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c, - 0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94, - 0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c, - 0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4, - 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac, - 0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4, - 0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc, - 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4, - 0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc, - 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4, - 0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc, - 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4, - 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec, - 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4, - 0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc, - 0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04, - 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c, - 0x5f0d, 0x5f0e, 0x5f0f, 0x0000, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 32, 32, 31, 31, 32, 33, 31, 33, + 33, 32, 32, 30, 34, 31, 32, 29, + 33, 30, 32, 33, 31, 35, 34, 30, + 34, 31, 33, 29, 29, 31, 33, 35, + 30, 30, 35, 32, 32, 34, 34, 28, + 25, 32, 36, 27, 32, 32, 32, 37, + 39, 3, 32, 30, 31, 26, 31, 32, + 32, 38, 29, 29, 32, 34, 31, 31, + 34, 35, 33, 33, 28, 33, 1, 33, + 27, 29, 30, 31, 28, 29, 37, 35, + 31, 33, 35, 27, 36, 37, 25, 25, + 61, 35, 4, 5, 32, 33, 36, 30, + 23, 30, 28, 34, 31, 32, 32, 39, + 32, 34, 21, 39, 32, 59, 32, 28, + 32, 36, 60, 33, 24, 36, 32, 32, + 41, 2, 32, 38, 26, 22, 33, 30, + 31, 32, 32, 30, 31, 32, 29, 3, + 40, 38, 32, 32, 33, 26, 31, 34, + 28, 38, 34, 31, 3, 31, 35, 38, + 27, 35, 33, 28, 29, 27, 29, 27, + 43, 29, 37, 63, 31, 33, 34, 30, + 31, 30, 37, 30, 35, 35, 26, 41, + 37, 31, 33, 28, 26, 30, 42, 24, + 7, 27, 33, 29, 36, 28, 34, 57, + 23, 41, 36, 23, 35, 34, 25, 30, + 25, 33, 25, 25, 29, 24, 33, 39, + 33, 33, 0, 37, 31, 36, 21, 32, + 61, 24, 35, 61, 31, 5, 31, 59, + 39, 21, 32, 30, 34, 22, 40, 32, + 29, 16, 31, 5, 62, 2, 20, 39, + 39, 32, 33, 1, 31, 24, 36, 32, + 36, 32, 28, 26, 6, 31, 38, 34, + 58, 35, 32, 33, 33, 17, 43, 26, + 31, 40, 31, 34, 32, 32, 31, 19, + 30, 32, 29, 33, 38, 38, 32, 59, + 40, 18, 38, 32, 35, 34, 32, 17, + 1, 15, 30, 28, 31, 28, 34, 29, + 32, 27, 35, 27, 49, 22, 37, 34, + 37, 26, 32, 32, 22, 28, 45, 29, + 30, 31, 43, 46, 41, 30, 26, 13, + 34, 32, 27, 38, 42, 42, 33, 47, + 33, 60, 27, 42, 25, 32, 22, 32, + 48, 32, 45, 33, 33, 41, 27, 25, + 19, 31, 35, 19, 36, 42, 27, 17, + 31, 44, 28, 33, 33, 31, 23, 31, + 40, 33, 31, 34, 30, 32, 33, 36, + 35, 47, 37, 41, 31, 23, 41, 29, + 30, 35, 32, 25, 32, 28, 58, 2, + 37, 33, 14, 33, 49, 20, 39, 36, + 21, 9, 23, 33, 35, 24, 39, 37, + 11, 33, 30, 31, 31, 28, 51, 40, + 35, 29, 25, 33, 46, 35, 37, 30, + 30, 8, 63, 28, 15, 40, 33, 45, + 49, 25, 32, 4, 47, 51, 36, 39, + 53, 10, 24, 29, 30, 31, 25, 40, + 38, 38, 33, 56, 23, 27, 32, 37, + 26, 29, 43, 36, 33, 24, 55, 43, + 9, 29, 34, 34, 24, 33, 18, 33, + 33, 30, 31, 50, 24, 60, 30, 39, + 34, 30, 39, 28, 22, 38, 2, 26, + 63, 32, 57, 21, 39, 33, 28, 18, + 30, 34, 22, 33, 29, 41, 30, 34, + 35, 21, 13, 34, 35, 39, 30, 46, + 32, 42, 32, 31, 33, 26, 11, 33, + 22, 31, 25, 31, 53, 27, 43, 25, + 40, 50, 21, 36, 38, 30, 12, 31, + 34, 20, 15, 29, 32, 62, 30, 13, + 17, 32, 19, 31, 20, 31, 30, 7, + 1, 17, 34, 37, 31, 31, 44, 34, + 26, 40, 16, 37, 52, 48, 30, 20, + 18, 33, 38, 29, 7, 25, 30, 54, + 45, 47, 46, 41, 29, 29, 16, 30, + 14, 26, 38, 34, 34, 29, 34, 30, + 29, 30, 57, 30, 4, 46, 33, 29, + 39, 44, 30, 31, 50, 33, 31, 32, + 19, 32, 40, 31, 37, 47, 1, 35, + 16, 31, 0, 35, 33, 1, 17, 34, + 9, 34, 33, 31, 49, 43, 42, 51, + 34, 29, 23, 29, 14, 30, 45, 49, + 11, 24, 31, 28, 35, 41, 30, 44, + 18, 29, 34, 35, 36, 25, 26, 21, + 31, 30, 34, 19, 34, 44, 36, 38, + 25, 31, 28, 23, 37, 3, 55, 41, + 30, 22, 41, 24, 33, 26, 35, 35, + 30, 55, 51, 47, 48, 38, 24, 15, + 21, 50, 25, 46, 30, 29, 10, 34, + 42, 45, 29, 42, 22, 3, 33, 27, + 34, 1, 34, 28, 34, 36, 35, 23, + 23, 13, 58, 3, 26, 63, 25, 31, + 34, 61, 38, 39, 25, 61, 29, 37, + 30, 41, 26, 48, 28, 33, 50, 35, + 30, 37, 29, 29, 40, 6, 39, 28, + 28, 19, 8, 22, 45, 34, 35, 10, + 58, 17, 37, 39, 30, 18, 54, 14, + 29, 16, 59, 30, 35, 23, 35, 30, + 47, 36, 29, 55, 20, 12, 31, 35, + 14, 29, 18, 34, 34, 24, 29, 26, + 22, 2, 27, 23, 8, 30, 55, 38, + 60, 31, 4, 34, 49, 34, 27, 34, + 33, 30, 31, 54, 42, 35, 38, 46, + 44, 26, 27, 9, 39, 25, 21, 29, + 28, 42, 13, 0, 5, 34, 37, 28, + 24, 29, 63, 26, 22, 27, 29, 25, + 33, 25, 61, 0, 35, 25, 36, 15, + 27, 40, 53, 33, 3, 10, 16, 37, + 38, 18, 30, 46, 27, 9, 6, 29, + 62, 8, 42, 28, 29, 3, 25, 16, + 26, 29, 35, 28, 27, 51, 61, 48, + 37, 9, 34, 7, 49, 45, 20, 29, + 21, 5, 5, 29, 28, 34, 29, 24, + 10, 24, 35, 36, 38, 55, 11, 36, + 38, 53, 54, 26, 30, 49, 20, 27, + 30, 39, 33, 41, 49, 22, 38, 38, + 4, 30, 8, 9, 3, 24, 22, 50, + 37, 36, 31, 27, 2, 9, 42, 63, + 25, 19, 44, 1, 28, 28, 48, 30, + 34, 41, 41, 38, 12, 27, 15, 0, + 16, 34, 35, 38, 28, 29, 40, 42, + 51, 52, 45, 54, 59, 59, 42, 44, + 37, 26, 46, 24, 15, 39, 22, 46, + 19, 35, 38, 17, 37, 23, 52, 55, + 50, 37, 26, 11, 37, 12, 24, 30, + 16, 13, 22, 13, 36, 35, 40, 41, + 34, 41, 26, 53, 51, 5, 21, 30, + 2, 63, 41, 20, 1, 56, 21, 24, + 25, 5, 28, 35, 26, 28, 30, 18, + 29, 23, 40, 34, 20, 42, 39, 34, + 28, 61, 38, 27, 62, 9, 36, 17, + 9, 49, 24, 25, 54, 34, 39, 37, + 3, 1, 25, 38, 38, 44, 35, 36, + 12, 60, 36, 38, 40, 25, 43, 39, + 53, 28, 39, 57, 46, 10, 52, 27, + 35, 42, 45, 59, 15, 60, 38, 24, + 23, 39, 12, 29, 24, 0, 20, 16, + 28, 43, 35, 28, 1, 49, 4, 21, + 42, 39, 29, 3, 44, 21, 53, 55, + 11, 5, 3, 39, 53, 28, 25, 19, + 34, 28, 21, }; MVTable ff_mv_tables[2] = { - { - 1099, - table0_mv_code, - table0_mv_bits, - table0_mvx, - table0_mvy, - }, - { - 1099, - table1_mv_code, - table1_mv_bits, - table1_mvx, - table1_mvy, - } + { 1099, + table0_mv_code, + table0_mv_bits, + table0_mvx, + table0_mvy, }, + { 1099, + table1_mv_code, + table1_mv_bits, + table1_mvx, + table1_mvy, } }; const uint8_t ff_v2_mb_type[8][2] = { - {1, 1}, {0 , 2}, {3 , 3}, {9 , 5}, - {5, 4}, {0x21, 7}, {0x20, 7}, {0x11, 6}, + { 1, 1 }, { 0, 2 }, { 3, 3 }, { 9, 5 }, + { 5, 4 }, { 0x21, 7 }, { 0x20, 7 }, { 0x11, 6 }, }; const uint8_t ff_v2_intra_cbpc[4][2] = { - {1, 1}, {0, 3}, {1, 3}, {1, 2}, + { 1, 1 }, { 0, 3 }, { 1, 3 }, { 1, 2 }, }; -const uint8_t ff_wmv1_y_dc_scale_table[32]={ -// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 - 0, 8, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21 +const uint8_t ff_wmv1_y_dc_scale_table[32] = { + 0, 8, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21 }; -const uint8_t ff_wmv1_c_dc_scale_table[32]={ -// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 - 0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22 +const uint8_t ff_wmv1_c_dc_scale_table[32] = { + 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, + 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22 }; -const uint8_t ff_old_ff_y_dc_scale_table[32]={ -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - 0, 8, 8, 8, 8,10,12,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39 +const uint8_t ff_old_ff_y_dc_scale_table[32] = { + 0, 8, 8, 8, 8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 }; -const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64]={ - { - 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, - 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, - 0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05, - 0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A, - 0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, - 0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34, - 0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35, - 0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F, - }, - { - 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, - 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, - 0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D, - 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A, - 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D, - 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25, - 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35, - 0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F, - }, - { - 0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18, - 0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20, - 0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07, - 0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, - 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D, - 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E, - 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35, - 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, - }, - { - 0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09, - 0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29, - 0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13, - 0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C, - 0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24, - 0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E, - 0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35, - 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, - } +const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64] = { + { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, + 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, + 0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05, + 0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A, + 0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, + 0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34, + 0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35, + 0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F, }, + { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, + 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, + 0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D, + 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A, + 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D, + 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25, + 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35, + 0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F, }, + { 0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18, + 0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20, + 0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07, + 0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, + 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D, + 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E, + 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35, + 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, }, + { 0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09, + 0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29, + 0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13, + 0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C, + 0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24, + 0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E, + 0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35, + 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, } }; -const uint8_t ff_table_inter_intra[4][2]={ - {0,1} /*Luma-Left Chroma-Left*/, - {2,2} /*Luma-Top Chroma-Left*/, - {6,3} /*luma-Left Chroma-Top */, - {7,3} /*luma-Top Chroma-Top */ +const uint8_t ff_table_inter_intra[4][2] = { + { 0, 1 } /* Luma-Left Chroma-Left */, + { 2, 2 } /* Luma-Top Chroma-Left */, + { 6, 3 } /* luma-Left Chroma-Top */, + { 7, 3 } /* luma-Top Chroma-Top */ }; static const uint32_t table_mb_non_intra2[128][2] = { -{0x0000A7, 14}, {0x01B2B8, 18}, {0x01B28E, 18}, {0x036575, 19}, -{0x006CAC, 16}, {0x000A69, 18}, {0x002934, 20}, {0x00526B, 21}, -{0x006CA1, 16}, {0x01B2B9, 18}, {0x0029AD, 20}, {0x029353, 24}, -{0x006CA7, 16}, {0x006CAB, 16}, {0x01B2BB, 18}, {0x00029B, 16}, -{0x00D944, 17}, {0x000A6A, 18}, {0x0149A8, 23}, {0x03651F, 19}, -{0x006CAF, 16}, {0x000A4C, 18}, {0x03651E, 19}, {0x000A48, 18}, -{0x00299C, 20}, {0x00299F, 20}, {0x029352, 24}, {0x0029AC, 20}, -{0x000296, 16}, {0x00D946, 17}, {0x000A68, 18}, {0x000298, 16}, -{0x000527, 17}, {0x00D94D, 17}, {0x0014D7, 19}, {0x036574, 19}, -{0x000A5C, 18}, {0x01B299, 18}, {0x00299D, 20}, {0x00299E, 20}, -{0x000525, 17}, {0x000A66, 18}, {0x00A4D5, 22}, {0x00149B, 19}, -{0x000295, 16}, {0x006CAD, 16}, {0x000A49, 18}, {0x000521, 17}, -{0x006CAA, 16}, {0x00D945, 17}, {0x01B298, 18}, {0x00052F, 17}, -{0x003654, 15}, {0x006CA0, 16}, {0x000532, 17}, {0x000291, 16}, -{0x003652, 15}, {0x000520, 17}, {0x000A5D, 18}, {0x000294, 16}, -{0x00009B, 11}, {0x0006E2, 12}, {0x000028, 12}, {0x0001B0, 10}, -{0x000001, 3}, {0x000010, 8}, {0x00002F, 6}, {0x00004C, 10}, -{0x00000D, 4}, {0x000000, 10}, {0x000006, 9}, {0x000134, 12}, -{0x00000C, 4}, {0x000007, 10}, {0x000007, 9}, {0x0006E1, 12}, -{0x00000E, 5}, {0x0000DA, 9}, {0x000022, 9}, {0x000364, 11}, -{0x00000F, 4}, {0x000006, 10}, {0x00000F, 9}, {0x000135, 12}, -{0x000014, 5}, {0x0000DD, 9}, {0x000004, 9}, {0x000015, 11}, -{0x00001A, 6}, {0x0001B3, 10}, {0x000005, 10}, {0x0006E3, 12}, -{0x00000C, 5}, {0x0000B9, 8}, {0x000004, 8}, {0x0000DB, 9}, -{0x00000E, 4}, {0x00000B, 10}, {0x000023, 9}, {0x0006CB, 12}, -{0x000005, 6}, {0x0001B1, 10}, {0x000001, 10}, {0x0006E0, 12}, -{0x000011, 5}, {0x0000DF, 9}, {0x00000E, 9}, {0x000373, 11}, -{0x000003, 5}, {0x0000B8, 8}, {0x000006, 8}, {0x000175, 9}, -{0x000015, 5}, {0x000174, 9}, {0x000027, 9}, {0x000372, 11}, -{0x000010, 5}, {0x0000BB, 8}, {0x000005, 8}, {0x0000DE, 9}, -{0x00000F, 5}, {0x000001, 9}, {0x000012, 8}, {0x000004, 10}, -{0x000002, 3}, {0x000016, 5}, {0x000009, 4}, {0x000001, 5}, + { 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}, + { 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}, + { 0x0000D4, 8 }, { 0x0021C5, 14 }, { 0x00F18A, 16 }, { 0x00D5BC, 16 }, + { 0x000879, 12 }, { 0x00354D, 14 }, { 0x010E3F, 17 }, { 0x010F54, 17 }, + { 0x000866, 12 }, { 0x00356E, 14 }, { 0x010F55, 17 }, { 0x010E3E, 17 }, + { 0x0010CE, 13 }, { 0x003C84, 14 }, { 0x00D5BD, 16 }, { 0x00F18B, 16 }, + { 0x000868, 12 }, { 0x00438C, 15 }, { 0x0087AB, 16 }, { 0x00790B, 15 }, + { 0x000F10, 12 }, { 0x00433D, 15 }, { 0x006AD3, 15 }, { 0x00790A, 15 }, + { 0x001AA7, 13 }, { 0x0043D4, 15 }, { 0x00871E, 16 }, { 0x006ADF, 15 }, + { 0x000D7C, 12 }, { 0x003C94, 14 }, { 0x00438D, 15 }, { 0x006AD2, 15 }, + { 0x0006BC, 11 }, { 0x0021E9, 14 }, { 0x006ADA, 15 }, { 0x006A99, 15 }, + { 0x0010F7, 13 }, { 0x004389, 15 }, { 0x006ADB, 15 }, { 0x0078C4, 15 }, + { 0x000D56, 12 }, { 0x0035F7, 14 }, { 0x00438E, 15 }, { 0x006A98, 15 }, + { 0x000D52, 12 }, { 0x003C95, 14 }, { 0x004388, 15 }, { 0x00433C, 15 }, + { 0x000D54, 12 }, { 0x001E4B, 13 }, { 0x003C63, 14 }, { 0x003C83, 14 }, + { 0x000861, 12 }, { 0x0021EB, 14 }, { 0x00356C, 14 }, { 0x0035F6, 14 }, + { 0x000863, 12 }, { 0x00219F, 14 }, { 0x003568, 14 }, { 0x003C82, 14 }, + { 0x0001AE, 9 }, { 0x0010C0, 13 }, { 0x000F11, 12 }, { 0x001AFA, 13 }, + { 0x000000, 1 }, { 0x0000F0, 8 }, { 0x0001AD, 9 }, { 0x0010C1, 13 }, + { 0x00000A, 4 }, { 0x0003C5, 10 }, { 0x000789, 11 }, { 0x001AB5, 13 }, + { 0x000009, 4 }, { 0x000435, 11 }, { 0x000793, 11 }, { 0x001E40, 13 }, + { 0x00001D, 5 }, { 0x0003CB, 10 }, { 0x000878, 12 }, { 0x001AAF, 13 }, + { 0x00000B, 4 }, { 0x0003C7, 10 }, { 0x000791, 11 }, { 0x001AAB, 13 }, + { 0x00001F, 5 }, { 0x000436, 11 }, { 0x0006BF, 11 }, { 0x000F19, 12 }, + { 0x00003D, 6 }, { 0x000D51, 12 }, { 0x0010C4, 13 }, { 0x0021E8, 14 }, + { 0x000036, 6 }, { 0x000437, 11 }, { 0x0006AF, 11 }, { 0x0010C5, 13 }, + { 0x00000C, 4 }, { 0x000432, 11 }, { 0x000794, 11 }, { 0x001E30, 13 }, + { 0x000042, 7 }, { 0x000870, 12 }, { 0x000F24, 12 }, { 0x001E43, 13 }, + { 0x000020, 6 }, { 0x00043E, 11 }, { 0x000795, 11 }, { 0x001AAA, 13 }, + { 0x000037, 6 }, { 0x0006AC, 11 }, { 0x0006AE, 11 }, { 0x0010F6, 13 }, + { 0x000034, 6 }, { 0x00043A, 11 }, { 0x000D50, 12 }, { 0x001AAE, 13 }, + { 0x000039, 6 }, { 0x00043F, 11 }, { 0x00078D, 11 }, { 0x0010D2, 13 }, + { 0x000038, 6 }, { 0x00043B, 11 }, { 0x0006BD, 11 }, { 0x0010D3, 13 }, + { 0x000011, 5 }, { 0x0001AC, 9 }, { 0x0000F3, 8 }, { 0x000439, 11 }, }; -const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]={ +const uint32_t (*const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2] = { table_mb_non_intra2, table_mb_non_intra3, table_mb_non_intra4, ff_table_mb_non_intra, }; - -const uint8_t ff_wmv2_scantableA[64]={ -0x00, 0x01, 0x02, 0x08, 0x03, 0x09, 0x0A, 0x10, -0x04, 0x0B, 0x11, 0x18, 0x12, 0x0C, 0x05, 0x13, -0x19, 0x0D, 0x14, 0x1A, 0x1B, 0x06, 0x15, 0x1C, -0x0E, 0x16, 0x1D, 0x07, 0x1E, 0x0F, 0x17, 0x1F, -}; - -const uint8_t ff_wmv2_scantableB[64]={ -0x00, 0x08, 0x01, 0x10, 0x09, 0x18, 0x11, 0x02, -0x20, 0x0A, 0x19, 0x28, 0x12, 0x30, 0x21, 0x1A, -0x38, 0x29, 0x22, 0x03, 0x31, 0x39, 0x0B, 0x2A, -0x13, 0x32, 0x1B, 0x3A, 0x23, 0x2B, 0x33, 0x3B, -}; diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h index ca2dac1..2c2dfab 100644 --- a/libavcodec/msmpeg4data.h +++ b/libavcodec/msmpeg4data.h @@ -31,8 +31,9 @@ #define AVCODEC_MSMPEG4DATA_H #include "libavutil/common.h" -#include "get_bits.h" + #include "rl.h" +#include "vlc.h" /* motion vector table */ typedef struct MVTable { @@ -84,7 +85,4 @@ extern const uint32_t ff_table1_dc_chroma[120][2]; #define WMV2_INTER_CBP_TABLE_COUNT 4 extern const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]; -extern const uint8_t ff_wmv2_scantableA[64]; -extern const uint8_t ff_wmv2_scantableB[64]; - #endif /* AVCODEC_MSMPEG4DATA_H */ diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index 191f81a..a2d0ad4 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -23,14 +23,15 @@ */ #include "avcodec.h" +#include "internal.h" #include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4.h" -#include "libavutil/x86/asm.h" #include "h263.h" #include "mpeg4video.h" #include "msmpeg4data.h" #include "vc1data.h" +#include "wmv2.h" #define DC_VLC_BITS 9 #define V2_INTRA_CBPC_VLC_BITS 3 @@ -67,13 +68,13 @@ static VLC v2_mb_type_vlc; static VLC v2_mv_vlc; VLC ff_inter_intra_vlc; -/* This is identical to h263 except that its range is multiplied by 2. */ +/* This is identical to H.263 except that its range is multiplied by 2. */ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code) { int code, val, sign, shift; code = get_vlc2(&s->gb, v2_mv_vlc.table, V2_MV_VLC_BITS, 2); - av_dlog(s, "MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred); + ff_dlog(s, "MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred); if (code < 0) return 0xffff; @@ -249,14 +250,14 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) s->mv[0][0][1] = my; *mb_type_ptr = MB_TYPE_L0 | MB_TYPE_16x16; } else { - av_dlog(s, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, + ff_dlog(s, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp & 3) ? 1 : 0) +((cbp & 0x3C)? 2 : 0), show_bits(&s->gb, 24)); s->ac_pred = get_bits1(&s->gb); *mb_type_ptr = MB_TYPE_INTRA; if(s->inter_intra_pred){ s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); - av_dlog(s, "%d%d %d %d/", + ff_dlog(s, "%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); } if(s->per_mb_rl_table && cbp){ @@ -294,7 +295,7 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) done = 1; for(i=0;iavctx, AV_LOG_ERROR, "invalid picture type\n"); return -1; } -#if 0 -{ - static int had_i=0; - if(s->pict_type == AV_PICTURE_TYPE_I) had_i=1; - if(!had_i) return -1; -} -#endif s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); if(s->qscale==0){ av_log(s->avctx, AV_LOG_ERROR, "invalid qscale\n"); @@ -532,7 +526,7 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) s->no_rounding = 0; } } - av_dlog(s->avctx, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, + ff_dlog(s->avctx, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height); s->esc3_level_length= 0; @@ -563,7 +557,7 @@ int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size) } else { - av_log(s->avctx, AV_LOG_ERROR, "I frame too long, ignoring ext header\n"); + av_log(s->avctx, AV_LOG_ERROR, "I-frame too long, ignoring ext header\n"); } return 0; @@ -626,7 +620,6 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) return level; } -//#define ERROR_DETAILS int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, int n, int coded, const uint8_t *scan_table) { @@ -720,7 +713,7 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, last= SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1); if(!s->esc3_level_length){ int ll; - av_dlog(s->avctx, "ESC-3 %X at %d %d\n", + ff_dlog(s->avctx, "ESC-3 %X at %d %d\n", show_bits(&s->gb, 24), s->mb_x, s->mb_y); if(s->qscale<8){ ll= SHOW_UBITS(re, &s->gb, 3); SKIP_BITS(re, &s->gb, 3); @@ -751,43 +744,11 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, if(sign) level= -level; } -#if 0 // waste of time / this will detect very few errors - { - const int abs_level= FFABS(level); - const int run1= run - rl->max_run[last][abs_level] - run_diff; - if(abs_level<=MAX_LEVEL && run<=MAX_RUN){ - if(abs_level <= rl->max_level[last][run]){ - av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, vlc encoding possible\n"); - return DECODING_AC_LOST; - } - if(abs_level <= rl->max_level[last][run]*2){ - av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 1 encoding possible\n"); - return DECODING_AC_LOST; - } - if(run1>=0 && abs_level <= rl->max_level[last][run1]){ - av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 2 encoding possible\n"); - return DECODING_AC_LOST; - } - } - } -#endif //level = level * qmul + (level>0) * qadd - (level<=0) * qadd ; if (level>0) level= level * qmul + qadd; else level= level * qmul - qadd; -#if 0 // waste of time too :( - if(level>2048 || level<-2048){ - av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc\n"); - return DECODING_AC_LOST; - } -#endif i+= run + 1; if(last) i+=192; -#ifdef ERROR_DETAILS - if(run==66) - av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code in ESC3 level=%d\n", level); - else if((i>62 && i<192) || i>192+63) - av_log(s->avctx, AV_LOG_ERROR, "run overflow in ESC3 i=%d run=%d level=%d\n", i, run, level); -#endif } else { /* second escape */ SKIP_BITS(re, &s->gb, 2); @@ -795,12 +756,6 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, 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 */ @@ -810,29 +765,19 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, level = level + rl->max_level[run>>7][(run-1)&63] * qmul;//FIXME opt indexing level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); LAST_SKIP_BITS(re, &s->gb, 1); -#ifdef ERROR_DETAILS - if(run==66) - av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code in ESC1 level=%d\n", level); - else if((i>62 && i<192) || i>192+63) - av_log(s->avctx, AV_LOG_ERROR, "run overflow in ESC1 i=%d run=%d level=%d\n", i, run, level); -#endif } } else { i+= run; level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); LAST_SKIP_BITS(re, &s->gb, 1); -#ifdef ERROR_DETAILS - if(run==66) - av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code level=%d\n", level); - else if((i>62 && i<192) || i>192+63) - av_log(s->avctx, AV_LOG_ERROR, "run overflow i=%d run=%d level=%d\n", i, run, level); -#endif } if (i > 62){ i-= 192; if(i&(~63)){ const int left= get_bits_left(&s->gb); - if(((i+192 == 64 && level/qmul==-1) || !(s->err_recognition&AV_EF_BITSTREAM)) && left>=0){ + if (((i + 192 == 64 && level / qmul == -1) || + !(s->avctx->err_recognition & AV_EF_BITSTREAM)) && + left >= 0) { av_log(s->avctx, AV_LOG_ERROR, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y); break; }else{ @@ -909,7 +854,7 @@ AVCodec ff_msmpeg4v1_decoder = { .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE @@ -925,7 +870,7 @@ AVCodec ff_msmpeg4v2_decoder = { .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE @@ -941,7 +886,7 @@ AVCodec ff_msmpeg4v3_decoder = { .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE @@ -957,7 +902,7 @@ AVCodec ff_wmv1_decoder = { .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 45ef208..6d353e5 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -36,6 +36,7 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "h263.h" +#include "internal.h" #include "mpeg4video.h" #include "msmpeg4.h" #include "msmpeg4data.h" @@ -46,11 +47,14 @@ static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; /* build the table which associate a (x,y) motion vector to a vlc */ -static av_cold void init_mv_table(MVTable *tab) +static av_cold int init_mv_table(MVTable *tab) { int i, x, y; tab->table_mv_index = av_malloc(sizeof(uint16_t) * 4096); + if (!tab->table_mv_index) + return AVERROR(ENOMEM); + /* mark all entries as not used */ for(i=0;i<4096;i++) tab->table_mv_index[i] = tab->n; @@ -60,6 +64,8 @@ static av_cold void init_mv_table(MVTable *tab) y = tab->table_mvy[i]; tab->table_mv_index[(x << 6) | y] = i; } + + return 0; } void ff_msmpeg4_code012(PutBitContext *pb, int n) @@ -113,10 +119,10 @@ static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, return size; } -av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) +av_cold int ff_msmpeg4_encode_init(MpegEncContext *s) { static int init_done=0; - int i; + int i, ret; ff_msmpeg4_common_init(s); if(s->msmpeg4_version>=4){ @@ -127,10 +133,12 @@ av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) if (!init_done) { /* init various encoding tables */ init_done = 1; - init_mv_table(&ff_mv_tables[0]); - init_mv_table(&ff_mv_tables[1]); + if ((ret = init_mv_table(&ff_mv_tables[0])) < 0) + return ret; + if ((ret = init_mv_table(&ff_mv_tables[1])) < 0) + return ret; for(i=0;idc_table_index = 1; - s->mv_table_index = 1; /* only if P frame */ - s->use_skip_mb_code = 1; /* only if P frame */ + s->mv_table_index = 1; /* only if P-frame */ + s->use_skip_mb_code = 1; /* only if P-frame */ s->per_mb_rl_table = 0; if(s->msmpeg4_version==4) s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE && s->pict_type==AV_PICTURE_TYPE_P); - av_dlog(s, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, + ff_dlog(s, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height); if (s->pict_type == AV_PICTURE_TYPE_I) { @@ -304,11 +314,6 @@ void ff_msmpeg4_encode_motion(MpegEncContext * s, mx += 32; my += 32; -#if 0 - if ((unsigned)mx >= 64 || - (unsigned)my >= 64) - av_log(s->avctx, AV_LOG_ERROR, "error mx=%d my=%d\n", mx, my); -#endif mv = &ff_mv_tables[s->mv_table_index]; code = mv->table_mv_index[(mx << 6) | my]; @@ -567,9 +572,8 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr } } -/* Encoding of a block. Very similar to MPEG4 except for a different - escape coding (same as H263) and more vlc tables. - */ +/* Encoding of a block; very similar to MPEG-4 except for a different + * escape coding (same as H.263) and more VLC tables. */ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) { int level, run, last, i, j, last_index; diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c index 4b39c92..a7838ab 100644 --- a/libavcodec/msrle.c +++ b/libavcodec/msrle.c @@ -1,6 +1,6 @@ /* * Microsoft RLE video decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -126,7 +126,7 @@ static int msrle_decode_frame(AVCodecContext *avctx, } } else { bytestream2_init(&s->gb, buf, buf_size); - ff_msrle_decode(avctx, (AVPicture*)s->frame, avctx->bits_per_coded_sample, &s->gb); + ff_msrle_decode(avctx, s->frame, avctx->bits_per_coded_sample, &s->gb); } if ((ret = av_frame_ref(data, s->frame)) < 0) @@ -157,5 +157,5 @@ AVCodec ff_msrle_decoder = { .init = msrle_decode_init, .close = msrle_decode_end, .decode = msrle_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/msrledec.c b/libavcodec/msrledec.c index 370d9bd..f45179f 100644 --- a/libavcodec/msrledec.c +++ b/libavcodec/msrledec.c @@ -30,7 +30,7 @@ #include "avcodec.h" #include "msrledec.h" -static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic, +static int msrle_decode_pal4(AVCodecContext *avctx, AVFrame *pic, GetByteContext *gb) { unsigned char rle_code; @@ -128,7 +128,7 @@ static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic, } -static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, +static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVFrame *pic, int depth, GetByteContext *gb) { uint8_t *output, *output_end; @@ -243,7 +243,7 @@ static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, } -int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, +int ff_msrle_decode(AVCodecContext *avctx, AVFrame *pic, int depth, GetByteContext *gb) { switch(depth){ diff --git a/libavcodec/msrledec.h b/libavcodec/msrledec.h index a594de3..0c5b8b1 100644 --- a/libavcodec/msrledec.h +++ b/libavcodec/msrledec.h @@ -33,7 +33,7 @@ * @param depth bit depth * @param gb input bytestream context */ -int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, +int ff_msrle_decode(AVCodecContext *avctx, AVFrame *pic, int depth, GetByteContext *gb); #endif /* AVCODEC_MSRLEDEC_H */ diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index a67a942..a31af06 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -224,5 +224,5 @@ AVCodec ff_mss1_decoder = { .init = mss1_decode_init, .close = mss1_decode_end, .decode = mss1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/mss12.c b/libavcodec/mss12.c index d4b621f..b9bda16 100644 --- a/libavcodec/mss12.c +++ b/libavcodec/mss12.c @@ -588,6 +588,16 @@ av_cold int ff_mss12_decode_init(MSS12Context *c, int version, avctx->coded_width, avctx->coded_height); return AVERROR_INVALIDDATA; } + if (avctx->width || avctx->height) { + if (avctx->width <= 0 || avctx->width > avctx->coded_width || + avctx->height <= 0 || avctx->height > avctx->coded_height) { + av_log(avctx, AV_LOG_ERROR, "Invalid display dimensions\n"); + return AVERROR_INVALIDDATA; + } + } else { + avctx->width = avctx->coded_width; + avctx->height = avctx->coded_height; + } av_log(avctx, AV_LOG_DEBUG, "Encoder version %"PRIu32".%"PRIu32"\n", AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c index d71d308..3768196 100644 --- a/libavcodec/mss2.c +++ b/libavcodec/mss2.c @@ -27,9 +27,10 @@ #include "error_resilience.h" #include "internal.h" #include "mpeg_er.h" -#include "msmpeg4data.h" +#include "msmpeg4.h" #include "qpeldsp.h" #include "vc1.h" +#include "wmv2data.h" #include "mss12.h" #include "mss2dsp.h" @@ -415,7 +416,13 @@ static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size, ff_vc1_decode_blocks(v); - ff_er_frame_end(&s->er); + if (v->end_mb_x == s->mb_width && s->end_mb_y == s->mb_height) { + ff_er_frame_end(&s->er); + } else { + av_log(v->s.avctx, AV_LOG_WARNING, + "disabling error correction due to block count mismatch %dx%d != %dx%d\n", + v->end_mb_x, s->end_mb_y, s->mb_width, s->mb_height); + } ff_mpv_frame_end(s); @@ -475,9 +482,6 @@ static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, Rectangle wmv9rects[MAX_WMV9_RECTANGLES], *r; int used_rects = 0, i, implicit_rect = 0, av_uninit(wmv9_mask); - av_assert0(FF_INPUT_BUFFER_PADDING_SIZE >= - ARITH2_PADDING + (MIN_CACHE_BITS + 7) / 8); - init_get_bits(&gb, buf, buf_size * 8); if (keyframe = get_bits1(&gb)) @@ -853,5 +857,5 @@ AVCodec ff_mss2_decoder = { .init = mss2_decode_init, .close = mss2_decode_end, .decode = mss2_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/mss3.c b/libavcodec/mss3.c index 9a0b1fb..c124834 100644 --- a/libavcodec/mss3.c +++ b/libavcodec/mss3.c @@ -870,5 +870,5 @@ AVCodec ff_msa1_decoder = { .init = mss3_decode_init, .close = mss3_decode_end, .decode = mss3_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index 9198acc..a953a57 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -680,5 +680,5 @@ AVCodec ff_mts2_decoder = { .init = mss4_decode_init, .close = mss4_decode_end, .decode = mss4_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c index 7fd8633..37ea32d 100644 --- a/libavcodec/msvideo1.c +++ b/libavcodec/msvideo1.c @@ -1,6 +1,6 @@ /* * Microsoft Video-1 Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -24,7 +24,6 @@ * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net) * For more information about the MS Video-1 format, visit: * http://www.pcisys.net/~melanson/codecs/ - * */ #include @@ -346,5 +345,5 @@ AVCodec ff_msvideo1_decoder = { .init = msvideo1_decode_init, .close = msvideo1_decode_end, .decode = msvideo1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c index 7cc0329..1546bcc 100644 --- a/libavcodec/mvcdec.c +++ b/libavcodec/mvcdec.c @@ -274,7 +274,7 @@ AVCodec ff_mvc1_decoder = { .init = mvc_decode_init, .close = mvc_decode_end, .decode = mvc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -288,6 +288,6 @@ AVCodec ff_mvc2_decoder = { .init = mvc_decode_init, .close = mvc_decode_end, .decode = mvc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c index bfaae34..a8ef6d0 100644 --- a/libavcodec/mxpegdec.c +++ b/libavcodec/mxpegdec.c @@ -345,5 +345,6 @@ AVCodec ff_mxpeg_decoder = { .init = mxpeg_decode_init, .close = mxpeg_decode_end, .decode = mxpeg_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/nellymoser.c b/libavcodec/nellymoser.c index 0740c75..027726e 100644 --- a/libavcodec/nellymoser.c +++ b/libavcodec/nellymoser.c @@ -31,11 +31,10 @@ * implementors. The original code is available from http://code.google.com/p/nelly2pcm/ */ -#include "nellymoser.h" -#include "avcodec.h" +#include "libavutil/common.h" -#define BITSTREAM_READER_LE -#include "get_bits.h" +#include "avcodec.h" +#include "nellymoser.h" const float ff_nelly_dequantization_table[127] = { 0.0000000000, diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c index 3b9b77c..355935f 100644 --- a/libavcodec/nellymoserdec.c +++ b/libavcodec/nellymoserdec.c @@ -35,16 +35,15 @@ #include "libavutil/float_dsp.h" #include "libavutil/lfg.h" #include "libavutil/random_seed.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "fft.h" -#include "fmtconvert.h" +#include "get_bits.h" #include "internal.h" #include "nellymoser.h" #include "sinewin.h" -#define BITSTREAM_READER_LE -#include "get_bits.h" - typedef struct NellyMoserDecodeContext { AVCodecContext* avctx; @@ -122,7 +121,7 @@ static av_cold int decode_init(AVCodecContext * avctx) { av_lfg_init(&s->random_state, 0); ff_mdct_init(&s->imdct_ctx, 8, 1, 1.0); - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); s->scale_bias = 1.0/(32768*8); avctx->sample_fmt = AV_SAMPLE_FMT_FLT; @@ -200,7 +199,7 @@ AVCodec ff_nellymoser_decoder = { .init = decode_init, .close = decode_end, .decode = decode_tag, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c index 5732163..9d12081 100644 --- a/libavcodec/nellymoserenc.c +++ b/libavcodec/nellymoserenc.c @@ -62,8 +62,8 @@ typedef struct NellyMoserEncodeContext { DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES]; DECLARE_ALIGNED(32, float, in_buff)[NELLY_SAMPLES]; DECLARE_ALIGNED(32, float, buf)[3 * NELLY_BUF_LEN]; ///< sample buffer - float (*opt )[NELLY_BANDS]; - uint8_t (*path)[NELLY_BANDS]; + float (*opt )[OPT_SIZE]; + uint8_t (*path)[OPT_SIZE]; } NellyMoserEncodeContext; static float pow_table[POW_TABLE_SIZE]; ///< -pow(2, -i / 2048.0 - 3.0); @@ -165,12 +165,12 @@ static av_cold int encode_init(AVCodecContext *avctx) } avctx->frame_size = NELLY_SAMPLES; - avctx->delay = NELLY_BUF_LEN; + avctx->initial_padding = NELLY_BUF_LEN; ff_af_queue_init(avctx, &s->afq); s->avctx = avctx; if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0) goto error; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); /* Generate overlap window */ ff_sine_window_init(ff_sine_128, 128); @@ -228,10 +228,10 @@ static void get_exponent_dynamic(NellyMoserEncodeContext *s, float *cand, int *i int i, j, band, best_idx; float power_candidate, best_val; - float (*opt )[NELLY_BANDS] = s->opt ; - uint8_t(*path)[NELLY_BANDS] = s->path; + float (*opt )[OPT_SIZE] = s->opt ; + uint8_t(*path)[OPT_SIZE] = s->path; - for (i = 0; i < NELLY_BANDS * OPT_SIZE; i++) { + for (i = 0; i < OPT_SIZE; i++) { opt[0][i] = INFINITY; } @@ -415,7 +415,7 @@ AVCodec ff_nellymoser_encoder = { .init = encode_init, .encode2 = encode_frame, .close = encode_end, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c index 3e552e2..3b41dbf 100644 --- a/libavcodec/noise_bsf.c +++ b/libavcodec/noise_bsf.c @@ -22,29 +22,67 @@ #include #include "avcodec.h" +#include "bsf.h" + +#include "libavutil/log.h" #include "libavutil/mem.h" +#include "libavutil/opt.h" + +typedef struct NoiseContext { + const AVClass *class; + int amount; + unsigned int state; +} NoiseContext; + +static int noise(AVBSFContext *ctx, AVPacket *out) +{ + NoiseContext *s = ctx->priv_data; + AVPacket *in; + int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1); + int i, ret = 0; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + ret = av_new_packet(out, in->size); + if (ret < 0) + goto fail; -static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe){ - unsigned int *state= bsfc->priv_data; - int amount= args ? atoi(args) : (*state % 10001+1); - int i; + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; - *poutbuf= av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(out->data, in->data, in->size); - memcpy(*poutbuf, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); - for(i=0; isize; i++) { + s->state += out->data[i] + 1; + if (s->state % amount == 0) + out->data[i] = s->state; } - return 1; +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; } -AVBitStreamFilter ff_noise_bsf={ - "noise", - sizeof(int), - noise, +#define OFFSET(x) offsetof(NoiseContext, x) +static const AVOption options[] = { + { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX }, + { NULL }, +}; + +static const AVClass noise_class = { + .class_name = "noise", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVBitStreamFilter ff_noise_bsf = { + .name = "noise", + .priv_data_size = sizeof(int), + .priv_class = &noise_class, + .filter = noise, }; diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index c31ff11..92c1fda 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -32,7 +32,7 @@ #include "internal.h" #include "rtjpeg.h" -typedef struct { +typedef struct NuvContext { AVFrame *pic; int codec_frameheader; int quality; @@ -74,9 +74,12 @@ static const uint8_t fallback_cquant[] = { */ static void copy_frame(AVFrame *f, const uint8_t *src, int width, int height) { - AVPicture pic; - avpicture_fill(&pic, src, AV_PIX_FMT_YUV420P, width, height); - av_picture_copy((AVPicture *)f, &pic, AV_PIX_FMT_YUV420P, width, height); + uint8_t *src_data[4]; + int src_linesize[4]; + av_image_fill_arrays(src_data, src_linesize, src, + f->format, width, height, 1); + av_image_copy(f->data, f->linesize, src_data, src_linesize, + f->format, width, height); } /** @@ -128,7 +131,7 @@ static int codec_reinit(AVCodecContext *avctx, int width, int height, avctx->height = c->height = height; ptr = av_fast_realloc(c->decomp_buf, &c->decomp_size, c->height * c->width * 3 / 2 + - FF_INPUT_BUFFER_PADDING_SIZE + + AV_INPUT_BUFFER_PADDING_SIZE + RTJPEG_HEADER_SIZE); if (!ptr) { av_log(avctx, AV_LOG_ERROR, @@ -171,7 +174,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, // codec data (rtjpeg quant tables) if (buf[0] == 'D' && buf[1] == 'R') { int ret; - // skip rest of the frameheader. + // Skip the rest of the frame header. buf = &buf[12]; buf_size -= 12; ret = get_quant(avctx, c, buf, buf_size); @@ -198,11 +201,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, keyframe = 1; break; } - // skip rest of the frameheader. + // Skip the rest of the frame header. buf = &buf[12]; buf_size -= 12; if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) { - int outlen = c->decomp_size - FF_INPUT_BUFFER_PADDING_SIZE; + int outlen = c->decomp_size - AV_INPUT_BUFFER_PADDING_SIZE; int inlen = buf_size; if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) { av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); @@ -332,5 +335,5 @@ AVCodec ff_nuv_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c new file mode 100644 index 0000000..3c1528c --- /dev/null +++ b/libavcodec/nvenc.c @@ -0,0 +1,1460 @@ +/* + * NVIDIA NVENC Support + * Copyright (C) 2015 Luca Barbato + * Copyright (C) 2015 Philip Langdale + * Copyright (C) 2014 Timo Rothenpieler + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include + +#define CUDA_LIBNAME "libcuda.so" + +#if HAVE_DLFCN_H +#include + +#define NVENC_LIBNAME "libnvidia-encode.so" + +#elif HAVE_WINDOWS_H +#include + +#if ARCH_X86_64 +#define NVENC_LIBNAME "nvEncodeAPI64.dll" +#else +#define NVENC_LIBNAME "nvEncodeAPI.dll" +#endif + +#define dlopen(filename, flags) LoadLibrary((filename)) +#define dlsym(handle, symbol) GetProcAddress(handle, symbol) +#define dlclose(handle) FreeLibrary(handle) +#endif + +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "internal.h" +#include "nvenc.h" + +#if CONFIG_CUDA +#include "libavutil/hwcontext_cuda.h" +#endif + +#define NVENC_CAP 0x30 +#define BITSTREAM_BUFFER_SIZE 1024 * 1024 +#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \ + rc == NV_ENC_PARAMS_RC_2_PASS_QUALITY || \ + rc == NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP) + +#define LOAD_LIBRARY(l, path) \ + do { \ + if (!((l) = dlopen(path, RTLD_LAZY))) { \ + av_log(avctx, AV_LOG_ERROR, \ + "Cannot load %s\n", \ + path); \ + return AVERROR_UNKNOWN; \ + } \ + } while (0) + +#define LOAD_SYMBOL(fun, lib, symbol) \ + do { \ + if (!((fun) = dlsym(lib, symbol))) { \ + av_log(avctx, AV_LOG_ERROR, \ + "Cannot load %s\n", \ + symbol); \ + return AVERROR_UNKNOWN; \ + } \ + } while (0) + +const enum AVPixelFormat ff_nvenc_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV444P, +#if CONFIG_CUDA + AV_PIX_FMT_CUDA, +#endif + AV_PIX_FMT_NONE +}; + +static const struct { + NVENCSTATUS nverr; + int averr; + const char *desc; +} nvenc_errors[] = { + { NV_ENC_SUCCESS, 0, "success" }, + { NV_ENC_ERR_NO_ENCODE_DEVICE, AVERROR(ENOENT), "no encode device" }, + { NV_ENC_ERR_UNSUPPORTED_DEVICE, AVERROR(ENOSYS), "unsupported device" }, + { NV_ENC_ERR_INVALID_ENCODERDEVICE, AVERROR(EINVAL), "invalid encoder device" }, + { NV_ENC_ERR_INVALID_DEVICE, AVERROR(EINVAL), "invalid device" }, + { NV_ENC_ERR_DEVICE_NOT_EXIST, AVERROR(EIO), "device does not exist" }, + { NV_ENC_ERR_INVALID_PTR, AVERROR(EFAULT), "invalid ptr" }, + { NV_ENC_ERR_INVALID_EVENT, AVERROR(EINVAL), "invalid event" }, + { NV_ENC_ERR_INVALID_PARAM, AVERROR(EINVAL), "invalid param" }, + { NV_ENC_ERR_INVALID_CALL, AVERROR(EINVAL), "invalid call" }, + { NV_ENC_ERR_OUT_OF_MEMORY, AVERROR(ENOMEM), "out of memory" }, + { NV_ENC_ERR_ENCODER_NOT_INITIALIZED, AVERROR(EINVAL), "encoder not initialized" }, + { NV_ENC_ERR_UNSUPPORTED_PARAM, AVERROR(ENOSYS), "unsupported param" }, + { NV_ENC_ERR_LOCK_BUSY, AVERROR(EBUSY), "lock busy" }, + { NV_ENC_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOBUFS), "not enough buffer" }, + { NV_ENC_ERR_INVALID_VERSION, AVERROR(EINVAL), "invalid version" }, + { NV_ENC_ERR_MAP_FAILED, AVERROR(EIO), "map failed" }, + /* this is error should always be treated specially, so this "mapping" + * is for completeness only */ + { NV_ENC_ERR_NEED_MORE_INPUT, AVERROR_UNKNOWN, "need more input" }, + { NV_ENC_ERR_ENCODER_BUSY, AVERROR(EBUSY), "encoder busy" }, + { NV_ENC_ERR_EVENT_NOT_REGISTERD, AVERROR(EBADF), "event not registered" }, + { NV_ENC_ERR_GENERIC, AVERROR_UNKNOWN, "generic error" }, + { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY, AVERROR(EINVAL), "incompatible client key" }, + { NV_ENC_ERR_UNIMPLEMENTED, AVERROR(ENOSYS), "unimplemented" }, + { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO), "resource register failed" }, + { NV_ENC_ERR_RESOURCE_NOT_REGISTERED, AVERROR(EBADF), "resource not registered" }, + { NV_ENC_ERR_RESOURCE_NOT_MAPPED, AVERROR(EBADF), "resource not mapped" }, +}; + +static int nvenc_map_error(NVENCSTATUS err, const char **desc) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) { + if (nvenc_errors[i].nverr == err) { + if (desc) + *desc = nvenc_errors[i].desc; + return nvenc_errors[i].averr; + } + } + if (desc) + *desc = "unknown error"; + return AVERROR_UNKNOWN; +} + +static int nvenc_print_error(void *log_ctx, NVENCSTATUS err, + const char *error_string) +{ + const char *desc; + int ret; + ret = nvenc_map_error(err, &desc); + av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err); + return ret; +} + +static av_cold int nvenc_load_libraries(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NVENCLibraryContext *nvel = &ctx->nvel; + PNVENCODEAPICREATEINSTANCE nvenc_create_instance; + NVENCSTATUS err; + +#if CONFIG_CUDA + nvel->cu_init = cuInit; + nvel->cu_device_get_count = cuDeviceGetCount; + nvel->cu_device_get = cuDeviceGet; + nvel->cu_device_get_name = cuDeviceGetName; + nvel->cu_device_compute_capability = cuDeviceComputeCapability; + nvel->cu_ctx_create = cuCtxCreate_v2; + nvel->cu_ctx_pop_current = cuCtxPopCurrent_v2; + nvel->cu_ctx_destroy = cuCtxDestroy_v2; +#else + LOAD_LIBRARY(nvel->cuda, CUDA_LIBNAME); + + LOAD_SYMBOL(nvel->cu_init, nvel->cuda, "cuInit"); + LOAD_SYMBOL(nvel->cu_device_get_count, nvel->cuda, "cuDeviceGetCount"); + LOAD_SYMBOL(nvel->cu_device_get, nvel->cuda, "cuDeviceGet"); + LOAD_SYMBOL(nvel->cu_device_get_name, nvel->cuda, "cuDeviceGetName"); + LOAD_SYMBOL(nvel->cu_device_compute_capability, nvel->cuda, + "cuDeviceComputeCapability"); + LOAD_SYMBOL(nvel->cu_ctx_create, nvel->cuda, "cuCtxCreate_v2"); + LOAD_SYMBOL(nvel->cu_ctx_pop_current, nvel->cuda, "cuCtxPopCurrent_v2"); + LOAD_SYMBOL(nvel->cu_ctx_destroy, nvel->cuda, "cuCtxDestroy_v2"); +#endif + + LOAD_LIBRARY(nvel->nvenc, NVENC_LIBNAME); + + LOAD_SYMBOL(nvenc_create_instance, nvel->nvenc, + "NvEncodeAPICreateInstance"); + + nvel->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER; + + err = nvenc_create_instance(&nvel->nvenc_funcs); + if (err != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, err, "Cannot create the NVENC instance"); + + return 0; +} + +static int nvenc_open_session(AVCodecContext *avctx) +{ + NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 }; + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int ret; + + params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER; + params.apiVersion = NVENCAPI_VERSION; + params.device = ctx->cu_context; + params.deviceType = NV_ENC_DEVICE_TYPE_CUDA; + + ret = nv->nvEncOpenEncodeSessionEx(¶ms, &ctx->nvenc_ctx); + if (ret != NV_ENC_SUCCESS) { + ctx->nvenc_ctx = NULL; + return nvenc_print_error(avctx, ret, "Cannot open the NVENC Session"); + } + + return 0; +} + +static int nvenc_check_codec_support(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int i, ret, count = 0; + GUID *guids = NULL; + + ret = nv->nvEncGetEncodeGUIDCount(ctx->nvenc_ctx, &count); + + if (ret != NV_ENC_SUCCESS || !count) + return AVERROR(ENOSYS); + + guids = av_malloc(count * sizeof(GUID)); + if (!guids) + return AVERROR(ENOMEM); + + ret = nv->nvEncGetEncodeGUIDs(ctx->nvenc_ctx, guids, count, &count); + if (ret != NV_ENC_SUCCESS) { + ret = AVERROR(ENOSYS); + goto fail; + } + + ret = AVERROR(ENOSYS); + for (i = 0; i < count; i++) { + if (!memcmp(&guids[i], &ctx->params.encodeGUID, sizeof(*guids))) { + ret = 0; + break; + } + } + +fail: + av_free(guids); + + return ret; +} + +static int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NV_ENC_CAPS_PARAM params = { 0 }; + int ret, val = 0; + + params.version = NV_ENC_CAPS_PARAM_VER; + params.capsToQuery = cap; + + ret = nv->nvEncGetEncodeCaps(ctx->nvenc_ctx, ctx->params.encodeGUID, ¶ms, &val); + + if (ret == NV_ENC_SUCCESS) + return val; + return 0; +} + +static int nvenc_check_capabilities(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + int ret; + + ret = nvenc_check_codec_support(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_VERBOSE, "Codec not supported\n"); + return ret; + } + + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE); + if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P && ret <= 0) { + av_log(avctx, AV_LOG_VERBOSE, "YUV444P not supported\n"); + return AVERROR(ENOSYS); + } + + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX); + if (ret < avctx->width) { + av_log(avctx, AV_LOG_VERBOSE, "Width %d exceeds %d\n", + avctx->width, ret); + return AVERROR(ENOSYS); + } + + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX); + if (ret < avctx->height) { + av_log(avctx, AV_LOG_VERBOSE, "Height %d exceeds %d\n", + avctx->height, ret); + return AVERROR(ENOSYS); + } + + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES); + if (ret < avctx->max_b_frames) { + av_log(avctx, AV_LOG_VERBOSE, "Max B-frames %d exceed %d\n", + avctx->max_b_frames, ret); + + return AVERROR(ENOSYS); + } + + return 0; +} + +static int nvenc_check_device(AVCodecContext *avctx, int idx) +{ + NVENCContext *ctx = avctx->priv_data; + NVENCLibraryContext *nvel = &ctx->nvel; + char name[128] = { 0 }; + int major, minor, ret; + CUdevice cu_device; + CUcontext dummy; + int loglevel = AV_LOG_VERBOSE; + + if (ctx->device == LIST_DEVICES) + loglevel = AV_LOG_INFO; + + ret = nvel->cu_device_get(&cu_device, idx); + if (ret != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, + "Cannot access the CUDA device %d\n", + idx); + return -1; + } + + ret = nvel->cu_device_get_name(name, sizeof(name), cu_device); + if (ret != CUDA_SUCCESS) + return -1; + + ret = nvel->cu_device_compute_capability(&major, &minor, cu_device); + if (ret != CUDA_SUCCESS) + return -1; + + av_log(avctx, loglevel, "Device %d [%s] ", cu_device, name); + + if (((major << 4) | minor) < NVENC_CAP) + goto fail; + + ret = nvel->cu_ctx_create(&ctx->cu_context_internal, 0, cu_device); + if (ret != CUDA_SUCCESS) + goto fail; + + ctx->cu_context = ctx->cu_context_internal; + + ret = nvel->cu_ctx_pop_current(&dummy); + if (ret != CUDA_SUCCESS) + goto fail2; + + if ((ret = nvenc_open_session(avctx)) < 0) + goto fail2; + + if ((ret = nvenc_check_capabilities(avctx)) < 0) + goto fail3; + + av_log(avctx, loglevel, "supports NVENC\n"); + + if (ctx->device == cu_device || ctx->device == ANY_DEVICE) + return 0; + +fail3: + nvel->nvenc_funcs.nvEncDestroyEncoder(ctx->nvenc_ctx); + ctx->nvenc_ctx = NULL; + +fail2: + nvel->cu_ctx_destroy(ctx->cu_context_internal); + ctx->cu_context_internal = NULL; + +fail: + if (ret != 0) + av_log(avctx, loglevel, "does not support NVENC (major %d minor %d)\n", + major, minor); + + return AVERROR(ENOSYS); +} + +static int nvenc_setup_device(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NVENCLibraryContext *nvel = &ctx->nvel; + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + ctx->params.encodeGUID = NV_ENC_CODEC_H264_GUID; + break; + case AV_CODEC_ID_HEVC: + ctx->params.encodeGUID = NV_ENC_CODEC_HEVC_GUID; + break; + default: + return AVERROR_BUG; + } + + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { +#if CONFIG_CUDA + AVHWFramesContext *frames_ctx; + AVCUDADeviceContext *device_hwctx; + int ret; + + if (!avctx->hw_frames_ctx) + return AVERROR(EINVAL); + + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + device_hwctx = frames_ctx->device_ctx->hwctx; + + ctx->cu_context = device_hwctx->cuda_ctx; + + ret = nvenc_open_session(avctx); + if (ret < 0) + return ret; + + ret = nvenc_check_capabilities(avctx); + if (ret < 0) + return ret; +#else + return AVERROR_BUG; +#endif + } else { + int i, nb_devices = 0; + + if ((nvel->cu_init(0)) != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, + "Cannot init CUDA\n"); + return AVERROR_UNKNOWN; + } + + if ((nvel->cu_device_get_count(&nb_devices)) != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, + "Cannot enumerate the CUDA devices\n"); + return AVERROR_UNKNOWN; + } + + + for (i = 0; i < nb_devices; ++i) { + if ((nvenc_check_device(avctx, i)) >= 0 && ctx->device != LIST_DEVICES) + return 0; + } + + if (ctx->device == LIST_DEVICES) + return AVERROR_EXIT; + + return AVERROR(ENOSYS); + } + + return 0; +} + +typedef struct GUIDTuple { + const GUID guid; + int flags; +} GUIDTuple; + +static int nvec_map_preset(NVENCContext *ctx) +{ + GUIDTuple presets[] = { + { NV_ENC_PRESET_DEFAULT_GUID }, + { NV_ENC_PRESET_HP_GUID }, + { NV_ENC_PRESET_HQ_GUID }, + { NV_ENC_PRESET_BD_GUID }, + { NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID, NVENC_LOWLATENCY }, + { NV_ENC_PRESET_LOW_LATENCY_HP_GUID, NVENC_LOWLATENCY }, + { NV_ENC_PRESET_LOW_LATENCY_HQ_GUID, NVENC_LOWLATENCY }, + { NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID, NVENC_LOSSLESS }, + { NV_ENC_PRESET_LOSSLESS_HP_GUID, NVENC_LOSSLESS }, + { { 0 } } + }; + + GUIDTuple *t = &presets[ctx->preset]; + + ctx->params.presetGUID = t->guid; + ctx->flags = t->flags; + + return AVERROR(EINVAL); +} + +static void set_constqp(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) +{ + rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; + rc->constQP.qpInterB = avctx->global_quality; + rc->constQP.qpInterP = avctx->global_quality; + rc->constQP.qpIntra = avctx->global_quality; +} + +static void set_vbr(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) +{ + if (avctx->qmin >= 0) { + rc->enableMinQP = 1; + rc->minQP.qpInterB = avctx->qmin; + rc->minQP.qpInterP = avctx->qmin; + rc->minQP.qpIntra = avctx->qmin; + } + + if (avctx->qmax >= 0) { + rc->enableMaxQP = 1; + rc->maxQP.qpInterB = avctx->qmax; + rc->maxQP.qpInterP = avctx->qmax; + rc->maxQP.qpIntra = avctx->qmax; + } +} + +static void set_lossless(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) +{ + rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; + rc->constQP.qpInterB = 0; + rc->constQP.qpInterP = 0; + rc->constQP.qpIntra = 0; +} + +static void nvenc_override_rate_control(AVCodecContext *avctx, + NV_ENC_RC_PARAMS *rc) +{ + NVENCContext *ctx = avctx->priv_data; + + switch (ctx->rc) { + case NV_ENC_PARAMS_RC_CONSTQP: + if (avctx->global_quality < 0) { + av_log(avctx, AV_LOG_WARNING, + "The constant quality rate-control requires " + "the 'global_quality' option set.\n"); + return; + } + set_constqp(avctx, rc); + return; + case NV_ENC_PARAMS_RC_2_PASS_VBR: + case NV_ENC_PARAMS_RC_VBR: + if (avctx->qmin < 0 && avctx->qmax < 0) { + av_log(avctx, AV_LOG_WARNING, + "The variable bitrate rate-control requires " + "the 'qmin' and/or 'qmax' option set.\n"); + return; + } + case NV_ENC_PARAMS_RC_VBR_MINQP: + if (avctx->qmin < 0) { + av_log(avctx, AV_LOG_WARNING, + "The variable bitrate rate-control requires " + "the 'qmin' option set.\n"); + return; + } + set_vbr(avctx, rc); + break; + case NV_ENC_PARAMS_RC_CBR: + break; + case NV_ENC_PARAMS_RC_2_PASS_QUALITY: + case NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP: + if (!(ctx->flags & NVENC_LOWLATENCY)) { + av_log(avctx, AV_LOG_WARNING, + "The multipass rate-control requires " + "a low-latency preset.\n"); + return; + } + } + + rc->rateControlMode = ctx->rc; +} + +static void nvenc_setup_rate_control(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENC_RC_PARAMS *rc = &ctx->config.rcParams; + + if (avctx->bit_rate > 0) + rc->averageBitRate = avctx->bit_rate; + + if (avctx->rc_max_rate > 0) + rc->maxBitRate = avctx->rc_max_rate; + + if (ctx->rc > 0) { + nvenc_override_rate_control(avctx, rc); + } else if (ctx->flags & NVENC_LOSSLESS) { + set_lossless(avctx, rc); + } else if (avctx->global_quality > 0) { + set_constqp(avctx, rc); + } else if (avctx->qmin >= 0 && avctx->qmax >= 0) { + rc->rateControlMode = NV_ENC_PARAMS_RC_VBR; + set_vbr(avctx, rc); + } + + if (avctx->rc_buffer_size > 0) + rc->vbvBufferSize = avctx->rc_buffer_size; + + if (rc->averageBitRate > 0) + avctx->bit_rate = rc->averageBitRate; +} + +static int nvenc_setup_h264_config(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENC_CONFIG *cc = &ctx->config; + NV_ENC_CONFIG_H264 *h264 = &cc->encodeCodecConfig.h264Config; + NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters; + + vui->colourDescriptionPresentFlag = avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED; + + vui->colourMatrix = avctx->colorspace; + vui->colourPrimaries = avctx->color_primaries; + vui->transferCharacteristics = avctx->color_trc; + + vui->videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG; + + vui->videoSignalTypePresentFlag = vui->colourDescriptionPresentFlag || + vui->videoFullRangeFlag; + + h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; + h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; + h264->outputAUD = 1; + + h264->maxNumRefFrames = avctx->refs; + h264->idrPeriod = cc->gopLength; + + h264->sliceMode = 3; + h264->sliceModeData = FFMAX(avctx->slices, 1); + + if (ctx->flags & NVENC_LOSSLESS) + h264->qpPrimeYZeroTransformBypassFlag = 1; + + if (IS_CBR(cc->rcParams.rateControlMode)) { + h264->outputBufferingPeriodSEI = 1; + h264->outputPictureTimingSEI = 1; + } + + if (ctx->profile) + avctx->profile = ctx->profile; + + if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P) + h264->chromaFormatIDC = 3; + else + h264->chromaFormatIDC = 1; + + switch (ctx->profile) { + case NV_ENC_H264_PROFILE_BASELINE: + cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID; + break; + case NV_ENC_H264_PROFILE_MAIN: + cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID; + break; + case NV_ENC_H264_PROFILE_HIGH: + cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID; + break; + case NV_ENC_H264_PROFILE_HIGH_444: + cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID; + break; + case NV_ENC_H264_PROFILE_CONSTRAINED_HIGH: + cc->profileGUID = NV_ENC_H264_PROFILE_CONSTRAINED_HIGH_GUID; + break; + } + + h264->level = ctx->level; + + return 0; +} + +static int nvenc_setup_hevc_config(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENC_CONFIG *cc = &ctx->config; + NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig; + NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters; + + vui->colourDescriptionPresentFlag = avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED; + + vui->colourMatrix = avctx->colorspace; + vui->colourPrimaries = avctx->color_primaries; + vui->transferCharacteristics = avctx->color_trc; + + vui->videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG; + + vui->videoSignalTypePresentFlag = vui->colourDescriptionPresentFlag || + vui->videoFullRangeFlag; + + hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; + hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; + hevc->outputAUD = 1; + + hevc->maxNumRefFramesInDPB = avctx->refs; + hevc->idrPeriod = cc->gopLength; + + if (IS_CBR(cc->rcParams.rateControlMode)) { + hevc->outputBufferingPeriodSEI = 1; + hevc->outputPictureTimingSEI = 1; + } + + /* No other profile is supported in the current SDK version 5 */ + cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; + avctx->profile = FF_PROFILE_HEVC_MAIN; + + hevc->sliceMode = 3; + hevc->sliceModeData = FFMAX(avctx->slices, 1); + + if (ctx->level) { + hevc->level = ctx->level; + } else { + hevc->level = NV_ENC_LEVEL_AUTOSELECT; + } + + if (ctx->tier) { + hevc->tier = ctx->tier; + } + + return 0; +} +static int nvenc_setup_codec_config(AVCodecContext *avctx) +{ + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + return nvenc_setup_h264_config(avctx); + case AV_CODEC_ID_HEVC: + return nvenc_setup_hevc_config(avctx); + } + return 0; +} + +static int nvenc_setup_encoder(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NV_ENC_PRESET_CONFIG preset_cfg = { 0 }; + AVCPBProperties *cpb_props; + int ret; + + ctx->params.version = NV_ENC_INITIALIZE_PARAMS_VER; + + ctx->params.encodeHeight = avctx->height; + ctx->params.encodeWidth = avctx->width; + + if (avctx->sample_aspect_ratio.num && + avctx->sample_aspect_ratio.den && + (avctx->sample_aspect_ratio.num != 1 || + avctx->sample_aspect_ratio.den != 1)) { + av_reduce(&ctx->params.darWidth, + &ctx->params.darHeight, + avctx->width * avctx->sample_aspect_ratio.num, + avctx->height * avctx->sample_aspect_ratio.den, + INT_MAX / 8); + } else { + ctx->params.darHeight = avctx->height; + ctx->params.darWidth = avctx->width; + } + + // De-compensate for hardware, dubiously, trying to compensate for + // playback at 704 pixel width. + if (avctx->width == 720 && (avctx->height == 480 || avctx->height == 576)) { + av_reduce(&ctx->params.darWidth, &ctx->params.darHeight, + ctx->params.darWidth * 44, + ctx->params.darHeight * 45, + 1024 * 1024); + } + + ctx->params.frameRateNum = avctx->time_base.den; + ctx->params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; + + ctx->params.enableEncodeAsync = 0; + ctx->params.enablePTD = 1; + + ctx->params.encodeConfig = &ctx->config; + + nvec_map_preset(ctx); + + preset_cfg.version = NV_ENC_PRESET_CONFIG_VER; + preset_cfg.presetCfg.version = NV_ENC_CONFIG_VER; + + ret = nv->nvEncGetEncodePresetConfig(ctx->nvenc_ctx, + ctx->params.encodeGUID, + ctx->params.presetGUID, + &preset_cfg); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "Cannot get the preset configuration"); + + memcpy(&ctx->config, &preset_cfg.presetCfg, sizeof(ctx->config)); + + ctx->config.version = NV_ENC_CONFIG_VER; + + if (avctx->gop_size > 0) { + if (avctx->max_b_frames > 0) { + /* 0 is intra-only, + * 1 is I/P only, + * 2 is one B-Frame, + * 3 two B-frames, and so on. */ + ctx->config.frameIntervalP = avctx->max_b_frames + 1; + } else if (avctx->max_b_frames == 0) { + ctx->config.frameIntervalP = 1; + } + ctx->config.gopLength = avctx->gop_size; + } else if (avctx->gop_size == 0) { + ctx->config.frameIntervalP = 0; + ctx->config.gopLength = 1; + } + + if (ctx->config.frameIntervalP > 1) + avctx->max_b_frames = ctx->config.frameIntervalP - 1; + + ctx->initial_pts[0] = AV_NOPTS_VALUE; + ctx->initial_pts[1] = AV_NOPTS_VALUE; + + nvenc_setup_rate_control(avctx); + + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD; + } else { + ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME; + } + + if ((ret = nvenc_setup_codec_config(avctx)) < 0) + return ret; + + ret = nv->nvEncInitializeEncoder(ctx->nvenc_ctx, &ctx->params); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "Cannot initialize the decoder"); + + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->min_bitrate = avctx->rc_min_rate; + cpb_props->avg_bitrate = avctx->bit_rate; + cpb_props->buffer_size = avctx->rc_buffer_size; + + return 0; +} + +static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int ret; + NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 }; + + switch (ctx->data_pix_fmt) { + case AV_PIX_FMT_YUV420P: + ctx->frames[idx].format = NV_ENC_BUFFER_FORMAT_YV12_PL; + break; + case AV_PIX_FMT_NV12: + ctx->frames[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL; + break; + case AV_PIX_FMT_YUV444P: + ctx->frames[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL; + break; + default: + return AVERROR_BUG; + } + + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + ctx->frames[idx].in_ref = av_frame_alloc(); + if (!ctx->frames[idx].in_ref) + return AVERROR(ENOMEM); + } else { + NV_ENC_CREATE_INPUT_BUFFER in_buffer = { 0 }; + + in_buffer.version = NV_ENC_CREATE_INPUT_BUFFER_VER; + + in_buffer.width = avctx->width; + in_buffer.height = avctx->height; + + in_buffer.bufferFmt = ctx->frames[idx].format; + in_buffer.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_UNCACHED; + + ret = nv->nvEncCreateInputBuffer(ctx->nvenc_ctx, &in_buffer); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "CreateInputBuffer failed"); + + ctx->frames[idx].in = in_buffer.inputBuffer; + } + + out_buffer.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; + /* 1MB is large enough to hold most output frames. + * NVENC increases this automatically if it is not enough. */ + out_buffer.size = BITSTREAM_BUFFER_SIZE; + + out_buffer.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_UNCACHED; + + ret = nv->nvEncCreateBitstreamBuffer(ctx->nvenc_ctx, &out_buffer); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "CreateBitstreamBuffer failed"); + + ctx->frames[idx].out = out_buffer.bitstreamBuffer; + + return 0; +} + +static int nvenc_setup_surfaces(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + int i, ret; + + ctx->nb_surfaces = FFMAX(4 + avctx->max_b_frames, + ctx->nb_surfaces); + ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); + + + ctx->frames = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->frames)); + if (!ctx->frames) + return AVERROR(ENOMEM); + + ctx->timestamps = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t)); + if (!ctx->timestamps) + return AVERROR(ENOMEM); + ctx->pending = av_fifo_alloc(ctx->nb_surfaces * sizeof(*ctx->frames)); + if (!ctx->pending) + return AVERROR(ENOMEM); + ctx->ready = av_fifo_alloc(ctx->nb_surfaces * sizeof(*ctx->frames)); + if (!ctx->ready) + return AVERROR(ENOMEM); + + for (i = 0; i < ctx->nb_surfaces; i++) { + if ((ret = nvenc_alloc_surface(avctx, i)) < 0) + return ret; + } + + return 0; +} + +#define EXTRADATA_SIZE 512 + +static int nvenc_setup_extradata(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 }; + int ret; + + avctx->extradata = av_mallocz(EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + + payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER; + payload.spsppsBuffer = avctx->extradata; + payload.inBufferSize = EXTRADATA_SIZE; + payload.outSPSPPSPayloadSize = &avctx->extradata_size; + + ret = nv->nvEncGetSequenceParams(ctx->nvenc_ctx, &payload); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "Cannot get the extradata"); + + return 0; +} + +av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int i; + + /* the encoder has to be flushed before it can be closed */ + if (ctx->nvenc_ctx) { + NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER, + .encodePicFlags = NV_ENC_PIC_FLAG_EOS }; + + nv->nvEncEncodePicture(ctx->nvenc_ctx, ¶ms); + } + + av_fifo_free(ctx->timestamps); + av_fifo_free(ctx->pending); + av_fifo_free(ctx->ready); + + if (ctx->frames) { + for (i = 0; i < ctx->nb_surfaces; ++i) { + if (avctx->pix_fmt != AV_PIX_FMT_CUDA) { + nv->nvEncDestroyInputBuffer(ctx->nvenc_ctx, ctx->frames[i].in); + } else if (ctx->frames[i].in) { + nv->nvEncUnmapInputResource(ctx->nvenc_ctx, ctx->frames[i].in_map.mappedResource); + } + + av_frame_free(&ctx->frames[i].in_ref); + nv->nvEncDestroyBitstreamBuffer(ctx->nvenc_ctx, ctx->frames[i].out); + } + } + for (i = 0; i < ctx->nb_registered_frames; i++) { + if (ctx->registered_frames[i].regptr) + nv->nvEncUnregisterResource(ctx->nvenc_ctx, ctx->registered_frames[i].regptr); + } + ctx->nb_registered_frames = 0; + + av_freep(&ctx->frames); + + if (ctx->nvenc_ctx) + nv->nvEncDestroyEncoder(ctx->nvenc_ctx); + + if (ctx->cu_context_internal) + ctx->nvel.cu_ctx_destroy(ctx->cu_context_internal); + + if (ctx->nvel.nvenc) + dlclose(ctx->nvel.nvenc); + +#if !CONFIG_CUDA + if (ctx->nvel.cuda) + dlclose(ctx->nvel.cuda); +#endif + + return 0; +} + +av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + int ret; + + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + AVHWFramesContext *frames_ctx; + if (!avctx->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, + "hw_frames_ctx must be set when using GPU frames as input\n"); + return AVERROR(EINVAL); + } + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + ctx->data_pix_fmt = frames_ctx->sw_format; + } else { + ctx->data_pix_fmt = avctx->pix_fmt; + } + + if ((ret = nvenc_load_libraries(avctx)) < 0) + return ret; + + if ((ret = nvenc_setup_device(avctx)) < 0) + return ret; + + if ((ret = nvenc_setup_encoder(avctx)) < 0) + return ret; + + if ((ret = nvenc_setup_surfaces(avctx)) < 0) + return ret; + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + if ((ret = nvenc_setup_extradata(avctx)) < 0) + return ret; + } + + return 0; +} + +static NVENCFrame *get_free_frame(NVENCContext *ctx) +{ + int i; + + for (i = 0; i < ctx->nb_surfaces; i++) { + if (!ctx->frames[i].locked) { + ctx->frames[i].locked = 1; + return &ctx->frames[i]; + } + } + + return NULL; +} + +static int nvenc_copy_frame(NV_ENC_LOCK_INPUT_BUFFER *in, const AVFrame *frame) +{ + uint8_t *buf = in->bufferDataPtr; + int off = frame->height * in->pitch; + + switch (frame->format) { + case AV_PIX_FMT_YUV420P: + av_image_copy_plane(buf, in->pitch, + frame->data[0], frame->linesize[0], + frame->width, frame->height); + buf += off; + + av_image_copy_plane(buf, in->pitch >> 1, + frame->data[2], frame->linesize[2], + frame->width >> 1, frame->height >> 1); + + buf += off >> 2; + + av_image_copy_plane(buf, in->pitch >> 1, + frame->data[1], frame->linesize[1], + frame->width >> 1, frame->height >> 1); + break; + case AV_PIX_FMT_NV12: + av_image_copy_plane(buf, in->pitch, + frame->data[0], frame->linesize[0], + frame->width, frame->height); + buf += off; + + av_image_copy_plane(buf, in->pitch, + frame->data[1], frame->linesize[1], + frame->width, frame->height >> 1); + break; + case AV_PIX_FMT_YUV444P: + av_image_copy_plane(buf, in->pitch, + frame->data[0], frame->linesize[0], + frame->width, frame->height); + buf += off; + + av_image_copy_plane(buf, in->pitch, + frame->data[1], frame->linesize[1], + frame->width, frame->height); + buf += off; + + av_image_copy_plane(buf, in->pitch, + frame->data[2], frame->linesize[2], + frame->width, frame->height); + break; + default: + return AVERROR_BUG; + } + + return 0; +} + +static int nvenc_find_free_reg_resource(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int i; + + if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) { + for (i = 0; i < ctx->nb_registered_frames; i++) { + if (!ctx->registered_frames[i].mapped) { + if (ctx->registered_frames[i].regptr) { + nv->nvEncUnregisterResource(ctx->nvenc_ctx, + ctx->registered_frames[i].regptr); + ctx->registered_frames[i].regptr = NULL; + } + return i; + } + } + } else { + return ctx->nb_registered_frames++; + } + + av_log(avctx, AV_LOG_ERROR, "Too many registered CUDA frames\n"); + return AVERROR(ENOMEM); +} + +static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + NV_ENC_REGISTER_RESOURCE reg; + int i, idx, ret; + + for (i = 0; i < ctx->nb_registered_frames; i++) { + if (ctx->registered_frames[i].ptr == (CUdeviceptr)frame->data[0]) + return i; + } + + idx = nvenc_find_free_reg_resource(avctx); + if (idx < 0) + return idx; + + reg.version = NV_ENC_REGISTER_RESOURCE_VER; + reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; + reg.width = frames_ctx->width; + reg.height = frames_ctx->height; + reg.bufferFormat = ctx->frames[0].format; + reg.pitch = frame->linesize[0]; + reg.resourceToRegister = frame->data[0]; + + ret = nv->nvEncRegisterResource(ctx->nvenc_ctx, ®); + if (ret != NV_ENC_SUCCESS) { + nvenc_print_error(avctx, ret, "Error registering an input resource"); + return AVERROR_UNKNOWN; + } + + ctx->registered_frames[idx].ptr = (CUdeviceptr)frame->data[0]; + ctx->registered_frames[idx].regptr = reg.registeredResource; + return idx; +} + +static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, + NVENCFrame *nvenc_frame) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + int ret; + + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + int reg_idx; + + ret = nvenc_register_frame(avctx, frame); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not register an input CUDA frame\n"); + return ret; + } + reg_idx = ret; + + ret = av_frame_ref(nvenc_frame->in_ref, frame); + if (ret < 0) + return ret; + + nvenc_frame->in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER; + nvenc_frame->in_map.registeredResource = ctx->registered_frames[reg_idx].regptr; + + ret = nv->nvEncMapInputResource(ctx->nvenc_ctx, &nvenc_frame->in_map); + if (ret != NV_ENC_SUCCESS) { + av_frame_unref(nvenc_frame->in_ref); + return nvenc_print_error(avctx, ret, "Error mapping an input resource"); + } + + ctx->registered_frames[reg_idx].mapped = 1; + nvenc_frame->reg_idx = reg_idx; + nvenc_frame->in = nvenc_frame->in_map.mappedResource; + } else { + NV_ENC_LOCK_INPUT_BUFFER params = { 0 }; + + params.version = NV_ENC_LOCK_INPUT_BUFFER_VER; + params.inputBuffer = nvenc_frame->in; + + ret = nv->nvEncLockInputBuffer(ctx->nvenc_ctx, ¶ms); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "Cannot lock the buffer"); + + ret = nvenc_copy_frame(¶ms, frame); + if (ret < 0) { + nv->nvEncUnlockInputBuffer(ctx->nvenc_ctx, nvenc_frame->in); + return ret; + } + + ret = nv->nvEncUnlockInputBuffer(ctx->nvenc_ctx, nvenc_frame->in); + if (ret != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, ret, "Cannot unlock the buffer"); + } + + return 0; +} + +static void nvenc_codec_specific_pic_params(AVCodecContext *avctx, + NV_ENC_PIC_PARAMS *params) +{ + NVENCContext *ctx = avctx->priv_data; + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + params->codecPicParams.h264PicParams.sliceMode = + ctx->config.encodeCodecConfig.h264Config.sliceMode; + params->codecPicParams.h264PicParams.sliceModeData = + ctx->config.encodeCodecConfig.h264Config.sliceModeData; + break; + case AV_CODEC_ID_HEVC: + params->codecPicParams.hevcPicParams.sliceMode = + ctx->config.encodeCodecConfig.hevcConfig.sliceMode; + params->codecPicParams.hevcPicParams.sliceModeData = + ctx->config.encodeCodecConfig.hevcConfig.sliceModeData; + break; + } +} + +static inline int nvenc_enqueue_timestamp(AVFifoBuffer *f, int64_t pts) +{ + return av_fifo_generic_write(f, &pts, sizeof(pts), NULL); +} + +static inline int nvenc_dequeue_timestamp(AVFifoBuffer *f, int64_t *pts) +{ + return av_fifo_generic_read(f, pts, sizeof(*pts), NULL); +} + +static int nvenc_set_timestamp(AVCodecContext *avctx, + NV_ENC_LOCK_BITSTREAM *params, + AVPacket *pkt) +{ + NVENCContext *ctx = avctx->priv_data; + + pkt->pts = params->outputTimeStamp; + pkt->duration = params->outputDuration; + + /* generate the first dts by linearly extrapolating the + * first two pts values to the past */ + if (avctx->max_b_frames > 0 && !ctx->first_packet_output && + ctx->initial_pts[1] != AV_NOPTS_VALUE) { + int64_t ts0 = ctx->initial_pts[0], ts1 = ctx->initial_pts[1]; + int64_t delta; + + if ((ts0 < 0 && ts1 > INT64_MAX + ts0) || + (ts0 > 0 && ts1 < INT64_MIN + ts0)) + return AVERROR(ERANGE); + delta = ts1 - ts0; + + if ((delta < 0 && ts0 > INT64_MAX + delta) || + (delta > 0 && ts0 < INT64_MIN + delta)) + return AVERROR(ERANGE); + pkt->dts = ts0 - delta; + + ctx->first_packet_output = 1; + return 0; + } + return nvenc_dequeue_timestamp(ctx->timestamps, &pkt->dts); +} + +static int nvenc_get_output(AVCodecContext *avctx, AVPacket *pkt) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NV_ENC_LOCK_BITSTREAM params = { 0 }; + NVENCFrame *frame; + int ret; + + ret = av_fifo_generic_read(ctx->ready, &frame, sizeof(frame), NULL); + if (ret) + return ret; + + params.version = NV_ENC_LOCK_BITSTREAM_VER; + params.outputBitstream = frame->out; + + ret = nv->nvEncLockBitstream(ctx->nvenc_ctx, ¶ms); + if (ret < 0) + return nvenc_print_error(avctx, ret, "Cannot lock the bitstream"); + + ret = ff_alloc_packet(pkt, params.bitstreamSizeInBytes); + if (ret < 0) + return ret; + + memcpy(pkt->data, params.bitstreamBufferPtr, pkt->size); + + ret = nv->nvEncUnlockBitstream(ctx->nvenc_ctx, frame->out); + if (ret < 0) + return nvenc_print_error(avctx, ret, "Cannot unlock the bitstream"); + + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + nv->nvEncUnmapInputResource(ctx->nvenc_ctx, frame->in_map.mappedResource); + av_frame_unref(frame->in_ref); + ctx->registered_frames[frame->reg_idx].mapped = 0; + + frame->in = NULL; + } + + frame->locked = 0; + + ret = nvenc_set_timestamp(avctx, ¶ms, pkt); + if (ret < 0) + return ret; + + switch (params.pictureType) { + case NV_ENC_PIC_TYPE_IDR: + pkt->flags |= AV_PKT_FLAG_KEY; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + case NV_ENC_PIC_TYPE_INTRA_REFRESH: + case NV_ENC_PIC_TYPE_I: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + break; + case NV_ENC_PIC_TYPE_P: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; + break; + case NV_ENC_PIC_TYPE_B: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; + break; + case NV_ENC_PIC_TYPE_BI: + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_BI; + break; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } + + return 0; +} + +static int output_ready(AVCodecContext *avctx, int flush) +{ + NVENCContext *ctx = avctx->priv_data; + int nb_ready, nb_pending; + + /* when B-frames are enabled, we wait for two initial timestamps to + * calculate the first dts */ + if (!flush && avctx->max_b_frames > 0 && + (ctx->initial_pts[0] == AV_NOPTS_VALUE || ctx->initial_pts[1] == AV_NOPTS_VALUE)) + return 0; + + nb_ready = av_fifo_size(ctx->ready) / sizeof(NVENCFrame*); + nb_pending = av_fifo_size(ctx->pending) / sizeof(NVENCFrame*); + if (flush) + return nb_ready > 0; + return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth); +} + +int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + NVENCContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NV_ENC_PIC_PARAMS params = { 0 }; + NVENCFrame *nvenc_frame = NULL; + int enc_ret, ret; + + params.version = NV_ENC_PIC_PARAMS_VER; + + if (frame) { + nvenc_frame = get_free_frame(ctx); + if (!nvenc_frame) { + av_log(avctx, AV_LOG_ERROR, "No free surfaces\n"); + return AVERROR_BUG; + } + + ret = nvenc_upload_frame(avctx, frame, nvenc_frame); + if (ret < 0) + return ret; + + params.inputBuffer = nvenc_frame->in; + params.bufferFmt = nvenc_frame->format; + params.inputWidth = frame->width; + params.inputHeight = frame->height; + params.outputBitstream = nvenc_frame->out; + params.inputTimeStamp = frame->pts; + + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + if (frame->top_field_first) + params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM; + else + params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP; + } else { + params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME; + } + + nvenc_codec_specific_pic_params(avctx, ¶ms); + + ret = nvenc_enqueue_timestamp(ctx->timestamps, frame->pts); + if (ret < 0) + return ret; + + if (ctx->initial_pts[0] == AV_NOPTS_VALUE) + ctx->initial_pts[0] = frame->pts; + else if (ctx->initial_pts[1] == AV_NOPTS_VALUE) + ctx->initial_pts[1] = frame->pts; + } else { + params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; + } + + enc_ret = nv->nvEncEncodePicture(ctx->nvenc_ctx, ¶ms); + if (enc_ret != NV_ENC_SUCCESS && + enc_ret != NV_ENC_ERR_NEED_MORE_INPUT) + return nvenc_print_error(avctx, enc_ret, "Error encoding the frame"); + + if (nvenc_frame) { + ret = av_fifo_generic_write(ctx->pending, &nvenc_frame, sizeof(nvenc_frame), NULL); + if (ret < 0) + return ret; + } + + /* all the pending buffers are now ready for output */ + if (enc_ret == NV_ENC_SUCCESS) { + while (av_fifo_size(ctx->pending) > 0) { + av_fifo_generic_read(ctx->pending, &nvenc_frame, sizeof(nvenc_frame), NULL); + av_fifo_generic_write(ctx->ready, &nvenc_frame, sizeof(nvenc_frame), NULL); + } + } + + if (output_ready(avctx, !frame)) { + ret = nvenc_get_output(avctx, pkt); + if (ret < 0) + return ret; + *got_packet = 1; + } else { + *got_packet = 0; + } + + return 0; +} diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h new file mode 100644 index 0000000..e7e6182 --- /dev/null +++ b/libavcodec/nvenc.h @@ -0,0 +1,174 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_NVENC_H +#define AVCODEC_NVENC_H + +#include + +#include "config.h" + +#include "libavutil/fifo.h" +#include "libavutil/opt.h" + +#include "avcodec.h" + +#if CONFIG_CUDA +#include +#else + +#if defined(_WIN32) +#define CUDAAPI __stdcall +#else +#define CUDAAPI +#endif + +typedef enum cudaError_enum { + CUDA_SUCCESS = 0 +} CUresult; +typedef int CUdevice; +typedef void* CUcontext; +typedef void* CUdeviceptr; +#endif + +#define MAX_REGISTERED_FRAMES 64 + +typedef struct NVENCFrame { + NV_ENC_INPUT_PTR in; + AVFrame *in_ref; + NV_ENC_MAP_INPUT_RESOURCE in_map; + int reg_idx; + + NV_ENC_OUTPUT_PTR out; + NV_ENC_BUFFER_FORMAT format; + int locked; +} NVENCFrame; + +typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags); +typedef CUresult(CUDAAPI *PCUDEVICEGETCOUNT)(int *count); +typedef CUresult(CUDAAPI *PCUDEVICEGET)(CUdevice *device, int ordinal); +typedef CUresult(CUDAAPI *PCUDEVICEGETNAME)(char *name, int len, CUdevice dev); +typedef CUresult(CUDAAPI *PCUDEVICECOMPUTECAPABILITY)(int *major, int *minor, CUdevice dev); +typedef CUresult(CUDAAPI *PCUCTXCREATE)(CUcontext *pctx, unsigned int flags, CUdevice dev); +typedef CUresult(CUDAAPI *PCUCTXPOPCURRENT)(CUcontext *pctx); +typedef CUresult(CUDAAPI *PCUCTXDESTROY)(CUcontext ctx); + +typedef NVENCSTATUS (NVENCAPI *PNVENCODEAPICREATEINSTANCE)(NV_ENCODE_API_FUNCTION_LIST *functionList); + +typedef struct NVENCLibraryContext +{ +#if !CONFIG_CUDA + void *cuda; +#endif + void *nvenc; + + PCUINIT cu_init; + PCUDEVICEGETCOUNT cu_device_get_count; + PCUDEVICEGET cu_device_get; + PCUDEVICEGETNAME cu_device_get_name; + PCUDEVICECOMPUTECAPABILITY cu_device_compute_capability; + PCUCTXCREATE cu_ctx_create; + PCUCTXPOPCURRENT cu_ctx_pop_current; + PCUCTXDESTROY cu_ctx_destroy; + + NV_ENCODE_API_FUNCTION_LIST nvenc_funcs; +} NVENCLibraryContext; + +enum { + PRESET_DEFAULT, + PRESET_HP, + PRESET_HQ, + PRESET_BD , + PRESET_LOW_LATENCY_DEFAULT , + PRESET_LOW_LATENCY_HQ , + PRESET_LOW_LATENCY_HP, + PRESET_LOSSLESS_DEFAULT, + PRESET_LOSSLESS_HP, +}; + +enum { + NV_ENC_H264_PROFILE_BASELINE, + NV_ENC_H264_PROFILE_MAIN, + NV_ENC_H264_PROFILE_HIGH, + NV_ENC_H264_PROFILE_HIGH_444, + NV_ENC_H264_PROFILE_CONSTRAINED_HIGH, +}; + +enum { + NVENC_LOWLATENCY = 1, + NVENC_LOSSLESS, +}; + +enum { + LIST_DEVICES = -2, + ANY_DEVICE, +}; + +typedef struct NVENCContext { + AVClass *class; + NVENCLibraryContext nvel; + + NV_ENC_INITIALIZE_PARAMS params; + NV_ENC_CONFIG config; + + CUcontext cu_context; + CUcontext cu_context_internal; + + int nb_surfaces; + NVENCFrame *frames; + AVFifoBuffer *timestamps; + AVFifoBuffer *pending, *ready; + + struct { + CUdeviceptr ptr; + NV_ENC_REGISTERED_PTR regptr; + int mapped; + } registered_frames[MAX_REGISTERED_FRAMES]; + int nb_registered_frames; + + /* the actual data pixel format, different from + * AVCodecContext.pix_fmt when using hwaccel frames on input */ + enum AVPixelFormat data_pix_fmt; + + /* timestamps of the first two frames, for computing the first dts + * when B-frames are present */ + int64_t initial_pts[2]; + int first_packet_output; + + void *nvenc_ctx; + + int preset; + int profile; + int level; + int tier; + int rc; + int device; + int flags; + int async_depth; +} NVENCContext; + +int ff_nvenc_encode_init(AVCodecContext *avctx); + +int ff_nvenc_encode_close(AVCodecContext *avctx); + +int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet); + +extern const enum AVPixelFormat ff_nvenc_pix_fmts[]; + +#endif /* AVCODEC_NVENC_H */ diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c new file mode 100644 index 0000000..ea91e07 --- /dev/null +++ b/libavcodec/nvenc_h264.c @@ -0,0 +1,143 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" + +#include "nvenc.h" + +#define OFFSET(x) offsetof(NVENCContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_HQ }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" }, + { "default", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" }, + { "hp", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_HP }, 0, 0, VE, "preset" }, + { "hq", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_HQ }, 0, 0, VE, "preset" }, + { "bd", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_BD }, 0, 0, VE, "preset" }, + { "ll", "low latency", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" }, + { "llhq", "low latency hq", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" }, + { "llhp", "low latency hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" }, + { "lossless", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" }, + { "losslesshp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" }, + { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_H264_PROFILE_HIGH }, NV_ENC_H264_PROFILE_BASELINE, NV_ENC_H264_PROFILE_CONSTRAINED_HIGH, VE, "profile" }, + { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, "profile" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH }, 0, 0, VE, "profile" }, + { "high_444", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444 }, 0, 0, VE, "profile" }, + { "constrained_high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" }, + { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_51, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1 }, 0, 0, VE, "level" }, + { "1.b", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1b }, 0, 0, VE, "level" }, + { "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_11 }, 0, 0, VE, "level" }, + { "1.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_12 }, 0, 0, VE, "level" }, + { "1.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_13 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_2 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_21 }, 0, 0, VE, "level" }, + { "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_22 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_3 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_31 }, 0, 0, VE, "level" }, + { "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_32 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_4 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_41 }, 0, 0, VE, "level" }, + { "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_42 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_5 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_51 }, 0, 0, VE, "level" }, + { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" }, + { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, + { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, + { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, + { "vbr_minqp", "Variable bitrate mode with MinQP", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR_MINQP }, 0, 0, VE, "rc" }, + { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY }, 0, 0, VE, "rc" }, + { "ll_2pass_size", "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" }, + { "vbr_2pass", "Multi-pass variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR }, 0, 0, VE, "rc" }, + { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, VE }, + { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, + { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, + { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, + { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { NULL } +}; + +static const AVClass nvenc_h264_class = { + .class_name = "nvenc_h264", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "qdiff", "-1" }, + { "qblur", "-1" }, + { "qcomp", "-1" }, + { NULL }, +}; + +AVCodec ff_h264_nvenc_encoder = { + .name = "h264_nvenc", + .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = ff_nvenc_encode_init, + .encode2 = ff_nvenc_encode_frame, + .close = ff_nvenc_encode_close, + .priv_data_size = sizeof(NVENCContext), + .priv_class = &nvenc_h264_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_nvenc_pix_fmts, +}; + +#if FF_API_NVENC_OLD_NAME + +static int nvenc_old_init(AVCodecContext *avctx) +{ + av_log(avctx, AV_LOG_WARNING, "This encoder is deprecated, use 'h264_nvenc' instead\n"); + return ff_nvenc_encode_init(avctx); +} + +static const AVClass nvenc_h264_old_class = { + .class_name = "nvenc_h264", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_nvenc_h264_encoder = { + .name = "nvenc_h264", + .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = nvenc_old_init, + .encode2 = ff_nvenc_encode_frame, + .close = ff_nvenc_encode_close, + .priv_data_size = sizeof(NVENCContext), + .priv_class = &nvenc_h264_old_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_nvenc_pix_fmts, +}; +#endif diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c new file mode 100644 index 0000000..6ff3506 --- /dev/null +++ b/libavcodec/nvenc_hevc.c @@ -0,0 +1,139 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" + +#include "nvenc.h" + +#define OFFSET(x) offsetof(NVENCContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_HQ }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" }, + { "default", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" }, + { "hp", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_HP }, 0, 0, VE, "preset" }, + { "hq", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_HQ }, 0, 0, VE, "preset" }, + { "bd", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_BD }, 0, 0, VE, "preset" }, + { "ll", "low latency", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" }, + { "llhq", "low latency hq", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" }, + { "llhp", "low latency hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" }, + { "lossless", "lossless", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" }, + { "losslesshp", "lossless hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" }, + { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_HEVC_MAIN }, FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_MAIN, VE, "profile" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN }, 0, 0, VE, "profile" }, + { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_HEVC_62, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_1 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_2 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_21 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_3 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_31 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_4 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_41 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_5 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_51 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_52 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_6 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_61 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_62 }, 0, 0, VE, "level" }, + { "tier", "Set the encoding tier", OFFSET(tier), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TIER_HEVC_MAIN }, NV_ENC_TIER_HEVC_MAIN, NV_ENC_TIER_HEVC_HIGH, VE, "tier"}, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_HEVC_MAIN }, 0, 0, VE, "tier" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_HEVC_HIGH }, 0, 0, VE, "tier" }, + { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" }, + { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, + { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, + { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, + { "vbr_minqp", "Variable bitrate mode with MinQP", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR_MINQP }, 0, 0, VE, "rc" }, + { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY }, 0, 0, VE, "rc" }, + { "ll_2pass_size", "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" }, + { "vbr_2pass", "Multi-pass variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR }, 0, 0, VE, "rc" }, + { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, VE }, + { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, + { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, + { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, + { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { NULL } +}; + +static const AVClass nvenc_hevc_class = { + .class_name = "nvenc_hevc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "qdiff", "-1" }, + { "qblur", "-1" }, + { "qcomp", "-1" }, + { NULL }, +}; + +AVCodec ff_hevc_nvenc_encoder = { + .name = "hevc_nvenc", + .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC HEVC encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = ff_nvenc_encode_init, + .encode2 = ff_nvenc_encode_frame, + .close = ff_nvenc_encode_close, + .priv_data_size = sizeof(NVENCContext), + .priv_class = &nvenc_hevc_class, + .defaults = defaults, + .pix_fmts = ff_nvenc_pix_fmts, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; + +#if FF_API_NVENC_OLD_NAME + +static int nvenc_old_init(AVCodecContext *avctx) +{ + av_log(avctx, AV_LOG_WARNING, "This encoder is deprecated, use 'hevc_nvenc' instead\n"); + return ff_nvenc_encode_init(avctx); +} + +static const AVClass nvenc_hevc_old_class = { + .class_name = "nvenc_hevc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_nvenc_hevc_encoder = { + .name = "nvenc_hevc", + .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC HEVC encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = nvenc_old_init, + .encode2 = ff_nvenc_encode_frame, + .close = ff_nvenc_encode_close, + .priv_data_size = sizeof(NVENCContext), + .priv_class = &nvenc_hevc_old_class, + .defaults = defaults, + .pix_fmts = ff_nvenc_pix_fmts, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; +#endif diff --git a/libavcodec/omx.c b/libavcodec/omx.c new file mode 100644 index 0000000..0c61c2f --- /dev/null +++ b/libavcodec/omx.c @@ -0,0 +1,931 @@ +/* + * OMX Video encoder + * Copyright (C) 2011 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#if CONFIG_OMX_RPI +#define OMX_SKIP64BIT +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "h264.h" +#include "internal.h" + +#ifdef OMX_SKIP64BIT +static OMX_TICKS to_omx_ticks(int64_t value) +{ + OMX_TICKS s; + s.nLowPart = value & 0xffffffff; + s.nHighPart = value >> 32; + return s; +} +static int64_t from_omx_ticks(OMX_TICKS value) +{ + return (((int64_t)value.nHighPart) << 32) | value.nLowPart; +} +#else +#define to_omx_ticks(x) (x) +#define from_omx_ticks(x) (x) +#endif + +#define INIT_STRUCT(x) do { \ + x.nSize = sizeof(x); \ + x.nVersion = s->version; \ + } while (0) +#define CHECK(x) do { \ + if (x != OMX_ErrorNone) { \ + av_log(avctx, AV_LOG_ERROR, \ + "err %x (%d) on line %d\n", x, x, __LINE__); \ + return AVERROR_UNKNOWN; \ + } \ + } while (0) + +typedef struct OMXContext { + void *lib; + void *lib2; + OMX_ERRORTYPE (*ptr_Init)(void); + OMX_ERRORTYPE (*ptr_Deinit)(void); + OMX_ERRORTYPE (*ptr_ComponentNameEnum)(OMX_STRING, OMX_U32, OMX_U32); + OMX_ERRORTYPE (*ptr_GetHandle)(OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*); + OMX_ERRORTYPE (*ptr_FreeHandle)(OMX_HANDLETYPE); + OMX_ERRORTYPE (*ptr_GetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); + OMX_ERRORTYPE (*ptr_GetRolesOfComponent)(OMX_STRING, OMX_U32*, OMX_U8**); + void (*host_init)(void); +} OMXContext; + +static av_cold void *dlsym_prefixed(void *handle, const char *symbol, const char *prefix) +{ + char buf[50]; + snprintf(buf, sizeof(buf), "%s%s", prefix ? prefix : "", symbol); + return dlsym(handle, buf); +} + +static av_cold int omx_try_load(OMXContext *s, void *logctx, + const char *libname, const char *prefix, + const char *libname2) +{ + if (libname2) { + s->lib2 = dlopen(libname2, RTLD_NOW | RTLD_GLOBAL); + if (!s->lib2) { + av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname); + return AVERROR_ENCODER_NOT_FOUND; + } + s->host_init = dlsym(s->lib2, "bcm_host_init"); + if (!s->host_init) { + av_log(logctx, AV_LOG_WARNING, "bcm_host_init not found\n"); + dlclose(s->lib2); + s->lib2 = NULL; + return AVERROR_ENCODER_NOT_FOUND; + } + } + s->lib = dlopen(libname, RTLD_NOW | RTLD_GLOBAL); + if (!s->lib) { + av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname); + return AVERROR_ENCODER_NOT_FOUND; + } + s->ptr_Init = dlsym_prefixed(s->lib, "OMX_Init", prefix); + s->ptr_Deinit = dlsym_prefixed(s->lib, "OMX_Deinit", prefix); + s->ptr_ComponentNameEnum = dlsym_prefixed(s->lib, "OMX_ComponentNameEnum", prefix); + s->ptr_GetHandle = dlsym_prefixed(s->lib, "OMX_GetHandle", prefix); + s->ptr_FreeHandle = dlsym_prefixed(s->lib, "OMX_FreeHandle", prefix); + s->ptr_GetComponentsOfRole = dlsym_prefixed(s->lib, "OMX_GetComponentsOfRole", prefix); + s->ptr_GetRolesOfComponent = dlsym_prefixed(s->lib, "OMX_GetRolesOfComponent", prefix); + if (!s->ptr_Init || !s->ptr_Deinit || !s->ptr_ComponentNameEnum || + !s->ptr_GetHandle || !s->ptr_FreeHandle || + !s->ptr_GetComponentsOfRole || !s->ptr_GetRolesOfComponent) { + av_log(logctx, AV_LOG_WARNING, "Not all functions found in %s\n", libname); + dlclose(s->lib); + s->lib = NULL; + if (s->lib2) + dlclose(s->lib2); + s->lib2 = NULL; + return AVERROR_ENCODER_NOT_FOUND; + } + return 0; +} + +static av_cold OMXContext *omx_init(void *logctx, const char *libname, const char *prefix) +{ + static const char * const libnames[] = { +#if CONFIG_OMX_RPI + "/opt/vc/lib/libopenmaxil.so", "/opt/vc/lib/libbcm_host.so", +#else + "libOMX_Core.so", NULL, + "libOmxCore.so", NULL, +#endif + NULL + }; + const char* const* nameptr; + int ret = AVERROR_ENCODER_NOT_FOUND; + OMXContext *omx_context; + + omx_context = av_mallocz(sizeof(*omx_context)); + if (!omx_context) + return NULL; + if (libname) { + ret = omx_try_load(omx_context, logctx, libname, prefix, NULL); + if (ret < 0) { + av_free(omx_context); + return NULL; + } + } else { + for (nameptr = libnames; *nameptr; nameptr += 2) + if (!(ret = omx_try_load(omx_context, logctx, nameptr[0], prefix, nameptr[1]))) + break; + if (!*nameptr) { + av_free(omx_context); + return NULL; + } + } + + if (omx_context->host_init) + omx_context->host_init(); + omx_context->ptr_Init(); + return omx_context; +} + +static av_cold void omx_deinit(OMXContext *omx_context) +{ + if (!omx_context) + return; + omx_context->ptr_Deinit(); + dlclose(omx_context->lib); + av_free(omx_context); +} + +typedef struct OMXCodecContext { + const AVClass *class; + char *libname; + char *libprefix; + OMXContext *omx_context; + + AVCodecContext *avctx; + + char component_name[OMX_MAX_STRINGNAME_SIZE]; + OMX_VERSIONTYPE version; + OMX_HANDLETYPE handle; + int in_port, out_port; + OMX_COLOR_FORMATTYPE color_format; + int stride, plane_size; + + int num_in_buffers, num_out_buffers; + OMX_BUFFERHEADERTYPE **in_buffer_headers; + OMX_BUFFERHEADERTYPE **out_buffer_headers; + int num_free_in_buffers; + OMX_BUFFERHEADERTYPE **free_in_buffers; + int num_done_out_buffers; + OMX_BUFFERHEADERTYPE **done_out_buffers; + pthread_mutex_t input_mutex; + pthread_cond_t input_cond; + pthread_mutex_t output_mutex; + pthread_cond_t output_cond; + + pthread_mutex_t state_mutex; + pthread_cond_t state_cond; + OMX_STATETYPE state; + OMX_ERRORTYPE error; + + int mutex_cond_inited; + + int num_in_frames, num_out_frames; + + uint8_t *output_buf; + int output_buf_size; + + int input_zerocopy; +} OMXCodecContext; + +static void append_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond, + int* array_size, OMX_BUFFERHEADERTYPE **array, + OMX_BUFFERHEADERTYPE *buffer) +{ + pthread_mutex_lock(mutex); + array[(*array_size)++] = buffer; + pthread_cond_broadcast(cond); + pthread_mutex_unlock(mutex); +} + +static OMX_BUFFERHEADERTYPE *get_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond, + int* array_size, OMX_BUFFERHEADERTYPE **array, + int wait) +{ + OMX_BUFFERHEADERTYPE *buffer; + pthread_mutex_lock(mutex); + if (wait) { + while (!*array_size) + pthread_cond_wait(cond, mutex); + } + if (*array_size > 0) { + buffer = array[0]; + (*array_size)--; + memmove(&array[0], &array[1], (*array_size) * sizeof(OMX_BUFFERHEADERTYPE*)); + } else { + buffer = NULL; + } + pthread_mutex_unlock(mutex); + return buffer; +} + +static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, OMX_EVENTTYPE event, + OMX_U32 data1, OMX_U32 data2, OMX_PTR event_data) +{ + OMXCodecContext *s = app_data; + // This uses casts in the printfs, since OMX_U32 actually is a typedef for + // unsigned long in official header versions (but there are also modified + // versions where it is something else). + switch (event) { + case OMX_EventError: + pthread_mutex_lock(&s->state_mutex); + av_log(s->avctx, AV_LOG_ERROR, "OMX error %"PRIx32"\n", (uint32_t) data1); + s->error = data1; + pthread_cond_broadcast(&s->state_cond); + pthread_mutex_unlock(&s->state_mutex); + break; + case OMX_EventCmdComplete: + if (data1 == OMX_CommandStateSet) { + pthread_mutex_lock(&s->state_mutex); + s->state = data2; + av_log(s->avctx, AV_LOG_VERBOSE, "OMX state changed to %"PRIu32"\n", (uint32_t) data2); + pthread_cond_broadcast(&s->state_cond); + pthread_mutex_unlock(&s->state_mutex); + } else if (data1 == OMX_CommandPortDisable) { + av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" disabled\n", (uint32_t) data2); + } else if (data1 == OMX_CommandPortEnable) { + av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" enabled\n", (uint32_t) data2); + } else { + av_log(s->avctx, AV_LOG_VERBOSE, "OMX command complete, command %"PRIu32", value %"PRIu32"\n", + (uint32_t) data1, (uint32_t) data2); + } + break; + case OMX_EventPortSettingsChanged: + av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" settings changed\n", (uint32_t) data1); + break; + default: + av_log(s->avctx, AV_LOG_VERBOSE, "OMX event %d %"PRIx32" %"PRIx32"\n", + event, (uint32_t) data1, (uint32_t) data2); + break; + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_data, + OMX_BUFFERHEADERTYPE *buffer) +{ + OMXCodecContext *s = app_data; + if (s->input_zerocopy) { + if (buffer->pAppPrivate) { + if (buffer->pOutputPortPrivate) + av_free(buffer->pAppPrivate); + else + av_frame_free((AVFrame**)&buffer->pAppPrivate); + buffer->pAppPrivate = NULL; + } + } + append_buffer(&s->input_mutex, &s->input_cond, + &s->num_free_in_buffers, s->free_in_buffers, buffer); + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_data, + OMX_BUFFERHEADERTYPE *buffer) +{ + OMXCodecContext *s = app_data; + append_buffer(&s->output_mutex, &s->output_cond, + &s->num_done_out_buffers, s->done_out_buffers, buffer); + return OMX_ErrorNone; +} + +static const OMX_CALLBACKTYPE callbacks = { + event_handler, + empty_buffer_done, + fill_buffer_done +}; + +static av_cold int find_component(OMXContext *omx_context, void *logctx, + const char *role, char *str, int str_size) +{ + OMX_U32 i, num = 0; + char **components; + int ret = 0; + +#if CONFIG_OMX_RPI + if (av_strstart(role, "video_encoder.", NULL)) { + av_strlcpy(str, "OMX.broadcom.video_encode", str_size); + return 0; + } +#endif + omx_context->ptr_GetComponentsOfRole((OMX_STRING) role, &num, NULL); + if (!num) { + av_log(logctx, AV_LOG_WARNING, "No component for role %s found\n", role); + return AVERROR_ENCODER_NOT_FOUND; + } + components = av_mallocz(sizeof(char*) * num); + if (!components) + return AVERROR(ENOMEM); + for (i = 0; i < num; i++) { + components[i] = av_mallocz(OMX_MAX_STRINGNAME_SIZE); + if (!components) { + ret = AVERROR(ENOMEM); + goto end; + } + } + omx_context->ptr_GetComponentsOfRole((OMX_STRING) role, &num, (OMX_U8**) components); + av_strlcpy(str, components[0], str_size); +end: + for (i = 0; i < num; i++) + av_free(components[i]); + av_free(components); + return ret; +} + +static av_cold int wait_for_state(OMXCodecContext *s, OMX_STATETYPE state) +{ + int ret = 0; + pthread_mutex_lock(&s->state_mutex); + while (s->state != state && s->error == OMX_ErrorNone) + pthread_cond_wait(&s->state_cond, &s->state_mutex); + if (s->error != OMX_ErrorNone) + ret = AVERROR_ENCODER_NOT_FOUND; + pthread_mutex_unlock(&s->state_mutex); + return ret; +} + +static av_cold int omx_component_init(AVCodecContext *avctx, const char *role) +{ + OMXCodecContext *s = avctx->priv_data; + OMX_PARAM_COMPONENTROLETYPE role_params = { 0 }; + OMX_PORT_PARAM_TYPE video_port_params = { 0 }; + OMX_PARAM_PORTDEFINITIONTYPE in_port_params = { 0 }, out_port_params = { 0 }; + OMX_VIDEO_PARAM_PORTFORMATTYPE video_port_format = { 0 }; + OMX_VIDEO_PARAM_BITRATETYPE vid_param_bitrate = { 0 }; + OMX_ERRORTYPE err; + int i; + + s->version.s.nVersionMajor = 1; + s->version.s.nVersionMinor = 1; + s->version.s.nRevision = 2; + + err = s->omx_context->ptr_GetHandle(&s->handle, s->component_name, s, (OMX_CALLBACKTYPE*) &callbacks); + if (err != OMX_ErrorNone) { + av_log(avctx, AV_LOG_ERROR, "OMX_GetHandle(%s) failed: %x\n", s->component_name, err); + return AVERROR_UNKNOWN; + } + + // This one crashes the mediaserver on qcom, if used over IOMX + INIT_STRUCT(role_params); + av_strlcpy(role_params.cRole, role, sizeof(role_params.cRole)); + // Intentionally ignore errors on this one + OMX_SetParameter(s->handle, OMX_IndexParamStandardComponentRole, &role_params); + + INIT_STRUCT(video_port_params); + err = OMX_GetParameter(s->handle, OMX_IndexParamVideoInit, &video_port_params); + CHECK(err); + + s->in_port = s->out_port = -1; + for (i = 0; i < video_port_params.nPorts; i++) { + int port = video_port_params.nStartPortNumber + i; + OMX_PARAM_PORTDEFINITIONTYPE port_params = { 0 }; + INIT_STRUCT(port_params); + port_params.nPortIndex = port; + err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &port_params); + if (err != OMX_ErrorNone) { + av_log(avctx, AV_LOG_WARNING, "port %d error %x\n", port, err); + break; + } + if (port_params.eDir == OMX_DirInput && s->in_port < 0) { + in_port_params = port_params; + s->in_port = port; + } else if (port_params.eDir == OMX_DirOutput && s->out_port < 0) { + out_port_params = port_params; + s->out_port = port; + } + } + if (s->in_port < 0 || s->out_port < 0) { + av_log(avctx, AV_LOG_ERROR, "No in or out port found (in %d out %d)\n", s->in_port, s->out_port); + return AVERROR_UNKNOWN; + } + + s->color_format = 0; + for (i = 0; ; i++) { + INIT_STRUCT(video_port_format); + video_port_format.nIndex = i; + video_port_format.nPortIndex = s->in_port; + if (OMX_GetParameter(s->handle, OMX_IndexParamVideoPortFormat, &video_port_format) != OMX_ErrorNone) + break; + if (video_port_format.eColorFormat == OMX_COLOR_FormatYUV420Planar || + video_port_format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar) { + s->color_format = video_port_format.eColorFormat; + break; + } + } + if (s->color_format == 0) { + av_log(avctx, AV_LOG_ERROR, "No supported pixel formats (%d formats available)\n", i); + return AVERROR_UNKNOWN; + } + + in_port_params.bEnabled = OMX_TRUE; + in_port_params.bPopulated = OMX_FALSE; + in_port_params.eDomain = OMX_PortDomainVideo; + + in_port_params.format.video.pNativeRender = NULL; + in_port_params.format.video.bFlagErrorConcealment = OMX_FALSE; + in_port_params.format.video.eColorFormat = s->color_format; + s->stride = avctx->width; + s->plane_size = avctx->height; + // If specific codecs need to manually override the stride/plane_size, + // that can be done here. + in_port_params.format.video.nStride = s->stride; + in_port_params.format.video.nSliceHeight = s->plane_size; + in_port_params.format.video.nFrameWidth = avctx->width; + in_port_params.format.video.nFrameHeight = avctx->height; + if (avctx->framerate.den > 0 && avctx->framerate.num > 0) + in_port_params.format.video.xFramerate = (1 << 16) * avctx->framerate.num / avctx->framerate.den; + else + in_port_params.format.video.xFramerate = (1 << 16) * avctx->time_base.den / avctx->time_base.num; + + err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params); + CHECK(err); + err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params); + CHECK(err); + s->stride = in_port_params.format.video.nStride; + s->plane_size = in_port_params.format.video.nSliceHeight; + s->num_in_buffers = in_port_params.nBufferCountActual; + + err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params); + out_port_params.bEnabled = OMX_TRUE; + out_port_params.bPopulated = OMX_FALSE; + out_port_params.eDomain = OMX_PortDomainVideo; + out_port_params.format.video.pNativeRender = NULL; + out_port_params.format.video.nFrameWidth = avctx->width; + out_port_params.format.video.nFrameHeight = avctx->height; + out_port_params.format.video.nStride = 0; + out_port_params.format.video.nSliceHeight = 0; + out_port_params.format.video.nBitrate = avctx->bit_rate; + out_port_params.format.video.xFramerate = in_port_params.format.video.xFramerate; + out_port_params.format.video.bFlagErrorConcealment = OMX_FALSE; + if (avctx->codec->id == AV_CODEC_ID_MPEG4) + out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + else if (avctx->codec->id == AV_CODEC_ID_H264) + out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + + err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params); + CHECK(err); + err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params); + CHECK(err); + s->num_out_buffers = out_port_params.nBufferCountActual; + + INIT_STRUCT(vid_param_bitrate); + vid_param_bitrate.nPortIndex = s->out_port; + vid_param_bitrate.eControlRate = OMX_Video_ControlRateVariable; + vid_param_bitrate.nTargetBitrate = avctx->bit_rate; + err = OMX_SetParameter(s->handle, OMX_IndexParamVideoBitrate, &vid_param_bitrate); + if (err != OMX_ErrorNone) + av_log(avctx, AV_LOG_WARNING, "Unable to set video bitrate parameter\n"); + + if (avctx->codec->id == AV_CODEC_ID_H264) { + OMX_VIDEO_PARAM_AVCTYPE avc = { 0 }; + INIT_STRUCT(avc); + avc.nPortIndex = s->out_port; + err = OMX_GetParameter(s->handle, OMX_IndexParamVideoAvc, &avc); + CHECK(err); + avc.nBFrames = 0; + avc.nPFrames = avctx->gop_size - 1; + err = OMX_SetParameter(s->handle, OMX_IndexParamVideoAvc, &avc); + CHECK(err); + } + + err = OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateIdle, NULL); + CHECK(err); + + s->in_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers); + s->free_in_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers); + s->out_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); + s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); + if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers) + return AVERROR(ENOMEM); + for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) { + if (s->input_zerocopy) + err = OMX_UseBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize, NULL); + else + err = OMX_AllocateBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize); + if (err == OMX_ErrorNone) + s->in_buffer_headers[i]->pAppPrivate = s->in_buffer_headers[i]->pOutputPortPrivate = NULL; + } + CHECK(err); + s->num_in_buffers = i; + for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++) + err = OMX_AllocateBuffer(s->handle, &s->out_buffer_headers[i], s->out_port, s, out_port_params.nBufferSize); + CHECK(err); + s->num_out_buffers = i; + + if (wait_for_state(s, OMX_StateIdle) < 0) { + av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateIdle\n"); + return AVERROR_UNKNOWN; + } + err = OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + CHECK(err); + if (wait_for_state(s, OMX_StateExecuting) < 0) { + av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateExecuting\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++) + err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[i]); + if (err != OMX_ErrorNone) { + for (; i < s->num_out_buffers; i++) + s->done_out_buffers[s->num_done_out_buffers++] = s->out_buffer_headers[i]; + } + for (i = 0; i < s->num_in_buffers; i++) + s->free_in_buffers[s->num_free_in_buffers++] = s->in_buffer_headers[i]; + return err != OMX_ErrorNone ? AVERROR_UNKNOWN : 0; +} + +static av_cold void cleanup(OMXCodecContext *s) +{ + int i, executing; + + pthread_mutex_lock(&s->state_mutex); + executing = s->state == OMX_StateExecuting; + pthread_mutex_unlock(&s->state_mutex); + + if (executing) { + OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateIdle, NULL); + wait_for_state(s, OMX_StateIdle); + OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateLoaded, NULL); + for (i = 0; i < s->num_in_buffers; i++) { + OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond, + &s->num_free_in_buffers, s->free_in_buffers, 1); + if (s->input_zerocopy) + buffer->pBuffer = NULL; + OMX_FreeBuffer(s->handle, s->in_port, buffer); + } + for (i = 0; i < s->num_out_buffers; i++) { + OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->output_mutex, &s->output_cond, + &s->num_done_out_buffers, s->done_out_buffers, 1); + OMX_FreeBuffer(s->handle, s->out_port, buffer); + } + wait_for_state(s, OMX_StateLoaded); + } + if (s->handle) { + s->omx_context->ptr_FreeHandle(s->handle); + s->handle = NULL; + } + + omx_deinit(s->omx_context); + s->omx_context = NULL; + if (s->mutex_cond_inited) { + pthread_cond_destroy(&s->state_cond); + pthread_mutex_destroy(&s->state_mutex); + pthread_cond_destroy(&s->input_cond); + pthread_mutex_destroy(&s->input_mutex); + pthread_cond_destroy(&s->output_cond); + pthread_mutex_destroy(&s->output_mutex); + s->mutex_cond_inited = 0; + } + av_freep(&s->in_buffer_headers); + av_freep(&s->out_buffer_headers); + av_freep(&s->free_in_buffers); + av_freep(&s->done_out_buffers); + av_freep(&s->output_buf); +} + +static av_cold int omx_encode_init(AVCodecContext *avctx) +{ + OMXCodecContext *s = avctx->priv_data; + int ret = AVERROR_ENCODER_NOT_FOUND; + const char *role; + OMX_BUFFERHEADERTYPE *buffer; + OMX_ERRORTYPE err; + +#if CONFIG_OMX_RPI + s->input_zerocopy = 1; +#endif + + s->omx_context = omx_init(avctx, s->libname, s->libprefix); + if (!s->omx_context) + return AVERROR_ENCODER_NOT_FOUND; + + pthread_mutex_init(&s->state_mutex, NULL); + pthread_cond_init(&s->state_cond, NULL); + pthread_mutex_init(&s->input_mutex, NULL); + pthread_cond_init(&s->input_cond, NULL); + pthread_mutex_init(&s->output_mutex, NULL); + pthread_cond_init(&s->output_cond, NULL); + s->mutex_cond_inited = 1; + s->avctx = avctx; + s->state = OMX_StateLoaded; + s->error = OMX_ErrorNone; + + switch (avctx->codec->id) { + case AV_CODEC_ID_MPEG4: + role = "video_encoder.mpeg4"; + break; + case AV_CODEC_ID_H264: + role = "video_encoder.avc"; + break; + default: + return AVERROR(ENOSYS); + } + + if ((ret = find_component(s->omx_context, avctx, role, s->component_name, sizeof(s->component_name))) < 0) + goto fail; + + av_log(avctx, AV_LOG_INFO, "Using %s\n", s->component_name); + + if ((ret = omx_component_init(avctx, role)) < 0) + goto fail; + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + while (1) { + buffer = get_buffer(&s->output_mutex, &s->output_cond, + &s->num_done_out_buffers, s->done_out_buffers, 1); + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if ((ret = av_reallocp(&avctx->extradata, avctx->extradata_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { + avctx->extradata_size = 0; + goto fail; + } + memcpy(avctx->extradata + avctx->extradata_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen); + avctx->extradata_size += buffer->nFilledLen; + memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + err = OMX_FillThisBuffer(s->handle, buffer); + if (err != OMX_ErrorNone) { + append_buffer(&s->output_mutex, &s->output_cond, + &s->num_done_out_buffers, s->done_out_buffers, buffer); + av_log(avctx, AV_LOG_ERROR, "OMX_FillThisBuffer failed: %x\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + if (avctx->codec->id == AV_CODEC_ID_H264) { + // For H.264, the extradata can be returned in two separate buffers + // (the videocore encoder on raspberry pi does this); + // therefore check that we have got both SPS and PPS before continuing. + int nals[32] = { 0 }; + int i; + for (i = 0; i + 4 < avctx->extradata_size; i++) { + if (!avctx->extradata[i + 0] && + !avctx->extradata[i + 1] && + !avctx->extradata[i + 2] && + avctx->extradata[i + 3] == 1) { + nals[avctx->extradata[i + 4] & 0x1f]++; + } + } + if (nals[H264_NAL_SPS] && nals[H264_NAL_PPS]) + break; + } else { + if (avctx->extradata_size > 0) + break; + } + } + } + + return 0; +fail: + return ret; +} + + +static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + OMXCodecContext *s = avctx->priv_data; + int ret = 0; + OMX_BUFFERHEADERTYPE* buffer; + OMX_ERRORTYPE err; + + if (frame) { + uint8_t *dst[4]; + int linesize[4]; + int need_copy; + buffer = get_buffer(&s->input_mutex, &s->input_cond, + &s->num_free_in_buffers, s->free_in_buffers, 1); + + buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1); + + if (s->input_zerocopy) { + uint8_t *src[4] = { NULL }; + int src_linesize[4]; + av_image_fill_arrays(src, src_linesize, frame->data[0], avctx->pix_fmt, s->stride, s->plane_size, 1); + if (frame->linesize[0] == src_linesize[0] && + frame->linesize[1] == src_linesize[1] && + frame->linesize[2] == src_linesize[2] && + frame->data[1] == src[1] && + frame->data[2] == src[2]) { + // If the input frame happens to have all planes stored contiguously, + // with the right strides, just clone the frame and set the OMX + // buffer header to point to it + AVFrame *local = av_frame_clone(frame); + if (!local) { + // Return the buffer to the queue so it's not lost + append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); + return AVERROR(ENOMEM); + } else { + buffer->pAppPrivate = local; + buffer->pOutputPortPrivate = NULL; + buffer->pBuffer = local->data[0]; + need_copy = 0; + } + } else { + // If not, we need to allocate a new buffer with the right + // size and copy the input frame into it. + uint8_t *buf = av_malloc(av_image_get_buffer_size(avctx->pix_fmt, s->stride, s->plane_size, 1)); + if (!buf) { + // Return the buffer to the queue so it's not lost + append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); + return AVERROR(ENOMEM); + } else { + buffer->pAppPrivate = buf; + // Mark that pAppPrivate is an av_malloc'ed buffer, not an AVFrame + buffer->pOutputPortPrivate = (void*) 1; + buffer->pBuffer = buf; + need_copy = 1; + buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1); + } + } + } else { + need_copy = 1; + } + if (need_copy) + av_image_copy(dst, linesize, (const uint8_t**) frame->data, frame->linesize, avctx->pix_fmt, avctx->width, avctx->height); + buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; + buffer->nOffset = 0; + // Convert the timestamps to microseconds; some encoders can ignore + // the framerate and do VFR bit allocation based on timestamps. + buffer->nTimeStamp = to_omx_ticks(av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q)); + err = OMX_EmptyThisBuffer(s->handle, buffer); + if (err != OMX_ErrorNone) { + append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); + av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err); + return AVERROR_UNKNOWN; + } + s->num_in_frames++; + } + + while (!*got_packet && ret == 0) { + // Only wait for output if flushing and not all frames have been output + buffer = get_buffer(&s->output_mutex, &s->output_cond, + &s->num_done_out_buffers, s->done_out_buffers, + !frame && s->num_out_frames < s->num_in_frames); + if (!buffer) + break; + + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG && avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + if ((ret = av_reallocp(&avctx->extradata, avctx->extradata_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { + avctx->extradata_size = 0; + goto end; + } + memcpy(avctx->extradata + avctx->extradata_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen); + avctx->extradata_size += buffer->nFilledLen; + memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } else { + if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) + s->num_out_frames++; + if (!(buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) || !pkt->data) { + // If the output packet isn't preallocated, just concatenate everything in our + // own buffer + int newsize = s->output_buf_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE; + if ((ret = av_reallocp(&s->output_buf, newsize)) < 0) { + s->output_buf_size = 0; + goto end; + } + memcpy(s->output_buf + s->output_buf_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen); + s->output_buf_size += buffer->nFilledLen; + if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) { + if ((ret = av_packet_from_data(pkt, s->output_buf, s->output_buf_size)) < 0) { + av_freep(&s->output_buf); + s->output_buf_size = 0; + goto end; + } + s->output_buf = NULL; + s->output_buf_size = 0; + } + } else { + // End of frame, and the caller provided a preallocated frame + if ((ret = ff_alloc_packet(pkt, s->output_buf_size + buffer->nFilledLen)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", + (int)(s->output_buf_size + buffer->nFilledLen)); + goto end; + } + memcpy(pkt->data, s->output_buf, s->output_buf_size); + memcpy(pkt->data + s->output_buf_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen); + av_freep(&s->output_buf); + s->output_buf_size = 0; + } + if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) { + pkt->pts = av_rescale_q(from_omx_ticks(buffer->nTimeStamp), AV_TIME_BASE_Q, avctx->time_base); + // We don't currently enable B-frames for the encoders, so set + // pkt->dts = pkt->pts. (The calling code behaves worse if the encoder + // doesn't set the dts). + pkt->dts = pkt->pts; + if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + } + } +end: + err = OMX_FillThisBuffer(s->handle, buffer); + if (err != OMX_ErrorNone) { + append_buffer(&s->output_mutex, &s->output_cond, &s->num_done_out_buffers, s->done_out_buffers, buffer); + av_log(avctx, AV_LOG_ERROR, "OMX_FillThisBuffer failed: %x\n", err); + ret = AVERROR_UNKNOWN; + } + } + return ret; +} + +static av_cold int omx_encode_end(AVCodecContext *avctx) +{ + OMXCodecContext *s = avctx->priv_data; + + cleanup(s); + return 0; +} + +#define OFFSET(x) offsetof(OMXCodecContext, x) +#define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE }, + { "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE }, + { "zerocopy", "Try to avoid copying input frames if possible", OFFSET(input_zerocopy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL } +}; + +static const enum AVPixelFormat omx_encoder_pix_fmts[] = { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE +}; + +static const AVClass omx_mpeg4enc_class = { + .class_name = "mpeg4_omx", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; +AVCodec ff_mpeg4_omx_encoder = { + .name = "mpeg4_omx", + .long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL MPEG-4 video encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(OMXCodecContext), + .init = omx_encode_init, + .encode2 = omx_encode_frame, + .close = omx_encode_end, + .pix_fmts = omx_encoder_pix_fmts, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &omx_mpeg4enc_class, +}; + +static const AVClass omx_h264enc_class = { + .class_name = "h264_omx", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; +AVCodec ff_h264_omx_encoder = { + .name = "h264_omx", + .long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL H.264 video encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(OMXCodecContext), + .init = omx_encode_init, + .encode2 = omx_encode_frame, + .close = omx_encode_end, + .pix_fmts = omx_encoder_pix_fmts, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &omx_h264enc_class, +}; diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c index c00339f..2a528c6 100644 --- a/libavcodec/on2avc.c +++ b/libavcodec/on2avc.c @@ -26,9 +26,7 @@ #include "bytestream.h" #include "fft.h" #include "get_bits.h" -#include "golomb.h" #include "internal.h" -#include "unary.h" #include "on2avcdata.h" @@ -186,7 +184,7 @@ static int on2avc_decode_band_scales(On2AVCContext *c, GetBitContext *gb) static inline float on2avc_scale(int v, float scale) { - return v * sqrtf(fabsf(v)) * scale; + return v * sqrtf(abs(v)) * scale; } // spectral data is coded completely differently - there are no unsigned codebooks @@ -211,9 +209,16 @@ static inline int get_egolomb(GetBitContext *gb) { int v = 4; - while (get_bits1(gb)) v++; + while (get_bits1(gb)) { + v++; + if (v > 30) { + av_log(NULL, AV_LOG_WARNING, "Too large golomb code in get_egolomb.\n"); + v = 30; + break; + } + } - return (1 << v) + get_bits(gb, v); + return (1 << v) + get_bits_long(gb, v); } static int on2avc_decode_pairs(On2AVCContext *c, GetBitContext *gb, float *dst, @@ -951,7 +956,7 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx) ff_fft_init(&c->fft256, 7, 0); ff_fft_init(&c->fft512, 8, 1); ff_fft_init(&c->fft1024, 9, 1); - avpriv_float_dsp_init(&c->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&c->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); if (init_vlc(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS, ff_on2avc_scale_diff_bits, 1, 1, @@ -1012,7 +1017,7 @@ AVCodec ff_on2avc_decoder = { .init = on2avc_decode_init, .decode = on2avc_decode_frame, .close = on2avc_decode_close, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/options.c b/libavcodec/options.c index f428976..00921fb 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -27,12 +27,15 @@ #include "avcodec.h" #include "internal.h" #include "libavutil/avassert.h" +#include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include /* FLT_MIN, FLT_MAX */ #include +FF_DISABLE_DEPRECATION_WARNINGS #include "options_table.h" +FF_ENABLE_DEPRECATION_WARNINGS static const char* context_to_name(void* ptr) { AVCodecContext *avc= ptr; @@ -77,7 +80,7 @@ static const AVClass av_codec_context_class = { .child_class_next = codec_child_class_next, }; -int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) +static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) { memset(s, 0, sizeof(AVCodecContext)); @@ -88,12 +91,14 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) av_opt_set_defaults(s); s->time_base = (AVRational){0,1}; + s->framerate = (AVRational){ 0, 1 }; s->get_buffer2 = avcodec_default_get_buffer2; s->get_format = avcodec_default_get_format; s->execute = avcodec_default_execute; s->execute2 = avcodec_default_execute2; s->sample_aspect_ratio = (AVRational){0,1}; s->pix_fmt = AV_PIX_FMT_NONE; + s->sw_pix_fmt = AV_PIX_FMT_NONE; s->sample_fmt = AV_SAMPLE_FMT_NONE; s->reordered_opaque = AV_NOPTS_VALUE; @@ -121,6 +126,13 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) return 0; } +#if FF_API_GET_CONTEXT_DEFAULTS +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) +{ + return init_context_defaults(s, codec); +} +#endif + AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) { AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); @@ -128,7 +140,7 @@ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) if (!avctx) return NULL; - if(avcodec_get_context_defaults3(avctx, codec) < 0){ + if (init_context_defaults(avctx, codec) < 0) { av_free(avctx); return NULL; } @@ -151,6 +163,7 @@ void avcodec_free_context(AVCodecContext **pavctx) av_freep(pavctx); } +#if FF_API_COPY_CONTEXT int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) { const AVCodec *orig_codec = dest->codec; @@ -173,17 +186,22 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) dest->internal = NULL; /* reallocate values that should be allocated separately */ - dest->rc_eq = NULL; dest->extradata = NULL; dest->intra_matrix = NULL; dest->inter_matrix = NULL; dest->rc_override = NULL; dest->subtitle_header = NULL; + dest->hw_frames_ctx = NULL; +#if FF_API_MPV_OPT + FF_DISABLE_DEPRECATION_WARNINGS + dest->rc_eq = NULL; if (src->rc_eq) { dest->rc_eq = av_strdup(src->rc_eq); if (!dest->rc_eq) return AVERROR(ENOMEM); } + FF_ENABLE_DEPRECATION_WARNINGS +#endif #define alloc_and_copy_or_fail(obj, size, pad) \ if (src->obj && size > 0) { \ @@ -195,7 +213,7 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) memset(((uint8_t *) dest->obj) + size, 0, pad); \ } alloc_and_copy_or_fail(extradata, src->extradata_size, - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); alloc_and_copy_or_fail(intra_matrix, 64 * sizeof(int16_t), 0); alloc_and_copy_or_fail(inter_matrix, 64 * sizeof(int16_t), 0); alloc_and_copy_or_fail(rc_override, src->rc_override_count * sizeof(*src->rc_override), 0); @@ -203,16 +221,29 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) dest->subtitle_header_size = src->subtitle_header_size; #undef alloc_and_copy_or_fail + if (src->hw_frames_ctx) { + dest->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); + if (!dest->hw_frames_ctx) + goto fail; + } + return 0; fail: + av_freep(&dest->subtitle_header); av_freep(&dest->rc_override); av_freep(&dest->intra_matrix); av_freep(&dest->inter_matrix); av_freep(&dest->extradata); + av_buffer_unref(&dest->hw_frames_ctx); +#if FF_API_MPV_OPT + FF_DISABLE_DEPRECATION_WARNINGS av_freep(&dest->rc_eq); + FF_ENABLE_DEPRECATION_WARNINGS +#endif return AVERROR(ENOMEM); } +#endif const AVClass *avcodec_get_class(void) { diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index cf1f20a..5090806 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -47,11 +46,11 @@ static const AVOption avcodec_options[] = { "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.", OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E}, {"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|E|D, "flags"}, -{"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" }, -{"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"}, -{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"}, -{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, -{"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, +{"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = AV_CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" }, +{"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"}, +{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"}, +{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, +{"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, #if FF_API_GMC {"gmc", "use gmc", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GMC }, INT_MIN, INT_MAX, V|E, "flags"}, #endif @@ -61,29 +60,30 @@ static const AVOption avcodec_options[] = { #if FF_API_INPUT_PRESERVED {"input_preserved", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INPUT_PRESERVED }, INT_MIN, INT_MAX, 0, "flags"}, #endif -{"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, -{"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, -{"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, +{"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, +{"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, +{"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, #if FF_API_EMU_EDGE {"emu_edge", "do not draw edges", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_EMU_EDGE }, INT_MIN, INT_MAX, 0, "flags"}, #endif -{"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, -{"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, +{"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, +{"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, #if FF_API_NORMALIZE_AQP {"naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_NORMALIZE_AQP }, INT_MIN, INT_MAX, V|E, "flags"}, #endif -{"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"}, -{"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"}, -{"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"}, -{"bitexact", "use only bitexact functions (except (I)DCT)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_BITEXACT }, INT_MIN, INT_MAX, A|V|S|D|E, "flags"}, -{"aic", "H.263 advanced intra coding / MPEG-4 AC prediction", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_AC_PRED }, INT_MIN, INT_MAX, V|E, "flags"}, -{"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"}, -{"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"}, -{"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"}, -{"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"}, -{"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, -{"ignorecrop", "ignore cropping information from sps", 1, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"}, -{"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"}, +{"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"}, +{"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"}, +{"bitexact", "use only bitexact functions (except (I)DCT)", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_BITEXACT }, INT_MIN, INT_MAX, A|V|S|D|E, "flags"}, +{"aic", "H.263 advanced intra coding / MPEG-4 AC prediction", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_AC_PRED }, INT_MIN, INT_MAX, V|E, "flags"}, +{"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"}, +{"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"}, +{"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"}, +{"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"ignorecrop", "ignore cropping information from sps", 1, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"}, +{"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"}, +#if FF_API_MOTION_EST {"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"}, {"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" }, {"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" }, @@ -96,6 +96,7 @@ static const AVOption avcodec_options[] = { {"x1", "X1 motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_X1 }, INT_MIN, INT_MAX, V|E, "me_method" }, {"hex", "hex motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_HEX }, INT_MIN, INT_MAX, V|E, "me_method" }, {"umh", "umh motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_UMH }, INT_MIN, INT_MAX, V|E, "me_method" }, +#endif {"extradata_size", NULL, OFFSET(extradata_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, INT_MIN, INT_MAX}, {"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E}, @@ -112,11 +113,16 @@ static const AVOption avcodec_options[] = { {"qmin", "minimum video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E}, {"qmax", "maximum video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 69, V|E}, {"qdiff", "maximum difference between the quantizer scales (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E}, -{"bf", "use 'frames' B frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E}, +{"bf", "use 'frames' B-frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E}, {"b_qfactor", "QP factor between P- and B-frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E}, +#if FF_API_RC_STRATEGY {"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif +#if FF_API_PRIVATE_OPT {"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, {"ps", "RTP payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif +#if FF_API_STAT_BITS {"mv_bits", NULL, OFFSET(mv_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"header_bits", NULL, OFFSET(header_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"i_tex_bits", NULL, OFFSET(i_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, @@ -126,6 +132,7 @@ static const AVOption avcodec_options[] = { {"skip_count", NULL, OFFSET(skip_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#endif {"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"bug", "work around not autodetected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, {"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, @@ -162,30 +169,34 @@ static const AVOption avcodec_options[] = { {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, V|D, "err_detect"}, {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#if FF_API_PRIVATE_OPT {"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E}, -{"rc_qmod_amp", "experimental quantizer modulation", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, -{"rc_qmod_freq", "experimental quantizer modulation", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif +#if FF_API_MPV_OPT +{"qsquish", "deprecated, use encoder private options instead", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E}, +{"rc_qmod_amp", "deprecated, use encoder private options instead", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +{"rc_qmod_freq", "deprecated, use encoder private options instead", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"rc_override_count", NULL, OFFSET(rc_override_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -{"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " - "defined in the section 'Expression Evaluation', the following functions are available: " - "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " - "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", - OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E}, +#if FF_API_MPV_OPT +{"rc_eq", "deprecated, use encoder private options instead", OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E}, +#endif {"maxrate", "Set maximum bitrate tolerance (in bits/s). Requires bufsize to be set.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, {"minrate", "Set minimum bitrate tolerance (in bits/s). Most useful in setting up a CBR encode. It is of little use otherwise.", OFFSET(rc_min_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, {"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|E}, -{"rc_buf_aggressivity", "currently useless", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E}, +#if FF_API_MPV_OPT +{"rc_buf_aggressivity", "deprecated, use encoder private options instead", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E}, +#endif {"i_qfactor", "QP factor between P- and I-frames", OFFSET(i_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = -0.8 }, -FLT_MAX, FLT_MAX, V|E}, {"i_qoffset", "QP offset between P- and I-frames", OFFSET(i_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -FLT_MAX, FLT_MAX, V|E}, -{"rc_init_cplx", "initial complexity for 1-pass encoding", OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +#if FF_API_MPV_OPT +{"rc_init_cplx", "deprecated, use encoder private options instead", OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +#endif {"dct", "DCT algorithm", OFFSET(dct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E, "dct"}, {"auto", "autoselect a good one (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_AUTO }, INT_MIN, INT_MAX, V|E, "dct"}, {"fastint", "fast integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FASTINT }, INT_MIN, INT_MAX, V|E, "dct"}, -#if FF_API_UNUSED_MEMBERS {"int", "accurate integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_INT }, INT_MIN, INT_MAX, V|E, "dct"}, -#endif /* FF_API_UNUSED_MEMBERS */ {"mmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_MMX }, INT_MIN, INT_MAX, V|E, "dct"}, {"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_ALTIVEC }, INT_MIN, INT_MAX, V|E, "dct"}, {"faan", "floating point AAN DCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FAAN }, INT_MIN, INT_MAX, V|E, "dct"}, @@ -224,10 +235,12 @@ static const AVOption avcodec_options[] = { {"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"}, {"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"}, {"bits_per_coded_sample", NULL, OFFSET(bits_per_coded_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#if FF_API_PRIVATE_OPT {"pred", "prediction method", OFFSET(prediction_method), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "pred"}, {"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_LEFT }, INT_MIN, INT_MAX, V|E, "pred"}, {"plane", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_PLANE }, INT_MIN, INT_MAX, V|E, "pred"}, {"median", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_MEDIAN }, INT_MIN, INT_MAX, V|E, "pred"}, +#endif {"aspect", "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E}, {"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"}, {"pict", "picture info", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PICT_INFO }, INT_MIN, INT_MAX, V|D, "debug"}, @@ -265,7 +278,9 @@ static const AVOption avcodec_options[] = { {"ildctcmp", "interlaced DCT compare function", OFFSET(ildct_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"dia_size", "diamond type & size for motion estimation", OFFSET(dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"last_pred", "amount of motion predictors from the previous frame", OFFSET(last_predictor_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#if FF_API_PRIVATE_OPT {"preme", "pre motion estimation", OFFSET(pre_me), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"precmp", "pre motion estimation compare function", OFFSET(me_pre_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"sad", "sum of absolute differences, fast (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"sse", "sum of squared errors", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SSE }, INT_MIN, INT_MAX, V|E, "cmp_func"}, @@ -282,11 +297,16 @@ static const AVOption avcodec_options[] = { {"chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, +#if FF_API_AFD {"dtg_active_format", NULL, OFFSET(dtg_active_format), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#endif {"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#if FF_API_QUANT_BIAS {"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, {"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, +#endif {"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +#if FF_API_CODER_TYPE {"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"}, {"vlc", "variable length coder / Huffman coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_VLC }, INT_MIN, INT_MAX, V|E, "coder"}, {"ac", "arithmetic coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_AC }, INT_MIN, INT_MAX, V|E, "coder"}, @@ -295,7 +315,10 @@ static const AVOption avcodec_options[] = { #if FF_API_UNUSED_MEMBERS {"deflate", "deflate-based coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_DEFLATE }, INT_MIN, INT_MAX, V|E, "coder"}, #endif /* FF_API_UNUSED_MEMBERS */ +#endif /* FF_API_CODER_TYPE */ +#if FF_API_PRIVATE_OPT {"context", "context model", OFFSET(context_model), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"slice_flags", NULL, OFFSET(slice_flags), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, #if FF_API_XVMC {"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, @@ -304,11 +327,19 @@ static const AVOption avcodec_options[] = { {"simple", "use mbcmp (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_SIMPLE }, INT_MIN, INT_MAX, V|E, "mbd"}, {"bits", "use fewest bits", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_BITS }, INT_MIN, INT_MAX, V|E, "mbd"}, {"rd", "use best rate distortion", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_RD }, INT_MIN, INT_MAX, V|E, "mbd"}, +#if FF_API_STREAM_CODEC_TAG {"stream_codec_tag", NULL, OFFSET(stream_codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#endif +#if FF_API_PRIVATE_OPT {"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -{"lmin", "minimum Lagrange factor (VBR)", OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, V|E}, -{"lmax", "maximum Lagrange factor (VBR)", OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, V|E}, +#endif +#if FF_API_MPV_OPT +{"lmin", "deprecated, use encoder private options instead", OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, +{"lmax", "deprecated, use encoder private options instead", OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, +#endif +#if FF_API_PRIVATE_OPT {"nr", "noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"rc_init_occupancy", "number of bits which should be loaded into the rc buffer before decoding starts", OFFSET(rc_initial_buffer_occupancy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"}, #if FF_API_ERROR_RATE @@ -316,8 +347,10 @@ static const AVOption avcodec_options[] = { #endif {"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, V|E|D, "threads"}, {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, +#if FF_API_MPV_OPT {"me_threshold", "motion estimation threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, {"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, {"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, @@ -341,14 +374,20 @@ static const AVOption avcodec_options[] = { {"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"}, {"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, +#if FF_API_PRIVATE_OPT {"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"}, -{"border_mask", "increase the quantizer for macroblocks close to borders", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +#endif +#if FF_API_MPV_OPT +{"border_mask", "deprecated, use encoder private options instead", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +#endif {"mblmin", "minimum macroblock Lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E}, {"mblmax", "maximum macroblock Lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E}, +#if FF_API_PRIVATE_OPT {"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, V|E}, +#endif {"skip_loop_filter", NULL, OFFSET(skip_loop_filter), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"skip_idct" , NULL, OFFSET(skip_idct) , AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"skip_frame" , NULL, OFFSET(skip_frame) , AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, @@ -359,22 +398,27 @@ static const AVOption avcodec_options[] = { {"nokey" , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"all" , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E}, +#if FF_API_PRIVATE_OPT {"brd_scale", "downscale frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 10, V|E}, +#endif {"keyint_min", "minimum interval between IDR-frames (x264)", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E}, {"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.i64 = 1 }, INT_MIN, INT_MAX, V|E}, +#if FF_API_PRIVATE_OPT {"chromaoffset", "chroma QP offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +#endif {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, #if FF_API_UNUSED_MEMBERS {"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), AV_OPT_TYPE_INT, {.i64 = 6 }, 0, INT_MAX, V|E}, #endif /* FF_API_UNUSED_MEMBERS */ {"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.i64 = 256 }, 0, INT_MAX, V|E}, +#if FF_API_PRIVATE_OPT {"b_sensitivity", "adjust sensitivity of b_frame_strategy 1", OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, V|E}, +#endif {"compression_level", NULL, OFFSET(compression_level), AV_OPT_TYPE_INT, {.i64 = FF_COMPRESSION_DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +#if FF_API_PRIVATE_OPT {"min_prediction_order", NULL, OFFSET(min_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E}, {"max_prediction_order", NULL, OFFSET(max_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E}, {"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, V|E}, -#if FF_API_REQUEST_CHANNELS -{"request_channels", "set desired number of audio channels", OFFSET(request_channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D}, #endif {"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"channel_layout", NULL, OFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|E|D, "channel_layout"}, @@ -384,44 +428,77 @@ static const AVOption avcodec_options[] = { {"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D}, {"color_primaries", "color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64 = AVCOL_PRI_UNSPECIFIED }, 1, AVCOL_PRI_NB-1, V|E|D, "color_primaries_type"}, {"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT709 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, -{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"bt470m", "BT.470 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT470M }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"bt470bg", "BT.470 BG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT470BG }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"smpte170m", "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE170M }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"smpte240m", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE240M }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"film", "Film", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_FILM }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"bt2020", "BT.2020", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT2020 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, -{"color_trc", "color transfert characteristic", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, AVCOL_TRC_NB-1, V|E|D, "color_trc_type"}, +{"smpte428", "SMPTE 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE428 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"smpte431", "SMPTE 431-2", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE431 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"smpte432", "SMPTE 422-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE432 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"smptest428_1", "SMPTE 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE428 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"color_trc", "color transfer characteristics", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, AVCOL_TRC_NB-1, V|E|D, "color_trc_type"}, {"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT709 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"gamma22", "Gamma 2.2", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA22 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"gamma28", "Gamma 2.8", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA28 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"gamma22", "BT.470 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA22 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"gamma28", "BT.470 BG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA28 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"smpte170m", "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE170M }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"smpte240m", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE240M }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"linear", "Linear", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LINEAR }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"log", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"log_sqrt", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG_SQRT }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"iec61966_2_4", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_4 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"log100", "Log", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"log316", "Log square root", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG_SQRT }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"iec61966-2-4", "IEC 61966-2-4", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_4 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"bt1361e", "BT.1361", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT1361_ECG }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"iec61966-2-1", "IEC 61966-2-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"bt2020-10", "BT.2020 - 10 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_10 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"bt2020-12", "BT.2020 - 12 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_12 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"smpte2084", "SMPTE 2084", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE2084 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"smpte428", "SMPTE 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE428 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"arib-std-b67", "ARIB STD-B67", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_ARIB_STD_B67 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"log", "Log", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"log_sqrt", "Log square root", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG_SQRT }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"iec61966_2_4", "IEC 61966-2-4", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_4 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"bt1361", "BT.1361", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT1361_ECG }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"iec61966_2_1", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"iec61966_2_1", "IEC 61966-2-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"bt2020_10bit", "BT.2020 - 10 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_10 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"bt2020_12bit", "BT.2020 - 12 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_12 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, -{"colorspace", "colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 1, AVCOL_SPC_NB-1, V|E|D, "colorspace_type"}, +{"smptest2084", "SMPTE 2084", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE2084 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"smptest428_1", "SMPTE 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE428 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, +{"colorspace", "color space", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 0, AVCOL_SPC_NB-1, V|E|D, "colorspace_type"}, {"rgb", "RGB", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_RGB }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT709 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"fcc", "FourCC", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_FCC }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"fcc", "FCC", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_FCC }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"bt470bg", "BT.470 BG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT470BG }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"smpte170m", "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE170M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"smpte240m", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE240M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"ycocg", "YCOCG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCOCG }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020nc", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020c", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"smpte2085", "SMPTE 2085", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE2085 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"bt2020_ncl", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"bt2020_cl", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"color_range", "color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, AVCOL_RANGE_NB-1, V|E|D, "color_range_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, +{"tv", "MPEG (219*2^(n-8))", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, +{"pc", "JPEG (2^n-1)", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, {"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, {"mpeg", "MPEG (219*2^(n-8))", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, {"jpeg", "JPEG (2^n-1)", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, -{"chroma_sample_location", NULL, OFFSET(chroma_sample_location), AV_OPT_TYPE_INT, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, V|E|D}, +{"chroma_sample_location", "chroma sample location", OFFSET(chroma_sample_location), AV_OPT_TYPE_INT, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, V|E|D, "chroma_sample_location_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"left", "Left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_LEFT }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"center", "Center", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_CENTER }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"topleft", "Top-left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_TOPLEFT }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"top", "Top", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_TOP }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"bottomleft", "Bottom-left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOMLEFT }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"bottom", "Bottom", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOM }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, +{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"}, {"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX }, {"slices", "number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, {"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|E|D, "thread_type"}, @@ -449,7 +526,9 @@ static const AVOption avcodec_options[] = { {"fltp", "32-bit float planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLTP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, {"dblp", "64-bit double planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBLP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, {"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, A|V|D }, -{"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, A|V|E }, +#if FF_API_SIDEDATA_ONLY_PKT +{"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E }, +#endif {NULL}, }; diff --git a/libavcodec/opus.c b/libavcodec/opus.c index 91021ce..8e896dd 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -264,7 +264,7 @@ int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size, } else { pkt->mode = OPUS_MODE_CELT; pkt->bandwidth = (pkt->config - 16) >> 2; - /* skip mediumband */ + /* skip medium band */ if (pkt->bandwidth) pkt->bandwidth++; } @@ -290,10 +290,6 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, OpusContext *s) { static const uint8_t default_channel_map[2] = { 0, 1 }; - uint8_t default_extradata[19] = { - 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; int (*channel_reorder)(int, int) = channel_reorder_unknown; @@ -308,9 +304,8 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, "Multichannel configuration without extradata.\n"); return AVERROR(EINVAL); } - default_extradata[9] = (avctx->channels == 1) ? 1 : 2; - extradata = default_extradata; - extradata_size = sizeof(default_extradata); + extradata = opus_default_extradata; + extradata_size = sizeof(opus_default_extradata); } else { extradata = avctx->extradata; extradata_size = avctx->extradata_size; @@ -330,7 +325,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, avctx->delay = AV_RL16(extradata + 10); - channels = extradata[9]; + channels = avctx->extradata ? extradata[9] : (avctx->channels == 1) ? 1 : 2; if (!channels) { av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the extadata\n"); return AVERROR_INVALIDDATA; @@ -401,7 +396,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - /* check that we din't see this index yet */ + /* check that we did not see this index yet */ map->copy = 0; for (j = 0; j < i; j++) if (channel_map[channel_reorder(channels, j)] == idx) { diff --git a/libavcodec/opus.h b/libavcodec/opus.h index accb998..55c91fa 100644 --- a/libavcodec/opus.h +++ b/libavcodec/opus.h @@ -61,6 +61,15 @@ #define ROUND_MUL16(a,b) ((MUL16(a, b) + 16384) >> 15) #define opus_ilog(i) (av_log2(i) + !!(i)) +#define OPUS_TS_HEADER 0x7FE0 // 0x3ff (11 bits) +#define OPUS_TS_MASK 0xFFE0 // top 11 bits + +static const uint8_t opus_default_extradata[30] = { + 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + enum OpusMode { OPUS_MODE_SILK, OPUS_MODE_HYBRID, diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index af3e549..07a4f77 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -28,8 +28,8 @@ #include "libavutil/float_dsp.h" +#include "imdct15.h" #include "opus.h" -#include "opus_imdct.h" enum CeltSpread { CELT_SPREAD_NONE, @@ -61,7 +61,7 @@ typedef struct CeltFrame { struct CeltContext { // constant values that do not change during context lifetime AVCodecContext *avctx; - CeltIMDCTContext *imdct[4]; + IMDCT15Context *imdct[4]; AVFloatDSPContext dsp; int output_channels; @@ -1909,7 +1909,7 @@ static void celt_decode_bands(CeltContext *s, OpusRangeCoder *rc) s->remaining2 = totalbits - consumed - 1; if (i <= s->codedbands - 1) { int curr_balance = s->remaining / FFMIN(3, s->codedbands-i); - b = av_clip(FFMIN(s->remaining2 + 1, s->pulses[i] + curr_balance), 0, 16383); + b = av_clip_uintp2(FFMIN(s->remaining2 + 1, s->pulses[i] + curr_balance), 14); } else b = 0; @@ -1983,7 +1983,7 @@ int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc, int silence = 0; int transient = 0; int anticollapse = 0; - CeltIMDCTContext *imdct; + IMDCT15Context *imdct; float imdct_scale = 1.0; if (coded_channels != 1 && coded_channels != 2) { @@ -2179,7 +2179,7 @@ void ff_celt_free(CeltContext **ps) return; for (i = 0; i < FF_ARRAY_ELEMS(s->imdct); i++) - ff_celt_imdct_uninit(&s->imdct[i]); + ff_imdct15_uninit(&s->imdct[i]); av_freep(ps); } @@ -2203,12 +2203,12 @@ int ff_celt_init(AVCodecContext *avctx, CeltContext **ps, int output_channels) s->output_channels = output_channels; for (i = 0; i < FF_ARRAY_ELEMS(s->imdct); i++) { - ret = ff_celt_imdct_init(&s->imdct[i], i + 3); + ret = ff_imdct15_init(&s->imdct[i], i + 3); if (ret < 0) goto fail; } - avpriv_float_dsp_init(&s->dsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); ff_celt_flush(s); diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c index 8a2bc22..d256fbb 100644 --- a/libavcodec/opus_parser.c +++ b/libavcodec/opus_parser.c @@ -26,50 +26,163 @@ */ #include "avcodec.h" +#include "bytestream.h" #include "opus.h" +#include "parser.h" typedef struct OpusParseContext { OpusContext ctx; OpusPacket pkt; int extradata_parsed; + ParseContext pc; + int ts_framing; } OpusParseContext; -static int opus_parse(AVCodecParserContext *ctx, AVCodecContext *avctx, - const uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size) +static const uint8_t *parse_opus_ts_header(const uint8_t *start, int *payload_len, int buf_len) +{ + const uint8_t *buf = start + 1; + int start_trim_flag, end_trim_flag, control_extension_flag, control_extension_length; + uint8_t flags; + + GetByteContext gb; + bytestream2_init(&gb, buf, buf_len); + + flags = bytestream2_get_byte(&gb); + start_trim_flag = (flags >> 4) & 1; + end_trim_flag = (flags >> 3) & 1; + control_extension_flag = (flags >> 2) & 1; + + *payload_len = 0; + while (bytestream2_peek_byte(&gb) == 0xff) + *payload_len += bytestream2_get_byte(&gb); + + *payload_len += bytestream2_get_byte(&gb); + + if (start_trim_flag) + bytestream2_skip(&gb, 2); + if (end_trim_flag) + bytestream2_skip(&gb, 2); + if (control_extension_flag) { + control_extension_length = bytestream2_get_byte(&gb); + bytestream2_skip(&gb, control_extension_length); + } + + return buf + bytestream2_tell(&gb); +} + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int opus_find_frame_end(AVCodecParserContext *ctx, AVCodecContext *avctx, + const uint8_t *buf, int buf_size, int *header_len) { OpusParseContext *s = ctx->priv_data; - int ret; + ParseContext *pc = &s->pc; + int ret, start_found, i = 0, payload_len = 0; + const uint8_t *payload; + uint32_t state; + uint16_t hdr; + *header_len = 0; if (!buf_size) return 0; + start_found = pc->frame_start_found; + state = pc->state; + payload = buf; + + /* Check if we're using Opus in MPEG-TS framing */ + if (!s->ts_framing && buf_size > 2) { + hdr = AV_RB16(buf); + if ((hdr & OPUS_TS_MASK) == OPUS_TS_HEADER) + s->ts_framing = 1; + } + + if (s->ts_framing && !start_found) { + for (i = 0; i < buf_size-2; i++) { + state = (state << 8) | payload[i]; + if ((state & OPUS_TS_MASK) == OPUS_TS_HEADER) { + payload = parse_opus_ts_header(payload, &payload_len, buf_size - i); + *header_len = payload - buf; + start_found = 1; + break; + } + } + } + + if (!s->ts_framing) + payload_len = buf_size; + if (avctx->extradata && !s->extradata_parsed) { ret = ff_opus_parse_extradata(avctx, &s->ctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error parsing Ogg extradata.\n"); - goto fail; + return AVERROR_INVALIDDATA; } av_freep(&s->ctx.channel_maps); s->extradata_parsed = 1; } - ret = ff_opus_parse_packet(&s->pkt, buf, buf_size, s->ctx.nb_streams > 1); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error parsing Opus packet header.\n"); - goto fail; + if (payload_len <= buf_size && (!s->ts_framing || start_found)) { + ret = ff_opus_parse_packet(&s->pkt, payload, payload_len, s->ctx.nb_streams > 1); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing Opus packet header.\n"); + pc->frame_start_found = 0; + return AVERROR_INVALIDDATA; + } + + ctx->duration = s->pkt.frame_count * s->pkt.frame_duration; } - ctx->duration = s->pkt.frame_count * s->pkt.frame_duration; + if (s->ts_framing) { + if (start_found) { + if (payload_len + *header_len <= buf_size) { + pc->frame_start_found = 0; + pc->state = -1; + return payload_len + *header_len; + } + } + + pc->frame_start_found = start_found; + pc->state = state; + return END_NOT_FOUND; + } -fail: - *poutbuf = buf; - *poutbuf_size = buf_size; return buf_size; } +static int opus_parse(AVCodecParserContext *ctx, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + OpusParseContext *s = ctx->priv_data; + ParseContext *pc = &s->pc; + int next, header_len; + + next = opus_find_frame_end(ctx, avctx, buf, buf_size, &header_len); + + if (s->ts_framing && next != AVERROR_INVALIDDATA && + ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + if (next == AVERROR_INVALIDDATA){ + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = buf + header_len; + *poutbuf_size = buf_size - header_len; + return next; +} + AVCodecParser ff_opus_parser = { .codec_ids = { AV_CODEC_ID_OPUS }, .priv_data_size = sizeof(OpusParseContext), .parser_parse = opus_parse, + .parser_close = ff_parse_close }; diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c index 3552484..d83fb37 100644 --- a/libavcodec/opus_silk.c +++ b/libavcodec/opus_silk.c @@ -824,7 +824,7 @@ static inline void silk_stabilize_lsf(int16_t nlsf[16], int order, const uint16_ /* upper extent */ for (i = order; i > k; i--) - max_center -= min_delta[k]; + max_center -= min_delta[i]; max_center -= min_delta[k] >> 1; /* move apart */ @@ -1077,7 +1077,7 @@ static inline void silk_decode_lpc(SilkContext *s, SilkFrame *frame, weight = y + ((213 * fpart * y) >> 16); value = cur * 128 + (lsf_res[i] * 16384) / weight; - nlsf[i] = av_clip(value, 0, 32767); + nlsf[i] = av_clip_uintp2(value, 15); } /* stabilize the NLSF coefficients */ @@ -1288,8 +1288,8 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc, } else { /* gain is coded relative */ int delta_gain = opus_rc_getsymbol(rc, silk_model_gain_delta); - log_gain = av_clip(FFMAX((delta_gain<<1) - 16, - frame->log_gain + delta_gain - 4), 0, 63); + log_gain = av_clip_uintp2(FFMAX((delta_gain<<1) - 16, + frame->log_gain + delta_gain - 4), 6); } frame->log_gain = log_gain; @@ -1323,7 +1323,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc, if (lag_absolute) { /* primary lag is coded absolute */ int highbits, lowbits; - const uint16_t *model[] = { + static const uint16_t *model[] = { silk_model_pitch_lowbits_nb, silk_model_pitch_lowbits_mb, silk_model_pitch_lowbits_wb }; @@ -1357,11 +1357,11 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc, ltpfilter = opus_rc_getsymbol(rc, silk_model_ltp_filter); for (i = 0; i < s->subframes; i++) { int index, j; - const uint16_t *filter_sel[] = { + static const uint16_t *filter_sel[] = { silk_model_ltp_filter0_sel, silk_model_ltp_filter1_sel, silk_model_ltp_filter2_sel }; - const int8_t (*filter_taps[])[5] = { + static const int8_t (*filter_taps[])[5] = { silk_ltp_filter0_taps, silk_ltp_filter1_taps, silk_ltp_filter2_taps }; index = opus_rc_getsymbol(rc, filter_sel[ltpfilter]); diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c index 80a80b4..92e651c 100644 --- a/libavcodec/opusdec.c +++ b/libavcodec/opusdec.c @@ -567,8 +567,8 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data, if (buffer_samples) { float *buf[2] = { c->out[2 * i + 0] ? c->out[2 * i + 0] : (float*)frame->extended_data[0], c->out[2 * i + 1] ? c->out[2 * i + 1] : (float*)frame->extended_data[0] }; - buf[0] += buffer_samples; - buf[1] += buffer_samples; + buf[0] += decoded_samples; + buf[1] += decoded_samples; ret = av_audio_fifo_write(c->sync_buffers[i], (void**)buf, buffer_samples); if (ret < 0) return ret; @@ -587,7 +587,7 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data, memset(frame->extended_data[i], 0, frame->linesize[0]); } - if (c->gain_i) { + if (c->gain_i && decoded_samples > 0) { c->fdsp.vector_fmul_scalar((float*)frame->extended_data[i], (float*)frame->extended_data[i], c->gain, FFALIGN(decoded_samples, 8)); @@ -751,5 +751,5 @@ AVCodec ff_opus_decoder = { .close = opus_decode_close, .decode = opus_decode_packet, .flush = opus_decode_flush, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, }; diff --git a/libavcodec/pafaudio.c b/libavcodec/pafaudio.c index 52aaabf..c83e7f5 100644 --- a/libavcodec/pafaudio.c +++ b/libavcodec/pafaudio.c @@ -80,5 +80,5 @@ AVCodec ff_paf_audio_decoder = { .id = AV_CODEC_ID_PAF_AUDIO, .init = paf_audio_init, .decode = paf_audio_decode, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index 650d036..b77f47e 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -382,5 +382,5 @@ AVCodec ff_paf_video_decoder = { .init = paf_video_init, .close = paf_video_close, .decode = paf_video_decode, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/pamenc.c b/libavcodec/pamenc.c index 8535d3d..2b63af9 100644 --- a/libavcodec/pamenc.c +++ b/libavcodec/pamenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -31,10 +33,10 @@ static int pam_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int i, h, w, n, linesize, depth, maxval, ret; const char *tuple_type; uint8_t *ptr; + int size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); - if ((ret = ff_alloc_packet(pkt, avpicture_get_size(avctx->pix_fmt, - avctx->width, - avctx->height) + 200)) < 0) { + if ((ret = ff_alloc_packet(pkt, size + 200)) < 0) { av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); return ret; } @@ -109,29 +111,22 @@ static int pam_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int pam_encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } -static av_cold int pam_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - AVCodec ff_pam_encoder = { .name = "pam", .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PAM, .init = pam_encode_init, - .close = pam_encode_close, .encode2 = pam_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_GRAY8, AV_PIX_FMT_MONOWHITE, diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 6d20516..355187a 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -23,8 +23,10 @@ #include #include +#include "libavutil/internal.h" #include "libavutil/mem.h" +#include "internal.h" #include "parser.h" static AVCodecParser *av_first_parser = NULL; @@ -85,10 +87,16 @@ found: s->fetch_timestamp = 1; s->pict_type = AV_PICTURE_TYPE_I; s->key_frame = -1; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS s->convergence_duration = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->dts_sync_point = INT_MIN; s->dts_ref_dts_delta = INT_MIN; s->pts_dts_delta = INT_MIN; + s->format = -1; + return s; } @@ -123,7 +131,7 @@ int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, int64_t pts, int64_t dts, int64_t pos) { int index, i; - uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t dummy_buf[AV_INPUT_BUFFER_PADDING_SIZE]; if (!(s->flags & PARSER_FLAG_FETCHED_OFFSET)) { s->next_frame_offset = @@ -176,8 +184,8 @@ int av_parser_change(AVCodecParserContext *s, AVCodecContext *avctx, 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) { + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER || + avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER) { int i = s->parser->split(avctx, buf, buf_size); buf += i; buf_size -= i; @@ -188,15 +196,17 @@ int av_parser_change(AVCodecParserContext *s, AVCodecContext *avctx, *poutbuf = (uint8_t *) buf; *poutbuf_size = buf_size; if (avctx->extradata) { - if (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) { + if (keyframe && (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER)) { int size = buf_size + avctx->extradata_size; *poutbuf_size = size; - *poutbuf = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + *poutbuf = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!*poutbuf) + return AVERROR(ENOMEM); memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); memcpy(*poutbuf + avctx->extradata_size, buf, - buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + buf_size + AV_INPUT_BUFFER_PADDING_SIZE); return 1; } } @@ -218,9 +228,9 @@ int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) { if (pc->overread) { - av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", + ff_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); - av_dlog(NULL, "%X %X %X %X\n", + ff_dlog(NULL, "%X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); } @@ -238,7 +248,7 @@ int ff_combine_frame(ParseContext *pc, int next, if (next == END_NOT_FOUND) { void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, *buf_size + pc->index + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!new_buffer) return AVERROR(ENOMEM); @@ -255,14 +265,14 @@ int ff_combine_frame(ParseContext *pc, int next, if (pc->index) { void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!new_buffer) return AVERROR(ENOMEM); pc->buffer = new_buffer; - if (next > -FF_INPUT_BUFFER_PADDING_SIZE) + if (next > -AV_INPUT_BUFFER_PADDING_SIZE) memcpy(&pc->buffer[pc->index], *buf, - next + FF_INPUT_BUFFER_PADDING_SIZE); + next + AV_INPUT_BUFFER_PADDING_SIZE); pc->index = 0; *buf = pc->buffer; } @@ -275,9 +285,9 @@ int ff_combine_frame(ParseContext *pc, int next, } if (pc->overread) { - av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", + ff_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); - av_dlog(NULL, "%X %X %X %X\n", + ff_dlog(NULL, "%X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); } diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c index 7e4dcf8..51fcd2d 100644 --- a/libavcodec/pcm-bluray.c +++ b/libavcodec/pcm-bluray.c @@ -66,7 +66,7 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx, uint8_t channel_layout = header[2] >> 4; if (avctx->debug & FF_DEBUG_PICT_INFO) - av_dlog(avctx, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n", + ff_dlog(avctx, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n", header[0], header[1], header[2], header[3]); /* get the sample depth and derive the sample format from it */ @@ -115,7 +115,7 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx, avctx->bits_per_coded_sample; if (avctx->debug & FF_DEBUG_PICT_INFO) - av_dlog(avctx, + ff_dlog(avctx, "pcm_bluray_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n", avctx->channels, avctx->bits_per_coded_sample, avctx->sample_rate, avctx->bit_rate); @@ -297,7 +297,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, retval = bytestream2_tell(&gb); if (avctx->debug & FF_DEBUG_BITSTREAM) - av_dlog(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n", + ff_dlog(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n", retval, buf_size); return retval + 4; } @@ -308,7 +308,7 @@ AVCodec ff_pcm_bluray_decoder = { .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_PCM_BLURAY, .decode = pcm_bluray_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c index 0872d29..62aacf8 100644 --- a/libavcodec/pcm-dvd.c +++ b/libavcodec/pcm-dvd.c @@ -32,7 +32,7 @@ typedef struct PCMDVDContext { uint32_t last_header; // Cached header to see if parsing is needed int block_size; // Size of a block of samples in bytes int samples_per_block; // Number of samples per channel per block - int groups_per_block; // Number of 20/24bit sample groups per block + int groups_per_block; // Number of 20/24-bit sample groups per block uint8_t *extra_samples; // Pointer to leftover samples from a frame int extra_sample_count; // Number of leftover samples in the buffer } PCMDVDContext; @@ -71,7 +71,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) return 0; if (avctx->debug & FF_DEBUG_PICT_INFO) - av_dlog(avctx, "pcm_dvd_parse_header: header = %02x%02x%02x\n", + ff_dlog(avctx, "pcm_dvd_parse_header: header = %02x%02x%02x\n", header[0], header[1], header[2]); /* * header[0] emphasis (1), muse(1), reserved(1), frame number(5) @@ -102,7 +102,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) avctx->sample_rate * avctx->bits_per_coded_sample; - /* 4 samples form a group in 20/24bit PCM on DVD Video. + /* 4 samples form a group in 20/24-bit PCM on DVD Video. * A block is formed by the number of groups that are * needed to complete a set of samples for each channel. */ if (avctx->bits_per_coded_sample == 16) { @@ -135,7 +135,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) } if (avctx->debug & FF_DEBUG_PICT_INFO) - av_dlog(avctx, + ff_dlog(avctx, "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n", avctx->channels, avctx->bits_per_coded_sample, avctx->sample_rate, avctx->bit_rate); @@ -154,21 +154,21 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, GetByteContext gb; int i; uint8_t t; - int samples; bytestream2_init(&gb, src, blocks * s->block_size); switch (avctx->bits_per_coded_sample) { - case 16: + case 16: { #if HAVE_BIGENDIAN bytestream2_get_buffer(&gb, dst16, blocks * s->block_size); dst16 += blocks * s->block_size / 2; #else - samples = blocks * avctx->channels; + int samples = blocks * avctx->channels; do { *dst16++ = bytestream2_get_be16u(&gb); } while (--samples); #endif return dst16; + } case 20: do { for (i = s->groups_per_block; i; i--) { @@ -281,7 +281,7 @@ AVCodec ff_pcm_dvd_decoder = { .init = pcm_dvd_decode_init, .decode = pcm_dvd_decode_frame, .close = pcm_dvd_decode_uninit, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE } diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index e06712e..959c50b 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -48,16 +48,6 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx) avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8; avctx->bit_rate = avctx->block_align * avctx->sample_rate * 8; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - - return 0; -} - -static av_cold int pcm_encode_close(AVCodecContext *avctx) -{ - av_freep(&avctx->coded_frame); return 0; } @@ -347,6 +337,9 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, samples += 2; } break; + case AV_CODEC_ID_PCM_S16BE_PLANAR: + DECODE_PLANAR(16, be16, src, samples, n, 0, 0); + break; case AV_CODEC_ID_PCM_S16LE_PLANAR: DECODE_PLANAR(16, le16, src, samples, n, 0, 0); break; @@ -457,8 +450,7 @@ AVCodec ff_ ## name_ ## _encoder = { \ .id = AV_CODEC_ID_ ## id_, \ .init = pcm_encode_init, \ .encode2 = pcm_encode_frame, \ - .close = pcm_encode_close, \ - .capabilities = CODEC_CAP_VARIABLE_FRAME_SIZE, \ + .capabilities = AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \ .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ } @@ -480,7 +472,7 @@ AVCodec ff_ ## name_ ## _decoder = { \ .priv_data_size = sizeof(PCMDecode), \ .init = pcm_decode_init, \ .decode = pcm_decode_frame, \ - .capabilities = CODEC_CAP_DR1, \ + .capabilities = AV_CODEC_CAP_DR1, \ .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ } @@ -506,6 +498,7 @@ PCM_DECODER(PCM_LXF, AV_SAMPLE_FMT_S32P, pcm_lxf, "PCM signed PCM_CODEC (PCM_MULAW, AV_SAMPLE_FMT_S16, pcm_mulaw, "PCM mu-law"); PCM_CODEC (PCM_S8, AV_SAMPLE_FMT_U8, pcm_s8, "PCM signed 8-bit"); PCM_CODEC (PCM_S16BE, AV_SAMPLE_FMT_S16, pcm_s16be, "PCM signed 16-bit big-endian"); +PCM_DECODER(PCM_S16BE_PLANAR, AV_SAMPLE_FMT_S16P,pcm_s16be_planar, "PCM signed 16-bit big-endian planar"); PCM_CODEC (PCM_S16LE, AV_SAMPLE_FMT_S16, pcm_s16le, "PCM signed 16-bit little-endian"); PCM_DECODER(PCM_S16LE_PLANAR, AV_SAMPLE_FMT_S16P, pcm_s16le_planar, "PCM 16-bit little-endian planar"); PCM_CODEC (PCM_S24BE, AV_SAMPLE_FMT_S32, pcm_s24be, "PCM signed 24-bit big-endian"); diff --git a/libavcodec/pcm_tablegen.h b/libavcodec/pcm_tablegen.h index 79d6561..438c2b9 100644 --- a/libavcodec/pcm_tablegen.h +++ b/libavcodec/pcm_tablegen.h @@ -36,10 +36,7 @@ #define BIAS (0x84) /* Bias for linear code. */ -/* - * alaw2linear() - Convert an A-law value to 16-bit linear PCM - * - */ +/* alaw2linear() - Convert an A-law value to 16-bit linear PCM */ static av_cold int alaw2linear(unsigned char a_val) { int t; diff --git a/libavcodec/pcx.c b/libavcodec/pcx.c index 61c971e..a2d49b4 100644 --- a/libavcodec/pcx.c +++ b/libavcodec/pcx.c @@ -28,44 +28,42 @@ #include "get_bits.h" #include "internal.h" +#define PCX_HEADER_SIZE 128 + /** * @return advanced src pointer */ -static const uint8_t *pcx_rle_decode(const uint8_t *src, - const uint8_t *end, - uint8_t *dst, - unsigned int bytes_per_scanline, - int compressed) +static void pcx_rle_decode(GetByteContext *gb, + uint8_t *dst, + unsigned int bytes_per_scanline, + int compressed) { unsigned int i = 0; unsigned char run, value; if (compressed) { - while (i < bytes_per_scanline && src < end) { + while (i < bytes_per_scanline && bytestream2_get_bytes_left(gb)) { run = 1; - value = *src++; - if (value >= 0xc0 && src < end) { + value = bytestream2_get_byte(gb); + if (value >= 0xc0 && bytestream2_get_bytes_left(gb)) { run = value & 0x3f; - value = *src++; + value = bytestream2_get_byte(gb); } while (i < bytes_per_scanline && run--) dst[i++] = value; } } else { - memcpy(dst, src, bytes_per_scanline); - src += bytes_per_scanline; + bytestream2_get_buffer(gb, dst, bytes_per_scanline); } - - return src; } -static void pcx_palette(const uint8_t **src, uint32_t *dst, +static void pcx_palette(GetByteContext *gb, uint32_t *dst, unsigned int pallen) { unsigned int i; for (i = 0; i < pallen; i++) - *dst++ = bytestream_get_be24(src); + *dst++ = bytestream2_get_be24(gb); if (pallen < 256) memset(dst, 0, (256 - pallen) * sizeof(*dst)); } @@ -76,15 +74,19 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AVFrame *const p = data; + GetByteContext gb; int compressed, xmin, ymin, xmax, ymax; unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, bytes_per_scanline; uint8_t *ptr; - const uint8_t *buf_end = buf + buf_size; - uint8_t const *bufstart = buf; uint8_t *scanline; int ret = -1; + if (buf_size < PCX_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); + return AVERROR_INVALIDDATA; + } + if (buf[0] != 0x0a || buf[1] > 5) { av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); return AVERROR_INVALIDDATA; @@ -133,7 +135,7 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; } - buf += 128; + bytestream2_init(&gb, buf + PCX_HEADER_SIZE, buf_size - PCX_HEADER_SIZE); if ((ret = ff_set_dimensions(avctx, w, h)) < 0) return ret; @@ -148,14 +150,13 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ptr = p->data[0]; stride = p->linesize[0]; - scanline = av_malloc(bytes_per_scanline); + scanline = av_malloc(bytes_per_scanline + AV_INPUT_BUFFER_PADDING_SIZE); if (!scanline) return AVERROR(ENOMEM); if (nplanes == 3 && bits_per_pixel == 8) { for (y = 0; y < h; y++) { - buf = pcx_rle_decode(buf, buf_end, - scanline, bytes_per_scanline, compressed); + pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x = 0; x < w; x++) { ptr[3 * x] = scanline[x]; @@ -166,26 +167,12 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ptr += stride; } } else if (nplanes == 1 && bits_per_pixel == 8) { - const uint8_t *palstart = bufstart + buf_size - 769; - - if (buf_size < 769) { - av_log(avctx, AV_LOG_ERROR, "File is too short\n"); - ret = avctx->err_recognition & AV_EF_EXPLODE ? - AVERROR_INVALIDDATA : buf_size; - goto end; - } - for (y = 0; y < h; y++, ptr += stride) { - buf = pcx_rle_decode(buf, buf_end, - scanline, bytes_per_scanline, compressed); + pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); memcpy(ptr, scanline, w); } - if (buf != palstart) { - av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); - buf = palstart; - } - if (*buf++ != 12) { + if (bytestream2_get_byte(&gb) != 12) { av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); ret = avctx->err_recognition & AV_EF_EXPLODE ? AVERROR_INVALIDDATA : buf_size; @@ -197,8 +184,7 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (y = 0; y < h; y++) { init_get_bits(&s, scanline, bytes_per_scanline << 3); - buf = pcx_rle_decode(buf, buf_end, - scanline, bytes_per_scanline, compressed); + pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x = 0; x < w; x++) ptr[x] = get_bits(&s, bits_per_pixel); @@ -208,8 +194,7 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int i; for (y = 0; y < h; y++) { - buf = pcx_rle_decode(buf, buf_end, - scanline, bytes_per_scanline, compressed); + pcx_rle_decode(&gb, scanline, bytes_per_scanline, compressed); for (x = 0; x < w; x++) { int m = 0x80 >> (x & 7), v = 0; @@ -224,15 +209,22 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } if (nplanes == 1 && bits_per_pixel == 8) { - pcx_palette(&buf, (uint32_t *)p->data[1], 256); + if (bytestream2_get_bytes_left(&gb) < 768) { + av_log(avctx, AV_LOG_ERROR, "Palette truncated\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + pcx_palette(&gb, (uint32_t *)p->data[1], 256); } else if (bits_per_pixel < 8) { - const uint8_t *palette = bufstart + 16; - pcx_palette(&palette, (uint32_t *)p->data[1], 16); + GetByteContext gb1; + bytestream2_init(&gb1, avpkt->data + 16, 48); + pcx_palette(&gb1, (uint32_t *)p->data[1], 16); } *got_frame = 1; - ret = buf - bufstart; + ret = bytestream2_tell(&gb); end: av_free(scanline); return ret; @@ -244,5 +236,5 @@ AVCodec ff_pcx_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PCX, .decode = pcx_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c index 4bf7377..7fc0d9c 100644 --- a/libavcodec/pcxenc.c +++ b/libavcodec/pcxenc.c @@ -34,22 +34,16 @@ static const uint32_t monoblack_pal[16] = { 0x000000, 0xFFFFFF }; static av_cold int pcx_encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } -static av_cold int pcx_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - /** * PCX run-length encoder * @param dst output buffer @@ -68,7 +62,7 @@ static int pcx_rle_encode( uint8_t *dst, int dst_size, // check worst-case upper bound on dst_size if (dst_size < 2LL * src_plane_size * nplanes || src_plane_size <= 0) - return -1; + return AVERROR(EINVAL); for (p = 0; p < nplanes; p++) { int count = 1; @@ -112,7 +106,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (avctx->width > 65535 || avctx->height > 65535) { av_log(avctx, AV_LOG_ERROR, "image dimensions do not fit in 16 bits\n"); - return -1; + return AVERROR(EINVAL); } switch (avctx->pix_fmt) { @@ -137,7 +131,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, break; default: av_log(avctx, AV_LOG_ERROR, "unsupported pixfmt\n"); - return -1; + return AVERROR(EINVAL); } line_bytes = (avctx->width * bpp + 7) >> 3; @@ -176,7 +170,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if ((written = pcx_rle_encode(buf, buf_end - buf, src, line_bytes, nplanes)) < 0) { av_log(avctx, AV_LOG_ERROR, "buffer too small\n"); - return -1; + return AVERROR_BUG; } buf += written; src += frame->linesize[0]; @@ -185,7 +179,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (nplanes == 1 && bpp == 8) { if (buf_end - buf < 257) { av_log(avctx, AV_LOG_ERROR, "buffer too small\n"); - return -1; + return AVERROR_BUG; } bytestream_put_byte(&buf, 12); for (i = 0; i < 256; i++) { @@ -206,7 +200,6 @@ AVCodec ff_pcx_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PCX, .init = pcx_encode_init, - .close = pcx_encode_close, .encode2 = pcx_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 6217c40..886685b 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -163,9 +163,9 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitleRect *rect, rle_bitmap_end = buf + buf_size; - rect->pict.data[0] = av_malloc(rect->w * rect->h); + rect->data[0] = av_malloc(rect->w * rect->h); - if (!rect->pict.data[0]) + if (!rect->data[0]) return AVERROR(ENOMEM); pixel_count = 0; @@ -187,7 +187,7 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitleRect *rect, } if (run > 0 && pixel_count + run <= rect->w * rect->h) { - memset(rect->pict.data[0] + pixel_count, color, run); + memset(rect->data[0] + pixel_count, color, run); pixel_count += run; } else if (!run) { /* @@ -210,7 +210,7 @@ static int decode_rle(AVCodecContext *avctx, AVSubtitleRect *rect, return AVERROR_INVALIDDATA; } - av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, rect->w * rect->h); + ff_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, rect->w * rect->h); return 0; } @@ -351,10 +351,16 @@ static int parse_palette_segment(AVCodecContext *avctx, cb = bytestream_get_byte(&buf); alpha = bytestream_get_byte(&buf); - YUV_TO_RGB1(cb, cr); - YUV_TO_RGB2(r, g, b, y); + /* Default to BT.709 colorspace. In case of <= 576 height use BT.601 */ + if (avctx->height <= 0 || avctx->height > 576) { + YUV_TO_RGB1_CCIR_BT709(cb, cr); + } else { + YUV_TO_RGB1_CCIR(cb, cr); + } + + YUV_TO_RGB2_CCIR(r, g, b, y); - av_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); + ff_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); /* Store color in palette */ palette->clut[color_id] = RGBA(r,g,b,alpha); @@ -387,7 +393,7 @@ static int parse_presentation_segment(AVCodecContext *avctx, ctx->presentation.pts = pts; - av_dlog(avctx, "Video Dimensions %dx%d\n", + ff_dlog(avctx, "Video Dimensions %dx%d\n", w, h); ret = ff_set_dimensions(avctx, w, h); if (ret < 0) @@ -445,7 +451,7 @@ static int parse_presentation_segment(AVCodecContext *avctx, ctx->presentation.objects[i].crop_h = bytestream_get_be16(&buf); } - av_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", + ff_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", ctx->presentation.objects[i].x, ctx->presentation.objects[i].y); if (ctx->presentation.objects[i].x > avctx->width || @@ -539,7 +545,7 @@ static int display_end_segment(AVCodecContext *avctx, void *data, sub->rects[i]->w = object->w; sub->rects[i]->h = object->h; - sub->rects[i]->pict.linesize[0] = object->w; + sub->rects[i]->linesize[0] = object->w; if (object->rle) { if (object->rle_remaining_len) { @@ -564,13 +570,27 @@ static int display_end_segment(AVCodecContext *avctx, void *data, } /* Allocate memory for colors */ sub->rects[i]->nb_colors = 256; - sub->rects[i]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[i]->pict.data[1]) { + sub->rects[i]->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!sub->rects[i]->data[1]) { avsubtitle_free(sub); return AVERROR(ENOMEM); } - memcpy(sub->rects[i]->pict.data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS +{ + AVSubtitleRect *rect; + int j; + rect = sub->rects[i]; + for (j = 0; j < 4; j++) { + rect->pict.data[j] = rect->data[j]; + rect->pict.linesize[j] = rect->linesize[j]; + } +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + memcpy(sub->rects[i]->data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); } return 1; @@ -587,16 +607,16 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, int segment_length; int i, ret; - av_dlog(avctx, "PGS sub packet:\n"); + ff_dlog(avctx, "PGS sub packet:\n"); for (i = 0; i < buf_size; i++) { - av_dlog(avctx, "%02x ", buf[i]); + ff_dlog(avctx, "%02x ", buf[i]); if (i % 16 == 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); } if (i & 15) - av_dlog(avctx, "\n"); + ff_dlog(avctx, "\n"); *data_size = 0; @@ -611,7 +631,7 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, segment_type = bytestream_get_byte(&buf); segment_length = bytestream_get_be16(&buf); - av_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type); + ff_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type); if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf) break; diff --git a/libavcodec/pictordec.c b/libavcodec/pictordec.c index 33c4545..9477bc4 100644 --- a/libavcodec/pictordec.c +++ b/libavcodec/pictordec.c @@ -249,5 +249,5 @@ AVCodec ff_pictor_decoder = { .id = AV_CODEC_ID_PICTOR, .priv_data_size = sizeof(PicContext), .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 2790bf4..a6ab665 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -18,7 +18,11 @@ * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "libavutil/avstring.h" #include "libavutil/imgutils.h" +#include "libavutil/stereo3d.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -414,10 +418,23 @@ static int decode_frame(AVCodecContext *avctx, int ret; /* check signature */ - if (buf_size < 8 || - memcmp(buf, ff_pngsig, 8) != 0 && - memcmp(buf, ff_mngsig, 8) != 0) - return -1; + if (buf_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Not enough data %d\n", + buf_size); + return AVERROR_INVALIDDATA; + } + if (memcmp(buf, ff_pngsig, 8) != 0 && + memcmp(buf, ff_mngsig, 8) != 0) { + char signature[5 * 8 + 1] = { 0 }; + int i; + for (i = 0; i < 8; i++) { + av_strlcatf(signature + i * 5, sizeof(signature) - i * 5, + " 0x%02x", buf[i]); + } + av_log(avctx, AV_LOG_ERROR, "Invalid PNG signature %s\n", + signature); + return AVERROR_INVALIDDATA; + } bytestream2_init(&s->gb, buf + 8, buf_size - 8); s->y = s->state = 0; @@ -436,7 +453,7 @@ static int decode_frame(AVCodecContext *avctx, if (length > 0x7fffffff) goto fail; tag = bytestream2_get_le32(&s->gb); - av_dlog(avctx, "png: tag=%c%c%c%c length=%u\n", + ff_dlog(avctx, "png: tag=%c%c%c%c length=%u\n", (tag & 0xff), ((tag >> 8) & 0xff), ((tag >> 16) & 0xff), @@ -458,7 +475,7 @@ static int decode_frame(AVCodecContext *avctx, s->interlace_type = bytestream2_get_byte(&s->gb); bytestream2_skip(&s->gb, 4); /* crc */ s->state |= PNG_IHDR; - av_dlog(avctx, "width=%d height=%d depth=%d color_type=%d " + ff_dlog(avctx, "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); @@ -525,7 +542,7 @@ static int decode_frame(AVCodecContext *avctx, s->width); s->crow_size = s->pass_row_size + 1; } - av_dlog(avctx, "row_size=%d crow_size =%d\n", + ff_dlog(avctx, "row_size=%d crow_size =%d\n", s->row_size, s->crow_size); s->image_buf = p->data[0]; s->image_linesize = p->linesize[0]; @@ -593,6 +610,22 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&s->gb, 4); /* crc */ } break; + case MKTAG('s', 'T', 'E', 'R'): { + int mode = bytestream2_get_byte(&s->gb); + AVStereo3D *stereo3d = av_stereo3d_create_side_data(p); + if (!stereo3d) + goto the_end; + + if (mode == 0 || mode == 1) { + stereo3d->type = AV_STEREO3D_SIDEBYSIDE; + stereo3d->flags = mode ? 0 : AV_STEREO3D_FLAG_INVERT; + } else { + av_log(avctx, AV_LOG_WARNING, + "Unknown value in sTER chunk (%d)\n", mode); + } + bytestream2_skip(&s->gb, 4); /* crc */ + break; + } case MKTAG('I', 'E', 'N', 'D'): if (!(s->state & PNG_ALLIMAGE)) goto fail; @@ -606,7 +639,7 @@ skip_tag: } } exit_loop: - /* handle p-frames only if a predecessor frame is available */ + /* handle P-frames only if a predecessor frame is available */ if (s->prev->data[0]) { if (!(avpkt->flags & AV_PKT_FLAG_KEY)) { int i, j; @@ -674,5 +707,5 @@ AVCodec ff_png_decoder = { .init = png_dec_init, .close = png_dec_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/, + .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, }; diff --git a/libavcodec/pngdsp.h b/libavcodec/pngdsp.h index 98d29a8..607fe64 100644 --- a/libavcodec/pngdsp.h +++ b/libavcodec/pngdsp.h @@ -37,4 +37,4 @@ typedef struct PNGDSPContext { void ff_pngdsp_init(PNGDSPContext *dsp); void ff_pngdsp_init_x86(PNGDSPContext *dsp); -#endif /* AVCDODEC_PNGDSP_H */ +#endif /* AVCODEC_PNGDSP_H */ diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 3d11f37..f91c54c 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" +#include "libavutil/stereo3d.h" + #include "avcodec.h" #include "bytestream.h" #include "huffyuvencdsp.h" @@ -33,6 +36,7 @@ #define IOBUF_SIZE 4096 typedef struct PNGEncContext { + AVClass *class; HuffYUVEncDSPContext hdsp; uint8_t *bytestream; @@ -233,6 +237,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { PNGEncContext *s = avctx->priv_data; + AVFrameSideData *side_data; const AVFrame *const p = pict; int bit_depth, color_type, y, len, row_size, ret, is_progressive; int bits_per_pixel, pass_row_size, enc_row_size, max_packet_size; @@ -243,7 +248,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, uint8_t *rgba_buf = NULL; uint8_t *top_buf = NULL; - is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); + is_progressive = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT); switch (avctx->pix_fmt) { case AV_PIX_FMT_RGBA64BE: bit_depth = 16; @@ -297,7 +302,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, enc_row_size = deflateBound(&s->zstream, row_size); max_packet_size = avctx->height * (enc_row_size + ((enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) * 12) - + FF_MIN_BUFFER_SIZE; + + AV_INPUT_BUFFER_MIN_SIZE; if (!pkt->data && (ret = av_new_packet(pkt, max_packet_size)) < 0) { av_log(avctx, AV_LOG_ERROR, "Could not allocate output packet of size %d.\n", @@ -371,6 +376,25 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } } + /* write stereoscopic information */ + side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_STEREO3D); + if (side_data) { + AVStereo3D *stereo3d = (AVStereo3D *)side_data->data; + uint8_t sm; + switch (stereo3d->type) { + case AV_STEREO3D_SIDEBYSIDE: + sm = !(stereo3d->flags & AV_STEREO3D_FLAG_INVERT); + png_write_chunk(&s->bytestream, MKTAG('s', 'T', 'E', 'R'), &sm, 1); + break; + case AV_STEREO3D_2D: + break; + default: + av_log(avctx, AV_LOG_WARNING, + "Only side-by-side stereo3d flag can be defined within sTER chunk\n"); + break; + } + } + /* now put each row */ s->zstream.avail_out = IOBUF_SIZE; s->zstream.next_out = s->buf; @@ -455,38 +479,58 @@ static av_cold int png_enc_init(AVCodecContext *avctx) { PNGEncContext *s = avctx->priv_data; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ff_huffyuvencdsp_init(&s->hdsp); - s->filter_type = av_clip(avctx->prediction_method, - PNG_FILTER_VALUE_NONE, - PNG_FILTER_VALUE_MIXED); +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->prediction_method) + s->filter_type = av_clip(avctx->prediction_method, + PNG_FILTER_VALUE_NONE, + PNG_FILTER_VALUE_MIXED); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) s->filter_type = PNG_FILTER_VALUE_NONE; return 0; } -static av_cold int png_enc_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} +#define OFFSET(x) offsetof(PNGEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +{ "pred", "Prediction method", OFFSET(filter_type), AV_OPT_TYPE_INT, { .i64 = PNG_FILTER_VALUE_NONE }, PNG_FILTER_VALUE_NONE, PNG_FILTER_VALUE_MIXED, VE, "pred" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_NONE }, INT_MIN, INT_MAX, VE, "pred" }, + { "sub", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_SUB }, INT_MIN, INT_MAX, VE, "pred" }, + { "up", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_UP }, INT_MIN, INT_MAX, VE, "pred" }, + { "avg", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_AVG }, INT_MIN, INT_MAX, VE, "pred" }, + { "paeth", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_PAETH }, INT_MIN, INT_MAX, VE, "pred" }, + { "mixed", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_MIXED }, INT_MIN, INT_MAX, VE, "pred" }, + + { NULL}, +}; +static const AVClass png_class = { + .class_name = "png", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_png_encoder = { .name = "png", .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PNG, .priv_data_size = sizeof(PNGEncContext), + .priv_class = &png_class, .init = png_enc_init, - .close = png_enc_close, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, diff --git a/libavcodec/pnm_parser.c b/libavcodec/pnm_parser.c index 2e00c0a..03d2da9 100644 --- a/libavcodec/pnm_parser.c +++ b/libavcodec/pnm_parser.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" + #include "parser.h" //for ParseContext #include "pnm.h" @@ -54,19 +56,10 @@ retry: } 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); + + av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); if (pnmctx.bytestream_start != buf) next -= pc->index; if (next > buf_size) diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index 9074d9b..d23e2c0 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -235,7 +235,7 @@ AVCodec ff_pgm_decoder = { .id = AV_CODEC_ID_PGM, .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -247,7 +247,7 @@ AVCodec ff_pgmyuv_decoder = { .id = AV_CODEC_ID_PGMYUV, .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -259,7 +259,7 @@ AVCodec ff_ppm_decoder = { .id = AV_CODEC_ID_PPM, .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -271,7 +271,7 @@ AVCodec ff_pbm_decoder = { .id = AV_CODEC_ID_PBM, .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif @@ -283,6 +283,6 @@ AVCodec ff_pam_decoder = { .id = AV_CODEC_ID_PAM, .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c index 7513552..f8c600f 100644 --- a/libavcodec/pnmenc.c +++ b/libavcodec/pnmenc.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" @@ -31,10 +32,10 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame * const p = pict; int i, h, h1, c, n, linesize, ret; uint8_t *ptr, *ptr1, *ptr2; + int size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); - if ((ret = ff_alloc_packet(pkt, avpicture_get_size(avctx->pix_fmt, - avctx->width, - avctx->height) + 200)) < 0) { + if ((ret = ff_alloc_packet(pkt, size + 200)) < 0) { av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); return ret; } @@ -83,7 +84,7 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, "P%c\n%d %d\n", c, avctx->width, h1); bytestream += strlen(bytestream); if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE) { - int maxdepth = (1 << (av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1)) - 1; + int maxdepth = (1 << av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth) - 1; snprintf(bytestream, bytestream_end - bytestream, "%d\n", maxdepth); bytestream += strlen(bytestream); @@ -120,22 +121,16 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int pnm_encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } -static av_cold int pnm_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - #if CONFIG_PGM_ENCODER AVCodec ff_pgm_encoder = { .name = "pgm", @@ -143,7 +138,6 @@ AVCodec ff_pgm_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PGM, .init = pnm_encode_init, - .close = pnm_encode_close, .encode2 = pnm_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE @@ -158,7 +152,6 @@ AVCodec ff_pgmyuv_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PGMYUV, .init = pnm_encode_init, - .close = pnm_encode_close, .encode2 = pnm_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE @@ -173,7 +166,6 @@ AVCodec ff_ppm_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PPM, .init = pnm_encode_init, - .close = pnm_encode_close, .encode2 = pnm_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE @@ -188,7 +180,6 @@ AVCodec ff_pbm_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PBM, .init = pnm_encode_init, - .close = pnm_encode_close, .encode2 = pnm_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, diff --git a/libavcodec/ppc/Makefile b/libavcodec/ppc/Makefile index c6ff0f1..9234e77 100644 --- a/libavcodec/ppc/Makefile +++ b/libavcodec/ppc/Makefile @@ -1,30 +1,30 @@ -OBJS += ppc/fmtconvert_altivec.o \ - # subsystems OBJS-$(CONFIG_AUDIODSP) += ppc/audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += ppc/blockdsp.o OBJS-$(CONFIG_FFT) += ppc/fft_init.o \ ppc/fft_altivec.o +OBJS-$(CONFIG_FDCTDSP) += ppc/fdctdsp.o +OBJS-$(CONFIG_FMTCONVERT) += ppc/fmtconvert_altivec.o OBJS-$(CONFIG_H264CHROMA) += ppc/h264chroma_init.o OBJS-$(CONFIG_H264DSP) += ppc/h264dsp.o OBJS-$(CONFIG_H264QPEL) += ppc/h264qpel.o OBJS-$(CONFIG_HPELDSP) += ppc/hpeldsp_altivec.o OBJS-$(CONFIG_HUFFYUVDSP) += ppc/huffyuvdsp_altivec.o -OBJS-$(CONFIG_FDCTDSP) += ppc/fdctdsp.o OBJS-$(CONFIG_IDCTDSP) += ppc/idctdsp.o +OBJS-$(CONFIG_MDCT) += ppc/mdct_init.o OBJS-$(CONFIG_ME_CMP) += ppc/me_cmp.o OBJS-$(CONFIG_MPEGAUDIODSP) += ppc/mpegaudiodsp_altivec.o OBJS-$(CONFIG_MPEGVIDEO) += ppc/mpegvideo_altivec.o \ ppc/mpegvideodsp.o OBJS-$(CONFIG_MPEGVIDEOENC) += ppc/mpegvideoencdsp.o OBJS-$(CONFIG_PIXBLOCKDSP) += ppc/pixblockdsp.o +OBJS-$(CONFIG_VC1DSP) += ppc/vc1dsp_altivec.o OBJS-$(CONFIG_VIDEODSP) += ppc/videodsp_ppc.o OBJS-$(CONFIG_VP3DSP) += ppc/vp3dsp_altivec.o +OBJS-$(CONFIG_VP8DSP) += ppc/vp8dsp_altivec.o # decoders/encoders OBJS-$(CONFIG_APE_DECODER) += ppc/apedsp_altivec.o OBJS-$(CONFIG_SVQ1_ENCODER) += ppc/svq1enc_altivec.o -OBJS-$(CONFIG_VC1_DECODER) += ppc/vc1dsp_altivec.o OBJS-$(CONFIG_VORBIS_DECODER) += ppc/vorbisdsp_altivec.o OBJS-$(CONFIG_VP7_DECODER) += ppc/vp8dsp_altivec.o -OBJS-$(CONFIG_VP8_DECODER) += ppc/vp8dsp_altivec.o diff --git a/libavcodec/ppc/apedsp_altivec.c b/libavcodec/ppc/apedsp_altivec.c index d8bf4bd..3b9d045 100644 --- a/libavcodec/ppc/apedsp_altivec.c +++ b/libavcodec/ppc/apedsp_altivec.c @@ -29,7 +29,7 @@ #include "libavutil/ppc/types_altivec.h" #include "libavcodec/apedsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, const int16_t *v2, const int16_t *v3, @@ -73,7 +73,7 @@ static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, av_cold void ff_apedsp_init_ppc(APEDSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/audiodsp.c b/libavcodec/ppc/audiodsp.c index 36506ce..2a0a6d8 100644 --- a/libavcodec/ppc/audiodsp.c +++ b/libavcodec/ppc/audiodsp.c @@ -35,7 +35,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/audiodsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, int order) @@ -63,7 +63,7 @@ static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, av_cold void ff_audiodsp_init_ppc(AudioDSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/fdctdsp.c b/libavcodec/ppc/fdctdsp.c index 51417a5..89ceb47 100644 --- a/libavcodec/ppc/fdctdsp.c +++ b/libavcodec/ppc/fdctdsp.c @@ -29,7 +29,7 @@ #include "libavcodec/fdctdsp.h" #include "fdct.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define vs16(v) ((vector signed short) (v)) #define vs32(v) ((vector signed int) (v)) @@ -465,7 +465,7 @@ void ff_fdct_altivec(int16_t *block) av_cold void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/fft_altivec.S b/libavcodec/ppc/fft_altivec.S index c92b30b..cb7c871 100644 --- a/libavcodec/ppc/fft_altivec.S +++ b/libavcodec/ppc/fft_altivec.S @@ -40,7 +40,7 @@ #include "config.h" -#if HAVE_GNU_AS && HAVE_ALTIVEC +#if HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN #include "asm.S" @@ -451,4 +451,4 @@ fft_dispatch_tab\suffix\()_altivec: DECL_FFTS 0 DECL_FFTS 1, _interleave -#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */ +#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */ diff --git a/libavcodec/ppc/fft_init.c b/libavcodec/ppc/fft_init.c index 8fcc033..56eafb9 100644 --- a/libavcodec/ppc/fft_init.c +++ b/libavcodec/ppc/fft_init.c @@ -1,8 +1,4 @@ /* - * FFT/IFFT transforms - * AltiVec-enabled - * Copyright (c) 2009 Loren Merritt - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -21,136 +17,20 @@ */ #include "config.h" + #include "libavutil/cpu.h" #include "libavutil/ppc/cpu.h" -#include "libavutil/ppc/types_altivec.h" -#include "libavutil/ppc/util_altivec.h" -#include "libavcodec/fft.h" -/** - * Do a complex FFT with the parameters defined in ff_fft_init(). - * The input data must be permuted before with s->revtab table. - * No 1.0 / sqrt(n) normalization is done. - * AltiVec-enabled: - * This code assumes that the 'z' pointer is 16 bytes-aligned. - * It also assumes all FFTComplex are 8 bytes-aligned pairs of floats. - */ +#include "libavcodec/fft.h" -void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); void ff_fft_calc_interleave_altivec(FFTContext *s, FFTComplex *z); -#if HAVE_GNU_AS && HAVE_ALTIVEC -static void imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) -{ - int j, k; - int n = 1 << s->mdct_bits; - int n4 = n >> 2; - int n8 = n >> 3; - int n32 = n >> 5; - const uint16_t *revtabj = s->revtab; - const uint16_t *revtabk = s->revtab+n4; - const vec_f *tcos = (const vec_f*)(s->tcos+n8); - const vec_f *tsin = (const vec_f*)(s->tsin+n8); - const vec_f *pin = (const vec_f*)(input+n4); - vec_f *pout = (vec_f*)(output+n4); - - /* pre rotation */ - k = n32-1; - do { - vec_f cos,sin,cos0,sin0,cos1,sin1,re,im,r0,i0,r1,i1,a,b,c,d; -#define CMULA(p,o0,o1,o2,o3)\ - a = pin[ k*2+p]; /* { z[k].re, z[k].im, z[k+1].re, z[k+1].im } */\ - b = pin[-k*2-p-1]; /* { z[-k-2].re, z[-k-2].im, z[-k-1].re, z[-k-1].im } */\ - re = vec_perm(a, b, vcprm(0,2,s0,s2)); /* { z[k].re, z[k+1].re, z[-k-2].re, z[-k-1].re } */\ - im = vec_perm(a, b, vcprm(s3,s1,3,1)); /* { z[-k-1].im, z[-k-2].im, z[k+1].im, z[k].im } */\ - cos = vec_perm(cos0, cos1, vcprm(o0,o1,s##o2,s##o3)); /* { cos[k], cos[k+1], cos[-k-2], cos[-k-1] } */\ - sin = vec_perm(sin0, sin1, vcprm(o0,o1,s##o2,s##o3));\ - r##p = im*cos - re*sin;\ - i##p = re*cos + im*sin; -#define STORE2(v,dst)\ - j = dst;\ - vec_ste(v, 0, output+j*2);\ - vec_ste(v, 4, output+j*2); -#define STORE8(p)\ - a = vec_perm(r##p, i##p, vcprm(0,s0,0,s0));\ - b = vec_perm(r##p, i##p, vcprm(1,s1,1,s1));\ - c = vec_perm(r##p, i##p, vcprm(2,s2,2,s2));\ - d = vec_perm(r##p, i##p, vcprm(3,s3,3,s3));\ - STORE2(a, revtabk[ p*2-4]);\ - STORE2(b, revtabk[ p*2-3]);\ - STORE2(c, revtabj[-p*2+2]);\ - STORE2(d, revtabj[-p*2+3]); - - cos0 = tcos[k]; - sin0 = tsin[k]; - cos1 = tcos[-k-1]; - sin1 = tsin[-k-1]; - CMULA(0, 0,1,2,3); - CMULA(1, 2,3,0,1); - STORE8(0); - STORE8(1); - revtabj += 4; - revtabk -= 4; - k--; - } while(k >= 0); - - ff_fft_calc_altivec(s, (FFTComplex*)output); - - /* post rotation + reordering */ - j = -n32; - k = n32-1; - do { - vec_f cos,sin,re,im,a,b,c,d; -#define CMULB(d0,d1,o)\ - re = pout[o*2];\ - im = pout[o*2+1];\ - cos = tcos[o];\ - sin = tsin[o];\ - d0 = im*sin - re*cos;\ - d1 = re*sin + im*cos; - - CMULB(a,b,j); - CMULB(c,d,k); - pout[2*j] = vec_perm(a, d, vcprm(0,s3,1,s2)); - pout[2*j+1] = vec_perm(a, d, vcprm(2,s1,3,s0)); - pout[2*k] = vec_perm(c, b, vcprm(0,s3,1,s2)); - pout[2*k+1] = vec_perm(c, b, vcprm(2,s1,3,s0)); - j++; - k--; - } while(k >= 0); -} - -static void imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) -{ - int k; - int n = 1 << s->mdct_bits; - int n4 = n >> 2; - int n16 = n >> 4; - vec_u32 sign = {1U<<31,1U<<31,1U<<31,1U<<31}; - vec_u32 *p0 = (vec_u32*)(output+n4); - vec_u32 *p1 = (vec_u32*)(output+n4*3); - - imdct_half_altivec(s, output + n4, input); - - for (k = 0; k < n16; k++) { - vec_u32 a = p0[k] ^ sign; - vec_u32 b = p1[-k-1]; - p0[-k-1] = vec_perm(a, a, vcprm(3,2,1,0)); - p1[k] = vec_perm(b, b, vcprm(3,2,1,0)); - } -} -#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */ - av_cold void ff_fft_init_ppc(FFTContext *s) { -#if HAVE_GNU_AS && HAVE_ALTIVEC +#if HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; s->fft_calc = ff_fft_calc_interleave_altivec; - if (s->mdct_bits >= 5) { - s->imdct_calc = imdct_calc_altivec; - s->imdct_half = imdct_half_altivec; - } -#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */ +#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */ } diff --git a/libavcodec/ppc/fmtconvert_altivec.c b/libavcodec/ppc/fmtconvert_altivec.c index 14aaf6b..796c431 100644 --- a/libavcodec/ppc/fmtconvert_altivec.c +++ b/libavcodec/ppc/fmtconvert_altivec.c @@ -26,7 +26,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/fmtconvert.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static void int32_to_float_fmul_scalar_altivec(float *dst, const int32_t *src, float mul, int len) @@ -52,126 +52,15 @@ static void int32_to_float_fmul_scalar_altivec(float *dst, const int32_t *src, } } - -static vector signed short float_to_int16_one_altivec(const float *src) -{ - vector float s0 = vec_ld(0, src); - vector float s1 = vec_ld(16, src); - vector signed int t0 = vec_cts(s0, 0); - vector signed int t1 = vec_cts(s1, 0); - return vec_packs(t0,t1); -} - -static void float_to_int16_altivec(int16_t *dst, const float *src, long len) -{ - int i; - vector signed short d0, d1, d; - vector unsigned char align; - if (((long)dst) & 15) { //FIXME - for (i = 0; i < len - 7; i += 8) { - d0 = vec_ld(0, dst+i); - d = float_to_int16_one_altivec(src + i); - d1 = vec_ld(15, dst+i); - d1 = vec_perm(d1, d0, vec_lvsl(0, dst + i)); - align = vec_lvsr(0, dst + i); - d0 = vec_perm(d1, d, align); - d1 = vec_perm(d, d1, align); - vec_st(d0, 0, dst + i); - vec_st(d1, 15, dst + i); - } - } else { - for (i = 0; i < len - 7; i += 8) { - d = float_to_int16_one_altivec(src + i); - vec_st(d, 0, dst + i); - } - } -} - -#define VSTE_INC(dst, v, elem, inc) do { \ - vector signed short s = vec_splat(v, elem); \ - vec_ste(s, 0, dst); \ - dst += inc; \ - } while (0) - -static void float_to_int16_stride_altivec(int16_t *dst, const float *src, - long len, int stride) -{ - int i; - vector signed short d; - - for (i = 0; i < len - 7; i += 8) { - d = float_to_int16_one_altivec(src + i); - VSTE_INC(dst, d, 0, stride); - VSTE_INC(dst, d, 1, stride); - VSTE_INC(dst, d, 2, stride); - VSTE_INC(dst, d, 3, stride); - VSTE_INC(dst, d, 4, stride); - VSTE_INC(dst, d, 5, stride); - VSTE_INC(dst, d, 6, stride); - VSTE_INC(dst, d, 7, stride); - } -} - -static void float_to_int16_interleave_altivec(int16_t *dst, const float **src, - long len, int channels) -{ - int i; - vector signed short d0, d1, d2, c0, c1, t0, t1; - vector unsigned char align; - - if (channels == 1) - float_to_int16_altivec(dst, src[0], len); - else { - if (channels == 2) { - if (((long)dst) & 15) { - for (i = 0; i < len - 7; i += 8) { - d0 = vec_ld(0, dst + i); - t0 = float_to_int16_one_altivec(src[0] + i); - d1 = vec_ld(31, dst + i); - t1 = float_to_int16_one_altivec(src[1] + i); - c0 = vec_mergeh(t0, t1); - c1 = vec_mergel(t0, t1); - d2 = vec_perm(d1, d0, vec_lvsl(0, dst + i)); - align = vec_lvsr(0, dst + i); - d0 = vec_perm(d2, c0, align); - d1 = vec_perm(c0, c1, align); - vec_st(d0, 0, dst + i); - d0 = vec_perm(c1, d2, align); - vec_st(d1, 15, dst + i); - vec_st(d0, 31, dst + i); - dst += 8; - } - } else { - for (i = 0; i < len - 7; i += 8) { - t0 = float_to_int16_one_altivec(src[0] + i); - t1 = float_to_int16_one_altivec(src[1] + i); - d0 = vec_mergeh(t0, t1); - d1 = vec_mergel(t0, t1); - vec_st(d0, 0, dst + i); - vec_st(d1, 16, dst + i); - dst += 8; - } - } - } else { - for (i = 0; i < channels; i++) - float_to_int16_stride_altivec(dst + i, src[i], len, channels); - } - } -} - #endif /* HAVE_ALTIVEC */ av_cold void ff_fmt_convert_init_ppc(FmtConvertContext *c, AVCodecContext *avctx) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_altivec; - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->float_to_int16 = float_to_int16_altivec; - c->float_to_int16_interleave = float_to_int16_interleave_altivec; - } #endif /* HAVE_ALTIVEC */ } diff --git a/libavcodec/ppc/h264chroma_init.c b/libavcodec/ppc/h264chroma_init.c index 6d656d4..178f239 100644 --- a/libavcodec/ppc/h264chroma_init.c +++ b/libavcodec/ppc/h264chroma_init.c @@ -27,7 +27,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/h264chroma.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define PUT_OP_U8_ALTIVEC(d, s, dst) d = s #define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s) @@ -50,7 +50,7 @@ av_cold void ff_h264chroma_init_ppc(H264ChromaContext *c, int bit_depth) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN const int high_bit_depth = bit_depth > 8; if (!PPC_ALTIVEC(av_get_cpu_flags())) diff --git a/libavcodec/ppc/h264dsp.c b/libavcodec/ppc/h264dsp.c index 31dc141..0538dbc 100644 --- a/libavcodec/ppc/h264dsp.c +++ b/libavcodec/ppc/h264dsp.c @@ -19,16 +19,22 @@ */ #include "config.h" + +#include +#include + #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/types_altivec.h" #include "libavutil/ppc/util_altivec.h" -#include "libavcodec/h264data.h" + +#include "libavcodec/h264dec.h" #include "libavcodec/h264dsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN /**************************************************************************** * IDCT transform: @@ -745,7 +751,7 @@ H264_WEIGHT( 8) av_cold void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth, const int chroma_format_idc) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/h264qpel.c b/libavcodec/ppc/h264qpel.c index f840277..92c86f3 100644 --- a/libavcodec/ppc/h264qpel.c +++ b/libavcodec/ppc/h264qpel.c @@ -28,7 +28,7 @@ #include "libavcodec/h264qpel.h" #include "hpeldsp_altivec.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define PUT_OP_U8_ALTIVEC(d, s, dst) d = s #define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s) @@ -286,7 +286,7 @@ H264_MC(avg_, 16, altivec) av_cold void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN const int high_bit_depth = bit_depth > 8; if (!PPC_ALTIVEC(av_get_cpu_flags())) diff --git a/libavcodec/ppc/hpeldsp_altivec.c b/libavcodec/ppc/hpeldsp_altivec.c index fd6ae73..780240b 100644 --- a/libavcodec/ppc/hpeldsp_altivec.c +++ b/libavcodec/ppc/hpeldsp_altivec.c @@ -34,7 +34,7 @@ #include "libavcodec/hpeldsp.h" #include "hpeldsp_altivec.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN /* next one assumes that ((line_size % 16) == 0) */ void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { @@ -449,7 +449,7 @@ static void avg_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, ptrdi av_cold void ff_hpeldsp_init_ppc(HpelDSPContext *c, int flags) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/huffyuvdsp_altivec.c b/libavcodec/ppc/huffyuvdsp_altivec.c index 7c34a67..4c16283 100644 --- a/libavcodec/ppc/huffyuvdsp_altivec.c +++ b/libavcodec/ppc/huffyuvdsp_altivec.c @@ -32,7 +32,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/huffyuvdsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w) { register int i; @@ -53,7 +53,7 @@ static void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w) av_cold void ff_huffyuvdsp_init_ppc(HuffYUVDSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/idctdsp.c b/libavcodec/ppc/idctdsp.c index 17f7dbb..c85b58e 100644 --- a/libavcodec/ppc/idctdsp.c +++ b/libavcodec/ppc/idctdsp.c @@ -43,7 +43,7 @@ #include "libavutil/ppc/types_altivec.h" #include "libavcodec/idctdsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define IDCT_HALF \ /* 1st stage */ \ @@ -230,7 +230,7 @@ static void idct_add_altivec(uint8_t *dest, int stride, int16_t *blk) av_cold void ff_idctdsp_init_ppc(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/mdct_init.c b/libavcodec/ppc/mdct_init.c new file mode 100644 index 0000000..d3582bc --- /dev/null +++ b/libavcodec/ppc/mdct_init.c @@ -0,0 +1,154 @@ +/* + * FFT/IFFT transforms + * AltiVec-enabled + * Copyright (c) 2009 Loren Merritt + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/fft.h" + +/** + * Do a complex FFT with the parameters defined in ff_fft_init(). + * The input data must be permuted before with s->revtab table. + * No 1.0 / sqrt(n) normalization is done. + * AltiVec-enabled: + * This code assumes that the 'z' pointer is 16 bytes-aligned. + * It also assumes all FFTComplex are 8 bytes-aligned pairs of floats. + */ + +void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); + +#if HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN +static void imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int j, k; + int n = 1 << s->mdct_bits; + int n4 = n >> 2; + int n8 = n >> 3; + int n32 = n >> 5; + const uint16_t *revtabj = s->revtab; + const uint16_t *revtabk = s->revtab+n4; + const vec_f *tcos = (const vec_f*)(s->tcos+n8); + const vec_f *tsin = (const vec_f*)(s->tsin+n8); + const vec_f *pin = (const vec_f*)(input+n4); + vec_f *pout = (vec_f*)(output+n4); + + /* pre rotation */ + k = n32-1; + do { + vec_f cos,sin,cos0,sin0,cos1,sin1,re,im,r0,i0,r1,i1,a,b,c,d; +#define CMULA(p,o0,o1,o2,o3)\ + a = pin[ k*2+p]; /* { z[k].re, z[k].im, z[k+1].re, z[k+1].im } */\ + b = pin[-k*2-p-1]; /* { z[-k-2].re, z[-k-2].im, z[-k-1].re, z[-k-1].im } */\ + re = vec_perm(a, b, vcprm(0,2,s0,s2)); /* { z[k].re, z[k+1].re, z[-k-2].re, z[-k-1].re } */\ + im = vec_perm(a, b, vcprm(s3,s1,3,1)); /* { z[-k-1].im, z[-k-2].im, z[k+1].im, z[k].im } */\ + cos = vec_perm(cos0, cos1, vcprm(o0,o1,s##o2,s##o3)); /* { cos[k], cos[k+1], cos[-k-2], cos[-k-1] } */\ + sin = vec_perm(sin0, sin1, vcprm(o0,o1,s##o2,s##o3));\ + r##p = im*cos - re*sin;\ + i##p = re*cos + im*sin; +#define STORE2(v,dst)\ + j = dst;\ + vec_ste(v, 0, output+j*2);\ + vec_ste(v, 4, output+j*2); +#define STORE8(p)\ + a = vec_perm(r##p, i##p, vcprm(0,s0,0,s0));\ + b = vec_perm(r##p, i##p, vcprm(1,s1,1,s1));\ + c = vec_perm(r##p, i##p, vcprm(2,s2,2,s2));\ + d = vec_perm(r##p, i##p, vcprm(3,s3,3,s3));\ + STORE2(a, revtabk[ p*2-4]);\ + STORE2(b, revtabk[ p*2-3]);\ + STORE2(c, revtabj[-p*2+2]);\ + STORE2(d, revtabj[-p*2+3]); + + cos0 = tcos[k]; + sin0 = tsin[k]; + cos1 = tcos[-k-1]; + sin1 = tsin[-k-1]; + CMULA(0, 0,1,2,3); + CMULA(1, 2,3,0,1); + STORE8(0); + STORE8(1); + revtabj += 4; + revtabk -= 4; + k--; + } while(k >= 0); + + ff_fft_calc_altivec(s, (FFTComplex*)output); + + /* post rotation + reordering */ + j = -n32; + k = n32-1; + do { + vec_f cos,sin,re,im,a,b,c,d; +#define CMULB(d0,d1,o)\ + re = pout[o*2];\ + im = pout[o*2+1];\ + cos = tcos[o];\ + sin = tsin[o];\ + d0 = im*sin - re*cos;\ + d1 = re*sin + im*cos; + + CMULB(a,b,j); + CMULB(c,d,k); + pout[2*j] = vec_perm(a, d, vcprm(0,s3,1,s2)); + pout[2*j+1] = vec_perm(a, d, vcprm(2,s1,3,s0)); + pout[2*k] = vec_perm(c, b, vcprm(0,s3,1,s2)); + pout[2*k+1] = vec_perm(c, b, vcprm(2,s1,3,s0)); + j++; + k--; + } while(k >= 0); +} + +static void imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k; + int n = 1 << s->mdct_bits; + int n4 = n >> 2; + int n16 = n >> 4; + vec_u32 sign = {1U<<31,1U<<31,1U<<31,1U<<31}; + vec_u32 *p0 = (vec_u32*)(output+n4); + vec_u32 *p1 = (vec_u32*)(output+n4*3); + + imdct_half_altivec(s, output + n4, input); + + for (k = 0; k < n16; k++) { + vec_u32 a = p0[k] ^ sign; + vec_u32 b = p1[-k-1]; + p0[-k-1] = vec_perm(a, a, vcprm(3,2,1,0)); + p1[k] = vec_perm(b, b, vcprm(3,2,1,0)); + } +} +#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */ + +av_cold void ff_mdct_init_ppc(FFTContext *s) +{ +#if HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + if (s->mdct_bits >= 5) { + s->imdct_calc = imdct_calc_altivec; + s->imdct_half = imdct_half_altivec; + } +#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */ +} diff --git a/libavcodec/ppc/me_cmp.c b/libavcodec/ppc/me_cmp.c index 88c7fea..b074d28 100644 --- a/libavcodec/ppc/me_cmp.c +++ b/libavcodec/ppc/me_cmp.c @@ -34,9 +34,9 @@ #include "libavcodec/mpegvideo.h" #include "libavcodec/me_cmp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s = 0; const vector unsigned char zero = @@ -66,8 +66,8 @@ static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } /* Sum up the four partial sums, and put the result into s. */ sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); @@ -78,7 +78,7 @@ static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, } static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s = 0; const vector unsigned char zero = @@ -87,9 +87,9 @@ static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, vector unsigned char pix1v, pix3v, avgv, t5; vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; - /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one + /* Due to the fact that pix3 = pix2 + stride, 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. @@ -119,9 +119,9 @@ static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); - pix1 += line_size; + pix1 += stride; pix2v = pix3v; - pix3 += line_size; + pix3 += stride; } /* Sum up the four partial sums, and put the result into s. */ @@ -132,10 +132,10 @@ static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, } static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s = 0; - uint8_t *pix3 = pix2 + line_size; + uint8_t *pix3 = pix2 + stride; const vector unsigned char zero = (const vector unsigned char) vec_splat_u8(0); const vector unsigned short two = @@ -149,7 +149,7 @@ static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, vector unsigned int sad = (vector unsigned int) vec_splat_u32(0); vector signed int sumdiffs; - /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one + /* Due to the fact that pix3 = pix2 + stride, 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. @@ -212,8 +212,8 @@ static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); - pix1 += line_size; - pix3 += line_size; + pix1 += stride; + pix3 += stride; /* Transfer the calculated values for pix3 into pix2. */ t1 = t3; t2 = t4; @@ -227,7 +227,7 @@ static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, } static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s; const vector unsigned int zero = @@ -251,8 +251,8 @@ static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } /* Sum up the four partial sums, and put the result into s. */ @@ -264,7 +264,7 @@ static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, } static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s; const vector unsigned int zero = @@ -298,8 +298,8 @@ static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Add each 4 pixel group together and put 4 results into sad. */ sad = vec_sum4s(t5, sad); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } /* Sum up the four partial sums, and put the result into s. */ @@ -313,7 +313,7 @@ static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Sum of Squared Errors for an 8x8 block, AltiVec-enhanced. * It's the sad8_altivec code above w/ squaring added. */ static int sse8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s; const vector unsigned int zero = @@ -350,8 +350,8 @@ static int sse8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Square the values and add them to our sum. */ sum = vec_msum(t5, t5, sum); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } /* Sum up the four partial sums, and put the result into s. */ @@ -365,7 +365,7 @@ static int sse8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Sum of Squared Errors for a 16x16 block, AltiVec-enhanced. * It's the sad16_altivec code above w/ squaring added. */ static int sse16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int i, s; const vector unsigned int zero = @@ -392,8 +392,8 @@ static int sse16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, /* Square the values and add them to our sum. */ sum = vec_msum(t5, t5, sum); - pix1 += line_size; - pix2 += line_size; + pix1 += stride; + pix2 += stride; } /* Sum up the four partial sums, and put the result into s. */ @@ -405,7 +405,7 @@ static int sse16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, } static int hadamard8_diff8x8_altivec(MpegEncContext *s, uint8_t *dst, - uint8_t *src, int stride, int h) + uint8_t *src, ptrdiff_t stride, int h) { int sum; register const vector unsigned char vzero = @@ -534,7 +534,7 @@ static int hadamard8_diff8x8_altivec(MpegEncContext *s, uint8_t *dst, * but xlc goes to around 660 on the regular C code... */ static int hadamard8_diff16x8_altivec(MpegEncContext *s, uint8_t *dst, - uint8_t *src, int stride, int h) + uint8_t *src, ptrdiff_t stride, int h) { int sum; register vector signed short @@ -731,7 +731,7 @@ static int hadamard8_diff16x8_altivec(MpegEncContext *s, uint8_t *dst, } static int hadamard8_diff16_altivec(MpegEncContext *s, uint8_t *dst, - uint8_t *src, int stride, int h) + uint8_t *src, ptrdiff_t stride, int h) { int score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8); @@ -746,7 +746,7 @@ static int hadamard8_diff16_altivec(MpegEncContext *s, uint8_t *dst, av_cold void ff_me_cmp_init_ppc(MECmpContext *c, AVCodecContext *avctx) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/mpegaudiodsp_altivec.c b/libavcodec/ppc/mpegaudiodsp_altivec.c index c37f8ec..21cbcf3 100644 --- a/libavcodec/ppc/mpegaudiodsp_altivec.c +++ b/libavcodec/ppc/mpegaudiodsp_altivec.c @@ -27,7 +27,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegaudiodsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define MACS(rt, ra, rb) rt+=(ra)*(rb) #define MLSS(rt, ra, rb) rt-=(ra)*(rb) @@ -132,7 +132,7 @@ static void apply_window_mp3(float *in, float *win, int *unused, float *out, av_cold void ff_mpadsp_init_ppc(MPADSPContext *s) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/mpegvideo_altivec.c b/libavcodec/ppc/mpegvideo_altivec.c index 9ae849f..550a03a 100644 --- a/libavcodec/ppc/mpegvideo_altivec.c +++ b/libavcodec/ppc/mpegvideo_altivec.c @@ -32,7 +32,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegvideo.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN /* AltiVec version of dct_unquantize_h263 this code assumes `block' is 16 bytes-aligned */ @@ -117,7 +117,7 @@ static void dct_unquantize_h263_altivec(MpegEncContext *s, av_cold void ff_mpv_common_init_ppc(MpegEncContext *s) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/mpegvideodsp.c b/libavcodec/ppc/mpegvideodsp.c index 2bdf909..0b426e5 100644 --- a/libavcodec/ppc/mpegvideodsp.c +++ b/libavcodec/ppc/mpegvideodsp.c @@ -25,7 +25,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegvideodsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN /* AltiVec-enhanced gmc1. ATM this code assumes stride is a multiple of 8 * to preserve proper dst alignment. */ static void gmc1_altivec(uint8_t *dst /* align 8 */, uint8_t *src /* align1 */, @@ -127,7 +127,7 @@ static void gmc1_altivec(uint8_t *dst /* align 8 */, uint8_t *src /* align1 */, av_cold void ff_mpegvideodsp_init_ppc(MpegVideoDSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN c->gmc1 = gmc1_altivec; #endif /* HAVE_ALTIVEC */ } diff --git a/libavcodec/ppc/mpegvideoencdsp.c b/libavcodec/ppc/mpegvideoencdsp.c index b5348e6..7354816 100644 --- a/libavcodec/ppc/mpegvideoencdsp.c +++ b/libavcodec/ppc/mpegvideoencdsp.c @@ -29,7 +29,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegvideoencdsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static int pix_norm1_altivec(uint8_t *pix, int line_size) { @@ -93,7 +93,7 @@ static int pix_sum_altivec(uint8_t *pix, int line_size) av_cold void ff_mpegvideoencdsp_init_ppc(MpegvideoEncDSPContext *c, AVCodecContext *avctx) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/pixblockdsp.c b/libavcodec/ppc/pixblockdsp.c index 698d655..9cac70e 100644 --- a/libavcodec/ppc/pixblockdsp.c +++ b/libavcodec/ppc/pixblockdsp.c @@ -33,30 +33,28 @@ #include "libavcodec/avcodec.h" #include "libavcodec/pixblockdsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static void get_pixels_altivec(int16_t *restrict block, const uint8_t *pixels, int line_size) { int i; - vector unsigned char perm = vec_lvsl(0, pixels); - const vector unsigned char zero = - (const vector unsigned char) vec_splat_u8(0); + vec_u8 perm = vec_lvsl(0, pixels); + const vec_u8 zero = (const vec_u8)vec_splat_u8(0); for (i = 0; i < 8; i++) { /* Read potentially unaligned pixels. * We're reading 16 pixels, and actually only want 8, * but we simply ignore the extras. */ - vector unsigned char pixl = vec_ld(0, pixels); - vector unsigned char pixr = vec_ld(7, pixels); - vector unsigned char bytes = vec_perm(pixl, pixr, perm); + vec_u8 pixl = vec_ld(0, pixels); + vec_u8 pixr = vec_ld(7, pixels); + vec_u8 bytes = vec_perm(pixl, pixr, perm); // Convert the bytes into shorts. - vector signed short shorts = (vector signed short) vec_mergeh(zero, - bytes); + vec_s16 shorts = (vec_s16)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); + vec_st(shorts, i * 16, (vec_s16 *)block); pixels += line_size; } @@ -66,22 +64,21 @@ static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, const uint8_t *s2, int stride) { int i; - vector unsigned char perm1 = vec_lvsl(0, s1); - vector unsigned char perm2 = vec_lvsl(0, s2); - const vector unsigned char zero = - (const vector unsigned char) vec_splat_u8(0); - vector signed short shorts1, shorts2; + vec_u8 perm1 = vec_lvsl(0, s1); + vec_u8 perm2 = vec_lvsl(0, s2); + const vec_u8 zero = (const vec_u8)vec_splat_u8(0); + vec_s16 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. */ - vector unsigned char pixl = vec_ld(0, s1); - vector unsigned char pixr = vec_ld(15, s1); - vector unsigned char bytes = vec_perm(pixl, pixr, perm1); + vec_u8 pixl = vec_ld(0, s1); + vec_u8 pixr = vec_ld(15, s1); + vec_u8 bytes = vec_perm(pixl, pixr, perm1); // Convert the bytes into shorts. - shorts1 = (vector signed short) vec_mergeh(zero, bytes); + shorts1 = (vec_s16)vec_mergeh(zero, bytes); // Do the same for the second block of pixels. pixl = vec_ld(0, s2); @@ -89,13 +86,13 @@ static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, bytes = vec_perm(pixl, pixr, perm2); // Convert the bytes into shorts. - shorts2 = (vector signed short) vec_mergeh(zero, bytes); + shorts2 = (vec_s16)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); + vec_st(shorts1, 0, (vec_s16 *)block); s1 += stride; s2 += stride; @@ -112,7 +109,7 @@ static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, bytes = vec_perm(pixl, pixr, perm1); // Convert the bytes into shorts. - shorts1 = (vector signed short) vec_mergeh(zero, bytes); + shorts1 = (vec_s16)vec_mergeh(zero, bytes); // Do the same for the second block of pixels. pixl = vec_ld(0, s2); @@ -120,13 +117,13 @@ static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, bytes = vec_perm(pixl, pixr, perm2); // Convert the bytes into shorts. - shorts2 = (vector signed short) vec_mergeh(zero, bytes); + shorts2 = (vec_s16)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); + vec_st(shorts1, 0, (vec_s16 *)block); s1 += stride; s2 += stride; @@ -136,11 +133,45 @@ static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, #endif /* HAVE_ALTIVEC */ +#if HAVE_VSX +static void get_pixels_vsx(int16_t *restrict block, const uint8_t *pixels, + int line_size) +{ + int i; + for (i = 0; i < 8; i++) { + vec_s16 shorts = vsx_ld_u8_s16(0, pixels); + + vec_vsx_st(shorts, i * 16, block); + + pixels += line_size; + } +} + +static void diff_pixels_vsx(int16_t *restrict block, const uint8_t *s1, + const uint8_t *s2, int stride) +{ + int i; + vec_s16 shorts1, shorts2; + for (i = 0; i < 8; i++) { + shorts1 = vsx_ld_u8_s16(0, s1); + shorts2 = vsx_ld_u8_s16(0, s2); + + shorts1 = vec_sub(shorts1, shorts2); + + vec_vsx_st(shorts1, 0, block); + + s1 += stride; + s2 += stride; + block += 8; + } +} +#endif /* HAVE_VSX */ + av_cold void ff_pixblockdsp_init_ppc(PixblockDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; @@ -150,4 +181,14 @@ av_cold void ff_pixblockdsp_init_ppc(PixblockDSPContext *c, c->get_pixels = get_pixels_altivec; } #endif /* HAVE_ALTIVEC */ + +#if HAVE_VSX + if (!PPC_VSX(av_get_cpu_flags())) + return; + + c->diff_pixels = diff_pixels_vsx; + + if (!high_bit_depth) + c->get_pixels = get_pixels_vsx; +#endif /* HAVE_VSX */ } diff --git a/libavcodec/ppc/svq1enc_altivec.c b/libavcodec/ppc/svq1enc_altivec.c index 564f129..222f7c1 100644 --- a/libavcodec/ppc/svq1enc_altivec.c +++ b/libavcodec/ppc/svq1enc_altivec.c @@ -32,7 +32,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/svq1enc.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, int size) { @@ -76,7 +76,7 @@ static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, av_cold void ff_svq1enc_init_ppc(SVQ1EncContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/vc1dsp_altivec.c b/libavcodec/ppc/vc1dsp_altivec.c index 90c3d27..caf8721 100644 --- a/libavcodec/ppc/vc1dsp_altivec.c +++ b/libavcodec/ppc/vc1dsp_altivec.c @@ -27,7 +27,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/vc1dsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN // main steps of 8x8 transform #define STEP8(s0, s1, s2, s3, s4, s5, s6, s7, vec_rnd) \ @@ -344,7 +344,7 @@ static void vc1_inv_trans_8x4_altivec(uint8_t *dest, int stride, int16_t *block) av_cold void ff_vc1dsp_init_ppc(VC1DSPContext *dsp) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/vorbisdsp_altivec.c b/libavcodec/ppc/vorbisdsp_altivec.c index 43f4d03..a7aad86 100644 --- a/libavcodec/ppc/vorbisdsp_altivec.c +++ b/libavcodec/ppc/vorbisdsp_altivec.c @@ -27,7 +27,7 @@ #include "libavutil/ppc/cpu.h" #include "libavcodec/vorbisdsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static void vorbis_inverse_coupling_altivec(float *mag, float *ang, intptr_t blocksize) { @@ -54,7 +54,7 @@ static void vorbis_inverse_coupling_altivec(float *mag, float *ang, av_cold void ff_vorbisdsp_init_ppc(VorbisDSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/vp3dsp_altivec.c b/libavcodec/ppc/vp3dsp_altivec.c index bce49e3..1d907d7 100644 --- a/libavcodec/ppc/vp3dsp_altivec.c +++ b/libavcodec/ppc/vp3dsp_altivec.c @@ -28,7 +28,7 @@ #include "libavutil/ppc/util_altivec.h" #include "libavcodec/vp3dsp.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN static const vec_s16 constants = {0, 64277, 60547, 54491, 46341, 36410, 25080, 12785}; @@ -114,7 +114,7 @@ static inline vec_s16 M16(vec_s16 a, vec_s16 C) #define ADD8(a) vec_add(a, eight) #define SHIFT4(a) vec_sra(a, four) -static void vp3_idct_put_altivec(uint8_t *dst, int stride, int16_t block[64]) +static void vp3_idct_put_altivec(uint8_t *dst, ptrdiff_t stride, int16_t block[64]) { vec_u8 t; IDCT_START @@ -143,7 +143,7 @@ static void vp3_idct_put_altivec(uint8_t *dst, int stride, int16_t block[64]) memset(block, 0, sizeof(*block) * 64); } -static void vp3_idct_add_altivec(uint8_t *dst, int stride, int16_t block[64]) +static void vp3_idct_add_altivec(uint8_t *dst, ptrdiff_t stride, int16_t block[64]) { LOAD_ZERO; vec_u8 t, vdst; @@ -179,7 +179,7 @@ static void vp3_idct_add_altivec(uint8_t *dst, int stride, int16_t block[64]) av_cold void ff_vp3dsp_init_ppc(VP3DSPContext *c, int flags) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/ppc/vp8dsp_altivec.c b/libavcodec/ppc/vp8dsp_altivec.c index e010dee..869fe67 100644 --- a/libavcodec/ppc/vp8dsp_altivec.c +++ b/libavcodec/ppc/vp8dsp_altivec.c @@ -29,7 +29,7 @@ #include "libavcodec/vp8dsp.h" #include "hpeldsp_altivec.h" -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN #define REPT4(...) { __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__ } // h subpel filter uses msum to multiply+add 4 pixel taps at once @@ -315,7 +315,7 @@ static void put_vp8_pixels16_altivec(uint8_t *dst, ptrdiff_t dstride, uint8_t *s av_cold void ff_vp78dsp_init_ppc(VP8DSPContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN if (!PPC_ALTIVEC(av_get_cpu_flags())) return; diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c new file mode 100644 index 0000000..d5c5df2 --- /dev/null +++ b/libavcodec/profiles.c @@ -0,0 +1,123 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "avcodec.h" +#include "profiles.h" + +#if !CONFIG_SMALL + +const AVProfile ff_aac_profiles[] = { + { FF_PROFILE_AAC_LOW, "LC" }, + { FF_PROFILE_AAC_HE, "HE-AAC" }, + { FF_PROFILE_AAC_HE_V2, "HE-AACv2" }, + { FF_PROFILE_AAC_LD, "LD" }, + { FF_PROFILE_AAC_ELD, "ELD" }, + { FF_PROFILE_AAC_MAIN, "Main" }, + { FF_PROFILE_AAC_LOW, "LC" }, + { FF_PROFILE_AAC_SSR, "SSR" }, + { FF_PROFILE_AAC_LTP, "LTP" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_dca_profiles[] = { + { FF_PROFILE_DTS, "DTS" }, + { FF_PROFILE_DTS_ES, "DTS-ES" }, + { FF_PROFILE_DTS_96_24, "DTS 96/24" }, + { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, + { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_h264_profiles[] = { + { FF_PROFILE_H264_BASELINE, "Baseline" }, + { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" }, + { FF_PROFILE_H264_MAIN, "Main" }, + { FF_PROFILE_H264_EXTENDED, "Extended" }, + { FF_PROFILE_H264_HIGH, "High" }, + { FF_PROFILE_H264_HIGH_10, "High 10" }, + { FF_PROFILE_H264_HIGH_10_INTRA, "High 10 Intra" }, + { FF_PROFILE_H264_HIGH_422, "High 4:2:2" }, + { FF_PROFILE_H264_HIGH_422_INTRA, "High 4:2:2 Intra" }, + { FF_PROFILE_H264_HIGH_444, "High 4:4:4" }, + { FF_PROFILE_H264_HIGH_444_PREDICTIVE, "High 4:4:4 Predictive" }, + { FF_PROFILE_H264_HIGH_444_INTRA, "High 4:4:4 Intra" }, + { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" }, + { FF_PROFILE_H264_MULTIVIEW_HIGH, "Multiview High" }, + { FF_PROFILE_H264_STEREO_HIGH, "Stereo High" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_hevc_profiles[] = { + { FF_PROFILE_HEVC_MAIN, "Main" }, + { FF_PROFILE_HEVC_MAIN_10, "Main 10" }, + { FF_PROFILE_HEVC_MAIN_STILL_PICTURE, "Main Still Picture" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_jpeg2000_profiles[] = { + { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0, "JPEG 2000 codestream restriction 0" }, + { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1, "JPEG 2000 codestream restriction 1" }, + { FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION, "JPEG 2000 no codestream restrictions" }, + { FF_PROFILE_JPEG2000_DCINEMA_2K, "JPEG 2000 digital cinema 2K" }, + { FF_PROFILE_JPEG2000_DCINEMA_4K, "JPEG 2000 digital cinema 4K" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_mpeg2_video_profiles[] = { + { FF_PROFILE_MPEG2_422, "4:2:2" }, + { FF_PROFILE_MPEG2_HIGH, "High" }, + { FF_PROFILE_MPEG2_SS, "Spatially Scalable" }, + { FF_PROFILE_MPEG2_SNR_SCALABLE, "SNR Scalable" }, + { FF_PROFILE_MPEG2_MAIN, "Main" }, + { FF_PROFILE_MPEG2_SIMPLE, "Simple" }, + { FF_PROFILE_RESERVED, "Reserved" }, + { FF_PROFILE_RESERVED, "Reserved" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_mpeg4_video_profiles[] = { + { FF_PROFILE_MPEG4_SIMPLE, "Simple Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_SCALABLE, "Simple Scalable Profile" }, + { FF_PROFILE_MPEG4_CORE, "Core Profile" }, + { FF_PROFILE_MPEG4_MAIN, "Main Profile" }, + { FF_PROFILE_MPEG4_N_BIT, "N-bit Profile" }, + { FF_PROFILE_MPEG4_SCALABLE_TEXTURE, "Scalable Texture Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION, "Simple Face Animation Profile" }, + { FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE, "Basic Animated Texture Profile" }, + { FF_PROFILE_MPEG4_HYBRID, "Hybrid Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_REAL_TIME, "Advanced Real Time Simple Profile" }, + { FF_PROFILE_MPEG4_CORE_SCALABLE, "Code Scalable Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_CODING, "Advanced Coding Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_CORE, "Advanced Core Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE, "Advanced Scalable Texture Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_STUDIO, "Simple Studio Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, "Advanced Simple Profile" }, + { FF_PROFILE_UNKNOWN }, +}; + +const AVProfile ff_vc1_profiles[] = { + { FF_PROFILE_VC1_SIMPLE, "Simple" }, + { FF_PROFILE_VC1_MAIN, "Main" }, + { FF_PROFILE_VC1_COMPLEX, "Complex" }, + { FF_PROFILE_VC1_ADVANCED, "Advanced" }, + { FF_PROFILE_UNKNOWN }, +}; + +#endif /* !CONFIG_SMALL */ diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h new file mode 100644 index 0000000..0276b17 --- /dev/null +++ b/libavcodec/profiles.h @@ -0,0 +1,33 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_PROFILES_H +#define AVCODEC_PROFILES_H + +#include "avcodec.h" + +extern const AVProfile ff_aac_profiles[]; +extern const AVProfile ff_dca_profiles[]; +extern const AVProfile ff_h264_profiles[]; +extern const AVProfile ff_hevc_profiles[]; +extern const AVProfile ff_jpeg2000_profiles[]; +extern const AVProfile ff_mpeg2_video_profiles[]; +extern const AVProfile ff_mpeg4_video_profiles[]; +extern const AVProfile ff_vc1_profiles[]; + +#endif /* AVCODEC_PROFILES_H */ diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c index da5feff..8a53719 100644 --- a/libavcodec/proresdec.c +++ b/libavcodec/proresdec.c @@ -40,7 +40,7 @@ #include "proresdsp.h" #include "get_bits.h" -typedef struct { +typedef struct ProresThreadData { const uint8_t *index; ///< pointers to the data of this slice int slice_num; int x_pos, y_pos; @@ -51,7 +51,7 @@ typedef struct { DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64]; } ProresThreadData; -typedef struct { +typedef struct ProresContext { ProresDSPContext dsp; AVFrame *frame; ScanTable scantable; @@ -778,5 +778,5 @@ AVCodec ff_prores_decoder = { .init = decode_init, .close = decode_close, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, }; diff --git a/libavcodec/proresdsp.c b/libavcodec/proresdsp.c index 3af2f0b..f782c90 100644 --- a/libavcodec/proresdsp.c +++ b/libavcodec/proresdsp.c @@ -36,11 +36,11 @@ /** * Add bias value, clamp and output pixels of a slice */ -static void put_pixels(uint16_t *dst, int stride, const int16_t *in) +static void put_pixels(uint16_t *dst, ptrdiff_t linesize, const int16_t *in) { int x, y, src_offset, dst_offset; - for (y = 0, dst_offset = 0; y < 8; y++, dst_offset += stride) { + for (y = 0, dst_offset = 0; y < 8; y++, dst_offset += linesize) { for (x = 0; x < 8; x++) { src_offset = (y << 3) + x; @@ -49,7 +49,7 @@ static void put_pixels(uint16_t *dst, int stride, const int16_t *in) } } -static void prores_idct_put_c(uint16_t *out, int linesize, int16_t *block, const int16_t *qmat) +static void prores_idct_put_c(uint16_t *out, ptrdiff_t linesize, int16_t *block, const int16_t *qmat) { ff_prores_idct(block, qmat); put_pixels(out, linesize >> 1, block); diff --git a/libavcodec/proresdsp.h b/libavcodec/proresdsp.h index e8a3ea9..7f06494 100644 --- a/libavcodec/proresdsp.h +++ b/libavcodec/proresdsp.h @@ -23,6 +23,7 @@ #ifndef AVCODEC_PRORESDSP_H #define AVCODEC_PRORESDSP_H +#include #include #define PRORES_BITS_PER_SAMPLE 10 ///< output precision of prores decoder @@ -30,7 +31,7 @@ typedef struct ProresDSPContext { int idct_permutation_type; uint8_t idct_permutation[64]; - void (* idct_put) (uint16_t *out, int linesize, int16_t *block, const int16_t *qmat); + void (*idct_put)(uint16_t *out, ptrdiff_t linesize, int16_t *block, const int16_t *qmat); } ProresDSPContext; void ff_proresdsp_init(ProresDSPContext *dsp); diff --git a/libavcodec/proresenc.c b/libavcodec/proresenc.c index f61aa60..e4842d2 100644 --- a/libavcodec/proresenc.c +++ b/libavcodec/proresenc.c @@ -192,9 +192,10 @@ typedef struct ProresContext { const uint8_t *scantable; void (*fdct)(FDCTDSPContext *fdsp, const uint16_t *src, - int linesize, int16_t *block); + ptrdiff_t linesize, int16_t *block); FDCTDSPContext fdsp; + const AVFrame *pic; int mb_width, mb_height; int mbs_per_slice; int num_chroma_blocks, chroma_factor; @@ -222,13 +223,13 @@ typedef struct ProresContext { } ProresContext; static void get_slice_data(ProresContext *ctx, const uint16_t *src, - int linesize, int x, int y, int w, int h, + ptrdiff_t linesize, int x, int y, int w, int h, int16_t *blocks, uint16_t *emu_buf, int mbs_per_slice, int blocks_per_mb, int is_chroma) { const uint16_t *esrc; const int mb_width = 4 * blocks_per_mb; - int elinesize; + ptrdiff_t elinesize; int i, j, k; for (i = 0; i < mbs_per_slice; i++, src += mb_width) { @@ -293,7 +294,7 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src, } static void get_alpha_data(ProresContext *ctx, const uint16_t *src, - int linesize, int x, int y, int w, int h, + ptrdiff_t linesize, int x, int y, int w, int h, int16_t *blocks, int mbs_per_slice, int abits) { const int slice_width = 16 * mbs_per_slice; @@ -416,7 +417,7 @@ static void encode_acs(PutBitContext *pb, int16_t *blocks, } static int encode_slice_plane(ProresContext *ctx, PutBitContext *pb, - const uint16_t *src, int linesize, + const uint16_t *src, ptrdiff_t linesize, int mbs_per_slice, int16_t *blocks, int blocks_per_mb, int plane_size_factor, const int16_t *qmat) @@ -510,7 +511,8 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int total_size = 0; const uint16_t *src; int slice_width_factor = av_log2(mbs_per_slice); - int num_cblocks, pwidth, linesize, line_add; + int num_cblocks, pwidth, line_add; + ptrdiff_t linesize; int plane_factor, is_chroma; uint16_t *qmat; @@ -666,7 +668,7 @@ static int estimate_acs(int *error, int16_t *blocks, int blocks_per_slice, } static int estimate_slice_plane(ProresContext *ctx, int *error, int plane, - const uint16_t *src, int linesize, + const uint16_t *src, ptrdiff_t linesize, int mbs_per_slice, int blocks_per_mb, int plane_size_factor, const int16_t *qmat, ProresThreadData *td) @@ -700,7 +702,7 @@ static int est_alpha_diff(int cur, int prev, int abits) } static int estimate_alpha_plane(ProresContext *ctx, int *error, - const uint16_t *src, int linesize, + const uint16_t *src, ptrdiff_t linesize, int mbs_per_slice, int quant, int16_t *blocks) { @@ -743,7 +745,7 @@ static int estimate_alpha_plane(ProresContext *ctx, int *error, return bits; } -static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, +static int find_slice_quant(AVCodecContext *avctx, int trellis_node, int x, int y, int mbs_per_slice, ProresThreadData *td) { @@ -765,7 +767,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, if (ctx->pictures_per_frame == 1) line_add = 0; else - line_add = ctx->cur_picture_idx ^ !pic->top_field_first; + line_add = ctx->cur_picture_idx ^ !ctx->pic->top_field_first; mbs = x + mbs_per_slice; for (i = 0; i < ctx->num_planes; i++) { @@ -785,9 +787,9 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, pwidth = avctx->width >> 1; } - linesize[i] = pic->linesize[i] * ctx->pictures_per_frame; - src = (const uint16_t*)(pic->data[i] + yp * linesize[i] + - line_add * pic->linesize[i]) + xp; + linesize[i] = ctx->pic->linesize[i] * ctx->pictures_per_frame; + src = (const uint16_t *)(ctx->pic->data[i] + yp * linesize[i] + + line_add * ctx->pic->linesize[i]) + xp; if (i < 3) { get_slice_data(ctx, src, linesize[i], xp, yp, @@ -910,7 +912,7 @@ static int find_quant_thread(AVCodecContext *avctx, void *arg, for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { while (ctx->mb_width - x < mbs_per_slice) mbs_per_slice >>= 1; - q = find_slice_quant(avctx, avctx->coded_frame, + q = find_slice_quant(avctx, (mb + 1) * TRELLIS_WIDTH, x, y, mbs_per_slice, td); } @@ -937,13 +939,17 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int pkt_size, ret, max_slice_size = 0; uint8_t frame_flags; - *avctx->coded_frame = *pic; + ctx->pic = pic; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt_size = ctx->frame_size_upper_bound; - if ((ret = ff_alloc_packet(pkt, pkt_size + FF_MIN_BUFFER_SIZE)) < 0) { + if ((ret = ff_alloc_packet(pkt, pkt_size + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } @@ -964,7 +970,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream_put_be16 (&buf, avctx->height); frame_flags = ctx->chroma_factor << 6; - if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) frame_flags |= pic->top_field_first ? 0x04 : 0x08; bytestream_put_byte (&buf, frame_flags); @@ -1096,8 +1102,6 @@ static av_cold int encode_close(AVCodecContext *avctx) ProresContext *ctx = avctx->priv_data; int i; - av_freep(&avctx->coded_frame); - if (ctx->tdata) { for (i = 0; i < avctx->thread_count; i++) av_free(ctx->tdata[i].nodes); @@ -1109,7 +1113,7 @@ static av_cold int encode_close(AVCodecContext *avctx) } static void prores_fdct(FDCTDSPContext *fdsp, const uint16_t *src, - int linesize, int16_t *block) + ptrdiff_t linesize, int16_t *block) { int x, y; const uint16_t *tsrc = src; @@ -1128,12 +1132,9 @@ static av_cold int encode_init(AVCodecContext *avctx) int mps; int i, j; int min_quant, max_quant; - int interlaced = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); + int interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT); avctx->bits_per_raw_sample = 10; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); ctx->fdct = prores_fdct; ctx->scantable = interlaced ? ff_prores_interlaced_scan @@ -1151,6 +1152,7 @@ static av_cold int encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "alpha bits should be 0, 8 or 16\n"); return AVERROR(EINVAL); } + avctx->bits_per_coded_sample = 32; } else { ctx->alpha_bits = 0; } @@ -1331,7 +1333,7 @@ AVCodec ff_prores_encoder = { .init = encode_init, .close = encode_close, .encode2 = encode_frame, - .capabilities = CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c index a2af611..5179ede 100644 --- a/libavcodec/psymodel.c +++ b/libavcodec/psymodel.c @@ -39,6 +39,12 @@ av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens, ctx->group = av_mallocz(sizeof(ctx->group[0]) * num_groups); ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens); ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens); + + if (!ctx->ch || !ctx->group || !ctx->bands || !ctx->num_bands) { + ff_psy_end(ctx); + return AVERROR(ENOMEM); + } + memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens); memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens); @@ -98,6 +104,8 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av int i; float cutoff_coeff = 0; ctx = av_mallocz(sizeof(FFPsyPreprocessContext)); + if (!ctx) + return NULL; ctx->avctx = avctx; if (avctx->cutoff > 0) @@ -109,6 +117,10 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av cutoff_coeff, 0.0, 0.0); if (ctx->fcoeffs) { ctx->fstate = av_mallocz(sizeof(ctx->fstate[0]) * avctx->channels); + if (!ctx->fstate) { + av_free(ctx); + return NULL; + } for (i = 0; i < avctx->channels; i++) ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER); } diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 682fd05..3b3f3ad 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -45,18 +45,18 @@ */ static void validate_thread_parameters(AVCodecContext *avctx) { - int frame_threading_supported = (avctx->codec->capabilities & CODEC_CAP_FRAME_THREADS) - && !(avctx->flags & CODEC_FLAG_TRUNCATED) - && !(avctx->flags & CODEC_FLAG_LOW_DELAY) - && !(avctx->flags2 & CODEC_FLAG2_CHUNKS); + int frame_threading_supported = (avctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) + && !(avctx->flags & AV_CODEC_FLAG_TRUNCATED) + && !(avctx->flags & AV_CODEC_FLAG_LOW_DELAY) + && !(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS); if (avctx->thread_count == 1) { avctx->active_thread_type = 0; } else if (frame_threading_supported && (avctx->thread_type & FF_THREAD_FRAME)) { avctx->active_thread_type = FF_THREAD_FRAME; - } else if (avctx->codec->capabilities & CODEC_CAP_SLICE_THREADS && + } else if (avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS && avctx->thread_type & FF_THREAD_SLICE) { avctx->active_thread_type = FF_THREAD_SLICE; - } else if (!(avctx->codec->capabilities & CODEC_CAP_AUTO_THREADS)) { + } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)) { avctx->thread_count = 1; avctx->active_thread_type = 0; } diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index a658f3e..c72da53 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -178,6 +178,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, if (dst != src) { dst->time_base = src->time_base; + dst->framerate = src->framerate; dst->width = src->width; dst->height = src->height; dst->pix_fmt = src->pix_fmt; @@ -214,7 +215,11 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (for_user) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->coded_frame = src->coded_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { if (dst->codec->update_thread_context) err = dst->codec->update_thread_context(dst, src); @@ -237,12 +242,6 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->draw_horiz_band= src->draw_horiz_band; dst->get_buffer2 = src->get_buffer2; -#if FF_API_GET_BUFFER -FF_DISABLE_DEPRECATION_WARNINGS - dst->get_buffer = src->get_buffer; - dst->release_buffer = src->release_buffer; -FF_ENABLE_DEPRECATION_WARNINGS -#endif dst->opaque = src->opaque; dst->debug = src->debug; @@ -299,7 +298,8 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) PerThreadContext *prev_thread = fctx->prev_thread; const AVCodec *codec = p->avctx->codec; - if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; + if (!avpkt->size && !(codec->capabilities & AV_CODEC_CAP_DELAY)) + return 0; pthread_mutex_lock(&p->mutex); @@ -334,13 +334,8 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) * and it calls back to the client here. */ -FF_DISABLE_DEPRECATION_WARNINGS - if (!p->avctx->thread_safe_callbacks && ( -#if FF_API_GET_BUFFER - p->avctx->get_buffer || -#endif - p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { -FF_ENABLE_DEPRECATION_WARNINGS + if (!p->avctx->thread_safe_callbacks && + p->avctx->get_buffer2 != avcodec_default_get_buffer2) { while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { pthread_mutex_lock(&p->progress_mutex); while (p->state == STATE_SETTING_UP) @@ -583,8 +578,15 @@ int ff_frame_thread_init(AVCodecContext *avctx) } avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext)); + if (!fctx) + return AVERROR(ENOMEM); fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); + if (!fctx->threads) { + av_freep(&avctx->internal->thread_ctx); + return AVERROR(ENOMEM); + } + pthread_mutex_init(&fctx->buffer_mutex, NULL); fctx->delaying = 1; @@ -600,6 +602,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) p->frame = av_frame_alloc(); if (!p->frame) { + av_freep(©); err = AVERROR(ENOMEM); goto error; } @@ -714,13 +717,8 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) } pthread_mutex_lock(&p->parent->buffer_mutex); -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->thread_safe_callbacks || ( -#if FF_API_GET_BUFFER - !avctx->get_buffer && -#endif - avctx->get_buffer2 == avcodec_default_get_buffer2)) { -FF_ENABLE_DEPRECATION_WARNINGS + if (avctx->thread_safe_callbacks || + avctx->get_buffer2 == avcodec_default_get_buffer2) { err = ff_get_buffer(avctx, f->f, flags); } else { p->requested_frame = f->f; @@ -753,15 +751,9 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) PerThreadContext *p = avctx->internal->thread_ctx; FrameThreadContext *fctx; AVFrame *dst, *tmp; -FF_DISABLE_DEPRECATION_WARNINGS int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || - ( -#if FF_API_GET_BUFFER - !avctx->get_buffer && -#endif - avctx->get_buffer2 == avcodec_default_get_buffer2); -FF_ENABLE_DEPRECATION_WARNINGS + avctx->get_buffer2 == avcodec_default_get_buffer2; if (!f->f || !f->f->buf[0]) return; diff --git a/libavcodec/pthread_internal.h b/libavcodec/pthread_internal.h index 5dfd0b2..fca9b10 100644 --- a/libavcodec/pthread_internal.h +++ b/libavcodec/pthread_internal.h @@ -21,7 +21,7 @@ #include "avcodec.h" -/* H264 slice threading seems to be buggy with more than 16 threads, +/* H.264 slice threading seems to be buggy with more than 16 threads, * limit the number of threads to 16 for automatic detection */ #define MAX_AUTO_THREADS 16 diff --git a/libavcodec/ptx.c b/libavcodec/ptx.c index 76fff26..312850c 100644 --- a/libavcodec/ptx.c +++ b/libavcodec/ptx.c @@ -96,5 +96,5 @@ AVCodec ff_ptx_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PTX, .decode = ptx_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c index 7d9427c..e9e7347 100644 --- a/libavcodec/qcelpdec.c +++ b/libavcodec/qcelpdec.c @@ -52,7 +52,7 @@ typedef enum { RATE_FULL } qcelp_packet_rate; -typedef struct { +typedef struct QCELPContext { GetBitContext gb; qcelp_packet_rate bitrate; QCELPFrame frame; /**< unpacked data frame */ @@ -600,7 +600,7 @@ static qcelp_packet_rate buf_size2bitrate(const int buf_size) * * @param avctx the AV codec context * @param buf_size length of the buffer - * @param buf the bufffer + * @param buf the buffer * * @return the bitrate on success, * I_F_Q if the bitrate cannot be satisfactorily determined @@ -794,6 +794,6 @@ AVCodec ff_qcelp_decoder = { .id = AV_CODEC_ID_QCELP, .init = qcelp_decode_init, .decode = qcelp_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(QCELPContext), }; diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 4718b34..7a7c149 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -35,21 +35,19 @@ #include #include -#define BITSTREAM_READER_LE #include "libavutil/channel_layout.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "rdft.h" -#include "mpegaudiodsp.h" #include "mpegaudio.h" +#include "mpegaudiodsp.h" +#include "rdft.h" #include "qdm2data.h" #include "qdm2_tablegen.h" -#undef NDEBUG -#include - #define QDM2_LIST_ADD(list, size, packet) \ do { \ @@ -83,7 +81,7 @@ typedef int8_t sb_int8_array[2][30][64]; /** * Subpacket */ -typedef struct { +typedef struct QDM2SubPacket { 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) @@ -97,12 +95,12 @@ typedef struct QDM2SubPNode { struct QDM2SubPNode *next; ///< pointer to next packet in the list, NULL if leaf node } QDM2SubPNode; -typedef struct { +typedef struct QDM2Complex { float re; float im; } QDM2Complex; -typedef struct { +typedef struct FFTTone { float level; QDM2Complex *complex; const float *table; @@ -113,7 +111,7 @@ typedef struct { short cutoff; } FFTTone; -typedef struct { +typedef struct FFTCoefficient { int16_t sub_packet; uint8_t channel; int16_t offset; @@ -121,14 +119,14 @@ typedef struct { uint8_t phase; } FFTCoefficient; -typedef struct { +typedef struct QDM2FFT { DECLARE_ALIGNED(32, QDM2Complex, complex)[MPA_MAX_CHANNELS][256]; } QDM2FFT; /** * QDM2 decoder context */ -typedef struct { +typedef struct QDM2Context { /// Parameters from codec header, do not change during playback int nb_channels; ///< number of channels int channels; ///< number of channels @@ -395,7 +393,7 @@ static int qdm2_get_se_vlc(VLC *vlc, GetBitContext *gb, int depth) /** * QDM2 checksum * - * @param data pointer to data to be checksum'ed + * @param data pointer to data to be checksummed * @param length data length * @param value checksum value * @@ -724,67 +722,68 @@ static void fill_coding_method_array(sb_int8_array tone_level_idx, } tone_level_idx_temp[ch][sb][0] = tone_level_idx_temp[ch][sb][1]; } - acc = 0; - for (ch = 0; ch < nb_channels; ch++) - for (sb = 0; sb < 30; sb++) - for (j = 0; j < 64; j++) - acc += tone_level_idx_temp[ch][sb][j]; - - multres = 0x66666667LL * (acc * 10); - esp_40 = (multres >> 32) / 8 + ((multres & 0xffffffff) >> 31); - for (ch = 0; ch < nb_channels; ch++) - for (sb = 0; sb < 30; sb++) - for (j = 0; j < 64; j++) { - comp = tone_level_idx_temp[ch][sb][j]* esp_40 * 10; - if (comp < 0) - comp += 0xff; - comp /= 256; // signed shift - switch(sb) { - case 0: - if (comp < 30) - comp = 30; - comp += 15; - break; - case 1: - if (comp < 24) - comp = 24; - comp += 10; - break; - case 2: - case 3: - case 4: - if (comp < 16) - comp = 16; - } - if (comp <= 5) - tmp = 0; - else if (comp <= 10) - tmp = 10; - else if (comp <= 16) - tmp = 16; - else if (comp <= 24) - tmp = -1; - else - tmp = 0; - coding_method[ch][sb][j] = ((tmp & 0xfffa) + 30 )& 0xff; + + acc = 0; + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) + acc += tone_level_idx_temp[ch][sb][j]; + + multres = 0x66666667LL * (acc * 10); + esp_40 = (multres >> 32) / 8 + ((multres & 0xffffffff) >> 31); + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) { + comp = tone_level_idx_temp[ch][sb][j]* esp_40 * 10; + if (comp < 0) + comp += 0xff; + comp /= 256; // signed shift + switch(sb) { + case 0: + if (comp < 30) + comp = 30; + comp += 15; + break; + case 1: + if (comp < 24) + comp = 24; + comp += 10; + break; + case 2: + case 3: + case 4: + if (comp < 16) + comp = 16; } + if (comp <= 5) + tmp = 0; + else if (comp <= 10) + tmp = 10; + else if (comp <= 16) + tmp = 16; + else if (comp <= 24) + tmp = -1; + else + tmp = 0; + coding_method[ch][sb][j] = ((tmp & 0xfffa) + 30 )& 0xff; + } + for (sb = 0; sb < 30; sb++) + fix_coding_method_array(sb, nb_channels, coding_method); + for (ch = 0; ch < nb_channels; ch++) for (sb = 0; sb < 30; sb++) - 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; + 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 (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; - } + 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++) @@ -794,7 +793,6 @@ static void fill_coding_method_array(sb_int8_array tone_level_idx, } /** - * * 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 @@ -1762,7 +1760,7 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) if (!avctx->extradata || (avctx->extradata_size < 48)) { av_log(avctx, AV_LOG_ERROR, "extradata missing or truncated\n"); - return -1; + return AVERROR_INVALIDDATA; } extradata = avctx->extradata; @@ -1778,18 +1776,18 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) if (extradata_size < 12) { av_log(avctx, AV_LOG_ERROR, "not enough extradata (%i)\n", extradata_size); - return -1; + return AVERROR_INVALIDDATA; } if (memcmp(extradata, "frmaQDM", 7)) { av_log(avctx, AV_LOG_ERROR, "invalid headers, QDM? not found\n"); - return -1; + return AVERROR_INVALIDDATA; } 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; + avpriv_report_missing_feature(avctx, "QDMC version 1"); + return AVERROR_PATCHWELCOME; } extradata += 8; @@ -1800,14 +1798,14 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) if(size > extradata_size){ av_log(avctx, AV_LOG_ERROR, "extradata size too small, %i < %i\n", extradata_size, size); - return -1; + return AVERROR_INVALIDDATA; } extradata += 4; av_log(avctx, AV_LOG_DEBUG, "size: %d\n", size); if (AV_RB32(extradata) != MKBETAG('Q','D','C','A')) { av_log(avctx, AV_LOG_ERROR, "invalid extradata, expecting QDCA\n"); - return -1; + return AVERROR_INVALIDDATA; } extradata += 8; @@ -1882,8 +1880,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) // Fail on unknown fft order if ((s->fft_order < 7) || (s->fft_order > 9)) { - av_log(avctx, AV_LOG_ERROR, "Unknown FFT order (%d), contact the developers!\n", s->fft_order); - return -1; + avpriv_request_sample(avctx, "Unknown FFT order %d", s->fft_order); + return AVERROR_PATCHWELCOME; } if (s->fft_size != (1 << (s->fft_order - 1))) { av_log(avctx, AV_LOG_ERROR, "FFT size %d not power of 2.\n", s->fft_size); @@ -1951,7 +1949,7 @@ static int qdm2_decode(QDM2Context *q, const uint8_t *in, int16_t *out) q->sub_packet = (q->sub_packet + 1) % 16; - /* clip and convert output float[] to 16bit signed samples */ + /* clip and convert output float[] to 16-bit signed samples */ for (i = 0; i < frame_size; i++) { int value = (int)q->output_buffer[i]; @@ -1990,8 +1988,8 @@ static int qdm2_decode_frame(AVCodecContext *avctx, void *data, out = (int16_t *)frame->data[0]; for (i = 0; i < 16; i++) { - if (qdm2_decode(s, buf, out) < 0) - return -1; + if ((ret = qdm2_decode(s, buf, out)) < 0) + return ret; out += s->channels * s->frame_size; } @@ -2010,5 +2008,5 @@ AVCodec ff_qdm2_decoder = { .init_static_data = qdm2_init_static_data, .close = qdm2_decode_close, .decode = qdm2_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index c365bfd..b7493e4 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -1,6 +1,7 @@ /* * QuickDraw (qdrw) codec * Copyright (c) 2004 Konstantin Shishkov + * Copyright (c) 2015 Vittorio Giovara * * This file is part of Libav. * @@ -22,124 +23,283 @@ /** * @file * Apple QuickDraw codec. + * https://developer.apple.com/legacy/library/documentation/mac/QuickDraw/QuickDraw-461.html */ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "bytestream.h" #include "internal.h" -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) -{ - const uint8_t *buf = avpkt->data; - const uint8_t *buf_end = avpkt->data + avpkt->size; - int buf_size = avpkt->size; - AVFrame * const p = data; - uint8_t* outdata; - int colors; - int i, ret; - uint32_t *pal; - int r, g, b; +enum QuickdrawOpcodes { + PACKBITSRECT = 0x0098, + PACKBITSRGN, + DIRECTBITSRECT, + DIRECTBITSRGN, - if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return ret; - } - p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; - - outdata = p->data[0]; - - if (buf_end - buf < 0x68 + 4) - return AVERROR_INVALIDDATA; - buf += 0x68; /* jump to palette */ - colors = AV_RB32(buf); - buf += 4; + EOP = 0x00FF, +}; - if (colors < 0 || colors > 256) { - av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); - return AVERROR_INVALIDDATA; - } - if (buf_end - buf < (colors + 1) * 8) - return AVERROR_INVALIDDATA; +static int parse_palette(AVCodecContext *avctx, GetByteContext *gbc, + uint32_t *pal, int colors) +{ + int i; - pal = (uint32_t*)p->data[1]; for (i = 0; i <= colors; i++) { - unsigned int idx; - idx = AV_RB16(buf); /* color index */ - buf += 2; - + uint8_t r, g, b; + unsigned int idx = bytestream2_get_be16(gbc); /* color index */ if (idx > 255) { - av_log(avctx, AV_LOG_ERROR, "Palette index out of range: %u\n", idx); - buf += 6; + av_log(avctx, AV_LOG_WARNING, + "Palette index out of range: %u\n", idx); + bytestream2_skip(gbc, 6); continue; } - r = *buf++; - buf++; - g = *buf++; - buf++; - b = *buf++; - buf++; - pal[idx] = (r << 16) | (g << 8) | b; + r = bytestream2_get_byte(gbc); + bytestream2_skip(gbc, 1); + g = bytestream2_get_byte(gbc); + bytestream2_skip(gbc, 1); + b = bytestream2_get_byte(gbc); + bytestream2_skip(gbc, 1); + pal[idx] = (0xFFU << 24) | (r << 16) | (g << 8) | b; } - p->palette_has_changed = 1; + return 0; +} + +static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc, + int step) +{ + int i, j; + int offset = avctx->width * step; + uint8_t *outdata = p->data[0]; - if (buf_end - buf < 18) - return AVERROR_INVALIDDATA; - buf += 18; /* skip unneeded data */ for (i = 0; i < avctx->height; i++) { int size, left, code, pix; - const uint8_t *next; - uint8_t *out; - int tsize = 0; + uint8_t *out = outdata; + int pos = 0; - /* decode line */ - out = outdata; - size = AV_RB16(buf); /* size of packed line */ - buf += 2; - if (buf_end - buf < size) + /* size of packed line */ + size = left = bytestream2_get_be16(gbc); + if (bytestream2_get_bytes_left(gbc) < size) return AVERROR_INVALIDDATA; - left = size; - next = buf + size; + /* decode line */ while (left > 0) { - code = *buf++; + code = bytestream2_get_byte(gbc); if (code & 0x80 ) { /* run */ - pix = *buf++; - if ((out + (257 - code)) > (outdata + p->linesize[0])) - break; - memset(out, pix, 257 - code); - out += 257 - code; - tsize += 257 - code; + pix = bytestream2_get_byte(gbc); + for (j = 0; j < 257 - code; j++) { + out[pos] = pix; + pos += step; + if (pos >= offset) { + pos -= offset; + pos++; + } + } left -= 2; } else { /* copy */ - if ((out + code) > (outdata + p->linesize[0])) - break; - if (buf_end - buf < code + 1) - return AVERROR_INVALIDDATA; - memcpy(out, buf, code + 1); - out += code + 1; - buf += code + 1; + for (j = 0; j < code + 1; j++) { + out[pos] = bytestream2_get_byte(gbc); + pos += step; + if (pos >= offset) { + pos -= offset; + pos++; + } + } left -= 2 + code; - tsize += code + 1; } } - buf = next; outdata += p->linesize[0]; } - - *got_frame = 1; - - return buf_size; + return 0; } -static av_cold int decode_init(AVCodecContext *avctx) +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) { - avctx->pix_fmt= AV_PIX_FMT_PAL8; + AVFrame * const p = data; + GetByteContext gbc; + int colors; + int w, h, ret; - return 0; + bytestream2_init(&gbc, avpkt->data, avpkt->size); + + /* PICT images start with a 512 bytes empty header */ + if (bytestream2_peek_be32(&gbc) == 0) + bytestream2_skip(&gbc, 512); + + /* smallest PICT header */ + if (bytestream2_get_bytes_left(&gbc) < 40) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small %d\n", + bytestream2_get_bytes_left(&gbc)); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbc, 6); + h = bytestream2_get_be16(&gbc); + w = bytestream2_get_be16(&gbc); + + ret = ff_set_dimensions(avctx, w, h); + if (ret < 0) + return ret; + + /* version 1 is identified by 0x1101 + * it uses byte-aligned opcodes rather than word-aligned */ + if (bytestream2_get_be32(&gbc) != 0x001102FF) { + avpriv_request_sample(avctx, "QuickDraw version 1"); + return AVERROR_PATCHWELCOME; + } + + bytestream2_skip(&gbc, 26); + + while (bytestream2_get_bytes_left(&gbc) >= 4) { + int bppcnt, bpp; + int rowbytes, pack_type; + int opcode = bytestream2_get_be16(&gbc); + + switch(opcode) { + case PACKBITSRECT: + case PACKBITSRGN: + av_log(avctx, AV_LOG_DEBUG, "Parsing Packbit opcode\n"); + + bytestream2_skip(&gbc, 30); + bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */ + bpp = bytestream2_get_be16(&gbc); /* cmpSize */ + + av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); + if (bppcnt == 1 && bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + av_log(avctx, AV_LOG_ERROR, + "Invalid pixel format (bppcnt %d bpp %d) in Packbit\n", + bppcnt, bpp); + return AVERROR_INVALIDDATA; + } + + /* jump to palette */ + bytestream2_skip(&gbc, 18); + colors = bytestream2_get_be16(&gbc); + + if (colors < 0 || colors > 256) { + av_log(avctx, AV_LOG_ERROR, + "Error color count - %i(0x%X)\n", colors, colors); + return AVERROR_INVALIDDATA; + } + if (bytestream2_get_bytes_left(&gbc) < (colors + 1) * 8) { + av_log(avctx, AV_LOG_ERROR, "Palette is too small %d\n", + bytestream2_get_bytes_left(&gbc)); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + parse_palette(avctx, &gbc, (uint32_t *)p->data[1], colors); + p->palette_has_changed = 1; + + /* jump to image data */ + bytestream2_skip(&gbc, 18); + + if (opcode == PACKBITSRGN) { + bytestream2_skip(&gbc, 2 + 8); /* size + rect */ + avpriv_report_missing_feature(avctx, "Packbit mask region"); + } + + ret = decode_rle(avctx, p, &gbc, bppcnt); + if (ret < 0) + return ret; + *got_frame = 1; + break; + case DIRECTBITSRECT: + case DIRECTBITSRGN: + av_log(avctx, AV_LOG_DEBUG, "Parsing Directbit opcode\n"); + + bytestream2_skip(&gbc, 4); + rowbytes = bytestream2_get_be16(&gbc) & 0x3FFF; + if (rowbytes <= 250) { + avpriv_report_missing_feature(avctx, "Short rowbytes"); + return AVERROR_PATCHWELCOME; + } + + bytestream2_skip(&gbc, 10); + pack_type = bytestream2_get_be16(&gbc); + + bytestream2_skip(&gbc, 16); + bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */ + bpp = bytestream2_get_be16(&gbc); /* cmpSize */ + + av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); + if (bppcnt == 3 && bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else if (bppcnt == 4 && bpp == 8) { + avctx->pix_fmt = AV_PIX_FMT_ARGB; + } else { + av_log(avctx, AV_LOG_ERROR, + "Invalid pixel format (bppcnt %d bpp %d) in Directbit\n", + bppcnt, bpp); + return AVERROR_INVALIDDATA; + } + + /* set packing when default is selected */ + if (pack_type == 0) + pack_type = bppcnt; + + if (pack_type != 3 && pack_type != 4) { + avpriv_request_sample(avctx, "Pack type %d", pack_type); + return AVERROR_PATCHWELCOME; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + + /* jump to data */ + bytestream2_skip(&gbc, 30); + + if (opcode == DIRECTBITSRGN) { + bytestream2_skip(&gbc, 2 + 8); /* size + rect */ + avpriv_report_missing_feature(avctx, "DirectBit mask region"); + } + + ret = decode_rle(avctx, p, &gbc, bppcnt); + if (ret < 0) + return ret; + *got_frame = 1; + break; + default: + av_log(avctx, AV_LOG_TRACE, "Unknown 0x%04X opcode\n", opcode); + break; + } + /* exit the loop when a known pixel block has been found */ + if (*got_frame) { + int eop, trail; + + /* re-align to a word */ + bytestream2_skip(&gbc, bytestream2_get_bytes_left(&gbc) % 2); + + eop = bytestream2_get_be16(&gbc); + trail = bytestream2_get_bytes_left(&gbc); + if (eop != EOP) + av_log(avctx, AV_LOG_WARNING, + "Missing end of picture opcode (found 0x%04X)\n", eop); + if (trail) + av_log(avctx, AV_LOG_WARNING, "Got %d trailing bytes\n", trail); + break; + } + } + + if (*got_frame) { + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + return avpkt->size; + } else { + av_log(avctx, AV_LOG_ERROR, "Frame contained no usable data\n"); + + return AVERROR_INVALIDDATA; + } } AVCodec ff_qdraw_decoder = { @@ -147,7 +307,6 @@ AVCodec ff_qdraw_decoder = { .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_QDRAW, - .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index 4de1655..3a2e56c 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -161,9 +161,9 @@ static void qpeg_decode_inter(QpegContext *qctx, uint8_t *dst, /* 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) || + (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", + av_log(qctx->avctx, 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 */ @@ -327,5 +327,5 @@ AVCodec ff_qpeg_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c new file mode 100644 index 0000000..45a353a --- /dev/null +++ b/libavcodec/qsv.c @@ -0,0 +1,380 @@ +/* + * Intel MediaSDK QSV encoder/decoder shared code + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" + +#include "avcodec.h" +#include "qsv_internal.h" + +int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id) +{ + switch (codec_id) { + case AV_CODEC_ID_H264: + return MFX_CODEC_AVC; +#if QSV_VERSION_ATLEAST(1, 8) + case AV_CODEC_ID_HEVC: + return MFX_CODEC_HEVC; +#endif + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + return MFX_CODEC_MPEG2; + case AV_CODEC_ID_VC1: + return MFX_CODEC_VC1; + default: + break; + } + + return AVERROR(ENOSYS); +} + +static const struct { + mfxStatus mfxerr; + int averr; + const char *desc; +} qsv_errors[] = { + { MFX_ERR_NONE, 0, "success" }, + { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" }, + { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" }, + { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" }, + { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" }, + { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" }, + { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" }, + { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" }, + { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" }, + { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" }, + /* the following 3 errors should always be handled explicitly, so those "mappings" + * are for completeness only */ + { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" }, + { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" }, + { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" }, + { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" }, + { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" }, + { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" }, + { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" }, + { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" }, + { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" }, + { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" }, + { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" }, + + { MFX_WRN_IN_EXECUTION, 0, "operation in execution" }, + { MFX_WRN_DEVICE_BUSY, 0, "device busy" }, + { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" }, + { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" }, + { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" }, + { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" }, + { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" }, + { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" }, + { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" }, +}; + +int ff_qsv_map_error(mfxStatus mfx_err, const char **desc) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) { + if (qsv_errors[i].mfxerr == mfx_err) { + if (desc) + *desc = qsv_errors[i].desc; + return qsv_errors[i].averr; + } + } + if (desc) + *desc = "unknown error"; + return AVERROR_UNKNOWN; +} + +int ff_qsv_print_error(void *log_ctx, mfxStatus err, + const char *error_string) +{ + const char *desc; + int ret; + ret = ff_qsv_map_error(err, &desc); + av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err); + return ret; +} + +int ff_qsv_print_warning(void *log_ctx, mfxStatus err, + const char *warning_string) +{ + const char *desc; + int ret; + ret = ff_qsv_map_error(err, &desc); + av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err); + return ret; +} + +int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc) +{ + switch (format) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_NV12: + *fourcc = MFX_FOURCC_NV12; + return AV_PIX_FMT_NV12; + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_P010: + *fourcc = MFX_FOURCC_P010; + return AV_PIX_FMT_P010; + default: + return AVERROR(ENOSYS); + } +} + +static int qsv_load_plugins(mfxSession session, const char *load_plugins, + void *logctx) +{ + if (!load_plugins || !*load_plugins) + return 0; + + while (*load_plugins) { + mfxPluginUID uid; + mfxStatus ret; + int i, err = 0; + + char *plugin = av_get_token(&load_plugins, ":"); + if (!plugin) + return AVERROR(ENOMEM); + if (strlen(plugin) != 2 * sizeof(uid.Data)) { + av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID length\n"); + err = AVERROR(EINVAL); + goto load_plugin_fail; + } + + for (i = 0; i < sizeof(uid.Data); i++) { + err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i); + if (err != 1) { + av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID\n"); + err = AVERROR(EINVAL); + goto load_plugin_fail; + } + + } + + ret = MFXVideoUSER_Load(session, &uid, 1); + if (ret < 0) { + char errorbuf[128]; + snprintf(errorbuf, sizeof(errorbuf), + "Could not load the requested plugin '%s'", plugin); + err = ff_qsv_print_error(logctx, ret, errorbuf); + goto load_plugin_fail; + } + + if (*load_plugins) + load_plugins++; +load_plugin_fail: + av_freep(&plugin); + if (err < 0) + return err; + } + + return 0; + +} + +int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, + const char *load_plugins) +{ + mfxIMPL impl = MFX_IMPL_AUTO_ANY; + mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } }; + + const char *desc; + int ret; + + ret = MFXInit(impl, &ver, session); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error initializing an internal MFX session"); + + ret = qsv_load_plugins(*session, load_plugins, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); + return ret; + } + + MFXQueryIMPL(*session, &impl); + + switch (MFX_IMPL_BASETYPE(impl)) { + case MFX_IMPL_SOFTWARE: + desc = "software"; + break; + case MFX_IMPL_HARDWARE: + case MFX_IMPL_HARDWARE2: + case MFX_IMPL_HARDWARE3: + case MFX_IMPL_HARDWARE4: + desc = "hardware accelerated"; + break; + default: + desc = "unknown"; + } + + av_log(avctx, AV_LOG_VERBOSE, + "Initialized an internal MFX session using %s implementation\n", + desc); + + return 0; +} + +static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + QSVFramesContext *ctx = pthis; + mfxFrameInfo *i = &req->Info; + mfxFrameInfo *i1 = &ctx->info; + + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) || + !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)) || + !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) + return MFX_ERR_UNSUPPORTED; + if (i->Width != i1->Width || i->Height != i1->Height || + i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) { + av_log(ctx, AV_LOG_ERROR, "Mismatching surface properties in an " + "allocation request: %dx%d %d %d vs %dx%d %d %d\n", + i->Width, i->Height, i->FourCC, i->ChromaFormat, + i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat); + return MFX_ERR_UNSUPPORTED; + } + + resp->mids = ctx->mids; + resp->NumFrameActual = ctx->nb_mids; + + return MFX_ERR_NONE; +} + +static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + return MFX_ERR_NONE; +} + +static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession, + QSVFramesContext *qsv_frames_ctx, + const char *load_plugins, int opaque) +{ + static const mfxHandleType handle_types[] = { + MFX_HANDLE_VA_DISPLAY, + MFX_HANDLE_D3D9_DEVICE_MANAGER, + MFX_HANDLE_D3D11_DEVICE, + }; + mfxFrameAllocator frame_allocator = { + .pthis = qsv_frames_ctx, + .Alloc = qsv_frame_alloc, + .Lock = qsv_frame_lock, + .Unlock = qsv_frame_unlock, + .GetHDL = qsv_frame_get_hdl, + .Free = qsv_frame_free, + }; + + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + AVQSVDeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + mfxSession parent_session = device_hwctx->session; + + mfxSession session; + mfxVersion ver; + mfxIMPL impl; + mfxHDL handle = NULL; + mfxHandleType handle_type; + mfxStatus err; + + int i, ret; + + err = MFXQueryIMPL(parent_session, &impl); + if (err == MFX_ERR_NONE) + err = MFXQueryVersion(parent_session, &ver); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error querying the session attributes"); + + for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { + err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle); + if (err == MFX_ERR_NONE) { + handle_type = handle_types[i]; + break; + } + handle = NULL; + } + if (!handle) { + av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved " + "from the session\n"); + } + + err = MFXInit(impl, &ver, &session); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error initializing a child MFX session"); + + if (handle) { + err = MFXVideoCORE_SetHandle(session, handle_type, handle); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error setting a HW handle"); + } + + ret = qsv_load_plugins(session, load_plugins, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); + return ret; + } + + if (!opaque) { + av_freep(&qsv_frames_ctx->mids); + qsv_frames_ctx->mids = av_mallocz_array(frames_hwctx->nb_surfaces, + sizeof(*qsv_frames_ctx->mids)); + if (!qsv_frames_ctx->mids) + return AVERROR(ENOMEM); + + qsv_frames_ctx->info = frames_hwctx->surfaces[0].Info; + qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces; + for (i = 0; i < frames_hwctx->nb_surfaces; i++) + qsv_frames_ctx->mids[i] = frames_hwctx->surfaces[i].Data.MemId; + + err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error setting a frame allocator"); + } + + *psession = session; + return 0; +} diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h new file mode 100644 index 0000000..1d1f8b4 --- /dev/null +++ b/libavcodec/qsv.h @@ -0,0 +1,107 @@ +/* + * Intel MediaSDK QSV public API + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_QSV_H +#define AVCODEC_QSV_H + +#include + +#include "libavutil/buffer.h" + +/** + * This struct is used for communicating QSV parameters between libavcodec and + * the caller. It is managed by the caller and must be assigned to + * AVCodecContext.hwaccel_context. + * - decoding: hwaccel_context must be set on return from the get_format() + * callback + * - encoding: hwaccel_context must be set before avcodec_open2() + */ +typedef struct AVQSVContext { + /** + * If non-NULL, the session to use for encoding or decoding. + * Otherwise, libavcodec will try to create an internal session. + */ + mfxSession session; + + /** + * The IO pattern to use. + */ + int iopattern; + + /** + * Extra buffers to pass to encoder or decoder initialization. + */ + mfxExtBuffer **ext_buffers; + int nb_ext_buffers; + + /** + * Encoding only. If this field is set to non-zero by the caller, libavcodec + * will create an mfxExtOpaqueSurfaceAlloc extended buffer and pass it to + * the encoder initialization. This only makes sense if iopattern is also + * set to MFX_IOPATTERN_IN_OPAQUE_MEMORY. + * + * The number of allocated opaque surfaces will be the sum of the number + * required by the encoder and the user-provided value nb_opaque_surfaces. + * The array of the opaque surfaces will be exported to the caller through + * the opaque_surfaces field. + */ + int opaque_alloc; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. Before + * calling avcodec_open2(), the caller should set this field to the number + * of extra opaque surfaces to allocate beyond what is required by the + * encoder. + * + * On return from avcodec_open2(), this field will be set by libavcodec to + * the total number of allocated opaque surfaces. + */ + int nb_opaque_surfaces; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. On return + * from avcodec_open2(), this field will be used by libavcodec to export the + * array of the allocated opaque surfaces to the caller, so they can be + * passed to other parts of the pipeline. + * + * The buffer reference exported here is owned and managed by libavcodec, + * the callers should make their own reference with av_buffer_ref() and free + * it with av_buffer_unref() when it is no longer needed. + * + * The buffer data is an nb_opaque_surfaces-sized array of mfxFrameSurface1. + */ + AVBufferRef *opaque_surfaces; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. On return + * from avcodec_open2(), this field will be set to the surface type used in + * the opaque allocation request. + */ + int opaque_alloc_type; +} AVQSVContext; + +/** + * Allocate a new context. + * + * It must be freed by the caller with av_free(). + */ +AVQSVContext *av_qsv_alloc_context(void); + +#endif /* AVCODEC_QSV_H */ diff --git a/libavcodec/qsv_api.c b/libavcodec/qsv_api.c new file mode 100644 index 0000000..234b596 --- /dev/null +++ b/libavcodec/qsv_api.c @@ -0,0 +1,42 @@ +/* + * Intel MediaSDK QSV public API functions + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include + +#include "libavutil/mem.h" + +#if CONFIG_QSV +#include "qsv.h" + +AVQSVContext *av_qsv_alloc_context(void) +{ + return av_mallocz(sizeof(AVQSVContext)); +} +#else + +struct AVQSVContext *av_qsv_alloc_context(void); + +struct AVQSVContext *av_qsv_alloc_context(void) +{ + return NULL; +} +#endif diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h new file mode 100644 index 0000000..41f4c3d --- /dev/null +++ b/libavcodec/qsv_internal.h @@ -0,0 +1,79 @@ +/* + * Intel MediaSDK QSV encoder/decoder shared code + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_QSV_INTERNAL_H +#define AVCODEC_QSV_INTERNAL_H + +#include + +#include "libavutil/frame.h" + +#include "avcodec.h" + +#define QSV_VERSION_MAJOR 1 +#define QSV_VERSION_MINOR 1 + +#define ASYNC_DEPTH_DEFAULT 4 // internal parallelism + +#define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ + (MFX_VERSION_MAJOR > (MAJOR) || \ + MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) + +typedef struct QSVFrame { + AVFrame *frame; + mfxFrameSurface1 *surface; + + mfxFrameSurface1 surface_internal; + + int queued; + + struct QSVFrame *next; +} QSVFrame; + +typedef struct QSVFramesContext { + AVBufferRef *hw_frames_ctx; + mfxFrameInfo info; + mfxMemId *mids; + int nb_mids; +} QSVFramesContext; + +/** + * Convert a libmfx error code into a libav error code. + */ +int ff_qsv_map_error(mfxStatus mfx_err, const char **desc); + +int ff_qsv_print_error(void *log_ctx, mfxStatus err, + const char *error_string); + +int ff_qsv_print_warning(void *log_ctx, mfxStatus err, + const char *warning_string); + +int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id); + +int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc); + +int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, + const char *load_plugins); + +int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session, + QSVFramesContext *qsv_frames_ctx, + const char *load_plugins, int opaque); + +#endif /* AVCODEC_QSV_INTERNAL_H */ diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c new file mode 100644 index 0000000..e19eba5 --- /dev/null +++ b/libavcodec/qsvdec.c @@ -0,0 +1,501 @@ +/* + * Intel MediaSDK QSV codec-independent code + * + * copyright (c) 2013 Luca Barbato + * copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/mem.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" +#include "libavutil/time.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvdec.h" + +static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, + AVBufferRef *hw_frames_ref) +{ + int ret; + + if (session) { + q->session = session; + } else if (hw_frames_ref) { + if (q->internal_session) { + MFXClose(q->internal_session); + q->internal_session = NULL; + } + av_buffer_unref(&q->frames_ctx.hw_frames_ctx); + + q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref); + if (!q->frames_ctx.hw_frames_ctx) + return AVERROR(ENOMEM); + + ret = ff_qsv_init_session_hwcontext(avctx, &q->internal_session, + &q->frames_ctx, q->load_plugins, + q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); + if (ret < 0) { + av_buffer_unref(&q->frames_ctx.hw_frames_ctx); + return ret; + } + + q->session = q->internal_session; + } else { + if (!q->internal_session) { + ret = ff_qsv_init_internal_session(avctx, &q->internal_session, + q->load_plugins); + if (ret < 0) + return ret; + } + + q->session = q->internal_session; + } + + /* make sure the decoder is uninitialized */ + MFXVideoDECODE_Close(q->session); + + return 0; +} + +static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) +{ + const AVPixFmtDescriptor *desc; + mfxSession session = NULL; + int iopattern = 0; + mfxVideoParam param = { { 0 } }; + int frame_width = avctx->coded_width; + int frame_height = avctx->coded_height; + int ret; + + desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!desc) + return AVERROR_BUG; + + if (!q->async_fifo) { + q->async_fifo = av_fifo_alloc((1 + q->async_depth) * + (sizeof(mfxSyncPoint*) + sizeof(QSVFrame*))); + if (!q->async_fifo) + return AVERROR(ENOMEM); + } + + if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) { + AVQSVContext *user_ctx = avctx->hwaccel_context; + session = user_ctx->session; + iopattern = user_ctx->iopattern; + q->ext_buffers = user_ctx->ext_buffers; + q->nb_ext_buffers = user_ctx->nb_ext_buffers; + } + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + + if (!iopattern) { + if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME) + iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) + iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; + } + + frame_width = frames_hwctx->surfaces[0].Info.Width; + frame_height = frames_hwctx->surfaces[0].Info.Height; + } + + if (!iopattern) + iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + q->iopattern = iopattern; + + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); + return ret; + } + + ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); + if (ret < 0) + return ret; + + param.mfx.CodecId = ret; + param.mfx.CodecProfile = avctx->profile; + param.mfx.CodecLevel = avctx->level; + + param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; + param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; + param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + param.mfx.FrameInfo.FourCC = q->fourcc; + param.mfx.FrameInfo.Width = frame_width; + param.mfx.FrameInfo.Height = frame_height; + param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + + param.IOPattern = q->iopattern; + param.AsyncDepth = q->async_depth; + param.ExtParam = q->ext_buffers; + param.NumExtParam = q->nb_ext_buffers; + + ret = MFXVideoDECODE_Init(q->session, ¶m); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error initializing the MFX video decoder"); + + q->frame_info = param.mfx.FrameInfo; + + return 0; +} + +static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) +{ + int ret; + + ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) + return ret; + + if (frame->frame->format == AV_PIX_FMT_QSV) { + frame->surface = (mfxFrameSurface1*)frame->frame->data[3]; + } else { + frame->surface_internal.Info = q->frame_info; + + frame->surface_internal.Data.PitchLow = frame->frame->linesize[0]; + frame->surface_internal.Data.Y = frame->frame->data[0]; + frame->surface_internal.Data.UV = frame->frame->data[1]; + + frame->surface = &frame->surface_internal; + } + + return 0; +} + +static void qsv_clear_unused_frames(QSVContext *q) +{ + QSVFrame *cur = q->work_frames; + while (cur) { + if (cur->surface && !cur->surface->Data.Locked && !cur->queued) { + cur->surface = NULL; + av_frame_unref(cur->frame); + } + cur = cur->next; + } +} + +static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf) +{ + QSVFrame *frame, **last; + int ret; + + qsv_clear_unused_frames(q); + + frame = q->work_frames; + last = &q->work_frames; + while (frame) { + if (!frame->surface) { + ret = alloc_frame(avctx, q, frame); + if (ret < 0) + return ret; + *surf = frame->surface; + return 0; + } + + last = &frame->next; + frame = frame->next; + } + + frame = av_mallocz(sizeof(*frame)); + if (!frame) + return AVERROR(ENOMEM); + frame->frame = av_frame_alloc(); + if (!frame->frame) { + av_freep(&frame); + return AVERROR(ENOMEM); + } + *last = frame; + + ret = alloc_frame(avctx, q, frame); + if (ret < 0) + return ret; + + *surf = frame->surface; + + return 0; +} + +static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) +{ + QSVFrame *cur = q->work_frames; + while (cur) { + if (surf == cur->surface) + return cur; + cur = cur->next; + } + return NULL; +} + +static int qsv_decode(AVCodecContext *avctx, QSVContext *q, + AVFrame *frame, int *got_frame, + AVPacket *avpkt) +{ + QSVFrame *out_frame; + mfxFrameSurface1 *insurf; + mfxFrameSurface1 *outsurf; + mfxSyncPoint *sync; + mfxBitstream bs = { { { 0 } } }; + int ret; + + if (avpkt->size) { + bs.Data = avpkt->data; + bs.DataLength = avpkt->size; + bs.MaxLength = bs.DataLength; + bs.TimeStamp = avpkt->pts; + } + + sync = av_mallocz(sizeof(*sync)); + if (!sync) { + av_freep(&sync); + return AVERROR(ENOMEM); + } + + do { + ret = get_surface(avctx, q, &insurf); + if (ret < 0) + return ret; + + ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL, + insurf, &outsurf, sync); + if (ret == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + + } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); + + if (ret != MFX_ERR_NONE && + ret != MFX_ERR_MORE_DATA && + ret != MFX_WRN_VIDEO_PARAM_CHANGED && + ret != MFX_ERR_MORE_SURFACE) { + av_freep(&sync); + return ff_qsv_print_error(avctx, ret, + "Error during QSV decoding."); + } + + /* make sure we do not enter an infinite loop if the SDK + * did not consume any data and did not return anything */ + if (!*sync && !bs.DataOffset) { + av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n"); + bs.DataOffset = avpkt->size; + } + + if (*sync) { + QSVFrame *out_frame = find_frame(q, outsurf); + + if (!out_frame) { + av_log(avctx, AV_LOG_ERROR, + "The returned surface does not correspond to any frame\n"); + av_freep(&sync); + return AVERROR_BUG; + } + + out_frame->queued = 1; + av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); + av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); + } else { + av_freep(&sync); + } + + if (!av_fifo_space(q->async_fifo) || + (!avpkt->size && av_fifo_size(q->async_fifo))) { + AVFrame *src_frame; + + av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); + av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); + out_frame->queued = 0; + + do { + ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000); + } while (ret == MFX_WRN_IN_EXECUTION); + + av_freep(&sync); + + src_frame = out_frame->frame; + + ret = av_frame_ref(frame, src_frame); + if (ret < 0) + return ret; + + outsurf = out_frame->surface; + +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pts = outsurf->Data.TimeStamp; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->pts = outsurf->Data.TimeStamp; + + frame->repeat_pict = + outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 : + outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 : + outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0; + frame->top_field_first = + outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF; + frame->interlaced_frame = + !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); + + *got_frame = 1; + } + + return bs.DataOffset; +} + +int ff_qsv_decode_close(QSVContext *q) +{ + QSVFrame *cur = q->work_frames; + + if (q->session) + MFXVideoDECODE_Close(q->session); + + while (q->async_fifo && av_fifo_size(q->async_fifo)) { + QSVFrame *out_frame; + mfxSyncPoint *sync; + + av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); + av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); + + av_freep(&sync); + } + + while (cur) { + q->work_frames = cur->next; + av_frame_free(&cur->frame); + av_freep(&cur); + cur = q->work_frames; + } + + av_fifo_free(q->async_fifo); + q->async_fifo = NULL; + + av_parser_close(q->parser); + avcodec_free_context(&q->avctx_internal); + + if (q->internal_session) + MFXClose(q->internal_session); + + av_buffer_unref(&q->frames_ctx.hw_frames_ctx); + av_freep(&q->frames_ctx.mids); + q->frames_ctx.nb_mids = 0; + + return 0; +} + +int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, + AVFrame *frame, int *got_frame, AVPacket *pkt) +{ + uint8_t *dummy_data; + int dummy_size; + int ret; + + if (!q->avctx_internal) { + q->avctx_internal = avcodec_alloc_context3(NULL); + if (!q->avctx_internal) + return AVERROR(ENOMEM); + + if (avctx->extradata) { + q->avctx_internal->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!q->avctx_internal->extradata) + return AVERROR(ENOMEM); + + memcpy(q->avctx_internal->extradata, avctx->extradata, + avctx->extradata_size); + q->avctx_internal->extradata_size = avctx->extradata_size; + } + + q->parser = av_parser_init(avctx->codec_id); + if (!q->parser) + return AVERROR(ENOMEM); + + q->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + q->orig_pix_fmt = AV_PIX_FMT_NONE; + } + + if (!pkt->size) + return qsv_decode(avctx, q, frame, got_frame, pkt); + + /* we assume the packets are already split properly and want + * just the codec parameters here */ + av_parser_parse2(q->parser, q->avctx_internal, + &dummy_data, &dummy_size, + pkt->data, pkt->size, pkt->pts, pkt->dts, + pkt->pos); + + /* TODO: flush delayed frames on reinit */ + if (q->parser->format != q->orig_pix_fmt || + q->parser->coded_width != avctx->coded_width || + q->parser->coded_height != avctx->coded_height) { + enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE, + AV_PIX_FMT_NONE }; + enum AVPixelFormat qsv_format; + + qsv_format = ff_qsv_map_pixfmt(q->parser->format, &q->fourcc); + if (qsv_format < 0) { + av_log(avctx, AV_LOG_ERROR, + "Decoding pixel format '%s' is not supported\n", + av_get_pix_fmt_name(q->parser->format)); + ret = AVERROR(ENOSYS); + goto reinit_fail; + } + + q->orig_pix_fmt = q->parser->format; + avctx->pix_fmt = pix_fmts[1] = qsv_format; + avctx->width = q->parser->width; + avctx->height = q->parser->height; + avctx->coded_width = q->parser->coded_width; + avctx->coded_height = q->parser->coded_height; + avctx->level = q->avctx_internal->level; + avctx->profile = q->avctx_internal->profile; + + ret = ff_get_format(avctx, pix_fmts); + if (ret < 0) + goto reinit_fail; + + avctx->pix_fmt = ret; + + ret = qsv_decode_init(avctx, q); + if (ret < 0) + goto reinit_fail; + } + + return qsv_decode(avctx, q, frame, got_frame, pkt); + +reinit_fail: + q->orig_pix_fmt = q->parser->format = avctx->pix_fmt = AV_PIX_FMT_NONE; + return ret; +} + +void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q) +{ + q->orig_pix_fmt = AV_PIX_FMT_NONE; +} diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h new file mode 100644 index 0000000..d807864 --- /dev/null +++ b/libavcodec/qsvdec.h @@ -0,0 +1,79 @@ +/* + * Intel MediaSDK QSV utility functions + * + * copyright (c) 2013 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_QSVDEC_H +#define AVCODEC_QSVDEC_H + +#include +#include + +#include + +#include "libavutil/fifo.h" +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "qsv_internal.h" + +typedef struct QSVContext { + // the session used for decoding + mfxSession session; + + // the session we allocated internally, in case the caller did not provide + // one + mfxSession internal_session; + + QSVFramesContext frames_ctx; + + /** + * a linked list of frames currently being used by QSV + */ + QSVFrame *work_frames; + + AVFifoBuffer *async_fifo; + + // the internal parser and codec context for parsing the data + AVCodecParserContext *parser; + AVCodecContext *avctx_internal; + enum AVPixelFormat orig_pix_fmt; + uint32_t fourcc; + mfxFrameInfo frame_info; + + // options set by the caller + int async_depth; + int iopattern; + + char *load_plugins; + + mfxExtBuffer **ext_buffers; + int nb_ext_buffers; +} QSVContext; + +int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, + AVFrame *frame, int *got_frame, AVPacket *pkt); + +void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q); + +int ff_qsv_decode_close(QSVContext *q); + +#endif /* AVCODEC_QSVDEC_H */ diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c new file mode 100644 index 0000000..a26f150 --- /dev/null +++ b/libavcodec/qsvdec_h2645.c @@ -0,0 +1,315 @@ +/* + * Intel MediaSDK QSV based H.264 / HEVC decoder + * + * copyright (c) 2013 Luca Barbato + * copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/fifo.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv_internal.h" +#include "qsvdec.h" +#include "qsv.h" + +enum LoadPlugin { + LOAD_PLUGIN_NONE, + LOAD_PLUGIN_HEVC_SW, + LOAD_PLUGIN_HEVC_HW, +}; + +typedef struct QSVH2645Context { + AVClass *class; + QSVContext qsv; + + int load_plugin; + + // the filter for converting to Annex B + AVBSFContext *bsf; + + AVFifoBuffer *packet_fifo; + + AVPacket pkt_filtered; +} QSVH2645Context; + +static void qsv_clear_buffers(QSVH2645Context *s) +{ + AVPacket pkt; + while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { + av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + + av_bsf_free(&s->bsf); + + av_packet_unref(&s->pkt_filtered); +} + +static av_cold int qsv_decode_close(AVCodecContext *avctx) +{ + QSVH2645Context *s = avctx->priv_data; + + ff_qsv_decode_close(&s->qsv); + + qsv_clear_buffers(s); + + av_fifo_free(s->packet_fifo); + + return 0; +} + +static av_cold int qsv_decode_init(AVCodecContext *avctx) +{ + QSVH2645Context *s = avctx->priv_data; + int ret; + + if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) { + static const char *uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6"; + static const char *uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e"; + + if (s->qsv.load_plugins[0]) { + av_log(avctx, AV_LOG_WARNING, + "load_plugins is not empty, but load_plugin is not set to 'none'." + "The load_plugin value will be ignored.\n"); + } else { + av_freep(&s->qsv.load_plugins); + + if (s->load_plugin == LOAD_PLUGIN_HEVC_SW) + s->qsv.load_plugins = av_strdup(uid_hevcdec_sw); + else + s->qsv.load_plugins = av_strdup(uid_hevcdec_hw); + if (!s->qsv.load_plugins) + return AVERROR(ENOMEM); + } + } + + s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); + if (!s->packet_fifo) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; +fail: + qsv_decode_close(avctx); + return ret; +} + +static int qsv_init_bsf(AVCodecContext *avctx, QSVH2645Context *s) +{ + const char *filter_name = avctx->codec_id == AV_CODEC_ID_HEVC ? + "hevc_mp4toannexb" : "h264_mp4toannexb"; + const AVBitStreamFilter *filter; + int ret; + + if (s->bsf) + return 0; + + filter = av_bsf_get_by_name(filter_name); + if (!filter) + return AVERROR_BUG; + + ret = av_bsf_alloc(filter, &s->bsf); + if (ret < 0) + return ret; + + ret = avcodec_parameters_from_context(s->bsf->par_in, avctx); + if (ret < 0) + return ret; + + s->bsf->time_base_in = avctx->time_base; + + ret = av_bsf_init(s->bsf); + if (ret < 0) + return ret; + + return ret; +} + +static int qsv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + QSVH2645Context *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + /* make sure the bitstream filter is initialized */ + ret = qsv_init_bsf(avctx, s); + if (ret < 0) + return ret; + + /* buffer the input packet */ + if (avpkt->size) { + AVPacket input_ref = { 0 }; + + if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { + ret = av_fifo_realloc2(s->packet_fifo, + av_fifo_size(s->packet_fifo) + sizeof(input_ref)); + if (ret < 0) + return ret; + } + + ret = av_packet_ref(&input_ref, avpkt); + if (ret < 0) + return ret; + av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + } + + /* process buffered data */ + while (!*got_frame) { + /* prepare the input data -- convert to Annex B if needed */ + if (s->pkt_filtered.size <= 0) { + AVPacket input_ref; + + /* no more data */ + if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) + return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); + + av_packet_unref(&s->pkt_filtered); + + av_fifo_generic_read(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + ret = av_bsf_send_packet(s->bsf, &input_ref); + if (ret < 0) { + av_packet_unref(&input_ref); + return ret; + } + + ret = av_bsf_receive_packet(s->bsf, &s->pkt_filtered); + if (ret < 0) + av_packet_move_ref(&s->pkt_filtered, &input_ref); + else + av_packet_unref(&input_ref); + } + + ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->pkt_filtered); + if (ret < 0) + return ret; + + s->pkt_filtered.size -= ret; + s->pkt_filtered.data += ret; + } + + return avpkt->size; +} + +static void qsv_decode_flush(AVCodecContext *avctx) +{ + QSVH2645Context *s = avctx->priv_data; + + qsv_clear_buffers(s); + ff_qsv_decode_flush(avctx, &s->qsv); +} + +#define OFFSET(x) offsetof(QSVH2645Context, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +#if CONFIG_HEVC_QSV_DECODER +AVHWAccel ff_hevc_qsv_hwaccel = { + .name = "hevc_qsv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_QSV, +}; + +static const AVOption hevc_options[] = { + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, + + { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" }, + { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" }, + { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" }, + + { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session", + OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, + { NULL }, +}; + +static const AVClass hevc_class = { + .class_name = "hevc_qsv", + .item_name = av_default_item_name, + .option = hevc_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_hevc_qsv_decoder = { + .name = "hevc_qsv", + .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVH2645Context), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = qsv_decode_init, + .decode = qsv_decode_frame, + .flush = qsv_decode_flush, + .close = qsv_decode_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .priv_class = &hevc_class, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, +}; +#endif + +#if CONFIG_H264_QSV_DECODER +AVHWAccel ff_h264_qsv_hwaccel = { + .name = "h264_qsv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_QSV, +}; + +static const AVOption options[] = { + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "h264_qsv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_qsv_decoder = { + .name = "h264_qsv", + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVH2645Context), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = qsv_decode_init, + .decode = qsv_decode_frame, + .flush = qsv_decode_flush, + .close = qsv_decode_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .priv_class = &class, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, +}; +#endif diff --git a/libavcodec/qsvdec_mpeg2.c b/libavcodec/qsvdec_mpeg2.c new file mode 100644 index 0000000..2daad56 --- /dev/null +++ b/libavcodec/qsvdec_mpeg2.c @@ -0,0 +1,179 @@ +/* + * Intel MediaSDK QSV based MPEG-2 decoder + * + * copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/fifo.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv_internal.h" +#include "qsvdec.h" +#include "qsv.h" + +typedef struct QSVMPEG2Context { + AVClass *class; + QSVContext qsv; + + AVFifoBuffer *packet_fifo; + + AVPacket input_ref; +} QSVMPEG2Context; + +static void qsv_clear_buffers(QSVMPEG2Context *s) +{ + AVPacket pkt; + while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { + av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + + av_packet_unref(&s->input_ref); +} + +static av_cold int qsv_decode_close(AVCodecContext *avctx) +{ + QSVMPEG2Context *s = avctx->priv_data; + + ff_qsv_decode_close(&s->qsv); + + qsv_clear_buffers(s); + + av_fifo_free(s->packet_fifo); + + return 0; +} + +static av_cold int qsv_decode_init(AVCodecContext *avctx) +{ + QSVMPEG2Context *s = avctx->priv_data; + int ret; + + s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); + if (!s->packet_fifo) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; +fail: + qsv_decode_close(avctx); + return ret; +} + +static int qsv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + QSVMPEG2Context *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + /* buffer the input packet */ + if (avpkt->size) { + AVPacket input_ref = { 0 }; + + if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { + ret = av_fifo_realloc2(s->packet_fifo, + av_fifo_size(s->packet_fifo) + sizeof(input_ref)); + if (ret < 0) + return ret; + } + + ret = av_packet_ref(&input_ref, avpkt); + if (ret < 0) + return ret; + av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + } + + /* process buffered data */ + while (!*got_frame) { + if (s->input_ref.size <= 0) { + /* no more data */ + if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) + return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); + + av_packet_unref(&s->input_ref); + av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL); + } + + ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref); + if (ret < 0) + return ret; + + s->input_ref.size -= ret; + s->input_ref.data += ret; + } + + return avpkt->size; +} + +static void qsv_decode_flush(AVCodecContext *avctx) +{ + QSVMPEG2Context *s = avctx->priv_data; + + qsv_clear_buffers(s); + ff_qsv_decode_flush(avctx, &s->qsv); +} + +AVHWAccel ff_mpeg2_qsv_hwaccel = { + .name = "mpeg2_qsv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_QSV, +}; + +#define OFFSET(x) offsetof(QSVMPEG2Context, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "mpeg2_qsv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mpeg2_qsv_decoder = { + .name = "mpeg2_qsv", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVMPEG2Context), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .init = qsv_decode_init, + .decode = qsv_decode_frame, + .flush = qsv_decode_flush, + .close = qsv_decode_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .priv_class = &class, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, +}; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c new file mode 100644 index 0000000..ba07db6 --- /dev/null +++ b/libavcodec/qsvenc.c @@ -0,0 +1,1121 @@ +/* + * Intel MediaSDK QSV encoder utility functions + * + * copyright (c) 2013 Yukinori Yamazoe + * copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/mem.h" +#include "libavutil/log.h" +#include "libavutil/time.h" +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +static const struct { + mfxU16 profile; + const char *name; +} profile_names[] = { + { MFX_PROFILE_AVC_BASELINE, "baseline" }, + { MFX_PROFILE_AVC_MAIN, "main" }, + { MFX_PROFILE_AVC_EXTENDED, "extended" }, + { MFX_PROFILE_AVC_HIGH, "high" }, +#if QSV_VERSION_ATLEAST(1, 15) + { MFX_PROFILE_AVC_HIGH_422, "high 422" }, +#endif +#if QSV_VERSION_ATLEAST(1, 4) + { MFX_PROFILE_AVC_CONSTRAINED_BASELINE, "constrained baseline" }, + { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "constrained high" }, + { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "progressive high" }, +#endif + { MFX_PROFILE_MPEG2_SIMPLE, "simple" }, + { MFX_PROFILE_MPEG2_MAIN, "main" }, + { MFX_PROFILE_MPEG2_HIGH, "high" }, + { MFX_PROFILE_VC1_SIMPLE, "simple" }, + { MFX_PROFILE_VC1_MAIN, "main" }, + { MFX_PROFILE_VC1_ADVANCED, "advanced" }, +#if QSV_VERSION_ATLEAST(1, 8) + { MFX_PROFILE_HEVC_MAIN, "main" }, + { MFX_PROFILE_HEVC_MAIN10, "main10" }, + { MFX_PROFILE_HEVC_MAINSP, "mainsp" }, +#endif +}; + +static const char *print_profile(mfxU16 profile) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(profile_names); i++) + if (profile == profile_names[i].profile) + return profile_names[i].name; + return "unknown"; +} + +static const struct { + mfxU16 rc_mode; + const char *name; +} rc_names[] = { + { MFX_RATECONTROL_CBR, "CBR" }, + { MFX_RATECONTROL_VBR, "VBR" }, + { MFX_RATECONTROL_CQP, "CQP" }, + { MFX_RATECONTROL_AVBR, "AVBR" }, +#if QSV_HAVE_LA + { MFX_RATECONTROL_LA, "LA" }, +#endif +#if QSV_HAVE_ICQ + { MFX_RATECONTROL_ICQ, "ICQ" }, + { MFX_RATECONTROL_LA_ICQ, "LA_ICQ" }, +#endif +#if QSV_HAVE_VCM + { MFX_RATECONTROL_VCM, "VCM" }, +#endif +#if QSV_VERSION_ATLEAST(1, 10) + { MFX_RATECONTROL_LA_EXT, "LA_EXT" }, +#endif +#if QSV_HAVE_LA_HRD + { MFX_RATECONTROL_LA_HRD, "LA_HRD" }, +#endif +#if QSV_HAVE_QVBR + { MFX_RATECONTROL_QVBR, "QVBR" }, +#endif +}; + +static const char *print_ratecontrol(mfxU16 rc_mode) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(rc_names); i++) + if (rc_mode == rc_names[i].rc_mode) + return rc_names[i].name; + return "unknown"; +} + +static const char *print_threestate(mfxU16 val) +{ + if (val == MFX_CODINGOPTION_ON) + return "ON"; + else if (val == MFX_CODINGOPTION_OFF) + return "OFF"; + return "unknown"; +} + +static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, + mfxExtBuffer **coding_opts) +{ + mfxInfoMFX *info = &q->param.mfx; + + mfxExtCodingOption *co = (mfxExtCodingOption*)coding_opts[0]; +#if QSV_HAVE_CO2 + mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; +#endif +#if QSV_HAVE_CO3 + mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2]; +#endif + + av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", + print_profile(info->CodecProfile), info->CodecLevel); + + av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", + info->GopPicSize, info->GopRefDist); + if (info->GopOptFlag & MFX_GOP_CLOSED) + av_log(avctx, AV_LOG_VERBOSE, "closed "); + if (info->GopOptFlag & MFX_GOP_STRICT) + av_log(avctx, AV_LOG_VERBOSE, "strict "); + av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval); + + av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n", + info->TargetUsage, print_ratecontrol(info->RateControlMethod)); + + if (info->RateControlMethod == MFX_RATECONTROL_CBR || + info->RateControlMethod == MFX_RATECONTROL_VBR +#if QSV_HAVE_VCM + || info->RateControlMethod == MFX_RATECONTROL_VCM +#endif + ) { + av_log(avctx, AV_LOG_VERBOSE, + "InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"\n", + info->InitialDelayInKB, info->TargetKbps, info->MaxKbps); + } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) { + av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", + info->QPI, info->QPP, info->QPB); + } else if (info->RateControlMethod == MFX_RATECONTROL_AVBR) { + av_log(avctx, AV_LOG_VERBOSE, + "TargetKbps: %"PRIu16"; Accuracy: %"PRIu16"; Convergence: %"PRIu16"\n", + info->TargetKbps, info->Accuracy, info->Convergence); + } +#if QSV_HAVE_LA + else if (info->RateControlMethod == MFX_RATECONTROL_LA +#if QSV_HAVE_LA_HRD + || info->RateControlMethod == MFX_RATECONTROL_LA_HRD +#endif + ) { + av_log(avctx, AV_LOG_VERBOSE, + "TargetKbps: %"PRIu16"; LookAheadDepth: %"PRIu16"\n", + info->TargetKbps, co2->LookAheadDepth); + } +#endif +#if QSV_HAVE_ICQ + else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) { + av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); + } else if (info->RateControlMethod == MFX_RATECONTROL_LA_ICQ) { + av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"; LookAheadDepth: %"PRIu16"\n", + info->ICQQuality, co2->LookAheadDepth); + } +#endif +#if QSV_HAVE_QVBR + else if (info->RateControlMethod == MFX_RATECONTROL_QVBR) { + av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n", + co3->QVBRQuality); + } +#endif + + av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n", + info->NumSlice, info->NumRefFrame); + av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n", + print_threestate(co->RateDistortionOpt)); + +#if QSV_HAVE_CO2 + av_log(avctx, AV_LOG_VERBOSE, + "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", + print_threestate(co->RecoveryPointSEI), co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %"PRIu16"; ", co2->MaxFrameSize); +#if QSV_HAVE_MAX_SLICE_SIZE + av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %"PRIu16"; ", co2->MaxSliceSize); +#endif + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + +#if QSV_HAVE_TRELLIS + av_log(avctx, AV_LOG_VERBOSE, "Trellis: "); + if (co2->Trellis & MFX_TRELLIS_OFF) { + av_log(avctx, AV_LOG_VERBOSE, "off"); + } else if (!co2->Trellis) { + av_log(avctx, AV_LOG_VERBOSE, "auto"); + } else { + if (co2->Trellis & MFX_TRELLIS_I) av_log(avctx, AV_LOG_VERBOSE, "I"); + if (co2->Trellis & MFX_TRELLIS_P) av_log(avctx, AV_LOG_VERBOSE, "P"); + if (co2->Trellis & MFX_TRELLIS_B) av_log(avctx, AV_LOG_VERBOSE, "B"); + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); +#endif + +#if QSV_VERSION_ATLEAST(1, 8) + av_log(avctx, AV_LOG_VERBOSE, + "RepeatPPS: %s; NumMbPerSlice: %"PRIu16"; LookAheadDS: ", + print_threestate(co2->RepeatPPS), co2->NumMbPerSlice); + switch (co2->LookAheadDS) { + case MFX_LOOKAHEAD_DS_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; + case MFX_LOOKAHEAD_DS_2x: av_log(avctx, AV_LOG_VERBOSE, "2x"); break; + case MFX_LOOKAHEAD_DS_4x: av_log(avctx, AV_LOG_VERBOSE, "4x"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, "AdaptiveI: %s; AdaptiveB: %s; BRefType: ", + print_threestate(co2->AdaptiveI), print_threestate(co2->AdaptiveB)); + switch (co2->BRefType) { + case MFX_B_REF_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; + case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "auto"); break; + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); +#endif + +#if QSV_VERSION_ATLEAST(1, 9) + av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); +#endif +#endif + + if (avctx->codec_id == AV_CODEC_ID_H264) { + av_log(avctx, AV_LOG_VERBOSE, "Entropy coding: %s; MaxDecFrameBuffering: %"PRIu16"\n", + co->CAVLC == MFX_CODINGOPTION_ON ? "CAVLC" : "CABAC", co->MaxDecFrameBuffering); + av_log(avctx, AV_LOG_VERBOSE, + "NalHrdConformance: %s; SingleSeiNalUnit: %s; VuiVclHrdParameters: %s VuiNalHrdParameters: %s\n", + print_threestate(co->NalHrdConformance), print_threestate(co->SingleSeiNalUnit), + print_threestate(co->VuiVclHrdParameters), print_threestate(co->VuiNalHrdParameters)); + } +} + +static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) +{ + const char *rc_desc; + mfxU16 rc_mode; + + int want_la = q->la_depth >= 0; + int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); + int want_vcm = q->vcm; + + if (want_la && !QSV_HAVE_LA) { + av_log(avctx, AV_LOG_ERROR, + "Lookahead ratecontrol mode requested, but is not supported by this SDK version\n"); + return AVERROR(ENOSYS); + } + if (want_vcm && !QSV_HAVE_VCM) { + av_log(avctx, AV_LOG_ERROR, + "VCM ratecontrol mode requested, but is not supported by this SDK version\n"); + return AVERROR(ENOSYS); + } + + if (want_la + want_qscale + want_vcm > 1) { + av_log(avctx, AV_LOG_ERROR, + "More than one of: { constant qscale, lookahead, VCM } requested, " + "only one of them can be used at a time.\n"); + return AVERROR(EINVAL); + } + + if (want_qscale) { + rc_mode = MFX_RATECONTROL_CQP; + rc_desc = "constant quantization parameter (CQP)"; + } +#if QSV_HAVE_VCM + else if (want_vcm) { + rc_mode = MFX_RATECONTROL_VCM; + rc_desc = "video conferencing mode (VCM)"; + } +#endif +#if QSV_HAVE_LA + else if (want_la) { + rc_mode = MFX_RATECONTROL_LA; + rc_desc = "VBR with lookahead (LA)"; + +#if QSV_HAVE_ICQ + if (avctx->global_quality > 0) { + rc_mode = MFX_RATECONTROL_LA_ICQ; + rc_desc = "intelligent constant quality with lookahead (LA_ICQ)"; + } +#endif + } +#endif +#if QSV_HAVE_ICQ + else if (avctx->global_quality > 0) { + rc_mode = MFX_RATECONTROL_ICQ; + rc_desc = "intelligent constant quality (ICQ)"; + } +#endif + else if (avctx->rc_max_rate == avctx->bit_rate) { + rc_mode = MFX_RATECONTROL_CBR; + rc_desc = "constant bitrate (CBR)"; + } else if (!avctx->rc_max_rate) { + rc_mode = MFX_RATECONTROL_AVBR; + rc_desc = "average variable bitrate (AVBR)"; + } else { + rc_mode = MFX_RATECONTROL_VBR; + rc_desc = "variable bitrate (VBR)"; + } + + q->param.mfx.RateControlMethod = rc_mode; + av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", rc_desc); + + return 0; +} + +static int rc_supported(QSVEncContext *q) +{ + mfxVideoParam param_out = { .mfx.CodecId = q->param.mfx.CodecId }; + mfxStatus ret; + + ret = MFXVideoENCODE_Query(q->session, &q->param, ¶m_out); + if (ret < 0 || + param_out.mfx.RateControlMethod != q->param.mfx.RateControlMethod) + return 0; + return 1; +} + +static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) +{ + enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? + avctx->sw_pix_fmt : avctx->pix_fmt; + const AVPixFmtDescriptor *desc; + float quant; + int ret; + + ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); + if (ret < 0) + return AVERROR_BUG; + q->param.mfx.CodecId = ret; + + q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; + + if (avctx->level > 0) + q->param.mfx.CodecLevel = avctx->level; + + q->param.mfx.CodecProfile = q->profile; + q->param.mfx.TargetUsage = q->preset; + q->param.mfx.GopPicSize = FFMAX(0, avctx->gop_size); + q->param.mfx.GopRefDist = FFMAX(-1, avctx->max_b_frames) + 1; + q->param.mfx.GopOptFlag = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ? + MFX_GOP_CLOSED : 0; + q->param.mfx.IdrInterval = q->idr_interval; + q->param.mfx.NumSlice = avctx->slices; + q->param.mfx.NumRefFrame = FFMAX(0, avctx->refs); + q->param.mfx.EncodedOrder = 0; + q->param.mfx.BufferSizeInKB = 0; + + desc = av_pix_fmt_desc_get(sw_format); + if (!desc) + return AVERROR_BUG; + + ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 32); + q->param.mfx.FrameInfo.CropX = 0; + q->param.mfx.FrameInfo.CropY = 0; + q->param.mfx.FrameInfo.CropW = avctx->width; + q->param.mfx.FrameInfo.CropH = avctx->height; + q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; + q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; + q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; + q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; + q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; + q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; + } + + if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den; + } else { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; + } + + ret = select_rc_mode(avctx, q); + if (ret < 0) + return ret; + + switch (q->param.mfx.RateControlMethod) { + case MFX_RATECONTROL_CBR: + case MFX_RATECONTROL_VBR: +#if QSV_HAVE_VCM + case MFX_RATECONTROL_VCM: +#endif + q->param.mfx.InitialDelayInKB = avctx->rc_initial_buffer_occupancy / 1000; + q->param.mfx.TargetKbps = avctx->bit_rate / 1000; + q->param.mfx.MaxKbps = avctx->rc_max_rate / 1000; + break; + case MFX_RATECONTROL_CQP: + quant = avctx->global_quality / FF_QP2LAMBDA; + + q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51); + q->param.mfx.QPP = av_clip(quant, 0, 51); + q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51); + + break; + case MFX_RATECONTROL_AVBR: + q->param.mfx.TargetKbps = avctx->bit_rate / 1000; + q->param.mfx.Convergence = q->avbr_convergence; + q->param.mfx.Accuracy = q->avbr_accuracy; + break; +#if QSV_HAVE_LA + case MFX_RATECONTROL_LA: + q->param.mfx.TargetKbps = avctx->bit_rate / 1000; + q->extco2.LookAheadDepth = q->la_depth; + break; +#if QSV_HAVE_ICQ + case MFX_RATECONTROL_LA_ICQ: + q->extco2.LookAheadDepth = q->la_depth; + case MFX_RATECONTROL_ICQ: + q->param.mfx.ICQQuality = avctx->global_quality; + break; +#endif +#endif + } + + // the HEVC encoder plugin currently fails if coding options + // are provided + if (avctx->codec_id != AV_CODEC_ID_HEVC) { + q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + q->extco.Header.BufferSz = sizeof(q->extco); +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type != 0) + q->cavlc = avctx->coder_type == FF_CODER_TYPE_VLC; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + q->extco.CAVLC = q->cavlc ? MFX_CODINGOPTION_ON + : MFX_CODINGOPTION_UNKNOWN; + + if (q->rdo >= 0) + q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + if (avctx->codec_id == AV_CODEC_ID_H264) { + if (avctx->strict_std_compliance != FF_COMPLIANCE_NORMAL) + q->extco.NalHrdConformance = avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL ? + MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + if (q->single_sei_nal_unit >= 0) + q->extco.SingleSeiNalUnit = q->single_sei_nal_unit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->recovery_point_sei >= 0) + q->extco.RecoveryPointSEI = q->recovery_point_sei ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + q->extco.MaxDecFrameBuffering = q->max_dec_frame_buffering; + } + + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; + +#if QSV_HAVE_CO2 + if (avctx->codec_id == AV_CODEC_ID_H264) { + q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; + q->extco2.Header.BufferSz = sizeof(q->extco2); + + if (q->int_ref_type >= 0) + q->extco2.IntRefType = q->int_ref_type; + if (q->int_ref_cycle_size >= 0) + q->extco2.IntRefCycleSize = q->int_ref_cycle_size; + if (q->int_ref_qp_delta != INT16_MIN) + q->extco2.IntRefQPDelta = q->int_ref_qp_delta; + + if (q->bitrate_limit >= 0) + q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->mbbrc >= 0) + q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->extbrc >= 0) + q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + if (q->max_frame_size >= 0) + q->extco2.MaxFrameSize = q->max_frame_size; +#if QSV_HAVE_MAX_SLICE_SIZE + if (q->max_slice_size >= 0) + q->extco2.MaxSliceSize = q->max_slice_size; +#endif + +#if QSV_HAVE_TRELLIS + q->extco2.Trellis = q->trellis; +#endif + +#if QSV_HAVE_BREF_TYPE +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->b_frame_strategy >= 0) + q->b_strategy = avctx->b_frame_strategy; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (q->b_strategy >= 0) + q->extco2.BRefType = q->b_strategy ? MFX_B_REF_PYRAMID : MFX_B_REF_OFF; + if (q->adaptive_i >= 0) + q->extco2.AdaptiveI = q->adaptive_i ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->adaptive_b >= 0) + q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; +#endif + + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2; + } +#endif + } + + if (!rc_supported(q)) { + av_log(avctx, AV_LOG_ERROR, + "Selected ratecontrol mode is not supported by the QSV " + "runtime. Choose a different mode.\n"); + return AVERROR(ENOSYS); + } + + return 0; +} + +static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) +{ + AVCPBProperties *cpb_props; + + uint8_t sps_buf[128]; + uint8_t pps_buf[128]; + + mfxExtCodingOptionSPSPPS extradata = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS, + .Header.BufferSz = sizeof(extradata), + .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf), + .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf) + }; + + mfxExtCodingOption co = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION, + .Header.BufferSz = sizeof(co), + }; +#if QSV_HAVE_CO2 + mfxExtCodingOption2 co2 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2, + .Header.BufferSz = sizeof(co2), + }; +#endif +#if QSV_HAVE_CO3 + mfxExtCodingOption3 co3 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3, + .Header.BufferSz = sizeof(co3), + }; +#endif + + mfxExtBuffer *ext_buffers[] = { + (mfxExtBuffer*)&extradata, + (mfxExtBuffer*)&co, +#if QSV_HAVE_CO2 + (mfxExtBuffer*)&co2, +#endif +#if QSV_HAVE_CO3 + (mfxExtBuffer*)&co3, +#endif + }; + + int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; + int ret; + + q->param.ExtParam = ext_buffers; + q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers); + + ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error calling GetVideoParam"); + + q->packet_size = q->param.mfx.BufferSizeInKB * 1000; + + if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) { + av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n"); + return AVERROR_UNKNOWN; + } + + avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + + memcpy(avctx->extradata, sps_buf, extradata.SPSBufSize); + if (need_pps) + memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize); + avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize; + memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->min_bitrate = avctx->rc_min_rate; + cpb_props->avg_bitrate = avctx->bit_rate; + cpb_props->buffer_size = avctx->rc_buffer_size; + + dump_video_param(avctx, q, ext_buffers + 1); + + return 0; +} + +static int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q) +{ + AVQSVContext *qsv = avctx->hwaccel_context; + mfxFrameSurface1 *surfaces; + int nb_surfaces, i; + + nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested + q->async_depth; + + q->opaque_alloc_buf = av_buffer_allocz(sizeof(*surfaces) * nb_surfaces); + if (!q->opaque_alloc_buf) + return AVERROR(ENOMEM); + + q->opaque_surfaces = av_malloc_array(nb_surfaces, sizeof(*q->opaque_surfaces)); + if (!q->opaque_surfaces) + return AVERROR(ENOMEM); + + surfaces = (mfxFrameSurface1*)q->opaque_alloc_buf->data; + for (i = 0; i < nb_surfaces; i++) { + surfaces[i].Info = q->req.Info; + q->opaque_surfaces[i] = surfaces + i; + } + + q->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; + q->opaque_alloc.Header.BufferSz = sizeof(q->opaque_alloc); + q->opaque_alloc.In.Surfaces = q->opaque_surfaces; + q->opaque_alloc.In.NumSurface = nb_surfaces; + q->opaque_alloc.In.Type = q->req.Type; + + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->opaque_alloc; + + qsv->nb_opaque_surfaces = nb_surfaces; + qsv->opaque_surfaces = q->opaque_alloc_buf; + qsv->opaque_alloc_type = q->req.Type; + + return 0; +} + +static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) +{ + int ret; + + if (avctx->hwaccel_context) { + AVQSVContext *qsv = avctx->hwaccel_context; + q->session = qsv->session; + } else if (avctx->hw_frames_ctx) { + q->frames_ctx.hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); + if (!q->frames_ctx.hw_frames_ctx) + return AVERROR(ENOMEM); + + ret = ff_qsv_init_session_hwcontext(avctx, &q->internal_session, + &q->frames_ctx, q->load_plugins, + q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY); + if (ret < 0) { + av_buffer_unref(&q->frames_ctx.hw_frames_ctx); + return ret; + } + + q->session = q->internal_session; + } else { + ret = ff_qsv_init_internal_session(avctx, &q->internal_session, + q->load_plugins); + if (ret < 0) + return ret; + + q->session = q->internal_session; + } + + return 0; +} + +int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) +{ + int iopattern = 0; + int opaque_alloc = 0; + int ret; + + q->param.AsyncDepth = q->async_depth; + + q->async_fifo = av_fifo_alloc((1 + q->async_depth) * + (sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); + if (!q->async_fifo) + return AVERROR(ENOMEM); + + if (avctx->hwaccel_context) { + AVQSVContext *qsv = avctx->hwaccel_context; + + iopattern = qsv->iopattern; + opaque_alloc = qsv->opaque_alloc; + } + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + + if (!iopattern) { + if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME) + iopattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY; + else if (frames_hwctx->frame_type & + (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) + iopattern = MFX_IOPATTERN_IN_VIDEO_MEMORY; + } + } + + if (!iopattern) + iopattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; + q->param.IOPattern = iopattern; + + ret = qsvenc_init_session(avctx, q); + if (ret < 0) + return ret; + + ret = init_video_param(avctx, q); + if (ret < 0) + return ret; + + ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error querying the encoding parameters"); + + if (opaque_alloc) { + ret = qsv_init_opaque_alloc(avctx, q); + if (ret < 0) + return ret; + } + + if (avctx->hwaccel_context) { + AVQSVContext *qsv = avctx->hwaccel_context; + int i, j; + + q->extparam = av_mallocz_array(qsv->nb_ext_buffers + q->nb_extparam_internal, + sizeof(*q->extparam)); + if (!q->extparam) + return AVERROR(ENOMEM); + + q->param.ExtParam = q->extparam; + for (i = 0; i < qsv->nb_ext_buffers; i++) + q->param.ExtParam[i] = qsv->ext_buffers[i]; + q->param.NumExtParam = qsv->nb_ext_buffers; + + for (i = 0; i < q->nb_extparam_internal; i++) { + for (j = 0; j < qsv->nb_ext_buffers; j++) { + if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId) + break; + } + if (j < qsv->nb_ext_buffers) + continue; + + q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i]; + } + } else { + q->param.ExtParam = q->extparam_internal; + q->param.NumExtParam = q->nb_extparam_internal; + } + + ret = MFXVideoENCODE_Init(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error initializing the encoder"); + else if (ret > 0) + ff_qsv_print_warning(avctx, ret, + "Warning in encoder initialization"); + + ret = qsv_retrieve_enc_params(avctx, q); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n"); + return ret; + } + + q->avctx = avctx; + + return 0; +} + +static void clear_unused_frames(QSVEncContext *q) +{ + QSVFrame *cur = q->work_frames; + while (cur) { + if (cur->surface && !cur->surface->Data.Locked) { + cur->surface = NULL; + av_frame_unref(cur->frame); + } + cur = cur->next; + } +} + +static int get_free_frame(QSVEncContext *q, QSVFrame **f) +{ + QSVFrame *frame, **last; + + clear_unused_frames(q); + + frame = q->work_frames; + last = &q->work_frames; + while (frame) { + if (!frame->surface) { + *f = frame; + return 0; + } + + last = &frame->next; + frame = frame->next; + } + + frame = av_mallocz(sizeof(*frame)); + if (!frame) + return AVERROR(ENOMEM); + frame->frame = av_frame_alloc(); + if (!frame->frame) { + av_freep(&frame); + return AVERROR(ENOMEM); + } + *last = frame; + + *f = frame; + + return 0; +} + +static int submit_frame(QSVEncContext *q, const AVFrame *frame, + mfxFrameSurface1 **surface) +{ + QSVFrame *qf; + int ret; + + ret = get_free_frame(q, &qf); + if (ret < 0) + return ret; + + if (frame->format == AV_PIX_FMT_QSV) { + ret = av_frame_ref(qf->frame, frame); + if (ret < 0) + return ret; + + qf->surface = (mfxFrameSurface1*)qf->frame->data[3]; + } else { + /* make a copy if the input is not padded as libmfx requires */ + if (frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) { + qf->frame->height = FFALIGN(frame->height, 32); + qf->frame->width = FFALIGN(frame->width, q->width_align); + + ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) + return ret; + + qf->frame->height = frame->height; + qf->frame->width = frame->width; + ret = av_frame_copy(qf->frame, frame); + if (ret < 0) { + av_frame_unref(qf->frame); + return ret; + } + } else { + ret = av_frame_ref(qf->frame, frame); + if (ret < 0) + return ret; + } + + qf->surface_internal.Info = q->param.mfx.FrameInfo; + + qf->surface_internal.Info.PicStruct = + !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : + frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + MFX_PICSTRUCT_FIELD_BFF; + if (frame->repeat_pict == 1) + qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; + else if (frame->repeat_pict == 2) + qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING; + else if (frame->repeat_pict == 4) + qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; + + qf->surface_internal.Data.PitchLow = qf->frame->linesize[0]; + qf->surface_internal.Data.Y = qf->frame->data[0]; + qf->surface_internal.Data.UV = qf->frame->data[1]; + + qf->surface = &qf->surface_internal; + } + + qf->surface->Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); + + *surface = qf->surface; + + return 0; +} + +static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q) +{ + if (q->param.mfx.CodecId == MFX_CODEC_AVC) { + if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE || + q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 || + q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41) + av_log(avctx, AV_LOG_WARNING, + "Interlaced coding is supported" + " at Main/High Profile Level 2.1-4.1\n"); + } +} + +static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ + AVPacket new_pkt = { 0 }; + mfxBitstream *bs; + + mfxFrameSurface1 *surf = NULL; + mfxSyncPoint *sync = NULL; + int ret; + + if (frame) { + ret = submit_frame(q, frame, &surf); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n"); + return ret; + } + } + + ret = av_new_packet(&new_pkt, q->packet_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n"); + return ret; + } + + bs = av_mallocz(sizeof(*bs)); + if (!bs) { + av_packet_unref(&new_pkt); + return AVERROR(ENOMEM); + } + bs->Data = new_pkt.data; + bs->MaxLength = new_pkt.size; + + sync = av_mallocz(sizeof(*sync)); + if (!sync) { + av_freep(&bs); + av_packet_unref(&new_pkt); + return AVERROR(ENOMEM); + } + + do { + ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, sync); + if (ret == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION); + + if (ret > 0) + ff_qsv_print_warning(avctx, ret, "Warning during encoding"); + + if (ret < 0) { + av_packet_unref(&new_pkt); + av_freep(&bs); + av_freep(&sync); + return (ret == MFX_ERR_MORE_DATA) ? + 0 : ff_qsv_print_error(avctx, ret, "Error during encoding"); + } + + if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame->interlaced_frame) + print_interlace_msg(avctx, q); + + if (*sync) { + av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); + av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); + av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL); + } else { + av_freep(&sync); + av_packet_unref(&new_pkt); + av_freep(&bs); + } + + return 0; +} + +int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, + AVPacket *pkt, const AVFrame *frame, int *got_packet) +{ + int ret; + + ret = encode_frame(avctx, q, frame); + if (ret < 0) + return ret; + + if (!av_fifo_space(q->async_fifo) || + (!frame && av_fifo_size(q->async_fifo))) { + AVPacket new_pkt; + mfxBitstream *bs; + mfxSyncPoint *sync; + + av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); + av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); + av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); + + do { + ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000); + } while (ret == MFX_WRN_IN_EXECUTION); + + new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base); + new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base); + new_pkt.size = bs->DataLength; + + if (bs->FrameType & MFX_FRAMETYPE_IDR || + bs->FrameType & MFX_FRAMETYPE_xIDR) + new_pkt.flags |= AV_PKT_FLAG_KEY; + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; + else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB) + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + av_freep(&bs); + av_freep(&sync); + + if (pkt->data) { + if (pkt->size < new_pkt.size) { + av_log(avctx, AV_LOG_ERROR, "Submitted buffer not large enough: %d < %d\n", + pkt->size, new_pkt.size); + av_packet_unref(&new_pkt); + return AVERROR(EINVAL); + } + + memcpy(pkt->data, new_pkt.data, new_pkt.size); + pkt->size = new_pkt.size; + + ret = av_packet_copy_props(pkt, &new_pkt); + av_packet_unref(&new_pkt); + if (ret < 0) + return ret; + } else + *pkt = new_pkt; + + *got_packet = 1; + } + + return 0; +} + +int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) +{ + QSVFrame *cur; + + if (q->session) + MFXVideoENCODE_Close(q->session); + if (q->internal_session) + MFXClose(q->internal_session); + q->session = NULL; + q->internal_session = NULL; + + av_buffer_unref(&q->frames_ctx.hw_frames_ctx); + av_freep(&q->frames_ctx.mids); + q->frames_ctx.nb_mids = 0; + + cur = q->work_frames; + while (cur) { + q->work_frames = cur->next; + av_frame_free(&cur->frame); + av_freep(&cur); + cur = q->work_frames; + } + + while (q->async_fifo && av_fifo_size(q->async_fifo)) { + AVPacket pkt; + mfxSyncPoint *sync; + mfxBitstream *bs; + + av_fifo_generic_read(q->async_fifo, &pkt, sizeof(pkt), NULL); + av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); + av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); + + av_freep(&sync); + av_freep(&bs); + av_packet_unref(&pkt); + } + av_fifo_free(q->async_fifo); + q->async_fifo = NULL; + + av_freep(&q->opaque_surfaces); + av_buffer_unref(&q->opaque_alloc_buf); + + av_freep(&q->extparam); + + return 0; +} diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h new file mode 100644 index 0000000..7ac5dc7 --- /dev/null +++ b/libavcodec/qsvenc.h @@ -0,0 +1,143 @@ +/* + * Intel MediaSDK QSV encoder utility functions + * + * copyright (c) 2013 Yukinori Yamazoe + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_QSVENC_H +#define AVCODEC_QSVENC_H + +#include +#include + +#include + +#include "libavutil/avutil.h" +#include "libavutil/fifo.h" + +#include "avcodec.h" +#include "qsv_internal.h" + +#define QSV_HAVE_CO2 QSV_VERSION_ATLEAST(1, 6) +#define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11) + +#define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8) +#define QSV_HAVE_MAX_SLICE_SIZE QSV_VERSION_ATLEAST(1, 9) +#define QSV_HAVE_BREF_TYPE QSV_VERSION_ATLEAST(1, 8) + +#define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) +#define QSV_HAVE_LA_HRD QSV_VERSION_ATLEAST(1, 11) +#define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 8) +#define QSV_HAVE_VCM QSV_VERSION_ATLEAST(1, 8) +#define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11) + +#define QSV_COMMON_OPTS \ +{ "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, \ +{ "avbr_accuracy", "Accuracy of the AVBR ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \ +{ "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \ +{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, 0, 7, VE, "preset" }, \ +{ "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, \ +{ "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED }, INT_MIN, INT_MAX, VE, "preset" }, \ +{ "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \ +{ "la_depth", "Number of frames to analyze before encoding.", OFFSET(qsv.la_depth), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE }, \ +{ "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ +{ "rdo", "Enable rate distortion optimization", OFFSET(qsv.rdo), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "max_frame_size", "Maximum encoded frame size in bytes", OFFSET(qsv.max_frame_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \ +{ "max_slice_size", "Maximum encoded slice size in bytes", OFFSET(qsv.max_slice_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \ +{ "bitrate_limit", "Toggle bitrate limitations", OFFSET(qsv.bitrate_limit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "mbbrc", "MB level bitrate control", OFFSET(qsv.mbbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "extbrc", "Extended bitrate control", OFFSET(qsv.extbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ + +typedef struct QSVEncContext { + AVCodecContext *avctx; + + QSVFrame *work_frames; + + mfxSession session; + mfxSession internal_session; + + int packet_size; + int width_align; + + mfxVideoParam param; + mfxFrameAllocRequest req; + + mfxExtCodingOption extco; +#if QSV_HAVE_CO2 + mfxExtCodingOption2 extco2; +#endif + + mfxExtOpaqueSurfaceAlloc opaque_alloc; + mfxFrameSurface1 **opaque_surfaces; + AVBufferRef *opaque_alloc_buf; + + mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2]; + int nb_extparam_internal; + + mfxExtBuffer **extparam; + + AVFifoBuffer *async_fifo; + + QSVFramesContext frames_ctx; + + // options set by the caller + int async_depth; + int idr_interval; + int profile; + int preset; + int avbr_accuracy; + int avbr_convergence; + int la_depth; + int vcm; + int rdo; + int max_frame_size; + int max_slice_size; + + int single_sei_nal_unit; + int max_dec_frame_buffering; + int trellis; + + int bitrate_limit; + int mbbrc; + int extbrc; + int adaptive_i; + int adaptive_b; + int b_strategy; + int cavlc; + + int int_ref_type; + int int_ref_cycle_size; + int int_ref_qp_delta; + int recovery_point_sei; + + char *load_plugins; +} QSVEncContext; + +int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); + +int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, + AVPacket *pkt, const AVFrame *frame, int *got_packet); + +int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q); + +#endif /* AVCODEC_QSVENC_H */ diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c new file mode 100644 index 0000000..a968dcf --- /dev/null +++ b/libavcodec/qsvenc_h264.c @@ -0,0 +1,135 @@ +/* + * Intel MediaSDK QSV based H.264 enccoder + * + * copyright (c) 2013 Yukinori Yamazoe + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +typedef struct QSVH264EncContext { + AVClass *class; + QSVEncContext qsv; +} QSVH264EncContext; + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVH264EncContext *q = avctx->priv_data; + + return ff_qsv_enc_init(avctx, &q->qsv); +} + +static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + QSVH264EncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVH264EncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVH264EncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + QSV_COMMON_OPTS + + { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + { "single_sei_nal_unit", "Put all the SEI messages into one NALU", OFFSET(qsv.single_sei_nal_unit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, + + { "int_ref_type", "Intra refresh type", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, + { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, + { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, + { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, + { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + + { "trellis", "Trellis quantization", OFFSET(qsv.trellis), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, UINT_MAX, VE, "trellis" }, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_OFF }, .flags = VE, "trellis" }, + { "I", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_I }, .flags = VE, "trellis" }, + { "P", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_P }, .flags = VE, "trellis" }, + { "B", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TRELLIS_B }, .flags = VE, "trellis" }, + + { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, + { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, + { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, + { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + + { NULL }, +}; + +static const AVClass class = { + .class_name = "h264_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault qsv_enc_defaults[] = { + { "b", "1M" }, + { "refs", "0" }, + // same as the x264 default + { "g", "250" }, + { "bf", "3" }, + { "coder", "ac" }, + + { "flags", "+cgop" }, +#if FF_API_PRIVATE_OPT + { "b_strategy", "-1" }, +#endif + { NULL }, +}; + +AVCodec ff_h264_qsv_encoder = { + .name = "h264_qsv", + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVH264EncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, + .defaults = qsv_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c new file mode 100644 index 0000000..ddb2a42 --- /dev/null +++ b/libavcodec/qsvenc_hevc.c @@ -0,0 +1,271 @@ +/* + * Intel MediaSDK QSV based HEVC encoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "hevc.h" +#include "h2645_parse.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +enum LoadPlugin { + LOAD_PLUGIN_NONE, + LOAD_PLUGIN_HEVC_SW, + LOAD_PLUGIN_HEVC_HW, +}; + +typedef struct QSVHEVCEncContext { + AVClass *class; + QSVEncContext qsv; + int load_plugin; +} QSVHEVCEncContext; + +static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) +{ + GetByteContext gbc; + PutByteContext pbc; + + GetBitContext gb; + H2645NAL sps_nal = { NULL }; + HEVCSPS sps = { 0 }; + HEVCVPS vps = { 0 }; + uint8_t vps_buf[128], vps_rbsp_buf[128]; + uint8_t *new_extradata; + unsigned int sps_id; + int ret, i, type, vps_size; + + if (!avctx->extradata_size) { + av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx\n"); + return AVERROR_UNKNOWN; + } + + /* parse the SPS */ + ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n"); + return ret; + } + + ret = init_get_bits8(&gb, sps_nal.data, sps_nal.size); + if (ret < 0) { + av_freep(&sps_nal.rbsp_buffer); + return ret; + } + + get_bits(&gb, 1); + type = get_bits(&gb, 6); + if (type != NAL_SPS) { + av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n", + type); + av_freep(&sps_nal.rbsp_buffer); + return AVERROR_INVALIDDATA; + } + get_bits(&gb, 9); + + ret = ff_hevc_parse_sps(&sps, &gb, &sps_id, 0, NULL, avctx); + av_freep(&sps_nal.rbsp_buffer); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n"); + return ret; + } + + /* generate the VPS */ + vps.vps_max_layers = 1; + vps.vps_max_sub_layers = sps.max_sub_layers; + memcpy(&vps.ptl, &sps.ptl, sizeof(vps.ptl)); + vps.vps_sub_layer_ordering_info_present_flag = 1; + for (i = 0; i < MAX_SUB_LAYERS; i++) { + vps.vps_max_dec_pic_buffering[i] = sps.temporal_layer[i].max_dec_pic_buffering; + vps.vps_num_reorder_pics[i] = sps.temporal_layer[i].num_reorder_pics; + vps.vps_max_latency_increase[i] = sps.temporal_layer[i].max_latency_increase; + } + + vps.vps_num_layer_sets = 1; + vps.vps_timing_info_present_flag = sps.vui.vui_timing_info_present_flag; + vps.vps_num_units_in_tick = sps.vui.vui_num_units_in_tick; + vps.vps_time_scale = sps.vui.vui_time_scale; + vps.vps_poc_proportional_to_timing_flag = sps.vui.vui_poc_proportional_to_timing_flag; + vps.vps_num_ticks_poc_diff_one = sps.vui.vui_num_ticks_poc_diff_one_minus1 + 1; + + /* generate the encoded RBSP form of the VPS */ + ret = ff_hevc_encode_nal_vps(&vps, sps.vps_id, vps_rbsp_buf, sizeof(vps_rbsp_buf)); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error writing the VPS\n"); + return ret; + } + + /* escape and add the startcode */ + bytestream2_init(&gbc, vps_rbsp_buf, ret); + bytestream2_init_writer(&pbc, vps_buf, sizeof(vps_buf)); + + bytestream2_put_be32(&pbc, 1); // startcode + bytestream2_put_byte(&pbc, NAL_VPS << 1); // NAL + bytestream2_put_byte(&pbc, 1); // header + + while (bytestream2_get_bytes_left(&gbc)) { + uint32_t b = bytestream2_peek_be24(&gbc); + if (b <= 3) { + bytestream2_put_be24(&pbc, 3); + bytestream2_skip(&gbc, 2); + } else + bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc)); + } + + vps_size = bytestream2_tell_p(&pbc); + new_extradata = av_mallocz(vps_size + avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!new_extradata) + return AVERROR(ENOMEM); + memcpy(new_extradata, vps_buf, vps_size); + memcpy(new_extradata + vps_size, avctx->extradata, avctx->extradata_size); + + av_freep(&avctx->extradata); + avctx->extradata = new_extradata; + avctx->extradata_size += vps_size; + + return 0; +} + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVHEVCEncContext *q = avctx->priv_data; + int ret; + + if (q->load_plugin != LOAD_PLUGIN_NONE) { + static const char *uid_hevcenc_sw = "2fca99749fdb49aeb121a5b63ef568f7"; + static const char *uid_hevcenc_hw = "6fadc791a0c2eb479ab6dcd5ea9da347"; + + if (q->qsv.load_plugins[0]) { + av_log(avctx, AV_LOG_WARNING, + "load_plugins is not empty, but load_plugin is not set to 'none'." + "The load_plugin value will be ignored.\n"); + } else { + av_freep(&q->qsv.load_plugins); + + if (q->load_plugin == LOAD_PLUGIN_HEVC_SW) + q->qsv.load_plugins = av_strdup(uid_hevcenc_sw); + else + q->qsv.load_plugins = av_strdup(uid_hevcenc_hw); + + if (!q->qsv.load_plugins) + return AVERROR(ENOMEM); + } + } + + ret = ff_qsv_enc_init(avctx, &q->qsv); + if (ret < 0) + return ret; + + ret = generate_fake_vps(&q->qsv, avctx); + if (ret < 0) { + ff_qsv_enc_close(avctx, &q->qsv); + return ret; + } + + return 0; +} + +static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + QSVHEVCEncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVHEVCEncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVHEVCEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + QSV_COMMON_OPTS + + { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VE, "load_plugin" }, + { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" }, + { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VE, "load_plugin" }, + + { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session", + OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VE }, + + { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, + { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, + { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "main10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, + { "mainsp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP }, INT_MIN, INT_MAX, VE, "profile" }, + + { NULL }, +}; + +static const AVClass class = { + .class_name = "hevc_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault qsv_enc_defaults[] = { + { "b", "1M" }, + { "refs", "0" }, + // same as the x264 default + { "g", "248" }, + { "bf", "8" }, + + { "flags", "+cgop" }, +#if FF_API_PRIVATE_OPT + { "b_strategy", "-1" }, +#endif + { NULL }, +}; + +AVCodec ff_hevc_qsv_encoder = { + .name = "hevc_qsv", + .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVHEVCEncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, + .defaults = qsv_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c new file mode 100644 index 0000000..f29f445 --- /dev/null +++ b/libavcodec/qsvenc_mpeg2.c @@ -0,0 +1,114 @@ +/* + * Intel MediaSDK QSV based MPEG-2 encoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +typedef struct QSVMpeg2EncContext { + AVClass *class; + QSVEncContext qsv; +} QSVMpeg2EncContext; + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVMpeg2EncContext *q = avctx->priv_data; + + return ff_qsv_enc_init(avctx, &q->qsv); +} + +static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + QSVMpeg2EncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVMpeg2EncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVMpeg2EncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + QSV_COMMON_OPTS + + { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, + { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, + { "simple", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_SIMPLE }, INT_MIN, INT_MAX, VE, "profile" }, + { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + + { NULL }, +}; + +static const AVClass class = { + .class_name = "mpeg2_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault qsv_enc_defaults[] = { + { "b", "1M" }, + { "refs", "0" }, + // same as the x264 default + { "g", "250" }, + { "bf", "3" }, + + { "flags", "+cgop" }, +#if FF_API_PRIVATE_OPT + { "b_strategy", "-1" }, +#endif + { NULL }, +}; + +AVCodec ff_mpeg2_qsv_encoder = { + .name = "mpeg2_qsv", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVMpeg2EncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, + .defaults = qsv_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c index 28f1720..70440d3 100644 --- a/libavcodec/qtrle.c +++ b/libavcodec/qtrle.c @@ -1,6 +1,6 @@ /* * Quicktime Animation (RLE) Video Decoder - * Copyright (C) 2004 the ffmpeg project + * Copyright (C) 2004 The FFmpeg project * * This file is part of Libav. * @@ -513,5 +513,5 @@ AVCodec ff_qtrle_decoder = { .init = qtrle_decode_init, .close = qtrle_decode_end, .decode = qtrle_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index 7c98bea..e7de209 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -37,7 +37,7 @@ typedef struct QtrleEncContext { AVCodecContext *avctx; int pixel_size; - AVPicture previous_frame; + AVFrame *previous_frame; unsigned int max_buf_size; /** * This array will contain at ith position the value of the best RLE code @@ -57,15 +57,16 @@ typedef struct QtrleEncContext { * Will contain at ith position the number of consecutive pixels equal to the previous * frame starting from pixel i */ uint8_t* skip_table; + + /** Encoded frame is a key frame */ + int key_frame; } QtrleEncContext; static av_cold int qtrle_encode_end(AVCodecContext *avctx) { QtrleEncContext *s = avctx->priv_data; - av_frame_free(&avctx->coded_frame); - - avpicture_free(&s->previous_frame); + av_frame_free(&s->previous_frame); av_free(s->rlecode_table); av_free(s->length_table); av_free(s->skip_table); @@ -104,7 +105,8 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n"); return -1; } - if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) { + s->previous_frame = av_frame_alloc(); + if (!s->previous_frame) { av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n"); return -1; } @@ -114,12 +116,6 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) + s->avctx->height*2 /* skip code+rle end */ + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - qtrle_encode_end(avctx); - return AVERROR(ENOMEM); - } - return 0; } @@ -134,7 +130,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui /* We will use it to compute the best bulk copy sequence */ unsigned int bulkcount; - /* This will be the number of pixels equal to the preivous frame one's + /* This will be the number of pixels equal to the previous frame one's * starting from the ith pixel */ unsigned int skipcount; /* This will be the number of consecutive equal pixels in the current @@ -151,7 +147,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui uint8_t *this_line = p-> data[0] + line*p-> linesize[0] + (width - 1)*s->pixel_size; - uint8_t *prev_line = s->previous_frame.data[0] + line*s->previous_frame.linesize[0] + + uint8_t *prev_line = s->previous_frame->data[0] + line * s->previous_frame->linesize[0] + (width - 1)*s->pixel_size; s->length_table[width] = 0; @@ -159,7 +155,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui for (i = width - 1; i >= 0; i--) { - if (!s->avctx->coded_frame->key_frame && !memcmp(this_line, prev_line, s->pixel_size)) + if (!s->key_frame && !memcmp(this_line, prev_line, s->pixel_size)) skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP); else skipcount = 0; @@ -218,7 +214,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui prev_line -= s->pixel_size; } - /* Good ! Now we have the best sequence for this line, let's ouput it */ + /* Good! Now we have the best sequence for this line, let's output it. */ /* We do a special case for the first pixel so that we avoid testing it in * the whole loop */ @@ -263,17 +259,17 @@ static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf) int end_line = s->avctx->height; uint8_t *orig_buf = buf; - if (!s->avctx->coded_frame->key_frame) { + if (!s->key_frame) { unsigned line_size = s->avctx->width * s->pixel_size; for (start_line = 0; start_line < s->avctx->height; start_line++) if (memcmp(p->data[0] + start_line*p->linesize[0], - s->previous_frame.data[0] + start_line*s->previous_frame.linesize[0], + s->previous_frame->data[0] + start_line * s->previous_frame->linesize[0], line_size)) break; for (end_line=s->avctx->height; end_line > start_line; end_line--) if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0], - s->previous_frame.data[0] + (end_line - 1)*s->previous_frame.linesize[0], + s->previous_frame->data[0] + (end_line - 1) * s->previous_frame->linesize[0], line_size)) break; } @@ -301,7 +297,9 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { QtrleEncContext * const s = avctx->priv_data; - AVFrame * const p = avctx->coded_frame; +#if FF_API_CODED_FRAME + enum AVPictureType pict_type; +#endif int ret; if ((ret = ff_alloc_packet(pkt, s->max_buf_size)) < 0) { @@ -312,21 +310,36 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { /* I-Frame */ - p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; +#if FF_API_CODED_FRAME + pict_type = AV_PICTURE_TYPE_I; +#endif + s->key_frame = 1; } else { /* P-Frame */ - p->pict_type = AV_PICTURE_TYPE_P; - p->key_frame = 0; +#if FF_API_CODED_FRAME + pict_type = AV_PICTURE_TYPE_P; +#endif + s->key_frame = 0; } pkt->size = encode_frame(s, pict, pkt->data); /* save the current frame */ - av_picture_copy(&s->previous_frame, (const AVPicture *)pict, - avctx->pix_fmt, avctx->width, avctx->height); + av_frame_unref(s->previous_frame); + ret = av_frame_ref(s->previous_frame, pict); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "cannot add reference\n"); + return ret; + } + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->key_frame = s->key_frame; + avctx->coded_frame->pict_type = pict_type; +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (p->key_frame) + if (s->key_frame) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; diff --git a/libavcodec/r210dec.c b/libavcodec/r210dec.c index 6adaac0..f168fd3 100644 --- a/libavcodec/r210dec.c +++ b/libavcodec/r210dec.c @@ -89,7 +89,7 @@ AVCodec ff_r210_decoder = { .id = AV_CODEC_ID_R210, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif #if CONFIG_R10K_DECODER @@ -100,6 +100,6 @@ AVCodec ff_r10k_decoder = { .id = AV_CODEC_ID_R10K, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff --git a/libavcodec/ra144.c b/libavcodec/ra144.c index 355badd..ccaa149 100644 --- a/libavcodec/ra144.c +++ b/libavcodec/ra144.c @@ -1,6 +1,6 @@ /* * Real Audio 1.0 (14.4K) - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/ra144.h b/libavcodec/ra144.h index 81d6964..89d4fb5 100644 --- a/libavcodec/ra144.h +++ b/libavcodec/ra144.h @@ -1,6 +1,6 @@ /* * Real Audio 1.0 (14.4K) - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/ra144dec.c b/libavcodec/ra144dec.c index 3be3877..2895357 100644 --- a/libavcodec/ra144dec.c +++ b/libavcodec/ra144dec.c @@ -135,5 +135,5 @@ AVCodec ff_ra_144_decoder = { .priv_data_size = sizeof(RA144Context), .init = ra144_decode_init, .decode = ra144_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c index 7627adc..678e668 100644 --- a/libavcodec/ra144enc.c +++ b/libavcodec/ra144enc.c @@ -56,7 +56,7 @@ static av_cold int ra144_encode_init(AVCodecContext * avctx) return -1; } avctx->frame_size = NBLOCKS * BLOCKSIZE; - avctx->delay = avctx->frame_size; + avctx->initial_padding = avctx->frame_size; avctx->bit_rate = 8000; ractx = avctx->priv_data; ractx->lpc_coef[0] = ractx->lpc_tables[0]; @@ -128,7 +128,7 @@ static void orthogonalize(float *v, const float *u) /** * Calculate match score and gain of an LPC-filtered vector with respect to - * input data, possibly othogonalizing it to up to 2 other vectors + * input data, possibly orthogonalizing it to up to two other vectors. * * @param work array used to calculate the filtered vector * @param coefs coefficients of the LPC filter @@ -229,8 +229,8 @@ static int adaptive_cb_search(const int16_t *adapt_cb, float *work, /** * Find the best vector of a fixed codebook by applying an LPC filter to - * codebook entries, possibly othogonalizing them to up to 2 other vectors and - * matching the results with input data + * codebook entries, possibly orthogonalizing them to up to two other vectors + * and matching the results with input data. * * @param work array used to calculate the filtered vectors * @param coefs coefficients of the LPC filter @@ -553,7 +553,7 @@ AVCodec ff_ra_144_encoder = { .init = ra144_encode_init, .encode2 = ra144_encode_frame, .close = ra144_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c index 215786c..96d8d1e 100644 --- a/libavcodec/ra288.c +++ b/libavcodec/ra288.c @@ -1,6 +1,6 @@ /* * RealAudio 2.0 (28.8K) - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -22,13 +22,14 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/internal.h" -#include "avcodec.h" -#include "internal.h" + #define BITSTREAM_READER_LE +#include "avcodec.h" +#include "celp_filters.h" #include "get_bits.h" -#include "ra288.h" +#include "internal.h" #include "lpc.h" -#include "celp_filters.h" +#include "ra288.h" #define MAX_BACKWARD_FILTER_ORDER 36 #define MAX_BACKWARD_FILTER_LEN 40 @@ -37,7 +38,7 @@ #define RA288_BLOCK_SIZE 5 #define RA288_BLOCKS_PER_FRAME 32 -typedef struct { +typedef struct RA288Context { AVFloatDSPContext fdsp; DECLARE_ALIGNED(32, float, sp_lpc)[FFALIGN(36, 16)]; ///< LPC coefficients for speech data (spec: A) DECLARE_ALIGNED(32, float, gain_lpc)[FFALIGN(10, 16)]; ///< LPC coefficients for gain (spec: GB) @@ -67,7 +68,7 @@ static av_cold int ra288_decode_init(AVCodecContext *avctx) avctx->channel_layout = AV_CH_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - avpriv_float_dsp_init(&ractx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&ractx->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); return 0; } @@ -230,5 +231,5 @@ AVCodec ff_ra_288_decoder = { .priv_data_size = sizeof(RA288Context), .init = ra288_decode_init, .decode = ra288_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/ra288.h b/libavcodec/ra288.h index 9f4beeb..3d6ed8d 100644 --- a/libavcodec/ra288.h +++ b/libavcodec/ra288.h @@ -1,6 +1,6 @@ /* * RealAudio 2.0 (28.8K) - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/ralf.c b/libavcodec/ralf.c index ebcdf6f..bed5adf 100644 --- a/libavcodec/ralf.c +++ b/libavcodec/ralf.c @@ -532,7 +532,7 @@ AVCodec ff_ralf_decoder = { .close = decode_close, .decode = decode_frame, .flush = decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/rangecoder.c b/libavcodec/rangecoder.c index af0a8c0..4c4731d 100644 --- a/libavcodec/rangecoder.c +++ b/libavcodec/rangecoder.c @@ -28,15 +28,15 @@ * G. N. N. Martin Presented in March 1979 to the Video & * Data Recording Conference, * IBM UK Scientific Center held in Southampton July 24-27 1979." - * */ #include #include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" + #include "avcodec.h" #include "rangecoder.h" -#include "bytestream.h" av_cold void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size) { @@ -55,7 +55,8 @@ av_cold void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, /* cast to avoid compiler warning */ ff_init_range_encoder(c, (uint8_t *)buf, buf_size); - c->low = bytestream_get_be16(&c->bytestream); + c->low = AV_RB16(c->bytestream); + c->bytestream += 2; } void ff_build_rac_states(RangeCoder *c, int factor, int max_p) @@ -112,47 +113,3 @@ int ff_rac_terminate(RangeCoder *c) return c->bytestream - c->bytestream_start; } - -#ifdef TEST -#define SIZE 10240 - -#include "libavutil/lfg.h" -#include "libavutil/log.h" - -int main(void) -{ - RangeCoder c; - uint8_t b[9 * SIZE]; - uint8_t r[9 * SIZE]; - int i; - uint8_t state[10]; - AVLFG prng; - - av_lfg_init(&prng, 1); - - ff_init_range_encoder(&c, b, SIZE); - ff_build_rac_states(&c, 0.05 * (1LL << 32), 128 + 64 + 32 + 16); - - memset(state, 128, sizeof(state)); - - for (i = 0; i < SIZE; i++) - r[i] = av_lfg_get(&prng) % 7; - - for (i = 0; i < SIZE; i++) - put_rac(&c, state, r[i] & 1); - - ff_rac_terminate(&c); - - ff_init_range_decoder(&c, b, SIZE); - - memset(state, 128, sizeof(state)); - - for (i = 0; i < SIZE; i++) - if ((r[i] & 1) != get_rac(&c, state)) { - av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i); - return 1; - } - - return 0; -} -#endif /* TEST */ diff --git a/libavcodec/rangecoder.h b/libavcodec/rangecoder.h index ad9c81f..2ead446 100644 --- a/libavcodec/rangecoder.h +++ b/libavcodec/rangecoder.h @@ -115,10 +115,8 @@ static inline void refill(RangeCoder *c) static inline int get_rac(RangeCoder *c, uint8_t *const state) { int range1 = (c->range * (*state)) >> 8; - int av_unused one_mask; c->range -= range1; -#if 1 if (c->low < c->range) { *state = c->zero_state[*state]; refill(c); @@ -130,18 +128,6 @@ static inline int get_rac(RangeCoder *c, uint8_t *const state) refill(c); return 1; } -#else - one_mask = (c->range - c->low - 1) >> 31; - - c->low -= c->range & one_mask; - c->range += (range1 - c->range) & one_mask; - - *state = c->zero_state[(*state) + (256 & one_mask)]; - - refill(c); - - return one_mask & 1; -#endif } #endif /* AVCODEC_RANGECODER_H */ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 70d9787..78a438f 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -26,7 +26,10 @@ */ #include "libavutil/attributes.h" +#include "libavutil/internal.h" + #include "avcodec.h" +#include "internal.h" #include "ratecontrol.h" #include "mpegutils.h" #include "mpegvideo.h" @@ -39,45 +42,406 @@ #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); +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; +} + +static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, double q) +{ + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + const int pict_type = rce->new_pict_type; + const double last_p_q = rcc->last_qscale_for[AV_PICTURE_TYPE_P]; + const double last_non_b_q = rcc->last_qscale_for[rcc->last_non_b_pict_type]; + + if (pict_type == AV_PICTURE_TYPE_I && + (a->i_quant_factor > 0.0 || rcc->last_non_b_pict_type == AV_PICTURE_TYPE_P)) + q = last_p_q * FFABS(a->i_quant_factor) + a->i_quant_offset; + else if (pict_type == AV_PICTURE_TYPE_B && + a->b_quant_factor > 0.0) + q = last_non_b_q * a->b_quant_factor + a->b_quant_offset; + if (q < 1) + q = 1; + + /* last qscale / qdiff stuff */ + if (rcc->last_non_b_pict_type == pict_type || pict_type != AV_PICTURE_TYPE_I) { + double last_q = rcc->last_qscale_for[pict_type]; + const int maxdiff = FF_QP2LAMBDA * a->max_qdiff; + + if (q > last_q + maxdiff) + q = last_q + maxdiff; + else if (q < last_q - maxdiff) + q = last_q - maxdiff; + } + + rcc->last_qscale_for[pict_type] = q; // Note we cannot do that after blurring + + if (pict_type != AV_PICTURE_TYPE_B) + rcc->last_non_b_pict_type = pict_type; + + return q; +} + +/** + * Get the qmin & qmax for pict_type. + */ +static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type) +{ + int qmin = s->lmin; + int qmax = s->lmax; + + assert(qmin <= qmax); + + switch (pict_type) { + case AV_PICTURE_TYPE_B: + qmin = (int)(qmin * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); + qmax = (int)(qmax * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); + break; + case AV_PICTURE_TYPE_I: + qmin = (int)(qmin * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); + qmax = (int)(qmax * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); + break; + } + + qmin = av_clip(qmin, 1, FF_LAMBDA_MAX); + qmax = av_clip(qmax, 1, FF_LAMBDA_MAX); + + if (qmax < qmin) + qmax = qmin; + + *qmin_ret = qmin; + *qmax_ret = qmax; +} + +static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, + double q, int frame_num) +{ + RateControlContext *rcc = &s->rc_context; + const double buffer_size = s->avctx->rc_buffer_size; + const double fps = 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; + const int pict_type = rce->new_pict_type; + int qmin, qmax; + + get_qminmax(&qmin, &qmax, s, pict_type); + + /* modulation */ + if (s->rc_qmod_freq && + frame_num % s->rc_qmod_freq == 0 && + pict_type == AV_PICTURE_TYPE_P) + q *= s->rc_qmod_amp; + + /* buffer overflow/underflow protection */ + if (buffer_size) { + double expected_size = rcc->buffer_index; + double q_limit; + + if (min_rate) { + double d = 2 * (buffer_size - expected_size) / buffer_size; + if (d > 1.0) + d = 1.0; + else if (d < 0.0001) + d = 0.0001; + q *= pow(d, 1.0 / s->rc_buffer_aggressivity); + + q_limit = bits2qp(rce, + FFMAX((min_rate - buffer_size + rcc->buffer_index) * + s->avctx->rc_min_vbv_overflow_use, 1)); + + if (q > q_limit) { + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, + "limiting QP %f -> %f\n", q, q_limit); + q = q_limit; + } + } + + if (max_rate) { + double d = 2 * expected_size / buffer_size; + if (d > 1.0) + d = 1.0; + else if (d < 0.0001) + d = 0.0001; + q /= pow(d, 1.0 / s->rc_buffer_aggressivity); + + q_limit = bits2qp(rce, + FFMAX(rcc->buffer_index * + s->avctx->rc_max_available_vbv_use, + 1)); + if (q < q_limit) { + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, + "limiting QP %f -> %f\n", q, q_limit); + q = q_limit; + } + } + } + ff_dlog(s, "q:%f max:%f min:%f size:%f index:%f agr:%f\n", + q, max_rate, min_rate, buffer_size, rcc->buffer_index, + s->rc_buffer_aggressivity); + if (s->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; +} + +/** + * Modify the bitrate curve from pass1 for one frame. + */ +static double get_qscale(MpegEncContext *s, RateControlEntry *rce, + double rate_factor, int frame_num) +{ + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + const int pict_type = rce->new_pict_type; + const double mb_num = s->mb_num; + double q, bits; + int i; + + double const_values[] = { + M_PI, + M_E, + rce->i_tex_bits * rce->qscale, + rce->p_tex_bits * rce->qscale, + (rce->i_tex_bits + rce->p_tex_bits) * (double)rce->qscale, + rce->mv_bits / mb_num, + rce->pict_type == AV_PICTURE_TYPE_B ? (rce->f_code + rce->b_code) * 0.5 : rce->f_code, + rce->i_count / mb_num, + rce->mc_mb_var_sum / mb_num, + rce->mb_var_sum / mb_num, + rce->pict_type == AV_PICTURE_TYPE_I, + rce->pict_type == AV_PICTURE_TYPE_P, + rce->pict_type == AV_PICTURE_TYPE_B, + rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type], + a->qcompress, + rcc->i_cplx_sum[AV_PICTURE_TYPE_I] / (double)rcc->frame_count[AV_PICTURE_TYPE_I], + rcc->i_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], + rcc->p_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], + rcc->p_cplx_sum[AV_PICTURE_TYPE_B] / (double)rcc->frame_count[AV_PICTURE_TYPE_B], + (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type], + 0 + }; + + bits = av_expr_eval(rcc->rc_eq_eval, const_values, rce); + if (isnan(bits)) { + av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->rc_eq); + return -1; + } + + rcc->pass1_rc_eq_output_sum += bits; + bits *= rate_factor; + if (bits < 0.0) + bits = 0.0; + bits += 1.0; // avoid 1/0 issues + + /* user override */ + for (i = 0; i < s->avctx->rc_override_count; i++) { + RcOverride *rco = s->avctx->rc_override; + if (rco[i].start_frame > frame_num) + continue; + if (rco[i].end_frame < frame_num) + continue; + + if (rco[i].qscale) + bits = qp2bits(rce, rco[i].qscale); // FIXME move at end to really force it? + else + bits *= rco[i].quality_factor; + } + + q = bits2qp(rce, bits); + + /* I/B difference */ + if (pict_type == AV_PICTURE_TYPE_I && s->avctx->i_quant_factor < 0.0) + q = -q * s->avctx->i_quant_factor + s->avctx->i_quant_offset; + else if (pict_type == AV_PICTURE_TYPE_B && s->avctx->b_quant_factor < 0.0) + q = -q * s->avctx->b_quant_factor + s->avctx->b_quant_offset; + if (q < 1) + q = 1; + + return q; +} + +static 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 }; // approximate bits at quant=1 + uint64_t const_bits[5] = { 0 }; // quantizer independent bits + uint64_t all_const_bits; + uint64_t all_available_bits = (uint64_t)(s->bit_rate * + (double)rcc->num_entries / fps); + double rate_factor = 0; + double step; + const int filter_size = (int)(a->qblur * 4) | 1; + double expected_bits; + double *qscale, *blurred_qscale, qscale_sum; + + /* find complexity & const_bits & decide the pict_types */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + rce->new_pict_type = rce->pict_type; + rcc->i_cplx_sum[rce->pict_type] += rce->i_tex_bits * rce->qscale; + rcc->p_cplx_sum[rce->pict_type] += rce->p_tex_bits * rce->qscale; + rcc->mv_bits_sum[rce->pict_type] += rce->mv_bits; + rcc->frame_count[rce->pict_type]++; + + complexity[rce->new_pict_type] += (rce->i_tex_bits + rce->p_tex_bits) * + (double)rce->qscale; + const_bits[rce->new_pict_type] += rce->mv_bits + rce->misc_bits; + } + + all_const_bits = const_bits[AV_PICTURE_TYPE_I] + + const_bits[AV_PICTURE_TYPE_P] + + const_bits[AV_PICTURE_TYPE_B]; + + if (all_available_bits < all_const_bits) { + av_log(s->avctx, AV_LOG_ERROR, "requested bitrate is too low\n"); + return -1; + } + + qscale = av_malloc(sizeof(double) * rcc->num_entries); + blurred_qscale = av_malloc(sizeof(double) * rcc->num_entries); + if (!qscale || !blurred_qscale) { + av_free(qscale); + av_free(blurred_qscale); + return AVERROR(ENOMEM); + } + toobig = 0; + + for (step = 256 * 256; step > 0.0000001; step *= 0.5) { + expected_bits = 0; + rate_factor += step; + + rcc->buffer_index = s->avctx->rc_buffer_size / 2; + + /* find qscale */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + qscale[i] = get_qscale(s, &rcc->entry[i], rate_factor, i); + rcc->last_qscale_for[rce->pict_type] = qscale[i]; + } + assert(filter_size % 2 == 1); + + /* fixed I/B QP relative to P mode */ + for (i = rcc->num_entries - 1; i >= 0; i--) { + RateControlEntry *rce = &rcc->entry[i]; + + qscale[i] = get_diff_limited_q(s, rce, qscale[i]); + } + + /* smooth curve */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + const int pict_type = rce->new_pict_type; + int j; + double q = 0.0, sum = 0.0; + + for (j = 0; j < filter_size; j++) { + int index = i + j - filter_size / 2; + double d = index - i; + double coeff = a->qblur == 0 ? 1.0 : exp(-d * d / (a->qblur * a->qblur)); + + if (index < 0 || index >= rcc->num_entries) + continue; + if (pict_type != rcc->entry[index].new_pict_type) + continue; + q += qscale[index] * coeff; + sum += coeff; + } + blurred_qscale[i] = q / sum; + } + + /* find expected bits */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + double bits; + + rce->new_qscale = modify_qscale(s, rce, blurred_qscale[i], i); -void ff_write_pass1_stats(MpegEncContext *s) -{ - snprintf(s->avctx->stats_out, 256, - "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d " - "fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d;\n", - s->current_picture_ptr->f->display_picture_number, - s->current_picture_ptr->f->coded_picture_number, - s->pict_type, - s->current_picture.f->quality, - s->i_tex_bits, - s->p_tex_bits, - s->mv_bits, - s->misc_bits, - s->f_code, - s->b_code, - s->current_picture.mc_mb_var_sum, - s->current_picture.mb_var_sum, - s->i_count, s->skip_count, - s->header_bits); -} + bits = qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; + bits += 8 * ff_vbv_update(s, bits); -static inline double qp2bits(RateControlEntry *rce, double qp) -{ - if (qp <= 0.0) { - av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n"); + rce->expected_bits = expected_bits; + expected_bits += bits; + } + + ff_dlog(s->avctx, + "expected_bits: %f all_available_bits: %d rate_factor: %f\n", + expected_bits, (int)all_available_bits, rate_factor); + if (expected_bits > all_available_bits) { + rate_factor -= step; + ++toobig; + } } - return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits + 1) / qp; -} + av_free(qscale); + av_free(blurred_qscale); -static inline double bits2qp(RateControlEntry *rce, double bits) -{ - if (bits < 0.9) { - av_log(NULL, AV_LOG_ERROR, "bits<0.9\n"); + /* check bitrate calculations and print info */ + qscale_sum = 0.0; + for (i = 0; i < rcc->num_entries; i++) { + ff_dlog(s, "[lavc rc] entry[%d].new_qscale = %.3f qp = %.3f\n", + i, + rcc->entry[i].new_qscale, + rcc->entry[i].new_qscale / FF_QP2LAMBDA); + qscale_sum += av_clip(rcc->entry[i].new_qscale / FF_QP2LAMBDA, + s->avctx->qmin, s->avctx->qmax); } - return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits + 1) / bits; + 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; } av_cold int ff_rate_control_init(MpegEncContext *s) @@ -100,12 +464,6 @@ av_cold int ff_rate_control_init(MpegEncContext *s) "isB", "avgQP", "qComp", -#if 0 - "lastIQP", - "lastPQP", - "lastBQP", - "nextNonBQP", -#endif "avgIITex", "avgPITex", "avgPPTex", @@ -126,11 +484,11 @@ av_cold int ff_rate_control_init(MpegEncContext *s) emms_c(); res = av_expr_parse(&rcc->rc_eq_eval, - s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", + s->rc_eq ? s->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx); if (res < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->avctx->rc_eq); + av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->rc_eq); return res; } @@ -149,7 +507,7 @@ av_cold int ff_rate_control_init(MpegEncContext *s) } rcc->buffer_index = s->avctx->rc_initial_buffer_occupancy; - if (s->flags & CODEC_FLAG_PASS2) { + if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { int i; char *p; @@ -162,9 +520,11 @@ av_cold int ff_rate_control_init(MpegEncContext *s) return -1; rcc->entry = av_mallocz(i * sizeof(RateControlEntry)); rcc->num_entries = i; + if (!rcc->entry) + return AVERROR(ENOMEM); - /* init all to skipped p frames - * (with b frames we might have a not encoded frame at the end FIXME) */ + /* 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]; @@ -184,7 +544,7 @@ av_cold int ff_rate_control_init(MpegEncContext *s) next = strchr(p, ';'); if (next) { - (*next) = 0; // sscanf in unbelievably slow on looong strings // FIXME copy / do not write + (*next) = 0; // sscanf is unbelievably slow on looong strings // FIXME copy / do not write next++; } e = sscanf(p, " in:%d ", &picture_number); @@ -209,22 +569,13 @@ av_cold int ff_rate_control_init(MpegEncContext *s) p = next; } - if (init_pass2(s) < 0) - return -1; - - // FIXME maybe move to end - if ((s->flags & CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) { -#if CONFIG_LIBXVID - return ff_xvid_rate_control_init(s); -#else - av_log(s->avctx, AV_LOG_ERROR, - "Xvid ratecontrol requires libavcodec compiled with Xvid support.\n"); + if (init_pass2(s) < 0) { + ff_rate_control_uninit(s); return -1; -#endif } } - if (!(s->flags & CODEC_FLAG_PASS2)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_PASS2)) { rcc->short_term_qsum = 0.001; rcc->short_term_qcount = 0.001; @@ -236,9 +587,9 @@ av_cold int ff_rate_control_init(MpegEncContext *s) return -1; } /* init stuff with the user specified complexity */ - if (s->avctx->rc_initial_cplx) { + if (s->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; + double bits = s->rc_initial_cplx * (i / 10000.0 + 1.0) * s->mb_num; RateControlEntry rce; if (i % ((s->gop_size + 3) / 4) == 0) @@ -278,305 +629,60 @@ av_cold int ff_rate_control_init(MpegEncContext *s) // FIXME misbehaves a little for variable fps rcc->pass1_wanted_bits += s->bit_rate / (1 / av_q2d(s->avctx->time_base)); } - } - } - - return 0; -} - -av_cold void ff_rate_control_uninit(MpegEncContext *s) -{ - RateControlContext *rcc = &s->rc_context; - emms_c(); - - av_expr_free(rcc->rc_eq_eval); - av_freep(&rcc->entry); - -#if CONFIG_LIBXVID - if ((s->flags & CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) - ff_xvid_rate_control_uninit(s); -#endif -} - -int ff_vbv_update(MpegEncContext *s, int frame_size) -{ - RateControlContext *rcc = &s->rc_context; - const double fps = 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; - - av_dlog(s, "%d %f %d %f %f\n", - buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate); - - if (buffer_size) { - int left; - - rcc->buffer_index -= frame_size; - if (rcc->buffer_index < 0) { - av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n"); - rcc->buffer_index = 0; - } - - left = buffer_size - rcc->buffer_index - 1; - rcc->buffer_index += av_clip(left, min_rate, max_rate); - - if (rcc->buffer_index > buffer_size) { - int stuffing = ceil((rcc->buffer_index - buffer_size) / 8); - - if (stuffing < 4 && s->codec_id == AV_CODEC_ID_MPEG4) - stuffing = 4; - rcc->buffer_index -= 8 * stuffing; - - if (s->avctx->debug & FF_DEBUG_RC) - av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing); - - return stuffing; - } - } - return 0; -} - -/** - * Modify the bitrate curve from pass1 for one frame. - */ -static double get_qscale(MpegEncContext *s, RateControlEntry *rce, - double rate_factor, int frame_num) -{ - RateControlContext *rcc = &s->rc_context; - AVCodecContext *a = s->avctx; - const int pict_type = rce->new_pict_type; - const double mb_num = s->mb_num; - double q, bits; - int i; - - double const_values[] = { - M_PI, - M_E, - rce->i_tex_bits * rce->qscale, - rce->p_tex_bits * rce->qscale, - (rce->i_tex_bits + rce->p_tex_bits) * (double)rce->qscale, - rce->mv_bits / mb_num, - rce->pict_type == AV_PICTURE_TYPE_B ? (rce->f_code + rce->b_code) * 0.5 : rce->f_code, - rce->i_count / mb_num, - rce->mc_mb_var_sum / mb_num, - rce->mb_var_sum / mb_num, - rce->pict_type == AV_PICTURE_TYPE_I, - rce->pict_type == AV_PICTURE_TYPE_P, - rce->pict_type == AV_PICTURE_TYPE_B, - rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type], - a->qcompress, -#if 0 - rcc->last_qscale_for[AV_PICTURE_TYPE_I], - rcc->last_qscale_for[AV_PICTURE_TYPE_P], - rcc->last_qscale_for[AV_PICTURE_TYPE_B], - rcc->next_non_b_qscale, -#endif - rcc->i_cplx_sum[AV_PICTURE_TYPE_I] / (double)rcc->frame_count[AV_PICTURE_TYPE_I], - rcc->i_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], - rcc->p_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], - rcc->p_cplx_sum[AV_PICTURE_TYPE_B] / (double)rcc->frame_count[AV_PICTURE_TYPE_B], - (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type], - 0 - }; - - bits = av_expr_eval(rcc->rc_eq_eval, const_values, rce); - if (isnan(bits)) { - av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->avctx->rc_eq); - return -1; - } - - rcc->pass1_rc_eq_output_sum += bits; - bits *= rate_factor; - if (bits < 0.0) - bits = 0.0; - bits += 1.0; // avoid 1/0 issues - - /* user override */ - for (i = 0; i < s->avctx->rc_override_count; i++) { - RcOverride *rco = s->avctx->rc_override; - if (rco[i].start_frame > frame_num) - continue; - if (rco[i].end_frame < frame_num) - continue; - - if (rco[i].qscale) - bits = qp2bits(rce, rco[i].qscale); // FIXME move at end to really force it? - else - bits *= rco[i].quality_factor; - } - - q = bits2qp(rce, bits); - - /* I/B difference */ - if (pict_type == AV_PICTURE_TYPE_I && s->avctx->i_quant_factor < 0.0) - q = -q * s->avctx->i_quant_factor + s->avctx->i_quant_offset; - else if (pict_type == AV_PICTURE_TYPE_B && s->avctx->b_quant_factor < 0.0) - q = -q * s->avctx->b_quant_factor + s->avctx->b_quant_offset; - if (q < 1) - q = 1; - - return q; -} - -static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, double q) -{ - RateControlContext *rcc = &s->rc_context; - AVCodecContext *a = s->avctx; - const int pict_type = rce->new_pict_type; - const double last_p_q = rcc->last_qscale_for[AV_PICTURE_TYPE_P]; - const double last_non_b_q = rcc->last_qscale_for[rcc->last_non_b_pict_type]; - - if (pict_type == AV_PICTURE_TYPE_I && - (a->i_quant_factor > 0.0 || rcc->last_non_b_pict_type == AV_PICTURE_TYPE_P)) - q = last_p_q * FFABS(a->i_quant_factor) + a->i_quant_offset; - else if (pict_type == AV_PICTURE_TYPE_B && - a->b_quant_factor > 0.0) - q = last_non_b_q * a->b_quant_factor + a->b_quant_offset; - if (q < 1) - q = 1; - - /* last qscale / qdiff stuff */ - if (rcc->last_non_b_pict_type == pict_type || pict_type != AV_PICTURE_TYPE_I) { - double last_q = rcc->last_qscale_for[pict_type]; - const int maxdiff = FF_QP2LAMBDA * a->max_qdiff; - - if (q > last_q + maxdiff) - q = last_q + maxdiff; - else if (q < last_q - maxdiff) - q = last_q - maxdiff; - } - - rcc->last_qscale_for[pict_type] = q; // Note we cannot do that after blurring - - if (pict_type != AV_PICTURE_TYPE_B) - rcc->last_non_b_pict_type = pict_type; - - return q; -} - -/** - * Get the qmin & qmax for pict_type. - */ -static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type) -{ - int qmin = s->avctx->lmin; - int qmax = s->avctx->lmax; - - assert(qmin <= qmax); - - switch (pict_type) { - case AV_PICTURE_TYPE_B: - qmin = (int)(qmin * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); - qmax = (int)(qmax * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); - break; - case AV_PICTURE_TYPE_I: - qmin = (int)(qmin * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); - qmax = (int)(qmax * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); - break; - } - - qmin = av_clip(qmin, 1, FF_LAMBDA_MAX); - qmax = av_clip(qmax, 1, FF_LAMBDA_MAX); - - if (qmax < qmin) - qmax = qmin; + } + } - *qmin_ret = qmin; - *qmax_ret = qmax; + return 0; } -static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, - double q, int frame_num) +av_cold void ff_rate_control_uninit(MpegEncContext *s) { - RateControlContext *rcc = &s->rc_context; - 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; - const int pict_type = rce->new_pict_type; - int qmin, qmax; - - get_qminmax(&qmin, &qmax, s, pict_type); + RateControlContext *rcc = &s->rc_context; + emms_c(); - /* modulation */ - if (s->avctx->rc_qmod_freq && - frame_num % s->avctx->rc_qmod_freq == 0 && - pict_type == AV_PICTURE_TYPE_P) - q *= s->avctx->rc_qmod_amp; + av_expr_free(rcc->rc_eq_eval); + av_freep(&rcc->entry); +} - /* buffer overflow/underflow protection */ - if (buffer_size) { - double expected_size = rcc->buffer_index; - double q_limit; +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; - 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); + ff_dlog(s, "%d %f %d %f %f\n", + buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate); - q_limit = bits2qp(rce, - FFMAX((min_rate - buffer_size + rcc->buffer_index) * - s->avctx->rc_min_vbv_overflow_use, 1)); + if (buffer_size) { + int left; - 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; - } + 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; } - 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); + left = buffer_size - rcc->buffer_index - 1; + rcc->buffer_index += av_clip(left, min_rate, max_rate); - q_limit = bits2qp(rce, - FFMAX(rcc->buffer_index * - s->avctx->rc_max_available_vbv_use, - 1)); - if (q < q_limit) { - if (s->avctx->debug & FF_DEBUG_RC) - av_log(s->avctx, AV_LOG_DEBUG, - "limiting QP %f -> %f\n", q, q_limit); - q = q_limit; - } - } - } - av_dlog(s, "q:%f max:%f min:%f size:%f index:%f agr:%f\n", - q, max_rate, min_rate, buffer_size, rcc->buffer_index, - s->avctx->rc_buffer_aggressivity); - if (s->avctx->rc_qsquish == 0.0 || qmin == qmax) { - if (q < qmin) - q = qmin; - else if (q > qmax) - q = qmax; - } else { - double min2 = log(qmin); - double max2 = log(qmax); + if (rcc->buffer_index > buffer_size) { + int stuffing = ceil((rcc->buffer_index - buffer_size) / 8); - 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; + if (stuffing < 4 && s->codec_id == AV_CODEC_ID_MPEG4) + stuffing = 4; + rcc->buffer_index -= 8 * stuffing; - q = exp(q); - } + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing); - return q; + return stuffing; + } + } + return 0; } -// ---------------------------------- -// 1 Pass Code - static double predict_size(Predictor *p, double q, double var) { return p->coeff * var / (q * p->count); @@ -602,7 +708,7 @@ static void adaptive_quantization(MpegEncContext *s, double q) 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; + const float border_masking = s->border_masking; float bits_sum = 0.0; float cplx_sum = 0.0; float *cplx_tab = s->cplx_tab; @@ -624,9 +730,9 @@ static void adaptive_quantization(MpegEncContext *s, double q) int mb_distance; float mb_factor = 0.0; if (spat_cplx < 4) - spat_cplx = 4; // FIXME finetune + spat_cplx = 4; // FIXME fine-tune if (temp_cplx < 4) - temp_cplx = 4; // FIXME finetune + temp_cplx = 4; // FIXME fine-tune if ((s->mb_type[mb_xy] & CANDIDATE_MB_TYPE_INTRA)) { // FIXME hq mode cplx = spat_cplx; @@ -742,12 +848,6 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) Picture * const pic = &s->current_picture; emms_c(); -#if CONFIG_LIBXVID - if ((s->flags & CODEC_FLAG_PASS2) && - s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) - return ff_xvid_rate_estimate_qscale(s, dry_run); -#endif - get_qminmax(&qmin, &qmax, s, pict_type); fps = 1 / av_q2d(s->avctx->time_base); @@ -760,7 +860,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) sqrt(last_var), s->frame_bits); } - if (s->flags & CODEC_FLAG_PASS2) { + if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { assert(picture_number >= 0); assert(picture_number < rcc->num_entries); rce = &rcc->entry[picture_number]; @@ -791,12 +891,12 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) var = pict_type == AV_PICTURE_TYPE_I ? pic->mb_var_sum : pic->mc_mb_var_sum; short_term_q = 0; /* avoid warning */ - if (s->flags & CODEC_FLAG_PASS2) { + if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { if (pict_type != AV_PICTURE_TYPE_I) assert(pict_type == rce->new_pict_type); q = rce->new_qscale / br_compensation; - av_dlog(s, "%f %f %f last:%d var:%d type:%d//\n", q, rce->new_qscale, + ff_dlog(s, "%f %f %f last:%d var:%d type:%d//\n", q, rce->new_qscale, br_compensation, s->frame_bits, var, pict_type); } else { rce->pict_type = @@ -884,156 +984,3 @@ float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) } 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 }; // approximate bits at quant=1 - uint64_t const_bits[5] = { 0 }; // quantizer independent bits - uint64_t all_const_bits; - uint64_t all_available_bits = (uint64_t)(s->bit_rate * - (double)rcc->num_entries / fps); - double rate_factor = 0; - double step; - const int filter_size = (int)(a->qblur * 4) | 1; - double expected_bits; - double *qscale, *blurred_qscale, qscale_sum; - - /* find complexity & const_bits & decide the pict_types */ - for (i = 0; i < rcc->num_entries; i++) { - RateControlEntry *rce = &rcc->entry[i]; - - rce->new_pict_type = rce->pict_type; - rcc->i_cplx_sum[rce->pict_type] += rce->i_tex_bits * rce->qscale; - rcc->p_cplx_sum[rce->pict_type] += rce->p_tex_bits * rce->qscale; - rcc->mv_bits_sum[rce->pict_type] += rce->mv_bits; - rcc->frame_count[rce->pict_type]++; - - complexity[rce->new_pict_type] += (rce->i_tex_bits + rce->p_tex_bits) * - (double)rce->qscale; - const_bits[rce->new_pict_type] += rce->mv_bits + rce->misc_bits; - } - - all_const_bits = const_bits[AV_PICTURE_TYPE_I] + - const_bits[AV_PICTURE_TYPE_P] + - const_bits[AV_PICTURE_TYPE_B]; - - if (all_available_bits < all_const_bits) { - av_log(s->avctx, AV_LOG_ERROR, "requested bitrate is too low\n"); - return -1; - } - - qscale = av_malloc(sizeof(double) * rcc->num_entries); - blurred_qscale = av_malloc(sizeof(double) * rcc->num_entries); - toobig = 0; - - for (step = 256 * 256; step > 0.0000001; step *= 0.5) { - expected_bits = 0; - rate_factor += step; - - rcc->buffer_index = s->avctx->rc_buffer_size / 2; - - /* find qscale */ - for (i = 0; i < rcc->num_entries; i++) { - RateControlEntry *rce = &rcc->entry[i]; - - qscale[i] = get_qscale(s, &rcc->entry[i], rate_factor, i); - rcc->last_qscale_for[rce->pict_type] = qscale[i]; - } - assert(filter_size % 2 == 1); - - /* fixed I/B QP relative to P mode */ - for (i = rcc->num_entries - 1; i >= 0; i--) { - RateControlEntry *rce = &rcc->entry[i]; - - qscale[i] = get_diff_limited_q(s, rce, qscale[i]); - } - - /* smooth curve */ - for (i = 0; i < rcc->num_entries; i++) { - RateControlEntry *rce = &rcc->entry[i]; - const int pict_type = rce->new_pict_type; - int j; - double q = 0.0, sum = 0.0; - - for (j = 0; j < filter_size; j++) { - int index = i + j - filter_size / 2; - double d = index - i; - double coeff = a->qblur == 0 ? 1.0 : exp(-d * d / (a->qblur * a->qblur)); - - if (index < 0 || index >= rcc->num_entries) - continue; - if (pict_type != rcc->entry[index].new_pict_type) - continue; - q += qscale[index] * coeff; - sum += coeff; - } - blurred_qscale[i] = q / sum; - } - - /* find expected bits */ - for (i = 0; i < rcc->num_entries; i++) { - RateControlEntry *rce = &rcc->entry[i]; - double bits; - - rce->new_qscale = modify_qscale(s, rce, blurred_qscale[i], i); - - bits = qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; - bits += 8 * ff_vbv_update(s, bits); - - rce->expected_bits = expected_bits; - expected_bits += bits; - } - - av_dlog(s->avctx, - "expected_bits: %f all_available_bits: %d rate_factor: %f\n", - expected_bits, (int)all_available_bits, rate_factor); - if (expected_bits > all_available_bits) { - rate_factor -= step; - ++toobig; - } - } - av_free(qscale); - av_free(blurred_qscale); - - /* check bitrate calculations and print info */ - qscale_sum = 0.0; - for (i = 0; i < rcc->num_entries; i++) { - av_dlog(s, "[lavc rc] entry[%d].new_qscale = %.3f qp = %.3f\n", - i, - rcc->entry[i].new_qscale, - rcc->entry[i].new_qscale / FF_QP2LAMBDA); - qscale_sum += av_clip(rcc->entry[i].new_qscale / FF_QP2LAMBDA, - s->avctx->qmin, s->avctx->qmax); - } - assert(toobig <= 40); - av_log(s->avctx, AV_LOG_DEBUG, - "[lavc rc] requested bitrate: %d bps expected bitrate: %d bps\n", - s->bit_rate, - (int)(expected_bits / ((double)all_available_bits / s->bit_rate))); - av_log(s->avctx, AV_LOG_DEBUG, - "[lavc rc] estimated target average qp: %.3f\n", - (float)qscale_sum / rcc->num_entries); - if (toobig == 0) { - av_log(s->avctx, AV_LOG_INFO, - "[lavc rc] Using all of requested bitrate is not " - "necessary for this video with these parameters.\n"); - } else if (toobig == 40) { - av_log(s->avctx, AV_LOG_ERROR, - "[lavc rc] Error: bitrate too low for this video " - "with these parameters.\n"); - return -1; - } else if (fabs(expected_bits / all_available_bits - 1.0) > 0.01) { - av_log(s->avctx, AV_LOG_ERROR, - "[lavc rc] Error: 2pass curve failed to converge\n"); - return -1; - } - - return 0; -} diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h index 63ebeb2..2976806 100644 --- a/libavcodec/ratecontrol.h +++ b/libavcodec/ratecontrol.h @@ -68,7 +68,7 @@ typedef struct RateControlContext{ 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 pass1_wanted_bits; ///< bits which should have been output 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; @@ -91,13 +91,8 @@ 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/libavcodec/raw.c b/libavcodec/raw.c index 541ef7a..67dff9b 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -53,6 +53,7 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { { AV_PIX_FMT_YUYV422, MKTAG('V', '4', '2', '2') }, { AV_PIX_FMT_YUYV422, MKTAG('V', 'Y', 'U', 'Y') }, { AV_PIX_FMT_YUYV422, MKTAG('Y', 'U', 'N', 'V') }, + { AV_PIX_FMT_YUYV422, MKTAG('Y', 'U', 'Y', 'V') }, { AV_PIX_FMT_YVYU422, MKTAG('Y', 'V', 'Y', 'U') }, /* Philips */ { AV_PIX_FMT_UYVY422, MKTAG('U', 'Y', 'V', 'Y') }, { AV_PIX_FMT_UYVY422, MKTAG('H', 'D', 'Y', 'C') }, diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 3b69e49..284c345 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -109,8 +109,10 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) memset(context->palette->data, 0, AVPALETTE_SIZE); } - context->frame_size = avpicture_get_size(avctx->pix_fmt, avctx->width, - avctx->height); + context->frame_size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, + avctx->height, 1); + if ((avctx->bits_per_coded_sample == 4 || avctx->bits_per_coded_sample == 2) && avctx->pix_fmt == AV_PIX_FMT_PAL8 && (!avctx->codec_tag || avctx->codec_tag == MKTAG('r','a','w',' '))) @@ -129,10 +131,10 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) return 0; } -static void flip(AVCodecContext *avctx, AVPicture *picture) +static void flip(AVCodecContext *avctx, AVFrame *frame) { - picture->data[0] += picture->linesize[0] * (avctx->height - 1); - picture->linesize[0] *= -1; + frame->data[0] += frame->linesize[0] * (avctx->height - 1); + frame->linesize[0] *= -1; } static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, @@ -146,7 +148,6 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, int res; AVFrame *frame = data; - AVPicture *picture = data; frame->pict_type = AV_PICTURE_TYPE_I; frame->key_frame = 1; @@ -194,8 +195,9 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, avctx->codec_tag == MKTAG('A', 'V', 'u', 'p')) buf += buf_size - context->frame_size; - if ((res = avpicture_fill(picture, buf, avctx->pix_fmt, - avctx->width, avctx->height)) < 0) + if ((res = av_image_fill_arrays(frame->data, frame->linesize, + buf, avctx->pix_fmt, + avctx->width, avctx->height, 1)) < 0) return res; if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { @@ -224,22 +226,22 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, frame->linesize[0] = (frame->linesize[0] + 3) & ~3; if (context->flip) - flip(avctx, picture); + flip(avctx, frame); if (avctx->codec_tag == MKTAG('Y', 'V', '1', '2') || avctx->codec_tag == MKTAG('Y', 'V', '1', '6') || avctx->codec_tag == MKTAG('Y', 'V', '2', '4') || avctx->codec_tag == MKTAG('Y', 'V', 'U', '9')) - FFSWAP(uint8_t *, picture->data[1], picture->data[2]); + FFSWAP(uint8_t *, frame->data[1], frame->data[2]); if (avctx->codec_tag == AV_RL32("yuv2") && avctx->pix_fmt == AV_PIX_FMT_YUYV422) { int x, y; - uint8_t *line = picture->data[0]; + uint8_t *line = frame->data[0]; for (y = 0; y < avctx->height; y++) { for (x = 0; x < avctx->width; x++) line[2 * x + 1] ^= 0x80; - line += picture->linesize[0]; + line += frame->linesize[0]; } } diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index bca0d08..60bd0c7 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -29,15 +29,19 @@ #include "internal.h" #include "libavutil/pixdesc.h" #include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" #include "libavutil/internal.h" static av_cold int raw_encode_init(AVCodecContext *avctx) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - avctx->coded_frame = avctx->priv_data; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc); if(!avctx->codec_tag) avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt); @@ -47,15 +51,18 @@ static av_cold int raw_encode_init(AVCodecContext *avctx) static int raw_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { - int ret = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + int ret = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); if (ret < 0) return ret; if ((ret = ff_alloc_packet(pkt, ret)) < 0) return ret; - if ((ret = avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, avctx->width, - avctx->height, pkt->data, pkt->size)) < 0) + if ((ret = av_image_copy_to_buffer(pkt->data, pkt->size, + frame->data, frame->linesize, + frame->format, + frame->width, frame->height, 1)) < 0) return ret; if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 && @@ -74,7 +81,6 @@ AVCodec ff_rawvideo_encoder = { .long_name = NULL_IF_CONFIG_SMALL("raw video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_RAWVIDEO, - .priv_data_size = sizeof(AVFrame), .init = raw_encode_init, .encode2 = raw_encode, }; diff --git a/libavcodec/rdft.c b/libavcodec/rdft.c index 54cf14a..1965253 100644 --- a/libavcodec/rdft.c +++ b/libavcodec/rdft.c @@ -99,8 +99,6 @@ static void rdft_calc_c(RDFTContext *s, FFTSample *data) av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans) { int n = 1 << nbits; - int i; - const double theta = (trans == DFT_R2C || trans == DFT_C2R ? -1 : 1)*2*M_PI/n; s->nbits = nbits; s->inverse = trans == IDFT_C2R || trans == DFT_C2R; @@ -116,8 +114,11 @@ av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans) s->tcos = ff_cos_tabs[nbits]; s->tsin = ff_sin_tabs[nbits]+(trans == DFT_R2C || trans == DFT_C2R)*(n>>2); #if !CONFIG_HARDCODED_TABLES - for (i = 0; i < (n>>2); i++) { - s->tsin[i] = sin(i*theta); + { + int i; + const double theta = (trans == DFT_R2C || trans == DFT_C2R ? -1 : 1) * 2 * M_PI / n; + for (i = 0; i < (n >> 2); i++) + s->tsin[i] = sin(i * theta); } #endif s->rdft_calc = rdft_calc_c; diff --git a/libavcodec/rectangle.h b/libavcodec/rectangle.h index 73e8b0a..616a637 100644 --- a/libavcodec/rectangle.h +++ b/libavcodec/rectangle.h @@ -64,7 +64,7 @@ static av_always_inline void fill_rectangle(void *vp, int w, int h, int stride, *(uint32_t*)(p + 2*stride)= v; *(uint32_t*)(p + 3*stride)= v; }else if(w==8){ - //gcc can't optimize 64bit math on x86_32 + // gcc cannot optimize 64-bit math on x86_32 #if HAVE_FAST_64BIT const uint64_t v= size==2 ? val*0x0001000100010001ULL : val*0x0100000001ULL; *(uint64_t*)(p + 0*stride)= v; diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c index 460482a..a89fa06 100644 --- a/libavcodec/remove_extradata_bsf.c +++ b/libavcodec/remove_extradata_bsf.c @@ -18,38 +18,99 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/log.h" +#include "libavutil/opt.h" + #include "avcodec.h" +#include "bsf.h" +enum RemoveFreq { + REMOVE_FREQ_KEYFRAME, + REMOVE_FREQ_ALL, +}; -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; +typedef struct RemoveExtradataContext { + const AVClass *class; + int freq; - 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; + AVCodecParserContext *parser; + AVCodecContext *avctx; +} RemoveExtradataContext; + +static int remove_extradata(AVBSFContext *ctx, AVPacket *out) +{ + RemoveExtradataContext *s = ctx->priv_data; + + AVPacket *in; + int ret; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (s->parser && s->parser->parser->split) { + if (s->freq == REMOVE_FREQ_ALL || + (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) { + int i = s->parser->parser->split(s->avctx, in->data, in->size); + in->data += i; + in->size -= i; } } - *poutbuf= (uint8_t *) buf; - *poutbuf_size= buf_size; + + av_packet_move_ref(out, in); + av_packet_free(&in); return 0; } -AVBitStreamFilter ff_remove_extradata_bsf={ - "remove_extra", - 0, - remove_extradata, +static int remove_extradata_init(AVBSFContext *ctx) +{ + RemoveExtradataContext *s = ctx->priv_data; + int ret; + + s->parser = av_parser_init(ctx->par_in->codec_id); + + if (s->parser) { + s->avctx = avcodec_alloc_context3(NULL); + if (!s->avctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(s->avctx, ctx->par_in); + if (ret < 0) + return ret; + } + + return 0; +} + +static void remove_extradata_close(AVBSFContext *ctx) +{ + RemoveExtradataContext *s = ctx->priv_data; + + avcodec_free_context(&s->avctx); + av_parser_close(s->parser); +} + +#define OFFSET(x) offsetof(RemoveExtradataContext, x) +static const AVOption options[] = { + { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_ALL, 0, "freq" }, + { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" }, + { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .unit = "freq" }, + { NULL }, +}; + +static const AVClass remove_extradata_class = { + .class_name = "remove_extradata", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVBitStreamFilter ff_remove_extradata_bsf = { + .name = "remove_extra", + .priv_data_size = sizeof(RemoveExtradataContext), + .priv_class = &remove_extradata_class, + .init = remove_extradata_init, + .close = remove_extradata_close, + .filter = remove_extradata, }; diff --git a/libavcodec/rl.c b/libavcodec/rl.c new file mode 100644 index 0000000..9a9cbd9 --- /dev/null +++ b/libavcodec/rl.c @@ -0,0 +1,142 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/mem.h" + +#include "rl.h" + +void ff_rl_free(RLTable *rl) +{ + int i; + + for (i = 0; i < 2; i++) { + av_freep(&rl->max_run[i]); + av_freep(&rl->max_level[i]); + av_freep(&rl->index_run[i]); + } +} + +av_cold int ff_rl_init(RLTable *rl, + uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) +{ + int8_t max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1]; + uint8_t index_run[MAX_RUN + 1]; + int last, run, level, start, end, i; + + /* If table is static, we can quit if rl->max_level[0] is not NULL */ + if (static_store && rl->max_level[0]) + return 0; + + /* compute max_level[], max_run[] and index_run[] */ + for (last = 0; last < 2; last++) { + if (last == 0) { + start = 0; + end = rl->last; + } else { + start = rl->last; + end = rl->n; + } + + memset(max_level, 0, MAX_RUN + 1); + memset(max_run, 0, MAX_LEVEL + 1); + memset(index_run, rl->n, MAX_RUN + 1); + for (i = start; i < end; i++) { + run = rl->table_run[i]; + level = rl->table_level[i]; + if (index_run[run] == rl->n) + index_run[run] = i; + if (level > max_level[run]) + max_level[run] = level; + if (run > max_run[level]) + max_run[level] = run; + } + if (static_store) + rl->max_level[last] = static_store[last]; + else { + rl->max_level[last] = av_malloc(MAX_RUN + 1); + if (!rl->max_level[last]) + goto fail; + } + memcpy(rl->max_level[last], max_level, MAX_RUN + 1); + if (static_store) + rl->max_run[last] = static_store[last] + MAX_RUN + 1; + else { + rl->max_run[last] = av_malloc(MAX_LEVEL + 1); + if (!rl->max_run[last]) + goto fail; + } + memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); + if (static_store) + rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; + else { + rl->index_run[last] = av_malloc(MAX_RUN + 1); + if (!rl->index_run[last]) + goto fail; + } + memcpy(rl->index_run[last], index_run, MAX_RUN + 1); + } + return 0; + +fail: + ff_rl_free(rl); + return AVERROR(ENOMEM); +} + +av_cold void ff_rl_init_vlc(RLTable *rl) +{ + int i, q; + + for (q = 0; q < 32; q++) { + int qmul = q * 2; + int qadd = (q - 1) | 1; + + if (q == 0) { + qmul = 1; + qadd = 0; + } + for (i = 0; i < rl->vlc.table_size; i++) { + int code = rl->vlc.table[i][0]; + int len = rl->vlc.table[i][1]; + int level, run; + + if (len == 0) { // illegal code + run = 66; + level = MAX_LEVEL; + } else if (len < 0) { // more bits needed + run = 0; + level = code; + } else { + if (code == rl->n) { // esc + run = 66; + level = 0; + } else { + run = rl->table_run[code] + 1; + level = rl->table_level[code] * qmul + qadd; + if (code >= rl->last) run += 192; + } + } + rl->rl_vlc[q][i].len = len; + rl->rl_vlc[q][i].level = level; + rl->rl_vlc[q][i].run = run; + } + } +} diff --git a/libavcodec/rl.h b/libavcodec/rl.h index 367cc98..a5725ce 100644 --- a/libavcodec/rl.h +++ b/libavcodec/rl.h @@ -28,7 +28,8 @@ #define AVCODEC_RL_H #include -#include "get_bits.h" + +#include "vlc.h" /* run length table */ #define MAX_RUN 64 @@ -49,12 +50,16 @@ typedef struct RLTable { } RLTable; /** - * * @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] which will hold * the level and run tables, if this is NULL av_malloc() will be used */ -void ff_init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]); -void ff_init_vlc_rl(RLTable *rl); +int ff_rl_init(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]); +void ff_rl_init_vlc(RLTable *rl); + +/** + * Free the contents of a dynamically allocated table. + */ +void ff_rl_free(RLTable *rl); #define INIT_VLC_RL(rl, static_size)\ {\ @@ -68,7 +73,7 @@ void ff_init_vlc_rl(RLTable *rl); for(q=0; q<32; q++)\ rl.rl_vlc[q]= rl_vlc_table[q];\ \ - ff_init_vlc_rl(&rl);\ + ff_rl_init_vlc(&rl);\ }\ } diff --git a/libavcodec/rl2.c b/libavcodec/rl2.c index 54b3e6a..c42a1cd 100644 --- a/libavcodec/rl2.c +++ b/libavcodec/rl2.c @@ -53,7 +53,7 @@ typedef struct Rl2Context { * @param s rl2 context * @param in input buffer * @param size input buffer size - * @param out ouput buffer + * @param out output buffer * @param stride stride of the output buffer * @param video_base offset of the rle data inside the frame */ @@ -224,5 +224,5 @@ AVCodec ff_rl2_decoder = { .init = rl2_decode_init, .close = rl2_decode_end, .decode = rl2_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/rle.c b/libavcodec/rle.c index cbbde93..6c8bf27 100644 --- a/libavcodec/rle.c +++ b/libavcodec/rle.c @@ -18,35 +18,29 @@ * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "libavutil/common.h" + #include "avcodec.h" #include "rle.h" -#include "libavutil/common.h" -/** - * Count up to 127 consecutive pixels which are either all the same or - * all differ from the previous and next pixels. - * @param start Pointer to the first pixel - * @param len Maximum number of pixels - * @param bpp Bytes per pixel - * @param same 1 if searching for identical pixel values. 0 for differing - * @return Number of matching consecutive pixels found - */ -static int count_pixels(const uint8_t *start, int len, int bpp, int same) +int ff_rle_count_pixels(const uint8_t *start, int len, int bpp, int same) { const uint8_t *pos; int count = 1; - for(pos = start + bpp; count < FFMIN(127, len); pos += bpp, count ++) { - if(same != !memcmp(pos-bpp, pos, bpp)) { - if(!same) { - /* if bpp == 1, then 0 1 1 0 is more efficiently encoded as a single - * raw block of pixels. for larger bpp, RLE is as good or better */ - if(bpp == 1 && count + 1 < FFMIN(127, len) && *pos != *(pos+1)) + for (pos = start + bpp; count < FFMIN(127, len); pos += bpp, count++) { + if (same != !memcmp(pos - bpp, pos, bpp)) { + if (!same) { + /* if bpp == 1, then 0 1 1 0 is more efficiently encoded as a + * single raw block of pixels. For larger bpp, RLE is as good + * or better */ + if (bpp == 1 && count + 1 < FFMIN(127, len) && *pos != *(pos + 1)) continue; /* if RLE can encode the next block better than as a raw block, * back up and leave _all_ the identical pixels for RLE */ - count --; + count--; } break; } @@ -55,25 +49,28 @@ static int count_pixels(const uint8_t *start, int len, int bpp, int same) return count; } -int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *ptr , int bpp, int w, - int add_rep, int xor_rep, int add_raw, int xor_raw) +int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *ptr, int bpp, + int w, int add_rep, int xor_rep, int add_raw, int xor_raw) { int count, x; uint8_t *out = outbuf; - for(x = 0; x < w; x += count) { + for (x = 0; x < w; x += count) { /* see if we can encode the next set of pixels with RLE */ - if((count = count_pixels(ptr, w-x, bpp, 1)) > 1) { - if(out + bpp + 1 > outbuf + out_size) return -1; + if ((count = ff_rle_count_pixels(ptr, w - x, bpp, 1)) > 1) { + if (out + bpp + 1 > outbuf + out_size) + return -1; + *out++ = (count ^ xor_rep) + add_rep; memcpy(out, ptr, bpp); out += bpp; } else { /* fall back on uncompressed */ - count = count_pixels(ptr, w-x, bpp, 0); - if(out + bpp*count >= outbuf + out_size) return -1; - *out++ = (count ^ xor_raw) + add_raw; + count = ff_rle_count_pixels(ptr, w - x, bpp, 0); + if (out + bpp * count >= outbuf + out_size) + return -1; + *out++ = (count ^ xor_raw) + add_raw; memcpy(out, ptr, bpp * count); out += bpp * count; } diff --git a/libavcodec/rle.h b/libavcodec/rle.h index 00261d3..f1b0c78 100644 --- a/libavcodec/rle.h +++ b/libavcodec/rle.h @@ -24,8 +24,20 @@ #include /** - * RLE compress the row, with maximum size of out_size. Value before repeated bytes is (count ^ xor_rep) + add_rep. - * Value before raw bytes is (count ^ xor_raw) + add_raw. + * Count up to 127 consecutive pixels which are either all the same or + * all differ from the previous and next pixels. + * @param start Pointer to the first pixel + * @param len Maximum number of pixels + * @param bpp Bytes per pixel + * @param same 1 if searching for identical pixel values, 0 for differing + * @return Number of matching consecutive pixels found + */ +int ff_rle_count_pixels(const uint8_t *start, int len, int bpp, int same); + +/** + * RLE compress the row, with maximum size of out_size. + * Value before repeated bytes is (count ^ xor_rep) + add_rep. + * Value before raw bytes is (count ^ xor_raw) + add_raw. * @param outbuf Output buffer * @param out_size Maximum output size * @param inbuf Input buffer @@ -33,7 +45,7 @@ * @param w Image width * @return Size of output in bytes, or -1 if larger than out_size */ -int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *inbuf, int bpp, int w, - int add_rep, int xor_rep, int add_raw, int xor_raw); +int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *inbuf, int bpp, + int w, int add_rep, int xor_rep, int add_raw, int xor_raw); #endif /* AVCODEC_RLE_H */ diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c index 402eb78..f687f5c 100644 --- a/libavcodec/roqaudioenc.c +++ b/libavcodec/roqaudioenc.c @@ -32,8 +32,7 @@ #define MAX_DPCM (127*127) -typedef struct -{ +typedef struct ROQDPCMContext { short lastSample[2]; int input_frames; int buffered_samples; @@ -201,7 +200,7 @@ AVCodec ff_roq_dpcm_encoder = { .init = roq_dpcm_encode_init, .encode2 = roq_dpcm_encode_frame, .close = roq_dpcm_encode_close, - .capabilities = CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c index ac7d4ba..4f778dc 100644 --- a/libavcodec/roqvideodec.c +++ b/libavcodec/roqvideodec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -29,6 +29,8 @@ #include #include +#include "libavutil/imgutils.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -190,7 +192,7 @@ static int roq_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; RoqContext *s = avctx->priv_data; - int copy= !s->current_frame->data[0]; + int copy = !s->current_frame->data[0] && s->last_frame->data[0]; int ret; if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) { @@ -198,9 +200,11 @@ static int roq_decode_frame(AVCodecContext *avctx, return ret; } - if(copy) - av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame, - avctx->pix_fmt, avctx->width, avctx->height); + if (copy) { + ret = av_frame_copy(s->current_frame, s->last_frame); + if (ret < 0) + return ret; + } bytestream2_init(&s->gb, buf, buf_size); roqvideo_decode_frame(s); @@ -234,5 +238,5 @@ AVCodec ff_roq_decoder = { .init = roq_decode_init, .close = roq_decode_end, .decode = roq_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 871371b..6421ccc 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -183,8 +183,7 @@ static inline int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size) return sdiff; } -typedef struct -{ +typedef struct SubcelEvaluation { int eval_dist[4]; int best_bit_use; int best_coding; @@ -194,8 +193,7 @@ typedef struct int cbEntry; } SubcelEvaluation; -typedef struct -{ +typedef struct CelEvaluation { int eval_dist[4]; int best_coding; @@ -207,8 +205,7 @@ typedef struct int sourceX, sourceY; } CelEvaluation; -typedef struct -{ +typedef struct RoqCodebooks { int numCB4; int numCB2; int usedCB2[MAX_CBS_2x2]; @@ -244,11 +241,13 @@ typedef struct RoqTempData /** * Initialize cel evaluators and set their source coordinates */ -static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) +static int create_cel_evals(RoqContext *enc, RoqTempdata *tempData) { int n=0, x, y, i; tempData->cel_evals = av_malloc(enc->width*enc->height/64 * sizeof(CelEvaluation)); + if (!tempData->cel_evals) + return AVERROR(ENOMEM); /* Map to the ROQ quadtree order */ for (y=0; yheight; y+=16) @@ -257,6 +256,8 @@ static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) tempData->cel_evals[n ].sourceX = x + (i&1)*8; tempData->cel_evals[n++].sourceY = y + (i&2)*4; } + + return 0; } /** @@ -598,8 +599,7 @@ static inline uint8_t motion_arg(motion_vect mot) return ((ax&15)<<4) | (ay&15); } -typedef struct -{ +typedef struct CodingSpool { int typeSpool; int typeSpoolLength; uint8_t argumentSpool[64]; @@ -735,21 +735,6 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData, /* Flush the remainder of the argument/type spool */ while (spool.typeSpoolLength) write_typecode(&spool, 0x0); - -#if 0 - uint8_t *fdata[3] = {enc->frame_to_enc->data[0], - enc->frame_to_enc->data[1], - enc->frame_to_enc->data[2]}; - uint8_t *cdata[3] = {enc->current_frame->data[0], - enc->current_frame->data[1], - enc->current_frame->data[2]}; - av_log(enc->avctx, AV_LOG_ERROR, "Expected distortion: %i Actual: %i\n", - dist, - block_sse(fdata, cdata, 0, 0, 0, 0, - enc->frame_to_enc->linesize, - enc->current_frame->linesize, - enc->width)); //WARNING: Square dimensions implied... -#endif } @@ -791,26 +776,36 @@ static void create_clusters(const AVFrame *frame, int w, int h, uint8_t *yuvClus } } -static void generate_codebook(RoqContext *enc, RoqTempdata *tempdata, - int *points, int inputCount, roq_cell *results, - int size, int cbsize) +static int generate_codebook(RoqContext *enc, RoqTempdata *tempdata, + int *points, int inputCount, roq_cell *results, + int size, int cbsize) { - int i, j, k; + int i, j, k, ret = 0; int c_size = size*size/4; int *buf; int *codebook = av_malloc(6*c_size*cbsize*sizeof(int)); int *closest_cb; - if (size == 4) + if (!codebook) + return AVERROR(ENOMEM); + + if (size == 4) { closest_cb = av_malloc(6*c_size*inputCount*sizeof(int)); - else + if (!closest_cb) { + ret = AVERROR(ENOMEM); + goto out; + } + } else closest_cb = tempdata->closest_cb2; - ff_init_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); - ff_do_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); - - if (size == 4) - av_free(closest_cb); + ret = ff_init_elbg(points, 6 * c_size, inputCount, codebook, + cbsize, 1, closest_cb, &enc->randctx); + if (ret < 0) + goto out; + ret = ff_do_elbg(points, 6 * c_size, inputCount, codebook, + cbsize, 1, closest_cb, &enc->randctx); + if (ret < 0) + goto out; buf = codebook; for (i=0; iv = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS; results++; } - +out: + if (size == 4) + av_free(closest_cb); av_free(codebook); + return ret; } -static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) +static int generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) { - int i,j; + int i, j, ret = 0; RoqCodebooks *codebooks = &tempData->codebooks; int max = enc->width*enc->height/16; uint8_t mb2[3*4]; @@ -837,6 +835,11 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) int *points = av_malloc(max*6*4*sizeof(int)); int bias; + if (!results4 || !yuvClusters || !points) { + ret = AVERROR(ENOMEM); + goto out; + } + /* Subsample YUV data */ create_clusters(enc->frame_to_enc, enc->width, enc->height, yuvClusters); @@ -847,14 +850,22 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) } /* Create 4x4 codebooks */ - generate_codebook(enc, tempData, points, max, results4, 4, MAX_CBS_4x4); + if ((ret = generate_codebook(enc, tempData, points, max, + results4, 4, MAX_CBS_4x4)) < 0) + goto out; codebooks->numCB4 = MAX_CBS_4x4; tempData->closest_cb2 = av_malloc(max*4*sizeof(int)); + if (!tempData->closest_cb2) { + ret = AVERROR(ENOMEM); + goto out; + } /* Create 2x2 codebooks */ - generate_codebook(enc, tempData, points, max*4, enc->cb2x2, 2, MAX_CBS_2x2); + if ((ret = generate_codebook(enc, tempData, points, max * 4, + enc->cb2x2, 2, MAX_CBS_2x2)) < 0) + goto out; codebooks->numCB2 = MAX_CBS_2x2; @@ -874,22 +885,27 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3, codebooks->unpacked_cb4_enlarged + i*8*8*3); } - +out: av_free(yuvClusters); av_free(points); av_free(results4); + return ret; } -static void roq_encode_video(RoqContext *enc) +static int roq_encode_video(RoqContext *enc) { RoqTempdata *tempData = enc->tmpData; - int i; + int i, ret; memset(tempData, 0, sizeof(*tempData)); - create_cel_evals(enc, tempData); + ret = create_cel_evals(enc, tempData); + if (ret < 0) + return ret; - generate_new_codebooks(enc, tempData); + ret = generate_new_codebooks(enc, tempData); + if (ret < 0) + return ret; if (enc->framesSinceKeyframe >= 1) { motion_search(enc, 8); @@ -924,8 +940,6 @@ static void roq_encode_video(RoqContext *enc) reconstruct_and_encode_image(enc, tempData, enc->width, enc->height, enc->width*enc->height/64); - enc->avctx->coded_frame = enc->current_frame; - /* Rotate frame history */ FFSWAP(AVFrame *, enc->current_frame, enc->last_frame); FFSWAP(motion_vect *, enc->last_motion4, enc->this_motion4); @@ -935,6 +949,8 @@ static void roq_encode_video(RoqContext *enc) av_free(tempData->closest_cb2); enc->framesSinceKeyframe++; + + return 0; } static av_cold int roq_encode_end(AVCodecContext *avctx) @@ -1049,7 +1065,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } enc->out_buf = pkt->data; - /* Check for I frame */ + /* Check for I-frame */ if (enc->framesSinceKeyframe == avctx->gop_size) enc->framesSinceKeyframe = 0; @@ -1069,7 +1085,9 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* Encode the actual frame */ - roq_encode_video(enc); + ret = roq_encode_video(enc); + if (ret < 0) + return ret; pkt->size = enc->out_buf - pkt->data; if (enc->framesSinceKeyframe == 1) diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c index 83dde7a..f3f3fbc 100644 --- a/libavcodec/rpza.c +++ b/libavcodec/rpza.c @@ -1,6 +1,6 @@ /* * Quicktime Video (RPZA) Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -52,23 +52,25 @@ typedef struct RpzaContext { GetByteContext gb; } 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; \ - } \ -} +#define CHECK_BLOCK() \ + if (total_blocks < 1) { \ + av_log(s->avctx, AV_LOG_ERROR, \ + "Block counter just went negative (this should not happen)\n"); \ + return AVERROR_INVALIDDATA; \ + } \ + +#define ADVANCE_BLOCK() \ + { \ + pixel_ptr += 4; \ + if (pixel_ptr >= width) \ + { \ + pixel_ptr = 0; \ + row_ptr += stride * 4; \ + } \ + total_blocks--; \ + } -static void rpza_decode_stream(RpzaContext *s) +static int rpza_decode_stream(RpzaContext *s) { int width = s->avctx->width; int stride = s->frame->linesize[0] / 2; @@ -90,7 +92,7 @@ static void rpza_decode_stream(RpzaContext *s) av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1\n", bytestream2_peek_byte(&s->gb)); - /* Get chunk size, ingnoring first byte */ + /* Get chunk size, ignoring first byte */ chunk_size = bytestream2_get_be32(&s->gb) & 0x00FFFFFF; /* If length mismatch use size from MOV file and try to decode anyway */ @@ -126,7 +128,8 @@ static void rpza_decode_stream(RpzaContext *s) /* Skip blocks */ case 0x80: while (n_blocks--) { - ADVANCE_BLOCK(); + CHECK_BLOCK(); + ADVANCE_BLOCK(); } break; @@ -134,6 +137,7 @@ static void rpza_decode_stream(RpzaContext *s) case 0xa0: colorA = bytestream2_get_be16(&s->gb); while (n_blocks--) { + CHECK_BLOCK(); block_ptr = row_ptr + pixel_ptr; for (pixel_y = 0; pixel_y < 4; pixel_y++) { for (pixel_x = 0; pixel_x < 4; pixel_x++){ @@ -177,8 +181,9 @@ static void rpza_decode_stream(RpzaContext *s) color4[2] |= ((21 * ta + 11 * tb) >> 5); if (bytestream2_get_bytes_left(&s->gb) < n_blocks * 4) - return; + return AVERROR_INVALIDDATA; while (n_blocks--) { + CHECK_BLOCK(); block_ptr = row_ptr + pixel_ptr; for (pixel_y = 0; pixel_y < 4; pixel_y++) { uint8_t index = bytestream2_get_byteu(&s->gb); @@ -196,7 +201,8 @@ static void rpza_decode_stream(RpzaContext *s) /* Fill block with 16 colors */ case 0x00: if (bytestream2_get_bytes_left(&s->gb) < 30) - return; + return AVERROR_INVALIDDATA; + CHECK_BLOCK(); block_ptr = row_ptr + pixel_ptr; for (pixel_y = 0; pixel_y < 4; pixel_y++) { for (pixel_x = 0; pixel_x < 4; pixel_x++){ @@ -216,9 +222,11 @@ static void rpza_decode_stream(RpzaContext *s) av_log(s->avctx, AV_LOG_ERROR, "Unknown opcode %d in rpza chunk." " Skip remaining %d bytes of chunk data.\n", opcode, bytestream2_get_bytes_left(&s->gb)); - return; + return AVERROR_INVALIDDATA; } /* Opcode switch */ } + + return 0; } static av_cold int rpza_decode_init(AVCodecContext *avctx) @@ -249,7 +257,9 @@ static int rpza_decode_frame(AVCodecContext *avctx, return ret; } - rpza_decode_stream(s); + ret = rpza_decode_stream(s); + if (ret < 0) + return ret; if ((ret = av_frame_ref(data, s->frame)) < 0) return ret; @@ -278,5 +288,5 @@ AVCodec ff_rpza_decoder = { .init = rpza_decode_init, .close = rpza_decode_end, .decode = rpza_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c new file mode 100644 index 0000000..4a91783 --- /dev/null +++ b/libavcodec/rscc.c @@ -0,0 +1,313 @@ +/* + * innoHeim/Rsupport Screen Capture Codec + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * innoHeim/Rsupport Screen Capture Codec decoder + * + * Fourcc: ISCC, RSCC + * + * Lossless codec, data stored in tiles, with optional deflate compression. + * + * Header contains the number of tiles in a frame with the tile coordinates, + * and it can be deflated or not. Similarly, pixel data comes after the header + * and a variable size value, and it can be deflated or just raw. + * + * Supports: BGRA, BGR24, RGB555, RGB8 + */ + +#include +#include +#include + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define TILE_SIZE 8 + +typedef struct Tile { + int x, y; + int w, h; +} Tile; + +typedef struct RsccContext { + GetByteContext gbc; + AVFrame *reference; + Tile *tiles; + unsigned int tiles_size; + int component_size; + + /* zlib interaction */ + uint8_t *inflated_buf; + uLongf inflated_size; +} RsccContext; + +static av_cold int rscc_init(AVCodecContext *avctx) +{ + RsccContext *ctx = avctx->priv_data; + + /* These needs to be set to estimate uncompressed buffer */ + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + /* Allocate reference frame */ + ctx->reference = av_frame_alloc(); + if (!ctx->reference) + return AVERROR(ENOMEM); + + /* Get pixel format and the size of the pixel */ + if (avctx->codec_tag == MKTAG('I', 'S', 'C', 'C')) { + avctx->pix_fmt = AV_PIX_FMT_BGRA; + ctx->component_size = 4; + } else if (avctx->codec_tag == MKTAG('R', 'S', 'C', 'C')) { + ctx->component_size = avctx->bits_per_coded_sample / 8; + switch (avctx->bits_per_coded_sample) { + case 8: + avpriv_report_missing_feature(avctx, "8 bits per pixel"); + return AVERROR_PATCHWELCOME; + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 32: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n", + avctx->bits_per_coded_sample); + return AVERROR_INVALIDDATA; + } + } else { + av_log(avctx, AV_LOG_ERROR, "Invalid codec tag\n"); + return AVERROR_INVALIDDATA; + } + + /* Store the value to check for keyframes */ + ctx->inflated_size = avctx->width * avctx->height * ctx->component_size; + + /* Allocate maximum size possible, a full frame */ + ctx->inflated_buf = av_malloc(ctx->inflated_size); + if (!ctx->inflated_buf) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int rscc_close(AVCodecContext *avctx) +{ + RsccContext *ctx = avctx->priv_data; + + av_freep(&ctx->tiles); + av_freep(&ctx->inflated_buf); + av_frame_free(&ctx->reference); + + return 0; +} + +static int rscc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + RsccContext *ctx = avctx->priv_data; + GetByteContext *gbc = &ctx->gbc; + GetByteContext tiles_gbc; + AVFrame *frame = data; + const uint8_t *pixels, *raw; + uint8_t *inflated_tiles = NULL; + int tiles_nb, packed_size, pixel_size = 0; + int i, ret = 0; + + bytestream2_init(gbc, avpkt->data, avpkt->size); + + /* Size check */ + if (bytestream2_get_bytes_left(gbc) < 12) { + av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + /* Read number of tiles, and allocate the array */ + tiles_nb = bytestream2_get_le16(gbc); + av_fast_malloc(&ctx->tiles, &ctx->tiles_size, + tiles_nb * sizeof(*ctx->tiles)); + if (!ctx->tiles) { + ret = AVERROR(ENOMEM); + goto end; + } + + av_log(avctx, AV_LOG_DEBUG, "Frame with %d tiles.\n", tiles_nb); + + /* When there are more than 5 tiles, they are packed together with + * a size header. When that size does not match the number of tiles + * times the tile size, it means it needs to be inflated as well */ + if (tiles_nb > 5) { + uLongf packed_tiles_size; + + if (tiles_nb < 32) + packed_tiles_size = bytestream2_get_byte(gbc); + else + packed_tiles_size = bytestream2_get_le16(gbc); + + ff_dlog(avctx, "packed tiles of size %lu.\n", packed_tiles_size); + + /* If necessary, uncompress tiles, and hijack the bytestream reader */ + if (packed_tiles_size != tiles_nb * TILE_SIZE) { + uLongf length = tiles_nb * TILE_SIZE; + inflated_tiles = av_malloc(length); + if (!inflated_tiles) { + ret = AVERROR(ENOMEM); + goto end; + } + + ret = uncompress(inflated_tiles, &length, + gbc->buffer, packed_tiles_size); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Tile deflate error %d.\n", ret); + ret = AVERROR_UNKNOWN; + goto end; + } + + /* Skip the compressed tile section in the main byte reader, + * and point it to read the newly uncompressed data */ + bytestream2_skip(gbc, packed_tiles_size); + bytestream2_init(&tiles_gbc, inflated_tiles, length); + gbc = &tiles_gbc; + } + } + + /* Fill in array of tiles, keeping track of how many pixels are updated */ + for (i = 0; i < tiles_nb; i++) { + ctx->tiles[i].x = bytestream2_get_le16(gbc); + ctx->tiles[i].w = bytestream2_get_le16(gbc); + ctx->tiles[i].y = bytestream2_get_le16(gbc); + ctx->tiles[i].h = bytestream2_get_le16(gbc); + + pixel_size += ctx->tiles[i].w * ctx->tiles[i].h * ctx->component_size; + + ff_dlog(avctx, "tile %d orig(%d,%d) %dx%d.\n", i, + ctx->tiles[i].x, ctx->tiles[i].y, + ctx->tiles[i].w, ctx->tiles[i].h); + + if (ctx->tiles[i].w == 0 || ctx->tiles[i].h == 0) { + av_log(avctx, AV_LOG_ERROR, + "invalid tile %d at (%d.%d) with size %dx%d.\n", i, + ctx->tiles[i].x, ctx->tiles[i].y, + ctx->tiles[i].w, ctx->tiles[i].h); + ret = AVERROR_INVALIDDATA; + goto end; + } else if (ctx->tiles[i].x + ctx->tiles[i].w > avctx->width || + ctx->tiles[i].y + ctx->tiles[i].h > avctx->height) { + av_log(avctx, AV_LOG_ERROR, + "out of bounds tile %d at (%d.%d) with size %dx%d.\n", i, + ctx->tiles[i].x, ctx->tiles[i].y, + ctx->tiles[i].w, ctx->tiles[i].h); + ret = AVERROR_INVALIDDATA; + goto end; + } + } + + /* Reset the reader in case it had been modified before */ + gbc = &ctx->gbc; + + /* Extract how much pixel data the tiles contain */ + if (pixel_size < 0x100) + packed_size = bytestream2_get_byte(gbc); + else if (pixel_size < 0x10000) + packed_size = bytestream2_get_le16(gbc); + else if (pixel_size < 0x1000000) + packed_size = bytestream2_get_le24(gbc); + else + packed_size = bytestream2_get_le32(gbc); + + ff_dlog(avctx, "pixel_size %d packed_size %d.\n", pixel_size, packed_size); + + /* Get pixels buffer, it may be deflated or just raw */ + if (pixel_size == packed_size) { + pixels = gbc->buffer; + } else { + uLongf len = ctx->inflated_size; + ret = uncompress(ctx->inflated_buf, &len, gbc->buffer, packed_size); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Pixel deflate error %d.\n", ret); + ret = AVERROR_UNKNOWN; + goto end; + } + pixels = ctx->inflated_buf; + } + + /* Allocate when needed */ + ret = ff_reget_buffer(avctx, ctx->reference); + if (ret < 0) + goto end; + + /* Pointer to actual pixels, will be updated when data is consumed */ + raw = pixels; + for (i = 0; i < tiles_nb; i++) { + uint8_t *dst = ctx->reference->data[0] + ctx->reference->linesize[0] * + (avctx->height - ctx->tiles[i].y - 1) + + ctx->tiles[i].x * ctx->component_size; + av_image_copy_plane(dst, -1 * ctx->reference->linesize[0], + raw, ctx->tiles[i].w * ctx->component_size, + ctx->tiles[i].w * ctx->component_size, + ctx->tiles[i].h); + raw += ctx->tiles[i].w * ctx->component_size * ctx->tiles[i].h; + } + + /* Frame is ready to be output */ + ret = av_frame_ref(frame, ctx->reference); + if (ret < 0) + goto end; + + /* Keyframe when the number of pixels updated matches the whole surface */ + if (pixel_size == ctx->inflated_size) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + } + *got_frame = 1; + +end: + av_free(inflated_tiles); + return ret; +} + +AVCodec ff_rscc_decoder = { + .name = "rscc", + .long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RSCC, + .init = rscc_init, + .decode = rscc_decode_frame, + .close = rscc_close, + .priv_data_size = sizeof(RsccContext), + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index e5b76f0..3b5f4df 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -32,10 +32,14 @@ #include "avcodec.h" #include "error_resilience.h" #include "h263.h" +#include "h263data.h" #include "internal.h" #include "mpeg_er.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "mpeg4video.h" +#include "mpegvideodata.h" +#include "rv10.h" #define RV_GET_MAJOR_VER(x) ((x) >> 28) #define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) @@ -258,10 +262,10 @@ static int rv10_decode_picture_header(MpegEncContext *s) pb_frame = get_bits1(&s->gb); - av_dlog(s->avctx, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame); + ff_dlog(s->avctx, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame); if (pb_frame) { - avpriv_request_sample(s->avctx, "pb frame"); + avpriv_request_sample(s->avctx, "PB-frame"); return AVERROR_PATCHWELCOME; } @@ -277,7 +281,7 @@ static int rv10_decode_picture_header(MpegEncContext *s) s->last_dc[0] = get_bits(&s->gb, 8); s->last_dc[1] = get_bits(&s->gb, 8); s->last_dc[2] = get_bits(&s->gb, 8); - av_dlog(s->avctx, "DC:%d %d %d\n", s->last_dc[0], + ff_dlog(s->avctx, "DC:%d %d %d\n", s->last_dc[0], s->last_dc[1], s->last_dc[2]); } } @@ -409,7 +413,7 @@ static int rv20_decode_picture_header(RVDecContext *rv) 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"); + "from seeking? skipping current B-frame\n"); return FRAME_SKIPPED; } ff_mpeg4_init_direct_mv(s); @@ -574,7 +578,7 @@ static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf, } } - av_dlog(avctx, "qscale=%d\n", s->qscale); + ff_dlog(avctx, "qscale=%d\n", s->qscale); /* default quantization values */ if (s->codec_id == AV_CODEC_ID_RV10) { @@ -614,7 +618,7 @@ static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf, for (s->mb_num_left = mb_count; s->mb_num_left > 0; s->mb_num_left--) { int ret; ff_update_block_index(s); - av_dlog(avctx, "**mb x=%d y=%d\n", s->mb_x, s->mb_y); + ff_dlog(avctx, "**mb x=%d y=%d\n", s->mb_x, s->mb_y); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; @@ -686,7 +690,7 @@ static int rv10_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int slice_count; const uint8_t *slices_hdr = NULL; - av_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); /* no supplementary picture */ if (buf_size == 0) { @@ -771,7 +775,7 @@ AVCodec ff_rv10_decoder = { .init = rv10_decode_init, .close = rv10_decode_end, .decode = rv10_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE @@ -787,7 +791,7 @@ AVCodec ff_rv20_decoder = { .init = rv10_decode_init, .close = rv10_decode_end, .decode = rv10_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .flush = ff_mpeg_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, diff --git a/libavcodec/rv10.h b/libavcodec/rv10.h new file mode 100644 index 0000000..b44bc1f --- /dev/null +++ b/libavcodec/rv10.h @@ -0,0 +1,33 @@ +/* + * RV10/RV20 decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_RV10_H +#define AVCODEC_RV10_H + +#include + +#include "mpegvideo.h" + +int ff_rv_decode_dc(MpegEncContext *s, int n); + +int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number); + +#endif /* AVCODEC_RV10_H */ diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index 2eca9c3..765c57d 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -27,6 +27,7 @@ #include "mpegvideo.h" #include "put_bits.h" +#include "rv10.h" int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) { @@ -38,7 +39,7 @@ int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) put_bits(&s->pb, 1, (s->pict_type == AV_PICTURE_TYPE_P)); - put_bits(&s->pb, 1, 0); /* not PB frame */ + put_bits(&s->pb, 1, 0); /* not PB-mframe */ put_bits(&s->pb, 5, s->qscale); @@ -62,7 +63,12 @@ int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) return 0; } -FF_MPV_GENERIC_CLASS(rv10) +static const AVClass rv10_class = { + .class_name = "rv10 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_rv10_encoder = { .name = "rv10", diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index 4462bde..20090b1 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -26,8 +26,11 @@ */ #include "mpegvideo.h" +#include "mpegvideodata.h" #include "h263.h" +#include "h263data.h" #include "put_bits.h" +#include "rv10.h" void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? @@ -57,7 +60,12 @@ void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ } } -FF_MPV_GENERIC_CLASS(rv20) +static const AVClass rv20_class = { + .class_name = "rv20 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_rv20_encoder = { .name = "rv20", diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c index 1675ea2..7218fa3 100644 --- a/libavcodec/rv30.c +++ b/libavcodec/rv30.c @@ -81,7 +81,7 @@ static int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){ for(j = 0; j < 4; j+= 2){ - unsigned code = svq3_get_ue_golomb(gb) << 1; + unsigned code = get_interleaved_ue_golomb(gb) << 1; if(code >= 81*2){ av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n"); return -1; @@ -109,7 +109,7 @@ static int rv30_decode_mb_info(RV34DecContext *r) static const int rv30_b_types[6] = { RV34_MB_SKIP, RV34_MB_B_DIRECT, RV34_MB_B_FORWARD, RV34_MB_B_BACKWARD, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 }; MpegEncContext *s = &r->s; GetBitContext *gb = &s->gb; - unsigned code = svq3_get_ue_golomb(gb); + unsigned code = get_interleaved_ue_golomb(gb); if (code > 11) { av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n"); @@ -282,8 +282,8 @@ AVCodec ff_rv30_decoder = { .init = rv30_decode_init, .close = ff_rv34_decode_end, .decode = ff_rv34_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, diff --git a/libavcodec/rv30data.h b/libavcodec/rv30data.h index 5ee3048..079204d 100644 --- a/libavcodec/rv30data.h +++ b/libavcodec/rv30data.h @@ -58,7 +58,7 @@ static const uint8_t rv30_itype_code[9*9*2] = { * * This is really a three-dimensional matrix with dimensions * [-1..9][-1..9][0..9]. The first and second coordinates are - * detemined by the top and left neighbors (-1 if unavailable). + * determined by the top and left neighbors (-1 if unavailable). */ static const uint8_t rv30_itype_from_context[900] = { 0, 9, 9, 9, 9, 9, 9, 9, 9, diff --git a/libavcodec/rv30dsp.c b/libavcodec/rv30dsp.c index 36187a7..50f4186 100644 --- a/libavcodec/rv30dsp.c +++ b/libavcodec/rv30dsp.c @@ -31,7 +31,7 @@ #include "rv34dsp.h" #define RV30_LOWPASS(OPNAME, OP) \ -static av_unused void OPNAME ## rv30_tpel8_h_lowpass(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ +static void OPNAME ## rv30_tpel8_h_lowpass(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ const int h = 8;\ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index 4ed2a33..4220195 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -215,7 +215,7 @@ static int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table) } /** - * Get one coefficient value from the bistream and store it. + * Get one coefficient value from the bitstream and store it. */ static inline void decode_coeff(int16_t *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q) { @@ -723,14 +723,14 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, if(s->h_edge_pos - (width << 3) < 6 || s->v_edge_pos - (height << 3) < 6 || (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 || (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4) { - uint8_t *uvbuf = s->edge_emu_buffer + 22 * s->linesize; + uint8_t *uvbuf = s->sc.edge_emu_buffer + 22 * s->linesize; srcY -= 2 + 2*s->linesize; - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, s->linesize, s->linesize, (width << 3) + 6, (height << 3) + 6, src_x - 2, src_y - 2, s->h_edge_pos, s->v_edge_pos); - srcY = s->edge_emu_buffer + 2 + 2*s->linesize; + srcY = s->sc.edge_emu_buffer + 2 + 2*s->linesize; s->vdsp.emulated_edge_mc(uvbuf, srcU, s->uvlinesize,s->uvlinesize, (width << 2) + 1, (height << 2) + 1, @@ -854,8 +854,8 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type) memset(r->dmv, 0, sizeof(r->dmv)); for(i = 0; i < num_mvs[block_type]; i++){ - r->dmv[i][0] = svq3_get_se_golomb(gb); - r->dmv[i][1] = svq3_get_se_golomb(gb); + r->dmv[i][0] = get_interleaved_se_golomb(gb); + r->dmv[i][1] = get_interleaved_se_golomb(gb); } switch(block_type){ case RV34_MB_TYPE_INTRA: @@ -1464,7 +1464,7 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int return s->mb_y == s->mb_height; } -/** @} */ // recons group end +/** @} */ // reconstruction group end /** * Initialize decoder. @@ -1555,16 +1555,18 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte return err; } - if ((err = ff_mpeg_update_thread_context(dst, src))) - return err; - r->cur_pts = r1->cur_pts; r->last_pts = r1->last_pts; r->next_pts = r1->next_pts; memset(&r->si, 0, sizeof(r->si)); - return 0; + // Do no call ff_mpeg_update_thread_context on a partially initialized + // decoder context. + if (!s1->linesize) + return 0; + + return ff_mpeg_update_thread_context(dst, src); } static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) diff --git a/libavcodec/rv34.h b/libavcodec/rv34.h index c32c089..0ac24bf 100644 --- a/libavcodec/rv34.h +++ b/libavcodec/rv34.h @@ -101,12 +101,12 @@ typedef struct RV34DecContext{ int is16; ///< current block has additional 16x16 specific features or not int dmv[4][2]; ///< differential motion vectors for the current macroblock - int rv30; ///< indicates which RV variasnt is currently decoded + int rv30; ///< indicates which RV variant is currently decoded int rpr; ///< one field size in RV30 slice header int cur_pts, last_pts, next_pts; int scaled_weight; - int weight1, weight2; ///< B frame distance fractions (0.14) used in motion compensation + int weight1, weight2; ///< B-frame distance fractions (0.14) used in motion compensation int mv_weight1, mv_weight2; uint16_t *cbp_luma; ///< CBP values for luma subblocks diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c index 8af7443..ec6d3a5 100644 --- a/libavcodec/rv34_parser.c +++ b/libavcodec/rv34_parser.c @@ -27,7 +27,7 @@ #include "parser.h" #include "libavutil/intreadwrite.h" -typedef struct { +typedef struct RV34ParseContext { ParseContext pc; int64_t key_dts; int key_pts; diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c index b7e113c..0da1312 100644 --- a/libavcodec/rv40.c +++ b/libavcodec/rv40.c @@ -130,22 +130,23 @@ static int rv40_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceIn int mb_bits; int w = r->s.width, h = r->s.height; int mb_size; + int ret; memset(si, 0, sizeof(SliceInfo)); if(get_bits1(gb)) - return -1; + return AVERROR_INVALIDDATA; si->type = get_bits(gb, 2); if(si->type == 1) si->type = 0; si->quant = get_bits(gb, 5); if(get_bits(gb, 2)) - return -1; + return AVERROR_INVALIDDATA; si->vlc_set = get_bits(gb, 2); skip_bits1(gb); si->pts = get_bits(gb, 13); if(!si->type || !get_bits1(gb)) rv40_parse_picture_size(gb, &w, &h); - if(av_image_check_size(w, h, 0, r->s.avctx) < 0) - return -1; + if ((ret = av_image_check_size(w, h, 0, r->s.avctx)) < 0) + return ret; si->width = w; si->height = h; mb_size = ((w + 15) >> 4) * ((h + 15) >> 4); @@ -230,7 +231,7 @@ static int rv40_decode_mb_info(RV34DecContext *r) int mb_pos = s->mb_x + s->mb_y * s->mb_stride; if(!r->s.mb_skip_run) - r->s.mb_skip_run = svq3_get_ue_golomb(gb) + 1; + r->s.mb_skip_run = get_interleaved_ue_golomb(gb) + 1; if(--r->s.mb_skip_run) return RV34_MB_SKIP; @@ -570,8 +571,8 @@ AVCodec ff_rv40_decoder = { .init = rv40_decode_init, .close = ff_rv34_decode_end, .decode = ff_rv34_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, diff --git a/libavcodec/rv40dsp.c b/libavcodec/rv40dsp.c index d1643e0..da3efb4 100644 --- a/libavcodec/rv40dsp.c +++ b/libavcodec/rv40dsp.c @@ -34,7 +34,7 @@ #include "rv34dsp.h" #define RV40_LOWPASS(OPNAME, OP) \ -static av_unused void OPNAME ## rv40_qpel8_h_lowpass(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride,\ +static void OPNAME ## rv40_qpel8_h_lowpass(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride,\ const int h, const int C1, const int C2, const int SHIFT){\ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;\ int i;\ diff --git a/libavcodec/s302m.c b/libavcodec/s302m.c index 36384fb..635f697 100644 --- a/libavcodec/s302m.c +++ b/libavcodec/s302m.c @@ -146,5 +146,5 @@ AVCodec ff_s302m_decoder = { .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_S302M, .decode = s302m_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/s3tc.c b/libavcodec/s3tc.c deleted file mode 100644 index d35cf2a..0000000 --- a/libavcodec/s3tc.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * S3 Texture Compression (S3TC) decoding functions - * Copyright (c) 2007 by Ivo van Poorten - * - * see also: http://wiki.multimedia.cx/index.php?title=S3TC - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "avcodec.h" -#include "bytestream.h" -#include "s3tc.h" - -static inline void dxt1_decode_pixels(GetByteContext *gb, uint32_t *d, - unsigned int qstride, unsigned int flag, - uint64_t alpha) { - unsigned int x, y, c0, c1, a = (!flag * 255u) << 24; - unsigned int rb0, rb1, rb2, rb3, g0, g1, g2, g3; - uint32_t colors[4], pixels; - - c0 = bytestream2_get_le16(gb); - c1 = bytestream2_get_le16(gb); - - rb0 = (c0<<3 | c0<<8) & 0xf800f8; - rb1 = (c1<<3 | c1<<8) & 0xf800f8; - rb0 += (rb0>>5) & 0x070007; - rb1 += (rb1>>5) & 0x070007; - g0 = (c0 <<5) & 0x00fc00; - g1 = (c1 <<5) & 0x00fc00; - g0 += (g0 >>6) & 0x000300; - g1 += (g1 >>6) & 0x000300; - - colors[0] = rb0 + g0 + a; - colors[1] = rb1 + g1 + a; - - if (c0 > c1 || flag) { - rb2 = (((2*rb0+rb1) * 21) >> 6) & 0xff00ff; - rb3 = (((2*rb1+rb0) * 21) >> 6) & 0xff00ff; - g2 = (((2*g0 +g1 ) * 21) >> 6) & 0x00ff00; - g3 = (((2*g1 +g0 ) * 21) >> 6) & 0x00ff00; - colors[3] = rb3 + g3 + a; - } else { - rb2 = ((rb0+rb1) >> 1) & 0xff00ff; - g2 = ((g0 +g1 ) >> 1) & 0x00ff00; - colors[3] = 0; - } - - colors[2] = rb2 + g2 + a; - - pixels = bytestream2_get_le32(gb); - for (y=0; y<4; y++) { - for (x=0; x<4; x++) { - a = (alpha & 0x0f) << 28; - a += a >> 4; - d[x] = a + colors[pixels&3]; - pixels >>= 2; - alpha >>= 4; - } - d += qstride; - } -} - -void ff_decode_dxt1(GetByteContext *gb, uint8_t *dst, - const unsigned int w, const unsigned int h, - const unsigned int stride) { - unsigned int bx, by, qstride = stride/4; - uint32_t *d = (uint32_t *) dst; - - for (by=0; by < h/4; by++, d += stride-w) - for (bx = 0; bx < w / 4; bx++, d += 4) - dxt1_decode_pixels(gb, d, qstride, 0, 0LL); -} - -void ff_decode_dxt3(GetByteContext *gb, uint8_t *dst, - const unsigned int w, const unsigned int h, - const unsigned int stride) { - unsigned int bx, by, qstride = stride/4; - uint32_t *d = (uint32_t *) dst; - - for (by=0; by < h/4; by++, d += stride-w) - for (bx = 0; bx < w / 4; bx++, d += 4) - dxt1_decode_pixels(gb, d, qstride, 1, bytestream2_get_le64(gb)); -} diff --git a/libavcodec/s3tc.h b/libavcodec/s3tc.h deleted file mode 100644 index 25237b9..0000000 --- a/libavcodec/s3tc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * S3 Texture Compression (S3TC) decoding functions - * Copyright (c) 2007 by Ivo van Poorten - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_S3TC_H -#define AVCODEC_S3TC_H - -#include - -#include "bytestream.h" - -#define FF_S3TC_DXT1 0x31545844 -#define FF_S3TC_DXT3 0x33545844 - -/** - * Decode DXT1 encoded data to RGB32 - * @param gb GetByteContext - * @param dst destination buffer - * @param w width of output image - * @param h height of output image - * @param stride line size of output image - */ -void ff_decode_dxt1(GetByteContext *gb, uint8_t *dst, - const unsigned int w, const unsigned int h, - const unsigned int stride); -/** - * Decode DXT3 encoded data to RGB32 - * @param gb GetByteContext - * @param dst destination buffer - * @param w width of output image - * @param h height of output image - * @param stride line size of output image - */ -void ff_decode_dxt3(GetByteContext *gb, uint8_t *dst, - const unsigned int w, const unsigned int h, - const unsigned int stride); - -#endif /* AVCODEC_S3TC_H */ diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 41c6551..6436f84 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1473,5 +1473,5 @@ AVCodec ff_sanm_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c index b7917dc..0294332 100644 --- a/libavcodec/sbrdsp.c +++ b/libavcodec/sbrdsp.c @@ -168,8 +168,8 @@ static void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2]) phi[2 - 1][1][1] = imag_sum1 + x[ 0][0] * x[ 1][1] - x[ 0][1] * x[ 1][0]; phi[0 ][0][0] = real_sum1 + x[38][0] * x[39][0] + x[38][1] * x[39][1]; phi[0 ][0][1] = imag_sum1 + x[38][0] * x[39][1] - x[38][1] * x[39][0]; -#endif } +#endif static void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2], const float alpha0[2], const float alpha1[2], diff --git a/libavcodec/screenpresso.c b/libavcodec/screenpresso.c new file mode 100644 index 0000000..eae0ae7 --- /dev/null +++ b/libavcodec/screenpresso.c @@ -0,0 +1,197 @@ +/* + * Screenpresso decoder + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Screenpresso decoder + * + * Fourcc: SPV1 + * + * Screenpresso simply horizontally flips and then deflates frames, + * alternating full pictures and deltas. Deltas are related to the currently + * rebuilt frame (not the reference), and since there is no coordinate system + * they contain exactly as many pixel as the keyframe. + * + * Supports: BGRA, BGR24, RGB555 + */ + +#include +#include +#include + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "internal.h" + +typedef struct ScreenpressoContext { + AVFrame *current; + + /* zlib interaction */ + uint8_t *inflated_buf; + uLongf inflated_size; +} ScreenpressoContext; + +static av_cold int screenpresso_close(AVCodecContext *avctx) +{ + ScreenpressoContext *ctx = avctx->priv_data; + + av_frame_free(&ctx->current); + av_freep(&ctx->inflated_buf); + + return 0; +} + +static av_cold int screenpresso_init(AVCodecContext *avctx) +{ + ScreenpressoContext *ctx = avctx->priv_data; + + /* These needs to be set to estimate uncompressed buffer */ + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + /* Allocate current frame */ + ctx->current = av_frame_alloc(); + if (!ctx->current) + return AVERROR(ENOMEM); + + /* Allocate maximum size possible, a full RGBA frame */ + ctx->inflated_size = avctx->width * avctx->height * 4; + ctx->inflated_buf = av_malloc(ctx->inflated_size); + if (!ctx->inflated_buf) + return AVERROR(ENOMEM); + + return 0; +} + +static void sum_delta_flipped(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height) +{ + int i; + for (; height > 0; height--) { + for (i = 0; i < bytewidth; i++) + dst[i] += src[(height - 1) * src_linesize + i]; + dst += dst_linesize; + } +} + +static int screenpresso_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + ScreenpressoContext *ctx = avctx->priv_data; + AVFrame *frame = data; + uLongf length = ctx->inflated_size; + int keyframe, component_size, src_linesize; + int ret; + + /* Size check */ + if (avpkt->size < 3) { + av_log(avctx, AV_LOG_ERROR, "Packet too small (%d)\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + /* Compression level (4 bits) and keyframe information (1 bit) */ + av_log(avctx, AV_LOG_DEBUG, "Compression level %d\n", avpkt->data[0] >> 4); + keyframe = avpkt->data[0] & 1; + + /* Pixel size */ + component_size = ((avpkt->data[1] >> 2) & 0x03) + 1; + switch (component_size) { + case 2: + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + break; + case 3: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 4: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n", + component_size); + return AVERROR_INVALIDDATA; + } + + /* Inflate the frame after the 2 byte header */ + ret = uncompress(ctx->inflated_buf, &length, + avpkt->data + 2, avpkt->size - 2); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret); + return AVERROR_UNKNOWN; + } + + ret = ff_reget_buffer(avctx, ctx->current); + if (ret < 0) + return ret; + + /* Codec has aligned strides */ + src_linesize = FFALIGN(avctx->width * component_size, 4); + + /* When a keyframe is found, copy it (flipped) */ + if (keyframe) + av_image_copy_plane(ctx->current->data[0] + + ctx->current->linesize[0] * (avctx->height - 1), + -1 * ctx->current->linesize[0], + ctx->inflated_buf, src_linesize, + avctx->width * component_size, avctx->height); + /* Otherwise sum the delta on top of the current frame */ + else + sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0], + ctx->inflated_buf, src_linesize, + avctx->width * component_size, avctx->height); + + /* Frame is ready to be output */ + ret = av_frame_ref(frame, ctx->current); + if (ret < 0) + return ret; + + /* Usual properties */ + if (keyframe) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + } + *got_frame = 1; + + return 0; +} + +AVCodec ff_screenpresso_decoder = { + .name = "screenpresso", + .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SCREENPRESSO, + .init = screenpresso_init, + .decode = screenpresso_decode_frame, + .close = screenpresso_close, + .priv_data_size = sizeof(ScreenpressoContext), + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index ebca2e8..6f93a30 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -229,13 +229,13 @@ static int decode_frame(AVCodecContext *avctx, if (s->bytes_per_channel != 1 && s->bytes_per_channel != 2) { av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); - return -1; + return AVERROR(EINVAL); } /* Check for supported image dimensions. */ if (dimension != 2 && dimension != 3) { av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); - return -1; + return AVERROR(EINVAL); } if (s->depth == SGI_GRAYSCALE) { @@ -246,16 +246,17 @@ static int decode_frame(AVCodecContext *avctx, avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); - return -1; + return AVERROR(EINVAL); } ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; - if (ff_get_buffer(avctx, p, 0) < 0) { + ret = ff_get_buffer(avctx, p, 0); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); - return -1; + return ret; } p->pict_type = AV_PICTURE_TYPE_I; @@ -299,5 +300,5 @@ AVCodec ff_sgi_decoder = { .priv_data_size = sizeof(SgiState), .decode = decode_frame, .init = sgi_decode_init, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index bfc0995..07e224c 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -28,6 +30,12 @@ #define SGI_SINGLE_CHAN 2 #define SGI_MULTI_CHAN 3 +typedef struct SgiContext { + AVClass *class; + + int rle; +} SgiContext; + static av_cold int encode_init(AVCodecContext *avctx) { if (avctx->width > 65535 || avctx->height > 65535) { @@ -36,25 +44,74 @@ static av_cold int encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - return 0; } +static int sgi_rle_encode(PutByteContext *pbc, const uint8_t *src, + int w, int bpp) +{ + int val, count, x, start = bytestream2_tell_p(pbc); + void (*bytestream2_put)(PutByteContext *, unsigned int); + + if (bpp == 1) + bytestream2_put = bytestream2_put_byte; + else + bytestream2_put = bytestream2_put_be16; + + for (x = 0; x < w; x += count) { + /* see if we can encode the next set of pixels with RLE */ + count = ff_rle_count_pixels(src, w - x, bpp, 1); + if (count > 1) { + if (bytestream2_get_bytes_left_p(pbc) < bpp * 2) + return AVERROR_INVALIDDATA; + + val = bpp == 1 ? *src : AV_RB16(src); + bytestream2_put(pbc, count); + bytestream2_put(pbc, val); + } else { + int i; + /* fall back on uncompressed */ + count = ff_rle_count_pixels(src, w - x, bpp, 0); + if (bytestream2_get_bytes_left_p(pbc) < bpp * (count + 1)) + return AVERROR_INVALIDDATA; + + bytestream2_put(pbc, count + 0x80); + for (i = 0; i < count; i++) { + val = bpp == 1 ? src[i] : AV_RB16(src + i * bpp); + bytestream2_put(pbc, val); + } + } + + src += count * bpp; + } + + return bytestream2_tell_p(pbc) - start; +} + static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { + SgiContext *s = avctx->priv_data; const AVFrame * const p = frame; - uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; - int x, y, z, length, tablesize, ret; + PutByteContext pbc; + uint8_t *in_buf, *encode_buf; + int x, y, z, length, tablesize, ret, i; unsigned int width, height, depth, dimension; unsigned int bytes_per_channel, pixmax, put_be; - unsigned char *end_buf; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type == FF_CODER_TYPE_RAW) + s->rle = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif width = avctx->width; height = avctx->height; @@ -78,7 +135,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_GRAY16LE: put_be = !HAVE_BIGENDIAN; case AV_PIX_FMT_GRAY16BE: - avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_SINGLE_CHAN; @@ -87,7 +143,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_RGB48LE: put_be = !HAVE_BIGENDIAN; case AV_PIX_FMT_RGB48BE: - avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_MULTI_CHAN; @@ -96,7 +151,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_RGBA64LE: put_be = !HAVE_BIGENDIAN; case AV_PIX_FMT_RGBA64BE: - avctx->coder_type = FF_CODER_TYPE_RAW; bytes_per_channel = 2; pixmax = 0xFFFF; dimension = SGI_MULTI_CHAN; @@ -108,71 +162,74 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, tablesize = depth * height * 4; length = SGI_HEADER_SIZE; - if (avctx->coder_type == FF_CODER_TYPE_RAW) + if (!s->rle) length += depth * height * width; - else // assume ff_rl_encode() produces at most 2x size of input + else // assume sgi_rle_encode() produces at most 2x size of input length += tablesize * 2 + depth * height * (2 * width + 1); if ((ret = ff_alloc_packet(pkt, bytes_per_channel * length)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", length); return ret; } - buf = pkt->data; - end_buf = pkt->data + pkt->size; + + bytestream2_init_writer(&pbc, pkt->data, pkt->size); /* Encode header. */ - bytestream_put_be16(&buf, SGI_MAGIC); - bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/ - bytestream_put_byte(&buf, bytes_per_channel); - bytestream_put_be16(&buf, dimension); - bytestream_put_be16(&buf, width); - bytestream_put_be16(&buf, height); - bytestream_put_be16(&buf, depth); - - bytestream_put_be32(&buf, 0L); /* pixmin */ - bytestream_put_be32(&buf, pixmax); - bytestream_put_be32(&buf, 0L); /* dummy */ + bytestream2_put_be16(&pbc, SGI_MAGIC); + bytestream2_put_byte(&pbc, s->rle); /* RLE 1 - VERBATIM 0 */ + bytestream2_put_byte(&pbc, bytes_per_channel); + bytestream2_put_be16(&pbc, dimension); + bytestream2_put_be16(&pbc, width); + bytestream2_put_be16(&pbc, height); + bytestream2_put_be16(&pbc, depth); + + bytestream2_put_be32(&pbc, 0L); /* pixmin */ + bytestream2_put_be32(&pbc, pixmax); + bytestream2_put_be32(&pbc, 0L); /* dummy */ /* name */ - memset(buf, 0, SGI_HEADER_SIZE); - buf += 80; + for (i = 0; i < 80; i++) + bytestream2_put_byte(&pbc, 0L); /* colormap */ - bytestream_put_be32(&buf, 0L); + bytestream2_put_be32(&pbc, 0L); /* The rest of the 512 byte header is unused. */ - buf += 404; - offsettab = buf; + for (i = 0; i < 404; i++) + bytestream2_put_byte(&pbc, 0L); + + if (s->rle) { + PutByteContext taboff_pcb, tablen_pcb; - if (avctx->coder_type != FF_CODER_TYPE_RAW) { /* Skip RLE offset table. */ - buf += tablesize; - lengthtab = buf; + bytestream2_init_writer(&taboff_pcb, pbc.buffer, tablesize); + bytestream2_skip_p(&pbc, tablesize); /* Skip RLE length table. */ - buf += tablesize; + bytestream2_init_writer(&tablen_pcb, pbc.buffer, tablesize); + bytestream2_skip_p(&pbc, tablesize); /* Make an intermediate consecutive buffer. */ - if (!(encode_buf = av_malloc(width))) - return -1; + if (!(encode_buf = av_malloc(width * bytes_per_channel))) + return AVERROR(ENOMEM); for (z = 0; z < depth; z++) { - in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; + in_buf = p->data[0] + p->linesize[0] * (height - 1) + z * bytes_per_channel; for (y = 0; y < height; y++) { - bytestream_put_be32(&offsettab, buf - pkt->data); + bytestream2_put_be32(&taboff_pcb, bytestream2_tell_p(&pbc)); - for (x = 0; x < width; x++) + for (x = 0; x < width * bytes_per_channel; x += bytes_per_channel) encode_buf[x] = in_buf[depth * x]; - if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { + length = sgi_rle_encode(&pbc, encode_buf, width, + bytes_per_channel); + if (length < 1) { av_free(encode_buf); - return -1; + return AVERROR_INVALIDDATA; } - buf += length; - bytestream_put_byte(&buf, 0); - bytestream_put_be32(&lengthtab, length + 1); + bytestream2_put_be32(&tablen_pcb, length); in_buf -= p->linesize[0]; } } @@ -185,12 +242,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (y = 0; y < height; y++) { for (x = 0; x < width * depth; x += depth) if (bytes_per_channel == 1) - bytestream_put_byte(&buf, in_buf[x]); + bytestream2_put_byte(&pbc, in_buf[x]); else if (put_be) - bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]); + bytestream2_put_be16(&pbc, ((uint16_t *)in_buf)[x]); else - bytestream_put_le16(&buf, ((uint16_t *)in_buf)[x]); + bytestream2_put_le16(&pbc, ((uint16_t *)in_buf)[x]); in_buf -= p->linesize[0]; } @@ -198,27 +255,37 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* total length */ - pkt->size = buf - pkt->data; + pkt->size = bytestream2_tell_p(&pbc); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; } -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} +#define OFFSET(x) offsetof(SgiContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "rle", "Use run-length compression", OFFSET(rle), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + + { NULL }, +}; + +static const AVClass sgi_class = { + .class_name = "sgi", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_sgi_encoder = { .name = "sgi", .long_name = NULL_IF_CONFIG_SMALL("SGI image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SGI, + .priv_data_size = sizeof(SgiContext), + .priv_class = &sgi_class, .init = encode_init, .encode2 = encode_frame, - .close = encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE, diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c index d7bc5a9..f636bbc 100644 --- a/libavcodec/sgirledec.c +++ b/libavcodec/sgirledec.c @@ -31,17 +31,9 @@ #include "avcodec.h" #include "internal.h" -typedef struct SGIRLEContext { - AVFrame *frame; -} SGIRLEContext; - static av_cold int sgirle_decode_init(AVCodecContext *avctx) { - SGIRLEContext *s = avctx->priv_data; avctx->pix_fmt = AV_PIX_FMT_BGR8; - s->frame = av_frame_alloc(); - if (!s->frame) - return AVERROR(ENOMEM); return 0; } @@ -120,41 +112,31 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, static int sgirle_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - SGIRLEContext *s = avctx->priv_data; + AVFrame *frame = data; int ret; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size, - avctx->width, avctx->height, s->frame->linesize[0]); + ret = decode_sgirle8(avctx, frame->data[0], avpkt->data, avpkt->size, + avctx->width, avctx->height, frame->linesize[0]); if (ret < 0) return ret; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) - return ret; return avpkt->size; } -static av_cold int sgirle_decode_end(AVCodecContext *avctx) -{ - SGIRLEContext *s = avctx->priv_data; - - av_frame_free(&s->frame); - - return 0; -} - AVCodec ff_sgirle_decoder = { .name = "sgirle", .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SGIRLE, - .priv_data_size = sizeof(SGIRLEContext), .init = sgirle_decode_init, - .close = sgirle_decode_end, .decode = sgirle_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index c465fff..ee6dc70 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -23,7 +23,6 @@ * @file * Shorten decoder * @author Jeff Muizelaar - * */ #include @@ -431,7 +430,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data, void *tmp_ptr; s->max_framesize = 1024; // should hopefully be enough for the first header tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, - s->max_framesize + FF_INPUT_BUFFER_PADDING_SIZE); + s->max_framesize + AV_INPUT_BUFFER_PADDING_SIZE); if (!tmp_ptr) { av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n"); return AVERROR(ENOMEM); @@ -510,6 +509,8 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data, break; case FN_BITSHIFT: s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); + if (s->bitshift < 0) + return AVERROR_INVALIDDATA; break; case FN_BLOCKSIZE: { unsigned blocksize = get_uint(s, av_log2(s->blocksize)); @@ -656,7 +657,7 @@ AVCodec ff_shorten_decoder = { .init = shorten_decode_init, .close = shorten_decode_close, .decode = shorten_decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/simple_idct.c b/libavcodec/simple_idct.c index f61e9e6..6ee1320 100644 --- a/libavcodec/simple_idct.c +++ b/libavcodec/simple_idct.c @@ -218,6 +218,7 @@ void ff_simple_idct44_add(uint8_t *dest, int line_size, int16_t *block) } } +#if CONFIG_PRORES_DECODER void ff_prores_idct(int16_t *block, const int16_t *qmat) { int i; @@ -231,3 +232,4 @@ void ff_prores_idct(int16_t *block, const int16_t *qmat) for (i = 0; i < 8; i++) idctSparseCol_10(block + i); } +#endif /* CONFIG_PRORES_DECODER */ diff --git a/libavcodec/simple_idct_template.c b/libavcodec/simple_idct_template.c index b287c4f..171cdf6 100644 --- a/libavcodec/simple_idct_template.c +++ b/libavcodec/simple_idct_template.c @@ -25,10 +25,8 @@ * simpleidct in C. */ -/* - based upon some outcommented c code from mpeg2dec (idct_mmx.c - written by Aaron Holtzman ) - */ +/* Based upon some commented-out C code from mpeg2dec (idct_mmx.c + * written by Aaron Holtzman ). */ #include "simple_idct.h" @@ -93,33 +91,35 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) #if HAVE_FAST_64BIT #define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN) - if (((((uint64_t *)row)[0] & ~ROW0_MASK) | ((uint64_t *)row)[1]) == 0) { + if (((AV_RN64A(row) & ~ROW0_MASK) | AV_RN64A(row+4)) == 0) { uint64_t temp; if (DC_SHIFT - extra_shift > 0) { - temp = (row[0] << (DC_SHIFT - extra_shift)) & 0xffff; + temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff; } else { temp = (row[0] >> (extra_shift - DC_SHIFT)) & 0xffff; } - temp += temp << 16; - temp += temp << 32; - ((uint64_t *)row)[0] = temp; - ((uint64_t *)row)[1] = temp; + temp += temp * (1 << 16); + temp += temp * ((uint64_t) 1 << 32); + AV_WN64A(row, temp); + AV_WN64A(row + 4, temp); return; } #else - if (!(((uint32_t*)row)[1] | - ((uint32_t*)row)[2] | - ((uint32_t*)row)[3] | + if (!(AV_RN32A(row+2) | + AV_RN32A(row+4) | + AV_RN32A(row+6) | row[1])) { uint32_t temp; if (DC_SHIFT - extra_shift > 0) { - temp = (row[0] << (DC_SHIFT - extra_shift)) & 0xffff; + temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff; } else { temp = (row[0] >> (extra_shift - DC_SHIFT)) & 0xffff; } - temp += temp << 16; - ((uint32_t*)row)[0]=((uint32_t*)row)[1] = - ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp; + temp += temp * (1 << 16); + AV_WN32A(row, temp); + AV_WN32A(row+2, temp); + AV_WN32A(row+4, temp); + AV_WN32A(row+6, temp); return; } #endif diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c index 98607f2..686b3e2 100644 --- a/libavcodec/sipr.c +++ b/libavcodec/sipr.c @@ -28,11 +28,11 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/mathematics.h" -#include "avcodec.h" + #define BITSTREAM_READER_LE +#include "avcodec.h" #include "get_bits.h" #include "internal.h" - #include "lsp.h" #include "acelp_vectors.h" #include "acelp_pitch_delay.h" @@ -44,7 +44,7 @@ #include "sipr.h" #include "siprdata.h" -typedef struct { +typedef struct SiprModeParam { const char *mode_name; uint16_t bits_per_frame; uint8_t subframe_count; @@ -572,5 +572,5 @@ AVCodec ff_sipr_decoder = { .priv_data_size = sizeof(SiprContext), .init = sipr_decoder_init, .decode = sipr_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index ba69303..e3e5475 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -32,20 +32,18 @@ #include #include "libavutil/channel_layout.h" -#include "avcodec.h" -#include "internal.h" -#include "mathops.h" #define BITSTREAM_READER_LE -#include "get_bits.h" +#include "avcodec.h" #include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 -/* - * Decoder context - */ + typedef struct SmackVContext { AVCodecContext *avctx; AVFrame *pic; @@ -531,12 +529,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } - -/* - * - * Uninit smacker decoder - * - */ static av_cold int decode_end(AVCodecContext *avctx) { SmackVContext * const smk = avctx->priv_data; @@ -552,11 +544,6 @@ static av_cold int decode_end(AVCodecContext *avctx) } -/* - * - * Init smacker decoder - * - */ static av_cold int decode_init(AVCodecContext *avctx) { SmackVContext * const c = avctx->priv_data; @@ -763,7 +750,7 @@ AVCodec ff_smacker_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; AVCodec ff_smackaud_decoder = { @@ -773,5 +760,5 @@ AVCodec ff_smackaud_decoder = { .id = AV_CODEC_ID_SMACKAUDIO, .init = smka_decode_init, .decode = smka_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/smc.c b/libavcodec/smc.c index c6541da..92e522b 100644 --- a/libavcodec/smc.c +++ b/libavcodec/smc.c @@ -1,6 +1,6 @@ /* * Quicktime Graphics (SMC) Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -474,5 +474,5 @@ AVCodec ff_smc_decoder = { .init = smc_decode_init, .close = smc_decode_end, .decode = smc_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/snappy.c b/libavcodec/snappy.c new file mode 100644 index 0000000..df6c6b3 --- /dev/null +++ b/libavcodec/snappy.c @@ -0,0 +1,183 @@ +/* + * Snappy decompression algorithm + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/mem.h" + +#include "bytestream.h" +#include "snappy.h" + +enum { + SNAPPY_LITERAL, + SNAPPY_COPY_1, + SNAPPY_COPY_2, + SNAPPY_COPY_4, +}; + +static int64_t bytestream2_get_levarint(GetByteContext *gb) +{ + uint64_t val = 0; + int shift = 0; + int tmp; + + do { + tmp = bytestream2_get_byte(gb); + val |= (tmp & 127) << shift; + shift += 7; + } while (tmp & 128); + + return val; +} + +static int snappy_literal(GetByteContext *gb, uint8_t *p, int size, int val) +{ + unsigned int len = 1; + + switch (val) { + case 63: + len += bytestream2_get_le32(gb); + break; + case 62: + len += bytestream2_get_le24(gb); + break; + case 61: + len += bytestream2_get_le16(gb); + break; + case 60: + len += bytestream2_get_byte(gb); + break; + default: // val < 60 + len += val; + } + + if (size < len) + return AVERROR_INVALIDDATA; + + bytestream2_get_buffer(gb, p, len); + + return len; +} + +static int snappy_copy(uint8_t *start, uint8_t *p, int size, + unsigned int off, int len) +{ + uint8_t *q; + int i; + if (off > p - start || size < len) + return AVERROR_INVALIDDATA; + + q = p - off; + + for (i = 0; i < len; i++) + p[i] = q[i]; + + return len; +} + +static int snappy_copy1(GetByteContext *gb, uint8_t *start, uint8_t *p, + int size, int val) +{ + int len = 4 + (val & 0x7); + unsigned int off = bytestream2_get_byte(gb) | (val & 0x38) << 5; + + return snappy_copy(start, p, size, off, len); +} + +static int snappy_copy2(GetByteContext *gb, uint8_t *start, uint8_t *p, + int size, int val) +{ + int len = 1 + val; + unsigned int off = bytestream2_get_le16(gb); + + return snappy_copy(start, p, size, off, len); +} + +static int snappy_copy4(GetByteContext *gb, uint8_t *start, uint8_t *p, + int size, int val) +{ + int len = 1 + val; + unsigned int off = bytestream2_get_le32(gb); + + return snappy_copy(start, p, size, off, len); +} + +static int64_t decode_len(GetByteContext *gb) +{ + int64_t len = bytestream2_get_levarint(gb); + + if (len < 0 || len > UINT_MAX) + return AVERROR_INVALIDDATA; + + return len; +} + +int64_t ff_snappy_peek_uncompressed_length(GetByteContext *gb) +{ + int pos = bytestream2_get_bytes_left(gb); + int64_t len = decode_len(gb); + + bytestream2_seek(gb, -pos, SEEK_END); + + return len; +} + +int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size) +{ + int64_t len = decode_len(gb); + int ret = 0; + uint8_t *p; + + if (len < 0) + return len; + + if (len > *size) + return AVERROR_BUG; + + *size = len; + p = buf; + + while (bytestream2_get_bytes_left(gb) > 0) { + uint8_t s = bytestream2_get_byte(gb); + int val = s >> 2; + + switch (s & 0x03) { + case SNAPPY_LITERAL: + ret = snappy_literal(gb, p, len, val); + break; + case SNAPPY_COPY_1: + ret = snappy_copy1(gb, buf, p, len, val); + break; + case SNAPPY_COPY_2: + ret = snappy_copy2(gb, buf, p, len, val); + break; + case SNAPPY_COPY_4: + ret = snappy_copy4(gb, buf, p, len, val); + break; + } + + if (ret < 0) + return ret; + + p += ret; + len -= ret; + } + + return 0; +} diff --git a/libavcodec/snappy.h b/libavcodec/snappy.h new file mode 100644 index 0000000..8d365c0 --- /dev/null +++ b/libavcodec/snappy.h @@ -0,0 +1,60 @@ +/* + * Snappy module + * Copyright (c) Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Snappy decompression + * + * Snappy is a compression/decompression algorithm that does not aim for + * maximum compression, but rather for very high speeds and reasonable + * compression. + * + * http://en.wikipedia.org/wiki/Snappy_%28software%29 + */ + +#ifndef AVCODEC_SNAPPY_H +#define AVCODEC_SNAPPY_H + +#include + +#include "bytestream.h" + +/** + * Get the uncompressed length of an input buffer compressed using the Snappy + * algorithm. The GetByteContext is not advanced. + * + * @param gb input GetByteContext. + * @return A positive length on success, AVERROR otherwise. + */ + int64_t ff_snappy_peek_uncompressed_length(GetByteContext *gb); + +/** + * Decompress an input buffer using Snappy algorithm. + * + * @param gb input GetByteContext. + * @param buf input buffer pointer. + * @param size input/output on input, the size of buffer, on output, the size + * of the uncompressed data. + * @return 0 if success, AVERROR otherwise. + */ +int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size); + +#endif /* AVCODEC_SNAPPY_H */ diff --git a/libavcodec/sp5x.h b/libavcodec/sp5x.h index 1577302..090662b 100644 --- a/libavcodec/sp5x.h +++ b/libavcodec/sp5x.h @@ -1,6 +1,6 @@ /* * Sunplus JPEG tables - * Copyright (c) 2003 the ffmpeg project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/sp5xdec.c b/libavcodec/sp5xdec.c index ca6b9fd..7f57b63 100644 --- a/libavcodec/sp5xdec.c +++ b/libavcodec/sp5xdec.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "internal.h" #include "mjpeg.h" #include "mjpegdec.h" #include "sp5x.h" @@ -102,7 +103,8 @@ AVCodec ff_sp5x_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = sp5x_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; AVCodec ff_amv_decoder = { @@ -114,4 +116,6 @@ AVCodec ff_amv_decoder = { .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, .decode = sp5x_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c index bbc8061..3bee3c7 100644 --- a/libavcodec/srtdec.c +++ b/libavcodec/srtdec.c @@ -41,7 +41,7 @@ enum { PARAM_NUMBER }; -typedef struct { +typedef struct SrtStack { char tag[128]; char param[PARAM_NUMBER][128]; } SrtStack; diff --git a/libavcodec/startcode.c b/libavcodec/startcode.c index d34981e..5c1ec84 100644 --- a/libavcodec/startcode.c +++ b/libavcodec/startcode.c @@ -33,7 +33,7 @@ int ff_startcode_find_candidate_c(const uint8_t *buf, int size) int i = 0; #if HAVE_FAST_UNALIGNED /* we check i < size instead of i + 3 / 7 because it is - * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE + * simpler and there must be AV_INPUT_BUFFER_PADDING_SIZE * bytes at the end. */ #if HAVE_FAST_64BIT diff --git a/libavcodec/sunrast.c b/libavcodec/sunrast.c index ffa685c..6a928bb 100644 --- a/libavcodec/sunrast.c +++ b/libavcodec/sunrast.c @@ -172,5 +172,5 @@ AVCodec ff_sunrast_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SUNRAST, .decode = sunrast_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c index 25ae9bd..3a5f410 100644 --- a/libavcodec/sunrastenc.c +++ b/libavcodec/sunrastenc.c @@ -19,12 +19,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" #include "sunrast.h" typedef struct SUNRASTContext { + AVClass *class; + PutByteContext p; int depth; ///< depth of pixel int length; ///< length (bytes) of image @@ -141,6 +145,8 @@ static av_cold int sunrast_encode_init(AVCodecContext *avctx) { SUNRASTContext *s = avctx->priv_data; +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS switch (avctx->coder_type) { case FF_CODER_TYPE_RLE: s->type = RT_BYTE_ENCODED; @@ -152,13 +158,18 @@ static av_cold int sunrast_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "invalid coder_type\n"); return AVERROR(EINVAL); } +FF_ENABLE_DEPRECATION_WARNINGS + if (s->type != RT_BYTE_ENCODED && s->type != RT_STANDARD) +#endif + // adjust boolean option to RT equivalent + s->type++; - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->maptype = RMT_NONE; s->maplength = 0; @@ -169,6 +180,7 @@ static av_cold int sunrast_encode_init(AVCodecContext *avctx) case AV_PIX_FMT_PAL8 : s->maptype = RMT_EQUAL_RGB; s->maplength = 3 * 256; + /* fall-through */ case AV_PIX_FMT_GRAY8: s->depth = 8; break; @@ -179,8 +191,7 @@ static av_cold int sunrast_encode_init(AVCodecContext *avctx) return AVERROR_BUG; } s->length = avctx->height * (FFALIGN(avctx->width * s->depth, 16) >> 3); - s->size = 32 + s->maplength + - s->length * (s->type == RT_BYTE_ENCODED ? 2 : 1); + s->size = 32 + s->maplength + s->length * s->type; return 0; } @@ -209,16 +220,27 @@ static int sunrast_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static av_cold int sunrast_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} +#define OFFSET(x) offsetof(SUNRASTContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "rle", "Use run-length compression", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + + { NULL }, +}; + +static const AVClass sunrast_class = { + .class_name = "sunrast", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; +#if FF_API_CODER_TYPE static const AVCodecDefault sunrast_defaults[] = { { "coder", "rle" }, { NULL }, }; +#endif AVCodec ff_sunrast_encoder = { .name = "sunrast", @@ -226,10 +248,12 @@ AVCodec ff_sunrast_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SUNRAST, .priv_data_size = sizeof(SUNRASTContext), + .priv_class = &sunrast_class, .init = sunrast_encode_init, - .close = sunrast_encode_close, .encode2 = sunrast_encode_frame, +#if FF_API_CODER_TYPE .defaults = sunrast_defaults, +#endif .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, diff --git a/libavcodec/svq1.c b/libavcodec/svq1.c index 545df80..b9922a7 100644 --- a/libavcodec/svq1.c +++ b/libavcodec/svq1.c @@ -4,7 +4,7 @@ * ported to libavcodec by Nick Kurshev * * Copyright (C) 2002 the xine project - * Copyright (C) 2002 the ffmpeg project + * Copyright (C) 2002 The FFmpeg project * * SVQ1 Encoder (c) 2004 Mike Melanson * diff --git a/libavcodec/svq1.h b/libavcodec/svq1.h index 70b5c37..988a0a0 100644 --- a/libavcodec/svq1.h +++ b/libavcodec/svq1.h @@ -4,7 +4,7 @@ * ported to libavcodec by Nick Kurshev * * Copyright (C) 2002 the xine project - * Copyright (C) 2002 the ffmpeg project + * Copyright (C) 2002 The FFmpeg project * * SVQ1 Encoder (c) 2004 Mike Melanson * diff --git a/libavcodec/svq1_cb.h b/libavcodec/svq1_cb.h index e22cd60..396cdf7 100644 --- a/libavcodec/svq1_cb.h +++ b/libavcodec/svq1_cb.h @@ -4,7 +4,7 @@ * ported to libavcodec by Nick Kurshev * * Copyright (C) 2002 the xine project - * Copyright (C) 2002 the ffmpeg project + * Copyright (C) 2002 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/svq1_vlc.h b/libavcodec/svq1_vlc.h index 834279d..073bb6d 100644 --- a/libavcodec/svq1_vlc.h +++ b/libavcodec/svq1_vlc.h @@ -1,5 +1,5 @@ /* - * copyright (C) 2003 the ffmpeg project + * copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index 789a013..d6f4b43 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -4,7 +4,7 @@ * ported to libavcodec by Nick Kurshev * * Copyright (C) 2002 the xine project - * Copyright (C) 2002 the ffmpeg project + * Copyright (C) 2002 The FFmpeg project * * SVQ1 Encoder (c) 2004 Mike Melanson * @@ -40,9 +40,6 @@ #include "mathops.h" #include "svq1.h" -#undef NDEBUG -#include - static VLC svq1_block_type; static VLC svq1_motion_component; static VLC svq1_intra_multistage[6]; @@ -191,8 +188,8 @@ static int svq1_decode_block_intra(GetBitContext *bitbuf, uint8_t *pixels, continue; /* skip vector */ } - if (stages > 0 && level >= 4) { - av_dlog(NULL, + if ((stages > 0 && level >= 4) || stages < 0) { + ff_dlog(NULL, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n", stages, level); return AVERROR_INVALIDDATA; /* invalid vector */ @@ -253,8 +250,8 @@ static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels, if (stages == -1) continue; /* skip vector */ - if ((stages > 0) && (level >= 4)) { - av_dlog(NULL, + if ((stages > 0 && level >= 4) || stages < 0) { + ff_dlog(NULL, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n", stages, level); return AVERROR_INVALIDDATA; /* invalid vector */ @@ -480,7 +477,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp, pitch, motion, x, y, width, height); if (result != 0) { - av_dlog(avctx, "Error in svq1_motion_inter_block %i\n", result); + ff_dlog(avctx, "Error in svq1_motion_inter_block %i\n", result); break; } result = svq1_decode_block_non_intra(bitbuf, current, pitch); @@ -491,7 +488,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp, pitch, motion, x, y, width, height); if (result != 0) { - av_dlog(avctx, "Error in svq1_motion_inter_4v_block %i\n", result); + ff_dlog(avctx, "Error in svq1_motion_inter_4v_block %i\n", result); break; } result = svq1_decode_block_non_intra(bitbuf, current, pitch); @@ -552,7 +549,7 @@ static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame) bitbuf->size_in_bits >> 3, csum); - av_dlog(avctx, "%s checksum (%02x) for packet data\n", + ff_dlog(avctx, "%s checksum (%02x) for packet data\n", (csum == 0) ? "correct" : "incorrect", csum); } @@ -657,7 +654,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, void *data, result = svq1_decode_frame_header(avctx, cur); if (result != 0) { - av_dlog(avctx, "Error in svq1_decode_frame_header %i\n", result); + ff_dlog(avctx, "Error in svq1_decode_frame_header %i\n", result); return result; } @@ -686,7 +683,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, void *data, width = FFALIGN(s->width, 16); height = FFALIGN(s->height, 16); } else { - if (avctx->flags & CODEC_FLAG_GRAY) + if (avctx->flags & AV_CODEC_FLAG_GRAY) break; width = FFALIGN(s->width / 4, 16); height = FFALIGN(s->height / 4, 16); @@ -728,7 +725,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, void *data, previous, linesize, pmv, x, y, width, height); if (result != 0) { - av_dlog(avctx, + ff_dlog(avctx, "Error in svq1_decode_delta_block %i\n", result); goto err; @@ -839,7 +836,7 @@ AVCodec ff_svq1_decoder = { .init = svq1_decode_init, .close = svq1_decode_end, .decode = svq1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = svq1_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index d70bba3..12a23d0 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -150,7 +150,7 @@ static int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref, vector = codebook + stage * size * 16 + i * size; sqr = s->ssd_int8_vs_int16(vector, block[stage], size); diff = block_sum[stage] - sum; - score = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64bit slooow + score = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64 bits slooow if (score < best_vector_score) { int mean = diff + (size >> 1) >> (level + 3); assert(mean > -300 && mean < 300); @@ -238,14 +238,13 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, unsigned char *decoded_plane, int width, int height, int src_stride, int stride) { - const AVFrame *f = s->avctx->coded_frame; int x, y; int i; int block_width, block_height; int level; int threshold[6]; uint8_t *src = s->scratchbuf + stride * 16; - const int lambda = (f->quality * f->quality) >> + const int lambda = (s->quality * s->quality) >> (2 * FF_LAMBDA_SHIFT); /* figure out the acceptable level thresholds in advance */ @@ -256,7 +255,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, block_width = (width + 15) / 16; block_height = (height + 15) / 16; - if (f->pict_type == AV_PICTURE_TYPE_P) { + if (s->pict_type == AV_PICTURE_TYPE_P) { s->m.avctx = s->avctx; s->m.current_picture_ptr = &s->m.current_picture; s->m.last_picture_ptr = &s->m.last_picture; @@ -272,13 +271,25 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, 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 = f->pict_type; + s->m.pict_type = s->pict_type; +#if FF_API_MOTION_EST +FF_DISABLE_DEPRECATION_WARNINGS s->m.me_method = s->avctx->me_method; + if (s->motion_est == FF_ME_EPZS) { + if (s->avctx->me_method == ME_ZERO) + s->motion_est = FF_ME_ZERO; + else if (s->avctx->me_method == ME_EPZS) + s->motion_est = FF_ME_EPZS; + else if (s->avctx->me_method == ME_X1) + s->motion_est = FF_ME_XONE; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + s->m.motion_est = s->motion_est; 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 = f->quality; + s->m.lambda = s->quality; s->m.qscale = s->m.lambda * 139 + FF_LAMBDA_SCALE * 64 >> FF_LAMBDA_SHIFT + 7; @@ -293,6 +304,8 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, s->motion_val16[plane] = av_mallocz((s->m.mb_stride * (block_height + 2) + 1) * 2 * sizeof(int16_t)); + if (!s->motion_val8[plane] || !s->motion_val16[plane]) + return AVERROR(ENOMEM); } s->m.mb_type = s->mb_type; @@ -371,13 +384,13 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, ff_init_block_index(&s->m); ff_update_block_index(&s->m); - if (f->pict_type == AV_PICTURE_TYPE_I || + if (s->pict_type == AV_PICTURE_TYPE_I || (s->m.mb_type[x + y * s->m.mb_stride] & CANDIDATE_MB_TYPE_INTRA)) { for (i = 0; i < 6; i++) init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], 7 * 32); - if (f->pict_type == AV_PICTURE_TYPE_P) { + if (s->pict_type == AV_PICTURE_TYPE_P) { const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA]; put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); score[0] = vlc[1] * lambda; @@ -393,7 +406,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, best = 0; - if (f->pict_type == AV_PICTURE_TYPE_P) { + if (s->pict_type == AV_PICTURE_TYPE_P) { const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER]; int mx, my, pred_x, pred_y, dxy; int16_t *motion_ptr; @@ -499,7 +512,6 @@ static av_cold int svq1_encode_end(AVCodecContext *avctx) av_frame_free(&s->current_picture); av_frame_free(&s->last_picture); - av_frame_free(&avctx->coded_frame); return 0; } @@ -513,10 +525,9 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) ff_me_cmp_init(&s->mecc, avctx); ff_mpegvideoencdsp_init(&s->m.mpvencdsp, avctx); - avctx->coded_frame = av_frame_alloc(); s->current_picture = av_frame_alloc(); s->last_picture = av_frame_alloc(); - if (!avctx->coded_frame || !s->current_picture || !s->last_picture) { + if (!s->current_picture || !s->last_picture) { svq1_encode_end(avctx); return AVERROR(ENOMEM); } @@ -550,6 +561,12 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) s->y_block_height * sizeof(int32_t)); s->ssd_int8_vs_int16 = ssd_int8_vs_int16_c; + if (!s->m.me.temp || !s->m.me.scratchpad || !s->m.me.map || + !s->m.me.score_map || !s->mb_type || !s->dummy) { + svq1_encode_end(avctx); + return AVERROR(ENOMEM); + } + if (ARCH_PPC) ff_svq1enc_init_ppc(s); if (ARCH_X86) @@ -564,12 +581,12 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { SVQ1EncContext *const s = avctx->priv_data; - AVFrame *const p = avctx->coded_frame; int i, ret; + uint8_t *sd; if (!pkt->data && (ret = av_new_packet(pkt, s->y_block_width * s->y_block_height * - MAX_MB_BYTES * 3 + FF_MIN_BUFFER_SIZE)) < 0) { + MAX_MB_BYTES * 3 + AV_INPUT_BUFFER_MIN_SIZE)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } @@ -583,22 +600,41 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ret = ff_get_buffer(avctx, s->current_picture, 0); if (ret < 0) return ret; + } + if (!s->last_picture->data[0]) { ret = ff_get_buffer(avctx, s->last_picture, 0); if (ret < 0) return ret; + } + if (!s->scratchbuf) { s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 2); + if (!s->scratchbuf) + return AVERROR(ENOMEM); } FFSWAP(AVFrame*, s->current_picture, s->last_picture); init_put_bits(&s->pb, pkt->data, pkt->size); - p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ? - AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; - p->key_frame = p->pict_type == AV_PICTURE_TYPE_I; - p->quality = pict->quality; + if (avctx->gop_size && (avctx->frame_number % avctx->gop_size)) + s->pict_type = AV_PICTURE_TYPE_P; + else + s->pict_type = AV_PICTURE_TYPE_I; + s->quality = pict->quality; + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = s->pict_type; + avctx->coded_frame->key_frame = s->pict_type == AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = pict->quality; - svq1_write_header(s, p->pict_type); + svq1_write_header(s, s->pict_type); for (i = 0; i < 3; i++) if (svq1_encode_plane(s, i, pict->data[i], @@ -607,8 +643,15 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->frame_width / (i ? 4 : 1), s->frame_height / (i ? 4 : 1), pict->linesize[i], - s->current_picture->linesize[i]) < 0) + s->current_picture->linesize[i]) < 0) { + int j; + for (j = 0; j < i; j++) { + av_freep(&s->motion_val8[j]); + av_freep(&s->motion_val16[j]); + } + av_freep(&s->scratchbuf); return -1; + } // avpriv_align_put_bits(&s->pb); while (put_bits_count(&s->pb) & 31) @@ -617,19 +660,38 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, flush_put_bits(&s->pb); pkt->size = put_bits_count(&s->pb) / 8; - if (p->pict_type == AV_PICTURE_TYPE_I) + if (s->pict_type == AV_PICTURE_TYPE_I) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; } +#define OFFSET(x) offsetof(struct SVQ1EncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "motion-est", "Motion estimation algorithm", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, VE, "motion-est"}, + { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, + { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, + { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, + + { NULL }, +}; + +static const AVClass svq1enc_class = { + .class_name = "svq1enc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_svq1_encoder = { .name = "svq1", .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SVQ1, .priv_data_size = sizeof(SVQ1EncContext), + .priv_class = &svq1enc_class, .init = svq1_encode_init, .encode2 = svq1_encode_frame, .close = svq1_encode_end, diff --git a/libavcodec/svq1enc.h b/libavcodec/svq1enc.h index 516e875..94458d6 100644 --- a/libavcodec/svq1enc.h +++ b/libavcodec/svq1enc.h @@ -24,8 +24,8 @@ #include #include "libavutil/frame.h" + #include "avcodec.h" -#include "get_bits.h" #include "hpeldsp.h" #include "me_cmp.h" #include "mpegvideo.h" @@ -42,7 +42,10 @@ typedef struct SVQ1EncContext { AVFrame *current_picture; AVFrame *last_picture; PutBitContext pb; - GetBitContext gb; + + /* Some compression statistics */ + enum AVPictureType pict_type; + int quality; /* why ooh why this sick breadth first order, * everything is slower and more complex */ @@ -68,6 +71,8 @@ typedef struct SVQ1EncContext { uint8_t *scratchbuf; + int motion_est; + int (*ssd_int8_vs_int16)(const int8_t *pix1, const int16_t *pix2, int size); } SVQ1EncContext; diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index fc2120b..aa85e7c 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -46,13 +46,11 @@ #include "internal.h" #include "avcodec.h" #include "mpegutils.h" -#include "h264.h" - -#include "h264data.h" // FIXME FIXME FIXME - -#include "h264_mvpred.h" +#include "h264dec.h" +#include "h264data.h" #include "golomb.h" #include "hpeldsp.h" +#include "mathops.h" #include "rectangle.h" #include "tpeldsp.h" @@ -61,30 +59,89 @@ #endif #include "svq1.h" -#include "svq3.h" /** * @file * svq3 decoder. */ -typedef struct { - H264Context h; +typedef struct SVQ3Frame { + AVFrame *f; + + AVBufferRef *motion_val_buf[2]; + int16_t (*motion_val[2])[2]; + + AVBufferRef *mb_type_buf; + uint32_t *mb_type; + + + AVBufferRef *ref_index_buf[2]; + int8_t *ref_index[2]; +} SVQ3Frame; + +typedef struct SVQ3Context { + AVCodecContext *avctx; + + H264DSPContext h264dsp; + H264PredContext hpc; HpelDSPContext hdsp; TpelDSPContext tdsp; - H264Picture *cur_pic; - H264Picture *next_pic; - H264Picture *last_pic; + VideoDSPContext vdsp; + + SVQ3Frame *cur_pic; + SVQ3Frame *next_pic; + SVQ3Frame *last_pic; + GetBitContext gb; + GetBitContext gb_slice; + uint8_t *slice_buf; + int slice_size; int halfpel_flag; int thirdpel_flag; int unknown_flag; - int next_slice_index; uint32_t watermark_key; int adaptive_quant; int next_p_frame_damaged; int h_edge_pos; int v_edge_pos; int last_frame_output; + int slice_num; + int qscale; + int cbp; + int frame_num; + int frame_num_offset; + int prev_frame_num_offset; + int prev_frame_num; + + enum AVPictureType pict_type; + int low_delay; + + int mb_x, mb_y; + int mb_xy; + int mb_width, mb_height; + int mb_stride, mb_num; + int b_stride; + + uint32_t *mb2br_xy; + + int chroma_pred_mode; + int intra16x16_pred_mode; + + int8_t intra4x4_pred_mode_cache[5 * 8]; + int8_t (*intra4x4_pred_mode); + + unsigned int top_samples_available; + unsigned int topright_samples_available; + unsigned int left_samples_available; + + uint8_t *edge_emu_buffer; + + DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2]; + DECLARE_ALIGNED(8, int8_t, ref_cache)[2][5 * 8]; + DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2]; + DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2]; + DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; + uint32_t dequant4_coeff[QP_MAX_NUM + 1][16]; + int block_offset[2 * (16 * 3)]; } SVQ3Context; #define FULLPEL_MODE 1 @@ -92,7 +149,7 @@ typedef struct { #define THIRDPEL_MODE 3 #define PREDICT_MODE 4 -/* dual scan (from some older h264 draft) +/* dual scan (from some older H.264 draft) * o-->o-->o o * | /| * o o o / o @@ -159,7 +216,7 @@ static const uint32_t svq3_dequant_coeff[32] = { 61694, 68745, 77615, 89113, 100253, 109366, 126635, 141533 }; -void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp) +static void svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp) { const int qmul = svq3_dequant_coeff[qp]; #define stride 16 @@ -194,8 +251,8 @@ void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp) } #undef stride -void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, - int stride, int qp, int dc) +static void svq3_add_idct_c(uint8_t *dst, int16_t *block, + int stride, int qp, int dc) { const int qmul = svq3_dequant_coeff[qp]; int i; @@ -237,8 +294,9 @@ void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, static inline int svq3_decode_block(GetBitContext *gb, int16_t *block, int index, const int type) { - static const uint8_t *const scan_patterns[4] = - { luma_dc_zigzag_scan, zigzag_scan, svq3_scan, chroma_dc_scan }; + static const uint8_t *const scan_patterns[4] = { + luma_dc_zigzag_scan, ff_zigzag_scan, svq3_scan, ff_h264_chroma_dc_scan + }; int run, level, limit; unsigned vlc; @@ -246,7 +304,7 @@ static inline int svq3_decode_block(GetBitContext *gb, int16_t *block, 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++) { + for (; (vlc = get_interleaved_ue_golomb(gb)) != 0; index++) { int sign = (vlc & 1) ? 0 : -1; vlc = vlc + 1 >> 1; @@ -290,16 +348,88 @@ static inline int svq3_decode_block(GetBitContext *gb, int16_t *block, return 0; } +static av_always_inline int +svq3_fetch_diagonal_mv(const SVQ3Context *s, const int16_t **C, + int i, int list, int part_width) +{ + const int topright_ref = s->ref_cache[list][i - 8 + part_width]; + + if (topright_ref != PART_NOT_AVAILABLE) { + *C = s->mv_cache[list][i - 8 + part_width]; + return topright_ref; + } else { + *C = s->mv_cache[list][i - 8 - 1]; + return s->ref_cache[list][i - 8 - 1]; + } +} + +/** + * Get the predicted MV. + * @param n the block index + * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4) + * @param mx the x component of the predicted motion vector + * @param my the y component of the predicted motion vector + */ +static av_always_inline void svq3_pred_motion(const SVQ3Context *s, int n, + int part_width, int list, + int ref, int *const mx, int *const my) +{ + const int index8 = scan8[n]; + const int top_ref = s->ref_cache[list][index8 - 8]; + const int left_ref = s->ref_cache[list][index8 - 1]; + const int16_t *const A = s->mv_cache[list][index8 - 1]; + const int16_t *const B = s->mv_cache[list][index8 - 8]; + const int16_t *C; + int diagonal_ref, match_count; + +/* mv_cache + * B . . A T T T T + * U . . L . . , . + * U . . L . . . . + * U . . L . . , . + * . . . L . . . . + */ + + diagonal_ref = svq3_fetch_diagonal_mv(s, &C, index8, list, part_width); + match_count = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref); + 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]); + } + } +} + static inline void svq3_mc_dir_part(SVQ3Context *s, int x, int y, int width, int height, int mx, int my, int dxy, int thirdpel, int dir, int avg) { - H264Context *h = &s->h; - const H264Picture *pic = (dir == 0) ? s->last_pic : s->next_pic; + const SVQ3Frame *pic = (dir == 0) ? s->last_pic : s->next_pic; uint8_t *src, *dest; int i, emu = 0; int blocksize = 2 - (width >> 3); // 16->0, 8->1, 4->2 + int linesize = s->cur_pic->f->linesize[0]; + int uvlinesize = s->cur_pic->f->linesize[1]; mx += x; my += y; @@ -312,26 +442,26 @@ static inline void svq3_mc_dir_part(SVQ3Context *s, } /* form component predictions */ - dest = h->cur_pic.f.data[0] + x + y * h->linesize; - src = pic->f.data[0] + mx + my * h->linesize; + dest = s->cur_pic->f->data[0] + x + y * linesize; + src = pic->f->data[0] + mx + my * linesize; if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src, - h->linesize, h->linesize, + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, + linesize, linesize, width + 1, height + 1, mx, my, s->h_edge_pos, s->v_edge_pos); - src = h->edge_emu_buffer; + src = s->edge_emu_buffer; } if (thirdpel) (avg ? s->tdsp.avg_tpel_pixels_tab - : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, h->linesize, + : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, linesize, width, height); else (avg ? s->hdsp.avg_pixels_tab - : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, h->linesize, + : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, linesize, height); - if (!(h->flags & CODEC_FLAG_GRAY)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { mx = mx + (mx < (int) x) >> 1; my = my + (my < (int) y) >> 1; width = width >> 1; @@ -339,26 +469,26 @@ static inline void svq3_mc_dir_part(SVQ3Context *s, blocksize++; for (i = 1; i < 3; i++) { - dest = h->cur_pic.f.data[i] + (x >> 1) + (y >> 1) * h->uvlinesize; - src = pic->f.data[i] + mx + my * h->uvlinesize; + dest = s->cur_pic->f->data[i] + (x >> 1) + (y >> 1) * uvlinesize; + src = pic->f->data[i] + mx + my * uvlinesize; if (emu) { - h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src, - h->uvlinesize, h->uvlinesize, + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, + uvlinesize, uvlinesize, width + 1, height + 1, mx, my, (s->h_edge_pos >> 1), s->v_edge_pos >> 1); - src = h->edge_emu_buffer; + src = s->edge_emu_buffer; } if (thirdpel) (avg ? s->tdsp.avg_tpel_pixels_tab : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, - h->uvlinesize, + uvlinesize, width, height); else (avg ? s->hdsp.avg_pixels_tab : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, - h->uvlinesize, + uvlinesize, height); } } @@ -368,7 +498,6 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode, int dir, int avg) { int i, j, k, mx, my, dx, dy, x, y; - H264Context *h = &s->h; const int part_width = ((size & 5) == 4) ? 4 : 16 >> (size & 1); const int part_height = 16 >> ((unsigned)(size + 1) / 3); const int extra_width = (mode == PREDICT_MODE) ? -16 * 6 : 0; @@ -377,30 +506,30 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode, for (i = 0; i < 16; i += part_height) for (j = 0; j < 16; j += part_width) { - const int b_xy = (4 * h->mb_x + (j >> 2)) + - (4 * h->mb_y + (i >> 2)) * h->b_stride; + const int b_xy = (4 * s->mb_x + (j >> 2)) + + (4 * s->mb_y + (i >> 2)) * s->b_stride; int dxy; - x = 16 * h->mb_x + j; - y = 16 * h->mb_y + i; + 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); + svq3_pred_motion(s, k, part_width >> 2, dir, 1, &mx, &my); } else { mx = s->next_pic->motion_val[0][b_xy][0] << 1; my = s->next_pic->motion_val[0][b_xy][1] << 1; if (dir == 0) { - mx = mx * h->frame_num_offset / - h->prev_frame_num_offset + 1 >> 1; - my = my * h->frame_num_offset / - h->prev_frame_num_offset + 1 >> 1; + mx = mx * s->frame_num_offset / + s->prev_frame_num_offset + 1 >> 1; + my = my * s->frame_num_offset / + s->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; + mx = mx * (s->frame_num_offset - s->prev_frame_num_offset) / + s->prev_frame_num_offset + 1 >> 1; + my = my * (s->frame_num_offset - s->prev_frame_num_offset) / + s->prev_frame_num_offset + 1 >> 1; } } @@ -412,11 +541,11 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode, if (mode == PREDICT_MODE) { dx = dy = 0; } else { - dy = svq3_get_se_golomb(&h->gb); - dx = svq3_get_se_golomb(&h->gb); + dy = get_interleaved_se_golomb(&s->gb_slice); + dx = get_interleaved_se_golomb(&s->gb_slice); if (dx == INVALID_VLC || dy == INVALID_VLC) { - av_log(h->avctx, AV_LOG_ERROR, "invalid MV vlc\n"); + av_log(s->avctx, AV_LOG_ERROR, "invalid MV vlc\n"); return -1; } } @@ -458,48 +587,154 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode, int32_t mv = pack16to32(mx, my); if (part_height == 8 && i < 8) { - AV_WN32A(h->mv_cache[dir][scan8[k] + 1 * 8], mv); + AV_WN32A(s->mv_cache[dir][scan8[k] + 1 * 8], mv); if (part_width == 8 && j < 8) - AV_WN32A(h->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv); + AV_WN32A(s->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv); } if (part_width == 8 && j < 8) - AV_WN32A(h->mv_cache[dir][scan8[k] + 1], mv); + AV_WN32A(s->mv_cache[dir][scan8[k] + 1], mv); if (part_width == 4 || part_height == 4) - AV_WN32A(h->mv_cache[dir][scan8[k]], mv); + AV_WN32A(s->mv_cache[dir][scan8[k]], mv); } /* write back motion vectors */ - fill_rectangle(h->cur_pic.motion_val[dir][b_xy], - part_width >> 2, part_height >> 2, h->b_stride, + fill_rectangle(s->cur_pic->motion_val[dir][b_xy], + part_width >> 2, part_height >> 2, s->b_stride, pack16to32(mx, my), 4); } return 0; } +static av_always_inline void hl_decode_mb_idct_luma(SVQ3Context *s, + int mb_type, const int *block_offset, + int linesize, uint8_t *dest_y) +{ + int i; + if (!IS_INTRA4x4(mb_type)) { + for (i = 0; i < 16; i++) + if (s->non_zero_count_cache[scan8[i]] || s->mb[i * 16]) { + uint8_t *const ptr = dest_y + block_offset[i]; + svq3_add_idct_c(ptr, s->mb + i * 16, linesize, + s->qscale, IS_INTRA(mb_type) ? 1 : 0); + } + } +} + +static av_always_inline int dctcoef_get(int16_t *mb, int index) +{ + return AV_RN16A(mb + index); +} + +static av_always_inline void hl_decode_mb_predict_luma(SVQ3Context *s, + int mb_type, + const int *block_offset, + int linesize, + uint8_t *dest_y) +{ + int i; + int qscale = s->qscale; + + if (IS_INTRA4x4(mb_type)) { + for (i = 0; i < 16; i++) { + uint8_t *const ptr = dest_y + block_offset[i]; + const int dir = s->intra4x4_pred_mode_cache[scan8[i]]; + + uint8_t *topright; + int nnz, tr; + if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { + const int topright_avail = (s->topright_samples_available << i) & 0x8000; + assert(s->mb_y || linesize <= block_offset[i]); + if (!topright_avail) { + tr = ptr[3 - linesize] * 0x01010101u; + topright = (uint8_t *)&tr; + } else + topright = ptr + 4 - linesize; + } else + topright = NULL; + + s->hpc.pred4x4[dir](ptr, topright, linesize); + nnz = s->non_zero_count_cache[scan8[i]]; + if (nnz) { + svq3_add_idct_c(ptr, s->mb + i * 16, linesize, qscale, 0); + } + } + } else { + s->hpc.pred16x16[s->intra16x16_pred_mode](dest_y, linesize); + svq3_luma_dc_dequant_idct_c(s->mb, s->mb_luma_dc[0], qscale); + } +} + +static void hl_decode_mb(SVQ3Context *s) +{ + const int mb_x = s->mb_x; + const int mb_y = s->mb_y; + const int mb_xy = s->mb_xy; + const int mb_type = s->cur_pic->mb_type[mb_xy]; + uint8_t *dest_y, *dest_cb, *dest_cr; + int linesize, uvlinesize; + int i, j; + const int *block_offset = &s->block_offset[0]; + const int block_h = 16 >> 1; + + linesize = s->cur_pic->f->linesize[0]; + uvlinesize = s->cur_pic->f->linesize[1]; + + dest_y = s->cur_pic->f->data[0] + (mb_x + mb_y * linesize) * 16; + dest_cb = s->cur_pic->f->data[1] + mb_x * 8 + mb_y * uvlinesize * block_h; + dest_cr = s->cur_pic->f->data[2] + mb_x * 8 + mb_y * uvlinesize * block_h; + + s->vdsp.prefetch(dest_y + (s->mb_x & 3) * 4 * linesize + 64, linesize, 4); + s->vdsp.prefetch(dest_cb + (s->mb_x & 7) * uvlinesize + 64, dest_cr - dest_cb, 2); + + if (IS_INTRA(mb_type)) { + s->hpc.pred8x8[s->chroma_pred_mode](dest_cb, uvlinesize); + s->hpc.pred8x8[s->chroma_pred_mode](dest_cr, uvlinesize); + + hl_decode_mb_predict_luma(s, mb_type, block_offset, linesize, dest_y); + } + + hl_decode_mb_idct_luma(s, mb_type, block_offset, linesize, dest_y); + + if (s->cbp & 0x30) { + uint8_t *dest[2] = { dest_cb, dest_cr }; + s->h264dsp.h264_chroma_dc_dequant_idct(s->mb + 16 * 16 * 1, + s->dequant4_coeff[4][0]); + s->h264dsp.h264_chroma_dc_dequant_idct(s->mb + 16 * 16 * 2, + s->dequant4_coeff[4][0]); + for (j = 1; j < 3; j++) { + for (i = j * 16; i < j * 16 + 4; i++) + if (s->non_zero_count_cache[scan8[i]] || s->mb[i * 16]) { + uint8_t *const ptr = dest[j - 1] + block_offset[i]; + svq3_add_idct_c(ptr, s->mb + i * 16, + uvlinesize, ff_h264_chroma_qp[0][s->qscale + 12] - 12, 2); + } + } + } +} + static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) { - H264Context *h = &s->h; int i, j, k, m, dir, mode; int cbp = 0; uint32_t vlc; int8_t *top, *left; - const int mb_xy = h->mb_xy; - const int b_xy = 4 * h->mb_x + 4 * h->mb_y * h->b_stride; + const int mb_xy = s->mb_xy; + const int b_xy = 4 * s->mb_x + 4 * s->mb_y * s->b_stride; - h->top_samples_available = (h->mb_y == 0) ? 0x33FF : 0xFFFF; - h->left_samples_available = (h->mb_x == 0) ? 0x5F5F : 0xFFFF; - h->topright_samples_available = 0xFFFF; + s->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; + s->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF; + s->topright_samples_available = 0xFFFF; if (mb_type == 0) { /* SKIP */ - if (h->pict_type == AV_PICTURE_TYPE_P || + if (s->pict_type == AV_PICTURE_TYPE_P || s->next_pic->mb_type[mb_xy] == -1) { - svq3_mc_dir_part(s, 16 * h->mb_x, 16 * h->mb_y, 16, 16, + svq3_mc_dir_part(s, 16 * s->mb_x, 16 * s->mb_y, 16, 16, 0, 0, 0, 0, 0, 0); - if (h->pict_type == AV_PICTURE_TYPE_B) - svq3_mc_dir_part(s, 16 * h->mb_x, 16 * h->mb_y, 16, 16, + if (s->pict_type == AV_PICTURE_TYPE_B) + 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; @@ -513,10 +748,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) mb_type = MB_TYPE_16x16; } } else if (mb_type < 8) { /* INTER */ - if (s->thirdpel_flag && s->halfpel_flag == !get_bits1(&h->gb)) + if (s->thirdpel_flag && s->halfpel_flag == !get_bits1(&s->gb_slice)) mode = THIRDPEL_MODE; else if (s->halfpel_flag && - s->thirdpel_flag == !get_bits1(&h->gb)) + s->thirdpel_flag == !get_bits1(&s->gb_slice)) mode = HALFPEL_MODE; else mode = FULLPEL_MODE; @@ -531,46 +766,46 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) */ for (m = 0; m < 2; m++) { - if (h->mb_x > 0 && h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6] != -1) { + if (s->mb_x > 0 && s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - 1] + 6] != -1) { for (i = 0; i < 4; i++) - AV_COPY32(h->mv_cache[m][scan8[0] - 1 + i * 8], - h->cur_pic.motion_val[m][b_xy - 1 + i * h->b_stride]); + AV_COPY32(s->mv_cache[m][scan8[0] - 1 + i * 8], + s->cur_pic->motion_val[m][b_xy - 1 + i * s->b_stride]); } else { for (i = 0; i < 4; i++) - AV_ZERO32(h->mv_cache[m][scan8[0] - 1 + i * 8]); + AV_ZERO32(s->mv_cache[m][scan8[0] - 1 + i * 8]); } - if (h->mb_y > 0) { - memcpy(h->mv_cache[m][scan8[0] - 1 * 8], - h->cur_pic.motion_val[m][b_xy - h->b_stride], + if (s->mb_y > 0) { + memcpy(s->mv_cache[m][scan8[0] - 1 * 8], + s->cur_pic->motion_val[m][b_xy - s->b_stride], 4 * 2 * sizeof(int16_t)); - memset(&h->ref_cache[m][scan8[0] - 1 * 8], - (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4); - - if (h->mb_x < h->mb_width - 1) { - AV_COPY32(h->mv_cache[m][scan8[0] + 4 - 1 * 8], - h->cur_pic.motion_val[m][b_xy - h->b_stride + 4]); - h->ref_cache[m][scan8[0] + 4 - 1 * 8] = - (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride + 1] + 6] == -1 || - h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1; + memset(&s->ref_cache[m][scan8[0] - 1 * 8], + (s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4); + + if (s->mb_x < s->mb_width - 1) { + AV_COPY32(s->mv_cache[m][scan8[0] + 4 - 1 * 8], + s->cur_pic->motion_val[m][b_xy - s->b_stride + 4]); + s->ref_cache[m][scan8[0] + 4 - 1 * 8] = + (s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride + 1] + 6] == -1 || + s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1; } else - h->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE; - if (h->mb_x > 0) { - AV_COPY32(h->mv_cache[m][scan8[0] - 1 - 1 * 8], - h->cur_pic.motion_val[m][b_xy - h->b_stride - 1]); - h->ref_cache[m][scan8[0] - 1 - 1 * 8] = - (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] == -1) ? PART_NOT_AVAILABLE : 1; + s->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE; + if (s->mb_x > 0) { + AV_COPY32(s->mv_cache[m][scan8[0] - 1 - 1 * 8], + s->cur_pic->motion_val[m][b_xy - s->b_stride - 1]); + s->ref_cache[m][scan8[0] - 1 - 1 * 8] = + (s->intra4x4_pred_mode[s->mb2br_xy[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; + s->ref_cache[m][scan8[0] - 1 - 1 * 8] = PART_NOT_AVAILABLE; } else - memset(&h->ref_cache[m][scan8[0] - 1 * 8 - 1], + memset(&s->ref_cache[m][scan8[0] - 1 * 8 - 1], PART_NOT_AVAILABLE, 8); - if (h->pict_type != AV_PICTURE_TYPE_B) + if (s->pict_type != AV_PICTURE_TYPE_B) break; } /* decode motion vector(s) and form prediction(s) */ - if (h->pict_type == AV_PICTURE_TYPE_P) { + if (s->pict_type == AV_PICTURE_TYPE_P) { if (svq3_mc_dir(s, mb_type - 1, mode, 0, 0) < 0) return -1; } else { /* AV_PICTURE_TYPE_B */ @@ -579,7 +814,7 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) return -1; } else { for (i = 0; i < 4; i++) - memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride], + memset(s->cur_pic->motion_val[0][b_xy + i * s->b_stride], 0, 4 * 2 * sizeof(int16_t)); } if (mb_type != 1) { @@ -587,128 +822,137 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) return -1; } else { for (i = 0; i < 4; i++) - memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride], + memset(s->cur_pic->motion_val[1][b_xy + i * s->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)); + int8_t *i4x4 = s->intra4x4_pred_mode + s->mb2br_xy[s->mb_xy]; + int8_t *i4x4_cache = s->intra4x4_pred_mode_cache; + + memset(s->intra4x4_pred_mode_cache, -1, 8 * 5 * sizeof(int8_t)); if (mb_type == 8) { - if (h->mb_x > 0) { + 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[h->mb2br_xy[mb_xy - 1] + 6 - i]; - if (h->intra4x4_pred_mode_cache[scan8[0] - 1] == -1) - h->left_samples_available = 0x5F5F; + s->intra4x4_pred_mode_cache[scan8[0] - 1 + i * 8] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - 1] + 6 - i]; + if (s->intra4x4_pred_mode_cache[scan8[0] - 1] == -1) + s->left_samples_available = 0x5F5F; } - if (h->mb_y > 0) { - h->intra4x4_pred_mode_cache[4 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 0]; - h->intra4x4_pred_mode_cache[5 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 1]; - h->intra4x4_pred_mode_cache[6 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 2]; - h->intra4x4_pred_mode_cache[7 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 3]; - - if (h->intra4x4_pred_mode_cache[4 + 8 * 0] == -1) - h->top_samples_available = 0x33FF; + if (s->mb_y > 0) { + s->intra4x4_pred_mode_cache[4 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 0]; + s->intra4x4_pred_mode_cache[5 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 1]; + s->intra4x4_pred_mode_cache[6 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 2]; + s->intra4x4_pred_mode_cache[7 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 3]; + + if (s->intra4x4_pred_mode_cache[4 + 8 * 0] == -1) + s->top_samples_available = 0x33FF; } /* decode prediction codes for luma blocks */ for (i = 0; i < 16; i += 2) { - vlc = svq3_get_ue_golomb(&h->gb); + vlc = get_interleaved_ue_golomb(&s->gb_slice); if (vlc >= 25) { - av_log(h->avctx, AV_LOG_ERROR, + av_log(s->avctx, AV_LOG_ERROR, "luma prediction:%"PRIu32"\n", vlc); return -1; } - left = &h->intra4x4_pred_mode_cache[scan8[i] - 1]; - top = &h->intra4x4_pred_mode_cache[scan8[i] - 8]; + left = &s->intra4x4_pred_mode_cache[scan8[i] - 1]; + top = &s->intra4x4_pred_mode_cache[scan8[i] - 8]; left[1] = svq3_pred_1[top[0] + 1][left[0] + 1][svq3_pred_0[vlc][0]]; left[2] = svq3_pred_1[top[1] + 1][left[1] + 1][svq3_pred_0[vlc][1]]; if (left[1] == -1 || left[2] == -1) { - av_log(h->avctx, AV_LOG_ERROR, "weird prediction\n"); + av_log(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); + memset(&s->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_PRED, 4); } - write_back_intra_pred_mode(h); + AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4); + i4x4[4] = i4x4_cache[7 + 8 * 3]; + i4x4[5] = i4x4_cache[7 + 8 * 2]; + i4x4[6] = i4x4_cache[7 + 8 * 1]; if (mb_type == 8) { - ff_h264_check_intra4x4_pred_mode(h); + ff_h264_check_intra4x4_pred_mode(s->intra4x4_pred_mode_cache, + s->avctx, s->top_samples_available, + s->left_samples_available); - h->top_samples_available = (h->mb_y == 0) ? 0x33FF : 0xFFFF; - h->left_samples_available = (h->mb_x == 0) ? 0x5F5F : 0xFFFF; + s->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; + s->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); + memset(&s->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_128_PRED, 4); - h->top_samples_available = 0x33FF; - h->left_samples_available = 0x5F5F; + s->top_samples_available = 0x33FF; + s->left_samples_available = 0x5F5F; } mb_type = MB_TYPE_INTRA4x4; } else { /* INTRA16x16 */ - dir = i_mb_type_info[mb_type - 8].pred_mode; + dir = ff_h264_i_mb_type_info[mb_type - 8].pred_mode; dir = (dir >> 1) ^ 3 * (dir & 1) ^ 1; - if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir, 0)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n"); - return h->intra16x16_pred_mode; + if ((s->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(s->avctx, s->top_samples_available, + s->left_samples_available, dir, 0)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n"); + return s->intra16x16_pred_mode; } - cbp = i_mb_type_info[mb_type - 8].cbp; + cbp = ff_h264_i_mb_type_info[mb_type - 8].cbp; mb_type = MB_TYPE_INTRA16x16; } - if (!IS_INTER(mb_type) && h->pict_type != AV_PICTURE_TYPE_I) { + if (!IS_INTER(mb_type) && s->pict_type != AV_PICTURE_TYPE_I) { for (i = 0; i < 4; i++) - memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride], + memset(s->cur_pic->motion_val[0][b_xy + i * s->b_stride], 0, 4 * 2 * sizeof(int16_t)); - if (h->pict_type == AV_PICTURE_TYPE_B) { + if (s->pict_type == AV_PICTURE_TYPE_B) { for (i = 0; i < 4; i++) - memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride], + memset(s->cur_pic->motion_val[1][b_xy + i * s->b_stride], 0, 4 * 2 * sizeof(int16_t)); } } if (!IS_INTRA4x4(mb_type)) { - memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy], DC_PRED, 8); + memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy], DC_PRED, 8); } - if (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B) { - memset(h->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t)); + if (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B) { + memset(s->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t)); } if (!IS_INTRA16x16(mb_type) && - (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B)) { - if ((vlc = svq3_get_ue_golomb(&h->gb)) >= 48) { - av_log(h->avctx, AV_LOG_ERROR, "cbp_vlc=%"PRIu32"\n", vlc); + (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B)) { + if ((vlc = get_interleaved_ue_golomb(&s->gb_slice)) >= 48) { + av_log(s->avctx, AV_LOG_ERROR, "cbp_vlc=%"PRIu32"\n", vlc); return -1; } - cbp = IS_INTRA(mb_type) ? golomb_to_intra4x4_cbp[vlc] - : golomb_to_inter_cbp[vlc]; + cbp = IS_INTRA(mb_type) ? ff_h264_golomb_to_intra4x4_cbp[vlc] + : ff_h264_golomb_to_inter_cbp[vlc]; } if (IS_INTRA16x16(mb_type) || - (h->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) { - h->qscale += svq3_get_se_golomb(&h->gb); + (s->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) { + s->qscale += get_interleaved_se_golomb(&s->gb_slice); - if (h->qscale > 31u) { - av_log(h->avctx, AV_LOG_ERROR, "qscale:%d\n", h->qscale); + if (s->qscale > 31u) { + av_log(s->avctx, AV_LOG_ERROR, "qscale:%d\n", s->qscale); return -1; } } if (IS_INTRA16x16(mb_type)) { - AV_ZERO128(h->mb_luma_dc[0] + 0); - AV_ZERO128(h->mb_luma_dc[0] + 8); - if (svq3_decode_block(&h->gb, h->mb_luma_dc[0], 0, 1)) { - av_log(h->avctx, AV_LOG_ERROR, + AV_ZERO128(s->mb_luma_dc[0] + 0); + AV_ZERO128(s->mb_luma_dc[0] + 8); + if (svq3_decode_block(&s->gb_slice, s->mb_luma_dc[0], 0, 1)) { + av_log(s->avctx, AV_LOG_ERROR, "error while decoding intra luma dc\n"); return -1; } @@ -716,7 +960,7 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) if (cbp) { const int index = IS_INTRA16x16(mb_type) ? 1 : 0; - const int type = ((h->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1); + const int type = ((s->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1); for (i = 0; i < 4; i++) if ((cbp & (1 << i))) { @@ -724,10 +968,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) k = index ? (1 * (j & 1) + 2 * (i & 1) + 2 * (j & 2) + 4 * (i & 2)) : (4 * i + j); - h->non_zero_count_cache[scan8[k]] = 1; + s->non_zero_count_cache[scan8[k]] = 1; - if (svq3_decode_block(&h->gb, &h->mb[16 * k], index, type)) { - av_log(h->avctx, AV_LOG_ERROR, + if (svq3_decode_block(&s->gb_slice, &s->mb[16 * k], index, type)) { + av_log(s->avctx, AV_LOG_ERROR, "error while decoding block\n"); return -1; } @@ -736,8 +980,8 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) if ((cbp & 0x30)) { for (i = 1; i < 3; ++i) - if (svq3_decode_block(&h->gb, &h->mb[16 * 16 * i], 0, 3)) { - av_log(h->avctx, AV_LOG_ERROR, + if (svq3_decode_block(&s->gb_slice, &s->mb[16 * 16 * i], 0, 3)) { + av_log(s->avctx, AV_LOG_ERROR, "error while decoding chroma dc block\n"); return -1; } @@ -746,10 +990,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) for (i = 1; i < 3; i++) { for (j = 0; j < 4; j++) { k = 16 * i + j; - h->non_zero_count_cache[scan8[k]] = 1; + s->non_zero_count_cache[scan8[k]] = 1; - if (svq3_decode_block(&h->gb, &h->mb[16 * k], 1, 1)) { - av_log(h->avctx, AV_LOG_ERROR, + if (svq3_decode_block(&s->gb_slice, &s->mb[16 * k], 1, 1)) { + av_log(s->avctx, AV_LOG_ERROR, "error while decoding chroma ac block\n"); return -1; } @@ -759,11 +1003,12 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) } } - h->cbp = cbp; - h->cur_pic.mb_type[mb_xy] = mb_type; + s->cbp = cbp; + s->cur_pic->mb_type[mb_xy] = mb_type; if (IS_INTRA(mb_type)) - h->chroma_pred_mode = ff_h264_check_intra_pred_mode(h, DC_PRED8x8, 1); + s->chroma_pred_mode = ff_h264_check_intra_pred_mode(s->avctx, s->top_samples_available, + s->left_samples_available, DC_PRED8x8, 1); return 0; } @@ -771,99 +1016,115 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) static int svq3_decode_slice_header(AVCodecContext *avctx) { SVQ3Context *s = avctx->priv_data; - H264Context *h = &s->h; - const int mb_xy = h->mb_xy; + const int mb_xy = s->mb_xy; int i, header; unsigned slice_id; - header = get_bits(&h->gb, 8); + header = get_bits(&s->gb, 8); if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) { /* TODO: what? */ av_log(avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header); return -1; } else { + int slice_bits, slice_bytes, slice_length; int length = header >> 5 & 3; - s->next_slice_index = get_bits_count(&h->gb) + - 8 * show_bits(&h->gb, 8 * length) + - 8 * length; + slice_length = show_bits(&s->gb, 8 * length); + slice_bits = slice_length * 8; + slice_bytes = slice_length + length - 1; - if (s->next_slice_index > h->gb.size_in_bits) { + if (slice_bytes > get_bits_left(&s->gb)) { av_log(avctx, AV_LOG_ERROR, "slice after bitstream end\n"); return -1; } - h->gb.size_in_bits = s->next_slice_index - 8 * (length - 1); - skip_bits(&h->gb, 8); + skip_bits(&s->gb, 8); + + av_fast_malloc(&s->slice_buf, &s->slice_size, slice_bytes + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->slice_buf) + return AVERROR(ENOMEM); + + memcpy(s->slice_buf, s->gb.buffer + s->gb.index / 8, slice_bytes); + + init_get_bits(&s->gb_slice, s->slice_buf, slice_bits); if (s->watermark_key) { - uint32_t header = AV_RL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1]); - AV_WL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1], - header ^ s->watermark_key); + uint32_t header = AV_RL32(&s->gb_slice.buffer[1]); + AV_WL32(&s->gb_slice.buffer[1], header ^ s->watermark_key); } if (length > 0) { - memcpy((uint8_t *) &h->gb.buffer[get_bits_count(&h->gb) >> 3], - &h->gb.buffer[h->gb.size_in_bits >> 3], length - 1); + memcpy(s->slice_buf, &s->slice_buf[slice_length], length - 1); } - skip_bits_long(&h->gb, 0); + skip_bits_long(&s->gb, slice_bytes * 8); } - if ((slice_id = svq3_get_ue_golomb(&h->gb)) >= 3) { - av_log(h->avctx, AV_LOG_ERROR, "illegal slice type %u \n", slice_id); + if ((slice_id = get_interleaved_ue_golomb(&s->gb_slice)) >= 3) { + av_log(s->avctx, AV_LOG_ERROR, "illegal slice type %u \n", slice_id); return -1; } - h->slice_type = golomb_to_pict_type[slice_id]; + s->pict_type = ff_h264_golomb_to_pict_type[slice_id]; if ((header & 0x9F) == 2) { - i = (h->mb_num < 64) ? 6 : (1 + av_log2(h->mb_num - 1)); - h->mb_skip_run = get_bits(&h->gb, i) - - (h->mb_y * h->mb_width + h->mb_x); + i = (s->mb_num < 64) ? 6 : (1 + av_log2(s->mb_num - 1)); + get_bits(&s->gb_slice, i); } else { - skip_bits1(&h->gb); - h->mb_skip_run = 0; + skip_bits1(&s->gb_slice); } - h->slice_num = get_bits(&h->gb, 8); - h->qscale = get_bits(&h->gb, 5); - s->adaptive_quant = get_bits1(&h->gb); + s->slice_num = get_bits(&s->gb_slice, 8); + s->qscale = get_bits(&s->gb_slice, 5); + s->adaptive_quant = get_bits1(&s->gb_slice); /* unknown fields */ - skip_bits1(&h->gb); + skip_bits1(&s->gb_slice); if (s->unknown_flag) - skip_bits1(&h->gb); + skip_bits1(&s->gb_slice); - skip_bits1(&h->gb); - skip_bits(&h->gb, 2); + skip_bits1(&s->gb_slice); + skip_bits(&s->gb_slice, 2); - while (get_bits1(&h->gb)) - skip_bits(&h->gb, 8); + while (get_bits1(&s->gb_slice)) + skip_bits(&s->gb_slice, 8); /* reset intra predictors and invalidate motion vector references */ - if (h->mb_x > 0) { - memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - 1] + 3, + if (s->mb_x > 0) { + memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - 1] + 3, -1, 4 * sizeof(int8_t)); - memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - h->mb_x], - -1, 8 * sizeof(int8_t) * h->mb_x); + memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - s->mb_x], + -1, 8 * sizeof(int8_t) * s->mb_x); } - if (h->mb_y > 0) { - memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - h->mb_stride], - -1, 8 * sizeof(int8_t) * (h->mb_width - h->mb_x)); + if (s->mb_y > 0) { + memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - s->mb_stride], + -1, 8 * sizeof(int8_t) * (s->mb_width - s->mb_x)); - if (h->mb_x > 0) - h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] = -1; + if (s->mb_x > 0) + s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride - 1] + 3] = -1; } return 0; } +static void init_dequant4_coeff_table(SVQ3Context *s) +{ + int q, x; + const int max_qp = 51; + + for (q = 0; q < max_qp + 1; q++) { + int shift = ff_h264_quant_div6[q] + 2; + int idx = ff_h264_quant_rem6[q]; + for (x = 0; x < 16; x++) + s->dequant4_coeff[q][(x >> 2) | ((x << 2) & 0xF)] = + ((uint32_t)ff_h264_dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * 16) << shift; + } +} + static av_cold int svq3_decode_init(AVCodecContext *avctx) { SVQ3Context *s = avctx->priv_data; - H264Context *h = &s->h; - int m; + int m, x, y; unsigned char *extradata; unsigned char *extradata_end; unsigned int size; @@ -879,21 +1140,23 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - if (ff_h264_decode_init(avctx) < 0) - return -1; + s->cur_pic->f = av_frame_alloc(); + s->last_pic->f = av_frame_alloc(); + s->next_pic->f = av_frame_alloc(); + if (!s->cur_pic->f || !s->last_pic->f || !s->next_pic->f) + return AVERROR(ENOMEM); + + ff_h264dsp_init(&s->h264dsp, 8, 1); + ff_h264_pred_init(&s->hpc, AV_CODEC_ID_SVQ3, 8, 1); + ff_videodsp_init(&s->vdsp, 8); ff_hpeldsp_init(&s->hdsp, avctx->flags); ff_tpeldsp_init(&s->tdsp); - h->flags = avctx->flags; - h->is_complex = 1; - h->picture_structure = PICT_FRAME; avctx->pix_fmt = AV_PIX_FMT_YUVJ420P; avctx->color_range = AVCOL_RANGE_JPEG; - h->chroma_qp[0] = h->chroma_qp[1] = 4; - h->chroma_x_shift = h->chroma_y_shift = 1; - + s->avctx = avctx; s->halfpel_flag = 1; s->thirdpel_flag = 1; s->unknown_flag = 0; @@ -967,7 +1230,7 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) skip_bits1(&gb); skip_bits1(&gb); - h->low_delay = get_bits1(&gb); + s->low_delay = get_bits1(&gb); /* unknown field */ skip_bits1(&gb); @@ -976,15 +1239,15 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) skip_bits(&gb, 8); s->unknown_flag = get_bits1(&gb); - avctx->has_b_frames = !h->low_delay; + avctx->has_b_frames = !s->low_delay; if (s->unknown_flag) { #if CONFIG_ZLIB - unsigned watermark_width = svq3_get_ue_golomb(&gb); - unsigned watermark_height = svq3_get_ue_golomb(&gb); - int u1 = svq3_get_ue_golomb(&gb); + unsigned watermark_width = get_interleaved_ue_golomb(&gb); + unsigned watermark_height = get_interleaved_ue_golomb(&gb); + int u1 = get_interleaved_ue_golomb(&gb); int u2 = get_bits(&gb, 8); int u3 = get_bits(&gb, 2); - int u4 = svq3_get_ue_golomb(&gb); + int u4 = get_interleaved_ue_golomb(&gb); unsigned long buf_len = watermark_width * watermark_height * 4; int offset = get_bits_count(&gb) + 7 >> 3; @@ -1020,25 +1283,36 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx) } } - h->width = avctx->width; - h->height = avctx->height; - h->mb_width = (h->width + 15) / 16; - h->mb_height = (h->height + 15) / 16; - h->mb_stride = h->mb_width + 1; - h->mb_num = h->mb_width * h->mb_height; - h->b_stride = 4 * h->mb_width; - s->h_edge_pos = h->mb_width * 16; - s->v_edge_pos = h->mb_height * 16; - - if (ff_h264_alloc_tables(h) < 0) { - av_log(avctx, AV_LOG_ERROR, "svq3 memory allocation failed\n"); + s->mb_width = (avctx->width + 15) / 16; + s->mb_height = (avctx->height + 15) / 16; + s->mb_stride = s->mb_width + 1; + s->mb_num = s->mb_width * s->mb_height; + s->b_stride = 4 * s->mb_width; + s->h_edge_pos = s->mb_width * 16; + s->v_edge_pos = s->mb_height * 16; + + s->intra4x4_pred_mode = av_mallocz(s->mb_stride * 2 * 8); + if (!s->intra4x4_pred_mode) return AVERROR(ENOMEM); - } + + s->mb2br_xy = av_mallocz(s->mb_stride * (s->mb_height + 1) * + sizeof(*s->mb2br_xy)); + if (!s->mb2br_xy) + return AVERROR(ENOMEM); + + 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; + + s->mb2br_xy[mb_xy] = 8 * (mb_xy % (2 * s->mb_stride)); + } + + init_dequant4_coeff_table(s); return 0; } -static void free_picture(AVCodecContext *avctx, H264Picture *pic) +static void free_picture(AVCodecContext *avctx, SVQ3Frame *pic) { int i; for (i = 0; i < 2; i++) { @@ -1047,26 +1321,25 @@ static void free_picture(AVCodecContext *avctx, H264Picture *pic) } av_buffer_unref(&pic->mb_type_buf); - av_frame_unref(&pic->f); + av_frame_unref(pic->f); } -static int get_buffer(AVCodecContext *avctx, H264Picture *pic) +static int get_buffer(AVCodecContext *avctx, SVQ3Frame *pic) { SVQ3Context *s = avctx->priv_data; - H264Context *h = &s->h; - const int big_mb_num = h->mb_stride * (h->mb_height + 1) + 1; - const int mb_array_size = h->mb_stride * h->mb_height; - const int b4_stride = h->mb_width * 4 + 1; - const int b4_array_size = b4_stride * h->mb_height * 4; + const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; + const int mb_array_size = s->mb_stride * s->mb_height; + const int b4_stride = s->mb_width * 4 + 1; + const int b4_array_size = b4_stride * s->mb_height * 4; int ret; if (!pic->motion_val_buf[0]) { int i; - pic->mb_type_buf = av_buffer_allocz((big_mb_num + h->mb_stride) * sizeof(uint32_t)); + pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * sizeof(uint32_t)); if (!pic->mb_type_buf) return AVERROR(ENOMEM); - pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1; + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1; for (i = 0; i < 2; i++) { pic->motion_val_buf[i] = av_buffer_allocz(2 * (b4_array_size + 4) * sizeof(int16_t)); @@ -1080,22 +1353,19 @@ static int get_buffer(AVCodecContext *avctx, H264Picture *pic) pic->ref_index[i] = pic->ref_index_buf[i]->data; } } - pic->reference = !(h->pict_type == AV_PICTURE_TYPE_B); - ret = ff_get_buffer(avctx, &pic->f, - pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + ret = ff_get_buffer(avctx, pic->f, + (s->pict_type != AV_PICTURE_TYPE_B) ? + AV_GET_BUFFER_FLAG_REF : 0); if (ret < 0) goto fail; - if (!h->edge_emu_buffer) { - h->edge_emu_buffer = av_mallocz(pic->f.linesize[0] * 17); - if (!h->edge_emu_buffer) + if (!s->edge_emu_buffer) { + s->edge_emu_buffer = av_mallocz(pic->f->linesize[0] * 17); + if (!s->edge_emu_buffer) return AVERROR(ENOMEM); } - h->linesize = pic->f.linesize[0]; - h->uvlinesize = pic->f.linesize[1]; - return 0; fail: free_picture(avctx, pic); @@ -1107,14 +1377,13 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, { const uint8_t *buf = avpkt->data; SVQ3Context *s = avctx->priv_data; - H264Context *h = &s->h; int buf_size = avpkt->size; int ret, m, i; /* special case for last picture */ if (buf_size == 0) { - if (s->next_pic->f.data[0] && !h->low_delay && !s->last_frame_output) { - ret = av_frame_ref(data, &s->next_pic->f); + if (s->next_pic->f->data[0] && !s->low_delay && !s->last_frame_output) { + ret = av_frame_ref(data, s->next_pic->f); if (ret < 0) return ret; s->last_frame_output = 1; @@ -1123,108 +1392,101 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, return 0; } - init_get_bits(&h->gb, buf, 8 * buf_size); + ret = init_get_bits(&s->gb, buf, 8 * buf_size); + if (ret < 0) + return ret; - h->mb_x = h->mb_y = h->mb_xy = 0; + s->mb_x = s->mb_y = s->mb_xy = 0; if (svq3_decode_slice_header(avctx)) return -1; - h->pict_type = h->slice_type; - - if (h->pict_type != AV_PICTURE_TYPE_B) - FFSWAP(H264Picture*, s->next_pic, s->last_pic); + if (s->pict_type != AV_PICTURE_TYPE_B) + FFSWAP(SVQ3Frame*, s->next_pic, s->last_pic); - av_frame_unref(&s->cur_pic->f); + av_frame_unref(s->cur_pic->f); /* for skipping the frame */ - s->cur_pic->f.pict_type = h->pict_type; - s->cur_pic->f.key_frame = (h->pict_type == AV_PICTURE_TYPE_I); + s->cur_pic->f->pict_type = s->pict_type; + s->cur_pic->f->key_frame = (s->pict_type == AV_PICTURE_TYPE_I); ret = get_buffer(avctx, s->cur_pic); if (ret < 0) return ret; - h->cur_pic_ptr = s->cur_pic; - av_frame_unref(&h->cur_pic.f); - h->cur_pic = *s->cur_pic; - ret = av_frame_ref(&h->cur_pic.f, &s->cur_pic->f); - if (ret < 0) - return ret; - for (i = 0; i < 16; i++) { - h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); - h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + s->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * s->cur_pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3); + s->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * s->cur_pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3); } for (i = 0; i < 16; i++) { - h->block_offset[16 + i] = - h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); - h->block_offset[48 + 16 + i] = - h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + s->block_offset[16 + i] = + s->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * s->cur_pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3); + s->block_offset[48 + 16 + i] = + s->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * s->cur_pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3); } - if (h->pict_type != AV_PICTURE_TYPE_I) { - if (!s->last_pic->f.data[0]) { + if (s->pict_type != AV_PICTURE_TYPE_I) { + if (!s->last_pic->f->data[0]) { av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); ret = get_buffer(avctx, s->last_pic); if (ret < 0) return ret; - memset(s->last_pic->f.data[0], 0, avctx->height * s->last_pic->f.linesize[0]); - memset(s->last_pic->f.data[1], 0x80, (avctx->height / 2) * - s->last_pic->f.linesize[1]); - memset(s->last_pic->f.data[2], 0x80, (avctx->height / 2) * - s->last_pic->f.linesize[2]); + memset(s->last_pic->f->data[0], 0, avctx->height * s->last_pic->f->linesize[0]); + memset(s->last_pic->f->data[1], 0x80, (avctx->height / 2) * + s->last_pic->f->linesize[1]); + memset(s->last_pic->f->data[2], 0x80, (avctx->height / 2) * + s->last_pic->f->linesize[2]); } - if (h->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f.data[0]) { + if (s->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f->data[0]) { av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); ret = get_buffer(avctx, s->next_pic); if (ret < 0) return ret; - memset(s->next_pic->f.data[0], 0, avctx->height * s->next_pic->f.linesize[0]); - memset(s->next_pic->f.data[1], 0x80, (avctx->height / 2) * - s->next_pic->f.linesize[1]); - memset(s->next_pic->f.data[2], 0x80, (avctx->height / 2) * - s->next_pic->f.linesize[2]); + memset(s->next_pic->f->data[0], 0, avctx->height * s->next_pic->f->linesize[0]); + memset(s->next_pic->f->data[1], 0x80, (avctx->height / 2) * + s->next_pic->f->linesize[1]); + memset(s->next_pic->f->data[2], 0x80, (avctx->height / 2) * + s->next_pic->f->linesize[2]); } } if (avctx->debug & FF_DEBUG_PICT_INFO) - av_log(h->avctx, AV_LOG_DEBUG, + av_log(s->avctx, AV_LOG_DEBUG, "%c hpel:%d, tpel:%d aqp:%d qp:%d, slice_num:%02X\n", - av_get_picture_type_char(h->pict_type), + av_get_picture_type_char(s->pict_type), s->halfpel_flag, s->thirdpel_flag, - s->adaptive_quant, h->qscale, h->slice_num); + s->adaptive_quant, s->qscale, s->slice_num); - if (avctx->skip_frame >= AVDISCARD_NONREF && h->pict_type == AV_PICTURE_TYPE_B || - avctx->skip_frame >= AVDISCARD_NONKEY && h->pict_type != AV_PICTURE_TYPE_I || + if (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B || + avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I || avctx->skip_frame >= AVDISCARD_ALL) return 0; if (s->next_p_frame_damaged) { - if (h->pict_type == AV_PICTURE_TYPE_B) + if (s->pict_type == AV_PICTURE_TYPE_B) return 0; else s->next_p_frame_damaged = 0; } - if (h->pict_type == AV_PICTURE_TYPE_B) { - h->frame_num_offset = h->slice_num - h->prev_frame_num; + if (s->pict_type == AV_PICTURE_TYPE_B) { + s->frame_num_offset = s->slice_num - s->prev_frame_num; - if (h->frame_num_offset < 0) - h->frame_num_offset += 256; - if (h->frame_num_offset == 0 || - h->frame_num_offset >= h->prev_frame_num_offset) { - av_log(h->avctx, AV_LOG_ERROR, "error in B-frame picture id\n"); + if (s->frame_num_offset < 0) + s->frame_num_offset += 256; + if (s->frame_num_offset == 0 || + s->frame_num_offset >= s->prev_frame_num_offset) { + av_log(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; + s->prev_frame_num = s->frame_num; + s->frame_num = s->slice_num; + s->prev_frame_num_offset = s->frame_num - s->prev_frame_num; - if (h->prev_frame_num_offset < 0) - h->prev_frame_num_offset += 256; + if (s->prev_frame_num_offset < 0) + s->prev_frame_num_offset += 256; } for (m = 0; m < 2; m++) { @@ -1232,70 +1494,68 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, for (i = 0; i < 4; i++) { int j; for (j = -1; j < 4; j++) - h->ref_cache[m][scan8[0] + 8 * i + j] = 1; + s->ref_cache[m][scan8[0] + 8 * i + j] = 1; if (i < 3) - h->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE; + s->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE; } } - for (h->mb_y = 0; h->mb_y < h->mb_height; h->mb_y++) { - for (h->mb_x = 0; h->mb_x < h->mb_width; h->mb_x++) { + 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++) { unsigned mb_type; - h->mb_xy = h->mb_x + h->mb_y * h->mb_stride; + s->mb_xy = s->mb_x + s->mb_y * s->mb_stride; - if ((get_bits_count(&h->gb) + 7) >= h->gb.size_in_bits && - ((get_bits_count(&h->gb) & 7) == 0 || - show_bits(&h->gb, -get_bits_count(&h->gb) & 7) == 0)) { - skip_bits(&h->gb, s->next_slice_index - get_bits_count(&h->gb)); - h->gb.size_in_bits = 8 * buf_size; - - if (svq3_decode_slice_header(avctx)) - return -1; + if ((get_bits_left(&s->gb_slice)) <= 7) { + if (((get_bits_count(&s->gb_slice) & 7) == 0 || + show_bits(&s->gb_slice, get_bits_left(&s->gb_slice) & 7) == 0)) { + if (svq3_decode_slice_header(avctx)) + return -1; + } /* TODO: support s->mb_skip_run */ } - mb_type = svq3_get_ue_golomb(&h->gb); + mb_type = get_interleaved_ue_golomb(&s->gb_slice); - if (h->pict_type == AV_PICTURE_TYPE_I) + if (s->pict_type == AV_PICTURE_TYPE_I) mb_type += 8; - else if (h->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4) + else if (s->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4) mb_type += 4; if (mb_type > 33 || svq3_decode_mb(s, mb_type)) { - av_log(h->avctx, AV_LOG_ERROR, - "error while decoding MB %d %d\n", h->mb_x, h->mb_y); + av_log(s->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d\n", s->mb_x, s->mb_y); return -1; } if (mb_type != 0) - ff_h264_hl_decode_mb(h); + hl_decode_mb(s); - if (h->pict_type != AV_PICTURE_TYPE_B && !h->low_delay) - h->cur_pic.mb_type[h->mb_x + h->mb_y * h->mb_stride] = - (h->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1; + if (s->pict_type != AV_PICTURE_TYPE_B && !s->low_delay) + s->cur_pic->mb_type[s->mb_x + s->mb_y * s->mb_stride] = + (s->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1; } - ff_draw_horiz_band(avctx, &s->cur_pic->f, - s->last_pic->f.data[0] ? &s->last_pic->f : NULL, - 16 * h->mb_y, 16, h->picture_structure, 0, - h->low_delay); + ff_draw_horiz_band(avctx, s->cur_pic->f, + s->last_pic->f->data[0] ? s->last_pic->f : NULL, + 16 * s->mb_y, 16, PICT_FRAME, 0, + s->low_delay); } - if (h->pict_type == AV_PICTURE_TYPE_B || h->low_delay) - ret = av_frame_ref(data, &s->cur_pic->f); - else if (s->last_pic->f.data[0]) - ret = av_frame_ref(data, &s->last_pic->f); + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) + ret = av_frame_ref(data, s->cur_pic->f); + else if (s->last_pic->f->data[0]) + ret = av_frame_ref(data, s->last_pic->f); if (ret < 0) return ret; /* Do not output the last pic after seeking. */ - if (s->last_pic->f.data[0] || h->low_delay) + if (s->last_pic->f->data[0] || s->low_delay) *got_frame = 1; - if (h->pict_type != AV_PICTURE_TYPE_B) { - FFSWAP(H264Picture*, s->cur_pic, s->next_pic); + if (s->pict_type != AV_PICTURE_TYPE_B) { + FFSWAP(SVQ3Frame*, s->cur_pic, s->next_pic); } else { - av_frame_unref(&s->cur_pic->f); + av_frame_unref(s->cur_pic->f); } return buf_size; @@ -1304,18 +1564,20 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, static av_cold int svq3_decode_end(AVCodecContext *avctx) { SVQ3Context *s = avctx->priv_data; - H264Context *h = &s->h; free_picture(avctx, s->cur_pic); free_picture(avctx, s->next_pic); free_picture(avctx, s->last_pic); + av_frame_free(&s->cur_pic->f); + av_frame_free(&s->next_pic->f); + av_frame_free(&s->last_pic->f); av_freep(&s->cur_pic); av_freep(&s->next_pic); av_freep(&s->last_pic); - - av_frame_unref(&h->cur_pic.f); - - ff_h264_free_context(h); + av_freep(&s->slice_buf); + av_freep(&s->intra4x4_pred_mode); + av_freep(&s->edge_emu_buffer); + av_freep(&s->mb2br_xy); return 0; } @@ -1329,9 +1591,9 @@ AVCodec ff_svq3_decoder = { .init = svq3_decode_init, .close = svq3_decode_end, .decode = svq3_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | - CODEC_CAP_DR1 | - CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_DELAY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE}, }; diff --git a/libavcodec/synth_filter.c b/libavcodec/synth_filter.c index d0ace40..708bd4e 100644 --- a/libavcodec/synth_filter.c +++ b/libavcodec/synth_filter.c @@ -60,6 +60,10 @@ av_cold void ff_synth_filter_init(SynthFilterContext *c) { c->synth_filter_float = synth_filter_float; - if (ARCH_ARM) ff_synth_filter_init_arm(c); - if (ARCH_X86) ff_synth_filter_init_x86(c); + if (ARCH_AARCH64) + ff_synth_filter_init_aarch64(c); + if (ARCH_ARM) + ff_synth_filter_init_arm(c); + if (ARCH_X86) + ff_synth_filter_init_x86(c); } diff --git a/libavcodec/synth_filter.h b/libavcodec/synth_filter.h index f842c70..a93dc4f 100644 --- a/libavcodec/synth_filter.h +++ b/libavcodec/synth_filter.h @@ -32,6 +32,7 @@ typedef struct SynthFilterContext { } SynthFilterContext; void ff_synth_filter_init(SynthFilterContext *c); +void ff_synth_filter_init_aarch64(SynthFilterContext *c); void ff_synth_filter_init_arm(SynthFilterContext *c); void ff_synth_filter_init_x86(SynthFilterContext *c); diff --git a/libavcodec/tak.c b/libavcodec/tak.c index 867a84b..bd82c3d 100644 --- a/libavcodec/tak.c +++ b/libavcodec/tak.c @@ -22,6 +22,8 @@ #include "libavutil/bswap.h" #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" + +#define BITSTREAM_READER_LE #include "tak.h" static const uint16_t frame_duration_type_quants[] = { diff --git a/libavcodec/tak.h b/libavcodec/tak.h index fa91149..19b1c47 100644 --- a/libavcodec/tak.h +++ b/libavcodec/tak.h @@ -29,9 +29,8 @@ #include -#define BITSTREAM_READER_LE -#include "get_bits.h" #include "avcodec.h" +#include "get_bits.h" #define TAK_FORMAT_DATA_TYPE_BITS 3 #define TAK_FORMAT_SAMPLE_RATE_BITS 18 diff --git a/libavcodec/tak_parser.c b/libavcodec/tak_parser.c index 295df24..9ac1deb 100644 --- a/libavcodec/tak_parser.c +++ b/libavcodec/tak_parser.c @@ -24,8 +24,9 @@ * TAK parser **/ -#include "tak.h" +#define BITSTREAM_READER_LE #include "parser.h" +#include "tak.h" typedef struct TAKParseContext { ParseContext pc; diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c index b0e84ea..c9db928 100644 --- a/libavcodec/takdec.c +++ b/libavcodec/takdec.c @@ -27,11 +27,13 @@ #include "libavutil/internal.h" #include "libavutil/samplefmt.h" -#include "tak.h" + +#define BITSTREAM_READER_LE #include "audiodsp.h" #include "avcodec.h" #include "internal.h" #include "unary.h" +#include "tak.h" #define MAX_SUBFRAMES 8 // max number of subframes per channel #define MAX_PREDICTORS 256 @@ -487,7 +489,7 @@ static int decode_subframe(TAKDecContext *s, int32_t *decoded, v += s->adsp.scalarproduct_int16(&s->residues[i], filter, FFALIGN(filter_order, 16)); - v = (av_clip(v >> filter_quant, -8192, 8191) << dshift) - *decoded; + v = (av_clip_intp2(v >> filter_quant, 13) << dshift) - *decoded; *decoded++ = v; s->residues[filter_order + i] = v >> dshift; } @@ -657,7 +659,7 @@ static int decorrelate(TAKDecContext *s, int c1, int c2, int length) v += s->adsp.scalarproduct_int16(&s->residues[i], filter, FFALIGN(filter_order, 16)); - p1[i] = (av_clip(v >> 10, -8192, 8191) << dshift) - p1[i]; + p1[i] = (av_clip_intp2(v >> 10, 13) << dshift) - p1[i]; } emms_c(); @@ -748,6 +750,8 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, int buf_size = av_samples_get_buffer_size(NULL, avctx->channels, s->nb_samples, AV_SAMPLE_FMT_S32P, 0); + if (buf_size < 0) + return buf_size; av_fast_malloc(&s->decode_buffer, &s->decode_buffer_size, buf_size); if (!s->decode_buffer) return AVERROR(ENOMEM); @@ -804,6 +808,12 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, if (s->mcdparams[i].present) { s->mcdparams[i].index = get_bits(gb, 2); s->mcdparams[i].chan2 = get_bits(gb, 4); + if (s->mcdparams[i].chan2 >= avctx->channels) { + av_log(avctx, AV_LOG_ERROR, + "invalid channel 2 (%d) for %d channel(s)\n", + s->mcdparams[i].chan2, avctx->channels); + return AVERROR_INVALIDDATA; + } if (s->mcdparams[i].index == 1) { if ((nbit == s->mcdparams[i].chan2) || (ch_mask & 1 << s->mcdparams[i].chan2)) @@ -925,7 +935,7 @@ AVCodec ff_tak_decoder = { .init_static_data = tak_init_static_data, .close = tak_decode_close, .decode = tak_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, diff --git a/libavcodec/targa.c b/libavcodec/targa.c index f077c03..ef8565f 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -238,5 +238,5 @@ AVCodec ff_targa_decoder = { .id = AV_CODEC_ID_TARGA, .priv_data_size = sizeof(TargaContext), .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c index 7679029..f0cee38 100644 --- a/libavcodec/targaenc.c +++ b/libavcodec/targaenc.c @@ -21,14 +21,22 @@ #include +#include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "internal.h" #include "rle.h" #include "targa.h" +typedef struct TargaContext { + AVClass *class; + + int rle; +} TargaContext; + /** * RLE compress the image, with maximum size of out_size * @param outbuf Output buffer @@ -77,14 +85,12 @@ static int targa_encode_normal(uint8_t *outbuf, const AVFrame *pic, int bpp, int static int targa_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { + TargaContext *s = avctx->priv_data; int bpp, picsize, datasize = -1, ret; uint8_t *out; - if(avctx->width > 0xffff || avctx->height > 0xffff) { - av_log(avctx, AV_LOG_ERROR, "image dimensions too large\n"); - return AVERROR(EINVAL); - } - picsize = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + picsize = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); if ((ret = ff_alloc_packet(pkt, picsize + 45)) < 0) { av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); return ret; @@ -123,8 +129,15 @@ static int targa_encode_frame(AVCodecContext *avctx, AVPacket *pkt, out = pkt->data + 18; /* skip past the header we just output */ +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type == FF_CODER_TYPE_RAW) + s->rle = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + /* try RLE compression */ - if (avctx->coder_type != FF_CODER_TYPE_RAW) + if (s->rle) datasize = targa_encode_rle(out, picsize, p, bpp, avctx->width, avctx->height); /* if that worked well, mark the picture as RLE compressed */ @@ -150,29 +163,44 @@ static int targa_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int targa_encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); + if (avctx->width > 0xffff || avctx->height > 0xffff) { + av_log(avctx, AV_LOG_ERROR, "image dimensions too large\n"); + return AVERROR(EINVAL); + } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } -static av_cold int targa_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} +#define OFFSET(x) offsetof(TargaContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "rle", "Use run-length compression", OFFSET(rle), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + + { NULL }, +}; + +static const AVClass targa_class = { + .class_name = "targa", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_targa_encoder = { .name = "targa", .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_TARGA, + .priv_data_size = sizeof(TargaContext), + .priv_class = &targa_class, .init = targa_encode_init, - .close = targa_encode_close, .encode2 = targa_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_GRAY8, diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c new file mode 100644 index 0000000..c70c77f --- /dev/null +++ b/libavcodec/tdsc.c @@ -0,0 +1,627 @@ +/* + * TDSC decoder + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * TDSC decoder + * + * Fourcc: TSDC + * + * TDSC is very simple. It codes picture by tiles, storing them in raw BGR24 + * format or compressing them in JPEG. Frames can be full pictures or just + * updates to the previous frame. Cursor is found in its own frame or at the + * bottom of the picture. Every frame is then packed with zlib. + * + * Supports: BGR24 + */ + +#include +#include + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define BITMAPINFOHEADER_SIZE 0x28 +#define TDSF_HEADER_SIZE 0x56 +#define TDSB_HEADER_SIZE 0x08 + +typedef struct TDSCContext { + AVCodecContext *jpeg_avctx; // wrapper context for MJPEG + + int width, height; + GetByteContext gbc; + + AVFrame *refframe; // full decoded frame (without cursor) + AVFrame *jpgframe; // decoded JPEG tile + uint8_t *tilebuffer; // buffer containing tile data + + /* zlib interaction */ + uint8_t *deflatebuffer; + uLongf deflatelen; + + /* All that is cursor */ + uint8_t *cursor; + int cursor_stride; + int cursor_w, cursor_h, cursor_x, cursor_y; + int cursor_hot_x, cursor_hot_y; +} TDSCContext; + +/* 1 byte bits, 1 byte planes, 2 bytes format (probably) */ +enum TDSCCursorFormat { + CUR_FMT_MONO = 0x01010004, + CUR_FMT_BGRA = 0x20010004, + CUR_FMT_RGBA = 0x20010008, +}; + +static av_cold int tdsc_close(AVCodecContext *avctx) +{ + TDSCContext *ctx = avctx->priv_data; + + av_frame_free(&ctx->refframe); + av_frame_free(&ctx->jpgframe); + av_freep(&ctx->deflatebuffer); + av_freep(&ctx->tilebuffer); + av_freep(&ctx->cursor); + avcodec_free_context(&ctx->jpeg_avctx); + + return 0; +} + +static av_cold int tdsc_init(AVCodecContext *avctx) +{ + TDSCContext *ctx = avctx->priv_data; + const AVCodec *codec; + int ret; + + avctx->pix_fmt = AV_PIX_FMT_BGR24; + + /* These needs to be set to estimate buffer and frame size */ + if (!(avctx->width && avctx->height)) { + av_log(avctx, AV_LOG_ERROR, "Video size not set.\n"); + return AVERROR_INVALIDDATA; + } + + /* This value should be large enough for a RAW-only frame plus headers */ + ctx->deflatelen = avctx->width * avctx->height * (3 + 1); + ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen); + if (ret < 0) + return ret; + + /* Allocate reference and JPEG frame */ + ctx->refframe = av_frame_alloc(); + ctx->jpgframe = av_frame_alloc(); + if (!ctx->refframe || !ctx->jpgframe) + return AVERROR(ENOMEM); + + /* Prepare everything needed for JPEG decoding */ + codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); + if (!codec) + return AVERROR_BUG; + ctx->jpeg_avctx = avcodec_alloc_context3(codec); + if (!ctx->jpeg_avctx) + return AVERROR(ENOMEM); + ctx->jpeg_avctx->flags = avctx->flags; + ctx->jpeg_avctx->flags2 = avctx->flags2; + ctx->jpeg_avctx->dct_algo = avctx->dct_algo; + ctx->jpeg_avctx->idct_algo = avctx->idct_algo;; + ret = avcodec_open2(ctx->jpeg_avctx, codec, NULL); + if (ret < 0) + return ret; + + /* Set the output pixel format on the reference frame */ + ctx->refframe->format = avctx->pix_fmt; + + return 0; +} + +#define APPLY_ALPHA(src, new, alpha) \ + src = (src * (256 - alpha) + new * alpha) >> 8 + +/* Paint a region over a buffer, without drawing out of its bounds. */ +static void tdsc_paint_cursor(AVCodecContext *avctx, uint8_t *dst, int stride) +{ + TDSCContext *ctx = avctx->priv_data; + const uint8_t *cursor = ctx->cursor; + int x = ctx->cursor_x - ctx->cursor_hot_x; + int y = ctx->cursor_y - ctx->cursor_hot_y; + int w = ctx->cursor_w; + int h = ctx->cursor_h; + int i, j; + + if (!ctx->cursor) + return; + + if (x + w > ctx->width) + w = ctx->width - x; + if (y + h > ctx->height) + h = ctx->height - y; + if (x < 0) { + w += x; + cursor += -x * 4; + } else { + dst += x * 3; + } + if (y < 0) { + h += y; + cursor += -y * ctx->cursor_stride; + } else { + dst += y * stride; + } + if (w < 0 || h < 0) + return; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + uint8_t alpha = cursor[i * 4]; + APPLY_ALPHA(dst[i * 3 + 0], cursor[i * 4 + 1], alpha); + APPLY_ALPHA(dst[i * 3 + 1], cursor[i * 4 + 2], alpha); + APPLY_ALPHA(dst[i * 3 + 2], cursor[i * 4 + 3], alpha); + } + dst += stride; + cursor += ctx->cursor_stride; + } +} + +/* Load cursor data and store it in ABGR mode. */ +static int tdsc_load_cursor(AVCodecContext *avctx) +{ + TDSCContext *ctx = avctx->priv_data; + int i, j, k, ret, bits, cursor_fmt; + uint8_t *dst; + + ctx->cursor_hot_x = bytestream2_get_le16(&ctx->gbc); + ctx->cursor_hot_y = bytestream2_get_le16(&ctx->gbc); + ctx->cursor_w = bytestream2_get_le16(&ctx->gbc); + ctx->cursor_h = bytestream2_get_le16(&ctx->gbc); + + ctx->cursor_stride = FFALIGN(ctx->cursor_w, 32) * 4; + cursor_fmt = bytestream2_get_le32(&ctx->gbc); + + if (ctx->cursor_x >= avctx->width || ctx->cursor_y >= avctx->height) { + av_log(avctx, AV_LOG_ERROR, + "Invalid cursor position (%d.%d outside %dx%d).\n", + ctx->cursor_x, ctx->cursor_y, avctx->width, avctx->height); + return AVERROR_INVALIDDATA; + } + if (ctx->cursor_w < 1 || ctx->cursor_w > 256 || + ctx->cursor_h < 1 || ctx->cursor_h > 256) { + av_log(avctx, AV_LOG_ERROR, + "Invalid cursor dimensions %dx%d.\n", + ctx->cursor_w, ctx->cursor_h); + return AVERROR_INVALIDDATA; + } + if (ctx->cursor_hot_x > ctx->cursor_w || + ctx->cursor_hot_y > ctx->cursor_h) { + av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %d.%d.\n", + ctx->cursor_hot_x, ctx->cursor_hot_y); + ctx->cursor_hot_x = FFMIN(ctx->cursor_hot_x, ctx->cursor_w - 1); + ctx->cursor_hot_y = FFMIN(ctx->cursor_hot_y, ctx->cursor_h - 1); + } + + ret = av_reallocp(&ctx->cursor, ctx->cursor_stride * ctx->cursor_h); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate cursor buffer.\n"); + return ret; + } + + dst = ctx->cursor; + /* here data is packed in BE */ + switch (cursor_fmt) { + case CUR_FMT_MONO: + for (j = 0; j < ctx->cursor_h; j++) { + for (i = 0; i < ctx->cursor_w; i += 32) { + bits = bytestream2_get_be32(&ctx->gbc); + for (k = 0; k < 32; k++) { + dst[0] = !!(bits & 0x80000000); + dst += 4; + bits <<= 1; + } + } + dst += ctx->cursor_stride - ctx->cursor_w * 4; + } + + dst = ctx->cursor; + for (j = 0; j < ctx->cursor_h; j++) { + for (i = 0; i < ctx->cursor_w; i += 32) { + bits = bytestream2_get_be32(&ctx->gbc); + for (k = 0; k < 32; k++) { + int mask_bit = !!(bits & 0x80000000); + switch (dst[0] * 2 + mask_bit) { + case 0: + dst[0] = 0xFF; + dst[1] = 0x00; + dst[2] = 0x00; + dst[3] = 0x00; + break; + case 1: + dst[0] = 0xFF; + dst[1] = 0xFF; + dst[2] = 0xFF; + dst[3] = 0xFF; + break; + default: + dst[0] = 0x00; + dst[1] = 0x00; + dst[2] = 0x00; + dst[3] = 0x00; + } + dst += 4; + bits <<= 1; + } + } + dst += ctx->cursor_stride - ctx->cursor_w * 4; + } + break; + case CUR_FMT_BGRA: + case CUR_FMT_RGBA: + /* Skip monochrome version of the cursor */ + bytestream2_skip(&ctx->gbc, + ctx->cursor_h * (FFALIGN(ctx->cursor_w, 32) >> 3)); + if (cursor_fmt & 8) { // RGBA -> ABGR + for (j = 0; j < ctx->cursor_h; j++) { + for (i = 0; i < ctx->cursor_w; i++) { + int val = bytestream2_get_be32(&ctx->gbc); + *dst++ = val >> 24; + *dst++ = val >> 16; + *dst++ = val >> 8; + *dst++ = val >> 0; + } + dst += ctx->cursor_stride - ctx->cursor_w * 4; + } + } else { // BGRA -> ABGR + for (j = 0; j < ctx->cursor_h; j++) { + for (i = 0; i < ctx->cursor_w; i++) { + int val = bytestream2_get_be32(&ctx->gbc); + *dst++ = val >> 0; + *dst++ = val >> 24; + *dst++ = val >> 16; + *dst++ = val >> 8; + } + dst += ctx->cursor_stride - ctx->cursor_w * 4; + } + } + break; + default: + avpriv_request_sample(avctx, "Cursor format %08x", cursor_fmt); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +/* Convert a single YUV pixel to RGB. */ +static inline void tdsc_yuv2rgb(uint8_t *out, int Y, int U, int V) +{ + out[0] = av_clip_uint8(Y + ( 91881 * V + 32768 >> 16)); + out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16)); + out[2] = av_clip_uint8(Y + (116130 * U + 32768 >> 16)); +} + +/* Convert a YUV420 buffer to a RGB buffer. */ +static av_always_inline void tdsc_blit(uint8_t *dst, int dst_stride, + const uint8_t *srcy, int srcy_stride, + const uint8_t *srcu, const uint8_t *srcv, + int srcuv_stride, int width, int height) +{ + int col, line; + for (line = 0; line < height; line++) { + for (col = 0; col < width; col++) + tdsc_yuv2rgb(dst + col * 3, srcy[col], + srcu[col >> 1] - 128, srcv[col >> 1] - 128); + + dst += dst_stride; + srcy += srcy_stride; + srcu += srcuv_stride * (line & 1); + srcv += srcuv_stride * (line & 1); + } +} + +/* Invoke the MJPEG decoder to decode the tile. */ +static int tdsc_decode_jpeg_tile(AVCodecContext *avctx, int tile_size, + int x, int y, int w, int h) +{ + TDSCContext *ctx = avctx->priv_data; + AVPacket jpkt; + int got_frame = 0; + int ret; + + /* Prepare a packet and send to the MJPEG decoder */ + av_init_packet(&jpkt); + jpkt.data = ctx->tilebuffer; + jpkt.size = tile_size; + + ret = avcodec_decode_video2(ctx->jpeg_avctx, ctx->jpgframe, + &got_frame, &jpkt); + if (ret < 0 || !got_frame || ctx->jpgframe->format != AV_PIX_FMT_YUVJ420P) { + av_log(avctx, AV_LOG_ERROR, + "JPEG decoding error (%d) for (%d) frame.\n", + ret, got_frame); + + /* Normally skip, error if explode */ + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + else + return 0; + } + + /* Let's paint onto the buffer */ + tdsc_blit(ctx->refframe->data[0] + x * 3 + ctx->refframe->linesize[0] * y, + ctx->refframe->linesize[0], + ctx->jpgframe->data[0], ctx->jpgframe->linesize[0], + ctx->jpgframe->data[1], ctx->jpgframe->data[2], + ctx->jpgframe->linesize[1], w, h); + + av_frame_unref(ctx->jpgframe); + + return 0; +} + +/* Parse frame and either copy data or decode JPEG. */ +static int tdsc_decode_tiles(AVCodecContext *avctx, int number_tiles) +{ + TDSCContext *ctx = avctx->priv_data; + int i; + + /* Iterate over the number of tiles */ + for (i = 0; i < number_tiles; i++) { + int tile_size; + int tile_mode; + int x, y, w, h; + int ret; + + if (bytestream2_get_bytes_left(&ctx->gbc) < 4 || + bytestream2_get_le32(&ctx->gbc) != MKTAG('T','D','S','B') || + bytestream2_get_bytes_left(&ctx->gbc) < TDSB_HEADER_SIZE - 4) { + av_log(avctx, AV_LOG_ERROR, "TDSB tag is too small.\n"); + return AVERROR_INVALIDDATA; + } + + tile_size = bytestream2_get_le32(&ctx->gbc); + if (bytestream2_get_bytes_left(&ctx->gbc) < tile_size) + return AVERROR_INVALIDDATA; + + tile_mode = bytestream2_get_le32(&ctx->gbc); + bytestream2_skip(&ctx->gbc, 4); // unknown + x = bytestream2_get_le32(&ctx->gbc); + y = bytestream2_get_le32(&ctx->gbc); + w = bytestream2_get_le32(&ctx->gbc) - x; + h = bytestream2_get_le32(&ctx->gbc) - y; + + if (x >= ctx->width || y >= ctx->height) { + av_log(avctx, AV_LOG_ERROR, + "Invalid tile position (%d.%d outside %dx%d).\n", + x, y, ctx->width, ctx->height); + return AVERROR_INVALIDDATA; + } + if (x + w > ctx->width || y + h > ctx->height) { + av_log(avctx, AV_LOG_ERROR, + "Invalid tile size %dx%d\n", w, h); + return AVERROR_INVALIDDATA; + } + + ret = av_reallocp(&ctx->tilebuffer, tile_size); + if (!ctx->tilebuffer) + return ret; + + bytestream2_get_buffer(&ctx->gbc, ctx->tilebuffer, tile_size); + + if (tile_mode == MKTAG('G','E','P','J')) { + /* Decode JPEG tile and copy it in the reference frame */ + ret = tdsc_decode_jpeg_tile(avctx, tile_size, x, y, w, h); + if (ret < 0) + return ret; + } else if (tile_mode == MKTAG(' ','W','A','R')) { + /* Just copy the buffer to output */ + av_image_copy_plane(ctx->refframe->data[0] + x * 3 + + ctx->refframe->linesize[0] * y, + ctx->refframe->linesize[0], ctx->tilebuffer, + w * 3, w * 3, h); + } else { + av_log(avctx, AV_LOG_ERROR, "Unknown tile type %08x.\n", tile_mode); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "Tile %d, %dx%d (%d.%d)\n", i, w, h, x, y); + } + + return 0; +} + +static int tdsc_parse_tdsf(AVCodecContext *avctx, int number_tiles) +{ + TDSCContext *ctx = avctx->priv_data; + int ret, w, h, init_refframe = !ctx->refframe->data[0]; + + /* BITMAPINFOHEADER + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx */ + if (bytestream2_get_le32(&ctx->gbc) != BITMAPINFOHEADER_SIZE) + return AVERROR_INVALIDDATA; + + /* Store size, but wait for context reinit before updating avctx */ + w = bytestream2_get_le32(&ctx->gbc); + h = -bytestream2_get_le32(&ctx->gbc); + + if (bytestream2_get_le16(&ctx->gbc) != 1 || // 1 plane + bytestream2_get_le16(&ctx->gbc) != 24) // BGR24 + return AVERROR_INVALIDDATA; + + bytestream2_skip(&ctx->gbc, 24); // unused fields + + /* Update sizes */ + if (avctx->width != w || avctx->height != h) { + av_log(avctx, AV_LOG_DEBUG, "Size update %dx%d -> %d%d.\n", + avctx->width, avctx->height, ctx->width, ctx->height); + ret = ff_set_dimensions(avctx, w, h); + if (ret < 0) + return ret; + init_refframe = 1; + } + ctx->refframe->width = ctx->width = w; + ctx->refframe->height = ctx->height = h; + + /* Allocate the reference frame if not already done or on size change */ + if (init_refframe) { + ret = av_frame_get_buffer(ctx->refframe, 32); + if (ret < 0) + return ret; + } + + /* Decode all tiles in a frame */ + return tdsc_decode_tiles(avctx, number_tiles); +} + +static int tdsc_parse_dtsm(AVCodecContext *avctx) +{ + TDSCContext *ctx = avctx->priv_data; + int ret; + int action = bytestream2_get_le32(&ctx->gbc); + + bytestream2_skip(&ctx->gbc, 4); // some kind of ID or version maybe? + + if (action == 2 || action == 3) { + /* Load cursor coordinates */ + ctx->cursor_x = bytestream2_get_le32(&ctx->gbc); + ctx->cursor_y = bytestream2_get_le32(&ctx->gbc); + + /* Load a full cursor sprite */ + if (action == 3) { + ret = tdsc_load_cursor(avctx); + /* Do not consider cursor errors fatal unless in explode mode */ + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + } + } else { + avpriv_request_sample(avctx, "Cursor action %d", action); + } + + return 0; +} + +static int tdsc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + TDSCContext *ctx = avctx->priv_data; + AVFrame *frame = data; + int ret, tag_header, keyframe = 0; + uLongf dlen; + + /* Resize deflate buffer on resolution change */ + if (ctx->width != avctx->width || ctx->height != avctx->height) { + ctx->deflatelen = avctx->width * avctx->height * (3 + 1); + ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen); + if (ret < 0) + return ret; + } + dlen = ctx->deflatelen; + + /* Frames are deflated, need to inflate them first */ + ret = uncompress(ctx->deflatebuffer, &dlen, avpkt->data, avpkt->size); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret); + return AVERROR_UNKNOWN; + } + + bytestream2_init(&ctx->gbc, ctx->deflatebuffer, dlen); + + /* Check for tag and for size info */ + if (bytestream2_get_bytes_left(&ctx->gbc) < 4 + 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too small.\n"); + return AVERROR_INVALIDDATA; + } + + /* Read tag */ + tag_header = bytestream2_get_le32(&ctx->gbc); + + if (tag_header == MKTAG('T','D','S','F')) { + int number_tiles; + if (bytestream2_get_bytes_left(&ctx->gbc) < TDSF_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "TDSF tag is too small.\n"); + return AVERROR_INVALIDDATA; + } + /* First 4 bytes here are the number of GEPJ/WAR tiles in this frame */ + number_tiles = bytestream2_get_le32(&ctx->gbc); + + bytestream2_skip(&ctx->gbc, 4); // internal timestamp maybe? + keyframe = bytestream2_get_le32(&ctx->gbc) == 0x30; + + ret = tdsc_parse_tdsf(avctx, number_tiles); + if (ret < 0) + return ret; + + /* Check if there is anything else we are able to parse */ + if (bytestream2_get_bytes_left(&ctx->gbc) >= 4 + 4) + tag_header = bytestream2_get_le32(&ctx->gbc); + } + + /* This tag can be after a TDSF block or on its own frame */ + if (tag_header == MKTAG('D','T','S','M')) { + /* First 4 bytes here are the total size in bytes for this frame */ + int tag_size = bytestream2_get_le32(&ctx->gbc); + + if (bytestream2_get_bytes_left(&ctx->gbc) < tag_size) { + av_log(avctx, AV_LOG_ERROR, "DTSM tag is too small.\n"); + return AVERROR_INVALIDDATA; + } + + ret = tdsc_parse_dtsm(avctx); + if (ret < 0) + return ret; + } + + /* Get the output frame and copy the reference frame */ + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + return ret; + + ret = av_frame_copy(frame, ctx->refframe); + if (ret < 0) + return ret; + + /* Paint the cursor on the output frame */ + tdsc_paint_cursor(avctx, frame->data[0], frame->linesize[0]); + + /* Frame is ready to be output */ + if (keyframe) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + } + *got_frame = 1; + + return 0; +} + +AVCodec ff_tdsc_decoder = { + .name = "tdsc", + .long_name = NULL_IF_CONFIG_SMALL("TDSC"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TDSC, + .init = tdsc_init, + .decode = tdsc_decode_frame, + .close = tdsc_close, + .priv_data_size = sizeof(TDSCContext), + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore new file mode 100644 index 0000000..31fa59b --- /dev/null +++ b/libavcodec/tests/.gitignore @@ -0,0 +1,6 @@ +/dct +/fft +/fft-fixed +/golomb +/iirfilter +/rangecoder diff --git a/libavcodec/arm/dct-test.c b/libavcodec/tests/arm/dct.c similarity index 97% rename from libavcodec/arm/dct-test.c rename to libavcodec/tests/arm/dct.c index 70e5c1c..d18cb52 100644 --- a/libavcodec/arm/dct-test.c +++ b/libavcodec/tests/arm/dct.c @@ -18,7 +18,7 @@ #include "config.h" -#include "idct.h" +#include "libavcodec/arm/idct.h" static const struct algo fdct_tab_arch[] = { { 0 } diff --git a/libavcodec/dct-test.c b/libavcodec/tests/dct.c similarity index 92% rename from libavcodec/dct-test.c rename to libavcodec/tests/dct.c index a531c88..6c6a4e0 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/tests/dct.c @@ -36,16 +36,18 @@ #include "libavutil/cpu.h" #include "libavutil/common.h" +#include "libavutil/internal.h" #include "libavutil/lfg.h" #include "libavutil/time.h" -#include "dct.h" -#include "idctdsp.h" -#include "simple_idct.h" -#include "aandcttab.h" -#include "faandct.h" -#include "faanidct.h" -#include "dctref.h" +#include "libavcodec/aandcttab.h" +#include "libavcodec/dct.h" +#include "libavcodec/dctref.h" +#include "libavcodec/faandct.h" +#include "libavcodec/faanidct.h" +#include "libavcodec/idctdsp.h" +#include "libavcodec/simple_idct.h" +#include "libavcodec/xvididct.h" struct algo { const char *name; @@ -55,29 +57,36 @@ struct algo { int nonspec; }; -static const struct algo fdct_tab[4] = { +static const struct algo fdct_tab[] = { { "REF-DBL", ff_ref_fdct, FF_IDCT_PERM_NONE }, - { "FAAN", ff_faandct, FF_IDCT_PERM_NONE }, { "IJG-AAN-INT", ff_fdct_ifast, FF_IDCT_PERM_NONE }, { "IJG-LLM-INT", ff_jpeg_fdct_islow_8, FF_IDCT_PERM_NONE }, +#if CONFIG_FAANDCT + { "FAAN", ff_faandct, FF_IDCT_PERM_NONE }, +#endif /* CONFIG_FAANDCT */ }; -static const struct algo idct_tab[4] = { - { "FAANI", ff_faanidct, FF_IDCT_PERM_NONE }, +static const struct algo idct_tab[] = { { "REF-DBL", ff_ref_idct, FF_IDCT_PERM_NONE }, { "INT", ff_j_rev_dct, FF_IDCT_PERM_LIBMPEG2 }, { "SIMPLE-C", ff_simple_idct_8, FF_IDCT_PERM_NONE }, +#if CONFIG_FAANIDCT + { "FAANI", ff_faanidct, FF_IDCT_PERM_NONE }, +#endif /* CONFIG_FAANIDCT */ +#if CONFIG_MPEG4_DECODER + { "XVID", ff_xvid_idct, FF_IDCT_PERM_NONE, 0, 1 }, +#endif /* CONFIG_MPEG4_DECODER */ }; #if ARCH_ARM -#include "arm/dct-test.c" +#include "arm/dct.c" #elif ARCH_PPC -#include "ppc/dct-test.c" +#include "ppc/dct.c" #elif ARCH_X86 -#include "x86/dct-test.c" +#include "x86/dct.c" #else -static const struct algo fdct_tab_arch[] = { 0 }; -static const struct algo idct_tab_arch[] = { 0 }; +static const struct algo fdct_tab_arch[] = { { 0 } }; +static const struct algo idct_tab_arch[] = { { 0 } }; #endif #define AANSCALE_BITS 12 @@ -223,7 +232,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) init_block(block, test, is_idct, &prng); permute(block1, block, dct->perm_type); - ti = av_gettime(); + ti = av_gettime_relative(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { @@ -231,7 +240,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) dct->func(block); } it1 += NB_ITS_SPEED; - ti1 = av_gettime() - ti; + ti1 = av_gettime_relative() - ti; } while (ti1 < 1000000); emms_c(); @@ -364,7 +373,7 @@ static void idct248_error(const char *name, if (!speed) return; - ti = av_gettime(); + ti = av_gettime_relative(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { @@ -373,7 +382,7 @@ static void idct248_error(const char *name, idct248_put(img_dest, 8, block); } it1 += NB_ITS_SPEED; - ti1 = av_gettime() - ti; + ti1 = av_gettime_relative() - ti; } while (ti1 < 1000000); emms_c(); @@ -386,7 +395,7 @@ static void help(void) printf("dct-test [-i] []\n" "test-number 0 -> test with random matrixes\n" " 1 -> test with random sparse matrixes\n" - " 2 -> do 3. test from mpeg4 std\n" + " 2 -> do 3. test from MPEG-4 std\n" "-i test IDCT implementations\n" "-4 test IDCT248 implementations\n" "-t speed test\n"); diff --git a/libavcodec/fft-fixed-test.c b/libavcodec/tests/fft-fixed.c similarity index 97% rename from libavcodec/fft-fixed-test.c rename to libavcodec/tests/fft-fixed.c index d6ea987..6edd810 100644 --- a/libavcodec/fft-fixed-test.c +++ b/libavcodec/tests/fft-fixed.c @@ -17,4 +17,4 @@ */ #define FFT_FLOAT 0 -#include "fft-test.c" +#include "fft.c" diff --git a/libavcodec/fft-test.c b/libavcodec/tests/fft.c similarity index 98% rename from libavcodec/fft-test.c rename to libavcodec/tests/fft.c index f62cf0d..db1ce98 100644 --- a/libavcodec/fft-test.c +++ b/libavcodec/tests/fft.c @@ -39,10 +39,10 @@ #include "libavutil/mathematics.h" #include "libavutil/time.h" -#include "fft.h" +#include "libavcodec/fft.h" #if FFT_FLOAT -#include "dct.h" -#include "rdft.h" +#include "libavcodec/dct.h" +#include "libavcodec/rdft.h" #endif /* reference fft */ @@ -193,7 +193,7 @@ static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale) double error = 0, max = 0; for (i = 0; i < n; i++) { - double e = fabsf(tab1[i] - (tab2[i] / scale)) / RANGE; + double e = fabs(tab1[i] - (tab2[i] / scale)) / RANGE; if (e >= 1e-3) { av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n", i, tab1[i], tab2[i]); @@ -439,7 +439,7 @@ int main(int argc, char **argv) /* we measure during about 1 seconds */ nb_its = 1; for (;;) { - time_start = av_gettime(); + time_start = av_gettime_relative(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: @@ -464,7 +464,7 @@ int main(int argc, char **argv) #endif /* FFT_FLOAT */ } } - duration = av_gettime() - time_start; + duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; diff --git a/libavcodec/golomb-test.c b/libavcodec/tests/golomb.c similarity index 96% rename from libavcodec/golomb-test.c rename to libavcodec/tests/golomb.c index e740a20..7587402 100644 --- a/libavcodec/golomb-test.c +++ b/libavcodec/tests/golomb.c @@ -21,9 +21,9 @@ #include "libavutil/mem.h" -#include "get_bits.h" -#include "golomb.h" -#include "put_bits.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/put_bits.h" +#include "libavcodec/golomb.h" #define COUNT 8191 #define SIZE (COUNT * 4) diff --git a/libavcodec/tests/iirfilter.c b/libavcodec/tests/iirfilter.c new file mode 100644 index 0000000..a6001a3 --- /dev/null +++ b/libavcodec/tests/iirfilter.c @@ -0,0 +1,54 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/libm.h" + +#include "libavcodec/iirfilter.h" + +#define FILT_ORDER 4 +#define SIZE 1024 + +int main(void) +{ + struct FFIIRFilterCoeffs *fcoeffs = NULL; + struct FFIIRFilterState *fstate = NULL; + float cutoff_coeff = 0.4; + int16_t x[SIZE], y[SIZE]; + int i; + + fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH, + FF_FILTER_MODE_LOWPASS, FILT_ORDER, + cutoff_coeff, 0.0, 0.0); + fstate = ff_iir_filter_init_state(FILT_ORDER); + + for (i = 0; i < SIZE; i++) + x[i] = lrint(0.75 * INT16_MAX * sin(0.5 * M_PI * i * i / SIZE)); + + ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1); + + for (i = 0; i < SIZE; i++) + printf("%6d %6d\n", x[i], y[i]); + + ff_iir_filter_free_coeffs(fcoeffs); + ff_iir_filter_free_state(fstate); + return 0; +} diff --git a/libavcodec/ppc/dct-test.c b/libavcodec/tests/ppc/dct.c similarity index 93% rename from libavcodec/ppc/dct-test.c rename to libavcodec/tests/ppc/dct.c index 37fd8bb..3d160d3 100644 --- a/libavcodec/ppc/dct-test.c +++ b/libavcodec/tests/ppc/dct.c @@ -18,10 +18,10 @@ #include "config.h" -#include "fdct.h" +#include "libavcodec/ppc/fdct.h" static const struct algo fdct_tab_arch[] = { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN { "altivecfdct", ff_fdct_altivec, FF_IDCT_PERM_NONE, AV_CPU_FLAG_ALTIVEC }, #endif { 0 } diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c new file mode 100644 index 0000000..26bb589 --- /dev/null +++ b/libavcodec/tests/rangecoder.c @@ -0,0 +1,64 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/lfg.h" +#include "libavutil/log.h" + +#include "libavcodec/rangecoder.h" + +#define SIZE 10240 + +int main(void) +{ + RangeCoder c; + uint8_t b[9 * SIZE]; + uint8_t r[9 * SIZE]; + int i; + uint8_t state[10]; + AVLFG prng; + + av_lfg_init(&prng, 1); + + ff_init_range_encoder(&c, b, SIZE); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 128 + 64 + 32 + 16); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + r[i] = av_lfg_get(&prng) % 7; + + for (i = 0; i < SIZE; i++) + put_rac(&c, state, r[i] & 1); + + ff_rac_terminate(&c); + + ff_init_range_decoder(&c, b, SIZE); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + if ((r[i] & 1) != get_rac(&c, state)) { + av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i); + return 1; + } + + return 0; +} diff --git a/libavcodec/x86/dct-test.c b/libavcodec/tests/x86/dct.c similarity index 89% rename from libavcodec/x86/dct-test.c rename to libavcodec/tests/x86/dct.c index d97c53c..2ddb555 100644 --- a/libavcodec/x86/dct-test.c +++ b/libavcodec/tests/x86/dct.c @@ -18,9 +18,9 @@ #include "config.h" -#include "fdct.h" -#include "idct_xvid.h" -#include "simple_idct.h" +#include "libavcodec/x86/fdct.h" +#include "libavcodec/x86/xvididct.h" +#include "libavcodec/x86/simple_idct.h" static const struct algo fdct_tab_arch[] = { #if HAVE_MMX_INLINE @@ -41,13 +41,13 @@ static const struct algo idct_tab_arch[] = { #endif #if CONFIG_MPEG4_DECODER #if HAVE_MMX_INLINE - { "XVID-MMX", ff_idct_xvid_mmx, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX, 1 }, + { "XVID-MMX", ff_xvid_idct_mmx, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX, 1 }, #endif #if HAVE_MMXEXT_INLINE - { "XVID-MMXEXT", ff_idct_xvid_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT, 1 }, + { "XVID-MMXEXT", ff_xvid_idct_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT, 1 }, #endif #if HAVE_SSE2_INLINE - { "XVID-SSE2", ff_idct_xvid_sse2, FF_IDCT_PERM_SSE2, AV_CPU_FLAG_SSE2, 1 }, + { "XVID-SSE2", ff_xvid_idct_sse2, FF_IDCT_PERM_SSE2, AV_CPU_FLAG_SSE2, 1 }, #endif #endif /* CONFIG_MPEG4_DECODER */ { 0 } diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c new file mode 100644 index 0000000..7b54a5d --- /dev/null +++ b/libavcodec/texturedsp.c @@ -0,0 +1,613 @@ +/* + * Texture block decompression + * Copyright (C) 2009 Benjamin Dobell, Glass Echidna + * Copyright (C) 2012 Matthäus G. "Anteru" Chajdas (http://anteru.net) + * Copyright (C) 2015 Vittorio Giovara + * + * 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 +#include + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "texturedsp.h" + +#define RGBA(r, g, b, a) ((uint8_t)(r) << 0) | \ + ((uint8_t)(g) << 8) | \ + ((uint8_t)(b) << 16) | \ + ((uint8_t)(a) << 24) + +static av_always_inline void extract_color(uint32_t colors[4], + uint16_t color0, + uint16_t color1, + int dxtn, int alpha) +{ + int tmp; + uint8_t r0, g0, b0, r1, g1, b1; + uint8_t a = dxtn ? 0 : 255; + + tmp = (color0 >> 11) * 255 + 16; + r0 = (uint8_t) ((tmp / 32 + tmp) / 32); + tmp = ((color0 & 0x07E0) >> 5) * 255 + 32; + g0 = (uint8_t) ((tmp / 64 + tmp) / 64); + tmp = (color0 & 0x001F) * 255 + 16; + b0 = (uint8_t) ((tmp / 32 + tmp) / 32); + + tmp = (color1 >> 11) * 255 + 16; + r1 = (uint8_t) ((tmp / 32 + tmp) / 32); + tmp = ((color1 & 0x07E0) >> 5) * 255 + 32; + g1 = (uint8_t) ((tmp / 64 + tmp) / 64); + tmp = (color1 & 0x001F) * 255 + 16; + b1 = (uint8_t) ((tmp / 32 + tmp) / 32); + + if (dxtn || color0 > color1) { + colors[0] = RGBA(r0, g0, b0, a); + colors[1] = RGBA(r1, g1, b1, a); + colors[2] = RGBA((2 * r0 + r1) / 3, + (2 * g0 + g1) / 3, + (2 * b0 + b1) / 3, + a); + colors[3] = RGBA((2 * r1 + r0) / 3, + (2 * g1 + g0) / 3, + (2 * b1 + b0) / 3, + a); + } else { + colors[0] = RGBA(r0, g0, b0, a); + colors[1] = RGBA(r1, g1, b1, a); + colors[2] = RGBA((r0 + r1) / 2, + (g0 + g1) / 2, + (b0 + b1) / 2, + a); + colors[3] = RGBA(0, 0, 0, alpha); + } +} + +static inline void dxt1_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block, uint8_t alpha) +{ + int x, y; + uint32_t colors[4]; + uint16_t color0 = AV_RL16(block + 0); + uint16_t color1 = AV_RL16(block + 2); + uint32_t code = AV_RL32(block + 4); + + extract_color(colors, color0, color1, 0, alpha); + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + uint32_t pixel = colors[code & 3]; + code >>= 2; + AV_WL32(dst + x * 4, pixel); + } + dst += stride; + } +} + +/** + * Decompress one block of a DXT1 texture and store the resulting + * RGBA pixels in 'dst'. Alpha component is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt1_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + dxt1_block_internal(dst, stride, block, 255); + + return 8; +} + +/** + * Decompress one block of a DXT1 with 1-bit alpha texture and store + * the resulting RGBA pixels in 'dst'. Alpha is either fully opaque or + * fully transparent. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt1a_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + dxt1_block_internal(dst, stride, block, 0); + + return 8; +} + +static inline void dxt3_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block) +{ + int x, y; + uint32_t colors[4]; + uint16_t color0 = AV_RL16(block + 8); + uint16_t color1 = AV_RL16(block + 10); + uint32_t code = AV_RL32(block + 12); + + extract_color(colors, color0, color1, 1, 0); + + for (y = 0; y < 4; y++) { + const uint16_t alpha_code = AV_RL16(block + 2 * y); + uint8_t alpha_values[4]; + + alpha_values[0] = ((alpha_code >> 0) & 0x0F) * 17; + alpha_values[1] = ((alpha_code >> 4) & 0x0F) * 17; + alpha_values[2] = ((alpha_code >> 8) & 0x0F) * 17; + alpha_values[3] = ((alpha_code >> 12) & 0x0F) * 17; + + for (x = 0; x < 4; x++) { + uint8_t alpha = alpha_values[x]; + uint32_t pixel = colors[code & 3] | (alpha << 24); + code >>= 2; + + AV_WL32(dst + x * 4, pixel); + } + dst += stride; + } +} + +/** Convert a premultiplied alpha pixel to a straight alpha pixel. */ +static av_always_inline void premult2straight(uint8_t *src) +{ + int r = src[0]; + int g = src[1]; + int b = src[2]; + int a = src[3]; /* unchanged */ + + src[0] = (uint8_t) r * a / 255; + src[1] = (uint8_t) g * a / 255; + src[2] = (uint8_t) b * a / 255; +} + +/** + * Decompress one block of a DXT2 texture and store the resulting + * RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt2_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + + dxt3_block_internal(dst, stride, block); + + /* This format is DXT3, but returns premultiplied alpha. It needs to be + * converted because it's what lavc outputs (and swscale expects). */ + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + premult2straight(dst + x * 4 + y * stride); + + return 16; +} + +/** + * Decompress one block of a DXT3 texture and store the resulting + * RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt3_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + dxt3_block_internal(dst, stride, block); + + return 16; +} + +/** + * Decompress a BC 16x3 index block stored as + * h g f e + * d c b a + * p o n m + * l k j i + * + * Bits packed as + * | h | g | f | e | d | c | b | a | // Entry + * |765 432 107 654 321 076 543 210| // Bit + * |0000000000111111111112222222222| // Byte + * + * into 16 8-bit indices. + */ +static void decompress_indices(uint8_t *dst, const uint8_t *src) +{ + int block, i; + + for (block = 0; block < 2; block++) { + int tmp = AV_RL24(src); + + /* Unpack 8x3 bit from last 3 byte block */ + for (i = 0; i < 8; i++) + dst[i] = (tmp >> (i * 3)) & 0x7; + + src += 3; + dst += 8; + } +} + +static inline void dxt5_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block) +{ + int x, y; + uint32_t colors[4]; + uint8_t alpha_indices[16]; + uint16_t color0 = AV_RL16(block + 8); + uint16_t color1 = AV_RL16(block + 10); + uint32_t code = AV_RL32(block + 12); + uint8_t alpha0 = *(block); + uint8_t alpha1 = *(block + 1); + + decompress_indices(alpha_indices, block + 2); + + extract_color(colors, color0, color1, 1, 0); + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int alpha_code = alpha_indices[x + y * 4]; + uint32_t pixel; + uint8_t alpha; + + if (alpha_code == 0) { + alpha = alpha0; + } else if (alpha_code == 1) { + alpha = alpha1; + } else { + if (alpha0 > alpha1) { + alpha = (uint8_t) (((8 - alpha_code) * alpha0 + + (alpha_code - 1) * alpha1) / 7); + } else { + if (alpha_code == 6) { + alpha = 0; + } else if (alpha_code == 7) { + alpha = 255; + } else { + alpha = (uint8_t) (((6 - alpha_code) * alpha0 + + (alpha_code - 1) * alpha1) / 5); + } + } + } + pixel = colors[code & 3] | (alpha << 24); + code >>= 2; + AV_WL32(dst + x * 4, pixel); + } + dst += stride; + } +} + +/** + * Decompress one block of a DXT4 texture and store the resulting + * RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt4_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + + dxt5_block_internal(dst, stride, block); + + /* This format is DXT5, but returns premultiplied alpha. It needs to be + * converted because it's what lavc outputs (and swscale expects). */ + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + premult2straight(dst + x * 4 + y * stride); + + return 16; +} + +/** + * Decompress one block of a DXT5 texture and store the resulting + * RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt5_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + dxt5_block_internal(dst, stride, block); + + return 16; +} + +/** + * Convert a YCoCg buffer to RGBA. + * + * @param src input buffer. + * @param scaled variant with scaled chroma components and opaque alpha. + */ +static av_always_inline void ycocg2rgba(uint8_t *src, int scaled) +{ + int r = src[0]; + int g = src[1]; + int b = src[2]; + int a = src[3]; + + int s = scaled ? (b >> 3) + 1 : 1; + int y = a; + int co = (r - 128) / s; + int cg = (g - 128) / s; + + src[0] = av_clip_uint8(y + co - cg); + src[1] = av_clip_uint8(y + cg); + src[2] = av_clip_uint8(y - co - cg); + src[3] = scaled ? 255 : b; +} + +/** + * Decompress one block of a DXT5 texture with classic YCoCg and store + * the resulting RGBA pixels in 'dst'. Alpha component is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt5y_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + + /* This format is basically DXT5, with luma stored in alpha. + * Run a normal decompress and then reorder the components. */ + dxt5_block_internal(dst, stride, block); + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + ycocg2rgba(dst + x * 4 + y * stride, 0); + + return 16; +} + +/** + * Decompress one block of a DXT5 texture with scaled YCoCg and store + * the resulting RGBA pixels in 'dst'. Alpha component is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + + /* This format is basically DXT5, with luma stored in alpha. + * Run a normal decompress and then reorder the components. */ + dxt5_block_internal(dst, stride, block); + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + ycocg2rgba(dst + x * 4 + y * stride, 1); + + return 16; +} + +static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block, + const int *color_tab) +{ + uint8_t indices[16]; + int x, y; + + decompress_indices(indices, block + 2); + + /* Only one or two channels are stored at most, since it only used to + * compress specular (black and white) or normal (red and green) maps. + * Although the standard says to zero out unused components, many + * implementations fill all of them with the same value. */ + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int i = indices[x + y * 4]; + /* Interval expansion from [-1 1] or [0 1] to [0 255]. */ + int c = color_tab[i]; + uint32_t pixel = RGBA(c, c, c, 255); + AV_WL32(dst + x * 4 + y * stride, pixel); + } + } +} + +static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block, int sign) +{ + int color_table[8]; + int r0, r1; + + if (sign) { + /* signed data is in [-128 127] so just offset it to unsigned + * and it can be treated exactly the same */ + r0 = ((int8_t) block[0]) + 128; + r1 = ((int8_t) block[1]) + 128; + } else { + r0 = block[0]; + r1 = block[1]; + } + + color_table[0] = r0; + color_table[1] = r1; + + if (r0 > r1) { + /* 6 interpolated color values */ + color_table[2] = (6 * r0 + 1 * r1) / 7; // bit code 010 + color_table[3] = (5 * r0 + 2 * r1) / 7; // bit code 011 + color_table[4] = (4 * r0 + 3 * r1) / 7; // bit code 100 + color_table[5] = (3 * r0 + 4 * r1) / 7; // bit code 101 + color_table[6] = (2 * r0 + 5 * r1) / 7; // bit code 110 + color_table[7] = (1 * r0 + 6 * r1) / 7; // bit code 111 + } else { + /* 4 interpolated color values */ + color_table[2] = (4 * r0 + 1 * r1) / 5; // bit code 010 + color_table[3] = (3 * r0 + 2 * r1) / 5; // bit code 011 + color_table[4] = (2 * r0 + 3 * r1) / 5; // bit code 100 + color_table[5] = (1 * r0 + 4 * r1) / 5; // bit code 101 + color_table[6] = 0; /* min range */ // bit code 110 + color_table[7] = 255; /* max range */ // bit code 111 + } + + rgtc_block_internal(dst, stride, block, color_table); +} + +/** + * Decompress one block of a RGRC1 texture with signed components + * and store the resulting RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc1_block_internal(dst, stride, block, 1); + + return 8; +} + +/** + * Decompress one block of a RGRC1 texture with unsigned components + * and store the resulting RGBA pixels in 'dst'. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc1u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc1_block_internal(dst, stride, block, 0); + + return 8; +} + +static inline void rgtc2_block_internal(uint8_t *dst, ptrdiff_t stride, + const uint8_t *block, int sign) +{ + /* 4x4 block containing 4 component pixels. */ + uint8_t c0[4 * 4 * 4]; + uint8_t c1[4 * 4 * 4]; + int x, y; + + /* Decompress the two channels separately and interleave them afterwards. */ + rgtc1_block_internal(c0, 16, block, sign); + rgtc1_block_internal(c1, 16, block + 8, sign); + + /* B is rebuilt exactly like a normal map. */ + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + uint8_t *p = dst + x * 4 + y * stride; + int r = c0[x * 4 + y * 16]; + int g = c1[x * 4 + y * 16]; + int b = 127; + + int d = (255 * 255 - r * r - g * g) / 2; + if (d > 0) + b = rint(sqrtf(d)); + + p[0] = r; + p[1] = g; + p[2] = b; + p[3] = 255; + } + } +} + +/** + * Decompress one block of a RGRC2 texture with signed components + * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc2s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc2_block_internal(dst, stride, block, 1); + + return 16; +} + +/** + * Decompress one block of a RGRC2 texture with unsigned components + * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc2u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc2_block_internal(dst, stride, block, 0); + + return 16; +} + +/** + * Decompress one block of a 3Dc texture with unsigned components + * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int dxn3dc_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + rgtc2_block_internal(dst, stride, block, 0); + + /* This is the 3Dc variant of RGTC2, with swapped R and G. */ + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + uint8_t *p = dst + x * 4 + y * stride; + FFSWAP(uint8_t, p[0], p[1]); + } + } + + return 16; +} + +av_cold void ff_texturedsp_init(TextureDSPContext *c) +{ + c->dxt1_block = dxt1_block; + c->dxt1a_block = dxt1a_block; + c->dxt2_block = dxt2_block; + c->dxt3_block = dxt3_block; + c->dxt4_block = dxt4_block; + c->dxt5_block = dxt5_block; + c->dxt5y_block = dxt5y_block; + c->dxt5ys_block = dxt5ys_block; + c->rgtc1s_block = rgtc1s_block; + c->rgtc1u_block = rgtc1u_block; + c->rgtc2s_block = rgtc2s_block; + c->rgtc2u_block = rgtc2u_block; + c->dxn3dc_block = dxn3dc_block; +} diff --git a/libavcodec/texturedsp.h b/libavcodec/texturedsp.h new file mode 100644 index 0000000..fcbe7a4 --- /dev/null +++ b/libavcodec/texturedsp.h @@ -0,0 +1,64 @@ +/* + * Texture block module + * Copyright (C) 2015 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Texture block (4x4) module + * + * References: + * https://www.opengl.org/wiki/S3_Texture_Compression + * https://www.opengl.org/wiki/Red_Green_Texture_Compression + * https://msdn.microsoft.com/en-us/library/bb694531%28v=vs.85%29.aspx + * + * All functions return how much data has been written or read. + * + * Pixel input or output format is always AV_PIX_FMT_RGBA. + */ + +#ifndef AVCODEC_TEXTUREDSP_H +#define AVCODEC_TEXTUREDSP_H + +#include +#include + +#define TEXTURE_BLOCK_W 4 +#define TEXTURE_BLOCK_H 4 + +typedef struct TextureDSPContext { + int (*dxt1_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt1a_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt2_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt3_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt4_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5y_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5ys_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc2s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc2u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxn3dc_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); +} TextureDSPContext; + +void ff_texturedsp_init(TextureDSPContext *c); +void ff_texturedspenc_init(TextureDSPContext *c); + +#endif /* AVCODEC_TEXTUREDSP_H */ diff --git a/libavcodec/texturedspenc.c b/libavcodec/texturedspenc.c new file mode 100644 index 0000000..27aaa78 --- /dev/null +++ b/libavcodec/texturedspenc.c @@ -0,0 +1,655 @@ +/* + * Texture block compression + * Copyright (C) 2015 Vittorio Giovara + * Based on public domain code by Fabian Giesen, Sean Barrett and Yann Collet. + * + * This file is part of Libav + * + * 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 +#include + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "texturedsp.h" + +static const uint8_t expand5[32] = { + 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, + 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, + 198, 206, 214, 222, 231, 239, 247, 255, +}; + +static const uint8_t expand6[64] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 60, 65, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, + 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, + 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, + 243, 247, 251, 255, +}; + +static const uint8_t match5[256][2] = { + { 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, + { 1, 0 }, { 1, 1 }, { 1, 1 }, { 2, 0 }, { 2, 0 }, { 0, 4 }, + { 2, 1 }, { 2, 1 }, { 2, 1 }, { 3, 0 }, { 3, 0 }, { 3, 0 }, + { 3, 1 }, { 1, 5 }, { 3, 2 }, { 3, 2 }, { 4, 0 }, { 4, 0 }, + { 4, 1 }, { 4, 1 }, { 4, 2 }, { 4, 2 }, { 4, 2 }, { 3, 5 }, + { 5, 1 }, { 5, 1 }, { 5, 2 }, { 4, 4 }, { 5, 3 }, { 5, 3 }, + { 5, 3 }, { 6, 2 }, { 6, 2 }, { 6, 2 }, { 6, 3 }, { 5, 5 }, + { 6, 4 }, { 6, 4 }, { 4, 8 }, { 7, 3 }, { 7, 3 }, { 7, 3 }, + { 7, 4 }, { 7, 4 }, { 7, 4 }, { 7, 5 }, { 5, 9 }, { 7, 6 }, + { 7, 6 }, { 8, 4 }, { 8, 4 }, { 8, 5 }, { 8, 5 }, { 8, 6 }, + { 8, 6 }, { 8, 6 }, { 7, 9 }, { 9, 5 }, { 9, 5 }, { 9, 6 }, + { 8, 8 }, { 9, 7 }, { 9, 7 }, { 9, 7 }, { 10, 6 }, { 10, 6 }, + { 10, 6 }, { 10, 7 }, { 9, 9 }, { 10, 8 }, { 10, 8 }, { 8, 12 }, + { 11, 7 }, { 11, 7 }, { 11, 7 }, { 11, 8 }, { 11, 8 }, { 11, 8 }, + { 11, 9 }, { 9, 13 }, { 11, 10 }, { 11, 10 }, { 12, 8 }, { 12, 8 }, + { 12, 9 }, { 12, 9 }, { 12, 10 }, { 12, 10 }, { 12, 10 }, { 11, 13 }, + { 13, 9 }, { 13, 9 }, { 13, 10 }, { 12, 12 }, { 13, 11 }, { 13, 11 }, + { 13, 11 }, { 14, 10 }, { 14, 10 }, { 14, 10 }, { 14, 11 }, { 13, 13 }, + { 14, 12 }, { 14, 12 }, { 12, 16 }, { 15, 11 }, { 15, 11 }, { 15, 11 }, + { 15, 12 }, { 15, 12 }, { 15, 12 }, { 15, 13 }, { 13, 17 }, { 15, 14 }, + { 15, 14 }, { 16, 12 }, { 16, 12 }, { 16, 13 }, { 16, 13 }, { 16, 14 }, + { 16, 14 }, { 16, 14 }, { 15, 17 }, { 17, 13 }, { 17, 13 }, { 17, 14 }, + { 16, 16 }, { 17, 15 }, { 17, 15 }, { 17, 15 }, { 18, 14 }, { 18, 14 }, + { 18, 14 }, { 18, 15 }, { 17, 17 }, { 18, 16 }, { 18, 16 }, { 16, 20 }, + { 19, 15 }, { 19, 15 }, { 19, 15 }, { 19, 16 }, { 19, 16 }, { 19, 16 }, + { 19, 17 }, { 17, 21 }, { 19, 18 }, { 19, 18 }, { 20, 16 }, { 20, 16 }, + { 20, 17 }, { 20, 17 }, { 20, 18 }, { 20, 18 }, { 20, 18 }, { 19, 21 }, + { 21, 17 }, { 21, 17 }, { 21, 18 }, { 20, 20 }, { 21, 19 }, { 21, 19 }, + { 21, 19 }, { 22, 18 }, { 22, 18 }, { 22, 18 }, { 22, 19 }, { 21, 21 }, + { 22, 20 }, { 22, 20 }, { 20, 24 }, { 23, 19 }, { 23, 19 }, { 23, 19 }, + { 23, 20 }, { 23, 20 }, { 23, 20 }, { 23, 21 }, { 21, 25 }, { 23, 22 }, + { 23, 22 }, { 24, 20 }, { 24, 20 }, { 24, 21 }, { 24, 21 }, { 24, 22 }, + { 24, 22 }, { 24, 22 }, { 23, 25 }, { 25, 21 }, { 25, 21 }, { 25, 22 }, + { 24, 24 }, { 25, 23 }, { 25, 23 }, { 25, 23 }, { 26, 22 }, { 26, 22 }, + { 26, 22 }, { 26, 23 }, { 25, 25 }, { 26, 24 }, { 26, 24 }, { 24, 28 }, + { 27, 23 }, { 27, 23 }, { 27, 23 }, { 27, 24 }, { 27, 24 }, { 27, 24 }, + { 27, 25 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 28, 24 }, + { 28, 25 }, { 28, 25 }, { 28, 26 }, { 28, 26 }, { 28, 26 }, { 27, 29 }, + { 29, 25 }, { 29, 25 }, { 29, 26 }, { 28, 28 }, { 29, 27 }, { 29, 27 }, + { 29, 27 }, { 30, 26 }, { 30, 26 }, { 30, 26 }, { 30, 27 }, { 29, 29 }, + { 30, 28 }, { 30, 28 }, { 30, 28 }, { 31, 27 }, { 31, 27 }, { 31, 27 }, + { 31, 28 }, { 31, 28 }, { 31, 28 }, { 31, 29 }, { 31, 29 }, { 31, 30 }, + { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 }, +}; + +static const uint8_t match6[256][2] = { + { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, { 2, 0 }, + { 2, 1 }, { 3, 0 }, { 3, 0 }, { 3, 1 }, { 4, 0 }, { 4, 0 }, + { 4, 1 }, { 5, 0 }, { 5, 1 }, { 6, 0 }, { 6, 0 }, { 6, 1 }, + { 7, 0 }, { 7, 0 }, { 7, 1 }, { 8, 0 }, { 8, 1 }, { 8, 1 }, + { 8, 2 }, { 9, 1 }, { 9, 2 }, { 9, 2 }, { 9, 3 }, { 10, 2 }, + { 10, 3 }, { 10, 3 }, { 10, 4 }, { 11, 3 }, { 11, 4 }, { 11, 4 }, + { 11, 5 }, { 12, 4 }, { 12, 5 }, { 12, 5 }, { 12, 6 }, { 13, 5 }, + { 13, 6 }, { 8, 16 }, { 13, 7 }, { 14, 6 }, { 14, 7 }, { 9, 17 }, + { 14, 8 }, { 15, 7 }, { 15, 8 }, { 11, 16 }, { 15, 9 }, { 15, 10 }, + { 16, 8 }, { 16, 9 }, { 16, 10 }, { 15, 13 }, { 17, 9 }, { 17, 10 }, + { 17, 11 }, { 15, 16 }, { 18, 10 }, { 18, 11 }, { 18, 12 }, { 16, 16 }, + { 19, 11 }, { 19, 12 }, { 19, 13 }, { 17, 17 }, { 20, 12 }, { 20, 13 }, + { 20, 14 }, { 19, 16 }, { 21, 13 }, { 21, 14 }, { 21, 15 }, { 20, 17 }, + { 22, 14 }, { 22, 15 }, { 25, 10 }, { 22, 16 }, { 23, 15 }, { 23, 16 }, + { 26, 11 }, { 23, 17 }, { 24, 16 }, { 24, 17 }, { 27, 12 }, { 24, 18 }, + { 25, 17 }, { 25, 18 }, { 28, 13 }, { 25, 19 }, { 26, 18 }, { 26, 19 }, + { 29, 14 }, { 26, 20 }, { 27, 19 }, { 27, 20 }, { 30, 15 }, { 27, 21 }, + { 28, 20 }, { 28, 21 }, { 28, 21 }, { 28, 22 }, { 29, 21 }, { 29, 22 }, + { 24, 32 }, { 29, 23 }, { 30, 22 }, { 30, 23 }, { 25, 33 }, { 30, 24 }, + { 31, 23 }, { 31, 24 }, { 27, 32 }, { 31, 25 }, { 31, 26 }, { 32, 24 }, + { 32, 25 }, { 32, 26 }, { 31, 29 }, { 33, 25 }, { 33, 26 }, { 33, 27 }, + { 31, 32 }, { 34, 26 }, { 34, 27 }, { 34, 28 }, { 32, 32 }, { 35, 27 }, + { 35, 28 }, { 35, 29 }, { 33, 33 }, { 36, 28 }, { 36, 29 }, { 36, 30 }, + { 35, 32 }, { 37, 29 }, { 37, 30 }, { 37, 31 }, { 36, 33 }, { 38, 30 }, + { 38, 31 }, { 41, 26 }, { 38, 32 }, { 39, 31 }, { 39, 32 }, { 42, 27 }, + { 39, 33 }, { 40, 32 }, { 40, 33 }, { 43, 28 }, { 40, 34 }, { 41, 33 }, + { 41, 34 }, { 44, 29 }, { 41, 35 }, { 42, 34 }, { 42, 35 }, { 45, 30 }, + { 42, 36 }, { 43, 35 }, { 43, 36 }, { 46, 31 }, { 43, 37 }, { 44, 36 }, + { 44, 37 }, { 44, 37 }, { 44, 38 }, { 45, 37 }, { 45, 38 }, { 40, 48 }, + { 45, 39 }, { 46, 38 }, { 46, 39 }, { 41, 49 }, { 46, 40 }, { 47, 39 }, + { 47, 40 }, { 43, 48 }, { 47, 41 }, { 47, 42 }, { 48, 40 }, { 48, 41 }, + { 48, 42 }, { 47, 45 }, { 49, 41 }, { 49, 42 }, { 49, 43 }, { 47, 48 }, + { 50, 42 }, { 50, 43 }, { 50, 44 }, { 48, 48 }, { 51, 43 }, { 51, 44 }, + { 51, 45 }, { 49, 49 }, { 52, 44 }, { 52, 45 }, { 52, 46 }, { 51, 48 }, + { 53, 45 }, { 53, 46 }, { 53, 47 }, { 52, 49 }, { 54, 46 }, { 54, 47 }, + { 57, 42 }, { 54, 48 }, { 55, 47 }, { 55, 48 }, { 58, 43 }, { 55, 49 }, + { 56, 48 }, { 56, 49 }, { 59, 44 }, { 56, 50 }, { 57, 49 }, { 57, 50 }, + { 60, 45 }, { 57, 51 }, { 58, 50 }, { 58, 51 }, { 61, 46 }, { 58, 52 }, + { 59, 51 }, { 59, 52 }, { 62, 47 }, { 59, 53 }, { 60, 52 }, { 60, 53 }, + { 60, 53 }, { 60, 54 }, { 61, 53 }, { 61, 54 }, { 61, 54 }, { 61, 55 }, + { 62, 54 }, { 62, 55 }, { 62, 55 }, { 62, 56 }, { 63, 55 }, { 63, 56 }, + { 63, 56 }, { 63, 57 }, { 63, 58 }, { 63, 59 }, { 63, 59 }, { 63, 60 }, + { 63, 61 }, { 63, 62 }, { 63, 62 }, { 63, 63 }, +}; + +/* Multiplication over 8 bit emulation */ +#define mul8(a, b) (a * b + 128 + ((a * b + 128) >> 8)) >> 8 + +/* Conversion from rgb24 to rgb565 */ +#define rgb2rgb565(r, g, b) \ + (mul8(r, 31) << 11) | (mul8(g, 63) << 5) | (mul8(b, 31) << 0) + +/* Linear interpolation at 1/3 point between a and b */ +#define lerp13(a, b) (2 * a + b) / 3 + +/* Linear interpolation on an RGB pixel */ +static inline void lerp13rgb(uint8_t *out, uint8_t *p1, uint8_t *p2) +{ + out[0] = lerp13(p1[0], p2[0]); + out[1] = lerp13(p1[1], p2[1]); + out[2] = lerp13(p1[2], p2[2]); +} + +/* Conversion from rgb565 to rgb24 */ +static inline void rgb5652rgb(uint8_t *out, uint16_t v) +{ + int rv = (v & 0xf800) >> 11; + int gv = (v & 0x07e0) >> 5; + int bv = (v & 0x001f) >> 0; + + out[0] = expand5[rv]; + out[1] = expand6[gv]; + out[2] = expand5[bv]; + out[3] = 0; +} + +/* Color matching function */ +static unsigned int match_colors(const uint8_t *block, ptrdiff_t stride, + uint16_t c0, uint16_t c1) +{ + uint32_t mask = 0; + int dirr, dirg, dirb; + int dots[16]; + int stops[4]; + int x, y, k = 0; + int c0_point, half_point, c3_point; + uint8_t color[16]; + static const int indexMap[8] = { + 0 << 30, 2 << 30, 0 << 30, 2 << 30, + 3 << 30, 3 << 30, 1 << 30, 1 << 30, + }; + + /* Fill color and compute direction for each component */ + rgb5652rgb(color + 0, c0); + rgb5652rgb(color + 4, c1); + lerp13rgb(color + 8, color + 0, color + 4); + lerp13rgb(color + 12, color + 4, color + 0); + + dirr = color[0 * 4 + 0] - color[1 * 4 + 0]; + dirg = color[0 * 4 + 1] - color[1 * 4 + 1]; + dirb = color[0 * 4 + 2] - color[1 * 4 + 2]; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) + dots[k++] = block[0 + x * 4 + y * stride] * dirr + + block[1 + x * 4 + y * stride] * dirg + + block[2 + x * 4 + y * stride] * dirb; + + stops[y] = color[0 + y * 4] * dirr + + color[1 + y * 4] * dirg + + color[2 + y * 4] * dirb; + } + + /* Think of the colors as arranged on a line; project point onto that line, + * then choose next color out of available ones. we compute the crossover + * points for 'best color in top half'/'best in bottom half' and then + * the same inside that subinterval. + * + * Relying on this 1d approximation isn't always optimal in terms of + * Euclidean distance, but it's very close and a lot faster. + * + * http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html */ + c0_point = (stops[1] + stops[3]) >> 1; + half_point = (stops[3] + stops[2]) >> 1; + c3_point = (stops[2] + stops[0]) >> 1; + + for (x = 0; x < 16; x++) { + int dot = dots[x]; + int bits = (dot < half_point ? 4 : 0) | + (dot < c0_point ? 2 : 0) | + (dot < c3_point ? 1 : 0); + + mask >>= 2; + mask |= indexMap[bits]; + } + + return mask; +} + +/* Color optimization function */ +static void optimize_colors(const uint8_t *block, ptrdiff_t stride, + uint16_t *pmax16, uint16_t *pmin16) +{ + const uint8_t *minp; + const uint8_t *maxp; + const int iter_power = 4; + double magn; + int v_r, v_g, v_b; + float covf[6], vfr, vfg, vfb; + int mind, maxd; + int cov[6] = { 0 }; + int mu[3], min[3], max[3]; + int ch, iter, x, y; + + /* Determine color distribution */ + for (ch = 0; ch < 3; ch++) { + const uint8_t *bp = &block[ch]; + int muv, minv, maxv; + + muv = minv = maxv = bp[0]; + for (y = 0; y < 4; y++) { + for (x = 4; x < 4; x += 4) { + muv += bp[x * 4 + y * stride]; + if (bp[x] < minv) + minv = bp[x * 4 + y * stride]; + else if (bp[x] > maxv) + maxv = bp[x * 4 + y * stride]; + } + } + + mu[ch] = (muv + 8) >> 4; + min[ch] = minv; + max[ch] = maxv; + } + + /* Determine covariance matrix */ + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int r = block[x * 4 + stride * y + 0] - mu[0]; + int g = block[x * 4 + stride * y + 1] - mu[1]; + int b = block[x * 4 + stride * y + 2] - mu[2]; + + cov[0] += r * r; + cov[1] += r * g; + cov[2] += r * b; + cov[3] += g * g; + cov[4] += g * b; + cov[5] += b * b; + } + } + + /* Convert covariance matrix to float, find principal axis via power iter */ + for (x = 0; x < 6; x++) + covf[x] = cov[x] / 255.0f; + + vfr = (float) (max[0] - min[0]); + vfg = (float) (max[1] - min[1]); + vfb = (float) (max[2] - min[2]); + + for (iter = 0; iter < iter_power; iter++) { + float r = vfr * covf[0] + vfg * covf[1] + vfb * covf[2]; + float g = vfr * covf[1] + vfg * covf[3] + vfb * covf[4]; + float b = vfr * covf[2] + vfg * covf[4] + vfb * covf[5]; + + vfr = r; + vfg = g; + vfb = b; + } + + magn = fabs(vfr); + if (fabs(vfg) > magn) + magn = fabs(vfg); + if (fabs(vfb) > magn) + magn = fabs(vfb); + + /* if magnitude is too small, default to luminance */ + if (magn < 4.0f) { + /* JPEG YCbCr luma coefs, scaled by 1000 */ + v_r = 299; + v_g = 587; + v_b = 114; + } else { + magn = 512.0 / magn; + v_r = (int) (vfr * magn); + v_g = (int) (vfg * magn); + v_b = (int) (vfb * magn); + } + + /* Pick colors at extreme points */ + mind = maxd = block[0] * v_r + block[1] * v_g + block[2] * v_b; + minp = maxp = block; + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int dot = block[x * 4 + y * stride + 0] * v_r + + block[x * 4 + y * stride + 1] * v_g + + block[x * 4 + y * stride + 2] * v_b; + + if (dot < mind) { + mind = dot; + minp = block + x * 4 + y * stride; + } else if (dot > maxd) { + maxd = dot; + maxp = block + x * 4 + y * stride; + } + } + } + + *pmax16 = rgb2rgb565(maxp[0], maxp[1], maxp[2]); + *pmin16 = rgb2rgb565(minp[0], minp[1], minp[2]); +} + +/* Try to optimize colors to suit block contents better, by solving + * a least squares system via normal equations + Cramer's rule. */ +static int refine_colors(const uint8_t *block, ptrdiff_t stride, + uint16_t *pmax16, uint16_t *pmin16, uint32_t mask) +{ + uint32_t cm = mask; + uint16_t oldMin = *pmin16; + uint16_t oldMax = *pmax16; + uint16_t min16, max16; + int x, y; + + /* Additional magic to save a lot of multiplies in the accumulating loop. + * The tables contain precomputed products of weights for least squares + * system, accumulated inside one 32-bit register */ + static const int w1tab[4] = { 3, 0, 2, 1 }; + static const int prods[4] = { 0x090000, 0x000900, 0x040102, 0x010402 }; + + /* Check if all pixels have the same index */ + if ((mask ^ (mask << 2)) < 4) { + /* If so, linear system would be singular; solve using optimal + * single-color match on average color. */ + int r = 8, g = 8, b = 8; + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + r += block[0 + x * 4 + y * stride]; + g += block[1 + x * 4 + y * stride]; + b += block[2 + x * 4 + y * stride]; + } + } + + r >>= 4; + g >>= 4; + b >>= 4; + + max16 = (match5[r][0] << 11) | (match6[g][0] << 5) | match5[b][0]; + min16 = (match5[r][1] << 11) | (match6[g][1] << 5) | match5[b][1]; + } else { + float fr, fg, fb; + int at1_r = 0, at1_g = 0, at1_b = 0; + int at2_r = 0, at2_g = 0, at2_b = 0; + int akku = 0; + int xx, xy, yy; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int step = cm & 3; + int w1 = w1tab[step]; + int r = block[0 + x * 4 + y * stride]; + int g = block[1 + x * 4 + y * stride]; + int b = block[2 + x * 4 + y * stride]; + + akku += prods[step]; + at1_r += w1 * r; + at1_g += w1 * g; + at1_b += w1 * b; + at2_r += r; + at2_g += g; + at2_b += b; + + cm >>= 2; + } + } + + at2_r = 3 * at2_r - at1_r; + at2_g = 3 * at2_g - at1_g; + at2_b = 3 * at2_b - at1_b; + + /* Extract solutions and decide solvability */ + xx = akku >> 16; + yy = (akku >> 8) & 0xFF; + xy = (akku >> 0) & 0xFF; + + fr = 3.0f * 31.0f / 255.0f / (xx * yy - xy * xy); + fg = fr * 63.0f / 31.0f; + fb = fr; + + /* Solve */ + max16 = av_clip_uintp2((at1_r * yy - at2_r * xy) * fr + 0.5f, 5) << 11; + max16 |= av_clip_uintp2((at1_g * yy - at2_g * xy) * fg + 0.5f, 6) << 5; + max16 |= av_clip_uintp2((at1_b * yy - at2_b * xy) * fb + 0.5f, 5) << 0; + + min16 = av_clip_uintp2((at2_r * xx - at1_r * xy) * fr + 0.5f, 5) << 11; + min16 |= av_clip_uintp2((at2_g * xx - at1_g * xy) * fg + 0.5f, 6) << 5; + min16 |= av_clip_uintp2((at2_b * xx - at1_b * xy) * fb + 0.5f, 5) << 0; + } + + *pmin16 = min16; + *pmax16 = max16; + return oldMin != min16 || oldMax != max16; +} + +/* Check if input block is a constant color */ +static int constant_color(const uint8_t *block, ptrdiff_t stride) +{ + int x, y; + uint32_t first = AV_RL32(block); + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + if (first != AV_RL32(block + x * 4 + y * stride)) + return 0; + return 1; +} + +/* Main color compression function */ +static void compress_color(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + uint32_t mask; + uint16_t max16, min16; + int constant = constant_color(block, stride); + + /* Constant color will load values from tables */ + if (constant) { + int r = block[0]; + int g = block[1]; + int b = block[2]; + mask = 0xAAAAAAAA; + max16 = (match5[r][0] << 11) | (match6[g][0] << 5) | match5[b][0]; + min16 = (match5[r][1] << 11) | (match6[g][1] << 5) | match5[b][1]; + } else { + int refine; + + /* Otherwise find pca and map along principal axis */ + optimize_colors(block, stride, &max16, &min16); + if (max16 != min16) + mask = match_colors(block, stride, max16, min16); + else + mask = 0; + + /* One pass refinement */ + refine = refine_colors(block, stride, &max16, &min16, mask); + if (refine) { + if (max16 != min16) + mask = match_colors(block, stride, max16, min16); + else + mask = 0; + } + } + + /* Finally write the color block */ + if (max16 < min16) { + FFSWAP(uint16_t, min16, max16); + mask ^= 0x55555555; + } + + AV_WL16(dst + 0, max16); + AV_WL16(dst + 2, min16); + AV_WL32(dst + 4, mask); +} + +/* Alpha compression function */ +static void compress_alpha(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + int dist, bias, dist4, dist2; + int mn, mx; + int bits = 0; + int mask = 0; + + memset(dst, 0, 8); + + /* Find min/max color */ + mn = mx = block[3]; + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int val = block[3 + x * 4 + y * stride]; + if (val < mn) + mn = val; + else if (val > mx) + mx = val; + } + } + + /* Encode them */ + dst[0] = (uint8_t) mx; + dst[1] = (uint8_t) mn; + dst += 2; + + /* Mono-alpha shortcut */ + if (mn == mx) + return; + + /* Determine bias and emit color indices. + * Given the choice of mx/mn, these indices are optimal: + * fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination */ + dist = mx - mn; + + dist4 = dist * 4; + dist2 = dist * 2; + if (dist < 8) + bias = dist - 1 - mn * 7; + else + bias = dist / 2 + 2 - mn * 7; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int alp = block[3 + x * 4 + y * stride] * 7 + bias; + int ind, tmp; + + /* This is a "linear scale" lerp factor between 0 (val=min) + * and 7 (val=max) to select index. */ + tmp = (alp >= dist4) ? -1 : 0; + ind = tmp & 4; + alp -= dist4 & tmp; + tmp = (alp >= dist2) ? -1 : 0; + ind += tmp & 2; + alp -= dist2 & tmp; + ind += (alp >= dist); + + /* Turn linear scale into DXT index (0/1 are extreme points) */ + ind = -ind & 7; + ind ^= (2 > ind); + + /* Write index */ + mask |= ind << bits; + bits += 3; + if (bits >= 8) { + *dst++ = mask; + mask >>= 8; + bits -= 8; + } + } + } +} + +/** + * Convert a RGBA buffer to unscaled YCoCg. + * Scale is usually introduced to avoid banding over a certain range of colors, + * but this version of the algorithm does not introduce it as much as other + * implementations, allowing for a simpler and faster conversion. + */ +static void rgba2ycocg(uint8_t *dst, const uint8_t *pixel) +{ + int r = pixel[0]; + int g = (pixel[1] + 1) >> 1; + int b = pixel[2]; + int t = (2 + r + b) >> 2; + + dst[0] = av_clip_uint8(128 + ((r - b + 1) >> 1)); /* Co */ + dst[1] = av_clip_uint8(128 + g - t); /* Cg */ + dst[2] = 0; + dst[3] = av_clip_uint8(g + t); /* Y */ +} + +/** + * Compress one block of RGBA pixels in a DXT1 texture and store the + * resulting bytes in 'dst'. Alpha is not preserved. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to compress. + * @return how much texture data has been written. + */ +static int dxt1_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + compress_color(dst, stride, block); + + return 8; +} + +/** + * Compress one block of RGBA pixels in a DXT5 texture and store the + * resulting bytes in 'dst'. Alpha is preserved. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to compress. + * @return how much texture data has been written. + */ +static int dxt5_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + compress_alpha(dst, stride, block); + compress_color(dst + 8, stride, block); + + return 16; +} + +/** + * Compress one block of RGBA pixels in a DXT5-YCoCg texture and store the + * resulting bytes in 'dst'. Alpha is not preserved. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to compress. + * @return how much texture data has been written. + */ +static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + int x, y; + uint8_t reorder[64]; + + /* Reorder the components and then run a normal DXT5 compression. */ + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + rgba2ycocg(reorder + x * 4 + y * 16, block + x * 4 + y * stride); + + compress_alpha(dst + 0, 16, reorder); + compress_color(dst + 8, 16, reorder); + + return 16; +} + +av_cold void ff_texturedspenc_init(TextureDSPContext *c) +{ + c->dxt1_block = dxt1_block; + c->dxt5_block = dxt5_block; + c->dxt5ys_block = dxt5ys_block; +} diff --git a/libavcodec/tiertexseqv.c b/libavcodec/tiertexseqv.c index 33b2579..8ca7edf 100644 --- a/libavcodec/tiertexseqv.c +++ b/libavcodec/tiertexseqv.c @@ -24,8 +24,8 @@ * Tiertex Limited SEQ video decoder */ -#include "avcodec.h" #define BITSTREAM_READER_LE +#include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -267,5 +267,5 @@ AVCodec ff_tiertexseqvideo_decoder = { .init = seqvideo_decode_init, .close = seqvideo_decode_end, .decode = seqvideo_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4732e67..97b9d6f 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -52,6 +52,7 @@ typedef struct TiffContext { int le; enum TiffCompr compr; enum TiffPhotometric photometric; + int planar; int fax_opts; int predictor; int fill_order; @@ -140,7 +141,7 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, { int i, ret = 0; uint8_t *src2 = av_malloc((unsigned)size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!src2) { av_log(s->avctx, AV_LOG_ERROR, @@ -158,7 +159,7 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, for (i = 0; i < size; i++) src2[i] = ff_reverse[src[i]]; } - memset(src2 + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(src2 + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, s->compr, s->fax_opts); av_free(src2); @@ -172,6 +173,9 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, int c, line, pixels, code, ret; int width = ((s->width * s->bpp) + 7) >> 3; + if (s->planar) + width /= s->bppcount; + if (size <= 0) return AVERROR_INVALIDDATA; @@ -256,7 +260,7 @@ static int init_image(TiffContext *s, AVFrame *frame) return AVERROR_INVALIDDATA; } - switch (s->bpp * 10 + s->bppcount) { + switch (s->planar * 1000 + s->bpp * 10 + s->bppcount) { case 11: s->avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; break; @@ -281,6 +285,21 @@ static int init_image(TiffContext *s, AVFrame *frame) case 483: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; break; + case 644: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE; + break; + case 1243: + s->avctx->pix_fmt = AV_PIX_FMT_GBRP; + break; + case 1324: + s->avctx->pix_fmt = AV_PIX_FMT_GBRAP; + break; + case 1483: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GBRP16LE : AV_PIX_FMT_GBRP16BE; + break; + case 1644: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GBRAP16LE : AV_PIX_FMT_GBRAP16BE; + break; default: av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, bppcount=%d)\n", @@ -512,10 +531,7 @@ static int tiff_decode_tag(TiffContext *s) break; } case TIFF_PLANAR: - if (value == 2) { - avpriv_report_missing_feature(s->avctx, "Planar format"); - return AVERROR_PATCHWELCOME; - } + s->planar = value == 2; break; case TIFF_T4OPTIONS: if (s->compr == TIFF_G3) @@ -543,7 +559,7 @@ static int decode_frame(AVCodecContext *avctx, TiffContext *const s = avctx->priv_data; AVFrame *const p = data; unsigned off; - int id, le, ret; + int id, le, ret, plane, planes; int i, j, entries, stride; unsigned soff, ssize; uint8_t *dst; @@ -601,8 +617,6 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); s->stripsize = avpkt->size - s->stripoff; } - stride = p->linesize[0]; - dst = p->data[0]; if (s->stripsizesoff) { if (s->stripsizesoff >= avpkt->size) @@ -617,62 +631,77 @@ static int decode_frame(AVCodecContext *avctx, avpkt->size - s->strippos); } - for (i = 0; i < s->height; i += s->rps) { - if (s->stripsizesoff) - ssize = tget(&stripsizes, s->sstype, le); - else - ssize = s->stripsize; - - if (s->strippos) - soff = tget(&stripdata, s->sot, le); - else - soff = s->stripoff; - - if (soff > avpkt->size || ssize > avpkt->size - soff) { - av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); - return AVERROR_INVALIDDATA; - } - if ((ret = tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize, - FFMIN(s->rps, s->height - i))) < 0) { - if (avctx->err_recognition & AV_EF_EXPLODE) - return ret; - break; - } - dst += s->rps * stride; - } - if (s->predictor == 2) { - dst = p->data[0]; - soff = s->bpp >> 3; - ssize = s->width * soff; - if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE) { - for (i = 0; i < s->height; i++) { - for (j = soff; j < ssize; j += 2) - AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); - dst += stride; + planes = s->planar ? s->bppcount : 1; + for (plane = 0; plane < planes; plane++) { + stride = p->linesize[plane]; + dst = p->data[plane]; + for (i = 0; i < s->height; i += s->rps) { + if (s->stripsizesoff) + ssize = tget(&stripsizes, s->sstype, le); + else + ssize = s->stripsize; + + if (s->strippos) + soff = tget(&stripdata, s->sot, le); + else + soff = s->stripoff; + + if (soff > avpkt->size || ssize > avpkt->size - soff) { + av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); + return AVERROR_INVALIDDATA; } - } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48BE) { - for (i = 0; i < s->height; i++) { - for (j = soff; j < ssize; j += 2) - AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); - dst += stride; + if ((ret = tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize, + FFMIN(s->rps, s->height - i))) < 0) { + if (avctx->err_recognition & AV_EF_EXPLODE) + return ret; + break; } - } else { + dst += s->rps * stride; + } + if (s->predictor == 2) { + dst = p->data[plane]; + soff = s->bpp >> 3; + ssize = s->width * soff; + if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBA64LE) { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j += 2) + AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); + dst += stride; + } + } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48BE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j += 2) + AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); + dst += stride; + } + } else { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j++) + dst[j] += dst[j - soff]; + dst += stride; + } + } + } + + if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { + dst = p->data[plane]; for (i = 0; i < s->height; i++) { - for (j = soff; j < ssize; j++) - dst[j] += dst[j - soff]; + for (j = 0; j < stride; j++) + dst[j] = 255 - dst[j]; dst += stride; } } } - if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { - dst = p->data[0]; - for (i = 0; i < s->height; i++) { - for (j = 0; j < p->linesize[0]; j++) - dst[j] = 255 - dst[j]; - dst += stride; - } + if (s->planar && s->bppcount > 2) { + FFSWAP(uint8_t*, p->data[0], p->data[2]); + FFSWAP(int, p->linesize[0], p->linesize[2]); + FFSWAP(uint8_t*, p->data[0], p->data[1]); + FFSWAP(int, p->linesize[0], p->linesize[1]); } + *got_frame = 1; return avpkt->size; @@ -708,5 +737,5 @@ AVCodec ff_tiff_decoder = { .init = tiff_init, .close = tiff_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c index 6c2cde9..8791c54 100644 --- a/libavcodec/tiffenc.c +++ b/libavcodec/tiffenc.c @@ -153,7 +153,8 @@ static int add_entry1(TiffEncoderContext *s, * @param dst Output buffer * @param n Size of input buffer * @param compr Compression method - * @return Number of output bytes. If an output error is encountered, -1 returned + * @return Number of output bytes. If an output error is encountered, a negative + * value corresponding to an AVERROR error code is returned. */ static int encode_strip(TiffEncoderContext *s, const int8_t *src, uint8_t *dst, int n, int compr) @@ -166,14 +167,14 @@ static int encode_strip(TiffEncoderContext *s, const int8_t *src, unsigned long zlen = s->buf_size - (*s->buf - s->buf_start); if (compress(dst, &zlen, src, n) != Z_OK) { av_log(s->avctx, AV_LOG_ERROR, "Compressing failed\n"); - return -1; + return AVERROR_UNKNOWN; } return zlen; } #endif case TIFF_RAW: if (check_size(s, n)) - return -1; + return AVERROR(EINVAL); memcpy(dst, src, n); return n; case TIFF_PACKBITS: @@ -182,7 +183,7 @@ static int encode_strip(TiffEncoderContext *s, const int8_t *src, case TIFF_LZW: return ff_lzw_encode(s->lzws, src, n); default: - return -1; + return AVERROR(EINVAL); } } @@ -246,13 +247,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->subsampling[1] = 1; switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGBA64LE: case AV_PIX_FMT_RGB48LE: case AV_PIX_FMT_GRAY16LE: case AV_PIX_FMT_RGBA: case AV_PIX_FMT_RGB24: case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_PAL8: - pfd = av_pix_fmt_desc_get(avctx->pix_fmt); + pfd = av_pix_fmt_desc_get(avctx->pix_fmt); + if (!pfd) + return AVERROR_BUG; s->bpp = av_get_bits_per_pixel(pfd); if (pfd->flags & AV_PIX_FMT_FLAG_PAL) s->photometric_interpretation = TIFF_PHOTOMETRIC_PALETTE; @@ -290,7 +294,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, default: av_log(s->avctx, AV_LOG_ERROR, "This colors format is not supported\n"); - return -1; + return AVERROR(EINVAL); } if (s->compr == TIFF_DEFLATE || @@ -307,7 +311,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, strips = (s->height - 1) / s->rps + 1; packet_size = avctx->height * ((avctx->width * s->bpp + 7) >> 3) * 2 + - avctx->height * 4 + FF_MIN_BUFFER_SIZE; + avctx->height * 4 + AV_INPUT_BUFFER_MIN_SIZE; if (!pkt->data && (ret = av_new_packet(pkt, packet_size)) < 0) { @@ -319,8 +323,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->buf = &ptr; s->buf_size = pkt->size; - if (check_size(s, 8)) + if (check_size(s, 8)) { + ret = AVERROR(EINVAL); goto fail; + } // write header bytestream_put_le16(&ptr, 0x4949); @@ -329,8 +335,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, offset = ptr; bytestream_put_le32(&ptr, 0); - strip_sizes = av_mallocz(sizeof(*strip_sizes) * strips); - strip_offsets = av_mallocz(sizeof(*strip_offsets) * strips); + strip_sizes = av_mallocz_array(strips, sizeof(*strip_sizes)); + strip_offsets = av_mallocz_array(strips, sizeof(*strip_offsets)); if (!strip_sizes || !strip_offsets) { ret = AVERROR(ENOMEM); goto fail; @@ -442,7 +448,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, ADD_ENTRY(s, TIFF_YRES, TIFF_RATIONAL, 1, res); ADD_ENTRY1(s, TIFF_RES_UNIT, TIFF_SHORT, 2); - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) ADD_ENTRY(s, TIFF_SOFTWARE_NAME, TIFF_STRING, strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT); @@ -486,22 +492,26 @@ fail: static av_cold int encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); +#if !CONFIG_ZLIB + TiffEncoderContext *s = avctx->priv_data; + if (s->compr == TIFF_DEFLATE) { + av_log(avctx, AV_LOG_ERROR, + "Deflate compression needs zlib compiled in\n"); + return AVERROR(ENOSYS); + } +#endif + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - return 0; -} - #define OFFSET(x) offsetof(TiffEncoderContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -509,9 +519,7 @@ static const AVOption options[] = { { "packbits", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_PACKBITS }, 0, 0, VE, "compression_algo" }, { "raw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_RAW }, 0, 0, VE, "compression_algo" }, { "lzw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_LZW }, 0, 0, VE, "compression_algo" }, -#if CONFIG_ZLIB { "deflate", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_DEFLATE }, 0, 0, VE, "compression_algo" }, -#endif { NULL }, }; @@ -529,11 +537,10 @@ AVCodec ff_tiff_encoder = { .id = AV_CODEC_ID_TIFF, .priv_data_size = sizeof(TiffEncoderContext), .init = encode_init, - .close = encode_close, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8, - AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, diff --git a/libavcodec/tmv.c b/libavcodec/tmv.c index f04a5f5..a9fcdf3 100644 --- a/libavcodec/tmv.c +++ b/libavcodec/tmv.c @@ -93,5 +93,5 @@ AVCodec ff_tmv_decoder = { .id = AV_CODEC_ID_TMV, .init = tmv_decode_init, .decode = tmv_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/truemotion1.c b/libavcodec/truemotion1.c index 5dffb4e..3eab33a 100644 --- a/libavcodec/truemotion1.c +++ b/libavcodec/truemotion1.c @@ -910,5 +910,5 @@ AVCodec ff_truemotion1_decoder = { .init = truemotion1_decode_init, .close = truemotion1_decode_end, .decode = truemotion1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index 122643d..1726440 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -171,6 +171,10 @@ static int tm2_build_huff_table(TM2Context *ctx, TM2Codes *code) 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 (!huff.nums || !huff.bits || !huff.lens) { + res = AVERROR(ENOMEM); + goto out; + } res = tm2_read_tree(ctx, 0, 0, &huff); @@ -193,10 +197,16 @@ static int tm2_build_huff_table(TM2Context *ctx, TM2Codes *code) code->bits = huff.max_bits; code->length = huff.max_num; code->recode = av_malloc(code->length * sizeof(int)); + if (!code->recode) { + res = AVERROR(ENOMEM); + goto out; + } for (i = 0; i < code->length; i++) code->recode[i] = huff.nums[i]; } } + +out: /* free allocated memory */ av_free(huff.nums); av_free(huff.bits); @@ -281,7 +291,7 @@ static int tm2_read_stream(TM2Context *ctx, const uint8_t *buf, int stream_id, i if (len == 0) return 4; - if (len >= INT_MAX/4-1 || len < 0 || len > buf_size) { + if (len >= INT_MAX / 4 - 1 || len < 0 || skip > buf_size) { av_log(ctx->avctx, AV_LOG_ERROR, "Error, invalid stream size.\n"); return AVERROR_INVALIDDATA; } @@ -846,7 +856,7 @@ static int decode_frame(AVCodecContext *avctx, int i, t, ret; uint8_t *swbuf; - swbuf = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + swbuf = av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!swbuf) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); return AVERROR(ENOMEM); @@ -988,5 +998,5 @@ AVCodec ff_truemotion2_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c new file mode 100644 index 0000000..ed7fb68 --- /dev/null +++ b/libavcodec/truemotion2rt.c @@ -0,0 +1,230 @@ +/* + * Duck TrueMotion 2.0 Real Time decoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +typedef struct TrueMotion2RTContext { + GetBitContext gb; + int delta_size; + int hscale; +} TrueMotion2RTContext; + +static const int16_t delta_tab2[] = { + 5, -7, 36, -36, +}; + +static const int16_t delta_tab3[] = { + 2, -3, 8, -8, 18, -18, 36, -36, +}; + +static const int16_t delta_tab4[] = { + 1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144, +}; + +static const int16_t *const delta_tabs[] = { + delta_tab2, delta_tab3, delta_tab4, +}; + +/* Returns the number of bytes consumed from the bytestream, or + * AVERROR_INVALIDDATA if there was an error while decoding the header. */ +static int truemotion2rt_decode_header(AVCodecContext *avctx, AVPacket *avpkt) +{ + TrueMotion2RTContext *s = avctx->priv_data; + int header_size; + uint8_t header_buffer[128] = { 0 }; /* logical maximum header size */ + const uint8_t *buf = avpkt->data; + int size = avpkt->size; + int width, height; + int ret, i; + + if (size < 1) { + av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); + return AVERROR_INVALIDDATA; + } + + header_size = ((buf[0] >> 5) | (buf[0] << 3)) & 0x7f; + if (header_size < 10) { + av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size); + return AVERROR_INVALIDDATA; + } + + if (header_size + 1 > size) { + av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); + return AVERROR_INVALIDDATA; + } + + /* unscramble the header bytes with a XOR operation */ + for (i = 1; i < header_size; i++) + header_buffer[i - 1] = buf[i] ^ buf[i + 1]; + + s->delta_size = header_buffer[1]; + s->hscale = 1 + !!header_buffer[3]; + if (s->delta_size < 2 || s->delta_size > 4) + return AVERROR_INVALIDDATA; + + height = AV_RL16(header_buffer + 5); + width = AV_RL16(header_buffer + 7); + + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + + av_log(avctx, AV_LOG_DEBUG, "Header size: %d\n", header_size); + return header_size; +} + +static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + TrueMotion2RTContext *s = avctx->priv_data; + AVFrame * const p = data; + GetBitContext *gb = &s->gb; + uint8_t *dst; + int x, y, delta_mode; + int ret; + + ret = truemotion2rt_decode_header(avctx, avpkt); + if (ret < 0) + return ret; + + ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret); + if (ret < 0) + return ret; + + ret = ff_get_buffer(avctx, p, 0); + if (ret < 0) + return ret; + + skip_bits(gb, 32); + delta_mode = s->delta_size - 2; + dst = p->data[0]; + for (y = 0; y < avctx->height; y++) { + int diff = 0; + for (x = 0; x < avctx->width; x += s->hscale) { + diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; + dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff); + } + dst += p->linesize[0]; + } + + if (s->hscale > 1) { + dst = p->data[0]; + for (y = 0; y < avctx->height; y++) { + for (x = 1; x < avctx->width; x += s->hscale) + dst[x] = dst[x - 1]; + dst += p->linesize[0]; + } + } + + dst = p->data[0]; + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) + dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3); + dst += p->linesize[0]; + } + + dst = p->data[1]; + for (y = 0; y < avctx->height >> 2; y++) { + int diff = 0; + for (x = 0; x < avctx->width >> 2; x += s->hscale) { + diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; + dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff); + } + dst += p->linesize[1]; + } + + if (s->hscale > 1) { + dst = p->data[1]; + for (y = 0; y < avctx->height >> 2; y++) { + for (x = 1; x < avctx->width >> 2; x += s->hscale) + dst[x] = dst[x - 1]; + dst += p->linesize[1]; + } + } + + dst = p->data[1]; + for (y = 0; y < avctx->height >> 2; y++) { + for (x = 0; x < avctx->width >> 2; x++) + dst[x] += (dst[x] - 128) / 8; + dst += p->linesize[1]; + } + + dst = p->data[2]; + for (y = 0; y < avctx->height >> 2; y++) { + int diff = 0; + for (x = 0; x < avctx->width >> 2; x += s->hscale) { + diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; + dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff); + } + dst += p->linesize[2]; + } + + if (s->hscale > 1) { + dst = p->data[2]; + for (y = 0; y < avctx->height >> 2; y++) { + for (x = 1; x < avctx->width >> 2; x += s->hscale) + dst[x] = dst[x - 1]; + dst += p->linesize[2]; + } + } + + dst = p->data[2]; + for (y = 0; y < avctx->height >> 2; y++) { + for (x = 0; x < avctx->width >> 2; x++) + dst[x] += (dst[x] - 128) / 8; + dst += p->linesize[2]; + } + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int truemotion2rt_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + return 0; +} + +AVCodec ff_truemotion2rt_decoder = { + .name = "truemotion2rt", + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TRUEMOTION2RT, + .priv_data_size = sizeof(TrueMotion2RTContext), + .init = truemotion2rt_decode_init, + .decode = truemotion2rt_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 34b7c3b..b2195ba 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -35,7 +35,7 @@ /** * TrueSpeech decoder context */ -typedef struct { +typedef struct TSContext { BswapDSPContext bdsp; /* input data */ DECLARE_ALIGNED(16, uint8_t, buffer)[32]; @@ -364,5 +364,5 @@ AVCodec ff_truespeech_decoder = { .priv_data_size = sizeof(TSContext), .init = truespeech_decode_init, .decode = truespeech_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c index 8619934..7c54473 100644 --- a/libavcodec/tscc.c +++ b/libavcodec/tscc.c @@ -32,7 +32,6 @@ * then this coded picture is packed with ZLib * * Supports: BGR8,BGR555,BGR24 - only BGR8 and BGR555 tested - * */ #include @@ -95,7 +94,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ret != Z_DATA_ERROR) { bytestream2_init(&c->gb, c->decomp_buf, c->decomp_size - c->zstream.avail_out); - ff_msrle_decode(avctx, (AVPicture*)frame, c->bpp, &c->gb); + ff_msrle_decode(avctx, frame, c->bpp, &c->gb); } /* make the palette available on the way out */ @@ -180,5 +179,5 @@ AVCodec ff_tscc_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c index bd1854b..d3d45e4 100644 --- a/libavcodec/tscc2.c +++ b/libavcodec/tscc2.c @@ -28,9 +28,10 @@ #define BITSTREAM_READER_LE #include "avcodec.h" -#include "get_bits.h" #include "bytestream.h" +#include "get_bits.h" #include "internal.h" +#include "mathops.h" #include "tscc2data.h" typedef struct TSCC2Context { @@ -179,7 +180,7 @@ static int tscc2_decode_mb(TSCC2Context *c, int *q, int vlc_set, if (bpos >= 16) return AVERROR_INVALIDDATA; val = sign_extend(ac >> 4, 8); - c->block[tscc2_zigzag[bpos++]] = val; + c->block[ff_zigzag_scan[bpos++]] = val; } tscc2_idct4_put(c->block, q, dst + k * 4, stride); } @@ -384,5 +385,5 @@ AVCodec ff_tscc2_decoder = { .init = tscc2_decode_init, .close = tscc2_decode_end, .decode = tscc2_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/tscc2data.h b/libavcodec/tscc2data.h index 70a06e5..ac0a898 100644 --- a/libavcodec/tscc2data.h +++ b/libavcodec/tscc2data.h @@ -24,13 +24,6 @@ #include -static const uint8_t tscc2_zigzag[16] = { - 0, 1, 4, 8, - 5, 2, 3, 6, - 9, 12, 13, 10, - 7, 11, 14, 15 -}; - #define NUM_VLC_SETS 13 static const uint16_t tscc2_quants[NUM_VLC_SETS][3] = { diff --git a/libavcodec/tta.c b/libavcodec/tta.c index 4d2e2a0..2b57406 100644 --- a/libavcodec/tta.c +++ b/libavcodec/tta.c @@ -27,12 +27,14 @@ * @author Alex Beregszaszi */ -#define BITSTREAM_READER_LE #include + +#include "libavutil/crc.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "libavutil/crc.h" #define FORMAT_SIMPLE 1 #define FORMAT_ENCRYPTED 2 @@ -477,5 +479,5 @@ AVCodec ff_tta_decoder = { .init = tta_decode_init, .close = tta_decode_close, .decode = tta_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c index e1b1c7b..940def4 100644 --- a/libavcodec/twinvq.c +++ b/libavcodec/twinvq.c @@ -790,7 +790,7 @@ av_cold int ff_twinvq_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); if ((ret = init_mdct_win(tctx))) { av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); ff_twinvq_decode_close(avctx); diff --git a/libavcodec/twinvq.h b/libavcodec/twinvq.h index 7601e5b..e810565 100644 --- a/libavcodec/twinvq.h +++ b/libavcodec/twinvq.h @@ -109,7 +109,7 @@ typedef struct TwinVQFrameData { * bitrate/sample rate */ typedef struct TwinVQModeTab { - struct TwinVQFrameMode fmode[3]; ///< frame type-dependant parameters + struct TwinVQFrameMode fmode[3]; ///< frame type-dependent parameters uint16_t size; ///< frame size in samples uint8_t n_lsp; ///< number of lsp coefficients @@ -197,7 +197,7 @@ static inline float twinvq_mulawinv(float y, float clip, float mu) int ff_twinvq_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt); -av_cold int ff_twinvq_decode_close(AVCodecContext *avctx); -av_cold int ff_twinvq_decode_init(AVCodecContext *avctx); +int ff_twinvq_decode_close(AVCodecContext *avctx); +int ff_twinvq_decode_init(AVCodecContext *avctx); -#endif /* AVCODEC_TWINVQ_DATA_H */ +#endif /* AVCODEC_TWINVQ_H */ diff --git a/libavcodec/twinvqdec.c b/libavcodec/twinvqdec.c index 65028a6..56df105 100644 --- a/libavcodec/twinvqdec.c +++ b/libavcodec/twinvqdec.c @@ -149,7 +149,7 @@ static int very_broken_op(int a, int b) /** * Sum to data a periodic peak of a given period, width and shape. * - * @param period the period of the peak divised by 400.0 + * @param period the period of the peak divided by 400.0 */ static void add_peak(int period, int width, const float *shape, float ppc_gain, float *speech, int len) @@ -421,7 +421,7 @@ AVCodec ff_twinvq_decoder = { .init = twinvq_decode_init, .close = ff_twinvq_decode_close, .decode = ff_twinvq_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/txd.c b/libavcodec/txd.c index 8f12291..463223c 100644 --- a/libavcodec/txd.c +++ b/libavcodec/txd.c @@ -26,18 +26,25 @@ #include "avcodec.h" #include "bytestream.h" #include "internal.h" -#include "s3tc.h" +#include "texturedsp.h" + +#define TXD_DXT1 0x31545844 +#define TXD_DXT3 0x33545844 static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { GetByteContext gb; + TextureDSPContext dxtc; AVFrame * const p = data; unsigned int version, w, h, d3d_format, depth, stride, flags; unsigned int y, v; uint8_t *ptr; uint32_t *pal; + int i, j; int ret; + ff_texturedsp_init(&dxtc); + bytestream2_init(&gb, avpkt->data, avpkt->size); version = bytestream2_get_le32(&gb); bytestream2_skip(&gb, 72); @@ -57,7 +64,7 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (depth == 8) { avctx->pix_fmt = AV_PIX_FMT_PAL8; } else if (depth == 16 || depth == 32) { - avctx->pix_fmt = AV_PIX_FMT_RGB32; + avctx->pix_fmt = AV_PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth); return AVERROR_PATCHWELCOME; @@ -66,6 +73,9 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ff_set_dimensions(avctx, w, h)) < 0) return ret; + avctx->coded_width = FFALIGN(w, 4); + avctx->coded_height = FFALIGN(h, 4); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; @@ -93,11 +103,23 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case 0: if (!(flags & 1)) goto unsupported; - case FF_S3TC_DXT1: - ff_decode_dxt1(&gb, ptr, w, h, stride); + case TXD_DXT1: + for (j = 0; j < avctx->height; j += 4) { + for (i = 0; i < avctx->width; i += 4) { + uint8_t *p = ptr + i * 4 + j * stride; + int step = dxtc.dxt1_block(p, stride, gb.buffer); + bytestream2_skip(&gb, step); + } + } break; - case FF_S3TC_DXT3: - ff_decode_dxt3(&gb, ptr, w, h, stride); + case TXD_DXT3: + for (j = 0; j < avctx->height; j += 4) { + for (i = 0; i < avctx->width; i += 4) { + uint8_t *p = ptr + i * 4 + j * stride; + int step = dxtc.dxt3_block(p, stride, gb.buffer); + bytestream2_skip(&gb, step); + } + } break; default: goto unsupported; @@ -131,5 +153,5 @@ AVCodec ff_txd_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_TXD, .decode = txd_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/ulti.c b/libavcodec/ulti.c index 186f1a6..46aa27d 100644 --- a/libavcodec/ulti.c +++ b/libavcodec/ulti.c @@ -384,12 +384,11 @@ static int ulti_decode_frame(AVCodecContext *avctx, Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F; ulti_grad(s->frame, tx, ty, Y, chroma, angle); //draw block } else { // some patterns - int f0, f1; - f0 = bytestream2_get_byteu(&s->gb); - f1 = tmp; + int f0 = tmp; + int f1 = bytestream2_get_byteu(&s->gb); Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F; Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F; - ulti_pattern(s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); + ulti_pattern(s->frame, tx, ty, f0, f1, Y[0], Y[1], chroma); } } break; @@ -427,5 +426,5 @@ AVCodec ff_ulti_decoder = { .init = ulti_decode_init, .close = ulti_decode_end, .decode = ulti_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index c5fa50d..837edbd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -32,6 +32,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" @@ -59,14 +60,14 @@ static void *avformat_mutex; void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { void **p = ptr; - if (min_size > SIZE_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + if (min_size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { av_freep(p); *size = 0; return; } - av_fast_malloc(p, size, min_size + FF_INPUT_BUFFER_PADDING_SIZE); + av_fast_malloc(p, size, min_size + AV_INPUT_BUFFER_PADDING_SIZE); if (*size) - memset((uint8_t *)*p + min_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset((uint8_t *)*p + min_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } /* encoder management */ @@ -94,12 +95,12 @@ static av_cold void avcodec_init(void) int av_codec_is_encoder(const AVCodec *codec) { - return codec && (codec->encode_sub || codec->encode2); + return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame); } int av_codec_is_decoder(const AVCodec *codec) { - return codec && codec->decode; + return codec && (codec->decode || codec->send_packet); } av_cold void avcodec_register(AVCodec *codec) @@ -147,7 +148,7 @@ int ff_set_sar(AVCodecContext *avctx, AVRational sar) int ret = av_image_check_sar(avctx->width, avctx->height, sar); if (ret < 0) { - av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %d/%d\n", sar.num, sar.den); avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; return ret; @@ -177,7 +178,9 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame, return 0; } -#if HAVE_SIMD_ALIGN_16 +#if HAVE_SIMD_ALIGN_32 +# define STRIDE_ALIGN 32 +#elif HAVE_SIMD_ALIGN_16 # define STRIDE_ALIGN 16 #else # define STRIDE_ALIGN 8 @@ -199,6 +202,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, case AV_PIX_FMT_YUV440P: case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_GRAY16BE: case AV_PIX_FMT_GRAY16LE: @@ -336,7 +340,8 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: { - AVPicture picture; + uint8_t *data[4]; + int linesize[4]; int size[4] = { 0 }; int w = frame->width; int h = frame->height; @@ -351,27 +356,27 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) do { // NOTE: do not align linesizes individually, this breaks e.g. assumptions // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 - av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w); + av_image_fill_linesizes(linesize, avctx->pix_fmt, w); // increase alignment of w for next try (rhs gives the lowest bit set in w) w += w & ~(w - 1); unaligned = 0; for (i = 0; i < 4; i++) - unaligned |= picture.linesize[i] % pool->stride_align[i]; + unaligned |= linesize[i] % pool->stride_align[i]; } while (unaligned); - tmpsize = av_image_fill_pointers(picture.data, avctx->pix_fmt, h, - NULL, picture.linesize); + tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h, + NULL, linesize); if (tmpsize < 0) return -1; - for (i = 0; i < 3 && picture.data[i + 1]; i++) - size[i] = picture.data[i + 1] - picture.data[i]; - size[i] = tmpsize - (picture.data[i] - picture.data[0]); + for (i = 0; i < 3 && data[i + 1]; i++) + size[i] = data[i + 1] - data[i]; + size[i] = tmpsize - (data[i] - data[0]); for (i = 0; i < 4; i++) { av_buffer_pool_uninit(&pool->pools[i]); - pool->linesize[i] = picture.linesize[i]; + pool->linesize[i] = linesize[i]; if (size[i]) { pool->pools[i] = av_buffer_pool_init(size[i] + 16, NULL); if (!pool->pools[i]) { @@ -510,15 +515,12 @@ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags { int ret; + if (avctx->hw_frames_ctx) + return av_hwframe_get_buffer(avctx->hw_frames_ctx, frame, 0); + if ((ret = update_frame_pool(avctx, frame)) < 0) return ret; -#if FF_API_GET_BUFFER -FF_DISABLE_DEPRECATION_WARNINGS - frame->type = FF_BUFFER_TYPE_INTERNAL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: return video_get_buffer(avctx, frame); @@ -529,40 +531,19 @@ FF_ENABLE_DEPRECATION_WARNINGS } } -#if FF_API_GET_BUFFER -FF_DISABLE_DEPRECATION_WARNINGS -int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame) -{ - return avcodec_default_get_buffer2(avctx, frame, 0); -} - -typedef struct CompatReleaseBufPriv { - AVCodecContext avctx; - AVFrame frame; -} CompatReleaseBufPriv; - -static void compat_free_buffer(void *opaque, uint8_t *data) -{ - CompatReleaseBufPriv *priv = opaque; - if (priv->avctx.release_buffer) - priv->avctx.release_buffer(&priv->avctx, &priv->frame); - av_freep(&priv); -} - -static void compat_release_buffer(void *opaque, uint8_t *data) -{ - AVBufferRef *buf = opaque; - av_buffer_unref(&buf); -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) { AVPacket *pkt = avctx->internal->pkt; - uint8_t *packet_sd; - int size; - AVFrameSideData *frame_sd; + int i; + struct { + enum AVPacketSideDataType packet; + enum AVFrameSideDataType frame; + } sd[] = { + { AV_PKT_DATA_REPLAYGAIN , AV_FRAME_DATA_REPLAYGAIN }, + { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX }, + { AV_PKT_DATA_STEREO3D, AV_FRAME_DATA_STEREO3D }, + { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE }, + }; frame->color_primaries = avctx->color_primaries; frame->color_trc = avctx->color_trc; @@ -572,38 +553,34 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) frame->reordered_opaque = avctx->reordered_opaque; if (!pkt) { +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pts = AV_NOPTS_VALUE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->pts = AV_NOPTS_VALUE; return 0; } +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pts = pkt->pts; - - /* copy the replaygain data to the output frame */ - packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_REPLAYGAIN, &size); - if (packet_sd) { - frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_REPLAYGAIN, size); - if (!frame_sd) - return AVERROR(ENOMEM); - - memcpy(frame_sd->data, packet_sd, size); - } - /* copy the displaymatrix to the output frame */ - packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size); - if (packet_sd) { - frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, size); - if (!frame_sd) - return AVERROR(ENOMEM); - - memcpy(frame_sd->data, packet_sd, size); - } - /* copy the stereo3d format to the output frame */ - packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_STEREO3D, &size); - if (packet_sd) { - frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_STEREO3D, size); - if (!frame_sd) - return AVERROR(ENOMEM); - - memcpy(frame_sd->data, packet_sd, size); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->pts = pkt->pts; + + for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) { + int size; + uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size); + if (packet_sd) { + AVFrameSideData *frame_sd = av_frame_new_side_data(frame, + sd[i].frame, + size); + if (!frame_sd) + return AVERROR(ENOMEM); + + memcpy(frame_sd->data, packet_sd, size); + } } return 0; @@ -673,126 +650,13 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) if (ret < 0) return ret; - if (hwaccel && hwaccel->alloc_frame) { - ret = hwaccel->alloc_frame(avctx, frame); - goto end; - } - -#if FF_API_GET_BUFFER -FF_DISABLE_DEPRECATION_WARNINGS - /* - * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers. - * We wrap each plane in its own AVBuffer. Each of those has a reference to - * a dummy AVBuffer as its private data, unreffing it on free. - * When all the planes are freed, the dummy buffer's free callback calls - * release_buffer(). - */ - if (avctx->get_buffer) { - CompatReleaseBufPriv *priv = NULL; - AVBufferRef *dummy_buf = NULL; - int planes, i, ret; - - if (flags & AV_GET_BUFFER_FLAG_REF) - frame->reference = 1; - - ret = avctx->get_buffer(avctx, frame); - if (ret < 0) - return ret; - - /* return if the buffers are already set up - * this would happen e.g. when a custom get_buffer() calls - * avcodec_default_get_buffer - */ - if (frame->buf[0]) - return 0; - - priv = av_mallocz(sizeof(*priv)); - if (!priv) { - ret = AVERROR(ENOMEM); - goto fail; - } - priv->avctx = *avctx; - priv->frame = *frame; - - dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0); - if (!dummy_buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - -#define WRAP_PLANE(ref_out, data, data_size) \ -do { \ - AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf); \ - if (!dummy_ref) { \ - ret = AVERROR(ENOMEM); \ - goto fail; \ - } \ - ref_out = av_buffer_create(data, data_size, compat_release_buffer, \ - dummy_ref, 0); \ - if (!ref_out) { \ - av_frame_unref(frame); \ - ret = AVERROR(ENOMEM); \ - goto fail; \ - } \ -} while (0) - - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - - planes = av_pix_fmt_count_planes(frame->format); - /* workaround for AVHWAccel plane count of 0, buf[0] is used as - check for allocated buffers: make libavcodec happy */ - if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) - planes = 1; - if (!desc || planes <= 0) { - ret = AVERROR(EINVAL); - goto fail; - } - - for (i = 0; i < planes; i++) { - int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - int plane_size = (frame->height >> v_shift) * frame->linesize[i]; - - WRAP_PLANE(frame->buf[i], frame->data[i], plane_size); - } - } else { - int planar = av_sample_fmt_is_planar(frame->format); - planes = planar ? avctx->channels : 1; - - if (planes > FF_ARRAY_ELEMS(frame->buf)) { - frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf); - frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) * - frame->nb_extended_buf); - if (!frame->extended_buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - - for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++) - WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]); - - for (i = 0; i < frame->nb_extended_buf; i++) - WRAP_PLANE(frame->extended_buf[i], - frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)], - frame->linesize[0]); + if (hwaccel) { + if (hwaccel->alloc_frame) { + ret = hwaccel->alloc_frame(avctx, frame); + goto end; } - - av_buffer_unref(&dummy_buf); - - frame->width = avctx->width; - frame->height = avctx->height; - - return 0; - -fail: - avctx->release_buffer(avctx, frame); - av_freep(&priv); - av_buffer_unref(&dummy_buf); - return ret; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif + } else + avctx->sw_pix_fmt = avctx->pix_fmt; ret = avctx->get_buffer2(avctx, frame, flags); @@ -836,19 +700,6 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) return 0; } -#if FF_API_GET_BUFFER -void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) -{ - av_frame_unref(pic); -} - -int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic) -{ - av_assert0(0); - return AVERROR_BUG; -} -#endif - int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) { int i; @@ -898,86 +749,103 @@ static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, return NULL; } +static int setup_hwaccel(AVCodecContext *avctx, + const enum AVPixelFormat fmt, + const char *name) +{ + AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt); + int ret = 0; + + if (!hwa) { + av_log(avctx, AV_LOG_ERROR, + "Could not find an AVHWAccel for the pixel format: %s", + name); + return AVERROR(ENOENT); + } + + if (hwa->priv_data_size) { + avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size); + if (!avctx->internal->hwaccel_priv_data) + return AVERROR(ENOMEM); + } + + if (hwa->init) { + ret = hwa->init(avctx); + if (ret < 0) { + av_freep(&avctx->internal->hwaccel_priv_data); + return ret; + } + } + + avctx->hwaccel = hwa; + + return 0; +} int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { const AVPixFmtDescriptor *desc; - enum AVPixelFormat ret = avctx->get_format(avctx, fmt); + enum AVPixelFormat *choices; + enum AVPixelFormat ret; + unsigned n = 0; - desc = av_pix_fmt_desc_get(ret); - if (!desc) - return AV_PIX_FMT_NONE; + while (fmt[n] != AV_PIX_FMT_NONE) + ++n; - if (avctx->hwaccel && avctx->hwaccel->uninit) - avctx->hwaccel->uninit(avctx); - av_freep(&avctx->internal->hwaccel_priv_data); - avctx->hwaccel = NULL; + av_assert0(n >= 1); + avctx->sw_pix_fmt = fmt[n - 1]; + av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt)); - if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { - AVHWAccel *hwaccel; - int err; + choices = av_malloc_array(n + 1, sizeof(*choices)); + if (!choices) + return AV_PIX_FMT_NONE; - hwaccel = find_hwaccel(avctx->codec_id, ret); - if (!hwaccel) { - av_log(avctx, AV_LOG_ERROR, - "Could not find an AVHWAccel for the pixel format: %s", - desc->name); - return AV_PIX_FMT_NONE; - } + memcpy(choices, fmt, (n + 1) * sizeof(*choices)); - if (hwaccel->priv_data_size) { - avctx->internal->hwaccel_priv_data = av_mallocz(hwaccel->priv_data_size); - if (!avctx->internal->hwaccel_priv_data) - return AV_PIX_FMT_NONE; - } - - if (hwaccel->init) { - err = hwaccel->init(avctx); - if (err < 0) { - av_freep(&avctx->internal->hwaccel_priv_data); - return AV_PIX_FMT_NONE; - } - } - avctx->hwaccel = hwaccel; - } + for (;;) { + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; - return ret; -} + av_buffer_unref(&avctx->hw_frames_ctx); -#if FF_API_AVFRAME_LAVC -void avcodec_get_frame_defaults(AVFrame *frame) -{ - if (frame->extended_data != frame->data) - av_freep(&frame->extended_data); + ret = avctx->get_format(avctx, choices); - memset(frame, 0, sizeof(AVFrame)); + desc = av_pix_fmt_desc_get(ret); + if (!desc) { + ret = AV_PIX_FMT_NONE; + break; + } - frame->pts = AV_NOPTS_VALUE; - frame->key_frame = 1; - frame->sample_aspect_ratio = (AVRational) {0, 1 }; - frame->format = -1; /* unknown */ - frame->extended_data = frame->data; -} + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + break; -AVFrame *avcodec_alloc_frame(void) -{ - AVFrame *frame = av_mallocz(sizeof(AVFrame)); + if (avctx->hw_frames_ctx) { + AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (hw_frames_ctx->format != ret) { + av_log(avctx, AV_LOG_ERROR, "Format returned from get_buffer() " + "does not match the format of provided AVHWFramesContext\n"); + ret = AV_PIX_FMT_NONE; + break; + } + } - if (!frame) - return NULL; + if (!setup_hwaccel(avctx, ret, desc->name)) + break; -FF_DISABLE_DEPRECATION_WARNINGS - avcodec_get_frame_defaults(frame); -FF_ENABLE_DEPRECATION_WARNINGS + /* Remove failed hwaccel from choices */ + for (n = 0; choices[n] != ret; n++) + av_assert0(choices[n] != AV_PIX_FMT_NONE); - return frame; -} + do + choices[n] = choices[n + 1]; + while (choices[n++] != AV_PIX_FMT_NONE); + } -void avcodec_free_frame(AVFrame **frame) -{ - av_frame_free(frame); + av_freep(&choices); + return ret; } -#endif int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) { @@ -1006,16 +874,21 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code av_dict_copy(&tmp, *options, 0); /* If there is a user-supplied mutex locking routine, call it. */ - if (lockmgr_cb) { - if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) - return -1; - } + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) { + if (lockmgr_cb) { + if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) + return -1; + } - entangled_thread_counter++; - if (entangled_thread_counter != 1) { - av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n"); - ret = -1; - goto end; + entangled_thread_counter++; + if (entangled_thread_counter != 1) { + av_log(avctx, AV_LOG_ERROR, + "Insufficient thread locking. At least %d threads are " + "calling avcodec_open2() at the same time right now.\n", + entangled_thread_counter); + ret = -1; + goto end; + } } avctx->internal = av_mallocz(sizeof(AVCodecInternal)); @@ -1036,6 +909,18 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code goto free_and_end; } + avctx->internal->buffer_frame = av_frame_alloc(); + if (!avctx->internal->buffer_frame) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } + + avctx->internal->buffer_pkt = av_packet_alloc(); + if (!avctx->internal->buffer_pkt) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } + if (codec->priv_data_size > 0) { if (!avctx->priv_data) { avctx->priv_data = av_mallocz(codec->priv_data_size); @@ -1104,7 +989,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } avctx->frame_number = 0; - if (avctx->codec->capabilities & CODEC_CAP_EXPERIMENTAL && + if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { ret = AVERROR_EXPERIMENTAL; goto free_and_end; @@ -1122,11 +1007,27 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code goto free_and_end; } } - if (!HAVE_THREADS && !(codec->capabilities & CODEC_CAP_AUTO_THREADS)) + if (!HAVE_THREADS && !(codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)) avctx->thread_count = 1; if (av_codec_is_encoder(avctx->codec)) { int i; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame = av_frame_alloc(); + if (!avctx->coded_frame) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { + av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->codec->sample_fmts) { for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) @@ -1153,6 +1054,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code ret = AVERROR(EINVAL); goto free_and_end; } + if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) + avctx->color_range = AVCOL_RANGE_JPEG; } if (avctx->codec->supported_samplerates) { for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) @@ -1190,6 +1096,37 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if (!avctx->rc_initial_buffer_occupancy) avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3 / 4; + + if (avctx->ticks_per_frame && + avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { + av_log(avctx, AV_LOG_ERROR, + "ticks_per_frame %d too large for the timebase %d/%d.", + avctx->ticks_per_frame, + avctx->time_base.num, + avctx->time_base.den); + goto free_and_end; + } + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (frames_ctx->format != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, + "Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->sw_pix_fmt != AV_PIX_FMT_NONE && + avctx->sw_pix_fmt != frames_ctx->sw_format) { + av_log(avctx, AV_LOG_ERROR, + "Mismatching AVCodecContext.sw_pix_fmt (%s) " + "and AVHWFramesContext.sw_format (%s)\n", + av_get_pix_fmt_name(avctx->sw_pix_fmt), + av_get_pix_fmt_name(frames_ctx->sw_format)); + ret = AVERROR(EINVAL); + goto free_and_end; + } + avctx->sw_pix_fmt = frames_ctx->sw_format; + } } if (avctx->codec->init && !(avctx->active_thread_type & FF_THREAD_FRAME)) { @@ -1199,6 +1136,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } } +#if FF_API_AUDIOENC_DELAY + if (av_codec_is_encoder(avctx->codec)) + avctx->delay = avctx->initial_padding; +#endif + if (av_codec_is_decoder(avctx->codec)) { /* validate channel layout from the decoder */ if (avctx->channel_layout) { @@ -1216,14 +1158,22 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code ret = AVERROR(EINVAL); goto free_and_end; } + +#if FF_API_AVCTX_TIMEBASE + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + avctx->time_base = av_inv_q(avctx->framerate); +#endif } end: - entangled_thread_counter--; + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) { + entangled_thread_counter--; - /* Release any user-supplied mutex. */ - if (lockmgr_cb) { - (*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); + /* Release any user-supplied mutex. */ + if (lockmgr_cb) { + (*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); + } } + if (options) { av_dict_free(options); *options = tmp; @@ -1231,10 +1181,26 @@ end: return ret; free_and_end: + if (avctx->codec && + (avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP)) + avctx->codec->close(avctx); + + if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) + av_opt_free(avctx->priv_data); + av_opt_free(avctx); + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_free(&avctx->coded_frame); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_dict_free(&tmp); av_freep(&avctx->priv_data); if (avctx->internal) { av_frame_free(&avctx->internal->to_free); + av_frame_free(&avctx->internal->buffer_frame); + av_packet_free(&avctx->internal->buffer_pkt); av_freep(&avctx->internal->pool); } av_freep(&avctx->internal); @@ -1244,26 +1210,16 @@ free_and_end: int ff_alloc_packet(AVPacket *avpkt, int size) { - if (size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + if (size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return AVERROR(EINVAL); if (avpkt->data) { AVBufferRef *buf = avpkt->buf; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - void *destruct = avpkt->destruct; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (avpkt->size < size) return AVERROR(EINVAL); av_init_packet(avpkt); -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - avpkt->destruct = destruct; -FF_ENABLE_DEPRECATION_WARNINGS -#endif avpkt->buf = buf; avpkt->size = size; return 0; @@ -1323,8 +1279,13 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, *got_packet_ptr = 0; - if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { - av_free_packet(avpkt); + if (!avctx->codec->encode2) { + av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n"); + return AVERROR(ENOSYS); + } + + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) && !frame) { + av_packet_unref(avpkt); av_init_packet(avpkt); return 0; } @@ -1345,12 +1306,19 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, frame = &tmp; } + /* extract audio service type metadata */ + if (frame) { + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_AUDIO_SERVICE_TYPE); + if (sd && sd->size >= sizeof(enum AVAudioServiceType)) + avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data; + } + /* check for valid frame size */ if (frame) { - if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { + if (avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) { if (frame->nb_samples > avctx->frame_size) return AVERROR(EINVAL); - } else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { + } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) { if (frame->nb_samples < avctx->frame_size && !avctx->internal->last_audio_frame) { ret = pad_last_frame(avctx, &padded_frame, frame); @@ -1371,7 +1339,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); if (!ret) { if (*got_packet_ptr) { - if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) { + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { if (avpkt->pts == AV_NOPTS_VALUE) avpkt->pts = frame->pts; if (!avpkt->duration) @@ -1393,7 +1361,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, } if (ret < 0 || !*got_packet_ptr) { - av_free_packet(avpkt); + av_packet_unref(avpkt); av_init_packet(avpkt); goto end; } @@ -1406,6 +1374,10 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, end: av_frame_free(&padded_frame); +#if FF_API_AUDIOENC_DELAY + avctx->delay = avctx->initial_padding; +#endif + return ret; } @@ -1419,8 +1391,13 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, *got_packet_ptr = 0; - if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { - av_free_packet(avpkt); + if (!avctx->codec->encode2) { + av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n"); + return AVERROR(ENOSYS); + } + + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) && !frame) { + av_packet_unref(avpkt); av_init_packet(avpkt); avpkt->size = 0; return 0; @@ -1435,7 +1412,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, if (!ret) { if (!*got_packet_ptr) avpkt->size = 0; - else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) + else if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) avpkt->pts = avpkt->dts = frame->pts; if (!user_packet && avpkt->size) { @@ -1448,7 +1425,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, } if (ret < 0 || !*got_packet_ptr) - av_free_packet(avpkt); + av_packet_unref(avpkt); emms_c(); return ret; @@ -1479,10 +1456,11 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) if (!data) return 0; - if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) { + if (!(avctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE)) { av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter " "changes, but PARAM_CHANGE side data was sent to it.\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail2; } if (size < 4) @@ -1517,13 +1495,20 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) size -= 8; ret = ff_set_dimensions(avctx, avctx->width, avctx->height); if (ret < 0) - return ret; + goto fail2; } return 0; fail: av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; +fail2: + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) + return ret; + } + return 0; } static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame) @@ -1582,26 +1567,30 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx)) return -1; + if (!avctx->codec->decode) { + av_log(avctx, AV_LOG_ERROR, "This decoder requires using the avcodec_send_packet() API.\n"); + return AVERROR(ENOSYS); + } + avctx->internal->pkt = avpkt; ret = apply_param_change(avctx, avpkt); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n"); - if (avctx->err_recognition & AV_EF_EXPLODE) - return ret; - } + if (ret < 0) + return ret; av_frame_unref(picture); - if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) { + if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size || + (avctx->active_thread_type & FF_THREAD_FRAME)) { if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr, avpkt); else { ret = avctx->codec->decode(avctx, picture, got_picture_ptr, avpkt); - picture->pkt_dts = avpkt->dts; + if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) + picture->pkt_dts = avpkt->dts; /* get_buffer is supposed to set frame parameters */ - if (!(avctx->codec->capabilities & CODEC_CAP_DR1)) { + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) { picture->sample_aspect_ratio = avctx->sample_aspect_ratio; picture->width = avctx->width; picture->height = avctx->height; @@ -1624,6 +1613,11 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi } else ret = 0; +#if FF_API_AVCTX_TIMEBASE + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + avctx->time_base = av_inv_q(avctx->framerate); +#endif + return ret; } @@ -1637,6 +1631,11 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, *got_frame_ptr = 0; + if (!avctx->codec->decode) { + av_log(avctx, AV_LOG_ERROR, "This decoder requires using the avcodec_send_packet() API.\n"); + return AVERROR(ENOSYS); + } + avctx->internal->pkt = avpkt; if (!avpkt->data && avpkt->size) { @@ -1645,15 +1644,12 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, } ret = apply_param_change(avctx, avpkt); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n"); - if (avctx->err_recognition & AV_EF_EXPLODE) - return ret; - } + if (ret < 0) + return ret; av_frame_unref(frame); - if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) { + if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) { ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt); if (ret >= 0 && *got_frame_ptr) { avctx->frame_number++; @@ -1693,10 +1689,10 @@ void avsubtitle_free(AVSubtitle *sub) int i; for (i = 0; i < sub->num_rects; i++) { - av_freep(&sub->rects[i]->pict.data[0]); - av_freep(&sub->rects[i]->pict.data[1]); - av_freep(&sub->rects[i]->pict.data[2]); - av_freep(&sub->rects[i]->pict.data[3]); + av_freep(&sub->rects[i]->data[0]); + av_freep(&sub->rects[i]->data[1]); + av_freep(&sub->rects[i]->data[2]); + av_freep(&sub->rects[i]->data[3]); av_freep(&sub->rects[i]->text); av_freep(&sub->rects[i]->ass); av_freep(&sub->rects[i]); @@ -1707,17 +1703,257 @@ void avsubtitle_free(AVSubtitle *sub) memset(sub, 0, sizeof(AVSubtitle)); } +static int do_decode(AVCodecContext *avctx, AVPacket *pkt) +{ + int got_frame; + int ret; + + av_assert0(!avctx->internal->buffer_frame->buf[0]); + + if (!pkt) + pkt = avctx->internal->buffer_pkt; + + // This is the lesser evil. The field is for compatibility with legacy users + // of the legacy API, and users using the new API should not be forced to + // even know about this field. + avctx->refcounted_frames = 1; + + // Some codecs (at least wma lossless) will crash when feeding drain packets + // after EOF was signaled. + if (avctx->internal->draining_done) + return AVERROR_EOF; + + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = avcodec_decode_video2(avctx, avctx->internal->buffer_frame, + &got_frame, pkt); + if (ret >= 0) + ret = pkt->size; + } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = avcodec_decode_audio4(avctx, avctx->internal->buffer_frame, + &got_frame, pkt); + } else { + ret = AVERROR(EINVAL); + } + + if (ret < 0) + return ret; + + if (avctx->internal->draining && !got_frame) + avctx->internal->draining_done = 1; + + if (ret >= pkt->size) { + av_packet_unref(avctx->internal->buffer_pkt); + } else { + int consumed = ret; + + if (pkt != avctx->internal->buffer_pkt) { + av_packet_unref(avctx->internal->buffer_pkt); + if ((ret = av_packet_ref(avctx->internal->buffer_pkt, pkt)) < 0) + return ret; + } + + avctx->internal->buffer_pkt->data += consumed; + avctx->internal->buffer_pkt->size -= consumed; + avctx->internal->buffer_pkt->pts = AV_NOPTS_VALUE; + avctx->internal->buffer_pkt->dts = AV_NOPTS_VALUE; + } + + if (got_frame) + av_assert0(avctx->internal->buffer_frame->buf[0]); + + return 0; +} + +int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt) +{ + int ret; + + if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avctx->internal->draining) + return AVERROR_EOF; + + if (!avpkt || !avpkt->size) { + avctx->internal->draining = 1; + avpkt = NULL; + + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + return 0; + } + + if (avctx->codec->send_packet) { + if (avpkt) { + ret = apply_param_change(avctx, (AVPacket *)avpkt); + if (ret < 0) + return ret; + } + return avctx->codec->send_packet(avctx, avpkt); + } + + // Emulation via old API. Assume avpkt is likely not refcounted, while + // decoder output is always refcounted, and avoid copying. + + if (avctx->internal->buffer_pkt->size || avctx->internal->buffer_frame->buf[0]) + return AVERROR(EAGAIN); + + // The goal is decoding the first frame of the packet without using memcpy, + // because the common case is having only 1 frame per packet (especially + // with video, but audio too). In other cases, it can't be avoided, unless + // the user is feeding refcounted packets. + return do_decode(avctx, (AVPacket *)avpkt); +} + +int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) +{ + int ret; + + av_frame_unref(frame); + + if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avctx->codec->receive_frame) { + if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + return AVERROR_EOF; + return avctx->codec->receive_frame(avctx, frame); + } + + // Emulation via old API. + + if (!avctx->internal->buffer_frame->buf[0]) { + if (!avctx->internal->buffer_pkt->size && !avctx->internal->draining) + return AVERROR(EAGAIN); + + while (1) { + if ((ret = do_decode(avctx, avctx->internal->buffer_pkt)) < 0) { + av_packet_unref(avctx->internal->buffer_pkt); + return ret; + } + // Some audio decoders may consume partial data without returning + // a frame (fate-wmapro-2ch). There is no way to make the caller + // call avcodec_receive_frame() again without returning a frame, + // so try to decode more in these cases. + if (avctx->internal->buffer_frame->buf[0] || + !avctx->internal->buffer_pkt->size) + break; + } + } + + if (!avctx->internal->buffer_frame->buf[0]) + return avctx->internal->draining ? AVERROR_EOF : AVERROR(EAGAIN); + + av_frame_move_ref(frame, avctx->internal->buffer_frame); + return 0; +} + +static int do_encode(AVCodecContext *avctx, const AVFrame *frame, int *got_packet) +{ + int ret; + *got_packet = 0; + + av_packet_unref(avctx->internal->buffer_pkt); + avctx->internal->buffer_pkt_valid = 0; + + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = avcodec_encode_video2(avctx, avctx->internal->buffer_pkt, + frame, got_packet); + } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = avcodec_encode_audio2(avctx, avctx->internal->buffer_pkt, + frame, got_packet); + } else { + ret = AVERROR(EINVAL); + } + + if (ret >= 0 && *got_packet) { + // Encoders must always return ref-counted buffers. + // Side-data only packets have no data and can be not ref-counted. + av_assert0(!avctx->internal->buffer_pkt->data || avctx->internal->buffer_pkt->buf); + avctx->internal->buffer_pkt_valid = 1; + ret = 0; + } else { + av_packet_unref(avctx->internal->buffer_pkt); + } + + return ret; +} + +int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avctx->internal->draining) + return AVERROR_EOF; + + if (!frame) { + avctx->internal->draining = 1; + + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + return 0; + } + + if (avctx->codec->send_frame) + return avctx->codec->send_frame(avctx, frame); + + // Emulation via old API. Do it here instead of avcodec_receive_packet, because: + // 1. if the AVFrame is not refcounted, the copying will be much more + // expensive than copying the packet data + // 2. assume few users use non-refcounted AVPackets, so usually no copy is + // needed + + if (avctx->internal->buffer_pkt_valid) + return AVERROR(EAGAIN); + + return do_encode(avctx, frame, &(int){0}); +} + +int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +{ + av_packet_unref(avpkt); + + if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avctx->codec->receive_packet) { + if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + return AVERROR_EOF; + return avctx->codec->receive_packet(avctx, avpkt); + } + + // Emulation via old API. + + if (!avctx->internal->buffer_pkt_valid) { + int got_packet; + int ret; + if (!avctx->internal->draining) + return AVERROR(EAGAIN); + ret = do_encode(avctx, NULL, &got_packet); + if (ret < 0) + return ret; + if (ret >= 0 && !got_packet) + return AVERROR_EOF; + } + + av_packet_move_ref(avpkt, avctx->internal->buffer_pkt); + avctx->internal->buffer_pkt_valid = 0; + return 0; +} + av_cold int avcodec_close(AVCodecContext *avctx) { + int i; + if (avcodec_is_open(avctx)) { FramePool *pool = avctx->internal->pool; - int i; + if (HAVE_THREADS && avctx->internal->thread_ctx) ff_thread_free(avctx); if (avctx->codec && avctx->codec->close) avctx->codec->close(avctx); - avctx->coded_frame = NULL; av_frame_free(&avctx->internal->to_free); + av_frame_free(&avctx->internal->buffer_frame); + av_packet_free(&avctx->internal->buffer_pkt); for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) av_buffer_pool_uninit(&pool->pools[i]); av_freep(&avctx->internal->pool); @@ -1729,12 +1965,25 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_freep(&avctx->internal); } + for (i = 0; i < avctx->nb_coded_side_data; i++) + av_freep(&avctx->coded_side_data[i].data); + av_freep(&avctx->coded_side_data); + avctx->nb_coded_side_data = 0; + + av_buffer_unref(&avctx->hw_frames_ctx); + if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) av_opt_free(avctx->priv_data); av_opt_free(avctx); av_freep(&avctx->priv_data); - if (av_codec_is_encoder(avctx->codec)) + if (av_codec_is_encoder(avctx->codec)) { av_freep(&avctx->extradata); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_free(&avctx->coded_frame); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } avctx->codec = NULL; avctx->active_thread_type = 0; @@ -1748,7 +1997,7 @@ static AVCodec *find_encdec(enum AVCodecID id, int encoder) while (p) { if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) && p->id == id) { - if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { + if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) { experimental = p; } else return p; @@ -1843,21 +2092,15 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { const char *codec_name; const char *profile = NULL; - const AVCodec *p; char buf1[32]; int bitrate; + int new_line = 0; AVRational display_aspect_ratio; + const AVCodecDescriptor *desc = avcodec_descriptor_get(enc->codec_id); - if (enc->codec) - p = enc->codec; - else if (encode) - p = avcodec_find_encoder(enc->codec_id); - else - p = avcodec_find_decoder(enc->codec_id); - - if (p) { - codec_name = p->name; - profile = av_get_profile_name(p, enc->profile); + if (desc) { + codec_name = desc->name; + profile = avcodec_profile_name(enc->codec_id, enc->profile); } else if (enc->codec_id == AV_CODEC_ID_MPEG2TS) { /* fake mpeg2 transport stream codec (currently not * registered) */ @@ -1878,15 +2121,48 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (profile) snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); - if (enc->pix_fmt != AV_PIX_FMT_NONE) { + if (enc->codec_tag) { + char tag_buf[32]; + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag); snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %s", + " [%s / 0x%04X]", tag_buf, enc->codec_tag); + } + + av_strlcat(buf, "\n ", buf_size); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(enc->pix_fmt)); + + if (enc->color_range != AVCOL_RANGE_UNSPECIFIED) + snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s", + av_color_range_name(enc->color_range)); + if (enc->colorspace != AVCOL_SPC_UNSPECIFIED || + enc->color_primaries != AVCOL_PRI_UNSPECIFIED || + enc->color_trc != AVCOL_TRC_UNSPECIFIED) { + new_line = 1; + snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s/%s/%s", + av_color_space_name(enc->colorspace), + av_color_primaries_name(enc->color_primaries), + av_color_transfer_name(enc->color_trc)); } + if (av_log_get_level() >= AV_LOG_DEBUG && + enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) + snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s", + av_chroma_location_name(enc->chroma_sample_location)); + if (enc->width) { + av_strlcat(buf, new_line ? "\n " : ", ", buf_size); + snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %dx%d", + "%dx%d", enc->width, enc->height); + + if (av_log_get_level() >= AV_LOG_VERBOSE && + (enc->width != enc->coded_width || + enc->height != enc->coded_height)) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%dx%d)", enc->coded_width, enc->coded_height); + if (enc->sample_aspect_ratio.num) { av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, enc->width * enc->sample_aspect_ratio.num, @@ -1916,11 +2192,18 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (profile) snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); + if (enc->codec_tag) { + char tag_buf[32]; + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " [%s / 0x%04X]", tag_buf, enc->codec_tag); + } + + av_strlcat(buf, "\n ", buf_size); if (enc->sample_rate) { snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %d Hz", enc->sample_rate); + "%d Hz, ", enc->sample_rate); } - av_strlcat(buf, ", ", buf_size); av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout); if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) { snprintf(buf + strlen(buf), buf_size - strlen(buf), @@ -1941,10 +2224,10 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) return; } if (encode) { - if (enc->flags & CODEC_FLAG_PASS1) + if (enc->flags & AV_CODEC_FLAG_PASS1) snprintf(buf + strlen(buf), buf_size - strlen(buf), ", pass 1"); - if (enc->flags & CODEC_FLAG_PASS2) + if (enc->flags & AV_CODEC_FLAG_PASS2) snprintf(buf + strlen(buf), buf_size - strlen(buf), ", pass 2"); } @@ -1968,6 +2251,21 @@ const char *av_get_profile_name(const AVCodec *codec, int profile) return NULL; } +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile) +{ + const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); + const AVProfile *p; + + if (profile == FF_PROFILE_UNKNOWN || !desc || !desc->profiles) + return NULL; + + for (p = desc->profiles; p->profile != FF_PROFILE_UNKNOWN; p++) + if (p->profile == profile) + return p->name; + + return NULL; +} + unsigned avcodec_version(void) { return LIBAVCODEC_VERSION_INT; @@ -1986,6 +2284,12 @@ const char *avcodec_license(void) void avcodec_flush_buffers(AVCodecContext *avctx) { + avctx->internal->draining = 0; + avctx->internal->draining_done = 0; + av_frame_unref(avctx->internal->buffer_frame); + av_packet_unref(avctx->internal->buffer_pkt); + avctx->internal->buffer_pkt_valid = 0; + if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) ff_thread_flush(avctx); else if (avctx->codec->flush) @@ -2012,6 +2316,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) case AV_CODEC_ID_PCM_ZORK: return 8; case AV_CODEC_ID_PCM_S16BE: + case AV_CODEC_ID_PCM_S16BE_PLANAR: case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16LE_PLANAR: case AV_CODEC_ID_PCM_U16BE: @@ -2058,21 +2363,15 @@ int av_get_bits_per_sample(enum AVCodecID codec_id) } } -int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) +static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, + uint32_t tag, int bits_per_coded_sample, int frame_bytes) { - int id, sr, ch, ba, tag, bps; - - id = avctx->codec_id; - sr = avctx->sample_rate; - ch = avctx->channels; - ba = avctx->block_align; - tag = avctx->codec_tag; - bps = av_get_exact_bits_per_sample(avctx->codec_id); + int bps = av_get_exact_bits_per_sample(id); /* codecs with an exact constant bits per sample */ if (bps > 0 && ch > 0 && frame_bytes > 0) return (frame_bytes * 8) / (bps * ch); - bps = avctx->bits_per_coded_sample; + bps = bits_per_coded_sample; /* codecs with a fixed packet duration */ switch (id) { @@ -2176,7 +2475,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) if (ba > 0) { /* calc from frame_bytes, channels, and block_align */ int blocks = frame_bytes / ba; - switch (avctx->codec_id) { + switch (id) { case AV_CODEC_ID_ADPCM_IMA_WAV: return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8); case AV_CODEC_ID_ADPCM_IMA_DK3: @@ -2190,7 +2489,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) if (bps > 0) { /* calc from frame_bytes, channels, and bits_per_coded_sample */ - switch (avctx->codec_id) { + switch (id) { case AV_CODEC_ID_PCM_DVD: return 2 * (frame_bytes / ((bps * 2 / 8) * ch)); case AV_CODEC_ID_PCM_BLURAY: @@ -2205,6 +2504,22 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) return 0; } +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) +{ + return get_audio_frame_duration(avctx->codec_id, avctx->sample_rate, + avctx->channels, avctx->block_align, + avctx->codec_tag, avctx->bits_per_coded_sample, + frame_bytes); +} + +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes) +{ + return get_audio_frame_duration(par->codec_id, par->sample_rate, + par->channels, par->block_align, + par->codec_tag, par->bits_per_coded_sample, + frame_bytes); +} + #if !HAVE_THREADS int ff_thread_init(AVCodecContext *s) { @@ -2282,20 +2597,32 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { if (lockmgr_cb) { - if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) - return -1; - if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) - return -1; + // There is no good way to rollback a failure to destroy the + // mutex, so we ignore failures. + lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY); + lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY); + lockmgr_cb = NULL; + codec_mutex = NULL; + avformat_mutex = NULL; + } + + if (cb) { + void *new_codec_mutex = NULL; + void *new_avformat_mutex = NULL; + int err; + if (err = cb(&new_codec_mutex, AV_LOCK_CREATE)) { + return err > 0 ? AVERROR_UNKNOWN : err; + } + if (err = cb(&new_avformat_mutex, AV_LOCK_CREATE)) { + // Ignore failures to destroy the newly created mutex. + cb(&new_codec_mutex, AV_LOCK_DESTROY); + return err > 0 ? AVERROR_UNKNOWN : err; + } + lockmgr_cb = cb; + codec_mutex = new_codec_mutex; + avformat_mutex = new_avformat_mutex; } - lockmgr_cb = cb; - - if (lockmgr_cb) { - if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) - return -1; - if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) - return -1; - } return 0; } @@ -2372,20 +2699,6 @@ void ff_thread_await_progress(ThreadFrame *f, int progress, int field) #endif -enum AVMediaType avcodec_get_type(enum AVCodecID codec_id) -{ - if (codec_id <= AV_CODEC_ID_NONE) - return AVMEDIA_TYPE_UNKNOWN; - else if (codec_id < AV_CODEC_ID_FIRST_AUDIO) - return AVMEDIA_TYPE_VIDEO; - else if (codec_id < AV_CODEC_ID_FIRST_SUBTITLE) - return AVMEDIA_TYPE_AUDIO; - else if (codec_id < AV_CODEC_ID_FIRST_UNKNOWN) - return AVMEDIA_TYPE_SUBTITLE; - - return AVMEDIA_TYPE_UNKNOWN; -} - int avcodec_is_open(AVCodecContext *s) { return !!s->internal; @@ -2423,3 +2736,195 @@ const uint8_t *avpriv_find_start_code(const uint8_t *restrict p, return p + 4; } + +AVCPBProperties *av_cpb_properties_alloc(size_t *size) +{ + AVCPBProperties *props = av_mallocz(sizeof(AVCPBProperties)); + if (!props) + return NULL; + + if (size) + *size = sizeof(*props); + + props->vbv_delay = UINT64_MAX; + + return props; +} + +AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx) +{ + AVPacketSideData *tmp; + AVCPBProperties *props; + size_t size; + + props = av_cpb_properties_alloc(&size); + if (!props) + return NULL; + + tmp = av_realloc_array(avctx->coded_side_data, avctx->nb_coded_side_data + 1, sizeof(*tmp)); + if (!tmp) { + av_freep(&props); + return NULL; + } + + avctx->coded_side_data = tmp; + avctx->nb_coded_side_data++; + + avctx->coded_side_data[avctx->nb_coded_side_data - 1].type = AV_PKT_DATA_CPB_PROPERTIES; + avctx->coded_side_data[avctx->nb_coded_side_data - 1].data = (uint8_t*)props; + avctx->coded_side_data[avctx->nb_coded_side_data - 1].size = size; + + return props; +} + +static void codec_parameters_reset(AVCodecParameters *par) +{ + av_freep(&par->extradata); + + memset(par, 0, sizeof(*par)); + + par->codec_type = AVMEDIA_TYPE_UNKNOWN; + par->codec_id = AV_CODEC_ID_NONE; + par->format = -1; + par->field_order = AV_FIELD_UNKNOWN; + par->color_range = AVCOL_RANGE_UNSPECIFIED; + par->color_primaries = AVCOL_PRI_UNSPECIFIED; + par->color_trc = AVCOL_TRC_UNSPECIFIED; + par->color_space = AVCOL_SPC_UNSPECIFIED; + par->chroma_location = AVCHROMA_LOC_UNSPECIFIED; + par->sample_aspect_ratio = (AVRational){ 0, 1 }; +} + +AVCodecParameters *avcodec_parameters_alloc(void) +{ + AVCodecParameters *par = av_mallocz(sizeof(*par)); + + if (!par) + return NULL; + codec_parameters_reset(par); + return par; +} + +void avcodec_parameters_free(AVCodecParameters **ppar) +{ + AVCodecParameters *par = *ppar; + + if (!par) + return; + codec_parameters_reset(par); + + av_freep(ppar); +} + +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src) +{ + codec_parameters_reset(dst); + memcpy(dst, src, sizeof(*dst)); + + dst->extradata = NULL; + dst->extradata_size = 0; + if (src->extradata) { + dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!dst->extradata) + return AVERROR(ENOMEM); + memcpy(dst->extradata, src->extradata, src->extradata_size); + dst->extradata_size = src->extradata_size; + } + + return 0; +} + +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec) +{ + codec_parameters_reset(par); + + par->codec_type = codec->codec_type; + par->codec_id = codec->codec_id; + par->codec_tag = codec->codec_tag; + + par->bit_rate = codec->bit_rate; + par->bits_per_coded_sample = codec->bits_per_coded_sample; + par->profile = codec->profile; + par->level = codec->level; + + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + par->format = codec->pix_fmt; + par->width = codec->width; + par->height = codec->height; + par->field_order = codec->field_order; + par->color_range = codec->color_range; + par->color_primaries = codec->color_primaries; + par->color_trc = codec->color_trc; + par->color_space = codec->colorspace; + par->chroma_location = codec->chroma_sample_location; + par->sample_aspect_ratio = codec->sample_aspect_ratio; + break; + case AVMEDIA_TYPE_AUDIO: + par->format = codec->sample_fmt; + par->channel_layout = codec->channel_layout; + par->channels = codec->channels; + par->sample_rate = codec->sample_rate; + par->block_align = codec->block_align; + par->initial_padding = codec->initial_padding; + break; + } + + if (codec->extradata) { + par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) + return AVERROR(ENOMEM); + memcpy(par->extradata, codec->extradata, codec->extradata_size); + par->extradata_size = codec->extradata_size; + } + + return 0; +} + +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par) +{ + codec->codec_type = par->codec_type; + codec->codec_id = par->codec_id; + codec->codec_tag = par->codec_tag; + + codec->bit_rate = par->bit_rate; + codec->bits_per_coded_sample = par->bits_per_coded_sample; + codec->profile = par->profile; + codec->level = par->level; + + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + codec->pix_fmt = par->format; + codec->width = par->width; + codec->height = par->height; + codec->field_order = par->field_order; + codec->color_range = par->color_range; + codec->color_primaries = par->color_primaries; + codec->color_trc = par->color_trc; + codec->colorspace = par->color_space; + codec->chroma_sample_location = par->chroma_location; + codec->sample_aspect_ratio = par->sample_aspect_ratio; + break; + case AVMEDIA_TYPE_AUDIO: + codec->sample_fmt = par->format; + codec->channel_layout = par->channel_layout; + codec->channels = par->channels; + codec->sample_rate = par->sample_rate; + codec->block_align = par->block_align; + codec->initial_padding = par->initial_padding; + break; + } + + if (par->extradata) { + av_freep(&codec->extradata); + codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!codec->extradata) + return AVERROR(ENOMEM); + memcpy(codec->extradata, par->extradata, par->extradata_size); + codec->extradata_size = par->extradata_size; + } + + return 0; +} diff --git a/libavcodec/utvideo.c b/libavcodec/utvideo.c index eb5a924..35e927c 100644 --- a/libavcodec/utvideo.c +++ b/libavcodec/utvideo.c @@ -26,9 +26,11 @@ #include "utvideo.h" +#if FF_API_PRIVATE_OPT const int ff_ut_pred_order[5] = { PRED_LEFT, PRED_MEDIAN, PRED_MEDIAN, PRED_NONE, PRED_GRADIENT }; +#endif const int ff_ut_rgb_order[4] = { 1, 2, 0, 3 }; // G, B, R, A diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index 718273c..0035e9c 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -65,6 +65,7 @@ extern const int ff_ut_pred_order[5]; extern const int ff_ut_rgb_order[4]; typedef struct UtvideoContext { + const AVClass *class; AVCodecContext *avctx; BswapDSPContext bdsp; HuffYUVEncDSPContext hdsp; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index bb8c7aa..30ca4d2 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -142,7 +142,7 @@ static int decode_plane(UtvideoContext *c, int plane_no, memcpy(c->slice_bits, src + slice_data_start + c->slices * 4, slice_size); - memset(c->slice_bits + slice_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); c->bdsp.bswap_buf((uint32_t *) c->slice_bits, (uint32_t *) c->slice_bits, (slice_data_end - slice_data_start + 3) >> 2); @@ -388,7 +388,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - max_slice_size + FF_INPUT_BUFFER_PADDING_SIZE); + max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->slice_bits) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); @@ -562,5 +562,5 @@ AVCodec ff_utvideo_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index 8dc208b..4eddd98 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -26,6 +26,8 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + #include "avcodec.h" #include "internal.h" #include "bswapdsp.h" @@ -48,7 +50,6 @@ static av_cold int utvideo_encode_close(AVCodecContext *avctx) UtvideoContext *c = avctx->priv_data; int i; - av_freep(&avctx->coded_frame); av_freep(&c->slice_bits); for (i = 0; i < 4; i++) av_freep(&c->slice_buffer[i]); @@ -112,6 +113,8 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) ff_bswapdsp_init(&c->bdsp); ff_huffyuvencdsp_init(&c->hdsp); +#if FF_API_PRIVATE_OPT +FF_DISABLE_DEPRECATION_WARNINGS /* Check the prediction method, and error out if unsupported */ if (avctx->prediction_method < 0 || avctx->prediction_method > 4) { av_log(avctx, AV_LOG_WARNING, @@ -127,7 +130,10 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) } /* Convert from libavcodec prediction type to Ut Video's */ - c->frame_pred = ff_ut_pred_order[avctx->prediction_method]; + if (avctx->prediction_method) + c->frame_pred = ff_ut_pred_order[avctx->prediction_method]; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (c->frame_pred == PRED_GRADIENT) { av_log(avctx, AV_LOG_ERROR, "Gradient prediction is not supported.\n"); @@ -154,19 +160,11 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - avctx->coded_frame = av_frame_alloc(); - - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); - utvideo_encode_close(avctx); - return AVERROR(ENOMEM); - } - - /* extradata size is 4 * 32bit */ + /* extradata size is 4 * 32 bits */ avctx->extradata_size = 16; avctx->extradata = av_mallocz(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata.\n"); @@ -176,7 +174,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) for (i = 0; i < c->planes; i++) { c->slice_buffer[i] = av_malloc(c->slice_stride * (avctx->height + 2) + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->slice_buffer[i]) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 1.\n"); utvideo_encode_close(avctx); @@ -373,7 +371,7 @@ static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size, src += width; } - /* Pad output to a 32bit boundary */ + /* Pad output to a 32-bit boundary */ count = put_bits_count(&pb) & 0x1F; if (count) @@ -556,7 +554,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream2_init_writer(&pb, dst, pkt->size); av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - width * height + FF_INPUT_BUFFER_PADDING_SIZE); + width * height + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->slice_bits) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); @@ -613,7 +611,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* - * Write frame information (LE 32bit unsigned) + * Write frame information (LE 32-bit unsigned) * into the output packet. * Contains the prediction method. */ @@ -624,8 +622,12 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, * At least currently Ut Video is IDR only. * Set flags accordingly. */ +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->size = bytestream2_tell_p(&pb); pkt->flags |= AV_PKT_FLAG_KEY; @@ -636,12 +638,32 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } +#define OFFSET(x) offsetof(UtvideoContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { +{ "pred", "Prediction method", OFFSET(frame_pred), AV_OPT_TYPE_INT, { .i64 = PRED_LEFT }, PRED_NONE, PRED_MEDIAN, VE, "pred" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_NONE }, INT_MIN, INT_MAX, VE, "pred" }, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_LEFT }, INT_MIN, INT_MAX, VE, "pred" }, + { "gradient", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_GRADIENT }, INT_MIN, INT_MAX, VE, "pred" }, + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_MEDIAN }, INT_MIN, INT_MAX, VE, "pred" }, + + { NULL}, +}; + +static const AVClass utvideo_class = { + .class_name = "utvideo", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_utvideo_encoder = { .name = "utvideo", .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_UTVIDEO, .priv_data_size = sizeof(UtvideoContext), + .priv_class = &utvideo_class, .init = utvideo_encode_init, .encode2 = utvideo_encode_frame, .close = utvideo_encode_close, diff --git a/libavcodec/v210dec.c b/libavcodec/v210dec.c index 8827397..74301fe 100644 --- a/libavcodec/v210dec.c +++ b/libavcodec/v210dec.c @@ -113,5 +113,5 @@ AVCodec ff_v210_decoder = { .id = AV_CODEC_ID_V210, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index ef0d6ab..51c182c 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -24,23 +24,91 @@ #include "avcodec.h" #include "bytestream.h" #include "internal.h" +#include "v210enc.h" + +#define CLIP(v) av_clip(v, 4, 1019) +#define CLIP8(v) av_clip(v, 1, 254) + +#define WRITE_PIXELS(a, b, c) \ + do { \ + val = CLIP(*a++); \ + val |= (CLIP(*b++) << 10) | \ + (CLIP(*c++) << 20); \ + AV_WL32(dst, val); \ + dst += 4; \ + } while (0) + +#define WRITE_PIXELS8(a, b, c) \ + do { \ + val = (CLIP8(*a++) << 2); \ + val |= (CLIP8(*b++) << 12) | \ + (CLIP8(*c++) << 22); \ + AV_WL32(dst, val); \ + dst += 4; \ + } while (0) + +static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, + ptrdiff_t width) +{ + uint32_t val; + int i; + + /* unroll this to match the assembly */ + for (i = 0; i < width - 11; i += 12) { + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + } +} + +static void v210_planar_pack_10_c(const uint16_t *y, const uint16_t *u, + const uint16_t *v, uint8_t *dst, + ptrdiff_t width) +{ + uint32_t val; + int i; + + for (i = 0; i < width - 5; i += 6) { + WRITE_PIXELS(u, y, v); + WRITE_PIXELS(y, u, y); + WRITE_PIXELS(v, y, u); + WRITE_PIXELS(y, v, y); + } +} + +av_cold void ff_v210enc_init(V210EncContext *s) +{ + s->pack_line_8 = v210_planar_pack_8_c; + s->pack_line_10 = v210_planar_pack_10_c; + s->sample_factor_8 = 1; + s->sample_factor_10 = 1; + + if (ARCH_X86) + ff_v210enc_init_x86(s); +} static av_cold int encode_init(AVCodecContext *avctx) { + V210EncContext *s = avctx->priv_data; + if (avctx->width & 1) { av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n"); return AVERROR(EINVAL); } - if (avctx->bits_per_raw_sample != 10) - av_log(avctx, AV_LOG_WARNING, "bits per raw sample: %d != 10-bit\n", - avctx->bits_per_raw_sample); - - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + ff_v210enc_init(s); return 0; } @@ -48,60 +116,118 @@ static av_cold int encode_init(AVCodecContext *avctx) static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) { + V210EncContext *s = avctx->priv_data; int aligned_width = ((avctx->width + 47) / 48) * 48; int stride = aligned_width * 8 / 3; int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4; int h, w, ret; - const uint16_t *y = (const uint16_t*)pic->data[0]; - const uint16_t *u = (const uint16_t*)pic->data[1]; - const uint16_t *v = (const uint16_t*)pic->data[2]; - PutByteContext p; + uint8_t *dst; - if ((ret = ff_alloc_packet(pkt, avctx->height * stride)) < 0) { + ret = ff_alloc_packet(pkt, avctx->height * stride); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; } - - bytestream2_init_writer(&p, pkt->data, pkt->size); - -#define CLIP(v) av_clip(v, 4, 1019) - -#define WRITE_PIXELS(a, b, c) \ - do { \ - val = CLIP(*a++); \ - val |= (CLIP(*b++) << 10) | \ - (CLIP(*c++) << 20); \ - bytestream2_put_le32u(&p, val); \ - } while (0) - - for (h = 0; h < avctx->height; h++) { - uint32_t val; - for (w = 0; w < avctx->width - 5; w += 6) { - WRITE_PIXELS(u, y, v); - WRITE_PIXELS(y, u, y); - WRITE_PIXELS(v, y, u); - WRITE_PIXELS(y, v, y); - } - if (w < avctx->width - 1) { - WRITE_PIXELS(u, y, v); - - val = CLIP(*y++); - if (w == avctx->width - 2) - bytestream2_put_le32u(&p, val); + dst = pkt->data; + + if (pic->format == AV_PIX_FMT_YUV422P10) { + const uint16_t *y = (const uint16_t *)pic->data[0]; + const uint16_t *u = (const uint16_t *)pic->data[1]; + const uint16_t *v = (const uint16_t *)pic->data[2]; + + const int sample_size = 6 * s->sample_factor_10; + const int sample_w = avctx->width / sample_size; + + for (h = 0; h < avctx->height; h++) { + uint32_t val; + w = sample_w * sample_size; + s->pack_line_10(y, u, v, dst, w); + + y += w; + u += w >> 1; + v += w >> 1; + dst += sample_w * 16 * s->sample_factor_10; + + for (; w < avctx->width - 5; w += 6) { + WRITE_PIXELS(u, y, v); + WRITE_PIXELS(y, u, y); + WRITE_PIXELS(v, y, u); + WRITE_PIXELS(y, v, y); + } + if (w < avctx->width - 1) { + WRITE_PIXELS(u, y, v); + + val = CLIP(*y++); + if (w == avctx->width - 2) { + AV_WL32(dst, val); + dst += 4; + } + } + if (w < avctx->width - 3) { + val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); + AV_WL32(dst, val); + dst += 4; + + val = CLIP(*v++) | (CLIP(*y++) << 10); + AV_WL32(dst, val); + dst += 4; + } + + memset(dst, 0, line_padding); + dst += line_padding; + y += pic->linesize[0] / 2 - avctx->width; + u += pic->linesize[1] / 2 - avctx->width / 2; + v += pic->linesize[2] / 2 - avctx->width / 2; } - if (w < avctx->width - 3) { - val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); - bytestream2_put_le32u(&p, val); - - val = CLIP(*v++) | (CLIP(*y++) << 10); - bytestream2_put_le32u(&p, val); + } else if(pic->format == AV_PIX_FMT_YUV422P) { + const uint8_t *y = pic->data[0]; + const uint8_t *u = pic->data[1]; + const uint8_t *v = pic->data[2]; + + const int sample_size = 12 * s->sample_factor_8; + const int sample_w = avctx->width / sample_size; + + for (h = 0; h < avctx->height; h++) { + uint32_t val; + w = sample_w * sample_size; + s->pack_line_8(y, u, v, dst, w); + + y += w; + u += w >> 1; + v += w >> 1; + dst += sample_w * 32 * s->sample_factor_8; + + for (; w < avctx->width - 5; w += 6) { + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + } + if (w < avctx->width - 1) { + WRITE_PIXELS8(u, y, v); + + val = CLIP8(*y++) << 2; + if (w == avctx->width - 2) { + AV_WL32(dst, val); + dst += 4; + } + } + if (w < avctx->width - 3) { + val |= (CLIP8(*u++) << 12) | (CLIP8(*y++) << 22); + AV_WL32(dst, val); + dst += 4; + + val = (CLIP8(*v++) << 2) | (CLIP8(*y++) << 12); + AV_WL32(dst, val); + dst += 4; + } + memset(dst, 0, line_padding); + dst += line_padding; + + y += pic->linesize[0] - avctx->width; + u += pic->linesize[1] - avctx->width / 2; + v += pic->linesize[2] - avctx->width / 2; } - - bytestream2_set_buffer(&p, 0, line_padding); - - y += pic->linesize[0] / 2 - avctx->width; - u += pic->linesize[1] / 2 - avctx->width / 2; - v += pic->linesize[2] / 2 - avctx->width / 2; } pkt->flags |= AV_PKT_FLAG_KEY; @@ -109,20 +235,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int encode_close(AVCodecContext *avctx) -{ - av_freep(&avctx->coded_frame); - - return 0; -} - AVCodec ff_v210_encoder = { .name = "v210", .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_V210, + .priv_data_size = sizeof(V210EncContext), .init = encode_init, .encode2 = encode_frame, - .close = encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/v210enc.h b/libavcodec/v210enc.h new file mode 100644 index 0000000..ee3637a --- /dev/null +++ b/libavcodec/v210enc.h @@ -0,0 +1,39 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_V210ENC_H +#define AVCODEC_V210ENC_H + +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +typedef struct V210EncContext { + void (*pack_line_8)(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, ptrdiff_t width); + void (*pack_line_10)(const uint16_t *y, const uint16_t *u, + const uint16_t *v, uint8_t *dst, ptrdiff_t width); + int sample_factor_8; + int sample_factor_10; +} V210EncContext; + +void ff_v210enc_init(V210EncContext *s); + +void ff_v210enc_init_x86(V210EncContext *s); + +#endif /* AVCODEC_V210ENC_H */ diff --git a/libavcodec/v210x.c b/libavcodec/v210x.c index 2922c05..3f220ff 100644 --- a/libavcodec/v210x.c +++ b/libavcodec/v210x.c @@ -127,5 +127,5 @@ AVCodec ff_v210x_decoder = { .id = AV_CODEC_ID_V210X, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/v410dec.c b/libavcodec/v410dec.c index 07be502..ca68e0b 100644 --- a/libavcodec/v410dec.c +++ b/libavcodec/v410dec.c @@ -96,5 +96,5 @@ AVCodec ff_v410_decoder = { .id = AV_CODEC_ID_V410, .init = v410_decode_init, .decode = v410_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c index 77b32d7..1e3f38f 100644 --- a/libavcodec/v410enc.c +++ b/libavcodec/v410enc.c @@ -32,13 +32,6 @@ static av_cold int v410_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - avctx->coded_frame = av_frame_alloc(); - - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); - return AVERROR(ENOMEM); - } - return 0; } @@ -56,8 +49,12 @@ static int v410_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } dst = pkt->data; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif y = (uint16_t *)pic->data[0]; u = (uint16_t *)pic->data[1]; @@ -81,13 +78,6 @@ static int v410_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int v410_encode_close(AVCodecContext *avctx) -{ - av_freep(&avctx->coded_frame); - - return 0; -} - AVCodec ff_v410_encoder = { .name = "v410", .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), @@ -95,6 +85,5 @@ AVCodec ff_v410_encoder = { .id = AV_CODEC_ID_V410, .init = v410_encode_init, .encode2 = v410_encode_frame, - .close = v410_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/vaapi.c b/libavcodec/vaapi.c index fcc6243..d2aafac 100644 --- a/libavcodec/vaapi.c +++ b/libavcodec/vaapi.c @@ -21,7 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "h264.h" +#include "h264dec.h" +#include "mpegvideo.h" #include "vaapi_internal.h" /** @@ -180,8 +181,6 @@ void ff_vaapi_common_end_frame(AVCodecContext *avctx) { struct vaapi_context * const vactx = avctx->hwaccel_context; - av_dlog(avctx, "ff_vaapi_common_end_frame()\n"); - destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1); destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1); destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c new file mode 100644 index 0000000..cdda485 --- /dev/null +++ b/libavcodec/vaapi_encode.c @@ -0,0 +1,1336 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" + +#include "vaapi_encode.h" +#include "avcodec.h" + +static const char *picture_type_name[] = { "IDR", "I", "P", "B" }; + +static int vaapi_encode_make_packed_header(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int type, char *data, size_t bit_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAStatus vas; + VABufferID param_buffer, data_buffer; + VAEncPackedHeaderParameterBuffer params = { + .type = type, + .bit_length = bit_len, + .has_emulation_bytes = 1, + }; + + av_assert0(pic->nb_param_buffers + 2 <= MAX_PARAM_BUFFERS); + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAEncPackedHeaderParameterBufferType, + sizeof(params), 1, ¶ms, ¶m_buffer); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer " + "for packed header (type %d): %d (%s).\n", + type, vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + pic->param_buffers[pic->nb_param_buffers++] = param_buffer; + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAEncPackedHeaderDataBufferType, + (bit_len + 7) / 8, 1, data, &data_buffer); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create data buffer " + "for packed header (type %d): %d (%s).\n", + type, vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + pic->param_buffers[pic->nb_param_buffers++] = data_buffer; + + av_log(avctx, AV_LOG_DEBUG, "Packed header buffer (%d) is %#x/%#x " + "(%zu bits).\n", type, param_buffer, data_buffer, bit_len); + return 0; +} + +static int vaapi_encode_make_param_buffer(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int type, char *data, size_t len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAStatus vas; + VABufferID buffer; + + av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS); + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + type, len, 1, data, &buffer); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer " + "(type %d): %d (%s).\n", type, vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + pic->param_buffers[pic->nb_param_buffers++] = buffer; + + av_log(avctx, AV_LOG_DEBUG, "Param buffer (%d) is %#x.\n", + type, buffer); + return 0; +} + +static int vaapi_encode_wait(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAStatus vas; + + av_assert0(pic->encode_issued); + + if (pic->encode_complete) { + // Already waited for this picture. + return 0; + } + + av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" " + "(recon surface %#x).\n", pic->display_order, + pic->encode_order, pic->recon_surface); + + vas = vaSyncSurface(ctx->hwctx->display, pic->recon_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + // Input is definitely finished with now. + av_frame_free(&pic->input_image); + + pic->encode_complete = 1; + return 0; +} + +static int vaapi_encode_issue(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + VAStatus vas; + int err, i; + char data[MAX_PARAM_BUFFER_SIZE]; + size_t bit_len; + + av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " + "as type %s.\n", pic->display_order, pic->encode_order, + picture_type_name[pic->type]); + if (pic->nb_refs == 0) { + av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); + } else { + av_log(avctx, AV_LOG_DEBUG, "Refers to:"); + for (i = 0; i < pic->nb_refs; i++) { + av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64, + pic->refs[i]->display_order, pic->refs[i]->encode_order); + } + av_log(avctx, AV_LOG_DEBUG, ".\n"); + } + + av_assert0(pic->input_available && !pic->encode_issued); + for (i = 0; i < pic->nb_refs; i++) { + av_assert0(pic->refs[i]); + // If we are serialised then the references must have already + // completed. If not, they must have been issued but need not + // have completed yet. + if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING) + av_assert0(pic->refs[i]->encode_complete); + else + av_assert0(pic->refs[i]->encode_issued); + } + + av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); + + pic->recon_image = av_frame_alloc(); + if (!pic->recon_image) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwframe_get_buffer(ctx->recon_frames_ref, pic->recon_image, 0); + if (err < 0) { + err = AVERROR(ENOMEM); + goto fail; + } + pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface); + + pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool); + if (!pic->output_buffer_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data; + av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n", + pic->output_buffer); + + if (ctx->codec->picture_params_size > 0) { + pic->codec_picture_params = av_malloc(ctx->codec->picture_params_size); + if (!pic->codec_picture_params) + goto fail; + memcpy(pic->codec_picture_params, ctx->codec_picture_params, + ctx->codec->picture_params_size); + } else { + av_assert0(!ctx->codec_picture_params); + } + + pic->nb_param_buffers = 0; + + if (pic->encode_order == 0) { + // Global parameter buffers are set on the first picture only. + + for (i = 0; i < ctx->nb_global_params; i++) { + err = vaapi_encode_make_param_buffer(avctx, pic, + VAEncMiscParameterBufferType, + (char*)ctx->global_params[i], + ctx->global_params_size[i]); + if (err < 0) + goto fail; + } + } + + if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { + err = vaapi_encode_make_param_buffer(avctx, pic, + VAEncSequenceParameterBufferType, + ctx->codec_sequence_params, + ctx->codec->sequence_params_size); + if (err < 0) + goto fail; + } + + if (ctx->codec->init_picture_params) { + err = ctx->codec->init_picture_params(avctx, pic); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture " + "parameters: %d.\n", err); + goto fail; + } + err = vaapi_encode_make_param_buffer(avctx, pic, + VAEncPictureParameterBufferType, + pic->codec_picture_params, + ctx->codec->picture_params_size); + if (err < 0) + goto fail; + } + + if (pic->type == PICTURE_TYPE_IDR) { + if (ctx->codec->write_sequence_header) { + bit_len = 8 * sizeof(data); + err = ctx->codec->write_sequence_header(avctx, data, &bit_len); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence " + "header: %d.\n", err); + goto fail; + } + err = vaapi_encode_make_packed_header(avctx, pic, + ctx->codec->sequence_header_type, + data, bit_len); + if (err < 0) + goto fail; + } + } + + if (ctx->codec->write_picture_header) { + bit_len = 8 * sizeof(data); + err = ctx->codec->write_picture_header(avctx, pic, data, &bit_len); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write per-picture " + "header: %d.\n", err); + goto fail; + } + err = vaapi_encode_make_packed_header(avctx, pic, + ctx->codec->picture_header_type, + data, bit_len); + if (err < 0) + goto fail; + } + + if (ctx->codec->write_extra_buffer) { + for (i = 0;; i++) { + size_t len = sizeof(data); + int type; + err = ctx->codec->write_extra_buffer(avctx, pic, i, &type, + data, &len); + if (err == AVERROR_EOF) + break; + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write extra " + "buffer %d: %d.\n", i, err); + goto fail; + } + + err = vaapi_encode_make_param_buffer(avctx, pic, type, + data, len); + if (err < 0) + goto fail; + } + } + + if (ctx->codec->write_extra_header) { + for (i = 0;; i++) { + int type; + bit_len = 8 * sizeof(data); + err = ctx->codec->write_extra_header(avctx, pic, i, &type, + data, &bit_len); + if (err == AVERROR_EOF) + break; + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write extra " + "header %d: %d.\n", i, err); + goto fail; + } + + err = vaapi_encode_make_packed_header(avctx, pic, type, + data, bit_len); + if (err < 0) + goto fail; + } + } + + av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES); + for (i = 0; i < pic->nb_slices; i++) { + slice = av_mallocz(sizeof(*slice)); + if (!slice) { + err = AVERROR(ENOMEM); + goto fail; + } + pic->slices[i] = slice; + + if (ctx->codec->slice_params_size > 0) { + slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size); + if (!slice->codec_slice_params) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + if (ctx->codec->init_slice_params) { + err = ctx->codec->init_slice_params(avctx, pic, slice); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initalise slice " + "parameters: %d.\n", err); + goto fail; + } + } + + if (ctx->codec->write_slice_header) { + bit_len = 8 * sizeof(data); + err = ctx->codec->write_slice_header(avctx, pic, slice, + data, &bit_len); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write per-slice " + "header: %d.\n", err); + goto fail; + } + err = vaapi_encode_make_packed_header(avctx, pic, + ctx->codec->slice_header_type, + data, bit_len); + if (err < 0) + goto fail; + } + + if (ctx->codec->init_slice_params) { + err = vaapi_encode_make_param_buffer(avctx, pic, + VAEncSliceParameterBufferType, + slice->codec_slice_params, + ctx->codec->slice_params_size); + if (err < 0) + goto fail; + } + } + + vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, + pic->input_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_with_picture; + } + + vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, + pic->param_buffers, pic->nb_param_buffers); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_with_picture; + } + + vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + // vaRenderPicture() has been called here, so we should not destroy + // the parameter buffers unless separate destruction is required. + if (ctx->hwctx->driver_quirks & + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) + goto fail; + else + goto fail_at_end; + } + + if (ctx->hwctx->driver_quirks & + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { + for (i = 0; i < pic->nb_param_buffers; i++) { + vas = vaDestroyBuffer(ctx->hwctx->display, + pic->param_buffers[i]); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to destroy " + "param buffer %#x: %d (%s).\n", + pic->param_buffers[i], vas, vaErrorStr(vas)); + // And ignore. + } + } + } + + pic->encode_issued = 1; + + if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING) + return vaapi_encode_wait(avctx, pic); + else + return 0; + +fail_with_picture: + vaEndPicture(ctx->hwctx->display, ctx->va_context); +fail: + for(i = 0; i < pic->nb_param_buffers; i++) + vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]); +fail_at_end: + av_freep(&pic->codec_picture_params); + av_frame_free(&pic->recon_image); + return err; +} + +static int vaapi_encode_output(AVCodecContext *avctx, + VAAPIEncodePicture *pic, AVPacket *pkt) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VACodedBufferSegment *buf_list, *buf; + VAStatus vas; + int err; + + err = vaapi_encode_wait(avctx, pic); + if (err < 0) + return err; + + buf_list = NULL; + vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer, + (void**)&buf_list); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + for (buf = buf_list; buf; buf = buf->next) { + av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes " + "(status %08x).\n", buf->size, buf->status); + + err = av_new_packet(pkt, buf->size); + if (err < 0) + goto fail_mapped; + + memcpy(pkt->data, buf->buf, buf->size); + } + + if (pic->type == PICTURE_TYPE_IDR) + pkt->flags |= AV_PKT_FLAG_KEY; + + pkt->pts = pic->pts; + + vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + av_buffer_unref(&pic->output_buffer_ref); + pic->output_buffer = VA_INVALID_ID; + + av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", + pic->display_order, pic->encode_order); + return 0; + +fail_mapped: + vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); +fail: + av_buffer_unref(&pic->output_buffer_ref); + pic->output_buffer = VA_INVALID_ID; + return err; +} + +static int vaapi_encode_discard(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + vaapi_encode_wait(avctx, pic); + + if (pic->output_buffer_ref) { + av_log(avctx, AV_LOG_DEBUG, "Discard output for pic " + "%"PRId64"/%"PRId64".\n", + pic->display_order, pic->encode_order); + + av_buffer_unref(&pic->output_buffer_ref); + pic->output_buffer = VA_INVALID_ID; + } + + return 0; +} + +static VAAPIEncodePicture *vaapi_encode_alloc(void) +{ + VAAPIEncodePicture *pic; + + pic = av_mallocz(sizeof(*pic)); + if (!pic) + return NULL; + + pic->input_surface = VA_INVALID_ID; + pic->recon_surface = VA_INVALID_ID; + pic->output_buffer = VA_INVALID_ID; + + return pic; +} + +static int vaapi_encode_free(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + int i; + + if (pic->encode_issued) + vaapi_encode_discard(avctx, pic); + + for (i = 0; i < pic->nb_slices; i++) { + av_freep(&pic->slices[i]->priv_data); + av_freep(&pic->slices[i]->codec_slice_params); + av_freep(&pic->slices[i]); + } + av_freep(&pic->codec_picture_params); + + av_frame_free(&pic->input_image); + av_frame_free(&pic->recon_image); + + // Output buffer should already be destroyed. + av_assert0(pic->output_buffer == VA_INVALID_ID); + + av_freep(&pic->priv_data); + av_freep(&pic->codec_picture_params); + + av_free(pic); + + return 0; +} + +static int vaapi_encode_step(AVCodecContext *avctx, + VAAPIEncodePicture *target) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic; + int i, err; + + if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING || + ctx->issue_mode == ISSUE_MODE_MINIMISE_LATENCY) { + // These two modes are equivalent, except that we wait for + // immediate completion on each operation if serialised. + + if (!target) { + // No target, nothing to do yet. + return 0; + } + + if (target->encode_complete) { + // Already done. + return 0; + } + + pic = target; + for (i = 0; i < pic->nb_refs; i++) { + if (!pic->refs[i]->encode_complete) { + err = vaapi_encode_step(avctx, pic->refs[i]); + if (err < 0) + return err; + } + } + + err = vaapi_encode_issue(avctx, pic); + if (err < 0) + return err; + + } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) { + int activity; + + do { + activity = 0; + for (pic = ctx->pic_start; pic; pic = pic->next) { + if (!pic->input_available || pic->encode_issued) + continue; + for (i = 0; i < pic->nb_refs; i++) { + if (!pic->refs[i]->encode_issued) + break; + } + if (i < pic->nb_refs) + continue; + err = vaapi_encode_issue(avctx, pic); + if (err < 0) + return err; + activity = 1; + } + } while(activity); + + if (target) { + av_assert0(target->encode_issued && "broken dependencies?"); + } + + } else { + av_assert0(0); + } + + return 0; +} + +static int vaapi_encode_get_next(AVCodecContext *avctx, + VAAPIEncodePicture **pic_out) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *start, *end, *pic; + int i; + + for (pic = ctx->pic_start; pic; pic = pic->next) { + if (pic->next) + av_assert0(pic->display_order + 1 == pic->next->display_order); + if (pic->display_order == ctx->input_order) { + *pic_out = pic; + return 0; + } + } + + if (ctx->input_order == 0) { + // First frame is always an IDR frame. + av_assert0(!ctx->pic_start && !ctx->pic_end); + + pic = vaapi_encode_alloc(); + if (!pic) + return AVERROR(ENOMEM); + + pic->type = PICTURE_TYPE_IDR; + pic->display_order = 0; + pic->encode_order = 0; + + ctx->pic_start = ctx->pic_end = pic; + + *pic_out = pic; + return 0; + } + + pic = vaapi_encode_alloc(); + if (!pic) + return AVERROR(ENOMEM); + + if (ctx->p_per_i == 0 || ctx->p_counter == ctx->p_per_i) { + if (ctx->i_per_idr == 0 || ctx->i_counter == ctx->i_per_idr) { + pic->type = PICTURE_TYPE_IDR; + ctx->i_counter = 0; + } else { + pic->type = PICTURE_TYPE_I; + ++ctx->i_counter; + } + ctx->p_counter = 0; + } else { + pic->type = PICTURE_TYPE_P; + pic->refs[0] = ctx->pic_end; + pic->nb_refs = 1; + ++ctx->p_counter; + } + start = end = pic; + + if (pic->type != PICTURE_TYPE_IDR) { + // If that was not an IDR frame, add B-frames display-before and + // encode-after it. + + for (i = 0; i < ctx->b_per_p; i++) { + pic = vaapi_encode_alloc(); + if (!pic) + goto fail; + + pic->type = PICTURE_TYPE_B; + pic->refs[0] = ctx->pic_end; + pic->refs[1] = end; + pic->nb_refs = 2; + + pic->next = start; + pic->display_order = ctx->input_order + ctx->b_per_p - i - 1; + pic->encode_order = pic->display_order + 1; + start = pic; + } + } + + for (i = 0, pic = start; pic; i++, pic = pic->next) { + pic->display_order = ctx->input_order + i; + if (end->type == PICTURE_TYPE_IDR) + pic->encode_order = ctx->input_order + i; + else if (pic == end) + pic->encode_order = ctx->input_order; + else + pic->encode_order = ctx->input_order + i + 1; + } + + av_assert0(ctx->pic_end); + ctx->pic_end->next = start; + ctx->pic_end = end; + + *pic_out = start; + + av_log(avctx, AV_LOG_DEBUG, "Pictures:"); + for (pic = ctx->pic_start; pic; pic = pic->next) { + av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", + picture_type_name[pic->type], + pic->display_order, pic->encode_order); + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + + return 0; + +fail: + while (start) { + pic = start->next; + vaapi_encode_free(avctx, start); + start = pic; + } + return AVERROR(ENOMEM); +} + +static int vaapi_encode_mangle_end(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic, *last_pic, *next; + + // Find the last picture we actually have input for. + for (pic = ctx->pic_start; pic; pic = pic->next) { + if (!pic->input_available) + break; + last_pic = pic; + } + + if (pic) { + av_assert0(last_pic); + + if (last_pic->type == PICTURE_TYPE_B) { + // Some fixing up is required. Change the type of this + // picture to P, then modify preceding B references which + // point beyond it to point at it instead. + + last_pic->type = PICTURE_TYPE_P; + last_pic->encode_order = last_pic->refs[1]->encode_order; + + for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) { + if (pic->type == PICTURE_TYPE_B && + pic->refs[1] == last_pic->refs[1]) + pic->refs[1] = last_pic; + } + + last_pic->nb_refs = 1; + last_pic->refs[1] = NULL; + } else { + // We can use the current structure (no references point + // beyond the end), but there are unused pics to discard. + } + + // Discard all following pics, they will never be used. + for (pic = last_pic->next; pic; pic = next) { + next = pic->next; + vaapi_encode_free(avctx, pic); + } + + last_pic->next = NULL; + ctx->pic_end = last_pic; + + } else { + // Input is available for all pictures, so we don't need to + // mangle anything. + } + + av_log(avctx, AV_LOG_DEBUG, "Pictures at end of stream:"); + for (pic = ctx->pic_start; pic; pic = pic->next) { + av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", + picture_type_name[pic->type], + pic->display_order, pic->encode_order); + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + + return 0; +} + +static int vaapi_encode_clear_old(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic, *old; + int i; + + while (ctx->pic_start != ctx->pic_end) { + old = ctx->pic_start; + if (old->encode_order > ctx->output_order) + break; + + for (pic = old->next; pic; pic = pic->next) { + if (pic->encode_complete) + continue; + for (i = 0; i < pic->nb_refs; i++) { + if (pic->refs[i] == old) { + // We still need this picture because it's referred to + // directly by a later one, so it and all following + // pictures have to stay. + return 0; + } + } + } + + pic = ctx->pic_start; + ctx->pic_start = pic->next; + vaapi_encode_free(avctx, pic); + } + + return 0; +} + +int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *input_image, int *got_packet) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic; + int err; + + if (input_image) { + av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n", + input_image->width, input_image->height, input_image->pts); + + err = vaapi_encode_get_next(avctx, &pic); + if (err) { + av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err); + return err; + } + + pic->input_image = av_frame_alloc(); + if (!pic->input_image) { + err = AVERROR(ENOMEM); + goto fail; + } + err = av_frame_ref(pic->input_image, input_image); + if (err < 0) + goto fail; + pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3]; + pic->pts = input_image->pts; + + if (ctx->input_order == 0) + ctx->first_pts = pic->pts; + if (ctx->input_order == ctx->decode_delay) + ctx->dts_pts_diff = pic->pts - ctx->first_pts; + if (ctx->output_delay > 0) + ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts; + + pic->input_available = 1; + + } else { + if (!ctx->end_of_stream) { + err = vaapi_encode_mangle_end(avctx); + if (err < 0) + goto fail; + ctx->end_of_stream = 1; + } + } + + ++ctx->input_order; + ++ctx->output_order; + av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order); + + for (pic = ctx->pic_start; pic; pic = pic->next) + if (pic->encode_order == ctx->output_order) + break; + + // pic can be null here if we don't have a specific target in this + // iteration. We might still issue encodes if things can be overlapped, + // even though we don't intend to output anything. + + err = vaapi_encode_step(avctx, pic); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); + goto fail; + } + + if (!pic) { + *got_packet = 0; + } else { + err = vaapi_encode_output(avctx, pic, pkt); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); + goto fail; + } + + if (ctx->output_delay == 0) { + pkt->dts = pkt->pts; + } else if (ctx->output_order < ctx->decode_delay) { + if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff) + pkt->dts = INT64_MIN; + else + pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff; + } else { + pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) % + (3 * ctx->output_delay)]; + } + + *got_packet = 1; + } + + err = vaapi_encode_clear_old(avctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err); + goto fail; + } + + return 0; + +fail: + // Unclear what to clean up on failure. There are probably some things we + // could do usefully clean up here, but for now just leave them for uninit() + // to do instead. + return err; +} + +static av_cold int vaapi_encode_check_config(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAStatus vas; + int i, n, err; + VAProfile *profiles = NULL; + VAEntrypoint *entrypoints = NULL; + VAConfigAttrib attr[] = { + { VAConfigAttribRateControl }, + { VAConfigAttribEncMaxRefFrames }, + }; + + n = vaMaxNumProfiles(ctx->hwctx->display); + profiles = av_malloc_array(n, sizeof(VAProfile)); + if (!profiles) { + err = AVERROR(ENOMEM); + goto fail; + } + vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, &n); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n", + vas, vaErrorStr(vas)); + err = AVERROR(ENOSYS); + goto fail; + } + for (i = 0; i < n; i++) { + if (profiles[i] == ctx->va_profile) + break; + } + if (i >= n) { + av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n", + ctx->va_profile); + err = AVERROR(ENOSYS); + goto fail; + } + + n = vaMaxNumEntrypoints(ctx->hwctx->display); + entrypoints = av_malloc_array(n, sizeof(VAEntrypoint)); + if (!entrypoints) { + err = AVERROR(ENOMEM); + goto fail; + } + vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile, + entrypoints, &n); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for " + "profile %u: %d (%s).\n", ctx->va_profile, + vas, vaErrorStr(vas)); + err = AVERROR(ENOSYS); + goto fail; + } + for (i = 0; i < n; i++) { + if (entrypoints[i] == ctx->va_entrypoint) + break; + } + if (i >= n) { + av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found " + "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint); + err = AVERROR(ENOSYS); + goto fail; + } + + vas = vaGetConfigAttributes(ctx->hwctx->display, + ctx->va_profile, ctx->va_entrypoint, + attr, FF_ARRAY_ELEMS(attr)); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to fetch config " + "attributes: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EINVAL); + } + + for (i = 0; i < FF_ARRAY_ELEMS(attr); i++) { + if (attr[i].value == VA_ATTRIB_NOT_SUPPORTED) { + // Unfortunately we have to treat this as "don't know" and hope + // for the best, because the Intel MJPEG encoder returns this + // for all the interesting attributes. + continue; + } + switch (attr[i].type) { + case VAConfigAttribRateControl: + if (!(ctx->va_rc_mode & attr[i].value)) { + av_log(avctx, AV_LOG_ERROR, "Rate control mode is not " + "supported: %x\n", attr[i].value); + err = AVERROR(EINVAL); + goto fail; + } + break; + case VAConfigAttribEncMaxRefFrames: + { + unsigned int ref_l0 = attr[i].value & 0xffff; + unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff; + + if (avctx->gop_size > 1 && ref_l0 < 1) { + av_log(avctx, AV_LOG_ERROR, "P frames are not " + "supported (%x).\n", attr[i].value); + err = AVERROR(EINVAL); + goto fail; + } + if (avctx->max_b_frames > 0 && ref_l1 < 1) { + av_log(avctx, AV_LOG_ERROR, "B frames are not " + "supported (%x).\n", attr[i].value); + err = AVERROR(EINVAL); + goto fail; + } + } + break; + } + } + + err = 0; +fail: + av_freep(&profiles); + av_freep(&entrypoints); + return err; +} + +static void vaapi_encode_free_output_buffer(void *opaque, + uint8_t *data) +{ + AVCodecContext *avctx = opaque; + VAAPIEncodeContext *ctx = avctx->priv_data; + VABufferID buffer_id; + + buffer_id = (VABufferID)(uintptr_t)data; + + vaDestroyBuffer(ctx->hwctx->display, buffer_id); + + av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id); +} + +static AVBufferRef *vaapi_encode_alloc_output_buffer(void *opaque, + int size) +{ + AVCodecContext *avctx = opaque; + VAAPIEncodeContext *ctx = avctx->priv_data; + VABufferID buffer_id; + VAStatus vas; + AVBufferRef *ref; + + // The output buffer size is fixed, so it needs to be large enough + // to hold the largest possible compressed frame. We assume here + // that the uncompressed frame plus some header data is an upper + // bound on that. + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAEncCodedBufferType, + 3 * ctx->aligned_width * ctx->aligned_height + + (1 << 16), 1, 0, &buffer_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream " + "output buffer: %d (%s).\n", vas, vaErrorStr(vas)); + return NULL; + } + + av_log(avctx, AV_LOG_DEBUG, "Allocated output buffer %#x\n", buffer_id); + + ref = av_buffer_create((uint8_t*)(uintptr_t)buffer_id, + sizeof(buffer_id), + &vaapi_encode_free_output_buffer, + avctx, AV_BUFFER_FLAG_READONLY); + if (!ref) { + vaDestroyBuffer(ctx->hwctx->display, buffer_id); + return NULL; + } + + return ref; +} + +av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, + const VAAPIEncodeType *type) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + AVVAAPIFramesContext *recon_hwctx = NULL; + AVVAAPIHWConfig *hwconfig = NULL; + AVHWFramesConstraints *constraints = NULL; + enum AVPixelFormat recon_format; + VAStatus vas; + int err, i; + + if (!avctx->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); + return AVERROR(EINVAL); + } + + ctx->codec = type; + ctx->codec_options = ctx->codec_options_data; + + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + + ctx->priv_data = av_mallocz(type->priv_data_size); + if (!ctx->priv_data) { + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); + if (!ctx->input_frames_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data; + + ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); + if (!ctx->device_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; + ctx->hwctx = ctx->device->hwctx; + + err = ctx->codec->init(avctx); + if (err < 0) + goto fail; + + err = vaapi_encode_check_config(avctx); + if (err < 0) + goto fail; + + vas = vaCreateConfig(ctx->hwctx->display, + ctx->va_profile, ctx->va_entrypoint, + ctx->config_attributes, ctx->nb_config_attributes, + &ctx->va_config); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline " + "configuration: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); + if (!hwconfig) { + err = AVERROR(ENOMEM); + goto fail; + } + hwconfig->config_id = ctx->va_config; + + constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); + if (!constraints) { + err = AVERROR(ENOMEM); + goto fail; + } + + // Probably we can use the input surface format as the surface format + // of the reconstructed frames. If not, we just pick the first (only?) + // format in the valid list and hope that it all works. + recon_format = AV_PIX_FMT_NONE; + if (constraints->valid_sw_formats) { + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + if (ctx->input_frames->sw_format == + constraints->valid_sw_formats[i]) { + recon_format = ctx->input_frames->sw_format; + break; + } + } + if (recon_format == AV_PIX_FMT_NONE) { + // No match. Just use the first in the supported list and + // hope for the best. + recon_format = constraints->valid_sw_formats[0]; + } + } else { + // No idea what to use; copy input format. + recon_format = ctx->input_frames->sw_format; + } + av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + + if (ctx->aligned_width < constraints->min_width || + ctx->aligned_height < constraints->min_height || + ctx->aligned_width > constraints->max_width || + ctx->aligned_height > constraints->max_height) { + av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->aligned_width, ctx->aligned_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); + err = AVERROR(EINVAL); + goto fail; + } + + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + + ctx->recon_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); + if (!ctx->recon_frames_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data; + + ctx->recon_frames->format = AV_PIX_FMT_VAAPI; + ctx->recon_frames->sw_format = recon_format; + ctx->recon_frames->width = ctx->aligned_width; + ctx->recon_frames->height = ctx->aligned_height; + ctx->recon_frames->initial_pool_size = ctx->nb_recon_frames; + + err = av_hwframe_ctx_init(ctx->recon_frames_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed " + "frame context: %d.\n", err); + goto fail; + } + recon_hwctx = ctx->recon_frames->hwctx; + + vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, + ctx->aligned_width, ctx->aligned_height, + VA_PROGRESSIVE, + recon_hwctx->surface_ids, + recon_hwctx->nb_surfaces, + &ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + ctx->input_order = 0; + ctx->output_delay = avctx->max_b_frames; + ctx->decode_delay = 1; + ctx->output_order = - ctx->output_delay - 1; + + if (ctx->codec->sequence_params_size > 0) { + ctx->codec_sequence_params = + av_mallocz(ctx->codec->sequence_params_size); + if (!ctx->codec_sequence_params) { + err = AVERROR(ENOMEM); + goto fail; + } + } + if (ctx->codec->picture_params_size > 0) { + ctx->codec_picture_params = + av_mallocz(ctx->codec->picture_params_size); + if (!ctx->codec_picture_params) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + if (ctx->codec->init_sequence_params) { + err = ctx->codec->init_sequence_params(avctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation " + "failed: %d.\n", err); + goto fail; + } + } + + ctx->output_buffer_pool = + av_buffer_pool_init2(sizeof(VABufferID), avctx, + &vaapi_encode_alloc_output_buffer, NULL); + if (!ctx->output_buffer_pool) { + err = AVERROR(ENOMEM); + goto fail; + } + + // All I are IDR for now. + ctx->i_per_idr = 0; + ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) / + (avctx->max_b_frames + 1)); + ctx->b_per_p = avctx->max_b_frames; + + // This should be configurable somehow. (Needs testing on a machine + // where it actually overlaps properly, though.) + ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT; + + return 0; + +fail: + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + ff_vaapi_encode_close(avctx); + return err; +} + +av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic, *next; + + for (pic = ctx->pic_start; pic; pic = next) { + next = pic->next; + vaapi_encode_free(avctx, pic); + } + + if (ctx->va_context != VA_INVALID_ID) { + vaDestroyContext(ctx->hwctx->display, ctx->va_context); + ctx->va_context = VA_INVALID_ID; + } + + if (ctx->va_config != VA_INVALID_ID) { + vaDestroyConfig(ctx->hwctx->display, ctx->va_config); + ctx->va_config = VA_INVALID_ID; + } + + if (ctx->codec->close) + ctx->codec->close(avctx); + + av_buffer_pool_uninit(&ctx->output_buffer_pool); + + av_freep(&ctx->codec_sequence_params); + av_freep(&ctx->codec_picture_params); + + av_buffer_unref(&ctx->recon_frames_ref); + av_buffer_unref(&ctx->input_frames_ref); + av_buffer_unref(&ctx->device_ref); + + av_freep(&ctx->priv_data); + + return 0; +} diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h new file mode 100644 index 0000000..eede73c --- /dev/null +++ b/libavcodec/vaapi_encode.h @@ -0,0 +1,234 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VAAPI_ENCODE_H +#define AVCODEC_VAAPI_ENCODE_H + +#include + +#include + +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vaapi.h" + +#include "avcodec.h" + +struct VAAPIEncodeType; +struct VAAPIEncodePicture; + +enum { + MAX_CONFIG_ATTRIBUTES = 4, + MAX_GLOBAL_PARAMS = 4, + MAX_PICTURE_REFERENCES = 2, + MAX_PICTURE_SLICES = 1, + MAX_PARAM_BUFFERS = 16, + MAX_REORDER_DELAY = 16, + MAX_PARAM_BUFFER_SIZE = 1024, +}; + +enum { + PICTURE_TYPE_IDR = 0, + PICTURE_TYPE_I = 1, + PICTURE_TYPE_P = 2, + PICTURE_TYPE_B = 3, +}; + +enum { + // All encode operations are done independently. + ISSUE_MODE_SERIALISE_EVERYTHING = 0, + // Overlap as many operations as possible. + ISSUE_MODE_MAXIMISE_THROUGHPUT, + // Overlap operations only when satisfying parallel dependencies. + ISSUE_MODE_MINIMISE_LATENCY, +}; + +typedef struct VAAPIEncodeSlice { + void *priv_data; + void *codec_slice_params; +} VAAPIEncodeSlice; + +typedef struct VAAPIEncodePicture { + struct VAAPIEncodePicture *next; + + int64_t display_order; + int64_t encode_order; + int64_t pts; + + int type; + int input_available; + int encode_issued; + int encode_complete; + + AVFrame *input_image; + VASurfaceID input_surface; + + AVFrame *recon_image; + VASurfaceID recon_surface; + + int nb_param_buffers; + VABufferID param_buffers[MAX_PARAM_BUFFERS]; + + AVBufferRef *output_buffer_ref; + VABufferID output_buffer; + + void *priv_data; + void *codec_picture_params; + + int nb_refs; + struct VAAPIEncodePicture *refs[MAX_PICTURE_REFERENCES]; + + int nb_slices; + VAAPIEncodeSlice *slices[MAX_PICTURE_SLICES]; +} VAAPIEncodePicture; + +typedef struct VAAPIEncodeContext { + const AVClass *class; + + // Codec-specific hooks. + const struct VAAPIEncodeType *codec; + + // Codec-specific state. + void *priv_data; + + VAProfile va_profile; + VAEntrypoint va_entrypoint; + VAConfigID va_config; + VAContextID va_context; + + int va_rc_mode; + + AVBufferRef *device_ref; + AVHWDeviceContext *device; + AVVAAPIDeviceContext *hwctx; + + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + // Input size, set from input frames. + int input_width; + int input_height; + // Aligned size, set by codec init, becomes hwframe size. + int aligned_width; + int aligned_height; + + int nb_recon_frames; + AVBufferRef *recon_frames_ref; + AVHWFramesContext *recon_frames; + + AVBufferPool *output_buffer_pool; + + VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES]; + int nb_config_attributes; + + VAEncMiscParameterBuffer *global_params[MAX_GLOBAL_PARAMS]; + size_t global_params_size[MAX_GLOBAL_PARAMS]; + int nb_global_params; + + // Per-sequence parameter structure (VAEncSequenceParameterBuffer*). + void *codec_sequence_params; + + // Per-sequence parameters found in the per-picture parameter + // structure (VAEncPictureParameterBuffer*). + void *codec_picture_params; + + // Current encoding window, in display (input) order. + VAAPIEncodePicture *pic_start, *pic_end; + + // Next input order index (display order). + int64_t input_order; + // Number of frames that output is behind input. + int64_t output_delay; + // Number of frames decode output will need to be delayed. + int64_t decode_delay; + // Next output order index (encode order). + int64_t output_order; + + int issue_mode; + + // Timestamp handling. + int64_t first_pts; + int64_t dts_pts_diff; + int64_t ts_ring[MAX_REORDER_DELAY * 3]; + + // Frame type decision. + int i_per_idr; + int p_per_i; + int b_per_p; + int idr_counter; + int i_counter; + int p_counter; + int end_of_stream; + + // Codec-local options are allocated to follow this structure in + // memory (in the AVCodec definition, set priv_data_size to + // sizeof(VAAPIEncodeContext) + sizeof(VAAPIEncodeFooOptions)). + void *codec_options; + char codec_options_data[0]; +} VAAPIEncodeContext; + + +typedef struct VAAPIEncodeType { + size_t priv_data_size; + + int (*init)(AVCodecContext *avctx); + int (*close)(AVCodecContext *avctx); + + size_t sequence_params_size; + size_t picture_params_size; + size_t slice_params_size; + + int (*init_sequence_params)(AVCodecContext *avctx); + int (*init_picture_params)(AVCodecContext *avctx, + VAAPIEncodePicture *pic); + int (*init_slice_params)(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice); + + int sequence_header_type; + int picture_header_type; + int slice_header_type; + + int (*write_sequence_header)(AVCodecContext *avctx, + char *data, size_t *data_len); + int (*write_picture_header)(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + char *data, size_t *data_len); + int (*write_slice_header)(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice, + char *data, size_t *data_len); + + int (*write_extra_buffer)(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int index, int *type, + char *data, size_t *data_len); + int (*write_extra_header)(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int index, int *type, + char *data, size_t *data_len); +} VAAPIEncodeType; + + +int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *input_image, int *got_packet); + +int ff_vaapi_encode_init(AVCodecContext *avctx, + const VAAPIEncodeType *type); +int ff_vaapi_encode_close(AVCodecContext *avctx); + +#endif /* AVCODEC_VAAPI_ENCODE_H */ diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c new file mode 100644 index 0000000..5bd5605 --- /dev/null +++ b/libavcodec/vaapi_encode_h264.c @@ -0,0 +1,1351 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "h264.h" +#include "h264_sei.h" +#include "internal.h" +#include "vaapi_encode.h" +#include "vaapi_encode_h26x.h" + +enum { + SLICE_TYPE_P = 0, + SLICE_TYPE_B = 1, + SLICE_TYPE_I = 2, + SLICE_TYPE_SP = 3, + SLICE_TYPE_SI = 4, +}; + +// This structure contains all possibly-useful per-sequence syntax elements +// which are not already contained in the various VAAPI structures. +typedef struct VAAPIEncodeH264MiscSequenceParams { + unsigned int profile_idc; + char constraint_set0_flag; + char constraint_set1_flag; + char constraint_set2_flag; + char constraint_set3_flag; + char constraint_set4_flag; + char constraint_set5_flag; + + char separate_colour_plane_flag; + char qpprime_y_zero_transform_bypass_flag; + + char gaps_in_frame_num_allowed_flag; + char delta_pic_order_always_zero_flag; + char bottom_field_pic_order_in_frame_present_flag; + + unsigned int num_slice_groups_minus1; + unsigned int slice_group_map_type; + + int pic_init_qs_minus26; + + char overscan_info_present_flag; + char overscan_appropriate_flag; + + char video_signal_type_present_flag; + unsigned int video_format; + char video_full_range_flag; + char colour_description_present_flag; + unsigned int colour_primaries; + unsigned int transfer_characteristics; + unsigned int matrix_coefficients; + + char chroma_loc_info_present_flag; + unsigned int chroma_sample_loc_type_top_field; + unsigned int chroma_sample_loc_type_bottom_field; + + // Some timing elements are in VAEncSequenceParameterBufferH264. + char fixed_frame_rate_flag; + + char nal_hrd_parameters_present_flag; + char vcl_hrd_parameters_present_flag; + char low_delay_hrd_flag; + char pic_struct_present_flag; + char bitstream_restriction_flag; + + unsigned int cpb_cnt_minus1; + unsigned int bit_rate_scale; + unsigned int cpb_size_scale; + unsigned int bit_rate_value_minus1[32]; + unsigned int cpb_size_value_minus1[32]; + char cbr_flag[32]; + unsigned int initial_cpb_removal_delay_length_minus1; + unsigned int cpb_removal_delay_length_minus1; + unsigned int dpb_output_delay_length_minus1; + unsigned int time_offset_length; + + unsigned int initial_cpb_removal_delay; + unsigned int initial_cpb_removal_delay_offset; + + unsigned int pic_struct; +} VAAPIEncodeH264MiscSequenceParams; + +// This structure contains all possibly-useful per-slice syntax elements +// which are not already contained in the various VAAPI structures. +typedef struct VAAPIEncodeH264MiscSliceParams { + unsigned int nal_unit_type; + unsigned int nal_ref_idc; + + unsigned int colour_plane_id; + char field_pic_flag; + char bottom_field_flag; + + unsigned int redundant_pic_cnt; + + char sp_for_switch_flag; + int slice_qs_delta; + + char ref_pic_list_modification_flag_l0; + char ref_pic_list_modification_flag_l1; + + char no_output_of_prior_pics_flag; + char long_term_reference_flag; + char adaptive_ref_pic_marking_mode_flag; +} VAAPIEncodeH264MiscSliceParams; + +typedef struct VAAPIEncodeH264Slice { + VAAPIEncodeH264MiscSliceParams misc_slice_params; +} VAAPIEncodeH264Slice; + +typedef struct VAAPIEncodeH264Context { + VAAPIEncodeH264MiscSequenceParams misc_sequence_params; + + int mb_width; + int mb_height; + + int fixed_qp_idr; + int fixed_qp_p; + int fixed_qp_b; + + int next_frame_num; + int64_t idr_pic_count; + + int cpb_delay; + int dpb_delay; + + // Rate control configuration. + int send_timing_sei; + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterRateControl rc; + } rc_params; + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterHRD hrd; + } hrd_params; + +#if VA_CHECK_VERSION(0, 36, 0) + // Speed-quality tradeoff setting. + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterBufferQualityLevel quality; + } quality_params; +#endif +} VAAPIEncodeH264Context; + +typedef struct VAAPIEncodeH264Options { + int qp; + int quality; + int low_power; +} VAAPIEncodeH264Options; + + +#define vseq_var(name) vseq->name, name +#define vseq_field(name) vseq->seq_fields.bits.name, name +#define vvui_field(name) vseq->vui_fields.bits.name, name +#define vpic_var(name) vpic->name, name +#define vpic_field(name) vpic->pic_fields.bits.name, name +#define vslice_var(name) vslice->name, name +#define vslice_field(name) vslice->slice_fields.bits.name, name +#define mseq_var(name) mseq->name, name +#define mslice_var(name) mslice->name, name + +static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc, + int nal_unit_type, int nal_ref_idc) +{ + u(1, 0, forbidden_zero_bit); + u(2, nal_ref_idc, nal_ref_idc); + u(5, nal_unit_type, nal_unit_type); +} + +static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc) +{ + u(1, 1, rbsp_stop_one_bit); + while (put_bits_count(pbc) & 7) + u(1, 0, rbsp_alignment_zero_bit); +} + +static void vaapi_encode_h264_write_vui(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + u(1, vvui_field(aspect_ratio_info_present_flag)); + if (vseq->vui_fields.bits.aspect_ratio_info_present_flag) { + u(8, vseq_var(aspect_ratio_idc)); + if (vseq->aspect_ratio_idc == 255) { + u(16, vseq_var(sar_width)); + u(16, vseq_var(sar_height)); + } + } + + u(1, mseq_var(overscan_info_present_flag)); + if (mseq->overscan_info_present_flag) + u(1, mseq_var(overscan_appropriate_flag)); + + u(1, mseq_var(video_signal_type_present_flag)); + if (mseq->video_signal_type_present_flag) { + u(3, mseq_var(video_format)); + u(1, mseq_var(video_full_range_flag)); + u(1, mseq_var(colour_description_present_flag)); + if (mseq->colour_description_present_flag) { + u(8, mseq_var(colour_primaries)); + u(8, mseq_var(transfer_characteristics)); + u(8, mseq_var(matrix_coefficients)); + } + } + + u(1, mseq_var(chroma_loc_info_present_flag)); + if (mseq->chroma_loc_info_present_flag) { + ue(mseq_var(chroma_sample_loc_type_top_field)); + ue(mseq_var(chroma_sample_loc_type_bottom_field)); + } + + u(1, vvui_field(timing_info_present_flag)); + if (vseq->vui_fields.bits.timing_info_present_flag) { + u(32, vseq_var(num_units_in_tick)); + u(32, vseq_var(time_scale)); + u(1, mseq_var(fixed_frame_rate_flag)); + } + + u(1, mseq_var(nal_hrd_parameters_present_flag)); + if (mseq->nal_hrd_parameters_present_flag) { + ue(mseq_var(cpb_cnt_minus1)); + u(4, mseq_var(bit_rate_scale)); + u(4, mseq_var(cpb_size_scale)); + for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { + ue(mseq_var(bit_rate_value_minus1[i])); + ue(mseq_var(cpb_size_value_minus1[i])); + u(1, mseq_var(cbr_flag[i])); + } + u(5, mseq_var(initial_cpb_removal_delay_length_minus1)); + u(5, mseq_var(cpb_removal_delay_length_minus1)); + u(5, mseq_var(dpb_output_delay_length_minus1)); + u(5, mseq_var(time_offset_length)); + } + u(1, mseq_var(vcl_hrd_parameters_present_flag)); + if (mseq->vcl_hrd_parameters_present_flag) { + av_assert0(0 && "vcl hrd parameters not supported"); + } + + if (mseq->nal_hrd_parameters_present_flag || + mseq->vcl_hrd_parameters_present_flag) + u(1, mseq_var(low_delay_hrd_flag)); + u(1, mseq_var(pic_struct_present_flag)); + + u(1, vvui_field(bitstream_restriction_flag)); + if (vseq->vui_fields.bits.bitstream_restriction_flag) { + av_assert0(0 && "bitstream restrictions not supported"); + } +} + +static void vaapi_encode_h264_write_sps(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SPS, 3); + + u(8, mseq_var(profile_idc)); + u(1, mseq_var(constraint_set0_flag)); + u(1, mseq_var(constraint_set1_flag)); + u(1, mseq_var(constraint_set2_flag)); + u(1, mseq_var(constraint_set3_flag)); + u(1, mseq_var(constraint_set4_flag)); + u(1, mseq_var(constraint_set5_flag)); + u(2, 0, reserved_zero_2bits); + + u(8, vseq_var(level_idc)); + + ue(vseq_var(seq_parameter_set_id)); + + if (mseq->profile_idc == 100 || mseq->profile_idc == 110 || + mseq->profile_idc == 122 || mseq->profile_idc == 244 || + mseq->profile_idc == 44 || mseq->profile_idc == 83 || + mseq->profile_idc == 86 || mseq->profile_idc == 118 || + mseq->profile_idc == 128 || mseq->profile_idc == 138) { + ue(vseq_field(chroma_format_idc)); + + if (vseq->seq_fields.bits.chroma_format_idc == 3) + u(1, mseq_var(separate_colour_plane_flag)); + + ue(vseq_var(bit_depth_luma_minus8)); + ue(vseq_var(bit_depth_chroma_minus8)); + + u(1, mseq_var(qpprime_y_zero_transform_bypass_flag)); + + u(1, vseq_field(seq_scaling_matrix_present_flag)); + if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) { + av_assert0(0 && "scaling matrices not supported"); + } + } + + ue(vseq_field(log2_max_frame_num_minus4)); + ue(vseq_field(pic_order_cnt_type)); + + if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { + ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4)); + } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) { + u(1, mseq_var(delta_pic_order_always_zero_flag)); + se(vseq_var(offset_for_non_ref_pic)); + se(vseq_var(offset_for_top_to_bottom_field)); + ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle)); + + for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++) + se(vseq_var(offset_for_ref_frame[i])); + } + + ue(vseq_var(max_num_ref_frames)); + u(1, mseq_var(gaps_in_frame_num_allowed_flag)); + + ue(vseq->picture_width_in_mbs - 1, pic_width_in_mbs_minus1); + ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1); + + u(1, vseq_field(frame_mbs_only_flag)); + if (!vseq->seq_fields.bits.frame_mbs_only_flag) + u(1, vseq_field(mb_adaptive_frame_field_flag)); + + u(1, vseq_field(direct_8x8_inference_flag)); + + u(1, vseq_var(frame_cropping_flag)); + if (vseq->frame_cropping_flag) { + ue(vseq_var(frame_crop_left_offset)); + ue(vseq_var(frame_crop_right_offset)); + ue(vseq_var(frame_crop_top_offset)); + ue(vseq_var(frame_crop_bottom_offset)); + } + + u(1, vseq_var(vui_parameters_present_flag)); + if (vseq->vui_parameters_present_flag) + vaapi_encode_h264_write_vui(pbc, ctx); + + vaapi_encode_h264_write_trailing_rbsp(pbc); +} + +static void vaapi_encode_h264_write_pps(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + + vaapi_encode_h264_write_nal_header(pbc, H264_NAL_PPS, 3); + + ue(vpic_var(pic_parameter_set_id)); + ue(vpic_var(seq_parameter_set_id)); + + u(1, vpic_field(entropy_coding_mode_flag)); + u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag)); + + ue(mseq_var(num_slice_groups_minus1)); + if (mseq->num_slice_groups_minus1 > 0) { + ue(mseq_var(slice_group_map_type)); + av_assert0(0 && "slice groups not supported"); + } + + ue(vpic_var(num_ref_idx_l0_active_minus1)); + ue(vpic_var(num_ref_idx_l1_active_minus1)); + + u(1, vpic_field(weighted_pred_flag)); + u(2, vpic_field(weighted_bipred_idc)); + + se(vpic->pic_init_qp - 26, pic_init_qp_minus26); + se(mseq_var(pic_init_qs_minus26)); + se(vpic_var(chroma_qp_index_offset)); + + u(1, vpic_field(deblocking_filter_control_present_flag)); + u(1, vpic_field(constrained_intra_pred_flag)); + u(1, vpic_field(redundant_pic_cnt_present_flag)); + u(1, vpic_field(transform_8x8_mode_flag)); + + u(1, vpic_field(pic_scaling_matrix_present_flag)); + if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) { + av_assert0(0 && "scaling matrices not supported"); + } + + se(vpic_var(second_chroma_qp_index_offset)); + + vaapi_encode_h264_write_trailing_rbsp(pbc); +} + +static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice) +{ + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + VAAPIEncodeH264Slice *pslice = slice->priv_data; + VAAPIEncodeH264MiscSliceParams *mslice = &pslice->misc_slice_params; + + vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type, + mslice->nal_ref_idc); + + ue(vslice->macroblock_address, first_mb_in_slice); + ue(vslice_var(slice_type)); + ue(vpic_var(pic_parameter_set_id)); + + if (mseq->separate_colour_plane_flag) { + u(2, mslice_var(colour_plane_id)); + } + + u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4, + (vpic->frame_num & + ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)), + frame_num); + + if (!vseq->seq_fields.bits.frame_mbs_only_flag) { + u(1, mslice_var(field_pic_flag)); + if (mslice->field_pic_flag) + u(1, mslice_var(bottom_field_flag)); + } + + if (vpic->pic_fields.bits.idr_pic_flag) { + ue(vslice_var(idr_pic_id)); + } + + if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { + u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4, + vslice_var(pic_order_cnt_lsb)); + if (mseq->bottom_field_pic_order_in_frame_present_flag && + !mslice->field_pic_flag) { + se(vslice_var(delta_pic_order_cnt_bottom)); + } + } + + if (vseq->seq_fields.bits.pic_order_cnt_type == 1 && + !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) { + se(vslice_var(delta_pic_order_cnt[0])); + if (mseq->bottom_field_pic_order_in_frame_present_flag && + !mslice->field_pic_flag) { + se(vslice_var(delta_pic_order_cnt[1])); + } + } + + if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) { + ue(mslice_var(redundant_pic_cnt)); + } + + if (vslice->slice_type == SLICE_TYPE_B) { + u(1, vslice_var(direct_spatial_mv_pred_flag)); + } + + if (vslice->slice_type == SLICE_TYPE_P || + vslice->slice_type == SLICE_TYPE_SP || + vslice->slice_type == SLICE_TYPE_B) { + u(1, vslice_var(num_ref_idx_active_override_flag)); + if (vslice->num_ref_idx_active_override_flag) { + ue(vslice_var(num_ref_idx_l0_active_minus1)); + if (vslice->slice_type == SLICE_TYPE_B) + ue(vslice_var(num_ref_idx_l1_active_minus1)); + } + } + + if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) { + av_assert0(0 && "no MVC support"); + } else { + if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) { + u(1, mslice_var(ref_pic_list_modification_flag_l0)); + if (mslice->ref_pic_list_modification_flag_l0) { + av_assert0(0 && "ref pic list modification"); + } + } + if (vslice->slice_type % 5 == 1) { + u(1, mslice_var(ref_pic_list_modification_flag_l1)); + if (mslice->ref_pic_list_modification_flag_l1) { + av_assert0(0 && "ref pic list modification"); + } + } + } + + if ((vpic->pic_fields.bits.weighted_pred_flag && + (vslice->slice_type == SLICE_TYPE_P || + vslice->slice_type == SLICE_TYPE_SP)) || + (vpic->pic_fields.bits.weighted_bipred_idc == 1 && + vslice->slice_type == SLICE_TYPE_B)) { + av_assert0(0 && "prediction weights not supported"); + } + + av_assert0(mslice->nal_ref_idc > 0 == + vpic->pic_fields.bits.reference_pic_flag); + if (mslice->nal_ref_idc != 0) { + if (vpic->pic_fields.bits.idr_pic_flag) { + u(1, mslice_var(no_output_of_prior_pics_flag)); + u(1, mslice_var(long_term_reference_flag)); + } else { + u(1, mslice_var(adaptive_ref_pic_marking_mode_flag)); + if (mslice->adaptive_ref_pic_marking_mode_flag) { + av_assert0(0 && "MMCOs not supported"); + } + } + } + + if (vpic->pic_fields.bits.entropy_coding_mode_flag && + vslice->slice_type != SLICE_TYPE_I && + vslice->slice_type != SLICE_TYPE_SI) { + ue(vslice_var(cabac_init_idc)); + } + + se(vslice_var(slice_qp_delta)); + if (vslice->slice_type == SLICE_TYPE_SP || + vslice->slice_type == SLICE_TYPE_SI) { + if (vslice->slice_type == SLICE_TYPE_SP) + u(1, mslice_var(sp_for_switch_flag)); + se(mslice_var(slice_qs_delta)); + } + + if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) { + ue(vslice_var(disable_deblocking_filter_idc)); + if (vslice->disable_deblocking_filter_idc != 1) { + se(vslice_var(slice_alpha_c0_offset_div2)); + se(vslice_var(slice_beta_offset_div2)); + } + } + + if (mseq->num_slice_groups_minus1 > 0 && + mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) { + av_assert0(0 && "slice groups not supported"); + } + + // No alignment - this need not be a byte boundary. +} + +static void vaapi_encode_h264_write_buffering_period(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + int i; + + ue(vpic_var(seq_parameter_set_id)); + + if (mseq->nal_hrd_parameters_present_flag) { + for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { + u(mseq->initial_cpb_removal_delay_length_minus1 + 1, + mseq_var(initial_cpb_removal_delay)); + u(mseq->initial_cpb_removal_delay_length_minus1 + 1, + mseq_var(initial_cpb_removal_delay_offset)); + } + } + if (mseq->vcl_hrd_parameters_present_flag) { + av_assert0(0 && "vcl hrd parameters not supported"); + } +} + +static void vaapi_encode_h264_write_pic_timing(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic) +{ + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i, num_clock_ts; + + if (mseq->nal_hrd_parameters_present_flag || + mseq->vcl_hrd_parameters_present_flag) { + u(mseq->cpb_removal_delay_length_minus1 + 1, + 2 * vseq->num_units_in_tick * priv->cpb_delay, + cpb_removal_delay); + u(mseq->dpb_output_delay_length_minus1 + 1, + 2 * vseq->num_units_in_tick * priv->dpb_delay, + dpb_output_delay); + } + if (mseq->pic_struct_present_flag) { + u(4, mseq_var(pic_struct)); + num_clock_ts = (mseq->pic_struct <= 2 ? 1 : + mseq->pic_struct <= 4 ? 2 : + mseq->pic_struct <= 8 ? 3 : 0); + for (i = 0; i < num_clock_ts; i++) { + u(1, 0, clock_timestamp_flag[i]); + // No full timestamp information. + } + } +} + +static void vaapi_encode_h264_write_identifier(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic) +{ + const char *lavc = LIBAVCODEC_IDENT; + const char *vaapi = VA_VERSION_S; + const char *driver = vaQueryVendorString(ctx->hwctx->display); + char tmp[256]; + int i; + + // Random (version 4) ISO 11578 UUID. + uint8_t uuid[16] = { + 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, + 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d, + }; + + for (i = 0; i < 16; i++) + u(8, uuid[i], uuid_iso_iec_11578); + + snprintf(tmp, sizeof(tmp), "%s / VAAPI %s / %s", lavc, vaapi, driver); + for (i = 0; i < sizeof(tmp) && tmp[i]; i++) + u(8, tmp[i], user_data_payload_byte); +} + +static void vaapi_encode_h264_write_sei(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeH264Context *priv = ctx->priv_data; + PutBitContext payload_bits; + char payload[256]; + int payload_type, payload_size, i; + void (*write_payload)(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic) = NULL; + + vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SEI, 0); + + for (payload_type = 0; payload_type < 64; payload_type++) { + switch (payload_type) { + case SEI_TYPE_BUFFERING_PERIOD: + if (!priv->send_timing_sei || + pic->type != PICTURE_TYPE_IDR) + continue; + write_payload = &vaapi_encode_h264_write_buffering_period; + break; + case SEI_TYPE_PIC_TIMING: + if (!priv->send_timing_sei) + continue; + write_payload = &vaapi_encode_h264_write_pic_timing; + break; + case SEI_TYPE_USER_DATA_UNREGISTERED: + if (pic->encode_order != 0) + continue; + write_payload = &vaapi_encode_h264_write_identifier; + break; + default: + continue; + } + + init_put_bits(&payload_bits, payload, sizeof(payload)); + write_payload(&payload_bits, ctx, pic); + if (put_bits_count(&payload_bits) & 7) { + write_u(&payload_bits, 1, 1, bit_equal_to_one); + while (put_bits_count(&payload_bits) & 7) + write_u(&payload_bits, 1, 0, bit_equal_to_zero); + } + payload_size = put_bits_count(&payload_bits) / 8; + flush_put_bits(&payload_bits); + + u(8, payload_type, last_payload_type_byte); + u(8, payload_size, last_payload_size_byte); + for (i = 0; i < payload_size; i++) + u(8, payload[i] & 0xff, sei_payload); + } + + vaapi_encode_h264_write_trailing_rbsp(pbc); +} + +static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + PutBitContext pbc; + char tmp[256]; + int err; + size_t nal_len, bit_len, bit_pos, next_len; + + bit_len = *data_len; + bit_pos = 0; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h264_write_sps(&pbc, ctx); + nal_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + next_len = bit_len - bit_pos; + err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, + &next_len, + tmp, nal_len); + if (err < 0) + return err; + bit_pos += next_len; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h264_write_pps(&pbc, ctx); + nal_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + next_len = bit_len - bit_pos; + err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, + &next_len, + tmp, nal_len); + if (err < 0) + return err; + bit_pos += next_len; + + *data_len = bit_pos; + return 0; +} + +static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + PutBitContext pbc; + char tmp[256]; + size_t header_len; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice); + header_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, + tmp, header_len); +} + +static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int index, int *type, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + PutBitContext pbc; + char tmp[256]; + size_t header_len; + + if (index == 0 && ctx->va_rc_mode == VA_RC_CBR) { + *type = VAEncPackedHeaderH264_SEI; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h264_write_sei(&pbc, ctx, pic); + header_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, + tmp, header_len); + + } else { + return AVERROR_EOF; + } +} + +static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + { + vseq->seq_parameter_set_id = 0; + + vseq->level_idc = avctx->level; + + vseq->max_num_ref_frames = 2; + + vseq->picture_width_in_mbs = priv->mb_width; + vseq->picture_height_in_mbs = priv->mb_height; + + vseq->seq_fields.bits.chroma_format_idc = 1; + vseq->seq_fields.bits.frame_mbs_only_flag = 1; + vseq->seq_fields.bits.direct_8x8_inference_flag = 1; + vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4; + vseq->seq_fields.bits.pic_order_cnt_type = 0; + + if (ctx->input_width != ctx->aligned_width || + ctx->input_height != ctx->aligned_height) { + vseq->frame_cropping_flag = 1; + + vseq->frame_crop_left_offset = 0; + vseq->frame_crop_right_offset = + (ctx->aligned_width - ctx->input_width) / 2; + vseq->frame_crop_top_offset = 0; + vseq->frame_crop_bottom_offset = + (ctx->aligned_height - ctx->input_height) / 2; + } else { + vseq->frame_cropping_flag = 0; + } + + vseq->vui_parameters_present_flag = 1; + if (avctx->sample_aspect_ratio.num != 0) { + vseq->vui_fields.bits.aspect_ratio_info_present_flag = 1; + // There is a large enum of these which we could support + // individually rather than using the generic X/Y form? + if (avctx->sample_aspect_ratio.num == + avctx->sample_aspect_ratio.den) { + vseq->aspect_ratio_idc = 1; + } else { + vseq->aspect_ratio_idc = 255; // Extended SAR. + vseq->sar_width = avctx->sample_aspect_ratio.num; + vseq->sar_height = avctx->sample_aspect_ratio.den; + } + } + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + mseq->video_signal_type_present_flag = 1; + mseq->video_format = 5; // Unspecified. + mseq->video_full_range_flag = 0; + mseq->colour_description_present_flag = 1; + // These enums are derived from the standard and hence + // we can just use the values directly. + mseq->colour_primaries = avctx->color_primaries; + mseq->transfer_characteristics = avctx->color_trc; + mseq->matrix_coefficients = avctx->colorspace; + } + + vseq->bits_per_second = avctx->bit_rate; + + vseq->vui_fields.bits.timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + vseq->num_units_in_tick = avctx->framerate.num; + vseq->time_scale = 2 * avctx->framerate.den; + mseq->fixed_frame_rate_flag = 1; + } else { + vseq->num_units_in_tick = avctx->time_base.num; + vseq->time_scale = 2 * avctx->time_base.den; + mseq->fixed_frame_rate_flag = 0; + } + + if (ctx->va_rc_mode == VA_RC_CBR) { + priv->send_timing_sei = 1; + mseq->nal_hrd_parameters_present_flag = 1; + + mseq->cpb_cnt_minus1 = 0; + + // Try to scale these to a sensible range so that the + // golomb encode of the value is not overlong. + mseq->bit_rate_scale = + av_clip(av_log2(avctx->bit_rate) - 15, 0, 15); + mseq->bit_rate_value_minus1[0] = + (avctx->bit_rate >> mseq->bit_rate_scale) - 1; + + mseq->cpb_size_scale = + av_clip(av_log2(priv->hrd_params.hrd.buffer_size) - 15, 0, 15); + mseq->cpb_size_value_minus1[0] = + (priv->hrd_params.hrd.buffer_size >> mseq->cpb_size_scale) - 1; + + // CBR mode isn't actually available here, despite naming. + mseq->cbr_flag[0] = 0; + + mseq->initial_cpb_removal_delay_length_minus1 = 23; + mseq->cpb_removal_delay_length_minus1 = 23; + mseq->dpb_output_delay_length_minus1 = 7; + mseq->time_offset_length = 0; + + // This calculation can easily overflow 32 bits. + mseq->initial_cpb_removal_delay = 90000 * + (uint64_t)priv->hrd_params.hrd.initial_buffer_fullness / + priv->hrd_params.hrd.buffer_size; + + mseq->initial_cpb_removal_delay_offset = 0; + } else { + priv->send_timing_sei = 0; + mseq->nal_hrd_parameters_present_flag = 0; + } + + vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1); + vseq->intra_idr_period = vseq->intra_period; + vseq->ip_period = ctx->b_per_p + 1; + } + + { + vpic->CurrPic.picture_id = VA_INVALID_ID; + vpic->CurrPic.flags = VA_PICTURE_H264_INVALID; + + for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { + vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; + vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + } + + vpic->coded_buf = VA_INVALID_ID; + + vpic->pic_parameter_set_id = 0; + vpic->seq_parameter_set_id = 0; + + vpic->num_ref_idx_l0_active_minus1 = 0; + vpic->num_ref_idx_l1_active_minus1 = 0; + + vpic->pic_fields.bits.entropy_coding_mode_flag = + ((avctx->profile & 0xff) != 66); + vpic->pic_fields.bits.weighted_pred_flag = 0; + vpic->pic_fields.bits.weighted_bipred_idc = 0; + vpic->pic_fields.bits.transform_8x8_mode_flag = + ((avctx->profile & 0xff) >= 100); + + vpic->pic_init_qp = priv->fixed_qp_idr; + } + + { + mseq->profile_idc = avctx->profile & 0xff; + + if (avctx->profile & FF_PROFILE_H264_CONSTRAINED) + mseq->constraint_set1_flag = 1; + if (avctx->profile & FF_PROFILE_H264_INTRA) + mseq->constraint_set3_flag = 1; + } + + return 0; +} + +static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + int i; + + if (pic->type == PICTURE_TYPE_IDR) { + av_assert0(pic->display_order == pic->encode_order); + vpic->frame_num = 0; + priv->next_frame_num = 1; + priv->cpb_delay = 0; + } else { + vpic->frame_num = priv->next_frame_num; + if (pic->type != PICTURE_TYPE_B) { + // nal_ref_idc != 0 + ++priv->next_frame_num; + } + ++priv->cpb_delay; + } + priv->dpb_delay = pic->display_order - pic->encode_order + 1; + + vpic->frame_num = vpic->frame_num & + ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1); + + vpic->CurrPic.picture_id = pic->recon_surface; + vpic->CurrPic.frame_idx = vpic->frame_num; + vpic->CurrPic.flags = 0; + vpic->CurrPic.TopFieldOrderCnt = pic->display_order; + vpic->CurrPic.BottomFieldOrderCnt = pic->display_order; + + for (i = 0; i < pic->nb_refs; i++) { + VAAPIEncodePicture *ref = pic->refs[i]; + av_assert0(ref && ref->encode_order < pic->encode_order); + vpic->ReferenceFrames[i].picture_id = ref->recon_surface; + vpic->ReferenceFrames[i].frame_idx = ref->encode_order; + vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; + vpic->ReferenceFrames[i].TopFieldOrderCnt = ref->display_order; + vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order; + } + for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { + vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; + vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + } + + vpic->coded_buf = pic->output_buffer; + + vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); + vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B); + + pic->nb_slices = 1; + + return 0; +} + +static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Slice *pslice; + VAAPIEncodeH264MiscSliceParams *mslice; + int i; + + slice->priv_data = av_mallocz(sizeof(*pslice)); + if (!slice->priv_data) + return AVERROR(ENOMEM); + pslice = slice->priv_data; + mslice = &pslice->misc_slice_params; + + if (pic->type == PICTURE_TYPE_IDR) + mslice->nal_unit_type = H264_NAL_IDR_SLICE; + else + mslice->nal_unit_type = H264_NAL_SLICE; + + switch (pic->type) { + case PICTURE_TYPE_IDR: + vslice->slice_type = SLICE_TYPE_I; + mslice->nal_ref_idc = 3; + break; + case PICTURE_TYPE_I: + vslice->slice_type = SLICE_TYPE_I; + mslice->nal_ref_idc = 2; + break; + case PICTURE_TYPE_P: + vslice->slice_type = SLICE_TYPE_P; + mslice->nal_ref_idc = 1; + break; + case PICTURE_TYPE_B: + vslice->slice_type = SLICE_TYPE_B; + mslice->nal_ref_idc = 0; + break; + default: + av_assert0(0 && "invalid picture type"); + } + + // Only one slice per frame. + vslice->macroblock_address = 0; + vslice->num_macroblocks = priv->mb_width * priv->mb_height; + + vslice->macroblock_info = VA_INVALID_ID; + + vslice->pic_parameter_set_id = vpic->pic_parameter_set_id; + vslice->idr_pic_id = priv->idr_pic_count++; + + vslice->pic_order_cnt_lsb = pic->display_order & + ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1); + + for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) { + vslice->RefPicList0[i].picture_id = VA_INVALID_ID; + vslice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + vslice->RefPicList1[i].picture_id = VA_INVALID_ID; + vslice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID; + } + + av_assert0(pic->nb_refs <= 2); + if (pic->nb_refs >= 1) { + // Backward reference for P- or B-frame. + av_assert0(pic->type == PICTURE_TYPE_P || + pic->type == PICTURE_TYPE_B); + + vslice->num_ref_idx_l0_active_minus1 = 0; + vslice->RefPicList0[0] = vpic->ReferenceFrames[0]; + } + if (pic->nb_refs >= 2) { + // Forward reference for B-frame. + av_assert0(pic->type == PICTURE_TYPE_B); + + vslice->num_ref_idx_l1_active_minus1 = 0; + vslice->RefPicList1[0] = vpic->ReferenceFrames[1]; + } + + if (pic->type == PICTURE_TYPE_B) + vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; + else if (pic->type == PICTURE_TYPE_P) + vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; + else + vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; + + vslice->direct_spatial_mv_pred_flag = 1; + + return 0; +} + +static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + int hrd_buffer_size; + int hrd_initial_buffer_fullness; + + if (avctx->rc_buffer_size) + hrd_buffer_size = avctx->rc_buffer_size; + else + hrd_buffer_size = avctx->bit_rate; + if (avctx->rc_initial_buffer_occupancy) + hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy; + else + hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4; + + priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl; + priv->rc_params.rc = (VAEncMiscParameterRateControl) { + .bits_per_second = avctx->bit_rate, + .target_percentage = 66, + .window_size = 1000, + .initial_qp = (avctx->qmax >= 0 ? avctx->qmax : 40), + .min_qp = (avctx->qmin >= 0 ? avctx->qmin : 18), + .basic_unit_size = 0, + }; + ctx->global_params[ctx->nb_global_params] = + &priv->rc_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(priv->rc_params); + + priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD; + priv->hrd_params.hrd = (VAEncMiscParameterHRD) { + .initial_buffer_fullness = hrd_initial_buffer_fullness, + .buffer_size = hrd_buffer_size, + }; + ctx->global_params[ctx->nb_global_params] = + &priv->hrd_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(priv->hrd_params); + + // These still need to be set for pic_init_qp/slice_qp_delta. + priv->fixed_qp_idr = 26; + priv->fixed_qp_p = 26; + priv->fixed_qp_b = 26; + + av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n", + avctx->bit_rate); + return 0; +} + +static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + + priv->fixed_qp_p = opt->qp; + if (avctx->i_quant_factor > 0.0) + priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor + + avctx->i_quant_offset) + 0.5); + else + priv->fixed_qp_idr = priv->fixed_qp_p; + if (avctx->b_quant_factor > 0.0) + priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor + + avctx->b_quant_offset) + 0.5); + else + priv->fixed_qp_b = priv->fixed_qp_p; + + av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " + "%d / %d / %d for IDR- / P- / B-frames.\n", + priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); + return 0; +} + +static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) +{ + static const VAConfigAttrib default_config_attributes[] = { + { .type = VAConfigAttribRTFormat, + .value = VA_RT_FORMAT_YUV420 }, + { .type = VAConfigAttribEncPackedHeaders, + .value = (VA_ENC_PACKED_HEADER_SEQUENCE | + VA_ENC_PACKED_HEADER_SLICE) }, + }; + + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + int i, err; + + switch (avctx->profile) { + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + ctx->va_profile = VAProfileH264ConstrainedBaseline; + break; + case FF_PROFILE_H264_BASELINE: + ctx->va_profile = VAProfileH264Baseline; + break; + case FF_PROFILE_H264_MAIN: + ctx->va_profile = VAProfileH264Main; + break; + case FF_PROFILE_H264_EXTENDED: + av_log(avctx, AV_LOG_ERROR, "H.264 extended profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_UNKNOWN: + case FF_PROFILE_H264_HIGH: + ctx->va_profile = VAProfileH264High; + break; + case FF_PROFILE_H264_HIGH_10: + case FF_PROFILE_H264_HIGH_10_INTRA: + av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles " + "are not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_H264_HIGH_422: + case FF_PROFILE_H264_HIGH_422_INTRA: + case FF_PROFILE_H264_HIGH_444: + case FF_PROFILE_H264_HIGH_444_PREDICTIVE: + case FF_PROFILE_H264_HIGH_444_INTRA: + case FF_PROFILE_H264_CAVLC_444: + av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles " + "are not supported.\n"); + return AVERROR_PATCHWELCOME; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n", + avctx->profile); + return AVERROR(EINVAL); + } + if (opt->low_power) { +#if VA_CHECK_VERSION(0, 39, 1) + ctx->va_entrypoint = VAEntrypointEncSliceLP; +#else + av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not " + "supported with this VAAPI version.\n"); + return AVERROR(EINVAL); +#endif + } else { + ctx->va_entrypoint = VAEntrypointEncSlice; + } + + ctx->input_width = avctx->width; + ctx->input_height = avctx->height; + ctx->aligned_width = FFALIGN(ctx->input_width, 16); + ctx->aligned_height = FFALIGN(ctx->input_height, 16); + priv->mb_width = ctx->aligned_width / 16; + priv->mb_height = ctx->aligned_height / 16; + + for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { + ctx->config_attributes[ctx->nb_config_attributes++] = + default_config_attributes[i]; + } + + if (avctx->bit_rate > 0) { + ctx->va_rc_mode = VA_RC_CBR; + err = vaapi_encode_h264_init_constant_bitrate(avctx); + } else { + ctx->va_rc_mode = VA_RC_CQP; + err = vaapi_encode_h264_init_fixed_qp(avctx); + } + if (err < 0) + return err; + + ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) { + .type = VAConfigAttribRateControl, + .value = ctx->va_rc_mode, + }; + + if (opt->quality > 0) { +#if VA_CHECK_VERSION(0, 36, 0) + priv->quality_params.misc.type = + VAEncMiscParameterTypeQualityLevel; + priv->quality_params.quality.quality_level = opt->quality; + + ctx->global_params[ctx->nb_global_params] = + &priv->quality_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(priv->quality_params); +#else + av_log(avctx, AV_LOG_WARNING, "The encode quality option is not " + "supported with this VAAPI version.\n"); +#endif + } + + ctx->nb_recon_frames = 20; + + return 0; +} + +static VAAPIEncodeType vaapi_encode_type_h264 = { + .priv_data_size = sizeof(VAAPIEncodeH264Context), + + .init = &vaapi_encode_h264_init_internal, + + .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264), + .init_sequence_params = &vaapi_encode_h264_init_sequence_params, + + .picture_params_size = sizeof(VAEncPictureParameterBufferH264), + .init_picture_params = &vaapi_encode_h264_init_picture_params, + + .slice_params_size = sizeof(VAEncSliceParameterBufferH264), + .init_slice_params = &vaapi_encode_h264_init_slice_params, + + .sequence_header_type = VAEncPackedHeaderSequence, + .write_sequence_header = &vaapi_encode_h264_write_sequence_header, + + .slice_header_type = VAEncPackedHeaderH264_Slice, + .write_slice_header = &vaapi_encode_h264_write_slice_header, + + .write_extra_header = &vaapi_encode_h264_write_extra_header, +}; + +static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) +{ + return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264); +} + +#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ + offsetof(VAAPIEncodeH264Options, x)) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +static const AVOption vaapi_encode_h264_options[] = { + { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", + OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS }, + { "quality", "Set encode quality (trades off against speed, higher is faster)", + OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, FLAGS }, + { "low_power", "Use low-power encoding mode (experimental: only supported " + "on some platforms, does not support all features)", + OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, +}; + +static const AVCodecDefault vaapi_encode_h264_defaults[] = { + { "profile", "100" }, + { "level", "51" }, + { "b", "0" }, + { "bf", "2" }, + { "g", "120" }, + { "i_qfactor", "1.0" }, + { "i_qoffset", "0.0" }, + { "b_qfactor", "1.2" }, + { "b_qoffset", "0.0" }, + { NULL }, +}; + +static const AVClass vaapi_encode_h264_class = { + .class_name = "h264_vaapi", + .item_name = av_default_item_name, + .option = vaapi_encode_h264_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_vaapi_encoder = { + .name = "h264_vaapi", + .long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = (sizeof(VAAPIEncodeContext) + + sizeof(VAAPIEncodeH264Options)), + .init = &vaapi_encode_h264_init, + .encode2 = &ff_vaapi_encode2, + .close = &ff_vaapi_encode_close, + .priv_class = &vaapi_encode_h264_class, + .capabilities = AV_CODEC_CAP_DELAY, + .defaults = vaapi_encode_h264_defaults, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE, + }, +}; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c new file mode 100644 index 0000000..010db92 --- /dev/null +++ b/libavcodec/vaapi_encode_h265.c @@ -0,0 +1,1369 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "hevc.h" +#include "internal.h" +#include "put_bits.h" +#include "vaapi_encode.h" +#include "vaapi_encode_h26x.h" + + +#define MAX_ST_REF_PIC_SETS 32 +#define MAX_DPB_PICS 16 +#define MAX_LAYERS 1 + + +typedef struct VAAPIEncodeH265STRPS { + char inter_ref_pic_set_prediction_flag; + + unsigned int num_negative_pics; + unsigned int num_positive_pics; + + unsigned int delta_poc_s0_minus1[MAX_DPB_PICS]; + char used_by_curr_pic_s0_flag[MAX_DPB_PICS]; + + unsigned int delta_poc_s1_minus1[MAX_DPB_PICS]; + char used_by_curr_pic_s1_flag[MAX_DPB_PICS]; +} VAAPIEncodeH265STRPS; + +// This structure contains all possibly-useful per-sequence syntax elements +// which are not already contained in the various VAAPI structures. +typedef struct VAAPIEncodeH265MiscSequenceParams { + + // Parameter set IDs. + unsigned int video_parameter_set_id; + unsigned int seq_parameter_set_id; + + // Layering. + unsigned int vps_max_layers_minus1; + unsigned int vps_max_sub_layers_minus1; + char vps_temporal_id_nesting_flag; + unsigned int vps_max_layer_id; + unsigned int vps_num_layer_sets_minus1; + unsigned int sps_max_sub_layers_minus1; + char sps_temporal_id_nesting_flag; + char layer_id_included_flag[MAX_LAYERS][64]; + + // Profile/tier/level parameters. + char general_profile_compatibility_flag[32]; + char general_progressive_source_flag; + char general_interlaced_source_flag; + char general_non_packed_constraint_flag; + char general_frame_only_constraint_flag; + char general_inbld_flag; + + // Decode/display ordering parameters. + unsigned int log2_max_pic_order_cnt_lsb_minus4; + char vps_sub_layer_ordering_info_present_flag; + unsigned int vps_max_dec_pic_buffering_minus1[MAX_LAYERS]; + unsigned int vps_max_num_reorder_pics[MAX_LAYERS]; + unsigned int vps_max_latency_increase_plus1[MAX_LAYERS]; + char sps_sub_layer_ordering_info_present_flag; + unsigned int sps_max_dec_pic_buffering_minus1[MAX_LAYERS]; + unsigned int sps_max_num_reorder_pics[MAX_LAYERS]; + unsigned int sps_max_latency_increase_plus1[MAX_LAYERS]; + + // Timing information. + char vps_timing_info_present_flag; + unsigned int vps_num_units_in_tick; + unsigned int vps_time_scale; + char vps_poc_proportional_to_timing_flag; + unsigned int vps_num_ticks_poc_diff_minus1; + + // Cropping information. + char conformance_window_flag; + unsigned int conf_win_left_offset; + unsigned int conf_win_right_offset; + unsigned int conf_win_top_offset; + unsigned int conf_win_bottom_offset; + + // Short-term reference picture sets. + unsigned int num_short_term_ref_pic_sets; + VAAPIEncodeH265STRPS st_ref_pic_set[MAX_ST_REF_PIC_SETS]; + + // Long-term reference pictures. + char long_term_ref_pics_present_flag; + unsigned int num_long_term_ref_pics_sps; + struct { + unsigned int lt_ref_pic_poc_lsb_sps; + char used_by_curr_pic_lt_sps_flag; + } lt_ref_pic; + + // Deblocking filter control. + char deblocking_filter_control_present_flag; + char deblocking_filter_override_enabled_flag; + char pps_deblocking_filter_disabled_flag; + int pps_beta_offset_div2; + int pps_tc_offset_div2; + + // Video Usability Information. + char vui_parameters_present_flag; + char aspect_ratio_info_present_flag; + unsigned int aspect_ratio_idc; + unsigned int sar_width; + unsigned int sar_height; + char video_signal_type_present_flag; + unsigned int video_format; + char video_full_range_flag; + char colour_description_present_flag; + unsigned int colour_primaries; + unsigned int transfer_characteristics; + unsigned int matrix_coeffs; + + // Oddments. + char uniform_spacing_flag; + char output_flag_present_flag; + char cabac_init_present_flag; + unsigned int num_extra_slice_header_bits; + char lists_modification_present_flag; + char pps_slice_chroma_qp_offsets_present_flag; + char pps_slice_chroma_offset_list_enabled_flag; +} VAAPIEncodeH265MiscSequenceParams; + +// This structure contains all possibly-useful per-slice syntax elements +// which are not already contained in the various VAAPI structures. +typedef struct VAAPIEncodeH265MiscSliceParams { + // Slice segments. + char first_slice_segment_in_pic_flag; + unsigned int slice_segment_address; + + // Short-term reference picture sets. + char short_term_ref_pic_set_sps_flag; + unsigned int short_term_ref_pic_idx; + VAAPIEncodeH265STRPS st_ref_pic_set; + + // Deblocking filter. + char deblocking_filter_override_flag; + + // Oddments. + char slice_reserved_flag[8]; + char no_output_of_prior_pics_flag; + char pic_output_flag; +} VAAPIEncodeH265MiscSliceParams; + +typedef struct VAAPIEncodeH265Slice { + VAAPIEncodeH265MiscSliceParams misc_slice_params; + + int64_t pic_order_cnt; +} VAAPIEncodeH265Slice; + +typedef struct VAAPIEncodeH265Context { + VAAPIEncodeH265MiscSequenceParams misc_sequence_params; + + unsigned int ctu_width; + unsigned int ctu_height; + + int fixed_qp_idr; + int fixed_qp_p; + int fixed_qp_b; + + int64_t last_idr_frame; + + // Rate control configuration. + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterRateControl rc; + } rc_params; + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterHRD hrd; + } hrd_params; +} VAAPIEncodeH265Context; + +typedef struct VAAPIEncodeH265Options { + int qp; +} VAAPIEncodeH265Options; + + +#define vseq_var(name) vseq->name, name +#define vseq_field(name) vseq->seq_fields.bits.name, name +#define vpic_var(name) vpic->name, name +#define vpic_field(name) vpic->pic_fields.bits.name, name +#define vslice_var(name) vslice->name, name +#define vslice_field(name) vslice->slice_fields.bits.name, name +#define mseq_var(name) mseq->name, name +#define mslice_var(name) mslice->name, name +#define mstrps_var(name) mstrps->name, name + +static void vaapi_encode_h265_write_nal_unit_header(PutBitContext *pbc, + int nal_unit_type) +{ + u(1, 0, forbidden_zero_bit); + u(6, nal_unit_type, nal_unit_type); + u(6, 0, nuh_layer_id); + u(3, 1, nuh_temporal_id_plus1); +} + +static void vaapi_encode_h265_write_rbsp_trailing_bits(PutBitContext *pbc) +{ + u(1, 1, rbsp_stop_one_bit); + while (put_bits_count(pbc) & 7) + u(1, 0, rbsp_alignment_zero_bit); +} + +static void vaapi_encode_h265_write_profile_tier_level(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + int j; + + if (1) { + u(2, 0, general_profile_space); + u(1, vseq_var(general_tier_flag)); + u(5, vseq_var(general_profile_idc)); + + for (j = 0; j < 32; j++) { + u(1, mseq_var(general_profile_compatibility_flag[j])); + } + + u(1, mseq_var(general_progressive_source_flag)); + u(1, mseq_var(general_interlaced_source_flag)); + u(1, mseq_var(general_non_packed_constraint_flag)); + u(1, mseq_var(general_frame_only_constraint_flag)); + + if (0) { + // Not main profile. + // Lots of extra constraint flags. + } else { + // put_bits only handles up to 31 bits. + u(23, 0, general_reserved_zero_43bits); + u(20, 0, general_reserved_zero_43bits); + } + + if (vseq->general_profile_idc >= 1 && vseq->general_profile_idc <= 5) { + u(1, mseq_var(general_inbld_flag)); + } else { + u(1, 0, general_reserved_zero_bit); + } + } + + u(8, vseq_var(general_level_idc)); + + // No sublayers. +} + +static void vaapi_encode_h265_write_vps(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i, j; + + vaapi_encode_h265_write_nal_unit_header(pbc, NAL_VPS); + + u(4, mseq->video_parameter_set_id, vps_video_parameter_set_id); + + u(1, 1, vps_base_layer_internal_flag); + u(1, 1, vps_base_layer_available_flag); + u(6, mseq_var(vps_max_layers_minus1)); + u(3, mseq_var(vps_max_sub_layers_minus1)); + u(1, mseq_var(vps_temporal_id_nesting_flag)); + + u(16, 0xffff, vps_reserved_0xffff_16bits); + + vaapi_encode_h265_write_profile_tier_level(pbc, ctx); + + u(1, mseq_var(vps_sub_layer_ordering_info_present_flag)); + for (i = (mseq->vps_sub_layer_ordering_info_present_flag ? + 0 : mseq->vps_max_sub_layers_minus1); + i <= mseq->vps_max_sub_layers_minus1; i++) { + ue(mseq_var(vps_max_dec_pic_buffering_minus1[i])); + ue(mseq_var(vps_max_num_reorder_pics[i])); + ue(mseq_var(vps_max_latency_increase_plus1[i])); + } + + u(6, mseq_var(vps_max_layer_id)); + ue(mseq_var(vps_num_layer_sets_minus1)); + for (i = 1; i <= mseq->vps_num_layer_sets_minus1; i++) { + for (j = 0; j < mseq->vps_max_layer_id; j++) + u(1, mseq_var(layer_id_included_flag[i][j])); + } + + u(1, mseq_var(vps_timing_info_present_flag)); + if (mseq->vps_timing_info_present_flag) { + u(1, 0, put_bits_hack_zero_bit); + u(31, mseq_var(vps_num_units_in_tick)); + u(1, 0, put_bits_hack_zero_bit); + u(31, mseq_var(vps_time_scale)); + u(1, mseq_var(vps_poc_proportional_to_timing_flag)); + if (mseq->vps_poc_proportional_to_timing_flag) { + ue(mseq_var(vps_num_ticks_poc_diff_minus1)); + } + ue(0, vps_num_hrd_parameters); + } + + u(1, 0, vps_extension_flag); + + vaapi_encode_h265_write_rbsp_trailing_bits(pbc); +} + +static void vaapi_encode_h265_write_st_ref_pic_set(PutBitContext *pbc, + int st_rps_idx, + VAAPIEncodeH265STRPS *mstrps) +{ + int i; + + if (st_rps_idx != 0) + u(1, mstrps_var(inter_ref_pic_set_prediction_flag)); + + if (mstrps->inter_ref_pic_set_prediction_flag) { + av_assert0(0 && "inter ref pic set prediction not supported"); + } else { + ue(mstrps_var(num_negative_pics)); + ue(mstrps_var(num_positive_pics)); + + for (i = 0; i < mstrps->num_negative_pics; i++) { + ue(mstrps_var(delta_poc_s0_minus1[i])); + u(1, mstrps_var(used_by_curr_pic_s0_flag[i])); + } + for (i = 0; i < mstrps->num_positive_pics; i++) { + ue(mstrps_var(delta_poc_s1_minus1[i])); + u(1, mstrps_var(used_by_curr_pic_s1_flag[i])); + } + } +} + +static void vaapi_encode_h265_write_vui_parameters(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + + u(1, mseq_var(aspect_ratio_info_present_flag)); + if (mseq->aspect_ratio_info_present_flag) { + u(8, mseq_var(aspect_ratio_idc)); + if (mseq->aspect_ratio_idc == 255) { + u(16, mseq_var(sar_width)); + u(16, mseq_var(sar_height)); + } + } + + u(1, 0, overscan_info_present_flag); + + u(1, mseq_var(video_signal_type_present_flag)); + if (mseq->video_signal_type_present_flag) { + u(3, mseq_var(video_format)); + u(1, mseq_var(video_full_range_flag)); + u(1, mseq_var(colour_description_present_flag)); + if (mseq->colour_description_present_flag) { + u(8, mseq_var(colour_primaries)); + u(8, mseq_var(transfer_characteristics)); + u(8, mseq_var(matrix_coeffs)); + } + } + + u(1, 0, chroma_loc_info_present_flag); + u(1, 0, neutral_chroma_indication_flag); + u(1, 0, field_seq_flag); + u(1, 0, frame_field_info_present_flag); + u(1, 0, default_display_window_flag); + u(1, 0, vui_timing_info_present_flag); + u(1, 0, bitstream_restriction_flag_flag); +} + +static void vaapi_encode_h265_write_sps(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + vaapi_encode_h265_write_nal_unit_header(pbc, NAL_SPS); + + u(4, mseq->video_parameter_set_id, sps_video_parameter_set_id); + + u(3, mseq_var(sps_max_sub_layers_minus1)); + u(1, mseq_var(sps_temporal_id_nesting_flag)); + + vaapi_encode_h265_write_profile_tier_level(pbc, ctx); + + ue(mseq->seq_parameter_set_id, sps_seq_parameter_set_id); + ue(vseq_field(chroma_format_idc)); + if (vseq->seq_fields.bits.chroma_format_idc == 3) + u(1, 0, separate_colour_plane_flag); + + ue(vseq_var(pic_width_in_luma_samples)); + ue(vseq_var(pic_height_in_luma_samples)); + + u(1, mseq_var(conformance_window_flag)); + if (mseq->conformance_window_flag) { + ue(mseq_var(conf_win_left_offset)); + ue(mseq_var(conf_win_right_offset)); + ue(mseq_var(conf_win_top_offset)); + ue(mseq_var(conf_win_bottom_offset)); + } + + ue(vseq_field(bit_depth_luma_minus8)); + ue(vseq_field(bit_depth_chroma_minus8)); + + ue(mseq_var(log2_max_pic_order_cnt_lsb_minus4)); + + u(1, mseq_var(sps_sub_layer_ordering_info_present_flag)); + for (i = (mseq->sps_sub_layer_ordering_info_present_flag ? + 0 : mseq->sps_max_sub_layers_minus1); + i <= mseq->sps_max_sub_layers_minus1; i++) { + ue(mseq_var(sps_max_dec_pic_buffering_minus1[i])); + ue(mseq_var(sps_max_num_reorder_pics[i])); + ue(mseq_var(sps_max_latency_increase_plus1[i])); + } + + ue(vseq_var(log2_min_luma_coding_block_size_minus3)); + ue(vseq_var(log2_diff_max_min_luma_coding_block_size)); + ue(vseq_var(log2_min_transform_block_size_minus2)); + ue(vseq_var(log2_diff_max_min_transform_block_size)); + ue(vseq_var(max_transform_hierarchy_depth_inter)); + ue(vseq_var(max_transform_hierarchy_depth_intra)); + + u(1, vseq_field(scaling_list_enabled_flag)); + if (vseq->seq_fields.bits.scaling_list_enabled_flag) { + u(1, 0, sps_scaling_list_data_present_flag); + } + + u(1, vseq_field(amp_enabled_flag)); + u(1, vseq_field(sample_adaptive_offset_enabled_flag)); + + u(1, vseq_field(pcm_enabled_flag)); + if (vseq->seq_fields.bits.pcm_enabled_flag) { + u(4, vseq_var(pcm_sample_bit_depth_luma_minus1)); + u(4, vseq_var(pcm_sample_bit_depth_chroma_minus1)); + ue(vseq_var(log2_min_pcm_luma_coding_block_size_minus3)); + ue(vseq->log2_max_pcm_luma_coding_block_size_minus3 - + vseq->log2_min_pcm_luma_coding_block_size_minus3, + log2_diff_max_min_pcm_luma_coding_block_size); + u(1, vseq_field(pcm_loop_filter_disabled_flag)); + } + + ue(mseq_var(num_short_term_ref_pic_sets)); + for (i = 0; i < mseq->num_short_term_ref_pic_sets; i++) + vaapi_encode_h265_write_st_ref_pic_set(pbc, i, + &mseq->st_ref_pic_set[i]); + + u(1, mseq_var(long_term_ref_pics_present_flag)); + if (mseq->long_term_ref_pics_present_flag) { + ue(0, num_long_term_ref_pics_sps); + } + + u(1, vseq_field(sps_temporal_mvp_enabled_flag)); + u(1, vseq_field(strong_intra_smoothing_enabled_flag)); + + u(1, mseq_var(vui_parameters_present_flag)); + if (mseq->vui_parameters_present_flag) { + vaapi_encode_h265_write_vui_parameters(pbc, ctx); + } + + u(1, 0, sps_extension_present_flag); + + vaapi_encode_h265_write_rbsp_trailing_bits(pbc); +} + +static void vaapi_encode_h265_write_pps(PutBitContext *pbc, + VAAPIEncodeContext *ctx) +{ + VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + vaapi_encode_h265_write_nal_unit_header(pbc, NAL_PPS); + + ue(vpic->slice_pic_parameter_set_id, pps_pic_parameter_set_id); + ue(mseq->seq_parameter_set_id, pps_seq_parameter_set_id); + + u(1, vpic_field(dependent_slice_segments_enabled_flag)); + u(1, mseq_var(output_flag_present_flag)); + u(3, mseq_var(num_extra_slice_header_bits)); + u(1, vpic_field(sign_data_hiding_enabled_flag)); + u(1, mseq_var(cabac_init_present_flag)); + + ue(vpic_var(num_ref_idx_l0_default_active_minus1)); + ue(vpic_var(num_ref_idx_l1_default_active_minus1)); + + se(vpic->pic_init_qp - 26, init_qp_minus26); + + u(1, vpic_field(constrained_intra_pred_flag)); + u(1, vpic_field(transform_skip_enabled_flag)); + + u(1, vpic_field(cu_qp_delta_enabled_flag)); + if (vpic->pic_fields.bits.cu_qp_delta_enabled_flag) + ue(vpic_var(diff_cu_qp_delta_depth)); + + se(vpic_var(pps_cb_qp_offset)); + se(vpic_var(pps_cr_qp_offset)); + + u(1, mseq_var(pps_slice_chroma_qp_offsets_present_flag)); + u(1, vpic_field(weighted_pred_flag)); + u(1, vpic_field(weighted_bipred_flag)); + u(1, vpic_field(transquant_bypass_enabled_flag)); + u(1, vpic_field(tiles_enabled_flag)); + u(1, vpic_field(entropy_coding_sync_enabled_flag)); + + if (vpic->pic_fields.bits.tiles_enabled_flag) { + ue(vpic_var(num_tile_columns_minus1)); + ue(vpic_var(num_tile_rows_minus1)); + u(1, mseq_var(uniform_spacing_flag)); + if (!mseq->uniform_spacing_flag) { + for (i = 0; i < vpic->num_tile_columns_minus1; i++) + ue(vpic_var(column_width_minus1[i])); + for (i = 0; i < vpic->num_tile_rows_minus1; i++) + ue(vpic_var(row_height_minus1[i])); + } + u(1, vpic_field(loop_filter_across_tiles_enabled_flag)); + } + + u(1, vpic_field(pps_loop_filter_across_slices_enabled_flag)); + u(1, mseq_var(deblocking_filter_control_present_flag)); + if (mseq->deblocking_filter_control_present_flag) { + u(1, mseq_var(deblocking_filter_override_enabled_flag)); + u(1, mseq_var(pps_deblocking_filter_disabled_flag)); + if (!mseq->pps_deblocking_filter_disabled_flag) { + se(mseq_var(pps_beta_offset_div2)); + se(mseq_var(pps_tc_offset_div2)); + } + } + + u(1, 0, pps_scaling_list_data_present_flag); + // No scaling list data. + + u(1, mseq_var(lists_modification_present_flag)); + ue(vpic_var(log2_parallel_merge_level_minus2)); + u(1, 0, slice_segment_header_extension_present_flag); + u(1, 0, pps_extension_present_flag); + + vaapi_encode_h265_write_rbsp_trailing_bits(pbc); +} + +static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc, + VAAPIEncodeContext *ctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice) +{ + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + VAAPIEncodeH265Slice *pslice = slice->priv_data; + VAAPIEncodeH265MiscSliceParams *mslice = &pslice->misc_slice_params; + int i; + + vaapi_encode_h265_write_nal_unit_header(pbc, vpic->nal_unit_type); + + u(1, mslice_var(first_slice_segment_in_pic_flag)); + if (vpic->nal_unit_type >= NAL_BLA_W_LP && + vpic->nal_unit_type <= 23) + u(1, mslice_var(no_output_of_prior_pics_flag)); + + ue(vslice_var(slice_pic_parameter_set_id)); + + if (!mslice->first_slice_segment_in_pic_flag) { + if (vpic->pic_fields.bits.dependent_slice_segments_enabled_flag) + u(1, vslice_field(dependent_slice_segment_flag)); + u(av_log2((priv->ctu_width * priv->ctu_height) - 1) + 1, + mslice_var(slice_segment_address)); + } + if (!vslice->slice_fields.bits.dependent_slice_segment_flag) { + for (i = 0; i < mseq->num_extra_slice_header_bits; i++) + u(1, mslice_var(slice_reserved_flag[i])); + + ue(vslice_var(slice_type)); + if (mseq->output_flag_present_flag) + u(1, 1, pic_output_flag); + if (vseq->seq_fields.bits.separate_colour_plane_flag) + u(2, vslice_field(colour_plane_id)); + if (vpic->nal_unit_type != NAL_IDR_W_RADL && + vpic->nal_unit_type != NAL_IDR_N_LP) { + u(4 + mseq->log2_max_pic_order_cnt_lsb_minus4, + (pslice->pic_order_cnt & + ((1 << (mseq->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1)), + slice_pic_order_cnt_lsb); + + u(1, mslice_var(short_term_ref_pic_set_sps_flag)); + if (!mslice->short_term_ref_pic_set_sps_flag) { + vaapi_encode_h265_write_st_ref_pic_set(pbc, mseq->num_short_term_ref_pic_sets, + &mslice->st_ref_pic_set); + } else if (mseq->num_short_term_ref_pic_sets > 1) { + u(av_log2(mseq->num_short_term_ref_pic_sets - 1) + 1, + mslice_var(short_term_ref_pic_idx)); + } + + if (mseq->long_term_ref_pics_present_flag) { + av_assert0(0); + } + + if (vseq->seq_fields.bits.sps_temporal_mvp_enabled_flag) { + u(1, vslice_field(slice_temporal_mvp_enabled_flag)); + } + + if (vseq->seq_fields.bits.sample_adaptive_offset_enabled_flag) { + u(1, vslice_field(slice_sao_luma_flag)); + if (!vseq->seq_fields.bits.separate_colour_plane_flag && + vseq->seq_fields.bits.chroma_format_idc != 0) { + u(1, vslice_field(slice_sao_chroma_flag)); + } + } + + if (vslice->slice_type == P_SLICE || vslice->slice_type == B_SLICE) { + u(1, vslice_field(num_ref_idx_active_override_flag)); + if (vslice->slice_fields.bits.num_ref_idx_active_override_flag) { + ue(vslice_var(num_ref_idx_l0_active_minus1)); + if (vslice->slice_type == B_SLICE) { + ue(vslice_var(num_ref_idx_l1_active_minus1)); + } + } + + if (mseq->lists_modification_present_flag) { + av_assert0(0); + // ref_pic_lists_modification() + } + if (vslice->slice_type == B_SLICE) { + u(1, vslice_field(mvd_l1_zero_flag)); + } + if (mseq->cabac_init_present_flag) { + u(1, vslice_field(cabac_init_flag)); + } + if (vslice->slice_fields.bits.slice_temporal_mvp_enabled_flag) { + if (vslice->slice_type == B_SLICE) + u(1, vslice_field(collocated_from_l0_flag)); + ue(vpic->collocated_ref_pic_index, collocated_ref_idx); + } + if ((vpic->pic_fields.bits.weighted_pred_flag && + vslice->slice_type == P_SLICE) || + (vpic->pic_fields.bits.weighted_bipred_flag && + vslice->slice_type == B_SLICE)) { + av_assert0(0); + // pred_weight_table() + } + ue(5 - vslice->max_num_merge_cand, five_minus_max_num_merge_cand); + } + + se(vslice_var(slice_qp_delta)); + if (mseq->pps_slice_chroma_qp_offsets_present_flag) { + se(vslice_var(slice_cb_qp_offset)); + se(vslice_var(slice_cr_qp_offset)); + } + if (mseq->pps_slice_chroma_offset_list_enabled_flag) { + u(1, 0, cu_chroma_qp_offset_enabled_flag); + } + if (mseq->deblocking_filter_override_enabled_flag) { + u(1, mslice_var(deblocking_filter_override_flag)); + } + if (mslice->deblocking_filter_override_flag) { + u(1, vslice_field(slice_deblocking_filter_disabled_flag)); + if (!vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag) { + se(vslice_var(slice_beta_offset_div2)); + se(vslice_var(slice_tc_offset_div2)); + } + } + if (vpic->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag && + (vslice->slice_fields.bits.slice_sao_luma_flag || + vslice->slice_fields.bits.slice_sao_chroma_flag || + vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag)) { + u(1, vslice_field(slice_loop_filter_across_slices_enabled_flag)); + } + } + + if (vpic->pic_fields.bits.tiles_enabled_flag || + vpic->pic_fields.bits.entropy_coding_sync_enabled_flag) { + // num_entry_point_offsets + } + + if (0) { + // slice_segment_header_extension_length + } + } + + u(1, 1, alignment_bit_equal_to_one); + while (put_bits_count(pbc) & 7) + u(1, 0, alignment_bit_equal_to_zero); +} + +static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + PutBitContext pbc; + char tmp[256]; + int err; + size_t nal_len, bit_len, bit_pos, next_len; + + bit_len = *data_len; + bit_pos = 0; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h265_write_vps(&pbc, ctx); + nal_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + next_len = bit_len - bit_pos; + err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, + &next_len, + tmp, nal_len); + if (err < 0) + return err; + bit_pos += next_len; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h265_write_sps(&pbc, ctx); + nal_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + next_len = bit_len - bit_pos; + err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, + &next_len, + tmp, nal_len); + if (err < 0) + return err; + bit_pos += next_len; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h265_write_pps(&pbc, ctx); + nal_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + next_len = bit_len - bit_pos; + err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, + &next_len, + tmp, nal_len); + if (err < 0) + return err; + bit_pos += next_len; + + *data_len = bit_pos; + return 0; +} + +static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + PutBitContext pbc; + char tmp[256]; + size_t header_len; + + init_put_bits(&pbc, tmp, sizeof(tmp)); + vaapi_encode_h265_write_slice_header2(&pbc, ctx, pic, slice); + header_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, + tmp, header_len); +} + +static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + int i; + + { + // general_profile_space == 0. + vseq->general_profile_idc = 1; // Main profile (ctx->codec_profile?) + vseq->general_tier_flag = 0; + + vseq->general_level_idc = avctx->level * 3; + + vseq->intra_period = 0; + vseq->intra_idr_period = 0; + vseq->ip_period = 0; + + vseq->pic_width_in_luma_samples = ctx->aligned_width; + vseq->pic_height_in_luma_samples = ctx->aligned_height; + + vseq->seq_fields.bits.chroma_format_idc = 1; // 4:2:0. + vseq->seq_fields.bits.separate_colour_plane_flag = 0; + vseq->seq_fields.bits.bit_depth_luma_minus8 = 0; // 8-bit luma. + vseq->seq_fields.bits.bit_depth_chroma_minus8 = 0; // 8-bit chroma. + // Other misc flags all zero. + + // These have to come from the capabilities of the encoder. We have + // no way to query it, so just hardcode ones which worked for me... + // CTB size from 8x8 to 32x32. + vseq->log2_min_luma_coding_block_size_minus3 = 0; + vseq->log2_diff_max_min_luma_coding_block_size = 2; + // Transform size from 4x4 to 32x32. + vseq->log2_min_transform_block_size_minus2 = 0; + vseq->log2_diff_max_min_transform_block_size = 3; + // Full transform hierarchy allowed (2-5). + vseq->max_transform_hierarchy_depth_inter = 3; + vseq->max_transform_hierarchy_depth_intra = 3; + + vseq->vui_parameters_present_flag = 0; + + vseq->bits_per_second = avctx->bit_rate; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + vseq->vui_num_units_in_tick = avctx->framerate.num; + vseq->vui_time_scale = avctx->framerate.den; + } else { + vseq->vui_num_units_in_tick = avctx->time_base.num; + vseq->vui_time_scale = avctx->time_base.den; + } + + vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1); + vseq->intra_idr_period = vseq->intra_period; + vseq->ip_period = ctx->b_per_p + 1; + } + + { + vpic->decoded_curr_pic.picture_id = VA_INVALID_ID; + vpic->decoded_curr_pic.flags = VA_PICTURE_HEVC_INVALID; + + for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { + vpic->reference_frames[i].picture_id = VA_INVALID_ID; + vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; + } + + vpic->collocated_ref_pic_index = 0xff; + + vpic->last_picture = 0; + + vpic->pic_init_qp = priv->fixed_qp_idr; + + vpic->diff_cu_qp_delta_depth = 0; + vpic->pps_cb_qp_offset = 0; + vpic->pps_cr_qp_offset = 0; + + // tiles_enabled_flag == 0, so ignore num_tile_(rows|columns)_minus1. + + vpic->log2_parallel_merge_level_minus2 = 0; + + // No limit on size. + vpic->ctu_max_bitsize_allowed = 0; + + vpic->num_ref_idx_l0_default_active_minus1 = 0; + vpic->num_ref_idx_l1_default_active_minus1 = 0; + + vpic->slice_pic_parameter_set_id = 0; + + vpic->pic_fields.bits.screen_content_flag = 0; + vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0; + + // Per-CU QP changes are required for non-constant-QP modes. + vpic->pic_fields.bits.cu_qp_delta_enabled_flag = + ctx->va_rc_mode != VA_RC_CQP; + } + + { + mseq->video_parameter_set_id = 5; + mseq->seq_parameter_set_id = 5; + + mseq->vps_max_layers_minus1 = 0; + mseq->vps_max_sub_layers_minus1 = 0; + mseq->vps_temporal_id_nesting_flag = 1; + mseq->sps_max_sub_layers_minus1 = 0; + mseq->sps_temporal_id_nesting_flag = 1; + + for (i = 0; i < 32; i++) { + mseq->general_profile_compatibility_flag[i] = + (i == vseq->general_profile_idc); + } + + mseq->general_progressive_source_flag = 1; + mseq->general_interlaced_source_flag = 0; + mseq->general_non_packed_constraint_flag = 0; + mseq->general_frame_only_constraint_flag = 1; + mseq->general_inbld_flag = 0; + + mseq->log2_max_pic_order_cnt_lsb_minus4 = 8; + mseq->vps_sub_layer_ordering_info_present_flag = 0; + mseq->vps_max_dec_pic_buffering_minus1[0] = 1; + mseq->vps_max_num_reorder_pics[0] = ctx->b_per_p; + mseq->vps_max_latency_increase_plus1[0] = 0; + mseq->sps_sub_layer_ordering_info_present_flag = 0; + mseq->sps_max_dec_pic_buffering_minus1[0] = 1; + mseq->sps_max_num_reorder_pics[0] = ctx->b_per_p; + mseq->sps_max_latency_increase_plus1[0] = 0; + + mseq->vps_timing_info_present_flag = 1; + mseq->vps_num_units_in_tick = avctx->time_base.num; + mseq->vps_time_scale = avctx->time_base.den; + mseq->vps_poc_proportional_to_timing_flag = 1; + mseq->vps_num_ticks_poc_diff_minus1 = 0; + + if (ctx->input_width != ctx->aligned_width || + ctx->input_height != ctx->aligned_height) { + mseq->conformance_window_flag = 1; + mseq->conf_win_left_offset = 0; + mseq->conf_win_right_offset = + (ctx->aligned_width - ctx->input_width) / 2; + mseq->conf_win_top_offset = 0; + mseq->conf_win_bottom_offset = + (ctx->aligned_height - ctx->input_height) / 2; + } else { + mseq->conformance_window_flag = 0; + } + + mseq->num_short_term_ref_pic_sets = 0; + // STRPSs should ideally be here rather than repeated in each slice. + + mseq->vui_parameters_present_flag = 1; + if (avctx->sample_aspect_ratio.num != 0) { + mseq->aspect_ratio_info_present_flag = 1; + if (avctx->sample_aspect_ratio.num == + avctx->sample_aspect_ratio.den) { + mseq->aspect_ratio_idc = 1; + } else { + mseq->aspect_ratio_idc = 255; // Extended SAR. + mseq->sar_width = avctx->sample_aspect_ratio.num; + mseq->sar_height = avctx->sample_aspect_ratio.den; + } + } + if (1) { + // Should this be conditional on some of these being set? + mseq->video_signal_type_present_flag = 1; + mseq->video_format = 5; // Unspecified. + mseq->video_full_range_flag = 0; + mseq->colour_description_present_flag = 1; + mseq->colour_primaries = avctx->color_primaries; + mseq->transfer_characteristics = avctx->color_trc; + mseq->matrix_coeffs = avctx->colorspace; + } + } + + return 0; +} + +static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + int i; + + if (pic->type == PICTURE_TYPE_IDR) { + av_assert0(pic->display_order == pic->encode_order); + priv->last_idr_frame = pic->display_order; + } else { + av_assert0(pic->encode_order > priv->last_idr_frame); + // Display order need not be if we have RA[SD]L pictures, though. + } + + vpic->decoded_curr_pic.picture_id = pic->recon_surface; + vpic->decoded_curr_pic.pic_order_cnt = + pic->display_order - priv->last_idr_frame; + vpic->decoded_curr_pic.flags = 0; + + for (i = 0; i < pic->nb_refs; i++) { + VAAPIEncodePicture *ref = pic->refs[i]; + av_assert0(ref); + vpic->reference_frames[i].picture_id = ref->recon_surface; + vpic->reference_frames[i].pic_order_cnt = + ref->display_order - priv->last_idr_frame; + vpic->reference_frames[i].flags = + (ref->display_order < pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | + (ref->display_order > pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0); + } + for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { + vpic->reference_frames[i].picture_id = VA_INVALID_ID; + vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; + } + + vpic->coded_buf = pic->output_buffer; + + switch (pic->type) { + case PICTURE_TYPE_IDR: + vpic->nal_unit_type = NAL_IDR_W_RADL; + vpic->pic_fields.bits.idr_pic_flag = 1; + vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.reference_pic_flag = 1; + break; + case PICTURE_TYPE_I: + vpic->nal_unit_type = NAL_TRAIL_R; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.reference_pic_flag = 1; + break; + case PICTURE_TYPE_P: + vpic->nal_unit_type = NAL_TRAIL_R; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 2; + vpic->pic_fields.bits.reference_pic_flag = 1; + break; + case PICTURE_TYPE_B: + vpic->nal_unit_type = NAL_TRAIL_R; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 3; + vpic->pic_fields.bits.reference_pic_flag = 0; + break; + default: + av_assert0(0 && "invalid picture type"); + } + + pic->nb_slices = 1; + + return 0; +} + +static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265Slice *pslice; + VAAPIEncodeH265MiscSliceParams *mslice; + int i; + + slice->priv_data = av_mallocz(sizeof(*pslice)); + if (!slice->priv_data) + return AVERROR(ENOMEM); + pslice = slice->priv_data; + mslice = &pslice->misc_slice_params; + + // Currently we only support one slice per frame. + vslice->slice_segment_address = 0; + vslice->num_ctu_in_slice = priv->ctu_width * priv->ctu_height; + + switch (pic->type) { + case PICTURE_TYPE_IDR: + case PICTURE_TYPE_I: + vslice->slice_type = I_SLICE; + break; + case PICTURE_TYPE_P: + vslice->slice_type = P_SLICE; + break; + case PICTURE_TYPE_B: + vslice->slice_type = B_SLICE; + break; + default: + av_assert0(0 && "invalid picture type"); + } + + vslice->slice_pic_parameter_set_id = vpic->slice_pic_parameter_set_id; + + pslice->pic_order_cnt = pic->display_order - priv->last_idr_frame; + + for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { + vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID; + vslice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; + vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID; + vslice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; + } + + av_assert0(pic->nb_refs <= 2); + if (pic->nb_refs >= 1) { + // Backward reference for P- or B-frame. + av_assert0(pic->type == PICTURE_TYPE_P || + pic->type == PICTURE_TYPE_B); + + vslice->num_ref_idx_l0_active_minus1 = 0; + vslice->ref_pic_list0[0] = vpic->reference_frames[0]; + } + if (pic->nb_refs >= 2) { + // Forward reference for B-frame. + av_assert0(pic->type == PICTURE_TYPE_B); + + vslice->num_ref_idx_l1_active_minus1 = 0; + vslice->ref_pic_list1[0] = vpic->reference_frames[1]; + } + + vslice->max_num_merge_cand = 5; + + if (pic->type == PICTURE_TYPE_B) + vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; + else if (pic->type == PICTURE_TYPE_P) + vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; + else + vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; + + vslice->slice_fields.bits.last_slice_of_pic_flag = 1; + + mslice->first_slice_segment_in_pic_flag = 1; + + if (pic->type == PICTURE_TYPE_IDR) { + // No reference pictures. + } else if (0) { + mslice->short_term_ref_pic_set_sps_flag = 1; + mslice->short_term_ref_pic_idx = 0; + } else { + VAAPIEncodePicture *st; + int used; + + mslice->short_term_ref_pic_set_sps_flag = 0; + mslice->st_ref_pic_set.inter_ref_pic_set_prediction_flag = 0; + + for (st = ctx->pic_start; st; st = st->next) { + if (st->encode_order >= pic->encode_order) { + // Not yet in DPB. + continue; + } + used = 0; + for (i = 0; i < pic->nb_refs; i++) { + if (pic->refs[i] == st) + used = 1; + } + if (!used) { + // Currently true, but need not be. + continue; + } + // This only works for one instance of each (delta_poc_sN_minus1 + // is relative to the previous frame in the list, not relative to + // the current frame directly). + if (st->display_order < pic->display_order) { + i = mslice->st_ref_pic_set.num_negative_pics; + mslice->st_ref_pic_set.delta_poc_s0_minus1[i] = + pic->display_order - st->display_order - 1; + mslice->st_ref_pic_set.used_by_curr_pic_s0_flag[i] = used; + ++mslice->st_ref_pic_set.num_negative_pics; + } else { + i = mslice->st_ref_pic_set.num_positive_pics; + mslice->st_ref_pic_set.delta_poc_s1_minus1[i] = + st->display_order - pic->display_order - 1; + mslice->st_ref_pic_set.used_by_curr_pic_s1_flag[i] = used; + ++mslice->st_ref_pic_set.num_positive_pics; + } + } + } + + return 0; +} + +static av_cold int vaapi_encode_h265_init_constant_bitrate(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + int hrd_buffer_size; + int hrd_initial_buffer_fullness; + + if (avctx->rc_buffer_size) + hrd_buffer_size = avctx->rc_buffer_size; + else + hrd_buffer_size = avctx->bit_rate; + if (avctx->rc_initial_buffer_occupancy) + hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy; + else + hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4; + + priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl; + priv->rc_params.rc = (VAEncMiscParameterRateControl) { + .bits_per_second = avctx->bit_rate, + .target_percentage = 66, + .window_size = 1000, + .initial_qp = (avctx->qmax >= 0 ? avctx->qmax : 40), + .min_qp = (avctx->qmin >= 0 ? avctx->qmin : 20), + .basic_unit_size = 0, + }; + ctx->global_params[ctx->nb_global_params] = + &priv->rc_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(priv->rc_params); + + priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD; + priv->hrd_params.hrd = (VAEncMiscParameterHRD) { + .initial_buffer_fullness = hrd_initial_buffer_fullness, + .buffer_size = hrd_buffer_size, + }; + ctx->global_params[ctx->nb_global_params] = + &priv->hrd_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(priv->hrd_params); + + // These still need to be set for pic_init_qp/slice_qp_delta. + priv->fixed_qp_idr = 30; + priv->fixed_qp_p = 30; + priv->fixed_qp_b = 30; + + av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n", + avctx->bit_rate); + return 0; +} + +static av_cold int vaapi_encode_h265_init_fixed_qp(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265Options *opt = ctx->codec_options; + + priv->fixed_qp_p = opt->qp; + if (avctx->i_quant_factor > 0.0) + priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor + + avctx->i_quant_offset) + 0.5); + else + priv->fixed_qp_idr = priv->fixed_qp_p; + if (avctx->b_quant_factor > 0.0) + priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor + + avctx->b_quant_offset) + 0.5); + else + priv->fixed_qp_b = priv->fixed_qp_p; + + av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " + "%d / %d / %d for IDR- / P- / B-frames.\n", + priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); + return 0; +} + +static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx) +{ + static const VAConfigAttrib default_config_attributes[] = { + { .type = VAConfigAttribRTFormat, + .value = VA_RT_FORMAT_YUV420 }, + { .type = VAConfigAttribEncPackedHeaders, + .value = (VA_ENC_PACKED_HEADER_SEQUENCE | + VA_ENC_PACKED_HEADER_SLICE) }, + }; + + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + int i, err; + + switch (avctx->profile) { + case FF_PROFILE_HEVC_MAIN: + case FF_PROFILE_UNKNOWN: + ctx->va_profile = VAProfileHEVCMain; + break; + case FF_PROFILE_HEVC_MAIN_10: + av_log(avctx, AV_LOG_ERROR, "H.265 main 10-bit profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown H.265 profile %d.\n", + avctx->profile); + return AVERROR(EINVAL); + } + ctx->va_entrypoint = VAEntrypointEncSlice; + + ctx->input_width = avctx->width; + ctx->input_height = avctx->height; + ctx->aligned_width = FFALIGN(ctx->input_width, 16); + ctx->aligned_height = FFALIGN(ctx->input_height, 16); + priv->ctu_width = FFALIGN(ctx->aligned_width, 32) / 32; + priv->ctu_height = FFALIGN(ctx->aligned_height, 32) / 32; + + av_log(avctx, AV_LOG_VERBOSE, "Input %ux%u -> Aligned %ux%u -> CTU %ux%u.\n", + ctx->input_width, ctx->input_height, ctx->aligned_width, + ctx->aligned_height, priv->ctu_width, priv->ctu_height); + + for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { + ctx->config_attributes[ctx->nb_config_attributes++] = + default_config_attributes[i]; + } + + if (avctx->bit_rate > 0) { + ctx->va_rc_mode = VA_RC_CBR; + err = vaapi_encode_h265_init_constant_bitrate(avctx); + } else { + ctx->va_rc_mode = VA_RC_CQP; + err = vaapi_encode_h265_init_fixed_qp(avctx); + } + if (err < 0) + return err; + + ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) { + .type = VAConfigAttribRateControl, + .value = ctx->va_rc_mode, + }; + + ctx->nb_recon_frames = 20; + + return 0; +} + +static VAAPIEncodeType vaapi_encode_type_h265 = { + .priv_data_size = sizeof(VAAPIEncodeH265Context), + + .init = &vaapi_encode_h265_init_internal, + + .sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC), + .init_sequence_params = &vaapi_encode_h265_init_sequence_params, + + .picture_params_size = sizeof(VAEncPictureParameterBufferHEVC), + .init_picture_params = &vaapi_encode_h265_init_picture_params, + + .slice_params_size = sizeof(VAEncSliceParameterBufferHEVC), + .init_slice_params = &vaapi_encode_h265_init_slice_params, + + .sequence_header_type = VAEncPackedHeaderSequence, + .write_sequence_header = &vaapi_encode_h265_write_sequence_header, + + .slice_header_type = VAEncPackedHeaderHEVC_Slice, + .write_slice_header = &vaapi_encode_h265_write_slice_header, +}; + +static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) +{ + return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h265); +} + +#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ + offsetof(VAAPIEncodeH265Options, x)) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +static const AVOption vaapi_encode_h265_options[] = { + { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", + OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS }, + { NULL }, +}; + +static const AVCodecDefault vaapi_encode_h265_defaults[] = { + { "profile", "1" }, + { "level", "51" }, + { "b", "0" }, + { "bf", "2" }, + { "g", "120" }, + { "i_qfactor", "1.0" }, + { "i_qoffset", "0.0" }, + { "b_qfactor", "1.2" }, + { "b_qoffset", "0.0" }, + { NULL }, +}; + +static const AVClass vaapi_encode_h265_class = { + .class_name = "h265_vaapi", + .item_name = av_default_item_name, + .option = vaapi_encode_h265_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_hevc_vaapi_encoder = { + .name = "hevc_vaapi", + .long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .priv_data_size = (sizeof(VAAPIEncodeContext) + + sizeof(VAAPIEncodeH265Options)), + .init = &vaapi_encode_h265_init, + .encode2 = &ff_vaapi_encode2, + .close = &ff_vaapi_encode_close, + .priv_class = &vaapi_encode_h265_class, + .capabilities = AV_CODEC_CAP_DELAY, + .defaults = vaapi_encode_h265_defaults, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE, + }, +}; diff --git a/libavcodec/vaapi_encode_h26x.c b/libavcodec/vaapi_encode_h26x.c new file mode 100644 index 0000000..bf9eb92 --- /dev/null +++ b/libavcodec/vaapi_encode_h26x.c @@ -0,0 +1,68 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "vaapi_encode_h26x.h" + +int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_bit_len, + uint8_t *src, size_t src_bit_len) +{ + size_t dp, sp; + int zero_run = 0; + size_t dst_len = *dst_bit_len / 8; + size_t src_len = (src_bit_len + 7) / 8; + int trailing_zeroes = src_len * 8 - src_bit_len; + + if (dst_len < src_len + 4) { + // Definitely doesn't fit. + goto fail; + } + + // Start code. + dst[0] = dst[1] = dst[2] = 0; + dst[3] = 1; + dp = 4; + + for (sp = 0; sp < src_len; sp++) { + if (dp >= dst_len) + goto fail; + if (zero_run < 2) { + if (src[sp] == 0) + ++zero_run; + else + zero_run = 0; + } else { + if ((src[sp] & ~3) == 0) { + // emulation_prevention_three_byte + dst[dp++] = 3; + if (dp >= dst_len) + goto fail; + } + zero_run = src[sp] == 0; + } + dst[dp++] = src[sp]; + } + + *dst_bit_len = 8 * dp - trailing_zeroes; + return 0; + +fail: + *dst_bit_len = 0; + return AVERROR(ENOSPC); +} diff --git a/libavcodec/vaapi_encode_h26x.h b/libavcodec/vaapi_encode_h26x.h new file mode 100644 index 0000000..d6db69a --- /dev/null +++ b/libavcodec/vaapi_encode_h26x.h @@ -0,0 +1,45 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VAAPI_ENCODE_H26X_H +#define AVCODEC_VAAPI_ENCODE_H26X_H + +#include +#include + +#include "golomb.h" +#include "put_bits.h" + + +// Debug code may be interested in the name of the syntax element being +// for tracing purposes. Here, it is just discarded. + +#define write_u(pbc, width, value, name) put_bits(pbc, width, value) +#define write_ue(pbc, value, name) set_ue_golomb(pbc, value) +#define write_se(pbc, value, name) set_se_golomb(pbc, value) + +#define u(width, ...) write_u(pbc, width, __VA_ARGS__) +#define ue(...) write_ue(pbc, __VA_ARGS__) +#define se(...) write_se(pbc, __VA_ARGS__) + + +// Copy from src to dst, applying emulation prevention. +int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_len, + uint8_t *src, size_t src_len); + +#endif /* AVCODEC_VAAPI_ENCODE_H26X_H */ diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c new file mode 100644 index 0000000..e3bf191 --- /dev/null +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -0,0 +1,422 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "internal.h" +#include "jpegtables.h" +#include "mjpeg.h" +#include "put_bits.h" +#include "vaapi_encode.h" + + +// Standard JPEG quantisation tables, in zigzag order. +static const unsigned char vaapi_encode_mjpeg_quant_luminance[64] = { + 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, +}; +static const unsigned char vaapi_encode_mjpeg_quant_chrominance[64] = { + 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, +}; + +typedef struct VAAPIEncodeMJPEGContext { + int quality; + int component_subsample_h[3]; + int component_subsample_v[3]; + + VAQMatrixBufferJPEG quant_tables; + VAHuffmanTableBufferJPEGBaseline huffman_tables; +} VAAPIEncodeMJPEGContext; + +static av_cold void vaapi_encode_mjpeg_copy_huffman(unsigned char *dst_lengths, + unsigned char *dst_values, + const unsigned char *src_lengths, + const unsigned char *src_values) +{ + int i, mt; + + ++src_lengths; + + mt = 0; + for (i = 0; i < 16; i++) + mt += (dst_lengths[i] = src_lengths[i]); + + for (i = 0; i < mt; i++) + dst_values[i] = src_values[i]; +} + +static av_cold void vaapi_encode_mjpeg_init_tables(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMJPEGContext *priv = ctx->priv_data; + VAQMatrixBufferJPEG *quant = &priv->quant_tables; + VAHuffmanTableBufferJPEGBaseline *huff = &priv->huffman_tables; + int i; + + quant->load_lum_quantiser_matrix = 1; + quant->load_chroma_quantiser_matrix = 1; + + for (i = 0; i < 64; i++) { + quant->lum_quantiser_matrix[i] = + vaapi_encode_mjpeg_quant_luminance[i]; + quant->chroma_quantiser_matrix[i] = + vaapi_encode_mjpeg_quant_chrominance[i]; + } + + huff->load_huffman_table[0] = 1; + vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_dc_codes, + huff->huffman_table[0].dc_values, + avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc); + vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_ac_codes, + huff->huffman_table[0].ac_values, + avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance); + memset(huff->huffman_table[0].pad, 0, sizeof(huff->huffman_table[0].pad)); + + huff->load_huffman_table[1] = 1; + vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_dc_codes, + huff->huffman_table[1].dc_values, + avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc); + vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_ac_codes, + huff->huffman_table[1].ac_values, + avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance); + memset(huff->huffman_table[1].pad, 0, sizeof(huff->huffman_table[1].pad)); +} + +static void vaapi_encode_mjpeg_write_marker(PutBitContext *pbc, int marker) +{ + put_bits(pbc, 8, 0xff); + put_bits(pbc, 8, marker); +} + +static int vaapi_encode_mjpeg_write_image_header(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params; + VAAPIEncodeMJPEGContext *priv = ctx->priv_data; + PutBitContext pbc; + int t, i, quant_scale; + + init_put_bits(&pbc, data, *data_len); + + vaapi_encode_mjpeg_write_marker(&pbc, SOI); + + // Quantisation table coefficients are scaled for quality by the driver, + // so we also need to do it ourselves here so that headers match. + if (priv->quality < 50) + quant_scale = 5000 / priv->quality; + else + quant_scale = 200 - 2 * priv->quality; + + for (t = 0; t < 2; t++) { + int q; + + vaapi_encode_mjpeg_write_marker(&pbc, DQT); + + put_bits(&pbc, 16, 3 + 64); // Lq + put_bits(&pbc, 4, 0); // Pq + put_bits(&pbc, 4, t); // Tq + + for (i = 0; i < 64; i++) { + q = i[t ? priv->quant_tables.chroma_quantiser_matrix + : priv->quant_tables.lum_quantiser_matrix]; + q = (q * quant_scale) / 100; + if (q < 1) q = 1; + if (q > 255) q = 255; + put_bits(&pbc, 8, q); + } + } + + vaapi_encode_mjpeg_write_marker(&pbc, SOF0); + + put_bits(&pbc, 16, 8 + 3 * vpic->num_components); // Lf + put_bits(&pbc, 8, vpic->sample_bit_depth); // P + put_bits(&pbc, 16, vpic->picture_height); // Y + put_bits(&pbc, 16, vpic->picture_width); // X + put_bits(&pbc, 8, vpic->num_components); // Nf + + for (i = 0; i < vpic->num_components; i++) { + put_bits(&pbc, 8, vpic->component_id[i]); // Ci + put_bits(&pbc, 4, priv->component_subsample_h[i]); // Hi + put_bits(&pbc, 4, priv->component_subsample_v[i]); // Vi + put_bits(&pbc, 8, vpic->quantiser_table_selector[i]); // Tqi + } + + for (t = 0; t < 4; t++) { + int mt; + unsigned char *lengths, *values; + + vaapi_encode_mjpeg_write_marker(&pbc, DHT); + + if ((t & 1) == 0) { + lengths = priv->huffman_tables.huffman_table[t / 2].num_dc_codes; + values = priv->huffman_tables.huffman_table[t / 2].dc_values; + } else { + lengths = priv->huffman_tables.huffman_table[t / 2].num_ac_codes; + values = priv->huffman_tables.huffman_table[t / 2].ac_values; + } + + mt = 0; + for (i = 0; i < 16; i++) + mt += lengths[i]; + + put_bits(&pbc, 16, 2 + 17 + mt); // Lh + put_bits(&pbc, 4, t & 1); // Tc + put_bits(&pbc, 4, t / 2); // Th + + for (i = 0; i < 16; i++) + put_bits(&pbc, 8, lengths[i]); + for (i = 0; i < mt; i++) + put_bits(&pbc, 8, values[i]); + } + + vaapi_encode_mjpeg_write_marker(&pbc, SOS); + + av_assert0(vpic->num_components == vslice->num_components); + + put_bits(&pbc, 16, 6 + 2 * vslice->num_components); // Ls + put_bits(&pbc, 8, vslice->num_components); // Ns + + for (i = 0; i < vslice->num_components; i++) { + put_bits(&pbc, 8, vslice->components[i].component_selector); // Csj + put_bits(&pbc, 4, vslice->components[i].dc_table_selector); // Tdj + put_bits(&pbc, 4, vslice->components[i].ac_table_selector); // Taj + } + + put_bits(&pbc, 8, 0); // Ss + put_bits(&pbc, 8, 63); // Se + put_bits(&pbc, 4, 0); // Ah + put_bits(&pbc, 4, 0); // Al + + *data_len = put_bits_count(&pbc); + flush_put_bits(&pbc); + + return 0; +} + +static int vaapi_encode_mjpeg_write_extra_buffer(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + int index, int *type, + char *data, size_t *data_len) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMJPEGContext *priv = ctx->priv_data; + + if (index == 0) { + // Write quantisation tables. + if (*data_len < sizeof(priv->quant_tables)) + return AVERROR(EINVAL); + *type = VAQMatrixBufferType; + memcpy(data, &priv->quant_tables, + *data_len = sizeof(priv->quant_tables)); + + } else if (index == 1) { + // Write huffman tables. + if (*data_len < sizeof(priv->huffman_tables)) + return AVERROR(EINVAL); + *type = VAHuffmanTableBufferType; + memcpy(data, &priv->huffman_tables, + *data_len = sizeof(priv->huffman_tables)); + + } else { + return AVERROR_EOF; + } + return 0; +} + +static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params; + VAAPIEncodeMJPEGContext *priv = ctx->priv_data; + + vpic->reconstructed_picture = pic->recon_surface; + vpic->coded_buf = pic->output_buffer; + + vpic->picture_width = ctx->input_width; + vpic->picture_height = ctx->input_height; + + vpic->pic_flags.bits.profile = 0; + vpic->pic_flags.bits.progressive = 0; + vpic->pic_flags.bits.huffman = 1; + vpic->pic_flags.bits.interleaved = 0; + vpic->pic_flags.bits.differential = 0; + + vpic->sample_bit_depth = 8; + vpic->num_scan = 1; + + vpic->num_components = 3; + + vpic->component_id[0] = 1; + vpic->component_id[1] = 2; + vpic->component_id[2] = 3; + + priv->component_subsample_h[0] = 2; + priv->component_subsample_v[0] = 2; + priv->component_subsample_h[1] = 1; + priv->component_subsample_v[1] = 1; + priv->component_subsample_h[2] = 1; + priv->component_subsample_v[2] = 1; + + vpic->quantiser_table_selector[0] = 0; + vpic->quantiser_table_selector[1] = 1; + vpic->quantiser_table_selector[2] = 1; + + vpic->quality = priv->quality; + + pic->nb_slices = 1; + + return 0; +} + +static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic, + VAAPIEncodeSlice *slice) +{ + VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params; + int i; + + vslice->restart_interval = 0; + + vslice->num_components = vpic->num_components; + for (i = 0; i < vslice->num_components; i++) { + vslice->components[i].component_selector = i + 1; + vslice->components[i].dc_table_selector = (i > 0); + vslice->components[i].ac_table_selector = (i > 0); + } + + return 0; +} + +static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx) +{ + static const VAConfigAttrib default_config_attributes[] = { + { .type = VAConfigAttribRTFormat, + .value = VA_RT_FORMAT_YUV420 }, + { .type = VAConfigAttribEncPackedHeaders, + .value = VA_ENC_PACKED_HEADER_SEQUENCE }, + }; + + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMJPEGContext *priv = ctx->priv_data; + int i; + + ctx->va_profile = VAProfileJPEGBaseline; + ctx->va_entrypoint = VAEntrypointEncPicture; + + ctx->input_width = avctx->width; + ctx->input_height = avctx->height; + ctx->aligned_width = FFALIGN(ctx->input_width, 8); + ctx->aligned_height = FFALIGN(ctx->input_height, 8); + + for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { + ctx->config_attributes[ctx->nb_config_attributes++] = + default_config_attributes[i]; + } + + priv->quality = avctx->global_quality; + if (priv->quality < 1 || priv->quality > 100) { + av_log(avctx, AV_LOG_ERROR, "Invalid quality value %d " + "(must be 1-100).\n", priv->quality); + return AVERROR(EINVAL); + } + + vaapi_encode_mjpeg_init_tables(avctx); + + return 0; +} + +static VAAPIEncodeType vaapi_encode_type_mjpeg = { + .priv_data_size = sizeof(VAAPIEncodeMJPEGContext), + + .init = &vaapi_encode_mjpeg_init_internal, + + .picture_params_size = sizeof(VAEncPictureParameterBufferJPEG), + .init_picture_params = &vaapi_encode_mjpeg_init_picture_params, + + .slice_params_size = sizeof(VAEncSliceParameterBufferJPEG), + .init_slice_params = &vaapi_encode_mjpeg_init_slice_params, + + .slice_header_type = VAEncPackedHeaderRawData, + .write_slice_header = &vaapi_encode_mjpeg_write_image_header, + + .write_extra_buffer = &vaapi_encode_mjpeg_write_extra_buffer, +}; + +static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx) +{ + return ff_vaapi_encode_init(avctx, &vaapi_encode_type_mjpeg); +} + +static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = { + { "global_quality", "80" }, + { NULL }, +}; + +static const AVClass vaapi_encode_mjpeg_class = { + .class_name = "mjpeg_vaapi", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mjpeg_vaapi_encoder = { + .name = "mjpeg_vaapi", + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .priv_data_size = sizeof(VAAPIEncodeContext), + .init = &vaapi_encode_mjpeg_init, + .encode2 = &ff_vaapi_encode2, + .close = &ff_vaapi_encode_close, + .priv_class = &vaapi_encode_mjpeg_class, + .defaults = vaapi_encode_mjpeg_defaults, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE, + }, +}; diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index 651a50b..259287a 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -21,7 +21,8 @@ */ #include "vaapi_internal.h" -#include "h264.h" +#include "h264dec.h" +#include "h264_ps.h" #include "mpegutils.h" /** @@ -52,14 +53,14 @@ static void init_vaapi_pic(VAPictureH264 *va_pic) * supersedes pic's field type if nonzero. */ static void fill_vaapi_pic(VAPictureH264 *va_pic, - H264Picture *pic, + const H264Picture *pic, int pic_structure) { if (pic_structure == 0) pic_structure = pic->reference; pic_structure &= PICT_FRAME; /* PICT_TOP_FIELD|PICT_BOTTOM_FIELD */ - va_pic->picture_id = ff_vaapi_get_surface_id(&pic->f); + va_pic->picture_id = ff_vaapi_get_surface_id(pic->f); va_pic->frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; va_pic->flags = 0; @@ -90,7 +91,7 @@ typedef struct DPB { * available. The decoded picture buffer's size must be large enough * to receive the new VA API picture object. */ -static int dpb_add(DPB *dpb, H264Picture *pic) +static int dpb_add(DPB *dpb, const H264Picture *pic) { int i; @@ -99,7 +100,7 @@ static int dpb_add(DPB *dpb, H264Picture *pic) for (i = 0; i < dpb->size; i++) { VAPictureH264 * const va_pic = &dpb->va_pics[i]; - if (va_pic->picture_id == ff_vaapi_get_surface_id(&pic->f)) { + if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f)) { VAPictureH264 temp_va_pic; fill_vaapi_pic(&temp_va_pic, pic, 0); @@ -122,7 +123,7 @@ static int dpb_add(DPB *dpb, H264Picture *pic) /** Fill in VA API reference frames array. */ static int fill_vaapi_ReferenceFrames(VAPictureParameterBufferH264 *pic_param, - H264Context *h) + const H264Context *h) { DPB dpb; int i; @@ -134,13 +135,13 @@ static int fill_vaapi_ReferenceFrames(VAPictureParameterBufferH264 *pic_param, init_vaapi_pic(&dpb.va_pics[i]); for (i = 0; i < h->short_ref_count; i++) { - H264Picture * const pic = h->short_ref[i]; + const H264Picture *pic = h->short_ref[i]; if (pic && pic->reference && dpb_add(&dpb, pic) < 0) return -1; } for (i = 0; i < 16; i++) { - H264Picture * const pic = h->long_ref[i]; + const H264Picture *pic = h->long_ref[i]; if (pic && pic->reference && dpb_add(&dpb, pic) < 0) return -1; } @@ -156,13 +157,14 @@ static int fill_vaapi_ReferenceFrames(VAPictureParameterBufferH264 *pic_param, * @param[in] ref_count The number of reference pictures in ref_list */ static void fill_vaapi_RefPicList(VAPictureH264 RefPicList[32], - H264Picture *ref_list, + const H264Ref *ref_list, unsigned int ref_count) { unsigned int i, n = 0; for (i = 0; i < ref_count; i++) if (ref_list[i].reference) - fill_vaapi_pic(&RefPicList[n++], &ref_list[i], 0); + fill_vaapi_pic(&RefPicList[n++], ref_list[i].parent, + ref_list[i].reference); for (; n < 32; n++) init_vaapi_pic(&RefPicList[n]); @@ -183,7 +185,7 @@ static void fill_vaapi_RefPicList(VAPictureH264 RefPicList[32], * @param[out] chroma_weight VA API plain chroma weight table * @param[out] chroma_offset VA API plain chroma offset table */ -static void fill_vaapi_plain_pred_weight_table(H264Context *h, +static void fill_vaapi_plain_pred_weight_table(const H264Context *h, int list, unsigned char *luma_weight_flag, short luma_weight[32], @@ -192,27 +194,28 @@ static void fill_vaapi_plain_pred_weight_table(H264Context *h, short chroma_weight[32][2], short chroma_offset[32][2]) { + const H264SliceContext *sl = &h->slice_ctx[0]; unsigned int i, j; - *luma_weight_flag = h->luma_weight_flag[list]; - *chroma_weight_flag = h->chroma_weight_flag[list]; + *luma_weight_flag = sl->pwt.luma_weight_flag[list]; + *chroma_weight_flag = sl->pwt.chroma_weight_flag[list]; - for (i = 0; i < h->ref_count[list]; i++) { + for (i = 0; i < sl->ref_count[list]; i++) { /* VA API also wants the inferred (default) values, not only what is available in the bitstream (7.4.3.2). */ - if (h->luma_weight_flag[list]) { - luma_weight[i] = h->luma_weight[i][list][0]; - luma_offset[i] = h->luma_weight[i][list][1]; + if (sl->pwt.luma_weight_flag[list]) { + luma_weight[i] = sl->pwt.luma_weight[i][list][0]; + luma_offset[i] = sl->pwt.luma_weight[i][list][1]; } else { - luma_weight[i] = 1 << h->luma_log2_weight_denom; + luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom; luma_offset[i] = 0; } for (j = 0; j < 2; j++) { - if (h->chroma_weight_flag[list]) { - chroma_weight[i][j] = h->chroma_weight[i][list][j][0]; - chroma_offset[i][j] = h->chroma_weight[i][list][j][1]; + if (sl->pwt.chroma_weight_flag[list]) { + chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0]; + chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1]; } else { - chroma_weight[i][j] = 1 << h->chroma_log2_weight_denom; + chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom; chroma_offset[i][j] = 0; } } @@ -224,13 +227,13 @@ static int vaapi_h264_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { - H264Context * const h = avctx->priv_data; + const H264Context *h = avctx->priv_data; struct vaapi_context * const vactx = avctx->hwaccel_context; + const PPS *pps = h->ps.pps; + const SPS *sps = h->ps.sps; VAPictureParameterBufferH264 *pic_param; VAIQMatrixBufferH264 *iq_matrix; - av_dlog(avctx, "vaapi_h264_start_frame()\n"); - vactx->slice_param_size = sizeof(VASliceParameterBufferH264); /* Fill in VAPictureParameterBufferH264. */ @@ -242,48 +245,48 @@ static int vaapi_h264_start_frame(AVCodecContext *avctx, return -1; pic_param->picture_width_in_mbs_minus1 = h->mb_width - 1; pic_param->picture_height_in_mbs_minus1 = h->mb_height - 1; - pic_param->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; - pic_param->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; - pic_param->num_ref_frames = h->sps.ref_frame_count; + pic_param->bit_depth_luma_minus8 = sps->bit_depth_luma - 8; + pic_param->bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8; + pic_param->num_ref_frames = sps->ref_frame_count; pic_param->seq_fields.value = 0; /* reset all bits */ - pic_param->seq_fields.bits.chroma_format_idc = h->sps.chroma_format_idc; - pic_param->seq_fields.bits.residual_colour_transform_flag = h->sps.residual_color_transform_flag; /* XXX: only for 4:4:4 high profile? */ - pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag; - pic_param->seq_fields.bits.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; - pic_param->seq_fields.bits.mb_adaptive_frame_field_flag = h->sps.mb_aff; - pic_param->seq_fields.bits.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; - pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = h->sps.level_idc >= 31; /* A.3.3.2 */ - pic_param->seq_fields.bits.log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; - pic_param->seq_fields.bits.pic_order_cnt_type = h->sps.poc_type; - pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; - pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; - pic_param->num_slice_groups_minus1 = h->pps.slice_group_count - 1; - pic_param->slice_group_map_type = h->pps.mb_slice_group_map_type; + pic_param->seq_fields.bits.chroma_format_idc = sps->chroma_format_idc; + pic_param->seq_fields.bits.residual_colour_transform_flag = sps->residual_color_transform_flag; /* XXX: only for 4:4:4 high profile? */ + pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag; + pic_param->seq_fields.bits.frame_mbs_only_flag = sps->frame_mbs_only_flag; + pic_param->seq_fields.bits.mb_adaptive_frame_field_flag = sps->mb_aff; + pic_param->seq_fields.bits.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* A.3.3.2 */ + pic_param->seq_fields.bits.log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4; + pic_param->seq_fields.bits.pic_order_cnt_type = sps->poc_type; + pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4; + pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pic_param->num_slice_groups_minus1 = pps->slice_group_count - 1; + pic_param->slice_group_map_type = pps->mb_slice_group_map_type; pic_param->slice_group_change_rate_minus1 = 0; /* XXX: unimplemented in Libav */ - pic_param->pic_init_qp_minus26 = h->pps.init_qp - 26; - pic_param->pic_init_qs_minus26 = h->pps.init_qs - 26; - pic_param->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; - pic_param->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + pic_param->pic_init_qp_minus26 = pps->init_qp - 26; + pic_param->pic_init_qs_minus26 = pps->init_qs - 26; + pic_param->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; + pic_param->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; pic_param->pic_fields.value = 0; /* reset all bits */ - pic_param->pic_fields.bits.entropy_coding_mode_flag = h->pps.cabac; - pic_param->pic_fields.bits.weighted_pred_flag = h->pps.weighted_pred; - pic_param->pic_fields.bits.weighted_bipred_idc = h->pps.weighted_bipred_idc; - pic_param->pic_fields.bits.transform_8x8_mode_flag = h->pps.transform_8x8_mode; + pic_param->pic_fields.bits.entropy_coding_mode_flag = pps->cabac; + pic_param->pic_fields.bits.weighted_pred_flag = pps->weighted_pred; + pic_param->pic_fields.bits.weighted_bipred_idc = pps->weighted_bipred_idc; + pic_param->pic_fields.bits.transform_8x8_mode_flag = pps->transform_8x8_mode; pic_param->pic_fields.bits.field_pic_flag = h->picture_structure != PICT_FRAME; - pic_param->pic_fields.bits.constrained_intra_pred_flag = h->pps.constrained_intra_pred; - pic_param->pic_fields.bits.pic_order_present_flag = h->pps.pic_order_present; - pic_param->pic_fields.bits.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; - pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; + pic_param->pic_fields.bits.constrained_intra_pred_flag = pps->constrained_intra_pred; + pic_param->pic_fields.bits.pic_order_present_flag = pps->pic_order_present; + pic_param->pic_fields.bits.deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present; + pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present; pic_param->pic_fields.bits.reference_pic_flag = h->nal_ref_idc != 0; - pic_param->frame_num = h->frame_num; + pic_param->frame_num = h->poc.frame_num; /* Fill in VAIQMatrixBufferH264. */ iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferH264)); if (!iq_matrix) return -1; - memcpy(iq_matrix->ScalingList4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->ScalingList4x4)); - memcpy(iq_matrix->ScalingList8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->ScalingList8x8[0])); - memcpy(iq_matrix->ScalingList8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->ScalingList8x8[0])); + memcpy(iq_matrix->ScalingList4x4, pps->scaling_matrix4, sizeof(iq_matrix->ScalingList4x4)); + memcpy(iq_matrix->ScalingList8x8[0], pps->scaling_matrix8[0], sizeof(iq_matrix->ScalingList8x8[0])); + memcpy(iq_matrix->ScalingList8x8[1], pps->scaling_matrix8[3], sizeof(iq_matrix->ScalingList8x8[0])); return 0; } @@ -291,19 +294,19 @@ static int vaapi_h264_start_frame(AVCodecContext *avctx, static int vaapi_h264_end_frame(AVCodecContext *avctx) { struct vaapi_context * const vactx = avctx->hwaccel_context; - H264Context * const h = avctx->priv_data; + const H264Context *h = avctx->priv_data; + H264SliceContext *sl = &h->slice_ctx[0]; int ret; - av_dlog(avctx, "vaapi_h264_end_frame()\n"); ret = ff_vaapi_commit_slices(vactx); if (ret < 0) goto finish; - ret = ff_vaapi_render_picture(vactx, ff_vaapi_get_surface_id(&h->cur_pic_ptr->f)); + ret = ff_vaapi_render_picture(vactx, ff_vaapi_get_surface_id(h->cur_pic_ptr->f)); if (ret < 0) goto finish; - ff_h264_draw_horiz_band(h, 0, h->avctx->height); + ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height); finish: ff_vaapi_common_end_frame(avctx); @@ -315,32 +318,30 @@ static int vaapi_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { - H264Context * const h = avctx->priv_data; + const H264Context *h = avctx->priv_data; + const H264SliceContext *sl = &h->slice_ctx[0]; VASliceParameterBufferH264 *slice_param; - av_dlog(avctx, "vaapi_h264_decode_slice(): buffer %p, size %d\n", - buffer, size); - /* Fill in VASliceParameterBufferH264. */ slice_param = (VASliceParameterBufferH264 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); if (!slice_param) return -1; - slice_param->slice_data_bit_offset = get_bits_count(&h->gb) + 8; /* bit buffer started beyond nal_unit_type */ - slice_param->first_mb_in_slice = (h->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + h->mb_x; - slice_param->slice_type = ff_h264_get_slice_type(h); - slice_param->direct_spatial_mv_pred_flag = h->slice_type == AV_PICTURE_TYPE_B ? h->direct_spatial_mv_pred : 0; - slice_param->num_ref_idx_l0_active_minus1 = h->list_count > 0 ? h->ref_count[0] - 1 : 0; - slice_param->num_ref_idx_l1_active_minus1 = h->list_count > 1 ? h->ref_count[1] - 1 : 0; - slice_param->cabac_init_idc = h->cabac_init_idc; - slice_param->slice_qp_delta = h->qscale - h->pps.init_qp; - slice_param->disable_deblocking_filter_idc = h->deblocking_filter < 2 ? !h->deblocking_filter : h->deblocking_filter; - slice_param->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2; - slice_param->slice_beta_offset_div2 = h->slice_beta_offset / 2; - slice_param->luma_log2_weight_denom = h->luma_log2_weight_denom; - slice_param->chroma_log2_weight_denom = h->chroma_log2_weight_denom; - - fill_vaapi_RefPicList(slice_param->RefPicList0, h->ref_list[0], h->list_count > 0 ? h->ref_count[0] : 0); - fill_vaapi_RefPicList(slice_param->RefPicList1, h->ref_list[1], h->list_count > 1 ? h->ref_count[1] : 0); + slice_param->slice_data_bit_offset = get_bits_count(&sl->gb); + slice_param->first_mb_in_slice = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x; + slice_param->slice_type = ff_h264_get_slice_type(sl); + slice_param->direct_spatial_mv_pred_flag = sl->slice_type == AV_PICTURE_TYPE_B ? sl->direct_spatial_mv_pred : 0; + slice_param->num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0; + slice_param->num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0; + slice_param->cabac_init_idc = sl->cabac_init_idc; + slice_param->slice_qp_delta = sl->qscale - h->ps.pps->init_qp; + slice_param->disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter; + slice_param->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2; + slice_param->slice_beta_offset_div2 = sl->slice_beta_offset / 2; + slice_param->luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; + slice_param->chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; + + fill_vaapi_RefPicList(slice_param->RefPicList0, sl->ref_list[0], sl->list_count > 0 ? sl->ref_count[0] : 0); + fill_vaapi_RefPicList(slice_param->RefPicList1, sl->ref_list[1], sl->list_count > 1 ? sl->ref_count[1] : 0); fill_vaapi_plain_pred_weight_table(h, 0, &slice_param->luma_weight_l0_flag, slice_param->luma_weight_l0, slice_param->luma_offset_l0, @@ -355,7 +356,7 @@ AVHWAccel ff_h264_vaapi_hwaccel = { .name = "h264_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_h264_start_frame, .end_frame = vaapi_h264_end_frame, .decode_slice = vaapi_h264_decode_slice, diff --git a/libavcodec/vaapi_internal.h b/libavcodec/vaapi_internal.h index d0fa7ae..5e2a6ca 100644 --- a/libavcodec/vaapi_internal.h +++ b/libavcodec/vaapi_internal.h @@ -27,7 +27,6 @@ #include #include "vaapi.h" #include "avcodec.h" -#include "mpegvideo.h" /** * @addtogroup VAAPI_Decoding diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index 31e0218..459eb75 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -21,31 +21,31 @@ */ #include "mpegutils.h" +#include "mpegvideo.h" #include "vaapi_internal.h" +#include "internal.h" /** Reconstruct bitstream f_code */ -static inline int mpeg2_get_f_code(MpegEncContext *s) +static inline int mpeg2_get_f_code(const MpegEncContext *s) { return (s->mpeg_f_code[0][0] << 12) | (s->mpeg_f_code[0][1] << 8) | (s->mpeg_f_code[1][0] << 4) | s->mpeg_f_code[1][1]; } /** Determine frame start: first field for field picture or frame picture */ -static inline int mpeg2_get_is_frame_start(MpegEncContext *s) +static inline int mpeg2_get_is_frame_start(const MpegEncContext *s) { return s->first_field || s->picture_structure == PICT_FRAME; } static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { - struct MpegEncContext * const s = avctx->priv_data; + const MpegEncContext *s = avctx->priv_data; struct vaapi_context * const vactx = avctx->hwaccel_context; VAPictureParameterBufferMPEG2 *pic_param; VAIQMatrixBufferMPEG2 *iq_matrix; int i; - av_dlog(avctx, "vaapi_mpeg2_start_frame()\n"); - vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG2); /* Fill in VAPictureParameterBufferMPEG2 */ @@ -101,13 +101,11 @@ static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_ static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { - MpegEncContext * const s = avctx->priv_data; + const MpegEncContext *s = avctx->priv_data; VASliceParameterBufferMPEG2 *slice_param; GetBitContext gb; uint32_t quantiser_scale_code, intra_slice_flag, macroblock_offset; - av_dlog(avctx, "vaapi_mpeg2_decode_slice(): buffer %p, size %d\n", buffer, size); - /* Determine macroblock_offset */ init_get_bits(&gb, buffer, 8 * size); if (get_bits_long(&gb, 32) >> 8 != 1) /* start code */ @@ -137,7 +135,7 @@ AVHWAccel ff_mpeg2_vaapi_hwaccel = { .name = "mpeg2_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_mpeg2_start_frame, .end_frame = ff_vaapi_mpeg_end_frame, .decode_slice = vaapi_mpeg2_decode_slice, diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index abdb6d9..6743e2a 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -21,8 +21,10 @@ */ #include "vaapi_internal.h" +#include "internal.h" #include "h263.h" #include "mpeg4video.h" +#include "mpegvideo.h" /** Reconstruct bitstream intra_dc_vlc_thr */ static int mpeg4_get_intra_dc_vlc_thr(Mpeg4DecContext *s) @@ -49,8 +51,6 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_ VAIQMatrixBufferMPEG4 *iq_matrix; int i; - av_dlog(avctx, "vaapi_mpeg4_start_frame()\n"); - vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG4); /* Fill in VAPictureParameterBufferMPEG4 */ @@ -88,8 +88,8 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_ pic_param->vop_fields.bits.alternate_vertical_scan_flag = s->alternate_scan; pic_param->vop_fcode_forward = s->f_code; pic_param->vop_fcode_backward = s->b_code; - pic_param->vop_time_increment_resolution = avctx->time_base.den; - pic_param->num_macroblocks_in_gob = s->mb_width * ff_h263_get_gob_height(s); + pic_param->vop_time_increment_resolution = avctx->framerate.num; + pic_param->num_macroblocks_in_gob = s->mb_width * H263_GOB_HEIGHT(s->height); pic_param->num_gobs_in_vop = (s->mb_width * s->mb_height) / pic_param->num_macroblocks_in_gob; pic_param->TRB = s->pb_time; pic_param->TRD = s->pp_time; @@ -122,8 +122,6 @@ static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer MpegEncContext * const s = avctx->priv_data; VASliceParameterBufferMPEG4 *slice_param; - av_dlog(avctx, "vaapi_mpeg4_decode_slice(): buffer %p, size %d\n", buffer, size); - /* video_plane_with_short_video_header() contains all GOBs * in-order, and this is what VA API (Intel backend) expects: only * a single slice param. So fake macroblock_number for Libav so @@ -151,7 +149,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = { .name = "mpeg4_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_mpeg4_start_frame, .end_frame = ff_vaapi_mpeg_end_frame, .decode_slice = vaapi_mpeg4_decode_slice, @@ -163,7 +161,7 @@ AVHWAccel ff_h263_vaapi_hwaccel = { .name = "h263_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H263, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_mpeg4_start_frame, .end_frame = ff_vaapi_mpeg_end_frame, .decode_slice = vaapi_mpeg4_decode_slice, diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 8886b0b..2fc03e6 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -21,6 +21,7 @@ */ #include "vaapi_internal.h" +#include "internal.h" #include "vc1.h" #include "vc1data.h" @@ -38,7 +39,7 @@ static int get_VAMvModeVC1(enum MVModes mv_mode) } /** Check whether the MVTYPEMB bitplane is present */ -static inline int vc1_has_MVTYPEMB_bitplane(VC1Context *v) +static inline int vc1_has_MVTYPEMB_bitplane(const VC1Context *v) { if (v->mv_type_is_raw) return 0; @@ -49,7 +50,7 @@ static inline int vc1_has_MVTYPEMB_bitplane(VC1Context *v) } /** Check whether the SKIPMB bitplane is present */ -static inline int vc1_has_SKIPMB_bitplane(VC1Context *v) +static inline int vc1_has_SKIPMB_bitplane(const VC1Context *v) { if (v->skip_is_raw) return 0; @@ -58,7 +59,7 @@ static inline int vc1_has_SKIPMB_bitplane(VC1Context *v) } /** Check whether the DIRECTMB bitplane is present */ -static inline int vc1_has_DIRECTMB_bitplane(VC1Context *v) +static inline int vc1_has_DIRECTMB_bitplane(const VC1Context *v) { if (v->dmb_is_raw) return 0; @@ -66,7 +67,7 @@ static inline int vc1_has_DIRECTMB_bitplane(VC1Context *v) } /** Check whether the ACPRED bitplane is present */ -static inline int vc1_has_ACPRED_bitplane(VC1Context *v) +static inline int vc1_has_ACPRED_bitplane(const VC1Context *v) { if (v->acpred_is_raw) return 0; @@ -76,7 +77,7 @@ static inline int vc1_has_ACPRED_bitplane(VC1Context *v) } /** Check whether the OVERFLAGS bitplane is present */ -static inline int vc1_has_OVERFLAGS_bitplane(VC1Context *v) +static inline int vc1_has_OVERFLAGS_bitplane(const VC1Context *v) { if (v->overflg_is_raw) return 0; @@ -88,9 +89,9 @@ static inline int vc1_has_OVERFLAGS_bitplane(VC1Context *v) } /** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */ -static int vc1_get_PTYPE(VC1Context *v) +static int vc1_get_PTYPE(const VC1Context *v) { - MpegEncContext * const s = &v->s; + const MpegEncContext *s = &v->s; switch (s->pict_type) { case AV_PICTURE_TYPE_I: return 0; case AV_PICTURE_TYPE_P: return v->p_frame_skipped ? 4 : 1; @@ -100,7 +101,7 @@ static int vc1_get_PTYPE(VC1Context *v) } /** Reconstruct bitstream MVMODE (7.1.1.32) */ -static inline VAMvModeVC1 vc1_get_MVMODE(VC1Context *v) +static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v) { if (v->s.pict_type == AV_PICTURE_TYPE_P || (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)) @@ -109,7 +110,7 @@ static inline VAMvModeVC1 vc1_get_MVMODE(VC1Context *v) } /** Reconstruct bitstream MVMODE2 (7.1.1.33) */ -static inline VAMvModeVC1 vc1_get_MVMODE2(VC1Context *v) +static inline VAMvModeVC1 vc1_get_MVMODE2(const VC1Context *v) { if (v->s.pict_type == AV_PICTURE_TYPE_P && v->mv_mode == MV_PMODE_INTENSITY_COMP) return get_VAMvModeVC1(v->mv_mode2); @@ -117,7 +118,7 @@ static inline VAMvModeVC1 vc1_get_MVMODE2(VC1Context *v) } /** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */ -static inline int vc1_get_TTFRM(VC1Context *v) +static inline int vc1_get_TTFRM(const VC1Context *v) { switch (v->ttfrm) { case TT_8X8: return 0; @@ -145,13 +146,11 @@ static inline void vc1_pack_bitplanes(uint8_t *bitplane, int n, const uint8_t *f static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { - VC1Context * const v = avctx->priv_data; - MpegEncContext * const s = &v->s; + const VC1Context *v = avctx->priv_data; + const MpegEncContext *s = &v->s; struct vaapi_context * const vactx = avctx->hwaccel_context; VAPictureParameterBufferVC1 *pic_param; - av_dlog(avctx, "vaapi_vc1_start_frame()\n"); - vactx->slice_param_size = sizeof(VASliceParameterBufferVC1); /* Fill in VAPictureParameterBufferVC1 */ @@ -172,9 +171,7 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t pic_param->sequence_fields.bits.syncmarker = v->resync_marker; pic_param->sequence_fields.bits.rangered = v->rangered; pic_param->sequence_fields.bits.max_b_frames = s->avctx->max_b_frames; -#if VA_CHECK_VERSION(0,32,0) pic_param->sequence_fields.bits.profile = v->profile; -#endif pic_param->coded_width = s->avctx->coded_width; pic_param->coded_height = s->avctx->coded_height; pic_param->entrypoint_fields.value = 0; /* reset all bits */ @@ -312,12 +309,10 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { - VC1Context * const v = avctx->priv_data; - MpegEncContext * const s = &v->s; + const VC1Context *v = avctx->priv_data; + const MpegEncContext *s = &v->s; VASliceParameterBufferVC1 *slice_param; - av_dlog(avctx, "vaapi_vc1_decode_slice(): buffer %p, size %d\n", buffer, size); - /* Current bit buffer is beyond any marker for VC-1, so skip it */ if (avctx->codec_id == AV_CODEC_ID_VC1 && IS_MARKER(AV_RB32(buffer))) { buffer += 4; @@ -338,7 +333,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = { .name = "wmv3_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_vc1_start_frame, .end_frame = ff_vaapi_mpeg_end_frame, .decode_slice = vaapi_vc1_decode_slice, @@ -349,7 +344,7 @@ AVHWAccel ff_vc1_vaapi_hwaccel = { .name = "vc1_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, - .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_vc1_start_frame, .end_frame = ff_vaapi_mpeg_end_frame, .decode_slice = vaapi_vc1_decode_slice, diff --git a/libavcodec/vb.c b/libavcodec/vb.c index 56094d8..43954c1 100644 --- a/libavcodec/vb.c +++ b/libavcodec/vb.c @@ -271,5 +271,5 @@ AVCodec ff_vb_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vble.c b/libavcodec/vble.c index 4d5cd96..1a78036 100644 --- a/libavcodec/vble.c +++ b/libavcodec/vble.c @@ -24,15 +24,16 @@ * VBLE Decoder */ -#define BITSTREAM_READER_LE +#include "libavutil/imgutils.h" +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "huffyuvdsp.h" #include "internal.h" #include "mathops.h" -typedef struct { +typedef struct VBLEContext { AVCodecContext *avctx; HuffYUVDSPContext hdsp; @@ -151,7 +152,7 @@ static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, vble_restore_plane(ctx, pic, 0, offset, avctx->width, avctx->height); /* Chroma */ - if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { offset += avctx->width * avctx->height; vble_restore_plane(ctx, pic, 1, offset, width_uv, height_uv); @@ -183,8 +184,8 @@ static av_cold int vble_decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->bits_per_raw_sample = 8; - ctx->size = avpicture_get_size(avctx->pix_fmt, - avctx->width, avctx->height); + ctx->size = av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, avctx->height, 1); ctx->val = av_malloc(ctx->size * sizeof(*ctx->val)); @@ -206,5 +207,5 @@ AVCodec ff_vble_decoder = { .init = vble_decode_init, .close = vble_decode_close, .decode = vble_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index cef0fe6..7a93e97 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -24,7 +24,6 @@ /** * @file * VC-1 and WMV3 decoder common code - * */ #include "libavutil/attributes.h" @@ -33,13 +32,10 @@ #include "mpegvideo.h" #include "vc1.h" #include "vc1data.h" -#include "msmpeg4data.h" +#include "wmv2data.h" #include "unary.h" #include "simple_idct.h" -#undef NDEBUG -#include - /***********************************************************************/ /** * @name VC-1 Bitplane decoding @@ -405,7 +401,7 @@ int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitCo "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", + "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->resync_marker, @@ -485,19 +481,19 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) if (get_bits1(gb)) { //framerate stuff if (get_bits1(gb)) { - v->s.avctx->time_base.num = 32; - v->s.avctx->time_base.den = get_bits(gb, 16) + 1; + v->s.avctx->framerate.den = 32; + v->s.avctx->framerate.num = get_bits(gb, 16) + 1; } else { int nr, dr; nr = get_bits(gb, 8); dr = get_bits(gb, 4); if (nr > 0 && nr < 8 && dr > 0 && dr < 3) { - v->s.avctx->time_base.num = ff_vc1_fps_dr[dr - 1]; - v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000; + v->s.avctx->framerate.den = ff_vc1_fps_dr[dr - 1]; + v->s.avctx->framerate.num = ff_vc1_fps_nr[nr - 1] * 1000; } } if (v->broadcast) { // Pulldown may be present - v->s.avctx->time_base.den *= 2; + v->s.avctx->framerate.num *= 2; v->s.avctx->ticks_per_frame = 2; } } @@ -703,7 +699,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) v->x8_type = get_bits1(gb); } else v->x8_type = 0; - av_dlog(v->s.avctx, "%c Frame: QP=[%i]%i (+%i/2) %i\n", + ff_dlog(v->s.avctx, "%c Frame: QP=[%i]%i (+%i/2) %i\n", (v->s.pict_type == AV_PICTURE_TYPE_P) ? 'P' : ((v->s.pict_type == AV_PICTURE_TYPE_I) ? 'I' : 'B'), pqindex, v->pq, v->halfpq, v->rangeredfrm); @@ -757,7 +753,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) 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 */ + /* Hopefully this is correct for P-frames */ v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; @@ -1140,7 +1136,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) 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 */ + /* Hopefully this is correct for P-frames */ v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; } else if (v->fcm == ILACE_FRAME) { // frame interlaced diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index 9db8edd..5087b7c 100644 --- a/libavcodec/vc1.h +++ b/libavcodec/vc1.h @@ -27,35 +27,11 @@ #include "h264chroma.h" #include "mpegvideo.h" #include "intrax8.h" +#include "vc1_common.h" #include "vc1dsp.h" #define AC_VLC_BITS 9 -/** Markers used in VC-1 AP frame data */ -//@{ -enum VC1Code { - VC1_CODE_RES0 = 0x00000100, - VC1_CODE_ENDOFSEQ = 0x0000010A, - VC1_CODE_SLICE, - VC1_CODE_FIELD, - VC1_CODE_FRAME, - VC1_CODE_ENTRYPOINT, - VC1_CODE_SEQHDR, -}; -//@} - -#define IS_MARKER(x) (((x) & ~0xFF) == VC1_CODE_RES0) - -/** Available Profiles */ -//@{ -enum Profile { - PROFILE_SIMPLE, - PROFILE_MAIN, - PROFILE_COMPLEX, ///< TODO: WMV9 specific - PROFILE_ADVANCED -}; -//@} - /** Sequence quantizer mode */ //@{ enum QuantMode { @@ -97,7 +73,7 @@ enum DQDoubleEdge { }; //@} -/** MV modes for P frames */ +/** MV modes for P-frames */ //@{ enum MVModes { MV_PMODE_1MV_HPEL_BILIN, @@ -120,7 +96,7 @@ enum MBModesIntfr { }; //@} -/** @name MV types for B frames */ +/** @name MV types for B-frames */ //@{ enum BMVTypes { BMV_TYPE_BACKWARD, @@ -130,7 +106,7 @@ enum BMVTypes { }; //@} -/** @name Block types for P/B frames */ +/** @name Block types for P/B-frames */ //@{ enum TransformTypes { TT_8X8, @@ -203,18 +179,18 @@ typedef struct VC1Context{ /** Advanced Profile */ //@{ - int level; ///< 3bits, for Advanced/Simple Profile, provided by TS layer - int chromaformat; ///< 2bits, 2=4:2:0, only defined + int level; ///< 3 bits, for Advanced/Simple Profile, provided by TS layer + int chromaformat; ///< 2 bits, 2=4:2:0, only defined int postprocflag; ///< Per-frame processing suggestion flag present int broadcast; ///< TFF/RFF present int interlace; ///< Progressive/interlaced (RPTFTM syntax element) int tfcntrflag; ///< TFCNTR present int panscanflag; ///< NUMPANSCANWIN, TOPLEFT{X,Y}, BOTRIGHT{X,Y} present int refdist_flag; ///< REFDIST syntax element present in II, IP, PI or PP field picture headers - int extended_dmv; ///< Additional extended dmv range at P/B frame-level - int 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 extended_dmv; ///< Additional extended dmv range at P/B-frame-level + int color_prim; ///< 8 bits, chroma coordinates of the color primaries + int transfer_char; ///< 8 bits, Opto-electronic transfer characteristics + int matrix_coef; ///< 8 bits, Color primaries->YCbCr transform matrix int hrd_param_flag; ///< Presence of Hypothetical Reference ///< Decoder parameters int psf; ///< Progressive Segmented Frame @@ -224,22 +200,22 @@ typedef struct VC1Context{ * 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 profile; ///< 2 bits, Profile + int frmrtq_postproc; ///< 3 bits + int bitrtq_postproc; ///< 5 bits, 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 dquant; ///< How qscale varies with MBs, 2 bits (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 quantizer_mode; ///< 2 bits, 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) + uint8_t mv_mode; ///< MV coding mode + 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 @@ -404,43 +380,6 @@ typedef struct VC1Context{ int resync_marker; ///< could this stream contain resync markers } VC1Context; -/** Find VC-1 marker in buffer - * @return position where next marker starts or end of buffer if no marker found - */ -static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end) -{ - uint32_t mrk = 0xFFFFFFFF; - - if (end-src < 4) - return end; - while (src < end) { - mrk = (mrk << 8) | *src++; - if (IS_MARKER(mrk)) - return src - 4; - } - return end; -} - -static av_always_inline int vc1_unescape_buffer(const uint8_t *src, int size, uint8_t *dst) -{ - int dsize = 0, i; - - if (size < 4) { - for (dsize = 0; dsize < size; dsize++) - *dst++ = *src++; - return size; - } - for (i = 0; i < size; i++, src++) { - if (src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size-1 && src[1] < 4) { - dst[dsize++] = src[1]; - src++; - i++; - } else - dst[dsize++] = *src; - } - return dsize; -} - /** * Decode Simple/Main Profiles sequence header * @see Figure 7-8, p16-17 @@ -461,4 +400,16 @@ void ff_vc1_init_transposed_scantables(VC1Context *v); int ff_vc1_decode_end(AVCodecContext *avctx); void ff_vc1_decode_blocks(VC1Context *v); +void ff_vc1_loop_filter_iblk(VC1Context *v, int pq); +void ff_vc1_loop_filter_iblk_delayed(VC1Context *v, int pq); +void ff_vc1_smooth_overlap_filter_iblk(VC1Context *v); +void ff_vc1_apply_p_loop_filter(VC1Context *v); + +void ff_vc1_mc_1mv(VC1Context *v, int dir); +void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg); +void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir); +void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg); + +void ff_vc1_interp_mc(VC1Context *v); + #endif /* AVCODEC_VC1_H */ diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c new file mode 100644 index 0000000..0e1018c --- /dev/null +++ b/libavcodec/vc1_block.c @@ -0,0 +1,3062 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * VC-1 and WMV3 block decoding routines + */ + +#include "avcodec.h" +#include "mpegutils.h" +#include "mpegvideo.h" +#include "msmpeg4data.h" +#include "unary.h" +#include "vc1.h" +#include "vc1_pred.h" +#include "vc1acdata.h" +#include "vc1data.h" + +#define MB_INTRA_VLC_BITS 9 +#define DC_VLC_BITS 9 + +// offset tables for interlaced picture MVDATA decoding +static const int offset_table1[9] = { 0, 1, 2, 4, 8, 16, 32, 64, 128 }; +static const int offset_table2[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + +/***********************************************************************/ +/** + * @name VC-1 Bitplane decoding + * @see 8.7, p56 + * @{ + */ + +/** + * Imode types + * @{ + */ +enum Imode { + IMODE_RAW, + IMODE_NORM2, + IMODE_DIFF2, + IMODE_NORM6, + IMODE_DIFF6, + IMODE_ROWSKIP, + IMODE_COLSKIP +}; +/** @} */ //imode defines + +static void init_block_index(VC1Context *v) +{ + MpegEncContext *s = &v->s; + ff_init_block_index(s); + if (v->field_mode && !(v->second_field ^ v->tff)) { + s->dest[0] += s->current_picture_ptr->f->linesize[0]; + s->dest[1] += s->current_picture_ptr->f->linesize[1]; + s->dest[2] += s->current_picture_ptr->f->linesize[2]; + } +} + +/** @} */ //Bitplane group + +static void vc1_put_signed_blocks_clamped(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int topleft_mb_pos, top_mb_pos; + int stride_y, fieldtx = 0; + int v_dist; + + /* The put pixels loop is always one MB row behind the decoding loop, + * because we can only put pixels when overlap filtering is done, and + * for filtering of the bottom edge of a MB, we need the next MB row + * present as well. + * Within the row, the put pixels loop is also one MB col behind the + * decoding loop. The reason for this is again, because for filtering + * of the right MB edge, we need the next MB present. */ + if (!s->first_slice_line) { + if (s->mb_x) { + topleft_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x - 1; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[topleft_mb_pos]; + stride_y = s->linesize << fieldtx; + v_dist = (16 - fieldtx) >> (fieldtx == 0); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0], + s->dest[0] - 16 * s->linesize - 16, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][1], + s->dest[0] - 16 * s->linesize - 8, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][2], + s->dest[0] - v_dist * s->linesize - 16, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][3], + s->dest[0] - v_dist * s->linesize - 8, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][4], + s->dest[1] - 8 * s->uvlinesize - 8, + s->uvlinesize); + s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][5], + s->dest[2] - 8 * s->uvlinesize - 8, + s->uvlinesize); + } + if (s->mb_x == s->mb_width - 1) { + top_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[top_mb_pos]; + stride_y = s->linesize << fieldtx; + v_dist = fieldtx ? 15 : 8; + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0], + s->dest[0] - 16 * s->linesize, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][1], + s->dest[0] - 16 * s->linesize + 8, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][2], + s->dest[0] - v_dist * s->linesize, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][3], + s->dest[0] - v_dist * s->linesize + 8, + stride_y); + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][4], + s->dest[1] - 8 * s->uvlinesize, + s->uvlinesize); + s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][5], + s->dest[2] - 8 * s->uvlinesize, + s->uvlinesize); + } + } + +#define inc_blk_idx(idx) do { \ + idx++; \ + if (idx >= v->n_allocated_blks) \ + idx = 0; \ + } while (0) + + inc_blk_idx(v->topleft_blk_idx); + inc_blk_idx(v->top_blk_idx); + inc_blk_idx(v->left_blk_idx); + inc_blk_idx(v->cur_blk_idx); +} + +/***********************************************************************/ +/** + * @name VC-1 Block-level functions + * @see 7.1.4, p91 and 8.1.1.7, p(1)04 + * @{ + */ + +/** + * @def GET_MQUANT + * @brief Get macroblock-level quantizer scale + */ +#define GET_MQUANT() \ + if (v->dquantfrm) { \ + int edges = 0; \ + if (v->dqprofile == DQPROFILE_ALL_MBS) { \ + if (v->dqbilevel) { \ + mquant = (get_bits1(gb)) ? v->altpq : v->pq; \ + } else { \ + mqdiff = get_bits(gb, 3); \ + if (mqdiff != 7) \ + mquant = v->pq + mqdiff; \ + else \ + mquant = get_bits(gb, 5); \ + } \ + } \ + if (v->dqprofile == DQPROFILE_SINGLE_EDGE) \ + edges = 1 << v->dqsbedge; \ + else if (v->dqprofile == DQPROFILE_DOUBLE_EDGES) \ + edges = (3 << v->dqsbedge) % 15; \ + else if (v->dqprofile == DQPROFILE_FOUR_EDGES) \ + edges = 15; \ + if ((edges&1) && !s->mb_x) \ + mquant = v->altpq; \ + if ((edges&2) && s->first_slice_line) \ + mquant = v->altpq; \ + if ((edges&4) && s->mb_x == (s->mb_width - 1)) \ + mquant = v->altpq; \ + if ((edges&8) && s->mb_y == (s->mb_height - 1)) \ + mquant = v->altpq; \ + if (!mquant || mquant > 31) { \ + av_log(v->s.avctx, AV_LOG_ERROR, \ + "Overriding invalid mquant %d\n", mquant); \ + mquant = 1; \ + } \ + } + +/** + * @def GET_MVDATA(_dmv_x, _dmv_y) + * @brief Get MV differentials + * @see MVDATA decoding from 8.3.5.2, p(1)20 + * @param _dmv_x Horizontal differential for decoded MV + * @param _dmv_y Vertical differential for decoded MV + */ +#define GET_MVDATA(_dmv_x, _dmv_y) \ + index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index].table, \ + VC1_MV_DIFF_VLC_BITS, 2); \ + if (index > 36) { \ + mb_has_coeffs = 1; \ + index -= 37; \ + } else \ + mb_has_coeffs = 0; \ + s->mb_intra = 0; \ + if (!index) { \ + _dmv_x = _dmv_y = 0; \ + } else if (index == 35) { \ + _dmv_x = get_bits(gb, v->k_x - 1 + s->quarter_sample); \ + _dmv_y = get_bits(gb, v->k_y - 1 + s->quarter_sample); \ + } else if (index == 36) { \ + _dmv_x = 0; \ + _dmv_y = 0; \ + s->mb_intra = 1; \ + } else { \ + index1 = index % 6; \ + if (!s->quarter_sample && index1 == 5) val = 1; \ + else val = 0; \ + if (size_table[index1] - val > 0) \ + val = get_bits(gb, size_table[index1] - val); \ + else val = 0; \ + sign = 0 - (val&1); \ + _dmv_x = (sign ^ ((val>>1) + offset_table[index1])) - sign; \ + \ + index1 = index / 6; \ + if (!s->quarter_sample && index1 == 5) val = 1; \ + else val = 0; \ + if (size_table[index1] - val > 0) \ + val = get_bits(gb, size_table[index1] - val); \ + else val = 0; \ + sign = 0 - (val & 1); \ + _dmv_y = (sign ^ ((val >> 1) + offset_table[index1])) - sign; \ + } + +static av_always_inline void get_mvdata_interlaced(VC1Context *v, int *dmv_x, + int *dmv_y, int *pred_flag) +{ + int index, index1; + int extend_x = 0, extend_y = 0; + GetBitContext *gb = &v->s.gb; + int bits, esc; + int val, sign; + const int* offs_tab; + + if (v->numref) { + bits = VC1_2REF_MVDATA_VLC_BITS; + esc = 125; + } else { + bits = VC1_1REF_MVDATA_VLC_BITS; + esc = 71; + } + switch (v->dmvrange) { + case 1: + extend_x = 1; + break; + case 2: + extend_y = 1; + break; + case 3: + extend_x = extend_y = 1; + break; + } + index = get_vlc2(gb, v->imv_vlc->table, bits, 3); + if (index == esc) { + *dmv_x = get_bits(gb, v->k_x); + *dmv_y = get_bits(gb, v->k_y); + if (v->numref) { + if (pred_flag) { + *pred_flag = *dmv_y & 1; + *dmv_y = (*dmv_y + *pred_flag) >> 1; + } else { + *dmv_y = (*dmv_y + (*dmv_y & 1)) >> 1; + } + } + } + else { + if (extend_x) + offs_tab = offset_table2; + else + offs_tab = offset_table1; + index1 = (index + 1) % 9; + if (index1 != 0) { + val = get_bits(gb, index1 + extend_x); + sign = 0 -(val & 1); + *dmv_x = (sign ^ ((val >> 1) + offs_tab[index1])) - sign; + } else + *dmv_x = 0; + if (extend_y) + offs_tab = offset_table2; + else + offs_tab = offset_table1; + index1 = (index + 1) / 9; + if (index1 > v->numref) { + val = get_bits(gb, (index1 + (extend_y << v->numref)) >> v->numref); + sign = 0 - (val & 1); + *dmv_y = (sign ^ ((val >> 1) + offs_tab[index1 >> v->numref])) - sign; + } else + *dmv_y = 0; + if (v->numref && pred_flag) + *pred_flag = index1 & 1; + } +} + +/** 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 (direct) { + ff_vc1_mc_1mv(v, 0); + ff_vc1_interp_mc(v); + return; + } + if (mode == BMV_TYPE_INTERPOLATED) { + ff_vc1_mc_1mv(v, 0); + ff_vc1_interp_mc(v); + return; + } + + ff_vc1_mc_1mv(v, (mode == BMV_TYPE_BACKWARD)); +} + +/** Get predicted DC value for I-frames only + * prediction dir: left=0, top=1 + * @param s MpegEncContext + * @param overlap flag indicating that overlap filtering is used + * @param pq integer part of picture quantizer + * @param[in] n block index in the current MB + * @param dc_val_ptr Pointer to DC predictor + * @param dir_ptr Prediction direction for use in AC prediction + */ +static inline int vc1_i_pred_dc(MpegEncContext *s, int overlap, int pq, int n, + int16_t **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, wrap, pred, scale; + int16_t *dc_val; + static const uint16_t dcpred[32] = { + -1, 1024, 512, 341, 256, 205, 171, 146, 128, + 114, 102, 93, 85, 79, 73, 68, 64, + 60, 57, 54, 51, 49, 47, 45, 43, + 41, 39, 38, 37, 35, 34, 33 + }; + + /* find prediction - wmv3_dc_scale always used here in fact */ + if (n < 4) scale = s->y_dc_scale; + else scale = s->c_dc_scale; + + wrap = s->block_wrap[n]; + dc_val = s->dc_val[0] + s->block_index[n]; + + /* B A + * C X + */ + c = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + a = dc_val[ - wrap]; + + if (pq < 9 || !overlap) { + /* Set outer values */ + if (s->first_slice_line && (n != 2 && n != 3)) + b = a = dcpred[scale]; + if (s->mb_x == 0 && (n != 1 && n != 3)) + b = c = dcpred[scale]; + } else { + /* Set outer values */ + if (s->first_slice_line && (n != 2 && n != 3)) + b = a = 0; + if (s->mb_x == 0 && (n != 1 && n != 3)) + b = c = 0; + } + + if (abs(a - b) <= abs(b - c)) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = a; + *dir_ptr = 0; // top + } + + /* update predictor */ + *dc_val_ptr = &dc_val[0]; + return pred; +} + + +/** Get predicted DC value + * prediction dir: left=0, top=1 + * @param s MpegEncContext + * @param overlap flag indicating that overlap filtering is used + * @param pq integer part of picture quantizer + * @param[in] n block index in the current MB + * @param a_avail flag indicating top block availability + * @param c_avail flag indicating left block availability + * @param dc_val_ptr Pointer to DC predictor + * @param dir_ptr Prediction direction for use in AC prediction + */ +static inline int ff_vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n, + int a_avail, int c_avail, + int16_t **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, wrap, pred; + int16_t *dc_val; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int q1, q2 = 0; + int dqscale_index; + + wrap = s->block_wrap[n]; + dc_val = s->dc_val[0] + s->block_index[n]; + + /* B A + * C X + */ + c = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + a = dc_val[ - wrap]; + /* scale predictors if needed */ + q1 = s->current_picture.qscale_table[mb_pos]; + dqscale_index = s->y_dc_scale_table[q1] - 1; + if (dqscale_index < 0) + return 0; + if (c_avail && (n != 1 && n != 3)) { + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (q2 && q2 != q1) + c = (c * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + if (a_avail && (n != 2 && n != 3)) { + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if (q2 && q2 != q1) + a = (a * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + if (a_avail && c_avail && (n != 3)) { + int off = mb_pos; + if (n != 1) + off--; + if (n != 2) + off -= s->mb_stride; + q2 = s->current_picture.qscale_table[off]; + if (q2 && q2 != q1) + b = (b * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + + if (a_avail && c_avail) { + if (abs(a - b) <= abs(b - c)) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = a; + *dir_ptr = 0; // top + } + } else if (a_avail) { + pred = a; + *dir_ptr = 0; // top + } else if (c_avail) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = 0; + *dir_ptr = 1; // left + } + + /* update predictor */ + *dc_val_ptr = &dc_val[0]; + return pred; +} + +/** @} */ // Block group + +/** + * @name VC1 Macroblock-level functions in Simple/Main Profiles + * @see 7.1.4, p91 and 8.1.1.7, p(1)04 + * @{ + */ + +static inline int vc1_coded_block_pred(MpegEncContext * s, int n, + uint8_t **coded_block_ptr) +{ + int xy, wrap, pred, a, b, c; + + xy = s->block_index[n]; + wrap = s->b8_stride; + + /* B C + * A X + */ + a = s->coded_block[xy - 1 ]; + b = s->coded_block[xy - 1 - wrap]; + c = s->coded_block[xy - wrap]; + + if (b == c) { + pred = a; + } else { + pred = c; + } + + /* store value */ + *coded_block_ptr = &s->coded_block[xy]; + + return pred; +} + +/** + * Decode one AC coefficient + * @param v The VC1 context + * @param last Last coefficient + * @param skip How much zero coefficients to skip + * @param value Decoded AC coefficient value + * @param codingset set of VLC to decode data + * @see 8.1.3.4 + */ +static void vc1_decode_ac_coeff(VC1Context *v, int *last, int *skip, + int *value, int codingset) +{ + GetBitContext *gb = &v->s.gb; + int index, escape, run = 0, level = 0, lst = 0; + + index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); + if (index != ff_vc1_ac_sizes[codingset] - 1) { + run = vc1_index_decode_table[codingset][index][0]; + level = vc1_index_decode_table[codingset][index][1]; + lst = index >= vc1_last_decode_table[codingset] || get_bits_left(gb) < 0; + if (get_bits1(gb)) + level = -level; + } else { + escape = decode210(gb); + if (escape != 2) { + index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); + run = vc1_index_decode_table[codingset][index][0]; + level = vc1_index_decode_table[codingset][index][1]; + lst = index >= vc1_last_decode_table[codingset]; + if (escape == 0) { + if (lst) + level += vc1_last_delta_level_table[codingset][run]; + else + level += vc1_delta_level_table[codingset][run]; + } else { + if (lst) + run += vc1_last_delta_run_table[codingset][level] + 1; + else + run += vc1_delta_run_table[codingset][level] + 1; + } + if (get_bits1(gb)) + level = -level; + } else { + int sign; + lst = get_bits1(gb); + if (v->s.esc3_level_length == 0) { + if (v->pq < 8 || v->dquantfrm) { // table 59 + v->s.esc3_level_length = get_bits(gb, 3); + if (!v->s.esc3_level_length) + v->s.esc3_level_length = get_bits(gb, 2) + 8; + } else { // table 60 + v->s.esc3_level_length = get_unary(gb, 1, 6) + 2; + } + v->s.esc3_run_length = 3 + get_bits(gb, 2); + } + run = get_bits(gb, v->s.esc3_run_length); + sign = get_bits1(gb); + level = get_bits(gb, v->s.esc3_level_length); + if (sign) + level = -level; + } + } + + *last = lst; + *skip = run; + *value = level; +} + +/** Decode intra block in intra frames - should be faster than decode_intra_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock index + * @param coded are AC coeffs present or not + * @param codingset set of VLC to decode data + */ +static int vc1_decode_i_block(VC1Context *v, int16_t block[64], int n, + int coded, int codingset) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val; + int16_t *ac_val, *ac_val2; + int dcdiff; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (v->pq == 1) dcdiff = get_bits(gb, 10); + else if (v->pq == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (v->pq == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (v->pq == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += vc1_i_pred_dc(&v->s, v->overlap, v->pq, n, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + /* Skip ? */ + if (!coded) { + goto not_coded; + } + + // AC Decoding + i = 1; + + { + int last = 0, skip, value; + const uint8_t *zz_table; + int scale; + int k; + + scale = v->pq * 2 + v->halfpq; + + if (v->s.ac_pred) { + if (!dc_pred_dir) + zz_table = v->zz_8x8[2]; + else + zz_table = v->zz_8x8[3]; + } else + zz_table = v->zz_8x8[1]; + + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + if (dc_pred_dir) // left + ac_val -= 16; + else // top + ac_val -= 16 * s->block_wrap[n]; + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + block[zz_table[i++]] = value; + } + + /* apply AC prediction if needed */ + if (s->ac_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -v->pq : v->pq; + } + + if (s->ac_pred) i = 63; + } + +not_coded: + if (!coded) { + int k, scale; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + i = 0; + scale = v->pq * 2 + v->halfpq; + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + ac_val -= 16; + if (s->ac_pred) + memcpy(ac_val2, ac_val, 8 * 2); + } else { // top + ac_val -= 16 * s->block_wrap[n]; + if (s->ac_pred) + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + } + + /* apply AC prediction if needed */ + if (s->ac_pred) { + if (dc_pred_dir) { //left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -v->pq : v->pq; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -v->pq : v->pq; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode intra block in intra frames - should be faster than decode_intra_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock number + * @param coded are AC coeffs present or not + * @param codingset set of VLC to decode data + * @param mquant quantizer value for this macroblock + */ +static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n, + int coded, int codingset, int mquant) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val; + int16_t *ac_val, *ac_val2; + int dcdiff; + int a_avail = v->a_avail, c_avail = v->c_avail; + int use_pred = s->ac_pred; + int scale; + int q1, q2 = 0; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (mquant == 1) dcdiff = get_bits(gb, 10); + else if (mquant == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (mquant == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (mquant == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += ff_vc1_pred_dc(&v->s, v->overlap, mquant, n, v->a_avail, v->c_avail, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + + //AC Decoding + i = 1; + + /* check if AC is needed at all */ + if (!a_avail && !c_avail) + use_pred = 0; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + scale = mquant * 2 + ((mquant == v->pq) ? v->halfpq : 0); + + if (dc_pred_dir) // left + ac_val -= 16; + else // top + ac_val -= 16 * s->block_wrap[n]; + + q1 = s->current_picture.qscale_table[mb_pos]; + if (dc_pred_dir && c_avail && mb_pos) + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if (dc_pred_dir && n == 1) + q2 = q1; + if (!dc_pred_dir && n == 2) + q2 = q1; + if (n == 3) + q2 = q1; + + if (coded) { + int last = 0, skip, value; + const uint8_t *zz_table; + int k; + + if (v->s.ac_pred) { + if (!use_pred && v->fcm == ILACE_FRAME) { + zz_table = v->zzi_8x8; + } else { + if (!dc_pred_dir) // top + zz_table = v->zz_8x8[2]; + else // left + zz_table = v->zz_8x8[3]; + } + } else { + if (v->fcm != ILACE_FRAME) + zz_table = v->zz_8x8[1]; + else + zz_table = v->zzi_8x8; + } + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + block[zz_table[i++]] = value; + } + + /* apply AC prediction if needed */ + if (use_pred) { + /* scale predictors if needed*/ + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + + if (q1 < 1) + return AVERROR_INVALIDDATA; + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } else { + if (dc_pred_dir) { //left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { //top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k ] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -mquant : mquant; + } + + if (use_pred) i = 63; + } else { // no AC coeffs + int k; + + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + if (use_pred) { + memcpy(ac_val2, ac_val, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } else { // top + if (use_pred) { + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val2[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode intra block in inter frames - more generic version than vc1_decode_i_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock index + * @param coded are AC coeffs present or not + * @param mquant block quantizer + * @param codingset set of VLC to decode data + */ +static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, + int coded, int mquant, int codingset) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val; + int16_t *ac_val, *ac_val2; + int dcdiff; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int a_avail = v->a_avail, c_avail = v->c_avail; + int use_pred = s->ac_pred; + int scale; + int q1, q2 = 0; + + s->bdsp.clear_block(block); + + /* XXX: Guard against dumb values of mquant */ + mquant = (mquant < 1) ? 0 : ((mquant > 31) ? 31 : mquant); + + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (mquant == 1) dcdiff = get_bits(gb, 10); + else if (mquant == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (mquant == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (mquant == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += ff_vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + + //AC Decoding + i = 1; + + /* check if AC is needed at all and adjust direction if needed */ + if (!a_avail) dc_pred_dir = 1; + if (!c_avail) dc_pred_dir = 0; + if (!a_avail && !c_avail) use_pred = 0; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + scale = mquant * 2 + v->halfpq; + + if (dc_pred_dir) //left + ac_val -= 16; + else //top + ac_val -= 16 * s->block_wrap[n]; + + q1 = s->current_picture.qscale_table[mb_pos]; + if (dc_pred_dir && c_avail && mb_pos) + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if (dc_pred_dir && n == 1) + q2 = q1; + if (!dc_pred_dir && n == 2) + q2 = q1; + if (n == 3) q2 = q1; + + if (coded) { + int last = 0, skip, value; + int k; + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + if (v->fcm == PROGRESSIVE) + block[v->zz_8x8[0][i++]] = value; + else { + if (use_pred && (v->fcm == ILACE_FRAME)) { + if (!dc_pred_dir) // top + block[v->zz_8x8[2][i++]] = value; + else // left + block[v->zz_8x8[3][i++]] = value; + } else { + block[v->zzi_8x8[i++]] = value; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + /* scale predictors if needed*/ + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + + if (q1 < 1) + return AVERROR_INVALIDDATA; + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } else { //top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } else { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k ] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -mquant : mquant; + } + + if (use_pred) i = 63; + } else { // no AC coeffs + int k; + + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + if (use_pred) { + memcpy(ac_val2, ac_val, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } else { // top + if (use_pred) { + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val2[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode P block + */ +static int vc1_decode_p_block(VC1Context *v, int16_t block[64], int n, + int mquant, int ttmb, int first_block, + uint8_t *dst, int linesize, int skip_block, + int *ttmb_out) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int subblkpat = 0; + int scale, off, idx, last, skip, value; + int ttblk = ttmb & 7; + int pat = 0; + + s->bdsp.clear_block(block); + + if (ttmb == -1) { + ttblk = ff_vc1_ttblk_to_tt[v->tt_index][get_vlc2(gb, ff_vc1_ttblk_vlc[v->tt_index].table, VC1_TTBLK_VLC_BITS, 1)]; + } + if (ttblk == TT_4X4) { + subblkpat = ~(get_vlc2(gb, ff_vc1_subblkpat_vlc[v->tt_index].table, VC1_SUBBLKPAT_VLC_BITS, 1) + 1); + } + if ((ttblk != TT_8X8 && ttblk != TT_4X4) + && ((v->ttmbf || (ttmb != -1 && (ttmb & 8) && !first_block)) + || (!v->res_rtm_flag && !first_block))) { + subblkpat = decode012(gb); + if (subblkpat) + subblkpat ^= 3; // swap decoded pattern bits + if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) + ttblk = TT_8X4; + if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) + ttblk = TT_4X8; + } + scale = 2 * mquant + ((v->pq == mquant) ? v->halfpq : 0); + + // convert transforms like 8X4_TOP to generic TT and SUBBLKPAT + if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) { + subblkpat = 2 - (ttblk == TT_8X4_TOP); + ttblk = TT_8X4; + } + if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) { + subblkpat = 2 - (ttblk == TT_4X8_LEFT); + ttblk = TT_4X8; + } + switch (ttblk) { + case TT_8X8: + pat = 0xF; + i = 0; + last = 0; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 63) + break; + if (!v->fcm) + idx = v->zz_8x8[0][i++]; + else + idx = v->zzi_8x8[i++]; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_8x8_dc(dst, linesize, block); + else { + v->vc1dsp.vc1_inv_trans_8x8(block); + s->idsp.add_pixels_clamped(block, dst, linesize); + } + } + break; + case TT_4X4: + pat = ~subblkpat & 0xF; + for (j = 0; j < 4; j++) { + last = subblkpat & (1 << (3 - j)); + i = 0; + off = (j & 1) * 4 + (j & 2) * 16; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 15) + break; + if (!v->fcm) + idx = ff_vc1_simple_progressive_4x4_zz[i++]; + else + idx = ff_vc1_adv_interlaced_4x4_zz[i++]; + block[idx + off] = value * scale; + if (!v->pquantizer) + block[idx + off] += (block[idx + off] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (3 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_4x4_dc(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_4x4(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); + } + } + break; + case TT_8X4: + pat = ~((subblkpat & 2) * 6 + (subblkpat & 1) * 3) & 0xF; + for (j = 0; j < 2; j++) { + last = subblkpat & (1 << (1 - j)); + i = 0; + off = j * 32; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 31) + break; + if (!v->fcm) + idx = v->zz_8x4[i++] + off; + else + idx = ff_vc1_adv_interlaced_8x4_zz[i++] + off; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (1 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_8x4_dc(dst + j * 4 * linesize, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_8x4(dst + j * 4 * linesize, linesize, block + off); + } + } + break; + case TT_4X8: + pat = ~(subblkpat * 5) & 0xF; + for (j = 0; j < 2; j++) { + last = subblkpat & (1 << (1 - j)); + i = 0; + off = j * 4; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 31) + break; + if (!v->fcm) + idx = v->zz_4x8[i++] + off; + else + idx = ff_vc1_adv_interlaced_4x8_zz[i++] + off; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (1 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_4x8_dc(dst + j * 4, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_4x8(dst + j*4, linesize, block + off); + } + } + break; + } + if (ttmb_out) + *ttmb_out |= ttblk << (n * 4); + return pat; +} + +/** @} */ // Macroblock group + +static const int size_table [6] = { 0, 2, 3, 4, 5, 8 }; +static const int offset_table[6] = { 0, 1, 3, 7, 15, 31 }; + +/** Decode one P-frame MB + */ +static int vc1_decode_p_mb(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int index, index1; /* LUT indexes */ + int val, sign; /* temp values */ + int first_block = 1; + int dst_idx, off; + int skipped, fourmv; + int block_cbp = 0, pat, block_tt = 0, block_intra = 0; + + mquant = v->pq; /* lossy initialization */ + + if (v->mv_type_is_raw) + fourmv = get_bits1(gb); + else + fourmv = v->mv_type_mb_plane[mb_pos]; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + if (!fourmv) { /* 1MV mode */ + if (!skipped) { + GET_MVDATA(dmv_x, dmv_y); + + if (s->mb_intra) { + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + } + s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16; + ff_vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + + /* FIXME Set DC val for inter block ? */ + if (s->mb_intra && !mb_has_coeffs) { + GET_MQUANT(); + s->ac_pred = get_bits1(gb); + cbp = 0; + } else if (mb_has_coeffs) { + if (s->mb_intra) + s->ac_pred = get_bits1(gb); + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + } else { + mquant = v->pq; + cbp = 0; + } + s->current_picture.qscale_table[mb_pos] = mquant; + + if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, + VC1_TTMB_VLC_BITS, 2); + if (!s->mb_intra) ff_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->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + i & 4 ? s->uvlinesize + : s->linesize); + if (v->pq >= 9 && v->overlap) { + if (v->c_avail) + v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + if (v->a_avail) + v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + } + block_cbp |= 0xF << (i << 2); + block_intra |= 1 << i; + } else if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, + s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } else { // skipped + s->mb_intra = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + ff_vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + ff_vc1_mc_1mv(v, 0); + } + } else { // 4MV mode + if (!skipped /* unskipped MB */) { + int intra_count = 0, coded_inter = 0; + int is_intra[6], is_coded[6]; + /* Get CBPCY */ + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + val = ((cbp >> (5 - i)) & 1); + s->dc_val[0][s->block_index[i]] = 0; + s->mb_intra = 0; + if (i < 4) { + dmv_x = dmv_y = 0; + s->mb_intra = 0; + mb_has_coeffs = 0; + if (val) { + GET_MVDATA(dmv_x, dmv_y); + } + ff_vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); + if (!s->mb_intra) + ff_vc1_mc_4mv_luma(v, i, 0, 0); + intra_count += s->mb_intra; + is_intra[i] = s->mb_intra; + is_coded[i] = mb_has_coeffs; + } + if (i & 4) { + is_intra[i] = (intra_count >= 3); + is_coded[i] = val; + } + if (i == 4) + ff_vc1_mc_4mv_chroma(v, 0); + v->mb_type[0][s->block_index[i]] = is_intra[i]; + if (!coded_inter) + coded_inter = !is_intra[i] & is_coded[i]; + } + // if there are no coded blocks then don't do anything more + dst_idx = 0; + if (!intra_count && !coded_inter) + goto end; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* test if block is intra and has pred */ + { + int intrapred = 0; + for (i = 0; i < 6; i++) + if (is_intra[i]) { + if (((!s->first_slice_line || (i == 2 || i == 3)) && v->mb_type[0][s->block_index[i] - s->block_wrap[i]]) + || ((s->mb_x || (i == 1 || i == 3)) && v->mb_type[0][s->block_index[i] - 1])) { + intrapred = 1; + break; + } + } + if (intrapred) + s->ac_pred = get_bits1(gb); + else + s->ac_pred = 0; + } + if (!v->ttmbf && coded_inter) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + dst_idx += i >> 2; + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->mb_intra = is_intra[i]; + if (is_intra[i]) { + /* check if prediction blocks A and C are available */ + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, is_coded[i], mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i > 3) && (s->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize + : s->linesize); + if (v->pq >= 9 && v->overlap) { + if (v->c_avail) + v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + if (v->a_avail) + v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + } + block_cbp |= 0xF << (i << 2); + block_intra |= 1 << i; + } else if (is_coded[i]) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), + &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } else { // skipped MB + s->mb_intra = 0; + s->current_picture.qscale_table[mb_pos] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + for (i = 0; i < 4; i++) { + ff_vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); + ff_vc1_mc_4mv_luma(v, i, 0, 0); + } + ff_vc1_mc_4mv_chroma(v, 0); + s->current_picture.qscale_table[mb_pos] = 0; + } + } +end: + v->cbp[s->mb_x] = block_cbp; + v->ttblk[s->mb_x] = block_tt; + v->is_intra[s->mb_x] = block_intra; + + return 0; +} + +/* Decode one macroblock in an interlaced frame p picture */ + +static int vc1_decode_p_mb_intfr(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int skipped, fourmv = 0, twomv = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0, mvbp; + int stride_y, fieldtx; + + mquant = v->pq; /* Lossy initialization */ + + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + if (!skipped) { + if (v->fourmvswitch) + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_4MV_MBMODE_VLC_BITS, 2); // try getting this done + else + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); // in a single line + switch (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0]) { + /* store the motion vector type in a flag (useful later) */ + case MV_PMODE_INTFR_4MV: + fourmv = 1; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + break; + case MV_PMODE_INTFR_4MV_FIELD: + fourmv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + break; + case MV_PMODE_INTFR_2MV_FIELD: + twomv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + break; + case MV_PMODE_INTFR_1MV: + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + break; + } + if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } + v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1. + s->mb_intra = 1; + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = get_bits1(gb); + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + dst_idx = 0; + for (i = 0; i < 6; i++) { + v->a_avail = v->c_avail = 0; + v->mb_type[0][s->block_index[i]] = 1; + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + 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->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (i < 4) { + stride_y = s->linesize << fieldtx; + off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; + } else { + stride_y = s->uvlinesize; + off = 0; + } + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + stride_y); + //TODO: loop filter + } + + } else { // inter MB + mb_has_coeffs = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][3]; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) { + v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); + } else { + if ((ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV) + || (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV_FIELD)) { + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + } + } + s->mb_intra = v->is_intra[s->mb_x] = 0; + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 0; + fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][1]; + /* for all motion vector read MVDATA and motion compensate each block */ + dst_idx = 0; + if (fourmv) { + mvbp = v->fourmvbp; + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x = dmv_y = 0; + val = ((mvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + ff_vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_4mv_luma(v, i, 0, 0); + } else if (i == 4) { + ff_vc1_mc_4mv_chroma4(v, 0, 0, 0); + } + } + } else if (twomv) { + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_4mv_luma(v, 0, 0, 0); + ff_vc1_mc_4mv_luma(v, 1, 0, 0); + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + ff_vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_4mv_luma(v, 2, 0, 0); + ff_vc1_mc_4mv_luma(v, 3, 0, 0); + ff_vc1_mc_4mv_chroma4(v, 0, 0, 0); + } else { + mvbp = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][2]; + dmv_x = dmv_y = 0; + if (mvbp) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_1mv(v, 0); + } + if (cbp) + GET_MQUANT(); // p. 227 + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + if (!fieldtx) + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + else + off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } + } else { // skipped + s->mb_intra = v->is_intra[s->mb_x] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_1mv(v, 0); + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride); + return 0; +} + +static int vc1_decode_p_mb_intfi(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp values */ + int first_block = 1; + int dst_idx, off; + int pred_flag; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0; + + mquant = v->pq; /* Lossy initialization */ + + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); + if (idx_mbmode <= 1) { // intra MB + v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1. + s->mb_intra = 1; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = idx_mbmode & 1; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); + dst_idx = 0; + for (i = 0; i < 6; i++) { + v->a_avail = v->c_avail = 0; + v->mb_type[0][s->block_index[i]] = 1; + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + 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->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize + : s->linesize); + // TODO: loop filter + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; + for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; + if (idx_mbmode <= 5) { // 1-MV + dmv_x = dmv_y = pred_flag = 0; + if (idx_mbmode & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); + } + ff_vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); + ff_vc1_mc_1mv(v, 0); + mb_has_coeffs = !(idx_mbmode & 2); + } else { // 4-MV + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x = dmv_y = pred_flag = 0; + val = ((v->fourmvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); + } + ff_vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); + ff_vc1_mc_4mv_luma(v, i, 0, 0); + } else if (i == 4) + ff_vc1_mc_4mv_chroma(v, 0); + } + mb_has_coeffs = idx_mbmode & 1; + } + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (cbp) { + GET_MQUANT(); + } + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) { + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), + &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) ttmb = -1; + first_block = 0; + } + } + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); + return 0; +} + +/** Decode one B-frame MB (in Main profile) + */ +static void vc1_decode_b_mb(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mb_has_coeffs = 0; /* last_flag */ + int index, index1; /* LUT indexes */ + int val, sign; /* temp values */ + int first_block = 1; + int dst_idx, off; + int skipped, direct; + int dmv_x[2], dmv_y[2]; + int bmvtype = BMV_TYPE_BACKWARD; + + mquant = v->pq; /* lossy initialization */ + s->mb_intra = 0; + + if (v->dmb_is_raw) + direct = get_bits1(gb); + else + direct = v->direct_mb_plane[mb_pos]; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.qscale_table[mb_pos] = 0; + + if (!direct) { + if (!skipped) { + GET_MVDATA(dmv_x[0], dmv_y[0]); + dmv_x[1] = dmv_x[0]; + dmv_y[1] = dmv_y[0]; + } + if (skipped || !s->mb_intra) { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; + break; + case 1: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + dmv_x[0] = dmv_y[0] = 0; + } + } + } + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = s->mb_intra; + + if (skipped) { + if (direct) + bmvtype = BMV_TYPE_INTERPOLATED; + ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + return; + } + if (direct) { + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + s->mb_intra = 0; + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + dmv_x[0] = dmv_y[0] = dmv_x[1] = dmv_y[1] = 0; + ff_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 */ + ff_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; + ff_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 */ + ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + return; + } + } + ff_vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + if (!s->mb_intra) { + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + } + if (s->mb_intra) + s->ac_pred = get_bits1(gb); + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + if (s->mb_intra) { + /* check if prediction blocks A and C are available */ + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i > 3) && (s->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + i & 4 ? s->uvlinesize + : s->linesize); + } else if (val) { + vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), NULL); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } +} + +/** Decode one B-frame MB (in interlaced field B picture) + */ +static void vc1_decode_b_mb_intfi(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mb_has_coeffs = 0; /* last_flag */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int fwd; + int dmv_x[2], dmv_y[2], pred_flag[2]; + int bmvtype = BMV_TYPE_BACKWARD; + int idx_mbmode, interpmvp; + + mquant = v->pq; /* Lossy initialization */ + s->mb_intra = 0; + + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); + if (idx_mbmode <= 1) { // intra MB + v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1. + s->mb_intra = 1; + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = idx_mbmode & 1; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); + dst_idx = 0; + for (i = 0; i < 6; i++) { + v->a_avail = v->c_avail = 0; + v->mb_type[0][s->block_index[i]] = 1; + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + 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->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize + : s->linesize); + // TODO: yet to perform loop filter + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; + for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; + if (v->fmb_is_raw) + fwd = v->forward_mb_plane[mb_pos] = get_bits1(gb); + else + fwd = v->forward_mb_plane[mb_pos]; + if (idx_mbmode <= 5) { // 1-MV + dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; + pred_flag[0] = pred_flag[1] = 0; + if (fwd) + bmvtype = BMV_TYPE_FORWARD; + else { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = BMV_TYPE_BACKWARD; + break; + case 1: + bmvtype = BMV_TYPE_DIRECT; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + interpmvp = get_bits1(gb); + } + } + v->bmvtype = bmvtype; + if (bmvtype != BMV_TYPE_DIRECT && idx_mbmode & 1) { + get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], &dmv_y[bmvtype == BMV_TYPE_BACKWARD], &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); + } + if (bmvtype == BMV_TYPE_INTERPOLATED && interpmvp) { + get_mvdata_interlaced(v, &dmv_x[1], &dmv_y[1], &pred_flag[1]); + } + if (bmvtype == BMV_TYPE_DIRECT) { + dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; + dmv_x[1] = dmv_y[1] = pred_flag[0] = 0; + } + ff_vc1_pred_b_mv_intfi(v, 0, dmv_x, dmv_y, 1, pred_flag); + vc1_b_mc(v, dmv_x, dmv_y, (bmvtype == BMV_TYPE_DIRECT), bmvtype); + mb_has_coeffs = !(idx_mbmode & 2); + } else { // 4-MV + if (fwd) + bmvtype = BMV_TYPE_FORWARD; + v->bmvtype = bmvtype; + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; + dmv_x[1] = dmv_y[1] = pred_flag[1] = 0; + val = ((v->fourmvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], + &dmv_y[bmvtype == BMV_TYPE_BACKWARD], + &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); + } + ff_vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag); + ff_vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD, 0); + } else if (i == 4) + ff_vc1_mc_4mv_chroma(v, bmvtype == BMV_TYPE_BACKWARD); + } + mb_has_coeffs = idx_mbmode & 1; + } + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (cbp) { + GET_MQUANT(); + } + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) { + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; + if (val) { + vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), NULL); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } +} + +/** Decode one B-frame MB (in interlaced frame B picture) + */ +static int vc1_decode_b_mb_intfr(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mvsw = 0; /* motion vector switch */ + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int skipped, direct, twomv = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0, mvbp; + int stride_y, fieldtx; + int bmvtype = BMV_TYPE_BACKWARD; + int dir, dir2; + + mquant = v->pq; /* Lossy initialization */ + s->mb_intra = 0; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + if (!skipped) { + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) { + twomv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + } else { + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + } + } + + if (v->dmb_is_raw) + direct = get_bits1(gb); + else + direct = v->direct_mb_plane[mb_pos]; + + if (direct) { + s->mv[0][0][0] = s->current_picture.motion_val[0][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = s->current_picture.motion_val[0][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = s->current_picture.motion_val[1][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = s->current_picture.motion_val[1][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 1, s->quarter_sample); + + if (twomv) { + s->mv[0][2][0] = s->current_picture.motion_val[0][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][2][1] = s->current_picture.motion_val[0][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][2][0] = s->current_picture.motion_val[1][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][2][1] = s->current_picture.motion_val[1][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 1, s->quarter_sample); + + for (i = 1; i < 4; i += 2) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][i-1][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][i-1][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][i-1][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][i-1][1]; + } + } else { + for (i = 1; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][0][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][0][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][0][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][0][1]; + } + } + } + + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB + for (i = 0; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = 0; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = 0; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } + v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1. + s->mb_intra = 1; + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = get_bits1(gb); + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + dst_idx = 0; + for (i = 0; i < 6; i++) { + v->a_avail = v->c_avail = 0; + v->mb_type[0][s->block_index[i]] = 1; + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + 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->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (i < 4) { + stride_y = s->linesize << fieldtx; + off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; + } else { + stride_y = s->uvlinesize; + off = 0; + } + s->idsp.put_signed_pixels_clamped(s->block[i], + s->dest[dst_idx] + off, + stride_y); + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + if (!direct) { + if (skipped || !s->mb_intra) { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; + break; + case 1: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + } + } + + if (twomv && bmvtype != BMV_TYPE_INTERPOLATED) + mvsw = get_bits1(gb); + } + + if (!skipped) { // inter MB + mb_has_coeffs = ff_vc1_mbmode_intfrp[0][idx_mbmode][3]; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED && twomv) { + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + } else if (bmvtype == BMV_TYPE_INTERPOLATED || twomv) { + v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); + } + } + + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 0; + fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[0][idx_mbmode][1]; + /* for all motion vector read MVDATA and motion compensate each block */ + dst_idx = 0; + if (direct) { + if (twomv) { + for (i = 0; i < 4; i++) { + ff_vc1_mc_4mv_luma(v, i, 0, 0); + ff_vc1_mc_4mv_luma(v, i, 1, 1); + } + ff_vc1_mc_4mv_chroma4(v, 0, 0, 0); + ff_vc1_mc_4mv_chroma4(v, 1, 1, 1); + } else { + ff_vc1_mc_1mv(v, 0); + ff_vc1_interp_mc(v); + } + } else if (twomv && bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->fourmvbp; + for (i = 0; i < 4; i++) { + dir = i==1 || i==3; + dmv_x = dmv_y = 0; + val = ((mvbp >> (3 - i)) & 1); + if (val) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + j = i > 1 ? 2 : 0; + ff_vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + ff_vc1_mc_4mv_luma(v, j, dir, dir); + ff_vc1_mc_4mv_luma(v, j+1, dir, dir); + } + + ff_vc1_mc_4mv_chroma4(v, 0, 0, 0); + ff_vc1_mc_4mv_chroma4(v, 1, 1, 1); + } else if (bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_mc_1mv(v, 0); + + dmv_x = dmv_y = 0; + if (mvbp & 1) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 1); + ff_vc1_interp_mc(v); + } else if (twomv) { + dir = bmvtype == BMV_TYPE_BACKWARD; + dir2 = dir; + if (mvsw) + dir2 = !dir; + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + + dmv_x = dmv_y = 0; + if (mvbp & 1) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + ff_vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir2); + + if (mvsw) { + for (i = 0; i < 2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + ff_vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + } + + ff_vc1_mc_4mv_luma(v, 0, dir, 0); + ff_vc1_mc_4mv_luma(v, 1, dir, 0); + ff_vc1_mc_4mv_luma(v, 2, dir2, 0); + ff_vc1_mc_4mv_luma(v, 3, dir2, 0); + ff_vc1_mc_4mv_chroma4(v, dir, dir2, 0); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + + mvbp = ff_vc1_mbmode_intfrp[0][idx_mbmode][2]; + dmv_x = dmv_y = 0; + if (mvbp) + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + + ff_vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], dir); + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i < 2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + ff_vc1_mc_1mv(v, dir); + } + + if (cbp) + GET_MQUANT(); // p. 227 + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + if (!fieldtx) + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + else + off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), + (i & 4) && (s->avctx->flags & AV_CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + + } else { // skipped + dir = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED) { + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 1); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], dir); + if (mvsw) { + int dir2 = dir; + if (mvsw) + dir2 = !dir; + for (i = 0; i < 2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + ff_vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i < 2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + } + } + } + + ff_vc1_mc_1mv(v, dir); + if (direct || bmvtype == BMV_TYPE_INTERPOLATED) { + ff_vc1_interp_mc(v); + } + } + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); + v->cbp[s->mb_x] = block_cbp; + v->ttblk[s->mb_x] = block_tt; + return 0; +} + +/** Decode blocks of I-frame + */ +static void vc1_decode_i_blocks(VC1Context *v) +{ + int k, j; + MpegEncContext *s = &v->s; + int cbp, val; + uint8_t *coded_val; + int mb_pos; + + /* select coding mode used for VLC tables selection */ + switch (v->y_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[v->pq]; + s->c_dc_scale = s->c_dc_scale_table[v->pq]; + + //do frame decode + s->mb_x = s->mb_y = 0; + s->mb_intra = 1; + s->first_slice_line = 1; + for (s->mb_y = 0; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < v->end_mb_x; s->mb_x++) { + uint8_t *dst[6]; + ff_update_block_index(s); + dst[0] = s->dest[0]; + dst[1] = dst[0] + 8; + dst[2] = s->dest[0] + s->linesize * 8; + dst[3] = dst[2] + 8; + dst[4] = s->dest[1]; + dst[5] = s->dest[2]; + s->bdsp.clear_blocks(s->block[0]); + mb_pos = s->mb_x + s->mb_y * s->mb_width; + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + s->current_picture.qscale_table[mb_pos] = v->pq; + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + + // do actual MB decoding and displaying + cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + v->s.ac_pred = get_bits1(&v->s.gb); + + for (k = 0; k < 6; k++) { + val = ((cbp >> (5 - k)) & 1); + + if (k < 4) { + int pred = vc1_coded_block_pred(&v->s, k, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - k); + + vc1_decode_i_block(v, s->block[k], k, val, (k < 4) ? v->codingset : v->codingset2); + + if (k > 3 && (s->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[k]); + if (v->pq >= 9 && v->overlap) { + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[k][j] <<= 1; + s->idsp.put_signed_pixels_clamped(s->block[k], dst[k], + k & 4 ? s->uvlinesize + : s->linesize); + } else { + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[k][j] = (s->block[k][j] - 64) << 1; + s->idsp.put_pixels_clamped(s->block[k], dst[k], + k & 4 ? s->uvlinesize + : s->linesize); + } + } + + if (v->pq >= 9 && v->overlap) { + if (s->mb_x) { + v->vc1dsp.vc1_h_overlap(s->dest[0], s->linesize); + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize); + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_h_overlap(s->dest[1], s->uvlinesize); + v->vc1dsp.vc1_h_overlap(s->dest[2], s->uvlinesize); + } + } + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize); + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); + if (!s->first_slice_line) { + v->vc1dsp.vc1_v_overlap(s->dest[0], s->linesize); + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize); + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_overlap(s->dest[1], s->uvlinesize); + v->vc1dsp.vc1_v_overlap(s->dest[2], s->uvlinesize); + } + } + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize); + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); + } + if (v->s.loop_filter) + ff_vc1_loop_filter_iblk(v, v->pq); + + if (get_bits_count(&s->gb) > v->bits) { + ff_er_add_slice(&s->er, 0, 0, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", + get_bits_count(&s->gb), v->bits); + return; + } + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + + s->first_slice_line = 0; + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + + /* This is intentionally mb_height and not end_mb_y - unlike in advanced + * profile, these only differ are when decoding MSS2 rectangles. */ + ff_er_add_slice(&s->er, 0, 0, s->mb_width - 1, s->mb_height - 1, ER_MB_END); +} + +/** Decode blocks of I-frame for advanced profile + */ +static void vc1_decode_i_blocks_adv(VC1Context *v) +{ + int k; + MpegEncContext *s = &v->s; + int cbp, val; + uint8_t *coded_val; + int mb_pos; + int mquant = v->pq; + int mqdiff; + GetBitContext *gb = &s->gb; + + /* select coding mode used for VLC tables selection */ + switch (v->y_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + // do frame decode + s->mb_x = s->mb_y = 0; + s->mb_intra = 1; + s->first_slice_line = 1; + s->mb_y = s->start_mb_y; + if (s->start_mb_y) { + s->mb_x = 0; + init_block_index(v); + memset(&s->coded_block[s->block_index[0] - s->b8_stride], 0, + (1 + s->b8_stride) * sizeof(*s->coded_block)); + } + for (; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (;s->mb_x < s->mb_width; s->mb_x++) { + int16_t (*block)[64] = v->block[v->cur_blk_idx]; + ff_update_block_index(s); + s->bdsp.clear_blocks(block[0]); + mb_pos = s->mb_x + s->mb_y * s->mb_stride; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + + // do actual MB decoding and displaying + if (v->fieldtx_is_raw) + v->fieldtx_plane[mb_pos] = get_bits1(&v->s.gb); + cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + if (v->acpred_is_raw) + v->s.ac_pred = get_bits1(&v->s.gb); + else + v->s.ac_pred = v->acpred_plane[mb_pos]; + + if (v->condover == CONDOVER_SELECT && v->overflg_is_raw) + v->over_flags_plane[mb_pos] = get_bits1(&v->s.gb); + + GET_MQUANT(); + + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + + for (k = 0; k < 6; k++) { + val = ((cbp >> (5 - k)) & 1); + + if (k < 4) { + int pred = vc1_coded_block_pred(&v->s, k, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - k); + + v->a_avail = !s->first_slice_line || (k == 2 || k == 3); + v->c_avail = !!s->mb_x || (k == 1 || k == 3); + + vc1_decode_i_block_adv(v, block[k], k, val, + (k < 4) ? v->codingset : v->codingset2, mquant); + + if (k > 3 && (s->avctx->flags & AV_CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(block[k]); + } + + ff_vc1_smooth_overlap_filter_iblk(v); + vc1_put_signed_blocks_clamped(v); + if (v->s.loop_filter) + ff_vc1_loop_filter_iblk_delayed(v, v->pq); + + if (get_bits_count(&s->gb) > v->bits) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", + get_bits_count(&s->gb), v->bits); + return; + } + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y-1) * 16, 16); + s->first_slice_line = 0; + } + + /* raw bottom MB row */ + s->mb_x = 0; + init_block_index(v); + + for (;s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + vc1_put_signed_blocks_clamped(v); + if (v->s.loop_filter) + ff_vc1_loop_filter_iblk_delayed(v, v->pq); + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y-1)*16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_p_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int apply_loop_filter; + + /* select coding mode used for VLC tables selection */ + switch (v->c_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + apply_loop_filter = s->loop_filter && !(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY) && + v->fcm == PROGRESSIVE; + s->first_slice_line = 1; + memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + + if (v->fcm == ILACE_FIELD) + vc1_decode_p_mb_intfi(v); + else if (v->fcm == ILACE_FRAME) + vc1_decode_p_mb_intfr(v); + else vc1_decode_p_mb(v); + if (s->mb_y != s->start_mb_y && apply_loop_filter) + ff_vc1_apply_p_loop_filter(v); + if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", + get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + return; + } + } + memmove(v->cbp_base, v->cbp, sizeof(v->cbp_base[0]) * s->mb_stride); + memmove(v->ttblk_base, v->ttblk, sizeof(v->ttblk_base[0]) * s->mb_stride); + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); + memmove(v->luma_mv_base, v->luma_mv, sizeof(v->luma_mv_base[0]) * s->mb_stride); + if (s->mb_y != s->start_mb_y) ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + s->first_slice_line = 0; + } + if (apply_loop_filter) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + ff_vc1_apply_p_loop_filter(v); + } + } + if (s->end_mb_y >= s->start_mb_y) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_b_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + + /* select coding mode used for VLC tables selection */ + switch (v->c_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + s->first_slice_line = 1; + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + + if (v->fcm == ILACE_FIELD) + vc1_decode_b_mb_intfi(v); + else if (v->fcm == ILACE_FRAME) + vc1_decode_b_mb_intfr(v); + else + vc1_decode_b_mb(v); + if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", + get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + return; + } + if (v->s.loop_filter) + ff_vc1_loop_filter_iblk(v, v->pq); + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + s->first_slice_line = 0; + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_skip_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + + if (!v->s.last_picture.f->data[0]) + return; + + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, ER_MB_END); + s->first_slice_line = 1; + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + ff_update_block_index(s); + memcpy(s->dest[0], s->last_picture.f->data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16); + memcpy(s->dest[1], s->last_picture.f->data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + memcpy(s->dest[2], s->last_picture.f->data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + s->first_slice_line = 0; + } + s->pict_type = AV_PICTURE_TYPE_P; +} + +void ff_vc1_decode_blocks(VC1Context *v) +{ + + v->s.esc3_level_length = 0; + if (v->x8_type) { + ff_intrax8_decode_picture(&v->x8, &v->s.current_picture, + &v->s.gb, &v->s.mb_x, &v->s.mb_y, + 2 * v->pq + v->halfpq, v->pq * !v->pquantizer, + v->s.loop_filter, v->s.low_delay); + + ff_er_add_slice(&v->s.er, 0, 0, + (v->s.mb_x >> 1) - 1, (v->s.mb_y >> 1) - 1, + ER_MB_END); + } else { + v->cur_blk_idx = 0; + v->left_blk_idx = -1; + v->topleft_blk_idx = 1; + v->top_blk_idx = 2; + switch (v->s.pict_type) { + case AV_PICTURE_TYPE_I: + if (v->profile == PROFILE_ADVANCED) + vc1_decode_i_blocks_adv(v); + else + vc1_decode_i_blocks(v); + break; + case AV_PICTURE_TYPE_P: + if (v->p_frame_skipped) + vc1_decode_skip_blocks(v); + else + vc1_decode_p_blocks(v); + break; + case AV_PICTURE_TYPE_B: + if (v->bi_type) { + if (v->profile == PROFILE_ADVANCED) + vc1_decode_i_blocks_adv(v); + else + vc1_decode_i_blocks(v); + } else + vc1_decode_b_blocks(v); + break; + } + } +} diff --git a/libavcodec/vc1_common.h b/libavcodec/vc1_common.h new file mode 100644 index 0000000..788d324 --- /dev/null +++ b/libavcodec/vc1_common.h @@ -0,0 +1,92 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VC1_COMMON_H +#define AVCODEC_VC1_COMMON_H + +#include + +#include "libavutil/attributes.h" + +/** Markers used in VC-1 AP frame data */ +//@{ +enum VC1Code { + VC1_CODE_RES0 = 0x00000100, + VC1_CODE_ENDOFSEQ = 0x0000010A, + VC1_CODE_SLICE, + VC1_CODE_FIELD, + VC1_CODE_FRAME, + VC1_CODE_ENTRYPOINT, + VC1_CODE_SEQHDR, +}; +//@} + +#define IS_MARKER(x) (((x) & ~0xFF) == VC1_CODE_RES0) + +/** Available Profiles */ +//@{ +enum Profile { + PROFILE_SIMPLE, + PROFILE_MAIN, + PROFILE_COMPLEX, ///< TODO: WMV9 specific + PROFILE_ADVANCED +}; +//@} + +/** Find VC-1 marker in buffer + * @return position where next marker starts or end of buffer if no marker found + */ +static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end) +{ + uint32_t mrk = 0xFFFFFFFF; + + if (end-src < 4) + return end; + while (src < end) { + mrk = (mrk << 8) | *src++; + if (IS_MARKER(mrk)) + return src - 4; + } + return end; +} + +static av_always_inline int vc1_unescape_buffer(const uint8_t *src, int size, uint8_t *dst) +{ + int dsize = 0, i; + + if (size < 4) { + for (dsize = 0; dsize < size; dsize++) + *dst++ = *src++; + return size; + } + for (i = 0; i < size; i++, src++) { + if (src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size-1 && src[1] < 4) { + dst[dsize++] = src[1]; + src++; + i++; + } else + dst[dsize++] = *src; + } + return dsize; +} + +#endif /* AVCODEC_VC1_COMMON_H */ diff --git a/libavcodec/vc1_loopfilter.c b/libavcodec/vc1_loopfilter.c new file mode 100644 index 0000000..52cff1e --- /dev/null +++ b/libavcodec/vc1_loopfilter.c @@ -0,0 +1,353 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * VC-1 and WMV3 loopfilter + */ + +#include "avcodec.h" +#include "mpegvideo.h" +#include "vc1.h" +#include "vc1dsp.h" + +void ff_vc1_loop_filter_iblk(VC1Context *v, int pq) +{ + MpegEncContext *s = &v->s; + int j; + if (!s->first_slice_line) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq); + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq); + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, pq); + + if (s->mb_y == s->end_mb_y - 1) { + if (s->mb_x) { + v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq); + v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq); + } + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq); + } +} + +void ff_vc1_loop_filter_iblk_delayed(VC1Context *v, int pq) +{ + MpegEncContext *s = &v->s; + int j; + + /* The loopfilter runs 1 row and 1 column behind the overlap filter, which + * means it runs two rows/cols behind the decoding loop. */ + if (!s->first_slice_line) { + if (s->mb_x) { + if (s->mb_y >= s->start_mb_y + 2) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); + + if (s->mb_x >= 2) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 16, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); + if (s->mb_x >= 2) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize - 8, s->uvlinesize, pq); + } + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, s->linesize, pq); + } + + if (s->mb_x == s->mb_width - 1) { + if (s->mb_y >= s->start_mb_y + 2) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + if (s->mb_x >= 2) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize, s->uvlinesize, pq); + } + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, s->linesize, pq); + } + + if (s->mb_y == s->end_mb_y) { + if (s->mb_x) { + if (s->mb_x >= 2) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 8, s->linesize, pq); + if (s->mb_x >= 2) { + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); + } + } + } + + if (s->mb_x == s->mb_width - 1) { + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); + if (s->mb_x) { + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + } + } + } + } + } +} + +void ff_vc1_smooth_overlap_filter_iblk(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int mb_pos; + + if (v->condover == CONDOVER_NONE) + return; + + mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + /* Within a MB, the horizontal overlap always runs before the vertical. + * To accomplish that, we run the H on left and internal borders of the + * currently decoded MB. Then, we wait for the next overlap iteration + * to do H overlap on the right edge of this MB, before moving over and + * running the V overlap. Therefore, the V overlap makes us trail by one + * MB col and the H overlap filter makes us trail by one MB row. This + * is reflected in the time at which we run the put_pixels loop. */ + if (v->condover == CONDOVER_ALL || v->pq >= 9 || v->over_flags_plane[mb_pos]) { + if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - 1])) { + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][1], + v->block[v->cur_blk_idx][0]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][3], + v->block[v->cur_blk_idx][2]); + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][4], + v->block[v->cur_blk_idx][4]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][5], + v->block[v->cur_blk_idx][5]); + } + } + v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][0], + v->block[v->cur_blk_idx][1]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][2], + v->block[v->cur_blk_idx][3]); + + if (s->mb_x == s->mb_width - 1) { + if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - s->mb_stride])) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][2], + v->block[v->cur_blk_idx][0]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][3], + v->block[v->cur_blk_idx][1]); + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][4], + v->block[v->cur_blk_idx][4]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][5], + v->block[v->cur_blk_idx][5]); + } + } + v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][0], + v->block[v->cur_blk_idx][2]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][1], + v->block[v->cur_blk_idx][3]); + } + } + if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos - 1])) { + if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - s->mb_stride - 1])) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][2], + v->block[v->left_blk_idx][0]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][3], + v->block[v->left_blk_idx][1]); + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][4], + v->block[v->left_blk_idx][4]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][5], + v->block[v->left_blk_idx][5]); + } + } + v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][0], + v->block[v->left_blk_idx][2]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][1], + v->block[v->left_blk_idx][3]); + } +} + +static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_num) +{ + MpegEncContext *s = &v->s; + int mb_cbp = v->cbp[s->mb_x - s->mb_stride], + block_cbp = mb_cbp >> (block_num * 4), bottom_cbp, + mb_is_intra = v->is_intra[s->mb_x - s->mb_stride], + block_is_intra = mb_is_intra >> (block_num * 4), bottom_is_intra; + int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; + uint8_t *dst; + + if (block_num > 3) { + dst = s->dest[block_num - 3]; + } else { + dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize; + } + if (s->mb_y != s->end_mb_y || block_num < 2) { + int16_t (*mv)[2]; + int mv_stride; + + if (block_num > 3) { + bottom_cbp = v->cbp[s->mb_x] >> (block_num * 4); + bottom_is_intra = v->is_intra[s->mb_x] >> block_num; + mv = &v->luma_mv[s->mb_x - s->mb_stride]; + mv_stride = s->mb_stride; + } else { + bottom_cbp = (block_num < 2) ? (mb_cbp >> ((block_num + 2) * 4)) + : (v->cbp[s->mb_x] >> ((block_num - 2) * 4)); + bottom_is_intra = (block_num < 2) ? (mb_is_intra >> (block_num + 2)) + : (v->is_intra[s->mb_x] >> (block_num - 2)); + mv_stride = s->b8_stride; + mv = &s->current_picture.motion_val[0][s->block_index[block_num] - 2 * mv_stride]; + } + + if (bottom_is_intra & 1 || block_is_intra & 1 || + mv[0][0] != mv[mv_stride][0] || mv[0][1] != mv[mv_stride][1]) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else { + idx = ((bottom_cbp >> 2) | block_cbp) & 3; + if (idx == 3) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); + else + v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); + } + } + } + + dst -= 4 * linesize; + ttblk = (v->ttblk[s->mb_x - s->mb_stride] >> (block_num * 4)) & 0xF; + if (ttblk == TT_4X4 || ttblk == TT_8X4) { + idx = (block_cbp | (block_cbp >> 2)) & 3; + if (idx == 3) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); + else + v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); + } + } +} + +static av_always_inline void vc1_apply_p_h_loop_filter(VC1Context *v, int block_num) +{ + MpegEncContext *s = &v->s; + int mb_cbp = v->cbp[s->mb_x - 1 - s->mb_stride], + block_cbp = mb_cbp >> (block_num * 4), right_cbp, + mb_is_intra = v->is_intra[s->mb_x - 1 - s->mb_stride], + block_is_intra = mb_is_intra >> block_num, right_is_intra; + int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; + uint8_t *dst; + + if (block_num > 3) { + dst = s->dest[block_num - 3] - 8 * linesize; + } else { + dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 16) * linesize - 8; + } + + if (s->mb_x != s->mb_width || !(block_num & 5)) { + int16_t (*mv)[2]; + + if (block_num > 3) { + right_cbp = v->cbp[s->mb_x - s->mb_stride] >> (block_num * 4); + right_is_intra = v->is_intra[s->mb_x - s->mb_stride] >> block_num; + mv = &v->luma_mv[s->mb_x - s->mb_stride - 1]; + } else { + right_cbp = (block_num & 1) ? (v->cbp[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) + : (mb_cbp >> ((block_num + 1) * 4)); + right_is_intra = (block_num & 1) ? (v->is_intra[s->mb_x - s->mb_stride] >> (block_num - 1)) + : (mb_is_intra >> (block_num + 1)); + mv = &s->current_picture.motion_val[0][s->block_index[block_num] - s->b8_stride * 2 - 2]; + } + if (block_is_intra & 1 || right_is_intra & 1 || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1]) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else { + idx = ((right_cbp >> 1) | block_cbp) & 5; // FIXME check + if (idx == 5) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize, linesize, v->pq); + else + v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); + } + } + } + + dst -= 4; + ttblk = (v->ttblk[s->mb_x - s->mb_stride - 1] >> (block_num * 4)) & 0xf; + if (ttblk == TT_4X4 || ttblk == TT_4X8) { + idx = (block_cbp | (block_cbp >> 1)) & 5; + if (idx == 5) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_h_loop_filter4(dst + linesize * 4, linesize, v->pq); + else + v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); + } + } +} + +void ff_vc1_apply_p_loop_filter(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int i; + + for (i = 0; i < 6; i++) { + vc1_apply_p_v_loop_filter(v, i); + } + + /* V always precedes H, therefore we run H one MB before V; + * at the end of a row, we catch up to complete the row */ + if (s->mb_x) { + for (i = 0; i < 6; i++) { + vc1_apply_p_h_loop_filter(v, i); + } + if (s->mb_x == s->mb_width - 1) { + s->mb_x++; + ff_update_block_index(s); + for (i = 0; i < 6; i++) { + vc1_apply_p_h_loop_filter(v, i); + } + } + } +} diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c new file mode 100644 index 0000000..f4632d6 --- /dev/null +++ b/libavcodec/vc1_mc.c @@ -0,0 +1,949 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * VC-1 and WMV3 block decoding routines + */ + +#include "avcodec.h" +#include "h264chroma.h" +#include "mathops.h" +#include "mpegvideo.h" +#include "vc1.h" + +/** Do motion compensation over 1 macroblock + * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c + */ +void ff_vc1_mc_1mv(VC1Context *v, int dir) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcY, *srcU, *srcV; + int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + int i; + uint8_t (*luty)[256], (*lutuv)[256]; + int use_ic; + + if ((!v->field_mode || + (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && + !v->s.last_picture.f->data[0]) + return; + + mx = s->mv[dir][0][0]; + my = s->mv[dir][0][1]; + + // store motion vectors for further use in B-frames + if (s->pict_type == AV_PICTURE_TYPE_P) { + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][1] = my; + } + } + + uvmx = (mx + ((mx & 3) == 3)) >> 1; + uvmy = (my + ((my & 3) == 3)) >> 1; + v->luma_mv[s->mb_x][0] = uvmx; + v->luma_mv[s->mb_x][1] = uvmy; + + if (v->field_mode && + v->cur_field_type != v->ref_field_type[dir]) { + my = my - 2 + 4 * v->cur_field_type; + uvmy = uvmy - 2 + 4 * v->cur_field_type; + } + + // fastuvmc shall be ignored for interlaced frame picture + if (v->fastuvmc && (v->fcm != ILACE_FRAME)) { + uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); + } + if (!dir) { + if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { + srcY = s->current_picture.f->data[0]; + srcU = s->current_picture.f->data[1]; + srcV = s->current_picture.f->data[2]; + luty = v->curr_luty; + lutuv = v->curr_lutuv; + use_ic = v->curr_use_ic; + } else { + srcY = s->last_picture.f->data[0]; + srcU = s->last_picture.f->data[1]; + srcV = s->last_picture.f->data[2]; + luty = v->last_luty; + lutuv = v->last_lutuv; + use_ic = v->last_use_ic; + } + } else { + srcY = s->next_picture.f->data[0]; + srcU = s->next_picture.f->data[1]; + srcV = s->next_picture.f->data[2]; + luty = v->next_luty; + lutuv = v->next_lutuv; + use_ic = v->next_use_ic; + } + + if (!srcY || !srcU) { + av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); + return; + } + + src_x = s->mb_x * 16 + (mx >> 2); + src_y = s->mb_y * 16 + (my >> 2); + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + srcY += src_y * s->linesize + src_x; + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode && v->ref_field_type[dir]) { + srcY += s->current_picture_ptr->f->linesize[0]; + srcU += s->current_picture_ptr->f->linesize[1]; + srcV += s->current_picture_ptr->f->linesize[2]; + } + + /* for grayscale we should not try to read from unknown area */ + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { + srcU = s->sc.edge_emu_buffer + 18 * s->linesize; + srcV = s->sc.edge_emu_buffer + 18 * s->linesize; + } + + if (v->rangeredfrm || use_ic + || s->h_edge_pos < 22 || v_edge_pos < 22 + || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 + || (unsigned)(src_y - 1) > v_edge_pos - (my&3) - 16 - 3) { + uint8_t *uvbuf = s->sc.edge_emu_buffer + 19 * s->linesize; + + srcY -= s->mspel * (1 + s->linesize); + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, + s->linesize, s->linesize, + 17 + s->mspel * 2, 17 + s->mspel * 2, + src_x - s->mspel, src_y - s->mspel, + s->h_edge_pos, v_edge_pos); + srcY = s->sc.edge_emu_buffer; + s->vdsp.emulated_edge_mc(uvbuf, srcU, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = uvbuf; + srcV = uvbuf + 16; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = ((src[i] - 128) >> 1) + 128; + src2[i] = ((src2[i] - 128) >> 1) + 128; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + /* if we deal with intensity compensation we need to scale source blocks */ + if (use_ic) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : ((j + src_y - s->mspel) & 1) ; + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = luty[f][src[i]]; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : ((j + uvsrc_y) & 1); + for (i = 0; i < 9; i++) { + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + srcY += s->mspel * (1 + s->linesize); + } + + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] , srcY , s->linesize, v->rnd); + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8, srcY + 8, s->linesize, v->rnd); + srcY += s->linesize * 8; + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8 * s->linesize , srcY , s->linesize, v->rnd); + v->vc1dsp.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) + s->hdsp.put_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16); + else + s->hdsp.put_no_rnd_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16); + } + + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + /* Chroma MC always uses qpel bilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} + +static inline int median4(int a, int b, int c, int d) +{ + if (a < b) { + if (c < d) return (FFMIN(b, d) + FFMAX(a, c)) / 2; + else return (FFMIN(b, c) + FFMAX(a, d)) / 2; + } else { + if (c < d) return (FFMIN(a, d) + FFMAX(b, c)) / 2; + else return (FFMIN(a, c) + FFMAX(b, d)) / 2; + } +} + +/** Do motion compensation for 4-MV macroblock - luminance block + */ +void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) +{ + MpegEncContext *s = &v->s; + uint8_t *srcY; + int dxy, mx, my, src_x, src_y; + int off; + int fieldmv = (v->fcm == ILACE_FRAME) ? v->blk_mv_type[s->block_index[n]] : 0; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + uint8_t (*luty)[256]; + int use_ic; + + if ((!v->field_mode || + (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && + !v->s.last_picture.f->data[0]) + return; + + mx = s->mv[dir][n][0]; + my = s->mv[dir][n][1]; + + if (!dir) { + if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { + srcY = s->current_picture.f->data[0]; + luty = v->curr_luty; + use_ic = v->curr_use_ic; + } else { + srcY = s->last_picture.f->data[0]; + luty = v->last_luty; + use_ic = v->last_use_ic; + } + } else { + srcY = s->next_picture.f->data[0]; + luty = v->next_luty; + use_ic = v->next_use_ic; + } + + if (!srcY) { + av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); + return; + } + + if (v->field_mode) { + if (v->cur_field_type != v->ref_field_type[dir]) + my = my - 2 + 4 * v->cur_field_type; + } + + if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) { + int same_count = 0, opp_count = 0, k; + int chosen_mv[2][4][2], f; + int tx = 0, ty = 0; + for (k = 0; k < 4; k++) { + f = v->mv_f[0][s->block_index[k] + v->blocks_off]; + chosen_mv[f][f ? opp_count : same_count][0] = s->mv[0][k][0]; + chosen_mv[f][f ? opp_count : same_count][1] = s->mv[0][k][1]; + opp_count += f; + same_count += 1 - f; + } + f = opp_count > same_count; + switch (f ? opp_count : same_count) { + case 4: + tx = median4(chosen_mv[f][0][0], chosen_mv[f][1][0], + chosen_mv[f][2][0], chosen_mv[f][3][0]); + ty = median4(chosen_mv[f][0][1], chosen_mv[f][1][1], + chosen_mv[f][2][1], chosen_mv[f][3][1]); + break; + case 3: + tx = mid_pred(chosen_mv[f][0][0], chosen_mv[f][1][0], chosen_mv[f][2][0]); + ty = mid_pred(chosen_mv[f][0][1], chosen_mv[f][1][1], chosen_mv[f][2][1]); + break; + case 2: + tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2; + ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2; + break; + } + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; + for (k = 0; k < 4; k++) + v->mv_f[1][s->block_index[k] + v->blocks_off] = f; + } + + if (v->fcm == ILACE_FRAME) { // not sure if needed for other types of picture + int qx, qy; + int width = s->avctx->coded_width; + int height = s->avctx->coded_height >> 1; + if (s->pict_type == AV_PICTURE_TYPE_P) { + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][1] = my; + } + qx = (s->mb_x * 16) + (mx >> 2); + qy = (s->mb_y * 8) + (my >> 3); + + if (qx < -17) + mx -= 4 * (qx + 17); + else if (qx > width) + mx -= 4 * (qx - width); + if (qy < -18) + my -= 8 * (qy + 18); + else if (qy > height + 1) + my -= 8 * (qy - height - 1); + } + + if ((v->fcm == ILACE_FRAME) && fieldmv) + off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8; + else + off = s->linesize * 4 * (n & 2) + (n & 1) * 8; + + src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2); + if (!fieldmv) + src_y = s->mb_y * 16 + (n & 2) * 4 + (my >> 2); + else + src_y = s->mb_y * 16 + ((n > 1) ? 1 : 0) + (my >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip(src_x, -16, s->mb_width * 16); + src_y = av_clip(src_y, -16, s->mb_height * 16); + } else { + src_x = av_clip(src_x, -17, s->avctx->coded_width); + if (v->fcm == ILACE_FRAME) { + if (src_y & 1) + src_y = av_clip(src_y, -17, s->avctx->coded_height + 1); + else + src_y = av_clip(src_y, -18, s->avctx->coded_height); + } else { + src_y = av_clip(src_y, -18, s->avctx->coded_height + 1); + } + } + + srcY += src_y * s->linesize + src_x; + if (v->field_mode && v->ref_field_type[dir]) + srcY += s->current_picture_ptr->f->linesize[0]; + + if (fieldmv && !(src_y & 1)) + v_edge_pos--; + if (fieldmv && (src_y & 1) && src_y < 4) + src_y--; + if (v->rangeredfrm || use_ic + || s->h_edge_pos < 13 || v_edge_pos < 23 + || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 + || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { + srcY -= s->mspel * (1 + (s->linesize << fieldmv)); + /* check emulate edge stride and offset */ + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, + s->linesize, s->linesize, + 9 + s->mspel * 2, (9 + s->mspel * 2) << fieldmv, + src_x - s->mspel, src_y - (s->mspel << fieldmv), + s->h_edge_pos, v_edge_pos); + srcY = s->sc.edge_emu_buffer; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src; + + src = srcY; + for (j = 0; j < 9 + s->mspel * 2; j++) { + for (i = 0; i < 9 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize << fieldmv; + } + } + /* if we deal with intensity compensation we need to scale source blocks */ + if (use_ic) { + int i, j; + uint8_t *src; + + src = srcY; + for (j = 0; j < 9 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[dir] : (((j<mspel << fieldmv)) & 1); + for (i = 0; i < 9 + s->mspel * 2; i++) + src[i] = luty[f][src[i]]; + src += s->linesize << fieldmv; + } + } + srcY += s->mspel * (1 + (s->linesize << fieldmv)); + } + + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + if (avg) + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + else + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + } else { // hpel mc - always used for luma + dxy = (my & 2) | ((mx & 2) >> 1); + if (!v->rnd) + s->hdsp.put_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); + else + s->hdsp.put_no_rnd_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); + } +} + +static av_always_inline int get_chroma_mv(int *mvx, int *mvy, int *a, int flag, int *tx, int *ty) +{ + int idx, i; + static const int count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; + + idx = ((a[3] != flag) << 3) + | ((a[2] != flag) << 2) + | ((a[1] != flag) << 1) + | (a[0] != flag); + if (!idx) { + *tx = median4(mvx[0], mvx[1], mvx[2], mvx[3]); + *ty = median4(mvy[0], mvy[1], mvy[2], mvy[3]); + return 4; + } else if (count[idx] == 1) { + switch (idx) { + case 0x1: + *tx = mid_pred(mvx[1], mvx[2], mvx[3]); + *ty = mid_pred(mvy[1], mvy[2], mvy[3]); + return 3; + case 0x2: + *tx = mid_pred(mvx[0], mvx[2], mvx[3]); + *ty = mid_pred(mvy[0], mvy[2], mvy[3]); + return 3; + case 0x4: + *tx = mid_pred(mvx[0], mvx[1], mvx[3]); + *ty = mid_pred(mvy[0], mvy[1], mvy[3]); + return 3; + case 0x8: + *tx = mid_pred(mvx[0], mvx[1], mvx[2]); + *ty = mid_pred(mvy[0], mvy[1], mvy[2]); + return 3; + } + } else if (count[idx] == 2) { + int t1 = 0, t2 = 0; + for (i = 0; i < 3; i++) + if (!a[i]) { + t1 = i; + break; + } + for (i = t1 + 1; i < 4; i++) + if (!a[i]) { + t2 = i; + break; + } + *tx = (mvx[t1] + mvx[t2]) / 2; + *ty = (mvy[t1] + mvy[t2]) / 2; + return 2; + } else { + return 0; + } + return -1; +} + +/** Do motion compensation for 4-MV macroblock - both chroma blocks + */ +void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcU, *srcV; + int uvmx, uvmy, uvsrc_x, uvsrc_y; + int k, tx = 0, ty = 0; + int mvx[4], mvy[4], intra[4], mv_f[4]; + int valid_count; + int chroma_ref_type = v->cur_field_type; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + uint8_t (*lutuv)[256]; + int use_ic; + + if (!v->field_mode && !v->s.last_picture.f->data[0]) + return; + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + + for (k = 0; k < 4; k++) { + mvx[k] = s->mv[dir][k][0]; + mvy[k] = s->mv[dir][k][1]; + intra[k] = v->mb_type[0][s->block_index[k]]; + if (v->field_mode) + mv_f[k] = v->mv_f[dir][s->block_index[k] + v->blocks_off]; + } + + /* calculate chroma MV vector from four luma MVs */ + if (!v->field_mode || (v->field_mode && !v->numref)) { + valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty); + chroma_ref_type = v->reffield; + if (!valid_count) { + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + return; //no need to do MC for intra blocks + } + } else { + int dominant = 0; + if (mv_f[0] + mv_f[1] + mv_f[2] + mv_f[3] > 2) + dominant = 1; + valid_count = get_chroma_mv(mvx, mvy, mv_f, dominant, &tx, &ty); + if (dominant) + chroma_ref_type = !v->cur_field_type; + } + if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0]) + return; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; + uvmx = (tx + ((tx & 3) == 3)) >> 1; + uvmy = (ty + ((ty & 3) == 3)) >> 1; + + v->luma_mv[s->mb_x][0] = uvmx; + v->luma_mv[s->mb_x][1] = uvmy; + + if (v->fastuvmc) { + uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); + } + // Field conversion bias + if (v->cur_field_type != chroma_ref_type) + uvmy += 2 - 4 * chroma_ref_type; + + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + if (!dir) { + if (v->field_mode && (v->cur_field_type != chroma_ref_type) && v->second_field) { + srcU = s->current_picture.f->data[1]; + srcV = s->current_picture.f->data[2]; + lutuv = v->curr_lutuv; + use_ic = v->curr_use_ic; + } else { + srcU = s->last_picture.f->data[1]; + srcV = s->last_picture.f->data[2]; + lutuv = v->last_lutuv; + use_ic = v->last_use_ic; + } + } else { + srcU = s->next_picture.f->data[1]; + srcV = s->next_picture.f->data[2]; + lutuv = v->next_lutuv; + use_ic = v->next_use_ic; + } + + if (!srcU) { + av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); + return; + } + + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode) { + if (chroma_ref_type) { + srcU += s->current_picture_ptr->f->linesize[1]; + srcV += s->current_picture_ptr->f->linesize[2]; + } + } + + if (v->rangeredfrm || use_ic + || s->h_edge_pos < 18 || v_edge_pos < 18 + || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 + || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = s->sc.edge_emu_buffer; + srcV = s->sc.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 (use_ic) { + int i, j; + uint8_t *src, *src2; + + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + int f = v->field_mode ? chroma_ref_type : ((j + uvsrc_y) & 1); + for (i = 0; i < 9; i++) { + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + } + + /* Chroma MC always uses qpel bilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} + +/** Do motion compensation for 4-MV interlaced frame chroma macroblock (both U and V) + */ +void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcU, *srcV; + int uvsrc_x, uvsrc_y; + int uvmx_field[4], uvmy_field[4]; + int i, off, tx, ty; + int fieldmv = v->blk_mv_type[s->block_index[0]]; + static const int s_rndtblfield[16] = { 0, 0, 1, 2, 4, 4, 5, 6, 2, 2, 3, 8, 6, 6, 7, 12 }; + int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks + int v_edge_pos = s->v_edge_pos >> 1; + int use_ic; + uint8_t (*lutuv)[256]; + + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + + for (i = 0; i < 4; i++) { + int d = i < 2 ? dir: dir2; + tx = s->mv[d][i][0]; + uvmx_field[i] = (tx + ((tx & 3) == 3)) >> 1; + ty = s->mv[d][i][1]; + if (fieldmv) + uvmy_field[i] = (ty >> 4) * 8 + s_rndtblfield[ty & 0xF]; + else + uvmy_field[i] = (ty + ((ty & 3) == 3)) >> 1; + } + + for (i = 0; i < 4; i++) { + off = (i & 1) * 4 + ((i & 2) ? v_dist * s->uvlinesize : 0); + uvsrc_x = s->mb_x * 8 + (i & 1) * 4 + (uvmx_field[i] >> 2); + uvsrc_y = s->mb_y * 8 + ((i & 2) ? v_dist : 0) + (uvmy_field[i] >> 2); + // FIXME: implement proper pull-back (see vc1cropmv.c, vc1CROPMV_ChromaPullBack()) + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + if (i < 2 ? dir : dir2) { + srcU = s->next_picture.f->data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcV = s->next_picture.f->data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + lutuv = v->next_lutuv; + use_ic = v->next_use_ic; + } else { + srcU = s->last_picture.f->data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcV = s->last_picture.f->data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + lutuv = v->last_lutuv; + use_ic = v->last_use_ic; + } + uvmx_field[i] = (uvmx_field[i] & 3) << 1; + uvmy_field[i] = (uvmy_field[i] & 3) << 1; + + if (fieldmv && !(uvsrc_y & 1)) + v_edge_pos--; + if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) + uvsrc_y--; + if (use_ic + || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv) + || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 + || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcU, + s->uvlinesize, s->uvlinesize, + 5, (5 << fieldmv), uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos); + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + 16, srcV, + s->uvlinesize, s->uvlinesize, + 5, (5 << fieldmv), uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos); + srcU = s->sc.edge_emu_buffer; + srcV = s->sc.edge_emu_buffer + 16; + + /* if we deal with intensity compensation we need to scale source blocks */ + if (use_ic) { + int i, j; + uint8_t *src, *src2; + + src = srcU; + src2 = srcV; + for (j = 0; j < 5; j++) { + int f = (uvsrc_y + (j << fieldmv)) & 1; + for (i = 0; i < 5; i++) { + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; + } + src += s->uvlinesize << fieldmv; + src2 += s->uvlinesize << fieldmv; + } + } + } + if (avg) { + if (!v->rnd) { + h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } else { + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } + } else { + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + h264chroma->put_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } + } + } +} + +/** Motion compensation for direct or interpolated blocks in B-frames + */ +void ff_vc1_interp_mc(VC1Context *v) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcY, *srcU, *srcV; + int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; + int off, off_uv; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + int use_ic = v->next_use_ic; + + if (!v->field_mode && !v->s.next_picture.f->data[0]) + return; + + mx = s->mv[1][0][0]; + my = s->mv[1][0][1]; + uvmx = (mx + ((mx & 3) == 3)) >> 1; + uvmy = (my + ((my & 3) == 3)) >> 1; + if (v->field_mode && v->cur_field_type != v->ref_field_type[1]) { + my = my - 2 + 4 * v->cur_field_type; + uvmy = uvmy - 2 + 4 * v->cur_field_type; + } + if (v->fastuvmc) { + uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1)); + } + srcY = s->next_picture.f->data[0]; + srcU = s->next_picture.f->data[1]; + srcV = s->next_picture.f->data[2]; + + src_x = s->mb_x * 16 + (mx >> 2); + src_y = s->mb_y * 16 + (my >> 2); + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + srcY += src_y * s->linesize + src_x; + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode && v->ref_field_type[1]) { + srcY += s->current_picture_ptr->f->linesize[0]; + srcU += s->current_picture_ptr->f->linesize[1]; + srcV += s->current_picture_ptr->f->linesize[2]; + } + + /* for grayscale we should not try to read from unknown area */ + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { + srcU = s->sc.edge_emu_buffer + 18 * s->linesize; + srcV = s->sc.edge_emu_buffer + 18 * s->linesize; + } + + if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || use_ic + || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3 + || (unsigned)(src_y - 1) > v_edge_pos - (my & 3) - 16 - 3) { + uint8_t *uvbuf = s->sc.edge_emu_buffer + 19 * s->linesize; + + srcY -= s->mspel * (1 + s->linesize); + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, + s->linesize, s->linesize, + 17 + s->mspel * 2, 17 + s->mspel * 2, + src_x - s->mspel, src_y - s->mspel, + s->h_edge_pos, v_edge_pos); + srcY = s->sc.edge_emu_buffer; + s->vdsp.emulated_edge_mc(uvbuf, srcU, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, + s->uvlinesize, s->uvlinesize, + 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = uvbuf; + srcV = uvbuf + 16; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = ((src[i] - 128) >> 1) + 128; + src2[i] = ((src2[i] - 128) >> 1) + 128; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + + if (use_ic) { + uint8_t (*luty )[256] = v->next_luty; + uint8_t (*lutuv)[256] = v->next_lutuv; + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + int f = v->field_mode ? v->ref_field_type[1] : ((j+src_y - s->mspel) & 1); + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = luty[f][src[i]]; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + int f = v->field_mode ? v->ref_field_type[1] : ((j+uvsrc_y) & 1); + for (i = 0; i < 9; i++) { + src[i] = lutuv[f][src[i]]; + src2[i] = lutuv[f][src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + srcY += s->mspel * (1 + s->linesize); + } + + off = 0; + off_uv = 0; + + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd); + srcY += s->linesize * 8; + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize , srcY , s->linesize, v->rnd); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd); + } else { // hpel mc + dxy = (my & 2) | ((mx & 2) >> 1); + + if (!v->rnd) + s->hdsp.avg_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16); + else + s->hdsp.avg_no_rnd_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, 16); + } + + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + /* Chroma MC always uses qpel bilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index 7d8d016..38b62f7 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -47,7 +47,7 @@ typedef enum { ONE } VC1ParseSearchState; -typedef struct { +typedef struct VC1ParseContext { ParseContext pc; VC1Context v; uint8_t prev_start_code; diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c new file mode 100644 index 0000000..25be787 --- /dev/null +++ b/libavcodec/vc1_pred.c @@ -0,0 +1,953 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * VC-1 and WMV3 block decoding routines + */ + +#include "mathops.h" +#include "mpegutils.h" +#include "mpegvideo.h" +#include "vc1.h" +#include "vc1_pred.h" +#include "vc1data.h" + +static av_always_inline int scaleforsame_x(VC1Context *v, int n /* MV */, int dir) +{ + int scaledvalue, refdist; + int scalesame1, scalesame2; + int scalezone1_x, zone1offset_x; + int table_index = dir ^ v->second_field; + + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = v->refdist; + else + refdist = dir ? v->brfd : v->frfd; + if (refdist > 3) + refdist = 3; + scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; + scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; + scalezone1_x = ff_vc1_field_mvpred_scales[table_index][3][refdist]; + zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist]; + + if (FFABS(n) > 255) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_x) + scaledvalue = (n * scalesame1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x; + else + scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x; + } + } + return av_clip(scaledvalue, -v->range_x, v->range_x - 1); +} + +static av_always_inline int scaleforsame_y(VC1Context *v, int i, int n /* MV */, int dir) +{ + int scaledvalue, refdist; + int scalesame1, scalesame2; + int scalezone1_y, zone1offset_y; + int table_index = dir ^ v->second_field; + + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = v->refdist; + else + refdist = dir ? v->brfd : v->frfd; + if (refdist > 3) + refdist = 3; + scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; + scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; + scalezone1_y = ff_vc1_field_mvpred_scales[table_index][4][refdist]; + zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist]; + + if (FFABS(n) > 63) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_y) + scaledvalue = (n * scalesame1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y; + else + scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y; + } + } + + if (v->cur_field_type && !v->ref_field_type[dir]) + return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); + else + return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); +} + +static av_always_inline int scaleforopp_x(VC1Context *v, int n /* MV */) +{ + int scalezone1_x, zone1offset_x; + int scaleopp1, scaleopp2, brfd; + int scaledvalue; + + brfd = FFMIN(v->brfd, 3); + scalezone1_x = ff_vc1_b_field_mvpred_scales[3][brfd]; + zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd]; + scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; + scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; + + if (FFABS(n) > 255) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_x) + scaledvalue = (n * scaleopp1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x; + else + scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x; + } + } + return av_clip(scaledvalue, -v->range_x, v->range_x - 1); +} + +static av_always_inline int scaleforopp_y(VC1Context *v, int n /* MV */, int dir) +{ + int scalezone1_y, zone1offset_y; + int scaleopp1, scaleopp2, brfd; + int scaledvalue; + + brfd = FFMIN(v->brfd, 3); + scalezone1_y = ff_vc1_b_field_mvpred_scales[4][brfd]; + zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd]; + scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; + scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; + + if (FFABS(n) > 63) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_y) + scaledvalue = (n * scaleopp1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y; + else + scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y; + } + } + if (v->cur_field_type && !v->ref_field_type[dir]) { + return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); + } else { + return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); + } +} + +static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */, + int dim, int dir) +{ + int brfd, scalesame; + int hpel = 1 - v->s.quarter_sample; + + n >>= hpel; + if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) { + if (dim) + n = scaleforsame_y(v, i, n, dir) << hpel; + else + n = scaleforsame_x(v, n, dir) << hpel; + return n; + } + brfd = FFMIN(v->brfd, 3); + scalesame = ff_vc1_b_field_mvpred_scales[0][brfd]; + + n = (n * scalesame >> 8) << hpel; + return n; +} + +static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, + int dim, int dir) +{ + int refdist, scaleopp; + int hpel = 1 - v->s.quarter_sample; + + n >>= hpel; + if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) { + if (dim) + n = scaleforopp_y(v, n, dir) << hpel; + else + n = scaleforopp_x(v, n) << hpel; + return n; + } + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = FFMIN(v->refdist, 3); + else + refdist = dir ? v->brfd : v->frfd; + scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist]; + + n = (n * scaleopp >> 8) << hpel; + return n; +} + +/** Predict and set motion vector + */ +void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, + int mv1, int r_x, int r_y, uint8_t* is_intra, + int pred_flag, int dir) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int16_t *A, *B, *C; + int px, py; + int sum; + int mixedmv_pic, num_samefield = 0, num_oppfield = 0; + int opposite, a_f, b_f, c_f; + int16_t field_predA[2]; + int16_t field_predB[2]; + int16_t field_predC[2]; + int a_valid, b_valid, c_valid; + int hybridmv_thresh, y_bias = 0; + + if (v->mv_mode == MV_PMODE_MIXED_MV || + ((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == MV_PMODE_MIXED_MV))) + mixedmv_pic = 1; + else + mixedmv_pic = 0; + /* scale MV difference to be quad-pel */ + dmv_x <<= 1 - s->quarter_sample; + dmv_y <<= 1 - s->quarter_sample; + + wrap = s->b8_stride; + xy = s->block_index[n]; + + if (s->mb_intra) { + s->mv[0][n][0] = s->current_picture.motion_val[0][xy + v->blocks_off][0] = 0; + s->mv[0][n][1] = s->current_picture.motion_val[0][xy + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; + if (mv1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[0][xy + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + 1 + v->blocks_off][1] = 0; + s->current_picture.motion_val[0][xy + wrap + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + wrap + v->blocks_off][1] = 0; + s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + s->current_picture.motion_val[1][xy + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0; + } + return; + } + + C = s->current_picture.motion_val[dir][xy - 1 + v->blocks_off]; + A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off]; + if (mv1) { + if (v->field_mode && mixedmv_pic) + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + else + off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2; + } else { + //in 4-MV mode different blocks have different B predictor position + switch (n) { + case 0: + off = (s->mb_x > 0) ? -1 : 1; + break; + case 1: + off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1; + break; + case 2: + off = 1; + break; + case 3: + off = -1; + } + } + B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off]; + + a_valid = !s->first_slice_line || (n == 2 || n == 3); + b_valid = a_valid && (s->mb_width > 1); + c_valid = s->mb_x || (n == 1 || n == 3); + if (v->field_mode) { + a_valid = a_valid && !is_intra[xy - wrap]; + b_valid = b_valid && !is_intra[xy - wrap + off]; + c_valid = c_valid && !is_intra[xy - 1]; + } + + if (a_valid) { + a_f = v->mv_f[dir][xy - wrap + v->blocks_off]; + num_oppfield += a_f; + num_samefield += 1 - a_f; + field_predA[0] = A[0]; + field_predA[1] = A[1]; + } else { + field_predA[0] = field_predA[1] = 0; + a_f = 0; + } + if (b_valid) { + b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; + num_oppfield += b_f; + num_samefield += 1 - b_f; + field_predB[0] = B[0]; + field_predB[1] = B[1]; + } else { + field_predB[0] = field_predB[1] = 0; + b_f = 0; + } + if (c_valid) { + c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; + num_oppfield += c_f; + num_samefield += 1 - c_f; + field_predC[0] = C[0]; + field_predC[1] = C[1]; + } else { + field_predC[0] = field_predC[1] = 0; + c_f = 0; + } + + if (v->field_mode) { + if (!v->numref) + // REFFIELD determines if the last field or the second-last field is + // to be used as reference + opposite = 1 - v->reffield; + else { + if (num_samefield <= num_oppfield) + opposite = 1 - pred_flag; + else + opposite = pred_flag; + } + } else + opposite = 0; + if (opposite) { + if (a_valid && !a_f) { + field_predA[0] = scaleforopp(v, field_predA[0], 0, dir); + field_predA[1] = scaleforopp(v, field_predA[1], 1, dir); + } + if (b_valid && !b_f) { + field_predB[0] = scaleforopp(v, field_predB[0], 0, dir); + field_predB[1] = scaleforopp(v, field_predB[1], 1, dir); + } + if (c_valid && !c_f) { + field_predC[0] = scaleforopp(v, field_predC[0], 0, dir); + field_predC[1] = scaleforopp(v, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 1; + v->ref_field_type[dir] = !v->cur_field_type; + } else { + if (a_valid && a_f) { + field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir); + field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir); + } + if (b_valid && b_f) { + field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir); + field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir); + } + if (c_valid && c_f) { + field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir); + field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 0; + v->ref_field_type[dir] = v->cur_field_type; + } + + if (a_valid) { + px = field_predA[0]; + py = field_predA[1]; + } else if (c_valid) { + px = field_predC[0]; + py = field_predC[1]; + } else if (b_valid) { + px = field_predB[0]; + py = field_predB[1]; + } else { + px = 0; + py = 0; + } + + if (num_samefield + num_oppfield > 1) { + px = mid_pred(field_predA[0], field_predB[0], field_predC[0]); + py = mid_pred(field_predA[1], field_predB[1], field_predC[1]); + } + + /* Pullback MV as specified in 8.3.5.3.4 */ + if (!v->field_mode) { + int qx, qy, X, Y; + qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0); + qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (mv1) { + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + } else { + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + } + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + + if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) { + /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */ + hybridmv_thresh = 32; + if (a_valid && c_valid) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]); + if (sum > hybridmv_thresh) { + if (get_bits1(&s->gb)) { // read HYBRIDPRED bit + px = field_predA[0]; + py = field_predA[1]; + } else { + px = field_predC[0]; + py = field_predC[1]; + } + } else { + if (is_intra[xy - 1]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - field_predC[0]) + FFABS(py - field_predC[1]); + if (sum > hybridmv_thresh) { + if (get_bits1(&s->gb)) { + px = field_predA[0]; + py = field_predA[1]; + } else { + px = field_predC[0]; + py = field_predC[1]; + } + } + } + } + } + + if (v->field_mode && v->numref) + r_y >>= 1; + if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0) + y_bias = 1; + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + y_bias; + if (mv1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + v->mv_f[dir][xy + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; + v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; + } +} + +/** Predict and set motion vector for interlaced frame picture MBs + */ +void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, + int mvn, int r_x, int r_y, uint8_t* is_intra, int dir) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int A[2], B[2], C[2]; + int px = 0, py = 0; + int a_valid = 0, b_valid = 0, c_valid = 0; + int field_a, field_b, field_c; // 0: same, 1: opposite + int total_valid, num_samefield, num_oppfield; + int pos_c, pos_b, n_adj; + + wrap = s->b8_stride; + xy = s->block_index[n]; + + if (s->mb_intra) { + s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0; + s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0; + s->current_picture.motion_val[1][xy][0] = 0; + s->current_picture.motion_val[1][xy][1] = 0; + if (mvn == 1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[0][xy + 1][0] = 0; + s->current_picture.motion_val[0][xy + 1][1] = 0; + s->current_picture.motion_val[0][xy + wrap][0] = 0; + s->current_picture.motion_val[0][xy + wrap][1] = 0; + s->current_picture.motion_val[0][xy + wrap + 1][0] = 0; + s->current_picture.motion_val[0][xy + wrap + 1][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + s->current_picture.motion_val[1][xy + 1][0] = 0; + s->current_picture.motion_val[1][xy + 1][1] = 0; + s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap][1] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][0] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][1] = 0; + } + return; + } + + off = ((n == 0) || (n == 1)) ? 1 : -1; + /* predict A */ + if (s->mb_x || (n == 1) || (n == 3)) { + if ((v->blk_mv_type[xy]) // current block (MB) has a field MV + || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV + A[0] = s->current_picture.motion_val[dir][xy - 1][0]; + A[1] = s->current_picture.motion_val[dir][xy - 1][1]; + a_valid = 1; + } else { // current block has frame mv and cand. has field MV (so average) + A[0] = (s->current_picture.motion_val[dir][xy - 1][0] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1; + A[1] = (s->current_picture.motion_val[dir][xy - 1][1] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1; + a_valid = 1; + } + if (!(n & 1) && v->is_intra[s->mb_x - 1]) { + a_valid = 0; + A[0] = A[1] = 0; + } + } else + A[0] = A[1] = 0; + /* Predict B and C */ + B[0] = B[1] = C[0] = C[1] = 0; + if (n == 0 || n == 1 || v->blk_mv_type[xy]) { + if (!s->first_slice_line) { + if (!v->is_intra[s->mb_x - s->mb_stride]) { + b_valid = 1; + n_adj = n | 2; + pos_b = s->block_index[n_adj] - 2 * wrap; + if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) { + n_adj = (n & 2) | (n & 1); + } + B[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0]; + B[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1]; + if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) { + B[0] = (B[0] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1; + B[1] = (B[1] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1; + } + } + if (s->mb_width > 1) { + if (!v->is_intra[s->mb_x - s->mb_stride + 1]) { + c_valid = 1; + n_adj = 2; + pos_c = s->block_index[2] - 2 * wrap + 2; + if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { + n_adj = n & 2; + } + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1]; + if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { + C[0] = (1 + C[0] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1; + C[1] = (1 + C[1] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1; + } + if (s->mb_x == s->mb_width - 1) { + if (!v->is_intra[s->mb_x - s->mb_stride - 1]) { + c_valid = 1; + n_adj = 3; + pos_c = s->block_index[3] - 2 * wrap - 2; + if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { + n_adj = n | 1; + } + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1]; + if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { + C[0] = (1 + C[0] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1; + C[1] = (1 + C[1] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1; + } + } else + c_valid = 0; + } + } + } + } + } else { + pos_b = s->block_index[1]; + b_valid = 1; + B[0] = s->current_picture.motion_val[dir][pos_b][0]; + B[1] = s->current_picture.motion_val[dir][pos_b][1]; + pos_c = s->block_index[0]; + c_valid = 1; + C[0] = s->current_picture.motion_val[dir][pos_c][0]; + C[1] = s->current_picture.motion_val[dir][pos_c][1]; + } + + total_valid = a_valid + b_valid + c_valid; + // check if predictor A is out of bounds + if (!s->mb_x && !(n == 1 || n == 3)) { + A[0] = A[1] = 0; + } + // check if predictor B is out of bounds + if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) { + B[0] = B[1] = C[0] = C[1] = 0; + } + if (!v->blk_mv_type[xy]) { + if (s->mb_width == 1) { + px = B[0]; + py = B[1]; + } else { + if (total_valid >= 2) { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } else if (total_valid) { + if (a_valid) { px = A[0]; py = A[1]; } + if (b_valid) { px = B[0]; py = B[1]; } + if (c_valid) { px = C[0]; py = C[1]; } + } + } + } else { + if (a_valid) + field_a = (A[1] & 4) ? 1 : 0; + else + field_a = 0; + if (b_valid) + field_b = (B[1] & 4) ? 1 : 0; + else + field_b = 0; + if (c_valid) + field_c = (C[1] & 4) ? 1 : 0; + else + field_c = 0; + + num_oppfield = field_a + field_b + field_c; + num_samefield = total_valid - num_oppfield; + if (total_valid == 3) { + if ((num_samefield == 3) || (num_oppfield == 3)) { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } else if (num_samefield >= num_oppfield) { + /* take one MV from same field set depending on priority + the check for B may not be necessary */ + px = !field_a ? A[0] : B[0]; + py = !field_a ? A[1] : B[1]; + } else { + px = field_a ? A[0] : B[0]; + py = field_a ? A[1] : B[1]; + } + } else if (total_valid == 2) { + if (num_samefield >= num_oppfield) { + if (!field_a && a_valid) { + px = A[0]; + py = A[1]; + } else if (!field_b && b_valid) { + px = B[0]; + py = B[1]; + } else if (c_valid) { + px = C[0]; + py = C[1]; + } + } else { + if (field_a && a_valid) { + px = A[0]; + py = A[1]; + } else if (field_b && b_valid) { + px = B[0]; + py = B[1]; + } + } + } else if (total_valid == 1) { + px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]); + py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]); + } + } + + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y; + if (mvn == 1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[dir][xy + 1 ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1 ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap + 1][1] = s->current_picture.motion_val[dir][xy][1]; + } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */ + s->current_picture.motion_val[dir][xy + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1][1] = s->current_picture.motion_val[dir][xy][1]; + s->mv[dir][n + 1][0] = s->mv[dir][n][0]; + s->mv[dir][n + 1][1] = s->mv[dir][n][1]; + } +} + +void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], + int direct, int mvtype) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int16_t *A, *B, *C; + int px, py; + int sum; + int r_x, r_y; + const uint8_t *is_intra = v->mb_type[0]; + + r_x = v->range_x; + r_y = v->range_y; + /* scale MV difference to be quad-pel */ + dmv_x[0] <<= 1 - s->quarter_sample; + dmv_y[0] <<= 1 - s->quarter_sample; + dmv_x[1] <<= 1 - s->quarter_sample; + dmv_y[1] <<= 1 - s->quarter_sample; + + wrap = s->b8_stride; + xy = s->block_index[0]; + + if (s->mb_intra) { + s->current_picture.motion_val[0][xy + v->blocks_off][0] = + s->current_picture.motion_val[0][xy + v->blocks_off][1] = + s->current_picture.motion_val[1][xy + v->blocks_off][0] = + s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; + return; + } + if (!v->field_mode) { + s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample); + + /* Pullback predicted motion vectors as specified in 8.4.5.4 */ + s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); + s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); + s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); + s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); + } + if (direct) { + s->current_picture.motion_val[0][xy + v->blocks_off][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][xy + v->blocks_off][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][xy + v->blocks_off][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][xy + v->blocks_off][1] = s->mv[1][0][1]; + return; + } + + if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { + C = s->current_picture.motion_val[0][xy - 2]; + A = s->current_picture.motion_val[0][xy - wrap * 2]; + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + B = s->current_picture.motion_val[0][xy - wrap * 2 + off]; + + if (!s->mb_x) C[0] = C[1] = 0; + if (!s->first_slice_line) { // predictor A is not out of bounds + if (s->mb_width == 1) { + px = A[0]; + py = A[1]; + } else { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } + } else if (s->mb_x) { // predictor C is not out of bounds + px = C[0]; + py = C[1]; + } else { + px = py = 0; + } + /* Pullback MV as specified in 8.3.5.3.4 */ + { + int qx, qy, X, Y; + if (v->profile < PROFILE_ADVANCED) { + qx = (s->mb_x << 5); + qy = (s->mb_y << 5); + X = (s->mb_width << 5) - 4; + Y = (s->mb_height << 5) - 4; + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } else { + qx = (s->mb_x << 6); + qy = (s->mb_y << 6); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + } + /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ + if (0 && !s->first_slice_line && s->mb_x) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - A[0]) + FFABS(py - A[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } else { + if (is_intra[xy - 2]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - C[0]) + FFABS(py - C[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } + } + } + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y; + } + if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { + C = s->current_picture.motion_val[1][xy - 2]; + A = s->current_picture.motion_val[1][xy - wrap * 2]; + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + B = s->current_picture.motion_val[1][xy - wrap * 2 + off]; + + if (!s->mb_x) + C[0] = C[1] = 0; + if (!s->first_slice_line) { // predictor A is not out of bounds + if (s->mb_width == 1) { + px = A[0]; + py = A[1]; + } else { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } + } else if (s->mb_x) { // predictor C is not out of bounds + px = C[0]; + py = C[1]; + } else { + px = py = 0; + } + /* Pullback MV as specified in 8.3.5.3.4 */ + { + int qx, qy, X, Y; + if (v->profile < PROFILE_ADVANCED) { + qx = (s->mb_x << 5); + qy = (s->mb_y << 5); + X = (s->mb_width << 5) - 4; + Y = (s->mb_height << 5) - 4; + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } else { + qx = (s->mb_x << 6); + qy = (s->mb_y << 6); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + } + /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ + if (0 && !s->first_slice_line && s->mb_x) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - A[0]) + FFABS(py - A[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } else { + if (is_intra[xy - 2]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - C[0]) + FFABS(py - C[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } + } + } + /* store MV using signed modulus of MV range defined in 4.11 */ + + s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y; + } + s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1]; +} + +void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, + int mv1, int *pred_flag) +{ + int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0; + MpegEncContext *s = &v->s; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + if (v->bmvtype == BMV_TYPE_DIRECT) { + int total_opp, k, f; + if (s->next_picture.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) { + s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], + v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], + v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], + v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], + v->bfraction, 1, s->quarter_sample); + + total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off] + + v->mv_f_next[0][s->block_index[1] + v->blocks_off] + + v->mv_f_next[0][s->block_index[2] + v->blocks_off] + + v->mv_f_next[0][s->block_index[3] + v->blocks_off]; + f = (total_opp > 2) ? 1 : 0; + } else { + s->mv[0][0][0] = s->mv[0][0][1] = 0; + s->mv[1][0][0] = s->mv[1][0][1] = 0; + f = 0; + } + v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f; + for (k = 0; k < 4; k++) { + s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][1] = s->mv[1][0][1]; + v->mv_f[0][s->block_index[k] + v->blocks_off] = f; + v->mv_f[1][s->block_index[k] + v->blocks_off] = f; + } + return; + } + if (v->bmvtype == BMV_TYPE_INTERPOLATED) { + ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); + ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); + return; + } + if (dir) { // backward + ff_vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); + if (n == 3 || mv1) { + ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + } + } else { // forward + ff_vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); + if (n == 3 || mv1) { + ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], 0, 1); + } + } +} diff --git a/libavcodec/vc1_pred.h b/libavcodec/vc1_pred.h new file mode 100644 index 0000000..34c9c1a --- /dev/null +++ b/libavcodec/vc1_pred.h @@ -0,0 +1,59 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VC1_PRED_H +#define AVCODEC_VC1_PRED_H + +#include "vc1.h" +#include "vc1data.h" + +void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, + int mv1, int r_x, int r_y, uint8_t* is_intra, + int pred_flag, int dir); +void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, + int mvn, int r_x, int r_y, uint8_t* is_intra, + int dir); +void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], + int direct, int mvtype); +void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, + int mv1, int *pred_flag); + +static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs) +{ + int n = bfrac; + +#if B_FRACTION_DEN==256 + if (inv) + n -= 256; + if (!qs) + return 2 * ((value * n + 255) >> 9); + return (value * n + 128) >> 8; +#else + if (inv) + n -= B_FRACTION_DEN; + if (!qs) + return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN)); + return (value * n + B_FRACTION_DEN/2) / B_FRACTION_DEN; +#endif +} + +#endif /* AVCODEC_VC1_PRED_H */ diff --git a/libavcodec/vc1data.h b/libavcodec/vc1data.h index 84e8188..79a434f 100644 --- a/libavcodec/vc1data.h +++ b/libavcodec/vc1data.h @@ -29,8 +29,10 @@ #define AVCODEC_VC1DATA_H #include + #include "libavutil/rational.h" -#include "get_bits.h" + +#include "vlc.h" /** Table for conversion between TTBLK and TTMB */ extern const int ff_vc1_ttblk_to_tt[3][8]; @@ -94,8 +96,6 @@ extern VLC ff_vc1_ac_coeff_table[8]; #define VC1_IF_MBMODE_VLC_BITS 5 //@} - -/* Denominator used for ff_vc1_bfraction_lut */ #define B_FRACTION_DEN 256 /* pre-computed scales for all bfractions and base=256 */ diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 37f5d7c..1955cea 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -26,5222 +26,21 @@ * VC-1 and WMV3 decoder */ -#include "internal.h" -#include "avcodec.h" -#include "error_resilience.h" -#include "mpeg_er.h" -#include "mpegutils.h" -#include "mpegvideo.h" -#include "h263.h" -#include "h264chroma.h" -#include "qpeldsp.h" -#include "vc1.h" -#include "vc1data.h" -#include "vc1acdata.h" -#include "msmpeg4data.h" -#include "unary.h" -#include "mathops.h" - -#undef NDEBUG -#include - -#define MB_INTRA_VLC_BITS 9 -#define DC_VLC_BITS 9 - - -// offset tables for interlaced picture MVDATA decoding -static const int offset_table1[9] = { 0, 1, 2, 4, 8, 16, 32, 64, 128 }; -static const int offset_table2[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; - -/***********************************************************************/ -/** - * @name VC-1 Bitplane decoding - * @see 8.7, p56 - * @{ - */ - -/** - * Imode types - * @{ - */ -enum Imode { - IMODE_RAW, - IMODE_NORM2, - IMODE_DIFF2, - IMODE_NORM6, - IMODE_DIFF6, - IMODE_ROWSKIP, - IMODE_COLSKIP -}; -/** @} */ //imode defines - -static void init_block_index(VC1Context *v) -{ - MpegEncContext *s = &v->s; - ff_init_block_index(s); - if (v->field_mode && !(v->second_field ^ v->tff)) { - s->dest[0] += s->current_picture_ptr->f->linesize[0]; - s->dest[1] += s->current_picture_ptr->f->linesize[1]; - s->dest[2] += s->current_picture_ptr->f->linesize[2]; - } -} - -/** @} */ //Bitplane group - -static void vc1_put_signed_blocks_clamped(VC1Context *v) -{ - MpegEncContext *s = &v->s; - int topleft_mb_pos, top_mb_pos; - int stride_y, fieldtx = 0; - int v_dist; - - /* The put pixels loop is always one MB row behind the decoding loop, - * because we can only put pixels when overlap filtering is done, and - * for filtering of the bottom edge of a MB, we need the next MB row - * present as well. - * Within the row, the put pixels loop is also one MB col behind the - * decoding loop. The reason for this is again, because for filtering - * of the right MB edge, we need the next MB present. */ - if (!s->first_slice_line) { - if (s->mb_x) { - topleft_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x - 1; - if (v->fcm == ILACE_FRAME) - fieldtx = v->fieldtx_plane[topleft_mb_pos]; - stride_y = s->linesize << fieldtx; - v_dist = (16 - fieldtx) >> (fieldtx == 0); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0], - s->dest[0] - 16 * s->linesize - 16, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][1], - s->dest[0] - 16 * s->linesize - 8, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][2], - s->dest[0] - v_dist * s->linesize - 16, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][3], - s->dest[0] - v_dist * s->linesize - 8, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][4], - s->dest[1] - 8 * s->uvlinesize - 8, - s->uvlinesize); - s->idsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][5], - s->dest[2] - 8 * s->uvlinesize - 8, - s->uvlinesize); - } - if (s->mb_x == s->mb_width - 1) { - top_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x; - if (v->fcm == ILACE_FRAME) - fieldtx = v->fieldtx_plane[top_mb_pos]; - stride_y = s->linesize << fieldtx; - v_dist = fieldtx ? 15 : 8; - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0], - s->dest[0] - 16 * s->linesize, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][1], - s->dest[0] - 16 * s->linesize + 8, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][2], - s->dest[0] - v_dist * s->linesize, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][3], - s->dest[0] - v_dist * s->linesize + 8, - stride_y); - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][4], - s->dest[1] - 8 * s->uvlinesize, - s->uvlinesize); - s->idsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][5], - s->dest[2] - 8 * s->uvlinesize, - s->uvlinesize); - } - } - -#define inc_blk_idx(idx) do { \ - idx++; \ - if (idx >= v->n_allocated_blks) \ - idx = 0; \ - } while (0) - - inc_blk_idx(v->topleft_blk_idx); - inc_blk_idx(v->top_blk_idx); - inc_blk_idx(v->left_blk_idx); - inc_blk_idx(v->cur_blk_idx); -} - -static void vc1_loop_filter_iblk(VC1Context *v, int pq) -{ - MpegEncContext *s = &v->s; - int j; - if (!s->first_slice_line) { - v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq); - if (s->mb_x) - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); - for (j = 0; j < 2; j++) { - v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq); - if (s->mb_x) - v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); - } - } - v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, pq); - - if (s->mb_y == s->end_mb_y - 1) { - if (s->mb_x) { - v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq); - v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq); - } - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq); - } -} - -static void vc1_loop_filter_iblk_delayed(VC1Context *v, int pq) -{ - MpegEncContext *s = &v->s; - int j; - - /* The loopfilter runs 1 row and 1 column behind the overlap filter, which - * means it runs two rows/cols behind the decoding loop. */ - if (!s->first_slice_line) { - if (s->mb_x) { - if (s->mb_y >= s->start_mb_y + 2) { - v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); - - if (s->mb_x >= 2) - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 16, s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 8, s->linesize, pq); - for (j = 0; j < 2; j++) { - v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); - if (s->mb_x >= 2) { - v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize - 8, s->uvlinesize, pq); - } - } - } - v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, s->linesize, pq); - } - - if (s->mb_x == s->mb_width - 1) { - if (s->mb_y >= s->start_mb_y + 2) { - v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); - - if (s->mb_x) - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize, s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 8, s->linesize, pq); - for (j = 0; j < 2; j++) { - v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); - if (s->mb_x >= 2) { - v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize, s->uvlinesize, pq); - } - } - } - v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, s->linesize, pq); - } - - if (s->mb_y == s->end_mb_y) { - if (s->mb_x) { - if (s->mb_x >= 2) - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 8, s->linesize, pq); - if (s->mb_x >= 2) { - for (j = 0; j < 2; j++) { - v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); - } - } - } - - if (s->mb_x == s->mb_width - 1) { - if (s->mb_x) - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); - v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); - if (s->mb_x) { - for (j = 0; j < 2; j++) { - v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); - } - } - } - } - } -} - -static void vc1_smooth_overlap_filter_iblk(VC1Context *v) -{ - MpegEncContext *s = &v->s; - int mb_pos; - - if (v->condover == CONDOVER_NONE) - return; - - mb_pos = s->mb_x + s->mb_y * s->mb_stride; - - /* Within a MB, the horizontal overlap always runs before the vertical. - * To accomplish that, we run the H on left and internal borders of the - * currently decoded MB. Then, we wait for the next overlap iteration - * to do H overlap on the right edge of this MB, before moving over and - * running the V overlap. Therefore, the V overlap makes us trail by one - * MB col and the H overlap filter makes us trail by one MB row. This - * is reflected in the time at which we run the put_pixels loop. */ - if (v->condover == CONDOVER_ALL || v->pq >= 9 || v->over_flags_plane[mb_pos]) { - if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 || - v->over_flags_plane[mb_pos - 1])) { - v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][1], - v->block[v->cur_blk_idx][0]); - v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][3], - v->block[v->cur_blk_idx][2]); - if (!(s->flags & CODEC_FLAG_GRAY)) { - v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][4], - v->block[v->cur_blk_idx][4]); - v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][5], - v->block[v->cur_blk_idx][5]); - } - } - v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][0], - v->block[v->cur_blk_idx][1]); - v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][2], - v->block[v->cur_blk_idx][3]); - - if (s->mb_x == s->mb_width - 1) { - if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || - v->over_flags_plane[mb_pos - s->mb_stride])) { - v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][2], - v->block[v->cur_blk_idx][0]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][3], - v->block[v->cur_blk_idx][1]); - if (!(s->flags & CODEC_FLAG_GRAY)) { - v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][4], - v->block[v->cur_blk_idx][4]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][5], - v->block[v->cur_blk_idx][5]); - } - } - v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][0], - v->block[v->cur_blk_idx][2]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][1], - v->block[v->cur_blk_idx][3]); - } - } - if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos - 1])) { - if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || - v->over_flags_plane[mb_pos - s->mb_stride - 1])) { - v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][2], - v->block[v->left_blk_idx][0]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][3], - v->block[v->left_blk_idx][1]); - if (!(s->flags & CODEC_FLAG_GRAY)) { - v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][4], - v->block[v->left_blk_idx][4]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][5], - v->block[v->left_blk_idx][5]); - } - } - v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][0], - v->block[v->left_blk_idx][2]); - v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][1], - v->block[v->left_blk_idx][3]); - } -} - -/** Do motion compensation over 1 macroblock - * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c - */ -static void vc1_mc_1mv(VC1Context *v, int dir) -{ - MpegEncContext *s = &v->s; - H264ChromaContext *h264chroma = &v->h264chroma; - uint8_t *srcY, *srcU, *srcV; - int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; - int v_edge_pos = s->v_edge_pos >> v->field_mode; - int i; - uint8_t (*luty)[256], (*lutuv)[256]; - int use_ic; - - if ((!v->field_mode || - (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && - !v->s.last_picture.f->data[0]) - return; - - mx = s->mv[dir][0][0]; - my = s->mv[dir][0][1]; - - // store motion vectors for further use in B frames - if (s->pict_type == AV_PICTURE_TYPE_P) { - for (i = 0; i < 4; i++) { - s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx; - s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][1] = my; - } - } - - uvmx = (mx + ((mx & 3) == 3)) >> 1; - uvmy = (my + ((my & 3) == 3)) >> 1; - v->luma_mv[s->mb_x][0] = uvmx; - v->luma_mv[s->mb_x][1] = uvmy; - - if (v->field_mode && - v->cur_field_type != v->ref_field_type[dir]) { - my = my - 2 + 4 * v->cur_field_type; - uvmy = uvmy - 2 + 4 * v->cur_field_type; - } - - // fastuvmc shall be ignored for interlaced frame picture - if (v->fastuvmc && (v->fcm != ILACE_FRAME)) { - uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); - uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); - } - if (!dir) { - if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { - srcY = s->current_picture.f->data[0]; - srcU = s->current_picture.f->data[1]; - srcV = s->current_picture.f->data[2]; - luty = v->curr_luty; - lutuv = v->curr_lutuv; - use_ic = v->curr_use_ic; - } else { - srcY = s->last_picture.f->data[0]; - srcU = s->last_picture.f->data[1]; - srcV = s->last_picture.f->data[2]; - luty = v->last_luty; - lutuv = v->last_lutuv; - use_ic = v->last_use_ic; - } - } else { - srcY = s->next_picture.f->data[0]; - srcU = s->next_picture.f->data[1]; - srcV = s->next_picture.f->data[2]; - luty = v->next_luty; - lutuv = v->next_lutuv; - use_ic = v->next_use_ic; - } - - if (!srcY || !srcU) { - av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); - return; - } - - src_x = s->mb_x * 16 + (mx >> 2); - src_y = s->mb_y * 16 + (my >> 2); - uvsrc_x = s->mb_x * 8 + (uvmx >> 2); - uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - - if (v->profile != PROFILE_ADVANCED) { - src_x = av_clip( src_x, -16, s->mb_width * 16); - src_y = av_clip( src_y, -16, s->mb_height * 16); - uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); - } else { - src_x = av_clip( src_x, -17, s->avctx->coded_width); - src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); - uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); - uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); - } - - srcY += src_y * s->linesize + src_x; - srcU += uvsrc_y * s->uvlinesize + uvsrc_x; - srcV += uvsrc_y * s->uvlinesize + uvsrc_x; - - if (v->field_mode && v->ref_field_type[dir]) { - srcY += s->current_picture_ptr->f->linesize[0]; - srcU += s->current_picture_ptr->f->linesize[1]; - srcV += s->current_picture_ptr->f->linesize[2]; - } - - /* for grayscale we should not try to read from unknown area */ - if (s->flags & CODEC_FLAG_GRAY) { - srcU = s->edge_emu_buffer + 18 * s->linesize; - srcV = s->edge_emu_buffer + 18 * s->linesize; - } - - if (v->rangeredfrm || use_ic - || s->h_edge_pos < 22 || v_edge_pos < 22 - || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 - || (unsigned)(src_y - 1) > v_edge_pos - (my&3) - 16 - 3) { - uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; - - srcY -= s->mspel * (1 + s->linesize); - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, - s->linesize, s->linesize, - 17 + s->mspel * 2, 17 + s->mspel * 2, - src_x - s->mspel, src_y - s->mspel, - s->h_edge_pos, v_edge_pos); - srcY = s->edge_emu_buffer; - s->vdsp.emulated_edge_mc(uvbuf, srcU, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, - uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, - uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); - srcU = uvbuf; - srcV = uvbuf + 16; - /* if we deal with range reduction we need to scale source blocks */ - if (v->rangeredfrm) { - int i, j; - uint8_t *src, *src2; - - src = srcY; - for (j = 0; j < 17 + s->mspel * 2; j++) { - for (i = 0; i < 17 + s->mspel * 2; i++) - src[i] = ((src[i] - 128) >> 1) + 128; - src += s->linesize; - } - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - for (i = 0; i < 9; i++) { - src[i] = ((src[i] - 128) >> 1) + 128; - src2[i] = ((src2[i] - 128) >> 1) + 128; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - /* if we deal with intensity compensation we need to scale source blocks */ - if (use_ic) { - int i, j; - uint8_t *src, *src2; - - src = srcY; - for (j = 0; j < 17 + s->mspel * 2; j++) { - int f = v->field_mode ? v->ref_field_type[dir] : ((j + src_y - s->mspel) & 1) ; - for (i = 0; i < 17 + s->mspel * 2; i++) - src[i] = luty[f][src[i]]; - src += s->linesize; - } - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - int f = v->field_mode ? v->ref_field_type[dir] : ((j + uvsrc_y) & 1); - for (i = 0; i < 9; i++) { - src[i] = lutuv[f][src[i]]; - src2[i] = lutuv[f][src2[i]]; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - srcY += s->mspel * (1 + s->linesize); - } - - if (s->mspel) { - dxy = ((my & 3) << 2) | (mx & 3); - v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] , srcY , s->linesize, v->rnd); - v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8, srcY + 8, s->linesize, v->rnd); - srcY += s->linesize * 8; - v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8 * s->linesize , srcY , s->linesize, v->rnd); - v->vc1dsp.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) - s->hdsp.put_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16); - else - s->hdsp.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 */ - uvmx = (uvmx & 3) << 1; - uvmy = (uvmy & 3) << 1; - if (!v->rnd) { - h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); - h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); - } else { - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); - } -} - -static inline int median4(int a, int b, int c, int d) -{ - if (a < b) { - if (c < d) return (FFMIN(b, d) + FFMAX(a, c)) / 2; - else return (FFMIN(b, c) + FFMAX(a, d)) / 2; - } else { - if (c < d) return (FFMIN(a, d) + FFMAX(b, c)) / 2; - else return (FFMIN(a, c) + FFMAX(b, d)) / 2; - } -} - -/** Do motion compensation for 4-MV macroblock - luminance block - */ -static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) -{ - MpegEncContext *s = &v->s; - uint8_t *srcY; - int dxy, mx, my, src_x, src_y; - int off; - int fieldmv = (v->fcm == ILACE_FRAME) ? v->blk_mv_type[s->block_index[n]] : 0; - int v_edge_pos = s->v_edge_pos >> v->field_mode; - uint8_t (*luty)[256]; - int use_ic; - - if ((!v->field_mode || - (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && - !v->s.last_picture.f->data[0]) - return; - - mx = s->mv[dir][n][0]; - my = s->mv[dir][n][1]; - - if (!dir) { - if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { - srcY = s->current_picture.f->data[0]; - luty = v->curr_luty; - use_ic = v->curr_use_ic; - } else { - srcY = s->last_picture.f->data[0]; - luty = v->last_luty; - use_ic = v->last_use_ic; - } - } else { - srcY = s->next_picture.f->data[0]; - luty = v->next_luty; - use_ic = v->next_use_ic; - } - - if (!srcY) { - av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); - return; - } - - if (v->field_mode) { - if (v->cur_field_type != v->ref_field_type[dir]) - my = my - 2 + 4 * v->cur_field_type; - } - - if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) { - int same_count = 0, opp_count = 0, k; - int chosen_mv[2][4][2], f; - int tx, ty; - for (k = 0; k < 4; k++) { - f = v->mv_f[0][s->block_index[k] + v->blocks_off]; - chosen_mv[f][f ? opp_count : same_count][0] = s->mv[0][k][0]; - chosen_mv[f][f ? opp_count : same_count][1] = s->mv[0][k][1]; - opp_count += f; - same_count += 1 - f; - } - f = opp_count > same_count; - switch (f ? opp_count : same_count) { - case 4: - tx = median4(chosen_mv[f][0][0], chosen_mv[f][1][0], - chosen_mv[f][2][0], chosen_mv[f][3][0]); - ty = median4(chosen_mv[f][0][1], chosen_mv[f][1][1], - chosen_mv[f][2][1], chosen_mv[f][3][1]); - break; - case 3: - tx = mid_pred(chosen_mv[f][0][0], chosen_mv[f][1][0], chosen_mv[f][2][0]); - ty = mid_pred(chosen_mv[f][0][1], chosen_mv[f][1][1], chosen_mv[f][2][1]); - break; - case 2: - tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2; - ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2; - break; - } - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; - for (k = 0; k < 4; k++) - v->mv_f[1][s->block_index[k] + v->blocks_off] = f; - } - - if (v->fcm == ILACE_FRAME) { // not sure if needed for other types of picture - int qx, qy; - int width = s->avctx->coded_width; - int height = s->avctx->coded_height >> 1; - if (s->pict_type == AV_PICTURE_TYPE_P) { - s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][0] = mx; - s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][1] = my; - } - qx = (s->mb_x * 16) + (mx >> 2); - qy = (s->mb_y * 8) + (my >> 3); - - if (qx < -17) - mx -= 4 * (qx + 17); - else if (qx > width) - mx -= 4 * (qx - width); - if (qy < -18) - my -= 8 * (qy + 18); - else if (qy > height + 1) - my -= 8 * (qy - height - 1); - } - - if ((v->fcm == ILACE_FRAME) && fieldmv) - off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8; - else - off = s->linesize * 4 * (n & 2) + (n & 1) * 8; - - src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2); - if (!fieldmv) - src_y = s->mb_y * 16 + (n & 2) * 4 + (my >> 2); - else - src_y = s->mb_y * 16 + ((n > 1) ? 1 : 0) + (my >> 2); - - if (v->profile != PROFILE_ADVANCED) { - src_x = av_clip(src_x, -16, s->mb_width * 16); - src_y = av_clip(src_y, -16, s->mb_height * 16); - } else { - src_x = av_clip(src_x, -17, s->avctx->coded_width); - if (v->fcm == ILACE_FRAME) { - if (src_y & 1) - src_y = av_clip(src_y, -17, s->avctx->coded_height + 1); - else - src_y = av_clip(src_y, -18, s->avctx->coded_height); - } else { - src_y = av_clip(src_y, -18, s->avctx->coded_height + 1); - } - } - - srcY += src_y * s->linesize + src_x; - if (v->field_mode && v->ref_field_type[dir]) - srcY += s->current_picture_ptr->f->linesize[0]; - - if (fieldmv && !(src_y & 1)) - v_edge_pos--; - if (fieldmv && (src_y & 1) && src_y < 4) - src_y--; - if (v->rangeredfrm || use_ic - || s->h_edge_pos < 13 || v_edge_pos < 23 - || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 - || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { - srcY -= s->mspel * (1 + (s->linesize << fieldmv)); - /* check emulate edge stride and offset */ - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, - s->linesize, s->linesize, - 9 + s->mspel * 2, (9 + s->mspel * 2) << fieldmv, - src_x - s->mspel, src_y - (s->mspel << fieldmv), - s->h_edge_pos, v_edge_pos); - srcY = s->edge_emu_buffer; - /* if we deal with range reduction we need to scale source blocks */ - if (v->rangeredfrm) { - int i, j; - uint8_t *src; - - src = srcY; - for (j = 0; j < 9 + s->mspel * 2; j++) { - for (i = 0; i < 9 + s->mspel * 2; i++) - src[i] = ((src[i] - 128) >> 1) + 128; - src += s->linesize << fieldmv; - } - } - /* if we deal with intensity compensation we need to scale source blocks */ - if (use_ic) { - int i, j; - uint8_t *src; - - src = srcY; - for (j = 0; j < 9 + s->mspel * 2; j++) { - int f = v->field_mode ? v->ref_field_type[dir] : (((j<mspel << fieldmv)) & 1); - for (i = 0; i < 9 + s->mspel * 2; i++) - src[i] = luty[f][src[i]]; - src += s->linesize << fieldmv; - } - } - srcY += s->mspel * (1 + (s->linesize << fieldmv)); - } - - if (s->mspel) { - dxy = ((my & 3) << 2) | (mx & 3); - if (avg) - v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); - else - v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); - } else { // hpel mc - always used for luma - dxy = (my & 2) | ((mx & 2) >> 1); - if (!v->rnd) - s->hdsp.put_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); - else - s->hdsp.put_no_rnd_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); - } -} - -static av_always_inline int get_chroma_mv(int *mvx, int *mvy, int *a, int flag, int *tx, int *ty) -{ - int idx, i; - static const int count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; - - idx = ((a[3] != flag) << 3) - | ((a[2] != flag) << 2) - | ((a[1] != flag) << 1) - | (a[0] != flag); - if (!idx) { - *tx = median4(mvx[0], mvx[1], mvx[2], mvx[3]); - *ty = median4(mvy[0], mvy[1], mvy[2], mvy[3]); - return 4; - } else if (count[idx] == 1) { - switch (idx) { - case 0x1: - *tx = mid_pred(mvx[1], mvx[2], mvx[3]); - *ty = mid_pred(mvy[1], mvy[2], mvy[3]); - return 3; - case 0x2: - *tx = mid_pred(mvx[0], mvx[2], mvx[3]); - *ty = mid_pred(mvy[0], mvy[2], mvy[3]); - return 3; - case 0x4: - *tx = mid_pred(mvx[0], mvx[1], mvx[3]); - *ty = mid_pred(mvy[0], mvy[1], mvy[3]); - return 3; - case 0x8: - *tx = mid_pred(mvx[0], mvx[1], mvx[2]); - *ty = mid_pred(mvy[0], mvy[1], mvy[2]); - return 3; - } - } else if (count[idx] == 2) { - int t1 = 0, t2 = 0; - for (i = 0; i < 3; i++) - if (!a[i]) { - t1 = i; - break; - } - for (i = t1 + 1; i < 4; i++) - if (!a[i]) { - t2 = i; - break; - } - *tx = (mvx[t1] + mvx[t2]) / 2; - *ty = (mvy[t1] + mvy[t2]) / 2; - return 2; - } else { - return 0; - } - return -1; -} - -/** Do motion compensation for 4-MV macroblock - both chroma blocks - */ -static void vc1_mc_4mv_chroma(VC1Context *v, int dir) -{ - MpegEncContext *s = &v->s; - H264ChromaContext *h264chroma = &v->h264chroma; - uint8_t *srcU, *srcV; - int uvmx, uvmy, uvsrc_x, uvsrc_y; - int k, tx = 0, ty = 0; - int mvx[4], mvy[4], intra[4], mv_f[4]; - int valid_count; - int chroma_ref_type = v->cur_field_type; - int v_edge_pos = s->v_edge_pos >> v->field_mode; - uint8_t (*lutuv)[256]; - int use_ic; - - if (!v->field_mode && !v->s.last_picture.f->data[0]) - return; - if (s->flags & CODEC_FLAG_GRAY) - return; - - for (k = 0; k < 4; k++) { - mvx[k] = s->mv[dir][k][0]; - mvy[k] = s->mv[dir][k][1]; - intra[k] = v->mb_type[0][s->block_index[k]]; - if (v->field_mode) - mv_f[k] = v->mv_f[dir][s->block_index[k] + v->blocks_off]; - } - - /* calculate chroma MV vector from four luma MVs */ - if (!v->field_mode || (v->field_mode && !v->numref)) { - valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty); - chroma_ref_type = v->reffield; - if (!valid_count) { - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; - v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; - return; //no need to do MC for intra blocks - } - } else { - int dominant = 0; - if (mv_f[0] + mv_f[1] + mv_f[2] + mv_f[3] > 2) - dominant = 1; - valid_count = get_chroma_mv(mvx, mvy, mv_f, dominant, &tx, &ty); - if (dominant) - chroma_ref_type = !v->cur_field_type; - } - if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0]) - return; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; - uvmx = (tx + ((tx & 3) == 3)) >> 1; - uvmy = (ty + ((ty & 3) == 3)) >> 1; - - v->luma_mv[s->mb_x][0] = uvmx; - v->luma_mv[s->mb_x][1] = uvmy; - - if (v->fastuvmc) { - uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); - uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); - } - // Field conversion bias - if (v->cur_field_type != chroma_ref_type) - uvmy += 2 - 4 * chroma_ref_type; - - uvsrc_x = s->mb_x * 8 + (uvmx >> 2); - uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - - if (v->profile != PROFILE_ADVANCED) { - uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); - } else { - uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); - uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); - } - - if (!dir) { - if (v->field_mode && (v->cur_field_type != chroma_ref_type) && v->second_field) { - srcU = s->current_picture.f->data[1]; - srcV = s->current_picture.f->data[2]; - lutuv = v->curr_lutuv; - use_ic = v->curr_use_ic; - } else { - srcU = s->last_picture.f->data[1]; - srcV = s->last_picture.f->data[2]; - lutuv = v->last_lutuv; - use_ic = v->last_use_ic; - } - } else { - srcU = s->next_picture.f->data[1]; - srcV = s->next_picture.f->data[2]; - lutuv = v->next_lutuv; - use_ic = v->next_use_ic; - } - - if (!srcU) { - av_log(v->s.avctx, AV_LOG_ERROR, "Referenced frame missing.\n"); - return; - } - - srcU += uvsrc_y * s->uvlinesize + uvsrc_x; - srcV += uvsrc_y * s->uvlinesize + uvsrc_x; - - if (v->field_mode) { - if (chroma_ref_type) { - srcU += s->current_picture_ptr->f->linesize[1]; - srcV += s->current_picture_ptr->f->linesize[2]; - } - } - - if (v->rangeredfrm || use_ic - || s->h_edge_pos < 18 || v_edge_pos < 18 - || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 - || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcU, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(s->edge_emu_buffer + 16, srcV, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, v_edge_pos >> 1); - srcU = s->edge_emu_buffer; - srcV = s->edge_emu_buffer + 16; - - /* if we deal with range reduction we need to scale source blocks */ - if (v->rangeredfrm) { - int i, j; - uint8_t *src, *src2; - - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - for (i = 0; i < 9; i++) { - src[i] = ((src[i] - 128) >> 1) + 128; - src2[i] = ((src2[i] - 128) >> 1) + 128; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - /* if we deal with intensity compensation we need to scale source blocks */ - if (use_ic) { - int i, j; - uint8_t *src, *src2; - - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - int f = v->field_mode ? chroma_ref_type : ((j + uvsrc_y) & 1); - for (i = 0; i < 9; i++) { - src[i] = lutuv[f][src[i]]; - src2[i] = lutuv[f][src2[i]]; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - } - - /* Chroma MC always uses qpel bilinear */ - uvmx = (uvmx & 3) << 1; - uvmy = (uvmy & 3) << 1; - if (!v->rnd) { - h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); - h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); - } else { - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy); - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); - } -} - -/** Do motion compensation for 4-MV interlaced frame chroma macroblock (both U and V) - */ -static void vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) -{ - MpegEncContext *s = &v->s; - H264ChromaContext *h264chroma = &v->h264chroma; - uint8_t *srcU, *srcV; - int uvsrc_x, uvsrc_y; - int uvmx_field[4], uvmy_field[4]; - int i, off, tx, ty; - int fieldmv = v->blk_mv_type[s->block_index[0]]; - static const int s_rndtblfield[16] = { 0, 0, 1, 2, 4, 4, 5, 6, 2, 2, 3, 8, 6, 6, 7, 12 }; - int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks - int v_edge_pos = s->v_edge_pos >> 1; - int use_ic; - uint8_t (*lutuv)[256]; - - if (s->flags & CODEC_FLAG_GRAY) - return; - - for (i = 0; i < 4; i++) { - int d = i < 2 ? dir: dir2; - tx = s->mv[d][i][0]; - uvmx_field[i] = (tx + ((tx & 3) == 3)) >> 1; - ty = s->mv[d][i][1]; - if (fieldmv) - uvmy_field[i] = (ty >> 4) * 8 + s_rndtblfield[ty & 0xF]; - else - uvmy_field[i] = (ty + ((ty & 3) == 3)) >> 1; - } - - for (i = 0; i < 4; i++) { - off = (i & 1) * 4 + ((i & 2) ? v_dist * s->uvlinesize : 0); - uvsrc_x = s->mb_x * 8 + (i & 1) * 4 + (uvmx_field[i] >> 2); - uvsrc_y = s->mb_y * 8 + ((i & 2) ? v_dist : 0) + (uvmy_field[i] >> 2); - // FIXME: implement proper pull-back (see vc1cropmv.c, vc1CROPMV_ChromaPullBack()) - uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); - uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); - if (i < 2 ? dir : dir2) { - srcU = s->next_picture.f->data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->next_picture.f->data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; - lutuv = v->next_lutuv; - use_ic = v->next_use_ic; - } else { - srcU = s->last_picture.f->data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; - srcV = s->last_picture.f->data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; - lutuv = v->last_lutuv; - use_ic = v->last_use_ic; - } - uvmx_field[i] = (uvmx_field[i] & 3) << 1; - uvmy_field[i] = (uvmy_field[i] & 3) << 1; - - if (fieldmv && !(uvsrc_y & 1)) - v_edge_pos--; - if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) - uvsrc_y--; - if (use_ic - || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv) - || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 - || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcU, - s->uvlinesize, s->uvlinesize, - 5, (5 << fieldmv), uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, v_edge_pos); - s->vdsp.emulated_edge_mc(s->edge_emu_buffer + 16, srcV, - s->uvlinesize, s->uvlinesize, - 5, (5 << fieldmv), uvsrc_x, uvsrc_y, - s->h_edge_pos >> 1, v_edge_pos); - srcU = s->edge_emu_buffer; - srcV = s->edge_emu_buffer + 16; - - /* if we deal with intensity compensation we need to scale source blocks */ - if (use_ic) { - int i, j; - uint8_t *src, *src2; - - src = srcU; - src2 = srcV; - for (j = 0; j < 5; j++) { - int f = (uvsrc_y + (j << fieldmv)) & 1; - for (i = 0; i < 5; i++) { - src[i] = lutuv[f][src[i]]; - src2[i] = lutuv[f][src2[i]]; - } - src += s->uvlinesize << fieldmv; - src2 += s->uvlinesize << fieldmv; - } - } - } - if (avg) { - if (!v->rnd) { - h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - h264chroma->avg_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - } else { - v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - } - } else { - if (!v->rnd) { - h264chroma->put_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - h264chroma->put_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - } else { - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); - } - } - } -} - -/***********************************************************************/ -/** - * @name VC-1 Block-level functions - * @see 7.1.4, p91 and 8.1.1.7, p(1)04 - * @{ - */ - -/** - * @def GET_MQUANT - * @brief Get macroblock-level quantizer scale - */ -#define GET_MQUANT() \ - if (v->dquantfrm) { \ - int edges = 0; \ - if (v->dqprofile == DQPROFILE_ALL_MBS) { \ - if (v->dqbilevel) { \ - mquant = (get_bits1(gb)) ? v->altpq : v->pq; \ - } else { \ - mqdiff = get_bits(gb, 3); \ - if (mqdiff != 7) \ - mquant = v->pq + mqdiff; \ - else \ - mquant = get_bits(gb, 5); \ - } \ - } \ - if (v->dqprofile == DQPROFILE_SINGLE_EDGE) \ - edges = 1 << v->dqsbedge; \ - else if (v->dqprofile == DQPROFILE_DOUBLE_EDGES) \ - edges = (3 << v->dqsbedge) % 15; \ - else if (v->dqprofile == DQPROFILE_FOUR_EDGES) \ - edges = 15; \ - if ((edges&1) && !s->mb_x) \ - mquant = v->altpq; \ - if ((edges&2) && s->first_slice_line) \ - mquant = v->altpq; \ - if ((edges&4) && s->mb_x == (s->mb_width - 1)) \ - mquant = v->altpq; \ - if ((edges&8) && s->mb_y == (s->mb_height - 1)) \ - mquant = v->altpq; \ - if (!mquant || mquant > 31) { \ - av_log(v->s.avctx, AV_LOG_ERROR, \ - "Overriding invalid mquant %d\n", mquant); \ - mquant = 1; \ - } \ - } - -/** - * @def GET_MVDATA(_dmv_x, _dmv_y) - * @brief Get MV differentials - * @see MVDATA decoding from 8.3.5.2, p(1)20 - * @param _dmv_x Horizontal differential for decoded MV - * @param _dmv_y Vertical differential for decoded MV - */ -#define GET_MVDATA(_dmv_x, _dmv_y) \ - index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index].table, \ - VC1_MV_DIFF_VLC_BITS, 2); \ - if (index > 36) { \ - mb_has_coeffs = 1; \ - index -= 37; \ - } else \ - mb_has_coeffs = 0; \ - s->mb_intra = 0; \ - if (!index) { \ - _dmv_x = _dmv_y = 0; \ - } else if (index == 35) { \ - _dmv_x = get_bits(gb, v->k_x - 1 + s->quarter_sample); \ - _dmv_y = get_bits(gb, v->k_y - 1 + s->quarter_sample); \ - } else if (index == 36) { \ - _dmv_x = 0; \ - _dmv_y = 0; \ - s->mb_intra = 1; \ - } else { \ - index1 = index % 6; \ - if (!s->quarter_sample && index1 == 5) val = 1; \ - else val = 0; \ - if (size_table[index1] - val > 0) \ - val = get_bits(gb, size_table[index1] - val); \ - else val = 0; \ - sign = 0 - (val&1); \ - _dmv_x = (sign ^ ((val>>1) + offset_table[index1])) - sign; \ - \ - index1 = index / 6; \ - if (!s->quarter_sample && index1 == 5) val = 1; \ - else val = 0; \ - if (size_table[index1] - val > 0) \ - val = get_bits(gb, size_table[index1] - val); \ - else val = 0; \ - sign = 0 - (val & 1); \ - _dmv_y = (sign ^ ((val >> 1) + offset_table[index1])) - sign; \ - } - -static av_always_inline void get_mvdata_interlaced(VC1Context *v, int *dmv_x, - int *dmv_y, int *pred_flag) -{ - int index, index1; - int extend_x = 0, extend_y = 0; - GetBitContext *gb = &v->s.gb; - int bits, esc; - int val, sign; - const int* offs_tab; - - if (v->numref) { - bits = VC1_2REF_MVDATA_VLC_BITS; - esc = 125; - } else { - bits = VC1_1REF_MVDATA_VLC_BITS; - esc = 71; - } - switch (v->dmvrange) { - case 1: - extend_x = 1; - break; - case 2: - extend_y = 1; - break; - case 3: - extend_x = extend_y = 1; - break; - } - index = get_vlc2(gb, v->imv_vlc->table, bits, 3); - if (index == esc) { - *dmv_x = get_bits(gb, v->k_x); - *dmv_y = get_bits(gb, v->k_y); - if (v->numref) { - if (pred_flag) { - *pred_flag = *dmv_y & 1; - *dmv_y = (*dmv_y + *pred_flag) >> 1; - } else { - *dmv_y = (*dmv_y + (*dmv_y & 1)) >> 1; - } - } - } - else { - if (extend_x) - offs_tab = offset_table2; - else - offs_tab = offset_table1; - index1 = (index + 1) % 9; - if (index1 != 0) { - val = get_bits(gb, index1 + extend_x); - sign = 0 -(val & 1); - *dmv_x = (sign ^ ((val >> 1) + offs_tab[index1])) - sign; - } else - *dmv_x = 0; - if (extend_y) - offs_tab = offset_table2; - else - offs_tab = offset_table1; - index1 = (index + 1) / 9; - if (index1 > v->numref) { - val = get_bits(gb, (index1 + (extend_y << v->numref)) >> v->numref); - sign = 0 - (val & 1); - *dmv_y = (sign ^ ((val >> 1) + offs_tab[index1 >> v->numref])) - sign; - } else - *dmv_y = 0; - if (v->numref && pred_flag) - *pred_flag = index1 & 1; - } -} - -static av_always_inline int scaleforsame_x(VC1Context *v, int n /* MV */, int dir) -{ - int scaledvalue, refdist; - int scalesame1, scalesame2; - int scalezone1_x, zone1offset_x; - int table_index = dir ^ v->second_field; - - if (v->s.pict_type != AV_PICTURE_TYPE_B) - refdist = v->refdist; - else - refdist = dir ? v->brfd : v->frfd; - if (refdist > 3) - refdist = 3; - scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; - scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; - scalezone1_x = ff_vc1_field_mvpred_scales[table_index][3][refdist]; - zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist]; - - if (FFABS(n) > 255) - scaledvalue = n; - else { - if (FFABS(n) < scalezone1_x) - scaledvalue = (n * scalesame1) >> 8; - else { - if (n < 0) - scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x; - else - scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x; - } - } - return av_clip(scaledvalue, -v->range_x, v->range_x - 1); -} - -static av_always_inline int scaleforsame_y(VC1Context *v, int i, int n /* MV */, int dir) -{ - int scaledvalue, refdist; - int scalesame1, scalesame2; - int scalezone1_y, zone1offset_y; - int table_index = dir ^ v->second_field; - - if (v->s.pict_type != AV_PICTURE_TYPE_B) - refdist = v->refdist; - else - refdist = dir ? v->brfd : v->frfd; - if (refdist > 3) - refdist = 3; - scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; - scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; - scalezone1_y = ff_vc1_field_mvpred_scales[table_index][4][refdist]; - zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist]; - - if (FFABS(n) > 63) - scaledvalue = n; - else { - if (FFABS(n) < scalezone1_y) - scaledvalue = (n * scalesame1) >> 8; - else { - if (n < 0) - scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y; - else - scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y; - } - } - - if (v->cur_field_type && !v->ref_field_type[dir]) - return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); - else - return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); -} - -static av_always_inline int scaleforopp_x(VC1Context *v, int n /* MV */) -{ - int scalezone1_x, zone1offset_x; - int scaleopp1, scaleopp2, brfd; - int scaledvalue; - - brfd = FFMIN(v->brfd, 3); - scalezone1_x = ff_vc1_b_field_mvpred_scales[3][brfd]; - zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd]; - scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; - scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; - - if (FFABS(n) > 255) - scaledvalue = n; - else { - if (FFABS(n) < scalezone1_x) - scaledvalue = (n * scaleopp1) >> 8; - else { - if (n < 0) - scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x; - else - scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x; - } - } - return av_clip(scaledvalue, -v->range_x, v->range_x - 1); -} - -static av_always_inline int scaleforopp_y(VC1Context *v, int n /* MV */, int dir) -{ - int scalezone1_y, zone1offset_y; - int scaleopp1, scaleopp2, brfd; - int scaledvalue; - - brfd = FFMIN(v->brfd, 3); - scalezone1_y = ff_vc1_b_field_mvpred_scales[4][brfd]; - zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd]; - scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; - scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; - - if (FFABS(n) > 63) - scaledvalue = n; - else { - if (FFABS(n) < scalezone1_y) - scaledvalue = (n * scaleopp1) >> 8; - else { - if (n < 0) - scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y; - else - scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y; - } - } - if (v->cur_field_type && !v->ref_field_type[dir]) { - return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); - } else { - return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); - } -} - -static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */, - int dim, int dir) -{ - int brfd, scalesame; - int hpel = 1 - v->s.quarter_sample; - - n >>= hpel; - if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) { - if (dim) - n = scaleforsame_y(v, i, n, dir) << hpel; - else - n = scaleforsame_x(v, n, dir) << hpel; - return n; - } - brfd = FFMIN(v->brfd, 3); - scalesame = ff_vc1_b_field_mvpred_scales[0][brfd]; - - n = (n * scalesame >> 8) << hpel; - return n; -} - -static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, - int dim, int dir) -{ - int refdist, scaleopp; - int hpel = 1 - v->s.quarter_sample; - - n >>= hpel; - if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) { - if (dim) - n = scaleforopp_y(v, n, dir) << hpel; - else - n = scaleforopp_x(v, n) << hpel; - return n; - } - if (v->s.pict_type != AV_PICTURE_TYPE_B) - refdist = FFMIN(v->refdist, 3); - else - refdist = dir ? v->brfd : v->frfd; - scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist]; - - n = (n * scaleopp >> 8) << hpel; - return n; -} - -/** Predict and set motion vector - */ -static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, - int mv1, int r_x, int r_y, uint8_t* is_intra, - int pred_flag, int dir) -{ - MpegEncContext *s = &v->s; - int xy, wrap, off = 0; - int16_t *A, *B, *C; - int px, py; - int sum; - int mixedmv_pic, num_samefield = 0, num_oppfield = 0; - int opposite, a_f, b_f, c_f; - int16_t field_predA[2]; - int16_t field_predB[2]; - int16_t field_predC[2]; - int a_valid, b_valid, c_valid; - int hybridmv_thresh, y_bias = 0; - - if (v->mv_mode == MV_PMODE_MIXED_MV || - ((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == MV_PMODE_MIXED_MV))) - mixedmv_pic = 1; - else - mixedmv_pic = 0; - /* scale MV difference to be quad-pel */ - dmv_x <<= 1 - s->quarter_sample; - dmv_y <<= 1 - s->quarter_sample; - - wrap = s->b8_stride; - xy = s->block_index[n]; - - if (s->mb_intra) { - s->mv[0][n][0] = s->current_picture.motion_val[0][xy + v->blocks_off][0] = 0; - s->mv[0][n][1] = s->current_picture.motion_val[0][xy + v->blocks_off][1] = 0; - s->current_picture.motion_val[1][xy + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; - if (mv1) { /* duplicate motion data for 1-MV block */ - s->current_picture.motion_val[0][xy + 1 + v->blocks_off][0] = 0; - s->current_picture.motion_val[0][xy + 1 + v->blocks_off][1] = 0; - s->current_picture.motion_val[0][xy + wrap + v->blocks_off][0] = 0; - s->current_picture.motion_val[0][xy + wrap + v->blocks_off][1] = 0; - s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][0] = 0; - s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][1] = 0; - v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; - s->current_picture.motion_val[1][xy + 1 + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1] = 0; - s->current_picture.motion_val[1][xy + wrap][0] = 0; - s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1] = 0; - s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0; - } - return; - } - - C = s->current_picture.motion_val[dir][xy - 1 + v->blocks_off]; - A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off]; - if (mv1) { - if (v->field_mode && mixedmv_pic) - off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; - else - off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2; - } else { - //in 4-MV mode different blocks have different B predictor position - switch (n) { - case 0: - off = (s->mb_x > 0) ? -1 : 1; - break; - case 1: - off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1; - break; - case 2: - off = 1; - break; - case 3: - off = -1; - } - } - B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off]; - - a_valid = !s->first_slice_line || (n == 2 || n == 3); - b_valid = a_valid && (s->mb_width > 1); - c_valid = s->mb_x || (n == 1 || n == 3); - if (v->field_mode) { - a_valid = a_valid && !is_intra[xy - wrap]; - b_valid = b_valid && !is_intra[xy - wrap + off]; - c_valid = c_valid && !is_intra[xy - 1]; - } - - if (a_valid) { - a_f = v->mv_f[dir][xy - wrap + v->blocks_off]; - num_oppfield += a_f; - num_samefield += 1 - a_f; - field_predA[0] = A[0]; - field_predA[1] = A[1]; - } else { - field_predA[0] = field_predA[1] = 0; - a_f = 0; - } - if (b_valid) { - b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; - num_oppfield += b_f; - num_samefield += 1 - b_f; - field_predB[0] = B[0]; - field_predB[1] = B[1]; - } else { - field_predB[0] = field_predB[1] = 0; - b_f = 0; - } - if (c_valid) { - c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; - num_oppfield += c_f; - num_samefield += 1 - c_f; - field_predC[0] = C[0]; - field_predC[1] = C[1]; - } else { - field_predC[0] = field_predC[1] = 0; - c_f = 0; - } - - if (v->field_mode) { - if (!v->numref) - // REFFIELD determines if the last field or the second-last field is - // to be used as reference - opposite = 1 - v->reffield; - else { - if (num_samefield <= num_oppfield) - opposite = 1 - pred_flag; - else - opposite = pred_flag; - } - } else - opposite = 0; - if (opposite) { - if (a_valid && !a_f) { - field_predA[0] = scaleforopp(v, field_predA[0], 0, dir); - field_predA[1] = scaleforopp(v, field_predA[1], 1, dir); - } - if (b_valid && !b_f) { - field_predB[0] = scaleforopp(v, field_predB[0], 0, dir); - field_predB[1] = scaleforopp(v, field_predB[1], 1, dir); - } - if (c_valid && !c_f) { - field_predC[0] = scaleforopp(v, field_predC[0], 0, dir); - field_predC[1] = scaleforopp(v, field_predC[1], 1, dir); - } - v->mv_f[dir][xy + v->blocks_off] = 1; - v->ref_field_type[dir] = !v->cur_field_type; - } else { - if (a_valid && a_f) { - field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir); - field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir); - } - if (b_valid && b_f) { - field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir); - field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir); - } - if (c_valid && c_f) { - field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir); - field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir); - } - v->mv_f[dir][xy + v->blocks_off] = 0; - v->ref_field_type[dir] = v->cur_field_type; - } - - if (a_valid) { - px = field_predA[0]; - py = field_predA[1]; - } else if (c_valid) { - px = field_predC[0]; - py = field_predC[1]; - } else if (b_valid) { - px = field_predB[0]; - py = field_predB[1]; - } else { - px = 0; - py = 0; - } - - if (num_samefield + num_oppfield > 1) { - px = mid_pred(field_predA[0], field_predB[0], field_predC[0]); - py = mid_pred(field_predA[1], field_predB[1], field_predC[1]); - } - - /* Pullback MV as specified in 8.3.5.3.4 */ - if (!v->field_mode) { - int qx, qy, X, Y; - qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0); - qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0); - X = (s->mb_width << 6) - 4; - Y = (s->mb_height << 6) - 4; - if (mv1) { - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - } else { - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - } - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } - - if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) { - /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */ - hybridmv_thresh = 32; - if (a_valid && c_valid) { - if (is_intra[xy - wrap]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]); - if (sum > hybridmv_thresh) { - if (get_bits1(&s->gb)) { // read HYBRIDPRED bit - px = field_predA[0]; - py = field_predA[1]; - } else { - px = field_predC[0]; - py = field_predC[1]; - } - } else { - if (is_intra[xy - 1]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - field_predC[0]) + FFABS(py - field_predC[1]); - if (sum > hybridmv_thresh) { - if (get_bits1(&s->gb)) { - px = field_predA[0]; - py = field_predA[1]; - } else { - px = field_predC[0]; - py = field_predC[1]; - } - } - } - } - } - - if (v->field_mode && v->numref) - r_y >>= 1; - if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0) - y_bias = 1; - /* store MV using signed modulus of MV range defined in 4.11 */ - s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; - s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + y_bias; - if (mv1) { /* duplicate motion data for 1-MV block */ - s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; - s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; - s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; - s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; - s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; - s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; - v->mv_f[dir][xy + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; - v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; - } -} - -/** Predict and set motion vector for interlaced frame picture MBs - */ -static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, - int mvn, int r_x, int r_y, uint8_t* is_intra, int dir) -{ - MpegEncContext *s = &v->s; - int xy, wrap, off = 0; - int A[2], B[2], C[2]; - int px, py; - int a_valid = 0, b_valid = 0, c_valid = 0; - int field_a, field_b, field_c; // 0: same, 1: opposit - int total_valid, num_samefield, num_oppfield; - int pos_c, pos_b, n_adj; - - wrap = s->b8_stride; - xy = s->block_index[n]; - - if (s->mb_intra) { - s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0; - s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0; - s->current_picture.motion_val[1][xy][0] = 0; - s->current_picture.motion_val[1][xy][1] = 0; - if (mvn == 1) { /* duplicate motion data for 1-MV block */ - s->current_picture.motion_val[0][xy + 1][0] = 0; - s->current_picture.motion_val[0][xy + 1][1] = 0; - s->current_picture.motion_val[0][xy + wrap][0] = 0; - s->current_picture.motion_val[0][xy + wrap][1] = 0; - s->current_picture.motion_val[0][xy + wrap + 1][0] = 0; - s->current_picture.motion_val[0][xy + wrap + 1][1] = 0; - v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; - s->current_picture.motion_val[1][xy + 1][0] = 0; - s->current_picture.motion_val[1][xy + 1][1] = 0; - s->current_picture.motion_val[1][xy + wrap][0] = 0; - s->current_picture.motion_val[1][xy + wrap][1] = 0; - s->current_picture.motion_val[1][xy + wrap + 1][0] = 0; - s->current_picture.motion_val[1][xy + wrap + 1][1] = 0; - } - return; - } - - off = ((n == 0) || (n == 1)) ? 1 : -1; - /* predict A */ - if (s->mb_x || (n == 1) || (n == 3)) { - if ((v->blk_mv_type[xy]) // current block (MB) has a field MV - || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV - A[0] = s->current_picture.motion_val[dir][xy - 1][0]; - A[1] = s->current_picture.motion_val[dir][xy - 1][1]; - a_valid = 1; - } else { // current block has frame mv and cand. has field MV (so average) - A[0] = (s->current_picture.motion_val[dir][xy - 1][0] - + s->current_picture.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1; - A[1] = (s->current_picture.motion_val[dir][xy - 1][1] - + s->current_picture.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1; - a_valid = 1; - } - if (!(n & 1) && v->is_intra[s->mb_x - 1]) { - a_valid = 0; - A[0] = A[1] = 0; - } - } else - A[0] = A[1] = 0; - /* Predict B and C */ - B[0] = B[1] = C[0] = C[1] = 0; - if (n == 0 || n == 1 || v->blk_mv_type[xy]) { - if (!s->first_slice_line) { - if (!v->is_intra[s->mb_x - s->mb_stride]) { - b_valid = 1; - n_adj = n | 2; - pos_b = s->block_index[n_adj] - 2 * wrap; - if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) { - n_adj = (n & 2) | (n & 1); - } - B[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0]; - B[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1]; - if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) { - B[0] = (B[0] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1; - B[1] = (B[1] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1; - } - } - if (s->mb_width > 1) { - if (!v->is_intra[s->mb_x - s->mb_stride + 1]) { - c_valid = 1; - n_adj = 2; - pos_c = s->block_index[2] - 2 * wrap + 2; - if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { - n_adj = n & 2; - } - C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0]; - C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1]; - if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { - C[0] = (1 + C[0] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1; - C[1] = (1 + C[1] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1; - } - if (s->mb_x == s->mb_width - 1) { - if (!v->is_intra[s->mb_x - s->mb_stride - 1]) { - c_valid = 1; - n_adj = 3; - pos_c = s->block_index[3] - 2 * wrap - 2; - if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { - n_adj = n | 1; - } - C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0]; - C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1]; - if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { - C[0] = (1 + C[0] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1; - C[1] = (1 + C[1] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1; - } - } else - c_valid = 0; - } - } - } - } - } else { - pos_b = s->block_index[1]; - b_valid = 1; - B[0] = s->current_picture.motion_val[dir][pos_b][0]; - B[1] = s->current_picture.motion_val[dir][pos_b][1]; - pos_c = s->block_index[0]; - c_valid = 1; - C[0] = s->current_picture.motion_val[dir][pos_c][0]; - C[1] = s->current_picture.motion_val[dir][pos_c][1]; - } - - total_valid = a_valid + b_valid + c_valid; - // check if predictor A is out of bounds - if (!s->mb_x && !(n == 1 || n == 3)) { - A[0] = A[1] = 0; - } - // check if predictor B is out of bounds - if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) { - B[0] = B[1] = C[0] = C[1] = 0; - } - if (!v->blk_mv_type[xy]) { - if (s->mb_width == 1) { - px = B[0]; - py = B[1]; - } else { - if (total_valid >= 2) { - px = mid_pred(A[0], B[0], C[0]); - py = mid_pred(A[1], B[1], C[1]); - } else if (total_valid) { - if (a_valid) { px = A[0]; py = A[1]; } - if (b_valid) { px = B[0]; py = B[1]; } - if (c_valid) { px = C[0]; py = C[1]; } - } else - px = py = 0; - } - } else { - if (a_valid) - field_a = (A[1] & 4) ? 1 : 0; - else - field_a = 0; - if (b_valid) - field_b = (B[1] & 4) ? 1 : 0; - else - field_b = 0; - if (c_valid) - field_c = (C[1] & 4) ? 1 : 0; - else - field_c = 0; - - num_oppfield = field_a + field_b + field_c; - num_samefield = total_valid - num_oppfield; - if (total_valid == 3) { - if ((num_samefield == 3) || (num_oppfield == 3)) { - px = mid_pred(A[0], B[0], C[0]); - py = mid_pred(A[1], B[1], C[1]); - } else if (num_samefield >= num_oppfield) { - /* take one MV from same field set depending on priority - the check for B may not be necessary */ - px = !field_a ? A[0] : B[0]; - py = !field_a ? A[1] : B[1]; - } else { - px = field_a ? A[0] : B[0]; - py = field_a ? A[1] : B[1]; - } - } else if (total_valid == 2) { - if (num_samefield >= num_oppfield) { - if (!field_a && a_valid) { - px = A[0]; - py = A[1]; - } else if (!field_b && b_valid) { - px = B[0]; - py = B[1]; - } else if (c_valid) { - px = C[0]; - py = C[1]; - } else px = py = 0; - } else { - if (field_a && a_valid) { - px = A[0]; - py = A[1]; - } else if (field_b && b_valid) { - px = B[0]; - py = B[1]; - } else if (c_valid) { - px = C[0]; - py = C[1]; - } else - px = py = 0; - } - } else if (total_valid == 1) { - px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]); - py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]); - } else - px = py = 0; - } - - /* store MV using signed modulus of MV range defined in 4.11 */ - s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; - s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y; - if (mvn == 1) { /* duplicate motion data for 1-MV block */ - s->current_picture.motion_val[dir][xy + 1 ][0] = s->current_picture.motion_val[dir][xy][0]; - s->current_picture.motion_val[dir][xy + 1 ][1] = s->current_picture.motion_val[dir][xy][1]; - s->current_picture.motion_val[dir][xy + wrap ][0] = s->current_picture.motion_val[dir][xy][0]; - s->current_picture.motion_val[dir][xy + wrap ][1] = s->current_picture.motion_val[dir][xy][1]; - s->current_picture.motion_val[dir][xy + wrap + 1][0] = s->current_picture.motion_val[dir][xy][0]; - s->current_picture.motion_val[dir][xy + wrap + 1][1] = s->current_picture.motion_val[dir][xy][1]; - } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */ - s->current_picture.motion_val[dir][xy + 1][0] = s->current_picture.motion_val[dir][xy][0]; - s->current_picture.motion_val[dir][xy + 1][1] = s->current_picture.motion_val[dir][xy][1]; - s->mv[dir][n + 1][0] = s->mv[dir][n][0]; - s->mv[dir][n + 1][1] = s->mv[dir][n][1]; - } -} - -/** Motion compensation for direct or interpolated blocks in B-frames - */ -static void vc1_interp_mc(VC1Context *v) -{ - MpegEncContext *s = &v->s; - H264ChromaContext *h264chroma = &v->h264chroma; - uint8_t *srcY, *srcU, *srcV; - int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; - int off, off_uv; - int v_edge_pos = s->v_edge_pos >> v->field_mode; - int use_ic = v->next_use_ic; - - if (!v->field_mode && !v->s.next_picture.f->data[0]) - return; - - mx = s->mv[1][0][0]; - my = s->mv[1][0][1]; - uvmx = (mx + ((mx & 3) == 3)) >> 1; - uvmy = (my + ((my & 3) == 3)) >> 1; - if (v->field_mode) { - if (v->cur_field_type != v->ref_field_type[1]) - my = my - 2 + 4 * v->cur_field_type; - uvmy = uvmy - 2 + 4 * v->cur_field_type; - } - if (v->fastuvmc) { - uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1)); - uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1)); - } - srcY = s->next_picture.f->data[0]; - srcU = s->next_picture.f->data[1]; - srcV = s->next_picture.f->data[2]; - - src_x = s->mb_x * 16 + (mx >> 2); - src_y = s->mb_y * 16 + (my >> 2); - uvsrc_x = s->mb_x * 8 + (uvmx >> 2); - uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - - if (v->profile != PROFILE_ADVANCED) { - src_x = av_clip( src_x, -16, s->mb_width * 16); - src_y = av_clip( src_y, -16, s->mb_height * 16); - uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); - } else { - src_x = av_clip( src_x, -17, s->avctx->coded_width); - src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); - uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); - uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); - } - - srcY += src_y * s->linesize + src_x; - srcU += uvsrc_y * s->uvlinesize + uvsrc_x; - srcV += uvsrc_y * s->uvlinesize + uvsrc_x; - - if (v->field_mode && v->ref_field_type[1]) { - srcY += s->current_picture_ptr->f->linesize[0]; - srcU += s->current_picture_ptr->f->linesize[1]; - srcV += s->current_picture_ptr->f->linesize[2]; - } - - /* for grayscale we should not try to read from unknown area */ - if (s->flags & CODEC_FLAG_GRAY) { - srcU = s->edge_emu_buffer + 18 * s->linesize; - srcV = s->edge_emu_buffer + 18 * s->linesize; - } - - if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || use_ic - || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3 - || (unsigned)(src_y - 1) > v_edge_pos - (my & 3) - 16 - 3) { - uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; - - srcY -= s->mspel * (1 + s->linesize); - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, - s->linesize, s->linesize, - 17 + s->mspel * 2, 17 + s->mspel * 2, - src_x - s->mspel, src_y - s->mspel, - s->h_edge_pos, v_edge_pos); - srcY = s->edge_emu_buffer; - s->vdsp.emulated_edge_mc(uvbuf, srcU, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, - uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); - s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, - s->uvlinesize, s->uvlinesize, - 8 + 1, 8 + 1, - uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); - srcU = uvbuf; - srcV = uvbuf + 16; - /* if we deal with range reduction we need to scale source blocks */ - if (v->rangeredfrm) { - int i, j; - uint8_t *src, *src2; - - src = srcY; - for (j = 0; j < 17 + s->mspel * 2; j++) { - for (i = 0; i < 17 + s->mspel * 2; i++) - src[i] = ((src[i] - 128) >> 1) + 128; - src += s->linesize; - } - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - for (i = 0; i < 9; i++) { - src[i] = ((src[i] - 128) >> 1) + 128; - src2[i] = ((src2[i] - 128) >> 1) + 128; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - - if (use_ic) { - uint8_t (*luty )[256] = v->next_luty; - uint8_t (*lutuv)[256] = v->next_lutuv; - int i, j; - uint8_t *src, *src2; - - src = srcY; - for (j = 0; j < 17 + s->mspel * 2; j++) { - int f = v->field_mode ? v->ref_field_type[1] : ((j+src_y - s->mspel) & 1); - for (i = 0; i < 17 + s->mspel * 2; i++) - src[i] = luty[f][src[i]]; - src += s->linesize; - } - src = srcU; - src2 = srcV; - for (j = 0; j < 9; j++) { - int f = v->field_mode ? v->ref_field_type[1] : ((j+uvsrc_y) & 1); - for (i = 0; i < 9; i++) { - src[i] = lutuv[f][src[i]]; - src2[i] = lutuv[f][src2[i]]; - } - src += s->uvlinesize; - src2 += s->uvlinesize; - } - } - srcY += s->mspel * (1 + s->linesize); - } - - off = 0; - off_uv = 0; - - if (s->mspel) { - dxy = ((my & 3) << 2) | (mx & 3); - v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); - v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd); - srcY += s->linesize * 8; - v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize , srcY , s->linesize, v->rnd); - v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd); - } else { // hpel mc - dxy = (my & 2) | ((mx & 2) >> 1); - - if (!v->rnd) - s->hdsp.avg_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16); - else - s->hdsp.avg_no_rnd_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, 16); - } - - if (s->flags & CODEC_FLAG_GRAY) return; - /* Chroma MC always uses qpel blilinear */ - uvmx = (uvmx & 3) << 1; - uvmy = (uvmy & 3) << 1; - if (!v->rnd) { - h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); - h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); - } else { - v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); - v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); - } -} - -static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs) -{ - int n = bfrac; - -#if B_FRACTION_DEN==256 - if (inv) - n -= 256; - if (!qs) - return 2 * ((value * n + 255) >> 9); - return (value * n + 128) >> 8; -#else - if (inv) - n -= B_FRACTION_DEN; - if (!qs) - return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN)); - return (value * n + B_FRACTION_DEN/2) / B_FRACTION_DEN; -#endif -} - -/** Reconstruct motion vector for B-frame and do motion compensation - */ -static inline void vc1_b_mc(VC1Context *v, int dmv_x[2], int dmv_y[2], - int direct, int mode) -{ - if (direct) { - vc1_mc_1mv(v, 0); - vc1_interp_mc(v); - return; - } - if (mode == BMV_TYPE_INTERPOLATED) { - vc1_mc_1mv(v, 0); - vc1_interp_mc(v); - return; - } - - vc1_mc_1mv(v, (mode == BMV_TYPE_BACKWARD)); -} - -static inline void vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], - int direct, int mvtype) -{ - MpegEncContext *s = &v->s; - int xy, wrap, off = 0; - int16_t *A, *B, *C; - int px, py; - int sum; - int r_x, r_y; - const uint8_t *is_intra = v->mb_type[0]; - - r_x = v->range_x; - r_y = v->range_y; - /* scale MV difference to be quad-pel */ - dmv_x[0] <<= 1 - s->quarter_sample; - dmv_y[0] <<= 1 - s->quarter_sample; - dmv_x[1] <<= 1 - s->quarter_sample; - dmv_y[1] <<= 1 - s->quarter_sample; - - wrap = s->b8_stride; - xy = s->block_index[0]; - - if (s->mb_intra) { - s->current_picture.motion_val[0][xy + v->blocks_off][0] = - s->current_picture.motion_val[0][xy + v->blocks_off][1] = - s->current_picture.motion_val[1][xy + v->blocks_off][0] = - s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; - return; - } - if (!v->field_mode) { - s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample); - s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample); - s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample); - s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample); - - /* Pullback predicted motion vectors as specified in 8.4.5.4 */ - s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); - s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); - s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); - s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); - } - if (direct) { - s->current_picture.motion_val[0][xy + v->blocks_off][0] = s->mv[0][0][0]; - s->current_picture.motion_val[0][xy + v->blocks_off][1] = s->mv[0][0][1]; - s->current_picture.motion_val[1][xy + v->blocks_off][0] = s->mv[1][0][0]; - s->current_picture.motion_val[1][xy + v->blocks_off][1] = s->mv[1][0][1]; - return; - } - - if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { - C = s->current_picture.motion_val[0][xy - 2]; - A = s->current_picture.motion_val[0][xy - wrap * 2]; - off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; - B = s->current_picture.motion_val[0][xy - wrap * 2 + off]; - - if (!s->mb_x) C[0] = C[1] = 0; - if (!s->first_slice_line) { // predictor A is not out of bounds - if (s->mb_width == 1) { - px = A[0]; - py = A[1]; - } else { - px = mid_pred(A[0], B[0], C[0]); - py = mid_pred(A[1], B[1], C[1]); - } - } else if (s->mb_x) { // predictor C is not out of bounds - px = C[0]; - py = C[1]; - } else { - px = py = 0; - } - /* Pullback MV as specified in 8.3.5.3.4 */ - { - int qx, qy, X, Y; - if (v->profile < PROFILE_ADVANCED) { - qx = (s->mb_x << 5); - qy = (s->mb_y << 5); - X = (s->mb_width << 5) - 4; - Y = (s->mb_height << 5) - 4; - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } else { - qx = (s->mb_x << 6); - qy = (s->mb_y << 6); - X = (s->mb_width << 6) - 4; - Y = (s->mb_height << 6) - 4; - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } - } - /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ - if (0 && !s->first_slice_line && s->mb_x) { - if (is_intra[xy - wrap]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - A[0]) + FFABS(py - A[1]); - if (sum > 32) { - if (get_bits1(&s->gb)) { - px = A[0]; - py = A[1]; - } else { - px = C[0]; - py = C[1]; - } - } else { - if (is_intra[xy - 2]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - C[0]) + FFABS(py - C[1]); - if (sum > 32) { - if (get_bits1(&s->gb)) { - px = A[0]; - py = A[1]; - } else { - px = C[0]; - py = C[1]; - } - } - } - } - /* store MV using signed modulus of MV range defined in 4.11 */ - s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x; - s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y; - } - if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { - C = s->current_picture.motion_val[1][xy - 2]; - A = s->current_picture.motion_val[1][xy - wrap * 2]; - off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; - B = s->current_picture.motion_val[1][xy - wrap * 2 + off]; - - if (!s->mb_x) - C[0] = C[1] = 0; - if (!s->first_slice_line) { // predictor A is not out of bounds - if (s->mb_width == 1) { - px = A[0]; - py = A[1]; - } else { - px = mid_pred(A[0], B[0], C[0]); - py = mid_pred(A[1], B[1], C[1]); - } - } else if (s->mb_x) { // predictor C is not out of bounds - px = C[0]; - py = C[1]; - } else { - px = py = 0; - } - /* Pullback MV as specified in 8.3.5.3.4 */ - { - int qx, qy, X, Y; - if (v->profile < PROFILE_ADVANCED) { - qx = (s->mb_x << 5); - qy = (s->mb_y << 5); - X = (s->mb_width << 5) - 4; - Y = (s->mb_height << 5) - 4; - if (qx + px < -28) px = -28 - qx; - if (qy + py < -28) py = -28 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } else { - qx = (s->mb_x << 6); - qy = (s->mb_y << 6); - X = (s->mb_width << 6) - 4; - Y = (s->mb_height << 6) - 4; - if (qx + px < -60) px = -60 - qx; - if (qy + py < -60) py = -60 - qy; - if (qx + px > X) px = X - qx; - if (qy + py > Y) py = Y - qy; - } - } - /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ - if (0 && !s->first_slice_line && s->mb_x) { - if (is_intra[xy - wrap]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - A[0]) + FFABS(py - A[1]); - if (sum > 32) { - if (get_bits1(&s->gb)) { - px = A[0]; - py = A[1]; - } else { - px = C[0]; - py = C[1]; - } - } else { - if (is_intra[xy - 2]) - sum = FFABS(px) + FFABS(py); - else - sum = FFABS(px - C[0]) + FFABS(py - C[1]); - if (sum > 32) { - if (get_bits1(&s->gb)) { - px = A[0]; - py = A[1]; - } else { - px = C[0]; - py = C[1]; - } - } - } - } - /* store MV using signed modulus of MV range defined in 4.11 */ - - s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x; - s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y; - } - s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0]; - s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1]; - s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0]; - s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1]; -} - -static inline void vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, int mv1, int *pred_flag) -{ - int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0; - MpegEncContext *s = &v->s; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - - if (v->bmvtype == BMV_TYPE_DIRECT) { - int total_opp, k, f; - if (s->next_picture.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) { - s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], - v->bfraction, 0, s->quarter_sample); - s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], - v->bfraction, 0, s->quarter_sample); - s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], - v->bfraction, 1, s->quarter_sample); - s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], - v->bfraction, 1, s->quarter_sample); - - total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off] - + v->mv_f_next[0][s->block_index[1] + v->blocks_off] - + v->mv_f_next[0][s->block_index[2] + v->blocks_off] - + v->mv_f_next[0][s->block_index[3] + v->blocks_off]; - f = (total_opp > 2) ? 1 : 0; - } else { - s->mv[0][0][0] = s->mv[0][0][1] = 0; - s->mv[1][0][0] = s->mv[1][0][1] = 0; - f = 0; - } - v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f; - for (k = 0; k < 4; k++) { - s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][0] = s->mv[0][0][0]; - s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][1] = s->mv[0][0][1]; - s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][0] = s->mv[1][0][0]; - s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][1] = s->mv[1][0][1]; - v->mv_f[0][s->block_index[k] + v->blocks_off] = f; - v->mv_f[1][s->block_index[k] + v->blocks_off] = f; - } - return; - } - if (v->bmvtype == BMV_TYPE_INTERPOLATED) { - vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); - vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); - return; - } - if (dir) { // backward - vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); - if (n == 3 || mv1) { - vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); - } - } else { // forward - vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); - if (n == 3 || mv1) { - vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], 0, 1); - } - } -} - -/** Get predicted DC value for I-frames only - * prediction dir: left=0, top=1 - * @param s MpegEncContext - * @param overlap flag indicating that overlap filtering is used - * @param pq integer part of picture quantizer - * @param[in] n block index in the current MB - * @param dc_val_ptr Pointer to DC predictor - * @param dir_ptr Prediction direction for use in AC prediction - */ -static inline int vc1_i_pred_dc(MpegEncContext *s, int overlap, int pq, int n, - int16_t **dc_val_ptr, int *dir_ptr) -{ - int a, b, c, wrap, pred, scale; - int16_t *dc_val; - static const uint16_t dcpred[32] = { - -1, 1024, 512, 341, 256, 205, 171, 146, 128, - 114, 102, 93, 85, 79, 73, 68, 64, - 60, 57, 54, 51, 49, 47, 45, 43, - 41, 39, 38, 37, 35, 34, 33 - }; - - /* find prediction - wmv3_dc_scale always used here in fact */ - if (n < 4) scale = s->y_dc_scale; - else scale = s->c_dc_scale; - - wrap = s->block_wrap[n]; - dc_val = s->dc_val[0] + s->block_index[n]; - - /* B A - * C X - */ - c = dc_val[ - 1]; - b = dc_val[ - 1 - wrap]; - a = dc_val[ - wrap]; - - if (pq < 9 || !overlap) { - /* Set outer values */ - if (s->first_slice_line && (n != 2 && n != 3)) - b = a = dcpred[scale]; - if (s->mb_x == 0 && (n != 1 && n != 3)) - b = c = dcpred[scale]; - } else { - /* Set outer values */ - if (s->first_slice_line && (n != 2 && n != 3)) - b = a = 0; - if (s->mb_x == 0 && (n != 1 && n != 3)) - b = c = 0; - } - - if (abs(a - b) <= abs(b - c)) { - pred = c; - *dir_ptr = 1; // left - } else { - pred = a; - *dir_ptr = 0; // top - } - - /* update predictor */ - *dc_val_ptr = &dc_val[0]; - return pred; -} - - -/** Get predicted DC value - * prediction dir: left=0, top=1 - * @param s MpegEncContext - * @param overlap flag indicating that overlap filtering is used - * @param pq integer part of picture quantizer - * @param[in] n block index in the current MB - * @param a_avail flag indicating top block availability - * @param c_avail flag indicating left block availability - * @param dc_val_ptr Pointer to DC predictor - * @param dir_ptr Prediction direction for use in AC prediction - */ -static inline int vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n, - int a_avail, int c_avail, - int16_t **dc_val_ptr, int *dir_ptr) -{ - int a, b, c, wrap, pred; - int16_t *dc_val; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int q1, q2 = 0; - int dqscale_index; - - wrap = s->block_wrap[n]; - dc_val = s->dc_val[0] + s->block_index[n]; - - /* B A - * C X - */ - c = dc_val[ - 1]; - b = dc_val[ - 1 - wrap]; - a = dc_val[ - wrap]; - /* scale predictors if needed */ - q1 = s->current_picture.qscale_table[mb_pos]; - dqscale_index = s->y_dc_scale_table[q1] - 1; - if (dqscale_index < 0) - return 0; - if (c_avail && (n != 1 && n != 3)) { - q2 = s->current_picture.qscale_table[mb_pos - 1]; - if (q2 && q2 != q1) - c = (c * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; - } - if (a_avail && (n != 2 && n != 3)) { - q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; - if (q2 && q2 != q1) - a = (a * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; - } - if (a_avail && c_avail && (n != 3)) { - int off = mb_pos; - if (n != 1) - off--; - if (n != 2) - off -= s->mb_stride; - q2 = s->current_picture.qscale_table[off]; - if (q2 && q2 != q1) - b = (b * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; - } - - if (a_avail && c_avail) { - if (abs(a - b) <= abs(b - c)) { - pred = c; - *dir_ptr = 1; // left - } else { - pred = a; - *dir_ptr = 0; // top - } - } else if (a_avail) { - pred = a; - *dir_ptr = 0; // top - } else if (c_avail) { - pred = c; - *dir_ptr = 1; // left - } else { - pred = 0; - *dir_ptr = 1; // left - } - - /* update predictor */ - *dc_val_ptr = &dc_val[0]; - return pred; -} - -/** @} */ // Block group - -/** - * @name VC1 Macroblock-level functions in Simple/Main Profiles - * @see 7.1.4, p91 and 8.1.1.7, p(1)04 - * @{ - */ - -static inline int vc1_coded_block_pred(MpegEncContext * s, int n, - uint8_t **coded_block_ptr) -{ - int xy, wrap, pred, a, b, c; - - xy = s->block_index[n]; - wrap = s->b8_stride; - - /* B C - * A X - */ - a = s->coded_block[xy - 1 ]; - b = s->coded_block[xy - 1 - wrap]; - c = s->coded_block[xy - wrap]; - - if (b == c) { - pred = a; - } else { - pred = c; - } - - /* store value */ - *coded_block_ptr = &s->coded_block[xy]; - - return pred; -} - -/** - * Decode one AC coefficient - * @param v The VC1 context - * @param last Last coefficient - * @param skip How much zero coefficients to skip - * @param value Decoded AC coefficient value - * @param codingset set of VLC to decode data - * @see 8.1.3.4 - */ -static void vc1_decode_ac_coeff(VC1Context *v, int *last, int *skip, - int *value, int codingset) -{ - GetBitContext *gb = &v->s.gb; - int index, escape, run = 0, level = 0, lst = 0; - - index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); - if (index != ff_vc1_ac_sizes[codingset] - 1) { - run = vc1_index_decode_table[codingset][index][0]; - level = vc1_index_decode_table[codingset][index][1]; - lst = index >= vc1_last_decode_table[codingset] || get_bits_left(gb) < 0; - if (get_bits1(gb)) - level = -level; - } else { - escape = decode210(gb); - if (escape != 2) { - index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); - run = vc1_index_decode_table[codingset][index][0]; - level = vc1_index_decode_table[codingset][index][1]; - lst = index >= vc1_last_decode_table[codingset]; - if (escape == 0) { - if (lst) - level += vc1_last_delta_level_table[codingset][run]; - else - level += vc1_delta_level_table[codingset][run]; - } else { - if (lst) - run += vc1_last_delta_run_table[codingset][level] + 1; - else - run += vc1_delta_run_table[codingset][level] + 1; - } - if (get_bits1(gb)) - level = -level; - } else { - int sign; - lst = get_bits1(gb); - if (v->s.esc3_level_length == 0) { - if (v->pq < 8 || v->dquantfrm) { // table 59 - v->s.esc3_level_length = get_bits(gb, 3); - if (!v->s.esc3_level_length) - v->s.esc3_level_length = get_bits(gb, 2) + 8; - } else { // table 60 - v->s.esc3_level_length = get_unary(gb, 1, 6) + 2; - } - v->s.esc3_run_length = 3 + get_bits(gb, 2); - } - run = get_bits(gb, v->s.esc3_run_length); - sign = get_bits1(gb); - level = get_bits(gb, v->s.esc3_level_length); - if (sign) - level = -level; - } - } - - *last = lst; - *skip = run; - *value = level; -} - -/** Decode intra block in intra frames - should be faster than decode_intra_block - * @param v VC1Context - * @param block block to decode - * @param[in] n subblock index - * @param coded are AC coeffs present or not - * @param codingset set of VLC to decode data - */ -static int vc1_decode_i_block(VC1Context *v, int16_t block[64], int n, - int coded, int codingset) -{ - GetBitContext *gb = &v->s.gb; - MpegEncContext *s = &v->s; - int dc_pred_dir = 0; /* Direction of the DC prediction used */ - int i; - int16_t *dc_val; - int16_t *ac_val, *ac_val2; - int dcdiff; - - /* Get DC differential */ - if (n < 4) { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } else { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } - if (dcdiff) { - if (dcdiff == 119 /* ESC index value */) { - /* TODO: Optimize */ - if (v->pq == 1) dcdiff = get_bits(gb, 10); - else if (v->pq == 2) dcdiff = get_bits(gb, 9); - else dcdiff = get_bits(gb, 8); - } else { - if (v->pq == 1) - dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; - else if (v->pq == 2) - dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; - } - if (get_bits1(gb)) - dcdiff = -dcdiff; - } - - /* Prediction */ - dcdiff += vc1_i_pred_dc(&v->s, v->overlap, v->pq, n, &dc_val, &dc_pred_dir); - *dc_val = dcdiff; - - /* Store the quantized DC coeff, used for prediction */ - if (n < 4) { - block[0] = dcdiff * s->y_dc_scale; - } else { - block[0] = dcdiff * s->c_dc_scale; - } - /* Skip ? */ - if (!coded) { - goto not_coded; - } - - // AC Decoding - i = 1; - - { - int last = 0, skip, value; - const uint8_t *zz_table; - int scale; - int k; - - scale = v->pq * 2 + v->halfpq; - - if (v->s.ac_pred) { - if (!dc_pred_dir) - zz_table = v->zz_8x8[2]; - else - zz_table = v->zz_8x8[3]; - } else - zz_table = v->zz_8x8[1]; - - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; - ac_val2 = ac_val; - if (dc_pred_dir) // left - ac_val -= 16; - else // top - ac_val -= 16 * s->block_wrap[n]; - - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); - i += skip; - if (i > 63) - break; - block[zz_table[i++]] = value; - } - - /* apply AC prediction if needed */ - if (s->ac_pred) { - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) - block[k << v->left_blk_sh] += ac_val[k]; - } else { // top - for (k = 1; k < 8; k++) - block[k << v->top_blk_sh] += ac_val[k + 8]; - } - } - /* save AC coeffs for further prediction */ - for (k = 1; k < 8; k++) { - ac_val2[k] = block[k << v->left_blk_sh]; - ac_val2[k + 8] = block[k << v->top_blk_sh]; - } - - /* scale AC coeffs */ - for (k = 1; k < 64; k++) - if (block[k]) { - block[k] *= scale; - if (!v->pquantizer) - block[k] += (block[k] < 0) ? -v->pq : v->pq; - } - - if (s->ac_pred) i = 63; - } - -not_coded: - if (!coded) { - int k, scale; - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; - ac_val2 = ac_val; - - i = 0; - scale = v->pq * 2 + v->halfpq; - memset(ac_val2, 0, 16 * 2); - if (dc_pred_dir) { // left - ac_val -= 16; - if (s->ac_pred) - memcpy(ac_val2, ac_val, 8 * 2); - } else { // top - ac_val -= 16 * s->block_wrap[n]; - if (s->ac_pred) - memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); - } - - /* apply AC prediction if needed */ - if (s->ac_pred) { - if (dc_pred_dir) { //left - for (k = 1; k < 8; k++) { - block[k << v->left_blk_sh] = ac_val[k] * scale; - if (!v->pquantizer && block[k << v->left_blk_sh]) - block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -v->pq : v->pq; - } - } else { // top - for (k = 1; k < 8; k++) { - block[k << v->top_blk_sh] = ac_val[k + 8] * scale; - if (!v->pquantizer && block[k << v->top_blk_sh]) - block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -v->pq : v->pq; - } - } - i = 63; - } - } - s->block_last_index[n] = i; - - return 0; -} - -/** Decode intra block in intra frames - should be faster than decode_intra_block - * @param v VC1Context - * @param block block to decode - * @param[in] n subblock number - * @param coded are AC coeffs present or not - * @param codingset set of VLC to decode data - * @param mquant quantizer value for this macroblock - */ -static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n, - int coded, int codingset, int mquant) -{ - GetBitContext *gb = &v->s.gb; - MpegEncContext *s = &v->s; - int dc_pred_dir = 0; /* Direction of the DC prediction used */ - int i; - int16_t *dc_val; - int16_t *ac_val, *ac_val2; - int dcdiff; - int a_avail = v->a_avail, c_avail = v->c_avail; - int use_pred = s->ac_pred; - int scale; - int q1, q2 = 0; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - - /* Get DC differential */ - if (n < 4) { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } else { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } - if (dcdiff) { - if (dcdiff == 119 /* ESC index value */) { - /* TODO: Optimize */ - if (mquant == 1) dcdiff = get_bits(gb, 10); - else if (mquant == 2) dcdiff = get_bits(gb, 9); - else dcdiff = get_bits(gb, 8); - } else { - if (mquant == 1) - dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; - else if (mquant == 2) - dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; - } - if (get_bits1(gb)) - dcdiff = -dcdiff; - } - - /* Prediction */ - dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, v->a_avail, v->c_avail, &dc_val, &dc_pred_dir); - *dc_val = dcdiff; - - /* Store the quantized DC coeff, used for prediction */ - if (n < 4) { - block[0] = dcdiff * s->y_dc_scale; - } else { - block[0] = dcdiff * s->c_dc_scale; - } - - //AC Decoding - i = 1; - - /* check if AC is needed at all */ - if (!a_avail && !c_avail) - use_pred = 0; - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; - ac_val2 = ac_val; - - scale = mquant * 2 + ((mquant == v->pq) ? v->halfpq : 0); - - if (dc_pred_dir) // left - ac_val -= 16; - else // top - ac_val -= 16 * s->block_wrap[n]; - - q1 = s->current_picture.qscale_table[mb_pos]; - if ( dc_pred_dir && c_avail && mb_pos) - q2 = s->current_picture.qscale_table[mb_pos - 1]; - if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) - q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; - if ( dc_pred_dir && n == 1) - q2 = q1; - if (!dc_pred_dir && n == 2) - q2 = q1; - if (n == 3) - q2 = q1; - - if (coded) { - int last = 0, skip, value; - const uint8_t *zz_table; - int k; - - if (v->s.ac_pred) { - if (!use_pred && v->fcm == ILACE_FRAME) { - zz_table = v->zzi_8x8; - } else { - if (!dc_pred_dir) // top - zz_table = v->zz_8x8[2]; - else // left - zz_table = v->zz_8x8[3]; - } - } else { - if (v->fcm != ILACE_FRAME) - zz_table = v->zz_8x8[1]; - else - zz_table = v->zzi_8x8; - } - - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); - i += skip; - if (i > 63) - break; - block[zz_table[i++]] = value; - } - - /* apply AC prediction if needed */ - if (use_pred) { - /* scale predictors if needed*/ - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - - if (q1 < 1) - return AVERROR_INVALIDDATA; - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) - block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } else { // top - for (k = 1; k < 8; k++) - block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } else { - if (dc_pred_dir) { //left - for (k = 1; k < 8; k++) - block[k << v->left_blk_sh] += ac_val[k]; - } else { //top - for (k = 1; k < 8; k++) - block[k << v->top_blk_sh] += ac_val[k + 8]; - } - } - } - /* save AC coeffs for further prediction */ - for (k = 1; k < 8; k++) { - ac_val2[k ] = block[k << v->left_blk_sh]; - ac_val2[k + 8] = block[k << v->top_blk_sh]; - } - - /* scale AC coeffs */ - for (k = 1; k < 64; k++) - if (block[k]) { - block[k] *= scale; - if (!v->pquantizer) - block[k] += (block[k] < 0) ? -mquant : mquant; - } - - if (use_pred) i = 63; - } else { // no AC coeffs - int k; - - memset(ac_val2, 0, 16 * 2); - if (dc_pred_dir) { // left - if (use_pred) { - memcpy(ac_val2, ac_val, 8 * 2); - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - if (q1 < 1) - return AVERROR_INVALIDDATA; - for (k = 1; k < 8; k++) - ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } - } else { // top - if (use_pred) { - memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - if (q1 < 1) - return AVERROR_INVALIDDATA; - for (k = 1; k < 8; k++) - ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } - } - - /* apply AC prediction if needed */ - if (use_pred) { - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) { - block[k << v->left_blk_sh] = ac_val2[k] * scale; - if (!v->pquantizer && block[k << v->left_blk_sh]) - block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; - } - } else { // top - for (k = 1; k < 8; k++) { - block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; - if (!v->pquantizer && block[k << v->top_blk_sh]) - block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; - } - } - i = 63; - } - } - s->block_last_index[n] = i; - - return 0; -} - -/** Decode intra block in inter frames - more generic version than vc1_decode_i_block - * @param v VC1Context - * @param block block to decode - * @param[in] n subblock index - * @param coded are AC coeffs present or not - * @param mquant block quantizer - * @param codingset set of VLC to decode data - */ -static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, - int coded, int mquant, int codingset) -{ - GetBitContext *gb = &v->s.gb; - MpegEncContext *s = &v->s; - int dc_pred_dir = 0; /* Direction of the DC prediction used */ - int i; - int16_t *dc_val; - int16_t *ac_val, *ac_val2; - int dcdiff; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int a_avail = v->a_avail, c_avail = v->c_avail; - int use_pred = s->ac_pred; - int scale; - int q1, q2 = 0; - - s->bdsp.clear_block(block); - - /* XXX: Guard against dumb values of mquant */ - mquant = (mquant < 1) ? 0 : ((mquant > 31) ? 31 : mquant); - - /* Set DC scale - y and c use the same */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - - /* Get DC differential */ - if (n < 4) { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } else { - dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); - } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } - if (dcdiff) { - if (dcdiff == 119 /* ESC index value */) { - /* TODO: Optimize */ - if (mquant == 1) dcdiff = get_bits(gb, 10); - else if (mquant == 2) dcdiff = get_bits(gb, 9); - else dcdiff = get_bits(gb, 8); - } else { - if (mquant == 1) - dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; - else if (mquant == 2) - dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; - } - if (get_bits1(gb)) - dcdiff = -dcdiff; - } - - /* Prediction */ - dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, &dc_val, &dc_pred_dir); - *dc_val = dcdiff; - - /* Store the quantized DC coeff, used for prediction */ - - if (n < 4) { - block[0] = dcdiff * s->y_dc_scale; - } else { - block[0] = dcdiff * s->c_dc_scale; - } - - //AC Decoding - i = 1; - - /* check if AC is needed at all and adjust direction if needed */ - if (!a_avail) dc_pred_dir = 1; - if (!c_avail) dc_pred_dir = 0; - if (!a_avail && !c_avail) use_pred = 0; - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; - ac_val2 = ac_val; - - scale = mquant * 2 + v->halfpq; - - if (dc_pred_dir) //left - ac_val -= 16; - else //top - ac_val -= 16 * s->block_wrap[n]; - - q1 = s->current_picture.qscale_table[mb_pos]; - if (dc_pred_dir && c_avail && mb_pos) - q2 = s->current_picture.qscale_table[mb_pos - 1]; - if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) - q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; - if ( dc_pred_dir && n == 1) - q2 = q1; - if (!dc_pred_dir && n == 2) - q2 = q1; - if (n == 3) q2 = q1; - - if (coded) { - int last = 0, skip, value; - int k; - - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); - i += skip; - if (i > 63) - break; - if (v->fcm == PROGRESSIVE) - block[v->zz_8x8[0][i++]] = value; - else { - if (use_pred && (v->fcm == ILACE_FRAME)) { - if (!dc_pred_dir) // top - block[v->zz_8x8[2][i++]] = value; - else // left - block[v->zz_8x8[3][i++]] = value; - } else { - block[v->zzi_8x8[i++]] = value; - } - } - } - - /* apply AC prediction if needed */ - if (use_pred) { - /* scale predictors if needed*/ - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - - if (q1 < 1) - return AVERROR_INVALIDDATA; - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) - block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } else { //top - for (k = 1; k < 8; k++) - block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } else { - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) - block[k << v->left_blk_sh] += ac_val[k]; - } else { // top - for (k = 1; k < 8; k++) - block[k << v->top_blk_sh] += ac_val[k + 8]; - } - } - } - /* save AC coeffs for further prediction */ - for (k = 1; k < 8; k++) { - ac_val2[k ] = block[k << v->left_blk_sh]; - ac_val2[k + 8] = block[k << v->top_blk_sh]; - } - - /* scale AC coeffs */ - for (k = 1; k < 64; k++) - if (block[k]) { - block[k] *= scale; - if (!v->pquantizer) - block[k] += (block[k] < 0) ? -mquant : mquant; - } - - if (use_pred) i = 63; - } else { // no AC coeffs - int k; - - memset(ac_val2, 0, 16 * 2); - if (dc_pred_dir) { // left - if (use_pred) { - memcpy(ac_val2, ac_val, 8 * 2); - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - if (q1 < 1) - return AVERROR_INVALIDDATA; - for (k = 1; k < 8; k++) - ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } - } else { // top - if (use_pred) { - memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); - if (q2 && q1 != q2) { - q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; - q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; - if (q1 < 1) - return AVERROR_INVALIDDATA; - for (k = 1; k < 8; k++) - ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; - } - } - } - - /* apply AC prediction if needed */ - if (use_pred) { - if (dc_pred_dir) { // left - for (k = 1; k < 8; k++) { - block[k << v->left_blk_sh] = ac_val2[k] * scale; - if (!v->pquantizer && block[k << v->left_blk_sh]) - block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; - } - } else { // top - for (k = 1; k < 8; k++) { - block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; - if (!v->pquantizer && block[k << v->top_blk_sh]) - block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; - } - } - i = 63; - } - } - s->block_last_index[n] = i; - - return 0; -} - -/** Decode P block - */ -static int vc1_decode_p_block(VC1Context *v, int16_t block[64], int n, - int mquant, int ttmb, int first_block, - uint8_t *dst, int linesize, int skip_block, - int *ttmb_out) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i, j; - int subblkpat = 0; - int scale, off, idx, last, skip, value; - int ttblk = ttmb & 7; - int pat = 0; - - s->bdsp.clear_block(block); - - if (ttmb == -1) { - ttblk = ff_vc1_ttblk_to_tt[v->tt_index][get_vlc2(gb, ff_vc1_ttblk_vlc[v->tt_index].table, VC1_TTBLK_VLC_BITS, 1)]; - } - if (ttblk == TT_4X4) { - subblkpat = ~(get_vlc2(gb, ff_vc1_subblkpat_vlc[v->tt_index].table, VC1_SUBBLKPAT_VLC_BITS, 1) + 1); - } - if ((ttblk != TT_8X8 && ttblk != TT_4X4) - && ((v->ttmbf || (ttmb != -1 && (ttmb & 8) && !first_block)) - || (!v->res_rtm_flag && !first_block))) { - subblkpat = decode012(gb); - if (subblkpat) - subblkpat ^= 3; // swap decoded pattern bits - if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) - ttblk = TT_8X4; - if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) - ttblk = TT_4X8; - } - scale = 2 * mquant + ((v->pq == mquant) ? v->halfpq : 0); - - // convert transforms like 8X4_TOP to generic TT and SUBBLKPAT - if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) { - subblkpat = 2 - (ttblk == TT_8X4_TOP); - ttblk = TT_8X4; - } - if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) { - subblkpat = 2 - (ttblk == TT_4X8_LEFT); - ttblk = TT_4X8; - } - switch (ttblk) { - case TT_8X8: - pat = 0xF; - i = 0; - last = 0; - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); - i += skip; - if (i > 63) - break; - if (!v->fcm) - idx = v->zz_8x8[0][i++]; - else - idx = v->zzi_8x8[i++]; - block[idx] = value * scale; - if (!v->pquantizer) - block[idx] += (block[idx] < 0) ? -mquant : mquant; - } - if (!skip_block) { - if (i == 1) - v->vc1dsp.vc1_inv_trans_8x8_dc(dst, linesize, block); - else { - v->vc1dsp.vc1_inv_trans_8x8(block); - s->idsp.add_pixels_clamped(block, dst, linesize); - } - } - break; - case TT_4X4: - pat = ~subblkpat & 0xF; - for (j = 0; j < 4; j++) { - last = subblkpat & (1 << (3 - j)); - i = 0; - off = (j & 1) * 4 + (j & 2) * 16; - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); - i += skip; - if (i > 15) - break; - if (!v->fcm) - idx = ff_vc1_simple_progressive_4x4_zz[i++]; - else - idx = ff_vc1_adv_interlaced_4x4_zz[i++]; - block[idx + off] = value * scale; - if (!v->pquantizer) - block[idx + off] += (block[idx + off] < 0) ? -mquant : mquant; - } - if (!(subblkpat & (1 << (3 - j))) && !skip_block) { - if (i == 1) - v->vc1dsp.vc1_inv_trans_4x4_dc(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); - else - v->vc1dsp.vc1_inv_trans_4x4(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); - } - } - break; - case TT_8X4: - pat = ~((subblkpat & 2) * 6 + (subblkpat & 1) * 3) & 0xF; - for (j = 0; j < 2; j++) { - last = subblkpat & (1 << (1 - j)); - i = 0; - off = j * 32; - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); - i += skip; - if (i > 31) - break; - if (!v->fcm) - idx = v->zz_8x4[i++] + off; - else - idx = ff_vc1_adv_interlaced_8x4_zz[i++] + off; - block[idx] = value * scale; - if (!v->pquantizer) - block[idx] += (block[idx] < 0) ? -mquant : mquant; - } - if (!(subblkpat & (1 << (1 - j))) && !skip_block) { - if (i == 1) - v->vc1dsp.vc1_inv_trans_8x4_dc(dst + j * 4 * linesize, linesize, block + off); - else - v->vc1dsp.vc1_inv_trans_8x4(dst + j * 4 * linesize, linesize, block + off); - } - } - break; - case TT_4X8: - pat = ~(subblkpat * 5) & 0xF; - for (j = 0; j < 2; j++) { - last = subblkpat & (1 << (1 - j)); - i = 0; - off = j * 4; - while (!last) { - vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); - i += skip; - if (i > 31) - break; - if (!v->fcm) - idx = v->zz_4x8[i++] + off; - else - idx = ff_vc1_adv_interlaced_4x8_zz[i++] + off; - block[idx] = value * scale; - if (!v->pquantizer) - block[idx] += (block[idx] < 0) ? -mquant : mquant; - } - if (!(subblkpat & (1 << (1 - j))) && !skip_block) { - if (i == 1) - v->vc1dsp.vc1_inv_trans_4x8_dc(dst + j * 4, linesize, block + off); - else - v->vc1dsp.vc1_inv_trans_4x8(dst + j*4, linesize, block + off); - } - } - break; - } - if (ttmb_out) - *ttmb_out |= ttblk << (n * 4); - return pat; -} - -/** @} */ // Macroblock group - -static const int size_table [6] = { 0, 2, 3, 4, 5, 8 }; -static const int offset_table[6] = { 0, 1, 3, 7, 15, 31 }; - -static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_num) -{ - MpegEncContext *s = &v->s; - int mb_cbp = v->cbp[s->mb_x - s->mb_stride], - block_cbp = mb_cbp >> (block_num * 4), bottom_cbp, - mb_is_intra = v->is_intra[s->mb_x - s->mb_stride], - block_is_intra = mb_is_intra >> (block_num * 4), bottom_is_intra; - int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; - uint8_t *dst; - - if (block_num > 3) { - dst = s->dest[block_num - 3]; - } else { - dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize; - } - if (s->mb_y != s->end_mb_y || block_num < 2) { - int16_t (*mv)[2]; - int mv_stride; - - if (block_num > 3) { - bottom_cbp = v->cbp[s->mb_x] >> (block_num * 4); - bottom_is_intra = v->is_intra[s->mb_x] >> (block_num * 4); - mv = &v->luma_mv[s->mb_x - s->mb_stride]; - mv_stride = s->mb_stride; - } else { - bottom_cbp = (block_num < 2) ? (mb_cbp >> ((block_num + 2) * 4)) - : (v->cbp[s->mb_x] >> ((block_num - 2) * 4)); - bottom_is_intra = (block_num < 2) ? (mb_is_intra >> ((block_num + 2) * 4)) - : (v->is_intra[s->mb_x] >> ((block_num - 2) * 4)); - mv_stride = s->b8_stride; - mv = &s->current_picture.motion_val[0][s->block_index[block_num] - 2 * mv_stride]; - } - - if (bottom_is_intra & 1 || block_is_intra & 1 || - mv[0][0] != mv[mv_stride][0] || mv[0][1] != mv[mv_stride][1]) { - v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); - } else { - idx = ((bottom_cbp >> 2) | block_cbp) & 3; - if (idx == 3) { - v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); - } else if (idx) { - if (idx == 1) - v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); - else - v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); - } - } - } - - dst -= 4 * linesize; - ttblk = (v->ttblk[s->mb_x - s->mb_stride] >> (block_num * 4)) & 0xF; - if (ttblk == TT_4X4 || ttblk == TT_8X4) { - idx = (block_cbp | (block_cbp >> 2)) & 3; - if (idx == 3) { - v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); - } else if (idx) { - if (idx == 1) - v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); - else - v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); - } - } -} - -static av_always_inline void vc1_apply_p_h_loop_filter(VC1Context *v, int block_num) -{ - MpegEncContext *s = &v->s; - int mb_cbp = v->cbp[s->mb_x - 1 - s->mb_stride], - block_cbp = mb_cbp >> (block_num * 4), right_cbp, - mb_is_intra = v->is_intra[s->mb_x - 1 - s->mb_stride], - block_is_intra = mb_is_intra >> (block_num * 4), right_is_intra; - int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; - uint8_t *dst; - - if (block_num > 3) { - dst = s->dest[block_num - 3] - 8 * linesize; - } else { - dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 16) * linesize - 8; - } - - if (s->mb_x != s->mb_width || !(block_num & 5)) { - int16_t (*mv)[2]; - - if (block_num > 3) { - right_cbp = v->cbp[s->mb_x - s->mb_stride] >> (block_num * 4); - right_is_intra = v->is_intra[s->mb_x - s->mb_stride] >> (block_num * 4); - mv = &v->luma_mv[s->mb_x - s->mb_stride - 1]; - } else { - right_cbp = (block_num & 1) ? (v->cbp[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) - : (mb_cbp >> ((block_num + 1) * 4)); - right_is_intra = (block_num & 1) ? (v->is_intra[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) - : (mb_is_intra >> ((block_num + 1) * 4)); - mv = &s->current_picture.motion_val[0][s->block_index[block_num] - s->b8_stride * 2 - 2]; - } - if (block_is_intra & 1 || right_is_intra & 1 || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1]) { - v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); - } else { - idx = ((right_cbp >> 1) | block_cbp) & 5; // FIXME check - if (idx == 5) { - v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); - } else if (idx) { - if (idx == 1) - v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize, linesize, v->pq); - else - v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); - } - } - } - - dst -= 4; - ttblk = (v->ttblk[s->mb_x - s->mb_stride - 1] >> (block_num * 4)) & 0xf; - if (ttblk == TT_4X4 || ttblk == TT_4X8) { - idx = (block_cbp | (block_cbp >> 1)) & 5; - if (idx == 5) { - v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); - } else if (idx) { - if (idx == 1) - v->vc1dsp.vc1_h_loop_filter4(dst + linesize * 4, linesize, v->pq); - else - v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); - } - } -} - -static void vc1_apply_p_loop_filter(VC1Context *v) -{ - MpegEncContext *s = &v->s; - int i; - - for (i = 0; i < 6; i++) { - vc1_apply_p_v_loop_filter(v, i); - } - - /* V always precedes H, therefore we run H one MB before V; - * at the end of a row, we catch up to complete the row */ - if (s->mb_x) { - for (i = 0; i < 6; i++) { - vc1_apply_p_h_loop_filter(v, i); - } - if (s->mb_x == s->mb_width - 1) { - s->mb_x++; - ff_update_block_index(s); - for (i = 0; i < 6; i++) { - vc1_apply_p_h_loop_filter(v, i); - } - } - } -} - -/** Decode one P-frame MB - */ -static int vc1_decode_p_mb(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i, j; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - - int mb_has_coeffs = 1; /* last_flag */ - int dmv_x, dmv_y; /* Differential MV components */ - int index, index1; /* LUT indexes */ - int val, sign; /* temp values */ - int first_block = 1; - int dst_idx, off; - int skipped, fourmv; - int block_cbp = 0, pat, block_tt = 0, block_intra = 0; - - mquant = v->pq; /* lossy initialization */ - - if (v->mv_type_is_raw) - fourmv = get_bits1(gb); - else - fourmv = v->mv_type_mb_plane[mb_pos]; - if (v->skip_is_raw) - skipped = get_bits1(gb); - else - skipped = v->s.mbskip_table[mb_pos]; - - if (!fourmv) { /* 1MV mode */ - if (!skipped) { - GET_MVDATA(dmv_x, dmv_y); - - if (s->mb_intra) { - s->current_picture.motion_val[1][s->block_index[0]][0] = 0; - s->current_picture.motion_val[1][s->block_index[0]][1] = 0; - } - s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16; - vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); - - /* FIXME Set DC val for inter block ? */ - if (s->mb_intra && !mb_has_coeffs) { - GET_MQUANT(); - s->ac_pred = get_bits1(gb); - cbp = 0; - } else if (mb_has_coeffs) { - if (s->mb_intra) - s->ac_pred = get_bits1(gb); - cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - GET_MQUANT(); - } else { - mquant = v->pq; - cbp = 0; - } - s->current_picture.qscale_table[mb_pos] = mquant; - - if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, - VC1_TTMB_VLC_BITS, 2); - if (!s->mb_intra) vc1_mc_1mv(v, 0); - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - v->mb_type[0][s->block_index[i]] = s->mb_intra; - if (s->mb_intra) { - /* check if prediction blocks A and C are available */ - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[i][j] <<= 1; - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - i & 4 ? s->uvlinesize - : s->linesize); - if (v->pq >= 9 && v->overlap) { - if (v->c_avail) - v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); - if (v->a_avail) - v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); - } - block_cbp |= 0xF << (i << 2); - block_intra |= 1 << i; - } else if (val) { - pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, - s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize, - (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); - block_cbp |= pat << (i << 2); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } - } else { // skipped - s->mb_intra = 0; - for (i = 0; i < 6; i++) { - v->mb_type[0][s->block_index[i]] = 0; - s->dc_val[0][s->block_index[i]] = 0; - } - s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; - s->current_picture.qscale_table[mb_pos] = 0; - vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); - vc1_mc_1mv(v, 0); - } - } else { // 4MV mode - if (!skipped /* unskipped MB */) { - int intra_count = 0, coded_inter = 0; - int is_intra[6], is_coded[6]; - /* Get CBPCY */ - cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - for (i = 0; i < 6; i++) { - val = ((cbp >> (5 - i)) & 1); - s->dc_val[0][s->block_index[i]] = 0; - s->mb_intra = 0; - if (i < 4) { - dmv_x = dmv_y = 0; - s->mb_intra = 0; - mb_has_coeffs = 0; - if (val) { - GET_MVDATA(dmv_x, dmv_y); - } - vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); - if (!s->mb_intra) - vc1_mc_4mv_luma(v, i, 0, 0); - intra_count += s->mb_intra; - is_intra[i] = s->mb_intra; - is_coded[i] = mb_has_coeffs; - } - if (i & 4) { - is_intra[i] = (intra_count >= 3); - is_coded[i] = val; - } - if (i == 4) - vc1_mc_4mv_chroma(v, 0); - v->mb_type[0][s->block_index[i]] = is_intra[i]; - if (!coded_inter) - coded_inter = !is_intra[i] & is_coded[i]; - } - // if there are no coded blocks then don't do anything more - dst_idx = 0; - if (!intra_count && !coded_inter) - goto end; - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - /* test if block is intra and has pred */ - { - int intrapred = 0; - for (i = 0; i < 6; i++) - if (is_intra[i]) { - if (((!s->first_slice_line || (i == 2 || i == 3)) && v->mb_type[0][s->block_index[i] - s->block_wrap[i]]) - || ((s->mb_x || (i == 1 || i == 3)) && v->mb_type[0][s->block_index[i] - 1])) { - intrapred = 1; - break; - } - } - if (intrapred) - s->ac_pred = get_bits1(gb); - else - s->ac_pred = 0; - } - if (!v->ttmbf && coded_inter) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - for (i = 0; i < 6; i++) { - dst_idx += i >> 2; - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - s->mb_intra = is_intra[i]; - if (is_intra[i]) { - /* check if prediction blocks A and C are available */ - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, is_coded[i], mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[i][j] <<= 1; - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize - : s->linesize); - if (v->pq >= 9 && v->overlap) { - if (v->c_avail) - v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); - if (v->a_avail) - v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); - } - block_cbp |= 0xF << (i << 2); - block_intra |= 1 << i; - } else if (is_coded[i]) { - pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : s->linesize, - (i & 4) && (s->flags & CODEC_FLAG_GRAY), - &block_tt); - block_cbp |= pat << (i << 2); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } - } else { // skipped MB - s->mb_intra = 0; - s->current_picture.qscale_table[mb_pos] = 0; - for (i = 0; i < 6; i++) { - v->mb_type[0][s->block_index[i]] = 0; - s->dc_val[0][s->block_index[i]] = 0; - } - for (i = 0; i < 4; i++) { - vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); - vc1_mc_4mv_luma(v, i, 0, 0); - } - vc1_mc_4mv_chroma(v, 0); - s->current_picture.qscale_table[mb_pos] = 0; - } - } -end: - v->cbp[s->mb_x] = block_cbp; - v->ttblk[s->mb_x] = block_tt; - v->is_intra[s->mb_x] = block_intra; - - return 0; -} - -/* Decode one macroblock in an interlaced frame p picture */ - -static int vc1_decode_p_mb_intfr(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp = 0; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - - int mb_has_coeffs = 1; /* last_flag */ - int dmv_x, dmv_y; /* Differential MV components */ - int val; /* temp value */ - int first_block = 1; - int dst_idx, off; - int skipped, fourmv = 0, twomv = 0; - int block_cbp = 0, pat, block_tt = 0; - int idx_mbmode = 0, mvbp; - int stride_y, fieldtx; - - mquant = v->pq; /* Loosy initialization */ - - if (v->skip_is_raw) - skipped = get_bits1(gb); - else - skipped = v->s.mbskip_table[mb_pos]; - if (!skipped) { - if (v->fourmvswitch) - idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_4MV_MBMODE_VLC_BITS, 2); // try getting this done - else - idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); // in a single line - switch (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0]) { - /* store the motion vector type in a flag (useful later) */ - case MV_PMODE_INTFR_4MV: - fourmv = 1; - v->blk_mv_type[s->block_index[0]] = 0; - v->blk_mv_type[s->block_index[1]] = 0; - v->blk_mv_type[s->block_index[2]] = 0; - v->blk_mv_type[s->block_index[3]] = 0; - break; - case MV_PMODE_INTFR_4MV_FIELD: - fourmv = 1; - v->blk_mv_type[s->block_index[0]] = 1; - v->blk_mv_type[s->block_index[1]] = 1; - v->blk_mv_type[s->block_index[2]] = 1; - v->blk_mv_type[s->block_index[3]] = 1; - break; - case MV_PMODE_INTFR_2MV_FIELD: - twomv = 1; - v->blk_mv_type[s->block_index[0]] = 1; - v->blk_mv_type[s->block_index[1]] = 1; - v->blk_mv_type[s->block_index[2]] = 1; - v->blk_mv_type[s->block_index[3]] = 1; - break; - case MV_PMODE_INTFR_1MV: - v->blk_mv_type[s->block_index[0]] = 0; - v->blk_mv_type[s->block_index[1]] = 0; - v->blk_mv_type[s->block_index[2]] = 0; - v->blk_mv_type[s->block_index[3]] = 0; - break; - } - if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB - for (i = 0; i < 4; i++) { - s->current_picture.motion_val[1][s->block_index[i]][0] = 0; - s->current_picture.motion_val[1][s->block_index[i]][1] = 0; - } - s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; - s->mb_intra = v->is_intra[s->mb_x] = 1; - for (i = 0; i < 6; i++) - v->mb_type[0][s->block_index[i]] = 1; - fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); - mb_has_coeffs = get_bits1(gb); - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - /* Set DC scale - y and c use the same (not sure if necessary here) */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - v->mb_type[0][s->block_index[i]] = s->mb_intra; - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (i < 4) { - stride_y = s->linesize << fieldtx; - off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; - } else { - stride_y = s->uvlinesize; - off = 0; - } - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - stride_y); - //TODO: loop filter - } - - } else { // inter MB - mb_has_coeffs = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][3]; - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) { - v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); - } else { - if ((ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV) - || (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV_FIELD)) { - v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); - } - } - s->mb_intra = v->is_intra[s->mb_x] = 0; - for (i = 0; i < 6; i++) - v->mb_type[0][s->block_index[i]] = 0; - fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][1]; - /* for all motion vector read MVDATA and motion compensate each block */ - dst_idx = 0; - if (fourmv) { - mvbp = v->fourmvbp; - for (i = 0; i < 6; i++) { - if (i < 4) { - dmv_x = dmv_y = 0; - val = ((mvbp >> (3 - i)) & 1); - if (val) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - } - vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_4mv_luma(v, i, 0, 0); - } else if (i == 4) { - vc1_mc_4mv_chroma4(v, 0, 0, 0); - } - } - } else if (twomv) { - mvbp = v->twomvbp; - dmv_x = dmv_y = 0; - if (mvbp & 2) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - } - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_4mv_luma(v, 0, 0, 0); - vc1_mc_4mv_luma(v, 1, 0, 0); - dmv_x = dmv_y = 0; - if (mvbp & 1) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - } - vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_4mv_luma(v, 2, 0, 0); - vc1_mc_4mv_luma(v, 3, 0, 0); - vc1_mc_4mv_chroma4(v, 0, 0, 0); - } else { - mvbp = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][2]; - dmv_x = dmv_y = 0; - if (mvbp) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - } - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_1mv(v, 0); - } - if (cbp) - GET_MQUANT(); // p. 227 - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf && cbp) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - if (!fieldtx) - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - else - off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); - if (val) { - pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), - (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); - block_cbp |= pat << (i << 2); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } - } - } else { // skipped - s->mb_intra = v->is_intra[s->mb_x] = 0; - for (i = 0; i < 6; i++) { - v->mb_type[0][s->block_index[i]] = 0; - s->dc_val[0][s->block_index[i]] = 0; - } - s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; - s->current_picture.qscale_table[mb_pos] = 0; - v->blk_mv_type[s->block_index[0]] = 0; - v->blk_mv_type[s->block_index[1]] = 0; - v->blk_mv_type[s->block_index[2]] = 0; - v->blk_mv_type[s->block_index[3]] = 0; - vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_1mv(v, 0); - } - if (s->mb_x == s->mb_width - 1) - memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride); - return 0; -} - -static int vc1_decode_p_mb_intfi(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp = 0; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - - int mb_has_coeffs = 1; /* last_flag */ - int dmv_x, dmv_y; /* Differential MV components */ - int val; /* temp values */ - int first_block = 1; - int dst_idx, off; - int pred_flag; - int block_cbp = 0, pat, block_tt = 0; - int idx_mbmode = 0; - - mquant = v->pq; /* Loosy initialization */ - - idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); - if (idx_mbmode <= 1) { // intra MB - s->mb_intra = v->is_intra[s->mb_x] = 1; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; - s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - /* Set DC scale - y and c use the same (not sure if necessary here) */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); - mb_has_coeffs = idx_mbmode & 1; - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - v->mb_type[0][s->block_index[i]] = 1; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize - : s->linesize); - // TODO: loop filter - } - } else { - s->mb_intra = v->is_intra[s->mb_x] = 0; - s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; - for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; - if (idx_mbmode <= 5) { // 1-MV - dmv_x = dmv_y = pred_flag = 0; - if (idx_mbmode & 1) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); - } - vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); - vc1_mc_1mv(v, 0); - mb_has_coeffs = !(idx_mbmode & 2); - } else { // 4-MV - v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); - for (i = 0; i < 6; i++) { - if (i < 4) { - dmv_x = dmv_y = pred_flag = 0; - val = ((v->fourmvbp >> (3 - i)) & 1); - if (val) { - get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); - } - vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); - vc1_mc_4mv_luma(v, i, 0, 0); - } else if (i == 4) - vc1_mc_4mv_chroma(v, 0); - } - mb_has_coeffs = idx_mbmode & 1; - } - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - if (cbp) { - GET_MQUANT(); - } - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf && cbp) { - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - } - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; - if (val) { - pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : s->linesize, - (i & 4) && (s->flags & CODEC_FLAG_GRAY), - &block_tt); - block_cbp |= pat << (i << 2); - if (!v->ttmbf && ttmb < 8) ttmb = -1; - first_block = 0; - } - } - } - if (s->mb_x == s->mb_width - 1) - memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); - return 0; -} - -/** Decode one B-frame MB (in Main profile) - */ -static void vc1_decode_b_mb(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i, j; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp = 0; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - int mb_has_coeffs = 0; /* last_flag */ - int index, index1; /* LUT indexes */ - int val, sign; /* temp values */ - int first_block = 1; - int dst_idx, off; - int skipped, direct; - int dmv_x[2], dmv_y[2]; - int bmvtype = BMV_TYPE_BACKWARD; - - mquant = v->pq; /* lossy initialization */ - s->mb_intra = 0; - - if (v->dmb_is_raw) - direct = get_bits1(gb); - else - direct = v->direct_mb_plane[mb_pos]; - if (v->skip_is_raw) - skipped = get_bits1(gb); - else - skipped = v->s.mbskip_table[mb_pos]; - - dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; - for (i = 0; i < 6; i++) { - v->mb_type[0][s->block_index[i]] = 0; - s->dc_val[0][s->block_index[i]] = 0; - } - s->current_picture.qscale_table[mb_pos] = 0; - - if (!direct) { - if (!skipped) { - GET_MVDATA(dmv_x[0], dmv_y[0]); - dmv_x[1] = dmv_x[0]; - dmv_y[1] = dmv_y[0]; - } - if (skipped || !s->mb_intra) { - bmvtype = decode012(gb); - switch (bmvtype) { - case 0: - bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; - break; - case 1: - bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; - break; - case 2: - bmvtype = BMV_TYPE_INTERPOLATED; - dmv_x[0] = dmv_y[0] = 0; - } - } - } - for (i = 0; i < 6; i++) - v->mb_type[0][s->block_index[i]] = s->mb_intra; - - if (skipped) { - if (direct) - bmvtype = BMV_TYPE_INTERPOLATED; - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); - return; - } - if (direct) { - cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - GET_MQUANT(); - s->mb_intra = 0; - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - dmv_x[0] = dmv_y[0] = dmv_x[1] = dmv_y[1] = 0; - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); - } else { - if (!mb_has_coeffs && !s->mb_intra) { - /* no coded blocks - effectively skipped */ - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); - return; - } - if (s->mb_intra && !mb_has_coeffs) { - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - s->ac_pred = get_bits1(gb); - cbp = 0; - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - } else { - if (bmvtype == BMV_TYPE_INTERPOLATED) { - GET_MVDATA(dmv_x[0], dmv_y[0]); - if (!mb_has_coeffs) { - /* interpolated skipped block */ - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); - return; - } - } - vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); - if (!s->mb_intra) { - vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); - } - if (s->mb_intra) - s->ac_pred = get_bits1(gb); - cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - } - } - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - v->mb_type[0][s->block_index[i]] = s->mb_intra; - if (s->mb_intra) { - /* check if prediction blocks A and C are available */ - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[i][j] <<= 1; - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - i & 4 ? s->uvlinesize - : s->linesize); - } else if (val) { - vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : s->linesize, - (i & 4) && (s->flags & CODEC_FLAG_GRAY), NULL); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } -} - -/** Decode one B-frame MB (in interlaced field B picture) - */ -static void vc1_decode_b_mb_intfi(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i, j; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp = 0; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - int mb_has_coeffs = 0; /* last_flag */ - int val; /* temp value */ - int first_block = 1; - int dst_idx, off; - int fwd; - int dmv_x[2], dmv_y[2], pred_flag[2]; - int bmvtype = BMV_TYPE_BACKWARD; - int idx_mbmode, interpmvp; - - mquant = v->pq; /* Loosy initialization */ - s->mb_intra = 0; - - idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); - if (idx_mbmode <= 1) { // intra MB - s->mb_intra = v->is_intra[s->mb_x] = 1; - s->current_picture.motion_val[1][s->block_index[0]][0] = 0; - s->current_picture.motion_val[1][s->block_index[0]][1] = 0; - s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - /* Set DC scale - y and c use the same (not sure if necessary here) */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); - mb_has_coeffs = idx_mbmode & 1; - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - v->mb_type[0][s->block_index[i]] = s->mb_intra; - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[i][j] <<= 1; - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize - : s->linesize); - // TODO: yet to perform loop filter - } - } else { - s->mb_intra = v->is_intra[s->mb_x] = 0; - s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; - for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; - if (v->fmb_is_raw) - fwd = v->forward_mb_plane[mb_pos] = get_bits1(gb); - else - fwd = v->forward_mb_plane[mb_pos]; - if (idx_mbmode <= 5) { // 1-MV - dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; - pred_flag[0] = pred_flag[1] = 0; - if (fwd) - bmvtype = BMV_TYPE_FORWARD; - else { - bmvtype = decode012(gb); - switch (bmvtype) { - case 0: - bmvtype = BMV_TYPE_BACKWARD; - break; - case 1: - bmvtype = BMV_TYPE_DIRECT; - break; - case 2: - bmvtype = BMV_TYPE_INTERPOLATED; - interpmvp = get_bits1(gb); - } - } - v->bmvtype = bmvtype; - if (bmvtype != BMV_TYPE_DIRECT && idx_mbmode & 1) { - get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], &dmv_y[bmvtype == BMV_TYPE_BACKWARD], &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); - } - if (bmvtype == BMV_TYPE_INTERPOLATED && interpmvp) { - get_mvdata_interlaced(v, &dmv_x[1], &dmv_y[1], &pred_flag[1]); - } - if (bmvtype == BMV_TYPE_DIRECT) { - dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; - dmv_x[1] = dmv_y[1] = pred_flag[0] = 0; - } - vc1_pred_b_mv_intfi(v, 0, dmv_x, dmv_y, 1, pred_flag); - vc1_b_mc(v, dmv_x, dmv_y, (bmvtype == BMV_TYPE_DIRECT), bmvtype); - mb_has_coeffs = !(idx_mbmode & 2); - } else { // 4-MV - if (fwd) - bmvtype = BMV_TYPE_FORWARD; - v->bmvtype = bmvtype; - v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); - for (i = 0; i < 6; i++) { - if (i < 4) { - dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; - dmv_x[1] = dmv_y[1] = pred_flag[1] = 0; - val = ((v->fourmvbp >> (3 - i)) & 1); - if (val) { - get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], - &dmv_y[bmvtype == BMV_TYPE_BACKWARD], - &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); - } - vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag); - vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD, 0); - } else if (i == 4) - vc1_mc_4mv_chroma(v, bmvtype == BMV_TYPE_BACKWARD); - } - mb_has_coeffs = idx_mbmode & 1; - } - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - if (cbp) { - GET_MQUANT(); - } - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf && cbp) { - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - } - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; - if (val) { - vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : s->linesize, - (i & 4) && (s->flags & CODEC_FLAG_GRAY), NULL); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } - } -} - -/** Decode one B-frame MB (in interlaced frame B picture) - */ -static int vc1_decode_b_mb_intfr(VC1Context *v) -{ - MpegEncContext *s = &v->s; - GetBitContext *gb = &s->gb; - int i, j; - int mb_pos = s->mb_x + s->mb_y * s->mb_stride; - int cbp = 0; /* cbp decoding stuff */ - int mqdiff, mquant; /* MB quantization */ - int ttmb = v->ttfrm; /* MB Transform type */ - int mvsw = 0; /* motion vector switch */ - int mb_has_coeffs = 1; /* last_flag */ - int dmv_x, dmv_y; /* Differential MV components */ - int val; /* temp value */ - int first_block = 1; - int dst_idx, off; - int skipped, direct, twomv = 0; - int block_cbp = 0, pat, block_tt = 0; - int idx_mbmode = 0, mvbp; - int stride_y, fieldtx; - int bmvtype = BMV_TYPE_BACKWARD; - int dir, dir2; - - mquant = v->pq; /* Lossy initialization */ - s->mb_intra = 0; - if (v->skip_is_raw) - skipped = get_bits1(gb); - else - skipped = v->s.mbskip_table[mb_pos]; - - if (!skipped) { - idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); - if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) { - twomv = 1; - v->blk_mv_type[s->block_index[0]] = 1; - v->blk_mv_type[s->block_index[1]] = 1; - v->blk_mv_type[s->block_index[2]] = 1; - v->blk_mv_type[s->block_index[3]] = 1; - } else { - v->blk_mv_type[s->block_index[0]] = 0; - v->blk_mv_type[s->block_index[1]] = 0; - v->blk_mv_type[s->block_index[2]] = 0; - v->blk_mv_type[s->block_index[3]] = 0; - } - } - - if (v->dmb_is_raw) - direct = get_bits1(gb); - else - direct = v->direct_mb_plane[mb_pos]; - - if (direct) { - s->mv[0][0][0] = s->current_picture.motion_val[0][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 0, s->quarter_sample); - s->mv[0][0][1] = s->current_picture.motion_val[0][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 0, s->quarter_sample); - s->mv[1][0][0] = s->current_picture.motion_val[1][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 1, s->quarter_sample); - s->mv[1][0][1] = s->current_picture.motion_val[1][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 1, s->quarter_sample); - - if (twomv) { - s->mv[0][2][0] = s->current_picture.motion_val[0][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 0, s->quarter_sample); - s->mv[0][2][1] = s->current_picture.motion_val[0][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 0, s->quarter_sample); - s->mv[1][2][0] = s->current_picture.motion_val[1][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 1, s->quarter_sample); - s->mv[1][2][1] = s->current_picture.motion_val[1][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 1, s->quarter_sample); - - for (i = 1; i < 4; i += 2) { - s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][i-1][0]; - s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][i-1][1]; - s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][i-1][0]; - s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][i-1][1]; - } - } else { - for (i = 1; i < 4; i++) { - s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][0][0]; - s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][0][1]; - s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][0][0]; - s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][0][1]; - } - } - } - - if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB - for (i = 0; i < 4; i++) { - s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = 0; - s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = 0; - s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = 0; - s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = 0; - } - s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; - s->mb_intra = v->is_intra[s->mb_x] = 1; - for (i = 0; i < 6; i++) - v->mb_type[0][s->block_index[i]] = 1; - fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); - mb_has_coeffs = get_bits1(gb); - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); - GET_MQUANT(); - s->current_picture.qscale_table[mb_pos] = mquant; - /* Set DC scale - y and c use the same (not sure if necessary here) */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - dst_idx = 0; - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - v->mb_type[0][s->block_index[i]] = s->mb_intra; - v->a_avail = v->c_avail = 0; - if (i == 2 || i == 3 || !s->first_slice_line) - v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; - if (i == 1 || i == 3 || s->mb_x) - v->c_avail = v->mb_type[0][s->block_index[i] - 1]; - - vc1_decode_intra_block(v, s->block[i], i, val, mquant, - (i & 4) ? v->codingset2 : v->codingset); - if (i > 3 && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); - if (i < 4) { - stride_y = s->linesize << fieldtx; - off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; - } else { - stride_y = s->uvlinesize; - off = 0; - } - s->idsp.put_signed_pixels_clamped(s->block[i], - s->dest[dst_idx] + off, - stride_y); - } - } else { - s->mb_intra = v->is_intra[s->mb_x] = 0; - if (!direct) { - if (skipped || !s->mb_intra) { - bmvtype = decode012(gb); - switch (bmvtype) { - case 0: - bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; - break; - case 1: - bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; - break; - case 2: - bmvtype = BMV_TYPE_INTERPOLATED; - } - } - - if (twomv && bmvtype != BMV_TYPE_INTERPOLATED) - mvsw = get_bits1(gb); - } - - if (!skipped) { // inter MB - mb_has_coeffs = ff_vc1_mbmode_intfrp[0][idx_mbmode][3]; - if (mb_has_coeffs) - cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); - if (!direct) { - if (bmvtype == BMV_TYPE_INTERPOLATED && twomv) { - v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); - } else if (bmvtype == BMV_TYPE_INTERPOLATED || twomv) { - v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); - } - } - - for (i = 0; i < 6; i++) - v->mb_type[0][s->block_index[i]] = 0; - fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[0][idx_mbmode][1]; - /* for all motion vector read MVDATA and motion compensate each block */ - dst_idx = 0; - if (direct) { - if (twomv) { - for (i = 0; i < 4; i++) { - vc1_mc_4mv_luma(v, i, 0, 0); - vc1_mc_4mv_luma(v, i, 1, 1); - } - vc1_mc_4mv_chroma4(v, 0, 0, 0); - vc1_mc_4mv_chroma4(v, 1, 1, 1); - } else { - vc1_mc_1mv(v, 0); - vc1_interp_mc(v); - } - } else if (twomv && bmvtype == BMV_TYPE_INTERPOLATED) { - mvbp = v->fourmvbp; - for (i = 0; i < 4; i++) { - dir = i==1 || i==3; - dmv_x = dmv_y = 0; - val = ((mvbp >> (3 - i)) & 1); - if (val) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - j = i > 1 ? 2 : 0; - vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); - vc1_mc_4mv_luma(v, j, dir, dir); - vc1_mc_4mv_luma(v, j+1, dir, dir); - } - - vc1_mc_4mv_chroma4(v, 0, 0, 0); - vc1_mc_4mv_chroma4(v, 1, 1, 1); - } else if (bmvtype == BMV_TYPE_INTERPOLATED) { - mvbp = v->twomvbp; - dmv_x = dmv_y = 0; - if (mvbp & 2) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_mc_1mv(v, 0); - - dmv_x = dmv_y = 0; - if (mvbp & 1) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 1); - vc1_interp_mc(v); - } else if (twomv) { - dir = bmvtype == BMV_TYPE_BACKWARD; - dir2 = dir; - if (mvsw) - dir2 = !dir; - mvbp = v->twomvbp; - dmv_x = dmv_y = 0; - if (mvbp & 2) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); - - dmv_x = dmv_y = 0; - if (mvbp & 1) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir2); - - if (mvsw) { - for (i = 0; i < 2; i++) { - s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; - s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; - s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; - s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; - } - } else { - vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); - vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); - } - - vc1_mc_4mv_luma(v, 0, dir, 0); - vc1_mc_4mv_luma(v, 1, dir, 0); - vc1_mc_4mv_luma(v, 2, dir2, 0); - vc1_mc_4mv_luma(v, 3, dir2, 0); - vc1_mc_4mv_chroma4(v, dir, dir2, 0); - } else { - dir = bmvtype == BMV_TYPE_BACKWARD; - - mvbp = ff_vc1_mbmode_intfrp[0][idx_mbmode][2]; - dmv_x = dmv_y = 0; - if (mvbp) - get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); - - vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], dir); - v->blk_mv_type[s->block_index[0]] = 1; - v->blk_mv_type[s->block_index[1]] = 1; - v->blk_mv_type[s->block_index[2]] = 1; - v->blk_mv_type[s->block_index[3]] = 1; - vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); - for (i = 0; i < 2; i++) { - s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; - s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; - } - vc1_mc_1mv(v, dir); - } - - if (cbp) - GET_MQUANT(); // p. 227 - s->current_picture.qscale_table[mb_pos] = mquant; - if (!v->ttmbf && cbp) - ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); - for (i = 0; i < 6; i++) { - s->dc_val[0][s->block_index[i]] = 0; - dst_idx += i >> 2; - val = ((cbp >> (5 - i)) & 1); - if (!fieldtx) - off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); - else - off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); - if (val) { - pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, - first_block, s->dest[dst_idx] + off, - (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), - (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); - block_cbp |= pat << (i << 2); - if (!v->ttmbf && ttmb < 8) - ttmb = -1; - first_block = 0; - } - } - - } else { // skipped - dir = 0; - for (i = 0; i < 6; i++) { - v->mb_type[0][s->block_index[i]] = 0; - s->dc_val[0][s->block_index[i]] = 0; - } - s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; - s->current_picture.qscale_table[mb_pos] = 0; - v->blk_mv_type[s->block_index[0]] = 0; - v->blk_mv_type[s->block_index[1]] = 0; - v->blk_mv_type[s->block_index[2]] = 0; - v->blk_mv_type[s->block_index[3]] = 0; - - if (!direct) { - if (bmvtype == BMV_TYPE_INTERPOLATED) { - vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); - vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 1); - } else { - dir = bmvtype == BMV_TYPE_BACKWARD; - vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], dir); - if (mvsw) { - int dir2 = dir; - if (mvsw) - dir2 = !dir; - for (i = 0; i < 2; i++) { - s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; - s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; - s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; - s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; - } - } else { - v->blk_mv_type[s->block_index[0]] = 1; - v->blk_mv_type[s->block_index[1]] = 1; - v->blk_mv_type[s->block_index[2]] = 1; - v->blk_mv_type[s->block_index[3]] = 1; - vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); - for (i = 0; i < 2; i++) { - s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; - s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; - } - } - } - } - - vc1_mc_1mv(v, dir); - if (direct || bmvtype == BMV_TYPE_INTERPOLATED) { - vc1_interp_mc(v); - } - } - } - if (s->mb_x == s->mb_width - 1) - memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); - v->cbp[s->mb_x] = block_cbp; - v->ttblk[s->mb_x] = block_tt; - return 0; -} - -/** Decode blocks of I-frame - */ -static void vc1_decode_i_blocks(VC1Context *v) -{ - int k, j; - MpegEncContext *s = &v->s; - int cbp, val; - uint8_t *coded_val; - int mb_pos; - - /* select codingmode used for VLC tables selection */ - switch (v->y_ac_table_index) { - case 0: - v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; - break; - case 1: - v->codingset = CS_HIGH_MOT_INTRA; - break; - case 2: - v->codingset = CS_MID_RATE_INTRA; - break; - } - - switch (v->c_ac_table_index) { - case 0: - v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; - break; - case 1: - v->codingset2 = CS_HIGH_MOT_INTER; - break; - case 2: - v->codingset2 = CS_MID_RATE_INTER; - break; - } - - /* Set DC scale - y and c use the same */ - s->y_dc_scale = s->y_dc_scale_table[v->pq]; - s->c_dc_scale = s->c_dc_scale_table[v->pq]; - - //do frame decode - s->mb_x = s->mb_y = 0; - s->mb_intra = 1; - s->first_slice_line = 1; - for (s->mb_y = 0; s->mb_y < s->end_mb_y; s->mb_y++) { - s->mb_x = 0; - init_block_index(v); - for (; s->mb_x < v->end_mb_x; s->mb_x++) { - uint8_t *dst[6]; - ff_update_block_index(s); - dst[0] = s->dest[0]; - dst[1] = dst[0] + 8; - dst[2] = s->dest[0] + s->linesize * 8; - dst[3] = dst[2] + 8; - dst[4] = s->dest[1]; - dst[5] = s->dest[2]; - s->bdsp.clear_blocks(s->block[0]); - mb_pos = s->mb_x + s->mb_y * s->mb_width; - s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; - s->current_picture.qscale_table[mb_pos] = v->pq; - s->current_picture.motion_val[1][s->block_index[0]][0] = 0; - s->current_picture.motion_val[1][s->block_index[0]][1] = 0; - - // do actual MB decoding and displaying - cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); - v->s.ac_pred = get_bits1(&v->s.gb); - - for (k = 0; k < 6; k++) { - val = ((cbp >> (5 - k)) & 1); - - if (k < 4) { - int pred = vc1_coded_block_pred(&v->s, k, &coded_val); - val = val ^ pred; - *coded_val = val; - } - cbp |= val << (5 - k); - - vc1_decode_i_block(v, s->block[k], k, val, (k < 4) ? v->codingset : v->codingset2); - - if (k > 3 && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(s->block[k]); - if (v->pq >= 9 && v->overlap) { - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[k][j] <<= 1; - s->idsp.put_signed_pixels_clamped(s->block[k], dst[k], - k & 4 ? s->uvlinesize - : s->linesize); - } else { - if (v->rangeredfrm) - for (j = 0; j < 64; j++) - s->block[k][j] = (s->block[k][j] - 64) << 1; - s->idsp.put_pixels_clamped(s->block[k], dst[k], - k & 4 ? s->uvlinesize - : s->linesize); - } - } - - if (v->pq >= 9 && v->overlap) { - if (s->mb_x) { - v->vc1dsp.vc1_h_overlap(s->dest[0], s->linesize); - v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize); - if (!(s->flags & CODEC_FLAG_GRAY)) { - v->vc1dsp.vc1_h_overlap(s->dest[1], s->uvlinesize); - v->vc1dsp.vc1_h_overlap(s->dest[2], s->uvlinesize); - } - } - v->vc1dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize); - v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); - if (!s->first_slice_line) { - v->vc1dsp.vc1_v_overlap(s->dest[0], s->linesize); - v->vc1dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize); - if (!(s->flags & CODEC_FLAG_GRAY)) { - v->vc1dsp.vc1_v_overlap(s->dest[1], s->uvlinesize); - v->vc1dsp.vc1_v_overlap(s->dest[2], s->uvlinesize); - } - } - v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize); - v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); - } - if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq); - - if (get_bits_count(&s->gb) > v->bits) { - ff_er_add_slice(&s->er, 0, 0, s->mb_x, s->mb_y, ER_MB_ERROR); - av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", - get_bits_count(&s->gb), v->bits); - return; - } - } - if (!v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); - else if (s->mb_y) - ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); - - s->first_slice_line = 0; - } - if (v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); - - /* This is intentionally mb_height and not end_mb_y - unlike in advanced - * profile, these only differ are when decoding MSS2 rectangles. */ - ff_er_add_slice(&s->er, 0, 0, s->mb_width - 1, s->mb_height - 1, ER_MB_END); -} - -/** Decode blocks of I-frame for advanced profile - */ -static void vc1_decode_i_blocks_adv(VC1Context *v) -{ - int k; - MpegEncContext *s = &v->s; - int cbp, val; - uint8_t *coded_val; - int mb_pos; - int mquant = v->pq; - int mqdiff; - GetBitContext *gb = &s->gb; - - /* select codingmode used for VLC tables selection */ - switch (v->y_ac_table_index) { - case 0: - v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; - break; - case 1: - v->codingset = CS_HIGH_MOT_INTRA; - break; - case 2: - v->codingset = CS_MID_RATE_INTRA; - break; - } - - switch (v->c_ac_table_index) { - case 0: - v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; - break; - case 1: - v->codingset2 = CS_HIGH_MOT_INTER; - break; - case 2: - v->codingset2 = CS_MID_RATE_INTER; - break; - } - - // do frame decode - s->mb_x = s->mb_y = 0; - s->mb_intra = 1; - s->first_slice_line = 1; - s->mb_y = s->start_mb_y; - if (s->start_mb_y) { - s->mb_x = 0; - init_block_index(v); - memset(&s->coded_block[s->block_index[0] - s->b8_stride], 0, - (1 + s->b8_stride) * sizeof(*s->coded_block)); - } - for (; s->mb_y < s->end_mb_y; s->mb_y++) { - s->mb_x = 0; - init_block_index(v); - for (;s->mb_x < s->mb_width; s->mb_x++) { - int16_t (*block)[64] = v->block[v->cur_blk_idx]; - ff_update_block_index(s); - s->bdsp.clear_blocks(block[0]); - mb_pos = s->mb_x + s->mb_y * s->mb_stride; - s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; - s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; - - // do actual MB decoding and displaying - if (v->fieldtx_is_raw) - v->fieldtx_plane[mb_pos] = get_bits1(&v->s.gb); - cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); - if ( v->acpred_is_raw) - v->s.ac_pred = get_bits1(&v->s.gb); - else - v->s.ac_pred = v->acpred_plane[mb_pos]; - - if (v->condover == CONDOVER_SELECT && v->overflg_is_raw) - v->over_flags_plane[mb_pos] = get_bits1(&v->s.gb); - - GET_MQUANT(); - - s->current_picture.qscale_table[mb_pos] = mquant; - /* Set DC scale - y and c use the same */ - s->y_dc_scale = s->y_dc_scale_table[mquant]; - s->c_dc_scale = s->c_dc_scale_table[mquant]; - - for (k = 0; k < 6; k++) { - val = ((cbp >> (5 - k)) & 1); - - if (k < 4) { - int pred = vc1_coded_block_pred(&v->s, k, &coded_val); - val = val ^ pred; - *coded_val = val; - } - cbp |= val << (5 - k); - - v->a_avail = !s->first_slice_line || (k == 2 || k == 3); - v->c_avail = !!s->mb_x || (k == 1 || k == 3); - - vc1_decode_i_block_adv(v, block[k], k, val, - (k < 4) ? v->codingset : v->codingset2, mquant); - - if (k > 3 && (s->flags & CODEC_FLAG_GRAY)) - continue; - v->vc1dsp.vc1_inv_trans_8x8(block[k]); - } - - vc1_smooth_overlap_filter_iblk(v); - vc1_put_signed_blocks_clamped(v); - if (v->s.loop_filter) vc1_loop_filter_iblk_delayed(v, v->pq); - - if (get_bits_count(&s->gb) > v->bits) { - // TODO: may need modification to handle slice coding - ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); - av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", - get_bits_count(&s->gb), v->bits); - return; - } - } - if (!v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); - else if (s->mb_y) - ff_mpeg_draw_horiz_band(s, (s->mb_y-1) * 16, 16); - s->first_slice_line = 0; - } - - /* raw bottom MB row */ - s->mb_x = 0; - init_block_index(v); - - for (;s->mb_x < s->mb_width; s->mb_x++) { - ff_update_block_index(s); - vc1_put_signed_blocks_clamped(v); - if (v->s.loop_filter) - vc1_loop_filter_iblk_delayed(v, v->pq); - } - if (v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, (s->end_mb_y-1)*16, 16); - ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, - (s->end_mb_y << v->field_mode) - 1, ER_MB_END); -} - -static void vc1_decode_p_blocks(VC1Context *v) -{ - MpegEncContext *s = &v->s; - int apply_loop_filter; - - /* select codingmode used for VLC tables selection */ - switch (v->c_ac_table_index) { - case 0: - v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; - break; - case 1: - v->codingset = CS_HIGH_MOT_INTRA; - break; - case 2: - v->codingset = CS_MID_RATE_INTRA; - break; - } - - switch (v->c_ac_table_index) { - case 0: - v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; - break; - case 1: - v->codingset2 = CS_HIGH_MOT_INTER; - break; - case 2: - v->codingset2 = CS_MID_RATE_INTER; - break; - } - - apply_loop_filter = s->loop_filter && !(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY) && - v->fcm == PROGRESSIVE; - s->first_slice_line = 1; - memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); - for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { - s->mb_x = 0; - init_block_index(v); - for (; s->mb_x < s->mb_width; s->mb_x++) { - ff_update_block_index(s); - - if (v->fcm == ILACE_FIELD) - vc1_decode_p_mb_intfi(v); - else if (v->fcm == ILACE_FRAME) - vc1_decode_p_mb_intfr(v); - else vc1_decode_p_mb(v); - if (s->mb_y != s->start_mb_y && apply_loop_filter) - vc1_apply_p_loop_filter(v); - if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { - // TODO: may need modification to handle slice coding - ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); - av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", - get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); - return; - } - } - memmove(v->cbp_base, v->cbp, sizeof(v->cbp_base[0]) * s->mb_stride); - memmove(v->ttblk_base, v->ttblk, sizeof(v->ttblk_base[0]) * s->mb_stride); - memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); - memmove(v->luma_mv_base, v->luma_mv, sizeof(v->luma_mv_base[0]) * s->mb_stride); - if (s->mb_y != s->start_mb_y) ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); - s->first_slice_line = 0; - } - if (apply_loop_filter) { - s->mb_x = 0; - init_block_index(v); - for (; s->mb_x < s->mb_width; s->mb_x++) { - ff_update_block_index(s); - vc1_apply_p_loop_filter(v); - } - } - if (s->end_mb_y >= s->start_mb_y) - ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); - ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, - (s->end_mb_y << v->field_mode) - 1, ER_MB_END); -} - -static void vc1_decode_b_blocks(VC1Context *v) -{ - MpegEncContext *s = &v->s; - - /* select codingmode used for VLC tables selection */ - switch (v->c_ac_table_index) { - case 0: - v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; - break; - case 1: - v->codingset = CS_HIGH_MOT_INTRA; - break; - case 2: - v->codingset = CS_MID_RATE_INTRA; - break; - } - - switch (v->c_ac_table_index) { - case 0: - v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; - break; - case 1: - v->codingset2 = CS_HIGH_MOT_INTER; - break; - case 2: - v->codingset2 = CS_MID_RATE_INTER; - break; - } - - s->first_slice_line = 1; - for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { - s->mb_x = 0; - init_block_index(v); - for (; s->mb_x < s->mb_width; s->mb_x++) { - ff_update_block_index(s); - - if (v->fcm == ILACE_FIELD) - vc1_decode_b_mb_intfi(v); - else if (v->fcm == ILACE_FRAME) - vc1_decode_b_mb_intfr(v); - else - vc1_decode_b_mb(v); - if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { - // TODO: may need modification to handle slice coding - ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); - av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", - get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); - return; - } - if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq); - } - if (!v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); - else if (s->mb_y) - ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); - s->first_slice_line = 0; - } - if (v->s.loop_filter) - ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); - ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, - (s->end_mb_y << v->field_mode) - 1, ER_MB_END); -} - -static void vc1_decode_skip_blocks(VC1Context *v) -{ - MpegEncContext *s = &v->s; - - if (!v->s.last_picture.f->data[0]) - return; - - ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, ER_MB_END); - s->first_slice_line = 1; - for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { - s->mb_x = 0; - init_block_index(v); - ff_update_block_index(s); - memcpy(s->dest[0], s->last_picture.f->data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16); - memcpy(s->dest[1], s->last_picture.f->data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); - memcpy(s->dest[2], s->last_picture.f->data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); - ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); - s->first_slice_line = 0; - } - s->pict_type = AV_PICTURE_TYPE_P; -} - -void ff_vc1_decode_blocks(VC1Context *v) -{ - - v->s.esc3_level_length = 0; - if (v->x8_type) { - ff_intrax8_decode_picture(&v->x8, 2*v->pq + v->halfpq, v->pq * !v->pquantizer); - } else { - v->cur_blk_idx = 0; - v->left_blk_idx = -1; - v->topleft_blk_idx = 1; - v->top_blk_idx = 2; - switch (v->s.pict_type) { - case AV_PICTURE_TYPE_I: - if (v->profile == PROFILE_ADVANCED) - vc1_decode_i_blocks_adv(v); - else - vc1_decode_i_blocks(v); - break; - case AV_PICTURE_TYPE_P: - if (v->p_frame_skipped) - vc1_decode_skip_blocks(v); - else - vc1_decode_p_blocks(v); - break; - case AV_PICTURE_TYPE_B: - if (v->bi_type) { - if (v->profile == PROFILE_ADVANCED) - vc1_decode_i_blocks_adv(v); - else - vc1_decode_i_blocks(v); - } else - vc1_decode_b_blocks(v); - break; - } - } -} +#include "avcodec.h" +#include "blockdsp.h" +#include "get_bits.h" +#include "internal.h" +#include "mpeg_er.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "profiles.h" +#include "vc1.h" +#include "vc1data.h" #if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER -typedef struct { +typedef struct SpriteData { /** * Transform coefficients for both sprites in 16.16 fixed point format, * in the order they appear in the bitstream: @@ -5384,9 +183,9 @@ static void vc1_draw_sprites(VC1Context *v, SpriteData* sd) yoff[i] = av_clip(sd->coefs[i][5], 0, v->sprite_height-1 << 16); yadv[i] = av_clip(sd->coefs[i][4], 0, ((v->sprite_height << 16) - yoff[i]) / v->output_height); } - alpha = av_clip(sd->coefs[1][6], 0, (1<<16) - 1); + alpha = av_clip_uint16(sd->coefs[1][6]); - for (plane = 0; plane < (s->flags&CODEC_FLAG_GRAY ? 1 : 3); plane++) { + for (plane = 0; plane < (s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++) { int width = v->output_width>>!!plane; for (row = 0; row < v->output_height>>!!plane; row++) { @@ -5471,7 +270,7 @@ static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) vc1_parse_sprites(v, gb, &sd); - if (!s->current_picture.f->data[0]) { + if (!s->current_picture.f || !s->current_picture.f->data[0]) { av_log(avctx, AV_LOG_ERROR, "Got no sprites\n"); return -1; } @@ -5504,7 +303,7 @@ static void vc1_sprite_flush(AVCodecContext *avctx) wrong but it looks better than doing nothing. */ if (f && f->data[0]) - for (plane = 0; plane < (s->flags&CODEC_FLAG_GRAY ? 1 : 3); plane++) + for (plane = 0; plane < (s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++) for (i = 0; i < v->sprite_height>>!!plane; i++) memset(f->data[plane] + i * f->linesize[plane], plane ? 128 : 0, f->linesize[plane]); @@ -5515,7 +314,7 @@ static void vc1_sprite_flush(AVCodecContext *avctx) av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v) { MpegEncContext *s = &v->s; - int i; + int i, ret = AVERROR(ENOMEM); int mb_height = FFALIGN(s->mb_height, 2); /* Allocate mb bitplanes */ @@ -5525,66 +324,72 @@ av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v) v->fieldtx_plane = av_mallocz(s->mb_stride * mb_height); v->acpred_plane = av_malloc (s->mb_stride * mb_height); v->over_flags_plane = av_malloc (s->mb_stride * mb_height); + if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->forward_mb_plane || + !v->fieldtx_plane || !v->acpred_plane || !v->over_flags_plane) + goto error; v->n_allocated_blks = s->mb_width + 2; v->block = av_malloc(sizeof(*v->block) * v->n_allocated_blks); v->cbp_base = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride); + if (!v->block || !v->cbp_base) + goto error; v->cbp = v->cbp_base + s->mb_stride; v->ttblk_base = av_malloc(sizeof(v->ttblk_base[0]) * 2 * s->mb_stride); + if (!v->ttblk_base) + goto error; v->ttblk = v->ttblk_base + s->mb_stride; v->is_intra_base = av_mallocz(sizeof(v->is_intra_base[0]) * 2 * s->mb_stride); + if (!v->is_intra_base) + goto error; v->is_intra = v->is_intra_base + s->mb_stride; v->luma_mv_base = av_malloc(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride); + if (!v->luma_mv_base) + goto error; v->luma_mv = v->luma_mv_base + s->mb_stride; /* allocate block type info in that way so it could be used with s->block_index[] */ v->mb_type_base = av_malloc(s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2); + if (!v->mb_type_base) + goto error; v->mb_type[0] = v->mb_type_base + s->b8_stride + 1; v->mb_type[1] = v->mb_type_base + s->b8_stride * (mb_height * 2 + 1) + s->mb_stride + 1; v->mb_type[2] = v->mb_type[1] + s->mb_stride * (mb_height + 1); /* allocate memory to store block level MV info */ v->blk_mv_type_base = av_mallocz( s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2); + if (!v->blk_mv_type_base) + goto error; v->blk_mv_type = v->blk_mv_type_base + s->b8_stride + 1; v->mv_f_base = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2)); + if (!v->mv_f_base) + goto error; v->mv_f[0] = v->mv_f_base + s->b8_stride + 1; v->mv_f[1] = v->mv_f[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2); v->mv_f_next_base = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2)); + if (!v->mv_f_next_base) + goto error; v->mv_f_next[0] = v->mv_f_next_base + s->b8_stride + 1; v->mv_f_next[1] = v->mv_f_next[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2); - /* Init coded blocks info */ - if (v->profile == PROFILE_ADVANCED) { -// if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0) -// return -1; -// if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0) -// return -1; - } - - ff_intrax8_common_init(&v->x8,s); - if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { - for (i = 0; i < 4; i++) - if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width))) return -1; + for (i = 0; i < 4; i++) { + v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width); + if (!v->sr_rows[i >> 1][i & 1]) + goto error; + } } - if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->acpred_plane || !v->over_flags_plane || - !v->block || !v->cbp_base || !v->ttblk_base || !v->is_intra_base || !v->luma_mv_base || - !v->mb_type_base) { - 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->block); - av_freep(&v->cbp_base); - av_freep(&v->ttblk_base); - av_freep(&v->is_intra_base); - av_freep(&v->luma_mv_base); - av_freep(&v->mb_type_base); - return AVERROR(ENOMEM); - } + ret = ff_intrax8_common_init(s->avctx, &v->x8, &s->idsp, + s->block, s->block_last_index, + s->mb_width, s->mb_height); + if (ret < 0) + goto error; return 0; + +error: + ff_vc1_decode_end(s->avctx); + return ret; } av_cold void ff_vc1_init_transposed_scantables(VC1Context *v) @@ -5604,7 +409,7 @@ av_cold void ff_vc1_init_transposed_scantables(VC1Context *v) /** Initialize a VC1/WMV3 decoder * @todo TODO: Handle VC-1 IDUs (Transport level?) - * @todo TODO: Decypher remaining bits in extra_data + * @todo TODO: Decipher remaining bits in extra_data */ static av_cold int vc1_decode_init(AVCodecContext *avctx) { @@ -5618,7 +423,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) if (!avctx->extradata_size || !avctx->extradata) return -1; - if (!(avctx->flags & CODEC_FLAG_GRAY)) + if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); else avctx->pix_fmt = AV_PIX_FMT_GRAY8; @@ -5646,7 +451,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) 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)); + count, get_bits_long(&gb, FFMIN(count, 32))); } else if (count < 0) { av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count); } @@ -5663,7 +468,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) return -1; } - buf2 = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + buf2 = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); start = find_next_marker(start, end); // in WVC1 extradata first byte is its size, but can be 0 in mkv next = start; for (; next < end; start = next) { @@ -5708,6 +513,13 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) avctx->has_b_frames = !!avctx->max_b_frames; + if (v->color_prim == 1 || v->color_prim == 5 || v->color_prim == 6) + avctx->color_primaries = v->color_prim; + if (v->transfer_char == 1 || v->transfer_char == 7) + avctx->color_trc = v->transfer_char; + if (v->matrix_coef == 1 || v->matrix_coef == 6 || v->matrix_coef == 7) + avctx->colorspace = v->matrix_coef; + s->mb_width = (avctx->coded_width + 15) >> 4; s->mb_height = (avctx->coded_height + 15) >> 4; @@ -5807,7 +619,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, //for advanced profile we may need to parse and unescape data if (avctx->codec_id == AV_CODEC_ID_VC1 || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { int buf_size2 = 0; - buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + buf2 = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (IS_MARKER(AV_RB32(buf))) { /* frame starts with marker and needs to be parsed */ const uint8_t *start, *end, *next; @@ -5830,7 +642,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (!tmp) goto err; slices = tmp; - slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!slices[n_slices].buf) goto err; buf_size3 = vc1_unescape_buffer(start + 4, size, @@ -5855,7 +667,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (!tmp) goto err; slices = tmp; - slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!slices[n_slices].buf) goto err; buf_size3 = vc1_unescape_buffer(start + 4, size, @@ -5881,7 +693,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, if (!tmp) goto err; slices = tmp; - slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!slices[n_slices].buf) goto err; buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf); @@ -6069,6 +881,12 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, s->end_mb_y = (i == n_slices ) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); else s->end_mb_y = (i <= n_slices1 + 1) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); + + if (s->end_mb_y <= s->start_mb_y) { + av_log(v->s.avctx, AV_LOG_ERROR, "Invalid slice size\n"); + goto err; + } + ff_vc1_decode_blocks(v); if (i != n_slices) s->gb = slices[i].gb; @@ -6085,7 +903,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, FFSWAP(uint8_t *, v->mv_f_next[1], v->mv_f[1]); } } - av_dlog(s->avctx, "Consumed %i/%i bits\n", + ff_dlog(s->avctx, "Consumed %i/%i bits\n", get_bits_count(&s->gb), s->gb.size_in_bits); // if (get_bits_count(&s->gb) > buf_size * 8) // return -1; @@ -6138,20 +956,15 @@ err: } -static const AVProfile profiles[] = { - { FF_PROFILE_VC1_SIMPLE, "Simple" }, - { FF_PROFILE_VC1_MAIN, "Main" }, - { FF_PROFILE_VC1_COMPLEX, "Complex" }, - { FF_PROFILE_VC1_ADVANCED, "Advanced" }, - { FF_PROFILE_UNKNOWN }, -}; - static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { #if CONFIG_VC1_DXVA2_HWACCEL AV_PIX_FMT_DXVA2_VLD, #endif +#if CONFIG_VC1_D3D11VA_HWACCEL + AV_PIX_FMT_D3D11VA_VLD, +#endif #if CONFIG_VC1_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI_VLD, + AV_PIX_FMT_VAAPI, #endif #if CONFIG_VC1_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, @@ -6170,9 +983,9 @@ AVCodec ff_vc1_decoder = { .close = ff_vc1_decode_end, .decode = vc1_decode_frame, .flush = ff_mpeg_flush, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, - .profiles = NULL_IF_CONFIG_SMALL(profiles) + .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #if CONFIG_WMV3_DECODER @@ -6186,9 +999,9 @@ AVCodec ff_wmv3_decoder = { .close = ff_vc1_decode_end, .decode = vc1_decode_frame, .flush = ff_mpeg_flush, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, - .profiles = NULL_IF_CONFIG_SMALL(profiles) + .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #endif @@ -6202,7 +1015,7 @@ AVCodec ff_wmv3image_decoder = { .init = vc1_decode_init, .close = ff_vc1_decode_end, .decode = vc1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = vc1_sprite_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, @@ -6221,7 +1034,7 @@ AVCodec ff_vc1image_decoder = { .init = vc1_decode_init, .close = ff_vc1_decode_end, .decode = vc1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = vc1_sprite_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c index a193dd7..cbcc8d2 100644 --- a/libavcodec/vc1dsp.c +++ b/libavcodec/vc1dsp.c @@ -22,7 +22,6 @@ /** * @file * VC-1 and WMV3 decoder - * */ #include "libavutil/common.h" diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h index 682f682..f2b0c70 100644 --- a/libavcodec/vc1dsp.h +++ b/libavcodec/vc1dsp.h @@ -22,7 +22,6 @@ /** * @file * VC-1 and WMV3 decoder - * */ #ifndef AVCODEC_VC1DSP_H diff --git a/libavcodec/vcr1.c b/libavcodec/vcr1.c index 161704f..76c47eb 100644 --- a/libavcodec/vcr1.c +++ b/libavcodec/vcr1.c @@ -138,5 +138,5 @@ AVCodec ff_vcr1_decoder = { .priv_data_size = sizeof(VCR1Context), .init = vcr1_decode_init, .decode = vcr1_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vda.c b/libavcodec/vda.c index f71fb16..eb4b998 100644 --- a/libavcodec/vda.c +++ b/libavcodec/vda.c @@ -28,15 +28,22 @@ AVVDAContext *av_vda_alloc_context(void) { AVVDAContext *ret = av_mallocz(sizeof(*ret)); - if (ret) + if (ret) { ret->output_callback = ff_vda_output_callback; + ret->cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8; + } return ret; } int av_vda_default_init(AVCodecContext *avctx) { - avctx->hwaccel_context = av_vda_alloc_context(); + return av_vda_default_init2(avctx, NULL); +} + +int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx) +{ + avctx->hwaccel_context = vdactx ?: av_vda_alloc_context(); if (!avctx->hwaccel_context) return AVERROR(ENOMEM); return ff_vda_default_init(avctx); diff --git a/libavcodec/vda.h b/libavcodec/vda.h index 9aa5d29..5e7228c 100644 --- a/libavcodec/vda.h +++ b/libavcodec/vda.h @@ -153,6 +153,12 @@ typedef struct AVVDAContext { * Set by av_vda_alloc_context(). */ VDADecoderOutputCallback output_callback; + + /** + * CVPixelBuffer Format Type that VDA will use for decoded frames; set by + * the caller. + */ + OSType cv_pix_fmt_type; } AVVDAContext; /** @@ -181,6 +187,17 @@ AVVDAContext *av_vda_alloc_context(void); int av_vda_default_init(AVCodecContext *avctx); /** + * This is a convenience function that creates and sets up the VDA context using + * an internal implementation. + * + * @param avctx the corresponding codec context + * @param vdactx the VDA context to use + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx); + +/** * This function must be called to free the VDA context initialized with * av_vda_default_init(). * diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index c7f6a74..037715d 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -25,7 +25,7 @@ #include #include "libavutil/avutil.h" -#include "h264.h" +#include "h264dec.h" #include "internal.h" #include "vda.h" #include "vda_internal.h" @@ -129,7 +129,7 @@ static int vda_old_h264_end_frame(AVCodecContext *avctx) H264Context *h = avctx->priv_data; VDAContext *vda = avctx->internal->hwaccel_priv_data; struct vda_context *vda_ctx = avctx->hwaccel_context; - AVFrame *frame = &h->cur_pic_ptr->f; + AVFrame *frame = h->cur_pic_ptr->f; int status; if (!vda_ctx->decoder || !vda->bitstream) @@ -158,7 +158,7 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, CFMutableDictionaryRef io_surface_properties; CFNumberRef cv_pix_fmt; - /* Each VCL NAL in the bistream sent to the decoder + /* Each VCL NAL in the bitstream sent to the decoder * is preceded by a 4 bytes length header. * Change the avcC atom header if needed, to signal headers of 4 bytes. */ if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) { @@ -325,7 +325,7 @@ static int vda_h264_end_frame(AVCodecContext *avctx) H264Context *h = avctx->priv_data; VDAContext *vda = avctx->internal->hwaccel_priv_data; AVVDAContext *vda_ctx = avctx->hwaccel_context; - AVFrame *frame = &h->cur_pic_ptr->f; + AVFrame *frame = h->cur_pic_ptr->f; uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames CFDataRef coded_frame; OSStatus status; @@ -345,24 +345,25 @@ static int vda_h264_end_frame(AVCodecContext *avctx) CFRelease(coded_frame); + if (!vda->frame) + return AVERROR_UNKNOWN; + if (status != kVDADecoderNoErr) { av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); return AVERROR_UNKNOWN; } - if (vda->frame) { - av_buffer_unref(&frame->buf[0]); + av_buffer_unref(&frame->buf[0]); - frame->buf[0] = av_buffer_create((uint8_t*)vda->frame, - sizeof(vda->frame), - release_buffer, NULL, - AV_BUFFER_FLAG_READONLY); - if (!frame->buf) - return AVERROR(ENOMEM); + frame->buf[0] = av_buffer_create((uint8_t*)vda->frame, + sizeof(vda->frame), + release_buffer, NULL, + AV_BUFFER_FLAG_READONLY); + if (!frame->buf[0]) + return AVERROR(ENOMEM); - frame->data[3] = (uint8_t*)vda->frame; - vda->frame = NULL; - } + frame->data[3] = (uint8_t*)vda->frame; + vda->frame = NULL; return 0; } @@ -379,11 +380,11 @@ int ff_vda_default_init(AVCodecContext *avctx) CFMutableDictionaryRef buffer_attributes; CFMutableDictionaryRef io_surface_properties; CFNumberRef cv_pix_fmt; - int32_t fmt = 'avc1', pix_fmt = kCVPixelFormatType_422YpCbCr8; + int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type; // kCVPixelFormatType_420YpCbCr8Planar; - /* Each VCL NAL in the bistream sent to the decoder + /* Each VCL NAL in the bitstream sent to the decoder * is preceded by a 4 bytes length header. * Change the avcC atom header if needed, to signal headers of 4 bytes. */ if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) { diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index 5406874..f638d20 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -22,13 +22,11 @@ */ #include + #include "avcodec.h" -#include "h264.h" +#include "internal.h" +#include "h264dec.h" #include "vc1.h" - -#undef NDEBUG -#include - #include "vdpau.h" #include "vdpau_internal.h" @@ -38,6 +36,215 @@ * @{ */ +static int vdpau_error(VdpStatus status) +{ + switch (status) { + case VDP_STATUS_OK: + return 0; + case VDP_STATUS_NO_IMPLEMENTATION: + return AVERROR(ENOSYS); + case VDP_STATUS_DISPLAY_PREEMPTED: + return AVERROR(EIO); + case VDP_STATUS_INVALID_HANDLE: + return AVERROR(EBADF); + case VDP_STATUS_INVALID_POINTER: + return AVERROR(EFAULT); + case VDP_STATUS_RESOURCES: + return AVERROR(ENOBUFS); + case VDP_STATUS_HANDLE_DEVICE_MISMATCH: + return AVERROR(EXDEV); + case VDP_STATUS_ERROR: + return AVERROR(EIO); + default: + return AVERROR(EINVAL); + } +} + +int av_vdpau_get_surface_parameters(AVCodecContext *avctx, + VdpChromaType *type, + uint32_t *width, uint32_t *height) +{ + VdpChromaType t; + uint32_t w = avctx->coded_width; + uint32_t h = avctx->coded_height; + + /* See for per-type alignment constraints. */ + switch (avctx->sw_pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + t = VDP_CHROMA_TYPE_420; + w = (w + 1) & ~1; + h = (h + 3) & ~3; + break; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUVJ422P: + t = VDP_CHROMA_TYPE_422; + w = (w + 1) & ~1; + h = (h + 1) & ~1; + break; + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUVJ444P: + t = VDP_CHROMA_TYPE_444; + h = (h + 1) & ~1; + break; + default: + return AVERROR(ENOSYS); + } + + if (type) + *type = t; + if (width) + *width = w; + if (height) + *height = h; + return 0; +} + +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, + int level) +{ + VDPAUHWContext *hwctx = avctx->hwaccel_context; + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + VdpVideoSurfaceQueryCapabilities *surface_query_caps; + VdpDecoderQueryCapabilities *decoder_query_caps; + VdpDecoderCreate *create; + void *func; + VdpStatus status; + VdpBool supported; + uint32_t max_level, max_mb, max_width, max_height; + VdpChromaType type; + uint32_t width; + uint32_t height; + + vdctx->width = UINT32_MAX; + vdctx->height = UINT32_MAX; + hwctx->reset = 0; + + if (hwctx->context.decoder != VDP_INVALID_HANDLE) { + vdctx->decoder = hwctx->context.decoder; + vdctx->render = hwctx->context.render; + vdctx->device = VDP_INVALID_HANDLE; + return 0; /* Decoder created by user */ + } + + vdctx->device = hwctx->device; + vdctx->get_proc_address = hwctx->get_proc_address; + + if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) + level = 0; + else if (level < 0) + return AVERROR(ENOTSUP); + + if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) + return AVERROR(ENOSYS); + + if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) && + type != VDP_CHROMA_TYPE_420) + return AVERROR(ENOSYS); + + status = vdctx->get_proc_address(vdctx->device, + VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + surface_query_caps = func; + + status = surface_query_caps(vdctx->device, type, &supported, + &max_width, &max_height); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + if (supported != VDP_TRUE || + max_width < width || max_height < height) + return AVERROR(ENOTSUP); + + status = vdctx->get_proc_address(vdctx->device, + VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + decoder_query_caps = func; + + status = decoder_query_caps(vdctx->device, profile, &supported, &max_level, + &max_mb, &max_width, &max_height); +#ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE + if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) { + profile = VDP_DECODER_PROFILE_H264_MAIN; + status = decoder_query_caps(vdctx->device, profile, &supported, + &max_level, &max_mb, + &max_width, &max_height); + } +#endif + if (status != VDP_STATUS_OK) + return vdpau_error(status); + + if (supported != VDP_TRUE || max_level < level || + max_width < width || max_height < height) + return AVERROR(ENOTSUP); + + status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + create = func; + + status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + vdctx->render = func; + + status = create(vdctx->device, profile, width, height, avctx->refs, + &vdctx->decoder); + if (status == VDP_STATUS_OK) { + vdctx->width = avctx->coded_width; + vdctx->height = avctx->coded_height; + } + + return vdpau_error(status); +} + +int ff_vdpau_common_uninit(AVCodecContext *avctx) +{ + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + VdpDecoderDestroy *destroy; + void *func; + VdpStatus status; + + if (vdctx->device == VDP_INVALID_HANDLE) + return 0; /* Decoder created and destroyed by user */ + if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX) + return 0; + + status = vdctx->get_proc_address(vdctx->device, + VDP_FUNC_ID_DECODER_DESTROY, &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + destroy = func; + + status = destroy(vdctx->decoder); + return vdpau_error(status); +} + +static int ff_vdpau_common_reinit(AVCodecContext *avctx) +{ + VDPAUHWContext *hwctx = avctx->hwaccel_context; + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + + if (vdctx->device == VDP_INVALID_HANDLE) + return 0; /* Decoder created by user */ + if (avctx->coded_width == vdctx->width && + avctx->coded_height == vdctx->height && !hwctx->reset) + return 0; + + avctx->hwaccel->uninit(avctx); + return avctx->hwaccel->init(avctx); +} + int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx, av_unused const uint8_t *buffer, av_unused uint32_t size) @@ -48,23 +255,41 @@ int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx, return 0; } -#if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG1_VDPAU_HWACCEL || \ +int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, + struct vdpau_picture_context *pic_ctx) +{ + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + VdpVideoSurface surf = ff_vdpau_get_surface_id(frame); + VdpStatus status; + int val; + + val = ff_vdpau_common_reinit(avctx); + if (val < 0) + return val; + + status = vdctx->render(vdctx->decoder, surf, (void *)&pic_ctx->info, + pic_ctx->bitstream_buffers_used, + pic_ctx->bitstream_buffers); + + av_freep(&pic_ctx->bitstream_buffers); + return vdpau_error(status); +} + +#if CONFIG_MPEG1_VDPAU_HWACCEL || \ CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \ CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx) { - AVVDPAUContext *hwctx = avctx->hwaccel_context; MpegEncContext *s = avctx->priv_data; Picture *pic = s->current_picture_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; - VdpVideoSurface surf = ff_vdpau_get_surface_id(pic->f); + int val; - hwctx->render(hwctx->decoder, surf, (void *)&pic_ctx->info, - pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers); + val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx); + if (val < 0) + return val; ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); - av_freep(&pic_ctx->bitstream_buffers); - return 0; } #endif @@ -88,52 +313,80 @@ int ff_vdpau_add_buffer(struct vdpau_picture_context *pic_ctx, return 0; } +#if FF_API_VDPAU_PROFILE int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile) { -#define PROFILE(prof) \ -do { \ - *profile = prof; \ - return 0; \ +#define PROFILE(prof) \ +do { \ + *profile = VDP_DECODER_PROFILE_##prof; \ + return 0; \ } while (0) switch (avctx->codec_id) { - case AV_CODEC_ID_MPEG1VIDEO: PROFILE(VDP_DECODER_PROFILE_MPEG1); + case AV_CODEC_ID_MPEG1VIDEO: PROFILE(MPEG1); case AV_CODEC_ID_MPEG2VIDEO: switch (avctx->profile) { - case FF_PROFILE_MPEG2_MAIN: PROFILE(VDP_DECODER_PROFILE_MPEG2_MAIN); - case FF_PROFILE_MPEG2_SIMPLE: PROFILE(VDP_DECODER_PROFILE_MPEG2_SIMPLE); + case FF_PROFILE_MPEG2_MAIN: PROFILE(MPEG2_MAIN); + case FF_PROFILE_MPEG2_SIMPLE: PROFILE(MPEG2_SIMPLE); default: return AVERROR(EINVAL); } - case AV_CODEC_ID_H263: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_ASP); + case AV_CODEC_ID_H263: PROFILE(MPEG4_PART2_ASP); case AV_CODEC_ID_MPEG4: switch (avctx->profile) { - case FF_PROFILE_MPEG4_SIMPLE: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_SP); - case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_ASP); + case FF_PROFILE_MPEG4_SIMPLE: PROFILE(MPEG4_PART2_SP); + case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: PROFILE(MPEG4_PART2_ASP); default: return AVERROR(EINVAL); } case AV_CODEC_ID_H264: switch (avctx->profile & ~FF_PROFILE_H264_INTRA) { + case FF_PROFILE_H264_BASELINE: PROFILE(H264_BASELINE); case FF_PROFILE_H264_CONSTRAINED_BASELINE: - case FF_PROFILE_H264_BASELINE: PROFILE(VDP_DECODER_PROFILE_H264_BASELINE); - case FF_PROFILE_H264_MAIN: PROFILE(VDP_DECODER_PROFILE_H264_MAIN); - case FF_PROFILE_H264_HIGH: PROFILE(VDP_DECODER_PROFILE_H264_HIGH); + case FF_PROFILE_H264_MAIN: PROFILE(H264_MAIN); + case FF_PROFILE_H264_HIGH: PROFILE(H264_HIGH); +#ifdef VDP_DECODER_PROFILE_H264_EXTENDED + case FF_PROFILE_H264_EXTENDED: PROFILE(H264_EXTENDED); +#endif default: return AVERROR(EINVAL); } case AV_CODEC_ID_WMV3: case AV_CODEC_ID_VC1: switch (avctx->profile) { - case FF_PROFILE_VC1_SIMPLE: PROFILE(VDP_DECODER_PROFILE_VC1_SIMPLE); - case FF_PROFILE_VC1_MAIN: PROFILE(VDP_DECODER_PROFILE_VC1_MAIN); - case FF_PROFILE_VC1_ADVANCED: PROFILE(VDP_DECODER_PROFILE_VC1_ADVANCED); + case FF_PROFILE_VC1_SIMPLE: PROFILE(VC1_SIMPLE); + case FF_PROFILE_VC1_MAIN: PROFILE(VC1_MAIN); + case FF_PROFILE_VC1_ADVANCED: PROFILE(VC1_ADVANCED); default: return AVERROR(EINVAL); } } return AVERROR(EINVAL); +#undef PROFILE } +#endif /* FF_API_VDPAU_PROFILE */ AVVDPAUContext *av_vdpau_alloc_context(void) { return av_mallocz(sizeof(AVVDPAUContext)); } +int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device, + VdpGetProcAddress *get_proc, unsigned flags) +{ + VDPAUHWContext *hwctx; + + if (flags & ~(AV_HWACCEL_FLAG_IGNORE_LEVEL|AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH)) + return AVERROR(EINVAL); + + if (av_reallocp(&avctx->hwaccel_context, sizeof(*hwctx))) + return AVERROR(ENOMEM); + + hwctx = avctx->hwaccel_context; + + memset(hwctx, 0, sizeof(*hwctx)); + hwctx->context.decoder = VDP_INVALID_HANDLE; + hwctx->device = device; + hwctx->get_proc_address = get_proc; + hwctx->flags = flags; + hwctx->reset = 1; + return 0; +} + /* @}*/ diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h index 75cb1bf..967c728 100644 --- a/libavcodec/vdpau.h +++ b/libavcodec/vdpau.h @@ -131,16 +131,59 @@ typedef struct AVVDPAUContext { } AVVDPAUContext; /** + * Associate a VDPAU device with a codec context for hardware acceleration. + * This function is meant to be called from the get_format() codec callback, + * or earlier. It can also be called after avcodec_flush_buffers() to change + * the underlying VDPAU device mid-stream (e.g. to recover from non-transparent + * display preemption). + * + * @note get_format() must return AV_PIX_FMT_VDPAU if this function completes + * successfully. + * + * @param avctx decoding context whose get_format() callback is invoked + * @param device VDPAU device handle to use for hardware acceleration + * @param get_proc_address VDPAU device driver + * @param flags zero of more OR'd AV_HWACCEL_FLAG_* flags + * + * @return 0 on success, an AVERROR code on failure. + */ +int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device, + VdpGetProcAddress *get_proc_address, unsigned flags); + +/** + * Gets the parameters to create an adequate VDPAU video surface for the codec + * context using VDPAU hardware decoding acceleration. + * + * @note Behavior is undefined if the context was not successfully bound to a + * VDPAU device using av_vdpau_bind_context(). + * + * @param avctx the codec context being used for decoding the stream + * @param type storage space for the VDPAU video surface chroma type + * (or NULL to ignore) + * @param width storage space for the VDPAU video surface pixel width + * (or NULL to ignore) + * @param height storage space for the VDPAU video surface pixel height + * (or NULL to ignore) + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type, + uint32_t *width, uint32_t *height); + +/** * Allocate an AVVDPAUContext. * * @return Newly-allocated AVVDPAUContext or NULL on failure. */ AVVDPAUContext *av_vdpau_alloc_context(void); +#if FF_API_VDPAU_PROFILE /** * Get a decoder profile that should be used for initializing a VDPAU decoder. * Should be called from the AVCodecContext.get_format() callback. * + * @deprecated Use av_vdpau_bind_context() instead. + * * @param avctx the codec context being used for decoding the stream * @param profile a pointer into which the result will be written on success. * The contents of profile are undefined if this function returns @@ -148,7 +191,9 @@ AVVDPAUContext *av_vdpau_alloc_context(void); * * @return 0 on success (non-negative), a negative AVERROR on failure. */ +attribute_deprecated int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile); +#endif #if FF_API_CAP_VDPAU /** @brief The videoSurface is used for rendering. */ diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index 32e9c28..3e13b76 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -24,7 +24,9 @@ #include #include "avcodec.h" -#include "h264.h" +#include "internal.h" +#include "h264dec.h" +#include "h264_ps.h" #include "mpegutils.h" #include "vdpau.h" #include "vdpau_internal.h" @@ -50,7 +52,7 @@ static void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf) static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, H264Picture *pic, int pic_structure) { - VdpVideoSurface surface = ff_vdpau_get_surface_id(&pic->f); + VdpVideoSurface surface = ff_vdpau_get_surface_id(pic->f); if (pic_structure == 0) pic_structure = pic->reference; @@ -87,7 +89,7 @@ static void vdpau_h264_set_reference_frames(AVCodecContext *avctx) if (!pic || !pic->reference) continue; pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; - surface_ref = ff_vdpau_get_surface_id(&pic->f); + surface_ref = ff_vdpau_get_surface_id(pic->f); rf2 = &info->referenceFrames[0]; while (rf2 != rf) { @@ -119,45 +121,54 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { H264Context * const h = avctx->priv_data; + const PPS *pps = h->ps.pps; + const SPS *sps = h->ps.sps; H264Picture *pic = h->cur_pic_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; VdpPictureInfoH264 *info = &pic_ctx->info.h264; +#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE + VdpPictureInfoH264Predictive *info2 = &pic_ctx->info.h264_predictive; +#endif /* init VdpPictureInfoH264 */ info->slice_count = 0; info->field_order_cnt[0] = h264_foc(pic->field_poc[0]); info->field_order_cnt[1] = h264_foc(pic->field_poc[1]); info->is_reference = h->nal_ref_idc != 0; - info->frame_num = h->frame_num; + info->frame_num = h->poc.frame_num; info->field_pic_flag = h->picture_structure != PICT_FRAME; info->bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD; - info->num_ref_frames = h->sps.ref_frame_count; - info->mb_adaptive_frame_field_flag = h->sps.mb_aff && !info->field_pic_flag; - info->constrained_intra_pred_flag = h->pps.constrained_intra_pred; - info->weighted_pred_flag = h->pps.weighted_pred; - info->weighted_bipred_idc = h->pps.weighted_bipred_idc; - info->frame_mbs_only_flag = h->sps.frame_mbs_only_flag; - info->transform_8x8_mode_flag = h->pps.transform_8x8_mode; - info->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; - info->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; - info->pic_init_qp_minus26 = h->pps.init_qp - 26; - info->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; - info->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; - info->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; - info->pic_order_cnt_type = h->sps.poc_type; - info->log2_max_pic_order_cnt_lsb_minus4 = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4; - info->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; - info->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; - info->entropy_coding_mode_flag = h->pps.cabac; - info->pic_order_present_flag = h->pps.pic_order_present; - info->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; - info->redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; - - memcpy(info->scaling_lists_4x4, h->pps.scaling_matrix4, + info->num_ref_frames = sps->ref_frame_count; + info->mb_adaptive_frame_field_flag = sps->mb_aff && !info->field_pic_flag; + info->constrained_intra_pred_flag = pps->constrained_intra_pred; + info->weighted_pred_flag = pps->weighted_pred; + info->weighted_bipred_idc = pps->weighted_bipred_idc; + info->frame_mbs_only_flag = sps->frame_mbs_only_flag; + info->transform_8x8_mode_flag = pps->transform_8x8_mode; + info->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; + info->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; + info->pic_init_qp_minus26 = pps->init_qp - 26; + info->num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1; + info->num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1; + info->log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4; + info->pic_order_cnt_type = sps->poc_type; + info->log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4; + info->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + info->direct_8x8_inference_flag = sps->direct_8x8_inference_flag; +#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE + info2->qpprime_y_zero_transform_bypass_flag = sps->transform_bypass; + info2->separate_colour_plane_flag = sps->residual_color_transform_flag; +#endif + info->entropy_coding_mode_flag = pps->cabac; + info->pic_order_present_flag = pps->pic_order_present; + info->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present; + info->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present; + + memcpy(info->scaling_lists_4x4, pps->scaling_matrix4, sizeof(info->scaling_lists_4x4)); - memcpy(info->scaling_lists_8x8[0], h->pps.scaling_matrix8[0], + memcpy(info->scaling_lists_8x8[0], pps->scaling_matrix8[0], sizeof(info->scaling_lists_8x8[0])); - memcpy(info->scaling_lists_8x8[1], h->pps.scaling_matrix8[3], + memcpy(info->scaling_lists_8x8[1], pps->scaling_matrix8[3], sizeof(info->scaling_lists_8x8[1])); vdpau_h264_set_reference_frames(avctx); @@ -189,21 +200,67 @@ static int vdpau_h264_decode_slice(AVCodecContext *avctx, static int vdpau_h264_end_frame(AVCodecContext *avctx) { - AVVDPAUContext *hwctx = avctx->hwaccel_context; H264Context *h = avctx->priv_data; + H264SliceContext *sl = &h->slice_ctx[0]; H264Picture *pic = h->cur_pic_ptr; struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; - VdpVideoSurface surf = ff_vdpau_get_surface_id(&pic->f); - - hwctx->render(hwctx->decoder, surf, (void *)&pic_ctx->info, - pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers); + int val; - ff_h264_draw_horiz_band(h, 0, h->avctx->height); - av_freep(&pic_ctx->bitstream_buffers); + val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx); + if (val < 0) + return val; + ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height); return 0; } +static int vdpau_h264_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + uint32_t level = avctx->level; + + switch (avctx->profile & ~FF_PROFILE_H264_INTRA) { + case FF_PROFILE_H264_BASELINE: + profile = VDP_DECODER_PROFILE_H264_BASELINE; + break; + case FF_PROFILE_H264_CONSTRAINED_BASELINE: +#ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE + profile = VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE; + break; +#endif + case FF_PROFILE_H264_MAIN: + profile = VDP_DECODER_PROFILE_H264_MAIN; + break; + case FF_PROFILE_H264_HIGH: + profile = VDP_DECODER_PROFILE_H264_HIGH; + break; +#ifdef VDP_DECODER_PROFILE_H264_EXTENDED + case FF_PROFILE_H264_EXTENDED: + profile = VDP_DECODER_PROFILE_H264_EXTENDED; + break; +#endif + case FF_PROFILE_H264_HIGH_10: + /* XXX: High 10 can be treated as High so long as only 8 bits per + * format are supported. */ + profile = VDP_DECODER_PROFILE_H264_HIGH; + break; +#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE + case FF_PROFILE_H264_HIGH_422: + case FF_PROFILE_H264_HIGH_444_PREDICTIVE: + case FF_PROFILE_H264_CAVLC_444: + profile = VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE; + break; +#endif + default: + return AVERROR(ENOTSUP); + } + + if ((avctx->profile & FF_PROFILE_H264_INTRA) && avctx->level == 11) + level = VDP_DECODER_LEVEL_H264_1b; + + return ff_vdpau_common_init(avctx, profile, level); +} + AVHWAccel ff_h264_vdpau_hwaccel = { .name = "h264_vdpau", .type = AVMEDIA_TYPE_VIDEO, @@ -213,4 +270,7 @@ AVHWAccel ff_h264_vdpau_hwaccel = { .end_frame = vdpau_h264_end_frame, .decode_slice = vdpau_h264_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_h264_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c new file mode 100644 index 0000000..1e5fb71 --- /dev/null +++ b/libavcodec/vdpau_hevc.c @@ -0,0 +1,426 @@ +/* + * MPEG-H Part 2 / HEVC / H.265 HW decode acceleration through VDPAU + * + * Copyright (c) 2013 Philip Langdale + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "avcodec.h" +#include "internal.h" +#include "hevc.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int vdpau_hevc_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + HEVCContext *h = avctx->priv_data; + HEVCFrame *pic = h->ref; + struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; + + VdpPictureInfoHEVC *info = &pic_ctx->info.hevc; + + const HEVCSPS *sps = h->ps.sps; + const HEVCPPS *pps = h->ps.pps; + const SliceHeader *sh = &h->sh; + const ScalingList *sl = pps->scaling_list_data_present_flag ? + &pps->scaling_list : &sps->scaling_list; + + /* init VdpPictureInfoHEVC */ + + /* SPS */ + info->chroma_format_idc = sps->chroma_format_idc; + info->separate_colour_plane_flag = sps->separate_colour_plane_flag; + info->pic_width_in_luma_samples = sps->width; + info->pic_height_in_luma_samples = sps->height; + info->bit_depth_luma_minus8 = sps->bit_depth - 8; + info->bit_depth_chroma_minus8 = sps->bit_depth - 8; + info->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4; + /* Provide the value corresponding to the nuh_temporal_id of the frame + to be decoded. */ + info->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1; + info->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3; + info->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size; + info->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2; + info->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size; + info->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter; + info->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra; + info->scaling_list_enabled_flag = sps->scaling_list_enable_flag; + /* Scaling lists, in diagonal order, to be used for this frame. */ + for (size_t i = 0; i < 6; i++) { + for (size_t j = 0; j < 16; j++) { + /* Scaling List for 4x4 quantization matrix, + indexed as ScalingList4x4[matrixId][i]. */ + uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; + info->ScalingList4x4[i][j] = sl->sl[0][i][pos]; + } + for (size_t j = 0; j < 64; j++) { + uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + /* Scaling List for 8x8 quantization matrix, + indexed as ScalingList8x8[matrixId][i]. */ + info->ScalingList8x8[i][j] = sl->sl[1][i][pos]; + /* Scaling List for 16x16 quantization matrix, + indexed as ScalingList16x16[matrixId][i]. */ + info->ScalingList16x16[i][j] = sl->sl[2][i][pos]; + if (i < 2) { + /* Scaling List for 32x32 quantization matrix, + indexed as ScalingList32x32[matrixId][i]. */ + info->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos]; + } + } + /* Scaling List DC Coefficients for 16x16, + indexed as ScalingListDCCoeff16x16[matrixId]. */ + info->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i]; + if (i < 2) { + /* Scaling List DC Coefficients for 32x32, + indexed as ScalingListDCCoeff32x32[matrixId]. */ + info->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3]; + } + } + info->amp_enabled_flag = sps->amp_enabled_flag; + info->sample_adaptive_offset_enabled_flag = sps->sao_enabled; + info->pcm_enabled_flag = sps->pcm_enabled_flag; + if (info->pcm_enabled_flag) { + /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ + info->pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1; + /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ + info->pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1; + /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ + info->log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3; + /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ + info->log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size; + /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ + info->pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag; + } + /* Per spec, when zero, assume short_term_ref_pic_set_sps_flag + is also zero. */ + info->num_short_term_ref_pic_sets = sps->nb_st_rps; + info->long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag; + /* Only needed if long_term_ref_pics_present_flag is set. Ignored + otherwise. */ + info->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps; + info->sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag; + info->strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag; + + /* Copy the HEVC Picture Parameter Set bitstream fields. */ + info->dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag; + info->output_flag_present_flag = pps->output_flag_present_flag; + info->num_extra_slice_header_bits = pps->num_extra_slice_header_bits; + info->sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag; + info->cabac_init_present_flag = pps->cabac_init_present_flag; + info->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1; + info->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1; + info->init_qp_minus26 = pps->pic_init_qp_minus26; + info->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + info->transform_skip_enabled_flag = pps->transform_skip_enabled_flag; + info->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag; + /* Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */ + info->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth; + info->pps_cb_qp_offset = pps->cb_qp_offset; + info->pps_cr_qp_offset = pps->cr_qp_offset; + info->pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag; + info->weighted_pred_flag = pps->weighted_pred_flag; + info->weighted_bipred_flag = pps->weighted_bipred_flag; + info->transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag; + info->tiles_enabled_flag = pps->tiles_enabled_flag; + info->entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag; + if (info->tiles_enabled_flag) { + /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ + info->num_tile_columns_minus1 = pps->num_tile_columns - 1; + /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ + info->num_tile_rows_minus1 = pps->num_tile_rows - 1; + /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ + info->uniform_spacing_flag = pps->uniform_spacing_flag; + /* Only need to set 0..num_tile_columns_minus1. The struct + definition reserves up to the maximum of 20. Invalid values are + ignored. */ + for (ssize_t i = 0; i < pps->num_tile_columns; i++) { + info->column_width_minus1[i] = pps->column_width[i] - 1; + } + /* Only need to set 0..num_tile_rows_minus1. The struct + definition reserves up to the maximum of 22. Invalid values are + ignored.*/ + for (ssize_t i = 0; i < pps->num_tile_rows; i++) { + info->row_height_minus1[i] = pps->row_height[i] - 1; + } + /* Only needed if tiles_enabled_flag is set. Invalid values are + ignored. */ + info->loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag; + } + info->pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag; + info->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + /* Only valid if deblocking_filter_control_present_flag is set. Ignored + otherwise. */ + info->deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag; + /* Only valid if deblocking_filter_control_present_flag is set. Ignored + otherwise. */ + info->pps_deblocking_filter_disabled_flag = pps->disable_dbf; + /* Only valid if deblocking_filter_control_present_flag is set and + pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/ + info->pps_beta_offset_div2 = pps->beta_offset / 2; + /* Only valid if deblocking_filter_control_present_flag is set and + pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */ + info->pps_tc_offset_div2 = pps->tc_offset / 2; + info->lists_modification_present_flag = pps->lists_modification_present_flag; + info->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2; + info->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag; + + /* Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP. + Set to zero otherwise. */ + info->IDRPicFlag = IS_IDR(h); + /* Set to 1 if nal_unit_type in the range of BLA_W_LP to + RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/ + info->RAPPicFlag = IS_IRAP(h); + /* See section 7.4.7.1 of the specification. */ + info->CurrRpsIdx = sps->nb_st_rps; + if (sh->short_term_ref_pic_set_sps_flag == 1) { + for (size_t i = 0; i < sps->nb_st_rps; i++) { + if (sh->short_term_rps == &sps->st_rps[i]) { + info->CurrRpsIdx = i; + break; + } + } + } + /* See section 7.4.7.2 of the specification. */ + info->NumPocTotalCurr = ff_hevc_frame_nb_refs(h); + if (sh->short_term_ref_pic_set_sps_flag == 0 && sh->short_term_rps) { + /* Corresponds to specification field, NumDeltaPocs[RefRpsIdx]. + Only applicable when short_term_ref_pic_set_sps_flag == 0. + Implementations will ignore this value in other cases. See 7.4.8. */ + info->NumDeltaPocsOfRefRpsIdx = sh->short_term_rps->rps_idx_num_delta_pocs; + } + /* Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of + the slice_segment_header. This header contains information that + some VDPAU implementations may choose to skip. The VDPAU API + requires client applications to track the number of bits used in the + slice header for structures associated with short term and long term + reference pictures. First, VDPAU requires the number of bits used by + the short_term_ref_pic_set array in the slice_segment_header. */ + info->NumShortTermPictureSliceHeaderBits = sh->short_term_ref_pic_set_size; + /* Second, VDPAU requires the number of bits used for long term reference + pictures in the slice_segment_header. This is equal to the number + of bits used for the contents of the block beginning with + "if(long_term_ref_pics_present_flag)". */ + info->NumLongTermPictureSliceHeaderBits = sh->long_term_ref_pic_set_size; + + /* The value of PicOrderCntVal of the picture in the access unit + containing the SEI message. The picture being decoded. */ + info->CurrPicOrderCntVal = h->poc; + + /* Slice Decoding Process - Reference Picture Sets */ + for (size_t i = 0; i < 16; i++) { + info->RefPics[i] = VDP_INVALID_HANDLE; + info->PicOrderCntVal[i] = 0; + info->IsLongTerm[i] = 0; + } + for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { + const HEVCFrame *frame = &h->DPB[i]; + if (frame != h->ref && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | + HEVC_FRAME_FLAG_SHORT_REF))) { + if (j > 16) { + av_log(avctx, AV_LOG_WARNING, + "VDPAU only supports up to 16 references in the DPB. " + "This frame may not be decoded correctly.\n"); + break; + } + /* Array of video reference surfaces. + Set any unused positions to VDP_INVALID_HANDLE. */ + info->RefPics[j] = ff_vdpau_get_surface_id(frame->frame); + /* Array of picture order counts. These correspond to positions + in the RefPics array. */ + info->PicOrderCntVal[j] = frame->poc; + /* Array used to specify whether a particular RefPic is + a long term reference. A value of "1" indicates a long-term + reference. */ + // XXX: Setting this caused glitches in the nvidia implementation + // Always setting it to zero, produces correct results + //info->IsLongTerm[j] = frame->flags & HEVC_FRAME_FLAG_LONG_REF; + info->IsLongTerm[j] = 0; + j++; + } + } + /* Copy of specification field, see Section 8.3.2 of the + H.265/HEVC Specification. */ + info->NumPocStCurrBefore = h->rps[ST_CURR_BEF].nb_refs; + if (info->NumPocStCurrBefore > 8) { + av_log(avctx, AV_LOG_WARNING, + "VDPAU only supports up to 8 references in StCurrBefore. " + "This frame may not be decoded correctly.\n"); + info->NumPocStCurrBefore = 8; + } + /* Copy of specification field, see Section 8.3.2 of the + H.265/HEVC Specification. */ + info->NumPocStCurrAfter = h->rps[ST_CURR_AFT].nb_refs; + if (info->NumPocStCurrAfter > 8) { + av_log(avctx, AV_LOG_WARNING, + "VDPAU only supports up to 8 references in StCurrAfter. " + "This frame may not be decoded correctly.\n"); + info->NumPocStCurrAfter = 8; + } + /* Copy of specification field, see Section 8.3.2 of the + H.265/HEVC Specification. */ + info->NumPocLtCurr = h->rps[LT_CURR].nb_refs; + if (info->NumPocLtCurr > 8) { + av_log(avctx, AV_LOG_WARNING, + "VDPAU only supports up to 8 references in LtCurr. " + "This frame may not be decoded correctly.\n"); + info->NumPocLtCurr = 8; + } + /* Reference Picture Set list, one of the short-term RPS. These + correspond to positions in the RefPics array. */ + for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { + HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i]; + if (frame) { + uint8_t found = 0; + uintptr_t id = ff_vdpau_get_surface_id(frame->frame); + for (size_t k = 0; k < 16; k++) { + if (id == info->RefPics[k]) { + info->RefPicSetStCurrBefore[j] = k; + j++; + found = 1; + break; + } + } + if (!found) { + av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", + (void *)id); + } + } else { + av_log(avctx, AV_LOG_WARNING, "missing STR Before frame: %zd\n", i); + } + } + /* Reference Picture Set list, one of the short-term RPS. These + correspond to positions in the RefPics array. */ + for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { + HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i]; + if (frame) { + uint8_t found = 0; + uintptr_t id = ff_vdpau_get_surface_id(frame->frame); + for (size_t k = 0; k < 16; k++) { + if (id == info->RefPics[k]) { + info->RefPicSetStCurrAfter[j] = k; + j++; + found = 1; + break; + } + } + if (!found) { + av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", + (void *)id); + } + } else { + av_log(avctx, AV_LOG_WARNING, "missing STR After frame: %zd\n", i); + } + } + /* Reference Picture Set list, one of the long-term RPS. These + correspond to positions in the RefPics array. */ + for (ssize_t i = 0, j = 0; i < h->rps[LT_CURR].nb_refs; i++) { + HEVCFrame *frame = h->rps[LT_CURR].ref[i]; + if (frame) { + uint8_t found = 0; + uintptr_t id = ff_vdpau_get_surface_id(frame->frame); + for (size_t k = 0; k < 16; k++) { + if (id == info->RefPics[k]) { + info->RefPicSetLtCurr[j] = k; + j++; + found = 1; + break; + } + } + if (!found) { + av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", + (void *)id); + } + } else { + av_log(avctx, AV_LOG_WARNING, "missing LTR frame: %zd\n", i); + } + } + + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); +} + +static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; + +static int vdpau_hevc_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + HEVCContext *h = avctx->priv_data; + struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private; + int val; + + val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3); + if (val) + return val; + + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); + if (val) + return val; + + return 0; +} + +static int vdpau_hevc_end_frame(AVCodecContext *avctx) +{ + HEVCContext *h = avctx->priv_data; + struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private; + int val; + + val = ff_vdpau_common_end_frame(avctx, h->ref->frame, pic_ctx); + if (val < 0) + return val; + + return 0; +} + +static int vdpau_hevc_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + uint32_t level = avctx->level; + + switch (avctx->profile) { + case FF_PROFILE_HEVC_MAIN: + profile = VDP_DECODER_PROFILE_HEVC_MAIN; + break; + case FF_PROFILE_HEVC_MAIN_10: + profile = VDP_DECODER_PROFILE_HEVC_MAIN_10; + break; + case FF_PROFILE_HEVC_MAIN_STILL_PICTURE: + profile = VDP_DECODER_PROFILE_HEVC_MAIN_STILL; + break; + default: + return AVERROR(ENOTSUP); + } + + return ff_vdpau_common_init(avctx, profile, level); +} + +AVHWAccel ff_hevc_vdpau_hwaccel = { + .name = "hevc_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_hevc_start_frame, + .end_frame = vdpau_hevc_end_frame, + .decode_slice = vdpau_hevc_decode_slice, + .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_hevc_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), +}; diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index 2443e0a..c7281a6 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -27,9 +27,10 @@ #include #include +#include "libavutil/frame.h" + #include "avcodec.h" -#include "mpegvideo.h" -#include "version.h" +#include "vdpau.h" /** Extract VdpVideoSurface from an AVFrame */ static inline uintptr_t ff_vdpau_get_surface_id(AVFrame *pic) @@ -37,22 +38,57 @@ static inline uintptr_t ff_vdpau_get_surface_id(AVFrame *pic) return (uintptr_t)pic->data[3]; } -#if !FF_API_BUFS_VDPAU -union AVVDPAUPictureInfo { +union VDPAUPictureInfo { VdpPictureInfoH264 h264; VdpPictureInfoMPEG1Or2 mpeg; VdpPictureInfoVC1 vc1; VdpPictureInfoMPEG4Part2 mpeg4; -}; -#else -#include "vdpau.h" +#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE + VdpPictureInfoH264Predictive h264_predictive; +#endif +#ifdef VDP_DECODER_PROFILE_HEVC_MAIN + VdpPictureInfoHEVC hevc; #endif +}; + +typedef struct VDPAUHWContext { + AVVDPAUContext context; + VdpDevice device; + VdpGetProcAddress *get_proc_address; + char reset; + unsigned char flags; +} VDPAUHWContext; + +typedef struct VDPAUContext { + /** + * VDPAU device handle + */ + VdpDevice device; + + /** + * VDPAU decoder handle + */ + VdpDecoder decoder; + + /** + * VDPAU device driver + */ + VdpGetProcAddress *get_proc_address; + + /** + * VDPAU decoder render callback + */ + VdpDecoderRender *render; + + uint32_t width; + uint32_t height; +} VDPAUContext; struct vdpau_picture_context { /** * VDPAU picture information. */ - union AVVDPAUPictureInfo info; + union VDPAUPictureInfo info; /** * Allocated size of the bitstream_buffers table. @@ -70,8 +106,14 @@ struct vdpau_picture_context { VdpBitstreamBuffer *bitstream_buffers; }; +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, + int level); +int ff_vdpau_common_uninit(AVCodecContext *avctx); + int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic, const uint8_t *buffer, uint32_t size); +int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, + struct vdpau_picture_context *pic); int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); int ff_vdpau_add_buffer(struct vdpau_picture_context *pic, const uint8_t *buf, uint32_t buf_size); diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index 2b53e66..cb6f81a 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -24,6 +24,7 @@ #include #include "avcodec.h" +#include "mpegvideo.h" #include "vdpau.h" #include "vdpau_internal.h" @@ -95,6 +96,12 @@ static int vdpau_mpeg_decode_slice(AVCodecContext *avctx, } #if CONFIG_MPEG1_VDPAU_HWACCEL +static int vdpau_mpeg1_init(AVCodecContext *avctx) +{ + return ff_vdpau_common_init(avctx, VDP_DECODER_PROFILE_MPEG1, + VDP_DECODER_LEVEL_MPEG1_NA); +} + AVHWAccel ff_mpeg1_vdpau_hwaccel = { .name = "mpeg1_vdpau", .type = AVMEDIA_TYPE_VIDEO, @@ -104,10 +111,31 @@ AVHWAccel ff_mpeg1_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_mpeg1_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; #endif #if CONFIG_MPEG2_VDPAU_HWACCEL +static int vdpau_mpeg2_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + + switch (avctx->profile) { + case FF_PROFILE_MPEG2_MAIN: + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + case FF_PROFILE_MPEG2_SIMPLE: + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + return AVERROR(EINVAL); + } + + return ff_vdpau_common_init(avctx, profile, VDP_DECODER_LEVEL_MPEG2_HL); +} + AVHWAccel ff_mpeg2_vdpau_hwaccel = { .name = "mpeg2_vdpau", .type = AVMEDIA_TYPE_VIDEO, @@ -117,5 +145,8 @@ AVHWAccel ff_mpeg2_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_mpeg2_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; #endif diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 64e781d..fcad42f 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -61,7 +61,7 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, info->trb[0] = s->pb_time; info->trd[1] = s->pp_field_time >> 1; info->trb[1] = s->pb_field_time >> 1; - info->vop_time_increment_resolution = s->avctx->time_base.den; + info->vop_time_increment_resolution = s->avctx->framerate.num; info->vop_fcode_forward = s->f_code; info->vop_fcode_backward = s->b_code; info->resync_marker_disable = !ctx->resync_marker; @@ -88,20 +88,24 @@ static int vdpau_mpeg4_decode_slice(av_unused AVCodecContext *avctx, return 0; } -#if CONFIG_H263_VDPAU_HWACCEL -AVHWAccel ff_h263_vdpau_hwaccel = { - .name = "h263_vdpau", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263, - .pix_fmt = AV_PIX_FMT_VDPAU, - .start_frame = vdpau_mpeg4_start_frame, - .end_frame = ff_vdpau_mpeg_end_frame, - .decode_slice = vdpau_mpeg4_decode_slice, - .frame_priv_data_size = sizeof(struct vdpau_picture_context), -}; -#endif +static int vdpau_mpeg4_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + + switch (avctx->profile) { + case FF_PROFILE_MPEG4_SIMPLE: + profile = VDP_DECODER_PROFILE_MPEG4_PART2_SP; + break; + case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: + profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; + break; + default: + return AVERROR(ENOTSUP); + } + + return ff_vdpau_common_init(avctx, profile, avctx->level); +} -#if CONFIG_MPEG4_VDPAU_HWACCEL AVHWAccel ff_mpeg4_vdpau_hwaccel = { .name = "mpeg4_vdpau", .type = AVMEDIA_TYPE_VIDEO, @@ -111,5 +115,7 @@ AVHWAccel ff_mpeg4_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg4_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_mpeg4_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; -#endif diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index f7a7ecc..4f87c52 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -109,6 +109,27 @@ static int vdpau_vc1_decode_slice(AVCodecContext *avctx, return 0; } +static int vdpau_vc1_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + + switch (avctx->profile) { + case FF_PROFILE_VC1_SIMPLE: + profile = VDP_DECODER_PROFILE_VC1_SIMPLE; + break; + case FF_PROFILE_VC1_MAIN: + profile = VDP_DECODER_PROFILE_VC1_MAIN; + break; + case FF_PROFILE_VC1_ADVANCED: + profile = VDP_DECODER_PROFILE_VC1_ADVANCED; + break; + default: + return AVERROR(ENOTSUP); + } + + return ff_vdpau_common_init(avctx, profile, avctx->level); +} + #if CONFIG_WMV3_VDPAU_HWACCEL AVHWAccel ff_wmv3_vdpau_hwaccel = { .name = "wm3_vdpau", @@ -119,6 +140,9 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_vc1_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; #endif @@ -131,4 +155,7 @@ AVHWAccel ff_vc1_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_vc1_init, + .uninit = ff_vdpau_common_uninit, + .priv_data_size = sizeof(VDPAUContext), }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 8cc2fb0..f944709 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -28,8 +27,8 @@ #include "libavutil/version.h" -#define LIBAVCODEC_VERSION_MAJOR 56 -#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MAJOR 57 +#define LIBAVCODEC_VERSION_MINOR 25 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -48,110 +47,164 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_REQUEST_CHANNELS -#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 57) -#endif -#ifndef FF_API_DEINTERLACE -#define FF_API_DEINTERLACE (LIBAVCODEC_VERSION_MAJOR < 57) -#endif -#ifndef FF_API_DESTRUCT_PACKET -#define FF_API_DESTRUCT_PACKET (LIBAVCODEC_VERSION_MAJOR < 57) -#endif -#ifndef FF_API_GET_BUFFER -#define FF_API_GET_BUFFER (LIBAVCODEC_VERSION_MAJOR < 57) +#ifndef FF_API_GETCHROMA +#define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MISSING_SAMPLE -#define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_LOWRES -#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_CAP_VDPAU -#define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_BUFS_VDPAU -#define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_VOXWARE -#define FF_API_VOXWARE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_VOXWARE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_SET_DIMENSIONS -#define FF_API_SET_DIMENSIONS (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_SET_DIMENSIONS (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_DEBUG_MV -#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_AC_VLC -#define FF_API_AC_VLC (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_AC_VLC (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_OLD_MSMPEG4 -#define FF_API_OLD_MSMPEG4 (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_OLD_MSMPEG4 (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_ASPECT_EXTENDED -#define FF_API_ASPECT_EXTENDED (LIBAVCODEC_VERSION_MAJOR < 57) -#endif -#ifndef FF_API_THREAD_OPAQUE -#define FF_API_THREAD_OPAQUE (LIBAVCODEC_VERSION_MAJOR < 57) -#endif -#ifndef FF_API_CODEC_PKT -#define FF_API_CODEC_PKT (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_ASPECT_EXTENDED (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_ARCH_ALPHA -#define FF_API_ARCH_ALPHA (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_ARCH_ALPHA (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_XVMC -#define FF_API_XVMC (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_XVMC (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_ERROR_RATE -#define FF_API_ERROR_RATE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_ERROR_RATE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_QSCALE_TYPE -#define FF_API_QSCALE_TYPE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_QSCALE_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MB_TYPE -#define FF_API_MB_TYPE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_MB_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MAX_BFRAMES -#define FF_API_MAX_BFRAMES (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_MAX_BFRAMES (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_FAST_MALLOC -#define FF_API_FAST_MALLOC (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_FAST_MALLOC (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_NEG_LINESIZES -#define FF_API_NEG_LINESIZES (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_NEG_LINESIZES (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_EMU_EDGE -#define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_ARCH_SH4 -#define FF_API_ARCH_SH4 (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_ARCH_SH4 (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_ARCH_SPARC -#define FF_API_ARCH_SPARC (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_ARCH_SPARC (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_UNUSED_MEMBERS -#define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_IDCT_XVIDMMX -#define FF_API_IDCT_XVIDMMX (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_IDCT_XVIDMMX (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_INPUT_PRESERVED -#define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_NORMALIZE_AQP -#define FF_API_NORMALIZE_AQP (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_NORMALIZE_AQP (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_GMC -#define FF_API_GMC (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_GMC (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MV0 -#define FF_API_MV0 (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_MV0 (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_CODEC_NAME -#define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_AFD -#define FF_API_AFD (LIBAVCODEC_VERSION_MAJOR < 57) +#define FF_API_AFD (LIBAVCODEC_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_AUDIOENC_DELAY +#define FF_API_AUDIOENC_DELAY (LIBAVCODEC_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_AVCTX_TIMEBASE +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MPV_OPT +#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STREAM_CODEC_TAG +#define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_QUANT_BIAS +#define FF_API_QUANT_BIAS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_RC_STRATEGY +#define FF_API_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODED_FRAME +#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MOTION_EST +#define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_WITHOUT_PREFIX +#define FF_API_WITHOUT_PREFIX (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_SIDEDATA_ONLY_PKT +#define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VDPAU_PROFILE +#define FF_API_VDPAU_PROFILE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CONVERGENCE_DURATION +#define FF_API_CONVERGENCE_DURATION (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPICTURE +#define FF_API_AVPICTURE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPACKET_OLD_API +#define FF_API_AVPACKET_OLD_API (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_RTP_CALLBACK +#define FF_API_RTP_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VBV_DELAY +#define FF_API_VBV_DELAY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODER_TYPE +#define FF_API_CODER_TYPE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STAT_BITS +#define FF_API_STAT_BITS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NVENC_OLD_NAME +#define FF_API_NVENC_OLD_NAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_PRIVATE_OPT +#define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_BSF +#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_COPY_CONTEXT +#define FF_API_COPY_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_GET_CONTEXT_DEFAULTS +#define FF_API_GET_CONTEXT_DEFAULTS (LIBAVCODEC_VERSION_MAJOR < 59) #endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavcodec/vima.c b/libavcodec/vima.c index 14a3bca..6f539a8 100644 --- a/libavcodec/vima.c +++ b/libavcodec/vima.c @@ -214,5 +214,5 @@ AVCodec ff_adpcm_vima_decoder = { .id = AV_CODEC_ID_ADPCM_VIMA, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h new file mode 100644 index 0000000..4ade824 --- /dev/null +++ b/libavcodec/vlc.h @@ -0,0 +1,65 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VLC_H +#define AVCODEC_VLC_H + +#include + +#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; + +#define init_vlc(vlc, nb_bits, nb_codes, \ + bits, bits_wrap, bits_size, \ + codes, codes_wrap, codes_size, \ + flags) \ + ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \ + bits, bits_wrap, bits_size, \ + codes, codes_wrap, codes_size, \ + NULL, 0, 0, flags) + +int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + const void *symbols, int symbols_wrap, int symbols_size, + int flags); +void ff_free_vlc(VLC *vlc); + +#define INIT_VLC_LE 2 +#define INIT_VLC_USE_NEW_STATIC 4 + +#define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \ + do { \ + static VLC_TYPE table[static_size][2]; \ + (vlc)->table = table; \ + (vlc)->table_allocated = static_size; \ + init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \ + } while (0) + +#endif /* AVCODEC_VLC_H */ diff --git a/libavcodec/vmdaudio.c b/libavcodec/vmdaudio.c index 66c5865..9e02ba7 100644 --- a/libavcodec/vmdaudio.c +++ b/libavcodec/vmdaudio.c @@ -229,5 +229,5 @@ AVCodec ff_vmdaudio_decoder = { .priv_data_size = sizeof(VmdAudioContext), .init = vmdaudio_decode_init, .decode = vmdaudio_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vmdvideo.c b/libavcodec/vmdvideo.c index aaeff43..2e91c06 100644 --- a/libavcodec/vmdvideo.c +++ b/libavcodec/vmdvideo.c @@ -463,5 +463,5 @@ AVCodec ff_vmdvideo_decoder = { .init = vmdvideo_decode_init, .close = vmdvideo_decode_end, .decode = vmdvideo_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c index 16984fb..7a01f1e 100644 --- a/libavcodec/vmnc.c +++ b/libavcodec/vmnc.c @@ -287,12 +287,24 @@ static int decode_hextile(VmncContext *c, uint8_t* dst, GetByteContext *gb, return AVERROR_INVALIDDATA; } for (k = 0; k < rects; k++) { + int rect_x, rect_y, rect_w, rect_h; if (color) fg = vmnc_get_pixel(gb, bpp, c->bigendian); xy = bytestream2_get_byte(gb); wh = bytestream2_get_byte(gb); - paint_rect(dst2, xy >> 4, xy & 0xF, - (wh>>4)+1, (wh & 0xF)+1, fg, bpp, stride); + + rect_x = xy >> 4; + rect_y = xy & 0xF; + rect_w = (wh >> 4) + 1; + rect_h = (wh & 0xF) + 1; + + if (rect_x + rect_w > bw || rect_y + rect_h > bh) { + av_log(c->avctx, AV_LOG_ERROR, "Invalid subrect\n"); + return AVERROR_INVALIDDATA; + } + + paint_rect(dst2, rect_x, rect_y, + rect_w, rect_h, fg, bpp, stride); } } } @@ -419,10 +431,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, c->pic->pict_type = AV_PICTURE_TYPE_I; depth = bytestream2_get_byte(gb); if (depth != c->bpp) { - av_log(avctx, AV_LOG_INFO, - "Depth mismatch. Container %i bpp, " - "Frame data: %i bpp\n", - c->bpp, depth); + av_log(avctx, AV_LOG_WARNING, "Depth mismatch. " + "Container %i bpp / Codec %i bpp\n", c->bpp, depth); + + if (depth != 8 && depth != 16 && depth != 32) { + av_log(avctx, AV_LOG_ERROR, + "Unsupported codec bitdepth %i\n", depth); + return AVERROR_INVALIDDATA; + } + + /* reset values */ + c->bpp = depth; + c->bpp2 = c->bpp / 8; } bytestream2_skip(gb, 1); c->bigendian = bytestream2_get_byte(gb); @@ -524,6 +544,9 @@ static av_cold int decode_init(AVCodecContext *avctx) case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break; + case 24: + /* 24 bits is not technically supported, but some clients might + * mistakenly set it -- delay the actual check until decode_frame() */ case 32: avctx->pix_fmt = AV_PIX_FMT_RGB32; break; @@ -560,5 +583,5 @@ AVCodec ff_vmnc_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index 66fa21b..2c54320 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -22,10 +22,9 @@ * @author Denes Balatoni ( dbalatoni programozo hu ) */ -#define BITSTREAM_READER_LE -#include "avcodec.h" -#include "get_bits.h" +#include "libavutil/common.h" +#include "avcodec.h" #include "vorbis.h" @@ -53,13 +52,8 @@ unsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n) int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) { uint32_t exit_at_level[33] = { 404 }; - unsigned i, j, p, code; -#ifdef DEBUG - GetBitContext gb; -#endif - for (p = 0; (bits[p] == 0) && (p < num); ++p) ; if (p == num) @@ -71,14 +65,6 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) for (i = 0; i < bits[p]; ++i) exit_at_level[i+1] = 1 << i; -#ifdef DEBUG - av_log(NULL, AV_LOG_INFO, " %u. of %u code len %d code %d - ", p, num, bits[p], codes[p]); - init_get_bits(&gb, (uint8_t *)&codes[p], bits[p]); - for (i = 0; i < bits[p]; ++i) - av_log(NULL, AV_LOG_INFO, "%s", get_bits1(&gb) ? "1" : "0"); - av_log(NULL, AV_LOG_INFO, "\n"); -#endif - ++p; for (; p < num; ++p) { @@ -98,15 +84,6 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) for (j = i + 1 ;j <= bits[p]; ++j) exit_at_level[j] = code + (1 << (j - 1)); codes[p] = code; - -#ifdef DEBUG - av_log(NULL, AV_LOG_INFO, " %d. code len %d code %d - ", p, bits[p], codes[p]); - init_get_bits(&gb, (uint8_t *)&codes[p], bits[p]); - for (i = 0; i < bits[p]; ++i) - av_log(NULL, AV_LOG_INFO, "%s", get_bits1(&gb) ? "1" : "0"); - av_log(NULL, AV_LOG_INFO, "\n"); -#endif - } //no exits should be left (underspecified tree - ie. unused valid vlcs - not allowed by SPEC) diff --git a/libavcodec/vorbis_parser.c b/libavcodec/vorbis_parser.c index c413135..054635d 100644 --- a/libavcodec/vorbis_parser.c +++ b/libavcodec/vorbis_parser.c @@ -25,34 +25,42 @@ * Determines the duration for each packet. */ +#include "libavutil/log.h" + #include "get_bits.h" #include "parser.h" #include "xiph.h" -#include "vorbis_parser.h" +#include "vorbis_parser_internal.h" + +static const AVClass vorbis_parser_class = { + .class_name = "Vorbis parser", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; -static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s, +static int parse_id_header(AVVorbisParseContext *s, const uint8_t *buf, int buf_size) { /* Id header should be 30 bytes */ if (buf_size < 30) { - av_log(avctx, AV_LOG_ERROR, "Id header is too short\n"); + av_log(s, AV_LOG_ERROR, "Id header is too short\n"); return AVERROR_INVALIDDATA; } /* make sure this is the Id header */ if (buf[0] != 1) { - av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Id header\n"); + av_log(s, AV_LOG_ERROR, "Wrong packet type in Id header\n"); return AVERROR_INVALIDDATA; } /* check for header signature */ if (memcmp(&buf[1], "vorbis", 6)) { - av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Id header\n"); + av_log(s, AV_LOG_ERROR, "Invalid packet signature in Id header\n"); return AVERROR_INVALIDDATA; } if (!(buf[29] & 0x1)) { - av_log(avctx, AV_LOG_ERROR, "Invalid framing bit in Id header\n"); + av_log(s, AV_LOG_ERROR, "Invalid framing bit in Id header\n"); return AVERROR_INVALIDDATA; } @@ -62,7 +70,7 @@ static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s, return 0; } -static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, +static int parse_setup_header(AVVorbisParseContext *s, const uint8_t *buf, int buf_size) { GetBitContext gb, gb0; @@ -72,25 +80,25 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, /* avoid overread */ if (buf_size < 7) { - av_log(avctx, AV_LOG_ERROR, "Setup header is too short\n"); + av_log(s, AV_LOG_ERROR, "Setup header is too short\n"); return AVERROR_INVALIDDATA; } /* make sure this is the Setup header */ if (buf[0] != 5) { - av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Setup header\n"); + av_log(s, AV_LOG_ERROR, "Wrong packet type in Setup header\n"); return AVERROR_INVALIDDATA; } /* check for header signature */ if (memcmp(&buf[1], "vorbis", 6)) { - av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Setup header\n"); + av_log(s, AV_LOG_ERROR, "Invalid packet signature in Setup header\n"); return AVERROR_INVALIDDATA; } /* reverse bytes so we can easily read backwards with get_bits() */ if (!(rev_buf = av_malloc(buf_size))) { - av_log(avctx, AV_LOG_ERROR, "Out of memory\n"); + av_log(s, AV_LOG_ERROR, "Out of memory\n"); return AVERROR(ENOMEM); } for (i = 0; i < buf_size; i++) @@ -105,7 +113,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, } } if (!got_framing_bit) { - av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); + av_log(s, AV_LOG_ERROR, "Invalid Setup header\n"); ret = AVERROR_INVALIDDATA; goto bad_header; } @@ -132,7 +140,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, } } if (!got_mode_header) { - av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); + av_log(s, AV_LOG_ERROR, "Invalid Setup header\n"); ret = AVERROR_INVALIDDATA; goto bad_header; } @@ -141,7 +149,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, * we may need to approach this the long way and parse the whole Setup * header, but I hope very much that it never comes to that. */ if (last_mode_count > 2) { - avpriv_request_sample(avctx, + avpriv_request_sample(s, "%d modes (either a false positive or a " "sample from an unknown encoder)", last_mode_count); @@ -149,7 +157,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, /* We're limiting the mode count to 63 so that we know that the previous * block flag will be in the first packet byte. */ if (last_mode_count > 63) { - av_log(avctx, AV_LOG_ERROR, "Unsupported mode count: %d\n", + av_log(s, AV_LOG_ERROR, "Unsupported mode count: %d\n", last_mode_count); ret = AVERROR_INVALIDDATA; goto bad_header; @@ -173,26 +181,27 @@ bad_header: return ret; } -int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s) +static int vorbis_parse_init(AVVorbisParseContext *s, + const uint8_t *extradata, int extradata_size) { uint8_t *header_start[3]; int header_len[3]; int ret; - s->avctx = avctx; + s->class = &vorbis_parser_class; s->extradata_parsed = 1; - if ((ret = avpriv_split_xiph_headers(avctx->extradata, - avctx->extradata_size, 30, + if ((ret = avpriv_split_xiph_headers(extradata, + extradata_size, 30, header_start, header_len)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Extradata corrupt.\n"); + av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); return ret; } - if ((ret = parse_id_header(avctx, s, header_start[0], header_len[0])) < 0) + if ((ret = parse_id_header(s, header_start[0], header_len[0])) < 0) return ret; - if ((ret = parse_setup_header(avctx, s, header_start[2], header_len[2])) < 0) + if ((ret = parse_setup_header(s, header_start[2], header_len[2])) < 0) return ret; s->valid_extradata = 1; @@ -201,8 +210,8 @@ int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s) return 0; } -int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, - int buf_size) +int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size) { int duration = 0; @@ -211,7 +220,7 @@ int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, int previous_blocksize = s->previous_blocksize; if (buf[0] & 1) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid packet\n"); + av_log(s, AV_LOG_ERROR, "Invalid packet\n"); return AVERROR_INVALIDDATA; } if (s->mode_count == 1) @@ -219,7 +228,7 @@ int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, else mode = (buf[0] & s->mode_mask) >> 1; if (mode >= s->mode_count) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid mode in packet\n"); + av_log(s, AV_LOG_ERROR, "Invalid mode in packet\n"); return AVERROR_INVALIDDATA; } if (mode) { @@ -234,13 +243,57 @@ int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, return duration; } -void avpriv_vorbis_parse_reset(VorbisParseContext *s) +void av_vorbis_parse_reset(AVVorbisParseContext *s) { if (s->valid_extradata) s->previous_blocksize = s->mode_blocksize[0]; } +void av_vorbis_parse_free(AVVorbisParseContext **s) +{ + av_freep(s); +} + +AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata, + int extradata_size) +{ + AVVorbisParseContext *s = av_mallocz(sizeof(*s)); + int ret; + + if (!s) + return NULL; + + ret = vorbis_parse_init(s, extradata, extradata_size); + if (ret < 0) { + av_vorbis_parse_free(&s); + return NULL; + } + + return s; +} + +#if LIBAVCODEC_VERSION_MAJOR < 57 +int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, AVVorbisParseContext *s) +{ + return vorbis_parse_init(s, avctx->extradata, avctx->extradata_size); +} +void avpriv_vorbis_parse_reset(AVVorbisParseContext *s) +{ + av_vorbis_parse_reset(s); +} +int avpriv_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size) +{ + return av_vorbis_parse_frame(s, buf, buf_size); +} +#endif + #if CONFIG_VORBIS_PARSER + +typedef struct VorbisParseContext { + AVVorbisParseContext *vp; +} VorbisParseContext; + static int vorbis_parse(AVCodecParserContext *s1, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) @@ -248,11 +301,13 @@ static int vorbis_parse(AVCodecParserContext *s1, AVCodecContext *avctx, VorbisParseContext *s = s1->priv_data; int duration; - if (!s->extradata_parsed && avctx->extradata && avctx->extradata_size) - if (avpriv_vorbis_parse_extradata(avctx, s)) - goto end; + if (!s->vp && avctx->extradata && avctx->extradata_size) { + s->vp = av_vorbis_parse_init(avctx->extradata, avctx->extradata_size); + } + if (!s->vp) + goto end; - if ((duration = avpriv_vorbis_parse_frame(s, buf, buf_size)) >= 0) + if ((duration = av_vorbis_parse_frame(s->vp, buf, buf_size)) >= 0) s1->duration = duration; end: @@ -263,9 +318,16 @@ end: return buf_size; } +static void vorbis_parser_close(AVCodecParserContext *ctx) +{ + VorbisParseContext *s = ctx->priv_data; + av_vorbis_parse_free(&s->vp); +} + AVCodecParser ff_vorbis_parser = { .codec_ids = { AV_CODEC_ID_VORBIS }, .priv_data_size = sizeof(VorbisParseContext), .parser_parse = vorbis_parse, + .parser_close = vorbis_parser_close, }; #endif /* CONFIG_VORBIS_PARSER */ diff --git a/libavcodec/vorbis_parser.h b/libavcodec/vorbis_parser.h index 480a918..f97a523 100644 --- a/libavcodec/vorbis_parser.h +++ b/libavcodec/vorbis_parser.h @@ -1,6 +1,4 @@ /* - * Copyright (c) 2012 Justin Ruggles - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -20,49 +18,42 @@ /** * @file - * Vorbis audio parser + * A public API for Vorbis parsing * * Determines the duration for each packet. */ -#ifndef AVCODEC_VORBIS_PARSER_H -#define AVCODEC_VORBIS_PARSER_H +#ifndef AVCODEC_VORBIS_PARSE_H +#define AVCODEC_VORBIS_PARSE_H -#include "avcodec.h" +#include -typedef struct VorbisParseContext { - AVCodecContext *avctx; ///< codec context - int extradata_parsed; ///< we have attempted to parse extradata - int valid_extradata; ///< extradata is valid, so we can calculate duration - int blocksize[2]; ///< short and long window sizes - int previous_blocksize; ///< previous window size - int mode_blocksize[64]; ///< window size mapping for each mode - int mode_count; ///< number of modes - int mode_mask; ///< bitmask used to get the mode in each packet - int prev_mask; ///< bitmask used to get the previous mode flag in each packet -} VorbisParseContext; +typedef struct AVVorbisParseContext AVVorbisParseContext; /** - * Initialize the Vorbis parser using headers in the extradata. + * Allocate and initialize the Vorbis parser using headers in the extradata. * * @param avctx codec context * @param s Vorbis parser context */ -int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s); +AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata, + int extradata_size); + +/** + * Free the parser and everything associated with it. + */ +void av_vorbis_parse_free(AVVorbisParseContext **s); /** * Get the duration for a Vorbis packet. * - * avpriv_vorbis_parse_extradata() must have been successfully called prior to - * this in order for a correct duration to be returned. - * * @param s Vorbis parser context * @param buf buffer containing a Vorbis frame * @param buf_size size of the buffer */ -int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, - int buf_size); +int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size); -void avpriv_vorbis_parse_reset(VorbisParseContext *s); +void av_vorbis_parse_reset(AVVorbisParseContext *s); -#endif /* AVCODEC_VORBIS_PARSER_H */ +#endif /* AVCODEC_VORBIS_PARSE_H */ diff --git a/libavcodec/vorbis_parser_internal.h b/libavcodec/vorbis_parser_internal.h new file mode 100644 index 0000000..8f76af7 --- /dev/null +++ b/libavcodec/vorbis_parser_internal.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Vorbis audio parser + * + * Determines the duration for each packet. + */ + +#ifndef AVCODEC_VORBIS_PARSER_H +#define AVCODEC_VORBIS_PARSER_H + +#include "avcodec.h" +#include "vorbis_parser.h" + +struct AVVorbisParseContext { + const AVClass *class; + int extradata_parsed; ///< we have attempted to parse extradata + int valid_extradata; ///< extradata is valid, so we can calculate duration + int blocksize[2]; ///< short and long window sizes + int previous_blocksize; ///< previous window size + int mode_blocksize[64]; ///< window size mapping for each mode + int mode_count; ///< number of modes + int mode_mask; ///< bitmask used to get the mode in each packet + int prev_mask; ///< bitmask used to get the previous mode flag in each packet +}; + +#if LIBAVCODEC_VERSION_MAJOR < 57 +/** + * Initialize the Vorbis parser using headers in the extradata. + * + * @param avctx codec context + * @param s Vorbis parser context + */ +int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, AVVorbisParseContext *s); + +/** + * Get the duration for a Vorbis packet. + * + * avpriv_vorbis_parse_extradata() must have been successfully called prior to + * this in order for a correct duration to be returned. + * + * @param s Vorbis parser context + * @param buf buffer containing a Vorbis frame + * @param buf_size size of the buffer + */ +int avpriv_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size); + +void avpriv_vorbis_parse_reset(AVVorbisParseContext *s); +#endif + +#endif /* AVCODEC_VORBIS_PARSER_H */ diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index 1ce9e26..8b800fd 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -25,14 +25,13 @@ #include #include -#define BITSTREAM_READER_LE #include "libavutil/float_dsp.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" -#include "get_bits.h" #include "fft.h" -#include "fmtconvert.h" +#include "get_bits.h" #include "internal.h" - #include "vorbis.h" #include "vorbisdsp.h" #include "xiph.h" @@ -42,7 +41,7 @@ #define V_MAX_VLCS (1 << 16) #define V_MAX_PARTITIONS (1 << 20) -typedef struct { +typedef struct vorbis_codebook { uint8_t dimensions; uint8_t lookup_type; uint8_t maxdepth; @@ -58,7 +57,7 @@ struct vorbis_context_s; typedef int (* vorbis_floor_decode_func) (struct vorbis_context_s *, vorbis_floor_data *, float *); -typedef struct { +typedef struct vorbis_floor { uint8_t floor_type; vorbis_floor_decode_func decode; union vorbis_floor_u { @@ -88,7 +87,7 @@ typedef struct { } data; } vorbis_floor; -typedef struct { +typedef struct vorbis_residue { uint16_t type; uint32_t begin; uint32_t end; @@ -101,7 +100,7 @@ typedef struct { uint8_t *classifs; } vorbis_residue; -typedef struct { +typedef struct vorbis_mapping { uint8_t submaps; uint16_t coupling_steps; uint8_t *magnitude; @@ -111,7 +110,7 @@ typedef struct { uint8_t submap_residue[16]; } vorbis_mapping; -typedef struct { +typedef struct vorbis_mode { uint8_t blockflag; uint16_t windowtype; uint16_t transformtype; @@ -123,7 +122,6 @@ typedef struct vorbis_context_s { GetBitContext gb; VorbisDSPContext dsp; AVFloatDSPContext fdsp; - FmtConvertContext fmt_conv; FFTContext mdct[2]; uint8_t first_frame; @@ -238,7 +236,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) vc->codebook_count = get_bits(gb, 8) + 1; - av_dlog(NULL, " Codebooks: %d \n", vc->codebook_count); + ff_dlog(NULL, " Codebooks: %d \n", vc->codebook_count); vc->codebooks = av_mallocz(vc->codebook_count * sizeof(*vc->codebooks)); tmp_vlc_bits = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_bits)); @@ -254,7 +252,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) vorbis_codebook *codebook_setup = &vc->codebooks[cb]; unsigned ordered, t, entries, used_entries = 0; - av_dlog(NULL, " %u. Codebook\n", cb); + ff_dlog(NULL, " %u. Codebook\n", cb); if (get_bits(gb, 24) != 0x564342) { av_log(vc->avctx, AV_LOG_ERROR, @@ -282,17 +280,17 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) ordered = get_bits1(gb); - av_dlog(NULL, " codebook_dimensions %d, codebook_entries %u\n", + ff_dlog(NULL, " codebook_dimensions %d, codebook_entries %u\n", codebook_setup->dimensions, entries); if (!ordered) { unsigned ce, flag; unsigned sparse = get_bits1(gb); - av_dlog(NULL, " not ordered \n"); + ff_dlog(NULL, " not ordered \n"); if (sparse) { - av_dlog(NULL, " sparse \n"); + ff_dlog(NULL, " sparse \n"); used_entries = 0; for (ce = 0; ce < entries; ++ce) { @@ -304,7 +302,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) tmp_vlc_bits[ce] = 0; } } else { - av_dlog(NULL, " not sparse \n"); + ff_dlog(NULL, " not sparse \n"); used_entries = entries; for (ce = 0; ce < entries; ++ce) @@ -314,17 +312,17 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) unsigned current_entry = 0; unsigned current_length = get_bits(gb, 5) + 1; - av_dlog(NULL, " ordered, current length: %u\n", current_length); //FIXME + ff_dlog(NULL, " ordered, current length: %u\n", current_length); //FIXME used_entries = entries; for (; current_entry < used_entries && current_length <= 32; ++current_length) { unsigned i, number; - av_dlog(NULL, " number bits: %u ", ilog(entries - current_entry)); + ff_dlog(NULL, " number bits: %u ", ilog(entries - current_entry)); number = get_bits(gb, ilog(entries - current_entry)); - av_dlog(NULL, " number: %u\n", number); + ff_dlog(NULL, " number: %u\n", number); for (i = current_entry; i < number+current_entry; ++i) if (i < used_entries) @@ -341,7 +339,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) codebook_setup->lookup_type = get_bits(gb, 4); - av_dlog(NULL, " lookup type: %d : %s \n", codebook_setup->lookup_type, + ff_dlog(NULL, " lookup type: %d : %s \n", codebook_setup->lookup_type, codebook_setup->lookup_type ? "vq" : "no lookup"); // If the codebook is used for (inverse) VQ, calculate codevectors. @@ -355,24 +353,29 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) unsigned codebook_value_bits = get_bits(gb, 4) + 1; unsigned codebook_sequence_p = get_bits1(gb); - av_dlog(NULL, " We expect %d numbers for building the codevectors. \n", + ff_dlog(NULL, " We expect %d numbers for building the codevectors. \n", codebook_lookup_values); - av_dlog(NULL, " delta %f minmum %f \n", + ff_dlog(NULL, " delta %f minmum %f \n", codebook_delta_value, codebook_minimum_value); for (i = 0; i < codebook_lookup_values; ++i) { codebook_multiplicands[i] = get_bits(gb, codebook_value_bits); - av_dlog(NULL, " multiplicands*delta+minmum : %e \n", + ff_dlog(NULL, " multiplicands*delta+minmum : %e \n", (float)codebook_multiplicands[i] * codebook_delta_value + codebook_minimum_value); - av_dlog(NULL, " multiplicand %u\n", codebook_multiplicands[i]); + ff_dlog(NULL, " multiplicand %u\n", codebook_multiplicands[i]); } // Weed out unused vlcs and build codevector vector - codebook_setup->codevectors = used_entries ? av_mallocz(used_entries * - codebook_setup->dimensions * - sizeof(*codebook_setup->codevectors)) - : NULL; + if (used_entries) { + codebook_setup->codevectors = + av_mallocz(used_entries * codebook_setup->dimensions * + sizeof(*codebook_setup->codevectors)); + if (!codebook_setup->codevectors) + return AVERROR(ENOMEM); + } else + codebook_setup->codevectors = NULL; + for (j = 0, i = 0; i < entries; ++i) { unsigned dim = codebook_setup->dimensions; @@ -380,7 +383,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) float last = 0.0; unsigned lookup_offset = i; - av_dlog(vc->avctx, "Lookup offset %u ,", i); + ff_dlog(vc->avctx, "Lookup offset %u ,", i); for (k = 0; k < dim; ++k) { unsigned multiplicand_offset = lookup_offset % codebook_lookup_values; @@ -391,11 +394,11 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) } tmp_vlc_bits[j] = tmp_vlc_bits[i]; - av_dlog(vc->avctx, "real lookup offset %u, vector: ", j); + ff_dlog(vc->avctx, "real lookup offset %u, vector: ", j); for (k = 0; k < dim; ++k) - av_dlog(vc->avctx, " %f ", + ff_dlog(vc->avctx, " %f ", codebook_setup->codevectors[j * dim + k]); - av_dlog(vc->avctx, "\n"); + ff_dlog(vc->avctx, "\n"); ++j; } @@ -463,7 +466,7 @@ static int vorbis_parse_setup_hdr_tdtransforms(vorbis_context *vc) for (i = 0; i < vorbis_time_count; ++i) { unsigned vorbis_tdtransform = get_bits(gb, 16); - av_dlog(NULL, " Vorbis time domain transform %u: %u\n", + ff_dlog(NULL, " Vorbis time domain transform %u: %u\n", vorbis_time_count, vorbis_tdtransform); if (vorbis_tdtransform) { @@ -497,7 +500,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) floor_setup->floor_type = get_bits(gb, 16); - av_dlog(NULL, " %d. floor type %d \n", i, floor_setup->floor_type); + ff_dlog(NULL, " %d. floor type %d \n", i, floor_setup->floor_type); if (floor_setup->floor_type == 1) { int maximum_class = -1; @@ -507,7 +510,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) floor_setup->data.t1.partitions = get_bits(gb, 5); - av_dlog(NULL, " %d.floor: %d partitions \n", + ff_dlog(NULL, " %d.floor: %d partitions \n", i, floor_setup->data.t1.partitions); for (j = 0; j < floor_setup->data.t1.partitions; ++j) { @@ -515,25 +518,25 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) if (floor_setup->data.t1.partition_class[j] > maximum_class) maximum_class = floor_setup->data.t1.partition_class[j]; - av_dlog(NULL, " %d. floor %d partition class %d \n", + ff_dlog(NULL, " %d. floor %d partition class %d \n", i, j, floor_setup->data.t1.partition_class[j]); } - av_dlog(NULL, " maximum class %d \n", maximum_class); + ff_dlog(NULL, " maximum class %d \n", maximum_class); for (j = 0; j <= maximum_class; ++j) { floor_setup->data.t1.class_dimensions[j] = get_bits(gb, 3) + 1; floor_setup->data.t1.class_subclasses[j] = get_bits(gb, 2); - av_dlog(NULL, " %d floor %d class dim: %d subclasses %d \n", i, j, + ff_dlog(NULL, " %d floor %d class dim: %d subclasses %d \n", i, j, floor_setup->data.t1.class_dimensions[j], floor_setup->data.t1.class_subclasses[j]); if (floor_setup->data.t1.class_subclasses[j]) { GET_VALIDATED_INDEX(floor_setup->data.t1.class_masterbook[j], 8, vc->codebook_count) - av_dlog(NULL, " masterbook: %d \n", floor_setup->data.t1.class_masterbook[j]); + ff_dlog(NULL, " masterbook: %d \n", floor_setup->data.t1.class_masterbook[j]); } for (k = 0; k < (1 << floor_setup->data.t1.class_subclasses[j]); ++k) { @@ -542,7 +545,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) VALIDATE_INDEX(bits, vc->codebook_count) floor_setup->data.t1.subclass_books[j][k] = bits; - av_dlog(NULL, " book %d. : %d \n", k, floor_setup->data.t1.subclass_books[j][k]); + ff_dlog(NULL, " book %d. : %d \n", k, floor_setup->data.t1.subclass_books[j][k]); } } @@ -572,7 +575,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) for (k = 0; k < floor_setup->data.t1.class_dimensions[floor_setup->data.t1.partition_class[j]]; ++k, ++floor1_values) { floor_setup->data.t1.list[floor1_values].x = get_bits(gb, rangebits); - av_dlog(NULL, " %u. floor1 Y coord. %d\n", floor1_values, + ff_dlog(NULL, " %u. floor1 Y coord. %d\n", floor1_values, floor_setup->data.t1.list[floor1_values].x); } } @@ -637,22 +640,22 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) return AVERROR(ENOMEM); /* debug output parsed headers */ - av_dlog(NULL, "floor0 order: %u\n", floor_setup->data.t0.order); - av_dlog(NULL, "floor0 rate: %u\n", floor_setup->data.t0.rate); - av_dlog(NULL, "floor0 bark map size: %u\n", + ff_dlog(NULL, "floor0 order: %u\n", floor_setup->data.t0.order); + ff_dlog(NULL, "floor0 rate: %u\n", floor_setup->data.t0.rate); + ff_dlog(NULL, "floor0 bark map size: %u\n", floor_setup->data.t0.bark_map_size); - av_dlog(NULL, "floor0 amplitude bits: %u\n", + ff_dlog(NULL, "floor0 amplitude bits: %u\n", floor_setup->data.t0.amplitude_bits); - av_dlog(NULL, "floor0 amplitude offset: %u\n", + ff_dlog(NULL, "floor0 amplitude offset: %u\n", floor_setup->data.t0.amplitude_offset); - av_dlog(NULL, "floor0 number of books: %u\n", + ff_dlog(NULL, "floor0 number of books: %u\n", floor_setup->data.t0.num_books); - av_dlog(NULL, "floor0 book list pointer: %p\n", + ff_dlog(NULL, "floor0 book list pointer: %p\n", floor_setup->data.t0.book_list); { int idx; for (idx = 0; idx < floor_setup->data.t0.num_books; ++idx) { - av_dlog(NULL, " Book %d: %u\n", idx + 1, + ff_dlog(NULL, " Book %d: %u\n", idx + 1, floor_setup->data.t0.book_list[idx]); } } @@ -676,7 +679,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) if (!vc->residues) return AVERROR(ENOMEM); - av_dlog(NULL, " There are %d residues. \n", vc->residue_count); + ff_dlog(NULL, " There are %d residues. \n", vc->residue_count); for (i = 0; i < vc->residue_count; ++i) { vorbis_residue *res_setup = &vc->residues[i]; @@ -685,7 +688,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) res_setup->type = get_bits(gb, 16); - av_dlog(NULL, " %u. residue type %d\n", i, res_setup->type); + ff_dlog(NULL, " %u. residue type %d\n", i, res_setup->type); res_setup->begin = get_bits(gb, 24); res_setup->end = get_bits(gb, 24); @@ -712,7 +715,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) if (!res_setup->classifs) return AVERROR(ENOMEM); - av_dlog(NULL, " begin %d end %d part.size %d classif.s %d classbook %d \n", + ff_dlog(NULL, " begin %d end %d part.size %d classif.s %d classbook %d \n", res_setup->begin, res_setup->end, res_setup->partition_size, res_setup->classifications, res_setup->classbook); @@ -723,7 +726,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) high_bits = get_bits(gb, 5); cascade[j] = (high_bits << 3) + low_bits; - av_dlog(NULL, " %u class cascade depth: %d\n", j, ilog(cascade[j])); + ff_dlog(NULL, " %u class cascade depth: %d\n", j, ilog(cascade[j])); } res_setup->maxpass = 0; @@ -732,7 +735,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) if (cascade[j]&(1 << k)) { GET_VALIDATED_INDEX(res_setup->books[j][k], 8, vc->codebook_count) - av_dlog(NULL, " %u class cascade depth %u book: %d\n", + ff_dlog(NULL, " %u class cascade depth %u book: %d\n", j, k, res_setup->books[j][k]); if (k>res_setup->maxpass) @@ -758,7 +761,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) if (!vc->mappings) return AVERROR(ENOMEM); - av_dlog(NULL, " There are %d mappings. \n", vc->mapping_count); + ff_dlog(NULL, " There are %d mappings. \n", vc->mapping_count); for (i = 0; i < vc->mapping_count; ++i) { vorbis_mapping *mapping_setup = &vc->mappings[i]; @@ -790,7 +793,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) mapping_setup->coupling_steps = 0; } - av_dlog(NULL, " %u mapping coupling steps: %d\n", + ff_dlog(NULL, " %u mapping coupling steps: %d\n", i, mapping_setup->coupling_steps); if (get_bits(gb, 2)) { @@ -813,7 +816,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) GET_VALIDATED_INDEX(mapping_setup->submap_floor[j], 8, vc->floor_count) GET_VALIDATED_INDEX(mapping_setup->submap_residue[j], 8, vc->residue_count) - av_dlog(NULL, " %u mapping %u submap : floor %d, residue %d\n", i, j, + ff_dlog(NULL, " %u mapping %u submap : floor %d, residue %d\n", i, j, mapping_setup->submap_floor[j], mapping_setup->submap_residue[j]); } @@ -852,7 +855,7 @@ static int create_map(vorbis_context *vc, unsigned floor_number) } for (idx = 0; idx <= n; ++idx) { - av_dlog(NULL, "floor0 map: map at pos %d is %d\n", idx, map[idx]); + ff_dlog(NULL, "floor0 map: map at pos %d is %d\n", idx, map[idx]); } return 0; @@ -868,7 +871,7 @@ static int vorbis_parse_setup_hdr_modes(vorbis_context *vc) if (!vc->modes) return AVERROR(ENOMEM); - av_dlog(NULL, " There are %d modes.\n", vc->mode_count); + ff_dlog(NULL, " There are %d modes.\n", vc->mode_count); for (i = 0; i < vc->mode_count; ++i) { vorbis_mode *mode_setup = &vc->modes[i]; @@ -878,7 +881,7 @@ static int vorbis_parse_setup_hdr_modes(vorbis_context *vc) mode_setup->transformtype = get_bits(gb, 16); //FIXME check GET_VALIDATED_INDEX(mode_setup->mapping, 8, vc->mapping_count); - av_dlog(NULL, " %u mode: blockflag %d, windowtype %d, transformtype %d, mapping %d\n", + ff_dlog(NULL, " %u mode: blockflag %d, windowtype %d, transformtype %d, mapping %d\n", i, mode_setup->blockflag, mode_setup->windowtype, mode_setup->transformtype, mode_setup->mapping); } @@ -985,7 +988,7 @@ static int vorbis_parse_id_hdr(vorbis_context *vc) ff_mdct_init(&vc->mdct[0], bl0, 1, -1.0); ff_mdct_init(&vc->mdct[1], bl1, 1, -1.0); - av_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ", + ff_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ", vc->version, vc->audio_channels, vc->audio_samplerate, vc->bitrate_maximum, vc->bitrate_nominal, vc->bitrate_minimum, vc->blocksize[0], vc->blocksize[1]); /* @@ -1012,8 +1015,7 @@ static av_cold int vorbis_decode_init(AVCodecContext *avctx) vc->avctx = avctx; ff_vorbisdsp_init(&vc->dsp); - avpriv_float_dsp_init(&vc->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); - ff_fmt_convert_init(&vc->fmt_conv, avctx); + avpriv_float_dsp_init(&vc->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; @@ -1089,7 +1091,7 @@ static int vorbis_floor0_decode(vorbis_context *vc, av_log(vc->avctx, AV_LOG_ERROR, "floor0 dec: booknumber too high!\n"); book_idx = 0; } - av_dlog(NULL, "floor0 dec: booknumber: %u\n", book_idx); + ff_dlog(NULL, "floor0 dec: booknumber: %u\n", book_idx); codebook = vc->codebooks[vf->book_list[book_idx]]; /* Invalid codebook! */ if (!codebook.codevectors) @@ -1098,13 +1100,13 @@ static int vorbis_floor0_decode(vorbis_context *vc, while (lsp_lenorder) { int vec_off; - av_dlog(NULL, "floor0 dec: book dimension: %d\n", codebook.dimensions); - av_dlog(NULL, "floor0 dec: maximum depth: %d\n", codebook.maxdepth); + ff_dlog(NULL, "floor0 dec: book dimension: %d\n", codebook.dimensions); + ff_dlog(NULL, "floor0 dec: maximum depth: %d\n", codebook.maxdepth); /* read temp vector */ vec_off = get_vlc2(&vc->gb, codebook.vlc.table, codebook.nb_bits, codebook.maxdepth) * codebook.dimensions; - av_dlog(NULL, "floor0 dec: vector offset: %d\n", vec_off); + ff_dlog(NULL, "floor0 dec: vector offset: %d\n", vec_off); /* copy each vector component and add last to it */ for (idx = 0; idx < codebook.dimensions; ++idx) lsp[lsp_len+idx] = codebook.codevectors[vec_off+idx] + last; @@ -1116,7 +1118,7 @@ static int vorbis_floor0_decode(vorbis_context *vc, { int idx; for (idx = 0; idx < lsp_len; ++idx) - av_dlog(NULL, "floor0 dec: coeff at %d is %f\n", idx, lsp[idx]); + ff_dlog(NULL, "floor0 dec: coeff at %d is %f\n", idx, lsp[idx]); } /* synthesize floor output vector */ @@ -1128,7 +1130,7 @@ static int vorbis_floor0_decode(vorbis_context *vc, for (i = 0; i < order; i++) lsp[i] = 2.0f * cos(lsp[i]); - av_dlog(NULL, "floor0 synth: map_size = %"PRIu32"; m = %d; wstep = %f\n", + ff_dlog(NULL, "floor0 synth: map_size = %"PRIu32"; m = %d; wstep = %f\n", vf->map_size[blockflag], order, wstep); i = 0; @@ -1170,7 +1172,7 @@ static int vorbis_floor0_decode(vorbis_context *vc, return 1; } - av_dlog(NULL, " Floor0 decoded\n"); + ff_dlog(NULL, " Floor0 decoded\n"); return 0; } @@ -1197,7 +1199,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, floor1_Y[0] = get_bits(gb, ilog(range - 1)); floor1_Y[1] = get_bits(gb, ilog(range - 1)); - av_dlog(NULL, "floor 0 Y %d floor 1 Y %d \n", floor1_Y[0], floor1_Y[1]); + ff_dlog(NULL, "floor 0 Y %d floor 1 Y %d \n", floor1_Y[0], floor1_Y[1]); offset = 2; for (i = 0; i < vf->partitions; ++i) { @@ -1207,7 +1209,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, csub = (1 << cbits) - 1; cval = 0; - av_dlog(NULL, "Cbits %u\n", cbits); + ff_dlog(NULL, "Cbits %u\n", cbits); if (cbits) // this reads all subclasses for this partition's class cval = get_vlc2(gb, vc->codebooks[vf->class_masterbook[class]].vlc.table, @@ -1216,7 +1218,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, for (j = 0; j < cdim; ++j) { book = vf->subclass_books[class][cval & csub]; - av_dlog(NULL, "book %d Cbits %u cval %u bits:%d\n", + ff_dlog(NULL, "book %d Cbits %u cval %u bits:%d\n", book, cbits, cval, get_bits_count(gb)); cval = cval >> cbits; @@ -1227,7 +1229,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, floor1_Y[offset+j] = 0; } - av_dlog(NULL, " floor(%d) = %d \n", + ff_dlog(NULL, " floor(%d) = %d \n", vf->list[offset+j].x, floor1_Y[offset+j]); } offset+=cdim; @@ -1286,7 +1288,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, floor1_Y_final[i] = av_clip_uint16(predicted); } - av_dlog(NULL, " Decoded floor(%d) = %u / val %u\n", + ff_dlog(NULL, " Decoded floor(%d) = %u / val %u\n", vf->list[i].x, floor1_Y_final[i], val); } @@ -1294,7 +1296,7 @@ static int vorbis_floor1_decode(vorbis_context *vc, ff_vorbis_floor1_render_list(vf->list, vf->x_list_dim, floor1_Y_final, floor1_flag, vf->multiplier, vec, vf->list[1].x); - av_dlog(NULL, " Floor decoded\n"); + ff_dlog(NULL, " Floor decoded\n"); return 0; } @@ -1305,16 +1307,17 @@ static av_always_inline int setup_classifs(vorbis_context *vc, unsigned ch_used, int partition_count) { + vorbis_codebook *codebook = vc->codebooks + vr->classbook; int p, j, i; - unsigned c_p_c = vc->codebooks[vr->classbook].dimensions; + unsigned c_p_c = codebook->dimensions; unsigned inverse_class = ff_inverse[vr->classifications]; int temp, temp2; for (p = 0, j = 0; j < ch_used; ++j) { if (!do_not_decode[j]) { - temp = get_vlc2(&vc->gb, vc->codebooks[vr->classbook].vlc.table, - vc->codebooks[vr->classbook].nb_bits, 3); + temp = get_vlc2(&vc->gb, codebook->vlc.table, + codebook->nb_bits, 3); - av_dlog(NULL, "Classword: %u\n", temp); + ff_dlog(NULL, "Classword: %u\n", temp); if (temp < 0) { av_log(vc->avctx, AV_LOG_ERROR, @@ -1369,7 +1372,7 @@ static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc, return AVERROR_INVALIDDATA; } - av_dlog(NULL, " residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c); + ff_dlog(NULL, " residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c); for (pass = 0; pass <= vr->maxpass; ++pass) { // FIXME OPTIMIZE? int voffset, partition_count, j_times_ptns_to_read; @@ -1410,7 +1413,7 @@ static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc, for (l = 0; l < dim; ++l, ++voffs) { vec[voffs]+=codebook.codevectors[coffs+l]; - av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d \n", + ff_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d \n", pass, voffs, vec[voffs], codebook.codevectors[coffs+l], coffs); } } @@ -1438,7 +1441,7 @@ static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc, vec[voffs ] += codebook.codevectors[coffs + l ]; vec[voffs + vlen] += codebook.codevectors[coffs + l + 1]; - av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", + ff_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffset / ch + (voffs % ch) * vlen, vec[voffset / ch + (voffs % ch) * vlen], codebook.codevectors[coffs + l], coffs, l); @@ -1455,7 +1458,7 @@ static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc, vec[voffs_div + voffs_mod * vlen] += codebook.codevectors[coffs + l]; - av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", + ff_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffs_div + voffs_mod * vlen, vec[voffs_div + voffs_mod * vlen], codebook.codevectors[coffs + l], coffs, l); @@ -1553,7 +1556,7 @@ static int vorbis_parse_audio_packet(vorbis_context *vc, float **floor_ptr) vc->mode_number = mode_number; mapping = &vc->mappings[vc->modes[mode_number].mapping]; - av_dlog(NULL, " Mode number: %u , mapping: %d , blocktype %d\n", mode_number, + ff_dlog(NULL, " Mode number: %u , mapping: %d , blocktype %d\n", mode_number, vc->modes[mode_number].mapping, vc->modes[mode_number].blockflag); blockflag = vc->modes[mode_number].blockflag; @@ -1695,7 +1698,7 @@ static int vorbis_decode_frame(AVCodecContext *avctx, void *data, float *channel_ptrs[255]; int i, len, ret; - av_dlog(NULL, "packet length %d \n", buf_size); + ff_dlog(NULL, "packet length %d \n", buf_size); /* get output buffer */ frame->nb_samples = vc->blocksize[1] / 2; @@ -1726,7 +1729,7 @@ static int vorbis_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } - av_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", + ff_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb) / 8, get_bits_count(gb) % 8, len); frame->nb_samples = len; @@ -1767,7 +1770,7 @@ AVCodec ff_vorbis_decoder = { .close = vorbis_decode_close, .decode = vorbis_decode_frame, .flush = vorbis_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .channel_layouts = ff_vorbis_channel_layouts, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index 830e5d1..35bdd57 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -39,7 +39,7 @@ #undef NDEBUG #include -typedef struct { +typedef struct vorbis_enc_codebook { int nentries; uint8_t *lens; uint32_t *codewords; @@ -53,14 +53,14 @@ typedef struct { float *pow2; } vorbis_enc_codebook; -typedef struct { +typedef struct vorbis_enc_floor_class { int dim; int subclass; int masterbook; int *books; } vorbis_enc_floor_class; -typedef struct { +typedef struct vorbis_enc_floor { int partitions; int *partition_to_class; int nclasses; @@ -71,7 +71,7 @@ typedef struct { vorbis_floor1_entry *list; } vorbis_enc_floor; -typedef struct { +typedef struct vorbis_enc_residue { int type; int begin; int end; @@ -82,7 +82,7 @@ typedef struct { float (*maxes)[2]; } vorbis_enc_residue; -typedef struct { +typedef struct vorbis_enc_mapping { int submaps; int *mux; int *floor; @@ -92,12 +92,12 @@ typedef struct { int *angle; } vorbis_enc_mapping; -typedef struct { +typedef struct vorbis_enc_mode { int blockflag; int mapping; } vorbis_enc_mode; -typedef struct { +typedef struct vorbis_enc_context { int channels; int sample_rate; int log2_blocksize[2]; @@ -1091,11 +1091,12 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, avpkt->size = put_bits_count(&pb) >> 3; avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); - if (frame) + if (frame) { if (frame->pts != AV_NOPTS_VALUE) avpkt->pts = ff_samples_to_time_base(avctx, frame->pts); - else + } else { avpkt->pts = venc->next_pts; + } if (avpkt->pts != AV_NOPTS_VALUE) venc->next_pts = avpkt->pts + avpkt->duration; @@ -1177,7 +1178,7 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) goto error; avctx->bit_rate = 0; - if (avctx->flags & CODEC_FLAG_QSCALE) + if (avctx->flags & AV_CODEC_FLAG_QSCALE) venc->quality = avctx->global_quality / (float)FF_QP2LAMBDA; else venc->quality = 3.0; @@ -1204,7 +1205,7 @@ AVCodec ff_vorbis_encoder = { .init = vorbis_encode_init, .encode2 = vorbis_encode_frame, .close = vorbis_encode_close, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index c2ea822..26374cc 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2004 the ffmpeg project + * Copyright (C) 2003-2004 The FFmpeg project * * This file is part of Libav. * @@ -171,6 +171,8 @@ typedef struct Vp3DecodeContext { Vp3Fragment *all_fragments; int fragment_start[3]; int data_offset[3]; + uint8_t offset_x; + uint8_t offset_y; int8_t (*motion_val[2])[2]; @@ -930,14 +932,14 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, int num_coeffs = s->num_coded_frags[plane][coeff_index]; int16_t *dct_tokens = s->dct_tokens[plane][coeff_index]; - /* local references to structure members to avoid repeated deferences */ + /* local references to structure members to avoid repeated dereferences */ int *coded_fragment_list = s->coded_fragment_list[plane]; Vp3Fragment *all_fragments = s->all_fragments; VLC_TYPE(*vlc_table)[2] = table->table; if (num_coeffs < 0) av_log(s->avctx, AV_LOG_ERROR, - "Invalid number of coefficents at level %d\n", coeff_index); + "Invalid number of coefficients at level %d\n", coeff_index); if (eob_run > num_coeffs) { coeff_i = @@ -1019,7 +1021,7 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, if (blocks_ended > s->num_coded_frags[plane][coeff_index]) av_log(s->avctx, AV_LOG_ERROR, "More blocks ended than coded!\n"); - // decrement the number of blocks that have higher coeffecients for each + // decrement the number of blocks that have higher coefficients for each // EOB run at this level if (blocks_ended) for (i = coeff_index + 1; i < 64; i++) @@ -1079,7 +1081,7 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) return residual_eob_run; /* reverse prediction of the C-plane DC coefficients */ - if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { + if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { reverse_dc_prediction(s, s->fragment_start[1], s->fragment_width[1], s->fragment_height[1]); reverse_dc_prediction(s, s->fragment_start[2], @@ -1108,7 +1110,7 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) c_tables[i] = &s->ac_vlc_4[ac_c_table]; } - /* decode all AC coefficents */ + /* decode all AC coefficients */ for (i = 1; i <= 63; i++) { residual_eob_run = unpack_vlcs(s, gb, y_tables[i], i, 0, residual_eob_run); @@ -1306,7 +1308,7 @@ static void apply_loop_filter(Vp3DecodeContext *s, int plane, for (x = 0; x < width; x++) { /* This code basically just deblocks on the edges of coded blocks. * However, it has to be much more complicated because of the - * braindamaged deblock ordering used in VP3/Theora. Order matters + * brain damaged deblock ordering used in VP3/Theora. Order matters * because some pixels get filtered twice. */ if (s->all_fragments[fragment].coding_method != MODE_COPY) { /* do not perform left edge filter for left columns frags */ @@ -1405,14 +1407,14 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) int offset[AV_NUM_DATA_POINTERS]; if (HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_FRAME) { - int y_flipped = s->flipped_image ? s->avctx->height - y : y; + int y_flipped = s->flipped_image ? s->height - y : y; /* At the end of the frame, report INT_MAX instead of the height of * the frame. This makes the other threads' ff_thread_await_progress() * calls cheaper, because they don't have to clip their values. */ ff_thread_report_progress(&s->current_frame, - y_flipped == s->avctx->height ? INT_MAX - : y_flipped - 1, + y_flipped == s->height ? INT_MAX + : y_flipped - 1, 0); } @@ -1424,7 +1426,7 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) y -= h; if (!s->flipped_image) - y = s->avctx->height - y - h; + y = s->height - y - h; cy = y >> s->chroma_y_shift; offset[0] = s->current_frame.f->linesize[0] * y; @@ -1502,7 +1504,7 @@ static void render_slice(Vp3DecodeContext *s, int slice) if (!s->flipped_image) stride = -stride; - if (CONFIG_GRAY && plane && (s->avctx->flags & CODEC_FLAG_GRAY)) + if (CONFIG_GRAY && plane && (s->avctx->flags & AV_CODEC_FLAG_GRAY)) continue; /* for each superblock row in the slice (both of them)... */ @@ -1579,7 +1581,7 @@ static void render_slice(Vp3DecodeContext *s, int slice) /* 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 */ + * put_no_rnd_pixels_tab is better optimized */ if (motion_halfpel_index != 3) { s->hdsp.put_no_rnd_pixels_tab[1][motion_halfpel_index]( output_plane + first_pixel, @@ -1721,12 +1723,12 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) s->version = 1; s->avctx = avctx; - s->width = FFALIGN(avctx->width, 16); - s->height = FFALIGN(avctx->height, 16); + s->width = FFALIGN(avctx->coded_width, 16); + s->height = FFALIGN(avctx->coded_height, 16); if (avctx->pix_fmt == AV_PIX_FMT_NONE) avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; - ff_hpeldsp_init(&s->hdsp, avctx->flags | CODEC_FLAG_BITEXACT); + ff_hpeldsp_init(&s->hdsp, avctx->flags | AV_CODEC_FLAG_BITEXACT); ff_videodsp_init(&s->vdsp, 8); ff_vp3dsp_init(&s->vp3dsp, avctx->flags); @@ -2115,10 +2117,17 @@ static int vp3_decode_frame(AVCodecContext *avctx, int row = (s->height >> (3 + (i && s->chroma_y_shift))) - 1; apply_loop_filter(s, i, row, row + 1); } - vp3_draw_horiz_band(s, s->avctx->height); + vp3_draw_horiz_band(s, s->height); + /* output frame, offset as needed */ if ((ret = av_frame_ref(data, s->current_frame.f)) < 0) return ret; + for (i = 0; i < 3; i++) { + AVFrame *dst = data; + int off = (s->offset_x >> (i && s->chroma_y_shift)) + + (s->offset_y >> (i && s->chroma_y_shift)) * dst->linesize[i]; + dst->data[i] += off; + } *got_frame = 1; if (!HAVE_THREADS || !(s->avctx->active_thread_type & FF_THREAD_FRAME)) { @@ -2149,7 +2158,7 @@ static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb) return -1; } token = get_bits(gb, 5); - av_dlog(avctx, "hti %d hbits %x token %d entry : %d size %d\n", + ff_dlog(avctx, "hti %d hbits %x token %d entry : %d size %d\n", s->hti, s->hbits, token, s->entries, s->huff_code_size); s->huffman_table[s->hti][token][0] = s->hbits; s->huffman_table[s->hti][token][1] = s->huff_code_size; @@ -2198,7 +2207,7 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) { Vp3DecodeContext *s = avctx->priv_data; int visible_width, visible_height, colorspace; - int offset_x = 0, offset_y = 0; + uint8_t offset_x = 0, offset_y = 0; int ret; AVRational fps, aspect; @@ -2226,6 +2235,17 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) offset_y = get_bits(gb, 8); /* offset y, from bottom */ } + /* sanity check */ + if (av_image_check_size(visible_width, visible_height, 0, avctx) < 0 || + visible_width + offset_x > s->width || + visible_height + offset_y > s->height) { + av_log(s, AV_LOG_ERROR, + "Invalid frame dimensions - w:%d h:%d x:%d y:%d (%dx%d).\n", + visible_width, visible_height, offset_x, offset_y, + s->width, s->height); + return AVERROR_INVALIDDATA; + } + fps.num = get_bits_long(gb, 32); fps.den = get_bits_long(gb, 32); if (fps.num && fps.den) { @@ -2233,7 +2253,7 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) av_log(avctx, AV_LOG_ERROR, "Invalid framerate\n"); return AVERROR_INVALIDDATA; } - av_reduce(&avctx->time_base.num, &avctx->time_base.den, + av_reduce(&avctx->framerate.den, &avctx->framerate.num, fps.den, fps.num, 1 << 30); } @@ -2259,16 +2279,25 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) skip_bits(gb, 3); /* reserved */ } -// align_get_bits(gb); - - if (visible_width <= s->width && visible_width > s->width - 16 && - visible_height <= s->height && visible_height > s->height - 16 && - !offset_x && (offset_y == s->height - visible_height)) - ret = ff_set_dimensions(avctx, visible_width, visible_height); - else - ret = ff_set_dimensions(avctx, s->width, s->height); + ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; + if (!(avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) && + (visible_width != s->width || visible_height != s->height)) { + avctx->width = visible_width; + avctx->height = visible_height; + // translate offsets from theora axis ([0,0] lower left) + // to normal axis ([0,0] upper left) + s->offset_x = offset_x; + s->offset_y = s->height - visible_height - offset_y; + + if ((s->offset_x & 0x1F) && !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { + s->offset_x &= ~0x1F; + av_log(avctx, AV_LOG_WARNING, "Reducing offset_x from %d to %d" + "chroma samples to preserve alignment.\n", + offset_x, s->offset_x); + } + } if (colorspace == 1) avctx->color_primaries = AVCOL_PRI_BT470M; @@ -2466,8 +2495,8 @@ AVCodec ff_theora_decoder = { .init = theora_decode_init, .close = vp3_decode_end, .decode = vp3_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context) @@ -2483,8 +2512,8 @@ AVCodec ff_vp3_decoder = { .init = vp3_decode_init, .close = vp3_decode_end, .decode = vp3_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | - CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), diff --git a/libavcodec/vp3data.h b/libavcodec/vp3data.h index da325c0..5603d3b 100644 --- a/libavcodec/vp3data.h +++ b/libavcodec/vp3data.h @@ -1,5 +1,5 @@ /* - * copyright (C) 2003 the ffmpeg project + * copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * diff --git a/libavcodec/vp3dsp.c b/libavcodec/vp3dsp.c index af687ec..459441e 100644 --- a/libavcodec/vp3dsp.c +++ b/libavcodec/vp3dsp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 the ffmpeg project + * Copyright (C) 2004 The FFmpeg project * * This file is part of Libav. * @@ -44,7 +44,7 @@ #define M(a, b) (((a) * (b)) >> 16) -static av_always_inline void idct(uint8_t *dst, int stride, +static av_always_inline void idct(uint8_t *dst, ptrdiff_t stride, int16_t *input, int type) { int16_t *ip = input; @@ -195,21 +195,21 @@ static av_always_inline void idct(uint8_t *dst, int stride, } } -static void vp3_idct_put_c(uint8_t *dest /* align 8 */, int line_size, +static void vp3_idct_put_c(uint8_t *dest /* align 8 */, ptrdiff_t stride, int16_t *block /* align 16 */) { - idct(dest, line_size, block, 1); + idct(dest, stride, block, 1); memset(block, 0, sizeof(*block) * 64); } -static void vp3_idct_add_c(uint8_t *dest /* align 8 */, int line_size, +static void vp3_idct_add_c(uint8_t *dest /* align 8 */, ptrdiff_t stride, int16_t *block /* align 16 */) { - idct(dest, line_size, block, 2); + idct(dest, stride, block, 2); memset(block, 0, sizeof(*block) * 64); } -static void vp3_idct_dc_add_c(uint8_t *dest /* align 8 */, int line_size, +static void vp3_idct_dc_add_c(uint8_t *dest /* align 8 */, ptrdiff_t stride, int16_t *block /* align 16 */) { int i, dc = (block[0] + 15) >> 5; @@ -223,17 +223,17 @@ static void vp3_idct_dc_add_c(uint8_t *dest /* align 8 */, int line_size, dest[5] = av_clip_uint8(dest[5] + dc); dest[6] = av_clip_uint8(dest[6] + dc); dest[7] = av_clip_uint8(dest[7] + dc); - dest += line_size; + dest += stride; } block[0] = 0; } -static void vp3_v_loop_filter_c(uint8_t *first_pixel, int stride, +static void vp3_v_loop_filter_c(uint8_t *first_pixel, ptrdiff_t stride, int *bounding_values) { unsigned char *end; int filter_value; - const int nstride = -stride; + const ptrdiff_t nstride = -stride; for (end = first_pixel + 8; first_pixel < end; first_pixel++) { filter_value = (first_pixel[2 * nstride] - first_pixel[stride]) + @@ -245,7 +245,7 @@ static void vp3_v_loop_filter_c(uint8_t *first_pixel, int stride, } } -static void vp3_h_loop_filter_c(uint8_t *first_pixel, int stride, +static void vp3_h_loop_filter_c(uint8_t *first_pixel, ptrdiff_t stride, int *bounding_values) { unsigned char *end; diff --git a/libavcodec/vp3dsp.h b/libavcodec/vp3dsp.h index 3099a7e..010f905 100644 --- a/libavcodec/vp3dsp.h +++ b/libavcodec/vp3dsp.h @@ -38,11 +38,11 @@ typedef struct VP3DSPContext { const uint8_t *b, ptrdiff_t stride, int h); - void (*idct_put)(uint8_t *dest, int line_size, int16_t *block); - void (*idct_add)(uint8_t *dest, int line_size, int16_t *block); - void (*idct_dc_add)(uint8_t *dest, int line_size, int16_t *block); - void (*v_loop_filter)(uint8_t *src, int stride, int *bounding_values); - void (*h_loop_filter)(uint8_t *src, int stride, int *bounding_values); + void (*idct_put)(uint8_t *dest, ptrdiff_t stride, int16_t *block); + void (*idct_add)(uint8_t *dest, ptrdiff_t stride, int16_t *block); + void (*idct_dc_add)(uint8_t *dest, ptrdiff_t stride, int16_t *block); + void (*v_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values); + void (*h_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values); } VP3DSPContext; void ff_vp3dsp_init(VP3DSPContext *c, int flags); diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index b609282..2d8ba1a 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -27,7 +27,6 @@ #include #include "avcodec.h" -#include "get_bits.h" #include "internal.h" #include "vp56.h" @@ -271,6 +270,7 @@ static av_cold int vp5_decode_init(AVCodecContext *avctx) if ((ret = ff_vp56_init(avctx, 1, 0)) < 0) return ret; + ff_vp5dsp_init(&s->vp56dsp); s->vp56_coord_div = vp5_coord_div; s->parse_vector_adjustment = vp5_parse_vector_adjustment; s->parse_coeff = vp5_parse_coeff; @@ -291,5 +291,5 @@ AVCodec ff_vp5_decoder = { .init = vp5_decode_init, .close = ff_vp56_free, .decode = ff_vp56_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index b9d3c87..39d82e9 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -473,7 +473,7 @@ static int vp56_size_changed(AVCodecContext *avctx) if (s->mb_width > 1000 || s->mb_height > 1000) { ff_set_dimensions(avctx, 0, 0); av_log(avctx, AV_LOG_ERROR, "picture too big\n"); - return -1; + return AVERROR_INVALIDDATA; } s->above_blocks = av_realloc(s->above_blocks, @@ -501,11 +501,11 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->has_alpha) { if (remaining_buf_size < 3) - return -1; + return AVERROR_INVALIDDATA; alpha_offset = bytestream_get_be24(&buf); remaining_buf_size -= 3; if (remaining_buf_size < alpha_offset) - return -1; + return AVERROR_INVALIDDATA; } for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) { @@ -530,20 +530,21 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, av_frame_unref(s->frames[i]); if (is_alpha) { ff_set_dimensions(avctx, 0, 0); - return -1; + return AVERROR_INVALIDDATA; } } if (!is_alpha) { - if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) { + int ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; + return ret; } if (res == VP56_SIZE_CHANGE) if (vp56_size_changed(avctx)) { av_frame_unref(p); - return -1; + return AVERROR_INVALIDDATA; } } @@ -662,7 +663,6 @@ av_cold int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha) ff_hpeldsp_init(&s->hdsp, avctx->flags); ff_videodsp_init(&s->vdsp, 8); ff_vp3dsp_init(&s->vp3dsp, avctx->flags); - ff_vp56dsp_init(&s->vp56dsp, avctx->codec->id); for (i = 0; i < 64; i++) { #define TRANSPOSE(x) (x >> 3) | ((x & 7) << 3) s->idct_scantable[i] = TRANSPOSE(ff_zigzag_direct[i]); diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h index a852ff8..8b7806e 100644 --- a/libavcodec/vp56.h +++ b/libavcodec/vp56.h @@ -26,6 +26,7 @@ #ifndef AVCODEC_VP56_H #define AVCODEC_VP56_H +#include "avcodec.h" #include "get_bits.h" #include "hpeldsp.h" #include "bytestream.h" @@ -72,7 +73,7 @@ typedef struct VP56mv { typedef void (*VP56ParseVectorAdjustment)(VP56Context *s, VP56mv *vect); typedef void (*VP56Filter)(VP56Context *s, uint8_t *dst, uint8_t *src, - int offset1, int offset2, int stride, + int offset1, int offset2, ptrdiff_t stride, VP56mv mv, int mask, int select, int luma); typedef void (*VP56ParseCoeff)(VP56Context *s); typedef void (*VP56DefaultModelsInit)(VP56Context *s); @@ -178,7 +179,7 @@ struct vp56_context { int flip; /* are we flipping ? */ int frbi; /* first row block index in MB */ int srbi; /* second row block index in MB */ - int stride[4]; /* stride for each plan */ + ptrdiff_t stride[4]; /* stride for each plan */ const uint8_t *vp56_coord_div; VP56ParseVectorAdjustment parse_vector_adjustment; @@ -299,7 +300,7 @@ static av_always_inline int vp8_rac_get(VP56RangeCoder *c) return vp56_rac_get_prob(c, 128); } -static av_unused int vp56_rac_gets(VP56RangeCoder *c, int bits) +static int vp56_rac_gets(VP56RangeCoder *c, int bits) { int value = 0; @@ -310,7 +311,7 @@ static av_unused int vp56_rac_gets(VP56RangeCoder *c, int bits) return value; } -static av_unused int vp8_rac_get_uint(VP56RangeCoder *c, int bits) +static int vp8_rac_get_uint(VP56RangeCoder *c, int bits) { int value = 0; diff --git a/libavcodec/vp56dsp.c b/libavcodec/vp56dsp.c index 5e09d24..fb3b37c 100644 --- a/libavcodec/vp56dsp.c +++ b/libavcodec/vp56dsp.c @@ -26,6 +26,23 @@ #include "vp56dsp.h" #include "libavutil/common.h" +#define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc) \ +static void pfx ## _edge_filter_ ## suf(uint8_t *yuv, ptrdiff_t stride, \ + int t) \ +{ \ + int pix2_inc = 2 * pix_inc; \ + int i, v; \ + \ + for (i=0; i<12; i++) { \ + v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\ + v = pfx##_adjust(v, t); \ + yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v); \ + yuv[0] = av_clip_uint8(yuv[0] - v); \ + yuv += line_inc; \ + } \ +} + +#if CONFIG_VP5_DECODER /* Gives very similar result than the vp6 version except in a few cases */ static int vp5_adjust(int v, int t) { @@ -43,6 +60,18 @@ static int vp5_adjust(int v, int t) return v; } + +VP56_EDGE_FILTER(vp5, hor, 1, stride) +VP56_EDGE_FILTER(vp5, ver, stride, 1) + +av_cold void ff_vp5dsp_init(VP56DSPContext *s) +{ + s->edge_filter_hor = vp5_edge_filter_hor; + s->edge_filter_ver = vp5_edge_filter_ver; +} +#endif /* CONFIG_VP5_DECODER */ + +#if CONFIG_VP6_DECODER static int vp6_adjust(int v, int t) { int V = v, s = v >> 31; @@ -56,43 +85,19 @@ static int vp6_adjust(int v, int t) return V; } - -#define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc) \ -static void pfx##_edge_filter_##suf(uint8_t *yuv, int stride, int t) \ -{ \ - int pix2_inc = 2 * pix_inc; \ - int i, v; \ - \ - for (i=0; i<12; i++) { \ - v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\ - v = pfx##_adjust(v, t); \ - yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v); \ - yuv[0] = av_clip_uint8(yuv[0] - v); \ - yuv += line_inc; \ - } \ -} - -VP56_EDGE_FILTER(vp5, hor, 1, stride) -VP56_EDGE_FILTER(vp5, ver, stride, 1) VP56_EDGE_FILTER(vp6, hor, 1, stride) VP56_EDGE_FILTER(vp6, ver, stride, 1) -av_cold void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec) +av_cold void ff_vp6dsp_init(VP56DSPContext *s) { - if (codec == AV_CODEC_ID_VP5) { - s->edge_filter_hor = vp5_edge_filter_hor; - s->edge_filter_ver = vp5_edge_filter_ver; - } else { - s->edge_filter_hor = vp6_edge_filter_hor; - s->edge_filter_ver = vp6_edge_filter_ver; + s->edge_filter_hor = vp6_edge_filter_hor; + s->edge_filter_ver = vp6_edge_filter_ver; - if (CONFIG_VP6_DECODER) { - s->vp6_filter_diag4 = ff_vp6_filter_diag4_c; + s->vp6_filter_diag4 = ff_vp6_filter_diag4_c; - if (ARCH_ARM) - ff_vp6dsp_init_arm(s, codec); - if (ARCH_X86) - ff_vp6dsp_init_x86(s, codec); - } - } + if (ARCH_ARM) + ff_vp6dsp_init_arm(s); + if (ARCH_X86) + ff_vp6dsp_init_x86(s); } +#endif /* CONFIG_VP6_DECODER */ diff --git a/libavcodec/vp56dsp.h b/libavcodec/vp56dsp.h index 389d359..8bf7a46 100644 --- a/libavcodec/vp56dsp.h +++ b/libavcodec/vp56dsp.h @@ -21,22 +21,24 @@ #ifndef AVCODEC_VP56DSP_H #define AVCODEC_VP56DSP_H +#include #include -#include "avcodec.h" typedef struct VP56DSPContext { - void (*edge_filter_hor)(uint8_t *yuv, int stride, int t); - void (*edge_filter_ver)(uint8_t *yuv, int stride, int t); + void (*edge_filter_hor)(uint8_t *yuv, ptrdiff_t stride, int t); + void (*edge_filter_ver)(uint8_t *yuv, ptrdiff_t stride, int t); - void (*vp6_filter_diag4)(uint8_t *dst, uint8_t *src, int stride, + void (*vp6_filter_diag4)(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights,const int16_t *v_weights); } VP56DSPContext; -void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, int stride, +void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights, const int16_t *v_weights); -void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec); -void ff_vp6dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec); -void ff_vp6dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec); +void ff_vp5dsp_init(VP56DSPContext *s); +void ff_vp6dsp_init(VP56DSPContext *s); + +void ff_vp6dsp_init_arm(VP56DSPContext *s); +void ff_vp6dsp_init_x86(VP56DSPContext *s); #endif /* AVCODEC_VP56DSP_H */ diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index d10a640..40948ad 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -252,7 +252,8 @@ static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], ff_free_vlc(vlc); /* then build the huffman tree according to probabilities */ - return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, + return ff_huff_build_tree(s->avctx, vlc, size, FF_HUFFMAN_BITS, + nodes, vp6_huff_cmp, FF_HUFFMAN_FLAG_HNODE_FIRST); } @@ -402,11 +403,11 @@ static void vp6_parse_coeff_huffman(VP56Context *s) } else { if (get_bits_left(&s->gb) <= 0) return; - coeff = get_vlc2(&s->gb, vlc_coeff->table, 9, 3); + coeff = get_vlc2(&s->gb, vlc_coeff->table, FF_HUFFMAN_BITS, 3); if (coeff == 0) { if (coeff_idx) { int pt = (coeff_idx >= 6); - run += get_vlc2(&s->gb, s->runv_vlc[pt].table, 9, 3); + run += get_vlc2(&s->gb, s->runv_vlc[pt].table, FF_HUFFMAN_BITS, 3); if (run >= 9) run += get_bits(&s->gb, 6); } else @@ -513,7 +514,7 @@ static void vp6_parse_coeff(VP56Context *s) } } -static int vp6_block_variance(uint8_t *src, int stride) +static int vp6_block_variance(uint8_t *src, ptrdiff_t stride) { int sum = 0, square_sum = 0; int y, x; @@ -528,7 +529,7 @@ static int vp6_block_variance(uint8_t *src, int stride) return (16*square_sum - sum*sum) >> 8; } -static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, int stride, +static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int delta, const int16_t *weights) { int x, y; @@ -546,7 +547,7 @@ static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, int stride, } static void vp6_filter_diag2(VP56Context *s, uint8_t *dst, uint8_t *src, - int stride, int h_weight, int v_weight) + ptrdiff_t stride, int h_weight, int v_weight) { uint8_t *tmp = s->edge_emu_buffer+16; s->h264chroma.put_h264_chroma_pixels_tab[0](tmp, src, stride, 9, h_weight, 0); @@ -554,7 +555,7 @@ static void vp6_filter_diag2(VP56Context *s, uint8_t *dst, uint8_t *src, } static void vp6_filter(VP56Context *s, uint8_t *dst, uint8_t *src, - int offset1, int offset2, int stride, + int offset1, int offset2, ptrdiff_t stride, VP56mv mv, int mask, int select, int luma) { int filter4 = 0; @@ -611,6 +612,7 @@ static av_cold int vp6_decode_init(AVCodecContext *avctx) if ((ret = ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6, avctx->codec->id == AV_CODEC_ID_VP6A)) < 0) return ret; + ff_vp6dsp_init(&s->vp56dsp); s->vp56_coord_div = vp6_coord_div; s->parse_vector_adjustment = vp6_parse_vector_adjustment; @@ -649,7 +651,7 @@ AVCodec ff_vp6_decoder = { .init = vp6_decode_init, .close = vp6_decode_free, .decode = ff_vp56_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; /* flash version, not flipped upside-down */ @@ -662,7 +664,7 @@ AVCodec ff_vp6f_decoder = { .init = vp6_decode_init, .close = vp6_decode_free, .decode = ff_vp56_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; /* flash version, not flipped upside-down, with alpha channel */ @@ -675,5 +677,5 @@ AVCodec ff_vp6a_decoder = { .init = vp6_decode_init, .close = vp6_decode_free, .decode = ff_vp56_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/vp6dsp.c b/libavcodec/vp6dsp.c index 54a96ed..c9968f2 100644 --- a/libavcodec/vp6dsp.c +++ b/libavcodec/vp6dsp.c @@ -27,7 +27,7 @@ #include "vp56dsp.h" -void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, int stride, +void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights, const int16_t *v_weights) { int x, y; diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 63c0ce7..546124c 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "internal.h" +#include "mathops.h" #include "rectangle.h" #include "thread.h" #include "vp8.h" @@ -168,19 +169,25 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7) s->top_border = av_mallocz((s->mb_width + 1) * sizeof(*s->top_border)); s->thread_data = av_mallocz(MAX_THREADS * sizeof(VP8ThreadData)); + if (!s->macroblocks_base || !s->top_nnz || !s->top_border || + !s->thread_data || (!s->intra4x4_pred_mode_top && !s->mb_layout)) { + free_buffers(s); + return AVERROR(ENOMEM); + } + for (i = 0; i < MAX_THREADS; i++) { s->thread_data[i].filter_strength = av_mallocz(s->mb_width * sizeof(*s->thread_data[0].filter_strength)); + if (!s->thread_data[i].filter_strength) { + free_buffers(s); + return AVERROR(ENOMEM); + } #if HAVE_THREADS pthread_mutex_init(&s->thread_data[i].lock, NULL); pthread_cond_init(&s->thread_data[i].cond, NULL); #endif } - if (!s->macroblocks_base || !s->top_nnz || !s->top_border || - (!s->intra4x4_pred_mode_top && !s->mb_layout)) - return AVERROR(ENOMEM); - s->macroblocks = s->macroblocks_base + 1; return 0; @@ -419,7 +426,7 @@ static void copy_luma(AVFrame *dst, AVFrame *src, int width, int height) } static void fade(uint8_t *dst, uint8_t *src, - int width, int height, int linesize, + int width, int height, ptrdiff_t linesize, int alpha, int beta) { int i, j; @@ -474,6 +481,10 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si int width = s->avctx->width; int height = s->avctx->height; + if (buf_size < 4) { + return AVERROR_INVALIDDATA; + } + s->profile = (buf[0] >> 1) & 7; if (s->profile > 1) { avpriv_request_sample(s->avctx, "Unknown profile %d", s->profile); @@ -487,6 +498,10 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si buf += 4 - s->profile; buf_size -= 4 - s->profile; + if (buf_size < part1_size) { + return AVERROR_INVALIDDATA; + } + memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab)); ff_vp56_init_range_decoder(c, buf, part1_size); @@ -513,7 +528,7 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si sizeof(vp7_mv_default_prob[i])); memset(&s->segmentation, 0, sizeof(s->segmentation)); memset(&s->lf_delta, 0, sizeof(s->lf_delta)); - memcpy(s->prob[0].scan, zigzag_scan, sizeof(s->prob[0].scan)); + memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan)); } if (s->keyframe || s->profile > 0) @@ -585,7 +600,7 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si /* G. DCT coefficient ordering specification */ if (vp8_rac_get(c)) for (i = 1; i < 16; i++) - s->prob[0].scan[i] = zigzag_scan[vp8_rac_get_uint(c, 4)]; + s->prob[0].scan[i] = ff_zigzag_scan[vp8_rac_get_uint(c, 4)]; /* H. Loop filter levels */ if (s->profile > 0) @@ -670,9 +685,10 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si buf_size -= header_size; if (s->keyframe) { - if (vp8_rac_get(c)) + s->colorspace = vp8_rac_get(c); + if (s->colorspace) av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n"); - vp8_rac_get(c); // whether we can skip clamping in dsp functions + s->fullrange = vp8_rac_get(c); } if ((s->segmentation.enabled = vp8_rac_get(c))) @@ -1115,10 +1131,10 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, uint8_t *segment, uint8_t *ref, int layout, int is_vp7) { VP56RangeCoder *c = &s->c; - const char *vp7_feature_name[] = { "q-index", - "lf-delta", - "partial-golden-update", - "blit-pitch" }; + static const char *vp7_feature_name[] = { "q-index", + "lf-delta", + "partial-golden-update", + "blit-pitch" }; if (is_vp7) { int i; *segment = 0; @@ -1302,7 +1318,7 @@ static int vp8_decode_block_coeffs_internal(VP56RangeCoder *r, int16_t qmul[2]) { return decode_block_coeffs_internal(r, block, probs, i, - token_prob, qmul, zigzag_scan, IS_VP8); + token_prob, qmul, ff_zigzag_scan, IS_VP8); } #endif @@ -1349,7 +1365,7 @@ void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, // decode DC values and do hadamard nnz = decode_block_coeffs(c, td->block_dc, s->prob->token[1], 0, nnz_pred, s->qmat[segment].luma_dc_qmul, - zigzag_scan, is_vp7); + ff_zigzag_scan, is_vp7); l_nnz[8] = t_nnz[8] = !!nnz; if (is_vp7 && mb->mode > MODE_I4x4) { @@ -1411,7 +1427,7 @@ void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c, static av_always_inline void backup_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, - int linesize, int uvlinesize, int simple) + ptrdiff_t linesize, ptrdiff_t uvlinesize, int simple) { AV_COPY128(top_border, src_y + 15 * linesize); if (!simple) { @@ -1422,7 +1438,7 @@ void backup_mb_border(uint8_t *top_border, uint8_t *src_y, static av_always_inline void xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, - uint8_t *src_cr, int linesize, int uvlinesize, int mb_x, + uint8_t *src_cr, ptrdiff_t linesize, ptrdiff_t uvlinesize, int mb_x, int mb_y, int mb_width, int simple, int xchg) { uint8_t *top_border_m1 = top_border - 32; // for TL prediction @@ -1575,7 +1591,8 @@ void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], for (y = 0; y < 4; y++) { uint8_t *topright = ptr + 4 - s->linesize; for (x = 0; x < 4; x++) { - int copy = 0, linesize = s->linesize; + int copy = 0; + ptrdiff_t linesize = s->linesize; uint8_t *dst = ptr + 4 * x; DECLARE_ALIGNED(4, uint8_t, copy_dst)[5 * 8]; @@ -1681,7 +1698,7 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, uint8_t *src = ref->f->data[0]; if (AV_RN32A(mv)) { - int src_linesize = linesize; + ptrdiff_t src_linesize = linesize; int mx = (mv->x << 1) & 7, mx_idx = subpel_idx[0][mx]; int my = (mv->y << 1) & 7, my_idx = subpel_idx[0][my]; @@ -2025,8 +2042,8 @@ void filter_mb(VP8Context *s, uint8_t *dst[3], VP8FilterStrength *f, int filter_level = f->filter_level; int inner_limit = f->inner_limit; int inner_filter = f->inner_filter; - int linesize = s->linesize; - int uvlinesize = s->uvlinesize; + ptrdiff_t linesize = s->linesize; + ptrdiff_t uvlinesize = s->uvlinesize; static const uint8_t hev_thresh_lut[2][64] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -2112,7 +2129,7 @@ void filter_mb_simple(VP8Context *s, uint8_t *dst, VP8FilterStrength *f, int filter_level = f->filter_level; int inner_limit = f->inner_limit; int inner_filter = f->inner_filter; - int linesize = s->linesize; + ptrdiff_t linesize = s->linesize; if (!filter_level) return; @@ -2490,6 +2507,13 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, curframe = s->framep[VP56_FRAME_CURRENT] = vp8_find_free_buffer(s); + if (!s->colorspace) + avctx->colorspace = AVCOL_SPC_BT470BG; + if (s->fullrange) + avctx->color_range = AVCOL_RANGE_JPEG; + else + avctx->color_range = AVCOL_RANGE_MPEG; + /* Given that arithmetic probabilities are updated every frame, it's quite * likely that the values we have on a random interframe are complete * junk if we didn't start decode on a keyframe. So just don't display @@ -2657,7 +2681,7 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7) } /* does not change for VP8 */ - memcpy(s->prob[0].scan, zigzag_scan, sizeof(s->prob[0].scan)); + memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan)); if ((ret = vp8_init_frames(s)) < 0) { ff_vp8_decode_free(avctx); @@ -2742,7 +2766,7 @@ AVCodec ff_vp7_decoder = { .init = vp7_decode_init, .close = ff_vp8_decode_free, .decode = vp7_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .flush = vp8_decode_flush, }; #endif /* CONFIG_VP7_DECODER */ @@ -2757,7 +2781,8 @@ AVCodec ff_vp8_decoder = { .init = ff_vp8_decode_init, .close = ff_vp8_decode_free, .decode = ff_vp8_decode_frame, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS, .flush = vp8_decode_flush, .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index 365e7b7..65948e1 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -143,8 +143,8 @@ typedef struct VP8Context { uint16_t mb_width; /* number of horizontal MB */ uint16_t mb_height; /* number of vertical MB */ - int linesize; - int uvlinesize; + ptrdiff_t linesize; + ptrdiff_t uvlinesize; uint8_t keyframe; uint8_t deblock_filter; @@ -223,7 +223,7 @@ typedef struct VP8Context { /** * These are all of the updatable probabilities for binary decisions. - * They are only implictly reset on keyframes, making it quite likely + * They are only implicitly reset on keyframes, making it quite likely * for an interframe to desync if a prior frame's header was corrupt * or missing outright! */ @@ -264,11 +264,14 @@ typedef struct VP8Context { vp8_mc_func put_pixels_tab[3][3][3]; VP8Frame frames[5]; + uint8_t colorspace; ///< 0 is the only value allowed (meaning bt601) + uint8_t fullrange; ///< whether we can skip clamping in dsp functions + int num_jobs; /** * This describes the macroblock memory layout. * 0 -> Only width+height*2+1 macroblocks allocated (frame/single thread). - * 1 -> Macroblocks for entire frame alloced (sliced thread). + * 1 -> Macroblocks for entire frame allocated (sliced thread). */ int mb_layout; diff --git a/libavcodec/vp8data.h b/libavcodec/vp8data.h index b49dea9..f8f9fff 100644 --- a/libavcodec/vp8data.h +++ b/libavcodec/vp8data.h @@ -708,14 +708,6 @@ static const uint8_t vp8_token_update_probs[4][8][3][NUM_DCT_TOKENS - 1] = { }, }; -// fixme: copied from h264data.h -static const uint8_t zigzag_scan[16]={ - 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4, - 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4, - 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4, - 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, -}; - static const uint8_t vp8_dc_qlookup[VP8_MAX_QUANT + 1] = { 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28, diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index 4864cf7..b248b86 100644 --- a/libavcodec/vp8dsp.h +++ b/libavcodec/vp8dsp.h @@ -70,12 +70,12 @@ typedef struct VP8DSPContext { void (*vp8_h_loop_filter_simple)(uint8_t *dst, ptrdiff_t stride, int flim); /** - * first dimension: width>>3, height is assumed equal to width + * first dimension: 4-log2(width) * second dimension: 0 if no vertical interpolation is needed; * 1 4-tap vertical interpolation filter (my & 1) * 2 6-tap vertical interpolation filter (!(my & 1)) * third dimension: same as second dimension, for horizontal interpolation - * so something like put_vp8_epel_pixels_tab[width>>3][2*!!my-(my&1)][2*!!mx-(mx&1)](..., mx, my) + * so something like put_vp8_epel_pixels_tab[4-log2(width)][2*!!my-(my&1)][2*!!mx-(mx&1)](..., mx, my) */ vp8_mc_func put_vp8_epel_pixels_tab[3][3][3]; vp8_mc_func put_vp8_bilinear_pixels_tab[3][3][3]; diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 2a6a138..32d995f 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -34,21 +34,91 @@ #define VP9_SYNCCODE 0x498342 #define MAX_PROB 255 +static void vp9_frame_unref(AVCodecContext *avctx, VP9Frame *f) +{ + ff_thread_release_buffer(avctx, &f->tf); + av_buffer_unref(&f->segmentation_map_buf); + av_buffer_unref(&f->mv_buf); + f->segmentation_map = NULL; + f->mv = NULL; +} + +static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f) +{ + VP9Context *s = avctx->priv_data; + int ret, sz; + + ret = ff_thread_get_buffer(avctx, &f->tf, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) + return ret; + + sz = 64 * s->sb_cols * s->sb_rows; + f->segmentation_map_buf = av_buffer_allocz(sz * sizeof(*f->segmentation_map)); + f->mv_buf = av_buffer_allocz(sz * sizeof(*f->mv)); + if (!f->segmentation_map_buf || !f->mv_buf) { + vp9_frame_unref(avctx, f); + return AVERROR(ENOMEM); + } + + f->segmentation_map = f->segmentation_map_buf->data; + f->mv = (VP9MVRefPair*)f->mv_buf->data; + + if (s->segmentation.enabled && !s->segmentation.update_map && + !s->keyframe && !s->intraonly) + memcpy(f->segmentation_map, s->frames[LAST_FRAME].segmentation_map, sz); + + return 0; +} + +static int vp9_frame_ref(VP9Frame *dst, VP9Frame *src) +{ + int ret; + + dst->segmentation_map_buf = av_buffer_ref(src->segmentation_map_buf); + dst->mv_buf = av_buffer_ref(src->mv_buf); + if (!dst->segmentation_map_buf || !dst->mv_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + dst->segmentation_map = src->segmentation_map; + dst->mv = src->mv; + + return 0; +fail: + av_buffer_unref(&dst->segmentation_map_buf); + av_buffer_unref(&dst->mv_buf); + return ret; +} + static void vp9_decode_flush(AVCodecContext *avctx) { VP9Context *s = avctx->priv_data; int i; + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) + vp9_frame_unref(avctx, &s->frames[i]); + for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) - av_frame_unref(s->refs[i]); + ff_thread_release_buffer(avctx, &s->refs[i]); + + s->use_last_frame_mvs = 0; + + s->alloc_width = 0; + s->alloc_height = 0; } static int update_size(AVCodecContext *avctx, int w, int h) { VP9Context *s = avctx->priv_data; uint8_t *p; + int nb_blocks, nb_superblocks; - if (s->above_partition_ctx && w == avctx->width && h == avctx->height) + if (s->above_partition_ctx && w == s->alloc_width && h == s->alloc_height) return 0; vp9_decode_flush(avctx); @@ -66,8 +136,7 @@ static int update_size(AVCodecContext *avctx, int w, int h) #define assign(var, type, n) var = (type)p; p += s->sb_cols * n * sizeof(*var) av_free(s->above_partition_ctx); p = av_malloc(s->sb_cols * - (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx) + - 64 * s->sb_rows * (1 + sizeof(*s->mv[0]) * 2))); + (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx))); if (!p) return AVERROR(ENOMEM); assign(s->above_partition_ctx, uint8_t *, 8); @@ -87,11 +156,31 @@ static int update_size(AVCodecContext *avctx, int w, int h) assign(s->above_filter_ctx, uint8_t *, 8); assign(s->lflvl, VP9Filter *, 1); assign(s->above_mv_ctx, VP56mv(*)[2], 16); - assign(s->segmentation_map, uint8_t *, 64 * s->sb_rows); - assign(s->mv[0], VP9MVRefPair *, 64 * s->sb_rows); - assign(s->mv[1], VP9MVRefPair *, 64 * s->sb_rows); #undef assign + av_freep(&s->b_base); + av_freep(&s->block_base); + + if (avctx->active_thread_type & FF_THREAD_FRAME) { + nb_blocks = s->cols * s->rows; + nb_superblocks = s->sb_cols * s->sb_rows; + } else { + nb_blocks = nb_superblocks = 1; + } + + s->b_base = av_malloc_array(nb_blocks, sizeof(*s->b_base)); + s->block_base = av_mallocz_array(nb_superblocks, (64 * 64 + 128) * 3); + if (!s->b_base || !s->block_base) + return AVERROR(ENOMEM); + s->uvblock_base[0] = s->block_base + nb_superblocks * 64 * 64; + s->uvblock_base[1] = s->uvblock_base[0] + nb_superblocks * 32 * 32; + s->eob_base = (uint8_t *)(s->uvblock_base[1] + nb_superblocks * 32 * 32); + s->uveob_base[0] = s->eob_base + nb_superblocks * 256; + s->uveob_base[1] = s->uveob_base[0] + nb_superblocks * 64; + + s->alloc_width = w; + s->alloc_height = h; + return 0; } @@ -205,7 +294,6 @@ static int decode_frame_header(AVCodecContext *avctx, last_invisible = s->invisible; s->invisible = !get_bits1(&s->gb); s->errorres = get_bits1(&s->gb); - // FIXME disable this upon resolution change s->use_last_frame_mvs = !s->errorres && !last_invisible; if (s->keyframe) { @@ -219,7 +307,29 @@ static int decode_frame_header(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } s->fullrange = get_bits1(&s->gb); - // for profile 1, here follows the subsampling bits + + // subsampling bits + if (s->profile == 1 || s->profile == 3) { + s->sub_x = get_bits1(&s->gb); + s->sub_y = get_bits1(&s->gb); + if (s->sub_x && s->sub_y) { + av_log(avctx, AV_LOG_ERROR, + "4:2:0 color not supported in profile 1 or 3\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(&s->gb)) { // reserved bit + av_log(avctx, AV_LOG_ERROR, "Reserved bit should be zero\n"); + return AVERROR_INVALIDDATA; + } + } else { + s->sub_x = s->sub_y = 1; + } + if (!s->sub_x || !s->sub_y) { + avpriv_report_missing_feature(avctx, "Subsampling %d:%d", + s->sub_x, s->sub_y); + return AVERROR_PATCHWELCOME; + } + s->refreshrefmask = 0xff; w = get_bits(&s->gb, 16) + 1; h = get_bits(&s->gb, 16) + 1; @@ -246,22 +356,22 @@ static int decode_frame_header(AVCodecContext *avctx, s->signbias[1] = get_bits1(&s->gb); s->refidx[2] = get_bits(&s->gb, 3); s->signbias[2] = get_bits1(&s->gb); - if (!s->refs[s->refidx[0]]->buf[0] || - !s->refs[s->refidx[1]]->buf[0] || - !s->refs[s->refidx[2]]->buf[0]) { + if (!s->refs[s->refidx[0]].f->buf[0] || + !s->refs[s->refidx[1]].f->buf[0] || + !s->refs[s->refidx[2]].f->buf[0]) { av_log(avctx, AV_LOG_ERROR, "Not all references are available\n"); return AVERROR_INVALIDDATA; } if (get_bits1(&s->gb)) { - w = s->refs[s->refidx[0]]->width; - h = s->refs[s->refidx[0]]->height; + w = s->refs[s->refidx[0]].f->width; + h = s->refs[s->refidx[0]].f->height; } else if (get_bits1(&s->gb)) { - w = s->refs[s->refidx[1]]->width; - h = s->refs[s->refidx[1]]->height; + w = s->refs[s->refidx[1]].f->width; + h = s->refs[s->refidx[1]].f->height; } else if (get_bits1(&s->gb)) { - w = s->refs[s->refidx[2]]->width; - h = s->refs[s->refidx[2]]->height; + w = s->refs[s->refidx[2]].f->width; + h = s->refs[s->refidx[2]].f->height; } else { w = get_bits(&s->gb, 16) + 1; h = get_bits(&s->gb, 16) + 1; @@ -657,6 +767,7 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col, ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl) { VP9Context *s = avctx->priv_data; + AVFrame *f = s->frames[CUR_FRAME].tf.f; int c = ((s->above_partition_ctx[col] >> (3 - bl)) & 1) | (((s->left_partition_ctx[row & 0x7] >> (3 - bl)) & 1) << 1); int ret; @@ -680,8 +791,8 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col, ret = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, bl, bp); if (!ret) { - yoff += hbs * 8 * s->cur_frame->linesize[0]; - uvoff += hbs * 4 * s->cur_frame->linesize[1]; + yoff += hbs * 8 * f->linesize[0]; + uvoff += hbs * 4 * f->linesize[1]; ret = ff_vp9_decode_block(avctx, row + hbs, col, lflvl, yoff, uvoff, bl, bp); } @@ -704,8 +815,8 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col, yoff + 8 * hbs, uvoff + 4 * hbs, bl + 1); if (!ret) { - yoff += hbs * 8 * s->cur_frame->linesize[0]; - uvoff += hbs * 4 * s->cur_frame->linesize[1]; + yoff += hbs * 8 * f->linesize[0]; + uvoff += hbs * 4 * f->linesize[1]; ret = decode_subblock(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1); if (!ret) { @@ -736,8 +847,8 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col, bp = PARTITION_SPLIT; ret = decode_subblock(avctx, row, col, lflvl, yoff, uvoff, bl + 1); if (!ret) { - yoff += hbs * 8 * s->cur_frame->linesize[0]; - uvoff += hbs * 4 * s->cur_frame->linesize[1]; + yoff += hbs * 8 * f->linesize[0]; + uvoff += hbs * 4 * f->linesize[1]; ret = decode_subblock(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1); } @@ -755,13 +866,70 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col, return ret; } +static int decode_superblock_mem(AVCodecContext *avctx, int row, int col, struct VP9Filter *lflvl, + ptrdiff_t yoff, ptrdiff_t uvoff, enum BlockLevel bl) +{ + VP9Context *s = avctx->priv_data; + VP9Block *b = s->b; + ptrdiff_t hbs = 4 >> bl; + AVFrame *f = s->frames[CUR_FRAME].tf.f; + ptrdiff_t y_stride = f->linesize[0], uv_stride = f->linesize[1]; + int res; + + if (bl == BL_8X8) { + av_assert2(b->bl == BL_8X8); + res = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp); + } else if (s->b->bl == bl) { + if ((res = ff_vp9_decode_block(avctx, row, col, lflvl, yoff, uvoff, b->bl, b->bp)) < 0) + return res; + if (b->bp == PARTITION_H && row + hbs < s->rows) { + yoff += hbs * 8 * y_stride; + uvoff += hbs * 4 * uv_stride; + res = ff_vp9_decode_block(avctx, row + hbs, col, lflvl, yoff, uvoff, b->bl, b->bp); + } else if (b->bp == PARTITION_V && col + hbs < s->cols) { + yoff += hbs * 8; + uvoff += hbs * 4; + res = ff_vp9_decode_block(avctx, row, col + hbs, lflvl, yoff, uvoff, b->bl, b->bp); + } + } else { + if ((res = decode_superblock_mem(avctx, row, col, lflvl, yoff, uvoff, bl + 1)) < 0) + return res; + if (col + hbs < s->cols) { // FIXME why not <=? + if (row + hbs < s->rows) { + if ((res = decode_superblock_mem(avctx, row, col + hbs, lflvl, yoff + 8 * hbs, + uvoff + 4 * hbs, bl + 1)) < 0) + return res; + yoff += hbs * 8 * y_stride; + uvoff += hbs * 4 * uv_stride; + if ((res = decode_superblock_mem(avctx, row + hbs, col, lflvl, yoff, + uvoff, bl + 1)) < 0) + return res; + res = decode_superblock_mem(avctx, row + hbs, col + hbs, lflvl, + yoff + 8 * hbs, uvoff + 4 * hbs, bl + 1); + } else { + yoff += hbs * 8; + uvoff += hbs * 4; + res = decode_superblock_mem(avctx, row, col + hbs, lflvl, yoff, uvoff, bl + 1); + } + } else if (row + hbs < s->rows) { + yoff += hbs * 8 * y_stride; + uvoff += hbs * 4 * uv_stride; + res = decode_superblock_mem(avctx, row + hbs, col, lflvl, yoff, uvoff, bl + 1); + } + } + + return res; +} + static void loopfilter_subblock(AVCodecContext *avctx, VP9Filter *lflvl, int row, int col, ptrdiff_t yoff, ptrdiff_t uvoff) { VP9Context *s = avctx->priv_data; - uint8_t *dst = s->cur_frame->data[0] + yoff, *lvl = lflvl->level; - ptrdiff_t ls_y = s->cur_frame->linesize[0], ls_uv = s->cur_frame->linesize[1]; + AVFrame *f = s->frames[CUR_FRAME].tf.f; + uint8_t *dst = f->data[0] + yoff; + ptrdiff_t ls_y = f->linesize[0], ls_uv = f->linesize[1]; + uint8_t *lvl = lflvl->level; int y, x, p; /* FIXME: In how far can we interleave the v/h loopfilter calls? E.g. @@ -838,7 +1006,7 @@ static void loopfilter_subblock(AVCodecContext *avctx, VP9Filter *lflvl, // block1 // filter edges between rows, Y plane (e.g. ------) // block2 - dst = s->cur_frame->data[0] + yoff; + dst = f->data[0] + yoff; lvl = lflvl->level; for (y = 0; y < 8; y++, dst += 8 * ls_y, lvl += 8) { uint8_t *ptr = dst, *l = lvl, *vmask = lflvl->mask[0][1][y]; @@ -902,7 +1070,7 @@ static void loopfilter_subblock(AVCodecContext *avctx, VP9Filter *lflvl, // same principle but for U/V planes for (p = 0; p < 2; p++) { lvl = lflvl->level; - dst = s->cur_frame->data[1 + p] + uvoff; + dst = f->data[1 + p] + uvoff; for (y = 0; y < 8; y += 4, dst += 16 * ls_uv, lvl += 32) { uint8_t *ptr = dst, *l = lvl, *hmask1 = lflvl->mask[1][0][y]; uint8_t *hmask2 = lflvl->mask[1][0][y + 2]; @@ -949,7 +1117,7 @@ static void loopfilter_subblock(AVCodecContext *avctx, VP9Filter *lflvl, } } lvl = lflvl->level; - dst = s->cur_frame->data[1 + p] + uvoff; + dst = f->data[1 + p] + uvoff; for (y = 0; y < 8; y++, dst += 4 * ls_uv) { uint8_t *ptr = dst, *l = lvl, *vmask = lflvl->mask[1][1][y]; unsigned vm = vmask[0] | vmask[1] | vmask[2]; @@ -1004,24 +1172,41 @@ static void set_tile_offset(int *start, int *end, int idx, int log2_n, int n) *end = FFMIN(sb_end, n) << 3; } +static int update_refs(AVCodecContext *avctx) +{ + VP9Context *s = avctx->priv_data; + int i, ret; + + for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) + if (s->refreshrefmask & (1 << i)) { + ff_thread_release_buffer(avctx, &s->refs[i]); + ret = ff_thread_ref_frame(&s->refs[i], &s->frames[CUR_FRAME].tf); + if (ret < 0) + return ret; + } + + return 0; +} + static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, - int *got_frame, const uint8_t *data, int size) + int *got_frame, const uint8_t *data, int size, + int can_finish_setup) { VP9Context *s = avctx->priv_data; + AVFrame *f; int ret, tile_row, tile_col, i, ref = -1, row, col; - ptrdiff_t yoff = 0, uvoff = 0; ret = decode_frame_header(avctx, data, size, &ref); if (ret < 0) { return ret; } else if (!ret) { - if (!s->refs[ref]->buf[0]) { + if (!s->refs[ref].f->buf[0]) { av_log(avctx, AV_LOG_ERROR, "Requested reference %d not available\n", ref); return AVERROR_INVALIDDATA; } - ret = av_frame_ref(frame, s->refs[ref]); + ret = av_frame_ref(frame, s->refs[ref].f); if (ret < 0) return ret; *got_frame = 1; @@ -1030,15 +1215,56 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, data += ret; size -= ret; - s->cur_frame = frame; + vp9_frame_unref(avctx, &s->frames[LAST_FRAME]); + if (!s->keyframe && s->frames[CUR_FRAME].tf.f->buf[0]) { + ret = vp9_frame_ref(&s->frames[LAST_FRAME], &s->frames[CUR_FRAME]); + if (ret < 0) + return ret; + } - av_frame_unref(s->cur_frame); - if ((ret = ff_get_buffer(avctx, s->cur_frame, - s->refreshrefmask ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) + vp9_frame_unref(avctx, &s->frames[CUR_FRAME]); + ret = vp9_frame_alloc(avctx, &s->frames[CUR_FRAME]); + if (ret < 0) return ret; - s->cur_frame->key_frame = s->keyframe; - s->cur_frame->pict_type = s->keyframe ? AV_PICTURE_TYPE_I - : AV_PICTURE_TYPE_P; + + f = s->frames[CUR_FRAME].tf.f; + f->key_frame = s->keyframe; + f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if (s->fullrange) + avctx->color_range = AVCOL_RANGE_JPEG; + else + avctx->color_range = AVCOL_RANGE_MPEG; + + switch (s->colorspace) { + case 1: avctx->colorspace = AVCOL_SPC_BT470BG; break; + case 2: avctx->colorspace = AVCOL_SPC_BT709; break; + case 3: avctx->colorspace = AVCOL_SPC_SMPTE170M; break; + case 4: avctx->colorspace = AVCOL_SPC_SMPTE240M; break; + } + + s->pass = s->uses_2pass = + avctx->active_thread_type & FF_THREAD_FRAME && s->refreshctx && !s->parallelmode; + + if (s->refreshctx && s->parallelmode) { + int j, k, l, m; + for (i = 0; i < 4; i++) { + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) + memcpy(s->prob_ctx[s->framectxid].coef[i][j][k][l][m], + s->prob.coef[i][j][k][l][m], 3); + if (s->txfmmode == i) + break; + } + s->prob_ctx[s->framectxid].p = s->prob.p; + } + if ((s->parallelmode || !s->refreshctx) && + can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) { + ff_thread_finish_setup(avctx); + s->setup_finished = 1; + } // main tile decode loop memset(s->above_partition_ctx, 0, s->cols); @@ -1051,130 +1277,156 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, memset(s->above_uv_nnz_ctx[0], 0, s->sb_cols * 8); memset(s->above_uv_nnz_ctx[1], 0, s->sb_cols * 8); memset(s->above_segpred_ctx, 0, s->cols); - for (tile_row = 0; tile_row < s->tiling.tile_rows; tile_row++) { - set_tile_offset(&s->tiling.tile_row_start, &s->tiling.tile_row_end, - tile_row, s->tiling.log2_tile_rows, s->sb_rows); - for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) { - int64_t tile_size; - - if (tile_col == s->tiling.tile_cols - 1 && - tile_row == s->tiling.tile_rows - 1) { - tile_size = size; - } else { - tile_size = AV_RB32(data); - data += 4; - size -= 4; - } - if (tile_size > size) - return AVERROR_INVALIDDATA; - ff_vp56_init_range_decoder(&s->c_b[tile_col], data, tile_size); - if (vp56_rac_get_prob_branchy(&s->c_b[tile_col], 128)) // marker bit - return AVERROR_INVALIDDATA; - data += tile_size; - size -= tile_size; - } - for (row = s->tiling.tile_row_start; - row < s->tiling.tile_row_end; - row += 8, yoff += s->cur_frame->linesize[0] * 64, - uvoff += s->cur_frame->linesize[1] * 32) { - VP9Filter *lflvl = s->lflvl; - ptrdiff_t yoff2 = yoff, uvoff2 = uvoff; - - for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) { - set_tile_offset(&s->tiling.tile_col_start, - &s->tiling.tile_col_end, - tile_col, s->tiling.log2_tile_cols, s->sb_cols); - - memset(s->left_partition_ctx, 0, 8); - memset(s->left_skip_ctx, 0, 8); - if (s->keyframe || s->intraonly) - memset(s->left_mode_ctx, DC_PRED, 16); - else - memset(s->left_mode_ctx, NEARESTMV, 8); - memset(s->left_y_nnz_ctx, 0, 16); - memset(s->left_uv_nnz_ctx, 0, 16); - memset(s->left_segpred_ctx, 0, 8); - - memcpy(&s->c, &s->c_b[tile_col], sizeof(s->c)); - for (col = s->tiling.tile_col_start; - col < s->tiling.tile_col_end; - col += 8, yoff2 += 64, uvoff2 += 32, lflvl++) { - // FIXME integrate with lf code (i.e. zero after each - // use, similar to invtxfm coefficients, or similar) - memset(lflvl->mask, 0, sizeof(lflvl->mask)); - - if ((ret = decode_subblock(avctx, row, col, lflvl, - yoff2, uvoff2, BL_64X64)) < 0) - return ret; + do { + ptrdiff_t yoff = 0, uvoff = 0; + s->b = s->b_base; + s->block = s->block_base; + s->uvblock[0] = s->uvblock_base[0]; + s->uvblock[1] = s->uvblock_base[1]; + s->eob = s->eob_base; + s->uveob[0] = s->uveob_base[0]; + s->uveob[1] = s->uveob_base[1]; + + for (tile_row = 0; tile_row < s->tiling.tile_rows; tile_row++) { + set_tile_offset(&s->tiling.tile_row_start, &s->tiling.tile_row_end, + tile_row, s->tiling.log2_tile_rows, s->sb_rows); + + if (s->pass != 2) { + for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) { + int64_t tile_size; + + if (tile_col == s->tiling.tile_cols - 1 && + tile_row == s->tiling.tile_rows - 1) { + tile_size = size; + } else { + tile_size = AV_RB32(data); + data += 4; + size -= 4; + } + if (tile_size > size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ff_vp56_init_range_decoder(&s->c_b[tile_col], data, tile_size); + if (vp56_rac_get_prob_branchy(&s->c_b[tile_col], 128)) { // marker bit + ret = AVERROR_INVALIDDATA; + goto fail; + } + data += tile_size; + size -= tile_size; } - memcpy(&s->c_b[tile_col], &s->c, sizeof(s->c)); } - // backup pre-loopfilter reconstruction data for intra - // prediction of next row of sb64s - if (row + 8 < s->rows) { - memcpy(s->intra_pred_data[0], - s->cur_frame->data[0] + yoff + - 63 * s->cur_frame->linesize[0], - 8 * s->cols); - memcpy(s->intra_pred_data[1], - s->cur_frame->data[1] + uvoff + - 31 * s->cur_frame->linesize[1], - 4 * s->cols); - memcpy(s->intra_pred_data[2], - s->cur_frame->data[2] + uvoff + - 31 * s->cur_frame->linesize[2], - 4 * s->cols); - } + for (row = s->tiling.tile_row_start; + row < s->tiling.tile_row_end; + row += 8, yoff += f->linesize[0] * 64, + uvoff += f->linesize[1] * 32) { + VP9Filter *lflvl = s->lflvl; + ptrdiff_t yoff2 = yoff, uvoff2 = uvoff; + + for (tile_col = 0; tile_col < s->tiling.tile_cols; tile_col++) { + set_tile_offset(&s->tiling.tile_col_start, + &s->tiling.tile_col_end, + tile_col, s->tiling.log2_tile_cols, s->sb_cols); + + memset(s->left_partition_ctx, 0, 8); + memset(s->left_skip_ctx, 0, 8); + if (s->keyframe || s->intraonly) + memset(s->left_mode_ctx, DC_PRED, 16); + else + memset(s->left_mode_ctx, NEARESTMV, 8); + memset(s->left_y_nnz_ctx, 0, 16); + memset(s->left_uv_nnz_ctx, 0, 16); + memset(s->left_segpred_ctx, 0, 8); + + memcpy(&s->c, &s->c_b[tile_col], sizeof(s->c)); + for (col = s->tiling.tile_col_start; + col < s->tiling.tile_col_end; + col += 8, yoff2 += 64, uvoff2 += 32, lflvl++) { + // FIXME integrate with lf code (i.e. zero after each + // use, similar to invtxfm coefficients, or similar) + if (s->pass != 1) + memset(lflvl->mask, 0, sizeof(lflvl->mask)); + + if (s->pass == 2) { + ret = decode_superblock_mem(avctx, row, col, lflvl, + yoff2, uvoff2, BL_64X64); + } else { + ret = decode_subblock(avctx, row, col, lflvl, + yoff2, uvoff2, BL_64X64); + } + if (ret < 0) + goto fail; + } + if (s->pass != 2) + memcpy(&s->c_b[tile_col], &s->c, sizeof(s->c)); + } - // loopfilter one row - if (s->filter.level) { - yoff2 = yoff; - uvoff2 = uvoff; - lflvl = s->lflvl; - for (col = 0; col < s->cols; - col += 8, yoff2 += 64, uvoff2 += 32, lflvl++) - loopfilter_subblock(avctx, lflvl, row, col, yoff2, uvoff2); + if (s->pass == 1) + continue; + + // backup pre-loopfilter reconstruction data for intra + // prediction of next row of sb64s + if (row + 8 < s->rows) { + memcpy(s->intra_pred_data[0], + f->data[0] + yoff + + 63 * f->linesize[0], + 8 * s->cols); + memcpy(s->intra_pred_data[1], + f->data[1] + uvoff + + 31 * f->linesize[1], + 4 * s->cols); + memcpy(s->intra_pred_data[2], + f->data[2] + uvoff + + 31 * f->linesize[2], + 4 * s->cols); + } + + // loopfilter one row + if (s->filter.level) { + yoff2 = yoff; + uvoff2 = uvoff; + lflvl = s->lflvl; + for (col = 0; col < s->cols; + col += 8, yoff2 += 64, uvoff2 += 32, lflvl++) + loopfilter_subblock(avctx, lflvl, row, col, yoff2, uvoff2); + } + + // FIXME maybe we can make this more finegrained by running the + // loopfilter per-block instead of after each sbrow + // In fact that would also make intra pred left preparation easier? + ff_thread_report_progress(&s->frames[CUR_FRAME].tf, row >> 3, 0); } } - } - // bw adaptivity (or in case of parallel decoding mode, fw adaptivity - // probability maintenance between frames) - if (s->refreshctx) { - if (s->parallelmode) { - int j, k, l, m; - for (i = 0; i < 4; i++) { - for (j = 0; j < 2; j++) - for (k = 0; k < 2; k++) - for (l = 0; l < 6; l++) - for (m = 0; m < 6; m++) - memcpy(s->prob_ctx[s->framectxid].coef[i][j][k][l][m], - s->prob.coef[i][j][k][l][m], 3); - if (s->txfmmode == i) - break; - } - s->prob_ctx[s->framectxid].p = s->prob.p; - } else { + if (s->pass < 2 && s->refreshctx && !s->parallelmode) { ff_vp9_adapt_probs(s); + if (can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) { + ff_thread_finish_setup(avctx); + s->setup_finished = 1; + } } - } - FFSWAP(VP9MVRefPair *, s->mv[0], s->mv[1]); + } while (s->pass++ == 1); +fail: + ff_thread_report_progress(&s->frames[CUR_FRAME].tf, INT_MAX, 0); + if (ret < 0) + return ret; // ref frame setup - for (i = 0; i < 8; i++) - if (s->refreshrefmask & (1 << i)) { - av_frame_unref(s->refs[i]); - ret = av_frame_ref(s->refs[i], s->cur_frame); - if (ret < 0) - return ret; - } + if (!s->setup_finished) { + ret = update_refs(avctx); + if (ret < 0) + return ret; + } - if (s->invisible) - av_frame_unref(s->cur_frame); - else + if (!s->invisible) { + av_frame_unref(frame); + ret = av_frame_ref(frame, s->frames[CUR_FRAME].tf.f); + if (ret < 0) + return ret; *got_frame = 1; + } return 0; } @@ -1182,10 +1434,13 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, static int vp9_decode_packet(AVCodecContext *avctx, void *frame, int *got_frame, AVPacket *avpkt) { + VP9Context *s = avctx->priv_data; const uint8_t *data = avpkt->data; int size = avpkt->size; int marker, ret; + s->setup_finished = 0; + /* Read superframe index - this is a collection of individual frames * that together lead to one visible frame */ marker = data[size - 1]; @@ -1211,19 +1466,20 @@ static int vp9_decode_packet(AVCodecContext *avctx, void *frame, return AVERROR_INVALIDDATA; } - ret = vp9_decode_frame(avctx, frame, got_frame, data, sz); + ret = vp9_decode_frame(avctx, frame, got_frame, data, sz, + !n_frames); if (ret < 0) return ret; data += sz; size -= sz; } - return size; + return avpkt->size; } } /* If we get here, there was no valid superframe index, i.e. this is just * one whole single frame. Decode it as such from the complete input buf. */ - if ((ret = vp9_decode_frame(avctx, frame, got_frame, data, size)) < 0) + if ((ret = vp9_decode_frame(avctx, frame, got_frame, data, size, 1)) < 0) return ret; return size; } @@ -1233,11 +1489,20 @@ static av_cold int vp9_decode_free(AVCodecContext *avctx) VP9Context *s = avctx->priv_data; int i; - for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) - av_frame_free(&s->refs[i]); + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { + vp9_frame_unref(avctx, &s->frames[i]); + av_frame_free(&s->frames[i].tf.f); + } + + for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) { + ff_thread_release_buffer(avctx, &s->refs[i]); + av_frame_free(&s->refs[i].f); + } av_freep(&s->c_b); av_freep(&s->above_partition_ctx); + av_freep(&s->b_base); + av_freep(&s->block_base); return 0; } @@ -1247,33 +1512,88 @@ static av_cold int vp9_decode_init(AVCodecContext *avctx) VP9Context *s = avctx->priv_data; int i; + memset(s, 0, sizeof(*s)); + + avctx->internal->allocate_progress = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; ff_vp9dsp_init(&s->dsp); ff_videodsp_init(&s->vdsp, 8); + s->frames[0].tf.f = av_frame_alloc(); + s->frames[1].tf.f = av_frame_alloc(); + if (!s->frames[0].tf.f || !s->frames[1].tf.f) + goto fail; + for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) { - s->refs[i] = av_frame_alloc(); - if (!s->refs[i]) { - vp9_decode_free(avctx); - return AVERROR(ENOMEM); - } + s->refs[i].f = av_frame_alloc(); + if (!s->refs[i].f) + goto fail; } s->filter.sharpness = -1; return 0; +fail: + vp9_decode_free(avctx); + return AVERROR(ENOMEM); +} + +static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + VP9Context *s = dst->priv_data, *ssrc = src->priv_data; + int i, ret; + + ret = update_size(dst, ssrc->alloc_width, ssrc->alloc_height); + if (ret < 0) + return ret; + + for (i = 0; i < 2; i++) { + if (s->frames[i].tf.f->data[0]) + vp9_frame_unref(dst, &s->frames[i]); + if (ssrc->frames[i].tf.f->data[0]) { + if ((ret = vp9_frame_ref(&s->frames[i], &ssrc->frames[i])) < 0) + return ret; + } + } + for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++) { + ff_thread_release_buffer(dst, &s->refs[i]); + if (ssrc->refs[i].f->buf[0]) { + ret = ff_thread_ref_frame(&s->refs[i], &ssrc->refs[i]); + if (ret < 0) + return ret; + } + } + + s->refreshrefmask = ssrc->refreshrefmask; + ret = update_refs(dst); + if (ret < 0) + return ret; + + s->invisible = ssrc->invisible; + s->keyframe = ssrc->keyframe; + s->last_uses_2pass = ssrc->uses_2pass; + + memcpy(&s->prob_ctx, &ssrc->prob_ctx, sizeof(s->prob_ctx)); + memcpy(&s->lf_delta, &ssrc->lf_delta, sizeof(s->lf_delta)); + memcpy(&s->segmentation.feat, &ssrc->segmentation.feat, + sizeof(s->segmentation.feat)); + + return 0; } AVCodec ff_vp9_decoder = { - .name = "vp9", - .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, - .priv_data_size = sizeof(VP9Context), - .init = vp9_decode_init, - .decode = vp9_decode_packet, - .flush = vp9_decode_flush, - .close = vp9_decode_free, - .capabilities = CODEC_CAP_DR1, + .name = "vp9", + .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .priv_data_size = sizeof(VP9Context), + .init = vp9_decode_init, + .decode = vp9_decode_packet, + .flush = vp9_decode_flush, + .close = vp9_decode_free, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .init_thread_copy = vp9_decode_init, + .update_thread_context = vp9_decode_update_thread_context, }; diff --git a/libavcodec/vp9.h b/libavcodec/vp9.h index 0a6c6ee..25bb2d1 100644 --- a/libavcodec/vp9.h +++ b/libavcodec/vp9.h @@ -27,9 +27,11 @@ #include #include +#include "libavutil/buffer.h" #include "libavutil/internal.h" #include "avcodec.h" +#include "thread.h" #include "vp56.h" enum TxfmMode { @@ -141,7 +143,7 @@ typedef struct VP9DSPContext { */ // FIXME(rbultje) maybe replace left/top pointers with HAVE_TOP/ // HAVE_LEFT/HAVE_TOPRIGHT flags instead, and then handle it in-place? - // also needs to fit in with what h264/vp8/etc do + // also needs to fit in with what H.264/VP8/etc do void (*intra_pred[N_TXFM_SIZES][N_INTRA_PRED_MODES])(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, @@ -225,6 +227,16 @@ typedef struct VP9Filter { [8 /* rows */][4 /* 0=16, 1=8, 2=4, 3=inner4 */]; } VP9Filter; +typedef struct VP9Frame { + ThreadFrame tf; + + uint8_t *segmentation_map; + VP9MVRefPair *mv; + + AVBufferRef *segmentation_map_buf; + AVBufferRef *mv_buf; +} VP9Frame; + enum BlockLevel { BL_64X64, BL_32X32, @@ -259,6 +271,9 @@ typedef struct VP9Block { int row, row7, col, col7; uint8_t *dst[3]; ptrdiff_t y_stride, uv_stride; + + enum BlockLevel bl; + enum BlockPartition bp; } VP9Block; typedef struct VP9Context { @@ -268,7 +283,16 @@ typedef struct VP9Context { VP56RangeCoder c; VP56RangeCoder *c_b; unsigned c_b_size; - VP9Block b; + VP9Block *b; + VP9Block *b_base; + + int alloc_width; + int alloc_height; + + int pass; + int uses_2pass; + int last_uses_2pass; + int setup_finished; // bitstream header uint8_t profile; @@ -277,6 +301,8 @@ typedef struct VP9Context { uint8_t use_last_frame_mvs; uint8_t errorres; uint8_t colorspace; + uint8_t sub_x; + uint8_t sub_y; uint8_t fullrange; uint8_t intraonly; uint8_t resetctx; @@ -291,8 +317,12 @@ typedef struct VP9Context { uint8_t refidx[3]; uint8_t signbias[3]; uint8_t varcompref[2]; - AVFrame *refs[8]; - AVFrame *cur_frame; + + ThreadFrame refs[8]; + +#define CUR_FRAME 0 +#define LAST_FRAME 1 + VP9Frame frames[2]; struct { uint8_t level; @@ -313,6 +343,7 @@ typedef struct VP9Context { uint8_t temporal; uint8_t absolute_vals; uint8_t update_map; + #define MAX_SEGMENT 8 struct { uint8_t q_enabled; uint8_t lf_enabled; @@ -323,7 +354,7 @@ typedef struct VP9Context { int8_t lf_val; int16_t qmul[2][2]; uint8_t lflvl[4][2]; - } feat[8]; + } feat[MAX_SEGMENT]; } segmentation; struct { unsigned log2_tile_cols, log2_tile_rows; @@ -389,17 +420,13 @@ typedef struct VP9Context { // whole-frame cache uint8_t *intra_pred_data[3]; - uint8_t *segmentation_map; - VP9MVRefPair *mv[2]; VP9Filter *lflvl; DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71 * 80]; // block reconstruction intermediates - DECLARE_ALIGNED(32, int16_t, block)[4096]; - DECLARE_ALIGNED(32, int16_t, uvblock)[2][1024]; - uint8_t eob[256]; - uint8_t uveob[2][64]; - VP56mv min_mv, max_mv; + int16_t *block_base, *block, *uvblock_base[2], *uvblock[2]; + uint8_t *eob_base, *uveob_base[2], *eob, *uveob[2]; + struct { int x, y; } min_mv, max_mv; DECLARE_ALIGNED(32, uint8_t, tmp_y)[64 * 64]; DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32 * 32]; } VP9Context; diff --git a/libavcodec/vp9block.c b/libavcodec/vp9block.c index caf3bcc..9b0d836 100644 --- a/libavcodec/vp9block.c +++ b/libavcodec/vp9block.c @@ -24,7 +24,6 @@ #include "libavutil/avassert.h" #include "avcodec.h" -#include "get_bits.h" #include "internal.h" #include "videodsp.h" #include "vp56.h" @@ -71,12 +70,17 @@ static void decode_mode(VP9Context *s, VP9Block *const b) vp56_rac_get_prob_branchy(&s->c, s->prob.segpred[s->above_segpred_ctx[col] + s->left_segpred_ctx[row7]]))) { - int pred = 8, x; + uint8_t *refsegmap = s->frames[LAST_FRAME].segmentation_map; + int pred = MAX_SEGMENT - 1; + int x; + + if (!s->last_uses_2pass) + ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0); for (y = 0; y < h4; y++) for (x = 0; x < w4; x++) pred = FFMIN(pred, - s->segmentation_map[(y + row) * 8 * s->sb_cols + x + col]); + refsegmap[(y + row) * 8 * s->sb_cols + x + col]); b->seg_id = pred; memset(&s->above_segpred_ctx[col], 1, w4); @@ -89,8 +93,10 @@ static void decode_mode(VP9Context *s, VP9Block *const b) memset(&s->left_segpred_ctx[row7], 0, h4); } if ((s->segmentation.enabled && s->segmentation.update_map) || s->keyframe) { + uint8_t *segmap = s->frames[CUR_FRAME].segmentation_map; + for (y = 0; y < h4; y++) - memset(&s->segmentation_map[(y + row) * 8 * s->sb_cols + col], + memset(&segmap[(y + row) * 8 * s->sb_cols + col], b->seg_id, w4); } @@ -684,24 +690,25 @@ static void decode_mode(VP9Context *s, VP9Block *const b) // FIXME kinda ugly for (y = 0; y < h4; y++) { int x, o = (row + y) * s->sb_cols * 8 + col; + VP9MVRefPair *mv = &s->frames[CUR_FRAME].mv[o]; if (b->intra) { for (x = 0; x < w4; x++) { - s->mv[0][o + x].ref[0] = - s->mv[0][o + x].ref[1] = -1; + mv[x].ref[0] = + mv[x].ref[1] = -1; } } else if (b->comp) { for (x = 0; x < w4; x++) { - s->mv[0][o + x].ref[0] = b->ref[0]; - s->mv[0][o + x].ref[1] = b->ref[1]; - AV_COPY32(&s->mv[0][o + x].mv[0], &b->mv[3][0]); - AV_COPY32(&s->mv[0][o + x].mv[1], &b->mv[3][1]); + mv[x].ref[0] = b->ref[0]; + mv[x].ref[1] = b->ref[1]; + AV_COPY32(&mv[x].mv[0], &b->mv[3][0]); + AV_COPY32(&mv[x].mv[1], &b->mv[3][1]); } } else { for (x = 0; x < w4; x++) { - s->mv[0][o + x].ref[0] = b->ref[0]; - s->mv[0][o + x].ref[1] = -1; - AV_COPY32(&s->mv[0][o + x].mv[0], &b->mv[3][0]); + mv[x].ref[0] = b->ref[0]; + mv[x].ref[1] = -1; + AV_COPY32(&mv[x].mv[0], &b->mv[3][0]); } } } @@ -819,7 +826,7 @@ skip_eob: static int decode_coeffs(AVCodecContext *avctx) { VP9Context *s = avctx->priv_data; - VP9Block *const b = &s->b; + VP9Block *b = s->b; int row = b->row, col = b->col; uint8_t (*p)[6][11] = s->prob.coef[b->tx][0 /* y */][!b->intra]; unsigned (*c)[6][3] = s->counts.coef[b->tx][0 /* y */][!b->intra]; @@ -1070,7 +1077,8 @@ static av_always_inline int check_intra_mode(VP9Context *s, int mode, static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off) { VP9Context *s = avctx->priv_data; - VP9Block *const b = &s->b; + VP9Block *b = s->b; + AVFrame *f = s->frames[CUR_FRAME].tf.f; int row = b->row, col = b->col; int w4 = bwh_tab[1][b->bs][0] << 1, step1d = 1 << b->tx, n; int h4 = bwh_tab[1][b->bs][1] << 1, x, y, step = 1 << (b->tx * 2); @@ -1078,7 +1086,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off int end_y = FFMIN(2 * (s->rows - row), h4); int tx = 4 * s->lossless + b->tx, uvtx = b->uvtx + 4 * s->lossless; int uvstep1d = 1 << b->uvtx, p; - uint8_t *dst = b->dst[0], *dst_r = s->cur_frame->data[0] + y_off; + uint8_t *dst = b->dst[0], *dst_r = f->data[0] + y_off; for (n = 0, y = 0; y < end_y; y += step1d) { uint8_t *ptr = dst, *ptr_r = dst_r; @@ -1092,7 +1100,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off int eob = b->tx > TX_8X8 ? AV_RN16A(&s->eob[n]) : s->eob[n]; mode = check_intra_mode(s, mode, &a, ptr_r, - s->cur_frame->linesize[0], + f->linesize[0], ptr, b->y_stride, l, col, x, w4, row, y, b->tx, 0); s->dsp.intra_pred[b->tx][mode](ptr, b->y_stride, l, a); @@ -1100,7 +1108,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off s->dsp.itxfm_add[tx][txtp](ptr, b->y_stride, s->block + 16 * n, eob); } - dst_r += 4 * s->cur_frame->linesize[0] * step1d; + dst_r += 4 * f->linesize[0] * step1d; dst += 4 * b->y_stride * step1d; } @@ -1112,7 +1120,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off step = 1 << (b->uvtx * 2); for (p = 0; p < 2; p++) { dst = b->dst[1 + p]; - dst_r = s->cur_frame->data[1 + p] + uv_off; + dst_r = f->data[1 + p] + uv_off; for (n = 0, y = 0; y < end_y; y += uvstep1d) { uint8_t *ptr = dst, *ptr_r = dst_r; for (x = 0; x < end_x; @@ -1125,7 +1133,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off : s->uveob[p][n]; mode = check_intra_mode(s, mode, &a, ptr_r, - s->cur_frame->linesize[1], + f->linesize[1], ptr, b->uv_stride, l, col, x, w4, row, y, b->uvtx, p + 1); s->dsp.intra_pred[b->uvtx][mode](ptr, b->uv_stride, l, a); @@ -1134,7 +1142,7 @@ static void intra_recon(AVCodecContext *avctx, ptrdiff_t y_off, ptrdiff_t uv_off s->uvblock[p] + 16 * n, eob); } - dst_r += 4 * uvstep1d * s->cur_frame->linesize[1]; + dst_r += 4 * uvstep1d * f->linesize[1]; dst += 4 * uvstep1d * b->uv_stride; } } @@ -1144,17 +1152,25 @@ static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func(*mc)[2], uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *ref, ptrdiff_t ref_stride, + ThreadFrame *ref_frame, ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, int bw, int bh, int w, int h) { int mx = mv->x, my = mv->y; + int th; y += my >> 3; x += mx >> 3; ref += y * ref_stride + x; mx &= 7; my &= 7; + + // we use +7 because the last 7 pixels of each sbrow can be changed in + // the longest loopfilter of the next sbrow + th = (y + bh + 4 * !!my + 7) >> 6; + ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0); + // FIXME bilinear filter only needs 0/1 pixels, not 3/4 if (x < !!mx * 3 || y < !!my * 3 || x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) { @@ -1177,11 +1193,13 @@ static av_always_inline void mc_chroma_dir(VP9Context *s, vp9_mc_func(*mc)[2], ptrdiff_t src_stride_u, const uint8_t *ref_v, ptrdiff_t src_stride_v, + ThreadFrame *ref_frame, ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, int bw, int bh, int w, int h) { int mx = mv->x, my = mv->y; + int th; y += my >> 4; x += mx >> 4; @@ -1189,6 +1207,12 @@ static av_always_inline void mc_chroma_dir(VP9Context *s, vp9_mc_func(*mc)[2], ref_v += y * src_stride_v + x; mx &= 15; my &= 15; + + // we use +7 because the last 7 pixels of each sbrow can be changed in + // the longest loopfilter of the next sbrow + th = (y + bh + 4 * !!my + 7) >> 5; + ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0); + // FIXME bilinear filter only needs 0/1 pixels, not 3/4 if (x < !!mx * 3 || y < !!my * 3 || x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) { @@ -1222,10 +1246,14 @@ static int inter_recon(AVCodecContext *avctx) { 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4 }, }; VP9Context *s = avctx->priv_data; - VP9Block *const b = &s->b; + VP9Block *b = s->b; int row = b->row, col = b->col; - AVFrame *ref1 = s->refs[s->refidx[b->ref[0]]]; - AVFrame *ref2 = b->comp ? s->refs[s->refidx[b->ref[1]]] : NULL; + + ThreadFrame *tref1 = &s->refs[s->refidx[b->ref[0]]]; + ThreadFrame *tref2 = b->comp ? &s->refs[s->refidx[b->ref[1]]] : NULL; + AVFrame *ref1 = tref1->f; + AVFrame *ref2 = tref2 ? tref2->f : NULL; + int w = avctx->width, h = avctx->height; ptrdiff_t ls_y = b->y_stride, ls_uv = b->uv_stride; @@ -1236,36 +1264,36 @@ static int inter_recon(AVCodecContext *avctx) if (b->bs > BS_8x8) { if (b->bs == BS_8x4) { mc_luma_dir(s, s->dsp.mc[3][b->filter][0], b->dst[0], ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, col << 3, &b->mv[0][0], 8, 4, w, h); mc_luma_dir(s, s->dsp.mc[3][b->filter][0], b->dst[0] + 4 * ls_y, ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, (row << 3) + 4, col << 3, &b->mv[2][0], 8, 4, w, h); if (b->comp) { mc_luma_dir(s, s->dsp.mc[3][b->filter][1], b->dst[0], ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, col << 3, &b->mv[0][1], 8, 4, w, h); mc_luma_dir(s, s->dsp.mc[3][b->filter][1], b->dst[0] + 4 * ls_y, ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, (row << 3) + 4, col << 3, &b->mv[2][1], 8, 4, w, h); } } else if (b->bs == BS_4x8) { mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0], ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, col << 3, &b->mv[0][0], 4, 8, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0] + 4, ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, (col << 3) + 4, &b->mv[1][0], 4, 8, w, h); if (b->comp) { mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0], ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, col << 3, &b->mv[0][1], 4, 8, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0] + 4, ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, (col << 3) + 4, &b->mv[1][1], 4, 8, w, h); } } else { @@ -1274,34 +1302,34 @@ static int inter_recon(AVCodecContext *avctx) // FIXME if two horizontally adjacent blocks have the same MV, // do a w8 instead of a w4 call mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0], ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, col << 3, &b->mv[0][0], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0] + 4, ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, (col << 3) + 4, &b->mv[1][0], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0] + 4 * ls_y, ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, (row << 3) + 4, col << 3, &b->mv[2][0], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][0], b->dst[0] + 4 * ls_y + 4, ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, (row << 3) + 4, (col << 3) + 4, &b->mv[3][0], 4, 4, w, h); if (b->comp) { mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0], ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, col << 3, &b->mv[0][1], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0] + 4, ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, (col << 3) + 4, &b->mv[1][1], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0] + 4 * ls_y, ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, (row << 3) + 4, col << 3, &b->mv[2][1], 4, 4, w, h); mc_luma_dir(s, s->dsp.mc[4][b->filter][1], b->dst[0] + 4 * ls_y + 4, ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, (row << 3) + 4, (col << 3) + 4, &b->mv[3][1], 4, 4, w, h); } } @@ -1311,12 +1339,12 @@ static int inter_recon(AVCodecContext *avctx) int bh = bwh_tab[0][b->bs][1] * 4; mc_luma_dir(s, s->dsp.mc[bwl][b->filter][0], b->dst[0], ls_y, - ref1->data[0], ref1->linesize[0], + ref1->data[0], ref1->linesize[0], tref1, row << 3, col << 3, &b->mv[0][0], bw, bh, w, h); if (b->comp) mc_luma_dir(s, s->dsp.mc[bwl][b->filter][1], b->dst[0], ls_y, - ref2->data[0], ref2->linesize[0], + ref2->data[0], ref2->linesize[0], tref2, row << 3, col << 3, &b->mv[0][1], bw, bh, w, h); } @@ -1340,7 +1368,7 @@ static int inter_recon(AVCodecContext *avctx) mc_chroma_dir(s, s->dsp.mc[bwl][b->filter][0], b->dst[1], b->dst[2], ls_uv, ref1->data[1], ref1->linesize[1], - ref1->data[2], ref1->linesize[2], + ref1->data[2], ref1->linesize[2], tref1, row << 2, col << 2, &mvuv, bw, bh, w, h); if (b->comp) { @@ -1355,7 +1383,7 @@ static int inter_recon(AVCodecContext *avctx) mc_chroma_dir(s, s->dsp.mc[bwl][b->filter][1], b->dst[1], b->dst[2], ls_uv, ref2->data[1], ref2->linesize[1], - ref2->data[2], ref2->linesize[2], + ref2->data[2], ref2->linesize[2], tref2, row << 2, col << 2, &mvuv, bw, bh, w, h); } } @@ -1546,7 +1574,8 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col, enum BlockLevel bl, enum BlockPartition bp) { VP9Context *s = avctx->priv_data; - VP9Block *const b = &s->b; + VP9Block *b = s->b; + AVFrame *f = s->frames[CUR_FRAME].tf.f; enum BlockSize bs = bl * 3 + bp; int ret, y, w4 = bwh_tab[1][bs][0], h4 = bwh_tab[1][bs][1], lvl; int emu[2]; @@ -1561,46 +1590,62 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col, s->max_mv.x = 128 + (s->cols - col - w4) * 64; s->max_mv.y = 128 + (s->rows - row - h4) * 64; - b->bs = bs; - decode_mode(s, b); - b->uvtx = b->tx - (w4 * 2 == (1 << b->tx) || h4 * 2 == (1 << b->tx)); + if (s->pass < 2) { + b->bs = bs; + b->bl = bl; + b->bp = bp; + decode_mode(s, b); + b->uvtx = b->tx - (w4 * 2 == (1 << b->tx) || h4 * 2 == (1 << b->tx)); - if (!b->skip) { - if ((ret = decode_coeffs(avctx)) < 0) - return ret; - } else { - int pl; + if (!b->skip) { + if ((ret = decode_coeffs(avctx)) < 0) + return ret; + } else { + int pl; - memset(&s->above_y_nnz_ctx[col * 2], 0, w4 * 2); - memset(&s->left_y_nnz_ctx[(row & 7) << 1], 0, h4 * 2); - for (pl = 0; pl < 2; pl++) { - memset(&s->above_uv_nnz_ctx[pl][col], 0, w4); - memset(&s->left_uv_nnz_ctx[pl][row & 7], 0, h4); + memset(&s->above_y_nnz_ctx[col * 2], 0, w4 * 2); + memset(&s->left_y_nnz_ctx[(row & 7) << 1], 0, h4 * 2); + for (pl = 0; pl < 2; pl++) { + memset(&s->above_uv_nnz_ctx[pl][col], 0, w4); + memset(&s->left_uv_nnz_ctx[pl][row & 7], 0, h4); + } + } + + if (s->pass == 1) { + s->b++; + s->block += w4 * h4 * 64; + s->uvblock[0] += w4 * h4 * 16; + s->uvblock[1] += w4 * h4 * 16; + s->eob += w4 * h4 * 4; + s->uveob[0] += w4 * h4; + s->uveob[1] += w4 * h4; + + return 0; } } /* Emulated overhangs if the stride of the target buffer can't hold. * This allows to support emu-edge and so on even if we have large * block overhangs. */ - emu[0] = (col + w4) * 8 > s->cur_frame->linesize[0] || + emu[0] = (col + w4) * 8 > f->linesize[0] || (row + h4) > s->rows; - emu[1] = (col + w4) * 4 > s->cur_frame->linesize[1] || + emu[1] = (col + w4) * 4 > f->linesize[1] || (row + h4) > s->rows; if (emu[0]) { b->dst[0] = s->tmp_y; b->y_stride = 64; } else { - b->dst[0] = s->cur_frame->data[0] + yoff; - b->y_stride = s->cur_frame->linesize[0]; + b->dst[0] = f->data[0] + yoff; + b->y_stride = f->linesize[0]; } if (emu[1]) { b->dst[1] = s->tmp_uv[0]; b->dst[2] = s->tmp_uv[1]; b->uv_stride = 32; } else { - b->dst[1] = s->cur_frame->data[1] + uvoff; - b->dst[2] = s->cur_frame->data[2] + uvoff; - b->uv_stride = s->cur_frame->linesize[1]; + b->dst[1] = f->data[1] + uvoff; + b->dst[2] = f->data[2] + uvoff; + b->uv_stride = f->linesize[1]; } if (b->intra) { intra_recon(avctx, yoff, uvoff); @@ -1618,9 +1663,9 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col, av_assert2(n <= 4); if (w & bw) { - s->dsp.mc[n][0][0][0][0](s->cur_frame->data[0] + yoff + o, + s->dsp.mc[n][0][0][0][0](f->data[0] + yoff + o, s->tmp_y + o, - s->cur_frame->linesize[0], + f->linesize[0], 64, h, 0, 0); o += bw; } @@ -1636,13 +1681,13 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col, av_assert2(n <= 4); if (w & bw) { - s->dsp.mc[n][0][0][0][0](s->cur_frame->data[1] + uvoff + o, + s->dsp.mc[n][0][0][0][0](f->data[1] + uvoff + o, s->tmp_uv[0] + o, - s->cur_frame->linesize[1], + f->linesize[1], 32, h, 0, 0); - s->dsp.mc[n][0][0][0][0](s->cur_frame->data[2] + uvoff + o, + s->dsp.mc[n][0][0][0][0](f->data[2] + uvoff + o, s->tmp_uv[1] + o, - s->cur_frame->linesize[2], + f->linesize[2], 32, h, 0, 0); o += bw; } @@ -1680,5 +1725,15 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col, } } + if (s->pass == 2) { + s->b++; + s->block += w4 * h4 * 64; + s->uvblock[0] += w4 * h4 * 16; + s->uvblock[1] += w4 * h4 * 16; + s->eob += w4 * h4 * 4; + s->uveob[0] += w4 * h4; + s->uveob[1] += w4 * h4; + } + return 0; } diff --git a/libavcodec/vp9mvs.c b/libavcodec/vp9mvs.c index 1f65aaa..dde0e84 100644 --- a/libavcodec/vp9mvs.c +++ b/libavcodec/vp9mvs.c @@ -64,7 +64,7 @@ static void find_ref_mvs(VP9Context *s, [BS_4x4] = { { 0, -1 }, { -1, 0 }, { -1, -1 }, { 0, -2 }, { -2, 0 }, { -1, -2 }, { -2, -1 }, { -2, -2 } }, }; - VP9Block *const b = &s->b; + VP9Block *b = s->b; int row = b->row, col = b->col, row7 = b->row7; const int8_t (*p)[2] = mv_ref_blk_off[b->bs]; #define INVALID_MV 0x80008000U @@ -125,7 +125,7 @@ static void find_ref_mvs(VP9Context *s, } while (0) if (row > 0) { - VP9MVRefPair *mv = &s->mv[0][(row - 1) * s->sb_cols * 8 + col]; + VP9MVRefPair *mv = &s->frames[CUR_FRAME].mv[(row - 1) * s->sb_cols * 8 + col]; if (mv->ref[0] == ref) RETURN_MV(s->above_mv_ctx[2 * col + (sb & 1)][0]); @@ -133,7 +133,7 @@ static void find_ref_mvs(VP9Context *s, RETURN_MV(s->above_mv_ctx[2 * col + (sb & 1)][1]); } if (col > s->tiling.tile_col_start) { - VP9MVRefPair *mv = &s->mv[0][row * s->sb_cols * 8 + col - 1]; + VP9MVRefPair *mv = &s->frames[CUR_FRAME].mv[row * s->sb_cols * 8 + col - 1]; if (mv->ref[0] == ref) RETURN_MV(s->left_mv_ctx[2 * row7 + (sb >> 1)][0]); @@ -151,7 +151,7 @@ static void find_ref_mvs(VP9Context *s, if (c >= s->tiling.tile_col_start && c < s->cols && r >= 0 && r < s->rows) { - VP9MVRefPair *mv = &s->mv[0][r * s->sb_cols * 8 + c]; + VP9MVRefPair *mv = &s->frames[CUR_FRAME].mv[r * s->sb_cols * 8 + c]; if (mv->ref[0] == ref) RETURN_MV(mv->mv[0]); @@ -162,7 +162,10 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using same reference frame if (s->use_last_frame_mvs) { - VP9MVRefPair *mv = &s->mv[1][row * s->sb_cols * 8 + col]; + VP9MVRefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col]; + + if (!s->last_uses_2pass) + ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0); if (mv->ref[0] == ref) RETURN_MV(mv->mv[0]); @@ -186,7 +189,7 @@ static void find_ref_mvs(VP9Context *s, if (c >= s->tiling.tile_col_start && c < s->cols && r >= 0 && r < s->rows) { - VP9MVRefPair *mv = &s->mv[0][r * s->sb_cols * 8 + c]; + VP9MVRefPair *mv = &s->frames[CUR_FRAME].mv[r * s->sb_cols * 8 + c]; if (mv->ref[0] != ref && mv->ref[0] >= 0) RETURN_SCALE_MV(mv->mv[0], @@ -203,8 +206,9 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using different reference frame if (s->use_last_frame_mvs) { - VP9MVRefPair *mv = &s->mv[1][row * s->sb_cols * 8 + col]; + VP9MVRefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col]; + // no need to await_progress, because we already did that above if (mv->ref[0] != ref && mv->ref[0] >= 0) RETURN_SCALE_MV(mv->mv[0], s->signbias[mv->ref[0]] != s->signbias[ref]); @@ -279,7 +283,7 @@ static av_always_inline int read_mv_component(VP9Context *s, int idx, int hp) void ff_vp9_fill_mv(VP9Context *s, VP56mv *mv, int mode, int sb) { - VP9Block *const b = &s->b; + VP9Block *b = s->b; if (mode == ZEROMV) { memset(mv, 0, sizeof(*mv) * 2); diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 86f2fcf..0d0d59a 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -1,6 +1,6 @@ /* * Westwood Studios VQA Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -235,7 +235,7 @@ static int decode_format80(GetByteContext *gb, int src_size, start = bytestream2_tell(gb); while (bytestream2_tell(gb) - start < src_size) { opcode = bytestream2_get_byte(gb); - av_dlog(NULL, " opcode %02X: ", opcode); + ff_dlog(NULL, " opcode %02X: ", opcode); /* 0x80 means that frame is finished */ if (opcode == 0x80) @@ -251,7 +251,7 @@ static int decode_format80(GetByteContext *gb, int src_size, count = bytestream2_get_le16(gb); src_pos = bytestream2_get_le16(gb); - av_dlog(NULL, "(1) copy %X bytes from absolute pos %X\n", count, src_pos); + ff_dlog(NULL, "(1) copy %X bytes from absolute pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -262,7 +262,7 @@ static int decode_format80(GetByteContext *gb, int src_size, count = bytestream2_get_le16(gb); color = bytestream2_get_byte(gb); - av_dlog(NULL, "(2) set %X bytes to %02X\n", count, color); + ff_dlog(NULL, "(2) set %X bytes to %02X\n", count, color); CHECK_COUNT(); memset(&dest[dest_index], color, count); dest_index += count; @@ -271,7 +271,7 @@ static int decode_format80(GetByteContext *gb, int src_size, count = (opcode & 0x3F) + 3; src_pos = bytestream2_get_le16(gb); - av_dlog(NULL, "(3) copy %X bytes from absolute pos %X\n", count, src_pos); + ff_dlog(NULL, "(3) copy %X bytes from absolute pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -281,7 +281,7 @@ static int decode_format80(GetByteContext *gb, int src_size, } else if (opcode > 0x80) { count = opcode & 0x3F; - av_dlog(NULL, "(4) copy %X bytes from source to dest\n", count); + ff_dlog(NULL, "(4) copy %X bytes from source to dest\n", count); CHECK_COUNT(); bytestream2_get_buffer(gb, &dest[dest_index], count); dest_index += count; @@ -290,7 +290,7 @@ static int decode_format80(GetByteContext *gb, int src_size, count = ((opcode & 0x70) >> 4) + 3; src_pos = bytestream2_get_byte(gb) | ((opcode & 0x0F) << 8); - av_dlog(NULL, "(5) copy %X bytes from relpos %X\n", count, src_pos); + ff_dlog(NULL, "(5) copy %X bytes from relpos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(dest_index - src_pos); for (i = 0; i < count; i++) @@ -646,5 +646,5 @@ AVCodec ff_vqa_decoder = { .init = vqa_decode_init, .close = vqa_decode_end, .decode = vqa_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index cbc5b04..7f55f51 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -19,14 +19,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define BITSTREAM_READER_LE - #include "libavutil/channel_layout.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" +#include "bytestream.h" #include "get_bits.h" #include "internal.h" #include "unary.h" -#include "bytestream.h" /** * @file @@ -248,7 +248,7 @@ static av_always_inline int get_tail(GetBitContext *gb, int k) return 0; p = av_log2(k); e = (1 << (p + 1)) - k - 1; - res = p ? get_bits(gb, p) : 0; + res = get_bitsz(gb, p); if (res >= e) res = (res << 1) - e + get_bits1(gb); return res; @@ -446,7 +446,7 @@ static float wv_get_value_float(WavpackFrameContext *s, uint32_t *crc, int S) const int max_bits = 1 + 23 + 8 + 1; const int left_bits = get_bits_left(&s->gb_extra_bits); - if (left_bits + 8 * FF_INPUT_BUFFER_PADDING_SIZE < max_bits) + if (left_bits + 8 * AV_INPUT_BUFFER_PADDING_SIZE < max_bits) return 0.0; } @@ -1234,5 +1234,5 @@ AVCodec ff_wavpack_decoder = { .close = wavpack_decode_end, .decode = wavpack_decode_frame, .flush = wavpack_decode_flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/webp.c b/libavcodec/webp.c index 62f35f7..b26399c 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -37,12 +37,13 @@ * - Exif and XMP metadata */ -#define BITSTREAM_READER_LE #include "libavutil/imgutils.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" -#include "internal.h" #include "get_bits.h" +#include "internal.h" #include "thread.h" #include "vp8.h" @@ -1362,7 +1363,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; } - while (bytestream2_get_bytes_left(&gb) > 0) { + while (bytestream2_get_bytes_left(&gb) > 8) { char chunk_str[5] = { 0 }; chunk_type = bytestream2_get_le32(&gb); @@ -1480,5 +1481,5 @@ AVCodec ff_webp_decoder = { .priv_data_size = sizeof(WebPContext), .decode = webp_decode_frame, .close = webp_decode_close, - .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff --git a/libavcodec/wma.c b/libavcodec/wma.c index f5ea64a..4067dff 100644 --- a/libavcodec/wma.c +++ b/libavcodec/wma.c @@ -20,22 +20,22 @@ */ #include "libavutil/attributes.h" + #include "avcodec.h" +#include "internal.h" #include "sinewin.h" #include "wma.h" #include "wma_common.h" +#include "wma_freqs.h" #include "wmadata.h" -#undef NDEBUG -#include - /* XXX: use same run/length optimization as mpeg decoders */ -//FIXME maybe split decode / encode or pass flag -static av_cold void init_coef_vlc(VLC *vlc, uint16_t **prun_table, - float **plevel_table, uint16_t **pint_table, - const CoefVLCTable *vlc_table) +// FIXME maybe split decode / encode or pass flag +static av_cold int init_coef_vlc(VLC *vlc, uint16_t **prun_table, + float **plevel_table, uint16_t **pint_table, + const CoefVLCTable *vlc_table) { - int n = vlc_table->n; + 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; @@ -45,20 +45,27 @@ static av_cold void init_coef_vlc(VLC *vlc, uint16_t **prun_table, init_vlc(vlc, VLCBITS, n, table_bits, 1, 1, table_codes, 4, 4, 0); - run_table = av_malloc(n * sizeof(uint16_t)); - level_table = av_malloc(n * sizeof(uint16_t)); - flevel_table= av_malloc(n * sizeof(*flevel_table)); - int_table = av_malloc(n * sizeof(uint16_t)); - i = 2; - level = 1; - k = 0; + run_table = av_malloc(n * sizeof(uint16_t)); + level_table = av_malloc(n * sizeof(uint16_t)); + flevel_table = av_malloc(n * sizeof(*flevel_table)); + int_table = av_malloc(n * sizeof(uint16_t)); + if (!run_table || !level_table || !flevel_table || !int_table) { + av_freep(&run_table); + av_freep(&level_table); + av_freep(&flevel_table); + av_freep(&int_table); + return AVERROR(ENOMEM); + } + i = 2; + level = 1; + k = 0; while (i < n) { int_table[k] = i; - l = levels_table[k++]; + l = levels_table[k++]; for (j = 0; j < l; j++) { - run_table[i] = j; - level_table[i] = level; - flevel_table[i]= level; + run_table[i] = j; + level_table[i] = level; + flevel_table[i] = level; i++; } level++; @@ -67,30 +74,30 @@ static av_cold void init_coef_vlc(VLC *vlc, uint16_t **prun_table, *plevel_table = flevel_table; *pint_table = int_table; av_free(level_table); + + return 0; } av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) { WMACodecContext *s = avctx->priv_data; - int i; + int i, ret; float bps1, high_freq; volatile float bps; int sample_rate1; int coef_vlc_table; - if ( avctx->sample_rate <= 0 || avctx->sample_rate > 50000 - || avctx->channels <= 0 || avctx->channels > 2 - || avctx->bit_rate <= 0) + if (avctx->sample_rate <= 0 || avctx->sample_rate > 50000 || + avctx->channels <= 0 || avctx->channels > 2 || + avctx->bit_rate <= 0) return -1; - ff_fmt_convert_init(&s->fmt_conv, avctx); - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (avctx->codec->id == AV_CODEC_ID_WMAV1) { + if (avctx->codec->id == AV_CODEC_ID_WMAV1) s->version = 1; - } else { + else s->version = 2; - } /* compute MDCT block size */ s->frame_len_bits = ff_wma_get_frame_len_bits(avctx->sample_rate, @@ -109,84 +116,78 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) if (nb > nb_max) nb = nb_max; s->nb_block_sizes = nb + 1; - } else { + } else s->nb_block_sizes = 1; - } /* init rate dependent parameters */ s->use_noise_coding = 1; - high_freq = avctx->sample_rate * 0.5; + high_freq = avctx->sample_rate * 0.5; /* if version 2, then the rates are normalized */ sample_rate1 = avctx->sample_rate; if (s->version == 2) { - if (sample_rate1 >= 44100) { + if (sample_rate1 >= 44100) sample_rate1 = 44100; - } else if (sample_rate1 >= 22050) { + else if (sample_rate1 >= 22050) sample_rate1 = 22050; - } else if (sample_rate1 >= 16000) { + else if (sample_rate1 >= 16000) sample_rate1 = 16000; - } else if (sample_rate1 >= 11025) { + else if (sample_rate1 >= 11025) sample_rate1 = 11025; - } else if (sample_rate1 >= 8000) { + else if (sample_rate1 >= 8000) sample_rate1 = 8000; - } } - bps = (float)avctx->bit_rate / (float)(avctx->channels * avctx->sample_rate); - s->byte_offset_bits = av_log2((int)(bps * s->frame_len / 8.0 + 0.5)) + 2; + bps = (float) avctx->bit_rate / + (float) (avctx->channels * avctx->sample_rate); + s->byte_offset_bits = av_log2((int) (bps * s->frame_len / 8.0 + 0.5)) + 2; /* compute high frequency value and choose if noise coding should - be activated */ + * be activated */ bps1 = bps; if (avctx->channels == 2) bps1 = bps * 1.6; if (sample_rate1 == 44100) { - if (bps1 >= 0.61) { + if (bps1 >= 0.61) s->use_noise_coding = 0; - } else { + else high_freq = high_freq * 0.4; - } } else if (sample_rate1 == 22050) { - if (bps1 >= 1.16) { + if (bps1 >= 1.16) s->use_noise_coding = 0; - } else if (bps1 >= 0.72) { + else if (bps1 >= 0.72) high_freq = high_freq * 0.7; - } else { + else high_freq = high_freq * 0.6; - } } else if (sample_rate1 == 16000) { - if (bps > 0.5) { + if (bps > 0.5) high_freq = high_freq * 0.5; - } else { + else high_freq = high_freq * 0.3; - } - } else if (sample_rate1 == 11025) { + } else if (sample_rate1 == 11025) high_freq = high_freq * 0.7; - } else if (sample_rate1 == 8000) { - if (bps <= 0.625) { + else if (sample_rate1 == 8000) { + if (bps <= 0.625) high_freq = high_freq * 0.5; - } else if (bps > 0.75) { + else if (bps > 0.75) s->use_noise_coding = 0; - } else { + else high_freq = high_freq * 0.65; - } } else { - if (bps >= 0.8) { + if (bps >= 0.8) high_freq = high_freq * 0.75; - } else if (bps >= 0.6) { + else if (bps >= 0.6) high_freq = high_freq * 0.6; - } else { + else high_freq = high_freq * 0.5; - } } - av_dlog(s->avctx, "flags2=0x%x\n", flags2); - av_dlog(s->avctx, "version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n", + ff_dlog(s->avctx, "flags2=0x%x\n", flags2); + ff_dlog(s->avctx, "version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n", s->version, avctx->channels, avctx->sample_rate, avctx->bit_rate, avctx->block_align); - av_dlog(s->avctx, "bps=%f bps1=%f high_freq=%f bitoffset=%d\n", + ff_dlog(s->avctx, "bps=%f bps1=%f high_freq=%f bitoffset=%d\n", bps, bps1, high_freq, s->byte_offset_bits); - av_dlog(s->avctx, "use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n", + ff_dlog(s->avctx, "use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n", s->use_noise_coding, s->use_exp_vlc, s->nb_block_sizes); /* compute the scale factor band sizes for each MDCT block size */ @@ -194,19 +195,18 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) int a, b, pos, lpos, k, block_len, i, j, n; const uint8_t *table; - if (s->version == 1) { + if (s->version == 1) s->coefs_start = 3; - } else { + else s->coefs_start = 0; - } for (k = 0; k < s->nb_block_sizes; k++) { block_len = s->frame_len >> k; if (s->version == 1) { lpos = 0; for (i = 0; i < 25; i++) { - a = ff_wma_critical_freqs[i]; - b = avctx->sample_rate; + a = ff_wma_critical_freqs[i]; + b = avctx->sample_rate; pos = ((block_len * 2 * a) + (b >> 1)) / b; if (pos > block_len) pos = block_len; @@ -221,15 +221,14 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) } else { /* hardcoded tables */ table = NULL; - a = s->frame_len_bits - BLOCK_MIN_BITS - k; + a = s->frame_len_bits - BLOCK_MIN_BITS - k; if (a < 3) { - if (avctx->sample_rate >= 44100) { + if (avctx->sample_rate >= 44100) table = exponent_band_44100[a]; - } else if (avctx->sample_rate >= 32000) { + else if (avctx->sample_rate >= 32000) table = exponent_band_32000[a]; - } else if (avctx->sample_rate >= 22050) { + else if (avctx->sample_rate >= 22050) table = exponent_band_22050[a]; - } } if (table) { n = *table++; @@ -237,12 +236,12 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) s->exponent_bands[k][i] = table[i]; s->exponent_sizes[k] = n; } else { - j = 0; + j = 0; lpos = 0; for (i = 0; i < 25; i++) { - a = ff_wma_critical_freqs[i]; - b = avctx->sample_rate; - pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); + a = ff_wma_critical_freqs[i]; + b = avctx->sample_rate; + pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); pos <<= 2; if (pos > block_len) pos = block_len; @@ -259,16 +258,16 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) /* max number of coefs */ s->coefs_end[k] = (s->frame_len - ((s->frame_len * 9) / 100)) >> k; /* high freq computation */ - s->high_band_start[k] = (int)((block_len * 2 * high_freq) / - avctx->sample_rate + 0.5); - n = s->exponent_sizes[k]; - j = 0; + s->high_band_start[k] = (int) ((block_len * 2 * high_freq) / + avctx->sample_rate + 0.5); + n = s->exponent_sizes[k]; + j = 0; pos = 0; for (i = 0; i < n; i++) { int start, end; start = pos; - pos += s->exponent_bands[k][i]; - end = pos; + 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]) @@ -277,16 +276,6 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) s->exponent_high_bands[k][j++] = end - start; } s->exponent_high_sizes[k] = j; -#if 0 - tprintf(s->avctx, "%5d: coefs_end=%d high_band_start=%d nb_high_bands=%d: ", - s->frame_len >> k, - s->coefs_end[k], - s->high_band_start[k], - s->exponent_high_sizes[k]); - for (j = 0; j < s->exponent_high_sizes[k]; j++) - tprintf(s->avctx, " %d", s->exponent_high_bands[k][j]); - tprintf(s->avctx, "\n"); -#endif } } @@ -294,15 +283,15 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) { int i, j; for (i = 0; i < s->nb_block_sizes; i++) { - tprintf(s->avctx, "%5d: n=%2d:", + ff_tlog(s->avctx, "%5d: n=%2d:", s->frame_len >> i, s->exponent_sizes[i]); for (j = 0; j < s->exponent_sizes[i]; j++) - tprintf(s->avctx, " %d", s->exponent_bands[i][j]); - tprintf(s->avctx, "\n"); + ff_tlog(s->avctx, " %d", s->exponent_bands[i][j]); + ff_tlog(s->avctx, "\n"); } } -#endif +#endif /* TRACE */ /* init MDCT windows : simple sine window */ for (i = 0; i < s->nb_block_sizes; i++) { @@ -313,13 +302,11 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) s->reset_block_lengths = 1; if (s->use_noise_coding) { - /* init the noise generator */ - if (s->use_exp_vlc) { + if (s->use_exp_vlc) s->noise_mult = 0.02; - } else { + else s->noise_mult = 0.04; - } #ifdef TRACE for (i = 0; i < NOISE_TAB_SIZE; i++) @@ -329,41 +316,46 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) unsigned int seed; float norm; seed = 1; - norm = (1.0 / (float)(1LL << 31)) * sqrt(3) * s->noise_mult; + 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; + seed = seed * 314159 + 1; + s->noise_table[i] = (float) ((int) seed) * norm; } } -#endif +#endif /* TRACE */ } /* choose the VLC tables for the coefficients */ coef_vlc_table = 2; if (avctx->sample_rate >= 32000) { - if (bps1 < 0.72) { + if (bps1 < 0.72) coef_vlc_table = 0; - } else if (bps1 < 1.16) { + else if (bps1 < 1.16) coef_vlc_table = 1; - } } - s->coef_vlcs[0]= &coef_vlcs[coef_vlc_table * 2 ]; - s->coef_vlcs[1]= &coef_vlcs[coef_vlc_table * 2 + 1]; - init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0], &s->int_table[0], - s->coef_vlcs[0]); - init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1], &s->int_table[1], - s->coef_vlcs[1]); - - return 0; + s->coef_vlcs[0] = &coef_vlcs[coef_vlc_table * 2]; + s->coef_vlcs[1] = &coef_vlcs[coef_vlc_table * 2 + 1]; + ret = init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0], + &s->int_table[0], s->coef_vlcs[0]); + if (ret < 0) + return ret; + + return init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1], + &s->int_table[1], s->coef_vlcs[1]); } int ff_wma_total_gain_to_bits(int total_gain) { - if (total_gain < 15) return 13; - else if (total_gain < 32) return 12; - else if (total_gain < 40) return 11; - else if (total_gain < 45) return 10; - else return 9; + if (total_gain < 15) + return 13; + else if (total_gain < 32) + return 12; + else if (total_gain < 40) + return 11; + else if (total_gain < 45) + return 10; + else + return 9; } int ff_wma_end(AVCodecContext *avctx) @@ -374,12 +366,10 @@ int ff_wma_end(AVCodecContext *avctx) for (i = 0; i < s->nb_block_sizes; i++) ff_mdct_end(&s->mdct_ctx[i]); - if (s->use_exp_vlc) { + if (s->use_exp_vlc) ff_free_vlc(&s->exp_vlc); - } - if (s->use_noise_coding) { + if (s->use_noise_coding) ff_free_vlc(&s->hgain_vlc); - } for (i = 0; i < 2; i++) { ff_free_vlc(&s->coef_vlc[i]); av_free(s->run_table[i]); @@ -395,7 +385,7 @@ int ff_wma_end(AVCodecContext *avctx) * @param gb GetBitContext * @return the decoded coefficient */ -unsigned int ff_wma_get_large_val(GetBitContext* gb) +unsigned int ff_wma_get_large_val(GetBitContext *gb) { /** consumes up to 34 bits */ int n_bits = 8; @@ -404,9 +394,8 @@ unsigned int ff_wma_get_large_val(GetBitContext* gb) n_bits += 8; if (get_bits1(gb)) { n_bits += 8; - if (get_bits1(gb)) { + if (get_bits1(gb)) n_bits += 7; - } } } return get_bits_long(gb, n_bits); @@ -422,30 +411,30 @@ unsigned int ff_wma_get_large_val(GetBitContext* gb) * @param version 0 for wma1,2 1 for wmapro * @param ptr output buffer * @param offset offset in the output buffer - * @param num_coefs number of input coefficents + * @param num_coefs number of input coefficients * @param block_len input buffer length (2^n) * @param frame_len_bits number of bits for escaped run codes * @param coef_nb_bits number of bits for escaped level codes * @return 0 on success, -1 otherwise */ -int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, - VLC *vlc, - const float *level_table, const uint16_t *run_table, - int version, WMACoef *ptr, int offset, - int num_coefs, int block_len, int frame_len_bits, +int ff_wma_run_level_decode(AVCodecContext *avctx, GetBitContext *gb, + VLC *vlc, const float *level_table, + const uint16_t *run_table, int version, + WMACoef *ptr, int offset, int num_coefs, + int block_len, int frame_len_bits, int coef_nb_bits) { int code, level, sign; - const uint32_t *ilvl = (const uint32_t*)level_table; - uint32_t *iptr = (uint32_t*)ptr; + const uint32_t *ilvl = (const uint32_t *) level_table; + uint32_t *iptr = (uint32_t *) ptr; const unsigned int coef_mask = block_len - 1; for (; offset < num_coefs; offset++) { code = get_vlc2(gb, vlc->table, VLCBITS, VLCMAX); if (code > 1) { /** normal code */ - offset += run_table[code]; - sign = get_bits1(gb) - 1; - iptr[offset & coef_mask] = ilvl[code] ^ sign<<31; + offset += run_table[code]; + sign = get_bits1(gb) - 1; + iptr[offset & coef_mask] = ilvl[code] ^ sign << 31; } else if (code == 1) { /** EOB */ break; @@ -454,7 +443,7 @@ int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, if (!version) { level = get_bits(gb, coef_nb_bits); /** NOTE: this is rather suboptimal. reading - block_len_bits would be better */ + * block_len_bits would be better */ offset += get_bits(gb, frame_len_bits); } else { level = ff_wma_get_large_val(gb); @@ -462,8 +451,8 @@ int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, if (get_bits1(gb)) { if (get_bits1(gb)) { if (get_bits1(gb)) { - av_log(avctx,AV_LOG_ERROR, - "broken escape sequence\n"); + av_log(avctx, AV_LOG_ERROR, + "broken escape sequence\n"); return -1; } else offset += get_bits(gb, frame_len_bits) + 4; @@ -471,8 +460,8 @@ int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, offset += get_bits(gb, 2) + 1; } } - sign = get_bits1(gb) - 1; - ptr[offset & coef_mask] = (level^sign) - sign; + sign = get_bits1(gb) - 1; + ptr[offset & coef_mask] = (level ^ sign) - sign; } } /** NOTE: EOB can be omitted */ diff --git a/libavcodec/wma.h b/libavcodec/wma.h index 513ba3f..c954d71 100644 --- a/libavcodec/wma.h +++ b/libavcodec/wma.h @@ -23,10 +23,11 @@ #define AVCODEC_WMA_H #include "libavutil/float_dsp.h" + +#include "avcodec.h" +#include "fft.h" #include "get_bits.h" #include "put_bits.h" -#include "fft.h" -#include "fmtconvert.h" /* size of blocks */ #define BLOCK_MIN_BITS 7 @@ -49,9 +50,9 @@ #define LSP_POW_BITS 7 -//FIXME should be in wmadec +// FIXME should be in wmadec #define VLCBITS 9 -#define VLCMAX ((22+VLCBITS-1)/VLCBITS) +#define VLCMAX ((22 + VLCBITS - 1) / VLCBITS) typedef float WMACoef; ///< type for decoded coefficients, int16_t would be enough for wma 1/2 @@ -64,7 +65,7 @@ typedef struct CoefVLCTable { } CoefVLCTable; typedef struct WMACodecContext { - AVCodecContext* avctx; + AVCodecContext *avctx; GetBitContext gb; PutBitContext pb; int version; ///< 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) @@ -88,7 +89,7 @@ typedef struct WMACodecContext { int high_band_values[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; /* there are two possible tables for spectral coefficients */ -//FIXME the following 3 tables should be shared between decoders +// FIXME the following 3 tables should be shared between decoders VLC coef_vlc[2]; uint16_t *run_table[2]; float *level_table[2]; @@ -119,7 +120,7 @@ typedef struct WMACodecContext { /* output buffer for one frame and the last for IMDCT windowing */ DECLARE_ALIGNED(32, float, frame_out)[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]; /* last frame info */ - uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; /* padding added */ + uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; /* padding added */ int last_bitoffset; int last_superframe_len; float noise_table[NOISE_TAB_SIZE]; @@ -130,30 +131,28 @@ typedef struct WMACodecContext { float lsp_pow_e_table[256]; float lsp_pow_m_table1[(1 << LSP_POW_BITS)]; float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; - FmtConvertContext fmt_conv; AVFloatDSPContext fdsp; #ifdef TRACE int frame_count; -#endif +#endif /* TRACE */ } WMACodecContext; -extern const uint16_t ff_wma_critical_freqs[25]; extern const uint16_t ff_wma_hgain_huffcodes[37]; extern const uint8_t ff_wma_hgain_huffbits[37]; extern const float ff_wma_lsp_codebook[NB_LSP_COEFS][16]; extern const uint32_t ff_aac_scalefactor_code[121]; extern const uint8_t ff_aac_scalefactor_bits[121]; -int ff_wma_init(AVCodecContext * avctx, int flags2); +int ff_wma_init(AVCodecContext *avctx, int flags2); int ff_wma_total_gain_to_bits(int total_gain); int ff_wma_end(AVCodecContext *avctx); -unsigned int ff_wma_get_large_val(GetBitContext* gb); -int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, - VLC *vlc, - const float *level_table, const uint16_t *run_table, - int version, WMACoef *ptr, int offset, - int num_coefs, int block_len, int frame_len_bits, +unsigned int ff_wma_get_large_val(GetBitContext *gb); +int ff_wma_run_level_decode(AVCodecContext *avctx, GetBitContext *gb, + VLC *vlc, const float *level_table, + const uint16_t *run_table, int version, + WMACoef *ptr, int offset, int num_coefs, + int block_len, int frame_len_bits, int coef_nb_bits); #endif /* AVCODEC_WMA_H */ diff --git a/libavcodec/wma_common.c b/libavcodec/wma_common.c index d1d8045..cf76f5c 100644 --- a/libavcodec/wma_common.c +++ b/libavcodec/wma_common.c @@ -19,6 +19,7 @@ */ #include "libavutil/attributes.h" + #include "wma_common.h" /** @@ -31,31 +32,27 @@ av_cold int ff_wma_get_frame_len_bits(int sample_rate, int version, unsigned int decode_flags) { - int frame_len_bits; - if (sample_rate <= 16000) { + if (sample_rate <= 16000) frame_len_bits = 9; - } else if (sample_rate <= 22050 || - (sample_rate <= 32000 && version == 1)) { + else if (sample_rate <= 22050 || (sample_rate <= 32000 && version == 1)) frame_len_bits = 10; - } else if (sample_rate <= 48000 || version < 3) { + else if (sample_rate <= 48000 || version < 3) frame_len_bits = 11; - } else if (sample_rate <= 96000) { + else if (sample_rate <= 96000) frame_len_bits = 12; - } else { + else frame_len_bits = 13; - } if (version == 3) { int tmp = decode_flags & 0x6; - if (tmp == 0x2) { + if (tmp == 0x2) ++frame_len_bits; - } else if (tmp == 0x4) { + else if (tmp == 0x4) --frame_len_bits; - } else if (tmp == 0x6) { + else if (tmp == 0x6) frame_len_bits -= 2; - } } return frame_len_bits; diff --git a/libavcodec/wma_freqs.c b/libavcodec/wma_freqs.c new file mode 100644 index 0000000..82cef3b --- /dev/null +++ b/libavcodec/wma_freqs.c @@ -0,0 +1,28 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "wma_freqs.h" + +const uint16_t ff_wma_critical_freqs[25] = { + 100, 200, 300, 400, 510, 630, 770, 920, + 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, + 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, + 24500, +}; diff --git a/libavcodec/svq3.h b/libavcodec/wma_freqs.h similarity index 76% rename from libavcodec/svq3.h rename to libavcodec/wma_freqs.h index a20e620..d40ab65 100644 --- a/libavcodec/svq3.h +++ b/libavcodec/wma_freqs.h @@ -16,12 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_SVQ3_H -#define AVCODEC_SVQ3_H +#ifndef AVCODEC_WMA_FREQS_H +#define AVCODEC_WMA_FREQS_H #include -void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp); -void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, int stride, int qp, int dc); +extern const uint16_t ff_wma_critical_freqs[25]; -#endif /* AVCODEC_SVQ3_H */ +#endif /* AVCODEC_WMA_FREQS_H */ diff --git a/libavcodec/wmadata.h b/libavcodec/wmadata.h index 07a1afe..58bffed 100644 --- a/libavcodec/wmadata.h +++ b/libavcodec/wmadata.h @@ -28,1376 +28,1357 @@ #define AVCODEC_WMADATA_H #include -#include "wma.h" -const uint16_t ff_wma_critical_freqs[25] = { - 100, 200, 300, 400, 510, 630, 770, 920, - 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, - 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, - 24500, -}; +#include "wma.h" /* 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, }, + { 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, }, + { 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, }, + { 12, 4, 4, 4, 4, 4, 8, 8, 8, 12, 16, 20, 36, }, + { 15, 4, 8, 4, 8, 8, 4, 8, 8, 12, 12, 12, 24, 28, 40, 76, }, + { 17, 4, 8, 8, 4, 12, 12, 8, 8, 24, 16, 20, 24, 32, 40, 60, 80, 152, }, }; const uint16_t ff_wma_hgain_huffcodes[37] = { - 0x00003, 0x002e7, 0x00001, 0x005cd, 0x0005d, 0x005c9, 0x0005e, 0x00003, - 0x00016, 0x0000b, 0x00001, 0x00006, 0x00001, 0x00006, 0x00004, 0x00005, - 0x00004, 0x00007, 0x00003, 0x00007, 0x00004, 0x0000a, 0x0000a, 0x00002, - 0x00003, 0x00000, 0x00005, 0x00002, 0x0005f, 0x00004, 0x00003, 0x00002, - 0x005c8, 0x000b8, 0x005ca, 0x005cb, 0x005cc, + 0x00003, 0x002e7, 0x00001, 0x005cd, 0x0005d, 0x005c9, 0x0005e, 0x00003, + 0x00016, 0x0000b, 0x00001, 0x00006, 0x00001, 0x00006, 0x00004, 0x00005, + 0x00004, 0x00007, 0x00003, 0x00007, 0x00004, 0x0000a, 0x0000a, 0x00002, + 0x00003, 0x00000, 0x00005, 0x00002, 0x0005f, 0x00004, 0x00003, 0x00002, + 0x005c8, 0x000b8, 0x005ca, 0x005cb, 0x005cc, }; const uint8_t ff_wma_hgain_huffbits[37] = { - 10, 12, 10, 13, 9, 13, 9, 8, - 7, 5, 5, 4, 4, 3, 3, 3, - 4, 3, 4, 4, 5, 5, 6, 8, - 7, 10, 8, 10, 9, 8, 9, 9, - 13, 10, 13, 13, 13, + 10, 12, 10, 13, 9, 13, 9, 8, 7, 5, 5, 4, 4, 3, 3, 3, + 4, 3, 4, 4, 5, 5, 6, 8, 7, 10, 8, 10, 9, 8, 9, 9, + 13, 10, 13, 13, 13, }; const float ff_wma_lsp_codebook[NB_LSP_COEFS][16] = { - { 1.98732877, 1.97944528, 1.97179088, 1.96260549, 1.95038374, 1.93336114, 1.90719232, 1.86191415, }, - { 1.97260000, 1.96083160, 1.94982586, 1.93806164, 1.92516608, 1.91010199, 1.89232331, 1.87149812, - 1.84564818, 1.81358067, 1.77620070, 1.73265264, 1.67907855, 1.60959081, 1.50829650, 1.33120330, }, - { 1.90109110, 1.86482426, 1.83419671, 1.80168452, 1.76650116, 1.72816320, 1.68502700, 1.63738256, - 1.58501580, 1.51795181, 1.43679906, 1.33950585, 1.24176208, 1.12260729, 0.96749668, 0.74048265, }, - { 1.76943864, 1.67822463, 1.59946365, 1.53560582, 1.47470796, 1.41210167, 1.34509536, 1.27339507, - 1.19303814, 1.09765169, 0.98818722, 0.87239446, 0.74369172, 0.59768184, 0.43168630, 0.17977021, }, - { 1.43428349, 1.32038354, 1.21074086, 1.10577988, 1.00561746, 0.90335924, 0.80437489, 0.70709671, - 0.60427395, 0.49814048, 0.38509539, 0.27106800, 0.14407416, 0.00219910, -0.16725141, -0.36936085, }, - { 0.99895687, 0.84188166, 0.70753739, 0.57906595, 0.47055563, 0.36966965, 0.26826648, 0.17163380, - 0.07208392, -0.03062936, -1.40037388, -0.25128968, -0.37213937, -0.51075646, -0.64887512, -0.80308031, }, - { 0.26515280, 0.06313551, -0.08872080, -0.21103548, -0.31069678, -0.39680323, -0.47223474, -0.54167135, - -0.61444740, -0.68943343, -0.76580211, -0.85170082, -0.95289061, -1.06514703, -1.20510707, -1.37617746, }, - { -0.53940301, -0.73770929, -0.88424876, -1.01117930, -1.13389091, -1.26830073, -1.42041987, -1.62033919, - -1.10158808, -1.16512566, -1.23337128, -1.30414401, -1.37663312, -1.46853845, -1.57625798, -1.66893638, }, - { -0.38601997, -0.56009350, -0.66978483, -0.76028471, -0.83846064, -0.90868087, -0.97408881, -1.03694962, }, - { -1.56144989, -1.65944032, -1.72689685, -1.77857740, -1.82203011, -1.86220079, -1.90283983, -1.94820479, }, + { 1.98732877, 1.97944528, 1.97179088, 1.96260549, 1.95038374, 1.93336114, 1.90719232, 1.86191415, }, + { 1.97260000, 1.96083160, 1.94982586, 1.93806164, 1.92516608, 1.91010199, 1.89232331, 1.87149812, + 1.84564818, 1.81358067, 1.77620070, 1.73265264, 1.67907855, 1.60959081, 1.50829650, 1.33120330, }, + { 1.90109110, 1.86482426, 1.83419671, 1.80168452, 1.76650116, 1.72816320, 1.68502700, 1.63738256, + 1.58501580, 1.51795181, 1.43679906, 1.33950585, 1.24176208, 1.12260729, 0.96749668, 0.74048265, }, + { 1.76943864, 1.67822463, 1.59946365, 1.53560582, 1.47470796, 1.41210167, 1.34509536, 1.27339507, + 1.19303814, 1.09765169, 0.98818722, 0.87239446, 0.74369172, 0.59768184, 0.43168630, 0.17977021, }, + { 1.43428349, 1.32038354, 1.21074086, 1.10577988, 1.00561746, 0.90335924, 0.80437489, 0.70709671, + 0.60427395, 0.49814048, 0.38509539, 0.27106800, 0.14407416, 0.00219910, -0.16725141, -0.36936085, }, + { 0.99895687, 0.84188166, 0.70753739, 0.57906595, 0.47055563, 0.36966965, 0.26826648, 0.17163380, + 0.07208392, -0.03062936, -1.40037388, -0.25128968, -0.37213937, -0.51075646, -0.64887512, -0.80308031, }, + { 0.26515280, 0.06313551, -0.08872080, -0.21103548, -0.31069678, -0.39680323, -0.47223474, -0.54167135, + -0.61444740, -0.68943343, -0.76580211, -0.85170082, -0.95289061, -1.06514703, -1.20510707, -1.37617746, }, + { -0.53940301, -0.73770929, -0.88424876, -1.01117930, -1.13389091, -1.26830073, -1.42041987, -1.62033919, + -1.10158808, -1.16512566, -1.23337128, -1.30414401, -1.37663312, -1.46853845, -1.57625798, -1.66893638, }, + { -0.38601997, -0.56009350, -0.66978483, -0.76028471, -0.83846064, -0.90868087, -0.97408881, -1.03694962, }, + { -1.56144989, -1.65944032, -1.72689685, -1.77857740, -1.82203011, -1.86220079, -1.90283983, -1.94820479, }, }; static const uint32_t coef0_huffcodes[666] = { - 0x00258, 0x0003d, 0x00000, 0x00005, 0x00008, 0x00008, 0x0000c, 0x0001b, - 0x0001f, 0x00015, 0x00024, 0x00032, 0x0003a, 0x00026, 0x0002c, 0x0002f, - 0x0004a, 0x0004d, 0x00061, 0x00070, 0x00073, 0x00048, 0x00052, 0x0005a, - 0x0005d, 0x0006e, 0x00099, 0x0009e, 0x000c1, 0x000ce, 0x000e4, 0x000f0, - 0x00093, 0x0009e, 0x000a2, 0x000a1, 0x000b8, 0x000d2, 0x000d3, 0x0012e, - 0x00130, 0x000de, 0x0012d, 0x0019b, 0x001e4, 0x00139, 0x0013a, 0x0013f, - 0x0014f, 0x0016d, 0x001a2, 0x0027c, 0x0027e, 0x00332, 0x0033c, 0x0033f, - 0x0038b, 0x00396, 0x003c5, 0x00270, 0x0027c, 0x0025a, 0x00395, 0x00248, - 0x004bd, 0x004fb, 0x00662, 0x00661, 0x0071b, 0x004e6, 0x004ff, 0x00666, - 0x0071c, 0x0071a, 0x0071f, 0x00794, 0x00536, 0x004e2, 0x0078e, 0x004ee, - 0x00518, 0x00535, 0x004fb, 0x0078d, 0x00530, 0x00680, 0x0068f, 0x005cb, - 0x00965, 0x006a6, 0x00967, 0x0097f, 0x00682, 0x006ae, 0x00cd0, 0x00e28, - 0x00f13, 0x00f1f, 0x009f5, 0x00cd3, 0x00f11, 0x00926, 0x00964, 0x00f32, - 0x00f12, 0x00f30, 0x00966, 0x00d0b, 0x00a68, 0x00b91, 0x009c7, 0x00b73, - 0x012fa, 0x0131d, 0x013f9, 0x01ca0, 0x0199c, 0x01c7a, 0x0198c, 0x01248, - 0x01c74, 0x01c64, 0x0139e, 0x012fd, 0x00a77, 0x012fc, 0x01c7b, 0x012ca, - 0x014cc, 0x014d2, 0x014e3, 0x014dc, 0x012dc, 0x03344, 0x02598, 0x0263c, - 0x0333b, 0x025e6, 0x01a1c, 0x01e3c, 0x014e2, 0x033d4, 0x01a11, 0x03349, - 0x03cce, 0x014e1, 0x01a34, 0x0273e, 0x02627, 0x0273f, 0x038ee, 0x03971, - 0x03c67, 0x03c61, 0x0333d, 0x038c2, 0x0263f, 0x038cd, 0x02638, 0x02e41, - 0x0351f, 0x03348, 0x03c66, 0x03562, 0x02989, 0x027d5, 0x0333c, 0x02e4f, - 0x0343b, 0x02ddf, 0x04bc8, 0x029c0, 0x02e57, 0x04c72, 0x025b7, 0x03547, - 0x03540, 0x029d3, 0x04c45, 0x025bb, 0x06600, 0x04c73, 0x04bce, 0x0357b, - 0x029a6, 0x029d2, 0x0263e, 0x0298a, 0x07183, 0x06602, 0x07958, 0x04b66, - 0x0537d, 0x05375, 0x04fe9, 0x04b67, 0x0799f, 0x04bc9, 0x051fe, 0x06a3b, - 0x05bb6, 0x04fa8, 0x0728f, 0x05376, 0x0492c, 0x0537e, 0x0795a, 0x06a3c, - 0x0e515, 0x07887, 0x0683a, 0x051f9, 0x051fd, 0x0cc6a, 0x06a8a, 0x0cc6d, - 0x05bb3, 0x0683b, 0x051fc, 0x05378, 0x0728e, 0x07886, 0x05bb7, 0x0f2a4, - 0x0795b, 0x0683c, 0x09fc1, 0x0683d, 0x0b752, 0x09678, 0x0a3e8, 0x06ac7, - 0x051f0, 0x0b759, 0x06af3, 0x04b6b, 0x0f2a0, 0x0f2ad, 0x096c3, 0x0e518, - 0x0b75c, 0x0d458, 0x0cc6b, 0x0537c, 0x067aa, 0x04fea, 0x0343a, 0x0cc71, - 0x0967f, 0x09fc4, 0x096c2, 0x0e516, 0x0f2a1, 0x0d45c, 0x0d45d, 0x0d45e, - 0x12fb9, 0x0967e, 0x1982f, 0x09883, 0x096c4, 0x0b753, 0x12fb8, 0x0f2a8, - 0x1ca21, 0x096c5, 0x0e51a, 0x1ca27, 0x12f3c, 0x0d471, 0x0f2aa, 0x0b75b, - 0x12fbb, 0x0f2a9, 0x0f2ac, 0x0d45a, 0x0b74f, 0x096c8, 0x16e91, 0x096ca, - 0x12fbf, 0x0d0a7, 0x13103, 0x0d516, 0x16e99, 0x12cbd, 0x0a3ea, 0x19829, - 0x0b755, 0x29ba7, 0x1ca28, 0x29ba5, 0x16e93, 0x1982c, 0x19828, 0x25994, - 0x0a3eb, 0x1ca29, 0x16e90, 0x1ca25, 0x1982d, 0x1ca26, 0x16e9b, 0x0b756, - 0x0967c, 0x25997, 0x0b75f, 0x198d3, 0x0b757, 0x19a2a, 0x0d45b, 0x0e517, - 0x1ca24, 0x1ca23, 0x1ca22, 0x0b758, 0x16e97, 0x0cd14, 0x13100, 0x00007, - 0x0003b, 0x0006b, 0x00097, 0x00138, 0x00125, 0x00173, 0x00258, 0x00335, - 0x0028e, 0x004c6, 0x00715, 0x00729, 0x004ef, 0x00519, 0x004ed, 0x00532, - 0x0068c, 0x00686, 0x00978, 0x00e5d, 0x00e31, 0x009f4, 0x00b92, 0x012f8, - 0x00d06, 0x00a67, 0x00d44, 0x00a76, 0x00d59, 0x012cd, 0x01c78, 0x01c75, - 0x0199f, 0x0198f, 0x01c67, 0x014c6, 0x01c79, 0x01c76, 0x00b94, 0x00d1b, - 0x01e32, 0x01e31, 0x01ab0, 0x01a05, 0x01aa1, 0x0333a, 0x025e5, 0x02626, - 0x03541, 0x03544, 0x03421, 0x03546, 0x02e55, 0x02e56, 0x0492d, 0x02dde, - 0x0299b, 0x02ddc, 0x0357a, 0x0249c, 0x0668b, 0x1c77f, 0x1ca20, 0x0d45f, - 0x09886, 0x16e9a, 0x0f2a7, 0x0b751, 0x0a3ee, 0x0cf59, 0x0cf57, 0x0b754, - 0x0d0a6, 0x16e98, 0x0b760, 0x06ac6, 0x0a3f0, 0x12fbe, 0x13104, 0x0f2a5, - 0x0a3ef, 0x0d472, 0x12cba, 0x1982e, 0x16e9c, 0x1c77e, 0x198d0, 0x13105, - 0x16e92, 0x0b75d, 0x0d459, 0x0001a, 0x000c0, 0x0016c, 0x003cd, 0x00350, - 0x0067b, 0x0051e, 0x006a9, 0x009f4, 0x00b72, 0x00d09, 0x01249, 0x01e3d, - 0x01ca1, 0x01a1f, 0x01721, 0x01a8a, 0x016e8, 0x03347, 0x01a35, 0x0249d, - 0x0299a, 0x02596, 0x02e4e, 0x0298b, 0x07182, 0x04c46, 0x025ba, 0x02e40, - 0x027d6, 0x04fe8, 0x06607, 0x05310, 0x09884, 0x072e1, 0x06a3d, 0x04b6a, - 0x04c7a, 0x06603, 0x04c7b, 0x03428, 0x06605, 0x09664, 0x09fc0, 0x071de, - 0x06601, 0x05bb2, 0x09885, 0x0a3e2, 0x1c61f, 0x12cbb, 0x0b750, 0x0cf58, - 0x0967d, 0x25995, 0x668ad, 0x0b75a, 0x09fc2, 0x0537f, 0x0b75e, 0x13fae, - 0x12fbc, 0x00031, 0x001c4, 0x004c5, 0x005b8, 0x00cf4, 0x0096f, 0x00d46, - 0x01e57, 0x01a04, 0x02625, 0x03346, 0x028f9, 0x04c47, 0x072e0, 0x04b69, - 0x03420, 0x07957, 0x06639, 0x0799e, 0x07959, 0x07881, 0x04b68, 0x09fc3, - 0x09fd6, 0x0cc70, 0x0a3f1, 0x12cbe, 0x0e30e, 0x0e51b, 0x06af2, 0x12cbc, - 0x1c77d, 0x0f2ab, 0x12fbd, 0x1aa2f, 0x0a3ec, 0x0d473, 0x05377, 0x0a3e9, - 0x1982b, 0x0e300, 0x12f3f, 0x0cf5f, 0x096c0, 0x38c3c, 0x16e94, 0x16e95, - 0x12f3d, 0x29ba4, 0x29ba6, 0x1c77c, 0x6a8ba, 0x3545c, 0x33457, 0x668ac, - 0x6a8bb, 0x16e9d, 0x0e519, 0x25996, 0x12f3e, 0x00036, 0x0033e, 0x006ad, - 0x00d03, 0x012c8, 0x0124a, 0x03c42, 0x03ccd, 0x06606, 0x07880, 0x06852, - 0x06a3a, 0x05bb4, 0x0f2a2, 0x09fc7, 0x12cb9, 0x0cc6c, 0x0a6e8, 0x096c1, - 0x0004a, 0x00355, 0x012f9, 0x014e8, 0x01abe, 0x025b6, 0x0492e, 0x09fc6, - 0x051ff, 0x0cc6f, 0x096cb, 0x0d071, 0x198d1, 0x12cb8, 0x38c3d, 0x13faf, - 0x096c9, 0x0009d, 0x00539, 0x012ce, 0x0341f, 0x029c1, 0x04b33, 0x0a3e3, - 0x0d070, 0x16e96, 0x0b763, 0x000a0, 0x009ce, 0x038cc, 0x0343d, 0x051fa, - 0x09888, 0x12fba, 0x000df, 0x00a75, 0x029a7, 0x09fc5, 0x0e301, 0x0967b, - 0x001e7, 0x012c9, 0x051fb, 0x09889, 0x0f2a6, 0x0016f, 0x01cb9, 0x0cf5a, - 0x12cbf, 0x09679, 0x00272, 0x01a15, 0x0967a, 0x003cb, 0x025f6, 0x0b762, - 0x0028d, 0x03c60, 0x0cf5e, 0x00352, 0x03ccc, 0x0072f, 0x07186, 0x004ec, - 0x05379, 0x0068e, 0x09887, 0x006a7, 0x06af1, 0x00e29, 0x0cf5b, 0x00f31, - 0x0d470, 0x009c6, 0x013fb, 0x13102, 0x019a5, 0x13101, 0x01983, 0x01c65, - 0x0124f, 0x014c7, 0x01726, 0x01abf, 0x03304, 0x02624, 0x03c41, 0x027d7, - 0x02ddd, 0x02e54, 0x0343c, 0x06604, 0x07181, 0x0663a, 0x04fa9, 0x0663b, - 0x05311, 0x0537a, 0x06839, 0x05bb5, 0x0492f, 0x06af0, 0x096c7, 0x0cc6e, - 0x0537b, 0x0cf5c, 0x0cf56, 0x198d2, 0x0cf5d, 0x0a3ed, 0x0f2a3, 0x1982a, - 0x0b761, 0x096c6, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 214, 72, 42, 40, 18, 4, 4, 2, + 2, 2, 2, 2, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, }; static const CoefVLCTable coef_vlcs[6] = { - { - sizeof(coef0_huffbits), sizeof(levels0)/2, coef0_huffcodes, coef0_huffbits, levels0, - }, - { - sizeof(coef1_huffbits), sizeof(levels1)/2, coef1_huffcodes, coef1_huffbits, levels1, - }, - { - sizeof(coef2_huffbits), sizeof(levels2)/2, coef2_huffcodes, coef2_huffbits, levels2, - }, - { - sizeof(coef3_huffbits), sizeof(levels3)/2, coef3_huffcodes, coef3_huffbits, levels3, - }, - { - sizeof(coef4_huffbits), sizeof(levels4)/2, coef4_huffcodes, coef4_huffbits, levels4, - }, - { - sizeof(coef5_huffbits), sizeof(levels5)/2, coef5_huffcodes, coef5_huffbits, levels5, - }, + { sizeof(coef0_huffbits), sizeof(levels0) / 2, coef0_huffcodes, coef0_huffbits, levels0, }, + { sizeof(coef1_huffbits), sizeof(levels1) / 2, coef1_huffcodes, coef1_huffbits, levels1, }, + { sizeof(coef2_huffbits), sizeof(levels2) / 2, coef2_huffcodes, coef2_huffbits, levels2, }, + { sizeof(coef3_huffbits), sizeof(levels3) / 2, coef3_huffcodes, coef3_huffbits, levels3, }, + { sizeof(coef4_huffbits), sizeof(levels4) / 2, coef4_huffcodes, coef4_huffbits, levels4, }, + { sizeof(coef5_huffbits), sizeof(levels5) / 2, coef5_huffcodes, coef5_huffbits, levels5, }, }; #endif /* AVCODEC_WMADATA_H */ diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 2dd5898..50c77dd 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -34,40 +34,39 @@ */ #include "libavutil/attributes.h" + #include "avcodec.h" #include "internal.h" #include "wma.h" -#undef NDEBUG -#include - #define EXPVLCBITS 8 -#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS) +#define EXPMAX ((19 + EXPVLCBITS - 1) / EXPVLCBITS) #define HGAINVLCBITS 9 -#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS) +#define HGAINMAX ((13 + HGAINVLCBITS - 1) / HGAINVLCBITS) static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len); #ifdef TRACE -static void dump_floats(WMACodecContext *s, const char *name, int prec, const float *tab, int n) +static void dump_floats(WMACodecContext *s, const char *name, + int prec, const float *tab, int n) { int i; - tprintf(s->avctx, "%s[%d]:\n", name, n); - for(i=0;iavctx, "%s[%d]:\n", name, n); + for (i = 0; i < n; i++) { if ((i & 7) == 0) - tprintf(s->avctx, "%4d: ", i); - tprintf(s->avctx, " %8.*f", prec, tab[i]); + ff_tlog(s->avctx, "%4d: ", i); + ff_tlog(s->avctx, " %8.*f", prec, tab[i]); if ((i & 7) == 7) - tprintf(s->avctx, "\n"); + ff_tlog(s->avctx, "\n"); } if ((i & 7) != 0) - tprintf(s->avctx, "\n"); + ff_tlog(s->avctx, "\n"); } -#endif +#endif /* TRACE */ -static av_cold int wma_decode_init(AVCodecContext * avctx) +static av_cold int wma_decode_init(AVCodecContext *avctx) { WMACodecContext *s = avctx->priv_data; int i, flags2; @@ -80,24 +79,23 @@ static av_cold int wma_decode_init(AVCodecContext * avctx) s->avctx = avctx; - /* extract flag infos */ - flags2 = 0; + /* extract flag info */ + flags2 = 0; extradata = avctx->extradata; - if (avctx->codec->id == AV_CODEC_ID_WMAV1 && avctx->extradata_size >= 4) { - flags2 = AV_RL16(extradata+2); - } else if (avctx->codec->id == AV_CODEC_ID_WMAV2 && avctx->extradata_size >= 6) { - flags2 = AV_RL16(extradata+4); - } + if (avctx->codec->id == AV_CODEC_ID_WMAV1 && avctx->extradata_size >= 4) + flags2 = AV_RL16(extradata + 2); + else if (avctx->codec->id == AV_CODEC_ID_WMAV2 && avctx->extradata_size >= 6) + flags2 = AV_RL16(extradata + 4); - s->use_exp_vlc = flags2 & 0x0001; - s->use_bit_reservoir = flags2 & 0x0002; + s->use_exp_vlc = flags2 & 0x0001; + s->use_bit_reservoir = flags2 & 0x0002; s->use_variable_block_len = flags2 & 0x0004; - if(ff_wma_init(avctx, flags2)<0) + if (ff_wma_init(avctx, flags2) < 0) return -1; /* init MDCT */ - for(i = 0; i < s->nb_block_sizes; i++) + for (i = 0; i < s->nb_block_sizes; i++) ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1, 1.0 / 32768.0); if (s->use_noise_coding) { @@ -106,13 +104,12 @@ static av_cold int wma_decode_init(AVCodecContext * avctx) ff_wma_hgain_huffcodes, 2, 2, 0); } - if (s->use_exp_vlc) { - init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_aac_scalefactor_bits), //FIXME move out of context + if (s->use_exp_vlc) + init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_aac_scalefactor_bits), // FIXME move out of context ff_aac_scalefactor_bits, 1, 1, ff_aac_scalefactor_code, 4, 4, 0); - } else { + else wma_lsp_to_curve_init(s, s->frame_len); - } avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; @@ -135,12 +132,12 @@ static inline float pow_m1_4(WMACodecContext *s, float x) float a, b; u.f = x; - e = u.v >> 23; - m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1); + 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]; + 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); } @@ -150,25 +147,25 @@ static av_cold void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) int i, e, m; wdel = M_PI / frame_len; - for(i=0;ilsp_cos_table[i] = 2.0f * cos(wdel * i); /* tables for x^-0.25 computation */ - for(i=0;i<256;i++) { - e = i - 126; + 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 */ + * 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); + 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; + b = a; } } @@ -176,26 +173,25 @@ static av_cold void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) * NOTE: We use the same code as Vorbis here * @todo optimize it further with SSE/3Dnow */ -static void wma_lsp_to_curve(WMACodecContext *s, - float *out, float *val_max_ptr, +static void wma_lsp_to_curve(WMACodecContext *s, float *out, float *val_max_ptr, int n, float *lsp) { int i, j; float p, q, w, v, val_max; val_max = 0; - for(i=0;ilsp_cos_table[i]; - for(j=1;j val_max) val_max = v; out[i] = v; @@ -211,7 +207,7 @@ static void decode_exp_lsp(WMACodecContext *s, int ch) float lsp_coefs[NB_LSP_COEFS]; int val, i; - for(i = 0; i < NB_LSP_COEFS; i++) { + for (i = 0; i < NB_LSP_COEFS; i++) { if (i == 0 || i >= 8) val = get_bits(&s->gb, 3); else @@ -315,41 +311,41 @@ static int decode_exp_vlc(WMACodecContext *s, int ch) float v, max_scale; uint32_t *q, *q_end, iv; const float *ptab = pow_tab + 60; - const uint32_t *iptab = (const uint32_t*)ptab; + const uint32_t *iptab = (const uint32_t *) ptab; - ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; - q = (uint32_t *)s->exponents[ch]; - q_end = q + s->block_len; + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = (uint32_t *) s->exponents[ch]; + q_end = q + s->block_len; max_scale = 0; if (s->version == 1) { - last_exp = get_bits(&s->gb, 5) + 10; - v = ptab[last_exp]; - iv = iptab[last_exp]; + last_exp = get_bits(&s->gb, 5) + 10; + v = ptab[last_exp]; + iv = iptab[last_exp]; max_scale = v; - n = *ptr++; + n = *ptr++; switch (n & 3) do { case 0: *q++ = iv; case 3: *q++ = iv; case 2: *q++ = iv; case 1: *q++ = iv; } while ((n -= 4) > 0); - }else + } else last_exp = 36; while (q < q_end) { code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX); - if (code < 0){ + if (code < 0) { av_log(s->avctx, AV_LOG_ERROR, "Exponent vlc invalid\n"); return -1; } - /* NOTE: this offset is the same as MPEG4 AAC ! */ + /* NOTE: this offset is the same as MPEG-4 AAC! */ last_exp += code - 60; - if ((unsigned)last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) { + if ((unsigned) last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) { av_log(s->avctx, AV_LOG_ERROR, "Exponent out of range: %d\n", last_exp); return -1; } - v = ptab[last_exp]; + v = ptab[last_exp]; iv = iptab[last_exp]; if (v > max_scale) max_scale = v; @@ -365,7 +361,6 @@ static int decode_exp_vlc(WMACodecContext *s, int ch) return 0; } - /** * Apply MDCT window and add into output. * @@ -380,49 +375,47 @@ static void wma_window(WMACodecContext *s, float *out) /* left part */ if (s->block_len_bits <= s->prev_block_len_bits) { block_len = s->block_len; - bsize = s->frame_len_bits - s->block_len_bits; + bsize = s->frame_len_bits - s->block_len_bits; s->fdsp.vector_fmul_add(out, in, s->windows[bsize], out, block_len); - } else { block_len = 1 << s->prev_block_len_bits; - n = (s->block_len - block_len) / 2; - bsize = s->frame_len_bits - s->prev_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->prev_block_len_bits; - s->fdsp.vector_fmul_add(out+n, in+n, s->windows[bsize], - out+n, block_len); + s->fdsp.vector_fmul_add(out + n, in + n, s->windows[bsize], + out + n, block_len); - memcpy(out+n+block_len, in+n+block_len, n*sizeof(float)); + memcpy(out + n + block_len, in + n + block_len, n * sizeof(float)); } out += s->block_len; - in += s->block_len; + in += s->block_len; /* right part */ if (s->block_len_bits <= s->next_block_len_bits) { block_len = s->block_len; - bsize = s->frame_len_bits - s->block_len_bits; + bsize = s->frame_len_bits - s->block_len_bits; s->fdsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len); - } else { block_len = 1 << s->next_block_len_bits; - n = (s->block_len - block_len) / 2; - bsize = s->frame_len_bits - s->next_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->next_block_len_bits; - memcpy(out, in, n*sizeof(float)); + memcpy(out, in, n * sizeof(float)); - s->fdsp.vector_fmul_reverse(out+n, in+n, s->windows[bsize], block_len); + s->fdsp.vector_fmul_reverse(out + n, in + n, s->windows[bsize], + block_len); - memset(out+n+block_len, 0, n*sizeof(float)); + memset(out + n + block_len, 0, n * sizeof(float)); } } - /** * @return 0 if OK. 1 if last block of frame. return -1 if - * unrecorrable error. + * unrecoverable error. */ static int wma_decode_block(WMACodecContext *s) { @@ -433,8 +426,9 @@ static int wma_decode_block(WMACodecContext *s) FFTContext *mdct; #ifdef TRACE - tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); -#endif + ff_tlog(s->avctx, "***decode_block: %d:%d\n", + s->frame_count - 1, s->block_num); +#endif /* TRACE */ /* compute current block length */ if (s->use_variable_block_len) { @@ -442,26 +436,32 @@ static int wma_decode_block(WMACodecContext *s) if (s->reset_block_lengths) { s->reset_block_lengths = 0; - v = get_bits(&s->gb, n); - if (v >= s->nb_block_sizes){ - av_log(s->avctx, AV_LOG_ERROR, "prev_block_len_bits %d out of range\n", s->frame_len_bits - v); + v = get_bits(&s->gb, n); + if (v >= s->nb_block_sizes) { + av_log(s->avctx, AV_LOG_ERROR, + "prev_block_len_bits %d out of range\n", + s->frame_len_bits - v); return -1; } s->prev_block_len_bits = s->frame_len_bits - v; - v = get_bits(&s->gb, n); - if (v >= s->nb_block_sizes){ - av_log(s->avctx, AV_LOG_ERROR, "block_len_bits %d out of range\n", s->frame_len_bits - v); + v = get_bits(&s->gb, n); + if (v >= s->nb_block_sizes) { + av_log(s->avctx, AV_LOG_ERROR, + "block_len_bits %d out of range\n", + s->frame_len_bits - v); return -1; } s->block_len_bits = s->frame_len_bits - v; } else { /* update block lengths */ s->prev_block_len_bits = s->block_len_bits; - s->block_len_bits = s->next_block_len_bits; + s->block_len_bits = s->next_block_len_bits; } v = get_bits(&s->gb, n); - if (v >= s->nb_block_sizes){ - av_log(s->avctx, AV_LOG_ERROR, "next_block_len_bits %d out of range\n", s->frame_len_bits - v); + if (v >= s->nb_block_sizes) { + av_log(s->avctx, AV_LOG_ERROR, + "next_block_len_bits %d out of range\n", + s->frame_len_bits - v); return -1; } s->next_block_len_bits = s->frame_len_bits - v; @@ -469,24 +469,23 @@ static int wma_decode_block(WMACodecContext *s) /* fixed block len */ s->next_block_len_bits = s->frame_len_bits; s->prev_block_len_bits = s->frame_len_bits; - s->block_len_bits = s->frame_len_bits; + s->block_len_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){ + if ((s->block_pos + s->block_len) > s->frame_len) { av_log(s->avctx, AV_LOG_ERROR, "frame_len overflow\n"); return -1; } - if (s->avctx->channels == 2) { + if (s->avctx->channels == 2) s->ms_stereo = get_bits1(&s->gb); - } v = 0; - for(ch = 0; ch < s->avctx->channels; ch++) { - a = get_bits1(&s->gb); + for (ch = 0; ch < s->avctx->channels; ch++) { + a = get_bits1(&s->gb); s->channel_coded[ch] = a; - v |= a; + v |= a; } bsize = s->frame_len_bits - s->block_len_bits; @@ -497,31 +496,30 @@ static int wma_decode_block(WMACodecContext *s) goto next; /* read total gain and extract corresponding number of bits for - coef escape coding */ + * coef escape coding */ total_gain = 1; - for(;;) { - a = get_bits(&s->gb, 7); + for (;;) { + a = get_bits(&s->gb, 7); total_gain += a; if (a != 127) break; } - coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); + coef_nb_bits = ff_wma_total_gain_to_bits(total_gain); /* compute number of coefficients */ n = s->coefs_end[bsize] - s->coefs_start; - for(ch = 0; ch < s->avctx->channels; ch++) + for (ch = 0; ch < s->avctx->channels; ch++) nb_coefs[ch] = n; /* complex coding */ if (s->use_noise_coding) { - - for(ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { int i, n, a; n = s->exponent_high_sizes[bsize]; - for(i=0;igb); + for (i = 0; i < n; i++) { + a = get_bits1(&s->gb); s->high_band_coded[ch][i] = a; /* if noise coding, the coefficients are not transmitted */ if (a) @@ -529,20 +527,22 @@ static int wma_decode_block(WMACodecContext *s) } } } - for(ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { int i, n, val, code; - n = s->exponent_high_sizes[bsize]; - val = (int)0x80000000; - for(i=0;iexponent_high_sizes[bsize]; + val = (int) 0x80000000; + for (i = 0; i < n; i++) { if (s->high_band_coded[ch][i]) { - if (val == (int)0x80000000) { + if (val == (int) 0x80000000) { val = get_bits(&s->gb, 7) - 19; } else { - code = get_vlc2(&s->gb, s->hgain_vlc.table, HGAINVLCBITS, HGAINMAX); - if (code < 0){ - av_log(s->avctx, AV_LOG_ERROR, "hgain vlc invalid\n"); + code = get_vlc2(&s->gb, s->hgain_vlc.table, + HGAINVLCBITS, HGAINMAX); + if (code < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "hgain vlc invalid\n"); return -1; } val += code - 18; @@ -555,9 +555,8 @@ static int wma_decode_block(WMACodecContext *s) } /* exponents can be reused in short blocks. */ - if ((s->block_len_bits == s->frame_len_bits) || - get_bits1(&s->gb)) { - for(ch = 0; ch < s->avctx->channels; ch++) { + if ((s->block_len_bits == s->frame_len_bits) || get_bits1(&s->gb)) { + for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { if (decode_exp_vlc(s, ch) < 0) @@ -574,29 +573,27 @@ static int wma_decode_block(WMACodecContext *s) for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { int tindex; - WMACoef* ptr = &s->coefs1[ch][0]; + WMACoef *ptr = &s->coefs1[ch][0]; /* special VLC tables are used for ms stereo because - there is potentially less energy there */ + * there is potentially less energy there */ tindex = (ch == 1 && s->ms_stereo); memset(ptr, 0, s->block_len * sizeof(WMACoef)); ff_wma_run_level_decode(s->avctx, &s->gb, &s->coef_vlc[tindex], - s->level_table[tindex], s->run_table[tindex], - 0, ptr, 0, nb_coefs[ch], - s->block_len, s->frame_len_bits, coef_nb_bits); + s->level_table[tindex], s->run_table[tindex], + 0, ptr, 0, nb_coefs[ch], + s->block_len, s->frame_len_bits, coef_nb_bits); } - if (s->version == 1 && s->avctx->channels >= 2) { + if (s->version == 1 && s->avctx->channels >= 2) align_get_bits(&s->gb); - } } /* normalize */ { int n4 = s->block_len / 2; - mdct_norm = 1.0 / (float)n4; - if (s->version == 1) { + mdct_norm = 1.0 / (float) n4; + if (s->version == 1) mdct_norm *= sqrt(n4); - } } /* finally compute the MDCT coefficients */ @@ -607,97 +604,94 @@ static int wma_decode_block(WMACodecContext *s) int i, j, n, n1, last_high_band, esize; float exp_power[HIGH_BAND_MAX_SIZE]; - coefs1 = s->coefs1[ch]; + coefs1 = s->coefs1[ch]; exponents = s->exponents[ch]; - esize = s->exponents_bsize[ch]; - mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; - mult *= mdct_norm; - coefs = s->coefs[ch]; + esize = s->exponents_bsize[ch]; + mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; + mult *= mdct_norm; + coefs = s->coefs[ch]; if (s->use_noise_coding) { mult1 = mult; /* very low freqs : noise */ - for(i = 0;i < s->coefs_start; i++) { + for (i = 0; i < s->coefs_start; i++) { *coefs++ = s->noise_table[s->noise_index] * - exponents[i<>esize] * mult1; - s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); + exponents[i << bsize >> esize] * mult1; + s->noise_index = (s->noise_index + 1) & + (NOISE_TAB_SIZE - 1); } n1 = s->exponent_high_sizes[bsize]; /* compute power of high bands */ exponents = s->exponents[ch] + - (s->high_band_start[bsize]<>esize); + (s->high_band_start[bsize] << bsize >> esize); last_high_band = 0; /* avoid warning */ - for(j=0;jexponent_high_bands[s->frame_len_bits - - s->block_len_bits][j]; + s->block_len_bits][j]; if (s->high_band_coded[ch][j]) { float e2, v; e2 = 0; - for(i = 0;i < n; i++) { - v = exponents[i<>esize]; + for (i = 0; i < n; i++) { + v = exponents[i << bsize >> esize]; e2 += v * v; } - exp_power[j] = e2 / n; + exp_power[j] = e2 / n; last_high_band = j; - tprintf(s->avctx, "%d: power=%f (%d)\n", j, exp_power[j], n); + ff_tlog(s->avctx, "%d: power=%f (%d)\n", j, exp_power[j], n); } - exponents += n<>esize; + exponents += n << bsize >> esize; } /* main freqs and high freqs */ - exponents = s->exponents[ch] + (s->coefs_start<>esize); - for(j=-1;jhigh_band_start[bsize] - - s->coefs_start; - } else { + exponents = s->exponents[ch] + (s->coefs_start << bsize >> esize); + 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]; - } + 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 = 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]; + for (i = 0; i < n; i++) { + noise = s->noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); - *coefs++ = noise * - exponents[i<>esize] * mult1; + *coefs++ = noise * exponents[i << bsize >> esize] * mult1; } - exponents += n<>esize; + exponents += n << bsize >> esize; } else { /* coded values + small noise */ - for(i = 0;i < n; i++) { - noise = s->noise_table[s->noise_index]; + for (i = 0; i < n; i++) { + noise = s->noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); - *coefs++ = ((*coefs1++) + noise) * - exponents[i<>esize] * mult; + *coefs++ = ((*coefs1++) + noise) * + exponents[i << bsize >> esize] * mult; } - exponents += n<>esize; + exponents += n << bsize >> esize; } } /* very high freqs : noise */ - n = s->block_len - s->coefs_end[bsize]; - mult1 = mult * exponents[((-1<>esize]; - for(i = 0; i < n; i++) { - *coefs++ = s->noise_table[s->noise_index] * mult1; + n = s->block_len - s->coefs_end[bsize]; + mult1 = mult * exponents[((-1 << bsize)) >> esize]; + for (i = 0; i < n; i++) { + *coefs++ = s->noise_table[s->noise_index] * mult1; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); } } else { /* XXX: optimize more */ - for(i = 0;i < s->coefs_start; i++) + for (i = 0; i < s->coefs_start; i++) *coefs++ = 0.0; n = nb_coefs[ch]; - for(i = 0;i < n; i++) { - *coefs++ = coefs1[i] * exponents[i<>esize] * mult; - } + for (i = 0; i < n; i++) + *coefs++ = coefs1[i] * exponents[i << bsize >> esize] * mult; n = s->block_len - s->coefs_end[bsize]; - for(i = 0;i < n; i++) + for (i = 0; i < n; i++) *coefs++ = 0.0; } } @@ -710,14 +704,14 @@ static int wma_decode_block(WMACodecContext *s) dump_floats(s, "coefs", 1, s->coefs[ch], s->block_len); } } -#endif +#endif /* TRACE */ if (s->ms_stereo && s->channel_coded[1]) { /* nominal case for ms stereo: we do it before mdct */ /* no need to optimize this case because it should almost - never happen */ + * never happen */ if (!s->channel_coded[0]) { - tprintf(s->avctx, "rare ms-stereo case happened\n"); + ff_tlog(s->avctx, "rare ms-stereo case happened\n"); memset(s->coefs[0], 0, sizeof(float) * s->block_len); s->channel_coded[0] = 1; } @@ -732,9 +726,9 @@ next: int n4, index; n4 = s->block_len / 2; - if(s->channel_coded[ch]){ + if (s->channel_coded[ch]) mdct->imdct_calc(mdct, s->output, s->coefs[ch]); - }else if(!(s->ms_stereo && ch==1)) + else if (!(s->ms_stereo && ch == 1)) memset(s->output, 0, sizeof(s->output)); /* multiply by the window and add in the frame */ @@ -758,13 +752,14 @@ static int wma_decode_frame(WMACodecContext *s, float **samples, int ret, ch; #ifdef TRACE - tprintf(s->avctx, "***decode_frame: %d size=%d\n", s->frame_count++, s->frame_len); -#endif + ff_tlog(s->avctx, "***decode_frame: %d size=%d\n", + s->frame_count++, s->frame_len); +#endif /* TRACE */ /* read each block */ s->block_num = 0; s->block_pos = 0; - for(;;) { + for (;;) { ret = wma_decode_block(s); if (ret < 0) return -1; @@ -781,8 +776,9 @@ static int wma_decode_frame(WMACodecContext *s, float **samples, s->frame_len * sizeof(*s->frame_out[ch])); #ifdef TRACE - dump_floats(s, "samples", 6, samples[ch] + samples_offset, s->frame_len); -#endif + dump_floats(s, "samples", 6, samples[ch] + samples_offset, + s->frame_len); +#endif /* TRACE */ } return 0; @@ -791,18 +787,18 @@ static int wma_decode_frame(WMACodecContext *s, float **samples, static int wma_decode_superframe(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; + AVFrame *frame = data; const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + int buf_size = avpkt->size; WMACodecContext *s = avctx->priv_data; int nb_frames, bit_offset, i, pos, len, ret; uint8_t *q; float **samples; int samples_offset; - tprintf(avctx, "***decode_superframe:\n"); + ff_tlog(avctx, "***decode_superframe:\n"); - if(buf_size==0){ + if (buf_size == 0) { s->last_superframe_len = 0; return 0; } @@ -814,15 +810,14 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, } buf_size = avctx->block_align; - init_get_bits(&s->gb, buf, buf_size*8); + init_get_bits(&s->gb, buf, buf_size * 8); if (s->use_bit_reservoir) { /* read super frame header */ skip_bits(&s->gb, 4); /* super frame index */ nb_frames = get_bits(&s->gb, 4) - (s->last_superframe_len <= 0); - } else { + } else nb_frames = 1; - } /* get output buffer */ frame->nb_samples = nb_frames * s->frame_len; @@ -830,7 +825,7 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - samples = (float **)frame->extended_data; + samples = (float **) frame->extended_data; samples_offset = 0; if (s->use_bit_reservoir) { @@ -847,24 +842,24 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, if ((s->last_superframe_len + ((bit_offset + 7) >> 3)) > MAX_CODED_SUPERFRAME_SIZE) goto fail; - q = s->last_superframe + s->last_superframe_len; + q = s->last_superframe + s->last_superframe_len; len = bit_offset; while (len > 7) { - *q++ = (get_bits)(&s->gb, 8); + *q++ = (get_bits) (&s->gb, 8); len -= 8; } - if (len > 0) { - *q++ = (get_bits)(&s->gb, len) << (8 - len); - } - memset(q, 0, FF_INPUT_BUFFER_PADDING_SIZE); + if (len > 0) + *q++ = (get_bits) (&s->gb, len) << (8 - len); + memset(q, 0, AV_INPUT_BUFFER_PADDING_SIZE); /* XXX: bit_offset bits into last frame */ - init_get_bits(&s->gb, s->last_superframe, s->last_superframe_len * 8 + bit_offset); + init_get_bits(&s->gb, s->last_superframe, + s->last_superframe_len * 8 + bit_offset); /* skip unused bits */ if (s->last_bitoffset > 0) skip_bits(&s->gb, s->last_bitoffset); /* this frame is stored in the last superframe and in the - current one */ + * current one */ if (wma_decode_frame(s, samples, samples_offset) < 0) goto fail; samples_offset += s->frame_len; @@ -875,23 +870,24 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, pos = bit_offset + 4 + 4 + s->byte_offset_bits + 3; if (pos >= MAX_CODED_SUPERFRAME_SIZE * 8 || pos > buf_size * 8) return AVERROR_INVALIDDATA; - init_get_bits(&s->gb, buf + (pos >> 3), (buf_size - (pos >> 3))*8); + init_get_bits(&s->gb, buf + (pos >> 3), (buf_size - (pos >> 3)) * 8); len = pos & 7; if (len > 0) skip_bits(&s->gb, len); s->reset_block_lengths = 1; - for(i=0;iframe_len; } /* we copy the end of the frame in the last frame buffer */ - pos = get_bits_count(&s->gb) + ((bit_offset + 4 + 4 + s->byte_offset_bits + 3) & ~7); + 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; + pos >>= 3; + len = buf_size - pos; if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0) { av_log(s->avctx, AV_LOG_ERROR, "len %d invalid\n", len); goto fail; @@ -905,14 +901,15 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, samples_offset += s->frame_len; } - av_dlog(s->avctx, "%d %d %d %d outbytes:%td eaten:%d\n", + ff_dlog(s->avctx, "%d %d %d %d outbytes:%td eaten:%d\n", s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, - (int8_t *)samples - (int8_t *)data, avctx->block_align); + (int8_t *) samples - (int8_t *) data, avctx->block_align); *got_frame_ptr = 1; return avctx->block_align; - fail: + +fail: /* when error, we reset the bit reservoir */ s->last_superframe_len = 0; return -1; @@ -922,8 +919,8 @@ static av_cold void flush(AVCodecContext *avctx) { WMACodecContext *s = avctx->priv_data; - s->last_bitoffset= - s->last_superframe_len= 0; + s->last_bitoffset = + s->last_superframe_len = 0; } AVCodec ff_wmav1_decoder = { @@ -936,7 +933,7 @@ AVCodec ff_wmav1_decoder = { .close = ff_wma_end, .decode = wma_decode_superframe, .flush = flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; @@ -951,7 +948,7 @@ AVCodec ff_wmav2_decoder = { .close = ff_wma_end, .decode = wma_decode_superframe, .flush = flush, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c index 899cae0..800c000 100644 --- a/libavcodec/wmaenc.c +++ b/libavcodec/wmaenc.c @@ -20,6 +20,7 @@ */ #include "libavutil/attributes.h" + #include "avcodec.h" #include "internal.h" #include "wma.h" @@ -36,8 +37,9 @@ static av_cold int encode_init(AVCodecContext *avctx) s->avctx = avctx; - if(avctx->channels > MAX_CHANNELS) { - av_log(avctx, AV_LOG_ERROR, "too many channels: got %i, need %i or fewer", + if (avctx->channels > MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, + "too many channels: got %i, need %i or fewer", avctx->channels, MAX_CHANNELS); return AVERROR(EINVAL); } @@ -48,30 +50,36 @@ static av_cold int encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if(avctx->bit_rate < 24*1000) { - av_log(avctx, AV_LOG_ERROR, "bitrate too low: got %i, need 24000 or higher\n", + if (avctx->bit_rate < 24 * 1000) { + av_log(avctx, AV_LOG_ERROR, + "bitrate too low: got %i, need 24000 or higher\n", avctx->bit_rate); return AVERROR(EINVAL); } - /* extract flag infos */ + /* extract flag info */ flags1 = 0; flags2 = 1; if (avctx->codec->id == AV_CODEC_ID_WMAV1) { - extradata= av_malloc(4); - avctx->extradata_size= 4; + extradata = av_malloc(4); + if (!extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = 4; AV_WL16(extradata, flags1); - AV_WL16(extradata+2, flags2); + AV_WL16(extradata + 2, flags2); } else if (avctx->codec->id == AV_CODEC_ID_WMAV2) { - extradata= av_mallocz(10); - avctx->extradata_size= 10; + extradata = av_mallocz(10); + if (!extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = 10; AV_WL32(extradata, flags1); - AV_WL16(extradata+4, flags2); - }else + AV_WL16(extradata + 4, flags2); + } else { assert(0); - avctx->extradata= extradata; - s->use_exp_vlc = flags2 & 0x0001; - s->use_bit_reservoir = flags2 & 0x0002; + } + avctx->extradata = extradata; + s->use_exp_vlc = flags2 & 0x0001; + s->use_bit_reservoir = flags2 & 0x0002; s->use_variable_block_len = flags2 & 0x0004; if (avctx->channels == 2) s->ms_stereo = 1; @@ -79,57 +87,58 @@ static av_cold int encode_init(AVCodecContext *avctx) ff_wma_init(avctx, flags2); /* init MDCT */ - for(i = 0; i < s->nb_block_sizes; i++) + for (i = 0; i < s->nb_block_sizes; i++) ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 0, 1.0); - block_align = avctx->bit_rate * (int64_t)s->frame_len / + block_align = avctx->bit_rate * (int64_t) s->frame_len / (avctx->sample_rate * 8); block_align = FFMIN(block_align, MAX_CODED_SUPERFRAME_SIZE); avctx->block_align = block_align; avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate / s->frame_len; - avctx->frame_size = avctx->delay = s->frame_len; + avctx->frame_size = avctx->initial_padding = s->frame_len; return 0; } - -static void apply_window_and_mdct(AVCodecContext * avctx, const AVFrame *frame) +static void apply_window_and_mdct(AVCodecContext *avctx, const AVFrame *frame) { WMACodecContext *s = avctx->priv_data; - float **audio = (float **)frame->extended_data; + float **audio = (float **) frame->extended_data; int len = frame->nb_samples; - int window_index= s->frame_len_bits - s->block_len_bits; - FFTContext *mdct = &s->mdct_ctx[window_index]; + int window_index = s->frame_len_bits - s->block_len_bits; + FFTContext *mdct = &s->mdct_ctx[window_index]; int ch; - const float * win = s->windows[window_index]; - int window_len = 1 << s->block_len_bits; - float n = 2.0 * 32768.0 / window_len; + const float *win = s->windows[window_index]; + int window_len = 1 << s->block_len_bits; + float n = 2.0 * 32768.0 / window_len; for (ch = 0; ch < avctx->channels; ch++) { memcpy(s->output, s->frame_out[ch], window_len * sizeof(*s->output)); s->fdsp.vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len); - s->fdsp.vector_fmul_reverse(&s->output[window_len], s->frame_out[ch], win, len); + s->fdsp.vector_fmul_reverse(&s->output[window_len], s->frame_out[ch], + win, len); s->fdsp.vector_fmul(s->frame_out[ch], s->frame_out[ch], win, len); mdct->mdct_calc(mdct, s->coefs[ch], s->output); } } -//FIXME use for decoding too -static void init_exp(WMACodecContext *s, int ch, const int *exp_param){ +// FIXME use for decoding too +static void init_exp(WMACodecContext *s, int ch, const int *exp_param) +{ int n; const uint16_t *ptr; float v, *q, max_scale, *q_end; - ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; - q = s->exponents[ch]; - q_end = q + s->block_len; + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; + q_end = q + s->block_len; max_scale = 0; while (q < q_end) { /* XXX: use a table */ - v = pow(10, *exp_param++ * (1.0 / 16.0)); - max_scale= FFMAX(max_scale, v); - n = *ptr++; + v = pow(10, *exp_param++ *(1.0 / 16.0)); + max_scale = FFMAX(max_scale, v); + n = *ptr++; do { *q++ = v; } while (--n); @@ -137,73 +146,81 @@ static void init_exp(WMACodecContext *s, int ch, const int *exp_param){ s->max_exponent[ch] = max_scale; } -static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param){ +static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param) +{ int last_exp; const uint16_t *ptr; float *q, *q_end; - ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; - q = s->exponents[ch]; + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; q_end = q + s->block_len; if (s->version == 1) { - last_exp= *exp_param++; - assert(last_exp-10 >= 0 && last_exp-10 < 32); + last_exp = *exp_param++; + assert(last_exp - 10 >= 0 && last_exp - 10 < 32); put_bits(&s->pb, 5, last_exp - 10); - q+= *ptr++; - }else + q += *ptr++; + } else last_exp = 36; while (q < q_end) { - int exp = *exp_param++; + int exp = *exp_param++; int code = exp - last_exp + 60; assert(code >= 0 && code < 120); - put_bits(&s->pb, ff_aac_scalefactor_bits[code], ff_aac_scalefactor_code[code]); + put_bits(&s->pb, ff_aac_scalefactor_bits[code], + ff_aac_scalefactor_code[code]); /* XXX: use a table */ - q+= *ptr++; - last_exp= exp; + q += *ptr++; + last_exp = exp; } } -static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], int total_gain){ +static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], + int total_gain) +{ int v, bsize, ch, coef_nb_bits, parse_exponents; float mdct_norm; int nb_coefs[MAX_CHANNELS]; - static const int fixed_exp[25]={20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20}; - - //FIXME remove duplication relative to decoder + static const int fixed_exp[25] = { + 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20 + }; + + // FIXME remove duplication relative to decoder if (s->use_variable_block_len) { - assert(0); //FIXME not implemented - }else{ + assert(0); // FIXME not implemented + } else { /* fixed block len */ s->next_block_len_bits = s->frame_len_bits; s->prev_block_len_bits = s->frame_len_bits; - s->block_len_bits = s->frame_len_bits; + s->block_len_bits = s->frame_len_bits; } s->block_len = 1 << s->block_len_bits; // assert((s->block_pos + s->block_len) <= s->frame_len); bsize = s->frame_len_bits - s->block_len_bits; - //FIXME factor + // FIXME factor v = s->coefs_end[bsize] - s->coefs_start; for (ch = 0; ch < s->avctx->channels; ch++) nb_coefs[ch] = v; { int n4 = s->block_len / 2; - mdct_norm = 1.0 / (float)n4; - if (s->version == 1) { + mdct_norm = 1.0 / (float) n4; + if (s->version == 1) mdct_norm *= sqrt(n4); - } } - if (s->avctx->channels == 2) { + if (s->avctx->channels == 2) put_bits(&s->pb, 1, !!s->ms_stereo); - } for (ch = 0; ch < s->avctx->channels; ch++) { - s->channel_coded[ch] = 1; //FIXME only set channel_coded when needed, instead of always - if (s->channel_coded[ch]) { + // FIXME only set channel_coded when needed, instead of always + s->channel_coded[ch] = 1; + if (s->channel_coded[ch]) init_exp(s, ch, fixed_exp); - } } for (ch = 0; ch < s->avctx->channels; ch++) { @@ -212,19 +229,19 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], float *coefs, *exponents, mult; int i, n; - coefs1 = s->coefs1[ch]; + coefs1 = s->coefs1[ch]; exponents = s->exponents[ch]; - mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; - mult *= mdct_norm; - coefs = src_coefs[ch]; + mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; + mult *= mdct_norm; + coefs = src_coefs[ch]; if (s->use_noise_coding && 0) { - assert(0); //FIXME not implemented + assert(0); // FIXME not implemented } else { coefs += s->coefs_start; - n = nb_coefs[ch]; - for(i = 0;i < n; i++){ - double t= *coefs++ / (exponents[i] * mult); - if(t<-32768 || t>32767) + n = nb_coefs[ch]; + for (i = 0; i < n; i++) { + double t = *coefs++ / (exponents[i] * mult); + if (t < -32768 || t > 32767) return -1; coefs1[i] = lrint(t); @@ -243,19 +260,19 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], if (!v) return 1; - for(v= total_gain-1; v>=127; v-= 127) + for (v = total_gain - 1; v >= 127; v -= 127) put_bits(&s->pb, 7, 127); put_bits(&s->pb, 7, v); - coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); + coef_nb_bits = ff_wma_total_gain_to_bits(total_gain); if (s->use_noise_coding) { for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { int i, n; n = s->exponent_high_sizes[bsize]; - for(i=0;ipb, 1, s->high_band_coded[ch][i]= 0); + for (i = 0; i < n; i++) { + put_bits(&s->pb, 1, s->high_band_coded[ch][i] = 0); if (0) nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; } @@ -264,9 +281,8 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], } parse_exponents = 1; - if (s->block_len_bits != s->frame_len_bits) { + if (s->block_len_bits != s->frame_len_bits) put_bits(&s->pb, 1, parse_exponents); - } if (parse_exponents) { for (ch = 0; ch < s->avctx->channels; ch++) { @@ -274,69 +290,68 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], if (s->use_exp_vlc) { encode_exp_vlc(s, ch, fixed_exp); } else { - assert(0); //FIXME not implemented + assert(0); // FIXME not implemented // encode_exp_lsp(s, ch); } } } - } else { - assert(0); //FIXME not implemented - } + } else + assert(0); // FIXME not implemented for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { int run, tindex; WMACoef *ptr, *eptr; tindex = (ch == 1 && s->ms_stereo); - ptr = &s->coefs1[ch][0]; - eptr = ptr + nb_coefs[ch]; - - run=0; - for(;ptr < eptr; ptr++){ - if(*ptr){ - int level= *ptr; - int abs_level= FFABS(level); - int code= 0; - if(abs_level <= s->coef_vlcs[tindex]->max_level){ - if(run < s->coef_vlcs[tindex]->levels[abs_level-1]) - code= run + s->int_table[tindex][abs_level-1]; - } + ptr = &s->coefs1[ch][0]; + eptr = ptr + nb_coefs[ch]; + + run = 0; + for (; ptr < eptr; ptr++) { + if (*ptr) { + int level = *ptr; + int abs_level = FFABS(level); + int code = 0; + if (abs_level <= s->coef_vlcs[tindex]->max_level) + if (run < s->coef_vlcs[tindex]->levels[abs_level - 1]) + code = run + s->int_table[tindex][abs_level - 1]; assert(code < s->coef_vlcs[tindex]->n); - put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[code], s->coef_vlcs[tindex]->huffcodes[code]); + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[code], + s->coef_vlcs[tindex]->huffcodes[code]); - if(code == 0){ - if(1<pb, coef_nb_bits, abs_level); put_bits(&s->pb, s->frame_len_bits, run); } - put_bits(&s->pb, 1, level < 0); //FIXME the sign is fliped somewhere - run=0; - }else{ + // FIXME the sign is flipped somewhere + put_bits(&s->pb, 1, level < 0); + run = 0; + } else run++; - } } - if(run) - put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], s->coef_vlcs[tindex]->huffcodes[1]); + if (run) + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], + s->coef_vlcs[tindex]->huffcodes[1]); } - if (s->version == 1 && s->avctx->channels >= 2) { + if (s->version == 1 && s->avctx->channels >= 2) avpriv_align_put_bits(&s->pb); - } } return 0; } -static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], uint8_t *buf, int buf_size, int total_gain){ +static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], + uint8_t *buf, int buf_size, int total_gain) +{ init_put_bits(&s->pb, buf, buf_size); - if (s->use_bit_reservoir) { - assert(0);//FIXME not implemented - }else{ - if(encode_block(s, src_coefs, total_gain) < 0) - return INT_MAX; - } + if (s->use_bit_reservoir) + assert(0); // FIXME not implemented + else if (encode_block(s, src_coefs, total_gain) < 0) + return INT_MAX; avpriv_align_put_bits(&s->pb); @@ -349,8 +364,8 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, WMACodecContext *s = avctx->priv_data; int i, total_gain, ret; - s->block_len_bits= s->frame_len_bits; //required by non variable block len - s->block_len = 1 << s->block_len_bits; + s->block_len_bits = s->frame_len_bits; // required by non variable block len + s->block_len = 1 << s->block_len_bits; apply_window_and_mdct(avctx, frame); @@ -358,9 +373,9 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, float a, b; int i; - for(i = 0; i < s->block_len; i++) { - a = s->coefs[0][i]*0.5; - b = s->coefs[1][i]*0.5; + for (i = 0; i < s->block_len; i++) { + a = s->coefs[0][i] * 0.5; + b = s->coefs[1][i] * 0.5; s->coefs[0][i] = a + b; s->coefs[1][i] = a - b; } @@ -371,34 +386,17 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, return ret; } -#if 1 - total_gain= 128; - for(i=64; i; i>>=1){ + total_gain = 128; + for (i = 64; i; i >>= 1) { int error = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain - i); - if(error<0) - total_gain-= i; - } -#else - total_gain= 90; - best = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain); - for(i=32; i; i>>=1){ - int scoreL = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain - i); - int scoreR = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain + i); - av_log(NULL, AV_LOG_ERROR, "%d %d %d (%d)\n", scoreL, best, scoreR, total_gain); - if(scoreL < FFMIN(best, scoreR)){ - best = scoreL; + if (error < 0) total_gain -= i; - }else if(scoreR < best){ - best = scoreR; - total_gain += i; - } } -#endif if ((i = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain)) >= 0) { av_log(avctx, AV_LOG_ERROR, "required frame size too large. please " - "use a higher bit rate.\n"); + "use a higher bit rate.\n"); return AVERROR(EINVAL); } assert((put_bits_count(&s->pb) & 7) == 0); @@ -408,9 +406,9 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&s->pb); if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); - avpkt->size = avctx->block_align; + avpkt->size = avctx->block_align; *got_packet_ptr = 1; return 0; } @@ -424,8 +422,8 @@ AVCodec ff_wmav1_encoder = { .init = encode_init, .encode2 = encode_superframe, .close = ff_wma_end, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE }, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, }; AVCodec ff_wmav2_encoder = { @@ -437,6 +435,6 @@ AVCodec ff_wmav2_encoder = { .init = encode_init, .encode2 = encode_superframe, .close = ff_wma_end, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE }, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index b8a1776..231a74d 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -50,7 +50,7 @@ /** * @brief frame-specific decoder context for a single channel */ -typedef struct { +typedef struct WmallChannelCtx { int16_t prev_block_len; ///< length of the previous block uint8_t transmit_coefs; uint8_t num_subframes; @@ -69,7 +69,7 @@ typedef struct WmallDecodeCtx { /* generic decoder variables */ AVCodecContext *avctx; AVFrame *frame; - uint8_t frame_data[MAX_FRAMESIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< compressed frame data + uint8_t frame_data[MAX_FRAMESIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< compressed frame data PutBitContext pb; ///< context for filling the frame_data buffer /* frame size dependent frame information (set during initialization) */ @@ -101,8 +101,8 @@ typedef struct WmallDecodeCtx { uint32_t frame_num; ///< current frame number (not used for decoding) GetBitContext gb; ///< bitstream reader context int buf_bit_size; ///< buffer size in bits - int16_t *samples_16[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (16-bit) - int32_t *samples_32[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (24-bit) + int16_t *samples_16[WMALL_MAX_CHANNELS]; ///< current sample buffer pointer (16-bit) + int32_t *samples_32[WMALL_MAX_CHANNELS]; ///< current sample buffer pointer (24-bit) uint8_t drc_gain; ///< gain for the DRC tool int8_t skip_frame; ///< skip output step int8_t parsed_all_subframes; ///< all subframes decoded? @@ -200,8 +200,8 @@ static av_cold int decode_init(AVCodecContext *avctx) } /* dump the extradata */ for (i = 0; i < avctx->extradata_size; i++) - av_dlog(avctx, "[%x] ", avctx->extradata[i]); - av_dlog(avctx, "\n"); + ff_dlog(avctx, "[%x] ", avctx->extradata[i]); + ff_dlog(avctx, "\n"); } else { avpriv_request_sample(avctx, "Unsupported extradata size"); @@ -411,8 +411,7 @@ static void decode_ac_filter(WmallDecodeCtx *s) s->acfilter_scaling = get_bits(&s->gb, 4); for (i = 0; i < s->acfilter_order; i++) - s->acfilter_coeffs[i] = (s->acfilter_scaling ? - get_bits(&s->gb, s->acfilter_scaling) : 0) + 1; + s->acfilter_coeffs[i] = get_bitsz(&s->gb, s->acfilter_scaling) + 1; } static void decode_mclms(WmallDecodeCtx *s) @@ -425,7 +424,7 @@ static void decode_mclms(WmallDecodeCtx *s) if (1 << cbits < s->mclms_scaling + 1) cbits++; - send_coef_bits = (cbits ? get_bits(&s->gb, cbits) : 0) + 2; + send_coef_bits = get_bitsz(&s->gb, cbits) + 2; for (i = 0; i < s->mclms_order * s->num_channels * s->num_channels; i++) s->mclms_coeffs[i] = get_bits(&s->gb, send_coef_bits); @@ -471,7 +470,7 @@ static int decode_cdlms(WmallDecodeCtx *s) if ((1 << cbits) < s->cdlms[c][i].scaling + 1) cbits++; - s->cdlms[c][i].bitsend = get_bits(&s->gb, cbits) + 2; + s->cdlms[c][i].bitsend = get_bitsz(&s->gb, cbits) + 2; shift_l = 32 - s->cdlms[c][i].bitsend; shift_r = 32 - s->cdlms[c][i].scaling - 2; for (j = 0; j < s->cdlms[c][i].coefsend; j++) @@ -950,7 +949,7 @@ static int decode_subframe(WmallDecodeCtx *s) "Invalid number of padding bits in raw PCM tile\n"); return AVERROR_INVALIDDATA; } - av_dlog(s->avctx, "RAWPCM %d bits per sample. " + ff_dlog(s->avctx, "RAWPCM %d bits per sample. " "total %d bits, remain=%d\n", bits, bits * s->num_channels * subframe_len, get_bits_count(&s->gb)); for (i = 0; i < s->num_channels; i++) @@ -1054,13 +1053,13 @@ static int decode_frame(WmallDecodeCtx *s) /* usually true for the first frame */ if (get_bits1(gb)) { skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); - av_dlog(s->avctx, "start skip: %i\n", skip); + ff_dlog(s->avctx, "start skip: %i\n", skip); } /* sometimes true for the last frame */ if (get_bits1(gb)) { skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); - av_dlog(s->avctx, "end skip: %i\n", skip); + ff_dlog(s->avctx, "end skip: %i\n", skip); } } @@ -1080,7 +1079,7 @@ static int decode_frame(WmallDecodeCtx *s) } } - av_dlog(s->avctx, "Frame done\n"); + ff_dlog(s->avctx, "Frame done\n"); if (s->skip_frame) s->skip_frame = 0; @@ -1193,7 +1192,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, /* parse packet header */ init_get_bits(gb, buf, s->buf_bit_size); packet_sequence_number = get_bits(gb, 4); - skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently ununused + skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently unused spliced_packet = get_bits1(gb); if (spliced_packet) avpriv_request_sample(avctx, "Bitstream splicing"); @@ -1226,7 +1225,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, if (num_bits_prev_frame < remaining_packet_bits && !s->packet_loss) decode_frame(s); } else if (s->num_saved_bits - s->frame_offset) { - av_dlog(avctx, "ignoring %x previously saved bits\n", + ff_dlog(avctx, "ignoring %x previously saved bits\n", s->num_saved_bits - s->frame_offset); } @@ -1311,7 +1310,7 @@ AVCodec ff_wmalossless_decoder = { .close = decode_close, .decode = decode_packet, .flush = flush, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index afe6ac2..daeaa79 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -132,7 +132,7 @@ static float sin64[33]; ///< sine table for decorrelation /** * @brief frame specific decoder context for a single channel */ -typedef struct { +typedef struct WMAProChannelCtx { int16_t prev_block_len; ///< length of the previous block uint8_t transmit_coefs; uint8_t num_subframes; @@ -157,7 +157,7 @@ typedef struct { /** * @brief channel group for channel transformations */ -typedef struct { +typedef struct WMAProChannelGrp { uint8_t num_channels; ///< number of channels in the group int8_t transform; ///< transform on / off int8_t transform_band[MAX_BANDS]; ///< controls if the transform is enabled for a certain band @@ -173,7 +173,7 @@ typedef struct WMAProDecodeCtx { AVCodecContext* avctx; ///< codec context for av_log AVFloatDSPContext fdsp; uint8_t frame_data[MAX_FRAMESIZE + - FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data + AV_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data PutBitContext pb; ///< context for filling the frame_data buffer FFTContext mdct_ctx[WMAPRO_BLOCK_SIZES]; ///< MDCT context per block size DECLARE_ALIGNED(32, float, tmp)[WMAPRO_BLOCK_MAX_SIZE]; ///< IMDCT output buffer @@ -286,7 +286,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } s->avctx = avctx; - avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); @@ -298,8 +298,8 @@ static av_cold int decode_init(AVCodecContext *avctx) s->bits_per_sample = AV_RL16(edata_ptr); /** dump the extradata */ for (i = 0; i < avctx->extradata_size; i++) - av_dlog(avctx, "[%x] ", avctx->extradata[i]); - av_dlog(avctx, "\n"); + ff_dlog(avctx, "[%x] ", avctx->extradata[i]); + ff_dlog(avctx, "\n"); } else { avpriv_request_sample(avctx, "Unknown extradata size"); @@ -607,7 +607,7 @@ static int decode_tilehdr(WMAProDecodeCtx *s) int i; int offset = 0; for (i = 0; i < s->channel[c].num_subframes; i++) { - av_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]" + ff_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]" " len %i\n", s->frame_num, c, i, s->channel[c].subframe_len[i]); s->channel[c].subframe_offset[i] = offset; @@ -807,7 +807,7 @@ static int decode_coeffs(WMAProDecodeCtx *s, int c) const uint16_t* run; const float* level; - av_dlog(s->avctx, "decode coefficients for channel %i\n", c); + ff_dlog(s->avctx, "decode coefficients for channel %i\n", c); vlctable = get_bits1(&s->gb); vlc = &coef_vlc[vlctable]; @@ -1092,7 +1092,7 @@ static int decode_subframe(WMAProDecodeCtx *s) } } - av_dlog(s->avctx, + ff_dlog(s->avctx, "processing subframe with offset %i len %i\n", offset, subframe_len); /** get a list of all channels that contain the estimated block */ @@ -1119,7 +1119,7 @@ static int decode_subframe(WMAProDecodeCtx *s) s->parsed_all_subframes = 1; - av_dlog(s->avctx, "subframe is part of %i channels\n", + ff_dlog(s->avctx, "subframe is part of %i channels\n", s->channels_for_cur_subframe); /** calculate number of scale factor bands and their offsets */ @@ -1145,7 +1145,7 @@ static int decode_subframe(WMAProDecodeCtx *s) int num_fill_bits; if (!(num_fill_bits = get_bits(&s->gb, 2))) { int len = get_bits(&s->gb, 4); - num_fill_bits = get_bits(&s->gb, len) + 1; + num_fill_bits = get_bitsz(&s->gb, len) + 1; } if (num_fill_bits >= 0) { @@ -1236,7 +1236,7 @@ static int decode_subframe(WMAProDecodeCtx *s) return AVERROR_INVALIDDATA; } - av_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n", + ff_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n", get_bits_count(&s->gb) - s->subframe_offset); /** parse coefficients */ @@ -1250,7 +1250,7 @@ static int decode_subframe(WMAProDecodeCtx *s) sizeof(*s->channel[c].coeffs) * subframe_len); } - av_dlog(s->avctx, "BITSTREAM: subframe length was %i\n", + ff_dlog(s->avctx, "BITSTREAM: subframe length was %i\n", get_bits_count(&s->gb) - s->subframe_offset); if (transmit_coeffs) { @@ -1318,7 +1318,7 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr) if (s->len_prefix) len = get_bits(gb, s->log2_frame_size); - av_dlog(s->avctx, "decoding frame with length %x\n", len); + ff_dlog(s->avctx, "decoding frame with length %x\n", len); /** decode tile information */ if (decode_tilehdr(s)) { @@ -1337,7 +1337,7 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr) /** read drc info */ if (s->dynamic_range_compression) { s->drc_gain = get_bits(gb, 8); - av_dlog(s->avctx, "drc_gain %i\n", s->drc_gain); + ff_dlog(s->avctx, "drc_gain %i\n", s->drc_gain); } /** no idea what these are for, might be the number of samples @@ -1348,18 +1348,18 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr) /** usually true for the first frame */ if (get_bits1(gb)) { skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); - av_dlog(s->avctx, "start skip: %i\n", skip); + ff_dlog(s->avctx, "start skip: %i\n", skip); } /** sometimes true for the last frame */ if (get_bits1(gb)) { skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); - av_dlog(s->avctx, "end skip: %i\n", skip); + ff_dlog(s->avctx, "end skip: %i\n", skip); } } - av_dlog(s->avctx, "BITSTREAM: frame header length was %i\n", + ff_dlog(s->avctx, "BITSTREAM: frame header length was %i\n", get_bits_count(gb) - s->frame_offset); /** reset subframe states */ @@ -1455,7 +1455,7 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len, int buflen; /** when the frame data does not need to be concatenated, the input buffer - is resetted and additional bits from the previous frame are copyed + is reset and additional bits from the previous frame are copied and skipped later so that a fast byte copy is possible */ if (!append) { @@ -1542,7 +1542,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, /** get number of bits that need to be added to the previous frame */ num_bits_prev_frame = get_bits(gb, s->log2_frame_size); - av_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number, + ff_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number, num_bits_prev_frame); /** check for packet loss */ @@ -1565,14 +1565,14 @@ static int decode_packet(AVCodecContext *avctx, void *data, /** append the previous frame data to the remaining data from the previous packet to create a full frame */ save_bits(s, gb, num_bits_prev_frame, 1); - av_dlog(avctx, "accumulated %x bits of frame data\n", + ff_dlog(avctx, "accumulated %x bits of frame data\n", s->num_saved_bits - s->frame_offset); /** decode the cross packet frame if it is valid */ if (!s->packet_loss) decode_frame(s, data, got_frame_ptr); } else if (s->num_saved_bits - s->frame_offset) { - av_dlog(avctx, "ignoring %x previously saved bits\n", + ff_dlog(avctx, "ignoring %x previously saved bits\n", s->num_saved_bits - s->frame_offset); } @@ -1651,7 +1651,7 @@ AVCodec ff_wmapro_decoder = { .init = decode_init, .close = decode_end, .decode = decode_packet, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 0d91077..62b603c 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -131,7 +131,7 @@ static const struct frame_type_desc { /** * WMA Voice decoding context. */ -typedef struct { +typedef struct WMAVoiceContext { /** * @name Global values specified in the stream header / extradata or used all over. * @{ @@ -205,7 +205,7 @@ typedef struct { ///< to #wmavoice_decode_packet() (since ///< they're part of the previous superframe) - uint8_t sframe_cache[SFRAME_CACHE_MAXSIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t sframe_cache[SFRAME_CACHE_MAXSIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< cache for superframe data split over ///< multiple packets int sframe_cache_size; ///< set to >0 if we have data from an @@ -1195,7 +1195,7 @@ static void aw_pulse_set1(WMAVoiceContext *s, GetBitContext *gb, /** * @} * - * Generate a random number from frame_cntr and block_idx, which will lief + * Generate a random number from frame_cntr and block_idx, which will live * in the range [0, 1000 - block_size] (so it can be used as an index in a * table of size 1000 of which you want to read block_size entries). * @@ -1518,7 +1518,7 @@ static int synth_frame(AVCodecContext *ctx, GetBitContext *gb, int frame_idx, /* Pitch is given per block. Per-block pitches are encoded as an * absolute value for the first block, and then delta values * relative to this value) for all subsequent blocks. The scale of - * this pitch value is semi-logaritmic compared to its use in the + * this pitch value is semi-logarithmic compared to its use in the * decoder, so we convert it to normal scale also. */ int block_pitch, t1 = (s->block_conv_table[1] - s->block_conv_table[0]) << 2, @@ -2074,6 +2074,6 @@ AVCodec ff_wmavoice_decoder = { .init_static_data = wmavoice_init_static_data, .close = wmavoice_decode_end, .decode = wmavoice_decode_packet, - .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .flush = wmavoice_flush, }; diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 7b1ea57..6542d31 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -20,14 +20,17 @@ #include "avcodec.h" #include "idctdsp.h" +#include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4data.h" #include "simple_idct.h" #include "wmv2.h" +#include "wmv2data.h" -av_cold void ff_wmv2_common_init(Wmv2Context * w){ - MpegEncContext * const s= &w->s; +av_cold void ff_wmv2_common_init(Wmv2Context *w) +{ + MpegEncContext *const s = &w->s; ff_blockdsp_init(&s->bdsp, s->avctx); ff_wmv2dsp_init(&w->wdsp); @@ -51,84 +54,87 @@ av_cold void ff_wmv2_common_init(Wmv2Context * w){ s->idsp.idct = NULL; } -static void wmv2_add_block(Wmv2Context *w, int16_t *block1, uint8_t *dst, int stride, int n){ - MpegEncContext * const s= &w->s; - - if (s->block_last_index[n] >= 0) { - switch(w->abt_type_table[n]){ - case 0: - w->wdsp.idct_add(dst, stride, block1); - break; - case 1: - ff_simple_idct84_add(dst , stride, block1); - ff_simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - case 2: - ff_simple_idct48_add(dst , stride, block1); - ff_simple_idct48_add(dst + 4 , stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); +static void wmv2_add_block(Wmv2Context *w, int16_t *block1, + uint8_t *dst, int stride, int n) +{ + MpegEncContext *const s = &w->s; + + if (s->block_last_index[n] >= 0) { + switch (w->abt_type_table[n]) { + case 0: + w->wdsp.idct_add(dst, stride, block1); + break; + case 1: + ff_simple_idct84_add(dst, stride, block1); + ff_simple_idct84_add(dst + 4 * stride, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + case 2: + ff_simple_idct48_add(dst, stride, block1); + ff_simple_idct48_add(dst + 4, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); + } } - } } -void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr){ - Wmv2Context * const w= (Wmv2Context*)s; +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) +{ + Wmv2Context *const w = (Wmv2Context *) s; - wmv2_add_block(w, block1[0], dest_y , s->linesize, 0); - wmv2_add_block(w, block1[1], dest_y + 8 , s->linesize, 1); - wmv2_add_block(w, block1[2], dest_y + 8*s->linesize, s->linesize, 2); - wmv2_add_block(w, block1[3], dest_y + 8 + 8*s->linesize, s->linesize, 3); + 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; + if (s->avctx->flags & AV_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); + 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) +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; + Wmv2Context *const w = (Wmv2Context *) s; uint8_t *ptr; int dxy, offset, mx, my, src_x, src_y, v_edge_pos; ptrdiff_t linesize, uvlinesize; - int emu=0; + int emu = 0; - dxy = ((motion_y & 1) << 1) | (motion_x & 1); - dxy = 2*dxy + w->hshift; + dxy = ((motion_y & 1) << 1) | (motion_x & 1); + dxy = 2 * dxy + w->hshift; src_x = s->mb_x * 16 + (motion_x >> 1); src_y = s->mb_y * 16 + (motion_y >> 1); /* WARNING: do no forget half pels */ v_edge_pos = s->v_edge_pos; - src_x = av_clip(src_x, -16, s->width); - src_y = av_clip(src_y, -16, s->height); + src_x = av_clip(src_x, -16, s->width); + src_y = av_clip(src_y, -16, s->height); - if(src_x<=-16 || src_x >= s->width) + if (src_x <= -16 || src_x >= s->width) dxy &= ~3; - if(src_y<=-16 || src_y >= s->height) + if (src_y <= -16 || src_y >= s->height) dxy &= ~4; linesize = s->linesize; uvlinesize = s->uvlinesize; - ptr = ref_picture[0] + (src_y * linesize) + src_x; - - if(src_x<1 || src_y<1 || src_x + 17 >= s->h_edge_pos - || src_y + h+1 >= v_edge_pos){ - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, - ptr - 1 - s->linesize, - s->linesize, s->linesize, - 19, 19, + ptr = ref_picture[0] + (src_y * linesize) + src_x; + + if (src_x < 1 || src_y < 1 || src_x + 17 >= s->h_edge_pos || + src_y + h + 1 >= v_edge_pos) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr - 1 - s->linesize, + 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; + ptr = s->sc.edge_emu_buffer + 1 + s->linesize; + emu = 1; } w->wdsp.put_mspel_pixels_tab[dxy](dest_y, ptr, linesize); @@ -136,7 +142,8 @@ void ff_mspel_motion(MpegEncContext *s, w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 * linesize, ptr + 8 * linesize, linesize); w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 + 8 * linesize, ptr + 8 + 8 * linesize, linesize); - if(s->flags&CODEC_FLAG_GRAY) return; + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; if (s->out_format == FMT_H263) { dxy = 0; @@ -147,9 +154,9 @@ void ff_mspel_motion(MpegEncContext *s, mx = motion_x >> 2; my = motion_y >> 2; } else { - mx = motion_x / 2; - my = motion_y / 2; - dxy = ((my & 1) << 1) | (mx & 1); + mx = motion_x / 2; + my = motion_y / 2; + dxy = ((my & 1) << 1) | (mx & 1); mx >>= 1; my >>= 1; } @@ -163,25 +170,25 @@ void ff_mspel_motion(MpegEncContext *s, if (src_y == (s->height >> 1)) dxy &= ~2; offset = (src_y * uvlinesize) + src_x; - ptr = ref_picture[1] + offset; - if(emu){ - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + ptr = ref_picture[1] + offset; + if (emu) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, s->uvlinesize, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr= s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1); ptr = ref_picture[2] + offset; - if(emu){ - s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + if (emu) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr, s->uvlinesize, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); - ptr= s->edge_emu_buffer; + ptr = s->sc.edge_emu_buffer; } pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1); } diff --git a/libavcodec/wmv2.h b/libavcodec/wmv2.h index e01f6c1..b77dd98 100644 --- a/libavcodec/wmv2.h +++ b/libavcodec/wmv2.h @@ -22,8 +22,8 @@ #define AVCODEC_WMV2_H #include "avcodec.h" -#include "mpegvideo.h" #include "intrax8.h" +#include "mpegvideo.h" #include "wmv2dsp.h" #define SKIP_TYPE_NONE 0 @@ -32,7 +32,7 @@ #define SKIP_TYPE_COL 3 -typedef struct Wmv2Context{ +typedef struct Wmv2Context { MpegEncContext s; IntraX8Context x8; WMV2DSPContext wdsp; @@ -52,8 +52,22 @@ typedef struct Wmv2Context{ ScanTable abt_scantable[2]; DECLARE_ALIGNED(16, int16_t, abt_block2)[6][64]; -}Wmv2Context; +} Wmv2Context; + +void ff_wmv2_common_init(Wmv2Context *w); + +int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); +int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], + int motion_x, int motion_y); +int ff_wmv2_decode_picture_header(MpegEncContext * s); +int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s); +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64], + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr); -void ff_wmv2_common_init(Wmv2Context * w); +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); #endif /* AVCODEC_WMV2_H */ diff --git a/libavcodec/wmv2data.c b/libavcodec/wmv2data.c new file mode 100644 index 0000000..bbb07bb --- /dev/null +++ b/libavcodec/wmv2data.c @@ -0,0 +1,35 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "wmv2data.h" + +const uint8_t ff_wmv2_scantableA[64] = { + 0x00, 0x01, 0x02, 0x08, 0x03, 0x09, 0x0A, 0x10, + 0x04, 0x0B, 0x11, 0x18, 0x12, 0x0C, 0x05, 0x13, + 0x19, 0x0D, 0x14, 0x1A, 0x1B, 0x06, 0x15, 0x1C, + 0x0E, 0x16, 0x1D, 0x07, 0x1E, 0x0F, 0x17, 0x1F, +}; + +const uint8_t ff_wmv2_scantableB[64] = { + 0x00, 0x08, 0x01, 0x10, 0x09, 0x18, 0x11, 0x02, + 0x20, 0x0A, 0x19, 0x28, 0x12, 0x30, 0x21, 0x1A, + 0x38, 0x29, 0x22, 0x03, 0x31, 0x39, 0x0B, 0x2A, + 0x13, 0x32, 0x1B, 0x3A, 0x23, 0x2B, 0x33, 0x3B, +}; diff --git a/libavcodec/wmv2data.h b/libavcodec/wmv2data.h new file mode 100644 index 0000000..8914e57 --- /dev/null +++ b/libavcodec/wmv2data.h @@ -0,0 +1,27 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_WMV2DATA_H +#define AVCODEC_WMV2DATA_H + +#include + +extern const uint8_t ff_wmv2_scantableA[64]; +extern const uint8_t ff_wmv2_scantableB[64]; + +#endif /* AVCODEC_WMV2DATA_H */ diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 4ebc801..e1f86d8 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -19,265 +19,279 @@ */ #include "avcodec.h" -#include "mpegutils.h" -#include "mpegvideo.h" #include "h263.h" +#include "internal.h" +#include "intrax8.h" #include "mathops.h" +#include "mpegutils.h" +#include "mpegvideo.h" #include "msmpeg4.h" #include "msmpeg4data.h" -#include "intrax8.h" #include "wmv2.h" -static void parse_mb_skip(Wmv2Context * w){ +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; + 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){ + w->skip_type = get_bits(&s->gb, 2); + switch (w->skip_type) { case SKIP_TYPE_NONE: - for(mb_y=0; mb_ymb_height; mb_y++){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_16x16 | MB_TYPE_L0; - } - } + 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_ymb_height; mb_y++){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } - } + 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_ymb_height; mb_y++){ - if(get_bits1(&s->gb)){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; - } - }else{ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } + 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_xmb_width; mb_x++){ - if(get_bits1(&s->gb)){ - for(mb_y=0; mb_ymb_height; mb_y++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; - } - }else{ - for(mb_y=0; mb_ymb_height; mb_y++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } + 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; +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; + if (s->avctx->extradata_size < 4) + return AVERROR_INVALIDDATA; init_get_bits(&gb, s->avctx->extradata, 32); - fps = get_bits(&gb, 5); - s->bit_rate = get_bits(&gb, 11)*1024; - w->mspel_bit = get_bits1(&gb); - s->loop_filter = get_bits1(&gb); - w->abt_flag = get_bits1(&gb); - w->j_type_bit = get_bits1(&gb); - w->top_left_mv_flag= get_bits1(&gb); - w->per_mb_rl_bit = get_bits1(&gb); - code = get_bits(&gb, 3); + fps = get_bits(&gb, 5); + s->bit_rate = get_bits(&gb, 11) * 1024; + w->mspel_bit = get_bits1(&gb); + s->loop_filter = get_bits1(&gb); + w->abt_flag = get_bits1(&gb); + w->j_type_bit = get_bits1(&gb); + w->top_left_mv_flag = get_bits1(&gb); + w->per_mb_rl_bit = get_bits1(&gb); + code = get_bits(&gb, 3); - if(code==0) return -1; + if (code == 0) + return AVERROR_INVALIDDATA; s->slice_height = s->mb_height / code; - if(s->avctx->debug&FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, slices:%d\n", - fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, - code); - } + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, + "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, " + "tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, " + "slices:%d\n", + fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, + w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, + code); return 0; } -int ff_wmv2_decode_picture_header(MpegEncContext * s) +int ff_wmv2_decode_picture_header(MpegEncContext *s) { - Wmv2Context * const w= (Wmv2Context*)s; + Wmv2Context *const w = (Wmv2Context *) s; int code; - if(s->picture_number==0) + if (s->picture_number == 0) decode_ext_header(w); s->pict_type = get_bits1(&s->gb) + 1; - if(s->pict_type == AV_PICTURE_TYPE_I){ + if (s->pict_type == AV_PICTURE_TYPE_I) { code = get_bits(&s->gb, 7); av_log(s->avctx, AV_LOG_DEBUG, "I7:%X/\n", code); } - s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); - if(s->qscale <= 0) - return -1; + s->chroma_qscale = s->qscale = get_bits(&s->gb, 5); + if (s->qscale <= 0) + return AVERROR_INVALIDDATA; return 0; } -int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s) +int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) { - Wmv2Context * const w= (Wmv2Context*)s; + Wmv2Context *const w = (Wmv2Context *) s; if (s->pict_type == AV_PICTURE_TYPE_I) { - if(w->j_type_bit) w->j_type= get_bits1(&s->gb); - else w->j_type= 0; //FIXME check - - if(!w->j_type){ - if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); - else s->per_mb_rl_table= 0; - - if(!s->per_mb_rl_table){ + 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->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); + 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{ + } else { int cbp_index; - w->j_type=0; + 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]; + 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->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->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 (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); + 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->dc_table_index = get_bits1(&s->gb); + s->mv_table_index = get_bits1(&s->gb); + + s->inter_intra_pred = 0; // (s->width * s->height < 320 * 240 && s->bit_rate <= II_BITRATE); + s->no_rounding ^= 1; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, + "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d " + "per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", + s->rl_table_index, s->rl_chroma_table_index, + s->dc_table_index, s->mv_table_index, + s->per_mb_rl_table, s->qscale, s->mspel, + w->per_mb_abt, w->abt_type, w->cbp_table_index, + s->inter_intra_pred); } } - s->esc3_level_length= 0; - s->esc3_run_length= 0; - -s->picture_number++; //FIXME ? - - - if(w->j_type){ - ff_intrax8_decode_picture(&w->x8, 2*s->qscale, (s->qscale-1)|1 ); + s->esc3_level_length = 0; + s->esc3_run_length = 0; + s->picture_number++; // FIXME ? + + if (w->j_type) { + ff_intrax8_decode_picture(&w->x8, &s->current_picture, + &s->gb, &s->mb_x, &s->mb_y, + 2 * s->qscale, (s->qscale - 1) | 1, + s->loop_filter, s->low_delay); + + ff_er_add_slice(&w->s.er, 0, 0, + (w->s.mb_x >> 1) - 1, (w->s.mb_y >> 1) - 1, + ER_MB_END); return 1; } return 0; } -static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ - MpegEncContext * const s= &w->s; +static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr) +{ + MpegEncContext *const s = &w->s; int ret; - ret= ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); + ret = ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); - if(ret<0) return -1; + if (ret < 0) + return ret; - if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) - w->hshift= get_bits1(&s->gb); + if ((((*mx_ptr) | (*my_ptr)) & 1) && s->mspel) + w->hshift = get_bits1(&s->gb); else - w->hshift= 0; + w->hshift = 0; return 0; } -static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ - MpegEncContext * const s= &w->s; +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]; + 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]; + 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])); + 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; + diff = 0; - if(diff >= 8) - type= get_bits1(&s->gb); + 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{ + 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]; @@ -291,89 +305,92 @@ static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ return mot_val; } -static inline int wmv2_decode_inter_block(Wmv2Context *w, int16_t *block, int n, int cbp){ - MpegEncContext * const s= &w->s; - static const int sub_cbp_table[3]= {2,3,1}; - int sub_cbp; +static inline int wmv2_decode_inter_block(Wmv2Context *w, int16_t *block, + int n, int cbp) +{ + MpegEncContext *const s = &w->s; + static const int sub_cbp_table[3] = { 2, 3, 1 }; + int sub_cbp, ret; - if(!cbp){ + if (!cbp) { s->block_last_index[n] = -1; - return 0; } - if(w->per_block_abt) - w->abt_type= decode012(&s->gb); - w->abt_type_table[n]= w->abt_type; + if (w->per_block_abt) + w->abt_type = decode012(&s->gb); + w->abt_type_table[n] = w->abt_type; - if(w->abt_type){ -// const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated; - const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; -// const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable; + 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) ]; + sub_cbp = sub_cbp_table[decode012(&s->gb)]; - if(sub_cbp&1){ - if (ff_msmpeg4_decode_block(s, block, n, 1, scantable) < 0) - return -1; - } + if (sub_cbp & 1) + if ((ret = ff_msmpeg4_decode_block(s, block, n, 1, scantable)) < 0) + return ret; + + if (sub_cbp & 2) + if ((ret = ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable)) < 0) + return ret; - if(sub_cbp&2){ - if (ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) - return -1; - } s->block_last_index[n] = 63; return 0; - }else{ - return ff_msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); + } else { + return ff_msmpeg4_decode_block(s, block, n, 1, + s->inter_scantable.permutated); } } - int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) { - Wmv2Context * const w= (Wmv2Context*)s; - int cbp, code, i; + Wmv2Context *const w = (Wmv2Context *) s; + int cbp, code, i, ret; uint8_t *coded_val; - if(w->j_type) return 0; + if (w->j_type) + return 0; if (s->pict_type == AV_PICTURE_TYPE_P) { if (IS_SKIP(s->current_picture.mb_type[s->mb_y * s->mb_stride + s->mb_x])) { /* skip mb */ s->mb_intra = 0; - for(i=0;i<6;i++) + 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_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; + s->mb_skipped = 1; + w->hshift = 0; return 0; } - code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); + code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, + MB_NON_INTRA_VLC_BITS, 3); if (code < 0) - return -1; + return AVERROR_INVALIDDATA; 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; + if (code < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); + return AVERROR_INVALIDDATA; } /* predict coded block pattern */ cbp = 0; - for(i=0;i<6;i++) { + for (i = 0; i < 6; i++) { int val = ((code >> (5 - i)) & 1); if (i < 4) { - int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); - val = val ^ pred; + int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); + val = val ^ pred; *coded_val = val; } cbp |= val << (5 - i); @@ -384,59 +401,62 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) int mx, my; wmv2_pred_motion(w, &mx, &my); - if(cbp){ + if (cbp) { s->bdsp.clear_blocks(s->block[0]); - if(s->per_mb_rl_table){ - s->rl_table_index = decode012(&s->gb); + 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 (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; + if ((ret = wmv2_decode_motion(w, &mx, &my)) < 0) + return ret; - s->mv_dir = MV_DIR_FORWARD; - s->mv_type = MV_TYPE_16X16; + 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; + if ((ret = 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 ret; } } } else { - if (s->pict_type==AV_PICTURE_TYPE_P) - av_dlog(s->avctx, "%d%d ", s->inter_intra_pred, cbp); - av_dlog(s->avctx, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, - ((cbp & 3) ? 1 : 0) +((cbp & 0x3C)? 2 : 0), + if (s->pict_type == AV_PICTURE_TYPE_P) + ff_dlog(s->avctx, "%d%d ", s->inter_intra_pred, cbp); + ff_dlog(s->avctx, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, + ((cbp & 3) ? 1 : 0) + ((cbp & 0x3C) ? 2 : 0), show_bits(&s->gb, 24)); s->ac_pred = get_bits1(&s->gb); - if(s->inter_intra_pred){ - s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); - av_dlog(s->avctx, "%d%d %d %d/", + if (s->inter_intra_pred) { + s->h263_aic_dir = get_vlc2(&s->gb, ff_inter_intra_vlc.table, + INTER_INTRA_VLC_BITS, 1); + ff_dlog(s->avctx, "%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); } - if(s->per_mb_rl_table && cbp){ - s->rl_table_index = decode012(&s->gb); + if (s->per_mb_rl_table && cbp) { + s->rl_table_index = decode012(&s->gb); s->rl_chroma_table_index = s->rl_table_index; } s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { - if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) - { - av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); - return -1; + if ((ret = ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "\nerror while decoding intra block: %d x %d (%d)\n", + s->mb_x, s->mb_y, i); + return ret; } } } @@ -444,17 +464,19 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) return 0; } -static av_cold int wmv2_decode_init(AVCodecContext *avctx){ - Wmv2Context * const w= avctx->priv_data; +static av_cold int wmv2_decode_init(AVCodecContext *avctx) +{ + Wmv2Context *const w = avctx->priv_data; + int ret; - if(ff_msmpeg4_decode_init(avctx) < 0) - return -1; + if ((ret = ff_msmpeg4_decode_init(avctx)) < 0) + return ret; ff_wmv2_common_init(w); - ff_intrax8_common_init(&w->x8,&w->s); - - return 0; + return ff_intrax8_common_init(avctx, &w->x8, &w->s.idsp, + w->s.block, w->s.block_last_index, + w->s.mb_width, w->s.mb_height); } static av_cold int wmv2_decode_end(AVCodecContext *avctx) @@ -474,9 +496,7 @@ AVCodec ff_wmv2_decoder = { .init = wmv2_decode_init, .close = wmv2_decode_end, .decode = ff_h263_decode_frame, - .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, - .pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE - }, + .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 9da2b3f..b09942e 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -19,30 +19,31 @@ */ #include "avcodec.h" +#include "h263.h" #include "mpegvideo.h" #include "msmpeg4.h" #include "msmpeg4data.h" -#include "h263.h" #include "wmv2.h" -static int encode_ext_header(Wmv2Context *w){ - MpegEncContext * const s= &w->s; +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, 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->mspel_bit = 1); put_bits(&pb, 1, s->loop_filter); - put_bits(&pb, 1, w->abt_flag=1); - put_bits(&pb, 1, w->j_type_bit=1); - put_bits(&pb, 1, w->top_left_mv_flag=0); - put_bits(&pb, 1, w->per_mb_rl_bit=1); - put_bits(&pb, 3, code=1); + 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); @@ -51,94 +52,100 @@ static int encode_ext_header(Wmv2Context *w){ return 0; } -static av_cold int wmv2_encode_init(AVCodecContext *avctx){ - Wmv2Context * const w= avctx->priv_data; +static av_cold int wmv2_encode_init(AVCodecContext *avctx) +{ + Wmv2Context *const w = avctx->priv_data; if (ff_mpv_encode_init(avctx) < 0) return -1; ff_wmv2_common_init(w); - avctx->extradata_size= 4; - avctx->extradata= av_mallocz(avctx->extradata_size + 10); + avctx->extradata_size = 4; + avctx->extradata = av_mallocz(avctx->extradata_size + 10); + if (!avctx->extradata) + return AVERROR(ENOMEM); + encode_ext_header(w); return 0; } -int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) +int ff_wmv2_encode_picture_header(MpegEncContext *s, int picture_number) { - Wmv2Context * const w= (Wmv2Context*)s; + Wmv2Context *const w = (Wmv2Context *) s; put_bits(&s->pb, 1, s->pict_type - 1); - if(s->pict_type == AV_PICTURE_TYPE_I){ + if (s->pict_type == AV_PICTURE_TYPE_I) put_bits(&s->pb, 7, 0); - } put_bits(&s->pb, 5, s->qscale); - s->dc_table_index = 1; - s->mv_table_index = 1; /* only if P frame */ + s->dc_table_index = 1; + s->mv_table_index = 1; /* only if P-frame */ s->per_mb_rl_table = 0; - s->mspel= 0; - w->per_mb_abt=0; - w->abt_type=0; - w->j_type=0; + s->mspel = 0; + w->per_mb_abt = 0; + w->abt_type = 0; + w->j_type = 0; assert(s->flipflop_rounding); if (s->pict_type == AV_PICTURE_TYPE_I) { - assert(s->no_rounding==1); - if(w->j_type_bit) put_bits(&s->pb, 1, w->j_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 (w->per_mb_rl_bit) + put_bits(&s->pb, 1, s->per_mb_rl_table); - if(!s->per_mb_rl_table){ + if (!s->per_mb_rl_table) { ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); ff_msmpeg4_code012(&s->pb, s->rl_table_index); } put_bits(&s->pb, 1, s->dc_table_index); - s->inter_intra_pred= 0; - }else{ + s->inter_intra_pred = 0; + } else { int cbp_index; put_bits(&s->pb, 2, SKIP_TYPE_NONE); - ff_msmpeg4_code012(&s->pb, cbp_index=0); - if(s->qscale <= 10){ - int map[3]= {0,2,1}; - w->cbp_table_index= map[cbp_index]; - }else if(s->qscale <= 20){ - int map[3]= {1,0,2}; - w->cbp_table_index= map[cbp_index]; - }else{ - int map[3]= {2,1,0}; - w->cbp_table_index= map[cbp_index]; + ff_msmpeg4_code012(&s->pb, cbp_index = 0); + if (s->qscale <= 10) { + int map[3] = { 0, 2, 1 }; + w->cbp_table_index = map[cbp_index]; + } else if (s->qscale <= 20) { + int map[3] = { 1, 0, 2 }; + w->cbp_table_index = map[cbp_index]; + } else { + int map[3] = { 2, 1, 0 }; + w->cbp_table_index = map[cbp_index]; } - if(w->mspel_bit) put_bits(&s->pb, 1, s->mspel); + if (w->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){ + if (w->abt_flag) { + put_bits(&s->pb, 1, w->per_mb_abt ^ 1); + if (!w->per_mb_abt) ff_msmpeg4_code012(&s->pb, w->abt_type); - } } - if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); + if (w->per_mb_rl_bit) + put_bits(&s->pb, 1, s->per_mb_rl_table); - if(!s->per_mb_rl_table){ + if (!s->per_mb_rl_table) { ff_msmpeg4_code012(&s->pb, s->rl_table_index); s->rl_chroma_table_index = s->rl_table_index; } put_bits(&s->pb, 1, s->dc_table_index); put_bits(&s->pb, 1, s->mv_table_index); - s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + s->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; + s->esc3_level_length = 0; + s->esc3_run_length = 0; return 0; } @@ -146,11 +153,10 @@ int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) /* Nearly identical to wmv1 but that is just because we do not use the * useless M$ crap features. It is duplicated here in case someone wants * to add support for these crap features. */ -void ff_wmv2_encode_mb(MpegEncContext * s, - int16_t block[6][64], +void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y) { - Wmv2Context * const w= (Wmv2Context*)s; + Wmv2Context *const w = (Wmv2Context *) s; int cbp, coded_cbp, i; int pred_x, pred_y; uint8_t *coded_block; @@ -160,10 +166,9 @@ void ff_wmv2_encode_mb(MpegEncContext * s, if (!s->mb_intra) { /* compute cbp */ cbp = 0; - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) if (s->block_last_index[i] >= 0) cbp |= 1 << (5 - i); - } put_bits(&s->pb, ff_wmv2_inter_table[w->cbp_table_index][cbp + 64][1], @@ -172,52 +177,62 @@ void ff_wmv2_encode_mb(MpegEncContext * s, /* motion vector */ ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); ff_msmpeg4_encode_motion(s, motion_x - pred_x, - motion_y - pred_y); + motion_y - pred_y); } else { /* compute cbp */ - cbp = 0; + cbp = 0; coded_cbp = 0; for (i = 0; i < 6; i++) { int val, pred; - val = (s->block_last_index[i] >= 1); + val = (s->block_last_index[i] >= 1); cbp |= val << (5 - i); if (i < 4) { /* predict value for close blocks only for luma */ - pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block); + pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block); *coded_block = val; - val = val ^ pred; + val = val ^ pred; } coded_cbp |= val << (5 - i); } - if (s->pict_type == AV_PICTURE_TYPE_I) { + if (s->pict_type == AV_PICTURE_TYPE_I) put_bits(&s->pb, - ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]); - } else { + ff_msmp4_mb_i_table[coded_cbp][1], + ff_msmp4_mb_i_table[coded_cbp][0]); + else put_bits(&s->pb, ff_wmv2_inter_table[w->cbp_table_index][cbp][1], ff_wmv2_inter_table[w->cbp_table_index][cbp][0]); - } put_bits(&s->pb, 1, 0); /* no AC prediction yet */ - if(s->inter_intra_pred){ - s->h263_aic_dir=0; - put_bits(&s->pb, ff_table_inter_intra[s->h263_aic_dir][1], ff_table_inter_intra[s->h263_aic_dir][0]); + if (s->inter_intra_pred) { + s->h263_aic_dir = 0; + put_bits(&s->pb, + ff_table_inter_intra[s->h263_aic_dir][1], + ff_table_inter_intra[s->h263_aic_dir][0]); } } - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) ff_msmpeg4_encode_block(s, block[i], i); - } } +static const AVClass wmv2_class = { + .class_name = "wmv2 encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_wmv2_encoder = { .name = "wmv2", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV2, .priv_data_size = sizeof(Wmv2Context), + .priv_class = &wmv2_class, .init = wmv2_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/wnv1.c b/libavcodec/wnv1.c index 7676c89..d0304c9 100644 --- a/libavcodec/wnv1.c +++ b/libavcodec/wnv1.c @@ -75,7 +75,7 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - rbuf = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + rbuf = av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!rbuf) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); return AVERROR(ENOMEM); @@ -157,5 +157,5 @@ AVCodec ff_wnv1_decoder = { .priv_data_size = sizeof(WNV1Context), .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c new file mode 100644 index 0000000..e1273e4 --- /dev/null +++ b/libavcodec/wrapped_avframe.c @@ -0,0 +1,73 @@ +/* + * AVFrame wrapper + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Simple wrapper to store an AVFrame and forward it as AVPacket. + */ + +#include "avcodec.h" +#include "internal.h" + +#include "libavutil/internal.h" +#include "libavutil/frame.h" +#include "libavutil/buffer.h" +#include "libavutil/pixdesc.h" + +static void wrapped_avframe_release_buffer(void *unused, uint8_t *data) +{ + AVFrame *frame = (AVFrame *)data; + + av_frame_free(&frame); +} + +static int wrapped_avframe_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + AVFrame *wrapped = av_frame_clone(frame); + + if (!wrapped) + return AVERROR(ENOMEM); + + pkt->buf = av_buffer_create((uint8_t *)wrapped, sizeof(*wrapped), + wrapped_avframe_release_buffer, NULL, + AV_BUFFER_FLAG_READONLY); + if (!pkt->buf) { + av_frame_free(&wrapped); + return AVERROR(ENOMEM); + } + + pkt->data = (uint8_t *)wrapped; + pkt->size = sizeof(*wrapped); + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +AVCodec ff_wrapped_avframe_encoder = { + .name = "wrapped_avframe", + .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WRAPPED_AVFRAME, + .encode2 = wrapped_avframe_encode, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/ws-snd1.c b/libavcodec/ws-snd1.c index fe6f812..11b7289 100644 --- a/libavcodec/ws-snd1.c +++ b/libavcodec/ws-snd1.c @@ -179,5 +179,5 @@ AVCodec ff_ws_snd1_decoder = { .id = AV_CODEC_ID_WESTWOOD_SND1, .init = ws_snd_decode_init, .decode = ws_snd_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index d06c5a1..204c856 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -1,5 +1,4 @@ OBJS += x86/constants.o \ - x86/fmtconvert_init.o \ # subsystems OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp_init.o @@ -9,6 +8,7 @@ OBJS-$(CONFIG_BSWAPDSP) += x86/bswapdsp_init.o OBJS-$(CONFIG_DCT) += x86/dct_init.o OBJS-$(CONFIG_FDCTDSP) += x86/fdctdsp_init.o OBJS-$(CONFIG_FFT) += x86/fft_init.o +OBJS-$(CONFIG_FMTCONVERT) += x86/fmtconvert_init.o OBJS-$(CONFIG_H263DSP) += x86/h263dsp_init.o OBJS-$(CONFIG_H264CHROMA) += x86/h264chroma_init.o OBJS-$(CONFIG_H264DSP) += x86/h264dsp_init.o @@ -19,6 +19,7 @@ OBJS-$(CONFIG_HUFFYUVDSP) += x86/huffyuvdsp_init.o OBJS-$(CONFIG_HUFFYUVENCDSP) += x86/huffyuvencdsp_mmx.o OBJS-$(CONFIG_IDCTDSP) += x86/idctdsp_init.o OBJS-$(CONFIG_LPC) += x86/lpc.o +OBJS-$(CONFIG_MDCT) += x86/mdct_init.o OBJS-$(CONFIG_ME_CMP) += x86/me_cmp_init.o OBJS-$(CONFIG_MPEGAUDIODSP) += x86/mpegaudiodsp.o OBJS-$(CONFIG_MPEGVIDEO) += x86/mpegvideo.o \ @@ -27,8 +28,11 @@ OBJS-$(CONFIG_MPEGVIDEOENC) += x86/mpegvideoenc.o \ x86/mpegvideoencdsp_init.o OBJS-$(CONFIG_PIXBLOCKDSP) += x86/pixblockdsp_init.o OBJS-$(CONFIG_QPELDSP) += x86/qpeldsp_init.o +OBJS-$(CONFIG_RV34DSP) += x86/rv34dsp_init.o +OBJS-$(CONFIG_VC1DSP) += x86/vc1dsp_init.o OBJS-$(CONFIG_VIDEODSP) += x86/videodsp_init.o OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp_init.o +OBJS-$(CONFIG_VP8DSP) += x86/vp8dsp_init.o OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o # decoders/encoders @@ -42,46 +46,38 @@ OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct_init.o OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o -OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp_init.o -OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp_init.o \ - x86/rv40dsp_init.o +OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp_init.o OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o -OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_init.o +OBJS-$(CONFIG_V210_ENCODER) += x86/v210enc_init.o OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp_init.o +OBJS-$(CONFIG_VP3_DECODER) += x86/hpeldsp_vp3_init.o OBJS-$(CONFIG_VP6_DECODER) += x86/vp6dsp_init.o -OBJS-$(CONFIG_VP7_DECODER) += x86/vp8dsp_init.o -OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp_init.o OBJS-$(CONFIG_VP9_DECODER) += x86/vp9dsp_init.o # GCC inline assembly optimizations # subsystems MMX-OBJS-$(CONFIG_AUDIODSP) += x86/audiodsp_mmx.o +MMX-OBJS-$(CONFIG_FDCTDSP) += x86/fdct.o MMX-OBJS-$(CONFIG_HPELDSP) += x86/fpel_mmx.o \ x86/hpeldsp_mmx.o -MMX-OBJS-$(CONFIG_FDCTDSP) += x86/fdct.o MMX-OBJS-$(CONFIG_IDCTDSP) += x86/idctdsp_mmx.o \ x86/simple_idct.o MMX-OBJS-$(CONFIG_QPELDSP) += x86/fpel_mmx.o +MMX-OBJS-$(CONFIG_VC1DSP) += x86/vc1dsp_mmx.o # decoders/encoders -MMX-OBJS-$(CONFIG_MPEG4_DECODER) += x86/idct_mmx_xvid.o \ - x86/idct_sse2_xvid.o -MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o - - -# YASM optimizations -YASM-OBJS += x86/deinterlace.o \ - x86/fmtconvert.o \ +MMX-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct_mmx.o \ + x86/xvididct_sse2.o # subsystems YASM-OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp.o YASM-OBJS-$(CONFIG_AUDIODSP) += x86/audiodsp.o YASM-OBJS-$(CONFIG_BSWAPDSP) += x86/bswapdsp.o YASM-OBJS-$(CONFIG_DCT) += x86/dct32.o -YASM-OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o YASM-OBJS-$(CONFIG_FFT) += x86/fft.o +YASM-OBJS-$(CONFIG_FMTCONVERT) += x86/fmtconvert.o YASM-OBJS-$(CONFIG_H263DSP) += x86/h263_loopfilter.o YASM-OBJS-$(CONFIG_H264CHROMA) += x86/h264_chromamc.o \ x86/h264_chromamc_10bit.o @@ -107,24 +103,26 @@ YASM-OBJS-$(CONFIG_PIXBLOCKDSP) += x86/pixblockdsp.o YASM-OBJS-$(CONFIG_QPELDSP) += x86/qpeldsp.o \ x86/fpel.o \ x86/qpel.o +YASM-OBJS-$(CONFIG_RV34DSP) += x86/rv34dsp.o +YASM-OBJS-$(CONFIG_VC1DSP) += x86/vc1dsp.o YASM-OBJS-$(CONFIG_VIDEODSP) += x86/videodsp.o YASM-OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp.o +YASM-OBJS-$(CONFIG_VP8DSP) += x86/vp8dsp.o \ + x86/vp8dsp_loopfilter.o # decoders/encoders YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp.o YASM-OBJS-$(CONFIG_APE_DECODER) += x86/apedsp.o YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o -YASM-OBJS-$(CONFIG_HEVC_DECODER) += x86/hevc_deblock.o +YASM-OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o +YASM-OBJS-$(CONFIG_HEVC_DECODER) += x86/hevc_deblock.o \ + x86/hevc_mc.o \ + x86/hevc_idct.o YASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o YASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o -YASM-OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp.o -YASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp.o \ - x86/rv40dsp.o -YASM-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp.o +YASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o +YASM-OBJS-$(CONFIG_V210_ENCODER) += x86/v210enc.o YASM-OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp.o +YASM-OBJS-$(CONFIG_VP3_DECODER) += x86/hpeldsp_vp3.o YASM-OBJS-$(CONFIG_VP6_DECODER) += x86/vp6dsp.o -YASM-OBJS-$(CONFIG_VP7_DECODER) += x86/vp8dsp.o \ - x86/vp8dsp_loopfilter.o -YASM-OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp.o \ - x86/vp8dsp_loopfilter.o -YASM-OBJS-$(CONFIG_VP9_DECODER) += x86/vp9dsp.o +YASM-OBJS-$(CONFIG_VP9_DECODER) += x86/vp9mc.o diff --git a/libavcodec/x86/ac3dsp_init.c b/libavcodec/x86/ac3dsp_init.c index cd638b9..89044f4 100644 --- a/libavcodec/x86/ac3dsp_init.c +++ b/libavcodec/x86/ac3dsp_init.c @@ -47,7 +47,6 @@ void ff_float_to_fixed24_sse2 (int32_t *dst, const float *src, unsigned int len) int ff_ac3_compute_mantissa_size_sse2(uint16_t mant_cnt[6][16]); -void ff_ac3_extract_exponents_3dnow(uint8_t *exp, int32_t *coef, int nb_coefs); void ff_ac3_extract_exponents_sse2 (uint8_t *exp, int32_t *coef, int nb_coefs); void ff_ac3_extract_exponents_ssse3(uint8_t *exp, int32_t *coef, int nb_coefs); @@ -224,16 +223,19 @@ av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact) c->float_to_fixed24 = ff_float_to_fixed24_sse2; c->compute_mantissa_size = ff_ac3_compute_mantissa_size_sse2; c->extract_exponents = ff_ac3_extract_exponents_sse2; - if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { - c->ac3_lshift_int16 = ff_ac3_lshift_int16_sse2; - c->ac3_rshift_int32 = ff_ac3_rshift_int32_sse2; - } if (bit_exact) { c->apply_window_int16 = ff_apply_window_int16_sse2; - } else if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { + } + } + + if (EXTERNAL_SSE2_FAST(cpu_flags)) { + c->ac3_lshift_int16 = ff_ac3_lshift_int16_sse2; + c->ac3_rshift_int32 = ff_ac3_rshift_int32_sse2; + if (!bit_exact) { c->apply_window_int16 = ff_apply_window_int16_round_sse2; } } + if (EXTERNAL_SSSE3(cpu_flags)) { c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_ssse3; if (cpu_flags & AV_CPU_FLAG_ATOM) { diff --git a/libavcodec/x86/apedsp.asm b/libavcodec/x86/apedsp.asm index d721ebd..d6abd98 100644 --- a/libavcodec/x86/apedsp.asm +++ b/libavcodec/x86/apedsp.asm @@ -20,7 +20,7 @@ %include "libavutil/x86/x86util.asm" -SECTION_TEXT +SECTION .text %macro SCALARPRODUCT 0 ; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, diff --git a/libavcodec/x86/audiodsp.asm b/libavcodec/x86/audiodsp.asm index f2e831d..d7e63eb 100644 --- a/libavcodec/x86/audiodsp.asm +++ b/libavcodec/x86/audiodsp.asm @@ -21,12 +21,12 @@ %include "libavutil/x86/x86util.asm" -SECTION_TEXT +SECTION .text %macro SCALARPRODUCT 0 ; int ff_scalarproduct_int16(int16_t *v1, int16_t *v2, int order) cglobal scalarproduct_int16, 3,3,3, v1, v2, order - shl orderq, 1 + add orderd, orderd add v1q, orderq add v2q, orderq neg orderq @@ -80,17 +80,17 @@ cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len SPLATD m4 SPLATD m5 .loop: -%assign %%i 1 +%assign %%i 0 %rep %2 - mova m0, [srcq+mmsize*0*%%i] - mova m1, [srcq+mmsize*1*%%i] - mova m2, [srcq+mmsize*2*%%i] - mova m3, [srcq+mmsize*3*%%i] + mova m0, [srcq + mmsize * (0 + %%i)] + mova m1, [srcq + mmsize * (1 + %%i)] + mova m2, [srcq + mmsize * (2 + %%i)] + mova m3, [srcq + mmsize * (3 + %%i)] %if %3 - mova m7, [srcq+mmsize*4*%%i] - mova m8, [srcq+mmsize*5*%%i] - mova m9, [srcq+mmsize*6*%%i] - mova m10, [srcq+mmsize*7*%%i] + mova m7, [srcq + mmsize * (4 + %%i)] + mova m8, [srcq + mmsize * (5 + %%i)] + mova m9, [srcq + mmsize * (6 + %%i)] + mova m10, [srcq + mmsize * (7 + %%i)] %endif CLIPD m0, m4, m5, m6 CLIPD m1, m4, m5, m6 @@ -102,17 +102,17 @@ cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len CLIPD m9, m4, m5, m6 CLIPD m10, m4, m5, m6 %endif - mova [dstq+mmsize*0*%%i], m0 - mova [dstq+mmsize*1*%%i], m1 - mova [dstq+mmsize*2*%%i], m2 - mova [dstq+mmsize*3*%%i], m3 + mova [dstq + mmsize * (0 + %%i)], m0 + mova [dstq + mmsize * (1 + %%i)], m1 + mova [dstq + mmsize * (2 + %%i)], m2 + mova [dstq + mmsize * (3 + %%i)], m3 %if %3 - mova [dstq+mmsize*4*%%i], m7 - mova [dstq+mmsize*5*%%i], m8 - mova [dstq+mmsize*6*%%i], m9 - mova [dstq+mmsize*7*%%i], m10 + mova [dstq + mmsize * (4 + %%i)], m7 + mova [dstq + mmsize * (5 + %%i)], m8 + mova [dstq + mmsize * (6 + %%i)], m9 + mova [dstq + mmsize * (7 + %%i)], m10 %endif -%assign %%i %%i+1 +%assign %%i (%%i + 4 * (1 + %3)) %endrep add srcq, mmsize*4*(%2+%3) add dstq, mmsize*4*(%2+%3) diff --git a/libavcodec/x86/audiodsp_init.c b/libavcodec/x86/audiodsp_init.c index 743f5a3..8eb2e56 100644 --- a/libavcodec/x86/audiodsp_init.c +++ b/libavcodec/x86/audiodsp_init.c @@ -21,7 +21,6 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/audiodsp.h" #include "audiodsp.h" diff --git a/libavcodec/x86/blockdsp.c b/libavcodec/x86/blockdsp.c index b529424..f14bb1f 100644 --- a/libavcodec/x86/blockdsp.c +++ b/libavcodec/x86/blockdsp.c @@ -33,18 +33,18 @@ static void name(int16_t *blocks) \ { \ __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "mov %1, %%"REG_a" \n\t" \ - "1: \n\t" \ - "movq %%mm7, (%0, %%"REG_a") \n\t" \ - "movq %%mm7, 8(%0, %%"REG_a") \n\t" \ - "movq %%mm7, 16(%0, %%"REG_a") \n\t" \ - "movq %%mm7, 24(%0, %%"REG_a") \n\t" \ - "add $32, %%"REG_a" \n\t" \ - "js 1b \n\t" \ + "pxor %%mm7, %%mm7 \n\t" \ + "mov %1, %%"FF_REG_a" \n\t" \ + "1: \n\t" \ + "movq %%mm7, (%0, %%"FF_REG_a") \n\t" \ + "movq %%mm7, 8(%0, %%"FF_REG_a") \n\t" \ + "movq %%mm7, 16(%0, %%"FF_REG_a") \n\t" \ + "movq %%mm7, 24(%0, %%"FF_REG_a") \n\t" \ + "add $32, %%"FF_REG_a" \n\t" \ + "js 1b \n\t" \ :: "r"(((uint8_t *) blocks) + 128 * n), \ "i"(-128 * n) \ - : "%"REG_a); \ + : "%"FF_REG_a); \ } CLEAR_BLOCKS(clear_blocks_mmx, 6) CLEAR_BLOCKS(clear_block_mmx, 1) @@ -68,21 +68,21 @@ static void clear_block_sse(int16_t *block) static void clear_blocks_sse(int16_t *blocks) { __asm__ volatile ( - "xorps %%xmm0, %%xmm0 \n" - "mov %1, %%"REG_a" \n" - "1: \n" - "movaps %%xmm0, (%0, %%"REG_a") \n" - "movaps %%xmm0, 16(%0, %%"REG_a") \n" - "movaps %%xmm0, 32(%0, %%"REG_a") \n" - "movaps %%xmm0, 48(%0, %%"REG_a") \n" - "movaps %%xmm0, 64(%0, %%"REG_a") \n" - "movaps %%xmm0, 80(%0, %%"REG_a") \n" - "movaps %%xmm0, 96(%0, %%"REG_a") \n" - "movaps %%xmm0, 112(%0, %%"REG_a") \n" - "add $128, %%"REG_a" \n" - "js 1b \n" + "xorps %%xmm0, %%xmm0 \n" + "mov %1, %%"FF_REG_a" \n" + "1: \n" + "movaps %%xmm0, (%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 16(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 32(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 48(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 64(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 80(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 96(%0, %%"FF_REG_a") \n" + "movaps %%xmm0, 112(%0, %%"FF_REG_a") \n" + "add $128, %%"FF_REG_a" \n" + "js 1b \n" :: "r"(((uint8_t *) blocks) + 128 * 6), "i"(-128 * 6) - : "%"REG_a); + : "%"FF_REG_a); } #endif /* HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/bswapdsp.asm b/libavcodec/x86/bswapdsp.asm index 17a6cb1..4810867 100644 --- a/libavcodec/x86/bswapdsp.asm +++ b/libavcodec/x86/bswapdsp.asm @@ -24,12 +24,12 @@ SECTION_RODATA pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 -SECTION_TEXT +SECTION .text ; %1 = aligned/unaligned %macro BSWAP_LOOPS 1 - mov r3, r2 - sar r2, 3 + mov r3d, r2d + sar r2d, 3 jz .left4_%1 .loop8_%1: mov%1 m0, [r1 + 0] @@ -57,11 +57,11 @@ SECTION_TEXT %endif add r0, 32 add r1, 32 - dec r2 + dec r2d jnz .loop8_%1 .left4_%1: - mov r2, r3 - and r3, 4 + mov r2d, r3d + test r3d, 4 jz .left mov%1 m0, [r1] %if cpuflag(ssse3) @@ -84,13 +84,11 @@ SECTION_TEXT %macro BSWAP32_BUF 0 %if cpuflag(ssse3) cglobal bswap32_buf, 3,4,3 - mov r3, r1 mova m2, [pb_bswap32] %else cglobal bswap32_buf, 3,4,5 - mov r3, r1 %endif - and r3, 15 + test r1, 15 jz .start_align BSWAP_LOOPS u jmp .left @@ -98,8 +96,7 @@ cglobal bswap32_buf, 3,4,5 BSWAP_LOOPS a .left: %if cpuflag(ssse3) - mov r3, r2 - and r2, 2 + test r2d, 2 jz .left1 movq m0, [r1] pshufb m0, m2 @@ -107,13 +104,13 @@ cglobal bswap32_buf, 3,4,5 add r1, 8 add r0, 8 .left1: - and r3, 1 + test r2d, 1 jz .end mov r2d, [r1] bswap r2d mov [r0], r2d %else - and r2, 3 + and r2d, 3 jz .end .loop2: mov r3d, [r1] @@ -121,7 +118,7 @@ cglobal bswap32_buf, 3,4,5 mov [r0], r3d add r1, 4 add r0, 4 - dec r2 + dec r2d jnz .loop2 %endif .end: diff --git a/libavcodec/x86/cabac.h b/libavcodec/x86/cabac.h index d1701bf..205511e 100644 --- a/libavcodec/x86/cabac.h +++ b/libavcodec/x86/cabac.h @@ -42,7 +42,7 @@ "sub "tmp" , "low" \n\t" #else /* HAVE_FAST_CMOV */ #define BRANCHLESS_GET_CABAC_UPDATE(ret, retq, low, range, tmp) \ -/* P4 Prescott has crappy cmov,sbb,64bit shift so avoid them */ \ +/* P4 Prescott has crappy cmov,sbb,64-bit shift so avoid them */ \ "sub "low" , "tmp" \n\t"\ "sar $31 , "tmp" \n\t"\ "sub %%ecx , "range" \n\t"\ @@ -72,12 +72,12 @@ "mov "tmpbyte" , "statep" \n\t"\ "test "lowword" , "lowword" \n\t"\ "jnz 2f \n\t"\ - "mov "byte" , %%"REG_c" \n\t"\ - "cmp "end" , %%"REG_c" \n\t"\ + "mov "byte" , %%"FF_REG_c" \n\t"\ + "cmp "end" , %%"FF_REG_c" \n\t"\ "jge 1f \n\t"\ - "add"OPSIZE" $2 , "byte" \n\t"\ + "add"FF_OPSIZE" $2 , "byte" \n\t"\ "1: \n\t"\ - "movzwl (%%"REG_c") , "tmp" \n\t"\ + "movzwl (%%"FF_REG_c"), "tmp" \n\t"\ "lea -1("low") , %%ecx \n\t"\ "xor "low" , %%ecx \n\t"\ "shr $15 , %%ecx \n\t"\ @@ -133,12 +133,12 @@ "mov "tmpbyte" , "statep" \n\t"\ "test "lowword" , "lowword" \n\t"\ " jnz 2f \n\t"\ - "mov "byte" , %%"REG_c" \n\t"\ - "cmp "end" , %%"REG_c" \n\t"\ + "mov "byte" , %%"FF_REG_c" \n\t"\ + "cmp "end" , %%"FF_REG_c" \n\t"\ "jge 1f \n\t"\ - "add"OPSIZE" $2 , "byte" \n\t"\ + "add"FF_OPSIZE" $2 , "byte" \n\t"\ "1: \n\t"\ - "movzwl (%%"REG_c") , "tmp" \n\t"\ + "movzwl (%%"FF_REG_c") , "tmp" \n\t"\ "lea -1("low") , %%ecx \n\t"\ "xor "low" , %%ecx \n\t"\ "shr $15 , %%ecx \n\t"\ @@ -183,7 +183,7 @@ static av_always_inline int get_cabac_inline_x86(CABACContext *c, "i"(offsetof(CABACContext, bytestream)), "i"(offsetof(CABACContext, bytestream_end)) TABLES_ARG - : "%"REG_c, "memory" + : "%"FF_REG_c, "memory" ); return bit & 1; } @@ -214,7 +214,7 @@ static av_always_inline int get_cabac_bypass_sign_x86(CABACContext *c, int val) "addl %%edx, %%eax \n\t" "cmp %c5(%2), %1 \n\t" "jge 1f \n\t" - "add"OPSIZE" $2, %c4(%2) \n\t" + "add"FF_OPSIZE" $2, %c4(%2) \n\t" "1: \n\t" "movl %%eax, %c3(%2) \n\t" @@ -254,7 +254,7 @@ static av_always_inline int get_cabac_bypass_x86(CABACContext *c) "addl %%ecx, %%eax \n\t" "cmp %c5(%2), %1 \n\t" "jge 1f \n\t" - "add"OPSIZE" $2, %c4(%2) \n\t" + "add"FF_OPSIZE" $2, %c4(%2) \n\t" "1: \n\t" "movl %%eax, %c3(%2) \n\t" diff --git a/libavcodec/x86/cavsdsp.c b/libavcodec/x86/cavsdsp.c index 39eec4b..b5406ef 100644 --- a/libavcodec/x86/cavsdsp.c +++ b/libavcodec/x86/cavsdsp.c @@ -136,7 +136,7 @@ static inline void cavs_idct8_1d(int16_t *block, uint64_t bias) SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\ SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */ -static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) +static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, ptrdiff_t stride) { int i; DECLARE_ALIGNED(8, int16_t, b2)[64]; @@ -332,7 +332,8 @@ static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) } #define QPEL_CAVS(OPNAME, OP, MMX)\ -static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{\ int h=8;\ __asm__ volatile(\ "pxor %%mm7, %%mm7 \n\t"\ @@ -379,43 +380,53 @@ static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, const uint8_t *src, int );\ }\ \ -static inline void OPNAME ## cavs_qpel8or16_v1_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h){\ +static inline void OPNAME ## cavs_qpel8or16_v1_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride, int h){\ +static inline void OPNAME ## cavs_qpel8or16_v2_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride, int h){\ +static inline void OPNAME ## cavs_qpel8or16_v3_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel8_v1_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst , src , dstStride, srcStride, 8);\ }\ -static void OPNAME ## cavs_qpel16_v1_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel16_v1_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel8_v2_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst , src , dstStride, srcStride, 8);\ }\ -static void OPNAME ## cavs_qpel16_v2_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel16_v2_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel8_v3_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst , src , dstStride, srcStride, 8);\ }\ -static void OPNAME ## cavs_qpel16_v3_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel16_v3_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t 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, const uint8_t *src, int dstStride, int srcStride){\ +static void OPNAME ## cavs_qpel16_h_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride)\ +{ \ OPNAME ## cavs_qpel8_h_ ## MMX(dst , src , dstStride, srcStride);\ OPNAME ## cavs_qpel8_h_ ## MMX(dst+8, src+8, dstStride, srcStride);\ src += 8*srcStride;\ diff --git a/libavcodec/x86/constants.c b/libavcodec/x86/constants.c index 5b8d1b2..6f7dd73 100644 --- a/libavcodec/x86/constants.c +++ b/libavcodec/x86/constants.c @@ -43,8 +43,11 @@ DECLARE_ALIGNED(16, const xmm_reg, ff_pw_64) = { 0x0040004000400040ULL, 0x004 DECLARE_ALIGNED(8, const uint64_t, ff_pw_96) = 0x0060006000600060ULL; DECLARE_ALIGNED(8, const uint64_t, ff_pw_128) = 0x0080008000800080ULL; DECLARE_ALIGNED(8, const uint64_t, ff_pw_255) = 0x00ff00ff00ff00ffULL; +DECLARE_ALIGNED(32, const ymm_reg, ff_pw_256) = { 0x0100010001000100ULL, 0x0100010001000100ULL, + 0x0100010001000100ULL, 0x0100010001000100ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_512) = { 0x0200020002000200ULL, 0x0200020002000200ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_1019) = { 0x03FB03FB03FB03FBULL, 0x03FB03FB03FB03FBULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_m1) = { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pb_0) = { 0x0000000000000000ULL, 0x0000000000000000ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pb_1) = { 0x0101010101010101ULL, 0x0101010101010101ULL }; diff --git a/libavcodec/x86/constants.h b/libavcodec/x86/constants.h index f38fbe3..59ff947 100644 --- a/libavcodec/x86/constants.h +++ b/libavcodec/x86/constants.h @@ -42,6 +42,9 @@ extern const xmm_reg ff_pw_64; extern const uint64_t ff_pw_96; extern const uint64_t ff_pw_128; extern const uint64_t ff_pw_255; +extern const ymm_reg ff_pw_256; +extern const xmm_reg ff_pw_512; +extern const xmm_reg ff_pw_m1; extern const xmm_reg ff_pb_1; extern const xmm_reg ff_pb_3; diff --git a/libavcodec/x86/dcadsp.asm b/libavcodec/x86/dcadsp.asm index c42ee23..89d4ac4 100644 --- a/libavcodec/x86/dcadsp.asm +++ b/libavcodec/x86/dcadsp.asm @@ -24,93 +24,7 @@ SECTION_RODATA pf_inv16: times 4 dd 0x3D800000 ; 1/16 -SECTION_TEXT - -; void decode_hf(float dst[DCA_SUBBANDS][8], const int32_t vq_num[DCA_SUBBANDS], -; const int8_t hf_vq[1024][32], intptr_t vq_offset, -; int32_t scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end) - -%macro DECODE_HF 0 -cglobal decode_hf, 6,6,5, dst, num, src, offset, scale, start, end - lea srcq, [srcq + offsetq] - shl startq, 2 - mov offsetd, endm -%define DICT offsetq - shl offsetq, 2 - mov endm, offsetq -.loop: -%if ARCH_X86_64 - mov offsetd, [scaleq + 2 * startq] - cvtsi2ss m0, offsetd -%else - cvtsi2ss m0, [scaleq + 2 * startq] -%endif - mov offsetd, [numq + startq] - mulss m0, [pf_inv16] - shl DICT, 5 - shufps m0, m0, 0 -%if cpuflag(sse2) -%if cpuflag(sse4) - pmovsxbd m1, [srcq + DICT + 0] - pmovsxbd m2, [srcq + DICT + 4] -%else - movq m1, [srcq + DICT] - punpcklbw m1, m1 - mova m2, m1 - punpcklwd m1, m1 - punpckhwd m2, m2 - psrad m1, 24 - psrad m2, 24 -%endif - cvtdq2ps m1, m1 - cvtdq2ps m2, m2 -%else - movd mm0, [srcq + DICT + 0] - movd mm1, [srcq + DICT + 4] - punpcklbw mm0, mm0 - punpcklbw mm1, mm1 - movq mm2, mm0 - movq mm3, mm1 - punpcklwd mm0, mm0 - punpcklwd mm1, mm1 - punpckhwd mm2, mm2 - punpckhwd mm3, mm3 - psrad mm0, 24 - psrad mm1, 24 - psrad mm2, 24 - psrad mm3, 24 - cvtpi2ps m1, mm0 - cvtpi2ps m2, mm1 - cvtpi2ps m3, mm2 - cvtpi2ps m4, mm3 - shufps m0, m0, 0 - shufps m1, m3, q1010 - shufps m2, m4, q1010 -%endif - mulps m1, m0 - mulps m2, m0 - mova [dstq + 8 * startq + 0], m1 - mova [dstq + 8 * startq + 16], m2 - add startq, 4 - cmp startq, endm - jl .loop -.end: -%if notcpuflag(sse2) - emms -%endif - REP_RET -%endmacro - -%if ARCH_X86_32 -INIT_XMM sse -DECODE_HF -%endif - -INIT_XMM sse2 -DECODE_HF - -INIT_XMM sse4 -DECODE_HF +SECTION .text ; %1=v0/v1 %2=in1 %3=in2 %macro FIR_LOOP 2-3 @@ -148,7 +62,7 @@ DECODE_HF addps m4, va ; va1+3 vb1+3 va2+4 vb2+4 movhlps vb, m4 ; va1+3 vb1+3 addps vb, m4 ; va0..4 vb0..4 - movh [outq + count], vb + movlps [outq + count], vb %if %1 sub cf0q, 8*NUM_COEF %endif diff --git a/libavcodec/x86/dcadsp_init.c b/libavcodec/x86/dcadsp_init.c index 9acb818..8632c4a 100644 --- a/libavcodec/x86/dcadsp_init.c +++ b/libavcodec/x86/dcadsp_init.c @@ -23,15 +23,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/dcadsp.h" -void ff_decode_hf_sse(float dst[DCA_SUBBANDS][8], const int vq_num[DCA_SUBBANDS], - const int8_t hf_vq[1024][32], intptr_t vq_offset, - int scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end); -void ff_decode_hf_sse2(float dst[DCA_SUBBANDS][8], const int vq_num[DCA_SUBBANDS], - const int8_t hf_vq[1024][32], intptr_t vq_offset, - int scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end); -void ff_decode_hf_sse4(float dst[DCA_SUBBANDS][8], const int vq_num[DCA_SUBBANDS], - const int8_t hf_vq[1024][32], intptr_t vq_offset, - int scale[DCA_SUBBANDS][2], intptr_t start, intptr_t end); void ff_dca_lfe_fir0_sse(float *out, const float *in, const float *coefs); void ff_dca_lfe_fir1_sse(float *out, const float *in, const float *coefs); @@ -40,20 +31,9 @@ av_cold void ff_dcadsp_init_x86(DCADSPContext *s) int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_SSE(cpu_flags)) { -#if ARCH_X86_32 - s->decode_hf = ff_decode_hf_sse; -#endif s->lfe_fir[0] = ff_dca_lfe_fir0_sse; s->lfe_fir[1] = ff_dca_lfe_fir1_sse; } - - if (EXTERNAL_SSE2(cpu_flags)) { - s->decode_hf = ff_decode_hf_sse2; - } - - if (EXTERNAL_SSE4(cpu_flags)) { - s->decode_hf = ff_decode_hf_sse4; - } } @@ -98,10 +78,10 @@ av_cold void ff_synth_filter_init_x86(SynthFilterContext *s) if (EXTERNAL_SSE2(cpu_flags)) { s->synth_filter_float = synth_filter_sse2; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { s->synth_filter_float = synth_filter_avx; } - if (EXTERNAL_FMA3(cpu_flags)) { + if (EXTERNAL_FMA3(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_AVXSLOW)) { s->synth_filter_float = synth_filter_fma3; } #endif /* HAVE_YASM */ diff --git a/libavcodec/x86/dct32.asm b/libavcodec/x86/dct32.asm index 9c147b9..2c4c32e 100644 --- a/libavcodec/x86/dct32.asm +++ b/libavcodec/x86/dct32.asm @@ -191,7 +191,7 @@ ps_p1p1m1m1: dd 0, 0, 0x80000000, 0x80000000, 0, 0, 0x80000000, 0x80000000 %endmacro INIT_YMM avx -SECTION_TEXT +SECTION .text ; void ff_dct32_float_avx(FFTSample *out, const FFTSample *in) cglobal dct32_float, 2,3,8, out, in, tmp ; pass 1 @@ -482,7 +482,10 @@ cglobal dct32_float, 2, 3, 16, out, in, tmp %endif %endmacro +%if ARCH_X86_32 INIT_XMM sse DCT32_FUNC +%endif + INIT_XMM sse2 DCT32_FUNC diff --git a/libavcodec/x86/dct_init.c b/libavcodec/x86/dct_init.c index 7bda5e8..b2e43a9 100644 --- a/libavcodec/x86/dct_init.c +++ b/libavcodec/x86/dct_init.c @@ -30,10 +30,12 @@ av_cold void ff_dct_init_x86(DCTContext *s) { int cpu_flags = av_get_cpu_flags(); +#if ARCH_X86_32 if (EXTERNAL_SSE(cpu_flags)) s->dct32 = ff_dct32_float_sse; +#endif if (EXTERNAL_SSE2(cpu_flags)) s->dct32 = ff_dct32_float_sse2; - if (EXTERNAL_AVX(cpu_flags)) + if (EXTERNAL_AVX_FAST(cpu_flags)) s->dct32 = ff_dct32_float_avx; } diff --git a/libavcodec/x86/deinterlace.asm b/libavcodec/x86/deinterlace.asm deleted file mode 100644 index 70d000e..0000000 --- a/libavcodec/x86/deinterlace.asm +++ /dev/null @@ -1,82 +0,0 @@ -;****************************************************************************** -;* SIMD-optimized deinterlacing functions -;* Copyright (c) 2010 Vitor Sessak -;* Copyright (c) 2002 Michael Niedermayer -;* -;* This file is part of Libav. -;* -;* Libav is free software; you can redistribute it and/or -;* modify it under the terms of the GNU Lesser General Public -;* License as published by the Free Software Foundation; either -;* version 2.1 of the License, or (at your option) any later version. -;* -;* Libav is distributed in the hope that it will be useful, -;* but WITHOUT ANY WARRANTY; without even the implied warranty of -;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;* Lesser General Public License for more details. -;* -;* You should have received a copy of the GNU Lesser General Public -;* License along with Libav; if not, write to the Free Software -;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -;****************************************************************************** - -%include "libavutil/x86/x86util.asm" - -SECTION_RODATA - -cextern pw_4 - -SECTION .text - -%macro DEINTERLACE 1 -%ifidn %1, inplace -;void ff_deinterlace_line_inplace_mmx(const uint8_t *lum_m4, const uint8_t *lum_m3, const uint8_t *lum_m2, const uint8_t *lum_m1, const uint8_t *lum, int size) -cglobal deinterlace_line_inplace_mmx, 6,6,7, lum_m4, lum_m3, lum_m2, lum_m1, lum, size -%else -;void ff_deinterlace_line_mmx(uint8_t *dst, const uint8_t *lum_m4, const uint8_t *lum_m3, const uint8_t *lum_m2, const uint8_t *lum_m1, const uint8_t *lum, int size) -cglobal deinterlace_line_mmx, 7,7,7, dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size -%endif - pxor mm7, mm7 - movq mm6, [pw_4] -.nextrow: - movd mm0, [lum_m4q] - movd mm1, [lum_m3q] - movd mm2, [lum_m2q] -%ifidn %1, inplace - movd [lum_m4q], mm2 -%endif - movd mm3, [lum_m1q] - movd mm4, [lumq] - punpcklbw mm0, mm7 - punpcklbw mm1, mm7 - punpcklbw mm2, mm7 - punpcklbw mm3, mm7 - punpcklbw mm4, mm7 - paddw mm1, mm3 - psllw mm2, 1 - paddw mm0, mm4 - psllw mm1, 2 - paddw mm2, mm6 - paddw mm1, mm2 - psubusw mm1, mm0 - psrlw mm1, 3 - packuswb mm1, mm7 -%ifidn %1, inplace - movd [lum_m2q], mm1 -%else - movd [dstq], mm1 - add dstq, 4 -%endif - add lum_m4q, 4 - add lum_m3q, 4 - add lum_m2q, 4 - add lum_m1q, 4 - add lumq, 4 - sub sized, 4 - jg .nextrow - REP_RET -%endmacro - -DEINTERLACE "" - -DEINTERLACE inplace diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index e4744a3..ef007f4 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -90,7 +90,7 @@ cextern cos_ %+ i %1 %endmacro -SECTION_TEXT +SECTION .text %macro T2_3DNOW 4 ; z0, z1, mem0, mem1 mova %1, %3 @@ -655,68 +655,6 @@ cglobal fft_permute, 2,7,1 jl .loopcopy REP_RET -%macro IMDCT_CALC_FUNC 0 -cglobal imdct_calc, 3,5,3 - mov r3d, [r0 + FFTContext.mdctsize] - mov r4, [r0 + FFTContext.imdcthalf] - add r1, r3 - PUSH r3 - PUSH r1 -%if ARCH_X86_32 - push r2 - push r1 - push r0 -%else - sub rsp, 8+32*WIN64 ; allocate win64 shadow space -%endif - call r4 -%if ARCH_X86_32 - add esp, 12 -%else - add rsp, 8+32*WIN64 -%endif - POP r1 - POP r3 - lea r0, [r1 + 2*r3] - mov r2, r3 - sub r3, mmsize - neg r2 - mova m2, [ps_m1m1m1m1] -.loop: -%if mmsize == 8 - PSWAPD m0, [r1 + r3] - PSWAPD m1, [r0 + r2] - pxor m0, m2 -%else - mova m0, [r1 + r3] - mova m1, [r0 + r2] - shufps m0, m0, 0x1b - shufps m1, m1, 0x1b - xorps m0, m2 -%endif - mova [r0 + r3], m1 - mova [r1 + r2], m0 - sub r3, mmsize - add r2, mmsize - jl .loop -%if cpuflag(3dnow) - femms - RET -%else - REP_RET -%endif -%endmacro - -%if ARCH_X86_32 -INIT_MMX 3dnow -IMDCT_CALC_FUNC -INIT_MMX 3dnowext -IMDCT_CALC_FUNC -%endif - -INIT_XMM sse -IMDCT_CALC_FUNC - %if ARCH_X86_32 INIT_MMX 3dnow %define mulps pfmul @@ -791,6 +729,70 @@ DECL_FFT 4 DECL_FFT 4, _interleave %endif +%if CONFIG_MDCT + +%macro IMDCT_CALC_FUNC 0 +cglobal imdct_calc, 3,5,3 + mov r3d, [r0 + FFTContext.mdctsize] + mov r4, [r0 + FFTContext.imdcthalf] + add r1, r3 + PUSH r3 + PUSH r1 +%if ARCH_X86_32 + push r2 + push r1 + push r0 +%else + sub rsp, 8+32*WIN64 ; allocate win64 shadow space +%endif + call r4 +%if ARCH_X86_32 + add esp, 12 +%else + add rsp, 8+32*WIN64 +%endif + POP r1 + POP r3 + lea r0, [r1 + 2*r3] + mov r2, r3 + sub r3, mmsize + neg r2 + mova m2, [ps_m1m1m1m1] +.loop: +%if mmsize == 8 + PSWAPD m0, [r1 + r3] + PSWAPD m1, [r0 + r2] + pxor m0, m2 +%else + mova m0, [r1 + r3] + mova m1, [r0 + r2] + shufps m0, m0, 0x1b + shufps m1, m1, 0x1b + xorps m0, m2 +%endif + mova [r0 + r3], m1 + mova [r1 + r2], m0 + sub r3, mmsize + add r2, mmsize + jl .loop +%if cpuflag(3dnow) + femms + RET +%else + REP_RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX 3dnow +IMDCT_CALC_FUNC +INIT_MMX 3dnowext +IMDCT_CALC_FUNC +%endif + +INIT_XMM sse +IMDCT_CALC_FUNC + INIT_XMM sse %undef mulps %undef addps @@ -1081,3 +1083,5 @@ DECL_IMDCT POSROTATESHUF_3DNOW INIT_YMM avx DECL_IMDCT POSROTATESHUF_AVX + +%endif ; CONFIG_MDCT diff --git a/libavcodec/x86/fft.h b/libavcodec/x86/fft.h index a604956..94405d0 100644 --- a/libavcodec/x86/fft.h +++ b/libavcodec/x86/fft.h @@ -27,12 +27,4 @@ void ff_fft_calc_sse(FFTContext *s, FFTComplex *z); void ff_fft_calc_3dnow(FFTContext *s, FFTComplex *z); void ff_fft_calc_3dnowext(FFTContext *s, FFTComplex *z); -void ff_imdct_calc_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_calc_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_calc_sse(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_sse(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_avx(FFTContext *s, FFTSample *output, const FFTSample *input); - #endif /* AVCODEC_X86_FFT_H */ diff --git a/libavcodec/x86/fft_init.c b/libavcodec/x86/fft_init.c index 7ca72c5..ed12909 100644 --- a/libavcodec/x86/fft_init.c +++ b/libavcodec/x86/fft_init.c @@ -17,9 +17,11 @@ */ #include "config.h" + #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/x86/cpu.h" + #include "fft.h" av_cold void ff_fft_init_x86(FFTContext *s) @@ -28,29 +30,21 @@ av_cold void ff_fft_init_x86(FFTContext *s) #if ARCH_X86_32 if (EXTERNAL_AMD3DNOW(cpu_flags)) { - /* 3DNow! for K6-2/3 */ - s->imdct_calc = ff_imdct_calc_3dnow; - s->imdct_half = ff_imdct_half_3dnow; s->fft_calc = ff_fft_calc_3dnow; } + if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { - /* 3DNowEx for K7 */ - s->imdct_calc = ff_imdct_calc_3dnowext; - s->imdct_half = ff_imdct_half_3dnowext; s->fft_calc = ff_fft_calc_3dnowext; } -#endif +#endif /* ARCH_X86_32 */ + if (EXTERNAL_SSE(cpu_flags)) { - /* SSE for P3/P4/K8 */ - s->imdct_calc = ff_imdct_calc_sse; - s->imdct_half = ff_imdct_half_sse; s->fft_permute = ff_fft_permute_sse; s->fft_calc = ff_fft_calc_sse; s->fft_permutation = FF_FFT_PERM_SWAP_LSBS; } - if (EXTERNAL_AVX(cpu_flags) && s->nbits >= 5) { - /* AVX for SB */ - s->imdct_half = ff_imdct_half_avx; + + if (EXTERNAL_AVX_FAST(cpu_flags) && s->nbits >= 5) { s->fft_calc = ff_fft_calc_avx; s->fft_permutation = FF_FFT_PERM_AVX; } diff --git a/libavcodec/x86/fmtconvert.asm b/libavcodec/x86/fmtconvert.asm index 8184376..2a3e4a5 100644 --- a/libavcodec/x86/fmtconvert.asm +++ b/libavcodec/x86/fmtconvert.asm @@ -21,15 +21,7 @@ %include "libavutil/x86/x86util.asm" -SECTION_TEXT - -%macro CVTPS2PI 2 -%if cpuflag(sse) - cvtps2pi %1, %2 -%elif cpuflag(3dnow) - pf2id %1, %2 -%endif -%endmacro +SECTION .text ;------------------------------------------------------------------------------ ; void ff_int32_to_float_fmul_scalar(float *dst, const int32_t *src, float mul, @@ -47,7 +39,7 @@ cglobal int32_to_float_fmul_scalar, 4, 4, %1, dst, src, mul, len movss m0, mulm %endif SPLATD m0 - shl lenq, 2 + shl lend, 2 add srcq, lenq add dstq, lenq neg lenq @@ -69,364 +61,17 @@ cglobal int32_to_float_fmul_scalar, 4, 4, %1, dst, src, mul, len mova [dstq+lenq+16], m2 add lenq, 32 jl .loop - REP_RET -%endmacro - -INIT_XMM sse -INT32_TO_FLOAT_FMUL_SCALAR 5 -INIT_XMM sse2 -INT32_TO_FLOAT_FMUL_SCALAR 3 - - -;------------------------------------------------------------------------------ -; void ff_float_to_int16(int16_t *dst, const float *src, long len); -;------------------------------------------------------------------------------ -%macro FLOAT_TO_INT16 1 -cglobal float_to_int16, 3, 3, %1, dst, src, len - add lenq, lenq - lea srcq, [srcq+2*lenq] - add dstq, lenq - neg lenq -.loop: -%if cpuflag(sse2) - cvtps2dq m0, [srcq+2*lenq ] - cvtps2dq m1, [srcq+2*lenq+16] - packssdw m0, m1 - mova [dstq+lenq], m0 -%else - CVTPS2PI m0, [srcq+2*lenq ] - CVTPS2PI m1, [srcq+2*lenq+ 8] - CVTPS2PI m2, [srcq+2*lenq+16] - CVTPS2PI m3, [srcq+2*lenq+24] - packssdw m0, m1 - packssdw m2, m3 - mova [dstq+lenq ], m0 - mova [dstq+lenq+8], m2 -%endif - add lenq, 16 - js .loop -%if mmsize == 8 - emms -%endif - REP_RET -%endmacro - -INIT_XMM sse2 -FLOAT_TO_INT16 2 -INIT_MMX sse -FLOAT_TO_INT16 0 -INIT_MMX 3dnow -FLOAT_TO_INT16 0 - -;------------------------------------------------------------------------------ -; void ff_float_to_int16_step(int16_t *dst, const float *src, long len, long step); -;------------------------------------------------------------------------------ -%macro FLOAT_TO_INT16_STEP 1 -cglobal float_to_int16_step, 4, 7, %1, dst, src, len, step, step3, v1, v2 - add lenq, lenq - lea srcq, [srcq+2*lenq] - lea step3q, [stepq*3] - neg lenq -.loop: -%if cpuflag(sse2) - cvtps2dq m0, [srcq+2*lenq ] - cvtps2dq m1, [srcq+2*lenq+16] - packssdw m0, m1 - movd v1d, m0 - psrldq m0, 4 - movd v2d, m0 - psrldq m0, 4 - mov [dstq], v1w - mov [dstq+stepq*4], v2w - shr v1d, 16 - shr v2d, 16 - mov [dstq+stepq*2], v1w - mov [dstq+step3q*2], v2w - lea dstq, [dstq+stepq*8] - movd v1d, m0 - psrldq m0, 4 - movd v2d, m0 - mov [dstq], v1w - mov [dstq+stepq*4], v2w - shr v1d, 16 - shr v2d, 16 - mov [dstq+stepq*2], v1w - mov [dstq+step3q*2], v2w - lea dstq, [dstq+stepq*8] -%else - CVTPS2PI m0, [srcq+2*lenq ] - CVTPS2PI m1, [srcq+2*lenq+ 8] - CVTPS2PI m2, [srcq+2*lenq+16] - CVTPS2PI m3, [srcq+2*lenq+24] - packssdw m0, m1 - packssdw m2, m3 - movd v1d, m0 - psrlq m0, 32 - movd v2d, m0 - mov [dstq], v1w - mov [dstq+stepq*4], v2w - shr v1d, 16 - shr v2d, 16 - mov [dstq+stepq*2], v1w - mov [dstq+step3q*2], v2w - lea dstq, [dstq+stepq*8] - movd v1d, m2 - psrlq m2, 32 - movd v2d, m2 - mov [dstq], v1w - mov [dstq+stepq*4], v2w - shr v1d, 16 - shr v2d, 16 - mov [dstq+stepq*2], v1w - mov [dstq+step3q*2], v2w - lea dstq, [dstq+stepq*8] -%endif - add lenq, 16 - js .loop -%if mmsize == 8 - emms -%endif - REP_RET -%endmacro - -INIT_XMM sse2 -FLOAT_TO_INT16_STEP 2 -INIT_MMX sse -FLOAT_TO_INT16_STEP 0 -INIT_MMX 3dnow -FLOAT_TO_INT16_STEP 0 - -;------------------------------------------------------------------------------- -; void ff_float_to_int16_interleave2(int16_t *dst, const float **src, long len); -;------------------------------------------------------------------------------- -%macro FLOAT_TO_INT16_INTERLEAVE2 0 -cglobal float_to_int16_interleave2, 3, 4, 2, dst, src0, src1, len - lea lenq, [4*r2q] - mov src1q, [src0q+gprsize] - mov src0q, [src0q] - add dstq, lenq - add src0q, lenq - add src1q, lenq - neg lenq -.loop: -%if cpuflag(sse2) - cvtps2dq m0, [src0q+lenq] - cvtps2dq m1, [src1q+lenq] - packssdw m0, m1 - movhlps m1, m0 - punpcklwd m0, m1 - mova [dstq+lenq], m0 -%else - CVTPS2PI m0, [src0q+lenq ] - CVTPS2PI m1, [src0q+lenq+8] - CVTPS2PI m2, [src1q+lenq ] - CVTPS2PI m3, [src1q+lenq+8] - packssdw m0, m1 - packssdw m2, m3 - mova m1, m0 - punpcklwd m0, m2 - punpckhwd m1, m2 - mova [dstq+lenq ], m0 - mova [dstq+lenq+8], m1 -%endif - add lenq, 16 - js .loop -%if mmsize == 8 +%if notcpuflag(sse2) + ;; cvtpi2ps switches to MMX even if the source is a memory location + ;; possible an error in documentation since every tested CPU disagrees with + ;; that. Use emms anyway since the vast majority of machines will use the + ;; SSE2 variant emms %endif - REP_RET -%endmacro - -INIT_MMX 3dnow -FLOAT_TO_INT16_INTERLEAVE2 -INIT_MMX sse -FLOAT_TO_INT16_INTERLEAVE2 -INIT_XMM sse2 -FLOAT_TO_INT16_INTERLEAVE2 - -;----------------------------------------------------------------------------- -; void ff_float_to_int16_interleave6(int16_t *dst, const float **src, int len) -;----------------------------------------------------------------------------- -%macro FLOAT_TO_INT16_INTERLEAVE6 0 -cglobal float_to_int16_interleave6, 2, 8, 0, dst, src, src1, src2, src3, src4, src5, len -%if ARCH_X86_64 - mov lend, r2d -%else - %define lend dword r2m -%endif - mov src1q, [srcq+1*gprsize] - mov src2q, [srcq+2*gprsize] - mov src3q, [srcq+3*gprsize] - mov src4q, [srcq+4*gprsize] - mov src5q, [srcq+5*gprsize] - mov srcq, [srcq] - sub src1q, srcq - sub src2q, srcq - sub src3q, srcq - sub src4q, srcq - sub src5q, srcq -.loop: - CVTPS2PI mm0, [srcq] - CVTPS2PI mm1, [srcq+src1q] - CVTPS2PI mm2, [srcq+src2q] - CVTPS2PI mm3, [srcq+src3q] - CVTPS2PI mm4, [srcq+src4q] - CVTPS2PI mm5, [srcq+src5q] - packssdw mm0, mm3 - packssdw mm1, mm4 - packssdw mm2, mm5 - PSWAPD mm3, mm0 - punpcklwd mm0, mm1 - punpckhwd mm1, mm2 - punpcklwd mm2, mm3 - PSWAPD mm3, mm0 - punpckldq mm0, mm2 - punpckhdq mm2, mm1 - punpckldq mm1, mm3 - movq [dstq ], mm0 - movq [dstq+16], mm2 - movq [dstq+ 8], mm1 - add srcq, 8 - add dstq, 24 - sub lend, 2 - jg .loop - emms RET -%endmacro ; FLOAT_TO_INT16_INTERLEAVE6 - -INIT_MMX sse -FLOAT_TO_INT16_INTERLEAVE6 -INIT_MMX 3dnow -FLOAT_TO_INT16_INTERLEAVE6 -INIT_MMX 3dnowext -FLOAT_TO_INT16_INTERLEAVE6 - -;----------------------------------------------------------------------------- -; void ff_float_interleave6(float *dst, const float **src, unsigned int len); -;----------------------------------------------------------------------------- - -%macro FLOAT_INTERLEAVE6 1 -cglobal float_interleave6, 2, 8, %1, dst, src, src1, src2, src3, src4, src5, len -%if ARCH_X86_64 - mov lend, r2d -%else - %define lend dword r2m -%endif - mov src1q, [srcq+1*gprsize] - mov src2q, [srcq+2*gprsize] - mov src3q, [srcq+3*gprsize] - mov src4q, [srcq+4*gprsize] - mov src5q, [srcq+5*gprsize] - mov srcq, [srcq] - sub src1q, srcq - sub src2q, srcq - sub src3q, srcq - sub src4q, srcq - sub src5q, srcq -.loop: -%if cpuflag(sse) - movaps m0, [srcq] - movaps m1, [srcq+src1q] - movaps m2, [srcq+src2q] - movaps m3, [srcq+src3q] - movaps m4, [srcq+src4q] - movaps m5, [srcq+src5q] - - SBUTTERFLYPS 0, 1, 6 - SBUTTERFLYPS 2, 3, 6 - SBUTTERFLYPS 4, 5, 6 - - movaps m6, m4 - shufps m4, m0, 0xe4 - movlhps m0, m2 - movhlps m6, m2 - movaps [dstq ], m0 - movaps [dstq+16], m4 - movaps [dstq+32], m6 - - movaps m6, m5 - shufps m5, m1, 0xe4 - movlhps m1, m3 - movhlps m6, m3 - movaps [dstq+48], m1 - movaps [dstq+64], m5 - movaps [dstq+80], m6 -%else ; mmx - movq m0, [srcq] - movq m1, [srcq+src1q] - movq m2, [srcq+src2q] - movq m3, [srcq+src3q] - movq m4, [srcq+src4q] - movq m5, [srcq+src5q] - - SBUTTERFLY dq, 0, 1, 6 - SBUTTERFLY dq, 2, 3, 6 - SBUTTERFLY dq, 4, 5, 6 - movq [dstq ], m0 - movq [dstq+ 8], m2 - movq [dstq+16], m4 - movq [dstq+24], m1 - movq [dstq+32], m3 - movq [dstq+40], m5 -%endif - add srcq, mmsize - add dstq, mmsize*6 - sub lend, mmsize/4 - jg .loop -%if mmsize == 8 - emms -%endif - REP_RET %endmacro -INIT_MMX mmx -FLOAT_INTERLEAVE6 0 INIT_XMM sse -FLOAT_INTERLEAVE6 7 - -;----------------------------------------------------------------------------- -; void ff_float_interleave2(float *dst, const float **src, unsigned int len); -;----------------------------------------------------------------------------- - -%macro FLOAT_INTERLEAVE2 1 -cglobal float_interleave2, 3, 4, %1, dst, src, len, src1 - mov src1q, [srcq+gprsize] - mov srcq, [srcq ] - sub src1q, srcq -.loop: - mova m0, [srcq ] - mova m1, [srcq+src1q ] - mova m3, [srcq +mmsize] - mova m4, [srcq+src1q+mmsize] - - mova m2, m0 - PUNPCKLDQ m0, m1 - PUNPCKHDQ m2, m1 - - mova m1, m3 - PUNPCKLDQ m3, m4 - PUNPCKHDQ m1, m4 - - mova [dstq ], m0 - mova [dstq+1*mmsize], m2 - mova [dstq+2*mmsize], m3 - mova [dstq+3*mmsize], m1 - - add srcq, mmsize*2 - add dstq, mmsize*4 - sub lend, mmsize/2 - jg .loop -%if mmsize == 8 - emms -%endif - REP_RET -%endmacro - -INIT_MMX mmx -%define PUNPCKLDQ punpckldq -%define PUNPCKHDQ punpckhdq -FLOAT_INTERLEAVE2 0 -INIT_XMM sse -%define PUNPCKLDQ unpcklps -%define PUNPCKHDQ unpckhps -FLOAT_INTERLEAVE2 5 +INT32_TO_FLOAT_FMUL_SCALAR 5 +INIT_XMM sse2 +INT32_TO_FLOAT_FMUL_SCALAR 3 diff --git a/libavcodec/x86/fmtconvert_init.c b/libavcodec/x86/fmtconvert_init.c index 3d75df9..2f10db4 100644 --- a/libavcodec/x86/fmtconvert_init.c +++ b/libavcodec/x86/fmtconvert_init.c @@ -24,7 +24,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/fmtconvert.h" @@ -33,84 +32,6 @@ void ff_int32_to_float_fmul_scalar_sse (float *dst, const int32_t *src, float mul, int len); void ff_int32_to_float_fmul_scalar_sse2(float *dst, const int32_t *src, float mul, int len); -void ff_float_to_int16_3dnow(int16_t *dst, const float *src, long len); -void ff_float_to_int16_sse (int16_t *dst, const float *src, long len); -void ff_float_to_int16_sse2 (int16_t *dst, const float *src, long len); - -void ff_float_to_int16_step_3dnow(int16_t *dst, const float *src, long len, long step); -void ff_float_to_int16_step_sse (int16_t *dst, const float *src, long len, long step); -void ff_float_to_int16_step_sse2 (int16_t *dst, const float *src, long len, long step); - -void ff_float_to_int16_interleave2_3dnow(int16_t *dst, const float **src, long len); -void ff_float_to_int16_interleave2_sse (int16_t *dst, const float **src, long len); -void ff_float_to_int16_interleave2_sse2 (int16_t *dst, const float **src, long len); - -void ff_float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len); -void ff_float_to_int16_interleave6_3dnow(int16_t *dst, const float **src, int len); -void ff_float_to_int16_interleave6_3dnowext(int16_t *dst, const float **src, int len); - -#define ff_float_to_int16_interleave6_sse2 ff_float_to_int16_interleave6_sse - -#define FLOAT_TO_INT16_INTERLEAVE(cpu) \ -/* gcc pessimizes register allocation if this is in the same function as float_to_int16_interleave_sse2*/\ -static av_noinline void float_to_int16_interleave_misc_##cpu(int16_t *dst, const float **src, long len, int channels){\ - int c;\ - for(c=0; cfloat_interleave = float_interleave_mmx; - } - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->float_to_int16 = ff_float_to_int16_3dnow; - c->float_to_int16_interleave = float_to_int16_interleave_3dnow; - } - } - if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { - c->float_to_int16_interleave = float_to_int16_interleave_3dnowext; - } - } if (EXTERNAL_SSE(cpu_flags)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse; - c->float_to_int16 = ff_float_to_int16_sse; - c->float_to_int16_interleave = float_to_int16_interleave_sse; - c->float_interleave = float_interleave_sse; } if (EXTERNAL_SSE2(cpu_flags)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse2; - c->float_to_int16 = ff_float_to_int16_sse2; - c->float_to_int16_interleave = float_to_int16_interleave_sse2; } #endif /* HAVE_YASM */ } diff --git a/libavcodec/x86/fpel_mmx.c b/libavcodec/x86/fpel_mmx.c index eef05ec..813bcc2 100644 --- a/libavcodec/x86/fpel_mmx.c +++ b/libavcodec/x86/fpel_mmx.c @@ -79,26 +79,26 @@ void ff_put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { __asm__ volatile ( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1 ), %%mm0 \n\t" "movq (%1, %3), %%mm1 \n\t" "movq %%mm0, (%2) \n\t" "movq %%mm1, (%2, %3) \n\t" - "add %%"REG_a", %1 \n\t" - "add %%"REG_a", %2 \n\t" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" : "+g"(h), "+r"(pixels), "+r"(block) : "r"((x86_reg)line_size) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); } @@ -106,7 +106,7 @@ void ff_put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { __asm__ volatile ( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1 ), %%mm0 \n\t" @@ -117,8 +117,8 @@ void ff_put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, "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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "movq (%1 ), %%mm0 \n\t" "movq 8(%1 ), %%mm4 \n\t" "movq (%1, %3), %%mm1 \n\t" @@ -127,13 +127,13 @@ void ff_put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, "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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" : "+g"(h), "+r"(pixels), "+r"(block) : "r"((x86_reg)line_size) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); } diff --git a/libavcodec/x86/h263_loopfilter.asm b/libavcodec/x86/h263_loopfilter.asm index 673f795..cd726ba 100644 --- a/libavcodec/x86/h263_loopfilter.asm +++ b/libavcodec/x86/h263_loopfilter.asm @@ -24,7 +24,7 @@ SECTION_RODATA cextern pb_FC cextern h263_loop_filter_strength -SECTION_TEXT +SECTION .text %macro H263_LOOP_FILTER 5 pxor m7, m7 diff --git a/libavcodec/x86/h264_chromamc.asm b/libavcodec/x86/h264_chromamc.asm index cc41f00..1447940 100644 --- a/libavcodec/x86/h264_chromamc.asm +++ b/libavcodec/x86/h264_chromamc.asm @@ -1,5 +1,5 @@ ;****************************************************************************** -;* MMX/SSSE3-optimized functions for H264 chroma MC +;* MMX/SSSE3-optimized functions for H.264 chroma MC ;* Copyright (c) 2005 Zoltan Hidvegi , ;* 2005-2008 Loren Merritt ;* diff --git a/libavcodec/x86/h264_deblock.asm b/libavcodec/x86/h264_deblock.asm index d2067c8..33fd5a9 100644 --- a/libavcodec/x86/h264_deblock.asm +++ b/libavcodec/x86/h264_deblock.asm @@ -444,13 +444,13 @@ cglobal deblock_%1_luma_8, 5,5,8,2*%2 ; int8_t *tc0) ;----------------------------------------------------------------------------- INIT_MMX cpuname -cglobal deblock_h_luma_8, 0,5,8,0x60+HAVE_ALIGNED_STACK*12 +cglobal deblock_h_luma_8, 0,5,8,0x60+12 mov r0, r0mp mov r3, r1m lea r4, [r3*3] sub r0, 4 lea r1, [r0+r4] -%define pix_tmp esp+12*HAVE_ALIGNED_STACK +%define pix_tmp esp+12 ; transpose 6x16 -> tmp space TRANSPOSE6x8_MEM PASS8ROWS(r0, r1, r3, r4), pix_tmp diff --git a/libavcodec/x86/h264_i386.h b/libavcodec/x86/h264_i386.h index bb881c3..ad57aa9 100644 --- a/libavcodec/x86/h264_i386.h +++ b/libavcodec/x86/h264_i386.h @@ -21,7 +21,7 @@ /** * @file - * H.264 / AVC / MPEG4 part10 codec. + * H.264 / AVC / MPEG-4 part10 codec. * non-MMX i386-specific optimizations for H.264 * @author Michael Niedermayer */ @@ -84,13 +84,13 @@ static int decode_significance_x86(CABACContext *c, int max_coeff, "sub %10, %1 \n\t" "mov %2, %0 \n\t" "movl %7, %%ecx \n\t" - "add %1, %%"REG_c" \n\t" + "add %1, %%"FF_REG_c" \n\t" "movl %%ecx, (%0) \n\t" "test $1, %4 \n\t" " jnz 5f \n\t" - "add"OPSIZE" $4, %2 \n\t" + "add"FF_OPSIZE" $4, %2 \n\t" "4: \n\t" "add $1, %1 \n\t" @@ -98,7 +98,7 @@ static int decode_significance_x86(CABACContext *c, int max_coeff, " jb 3b \n\t" "mov %2, %0 \n\t" "movl %7, %%ecx \n\t" - "add %1, %%"REG_c" \n\t" + "add %1, %%"FF_REG_c" \n\t" "movl %%ecx, (%0) \n\t" "5: \n\t" "add %9, %k0 \n\t" @@ -109,7 +109,7 @@ static int decode_significance_x86(CABACContext *c, int max_coeff, "i"(offsetof(CABACContext, bytestream)), "i"(offsetof(CABACContext, bytestream_end)) TABLES_ARG - : "%"REG_c, "memory" + : "%"FF_REG_c, "memory" ); return coeff_count; } @@ -175,7 +175,7 @@ static int decode_significance_8x8_x86(CABACContext *c, "test $1, %4 \n\t" " jnz 5f \n\t" - "add"OPSIZE" $4, %2 \n\t" + "add"FF_OPSIZE" $4, %2 \n\t" "4: \n\t" "addl $1, %k6 \n\t" @@ -194,7 +194,7 @@ static int decode_significance_8x8_x86(CABACContext *c, "i"(offsetof(CABACContext, bytestream)), "i"(offsetof(CABACContext, bytestream_end)), "i"(H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET) TABLES_ARG - : "%"REG_c, "memory" + : "%"FF_REG_c, "memory" ); return coeff_count; } diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index 313791a..eb99476 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -82,6 +82,7 @@ SECTION .text INIT_MMX mmx ; void ff_h264_idct_add_8_mmx(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct_add_8, 3, 3, 0 + movsxdifnidn r2, r2d IDCT4_ADD r0, r1, r2 RET @@ -204,6 +205,7 @@ cglobal h264_idct_add_8, 3, 3, 0 INIT_MMX mmx ; void ff_h264_idct8_add_8_mmx(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_add_8, 3, 4, 0 + movsxdifnidn r2, r2d %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -272,6 +274,7 @@ cglobal h264_idct8_add_8, 3, 4, 0 INIT_XMM sse2 ; void ff_h264_idct8_add_8_sse2(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_add_8, 3, 4, 10 + movsxdifnidn r2, r2d IDCT8_ADD_SSE r0, r1, r2, r3 RET @@ -310,6 +313,7 @@ INIT_MMX mmxext ; void ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) %if ARCH_X86_64 cglobal h264_idct_dc_add_8, 3, 4, 0 + movsxd r2, r2d movsx r3, word [r1] mov dword [r1], 0 DC_ADD_MMXEXT_INIT r3, r2 @@ -318,6 +322,7 @@ cglobal h264_idct_dc_add_8, 3, 4, 0 ; void ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_dc_add_8, 3, 4, 0 + movsxd r2, r2d movsx r3, word [r1] mov dword [r1], 0 DC_ADD_MMXEXT_INIT r3, r2 @@ -352,6 +357,7 @@ INIT_MMX mmx ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + movsxdifnidn r3, r3d xor r5, r5 %ifdef PIC lea picregq, [scan8_mem] @@ -375,6 +381,7 @@ cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + movsxdifnidn r3, r3d %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -409,6 +416,7 @@ INIT_MMX mmxext ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d xor r5, r5 %ifdef PIC lea picregq, [scan8_mem] @@ -456,6 +464,7 @@ INIT_MMX mmx ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + movsxdifnidn r3, r3d xor r5, r5 %ifdef PIC lea picregq, [scan8_mem] @@ -481,6 +490,7 @@ INIT_MMX mmxext ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d xor r5, r5 %ifdef PIC lea picregq, [scan8_mem] @@ -525,6 +535,7 @@ cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, s ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d %assign pad 128+4-(stack_offset&7) SUB rsp, pad @@ -587,6 +598,7 @@ INIT_XMM sse2 ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct8_add4_8, 5, 8 + npicregs, 10, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d xor r5, r5 %ifdef PIC lea picregq, [scan8_mem] @@ -638,6 +650,7 @@ INIT_XMM cpuname INIT_MMX mmx h264_idct_add8_mmx_plane: + movsxdifnidn r3, r3d .nextblock: movzx r6, byte [scan8+r5] movzx r6, byte [r4+r6] @@ -664,6 +677,7 @@ h264_idct_add8_mmx_plane: ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d mov r5, 16 add r2, 512 %ifdef PIC @@ -684,6 +698,7 @@ cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, RET h264_idct_add8_mmxext_plane: + movsxdifnidn r3, r3d .nextblock: movzx r6, byte [scan8+r5] movzx r6, byte [r4+r6] @@ -730,6 +745,7 @@ INIT_MMX mmxext ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + movsxdifnidn r3, r3d mov r5, 16 add r2, 512 %if ARCH_X86_64 @@ -751,6 +767,7 @@ cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, ; r0 = uint8_t *dst, r2 = int16_t *block, r3 = int stride, r6=clobbered h264_idct_dc_add8_mmxext: + movsxdifnidn r3, r3d movd m0, [r2 ] ; 0 0 X D mov word [r2+ 0], 0 punpcklwd m0, [r2+32] ; x X d D @@ -771,6 +788,7 @@ ALIGN 16 INIT_XMM sse2 ; r0 = uint8_t *dst (clobbered), r2 = int16_t *block, r3 = int stride h264_add8x4_idct_sse2: + movsxdifnidn r3, r3d movq m0, [r2+ 0] movq m1, [r2+ 8] movq m2, [r2+16] @@ -814,6 +832,7 @@ h264_add8x4_idct_sse2: ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 + movsxdifnidn r3, r3d %if ARCH_X86_64 mov r5, r0 %endif @@ -862,6 +881,7 @@ cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 + movsxdifnidn r3, r3d %if ARCH_X86_64 mov r7, r0 %endif @@ -914,6 +934,7 @@ cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 ; int16_t *block, int stride, ; const uint8_t nnzc[6 * 8]) cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 + movsxdifnidn r3, r3d add r2, 512 %if ARCH_X86_64 mov r7, r0 diff --git a/libavcodec/x86/h264_idct_10bit.asm b/libavcodec/x86/h264_idct_10bit.asm index b7d5105..432d74b 100644 --- a/libavcodec/x86/h264_idct_10bit.asm +++ b/libavcodec/x86/h264_idct_10bit.asm @@ -77,6 +77,7 @@ SECTION .text %macro IDCT_ADD_10 0 cglobal h264_idct_add_10, 3,3 + movsxdifnidn r2, r2d IDCT4_ADD_10 r0, r1, r2 RET %endmacro @@ -134,6 +135,7 @@ ADD4x4IDCT %macro IDCT_ADD16_10 0 cglobal h264_idct_add16_10, 5,6 + movsxdifnidn r3, r3d ADD16_OP 0, 4+1*8 ADD16_OP 1, 5+1*8 ADD16_OP 2, 4+2*8 @@ -190,6 +192,7 @@ IDCT_ADD16_10 INIT_MMX mmxext cglobal h264_idct_dc_add_10,3,3 + movsxdifnidn r2, r2d movd m0, [r1] mov dword [r1], 0 paddd m0, [pd_32] @@ -205,6 +208,7 @@ cglobal h264_idct_dc_add_10,3,3 ;----------------------------------------------------------------------------- %macro IDCT8_DC_ADD 0 cglobal h264_idct8_dc_add_10,3,4,7 + movsxdifnidn r2, r2d movd m0, [r1] mov dword[r1], 0 paddd m0, [pd_32] @@ -272,6 +276,7 @@ idct_dc_add %+ SUFFIX: ret cglobal h264_idct_add16intra_10,5,7,8 + movsxdifnidn r3, r3d ADD16_OP_INTRA 0, 4+1*8 ADD16_OP_INTRA 2, 4+2*8 ADD16_OP_INTRA 4, 6+1*8 @@ -304,6 +309,7 @@ IDCT_ADD16INTRA_10 ;----------------------------------------------------------------------------- %macro IDCT_ADD8 0 cglobal h264_idct_add8_10,5,8,7 + movsxdifnidn r3, r3d %if ARCH_X86_64 mov r7, r0 %endif @@ -438,6 +444,7 @@ IDCT_ADD8 %macro IDCT8_ADD 0 cglobal h264_idct8_add_10, 3,4,16 + movsxdifnidn r2, r2d %if UNIX64 == 0 %assign pad 16-gprsize-(stack_offset&15) sub rsp, pad @@ -560,6 +567,7 @@ IDCT8_ADD %macro IDCT8_ADD4 0 cglobal h264_idct8_add4_10, 0,7,16 + movsxdifnidn r3, r3d %assign pad 16-gprsize-(stack_offset&15) SUB rsp, pad mov r5, r0mp diff --git a/libavcodec/x86/h264_intrapred.asm b/libavcodec/x86/h264_intrapred.asm index 4a4fa10..df657a4 100644 --- a/libavcodec/x86/h264_intrapred.asm +++ b/libavcodec/x86/h264_intrapred.asm @@ -1027,9 +1027,9 @@ cglobal pred8x8l_top_dc_8, 4,4 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 ; top_left + test r1d, r1d ; top_left jz .fix_lt_2 - test r2, r2 ; top_right + test r2d, r2d ; top_right jz .fix_tr_1 jmp .body .fix_lt_2: @@ -1038,7 +1038,7 @@ cglobal pred8x8l_top_dc_8, 4,4 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 ; top_right + test r2d, r2d ; top_right jnz .body .fix_tr_1: movq mm5, mm3 @@ -1099,7 +1099,7 @@ cglobal pred8x8l_dc_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jnz .do_left .fix_lt_1: movq mm5, mm3 @@ -1114,7 +1114,7 @@ cglobal pred8x8l_dc_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .body .fix_tr_1: movq mm5, mm3 @@ -1138,9 +1138,9 @@ cglobal pred8x8l_dc_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .body: lea r1, [r0+r3*2] @@ -1182,7 +1182,7 @@ cglobal pred8x8l_horizontal_8, 4,4 sub r0, r3 lea r2, [r0+r3*2] movq mm0, [r0+r3*1-8] - test r1, r1 + test r1d, r1d lea r1, [r0+r3] cmovnz r1, r0 punpckhbw mm0, [r1+r3*0-8] @@ -1259,9 +1259,9 @@ cglobal pred8x8l_vertical_8, 4,4 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 ; top_left + test r1d, r1d ; top_left jz .fix_lt_2 - test r2, r2 ; top_right + test r2d, r2d ; top_right jz .fix_tr_1 jmp .body .fix_lt_2: @@ -1270,7 +1270,7 @@ cglobal pred8x8l_vertical_8, 4,4 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 ; top_right + test r2d, r2d ; top_right jnz .body .fix_tr_1: movq mm5, mm3 @@ -1310,9 +1310,9 @@ cglobal pred8x8l_down_left_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 jmp .do_top .fix_lt_2: @@ -1321,7 +1321,7 @@ cglobal pred8x8l_down_left_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1337,7 +1337,7 @@ cglobal pred8x8l_down_left_8, 4,5 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 movq mm7, mm4 - test r2, r2 + test r2d, r2d jz .fix_tr_2 movq mm0, [r0+8] movq mm5, mm0 @@ -1418,9 +1418,9 @@ cglobal pred8x8l_down_left_8, 4,4 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 ; top_left + test r1d, r1d ; top_left jz .fix_lt_2 - test r2, r2 ; top_right + test r2d, r2d ; top_right jz .fix_tr_1 jmp .do_top .fix_lt_2: @@ -1429,7 +1429,7 @@ cglobal pred8x8l_down_left_8, 4,4 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 ; top_right + test r2d, r2d ; top_right jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1445,7 +1445,7 @@ cglobal pred8x8l_down_left_8, 4,4 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 movq2dq xmm3, mm4 - test r2, r2 ; top_right + test r2d, r2d ; top_right jz .fix_tr_2 movq mm0, [r0+8] movq mm5, mm0 @@ -1527,7 +1527,7 @@ cglobal pred8x8l_down_right_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 ; top_left + test r1d, r1d ; top_left jz .fix_lt_1 .do_left: movq mm0, mm4 @@ -1545,9 +1545,9 @@ cglobal pred8x8l_down_right_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 ; top_left + test r1d, r1d ; top_left jz .fix_lt_2 - test r2, r2 ; top_right + test r2d, r2d ; top_right jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 @@ -1566,7 +1566,7 @@ cglobal pred8x8l_down_right_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 ; top_right + test r2d, r2d ; top_right jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1659,7 +1659,7 @@ cglobal pred8x8l_down_right_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jz .fix_lt_1 jmp .do_left .fix_lt_1: @@ -1675,7 +1675,7 @@ cglobal pred8x8l_down_right_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1701,9 +1701,9 @@ cglobal pred8x8l_down_right_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 @@ -1779,7 +1779,7 @@ cglobal pred8x8l_vertical_right_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jz .fix_lt_1 jmp .do_left .fix_lt_1: @@ -1795,7 +1795,7 @@ cglobal pred8x8l_vertical_right_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1815,9 +1815,9 @@ cglobal pred8x8l_vertical_right_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 @@ -1889,7 +1889,7 @@ cglobal pred8x8l_vertical_right_8, 4,5,7 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jnz .do_left .fix_lt_1: movq mm5, mm3 @@ -1904,7 +1904,7 @@ cglobal pred8x8l_vertical_right_8, 4,5,7 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -1924,9 +1924,9 @@ cglobal pred8x8l_vertical_right_8, 4,5,7 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 @@ -1991,9 +1991,9 @@ cglobal pred8x8l_vertical_left_8, 4,4 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 jmp .do_top .fix_lt_2: @@ -2002,7 +2002,7 @@ cglobal pred8x8l_vertical_left_8, 4,4 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -2018,7 +2018,7 @@ cglobal pred8x8l_vertical_left_8, 4,4 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 movq2dq xmm4, mm4 - test r2, r2 + test r2d, r2d jz .fix_tr_2 movq mm0, [r0+8] movq mm5, mm0 @@ -2076,7 +2076,7 @@ cglobal pred8x8l_horizontal_up_8, 4,4 sub r0, r3 lea r2, [r0+r3*2] movq mm0, [r0+r3*1-8] - test r1, r1 + test r1d, r1d lea r1, [r0+r3] cmovnz r1, r0 punpckhbw mm0, [r1+r3*0-8] @@ -2185,7 +2185,7 @@ cglobal pred8x8l_horizontal_down_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jnz .do_left .fix_lt_1: movq mm5, mm3 @@ -2200,7 +2200,7 @@ cglobal pred8x8l_horizontal_down_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -2225,9 +2225,9 @@ cglobal pred8x8l_horizontal_down_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 @@ -2300,7 +2300,7 @@ cglobal pred8x8l_horizontal_down_8, 4,5 movq mm2, mm3 PALIGNR mm4, mm0, 7, mm0 PALIGNR mm1, mm2, 1, mm2 - test r1, r1 + test r1d, r1d jnz .do_left .fix_lt_1: movq mm5, mm3 @@ -2315,7 +2315,7 @@ cglobal pred8x8l_horizontal_down_8, 4,5 psllq mm5, 56 psrlq mm5, 56 pxor mm2, mm5 - test r2, r2 + test r2d, r2d jnz .do_top .fix_tr_1: movq mm5, mm3 @@ -2346,14 +2346,14 @@ cglobal pred8x8l_horizontal_down_8, 4,5 movq mm4, mm3 PALIGNR mm2, mm0, 7, mm0 PALIGNR mm1, mm4, 1, mm4 - test r1, r1 + test r1d, r1d jz .fix_lt_2 - test r2, r2 + test r2d, r2d jz .fix_tr_1 .do_top: PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 movq2dq xmm1, mm4 - test r2, r2 + test r2d, r2d jz .fix_tr_2 movq mm0, [r0+8] movq mm5, mm0 diff --git a/libavcodec/x86/h264_intrapred_10bit.asm b/libavcodec/x86/h264_intrapred_10bit.asm index 55790a9..ecbe57b 100644 --- a/libavcodec/x86/h264_intrapred_10bit.asm +++ b/libavcodec/x86/h264_intrapred_10bit.asm @@ -26,6 +26,7 @@ SECTION_RODATA +cextern pw_512 cextern pw_16 cextern pw_8 cextern pw_4 @@ -35,7 +36,6 @@ cextern pw_1 pw_m32101234: dw -3, -2, -1, 0, 1, 2, 3, 4 pw_m3: times 8 dw -3 pw_pixel_max: times 8 dw ((1 << 10)-1) -pw_512: times 8 dw 512 pd_17: times 4 dd 17 pd_16: times 4 dd 16 diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index 9ca6d7e..43e150c 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -23,8 +23,8 @@ #include "libavutil/cpu.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" +#include "libavcodec/h264dec.h" #include "libavcodec/h264qpel.h" -#include "libavcodec/mpegvideo.h" #include "libavcodec/pixels.h" #include "fpel.h" @@ -566,11 +566,6 @@ av_cold void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) } if (EXTERNAL_SSE2(cpu_flags)) { - if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW) && !high_bit_depth) { - // these functions are slower than mmx on AMD, but faster on Intel - H264_QPEL_FUNCS(0, 0, sse2); - } - if (!high_bit_depth) { H264_QPEL_FUNCS(0, 1, sse2); H264_QPEL_FUNCS(0, 2, sse2); @@ -597,6 +592,12 @@ av_cold void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) } } + if (EXTERNAL_SSE2_FAST(cpu_flags)) { + if (!high_bit_depth) { + H264_QPEL_FUNCS(0, 0, sse2); + } + } + if (EXTERNAL_SSSE3(cpu_flags)) { if (!high_bit_depth) { H264_QPEL_FUNCS(1, 0, ssse3); diff --git a/libavcodec/x86/h264_weight.asm b/libavcodec/x86/h264_weight.asm index d1873af..9ad26de 100644 --- a/libavcodec/x86/h264_weight.asm +++ b/libavcodec/x86/h264_weight.asm @@ -135,6 +135,16 @@ WEIGHT_FUNC_HALF_MM 8, 8 add off_regd, 1 or off_regd, 1 add r4, 1 + cmp r6d, 128 + je .nonnormal + cmp r5, 128 + jne .normal +.nonnormal + sar r5, 1 + sar r6, 1 + sar off_regd, 1 + sub r4, 1 +.normal %if cpuflag(ssse3) movd m4, r5d movd m0, r6d diff --git a/libavcodec/x86/hevc_deblock.asm b/libavcodec/x86/hevc_deblock.asm index 1e895f0..153eaf7 100644 --- a/libavcodec/x86/hevc_deblock.asm +++ b/libavcodec/x86/hevc_deblock.asm @@ -27,12 +27,12 @@ SECTION_RODATA pw_pixel_max: times 8 dw ((1 << 10)-1) -pw_m1: times 8 dw -1 pw_m2: times 8 dw -2 pd_1 : times 4 dd 1 cextern pw_4 cextern pw_8 +cextern pw_m1 SECTION .text INIT_XMM sse2 diff --git a/libavcodec/x86/hevc_idct.asm b/libavcodec/x86/hevc_idct.asm new file mode 100644 index 0000000..d662aa9 --- /dev/null +++ b/libavcodec/x86/hevc_idct.asm @@ -0,0 +1,107 @@ +;******************************************************************************* +;* SIMD-optimized IDCT functions for HEVC decoding +;* Copyright (c) 2014 Pierre-Edouard LEPERE +;* Copyright (c) 2014 James Almer +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +section .text + +; void ff_hevc_idctHxW_dc_{8,10}_(int16_t *coeffs) +; %1 = HxW +; %2 = number of loops +; %3 = bitdepth +%macro IDCT_DC 3 +cglobal hevc_idct_%1x%1_dc_%3, 1, 2, 1, coeff, tmp + movsx tmpd, word [coeffq] + add tmpd, (1 << (14 - %3)) + 1 + sar tmpd, (15 - %3) + movd xm0, tmpd + SPLATW m0, xm0 + DEFINE_ARGS coeff, cnt + mov cntd, %2 +.loop: + mova [coeffq+mmsize*0], m0 + mova [coeffq+mmsize*1], m0 + mova [coeffq+mmsize*2], m0 + mova [coeffq+mmsize*3], m0 + add coeffq, mmsize*8 + mova [coeffq+mmsize*-4], m0 + mova [coeffq+mmsize*-3], m0 + mova [coeffq+mmsize*-2], m0 + mova [coeffq+mmsize*-1], m0 + dec cntd + jg .loop + RET +%endmacro + +; %1 = HxW +; %2 = bitdepth +%macro IDCT_DC_NL 2 ; No loop +cglobal hevc_idct_%1x%1_dc_%2, 1, 2, 1, coeff, tmp + movsx tmpd, word [coeffq] + add tmpd, (1 << (14 - %2)) + 1 + sar tmpd, (15 - %2) + movd m0, tmpd + SPLATW m0, xm0 + mova [coeffq+mmsize*0], m0 + mova [coeffq+mmsize*1], m0 + mova [coeffq+mmsize*2], m0 + mova [coeffq+mmsize*3], m0 +%if mmsize == 16 + mova [coeffq+mmsize*4], m0 + mova [coeffq+mmsize*5], m0 + mova [coeffq+mmsize*6], m0 + mova [coeffq+mmsize*7], m0 +%endif + RET +%endmacro + +; 8-bit +INIT_MMX mmxext +IDCT_DC_NL 4, 8 +IDCT_DC 8, 2, 8 + +INIT_XMM sse2 +IDCT_DC_NL 8, 8 +IDCT_DC 16, 4, 8 +IDCT_DC 32, 16, 8 + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +IDCT_DC 16, 2, 8 +IDCT_DC 32, 8, 8 +%endif ;HAVE_AVX2_EXTERNAL + +; 10-bit +INIT_MMX mmxext +IDCT_DC_NL 4, 10 +IDCT_DC 8, 2, 10 + +INIT_XMM sse2 +IDCT_DC_NL 8, 10 +IDCT_DC 16, 4, 10 +IDCT_DC 32, 16, 10 + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +IDCT_DC 16, 2, 10 +IDCT_DC 32, 8, 10 +%endif ;HAVE_AVX2_EXTERNAL diff --git a/libavcodec/x86/hevc_mc.asm b/libavcodec/x86/hevc_mc.asm new file mode 100644 index 0000000..8444c41 --- /dev/null +++ b/libavcodec/x86/hevc_mc.asm @@ -0,0 +1,851 @@ +;***************************************************************************** +;* x86-optimized HEVC MC +;* Copyright 2015 Anton Khirnov +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pw_1023: times 8 dw 1023 + +cextern hevc_qpel_coeffs +cextern hevc_qpel_coeffs8 + +cextern hevc_epel_coeffs +cextern hevc_epel_coeffs8 + +cextern pw_8 +cextern pw_16 +cextern pw_32 +cextern pw_64 + +SECTION .text + +; %1: width +; %2: bit depth +%macro COMMON_DEFS 2 + %assign blocksize 8 + %assign nb_blocks ((%1 + blocksize - 1) / blocksize) + %define last_block_truncated (blocksize * nb_blocks > %1) + %if %2 > 8 + %define LOAD_BLOCK movu + %define LOAD_HALFBLOCK movq + %assign pixelsize 2 + %else + %define LOAD_BLOCK movq + %define LOAD_HALFBLOCK movd + %assign pixelsize 1 + %endif + %define STORE_BLOCK mova + %define STORE_HALFBLOCK movq +%endmacro + +; %1: block index +%macro BLOCK_DEFS 1 + %if last_block_truncated && %1 == nb_blocks - 1 + %define block_truncated 1 + %define LOAD LOAD_HALFBLOCK + %define STORE STORE_HALFBLOCK + %else + %define block_truncated 0 + %define LOAD LOAD_BLOCK + %define STORE STORE_BLOCK + %endif +%endmacro + + +; hevc_get_pixels__(int16_t *dst, ptrdiff_t dststride, +; pixel *src, ptrdiff_t srcstride, +; int height, int mx, int my, int *mcbuffer) + +; %1: block width +; %2: bit depth +; %3: log2 of height unroll +%macro GET_PIXELS 3 +cglobal hevc_get_pixels_ %+ %1 %+ _ %+ %2, 5, 5, 2, dst, dststride, src, srcstride, height ; rest of the args unused + + %assign shift 14 - %2 + COMMON_DEFS %1, %2 + +%if pixelsize == 1 + pxor m0, m0 +%endif + + shr heightd, %3 + +.loop: + +%assign i 0 +%rep (1 << %3) + +%assign j 0 +%rep nb_blocks + + BLOCK_DEFS j + + LOAD m1, [srcq + j * pixelsize * blocksize] +%if pixelsize == 1 + punpcklbw m1, m0 +%endif + psllw m1, shift + STORE [dstq + j * 2 * blocksize], m1 + +%assign j (j + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq + +%assign i (i + 1) +%endrep + + dec heightd + jg .loop + RET +%endmacro + +INIT_XMM sse2 +GET_PIXELS 4, 8, 1 +GET_PIXELS 8, 8, 1 +GET_PIXELS 12, 8, 3 +GET_PIXELS 16, 8, 2 +GET_PIXELS 24, 8, 3 +GET_PIXELS 32, 8, 3 +GET_PIXELS 48, 8, 3 +GET_PIXELS 64, 8, 3 + +GET_PIXELS 4, 10, 1 +GET_PIXELS 8, 10, 1 +GET_PIXELS 12, 10, 3 +GET_PIXELS 16, 10, 2 +GET_PIXELS 24, 10, 3 +GET_PIXELS 32, 10, 3 +GET_PIXELS 48, 10, 3 +GET_PIXELS 64, 10, 3 + +; hevc_qpel_h/v__8(int16_t *dst, ptrdiff_t dststride, +; uint8_t *src, ptrdiff_t srcstride, +; int height, int mx, int my, int *mcbuffer) + +; 8-bit qpel interpolation +; %1: block width +; %2: 0 - horizontal; 1 - vertical +%macro QPEL_8 2 +%if %2 + %define postfix v + %define mvfrac myq + %define coeffsaddr r5q + %define pixstride srcstrideq + %define pixstride3 r5q + %define src_m3 r6q +%else + %define postfix h + %define mvfrac mxq + %define coeffsaddr r6q + %define pixstride 1 + %define pixstride3 3 + %define src_m3 (srcq - 3) +%endif + + COMMON_DEFS %1, 8 + +cglobal hevc_qpel_ %+ postfix %+ _ %+ %1 %+ _8, 7, 7, 7, dst, dststride, src, srcstride, height, mx, my + and mvfrac, 0x3 + dec mvfrac + shl mvfrac, 4 + lea coeffsaddr, [hevc_qpel_coeffs8] + mova m0, [coeffsaddr + mvfrac] + + SPLATW m1, m0, 1 + SPLATW m2, m0, 2 + SPLATW m3, m0, 3 + SPLATW m0, m0, 0 + +%if %2 + lea pixstride3, [srcstrideq + 2 * srcstrideq] + mov src_m3, srcq + sub src_m3, pixstride3 +%endif + +.loop + +%assign i 0 +%rep nb_blocks + + BLOCK_DEFS i + + LOAD m4, [src_m3 + i * blocksize] + LOAD m5, [src_m3 + i * blocksize + 1 * pixstride] + punpcklbw m4, m5 + pmaddubsw m4, m0 + + LOAD m5, [src_m3 + i * blocksize + 2 * pixstride] + LOAD m6, [srcq + i * blocksize] + punpcklbw m5, m6 + pmaddubsw m5, m1 + paddsw m4, m5 + + LOAD m5, [srcq + i * blocksize + 1 * pixstride] + LOAD m6, [srcq + i * blocksize + 2 * pixstride] + punpcklbw m5, m6 + pmaddubsw m5, m2 + paddsw m4, m5 + + LOAD m5, [srcq + i * blocksize + pixstride3] + LOAD m6, [srcq + i * blocksize + 4 * pixstride] + punpcklbw m5, m6 + pmaddubsw m5, m3 + paddsw m4, m5 + + STORE [dstq + i * 2 * blocksize], m4 + +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq +%if %2 + add src_m3, srcstrideq +%endif + + dec heightd + jg .loop + RET +%endmacro + +INIT_XMM ssse3 +QPEL_8 4, 0 +QPEL_8 8, 0 +QPEL_8 12, 0 +QPEL_8 16, 0 +QPEL_8 24, 0 +QPEL_8 32, 0 +QPEL_8 48, 0 +QPEL_8 64, 0 + +QPEL_8 4, 1 +QPEL_8 8, 1 +QPEL_8 12, 1 +QPEL_8 16, 1 +QPEL_8 24, 1 +QPEL_8 32, 1 +QPEL_8 48, 1 +QPEL_8 64, 1 + +; 16-bit qpel interpolation +; %1: block width +; %2: shift applied to the result +; %3: 0 - horizontal; 1 - vertical +%macro QPEL_16 3 +%if %3 + %define mvfrac myq + %define pixstride srcstrideq + %define pixstride3 sstride3q + %define src_m3 srcm3q +%else + %define mvfrac mxq + %define pixstride 2 + %define pixstride3 6 + %define src_m3 (srcq - 6) +%endif + + COMMON_DEFS %1, 16 + + and mvfrac, 0x3 + dec mvfrac + shl mvfrac, 4 + lea coeffsregq, [hevc_qpel_coeffs] + mova m0, [coeffsregq + mvfrac] + + pshufd m1, m0, 0x55 + pshufd m2, m0, 0xaa + pshufd m3, m0, 0xff + pshufd m0, m0, 0x00 + +%if %3 + lea sstride3q, [srcstrideq + 2 * srcstrideq] + mov srcm3q, srcq + sub srcm3q, sstride3q +%endif + +.loop + +%assign i 0 +%rep nb_blocks + + BLOCK_DEFS i + + LOAD m4, [src_m3 + i * 2 * blocksize] + LOAD m5, [src_m3 + i * 2 * blocksize + 1 * pixstride] + LOAD m6, [src_m3 + i * 2 * blocksize + 2 * pixstride] + LOAD m7, [srcq + i * 2 * blocksize + 0 * pixstride] + LOAD m8, [srcq + i * 2 * blocksize + 1 * pixstride] + LOAD m9, [srcq + i * 2 * blocksize + 2 * pixstride] + LOAD m10, [srcq + i * 2 * blocksize + pixstride3] + LOAD m11, [srcq + i * 2 * blocksize + 4 * pixstride] + + punpcklwd m12, m4, m5 + pmaddwd m12, m0 + + punpcklwd m13, m6, m7 + pmaddwd m13, m1 + paddd m12, m13 + + punpcklwd m13, m8, m9 + pmaddwd m13, m2 + paddd m12, m13 + + punpcklwd m13, m10, m11 + pmaddwd m13, m3 + paddd m12, m13 + psrad m12, %2 + + %if block_truncated == 0 + punpckhwd m4, m5 + pmaddwd m4, m0 + + punpckhwd m6, m7 + pmaddwd m6, m1 + paddd m4, m6 + + punpckhwd m8, m9 + pmaddwd m8, m2 + paddd m4, m8 + + punpckhwd m10, m11 + pmaddwd m10, m3 + paddd m4, m10 + + psrad m4, %2 + %endif + packssdw m12, m4 + STORE [dstq + i * 2 * blocksize], m12 + +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq +%if %3 + add srcm3q, srcstrideq +%endif + + dec heightd + jg .loop + RET +%endmacro + +%if ARCH_X86_64 + +%macro QPEL_H_10 1 +cglobal hevc_qpel_h_ %+ %1 %+ _10, 7, 9, 14, dst, dststride, src, srcstride, height, mx, my, mcbuffer, coeffsreg +QPEL_16 %1, 2, 0 +%endmacro + +INIT_XMM avx +QPEL_H_10 4 +QPEL_H_10 8 +QPEL_H_10 12 +QPEL_H_10 16 +QPEL_H_10 24 +QPEL_H_10 32 +QPEL_H_10 48 +QPEL_H_10 64 + +%macro QPEL_V_10 1 +cglobal hevc_qpel_v_ %+ %1 %+ _10, 7, 10, 14, dst, dststride, src, srcstride, height, mx, my, sstride3, srcm3, coeffsreg +QPEL_16 %1, 2, 1 +%endmacro + +INIT_XMM avx +QPEL_V_10 4 +QPEL_V_10 8 +QPEL_V_10 12 +QPEL_V_10 16 +QPEL_V_10 24 +QPEL_V_10 32 +QPEL_V_10 48 +QPEL_V_10 64 + +; hevc_qpel_hv_(int16_t *dst, ptrdiff_t dststride, +; uint8_t *src, ptrdiff_t srcstride, +; int height, int mx, int my, int *mcbuffer) + +%macro QPEL_HV 1 +cglobal hevc_qpel_hv_ %+ %1, 7, 10, 14, dst, dststride, src, srcstride, height, mx, my, sstride3, srcm3, coeffsreg +QPEL_16 %1, 6, 1 +%endmacro + +INIT_XMM avx +QPEL_HV 4 +QPEL_HV 8 +QPEL_HV 12 +QPEL_HV 16 +QPEL_HV 24 +QPEL_HV 32 +QPEL_HV 48 +QPEL_HV 64 + +%endif ; ARCH_X86_64 + +; hevc_epel_h/v__8(int16_t *dst, ptrdiff_t dststride, +; uint8_t *src, ptrdiff_t srcstride, +; int height, int mx, int my, int *mcbuffer) + +; 8-bit epel interpolation +; %1: block width +; %2: 0 - horizontal; 1 - vertical +%macro EPEL_8 2 +%if %2 + %define postfix v + %define mvfrac myq + %define coeffsaddr r5q + %define pixstride srcstrideq + %define pixstride3 r5q +%else + %define postfix h + %define mvfrac mxq + %define coeffsaddr r6q + %define pixstride 1 + %define pixstride3 3 +%endif + + COMMON_DEFS %1, 8 + +cglobal hevc_epel_ %+ postfix %+ _ %+ %1 %+ _8, 7, 7, 6, dst, dststride, src, srcstride, height, mx, my + and mvfrac, 0x7 + dec mvfrac + shl mvfrac, 4 + lea coeffsaddr, [hevc_epel_coeffs8] + movq m0, [coeffsaddr + mvfrac] + + SPLATW m1, m0, 1 + SPLATW m0, m0, 0 + +%if %2 + lea pixstride3, [srcstrideq + 2 * srcstrideq] +%endif + sub srcq, pixstride + +.loop + +%assign i 0 +%rep nb_blocks + + BLOCK_DEFS i + + LOAD m2, [srcq + i * blocksize + 0 * pixstride] + LOAD m3, [srcq + i * blocksize + 1 * pixstride] + LOAD m4, [srcq + i * blocksize + 2 * pixstride] + LOAD m5, [srcq + i * blocksize + pixstride3] + + punpcklbw m2, m3 + punpcklbw m4, m5 + + pmaddubsw m2, m0 + pmaddubsw m4, m1 + + paddsw m2, m4 + + STORE [dstq + i * 2 * blocksize], m2 + +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq + + dec heightd + jg .loop + RET +%endmacro + +INIT_XMM ssse3 +EPEL_8 4, 0 +EPEL_8 8, 0 +EPEL_8 12, 0 +EPEL_8 16, 0 +EPEL_8 24, 0 +EPEL_8 32, 0 + +EPEL_8 4, 1 +EPEL_8 8, 1 +EPEL_8 12, 1 +EPEL_8 16, 1 +EPEL_8 24, 1 +EPEL_8 32, 1 + +%macro EPEL_16 3 +%if %3 + %define mvfrac myq + %define pixstride srcstrideq + %define pixstride3 sstride3q +%else + %define mvfrac mxq + %define pixstride 2 + %define pixstride3 6 +%endif + + COMMON_DEFS %1, 16 + + and mvfrac, 0x7 + dec mvfrac + shl mvfrac, 5 + lea coeffsregq, [hevc_epel_coeffs] + mova m0, [coeffsregq + mvfrac] + + pshufd m1, m0, 0x55 + pshufd m0, m0, 0x00 + +%if %3 + lea sstride3q, [srcstrideq + 2 * srcstrideq] +%endif + sub srcq, pixstride + +.loop + +%assign i 0 +%rep nb_blocks + + BLOCK_DEFS i + + LOAD m2, [srcq + i * 2 * blocksize + 0 * pixstride] + LOAD m3, [srcq + i * 2 * blocksize + 1 * pixstride] + LOAD m4, [srcq + i * 2 * blocksize + 2 * pixstride] + LOAD m5, [srcq + i * 2 * blocksize + pixstride3] + + punpcklwd m6, m2, m3 + punpcklwd m7, m4, m5 + pmaddwd m6, m0 + pmaddwd m7, m1 + paddd m6, m7 + psrad m6, %2 + + %if block_truncated == 0 + punpckhwd m2, m3 + punpckhwd m4, m5 + pmaddwd m2, m0 + pmaddwd m4, m1 + paddd m2, m4 + psrad m2, %2 + %endif + packssdw m6, m2 + STORE [dstq + i * 2 * blocksize], m6 + +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq + + dec heightd + jg .loop + RET +%endmacro + +%if ARCH_X86_64 + +%macro EPEL_H_10 1 +cglobal hevc_epel_h_ %+ %1 %+ _10, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg +EPEL_16 %1, 2, 0 +%endmacro + +INIT_XMM avx +EPEL_H_10 4 +EPEL_H_10 8 +EPEL_H_10 12 +EPEL_H_10 16 +EPEL_H_10 24 +EPEL_H_10 32 + +%macro EPEL_V_10 1 +cglobal hevc_epel_v_ %+ %1 %+ _10, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg +EPEL_16 %1, 2, 1 +%endmacro + +INIT_XMM avx +EPEL_V_10 4 +EPEL_V_10 8 +EPEL_V_10 12 +EPEL_V_10 16 +EPEL_V_10 24 +EPEL_V_10 32 + +; hevc_epel_hv__8(int16_t *dst, ptrdiff_t dststride, +; int16_t *src, ptrdiff_t srcstride, +; int height, int mx, int my, int *mcbuffer) + +%macro EPEL_HV 1 +cglobal hevc_epel_hv_ %+ %1, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg +EPEL_16 %1, 6, 1 +%endmacro + +INIT_XMM avx +EPEL_HV 4 +EPEL_HV 8 +EPEL_HV 12 +EPEL_HV 16 +EPEL_HV 24 +EPEL_HV 32 + +%endif ; ARCH_X86_64 + +; hevc_put_unweighted_pred__(pixel *dst, ptrdiff_t dststride, +; int16_t *src, ptrdiff_t srcstride, +; int height) + +%macro AVG 5 + %if %3 + %if %4 == 4 + movq %5, %2 + paddsw %1, %5 + %else + paddsw %1, %2 + %endif + %endif +%endmacro + +; %1: 0 - one source; 1 - two sources +; %2: width +; %3: bit depth +%macro PUT_PRED 3 +%if %1 +cglobal hevc_put_unweighted_pred_avg_ %+ %2 %+ _ %+ %3, 6, 6, 4, dst, dststride, src, src2, srcstride, height +%else +cglobal hevc_put_unweighted_pred_ %+ %2 %+ _ %+ %3, 5, 5, 4, dst, dststride, src, srcstride, height +%endif + +%assign shift 14 + %1 - %3 +%assign offset (1 << (shift - 1)) +%define offset_data pw_ %+ offset + + mova m0, [offset_data] + +%if %3 > 8 + %define STORE_BLOCK movu + %define STORE_HALF movq + + %assign pixel_max ((1 << %3) - 1) + %define pw_pixel_max pw_ %+ pixel_max + pxor m1, m1 + mova m2, [pw_pixel_max] +%else + %define STORE_BLOCK movq + %define STORE_HALF movd +%endif + +.loop +%assign i 0 +%rep (%2 + 7) / 8 + + %if (i + 1) * 8 > %2 + %define LOAD movq + %define STORE STORE_HALF + %else + %define LOAD mova + %define STORE STORE_BLOCK + %endif + + LOAD m3, [srcq + 16 * i] + AVG m3, [src2q + 16 * i], %1, %3 - i * 8, m4 + + paddsw m3, m0 + psraw m3, shift + + %if %3 == 8 + packuswb m3, m3 + STORE [dstq + 8 * i], m3 + %else + CLIPW m3, m1, m2 + STORE [dstq + 16 * i], m3 + %endif +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add srcq, srcstrideq +%if %1 + add src2q, srcstrideq +%endif + + dec heightd + jg .loop + RET +%endmacro + +INIT_XMM sse2 +PUT_PRED 0, 4, 8 +PUT_PRED 1, 4, 8 +PUT_PRED 0, 8, 8 +PUT_PRED 1, 8, 8 +PUT_PRED 0, 12, 8 +PUT_PRED 1, 12, 8 +PUT_PRED 0, 16, 8 +PUT_PRED 1, 16, 8 +PUT_PRED 0, 24, 8 +PUT_PRED 1, 24, 8 +PUT_PRED 0, 32, 8 +PUT_PRED 1, 32, 8 +PUT_PRED 0, 48, 8 +PUT_PRED 1, 48, 8 +PUT_PRED 0, 64, 8 +PUT_PRED 1, 64, 8 + +PUT_PRED 0, 4, 10 +PUT_PRED 1, 4, 10 +PUT_PRED 0, 8, 10 +PUT_PRED 1, 8, 10 +PUT_PRED 0, 12, 10 +PUT_PRED 1, 12, 10 +PUT_PRED 0, 16, 10 +PUT_PRED 1, 16, 10 +PUT_PRED 0, 24, 10 +PUT_PRED 1, 24, 10 +PUT_PRED 0, 32, 10 +PUT_PRED 1, 32, 10 +PUT_PRED 0, 48, 10 +PUT_PRED 1, 48, 10 +PUT_PRED 0, 64, 10 +PUT_PRED 1, 64, 10 + +%macro PUT_WEIGHTED_PRED 3 +%if %1 +cglobal hevc_put_weighted_pred_avg_ %+ %2 %+ _ %+ %3, 11, 11, 8, denom, weight0, weight1, offset0, offset1, dst, dststride, src0, src1, srcstride, height +%else +cglobal hevc_put_weighted_pred_ %+ %2 %+ _ %+ %3, 8, 8, 8, denom, weight0, offset0, dst, dststride, src0, srcstride, height +%endif + + and denomd, 0xff + movsx weight0d, weight0w + movsx offset0d, offset0w +%if %1 + movsx weight1d, weight1w + movsx offset1d, offset1w +%endif + + add denomd, 14 + %1 - %3 + movd m0, denomd + +%if %3 > 8 + %assign pixel_max ((1 << %3) - 1) + %define pw_pixel_max pw_ %+ pixel_max + pxor m4, m4 + mova m5, [pw_pixel_max] + + shl offset0d, %3 - 8 +%if %1 + shl offset1d, %3 - 8 +%endif +%endif + +%if %1 + lea offset0d, [offset0d + offset1d + 1] +%else + lea offset0d, [2 * offset0d + 1] +%endif + movd m1, offset0d + SPLATD m1 + pslld m1, m0 + psrad m1, 1 + + movd m2, weight0d + SPLATD m2 +%if %1 + movd m3, weight1d + SPLATD m3 +%endif + +.loop +%assign i 0 +%rep (%2 + 3) / 4 + + pmovsxwd m6, [src0q + 8 * i] + pmulld m6, m2 + +%if %1 + pmovsxwd m7, [src1q + 8 * i] + pmulld m7, m3 + paddd m6, m7 +%endif + + paddd m6, m1 + psrad m6, m0 + + packssdw m6, m6 + +%if %3 > 8 + CLIPW m6, m4, m5 + movq [dstq + 8 * i], m6 +%else + packuswb m6, m6 + movd [dstq + 4 * i], m6 +%endif + +%assign i (i + 1) +%endrep + + add dstq, dststrideq + add src0q, srcstrideq +%if %1 + add src1q, srcstrideq +%endif + + dec heightd + jg .loop + RET +%endmacro + +%if ARCH_X86_64 +INIT_XMM sse4 +PUT_WEIGHTED_PRED 0, 4, 8 +PUT_WEIGHTED_PRED 1, 4, 8 +PUT_WEIGHTED_PRED 0, 8, 8 +PUT_WEIGHTED_PRED 1, 8, 8 +PUT_WEIGHTED_PRED 0, 12, 8 +PUT_WEIGHTED_PRED 1, 12, 8 +PUT_WEIGHTED_PRED 0, 16, 8 +PUT_WEIGHTED_PRED 1, 16, 8 +PUT_WEIGHTED_PRED 0, 24, 8 +PUT_WEIGHTED_PRED 1, 24, 8 +PUT_WEIGHTED_PRED 0, 32, 8 +PUT_WEIGHTED_PRED 1, 32, 8 +PUT_WEIGHTED_PRED 0, 48, 8 +PUT_WEIGHTED_PRED 1, 48, 8 +PUT_WEIGHTED_PRED 0, 64, 8 +PUT_WEIGHTED_PRED 1, 64, 8 + +PUT_WEIGHTED_PRED 0, 4, 10 +PUT_WEIGHTED_PRED 1, 4, 10 +PUT_WEIGHTED_PRED 0, 8, 10 +PUT_WEIGHTED_PRED 1, 8, 10 +PUT_WEIGHTED_PRED 0, 12, 10 +PUT_WEIGHTED_PRED 1, 12, 10 +PUT_WEIGHTED_PRED 0, 16, 10 +PUT_WEIGHTED_PRED 1, 16, 10 +PUT_WEIGHTED_PRED 0, 24, 10 +PUT_WEIGHTED_PRED 1, 24, 10 +PUT_WEIGHTED_PRED 0, 32, 10 +PUT_WEIGHTED_PRED 1, 32, 10 +PUT_WEIGHTED_PRED 0, 48, 10 +PUT_WEIGHTED_PRED 1, 48, 10 +PUT_WEIGHTED_PRED 0, 64, 10 +PUT_WEIGHTED_PRED 1, 64, 10 + +%endif ; ARCH_X86_64 diff --git a/libavcodec/x86/hevcdsp_init.c b/libavcodec/x86/hevcdsp_init.c index 04203c2..1a675ab 100644 --- a/libavcodec/x86/hevcdsp_init.c +++ b/libavcodec/x86/hevcdsp_init.c @@ -45,27 +45,321 @@ LFC_FUNCS(uint8_t, 10) LFL_FUNCS(uint8_t, 8) LFL_FUNCS(uint8_t, 10) +#define idct_dc_proto(size, bitd, opt) \ + void ff_hevc_idct_ ## size ## _dc_add_ ## bitd ## _ ## opt(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride) + +idct_dc_proto(4, 8,mmxext); +idct_dc_proto(8, 8,mmxext); +idct_dc_proto(16,8, sse2); +idct_dc_proto(32,8, sse2); + +idct_dc_proto(32,8, avx2); + +idct_dc_proto(4, 10,mmxext); +idct_dc_proto(8, 10, sse2); +idct_dc_proto(16,10, sse2); +idct_dc_proto(32,10, sse2); +idct_dc_proto(8, 10, avx); +idct_dc_proto(16,10, avx); +idct_dc_proto(32,10, avx); + +idct_dc_proto(16,10, avx2); +idct_dc_proto(32,10, avx2); + +#define IDCT_FUNCS(W, opt) \ +void ff_hevc_idct_ ## W ## _dc_8_ ## opt(int16_t *coeffs); \ +void ff_hevc_idct_ ## W ## _dc_10_ ## opt(int16_t *coeffs) + +IDCT_FUNCS(4x4, mmxext); +IDCT_FUNCS(8x8, mmxext); +IDCT_FUNCS(8x8, sse2); +IDCT_FUNCS(16x16, sse2); +IDCT_FUNCS(32x32, sse2); +IDCT_FUNCS(16x16, avx2); +IDCT_FUNCS(32x32, avx2); + +#define GET_PIXELS(width, depth, cf) \ +void ff_hevc_get_pixels_ ## width ## _ ## depth ## _ ## cf(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); + +GET_PIXELS(4, 8, sse2) +GET_PIXELS(8, 8, sse2) +GET_PIXELS(12, 8, sse2) +GET_PIXELS(16, 8, sse2) +GET_PIXELS(24, 8, sse2) +GET_PIXELS(32, 8, sse2) +GET_PIXELS(48, 8, sse2) +GET_PIXELS(64, 8, sse2) + +GET_PIXELS(4, 10, sse2) +GET_PIXELS(8, 10, sse2) +GET_PIXELS(12, 10, sse2) +GET_PIXELS(16, 10, sse2) +GET_PIXELS(24, 10, sse2) +GET_PIXELS(32, 10, sse2) +GET_PIXELS(48, 10, sse2) +GET_PIXELS(64, 10, sse2) + +/* those are independent of the bit depth, so declared separately */ +#define INTERP_HV_FUNC(width, cf) \ +void ff_hevc_qpel_hv_ ## width ## _ ## cf(int16_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); \ +void ff_hevc_epel_hv_ ## width ## _ ## cf(int16_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); + +INTERP_HV_FUNC(4, avx) +INTERP_HV_FUNC(8, avx) +INTERP_HV_FUNC(12, avx) +INTERP_HV_FUNC(16, avx) +INTERP_HV_FUNC(24, avx) +INTERP_HV_FUNC(32, avx) +INTERP_HV_FUNC(48, avx) +INTERP_HV_FUNC(64, avx) + +#if ARCH_X86_64 && HAVE_AVX_EXTERNAL +#define QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) \ +static void hevc_qpel_hv_ ## width ## _ ## depth ## _ ## cf_hv(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer) \ +{ \ + const ptrdiff_t stride = FFALIGN(width + 7, 8); \ + ff_hevc_qpel_h_ ## width ## _ ## depth ## _ ## cf_h(mcbuffer, 2 * stride, src - 3 * srcstride, srcstride, \ + height + 7, mx, my, mcbuffer); \ + ff_hevc_qpel_hv_ ## width ## _ ## cf_hv(dst, dststride, mcbuffer + 3 * stride, 2 * stride, \ + height, mx, my, mcbuffer); \ +} +#else +#define QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) +#endif /* ARCH_X86_64 && HAVE_AVX_EXTERNAL */ + +#define QPEL_FUNCS(width, depth, cf_h, cf_v, cf_hv) \ +void ff_hevc_qpel_h_ ## width ## _ ## depth ## _ ## cf_h(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); \ +void ff_hevc_qpel_v_ ## width ## _ ## depth ## _ ## cf_v(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); \ +QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) + +QPEL_FUNCS(4, 8, ssse3, ssse3, avx) +QPEL_FUNCS(8, 8, ssse3, ssse3, avx) +QPEL_FUNCS(12, 8, ssse3, ssse3, avx) +QPEL_FUNCS(16, 8, ssse3, ssse3, avx) +QPEL_FUNCS(24, 8, ssse3, ssse3, avx) +QPEL_FUNCS(32, 8, ssse3, ssse3, avx) +QPEL_FUNCS(48, 8, ssse3, ssse3, avx) +QPEL_FUNCS(64, 8, ssse3, ssse3, avx) + +QPEL_FUNCS(4, 10, avx, avx, avx) +QPEL_FUNCS(8, 10, avx, avx, avx) +QPEL_FUNCS(12, 10, avx, avx, avx) +QPEL_FUNCS(16, 10, avx, avx, avx) +QPEL_FUNCS(24, 10, avx, avx, avx) +QPEL_FUNCS(32, 10, avx, avx, avx) +QPEL_FUNCS(48, 10, avx, avx, avx) +QPEL_FUNCS(64, 10, avx, avx, avx) + +#if ARCH_X86_64 && HAVE_AVX_EXTERNAL +#define EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) \ +static void hevc_epel_hv_ ## width ## _ ## depth ## _ ## cf_hv(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer) \ +{ \ + const ptrdiff_t stride = FFALIGN(width + 3, 8); \ + ff_hevc_epel_h_ ## width ## _ ## depth ## _ ## cf_h(mcbuffer, 2 * stride, src - srcstride, srcstride, \ + height + 3, mx, my, mcbuffer); \ + ff_hevc_epel_hv_ ## width ## _ ## cf_hv(dst, dststride, mcbuffer + stride, 2 * stride, \ + height, mx, my, mcbuffer); \ +} +#else +#define EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) +#endif /* ARCH_X86_64 && HAVE_AVX_EXTERNAL */ + +#define EPEL_FUNCS(width, depth, cf_h, cf_v, cf_hv) \ +void ff_hevc_epel_h_ ## width ## _ ## depth ## _ ## cf_h(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); \ +void ff_hevc_epel_v_ ## width ## _ ## depth ## _ ## cf_v(int16_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int height, int mx, int my, int16_t *mcbuffer); \ +EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv) + +EPEL_FUNCS(4, 8, ssse3, ssse3, avx) +EPEL_FUNCS(8, 8, ssse3, ssse3, avx) +EPEL_FUNCS(12, 8, ssse3, ssse3, avx) +EPEL_FUNCS(16, 8, ssse3, ssse3, avx) +EPEL_FUNCS(24, 8, ssse3, ssse3, avx) +EPEL_FUNCS(32, 8, ssse3, ssse3, avx) + +EPEL_FUNCS(4, 10, avx, avx, avx) +EPEL_FUNCS(8, 10, avx, avx, avx) +EPEL_FUNCS(12, 10, avx, avx, avx) +EPEL_FUNCS(16, 10, avx, avx, avx) +EPEL_FUNCS(24, 10, avx, avx, avx) +EPEL_FUNCS(32, 10, avx, avx, avx) + +#define PUT_PRED(width, depth, cf_uw, cf_w) \ +void ff_hevc_put_unweighted_pred_ ## width ## _ ## depth ## _ ## cf_uw(uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, \ + int height); \ +void ff_hevc_put_unweighted_pred_avg_ ## width ## _ ## depth ## _ ## cf_uw(uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src1, int16_t *src2, \ + ptrdiff_t srcstride, int height); \ +void ff_hevc_put_weighted_pred_ ## width ## _ ## depth ## _ ## cf_w(uint8_t denom, int16_t weight, int16_t offset, \ + uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src, ptrdiff_t srcstride, \ + int height); \ +void ff_hevc_put_weighted_pred_avg_ ## width ## _ ## depth ## _ ## cf_w(uint8_t denom, int16_t weight0, int16_t weight1, \ + int16_t offset0, int16_t offset1, \ + uint8_t *dst, ptrdiff_t dststride, \ + int16_t *src0, int16_t *src1, ptrdiff_t srcstride, \ + int height); + +PUT_PRED(4, 8, sse2, sse4) +PUT_PRED(8, 8, sse2, sse4) +PUT_PRED(12, 8, sse2, sse4) +PUT_PRED(16, 8, sse2, sse4) +PUT_PRED(24, 8, sse2, sse4) +PUT_PRED(32, 8, sse2, sse4) +PUT_PRED(48, 8, sse2, sse4) +PUT_PRED(64, 8, sse2, sse4) + +PUT_PRED(4, 10, sse2, sse4) +PUT_PRED(8, 10, sse2, sse4) +PUT_PRED(12, 10, sse2, sse4) +PUT_PRED(16, 10, sse2, sse4) +PUT_PRED(24, 10, sse2, sse4) +PUT_PRED(32, 10, sse2, sse4) +PUT_PRED(48, 10, sse2, sse4) +PUT_PRED(64, 10, sse2, sse4) + void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth) { int cpu_flags = av_get_cpu_flags(); +#define SET_LUMA_FUNCS(tabname, funcname, depth, cf) \ + c->tabname[0] = funcname ## _4_ ## depth ## _ ## cf; \ + c->tabname[1] = funcname ## _8_ ## depth ## _ ## cf; \ + c->tabname[2] = funcname ## _12_ ## depth ## _ ## cf; \ + c->tabname[3] = funcname ## _16_ ## depth ## _ ## cf; \ + c->tabname[4] = funcname ## _24_ ## depth ## _ ## cf; \ + c->tabname[5] = funcname ## _32_ ## depth ## _ ## cf; \ + c->tabname[6] = funcname ## _48_ ## depth ## _ ## cf; \ + c->tabname[7] = funcname ## _64_ ## depth ## _ ## cf; + +#define SET_CHROMA_FUNCS(tabname, funcname, depth, cf) \ + c->tabname[1] = funcname ## _4_ ## depth ## _ ## cf; \ + c->tabname[3] = funcname ## _8_ ## depth ## _ ## cf; \ + c->tabname[4] = funcname ## _12_ ## depth ## _ ## cf; \ + c->tabname[5] = funcname ## _16_ ## depth ## _ ## cf; \ + c->tabname[6] = funcname ## _24_ ## depth ## _ ## cf; \ + c->tabname[7] = funcname ## _32_ ## depth ## _ ## cf; + +#define SET_QPEL_FUNCS(v, h, depth, cf, name) SET_LUMA_FUNCS (put_hevc_qpel[v][h], name, depth, cf) +#define SET_EPEL_FUNCS(v, h, depth, cf, name) SET_CHROMA_FUNCS(put_hevc_epel[v][h], name, depth, cf) + if (bit_depth == 8) { + if (EXTERNAL_MMXEXT(cpu_flags)) { + c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_mmxext; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_mmxext; + } if (EXTERNAL_SSE2(cpu_flags)) { c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_8_sse2; c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_8_sse2; + + c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_sse2; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_sse2; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_sse2; + SET_QPEL_FUNCS(0, 0, 8, sse2, ff_hevc_get_pixels); + SET_EPEL_FUNCS(0, 0, 8, sse2, ff_hevc_get_pixels); + + SET_LUMA_FUNCS(put_unweighted_pred, ff_hevc_put_unweighted_pred, 8, sse2); + SET_LUMA_FUNCS(put_unweighted_pred_avg, ff_hevc_put_unweighted_pred_avg, 8, sse2); + SET_CHROMA_FUNCS(put_unweighted_pred_chroma, ff_hevc_put_unweighted_pred, 8, sse2); + SET_CHROMA_FUNCS(put_unweighted_pred_avg_chroma, ff_hevc_put_unweighted_pred_avg, 8, sse2); } - if (EXTERNAL_SSSE3(cpu_flags) && ARCH_X86_64) { - c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_8_ssse3; - c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_8_ssse3; + if (EXTERNAL_SSSE3(cpu_flags)) { + SET_QPEL_FUNCS(0, 1, 8, ssse3, ff_hevc_qpel_h); + SET_QPEL_FUNCS(1, 0, 8, ssse3, ff_hevc_qpel_v); + SET_EPEL_FUNCS(0, 1, 8, ssse3, ff_hevc_epel_h); + SET_EPEL_FUNCS(1, 0, 8, ssse3, ff_hevc_epel_v); + } } else if (bit_depth == 10) { + if (EXTERNAL_MMXEXT(cpu_flags)) { + c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_mmxext; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_mmxext; + } if (EXTERNAL_SSE2(cpu_flags)) { c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2; c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_10_sse2; + + c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_sse2; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_sse2; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_sse2; + + SET_QPEL_FUNCS(0, 0, 10, sse2, ff_hevc_get_pixels); + SET_EPEL_FUNCS(0, 0, 10, sse2, ff_hevc_get_pixels); + + SET_LUMA_FUNCS(put_unweighted_pred, ff_hevc_put_unweighted_pred, 10, sse2); + SET_LUMA_FUNCS(put_unweighted_pred_avg, ff_hevc_put_unweighted_pred_avg, 10, sse2); + SET_CHROMA_FUNCS(put_unweighted_pred_chroma, ff_hevc_put_unweighted_pred, 10, sse2); + SET_CHROMA_FUNCS(put_unweighted_pred_avg_chroma, ff_hevc_put_unweighted_pred_avg, 10, sse2); + } + } + +#if ARCH_X86_64 + if (bit_depth == 8) { + if (EXTERNAL_SSSE3(cpu_flags)) { + c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_8_ssse3; + c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_8_ssse3; } - if (EXTERNAL_SSSE3(cpu_flags) && ARCH_X86_64) { + + if (EXTERNAL_SSE4(cpu_flags)) { + SET_LUMA_FUNCS(weighted_pred, ff_hevc_put_weighted_pred, 8, sse4); + SET_CHROMA_FUNCS(weighted_pred_chroma, ff_hevc_put_weighted_pred, 8, sse4); + SET_LUMA_FUNCS(weighted_pred_avg, ff_hevc_put_weighted_pred_avg, 8, sse4); + SET_CHROMA_FUNCS(weighted_pred_avg_chroma, ff_hevc_put_weighted_pred_avg, 8, sse4); + } + + if (EXTERNAL_AVX(cpu_flags)) { +#if HAVE_AVX_EXTERNAL + SET_QPEL_FUNCS(1, 1, 8, avx, hevc_qpel_hv); + SET_EPEL_FUNCS(1, 1, 8, avx, hevc_epel_hv); +#endif /* HAVE_AVX_EXTERNAL */ + } + if (EXTERNAL_AVX2(cpu_flags)) { + c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_avx2; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_avx2; + } + } else if (bit_depth == 10) { + if (EXTERNAL_SSSE3(cpu_flags)) { c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_10_ssse3; c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_10_ssse3; } + if (EXTERNAL_SSE4(cpu_flags)) { + SET_LUMA_FUNCS(weighted_pred, ff_hevc_put_weighted_pred, 10, sse4); + SET_CHROMA_FUNCS(weighted_pred_chroma, ff_hevc_put_weighted_pred, 10, sse4); + SET_LUMA_FUNCS(weighted_pred_avg, ff_hevc_put_weighted_pred_avg, 10, sse4); + SET_CHROMA_FUNCS(weighted_pred_avg_chroma, ff_hevc_put_weighted_pred_avg, 10, sse4); + } + if (EXTERNAL_AVX(cpu_flags)) { +#if HAVE_AVX_EXTERNAL + SET_QPEL_FUNCS(0, 1, 10, avx, ff_hevc_qpel_h); + SET_QPEL_FUNCS(1, 0, 10, avx, ff_hevc_qpel_v); + SET_QPEL_FUNCS(1, 1, 10, avx, hevc_qpel_hv); + SET_EPEL_FUNCS(0, 1, 10, avx, ff_hevc_epel_h); + SET_EPEL_FUNCS(1, 0, 10, avx, ff_hevc_epel_v); + SET_EPEL_FUNCS(1, 1, 10, avx, hevc_epel_hv); +#endif /* HAVE_AVX_EXTERNAL */ + } + if (EXTERNAL_AVX2(cpu_flags)) { + c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_avx2; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_avx2; + } } +#endif /* ARCH_X86_64 */ } diff --git a/libavcodec/x86/hpeldsp.asm b/libavcodec/x86/hpeldsp.asm index 073f7f9..8e21114 100644 --- a/libavcodec/x86/hpeldsp.asm +++ b/libavcodec/x86/hpeldsp.asm @@ -23,7 +23,7 @@ SECTION_RODATA cextern pb_1 -SECTION_TEXT +SECTION .text ; void ff_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_PIXELS8_X2 0 @@ -142,53 +142,6 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_X2 -; void ff_put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_X2_EXACT 0 -cglobal put_no_rnd_pixels8_x2_exact, 4,5 - lea r4, [r2*3] - pcmpeqb m6, m6 -.loop: - mova m0, [r1] - mova m2, [r1+r2] - mova m1, [r1+1] - mova m3, [r1+r2+1] - pxor m0, m6 - pxor m2, m6 - pxor m1, m6 - pxor m3, m6 - PAVGB m0, m1 - PAVGB m2, m3 - pxor m0, m6 - pxor m2, m6 - mova [r0], m0 - mova [r0+r2], m2 - mova m0, [r1+r2*2] - mova m1, [r1+r2*2+1] - mova m2, [r1+r4] - mova m3, [r1+r4+1] - pxor m0, m6 - pxor m1, m6 - pxor m2, m6 - pxor m3, m6 - PAVGB m0, m1 - PAVGB m2, m3 - pxor m0, m6 - pxor m2, m6 - mova [r0+r2*2], m0 - mova [r0+r4], m2 - lea r1, [r1+r2*4] - lea r0, [r0+r2*4] - sub r3d, 4 - jg .loop - REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_X2_EXACT -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_X2_EXACT - - ; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro PUT_PIXELS8_Y2 0 cglobal put_pixels8_y2, 4,5 @@ -260,48 +213,6 @@ INIT_MMX 3dnow PUT_NO_RND_PIXELS8_Y2 -; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_Y2_EXACT 0 -cglobal put_no_rnd_pixels8_y2_exact, 4,5 - lea r4, [r2*3] - mova m0, [r1] - pcmpeqb m6, m6 - add r1, r2 - pxor m0, m6 -.loop: - mova m1, [r1] - mova m2, [r1+r2] - pxor m1, m6 - pxor m2, m6 - PAVGB m0, m1 - PAVGB m1, m2 - pxor m0, m6 - pxor m1, m6 - mova [r0], m0 - mova [r0+r2], m1 - mova m1, [r1+r2*2] - mova m0, [r1+r4] - pxor m1, m6 - pxor m0, m6 - PAVGB m2, m1 - PAVGB m1, m0 - pxor m2, m6 - pxor m1, m6 - mova [r0+r2*2], m2 - mova [r0+r4], m1 - lea r1, [r1+r2*4] - lea r0, [r0+r2*4] - sub r3d, 4 - jg .loop - REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_Y2_EXACT -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_Y2_EXACT - - ; void ff_avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) %macro AVG_PIXELS8 0 cglobal avg_pixels8, 4,5 diff --git a/libavcodec/x86/hpeldsp.h b/libavcodec/x86/hpeldsp.h index 47b0b8b..566e518 100644 --- a/libavcodec/x86/hpeldsp.h +++ b/libavcodec/x86/hpeldsp.h @@ -22,6 +22,8 @@ #include #include +#include "libavcodec/hpeldsp.h" + void ff_avg_pixels8_x2_mmx(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); @@ -35,4 +37,6 @@ void ff_put_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, void ff_put_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_hpeldsp_vp3_init_x86(HpelDSPContext *c, int cpu_flags); + #endif /* AVCODEC_X86_HPELDSP_H */ diff --git a/libavcodec/x86/hpeldsp_init.c b/libavcodec/x86/hpeldsp_init.c index 1cc3bac..6a8d420 100644 --- a/libavcodec/x86/hpeldsp_init.c +++ b/libavcodec/x86/hpeldsp_init.c @@ -24,7 +24,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/hpeldsp.h" @@ -44,12 +43,6 @@ void ff_put_no_rnd_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_x2_exact_mmxext(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_x2_exact_3dnow(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, @@ -58,12 +51,6 @@ void ff_put_no_rnd_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_y2_exact_mmxext(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_y2_exact_3dnow(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_avg_pixels8_3dnow(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_avg_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, @@ -171,7 +158,7 @@ HPELDSP_AVG_PIXELS16(_mmxext) c->PFX ## _pixels_tab IDX [3] = PFX ## _pixels ## SIZE ## _xy2_ ## CPU; \ } while (0) -static void hpeldsp_init_mmx(HpelDSPContext *c, int flags, int cpu_flags) +static void hpeldsp_init_mmx(HpelDSPContext *c, int flags) { #if HAVE_MMX_INLINE SET_HPEL_FUNCS(put, [0], 16, mmx); @@ -184,7 +171,7 @@ static void hpeldsp_init_mmx(HpelDSPContext *c, int flags, int cpu_flags) #endif /* HAVE_MMX_INLINE */ } -static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) +static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags) { #if HAVE_MMXEXT_EXTERNAL c->put_pixels_tab[0][1] = ff_put_pixels16_x2_mmxext; @@ -201,7 +188,7 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_mmxext; c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_mmxext; - if (!(flags & CODEC_FLAG_BITEXACT)) { + if (!(flags & AV_CODEC_FLAG_BITEXACT)) { c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmxext; c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmxext; c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_mmxext; @@ -210,15 +197,10 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmxext; c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmxext; } - - if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_mmxext; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_mmxext; - } #endif /* HAVE_MMXEXT_EXTERNAL */ } -static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) +static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags) { #if HAVE_AMD3DNOW_EXTERNAL c->put_pixels_tab[0][1] = ff_put_pixels16_x2_3dnow; @@ -235,7 +217,7 @@ static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_3dnow; c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_3dnow; - if (!(flags & CODEC_FLAG_BITEXACT)){ + if (!(flags & AV_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] = ff_put_no_rnd_pixels8_x2_3dnow; @@ -244,23 +226,15 @@ static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int cpu_flags) c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow; c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_3dnow; } - - if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_3dnow; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_3dnow; - } #endif /* HAVE_AMD3DNOW_EXTERNAL */ } -static void hpeldsp_init_sse2(HpelDSPContext *c, int flags, int cpu_flags) +static void hpeldsp_init_sse2_fast(HpelDSPContext *c, int flags) { #if HAVE_SSE2_EXTERNAL - if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { - // these functions are slower than mmx on AMD, but faster on Intel - c->put_pixels_tab[0][0] = ff_put_pixels16_sse2; - c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_sse2; - c->avg_pixels_tab[0][0] = ff_avg_pixels16_sse2; - } + c->put_pixels_tab[0][0] = ff_put_pixels16_sse2; + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_sse2; + c->avg_pixels_tab[0][0] = ff_avg_pixels16_sse2; #endif /* HAVE_SSE2_EXTERNAL */ } @@ -269,14 +243,17 @@ av_cold void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags) int cpu_flags = av_get_cpu_flags(); if (INLINE_MMX(cpu_flags)) - hpeldsp_init_mmx(c, flags, cpu_flags); + hpeldsp_init_mmx(c, flags); if (EXTERNAL_AMD3DNOW(cpu_flags)) - hpeldsp_init_3dnow(c, flags, cpu_flags); + hpeldsp_init_3dnow(c, flags); if (EXTERNAL_MMXEXT(cpu_flags)) - hpeldsp_init_mmxext(c, flags, cpu_flags); + hpeldsp_init_mmxext(c, flags); + + if (EXTERNAL_SSE2_FAST(cpu_flags)) + hpeldsp_init_sse2_fast(c, flags); - if (EXTERNAL_SSE2(cpu_flags)) - hpeldsp_init_sse2(c, flags, cpu_flags); + if (CONFIG_VP3_DECODER) + ff_hpeldsp_vp3_init_x86(c, cpu_flags); } diff --git a/libavcodec/x86/hpeldsp_rnd_template.c b/libavcodec/x86/hpeldsp_rnd_template.c index d854e8a..82231ad 100644 --- a/libavcodec/x86/hpeldsp_rnd_template.c +++ b/libavcodec/x86/hpeldsp_rnd_template.c @@ -32,7 +32,7 @@ static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ { MOVQ_BFE(mm6); __asm__ volatile( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1), %%mm0 \n\t" @@ -42,8 +42,8 @@ static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ 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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "movq (%1), %%mm0 \n\t" "movq 1(%1), %%mm1 \n\t" "movq (%1, %3), %%mm2 \n\t" @@ -51,20 +51,20 @@ static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ 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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels), "+D"(block) :"r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { MOVQ_BFE(mm6); __asm__ volatile( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1), %%mm0 \n\t" @@ -81,8 +81,8 @@ static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff 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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "movq (%1), %%mm0 \n\t" "movq 1(%1), %%mm1 \n\t" "movq (%1, %3), %%mm2 \n\t" @@ -97,42 +97,42 @@ static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff 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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels), "+D"(block) :"r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } static void DEF(put, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) { MOVQ_BFE(mm6); __asm__ volatile( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" "movq (%1), %%mm0 \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1, %3), %%mm1 \n\t" - "movq (%1, %%"REG_a"),%%mm2 \n\t" + "movq (%1, %%"FF_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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "movq (%1, %3), %%mm1 \n\t" - "movq (%1, %%"REG_a"),%%mm0 \n\t" + "movq (%1, %%"FF_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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels), "+D"(block) :"r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -165,12 +165,12 @@ static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ { MOVQ_BFE(mm6); __asm__ volatile( - "lea (%3, %3), %%"REG_a" \n\t" + "lea (%3, %3), %%"FF_REG_a" \n\t" "movq (%1), %%mm0 \n\t" ".p2align 3 \n\t" "1: \n\t" "movq (%1, %3), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm2 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm2 \n\t" PAVGBP(%%mm1, %%mm0, %%mm4, %%mm2, %%mm1, %%mm5) "movq (%2), %%mm3 \n\t" PAVGB_MMX(%%mm3, %%mm4, %%mm0, %%mm6) @@ -178,11 +178,11 @@ static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ PAVGB_MMX(%%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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "movq (%1, %3), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" PAVGBP(%%mm1, %%mm2, %%mm4, %%mm0, %%mm1, %%mm5) "movq (%2), %%mm3 \n\t" PAVGB_MMX(%%mm3, %%mm4, %%mm2, %%mm6) @@ -190,12 +190,12 @@ static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_ PAVGB_MMX(%%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" + "add %%"FF_REG_a", %1 \n\t" + "add %%"FF_REG_a", %2 \n\t" "subl $4, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels), "+D"(block) :"r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } diff --git a/libavcodec/x86/hpeldsp_vp3.asm b/libavcodec/x86/hpeldsp_vp3.asm new file mode 100644 index 0000000..513f14e --- /dev/null +++ b/libavcodec/x86/hpeldsp_vp3.asm @@ -0,0 +1,111 @@ +;****************************************************************************** +;* SIMD-optimized halfpel functions for VP3 +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION .text + +; void ff_put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_X2_EXACT 0 +cglobal put_no_rnd_pixels8_x2_exact, 4,5 + lea r4, [r2*3] + pcmpeqb m6, m6 +.loop: + mova m0, [r1] + mova m2, [r1+r2] + mova m1, [r1+1] + mova m3, [r1+r2+1] + pxor m0, m6 + pxor m2, m6 + pxor m1, m6 + pxor m3, m6 + PAVGB m0, m1 + PAVGB m2, m3 + pxor m0, m6 + pxor m2, m6 + mova [r0], m0 + mova [r0+r2], m2 + mova m0, [r1+r2*2] + mova m1, [r1+r2*2+1] + mova m2, [r1+r4] + mova m3, [r1+r4+1] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m1 + PAVGB m2, m3 + pxor m0, m6 + pxor m2, m6 + mova [r0+r2*2], m0 + mova [r0+r4], m2 + lea r1, [r1+r2*4] + lea r0, [r0+r2*4] + sub r3d, 4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_X2_EXACT +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_X2_EXACT + + +; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_Y2_EXACT 0 +cglobal put_no_rnd_pixels8_y2_exact, 4,5 + lea r4, [r2*3] + mova m0, [r1] + pcmpeqb m6, m6 + add r1, r2 + pxor m0, m6 +.loop: + mova m1, [r1] + mova m2, [r1+r2] + pxor m1, m6 + pxor m2, m6 + PAVGB m0, m1 + PAVGB m1, m2 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + mova [r0+r2], m1 + mova m1, [r1+r2*2] + mova m0, [r1+r4] + pxor m1, m6 + pxor m0, m6 + PAVGB m2, m1 + PAVGB m1, m0 + pxor m2, m6 + pxor m1, m6 + mova [r0+r2*2], m2 + mova [r0+r4], m1 + lea r1, [r1+r2*4] + lea r0, [r0+r2*4] + sub r3d, 4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_Y2_EXACT +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_Y2_EXACT diff --git a/libavcodec/x86/hpeldsp_vp3_init.c b/libavcodec/x86/hpeldsp_vp3_init.c new file mode 100644 index 0000000..cc1f5e4 --- /dev/null +++ b/libavcodec/x86/hpeldsp_vp3_init.c @@ -0,0 +1,52 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/hpeldsp.h" + +#include "hpeldsp.h" + +void ff_put_no_rnd_pixels8_x2_exact_mmxext(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_exact_3dnow(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_exact_mmxext(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_exact_3dnow(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); + +av_cold void ff_hpeldsp_vp3_init_x86(HpelDSPContext *c, int cpu_flags) +{ + if (EXTERNAL_AMD3DNOW(cpu_flags)) { + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_3dnow; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_3dnow; + } + + if (EXTERNAL_MMXEXT(cpu_flags)) { + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_mmxext; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_mmxext; + } +} diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index 436abc8..692162b 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -28,7 +28,7 @@ pb_7: times 8 db 7 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13 -SECTION_TEXT +SECTION .text ; void ff_add_hfyu_median_pred_mmxext(uint8_t *dst, const uint8_t *top, ; const uint8_t *diff, int w, @@ -146,8 +146,8 @@ cglobal add_hfyu_left_pred, 3,3,7, dst, src, w, left psllq m0, 56 ADD_HFYU_LEFT_LOOP 1, 1 -INIT_XMM sse4 -cglobal add_hfyu_left_pred, 3,3,7, dst, src, w, left +INIT_XMM ssse3 +cglobal add_hfyu_left_pred_unaligned, 3,3,7, dst, src, w, left mova m5, [pb_f] mova m6, [pb_zzzzzzzz77777777] mova m4, [pb_zzzz3333zzzzbbbb] diff --git a/libavcodec/x86/huffyuvdsp_init.c b/libavcodec/x86/huffyuvdsp_init.c index 75537d7..80e6cfb 100644 --- a/libavcodec/x86/huffyuvdsp_init.c +++ b/libavcodec/x86/huffyuvdsp_init.c @@ -31,8 +31,8 @@ void ff_add_hfyu_median_pred_mmxext(uint8_t *dst, const uint8_t *top, int ff_add_hfyu_left_pred_ssse3(uint8_t *dst, const uint8_t *src, int w, int left); -int ff_add_hfyu_left_pred_sse4(uint8_t *dst, const uint8_t *src, - int w, int left); +int ff_add_hfyu_left_pred_unaligned_ssse3(uint8_t *dst, const uint8_t *src, + int w, int left); #if HAVE_INLINE_ASM @@ -124,7 +124,9 @@ av_cold void ff_huffyuvdsp_init_x86(HuffYUVDSPContext *c) if (EXTERNAL_SSSE3(cpu_flags)) { c->add_hfyu_left_pred = ff_add_hfyu_left_pred_ssse3; - if (cpu_flags & AV_CPU_FLAG_SSE4) // not really SSE4, just slow on Conroe - c->add_hfyu_left_pred = ff_add_hfyu_left_pred_sse4; + } + + if (EXTERNAL_SSSE3_FAST(cpu_flags)) { + c->add_hfyu_left_pred = ff_add_hfyu_left_pred_unaligned_ssse3; } } diff --git a/libavcodec/x86/idct_mmx_xvid.c b/libavcodec/x86/idct_mmx_xvid.c deleted file mode 100644 index 920ea4c..0000000 --- a/libavcodec/x86/idct_mmx_xvid.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * XVID MPEG-4 VIDEO CODEC - * - MMX and XMM forward discrete cosine transform - - * - * Copyright(C) 2001 Peter Ross - * - * Originally provided by Intel at AP-922 - * http://developer.intel.com/vtune/cbts/strmsimd/922down.htm - * (See more app notes at http://developer.intel.com/vtune/cbts/strmsimd/appnotes.htm) - * but in a limited edition. - * New macro implements a column part for precise iDCT - * The routine precision now satisfies IEEE standard 1180-1990. - * - * Copyright(C) 2000-2001 Peter Gubanov - * Rounding trick Copyright(C) 2000 Michel Lespinasse - * - * http://www.elecard.com/peter/idct.html - * http://www.linuxvideo.org/mpeg2dec/ - * - * These examples contain code fragments for first stage iDCT 8x8 - * (for rows) and first stage DCT 8x8 (for columns) - * - * conversion to gcc syntax by Michael Niedermayer - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Libav; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "config.h" -#include "libavcodec/avcodec.h" -#include "libavutil/mem.h" -#include "idct_xvid.h" -#include "idctdsp.h" - -#if HAVE_MMX_INLINE - -//============================================================================= -// Macros and other preprocessor constants -//============================================================================= - -#define BITS_INV_ACC 5 // 4 or 5 for IEEE -#define SHIFT_INV_ROW (16 - BITS_INV_ACC) //11 -#define SHIFT_INV_COL (1 + BITS_INV_ACC) //6 -#define RND_INV_ROW (1024 * (6 - BITS_INV_ACC)) -#define RND_INV_COL (16 * (BITS_INV_ACC - 3)) -#define RND_INV_CORR (RND_INV_COL - 1) - -#define BITS_FRW_ACC 3 // 2 or 3 for accuracy -#define SHIFT_FRW_COL BITS_FRW_ACC -#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17) -#define RND_FRW_ROW (262144*(BITS_FRW_ACC - 1)) - - -//----------------------------------------------------------------------------- -// Various memory constants (trigonometric values or rounding values) -//----------------------------------------------------------------------------- - - -DECLARE_ALIGNED(8, static const int16_t, tg_1_16)[4*4] = { - 13036,13036,13036,13036, // tg * (2<<16) + 0.5 - 27146,27146,27146,27146, // tg * (2<<16) + 0.5 - -21746,-21746,-21746,-21746, // tg * (2<<16) + 0.5 - 23170,23170,23170,23170}; // cos * (2<<15) + 0.5 - -DECLARE_ALIGNED(8, static const int32_t, rounder_0)[2*8] = { - 65536,65536, - 3597,3597, - 2260,2260, - 1203,1203, - 0,0, - 120,120, - 512,512, - 512,512}; - -//----------------------------------------------------------------------------- -// -// The first stage iDCT 8x8 - inverse DCTs of rows -// -//----------------------------------------------------------------------------- -// The 8-point inverse DCT direct algorithm -//----------------------------------------------------------------------------- -// -// static const short w[32] = { -// FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16), -// FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16), -// FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16), -// FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16), -// FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16), -// FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16), -// FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16), -// FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) }; -// -// #define DCT_8_INV_ROW(x, y) -// { -// int a0, a1, a2, a3, b0, b1, b2, b3; -// -// a0 =x[0]*w[0]+x[2]*w[1]+x[4]*w[2]+x[6]*w[3]; -// a1 =x[0]*w[4]+x[2]*w[5]+x[4]*w[6]+x[6]*w[7]; -// a2 = x[0] * w[ 8] + x[2] * w[ 9] + x[4] * w[10] + x[6] * w[11]; -// a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15]; -// b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19]; -// b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23]; -// b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27]; -// b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31]; -// -// y[0] = SHIFT_ROUND ( a0 + b0 ); -// y[1] = SHIFT_ROUND ( a1 + b1 ); -// y[2] = SHIFT_ROUND ( a2 + b2 ); -// y[3] = SHIFT_ROUND ( a3 + b3 ); -// y[4] = SHIFT_ROUND ( a3 - b3 ); -// y[5] = SHIFT_ROUND ( a2 - b2 ); -// y[6] = SHIFT_ROUND ( a1 - b1 ); -// y[7] = SHIFT_ROUND ( a0 - b0 ); -// } -// -//----------------------------------------------------------------------------- -// -// In this implementation the outputs of the iDCT-1D are multiplied -// for rows 0,4 - by cos_4_16, -// for rows 1,7 - by cos_1_16, -// for rows 2,6 - by cos_2_16, -// for rows 3,5 - by cos_3_16 -// and are shifted to the left for better accuracy -// -// For the constants used, -// FIX(float_const) = (short) (float_const * (1<<15) + 0.5) -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Tables for mmx processors -//----------------------------------------------------------------------------- - -// Table for rows 0,4 - constants are multiplied by cos_4_16 -DECLARE_ALIGNED(8, static const int16_t, tab_i_04_mmx)[32*4] = { - 16384,16384,16384,-16384, // movq-> w06 w04 w02 w00 - 21407,8867,8867,-21407, // w07 w05 w03 w01 - 16384,-16384,16384,16384, // w14 w12 w10 w08 - -8867,21407,-21407,-8867, // w15 w13 w11 w09 - 22725,12873,19266,-22725, // w22 w20 w18 w16 - 19266,4520,-4520,-12873, // w23 w21 w19 w17 - 12873,4520,4520,19266, // w30 w28 w26 w24 - -22725,19266,-12873,-22725, // w31 w29 w27 w25 -// Table for rows 1,7 - constants are multiplied by cos_1_16 - 22725,22725,22725,-22725, // movq-> w06 w04 w02 w00 - 29692,12299,12299,-29692, // w07 w05 w03 w01 - 22725,-22725,22725,22725, // w14 w12 w10 w08 - -12299,29692,-29692,-12299, // w15 w13 w11 w09 - 31521,17855,26722,-31521, // w22 w20 w18 w16 - 26722,6270,-6270,-17855, // w23 w21 w19 w17 - 17855,6270,6270,26722, // w30 w28 w26 w24 - -31521,26722,-17855,-31521, // w31 w29 w27 w25 -// Table for rows 2,6 - constants are multiplied by cos_2_16 - 21407,21407,21407,-21407, // movq-> w06 w04 w02 w00 - 27969,11585,11585,-27969, // w07 w05 w03 w01 - 21407,-21407,21407,21407, // w14 w12 w10 w08 - -11585,27969,-27969,-11585, // w15 w13 w11 w09 - 29692,16819,25172,-29692, // w22 w20 w18 w16 - 25172,5906,-5906,-16819, // w23 w21 w19 w17 - 16819,5906,5906,25172, // w30 w28 w26 w24 - -29692,25172,-16819,-29692, // w31 w29 w27 w25 -// Table for rows 3,5 - constants are multiplied by cos_3_16 - 19266,19266,19266,-19266, // movq-> w06 w04 w02 w00 - 25172,10426,10426,-25172, // w07 w05 w03 w01 - 19266,-19266,19266,19266, // w14 w12 w10 w08 - -10426,25172,-25172,-10426, // w15 w13 w11 w09 - 26722,15137,22654,-26722, // w22 w20 w18 w16 - 22654,5315,-5315,-15137, // w23 w21 w19 w17 - 15137,5315,5315,22654, // w30 w28 w26 w24 - -26722,22654,-15137,-26722, // w31 w29 w27 w25 -}; -//----------------------------------------------------------------------------- -// Tables for xmm processors -//----------------------------------------------------------------------------- - -// %3 for rows 0,4 - constants are multiplied by cos_4_16 -DECLARE_ALIGNED(8, static const int16_t, tab_i_04_xmm)[32*4] = { - 16384,21407,16384,8867, // movq-> w05 w04 w01 w00 - 16384,8867,-16384,-21407, // w07 w06 w03 w02 - 16384,-8867,16384,-21407, // w13 w12 w09 w08 - -16384,21407,16384,-8867, // w15 w14 w11 w10 - 22725,19266,19266,-4520, // w21 w20 w17 w16 - 12873,4520,-22725,-12873, // w23 w22 w19 w18 - 12873,-22725,4520,-12873, // w29 w28 w25 w24 - 4520,19266,19266,-22725, // w31 w30 w27 w26 -// %3 for rows 1,7 - constants are multiplied by cos_1_16 - 22725,29692,22725,12299, // movq-> w05 w04 w01 w00 - 22725,12299,-22725,-29692, // w07 w06 w03 w02 - 22725,-12299,22725,-29692, // w13 w12 w09 w08 - -22725,29692,22725,-12299, // w15 w14 w11 w10 - 31521,26722,26722,-6270, // w21 w20 w17 w16 - 17855,6270,-31521,-17855, // w23 w22 w19 w18 - 17855,-31521,6270,-17855, // w29 w28 w25 w24 - 6270,26722,26722,-31521, // w31 w30 w27 w26 -// %3 for rows 2,6 - constants are multiplied by cos_2_16 - 21407,27969,21407,11585, // movq-> w05 w04 w01 w00 - 21407,11585,-21407,-27969, // w07 w06 w03 w02 - 21407,-11585,21407,-27969, // w13 w12 w09 w08 - -21407,27969,21407,-11585, // w15 w14 w11 w10 - 29692,25172,25172,-5906, // w21 w20 w17 w16 - 16819,5906,-29692,-16819, // w23 w22 w19 w18 - 16819,-29692,5906,-16819, // w29 w28 w25 w24 - 5906,25172,25172,-29692, // w31 w30 w27 w26 -// %3 for rows 3,5 - constants are multiplied by cos_3_16 - 19266,25172,19266,10426, // movq-> w05 w04 w01 w00 - 19266,10426,-19266,-25172, // w07 w06 w03 w02 - 19266,-10426,19266,-25172, // w13 w12 w09 w08 - -19266,25172,19266,-10426, // w15 w14 w11 w10 - 26722,22654,22654,-5315, // w21 w20 w17 w16 - 15137,5315,-26722,-15137, // w23 w22 w19 w18 - 15137,-26722,5315,-15137, // w29 w28 w25 w24 - 5315,22654,22654,-26722, // w31 w30 w27 w26 -}; -//============================================================================= -// Helper macros for the code -//============================================================================= - -//----------------------------------------------------------------------------- -// DCT_8_INV_ROW_MMX( INP, OUT, TABLE, ROUNDER -//----------------------------------------------------------------------------- - -#define DCT_8_INV_ROW_MMX(A1,A2,A3,A4)\ - "movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\ - "movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\ - "movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\ - "movq " #A3 ",%%mm3 \n\t"/* 3 ; w06 w04 w02 w00*/\ - "punpcklwd %%mm1,%%mm0 \n\t"/* x5 x1 x4 x0*/\ - "movq %%mm0,%%mm5 \n\t"/* 5 ; x5 x1 x4 x0*/\ - "punpckldq %%mm0,%%mm0 \n\t"/* x4 x0 x4 x0*/\ - "movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w05 w03 w01*/\ - "punpckhwd %%mm1,%%mm2 \n\t"/* 1 ; x7 x3 x6 x2*/\ - "pmaddwd %%mm0,%%mm3 \n\t"/* x4*w06+x0*w04 x4*w02+x0*w00*/\ - "movq %%mm2,%%mm6 \n\t"/* 6 ; x7 x3 x6 x2*/\ - "movq 32+" #A3 ",%%mm1 \n\t"/* 1 ; w22 w20 w18 w16*/\ - "punpckldq %%mm2,%%mm2 \n\t"/* x6 x2 x6 x2*/\ - "pmaddwd %%mm2,%%mm4 \n\t"/* x6*w07+x2*w05 x6*w03+x2*w01*/\ - "punpckhdq %%mm5,%%mm5 \n\t"/* x5 x1 x5 x1*/\ - "pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x4*w14+x0*w12 x4*w10+x0*w08*/\ - "punpckhdq %%mm6,%%mm6 \n\t"/* x7 x3 x7 x3*/\ - "movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w21 w19 w17*/\ - "pmaddwd %%mm5,%%mm1 \n\t"/* x5*w22+x1*w20 x5*w18+x1*w16*/\ - "paddd " #A4 ",%%mm3 \n\t"/* +%4*/\ - "pmaddwd %%mm6,%%mm7 \n\t"/* x7*w23+x3*w21 x7*w19+x3*w17*/\ - "pmaddwd 24+" #A3 ",%%mm2 \n\t"/* x6*w15+x2*w13 x6*w11+x2*w09*/\ - "paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\ - "pmaddwd 48+" #A3 ",%%mm5 \n\t"/* x5*w30+x1*w28 x5*w26+x1*w24*/\ - "movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\ - "pmaddwd 56+" #A3 ",%%mm6 \n\t"/* x7*w31+x3*w29 x7*w27+x3*w25*/\ - "paddd %%mm7,%%mm1 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\ - "paddd " #A4 ",%%mm0 \n\t"/* +%4*/\ - "psubd %%mm1,%%mm3 \n\t"/* a1-b1 a0-b0*/\ - "psrad $11,%%mm3 \n\t"/* y6=a1-b1 y7=a0-b0*/\ - "paddd %%mm4,%%mm1 \n\t"/* 4 ; a1+b1 a0+b0*/\ - "paddd %%mm2,%%mm0 \n\t"/* 2 ; a3=sum(even3) a2=sum(even2)*/\ - "psrad $11,%%mm1 \n\t"/* y1=a1+b1 y0=a0+b0*/\ - "paddd %%mm6,%%mm5 \n\t"/* 6 ; b3=sum(odd3) b2=sum(odd2)*/\ - "movq %%mm0,%%mm4 \n\t"/* 4 ; a3 a2*/\ - "paddd %%mm5,%%mm0 \n\t"/* a3+b3 a2+b2*/\ - "psubd %%mm5,%%mm4 \n\t"/* 5 ; a3-b3 a2-b2*/\ - "psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\ - "psrad $11,%%mm4 \n\t"/* y4=a3-b3 y5=a2-b2*/\ - "packssdw %%mm0,%%mm1 \n\t"/* 0 ; y3 y2 y1 y0*/\ - "packssdw %%mm3,%%mm4 \n\t"/* 3 ; y6 y7 y4 y5*/\ - "movq %%mm4,%%mm7 \n\t"/* 7 ; y6 y7 y4 y5*/\ - "psrld $16,%%mm4 \n\t"/* 0 y6 0 y4*/\ - "pslld $16,%%mm7 \n\t"/* y7 0 y5 0*/\ - "movq %%mm1," #A2 " \n\t"/* 1 ; save y3 y2 y1 y0*/\ - "por %%mm4,%%mm7 \n\t"/* 4 ; y7 y6 y5 y4*/\ - "movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\ - - -//----------------------------------------------------------------------------- -// DCT_8_INV_ROW_XMM( INP, OUT, TABLE, ROUNDER -//----------------------------------------------------------------------------- - -#define DCT_8_INV_ROW_XMM(A1,A2,A3,A4)\ - "movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\ - "movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\ - "movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\ - "movq " #A3 ",%%mm3 \n\t"/* 3 ; w05 w04 w01 w00*/\ - "pshufw $0x88,%%mm0,%%mm0 \n\t"/* x2 x0 x2 x0*/\ - "movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w06 w03 w02*/\ - "movq %%mm1,%%mm5 \n\t"/* 5 ; x7 x6 x5 x4*/\ - "pmaddwd %%mm0,%%mm3 \n\t"/* x2*w05+x0*w04 x2*w01+x0*w00*/\ - "movq 32+" #A3 ",%%mm6 \n\t"/* 6 ; w21 w20 w17 w16*/\ - "pshufw $0x88,%%mm1,%%mm1 \n\t"/* x6 x4 x6 x4*/\ - "pmaddwd %%mm1,%%mm4 \n\t"/* x6*w07+x4*w06 x6*w03+x4*w02*/\ - "movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w22 w19 w18*/\ - "pshufw $0xdd,%%mm2,%%mm2 \n\t"/* x3 x1 x3 x1*/\ - "pmaddwd %%mm2,%%mm6 \n\t"/* x3*w21+x1*w20 x3*w17+x1*w16*/\ - "pshufw $0xdd,%%mm5,%%mm5 \n\t"/* x7 x5 x7 x5*/\ - "pmaddwd %%mm5,%%mm7 \n\t"/* x7*w23+x5*w22 x7*w19+x5*w18*/\ - "paddd " #A4 ",%%mm3 \n\t"/* +%4*/\ - "pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x2*w13+x0*w12 x2*w09+x0*w08*/\ - "paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\ - "pmaddwd 24+" #A3 ",%%mm1 \n\t"/* x6*w15+x4*w14 x6*w11+x4*w10*/\ - "movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\ - "pmaddwd 48+" #A3 ",%%mm2 \n\t"/* x3*w29+x1*w28 x3*w25+x1*w24*/\ - "paddd %%mm7,%%mm6 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\ - "pmaddwd 56+" #A3 ",%%mm5 \n\t"/* x7*w31+x5*w30 x7*w27+x5*w26*/\ - "paddd %%mm6,%%mm3 \n\t"/* a1+b1 a0+b0*/\ - "paddd " #A4 ",%%mm0 \n\t"/* +%4*/\ - "psrad $11,%%mm3 \n\t"/* y1=a1+b1 y0=a0+b0*/\ - "paddd %%mm1,%%mm0 \n\t"/* 1 ; a3=sum(even3) a2=sum(even2)*/\ - "psubd %%mm6,%%mm4 \n\t"/* 6 ; a1-b1 a0-b0*/\ - "movq %%mm0,%%mm7 \n\t"/* 7 ; a3 a2*/\ - "paddd %%mm5,%%mm2 \n\t"/* 5 ; b3=sum(odd3) b2=sum(odd2)*/\ - "paddd %%mm2,%%mm0 \n\t"/* a3+b3 a2+b2*/\ - "psrad $11,%%mm4 \n\t"/* y6=a1-b1 y7=a0-b0*/\ - "psubd %%mm2,%%mm7 \n\t"/* 2 ; a3-b3 a2-b2*/\ - "psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\ - "psrad $11,%%mm7 \n\t"/* y4=a3-b3 y5=a2-b2*/\ - "packssdw %%mm0,%%mm3 \n\t"/* 0 ; y3 y2 y1 y0*/\ - "packssdw %%mm4,%%mm7 \n\t"/* 4 ; y6 y7 y4 y5*/\ - "movq %%mm3, " #A2 " \n\t"/* 3 ; save y3 y2 y1 y0*/\ - "pshufw $0xb1,%%mm7,%%mm7 \n\t"/* y7 y6 y5 y4*/\ - "movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\ - - -//----------------------------------------------------------------------------- -// -// The first stage DCT 8x8 - forward DCTs of columns -// -// The %2puts are multiplied -// for rows 0,4 - on cos_4_16, -// for rows 1,7 - on cos_1_16, -// for rows 2,6 - on cos_2_16, -// for rows 3,5 - on cos_3_16 -// and are shifted to the left for rise of accuracy -// -//----------------------------------------------------------------------------- -// -// The 8-point scaled forward DCT algorithm (26a8m) -// -//----------------------------------------------------------------------------- -// -// #define DCT_8_FRW_COL(x, y) -//{ -// short t0, t1, t2, t3, t4, t5, t6, t7; -// short tp03, tm03, tp12, tm12, tp65, tm65; -// short tp465, tm465, tp765, tm765; -// -// t0 = LEFT_SHIFT ( x[0] + x[7] ); -// t1 = LEFT_SHIFT ( x[1] + x[6] ); -// t2 = LEFT_SHIFT ( x[2] + x[5] ); -// t3 = LEFT_SHIFT ( x[3] + x[4] ); -// t4 = LEFT_SHIFT ( x[3] - x[4] ); -// t5 = LEFT_SHIFT ( x[2] - x[5] ); -// t6 = LEFT_SHIFT ( x[1] - x[6] ); -// t7 = LEFT_SHIFT ( x[0] - x[7] ); -// -// tp03 = t0 + t3; -// tm03 = t0 - t3; -// tp12 = t1 + t2; -// tm12 = t1 - t2; -// -// y[0] = tp03 + tp12; -// y[4] = tp03 - tp12; -// -// y[2] = tm03 + tm12 * tg_2_16; -// y[6] = tm03 * tg_2_16 - tm12; -// -// tp65 =(t6 +t5 )*cos_4_16; -// tm65 =(t6 -t5 )*cos_4_16; -// -// tp765 = t7 + tp65; -// tm765 = t7 - tp65; -// tp465 = t4 + tm65; -// tm465 = t4 - tm65; -// -// y[1] = tp765 + tp465 * tg_1_16; -// y[7] = tp765 * tg_1_16 - tp465; -// y[5] = tm765 * tg_3_16 + tm465; -// y[3] = tm765 - tm465 * tg_3_16; -//} -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// DCT_8_INV_COL_4 INP,OUT -//----------------------------------------------------------------------------- - -#define DCT_8_INV_COL(A1,A2)\ - "movq 2*8(%3),%%mm0\n\t"\ - "movq 16*3+" #A1 ",%%mm3\n\t"\ - "movq %%mm0,%%mm1 \n\t"/* tg_3_16*/\ - "movq 16*5+" #A1 ",%%mm5\n\t"\ - "pmulhw %%mm3,%%mm0 \n\t"/* x3*(tg_3_16-1)*/\ - "movq (%3),%%mm4\n\t"\ - "pmulhw %%mm5,%%mm1 \n\t"/* x5*(tg_3_16-1)*/\ - "movq 16*7+" #A1 ",%%mm7\n\t"\ - "movq %%mm4,%%mm2 \n\t"/* tg_1_16*/\ - "movq 16*1+" #A1 ",%%mm6\n\t"\ - "pmulhw %%mm7,%%mm4 \n\t"/* x7*tg_1_16*/\ - "paddsw %%mm3,%%mm0 \n\t"/* x3*tg_3_16*/\ - "pmulhw %%mm6,%%mm2 \n\t"/* x1*tg_1_16*/\ - "paddsw %%mm3,%%mm1 \n\t"/* x3+x5*(tg_3_16-1)*/\ - "psubsw %%mm5,%%mm0 \n\t"/* x3*tg_3_16-x5 = tm35*/\ - "movq 3*8(%3),%%mm3\n\t"\ - "paddsw %%mm5,%%mm1 \n\t"/* x3+x5*tg_3_16 = tp35*/\ - "paddsw %%mm6,%%mm4 \n\t"/* x1+tg_1_16*x7 = tp17*/\ - "psubsw %%mm7,%%mm2 \n\t"/* x1*tg_1_16-x7 = tm17*/\ - "movq %%mm4,%%mm5 \n\t"/* tp17*/\ - "movq %%mm2,%%mm6 \n\t"/* tm17*/\ - "paddsw %%mm1,%%mm5 \n\t"/* tp17+tp35 = b0*/\ - "psubsw %%mm0,%%mm6 \n\t"/* tm17-tm35 = b3*/\ - "psubsw %%mm1,%%mm4 \n\t"/* tp17-tp35 = t1*/\ - "paddsw %%mm0,%%mm2 \n\t"/* tm17+tm35 = t2*/\ - "movq 1*8(%3),%%mm7\n\t"\ - "movq %%mm4,%%mm1 \n\t"/* t1*/\ - "movq %%mm5,3*16 +" #A2 "\n\t"/* save b0*/\ - "paddsw %%mm2,%%mm1 \n\t"/* t1+t2*/\ - "movq %%mm6,5*16 +" #A2 "\n\t"/* save b3*/\ - "psubsw %%mm2,%%mm4 \n\t"/* t1-t2*/\ - "movq 2*16+" #A1 ",%%mm5\n\t"\ - "movq %%mm7,%%mm0 \n\t"/* tg_2_16*/\ - "movq 6*16+" #A1 ",%%mm6\n\t"\ - "pmulhw %%mm5,%%mm0 \n\t"/* x2*tg_2_16*/\ - "pmulhw %%mm6,%%mm7 \n\t"/* x6*tg_2_16*/\ - "pmulhw %%mm3,%%mm1 \n\t"/* ocos_4_16*(t1+t2) = b1/2*/\ - "movq 0*16+" #A1 ",%%mm2\n\t"\ - "pmulhw %%mm3,%%mm4 \n\t"/* ocos_4_16*(t1-t2) = b2/2*/\ - "psubsw %%mm6,%%mm0 \n\t"/* t2*tg_2_16-x6 = tm26*/\ - "movq %%mm2,%%mm3 \n\t"/* x0*/\ - "movq 4*16+" #A1 ",%%mm6\n\t"\ - "paddsw %%mm5,%%mm7 \n\t"/* x2+x6*tg_2_16 = tp26*/\ - "paddsw %%mm6,%%mm2 \n\t"/* x0+x4 = tp04*/\ - "psubsw %%mm6,%%mm3 \n\t"/* x0-x4 = tm04*/\ - "movq %%mm2,%%mm5 \n\t"/* tp04*/\ - "movq %%mm3,%%mm6 \n\t"/* tm04*/\ - "psubsw %%mm7,%%mm2 \n\t"/* tp04-tp26 = a3*/\ - "paddsw %%mm0,%%mm3 \n\t"/* tm04+tm26 = a1*/\ - "paddsw %%mm1,%%mm1 \n\t"/* b1*/\ - "paddsw %%mm4,%%mm4 \n\t"/* b2*/\ - "paddsw %%mm7,%%mm5 \n\t"/* tp04+tp26 = a0*/\ - "psubsw %%mm0,%%mm6 \n\t"/* tm04-tm26 = a2*/\ - "movq %%mm3,%%mm7 \n\t"/* a1*/\ - "movq %%mm6,%%mm0 \n\t"/* a2*/\ - "paddsw %%mm1,%%mm3 \n\t"/* a1+b1*/\ - "paddsw %%mm4,%%mm6 \n\t"/* a2+b2*/\ - "psraw $6,%%mm3 \n\t"/* dst1*/\ - "psubsw %%mm1,%%mm7 \n\t"/* a1-b1*/\ - "psraw $6,%%mm6 \n\t"/* dst2*/\ - "psubsw %%mm4,%%mm0 \n\t"/* a2-b2*/\ - "movq 3*16+" #A2 ",%%mm1 \n\t"/* load b0*/\ - "psraw $6,%%mm7 \n\t"/* dst6*/\ - "movq %%mm5,%%mm4 \n\t"/* a0*/\ - "psraw $6,%%mm0 \n\t"/* dst5*/\ - "movq %%mm3,1*16+" #A2 "\n\t"\ - "paddsw %%mm1,%%mm5 \n\t"/* a0+b0*/\ - "movq %%mm6,2*16+" #A2 "\n\t"\ - "psubsw %%mm1,%%mm4 \n\t"/* a0-b0*/\ - "movq 5*16+" #A2 ",%%mm3 \n\t"/* load b3*/\ - "psraw $6,%%mm5 \n\t"/* dst0*/\ - "movq %%mm2,%%mm6 \n\t"/* a3*/\ - "psraw $6,%%mm4 \n\t"/* dst7*/\ - "movq %%mm0,5*16+" #A2 "\n\t"\ - "paddsw %%mm3,%%mm2 \n\t"/* a3+b3*/\ - "movq %%mm7,6*16+" #A2 "\n\t"\ - "psubsw %%mm3,%%mm6 \n\t"/* a3-b3*/\ - "movq %%mm5,0*16+" #A2 "\n\t"\ - "psraw $6,%%mm2 \n\t"/* dst3*/\ - "movq %%mm4,7*16+" #A2 "\n\t"\ - "psraw $6,%%mm6 \n\t"/* dst4*/\ - "movq %%mm2,3*16+" #A2 "\n\t"\ - "movq %%mm6,4*16+" #A2 "\n\t" - -//============================================================================= -// Code -//============================================================================= - -//----------------------------------------------------------------------------- -// void idct_mmx(uint16_t block[64]); -//----------------------------------------------------------------------------- - - -void ff_idct_xvid_mmx(short *block){ -__asm__ volatile( - //# Process each row - DCT_8_INV_ROW_MMX(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1)) - DCT_8_INV_ROW_MMX(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1)) - DCT_8_INV_ROW_MMX(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1)) - DCT_8_INV_ROW_MMX(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1)) - DCT_8_INV_ROW_MMX(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1)) - DCT_8_INV_ROW_MMX(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1)) - DCT_8_INV_ROW_MMX(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1)) - DCT_8_INV_ROW_MMX(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1)) - - //# Process the columns (4 at a time) - DCT_8_INV_COL(0(%0), 0(%0)) - DCT_8_INV_COL(8(%0), 8(%0)) - :: "r"(block), "r"(rounder_0), "r"(tab_i_04_mmx), "r"(tg_1_16)); -} - -void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_idct_xvid_mmx(block); - ff_put_pixels_clamped_mmx(block, dest, line_size); -} - -void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_idct_xvid_mmx(block); - ff_add_pixels_clamped_mmx(block, dest, line_size); -} - -#endif /* HAVE_MMX_INLINE */ - -#if HAVE_MMXEXT_INLINE - -//----------------------------------------------------------------------------- -// void idct_xmm(uint16_t block[64]); -//----------------------------------------------------------------------------- - - -void ff_idct_xvid_mmxext(short *block) -{ -__asm__ volatile( - //# Process each row - DCT_8_INV_ROW_XMM(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1)) - DCT_8_INV_ROW_XMM(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1)) - DCT_8_INV_ROW_XMM(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1)) - DCT_8_INV_ROW_XMM(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1)) - DCT_8_INV_ROW_XMM(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1)) - DCT_8_INV_ROW_XMM(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1)) - DCT_8_INV_ROW_XMM(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1)) - DCT_8_INV_ROW_XMM(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1)) - - //# Process the columns (4 at a time) - DCT_8_INV_COL(0(%0), 0(%0)) - DCT_8_INV_COL(8(%0), 8(%0)) - :: "r"(block), "r"(rounder_0), "r"(tab_i_04_xmm), "r"(tg_1_16)); -} - -void ff_idct_xvid_mmxext_put(uint8_t *dest, int line_size, int16_t *block) -{ - ff_idct_xvid_mmxext(block); - ff_put_pixels_clamped_mmx(block, dest, line_size); -} - -void ff_idct_xvid_mmxext_add(uint8_t *dest, int line_size, int16_t *block) -{ - ff_idct_xvid_mmxext(block); - ff_add_pixels_clamped_mmx(block, dest, line_size); -} - -#endif /* HAVE_MMXEXT_INLINE */ diff --git a/libavcodec/x86/imdct36.asm b/libavcodec/x86/imdct36.asm index 633fcd9..f85e2e4 100644 --- a/libavcodec/x86/imdct36.asm +++ b/libavcodec/x86/imdct36.asm @@ -72,7 +72,7 @@ costabs: times 4 dd 0.98480773 times 4 dd 5.73685646 %define SBLIMIT 32 -SECTION_TEXT +SECTION .text %macro PSHUFD 3 %if cpuflag(sse2) && notcpuflag(avx) diff --git a/libavcodec/x86/inline_asm.h b/libavcodec/x86/inline_asm.h index e4affab..fc554bf 100644 --- a/libavcodec/x86/inline_asm.h +++ b/libavcodec/x86/inline_asm.h @@ -50,7 +50,7 @@ #endif // using regr as temporary and for the output result -// first argument is unmodifed and second is trashed +// first argument is unmodified and second is trashed // regfe is supposed to contain 0xfefefefefefefefe #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \ "movq "#rega", "#regr" \n\t" \ diff --git a/libavcodec/x86/lpc.c b/libavcodec/x86/lpc.c index ea5d2ea..e8cce42 100644 --- a/libavcodec/x86/lpc.c +++ b/libavcodec/x86/lpc.c @@ -152,7 +152,7 @@ av_cold void ff_lpc_init_x86(LPCContext *c) #if HAVE_SSE2_INLINE int cpu_flags = av_get_cpu_flags(); - if (INLINE_SSE2(cpu_flags) && (cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { + if (INLINE_SSE2_SLOW(cpu_flags)) { c->lpc_apply_welch_window = lpc_apply_welch_window_sse2; c->lpc_compute_autocorr = lpc_compute_autocorr_sse2; } diff --git a/libavcodec/x86/mdct.h b/libavcodec/x86/mdct.h new file mode 100644 index 0000000..cc107cb --- /dev/null +++ b/libavcodec/x86/mdct.h @@ -0,0 +1,32 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_MDCT_H +#define AVCODEC_X86_MDCT_H + +#include "libavcodec/fft.h" + +void ff_imdct_calc_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_calc_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_calc_sse(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_sse(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_avx(FFTContext *s, FFTSample *output, const FFTSample *input); + +#endif /* AVCODEC_X86_MDCT_H */ diff --git a/libavcodec/x86/mdct_init.c b/libavcodec/x86/mdct_init.c new file mode 100644 index 0000000..db642d8 --- /dev/null +++ b/libavcodec/x86/mdct_init.c @@ -0,0 +1,51 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" + +#include "mdct.h" + +av_cold void ff_mdct_init_x86(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + +#if ARCH_X86_32 + if (EXTERNAL_AMD3DNOW(cpu_flags)) { + s->imdct_calc = ff_imdct_calc_3dnow; + s->imdct_half = ff_imdct_half_3dnow; + } + + if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { + s->imdct_calc = ff_imdct_calc_3dnowext; + s->imdct_half = ff_imdct_half_3dnowext; + } +#endif /* ARCH_X86_32 */ + + if (EXTERNAL_SSE(cpu_flags)) { + s->imdct_calc = ff_imdct_calc_sse; + s->imdct_half = ff_imdct_half_sse; + } + + if (EXTERNAL_AVX_FAST(cpu_flags) && s->nbits >= 5) { + s->imdct_half = ff_imdct_half_avx; + } +} diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c index e93b67b..ee5f559 100644 --- a/libavcodec/x86/me_cmp_init.c +++ b/libavcodec/x86/me_cmp_init.c @@ -32,7 +32,7 @@ #if HAVE_INLINE_ASM static int sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; @@ -74,8 +74,8 @@ static int sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, "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 */ + "lea (%0, %3, 2), %0 \n" /* pix1 += 2 * stride */ + "lea (%1, %3, 2), %1 \n" /* pix2 += 2 * stride */ "paddd %%mm2, %%mm1 \n" "paddd %%mm4, %%mm3 \n" @@ -90,14 +90,14 @@ static int sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, "paddd %%mm7, %%mm1 \n" "movd %%mm1, %2 \n" : "+r" (pix1), "+r" (pix2), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp; } static int sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; @@ -154,13 +154,13 @@ static int sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, "paddd %%mm7, %%mm1\n" "movd %%mm1, %2\n" : "+r" (pix1), "+r" (pix2), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp; } -static int hf_noise8_mmx(uint8_t *pix1, int line_size, int h) +static int hf_noise8_mmx(uint8_t *pix1, ptrdiff_t stride, int h) { int tmp; @@ -282,13 +282,13 @@ static int hf_noise8_mmx(uint8_t *pix1, int line_size, int h) "paddd %%mm6, %%mm0\n" "movd %%mm0, %1\n" : "+r" (pix1), "=r" (tmp) - : "r" ((x86_reg) line_size), "g" (h - 2) + : "r" (stride), "g" (h - 2) : "%ecx"); return tmp; } -static int hf_noise16_mmx(uint8_t *pix1, int line_size, int h) +static int hf_noise16_mmx(uint8_t *pix1, ptrdiff_t stride, int h) { int tmp; uint8_t *pix = pix1; @@ -399,23 +399,23 @@ static int hf_noise16_mmx(uint8_t *pix1, int line_size, int h) "paddd %%mm6, %%mm0\n" "movd %%mm0, %1\n" : "+r" (pix1), "=r" (tmp) - : "r" ((x86_reg) line_size), "g" (h - 2) + : "r" (stride), "g" (h - 2) : "%ecx"); - return tmp + hf_noise8_mmx(pix + 8, line_size, h); + return tmp + hf_noise8_mmx(pix + 8, stride, h); } static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int score1, score2; if (c) - score1 = c->mecc.sse[0](c, pix1, pix2, line_size, h); + score1 = c->mecc.sse[0](c, pix1, pix2, stride, 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); + score1 = sse16_mmx(c, pix1, pix2, stride, h); + score2 = hf_noise16_mmx(pix1, stride, h) - + hf_noise16_mmx(pix2, stride, h); if (c) return score1 + FFABS(score2) * c->avctx->nsse_weight; @@ -424,11 +424,11 @@ static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, } static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { - 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); + int score1 = sse8_mmx(c, pix1, pix2, stride, h); + int score2 = hf_noise8_mmx(pix1, stride, h) - + hf_noise8_mmx(pix2, stride, h); if (c) return score1 + FFABS(score2) * c->avctx->nsse_weight; @@ -437,12 +437,12 @@ static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, } static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; assert((((int) pix) & 7) == 0); - assert((line_size & 7) == 0); + assert((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ "movq (%0), %%mm2\n" \ @@ -493,7 +493,7 @@ static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, "paddw %%mm6, %%mm0\n" "movd %%mm0, %1\n" : "+r" (pix), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp & 0xFFFF; @@ -501,12 +501,12 @@ static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, #undef SUM static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; assert((((int) pix) & 7) == 0); - assert((line_size & 7) == 0); + assert((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ "movq (%0), " #out0 "\n" \ @@ -536,7 +536,7 @@ static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, "movd %%mm6, %1\n" : "+r" (pix), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp; @@ -544,13 +544,13 @@ static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, #undef SUM static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; assert((((int) pix1) & 7) == 0); assert((((int) pix2) & 7) == 0); - assert((line_size & 7) == 0); + assert((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ "movq (%0), %%mm2\n" \ @@ -617,7 +617,7 @@ static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, "paddw %%mm6, %%mm0\n" "movd %%mm0, %2\n" : "+r" (pix1), "+r" (pix2), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp & 0x7FFF; @@ -625,13 +625,13 @@ static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, #undef SUM static int vsad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h) + ptrdiff_t stride, int h) { int tmp; assert((((int) pix1) & 7) == 0); assert((((int) pix2) & 7) == 0); - assert((line_size & 7) == 0); + assert((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ "movq (%0), " #out0 "\n" \ @@ -677,7 +677,7 @@ static int vsad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, "movd %%mm6, %2\n" : "+r" (pix1), "+r" (pix2), "=r" (tmp) - : "r" ((x86_reg) line_size), "m" (h) + : "r" (stride), "m" (h) : "%ecx"); return tmp; @@ -805,21 +805,22 @@ DECLARE_ASM_CONST(8, uint64_t, round_tab)[3] = { DECLARE_ASM_CONST(8, uint64_t, bone) = 0x0101010101010101LL; -static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h) { x86_reg len = -(stride * h); __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" - "movq (%1, %%"REG_a"), %%mm0 \n\t" - "movq (%2, %%"REG_a"), %%mm2 \n\t" - "movq (%2, %%"REG_a"), %%mm4 \n\t" - "add %3, %%"REG_a" \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm2 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm4 \n\t" + "add %3, %%"FF_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" + "movq (%1, %%"FF_REG_a"), %%mm1 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm3 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm5 \n\t" "psubusb %%mm1, %%mm3 \n\t" "psubusb %%mm5, %%mm1 \n\t" "por %%mm2, %%mm0 \n\t" @@ -834,14 +835,14 @@ static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "paddw %%mm3, %%mm2 \n\t" "paddw %%mm2, %%mm0 \n\t" "paddw %%mm0, %%mm6 \n\t" - "add %3, %%"REG_a" \n\t" + "add %3, %%"FF_REG_a" \n\t" " js 1b \n\t" : "+a" (len) - : "r" (blk1 - len), "r" (blk2 - len), "r" ((x86_reg) stride)); + : "r" (blk1 - len), "r" (blk2 - len), "r" (stride)); } static inline void sad8_1_mmxext(uint8_t *blk1, uint8_t *blk2, - int stride, int h) + ptrdiff_t stride, int h) { __asm__ volatile ( ".p2align 4 \n\t" @@ -857,11 +858,11 @@ static inline void sad8_1_mmxext(uint8_t *blk1, uint8_t *blk2, "sub $2, %0 \n\t" " jg 1b \n\t" : "+r" (h), "+r" (blk1), "+r" (blk2) - : "r" ((x86_reg) stride)); + : "r" (stride)); } static int sad16_sse2(MpegEncContext *v, uint8_t *blk2, uint8_t *blk1, - int stride, int h) + ptrdiff_t stride, int h) { int ret; __asm__ volatile ( @@ -882,12 +883,12 @@ static int sad16_sse2(MpegEncContext *v, uint8_t *blk2, uint8_t *blk1, "paddw %%xmm0, %%xmm2 \n\t" "movd %%xmm2, %3 \n\t" : "+r" (h), "+r" (blk1), "+r" (blk2), "=r" (ret) - : "r" ((x86_reg) stride)); + : "r" (stride)); return ret; } static inline void sad8_x2a_mmxext(uint8_t *blk1, uint8_t *blk2, - int stride, int h) + ptrdiff_t stride, int h) { __asm__ volatile ( ".p2align 4 \n\t" @@ -905,11 +906,11 @@ static inline void sad8_x2a_mmxext(uint8_t *blk1, uint8_t *blk2, "sub $2, %0 \n\t" " jg 1b \n\t" : "+r" (h), "+r" (blk1), "+r" (blk2) - : "r" ((x86_reg) stride)); + : "r" (stride)); } static inline void sad8_y2a_mmxext(uint8_t *blk1, uint8_t *blk2, - int stride, int h) + ptrdiff_t stride, int h) { __asm__ volatile ( "movq (%1), %%mm0 \n\t" @@ -930,11 +931,11 @@ static inline void sad8_y2a_mmxext(uint8_t *blk1, uint8_t *blk2, "sub $2, %0 \n\t" " jg 1b \n\t" : "+r" (h), "+r" (blk1), "+r" (blk2) - : "r" ((x86_reg) stride)); + : "r" (stride)); } static inline void sad8_4_mmxext(uint8_t *blk1, uint8_t *blk2, - int stride, int h) + ptrdiff_t stride, int h) { __asm__ volatile ( "movq "MANGLE(bone)", %%mm5 \n\t" @@ -960,28 +961,28 @@ static inline void sad8_4_mmxext(uint8_t *blk1, uint8_t *blk2, "sub $2, %0 \n\t" " jg 1b \n\t" : "+r" (h), "+r" (blk1), "+r" (blk2) - : "r" ((x86_reg) stride)); + : "r" (stride)); } static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, - int stride, int h) + ptrdiff_t stride, int h) { x86_reg len = -(stride * h); __asm__ volatile ( ".p2align 4 \n\t" "1: \n\t" - "movq (%1, %%"REG_a"), %%mm0 \n\t" - "movq (%2, %%"REG_a"), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm2 \n\t" - "movq (%2, %%"REG_a"), %%mm3 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm1 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm2 \n\t" + "movq (%2, %%"FF_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" + "movq (%3, %%"FF_REG_a"), %%mm4 \n\t" + "movq (%3, %%"FF_REG_a"), %%mm2 \n\t" "paddw %%mm5, %%mm1 \n\t" "paddw %%mm5, %%mm3 \n\t" "psrlw $1, %%mm1 \n\t" @@ -995,19 +996,20 @@ static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, "punpckhbw %%mm7, %%mm1 \n\t" "paddw %%mm1, %%mm0 \n\t" "paddw %%mm0, %%mm6 \n\t" - "add %4, %%"REG_a" \n\t" + "add %4, %%"FF_REG_a" \n\t" " js 1b \n\t" : "+a" (len) : "r" (blk1a - len), "r" (blk1b - len), "r" (blk2 - len), - "r" ((x86_reg) stride)); + "r" (stride)); } -static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h) { x86_reg len = -(stride * h); __asm__ volatile ( - "movq (%1, %%"REG_a"), %%mm0 \n\t" - "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0\n\t" + "movq 1(%1, %%"FF_REG_a"), %%mm2\n\t" "movq %%mm0, %%mm1 \n\t" "movq %%mm2, %%mm3 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" @@ -1018,8 +1020,8 @@ static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "paddw %%mm3, %%mm1 \n\t" ".p2align 4 \n\t" "1: \n\t" - "movq (%2, %%"REG_a"), %%mm2 \n\t" - "movq 1(%2, %%"REG_a"), %%mm4 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm2\n\t" + "movq 1(%2, %%"FF_REG_a"), %%mm4\n\t" "movq %%mm2, %%mm3 \n\t" "movq %%mm4, %%mm5 \n\t" "punpcklbw %%mm7, %%mm2 \n\t" @@ -1033,8 +1035,8 @@ static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "paddw %%mm3, %%mm1 \n\t" "paddw %%mm5, %%mm0 \n\t" "paddw %%mm5, %%mm1 \n\t" - "movq (%3, %%"REG_a"), %%mm4 \n\t" - "movq (%3, %%"REG_a"), %%mm5 \n\t" + "movq (%3, %%"FF_REG_a"), %%mm4 \n\t" + "movq (%3, %%"FF_REG_a"), %%mm5 \n\t" "psrlw $2, %%mm0 \n\t" "psrlw $2, %%mm1 \n\t" "packuswb %%mm1, %%mm0 \n\t" @@ -1048,11 +1050,11 @@ static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) "paddw %%mm4, %%mm6 \n\t" "movq %%mm2, %%mm0 \n\t" "movq %%mm3, %%mm1 \n\t" - "add %4, %%"REG_a" \n\t" + "add %4, %%"FF_REG_a" \n\t" " js 1b \n\t" : "+a" (len) : "r" (blk1 - len), "r" (blk1 - len + stride), "r" (blk2 - len), - "r" ((x86_reg) stride)); + "r" (stride)); } static inline int sum_mmx(void) @@ -1079,19 +1081,21 @@ static inline int sum_mmxext(void) return ret; } -static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h) { sad8_2_mmx(blk1, blk1 + 1, blk2, stride, h); } -static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h) { sad8_2_mmx(blk1, blk1 + stride, blk2, stride, h); } #define PIX_SAD(suf) \ static int sad8_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ assert(h == 8); \ __asm__ volatile ( \ @@ -1105,7 +1109,7 @@ static int sad8_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad8_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ assert(h == 8); \ __asm__ volatile ( \ @@ -1120,7 +1124,7 @@ static int sad8_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad8_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ assert(h == 8); \ __asm__ volatile ( \ @@ -1135,7 +1139,7 @@ static int sad8_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ assert(h == 8); \ __asm__ volatile ( \ @@ -1149,7 +1153,7 @@ static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad16_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ __asm__ volatile ( \ "pxor %%mm7, %%mm7 \n\t" \ @@ -1163,7 +1167,7 @@ static int sad16_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad16_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ __asm__ volatile ( \ "pxor %%mm7, %%mm7 \n\t" \ @@ -1178,7 +1182,7 @@ static int sad16_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad16_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ __asm__ volatile ( \ "pxor %%mm7, %%mm7 \n\t" \ @@ -1193,7 +1197,7 @@ static int sad16_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ } \ \ static int sad16_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, int stride, int h) \ + uint8_t *blk1, ptrdiff_t stride, int h) \ { \ __asm__ volatile ( \ "pxor %%mm7, %%mm7 \n\t" \ @@ -1212,13 +1216,13 @@ PIX_SAD(mmxext) #endif /* HAVE_INLINE_ASM */ int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - int line_size, int h); + ptrdiff_t stride, int h); -#define hadamard_func(cpu) \ - int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1, \ - uint8_t *src2, int stride, int h); \ - int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1, \ - uint8_t *src2, int stride, int h); +#define hadamard_func(cpu) \ + int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1, \ + uint8_t *src2, ptrdiff_t stride, int h); \ + int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1, \ + uint8_t *src2, ptrdiff_t stride, int h); hadamard_func(mmx) hadamard_func(mmxext) @@ -1252,7 +1256,7 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) c->nsse[0] = nsse16_mmx; c->nsse[1] = nsse8_mmx; - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { c->vsad[0] = vsad16_mmx; } } @@ -1268,7 +1272,7 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) c->sad[0] = sad16_mmxext; c->sad[1] = sad8_mmxext; - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { c->pix_abs[0][1] = sad16_x2_mmxext; c->pix_abs[0][2] = sad16_y2_mmxext; c->pix_abs[0][3] = sad16_xy2_mmxext; diff --git a/libavcodec/x86/mpegvideo.c b/libavcodec/x86/mpegvideo.c index 1395156..6c0493e 100644 --- a/libavcodec/x86/mpegvideo.c +++ b/libavcodec/x86/mpegvideo.c @@ -1,6 +1,6 @@ /* * Optimized for ia32 CPUs by Nick Kurshev - * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer + * H.263, MPEG-1, MPEG-2 dequantizer & draw_edges by Michael Niedermayer * * This file is part of Libav. * @@ -179,7 +179,7 @@ static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s, block0 = block[0] * s->y_dc_scale; else block0 = block[0] * s->c_dc_scale; - /* XXX: only mpeg1 */ + /* XXX: only MPEG-1 */ quant_matrix = s->intra_matrix; __asm__ volatile( "pcmpeqw %%mm7, %%mm7 \n\t" @@ -187,13 +187,13 @@ __asm__ volatile( "movd %2, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" - "mov %3, %%"REG_a" \n\t" + "mov %3, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - "movq (%0, %%"REG_a"), %%mm0 \n\t" - "movq 8(%0, %%"REG_a"), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm4 \n\t" - "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "movq (%0, %%"FF_REG_a"), %%mm0\n\t" + "movq 8(%0, %%"FF_REG_a"), %%mm1\n\t" + "movq (%1, %%"FF_REG_a"), %%mm4\n\t" + "movq 8(%1, %%"FF_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" @@ -208,8 +208,8 @@ __asm__ volatile( "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 + "pcmpeqw (%0, %%"FF_REG_a"), %%mm4\n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"FF_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" @@ -222,13 +222,13 @@ __asm__ volatile( "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" + "movq %%mm4, (%0, %%"FF_REG_a")\n\t" + "movq %%mm5, 8(%0, %%"FF_REG_a")\n\t" - "add $16, %%"REG_a" \n\t" + "add $16, %%"FF_REG_a" \n\t" "js 1b \n\t" ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); block[0]= block0; } @@ -250,13 +250,13 @@ __asm__ volatile( "movd %2, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" - "mov %3, %%"REG_a" \n\t" + "mov %3, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - "movq (%0, %%"REG_a"), %%mm0 \n\t" - "movq 8(%0, %%"REG_a"), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm4 \n\t" - "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "movq (%0, %%"FF_REG_a"), %%mm0\n\t" + "movq 8(%0, %%"FF_REG_a"), %%mm1\n\t" + "movq (%1, %%"FF_REG_a"), %%mm4\n\t" + "movq 8(%1, %%"FF_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" @@ -275,8 +275,8 @@ __asm__ volatile( "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 + "pcmpeqw (%0, %%"FF_REG_a"), %%mm4\n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"FF_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" @@ -289,13 +289,13 @@ __asm__ volatile( "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" + "movq %%mm4, (%0, %%"FF_REG_a")\n\t" + "movq %%mm5, 8(%0, %%"FF_REG_a")\n\t" - "add $16, %%"REG_a" \n\t" + "add $16, %%"FF_REG_a" \n\t" "js 1b \n\t" ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); } @@ -322,13 +322,13 @@ __asm__ volatile( "movd %2, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" - "mov %3, %%"REG_a" \n\t" + "mov %3, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - "movq (%0, %%"REG_a"), %%mm0 \n\t" - "movq 8(%0, %%"REG_a"), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm4 \n\t" - "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "movq (%0, %%"FF_REG_a"), %%mm0\n\t" + "movq 8(%0, %%"FF_REG_a"), %%mm1\n\t" + "movq (%1, %%"FF_REG_a"), %%mm4\n\t" + "movq 8(%1, %%"FF_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" @@ -343,8 +343,8 @@ __asm__ volatile( "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 + "pcmpeqw (%0, %%"FF_REG_a"), %%mm4\n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"FF_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" @@ -353,13 +353,13 @@ __asm__ volatile( "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" + "movq %%mm4, (%0, %%"FF_REG_a")\n\t" + "movq %%mm5, 8(%0, %%"FF_REG_a")\n\t" - "add $16, %%"REG_a" \n\t" + "add $16, %%"FF_REG_a" \n\t" "jng 1b \n\t" ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); block[0]= block0; //Note, we do not do mismatch control for intra as errors cannot accumulate @@ -383,13 +383,13 @@ __asm__ volatile( "movd %2, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" "packssdw %%mm6, %%mm6 \n\t" - "mov %3, %%"REG_a" \n\t" + "mov %3, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - "movq (%0, %%"REG_a"), %%mm0 \n\t" - "movq 8(%0, %%"REG_a"), %%mm1 \n\t" - "movq (%1, %%"REG_a"), %%mm4 \n\t" - "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "movq (%0, %%"FF_REG_a"), %%mm0\n\t" + "movq 8(%0, %%"FF_REG_a"), %%mm1\n\t" + "movq (%1, %%"FF_REG_a"), %%mm4\n\t" + "movq 8(%1, %%"FF_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" @@ -408,8 +408,8 @@ __asm__ volatile( "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 + "pcmpeqw (%0, %%"FF_REG_a"), %%mm4\n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"FF_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" @@ -420,10 +420,10 @@ __asm__ volatile( "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" + "movq %%mm4, (%0, %%"FF_REG_a")\n\t" + "movq %%mm5, 8(%0, %%"FF_REG_a")\n\t" - "add $16, %%"REG_a" \n\t" + "add $16, %%"FF_REG_a" \n\t" "jng 1b \n\t" "movd 124(%0, %3), %%mm0 \n\t" "movq %%mm7, %%mm6 \n\t" @@ -438,7 +438,7 @@ __asm__ volatile( "movd %%mm0, 124(%0, %3) \n\t" ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "r" (-2*nCoeffs) - : "%"REG_a, "memory" + : "%"FF_REG_a, "memory" ); } @@ -454,7 +454,7 @@ av_cold void ff_mpv_common_init_x86(MpegEncContext *s) 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)) + if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx; } diff --git a/libavcodec/x86/mpegvideodsp.c b/libavcodec/x86/mpegvideodsp.c index 0e5dd0f..b701ef8 100644 --- a/libavcodec/x86/mpegvideodsp.c +++ b/libavcodec/x86/mpegvideodsp.c @@ -19,7 +19,6 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/mpegvideodsp.h" diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index 1274c13..72df76b 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -24,6 +24,7 @@ #include "libavutil/internal.h" #include "libavutil/x86/asm.h" +#include "libavcodec/mpegutils.h" #include "libavcodec/mpegvideo.h" #include "fdct.h" @@ -146,33 +147,33 @@ static int RENAME(dct_quantize)(MpegEncContext *s, if((s->out_format == FMT_H263 || s->out_format == FMT_H261) && s->mpeg_quant==0){ __asm__ volatile( - "movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1 + "movd %%"FF_REG_a", "MM"3 \n\t" // last_non_zero_p1 SPREADW(MM"3") "pxor "MM"7, "MM"7 \n\t" // 0 "pxor "MM"4, "MM"4 \n\t" // 0 MOVQ" (%2), "MM"5 \n\t" // qmat[0] "pxor "MM"6, "MM"6 \n\t" "psubw (%3), "MM"6 \n\t" // -bias[0] - "mov $-128, %%"REG_a" \n\t" + "mov $-128, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i] + MOVQ" (%1, %%"FF_REG_a"), "MM"0 \n\t" // block[i] SAVE_SIGN(MM"1", MM"0") // ABS(block[i]) "psubusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0] "pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16 "por "MM"0, "MM"4 \n\t" RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) - MOVQ" "MM"0, (%5, %%"REG_a") \n\t" + MOVQ" "MM"0, (%5, %%"FF_REG_a") \n\t" "pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00 - MOVQ" (%4, %%"REG_a"), "MM"1 \n\t" - MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0 + MOVQ" (%4, %%"FF_REG_a"), "MM"1 \n\t" + MOVQ" "MM"7, (%1, %%"FF_REG_a") \n\t" // 0 "pandn "MM"1, "MM"0 \n\t" PMAXW(MM"0", MM"3") - "add $"MMREG_WIDTH", %%"REG_a" \n\t" + "add $"MMREG_WIDTH", %%"FF_REG_a" \n\t" " js 1b \n\t" PMAX(MM"3", MM"0") - "movd "MM"3, %%"REG_a" \n\t" - "movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1 + "movd "MM"3, %%"FF_REG_a" \n\t" + "movzb %%al, %%"FF_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) @@ -181,32 +182,32 @@ static int RENAME(dct_quantize)(MpegEncContext *s, ); }else{ // FMT_H263 __asm__ volatile( - "movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1 + "movd %%"FF_REG_a", "MM"3 \n\t" // last_non_zero_p1 SPREADW(MM"3") "pxor "MM"7, "MM"7 \n\t" // 0 "pxor "MM"4, "MM"4 \n\t" // 0 - "mov $-128, %%"REG_a" \n\t" + "mov $-128, %%"FF_REG_a" \n\t" ".p2align 4 \n\t" "1: \n\t" - MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i] + MOVQ" (%1, %%"FF_REG_a"), "MM"0 \n\t" // block[i] SAVE_SIGN(MM"1", MM"0") // ABS(block[i]) - MOVQ" (%3, %%"REG_a"), "MM"6 \n\t" // bias[0] + MOVQ" (%3, %%"FF_REG_a"), "MM"6 \n\t" // bias[0] "paddusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0] - MOVQ" (%2, %%"REG_a"), "MM"5 \n\t" // qmat[i] + MOVQ" (%2, %%"FF_REG_a"), "MM"5 \n\t" // qmat[i] "pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16 "por "MM"0, "MM"4 \n\t" RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) - MOVQ" "MM"0, (%5, %%"REG_a") \n\t" + MOVQ" "MM"0, (%5, %%"FF_REG_a") \n\t" "pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00 - MOVQ" (%4, %%"REG_a"), "MM"1 \n\t" - MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0 + MOVQ" (%4, %%"FF_REG_a"), "MM"1 \n\t" + MOVQ" "MM"7, (%1, %%"FF_REG_a") \n\t" // 0 "pandn "MM"1, "MM"0 \n\t" PMAXW(MM"0", MM"3") - "add $"MMREG_WIDTH", %%"REG_a" \n\t" + "add $"MMREG_WIDTH", %%"FF_REG_a" \n\t" " js 1b \n\t" PMAX(MM"3", MM"0") - "movd "MM"3, %%"REG_a" \n\t" - "movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1 + "movd "MM"3, %%"FF_REG_a" \n\t" + "movzb %%al, %%"FF_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) diff --git a/libavcodec/x86/mpegvideoencdsp_init.c b/libavcodec/x86/mpegvideoencdsp_init.c index 7732e73..71fbf28 100644 --- a/libavcodec/x86/mpegvideoencdsp_init.c +++ b/libavcodec/x86/mpegvideoencdsp_init.c @@ -203,7 +203,7 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, #if HAVE_INLINE_ASM if (INLINE_MMX(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { c->try_8x8basis = try_8x8basis_mmx; } c->add_8x8basis = add_8x8basis_mmx; @@ -214,7 +214,7 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, } if (INLINE_AMD3DNOW(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { c->try_8x8basis = try_8x8basis_3dnow; } c->add_8x8basis = add_8x8basis_3dnow; @@ -222,7 +222,7 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, #if HAVE_SSSE3_INLINE if (INLINE_SSSE3(cpu_flags)) { - if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { c->try_8x8basis = try_8x8basis_ssse3; } c->add_8x8basis = add_8x8basis_ssse3; diff --git a/libavcodec/x86/pngdsp.asm b/libavcodec/x86/pngdsp.asm index c05f3da..722caf0 100644 --- a/libavcodec/x86/pngdsp.asm +++ b/libavcodec/x86/pngdsp.asm @@ -27,7 +27,7 @@ SECTION_RODATA cextern pw_255 -SECTION_TEXT +SECTION .text ; %1 = nr. of xmm registers used %macro ADD_BYTES_FN 1 diff --git a/libavcodec/x86/proresdsp.asm b/libavcodec/x86/proresdsp.asm index a0e97b3..9613fa1 100644 --- a/libavcodec/x86/proresdsp.asm +++ b/libavcodec/x86/proresdsp.asm @@ -54,7 +54,7 @@ cextern pw_8 cextern pw_512 cextern pw_1019 -section .text align=16 +SECTION .text ; interleave data while maintaining source ; %1=type, %2=dstlo, %3=dsthi, %4=src, %5=interleave @@ -326,11 +326,10 @@ section .text align=16 SUMSUB_SHPK m2, m3, m4, m5, m6, m7, %2 %endmacro -; void ff_prores_idct_put_10_(uint8_t *pixels, int stride, +; void ff_prores_idct_put_10_(uint8_t *pixels, ptrdiff_t linesize, ; int16_t *block, const int16_t *qmat); %macro idct_put_fn 1 cglobal prores_idct_put_10, 4, 4, %1 - movsxd r1, r1d pxor m15, m15 ; zero ; for (i = 0; i < 8; i++) diff --git a/libavcodec/x86/proresdsp_init.c b/libavcodec/x86/proresdsp_init.c index e82dac0..ff4d398 100644 --- a/libavcodec/x86/proresdsp_init.c +++ b/libavcodec/x86/proresdsp_init.c @@ -25,11 +25,11 @@ #include "libavcodec/idctdsp.h" #include "libavcodec/proresdsp.h" -void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize, +void ff_prores_idct_put_10_sse2(uint16_t *dst, ptrdiff_t linesize, int16_t *block, const int16_t *qmat); -void ff_prores_idct_put_10_sse4(uint16_t *dst, int linesize, +void ff_prores_idct_put_10_sse4(uint16_t *dst, ptrdiff_t linesize, int16_t *block, const int16_t *qmat); -void ff_prores_idct_put_10_avx (uint16_t *dst, int linesize, +void ff_prores_idct_put_10_avx (uint16_t *dst, ptrdiff_t linesize, int16_t *block, const int16_t *qmat); av_cold void ff_proresdsp_init_x86(ProresDSPContext *dsp) diff --git a/libavcodec/x86/qpeldsp.asm b/libavcodec/x86/qpeldsp.asm index 8f65550..ef5f1d8 100644 --- a/libavcodec/x86/qpeldsp.asm +++ b/libavcodec/x86/qpeldsp.asm @@ -30,7 +30,7 @@ cextern pw_16 cextern pw_20 -SECTION_TEXT +SECTION .text ; void ff_put_no_rnd_pixels8_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) %macro PUT_NO_RND_PIXELS8_L2 0 diff --git a/libavcodec/x86/rnd_template.c b/libavcodec/x86/rnd_template.c index a9fb132..0c76d91 100644 --- a/libavcodec/x86/rnd_template.c +++ b/libavcodec/x86/rnd_template.c @@ -46,12 +46,12 @@ STATIC void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "punpckhbw %%mm7, %%mm5 \n\t" "paddusw %%mm0, %%mm4 \n\t" "paddusw %%mm1, %%mm5 \n\t" - "xor %%"REG_a", %%"REG_a" \n\t" + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" "add %3, %1 \n\t" ".p2align 3 \n\t" "1: \n\t" - "movq (%1, %%"REG_a"), %%mm0 \n\t" - "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0\n\t" + "movq 1(%1, %%"FF_REG_a"), %%mm2\n\t" "movq %%mm0, %%mm1 \n\t" "movq %%mm2, %%mm3 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" @@ -67,11 +67,11 @@ STATIC void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "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 %%mm4, (%2, %%"FF_REG_a") \n\t" + "add %3, %%"FF_REG_a" \n\t" - "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 - "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm2\n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"FF_REG_a"), %%mm4\n\t" "movq %%mm2, %%mm3 \n\t" "movq %%mm4, %%mm5 \n\t" "punpcklbw %%mm7, %%mm2 \n\t" @@ -87,14 +87,14 @@ STATIC void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "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" + "movq %%mm0, (%2, %%"FF_REG_a") \n\t" + "add %3, %%"FF_REG_a" \n\t" "subl $2, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels) :"D"(block), "r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } // avg_pixels @@ -115,12 +115,12 @@ STATIC void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "punpckhbw %%mm7, %%mm5 \n\t" "paddusw %%mm0, %%mm4 \n\t" "paddusw %%mm1, %%mm5 \n\t" - "xor %%"REG_a", %%"REG_a" \n\t" + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" "add %3, %1 \n\t" ".p2align 3 \n\t" "1: \n\t" - "movq (%1, %%"REG_a"), %%mm0 \n\t" - "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0\n\t" + "movq 1(%1, %%"FF_REG_a"), %%mm2\n\t" "movq %%mm0, %%mm1 \n\t" "movq %%mm2, %%mm3 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" @@ -135,16 +135,16 @@ STATIC void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "paddusw %%mm1, %%mm5 \n\t" "psrlw $2, %%mm4 \n\t" "psrlw $2, %%mm5 \n\t" - "movq (%2, %%"REG_a"), %%mm3 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm3 \n\t" "packuswb %%mm5, %%mm4 \n\t" "pcmpeqd %%mm2, %%mm2 \n\t" "paddb %%mm2, %%mm2 \n\t" PAVGB_MMX(%%mm3, %%mm4, %%mm5, %%mm2) - "movq %%mm5, (%2, %%"REG_a") \n\t" - "add %3, %%"REG_a" \n\t" + "movq %%mm5, (%2, %%"FF_REG_a") \n\t" + "add %3, %%"FF_REG_a" \n\t" - "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 - "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq (%1, %%"FF_REG_a"), %%mm2\n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"FF_REG_a"), %%mm4\n\t" "movq %%mm2, %%mm3 \n\t" "movq %%mm4, %%mm5 \n\t" "punpcklbw %%mm7, %%mm2 \n\t" @@ -159,17 +159,17 @@ STATIC void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, "paddusw %%mm5, %%mm1 \n\t" "psrlw $2, %%mm0 \n\t" "psrlw $2, %%mm1 \n\t" - "movq (%2, %%"REG_a"), %%mm3 \n\t" + "movq (%2, %%"FF_REG_a"), %%mm3 \n\t" "packuswb %%mm1, %%mm0 \n\t" "pcmpeqd %%mm2, %%mm2 \n\t" "paddb %%mm2, %%mm2 \n\t" PAVGB_MMX(%%mm3, %%mm0, %%mm1, %%mm2) - "movq %%mm1, (%2, %%"REG_a") \n\t" - "add %3, %%"REG_a" \n\t" + "movq %%mm1, (%2, %%"FF_REG_a") \n\t" + "add %3, %%"FF_REG_a" \n\t" "subl $2, %0 \n\t" "jnz 1b \n\t" :"+g"(h), "+S"(pixels) :"D"(block), "r"((x86_reg)line_size) - :REG_a, "memory"); + :FF_REG_a, "memory"); } diff --git a/libavcodec/x86/rv34dsp_init.c b/libavcodec/x86/rv34dsp_init.c index 586e4e9..32d4c1a 100644 --- a/libavcodec/x86/rv34dsp_init.c +++ b/libavcodec/x86/rv34dsp_init.c @@ -21,7 +21,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/rv34dsp.h" diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm index 0a242b5..77f6ddb 100644 --- a/libavcodec/x86/rv40dsp.asm +++ b/libavcodec/x86/rv40dsp.asm @@ -335,14 +335,14 @@ INIT_XMM ssse3 FILTER_SSSE3 put FILTER_SSSE3 avg -; %1=5bits weights?, %2=dst %3=src1 %4=src3 %5=stride if sse2 +; %1=5-bit weights?, %2=dst %3=src1 %4=src3 %5=stride if SSE2 %macro RV40_WCORE 4-5 movh m4, [%3 + r6 + 0] movh m5, [%4 + r6 + 0] %if %0 == 4 %define OFFSET r6 + mmsize / 2 %else - ; 8x8 block and sse2, stride was provided + ; 8x8 block and SSE2, stride was provided %define OFFSET r6 add r6, r5 %endif @@ -350,7 +350,7 @@ FILTER_SSSE3 avg movh m7, [%4 + OFFSET] %if %1 == 0 - ; 14bits weights + ; 14-bit weights punpcklbw m4, m0 punpcklbw m5, m0 punpcklbw m6, m0 @@ -368,7 +368,7 @@ FILTER_SSSE3 avg paddw m4, m5 paddw m6, m7 %else - ; 5bits weights + ; 5-bit weights %if cpuflag(ssse3) punpcklbw m4, m5 punpcklbw m6, m7 @@ -404,7 +404,7 @@ FILTER_SSSE3 avg packuswb m4, m6 %if %0 == 5 - ; Only called for 8x8 blocks and sse2 + ; Only called for 8x8 blocks and SSE2 sub r6, r5 movh [%2 + r6], m4 add r6, r5 diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm index d7164b6..b449de5 100644 --- a/libavcodec/x86/sbrdsp.asm +++ b/libavcodec/x86/sbrdsp.asm @@ -27,7 +27,7 @@ ps_mask times 2 dd 1<<31, 0 ps_mask2 times 2 dd 0, 1<<31 ps_neg times 4 dd 1<<31 -SECTION_TEXT +SECTION .text INIT_XMM sse cglobal sbr_sum_square, 2, 3, 6 diff --git a/libavcodec/x86/simple_idct.c b/libavcodec/x86/simple_idct.c index 1002a78..49784e2 100644 --- a/libavcodec/x86/simple_idct.c +++ b/libavcodec/x86/simple_idct.c @@ -23,6 +23,9 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/x86/asm.h" + +#include "libavcodec/idctdsp.h" + #include "idctdsp.h" #include "simple_idct.h" @@ -87,259 +90,6 @@ static inline void idct(int16_t *block) 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 */\ @@ -1119,8 +869,6 @@ 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 @@ -1159,12 +907,12 @@ void ff_simple_idct_mmx(int16_t *block) void ff_simple_idct_put_mmx(uint8_t *dest, int line_size, int16_t *block) { idct(block); - ff_put_pixels_clamped_mmx(block, dest, line_size); + ff_put_pixels_clamped(block, dest, line_size); } void ff_simple_idct_add_mmx(uint8_t *dest, int line_size, int16_t *block) { idct(block); - ff_add_pixels_clamped_mmx(block, dest, line_size); + ff_add_pixels_clamped(block, dest, line_size); } #endif /* HAVE_INLINE_ASM */ diff --git a/libavcodec/x86/v210enc.asm b/libavcodec/x86/v210enc.asm new file mode 100644 index 0000000..ec4309f --- /dev/null +++ b/libavcodec/x86/v210enc.asm @@ -0,0 +1,178 @@ +;****************************************************************************** +;* V210 SIMD pack +;* Copyright (c) 2014 Kieran Kunhya +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +v210_enc_min_10: times 32 dw 0x4 +v210_enc_max_10: times 32 dw 0x3fb + +v210_enc_luma_mult_10: times 2 dw 4,1,16,4,1,16,0,0 +v210_enc_luma_shuf_10: times 2 db -1,0,1,-1,2,3,4,5,-1,6,7,-1,8,9,10,11 + +v210_enc_chroma_mult_10: times 2 dw 1,4,16,0,16,1,4,0 +v210_enc_chroma_shuf_10: times 2 db 0,1,8,9,-1,2,3,-1,10,11,4,5,-1,12,13,-1 + +v210_enc_min_8: times 32 db 0x1 +v210_enc_max_8: times 32 db 0xfe + +v210_enc_luma_mult_8: times 2 dw 16,4,64,16,4,64,0,0 +v210_enc_luma_shuf_8: times 2 db 6,-1,7,-1,8,-1,9,-1,10,-1,11,-1,-1,-1,-1,-1 + +v210_enc_chroma_mult_8: times 2 dw 4,16,64,0,64,4,16,0 +v210_enc_chroma_shuf1_8: times 2 db 0,-1,1,-1,2,-1,3,-1,8,-1,9,-1,10,-1,11,-1 +v210_enc_chroma_shuf2_8: times 2 db 3,-1,4,-1,5,-1,7,-1,11,-1,12,-1,13,-1,15,-1 + +SECTION .text + +%macro v210_planar_pack_10 0 + +; v210_planar_pack_10(const uint16_t *y, const uint16_t *u, const uint16_t *v, uint8_t *dst, ptrdiff_t width) +cglobal v210_planar_pack_10, 5, 5, 4+cpuflag(avx2), y, u, v, dst, width + lea r0, [yq+2*widthq] + add uq, widthq + add vq, widthq + neg widthq + + mova m2, [v210_enc_min_10] + mova m3, [v210_enc_max_10] + +.loop + movu xm0, [yq+2*widthq] +%if cpuflag(avx2) + vinserti128 m0, m0, [yq+2*widthq+12], 1 +%endif + CLIPW m0, m2, m3 + + movq xm1, [uq+widthq] + movhps xm1, [vq+widthq] +%if cpuflag(avx2) + movq xm4, [uq+widthq+6] + movhps xm4, [vq+widthq+6] + vinserti128 m1, m1, xm4, 1 +%endif + CLIPW m1, m2, m3 + + pmullw m0, [v210_enc_luma_mult_10] + pshufb m0, [v210_enc_luma_shuf_10] + + pmullw m1, [v210_enc_chroma_mult_10] + pshufb m1, [v210_enc_chroma_shuf_10] + + por m0, m1 + + movu [dstq], m0 + + add dstq, mmsize + add widthq, (mmsize*3)/8 + jl .loop + + RET +%endmacro + +%if HAVE_SSSE3_EXTERNAL +INIT_XMM ssse3 +v210_planar_pack_10 +%endif +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +v210_planar_pack_10 +%endif + +%macro v210_planar_pack_8 0 + +; v210_planar_pack_8(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, ptrdiff_t width) +cglobal v210_planar_pack_8, 5, 5, 7, y, u, v, dst, width + add yq, widthq + shr widthq, 1 + add uq, widthq + add vq, widthq + neg widthq + + mova m4, [v210_enc_min_8] + mova m5, [v210_enc_max_8] + pxor m6, m6 + +.loop + movu xm1, [yq+2*widthq] +%if cpuflag(avx2) + vinserti128 m1, m1, [yq+2*widthq+12], 1 +%endif + CLIPUB m1, m4, m5 + + punpcklbw m0, m1, m6 + ; can't unpack high bytes in the same way because we process + ; only six bytes at a time + pshufb m1, [v210_enc_luma_shuf_8] + + pmullw m0, [v210_enc_luma_mult_8] + pmullw m1, [v210_enc_luma_mult_8] + pshufb m0, [v210_enc_luma_shuf_10] + pshufb m1, [v210_enc_luma_shuf_10] + + movq xm3, [uq+widthq] + movhps xm3, [vq+widthq] +%if cpuflag(avx2) + movq xm2, [uq+widthq+6] + movhps xm2, [vq+widthq+6] + vinserti128 m3, m3, xm2, 1 +%endif + CLIPUB m3, m4, m5 + + ; shuffle and multiply to get the same packing as in 10-bit + pshufb m2, m3, [v210_enc_chroma_shuf1_8] + pshufb m3, [v210_enc_chroma_shuf2_8] + + pmullw m2, [v210_enc_chroma_mult_8] + pmullw m3, [v210_enc_chroma_mult_8] + pshufb m2, [v210_enc_chroma_shuf_10] + pshufb m3, [v210_enc_chroma_shuf_10] + + por m0, m2 + por m1, m3 + + movu [dstq], xm0 + movu [dstq+16], xm1 +%if cpuflag(avx2) + vextracti128 [dstq+32], m0, 1 + vextracti128 [dstq+48], m1, 1 +%endif + + add dstq, 2*mmsize + add widthq, (mmsize*3)/8 + jl .loop + + RET +%endmacro + +%if HAVE_SSSE3_EXTERNAL +INIT_XMM ssse3 +v210_planar_pack_8 +%endif +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +v210_planar_pack_8 +%endif +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +v210_planar_pack_8 +%endif diff --git a/libavcodec/x86/v210enc_init.c b/libavcodec/x86/v210enc_init.c new file mode 100644 index 0000000..c4d2745 --- /dev/null +++ b/libavcodec/x86/v210enc_init.c @@ -0,0 +1,54 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/x86/cpu.h" +#include "libavcodec/v210enc.h" + +void ff_v210_planar_pack_8_ssse3(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, + ptrdiff_t width); +void ff_v210_planar_pack_8_avx(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, ptrdiff_t width); +void ff_v210_planar_pack_8_avx2(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, ptrdiff_t width); +void ff_v210_planar_pack_10_ssse3(const uint16_t *y, const uint16_t *u, + const uint16_t *v, uint8_t *dst, + ptrdiff_t width); +void ff_v210_planar_pack_10_avx2(const uint16_t *y, const uint16_t *u, + const uint16_t *v, uint8_t *dst, + ptrdiff_t width); + +av_cold void ff_v210enc_init_x86(V210EncContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSSE3(cpu_flags)) { + s->pack_line_8 = ff_v210_planar_pack_8_ssse3; + s->pack_line_10 = ff_v210_planar_pack_10_ssse3; + } + + if (EXTERNAL_AVX(cpu_flags)) + s->pack_line_8 = ff_v210_planar_pack_8_avx; + + if (EXTERNAL_AVX2(cpu_flags)) { + s->sample_factor_8 = 2; + s->pack_line_8 = ff_v210_planar_pack_8_avx2; + s->sample_factor_10 = 2; + s->pack_line_10 = ff_v210_planar_pack_10_avx2; + } +} diff --git a/libavcodec/x86/vc1dsp_mmx.c b/libavcodec/x86/vc1dsp_mmx.c index 046affb..9bbc234 100644 --- a/libavcodec/x86/vc1dsp_mmx.c +++ b/libavcodec/x86/vc1dsp_mmx.c @@ -81,13 +81,13 @@ "movq %%mm"#R1", "#OFF"(%1) \n\t" \ "add %2, %0 \n\t" -/** Sacrifying mm6 allows to pipeline loads from src */ +/** Sacrificing mm6 allows to pipeline loads from src */ static void vc1_put_ver_16b_shift2_mmx(int16_t *dst, const uint8_t *src, x86_reg stride, int rnd, int64_t shift) { __asm__ volatile( - "mov $3, %%"REG_c" \n\t" + "mov $3, %%"FF_REG_c" \n\t" LOAD_ROUNDER_MMX("%5") "movq "MANGLE(ff_pw_9)", %%mm6 \n\t" "1: \n\t" @@ -106,12 +106,12 @@ static void vc1_put_ver_16b_shift2_mmx(int16_t *dst, SHIFT2_LINE(168, 4, 1, 2, 3) "sub %6, %0 \n\t" "add $8, %1 \n\t" - "dec %%"REG_c" \n\t" + "dec %%"FF_REG_c" \n\t" "jnz 1b \n\t" : "+r"(src), "+r"(dst) : "r"(stride), "r"(-2*stride), "m"(shift), "m"(rnd), "r"(9*stride-4) - : "%"REG_c, "memory" + : "%"FF_REG_c, "memory" ); } @@ -165,7 +165,7 @@ VC1_HOR_16b_SHIFT2(OP_AVG, avg_) /** * Purely vertical or horizontal 1/2 shift interpolation. - * Sacrify mm6 for *9 factor. + * Sacrifice mm6 for *9 factor. */ #define VC1_SHIFT2(OP, OPNAME)\ static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\ @@ -173,7 +173,7 @@ static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\ {\ rnd = 8-rnd;\ __asm__ volatile(\ - "mov $8, %%"REG_c" \n\t"\ + "mov $8, %%"FF_REG_c" \n\t"\ LOAD_ROUNDER_MMX("%5")\ "movq "MANGLE(ff_pw_9)", %%mm6\n\t"\ "1: \n\t"\ @@ -208,12 +208,12 @@ static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\ "movq %%mm3, (%1) \n\t"\ "add %6, %0 \n\t"\ "add %4, %1 \n\t"\ - "dec %%"REG_c" \n\t"\ + "dec %%"FF_REG_c" \n\t"\ "jnz 1b \n\t"\ : "+r"(src), "+r"(dst)\ : "r"(offset), "r"(-2*offset), "g"(stride), "m"(rnd),\ "g"(stride-offset)\ - : "%"REG_c, "memory"\ + : "%"FF_REG_c, "memory"\ );\ } @@ -223,7 +223,7 @@ VC1_SHIFT2(OP_AVG, avg_) /** * Core of the 1/4 and 3/4 shift bicubic interpolation. * - * @param UNPACK Macro unpacking arguments from 8 to 16bits (can be empty). + * @param UNPACK Macro unpacking arguments from 8 to 16 bits (can be empty). * @param MOVQ "movd 1" or "movq 2", if data read is already unpacked. * @param A1 Address of 1st tap (beware of unpacked/packed). * @param A2 Address of 2nd tap @@ -263,7 +263,7 @@ VC1_SHIFT2(OP_AVG, avg_) "paddw %%mm2, %%mm4 \n\t" /* 4,53,18,-3 */ /** - * Macro to build the vertical 16bits version of vc1_put_shift[13]. + * Macro to build the vertical 16 bits version of vc1_put_shift[13]. * Here, offset=src_stride. Parameters passed A1 to A4 must use * %3 (src_stride) and %4 (3*src_stride). * @@ -320,8 +320,8 @@ vc1_put_ver_16b_ ## NAME ## _mmx(int16_t *dst, const uint8_t *src, \ } /** - * Macro to build the horizontal 16bits version of vc1_put_shift[13]. - * Here, offset=16bits, so parameters passed A1 to A4 should be simple. + * Macro to build the horizontal 16 bits version of vc1_put_shift[13]. + * Here, offset=16 bits, so parameters passed A1 to A4 should be simple. * * @param NAME Either 1 or 3 * @see MSPEL_FILTER13_CORE for information on A1->A4 @@ -357,7 +357,7 @@ OPNAME ## vc1_hor_16b_ ## NAME ## _mmx(uint8_t *dst, x86_reg stride, \ } /** - * Macro to build the 8bits, any direction, version of vc1_put_shift[13]. + * Macro to build the 8 bits, any direction, version of vc1_put_shift[13]. * Here, offset=src_stride. Parameters passed A1 to A4 must use * %3 (offset) and %4 (3*offset). * diff --git a/libavcodec/x86/vp3dsp.asm b/libavcodec/x86/vp3dsp.asm index fc8a047..8587741 100644 --- a/libavcodec/x86/vp3dsp.asm +++ b/libavcodec/x86/vp3dsp.asm @@ -104,9 +104,6 @@ SECTION .text INIT_MMX mmxext cglobal vp3_v_loop_filter, 3, 4 -%if ARCH_X86_64 - movsxd r1, r1d -%endif mov r3, r1 neg r1 movq m6, [r0+r1*2] @@ -121,9 +118,6 @@ cglobal vp3_v_loop_filter, 3, 4 RET cglobal vp3_h_loop_filter, 3, 4 -%if ARCH_X86_64 - movsxd r1, r1d -%endif lea r3, [r1*3] movd m6, [r0 -2] @@ -525,7 +519,6 @@ cglobal vp3_h_loop_filter, 3, 4 cglobal vp3_idct_put, 3, 4, 9 VP3_IDCT r2 - movsxdifnidn r1, r1d mova m4, [pb_80] lea r3, [r1*3] %assign %%i 0 @@ -582,7 +575,6 @@ cglobal vp3_idct_put, 3, 4, 9 cglobal vp3_idct_add, 3, 4, 9 VP3_IDCT r2 - movsxdifnidn r1, r1d lea r3, [r1*3] pxor m4, m4 %if mmsize == 16 @@ -689,9 +681,6 @@ vp3_idct_funcs INIT_MMX mmxext cglobal vp3_idct_dc_add, 3, 4 -%if ARCH_X86_64 - movsxd r1, r1d -%endif movsx r3, word [r2] mov word [r2], 0 lea r2, [r1*3] diff --git a/libavcodec/x86/vp3dsp_init.c b/libavcodec/x86/vp3dsp_init.c index ed38a8e..043e10f 100644 --- a/libavcodec/x86/vp3dsp_init.c +++ b/libavcodec/x86/vp3dsp_init.c @@ -25,18 +25,17 @@ #include "libavcodec/vp3dsp.h" #include "config.h" -void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, int16_t *block); -void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, int16_t *block); +void ff_vp3_idct_put_mmx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vp3_idct_add_mmx(uint8_t *dest, ptrdiff_t stride, int16_t *block); -void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, int16_t *block); -void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, int16_t *block); +void ff_vp3_idct_put_sse2(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vp3_idct_add_sse2(uint8_t *dest, ptrdiff_t stride, int16_t *block); -void ff_vp3_idct_dc_add_mmxext(uint8_t *dest, int line_size, - int16_t *block); +void ff_vp3_idct_dc_add_mmxext(uint8_t *dest, ptrdiff_t stride, int16_t *block); -void ff_vp3_v_loop_filter_mmxext(uint8_t *src, int stride, +void ff_vp3_v_loop_filter_mmxext(uint8_t *src, ptrdiff_t stride, int *bounding_values); -void ff_vp3_h_loop_filter_mmxext(uint8_t *src, int stride, +void ff_vp3_h_loop_filter_mmxext(uint8_t *src, ptrdiff_t stride, int *bounding_values); av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags) @@ -53,7 +52,7 @@ av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags) if (EXTERNAL_MMXEXT(cpu_flags)) { c->idct_dc_add = ff_vp3_idct_dc_add_mmxext; - if (!(flags & CODEC_FLAG_BITEXACT)) { + if (!(flags & AV_CODEC_FLAG_BITEXACT)) { c->v_loop_filter = ff_vp3_v_loop_filter_mmxext; c->h_loop_filter = ff_vp3_h_loop_filter_mmxext; } diff --git a/libavcodec/x86/vp6dsp.asm b/libavcodec/x86/vp6dsp.asm index 80f8ca5..b667d38 100644 --- a/libavcodec/x86/vp6dsp.asm +++ b/libavcodec/x86/vp6dsp.asm @@ -115,7 +115,7 @@ SECTION .text %endmacro %macro vp6_filter_diag4 0 -; void ff_vp6_filter_diag4_(uint8_t *dst, uint8_t *src, int stride, +; void ff_vp6_filter_diag4_(uint8_t *dst, uint8_t *src, ptrdiff_t stride, ; const int16_t h_weight[4], const int16_t v_weights[4]) cglobal vp6_filter_diag4, 5, 7, 8 mov r5, rsp ; backup stack pointer @@ -126,9 +126,6 @@ cglobal vp6_filter_diag4, 5, 7, 8 sub rsp, 8*15 movq m6, [pw_64] %endif -%if ARCH_X86_64 - movsxd r2, r2d -%endif sub r1, r2 diff --git a/libavcodec/x86/vp6dsp_init.c b/libavcodec/x86/vp6dsp_init.c index cd94f3e..6d98db1 100644 --- a/libavcodec/x86/vp6dsp_init.c +++ b/libavcodec/x86/vp6dsp_init.c @@ -22,16 +22,15 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/vp56dsp.h" -void ff_vp6_filter_diag4_mmx(uint8_t *dst, uint8_t *src, int stride, +void ff_vp6_filter_diag4_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights,const int16_t *v_weights); -void ff_vp6_filter_diag4_sse2(uint8_t *dst, uint8_t *src, int stride, +void ff_vp6_filter_diag4_sse2(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights,const int16_t *v_weights); -av_cold void ff_vp6dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec) +av_cold void ff_vp6dsp_init_x86(VP56DSPContext *c) { int cpu_flags = av_get_cpu_flags(); diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm index adc9730..b0f6b83 100644 --- a/libavcodec/x86/vp8dsp.asm +++ b/libavcodec/x86/vp8dsp.asm @@ -143,21 +143,21 @@ filter_h6_shuf1: db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12 filter_h6_shuf2: db 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9 filter_h6_shuf3: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11 -pw_256: times 8 dw 256 pw_20091: times 4 dw 20091 pw_17734: times 4 dw 17734 cextern pw_3 cextern pw_4 cextern pw_64 +cextern pw_256 SECTION .text ;------------------------------------------------------------------------------- ; subpel MC functions: ; -; void ff_put_vp8_epel_hv_(uint8_t *dst, int deststride, -; uint8_t *src, int srcstride, +; void ff_put_vp8_epel_hv_(uint8_t *dst, ptrdiff_t deststride, +; uint8_t *src, ptrdiff_t srcstride, ; int height, int mx, int my); ;------------------------------------------------------------------------------- @@ -884,7 +884,7 @@ cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height REP_RET ;----------------------------------------------------------------------------- -; void ff_vp8_idct_dc_add_(uint8_t *dst, int16_t block[16], int stride); +; void ff_vp8_idct_dc_add_(uint8_t *dst, int16_t block[16], ptrdiff_t stride); ;----------------------------------------------------------------------------- %macro ADD_DC 4 @@ -962,7 +962,7 @@ cglobal vp8_idct_dc_add, 3, 3, 6, dst, block, stride RET ;----------------------------------------------------------------------------- -; void ff_vp8_idct_dc_add4y_(uint8_t *dst, int16_t block[4][16], int stride); +; void ff_vp8_idct_dc_add4y_(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); ;----------------------------------------------------------------------------- %if ARCH_X86_32 @@ -1035,7 +1035,7 @@ cglobal vp8_idct_dc_add4y, 3, 3, 6, dst, block, stride RET ;----------------------------------------------------------------------------- -; void ff_vp8_idct_dc_add4uv_(uint8_t *dst, int16_t block[4][16], int stride); +; void ff_vp8_idct_dc_add4uv_(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); ;----------------------------------------------------------------------------- INIT_MMX mmx @@ -1077,7 +1077,7 @@ cglobal vp8_idct_dc_add4uv, 3, 3, 0, dst, block, stride RET ;----------------------------------------------------------------------------- -; void ff_vp8_idct_add_(uint8_t *dst, int16_t block[16], int stride); +; void ff_vp8_idct_add_(uint8_t *dst, int16_t block[16], ptrdiff_t stride); ;----------------------------------------------------------------------------- ; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2) diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c index e5afd49..3e84bed 100644 --- a/libavcodec/x86/vp8dsp_init.c +++ b/libavcodec/x86/vp8dsp_init.c @@ -23,7 +23,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/mem.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/vp8dsp.h" @@ -347,7 +346,7 @@ av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_sse; } - if (EXTERNAL_SSE2(cpu_flags) && (cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { + if (EXTERNAL_SSE2_SLOW(cpu_flags)) { VP8_LUMA_MC_FUNC(0, 16, sse2); VP8_MC_FUNC(1, 8, sse2); VP8_BILINEAR_MC_FUNC(0, 16, sse2); @@ -417,7 +416,7 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_sse; } - if (EXTERNAL_SSE2(cpu_flags) && (cpu_flags & AV_CPU_FLAG_SSE2SLOW)) { + if (EXTERNAL_SSE2_SLOW(cpu_flags)) { c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_sse2; c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_sse2; diff --git a/libavcodec/x86/vp8dsp_loopfilter.asm b/libavcodec/x86/vp8dsp_loopfilter.asm index 5d792e8..9ffd83a 100644 --- a/libavcodec/x86/vp8dsp_loopfilter.asm +++ b/libavcodec/x86/vp8dsp_loopfilter.asm @@ -43,7 +43,7 @@ cextern pb_80 SECTION .text ;----------------------------------------------------------------------------- -; void ff_vp8_h/v_loop_filter_simple_(uint8_t *dst, int stride, int flim); +; void ff_vp8_h/v_loop_filter_simple_(uint8_t *dst, ptrdiff_t stride, int flim); ;----------------------------------------------------------------------------- ; macro called with 7 mm register indexes as argument, and 4 regular registers @@ -429,7 +429,7 @@ INIT_XMM sse4 SIMPLE_LOOPFILTER h, 5 ;----------------------------------------------------------------------------- -; void ff_vp8_h/v_loop_filter_inner_(uint8_t *dst, [uint8_t *v,] int stride, +; void ff_vp8_h/v_loop_filter_inner_(uint8_t *dst, [uint8_t *v,] ptrdiff_t stride, ; int flimE, int flimI, int hev_thr); ;----------------------------------------------------------------------------- @@ -921,7 +921,7 @@ INNER_LOOPFILTER v, 8 INNER_LOOPFILTER h, 8 ;----------------------------------------------------------------------------- -; void ff_vp8_h/v_loop_filter_mbedge_(uint8_t *dst, [uint8_t *v,] int stride, +; void ff_vp8_h/v_loop_filter_mbedge_(uint8_t *dst, [uint8_t *v,] ptrdiff_t stride, ; int flimE, int flimI, int hev_thr); ;----------------------------------------------------------------------------- diff --git a/libavcodec/x86/vp9dsp.asm b/libavcodec/x86/vp9dsp.asm deleted file mode 100644 index 6488f30..0000000 --- a/libavcodec/x86/vp9dsp.asm +++ /dev/null @@ -1,277 +0,0 @@ -;****************************************************************************** -;* VP9 SIMD optimizations -;* -;* Copyright (c) 2013 Ronald S. Bultje -;* -;* This file is part of Libav. -;* -;* Libav is free software; you can redistribute it and/or -;* modify it under the terms of the GNU Lesser General Public -;* License as published by the Free Software Foundation; either -;* version 2.1 of the License, or (at your option) any later version. -;* -;* Libav is distributed in the hope that it will be useful, -;* but WITHOUT ANY WARRANTY; without even the implied warranty of -;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;* Lesser General Public License for more details. -;* -;* You should have received a copy of the GNU Lesser General Public -;* License along with Libav; if not, write to the Free Software -;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -;****************************************************************************** - -%include "libavutil/x86/x86util.asm" - -SECTION_RODATA - -; FIXME share with vp8dsp.asm -pw_256: times 8 dw 256 - -%macro F8_TAPS 8 -times 8 db %1, %2 -times 8 db %3, %4 -times 8 db %5, %6 -times 8 db %7, %8 -%endmacro -; int8_t ff_filters_ssse3[3][15][4][16] -const filters_ssse3 ; smooth - F8_TAPS -3, -1, 32, 64, 38, 1, -3, 0 - F8_TAPS -2, -2, 29, 63, 41, 2, -3, 0 - F8_TAPS -2, -2, 26, 63, 43, 4, -4, 0 - F8_TAPS -2, -3, 24, 62, 46, 5, -4, 0 - F8_TAPS -2, -3, 21, 60, 49, 7, -4, 0 - F8_TAPS -1, -4, 18, 59, 51, 9, -4, 0 - F8_TAPS -1, -4, 16, 57, 53, 12, -4, -1 - F8_TAPS -1, -4, 14, 55, 55, 14, -4, -1 - F8_TAPS -1, -4, 12, 53, 57, 16, -4, -1 - F8_TAPS 0, -4, 9, 51, 59, 18, -4, -1 - F8_TAPS 0, -4, 7, 49, 60, 21, -3, -2 - F8_TAPS 0, -4, 5, 46, 62, 24, -3, -2 - F8_TAPS 0, -4, 4, 43, 63, 26, -2, -2 - F8_TAPS 0, -3, 2, 41, 63, 29, -2, -2 - F8_TAPS 0, -3, 1, 38, 64, 32, -1, -3 - ; regular - F8_TAPS 0, 1, -5, 126, 8, -3, 1, 0 - F8_TAPS -1, 3, -10, 122, 18, -6, 2, 0 - F8_TAPS -1, 4, -13, 118, 27, -9, 3, -1 - F8_TAPS -1, 4, -16, 112, 37, -11, 4, -1 - F8_TAPS -1, 5, -18, 105, 48, -14, 4, -1 - F8_TAPS -1, 5, -19, 97, 58, -16, 5, -1 - F8_TAPS -1, 6, -19, 88, 68, -18, 5, -1 - F8_TAPS -1, 6, -19, 78, 78, -19, 6, -1 - F8_TAPS -1, 5, -18, 68, 88, -19, 6, -1 - F8_TAPS -1, 5, -16, 58, 97, -19, 5, -1 - F8_TAPS -1, 4, -14, 48, 105, -18, 5, -1 - F8_TAPS -1, 4, -11, 37, 112, -16, 4, -1 - F8_TAPS -1, 3, -9, 27, 118, -13, 4, -1 - F8_TAPS 0, 2, -6, 18, 122, -10, 3, -1 - F8_TAPS 0, 1, -3, 8, 126, -5, 1, 0 - ; sharp - F8_TAPS -1, 3, -7, 127, 8, -3, 1, 0 - F8_TAPS -2, 5, -13, 125, 17, -6, 3, -1 - F8_TAPS -3, 7, -17, 121, 27, -10, 5, -2 - F8_TAPS -4, 9, -20, 115, 37, -13, 6, -2 - F8_TAPS -4, 10, -23, 108, 48, -16, 8, -3 - F8_TAPS -4, 10, -24, 100, 59, -19, 9, -3 - F8_TAPS -4, 11, -24, 90, 70, -21, 10, -4 - F8_TAPS -4, 11, -23, 80, 80, -23, 11, -4 - F8_TAPS -4, 10, -21, 70, 90, -24, 11, -4 - F8_TAPS -3, 9, -19, 59, 100, -24, 10, -4 - F8_TAPS -3, 8, -16, 48, 108, -23, 10, -4 - F8_TAPS -2, 6, -13, 37, 115, -20, 9, -4 - F8_TAPS -2, 5, -10, 27, 121, -17, 7, -3 - F8_TAPS -1, 3, -6, 17, 125, -13, 5, -2 - F8_TAPS 0, 1, -3, 8, 127, -7, 3, -1 - -SECTION .text - -%macro filter_h_fn 1 -%assign %%px mmsize/2 -cglobal %1_8tap_1d_h_ %+ %%px, 6, 6, 11, dst, src, dstride, sstride, h, filtery - mova m6, [pw_256] - mova m7, [filteryq+ 0] -%if ARCH_X86_64 && mmsize > 8 - mova m8, [filteryq+16] - mova m9, [filteryq+32] - mova m10, [filteryq+48] -%endif -.loop: - movh m0, [srcq-3] - movh m1, [srcq-2] - movh m2, [srcq-1] - movh m3, [srcq+0] - movh m4, [srcq+1] - movh m5, [srcq+2] - punpcklbw m0, m1 - punpcklbw m2, m3 - movh m1, [srcq+3] - movh m3, [srcq+4] - add srcq, sstrideq - punpcklbw m4, m5 - punpcklbw m1, m3 - pmaddubsw m0, m7 -%if ARCH_X86_64 && mmsize > 8 - pmaddubsw m2, m8 - pmaddubsw m4, m9 - pmaddubsw m1, m10 -%else - pmaddubsw m2, [filteryq+16] - pmaddubsw m4, [filteryq+32] - pmaddubsw m1, [filteryq+48] -%endif - paddw m0, m2 - paddw m4, m1 - paddsw m0, m4 - pmulhrsw m0, m6 -%ifidn %1, avg - movh m1, [dstq] -%endif - packuswb m0, m0 -%ifidn %1, avg - pavgb m0, m1 -%endif - movh [dstq], m0 - add dstq, dstrideq - dec hd - jg .loop - RET -%endmacro - -INIT_MMX ssse3 -filter_h_fn put -filter_h_fn avg - -INIT_XMM ssse3 -filter_h_fn put -filter_h_fn avg - -%macro filter_v_fn 1 -%assign %%px mmsize/2 -%if ARCH_X86_64 -cglobal %1_8tap_1d_v_ %+ %%px, 6, 8, 11, dst, src, dstride, sstride, h, filtery, src4, sstride3 -%else -cglobal %1_8tap_1d_v_ %+ %%px, 4, 7, 11, dst, src, dstride, sstride, filtery, src4, sstride3 - mov filteryq, r5mp -%define hd r4mp -%endif - sub srcq, sstrideq - lea sstride3q, [sstrideq*3] - sub srcq, sstrideq - mova m6, [pw_256] - sub srcq, sstrideq - mova m7, [filteryq+ 0] - lea src4q, [srcq+sstrideq*4] -%if ARCH_X86_64 && mmsize > 8 - mova m8, [filteryq+16] - mova m9, [filteryq+32] - mova m10, [filteryq+48] -%endif -.loop: - ; FIXME maybe reuse loads from previous rows, or just more generally - ; unroll this to prevent multiple loads of the same data? - movh m0, [srcq] - movh m1, [srcq+sstrideq] - movh m2, [srcq+sstrideq*2] - movh m3, [srcq+sstride3q] - movh m4, [src4q] - movh m5, [src4q+sstrideq] - punpcklbw m0, m1 - punpcklbw m2, m3 - movh m1, [src4q+sstrideq*2] - movh m3, [src4q+sstride3q] - add srcq, sstrideq - add src4q, sstrideq - punpcklbw m4, m5 - punpcklbw m1, m3 - pmaddubsw m0, m7 -%if ARCH_X86_64 && mmsize > 8 - pmaddubsw m2, m8 - pmaddubsw m4, m9 - pmaddubsw m1, m10 -%else - pmaddubsw m2, [filteryq+16] - pmaddubsw m4, [filteryq+32] - pmaddubsw m1, [filteryq+48] -%endif - paddw m0, m2 - paddw m4, m1 - paddsw m0, m4 - pmulhrsw m0, m6 -%ifidn %1, avg - movh m1, [dstq] -%endif - packuswb m0, m0 -%ifidn %1, avg - pavgb m0, m1 -%endif - movh [dstq], m0 - add dstq, dstrideq - dec hd - jg .loop - RET -%endmacro - -INIT_MMX ssse3 -filter_v_fn put -filter_v_fn avg - -INIT_XMM ssse3 -filter_v_fn put -filter_v_fn avg - -%macro fpel_fn 6 -%if %2 == 4 -%define %%srcfn movh -%define %%dstfn movh -%else -%define %%srcfn movu -%define %%dstfn mova -%endif - -%if %2 <= 16 -cglobal %1%2, 5, 7, 4, dst, src, dstride, sstride, h, dstride3, sstride3 - lea sstride3q, [sstrideq*3] - lea dstride3q, [dstrideq*3] -%else -cglobal %1%2, 5, 5, 4, dst, src, dstride, sstride, h -%endif -.loop: - %%srcfn m0, [srcq] - %%srcfn m1, [srcq+s%3] - %%srcfn m2, [srcq+s%4] - %%srcfn m3, [srcq+s%5] - lea srcq, [srcq+sstrideq*%6] -%ifidn %1, avg - pavgb m0, [dstq] - pavgb m1, [dstq+d%3] - pavgb m2, [dstq+d%4] - pavgb m3, [dstq+d%5] -%endif - %%dstfn [dstq], m0 - %%dstfn [dstq+d%3], m1 - %%dstfn [dstq+d%4], m2 - %%dstfn [dstq+d%5], m3 - lea dstq, [dstq+dstrideq*%6] - sub hd, %6 - jnz .loop - RET -%endmacro - -%define d16 16 -%define s16 16 -INIT_MMX mmx -fpel_fn put, 4, strideq, strideq*2, stride3q, 4 -fpel_fn put, 8, strideq, strideq*2, stride3q, 4 -INIT_MMX sse -fpel_fn avg, 4, strideq, strideq*2, stride3q, 4 -fpel_fn avg, 8, strideq, strideq*2, stride3q, 4 -INIT_XMM sse -fpel_fn put, 16, strideq, strideq*2, stride3q, 4 -fpel_fn put, 32, mmsize, strideq, strideq+mmsize, 2 -fpel_fn put, 64, mmsize, mmsize*2, mmsize*3, 1 -INIT_XMM sse2 -fpel_fn avg, 16, strideq, strideq*2, stride3q, 4 -fpel_fn avg, 32, mmsize, strideq, strideq+mmsize, 2 -fpel_fn avg, 64, mmsize, mmsize*2, mmsize*3, 1 -%undef s16 -%undef d16 diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index ce58c08..41fa35a 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -24,158 +24,193 @@ #include "libavutil/cpu.h" #include "libavutil/internal.h" #include "libavutil/mem.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/vp9.h" #if HAVE_YASM -#define fpel_func(avg, sz, opt) \ -void ff_ ## avg ## sz ## _ ## opt(uint8_t *dst, const uint8_t *src, \ - ptrdiff_t dst_stride, \ - ptrdiff_t src_stride, \ - int h, int mx, int my) +#define fpel_func(avg, sz, opt) \ +void ff_vp9_ ## avg ## sz ## _ ## opt(uint8_t *dst, const uint8_t *src, \ + ptrdiff_t dst_stride, \ + ptrdiff_t src_stride, \ + int h, int mx, int my) fpel_func(put, 4, mmx); fpel_func(put, 8, mmx); fpel_func(put, 16, sse); fpel_func(put, 32, sse); fpel_func(put, 64, sse); -fpel_func(avg, 4, sse); -fpel_func(avg, 8, sse); +fpel_func(avg, 4, mmxext); +fpel_func(avg, 8, mmxext); fpel_func(avg, 16, sse2); fpel_func(avg, 32, sse2); fpel_func(avg, 64, sse2); +fpel_func(put, 32, avx); +fpel_func(put, 64, avx); +fpel_func(avg, 32, avx2); +fpel_func(avg, 64, avx2); #undef fpel_func -#define mc_func(avg, sz, dir, opt) \ -void \ -ff_ ## avg ## _8tap_1d_ ## dir ## _ ## sz ## _ ## opt(uint8_t *dst, \ - const uint8_t *src, \ - ptrdiff_t dst_stride, \ - ptrdiff_t src_stride, \ - int h, \ - const int8_t (*filter)[16]) - -#define mc_funcs(sz) \ - mc_func(put, sz, h, ssse3); \ - mc_func(avg, sz, h, ssse3); \ - mc_func(put, sz, v, ssse3); \ - mc_func(avg, sz, v, ssse3) - -mc_funcs(4); -mc_funcs(8); +#define mc_func(avg, sz, dir, opt, type, f_sz) \ +void \ +ff_vp9_ ## avg ## _8tap_1d_ ## dir ## _ ## sz ## _ ## opt(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t dst_stride, \ + ptrdiff_t src_stride, \ + int h, \ + const type (*filter)[f_sz]) + +#define mc_funcs(sz, opt, type, f_sz) \ + mc_func(put, sz, h, opt, type, f_sz); \ + mc_func(avg, sz, h, opt, type, f_sz); \ + mc_func(put, sz, v, opt, type, f_sz); \ + mc_func(avg, sz, v, opt, type, f_sz) + +mc_funcs(4, mmxext, int16_t, 8); +mc_funcs(8, sse2, int16_t, 8); +mc_funcs(4, ssse3, int8_t, 32); +mc_funcs(8, ssse3, int8_t, 32); +#if ARCH_X86_64 +mc_funcs(16, ssse3, int8_t, 32); +mc_funcs(32, avx2, int8_t, 32); +#endif #undef mc_funcs #undef mc_func -#define mc_rep_func(avg, sz, hsz, dir, opt) \ +#define mc_rep_func(avg, sz, hsz, dir, opt, type, f_sz) \ static av_always_inline void \ -ff_ ## avg ## _8tap_1d_ ## dir ## _ ## sz ## _ ## opt(uint8_t *dst, \ +ff_vp9_ ## avg ## _8tap_1d_ ## dir ## _ ## sz ## _ ## opt(uint8_t *dst, \ const uint8_t *src, \ ptrdiff_t dst_stride, \ ptrdiff_t src_stride, \ int h, \ - const int8_t (*filter)[16]) \ + const type (*filter)[f_sz]) \ { \ - ff_ ## avg ## _8tap_1d_ ## dir ## _ ## hsz ## _ ## opt(dst, src, \ + ff_vp9_ ## avg ## _8tap_1d_ ## dir ## _ ## hsz ## _ ## opt(dst, src, \ dst_stride, \ src_stride, \ h, \ filter); \ - ff_ ## avg ## _8tap_1d_ ## dir ## _ ## hsz ## _ ## opt(dst + hsz, \ + ff_vp9_ ## avg ## _8tap_1d_ ## dir ## _ ## hsz ## _ ## opt(dst + hsz, \ src + hsz, \ dst_stride, \ src_stride, \ h, filter); \ } -#define mc_rep_funcs(sz, hsz) \ - mc_rep_func(put, sz, hsz, h, ssse3); \ - mc_rep_func(avg, sz, hsz, h, ssse3); \ - mc_rep_func(put, sz, hsz, v, ssse3); \ - mc_rep_func(avg, sz, hsz, v, ssse3) - -mc_rep_funcs(16, 8); -mc_rep_funcs(32, 16); -mc_rep_funcs(64, 32); +#define mc_rep_funcs(sz, hsz, opt, type, f_sz) \ + mc_rep_func(put, sz, hsz, h, opt, type, f_sz); \ + mc_rep_func(avg, sz, hsz, h, opt, type, f_sz); \ + mc_rep_func(put, sz, hsz, v, opt, type, f_sz); \ + mc_rep_func(avg, sz, hsz, v, opt, type, f_sz) + +mc_rep_funcs(16, 8, sse2, int16_t, 8); +#if ARCH_X86_32 +mc_rep_funcs(16, 8, ssse3, int8_t, 32); +#endif +mc_rep_funcs(32, 16, sse2, int16_t, 8); +mc_rep_funcs(32, 16, ssse3, int8_t, 32); +mc_rep_funcs(64, 32, sse2, int16_t, 8); +mc_rep_funcs(64, 32, ssse3, int8_t, 32); +#if ARCH_X86_64 && HAVE_AVX2_EXTERNAL +mc_rep_funcs(64, 32, avx2, int8_t, 32); +#endif #undef mc_rep_funcs #undef mc_rep_func -extern const int8_t ff_filters_ssse3[3][15][4][16]; - -#define filter_8tap_2d_fn(op, sz, f, fname) \ -static void \ -op ## _8tap_ ## fname ## _ ## sz ## hv_ssse3(uint8_t *dst, \ - const uint8_t *src, \ - ptrdiff_t dst_stride, \ - ptrdiff_t src_stride, \ - int h, int mx, int my) \ -{ \ - LOCAL_ALIGNED_16(uint8_t, temp, [71 * 64]); \ - ff_put_8tap_1d_h_ ## sz ## _ssse3(temp, src - 3 * src_stride, \ - 64, src_stride, \ - h + 7, \ - ff_filters_ssse3[f][mx - 1]); \ - ff_ ## op ## _8tap_1d_v_ ## sz ## _ssse3(dst, temp + 3 * 64, \ - dst_stride, 64, \ - h, \ - ff_filters_ssse3[f][my - 1]); \ +extern const int8_t ff_filters_ssse3[3][15][4][32]; +extern const int16_t ff_filters_sse2[3][15][8][8]; + +#define filter_8tap_2d_fn(op, sz, f, f_opt, fname, align, opt) \ +static void \ +op ## _8tap_ ## fname ## _ ## sz ## hv_ ## opt(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t dst_stride, \ + ptrdiff_t src_stride, \ + int h, int mx, int my) \ +{ \ + LOCAL_ALIGNED_ ## align(uint8_t, temp, [71 * 64]); \ + ff_vp9_put_8tap_1d_h_ ## sz ## _ ## opt(temp, src - 3 * src_stride, \ + 64, src_stride, \ + h + 7, \ + ff_filters_ ## f_opt[f][mx - 1]); \ + ff_vp9_ ## op ## _8tap_1d_v_ ## sz ## _ ## opt(dst, temp + 3 * 64, \ + dst_stride, 64, \ + h, \ + ff_filters_ ## f_opt[f][my - 1]); \ } -#define filters_8tap_2d_fn(op, sz) \ - filter_8tap_2d_fn(op, sz, FILTER_8TAP_REGULAR, regular) \ - filter_8tap_2d_fn(op, sz, FILTER_8TAP_SHARP, sharp) \ - filter_8tap_2d_fn(op, sz, FILTER_8TAP_SMOOTH, smooth) - -#define filters_8tap_2d_fn2(op) \ - filters_8tap_2d_fn(op, 64) \ - filters_8tap_2d_fn(op, 32) \ - filters_8tap_2d_fn(op, 16) \ - filters_8tap_2d_fn(op, 8) \ - filters_8tap_2d_fn(op, 4) - -filters_8tap_2d_fn2(put) -filters_8tap_2d_fn2(avg) +#define filters_8tap_2d_fn(op, sz, align, opt, f_opt) \ + filter_8tap_2d_fn(op, sz, FILTER_8TAP_REGULAR, f_opt, regular, align, opt) \ + filter_8tap_2d_fn(op, sz, FILTER_8TAP_SHARP, f_opt, sharp, align, opt) \ + filter_8tap_2d_fn(op, sz, FILTER_8TAP_SMOOTH, f_opt, smooth, align, opt) + +#define filters_8tap_2d_fn2(op, align, opt4, opt8, f_opt) \ + filters_8tap_2d_fn(op, 64, align, opt8, f_opt) \ + filters_8tap_2d_fn(op, 32, align, opt8, f_opt) \ + filters_8tap_2d_fn(op, 16, align, opt8, f_opt) \ + filters_8tap_2d_fn(op, 8, align, opt8, f_opt) \ + filters_8tap_2d_fn(op, 4, align, opt4, f_opt) + + +filters_8tap_2d_fn2(put, 16, mmxext, sse2, sse2) +filters_8tap_2d_fn2(avg, 16, mmxext, sse2, sse2) +filters_8tap_2d_fn2(put, 16, ssse3, ssse3, ssse3) +filters_8tap_2d_fn2(avg, 16, ssse3, ssse3, ssse3) +#if ARCH_X86_64 && HAVE_AVX2_EXTERNAL +filters_8tap_2d_fn(put, 64, 32, avx2, ssse3) +filters_8tap_2d_fn(put, 32, 32, avx2, ssse3) +filters_8tap_2d_fn(avg, 64, 32, avx2, ssse3) +filters_8tap_2d_fn(avg, 32, 32, avx2, ssse3) +#endif #undef filters_8tap_2d_fn2 #undef filters_8tap_2d_fn #undef filter_8tap_2d_fn -#define filter_8tap_1d_fn(op, sz, f, fname, dir, dvar) \ -static void \ -op ## _8tap_ ## fname ## _ ## sz ## dir ## _ssse3(uint8_t *dst, \ - const uint8_t *src, \ - ptrdiff_t dst_stride, \ - ptrdiff_t src_stride, \ - int h, int mx, \ - int my) \ -{ \ - ff_ ## op ## _8tap_1d_ ## dir ## _ ## sz ## _ssse3(dst, src, \ - dst_stride, \ - src_stride, h, \ - ff_filters_ssse3[f][dvar - 1]); \ +#define filter_8tap_1d_fn(op, sz, f, f_opt, fname, dir, dvar, opt) \ +static void \ +op ## _8tap_ ## fname ## _ ## sz ## dir ## _ ## opt(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t dst_stride, \ + ptrdiff_t src_stride, \ + int h, int mx, \ + int my) \ +{ \ + ff_vp9_ ## op ## _8tap_1d_ ## dir ## _ ## sz ## _ ## opt(dst, src, \ + dst_stride, \ + src_stride, h,\ + ff_filters_ ## f_opt[f][dvar - 1]); \ } -#define filters_8tap_1d_fn(op, sz, dir, dvar) \ - filter_8tap_1d_fn(op, sz, FILTER_8TAP_REGULAR, regular, dir, dvar) \ - filter_8tap_1d_fn(op, sz, FILTER_8TAP_SHARP, sharp, dir, dvar) \ - filter_8tap_1d_fn(op, sz, FILTER_8TAP_SMOOTH, smooth, dir, dvar) - -#define filters_8tap_1d_fn2(op, sz) \ - filters_8tap_1d_fn(op, sz, h, mx) \ - filters_8tap_1d_fn(op, sz, v, my) - -#define filters_8tap_1d_fn3(op) \ - filters_8tap_1d_fn2(op, 64) \ - filters_8tap_1d_fn2(op, 32) \ - filters_8tap_1d_fn2(op, 16) \ - filters_8tap_1d_fn2(op, 8) \ - filters_8tap_1d_fn2(op, 4) - -filters_8tap_1d_fn3(put) -filters_8tap_1d_fn3(avg) +#define filters_8tap_1d_fn(op, sz, dir, dvar, opt, f_opt) \ + filter_8tap_1d_fn(op, sz, FILTER_8TAP_REGULAR, f_opt, regular, dir, dvar, opt) \ + filter_8tap_1d_fn(op, sz, FILTER_8TAP_SHARP, f_opt, sharp, dir, dvar, opt) \ + filter_8tap_1d_fn(op, sz, FILTER_8TAP_SMOOTH, f_opt, smooth, dir, dvar, opt) + +#define filters_8tap_1d_fn2(op, sz, opt, f_opt) \ + filters_8tap_1d_fn(op, sz, h, mx, opt, f_opt) \ + filters_8tap_1d_fn(op, sz, v, my, opt, f_opt) + +#define filters_8tap_1d_fn3(op, opt4, opt8, f_opt) \ + filters_8tap_1d_fn2(op, 64, opt8, f_opt) \ + filters_8tap_1d_fn2(op, 32, opt8, f_opt) \ + filters_8tap_1d_fn2(op, 16, opt8, f_opt) \ + filters_8tap_1d_fn2(op, 8, opt8, f_opt) \ + filters_8tap_1d_fn2(op, 4, opt4, f_opt) + +filters_8tap_1d_fn3(put, mmxext, sse2, sse2) +filters_8tap_1d_fn3(avg, mmxext, sse2, sse2) +filters_8tap_1d_fn3(put, ssse3, ssse3, ssse3) +filters_8tap_1d_fn3(avg, ssse3, ssse3, ssse3) +#if ARCH_X86_64 && HAVE_AVX2_EXTERNAL +filters_8tap_1d_fn2(put, 64, avx2, ssse3) +filters_8tap_1d_fn2(put, 32, avx2, ssse3) +filters_8tap_1d_fn2(avg, 64, avx2, ssse3) +filters_8tap_1d_fn2(avg, 32, avx2, ssse3) +#endif #undef filters_8tap_1d_fn #undef filters_8tap_1d_fn2 @@ -193,7 +228,7 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][0][0] = \ dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][0][0] = \ dsp->mc[idx1][FILTER_8TAP_SHARP ][idx2][0][0] = \ - dsp->mc[idx1][FILTER_BILINEAR ][idx2][0][0] = ff_ ## type ## sz ## _ ## opt + dsp->mc[idx1][FILTER_BILINEAR ][idx2][0][0] = ff_vp9_ ## type ## sz ## _ ## opt #define init_subpel1(idx1, idx2, idxh, idxv, sz, dir, type, opt) \ @@ -201,32 +236,45 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][idxh][idxv] = type ## _8tap_regular_ ## sz ## dir ## _ ## opt; \ dsp->mc[idx1][FILTER_8TAP_SHARP][idx2][idxh][idxv] = type ## _8tap_sharp_ ## sz ## dir ## _ ## opt -#define init_subpel2(idx, idxh, idxv, dir, type, opt) \ - init_subpel1(0, idx, idxh, idxv, 64, dir, type, opt); \ - init_subpel1(1, idx, idxh, idxv, 32, dir, type, opt); \ - init_subpel1(2, idx, idxh, idxv, 16, dir, type, opt); \ - init_subpel1(3, idx, idxh, idxv, 8, dir, type, opt); \ - init_subpel1(4, idx, idxh, idxv, 4, dir, type, opt) +#define init_subpel2(idx1, idx2, sz, type, opt) \ + init_subpel1(idx1, idx2, 1, 1, sz, hv, type, opt); \ + init_subpel1(idx1, idx2, 0, 1, sz, v, type, opt); \ + init_subpel1(idx1, idx2, 1, 0, sz, h, type, opt) + +#define init_subpel3_32_64(idx, type, opt) \ + init_subpel2(0, idx, 64, type, opt); \ + init_subpel2(1, idx, 32, type, opt) + +#define init_subpel3_8to64(idx, type, opt) \ + init_subpel3_32_64(idx, type, opt); \ + init_subpel2(2, idx, 16, type, opt); \ + init_subpel2(3, idx, 8, type, opt) -#define init_subpel3(idx, type, opt) \ - init_subpel2(idx, 1, 1, hv, type, opt); \ - init_subpel2(idx, 0, 1, v, type, opt); \ - init_subpel2(idx, 1, 0, h, type, opt) +#define init_subpel3(idx, type, opt) \ + init_subpel3_8to64(idx, type, opt); \ + init_subpel2(4, idx, 4, type, opt) if (EXTERNAL_MMX(cpu_flags)) { init_fpel(4, 0, 4, put, mmx); init_fpel(3, 0, 8, put, mmx); } + if (EXTERNAL_MMXEXT(cpu_flags)) { + init_subpel2(4, 0, 4, put, mmxext); + init_subpel2(4, 1, 4, avg, mmxext); + init_fpel(4, 1, 4, avg, mmxext); + init_fpel(3, 1, 8, avg, mmxext); + } + if (EXTERNAL_SSE(cpu_flags)) { init_fpel(2, 0, 16, put, sse); init_fpel(1, 0, 32, put, sse); init_fpel(0, 0, 64, put, sse); - init_fpel(4, 1, 4, avg, sse); - init_fpel(3, 1, 8, avg, sse); } if (EXTERNAL_SSE2(cpu_flags)) { + init_subpel3_8to64(0, put, sse2); + init_subpel3_8to64(1, avg, sse2); init_fpel(2, 1, 16, avg, sse2); init_fpel(1, 1, 32, avg, sse2); init_fpel(0, 1, 64, avg, sse2); @@ -237,6 +285,21 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) init_subpel3(1, avg, ssse3); } + if (EXTERNAL_AVX(cpu_flags)) { + init_fpel(1, 0, 32, put, avx); + init_fpel(0, 0, 64, put, avx); + } + + if (EXTERNAL_AVX2(cpu_flags)) { + init_fpel(1, 1, 32, avg, avx2); + init_fpel(0, 1, 64, avg, avx2); + +#if ARCH_X86_64 && HAVE_AVX2_EXTERNAL + init_subpel3_32_64(0, put, avx2); + init_subpel3_32_64(1, avg, avx2); +#endif /* ARCH_X86_64 && HAVE_AVX2_EXTERNAL */ + } + #undef init_fpel #undef init_subpel1 #undef init_subpel2 diff --git a/libavcodec/x86/vp9mc.asm b/libavcodec/x86/vp9mc.asm new file mode 100644 index 0000000..15e93ea --- /dev/null +++ b/libavcodec/x86/vp9mc.asm @@ -0,0 +1,622 @@ +;****************************************************************************** +;* VP9 motion compensation SIMD optimizations +;* +;* Copyright (c) 2013 Ronald S. Bultje +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +cextern pw_256 +cextern pw_64 + +%macro F8_SSSE3_TAPS 8 +times 16 db %1, %2 +times 16 db %3, %4 +times 16 db %5, %6 +times 16 db %7, %8 +%endmacro + +%macro F8_SSE2_TAPS 8 +times 8 dw %1 +times 8 dw %2 +times 8 dw %3 +times 8 dw %4 +times 8 dw %5 +times 8 dw %6 +times 8 dw %7 +times 8 dw %8 +%endmacro + +%macro FILTER 1 +const filters_%1 ; smooth + F8_TAPS -3, -1, 32, 64, 38, 1, -3, 0 + F8_TAPS -2, -2, 29, 63, 41, 2, -3, 0 + F8_TAPS -2, -2, 26, 63, 43, 4, -4, 0 + F8_TAPS -2, -3, 24, 62, 46, 5, -4, 0 + F8_TAPS -2, -3, 21, 60, 49, 7, -4, 0 + F8_TAPS -1, -4, 18, 59, 51, 9, -4, 0 + F8_TAPS -1, -4, 16, 57, 53, 12, -4, -1 + F8_TAPS -1, -4, 14, 55, 55, 14, -4, -1 + F8_TAPS -1, -4, 12, 53, 57, 16, -4, -1 + F8_TAPS 0, -4, 9, 51, 59, 18, -4, -1 + F8_TAPS 0, -4, 7, 49, 60, 21, -3, -2 + F8_TAPS 0, -4, 5, 46, 62, 24, -3, -2 + F8_TAPS 0, -4, 4, 43, 63, 26, -2, -2 + F8_TAPS 0, -3, 2, 41, 63, 29, -2, -2 + F8_TAPS 0, -3, 1, 38, 64, 32, -1, -3 + ; regular + F8_TAPS 0, 1, -5, 126, 8, -3, 1, 0 + F8_TAPS -1, 3, -10, 122, 18, -6, 2, 0 + F8_TAPS -1, 4, -13, 118, 27, -9, 3, -1 + F8_TAPS -1, 4, -16, 112, 37, -11, 4, -1 + F8_TAPS -1, 5, -18, 105, 48, -14, 4, -1 + F8_TAPS -1, 5, -19, 97, 58, -16, 5, -1 + F8_TAPS -1, 6, -19, 88, 68, -18, 5, -1 + F8_TAPS -1, 6, -19, 78, 78, -19, 6, -1 + F8_TAPS -1, 5, -18, 68, 88, -19, 6, -1 + F8_TAPS -1, 5, -16, 58, 97, -19, 5, -1 + F8_TAPS -1, 4, -14, 48, 105, -18, 5, -1 + F8_TAPS -1, 4, -11, 37, 112, -16, 4, -1 + F8_TAPS -1, 3, -9, 27, 118, -13, 4, -1 + F8_TAPS 0, 2, -6, 18, 122, -10, 3, -1 + F8_TAPS 0, 1, -3, 8, 126, -5, 1, 0 + ; sharp + F8_TAPS -1, 3, -7, 127, 8, -3, 1, 0 + F8_TAPS -2, 5, -13, 125, 17, -6, 3, -1 + F8_TAPS -3, 7, -17, 121, 27, -10, 5, -2 + F8_TAPS -4, 9, -20, 115, 37, -13, 6, -2 + F8_TAPS -4, 10, -23, 108, 48, -16, 8, -3 + F8_TAPS -4, 10, -24, 100, 59, -19, 9, -3 + F8_TAPS -4, 11, -24, 90, 70, -21, 10, -4 + F8_TAPS -4, 11, -23, 80, 80, -23, 11, -4 + F8_TAPS -4, 10, -21, 70, 90, -24, 11, -4 + F8_TAPS -3, 9, -19, 59, 100, -24, 10, -4 + F8_TAPS -3, 8, -16, 48, 108, -23, 10, -4 + F8_TAPS -2, 6, -13, 37, 115, -20, 9, -4 + F8_TAPS -2, 5, -10, 27, 121, -17, 7, -3 + F8_TAPS -1, 3, -6, 17, 125, -13, 5, -2 + F8_TAPS 0, 1, -3, 8, 127, -7, 3, -1 +%endmacro + +%define F8_TAPS F8_SSSE3_TAPS +; int8_t ff_filters_ssse3[3][15][4][32] +FILTER ssse3 +%define F8_TAPS F8_SSE2_TAPS +; int16_t ff_filters_sse2[3][15][8][8] +FILTER sse2 + +SECTION .text + +%macro filter_sse2_h_fn 1 +%assign %%px mmsize/2 +cglobal vp9_%1_8tap_1d_h_ %+ %%px, 6, 6, 15, dst, src, dstride, sstride, h, filtery + pxor m5, m5 + mova m6, [pw_64] + mova m7, [filteryq+ 0] +%if ARCH_X86_64 && mmsize > 8 + mova m8, [filteryq+ 16] + mova m9, [filteryq+ 32] + mova m10, [filteryq+ 48] + mova m11, [filteryq+ 64] + mova m12, [filteryq+ 80] + mova m13, [filteryq+ 96] + mova m14, [filteryq+112] +%endif +.loop: + movh m0, [srcq-3] + movh m1, [srcq-2] + movh m2, [srcq-1] + movh m3, [srcq+0] + movh m4, [srcq+1] + punpcklbw m0, m5 + punpcklbw m1, m5 + punpcklbw m2, m5 + punpcklbw m3, m5 + punpcklbw m4, m5 + pmullw m0, m7 +%if ARCH_X86_64 && mmsize > 8 + pmullw m1, m8 + pmullw m2, m9 + pmullw m3, m10 + pmullw m4, m11 +%else + pmullw m1, [filteryq+ 16] + pmullw m2, [filteryq+ 32] + pmullw m3, [filteryq+ 48] + pmullw m4, [filteryq+ 64] +%endif + paddw m0, m1 + paddw m2, m3 + paddw m0, m4 + movh m1, [srcq+2] + movh m3, [srcq+3] + movh m4, [srcq+4] + add srcq, sstrideq + punpcklbw m1, m5 + punpcklbw m3, m5 + punpcklbw m4, m5 +%if ARCH_X86_64 && mmsize > 8 + pmullw m1, m12 + pmullw m3, m13 + pmullw m4, m14 +%else + pmullw m1, [filteryq+ 80] + pmullw m3, [filteryq+ 96] + pmullw m4, [filteryq+112] +%endif + paddw m0, m1 + paddw m3, m4 + paddw m0, m6 + paddw m2, m3 + paddsw m0, m2 + psraw m0, 7 +%ifidn %1, avg + movh m1, [dstq] +%endif + packuswb m0, m0 +%ifidn %1, avg + pavgb m0, m1 +%endif + movh [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_MMX mmxext +filter_sse2_h_fn put +filter_sse2_h_fn avg + +INIT_XMM sse2 +filter_sse2_h_fn put +filter_sse2_h_fn avg + +%macro filter_h_fn 1 +%assign %%px mmsize/2 +cglobal vp9_%1_8tap_1d_h_ %+ %%px, 6, 6, 11, dst, src, dstride, sstride, h, filtery + mova m6, [pw_256] + mova m7, [filteryq+ 0] +%if ARCH_X86_64 && mmsize > 8 + mova m8, [filteryq+32] + mova m9, [filteryq+64] + mova m10, [filteryq+96] +%endif +.loop: + movh m0, [srcq-3] + movh m1, [srcq-2] + movh m2, [srcq-1] + movh m3, [srcq+0] + movh m4, [srcq+1] + movh m5, [srcq+2] + punpcklbw m0, m1 + punpcklbw m2, m3 + movh m1, [srcq+3] + movh m3, [srcq+4] + add srcq, sstrideq + punpcklbw m4, m5 + punpcklbw m1, m3 + pmaddubsw m0, m7 +%if ARCH_X86_64 && mmsize > 8 + pmaddubsw m2, m8 + pmaddubsw m4, m9 + pmaddubsw m1, m10 +%else + pmaddubsw m2, [filteryq+32] + pmaddubsw m4, [filteryq+64] + pmaddubsw m1, [filteryq+96] +%endif + paddw m0, m4 + paddw m2, m1 + paddsw m0, m2 + pmulhrsw m0, m6 +%ifidn %1, avg + movh m1, [dstq] +%endif + packuswb m0, m0 +%ifidn %1, avg + pavgb m0, m1 +%endif + movh [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_MMX ssse3 +filter_h_fn put +filter_h_fn avg + +INIT_XMM ssse3 +filter_h_fn put +filter_h_fn avg + +%if ARCH_X86_64 +%macro filter_hx2_fn 1 +%assign %%px mmsize +cglobal vp9_%1_8tap_1d_h_ %+ %%px, 6, 6, 14, dst, src, dstride, sstride, h, filtery + mova m13, [pw_256] + mova m8, [filteryq+ 0] + mova m9, [filteryq+32] + mova m10, [filteryq+64] + mova m11, [filteryq+96] +.loop: + movu m0, [srcq-3] + movu m1, [srcq-2] + movu m2, [srcq-1] + movu m3, [srcq+0] + movu m4, [srcq+1] + movu m5, [srcq+2] + movu m6, [srcq+3] + movu m7, [srcq+4] + add srcq, sstrideq + SBUTTERFLY bw, 0, 1, 12 + SBUTTERFLY bw, 2, 3, 12 + SBUTTERFLY bw, 4, 5, 12 + SBUTTERFLY bw, 6, 7, 12 + pmaddubsw m0, m8 + pmaddubsw m1, m8 + pmaddubsw m2, m9 + pmaddubsw m3, m9 + pmaddubsw m4, m10 + pmaddubsw m5, m10 + pmaddubsw m6, m11 + pmaddubsw m7, m11 + paddw m0, m4 + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + paddsw m0, m2 + paddsw m1, m3 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 +%ifidn %1, avg + pavgb m0, [dstq] +%endif + mova [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_XMM ssse3 +filter_hx2_fn put +filter_hx2_fn avg + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +filter_hx2_fn put +filter_hx2_fn avg +%endif + +%endif ; ARCH_X86_64 + +%macro filter_sse2_v_fn 1 +%assign %%px mmsize/2 +%if ARCH_X86_64 +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 6, 8, 15, dst, src, dstride, sstride, h, filtery, src4, sstride3 +%else +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 4, 7, 15, dst, src, dstride, sstride, filtery, src4, sstride3 + mov filteryq, r5mp +%define hd r4mp +%endif + pxor m5, m5 + mova m6, [pw_64] + lea sstride3q, [sstrideq*3] + lea src4q, [srcq+sstrideq] + sub srcq, sstride3q + mova m7, [filteryq+ 0] +%if ARCH_X86_64 && mmsize > 8 + mova m8, [filteryq+ 16] + mova m9, [filteryq+ 32] + mova m10, [filteryq+ 48] + mova m11, [filteryq+ 64] + mova m12, [filteryq+ 80] + mova m13, [filteryq+ 96] + mova m14, [filteryq+112] +%endif +.loop: + ; FIXME maybe reuse loads from previous rows, or just + ; more generally unroll this to prevent multiple loads of + ; the same data? + movh m0, [srcq] + movh m1, [srcq+sstrideq] + movh m2, [srcq+sstrideq*2] + movh m3, [srcq+sstride3q] + add srcq, sstrideq + movh m4, [src4q] + punpcklbw m0, m5 + punpcklbw m1, m5 + punpcklbw m2, m5 + punpcklbw m3, m5 + punpcklbw m4, m5 + pmullw m0, m7 +%if ARCH_X86_64 && mmsize > 8 + pmullw m1, m8 + pmullw m2, m9 + pmullw m3, m10 + pmullw m4, m11 +%else + pmullw m1, [filteryq+ 16] + pmullw m2, [filteryq+ 32] + pmullw m3, [filteryq+ 48] + pmullw m4, [filteryq+ 64] +%endif + paddw m0, m1 + paddw m2, m3 + paddw m0, m4 + movh m1, [src4q+sstrideq] + movh m3, [src4q+sstrideq*2] + movh m4, [src4q+sstride3q] + add src4q, sstrideq + punpcklbw m1, m5 + punpcklbw m3, m5 + punpcklbw m4, m5 +%if ARCH_X86_64 && mmsize > 8 + pmullw m1, m12 + pmullw m3, m13 + pmullw m4, m14 +%else + pmullw m1, [filteryq+ 80] + pmullw m3, [filteryq+ 96] + pmullw m4, [filteryq+112] +%endif + paddw m0, m1 + paddw m3, m4 + paddw m0, m6 + paddw m2, m3 + paddsw m0, m2 + psraw m0, 7 +%ifidn %1, avg + movh m1, [dstq] +%endif + packuswb m0, m0 +%ifidn %1, avg + pavgb m0, m1 +%endif + movh [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_MMX mmxext +filter_sse2_v_fn put +filter_sse2_v_fn avg + +INIT_XMM sse2 +filter_sse2_v_fn put +filter_sse2_v_fn avg + +%macro filter_v_fn 1 +%assign %%px mmsize/2 +%if ARCH_X86_64 +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 6, 8, 11, dst, src, dstride, sstride, h, filtery, src4, sstride3 +%else +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 4, 7, 11, dst, src, dstride, sstride, filtery, src4, sstride3 + mov filteryq, r5mp +%define hd r4mp +%endif + mova m6, [pw_256] + lea sstride3q, [sstrideq*3] + lea src4q, [srcq+sstrideq] + sub srcq, sstride3q + mova m7, [filteryq+ 0] +%if ARCH_X86_64 && mmsize > 8 + mova m8, [filteryq+32] + mova m9, [filteryq+64] + mova m10, [filteryq+96] +%endif +.loop: + ; FIXME maybe reuse loads from previous rows, or just more generally + ; unroll this to prevent multiple loads of the same data? + movh m0, [srcq] + movh m1, [srcq+sstrideq] + movh m2, [srcq+sstrideq*2] + movh m3, [srcq+sstride3q] + movh m4, [src4q] + movh m5, [src4q+sstrideq] + punpcklbw m0, m1 + punpcklbw m2, m3 + movh m1, [src4q+sstrideq*2] + movh m3, [src4q+sstride3q] + add srcq, sstrideq + add src4q, sstrideq + punpcklbw m4, m5 + punpcklbw m1, m3 + pmaddubsw m0, m7 +%if ARCH_X86_64 && mmsize > 8 + pmaddubsw m2, m8 + pmaddubsw m4, m9 + pmaddubsw m1, m10 +%else + pmaddubsw m2, [filteryq+32] + pmaddubsw m4, [filteryq+64] + pmaddubsw m1, [filteryq+96] +%endif + paddw m0, m4 + paddw m2, m1 + paddsw m0, m2 + pmulhrsw m0, m6 +%ifidn %1, avg + movh m1, [dstq] +%endif + packuswb m0, m0 +%ifidn %1, avg + pavgb m0, m1 +%endif + movh [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_MMX ssse3 +filter_v_fn put +filter_v_fn avg + +INIT_XMM ssse3 +filter_v_fn put +filter_v_fn avg + +%if ARCH_X86_64 + +%macro filter_vx2_fn 1 +%assign %%px mmsize +cglobal vp9_%1_8tap_1d_v_ %+ %%px, 6, 8, 14, dst, src, dstride, sstride, h, filtery, src4, sstride3 + mova m13, [pw_256] + lea sstride3q, [sstrideq*3] + lea src4q, [srcq+sstrideq] + sub srcq, sstride3q + mova m8, [filteryq+ 0] + mova m9, [filteryq+32] + mova m10, [filteryq+64] + mova m11, [filteryq+96] +.loop: + ; FIXME maybe reuse loads from previous rows, or just + ; more generally unroll this to prevent multiple loads of + ; the same data? + movu m0, [srcq] + movu m1, [srcq+sstrideq] + movu m2, [srcq+sstrideq*2] + movu m3, [srcq+sstride3q] + movu m4, [src4q] + movu m5, [src4q+sstrideq] + movu m6, [src4q+sstrideq*2] + movu m7, [src4q+sstride3q] + add srcq, sstrideq + add src4q, sstrideq + SBUTTERFLY bw, 0, 1, 12 + SBUTTERFLY bw, 2, 3, 12 + SBUTTERFLY bw, 4, 5, 12 + SBUTTERFLY bw, 6, 7, 12 + pmaddubsw m0, m8 + pmaddubsw m1, m8 + pmaddubsw m2, m9 + pmaddubsw m3, m9 + pmaddubsw m4, m10 + pmaddubsw m5, m10 + pmaddubsw m6, m11 + pmaddubsw m7, m11 + paddw m0, m4 + paddw m1, m5 + paddw m2, m6 + paddw m3, m7 + paddsw m0, m2 + paddsw m1, m3 + pmulhrsw m0, m13 + pmulhrsw m1, m13 + packuswb m0, m1 +%ifidn %1, avg + pavgb m0, [dstq] +%endif + mova [dstq], m0 + add dstq, dstrideq + dec hd + jg .loop + RET +%endmacro + +INIT_XMM ssse3 +filter_vx2_fn put +filter_vx2_fn avg + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +filter_vx2_fn put +filter_vx2_fn avg +%endif + +%endif ; ARCH_X86_64 + +%macro fpel_fn 6 +%if %2 == 4 +%define %%srcfn movh +%define %%dstfn movh +%else +%define %%srcfn movu +%define %%dstfn mova +%endif + +%if %2 <= mmsize +cglobal vp9_%1%2, 5, 7, 4, dst, src, dstride, sstride, h, dstride3, sstride3 + lea sstride3q, [sstrideq*3] + lea dstride3q, [dstrideq*3] +%else +cglobal vp9_%1%2, 5, 5, 4, dst, src, dstride, sstride, h +%endif +.loop: + %%srcfn m0, [srcq] + %%srcfn m1, [srcq+s%3] + %%srcfn m2, [srcq+s%4] + %%srcfn m3, [srcq+s%5] + lea srcq, [srcq+sstrideq*%6] +%ifidn %1, avg + pavgb m0, [dstq] + pavgb m1, [dstq+d%3] + pavgb m2, [dstq+d%4] + pavgb m3, [dstq+d%5] +%endif + %%dstfn [dstq], m0 + %%dstfn [dstq+d%3], m1 + %%dstfn [dstq+d%4], m2 + %%dstfn [dstq+d%5], m3 + lea dstq, [dstq+dstrideq*%6] + sub hd, %6 + jnz .loop + RET +%endmacro + +%define d16 16 +%define s16 16 +%define d32 32 +%define s32 32 +INIT_MMX mmx +fpel_fn put, 4, strideq, strideq*2, stride3q, 4 +fpel_fn put, 8, strideq, strideq*2, stride3q, 4 +INIT_MMX mmxext +fpel_fn avg, 4, strideq, strideq*2, stride3q, 4 +fpel_fn avg, 8, strideq, strideq*2, stride3q, 4 +INIT_XMM sse +fpel_fn put, 16, strideq, strideq*2, stride3q, 4 +fpel_fn put, 32, mmsize, strideq, strideq+mmsize, 2 +fpel_fn put, 64, mmsize, mmsize*2, mmsize*3, 1 +INIT_XMM sse2 +fpel_fn avg, 16, strideq, strideq*2, stride3q, 4 +fpel_fn avg, 32, mmsize, strideq, strideq+mmsize, 2 +fpel_fn avg, 64, mmsize, mmsize*2, mmsize*3, 1 +INIT_YMM avx +fpel_fn put, 32, strideq, strideq*2, stride3q, 4 +fpel_fn put, 64, mmsize, strideq, strideq+mmsize, 2 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +fpel_fn avg, 32, strideq, strideq*2, stride3q, 4 +fpel_fn avg, 64, mmsize, strideq, strideq+mmsize, 2 +%endif +%undef s16 +%undef d16 +%undef s32 +%undef d32 diff --git a/libavcodec/x86/w64xmmtest.c b/libavcodec/x86/w64xmmtest.c index 2f064ca..400dc4d 100644 --- a/libavcodec/x86/w64xmmtest.c +++ b/libavcodec/x86/w64xmmtest.c @@ -23,7 +23,7 @@ #include "libavutil/x86/w64xmmtest.h" wrap(avcodec_open2(AVCodecContext *avctx, - AVCodec *codec, + const AVCodec *codec, AVDictionary **options)) { testxmmclobbers(avcodec_open2, avctx, codec, options); diff --git a/libavcodec/x86/idct_xvid.h b/libavcodec/x86/xvididct.h similarity index 60% rename from libavcodec/x86/idct_xvid.h rename to libavcodec/x86/xvididct.h index aea28ba..13a4e85 100644 --- a/libavcodec/x86/idct_xvid.h +++ b/libavcodec/x86/xvididct.h @@ -23,21 +23,21 @@ * header for Xvid IDCT functions */ -#ifndef AVCODEC_X86_IDCT_XVID_H -#define AVCODEC_X86_IDCT_XVID_H +#ifndef AVCODEC_X86_XVIDIDCT_H +#define AVCODEC_X86_XVIDIDCT_H #include -void ff_idct_xvid_mmx(short *block); -void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, int16_t *block); -void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, int16_t *block); +void ff_xvid_idct_mmx(short *block); +void ff_xvid_idct_mmx_put(uint8_t *dest, int line_size, int16_t *block); +void ff_xvid_idct_mmx_add(uint8_t *dest, int line_size, int16_t *block); -void ff_idct_xvid_mmxext(short *block); -void ff_idct_xvid_mmxext_put(uint8_t *dest, int line_size, int16_t *block); -void ff_idct_xvid_mmxext_add(uint8_t *dest, int line_size, int16_t *block); +void ff_xvid_idct_mmxext(short *block); +void ff_xvid_idct_mmxext_put(uint8_t *dest, int line_size, int16_t *block); +void ff_xvid_idct_mmxext_add(uint8_t *dest, int line_size, int16_t *block); -void ff_idct_xvid_sse2(short *block); -void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block); -void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block); +void ff_xvid_idct_sse2(short *block); +void ff_xvid_idct_sse2_put(uint8_t *dest, int line_size, short *block); +void ff_xvid_idct_sse2_add(uint8_t *dest, int line_size, short *block); -#endif /* AVCODEC_X86_IDCT_XVID_H */ +#endif /* AVCODEC_X86_XVIDIDCT_H */ diff --git a/libavcodec/x86/xvididct_init.c b/libavcodec/x86/xvididct_init.c index d5d8ac9..e4f7345 100644 --- a/libavcodec/x86/xvididct_init.c +++ b/libavcodec/x86/xvididct_init.c @@ -22,31 +22,38 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/idctdsp.h" #include "libavcodec/xvididct.h" -#include "idct_xvid.h" + #include "idctdsp.h" +#include "xvididct.h" -av_cold void ff_xvididct_init_x86(IDCTDSPContext *c) +av_cold void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) { int cpu_flags = av_get_cpu_flags(); + if (high_bit_depth || + !(avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_XVID)) + return; + if (INLINE_MMX(cpu_flags)) { - c->idct_put = ff_idct_xvid_mmx_put; - c->idct_add = ff_idct_xvid_mmx_add; - c->idct = ff_idct_xvid_mmx; + c->idct_put = ff_xvid_idct_mmx_put; + c->idct_add = ff_xvid_idct_mmx_add; + c->idct = ff_xvid_idct_mmx; c->perm_type = FF_IDCT_PERM_NONE; } if (INLINE_MMXEXT(cpu_flags)) { - c->idct_put = ff_idct_xvid_mmxext_put; - c->idct_add = ff_idct_xvid_mmxext_add; - c->idct = ff_idct_xvid_mmxext; + c->idct_put = ff_xvid_idct_mmxext_put; + c->idct_add = ff_xvid_idct_mmxext_add; + c->idct = ff_xvid_idct_mmxext; c->perm_type = FF_IDCT_PERM_NONE; } if (INLINE_SSE2(cpu_flags)) { - c->idct_put = ff_idct_xvid_sse2_put; - c->idct_add = ff_idct_xvid_sse2_add; - c->idct = ff_idct_xvid_sse2; + c->idct_put = ff_xvid_idct_sse2_put; + c->idct_add = ff_xvid_idct_sse2_add; + c->idct = ff_xvid_idct_sse2; c->perm_type = FF_IDCT_PERM_SSE2; } } diff --git a/libavcodec/x86/xvididct_mmx.c b/libavcodec/x86/xvididct_mmx.c new file mode 100644 index 0000000..e371142 --- /dev/null +++ b/libavcodec/x86/xvididct_mmx.c @@ -0,0 +1,548 @@ +/* + * XVID MPEG-4 VIDEO CODEC + * - MMX and XMM forward discrete cosine transform - + * + * Copyright(C) 2001 Peter Ross + * + * Originally provided by Intel at AP-922 + * http://developer.intel.com/vtune/cbts/strmsimd/922down.htm + * (See more app notes at http://developer.intel.com/vtune/cbts/strmsimd/appnotes.htm) + * but in a limited edition. + * New macro implements a column part for precise iDCT + * The routine precision now satisfies IEEE standard 1180-1990. + * + * Copyright(C) 2000-2001 Peter Gubanov + * Rounding trick Copyright(C) 2000 Michel Lespinasse + * + * http://www.elecard.com/peter/idct.html + * http://www.linuxvideo.org/mpeg2dec/ + * + * These examples contain code fragments for first stage iDCT 8x8 + * (for rows) and first stage DCT 8x8 (for columns) + * + * conversion to gcc syntax by Michael Niedermayer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#include "libavutil/mem.h" + +#include "libavcodec/avcodec.h" + +#include "idctdsp.h" +#include "xvididct.h" + +#if HAVE_MMX_INLINE + +// ----------------------------------------------------------------------------- +// Various memory constants (trigonometric values or rounding values) +// ----------------------------------------------------------------------------- + +DECLARE_ALIGNED(8, static const int16_t, tg_1_16)[4 * 4] = { + 13036, 13036, 13036, 13036, // tg * (2 << 16) + 0.5 + 27146, 27146, 27146, 27146, // tg * (2 << 16) + 0.5 + -21746, -21746, -21746, -21746, // tg * (2 << 16) + 0.5 + 23170, 23170, 23170, 23170 +}; // cos * (2 << 15) + 0.5 + +DECLARE_ALIGNED(8, static const int32_t, rounder_0)[2 * 8] = { + 65536, 65536, + 3597, 3597, + 2260, 2260, + 1203, 1203, + 0, 0, + 120, 120, + 512, 512, + 512, 512 +}; + +// ----------------------------------------------------------------------------- +// +// The first stage iDCT 8x8 - inverse DCTs of rows +// +// ----------------------------------------------------------------------------- +// The 8-point inverse DCT direct algorithm +// ----------------------------------------------------------------------------- +// +// static const short w[32] = { +// FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16), +// FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16), +// FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16), +// FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16), +// FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16), +// FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16), +// FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16), +// FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) }; +// +// #define DCT_8_INV_ROW(x, y) +// { +// int a0, a1, a2, a3, b0, b1, b2, b3; +// +// a0 = x[0] * w[0] + x[2] * w[1] + x[4] * w[2] + x[6] * w[3]; +// a1 = x[0] * w[4] + x[2] * w[5] + x[4] * w[6] + x[6] * w[7]; +// a2 = x[0] * w[8] + x[2] * w[9] + x[4] * w[10] + x[6] * w[11]; +// a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15]; +// b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19]; +// b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23]; +// b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27]; +// b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31]; +// +// y[0] = SHIFT_ROUND(a0 + b0); +// y[1] = SHIFT_ROUND(a1 + b1); +// y[2] = SHIFT_ROUND(a2 + b2); +// y[3] = SHIFT_ROUND(a3 + b3); +// y[4] = SHIFT_ROUND(a3 - b3); +// y[5] = SHIFT_ROUND(a2 - b2); +// y[6] = SHIFT_ROUND(a1 - b1); +// y[7] = SHIFT_ROUND(a0 - b0); +// } +// +// ----------------------------------------------------------------------------- +// +// In this implementation the outputs of the iDCT-1D are multiplied +// for rows 0,4 - by cos_4_16, +// for rows 1,7 - by cos_1_16, +// for rows 2,6 - by cos_2_16, +// for rows 3,5 - by cos_3_16 +// and are shifted to the left for better accuracy. +// +// For the constants used, +// FIX(float_const) = (short) (float_const * (1 << 15) + 0.5) +// +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Tables for mmx processors +// ----------------------------------------------------------------------------- + +// Table for rows 0,4 - constants are multiplied by cos_4_16 +DECLARE_ALIGNED(8, static const int16_t, tab_i_04_mmx)[32 * 4] = { + 16384, 16384, 16384, -16384, // movq-> w06 w04 w02 w00 + 21407, 8867, 8867, -21407, // w07 w05 w03 w01 + 16384, -16384, 16384, 16384, // w14 w12 w10 w08 + -8867, 21407, -21407, -8867, // w15 w13 w11 w09 + 22725, 12873, 19266, -22725, // w22 w20 w18 w16 + 19266, 4520, -4520, -12873, // w23 w21 w19 w17 + 12873, 4520, 4520, 19266, // w30 w28 w26 w24 + -22725, 19266, -12873, -22725, // w31 w29 w27 w25 +// Table for rows 1,7 - constants are multiplied by cos_1_16 + 22725, 22725, 22725, -22725, // movq-> w06 w04 w02 w00 + 29692, 12299, 12299, -29692, // w07 w05 w03 w01 + 22725, -22725, 22725, 22725, // w14 w12 w10 w08 + -12299, 29692, -29692, -12299, // w15 w13 w11 w09 + 31521, 17855, 26722, -31521, // w22 w20 w18 w16 + 26722, 6270, -6270, -17855, // w23 w21 w19 w17 + 17855, 6270, 6270, 26722, // w30 w28 w26 w24 + -31521, 26722, -17855, -31521, // w31 w29 w27 w25 +// Table for rows 2,6 - constants are multiplied by cos_2_16 + 21407, 21407, 21407, -21407, // movq-> w06 w04 w02 w00 + 27969, 11585, 11585, -27969, // w07 w05 w03 w01 + 21407, -21407, 21407, 21407, // w14 w12 w10 w08 + -11585, 27969, -27969, -11585, // w15 w13 w11 w09 + 29692, 16819, 25172, -29692, // w22 w20 w18 w16 + 25172, 5906, -5906, -16819, // w23 w21 w19 w17 + 16819, 5906, 5906, 25172, // w30 w28 w26 w24 + -29692, 25172, -16819, -29692, // w31 w29 w27 w25 +// Table for rows 3,5 - constants are multiplied by cos_3_16 + 19266, 19266, 19266, -19266, // movq-> w06 w04 w02 w00 + 25172, 10426, 10426, -25172, // w07 w05 w03 w01 + 19266, -19266, 19266, 19266, // w14 w12 w10 w08 + -10426, 25172, -25172, -10426, // w15 w13 w11 w09 + 26722, 15137, 22654, -26722, // w22 w20 w18 w16 + 22654, 5315, -5315, -15137, // w23 w21 w19 w17 + 15137, 5315, 5315, 22654, // w30 w28 w26 w24 + -26722, 22654, -15137, -26722, // w31 w29 w27 w25 +}; +// ----------------------------------------------------------------------------- +// Tables for xmm processors +// ----------------------------------------------------------------------------- + +// %3 for rows 0,4 - constants are multiplied by cos_4_16 +DECLARE_ALIGNED(8, static const int16_t, tab_i_04_xmm)[32 * 4] = { + 16384, 21407, 16384, 8867, // movq-> w05 w04 w01 w00 + 16384, 8867, -16384, -21407, // w07 w06 w03 w02 + 16384, -8867, 16384, -21407, // w13 w12 w09 w08 + -16384, 21407, 16384, -8867, // w15 w14 w11 w10 + 22725, 19266, 19266, -4520, // w21 w20 w17 w16 + 12873, 4520, -22725, -12873, // w23 w22 w19 w18 + 12873, -22725, 4520, -12873, // w29 w28 w25 w24 + 4520, 19266, 19266, -22725, // w31 w30 w27 w26 +// %3 for rows 1,7 - constants are multiplied by cos_1_16 + 22725, 29692, 22725, 12299, // movq-> w05 w04 w01 w00 + 22725, 12299, -22725, -29692, // w07 w06 w03 w02 + 22725, -12299, 22725, -29692, // w13 w12 w09 w08 + -22725, 29692, 22725, -12299, // w15 w14 w11 w10 + 31521, 26722, 26722, -6270, // w21 w20 w17 w16 + 17855, 6270, -31521, -17855, // w23 w22 w19 w18 + 17855, -31521, 6270, -17855, // w29 w28 w25 w24 + 6270, 26722, 26722, -31521, // w31 w30 w27 w26 +// %3 for rows 2,6 - constants are multiplied by cos_2_16 + 21407, 27969, 21407, 11585, // movq-> w05 w04 w01 w00 + 21407, 11585, -21407, -27969, // w07 w06 w03 w02 + 21407, -11585, 21407, -27969, // w13 w12 w09 w08 + -21407, 27969, 21407, -11585, // w15 w14 w11 w10 + 29692, 25172, 25172, -5906, // w21 w20 w17 w16 + 16819, 5906, -29692, -16819, // w23 w22 w19 w18 + 16819, -29692, 5906, -16819, // w29 w28 w25 w24 + 5906, 25172, 25172, -29692, // w31 w30 w27 w26 +// %3 for rows 3,5 - constants are multiplied by cos_3_16 + 19266, 25172, 19266, 10426, // movq-> w05 w04 w01 w00 + 19266, 10426, -19266, -25172, // w07 w06 w03 w02 + 19266, -10426, 19266, -25172, // w13 w12 w09 w08 + -19266, 25172, 19266, -10426, // w15 w14 w11 w10 + 26722, 22654, 22654, -5315, // w21 w20 w17 w16 + 15137, 5315, -26722, -15137, // w23 w22 w19 w18 + 15137, -26722, 5315, -15137, // w29 w28 w25 w24 + 5315, 22654, 22654, -26722, // w31 w30 w27 w26 +}; +// ============================================================================= +// Helper macros for the code +// ============================================================================= + +// ----------------------------------------------------------------------------- +// DCT_8_INV_ROW_MMX( INP, OUT, TABLE, ROUNDER +// ----------------------------------------------------------------------------- + +#define DCT_8_INV_ROW_MMX(A1, A2, A3, A4) \ + "movq "#A1", %%mm0 \n\t" /* 0 ; x3 x2 x1 x0 */ \ + "movq 8+"#A1", %%mm1 \n\t" /* 1 ; x7 x6 x5 x4 */ \ + "movq %%mm0, %%mm2 \n\t" /* 2 ; x3 x2 x1 x0 */ \ + "movq "#A3", %%mm3 \n\t" /* 3 ; w06 w04 w02 w00 */ \ + "punpcklwd %%mm1, %%mm0 \n\t" /* x5 x1 x4 x0 */ \ + "movq %%mm0, %%mm5 \n\t" /* 5 ; x5 x1 x4 x0 */ \ + "punpckldq %%mm0, %%mm0 \n\t" /* x4 x0 x4 x0 */ \ + "movq 8+"#A3", %%mm4 \n\t" /* 4 ; w07 w05 w03 w01 */ \ + "punpckhwd %%mm1, %%mm2 \n\t" /* 1 ; x7 x3 x6 x2 */ \ + "pmaddwd %%mm0, %%mm3 \n\t" /* x4*w06+x0*w04 x4*w02+x0*w00 */ \ + "movq %%mm2, %%mm6 \n\t" /* 6 ; x7 x3 x6 x2 */ \ + "movq 32+"#A3", %%mm1 \n\t" /* 1 ; w22 w20 w18 w16 */ \ + "punpckldq %%mm2, %%mm2 \n\t" /* x6 x2 x6 x2 */ \ + "pmaddwd %%mm2, %%mm4 \n\t" /* x6*w07+x2*w05 x6*w03+x2*w01 */ \ + "punpckhdq %%mm5, %%mm5 \n\t" /* x5 x1 x5 x1 */ \ + "pmaddwd 16+"#A3", %%mm0 \n\t" /* x4*w14+x0*w12 x4*w10+x0*w08 */ \ + "punpckhdq %%mm6, %%mm6 \n\t" /* x7 x3 x7 x3 */ \ + "movq 40+ "#A3", %%mm7 \n\t" /* 7 ; w23 w21 w19 w17 */ \ + "pmaddwd %%mm5, %%mm1 \n\t" /* x5*w22+x1*w20 x5*w18+x1*w16 */ \ + "paddd "#A4", %%mm3 \n\t" /* +%4 */ \ + "pmaddwd %%mm6, %%mm7 \n\t" /* x7*w23+x3*w21 x7*w19+x3*w17 */ \ + "pmaddwd 24+"#A3", %%mm2 \n\t" /* x6*w15+x2*w13 x6*w11+x2*w09 */ \ + "paddd %%mm4, %%mm3 \n\t" /* 4 ; a1=sum(even1) a0=sum(even0) */ \ + "pmaddwd 48+"#A3", %%mm5 \n\t" /* x5*w30+x1*w28 x5*w26+x1*w24 */ \ + "movq %%mm3, %%mm4 \n\t" /* 4 ; a1 a0 */ \ + "pmaddwd 56+"#A3", %%mm6 \n\t" /* x7*w31+x3*w29 x7*w27+x3*w25 */ \ + "paddd %%mm7, %%mm1 \n\t" /* 7 ; b1=sum(odd1) b0=sum(odd0) */ \ + "paddd "#A4", %%mm0 \n\t" /* +%4 */ \ + "psubd %%mm1, %%mm3 \n\t" /* a1-b1 a0-b0 */ \ + "psrad $11, %%mm3 \n\t" /* y6=a1-b1 y7=a0-b0 */ \ + "paddd %%mm4, %%mm1 \n\t" /* 4 ; a1+b1 a0+b0 */ \ + "paddd %%mm2, %%mm0 \n\t" /* 2 ; a3=sum(even3) a2=sum(even2) */ \ + "psrad $11, %%mm1 \n\t" /* y1=a1+b1 y0=a0+b0 */ \ + "paddd %%mm6, %%mm5 \n\t" /* 6 ; b3=sum(odd3) b2=sum(odd2) */ \ + "movq %%mm0, %%mm4 \n\t" /* 4 ; a3 a2 */ \ + "paddd %%mm5, %%mm0 \n\t" /* a3+b3 a2+b2 */ \ + "psubd %%mm5, %%mm4 \n\t" /* 5 ; a3-b3 a2-b2 */ \ + "psrad $11, %%mm0 \n\t" /* y3=a3+b3 y2=a2+b2 */ \ + "psrad $11, %%mm4 \n\t" /* y4=a3-b3 y5=a2-b2 */ \ + "packssdw %%mm0, %%mm1 \n\t" /* 0 ; y3 y2 y1 y0 */ \ + "packssdw %%mm3, %%mm4 \n\t" /* 3 ; y6 y7 y4 y5 */ \ + "movq %%mm4, %%mm7 \n\t" /* 7 ; y6 y7 y4 y5 */ \ + "psrld $16, %%mm4 \n\t" /* 0 y6 0 y4 */ \ + "pslld $16, %%mm7 \n\t" /* y7 0 y5 0 */ \ + "movq %%mm1, "#A2" \n\t" /* 1 ; save y3 y2 y1 y0 */ \ + "por %%mm4, %%mm7 \n\t" /* 4 ; y7 y6 y5 y4 */ \ + "movq %%mm7, 8+"#A2" \n\t" /* 7 ; save y7 y6 y5 y4 */ \ + + +// ----------------------------------------------------------------------------- +// DCT_8_INV_ROW_XMM( INP, OUT, TABLE, ROUNDER +// ----------------------------------------------------------------------------- + +#define DCT_8_INV_ROW_XMM(A1, A2, A3, A4) \ + "movq "#A1", %%mm0 \n\t" /* 0 ; x3 x2 x1 x0 */ \ + "movq 8+"#A1", %%mm1 \n\t" /* 1 ; x7 x6 x5 x4 */ \ + "movq %%mm0, %%mm2 \n\t" /* 2 ; x3 x2 x1 x0 */ \ + "movq "#A3", %%mm3 \n\t" /* 3 ; w05 w04 w01 w00 */ \ + "pshufw $0x88, %%mm0, %%mm0 \n\t" /* x2 x0 x2 x0 */ \ + "movq 8+"#A3", %%mm4 \n\t" /* 4 ; w07 w06 w03 w02 */ \ + "movq %%mm1, %%mm5 \n\t" /* 5 ; x7 x6 x5 x4 */ \ + "pmaddwd %%mm0, %%mm3 \n\t" /* x2*w05+x0*w04 x2*w01+x0*w00 */ \ + "movq 32+"#A3", %%mm6 \n\t" /* 6 ; w21 w20 w17 w16 */ \ + "pshufw $0x88, %%mm1, %%mm1 \n\t" /* x6 x4 x6 x4 */ \ + "pmaddwd %%mm1, %%mm4 \n\t" /* x6*w07+x4*w06 x6*w03+x4*w02 */ \ + "movq 40+"#A3", %%mm7 \n\t" /* 7; w23 w22 w19 w18 */ \ + "pshufw $0xdd, %%mm2, %%mm2 \n\t" /* x3 x1 x3 x1 */ \ + "pmaddwd %%mm2, %%mm6 \n\t" /* x3*w21+x1*w20 x3*w17+x1*w16 */ \ + "pshufw $0xdd, %%mm5, %%mm5 \n\t" /* x7 x5 x7 x5 */ \ + "pmaddwd %%mm5, %%mm7 \n\t" /* x7*w23+x5*w22 x7*w19+x5*w18 */ \ + "paddd "#A4", %%mm3 \n\t" /* +%4 */ \ + "pmaddwd 16+"#A3", %%mm0 \n\t" /* x2*w13+x0*w12 x2*w09+x0*w08 */ \ + "paddd %%mm4, %%mm3 \n\t" /* 4 ; a1=sum(even1) a0=sum(even0) */ \ + "pmaddwd 24+"#A3", %%mm1 \n\t" /* x6*w15+x4*w14 x6*w11+x4*w10 */ \ + "movq %%mm3, %%mm4 \n\t" /* 4 ; a1 a0 */ \ + "pmaddwd 48+"#A3", %%mm2 \n\t" /* x3*w29+x1*w28 x3*w25+x1*w24 */ \ + "paddd %%mm7, %%mm6 \n\t" /* 7 ; b1=sum(odd1) b0=sum(odd0) */ \ + "pmaddwd 56+"#A3", %%mm5 \n\t" /* x7*w31+x5*w30 x7*w27+x5*w26 */ \ + "paddd %%mm6, %%mm3 \n\t" /* a1+b1 a0+b0 */ \ + "paddd "#A4", %%mm0 \n\t" /* +%4 */ \ + "psrad $11, %%mm3 \n\t" /* y1=a1+b1 y0=a0+b0 */ \ + "paddd %%mm1, %%mm0 \n\t" /* 1 ; a3=sum(even3) a2=sum(even2) */ \ + "psubd %%mm6, %%mm4 \n\t" /* 6 ; a1-b1 a0-b0 */ \ + "movq %%mm0, %%mm7 \n\t" /* 7 ; a3 a2 */ \ + "paddd %%mm5, %%mm2 \n\t" /* 5 ; b3=sum(odd3) b2=sum(odd2) */ \ + "paddd %%mm2, %%mm0 \n\t" /* a3+b3 a2+b2 */ \ + "psrad $11, %%mm4 \n\t" /* y6=a1-b1 y7=a0-b0 */ \ + "psubd %%mm2, %%mm7 \n\t" /* 2 ; a3-b3 a2-b2 */ \ + "psrad $11, %%mm0 \n\t" /* y3=a3+b3 y2=a2+b2 */ \ + "psrad $11, %%mm7 \n\t" /* y4=a3-b3 y5=a2-b2 */ \ + "packssdw %%mm0, %%mm3 \n\t" /* 0 ; y3 y2 y1 y0 */ \ + "packssdw %%mm4, %%mm7 \n\t" /* 4 ; y6 y7 y4 y5 */ \ + "movq %%mm3, "#A2" \n\t" /* 3 ; save y3 y2 y1 y0 */ \ + "pshufw $0xb1, %%mm7, %%mm7 \n\t" /* y7 y6 y5 y4 */ \ + "movq %%mm7, 8+"#A2" \n\t" /* 7 ; save y7 y6 y5 y4 */ \ + + +// ----------------------------------------------------------------------------- +// +// The first stage DCT 8x8 - forward DCTs of columns +// +// The %2puts are multiplied +// for rows 0,4 - on cos_4_16, +// for rows 1,7 - on cos_1_16, +// for rows 2,6 - on cos_2_16, +// for rows 3,5 - on cos_3_16 +// and are shifted to the left for rise of accuracy +// +// ----------------------------------------------------------------------------- +// +// The 8-point scaled forward DCT algorithm (26a8m) +// +// ----------------------------------------------------------------------------- +// +//#define DCT_8_FRW_COL(x, y) +// { +// short t0, t1, t2, t3, t4, t5, t6, t7; +// short tp03, tm03, tp12, tm12, tp65, tm65; +// short tp465, tm465, tp765, tm765; +// +// t0 = LEFT_SHIFT(x[0] + x[7]); +// t1 = LEFT_SHIFT(x[1] + x[6]); +// t2 = LEFT_SHIFT(x[2] + x[5]); +// t3 = LEFT_SHIFT(x[3] + x[4]); +// t4 = LEFT_SHIFT(x[3] - x[4]); +// t5 = LEFT_SHIFT(x[2] - x[5]); +// t6 = LEFT_SHIFT(x[1] - x[6]); +// t7 = LEFT_SHIFT(x[0] - x[7]); +// +// tp03 = t0 + t3; +// tm03 = t0 - t3; +// tp12 = t1 + t2; +// tm12 = t1 - t2; +// +// y[0] = tp03 + tp12; +// y[4] = tp03 - tp12; +// +// y[2] = tm03 + tm12 * tg_2_16; +// y[6] = tm03 * tg_2_16 - tm12; +// +// tp65 = (t6 + t5) * cos_4_16; +// tm65 = (t6 - t5) * cos_4_16; +// +// tp765 = t7 + tp65; +// tm765 = t7 - tp65; +// tp465 = t4 + tm65; +// tm465 = t4 - tm65; +// +// y[1] = tp765 + tp465 * tg_1_16; +// y[7] = tp765 * tg_1_16 - tp465; +// y[5] = tm765 * tg_3_16 + tm465; +// y[3] = tm765 - tm465 * tg_3_16; +// } +// +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// DCT_8_INV_COL_4 INP,OUT +// ----------------------------------------------------------------------------- + +#define DCT_8_INV_COL(A1, A2) \ + "movq 2*8(%3), %%mm0 \n\t" \ + "movq 16*3+"#A1", %%mm3 \n\t" \ + "movq %%mm0, %%mm1 \n\t" /* tg_3_16 */ \ + "movq 16*5+"#A1", %%mm5 \n\t" \ + "pmulhw %%mm3, %%mm0 \n\t" /* x3*(tg_3_16-1) */ \ + "movq (%3), %%mm4 \n\t" \ + "pmulhw %%mm5, %%mm1 \n\t" /* x5*(tg_3_16-1) */ \ + "movq 16*7+"#A1", %%mm7 \n\t" \ + "movq %%mm4, %%mm2 \n\t" /* tg_1_16 */ \ + "movq 16*1+"#A1", %%mm6 \n\t" \ + "pmulhw %%mm7, %%mm4 \n\t" /* x7*tg_1_16 */ \ + "paddsw %%mm3, %%mm0 \n\t" /* x3*tg_3_16 */ \ + "pmulhw %%mm6, %%mm2 \n\t" /* x1*tg_1_16 */ \ + "paddsw %%mm3, %%mm1 \n\t" /* x3+x5*(tg_3_16-1) */ \ + "psubsw %%mm5, %%mm0 \n\t" /* x3*tg_3_16-x5 = tm35 */ \ + "movq 3*8(%3), %%mm3 \n\t" \ + "paddsw %%mm5, %%mm1 \n\t" /* x3+x5*tg_3_16 = tp35 */ \ + "paddsw %%mm6, %%mm4 \n\t" /* x1+tg_1_16*x7 = tp17 */ \ + "psubsw %%mm7, %%mm2 \n\t" /* x1*tg_1_16-x7 = tm17 */ \ + "movq %%mm4, %%mm5 \n\t" /* tp17 */ \ + "movq %%mm2, %%mm6 \n\t" /* tm17 */ \ + "paddsw %%mm1, %%mm5 \n\t" /* tp17+tp35 = b0 */ \ + "psubsw %%mm0, %%mm6 \n\t" /* tm17-tm35 = b3 */ \ + "psubsw %%mm1, %%mm4 \n\t" /* tp17-tp35 = t1 */ \ + "paddsw %%mm0, %%mm2 \n\t" /* tm17+tm35 = t2 */ \ + "movq 1*8(%3), %%mm7 \n\t" \ + "movq %%mm4, %%mm1 \n\t" /* t1 */ \ + "movq %%mm5, 3*16+"#A2" \n\t" /* save b0 */ \ + "paddsw %%mm2, %%mm1 \n\t" /* t1+t2 */ \ + "movq %%mm6, 5*16+"#A2" \n\t" /* save b3 */ \ + "psubsw %%mm2, %%mm4 \n\t" /* t1-t2 */ \ + "movq 2*16+"#A1", %%mm5 \n\t" \ + "movq %%mm7, %%mm0 \n\t" /* tg_2_16 */ \ + "movq 6*16+"#A1", %%mm6 \n\t" \ + "pmulhw %%mm5, %%mm0 \n\t" /* x2*tg_2_16 */ \ + "pmulhw %%mm6, %%mm7 \n\t" /* x6*tg_2_16 */ \ + "pmulhw %%mm3, %%mm1 \n\t" /* ocos_4_16*(t1+t2) = b1/2 */ \ + "movq 0*16+"#A1", %%mm2 \n\t" \ + "pmulhw %%mm3, %%mm4 \n\t" /* ocos_4_16*(t1-t2) = b2/2 */ \ + "psubsw %%mm6, %%mm0 \n\t" /* t2*tg_2_16-x6 = tm26 */ \ + "movq %%mm2, %%mm3 \n\t" /* x0 */ \ + "movq 4*16+"#A1", %%mm6 \n\t" \ + "paddsw %%mm5, %%mm7 \n\t" /* x2+x6*tg_2_16 = tp26 */ \ + "paddsw %%mm6, %%mm2 \n\t" /* x0+x4 = tp04 */ \ + "psubsw %%mm6, %%mm3 \n\t" /* x0-x4 = tm04 */ \ + "movq %%mm2, %%mm5 \n\t" /* tp04 */ \ + "movq %%mm3, %%mm6 \n\t" /* tm04 */ \ + "psubsw %%mm7, %%mm2 \n\t" /* tp04-tp26 = a3 */ \ + "paddsw %%mm0, %%mm3 \n\t" /* tm04+tm26 = a1 */ \ + "paddsw %%mm1, %%mm1 \n\t" /* b1 */ \ + "paddsw %%mm4, %%mm4 \n\t" /* b2 */ \ + "paddsw %%mm7, %%mm5 \n\t" /* tp04+tp26 = a0 */ \ + "psubsw %%mm0, %%mm6 \n\t" /* tm04-tm26 = a2 */ \ + "movq %%mm3, %%mm7 \n\t" /* a1 */ \ + "movq %%mm6, %%mm0 \n\t" /* a2 */ \ + "paddsw %%mm1, %%mm3 \n\t" /* a1+b1 */ \ + "paddsw %%mm4, %%mm6 \n\t" /* a2+b2 */ \ + "psraw $6, %%mm3 \n\t" /* dst1 */ \ + "psubsw %%mm1, %%mm7 \n\t" /* a1-b1 */ \ + "psraw $6, %%mm6 \n\t" /* dst2 */ \ + "psubsw %%mm4, %%mm0 \n\t" /* a2-b2 */ \ + "movq 3*16+"#A2", %%mm1 \n\t" /* load b0 */ \ + "psraw $6, %%mm7 \n\t" /* dst6 */ \ + "movq %%mm5, %%mm4 \n\t" /* a0 */ \ + "psraw $6, %%mm0 \n\t" /* dst5 */ \ + "movq %%mm3, 1*16+"#A2" \n\t" \ + "paddsw %%mm1, %%mm5 \n\t" /* a0+b0 */ \ + "movq %%mm6, 2*16+"#A2" \n\t" \ + "psubsw %%mm1, %%mm4 \n\t" /* a0-b0 */ \ + "movq 5*16+"#A2", %%mm3 \n\t" /* load b3 */ \ + "psraw $6, %%mm5 \n\t" /* dst0 */ \ + "movq %%mm2, %%mm6 \n\t" /* a3 */ \ + "psraw $6, %%mm4 \n\t" /* dst7 */ \ + "movq %%mm0, 5*16+"#A2" \n\t" \ + "paddsw %%mm3, %%mm2 \n\t" /* a3+b3 */ \ + "movq %%mm7, 6*16+"#A2" \n\t" \ + "psubsw %%mm3, %%mm6 \n\t" /* a3-b3 */ \ + "movq %%mm5, 0*16+"#A2" \n\t" \ + "psraw $6, %%mm2 \n\t" /* dst3 */ \ + "movq %%mm4, 7*16+"#A2" \n\t" \ + "psraw $6, %%mm6 \n\t" /* dst4 */ \ + "movq %%mm2, 3*16+"#A2" \n\t" \ + "movq %%mm6, 4*16+"#A2" \n\t" \ + +// ============================================================================= +// Code +// ============================================================================= + +// ----------------------------------------------------------------------------- +// void idct_mmx(uint16_t block[64]); +// ----------------------------------------------------------------------------- + +void ff_xvid_idct_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 ff_xvid_idct_mmx_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct_mmx(block); + ff_put_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_xvid_idct_mmx_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct_mmx(block); + ff_add_pixels_clamped_mmx(block, dest, line_size); +} + +#endif /* HAVE_MMX_INLINE */ + +#if HAVE_MMXEXT_INLINE + +// ----------------------------------------------------------------------------- +// void idct_xmm(uint16_t block[64]); +// ----------------------------------------------------------------------------- + +void ff_xvid_idct_mmxext(short *block) +{ + __asm__ volatile ( + // # Process each row + DCT_8_INV_ROW_XMM(0 * 16(%0), 0 * 16(%0), 64 * 0(%2), 8 * 0(%1)) + DCT_8_INV_ROW_XMM(1 * 16(%0), 1 * 16(%0), 64 * 1(%2), 8 * 1(%1)) + DCT_8_INV_ROW_XMM(2 * 16(%0), 2 * 16(%0), 64 * 2(%2), 8 * 2(%1)) + DCT_8_INV_ROW_XMM(3 * 16(%0), 3 * 16(%0), 64 * 3(%2), 8 * 3(%1)) + DCT_8_INV_ROW_XMM(4 * 16(%0), 4 * 16(%0), 64 * 0(%2), 8 * 4(%1)) + DCT_8_INV_ROW_XMM(5 * 16(%0), 5 * 16(%0), 64 * 3(%2), 8 * 5(%1)) + DCT_8_INV_ROW_XMM(6 * 16(%0), 6 * 16(%0), 64 * 2(%2), 8 * 6(%1)) + DCT_8_INV_ROW_XMM(7 * 16(%0), 7 * 16(%0), 64 * 1(%2), 8 * 7(%1)) + + // # Process the columns (4 at a time) + DCT_8_INV_COL(0(%0), 0(%0)) + DCT_8_INV_COL(8(%0), 8(%0)) + :: "r" (block), "r" (rounder_0), "r" (tab_i_04_xmm), "r" (tg_1_16)); +} + +void ff_xvid_idct_mmxext_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct_mmxext(block); + ff_put_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_xvid_idct_mmxext_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct_mmxext(block); + ff_add_pixels_clamped_mmx(block, dest, line_size); +} + +#endif /* HAVE_MMXEXT_INLINE */ diff --git a/libavcodec/x86/idct_sse2_xvid.c b/libavcodec/x86/xvididct_sse2.c similarity index 64% rename from libavcodec/x86/idct_sse2_xvid.c rename to libavcodec/x86/xvididct_sse2.c index 49149ea..d4f0169 100644 --- a/libavcodec/x86/idct_sse2_xvid.c +++ b/libavcodec/x86/xvididct_sse2.c @@ -41,8 +41,9 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/x86/asm.h" -#include "idct_xvid.h" + #include "idctdsp.h" +#include "xvididct.h" #if HAVE_SSE2_INLINE @@ -51,52 +52,49 @@ * @brief SSE2 IDCT compatible with the Xvid IDCT */ -#define X8(x) x,x,x,x,x,x,x,x - -#define ROW_SHIFT 11 -#define COL_SHIFT 6 +#define X8(x) x, x, x, x, x, x, x, x -DECLARE_ASM_CONST(16, int16_t, tan1)[] = {X8(13036)}; // tan( pi/16) -DECLARE_ASM_CONST(16, int16_t, tan2)[] = {X8(27146)}; // tan(2pi/16) = sqrt(2)-1 -DECLARE_ASM_CONST(16, int16_t, tan3)[] = {X8(43790)}; // tan(3pi/16)-1 -DECLARE_ASM_CONST(16, int16_t, sqrt2)[]= {X8(23170)}; // 0.5/sqrt(2) -DECLARE_ASM_CONST(8, uint8_t, m127)[] = {X8(127)}; +DECLARE_ASM_CONST(16, int16_t, tan1)[] = { X8(13036) }; // tan( pi/16) +DECLARE_ASM_CONST(16, int16_t, tan2)[] = { X8(27146) }; // tan(2pi/16) = sqrt(2)-1 +DECLARE_ASM_CONST(16, int16_t, tan3)[] = { X8(43790) }; // tan(3pi/16)-1 +DECLARE_ASM_CONST(16, int16_t, sqrt2)[] = { X8(23170) }; // 0.5/sqrt(2) +DECLARE_ASM_CONST(8, uint8_t, m127)[] = { X8(127) }; DECLARE_ASM_CONST(16, int16_t, iTab1)[] = { - 0x4000, 0x539f, 0xc000, 0xac61, 0x4000, 0xdd5d, 0x4000, 0xdd5d, - 0x4000, 0x22a3, 0x4000, 0x22a3, 0xc000, 0x539f, 0x4000, 0xac61, - 0x3249, 0x11a8, 0x4b42, 0xee58, 0x11a8, 0x4b42, 0x11a8, 0xcdb7, - 0x58c5, 0x4b42, 0xa73b, 0xcdb7, 0x3249, 0xa73b, 0x4b42, 0xa73b + 0x4000, 0x539f, 0xc000, 0xac61, 0x4000, 0xdd5d, 0x4000, 0xdd5d, + 0x4000, 0x22a3, 0x4000, 0x22a3, 0xc000, 0x539f, 0x4000, 0xac61, + 0x3249, 0x11a8, 0x4b42, 0xee58, 0x11a8, 0x4b42, 0x11a8, 0xcdb7, + 0x58c5, 0x4b42, 0xa73b, 0xcdb7, 0x3249, 0xa73b, 0x4b42, 0xa73b }; DECLARE_ASM_CONST(16, int16_t, iTab2)[] = { - 0x58c5, 0x73fc, 0xa73b, 0x8c04, 0x58c5, 0xcff5, 0x58c5, 0xcff5, - 0x58c5, 0x300b, 0x58c5, 0x300b, 0xa73b, 0x73fc, 0x58c5, 0x8c04, - 0x45bf, 0x187e, 0x6862, 0xe782, 0x187e, 0x6862, 0x187e, 0xba41, - 0x7b21, 0x6862, 0x84df, 0xba41, 0x45bf, 0x84df, 0x6862, 0x84df + 0x58c5, 0x73fc, 0xa73b, 0x8c04, 0x58c5, 0xcff5, 0x58c5, 0xcff5, + 0x58c5, 0x300b, 0x58c5, 0x300b, 0xa73b, 0x73fc, 0x58c5, 0x8c04, + 0x45bf, 0x187e, 0x6862, 0xe782, 0x187e, 0x6862, 0x187e, 0xba41, + 0x7b21, 0x6862, 0x84df, 0xba41, 0x45bf, 0x84df, 0x6862, 0x84df }; DECLARE_ASM_CONST(16, int16_t, iTab3)[] = { - 0x539f, 0x6d41, 0xac61, 0x92bf, 0x539f, 0xd2bf, 0x539f, 0xd2bf, - 0x539f, 0x2d41, 0x539f, 0x2d41, 0xac61, 0x6d41, 0x539f, 0x92bf, - 0x41b3, 0x1712, 0x6254, 0xe8ee, 0x1712, 0x6254, 0x1712, 0xbe4d, - 0x73fc, 0x6254, 0x8c04, 0xbe4d, 0x41b3, 0x8c04, 0x6254, 0x8c04 + 0x539f, 0x6d41, 0xac61, 0x92bf, 0x539f, 0xd2bf, 0x539f, 0xd2bf, + 0x539f, 0x2d41, 0x539f, 0x2d41, 0xac61, 0x6d41, 0x539f, 0x92bf, + 0x41b3, 0x1712, 0x6254, 0xe8ee, 0x1712, 0x6254, 0x1712, 0xbe4d, + 0x73fc, 0x6254, 0x8c04, 0xbe4d, 0x41b3, 0x8c04, 0x6254, 0x8c04 }; DECLARE_ASM_CONST(16, int16_t, iTab4)[] = { - 0x4b42, 0x6254, 0xb4be, 0x9dac, 0x4b42, 0xd746, 0x4b42, 0xd746, - 0x4b42, 0x28ba, 0x4b42, 0x28ba, 0xb4be, 0x6254, 0x4b42, 0x9dac, - 0x3b21, 0x14c3, 0x587e, 0xeb3d, 0x14c3, 0x587e, 0x14c3, 0xc4df, - 0x6862, 0x587e, 0x979e, 0xc4df, 0x3b21, 0x979e, 0x587e, 0x979e + 0x4b42, 0x6254, 0xb4be, 0x9dac, 0x4b42, 0xd746, 0x4b42, 0xd746, + 0x4b42, 0x28ba, 0x4b42, 0x28ba, 0xb4be, 0x6254, 0x4b42, 0x9dac, + 0x3b21, 0x14c3, 0x587e, 0xeb3d, 0x14c3, 0x587e, 0x14c3, 0xc4df, + 0x6862, 0x587e, 0x979e, 0xc4df, 0x3b21, 0x979e, 0x587e, 0x979e }; DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { - 65536, 65536, 65536, 65536, - 3597, 3597, 3597, 3597, - 2260, 2260, 2260, 2260, - 1203, 1203, 1203, 1203, - 120, 120, 120, 120, - 512, 512, 512, 512 + 65536, 65536, 65536, 65536, + 3597, 3597, 3597, 3597, + 2260, 2260, 2260, 2260, + 1203, 1203, 1203, 1203, + 120, 120, 120, 120, + 512, 512, 512, 512 }; // Temporary storage before the column pass @@ -166,46 +164,46 @@ DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { "pmovmskb %%mm1, "reg" \n\t" #define TEST_TWO_ROWS(row1, row2, reg1, reg2, clear1, clear2) \ - clear1 \ - clear2 \ - "movq "row1", %%mm1 \n\t" \ - "por 8+"row1", %%mm1 \n\t" \ - "movq "row2", %%mm2 \n\t" \ - "por 8+"row2", %%mm2 \n\t" \ - "paddusb %%mm0, %%mm1 \n\t" \ - "paddusb %%mm0, %%mm2 \n\t" \ - "pmovmskb %%mm1, "reg1" \n\t" \ + clear1 \ + clear2 \ + "movq "row1", %%mm1 \n\t" \ + "por 8+"row1", %%mm1 \n\t" \ + "movq "row2", %%mm2 \n\t" \ + "por 8+"row2", %%mm2 \n\t" \ + "paddusb %%mm0, %%mm1 \n\t" \ + "paddusb %%mm0, %%mm2 \n\t" \ + "pmovmskb %%mm1, "reg1" \n\t" \ "pmovmskb %%mm2, "reg2" \n\t" -///IDCT pass on rows. -#define iMTX_MULT(src, table, rounder, put) \ - "movdqa "src", %%xmm3 \n\t" \ - "movdqa %%xmm3, %%xmm0 \n\t" \ +/// IDCT pass on rows. +#define iMTX_MULT(src, table, rounder, put) \ + "movdqa "src", %%xmm3 \n\t" \ + "movdqa %%xmm3, %%xmm0 \n\t" \ "pshufd $0x11, %%xmm3, %%xmm1 \n\t" /* 4602 */ \ "punpcklqdq %%xmm0, %%xmm0 \n\t" /* 0246 */ \ - "pmaddwd "table", %%xmm0 \n\t" \ - "pmaddwd 16+"table", %%xmm1 \n\t" \ + "pmaddwd "table", %%xmm0 \n\t" \ + "pmaddwd 16+"table", %%xmm1 \n\t" \ "pshufd $0xBB, %%xmm3, %%xmm2 \n\t" /* 5713 */ \ "punpckhqdq %%xmm3, %%xmm3 \n\t" /* 1357 */ \ - "pmaddwd 32+"table", %%xmm2 \n\t" \ - "pmaddwd 48+"table", %%xmm3 \n\t" \ - "paddd %%xmm1, %%xmm0 \n\t" \ - "paddd %%xmm3, %%xmm2 \n\t" \ - rounder", %%xmm0 \n\t" \ - "movdqa %%xmm2, %%xmm3 \n\t" \ - "paddd %%xmm0, %%xmm2 \n\t" \ - "psubd %%xmm3, %%xmm0 \n\t" \ - "psrad $11, %%xmm2 \n\t" \ - "psrad $11, %%xmm0 \n\t" \ - "packssdw %%xmm0, %%xmm2 \n\t" \ - put \ + "pmaddwd 32+"table", %%xmm2 \n\t" \ + "pmaddwd 48+"table", %%xmm3 \n\t" \ + "paddd %%xmm1, %%xmm0 \n\t" \ + "paddd %%xmm3, %%xmm2 \n\t" \ + rounder", %%xmm0 \n\t" \ + "movdqa %%xmm2, %%xmm3 \n\t" \ + "paddd %%xmm0, %%xmm2 \n\t" \ + "psubd %%xmm3, %%xmm0 \n\t" \ + "psrad $11, %%xmm2 \n\t" \ + "psrad $11, %%xmm0 \n\t" \ + "packssdw %%xmm0, %%xmm2 \n\t" \ + put \ "1: \n\t" #define iLLM_HEAD \ "movdqa "MANGLE(tan3)", "TAN3" \n\t" \ "movdqa "MANGLE(tan1)", "TAN1" \n\t" \ -///IDCT pass on columns. +/// IDCT pass on columns. #define iLLM_PASS(dct) \ "movdqa "TAN3", %%xmm1 \n\t" \ "movdqa "TAN1", %%xmm3 \n\t" \ @@ -283,7 +281,7 @@ DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { "movdqa "REG4", 4*16("dct") \n\t" \ "movdqa %%xmm7, 7*16("dct") \n\t" -///IDCT pass on columns, assuming rows 4-7 are zero. +/// IDCT pass on columns, assuming rows 4-7 are zero. #define iLLM_PASS_SPARSE(dct) \ "pmulhw %%xmm4, "TAN3" \n\t" \ "paddsw %%xmm4, "TAN3" \n\t" \ @@ -344,64 +342,63 @@ DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { "movdqa %%xmm6, 4*16("dct") \n\t" \ "movdqa "SREG2", 7*16("dct") \n\t" -inline void ff_idct_xvid_sse2(short *block) +inline void ff_xvid_idct_sse2(short *block) { - __asm__ volatile( - "movq "MANGLE(m127)", %%mm0 \n\t" - iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(walkenIdctRounders), PUT_EVEN(ROW0)) - iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+1*16), PUT_ODD(ROW1)) - iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+2*16), PUT_EVEN(ROW2)) - - TEST_TWO_ROWS("3*16(%0)", "4*16(%0)", "%%eax", "%%ecx", CLEAR_ODD(ROW3), CLEAR_EVEN(ROW4)) - JZ("%%eax", "1f") - iMTX_MULT("3*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+3*16), PUT_ODD(ROW3)) - - TEST_TWO_ROWS("5*16(%0)", "6*16(%0)", "%%eax", "%%edx", CLEAR_ODD(ROW5), CLEAR_EVEN(ROW6)) - TEST_ONE_ROW("7*16(%0)", "%%esi", CLEAR_ODD(ROW7)) - iLLM_HEAD - ".p2align 4 \n\t" - JNZ("%%ecx", "2f") - JNZ("%%eax", "3f") - JNZ("%%edx", "4f") - JNZ("%%esi", "5f") - iLLM_PASS_SPARSE("%0") - "jmp 6f \n\t" - "2: \n\t" - iMTX_MULT("4*16(%0)", MANGLE(iTab1), "#", PUT_EVEN(ROW4)) - "3: \n\t" - iMTX_MULT("5*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+4*16), PUT_ODD(ROW5)) - JZ("%%edx", "1f") - "4: \n\t" - iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+5*16), PUT_EVEN(ROW6)) - JZ("%%esi", "1f") - "5: \n\t" - iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+5*16), PUT_ODD(ROW7)) + __asm__ volatile ( + "movq "MANGLE (m127) ", %%mm0 \n\t" + iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(walkenIdctRounders), PUT_EVEN(ROW0)) + iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders + 1 * 16), PUT_ODD(ROW1)) + iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders + 2 * 16), PUT_EVEN(ROW2)) + + TEST_TWO_ROWS("3*16(%0)", "4*16(%0)", "%%eax", "%%ecx", CLEAR_ODD(ROW3), CLEAR_EVEN(ROW4)) + JZ("%%eax", "1f") + iMTX_MULT("3*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders + 3 * 16), PUT_ODD(ROW3)) + + TEST_TWO_ROWS("5*16(%0)", "6*16(%0)", "%%eax", "%%edx", CLEAR_ODD(ROW5), CLEAR_EVEN(ROW6)) + TEST_ONE_ROW("7*16(%0)", "%%esi", CLEAR_ODD(ROW7)) + iLLM_HEAD + ".p2align 4 \n\t" + JNZ("%%ecx", "2f") + JNZ("%%eax", "3f") + JNZ("%%edx", "4f") + JNZ("%%esi", "5f") + iLLM_PASS_SPARSE("%0") + "jmp 6f \n\t" + "2: \n\t" + iMTX_MULT("4*16(%0)", MANGLE(iTab1), "#", PUT_EVEN(ROW4)) + "3: \n\t" + iMTX_MULT("5*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders + 4 * 16), PUT_ODD(ROW5)) + JZ("%%edx", "1f") + "4: \n\t" + iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders + 5 * 16), PUT_EVEN(ROW6)) + JZ("%%esi", "1f") + "5: \n\t" + iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders + 5 * 16), PUT_ODD(ROW7)) #if ARCH_X86_32 - iLLM_HEAD + iLLM_HEAD #endif - iLLM_PASS("%0") - "6: \n\t" - : "+r"(block) - : - : XMM_CLOBBERS("%xmm0" , "%xmm1" , "%xmm2" , "%xmm3" , - "%xmm4" , "%xmm5" , "%xmm6" , "%xmm7" ,) + iLLM_PASS("%0") + "6: \n\t" + : "+r" (block) + : + : XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7", ) #if ARCH_X86_64 - XMM_CLOBBERS("%xmm8" , "%xmm9" , "%xmm10", "%xmm11", - "%xmm12", "%xmm13", "%xmm14",) + XMM_CLOBBERS("%xmm8", "%xmm9", "%xmm10", "%xmm11", + "%xmm12", "%xmm13", "%xmm14", ) #endif - "%eax", "%ecx", "%edx", "%esi", "memory" - ); + "%eax", "%ecx", "%edx", "%esi", "memory"); } -void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block) +void ff_xvid_idct_sse2_put(uint8_t *dest, int line_size, short *block) { - ff_idct_xvid_sse2(block); + ff_xvid_idct_sse2(block); ff_put_pixels_clamped_mmx(block, dest, line_size); } -void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block) +void ff_xvid_idct_sse2_add(uint8_t *dest, int line_size, short *block) { - ff_idct_xvid_sse2(block); + ff_xvid_idct_sse2(block); ff_add_pixels_clamped_mmx(block, dest, line_size); } diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 4bf1d87..c16c651 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -1,6 +1,6 @@ /* * Wing Commander/Xan Video Decoder - * Copyright (C) 2003 the ffmpeg project + * Copyright (C) 2003 The FFmpeg project * * This file is part of Libav. * @@ -34,9 +34,10 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" -#define BITSTREAM_READER_LE #include "get_bits.h" #include "internal.h" @@ -620,5 +621,5 @@ AVCodec ff_xan_wc3_decoder = { .init = xan_decode_init, .close = xan_decode_end, .decode = xan_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/xbmdec.c b/libavcodec/xbmdec.c index c26f343..2ce1465 100644 --- a/libavcodec/xbmdec.c +++ b/libavcodec/xbmdec.c @@ -118,5 +118,5 @@ AVCodec ff_xbm_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_XBM, .decode = xbm_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/xbmenc.c b/libavcodec/xbmenc.c index 517e569..4840050 100644 --- a/libavcodec/xbmenc.c +++ b/libavcodec/xbmenc.c @@ -26,10 +26,11 @@ static av_cold int xbm_encode_init(AVCodecContext *avctx) { - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -67,13 +68,6 @@ static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int xbm_encode_close(AVCodecContext *avctx) -{ - av_frame_free(&avctx->coded_frame); - - return 0; -} - AVCodec ff_xbm_encoder = { .name = "xbm", .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), @@ -81,7 +75,6 @@ AVCodec ff_xbm_encoder = { .id = AV_CODEC_ID_XBM, .init = xbm_encode_init, .encode2 = xbm_encode_frame, - .close = xbm_encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/xl.c b/libavcodec/xl.c index 8e9bdc6..7286c14 100644 --- a/libavcodec/xl.c +++ b/libavcodec/xl.c @@ -137,5 +137,5 @@ AVCodec ff_xl_decoder = { .id = AV_CODEC_ID_VIXL, .init = decode_init, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c index d01b410..3af300c 100644 --- a/libavcodec/xsubdec.c +++ b/libavcodec/xsubdec.c @@ -95,35 +95,62 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, // allocate sub and set values sub->rects = av_mallocz(sizeof(*sub->rects)); + if (!sub->rects) + return AVERROR(ENOMEM); sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); + if (!sub->rects[0]) { + av_freep(&sub->rects); + return AVERROR(ENOMEM); + } sub->num_rects = 1; sub->rects[0]->x = x; sub->rects[0]->y = y; sub->rects[0]->w = w; sub->rects[0]->h = h; sub->rects[0]->type = SUBTITLE_BITMAP; - sub->rects[0]->pict.linesize[0] = w; - sub->rects[0]->pict.data[0] = av_malloc(w * h); + sub->rects[0]->linesize[0] = w; + sub->rects[0]->data[0] = av_malloc(w * h); sub->rects[0]->nb_colors = 4; - sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + sub->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!sub->rects[0]->data[0] || !sub->rects[0]->data[1]) { + av_freep(&sub->rects[0]->data[1]); + av_freep(&sub->rects[0]->data[0]); + av_freep(&sub->rects[0]); + av_freep(&sub->rects); + return AVERROR(ENOMEM); + } // read palette for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t*)sub->rects[0]->pict.data[1])[i] = bytestream_get_be24(&buf); + ((uint32_t*)sub->rects[0]->data[1])[i] = bytestream_get_be24(&buf); if (!has_alpha) { // make all except background (first entry) non-transparent for (i = 1; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->pict.data[1])[i] |= 0xff000000; + ((uint32_t *)sub->rects[0]->data[1])[i] |= 0xff000000; } else { for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->pict.data[1])[i] |= *buf++ << 24; + ((uint32_t *)sub->rects[0]->data[1])[i] |= *buf++ << 24; } +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS +{ + AVSubtitleRect *rect; + int j; + rect = sub->rects[0]; + for (j = 0; j < 4; j++) { + rect->pict.data[j] = rect->data[j]; + rect->pict.linesize[j] = rect->linesize[j]; + } +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + // process RLE-compressed data init_get_bits(&gb, buf, (buf_end - buf) * 8); - bitmap = sub->rects[0]->pict.data[0]; + bitmap = sub->rects[0]->data[0]; for (y = 0; y < h; y++) { // interlaced: do odd lines - if (y == (h + 1) / 2) bitmap = sub->rects[0]->pict.data[0] + w; + if (y == (h + 1) / 2) bitmap = sub->rects[0]->data[0] + w; for (x = 0; x < w; ) { int log2 = ff_log2_tab[show_bits(&gb, 8)]; int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); diff --git a/libavcodec/xsubenc.c b/libavcodec/xsubenc.c index fc46fb8..5b7e135 100644 --- a/libavcodec/xsubenc.c +++ b/libavcodec/xsubenc.c @@ -131,8 +131,21 @@ static int xsub_encode(AVCodecContext *avctx, unsigned char *buf, if (h->num_rects > 1) av_log(avctx, AV_LOG_WARNING, "Only single rects supported (%d in subtitle.)\n", h->num_rects); +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS + if (!h->rects[0]->data[0]) { + AVSubtitleRect *rect = h->rects[0]; + int j; + for (j = 0; j < 4; j++) { + rect->data[j] = rect->pict.data[j]; + rect->linesize[j] = rect->pict.linesize[j]; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + // TODO: render text-based subtitles into bitmaps - if (!h->rects[0]->pict.data[0] || !h->rects[0]->pict.data[1]) { + if (!h->rects[0]->data[0] || !h->rects[0]->data[1]) { av_log(avctx, AV_LOG_WARNING, "No subtitle bitmap available.\n"); return -1; } @@ -142,7 +155,7 @@ static int xsub_encode(AVCodecContext *avctx, unsigned char *buf, av_log(avctx, AV_LOG_WARNING, "No more than 4 subtitle colors supported (%d found.)\n", h->rects[0]->nb_colors); // TODO: Palette swapping if color zero is not transparent - if (((uint32_t *)h->rects[0]->pict.data[1])[0] & 0xff) + if (((uint32_t *)h->rects[0]->data[1])[0] & 0xff) av_log(avctx, AV_LOG_WARNING, "Color index 0 is not transparent. Transparency will be messed up.\n"); if (make_tc(startTime, start_tc) || make_tc(endTime, end_tc)) { @@ -174,19 +187,19 @@ static int xsub_encode(AVCodecContext *avctx, unsigned char *buf, // Palette for (i=0; i<4; i++) - bytestream_put_be24(&hdr, ((uint32_t *)h->rects[0]->pict.data[1])[i]); + bytestream_put_be24(&hdr, ((uint32_t *)h->rects[0]->data[1])[i]); // Bitmap // RLE buffer. Reserve 2 bytes for possible padding after the last row. init_put_bits(&pb, hdr, bufsize - (hdr - buf) - 2); - if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0], - h->rects[0]->pict.linesize[0]*2, + if (xsub_encode_rle(&pb, h->rects[0]->data[0], + h->rects[0]->linesize[0] * 2, h->rects[0]->w, (h->rects[0]->h + 1) >> 1)) return -1; bytestream_put_le16(&rlelenptr, put_bits_count(&pb) >> 3); // Length of first field - if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0] + h->rects[0]->pict.linesize[0], - h->rects[0]->pict.linesize[0]*2, + if (xsub_encode_rle(&pb, h->rects[0]->data[0] + h->rects[0]->linesize[0], + h->rects[0]->linesize[0] * 2, h->rects[0]->w, h->rects[0]->h >> 1)) return -1; diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c index 9d38662..ca89703 100644 --- a/libavcodec/xvididct.c +++ b/libavcodec/xvididct.c @@ -1,4 +1,8 @@ /* + * Xvid MPEG-4 IDCT + * + * Copyright (C) 2006-2011 Xvid Solutions GmbH + * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -16,23 +20,331 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + * @file + * Walken IDCT + * Alternative IDCT implementation for decoding compatibility. + * + * @author Skal + * @note This C version is not the original IDCT, but a modified one that + * yields the same error profile as the MMX/MMXEXT/SSE2 versions. + */ + #include "config.h" #include "libavutil/attributes.h" #include "avcodec.h" #include "idctdsp.h" #include "xvididct.h" -av_cold void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx) +#define ROW_SHIFT 11 +#define COL_SHIFT 6 + +// #define FIX(x) (int)((x) * (1 << ROW_SHIFT)) +#define RND0 65536 // 1 << (COL_SHIFT + ROW_SHIFT - 1); +#define RND1 3597 // FIX (1.75683487303); +#define RND2 2260 // FIX (1.10355339059); +#define RND3 1203 // FIX (0.587788325588); +#define RND4 0 +#define RND5 120 // FIX (0.058658283817); +#define RND6 512 // FIX (0.25); +#define RND7 512 // FIX (0.25); + +static const int TAB04[] = { 22725, 21407, 19266, 16384, 12873, 8867, 4520 }; +static const int TAB17[] = { 31521, 29692, 26722, 22725, 17855, 12299, 6270 }; +static const int TAB26[] = { 29692, 27969, 25172, 21407, 16819, 11585, 5906 }; +static const int TAB35[] = { 26722, 25172, 22654, 19266, 15137, 10426, 5315 }; + +static int idct_row(short *in, const int *const tab, int rnd) +{ + const int c1 = tab[0]; + const int c2 = tab[1]; + const int c3 = tab[2]; + const int c4 = tab[3]; + const int c5 = tab[4]; + const int c6 = tab[5]; + const int c7 = tab[6]; + + const int right = in[5] | in[6] | in[7]; + const int left = in[1] | in[2] | in[3]; + if (!(right | in[4])) { + const int k = c4 * in[0] + rnd; + if (left) { + const int a0 = k + c2 * in[2]; + const int a1 = k + c6 * in[2]; + const int a2 = k - c6 * in[2]; + const int a3 = k - c2 * in[2]; + + const int b0 = c1 * in[1] + c3 * in[3]; + const int b1 = c3 * in[1] - c7 * in[3]; + const int b2 = c5 * in[1] - c1 * in[3]; + const int b3 = c7 * in[1] - c5 * in[3]; + + in[0] = (a0 + b0) >> ROW_SHIFT; + in[1] = (a1 + b1) >> ROW_SHIFT; + in[2] = (a2 + b2) >> ROW_SHIFT; + in[3] = (a3 + b3) >> ROW_SHIFT; + in[4] = (a3 - b3) >> ROW_SHIFT; + in[5] = (a2 - b2) >> ROW_SHIFT; + in[6] = (a1 - b1) >> ROW_SHIFT; + in[7] = (a0 - b0) >> ROW_SHIFT; + } else { + const int a0 = k >> ROW_SHIFT; + if (a0) { + in[0] = + in[1] = + in[2] = + in[3] = + in[4] = + in[5] = + in[6] = + in[7] = a0; + } else + return 0; + } + } else if (!(left | right)) { + const int a0 = (rnd + c4 * (in[0] + in[4])) >> ROW_SHIFT; + const int a1 = (rnd + c4 * (in[0] - in[4])) >> ROW_SHIFT; + + in[0] = a0; + in[3] = a0; + in[4] = a0; + in[7] = a0; + in[1] = a1; + in[2] = a1; + in[5] = a1; + in[6] = a1; + } else { + const int k = c4 * in[0] + rnd; + const int a0 = k + c2 * in[2] + c4 * in[4] + c6 * in[6]; + const int a1 = k + c6 * in[2] - c4 * in[4] - c2 * in[6]; + const int a2 = k - c6 * in[2] - c4 * in[4] + c2 * in[6]; + const int a3 = k - c2 * in[2] + c4 * in[4] - c6 * in[6]; + + const int b0 = c1 * in[1] + c3 * in[3] + c5 * in[5] + c7 * in[7]; + const int b1 = c3 * in[1] - c7 * in[3] - c1 * in[5] - c5 * in[7]; + const int b2 = c5 * in[1] - c1 * in[3] + c7 * in[5] + c3 * in[7]; + const int b3 = c7 * in[1] - c5 * in[3] + c3 * in[5] - c1 * in[7]; + + in[0] = (a0 + b0) >> ROW_SHIFT; + in[1] = (a1 + b1) >> ROW_SHIFT; + in[2] = (a2 + b2) >> ROW_SHIFT; + in[3] = (a3 + b3) >> ROW_SHIFT; + in[4] = (a3 - b3) >> ROW_SHIFT; + in[5] = (a2 - b2) >> ROW_SHIFT; + in[6] = (a1 - b1) >> ROW_SHIFT; + in[7] = (a0 - b0) >> ROW_SHIFT; + } + return 1; +} + +#define TAN1 0x32EC +#define TAN2 0x6A0A +#define TAN3 0xAB0E +#define SQRT2 0x5A82 + +#define MULT(c, x, n) (((c) * (x)) >> (n)) +// 12b version => #define MULT(c,x, n) ((((c) >> 3) * (x)) >> ((n) - 3)) +// 12b zero-testing version: + +#define BUTTERFLY(a, b, tmp) \ + (tmp) = (a) + (b); \ + (b) = (a) - (b); \ + (a) = (tmp) + +#define LOAD_BUTTERFLY(m1, m2, a, b, tmp, s) \ + (m1) = (s)[(a)] + (s)[(b)]; \ + (m2) = (s)[(a)] - (s)[(b)] + +static void idct_col_8(short *const in) +{ + int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, spill; + + // odd + + mm4 = (int) in[7 * 8]; + mm5 = (int) in[5 * 8]; + mm6 = (int) in[3 * 8]; + mm7 = (int) in[1 * 8]; + + mm0 = MULT(TAN1, mm4, 16) + mm7; + mm1 = MULT(TAN1, mm7, 16) - mm4; + mm2 = MULT(TAN3, mm5, 16) + mm6; + mm3 = MULT(TAN3, mm6, 16) - mm5; + + mm7 = mm0 + mm2; + mm4 = mm1 - mm3; + mm0 = mm0 - mm2; + mm1 = mm1 + mm3; + mm6 = mm0 + mm1; + mm5 = mm0 - mm1; + mm5 = 2 * MULT(SQRT2, mm5, 16); // 2*sqrt2 + mm6 = 2 * MULT(SQRT2, mm6, 16); // Watch out: precision loss but done to match + // the pmulhw used in MMX/MMXEXT/SSE2 versions + + // even + + mm1 = (int) in[2 * 8]; + mm2 = (int) in[6 * 8]; + mm3 = MULT(TAN2, mm2, 16) + mm1; + mm2 = MULT(TAN2, mm1, 16) - mm2; + + LOAD_BUTTERFLY(mm0, mm1, 0 * 8, 4 * 8, spill, in); + + BUTTERFLY(mm0, mm3, spill); + BUTTERFLY(mm0, mm7, spill); + in[8 * 0] = (int16_t) (mm0 >> COL_SHIFT); + in[8 * 7] = (int16_t) (mm7 >> COL_SHIFT); + BUTTERFLY(mm3, mm4, mm0); + in[8 * 3] = (int16_t) (mm3 >> COL_SHIFT); + in[8 * 4] = (int16_t) (mm4 >> COL_SHIFT); + + BUTTERFLY(mm1, mm2, mm0); + BUTTERFLY(mm1, mm6, mm0); + in[8 * 1] = (int16_t) (mm1 >> COL_SHIFT); + in[8 * 6] = (int16_t) (mm6 >> COL_SHIFT); + BUTTERFLY(mm2, mm5, mm0); + in[8 * 2] = (int16_t) (mm2 >> COL_SHIFT); + in[8 * 5] = (int16_t) (mm5 >> COL_SHIFT); +} + +static void idct_col_4(short *const in) +{ + int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, spill; + + // odd + + mm0 = (int) in[1 * 8]; + mm2 = (int) in[3 * 8]; + + mm1 = MULT(TAN1, mm0, 16); + mm3 = MULT(TAN3, mm2, 16); + + mm7 = mm0 + mm2; + mm4 = mm1 - mm3; + mm0 = mm0 - mm2; + mm1 = mm1 + mm3; + mm6 = mm0 + mm1; + mm5 = mm0 - mm1; + mm6 = 2 * MULT(SQRT2, mm6, 16); // 2*sqrt2 + mm5 = 2 * MULT(SQRT2, mm5, 16); + + // even + + mm0 = mm1 = (int) in[0 * 8]; + mm3 = (int) in[2 * 8]; + mm2 = MULT(TAN2, mm3, 16); + + BUTTERFLY(mm0, mm3, spill); + BUTTERFLY(mm0, mm7, spill); + in[8 * 0] = (int16_t) (mm0 >> COL_SHIFT); + in[8 * 7] = (int16_t) (mm7 >> COL_SHIFT); + BUTTERFLY(mm3, mm4, mm0); + in[8 * 3] = (int16_t) (mm3 >> COL_SHIFT); + in[8 * 4] = (int16_t) (mm4 >> COL_SHIFT); + + BUTTERFLY(mm1, mm2, mm0); + BUTTERFLY(mm1, mm6, mm0); + in[8 * 1] = (int16_t) (mm1 >> COL_SHIFT); + in[8 * 6] = (int16_t) (mm6 >> COL_SHIFT); + BUTTERFLY(mm2, mm5, mm0); + in[8 * 2] = (int16_t) (mm2 >> COL_SHIFT); + in[8 * 5] = (int16_t) (mm5 >> COL_SHIFT); +} + +static void idct_col_3(short *const in) +{ + int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, spill; + + // odd + + mm7 = (int) in[1 * 8]; + mm4 = MULT(TAN1, mm7, 16); + + mm6 = mm7 + mm4; + mm5 = mm7 - mm4; + mm6 = 2 * MULT(SQRT2, mm6, 16); // 2*sqrt2 + mm5 = 2 * MULT(SQRT2, mm5, 16); + + // even + + mm0 = mm1 = (int) in[0 * 8]; + mm3 = (int) in[2 * 8]; + mm2 = MULT(TAN2, mm3, 16); + + BUTTERFLY(mm0, mm3, spill); + BUTTERFLY(mm0, mm7, spill); + in[8 * 0] = (int16_t) (mm0 >> COL_SHIFT); + in[8 * 7] = (int16_t) (mm7 >> COL_SHIFT); + BUTTERFLY(mm3, mm4, mm0); + in[8 * 3] = (int16_t) (mm3 >> COL_SHIFT); + in[8 * 4] = (int16_t) (mm4 >> COL_SHIFT); + + BUTTERFLY(mm1, mm2, mm0); + BUTTERFLY(mm1, mm6, mm0); + in[8 * 1] = (int16_t) (mm1 >> COL_SHIFT); + in[8 * 6] = (int16_t) (mm6 >> COL_SHIFT); + BUTTERFLY(mm2, mm5, mm0); + in[8 * 2] = (int16_t) (mm2 >> COL_SHIFT); + in[8 * 5] = (int16_t) (mm5 >> COL_SHIFT); +} + +void ff_xvid_idct(int16_t *const in) +{ + int i, rows = 0x07; + + idct_row(in + 0 * 8, TAB04, RND0); + idct_row(in + 1 * 8, TAB17, RND1); + idct_row(in + 2 * 8, TAB26, RND2); + if (idct_row(in + 3 * 8, TAB35, RND3)) + rows |= 0x08; + if (idct_row(in + 4 * 8, TAB04, RND4)) + rows |= 0x10; + if (idct_row(in + 5 * 8, TAB35, RND5)) + rows |= 0x20; + if (idct_row(in + 6 * 8, TAB26, RND6)) + rows |= 0x40; + if (idct_row(in + 7 * 8, TAB17, RND7)) + rows |= 0x80; + + if (rows & 0xF0) { + for (i = 0; i < 8; i++) + idct_col_8(in + i); + } else if (rows & 0x08) { + for (i = 0; i < 8; i++) + idct_col_4(in + i); + } else { + for (i = 0; i < 8; i++) + idct_col_3(in + i); + } +} + +static void xvid_idct_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct(block); + ff_put_pixels_clamped(block, dest, line_size); +} + +static void xvid_idct_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_xvid_idct(block); + ff_add_pixels_clamped(block, dest, line_size); +} + +av_cold void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx) { const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; - if (high_bit_depth || - !(avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_XVID)) - return; + if (!high_bit_depth && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_XVID)) { + c->idct_put = xvid_idct_put; + c->idct_add = xvid_idct_add; + c->idct = ff_xvid_idct; + c->perm_type = FF_IDCT_PERM_NONE; + } if (ARCH_X86) - ff_xvididct_init_x86(c); + ff_xvid_idct_init_x86(c, avctx, high_bit_depth); ff_init_scantable_permutation(c->idct_permutation, c->perm_type); } diff --git a/libavcodec/xvididct.h b/libavcodec/xvididct.h index a688bc8..499f819 100644 --- a/libavcodec/xvididct.h +++ b/libavcodec/xvididct.h @@ -19,11 +19,16 @@ #ifndef AVCODEC_XVIDIDCT_H #define AVCODEC_XVIDIDCT_H +#include + #include "avcodec.h" #include "idctdsp.h" -void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx); +void ff_xvid_idct(int16_t *const in); + +void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx); -void ff_xvididct_init_x86(IDCTDSPContext *c); +void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); #endif /* AVCODEC_XVIDIDCT_H */ diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c index f6ccb96..1c9874a 100644 --- a/libavcodec/xwddec.c +++ b/libavcodec/xwddec.c @@ -141,7 +141,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { + if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + (uint64_t)avctx->height * lsize) { av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); return AVERROR_INVALIDDATA; } @@ -248,5 +248,5 @@ AVCodec ff_xwd_decoder = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_XWD, .decode = xwd_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c index 54599a0..e346b5c 100644 --- a/libavcodec/xwdenc.c +++ b/libavcodec/xwdenc.c @@ -30,15 +30,6 @@ #define WINDOW_NAME "lavcxwdenc" #define WINDOW_NAME_SIZE 11 -static av_cold int xwd_encode_init(AVCodecContext *avctx) -{ - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); - - return 0; -} - static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { @@ -155,8 +146,12 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } buf = pkt->data; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif bytestream_put_be32(&buf, header_size); bytestream_put_be32(&buf, XWD_VERSION); // file version @@ -213,21 +208,12 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static av_cold int xwd_encode_close(AVCodecContext *avctx) -{ - av_freep(&avctx->coded_frame); - - return 0; -} - AVCodec ff_xwd_encoder = { .name = "xwd", .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_XWD, - .init = xwd_encode_init, .encode2 = xwd_encode_frame, - .close = xwd_encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c index d77a50f..5495bec 100644 --- a/libavcodec/xxan.c +++ b/libavcodec/xxan.c @@ -20,12 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" + +#include "avcodec.h" #include "bytestream.h" -#define BITSTREAM_READER_LE -#include "get_bits.h" #include "internal.h" typedef struct XanContext { @@ -440,5 +439,5 @@ AVCodec ff_xan_wc4_decoder = { .init = xan_decode_init, .close = xan_decode_end, .decode = xan_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/yop.c b/libavcodec/yop.c index 3434fd9..5de4ac8 100644 --- a/libavcodec/yop.c +++ b/libavcodec/yop.c @@ -22,11 +22,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" +#include + #include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "get_bits.h" #include "internal.h" typedef struct YopDecContext { @@ -251,5 +253,5 @@ AVCodec ff_yop_decoder = { .priv_data_size = sizeof(YopDecContext), .init = yop_decode_init, .decode = yop_decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/zerocodec.c b/libavcodec/zerocodec.c index eeba2de..1419e84 100644 --- a/libavcodec/zerocodec.c +++ b/libavcodec/zerocodec.c @@ -22,7 +22,7 @@ #include "internal.h" #include "libavutil/common.h" -typedef struct { +typedef struct ZeroCodecContext { AVFrame *previous_frame; z_stream zstream; } ZeroCodecContext; @@ -150,5 +150,5 @@ AVCodec ff_zerocodec_decoder = { .init = zerocodec_decode_init, .decode = zerocodec_decode_frame, .close = zerocodec_decode_close, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index f49cbdb..f945aea 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -498,7 +498,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return AVERROR_INVALIDDATA; } - if (c->comp == 0) { //Uncompressed data + if (c->comp == 0) { // uncompressed data if (c->decomp_size < len) { av_log(avctx, AV_LOG_ERROR, "Buffer too small\n"); return AVERROR_INVALIDDATA; @@ -662,5 +662,5 @@ AVCodec ff_zmbv_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c index d7b518d..4436bb3 100644 --- a/libavcodec/zmbvenc.c +++ b/libavcodec/zmbvenc.c @@ -133,8 +133,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, c->curfrm++; if(c->curfrm == c->keyint) c->curfrm = 0; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; avctx->coded_frame->key_frame = keyframe; +FF_ENABLE_DEPRECATION_WARNINGS +#endif chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024); palptr = (uint32_t*)p->data[1]; @@ -261,8 +265,6 @@ static av_cold int encode_end(AVCodecContext *avctx) deflateEnd(&c->zstream); av_freep(&c->prev); - av_frame_free(&avctx->coded_frame); - return 0; } @@ -326,12 +328,6 @@ static av_cold int encode_init(AVCodecContext *avctx) return -1; } - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - encode_end(avctx); - return AVERROR(ENOMEM); - } - return 0; } diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 25e126c..5bb1d3f 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -6,31 +6,30 @@ HEADERS = avdevice.h \ OBJS = alldevices.o \ avdevice.o \ +OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o + # input/output devices -OBJS-$(CONFIG_ALSA_INDEV) += alsa-audio-common.o \ - alsa-audio-dec.o -OBJS-$(CONFIG_ALSA_OUTDEV) += alsa-audio-common.o \ - alsa-audio-enc.o +OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o +OBJS-$(CONFIG_ALSA_OUTDEV) += alsa_enc.o alsa.o +OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o -OBJS-$(CONFIG_JACK_INDEV) += jack_audio.o timefilter.o -OBJS-$(CONFIG_OSS_INDEV) += oss_audio.o oss_audio_dec.o -OBJS-$(CONFIG_OSS_OUTDEV) += oss_audio.o oss_audio_enc.o +OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o +OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o +OBJS-$(CONFIG_OSS_OUTDEV) += oss_enc.o oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o -OBJS-$(CONFIG_SNDIO_INDEV) += sndio_common.o sndio_dec.o -OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_common.o sndio_enc.o +OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o +OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_enc.o sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o -OBJS-$(CONFIG_X11GRAB_INDEV) += x11grab.o +OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o # external libraries OBJS-$(CONFIG_LIBCDIO_INDEV) += libcdio.o OBJS-$(CONFIG_LIBDC1394_INDEV) += libdc1394.o -OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o - -SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H) += alsa-audio.h -SKIPHEADERS-$(HAVE_SNDIO_H) += sndio_common.h +SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H) += alsa.h +SKIPHEADERS-$(HAVE_SNDIO_H) += sndio.h -TESTPROGS = timefilter +TESTPROGS-$(CONFIG_JACK_INDEV) += timefilter diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 155f7a8..cdbca4c 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -48,6 +48,7 @@ void avdevice_register_all(void) /* devices */ REGISTER_INOUTDEV(ALSA, alsa); + REGISTER_INDEV (AVFOUNDATION, avfoundation); REGISTER_INDEV (BKTR, bktr); REGISTER_INDEV (DV1394, dv1394); REGISTER_INDEV (FBDEV, fbdev); @@ -57,7 +58,7 @@ void avdevice_register_all(void) REGISTER_INOUTDEV(SNDIO, sndio); REGISTER_INDEV (V4L2, v4l2); REGISTER_INDEV (VFWCAP, vfwcap); - REGISTER_INDEV (X11GRAB, x11grab); + REGISTER_INDEV (XCBGRAB, xcbgrab); /* external libraries */ REGISTER_INDEV (LIBCDIO, libcdio); diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa.c similarity index 99% rename from libavdevice/alsa-audio-common.c rename to libavdevice/alsa.c index 21f1594..d394e43 100644 --- a/libavdevice/alsa-audio-common.c +++ b/libavdevice/alsa.c @@ -33,7 +33,7 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" -#include "alsa-audio.h" +#include "alsa.h" static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id) { @@ -194,7 +194,7 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, snd_pcm_t *h; snd_pcm_hw_params_t *hw_params; snd_pcm_uframes_t buffer_size, period_size; - uint64_t layout = ctx->streams[0]->codec->channel_layout; + uint64_t layout = ctx->streams[0]->codecpar->channel_layout; if (ctx->filename[0] == 0) audio_device = "default"; else audio_device = ctx->filename; diff --git a/libavdevice/alsa-audio.h b/libavdevice/alsa.h similarity index 96% rename from libavdevice/alsa-audio.h rename to libavdevice/alsa.h index 26eaee6..590b354 100644 --- a/libavdevice/alsa-audio.h +++ b/libavdevice/alsa.h @@ -27,8 +27,8 @@ * @author Benoit Fouet ( benoit fouet free fr ) */ -#ifndef AVDEVICE_ALSA_AUDIO_H -#define AVDEVICE_ALSA_AUDIO_H +#ifndef AVDEVICE_ALSA_H +#define AVDEVICE_ALSA_H #include #include "config.h" @@ -93,4 +93,4 @@ int ff_alsa_xrun_recover(AVFormatContext *s1, int err); int ff_alsa_extend_reorder_buf(AlsaData *s, int size); -#endif /* AVDEVICE_ALSA_AUDIO_H */ +#endif /* AVDEVICE_ALSA_H */ diff --git a/libavdevice/alsa-audio-dec.c b/libavdevice/alsa_dec.c similarity index 92% rename from libavdevice/alsa-audio-dec.c rename to libavdevice/alsa_dec.c index 0687a4a..58bf1dd 100644 --- a/libavdevice/alsa-audio-dec.c +++ b/libavdevice/alsa_dec.c @@ -46,11 +46,14 @@ */ #include + +#include "libavutil/internal.h" +#include "libavutil/opt.h" + #include "libavformat/avformat.h" #include "libavformat/internal.h" -#include "libavutil/opt.h" -#include "alsa-audio.h" +#include "alsa.h" static av_cold int audio_read_header(AVFormatContext *s1) { @@ -98,10 +101,10 @@ static av_cold int audio_read_header(AVFormatContext *s1) } /* take real parameters */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = codec_id; - st->codec->sample_rate = s->sample_rate; - st->codec->channels = s->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ return 0; @@ -125,14 +128,14 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) { if (res == -EAGAIN) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EAGAIN); } if (ff_alsa_xrun_recover(s1, res) < 0) { av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", snd_strerror(res)); - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } @@ -141,9 +144,9 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) snd_pcm_htimestamp(s->h, &ts_delay, ×tamp); ts_delay += res; pkt->pts = timestamp.tv_sec * 1000000LL - + (timestamp.tv_nsec * st->codec->sample_rate - - (int64_t)ts_delay * 1000000000LL + st->codec->sample_rate * 500LL) - / (st->codec->sample_rate * 1000LL); + + (timestamp.tv_nsec * st->codecpar->sample_rate + - (int64_t)ts_delay * 1000000000LL + st->codecpar->sample_rate * 500LL) + / (st->codecpar->sample_rate * 1000LL); pkt->size = res * s->frame_size; diff --git a/libavdevice/alsa-audio-enc.c b/libavdevice/alsa_enc.c similarity index 91% rename from libavdevice/alsa-audio-enc.c rename to libavdevice/alsa_enc.c index bb4575f..3094b50 100644 --- a/libavdevice/alsa-audio-enc.c +++ b/libavdevice/alsa_enc.c @@ -38,9 +38,12 @@ */ #include + +#include "libavutil/internal.h" + #include "libavformat/avformat.h" -#include "alsa-audio.h" +#include "alsa.h" static av_cold int audio_write_header(AVFormatContext *s1) { @@ -51,14 +54,14 @@ static av_cold int audio_write_header(AVFormatContext *s1) int res; st = s1->streams[0]; - sample_rate = st->codec->sample_rate; - codec_id = st->codec->codec_id; + sample_rate = st->codecpar->sample_rate; + codec_id = st->codecpar->codec_id; res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate, - st->codec->channels, &codec_id); - if (sample_rate != st->codec->sample_rate) { + st->codecpar->channels, &codec_id); + if (sample_rate != st->codecpar->sample_rate) { av_log(s1, AV_LOG_ERROR, "sample rate %d not available, nearest is %d\n", - st->codec->sample_rate, sample_rate); + st->codecpar->sample_rate, sample_rate); goto fail; } diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 39166a5..7404311 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -36,7 +36,7 @@ * (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own * I/O functions). The filename passed to avformat_open_input() often does not * refer to an actually existing file, but has some special device-specific - * meaning - e.g. for x11grab it is the display name. + * meaning - e.g. for xcbgrab it is the display name. * * To use libavdevice, simply call avdevice_register_all() to register all * compiled muxers and demuxers. They all use standard libavformat API. diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m new file mode 100644 index 0000000..f01484c --- /dev/null +++ b/libavdevice/avfoundation_dec.m @@ -0,0 +1,686 @@ +/* + * AVFoundation input device + * Copyright (c) 2015 Luca Barbato + * Alexandre Lision + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#import +#include + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" + +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" + +#include "avdevice.h" + +struct AVPixelFormatMap { + enum AVPixelFormat pix_fmt; + OSType core_video_fmt; +}; + +static const struct AVPixelFormatMap pixel_format_map[] = { + { AV_PIX_FMT_ABGR, kCVPixelFormatType_32ABGR }, + { AV_PIX_FMT_ARGB, kCVPixelFormatType_32ARGB }, + { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR }, + { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB }, + { AV_PIX_FMT_BGRA, kCVPixelFormatType_32BGRA }, + { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome }, + { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange }, + { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB }, + { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 }, + { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 }, + { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 }, + { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 }, + { AV_PIX_FMT_RGBA, kCVPixelFormatType_32RGBA }, + { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 }, + { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar }, + { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 }, + { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 }, + { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 }, + { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 }, + { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R }, + { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 }, + { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs }, +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 + { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 }, +#endif + { AV_PIX_FMT_NONE, 0 } +}; + +static enum AVPixelFormat core_video_to_pix_fmt(OSType core_video_fmt) +{ + int i; + for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) + if (core_video_fmt == pixel_format_map[i].core_video_fmt) + return pixel_format_map[i].pix_fmt; + return AV_PIX_FMT_NONE; +} + +static OSType pix_fmt_to_core_video(enum AVPixelFormat pix_fmt) +{ + int i; + for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) + if (pix_fmt == pixel_format_map[i].pix_fmt) + return pixel_format_map[i].core_video_fmt; + return 0; +} + +typedef struct AVFoundationCaptureContext { + AVClass *class; + /* AVOptions */ + int list_devices; + int list_formats; + char *pixel_format; + char *video_size; /* String describing video size */ + char *framerate; /* String describing the framerate */ + + int video_stream_index; + int width, height; + AVRational internal_framerate; + + int64_t first_pts; + int frames_captured; + pthread_mutex_t frame_lock; + pthread_cond_t frame_wait_cond; + + /* ARC-compatible pointers to ObjC objects */ + CFTypeRef session; /* AVCaptureSession */ + CFTypeRef video_output; + CFTypeRef video_delegate; + CVImageBufferRef current_frame; +} AVFoundationCaptureContext; + +#define AUDIO_DEVICES 1 +#define VIDEO_DEVICES 2 +#define ALL_DEVICES AUDIO_DEVICES | VIDEO_DEVICES + +#define OFFSET(x) offsetof(AVFoundationCaptureContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "list_devices", "List available devices and exit", OFFSET(list_devices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC, "list_devices" }, + { "all", "Show all the supported devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = ALL_DEVICES }, 0, INT_MAX, DEC, "list_devices" }, + { "audio", "Show only the audio devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = AUDIO_DEVICES }, 0, INT_MAX, DEC, "list_devices" }, + { "video", "Show only the video devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = VIDEO_DEVICES }, 0, INT_MAX, DEC, "list_devices" }, + { "list_formats", "List available formats and exit", OFFSET(list_formats), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC, "list_formats" }, + { "pixel_format", "Preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC }, + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC }, + { "framerate", "A string representing desired framerate", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC }, + { NULL }, +}; + +static void list_capture_devices_by_type(AVFormatContext *s, NSString *type) +{ + NSArray *devices = [AVCaptureDevice devicesWithMediaType:type]; + + av_log(s, AV_LOG_INFO, "Type: %s\n", [type UTF8String]); + for (AVCaptureDevice *device in devices) { + av_log(s, AV_LOG_INFO, "uniqueID: %s\nname: %s\nformat:\n", + [[device uniqueID] UTF8String], + [[device localizedName] UTF8String]); + + for (AVCaptureDeviceFormat *format in device.formats) + av_log(s, AV_LOG_INFO, "\t%s\n", + [[NSString stringWithFormat: @ "%@", format] UTF8String]); + } +} + +static int avfoundation_list_capture_devices(AVFormatContext *s) +{ + AVFoundationCaptureContext *ctx = s->priv_data; + + if (ctx->list_devices & AUDIO_DEVICES) + list_capture_devices_by_type(s, AVMediaTypeAudio); + + if (ctx->list_devices & VIDEO_DEVICES) + list_capture_devices_by_type(s, AVMediaTypeVideo); + + return AVERROR_EXIT; +} + +static int list_formats(AVFormatContext *s) +{ + av_log(s, AV_LOG_VERBOSE, "Supported pixel formats (first is more efficient):\n"); + AVCaptureVideoDataOutput *out = [[AVCaptureVideoDataOutput alloc] init]; + + for (NSNumber *cv_pixel_format in[out availableVideoCVPixelFormatTypes]) { + OSType cv_fmt = [cv_pixel_format intValue]; + enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt); + if (pix_fmt != AV_PIX_FMT_NONE) { + av_log(s, AV_LOG_VERBOSE, " %s: %d\n", + av_get_pix_fmt_name(pix_fmt), + cv_fmt); + } + } + return AVERROR_EXIT; +} + +static void lock_frames(AVFoundationCaptureContext *ctx) +{ + pthread_mutex_lock(&ctx->frame_lock); +} + +static void unlock_frames(AVFoundationCaptureContext *ctx) +{ + pthread_mutex_unlock(&ctx->frame_lock); +} + +@interface VideoCapture : NSObject +{ + AVFoundationCaptureContext *_context; +} + +- (id)initWithContext:(AVFoundationCaptureContext *)context; + +- (void)captureOutput:(AVCaptureOutput *)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)videoFrame + fromConnection:(AVCaptureConnection *)connection; + +@end + +@implementation VideoCapture + +- (id)initWithContext:(AVFoundationCaptureContext *)context +{ + if (self = [super init]) { + _context = context; + } + return self; +} + +- (void)captureOutput:(AVCaptureOutput *)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)videoFrame + fromConnection:(AVCaptureConnection *)connection +{ + CVImageBufferRef buf; + lock_frames(_context); + + if (_context->current_frame != nil) { + CFRelease(_context->current_frame); + } + + buf = CMSampleBufferGetImageBuffer(videoFrame); + if (!buf) + return; + + CFRetain(buf); + + _context->current_frame = buf; + + pthread_cond_signal(&_context->frame_wait_cond); + + unlock_frames(_context); + + ++_context->frames_captured; +} + +@end + +/** + * Configure the video device. + */ +static bool configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device) +{ + AVFoundationCaptureContext *ctx = s->priv_data; + AVCaptureDeviceFormat *selected_format = nil; + AVFrameRateRange *selected_range = nil; + double framerate = av_q2d(ctx->internal_framerate); + double epsilon = 0.00000001; + + for (AVCaptureDeviceFormat *format in[video_device formats]) { + CMFormatDescriptionRef formatDescription; + CMVideoDimensions dimensions; + + formatDescription = (CMFormatDescriptionRef)format.formatDescription; + dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription); + + if ((ctx->width == 0 && ctx->height == 0) || + (dimensions.width == ctx->width && dimensions.height == ctx->height)) { + av_log(s, AV_LOG_VERBOSE, "Trying video size %dx%d\n", + dimensions.width, dimensions.height); + ctx->width = dimensions.width; + ctx->height = dimensions.height; + selected_format = format; + if (framerate) { + av_log(s, AV_LOG_VERBOSE, "Checking support for framerate %f\n", + framerate); + for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) + if (range.minFrameRate <= (framerate + epsilon) && + range.maxFrameRate >= (framerate - epsilon)) { + selected_range = range; + break; + } + } else { + selected_range = format.videoSupportedFrameRateRanges[0]; + framerate = selected_range.maxFrameRate; + break; + } + + if (selected_format && selected_range) + break; + } + } + + if (!selected_format) { + av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device\n", + ctx->width, ctx->height); + return false; + } else { + av_log(s, AV_LOG_VERBOSE, "Setting video size to %dx%d\n", + ctx->width, ctx->height); + } + + if (framerate && !selected_range) { + av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device\n", + framerate); + return false; + } else { + av_log(s, AV_LOG_VERBOSE, "Setting framerate to %f\n", + framerate); + } + + if ([video_device lockForConfiguration : NULL] == YES) { + [video_device setActiveFormat : selected_format]; + [video_device setActiveVideoMinFrameDuration : CMTimeMake(1, framerate)]; + [video_device setActiveVideoMaxFrameDuration : CMTimeMake(1, framerate)]; + } else { + av_log(s, AV_LOG_ERROR, "Could not lock device for configuration\n"); + return false; + } + return true; +} + +static void print_supported_formats(AVFormatContext *s, AVCaptureDevice *device) +{ + av_log(s, AV_LOG_WARNING, "Supported modes:\n"); + for (AVCaptureDeviceFormat *format in[device formats]) { + CMFormatDescriptionRef formatDescription; + CMVideoDimensions dimensions; + + formatDescription = (CMFormatDescriptionRef)format.formatDescription; + dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription); + + for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) + av_log(s, AV_LOG_WARNING, " %dx%d@[%f %f]fps\n", + dimensions.width, dimensions.height, + range.minFrameRate, range.maxFrameRate); + } +} + +static int setup_stream(AVFormatContext *s, AVCaptureDevice *device) +{ + AVFoundationCaptureContext *ctx = s->priv_data; + NSError *__autoreleasing error = nil; + AVCaptureDeviceInput *input; + AVCaptureSession *session = (__bridge AVCaptureSession *)ctx->session; + + av_log(s, AV_LOG_VERBOSE, "Setting up stream for device %s\n", [[device uniqueID] UTF8String]); + + if (!configure_video_device(s, device)) { + av_log(s, AV_LOG_ERROR, "device configuration failed\n"); + print_supported_formats(s, device); + return AVERROR(EINVAL); + } + + // add the input devices + input = [AVCaptureDeviceInput deviceInputWithDevice:device + error:&error]; + if (!input) { + av_log(s, AV_LOG_ERROR, "%s\n", + [[error localizedDescription] UTF8String]); + return AVERROR_UNKNOWN; + } + + if ([session canAddInput : input]) { + [session addInput : input]; + } else { + av_log(s, AV_LOG_ERROR, "Cannot add video input to capture session\n"); + return AVERROR(EINVAL); + } + + // add the output devices + if ([device hasMediaType : AVMediaTypeVideo]) { + AVCaptureVideoDataOutput *out = [[AVCaptureVideoDataOutput alloc] init]; + NSNumber *core_video_fmt = nil; + if (!out) { + av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n"); + return AVERROR(EINVAL); + } + + [out setAlwaysDiscardsLateVideoFrames : YES]; + + if (ctx->pixel_format) { + // Try to use specified pixel format + core_video_fmt = [NSNumber numberWithInt:pix_fmt_to_core_video(av_get_pix_fmt(ctx->pixel_format))]; + if ([[out availableVideoCVPixelFormatTypes] indexOfObject : core_video_fmt] != NSNotFound) { + av_log(s, AV_LOG_VERBOSE, "Pixel format %s supported!\n", ctx->pixel_format); + } else { + core_video_fmt = nil; + } + } + + if (!ctx->pixel_format || !core_video_fmt) { + av_log(s, AV_LOG_VERBOSE, "Pixel format not supported or not provided, overriding...\n"); + for (NSNumber *cv_pixel_format in[out availableVideoCVPixelFormatTypes]) { + OSType cv_fmt = [cv_pixel_format intValue]; + enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt); + // Use the first one in the list, it will be the most effective + if (pix_fmt != AV_PIX_FMT_NONE) { + core_video_fmt = cv_pixel_format; + ctx->pixel_format = av_strdup(av_get_pix_fmt_name(pix_fmt)); + break; + } + } + } + + // fail if there is no appropriate pixel format + if (!core_video_fmt) { + return AVERROR(EINVAL); + } else { + av_log(s, AV_LOG_VERBOSE, "Using %s.\n", + ctx->pixel_format); + } + + NSDictionary *capture_dict = [NSDictionary dictionaryWithObject:core_video_fmt + forKey:(const NSString *)kCVPixelBufferPixelFormatTypeKey]; + [out setVideoSettings : capture_dict]; + + VideoCapture *delegate = [[VideoCapture alloc] initWithContext:ctx]; + + dispatch_queue_t queue = dispatch_queue_create("avf_queue", NULL); + [out setSampleBufferDelegate : delegate queue : queue]; + + if ([session canAddOutput : out]) { + [session addOutput : out]; + ctx->video_output = (__bridge_retained CFTypeRef)out; + ctx->video_delegate = (__bridge_retained CFTypeRef)delegate; + } else { + av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n"); + return AVERROR(EINVAL); + } + } + + return 0; +} + +static int get_video_config(AVFormatContext *s) +{ + AVFoundationCaptureContext *ctx = (AVFoundationCaptureContext *)s->priv_data; + CVImageBufferRef image_buffer; + CGSize image_buffer_size; + AVStream *stream = avformat_new_stream(s, NULL); + + if (!stream) { + av_log(s, AV_LOG_ERROR, "Failed to create AVStream\n"); + return AVERROR(EINVAL); + } + + // Take stream info from the first frame. + while (ctx->frames_captured < 1) + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES); + + lock_frames(ctx); + + ctx->video_stream_index = stream->index; + + avpriv_set_pts_info(stream, 64, 1, 1000000); + + image_buffer = ctx->current_frame; + image_buffer_size = CVImageBufferGetEncodedSize(image_buffer); + + stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; + stream->codec->width = (int)image_buffer_size.width; + stream->codec->height = (int)image_buffer_size.height; + stream->codec->pix_fmt = av_get_pix_fmt(ctx->pixel_format); + + CFRelease(ctx->current_frame); + ctx->current_frame = nil; + + unlock_frames(ctx); + + return 0; +} + +static void destroy_context(AVFoundationCaptureContext *ctx) +{ + AVCaptureSession *session = (__bridge AVCaptureSession *)ctx->session; + [session stopRunning]; + + ctx->session = NULL; + + pthread_mutex_destroy(&ctx->frame_lock); + pthread_cond_destroy(&ctx->frame_wait_cond); + + if (ctx->current_frame) { + CFRelease(ctx->current_frame); + } +} + +static int setup_default_stream(AVFormatContext *s) +{ + AVCaptureDevice *device; + for (NSString *type in @[AVMediaTypeVideo]) { + device = [AVCaptureDevice defaultDeviceWithMediaType:type]; + if (device) { + av_log(s, AV_LOG_VERBOSE, "Using default device %s\n", + [[device uniqueID] UTF8String]); + return setup_stream(s, device); + } + } + return AVERROR(EINVAL); +} + +/** + * Try to open device given in filename + * Two supported formats: "device_unique_id" or "[device_unique_id]" + */ +static AVCaptureDevice *create_device(AVFormatContext *s) +{ + NSString *filename; + NSError *__autoreleasing error = nil; + NSRegularExpression *exp; + NSArray *matches; + AVCaptureDevice *device; + + filename = [NSString stringWithFormat:@ "%s", s->filename]; + + if ((device = [AVCaptureDevice deviceWithUniqueID:filename])) { + av_log(s, AV_LOG_VERBOSE, "Device with name %s found\n", [filename UTF8String]); + return device; + } + + // Remove '[]' from the device name + NSString *pat = @"(?<=\\[).*?(?=\\])"; + exp = [NSRegularExpression regularExpressionWithPattern:pat + options:0 + error:&error]; + if (!exp) { + av_log(s, AV_LOG_ERROR, "%s\n", + [[error localizedDescription] UTF8String]); + return NULL; + } + + matches = [exp matchesInString:filename options:0 + range:NSMakeRange(0, [filename length])]; + + if (matches.count > 0) { + for (NSTextCheckingResult *match in matches) { + NSRange range = [match rangeAtIndex:0]; + NSString *uniqueID = [filename substringWithRange:NSMakeRange(range.location, range.length)]; + av_log(s, AV_LOG_VERBOSE, "opening device with ID: %s\n", [uniqueID UTF8String]); + if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) { + av_log(s, AV_LOG_ERROR, "Device with name %s not found", [filename UTF8String]); + return NULL; + } + return device; + } + } + return NULL; +} + +static int setup_streams(AVFormatContext *s) +{ + AVFoundationCaptureContext *ctx = s->priv_data; + int ret; + AVCaptureDevice *device; + + pthread_mutex_init(&ctx->frame_lock, NULL); + pthread_cond_init(&ctx->frame_wait_cond, NULL); + + ctx->session = (__bridge_retained CFTypeRef)[[AVCaptureSession alloc] init]; + + if (!strncmp(s->filename, "default", 7)) { + ret = setup_default_stream(s); + } else { + device = create_device(s); + if (device) { + ret = setup_stream(s, device); + } else { + av_log(s, AV_LOG_ERROR, "No matches for %s\n", s->filename); + ret = setup_default_stream(s); + } + } + + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "No device could be added\n"); + return ret; + } + + av_log(s, AV_LOG_VERBOSE, "Starting session!\n"); + [(__bridge AVCaptureSession *)ctx->session startRunning]; + + // Session is started, unlock device + [device unlockForConfiguration]; + + av_log(s, AV_LOG_VERBOSE, "Checking video config\n"); + if (get_video_config(s)) { + destroy_context(ctx); + return AVERROR(EIO); + } + + return 0; +} + +static int avfoundation_read_header(AVFormatContext *s) +{ + AVFoundationCaptureContext *ctx = s->priv_data; + ctx->first_pts = av_gettime(); + + AVRational framerate_q = { 0, 1 }; + ctx->internal_framerate = framerate_q; + + if (ctx->list_devices) + return avfoundation_list_capture_devices(s); + if (ctx->list_formats) { + return list_formats(s); + } + + if (ctx->pixel_format) { + if (av_get_pix_fmt(ctx->pixel_format) == AV_PIX_FMT_NONE) { + av_log(s, AV_LOG_ERROR, "No such input format: %s.\n", + ctx->pixel_format); + return AVERROR(EINVAL); + } + } + + if (ctx->video_size && + (av_parse_video_size(&ctx->width, &ctx->height, ctx->video_size)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse video size '%s'.\n", + ctx->video_size); + return AVERROR(EINVAL); + } + + if (ctx->framerate && + (av_parse_video_rate(&ctx->internal_framerate, ctx->framerate)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", + ctx->framerate); + return AVERROR(EINVAL); + } + + return setup_streams(s); +} + +static int avfoundation_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVFoundationCaptureContext *ctx = (AVFoundationCaptureContext *)s->priv_data; + + do { + lock_frames(ctx); + + if (ctx->current_frame != nil) { + if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(ctx->current_frame)) < 0) { + return AVERROR(EIO); + } + + pkt->pts = pkt->dts = av_rescale_q(av_gettime() - ctx->first_pts, + AV_TIME_BASE_Q, + (AVRational) {1, 1000000 }); + pkt->stream_index = ctx->video_stream_index; + pkt->flags |= AV_PKT_FLAG_KEY; + + CVPixelBufferLockBaseAddress(ctx->current_frame, 0); + + void *data = CVPixelBufferGetBaseAddress(ctx->current_frame); + memcpy(pkt->data, data, pkt->size); + + CVPixelBufferUnlockBaseAddress(ctx->current_frame, 0); + CFRelease(ctx->current_frame); + ctx->current_frame = nil; + } else { + pkt->data = NULL; + pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock); + } + + unlock_frames(ctx); + } while (!pkt->data); + + return 0; +} + +static int avfoundation_read_close(AVFormatContext *s) +{ + av_log(s, AV_LOG_VERBOSE, "Closing session...\n"); + AVFoundationCaptureContext *ctx = s->priv_data; + destroy_context(ctx); + return 0; +} + +static const AVClass avfoundation_class = { + .class_name = "AVFoundation AVCaptureDevice indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_avfoundation_demuxer = { + .name = "avfoundation", + .long_name = NULL_IF_CONFIG_SMALL("AVFoundation AVCaptureDevice grab"), + .priv_data_size = sizeof(AVFoundationCaptureContext), + .read_header = avfoundation_read_header, + .read_packet = avfoundation_read_packet, + .read_close = avfoundation_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &avfoundation_class, +}; diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c index 695e13f..f76a163 100644 --- a/libavdevice/bktr.c +++ b/libavdevice/bktr.c @@ -105,6 +105,8 @@ static av_cold int bktr_init(const char *video_device, int width, int height, char *arg; int c; struct sigaction act = { 0 }, old; + int ret; + char errbuf[128]; if (idev < 0 || idev > 4) { @@ -143,8 +145,10 @@ static av_cold int bktr_init(const char *video_device, int width, int height, *video_fd = avpriv_open(video_device, O_RDONLY); if (*video_fd < 0) { - av_log(NULL, AV_LOG_ERROR, "%s: %s\n", video_device, strerror(errno)); - return -1; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_ERROR, "%s: %s\n", video_device, errbuf); + return ret; } geo.rows = height; @@ -166,19 +170,25 @@ static av_cold int bktr_init(const char *video_device, int width, int height, geo.oformat |= METEOR_GEO_EVEN_ONLY; if (ioctl(*video_fd, METEORSETGEO, &geo) < 0) { - av_log(NULL, AV_LOG_ERROR, "METEORSETGEO: %s\n", strerror(errno)); - return -1; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_ERROR, "METEORSETGEO: %s\n", errbuf); + return ret; } if (ioctl(*video_fd, BT848SFMT, &c) < 0) { - av_log(NULL, AV_LOG_ERROR, "BT848SFMT: %s\n", strerror(errno)); - return -1; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_ERROR, "BT848SFMT: %s\n", errbuf); + return ret; } c = bktr_dev[idev]; if (ioctl(*video_fd, METEORSINPUT, &c) < 0) { - av_log(NULL, AV_LOG_ERROR, "METEORSINPUT: %s\n", strerror(errno)); - return -1; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_ERROR, "METEORSINPUT: %s\n", errbuf); + return ret; } video_buf_size = width * height * 12 / 8; @@ -186,8 +196,10 @@ static av_cold int bktr_init(const char *video_device, int width, int height, 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) { - av_log(NULL, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); - return -1; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_ERROR, "mmap: %s\n", errbuf); + return ret; } if (frequency != 0.0) { @@ -283,13 +295,12 @@ static int grab_read_header(AVFormatContext *s1) s->height = height; s->per_frame = ((uint64_t)1000000 * framerate.den) / framerate.num; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->pix_fmt = AV_PIX_FMT_YUV420P; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->width = width; - st->codec->height = height; - st->codec->time_base.den = framerate.num; - st->codec->time_base.num = framerate.den; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->format = AV_PIX_FMT_YUV420P; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->width = width; + st->codecpar->height = height; + st->avg_frame_rate = framerate; if (bktr_init(s1->filename, width, height, s->standard, diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c index d259e1a..addf1ad 100644 --- a/libavdevice/dv1394.c +++ b/libavdevice/dv1394.c @@ -160,7 +160,7 @@ restart_poll: av_log(context, AV_LOG_ERROR, "Failed to get status: %s\n", strerror(errno)); return AVERROR(EIO); } - av_dlog(context, "DV1394: status\n" + av_log(context, AV_LOG_TRACE, "DV1394: status\n" "\tactive_frame\t%d\n" "\tfirst_clear_frame\t%d\n" "\tn_clear_frames\t%d\n" @@ -181,7 +181,7 @@ restart_poll: } } - av_dlog(context, "index %d, avail %d, done %d\n", dv->index, dv->avail, + av_log(context, AV_LOG_TRACE, "index %d, avail %d, done %d\n", dv->index, dv->avail, dv->done); size = avpriv_dv_produce_packet(dv->dv_demux, pkt, diff --git a/libavdevice/fbdev.c b/libavdevice/fbdev.c index 34e09f9..16469c5 100644 --- a/libavdevice/fbdev.c +++ b/libavdevice/fbdev.c @@ -58,6 +58,7 @@ static struct rgb_pixfmt_map_entry rgb_pixfmt_map[] = { { 32, 3, 2, 8, 0, AV_PIX_FMT_ABGR }, { 24, 0, 8, 16, 0, AV_PIX_FMT_RGB24 }, { 24, 16, 8, 0, 0, AV_PIX_FMT_BGR24 }, + { 16, 11, 5, 0, 0, AV_PIX_FMT_RGB565 }, }; static enum AVPixelFormat get_pixfmt_from_fb_varinfo(struct fb_var_screeninfo *varinfo) @@ -100,6 +101,7 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx) AVStream *st = NULL; enum AVPixelFormat pix_fmt; int ret, flags = O_RDONLY; + char errbuf[128]; ret = av_parse_video_rate(&fbdev->framerate_q, fbdev->framerate); if (ret < 0) { @@ -117,23 +119,26 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx) if ((fbdev->fd = avpriv_open(avctx->filename, flags)) == -1) { ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s': %s\n", - avctx->filename, strerror(ret)); + avctx->filename, errbuf); return ret; } if (ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->varinfo) < 0) { ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(avctx, AV_LOG_ERROR, - "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + "FBIOGET_VSCREENINFO: %s\n", errbuf); goto fail; } if (ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->fixinfo) < 0) { ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(avctx, AV_LOG_ERROR, - "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + "FBIOGET_FSCREENINFO: %s\n", errbuf); goto fail; } @@ -154,25 +159,26 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx) fbdev->data = mmap(NULL, fbdev->fixinfo.smem_len, PROT_READ, MAP_SHARED, fbdev->fd, 0); if (fbdev->data == MAP_FAILED) { ret = AVERROR(errno); - av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", strerror(errno)); + av_strerror(ret, errbuf, sizeof(errbuf)); + av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", errbuf); goto fail; } - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->width = fbdev->width; - st->codec->height = fbdev->height; - st->codec->pix_fmt = pix_fmt; - st->codec->time_base = (AVRational){fbdev->framerate_q.den, fbdev->framerate_q.num}; - st->codec->bit_rate = + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->width = fbdev->width; + st->codecpar->height = fbdev->height; + st->codecpar->format = pix_fmt; + st->codecpar->bit_rate = fbdev->width * fbdev->height * fbdev->bytes_per_pixel * av_q2d(fbdev->framerate_q) * 8; + st->avg_frame_rate = fbdev->framerate_q; av_log(avctx, AV_LOG_INFO, "w:%d h:%d bpp:%d pixfmt:%s fps:%d/%d bit_rate:%d\n", fbdev->width, fbdev->height, fbdev->varinfo.bits_per_pixel, av_get_pix_fmt_name(pix_fmt), fbdev->framerate_q.num, fbdev->framerate_q.den, - st->codec->bit_rate); + st->codecpar->bit_rate); return 0; fail: @@ -194,7 +200,7 @@ static int fbdev_read_packet(AVFormatContext *avctx, AVPacket *pkt) /* wait based on the frame rate */ curtime = av_gettime(); delay = fbdev->time_frame - curtime; - av_dlog(avctx, + av_log(avctx, AV_LOG_TRACE, "time_frame:%"PRId64" curtime:%"PRId64" delay:%"PRId64"\n", fbdev->time_frame, curtime, delay); if (delay > 0) { @@ -211,9 +217,12 @@ static int fbdev_read_packet(AVFormatContext *avctx, AVPacket *pkt) return ret; /* refresh fbdev->varinfo, visible data position may change at each call */ - if (ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->varinfo) < 0) + if (ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->varinfo) < 0) { + char errbuf[128]; + av_strerror(AVERROR(errno), errbuf, sizeof(errbuf)); av_log(avctx, AV_LOG_WARNING, - "Error refreshing variable info: %s\n", strerror(errno)); + "Error refreshing variable info: %s\n", errbuf); + } pkt->pts = curtime; diff --git a/libavdevice/jack_audio.c b/libavdevice/jack.c similarity index 94% rename from libavdevice/jack_audio.c rename to libavdevice/jack.c index 8ce3321..0b4deee 100644 --- a/libavdevice/jack_audio.c +++ b/libavdevice/jack.c @@ -24,6 +24,7 @@ #include #include +#include "libavutil/internal.h" #include "libavutil/log.h" #include "libavutil/fifo.h" #include "libavutil/opt.h" @@ -164,6 +165,8 @@ static int start_jack(AVFormatContext *context) self->sample_rate = jack_get_sample_rate(self->client); self->ports = av_malloc(self->nports * sizeof(*self->ports)); + if (!self->ports) + return AVERROR(ENOMEM); self->buffer_size = jack_get_buffer_size(self->client); /* Register JACK ports */ @@ -199,6 +202,10 @@ static int start_jack(AVFormatContext *context) self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket)); /* New packets FIFO with one extra packet for safety against underruns */ self->new_pkts = av_fifo_alloc((FIFO_PACKETS_NUM + 1) * sizeof(AVPacket)); + if (!self->new_pkts) { + jack_client_close(self->client); + return AVERROR(ENOMEM); + } if ((test = supply_new_packets(self, context))) { jack_client_close(self->client); return test; @@ -213,7 +220,7 @@ static void free_pkt_fifo(AVFifoBuffer *fifo) AVPacket pkt; while (av_fifo_size(fifo)) { av_fifo_generic_read(fifo, &pkt, sizeof(pkt), NULL); - av_free_packet(&pkt); + av_packet_unref(&pkt); } av_fifo_free(fifo); } @@ -247,14 +254,14 @@ static int audio_read_header(AVFormatContext *context) return AVERROR(ENOMEM); } - stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; + stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; #if HAVE_BIGENDIAN - stream->codec->codec_id = AV_CODEC_ID_PCM_F32BE; + stream->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE; #else - stream->codec->codec_id = AV_CODEC_ID_PCM_F32LE; + stream->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; #endif - stream->codec->sample_rate = self->sample_rate; - stream->codec->channels = self->nports; + stream->codecpar->sample_rate = self->sample_rate; + stream->codecpar->channels = self->nports; avpriv_set_pts_info(stream, 64, 1, 1000000); /* 64 bits pts in us */ return 0; @@ -289,8 +296,11 @@ static int audio_read_packet(AVFormatContext *context, AVPacket *pkt) av_log(context, AV_LOG_ERROR, "Input error: timed out when waiting for JACK process callback output\n"); } else { + char errbuf[128]; + int ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(context, AV_LOG_ERROR, "Error while waiting for audio packet: %s\n", - strerror(errno)); + errbuf); } if (!self->client) av_log(context, AV_LOG_ERROR, "Input error: JACK server is gone\n"); diff --git a/libavdevice/libavdevice.v b/libavdevice/libavdevice.v index 663af85..33042e5 100644 --- a/libavdevice/libavdevice.v +++ b/libavdevice/libavdevice.v @@ -1,4 +1,6 @@ -LIBAVDEVICE_$MAJOR { - global: avdevice_*; - local: *; +LIBAVDEVICE_MAJOR { + global: + avdevice_*; + local: + *; }; diff --git a/libavdevice/libcdio.c b/libavdevice/libcdio.c index 06ddb4a..f19ca99 100644 --- a/libavdevice/libcdio.c +++ b/libavdevice/libcdio.c @@ -85,19 +85,19 @@ static av_cold int read_header(AVFormatContext *ctx) } cdio_paranoia_modeset(s->paranoia, s->paranoia_mode); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; if (s->drive->bigendianp) - st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; else - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codec->sample_rate = 44100; - st->codec->channels = 2; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->sample_rate = 44100; + st->codecpar->channels = 2; if (s->drive->audio_last_sector != CDIO_INVALID_LSN && s->drive->audio_first_sector != CDIO_INVALID_LSN) st->duration = s->drive->audio_last_sector - s->drive->audio_first_sector; else if (s->drive->tracks) st->duration = s->drive->disc_toc[s->drive->tracks].dwStartSector; - avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2*st->codec->channels*st->codec->sample_rate); + avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2 * st->codecpar->channels * st->codecpar->sample_rate); for (i = 0; i < s->drive->tracks; i++) { char title[16]; diff --git a/libavdevice/libdc1394.c b/libavdevice/libdc1394.c index f030e3e..a0ea592 100644 --- a/libavdevice/libdc1394.c +++ b/libavdevice/libdc1394.c @@ -21,13 +21,6 @@ */ #include "config.h" -#include "libavformat/avformat.h" -#include "libavformat/internal.h" -#include "libavutil/log.h" -#include "libavutil/mathematics.h" -#include "libavutil/opt.h" -#include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" #if HAVE_LIBDC1394_2 #include @@ -48,6 +41,17 @@ #define DC1394_FRAMERATE_240 FRAMERATE_240 #endif +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" + typedef struct dc1394_data { AVClass *class; #if HAVE_LIBDC1394_1 @@ -65,7 +69,8 @@ typedef struct dc1394_data { char *pixel_format; /**< Set by a private option. */ char *framerate; /**< Set by a private option. */ - AVPacket packet; + int size; + int stream_index; } dc1394_data; struct dc1394_frame_format { @@ -75,6 +80,7 @@ struct dc1394_frame_format { int frame_size_id; } dc1394_frame_formats[] = { { 320, 240, AV_PIX_FMT_UYVY422, DC1394_VIDEO_MODE_320x240_YUV422 }, + { 640, 480, AV_PIX_FMT_GRAY8, DC1394_VIDEO_MODE_640x480_MONO8 }, { 640, 480, AV_PIX_FMT_UYYVYY411, DC1394_VIDEO_MODE_640x480_YUV411 }, { 640, 480, AV_PIX_FMT_UYVY422, DC1394_VIDEO_MODE_640x480_YUV422 }, { 0, 0, 0, 0 } /* gotta be the last one */ @@ -165,23 +171,20 @@ static inline int dc1394_read_common(AVFormatContext *c, goto out; } avpriv_set_pts_info(vst, 64, 1, 1000); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - vst->codec->time_base.den = framerate.num; - vst->codec->time_base.num = framerate.den; - 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 |= AV_PKT_FLAG_KEY; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + vst->codecpar->width = fmt->width; + vst->codecpar->height = fmt->height; + vst->codecpar->format = fmt->pix_fmt; + vst->avg_frame_rate = framerate; dc1394->current_frame = 0; + dc1394->stream_index = vst->index; + dc1394->size = av_image_get_buffer_size(fmt->pix_fmt, + fmt->width, fmt->height, 1); - vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000); + vst->codecpar->bit_rate = av_rescale(dc1394->size * 8, + fps->frame_rate, 1000); *select_fps = fps; *select_fmt = fmt; out: @@ -257,17 +260,17 @@ static int dc1394_v1_read_packet(AVFormatContext *c, AVPacket *pkt) 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->frame_rate; - res = dc1394->packet.size; + pkt->data = (uint8_t *)dc1394->camera.capture_buffer; + pkt->size = dc1394->size; + pkt->pts = (dc1394->current_frame * 1000000) / dc1394->frame_rate; + pkt->flags |= AV_PKT_FLAG_KEY; + pkt->stream_index = dc1394->stream_index; } else { av_log(c, AV_LOG_ERROR, "DMA capture failed\n"); - dc1394->packet.data = NULL; - res = -1; + return AVERROR_INVALIDDATA; } - *pkt = dc1394->packet; - return res; + return pkt->size; } static int dc1394_v1_close(AVFormatContext * context) @@ -369,17 +372,17 @@ static int dc1394_v2_read_packet(AVFormatContext *c, AVPacket *pkt) res = dc1394_capture_dequeue(dc1394->camera, DC1394_CAPTURE_POLICY_WAIT, &dc1394->frame); if (res == DC1394_SUCCESS) { - dc1394->packet.data = (uint8_t *) dc1394->frame->image; - dc1394->packet.pts = dc1394->current_frame * 1000000 / dc1394->frame_rate; - res = dc1394->frame->image_bytes; + pkt->data = (uint8_t *)dc1394->frame->image; + pkt->size = dc1394->frame->image_bytes; + pkt->pts = dc1394->current_frame * 1000000 / dc1394->frame_rate; + pkt->flags |= AV_PKT_FLAG_KEY; + pkt->stream_index = dc1394->stream_index; } else { av_log(c, AV_LOG_ERROR, "DMA capture failed\n"); - dc1394->packet.data = NULL; - res = -1; + return AVERROR_INVALIDDATA; } - *pkt = dc1394->packet; - return res; + return pkt->size; } static int dc1394_v2_close(AVFormatContext * context) diff --git a/libavdevice/oss_audio.c b/libavdevice/oss.c similarity index 99% rename from libavdevice/oss_audio.c rename to libavdevice/oss.c index 4feb937..eb8d454 100644 --- a/libavdevice/oss_audio.c +++ b/libavdevice/oss.c @@ -39,7 +39,7 @@ #include "libavformat/avformat.h" -#include "oss_audio.h" +#include "oss.h" int ff_oss_audio_open(AVFormatContext *s1, int is_output, const char *audio_device) diff --git a/libavdevice/oss_audio.h b/libavdevice/oss.h similarity index 93% rename from libavdevice/oss_audio.h rename to libavdevice/oss.h index 87ac4ad..0fbe14b 100644 --- a/libavdevice/oss_audio.h +++ b/libavdevice/oss.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVDEVICE_OSS_AUDIO_H -#define AVDEVICE_OSS_AUDIO_H +#ifndef AVDEVICE_OSS_H +#define AVDEVICE_OSS_H #include "libavcodec/avcodec.h" @@ -42,4 +42,4 @@ int ff_oss_audio_open(AVFormatContext *s1, int is_output, int ff_oss_audio_close(OSSAudioData *s); -#endif /* AVDEVICE_OSS_AUDIO_H */ +#endif /* AVDEVICE_OSS_H */ diff --git a/libavdevice/oss_audio_dec.c b/libavdevice/oss_dec.c similarity index 94% rename from libavdevice/oss_audio_dec.c rename to libavdevice/oss_dec.c index 601d91c..6f51a30 100644 --- a/libavdevice/oss_audio_dec.c +++ b/libavdevice/oss_dec.c @@ -42,7 +42,7 @@ #include "libavformat/avformat.h" #include "libavformat/internal.h" -#include "oss_audio.h" +#include "oss.h" static int audio_read_header(AVFormatContext *s1) { @@ -61,10 +61,10 @@ static int audio_read_header(AVFormatContext *s1) } /* take real parameters */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->codec_id; - st->codec->sample_rate = s->sample_rate; - st->codec->channels = s->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ return 0; @@ -82,7 +82,7 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) ret = read(s->fd, pkt->data, pkt->size); if (ret <= 0){ - av_free_packet(pkt); + av_packet_unref(pkt); pkt->size = 0; if (ret<0) return AVERROR(errno); else return AVERROR_EOF; diff --git a/libavdevice/oss_audio_enc.c b/libavdevice/oss_enc.c similarity index 96% rename from libavdevice/oss_audio_enc.c rename to libavdevice/oss_enc.c index 688982a..eb6432c 100644 --- a/libavdevice/oss_audio_enc.c +++ b/libavdevice/oss_enc.c @@ -38,7 +38,7 @@ #include "libavformat/avformat.h" #include "libavformat/internal.h" -#include "oss_audio.h" +#include "oss.h" static int audio_write_header(AVFormatContext *s1) { @@ -47,8 +47,8 @@ static int audio_write_header(AVFormatContext *s1) int ret; st = s1->streams[0]; - s->sample_rate = st->codec->sample_rate; - s->channels = st->codec->channels; + s->sample_rate = st->codecpar->sample_rate; + s->channels = st->codecpar->channels; ret = ff_oss_audio_open(s1, 1, s1->filename); if (ret < 0) { return AVERROR(EIO); diff --git a/libavdevice/pulse.c b/libavdevice/pulse.c index 2136ee3..c4d939a 100644 --- a/libavdevice/pulse.c +++ b/libavdevice/pulse.c @@ -29,10 +29,12 @@ #include #include +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" + #include "libavformat/avformat.h" #include "libavformat/internal.h" -#include "libavutil/time.h" -#include "libavutil/opt.h" #define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) @@ -105,10 +107,10 @@ static av_cold int pulse_read_header(AVFormatContext *s) return AVERROR(EIO); } /* take real parameters */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = codec_id; - st->codec->sample_rate = pd->sample_rate; - st->codec->channels = pd->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = codec_id; + st->codecpar->sample_rate = pd->sample_rate; + st->codecpar->channels = pd->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ pd->pts = AV_NOPTS_VALUE; @@ -131,7 +133,7 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt) if ((pa_simple_read(pd->s, pkt->data, pkt->size, &res)) < 0) { av_log(s, AV_LOG_ERROR, "pa_simple_read failed: %s\n", pa_strerror(res)); - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } diff --git a/libavdevice/sndio_common.c b/libavdevice/sndio.c similarity index 99% rename from libavdevice/sndio_common.c rename to libavdevice/sndio.c index 1bea6c5..739551b 100644 --- a/libavdevice/sndio_common.c +++ b/libavdevice/sndio.c @@ -24,7 +24,7 @@ #include "libavformat/avformat.h" -#include "sndio_common.h" +#include "libavdevice/sndio.h" static inline void movecb(void *addr, int delta) { diff --git a/libavdevice/sndio_common.h b/libavdevice/sndio.h similarity index 92% rename from libavdevice/sndio_common.h rename to libavdevice/sndio.h index 2f70213..cd5c55e 100644 --- a/libavdevice/sndio_common.h +++ b/libavdevice/sndio.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVDEVICE_SNDIO_COMMON_H -#define AVDEVICE_SNDIO_COMMON_H +#ifndef AVDEVICE_SNDIO_H +#define AVDEVICE_SNDIO_H #include #include @@ -45,4 +45,4 @@ typedef struct SndioData { int ff_sndio_open(AVFormatContext *s1, int is_output, const char *audio_device); int ff_sndio_close(SndioData *s); -#endif /* AVDEVICE_SNDIO_COMMON_H */ +#endif /* AVDEVICE_SNDIO_H */ diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c index 58caaa1..a839a6f 100644 --- a/libavdevice/sndio_dec.c +++ b/libavdevice/sndio_dec.c @@ -22,12 +22,14 @@ #include #include -#include "libavformat/avformat.h" -#include "libavformat/internal.h" +#include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/time.h" -#include "sndio_common.h" +#include "libavformat/avformat.h" +#include "libavformat/internal.h" + +#include "libavdevice/sndio.h" static av_cold int audio_read_header(AVFormatContext *s1) { @@ -44,10 +46,10 @@ static av_cold int audio_read_header(AVFormatContext *s1) return ret; /* take real parameters */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->codec_id; - st->codec->sample_rate = s->sample_rate; - st->codec->channels = s->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ @@ -65,7 +67,7 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) ret = sio_read(s->hdl, pkt->data, pkt->size); if (ret == 0 || sio_eof(s->hdl)) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR_EOF; } diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c index 6f69b9e..97b1827 100644 --- a/libavdevice/sndio_enc.c +++ b/libavdevice/sndio_enc.c @@ -22,9 +22,11 @@ #include #include +#include "libavutil/internal.h" + #include "libavformat/avformat.h" -#include "sndio_common.h" +#include "libavdevice/sndio.h" static av_cold int audio_write_header(AVFormatContext *s1) { @@ -33,8 +35,8 @@ static av_cold int audio_write_header(AVFormatContext *s1) int ret; st = s1->streams[0]; - s->sample_rate = st->codec->sample_rate; - s->channels = st->codec->channels; + s->sample_rate = st->codecpar->sample_rate; + s->channels = st->codecpar->channels; ret = ff_sndio_open(s1, 1, s1->filename); diff --git a/libavdevice/tests/.gitignore b/libavdevice/tests/.gitignore new file mode 100644 index 0000000..b4a2281 --- /dev/null +++ b/libavdevice/tests/.gitignore @@ -0,0 +1 @@ +/timefilter diff --git a/libavdevice/tests/timefilter.c b/libavdevice/tests/timefilter.c new file mode 100644 index 0000000..9e8ec09 --- /dev/null +++ b/libavdevice/tests/timefilter.c @@ -0,0 +1,79 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/lfg.h" + +#include "libavdevice/timefilter.h" + +#define LFG_MAX ((1LL << 32) - 1) + +int main(void) +{ + AVLFG prng; + double n0, n1; +#define SAMPLES 1000 + double ideal[SAMPLES]; + double samples[SAMPLES]; + for (n0 = 0; n0 < 40; n0 = 2 * n0 + 1) { + for (n1 = 0; n1 < 10; n1 = 2 * n1 + 1) { + double best_error = 1000000000; + double bestpar0 = 1; + double bestpar1 = 0.001; + int better, i; + + av_lfg_init(&prng, 123); + for (i = 0; i < SAMPLES; i++) { + ideal[i] = 10 + i + n1 * i / (1000); + samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2) / (LFG_MAX * 10LL); + } + + do { + double par0, par1; + better = 0; + for (par0 = bestpar0 * 0.8; par0 <= bestpar0 * 1.21; par0 += bestpar0 * 0.05) { + for (par1 = bestpar1 * 0.8; par1 <= bestpar1 * 1.21; par1 += bestpar1 * 0.05) { + double error = 0; + TimeFilter *tf = ff_timefilter_new(1, par0, par1); + if (!tf) { + printf("Could not allocate memory for timefilter.\n"); + exit(1); + } + for (i = 0; i < SAMPLES; i++) { + double filtered; + filtered = ff_timefilter_update(tf, samples[i], 1); + error += (filtered - ideal[i]) * (filtered - ideal[i]); + } + ff_timefilter_destroy(tf); + if (error < best_error) { + best_error = error; + bestpar0 = par0; + bestpar1 = par1; + better = 1; + } + } + } + } while (better); + printf(" [%f %f %9f]", bestpar0, bestpar1, best_error); + } + printf("\n"); + } + return 0; +} diff --git a/libavdevice/timefilter.c b/libavdevice/timefilter.c index a497351..4e0d500 100644 --- a/libavdevice/timefilter.c +++ b/libavdevice/timefilter.c @@ -24,7 +24,7 @@ #include "libavutil/common.h" #include "libavutil/mem.h" -#include "config.h" + #include "timefilter.h" struct TimeFilter { @@ -77,74 +77,3 @@ double ff_timefilter_update(TimeFilter *self, double system_time, double period) } return self->cycle_time; } - -#ifdef TEST -#include "libavutil/lfg.h" -#define LFG_MAX ((1LL << 32) - 1) - -int main(void) -{ - AVLFG prng; - double n0, n1; -#define SAMPLES 1000 - double ideal[SAMPLES]; - double samples[SAMPLES]; - for (n0 = 0; n0 < 40; n0 = 2 * n0 + 1) { - for (n1 = 0; n1 < 10; n1 = 2 * n1 + 1) { - double best_error = 1000000000; - double bestpar0 = 1; - double bestpar1 = 0.001; - int better, i; - - av_lfg_init(&prng, 123); - for (i = 0; i < SAMPLES; i++) { - ideal[i] = 10 + i + n1 * i / (1000); - samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2) / (LFG_MAX * 10LL); - } - - do { - double par0, par1; - better = 0; - for (par0 = bestpar0 * 0.8; par0 <= bestpar0 * 1.21; par0 += bestpar0 * 0.05) { - for (par1 = bestpar1 * 0.8; par1 <= bestpar1 * 1.21; par1 += bestpar1 * 0.05) { - double error = 0; - TimeFilter *tf = ff_timefilter_new(1, par0, par1); - if (!tf) { - printf("Could not allocate memory for timefilter.\n"); - exit(1); - } - for (i = 0; i < SAMPLES; i++) { - double filtered; - filtered = ff_timefilter_update(tf, samples[i], 1); - error += (filtered - ideal[i]) * (filtered - ideal[i]); - } - ff_timefilter_destroy(tf); - if (error < best_error) { - best_error = error; - bestpar0 = par0; - bestpar1 = par1; - better = 1; - } - } - } - } while (better); -#if 0 - double lastfil = 9; - TimeFilter *tf = ff_timefilter_new(1, bestpar0, bestpar1); - for (i = 0; i < SAMPLES; i++) { - double filtered; - filtered = ff_timefilter_update(tf, samples[i], 1); - printf("%f %f %f %f\n", i - samples[i] + 10, filtered - samples[i], - samples[FFMAX(i, 1)] - samples[FFMAX(i - 1, 0)], filtered - lastfil); - lastfil = filtered; - } - ff_timefilter_destroy(tf); -#else - printf(" [%f %f %9f]", bestpar0, bestpar1, best_error); -#endif - } - printf("\n"); - } - return 0; -} -#endif diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index e210dc4..47241e4 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -111,6 +111,9 @@ static struct fmt_map fmt_conversion_table[] = { { AV_PIX_FMT_NV12, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 }, { AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG }, { AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, +#ifdef V4L2_PIX_FMT_H264 + { AV_PIX_FMT_NONE, AV_CODEC_ID_H264, V4L2_PIX_FMT_H264 }, +#endif }; static int device_open(AVFormatContext *ctx) @@ -119,6 +122,7 @@ static int device_open(AVFormatContext *ctx) int fd; int res, err; int flags = O_RDWR; + char errbuf[128]; if (ctx->flags & AVFMT_FLAG_NONBLOCK) { flags |= O_NONBLOCK; @@ -126,19 +130,21 @@ static int device_open(AVFormatContext *ctx) fd = avpriv_open(ctx->filename, flags); if (fd < 0) { - err = errno; + err = AVERROR(errno); + av_strerror(err, errbuf, sizeof(errbuf)); av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", - ctx->filename, strerror(err)); + ctx->filename, errbuf); - return AVERROR(err); + return err; } res = ioctl(fd, VIDIOC_QUERYCAP, &cap); if (res < 0) { - err = errno; + err = AVERROR(errno); + av_strerror(err, errbuf, sizeof(errbuf)); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", - strerror(err)); + errbuf); goto fail; } @@ -148,7 +154,7 @@ static int device_open(AVFormatContext *ctx) if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n"); - err = ENODEV; + err = AVERROR(ENODEV); goto fail; } @@ -156,7 +162,7 @@ static int device_open(AVFormatContext *ctx) if (!(cap.capabilities & V4L2_CAP_STREAMING)) { av_log(ctx, AV_LOG_ERROR, "The device does not support the streaming I/O method.\n"); - err = ENOSYS; + err = AVERROR(ENOSYS); goto fail; } @@ -165,7 +171,7 @@ static int device_open(AVFormatContext *ctx) fail: close(fd); - return AVERROR(err); + return err; } static int device_init(AVFormatContext *ctx, int *width, int *height, @@ -312,9 +318,9 @@ static void list_formats(AVFormatContext *ctx, int fd, int type) vfd.description); } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED && type & V4L_COMPFORMATS) { - AVCodec *codec = avcodec_find_encoder(codec_id); + const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :", - codec ? codec->name : "Unsupported", + desc ? desc->name : "Unsupported", vfd.description); } else { continue; @@ -345,13 +351,14 @@ static int mmap_init(AVFormatContext *ctx) res = ioctl(s->fd, VIDIOC_REQBUFS, &req); if (res < 0) { - if (errno == EINVAL) { + res = AVERROR(errno); + if (res == AVERROR(EINVAL)) { av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n"); } else { av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n"); } - return AVERROR(errno); + return res; } if (req.count < 2) { @@ -383,9 +390,10 @@ static int mmap_init(AVFormatContext *ctx) res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf); if (res < 0) { + res = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n"); - return AVERROR(errno); + return res; } s->buf_len[i] = buf.length; @@ -401,28 +409,25 @@ static int mmap_init(AVFormatContext *ctx) s->fd, buf.m.offset); if (s->buf_start[i] == MAP_FAILED) { - av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); + char errbuf[128]; + res = AVERROR(errno); + av_strerror(res, errbuf, sizeof(errbuf)); + av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", errbuf); - return AVERROR(errno); + return res; } } return 0; } -#if FF_API_DESTRUCT_PACKET -static void dummy_release_buffer(AVPacket *pkt) -{ - av_assert0(0); -} -#endif - static void mmap_release_buffer(void *opaque, uint8_t *data) { struct v4l2_buffer buf = { 0 }; int res, fd; struct buff_data *buf_descriptor = opaque; struct video_data *s = buf_descriptor->s; + char errbuf[128]; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; @@ -431,9 +436,11 @@ static void mmap_release_buffer(void *opaque, uint8_t *data) av_free(buf_descriptor); res = ioctl(fd, VIDIOC_QBUF, &buf); - if (res < 0) + if (res < 0) { + av_strerror(AVERROR(errno), errbuf, sizeof(errbuf)); av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", - strerror(errno)); + errbuf); + } avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); } @@ -457,15 +464,18 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) /* FIXME: Some special treatment might be needed in case of loss of signal... */ while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR)); if (res < 0) { + char errbuf[128]; if (errno == EAGAIN) { pkt->size = 0; return AVERROR(EAGAIN); } + res = AVERROR(errno); + av_strerror(res, errbuf, sizeof(errbuf)); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", - strerror(errno)); + errbuf); - return AVERROR(errno); + return res; } if (buf.index >= s->buffers) { @@ -496,9 +506,10 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) res = ioctl(s->fd, VIDIOC_QBUF, &buf); if (res < 0) { + res = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n"); - av_free_packet(pkt); - return AVERROR(errno); + av_packet_unref(pkt); + return res; } avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); } else { @@ -506,11 +517,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) pkt->data = s->buf_start[buf.index]; pkt->size = buf.bytesused; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dummy_release_buffer; -FF_ENABLE_DEPRECATION_WARNINGS -#endif buf_descriptor = av_malloc(sizeof(struct buff_data)); if (!buf_descriptor) { @@ -542,7 +548,8 @@ static int mmap_start(AVFormatContext *ctx) { struct video_data *s = ctx->priv_data; enum v4l2_buf_type type; - int i, res; + int i, res, err; + char errbuf[128]; for (i = 0; i < s->buffers; i++) { struct v4l2_buffer buf = { @@ -553,10 +560,12 @@ static int mmap_start(AVFormatContext *ctx) res = ioctl(s->fd, VIDIOC_QBUF, &buf); if (res < 0) { + err = AVERROR(errno); + av_strerror(err, errbuf, sizeof(errbuf)); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", - strerror(errno)); + errbuf); - return AVERROR(errno); + return err; } } s->buffers_queued = s->buffers; @@ -564,10 +573,12 @@ static int mmap_start(AVFormatContext *ctx) type = V4L2_BUF_TYPE_VIDEO_CAPTURE; res = ioctl(s->fd, VIDIOC_STREAMON, &type); if (res < 0) { + err = AVERROR(errno); + av_strerror(err, errbuf, sizeof(errbuf)); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", - strerror(errno)); + errbuf); - return AVERROR(errno); + return err; } return 0; @@ -677,9 +688,12 @@ static int v4l2_set_parameters(AVFormatContext *s1) } } else { if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { + char errbuf[128]; + ret = AVERROR(errno); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", - strerror(errno)); - return AVERROR(errno); + errbuf); + return ret; } } s1->streams[0]->avg_frame_rate.num = tpf->denominator; @@ -759,8 +773,10 @@ static int v4l2_read_header(AVFormatContext *s1) if (s->pixel_format) { AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format); - if (codec) + if (codec) { s1->video_codec_id = codec->id; + st->need_parsing = AVSTREAM_PARSE_HEADERS; + } pix_fmt = av_get_pix_fmt(s->pixel_format); @@ -779,9 +795,12 @@ static int v4l2_read_header(AVFormatContext *s1) "Querying the device for the current frame size\n"); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { + char errbuf[128]; + res = AVERROR(errno); + av_strerror(res, errbuf, sizeof(errbuf)); av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", - strerror(errno)); - return AVERROR(errno); + errbuf); + return res; } s->width = fmt.fmt.pix.width; @@ -808,9 +827,9 @@ static int v4l2_read_header(AVFormatContext *s1) if ((res = v4l2_set_parameters(s1) < 0)) return res; - st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); - s->frame_size = - avpicture_get_size(st->codec->pix_fmt, s->width, s->height); + st->codecpar->format = fmt_v4l2ff(desired_format, codec_id); + s->frame_size = av_image_get_buffer_size(st->codecpar->format, + s->width, s->height, 1); if ((res = mmap_init(s1)) || (res = mmap_start(s1)) < 0) { @@ -820,33 +839,40 @@ static int v4l2_read_header(AVFormatContext *s1) s->top_field_first = first_field(s->fd); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = codec_id; if (codec_id == AV_CODEC_ID_RAWVIDEO) - st->codec->codec_tag = - avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); - st->codec->width = s->width; - st->codec->height = s->height; - st->codec->bit_rate = s->frame_size * av_q2d(st->avg_frame_rate) * 8; + st->codecpar->codec_tag = + avcodec_pix_fmt_to_codec_tag(st->codecpar->format); + st->codecpar->width = s->width; + st->codecpar->height = s->height; + st->codecpar->bit_rate = s->frame_size * av_q2d(st->avg_frame_rate) * 8; return 0; } static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) { +#if FF_API_CODED_FRAME && FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS struct video_data *s = s1->priv_data; AVFrame *frame = s1->streams[0]->codec->coded_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif int res; - av_init_packet(pkt); if ((res = mmap_read_frame(s1, pkt)) < 0) { return res; } +#if FF_API_CODED_FRAME && FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS if (frame && s->interlaced) { frame->interlaced_frame = 1; frame->top_field_first = s->top_field_first; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif return pkt->size; } diff --git a/libavdevice/version.h b/libavdevice/version.h index 3d82c97..a529732 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" -#define LIBAVDEVICE_VERSION_MAJOR 55 -#define LIBAVDEVICE_VERSION_MINOR 0 +#define LIBAVDEVICE_VERSION_MAJOR 56 +#define LIBAVDEVICE_VERSION_MINOR 1 #define LIBAVDEVICE_VERSION_MICRO 0 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ @@ -39,6 +39,8 @@ LIBAVDEVICE_VERSION_MICRO) #define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT +#define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION) + /** * FF_API_* defines may be placed below to indicate public API that will be * dropped at a future version bump. The defines themselves are not part of diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index b47de1b..9edd2c5 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -19,12 +19,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavformat/avformat.h" -#include "libavformat/internal.h" +#include "libavutil/internal.h" #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" + +// windows.h must no be included before winsock2.h, and libavformat internal +// headers may include winsock2.h #include +// windows.h needs to be included before vfw.h #include /* Some obsolete versions of MinGW32 before 4.0.0 lack this. */ @@ -154,7 +160,7 @@ static void dump_bih(AVFormatContext *s, BITMAPINFOHEADER *bih) static int shall_we_drop(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - const uint8_t dropscore[] = {62, 75, 87, 100}; + static const uint8_t dropscore[4] = { 62, 75, 87, 100 }; const int ndropscores = FF_ARRAY_ELEMS(dropscore); unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer; @@ -227,7 +233,7 @@ static int vfw_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { AVPacketList *next = pktl->next; - av_free_packet(&pktl->pkt); + av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; } @@ -238,7 +244,7 @@ static int vfw_read_close(AVFormatContext *s) static int vfw_read_header(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - AVCodecContext *codec; + AVCodecParameters *par; AVStream *st; int devnum; int bisize; @@ -367,29 +373,30 @@ static int vfw_read_header(AVFormatContext *s) if(!ret) goto fail_io; - codec = st->codec; - codec->time_base = (AVRational){framerate_q.den, framerate_q.num}; - codec->codec_type = AVMEDIA_TYPE_VIDEO; - codec->width = bi->bmiHeader.biWidth; - codec->height = bi->bmiHeader.biHeight; - codec->pix_fmt = vfw_pixfmt(biCompression, biBitCount); - if(codec->pix_fmt == AV_PIX_FMT_NONE) { - codec->codec_id = vfw_codecid(biCompression); - if(codec->codec_id == AV_CODEC_ID_NONE) { + st->avg_frame_rate = framerate_q; + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_VIDEO; + par->width = bi->bmiHeader.biWidth; + par->height = bi->bmiHeader.biHeight; + par->format = vfw_pixfmt(biCompression, biBitCount); + if (par->format == AV_PIX_FMT_NONE) { + par->codec_id = vfw_codecid(biCompression); + if (par->codec_id == AV_CODEC_ID_NONE) { av_log(s, AV_LOG_ERROR, "Unknown compression type. " "Please report verbose (-v 9) debug information.\n"); vfw_read_close(s); return AVERROR_PATCHWELCOME; } - codec->bits_per_coded_sample = biBitCount; + par->bits_per_coded_sample = biBitCount; } else { - codec->codec_id = AV_CODEC_ID_RAWVIDEO; + par->codec_id = AV_CODEC_ID_RAWVIDEO; if(biCompression == BI_RGB) { - codec->bits_per_coded_sample = biBitCount; - codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); - if (codec->extradata) { - codec->extradata_size = 9; - memcpy(codec->extradata, "BottomUp", 9); + par->bits_per_coded_sample = biBitCount; + par->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE); + if (par->extradata) { + par->extradata_size = 9; + memcpy(par->extradata, "BottomUp", 9); } } } diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c deleted file mode 100644 index 8edbf7b..0000000 --- a/libavdevice/x11grab.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * X11 video grab interface - * - * This file is part of Libav. - * - * Libav integration: - * Copyright (C) 2006 Clemens Fruhwirth - * Edouard Gomez - * - * This file contains code from grab.c: - * Copyright (c) 2000-2001 Fabrice Bellard - * - * This file contains code from the xvidcap project: - * Copyright (C) 1997-1998 Rasca, Berlin - * 2003-2004 Karl H. Beckers, Frankfurt - * - * Libav 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. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * X11 frame device demuxer - * @author Clemens Fruhwirth - * @author Edouard Gomez - */ - -#include "config.h" -#include "libavformat/avformat.h" -#include "libavformat/internal.h" -#include "libavutil/log.h" -#include "libavutil/opt.h" -#include "libavutil/parseutils.h" -#include "libavutil/time.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * X11 Device Demuxer context - */ -struct x11grab { - const AVClass *class; /**< Class for private options. */ - int frame_size; /**< Size in bytes of a grabbed frame */ - AVRational time_base; /**< Time base */ - int64_t time_frame; /**< Current time */ - - char *video_size; /**< String describing video size, set by a private option. */ - int height; /**< Height of the grab frame */ - int width; /**< Width of the grab frame */ - int x_off; /**< Horizontal top-left corner coordinate */ - int y_off; /**< Vertical top-left corner coordinate */ - - Display *dpy; /**< X11 display from which x11grab grabs frames */ - XImage *image; /**< X11 image holding the grab */ - int use_shm; /**< !0 when using XShm extension */ - XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */ - int draw_mouse; /**< Set by a private option. */ - int follow_mouse; /**< Set by a private option. */ - int show_region; /**< set by a private option. */ - char *framerate; /**< Set by a private option. */ - - Window region_win; /**< This is used by show_region option. */ -}; - -#define REGION_WIN_BORDER 3 -/** - * Draw grabbing region window - * - * @param s x11grab context - */ -static void -x11grab_draw_region_win(struct x11grab *s) -{ - Display *dpy = s->dpy; - int screen; - Window win = s->region_win; - GC gc; - - screen = DefaultScreen(dpy); - gc = XCreateGC(dpy, win, 0, 0); - XSetForeground(dpy, gc, WhitePixel(dpy, screen)); - XSetBackground(dpy, gc, BlackPixel(dpy, screen)); - XSetLineAttributes(dpy, gc, REGION_WIN_BORDER, LineDoubleDash, 0, 0); - XDrawRectangle(dpy, win, gc, - 1, 1, - (s->width + REGION_WIN_BORDER * 2) - 1 * 2 - 1, - (s->height + REGION_WIN_BORDER * 2) - 1 * 2 - 1); - XFreeGC(dpy, gc); -} - -/** - * Initialize grabbing region window - * - * @param s x11grab context - */ -static void -x11grab_region_win_init(struct x11grab *s) -{ - Display *dpy = s->dpy; - int screen; - XSetWindowAttributes attribs; - XRectangle rect; - - screen = DefaultScreen(dpy); - attribs.override_redirect = True; - s->region_win = XCreateWindow(dpy, RootWindow(dpy, screen), - s->x_off - REGION_WIN_BORDER, - s->y_off - REGION_WIN_BORDER, - s->width + REGION_WIN_BORDER * 2, - s->height + REGION_WIN_BORDER * 2, - 0, CopyFromParent, - InputOutput, CopyFromParent, - CWOverrideRedirect, &attribs); - rect.x = 0; - rect.y = 0; - rect.width = s->width; - rect.height = s->height; - XShapeCombineRectangles(dpy, s->region_win, - ShapeBounding, REGION_WIN_BORDER, REGION_WIN_BORDER, - &rect, 1, ShapeSubtract, 0); - XMapWindow(dpy, s->region_win); - XSelectInput(dpy, s->region_win, ExposureMask | StructureNotifyMask); - x11grab_draw_region_win(s); -} - -/** - * Initialize the x11 grab device demuxer (public device demuxer API). - * - * @param s1 Context from avformat core - * @return
    - *
  • AVERROR(ENOMEM) no memory left
  • - *
  • AVERROR(EIO) other failure case
  • - *
  • 0 success
  • - *
- */ -static int -x11grab_read_header(AVFormatContext *s1) -{ - struct x11grab *x11grab = s1->priv_data; - Display *dpy; - AVStream *st = NULL; - enum AVPixelFormat input_pixfmt; - XImage *image; - int x_off = 0; - int y_off = 0; - int screen; - int use_shm; - char *param, *offset; - int ret = 0; - AVRational framerate; - - param = av_strdup(s1->filename); - if (!param) - goto out; - - offset = strchr(param, '+'); - if (offset) { - sscanf(offset, "%d,%d", &x_off, &y_off); - x11grab->draw_mouse = !strstr(offset, "nomouse"); - *offset= 0; - } - - if ((ret = av_parse_video_size(&x11grab->width, &x11grab->height, x11grab->video_size)) < 0) { - av_log(s1, AV_LOG_ERROR, "Couldn't parse video size.\n"); - goto out; - } - if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) { - av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate); - goto out; - } - av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", - s1->filename, param, x_off, y_off, x11grab->width, x11grab->height); - - dpy = XOpenDisplay(param); - if(!dpy) { - av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); - ret = AVERROR(EIO); - goto out; - } - - st = avformat_new_stream(s1, NULL); - if (!st) { - ret = AVERROR(ENOMEM); - goto out; - } - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - screen = DefaultScreen(dpy); - - if (x11grab->follow_mouse) { - int screen_w, screen_h; - Window w; - - screen_w = DisplayWidth(dpy, screen); - screen_h = DisplayHeight(dpy, screen); - XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret); - x_off -= x11grab->width / 2; - y_off -= x11grab->height / 2; - x_off = FFMIN(FFMAX(x_off, 0), screen_w - x11grab->width); - y_off = FFMIN(FFMAX(y_off, 0), screen_h - x11grab->height); - av_log(s1, AV_LOG_INFO, "followmouse is enabled, resetting grabbing region to x: %d y: %d\n", x_off, y_off); - } - - use_shm = XShmQueryExtension(dpy); - av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ? "" : "not"); - - if(use_shm) { - int scr = XDefaultScreen(dpy); - image = XShmCreateImage(dpy, - DefaultVisual(dpy, scr), - DefaultDepth(dpy, scr), - ZPixmap, - NULL, - &x11grab->shminfo, - x11grab->width, x11grab->height); - x11grab->shminfo.shmid = shmget(IPC_PRIVATE, - image->bytes_per_line * image->height, - IPC_CREAT|0777); - if (x11grab->shminfo.shmid == -1) { - av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); - ret = AVERROR(ENOMEM); - goto out; - } - x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); - x11grab->shminfo.readOnly = False; - - if (!XShmAttach(dpy, &x11grab->shminfo)) { - av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); - /* needs some better error subroutine :) */ - ret = AVERROR(EIO); - goto out; - } - } else { - image = XGetImage(dpy, RootWindow(dpy, screen), - x_off,y_off, - x11grab->width, x11grab->height, - AllPlanes, ZPixmap); - } - - switch (image->bits_per_pixel) { - case 8: - av_log (s1, AV_LOG_DEBUG, "8 bit palette\n"); - input_pixfmt = AV_PIX_FMT_PAL8; - break; - case 16: - if ( image->red_mask == 0xf800 && - image->green_mask == 0x07e0 && - image->blue_mask == 0x001f ) { - av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); - input_pixfmt = AV_PIX_FMT_RGB565; - } else if (image->red_mask == 0x7c00 && - image->green_mask == 0x03e0 && - image->blue_mask == 0x001f ) { - av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); - input_pixfmt = AV_PIX_FMT_RGB555; - } else { - av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); - av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); - ret = AVERROR(EIO); - goto out; - } - break; - case 24: - if ( image->red_mask == 0xff0000 && - image->green_mask == 0x00ff00 && - image->blue_mask == 0x0000ff ) { - input_pixfmt = AV_PIX_FMT_BGR24; - } else if ( image->red_mask == 0x0000ff && - image->green_mask == 0x00ff00 && - image->blue_mask == 0xff0000 ) { - input_pixfmt = AV_PIX_FMT_RGB24; - } else { - av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); - av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); - ret = AVERROR(EIO); - goto out; - } - break; - case 32: - input_pixfmt = AV_PIX_FMT_RGB32; - break; - default: - av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); - ret = AVERROR(EINVAL); - goto out; - } - - x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8; - x11grab->dpy = dpy; - x11grab->time_base = (AVRational){framerate.den, framerate.num}; - x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base); - x11grab->x_off = x_off; - x11grab->y_off = y_off; - x11grab->image = image; - x11grab->use_shm = use_shm; - - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->width = x11grab->width; - st->codec->height = x11grab->height; - st->codec->pix_fmt = input_pixfmt; - st->codec->time_base = x11grab->time_base; - st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8; - -out: - av_free(param); - return ret; -} - -/** - * Paint a mouse pointer in an X11 image. - * - * @param image image to paint the mouse pointer to - * @param s context used to retrieve original grabbing rectangle - * coordinates - */ -static void -paint_mouse_pointer(XImage *image, struct x11grab *s) -{ - int x_off = s->x_off; - int y_off = s->y_off; - int width = s->width; - int height = s->height; - Display *dpy = s->dpy; - XFixesCursorImage *xcim; - int x, y; - int line, column; - int to_line, to_column; - int pixstride = image->bits_per_pixel >> 3; - /* Warning: in its insanity, xlib provides unsigned image data through a - * char* pointer, so we have to make it uint8_t to make things not break. - * Anyone who performs further investigation of the xlib API likely risks - * permanent brain damage. */ - uint8_t *pix = image->data; - - /* Code doesn't currently support 16-bit or PAL8 */ - if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32) - return; - - xcim = XFixesGetCursorImage(dpy); - - x = xcim->x - xcim->xhot; - y = xcim->y - xcim->yhot; - - to_line = FFMIN((y + xcim->height), (height + y_off)); - to_column = FFMIN((x + xcim->width), (width + x_off)); - - for (line = FFMAX(y, y_off); line < to_line; line++) { - for (column = FFMAX(x, x_off); column < to_column; column++) { - int xcim_addr = (line - y) * xcim->width + column - x; - int image_addr = ((line - y_off) * width + column - x_off) * pixstride; - int r = (uint8_t)(xcim->pixels[xcim_addr] >> 0); - int g = (uint8_t)(xcim->pixels[xcim_addr] >> 8); - int b = (uint8_t)(xcim->pixels[xcim_addr] >> 16); - int a = (uint8_t)(xcim->pixels[xcim_addr] >> 24); - - if (a == 255) { - pix[image_addr+0] = r; - pix[image_addr+1] = g; - pix[image_addr+2] = b; - } else if (a) { - /* pixel values from XFixesGetCursorImage come premultiplied by alpha */ - pix[image_addr+0] = r + (pix[image_addr+0]*(255-a) + 255/2) / 255; - pix[image_addr+1] = g + (pix[image_addr+1]*(255-a) + 255/2) / 255; - pix[image_addr+2] = b + (pix[image_addr+2]*(255-a) + 255/2) / 255; - } - } - } - - XFree(xcim); - xcim = NULL; -} - - -/** - * Read new data in the image structure. - * - * @param dpy X11 display to grab from - * @param d - * @param image Image where the grab will be put - * @param x Top-Left grabbing rectangle horizontal coordinate - * @param y Top-Left grabbing rectangle vertical coordinate - * @return 0 if error, !0 if successful - */ -static int -xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y) -{ - xGetImageReply rep; - xGetImageReq *req; - long nbytes; - - if (!image) { - return 0; - } - - LockDisplay(dpy); - GetReq(GetImage, req); - - /* First set up the standard stuff in the request */ - req->drawable = d; - req->x = x; - req->y = y; - req->width = image->width; - req->height = image->height; - req->planeMask = (unsigned int)AllPlanes; - req->format = ZPixmap; - - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) { - UnlockDisplay(dpy); - SyncHandle(); - return 0; - } - - nbytes = (long)rep.length << 2; - _XReadPad(dpy, image->data, nbytes); - - UnlockDisplay(dpy); - SyncHandle(); - return 1; -} - -/** - * Grab a frame from x11 (public device demuxer API). - * - * @param s1 Context from avformat core - * @param pkt Packet holding the brabbed frame - * @return frame size in bytes - */ -static int -x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - struct x11grab *s = s1->priv_data; - Display *dpy = s->dpy; - XImage *image = s->image; - int x_off = s->x_off; - int y_off = s->y_off; - - int screen; - Window root; - int follow_mouse = s->follow_mouse; - - int64_t curtime, delay; - struct timespec ts; - - /* Calculate the time of the next frame */ - s->time_frame += INT64_C(1000000); - - /* wait based on the frame rate */ - for(;;) { - curtime = av_gettime(); - delay = s->time_frame * av_q2d(s->time_base) - curtime; - if (delay <= 0) { - if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { - s->time_frame += INT64_C(1000000); - } - break; - } - ts.tv_sec = delay / 1000000; - ts.tv_nsec = (delay % 1000000) * 1000; - nanosleep(&ts, NULL); - } - - av_init_packet(pkt); - pkt->data = image->data; - pkt->size = s->frame_size; - pkt->pts = curtime; - - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - if (follow_mouse) { - int screen_w, screen_h; - int pointer_x, pointer_y, _; - Window w; - - screen_w = DisplayWidth(dpy, screen); - screen_h = DisplayHeight(dpy, screen); - XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_); - if (follow_mouse == -1) { - // follow the mouse, put it at center of grabbing region - x_off += pointer_x - s->width / 2 - x_off; - y_off += pointer_y - s->height / 2 - y_off; - } else { - // follow the mouse, but only move the grabbing region when mouse - // reaches within certain pixels to the edge. - if (pointer_x > x_off + s->width - follow_mouse) { - x_off += pointer_x - (x_off + s->width - follow_mouse); - } else if (pointer_x < x_off + follow_mouse) - x_off -= (x_off + follow_mouse) - pointer_x; - if (pointer_y > y_off + s->height - follow_mouse) { - y_off += pointer_y - (y_off + s->height - follow_mouse); - } else if (pointer_y < y_off + follow_mouse) - y_off -= (y_off + follow_mouse) - pointer_y; - } - // adjust grabbing region position if it goes out of screen. - s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width); - s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height); - - if (s->show_region && s->region_win) - XMoveWindow(dpy, s->region_win, - s->x_off - REGION_WIN_BORDER, - s->y_off - REGION_WIN_BORDER); - } - - if (s->show_region) { - if (s->region_win) { - XEvent evt; - // clean up the events, and do the initinal draw or redraw. - for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); ); - if (evt.type) - x11grab_draw_region_win(s); - } else { - x11grab_region_win_init(s); - } - } - - if(s->use_shm) { - if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) { - av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); - } - } else { - if (!xget_zpixmap(dpy, root, image, x_off, y_off)) { - av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); - } - } - - if (s->draw_mouse) { - paint_mouse_pointer(image, s); - } - - return s->frame_size; -} - -/** - * Close x11 frame grabber (public device demuxer API). - * - * @param s1 Context from avformat core - * @return 0 success, !0 failure - */ -static int -x11grab_read_close(AVFormatContext *s1) -{ - struct x11grab *x11grab = s1->priv_data; - - /* Detach cleanly from shared mem */ - if (x11grab->use_shm) { - XShmDetach(x11grab->dpy, &x11grab->shminfo); - shmdt(x11grab->shminfo.shmaddr); - shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); - } - - /* Destroy X11 image */ - if (x11grab->image) { - XDestroyImage(x11grab->image); - x11grab->image = NULL; - } - - if (x11grab->region_win) { - XDestroyWindow(x11grab->dpy, x11grab->region_win); - } - - /* Free X11 display */ - XCloseDisplay(x11grab->dpy); - return 0; -} - -#define OFFSET(x) offsetof(struct x11grab, x) -#define DEC AV_OPT_FLAG_DECODING_PARAM -static const AVOption options[] = { - { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = "vga"}, 0, 0, DEC }, - { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC }, - { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, DEC }, - { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.", - OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, DEC, "follow_mouse" }, - { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, DEC, "follow_mouse" }, - { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, DEC }, - { NULL }, -}; - -static const AVClass x11_class = { - .class_name = "X11grab indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -/** x11 grabber device demuxer declaration */ -AVInputFormat ff_x11grab_demuxer = { - .name = "x11grab", - .long_name = NULL_IF_CONFIG_SMALL("X11grab"), - .priv_data_size = sizeof(struct x11grab), - .read_header = x11grab_read_header, - .read_packet = x11grab_read_packet, - .read_close = x11grab_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &x11_class, -}; diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c new file mode 100644 index 0000000..0fd99eb --- /dev/null +++ b/libavdevice/xcbgrab.c @@ -0,0 +1,696 @@ +/* + * XCB input grabber + * Copyright (C) 2014 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include + +#if CONFIG_LIBXCB_XFIXES +#include +#endif + +#if CONFIG_LIBXCB_SHM +#include +#include +#endif + +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/time.h" + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" + +typedef struct XCBGrabContext { + const AVClass *class; + + xcb_connection_t *conn; + xcb_screen_t *screen; + xcb_window_t window; +#if CONFIG_LIBXCB_SHM + xcb_shm_seg_t segment; +#endif + int64_t time_frame; + AVRational time_base; + + int x, y; + int width, height; + int frame_size; + int bpp; + + int draw_mouse; + int follow_mouse; + int show_region; + int region_border; + int centered; + + const char *video_size; + const char *framerate; + + int has_shm; +} XCBGrabContext; + +#define FOLLOW_CENTER -1 + +#define OFFSET(x) offsetof(XCBGrabContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = "vga" }, 0, 0, D }, + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D }, + { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D }, + { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.", + OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, FOLLOW_CENTER, INT_MAX, D, "follow_mouse" }, + { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, D, "follow_mouse" }, + { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D }, + { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D }, + { NULL }, +}; + +static const AVClass xcbgrab_class = { + .class_name = "xcbgrab indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int xcbgrab_reposition(AVFormatContext *s, + xcb_query_pointer_reply_t *p, + xcb_get_geometry_reply_t *geo) +{ + XCBGrabContext *c = s->priv_data; + int x = c->x, y = c->y; + int w = c->width, h = c->height, f = c->follow_mouse; + int p_x, p_y; + + if (!p || !geo) + return AVERROR(EIO); + + p_x = p->win_x; + p_y = p->win_y; + + if (f == FOLLOW_CENTER) { + x = p_x - w / 2; + y = p_y - h / 2; + } else { + int left = x + f; + int right = x + w - f; + int top = y + f; + int bottom = y + h + f; + if (p_x > right) { + x += p_x - right; + } else if (p_x < left) { + x -= left - p_x; + } + if (p_y > bottom) { + y += p_y - bottom; + } else if (p_y < top) { + y -= top - p_y; + } + } + + c->x = FFMIN(FFMAX(0, x), geo->width - w); + c->y = FFMIN(FFMAX(0, y), geo->height - h); + + return 0; +} + +static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt) +{ + XCBGrabContext *c = s->priv_data; + xcb_get_image_cookie_t iq; + xcb_get_image_reply_t *img; + xcb_drawable_t drawable = c->screen->root; + xcb_generic_error_t *e = NULL; + uint8_t *data; + int length, ret; + + iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, + c->x, c->y, c->width, c->height, ~0); + + img = xcb_get_image_reply(c->conn, iq, &e); + + if (e) { + av_log(s, AV_LOG_ERROR, + "Cannot get the image data " + "event_error: response_type:%u error_code:%u " + "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n", + e->response_type, e->error_code, + e->sequence, e->resource_id, e->minor_code, e->major_code); + return AVERROR(EACCES); + } + + if (!img) + return AVERROR(EAGAIN); + + data = xcb_get_image_data(img); + length = xcb_get_image_data_length(img); + + ret = av_new_packet(pkt, length); + + if (!ret) + memcpy(pkt->data, data, length); + + free(img); + + return ret; +} + +static void wait_frame(AVFormatContext *s, AVPacket *pkt) +{ + XCBGrabContext *c = s->priv_data; + int64_t curtime, delay; + int64_t frame_time = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q); + + c->time_frame += frame_time; + + for (;;) { + curtime = av_gettime(); + delay = c->time_frame - curtime; + if (delay <= 0) + break; + av_usleep(delay); + } + + pkt->pts = curtime; +} + +#if CONFIG_LIBXCB_SHM +static int check_shm(xcb_connection_t *conn) +{ + xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn); + xcb_shm_query_version_reply_t *reply; + + reply = xcb_shm_query_version_reply(conn, cookie, NULL); + if (reply) { + free(reply); + return 1; + } + + return 0; +} + +static void dealloc_shm(void *unused, uint8_t *data) +{ + shmdt(data); +} + +static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) +{ + XCBGrabContext *c = s->priv_data; + xcb_shm_get_image_cookie_t iq; + xcb_shm_get_image_reply_t *img; + xcb_drawable_t drawable = c->screen->root; + uint8_t *data; + int size = c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE; + int id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); + xcb_generic_error_t *e = NULL; + + if (id == -1) { + char errbuf[1024]; + int err = AVERROR(errno); + av_strerror(err, errbuf, sizeof(errbuf)); + av_log(s, AV_LOG_ERROR, "Cannot get %d bytes of shared memory: %s.\n", + size, errbuf); + return err; + } + + xcb_shm_attach(c->conn, c->segment, id, 0); + + iq = xcb_shm_get_image(c->conn, drawable, + c->x, c->y, c->width, c->height, ~0, + XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0); + + xcb_shm_detach(c->conn, c->segment); + + img = xcb_shm_get_image_reply(c->conn, iq, &e); + + xcb_flush(c->conn); + + if (e) { + av_log(s, AV_LOG_ERROR, + "Cannot get the image data " + "event_error: response_type:%u error_code:%u " + "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n", + e->response_type, e->error_code, + e->sequence, e->resource_id, e->minor_code, e->major_code); + + shmctl(id, IPC_RMID, 0); + return AVERROR(EACCES); + } + + free(img); + + data = shmat(id, NULL, 0); + shmctl(id, IPC_RMID, 0); + + if ((intptr_t)data == -1) + return AVERROR(errno); + + pkt->buf = av_buffer_create(data, size, dealloc_shm, NULL, 0); + if (!pkt->buf) { + shmdt(data); + return AVERROR(ENOMEM); + } + + pkt->data = pkt->buf->data; + pkt->size = c->frame_size; + + return 0; +} +#endif /* CONFIG_LIBXCB_SHM */ + +#if CONFIG_LIBXCB_XFIXES +static int check_xfixes(xcb_connection_t *conn) +{ + xcb_xfixes_query_version_cookie_t cookie; + xcb_xfixes_query_version_reply_t *reply; + + cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + reply = xcb_xfixes_query_version_reply(conn, cookie, NULL); + + if (reply) { + free(reply); + return 1; + } + return 0; +} + +#define BLEND(target, source, alpha) \ + (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255 + +static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt, + xcb_query_pointer_reply_t *p, + xcb_get_geometry_reply_t *geo) +{ + XCBGrabContext *gr = s->priv_data; + uint32_t *cursor; + uint8_t *image = pkt->data; + int stride = gr->bpp / 8; + xcb_xfixes_get_cursor_image_cookie_t cc; + xcb_xfixes_get_cursor_image_reply_t *ci; + int cx, cy, x, y, w, h, c_off, i_off; + + cc = xcb_xfixes_get_cursor_image(gr->conn); + ci = xcb_xfixes_get_cursor_image_reply(gr->conn, cc, NULL); + if (!ci) + return; + + cursor = xcb_xfixes_get_cursor_image_cursor_image(ci); + if (!cursor) + return; + + cx = ci->x - ci->xhot; + cy = ci->y - ci->yhot; + + x = FFMAX(cx, gr->x); + y = FFMAX(cy, gr->y); + + w = FFMIN(cx + ci->width, gr->x + gr->width) - x; + h = FFMIN(cy + ci->height, gr->y + gr->height) - y; + + c_off = x - cx; + i_off = x - gr->x; + + cursor += (y - cy) * ci->width; + image += (y - gr->y) * gr->width * stride; + + for (y = 0; y < h; y++) { + cursor += c_off; + image += i_off * stride; + for (x = 0; x < w; x++, cursor++, image += stride) { + int r, g, b, a; + + r = *cursor & 0xff; + g = (*cursor >> 8) & 0xff; + b = (*cursor >> 16) & 0xff; + a = (*cursor >> 24) & 0xff; + + if (!a) + continue; + + if (a == 255) { + image[0] = r; + image[1] = g; + image[2] = b; + } else { + image[0] = BLEND(r, image[0], a); + image[1] = BLEND(g, image[1], a); + image[2] = BLEND(b, image[2], a); + } + + } + cursor += ci->width - w - c_off; + image += (gr->width - w - i_off) * stride; + } + + free(ci); +} +#endif /* CONFIG_LIBXCB_XFIXES */ + +static void xcbgrab_update_region(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + const uint32_t args[] = { c->x - c->region_border, + c->y - c->region_border }; + + xcb_configure_window(c->conn, + c->window, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, + args); +} + +static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + XCBGrabContext *c = s->priv_data; + xcb_query_pointer_cookie_t pc; + xcb_get_geometry_cookie_t gc; + xcb_query_pointer_reply_t *p = NULL; + xcb_get_geometry_reply_t *geo = NULL; + int ret = 0; + + wait_frame(s, pkt); + + if (c->follow_mouse || c->draw_mouse) { + pc = xcb_query_pointer(c->conn, c->screen->root); + gc = xcb_get_geometry(c->conn, c->screen->root); + p = xcb_query_pointer_reply(c->conn, pc, NULL); + geo = xcb_get_geometry_reply(c->conn, gc, NULL); + } + + if (c->follow_mouse && p->same_screen) + xcbgrab_reposition(s, p, geo); + + if (c->show_region) + xcbgrab_update_region(s); + +#if CONFIG_LIBXCB_SHM + if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) + c->has_shm = 0; +#endif + if (!c->has_shm) + ret = xcbgrab_frame(s, pkt); + +#if CONFIG_LIBXCB_XFIXES + if (ret >= 0 && c->draw_mouse && p->same_screen) + xcbgrab_draw_mouse(s, pkt, p, geo); +#endif + + free(p); + free(geo); + + return ret; +} + +static av_cold int xcbgrab_read_close(AVFormatContext *s) +{ + XCBGrabContext *ctx = s->priv_data; + + xcb_disconnect(ctx->conn); + + return 0; +} + +static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num) +{ + xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup); + xcb_screen_t *screen = NULL; + + for (; it.rem > 0; xcb_screen_next (&it)) { + if (!screen_num) { + screen = it.data; + break; + } + + screen_num--; + } + + return screen; +} + +static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, + int *pix_fmt) +{ + XCBGrabContext *c = s->priv_data; + const xcb_setup_t *setup = xcb_get_setup(c->conn); + const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); + int length = xcb_setup_pixmap_formats_length(setup); + + *pix_fmt = 0; + + while (length--) { + if (fmt->depth == depth) { + switch (depth) { + case 32: + if (fmt->bits_per_pixel == 32) + *pix_fmt = AV_PIX_FMT_ARGB; + break; + case 24: + if (fmt->bits_per_pixel == 32) + *pix_fmt = AV_PIX_FMT_RGB32; + else if (fmt->bits_per_pixel == 24) + *pix_fmt = AV_PIX_FMT_RGB24; + break; + case 16: + if (fmt->bits_per_pixel == 16) + *pix_fmt = AV_PIX_FMT_RGB565; + break; + case 15: + if (fmt->bits_per_pixel == 16) + *pix_fmt = AV_PIX_FMT_RGB555; + break; + case 8: + if (fmt->bits_per_pixel == 8) + *pix_fmt = AV_PIX_FMT_RGB8; + break; + } + } + + if (*pix_fmt) { + c->bpp = fmt->bits_per_pixel; + c->frame_size = c->width * c->height * fmt->bits_per_pixel / 8; + return 0; + } + + fmt++; + } + av_log(s, AV_LOG_ERROR, "Pixmap format not mappable.\n"); + + return AVERROR_PATCHWELCOME; +} + +static int create_stream(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + AVStream *st = avformat_new_stream(s, NULL); + xcb_get_geometry_cookie_t gc; + xcb_get_geometry_reply_t *geo; + int ret; + + if (!st) + return AVERROR(ENOMEM); + + ret = av_parse_video_size(&c->width, &c->height, c->video_size); + if (ret < 0) + return ret; + + ret = av_parse_video_rate(&st->avg_frame_rate, c->framerate); + if (ret < 0) + return ret; + + avpriv_set_pts_info(st, 64, 1, 1000000); + + gc = xcb_get_geometry(c->conn, c->screen->root); + geo = xcb_get_geometry_reply(c->conn, gc, NULL); + + if (c->x + c->width > geo->width || + c->y + c->height > geo->height) { + av_log(s, AV_LOG_ERROR, + "Capture area %dx%d at position %d.%d " + "outside the screen size %dx%d\n", + c->width, c->height, + c->x, c->y, + geo->width, geo->height); + return AVERROR(EINVAL); + } + + c->time_base = (AVRational){ st->avg_frame_rate.den, + st->avg_frame_rate.num }; + c->time_frame = av_gettime(); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->width = c->width; + st->codecpar->height = c->height; + + ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format); + + free(geo); + + return ret; +} + +static void draw_rectangle(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + xcb_gcontext_t gc = xcb_generate_id(c->conn); + uint32_t mask = XCB_GC_FOREGROUND | + XCB_GC_BACKGROUND | + XCB_GC_LINE_WIDTH | + XCB_GC_LINE_STYLE | + XCB_GC_FILL_STYLE; + uint32_t values[] = { c->screen->black_pixel, + c->screen->white_pixel, + c->region_border, + XCB_LINE_STYLE_DOUBLE_DASH, + XCB_FILL_STYLE_SOLID }; + xcb_rectangle_t r = { 1, 1, + c->width + c->region_border * 2 - 3, + c->height + c->region_border * 2 - 3 }; + + xcb_create_gc(c->conn, gc, c->window, mask, values); + + xcb_poly_rectangle(c->conn, c->window, gc, 1, &r); +} + +static void setup_window(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; + uint32_t values[] = { 1, + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY }; + xcb_rectangle_t rect = { 0, 0, c->width, c->height }; + + c->window = xcb_generate_id(c->conn); + + xcb_create_window(c->conn, XCB_COPY_FROM_PARENT, + c->window, + c->screen->root, + c->x - c->region_border, + c->y - c->region_border, + c->width + c->region_border * 2, + c->height + c->region_border * 2, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, + mask, values); + + xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + c->window, + c->region_border, c->region_border, + 1, &rect); + + xcb_map_window(c->conn, c->window); + + draw_rectangle(s); +} + +static av_cold int xcbgrab_read_header(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + int screen_num, ret; + const xcb_setup_t *setup; + char *host = s->filename[0] ? s->filename : NULL; + const char *opts = strchr(s->filename, '+'); + + if (opts) { + sscanf(opts, "%d,%d", &c->x, &c->y); + host = av_strdup(s->filename); + if (!host) + return AVERROR(ENOMEM); + host[opts - s->filename] = '\0'; + } + + c->conn = xcb_connect(host, &screen_num); + + if ((ret = xcb_connection_has_error(c->conn))) { + av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n", + s->filename[0] ? host : "default", ret); + if (opts) + av_freep(&host); + return AVERROR(EIO); + } + + if (opts) + av_freep(&host); + + setup = xcb_get_setup(c->conn); + + c->screen = get_screen(setup, screen_num); + if (!c->screen) { + av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n", + screen_num); + xcbgrab_read_close(s); + return AVERROR(EIO); + } + + ret = create_stream(s); + + if (ret < 0) { + xcbgrab_read_close(s); + return ret; + } + +#if CONFIG_LIBXCB_SHM + if ((c->has_shm = check_shm(c->conn))) + c->segment = xcb_generate_id(c->conn); +#endif + +#if CONFIG_LIBXCB_XFIXES + if (c->draw_mouse) { + if (!(c->draw_mouse = check_xfixes(c->conn))) { + av_log(s, AV_LOG_WARNING, + "XFixes not available, cannot draw the mouse.\n"); + } + if (c->bpp < 24) { + avpriv_report_missing_feature(s, "%d bits per pixel screen", + c->bpp); + c->draw_mouse = 0; + } + } +#endif + + if (c->show_region) + setup_window(s); + + return 0; +} + +AVInputFormat ff_xcbgrab_demuxer = { + .name = "x11grab", + .long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"), + .priv_data_size = sizeof(XCBGrabContext), + .read_header = xcbgrab_read_header, + .read_packet = xcbgrab_read_packet, + .read_close = xcbgrab_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &xcbgrab_class, +}; diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7b94f22..c3c1bea 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -10,7 +10,6 @@ OBJS = allfilters.o \ audio.o \ avfilter.o \ avfiltergraph.o \ - buffer.o \ buffersink.o \ buffersrc.o \ drawutils.o \ @@ -19,6 +18,9 @@ OBJS = allfilters.o \ graphparser.o \ video.o \ +OBJS-$(HAVE_THREADS) += pthread.o + +# audio filters OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o @@ -32,19 +34,21 @@ OBJS-$(CONFIG_BS2B_FILTER) += af_bs2b.o OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o OBJS-$(CONFIG_COMPAND_FILTER) += af_compand.o +OBJS-$(CONFIG_HDCD_FILTER) += af_hdcd.o OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o -OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o - OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o +OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o +# video filters OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o OBJS-$(CONFIG_CROP_FILTER) += vf_crop.o OBJS-$(CONFIG_CROPDETECT_FILTER) += vf_cropdetect.o +OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o OBJS-$(CONFIG_DRAWBOX_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWTEXT_FILTER) += vf_drawtext.o @@ -57,6 +61,9 @@ OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o +OBJS-$(CONFIG_HWDOWNLOAD_FILTER) += vf_hwdownload.o +OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o +OBJS-$(CONFIG_HWUPLOAD_FILTER) += vf_hwupload.o OBJS-$(CONFIG_INTERLACE_FILTER) += vf_interlace.o OBJS-$(CONFIG_LUT_FILTER) += vf_lut.o OBJS-$(CONFIG_LUTRGB_FILTER) += vf_lut.o @@ -69,6 +76,9 @@ OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o +OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o +OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o +OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o @@ -83,6 +93,8 @@ OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o +OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o + OBJS-$(CONFIG_COLOR_FILTER) += vsrc_color.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o OBJS-$(CONFIG_MOVIE_FILTER) += vsrc_movie.o @@ -90,9 +102,5 @@ OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o -OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o - -OBJS-$(HAVE_THREADS) += pthread.o - TOOLS = graph2dot TESTPROGS = filtfmts diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index 57120c1..5f0e254 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -36,6 +36,8 @@ #include "libavutil/replaygain.h" #include "libavutil/samplefmt.h" +#include "libavcodec/avcodec.h" + #include "audio.h" #include "avfilter.h" #include "internal.h" @@ -157,6 +159,30 @@ static void dump_replaygain(AVFilterContext *ctx, AVFrameSideData *sd) print_peak(ctx, "album peak", rg->album_peak); } +static void dump_audio_service_type(AVFilterContext *ctx, AVFrameSideData *sd) +{ + enum AVAudioServiceType *ast; + + av_log(ctx, AV_LOG_INFO, "audio service type: "); + if (sd->size < sizeof(*ast)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + ast = (enum AVAudioServiceType*)sd->data; + switch (*ast) { + case AV_AUDIO_SERVICE_TYPE_MAIN: av_log(ctx, AV_LOG_INFO, "Main Audio Service"); break; + case AV_AUDIO_SERVICE_TYPE_EFFECTS: av_log(ctx, AV_LOG_INFO, "Effects"); break; + case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: av_log(ctx, AV_LOG_INFO, "Visually Impaired"); break; + case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: av_log(ctx, AV_LOG_INFO, "Hearing Impaired"); break; + case AV_AUDIO_SERVICE_TYPE_DIALOGUE: av_log(ctx, AV_LOG_INFO, "Dialogue"); break; + case AV_AUDIO_SERVICE_TYPE_COMMENTARY: av_log(ctx, AV_LOG_INFO, "Commentary"); break; + case AV_AUDIO_SERVICE_TYPE_EMERGENCY: av_log(ctx, AV_LOG_INFO, "Emergency"); break; + case AV_AUDIO_SERVICE_TYPE_VOICE_OVER: av_log(ctx, AV_LOG_INFO, "Voice Over"); break; + case AV_AUDIO_SERVICE_TYPE_KARAOKE: av_log(ctx, AV_LOG_INFO, "Karaoke"); break; + default: av_log(ctx, AV_LOG_INFO, "unknown"); break; + } +} + static void dump_unknown(AVFilterContext *ctx, AVFrameSideData *sd) { av_log(ctx, AV_LOG_INFO, "unknown side data type: %d, size %d bytes", sd->type, sd->size); @@ -208,6 +234,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) case AV_FRAME_DATA_MATRIXENCODING: dump_matrixenc (ctx, sd); break; case AV_FRAME_DATA_DOWNMIX_INFO: dump_downmix (ctx, sd); break; case AV_FRAME_DATA_REPLAYGAIN: dump_replaygain(ctx, sd); break; + case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: dump_audio_service_type(ctx, sd); break; default: dump_unknown (ctx, sd); break; } diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index 3035405..5725498 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -57,7 +57,6 @@ enum MappingMode { #define MAX_CH 64 typedef struct ChannelMapContext { const AVClass *class; - AVFilterChannelLayouts *channel_layouts; char *mapping_str; char *channel_layout_str; uint64_t output_layout; @@ -276,8 +275,6 @@ static av_cold int channelmap_init(AVFilterContext *ctx) return AVERROR(EINVAL); } - ff_add_channel_layout(&s->channel_layouts, s->output_layout); - if (mode == MAP_PAIR_INT_STR || mode == MAP_PAIR_STR_STR) { for (i = 0; i < s->nch; i++) { s->map[i].out_channel_idx = av_get_channel_layout_channel_index( @@ -291,11 +288,14 @@ static av_cold int channelmap_init(AVFilterContext *ctx) static int channelmap_query_formats(AVFilterContext *ctx) { ChannelMapContext *s = ctx->priv; + AVFilterChannelLayouts *channel_layouts = NULL; + + ff_add_channel_layout(&channel_layouts, s->output_layout); ff_set_common_formats(ctx, ff_planar_sample_fmts()); ff_set_common_samplerates(ctx, ff_all_samplerates()); ff_channel_layouts_ref(ff_all_channel_layouts(), &ctx->inputs[0]->out_channel_layouts); - ff_channel_layouts_ref(s->channel_layouts, &ctx->outputs[0]->in_channel_layouts); + ff_channel_layouts_ref(channel_layouts, &ctx->outputs[0]->in_channel_layouts); return 0; } diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c new file mode 100644 index 0000000..b9dadec --- /dev/null +++ b/libavfilter/af_hdcd.c @@ -0,0 +1,197 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * HDCD decoding filter, using libhdcd + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +typedef struct HDCDContext { + const AVClass *class; + + hdcd_simple *shdcd; + + /* AVOption members */ + /** analyze mode replaces the audio with a solid tone and adjusts + * the amplitude to signal some specific aspect of the decoding + * process. See docs or HDCD_ANA_* defines. */ + int analyze_mode; + /* end AVOption members */ +} HDCDContext; + +#define OFFSET(x) offsetof(HDCDContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM +#define HDCD_ANA_MAX 6 +static const AVOption hdcd_options[] = { + { "analyze_mode", "Replace audio with solid tone and signal some processing aspect in the amplitude.", + OFFSET(analyze_mode), AV_OPT_TYPE_INT, { .i64=HDCD_ANA_OFF }, 0, HDCD_ANA_MAX, A, "analyze_mode"}, + { "off", HDCD_ANA_OFF_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_OFF}, 0, 0, A, "analyze_mode" }, + { "lle", HDCD_ANA_LLE_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_LLE}, 0, 0, A, "analyze_mode" }, + { "pe", HDCD_ANA_PE_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_PE}, 0, 0, A, "analyze_mode" }, + { "cdt", HDCD_ANA_CDT_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_CDT}, 0, 0, A, "analyze_mode" }, + { "tgm", HDCD_ANA_TGM_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_TGM}, 0, 0, A, "analyze_mode" }, + { "pel", HDCD_ANA_PEL_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_PEL}, 0, 0, A, "analyze_mode" }, + { "ltgm", HDCD_ANA_LTGM_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_LTGM}, 0, 0, A, "analyze_mode" }, + { NULL } +}; + +static const AVClass hdcd_class = { + .class_name = "HDCD filter", + .item_name = av_default_item_name, + .option = hdcd_options, + .version = LIBAVFILTER_VERSION_INT, +}; + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + HDCDContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + const int16_t *in_data; + int32_t *out_data; + int n, result; + int channel_count = av_get_channel_layout_nb_channels(in->channel_layout); + + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + result = av_frame_copy_props(out, in); + if (result) { + av_frame_free(&out); + av_frame_free(&in); + return result; + } + + in_data = (int16_t *)in->data[0]; + out_data = (int32_t *)out->data[0]; + for (n = 0; n < in->nb_samples * channel_count; n++) + out_data[n] = in_data[n]; + + hdcd_process(s->shdcd, out_data, in->nb_samples); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *in_formats, *out_formats, *sample_rates = NULL; + AVFilterChannelLayouts *layouts = NULL; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + + static const enum AVSampleFormat sample_fmts_in[] = { + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE + }; + static const enum AVSampleFormat sample_fmts_out[] = { + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_NONE + }; + + ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + + ff_set_common_channel_layouts(ctx, layouts); + + in_formats = ff_make_format_list(sample_fmts_in); + out_formats = ff_make_format_list(sample_fmts_out); + if (!in_formats || !out_formats) + return AVERROR(ENOMEM); + + ff_formats_ref(in_formats, &inlink->out_formats); + ff_formats_ref(out_formats, &outlink->in_formats); + + ff_add_format(&sample_rates, 44100); + ff_set_common_samplerates(ctx, sample_rates); + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + HDCDContext *s = ctx->priv; + char detect_str[256] = ""; + + /* log the HDCD decode information */ + hdcd_detect_str(s->shdcd, detect_str, sizeof(detect_str)); + av_log(ctx, AV_LOG_INFO, "%s\n", detect_str); + + hdcd_free(s->shdcd); +} + +/** callback for error logging */ +static void af_hdcd_log(const void *priv, const char *fmt, va_list args) +{ + av_vlog((AVFilterContext *)priv, AV_LOG_VERBOSE, fmt, args); +} + +static av_cold int init(AVFilterContext *ctx) +{ + HDCDContext *s = ctx->priv; + + s->shdcd = hdcd_new(); + hdcd_logger_attach(s->shdcd, af_hdcd_log, ctx); + + if (s->analyze_mode) + hdcd_analyze_mode(s->shdcd, s->analyze_mode); + av_log(ctx, AV_LOG_VERBOSE, "Analyze mode: [%d] %s\n", + s->analyze_mode, hdcd_str_analyze_mode_desc(s->analyze_mode)); + + return 0; +} + +static const AVFilterPad avfilter_af_hdcd_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad avfilter_af_hdcd_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_hdcd = { + .name = "hdcd", + .description = NULL_IF_CONFIG_SMALL("Apply High Definition Compatible Digital (HDCD) decoding."), + .priv_size = sizeof(HDCDContext), + .priv_class = &hdcd_class, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = avfilter_af_hdcd_inputs, + .outputs = avfilter_af_hdcd_outputs, +}; diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index e684cb9..4d86c8b 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or diff --git a/libavfilter/af_resample.c b/libavfilter/af_resample.c index fbe6105..413b663 100644 --- a/libavfilter/af_resample.c +++ b/libavfilter/af_resample.c @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -41,6 +40,7 @@ typedef struct ResampleContext { AVAudioResampleContext *avr; AVDictionary *options; + int resampling; int64_t next_pts; int64_t next_in_pts; @@ -118,6 +118,8 @@ static int config_output(AVFilterLink *outlink) char buf1[64], buf2[64]; int ret; + int64_t resampling_forced; + if (s->avr) { avresample_close(s->avr); avresample_free(&s->avr); @@ -156,9 +158,15 @@ static int config_output(AVFilterLink *outlink) if ((ret = avresample_open(s->avr)) < 0) return ret; - outlink->time_base = (AVRational){ 1, outlink->sample_rate }; - s->next_pts = AV_NOPTS_VALUE; - s->next_in_pts = AV_NOPTS_VALUE; + av_opt_get_int(s->avr, "force_resampling", 0, &resampling_forced); + s->resampling = resampling_forced || (inlink->sample_rate != outlink->sample_rate); + + if (s->resampling) { + outlink->time_base = (AVRational){ 1, outlink->sample_rate }; + s->next_pts = AV_NOPTS_VALUE; + s->next_in_pts = AV_NOPTS_VALUE; + } else + outlink->time_base = inlink->time_base; av_get_channel_layout_string(buf1, sizeof(buf1), -1, inlink ->channel_layout); @@ -202,6 +210,7 @@ static int request_frame(AVFilterLink *outlink) return (ret == 0) ? AVERROR_EOF : ret; } + frame->nb_samples = ret; frame->pts = s->next_pts; return ff_filter_frame(outlink, frame); } @@ -240,7 +249,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_assert0(!avresample_available(s->avr)); - if (s->next_pts == AV_NOPTS_VALUE) { + if (s->resampling && s->next_pts == AV_NOPTS_VALUE) { if (in->pts == AV_NOPTS_VALUE) { av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " "assuming 0.\n"); @@ -259,22 +268,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) goto fail; } - out->sample_rate = outlink->sample_rate; - /* Only convert in->pts if there is a discontinuous jump. - This ensures that out->pts tracks the number of samples actually - output by the resampler in the absence of such a jump. - Otherwise, the rounding in av_rescale_q() and av_rescale() - causes off-by-1 errors. */ - if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) { - out->pts = av_rescale_q(in->pts, inlink->time_base, - outlink->time_base) - - av_rescale(delay, outlink->sample_rate, - inlink->sample_rate); + if (s->resampling) { + out->sample_rate = outlink->sample_rate; + /* Only convert in->pts if there is a discontinuous jump. + This ensures that out->pts tracks the number of samples actually + output by the resampler in the absence of such a jump. + Otherwise, the rounding in av_rescale_q() and av_rescale() + causes off-by-1 errors. */ + if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) { + out->pts = av_rescale_q(in->pts, inlink->time_base, + outlink->time_base) - + av_rescale(delay, outlink->sample_rate, + inlink->sample_rate); + } else + out->pts = s->next_pts; + + s->next_pts = out->pts + out->nb_samples; + s->next_in_pts = in->pts + in->nb_samples; } else - out->pts = s->next_pts; - - s->next_pts = out->pts + out->nb_samples; - s->next_in_pts = in->pts + in->nb_samples; + out->pts = in->pts; ret = ff_filter_frame(outlink, out); s->got_output = 1; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 67a298d..ec27b5a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -57,6 +57,7 @@ void avfilter_register_all(void) REGISTER_FILTER(CHANNELMAP, channelmap, af); REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); REGISTER_FILTER(COMPAND, compand, af); + REGISTER_FILTER(HDCD, hdcd, af); REGISTER_FILTER(JOIN, join, af); REGISTER_FILTER(RESAMPLE, resample, af); REGISTER_FILTER(VOLUME, volume, af); @@ -70,6 +71,7 @@ void avfilter_register_all(void) REGISTER_FILTER(COPY, copy, vf); REGISTER_FILTER(CROP, crop, vf); REGISTER_FILTER(CROPDETECT, cropdetect, vf); + REGISTER_FILTER(DEINTERLACE_QSV,deinterlace_qsv,vf); REGISTER_FILTER(DELOGO, delogo, vf); REGISTER_FILTER(DRAWBOX, drawbox, vf); REGISTER_FILTER(DRAWTEXT, drawtext, vf); @@ -82,6 +84,9 @@ void avfilter_register_all(void) REGISTER_FILTER(GRADFUN, gradfun, vf); REGISTER_FILTER(HFLIP, hflip, vf); REGISTER_FILTER(HQDN3D, hqdn3d, vf); + REGISTER_FILTER(HWDOWNLOAD, hwdownload, vf); + REGISTER_FILTER(HWUPLOAD, hwupload, vf); + REGISTER_FILTER(HWUPLOAD_CUDA, hwupload_cuda, vf); REGISTER_FILTER(INTERLACE, interlace, vf); REGISTER_FILTER(LUT, lut, vf); REGISTER_FILTER(LUTRGB, lutrgb, vf); @@ -94,6 +99,9 @@ void avfilter_register_all(void) REGISTER_FILTER(PAD, pad, vf); REGISTER_FILTER(PIXDESCTEST, pixdesctest, vf); REGISTER_FILTER(SCALE, scale, vf); + REGISTER_FILTER(SCALE_NPP, scale_npp, vf); + REGISTER_FILTER(SCALE_QSV, scale_qsv, vf); + REGISTER_FILTER(SCALE_VAAPI, scale_vaapi, vf); REGISTER_FILTER(SELECT, select, vf); REGISTER_FILTER(SETDAR, setdar, vf); REGISTER_FILTER(SETPTS, setpts, vf); diff --git a/libavfilter/audio.c b/libavfilter/audio.c index b332e9e..5fe9da9 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -66,75 +66,3 @@ AVFrame *ff_get_audio_buffer(AVFilterLink *link, int nb_samples) return ret; } - -#if FF_API_AVFILTERBUFFER -AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays(uint8_t **data, - int linesize,int perms, - int nb_samples, - enum AVSampleFormat sample_fmt, - uint64_t channel_layout) -{ - int planes; - AVFilterBuffer *samples = av_mallocz(sizeof(*samples)); - AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref)); - - if (!samples || !samplesref) - goto fail; - - samplesref->buf = samples; - samplesref->buf->free = ff_avfilter_default_free_buffer; - if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio)))) - goto fail; - - samplesref->audio->nb_samples = nb_samples; - samplesref->audio->channel_layout = channel_layout; - samplesref->audio->planar = av_sample_fmt_is_planar(sample_fmt); - - planes = samplesref->audio->planar ? av_get_channel_layout_nb_channels(channel_layout) : 1; - - /* make sure the buffer gets read permission or it's useless for output */ - samplesref->perms = perms | AV_PERM_READ; - - samples->refcount = 1; - samplesref->type = AVMEDIA_TYPE_AUDIO; - samplesref->format = sample_fmt; - - memcpy(samples->data, data, - FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0])); - memcpy(samplesref->data, samples->data, sizeof(samples->data)); - - samples->linesize[0] = samplesref->linesize[0] = linesize; - - if (planes > FF_ARRAY_ELEMS(samples->data)) { - samples-> extended_data = av_mallocz(sizeof(*samples->extended_data) * - planes); - samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) * - planes); - - if (!samples->extended_data || !samplesref->extended_data) - goto fail; - - memcpy(samples-> extended_data, data, sizeof(*data)*planes); - memcpy(samplesref->extended_data, data, sizeof(*data)*planes); - } else { - samples->extended_data = samples->data; - samplesref->extended_data = samplesref->data; - } - - samplesref->pts = AV_NOPTS_VALUE; - - return samplesref; - -fail: - if (samples && samples->extended_data != samples->data) - av_freep(&samples->extended_data); - if (samplesref) { - av_freep(&samplesref->audio); - if (samplesref->extended_data != samplesref->data) - av_freep(&samplesref->extended_data); - } - av_freep(&samplesref); - av_freep(&samples); - return NULL; -} -#endif diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 4098973..1cedb15 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -20,8 +20,10 @@ */ #include "libavutil/avstring.h" +#include "libavutil/buffer.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/hwcontext.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -79,7 +81,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad || src->outputs[srcpad] || dst->inputs[dstpad]) - return -1; + return AVERROR(EINVAL); if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) { av_log(src, AV_LOG_ERROR, @@ -195,6 +197,8 @@ int avfilter_config_links(AVFilterContext *filter) link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1}; if (link->src->nb_inputs) { + if (!link->frame_rate.num && !link->frame_rate.den) + link->frame_rate = link->src->inputs[0]->frame_rate; if (!link->w) link->w = link->src->inputs[0]->w; if (!link->h) @@ -207,6 +211,17 @@ int avfilter_config_links(AVFilterContext *filter) } } + if (link->src->nb_inputs && link->src->inputs[0]->hw_frames_ctx && + !link->hw_frames_ctx) { + AVHWFramesContext *input_ctx = (AVHWFramesContext*)link->src->inputs[0]->hw_frames_ctx->data; + + if (input_ctx->format == link->format) { + link->hw_frames_ctx = av_buffer_ref(link->src->inputs[0]->hw_frames_ctx); + if (!link->hw_frames_ctx) + return AVERROR(ENOMEM); + } + } + if ((config_link = link->dstpad->config_props)) if ((ret = config_link(link)) < 0) { av_log(link->dst, AV_LOG_ERROR, @@ -225,7 +240,7 @@ int avfilter_config_links(AVFilterContext *filter) void ff_dlog_link(void *ctx, AVFilterLink *link, int end) { if (link->type == AVMEDIA_TYPE_VIDEO) { - av_dlog(ctx, + av_log(ctx, AV_LOG_TRACE, "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", link, link->w, link->h, av_get_pix_fmt_name(link->format), @@ -236,7 +251,7 @@ void ff_dlog_link(void *ctx, AVFilterLink *link, int end) char buf[128]; av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout); - av_dlog(ctx, + av_log(ctx, AV_LOG_TRACE, "link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s", link, link->sample_rate, buf, av_get_sample_fmt_name(link->format), @@ -254,7 +269,8 @@ int ff_request_frame(AVFilterLink *link) return link->srcpad->request_frame(link); else if (link->src->inputs[0]) return ff_request_frame(link->src->inputs[0]); - else return -1; + else + return AVERROR(EINVAL); } int ff_poll_frame(AVFilterLink *link) @@ -267,7 +283,7 @@ int ff_poll_frame(AVFilterLink *link) for (i = 0; i < link->src->nb_inputs; i++) { int val; if (!link->src->inputs[i]) - return -1; + return AVERROR(EINVAL); val = ff_poll_frame(link->src->inputs[i]); min = FFMIN(min, val); } @@ -444,12 +460,6 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) if (!ret->outputs) goto err; } -#if FF_API_FOO_COUNT -FF_DISABLE_DEPRECATION_WARNINGS - ret->output_count = ret->nb_outputs; - ret->input_count = ret->nb_inputs; -FF_ENABLE_DEPRECATION_WARNINGS -#endif return ret; @@ -484,6 +494,8 @@ static void free_link(AVFilterLink *link) if (link->dst) link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; + av_buffer_unref(&link->hw_frames_ctx); + ff_formats_unref(&link->in_formats); ff_formats_unref(&link->out_formats); ff_formats_unref(&link->in_samplerates); @@ -513,6 +525,8 @@ void avfilter_free(AVFilterContext *filter) if (filter->filter->priv_class) av_opt_free(filter->priv); + av_buffer_unref(&filter->hw_device_ctx); + av_freep(&filter->name); av_freep(&filter->input_pads); av_freep(&filter->output_pads); diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 1b42086..a17b2a2 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -35,12 +35,12 @@ #include "libavutil/attributes.h" #include "libavutil/avutil.h" +#include "libavutil/buffer.h" #include "libavutil/frame.h" #include "libavutil/log.h" #include "libavutil/samplefmt.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" -#include "libavcodec/avcodec.h" #include @@ -67,307 +67,6 @@ typedef struct AVFilterLink AVFilterLink; typedef struct AVFilterPad AVFilterPad; typedef struct AVFilterFormats AVFilterFormats; -#if FF_API_AVFILTERBUFFER -/** - * A reference-counted buffer data type used by the filter system. Filters - * should not store pointers to this structure directly, but instead use the - * AVFilterBufferRef structure below. - */ -typedef struct AVFilterBuffer { - uint8_t *data[8]; ///< buffer data for each plane/channel - - /** - * pointers to the data planes/channels. - * - * For video, this should simply point to data[]. - * - * For planar audio, each channel has a separate data pointer, and - * linesize[0] contains the size of each channel buffer. - * For packed audio, there is just one data pointer, and linesize[0] - * contains the total size of the buffer for all channels. - * - * Note: Both data and extended_data will always be set, but for planar - * audio with more channels that can fit in data, extended_data must be used - * in order to access all channels. - */ - uint8_t **extended_data; - int linesize[8]; ///< number of bytes per line - - /** private data to be used by a custom free function */ - void *priv; - /** - * A pointer to the function to deallocate this buffer if the default - * function is not sufficient. This could, for example, add the memory - * back into a memory pool to be reused later without the overhead of - * reallocating it from scratch. - */ - void (*free)(struct AVFilterBuffer *buf); - - int format; ///< media format - int w, h; ///< width and height of the allocated buffer - unsigned refcount; ///< number of references to this buffer -} AVFilterBuffer; - -#define AV_PERM_READ 0x01 ///< can read from the buffer -#define AV_PERM_WRITE 0x02 ///< can write to the buffer -#define AV_PERM_PRESERVE 0x04 ///< nobody else can overwrite the buffer -#define AV_PERM_REUSE 0x08 ///< can output the buffer multiple times, with the same contents each time -#define AV_PERM_REUSE2 0x10 ///< can output the buffer multiple times, modified each time -#define AV_PERM_NEG_LINESIZES 0x20 ///< the buffer requested can have negative linesizes - -/** - * Audio specific properties in a reference to an AVFilterBuffer. Since - * AVFilterBufferRef is common to different media formats, audio specific - * per reference properties must be separated out. - */ -typedef struct AVFilterBufferRefAudioProps { - uint64_t channel_layout; ///< channel layout of audio buffer - int nb_samples; ///< number of audio samples - int sample_rate; ///< audio buffer sample rate - int planar; ///< audio buffer - planar or packed -} AVFilterBufferRefAudioProps; - -/** - * Video specific properties in a reference to an AVFilterBuffer. Since - * AVFilterBufferRef is common to different media formats, video specific - * per reference properties must be separated out. - */ -typedef struct AVFilterBufferRefVideoProps { - int w; ///< image width - int h; ///< image height - AVRational pixel_aspect; ///< pixel aspect ratio - int interlaced; ///< is frame interlaced - int top_field_first; ///< field order - enum AVPictureType pict_type; ///< picture type of the frame - int key_frame; ///< 1 -> keyframe, 0-> not -} AVFilterBufferRefVideoProps; - -/** - * A reference to an AVFilterBuffer. Since filters can manipulate the origin of - * a buffer to, for example, crop image without any memcpy, the buffer origin - * and dimensions are per-reference properties. Linesize is also useful for - * image flipping, frame to field filters, etc, and so is also per-reference. - * - * TODO: add anything necessary for frame reordering - */ -typedef struct AVFilterBufferRef { - AVFilterBuffer *buf; ///< the buffer that this is a reference to - uint8_t *data[8]; ///< picture/audio data for each plane - /** - * pointers to the data planes/channels. - * - * For video, this should simply point to data[]. - * - * For planar audio, each channel has a separate data pointer, and - * linesize[0] contains the size of each channel buffer. - * For packed audio, there is just one data pointer, and linesize[0] - * contains the total size of the buffer for all channels. - * - * Note: Both data and extended_data will always be set, but for planar - * audio with more channels that can fit in data, extended_data must be used - * in order to access all channels. - */ - uint8_t **extended_data; - int linesize[8]; ///< number of bytes per line - - AVFilterBufferRefVideoProps *video; ///< video buffer specific properties - AVFilterBufferRefAudioProps *audio; ///< audio buffer specific properties - - /** - * presentation timestamp. The time unit may change during - * filtering, as it is specified in the link and the filter code - * may need to rescale the PTS accordingly. - */ - int64_t pts; - int64_t pos; ///< byte position in stream, -1 if unknown - - int format; ///< media format - - int perms; ///< permissions, see the AV_PERM_* flags - - enum AVMediaType type; ///< media type of buffer data -} AVFilterBufferRef; - -/** - * Copy properties of src to dst, without copying the actual data - */ -attribute_deprecated -void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src); - -/** - * Add a new reference to a buffer. - * - * @param ref an existing reference to the buffer - * @param pmask a bitmask containing the allowable permissions in the new - * reference - * @return a new reference to the buffer with the same properties as the - * old, excluding any permissions denied by pmask - */ -attribute_deprecated -AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask); - -/** - * Remove a reference to a buffer. If this is the last reference to the - * buffer, the buffer itself is also automatically freed. - * - * @param ref reference to the buffer, may be NULL - * - * @note it is recommended to use avfilter_unref_bufferp() instead of this - * function - */ -attribute_deprecated -void avfilter_unref_buffer(AVFilterBufferRef *ref); - -/** - * Remove a reference to a buffer and set the pointer to NULL. - * If this is the last reference to the buffer, the buffer itself - * is also automatically freed. - * - * @param ref pointer to the buffer reference - */ -attribute_deprecated -void avfilter_unref_bufferp(AVFilterBufferRef **ref); -#endif - -#if FF_API_AVFILTERPAD_PUBLIC -/** - * A filter pad used for either input or output. - * - * @warning this struct will be removed from public API. - * users should call avfilter_pad_get_name() and avfilter_pad_get_type() - * to access the name and type fields; there should be no need to access - * any other fields from outside of libavfilter. - */ -struct AVFilterPad { - /** - * Pad name. The name is unique among inputs and among outputs, but an - * input may have the same name as an output. This may be NULL if this - * pad has no need to ever be referenced by name. - */ - const char *name; - - /** - * AVFilterPad type. - */ - enum AVMediaType type; - - /** - * Minimum required permissions on incoming buffers. Any buffer with - * insufficient permissions will be automatically copied by the filter - * system to a new buffer which provides the needed access permissions. - * - * Input pads only. - */ - attribute_deprecated int min_perms; - - /** - * Permissions which are not accepted on incoming buffers. Any buffer - * which has any of these permissions set will be automatically copied - * by the filter system to a new buffer which does not have those - * permissions. This can be used to easily disallow buffers with - * AV_PERM_REUSE. - * - * Input pads only. - */ - attribute_deprecated int rej_perms; - - /** - * @deprecated unused - */ - int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); - - /** - * Callback function to get a video buffer. If NULL, the filter system will - * use avfilter_default_get_video_buffer(). - * - * Input video pads only. - */ - AVFrame *(*get_video_buffer)(AVFilterLink *link, int w, int h); - - /** - * Callback function to get an audio buffer. If NULL, the filter system will - * use avfilter_default_get_audio_buffer(). - * - * Input audio pads only. - */ - AVFrame *(*get_audio_buffer)(AVFilterLink *link, int nb_samples); - - /** - * @deprecated unused - */ - int (*end_frame)(AVFilterLink *link); - - /** - * @deprecated unused - */ - int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); - - /** - * Filtering callback. This is where a filter receives a frame with - * audio/video data and should do its processing. - * - * Input pads only. - * - * @return >= 0 on success, a negative AVERROR on error. This function - * must ensure that samplesref is properly unreferenced on error if it - * hasn't been passed on to another filter. - */ - int (*filter_frame)(AVFilterLink *link, AVFrame *frame); - - /** - * Frame poll callback. This returns the number of immediately available - * samples. It should return a positive value if the next request_frame() - * is guaranteed to return one frame (with no delay). - * - * Defaults to just calling the source poll_frame() method. - * - * Output pads only. - */ - int (*poll_frame)(AVFilterLink *link); - - /** - * Frame request callback. A call to this should result in at least one - * frame being output over the given link. This should return zero on - * success, and another value on error. - * - * Output pads only. - */ - int (*request_frame)(AVFilterLink *link); - - /** - * Link configuration callback. - * - * For output pads, this should set the link properties such as - * width/height. This should NOT set the format property - that is - * negotiated between filters by the filter system using the - * query_formats() callback before this function is called. - * - * For input pads, this should check the properties of the link, and update - * the filter's internal state as necessary. - * - * For both input and output filters, this should return zero on success, - * and another value on error. - */ - int (*config_props)(AVFilterLink *link); - - /** - * The filter expects a fifo to be inserted on its input link, - * typically because it has a delay. - * - * input pads only. - */ - int needs_fifo; - - /** - * The filter expects writable frames from its input link, - * duplicating data buffers if needed. - * - * input pads only. - */ - int needs_writable; -}; -#endif - /** * Get the number of elements in a NULL-terminated array of AVFilterPads (e.g. * AVFilter.inputs/outputs). @@ -569,16 +268,10 @@ struct AVFilterContext { AVFilterPad *input_pads; ///< array of input pads AVFilterLink **inputs; ///< array of pointers to input links -#if FF_API_FOO_COUNT - attribute_deprecated unsigned input_count; ///< @deprecated use nb_inputs -#endif unsigned nb_inputs; ///< number of input pads AVFilterPad *output_pads; ///< array of output pads AVFilterLink **outputs; ///< array of pointers to output links -#if FF_API_FOO_COUNT - attribute_deprecated unsigned output_count; ///< @deprecated use nb_outputs -#endif unsigned nb_outputs; ///< number of output pads void *priv; ///< private data for use by the filter @@ -607,6 +300,15 @@ struct AVFilterContext { * An opaque struct for libavfilter internal use. */ AVFilterInternal *internal; + + /** + * For filters which will create hardware frames, sets the device the + * filter should create them in. All other filters will ignore this field: + * in particular, a filter which consumes or processes hardware frames will + * instead use the hw_frames_ctx field in AVFilterLink to carry the + * hardware context information. + */ + AVBufferRef *hw_device_ctx; }; /** @@ -683,6 +385,24 @@ struct AVFilterLink { AVLINK_STARTINIT, ///< started, but incomplete AVLINK_INIT ///< complete } init_state; + + /** + * Frame rate of the stream on the link, or 1/0 if unknown or variable; + * if left to 0/0, will be automatically copied from the first input + * of the source filter if it exists. + * + * Sources should set it to the real constant frame rate. + * If the source frame rate is unknown or variable, set this to 1/0. + * Filters should update it if necessary depending on their function. + * Sinks can use it to set a default output frame rate. + */ + AVRational frame_rate; + + /** + * For hwaccel pixel formats, this should be a reference to the + * AVHWFramesContext describing the frames. + */ + AVBufferRef *hw_frames_ctx; }; /** @@ -705,43 +425,6 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, */ int avfilter_config_links(AVFilterContext *filter); -#if FF_API_AVFILTERBUFFER -/** - * Create a buffer reference wrapped around an already allocated image - * buffer. - * - * @param data pointers to the planes of the image to reference - * @param linesize linesizes for the planes of the image to reference - * @param perms the required access permissions - * @param w the width of the image specified by the data and linesize arrays - * @param h the height of the image specified by the data and linesize arrays - * @param format the pixel format of the image specified by the data and linesize arrays - */ -attribute_deprecated -AVFilterBufferRef * -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, - int w, int h, enum AVPixelFormat format); - -/** - * Create an audio buffer reference wrapped around an already - * allocated samples buffer. - * - * @param data pointers to the samples plane buffers - * @param linesize linesize for the samples plane buffers - * @param perms the required access permissions - * @param nb_samples number of samples per channel - * @param sample_fmt the format of each sample in the buffer to allocate - * @param channel_layout the channel layout of the buffer - */ -attribute_deprecated -AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_arrays(uint8_t **data, - int linesize, - int perms, - int nb_samples, - enum AVSampleFormat sample_fmt, - uint64_t channel_layout); -#endif - /** Initialize the filter system. Register all builtin filters. */ void avfilter_register_all(void); @@ -758,7 +441,7 @@ void avfilter_uninit(void); * is not registered. * * @param filter the filter to register - * @return 0 if the registration was succesfull, a negative value + * @return 0 if the registration was successful, a negative value * otherwise */ int avfilter_register(AVFilter *filter); @@ -879,26 +562,6 @@ void avfilter_free(AVFilterContext *filter); int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx); -#if FF_API_AVFILTERBUFFER -/** - * Copy the frame properties of src to dst, without copying the actual - * image data. - * - * @return 0 on success, a negative number on error. - */ -attribute_deprecated -int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src); - -/** - * Copy the frame properties and data pointers of src to dst, without copying - * the actual data. - * - * @return 0 on success, a negative number on error. - */ -attribute_deprecated -int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src); -#endif - /** * @return AVClass for AVFilterContext. * @@ -939,20 +602,11 @@ typedef int (avfilter_execute_func)(AVFilterContext *ctx, avfilter_action_func * typedef struct AVFilterGraph { const AVClass *av_class; -#if FF_API_FOO_COUNT - attribute_deprecated - unsigned filter_count; -#endif AVFilterContext **filters; -#if !FF_API_FOO_COUNT unsigned nb_filters; -#endif char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters char *resample_lavr_opts; ///< libavresample options to use for the auto-inserted resample filters -#if FF_API_FOO_COUNT - unsigned nb_filters; -#endif /** * Type of multithreading allowed for filters in this graph. A combination @@ -1004,6 +658,8 @@ typedef struct AVFilterGraph { /** * Allocate a filter graph. + * + * @return the allocated filter graph on success or NULL. */ AVFilterGraph *avfilter_graph_alloc(void); diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 0fc385c..5053e3c 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -127,12 +127,6 @@ int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter) graph->filters = filters; graph->filters[graph->nb_filters++] = filter; -#if FF_API_FOO_COUNT -FF_DISABLE_DEPRECATION_WARNINGS - graph->filter_count = graph->nb_filters; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - filter->graph = graph; return 0; @@ -193,12 +187,6 @@ AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, graph->filters = filters; graph->filters[graph->nb_filters++] = s; -#if FF_API_FOO_COUNT -FF_DISABLE_DEPRECATION_WARNINGS - graph->filter_count = graph->nb_filters; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - s->graph = graph; return s; @@ -283,9 +271,15 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) /* ask all the sub-filters for their supported media formats */ for (i = 0; i < graph->nb_filters; i++) { if (graph->filters[i]->filter->query_formats) - graph->filters[i]->filter->query_formats(graph->filters[i]); + ret = graph->filters[i]->filter->query_formats(graph->filters[i]); else - ff_default_query_formats(graph->filters[i]); + ret = ff_default_query_formats(graph->filters[i]); + if (ret < 0) { + av_log(log_ctx, AV_LOG_ERROR, + "Error querying formats for the filter %s (%s)\n", + graph->filters[i]->name, graph->filters[i]->filter->name); + return ret; + } } /* go through and merge as many format lists as possible */ diff --git a/libavfilter/buffer.c b/libavfilter/buffer.c deleted file mode 100644 index fd0b18f..0000000 --- a/libavfilter/buffer.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/channel_layout.h" -#include "libavutil/common.h" -#include "libavutil/internal.h" -#include "libavcodec/avcodec.h" - -#include "avfilter.h" -#include "internal.h" -#include "version.h" - -#if FF_API_AVFILTERBUFFER -/* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */ -void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr) -{ - if (ptr->extended_data != ptr->data) - av_freep(&ptr->extended_data); - av_free(ptr->data[0]); - av_free(ptr); -} - -AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) -{ - AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); - if (!ret) - return NULL; - *ret = *ref; - if (ref->type == AVMEDIA_TYPE_VIDEO) { - ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps)); - if (!ret->video) { - av_free(ret); - return NULL; - } - *ret->video = *ref->video; - ret->extended_data = ret->data; - } else if (ref->type == AVMEDIA_TYPE_AUDIO) { - ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps)); - if (!ret->audio) { - av_free(ret); - return NULL; - } - *ret->audio = *ref->audio; - - if (ref->extended_data != ref->data) { - int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout); - if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) * - nb_channels))) { - av_freep(&ret->audio); - av_freep(&ret); - return NULL; - } - memcpy(ret->extended_data, ref->extended_data, - sizeof(*ret->extended_data) * nb_channels); - } else - ret->extended_data = ret->data; - } - ret->perms &= pmask; - ret->buf->refcount ++; - return ret; -} - -void avfilter_unref_buffer(AVFilterBufferRef *ref) -{ - if (!ref) - return; - if (!(--ref->buf->refcount)) - ref->buf->free(ref->buf); - if (ref->extended_data != ref->data) - av_freep(&ref->extended_data); - av_free(ref->video); - av_free(ref->audio); - av_free(ref); -} - -void avfilter_unref_bufferp(AVFilterBufferRef **ref) -{ -FF_DISABLE_DEPRECATION_WARNINGS - avfilter_unref_buffer(*ref); -FF_ENABLE_DEPRECATION_WARNINGS - *ref = NULL; -} - -int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) -{ - dst->pts = src->pts; - dst->format = src->format; - - switch (dst->type) { - case AVMEDIA_TYPE_VIDEO: - dst->video->w = src->width; - dst->video->h = src->height; - dst->video->pixel_aspect = src->sample_aspect_ratio; - dst->video->interlaced = src->interlaced_frame; - dst->video->top_field_first = src->top_field_first; - dst->video->key_frame = src->key_frame; - dst->video->pict_type = src->pict_type; - break; - case AVMEDIA_TYPE_AUDIO: - dst->audio->sample_rate = src->sample_rate; - dst->audio->channel_layout = src->channel_layout; - break; - default: - return AVERROR(EINVAL); - } - - return 0; -} - -int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src) -{ - int planes, nb_channels; - - memcpy(dst->data, src->data, sizeof(dst->data)); - memcpy(dst->linesize, src->linesize, sizeof(dst->linesize)); - - dst->pts = src->pts; - dst->format = src->format; - - switch (src->type) { - case AVMEDIA_TYPE_VIDEO: - dst->width = src->video->w; - dst->height = src->video->h; - dst->sample_aspect_ratio = src->video->pixel_aspect; - dst->interlaced_frame = src->video->interlaced; - dst->top_field_first = src->video->top_field_first; - dst->key_frame = src->video->key_frame; - dst->pict_type = src->video->pict_type; - break; - case AVMEDIA_TYPE_AUDIO: - nb_channels = av_get_channel_layout_nb_channels(src->audio->channel_layout); - planes = av_sample_fmt_is_planar(src->format) ? nb_channels : 1; - - if (planes > FF_ARRAY_ELEMS(dst->data)) { - dst->extended_data = av_mallocz(planes * sizeof(*dst->extended_data)); - if (!dst->extended_data) - return AVERROR(ENOMEM); - memcpy(dst->extended_data, src->extended_data, - planes * sizeof(*dst->extended_data)); - } else - dst->extended_data = dst->data; - - dst->sample_rate = src->audio->sample_rate; - dst->channel_layout = src->audio->channel_layout; - dst->nb_samples = src->audio->nb_samples; - break; - default: - return AVERROR(EINVAL); - } - - return 0; -} - -void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src) -{ - // copy common properties - dst->pts = src->pts; - dst->pos = src->pos; - - switch (src->type) { - case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break; - case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break; - default: break; - } -} -#endif /* FF_API_AVFILTERBUFFER */ diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index 2894a5b..3b4d285 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -137,80 +137,6 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, return ret; } -#if FF_API_AVFILTERBUFFER -FF_DISABLE_DEPRECATION_WARNINGS -static void compat_free_buffer(AVFilterBuffer *buf) -{ - AVFrame *frame = buf->priv; - av_frame_free(&frame); - av_free(buf); -} - -static int compat_read(AVFilterContext *ctx, - AVFilterBufferRef **pbuf, int nb_samples) -{ - AVFilterBufferRef *buf; - AVFrame *frame; - int ret; - - if (!pbuf) - return ff_poll_frame(ctx->inputs[0]); - - frame = av_frame_alloc(); - if (!frame) - return AVERROR(ENOMEM); - - if (!nb_samples) - ret = av_buffersink_get_frame(ctx, frame); - else - ret = av_buffersink_get_samples(ctx, frame, nb_samples); - - if (ret < 0) - goto fail; - - if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) { - buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, - AV_PERM_READ, - frame->width, frame->height, - frame->format); - } else { - buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data, - frame->linesize[0], AV_PERM_READ, - frame->nb_samples, - frame->format, - frame->channel_layout); - } - if (!buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - - avfilter_copy_frame_props(buf, frame); - - buf->buf->priv = frame; - buf->buf->free = compat_free_buffer; - - *pbuf = buf; - - return 0; -fail: - av_frame_free(&frame); - return ret; -} - -int attribute_align_arg av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) -{ - return compat_read(ctx, buf, 0); -} - -int attribute_align_arg av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf, - int nb_samples) -{ - return compat_read(ctx, buf, nb_samples); -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - static const AVFilterPad avfilter_vsink_buffer_inputs[] = { { .name = "default", diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h index 83a8bd9..76f5a29 100644 --- a/libavfilter/buffersink.h +++ b/libavfilter/buffersink.h @@ -33,43 +33,6 @@ * @{ */ -#if FF_API_AVFILTERBUFFER -/** - * Get a buffer with filtered data from sink and put it in buf. - * - * @param ctx pointer to a context of a buffersink or abuffersink AVFilter. - * @param buf pointer to the buffer will be written here if buf is non-NULL. buf - * must be freed by the caller using avfilter_unref_buffer(). - * Buf may also be NULL to query whether a buffer is ready to be - * output. - * - * @return >= 0 in case of success, a negative AVERROR code in case of - * failure. - */ -attribute_deprecated -int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf); - -/** - * Same as av_buffersink_read, but with the ability to specify the number of - * samples read. This function is less efficient than av_buffersink_read(), - * because it copies the data around. - * - * @param ctx pointer to a context of the abuffersink AVFilter. - * @param buf pointer to the buffer will be written here if buf is non-NULL. buf - * must be freed by the caller using avfilter_unref_buffer(). buf - * will contain exactly nb_samples audio samples, except at the end - * of stream, when it can contain less than nb_samples. - * Buf may also be NULL to query whether a buffer is ready to be - * output. - * - * @warning do not mix this function with av_buffersink_read(). Use only one or - * the other with a single sink, not both. - */ -attribute_deprecated -int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf, - int nb_samples); -#endif - /** * Get a frame with filtered data from sink and put it in frame. * diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 00e28f8..f553508 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -44,6 +44,7 @@ typedef struct BufferSourceContext { const AVClass *class; AVFifoBuffer *fifo; AVRational time_base; ///< time_base to set in the output link + AVRational frame_rate; ///< frame_rate to set in the output link /* video only */ int h, w; @@ -51,6 +52,8 @@ typedef struct BufferSourceContext { char *pix_fmt_str; AVRational pixel_aspect; + AVBufferRef *hw_frames_ctx; + /* audio only */ int sample_rate; enum AVSampleFormat sample_fmt; @@ -58,6 +61,7 @@ typedef struct BufferSourceContext { uint64_t channel_layout; char *channel_layout_str; + int got_format_from_params; int eof; } BufferSourceContext; @@ -74,6 +78,62 @@ typedef struct BufferSourceContext { return AVERROR(EINVAL);\ } +AVBufferSrcParameters *av_buffersrc_parameters_alloc(void) +{ + AVBufferSrcParameters *par = av_mallocz(sizeof(*par)); + if (!par) + return NULL; + + par->format = -1; + + return par; +} + +int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param) +{ + BufferSourceContext *s = ctx->priv; + + if (param->time_base.num > 0 && param->time_base.den > 0) + s->time_base = param->time_base; + + switch (ctx->filter->outputs[0].type) { + case AVMEDIA_TYPE_VIDEO: + if (param->format != AV_PIX_FMT_NONE) { + s->got_format_from_params = 1; + s->pix_fmt = param->format; + } + if (param->width > 0) + s->w = param->width; + if (param->height > 0) + s->h = param->height; + if (param->sample_aspect_ratio.num > 0 && param->sample_aspect_ratio.den > 0) + s->pixel_aspect = param->sample_aspect_ratio; + if (param->frame_rate.num > 0 && param->frame_rate.den > 0) + s->frame_rate = param->frame_rate; + if (param->hw_frames_ctx) { + av_buffer_unref(&s->hw_frames_ctx); + s->hw_frames_ctx = av_buffer_ref(param->hw_frames_ctx); + if (!s->hw_frames_ctx) + return AVERROR(ENOMEM); + } + break; + case AVMEDIA_TYPE_AUDIO: + if (param->format != AV_SAMPLE_FMT_NONE) { + s->got_format_from_params = 1; + s->sample_fmt = param->format; + } + if (param->sample_rate > 0) + s->sample_rate = param->sample_rate; + if (param->channel_layout) + s->channel_layout = param->channel_layout; + break; + default: + return AVERROR_BUG; + } + + return 0; +} + int attribute_align_arg av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame) { AVFrame *copy; @@ -145,135 +205,34 @@ int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx, return 0; } -#if FF_API_AVFILTERBUFFER -FF_DISABLE_DEPRECATION_WARNINGS -static void compat_free_buffer(void *opaque, uint8_t *data) -{ - AVFilterBufferRef *buf = opaque; - avfilter_unref_buffer(buf); -} - -static void compat_unref_buffer(void *opaque, uint8_t *data) -{ - AVBufferRef *buf = opaque; - av_buffer_unref(&buf); -} - -int av_buffersrc_buffer(AVFilterContext *ctx, AVFilterBufferRef *buf) -{ - BufferSourceContext *s = ctx->priv; - AVFrame *frame = NULL; - AVBufferRef *dummy_buf = NULL; - int ret = 0, planes, i; - - if (!buf) { - s->eof = 1; - return 0; - } else if (s->eof) - return AVERROR(EINVAL); - - frame = av_frame_alloc(); - if (!frame) - return AVERROR(ENOMEM); - - dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, buf, 0); - if (!dummy_buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - - if ((ret = avfilter_copy_buf_props(frame, buf)) < 0) - goto fail; - -#define WRAP_PLANE(ref_out, data, data_size) \ -do { \ - AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf); \ - if (!dummy_ref) { \ - ret = AVERROR(ENOMEM); \ - goto fail; \ - } \ - ref_out = av_buffer_create(data, data_size, compat_unref_buffer, \ - dummy_ref, 0); \ - if (!ref_out) { \ - av_frame_unref(frame); \ - ret = AVERROR(ENOMEM); \ - goto fail; \ - } \ -} while (0) - - if (ctx->outputs[0]->type == AVMEDIA_TYPE_VIDEO) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - - planes = av_pix_fmt_count_planes(frame->format); - if (!desc || planes <= 0) { - ret = AVERROR(EINVAL); - goto fail; - } - - for (i = 0; i < planes; i++) { - int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - int plane_size = (frame->height >> v_shift) * frame->linesize[i]; - - WRAP_PLANE(frame->buf[i], frame->data[i], plane_size); - } - } else { - int planar = av_sample_fmt_is_planar(frame->format); - int channels = av_get_channel_layout_nb_channels(frame->channel_layout); - - planes = planar ? channels : 1; - - if (planes > FF_ARRAY_ELEMS(frame->buf)) { - frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf); - frame->extended_buf = av_mallocz(sizeof(*frame->extended_buf) * - frame->nb_extended_buf); - if (!frame->extended_buf) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - - for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++) - WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]); - - for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++) - WRAP_PLANE(frame->extended_buf[i], - frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)], - frame->linesize[0]); - } - - ret = av_buffersrc_add_frame(ctx, frame); - -fail: - av_buffer_unref(&dummy_buf); - av_frame_free(&frame); - - return ret; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - static av_cold int init_video(AVFilterContext *ctx) { BufferSourceContext *c = ctx->priv; - if (!c->pix_fmt_str || !c->w || !c->h || av_q2d(c->time_base) <= 0) { + if (!(c->pix_fmt_str || c->got_format_from_params) || !c->w || !c->h || + av_q2d(c->time_base) <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid parameters provided.\n"); return AVERROR(EINVAL); } - if ((c->pix_fmt = av_get_pix_fmt(c->pix_fmt_str)) == AV_PIX_FMT_NONE) { - char *tail; - c->pix_fmt = strtol(c->pix_fmt_str, &tail, 10); - if (*tail || c->pix_fmt < 0 || !av_pix_fmt_desc_get(c->pix_fmt)) { - av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", c->pix_fmt_str); - return AVERROR(EINVAL); + if (c->pix_fmt_str) { + if ((c->pix_fmt = av_get_pix_fmt(c->pix_fmt_str)) == AV_PIX_FMT_NONE) { + char *tail; + c->pix_fmt = strtol(c->pix_fmt_str, &tail, 10); + if (*tail || c->pix_fmt < 0 || !av_pix_fmt_desc_get(c->pix_fmt)) { + av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", c->pix_fmt_str); + return AVERROR(EINVAL); + } } } if (!(c->fifo = av_fifo_alloc(sizeof(AVFrame*)))) return AVERROR(ENOMEM); - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt)); + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d sar:%d/%d\n", + c->w, c->h, av_get_pix_fmt_name(c->pix_fmt), + c->time_base.num, c->time_base.den, + c->pixel_aspect.num, c->pixel_aspect.den); return 0; } @@ -293,8 +252,9 @@ static const AVOption video_options[] = { { "sar_num", "deprecated, do not use", OFFSET(pixel_aspect.num), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, { "sar_den", "deprecated, do not use", OFFSET(pixel_aspect.den), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, #endif - { "sar", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 1 }, 0, DBL_MAX, V }, + { "sar", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, + { "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { NULL }, }; @@ -325,14 +285,22 @@ static av_cold int init_audio(AVFilterContext *ctx) BufferSourceContext *s = ctx->priv; int ret = 0; - s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str); + if (!(s->sample_fmt_str || s->got_format_from_params)) { + av_log(ctx, AV_LOG_ERROR, "Sample format not provided\n"); + return AVERROR(EINVAL); + } + if (s->sample_fmt_str) + s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str); + if (s->sample_fmt == AV_SAMPLE_FMT_NONE) { av_log(ctx, AV_LOG_ERROR, "Invalid sample format %s.\n", s->sample_fmt_str); return AVERROR(EINVAL); } - s->channel_layout = av_get_channel_layout(s->channel_layout_str); + if (s->channel_layout_str) + s->channel_layout = av_get_channel_layout(s->channel_layout_str); + if (!s->channel_layout) { av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n", s->channel_layout_str); @@ -360,6 +328,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL); av_frame_free(&frame); } + av_buffer_unref(&s->hw_frames_ctx); av_fifo_free(s->fifo); s->fifo = NULL; } @@ -402,6 +371,12 @@ static int config_props(AVFilterLink *link) link->w = c->w; link->h = c->h; link->sample_aspect_ratio = c->pixel_aspect; + + if (c->hw_frames_ctx) { + link->hw_frames_ctx = av_buffer_ref(c->hw_frames_ctx); + if (!link->hw_frames_ctx) + return AVERROR(ENOMEM); + } break; case AVMEDIA_TYPE_AUDIO: link->channel_layout = c->channel_layout; @@ -412,6 +387,7 @@ static int config_props(AVFilterLink *link) } link->time_base = c->time_base; + link->frame_rate = c->frame_rate; return 0; } @@ -428,7 +404,7 @@ static int request_frame(AVFilterLink *link) } av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL); - ff_filter_frame(link, frame); + ret = ff_filter_frame(link, frame); return ret; } diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index 0ca4d96..dcea3da 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -34,20 +33,79 @@ * @{ */ -#if FF_API_AVFILTERBUFFER /** - * Add a buffer to a filtergraph. + * This structure contains the parameters describing the frames that will be + * passed to this filter. * - * @param ctx an instance of the buffersrc filter - * @param buf buffer containing frame data to be passed down the filtergraph. - * This function will take ownership of buf, the user must not free it. - * A NULL buf signals EOF -- i.e. no more frames will be sent to this filter. + * It should be allocated with av_buffersrc_parameters_alloc() and freed with + * av_free(). All the allocated fields in it remain owned by the caller. + */ +typedef struct AVBufferSrcParameters { + /** + * video: the pixel format, value corresponds to enum AVPixelFormat + * audio: the sample format, value corresponds to enum AVSampleFormat + */ + int format; + /** + * The timebase to be used for the timestamps on the input frames. + */ + AVRational time_base; + + /** + * Video only, the display dimensions of the input frames. + */ + int width, height; + + /** + * Video only, the sample (pixel) aspect ratio. + */ + AVRational sample_aspect_ratio; + + /** + * Video only, the frame rate of the input video. This field must only be + * set to a non-zero value if input stream has a known constant framerate + * and should be left at its initial value if the framerate is variable or + * unknown. + */ + AVRational frame_rate; + + /** + * Video with a hwaccel pixel format only. This should be a reference to an + * AVHWFramesContext instance describing the input frames. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Audio only, the audio sampling rate in samples per secon. + */ + int sample_rate; + + /** + * Audio only, the audio channel layout + */ + uint64_t channel_layout; +} AVBufferSrcParameters; + +/** + * Allocate a new AVBufferSrcParameters instance. It should be freed by the + * caller with av_free(). + */ +AVBufferSrcParameters *av_buffersrc_parameters_alloc(void); + +/** + * Initialize the buffersrc or abuffersrc filter with the provided parameters. + * This function may be called multiple times, the later calls override the + * previous ones. Some of the parameters may also be set through AVOptions, then + * whatever method is used last takes precedence. * - * @deprecated use av_buffersrc_write_frame() or av_buffersrc_add_frame() + * @param ctx an instance of the buffersrc or abuffersrc filter + * @param param the stream parameters. The frames later passed to this filter + * must conform to those parameters. All the allocated fields in + * param remain owned by the caller, libavfilter will make internal + * copies or references when necessary. + * @return 0 on success, a negative AVERROR code on failure. */ -attribute_deprecated -int av_buffersrc_buffer(AVFilterContext *ctx, AVFilterBufferRef *buf); -#endif +int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param); /** * Add a frame to the buffer source. diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 24a4fab..7b5a93c 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -171,8 +171,15 @@ AVFilterFormats *ff_make_format_list(const int *fmts) ; formats = av_mallocz(sizeof(*formats)); - if (count) + if (!formats) + return NULL; + if (count) { formats->formats = av_malloc(sizeof(*formats->formats) * count); + if (!formats->formats) { + av_freep(&formats); + return NULL; + } + } formats->nb_formats = count; memcpy(formats->formats, fmts, sizeof(*formats->formats) * count); @@ -188,8 +195,10 @@ do { \ \ fmts = av_realloc((*f)->list, \ sizeof(*(*f)->list) * ((*f)->nb + 1));\ - if (!fmts) \ + if (!fmts) { \ + av_freep(&f); \ return AVERROR(ENOMEM); \ + } \ \ (*f)->list = fmts; \ (*f)->list[(*f)->nb++] = fmt; \ @@ -213,8 +222,7 @@ AVFilterFormats *ff_all_formats(enum AVMediaType type) if (type == AVMEDIA_TYPE_VIDEO) { const AVPixFmtDescriptor *desc = NULL; while ((desc = av_pix_fmt_desc_next(desc))) { - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - ff_add_format(&ret, av_pix_fmt_desc_get_id(desc)); + ff_add_format(&ret, av_pix_fmt_desc_get_id(desc)); } } else if (type == AVMEDIA_TYPE_AUDIO) { enum AVSampleFormat fmt = 0; @@ -255,6 +263,8 @@ AVFilterChannelLayouts *ff_all_channel_layouts(void) do { \ *ref = f; \ f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount); \ + if (!f->refs) \ + return; \ f->refs[f->refcount-1] = ref; \ } while (0) diff --git a/libavfilter/formats.h b/libavfilter/formats.h index 2e44792..b273f8a 100644 --- a/libavfilter/formats.h +++ b/libavfilter/formats.h @@ -204,7 +204,6 @@ void ff_formats_ref(AVFilterFormats *formats, AVFilterFormats **ref); void ff_formats_unref(AVFilterFormats **ref); /** - * * Before After * ________ ________ * |formats |<---------. |formats |<---------. diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index e20dd62..da499b5 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -62,6 +62,8 @@ static char *parse_link_name(const char **buf, void *log_ctx) (*buf)++; name = av_get_token(buf, "]"); + if (!name) + goto fail; if (!name[0]) { av_log(log_ctx, AV_LOG_ERROR, @@ -79,6 +81,41 @@ static char *parse_link_name(const char **buf, void *log_ctx) return name; } +#define TMP_ARGS_SIZE 256 + +static void append_sws_flags(const char **args, const char *sws_opts, char *tmp) +{ + int nb_opts = 0; + const char *separator = ":"; + const char *opt = *args; + + if (strstr(*args, "flags")) + return; + + if (strstr(*args, "=")) + separator = ":flags="; + + while ((opt = strstr(opt, ":")) && *opt) { + av_log(NULL, AV_LOG_INFO, "opts '%s' \n", opt); + if (nb_opts > 2) { + return; + } + nb_opts++; + opt++; + } + + opt = strstr(sws_opts, "flags="); + if (opt && strlen(opt) > 6) + opt += 6; + else + opt = sws_opts; + + snprintf(tmp, TMP_ARGS_SIZE, "%s%s%s", + *args, separator, opt); + + *args = tmp; +} + /** * Create an instance of a filter, initialize and insert it in the * filtergraph in *ctx. @@ -96,7 +133,7 @@ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int ind { AVFilter *filt; char inst_name[30]; - char tmp_args[256]; + char tmp_args[TMP_ARGS_SIZE]; int ret; snprintf(inst_name, sizeof(inst_name), "Parsed filter %d %s", index, filt_name); @@ -116,11 +153,9 @@ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int ind return AVERROR(ENOMEM); } - if (!strcmp(filt_name, "scale") && args && !strstr(args, "flags") && + if (!strcmp(filt_name, "scale") && args && ctx->scale_sws_opts) { - snprintf(tmp_args, sizeof(tmp_args), "%s:%s", - args, ctx->scale_sws_opts); - args = tmp_args; + append_sws_flags(&args, ctx->scale_sws_opts, tmp_args); } ret = avfilter_init_str(*filt_ctx, args); diff --git a/libavfilter/interlace.h b/libavfilter/interlace.h new file mode 100644 index 0000000..fa571bd --- /dev/null +++ b/libavfilter/interlace.h @@ -0,0 +1,59 @@ +/* + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file + * progressive to interlaced content filter, inspired by heavy debugging of + * tinterlace filter. + */ + +#ifndef AVFILTER_INTERLACE_H +#define AVFILTER_INTERLACE_H + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +enum ScanMode { + MODE_TFF = 0, + MODE_BFF = 1, +}; + +enum FieldType { + FIELD_UPPER = 0, + FIELD_LOWER = 1, +}; + +typedef struct InterlaceContext { + const AVClass *class; + enum ScanMode scan; // top or bottom field first scanning + int lowpass; // enable or disable low pass filtering + AVFrame *cur, *next; // the two frames from which the new one is obtained + int got_output; // signal an output frame is ready to request_frame() + void (*lowpass_line)(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, + const uint8_t *srcp_above, const uint8_t *srcp_below); +} InterlaceContext; + +void ff_interlace_init_x86(InterlaceContext *interlace); + +#endif /* AVFILTER_INTERLACE_H */ diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 6a752dc..202c2c0 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -29,7 +29,6 @@ #include "thread.h" #include "version.h" -#if !FF_API_AVFILTERPAD_PUBLIC /** * A filter pad used for either input or output. */ @@ -126,7 +125,6 @@ struct AVFilterPad { */ int needs_writable; }; -#endif struct AVFilterGraphInternal { void *thread; @@ -137,15 +135,10 @@ struct AVFilterInternal { avfilter_execute_func *execute; }; -#if FF_API_AVFILTERBUFFER -/** default handler for freeing audio/video buffer when there are no references left */ -void ff_avfilter_default_free_buffer(AVFilterBuffer *buf); -#endif - /** Tell is a format is contained in the provided list terminated by -1. */ int ff_fmt_is_in(int fmt, const int *fmts); -#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func) +#define FF_DPRINTF_START(ctx, func) av_log(NULL, AV_LOG_TRACE, "%-16s: ", #func) void ff_dlog_link(void *ctx, AVFilterLink *link, int end); @@ -172,11 +165,6 @@ static inline void ff_insert_inpad(AVFilterContext *f, unsigned index, { ff_insert_pad(index, &f->nb_inputs, offsetof(AVFilterLink, dstpad), &f->input_pads, &f->inputs, p); -#if FF_API_FOO_COUNT -FF_DISABLE_DEPRECATION_WARNINGS - f->input_count = f->nb_inputs; -FF_ENABLE_DEPRECATION_WARNINGS -#endif } /** Insert a new output pad for the filter. */ @@ -185,11 +173,6 @@ static inline void ff_insert_outpad(AVFilterContext *f, unsigned index, { ff_insert_pad(index, &f->nb_outputs, offsetof(AVFilterLink, srcpad), &f->output_pads, &f->outputs, p); -#if FF_API_FOO_COUNT -FF_DISABLE_DEPRECATION_WARNINGS - f->output_count = f->nb_outputs; -FF_ENABLE_DEPRECATION_WARNINGS -#endif } /** diff --git a/libavfilter/libavfilter.v b/libavfilter/libavfilter.v index 83e8887..6518e5f 100644 --- a/libavfilter/libavfilter.v +++ b/libavfilter/libavfilter.v @@ -1,4 +1,7 @@ -LIBAVFILTER_$MAJOR { - global: avfilter_*; av_*; - local: *; +LIBAVFILTER_MAJOR { + global: + avfilter_*; + av_*; + local: + *; }; diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index dd3b174..2ebcc97 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -45,7 +44,7 @@ typedef struct ThreadContext { pthread_t *workers; avfilter_action_func *func; - /* per-execute perameters */ + /* per-execute parameters */ AVFilterContext *ctx; void *arg; int *rets; diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index fa7a0be..1c262b7 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -41,10 +41,11 @@ static const char *const var_names[] = { "E", ///< Euler number + "FRAME_RATE", ///< defined only for constant frame-rate video "INTERLACED", ///< tell if the current frame is interlaced "N", ///< frame / sample number (starting at zero) "PHI", ///< golden ratio - "PI", ///< greek pi + "PI", ///< Greek pi "PREV_INPTS", ///< previous input PTS "PREV_OUTPTS", ///< previous output PTS "PTS", ///< original pts in the file of the frame @@ -59,6 +60,7 @@ static const char *const var_names[] = { enum var_name { VAR_E, + VAR_FRAME_RATE, VAR_INTERLACED, VAR_N, VAR_PHI, @@ -115,6 +117,13 @@ static int config_input(AVFilterLink *inlink) setpts->var_values[VAR_SR] = inlink->sample_rate; } + setpts->var_values[VAR_FRAME_RATE] = inlink->frame_rate.num && + inlink->frame_rate.den ? + av_q2d(inlink->frame_rate) : NAN; + + // Indicate the output can be variable framerate. + inlink->frame_rate = (AVRational){1, 0}; + av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f\n", setpts->var_values[VAR_TB]); return 0; } @@ -143,7 +152,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) d = av_expr_eval(setpts->expr, setpts->var_values, NULL); frame->pts = D2TS(d); - av_dlog(inlink->dst, + av_log(inlink->dst, AV_LOG_TRACE, "n:%"PRId64" interlaced:%d pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", (int64_t)setpts->var_values[VAR_N], (int)setpts->var_values[VAR_INTERLACED], diff --git a/libavfilter/tests/.gitignore b/libavfilter/tests/.gitignore new file mode 100644 index 0000000..a55b386 --- /dev/null +++ b/libavfilter/tests/.gitignore @@ -0,0 +1 @@ +/filtfmts diff --git a/libavfilter/filtfmts.c b/libavfilter/tests/filtfmts.c similarity index 91% rename from libavfilter/filtfmts.c rename to libavfilter/tests/filtfmts.c index 40649c7..cc04654 100644 --- a/libavfilter/filtfmts.c +++ b/libavfilter/tests/filtfmts.c @@ -33,7 +33,7 @@ int main(int argc, char **argv) AVFilterGraph *graph_ctx; const char *filter_name; const char *filter_args = NULL; - int i, j; + int i, j, ret = 0; av_log_set_level(AV_LOG_DEBUG); @@ -74,11 +74,21 @@ int main(int argc, char **argv) /* create a link for each of the input pads */ for (i = 0; i < filter_ctx->nb_inputs; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); + if (!link) { + fprintf(stderr, "Unable to allocate memory for filter input link\n"); + ret = 1; + goto fail; + } link->type = avfilter_pad_get_type(filter_ctx->filter->inputs, i); filter_ctx->inputs[i] = link; } for (i = 0; i < filter_ctx->nb_outputs; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); + if (!link) { + fprintf(stderr, "Unable to allocate memory for filter output link\n"); + ret = 1; + goto fail; + } link->type = avfilter_pad_get_type(filter_ctx->filter->outputs, i); filter_ctx->outputs[i] = link; } @@ -106,8 +116,9 @@ int main(int argc, char **argv) av_get_pix_fmt_name(fmts->formats[j])); } +fail: avfilter_free(filter_ctx); avfilter_graph_free(&graph_ctx); fflush(stdout); - return 0; + return ret; } diff --git a/libavfilter/thread.h b/libavfilter/thread.h index 1cfea3e..42b7caf 100644 --- a/libavfilter/thread.h +++ b/libavfilter/thread.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or diff --git a/libavfilter/version.h b/libavfilter/version.h index 70b08e5..febfc8f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,8 @@ #include "libavutil/version.h" -#define LIBAVFILTER_VERSION_MAJOR 5 -#define LIBAVFILTER_VERSION_MINOR 0 +#define LIBAVFILTER_VERSION_MAJOR 6 +#define LIBAVFILTER_VERSION_MINOR 7 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ @@ -41,35 +41,28 @@ LIBAVFILTER_VERSION_MICRO) #define LIBAVFILTER_BUILD LIBAVFILTER_VERSION_INT +#define LIBAVFILTER_IDENT "Lavfi" AV_STRINGIFY(LIBAVFILTER_VERSION) + /** * FF_API_* defines may be placed below to indicate public API that will be * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AVFILTERPAD_PUBLIC -#define FF_API_AVFILTERPAD_PUBLIC (LIBAVFILTER_VERSION_MAJOR < 6) -#endif -#ifndef FF_API_FOO_COUNT -#define FF_API_FOO_COUNT (LIBAVFILTER_VERSION_MAJOR < 6) -#endif -#ifndef FF_API_AVFILTERBUFFER -#define FF_API_AVFILTERBUFFER (LIBAVFILTER_VERSION_MAJOR < 6) -#endif #ifndef FF_API_OLD_FILTER_OPTS -#define FF_API_OLD_FILTER_OPTS (LIBAVFILTER_VERSION_MAJOR < 6) +#define FF_API_OLD_FILTER_OPTS (LIBAVFILTER_VERSION_MAJOR < 7) #endif #ifndef FF_API_AVFILTER_OPEN -#define FF_API_AVFILTER_OPEN (LIBAVFILTER_VERSION_MAJOR < 6) +#define FF_API_AVFILTER_OPEN (LIBAVFILTER_VERSION_MAJOR < 7) #endif #ifndef FF_API_AVFILTER_INIT_FILTER -#define FF_API_AVFILTER_INIT_FILTER (LIBAVFILTER_VERSION_MAJOR < 6) +#define FF_API_AVFILTER_INIT_FILTER (LIBAVFILTER_VERSION_MAJOR < 7) #endif #ifndef FF_API_OLD_FILTER_REGISTER -#define FF_API_OLD_FILTER_REGISTER (LIBAVFILTER_VERSION_MAJOR < 6) +#define FF_API_OLD_FILTER_REGISTER (LIBAVFILTER_VERSION_MAJOR < 7) #endif #ifndef FF_API_NOCONST_GET_NAME -#define FF_API_NOCONST_GET_NAME (LIBAVFILTER_VERSION_MAJOR < 6) +#define FF_API_NOCONST_GET_NAME (LIBAVFILTER_VERSION_MAJOR < 7) #endif #endif /* AVFILTER_VERSION_H */ diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 9e820d7..4122d52 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -265,7 +265,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) s->x &= ~((1 << s->hsub) - 1); s->y &= ~((1 << s->vsub) - 1); - av_dlog(ctx, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n", + av_log(ctx, AV_LOG_TRACE, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n", (int)s->var_values[VAR_N], s->var_values[VAR_T], s->x, s->y, s->x+s->w, s->y+s->h); diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c new file mode 100644 index 0000000..b26a900 --- /dev/null +++ b/libavfilter/vf_deinterlace_qsv.c @@ -0,0 +1,580 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * deinterlace video filter - QSV + */ + +#include + +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +enum { + QSVDEINT_MORE_OUTPUT = 1, + QSVDEINT_MORE_INPUT, +}; + +typedef struct QSVFrame { + AVFrame *frame; + mfxFrameSurface1 surface; + int used; + + struct QSVFrame *next; +} QSVFrame; + +typedef struct QSVDeintContext { + const AVClass *class; + + AVBufferRef *hw_frames_ctx; + /* a clone of the main session, used internally for deinterlacing */ + mfxSession session; + + mfxMemId *mem_ids; + int nb_mem_ids; + + mfxFrameSurface1 **surface_ptrs; + int nb_surface_ptrs; + + mfxExtOpaqueSurfaceAlloc opaque_alloc; + mfxExtBuffer *ext_buffers[1]; + + QSVFrame *work_frames; + + int64_t last_pts; + + int got_output_frame; + int eof; +} QSVDeintContext; + +static void qsvdeint_uninit(AVFilterContext *ctx) +{ + QSVDeintContext *s = ctx->priv; + QSVFrame *cur; + + if (s->session) { + MFXClose(s->session); + s->session = NULL; + } + av_buffer_unref(&s->hw_frames_ctx); + + cur = s->work_frames; + while (cur) { + s->work_frames = cur->next; + av_frame_free(&cur->frame); + av_freep(&cur); + cur = s->work_frames; + } + + av_freep(&s->mem_ids); + s->nb_mem_ids = 0; + + av_freep(&s->surface_ptrs); + s->nb_surface_ptrs = 0; +} + +static int qsvdeint_query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_QSV, AV_PIX_FMT_NONE, + }; + AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + + ff_set_common_formats(ctx, pix_fmts); + + return 0; +} + +static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + AVFilterContext *ctx = pthis; + QSVDeintContext *s = ctx->priv; + + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || + !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || + !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) + return MFX_ERR_UNSUPPORTED; + + resp->mids = s->mem_ids; + resp->NumFrameActual = s->nb_mem_ids; + + return MFX_ERR_NONE; +} + +static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + return MFX_ERR_NONE; +} + +static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +static const mfxHandleType handle_types[] = { + MFX_HANDLE_VA_DISPLAY, + MFX_HANDLE_D3D9_DEVICE_MANAGER, + MFX_HANDLE_D3D11_DEVICE, +}; + +static int init_out_session(AVFilterContext *ctx) +{ + + QSVDeintContext *s = ctx->priv; + AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)s->hw_frames_ctx->data; + AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx; + AVQSVDeviceContext *device_hwctx = hw_frames_ctx->device_ctx->hwctx; + + int opaque = !!(hw_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); + + mfxHDL handle = NULL; + mfxHandleType handle_type; + mfxVersion ver; + mfxIMPL impl; + mfxVideoParam par; + mfxStatus err; + int i; + + /* extract the properties of the "master" session given to us */ + err = MFXQueryIMPL(device_hwctx->session, &impl); + if (err == MFX_ERR_NONE) + err = MFXQueryVersion(device_hwctx->session, &ver); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { + err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); + if (err == MFX_ERR_NONE) { + handle_type = handle_types[i]; + break; + } + } + + /* create a "slave" session with those same properties, to be used for + * actual deinterlacing */ + err = MFXInit(impl, &ver, &s->session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error initializing a session for deinterlacing\n"); + return AVERROR_UNKNOWN; + } + + if (handle) { + err = MFXVideoCORE_SetHandle(s->session, handle_type, handle); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + memset(&par, 0, sizeof(par)); + + if (opaque) { + s->surface_ptrs = av_mallocz_array(hw_frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs)); + if (!s->surface_ptrs) + return AVERROR(ENOMEM); + for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++) + s->surface_ptrs[i] = hw_frames_hwctx->surfaces + i; + s->nb_surface_ptrs = hw_frames_hwctx->nb_surfaces; + + s->opaque_alloc.In.Surfaces = s->surface_ptrs; + s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs; + s->opaque_alloc.In.Type = hw_frames_hwctx->frame_type; + + s->opaque_alloc.Out = s->opaque_alloc.In; + + s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; + s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); + + s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; + + par.ExtParam = s->ext_buffers; + par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); + + par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + } else { + mfxFrameAllocator frame_allocator = { + .pthis = ctx, + .Alloc = frame_alloc, + .Lock = frame_lock, + .Unlock = frame_unlock, + .GetHDL = frame_get_hdl, + .Free = frame_free, + }; + + s->mem_ids = av_mallocz_array(hw_frames_hwctx->nb_surfaces, + sizeof(*s->mem_ids)); + if (!s->mem_ids) + return AVERROR(ENOMEM); + for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++) + s->mem_ids[i] = hw_frames_hwctx->surfaces[i].Data.MemId; + s->nb_mem_ids = hw_frames_hwctx->nb_surfaces; + + err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + + par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; + } + + par.AsyncDepth = 1; // TODO async + + par.vpp.In = hw_frames_hwctx->surfaces[0].Info; + + par.vpp.In.CropW = ctx->inputs[0]->w; + par.vpp.In.CropH = ctx->inputs[0]->h; + + if (ctx->inputs[0]->frame_rate.num) { + par.vpp.In.FrameRateExtN = ctx->inputs[0]->frame_rate.num; + par.vpp.In.FrameRateExtD = ctx->inputs[0]->frame_rate.den; + } else { + par.vpp.In.FrameRateExtN = ctx->inputs[0]->time_base.num; + par.vpp.In.FrameRateExtD = ctx->inputs[0]->time_base.den; + } + + par.vpp.Out = par.vpp.In; + + if (ctx->outputs[0]->frame_rate.num) { + par.vpp.Out.FrameRateExtN = ctx->outputs[0]->frame_rate.num; + par.vpp.Out.FrameRateExtD = ctx->outputs[0]->frame_rate.den; + } else { + par.vpp.Out.FrameRateExtN = ctx->outputs[0]->time_base.num; + par.vpp.Out.FrameRateExtD = ctx->outputs[0]->time_base.den; + } + + err = MFXVideoVPP_Init(s->session, &par); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error opening the VPP for deinterlacing: %d\n", err); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int qsvdeint_config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + QSVDeintContext *s = ctx->priv; + int ret; + + qsvdeint_uninit(ctx); + + s->last_pts = AV_NOPTS_VALUE; + outlink->frame_rate = av_mul_q(inlink->frame_rate, + (AVRational){ 2, 1 }); + outlink->time_base = av_mul_q(inlink->time_base, + (AVRational){ 1, 2 }); + + /* check that we have a hw context */ + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } + + s->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + if (!s->hw_frames_ctx) + return AVERROR(ENOMEM); + + av_buffer_unref(&outlink->hw_frames_ctx); + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + if (!outlink->hw_frames_ctx) { + qsvdeint_uninit(ctx); + return AVERROR(ENOMEM); + } + + ret = init_out_session(ctx); + if (ret < 0) + return ret; + + + return 0; +} + +static void clear_unused_frames(QSVDeintContext *s) +{ + QSVFrame *cur = s->work_frames; + while (cur) { + if (!cur->surface.Data.Locked) { + av_frame_free(&cur->frame); + cur->used = 0; + } + cur = cur->next; + } +} + +static int get_free_frame(QSVDeintContext *s, QSVFrame **f) +{ + QSVFrame *frame, **last; + + clear_unused_frames(s); + + frame = s->work_frames; + last = &s->work_frames; + while (frame) { + if (!frame->used) { + *f = frame; + return 0; + } + + last = &frame->next; + frame = frame->next; + } + + frame = av_mallocz(sizeof(*frame)); + if (!frame) + return AVERROR(ENOMEM); + *last = frame; + *f = frame; + + return 0; +} + +static int submit_frame(AVFilterContext *ctx, AVFrame *frame, + mfxFrameSurface1 **surface) +{ + QSVDeintContext *s = ctx->priv; + QSVFrame *qf; + int ret; + + ret = get_free_frame(s, &qf); + if (ret < 0) + return ret; + + qf->frame = frame; + + qf->surface = *(mfxFrameSurface1*)qf->frame->data[3]; + + qf->surface.Data.Locked = 0; + qf->surface.Info.CropW = qf->frame->width; + qf->surface.Info.CropH = qf->frame->height; + + qf->surface.Info.PicStruct = !qf->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : + (qf->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + MFX_PICSTRUCT_FIELD_BFF); + if (qf->frame->repeat_pict == 1) + qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; + else if (qf->frame->repeat_pict == 2) + qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING; + else if (qf->frame->repeat_pict == 4) + qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; + + if (ctx->inputs[0]->frame_rate.num) { + qf->surface.Info.FrameRateExtN = ctx->inputs[0]->frame_rate.num; + qf->surface.Info.FrameRateExtD = ctx->inputs[0]->frame_rate.den; + } else { + qf->surface.Info.FrameRateExtN = ctx->inputs[0]->time_base.num; + qf->surface.Info.FrameRateExtD = ctx->inputs[0]->time_base.den; + } + + qf->surface.Data.TimeStamp = av_rescale_q(qf->frame->pts, + ctx->inputs[0]->time_base, + (AVRational){1, 90000}); + + *surface = &qf->surface; + qf->used = 1; + + return 0; +} + +static int process_frame(AVFilterContext *ctx, const AVFrame *in, + mfxFrameSurface1 *surf_in) +{ + QSVDeintContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + + AVFrame *out; + mfxFrameSurface1 *surf_out; + mfxSyncPoint sync = NULL; + mfxStatus err; + int ret, again = 0; + + out = av_frame_alloc(); + if (!out) + return AVERROR(ENOMEM); + + ret = av_hwframe_get_buffer(s->hw_frames_ctx, out, 0); + if (ret < 0) + goto fail; + + surf_out = (mfxFrameSurface1*)out->data[3]; + surf_out->Info.CropW = outlink->w; + surf_out->Info.CropH = outlink->h; + surf_out->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + + do { + err = MFXVideoVPP_RunFrameVPPAsync(s->session, surf_in, surf_out, + NULL, &sync); + if (err == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + } while (err == MFX_WRN_DEVICE_BUSY); + + if (err == MFX_ERR_MORE_DATA) { + av_frame_free(&out); + return QSVDEINT_MORE_INPUT; + } + + if ((err < 0 && err != MFX_ERR_MORE_SURFACE) || !sync) { + av_log(ctx, AV_LOG_ERROR, "Error during deinterlacing: %d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + if (err == MFX_ERR_MORE_SURFACE) + again = 1; + + do { + err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); + } while (err == MFX_WRN_IN_EXECUTION); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + + out->width = outlink->w; + out->height = outlink->h; + out->interlaced_frame = 0; + + out->pts = av_rescale_q(out->pts, inlink->time_base, outlink->time_base); + if (out->pts == s->last_pts) + out->pts++; + s->last_pts = out->pts; + + ret = ff_filter_frame(outlink, out); + if (ret < 0) + return ret; + + return again ? QSVDEINT_MORE_OUTPUT : 0; +fail: + av_frame_free(&out); + return ret; +} + +static int qsvdeint_filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + + mfxFrameSurface1 *surf_in; + int ret; + + ret = submit_frame(ctx, in, &surf_in); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + + do { + ret = process_frame(ctx, in, surf_in); + if (ret < 0) + return ret; + } while (ret == QSVDEINT_MORE_OUTPUT); + + return 0; +} + +static int qsvdeint_request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + QSVDeintContext *s = ctx->priv; + int ret = 0; + + s->got_output_frame = 0; + while (ret >= 0 && !s->got_output_frame) + ret = ff_request_frame(ctx->inputs[0]); + + return ret; +} + +#define OFFSET(x) offsetof(QSVDeintContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { NULL }, +}; + +static const AVClass qsvdeint_class = { + .class_name = "deinterlace_qsv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad qsvdeint_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = qsvdeint_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad qsvdeint_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = qsvdeint_config_props, + .request_frame = qsvdeint_request_frame, + }, + { NULL } +}; + +AVFilter ff_vf_deinterlace_qsv = { + .name = "deinterlace_qsv", + .description = NULL_IF_CONFIG_SMALL("QuickSync video deinterlacing"), + + .uninit = qsvdeint_uninit, + .query_formats = qsvdeint_query_formats, + + .priv_size = sizeof(QSVDeintContext), + .priv_class = &qsvdeint_class, + + .inputs = qsvdeint_inputs, + .outputs = qsvdeint_outputs, +}; diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index d954fdf..e36cfa2 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -47,6 +47,7 @@ #include "libavutil/random_seed.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" +#include "libavutil/time_internal.h" #include "libavutil/tree.h" #include "libavutil/lfg.h" #include "avfilter.h" @@ -151,6 +152,9 @@ typedef struct DrawTextContext { char *d_expr; AVExpr *d_pexpr; int draw; ///< set to zero to prevent drawing + char *a_expr; + AVExpr *a_pexpr; + int alpha; AVLFG prng; ///< random } DrawTextContext; @@ -168,13 +172,14 @@ static const AVOption drawtext_options[]= { { "boxcolor", NULL, OFFSET(boxcolor_string), AV_OPT_TYPE_STRING, { .str = "white" }, .flags = FLAGS }, { "shadowcolor", NULL, OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, { .str = "black" }, .flags = FLAGS }, { "box", NULL, OFFSET(draw_box), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, - { "fontsize", NULL, OFFSET(fontsize), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, 72, FLAGS }, + { "fontsize", NULL, OFFSET(fontsize), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, 1024, FLAGS }, { "x", NULL, OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, { "y", NULL, OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, { "shadowx", NULL, OFFSET(shadowx), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, { "shadowy", NULL, OFFSET(shadowy), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, { "tabsize", NULL, OFFSET(tabsize), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, INT_MAX, FLAGS }, { "draw", "if false do not draw", OFFSET(d_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, + { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, { "fix_bounds", "if true, check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS }, @@ -462,10 +467,6 @@ static av_cold int init(AVFilterContext *ctx) } s->tabsize *= glyph->advance; -#if !HAVE_LOCALTIME_R - av_log(ctx, AV_LOG_WARNING, "strftime() expansion unavailable!\n"); -#endif - return 0; } @@ -520,30 +521,15 @@ static inline int is_newline(uint32_t c) return c == '\n' || c == '\r' || c == '\f' || c == '\v'; } -static int dtext_prepare_text(AVFilterContext *ctx) +static int expand_strftime(DrawTextContext *s) { - DrawTextContext *s = ctx->priv; - uint32_t code = 0, prev_code = 0; - int x = 0, y = 0, i = 0, ret; - int text_height, baseline; - char *text = s->text; - uint8_t *p; - int str_w = 0, len; - int y_min = 32000, y_max = -32000; - FT_Vector delta; - Glyph *glyph = NULL, *prev_glyph = NULL; - Glyph dummy = { 0 }; - int width = ctx->inputs[0]->w; - int height = ctx->inputs[0]->h; - -#if HAVE_LOCALTIME_R - time_t now = time(0); struct tm ltime; + time_t now = time(0); uint8_t *buf = s->expanded_text; int buf_size = s->expanded_text_size; if (!buf) - buf_size = 2*strlen(s->text)+1; + buf_size = 2 * strlen(s->text) + 1; localtime_r(&now, <ime); @@ -556,9 +542,33 @@ static int dtext_prepare_text(AVFilterContext *ctx) if (!buf) return AVERROR(ENOMEM); - text = s->expanded_text = buf; + s->expanded_text = buf; s->expanded_text_size = buf_size; -#endif + + return 0; +} + +static int dtext_prepare_text(AVFilterContext *ctx) +{ + DrawTextContext *s = ctx->priv; + uint32_t code = 0, prev_code = 0; + int x = 0, y = 0, i = 0, ret; + int text_height, baseline; + char *text; + uint8_t *p; + int str_w = 0, len; + int y_min = 32000, y_max = -32000; + FT_Vector delta; + Glyph *glyph = NULL, *prev_glyph = NULL; + Glyph dummy = { 0 }; + int width = ctx->inputs[0]->w; + int height = ctx->inputs[0]->h; + + ret = expand_strftime(s); + if (ret < 0) + return ret; + + text = s->expanded_text ? s->expanded_text : s->text; if ((len = strlen(text)) > s->nb_positions) { FT_Vector *p = av_realloc(s->positions, @@ -680,6 +690,8 @@ static int config_input(AVFilterLink *inlink) (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || (ret = av_expr_parse(&s->d_pexpr, s->d_expr, var_names, + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || + (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) return AVERROR(EINVAL); @@ -715,7 +727,7 @@ static int config_input(AVFilterLink *inlink) #define SET_PIXEL_YUV(frame, yuva_color, val, x, y, hsub, vsub) { \ luma_pos = ((x) ) + ((y) ) * frame->linesize[0]; \ - alpha = yuva_color[3] * (val) * 129; \ + alpha = yuva_color[3] * alpha_mul * (val) * 129 / 255; \ frame->data[0][luma_pos] = (alpha * yuva_color[0] + (255*255*129 - alpha) * frame->data[0][luma_pos] ) >> 23; \ if (((x) & ((1<<(hsub)) - 1)) == 0 && ((y) & ((1<<(vsub)) - 1)) == 0) {\ chroma_pos1 = ((x) >> (hsub)) + ((y) >> (vsub)) * frame->linesize[1]; \ @@ -727,7 +739,8 @@ static int config_input(AVFilterLink *inlink) static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, - const uint8_t yuva_color[4], int hsub, int vsub) + const uint8_t yuva_color[4], int hsub, int vsub, + int alpha_mul) { int r, c, alpha; unsigned int luma_pos, chroma_pos1, chroma_pos2; @@ -749,7 +762,7 @@ static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int #define SET_PIXEL_RGB(frame, rgba_color, val, x, y, pixel_step, r_off, g_off, b_off, a_off) { \ p = frame->data[0] + (x) * pixel_step + ((y) * frame->linesize[0]); \ - alpha = rgba_color[3] * (val) * 129; \ + alpha = rgba_color[3] * alpha_mul * (val) * 129 / 255; \ *(p+r_off) = (alpha * rgba_color[0] + (255*255*129 - alpha) * *(p+r_off)) >> 23; \ *(p+g_off) = (alpha * rgba_color[1] + (255*255*129 - alpha) * *(p+g_off)) >> 23; \ *(p+b_off) = (alpha * rgba_color[2] + (255*255*129 - alpha) * *(p+b_off)) >> 23; \ @@ -758,7 +771,8 @@ static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int static inline int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int pixel_step, - const uint8_t rgba_color[4], const uint8_t rgba_map[4]) + const uint8_t rgba_color[4], const uint8_t rgba_map[4], + int alpha_mul) { int r, c, alpha; uint8_t *p; @@ -782,11 +796,12 @@ static inline int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap, static inline void drawbox(AVFrame *frame, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uint8_t *line[4], int pixel_step[4], uint8_t color[4], - int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4]) + int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4], + int alpha_mul) { int i, j, alpha; - if (color[3] != 0xFF) { + if (color[3] != 0xFF || alpha_mul != 0xFF) { if (is_rgba_packed) { uint8_t *p; for (j = 0; j < height; j++) @@ -807,9 +822,11 @@ static inline void drawbox(AVFrame *frame, unsigned int x, unsigned int y, } static int draw_glyphs(DrawTextContext *s, AVFrame *frame, - int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y) + int width, int height, + const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], + int x, int y) { - char *text = HAVE_LOCALTIME_R ? s->expanded_text : s->text; + char *text = s->expanded_text; uint32_t code = 0; int i; uint8_t *p; @@ -833,11 +850,11 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, if (s->is_packed_rgb) { draw_glyph_rgb(frame, &glyph->bitmap, s->positions[i].x+x, s->positions[i].y+y, width, height, - s->pixel_step[0], rgbcolor, s->rgba_map); + s->pixel_step[0], rgbcolor, s->rgba_map, s->alpha); } else { draw_glyph_yuv(frame, &glyph->bitmap, s->positions[i].x+x, s->positions[i].y+y, width, height, - yuvcolor, s->hsub, s->vsub); + yuvcolor, s->hsub, s->vsub, s->alpha); } } @@ -855,7 +872,7 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, drawbox(frame, s->x, s->y, s->w, s->h, s->box_line, s->pixel_step, s->boxcolor, s->hsub, s->vsub, s->is_packed_rgb, - s->rgba_map); + s->rgba_map, s->alpha); if (s->shadowx || s->shadowy) { if ((ret = draw_glyphs(s, frame, width, height, @@ -891,6 +908,21 @@ static inline int normalize_double(int *n, double d) return ret; } +static void update_alpha(DrawTextContext *s) +{ + double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng); + + if (isnan(alpha)) + return; + + if (alpha >= 1.0) + s->alpha = 255; + else if (alpha <= 0) + s->alpha = 0; + else + s->alpha = 256 * alpha; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -914,6 +946,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->draw = av_expr_eval(s->d_pexpr, s->var_values, &s->prng); + update_alpha(s); + normalize_double(&s->x, s->var_values[VAR_X]); normalize_double(&s->y, s->var_values[VAR_Y]); @@ -929,7 +963,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->x &= ~((1 << s->hsub) - 1); s->y &= ~((1 << s->vsub) - 1); - av_dlog(ctx, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n", + av_log(ctx, AV_LOG_TRACE, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n", (int)s->var_values[VAR_N], s->var_values[VAR_T], s->x, s->y, s->x+s->w, s->y+s->h); diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index eac0c2c..fd8c6ef 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -123,7 +123,8 @@ static int filter_slice_chroma(AVFilterContext *ctx, void *arg, int jobnr, AVFrame *frame = arg; int slice_h = FFALIGN(frame->height / nb_jobs, 1 << s->vsub); int slice_start = jobnr * slice_h; - int slice_end = (jobnr == nb_jobs - 1) ? frame->height : (jobnr + 1) * slice_h; + int slice_end = (jobnr == nb_jobs - 1) ? frame->height : + FFMIN((jobnr + 1) * slice_h, frame->height); int i, j, plane; for (plane = 1; plane < 3; plane++) { diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index c05d081..dd4f8cc 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -102,7 +102,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) return ff_filter_frame(outlink, frame); } - av_dlog(ctx, + av_log(ctx, AV_LOG_TRACE, "picture will move %s one line\n", s->dst_tff ? "up" : "down"); h = frame->height; diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index ea22d37..e5562c8 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -116,9 +116,10 @@ static int config_props(AVFilterLink* link) { FPSContext *s = link->src->priv; - link->time_base = (AVRational){ s->framerate.den, s->framerate.num }; - link->w = link->src->inputs[0]->w; - link->h = link->src->inputs[0]->h; + link->time_base = (AVRational){ s->framerate.den, s->framerate.num }; + link->frame_rate = s->framerate; + link->w = link->src->inputs[0]->w; + link->h = link->src->inputs[0]->h; return 0; } diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c index f5c761a..fd0c189 100644 --- a/libavfilter/vf_framepack.c +++ b/libavfilter/vf_framepack.c @@ -25,6 +25,7 @@ #include +#include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -76,12 +77,13 @@ static av_cold void framepack_uninit(AVFilterContext *ctx) static int config_output(AVFilterLink *outlink) { - AVFilterContext *ctx = outlink->src; - FramepackContext *s = outlink->src->priv; + AVFilterContext *ctx = outlink->src; + FramepackContext *s = outlink->src->priv; - int width = ctx->inputs[LEFT]->w; - int height = ctx->inputs[LEFT]->h; - AVRational time_base = ctx->inputs[LEFT]->time_base; + int width = ctx->inputs[LEFT]->w; + int height = ctx->inputs[LEFT]->h; + AVRational time_base = ctx->inputs[LEFT]->time_base; + AVRational frame_rate = ctx->inputs[LEFT]->frame_rate; // check size and fps match on the other input if (width != ctx->inputs[RIGHT]->w || @@ -93,11 +95,18 @@ static int config_output(AVFilterLink *outlink) return AVERROR_INVALIDDATA; } else if (av_cmp_q(time_base, ctx->inputs[RIGHT]->time_base) != 0) { av_log(ctx, AV_LOG_ERROR, - "Left and right framerates differ (%d/%d vs %d/%d).\n", + "Left and right time bases differ (%d/%d vs %d/%d).\n", time_base.num, time_base.den, ctx->inputs[RIGHT]->time_base.num, ctx->inputs[RIGHT]->time_base.den); return AVERROR_INVALIDDATA; + } else if (av_cmp_q(frame_rate, ctx->inputs[RIGHT]->frame_rate) != 0) { + av_log(ctx, AV_LOG_ERROR, + "Left and right framerates differ (%d/%d vs %d/%d).\n", + frame_rate.num, frame_rate.den, + ctx->inputs[RIGHT]->frame_rate.num, + ctx->inputs[RIGHT]->frame_rate.den); + return AVERROR_INVALIDDATA; } s->pix_desc = av_pix_fmt_desc_get(outlink->format); @@ -107,7 +116,9 @@ static int config_output(AVFilterLink *outlink) // modify output properties as needed switch (s->format) { case AV_STEREO3D_FRAMESEQUENCE: - time_base.den *= 2; + time_base.den *= 2; + frame_rate.num *= 2; + s->double_pts = AV_NOPTS_VALUE; break; case AV_STEREO3D_COLUMNS: @@ -123,99 +134,135 @@ static int config_output(AVFilterLink *outlink) return AVERROR_INVALIDDATA; } - outlink->w = width; - outlink->h = height; - outlink->time_base = time_base; + outlink->w = width; + outlink->h = height; + outlink->time_base = time_base; + outlink->frame_rate = frame_rate; return 0; } -static void horizontal_frame_pack(FramepackContext *s, - AVFrame *dst, +static void horizontal_frame_pack(AVFilterLink *outlink, + AVFrame *out, int interleaved) { - int plane, i; - int length = dst->width / 2; - int lines = dst->height; - - for (plane = 0; plane < s->pix_desc->nb_components; plane++) { - const uint8_t *leftp = s->input_views[LEFT]->data[plane]; - const uint8_t *rightp = s->input_views[RIGHT]->data[plane]; - uint8_t *dstp = dst->data[plane]; - - if (plane == 1 || plane == 2) { - length = -(-(dst->width / 2) >> s->pix_desc->log2_chroma_w); - lines = -(-(dst->height) >> s->pix_desc->log2_chroma_h); - } - - if (interleaved) { + AVFilterContext *ctx = outlink->src; + FramepackContext *s = ctx->priv; + int i, plane; + + if (interleaved) { + const uint8_t *leftp = s->input_views[LEFT]->data[0]; + const uint8_t *rightp = s->input_views[RIGHT]->data[0]; + uint8_t *dstp = out->data[0]; + int length = out->width / 2; + int lines = out->height; + + for (plane = 0; plane < s->pix_desc->nb_components; plane++) { + if (plane == 1 || plane == 2) { + length = AV_CEIL_RSHIFT(out->width / 2, s->pix_desc->log2_chroma_w); + lines = AV_CEIL_RSHIFT(out->height, s->pix_desc->log2_chroma_h); + } for (i = 0; i < lines; i++) { int j; - int k = 0; - + leftp = s->input_views[LEFT]->data[plane] + + s->input_views[LEFT]->linesize[plane] * i; + rightp = s->input_views[RIGHT]->data[plane] + + s->input_views[RIGHT]->linesize[plane] * i; + dstp = out->data[plane] + out->linesize[plane] * i; for (j = 0; j < length; j++) { - dstp[k++] = leftp[j]; - dstp[k++] = rightp[j]; + // interpolate chroma as necessary + if ((s->pix_desc->log2_chroma_w || + s->pix_desc->log2_chroma_h) && + (plane == 1 || plane == 2)) { + *dstp++ = (*leftp + *rightp) / 2; + *dstp++ = (*leftp + *rightp) / 2; + } else { + *dstp++ = *leftp; + *dstp++ = *rightp; + } + leftp += 1; + rightp += 1; } - - dstp += dst->linesize[plane]; - leftp += s->input_views[LEFT]->linesize[plane]; - rightp += s->input_views[RIGHT]->linesize[plane]; } - } else { - av_image_copy_plane(dst->data[plane], dst->linesize[plane], - leftp, s->input_views[LEFT]->linesize[plane], - length, lines); - av_image_copy_plane(dst->data[plane] + length, dst->linesize[plane], - rightp, s->input_views[RIGHT]->linesize[plane], - length, lines); + } + } else { + for (i = 0; i < 2; i++) { + const uint8_t *src[4]; + uint8_t *dst[4]; + int sub_w = s->input_views[i]->width >> s->pix_desc->log2_chroma_w; + + src[0] = s->input_views[i]->data[0]; + src[1] = s->input_views[i]->data[1]; + src[2] = s->input_views[i]->data[2]; + + dst[0] = out->data[0] + i * s->input_views[i]->width; + dst[1] = out->data[1] + i * sub_w; + dst[2] = out->data[2] + i * sub_w; + + av_image_copy(dst, out->linesize, src, s->input_views[i]->linesize, + s->input_views[i]->format, + s->input_views[i]->width, + s->input_views[i]->height); } } } -static void vertical_frame_pack(FramepackContext *s, - AVFrame *dst, +static void vertical_frame_pack(AVFilterLink *outlink, + AVFrame *out, int interleaved) { - int plane, offset; - int length = dst->width; - int lines = dst->height / 2; - - for (plane = 0; plane < s->pix_desc->nb_components; plane++) { - if (plane == 1 || plane == 2) { - length = -(-(dst->width) >> s->pix_desc->log2_chroma_w); - lines = -(-(dst->height / 2) >> s->pix_desc->log2_chroma_h); - } + AVFilterContext *ctx = outlink->src; + FramepackContext *s = ctx->priv; + int i; - offset = interleaved ? dst->linesize[plane] : dst->linesize[plane] * lines; - - av_image_copy_plane(dst->data[plane], - dst->linesize[plane] << interleaved, - s->input_views[LEFT]->data[plane], - s->input_views[LEFT]->linesize[plane], - length, lines); - av_image_copy_plane(dst->data[plane] + offset, - dst->linesize[plane] << interleaved, - s->input_views[RIGHT]->data[plane], - s->input_views[RIGHT]->linesize[plane], - length, lines); + for (i = 0; i < 2; i++) { + const uint8_t *src[4]; + uint8_t *dst[4]; + int linesizes[4]; + int sub_h = s->input_views[i]->height >> s->pix_desc->log2_chroma_h; + + src[0] = s->input_views[i]->data[0]; + src[1] = s->input_views[i]->data[1]; + src[2] = s->input_views[i]->data[2]; + + dst[0] = out->data[0] + i * out->linesize[0] * + (interleaved + s->input_views[i]->height * (1 - interleaved)); + dst[1] = out->data[1] + i * out->linesize[1] * + (interleaved + sub_h * (1 - interleaved)); + dst[2] = out->data[2] + i * out->linesize[2] * + (interleaved + sub_h * (1 - interleaved)); + + linesizes[0] = out->linesize[0] + + interleaved * out->linesize[0]; + linesizes[1] = out->linesize[1] + + interleaved * out->linesize[1]; + linesizes[2] = out->linesize[2] + + interleaved * out->linesize[2]; + + av_image_copy(dst, linesizes, src, s->input_views[i]->linesize, + s->input_views[i]->format, + s->input_views[i]->width, + s->input_views[i]->height); } } -static av_always_inline void spatial_frame_pack(FramepackContext *s, AVFrame *dst) +static av_always_inline void spatial_frame_pack(AVFilterLink *outlink, + AVFrame *dst) { + AVFilterContext *ctx = outlink->src; + FramepackContext *s = ctx->priv; switch (s->format) { case AV_STEREO3D_SIDEBYSIDE: - horizontal_frame_pack(s, dst, 0); + horizontal_frame_pack(outlink, dst, 0); break; case AV_STEREO3D_COLUMNS: - horizontal_frame_pack(s, dst, 1); + horizontal_frame_pack(outlink, dst, 1); break; case AV_STEREO3D_TOPBOTTOM: - vertical_frame_pack(s, dst, 0); + vertical_frame_pack(outlink, dst, 0); break; case AV_STEREO3D_LINES: - vertical_frame_pack(s, dst, 1); + vertical_frame_pack(outlink, dst, 1); break; } } @@ -276,7 +323,7 @@ static int request_frame(AVFilterLink *outlink) if (!dst) return AVERROR(ENOMEM); - spatial_frame_pack(s, dst); + spatial_frame_pack(outlink, dst); // get any property from the original frame ret = av_frame_copy_props(dst, s->input_views[LEFT]); diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c index 0122b8d..f41fbcb 100644 --- a/libavfilter/vf_frei0r.c +++ b/libavfilter/vf_frei0r.c @@ -156,54 +156,6 @@ static int set_params(AVFilterContext *ctx, const char *params) if (ret < 0) return ret; } - - av_log(ctx, AV_LOG_VERBOSE, - "idx:%d name:'%s' type:%s explanation:'%s' ", - i, info.name, - info.type == F0R_PARAM_BOOL ? "bool" : - info.type == F0R_PARAM_DOUBLE ? "double" : - info.type == F0R_PARAM_COLOR ? "color" : - info.type == F0R_PARAM_POSITION ? "position" : - info.type == F0R_PARAM_STRING ? "string" : "unknown", - info.explanation); - -#ifdef DEBUG - av_log(ctx, AV_LOG_DEBUG, "value:"); - switch (info.type) { - void *v; - double d; - char s[128]; - f0r_param_color_t col; - f0r_param_position_t pos; - - case F0R_PARAM_BOOL: - v = &d; - s->get_param_value(s->instance, v, i); - av_log(ctx, AV_LOG_DEBUG, "%s", d >= 0.5 && d <= 1.0 ? "y" : "n"); - break; - case F0R_PARAM_DOUBLE: - v = &d; - s->get_param_value(s->instance, v, i); - av_log(ctx, AV_LOG_DEBUG, "%f", d); - break; - case F0R_PARAM_COLOR: - v = &col; - s->get_param_value(s->instance, v, i); - av_log(ctx, AV_LOG_DEBUG, "%f/%f/%f", col.r, col.g, col.b); - break; - case F0R_PARAM_POSITION: - v = &pos; - s->get_param_value(s->instance, v, i); - av_log(ctx, AV_LOG_DEBUG, "%f/%f", pos.x, pos.y); - break; - default: /* F0R_PARAM_STRING */ - v = s; - s->get_param_value(s->instance, v, i); - av_log(ctx, AV_LOG_DEBUG, "'%s'", s); - break; - } -#endif - av_log(ctx, AV_LOG_VERBOSE, ".\n"); } return 0; @@ -459,6 +411,7 @@ static int source_config_props(AVFilterLink *outlink) outlink->w = s->w; outlink->h = s->h; outlink->time_base = s->time_base; + outlink->frame_rate = av_inv_q(s->time_base); if (s->destruct && s->instance) s->destruct(s->instance); diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index f7c4372..973cd7b 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -26,9 +26,9 @@ * * Apply a boxblur debanding algorithm (based on the gradfun2db * AviSynth filter by prunedtree). - * Foreach pixel, if it's within threshold of the blurred value, make it closer. - * So now we have a smoothed and higher bitdepth version of all the shallow - * gradients, while leaving detailed areas untouched. + * For each pixel, if it is within the threshold of the blurred value, make it + * closer. So now we have a smoothed and higher bitdepth version of all the + * shallow gradients, while leaving detailed areas untouched. * Dither it back to 8bit. */ @@ -172,8 +172,8 @@ static int config_input(AVFilterLink *inlink) if (!s->buf) return AVERROR(ENOMEM); - s->chroma_w = -((-inlink->w) >> hsub); - s->chroma_h = -((-inlink->h) >> vsub); + s->chroma_w = AV_CEIL_RSHIFT(inlink->w, hsub); + s->chroma_h = AV_CEIL_RSHIFT(inlink->h, vsub); s->chroma_r = av_clip(((((s->radius >> hsub) + (s->radius >> vsub)) / 2 ) + 1) & ~1, 4, 32); return 0; diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index be6b761..4d8297d 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -121,19 +121,21 @@ static void denoise_spatial(HQDN3DContext *s, } av_always_inline -static void denoise_depth(HQDN3DContext *s, - uint8_t *src, uint8_t *dst, - uint16_t *line_ant, uint16_t **frame_ant_ptr, - int w, int h, int sstride, int dstride, - int16_t *spatial, int16_t *temporal, int depth) +static int denoise_depth(HQDN3DContext *s, + uint8_t *src, uint8_t *dst, + uint16_t *line_ant, uint16_t **frame_ant_ptr, + int w, int h, int sstride, int dstride, + int16_t *spatial, int16_t *temporal, int depth) { - // FIXME: For 16bit depth, frame_ant could be a pointer to the previous + // FIXME: For 16-bit depth, frame_ant could be a pointer to the previous // filtered frame rather than a separate buffer. long x, y; uint16_t *frame_ant = *frame_ant_ptr; if (!frame_ant) { uint8_t *frame_src = src; *frame_ant_ptr = frame_ant = av_malloc(w*h*sizeof(uint16_t)); + if (!frame_ant) + return AVERROR(ENOMEM); for (y = 0; y < h; y++, src += sstride, frame_ant += w) for (x = 0; x < w; x++) frame_ant[x] = LOAD(x); @@ -148,15 +150,25 @@ static void denoise_depth(HQDN3DContext *s, denoise_temporal(src, dst, frame_ant, w, h, sstride, dstride, temporal, depth); emms_c(); + return 0; } -#define denoise(...) \ - switch (s->depth) {\ - case 8: denoise_depth(__VA_ARGS__, 8); break;\ - case 9: denoise_depth(__VA_ARGS__, 9); break;\ - case 10: denoise_depth(__VA_ARGS__, 10); break;\ - case 16: denoise_depth(__VA_ARGS__, 16); break;\ - } +#define denoise(...) \ + do { \ + int ret = AVERROR_INVALIDDATA; \ + switch (s->depth) { \ + case 8: ret = denoise_depth(__VA_ARGS__, 8); break; \ + case 9: ret = denoise_depth(__VA_ARGS__, 9); break; \ + case 10: ret = denoise_depth(__VA_ARGS__, 10); break; \ + case 16: ret = denoise_depth(__VA_ARGS__, 16); break; \ + } \ + if (ret < 0) { \ + av_frame_free(&out); \ + if (!direct) \ + av_frame_free(&in); \ + return ret; \ + } \ + } while (0) static int16_t *precalc_coefs(double dist25, int depth) { @@ -257,7 +269,7 @@ static int config_input(AVFilterLink *inlink) s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; - s->depth = desc->comp[0].depth_minus1+1; + s->depth = desc->comp[0].depth; s->line = av_malloc(inlink->w * sizeof(*s->line)); if (!s->line) @@ -280,13 +292,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) HQDN3DContext *s = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; - int direct, c; + int c, direct = av_frame_is_writable(in); - if (av_frame_is_writable(in)) { - direct = 1; + if (direct) { out = in; } else { - direct = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); diff --git a/libavfilter/vf_hwdownload.c b/libavfilter/vf_hwdownload.c new file mode 100644 index 0000000..42925b8 --- /dev/null +++ b/libavfilter/vf_hwdownload.c @@ -0,0 +1,215 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct HWDownloadContext { + const AVClass *class; + + AVBufferRef *hwframes_ref; + AVHWFramesContext *hwframes; +} HWDownloadContext; + +static int hwdownload_query_formats(AVFilterContext *avctx) +{ + AVFilterFormats *infmts = NULL; + AVFilterFormats *outfmts = NULL; + const AVPixFmtDescriptor *desc; + int err; + + for (desc = av_pix_fmt_desc_next(NULL); desc; + desc = av_pix_fmt_desc_next(desc)) { + if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) + err = ff_add_format(&infmts, av_pix_fmt_desc_get_id(desc)); + else + err = ff_add_format(&outfmts, av_pix_fmt_desc_get_id(desc)); + if (err) { + ff_formats_unref(&infmts); + ff_formats_unref(&outfmts); + return err; + } + } + + ff_formats_ref(infmts, &avctx->inputs[0]->out_formats); + ff_formats_ref(outfmts, &avctx->outputs[0]->in_formats); + return 0; +} + +static int hwdownload_config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + HWDownloadContext *ctx = avctx->priv; + + av_buffer_unref(&ctx->hwframes_ref); + + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "The input must have a hardware frame " + "reference.\n"); + return AVERROR(EINVAL); + } + + ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!ctx->hwframes_ref) + return AVERROR(ENOMEM); + + ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data; + + return 0; +} + +static int hwdownload_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; + HWDownloadContext *ctx = avctx->priv; + enum AVPixelFormat *formats; + int err, i, found; + + if (!ctx->hwframes_ref) + return AVERROR(EINVAL); + + err = av_hwframe_transfer_get_formats(ctx->hwframes_ref, + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + &formats, 0); + if (err < 0) + return err; + + found = 0; + for (i = 0; formats[i] != AV_PIX_FMT_NONE; i++) { + if (formats[i] == outlink->format) { + found = 1; + break; + } + } + av_freep(&formats); + + if (!found) { + av_log(ctx, AV_LOG_ERROR, "Invalid output format %s for hwframe " + "download.\n", av_get_pix_fmt_name(outlink->format)); + return AVERROR(EINVAL); + } + + outlink->w = inlink->w; + outlink->h = inlink->h; + + return 0; +} + +static int hwdownload_filter_frame(AVFilterLink *link, AVFrame *input) +{ + AVFilterContext *avctx = link->dst; + AVFilterLink *outlink = avctx->outputs[0]; + HWDownloadContext *ctx = avctx->priv; + AVFrame *output = NULL; + int err; + + if (!ctx->hwframes_ref || !input->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Input frames must have hardware context.\n"); + err = AVERROR(EINVAL); + goto fail; + } + if ((void*)ctx->hwframes != input->hw_frames_ctx->data) { + av_log(ctx, AV_LOG_ERROR, "Input frame is not the in the configured " + "hwframe context.\n"); + err = AVERROR(EINVAL); + goto fail; + } + + output = ff_get_video_buffer(outlink, ctx->hwframes->width, + ctx->hwframes->height); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwframe_transfer_data(output, input, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to download frame: %d.\n", err); + goto fail; + } + + output->width = outlink->w; + output->height = outlink->h; + + err = av_frame_copy_props(output, input); + if (err < 0) + goto fail; + + av_frame_free(&input); + + return ff_filter_frame(avctx->outputs[0], output); + +fail: + av_frame_free(&input); + av_frame_free(&output); + return err; +} + +static av_cold void hwdownload_uninit(AVFilterContext *avctx) +{ + HWDownloadContext *ctx = avctx->priv; + + av_buffer_unref(&ctx->hwframes_ref); +} + +static const AVClass hwdownload_class = { + .class_name = "hwdownload", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad hwdownload_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = hwdownload_config_input, + .filter_frame = hwdownload_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad hwdownload_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = hwdownload_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_hwdownload = { + .name = "hwdownload", + .description = NULL_IF_CONFIG_SMALL("Download a hardware frame to a normal frame"), + .uninit = hwdownload_uninit, + .query_formats = hwdownload_query_formats, + .priv_size = sizeof(HWDownloadContext), + .priv_class = &hwdownload_class, + .inputs = hwdownload_inputs, + .outputs = hwdownload_outputs, +}; diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c new file mode 100644 index 0000000..c438d5a --- /dev/null +++ b/libavfilter/vf_hwupload.c @@ -0,0 +1,241 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_internal.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct HWUploadContext { + const AVClass *class; + + AVBufferRef *hwdevice_ref; + AVHWDeviceContext *hwdevice; + + AVBufferRef *hwframes_ref; + AVHWFramesContext *hwframes; +} HWUploadContext; + +static int hwupload_query_formats(AVFilterContext *avctx) +{ + HWUploadContext *ctx = avctx->priv; + AVHWFramesConstraints *constraints = NULL; + const enum AVPixelFormat *input_pix_fmts, *output_pix_fmts; + AVFilterFormats *input_formats = NULL; + int err, i; + + if (!avctx->hw_device_ctx) { + av_log(ctx, AV_LOG_ERROR, "A hardware device reference is required " + "to upload frames to.\n"); + return AVERROR(EINVAL); + } + + ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hwdevice_ref) + return AVERROR(ENOMEM); + ctx->hwdevice = (AVHWDeviceContext*)ctx->hwdevice_ref->data; + + constraints = av_hwdevice_get_hwframe_constraints(ctx->hwdevice_ref, NULL); + if (!constraints) { + err = AVERROR(EINVAL); + goto fail; + } + + input_pix_fmts = constraints->valid_sw_formats; + output_pix_fmts = constraints->valid_hw_formats; + + input_formats = ff_make_format_list(output_pix_fmts); + if (!input_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + if (input_pix_fmts) { + for (i = 0; input_pix_fmts[i] != AV_PIX_FMT_NONE; i++) { + err = ff_add_format(&input_formats, input_pix_fmts[i]); + if (err < 0) { + ff_formats_unref(&input_formats); + goto fail; + } + } + } + + ff_formats_ref(input_formats, &avctx->inputs[0]->out_formats); + + ff_formats_ref(ff_make_format_list(output_pix_fmts), + &avctx->outputs[0]->in_formats); + + av_hwframe_constraints_free(&constraints); + return 0; + +fail: + av_buffer_unref(&ctx->hwdevice_ref); + av_hwframe_constraints_free(&constraints); + return err; +} + +static int hwupload_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; + HWUploadContext *ctx = avctx->priv; + int err; + + av_buffer_unref(&ctx->hwframes_ref); + + if (inlink->format == outlink->format) { + // The input is already a hardware format, so we just want to + // pass through the input frames in their own hardware context. + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No input hwframe context.\n"); + return AVERROR(EINVAL); + } + + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; + } + + ctx->hwframes_ref = av_hwframe_ctx_alloc(ctx->hwdevice_ref); + if (!ctx->hwframes_ref) + return AVERROR(ENOMEM); + + ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data; + + av_log(ctx, AV_LOG_DEBUG, "Surface format is %s.\n", + av_get_pix_fmt_name(inlink->format)); + + ctx->hwframes->format = outlink->format; + ctx->hwframes->sw_format = inlink->format; + ctx->hwframes->width = inlink->w; + ctx->hwframes->height = inlink->h; + + err = av_hwframe_ctx_init(ctx->hwframes_ref); + if (err < 0) + goto fail; + + outlink->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref); + if (!outlink->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } + + return 0; + +fail: + av_buffer_unref(&ctx->hwframes_ref); + return err; +} + +static int hwupload_filter_frame(AVFilterLink *link, AVFrame *input) +{ + AVFilterContext *avctx = link->dst; + AVFilterLink *outlink = avctx->outputs[0]; + HWUploadContext *ctx = avctx->priv; + AVFrame *output = NULL; + int err; + + if (input->format == outlink->format) + return ff_filter_frame(outlink, input); + + output = av_frame_alloc(); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwframe_get_buffer(ctx->hwframes_ref, output, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate frame to upload to.\n"); + goto fail; + } + + output->width = input->width; + output->height = input->height; + + err = av_hwframe_transfer_data(output, input, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to upload frame: %d.\n", err); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) + goto fail; + + av_frame_free(&input); + + return ff_filter_frame(outlink, output); + +fail: + av_frame_free(&input); + av_frame_free(&output); + return err; +} + +static av_cold void hwupload_uninit(AVFilterContext *avctx) +{ + HWUploadContext *ctx = avctx->priv; + + av_buffer_unref(&ctx->hwframes_ref); + av_buffer_unref(&ctx->hwdevice_ref); +} + +static const AVClass hwupload_class = { + .class_name = "hwupload", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad hwupload_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = hwupload_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad hwupload_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = hwupload_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_hwupload = { + .name = "hwupload", + .description = NULL_IF_CONFIG_SMALL("Upload a normal frame to a hardware frame"), + .uninit = hwupload_uninit, + .query_formats = hwupload_query_formats, + .priv_size = sizeof(HWUploadContext), + .priv_class = &hwupload_class, + .inputs = hwupload_inputs, + .outputs = hwupload_outputs, +}; diff --git a/libavfilter/vf_hwupload_cuda.c b/libavfilter/vf_hwupload_cuda.c new file mode 100644 index 0000000..dfb3506 --- /dev/null +++ b/libavfilter/vf_hwupload_cuda.c @@ -0,0 +1,237 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct CudaUploadContext { + const AVClass *class; + int device_idx; + + AVBufferRef *hwdevice; + AVBufferRef *hwframe; +} CudaUploadContext; + +static void cudaupload_ctx_free(AVHWDeviceContext *ctx) +{ + AVCUDADeviceContext *hwctx = ctx->hwctx; + cuCtxDestroy(hwctx->cuda_ctx); +} + +static av_cold int cudaupload_init(AVFilterContext *ctx) +{ + CudaUploadContext *s = ctx->priv; + + AVHWDeviceContext *device_ctx; + AVCUDADeviceContext *device_hwctx; + CUdevice device; + CUcontext cuda_ctx = NULL, dummy; + CUresult err; + int ret; + + err = cuInit(0); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n"); + return AVERROR_UNKNOWN; + } + + err = cuDeviceGet(&device, s->device_idx); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", s->device_idx); + return AVERROR_UNKNOWN; + } + + err = cuCtxCreate(&cuda_ctx, 0, device); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n"); + return AVERROR_UNKNOWN; + } + + cuCtxPopCurrent(&dummy); + + s->hwdevice = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA); + if (!s->hwdevice) { + cuCtxDestroy(cuda_ctx); + return AVERROR(ENOMEM); + } + + device_ctx = (AVHWDeviceContext*)s->hwdevice->data; + device_ctx->free = cudaupload_ctx_free; + + device_hwctx = device_ctx->hwctx; + device_hwctx->cuda_ctx = cuda_ctx; + + ret = av_hwdevice_ctx_init(s->hwdevice); + if (ret < 0) + return ret; + + return 0; +} + +static av_cold void cudaupload_uninit(AVFilterContext *ctx) +{ + CudaUploadContext *s = ctx->priv; + + av_buffer_unref(&s->hwframe); + av_buffer_unref(&s->hwdevice); +} + +static int cudaupload_query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat input_pix_fmts[] = { + AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NONE, + }; + static const enum AVPixelFormat output_pix_fmts[] = { + AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, + }; + AVFilterFormats *in_fmts = ff_make_format_list(input_pix_fmts); + AVFilterFormats *out_fmts = ff_make_format_list(output_pix_fmts); + + ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); + ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + + return 0; +} + +static int cudaupload_config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + CudaUploadContext *s = ctx->priv; + + AVHWFramesContext *hwframe_ctx; + int ret; + + av_buffer_unref(&s->hwframe); + s->hwframe = av_hwframe_ctx_alloc(s->hwdevice); + if (!s->hwframe) + return AVERROR(ENOMEM); + + hwframe_ctx = (AVHWFramesContext*)s->hwframe->data; + hwframe_ctx->format = AV_PIX_FMT_CUDA; + hwframe_ctx->sw_format = inlink->format; + hwframe_ctx->width = FFALIGN(inlink->w, 16); + hwframe_ctx->height = FFALIGN(inlink->h, 16); + + ret = av_hwframe_ctx_init(s->hwframe); + if (ret < 0) + return ret; + + outlink->hw_frames_ctx = av_buffer_ref(s->hwframe); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; +} + +static int cudaupload_filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + CudaUploadContext *s = ctx->priv; + + AVFrame *out = NULL; + int ret; + + out = av_frame_alloc(); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_hwframe_get_buffer(s->hwframe, out, 0); + if (ret < 0) + goto fail; + + out->width = in->width; + out->height = in->height; + + ret = av_hwframe_transfer_data(out, in, 0); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error transferring data to the GPU\n"); + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + + av_frame_free(&in); + + return ff_filter_frame(ctx->outputs[0], out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +#define OFFSET(x) offsetof(CudaUploadContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { "device", "Number of the device to use", OFFSET(device_idx), AV_OPT_TYPE_INT, { .i64 = 0 }, .flags = FLAGS }, + { NULL }, +}; + +static const AVClass cudaupload_class = { + .class_name = "cudaupload", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad cudaupload_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = cudaupload_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad cudaupload_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = cudaupload_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_hwupload_cuda = { + .name = "hwupload_cuda", + .description = NULL_IF_CONFIG_SMALL("Upload a system memory frame to a CUDA device"), + + .init = cudaupload_init, + .uninit = cudaupload_uninit, + + .query_formats = cudaupload_query_formats, + + .priv_size = sizeof(CudaUploadContext), + .priv_class = &cudaupload_class, + + .inputs = cudaupload_inputs, + .outputs = cudaupload_outputs, +}; diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c index c534b0b..ac435d7 100644 --- a/libavfilter/vf_interlace.c +++ b/libavfilter/vf_interlace.c @@ -28,27 +28,10 @@ #include "formats.h" #include "avfilter.h" +#include "interlace.h" #include "internal.h" #include "video.h" -enum ScanMode { - MODE_TFF = 0, - MODE_BFF = 1, -}; - -enum FieldType { - FIELD_UPPER = 0, - FIELD_LOWER = 1, -}; - -typedef struct InterlaceContext { - const AVClass *class; - enum ScanMode scan; // top or bottom field first scanning - int lowpass; // enable or disable low pass filterning - AVFrame *cur, *next; // the two frames from which the new one is obtained - int got_output; // signal an output frame is reday to request_frame() -} InterlaceContext; - #define OFFSET(x) offsetof(InterlaceContext, x) #define V AV_OPT_FLAG_VIDEO_PARAM static const AVOption options[] = { @@ -70,6 +53,19 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; +static void lowpass_line_c(uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, + const uint8_t *srcp_above, + const uint8_t *srcp_below) +{ + int i; + for (i = 0; i < linesize; i++) { + // this calculation is an integer representation of + // '0.5 * current + 0.25 * above + 0.25 * below' + // '1 +' is for rounding. + dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; + } +} static const enum AVPixelFormat formats_supported[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, @@ -106,15 +102,24 @@ static int config_out_props(AVFilterLink *outlink) } if (!s->lowpass) - av_log(ctx, AV_LOG_WARNING, "***warning*** Lowpass filter is disabled, " + av_log(ctx, AV_LOG_WARNING, "Lowpass filter is disabled, " "the resulting video will be aliased rather than interlaced.\n"); // same input size outlink->w = inlink->w; outlink->h = inlink->h; outlink->time_base = inlink->time_base; + outlink->frame_rate = inlink->frame_rate; // half framerate outlink->time_base.num *= 2; + outlink->frame_rate.den *= 2; + + + if (s->lowpass) { + s->lowpass_line = lowpass_line_c; + if (ARCH_X86) + ff_interlace_init_x86(s); + } av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n", s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" : "without"); @@ -122,27 +127,31 @@ static int config_out_props(AVFilterLink *outlink) return 0; } -static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame, +static void copy_picture_field(InterlaceContext *s, + AVFrame *src_frame, AVFrame *dst_frame, AVFilterLink *inlink, enum FieldType field_type, int lowpass) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int hsub = desc->log2_chroma_w; int vsub = desc->log2_chroma_h; - int plane, i, j; + int plane, j; for (plane = 0; plane < desc->nb_components; plane++) { - int lines = (plane == 1 || plane == 2) ? -(-inlink->h) >> vsub : inlink->h; - int linesize = av_image_get_linesize(inlink->format, inlink->w, plane); + int cols = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->w, hsub) + : inlink->w; + int lines = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->h, vsub) + : inlink->h; uint8_t *dstp = dst_frame->data[plane]; const uint8_t *srcp = src_frame->data[plane]; - av_assert0(linesize >= 0); + av_assert0(cols >= 0 || lines >= 0); lines = (lines + (field_type == FIELD_UPPER)) / 2; - if (field_type == FIELD_LOWER) + if (field_type == FIELD_LOWER) { srcp += src_frame->linesize[plane]; - if (field_type == FIELD_LOWER) dstp += dst_frame->linesize[plane]; + } if (lowpass) { int srcp_linesize = src_frame->linesize[plane] * 2; int dstp_linesize = dst_frame->linesize[plane] * 2; @@ -153,19 +162,14 @@ static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame, srcp_above = srcp; // there is no line above if (j == 1) srcp_below = srcp; // there is no line below - for (i = 0; i < linesize; i++) { - // this calculation is an integer representation of - // '0.5 * current + 0.25 * above + 0.25 * below' - // '1 +' is for rounding. - dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; - } + s->lowpass_line(dstp, cols, srcp, srcp_above, srcp_below); dstp += dstp_linesize; srcp += srcp_linesize; } } else { av_image_copy_plane(dstp, dst_frame->linesize[plane] * 2, srcp, src_frame->linesize[plane] * 2, - linesize, lines); + cols, lines); } } } @@ -209,11 +213,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) out->pts /= 2; // adjust pts to new framerate /* copy upper/lower field from cur */ - copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass); + copy_picture_field(s, s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass); av_frame_free(&s->cur); /* copy lower/upper field from next */ - copy_picture_field(s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER, s->lowpass); + copy_picture_field(s, s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER, s->lowpass); av_frame_free(&s->next); ret = ff_filter_frame(outlink, out); diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index bd3d59b..50d02f8 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -205,7 +205,7 @@ static int parse_iplconvkernel(IplConvKernel **kernel, char *buf, void *log_ctx) { char shape_filename[128] = "", shape_str[32] = "rect"; int cols = 0, rows = 0, anchor_x = 0, anchor_y = 0, shape = CV_SHAPE_RECT; - int *values = NULL, ret; + int *values = NULL, ret = 0; sscanf(buf, "%dx%d+%dx%d/%32[^=]=%127s", &cols, &rows, &anchor_x, &anchor_y, shape_str, shape_filename); @@ -219,30 +219,36 @@ static int parse_iplconvkernel(IplConvKernel **kernel, char *buf, void *log_ctx) } else { av_log(log_ctx, AV_LOG_ERROR, "Shape unspecified or type '%s' unknown.\n", shape_str); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto out; } if (rows <= 0 || cols <= 0) { av_log(log_ctx, AV_LOG_ERROR, "Invalid non-positive values for shape size %dx%d\n", cols, rows); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto out; } if (anchor_x < 0 || anchor_y < 0 || anchor_x >= cols || anchor_y >= rows) { av_log(log_ctx, AV_LOG_ERROR, "Shape anchor %dx%d is not inside the rectangle with size %dx%d.\n", anchor_x, anchor_y, cols, rows); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto out; } *kernel = cvCreateStructuringElementEx(cols, rows, anchor_x, anchor_y, shape, values); - av_freep(&values); - if (!*kernel) - return AVERROR(ENOMEM); + if (!*kernel) { + ret = AVERROR(ENOMEM); + goto out; + } av_log(log_ctx, AV_LOG_VERBOSE, "Structuring element: w:%d h:%d x:%d y:%d shape:%s\n", rows, cols, anchor_x, anchor_y, shape_str); - return 0; +out: + av_freep(&values); + return ret; } typedef struct DilateContext { @@ -255,19 +261,25 @@ static av_cold int dilate_init(AVFilterContext *ctx, const char *args) OCVContext *s = ctx->priv; DilateContext *dilate = s->priv; char default_kernel_str[] = "3x3+0x0/rect"; - char *kernel_str; + char *kernel_str = NULL; const char *buf = args; int ret; dilate->nb_iterations = 1; - if (args) + if (args) { kernel_str = av_get_token(&buf, "|"); - if ((ret = parse_iplconvkernel(&dilate->kernel, - *kernel_str ? kernel_str : default_kernel_str, - ctx)) < 0) - return ret; + if (!kernel_str) + return AVERROR(ENOMEM); + } + + ret = parse_iplconvkernel(&dilate->kernel, + (!kernel_str || !*kernel_str) ? default_kernel_str + : kernel_str, + ctx); av_free(kernel_str); + if (ret < 0) + return ret; sscanf(buf, "|%d", &dilate->nb_iterations); av_log(ctx, AV_LOG_VERBOSE, "iterations_nb:%d\n", dilate->nb_iterations); diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 11e0a6f..2fa791d 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -75,7 +75,7 @@ static const char *eof_action_str[] = { typedef struct OverlayContext { const AVClass *class; - int x, y; ///< position of overlayed picture + int x, y; ///< position of overlaid picture int max_plane_step[4]; ///< steps per pixel for each plane int hsub, vsub; ///< chroma subsampling values @@ -99,8 +99,8 @@ static av_cold void uninit(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { - const enum AVPixelFormat inout_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }; - const enum AVPixelFormat blend_pix_fmts[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat inout_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat blend_pix_fmts[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }; AVFilterFormats *inout_formats = ff_make_format_list(inout_pix_fmts); AVFilterFormats *blend_formats = ff_make_format_list(blend_pix_fmts); diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c index 634af4c..d901547 100644 --- a/libavfilter/vf_pad.c +++ b/libavfilter/vf_pad.c @@ -33,7 +33,6 @@ #include "libavutil/eval.h" #include "libavutil/pixdesc.h" #include "libavutil/colorspace.h" -#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/parseutils.h" #include "libavutil/mathematics.h" @@ -167,12 +166,17 @@ static int config_input(AVFilterLink *inlink) NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto eval_fail; s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; + if (!s->h) + var_values[VAR_OUT_H] = var_values[VAR_OH] = s->h = inlink->h; + /* evaluate the width again, as it may depend on the evaluated output height */ if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto eval_fail; s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; + if (!s->w) + var_values[VAR_OUT_W] = var_values[VAR_OW] = s->w = inlink->w; /* evaluate x and y */ av_expr_parse_and_eval(&res, (expr = s->x_expr), @@ -197,11 +201,6 @@ static int config_input(AVFilterLink *inlink) return AVERROR(EINVAL); } - if (!s->w) - s->w = inlink->w; - if (!s->h) - s->h = inlink->h; - s->w &= ~((1 << s->hsub) - 1); s->h &= ~((1 << s->vsub) - 1); s->x &= ~((1 << s->hsub) - 1); diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 73ea9d2..65cf632 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -79,6 +79,7 @@ typedef struct ScaleContext { */ int w, h; unsigned int flags; ///sws flags + double param[2]; // sws params int hsub, vsub; ///< chroma subsampling int slice_y; ///< top of current output slice @@ -238,7 +239,7 @@ static int config_props(AVFilterLink *outlink) else { scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format, outlink->w, outlink->h, outlink->format, - scale->flags, NULL, NULL, NULL); + scale->flags, NULL, NULL, scale->param); if (!scale->sws) return AVERROR(EINVAL); } @@ -300,6 +301,8 @@ static const AVOption options[] = { { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, { "flags", "Flags to pass to libswscale", OFFSET(flags_str), AV_OPT_TYPE_STRING, { .str = "bilinear" }, .flags = FLAGS }, + { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, + { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, { NULL }, }; diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c new file mode 100644 index 0000000..247baf1 --- /dev/null +++ b/libavfilter/vf_scale_npp.c @@ -0,0 +1,660 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * scale video filter + */ + +#include +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/eval.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda.h" +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +static const enum AVPixelFormat supported_formats[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV444P, +}; + +static const enum AVPixelFormat deinterleaved_formats[][2] = { + { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P }, +}; + +static const char *const var_names[] = { + "PI", + "PHI", + "E", + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", "dar", + "sar", + NULL +}; + +enum var_name { + VAR_PI, + VAR_PHI, + VAR_E, + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_A, VAR_DAR, + VAR_SAR, + VARS_NB +}; + +enum ScaleStage { + STAGE_DEINTERLEAVE, + STAGE_RESIZE, + STAGE_INTERLEAVE, + STAGE_NB, +}; + +typedef struct NPPScaleStageContext { + int stage_needed; + enum AVPixelFormat in_fmt; + enum AVPixelFormat out_fmt; + + struct { + int width; + int height; + } planes_in[3], planes_out[3]; + + AVBufferRef *frames_ctx; + AVFrame *frame; +} NPPScaleStageContext; + +typedef struct NPPScaleContext { + const AVClass *class; + + NPPScaleStageContext stages[STAGE_NB]; + AVFrame *tmp_frame; + int passthrough; + + int shift_width, shift_height; + + /** + * New dimensions. Special values are: + * 0 = original width/height + * -1 = keep original aspect + */ + int w, h; + + /** + * Output sw format. AV_PIX_FMT_NONE for no conversion. + */ + enum AVPixelFormat format; + + char *w_expr; ///< width expression string + char *h_expr; ///< height expression string + char *format_str; + + int interp_algo; +} NPPScaleContext; + +static int nppscale_init(AVFilterContext *ctx) +{ + NPPScaleContext *s = ctx->priv; + int i; + + if (!strcmp(s->format_str, "same")) { + s->format = AV_PIX_FMT_NONE; + } else { + s->format = av_get_pix_fmt(s->format_str); + if (s->format == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str); + return AVERROR(EINVAL); + } + } + + for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { + s->stages[i].frame = av_frame_alloc(); + if (!s->stages[i].frame) + return AVERROR(ENOMEM); + } + s->tmp_frame = av_frame_alloc(); + if (!s->tmp_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static void nppscale_uninit(AVFilterContext *ctx) +{ + NPPScaleContext *s = ctx->priv; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { + av_frame_free(&s->stages[i].frame); + av_buffer_unref(&s->stages[i].frames_ctx); + } + av_frame_free(&s->tmp_frame); +} + +static int nppscale_query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, + }; + AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + + ff_set_common_formats(ctx, pix_fmts); + + return 0; +} + +static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) +{ + AVBufferRef *out_ref = NULL; + AVHWFramesContext *out_ctx; + int in_sw, in_sh, out_sw, out_sh; + int ret, i; + + av_pix_fmt_get_chroma_sub_sample(stage->in_fmt, &in_sw, &in_sh); + av_pix_fmt_get_chroma_sub_sample(stage->out_fmt, &out_sw, &out_sh); + if (!stage->planes_out[0].width) { + stage->planes_out[0].width = stage->planes_in[0].width; + stage->planes_out[0].height = stage->planes_in[0].height; + } + + for (i = 1; i < FF_ARRAY_ELEMS(stage->planes_in); i++) { + stage->planes_in[i].width = stage->planes_in[0].width >> in_sw; + stage->planes_in[i].height = stage->planes_in[0].height >> in_sh; + stage->planes_out[i].width = stage->planes_out[0].width >> out_sw; + stage->planes_out[i].height = stage->planes_out[0].height >> out_sh; + } + + out_ref = av_hwframe_ctx_alloc(device_ctx); + if (!out_ref) + return AVERROR(ENOMEM); + out_ctx = (AVHWFramesContext*)out_ref->data; + + out_ctx->format = AV_PIX_FMT_CUDA; + out_ctx->sw_format = stage->out_fmt; + out_ctx->width = FFALIGN(stage->planes_out[0].width, 32); + out_ctx->height = FFALIGN(stage->planes_out[0].height, 32); + + ret = av_hwframe_ctx_init(out_ref); + if (ret < 0) + goto fail; + + av_frame_unref(stage->frame); + ret = av_hwframe_get_buffer(out_ref, stage->frame, 0); + if (ret < 0) + goto fail; + + stage->frame->width = stage->planes_out[0].width; + stage->frame->height = stage->planes_out[0].height; + + av_buffer_unref(&stage->frames_ctx); + stage->frames_ctx = out_ref; + + return 0; +fail: + av_buffer_unref(&out_ref); + return ret; +} + +static int format_is_supported(enum AVPixelFormat fmt) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) + if (supported_formats[i] == fmt) + return 1; + return 0; +} + +static enum AVPixelFormat get_deinterleaved_format(enum AVPixelFormat fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + int i, planes; + + planes = av_pix_fmt_count_planes(fmt); + if (planes == desc->nb_components) + return fmt; + for (i = 0; i < FF_ARRAY_ELEMS(deinterleaved_formats); i++) + if (deinterleaved_formats[i][0] == fmt) + return deinterleaved_formats[i][1]; + return AV_PIX_FMT_NONE; +} + +static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_height, + int out_width, int out_height) +{ + NPPScaleContext *s = ctx->priv; + + AVHWFramesContext *in_frames_ctx; + + enum AVPixelFormat in_format; + enum AVPixelFormat out_format; + enum AVPixelFormat in_deinterleaved_format; + enum AVPixelFormat out_deinterleaved_format; + + int i, ret, last_stage = -1; + + /* check that we have a hw context */ + if (!ctx->inputs[0]->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } + in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format; + + if (!format_is_supported(in_format)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported input format: %s\n", + av_get_pix_fmt_name(in_format)); + return AVERROR(ENOSYS); + } + if (!format_is_supported(out_format)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported output format: %s\n", + av_get_pix_fmt_name(out_format)); + return AVERROR(ENOSYS); + } + + in_deinterleaved_format = get_deinterleaved_format(in_format); + out_deinterleaved_format = get_deinterleaved_format(out_format); + if (in_deinterleaved_format == AV_PIX_FMT_NONE || + out_deinterleaved_format == AV_PIX_FMT_NONE) + return AVERROR_BUG; + + /* figure out which stages need to be done */ + if (in_width != out_width || in_height != out_height || + in_deinterleaved_format != out_deinterleaved_format) + s->stages[STAGE_RESIZE].stage_needed = 1; + + if (!s->stages[STAGE_RESIZE].stage_needed && in_format == out_format) + s->passthrough = 1; + + if (!s->passthrough) { + if (in_format != in_deinterleaved_format) + s->stages[STAGE_DEINTERLEAVE].stage_needed = 1; + if (out_format != out_deinterleaved_format) + s->stages[STAGE_INTERLEAVE].stage_needed = 1; + } + + s->stages[STAGE_DEINTERLEAVE].in_fmt = in_format; + s->stages[STAGE_DEINTERLEAVE].out_fmt = in_deinterleaved_format; + s->stages[STAGE_DEINTERLEAVE].planes_in[0].width = in_width; + s->stages[STAGE_DEINTERLEAVE].planes_in[0].height = in_height; + + s->stages[STAGE_RESIZE].in_fmt = in_deinterleaved_format; + s->stages[STAGE_RESIZE].out_fmt = out_deinterleaved_format; + s->stages[STAGE_RESIZE].planes_in[0].width = in_width; + s->stages[STAGE_RESIZE].planes_in[0].height = in_height; + s->stages[STAGE_RESIZE].planes_out[0].width = out_width; + s->stages[STAGE_RESIZE].planes_out[0].height = out_height; + + s->stages[STAGE_INTERLEAVE].in_fmt = out_deinterleaved_format; + s->stages[STAGE_INTERLEAVE].out_fmt = out_format; + s->stages[STAGE_INTERLEAVE].planes_in[0].width = out_width; + s->stages[STAGE_INTERLEAVE].planes_in[0].height = out_height; + + /* init the hardware contexts */ + for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { + if (!s->stages[i].stage_needed) + continue; + + ret = init_stage(&s->stages[i], in_frames_ctx->device_ref); + if (ret < 0) + return ret; + + last_stage = i; + } + + if (last_stage < 0) + return AVERROR_BUG; + ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx); + if (!ctx->outputs[0]->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; +} + +static int nppscale_config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = outlink->src->inputs[0]; + NPPScaleContext *s = ctx->priv; + int64_t w, h; + double var_values[VARS_NB], res; + char *expr; + int ret; + + var_values[VAR_PI] = M_PI; + var_values[VAR_PHI] = M_PHI; + var_values[VAR_E] = M_E; + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; + var_values[VAR_A] = (double) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; + + /* evaluate width and height */ + av_expr_parse_and_eval(&res, (expr = s->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); + s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; + if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; + /* evaluate again the width, as it may depend on the output height */ + if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + s->w = res; + + w = s->w; + h = s->h; + + /* sanity check params */ + if (w < -1 || h < -1) { + av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); + return AVERROR(EINVAL); + } + if (w == -1 && h == -1) + s->w = s->h = 0; + + if (!(w = s->w)) + w = inlink->w; + if (!(h = s->h)) + h = inlink->h; + if (w == -1) + w = av_rescale(h, inlink->w, inlink->h); + if (h == -1) + h = av_rescale(w, inlink->h, inlink->w); + + if (w > INT_MAX || h > INT_MAX || + (h * inlink->w) > INT_MAX || + (w * inlink->h) > INT_MAX) + av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); + + outlink->w = w; + outlink->h = h; + + ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h); + if (ret < 0) + return ret; + + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", + inlink->w, inlink->h, outlink->w, outlink->h); + + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, + outlink->w*inlink->h}, + inlink->sample_aspect_ratio); + else + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + + return 0; + +fail: + av_log(NULL, AV_LOG_ERROR, + "Error when evaluating the expression '%s'\n", expr); + return ret; +} + +static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage, + AVFrame *out, AVFrame *in) +{ + AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)in->hw_frames_ctx->data; + NppStatus err; + + switch (in_frames_ctx->sw_format) { + case AV_PIX_FMT_NV12: + err = nppiYCbCr420_8u_P2P3R(in->data[0], in->linesize[0], + in->data[1], in->linesize[1], + out->data, out->linesize, + (NppiSize){ in->width, in->height }); + break; + default: + return AVERROR_BUG; + } + if (err != NPP_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "NPP deinterleave error: %d\n", err); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int nppscale_resize(AVFilterContext *ctx, NPPScaleStageContext *stage, + AVFrame *out, AVFrame *in) +{ + NPPScaleContext *s = ctx->priv; + NppStatus err; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(in->data) && in->data[i]; i++) { + int iw = stage->planes_in[i].width; + int ih = stage->planes_in[i].height; + int ow = stage->planes_out[i].width; + int oh = stage->planes_out[i].height; + + err = nppiResizeSqrPixel_8u_C1R(in->data[i], (NppiSize){ iw, ih }, + in->linesize[i], (NppiRect){ 0, 0, iw, ih }, + out->data[i], out->linesize[i], + (NppiRect){ 0, 0, ow, oh }, + (double)ow / iw, (double)oh / ih, + 0.0, 0.0, s->interp_algo); + if (err != NPP_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "NPP resize error: %d\n", err); + return AVERROR_UNKNOWN; + } + } + + return 0; +} + +static int nppscale_interleave(AVFilterContext *ctx, NPPScaleStageContext *stage, + AVFrame *out, AVFrame *in) +{ + AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)out->hw_frames_ctx->data; + NppStatus err; + + switch (out_frames_ctx->sw_format) { + case AV_PIX_FMT_NV12: + err = nppiYCbCr420_8u_P3P2R((const uint8_t**)in->data, + in->linesize, + out->data[0], out->linesize[0], + out->data[1], out->linesize[1], + (NppiSize){ in->width, in->height }); + break; + default: + return AVERROR_BUG; + } + if (err != NPP_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "NPP deinterleave error: %d\n", err); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int (*const nppscale_process[])(AVFilterContext *ctx, NPPScaleStageContext *stage, + AVFrame *out, AVFrame *in) = { + [STAGE_DEINTERLEAVE] = nppscale_deinterleave, + [STAGE_RESIZE] = nppscale_resize, + [STAGE_INTERLEAVE] = nppscale_interleave, +}; + +static int nppscale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +{ + NPPScaleContext *s = ctx->priv; + AVFrame *src = in; + int i, ret, last_stage = -1; + + for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { + if (!s->stages[i].stage_needed) + continue; + + ret = nppscale_process[i](ctx, &s->stages[i], s->stages[i].frame, src); + if (ret < 0) + return ret; + + src = s->stages[i].frame; + last_stage = i; + } + + if (last_stage < 0) + return AVERROR_BUG; + ret = av_hwframe_get_buffer(src->hw_frames_ctx, s->tmp_frame, 0); + if (ret < 0) + return ret; + + av_frame_move_ref(out, src); + av_frame_move_ref(src, s->tmp_frame); + + ret = av_frame_copy_props(out, in); + if (ret < 0) + return ret; + + return 0; +} + +static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + NPPScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data; + AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + + AVFrame *out = NULL; + CUresult err; + CUcontext dummy; + int ret = 0; + + if (s->passthrough) + return ff_filter_frame(outlink, in); + + out = av_frame_alloc(); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, + (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, + (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, + INT_MAX); + + err = cuCtxPushCurrent(device_hwctx->cuda_ctx); + if (err != CUDA_SUCCESS) { + ret = AVERROR_UNKNOWN; + goto fail; + } + + ret = nppscale_scale(ctx, out, in); + + cuCtxPopCurrent(&dummy); + if (ret < 0) + goto fail; + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +#define OFFSET(x) offsetof(NPPScaleContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, + + { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" }, + { "nn", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN }, 0, 0, FLAGS, "interp_algo" }, + { "linear", "linear", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LINEAR }, 0, 0, FLAGS, "interp_algo" }, + { "cubic", "cubic", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC }, 0, 0, FLAGS, "interp_algo" }, + { "cubic2p_bspline", "2-parameter cubic (B=1, C=0)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_BSPLINE }, 0, 0, FLAGS, "interp_algo" }, + { "cubic2p_catmullrom", "2-parameter cubic (B=0, C=1/2)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_CATMULLROM }, 0, 0, FLAGS, "interp_algo" }, + { "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" }, + { "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" }, + { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" }, + { NULL }, +}; + +static const AVClass nppscale_class = { + .class_name = "nppscale", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad nppscale_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = nppscale_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad nppscale_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = nppscale_config_props, + }, + { NULL } +}; + +AVFilter ff_vf_scale_npp = { + .name = "scale_npp", + .description = NULL_IF_CONFIG_SMALL("NVIDIA Performance Primitives video " + "scaling and format conversion"), + + .init = nppscale_init, + .uninit = nppscale_uninit, + .query_formats = nppscale_query_formats, + + .priv_size = sizeof(NPPScaleContext), + .priv_class = &nppscale_class, + + .inputs = nppscale_inputs, + .outputs = nppscale_outputs, +}; diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c new file mode 100644 index 0000000..e5c3da5 --- /dev/null +++ b/libavfilter/vf_scale_qsv.c @@ -0,0 +1,633 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * scale video filter - QSV + */ + +#include + +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/eval.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +static const char *const var_names[] = { + "PI", + "PHI", + "E", + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", "dar", + "sar", + NULL +}; + +enum var_name { + VAR_PI, + VAR_PHI, + VAR_E, + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_A, VAR_DAR, + VAR_SAR, + VARS_NB +}; + +typedef struct QSVScaleContext { + const AVClass *class; + + AVBufferRef *out_frames_ref; + /* a clone of the main session, used internally for scaling */ + mfxSession session; + + mfxMemId *mem_ids_in; + int nb_mem_ids_in; + + mfxMemId *mem_ids_out; + int nb_mem_ids_out; + + mfxFrameSurface1 **surface_ptrs_in; + int nb_surface_ptrs_in; + + mfxFrameSurface1 **surface_ptrs_out; + int nb_surface_ptrs_out; + + mfxExtOpaqueSurfaceAlloc opaque_alloc; + mfxExtBuffer *ext_buffers[1]; + + int shift_width, shift_height; + + /** + * New dimensions. Special values are: + * 0 = original width/height + * -1 = keep original aspect + */ + int w, h; + + /** + * Output sw format. AV_PIX_FMT_NONE for no conversion. + */ + enum AVPixelFormat format; + + char *w_expr; ///< width expression string + char *h_expr; ///< height expression string + char *format_str; +} QSVScaleContext; + +static int qsvscale_init(AVFilterContext *ctx) +{ + QSVScaleContext *s = ctx->priv; + + if (!strcmp(s->format_str, "same")) { + s->format = AV_PIX_FMT_NONE; + } else { + s->format = av_get_pix_fmt(s->format_str); + if (s->format == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str); + return AVERROR(EINVAL); + } + } + + return 0; +} + +static void qsvscale_uninit(AVFilterContext *ctx) +{ + QSVScaleContext *s = ctx->priv; + + if (s->session) { + MFXClose(s->session); + s->session = NULL; + } + av_buffer_unref(&s->out_frames_ref); + + av_freep(&s->mem_ids_in); + av_freep(&s->mem_ids_out); + s->nb_mem_ids_in = 0; + s->nb_mem_ids_out = 0; + + av_freep(&s->surface_ptrs_in); + av_freep(&s->surface_ptrs_out); + s->nb_surface_ptrs_in = 0; + s->nb_surface_ptrs_out = 0; +} + +static int qsvscale_query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_QSV, AV_PIX_FMT_NONE, + }; + AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + + ff_set_common_formats(ctx, pix_fmts); + + return 0; +} + +static int init_out_pool(AVFilterContext *ctx, + int out_width, int out_height) +{ + QSVScaleContext *s = ctx->priv; + + AVHWFramesContext *in_frames_ctx; + AVHWFramesContext *out_frames_ctx; + AVQSVFramesContext *in_frames_hwctx; + AVQSVFramesContext *out_frames_hwctx; + enum AVPixelFormat in_format; + enum AVPixelFormat out_format; + int i, ret; + + /* check that we have a hw context */ + if (!ctx->inputs[0]->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } + in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; + in_frames_hwctx = in_frames_ctx->hwctx; + + in_format = in_frames_ctx->sw_format; + out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format; + + s->out_frames_ref = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); + if (!s->out_frames_ref) + return AVERROR(ENOMEM); + out_frames_ctx = (AVHWFramesContext*)s->out_frames_ref->data; + out_frames_hwctx = out_frames_ctx->hwctx; + + out_frames_ctx->format = AV_PIX_FMT_QSV; + out_frames_ctx->width = FFALIGN(out_width, 32); + out_frames_ctx->height = FFALIGN(out_height, 32); + out_frames_ctx->sw_format = out_format; + out_frames_ctx->initial_pool_size = 32; + + out_frames_hwctx->frame_type = in_frames_hwctx->frame_type; + + ret = av_hwframe_ctx_init(s->out_frames_ref); + if (ret < 0) + return ret; + + for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) { + mfxFrameInfo *info = &out_frames_hwctx->surfaces[i].Info; + info->CropW = out_width; + info->CropH = out_height; + } + + return 0; +} + +static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + AVFilterContext *ctx = pthis; + QSVScaleContext *s = ctx->priv; + + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || + !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || + !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) + return MFX_ERR_UNSUPPORTED; + + if (req->Type & MFX_MEMTYPE_FROM_VPPIN) { + resp->mids = s->mem_ids_in; + resp->NumFrameActual = s->nb_mem_ids_in; + } else { + resp->mids = s->mem_ids_out; + resp->NumFrameActual = s->nb_mem_ids_out; + } + + return MFX_ERR_NONE; +} + +static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + return MFX_ERR_NONE; +} + +static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +static const mfxHandleType handle_types[] = { + MFX_HANDLE_VA_DISPLAY, + MFX_HANDLE_D3D9_DEVICE_MANAGER, + MFX_HANDLE_D3D11_DEVICE, +}; + +static int init_out_session(AVFilterContext *ctx) +{ + + QSVScaleContext *s = ctx->priv; + AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; + AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)s->out_frames_ref->data; + AVQSVFramesContext *in_frames_hwctx = in_frames_ctx->hwctx; + AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx; + AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx; + + int opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); + + mfxHDL handle = NULL; + mfxHandleType handle_type; + mfxVersion ver; + mfxIMPL impl; + mfxVideoParam par; + mfxStatus err; + int i; + + /* extract the properties of the "master" session given to us */ + err = MFXQueryIMPL(device_hwctx->session, &impl); + if (err == MFX_ERR_NONE) + err = MFXQueryVersion(device_hwctx->session, &ver); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { + err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); + if (err == MFX_ERR_NONE) { + handle_type = handle_types[i]; + break; + } + } + + /* create a "slave" session with those same properties, to be used for + * actual scaling */ + err = MFXInit(impl, &ver, &s->session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error initializing a session for scaling\n"); + return AVERROR_UNKNOWN; + } + + if (handle) { + err = MFXVideoCORE_SetHandle(s->session, handle_type, handle); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + memset(&par, 0, sizeof(par)); + + if (opaque) { + s->surface_ptrs_in = av_mallocz_array(in_frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs_in)); + if (!s->surface_ptrs_in) + return AVERROR(ENOMEM); + for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) + s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i; + s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces; + + s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs_out)); + if (!s->surface_ptrs_out) + return AVERROR(ENOMEM); + for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) + s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i; + s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces; + + s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; + s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in; + s->opaque_alloc.In.Type = in_frames_hwctx->frame_type; + + s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out; + s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out; + s->opaque_alloc.Out.Type = out_frames_hwctx->frame_type; + + s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; + s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); + + s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; + + par.ExtParam = s->ext_buffers; + par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); + + par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + } else { + mfxFrameAllocator frame_allocator = { + .pthis = ctx, + .Alloc = frame_alloc, + .Lock = frame_lock, + .Unlock = frame_unlock, + .GetHDL = frame_get_hdl, + .Free = frame_free, + }; + + s->mem_ids_in = av_mallocz_array(in_frames_hwctx->nb_surfaces, + sizeof(*s->mem_ids_in)); + if (!s->mem_ids_in) + return AVERROR(ENOMEM); + for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) + s->mem_ids_in[i] = in_frames_hwctx->surfaces[i].Data.MemId; + s->nb_mem_ids_in = in_frames_hwctx->nb_surfaces; + + s->mem_ids_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, + sizeof(*s->mem_ids_out)); + if (!s->mem_ids_out) + return AVERROR(ENOMEM); + for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) + s->mem_ids_out[i] = out_frames_hwctx->surfaces[i].Data.MemId; + s->nb_mem_ids_out = out_frames_hwctx->nb_surfaces; + + err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + + par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; + } + + par.AsyncDepth = 1; // TODO async + + par.vpp.In = in_frames_hwctx->surfaces[0].Info; + par.vpp.Out = out_frames_hwctx->surfaces[0].Info; + + /* Apparently VPP requires the frame rate to be set to some value, otherwise + * init will fail (probably for the framerate conversion filter). Since we + * are only doing scaling here, we just invent an arbitrary + * value */ + par.vpp.In.FrameRateExtN = 25; + par.vpp.In.FrameRateExtD = 1; + par.vpp.Out.FrameRateExtN = 25; + par.vpp.Out.FrameRateExtD = 1; + + err = MFXVideoVPP_Init(s->session, &par); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error opening the VPP for scaling\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height, + int out_width, int out_height) +{ + QSVScaleContext *s = ctx->priv; + + int ret; + + qsvscale_uninit(ctx); + + ret = init_out_pool(ctx, out_width, out_height); + if (ret < 0) + return ret; + + ret = init_out_session(ctx); + if (ret < 0) + return ret; + + av_buffer_unref(&ctx->outputs[0]->hw_frames_ctx); + ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->out_frames_ref); + if (!ctx->outputs[0]->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; +} + +static int qsvscale_config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = outlink->src->inputs[0]; + QSVScaleContext *s = ctx->priv; + int64_t w, h; + double var_values[VARS_NB], res; + char *expr; + int ret; + + var_values[VAR_PI] = M_PI; + var_values[VAR_PHI] = M_PHI; + var_values[VAR_E] = M_E; + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; + var_values[VAR_A] = (double) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; + + /* evaluate width and height */ + av_expr_parse_and_eval(&res, (expr = s->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); + s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; + if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; + /* evaluate again the width, as it may depend on the output height */ + if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + goto fail; + s->w = res; + + w = s->w; + h = s->h; + + /* sanity check params */ + if (w < -1 || h < -1) { + av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); + return AVERROR(EINVAL); + } + if (w == -1 && h == -1) + s->w = s->h = 0; + + if (!(w = s->w)) + w = inlink->w; + if (!(h = s->h)) + h = inlink->h; + if (w == -1) + w = av_rescale(h, inlink->w, inlink->h); + if (h == -1) + h = av_rescale(w, inlink->h, inlink->w); + + if (w > INT_MAX || h > INT_MAX || + (h * inlink->w) > INT_MAX || + (w * inlink->h) > INT_MAX) + av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); + + outlink->w = w; + outlink->h = h; + + ret = init_scale_session(ctx, inlink->w, inlink->h, w, h); + if (ret < 0) + return ret; + + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", + inlink->w, inlink->h, outlink->w, outlink->h); + + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, + outlink->w*inlink->h}, + inlink->sample_aspect_ratio); + else + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + + return 0; + +fail: + av_log(NULL, AV_LOG_ERROR, + "Error when evaluating the expression '%s'\n", expr); + return ret; +} + +static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + QSVScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + mfxSyncPoint sync = NULL; + mfxStatus err; + + AVFrame *out = NULL; + int ret = 0; + + out = av_frame_alloc(); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_hwframe_get_buffer(s->out_frames_ref, out, 0); + if (ret < 0) + goto fail; + + do { + err = MFXVideoVPP_RunFrameVPPAsync(s->session, + (mfxFrameSurface1*)in->data[3], + (mfxFrameSurface1*)out->data[3], + NULL, &sync); + if (err == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + } while (err == MFX_WRN_DEVICE_BUSY); + + if (err < 0 || !sync) { + av_log(ctx, AV_LOG_ERROR, "Error during scaling\n"); + ret = AVERROR_UNKNOWN; + goto fail; + } + + do { + err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); + } while (err == MFX_WRN_IN_EXECUTION); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + + out->width = outlink->w; + out->height = outlink->h; + + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, + (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, + (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, + INT_MAX); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +#define OFFSET(x) offsetof(QSVScaleContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, + + { NULL }, +}; + +static const AVClass qsvscale_class = { + .class_name = "qsvscale", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad qsvscale_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = qsvscale_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad qsvscale_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = qsvscale_config_props, + }, + { NULL } +}; + +AVFilter ff_vf_scale_qsv = { + .name = "scale_qsv", + .description = NULL_IF_CONFIG_SMALL("QuickSync video scaling and format conversion"), + + .init = qsvscale_init, + .uninit = qsvscale_uninit, + .query_formats = qsvscale_query_formats, + + .priv_size = sizeof(QSVScaleContext), + .priv_class = &qsvscale_class, + + .inputs = qsvscale_inputs, + .outputs = qsvscale_outputs, +}; diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c new file mode 100644 index 0000000..561e09c --- /dev/null +++ b/libavfilter/vf_scale_vaapi.c @@ -0,0 +1,461 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vaapi.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +typedef struct ScaleVAAPIContext { + const AVClass *class; + + AVVAAPIDeviceContext *hwctx; + AVBufferRef *device_ref; + + int valid_ids; + VAConfigID va_config; + VAContextID va_context; + + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + AVBufferRef *output_frames_ref; + AVHWFramesContext *output_frames; + + char *output_format_string; + enum AVPixelFormat output_format; + int output_width; + int output_height; + +} ScaleVAAPIContext; + + +static int scale_vaapi_query_formats(AVFilterContext *avctx) +{ + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, + }; + + ff_formats_ref(ff_make_format_list(pix_fmts), + &avctx->inputs[0]->out_formats); + ff_formats_ref(ff_make_format_list(pix_fmts), + &avctx->outputs[0]->in_formats); + + return 0; +} + +static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx) +{ + if (ctx->va_context != VA_INVALID_ID) { + vaDestroyContext(ctx->hwctx->display, ctx->va_context); + ctx->va_context = VA_INVALID_ID; + } + + if (ctx->va_config != VA_INVALID_ID) { + vaDestroyConfig(ctx->hwctx->display, ctx->va_config); + ctx->va_config = VA_INVALID_ID; + } + + av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&ctx->device_ref); + ctx->hwctx = 0; + + return 0; +} + +static int scale_vaapi_config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + ScaleVAAPIContext *ctx = avctx->priv; + + scale_vaapi_pipeline_uninit(ctx); + + if (!inlink->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data; + + return 0; +} + +static int scale_vaapi_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + ScaleVAAPIContext *ctx = avctx->priv; + AVVAAPIHWConfig *hwconfig = NULL; + AVHWFramesConstraints *constraints = NULL; + AVVAAPIFramesContext *va_frames; + VAStatus vas; + int err, i; + + scale_vaapi_pipeline_uninit(ctx); + + ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); + ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx; + + av_assert0(ctx->va_config == VA_INVALID_ID); + vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone, + VAEntrypointVideoProc, 0, 0, &ctx->va_config); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline " + "config: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); + if (!hwconfig) { + err = AVERROR(ENOMEM); + goto fail; + } + hwconfig->config_id = ctx->va_config; + + constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); + if (!constraints) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (ctx->output_format == AV_PIX_FMT_NONE) + ctx->output_format = ctx->input_frames->sw_format; + if (constraints->valid_sw_formats) { + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + if (ctx->output_format == constraints->valid_sw_formats[i]) + break; + } + if (constraints->valid_sw_formats[i] == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Hardware does not support output " + "format %s.\n", av_get_pix_fmt_name(ctx->output_format)); + err = AVERROR(EINVAL); + goto fail; + } + } + + if (ctx->output_width < constraints->min_width || + ctx->output_height < constraints->min_height || + ctx->output_width > constraints->max_width || + ctx->output_height > constraints->max_height) { + av_log(ctx, AV_LOG_ERROR, "Hardware does not support scaling to " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->output_width, ctx->output_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); + err = AVERROR(EINVAL); + goto fail; + } + + ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); + if (!ctx->output_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; + + ctx->output_frames->format = AV_PIX_FMT_VAAPI; + ctx->output_frames->sw_format = ctx->output_format; + ctx->output_frames->width = ctx->output_width; + ctx->output_frames->height = ctx->output_height; + + // The number of output frames we need is determined by what follows + // the filter. If it's an encoder with complex frame reference + // structures then this could be very high. + ctx->output_frames->initial_pool_size = 10; + + err = av_hwframe_ctx_init(ctx->output_frames_ref); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " + "context for output: %d\n", err); + goto fail; + } + + va_frames = ctx->output_frames->hwctx; + + av_assert0(ctx->va_context == VA_INVALID_ID); + vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, + ctx->output_width, ctx->output_height, + VA_PROGRESSIVE, + va_frames->surface_ids, va_frames->nb_surfaces, + &ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + outlink->w = ctx->output_width; + outlink->h = ctx->output_height; + + outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); + if (!outlink->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } + + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + return 0; + +fail: + av_buffer_unref(&ctx->output_frames_ref); + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + return err; +} + +static int vaapi_proc_colour_standard(enum AVColorSpace av_cs) +{ + switch(av_cs) { +#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va; + CS(BT709, BT709); + CS(BT470BG, BT601); + CS(SMPTE170M, SMPTE170M); + CS(SMPTE240M, SMPTE240M); +#undef CS + default: + return VAProcColorStandardNone; + } +} + +static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + ScaleVAAPIContext *ctx = avctx->priv; + AVFrame *output_frame = NULL; + VASurfaceID input_surface, output_surface; + VAProcPipelineParameterBuffer params; + VABufferID params_id; + VAStatus vas; + int err; + + av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_frame->format), + input_frame->width, input_frame->height, input_frame->pts); + + if (ctx->va_context == VA_INVALID_ID) + return AVERROR(EINVAL); + + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; + av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale input.\n", + input_surface); + + output_frame = av_frame_alloc(); + if (!output_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate output frame."); + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwframe_get_buffer(ctx->output_frames_ref, output_frame, 0); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to get surface for " + "output: %d\n.", err); + } + + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale output.\n", + output_surface); + + memset(¶ms, 0, sizeof(params)); + + params.surface = input_surface; + params.surface_region = 0; + params.surface_color_standard = + vaapi_proc_colour_standard(input_frame->colorspace); + + params.output_region = 0; + params.output_background_color = 0xff000000; + params.output_color_standard = params.surface_color_standard; + + params.pipeline_flags = 0; + params.filter_flags = VA_FILTER_SCALING_HQ; + + vas = vaBeginPicture(ctx->hwctx->display, + ctx->va_context, output_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to attach new picture: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAProcPipelineParameterBufferType, + sizeof(params), 1, ¶ms, ¶ms_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } + av_log(ctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", + params_id); + + vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, + ¶ms_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to render parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } + + vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to start picture processing: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_render; + } + + if (ctx->hwctx->driver_quirks & + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { + vas = vaDestroyBuffer(ctx->hwctx->display, params_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to free parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + // And ignore. + } + } + + av_frame_copy_props(output_frame, input_frame); + av_frame_free(&input_frame); + + av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output_frame->format), + output_frame->width, output_frame->height, output_frame->pts); + + return ff_filter_frame(outlink, output_frame); + + // We want to make sure that if vaBeginPicture has been called, we also + // call vaRenderPicture and vaEndPicture. These calls may well fail or + // do something else nasty, but once we're in this failure case there + // isn't much else we can do. +fail_after_begin: + vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); +fail_after_render: + vaEndPicture(ctx->hwctx->display, ctx->va_context); +fail: + av_frame_free(&input_frame); + av_frame_free(&output_frame); + return err; +} + +static av_cold int scale_vaapi_init(AVFilterContext *avctx) +{ + ScaleVAAPIContext *ctx = avctx->priv; + + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + ctx->valid_ids = 1; + + if (ctx->output_format_string) { + ctx->output_format = av_get_pix_fmt(ctx->output_format_string); + if (ctx->output_format == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Invalid output format.\n"); + return AVERROR(EINVAL); + } + } else { + // Use the input format once that is configured. + ctx->output_format = AV_PIX_FMT_NONE; + } + + return 0; +} + +static av_cold void scale_vaapi_uninit(AVFilterContext *avctx) +{ + ScaleVAAPIContext *ctx = avctx->priv; + + if (ctx->valid_ids) + scale_vaapi_pipeline_uninit(ctx); + + av_buffer_unref(&ctx->input_frames_ref); + av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&ctx->device_ref); +} + + +#define OFFSET(x) offsetof(ScaleVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption scale_vaapi_options[] = { + { "w", "Output video width", + OFFSET(output_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "h", "Output video height", + OFFSET(output_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "format", "Output video format (software format of hardware frames)", + OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { NULL }, +}; + +static const AVClass scale_vaapi_class = { + .class_name = "scale_vaapi", + .item_name = av_default_item_name, + .option = scale_vaapi_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad scale_vaapi_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &scale_vaapi_filter_frame, + .config_props = &scale_vaapi_config_input, + }, + { NULL } +}; + +static const AVFilterPad scale_vaapi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &scale_vaapi_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_scale_vaapi = { + .name = "scale_vaapi", + .description = NULL_IF_CONFIG_SMALL("Scale to/from VAAPI surfaces."), + .priv_size = sizeof(ScaleVAAPIContext), + .init = &scale_vaapi_init, + .uninit = &scale_vaapi_uninit, + .query_formats = &scale_vaapi_query_formats, + .inputs = scale_vaapi_inputs, + .outputs = scale_vaapi_outputs, + .priv_class = &scale_vaapi_class, +}; diff --git a/libavfilter/vf_select.c b/libavfilter/vf_select.c index 8d0e6c3..4139e78 100644 --- a/libavfilter/vf_select.c +++ b/libavfilter/vf_select.c @@ -35,7 +35,7 @@ static const char *const var_names[] = { "E", ///< Euler number "PHI", ///< golden ratio - "PI", ///< greek pi + "PI", ///< Greek pi "TB", ///< timebase diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index ede1765..204ff7a 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -140,12 +140,36 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) return ff_filter_frame(inlink->dst->outputs[0], frame); } +static int config_props(AVFilterContext *ctx, AVFilterLink *link, int is_out) +{ + + av_log(ctx, AV_LOG_INFO, "config %s time_base: %d/%d, frame_rate: %d/%d\n", + is_out ? "out" : "in", + link->time_base.num, link->time_base.den, + link->frame_rate.num, link->frame_rate.den); + + return 0; +} + +static int config_props_in(AVFilterLink *link) +{ + AVFilterContext *ctx = link->dst; + return config_props(ctx, link, 0); +} + +static int config_props_out(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + return config_props(ctx, link, 1); +} + static const AVFilterPad avfilter_vf_showinfo_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, .filter_frame = filter_frame, + .config_props = config_props_in, }, { NULL } }; @@ -153,7 +177,8 @@ static const AVFilterPad avfilter_vf_showinfo_inputs[] = { static const AVFilterPad avfilter_vf_showinfo_outputs[] = { { .name = "default", - .type = AVMEDIA_TYPE_VIDEO + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props_out, }, { NULL } }; diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index d0d59e2..dbe3874 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -48,9 +48,6 @@ #define MIN_SIZE 3 #define MAX_SIZE 13 -/* right-shift and round-up */ -#define SHIFTUP(x,shift) (-((-(x))>>(shift))) - typedef struct FilterParam { int msize_x; ///< matrix width int msize_y; ///< matrix height @@ -182,7 +179,7 @@ static int config_props(AVFilterLink *link) unsharp->vsub = desc->log2_chroma_h; init_filter_param(link->dst, &unsharp->luma, "luma", link->w); - init_filter_param(link->dst, &unsharp->chroma, "chroma", SHIFTUP(link->w, unsharp->hsub)); + init_filter_param(link->dst, &unsharp->chroma, "chroma", AV_CEIL_RSHIFT(link->w, unsharp->hsub)); return 0; } @@ -208,8 +205,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) UnsharpContext *unsharp = link->dst->priv; AVFilterLink *outlink = link->dst->outputs[0]; AVFrame *out; - int cw = SHIFTUP(link->w, unsharp->hsub); - int ch = SHIFTUP(link->h, unsharp->vsub); + int cw = AV_CEIL_RSHIFT(link->w, unsharp->hsub); + int ch = AV_CEIL_RSHIFT(link->h, unsharp->vsub); out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 53c567c..75f2d17 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -186,7 +186,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) YADIFContext *s = ctx->priv; ThreadData *td = arg; int refs = s->cur->linesize[td->plane]; - int df = (s->csp->comp[td->plane].depth_minus1 + 8) / 8; + int df = (s->csp->comp[td->plane].depth + 7) / 8; int pix_3 = 3 * df; int slice_h = td->h / nb_jobs; int slice_start = jobnr * slice_h; @@ -398,7 +398,7 @@ static int poll_frame(AVFilterLink *link) if (val <= 0) return val; - //FIXME change API to not requre this red tape + //FIXME change API to not require this red tape if (val == 1 && !yadif->next) { if ((ret = ff_request_frame(link->src->inputs[0])) < 0) return ret; @@ -462,8 +462,12 @@ static int config_props(AVFilterLink *link) link->w = link->src->inputs[0]->w; link->h = link->src->inputs[0]->h; + if (s->mode & 1) + link->frame_rate = av_mul_q(link->src->inputs[0]->frame_rate, + (AVRational){2, 1}); + s->csp = av_pix_fmt_desc_get(link->format); - if (s->csp->comp[0].depth_minus1 / 8 == 1) { + if (s->csp->comp[0].depth > 8) { s->filter_line = filter_line_c_16bit; s->filter_edges = filter_edges_16bit; } else { diff --git a/libavfilter/video.c b/libavfilter/video.c index 9f1103e..cadac50 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -54,53 +54,6 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) return frame; } -#if FF_API_AVFILTERBUFFER -AVFilterBufferRef * -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, - int w, int h, enum AVPixelFormat format) -{ - AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); - AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef)); - - if (!pic || !picref) - goto fail; - - picref->buf = pic; - picref->buf->free = ff_avfilter_default_free_buffer; - if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)))) - goto fail; - - pic->w = picref->video->w = w; - pic->h = picref->video->h = h; - - /* make sure the buffer gets read permission or it's useless for output */ - picref->perms = perms | AV_PERM_READ; - - pic->refcount = 1; - picref->type = AVMEDIA_TYPE_VIDEO; - pic->format = picref->format = format; - - memcpy(pic->data, data, 4*sizeof(data[0])); - memcpy(pic->linesize, linesize, 4*sizeof(linesize[0])); - memcpy(picref->data, pic->data, sizeof(picref->data)); - memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); - - pic-> extended_data = pic->data; - picref->extended_data = picref->data; - - picref->pts = AV_NOPTS_VALUE; - - return picref; - -fail: - if (picref && picref->video) - av_free(picref->video); - av_free(picref); - av_free(pic); - return NULL; -} -#endif - AVFrame *ff_get_video_buffer(AVFilterLink *link, int w, int h) { AVFrame *ret = NULL; diff --git a/libavfilter/vsrc_color.c b/libavfilter/vsrc_color.c index 3b506ec..8c8ca3f 100644 --- a/libavfilter/vsrc_color.c +++ b/libavfilter/vsrc_color.c @@ -44,7 +44,7 @@ typedef struct ColorContext { const AVClass *class; int w, h; uint8_t color[4]; - AVRational time_base; + AVRational frame_rate; uint8_t *line[4]; int line_step[4]; int hsub, vsub; ///< chroma subsampling values @@ -57,7 +57,6 @@ typedef struct ColorContext { static av_cold int color_init(AVFilterContext *ctx) { ColorContext *color = ctx->priv; - AVRational frame_rate_q; int ret; if (av_parse_video_size(&color->w, &color->h, color->size_str) < 0) { @@ -65,13 +64,10 @@ static av_cold int color_init(AVFilterContext *ctx) return AVERROR(EINVAL); } - if (av_parse_video_rate(&frame_rate_q, color->framerate_str) < 0 || - frame_rate_q.den <= 0 || frame_rate_q.num <= 0) { + if (av_parse_video_rate(&color->frame_rate, color->framerate_str) < 0) { av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: %s\n", color->framerate_str); return AVERROR(EINVAL); } - color->time_base.num = frame_rate_q.den; - color->time_base.den = frame_rate_q.num; if ((ret = av_parse_color(color->color, color->color_str, -1, ctx)) < 0) return ret; @@ -132,12 +128,13 @@ static int color_config_props(AVFilterLink *inlink) inlink->format, rgba_color, &is_packed_rgba, NULL); av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d r:%d/%d color:0x%02x%02x%02x%02x[%s]\n", - color->w, color->h, color->time_base.den, color->time_base.num, + color->w, color->h, color->frame_rate.num, color->frame_rate.den, color->color[0], color->color[1], color->color[2], color->color[3], is_packed_rgba ? "rgba" : "yuva"); inlink->w = color->w; inlink->h = color->h; - inlink->time_base = color->time_base; + inlink->time_base = av_inv_q(color->frame_rate); + inlink->frame_rate = color->frame_rate; return 0; } diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c index 0e5df32..5989a59 100644 --- a/libavfilter/vsrc_movie.c +++ b/libavfilter/vsrc_movie.c @@ -86,6 +86,7 @@ static av_cold int movie_init(AVFilterContext *ctx) { MovieContext *movie = ctx->priv; AVInputFormat *iformat = NULL; + AVStream *st; AVCodec *codec; int ret; int64_t timestamp; @@ -132,18 +133,26 @@ static av_cold int movie_init(AVFilterContext *ctx) return ret; } movie->stream_index = ret; - movie->codec_ctx = movie->format_ctx->streams[movie->stream_index]->codec; + st = movie->format_ctx->streams[movie->stream_index]; /* * 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. */ - codec = avcodec_find_decoder(movie->codec_ctx->codec_id); + codec = avcodec_find_decoder(st->codecpar->codec_id); if (!codec) { av_log(ctx, AV_LOG_ERROR, "Failed to find any codec\n"); return AVERROR(EINVAL); } + movie->codec_ctx = avcodec_alloc_context3(codec); + if (!movie->codec_ctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(movie->codec_ctx, st->codecpar); + if (ret < 0) + return ret; + movie->codec_ctx->refcounted_frames = 1; if ((ret = avcodec_open2(movie->codec_ctx, codec, NULL)) < 0) { @@ -174,8 +183,7 @@ static av_cold void uninit(AVFilterContext *ctx) { MovieContext *movie = ctx->priv; - if (movie->codec_ctx) - avcodec_close(movie->codec_ctx); + avcodec_free_context(&movie->codec_ctx); if (movie->format_ctx) avformat_close_input(&movie->format_ctx); av_frame_free(&movie->frame); @@ -220,9 +228,7 @@ static int movie_get_frame(AVFilterLink *outlink) avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt); if (frame_decoded) { - if (movie->frame->pkt_pts != AV_NOPTS_VALUE) - movie->frame->pts = movie->frame->pkt_pts; - av_dlog(outlink->src, + av_log(outlink->src, AV_LOG_TRACE, "movie_get_frame(): file:'%s' pts:%"PRId64" time:%f aspect:%d/%d\n", movie->file_name, movie->frame->pts, (double)movie->frame->pts * @@ -230,13 +236,13 @@ static int movie_get_frame(AVFilterLink *outlink) movie->frame->sample_aspect_ratio.num, movie->frame->sample_aspect_ratio.den); // We got it. Free the packet since we are returning - av_free_packet(&pkt); + av_packet_unref(&pkt); return 0; } } // Free the packet that was allocated by av_read_frame - av_free_packet(&pkt); + av_packet_unref(&pkt); } // On multi-frame source we should stop the mixing process when diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index e41625e..5bd458c 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -46,7 +46,7 @@ typedef struct TestSourceContext { const AVClass *class; int h, w; unsigned int nb_frame; - AVRational time_base; + AVRational time_base, frame_rate; int64_t pts, max_pts; char *size; ///< video frame size char *rate; ///< video frame rate @@ -75,7 +75,6 @@ static const AVOption testsrc_options[] = { static av_cold int init_common(AVFilterContext *ctx) { TestSourceContext *test = ctx->priv; - AVRational frame_rate_q; int64_t duration = -1; int ret = 0; @@ -84,8 +83,7 @@ static av_cold int init_common(AVFilterContext *ctx) return ret; } - if ((ret = av_parse_video_rate(&frame_rate_q, test->rate)) < 0 || - frame_rate_q.den <= 0 || frame_rate_q.num <= 0) { + if ((ret = av_parse_video_rate(&test->frame_rate, test->rate)) < 0) { av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", test->rate); return ret; } @@ -95,15 +93,14 @@ static av_cold int init_common(AVFilterContext *ctx) return ret; } - test->time_base.num = frame_rate_q.den; - test->time_base.den = frame_rate_q.num; + test->time_base = av_inv_q(test->frame_rate); test->max_pts = duration >= 0 ? av_rescale_q(duration, AV_TIME_BASE_Q, test->time_base) : -1; test->nb_frame = 0; test->pts = 0; av_log(ctx, AV_LOG_DEBUG, "size:%dx%d rate:%d/%d duration:%f sar:%d/%d\n", - test->w, test->h, frame_rate_q.num, frame_rate_q.den, + test->w, test->h, test->frame_rate.num, test->frame_rate.den, duration < 0 ? -1 : test->max_pts * av_q2d(test->time_base), test->sar.num, test->sar.den); return 0; @@ -116,7 +113,8 @@ static int config_props(AVFilterLink *outlink) outlink->w = test->w; outlink->h = test->h; outlink->sample_aspect_ratio = test->sar; - outlink->time_base = test->time_base; + outlink->frame_rate = test->frame_rate; + outlink->time_base = test->time_base; return 0; } diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index 16b1307..13b5d31 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -1,9 +1,11 @@ OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun_init.o OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d_init.o +OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace_init.o OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif_init.o YASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o YASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d.o +YASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o YASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o YASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o diff --git a/libavfilter/x86/af_volume.asm b/libavfilter/x86/af_volume.asm index 4e5ad22..25ba923 100644 --- a/libavfilter/x86/af_volume.asm +++ b/libavfilter/x86/af_volume.asm @@ -29,7 +29,7 @@ pw_1: times 8 dw 1 pw_128: times 8 dw 128 pq_128: times 2 dq 128 -SECTION_TEXT +SECTION .text ;------------------------------------------------------------------------------ ; void ff_scale_samples_s16(uint8_t *dst, const uint8_t *src, int len, diff --git a/libavfilter/x86/af_volume_init.c b/libavfilter/x86/af_volume_init.c index c59e0ed..26605fb 100644 --- a/libavfilter/x86/af_volume_init.c +++ b/libavfilter/x86/af_volume_init.c @@ -52,7 +52,7 @@ av_cold void ff_volume_init_x86(VolumeContext *vol) vol->scale_samples = ff_scale_samples_s32_ssse3_atom; vol->samples_align = 4; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { vol->scale_samples = ff_scale_samples_s32_avx; vol->samples_align = 8; } diff --git a/libavfilter/x86/vf_gradfun_init.c b/libavfilter/x86/vf_gradfun_init.c index 3f23bf6..f8d85c7 100644 --- a/libavfilter/x86/vf_gradfun_init.c +++ b/libavfilter/x86/vf_gradfun_init.c @@ -22,7 +22,6 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/mem.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavfilter/gradfun.h" diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm new file mode 100644 index 0000000..85811da --- /dev/null +++ b/libavfilter/x86/vf_interlace.asm @@ -0,0 +1,65 @@ +;***************************************************************************** +;* x86-optimized functions for interlace filter +;* +;* Copyright (C) 2014 Kieran Kunhya +;* Copyright (c) 2014 Michael Niedermayer +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or modify +;* it under the terms of the GNU General Public License as published by +;* the Free Software Foundation; either version 2 of the License, or +;* (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;* GNU General Public License for more details. +;* +;* You should have received a copy of the GNU General Public License along +;* with Libav; if not, write to the Free Software Foundation, Inc., +;* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +SECTION .text + +%macro LOWPASS_LINE 0 +cglobal lowpass_line, 5, 5, 7 + add r0, r1 + add r2, r1 + add r3, r1 + add r4, r1 + neg r1 + + pcmpeqb m6, m6 + +.loop + mova m0, [r3+r1] + mova m1, [r3+r1+mmsize] + pavgb m0, [r4+r1] + pavgb m1, [r4+r1+mmsize] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6, [r2+r1] + pxor m3, m6, [r2+r1+mmsize] + pavgb m0, m2 + pavgb m1, m3 + pxor m0, m6 + pxor m1, m6 + mova [r0+r1], m0 + mova [r0+r1+mmsize], m1 + + add r1, 2*mmsize + jl .loop +REP_RET +%endmacro + +INIT_XMM sse2 +LOWPASS_LINE + +INIT_XMM avx +LOWPASS_LINE diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c new file mode 100644 index 0000000..105eeb6 --- /dev/null +++ b/libavfilter/x86/vf_interlace_init.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 Kieran Kunhya + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" +#include "libavutil/x86/cpu.h" + +#include "libavfilter/interlace.h" + +void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, + const uint8_t *srcp_above, + const uint8_t *srcp_below); +void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, + const uint8_t *srcp_above, + const uint8_t *srcp_below); + +av_cold void ff_interlace_init_x86(InterlaceContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags)) + s->lowpass_line = ff_lowpass_line_sse2; + if (EXTERNAL_AVX(cpu_flags)) + s->lowpass_line = ff_lowpass_line_avx; +} diff --git a/libavfilter/x86/vf_yadif_init.c b/libavfilter/x86/vf_yadif_init.c index 510a023..863e7df 100644 --- a/libavfilter/x86/vf_yadif_init.c +++ b/libavfilter/x86/vf_yadif_init.c @@ -22,7 +22,6 @@ #include "libavutil/cpu.h" #include "libavutil/internal.h" #include "libavutil/mem.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavfilter/yadif.h" diff --git a/libavformat/.gitignore b/libavformat/.gitignore new file mode 100644 index 0000000..cdc24b7 --- /dev/null +++ b/libavformat/.gitignore @@ -0,0 +1 @@ +/protocol_list.c diff --git a/libavformat/4xm.c b/libavformat/4xm.c index 6253ffb..1597b3b 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -1,6 +1,6 @@ /* * 4X Technologies .4xm File Demuxer (no muxer) - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -108,16 +108,16 @@ static int parse_vtrk(AVFormatContext *s, fourxm->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_4XM; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_4XM; - st->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = 4; - AV_WL32(st->codec->extradata, AV_RL32(buf + 16)); - st->codec->width = AV_RL32(buf + 36); - st->codec->height = AV_RL32(buf + 40); + st->codecpar->extradata_size = 4; + AV_WL32(st->codecpar->extradata, AV_RL32(buf + 16)); + st->codecpar->width = AV_RL32(buf + 36); + st->codecpar->height = AV_RL32(buf + 40); return 0; } @@ -165,23 +165,23 @@ static int parse_strk(AVFormatContext *s, fourxm->tracks[track].stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 0; - st->codec->channels = fourxm->tracks[track].channels; - st->codec->sample_rate = fourxm->tracks[track].sample_rate; - st->codec->bits_per_coded_sample = fourxm->tracks[track].bits; - st->codec->bit_rate = st->codec->channels * - st->codec->sample_rate * - st->codec->bits_per_coded_sample; - st->codec->block_align = st->codec->channels * - st->codec->bits_per_coded_sample; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 0; + st->codecpar->channels = fourxm->tracks[track].channels; + st->codecpar->sample_rate = fourxm->tracks[track].sample_rate; + st->codecpar->bits_per_coded_sample = fourxm->tracks[track].bits; + st->codecpar->bit_rate = st->codecpar->channels * + st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = st->codecpar->channels * + st->codecpar->bits_per_coded_sample; if (fourxm->tracks[track].adpcm){ - st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM; - } else if (st->codec->bits_per_coded_sample == 8) { - st->codec->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_4XM; + } else if (st->codecpar->bits_per_coded_sample == 8) { + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; } else - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; return 0; } @@ -308,7 +308,7 @@ static int fourxm_read_packet(AVFormatContext *s, ret = avio_read(s->pb, &pkt->data[8], size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); } else packet_read = 1; break; diff --git a/libavformat/Makefile b/libavformat/Makefile old mode 100755 new mode 100644 index a048157..d06d5d6 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -17,27 +17,36 @@ OBJS = allformats.o \ mux.o \ options.o \ os_support.o \ + protocols.o \ riff.o \ sdp.o \ - seek.o \ url.o \ utils.o \ +OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o + +# subsystems +OBJS-$(CONFIG_ISO_MEDIA) += isom.o OBJS-$(CONFIG_NETWORK) += network.o OBJS-$(CONFIG_RIFFDEC) += riffdec.o OBJS-$(CONFIG_RIFFENC) += riffenc.o OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtp.o \ rtpdec.o \ + rtpdec_ac3.o \ rtpdec_amr.o \ rtpdec_asf.o \ + rtpdec_dv.o \ rtpdec_g726.o \ + rtpdec_h261.o \ rtpdec_h263.o \ rtpdec_h263_rfc2190.o \ rtpdec_h264.o \ + rtpdec_hevc.o \ rtpdec_ilbc.o \ rtpdec_jpeg.o \ rtpdec_latm.o \ + rtpdec_mpa_robust.o \ rtpdec_mpeg12.o \ rtpdec_mpeg4.o \ rtpdec_mpegts.o \ @@ -46,18 +55,19 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtpdec_qt.o \ rtpdec_svq3.o \ rtpdec_vp8.o \ - rtpdec_xiph.o \ - srtp.o + rtpdec_vp9.o \ + rtpdec_xiph.o OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o +OBJS-$(CONFIG_SRTP) += srtp.o # muxers/demuxers OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o rawdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o +OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o OBJS-$(CONFIG_ADX_MUXER) += rawenc.o -OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o pcm.o OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o @@ -77,19 +87,20 @@ OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o OBJS-$(CONFIG_AVI_MUXER) += avienc.o OBJS-$(CONFIG_AVISYNTH) += avisynth.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o -OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o +OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o voc.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o -OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o +OBJS-$(CONFIG_C93_DEMUXER) += c93.o voc_packet.o voc.o OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ - isom.o replaygain.o + replaygain.o OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o +OBJS-$(CONFIG_DASH_MUXER) += dashenc.o OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o @@ -98,6 +109,7 @@ OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddec.o rawdec.o OBJS-$(CONFIG_DNXHD_MUXER) += rawenc.o OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o +OBJS-$(CONFIG_DSS_DEMUXER) += dss.o OBJS-$(CONFIG_DTS_DEMUXER) += dtsdec.o rawdec.o OBJS-$(CONFIG_DTS_MUXER) += rawenc.o OBJS-$(CONFIG_DV_DEMUXER) += dv.o @@ -124,13 +136,15 @@ OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o OBJS-$(CONFIG_FRAMEMD5_MUXER) += md5enc.o framehash.o +OBJS-$(CONFIG_G722_DEMUXER) += g722.o rawdec.o +OBJS-$(CONFIG_G722_MUXER) += rawenc.o +OBJS-$(CONFIG_G723_1_DEMUXER) += g723_1.o +OBJS-$(CONFIG_G723_1_MUXER) += rawenc.o +OBJS-$(CONFIG_G729_DEMUXER) += g729dec.o OBJS-$(CONFIG_GIF_MUXER) += gif.o OBJS-$(CONFIG_GSM_DEMUXER) += gsmdec.o OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o audiointerleave.o -OBJS-$(CONFIG_G722_DEMUXER) += g722.o rawdec.o -OBJS-$(CONFIG_G722_MUXER) += rawenc.o -OBJS-$(CONFIG_G723_1_DEMUXER) += g723_1.o OBJS-$(CONFIG_H261_DEMUXER) += h261dec.o rawdec.o OBJS-$(CONFIG_H261_MUXER) += rawenc.o OBJS-$(CONFIG_H263_DEMUXER) += h263dec.o rawdec.o @@ -165,11 +179,11 @@ OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ - isom.o rmsipr.o \ + rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ flac_picture.o replaygain.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ - isom.o avc.o hevc.o \ + avc.o hevc.o \ flacenc_header.o avlanguage.o vorbiscomment.o wv.o OBJS-$(CONFIG_MD5_MUXER) += md5enc.o OBJS-$(CONFIG_MJPEG_DEMUXER) += rawdec.o @@ -179,25 +193,26 @@ OBJS-$(CONFIG_MLP_MUXER) += rawenc.o OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o pcm.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o -OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o replaygain.o -OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o hevc.o \ +OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o replaygain.o +OBJS-$(CONFIG_MOV_MUXER) += movenc.o avc.o hevc.o \ movenchint.o mov_chan.o -OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o +OBJS-$(CONFIG_MP2_MUXER) += rawenc.o OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o OBJS-$(CONFIG_MPC_DEMUXER) += mpc.o apetag.o img2.o OBJS-$(CONFIG_MPC8_DEMUXER) += mpc8.o apetag.o img2.o OBJS-$(CONFIG_MPEG1SYSTEM_MUXER) += mpegenc.o OBJS-$(CONFIG_MPEG1VCD_MUXER) += mpegenc.o +OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_MPEG2DVD_MUXER) += mpegenc.o -OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpegenc.o OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpegenc.o -OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += rawenc.o +OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpegenc.o OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o -OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o isom.o +OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += mpegvideodec.o rawdec.o +OBJS-$(CONFIG_MPJPEG_DEMUXER) += mpjpegdec.o OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o @@ -222,6 +237,7 @@ OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \ oggparsespeex.o \ oggparsetheora.o \ oggparsevorbis.o \ + oggparsevp8.o \ replaygain.o \ vorbiscomment.o \ flac_picture.o @@ -281,22 +297,24 @@ OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o rm.o rmsipr.o OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o OBJS-$(CONFIG_ROQ_DEMUXER) += idroqdec.o OBJS-$(CONFIG_ROQ_MUXER) += idroqenc.o rawenc.o +OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o OBJS-$(CONFIG_RSO_DEMUXER) += rsodec.o rso.o pcm.o OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o -OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o +OBJS-$(CONFIG_RTP_MPEGTS_MUXER) += rtpenc_mpegts.o OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_aac.o \ rtpenc_latm.o \ rtpenc_amr.o \ + rtpenc_h261.o \ rtpenc_h263.o \ rtpenc_h263_rfc2190.o \ + rtpenc_h264_hevc.o \ rtpenc_jpeg.o \ rtpenc_mpv.o \ rtpenc.o \ - rtpenc_h264.o \ rtpenc_vp8.o \ rtpenc_xiph.o \ - avc.o + avc.o hevc.o OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o \ urldecode.o OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o \ @@ -311,7 +329,7 @@ OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o OBJS-$(CONFIG_SMJPEG_DEMUXER) += smjpegdec.o smjpeg.o OBJS-$(CONFIG_SMJPEG_MUXER) += smjpegenc.o smjpeg.o -OBJS-$(CONFIG_SMOOTHSTREAMING_MUXER) += smoothstreamingenc.o isom.o +OBJS-$(CONFIG_SMOOTHSTREAMING_MUXER) += smoothstreamingenc.o OBJS-$(CONFIG_SMUSH_DEMUXER) += smush.o OBJS-$(CONFIG_SOL_DEMUXER) += sol.o pcm.o OBJS-$(CONFIG_SOX_DEMUXER) += soxdec.o pcm.o @@ -336,7 +354,7 @@ OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o OBJS-$(CONFIG_VC1T_MUXER) += vc1testenc.o OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o -OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o +OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc_packet.o voc.o OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o pcm.o @@ -344,21 +362,21 @@ OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ - isom.o avc.o hevc.o \ + avc.o hevc.o \ flacenc_header.o avlanguage.o \ wv.o vorbiscomment.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o OBJS-$(CONFIG_WTV_DEMUXER) += wtv.o asfdec.o asf.o asfcrypt.o \ - avlanguage.o mpegts.o isom.o + avlanguage.o OBJS-$(CONFIG_WV_DEMUXER) += wvdec.o wv.o apetag.o img2.o OBJS-$(CONFIG_WV_MUXER) += wvenc.o wv.o apetag.o img2.o OBJS-$(CONFIG_XA_DEMUXER) += xa.o OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o OBJS-$(CONFIG_YOP_DEMUXER) += yop.o -OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpegenc.o OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpegdec.o +OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpegenc.o # external libraries OBJS-$(CONFIG_LIBRTMP) += librtmp.o @@ -376,9 +394,9 @@ OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_ICECAST_PROTOCOL) += icecast.o +OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o OBJS-$(CONFIG_MMSH_PROTOCOL) += mmsh.o mms.o asf.o OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o -OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o @@ -390,22 +408,24 @@ OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o -OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o +OBJS-$(CONFIG_TLS_GNUTLS_PROTOCOL) += tls_gnutls.o tls.o +OBJS-$(CONFIG_TLS_OPENSSL_PROTOCOL) += tls_openssl.o tls.o OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o -OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o - SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h TESTPROGS = seek \ - srtp \ url \ +TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh +TESTPROGS-$(CONFIG_MOV_MUXER) += movenc TESTPROGS-$(CONFIG_NETWORK) += noproxy +TESTPROGS-$(CONFIG_SRTP) += srtp TOOLS = aviocat \ ismindex \ pktdumper \ probetest \ + sidxindex \ diff --git a/libavformat/a64.c b/libavformat/a64.c index c8e8e64..fdd6f62 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -27,7 +27,7 @@ static int a64_write_header(AVFormatContext *s) { - AVCodecContext *avctx = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; uint8_t header[5] = { 0x00, //load 0x40, //address @@ -36,20 +36,20 @@ static int a64_write_header(AVFormatContext *s) 0x00 //fps in 50/fps; }; - if (avctx->extradata_size < 4) { + if (par->extradata_size < 4) { av_log(s, AV_LOG_ERROR, "Missing extradata\n"); return AVERROR_INVALIDDATA; } - switch (avctx->codec->id) { + switch (par->codec_id) { case AV_CODEC_ID_A64_MULTI: header[2] = 0x00; - header[3] = AV_RB32(avctx->extradata+0); + header[3] = AV_RB32(par->extradata+0); header[4] = 2; break; case AV_CODEC_ID_A64_MULTI5: header[2] = 0x01; - header[3] = AV_RB32(avctx->extradata+0); + header[3] = AV_RB32(par->extradata+0); header[4] = 3; break; default: diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 566c3e7..2f20792 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -82,8 +82,8 @@ static int adts_aac_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->iformat->raw_codec_id; st->need_parsing = AVSTREAM_PARSE_FULL; ff_id3v1_read(s); diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index bf7a62a..e7c72d8 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -28,7 +28,7 @@ #define ADTS_HEADER_SIZE 7 -typedef struct { +typedef struct ADTSContext { int write_adts; int objecttype; int sample_rate_index; @@ -57,23 +57,23 @@ static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, uint8_t if (adts->objecttype > 3U) { av_log(s, AV_LOG_ERROR, "MPEG-4 AOT %d is not allowed in ADTS\n", adts->objecttype+1); - return -1; + return AVERROR_INVALIDDATA; } if (adts->sample_rate_index == 15) { av_log(s, AV_LOG_ERROR, "Escape sample rate index illegal in ADTS\n"); - return -1; + return AVERROR_INVALIDDATA; } if (get_bits(&gb, 1)) { av_log(s, AV_LOG_ERROR, "960/120 MDCT window is not allowed in ADTS\n"); - return -1; + return AVERROR_INVALIDDATA; } if (get_bits(&gb, 1)) { av_log(s, AV_LOG_ERROR, "Scalable configurations are not allowed in ADTS\n"); - return -1; + return AVERROR_INVALIDDATA; } if (get_bits(&gb, 1)) { av_log(s, AV_LOG_ERROR, "Extension flag is not allowed in ADTS\n"); - return -1; + return AVERROR_INVALIDDATA; } if (!adts->channel_conf) { init_put_bits(&pb, adts->pce_data, MAX_PCE_SIZE); @@ -91,11 +91,11 @@ static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, uint8_t static int adts_write_header(AVFormatContext *s) { ADTSContext *adts = s->priv_data; - AVCodecContext *avc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; - if (avc->extradata_size > 0 && - adts_decode_extradata(s, adts, avc->extradata, avc->extradata_size) < 0) - return -1; + if (par->extradata_size > 0) + return adts_decode_extradata(s, adts, par->extradata, + par->extradata_size); return 0; } diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c index 9d3ebe3..8162c69 100644 --- a/libavformat/adxdec.c +++ b/libavformat/adxdec.c @@ -37,21 +37,21 @@ typedef struct ADXDemuxerContext { static int adx_read_packet(AVFormatContext *s, AVPacket *pkt) { ADXDemuxerContext *c = s->priv_data; - AVCodecContext *avctx = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; int ret, size; - size = BLOCK_SIZE * avctx->channels; + size = BLOCK_SIZE * par->channels; pkt->pos = avio_tell(s->pb); pkt->stream_index = 0; ret = av_get_packet(s->pb, pkt, size); if (ret != size) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } if (AV_RB16(pkt->data) & 0x8000) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR_EOF; } pkt->size = size; @@ -64,43 +64,43 @@ static int adx_read_packet(AVFormatContext *s, AVPacket *pkt) static int adx_read_header(AVFormatContext *s) { ADXDemuxerContext *c = s->priv_data; - AVCodecContext *avctx; + AVCodecParameters *par; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - avctx = s->streams[0]->codec; + par = s->streams[0]->codecpar; if (avio_rb16(s->pb) != 0x8000) return AVERROR_INVALIDDATA; c->header_size = avio_rb16(s->pb) + 4; avio_seek(s->pb, -4, SEEK_CUR); - avctx->extradata = av_mallocz(c->header_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) + par->extradata = av_mallocz(c->header_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) return AVERROR(ENOMEM); - if (avio_read(s->pb, avctx->extradata, c->header_size) < c->header_size) { - av_freep(&avctx->extradata); + if (avio_read(s->pb, par->extradata, c->header_size) < c->header_size) { + av_freep(&par->extradata); return AVERROR(EIO); } - avctx->extradata_size = c->header_size; + par->extradata_size = c->header_size; - if (avctx->extradata_size < 12) { + if (par->extradata_size < 12) { av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n"); return AVERROR_INVALIDDATA; } - avctx->channels = AV_RB8(avctx->extradata + 7); - avctx->sample_rate = AV_RB32(avctx->extradata + 8); + par->channels = AV_RB8 (par->extradata + 7); + par->sample_rate = AV_RB32(par->extradata + 8); - if (avctx->channels <= 0) { - av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", avctx->channels); + if (par->channels <= 0) { + av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels); return AVERROR_INVALIDDATA; } - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = s->iformat->raw_codec_id; - avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, avctx->sample_rate); + avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, par->sample_rate); return 0; } diff --git a/libavformat/aea.c b/libavformat/aea.c index 7675009..fc914f0 100644 --- a/libavformat/aea.c +++ b/libavformat/aea.c @@ -32,7 +32,7 @@ static int aea_read_probe(AVProbeData *p) if (p->buf_size <= 2048+212) return 0; - /* Magic is '00 08 00 00' in Little Endian*/ + /* Magic is '00 08 00 00' in little-endian*/ if (AV_RL32(p->buf)==0x800) { int bsm_s, bsm_e, inb_s, inb_e, ch; ch = p->buf[264]; @@ -62,29 +62,29 @@ static int aea_read_header(AVFormatContext *s) /* Parse the amount of channels and skip to pos 2048(0x800) */ avio_skip(s->pb, 264); - st->codec->channels = avio_r8(s->pb); + st->codecpar->channels = avio_r8(s->pb); avio_skip(s->pb, 1783); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ATRAC1; - st->codec->sample_rate = 44100; - st->codec->bit_rate = 292000; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ATRAC1; + st->codecpar->sample_rate = 44100; + st->codecpar->bit_rate = 292000; - if (st->codec->channels != 1 && st->codec->channels != 2) { - av_log(s,AV_LOG_ERROR,"Channels %d not supported!\n",st->codec->channels); - return -1; + if (st->codecpar->channels != 1 && st->codecpar->channels != 2) { + av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", st->codecpar->channels); + return AVERROR_INVALIDDATA; } - st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; - st->codec->block_align = AT1_SU_SIZE * st->codec->channels; + st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->channels; return 0; } static int aea_read_packet(AVFormatContext *s, AVPacket *pkt) { - int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align); + int ret = av_get_packet(s->pb, pkt, s->streams[0]->codecpar->block_align); pkt->stream_index = 0; if (ret <= 0) diff --git a/libavformat/aiff.h b/libavformat/aiff.h index f88f957..4ed135b 100644 --- a/libavformat/aiff.h +++ b/libavformat/aiff.h @@ -42,6 +42,7 @@ static const AVCodecTag ff_codec_aiff_tags[] = { { AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') }, { AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') }, { AV_CODEC_ID_GSM, MKTAG('G','S','M',' ') }, + { AV_CODEC_ID_ADPCM_G722, MKTAG('G','7','2','2') }, { AV_CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') }, { AV_CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') }, { AV_CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 6243bcb..3c45c61 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -29,7 +29,7 @@ #define AIFF 0 #define AIFF_C_VERSION1 0xA2805140 -typedef struct { +typedef struct AIFFInputContext { int64_t data_end; int block_duration; } AIFFInputContext; @@ -90,7 +90,7 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size, unsigned version) { AVIOContext *pb = s->pb; - AVCodecContext *codec = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; AIFFInputContext *aiff = s->priv_data; int exp; uint64_t val; @@ -99,30 +99,30 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size, if (size & 1) size++; - codec->codec_type = AVMEDIA_TYPE_AUDIO; - codec->channels = avio_rb16(pb); + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->channels = avio_rb16(pb); num_frames = avio_rb32(pb); - codec->bits_per_coded_sample = avio_rb16(pb); + par->bits_per_coded_sample = avio_rb16(pb); exp = avio_rb16(pb); val = avio_rb64(pb); sample_rate = ldexp(val, exp - 16383 - 63); - codec->sample_rate = sample_rate; + par->sample_rate = sample_rate; size -= 18; /* get codec id for AIFF-C */ if (version == AIFF_C_VERSION1) { - codec->codec_tag = avio_rl32(pb); - codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); + par->codec_tag = avio_rl32(pb); + par->codec_id = ff_codec_get_id(ff_codec_aiff_tags, par->codec_tag); size -= 4; } - if (version != AIFF_C_VERSION1 || codec->codec_id == AV_CODEC_ID_PCM_S16BE) { - codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); - codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); + if (version != AIFF_C_VERSION1 || par->codec_id == AV_CODEC_ID_PCM_S16BE) { + par->codec_id = aiff_codec_get_id(par->bits_per_coded_sample); + par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); aiff->block_duration = 1; } else { - switch (codec->codec_id) { + switch (par->codec_id) { case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_S16LE: @@ -131,36 +131,37 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size, aiff->block_duration = 1; break; case AV_CODEC_ID_ADPCM_IMA_QT: - codec->block_align = 34*codec->channels; + par->block_align = 34 * par->channels; break; case AV_CODEC_ID_MACE3: - codec->block_align = 2*codec->channels; + par->block_align = 2 * par->channels; break; + case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_MACE6: - codec->block_align = 1*codec->channels; + par->block_align = 1 * par->channels; break; case AV_CODEC_ID_GSM: - codec->block_align = 33; + par->block_align = 33; break; case AV_CODEC_ID_QCELP: - codec->block_align = 35; + par->block_align = 35; break; default: break; } - if (codec->block_align > 0) - aiff->block_duration = av_get_audio_frame_duration(codec, - codec->block_align); + if (par->block_align > 0) + aiff->block_duration = av_get_audio_frame_duration2(par, + par->block_align); } /* Block align needs to be computed in all cases, as the definition * is specific to applications -> here we use the WAVE format definition */ - if (!codec->block_align) - codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3; + if (!par->block_align) + par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; if (aiff->block_duration) { - codec->bit_rate = codec->sample_rate * (codec->block_align << 3) / - aiff->block_duration; + par->bit_rate = par->sample_rate * (par->block_align << 3) / + aiff->block_duration; } /* Chunk is over */ @@ -248,7 +249,7 @@ static int aiff_read_header(AVFormatContext *s) offset = avio_rb32(pb); /* Offset of sound data */ avio_rb32(pb); /* BlockSize... don't care */ offset += avio_tell(pb); /* Compute absolute data offset */ - if (st->codec->block_align) /* Assume COMM already parsed */ + if (st->codecpar->block_align) /* Assume COMM already parsed */ goto got_sound; if (!pb->seekable) { av_log(s, AV_LOG_ERROR, "file is not seekable\n"); @@ -259,27 +260,31 @@ static int aiff_read_header(AVFormatContext *s) case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) return -1; - st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = size; - avio_read(pb, st->codec->extradata, size); + st->codecpar->extradata_size = size; + avio_read(pb, st->codecpar->extradata, size); break; default: /* Jump */ - if (size & 1) /* Always even aligned */ - size++; avio_skip(pb, size); } + + /* Skip required padding byte for odd-sized chunks. */ + if (size & 1) { + filesize--; + avio_skip(pb, 1); + } } got_sound: - if (!st->codec->block_align) { + if (!st->codecpar->block_align) { av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); return -1; } /* Now positioned, get the sound data start and end */ - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->start_time = 0; st->duration = st->nb_frames * aiff->block_duration; @@ -305,10 +310,10 @@ static int aiff_read_packet(AVFormatContext *s, return AVERROR_EOF; /* Now for that packet */ - if (st->codec->block_align >= 33) // GSM, QCLP, IMA4 - size = st->codec->block_align; + if (st->codecpar->block_align >= 33) // GSM, QCLP, IMA4 + size = st->codecpar->block_align; else - size = (MAX_SIZE / st->codec->block_align) * st->codec->block_align; + size = (MAX_SIZE / st->codecpar->block_align) * st->codecpar->block_align; size = FFMIN(max_size, size); res = av_get_packet(s->pb, pkt, size); if (res < 0) @@ -316,7 +321,7 @@ static int aiff_read_packet(AVFormatContext *s, /* Only one stream in an AIFF file */ pkt->stream_index = 0; - pkt->duration = (res / st->codec->block_align) * aiff->block_duration; + pkt->duration = (res / st->codecpar->block_align) * aiff->block_duration; return 0; } diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index d4bffb3..6449c00 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -27,7 +27,7 @@ #include "aiff.h" #include "avio_internal.h" -typedef struct { +typedef struct AIFFOutputContext { int64_t form; int64_t frames; int64_t ssnd; @@ -37,14 +37,14 @@ static int aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; uint64_t sample_rate; int aifc = 0; /* First verify if format is ok */ - if (!enc->codec_tag) + if (!par->codec_tag) return -1; - if (enc->codec_tag != MKTAG('N','O','N','E')) + if (par->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ @@ -54,8 +54,8 @@ static int aiff_write_header(AVFormatContext *s) ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF"); if (aifc) { // compressed audio - enc->bits_per_coded_sample = 16; - if (!enc->block_align) { + par->bits_per_coded_sample = 16; + if (!par->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); return -1; } @@ -68,28 +68,28 @@ static int aiff_write_header(AVFormatContext *s) /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ - avio_wb16(pb, enc->channels); /* Number of channels */ + avio_wb16(pb, par->channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ - if (!enc->bits_per_coded_sample) - enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id); - if (!enc->bits_per_coded_sample) { + if (!par->bits_per_coded_sample) + par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); + if (!par->bits_per_coded_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_coded_sample * enc->channels) >> 3; + if (!par->block_align) + par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; - avio_wb16(pb, enc->bits_per_coded_sample); /* Sample size */ + avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */ - sample_rate = av_double2int(enc->sample_rate); + sample_rate = av_double2int(par->sample_rate); avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023)); avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11); if (aifc) { - avio_wl32(pb, enc->codec_tag); + avio_wl32(pb, par->codec_tag); avio_wb16(pb, 0); } @@ -100,7 +100,7 @@ static int aiff_write_header(AVFormatContext *s) avio_wb32(pb, 0); /* Data offset */ avio_wb32(pb, 0); /* Block-size (block align) */ - avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); + avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate); /* Data is starting here */ avio_flush(pb); @@ -119,7 +119,7 @@ static int aiff_write_trailer(AVFormatContext *s) { AVIOContext *pb = s->pb; AIFFOutputContext *aiff = s->priv_data; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; /* Chunks sizes must be even */ int64_t file_size, end_size; @@ -136,7 +136,7 @@ static int aiff_write_trailer(AVFormatContext *s) /* Number of sample frames */ avio_seek(pb, aiff->frames, SEEK_SET); - avio_wb32(pb, (file_size-aiff->ssnd-12)/enc->block_align); + avio_wb32(pb, (file_size - aiff->ssnd - 12) / par->block_align); /* Sound Data chunk size */ avio_seek(pb, aiff->ssnd, SEEK_SET); diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 984bb52..f51c4e7 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -41,13 +41,6 @@ #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x) -#define REGISTER_PROTOCOL(X, x) \ - { \ - extern URLProtocol ff_##x##_protocol; \ - if (CONFIG_##X##_PROTOCOL) \ - ffurl_register_protocol(&ff_##x##_protocol); \ - } - void av_register_all(void) { static int initialized; @@ -88,11 +81,13 @@ void av_register_all(void) REGISTER_DEMUXER (CDG, cdg); REGISTER_DEMUXER (CDXL, cdxl); REGISTER_MUXER (CRC, crc); + REGISTER_MUXER (DASH, dash); REGISTER_MUXDEMUX(DAUD, daud); REGISTER_DEMUXER (DFA, dfa); REGISTER_MUXDEMUX(DIRAC, dirac); REGISTER_MUXDEMUX(DNXHD, dnxhd); REGISTER_DEMUXER (DSICIN, dsicin); + REGISTER_DEMUXER (DSS, dss); REGISTER_MUXDEMUX(DTS, dts); REGISTER_MUXDEMUX(DV, dv); REGISTER_DEMUXER (DXA, dxa); @@ -109,7 +104,8 @@ void av_register_all(void) REGISTER_MUXER (FRAMECRC, framecrc); REGISTER_MUXER (FRAMEMD5, framemd5); REGISTER_MUXDEMUX(G722, g722); - REGISTER_DEMUXER (G723_1, g723_1); + REGISTER_MUXDEMUX(G723_1, g723_1); + REGISTER_DEMUXER (G729, g729); REGISTER_MUXER (GIF, gif); REGISTER_DEMUXER (GSM, gsm); REGISTER_MUXDEMUX(GXF, gxf); @@ -161,7 +157,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(MPEGTS, mpegts); REGISTER_DEMUXER (MPEGTSRAW, mpegtsraw); REGISTER_DEMUXER (MPEGVIDEO, mpegvideo); - REGISTER_MUXER (MPJPEG, mpjpeg); + REGISTER_MUXDEMUX(MPJPEG, mpjpeg); REGISTER_DEMUXER (MSNWC_TCP, msnwc_tcp); REGISTER_DEMUXER (MTV, mtv); REGISTER_DEMUXER (MV, mv); @@ -174,8 +170,10 @@ void av_register_all(void) REGISTER_MUXER (NULL, null); REGISTER_MUXDEMUX(NUT, nut); REGISTER_DEMUXER (NUV, nuv); + REGISTER_MUXER (OGA, oga); REGISTER_MUXDEMUX(OGG, ogg); REGISTER_MUXDEMUX(OMA, oma); + REGISTER_MUXER (OPUS, opus); REGISTER_DEMUXER (PAF, paf); REGISTER_MUXDEMUX(PCM_ALAW, pcm_alaw); REGISTER_MUXDEMUX(PCM_MULAW, pcm_mulaw); @@ -209,6 +207,7 @@ void av_register_all(void) REGISTER_DEMUXER (RPL, rpl); REGISTER_MUXDEMUX(RSO, rso); REGISTER_MUXDEMUX(RTP, rtp); + REGISTER_MUXER (RTP_MPEGTS, rtp_mpegts); REGISTER_MUXDEMUX(RTSP, rtsp); REGISTER_MUXDEMUX(SAP, sap); REGISTER_DEMUXER (SDP, sdp); @@ -226,6 +225,7 @@ void av_register_all(void) REGISTER_DEMUXER (SMUSH, smush); REGISTER_DEMUXER (SOL, sol); REGISTER_MUXDEMUX(SOX, sox); + REGISTER_MUXER (SPX, spx); REGISTER_MUXDEMUX(SPDIF, spdif); REGISTER_MUXDEMUX(SRT, srt); REGISTER_DEMUXER (STR, str); @@ -258,41 +258,4 @@ void av_register_all(void) REGISTER_DEMUXER (XWMA, xwma); REGISTER_DEMUXER (YOP, yop); REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe); - - /* protocols */ - REGISTER_PROTOCOL(CONCAT, concat); - REGISTER_PROTOCOL(CRYPTO, crypto); - REGISTER_PROTOCOL(FFRTMPCRYPT, ffrtmpcrypt); - REGISTER_PROTOCOL(FFRTMPHTTP, ffrtmphttp); - REGISTER_PROTOCOL(FILE, file); - REGISTER_PROTOCOL(GOPHER, gopher); - REGISTER_PROTOCOL(HLS, hls); - REGISTER_PROTOCOL(HTTP, http); - REGISTER_PROTOCOL(HTTPPROXY, httpproxy); - REGISTER_PROTOCOL(HTTPS, https); - REGISTER_PROTOCOL(ICECAST, icecast); - REGISTER_PROTOCOL(MMSH, mmsh); - REGISTER_PROTOCOL(MMST, mmst); - REGISTER_PROTOCOL(MD5, md5); - REGISTER_PROTOCOL(PIPE, pipe); - REGISTER_PROTOCOL(RTMP, rtmp); - REGISTER_PROTOCOL(RTMPE, rtmpe); - REGISTER_PROTOCOL(RTMPS, rtmps); - REGISTER_PROTOCOL(RTMPT, rtmpt); - REGISTER_PROTOCOL(RTMPTE, rtmpte); - REGISTER_PROTOCOL(RTMPTS, rtmpts); - REGISTER_PROTOCOL(RTP, rtp); - REGISTER_PROTOCOL(SCTP, sctp); - REGISTER_PROTOCOL(SRTP, srtp); - REGISTER_PROTOCOL(TCP, tcp); - REGISTER_PROTOCOL(TLS, tls); - REGISTER_PROTOCOL(UDP, udp); - REGISTER_PROTOCOL(UNIX, unix); - - /* external libraries */ - REGISTER_PROTOCOL(LIBRTMP, librtmp); - REGISTER_PROTOCOL(LIBRTMPE, librtmpe); - REGISTER_PROTOCOL(LIBRTMPS, librtmps); - REGISTER_PROTOCOL(LIBRTMPT, librtmpt); - REGISTER_PROTOCOL(LIBRTMPTE, librtmpte); } diff --git a/libavformat/amr.c b/libavformat/amr.c index afd062e..cdba27d 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -1,6 +1,6 @@ /* * amr file format - * Copyright (c) 2001 ffmpeg project + * Copyright (c) 2001 FFmpeg project * * This file is part of Libav. * @@ -37,13 +37,13 @@ static const char AMRWB_header[] = "#!AMR-WB\n"; static int amr_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; s->priv_data = NULL; - if (enc->codec_id == AV_CODEC_ID_AMR_NB) { + if (par->codec_id == AV_CODEC_ID_AMR_NB) { avio_write(pb, AMR_header, sizeof(AMR_header) - 1); /* magic number */ - } else if (enc->codec_id == AV_CODEC_ID_AMR_WB) { + } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */ } else { return -1; @@ -89,25 +89,25 @@ static int amr_read_header(AVFormatContext *s) return -1; } - st->codec->codec_tag = MKTAG('s', 'a', 'w', 'b'); - st->codec->codec_id = AV_CODEC_ID_AMR_WB; - st->codec->sample_rate = 16000; + st->codecpar->codec_tag = MKTAG('s', 'a', 'w', 'b'); + st->codecpar->codec_id = AV_CODEC_ID_AMR_WB; + st->codecpar->sample_rate = 16000; } else { - st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r'); - st->codec->codec_id = AV_CODEC_ID_AMR_NB; - st->codec->sample_rate = 8000; + st->codecpar->codec_tag = MKTAG('s', 'a', 'm', 'r'); + st->codecpar->codec_id = AV_CODEC_ID_AMR_NB; + st->codecpar->sample_rate = 8000; } - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; } static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) { - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; int read, size = 0, toc, mode; int64_t pos = avio_tell(s->pb); @@ -115,17 +115,17 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); } - // FIXME this is wrong, this should rather be in a AVParset + // FIXME this is wrong, this should rather be in an AVParser toc = avio_r8(s->pb); mode = (toc >> 3) & 0x0F; - if (enc->codec_id == AV_CODEC_ID_AMR_NB) { + if (par->codec_id == AV_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 == AV_CODEC_ID_AMR_WB) { + } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { static const uint8_t packed_size[16] = { 18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1 }; @@ -139,16 +139,16 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); /* Both AMR formats have 50 frames per second */ - s->streams[0]->codec->bit_rate = size*8*50; + s->streams[0]->codecpar->bit_rate = size*8*50; pkt->stream_index = 0; pkt->pos = pos; pkt->data[0] = toc; - pkt->duration = enc->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320; + pkt->duration = par->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320; read = avio_read(s->pb, pkt->data + 1, size - 1); if (read != size - 1) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } diff --git a/libavformat/anm.c b/libavformat/anm.c index f781492..2ab6712 100644 --- a/libavformat/anm.c +++ b/libavformat/anm.c @@ -28,13 +28,13 @@ #include "avformat.h" #include "internal.h" -typedef struct { +typedef struct Page { int base_record; unsigned int nb_records; int size; } Page; -typedef struct { +typedef struct AnmDemuxContext { unsigned int nb_pages; /**< total pages in file */ unsigned int nb_records; /**< total records in file */ int page_table_offset; @@ -100,11 +100,11 @@ static int read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_ANM; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = avio_rl16(pb); - st->codec->height = avio_rl16(pb); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_ANM; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = avio_rl16(pb); + st->codecpar->height = avio_rl16(pb); if (avio_r8(pb) != 0) goto invalid; avio_skip(pb, 1); /* frame rate multiplier info */ @@ -132,12 +132,12 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 58); /* color cycling and palette data */ - st->codec->extradata_size = 16*8 + 4*256; - st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) { + st->codecpar->extradata_size = 16*8 + 4*256; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) { return AVERROR(ENOMEM); } - ret = avio_read(pb, st->codec->extradata, st->codec->extradata_size); + ret = avio_read(pb, st->codecpar->extradata, st->codecpar->extradata_size); if (ret < 0) return ret; diff --git a/libavformat/apc.c b/libavformat/apc.c index 0b6c583..40ecdf2 100644 --- a/libavformat/apc.c +++ b/libavformat/apc.c @@ -45,33 +45,33 @@ static int apc_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_APC; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_APC; avio_rl32(pb); /* number of samples */ - st->codec->sample_rate = avio_rl32(pb); + st->codecpar->sample_rate = avio_rl32(pb); - st->codec->extradata_size = 2 * 4; - st->codec->extradata = av_malloc(st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata_size = 2 * 4; + st->codecpar->extradata = av_malloc(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); /* initial predictor values for adpcm decoder */ - avio_read(pb, st->codec->extradata, 2 * 4); + avio_read(pb, st->codecpar->extradata, 2 * 4); if (avio_rl32(pb)) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = st->codec->bits_per_coded_sample * st->codec->channels - * st->codec->sample_rate; - st->codec->block_align = 1; + st->codecpar->bits_per_coded_sample = 4; + st->codecpar->bit_rate = st->codecpar->bits_per_coded_sample * st->codecpar->channels + * st->codecpar->sample_rate; + st->codecpar->block_align = 1; return 0; } diff --git a/libavformat/ape.c b/libavformat/ape.c index d967a5d..bcc1f7a 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -42,7 +42,7 @@ #define APE_EXTRADATA_SIZE 6 -typedef struct { +typedef struct APEFrame { int64_t pos; int nblocks; int size; @@ -50,7 +50,7 @@ typedef struct { int64_t pts; } APEFrame; -typedef struct { +typedef struct APEContext { /* Derived fields */ uint32_t junklength; uint32_t firstframe; @@ -344,23 +344,23 @@ static int ape_read_header(AVFormatContext * s) total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_APE; - st->codec->codec_tag = MKTAG('A', 'P', 'E', ' '); - st->codec->channels = ape->channels; - st->codec->sample_rate = ape->samplerate; - st->codec->bits_per_coded_sample = ape->bps; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_APE; + st->codecpar->codec_tag = MKTAG('A', 'P', 'E', ' '); + st->codecpar->channels = ape->channels; + st->codecpar->sample_rate = ape->samplerate; + st->codecpar->bits_per_coded_sample = ape->bps; st->nb_frames = ape->totalframes; st->start_time = 0; st->duration = total_blocks / MAC_SUBFRAME_SIZE; avpriv_set_pts_info(st, 64, MAC_SUBFRAME_SIZE, ape->samplerate); - st->codec->extradata = av_malloc(APE_EXTRADATA_SIZE); - st->codec->extradata_size = APE_EXTRADATA_SIZE; - AV_WL16(st->codec->extradata + 0, ape->fileversion); - AV_WL16(st->codec->extradata + 2, ape->compressiontype); - AV_WL16(st->codec->extradata + 4, ape->formatflags); + st->codecpar->extradata = av_malloc(APE_EXTRADATA_SIZE); + st->codecpar->extradata_size = APE_EXTRADATA_SIZE; + AV_WL16(st->codecpar->extradata + 0, ape->fileversion); + AV_WL16(st->codecpar->extradata + 2, ape->compressiontype); + AV_WL16(st->codecpar->extradata + 4, ape->formatflags); pts = 0; for (i = 0; i < ape->totalframes; i++) { diff --git a/libavformat/apetag.c b/libavformat/apetag.c index bd8d0ed..fd26b51 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -31,8 +31,9 @@ #define APE_TAG_VERSION 2000 #define APE_TAG_FOOTER_BYTES 32 +#define APE_TAG_HEADER_BYTES 32 #define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) -#define APE_TAG_FLAG_CONTAINS_FOOTER (1 << 30) +#define APE_TAG_FLAG_LACKS_FOOTER (1 << 30) #define APE_TAG_FLAG_IS_HEADER (1 << 29) #define APE_TAG_FLAG_IS_BINARY (1 << 1) @@ -40,7 +41,7 @@ static int ape_tag_read_field(AVFormatContext *s) { AVIOContext *pb = s->pb; uint8_t key[1024], *value; - uint32_t size, flags; + int64_t size, flags; int i, c; size = avio_rl32(pb); /* field size */ @@ -57,7 +58,7 @@ static int ape_tag_read_field(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key); return -1; } - if (size > INT32_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + if (size > INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { av_log(s, AV_LOG_ERROR, "APE tag size too large.\n"); return AVERROR_INVALIDDATA; } @@ -87,22 +88,22 @@ static int ape_tag_read_field(AVFormatContext *s) } st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = id; st->attached_pic = pkt; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; } else { - st->codec->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - if (avio_read(pb, st->codec->extradata, size) != size) { - av_freep(&st->codec->extradata); + if (avio_read(pb, st->codecpar->extradata, size) != size) { + av_freep(&st->codecpar->extradata); return AVERROR(EIO); } - st->codec->extradata_size = size; - st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; + st->codecpar->extradata_size = size; + st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; } } else { value = av_malloc(size+1); @@ -154,7 +155,6 @@ int64_t ff_ape_parse_tag(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Invalid tag size %"PRIu32".\n", tag_bytes); return 0; } - tag_start = file_size - tag_bytes - APE_TAG_FOOTER_BYTES; fields = avio_rl32(pb); /* number of fields */ if (fields > 65536) { @@ -170,6 +170,11 @@ int64_t ff_ape_parse_tag(AVFormatContext *s) avio_seek(pb, file_size - tag_bytes, SEEK_SET); + if (val & APE_TAG_FLAG_CONTAINS_HEADER) + tag_bytes += APE_TAG_HEADER_BYTES; + + tag_start = file_size - tag_bytes; + for (i=0; ipb, 0); // reserve space for tag count // flags - avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | - APE_TAG_FLAG_IS_HEADER); + avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_IS_HEADER); ffio_fill(s->pb, 0, 8); // reserved while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { @@ -217,7 +221,7 @@ int ff_ape_write_tag(AVFormatContext *s) avio_wl32(s->pb, count); // tag count // flags - avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); + avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER); ffio_fill(s->pb, 0, 8); // reserved // update values in the header diff --git a/libavformat/asf.h b/libavformat/asf.h index 2f6722a..6130e7a 100644 --- a/libavformat/asf.h +++ b/libavformat/asf.h @@ -28,27 +28,6 @@ #define PACKET_SIZE 3200 -typedef struct ASFStream { - 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; - - int64_t packet_pos; - - uint16_t stream_language_index; - - int palette_changed; - uint32_t palette[256]; -} ASFStream; - typedef struct ASFMainHeader { ff_asf_guid guid; ///< generated by client computer uint64_t file_size; /**< in bytes @@ -61,7 +40,7 @@ typedef struct ASFMainHeader { * invalid if broadcasting (could be ignored) */ uint32_t preroll; /**< timestamp of the first packet, in milliseconds * if nonzero - subtract from time */ - uint32_t ignore; ///< preroll is 64bit - but let's just ignore it + uint32_t ignore; ///< preroll is 64 bits - but let's just ignore it uint32_t flags; /**< 0x01 - broadcast * 0x02 - seekable * rest is reserved should be 0 */ diff --git a/libavformat/asfcrypt.c b/libavformat/asfcrypt.c index c261475..891d4db 100644 --- a/libavformat/asfcrypt.c +++ b/libavformat/asfcrypt.c @@ -146,8 +146,8 @@ static uint64_t multiswap_dec(const uint32_t keys[12], void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) { - struct AVDES des; - struct AVRC4 rc4; + struct AVDES *des; + struct AVRC4 *rc4; int num_qwords = len >> 3; uint8_t *qwords = data; uint64_t rc4buff[8] = { 0 }; @@ -160,19 +160,26 @@ void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) data[i] ^= key[i]; return; } + des = av_des_alloc(); + rc4 = av_rc4_alloc(); + if (!des || !rc4) { + av_freep(&des); + av_freep(&rc4); + return; + } - av_rc4_init(&rc4, key, 12 * 8, 1); - av_rc4_crypt(&rc4, (uint8_t *)rc4buff, NULL, sizeof(rc4buff), NULL, 1); + av_rc4_init(rc4, key, 12 * 8, 1); + av_rc4_crypt(rc4, (uint8_t *)rc4buff, NULL, sizeof(rc4buff), NULL, 1); multiswap_init((uint8_t *)rc4buff, ms_keys); packetkey = AV_RN64(&qwords[num_qwords * 8 - 8]); packetkey ^= rc4buff[7]; - av_des_init(&des, key + 12, 64, 1); - av_des_crypt(&des, (uint8_t *)&packetkey, (uint8_t *)&packetkey, 1, NULL, 1); + av_des_init(des, key + 12, 64, 1); + av_des_crypt(des, (uint8_t *)&packetkey, (uint8_t *)&packetkey, 1, NULL, 1); packetkey ^= rc4buff[6]; - av_rc4_init(&rc4, (uint8_t *)&packetkey, 64, 1); - av_rc4_crypt(&rc4, data, data, len, NULL, 1); + av_rc4_init(rc4, (uint8_t *)&packetkey, 64, 1); + av_rc4_crypt(rc4, data, data, len, NULL, 1); ms_state = 0; for (i = 0; i < num_qwords - 1; i++, qwords += 8) @@ -182,4 +189,7 @@ void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) packetkey = av_le2ne64(packetkey); packetkey = multiswap_dec(ms_keys, ms_state, packetkey); AV_WL64(qwords, packetkey); + + av_free(rc4); + av_free(des); } diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index 85e800d..bda5b46 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -1,6 +1,6 @@ /* - * ASF compatible demuxer - * Copyright (c) 2000, 2001 Fabrice Bellard + * Microsoft Advanced Streaming Format demuxer + * Copyright (c) 2014 Alexandra Hájková * * This file is part of Libav. * @@ -19,10 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include "libavutil/attributes.h" -#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bswap.h" #include "libavutil/common.h" @@ -30,6 +27,8 @@ #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/time_internal.h" + #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" @@ -39,151 +38,326 @@ #include "asf.h" #include "asfcrypt.h" -typedef struct { - const AVClass *class; - int asfid2avid[128]; ///< conversion table from asf ID 2 AVStream ID - ASFStream streams[128]; ///< it's max number and it's not that big - uint32_t stream_bitrates[128]; ///< max number of streams, bitrate for each (for streaming) - AVRational dar[128]; - char stream_languages[128][6]; ///< max number of streams, language for each (RFC1766, e.g. en-US) - /* non streamed additonnal info */ - /* packet filling */ - int packet_size_left; - /* only for reading */ - uint64_t data_offset; ///< beginning 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; - unsigned int packet_frag_offset; - unsigned int packet_frag_size; - int64_t 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; - - ASFStream *asf_st; ///< currently decoded stream - - int no_resync_search; +#define ASF_BOOL 0x2 +#define ASF_WORD 0x5 +#define ASF_GUID 0x6 +#define ASF_DWORD 0x3 +#define ASF_QWORD 0x4 +#define ASF_UNICODE 0x0 +#define ASF_FLAG_BROADCAST 0x1 +#define ASF_BYTE_ARRAY 0x1 +#define ASF_TYPE_AUDIO 0x2 +#define ASF_TYPE_VIDEO 0x1 +#define ASF_STREAM_NUM 0x7F +#define ASF_MAX_STREAMS 128 +#define BMP_HEADER_SIZE 40 +#define ASF_NUM_OF_PAYLOADS 0x3F +#define ASF_ERROR_CORRECTION_LENGTH_TYPE 0x60 +#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2 + +typedef struct GUIDParseTable { + const char *name; + ff_asf_guid guid; + int (*read_object)(AVFormatContext *, const struct GUIDParseTable *); + int is_subobject; +} GUIDParseTable; + +typedef struct ASFPacket { + AVPacket avpkt; + int64_t dts; + uint32_t frame_num; // ASF payloads with the same number are parts of the same frame + int flags; + int data_size; + int duration; + int size_left; + uint8_t stream_index; +} ASFPacket; + +typedef struct ASFStream { + uint8_t stream_index; // from packet header + int index; // stream index in AVFormatContext, set in asf_read_stream_properties + int type; + int indexed; // added index entries from the Simple Index Object or not + int8_t span; // for deinterleaving + uint16_t virtual_pkt_len; + uint16_t virtual_chunk_len; + int16_t lang_idx; + ASFPacket pkt; +} ASFStream; + +typedef struct ASFStreamData{ + char langs[32]; + AVDictionary *asf_met; // for storing per-stream metadata + AVRational aspect_ratio; +} ASFStreamData; + +typedef struct ASFContext { + int data_reached; + int is_simple_index; // is simple index present or not 1/0 + int is_header; + + uint64_t preroll; + uint64_t nb_packets; // ASF packets + uint32_t packet_size; + int64_t send_time; + int duration; + + uint32_t b_flags; // flags with broadcast flag + uint32_t prop_flags; // file properties object flags + + uint64_t data_size; // data object size + uint64_t unknown_size; // size of the unknown object + + int64_t offset; // offset of the current object + + int64_t data_offset; + int64_t first_packet_offset; // packet offset + int64_t unknown_offset; // for top level header objects or subobjects without specified behavior + + // ASF file must not contain more than 128 streams according to the specification + ASFStream *asf_st[ASF_MAX_STREAMS]; + ASFStreamData asf_sd[ASF_MAX_STREAMS]; + int nb_streams; + + int stream_index; // from packet header, for the subpayload case + + // packet parameters + uint64_t sub_header_offset; // offset of subpayload header + int64_t sub_dts; + uint8_t dts_delta; // for subpayloads + uint32_t packet_size_internal; // packet size stored inside ASFPacket, can be 0 + int64_t packet_offset; // offset of the current packet inside Data Object + uint32_t pad_len; // padding after payload + uint32_t rep_data_len; + + // packet state + uint64_t sub_left; // subpayloads left or not + unsigned int nb_sub; // number of subpayloads read so far from the current ASF packet + uint16_t mult_sub_len; // total length of subpayloads array inside multiple payload + uint64_t nb_mult_left; // multiple payloads left + int return_subpayload; + enum { + PARSE_PACKET_HEADER, + READ_SINGLE, + READ_MULTI, + READ_MULTI_SUB + } state; } ASFContext; -static const AVOption options[] = { - { "no_resync_search", "Don't try to resynchronize by looking for a certain optional start code", offsetof(ASFContext, no_resync_search), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; +static int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size); +static const GUIDParseTable *find_guid(ff_asf_guid guid); -static const AVClass asf_class = { - .class_name = "asf demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; +static int asf_probe(AVProbeData *pd) +{ + /* check file header */ + if (!ff_guidcmp(pd->buf, &ff_asf_header)) + return AVPROBE_SCORE_MAX; + else + return 0; +} -#undef NDEBUG -#include +static void swap_guid(ff_asf_guid guid) +{ + FFSWAP(unsigned char, guid[0], guid[3]); + FFSWAP(unsigned char, guid[1], guid[2]); + FFSWAP(unsigned char, guid[4], guid[5]); + FFSWAP(unsigned char, guid[6], guid[7]); +} -#define ASF_MAX_STREAMS 127 -#define FRAME_HEADER_SIZE 17 -// Fix Me! FRAME_HEADER_SIZE may be different. +static void align_position(AVIOContext *pb, int64_t offset, uint64_t size) +{ + if (avio_tell(pb) != offset + size) + avio_seek(pb, offset + size, SEEK_SET); +} -static const ff_asf_guid index_guid = { - 0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb -}; +static int asf_read_unknown(AVFormatContext *s, const GUIDParseTable *g) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t size = avio_rl64(pb); + int ret; -#ifdef DEBUG -static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */ - 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 -}; + if (size > INT64_MAX) + return AVERROR_INVALIDDATA; -#define PRINT_IF_GUID(g, cmp) \ - if (!ff_guidcmp(g, &cmp)) \ - av_dlog(NULL, "(GUID: %s) ", # cmp) + if (asf->is_header) + asf->unknown_size = size; + asf->is_header = 0; + if (!g->is_subobject) { + if (!(ret = strcmp(g->name, "Header Extension"))) + avio_skip(pb, 22); // skip reserved fields and Data Size + if ((ret = detect_unknown_subobject(s, asf->unknown_offset, + asf->unknown_size)) < 0) + return ret; + } else { + if (size < 24) { + av_log(s, AV_LOG_ERROR, "Too small size %"PRIu64" (< 24).\n", size); + return AVERROR_INVALIDDATA; + } + avio_skip(pb, size - 24); + } + + return 0; +} -static void print_guid(ff_asf_guid *g) +static int get_asf_string(AVIOContext *pb, int maxlen, char *buf, int buflen) { - int i; - PRINT_IF_GUID(g, ff_asf_header); - else PRINT_IF_GUID(g, ff_asf_file_header); - else PRINT_IF_GUID(g, ff_asf_stream_header); - else PRINT_IF_GUID(g, ff_asf_audio_stream); - else PRINT_IF_GUID(g, ff_asf_audio_conceal_none); - else PRINT_IF_GUID(g, ff_asf_video_stream); - else PRINT_IF_GUID(g, ff_asf_video_conceal_none); - else PRINT_IF_GUID(g, ff_asf_command_stream); - else PRINT_IF_GUID(g, ff_asf_comment_header); - else PRINT_IF_GUID(g, ff_asf_codec_comment_header); - else PRINT_IF_GUID(g, ff_asf_codec_comment1_header); - else PRINT_IF_GUID(g, ff_asf_data_header); - else PRINT_IF_GUID(g, index_guid); - else PRINT_IF_GUID(g, ff_asf_head1_guid); - else PRINT_IF_GUID(g, ff_asf_head2_guid); - else PRINT_IF_GUID(g, ff_asf_my_guid); - else PRINT_IF_GUID(g, ff_asf_ext_stream_header); - else PRINT_IF_GUID(g, ff_asf_extended_content_header); - else PRINT_IF_GUID(g, ff_asf_ext_stream_embed_stream_header); - else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream); - else PRINT_IF_GUID(g, ff_asf_metadata_header); - else PRINT_IF_GUID(g, ff_asf_metadata_library_header); - else PRINT_IF_GUID(g, ff_asf_marker_header); - else PRINT_IF_GUID(g, stream_bitrate_guid); - else PRINT_IF_GUID(g, ff_asf_language_guid); - else - av_dlog(NULL, "(GUID: unknown) "); - for (i = 0; i < 16; i++) - av_dlog(NULL, " 0x%02x,", (*g)[i]); - av_dlog(NULL, "}\n"); + char *q = buf; + int ret = 0; + if (buflen <= 0) + return AVERROR(EINVAL); + while (ret + 1 < maxlen) { + uint8_t tmp; + uint32_t ch; + GET_UTF16(ch, (ret += 2) <= maxlen ? avio_rl16(pb) : 0, break;); + PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;) + } + *q = 0; + + return ret; } -#undef PRINT_IF_GUID -#else -#define print_guid(g) -#endif -static int asf_probe(AVProbeData *pd) +static int asf_read_marker(AVFormatContext *s, const GUIDParseTable *g) { - /* check file header */ - if (!ff_guidcmp(pd->buf, &ff_asf_header)) - return AVPROBE_SCORE_MAX; - else - return 0; + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t size = avio_rl64(pb); + int i, nb_markers, ret; + size_t len; + char name[1024]; + + avio_skip(pb, 8); + avio_skip(pb, 8); // skip reserved GUID + nb_markers = avio_rl32(pb); + avio_skip(pb, 2); // skip reserved field + len = avio_rl16(pb); + for (i = 0; i < len; i++) + avio_skip(pb, 1); + + for (i = 0; i < nb_markers; i++) { + int64_t pts; + + avio_skip(pb, 8); + pts = avio_rl64(pb); + pts -= asf->preroll * 10000; + avio_skip(pb, 2); // entry length + avio_skip(pb, 4); // send time + avio_skip(pb, 4); // flags + len = avio_rl32(pb); + + if ((ret = avio_get_str16le(pb, len, name, + sizeof(name))) < len) + avio_skip(pb, len - ret); + avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pts, + AV_NOPTS_VALUE, name); + } + align_position(pb, asf->offset, size); + + return 0; +} + +static int asf_read_metadata(AVFormatContext *s, const char *title, uint16_t len, + unsigned char *ch, uint16_t buflen) +{ + AVIOContext *pb = s->pb; + + avio_get_str16le(pb, len, ch, buflen); + if (ch[0]) { + if (av_dict_set(&s->metadata, title, ch, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } + + return 0; } -/* size of type 2 (BOOL) is 32bit for "Extended Content Description Object" - * but 16 bit for "Metadata Object" and "Metadata Library Object" */ -static int get_value(AVIOContext *pb, int type, int type2_size) +static int asf_read_value(AVFormatContext *s, const uint8_t *name, + uint16_t val_len, int type, AVDictionary **met) { + int ret; + uint8_t *value; + uint16_t buflen = 2 * val_len + 1; + AVIOContext *pb = s->pb; + + value = av_malloc(buflen); + if (!value) + return AVERROR(ENOMEM); + if (type == ASF_UNICODE) { + // get_asf_string reads UTF-16 and converts it to UTF-8 which needs longer buffer + if ((ret = get_asf_string(pb, val_len, value, buflen)) < 0) + goto failed; + if (av_dict_set(met, name, value, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } else { + char buf[256]; + if (val_len > sizeof(buf)) { + ret = AVERROR_INVALIDDATA; + goto failed; + } + if ((ret = avio_read(pb, value, val_len)) < 0) + goto failed; + if (ret < 2 * val_len) + value[ret] = '\0'; + else + value[2 * val_len - 1] = '\0'; + snprintf(buf, sizeof(buf), "%s", value); + if (av_dict_set(met, name, buf, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } + av_freep(&value); + + return 0; + +failed: + av_freep(&value); + return ret; +} +static int asf_read_generic_value(AVIOContext *pb, int type, uint64_t *value) +{ + switch (type) { - case 2: - return (type2_size == 32) ? avio_rl32(pb) : avio_rl16(pb); - case 3: - return avio_rl32(pb); - case 4: - return avio_rl64(pb); - case 5: - return avio_rl16(pb); + case ASF_BOOL: + *value = avio_rl16(pb); + break; + case ASF_DWORD: + *value = avio_rl32(pb); + break; + case ASF_QWORD: + *value = avio_rl64(pb); + break; + case ASF_WORD: + *value = avio_rl16(pb); + break; default: - return INT_MIN; + return AVERROR_INVALIDDATA; } + + return 0; +} + +static int asf_set_metadata(AVFormatContext *s, const uint8_t *name, + int type, AVDictionary **met) +{ + AVIOContext *pb = s->pb; + uint64_t value; + char buf[32]; + int ret; + + ret = asf_read_generic_value(pb, type, &value); + if (ret < 0) + return ret; + + snprintf(buf, sizeof(buf), "%"PRIu64, value); + if (av_dict_set(met, name, buf, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + + return 0; } /* MSDN claims that this should be "compatible with the ID3 frame, APIC", * but in reality this is only loosely similar */ static int asf_read_picture(AVFormatContext *s, int len) { + ASFContext *asf = s->priv_data; AVPacket pkt = { 0 }; const CodecMime *mime = ff_id3v2_mime_tags; enum AVCodecID id = AV_CODEC_ID_NONE; @@ -191,6 +365,7 @@ static int asf_read_picture(AVFormatContext *s, int len) uint8_t *desc = NULL; AVStream *st = NULL; int ret, type, picsize, desc_len; + ASFStream *asf_st; /* type + picsize + mime + desc */ if (len < 1 + 4 + 2 + 2) { @@ -247,29 +422,40 @@ static int asf_read_picture(AVFormatContext *s, int len) ret = AVERROR(ENOMEM); goto fail; } + asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st)); + asf_st = asf->asf_st[asf->nb_streams]; + if (!asf_st) { + ret = AVERROR(ENOMEM); + goto fail; + } + st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = id; + st->codecpar->codec_type = asf_st->type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = id; st->attached_pic = pkt; - st->attached_pic.stream_index = st->index; + st->attached_pic.stream_index = asf_st->index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; - if (*desc) - av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); - else + asf->nb_streams++; + + if (*desc) { + if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } else av_freep(&desc); - av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0); + if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); return 0; fail: av_freep(&desc); - av_free_packet(&pkt); + av_packet_unref(&pkt); return ret; } -static void get_id3_tag(AVFormatContext *s, int len) +static void get_id3_tag(AVFormatContext *s) { ID3v2ExtraMeta *id3v2_extra_meta = NULL; @@ -279,1232 +465,1318 @@ static void get_id3_tag(AVFormatContext *s, int len) ff_id3v2_free_extra_meta(&id3v2_extra_meta); } -static void get_tag(AVFormatContext *s, const char *key, int type, int len, int type2_size) +static int process_metadata(AVFormatContext *s, const uint8_t *name, uint16_t name_len, + uint16_t val_len, uint16_t type, AVDictionary **met) { - char *value; - int64_t off = avio_tell(s->pb); + int ret; + ff_asf_guid guid; - if ((unsigned)len >= (UINT_MAX - 1) / 2) - return; - - value = av_malloc(2 * len + 1); - if (!value) - goto finish; - - if (type == 0) { // UTF16-LE - avio_get_str16le(s->pb, len, value, 2 * len + 1); - } else if (type == 1) { // byte array - if (!strcmp(key, "WM/Picture")) { // handle cover art - asf_read_picture(s, len); - } else if (!strcmp(key, "ID3")) { // handle ID3 tag - get_id3_tag(s, len); - } else { - av_log(s, AV_LOG_VERBOSE, "Unsupported byte array in tag %s.\n", key); + if (val_len) { + switch (type) { + case ASF_UNICODE: + asf_read_value(s, name, val_len, type, met); + break; + case ASF_BYTE_ARRAY: + if (!strcmp(name, "WM/Picture")) // handle cover art + asf_read_picture(s, val_len); + else if (!strcmp(name, "ID3")) // handle ID3 tag + get_id3_tag(s); + else + asf_read_value(s, name, val_len, type, met); + break; + case ASF_GUID: + ff_get_guid(s->pb, &guid); + break; + default: + if ((ret = asf_set_metadata(s, name, type, met)) < 0) + return ret; + break; } - goto finish; - } else if (type > 1 && type <= 5) { // boolean or DWORD or QWORD or WORD - uint64_t num = get_value(s->pb, type, type2_size); - snprintf(value, len, "%"PRIu64, num); - } else if (type == 6) { // (don't) handle GUID - av_log(s, AV_LOG_DEBUG, "Unsupported GUID value in tag %s.\n", key); - goto finish; - } else { - av_log(s, AV_LOG_DEBUG, - "Unsupported value type %d in tag %s.\n", type, key); - goto finish; } - if (*value) - av_dict_set(&s->metadata, key, value, 0); -finish: - av_freep(&value); - avio_seek(s->pb, off + len, SEEK_SET); + return 0; } -static int asf_read_file_properties(AVFormatContext *s, int64_t size) +static int asf_read_ext_content(AVFormatContext *s, const GUIDParseTable *g) { - ASFContext *asf = s->priv_data; - AVIOContext *pb = s->pb; + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t size = avio_rl64(pb); + uint16_t nb_desc = avio_rl16(pb); + int i, ret; - ff_get_guid(pb, &asf->hdr.guid); - asf->hdr.file_size = avio_rl64(pb); - asf->hdr.create_time = avio_rl64(pb); - avio_rl64(pb); /* number of packets */ - asf->hdr.play_time = avio_rl64(pb); - asf->hdr.send_time = avio_rl64(pb); - asf->hdr.preroll = avio_rl32(pb); - asf->hdr.ignore = avio_rl32(pb); - asf->hdr.flags = avio_rl32(pb); - asf->hdr.min_pktsize = avio_rl32(pb); - asf->hdr.max_pktsize = avio_rl32(pb); - if (asf->hdr.min_pktsize >= (1U << 29)) - return AVERROR_INVALIDDATA; - asf->hdr.max_bitrate = avio_rl32(pb); - s->packet_size = asf->hdr.max_pktsize; + for (i = 0; i < nb_desc; i++) { + uint16_t name_len, type, val_len; + uint8_t *name = NULL; + name_len = avio_rl16(pb); + if (!name_len) + return AVERROR_INVALIDDATA; + name = av_malloc(name_len); + if (!name) + return AVERROR(ENOMEM); + avio_get_str16le(pb, name_len, name, + name_len); + type = avio_rl16(pb); + // BOOL values are 16 bits long in the Metadata Object + // but 32 bits long in the Extended Content Description Object + if (type == ASF_BOOL) + type = ASF_DWORD; + val_len = avio_rl16(pb); + + ret = process_metadata(s, name, name_len, val_len, type, &s->metadata); + av_freep(&name); + if (ret < 0) + return ret; + } + + align_position(pb, asf->offset, size); return 0; } -static int asf_read_stream_properties(AVFormatContext *s, int64_t size) +static AVStream *find_stream(AVFormatContext *s, uint16_t st_num) { + AVStream *st = NULL; ASFContext *asf = s->priv_data; - AVIOContext *pb = s->pb; - AVStream *st; - ASFStream *asf_st; - ff_asf_guid g; - enum AVMediaType type; - int type_specific_size, sizeX; - unsigned int tag1; - int64_t pos1, pos2, start_time; - int test_for_ext_stream_audio, is_dvr_ms_audio = 0; + int i; - if (s->nb_streams == ASF_MAX_STREAMS) { - av_log(s, AV_LOG_ERROR, "too many streams\n"); - return AVERROR(EINVAL); + for (i = 0; i < asf->nb_streams; i++) { + if (asf->asf_st[i]->stream_index == st_num) { + st = s->streams[asf->asf_st[i]->index]; + break; + } } - pos1 = avio_tell(pb); - - st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); - avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ - asf_st = av_mallocz(sizeof(ASFStream)); - if (!asf_st) - return AVERROR(ENOMEM); - st->priv_data = asf_st; - st->start_time = 0; - start_time = asf->hdr.preroll; + return st; +} - asf_st->stream_language_index = 128; // invalid stream index means no language info +static int asf_store_aspect_ratio(AVFormatContext *s, uint8_t st_num, uint8_t *name, int type) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t value = 0; + int ret; - if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming... - st->duration = asf->hdr.play_time / - (10000000 / 1000) - start_time; - } - ff_get_guid(pb, &g); + ret = asf_read_generic_value(pb, type, &value); + if (ret < 0) + return ret; - test_for_ext_stream_audio = 0; - if (!ff_guidcmp(&g, &ff_asf_audio_stream)) { - type = AVMEDIA_TYPE_AUDIO; - } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) { - type = AVMEDIA_TYPE_VIDEO; - } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) { - type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MJPEG; - } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) { - type = AVMEDIA_TYPE_DATA; - } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) { - test_for_ext_stream_audio = 1; - type = AVMEDIA_TYPE_UNKNOWN; - } else { - return -1; - } - ff_get_guid(pb, &g); - avio_skip(pb, 8); /* total_size */ - type_specific_size = avio_rl32(pb); - avio_rl32(pb); - st->id = avio_rl16(pb) & 0x7f; /* stream id */ - // mapping of asf ID to AV stream ID; - asf->asfid2avid[st->id] = s->nb_streams - 1; - - avio_rl32(pb); - - if (test_for_ext_stream_audio) { - ff_get_guid(pb, &g); - if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) { - type = AVMEDIA_TYPE_AUDIO; - is_dvr_ms_audio = 1; - ff_get_guid(pb, &g); - avio_rl32(pb); - avio_rl32(pb); - avio_rl32(pb); - ff_get_guid(pb, &g); - avio_rl32(pb); - } + if (st_num < ASF_MAX_STREAMS) { + if (!strcmp(name, "AspectRatioX")) + asf->asf_sd[st_num].aspect_ratio.num = value; + else + asf->asf_sd[st_num].aspect_ratio.den = value; } + return 0; +} - st->codec->codec_type = type; - if (type == AVMEDIA_TYPE_AUDIO) { - int ret = ff_get_wav_header(pb, st->codec, type_specific_size); - if (ret < 0) - return ret; - if (is_dvr_ms_audio) { - // codec_id and codec_tag are unreliable in dvr_ms - // files. Set them later by probing stream. - st->codec->codec_id = AV_CODEC_ID_PROBE; - st->codec->codec_tag = 0; - } - if (st->codec->codec_id == AV_CODEC_ID_AAC) - st->need_parsing = AVSTREAM_PARSE_NONE; - else - st->need_parsing = AVSTREAM_PARSE_FULL; - /* We have to init the frame size at some point .... */ - pos2 = avio_tell(pb); - if (size >= (pos2 + 8 - pos1 + 24)) { - asf_st->ds_span = avio_r8(pb); - asf_st->ds_packet_size = avio_rl16(pb); - asf_st->ds_chunk_size = avio_rl16(pb); - avio_rl16(pb); // ds_data_size - avio_r8(pb); // 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_packet_size % asf_st->ds_chunk_size) - asf_st->ds_span = 0; // disable descrambling - } - } else if (type == AVMEDIA_TYPE_VIDEO && - size - (avio_tell(pb) - pos1 + 24) >= 51) { - avio_rl32(pb); - avio_rl32(pb); - avio_r8(pb); - avio_rl16(pb); /* size */ - sizeX = avio_rl32(pb); /* size */ - st->codec->width = avio_rl32(pb); - st->codec->height = avio_rl32(pb); - /* not available for asf */ - avio_rl16(pb); /* panes */ - st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ - tag1 = avio_rl32(pb); - avio_skip(pb, 20); - if (sizeX > 40) { - st->codec->extradata_size = sizeX - 40; - st->codec->extradata = av_mallocz(st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - avio_read(pb, st->codec->extradata, st->codec->extradata_size); - } +static int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t size = avio_rl64(pb); + uint16_t nb_recs = avio_rl16(pb); // number of records in the Description Records list + int i, ret; - /* Extract palette from extradata if bpp <= 8 */ - /* This code assumes that extradata contains only palette */ - /* This is true for all paletted codecs implemented in libavcodec */ - if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { -#if HAVE_BIGENDIAN - int i; - for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE) / 4; i++) - asf_st->palette[i] = av_bswap32(((uint32_t *)st->codec->extradata)[i]); -#else - memcpy(asf_st->palette, st->codec->extradata, - FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); -#endif - asf_st->palette_changed = 1; - } + for (i = 0; i < nb_recs; i++) { + uint16_t name_len, buflen, type, val_len, st_num; + uint8_t *name = NULL; - st->codec->codec_tag = tag1; - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); - if (tag1 == MKTAG('D', 'V', 'R', ' ')) { - st->need_parsing = AVSTREAM_PARSE_FULL; - /* issue658 contains wrong w/h and MS even puts a fake seq header - * with wrong w/h in extradata while a correct one is in the stream. - * maximum lameness */ - st->codec->width = - st->codec->height = 0; - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; + avio_skip(pb, 2); // skip reserved field + st_num = avio_rl16(pb); + name_len = avio_rl16(pb); + buflen = 2 * name_len + 1; + if (!name_len) + break; + type = avio_rl16(pb); + val_len = avio_rl32(pb); + name = av_malloc(buflen); + if (!name) + return AVERROR(ENOMEM); + avio_get_str16le(pb, name_len, name, + buflen); + if (!strcmp(name, "AspectRatioX") || !strcmp(name, "AspectRatioY")) { + ret = asf_store_aspect_ratio(s, st_num, name, type); + if (ret < 0) { + av_freep(&name); + break; + } + } else { + if (st_num < ASF_MAX_STREAMS) { + if ((ret = process_metadata(s, name, name_len, val_len, type, + &asf->asf_sd[st_num].asf_met)) < 0) { + av_freep(&name); + break; + } + } } - if (st->codec->codec_id == AV_CODEC_ID_H264) - st->need_parsing = AVSTREAM_PARSE_FULL_ONCE; + av_freep(&name); } - pos2 = avio_tell(pb); - avio_skip(pb, size - (pos2 - pos1 + 24)); + align_position(pb, asf->offset, size); return 0; } -static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) +static int asf_read_content_desc(AVFormatContext *s, const GUIDParseTable *g) { ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; - ff_asf_guid g; - int ext_len, payload_ext_ct, stream_ct, i; - uint32_t leak_rate, stream_num; - unsigned int stream_languageid_index; - - avio_rl64(pb); // starttime - avio_rl64(pb); // endtime - leak_rate = avio_rl32(pb); // leak-datarate - avio_rl32(pb); // bucket-datasize - avio_rl32(pb); // init-bucket-fullness - avio_rl32(pb); // alt-leak-datarate - avio_rl32(pb); // alt-bucket-datasize - avio_rl32(pb); // alt-init-bucket-fullness - avio_rl32(pb); // max-object-size - avio_rl32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved) - stream_num = avio_rl16(pb); // stream-num - - stream_languageid_index = avio_rl16(pb); // stream-language-id-index - if (stream_num < 128) - asf->streams[stream_num].stream_language_index = stream_languageid_index; - - avio_rl64(pb); // avg frametime in 100ns units - stream_ct = avio_rl16(pb); // stream-name-count - payload_ext_ct = avio_rl16(pb); // payload-extension-system-count - - if (stream_num < 128) - asf->stream_bitrates[stream_num] = leak_rate; - - for (i = 0; i < stream_ct; i++) { - avio_rl16(pb); - ext_len = avio_rl16(pb); - avio_skip(pb, ext_len); + int i; + static const char *const titles[] = + { "Title", "Author", "Copyright", "Description", "Rate" }; + uint16_t len[5], buflen[5] = { 0 }; + uint8_t *ch; + uint64_t size = avio_rl64(pb); + + for (i = 0; i < 5; i++) { + len[i] = avio_rl16(pb); + // utf8 string should be <= 2 * utf16 string, extra byte for the terminator + buflen[i] = 2 * len[i] + 1; } - for (i = 0; i < payload_ext_ct; i++) { - ff_get_guid(pb, &g); - avio_skip(pb, 2); - ext_len = avio_rl32(pb); - avio_skip(pb, ext_len); + for (i = 0; i < 5; i++) { + ch = av_malloc(buflen[i]); + if (!ch) + return(AVERROR(ENOMEM)); + asf_read_metadata(s, titles[i], len[i], ch, buflen[i]); + av_freep(&ch); } + align_position(pb, asf->offset, size); return 0; } -static int asf_read_content_desc(AVFormatContext *s, int64_t size) +static int asf_read_properties(AVFormatContext *s, const GUIDParseTable *g) { + ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; - int len1, len2, len3, len4, len5; - - len1 = avio_rl16(pb); - len2 = avio_rl16(pb); - len3 = avio_rl16(pb); - len4 = avio_rl16(pb); - len5 = avio_rl16(pb); - get_tag(s, "title", 0, len1, 32); - get_tag(s, "author", 0, len2, 32); - get_tag(s, "copyright", 0, len3, 32); - get_tag(s, "comment", 0, len4, 32); - avio_skip(pb, len5); + time_t creation_time; + + avio_rl64(pb); // read object size + avio_skip(pb, 16); // skip File ID + avio_skip(pb, 8); // skip File size + creation_time = avio_rl64(pb); + if (!(asf->b_flags & ASF_FLAG_BROADCAST)) { + struct tm tmbuf; + struct tm *tm; + char buf[64]; + + // creation date is in 100 ns units from 1 Jan 1601, conversion to s + creation_time /= 10000000; + // there are 11644473600 seconds between 1 Jan 1601 and 1 Jan 1970 + creation_time -= 11644473600; + tm = gmtime_r(&creation_time, &tmbuf); + if (tm) { + if (!strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) + buf[0] = '\0'; + } else + buf[0] = '\0'; + if (buf[0]) { + if (av_dict_set(&s->metadata, "creation_time", buf, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } + } + asf->nb_packets = avio_rl64(pb); + asf->duration = avio_rl64(pb) / 10000; // stream duration + avio_skip(pb, 8); // skip send duration + asf->preroll = avio_rl64(pb); + asf->duration -= asf->preroll; + asf->b_flags = avio_rl32(pb); + avio_skip(pb, 4); // skip minimal packet size + asf->packet_size = avio_rl32(pb); + avio_skip(pb, 4); // skip max_bitrate return 0; } -static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size) +static int parse_video_info(AVIOContext *pb, AVStream *st) +{ + uint16_t size_asf; // ASF-specific Format Data size + uint32_t size_bmp; // BMP_HEADER-specific Format Data size + unsigned int tag; + + st->codecpar->width = avio_rl32(pb); + st->codecpar->height = avio_rl32(pb); + avio_skip(pb, 1); // skip reserved flags + size_asf = avio_rl16(pb); + tag = ff_get_bmp_header(pb, st, &size_bmp); + st->codecpar->codec_tag = tag; + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); + size_bmp = FFMAX(size_asf, size_bmp); + + if (size_bmp > BMP_HEADER_SIZE) { + int ret; + st->codecpar->extradata_size = size_bmp - BMP_HEADER_SIZE; + if (!(st->codecpar->extradata = av_malloc(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE))) { + st->codecpar->extradata_size = 0; + return AVERROR(ENOMEM); + } + memset(st->codecpar->extradata + st->codecpar->extradata_size , 0, + AV_INPUT_BUFFER_PADDING_SIZE); + if ((ret = avio_read(pb, st->codecpar->extradata, + st->codecpar->extradata_size)) < 0) + return ret; + } + return 0; +} + +static int asf_read_stream_properties(AVFormatContext *s, const GUIDParseTable *g) { - AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; - int desc_count, i, ret; + AVIOContext *pb = s->pb; + uint64_t size; + uint32_t err_data_len, ts_data_len; // type specific data length + uint16_t flags; + ff_asf_guid stream_type; + enum AVMediaType type; + int i, ret; + uint8_t stream_index; + AVStream *st; + ASFStream *asf_st; - desc_count = avio_rl16(pb); - for (i = 0; i < desc_count; i++) { - int name_len, value_type, value_len; - char name[1024]; + // ASF file must not contain more than 128 streams according to the specification + if (asf->nb_streams >= ASF_MAX_STREAMS) + return AVERROR_INVALIDDATA; - name_len = avio_rl16(pb); - if (name_len % 2) // must be even, broken lavf versions wrote len-1 - name_len += 1; - if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len) - avio_skip(pb, name_len - ret); - value_type = avio_rl16(pb); - value_len = avio_rl16(pb); - if (!value_type && value_len % 2) - value_len += 1; - /* My sample has that stream set to 0 maybe that mean the container. - * ASF stream count starts at 1. I am using 0 to the container value - * since it's unused. */ - if (!strcmp(name, "AspectRatioX")) - asf->dar[0].num = get_value(s->pb, value_type, 32); - else if (!strcmp(name, "AspectRatioY")) - asf->dar[0].den = get_value(s->pb, value_type, 32); - else - get_tag(s, name, value_type, value_len, 32); + size = avio_rl64(pb); + ff_get_guid(pb, &stream_type); + if (!ff_guidcmp(&stream_type, &ff_asf_audio_stream)) + type = AVMEDIA_TYPE_AUDIO; + else if (!ff_guidcmp(&stream_type, &ff_asf_video_stream)) + type = AVMEDIA_TYPE_VIDEO; + else if (!ff_guidcmp(&stream_type, &ff_asf_jfif_media)) + type = AVMEDIA_TYPE_VIDEO; + else if (!ff_guidcmp(&stream_type, &ff_asf_command_stream)) + type = AVMEDIA_TYPE_DATA; + else if (!ff_guidcmp(&stream_type, + &ff_asf_ext_stream_embed_stream_header)) + type = AVMEDIA_TYPE_UNKNOWN; + else + return AVERROR_INVALIDDATA; + + ff_get_guid(pb, &stream_type); // error correction type + avio_skip(pb, 8); // skip the time offset + ts_data_len = avio_rl32(pb); + err_data_len = avio_rl32(pb); + flags = avio_rl16(pb); // bit 15 - Encrypted Content + + stream_index = flags & ASF_STREAM_NUM; + for (i = 0; i < asf->nb_streams; i++) + if (stream_index == asf->asf_st[i]->stream_index) { + av_log(s, AV_LOG_WARNING, + "Duplicate stream found, this stream will be ignored.\n"); + align_position(pb, asf->offset, size); + return 0; + } + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + avpriv_set_pts_info(st, 32, 1, 1000); // pts should be dword, in milliseconds + st->codecpar->codec_type = type; + asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st)); + if (!asf->asf_st[asf->nb_streams]) + return AVERROR(ENOMEM); + asf_st = asf->asf_st[asf->nb_streams]; + asf->nb_streams++; + asf_st->stream_index = stream_index; + asf_st->index = st->index; + asf_st->indexed = 0; + st->id = flags & ASF_STREAM_NUM; + av_init_packet(&asf_st->pkt.avpkt); + asf_st->pkt.data_size = 0; + avio_skip(pb, 4); // skip reserved field + + switch (type) { + case AVMEDIA_TYPE_AUDIO: + asf_st->type = AVMEDIA_TYPE_AUDIO; + if ((ret = ff_get_wav_header(s, pb, st->codecpar, ts_data_len)) < 0) + return ret; + break; + case AVMEDIA_TYPE_VIDEO: + asf_st->type = AVMEDIA_TYPE_VIDEO; + if ((ret = parse_video_info(pb, st)) < 0) + return ret; + break; + default: + avio_skip(pb, ts_data_len); + break; } + if (err_data_len) { + if (type == AVMEDIA_TYPE_AUDIO) { + uint8_t span = avio_r8(pb); + if (span > 1) { + asf_st->span = span; + asf_st->virtual_pkt_len = avio_rl16(pb); + asf_st->virtual_chunk_len = avio_rl16(pb); + if (!asf_st->virtual_chunk_len || !asf_st->virtual_pkt_len) + return AVERROR_INVALIDDATA; + avio_skip(pb, err_data_len - 5); + } else + avio_skip(pb, err_data_len - 1); + } else + avio_skip(pb, err_data_len); + } + + align_position(pb, asf->offset, size); + return 0; } -static int asf_read_language_list(AVFormatContext *s, int64_t size) +static void set_language(AVFormatContext *s, const char *rfc1766, AVDictionary **met) +{ + // language abbr should contain at least 2 chars + if (rfc1766 && strlen(rfc1766) > 1) { + const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any + const char *iso6392 = av_convert_lang_to(primary_tag, + AV_LANG_ISO639_2_BIBL); + if (iso6392) + if (av_dict_set(met, "language", iso6392, 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } +} + +static int asf_read_ext_stream_properties(AVFormatContext *s, const GUIDParseTable *g) { - AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; - int j, ret; - int stream_count = avio_rl16(pb); - for (j = 0; j < stream_count; j++) { - char lang[6]; - unsigned int lang_len = avio_r8(pb); - if ((ret = avio_get_str16le(pb, lang_len, lang, - sizeof(lang))) < lang_len) - avio_skip(pb, lang_len - ret); - if (j < 128) - av_strlcpy(asf->stream_languages[j], lang, - sizeof(*asf->stream_languages)); + AVIOContext *pb = s->pb; + AVStream *st = NULL; + ff_asf_guid guid; + uint16_t nb_st_name, nb_pay_exts, st_num, lang_idx; + int i, ret; + uint32_t bitrate; + uint64_t start_time, end_time, time_per_frame; + uint64_t size = avio_rl64(pb); + + start_time = avio_rl64(pb); + end_time = avio_rl64(pb); + bitrate = avio_rl32(pb); + avio_skip(pb, 28); // skip some unused values + st_num = avio_rl16(pb); + st_num &= ASF_STREAM_NUM; + lang_idx = avio_rl16(pb); // Stream Language ID Index + for (i = 0; i < asf->nb_streams; i++) { + if (st_num == asf->asf_st[i]->stream_index) { + st = s->streams[asf->asf_st[i]->index]; + asf->asf_st[i]->lang_idx = lang_idx; + break; + } + } + time_per_frame = avio_rl64(pb); // average time per frame + if (st) { + st->start_time = start_time; + st->duration = end_time - start_time; + st->codecpar->bit_rate = bitrate; + st->avg_frame_rate.num = 10000000; + st->avg_frame_rate.den = time_per_frame; + } + nb_st_name = avio_rl16(pb); + nb_pay_exts = avio_rl16(pb); + for (i = 0; i < nb_st_name; i++) { + uint16_t len; + + avio_rl16(pb); // Language ID Index + len = avio_rl16(pb); + avio_skip(pb, len); } + for (i = 0; i < nb_pay_exts; i++) { + uint32_t len; + avio_skip(pb, 16); // Extension System ID + avio_skip(pb, 2); // Extension Data Size + len = avio_rl32(pb); + avio_skip(pb, len); + } + + if ((ret = ff_get_guid(pb, &guid)) < 0) { + align_position(pb, asf->offset, size); + + return 0; + } + + g = find_guid(guid); + if (g && !(strcmp(g->name, "Stream Properties"))) { + if ((ret = g->read_object(s, g)) < 0) + return ret; + } + + align_position(pb, asf->offset, size); return 0; } -static int asf_read_metadata(AVFormatContext *s, int64_t size) +static int asf_read_language_list(AVFormatContext *s, const GUIDParseTable *g) { - AVIOContext *pb = s->pb; - ASFContext *asf = s->priv_data; - int n, stream_num, name_len, value_len; - int ret, i; - n = avio_rl16(pb); - - for (i = 0; i < n; i++) { - char name[1024]; - int value_type; - - avio_rl16(pb); // lang_list_index - stream_num = avio_rl16(pb); - name_len = avio_rl16(pb); - value_type = avio_rl16(pb); /* value_type */ - value_len = avio_rl32(pb); - - if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len) - avio_skip(pb, name_len - ret); - av_dlog(s, "%d stream %d name_len %2d type %d len %4d <%s>\n", - i, stream_num, name_len, value_type, value_len, name); - - if (!strcmp(name, "AspectRatioX")){ - int aspect_x = get_value(s->pb, value_type, 16); - if(stream_num < 128) - asf->dar[stream_num].num = aspect_x; - } else if(!strcmp(name, "AspectRatioY")){ - int aspect_y = get_value(s->pb, value_type, 16); - if(stream_num < 128) - asf->dar[stream_num].den = aspect_y; - } else { - get_tag(s, name, value_type, value_len, 16); + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int i, ret; + uint64_t size = avio_rl64(pb); + uint16_t nb_langs = avio_rl16(pb); + + if (nb_langs < ASF_MAX_STREAMS) { + for (i = 0; i < nb_langs; i++) { + size_t len; + len = avio_r8(pb); + if (!len) + len = 6; + if ((ret = get_asf_string(pb, len, asf->asf_sd[i].langs, + sizeof(asf->asf_sd[i].langs))) < 0) { + return ret; + } } } + align_position(pb, asf->offset, size); return 0; } -static int asf_read_marker(AVFormatContext *s, int64_t size) +// returns data object offset when reading this object for the first time +static int asf_read_data(AVFormatContext *s, const GUIDParseTable *g) { - AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; - int i, count, name_len, ret; - char name[1024]; + AVIOContext *pb = s->pb; + uint64_t size = asf->data_size = avio_rl64(pb); + int i; - avio_rl64(pb); // reserved 16 bytes - avio_rl64(pb); // ... - count = avio_rl32(pb); // markers count - avio_rl16(pb); // reserved 2 bytes - name_len = avio_rl16(pb); // name length - for (i = 0; i < name_len; i++) - avio_r8(pb); // skip the name - - for (i = 0; i < count; i++) { - int64_t pres_time; - int name_len; - - avio_rl64(pb); // offset, 8 bytes - pres_time = avio_rl64(pb); // presentation time - pres_time -= asf->hdr.preroll * 10000; - avio_rl16(pb); // entry length - avio_rl32(pb); // send time - avio_rl32(pb); // flags - name_len = avio_rl32(pb); // name length - if ((ret = avio_get_str16le(pb, name_len * 2, name, - sizeof(name))) < name_len) - avio_skip(pb, name_len - ret); - avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pres_time, - AV_NOPTS_VALUE, name); + if (!asf->data_reached) { + asf->data_reached = 1; + asf->data_offset = asf->offset; } + for (i = 0; i < asf->nb_streams; i++) { + if (!(asf->b_flags & ASF_FLAG_BROADCAST)) + s->streams[i]->duration = asf->duration; + } + asf->nb_mult_left = 0; + asf->sub_left = 0; + asf->state = PARSE_PACKET_HEADER; + asf->return_subpayload = 0; + asf->packet_size_internal = 0; + avio_skip(pb, 16); // skip File ID + size = avio_rl64(pb); // Total Data Packets + if (size != asf->nb_packets) + av_log(s, AV_LOG_WARNING, + "Number of Packets from File Properties Object is not equal to Total" + "Datapackets value! num of packets %"PRIu64" total num %"PRIu64".\n", + size, asf->nb_packets); + avio_skip(pb, 2); // skip reserved field + asf->first_packet_offset = avio_tell(pb); + if (pb->seekable && !(asf->b_flags & ASF_FLAG_BROADCAST)) + align_position(pb, asf->offset, asf->data_size); + return 0; } -static int asf_read_header(AVFormatContext *s) +static int asf_read_simple_index(AVFormatContext *s, const GUIDParseTable *g) { ASFContext *asf = s->priv_data; - ff_asf_guid g; AVIOContext *pb = s->pb; + AVStream *st = NULL; + uint64_t interval; // index entry time interval in 100 ns units, usually it's 1s + uint32_t pkt_num, nb_entries; + int32_t prev_pkt_num = -1; int i; - int64_t gsize; - - ff_get_guid(pb, &g); - if (ff_guidcmp(&g, &ff_asf_header)) - return -1; - avio_rl64(pb); - avio_rl32(pb); - avio_r8(pb); - avio_r8(pb); - memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); - for (;;) { - uint64_t gpos = avio_tell(pb); - ff_get_guid(pb, &g); - gsize = avio_rl64(pb); - print_guid(&g); - if (!ff_guidcmp(&g, &ff_asf_data_header)) { - asf->data_object_offset = avio_tell(pb); - /* If not streaming, gsize is not unlimited (how?), - * and there is enough space in the file.. */ - if (!(asf->hdr.flags & 0x01) && gsize >= 100) - asf->data_object_size = gsize - 24; - else - asf->data_object_size = (uint64_t)-1; + int64_t offset; + uint64_t size = avio_rl64(pb); + + // simple index objects should be ordered by stream number, this loop tries to find + // the first not indexed video stream + for (i = 0; i < asf->nb_streams; i++) { + if ((asf->asf_st[i]->type == AVMEDIA_TYPE_VIDEO) && !asf->asf_st[i]->indexed) { + asf->asf_st[i]->indexed = 1; + st = s->streams[asf->asf_st[i]->index]; break; } - if (gsize < 24) - return -1; - if (!ff_guidcmp(&g, &ff_asf_file_header)) { - int ret = asf_read_file_properties(s, gsize); - if (ret < 0) - return ret; - } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) { - int ret = asf_read_stream_properties(s, gsize); - if (ret < 0) - return ret; - } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) { - asf_read_content_desc(s, gsize); - } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) { - asf_read_language_list(s, gsize); - } else if (!ff_guidcmp(&g, &ff_asf_extended_content_header)) { - asf_read_ext_content_desc(s, gsize); - } else if (!ff_guidcmp(&g, &ff_asf_metadata_header)) { - asf_read_metadata(s, gsize); - } else if (!ff_guidcmp(&g, &ff_asf_metadata_library_header)) { - asf_read_metadata(s, gsize); - } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) { - asf_read_ext_stream_properties(s, gsize); - - // there could be a optional stream properties object to follow - // if so the next iteration will pick it up - continue; - } else if (!ff_guidcmp(&g, &ff_asf_head1_guid)) { - ff_get_guid(pb, &g); - avio_skip(pb, 6); - continue; - } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) { - asf_read_marker(s, gsize); - } else if (pb->eof_reached) { - return -1; - } else { - if (!s->keylen) { - if (!ff_guidcmp(&g, &ff_asf_content_encryption)) { - av_log(s, AV_LOG_WARNING, - "DRM protected stream detected, decoding will likely fail!\n"); - } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) { - av_log(s, AV_LOG_WARNING, - "Ext DRM protected stream detected, decoding will likely fail!\n"); - } else if (!ff_guidcmp(&g, &ff_asf_digital_signature)) { - av_log(s, AV_LOG_WARNING, - "Digital signature detected, decoding will likely fail!\n"); - } - } - } - if (avio_tell(pb) != gpos + gsize) - av_log(s, AV_LOG_DEBUG, - "gpos mismatch our pos=%"PRIu64", end=%"PRId64"\n", - avio_tell(pb) - gpos, gsize); - avio_seek(pb, gpos + gsize, SEEK_SET); } - ff_get_guid(pb, &g); - avio_rl64(pb); - avio_r8(pb); - avio_r8(pb); - if (pb->eof_reached) - return -1; - asf->data_offset = avio_tell(pb); - asf->packet_size_left = 0; - - for (i = 0; i < 128; i++) { - int stream_num = asf->asfid2avid[i]; - if (stream_num >= 0) { - AVStream *st = s->streams[stream_num]; - if (!st->codec->bit_rate) - st->codec->bit_rate = asf->stream_bitrates[i]; - if (asf->dar[i].num > 0 && asf->dar[i].den > 0) { - av_reduce(&st->sample_aspect_ratio.num, - &st->sample_aspect_ratio.den, - asf->dar[i].num, asf->dar[i].den, INT_MAX); - } else if ((asf->dar[0].num > 0) && (asf->dar[0].den > 0) && - // Use ASF container value if the stream doesn't set AR. - (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)) - av_reduce(&st->sample_aspect_ratio.num, - &st->sample_aspect_ratio.den, - asf->dar[0].num, asf->dar[0].den, INT_MAX); - - av_dlog(s, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n", - i, st->codec->codec_type, asf->dar[i].num, asf->dar[i].den, - st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); - - // copy and convert language codes to the frontend - if (asf->streams[i].stream_language_index < 128) { - const char *rfc1766 = asf->stream_languages[asf->streams[i].stream_language_index]; - if (rfc1766 && strlen(rfc1766) > 1) { - const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any - const char *iso6392 = av_convert_lang_to(primary_tag, - AV_LANG_ISO639_2_BIBL); - if (iso6392) - av_dict_set(&st->metadata, "language", iso6392, 0); - } - } + if (!st) { + avio_skip(pb, size - 24); // if there's no video stream, skip index object + return 0; + } + avio_skip(pb, 16); // skip File ID + interval = avio_rl64(pb); + avio_skip(pb, 4); + nb_entries = avio_rl32(pb); + for (i = 0; i < nb_entries; i++) { + pkt_num = avio_rl32(pb); + offset = avio_skip(pb, 2); + if (offset < 0) { + av_log(s, AV_LOG_ERROR, "Skipping failed in asf_read_simple_index.\n"); + return offset; + } + if (prev_pkt_num != pkt_num) { + av_add_index_entry(st, asf->first_packet_offset + asf->packet_size * + pkt_num, av_rescale(interval, i, 10000), + asf->packet_size, 0, AVINDEX_KEYFRAME); + prev_pkt_num = pkt_num; } } - - ff_metadata_conv(&s->metadata, NULL, ff_asf_metadata_conv); + asf->is_simple_index = 1; + align_position(pb, asf->offset, size); return 0; } -#define DO_2BITS(bits, var, defval) \ - switch (bits & 3) { \ - case 3: \ - var = avio_rl32(pb); \ - rsize += 4; \ - break; \ - case 2: \ - var = avio_rl16(pb); \ - rsize += 2; \ - break; \ - case 1: \ - var = avio_r8(pb); \ - rsize++; \ - break; \ - default: \ - var = defval; \ - break; \ - } +static const GUIDParseTable gdef[] = { + { "Data", { 0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_data, 1 }, + { "Simple Index", { 0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB }, asf_read_simple_index, 1 }, + { "Content Description", { 0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_content_desc, 1 }, + { "Extended Content Description", { 0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50 }, asf_read_ext_content, 1 }, + { "Stream Bitrate Properties", { 0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2 }, asf_read_unknown, 1 }, + { "File Properties", { 0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_properties, 1 }, + { "Header Extension", { 0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_unknown, 0 }, + { "Stream Properties", { 0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_stream_properties, 1 }, + { "Codec List", { 0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 }, + { "Marker", { 0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_marker, 1 }, + { "Script Command", { 0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 }, + { "Language List", { 0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 }, asf_read_language_list, 1}, + { "Padding", { 0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8 }, asf_read_unknown, 1 }, + { "DRMv1 Header", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, + { "DRMv2 Header", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c }, asf_read_unknown, 1 }, + { "Index", { 0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Media Object Index", { 0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C }, asf_read_unknown, 1 }, + { "Timecode Index", { 0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C }, asf_read_unknown, 0 }, + { "Bitrate_Mutual_Exclusion", { 0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Error Correction", { 0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_unknown, 1 }, + { "Content Branding", { 0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, + { "Content Encryption", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, + { "Extended Content Encryption", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C }, asf_read_unknown, 1 }, + { "Digital Signature", { 0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 }, + { "Extended Stream Properties", { 0x14, 0xE6, 0xA5, 0xCB, 0xC6, 0x72, 0x43, 0x32, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A }, asf_read_ext_stream_properties, 1 }, + { "Advanced Mutual Exclusion", { 0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD }, asf_read_unknown, 1 }, + { "Group Mutual Exclusion", { 0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49 }, asf_read_unknown, 1}, + { "Stream Prioritization", { 0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24 }, asf_read_unknown, 1 }, + { "Bandwidth Sharing Object", { 0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, + { "Metadata", { 0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA }, asf_read_metadata_obj, 1 }, + { "Metadata Library", { 0x44, 0x23, 0x1C, 0x94, 0x94, 0x98, 0x49, 0xD1, 0xA1, 0x41, 0x1D, 0x13, 0x4E, 0x45, 0x70, 0x54 }, asf_read_metadata_obj, 1 }, + { "Audio Spread", { 0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }, asf_read_unknown, 1 }, + { "Index Parameters", { 0xD6, 0xE2, 0x29, 0xDF, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Content Encryption System Windows Media DRM Network Devices", + { 0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D }, asf_read_unknown, 1 }, + { "Mutex Language", { 0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Mutex Bitrate", { 0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Mutex Unknown", { 0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 }, + { "Bandwith Sharing Exclusive", { 0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, + { "Bandwith Sharing Partial", { 0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 }, + { "Payload Extension System Timecode", { 0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E }, asf_read_unknown, 1 }, + { "Payload Extension System File Name", { 0xE1, 0x65, 0xEC, 0x0E, 0x19, 0xED, 0x45, 0xD7, 0xB4, 0xA7, 0x25, 0xCB, 0xD1, 0xE2, 0x8E, 0x9B }, asf_read_unknown, 1 }, + { "Payload Extension System Content Type", { 0xD5, 0x90, 0xDC, 0x20, 0x07, 0xBC, 0x43, 0x6C, 0x9C, 0xF7, 0xF3, 0xBB, 0xFB, 0xF1, 0xA4, 0xDC }, asf_read_unknown, 1 }, + { "Payload Extension System Pixel Aspect Ratio", { 0x1, 0x1E, 0xE5, 0x54, 0xF9, 0xEA, 0x4B, 0xC8, 0x82, 0x1A, 0x37, 0x6B, 0x74, 0xE4, 0xC4, 0xB8 }, asf_read_unknown, 1 }, + { "Payload Extension System Sample Duration", { 0xC6, 0xBD, 0x94, 0x50, 0x86, 0x7F, 0x49, 0x07, 0x83, 0xA3, 0xC7, 0x79, 0x21, 0xB7, 0x33, 0xAD }, asf_read_unknown, 1 }, + { "Payload Extension System Encryption Sample ID", { 0x66, 0x98, 0xB8, 0x4E, 0x0A, 0xFA, 0x43, 0x30, 0xAE, 0xB2, 0x1C, 0x0A, 0x98, 0xD7, 0xA4, 0x4D }, asf_read_unknown, 1 }, + { "Payload Extension System Degradable JPEG", { 0x00, 0xE1, 0xAF, 0x06, 0x7B, 0xEC, 0x11, 0xD1, 0xA5, 0x82, 0x00, 0xC0, 0x4F, 0xC2, 0x9C, 0xFB }, asf_read_unknown, 1 }, +}; -/** - * Load a single ASF packet into the demuxer. - * @param s demux context - * @param pb context to read data from - * @return 0 on success, <0 on error - */ -static int asf_get_packet(AVFormatContext *s, AVIOContext *pb) +#define READ_LEN(flag, name, len) \ + do { \ + if ((flag) == name ## IS_BYTE) \ + len = avio_r8(pb); \ + else if ((flag) == name ## IS_WORD) \ + len = avio_rl16(pb); \ + else if ((flag) == name ## IS_DWORD) \ + len = avio_rl32(pb); \ + else \ + len = 0; \ + } while(0) + +static int asf_read_subpayload(AVFormatContext *s, AVPacket *pkt, int is_header) { ASFContext *asf = s->priv_data; - uint32_t packet_length, padsize; - int rsize = 8; - int c, d, e, off; - - // if we do not know packet size, allow skipping up to 32 kB - off = 32768; - if (asf->no_resync_search) - off = 3; - else if (s->packet_size > 0) - off = (avio_tell(pb) - s->data_offset) % s->packet_size + 3; - - c = d = e = -1; - while (off-- > 0) { - c = d; - d = e; - e = avio_r8(pb); - if (c == 0x82 && !d && !e) + AVIOContext *pb = s->pb; + uint8_t sub_len; + int ret, i; + + if (is_header) { + asf->dts_delta = avio_r8(pb); + if (asf->nb_mult_left) { + asf->mult_sub_len = avio_rl16(pb); // total + } + asf->sub_header_offset = avio_tell(pb); + asf->nb_sub = 0; + asf->sub_left = 1; + } + sub_len = avio_r8(pb); + if ((ret = av_get_packet(pb, pkt, sub_len)) < 0) // each subpayload is entire frame + return ret; + for (i = 0; i < asf->nb_streams; i++) { + if (asf->stream_index == asf->asf_st[i]->stream_index) { + pkt->stream_index = asf->asf_st[i]->index; break; + } } - - if (c != 0x82) { - /* This code allows handling of -EAGAIN at packet boundaries (i.e. - * if the packet sync code above triggers -EAGAIN). This does not - * imply complete -EAGAIN handling support at random positions in - * the stream. */ - if (pb->error == AVERROR(EAGAIN)) - return AVERROR(EAGAIN); - if (!pb->eof_reached) - av_log(s, AV_LOG_ERROR, - "ff asf bad header %x at:%"PRId64"\n", c, avio_tell(pb)); + asf->return_subpayload = 1; + if (!sub_len) + asf->return_subpayload = 0; + + if (sub_len) + asf->nb_sub++; + pkt->dts = asf->sub_dts + (asf->nb_sub - 1) * asf->dts_delta - asf->preroll; + if (asf->nb_mult_left && (avio_tell(pb) >= + (asf->sub_header_offset + asf->mult_sub_len))) { + asf->sub_left = 0; + asf->nb_mult_left--; } - if ((c & 0x8f) == 0x82) { - if (d || e) { - if (!pb->eof_reached) - av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n"); - return -1; + if (avio_tell(pb) >= asf->packet_offset + asf->packet_size - asf->pad_len) { + asf->sub_left = 0; + if (!asf->nb_mult_left) { + avio_skip(pb, asf->pad_len); + if (avio_tell(pb) != asf->packet_offset + asf->packet_size) { + if (!asf->packet_size) + return AVERROR_INVALIDDATA; + av_log(s, AV_LOG_WARNING, + "Position %"PRId64" wrong, should be %"PRId64"\n", + avio_tell(pb), asf->packet_offset + asf->packet_size); + avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); + } } - c = avio_r8(pb); - d = avio_r8(pb); - rsize += 3; - } else if (!pb->eof_reached) { - avio_seek(pb, -1, SEEK_CUR); // FIXME } - asf->packet_flags = c; - asf->packet_property = d; + return 0; +} - DO_2BITS(asf->packet_flags >> 5, packet_length, s->packet_size); - DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored - DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length +static void reset_packet(ASFPacket *asf_pkt) +{ + asf_pkt->size_left = 0; + asf_pkt->data_size = 0; + asf_pkt->duration = 0; + asf_pkt->flags = 0; + asf_pkt->dts = 0; + asf_pkt->duration = 0; + av_packet_unref(&asf_pkt->avpkt); + av_init_packet(&asf_pkt->avpkt); +} - // the following checks prevent overflows and infinite loops - if (!packet_length || packet_length >= (1U << 29)) { - av_log(s, AV_LOG_ERROR, - "invalid packet_length %"PRIu32" at:%"PRId64"\n", - packet_length, avio_tell(pb)); - return -1; - } - if (padsize >= packet_length) { - av_log(s, AV_LOG_ERROR, - "invalid padsize %"PRIu32" at:%"PRId64"\n", padsize, avio_tell(pb)); - return -1; - } +static int asf_read_replicated_data(AVFormatContext *s, ASFPacket *asf_pkt) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int ret, data_size; - asf->packet_timestamp = avio_rl32(pb); - avio_rl16(pb); /* duration */ - // rsize has at least 11 bytes which have to be present + if (!asf_pkt->data_size) { + data_size = avio_rl32(pb); // read media object size + if (data_size <= 0) + return AVERROR_INVALIDDATA; + if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) + return ret; + asf_pkt->data_size = asf_pkt->size_left = data_size; + } else + avio_skip(pb, 4); // reading of media object size is already done + asf_pkt->dts = avio_rl32(pb); // read presentation time + if (asf->rep_data_len && (asf->rep_data_len >= 8)) + avio_skip(pb, asf->rep_data_len - 8); // skip replicated data - if (asf->packet_flags & 0x01) { - asf->packet_segsizetype = avio_r8(pb); - rsize++; - asf->packet_segments = asf->packet_segsizetype & 0x3f; - } else { - asf->packet_segments = 1; - asf->packet_segsizetype = 0x80; - } - if (rsize > packet_length - padsize) { - asf->packet_size_left = 0; - av_log(s, AV_LOG_ERROR, - "invalid packet header length %d for pktlen %"PRIu32"-%"PRIu32" at %"PRId64"\n", - rsize, packet_length, padsize, avio_tell(pb)); - return -1; - } - 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; - av_dlog(s, "packet: size=%d padsize=%d left=%d\n", - s->packet_size, asf->packet_padsize, asf->packet_size_left); return 0; } -/** - * - * @return <0 if error - */ -static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb) +static int asf_read_multiple_payload(AVFormatContext *s, AVPacket *pkt, + ASFPacket *asf_pkt) { ASFContext *asf = s->priv_data; - int rsize = 1; - int num = avio_r8(pb); - int64_t ts0; - - asf->packet_segments--; - asf->packet_key_frame = num >> 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); - av_dlog(asf, "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 >= 8) { - asf->packet_obj_size = avio_rl32(pb); - if (asf->packet_obj_size >= (1 << 24) || asf->packet_obj_size <= 0) { - av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n"); - return -1; - } - asf->packet_frag_timestamp = avio_rl32(pb); // timestamp - if (asf->packet_replic_size >= 8 + 38 + 4) { - avio_skip(pb, 10); - ts0 = avio_rl64(pb); - avio_skip(pb, 8); - avio_skip(pb, 12); - avio_rl32(pb); - avio_skip(pb, asf->packet_replic_size - 8 - 38 - 4); - if (ts0 != -1) - asf->packet_frag_timestamp = ts0 / 10000; - else - asf->packet_frag_timestamp = AV_NOPTS_VALUE; - } else - avio_skip(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 beginning 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 = avio_r8(pb); - rsize++; - } else if (asf->packet_replic_size != 0) { - av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n", - asf->packet_replic_size); - return -1; - } - if (asf->packet_flags & 0x01) { - DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal - if (rsize > asf->packet_size_left) { - av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n"); - return -1; - } else if (asf->packet_frag_size > asf->packet_size_left - rsize) { - if (asf->packet_frag_size > asf->packet_size_left - rsize + asf->packet_padsize) { - av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid (%d-%d)\n", - asf->packet_size_left, rsize); - return -1; - } else { - int diff = asf->packet_frag_size - (asf->packet_size_left - rsize); - asf->packet_size_left += diff; - asf->packet_padsize -= diff; - } - } + AVIOContext *pb = s->pb; + uint16_t pay_len; + unsigned char *p; + int ret; + int skip = 0; + + // if replicated length is 1, subpayloads are present + if (asf->rep_data_len == 1) { + asf->sub_left = 1; + asf->state = READ_MULTI_SUB; + pkt->flags = asf_pkt->flags; + if ((ret = asf_read_subpayload(s, pkt, 1)) < 0) + return ret; } else { - if (rsize > asf->packet_size_left) { - av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n"); - return -1; + if (asf->rep_data_len) + if ((ret = asf_read_replicated_data(s, asf_pkt)) < 0) + return ret; + pay_len = avio_rl16(pb); // payload length should be WORD + if (pay_len > asf->packet_size) { + av_log(s, AV_LOG_ERROR, + "Error: invalid data packet size, pay_len %"PRIu16", " + "asf->packet_size %"PRIu32", offset %"PRId64".\n", + pay_len, asf->packet_size, avio_tell(pb)); + return AVERROR_INVALIDDATA; } - 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) - return -1; + p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; + if (pay_len > asf_pkt->size_left) { + av_log(s, AV_LOG_ERROR, + "Error: invalid buffer size, pay_len %d, data size left %d.\n", + pay_len, asf_pkt->size_left); + skip = pay_len - asf_pkt->size_left; + pay_len = asf_pkt->size_left; + } + if (asf_pkt->size_left <= 0) + return AVERROR_INVALIDDATA; + if ((ret = avio_read(pb, p, pay_len)) < 0) + return ret; + if (s->key && s->keylen == 20) + ff_asfcrypt_dec(s->key, p, ret); + avio_skip(pb, skip); + asf_pkt->size_left -= pay_len; + asf->nb_mult_left--; } - asf->packet_size_left -= rsize; return 0; } -/** - * Parse data from individual ASF packets (which were previously loaded - * with asf_get_packet()). - * @param s demux context - * @param pb context to read data from - * @param pkt pointer to store packet data into - * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF - * packets need to be loaded (through asf_get_packet()) - */ -static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +static int asf_read_single_payload(AVFormatContext *s, ASFPacket *asf_pkt) { - ASFContext *asf = s->priv_data; - ASFStream *asf_st = 0; - for (;;) { - int ret; - - if (pb->eof_reached) + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int64_t offset; + uint64_t size; + unsigned char *p; + int ret, data_size; + + if (!asf_pkt->data_size) { + data_size = avio_rl32(pb); // read media object size + if (data_size <= 0) return AVERROR_EOF; + if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) + return ret; + asf_pkt->data_size = asf_pkt->size_left = data_size; + } else + avio_skip(pb, 4); // skip media object size + asf_pkt->dts = avio_rl32(pb); // read presentation time + if (asf->rep_data_len >= 8) + avio_skip(pb, asf->rep_data_len - 8); // skip replicated data + offset = avio_tell(pb); + + // size of the payload - size of the packet without header and padding + if (asf->packet_size_internal) + size = asf->packet_size_internal - offset + asf->packet_offset - asf->pad_len; + else + size = asf->packet_size - offset + asf->packet_offset - asf->pad_len; + if (size > asf->packet_size) { + av_log(s, AV_LOG_ERROR, + "Error: invalid data packet size, offset %"PRId64".\n", + avio_tell(pb)); + return AVERROR_INVALIDDATA; + } + p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; + if (size > asf_pkt->size_left || asf_pkt->size_left <= 0) + return AVERROR_INVALIDDATA; + if (asf_pkt->size_left > size) + asf_pkt->size_left -= size; + else + asf_pkt->size_left = 0; + if ((ret = avio_read(pb, p, size)) < 0) + return ret; + if (s->key && s->keylen == 20) + ff_asfcrypt_dec(s->key, p, ret); + if (asf->packet_size_internal) + avio_skip(pb, asf->packet_size - asf->packet_size_internal); + avio_skip(pb, asf->pad_len); // skip padding - if (asf->packet_size_left < FRAME_HEADER_SIZE || - asf->packet_segments < 1) { - int ret = asf->packet_size_left + asf->packet_padsize; - - assert(ret >= 0); - /* fail safe */ - avio_skip(pb, ret); + return 0; +} - asf->packet_pos = avio_tell(pb); - if (asf->data_object_size != (uint64_t)-1 && - (asf->packet_pos - asf->data_object_offset >= asf->data_object_size)) - return AVERROR_EOF; /* Do not exceed the size of the data object */ - return 1; - } - if (asf->packet_time_start == 0) { - if (asf_read_frame_header(s, pb) < 0) { - asf->packet_segments = 0; - continue; - } - 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) */ - avio_skip(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 (unknown stream)\n", - asf->packet_frag_size); - continue; +static int asf_read_payload(AVFormatContext *s, AVPacket *pkt) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int ret, i; + ASFPacket *asf_pkt = NULL; + + if (!asf->sub_left) { + uint32_t off_len, media_len; + uint8_t stream_num; + + stream_num = avio_r8(pb); + asf->stream_index = stream_num & ASF_STREAM_NUM; + for (i = 0; i < asf->nb_streams; i++) { + if (asf->stream_index == asf->asf_st[i]->stream_index) { + asf_pkt = &asf->asf_st[i]->pkt; + asf_pkt->stream_index = asf->asf_st[i]->index; + break; } - asf->asf_st = s->streams[asf->stream_index]->priv_data; } - asf_st = asf->asf_st; - av_assert0(asf_st); - - if (!asf_st->frag_offset && asf->packet_frag_offset) { - av_dlog(s, "skipping asf data pkt with fragment offset for " - "stream:%d, expected:%d but got %d from pkt)\n", - asf->stream_index, asf_st->frag_offset, - asf->packet_frag_offset); - avio_skip(pb, asf->packet_frag_size); - asf->packet_size_left -= asf->packet_frag_size; - continue; + if (!asf_pkt) { + if (asf->packet_offset + asf->packet_size <= asf->data_offset + asf->data_size) { + if (!asf->packet_size) { + av_log(s, AV_LOG_ERROR, "Invalid packet size 0.\n"); + return AVERROR_INVALIDDATA; + } + avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); + av_log(s, AV_LOG_WARNING, "Skipping the stream with the invalid stream index %d.\n", + asf->stream_index); + return AVERROR(EAGAIN); + } else + return AVERROR_INVALIDDATA; } - if (asf->packet_replic_size == 1) { - // frag_offset is here used as the beginning 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 = avio_r8(pb); - asf->packet_size_left--; - asf->packet_multi_size--; - if (asf->packet_multi_size < asf->packet_obj_size) { - asf->packet_time_start = 0; - avio_skip(pb, asf->packet_multi_size); - asf->packet_size_left -= asf->packet_multi_size; - continue; - } - asf->packet_multi_size -= asf->packet_obj_size; + if (stream_num >> 7) + asf_pkt->flags |= AV_PKT_FLAG_KEY; + READ_LEN(asf->prop_flags & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE, + ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_, media_len); + READ_LEN(asf->prop_flags & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE, + ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_, off_len); + READ_LEN(asf->prop_flags & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE, + ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_, asf->rep_data_len); + if (asf_pkt->size_left && (asf_pkt->frame_num != media_len)) { + av_log(s, AV_LOG_WARNING, "Unfinished frame will be ignored\n"); + reset_packet(asf_pkt); } - if (asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size && - asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size) { - av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n", - asf_st->frag_offset, asf->packet_frag_size, - asf->packet_obj_size, asf_st->pkt.size); - asf->packet_obj_size = asf_st->pkt.size; + asf_pkt->frame_num = media_len; + asf->sub_dts = off_len; + if (asf->nb_mult_left) { + if ((ret = asf_read_multiple_payload(s, pkt, asf_pkt)) < 0) + return ret; + } else if (asf->rep_data_len == 1) { + asf->sub_left = 1; + asf->state = READ_SINGLE; + pkt->flags = asf_pkt->flags; + if ((ret = asf_read_subpayload(s, pkt, 1)) < 0) + return ret; + } else { + if ((ret = asf_read_single_payload(s, asf_pkt)) < 0) + return ret; } - - if (asf_st->pkt.size != asf->packet_obj_size || - // FIXME is this condition sufficient? - asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) { - if (asf_st->pkt.data) { - av_log(s, AV_LOG_INFO, - "freeing incomplete packet size %d, new %d\n", - asf_st->pkt.size, asf->packet_obj_size); - asf_st->frag_offset = 0; - av_free_packet(&asf_st->pkt); - } - /* new packet */ - av_new_packet(&asf_st->pkt, asf->packet_obj_size); - asf_st->seq = asf->packet_seq; - asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll; - asf_st->pkt.stream_index = asf->stream_index; - asf_st->pkt.pos = asf_st->packet_pos = asf->packet_pos; - - if (asf_st->pkt.data && asf_st->palette_changed) { - uint8_t *pal; - pal = av_packet_new_side_data(&asf_st->pkt, AV_PKT_DATA_PALETTE, - AVPALETTE_SIZE); - if (!pal) { - av_log(s, AV_LOG_ERROR, "Cannot append palette to packet\n"); - } else { - memcpy(pal, asf_st->palette, AVPALETTE_SIZE); - asf_st->palette_changed = 0; - } + } else { + for (i = 0; i <= asf->nb_streams; i++) { + if (asf->stream_index == asf->asf_st[i]->stream_index) { + asf_pkt = &asf->asf_st[i]->pkt; + break; } - av_dlog(asf, "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 & AV_PKT_FLAG_KEY, - s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO, - asf->packet_obj_size); - if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) - asf->packet_key_frame = 1; - if (asf->packet_key_frame) - asf_st->pkt.flags |= AV_PKT_FLAG_KEY; } + if (!asf_pkt) + return AVERROR_INVALIDDATA; + pkt->flags = asf_pkt->flags; + pkt->dts = asf_pkt->dts; + pkt->stream_index = asf->asf_st[i]->index; + if ((ret = asf_read_subpayload(s, pkt, 0)) < 0) // read subpayload without its header + return ret; + } - /* read data */ - av_dlog(asf, "READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n", - s->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; + return 0; +} - if (asf->packet_frag_offset >= asf_st->pkt.size || - asf->packet_frag_size > asf_st->pkt.size - asf->packet_frag_offset) { - av_log(s, AV_LOG_ERROR, - "packet fragment position invalid %u,%u not in %u\n", - asf->packet_frag_offset, asf->packet_frag_size, - asf_st->pkt.size); - continue; +static int asf_read_packet_header(AVFormatContext *s) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + uint64_t size; + uint32_t av_unused seq; + unsigned char error_flags, len_flags, pay_flags; + + asf->packet_offset = avio_tell(pb); + error_flags = avio_r8(pb); // read Error Correction Flags + if (error_flags & ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT) { + if (!(error_flags & ASF_ERROR_CORRECTION_LENGTH_TYPE)) { + size = error_flags & ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; + avio_skip(pb, size); } + len_flags = avio_r8(pb); + } else + len_flags = error_flags; + asf->prop_flags = avio_r8(pb); + READ_LEN(len_flags & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE, + ASF_PPI_FLAG_PACKET_LENGTH_FIELD_, asf->packet_size_internal); + READ_LEN(len_flags & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE, + ASF_PPI_FLAG_SEQUENCE_FIELD_, seq); + READ_LEN(len_flags & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE, + ASF_PPI_FLAG_PADDING_LENGTH_FIELD_, asf->pad_len ); + asf->send_time = avio_rl32(pb); // send time + avio_skip(pb, 2); // skip duration + if (len_flags & ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT) { // Multiple Payloads present + pay_flags = avio_r8(pb); + asf->nb_mult_left = (pay_flags & ASF_NUM_OF_PAYLOADS); + } - ret = avio_read(pb, asf_st->pkt.data + asf->packet_frag_offset, - asf->packet_frag_size); - if (ret != asf->packet_frag_size) { - if (ret < 0 || asf->packet_frag_offset + ret == 0) - return ret < 0 ? ret : AVERROR_EOF; - - if (asf_st->ds_span > 1) { - // scrambling, we can either drop it completely or fill the remainder - // TODO: should we fill the whole packet instead of just the current - // fragment? - memset(asf_st->pkt.data + asf->packet_frag_offset + ret, 0, - asf->packet_frag_size - ret); - ret = asf->packet_frag_size; - } else { - // no scrambling, so we can return partial packets - av_shrink_packet(&asf_st->pkt, asf->packet_frag_offset + ret); - } + return 0; +} + +static int asf_deinterleave(AVFormatContext *s, ASFPacket *asf_pkt, int st_num) +{ + ASFContext *asf = s->priv_data; + ASFStream *asf_st = asf->asf_st[st_num]; + unsigned char *p = asf_pkt->avpkt.data; + uint16_t pkt_len = asf->asf_st[st_num]->virtual_pkt_len; + uint16_t chunk_len = asf->asf_st[st_num]->virtual_chunk_len; + int nchunks = pkt_len / chunk_len; + AVPacket pkt; + int pos = 0, j, l, ret; + + + if ((ret = av_new_packet(&pkt, asf_pkt->data_size)) < 0) + return ret; + + while (asf_pkt->data_size >= asf_st->span * pkt_len + pos) { + if (pos >= asf_pkt->data_size) { + break; } - if (s->key && s->keylen == 20) - ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset, - ret); - asf_st->frag_offset += ret; - /* test if whole packet is read */ - if (asf_st->frag_offset == asf_st->pkt.size) { - // workaround for macroshit radio DVR-MS files - if (s->streams[asf->stream_index]->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO && - asf_st->pkt.size > 100) { - int i; - for (i = 0; i < asf_st->pkt.size && !asf_st->pkt.data[i]; i++) - ; - if (i == asf_st->pkt.size) { - av_log(s, AV_LOG_DEBUG, "discarding ms fart\n"); - asf_st->frag_offset = 0; - av_free_packet(&asf_st->pkt); - continue; - } + for (l = 0; l < pkt_len; l++) { + if (pos >= asf_pkt->data_size) { + break; } - - /* return packet */ - if (asf_st->ds_span > 1) { - if (asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span) { - av_log(s, AV_LOG_ERROR, - "pkt.size != ds_packet_size * ds_span (%d %d %d)\n", - asf_st->pkt.size, asf_st->ds_packet_size, - asf_st->ds_span); - } else { - /* packet descrambling */ - AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (buf) { - uint8_t *newdata = buf->data; - int offset = 0; - memset(newdata + asf_st->pkt.size, 0, - FF_INPUT_BUFFER_PADDING_SIZE); - 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; - assert(offset + asf_st->ds_chunk_size <= asf_st->pkt.size); - assert(idx + 1 <= asf_st->pkt.size / asf_st->ds_chunk_size); - 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_buffer_unref(&asf_st->pkt.buf); - asf_st->pkt.buf = buf; - asf_st->pkt.data = buf->data; - } - } + for (j = 0; j < asf_st->span; j++) { + if ((pos + chunk_len) >= asf_pkt->data_size) + break; + memcpy(pkt.data + pos, + p + (j * nchunks + l) * chunk_len, + chunk_len); + pos += chunk_len; } - asf_st->frag_offset = 0; - *pkt = asf_st->pkt; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - asf_st->pkt.destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - asf_st->pkt.buf = 0; - asf_st->pkt.size = 0; - asf_st->pkt.data = 0; - asf_st->pkt.side_data_elems = 0; - asf_st->pkt.side_data = NULL; - break; // packet completed } + p += asf_st->span * pkt_len; + if (p > asf_pkt->avpkt.data + asf_pkt->data_size) + break; } + av_packet_unref(&asf_pkt->avpkt); + asf_pkt->avpkt = pkt; + return 0; } static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) { ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int ret, i; - for (;;) { - int ret; - - /* parse cached packets, if any */ - if ((ret = asf_parse_packet(s, s->pb, pkt)) <= 0) + if ((avio_tell(pb) >= asf->data_offset + asf->data_size) && + !(asf->b_flags & ASF_FLAG_BROADCAST)) + return AVERROR_EOF; + while (!pb->eof_reached) { + if (asf->state == PARSE_PACKET_HEADER) { + asf_read_packet_header(s); + if (pb->eof_reached) + break; + if (!asf->nb_mult_left) + asf->state = READ_SINGLE; + else + asf->state = READ_MULTI; + } + ret = asf_read_payload(s, pkt); + if (ret == AVERROR(EAGAIN)) { + asf->state = PARSE_PACKET_HEADER; + continue; + } + else if (ret < 0) return ret; - if ((ret = asf_get_packet(s, s->pb)) < 0) - assert(asf->packet_size_left < FRAME_HEADER_SIZE || - asf->packet_segments < 1); - asf->packet_time_start = 0; + + switch (asf->state) { + case READ_SINGLE: + if (!asf->sub_left) + asf->state = PARSE_PACKET_HEADER; + break; + case READ_MULTI_SUB: + if (!asf->sub_left && !asf->nb_mult_left) { + asf->state = PARSE_PACKET_HEADER; + if (!asf->return_subpayload && + (avio_tell(pb) <= asf->packet_offset + + asf->packet_size - asf->pad_len)) + avio_skip(pb, asf->pad_len); // skip padding + if (asf->packet_offset + asf->packet_size > avio_tell(pb)) + avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); + } else if (!asf->sub_left) + asf->state = READ_MULTI; + break; + case READ_MULTI: + if (!asf->nb_mult_left) { + asf->state = PARSE_PACKET_HEADER; + if (!asf->return_subpayload && + (avio_tell(pb) <= asf->packet_offset + + asf->packet_size - asf->pad_len)) + avio_skip(pb, asf->pad_len); // skip padding + if (asf->packet_offset + asf->packet_size > avio_tell(pb)) + avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET); + } + break; + } + if (asf->return_subpayload) { + asf->return_subpayload = 0; + return 0; + } + for (i = 0; i < asf->nb_streams; i++) { + ASFPacket *asf_pkt = &asf->asf_st[i]->pkt; + if (asf_pkt && !asf_pkt->size_left && asf_pkt->data_size) { + if (asf->asf_st[i]->span > 1 && + asf->asf_st[i]->type == AVMEDIA_TYPE_AUDIO) + if ((ret = asf_deinterleave(s, asf_pkt, i)) < 0) + return ret; + av_packet_move_ref(pkt, &asf_pkt->avpkt); + pkt->stream_index = asf->asf_st[i]->index; + pkt->flags = asf_pkt->flags; + pkt->dts = asf_pkt->dts - asf->preroll; + asf_pkt->data_size = 0; + asf_pkt->frame_num = 0; + return 0; + } + } } + + if (pb->eof_reached) + return AVERROR_EOF; + + 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) +static int asf_read_close(AVFormatContext *s) { ASFContext *asf = s->priv_data; - ASFStream *asf_st; int i; - 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; - if (!asf_st) - continue; - av_free_packet(&asf_st->pkt); - asf_st->frag_offset = 0; - asf_st->seq = 0; + for (i = 0; i < ASF_MAX_STREAMS; i++) { + av_dict_free(&asf->asf_sd[i].asf_met); + if (i < asf->nb_streams) { + av_packet_unref(&asf->asf_st[i]->pkt.avpkt); + av_freep(&asf->asf_st[i]); + } } - asf->asf_st = NULL; + + asf->nb_streams = 0; + return 0; } -static int asf_read_close(AVFormatContext *s) +static void reset_packet_state(AVFormatContext *s) { - asf_reset_header(s); + ASFContext *asf = s->priv_data; + int i; - return 0; + asf->state = PARSE_PACKET_HEADER; + asf->offset = 0; + asf->return_subpayload = 0; + asf->sub_left = 0; + asf->sub_header_offset = 0; + asf->packet_offset = asf->first_packet_offset; + asf->pad_len = 0; + asf->rep_data_len = 0; + asf->dts_delta = 0; + asf->mult_sub_len = 0; + asf->nb_mult_left = 0; + asf->nb_sub = 0; + asf->prop_flags = 0; + asf->sub_dts = 0; + for (i = 0; i < asf->nb_streams; i++) { + ASFPacket *pkt = &asf->asf_st[i]->pkt; + pkt->size_left = 0; + pkt->data_size = 0; + pkt->duration = 0; + pkt->flags = 0; + pkt->dts = 0; + pkt->duration = 0; + av_packet_unref(&pkt->avpkt); + av_init_packet(&pkt->avpkt); + } } -static int64_t asf_read_pts(AVFormatContext *s, int stream_index, - int64_t *ppos, int64_t pos_limit) +/* + * Find a timestamp for the requested position within the payload + * where the pos (position) is the offset inside the Data Object. + * When position is not on the packet boundary, asf_read_timestamp tries + * to find the closest packet offset after this position. If this packet + * is a key frame, this packet timestamp is read and an index entry is created + * for the packet. If this packet belongs to the requested stream, + * asf_read_timestamp upgrades pos to the packet beginning offset and + * returns this packet's dts. So returned dts is the dts of the first key frame with + * matching stream number after given position. + */ +static int64_t asf_read_timestamp(AVFormatContext *s, int stream_index, + int64_t *pos, int64_t pos_limit) { - AVPacket pkt1, *pkt = &pkt1; - ASFStream *asf_st; - int64_t pts; - int64_t pos = *ppos; - int i; - int64_t start_pos[ASF_MAX_STREAMS]; - - for (i = 0; i < s->nb_streams; i++) - start_pos[i] = pos; - - if (s->packet_size > 0) - pos = (pos + s->packet_size - 1 - s->data_offset) / - s->packet_size * s->packet_size + - s->data_offset; - *ppos = pos; - avio_seek(s->pb, pos, SEEK_SET); - - asf_reset_header(s); - for (;;) { - if (asf_read_packet(s, pkt) < 0) { - av_log(s, AV_LOG_INFO, "asf_read_pts failed\n"); - return AV_NOPTS_VALUE; - } + ASFContext *asf = s->priv_data; + int64_t pkt_pos = *pos, pkt_offset, dts = AV_NOPTS_VALUE, data_end; + AVPacket pkt; + int n; - pts = pkt->dts; + data_end = asf->data_offset + asf->data_size; - av_free_packet(pkt); - if (pkt->flags & AV_PKT_FLAG_KEY) { - i = pkt->stream_index; + n = (pkt_pos - asf->first_packet_offset + asf->packet_size - 1) / + asf->packet_size; + n = av_clip(n, 0, ((data_end - asf->first_packet_offset) / asf->packet_size - 1)); + pkt_pos = asf->first_packet_offset + n * asf->packet_size; - asf_st = s->streams[i]->priv_data; - av_assert0(asf_st); + avio_seek(s->pb, pkt_pos, SEEK_SET); + pkt_offset = pkt_pos; -// assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0); - pos = asf_st->packet_pos; + reset_packet_state(s); + while (avio_tell(s->pb) < data_end) { - 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; + int i, ret, st_found; - if (pkt->stream_index == stream_index) - break; + av_init_packet(&pkt); + pkt_offset = avio_tell(s->pb); + if ((ret = asf_read_packet(s, &pkt)) < 0) { + dts = AV_NOPTS_VALUE; + return ret; + } + // ASFPacket may contain fragments of packets belonging to different streams, + // pkt_offset is the offset of the first fragment within it. + if ((pkt_offset >= (pkt_pos + asf->packet_size))) + pkt_pos += asf->packet_size; + for (i = 0; i < asf->nb_streams; i++) { + ASFStream *st = asf->asf_st[i]; + + st_found = 0; + if (pkt.flags & AV_PKT_FLAG_KEY) { + dts = pkt.dts; + if (dts) { + av_add_index_entry(s->streams[pkt.stream_index], pkt_pos, + dts, pkt.size, 0, AVINDEX_KEYFRAME); + if (stream_index == st->index) { + st_found = 1; + break; + } + } + } } + if (st_found) + break; + av_packet_unref(&pkt); } + *pos = pkt_pos; - *ppos = pos; - return pts; + av_packet_unref(&pkt); + return dts; } -static int asf_build_simple_index(AVFormatContext *s, int stream_index) +static int asf_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { - ff_asf_guid g; - ASFContext *asf = s->priv_data; - int64_t current_pos = avio_tell(s->pb); - int i, ret = 0; - - avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET); - if ((ret = ff_get_guid(s->pb, &g)) < 0) - goto end; - - /* the data object can be followed by other top-level objects, - * skip them until the simple index object is reached */ - while (ff_guidcmp(&g, &index_guid)) { - int64_t gsize = avio_rl64(s->pb); - if (gsize < 24 || s->pb->eof_reached) { - goto end; - } - avio_skip(s->pb, gsize - 24); - if ((ret = ff_get_guid(s->pb, &g)) < 0) - goto end; + ASFContext *asf = s->priv_data; + int idx, ret; + + if (s->streams[stream_index]->nb_index_entries && asf->is_simple_index) { + idx = av_index_search_timestamp(s->streams[stream_index], timestamp, flags); + if (idx < 0 || idx >= s->streams[stream_index]->nb_index_entries) + return AVERROR_INVALIDDATA; + avio_seek(s->pb, s->streams[stream_index]->index_entries[idx].pos, SEEK_SET); + } else { + if ((ret = ff_seek_frame_binary(s, stream_index, timestamp, flags)) < 0) + return ret; } - { - int64_t itime, last_pos = -1; - int pct, ict; - int64_t av_unused gsize = avio_rl64(s->pb); - if ((ret = ff_get_guid(s->pb, &g)) < 0) - goto end; - itime = avio_rl64(s->pb); - pct = avio_rl32(s->pb); - ict = avio_rl32(s->pb); - av_log(s, AV_LOG_DEBUG, - "itime:0x%"PRIx64", pct:%d, ict:%d\n", itime, pct, ict); - - for (i = 0; i < ict; i++) { - int pktnum = avio_rl32(s->pb); - int pktct = avio_rl16(s->pb); - int64_t pos = s->data_offset + s->packet_size * (int64_t)pktnum; - int64_t index_pts = FFMAX(av_rescale(itime, i, 10000) - asf->hdr.preroll, 0); - - if (pos != last_pos) { - av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d pts: %"PRId64"\n", - pktnum, pktct, index_pts); - av_add_index_entry(s->streams[stream_index], pos, index_pts, - s->packet_size, 0, AVINDEX_KEYFRAME); - last_pos = pos; - } - } - asf->index_read = ict > 0; + reset_packet_state(s); + + return 0; +} + +static const GUIDParseTable *find_guid(ff_asf_guid guid) +{ + int j, ret; + const GUIDParseTable *g; + + swap_guid(guid); + g = gdef; + for (j = 0; j < FF_ARRAY_ELEMS(gdef); j++) { + if (!(ret = memcmp(guid, g->guid, sizeof(g->guid)))) + return g; + g++; } -end: - if (s->pb->eof_reached) - ret = 0; - avio_seek(s->pb, current_pos, SEEK_SET); - return ret; + + return NULL; } -static int asf_read_seek(AVFormatContext *s, int stream_index, - int64_t pts, int flags) +static int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size) { ASFContext *asf = s->priv_data; - AVStream *st = s->streams[stream_index]; - int64_t pos; - int index, ret = 0; - - if (s->packet_size <= 0) - return -1; - - /* Try using the protocol's read_seek if available */ - if (s->pb) { - int ret = avio_seek_time(s->pb, stream_index, pts, flags); - if (ret >= 0) - asf_reset_header(s); - if (ret != AVERROR(ENOSYS)) + AVIOContext *pb = s->pb; + const GUIDParseTable *g = NULL; + ff_asf_guid guid; + int ret; + + while (avio_tell(pb) <= offset + size) { + if (avio_tell(pb) == asf->offset) + break; + asf->offset = avio_tell(pb); + if ((ret = ff_get_guid(pb, &guid)) < 0) return ret; + g = find_guid(guid); + if (g) { + if ((ret = g->read_object(s, g)) < 0) + return ret; + } else { + GUIDParseTable g2; + + g2.name = "Unknown"; + g2.is_subobject = 1; + asf_read_unknown(s, &g2); + } } - /* explicitly handle the case of seeking to 0 */ - if (!pts) { - asf_reset_header(s); - avio_seek(s->pb, s->data_offset, SEEK_SET); - return 0; + return 0; +} + +static int asf_read_header(AVFormatContext *s) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + const GUIDParseTable *g = NULL; + ff_asf_guid guid; + int i, ret; + uint64_t size; + + asf->preroll = 0; + asf->is_simple_index = 0; + ff_get_guid(pb, &guid); + if (ff_guidcmp(&guid, &ff_asf_header)) + return AVERROR_INVALIDDATA; + avio_skip(pb, 8); // skip header object size + avio_skip(pb, 6); // skip number of header objects and 2 reserved bytes + asf->data_reached = 0; + + /* 1 is here instead of pb->eof_reached because (when not streaming), Data are skipped + * for the first time, + * Index object is processed and got eof and then seeking back to the Data is performed. + */ + while (1) { + // for the cases when object size is invalid + if (avio_tell(pb) == asf->offset) + break; + asf->offset = avio_tell(pb); + if ((ret = ff_get_guid(pb, &guid)) < 0) { + if (ret == AVERROR_EOF && asf->data_reached) + break; + else + goto failed; + } + g = find_guid(guid); + if (g) { + asf->unknown_offset = asf->offset; + asf->is_header = 1; + if ((ret = g->read_object(s, g)) < 0) + goto failed; + } else { + size = avio_rl64(pb); + align_position(pb, asf->offset, size); + } + if (asf->data_reached && (!pb->seekable || (asf->b_flags & ASF_FLAG_BROADCAST))) + break; + } + + if (!asf->data_reached) { + av_log(s, AV_LOG_ERROR, "Data Object was not found.\n"); + ret = AVERROR_INVALIDDATA; + goto failed; } + if (pb->seekable) + avio_seek(pb, asf->first_packet_offset, SEEK_SET); - if (!asf->index_read) - ret = asf_build_simple_index(s, stream_index); + for (i = 0; i < asf->nb_streams; i++) { + const char *rfc1766 = asf->asf_sd[asf->asf_st[i]->lang_idx].langs; + AVStream *st = s->streams[asf->asf_st[i]->index]; + set_language(s, rfc1766, &st->metadata); + } - if (!ret && asf->index_read && st->index_entries) { - index = av_index_search_timestamp(st, pts, flags); - if (index >= 0) { - /* find the position */ - pos = st->index_entries[index].pos; + for (i = 0; i < ASF_MAX_STREAMS; i++) { + AVStream *st = NULL; - /* do the seek */ - av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos); - avio_seek(s->pb, pos, SEEK_SET); - asf_reset_header(s); - return 0; + st = find_stream(s, i); + if (st) { + av_dict_copy(&st->metadata, asf->asf_sd[i].asf_met, AV_DICT_IGNORE_SUFFIX); + if (asf->asf_sd[i].aspect_ratio.num > 0 && asf->asf_sd[i].aspect_ratio.den > 0) { + st->sample_aspect_ratio.num = asf->asf_sd[i].aspect_ratio.num; + st->sample_aspect_ratio.den = asf->asf_sd[i].aspect_ratio.den; + } } } - /* no index or seeking by index failed */ - if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0) - return -1; - asf_reset_header(s); + return 0; + +failed: + asf_read_close(s); + return ret; } AVInputFormat ff_asf_demuxer = { @@ -1515,8 +1787,7 @@ AVInputFormat ff_asf_demuxer = { .read_header = asf_read_header, .read_packet = asf_read_packet, .read_close = asf_read_close, + .read_timestamp = asf_read_timestamp, .read_seek = asf_read_seek, - .read_timestamp = asf_read_pts, .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH, - .priv_class = &asf_class, }; diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 79b44a7..dc1dd73 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -185,13 +185,33 @@ #define DATA_HEADER_SIZE 50 -typedef struct { +typedef struct ASFStream { + int num; + unsigned char seq; + /* use for reading */ + AVPacket pkt; + int frag_offset; + int timestamp; + + int ds_span; /* descrambling */ + int ds_packet_size; + int ds_chunk_size; + + int64_t packet_pos; + + uint16_t stream_language_index; + + int palette_changed; + uint32_t palette[256]; +} ASFStream; + +typedef struct ASFContext { uint32_t seqno; int is_streamed; ASFStream streams[128]; ///< it's max number and it's not that big - /* non streamed additonnal info */ + /* non-streamed additional info */ uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting - int64_t duration; ///< in 100ns units + uint64_t duration; ///< in ms /* packet filling */ unsigned char multi_payloads_present; int packet_size_left; @@ -356,10 +376,10 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; int has_title; int metadata_count; - AVCodecContext *enc; + AVCodecParameters *par; int64_t header_offset, cur_pos, hpos; int bit_rate; - int64_t duration; + uint64_t play_duration, send_duration; ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL); @@ -369,17 +389,27 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, tags[3] = av_dict_get(s->metadata, "comment", NULL, 0); tags[4] = av_dict_get(s->metadata, "rating", NULL, 0); - duration = asf->duration + PREROLL_TIME * 10000; + if (asf->duration > UINT64_MAX / 10000 - PREROLL_TIME) { + av_log(s, AV_LOG_WARNING, "Duration %"PRIu64" too large\n", asf->duration); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR(ERANGE); + send_duration = 0; + play_duration = 0; + } else { + send_duration = asf->duration * 10000; + play_duration = (asf->duration + PREROLL_TIME) * 10000; + } + has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; metadata_count = av_dict_count(s->metadata); bit_rate = 0; for (n = 0; n < s->nb_streams; n++) { - enc = s->streams[n]->codec; + par = s->streams[n]->codecpar; avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ - bit_rate += enc->bit_rate; + bit_rate += par->bit_rate; } if (asf->is_streamed) { @@ -400,8 +430,8 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, file_time = 0; avio_wl64(pb, unix_to_file_time(file_time)); avio_wl64(pb, asf->nb_packets); /* number of packets */ - avio_wl64(pb, duration); /* end time stamp (in 100ns units) */ - avio_wl64(pb, asf->duration); /* duration (in 100ns units) */ + avio_wl64(pb, play_duration); /* end time stamp (in 100ns units) */ + avio_wl64(pb, send_duration); /* duration (in 100ns units) */ avio_wl64(pb, PREROLL_TIME); /* start time stamp */ avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2); /* ??? */ avio_wl32(pb, s->packet_size); /* packet size */ @@ -416,7 +446,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avio_wl16(pb, 0); end_header(pb, hpos); - /* title and other infos */ + /* title and other info */ if (has_title) { int len; uint8_t *buf; @@ -458,11 +488,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t es_pos; // ASFStream *stream = &asf->streams[n]; - enc = s->streams[n]->codec; + par = s->streams[n]->codecpar; asf->streams[n].num = n + 1; asf->streams[n].seq = 0; - switch (enc->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: wav_extra_size = 0; extra_size = 18 + wav_extra_size; @@ -470,14 +500,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, break; default: case AVMEDIA_TYPE_VIDEO: - wav_extra_size = enc->extradata_size; + wav_extra_size = par->extradata_size; extra_size = 0x33 + wav_extra_size; extra_size2 = 0; break; } hpos = put_header(pb, &ff_asf_stream_header); - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { + if (par->codec_type == AVMEDIA_TYPE_AUDIO) { put_guid(pb, &ff_asf_audio_stream); put_guid(pb, &ff_asf_audio_conceal_spread); } else { @@ -491,9 +521,9 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avio_wl16(pb, n + 1); /* stream number */ avio_wl32(pb, 0); /* ??? */ - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { + if (par->codec_type == AVMEDIA_TYPE_AUDIO) { /* WAVEFORMATEX header */ - int wavsize = ff_put_wav_header(pb, enc); + int wavsize = ff_put_wav_header(s, pb, par); if (wavsize < 0) return -1; @@ -505,23 +535,23 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, } /* ERROR Correction */ avio_w8(pb, 0x01); - if (enc->codec_id == AV_CODEC_ID_ADPCM_G726 || !enc->block_align) { + if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) { avio_wl16(pb, 0x0190); avio_wl16(pb, 0x0190); } else { - avio_wl16(pb, enc->block_align); - avio_wl16(pb, enc->block_align); + avio_wl16(pb, par->block_align); + avio_wl16(pb, par->block_align); } avio_wl16(pb, 0x01); avio_w8(pb, 0x00); } else { - avio_wl32(pb, enc->width); - avio_wl32(pb, enc->height); + avio_wl32(pb, par->width); + avio_wl32(pb, par->height); avio_w8(pb, 2); /* ??? */ - avio_wl16(pb, 40 + enc->extradata_size); /* size */ + avio_wl16(pb, 40 + par->extradata_size); /* size */ /* BITMAPINFOHEADER header */ - ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1); + ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1); } end_header(pb, hpos); } @@ -535,17 +565,17 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, const AVCodecDescriptor *codec_desc; const char *desc; - enc = s->streams[n]->codec; - codec_desc = avcodec_descriptor_get(enc->codec_id); + par = s->streams[n]->codecpar; + codec_desc = avcodec_descriptor_get(par->codec_id); - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (par->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl16(pb, 2); - else if (enc->codec_type == AVMEDIA_TYPE_VIDEO) + else if (par->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl16(pb, 1); else avio_wl16(pb, -1); - if (enc->codec_id == AV_CODEC_ID_WMAV2) + if (par->codec_id == AV_CODEC_ID_WMAV2) desc = "Windows Media Audio V8"; else desc = codec_desc ? codec_desc->name : NULL; @@ -570,14 +600,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avio_wl16(pb, 0); /* no parameters */ /* id */ - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { + if (par->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wl16(pb, 2); - avio_wl16(pb, enc->codec_tag); + avio_wl16(pb, par->codec_tag); } else { avio_wl16(pb, 4); - avio_wl32(pb, enc->codec_tag); + avio_wl32(pb, par->codec_tag); } - if (!enc->codec_tag) + if (!par->codec_tag) return -1; } end_header(pb, hpos); @@ -630,6 +660,7 @@ static int asf_write_header(AVFormatContext *s) * It is needed to use asf as a streamable format. */ if (asf_write_header1(s, 0, DATA_HEADER_SIZE) < 0) { //av_free(asf); + av_freep(&asf->index_ptr); return -1; } @@ -791,7 +822,7 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst, PACKET_HEADER_MIN_SIZE - 1; if (frag_len1 < payload_len && - avst->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { flush_packet(s); continue; } @@ -832,23 +863,24 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; ASFStream *stream; - int64_t duration; - AVCodecContext *codec; + AVCodecParameters *par; int64_t packet_st, pts; int start_sec, i; int flags = pkt->flags; uint64_t offset = avio_tell(pb); - codec = s->streams[pkt->stream_index]->codec; + par = s->streams[pkt->stream_index]->codecpar; stream = &asf->streams[pkt->stream_index]; - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (par->codec_type == AVMEDIA_TYPE_AUDIO) flags &= ~AV_PKT_FLAG_KEY; pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; assert(pts != AV_NOPTS_VALUE); - duration = pts * 10000; - asf->duration = FFMAX(asf->duration, duration + pkt->duration * 10000); + + if (pts > UINT64_MAX - pkt->duration) + return AVERROR(ERANGE); + asf->duration = FFMAX(asf->duration, pts + pkt->duration); packet_st = asf->nb_packets; put_frame(s, stream, s->streams[pkt->stream_index], @@ -856,8 +888,11 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) /* check index */ if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) { - start_sec = (int)(duration / INT64_C(10000000)); - if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) { + if (pts / 1000LL > INT_MAX) + return AVERROR(ERANGE); + + start_sec = pts / 1000; + if (start_sec != asf->last_indexed_pts / 1000) { for (i = asf->nb_index_count; i < start_sec; i++) { if (i >= asf->nb_index_memory_alloc) { int err; @@ -878,7 +913,7 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) (uint16_t)(asf->nb_packets - packet_st)); } asf->nb_index_count = start_sec; - asf->last_indexed_pts = duration; + asf->last_indexed_pts = pts; } } return 0; diff --git a/libavformat/assdec.c b/libavformat/assdec.c index 08c1222..059cefe 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -63,7 +63,7 @@ static int64_t get_pts(const uint8_t *p) if (sscanf(p, "%*[^,],%d:%d:%d%*c%d", &hour, &min, &sec, &hsec) != 4) return AV_NOPTS_VALUE; - av_dlog(NULL, "%d %d %d %d [%s]\n", hour, min, sec, hsec, p); + av_log(NULL, AV_LOG_TRACE, "%d %d %d %d [%s]\n", hour, min, sec, hsec, p); min += 60 * hour; sec += 60 * min; @@ -91,11 +91,11 @@ static int read_header(AVFormatContext *s) if (!st) return -1; avpriv_set_pts_info(st, 64, 1, 100); - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = AV_CODEC_ID_SSA; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_SSA; header_remaining = INT_MAX; - dst[0] = &st->codec->extradata; + dst[0] = &st->codecpar->extradata; dst[1] = &ass->event_buffer; while (!pb->eof_reached) { uint8_t line[MAX_LINESIZE]; @@ -123,7 +123,7 @@ static int read_header(AVFormatContext *s) else header_remaining--; } - st->codec->extradata_size = pos[0]; + st->codecpar->extradata_size = pos[0]; if (ass->event_count >= UINT_MAX / sizeof(*ass->event)) goto fail; @@ -163,7 +163,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; pkt->flags |= AV_PKT_FLAG_KEY; - pkt->pos = p - ass->event_buffer + s->streams[0]->codec->extradata_size; + pkt->pos = p - ass->event_buffer + s->streams[0]->codecpar->extradata_size; pkt->pts = pkt->dts = get_pts(p); memcpy(pkt->data, p, pkt->size); diff --git a/libavformat/assenc.c b/libavformat/assenc.c index 751485d..c6f9851 100644 --- a/libavformat/assenc.c +++ b/libavformat/assenc.c @@ -28,18 +28,18 @@ typedef struct ASSContext{ static int write_header(AVFormatContext *s) { ASSContext *ass = s->priv_data; - AVCodecContext *avctx= s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; uint8_t *last= NULL; - if(s->nb_streams != 1 || avctx->codec_id != AV_CODEC_ID_SSA){ + if(s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_SSA){ av_log(s, AV_LOG_ERROR, "Exactly one ASS/SSA stream is needed.\n"); return -1; } - while(ass->extra_index < avctx->extradata_size){ - uint8_t *p = avctx->extradata + ass->extra_index; + while(ass->extra_index < par->extradata_size){ + uint8_t *p = par->extradata + ass->extra_index; uint8_t *end= strchr(p, '\n'); - if(!end) end= avctx->extradata + avctx->extradata_size; + if(!end) end= par->extradata + par->extradata_size; else end++; avio_write(s->pb, p, end-p); @@ -64,10 +64,10 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) static int write_trailer(AVFormatContext *s) { ASSContext *ass = s->priv_data; - AVCodecContext *avctx= s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; - avio_write(s->pb, avctx->extradata + ass->extra_index, - avctx->extradata_size - ass->extra_index); + avio_write(s->pb, par->extradata + ass->extra_index, + par->extradata_size - ass->extra_index); return 0; } diff --git a/libavformat/au.c b/libavformat/au.c index e682cbf..e303142 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -108,13 +108,13 @@ static int au_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = id; - st->codec->codec_id = codec; - st->codec->channels = channels; - st->codec->sample_rate = rate; - st->codec->bit_rate = channels * rate * bps; - st->codec->block_align = channels * bps >> 3; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = id; + st->codecpar->codec_id = codec; + st->codecpar->channels = channels; + st->codecpar->sample_rate = rate; + st->codecpar->bit_rate = channels * rate * bps; + st->codecpar->block_align = channels * bps >> 3; st->start_time = 0; avpriv_set_pts_info(st, 64, 1, rate); @@ -127,12 +127,12 @@ static int au_read_packet(AVFormatContext *s, AVPacket *pkt) int ret; ret = av_get_packet(s->pb, pkt, BLOCK_SIZE * - s->streams[0]->codec->block_align); + s->streams[0]->codecpar->block_align); if (ret < 0) return ret; pkt->stream_index = 0; - pkt->duration = ret / s->streams[0]->codec->block_align; + pkt->duration = ret / s->streams[0]->codecpar->block_align; return 0; } @@ -157,17 +157,17 @@ AVInputFormat ff_au_demuxer = { #define AU_UNKNOWN_SIZE ((uint32_t)(~0)) /* AUDIO_FILE header */ -static int put_au_header(AVIOContext *pb, AVCodecContext *enc) +static int put_au_header(AVIOContext *pb, AVCodecParameters *par) { - if (!enc->codec_tag) + if (!par->codec_tag) return AVERROR(EINVAL); ffio_wfourcc(pb, ".snd"); /* magic number */ avio_wb32(pb, 24); /* header size */ avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */ - avio_wb32(pb, enc->codec_tag); /* codec ID */ - avio_wb32(pb, enc->sample_rate); - avio_wb32(pb, enc->channels); + avio_wb32(pb, par->codec_tag); /* codec ID */ + avio_wb32(pb, par->sample_rate); + avio_wb32(pb, par->channels); return 0; } @@ -179,7 +179,7 @@ static int au_write_header(AVFormatContext *s) s->priv_data = NULL; - if ((ret = put_au_header(pb, s->streams[0]->codec)) < 0) + if ((ret = put_au_header(pb, s->streams[0]->codecpar)) < 0) return ret; avio_flush(pb); diff --git a/libavformat/audiointerleave.c b/libavformat/audiointerleave.c index ba78d4e..aa379f6 100644 --- a/libavformat/audiointerleave.c +++ b/libavformat/audiointerleave.c @@ -33,7 +33,7 @@ void ff_audio_interleave_close(AVFormatContext *s) AVStream *st = s->streams[i]; AudioInterleaveContext *aic = st->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) av_fifo_free(aic->fifo); } } @@ -51,9 +51,9 @@ int ff_audio_interleave_init(AVFormatContext *s, AVStream *st = s->streams[i]; AudioInterleaveContext *aic = st->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - aic->sample_size = (st->codec->channels * - av_get_bits_per_sample(st->codec->codec_id)) / 8; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + aic->sample_size = (st->codecpar->channels * + av_get_bits_per_sample(st->codecpar->codec_id)) / 8; if (!aic->sample_size) { av_log(s, AV_LOG_ERROR, "could not compute sample size\n"); return -1; @@ -106,7 +106,7 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt if (pkt) { AVStream *st = s->streams[pkt->stream_index]; AudioInterleaveContext *aic = st->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned new_size = av_fifo_size(aic->fifo) + pkt->size; if (new_size > aic->fifo_size) { if (av_fifo_realloc2(aic->fifo, new_size) < 0) @@ -126,8 +126,8 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - AVPacket new_pkt; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + AVPacket new_pkt = { 0 }; while (interleave_new_audio_packet(s, &new_pkt, i, flush)) if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0) return ret; diff --git a/libavformat/avc.c b/libavformat/avc.c index 2fd5ac8..5bfbad8 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -106,7 +106,7 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { if (len > 6) { - /* check for h264 start code */ + /* check for H.264 start code */ if (AV_RB32(data) == 0x00000001 || AV_RB24(data) == 0x000001) { uint8_t *buf=NULL, *end, *start; @@ -191,3 +191,20 @@ int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size) *size = out_size; return 0; } + +const uint8_t *ff_avc_mp4_find_startcode(const uint8_t *start, + const uint8_t *end, + int nal_length_size) +{ + unsigned int res = 0; + + if (end - start < nal_length_size) + return NULL; + while (nal_length_size--) + res = (res << 8) | *start++; + + if (res > end - start) + return NULL; + + return start + res; +} diff --git a/libavformat/avc.h b/libavformat/avc.h index 579756e..2442e5f 100644 --- a/libavformat/avc.h +++ b/libavformat/avc.h @@ -30,5 +30,8 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size); int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len); const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end); int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size); +const uint8_t *ff_avc_mp4_find_startcode(const uint8_t *start, + const uint8_t *end, + int nal_length_size); #endif /* AVFORMAT_AVC_H */ diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 5b29145..65c3d90 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -149,8 +149,8 @@ * av_read_frame() on it. Each call, if successful, will return an AVPacket * containing encoded data for one AVStream, identified by * AVPacket.stream_index. This packet may be passed straight into the libavcodec - * decoding functions avcodec_decode_video2(), avcodec_decode_audio4() or - * avcodec_decode_subtitle2() if the caller wishes to decode the data. + * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the + * caller wishes to decode the data. * * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for @@ -165,7 +165,7 @@ * until the next av_read_frame() call or closing the file. If the caller * requires a longer lifetime, av_dup_packet() will make an av_malloc()ed copy * of it. - * In both cases, the packet must be freed with av_free_packet() when it is no + * In both cases, the packet must be freed with av_packet_unref() when it is no * longer needed. * * @section lavf_decoding_seek Seeking @@ -191,13 +191,17 @@ * avio_open2() or a custom one. * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must * be created with the avformat_new_stream() function. The caller should fill - * the @ref AVStream.codec "stream codec context" information, such as the - * codec @ref AVCodecContext.codec_type "type", @ref AVCodecContext.codec_id + * the @ref AVStream.codecpar "stream codec parameters" information, such as the + * codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id * "id" and other parameters (e.g. width / height, the pixel or sample format, * etc.) as known. The @ref AVStream.time_base "stream timebase" should * be set to the timebase that the caller desires to use for this stream (note * that the timebase actually used by the muxer can be different, as will be * described later). + * - It is advised to manually initialize only the relevant fields in + * AVCodecParameters, rather than using @ref avcodec_parameters_copy() during + * remuxing: there is no guarantee that the codec context values remain valid + * for both input and output format contexts. * - The caller may fill in additional information, such as @ref * AVFormatContext.metadata "global" or @ref AVStream.metadata "per-stream" * metadata, @ref AVFormatContext.chapters "chapters", @ref @@ -247,7 +251,6 @@ * @{ * @} * @} - * */ #include @@ -396,7 +399,7 @@ typedef struct AVProbeData { const char *filename; unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ int buf_size; /**< Size of buf except extra allocated bytes */ - uint8_t *mime_type; /**< mime_type, when known. */ + const char *mime_type; /**< mime_type, when known. */ } AVProbeData; #define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension @@ -409,8 +412,10 @@ typedef struct AVProbeData { #define AVFMT_NOFILE 0x0001 #define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ #define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ +#if FF_API_LAVF_FMT_RAWPICTURE #define AVFMT_RAWPICTURE 0x0020 /**< Format wants AVPicture structure for - raw picture data. */ + raw picture data. @deprecated Not used anymore */ +#endif #define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ #define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ #define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ @@ -450,10 +455,10 @@ typedef struct AVOutputFormat { enum AVCodecID video_codec; /**< default video codec */ enum AVCodecID subtitle_codec; /**< default subtitle codec */ /** - * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_RAWPICTURE, + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, - * AVFMT_TS_NONSTRICT + * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE */ int flags; @@ -577,8 +582,8 @@ typedef struct AVInputFormat { /** * Read the format header and initialize the AVFormatContext - * structure. Return 0 if OK. Only used in raw format right - * now. 'avformat_new_stream' should be called to create new streams. + * structure. Return 0 if OK. 'avformat_new_stream' should be + * called to create new streams. */ int (*read_header)(struct AVFormatContext *); @@ -682,6 +687,8 @@ typedef struct AVIndexEntry { */ #define AV_DISPOSITION_ATTACHED_PIC 0x0400 +typedef struct AVStreamInternal AVStreamInternal; + /** * Stream structure. * New fields can be added to the end with minor version bumps. @@ -697,18 +704,13 @@ typedef struct AVStream { * encoding: set by the user, replaced by libavformat if left unset */ int id; +#if FF_API_LAVF_AVCTX /** - * Codec context associated with this stream. Allocated and freed by - * libavformat. - * - * - decoding: The demuxer exports codec information stored in the headers - * here. - * - encoding: The user sets codec information, the muxer writes it to the - * output. Mandatory fields as specified in AVCodecContext - * documentation must be set even if this AVCodecContext is - * not actually used for encoding. + * @deprecated use the codecpar struct instead */ + attribute_deprecated AVCodecContext *codec; +#endif void *priv_data; #if FF_API_LAVF_FRAC @@ -811,6 +813,17 @@ typedef struct AVStream { int event_flags; #define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. + /* + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavformat and can be changed and @@ -872,6 +885,12 @@ typedef struct AVStream { support seeking natively. */ int nb_index_entries; unsigned int index_entries_allocated_size; + + /** + * An opaque field for libavformat internal usage. + * Must not be accessed in any way by callers. + */ + AVStreamInternal *internal; } AVStream; #define AV_PROGRAM_RUNNING 1 @@ -1192,60 +1211,80 @@ typedef struct AVFormatContext { int event_flags; #define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. - /***************************************************************** - * All fields below this line are not part of the public API. They - * may not be used outside of libavformat and can be changed and - * removed at will. - * New public fields should be added right above. - ***************************************************************** + /** + * Maximum number of packets to read while waiting for the first timestamp. + * Decoding only. */ + int max_ts_probe; /** - * This buffer is only needed when packets were already buffered but - * not decoded, for example to get the codec parameters in MPEG - * streams. + * Avoid negative timestamps during muxing. + * Any value of the AVFMT_AVOID_NEG_TS_* constants. + * Note, this only works when using av_interleaved_write_frame. + * - muxing: Set by user + * - demuxing: unused */ - struct AVPacketList *packet_buffer; - struct AVPacketList *packet_buffer_end; - - /* av_seek_frame() support */ - int64_t data_offset; /**< offset of the first packet */ + int avoid_negative_ts; +#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative +#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 /** - * Raw packets from the demuxer, prior to parsing and decoding. - * This buffer is used for buffering packets until the codec can - * be identified, as parsing cannot be done without knowing the - * codec. + * An opaque field for libavformat internal usage. + * Must not be accessed in any way by callers. */ - struct AVPacketList *raw_packet_buffer; - struct AVPacketList *raw_packet_buffer_end; + AVFormatInternal *internal; + /** - * Packets split by the parser get queued here. + * Arbitrary user data set by the caller. */ - struct AVPacketList *parse_queue; - struct AVPacketList *parse_queue_end; + void *opaque; + /** - * Remaining size available for raw_packet_buffer, in bytes. + * A callback for opening new IO streams. + * + * Whenever a muxer or a demuxer needs to open an IO stream (typically from + * avformat_open_input() for demuxers, but for certain formats can happen at + * other times as well), it will call this callback to obtain an IO context. + * + * @param s the format context + * @param pb on success, the newly opened IO context should be returned here + * @param url the url to open + * @param flags a combination of AVIO_FLAG_* + * @param options a dictionary of additional options, with the same + * semantics as in avio_open2() + * @return 0 on success, a negative AVERROR code on failure + * + * @note Certain muxers and demuxers do nesting, i.e. they open one or more + * additional internal format contexts. Thus the AVFormatContext pointer + * passed to this callback may be different from the one facing the caller. + * It will, however, have the same 'opaque' field. */ -#define RAW_PACKET_BUFFER_SIZE 2500000 - int raw_packet_buffer_remaining_size; + int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **options); /** - * Offset to remap timestamps to be non-negative. - * Expressed in timebase units. + * A callback for closing the streams opened with AVFormatContext.io_open(). */ - int64_t offset; + void (*io_close)(struct AVFormatContext *s, AVIOContext *pb); /** - * Timebase for the timestamp offset. + * A comma-separated list of protocol names that will not be used internally + * by libavformat. If this field is a non-empty string, then protocols + * listed here will be forbidden. + * + * This field should be set using AVOptions. */ - AVRational offset_timebase; + char *protocol_blacklist; /** - * An opaque field for libavformat internal usage. - * Must not be accessed in any way by callers. + * A comma-separated list of protocol names that can be used internally by + * libavformat. If this field is a non-empty string, all protocols not + * listed here will be forbidden. + * + * This field should be set using AVOptions. */ - AVFormatInternal *internal; + char *protocol_whitelist; } AVFormatContext; typedef struct AVPacketList { @@ -1361,6 +1400,16 @@ const AVClass *avformat_get_class(void); AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c); /** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t *av_stream_new_side_data(AVStream *stream, + enum AVPacketSideDataType type, int size); +/** * Get side information from stream. * * @param stream stream @@ -1516,7 +1565,7 @@ int av_find_best_stream(AVFormatContext *ic, * If pkt->buf is NULL, then the packet is valid until the next * av_read_frame() or until avformat_close_input(). Otherwise the packet * is valid indefinitely. In both cases the packet must be freed with - * av_free_packet when it is no longer needed. For video, the packet contains + * av_packet_unref when it is no longer needed. 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. @@ -1646,10 +1695,17 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options); *
* Packet's @ref AVPacket.stream_index "stream_index" field must be * set to the index of the corresponding stream in @ref - * AVFormatContext.streams "s->streams". It is very strongly - * recommended that timing information (@ref AVPacket.pts "pts", @ref - * AVPacket.dts "dts", @ref AVPacket.duration "duration") is set to - * correct values. + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets passed to this function must be strictly + * increasing when compared in their respective timebases (unless the + * output format is flagged with the AVFMT_TS_NONSTRICT, then they + * merely have to be nondecreasing). @ref AVPacket.duration + * "duration") should also be set if known. * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush * * @see av_interleaved_write_frame() @@ -1664,6 +1720,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); * increasing dts. Callers doing their own interleaving should call * av_write_frame() instead of this function. * + * Using this function instead of av_write_frame() can give muxers advance + * knowledge of future packets, improving e.g. the behaviour of the mp4 + * muxer for VFR content in fragmenting mode. + * * @param s media file handle * @param pkt The packet containing the data to be written. *
@@ -1679,10 +1739,16 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); *
* Packet's @ref AVPacket.stream_index "stream_index" field must be * set to the index of the corresponding stream in @ref - * AVFormatContext.streams "s->streams". It is very strongly - * recommended that timing information (@ref AVPacket.pts "pts", @ref - * AVPacket.dts "dts", @ref AVPacket.duration "duration") is set to - * correct values. + * AVFormatContext.streams "s->streams". + *
+ * The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts") + * must be set to correct values in the stream's timebase (unless the + * output format is flagged with the AVFMT_NOTIMESTAMPS flag, then + * they can be set to AV_NOPTS_VALUE). + * The dts for subsequent packets in one stream must be strictly + * increasing (unless the output format is flagged with the + * AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). + * @ref AVPacket.duration "duration") should also be set if known. * * @return 0 on success, a negative AVERROR on error. Libavformat will always * take care of freeing the packet, even if this function fails. @@ -1869,7 +1935,7 @@ void av_url_split(char *proto, int proto_size, * @param ic the context to analyze * @param index the index to print, if you have multiple inputs or outputs * @param url the URL to print, such as source or destination file - * @param is_output whether the context is input or ouput + * @param is_output whether the context is input or output */ void av_dump_format(AVFormatContext *ic, int index, diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 54c4814..c7fd271 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -31,6 +31,7 @@ #include "avi.h" #include "dv.h" #include "internal.h" +#include "isom.h" #include "riff.h" #undef NDEBUG @@ -42,6 +43,7 @@ typedef struct AVIStream { int remaining; int packet_size; + uint32_t handler; uint32_t scale; uint32_t rate; int sample_size; /* size of one sample (or packet) @@ -60,7 +62,7 @@ typedef struct AVIStream { uint8_t *sub_buffer; } AVIStream; -typedef struct { +typedef struct AVIContext { int64_t riff_end; int64_t movi_end; int64_t fsize; @@ -93,7 +95,7 @@ static int avi_load_index(AVFormatContext *s); static int guess_ni_flag(AVFormatContext *s); #define print_tag(str, tag, size) \ - av_dlog(NULL, "%s: tag=%c%c%c%c size=0x%x\n", \ + av_log(NULL, AV_LOG_TRACE, "%s: tag=%c%c%c%c size=0x%x\n", \ str, tag & 0xff, \ (tag >> 8) & 0xff, \ (tag >> 16) & 0xff, \ @@ -151,9 +153,9 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num) AVIStream *ast; int i; int64_t last_pos = -1; - int64_t filesize = avio_size(s->pb); + int64_t filesize = avi->fsize; - av_dlog(s, + av_log(s, AV_LOG_TRACE, "longs_pre_entry:%d index_type:%d entries_in_use:%d " "chunk_id:%X base:%16"PRIX64"\n", longs_pre_entry, @@ -194,7 +196,7 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num) int key = len >= 0; len &= 0x7FFFFFFF; - av_dlog(s, "pos:%"PRId64", len:%X\n", pos, len); + av_log(s, AV_LOG_TRACE, "pos:%"PRId64", len:%X\n", pos, len); if (pb->eof_reached) return AVERROR_INVALIDDATA; @@ -365,6 +367,7 @@ static int avi_read_header(AVFormatContext *s) int avih_width = 0, avih_height = 0; int amv_file_format = 0; uint64_t list_end = 0; + int64_t pos; int ret; avi->stream_index = -1; @@ -374,7 +377,7 @@ static int avi_read_header(AVFormatContext *s) return ret; avi->fsize = avio_size(pb); - if (avi->fsize <= 0) + if (avi->fsize <= 0 || avi->fsize < avi->riff_end) avi->fsize = avi->riff_end == 8 ? INT64_MAX : avi->riff_end; /* first list tag */ @@ -402,8 +405,8 @@ static int avi_read_header(AVFormatContext *s) if (size) avi->movi_end = avi->movi_list + size + (size & 1); else - avi->movi_end = avio_size(pb); - av_dlog(NULL, "movi end=%"PRIx64"\n", avi->movi_end); + avi->movi_end = avi->fsize; + av_log(NULL, AV_LOG_TRACE, "movi end=%"PRIx64"\n", avi->movi_end); goto end_of_header; } else if (tag1 == MKTAG('I', 'N', 'F', 'O')) ff_read_riff_info(s, size - 4); @@ -484,8 +487,8 @@ static int avi_read_header(AVFormatContext *s) goto fail; ast = s->streams[0]->priv_data; - av_freep(&s->streams[0]->codec->extradata); - av_freep(&s->streams[0]->codec); + av_freep(&s->streams[0]->codecpar->extradata); + av_freep(&s->streams[0]->codecpar); av_freep(&s->streams[0]->info); av_freep(&s->streams[0]); s->nb_streams = 0; @@ -515,7 +518,7 @@ static int avi_read_header(AVFormatContext *s) } assert(stream_index < s->nb_streams); - st->codec->stream_codec_tag = handler; + ast->handler = handler; avio_rl32(pb); /* flags */ avio_rl16(pb); /* priority */ @@ -545,9 +548,9 @@ static int avi_read_header(AVFormatContext *s) st->start_time = 0; avio_rl32(pb); /* buffer size */ avio_rl32(pb); /* quality */ - ast->sample_size = avio_rl32(pb); /* sample ssize */ + ast->sample_size = avio_rl32(pb); /* sample size */ ast->cum_len *= FFMAX(1, ast->sample_size); - av_dlog(s, "%"PRIu32" %"PRIu32" %d\n", + av_log(s, AV_LOG_TRACE, "%"PRIu32" %"PRIu32" %d\n", ast->rate, ast->scale, ast->sample_size); switch (tag1) { @@ -603,52 +606,52 @@ static int avi_read_header(AVFormatContext *s) switch (codec_type) { case AVMEDIA_TYPE_VIDEO: if (amv_file_format) { - st->codec->width = avih_width; - st->codec->height = avih_height; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_AMV; + st->codecpar->width = avih_width; + st->codecpar->height = avih_height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_AMV; avio_skip(pb, size); break; } - tag1 = ff_get_bmp_header(pb, st); + tag1 = ff_get_bmp_header(pb, st, NULL); if (tag1 == MKTAG('D', 'X', 'S', 'B') || tag1 == MKTAG('D', 'X', 'S', 'A')) { - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_tag = tag1; - st->codec->codec_id = AV_CODEC_ID_XSUB; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_tag = tag1; + st->codecpar->codec_id = AV_CODEC_ID_XSUB; break; } 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); - if (!st->codec->extradata) { - st->codec->extradata_size = 0; + st->codecpar->extradata_size = size - 10 * 4; + st->codecpar->extradata = av_malloc(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) { + st->codecpar->extradata_size = 0; return AVERROR(ENOMEM); } avio_read(pb, - st->codec->extradata, - st->codec->extradata_size); + st->codecpar->extradata, + st->codecpar->extradata_size); } // FIXME: check if the encoder really did this correctly - if (st->codec->extradata_size & 1) + if (st->codecpar->extradata_size & 1) avio_r8(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 * Libav. */ - if (st->codec->extradata_size && - (st->codec->bits_per_coded_sample <= 8)) { - int pal_size = (1 << st->codec->bits_per_coded_sample) << 2; + if (st->codecpar->extradata_size && + (st->codecpar->bits_per_coded_sample <= 8)) { + int pal_size = (1 << st->codecpar->bits_per_coded_sample) << 2; const uint8_t *pal_src; - pal_size = FFMIN(pal_size, st->codec->extradata_size); - pal_src = st->codec->extradata + - st->codec->extradata_size - pal_size; + pal_size = FFMIN(pal_size, st->codecpar->extradata_size); + pal_src = st->codecpar->extradata + + st->codecpar->extradata_size - pal_size; #if HAVE_BIGENDIAN for (i = 0; i < pal_size / 4; i++) ast->pal[i] = av_bswap32(((uint32_t *)pal_src)[i]); @@ -660,48 +663,64 @@ static int avi_read_header(AVFormatContext *s) print_tag("video", tag1, 0); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = tag1; - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = tag1; + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); + /* If codec is not found yet, try with the mov tags. */ + if (!st->codecpar->codec_id) { + char tag_buf[32]; + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), tag1); + st->codecpar->codec_id = + ff_codec_get_id(ff_codec_movvideo_tags, tag1); + if (st->codecpar->codec_id) + av_log(s, AV_LOG_WARNING, + "mov tag found in avi (fourcc %s)\n", + tag_buf); + } /* This is needed to get the pict type which is necessary * for generating correct pts. */ st->need_parsing = AVSTREAM_PARSE_HEADERS; + + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4 && + ast->handler == MKTAG('X', 'V', 'I', 'D')) + st->codecpar->codec_tag = MKTAG('X', 'V', 'I', 'D'); + // Support "Resolution 1:1" for Avid AVI Codec if (tag1 == MKTAG('A', 'V', 'R', 'n') && - st->codec->extradata_size >= 31 && - !memcmp(&st->codec->extradata[28], "1:1", 3)) - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - - if (st->codec->codec_tag == 0 && st->codec->height > 0 && - st->codec->extradata_size < 1U << 30) { - st->codec->extradata_size += 9; - if ((ret = av_reallocp(&st->codec->extradata, - st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE)) < 0) { - st->codec->extradata_size = 0; + st->codecpar->extradata_size >= 31 && + !memcmp(&st->codecpar->extradata[28], "1:1", 3)) + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + + if (st->codecpar->codec_tag == 0 && st->codecpar->height > 0 && + st->codecpar->extradata_size < 1U << 30) { + st->codecpar->extradata_size += 9; + if ((ret = av_reallocp(&st->codecpar->extradata, + st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { + st->codecpar->extradata_size = 0; return ret; } else - memcpy(st->codec->extradata + st->codec->extradata_size - 9, + memcpy(st->codecpar->extradata + st->codecpar->extradata_size - 9, "BottomUp", 9); } - st->codec->height = FFABS(st->codec->height); + st->codecpar->height = FFABS(st->codecpar->height); // avio_skip(pb, size - 5 * 4); break; case AVMEDIA_TYPE_AUDIO: - ret = ff_get_wav_header(pb, st->codec, size); + ret = ff_get_wav_header(s, pb, st->codecpar, size); if (ret < 0) return ret; - ast->dshow_block_align = st->codec->block_align; - if (ast->sample_size && st->codec->block_align && - ast->sample_size != st->codec->block_align) { + ast->dshow_block_align = st->codecpar->block_align; + if (ast->sample_size && st->codecpar->block_align && + ast->sample_size != st->codecpar->block_align) { av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, - st->codec->block_align); - ast->sample_size = st->codec->block_align; + st->codecpar->block_align); + ast->sample_size = st->codecpar->block_align; } /* 2-aligned * (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ @@ -713,40 +732,40 @@ static int avi_read_header(AVFormatContext *s) /* 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 == AV_CODEC_ID_AAC && - st->codec->extradata_size) + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size) st->need_parsing = AVSTREAM_PARSE_NONE; /* 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 == AV_RL32("Axan")) { - st->codec->codec_id = AV_CODEC_ID_XAN_DPCM; - st->codec->codec_tag = 0; + if (ast->handler == AV_RL32("Axan")) { + st->codecpar->codec_id = AV_CODEC_ID_XAN_DPCM; + st->codecpar->codec_tag = 0; } if (amv_file_format) { - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV; ast->dshow_block_align = 0; } break; case AVMEDIA_TYPE_SUBTITLE: - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = AV_CODEC_ID_PROBE; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_PROBE; break; default: - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = AV_CODEC_ID_NONE; - st->codec->codec_tag = 0; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_NONE; + st->codecpar->codec_tag = 0; avio_skip(pb, size); break; } } break; case MKTAG('i', 'n', 'd', 'x'): - i = avio_tell(pb); + pos = avio_tell(pb); if (pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) && read_braindead_odml_indx(s, 0) < 0 && (s->error_recognition & AV_EF_EXPLODE)) goto fail; - avio_seek(pb, i + size, SEEK_SET); + avio_seek(pb, pos + size, SEEK_SET); break; case MKTAG('v', 'p', 'r', 'p'): if (stream_index < (unsigned)s->nb_streams && size > 9 * 4) { @@ -768,7 +787,7 @@ static int avi_read_header(AVFormatContext *s) if (active_aspect.num && active_aspect.den && active.num && active.den) { st->sample_aspect_ratio = av_div_q(active_aspect, active); - av_dlog(s, "vprp %d/%d %d/%d\n", + av_log(s, AV_LOG_TRACE, "vprp %d/%d %d/%d\n", active_aspect.num, active_aspect.den, active.num, active.den); } @@ -791,7 +810,7 @@ static int avi_read_header(AVFormatContext *s) if (s->error_recognition & AV_EF_EXPLODE) goto fail; avi->movi_list = avio_tell(pb) - 4; - avi->movi_end = avio_size(pb); + avi->movi_end = avi->fsize; goto end_of_header; } /* skip tag */ @@ -876,8 +895,7 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) ast->sub_ctx->pb = pb; if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) { ff_read_packet(ast->sub_ctx, &ast->sub_pkt); - *st->codec = *ast->sub_ctx->streams[0]->codec; - ast->sub_ctx->streams[0]->codec->extradata = NULL; + avcodec_parameters_copy(st->codecpar, ast->sub_ctx->streams[0]->codecpar); time_base = ast->sub_ctx->streams[0]->time_base; avpriv_set_pts_info(st, 64, time_base.num, time_base.den); } @@ -956,7 +974,7 @@ start_sync: size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24); n = get_stream_idx(d + 2); - av_dlog(s, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n", + av_log(s, AV_LOG_TRACE, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n); if (i + (uint64_t)size > avi->fsize || d[0] > 127) continue; @@ -976,7 +994,7 @@ start_sync: goto start_sync; } - n = avi->dv_demux ? 0 : get_stream_idx(d); + n = get_stream_idx(d); if (!((i - avi->last_pkt_pos) & 1) && get_stream_idx(d + 1) < s->nb_streams) @@ -988,6 +1006,9 @@ start_sync: goto start_sync; } + if (avi->dv_demux && n != 0) + continue; + // parse ##dc/##wb if (n < s->nb_streams) { AVStream *st; @@ -1000,8 +1021,8 @@ start_sync: AVIStream *ast1 = st1->priv_data; // workaround for broken small-file-bug402.avi if (d[2] == 'w' && d[3] == 'b' && n == 0 && - st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - st1->codec->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && ast->prefix == 'd' * 256 + 'c' && (d[2] * 256 + d[3] == ast1->prefix || !ast1->prefix_count)) { @@ -1072,14 +1093,80 @@ start_sync: return AVERROR_EOF; } +static int ni_prepare_read(AVFormatContext *s) +{ + AVIContext *avi = s->priv_data; + 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; + int64_t last_ts; + + if (!st->nb_index_entries) + continue; + + last_ts = st->index_entries[st->nb_index_entries - 1].timestamp; + if (!ast->remaining && ts > last_ts) + continue; + + ts = av_rescale_q(ts, st->time_base, + (AVRational) { FFMAX(1, ast->sample_size), + AV_TIME_BASE }); + + av_log(s, AV_LOG_TRACE, "%"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; + } + } + if (!best_st) + return AVERROR_EOF; + + best_ast = best_st->priv_data; + best_ts = av_rescale_q(best_ts, + (AVRational) { FFMAX(1, best_ast->sample_size), + AV_TIME_BASE }, + best_st->time_base); + 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); + if (i >= 0) + best_ast->frame_offset = best_st->index_entries[i].timestamp; + } + + if (i >= 0) { + int64_t pos = best_st->index_entries[i].pos; + pos += best_ast->packet_size - best_ast->remaining; + avio_seek(s->pb, pos + 8, SEEK_SET); + + 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; + } + + return 0; +} + static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int err; -#if FF_API_DESTRUCT_PACKET - void *dstr; -#endif if (CONFIG_DV_DEMUXER && avi->dv_demux) { int size = avpriv_dv_get_packet(avi->dv_demux, pkt); @@ -1090,68 +1177,9 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) } 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; - int64_t last_ts; - - if (!st->nb_index_entries) - continue; - - last_ts = st->index_entries[st->nb_index_entries - 1].timestamp; - if (!ast->remaining && ts > last_ts) - continue; - - ts = av_rescale_q(ts, st->time_base, - (AVRational) { FFMAX(1, ast->sample_size), - AV_TIME_BASE }); - - av_dlog(s, "%"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; - } - } - if (!best_st) - return AVERROR_EOF; - - best_ast = best_st->priv_data; - best_ts = av_rescale_q(best_ts, - (AVRational) { FFMAX(1, best_ast->sample_size), - AV_TIME_BASE }, - best_st->time_base); - 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); - if (i >= 0) - best_ast->frame_offset = best_st->index_entries[i].timestamp; - } - - if (i >= 0) { - int64_t pos = best_st->index_entries[i].pos; - pos += best_ast->packet_size - best_ast->remaining; - avio_seek(s->pb, pos + 8, SEEK_SET); - - 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; - } + err = ni_prepare_read(s); + if (err < 0) + return err; } resync: @@ -1195,24 +1223,14 @@ resync: if (CONFIG_DV_DEMUXER && avi->dv_demux) { AVBufferRef *avbuf = pkt->buf; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - dstr = pkt->destruct; -FF_ENABLE_DEPRECATION_WARNINGS -#endif size = avpriv_dv_produce_packet(avi->dv_demux, pkt, pkt->data, pkt->size); -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = dstr; -FF_ENABLE_DEPRECATION_WARNINGS -#endif pkt->buf = avbuf; pkt->flags |= AV_PKT_FLAG_KEY; if (size < 0) - av_free_packet(pkt); - } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE && - !st->codec->codec_tag && read_gab2_sub(st, pkt)) { + av_packet_unref(pkt); + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && + !st->codecpar->codec_tag && read_gab2_sub(st, pkt)) { ast->frame_offset++; avi->stream_index = -1; ast->remaining = 0; @@ -1223,7 +1241,7 @@ FF_ENABLE_DEPRECATION_WARNINGS // pkt->dts += ast->start; if (ast->sample_size) pkt->dts /= ast->sample_size; - av_dlog(s, + av_log(s, AV_LOG_TRACE, "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d " "base:%d st:%d size:%d\n", pkt->dts, @@ -1236,7 +1254,7 @@ FF_ENABLE_DEPRECATION_WARNINGS size); pkt->stream_index = avi->stream_index; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVIndexEntry *e; int index; assert(st->index_entries); @@ -1296,7 +1314,7 @@ static int avi_read_idx1(AVFormatContext *s, int size) flags = avio_rl32(pb); pos = avio_rl32(pb); len = avio_rl32(pb); - av_dlog(s, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", + av_log(s, AV_LOG_TRACE, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", i, tag, flags, pos, len); index = ((tag & 0xff) - '0') * 10; @@ -1312,7 +1330,7 @@ static int avi_read_idx1(AVFormatContext *s, int size) } pos += data_offset; - av_dlog(s, "%d cum_len=%"PRId64"\n", len, ast->cum_len); + av_log(s, AV_LOG_TRACE, "%d cum_len=%"PRId64"\n", len, ast->cum_len); if (pb->eof_reached) return AVERROR_INVALIDDATA; @@ -1372,7 +1390,7 @@ static int check_stream_max_drift(AVFormatContext *s) max_dts = FFMAX(max_dts, dts); max_buffer = FFMAX(max_buffer, av_rescale(dts - min_dts, - st->codec->bit_rate, + st->codecpar->bit_rate, AV_TIME_BASE)); } } @@ -1432,13 +1450,13 @@ static int avi_load_index(AVFormatContext *s) if (avio_seek(pb, avi->movi_end, SEEK_SET) < 0) goto the_end; // maybe truncated file - av_dlog(s, "movi_end=0x%"PRIx64"\n", avi->movi_end); + av_log(s, AV_LOG_TRACE, "movi_end=0x%"PRIx64"\n", avi->movi_end); for (;;) { if (pb->eof_reached) break; tag = avio_rl32(pb); size = avio_rl32(pb); - av_dlog(s, "tag=%c%c%c%c size=0x%x\n", + av_log(s, AV_LOG_TRACE, "tag=%c%c%c%c size=0x%x\n", tag & 0xff, (tag >> 8) & 0xff, (tag >> 16) & 0xff, @@ -1465,7 +1483,7 @@ static void seek_subtitle(AVStream *st, AVStream *st2, int64_t timestamp) { AVIStream *ast2 = st2->priv_data; int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base); - av_free_packet(&ast2->sub_pkt); + av_packet_unref(&ast2->sub_pkt); if (avformat_seek_file(ast2->sub_ctx, 0, INT64_MIN, ts2, ts2, 0) >= 0 || avformat_seek_file(ast2->sub_ctx, 0, ts2, ts2, INT64_MAX, 0) >= 0) ff_read_packet(ast2->sub_ctx, &ast2->sub_pkt); @@ -1504,7 +1522,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, pos = st->index_entries[index].pos; timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1); - av_dlog(s, "XX %"PRId64" %d %"PRId64"\n", + av_log(s, AV_LOG_TRACE, "XX %"PRId64" %d %"PRId64"\n", timestamp, index, st->index_entries[index].timestamp); if (CONFIG_DV_DEMUXER && avi->dv_demux) { @@ -1536,7 +1554,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, if (st2->nb_index_entries <= 0) continue; -// assert(st2->codec->block_align); +// assert(st2->codecpar->block_align); assert((int64_t)st2->time_base.num * ast2->rate == (int64_t)st2->time_base.den * ast2->scale); index = av_index_search_timestamp(st2, @@ -1556,7 +1574,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, index++; } - av_dlog(s, "%"PRId64" %d %"PRId64"\n", + av_log(s, AV_LOG_TRACE, "%"PRId64" %d %"PRId64"\n", timestamp, index, st2->index_entries[index].timestamp); /* extract the current frame number */ ast2->frame_offset = st2->index_entries[index].timestamp; @@ -1582,7 +1600,7 @@ static int avi_read_close(AVFormatContext *s) avformat_close_input(&ast->sub_ctx); } av_free(ast->sub_buffer); - av_free_packet(&ast->sub_pkt); + av_packet_unref(&ast->sub_pkt); } } diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 417a8e9..d89fab1 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -44,13 +44,13 @@ typedef struct AVIIndex { AVIIentry** cluster; } AVIIndex; -typedef struct { +typedef struct AVIContext { int64_t riff_start, movi_list, odml_list; int64_t frames_hdr_all; int riff_id; } AVIContext; -typedef struct { +typedef struct AVIStream { int64_t frames_hdr_strm; int audio_strm_length; int packet_count; @@ -111,21 +111,21 @@ static int avi_write_counters(AVFormatContext *s, int riff_id) AVIContext *avi = s->priv_data; int n, au_byterate, au_ssize, au_scale, nb_frames = 0; int64_t file_size; - AVCodecContext *stream; + AVCodecParameters *par; file_size = avio_tell(pb); for (n = 0; n < s->nb_streams; n++) { AVIStream *avist = s->streams[n]->priv_data; assert(avist->frames_hdr_strm); - stream = s->streams[n]->codec; + par = s->streams[n]->codecpar; avio_seek(pb, avist->frames_hdr_strm, SEEK_SET); ff_parse_specific_params(s->streams[n], &au_byterate, &au_ssize, &au_scale); if (au_ssize == 0) avio_wl32(pb, avist->packet_count); else avio_wl32(pb, avist->audio_strm_length / au_ssize); - if (stream->codec_type == AVMEDIA_TYPE_VIDEO) + if (par->codec_type == AVMEDIA_TYPE_VIDEO) nb_frames = FFMAX(nb_frames, avist->packet_count); } if (riff_id == 1) { @@ -143,7 +143,7 @@ static int avi_write_header(AVFormatContext *s) AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; - AVCodecContext *video_enc; + AVCodecParameters *video_par; AVStream *video_st = NULL; int64_t list1, list2, strh, strf; AVDictionaryEntry *t = NULL; @@ -169,12 +169,12 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 14 * 4); bitrate = 0; - video_enc = NULL; + video_par = NULL; for (n = 0; n < s->nb_streams; n++) { - AVCodecContext *codec = s->streams[n]->codec; - bitrate += codec->bit_rate; - if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { - video_enc = codec; + AVCodecParameters *par = s->streams[n]->codecpar; + bitrate += par->bit_rate; + if (par->codec_type == AVMEDIA_TYPE_VIDEO) { + video_par = par; video_st = s->streams[n]; } } @@ -198,9 +198,9 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 0); /* initial frame */ avio_wl32(pb, s->nb_streams); /* nb streams */ avio_wl32(pb, 1024 * 1024); /* suggested buffer size */ - if (video_enc) { - avio_wl32(pb, video_enc->width); - avio_wl32(pb, video_enc->height); + if (video_par) { + avio_wl32(pb, video_par->width); + avio_wl32(pb, video_par->height); } else { avio_wl32(pb, 0); avio_wl32(pb, 0); @@ -213,18 +213,18 @@ static int avi_write_header(AVFormatContext *s) /* stream list */ for (i = 0; i < n; i++) { AVStream *st = s->streams[i]; - AVCodecContext *enc = st->codec; + AVCodecParameters *par = st->codecpar; AVIStream *avist = st->priv_data; list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "strl"); /* stream generic header */ strh = ff_start_tag(pb, "strh"); - switch (enc->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. - if (enc->codec_id != AV_CODEC_ID_XSUB) { + if (par->codec_id != AV_CODEC_ID_XSUB) { av_log(s, AV_LOG_ERROR, "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n"); return AVERROR_PATCHWELCOME; @@ -242,9 +242,9 @@ static int avi_write_header(AVFormatContext *s) ffio_wfourcc(pb, "dats"); break; } - if (enc->codec_type == AVMEDIA_TYPE_VIDEO || - enc->codec_id == AV_CODEC_ID_XSUB) - avio_wl32(pb, enc->codec_tag); + if (par->codec_type == AVMEDIA_TYPE_VIDEO || + par->codec_id == AV_CODEC_ID_XSUB) + avio_wl32(pb, par->codec_tag); else avio_wl32(pb, 1); avio_wl32(pb, 0); /* flags */ @@ -268,32 +268,32 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 0); /* length, XXX: filled later */ /* suggested buffer size */ //FIXME set at the end to largest chunk - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) + if (par->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl32(pb, 1024 * 1024); - else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) + else if (par->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl32(pb, 12 * 1024); else avio_wl32(pb, 0); avio_wl32(pb, -1); /* quality */ avio_wl32(pb, au_ssize); /* sample size */ avio_wl32(pb, 0); - avio_wl16(pb, enc->width); - avio_wl16(pb, enc->height); + avio_wl16(pb, par->width); + avio_wl16(pb, par->height); ff_end_tag(pb, strh); - if (enc->codec_type != AVMEDIA_TYPE_DATA) { + if (par->codec_type != AVMEDIA_TYPE_DATA) { strf = ff_start_tag(pb, "strf"); - switch (enc->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_SUBTITLE: /* XSUB subtitles behave like video tracks, other subtitles * are not (yet) supported. */ - if (enc->codec_id != AV_CODEC_ID_XSUB) + if (par->codec_id != AV_CODEC_ID_XSUB) break; case AVMEDIA_TYPE_VIDEO: - ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 0); + ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 0); break; case AVMEDIA_TYPE_AUDIO: - if (ff_put_wav_header(pb, enc) < 0) + if (ff_put_wav_header(s, pb, par) < 0) return -1; break; default: @@ -320,7 +320,7 @@ static int avi_write_header(AVFormatContext *s) avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */ - ffio_wfourcc(pb, avi_stream2fourcc(tag, i, enc->codec_type)); + ffio_wfourcc(pb, avi_stream2fourcc(tag, i, par->codec_type)); /* dwChunkId */ avio_wl64(pb, 0); /* dwReserved[3] */ // avio_wl32(pb, 0); /* Must be 0. */ @@ -329,13 +329,13 @@ static int avi_write_header(AVFormatContext *s) ff_end_tag(pb, avist->indexes.indx_start); } - if (enc->codec_type == AVMEDIA_TYPE_VIDEO && + if (par->codec_type == AVMEDIA_TYPE_VIDEO && st->sample_aspect_ratio.num > 0 && st->sample_aspect_ratio.den > 0) { int vprp = ff_start_tag(pb, "vprp"); AVRational dar = av_mul_q(st->sample_aspect_ratio, - (AVRational) { enc->width, - enc->height }); + (AVRational) { par->width, + par->height }); int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); @@ -343,18 +343,18 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, 0); // video standard = unknown // TODO: should be avg_frame_rate avio_wl32(pb, lrintf(1.0 / av_q2d(st->time_base))); - avio_wl32(pb, enc->width); - avio_wl32(pb, enc->height); + avio_wl32(pb, par->width); + avio_wl32(pb, par->height); avio_wl16(pb, den); avio_wl16(pb, num); - avio_wl32(pb, enc->width); - avio_wl32(pb, enc->height); + avio_wl32(pb, par->width); + avio_wl32(pb, par->height); avio_wl32(pb, 1); // progressive FIXME - avio_wl32(pb, enc->height); - avio_wl32(pb, enc->width); - avio_wl32(pb, enc->height); - avio_wl32(pb, enc->width); + avio_wl32(pb, par->height); + avio_wl32(pb, par->width); + avio_wl32(pb, par->height); + avio_wl32(pb, par->width); avio_wl32(pb, 0); avio_wl32(pb, 0); @@ -412,7 +412,7 @@ static int avi_write_ix(AVFormatContext *s) AVIStream *avist = s->streams[i]->priv_data; int64_t ix, pos; - avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type); + avi_stream2fourcc(tag, i, s->streams[i]->codecpar->codec_type); ix_tag[3] = '0' + i; /* Writing AVI OpenDML leaf index chunk */ @@ -489,7 +489,7 @@ static int avi_write_idx1(AVFormatContext *s) if (!empty) { avist = s->streams[stream_id]->priv_data; avi_stream2fourcc(tag, stream_id, - s->streams[stream_id]->codec->codec_type); + s->streams[stream_id]->codecpar->codec_type); ffio_wfourcc(pb, tag); avio_wl32(pb, ie->flags); avio_wl32(pb, ie->pos); @@ -513,9 +513,9 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; AVIStream *avist = s->streams[stream_index]->priv_data; - AVCodecContext *enc = s->streams[stream_index]->codec; + AVCodecParameters *par = s->streams[stream_index]->codecpar; - while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE && + while (par->block_align == 0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count) { AVPacket empty_packet; @@ -540,10 +540,10 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); } - avi_stream2fourcc(tag, stream_index, enc->codec_type); + avi_stream2fourcc(tag, stream_index, par->codec_type); if (pkt->flags & AV_PKT_FLAG_KEY) flags = 0x10; - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (par->codec_type == AVMEDIA_TYPE_AUDIO) avist->audio_strm_length += size; if (s->pb->seekable) { @@ -604,15 +604,15 @@ static int avi_write_trailer(AVFormatContext *s) avio_skip(pb, 16); for (n = nb_frames = 0; n < s->nb_streams; n++) { - AVCodecContext *stream = s->streams[n]->codec; + AVCodecParameters *par = s->streams[n]->codecpar; AVIStream *avist = s->streams[n]->priv_data; - if (stream->codec_type == AVMEDIA_TYPE_VIDEO) { + if (par->codec_type == AVMEDIA_TYPE_VIDEO) { if (nb_frames < avist->packet_count) nb_frames = avist->packet_count; } else { - if (stream->codec_id == AV_CODEC_ID_MP2 || - stream->codec_id == AV_CODEC_ID_MP3) + if (par->codec_id == AV_CODEC_ID_MP2 || + par->codec_id == AV_CODEC_ID_MP3) nb_frames += avist->packet_count; } } diff --git a/libavformat/avio.c b/libavformat/avio.c index f68994c..1692f1b 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -30,13 +30,6 @@ #endif #include "url.h" -static URLProtocol *first_protocol = NULL; - -URLProtocol *ffurl_protocol_next(const URLProtocol *prev) -{ - return prev ? prev->next : first_protocol; -} - /** @name Logging context. */ /*@{*/ static const char *urlcontext_to_name(void *ptr) @@ -56,58 +49,24 @@ static void *urlcontext_child_next(void *obj, void *prev) return NULL; } -static const AVClass *urlcontext_child_class_next(const AVClass *prev) -{ - URLProtocol *p = NULL; - - /* find the protocol that corresponds to prev */ - while (prev && (p = ffurl_protocol_next(p))) - if (p->priv_data_class == prev) - break; - - /* find next protocol with priv options */ - while (p = ffurl_protocol_next(p)) - if (p->priv_data_class) - return p->priv_data_class; - return NULL; -} - -static const AVOption options[] = { { NULL } }; +static const AVOption options[] = { + { "rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM }, + { NULL } +}; const AVClass ffurl_context_class = { .class_name = "URLContext", .item_name = urlcontext_to_name, .option = options, .version = LIBAVUTIL_VERSION_INT, .child_next = urlcontext_child_next, - .child_class_next = urlcontext_child_class_next, + .child_class_next = ff_urlcontext_child_class_next, }; /*@}*/ -const char *avio_enum_protocols(void **opaque, int output) -{ - URLProtocol *p; - *opaque = ffurl_protocol_next(*opaque); - if (!(p = *opaque)) - return NULL; - if ((output && p->url_write) || (!output && p->url_read)) - return p->name; - return avio_enum_protocols(opaque, output); -} - -int ffurl_register_protocol(URLProtocol *protocol) -{ - URLProtocol **p; - p = &first_protocol; - while (*p) - p = &(*p)->next; - *p = protocol; - protocol->next = NULL; - return 0; -} - -static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up, +static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up, const char *filename, int flags, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols) { URLContext *uc; int err; @@ -128,6 +87,7 @@ static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up, uc->flags = flags; uc->is_streamed = 0; /* default = not streamed */ uc->max_packet_size = 0; /* default: stream file */ + uc->protocols = protocols; if (up->priv_data_size) { uc->priv_data = av_mallocz(up->priv_data_size); if (!uc->priv_data) { @@ -181,11 +141,12 @@ int ffurl_connect(URLContext *uc, AVDictionary **options) "0123456789+-." int ffurl_alloc(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols) { - URLProtocol *up = NULL; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); + int i; if (filename[proto_len] != ':' || is_dos_path(filename)) strcpy(proto_str, "file"); @@ -197,23 +158,33 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, if ((ptr = strchr(proto_nested, '+'))) *ptr = '\0'; - while (up = ffurl_protocol_next(up)) { + for (i = 0; protocols[i]; i++) { + const URLProtocol *up = protocols[i]; if (!strcmp(proto_str, up->name)) - return url_alloc_for_protocol(puc, up, filename, flags, int_cb); + return url_alloc_for_protocol(puc, up, filename, flags, int_cb, + protocols); if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && !strcmp(proto_nested, up->name)) - return url_alloc_for_protocol(puc, up, filename, flags, int_cb); + return url_alloc_for_protocol(puc, up, filename, flags, int_cb, + protocols); } *puc = NULL; return AVERROR_PROTOCOL_NOT_FOUND; } int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb, AVDictionary **options) + const AVIOInterruptCB *int_cb, AVDictionary **options, + const URLProtocol **protocols, + URLContext *parent) { - int ret = ffurl_alloc(puc, filename, flags, int_cb); + int ret = ffurl_alloc(puc, filename, flags, int_cb, protocols); if (ret) return ret; + if (parent) + av_opt_copy(*puc, parent); + if (options && + (ret = av_opt_set_dict(*puc, options)) < 0) + goto fail; if (options && (*puc)->prot->priv_data_class && (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0) goto fail; @@ -234,6 +205,7 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, { int ret, len; int fast_retries = 5; + int64_t wait_since = 0; len = 0; while (len < size_min) { @@ -244,14 +216,23 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, return ret; if (ret == AVERROR(EAGAIN)) { ret = 0; - if (fast_retries) + if (fast_retries) { fast_retries--; - else + } else { + if (h->rw_timeout) { + if (!wait_since) + wait_since = av_gettime_relative(); + else if (av_gettime_relative() > wait_since + h->rw_timeout) + return AVERROR(EIO); + } av_usleep(1000); + } } else if (ret < 1) return (ret < 0 && ret != AVERROR_EOF) ? ret : len; - if (ret) + if (ret) { fast_retries = FFMAX(fast_retries, 2); + wait_since = 0; + } len += ret; if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; @@ -281,7 +262,9 @@ int ffurl_write(URLContext *h, const unsigned char *buf, int size) if (h->max_packet_size && size > h->max_packet_size) return AVERROR(EIO); - return retry_transfer_wrapper(h, buf, size, size, h->prot->url_write); + return retry_transfer_wrapper(h, buf, size, size, + (int (*)(struct URLContext *, uint8_t *, int)) + h->prot->url_write); } int64_t ffurl_seek(URLContext *h, int64_t pos, int whence) @@ -317,10 +300,19 @@ int ffurl_close(URLContext *h) int avio_check(const char *url, int flags) { + const URLProtocol **protocols; URLContext *h; - int ret = ffurl_alloc(&h, url, flags, NULL); - if (ret) + int ret; + + protocols = ffurl_get_protocols(NULL, NULL); + if (!protocols) + return AVERROR(ENOMEM); + + ret = ffurl_alloc(&h, url, flags, NULL, protocols); + if (ret) { + av_freep(&protocols); return ret; + } if (h->prot->url_check) { ret = h->prot->url_check(h, flags); @@ -331,6 +323,7 @@ int avio_check(const char *url, int flags) } ffurl_close(h); + av_freep(&protocols); return ret; } diff --git a/libavformat/avio.h b/libavformat/avio.h index 3360e82..4bd5cb1 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -54,6 +54,42 @@ typedef struct AVIOInterruptCB { } AVIOInterruptCB; /** + * Different data types that can be returned via the AVIO + * write_data_type callback. + */ +enum AVIODataMarkerType { + /** + * Header data; this needs to be present for the stream to be decodeable. + */ + AVIO_DATA_MARKER_HEADER, + /** + * A point in the output bytestream where a decoder can start decoding + * (i.e. a keyframe). A demuxer/decoder given the data flagged with + * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT, + * should give decodeable results. + */ + AVIO_DATA_MARKER_SYNC_POINT, + /** + * A point in the output bytestream where a demuxer can start parsing + * (for non self synchronizing bytestream formats). That is, any + * non-keyframe packet start point. + */ + AVIO_DATA_MARKER_BOUNDARY_POINT, + /** + * This is any, unlabelled data. It can either be a muxer not marking + * any positions at all, it can be an actual boundary/sync point + * that the muxer chooses not to mark, or a later part of a packet/fragment + * that is cut into multiple write callbacks due to limited IO buffer size. + */ + AVIO_DATA_MARKER_UNKNOWN, + /** + * Trailer data, which doesn't contain actual content, but only for + * finalizing the output file. + */ + AVIO_DATA_MARKER_TRAILER +}; + +/** * Bytestream IO Context. * New fields can be added to the end with minor version bumps. * Removal, reordering and changes to existing fields require a major @@ -115,9 +151,25 @@ typedef struct AVIOContext { * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. */ int seekable; -} AVIOContext; -/* unbuffered I/O */ + /** + * A callback that is used instead of write_packet. + */ + int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size, + enum AVIODataMarkerType type, int64_t time); + /** + * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT, + * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly + * small chunks of data returned from the callback). + */ + int ignore_boundary_point; + + /** + * Internal, not meant to be used from outside of AVIOContext. + */ + enum AVIODataMarkerType current_type; + int64_t last_time; +} AVIOContext; /** * Return AVIO_FLAG_* access flags corresponding to the access permissions @@ -178,21 +230,45 @@ int avio_put_str(AVIOContext *s, const char *str); /** * Convert an UTF-8 string to UTF-16LE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * * @return number of bytes written. */ int avio_put_str16le(AVIOContext *s, const char *str); /** - * Passing this as the "whence" parameter to a seek function causes it to + * Convert an UTF-8 string to UTF-16BE and write it. + * @param s the AVIOContext + * @param str NULL-terminated UTF-8 string + * + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** + * Mark the written bytestream as a specific type. + * + * Zero-length ranges are omitted from the output. + * + * @param time the stream time the current bytestream pos corresponds to + * (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not + * applicable + * @param type the kind of data written starting at the current pos + */ +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); + +/** + * ORing this as the "whence" parameter to a seek function causes it to * return the filesize without seeking anywhere. Supporting this is optional. * If it is not supported then the seek function will return <0. */ #define AVSEEK_SIZE 0x10000 /** - * Oring this flag as into the "whence" parameter to a seek function causes it to - * seek by any means (like reopening and linear reading) or other normally unreasonble - * means that can be extreemly slow. + * Passing this flag as the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonable + * means that can be extremely slow. * This may be ignored by the seek code. */ #define AVSEEK_FORCE 0x20000 @@ -384,7 +460,7 @@ int avio_open_dyn_buf(AVIOContext **s); /** * Return the written size and a pointer to the buffer. The buffer * must be freed with av_free(). - * Padding of FF_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer. * * @param s IO context * @param pbuffer pointer to a byte buffer diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index a8bcadd..8616499 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -25,7 +24,7 @@ #include "libavutil/log.h" -extern const AVClass ffio_url_class; +extern const AVClass ff_avio_class; int ffio_init_context(AVIOContext *s, unsigned char *buffer, @@ -85,6 +84,13 @@ int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size uint64_t ffio_read_varlen(AVIOContext *bc); +/** + * Read size bytes from AVIOContext into buf. + * Check that exactly size bytes have been read. + * @return number of bytes read or AVERROR + */ +int ffio_read_size(AVIOContext *s, unsigned char *buf, int size); + /** @warning must be called before any I/O */ int ffio_set_buf_size(AVIOContext *s, int buf_size); @@ -139,4 +145,11 @@ int ffio_open_null_buf(AVIOContext **s); */ int ffio_close_null_buf(AVIOContext *s); +/** + * Free a dynamic buffer. + * + * @param s a pointer to an IO context opened by avio_open_dyn_buf() + */ +void ffio_free_dyn_buf(AVIOContext **s); + #endif /* AVFORMAT_AVIO_INTERNAL_H */ diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 6923b78..706cf5d 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -40,28 +40,67 @@ */ #define SHORT_SEEK_THRESHOLD 4096 -static void *ffio_url_child_next(void *obj, void *prev) +typedef struct AVIOInternal { + const AVClass *class; + + char *protocol_whitelist; + char *protocol_blacklist; + + URLContext *h; + const URLProtocol **protocols; +} AVIOInternal; + +static void *io_priv_child_next(void *obj, void *prev) +{ + AVIOInternal *internal = obj; + return prev ? NULL : internal->h; +} + +static const AVClass *io_priv_child_class_next(const AVClass *prev) +{ + return prev ? NULL : &ffurl_context_class; +} + +#define OFFSET(x) offsetof(AVIOInternal, x) +static const AVOption io_priv_options[] = { + { "protocol_whitelist", "A comma-separated list of allowed protocols", + OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING }, + { "protocol_blacklist", "A comma-separated list of forbidden protocols", + OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING }, + { NULL }, +}; + +static const AVClass io_priv_class = { + .class_name = "AVIOContext", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .option = io_priv_options, + .child_next = io_priv_child_next, + .child_class_next = io_priv_child_class_next, +}; + +static void *ff_avio_child_next(void *obj, void *prev) { AVIOContext *s = obj; return prev ? NULL : s->opaque; } -static const AVClass *ffio_url_child_class_next(const AVClass *prev) +static const AVClass *ff_avio_child_class_next(const AVClass *prev) { - return prev ? NULL : &ffurl_context_class; + return prev ? NULL : &io_priv_class; } -static const AVOption ffio_url_options[] = { +static const AVOption ff_avio_options[] = { { NULL }, }; -const AVClass ffio_url_class = { +const AVClass ff_avio_class = { .class_name = "AVIOContext", .item_name = av_default_item_name, .version = LIBAVUTIL_VERSION_INT, - .option = ffio_url_options, - .child_next = ffio_url_child_next, - .child_class_next = ffio_url_child_class_next, + .option = ff_avio_options, + .child_next = ff_avio_child_next, + .child_class_next = ff_avio_child_class_next, }; static void fill_buffer(AVIOContext *s); @@ -101,6 +140,11 @@ int ffio_init_context(AVIOContext *s, s->read_pause = NULL; s->read_seek = NULL; + s->write_data_type = NULL; + s->ignore_boundary_point = 0; + s->current_type = AVIO_DATA_MARKER_UNKNOWN; + s->last_time = AV_NOPTS_VALUE; + return 0; } @@ -124,13 +168,25 @@ AVIOContext *avio_alloc_context( static void flush_buffer(AVIOContext *s) { if (s->buf_ptr > s->buffer) { - if (s->write_packet && !s->error) { - int ret = s->write_packet(s->opaque, s->buffer, + if (!s->error) { + int ret = 0; + if (s->write_data_type) + ret = s->write_data_type(s->opaque, s->buffer, + s->buf_ptr - s->buffer, + s->current_type, + s->last_time); + else if (s->write_packet) + ret = s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); if (ret < 0) { s->error = ret; } } + if (s->current_type == AVIO_DATA_MARKER_SYNC_POINT || + s->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) { + s->current_type = AVIO_DATA_MARKER_UNKNOWN; + } + s->last_time = AV_NOPTS_VALUE; if (s->update_checksum) { s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); @@ -206,7 +262,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) } offset1 = offset - pos; if (!s->must_flush && - offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { + offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) { /* can do the seek inside the buffer */ s->buf_ptr = s->buffer + offset1; } else if ((!s->seekable || @@ -284,22 +340,28 @@ int avio_put_str(AVIOContext *s, const char *str) return len; } -int avio_put_str16le(AVIOContext *s, const char *str) -{ - const uint8_t *q = str; - int ret = 0; +#define PUT_STR16(type, write) \ + int avio_put_str16 ## type(AVIOContext * s, const char *str) \ + { \ + const uint8_t *q = str; \ + int ret = 0; \ + \ + while (*q) { \ + uint32_t ch; \ + uint16_t tmp; \ + \ + GET_UTF8(ch, *q++, break; ) \ + PUT_UTF16(ch, tmp, write(s, tmp); ret += 2; ) \ + } \ + write(s, 0); \ + ret += 2; \ + return ret; \ + } - while (*q) { - uint32_t ch; - uint16_t tmp; +PUT_STR16(le, avio_wl16) +PUT_STR16(be, avio_wb16) - GET_UTF8(ch, *q++, break;) - PUT_UTF16(ch, tmp, avio_wl16(s, tmp); ret += 2;) - } - avio_wl16(s, 0); - ret += 2; - return ret; -} +#undef PUT_STR16 int ff_get_v_length(uint64_t val) { @@ -357,6 +419,37 @@ void avio_wb24(AVIOContext *s, unsigned int val) avio_w8(s, val); } +void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type) +{ + if (!s->write_data_type) + return; + // If ignoring boundary points, just treat it as unknown + if (type == AVIO_DATA_MARKER_BOUNDARY_POINT && s->ignore_boundary_point) + type = AVIO_DATA_MARKER_UNKNOWN; + // Avoid unnecessary flushes if we are already in non-header/trailer + // data and setting the type to unknown + if (type == AVIO_DATA_MARKER_UNKNOWN && + (s->current_type != AVIO_DATA_MARKER_HEADER && + s->current_type != AVIO_DATA_MARKER_TRAILER)) + return; + + switch (type) { + case AVIO_DATA_MARKER_HEADER: + case AVIO_DATA_MARKER_TRAILER: + // For header/trailer, ignore a new marker of the same type; + // consecutive header/trailer markers can be merged. + if (type == s->current_type) + return; + break; + } + + // If we've reached here, we have a new, noteworthy marker. + // Flush the previous data and mark the start of the new data. + avio_flush(s); + s->current_type = type; + s->last_time = time; +} + /* Input stream */ static void fill_buffer(AVIOContext *s) @@ -496,6 +589,14 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) return size1 - size; } +int ffio_read_size(AVIOContext *s, unsigned char *buf, int size) +{ + int ret = avio_read(s, buf, size); + if (ret != size) + return AVERROR_INVALIDDATA; + return ret; +} + int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data) { if (s->buf_end - s->buf_ptr >= size && !s->write_flag) { @@ -676,9 +777,44 @@ uint64_t ffio_read_varlen(AVIOContext *bc){ return val; } +static int io_read_packet(void *opaque, uint8_t *buf, int buf_size) +{ + AVIOInternal *internal = opaque; + return ffurl_read(internal->h, buf, buf_size); +} + +static int io_write_packet(void *opaque, uint8_t *buf, int buf_size) +{ + AVIOInternal *internal = opaque; + return ffurl_write(internal->h, buf, buf_size); +} + +static int64_t io_seek(void *opaque, int64_t offset, int whence) +{ + AVIOInternal *internal = opaque; + return ffurl_seek(internal->h, offset, whence); +} + +static int io_read_pause(void *opaque, int pause) +{ + AVIOInternal *internal = opaque; + if (!internal->h->prot->url_read_pause) + return AVERROR(ENOSYS); + return internal->h->prot->url_read_pause(internal->h, pause); +} + +static int64_t io_read_seek(void *opaque, int stream_index, int64_t timestamp, int flags) +{ + AVIOInternal *internal = opaque; + if (!internal->h->prot->url_read_seek) + return AVERROR(ENOSYS); + return internal->h->prot->url_read_seek(internal->h, stream_index, timestamp, flags); +} + int ffio_fdopen(AVIOContext **s, URLContext *h) { - uint8_t *buffer; + AVIOInternal *internal = NULL; + uint8_t *buffer = NULL; int buffer_size, max_packet_size; max_packet_size = h->max_packet_size; @@ -691,20 +827,34 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) if (!buffer) return AVERROR(ENOMEM); - *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h, - ffurl_read, ffurl_write, ffurl_seek); - if (!*s) { - av_free(buffer); - return AVERROR(ENOMEM); - } + internal = av_mallocz(sizeof(*internal)); + if (!internal) + goto fail; + + internal->class = &io_priv_class; + internal->h = h; + + av_opt_set_defaults(internal); + + *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, + internal, io_read_packet, io_write_packet, io_seek); + if (!*s) + goto fail; + (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL; (*s)->max_packet_size = max_packet_size; if(h->prot) { - (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; - (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; + (*s)->read_pause = io_read_pause; + (*s)->read_seek = io_read_seek; } - (*s)->av_class = &ffio_url_class; + (*s)->av_class = &ff_avio_class; return 0; +fail: + if (internal) + av_opt_free(internal); + av_freep(&internal); + av_freep(&buffer); + return AVERROR(ENOMEM); } int ffio_set_buf_size(AVIOContext *s, int buf_size) @@ -783,29 +933,69 @@ int avio_open(AVIOContext **s, const char *filename, int flags) int avio_open2(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options) { + AVIOInternal *internal; + const URLProtocol **protocols; + char *proto_whitelist = NULL, *proto_blacklist = NULL; + AVDictionaryEntry *e; URLContext *h; int err; - err = ffurl_open(&h, filename, flags, int_cb, options); - if (err < 0) + if (options) { + e = av_dict_get(*options, "protocol_whitelist", NULL, 0); + if (e) + proto_whitelist = e->value; + e = av_dict_get(*options, "protocol_blacklist", NULL, 0); + if (e) + proto_blacklist = e->value; + } + + protocols = ffurl_get_protocols(proto_whitelist, proto_blacklist); + if (!protocols) + return AVERROR(ENOMEM); + + err = ffurl_open(&h, filename, flags, int_cb, options, protocols, NULL); + if (err < 0) { + av_freep(&protocols); return err; + } + err = ffio_fdopen(s, h); if (err < 0) { ffurl_close(h); + av_freep(&protocols); return err; } + + internal = (*s)->opaque; + internal->protocols = protocols; + + if (options) { + err = av_opt_set_dict(internal, options); + if (err < 0) { + avio_closep(s); + return err; + } + } + return 0; } int avio_close(AVIOContext *s) { + AVIOInternal *internal; URLContext *h; if (!s) return 0; avio_flush(s); - h = s->opaque; + internal = s->opaque; + h = internal->h; + + av_opt_free(internal); + + av_freep(&internal->protocols); + av_freep(&s->opaque); av_freep(&s->buffer); av_free(s); return ffurl_close(h); @@ -841,15 +1031,14 @@ int avio_pause(AVIOContext *s, int pause) int64_t avio_seek_time(AVIOContext *s, int stream_index, int64_t timestamp, int flags) { - URLContext *h = s->opaque; int64_t ret; if (!s->read_seek) return AVERROR(ENOSYS); - ret = s->read_seek(h, stream_index, timestamp, flags); + ret = s->read_seek(s->opaque, stream_index, timestamp, flags); if (ret >= 0) { int64_t pos; s->buf_ptr = s->buf_end; // Flush buffer - pos = s->seek(h, 0, SEEK_CUR); + pos = s->seek(s->opaque, 0, SEEK_CUR); if (pos >= 0) s->pos = pos; else if (pos != AVERROR(ENOSYS)) @@ -967,7 +1156,7 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) { DynBuffer *d; int size; - static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; + static const char padbuf[AV_INPUT_BUFFER_PADDING_SIZE] = {0}; int padding = 0; if (!s) { @@ -978,7 +1167,7 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) /* don't attempt to pad fixed-size packet buffers */ if (!s->max_packet_size) { avio_write(s, padbuf, sizeof(padbuf)); - padding = FF_INPUT_BUFFER_PADDING_SIZE; + padding = AV_INPUT_BUFFER_PADDING_SIZE; } avio_flush(s); @@ -991,6 +1180,16 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) return size - padding; } +void ffio_free_dyn_buf(AVIOContext **s) +{ + uint8_t *tmp; + if (!*s) + return; + avio_close_dyn_buf(*s, &tmp); + av_free(tmp); + *s = NULL; +} + static int null_buf_write(void *opaque, uint8_t *buf, int buf_size) { DynBuffer *d = opaque; diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index f94f7b7..fe71a42 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -1,6 +1,6 @@ /* * AviSynth/AvxSynth support - * Copyright (c) 2012 AvxSynth Team. + * Copyright (c) 2012 AvxSynth Team * * This file is part of Libav. * @@ -23,20 +23,12 @@ #include "libavcodec/internal.h" #include "avformat.h" #include "internal.h" +#include "config.h" /* Enable function pointer definitions for runtime loading. */ #define AVSC_NO_DECLSPEC -/* Platform-specific directives for AviSynth vs AvxSynth. - * - * avisynth_c.h needs to be the one provided with x264, as - * the one in AviSynth's CVS hasn't been updated to support - * 2.6's extra colorspaces. A temporary source of that header, - * installable from a GNU-style Makefile is available from - * github.com/qyot27/avisynth_headers -- AvxSynth doesn't - * require this kind of special treatment because like any - * standard *nix application, it installs its headers - * alongside its libs. */ +/* Platform-specific directives for AviSynth vs AvxSynth. */ #ifdef _WIN32 #include #undef EXTERN_C @@ -46,13 +38,10 @@ #else #include #include - #if defined (__APPLE__) - #define AVISYNTH_LIB "libavxsynth.dylib" - #else - #define AVISYNTH_LIB "libavxsynth.so" - #endif + #define AVISYNTH_NAME "libavxsynth" + #define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF - #define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_GLOBAL) + #define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL) #define GetProcAddress dlsym #define FreeLibrary dlclose #endif @@ -74,6 +63,17 @@ typedef struct AviSynthLibrary { AVSC_DECLARE_FUNC(avs_release_value); AVSC_DECLARE_FUNC(avs_release_video_frame); AVSC_DECLARE_FUNC(avs_take_clip); +#ifdef USING_AVISYNTH + AVSC_DECLARE_FUNC(avs_bits_per_pixel); + AVSC_DECLARE_FUNC(avs_get_height_p); + AVSC_DECLARE_FUNC(avs_get_pitch_p); + AVSC_DECLARE_FUNC(avs_get_read_ptr_p); + AVSC_DECLARE_FUNC(avs_get_row_size_p); + AVSC_DECLARE_FUNC(avs_is_yv24); + AVSC_DECLARE_FUNC(avs_is_yv16); + AVSC_DECLARE_FUNC(avs_is_yv411); + AVSC_DECLARE_FUNC(avs_is_y8); +#endif #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -137,6 +137,17 @@ static av_cold int avisynth_load_library(void) LOAD_AVS_FUNC(avs_release_value, 0); LOAD_AVS_FUNC(avs_release_video_frame, 0); LOAD_AVS_FUNC(avs_take_clip, 0); +#ifdef USING_AVISYNTH + LOAD_AVS_FUNC(avs_bits_per_pixel, 1); + LOAD_AVS_FUNC(avs_get_height_p, 1); + LOAD_AVS_FUNC(avs_get_pitch_p, 1); + LOAD_AVS_FUNC(avs_get_read_ptr_p, 1); + LOAD_AVS_FUNC(avs_get_row_size_p, 1); + LOAD_AVS_FUNC(avs_is_yv24, 1); + LOAD_AVS_FUNC(avs_is_yv16, 1); + LOAD_AVS_FUNC(avs_is_yv411, 1); + LOAD_AVS_FUNC(avs_is_y8, 1); +#endif #undef LOAD_AVS_FUNC atexit(avisynth_atexit_handler); @@ -222,10 +233,10 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) AviSynthContext *avs = s->priv_data; int planar = 0; // 0: packed, 1: YUV, 2: Y8 - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->width = avs->vi->width; - st->codec->height = avs->vi->height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->width = avs->vi->width; + st->codecpar->height = avs->vi->height; st->time_base = (AVRational) { avs->vi->fps_denominator, avs->vi->fps_numerator }; @@ -238,38 +249,38 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) switch (avs->vi->pixel_type) { #ifdef USING_AVISYNTH case AVS_CS_YV24: - st->codec->pix_fmt = AV_PIX_FMT_YUV444P; - planar = 1; + st->codecpar->format = AV_PIX_FMT_YUV444P; + planar = 1; break; case AVS_CS_YV16: - st->codec->pix_fmt = AV_PIX_FMT_YUV422P; - planar = 1; + st->codecpar->format = AV_PIX_FMT_YUV422P; + planar = 1; break; case AVS_CS_YV411: - st->codec->pix_fmt = AV_PIX_FMT_YUV411P; - planar = 1; + st->codecpar->format = AV_PIX_FMT_YUV411P; + planar = 1; break; case AVS_CS_Y8: - st->codec->pix_fmt = AV_PIX_FMT_GRAY8; - planar = 2; + st->codecpar->format = AV_PIX_FMT_GRAY8; + planar = 2; break; #endif case AVS_CS_BGR24: - st->codec->pix_fmt = AV_PIX_FMT_BGR24; + st->codecpar->format = AV_PIX_FMT_BGR24; break; case AVS_CS_BGR32: - st->codec->pix_fmt = AV_PIX_FMT_RGB32; + st->codecpar->format = AV_PIX_FMT_RGB32; break; case AVS_CS_YUY2: - st->codec->pix_fmt = AV_PIX_FMT_YUYV422; + st->codecpar->format = AV_PIX_FMT_YUYV422; break; case AVS_CS_YV12: - st->codec->pix_fmt = AV_PIX_FMT_YUV420P; - planar = 1; + st->codecpar->format = AV_PIX_FMT_YUV420P; + planar = 1; break; case AVS_CS_I420: // Is this even used anywhere? - st->codec->pix_fmt = AV_PIX_FMT_YUV420P; - planar = 1; + st->codecpar->format = AV_PIX_FMT_YUV420P; + planar = 1; break; default: av_log(s, AV_LOG_ERROR, @@ -298,28 +309,28 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st) { AviSynthContext *avs = s->priv_data; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->sample_rate = avs->vi->audio_samples_per_second; - st->codec->channels = avs->vi->nchannels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->sample_rate = avs->vi->audio_samples_per_second; + st->codecpar->channels = avs->vi->nchannels; st->time_base = (AVRational) { 1, avs->vi->audio_samples_per_second }; st->duration = avs->vi->num_audio_samples; switch (avs->vi->sample_type) { case AVS_SAMPLE_INT8: - st->codec->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; break; case AVS_SAMPLE_INT16: - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; case AVS_SAMPLE_INT24: - st->codec->codec_id = AV_CODEC_ID_PCM_S24LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; break; case AVS_SAMPLE_INT32: - st->codec->codec_id = AV_CODEC_ID_PCM_S32LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; break; case AVS_SAMPLE_FLOAT: - st->codec->codec_id = AV_CODEC_ID_PCM_F32LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; break; default: av_log(s, AV_LOG_ERROR, @@ -394,13 +405,14 @@ static int avisynth_open_file(AVFormatContext *s) avs->vi = avs_library.avs_get_video_info(avs->clip); #ifdef USING_AVISYNTH - /* libav only supports AviSynth 2.6 on Windows. Since AvxSynth - * identifies itself as interface version 3 like 2.5.8, this - * needs to be special-cased. */ + /* On Windows, libav supports AviSynth interface version 6 or higher. + * This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher, + * and excludes 2.5 and the 2.6 alphas. Since AvxSynth identifies itself + * as interface version 3 like 2.5.8, this needs to be special-cased. */ - if (avs_library.avs_get_version(avs->clip) == 3) { + if (avs_library.avs_get_version(avs->clip) < 6) { av_log(s, AV_LOG_ERROR, - "AviSynth 2.5.8 not supported. Please upgrade to 2.6.\n"); + "AviSynth version is too old. Please upgrade to either AviSynth 2.6 >= RC1 or AviSynth+ >= r1718.\n"); ret = AVERROR_UNKNOWN; goto fail; } @@ -460,17 +472,19 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, * Since AvxSynth doesn't have these functions, special-case * it in order to avoid implicit declaration errors. */ - if (avs_is_yv24(avs->vi)) + if (avs_library.avs_is_yv24(avs->vi)) bits = 24; - else if (avs_is_yv16(avs->vi)) + else if (avs_library.avs_is_yv16(avs->vi)) bits = 16; - else if (avs_is_yv411(avs->vi)) + else if (avs_library.avs_is_yv411(avs->vi)) bits = 12; - else if (avs_is_y8(avs->vi)) + else if (avs_library.avs_is_y8(avs->vi)) bits = 8; else + bits = avs_library.avs_bits_per_pixel(avs->vi); +#else + bits = avs_bits_per_pixel(avs->vi); #endif - bits = avs_bits_per_pixel(avs->vi); /* Without the cast to int64_t, calculation overflows at about 9k x 9k * resolution. */ @@ -499,11 +513,19 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, dst_p = pkt->data; for (i = 0; i < avs->n_planes; i++) { plane = avs->planes[i]; +#ifdef USING_AVISYNTH + src_p = avs_library.avs_get_read_ptr_p(frame, plane); + pitch = avs_library.avs_get_pitch_p(frame, plane); + + rowsize = avs_library.avs_get_row_size_p(frame, plane); + planeheight = avs_library.avs_get_height_p(frame, plane); +#else src_p = avs_get_read_ptr_p(frame, plane); pitch = avs_get_pitch_p(frame, plane); rowsize = avs_get_row_size_p(frame, plane); planeheight = avs_get_height_p(frame, plane); +#endif /* Flip RGB video. */ if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) { @@ -617,7 +639,7 @@ static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt) /* If either stream reaches EOF, try to read the other one before * giving up. */ avisynth_next_stream(s, &st, pkt, &discard); - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { ret = avisynth_read_packet_video(s, pkt, discard); if (ret == AVERROR_EOF && avs_has_audio(avs->vi)) { avisynth_next_stream(s, &st, pkt, &discard); @@ -659,7 +681,7 @@ static int avisynth_read_seek(AVFormatContext *s, int stream_index, samplerate = (AVRational) { avs->vi->audio_samples_per_second, 1 }; st = s->streams[stream_index]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { /* AviSynth frame counts are signed int. */ if ((timestamp >= avs->vi->num_frames) || (timestamp > INT_MAX) || diff --git a/libavformat/avlanguage.h b/libavformat/avlanguage.h index 2ec3e2d..128fb1c 100644 --- a/libavformat/avlanguage.h +++ b/libavformat/avlanguage.h @@ -26,7 +26,7 @@ */ enum AVLangCodespace { AV_LANG_ISO639_2_BIBL, /** 3-char bibliographic language codes as per ISO-IEC 639-2 */ - AV_LANG_ISO639_2_TERM, /** 3-char terminologic language codes as per ISO-IEC 639-2 */ + AV_LANG_ISO639_2_TERM, /** 3-char terminological language codes as per ISO-IEC 639-2 */ AV_LANG_ISO639_1 /** 2-char code of language as per ISO/IEC 639-1 */ }; diff --git a/libavformat/avs.c b/libavformat/avs.c index d8042c5..c825a3a 100644 --- a/libavformat/avs.c +++ b/libavformat/avs.c @@ -108,7 +108,7 @@ avs_read_video_packet(AVFormatContext * s, AVPacket * pkt, pkt->data[palette_size + 3] = (size >> 8) & 0xFF; ret = avio_read(s->pb, pkt->data + palette_size + 4, size - 4) + 4; if (ret < size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } @@ -184,11 +184,11 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt) avs->st_video = avformat_new_stream(s, NULL); if (!avs->st_video) return AVERROR(ENOMEM); - avs->st_video->codec->codec_type = AVMEDIA_TYPE_VIDEO; - avs->st_video->codec->codec_id = AV_CODEC_ID_AVS; - avs->st_video->codec->width = avs->width; - avs->st_video->codec->height = avs->height; - avs->st_video->codec->bits_per_coded_sample=avs->bits_per_sample; + avs->st_video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + avs->st_video->codecpar->codec_id = AV_CODEC_ID_AVS; + avs->st_video->codecpar->width = avs->width; + avs->st_video->codecpar->height = avs->height; + avs->st_video->codecpar->bits_per_coded_sample=avs->bits_per_sample; avs->st_video->nb_frames = avs->nb_frames; avs->st_video->avg_frame_rate = (AVRational){avs->fps, 1}; } @@ -200,7 +200,7 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt) avs->st_audio = avformat_new_stream(s, NULL); if (!avs->st_audio) return AVERROR(ENOMEM); - avs->st_audio->codec->codec_type = AVMEDIA_TYPE_AUDIO; + avs->st_audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; } avs->remaining_audio_size = size - 4; size = avs_read_audio_packet(s, pkt); diff --git a/libavformat/bethsoftvid.c b/libavformat/bethsoftvid.c index 120e145..8ed9d4f 100644 --- a/libavformat/bethsoftvid.c +++ b/libavformat/bethsoftvid.c @@ -113,13 +113,13 @@ static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt, "video packet"); } avpriv_set_pts_info(st, 64, 185, vid->sample_rate); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_BETHSOFTVID; - st->codec->width = vid->width; - st->codec->height = vid->height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_BETHSOFTVID; + st->codecpar->width = vid->width; + st->codecpar->height = vid->height; } st = s->streams[vid->video_index]; - npixels = st->codec->width * st->codec->height; + npixels = st->codecpar->width * st->codecpar->height; vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE); if(!vidbuf_start) @@ -177,7 +177,6 @@ static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt, if ((ret = av_new_packet(pkt, vidbuf_nbytes)) < 0) goto fail; memcpy(pkt->data, vidbuf_start, vidbuf_nbytes); - av_free(vidbuf_start); pkt->pos = position; pkt->stream_index = vid->video_index; @@ -189,12 +188,15 @@ static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt, if (vid->palette) { uint8_t *pdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, BVID_PALETTE_SIZE); + if (!pdata) { + ret = AVERROR(ENOMEM); + goto fail; + } memcpy(pdata, vid->palette, BVID_PALETTE_SIZE); av_freep(&vid->palette); } vid->nframes--; // used to check if all the frames were read - return 0; fail: av_free(vidbuf_start); return ret; @@ -238,13 +240,13 @@ static int vid_read_packet(AVFormatContext *s, if (!st) return AVERROR(ENOMEM); vid->audio_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_U8; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->bits_per_coded_sample = 8; - st->codec->sample_rate = vid->sample_rate; - st->codec->bit_rate = 8 * st->codec->sample_rate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->bits_per_coded_sample = 8; + st->codecpar->sample_rate = vid->sample_rate; + st->codecpar->bit_rate = 8 * st->codecpar->sample_rate; st->start_time = 0; avpriv_set_pts_info(st, 64, 1, vid->sample_rate); } diff --git a/libavformat/bfi.c b/libavformat/bfi.c index 19060e7..99371bd 100644 --- a/libavformat/bfi.c +++ b/libavformat/bfi.c @@ -75,34 +75,34 @@ static int bfi_read_header(AVFormatContext * s) avio_rl32(pb); fps = avio_rl32(pb); avio_skip(pb, 12); - vstream->codec->width = avio_rl32(pb); - vstream->codec->height = avio_rl32(pb); + vstream->codecpar->width = avio_rl32(pb); + vstream->codecpar->height = avio_rl32(pb); /*Load the palette to extradata */ avio_skip(pb, 8); - vstream->codec->extradata = av_malloc(768); - vstream->codec->extradata_size = 768; - avio_read(pb, vstream->codec->extradata, - vstream->codec->extradata_size); + vstream->codecpar->extradata = av_malloc(768); + vstream->codecpar->extradata_size = 768; + avio_read(pb, vstream->codecpar->extradata, + vstream->codecpar->extradata_size); - astream->codec->sample_rate = avio_rl32(pb); + astream->codecpar->sample_rate = avio_rl32(pb); /* Set up the video codec... */ avpriv_set_pts_info(vstream, 32, 1, fps); - vstream->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vstream->codec->codec_id = AV_CODEC_ID_BFI; - vstream->codec->pix_fmt = AV_PIX_FMT_PAL8; + vstream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vstream->codecpar->codec_id = AV_CODEC_ID_BFI; + vstream->codecpar->format = AV_PIX_FMT_PAL8; /* Set up the audio codec now... */ - astream->codec->codec_type = AVMEDIA_TYPE_AUDIO; - astream->codec->codec_id = AV_CODEC_ID_PCM_U8; - astream->codec->channels = 1; - astream->codec->channel_layout = AV_CH_LAYOUT_MONO; - astream->codec->bits_per_coded_sample = 8; - astream->codec->bit_rate = - astream->codec->sample_rate * astream->codec->bits_per_coded_sample; + astream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + astream->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + astream->codecpar->channels = 1; + astream->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + astream->codecpar->bits_per_coded_sample = 8; + astream->codecpar->bit_rate = + astream->codecpar->sample_rate * astream->codecpar->bits_per_coded_sample; avio_seek(pb, chunk_header - 3, SEEK_SET); - avpriv_set_pts_info(astream, 64, 1, astream->codec->sample_rate); + avpriv_set_pts_info(astream, 64, 1, astream->codecpar->sample_rate); return 0; } diff --git a/libavformat/bink.c b/libavformat/bink.c index 4d2a735..377db98 100644 --- a/libavformat/bink.c +++ b/libavformat/bink.c @@ -46,7 +46,7 @@ enum BinkAudFlags { #define BINK_MAX_WIDTH 7680 #define BINK_MAX_HEIGHT 4800 -typedef struct { +typedef struct BinkDemuxContext { uint32_t file_size; uint32_t num_audio_tracks; @@ -86,7 +86,7 @@ static int read_header(AVFormatContext *s) if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_tag = avio_rl32(pb); + vst->codecpar->codec_tag = avio_rl32(pb); bink->file_size = avio_rl32(pb) + 8; vst->duration = avio_rl32(pb); @@ -104,8 +104,8 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 4); - vst->codec->width = avio_rl32(pb); - vst->codec->height = avio_rl32(pb); + vst->codecpar->width = avio_rl32(pb); + vst->codecpar->height = avio_rl32(pb); fps_num = avio_rl32(pb); fps_den = avio_rl32(pb); @@ -118,13 +118,13 @@ static int read_header(AVFormatContext *s) avpriv_set_pts_info(vst, 64, fps_den, fps_num); vst->avg_frame_rate = av_inv_q(vst->time_base); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_BINKVIDEO; - vst->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!vst->codec->extradata) + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_BINKVIDEO; + vst->codecpar->extradata = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!vst->codecpar->extradata) return AVERROR(ENOMEM); - vst->codec->extradata_size = 4; - avio_read(pb, vst->codec->extradata, 4); + vst->codecpar->extradata_size = 4; + avio_read(pb, vst->codecpar->extradata, 4); bink->num_audio_tracks = avio_rl32(pb); @@ -142,25 +142,25 @@ static int read_header(AVFormatContext *s) ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_tag = 0; - ast->codec->sample_rate = avio_rl16(pb); - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_tag = 0; + ast->codecpar->sample_rate = avio_rl16(pb); + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); flags = avio_rl16(pb); - ast->codec->codec_id = flags & BINK_AUD_USEDCT ? + ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ? AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT; if (flags & BINK_AUD_STEREO) { - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - ast->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!ast->codec->extradata) + ast->codecpar->extradata = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!ast->codecpar->extradata) return AVERROR(ENOMEM); - ast->codec->extradata_size = 4; - AV_WL32(ast->codec->extradata, vst->codec->codec_tag); + ast->codecpar->extradata_size = 4; + AV_WL32(ast->codecpar->extradata, vst->codecpar->codec_tag); } for (i = 0; i < bink->num_audio_tracks; i++) @@ -239,10 +239,10 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = bink->audio_pts[bink->current_track - 1]; /* Each audio packet reports the number of decompressed samples - (in bytes). We use this value to calcuate the audio PTS */ + (in bytes). We use this value to calculate the audio PTS */ if (pkt->size >= 4) bink->audio_pts[bink->current_track -1] += - AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec->channels); + AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->channels); return 0; } else { avio_skip(pb, audio_size); diff --git a/libavformat/bmv.c b/libavformat/bmv.c index b5572af..9bc8dda 100644 --- a/libavformat/bmv.c +++ b/libavformat/bmv.c @@ -1,6 +1,6 @@ /* * Discworld II BMV demuxer - * Copyright (c) 2011 Konstantin Shishkov. + * Copyright (c) 2011 Konstantin Shishkov * * This file is part of Libav. * @@ -47,20 +47,20 @@ static int bmv_read_header(AVFormatContext *s) st = avformat_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_BMV_VIDEO; - st->codec->width = 640; - st->codec->height = 429; - st->codec->pix_fmt = AV_PIX_FMT_PAL8; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_BMV_VIDEO; + st->codecpar->width = 640; + st->codecpar->height = 429; + st->codecpar->format = AV_PIX_FMT_PAL8; avpriv_set_pts_info(st, 16, 1, 12); ast = avformat_new_stream(s, 0); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_BMV_AUDIO; - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; - ast->codec->sample_rate = 22050; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_BMV_AUDIO; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->sample_rate = 22050; avpriv_set_pts_info(ast, 16, 1, 22050); c->get_next = 1; diff --git a/libavformat/c93.c b/libavformat/c93.c index 3f2a98f..c213b06 100644 --- a/libavformat/c93.c +++ b/libavformat/c93.c @@ -24,13 +24,13 @@ #include "voc.h" #include "libavutil/intreadwrite.h" -typedef struct { +typedef struct C93BlockRecord { uint16_t index; uint8_t length; uint8_t frames; } C93BlockRecord; -typedef struct { +typedef struct C93DemuxContext { VocDecContext voc; C93BlockRecord block_records[512]; @@ -83,10 +83,10 @@ static int read_header(AVFormatContext *s) if (!video) return AVERROR(ENOMEM); - video->codec->codec_type = AVMEDIA_TYPE_VIDEO; - video->codec->codec_id = AV_CODEC_ID_C93; - video->codec->width = 320; - video->codec->height = 192; + video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + video->codecpar->codec_id = AV_CODEC_ID_C93; + video->codecpar->width = 320; + video->codecpar->height = 192; /* 4:3 320x200 with 8 empty lines */ video->sample_aspect_ratio = (AVRational) { 5, 6 }; avpriv_set_pts_info(video, 64, 2, 25); @@ -120,7 +120,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) c93->audio = avformat_new_stream(s, NULL); if (!c93->audio) return AVERROR(ENOMEM); - c93->audio->codec->codec_type = AVMEDIA_TYPE_AUDIO; + c93->audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; } avio_skip(pb, 26); /* VOC header */ ret = ff_voc_get_packet(s, pkt, c93->audio, datasize - 26); @@ -188,7 +188,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) return 0; fail: - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 0034f00..65bdcfc 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -36,7 +36,7 @@ #include "libavutil/dict.h" #include "caf.h" -typedef struct { +typedef struct CafContext { int bytes_per_packet; ///< bytes in a packet, or 0 if variable int frames_per_packet; ///< frames in a packet, or 0 if variable int64_t num_bytes; ///< total number of bytes in stream @@ -46,7 +46,7 @@ typedef struct { int64_t data_start; ///< data start position, in bytes int64_t data_size; ///< raw data size, in bytes -} CaffContext; +} CafContext; static int probe(AVProbeData *p) { @@ -59,7 +59,7 @@ static int probe(AVProbeData *p) static int read_desc_chunk(AVFormatContext *s) { AVIOContext *pb = s->pb; - CaffContext *caf = s->priv_data; + CafContext *caf = s->priv_data; AVStream *st; int flags; @@ -69,29 +69,29 @@ static int read_desc_chunk(AVFormatContext *s) return AVERROR(ENOMEM); /* parse format description */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->sample_rate = av_int2double(avio_rb64(pb)); - st->codec->codec_tag = avio_rb32(pb); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->sample_rate = av_int2double(avio_rb64(pb)); + st->codecpar->codec_tag = avio_rb32(pb); flags = avio_rb32(pb); caf->bytes_per_packet = avio_rb32(pb); - st->codec->block_align = caf->bytes_per_packet; + st->codecpar->block_align = caf->bytes_per_packet; caf->frames_per_packet = avio_rb32(pb); - st->codec->channels = avio_rb32(pb); - st->codec->bits_per_coded_sample = avio_rb32(pb); + st->codecpar->channels = avio_rb32(pb); + st->codecpar->bits_per_coded_sample = avio_rb32(pb); /* calculate bit rate for constant size packets */ if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { - st->codec->bit_rate = (uint64_t)st->codec->sample_rate * (uint64_t)caf->bytes_per_packet * 8 - / (uint64_t)caf->frames_per_packet; + st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8 + / (uint64_t)caf->frames_per_packet; } else { - st->codec->bit_rate = 0; + st->codecpar->bit_rate = 0; } /* determine codec */ - if (st->codec->codec_tag == MKBETAG('l','p','c','m')) - st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, (flags ^ 0x2) | 0x4); + if (st->codecpar->codec_tag == MKBETAG('l','p','c','m')) + st->codecpar->codec_id = ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample, (flags ^ 0x2) | 0x4); else - st->codec->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codec->codec_tag); + st->codecpar->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codecpar->codec_tag); return 0; } @@ -101,10 +101,10 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; - if (size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return -1; - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { /* The magic cookie format for AAC is an mp4 esds atom. The lavc AAC decoder requires the data from the codec specific description as extradata input. */ @@ -113,13 +113,13 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) strt = avio_tell(pb); ff_mov_read_esds(s, pb); skip = size - (avio_tell(pb) - strt); - if (skip < 0 || !st->codec->extradata || - st->codec->codec_id != AV_CODEC_ID_AAC) { + if (skip < 0 || !st->codecpar->extradata || + st->codecpar->codec_id != AV_CODEC_ID_AAC) { av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n"); return AVERROR_INVALIDDATA; } avio_skip(pb, skip); - } else if (st->codec->codec_id == AV_CODEC_ID_ALAC) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_ALAC) { #define ALAC_PREAMBLE 12 #define ALAC_HEADER 36 #define ALAC_NEW_KUKI 24 @@ -131,8 +131,8 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) } avio_read(pb, preamble, ALAC_PREAMBLE); - st->codec->extradata = av_mallocz(ALAC_HEADER + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_mallocz(ALAC_HEADER + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); /* For the old style cookie, we skip 12 bytes, then read 36 bytes. @@ -142,26 +142,26 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) if (!memcmp(&preamble[4], "frmaalac", 8)) { if (size < ALAC_PREAMBLE + ALAC_HEADER) { av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n"); - av_freep(&st->codec->extradata); + av_freep(&st->codecpar->extradata); return AVERROR_INVALIDDATA; } - avio_read(pb, st->codec->extradata, ALAC_HEADER); + avio_read(pb, st->codecpar->extradata, ALAC_HEADER); avio_skip(pb, size - ALAC_PREAMBLE - ALAC_HEADER); } else { - AV_WB32(st->codec->extradata, 36); - memcpy(&st->codec->extradata[4], "alac", 4); - AV_WB32(&st->codec->extradata[8], 0); - memcpy(&st->codec->extradata[12], preamble, 12); - avio_read(pb, &st->codec->extradata[24], ALAC_NEW_KUKI - 12); + AV_WB32(st->codecpar->extradata, 36); + memcpy(&st->codecpar->extradata[4], "alac", 4); + AV_WB32(&st->codecpar->extradata[8], 0); + memcpy(&st->codecpar->extradata[12], preamble, 12); + avio_read(pb, &st->codecpar->extradata[24], ALAC_NEW_KUKI - 12); avio_skip(pb, size - ALAC_NEW_KUKI); } - st->codec->extradata_size = ALAC_HEADER; + st->codecpar->extradata_size = ALAC_HEADER; } else { - st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - avio_read(pb, st->codec->extradata, size); - st->codec->extradata_size = size; + avio_read(pb, st->codecpar->extradata, size); + st->codecpar->extradata_size = size; } return 0; @@ -172,7 +172,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) { AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; - CaffContext *caf = s->priv_data; + CafContext *caf = s->priv_data; int64_t pos = 0, ccount, num_packets; int i; @@ -221,7 +221,7 @@ static void read_info_chunk(AVFormatContext *s, int64_t size) static int read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - CaffContext *caf = s->priv_data; + CafContext *caf = s->priv_data; AVStream *st; uint32_t tag = 0; int found_data, ret; @@ -309,7 +309,7 @@ static int read_header(AVFormatContext *s) if (caf->data_size > 0) st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet; } else if (st->nb_index_entries) { - st->codec->bit_rate = st->codec->sample_rate * caf->data_size * 8 / + st->codecpar->bit_rate = st->codecpar->sample_rate * caf->data_size * 8 / st->duration; } else { av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when " @@ -317,7 +317,7 @@ static int read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->start_time = 0; /* position the stream at the start of data */ @@ -333,7 +333,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; - CaffContext *caf = s->priv_data; + CafContext *caf = s->priv_data; int res, pkt_size = 0, pkt_frames = 0; int64_t left = CAF_MAX_PKT_SIZE; @@ -387,7 +387,7 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { AVStream *st = s->streams[0]; - CaffContext *caf = s->priv_data; + CafContext *caf = s->priv_data; int64_t pos, packet_cnt, frame_cnt; timestamp = FFMAX(timestamp, 0); @@ -419,7 +419,7 @@ static int read_seek(AVFormatContext *s, int stream_index, AVInputFormat ff_caf_demuxer = { .name = "caf", .long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"), - .priv_data_size = sizeof(CaffContext), + .priv_data_size = sizeof(CafContext), .read_probe = probe, .read_header = read_header, .read_packet = read_packet, diff --git a/libavformat/cdg.c b/libavformat/cdg.c index e699691..3f11286 100644 --- a/libavformat/cdg.c +++ b/libavformat/cdg.c @@ -39,8 +39,8 @@ static int read_header(AVFormatContext *s) if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_CDGRAPHICS; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_CDGRAPHICS; /// 75 sectors/sec * 4 packets/sector = 300 packets/sec avpriv_set_pts_info(vst, 32, 1, 300); @@ -62,7 +62,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(s->pb, pkt, CDG_PACKET_SIZE); if (ret < 1 || (pkt->data[0] & CDG_MASK) == CDG_COMMAND) break; - av_free_packet(pkt); + av_packet_unref(pkt); } if (!priv->got_first_packet) { diff --git a/libavformat/cdxl.c b/libavformat/cdxl.c index a2cba52..26a5f81 100644 --- a/libavformat/cdxl.c +++ b/libavformat/cdxl.c @@ -99,17 +99,17 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 0; - st->codec->codec_id = AV_CODEC_ID_PCM_S8; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 0; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S8; if (cdxl->header[1] & 0x10) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - st->codec->sample_rate = cdxl->sample_rate; + st->codecpar->sample_rate = cdxl->sample_rate; st->start_time = 0; cdxl->audio_stream_index = st->index; avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate); @@ -128,11 +128,11 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = 0; - st->codec->codec_id = AV_CODEC_ID_CDXL; - st->codec->width = width; - st->codec->height = height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = 0; + st->codecpar->codec_id = AV_CODEC_ID_CDXL; + st->codecpar->width = width; + st->codecpar->height = height; st->start_time = 0; cdxl->video_stream_index = st->index; if (cdxl->framerate) @@ -146,7 +146,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) memcpy(pkt->data, cdxl->header, CDXL_HEADER_SIZE); ret = avio_read(pb, pkt->data + CDXL_HEADER_SIZE, video_size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } av_shrink_packet(pkt, CDXL_HEADER_SIZE + ret); diff --git a/libavformat/concat.c b/libavformat/concat.c index 416bbf5..a338df6 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -21,9 +21,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avformat.h" #include "libavutil/avstring.h" #include "libavutil/mem.h" + +#include "avformat.h" #include "url.h" #define AV_CAT_SEPARATOR "|" @@ -59,24 +60,26 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) char *node_uri = NULL; int err = 0; int64_t size; - size_t len, i; + size_t len, i; URLContext *uc; struct concat_data *data = h->priv_data; struct concat_nodes *nodes; av_strstart(uri, "concat:", &uri); - for (i = 0, len = 1; uri[i]; i++) - if (uri[i] == *AV_CAT_SEPARATOR) + for (i = 0, len = 1; uri[i]; i++) { + if (uri[i] == *AV_CAT_SEPARATOR) { /* integer overflow */ if (++len == UINT_MAX / sizeof(*nodes)) { av_freep(&h->priv_data); return AVERROR(ENAMETOOLONG); } + } + } - if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len))) { + if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len))) return AVERROR(ENOMEM); - } else + else data->nodes = nodes; /* handle input */ @@ -87,12 +90,12 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) len = strcspn(uri, AV_CAT_SEPARATOR); if ((err = av_reallocp(&node_uri, len + 1)) < 0) break; - av_strlcpy(node_uri, uri, len+1); - uri += len + strspn(uri+len, AV_CAT_SEPARATOR); + av_strlcpy(node_uri, uri, len + 1); + uri += len + strspn(uri + len, AV_CAT_SEPARATOR); /* creating URLContext */ if ((err = ffurl_open(&uc, node_uri, flags, - &h->interrupt_callback, NULL)) < 0) + &h->interrupt_callback, NULL, h->protocols, h)) < 0) break; /* creating size */ @@ -123,16 +126,17 @@ static int concat_read(URLContext *h, unsigned char *buf, int size) int result, total = 0; struct concat_data *data = h->priv_data; struct concat_nodes *nodes = data->nodes; - size_t i = data->current; + size_t i = data->current; while (size > 0) { result = ffurl_read(nodes[i].uc, buf, size); if (result < 0) return total ? total : result; - if (!result) + if (!result) { if (i + 1 == data->length || ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0) break; + } total += result; buf += result; size -= result; @@ -150,9 +154,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence) switch (whence) { case SEEK_END: - for (i = data->length - 1; - i && pos < -nodes[i].size; - i--) + for (i = data->length - 1; i && pos < -nodes[i].size; i--) pos += nodes[i].size; break; case SEEK_CUR: @@ -179,7 +181,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence) return result; } -URLProtocol ff_concat_protocol = { +const URLProtocol ff_concat_protocol = { .name = "concat", .url_open = concat_open, .url_read = concat_read, diff --git a/libavformat/crypto.c b/libavformat/crypto.c index 3bc33f2..55430c4 100644 --- a/libavformat/crypto.c +++ b/libavformat/crypto.c @@ -29,7 +29,7 @@ #define MAX_BUFFER_BLOCKS 150 #define BLOCKSIZE 16 -typedef struct { +typedef struct CryptoContext { const AVClass *class; URLContext *hd; uint8_t inbuffer [BLOCKSIZE*MAX_BUFFER_BLOCKS], @@ -83,7 +83,7 @@ static int crypto_open(URLContext *h, const char *uri, int flags) goto err; } if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ, - &h->interrupt_callback, NULL)) < 0) { + &h->interrupt_callback, NULL, h->protocols, h)) < 0) { av_log(h, AV_LOG_ERROR, "Unable to open input\n"); goto err; } @@ -159,7 +159,7 @@ static int crypto_close(URLContext *h) return 0; } -URLProtocol ff_crypto_protocol = { +const URLProtocol ff_crypto_protocol = { .name = "crypto", .url_open = crypto_open, .url_read = crypto_read, diff --git a/libavformat/cutils.c b/libavformat/cutils.c index f58e152..f5339a9 100644 --- a/libavformat/cutils.c +++ b/libavformat/cutils.c @@ -18,6 +18,8 @@ * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "libavutil/time_internal.h" #include "avformat.h" #include "internal.h" @@ -49,30 +51,10 @@ void ff_dynarray_add(intptr_t **tab_ptr, int *nb_ptr, intptr_t elem) couple of places, though. */ struct tm *ff_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 > 365) { - ny = (y + days/366); - days -= (ny - y) * 365 + LEAPS_COUNT(ny - 1) - LEAPS_COUNT(y - 1); - y = ny; - } - if (days==365 && !ISLEAP(y)) { days=0; y++; } - md[1] = ISLEAP(y)?29:28; - for (m=0; days >= md[m]; m++) - days -= md[m]; + tm = gmtime_r(&secs, tm); - 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; + tm->tm_year += 1900; /* unlike gmtime_r we store complete year here */ + tm->tm_mon += 1; /* unlike gmtime_r tm_mon is from 1 to 12 */ return tm; } diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c new file mode 100644 index 0000000..9c7e23a --- /dev/null +++ b/libavformat/dashenc.c @@ -0,0 +1,1006 @@ +/* + * MPEG-DASH ISO BMFF segmenter + * Copyright (c) 2014 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#if HAVE_UNISTD_H +#include +#endif + +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/time_internal.h" + +#include "avc.h" +#include "avformat.h" +#include "avio_internal.h" +#include "internal.h" +#include "isom.h" +#include "os_support.h" +#include "url.h" + +// See ISO/IEC 23009-1:2014 5.3.9.4.4 +typedef enum { + DASH_TMPL_ID_UNDEFINED = -1, + DASH_TMPL_ID_ESCAPE, + DASH_TMPL_ID_REP_ID, + DASH_TMPL_ID_NUMBER, + DASH_TMPL_ID_BANDWIDTH, + DASH_TMPL_ID_TIME, +} DASHTmplId; + +typedef struct Segment { + char file[1024]; + int64_t start_pos; + int range_length, index_length; + int64_t time; + int duration; + int n; +} Segment; + +typedef struct OutputStream { + AVFormatContext *ctx; + int ctx_inited; + uint8_t iobuf[32768]; + AVIOContext *out; + int packets_written; + char initfile[1024]; + int64_t init_start_pos; + int init_range_length; + int nb_segments, segments_size, segment_index; + Segment **segments; + int64_t first_pts, start_pts, max_pts; + int64_t last_dts; + int bit_rate; + char bandwidth_str[64]; + + char codec_str[100]; +} OutputStream; + +typedef struct DASHContext { + const AVClass *class; /* Class for private options. */ + int window_size; + int extra_window_size; + int min_seg_duration; + int remove_at_exit; + int use_template; + int use_timeline; + int single_file; + OutputStream *streams; + int has_video, has_audio; + int64_t last_duration; + int64_t total_duration; + char availability_start_time[100]; + char dirname[1024]; + const char *single_file_name; + const char *init_seg_name; + const char *media_seg_name; +} DASHContext; + +static int dash_write(void *opaque, uint8_t *buf, int buf_size) +{ + OutputStream *os = opaque; + if (os->out) + avio_write(os->out, buf, buf_size); + return buf_size; +} + +// RFC 6381 +static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, + char *str, int size) +{ + const AVCodecTag *tags[2] = { NULL, NULL }; + uint32_t tag; + if (par->codec_type == AVMEDIA_TYPE_VIDEO) + tags[0] = ff_codec_movvideo_tags; + else if (par->codec_type == AVMEDIA_TYPE_AUDIO) + tags[0] = ff_codec_movaudio_tags; + else + return; + + tag = av_codec_get_tag(tags, par->codec_id); + if (!tag) + return; + if (size < 5) + return; + + AV_WL32(str, tag); + str[4] = '\0'; + if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) { + uint32_t oti; + tags[0] = ff_mp4_obj_type; + oti = av_codec_get_tag(tags, par->codec_id); + if (oti) + av_strlcatf(str, size, ".%02x", oti); + else + return; + + if (tag == MKTAG('m', 'p', '4', 'a')) { + if (par->extradata_size >= 2) { + int aot = par->extradata[0] >> 3; + if (aot == 31) + aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32; + av_strlcatf(str, size, ".%d", aot); + } + } else if (tag == MKTAG('m', 'p', '4', 'v')) { + // Unimplemented, should output ProfileLevelIndication as a decimal number + av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n"); + } + } else if (!strcmp(str, "avc1")) { + uint8_t *tmpbuf = NULL; + uint8_t *extradata = par->extradata; + int extradata_size = par->extradata_size; + if (!extradata_size) + return; + if (extradata[0] != 1) { + AVIOContext *pb; + if (avio_open_dyn_buf(&pb) < 0) + return; + if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) { + ffio_free_dyn_buf(&pb); + return; + } + extradata_size = avio_close_dyn_buf(pb, &extradata); + tmpbuf = extradata; + } + + if (extradata_size >= 4) + av_strlcatf(str, size, ".%02x%02x%02x", + extradata[1], extradata[2], extradata[3]); + av_free(tmpbuf); + } +} + +static void dash_free(AVFormatContext *s) +{ + DASHContext *c = s->priv_data; + int i, j; + if (!c->streams) + return; + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + if (os->ctx && os->ctx_inited) + av_write_trailer(os->ctx); + if (os->ctx && os->ctx->pb) + av_free(os->ctx->pb); + ff_format_io_close(s, &os->out); + if (os->ctx) + avformat_free_context(os->ctx); + for (j = 0; j < os->nb_segments; j++) + av_free(os->segments[j]); + av_free(os->segments); + } + av_freep(&c->streams); +} + +static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c) +{ + int i, start_index = 0, start_number = 1; + if (c->window_size) { + start_index = FFMAX(os->nb_segments - c->window_size, 0); + start_number = FFMAX(os->segment_index - c->window_size, 1); + } + + if (c->use_template) { + int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE; + avio_printf(out, "\t\t\t\tuse_timeline) + avio_printf(out, "duration=\"%"PRId64"\" ", c->last_duration); + avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", c->init_seg_name, c->media_seg_name, c->use_timeline ? start_number : 1); + if (c->use_timeline) { + int64_t cur_time = 0; + avio_printf(out, "\t\t\t\t\t\n"); + for (i = start_index; i < os->nb_segments; ) { + Segment *seg = os->segments[i]; + int repeat = 0; + avio_printf(out, "\t\t\t\t\t\ttime != cur_time) { + cur_time = seg->time; + avio_printf(out, "t=\"%"PRId64"\" ", seg->time); + } + avio_printf(out, "d=\"%d\" ", seg->duration); + while (i + repeat + 1 < os->nb_segments && + os->segments[i + repeat + 1]->duration == seg->duration && + os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration) + repeat++; + if (repeat > 0) + avio_printf(out, "r=\"%d\" ", repeat); + avio_printf(out, "/>\n"); + i += 1 + repeat; + cur_time += (1 + repeat) * seg->duration; + } + avio_printf(out, "\t\t\t\t\t\n"); + } + avio_printf(out, "\t\t\t\t\n"); + } else if (c->single_file) { + avio_printf(out, "\t\t\t\t%s\n", os->initfile); + avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, c->last_duration, start_number); + avio_printf(out, "\t\t\t\t\t\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1); + for (i = start_index; i < os->nb_segments; i++) { + Segment *seg = os->segments[i]; + avio_printf(out, "\t\t\t\t\tstart_pos, seg->start_pos + seg->range_length - 1); + if (seg->index_length) + avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1); + avio_printf(out, "/>\n"); + } + avio_printf(out, "\t\t\t\t\n"); + } else { + avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, c->last_duration, start_number); + avio_printf(out, "\t\t\t\t\t\n", os->initfile); + for (i = start_index; i < os->nb_segments; i++) { + Segment *seg = os->segments[i]; + avio_printf(out, "\t\t\t\t\t\n", seg->file); + } + avio_printf(out, "\t\t\t\t\n"); + } +} + +static DASHTmplId dash_read_tmpl_id(const char *identifier, char *format_tag, + size_t format_tag_size, const char **ptr) { + const char *next_ptr; + DASHTmplId id_type = DASH_TMPL_ID_UNDEFINED; + + if (av_strstart(identifier, "$$", &next_ptr)) { + id_type = DASH_TMPL_ID_ESCAPE; + *ptr = next_ptr; + } else if (av_strstart(identifier, "$RepresentationID$", &next_ptr)) { + id_type = DASH_TMPL_ID_REP_ID; + // default to basic format, as $RepresentationID$ identifiers + // are not allowed to have custom format-tags. + av_strlcpy(format_tag, "%d", format_tag_size); + *ptr = next_ptr; + } else { // the following identifiers may have an explicit format_tag + if (av_strstart(identifier, "$Number", &next_ptr)) + id_type = DASH_TMPL_ID_NUMBER; + else if (av_strstart(identifier, "$Bandwidth", &next_ptr)) + id_type = DASH_TMPL_ID_BANDWIDTH; + else if (av_strstart(identifier, "$Time", &next_ptr)) + id_type = DASH_TMPL_ID_TIME; + else + id_type = DASH_TMPL_ID_UNDEFINED; + + // next parse the dash format-tag and generate a c-string format tag + // (next_ptr now points at the first '%' at the beginning of the format-tag) + if (id_type != DASH_TMPL_ID_UNDEFINED) { + const char *number_format = (id_type == DASH_TMPL_ID_TIME) ? PRId64 : "d"; + if (next_ptr[0] == '$') { // no dash format-tag + snprintf(format_tag, format_tag_size, "%%%s", number_format); + *ptr = &next_ptr[1]; + } else { + const char *width_ptr; + // only tolerate single-digit width-field (i.e. up to 9-digit width) + if (av_strstart(next_ptr, "%0", &width_ptr) && + av_isdigit(width_ptr[0]) && + av_strstart(&width_ptr[1], "d$", &next_ptr)) { + // yes, we're using a format tag to build format_tag. + snprintf(format_tag, format_tag_size, "%s%c%s", "%0", width_ptr[0], number_format); + *ptr = next_ptr; + } else { + av_log(NULL, AV_LOG_WARNING, "Failed to parse format-tag beginning with %s. Expected either a " + "closing '$' character or a format-string like '%%0[width]d', " + "where width must be a single digit\n", next_ptr); + id_type = DASH_TMPL_ID_UNDEFINED; + } + } + } + } + return id_type; +} + +static void dash_fill_tmpl_params(char *dst, size_t buffer_size, + const char *template, int rep_id, + int number, int bit_rate, + int64_t time) { + int dst_pos = 0; + const char *t_cur = template; + while (dst_pos < buffer_size - 1 && *t_cur) { + char format_tag[7]; // May be "%d", "%0Xd", or "%0Xlld" (for $Time$), where X is in [0-9] + int n = 0; + DASHTmplId id_type; + const char *t_next = strchr(t_cur, '$'); // copy over everything up to the first '$' character + if (t_next) { + int num_copy_bytes = FFMIN(t_next - t_cur, buffer_size - dst_pos - 1); + av_strlcpy(&dst[dst_pos], t_cur, num_copy_bytes + 1); + // advance + dst_pos += num_copy_bytes; + t_cur = t_next; + } else { // no more DASH identifiers to substitute - just copy the rest over and break + av_strlcpy(&dst[dst_pos], t_cur, buffer_size - dst_pos); + break; + } + + if (dst_pos >= buffer_size - 1 || !*t_cur) + break; + + // t_cur is now pointing to a '$' character + id_type = dash_read_tmpl_id(t_cur, format_tag, sizeof(format_tag), &t_next); + switch (id_type) { + case DASH_TMPL_ID_ESCAPE: + av_strlcpy(&dst[dst_pos], "$", 2); + n = 1; + break; + case DASH_TMPL_ID_REP_ID: + n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, rep_id); + break; + case DASH_TMPL_ID_NUMBER: + n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, number); + break; + case DASH_TMPL_ID_BANDWIDTH: + n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, bit_rate); + break; + case DASH_TMPL_ID_TIME: + n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, time); + break; + case DASH_TMPL_ID_UNDEFINED: + // copy over one byte and advance + av_strlcpy(&dst[dst_pos], t_cur, 2); + n = 1; + t_next = &t_cur[1]; + break; + } + // t_next points just past the processed identifier + // n is the number of bytes that were attempted to be written to dst + // (may have failed to write all because buffer_size). + + // advance + dst_pos += FFMIN(n, buffer_size - dst_pos - 1); + t_cur = t_next; + } +} + +static char *xmlescape(const char *str) { + int outlen = strlen(str)*3/2 + 6; + char *out = av_realloc(NULL, outlen + 1); + int pos = 0; + if (!out) + return NULL; + for (; *str; str++) { + if (pos + 6 > outlen) { + char *tmp; + outlen = 2 * outlen + 6; + tmp = av_realloc(out, outlen + 1); + if (!tmp) { + av_free(out); + return NULL; + } + out = tmp; + } + if (*str == '&') { + memcpy(&out[pos], "&", 5); + pos += 5; + } else if (*str == '<') { + memcpy(&out[pos], "<", 4); + pos += 4; + } else if (*str == '>') { + memcpy(&out[pos], ">", 4); + pos += 4; + } else if (*str == '\'') { + memcpy(&out[pos], "'", 6); + pos += 6; + } else if (*str == '\"') { + memcpy(&out[pos], """, 6); + pos += 6; + } else { + out[pos++] = *str; + } + } + out[pos] = '\0'; + return out; +} + +static void write_time(AVIOContext *out, int64_t time) +{ + int seconds = time / AV_TIME_BASE; + int fractions = time % AV_TIME_BASE; + int minutes = seconds / 60; + int hours = minutes / 60; + seconds %= 60; + minutes %= 60; + avio_printf(out, "PT"); + if (hours) + avio_printf(out, "%dH", hours); + if (hours || minutes) + avio_printf(out, "%dM", minutes); + avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10)); +} + +static void format_date_now(char *buf, int size) +{ + time_t t = time(NULL); + struct tm *ptm, tmbuf; + ptm = gmtime_r(&t, &tmbuf); + if (ptm) { + if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) + buf[0] = '\0'; + } +} + +static int write_manifest(AVFormatContext *s, int final) +{ + DASHContext *c = s->priv_data; + AVIOContext *out; + char temp_filename[1024]; + int ret, i; + AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); + + snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename); + ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); + return ret; + } + avio_printf(out, "\n"); + avio_printf(out, "total_duration); + avio_printf(out, "\"\n"); + } else { + int64_t update_period = c->last_duration / AV_TIME_BASE; + char now_str[100]; + if (c->use_template && !c->use_timeline) + update_period = 500; + avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period); + avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); + if (!c->availability_start_time[0] && s->nb_streams > 0 && c->streams[0].nb_segments > 0) { + format_date_now(c->availability_start_time, sizeof(c->availability_start_time)); + } + if (c->availability_start_time[0]) + avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time); + format_date_now(now_str, sizeof(now_str)); + if (now_str[0]) + avio_printf(out, "\tpublishTime=\"%s\"\n", now_str); + if (c->window_size && c->use_template) { + avio_printf(out, "\ttimeShiftBufferDepth=\""); + write_time(out, c->last_duration * c->window_size); + avio_printf(out, "\"\n"); + } + } + avio_printf(out, "\tminBufferTime=\""); + write_time(out, c->last_duration); + avio_printf(out, "\">\n"); + avio_printf(out, "\t\n"); + if (title) { + char *escaped = xmlescape(title->value); + avio_printf(out, "\t\t%s\n", escaped); + av_free(escaped); + } + avio_printf(out, "\t\n"); + if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) { + OutputStream *os = &c->streams[0]; + int start_index = FFMAX(os->nb_segments - c->window_size, 0); + int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q); + avio_printf(out, "\t\n"); + } else { + avio_printf(out, "\t\n"); + } + + if (c->has_video) { + avio_printf(out, "\t\t\n"); + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + OutputStream *os = &c->streams[i]; + if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) + continue; + avio_printf(out, "\t\t\t\n", i, os->codec_str, os->bandwidth_str, st->codecpar->width, st->codecpar->height); + output_segment_list(&c->streams[i], out, c); + avio_printf(out, "\t\t\t\n"); + } + avio_printf(out, "\t\t\n"); + } + if (c->has_audio) { + avio_printf(out, "\t\t\n"); + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + OutputStream *os = &c->streams[i]; + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + avio_printf(out, "\t\t\t\n", i, os->codec_str, os->bandwidth_str, st->codecpar->sample_rate); + avio_printf(out, "\t\t\t\t\n", st->codecpar->channels); + output_segment_list(&c->streams[i], out, c); + avio_printf(out, "\t\t\t\n"); + } + avio_printf(out, "\t\t\n"); + } + avio_printf(out, "\t\n"); + avio_printf(out, "\n"); + avio_flush(out); + ff_format_io_close(s, &out); + return ff_rename(temp_filename, s->filename); +} + +static int dash_write_header(AVFormatContext *s) +{ + DASHContext *c = s->priv_data; + int ret = 0, i; + AVOutputFormat *oformat; + char *ptr; + char basename[1024]; + + if (c->single_file_name) + c->single_file = 1; + if (c->single_file) + c->use_template = 0; + + av_strlcpy(c->dirname, s->filename, sizeof(c->dirname)); + ptr = strrchr(c->dirname, '/'); + if (ptr) { + av_strlcpy(basename, &ptr[1], sizeof(basename)); + ptr[1] = '\0'; + } else { + c->dirname[0] = '\0'; + av_strlcpy(basename, s->filename, sizeof(basename)); + } + + ptr = strrchr(basename, '.'); + if (ptr) + *ptr = '\0'; + + oformat = av_guess_format("mp4", NULL, NULL); + if (!oformat) { + ret = AVERROR_MUXER_NOT_FOUND; + goto fail; + } + + c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); + if (!c->streams) { + ret = AVERROR(ENOMEM); + goto fail; + } + + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + AVFormatContext *ctx; + AVStream *st; + AVDictionary *opts = NULL; + char filename[1024]; + + os->bit_rate = s->streams[i]->codecpar->bit_rate; + if (os->bit_rate) { + snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), + " bandwidth=\"%d\"", os->bit_rate); + } else { + int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ? + AV_LOG_ERROR : AV_LOG_WARNING; + av_log(s, level, "No bit rate set for stream %d\n", i); + if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT) { + ret = AVERROR(EINVAL); + goto fail; + } + } + + ctx = avformat_alloc_context(); + if (!ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + os->ctx = ctx; + ctx->oformat = oformat; + ctx->interrupt_callback = s->interrupt_callback; + ctx->opaque = s->opaque; + ctx->io_close = s->io_close; + ctx->io_open = s->io_open; + + if (!(st = avformat_new_stream(ctx, NULL))) { + ret = AVERROR(ENOMEM); + goto fail; + } + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); + st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->time_base = s->streams[i]->time_base; + ctx->avoid_negative_ts = s->avoid_negative_ts; + + ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, dash_write, NULL); + if (!ctx->pb) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (c->single_file) { + if (c->single_file_name) + dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0); + else + snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i); + } else { + dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0); + } + snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); + ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL); + if (ret < 0) + goto fail; + os->init_start_pos = 0; + + av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); + if ((ret = avformat_write_header(ctx, &opts)) < 0) { + goto fail; + } + os->ctx_inited = 1; + avio_flush(ctx->pb); + av_dict_free(&opts); + + av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename); + + s->streams[i]->time_base = st->time_base; + // If the muxer wants to shift timestamps, request to have them shifted + // already before being handed to this muxer, so we don't have mismatches + // between the MPD and the actual segments. + s->avoid_negative_ts = ctx->avoid_negative_ts; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + c->has_video = 1; + else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + c->has_audio = 1; + + set_codec_str(s, st->codecpar, os->codec_str, sizeof(os->codec_str)); + os->first_pts = AV_NOPTS_VALUE; + os->max_pts = AV_NOPTS_VALUE; + os->last_dts = AV_NOPTS_VALUE; + os->segment_index = 1; + } + + if (!c->has_video && c->min_seg_duration <= 0) { + av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration set\n"); + ret = AVERROR(EINVAL); + } + ret = write_manifest(s, 0); + if (!ret) + av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->filename); + +fail: + if (ret) + dash_free(s); + return ret; +} + +static int add_segment(OutputStream *os, const char *file, + int64_t time, int duration, + int64_t start_pos, int64_t range_length, + int64_t index_length) +{ + int err; + Segment *seg; + if (os->nb_segments >= os->segments_size) { + os->segments_size = (os->segments_size + 1) * 2; + if ((err = av_reallocp(&os->segments, sizeof(*os->segments) * + os->segments_size)) < 0) { + os->segments_size = 0; + os->nb_segments = 0; + return err; + } + } + seg = av_mallocz(sizeof(*seg)); + if (!seg) + return AVERROR(ENOMEM); + av_strlcpy(seg->file, file, sizeof(seg->file)); + seg->time = time; + seg->duration = duration; + if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list + seg->duration += seg->time; + seg->time = 0; + } + seg->start_pos = start_pos; + seg->range_length = range_length; + seg->index_length = index_length; + os->segments[os->nb_segments++] = seg; + os->segment_index++; + return 0; +} + +static void write_styp(AVIOContext *pb) +{ + avio_wb32(pb, 24); + ffio_wfourcc(pb, "styp"); + ffio_wfourcc(pb, "msdh"); + avio_wb32(pb, 0); /* minor */ + ffio_wfourcc(pb, "msdh"); + ffio_wfourcc(pb, "msix"); +} + +static void find_index_range(AVFormatContext *s, const char *full_path, + int64_t pos, int *index_length) +{ + uint8_t buf[8]; + AVIOContext *pb; + int ret; + + ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL); + if (ret < 0) + return; + if (avio_seek(pb, pos, SEEK_SET) != pos) { + ff_format_io_close(s, &pb); + return; + } + ret = avio_read(pb, buf, 8); + ff_format_io_close(s, &pb); + if (ret < 8) + return; + if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x')) + return; + *index_length = AV_RB32(&buf[0]); +} + +static int update_stream_extradata(AVFormatContext *s, OutputStream *os, + AVCodecParameters *par) +{ + uint8_t *extradata; + + if (os->ctx->streams[0]->codecpar->extradata_size || !par->extradata_size) + return 0; + + extradata = av_malloc(par->extradata_size); + + if (!extradata) + return AVERROR(ENOMEM); + + memcpy(extradata, par->extradata, par->extradata_size); + + os->ctx->streams[0]->codecpar->extradata = extradata; + os->ctx->streams[0]->codecpar->extradata_size = par->extradata_size; + + set_codec_str(s, par, os->codec_str, sizeof(os->codec_str)); + + return 0; +} + +static int dash_flush(AVFormatContext *s, int final, int stream) +{ + DASHContext *c = s->priv_data; + int i, ret = 0; + int cur_flush_segment_index = 0; + if (stream >= 0) + cur_flush_segment_index = c->streams[stream].segment_index; + + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + char filename[1024] = "", full_path[1024], temp_path[1024]; + int64_t start_pos; + int range_length, index_length = 0; + + if (!os->packets_written) + continue; + + // Flush the single stream that got a keyframe right now. + // Flush all audio streams as well, in sync with video keyframes, + // but not the other video streams. + if (stream >= 0 && i != stream) { + if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + // Make sure we don't flush audio streams multiple times, when + // all video streams are flushed one at a time. + if (c->has_video && os->segment_index > cur_flush_segment_index) + continue; + } + + if (!os->init_range_length) { + av_write_frame(os->ctx, NULL); + os->init_range_length = avio_tell(os->ctx->pb); + if (!c->single_file) + ff_format_io_close(s, &os->out); + } + + start_pos = avio_tell(os->ctx->pb); + + if (!c->single_file) { + dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts); + snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); + snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path); + ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL); + if (ret < 0) + break; + write_styp(os->ctx->pb); + } else { + snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, os->initfile); + } + + av_write_frame(os->ctx, NULL); + avio_flush(os->ctx->pb); + os->packets_written = 0; + + range_length = avio_tell(os->ctx->pb) - start_pos; + if (c->single_file) { + find_index_range(s, full_path, start_pos, &index_length); + } else { + ff_format_io_close(s, &os->out); + ret = ff_rename(temp_path, full_path); + if (ret < 0) + break; + } + add_segment(os, filename, os->start_pts, os->max_pts - os->start_pts, start_pos, range_length, index_length); + av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, full_path); + } + + if (c->window_size || (final && c->remove_at_exit)) { + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + int j; + int remove = os->nb_segments - c->window_size - c->extra_window_size; + if (final && c->remove_at_exit) + remove = os->nb_segments; + if (remove > 0) { + for (j = 0; j < remove; j++) { + char filename[1024]; + snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file); + unlink(filename); + av_free(os->segments[j]); + } + os->nb_segments -= remove; + memmove(os->segments, os->segments + remove, os->nb_segments * sizeof(*os->segments)); + } + } + } + + if (ret >= 0) + ret = write_manifest(s, final); + return ret; +} + +static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + DASHContext *c = s->priv_data; + AVStream *st = s->streams[pkt->stream_index]; + OutputStream *os = &c->streams[pkt->stream_index]; + int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration; + int ret; + + ret = update_stream_extradata(s, os, st->codecpar); + if (ret < 0) + return ret; + + // Fill in a heuristic guess of the packet duration, if none is available. + // The mp4 muxer will do something similar (for the last packet in a fragment) + // if nothing is set (setting it for the other packets doesn't hurt). + // By setting a nonzero duration here, we can be sure that the mp4 muxer won't + // invoke its heuristic (this doesn't have to be identical to that algorithm), + // so that we know the exact timestamps of fragments. + if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE) + pkt->duration = pkt->dts - os->last_dts; + os->last_dts = pkt->dts; + + // If forcing the stream to start at 0, the mp4 muxer will set the start + // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps. + if (os->first_pts == AV_NOPTS_VALUE && + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { + pkt->pts -= pkt->dts; + pkt->dts = 0; + } + + if (os->first_pts == AV_NOPTS_VALUE) + os->first_pts = pkt->pts; + + if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && + pkt->flags & AV_PKT_FLAG_KEY && os->packets_written && + av_compare_ts(pkt->pts - os->first_pts, st->time_base, + seg_end_duration, AV_TIME_BASE_Q) >= 0) { + int64_t prev_duration = c->last_duration; + + c->last_duration = av_rescale_q(pkt->pts - os->start_pts, + st->time_base, + AV_TIME_BASE_Q); + c->total_duration = av_rescale_q(pkt->pts - os->first_pts, + st->time_base, + AV_TIME_BASE_Q); + + if ((!c->use_timeline || !c->use_template) && prev_duration) { + if (c->last_duration < prev_duration*9/10 || + c->last_duration > prev_duration*11/10) { + av_log(s, AV_LOG_WARNING, + "Segment durations differ too much, enable use_timeline " + "and use_template, or keep a stricter keyframe interval\n"); + } + } + + if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0) + return ret; + } + + if (!os->packets_written) { + // If we wrote a previous segment, adjust the start time of the segment + // to the end of the previous one (which is the same as the mp4 muxer + // does). This avoids gaps in the timeline. + if (os->max_pts != AV_NOPTS_VALUE) + os->start_pts = os->max_pts; + else + os->start_pts = pkt->pts; + } + if (os->max_pts == AV_NOPTS_VALUE) + os->max_pts = pkt->pts + pkt->duration; + else + os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration); + os->packets_written++; + return ff_write_chained(os->ctx, 0, pkt, s); +} + +static int dash_write_trailer(AVFormatContext *s) +{ + DASHContext *c = s->priv_data; + + if (s->nb_streams > 0) { + OutputStream *os = &c->streams[0]; + // If no segments have been written so far, try to do a crude + // guess of the segment duration + if (!c->last_duration) + c->last_duration = av_rescale_q(os->max_pts - os->start_pts, + s->streams[0]->time_base, + AV_TIME_BASE_Q); + c->total_duration = av_rescale_q(os->max_pts - os->first_pts, + s->streams[0]->time_base, + AV_TIME_BASE_Q); + } + dash_flush(s, 1, -1); + + if (c->remove_at_exit) { + char filename[1024]; + int i; + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); + unlink(filename); + } + unlink(s->filename); + } + + dash_free(s); + return 0; +} + +#define OFFSET(x) offsetof(DASHContext, x) +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E }, + { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E }, + { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E }, + { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E }, + { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E }, + { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E }, + { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E }, + { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, + { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E }, + { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, + { NULL }, +}; + +static const AVClass dash_class = { + .class_name = "dash muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVOutputFormat ff_dash_muxer = { + .name = "dash", + .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"), + .priv_data_size = sizeof(DASHContext), + .audio_codec = AV_CODEC_ID_AAC, + .video_codec = AV_CODEC_ID_H264, + .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, + .write_header = dash_write_header, + .write_packet = dash_write_packet, + .write_trailer = dash_write_trailer, + .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .priv_class = &dash_class, +}; diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c index 1855e84..98f8a57 100644 --- a/libavformat/dauddec.c +++ b/libavformat/dauddec.c @@ -26,15 +26,15 @@ static int daud_header(AVFormatContext *s) { AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_S24DAUD; - st->codec->codec_tag = MKTAG('d', 'a', 'u', 'd'); - st->codec->channels = 6; - st->codec->channel_layout = AV_CH_LAYOUT_5POINT1; - st->codec->sample_rate = 96000; - st->codec->bit_rate = 3 * 6 * 96000 * 8; - st->codec->block_align = 3 * 6; - st->codec->bits_per_coded_sample = 24; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24DAUD; + st->codecpar->codec_tag = MKTAG('d', 'a', 'u', 'd'); + st->codecpar->channels = 6; + st->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1; + st->codecpar->sample_rate = 96000; + st->codecpar->bit_rate = 3 * 6 * 96000 * 8; + st->codecpar->block_align = 3 * 6; + st->codecpar->bits_per_coded_sample = 24; return 0; } diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c index 416e895..93608e3 100644 --- a/libavformat/daudenc.c +++ b/libavformat/daudenc.c @@ -23,8 +23,8 @@ static int daud_write_header(struct AVFormatContext *s) { - AVCodecContext *codec = s->streams[0]->codec; - if (codec->channels!=6 || codec->sample_rate!=96000) + AVCodecParameters *par = s->streams[0]->codecpar; + if (par->channels!=6 || par->sample_rate!=96000) return -1; return 0; } diff --git a/libavformat/dfa.c b/libavformat/dfa.c index c097d72..cecf6b6 100644 --- a/libavformat/dfa.c +++ b/libavformat/dfa.c @@ -51,10 +51,10 @@ static int dfa_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DFA; - st->codec->width = avio_rl16(pb); - st->codec->height = avio_rl16(pb); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DFA; + st->codecpar->width = avio_rl16(pb); + st->codecpar->height = avio_rl16(pb); mspf = avio_rl32(pb); if (!mspf) { av_log(s, AV_LOG_WARNING, "Zero FPS reported, defaulting to 10\n"); @@ -82,7 +82,7 @@ static int dfa_read_packet(AVFormatContext *s, AVPacket *pkt) if (!first) { ret = av_append_packet(pb, pkt, 12); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } } else @@ -103,7 +103,7 @@ static int dfa_read_packet(AVFormatContext *s, AVPacket *pkt) } ret = av_append_packet(pb, pkt, frame_size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } } diff --git a/libavformat/dsicin.c b/libavformat/dsicin.c index 6a7c8b9..fa5943d 100644 --- a/libavformat/dsicin.c +++ b/libavformat/dsicin.c @@ -115,11 +115,11 @@ static int cin_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 32, 1, 12); cin->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DSICINVIDEO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = hdr->video_frame_width; - st->codec->height = hdr->video_frame_height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DSICINVIDEO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = hdr->video_frame_width; + st->codecpar->height = hdr->video_frame_height; /* initialize the audio decoder stream */ st = avformat_new_stream(s, NULL); @@ -128,14 +128,14 @@ static int cin_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 32, 1, 22050); cin->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_DSICINAUDIO; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = 22050; - st->codec->bits_per_coded_sample = 8; - st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_DSICINAUDIO; + st->codecpar->codec_tag = 0; /* no tag */ + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = 22050; + st->codecpar->bits_per_coded_sample = 8; + st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels; return 0; } @@ -197,7 +197,7 @@ static int cin_read_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_read(pb, &pkt->data[4], pkt_size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } if (ret < pkt_size) diff --git a/libavformat/dss.c b/libavformat/dss.c new file mode 100644 index 0000000..a9b2ebf --- /dev/null +++ b/libavformat/dss.c @@ -0,0 +1,342 @@ +/* + * Digital Speech Standard (DSS) demuxer + * Copyright (c) 2014 Oleksij Rempel + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/bswap.h" +#include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "internal.h" + +#define DSS_HEAD_OFFSET_AUTHOR 0xc +#define DSS_AUTHOR_SIZE 16 + +#define DSS_HEAD_OFFSET_START_TIME 0x26 +#define DSS_HEAD_OFFSET_END_TIME 0x32 +#define DSS_TIME_SIZE 12 + +#define DSS_HEAD_OFFSET_ACODEC 0x2a4 +#define DSS_ACODEC_DSS_SP 0x0 /* SP mode */ +#define DSS_ACODEC_G723_1 0x2 /* LP mode */ + +#define DSS_HEAD_OFFSET_COMMENT 0x31e +#define DSS_COMMENT_SIZE 64 + +#define DSS_BLOCK_SIZE 512 +#define DSS_HEADER_SIZE (DSS_BLOCK_SIZE * 2) +#define DSS_AUDIO_BLOCK_HEADER_SIZE 6 +#define DSS_FRAME_SIZE 42 + +static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; + +typedef struct DSSDemuxContext { + unsigned int audio_codec; + int counter; + int swap; + int dss_sp_swap_byte; + int8_t *dss_sp_buf; +} DSSDemuxContext; + +static int dss_probe(AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG(0x2, 'd', 's', 's')) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int dss_read_metadata_date(AVFormatContext *s, unsigned int offset, + const char *key) +{ + AVIOContext *pb = s->pb; + char datetime[64], string[DSS_TIME_SIZE + 1] = { 0 }; + int y, month, d, h, minute, sec; + int ret; + + avio_seek(pb, offset, SEEK_SET); + + ret = avio_read(s->pb, string, DSS_TIME_SIZE); + if (ret < DSS_TIME_SIZE) + return ret < 0 ? ret : AVERROR_EOF; + + sscanf(string, "%2d%2d%2d%2d%2d%2d", &y, &month, &d, &h, &minute, &sec); + /* We deal with a two-digit year here, so set the default date to 2000 + * and hope it will never be used in the next century. */ + snprintf(datetime, sizeof(datetime), "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", + y + 2000, month, d, h, minute, sec); + return av_dict_set(&s->metadata, key, datetime, 0); +} + +static int dss_read_metadata_string(AVFormatContext *s, unsigned int offset, + unsigned int size, const char *key) +{ + AVIOContext *pb = s->pb; + char *value; + int ret; + + avio_seek(pb, offset, SEEK_SET); + + value = av_mallocz(size + 1); + if (!value) + return AVERROR(ENOMEM); + + ret = avio_read(s->pb, value, size); + if (ret < size) { + ret = ret < 0 ? ret : AVERROR_EOF; + goto exit; + } + + ret = av_dict_set(&s->metadata, key, value, 0); + +exit: + av_free(value); + return ret; +} + +static int dss_read_header(AVFormatContext *s) +{ + DSSDemuxContext *ctx = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st; + int ret; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_AUTHOR, + DSS_AUTHOR_SIZE, "author"); + if (ret) + return ret; + + ret = dss_read_metadata_date(s, DSS_HEAD_OFFSET_END_TIME, "date"); + if (ret) + return ret; + + ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_COMMENT, + DSS_COMMENT_SIZE, "comment"); + if (ret) + return ret; + + avio_seek(pb, DSS_HEAD_OFFSET_ACODEC, SEEK_SET); + ctx->audio_codec = avio_r8(pb); + + if (ctx->audio_codec == DSS_ACODEC_DSS_SP) { + st->codecpar->codec_id = AV_CODEC_ID_DSS_SP; + st->codecpar->sample_rate = 12000; + } else if (ctx->audio_codec == DSS_ACODEC_G723_1) { + st->codecpar->codec_id = AV_CODEC_ID_G723_1; + st->codecpar->sample_rate = 8000; + } else { + avpriv_request_sample(s, "Support for codec %x in DSS", + ctx->audio_codec); + return AVERROR_PATCHWELCOME; + } + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + st->start_time = 0; + + /* Jump over header */ + + if (avio_seek(pb, DSS_HEADER_SIZE, SEEK_SET) != DSS_HEADER_SIZE) + return AVERROR(EIO); + + ctx->counter = 0; + ctx->swap = 0; + + ctx->dss_sp_buf = av_malloc(DSS_FRAME_SIZE + 1); + if (!ctx->dss_sp_buf) + return AVERROR(ENOMEM); + + return 0; +} + +static void dss_skip_audio_header(AVFormatContext *s, AVPacket *pkt) +{ + DSSDemuxContext *ctx = s->priv_data; + AVIOContext *pb = s->pb; + + avio_skip(pb, DSS_AUDIO_BLOCK_HEADER_SIZE); + ctx->counter += DSS_BLOCK_SIZE - DSS_AUDIO_BLOCK_HEADER_SIZE; +} + +static void dss_sp_byte_swap(DSSDemuxContext *ctx, + uint8_t *dst, const uint8_t *src) +{ + int i; + + if (ctx->swap) { + for (i = 3; i < DSS_FRAME_SIZE; i += 2) + dst[i] = src[i]; + + for (i = 0; i < DSS_FRAME_SIZE - 2; i += 2) + dst[i] = src[i + 4]; + + dst[1] = ctx->dss_sp_swap_byte; + } else { + memcpy(dst, src, DSS_FRAME_SIZE); + ctx->dss_sp_swap_byte = src[DSS_FRAME_SIZE - 2]; + } + + /* make sure byte 40 is always 0 */ + dst[DSS_FRAME_SIZE - 2] = 0; + ctx->swap ^= 1; +} + +static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DSSDemuxContext *ctx = s->priv_data; + int read_size, ret, offset = 0, buff_offset = 0; + + if (ctx->counter == 0) + dss_skip_audio_header(s, pkt); + + pkt->pos = avio_tell(s->pb); + + if (ctx->swap) { + read_size = DSS_FRAME_SIZE - 2; + buff_offset = 3; + } else + read_size = DSS_FRAME_SIZE; + + ctx->counter -= read_size; + + ret = av_new_packet(pkt, DSS_FRAME_SIZE); + if (ret < 0) + return ret; + + pkt->duration = 0; + pkt->stream_index = 0; + + if (ctx->counter < 0) { + int size2 = ctx->counter + read_size; + + ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset, + size2 - offset); + if (ret < size2 - offset) + goto error_eof; + + dss_skip_audio_header(s, pkt); + offset = size2; + } + + ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset, + read_size - offset); + if (ret < read_size - offset) + goto error_eof; + + dss_sp_byte_swap(ctx, pkt->data, ctx->dss_sp_buf); + + if (pkt->data[0] == 0xff) + return AVERROR_INVALIDDATA; + + return pkt->size; + +error_eof: + av_packet_unref(pkt); + return ret < 0 ? ret : AVERROR_EOF; +} + +static int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DSSDemuxContext *ctx = s->priv_data; + int size, byte, ret, offset; + + if (ctx->counter == 0) + dss_skip_audio_header(s, pkt); + + pkt->pos = avio_tell(s->pb); + /* We make one byte-step here. Don't forget to add offset. */ + byte = avio_r8(s->pb); + if (byte == 0xff) + return AVERROR_INVALIDDATA; + + size = frame_size[byte & 3]; + + ctx->counter -= size; + + ret = av_new_packet(pkt, size); + if (ret < 0) + return ret; + + pkt->data[0] = byte; + offset = 1; + pkt->duration = 240; + + pkt->stream_index = 0; + + if (ctx->counter < 0) { + int size2 = ctx->counter + size; + + ret = avio_read(s->pb, pkt->data + offset, + size2 - offset); + if (ret < size2 - offset) { + av_packet_unref(pkt); + return ret < 0 ? ret : AVERROR_EOF; + } + + dss_skip_audio_header(s, pkt); + offset = size2; + } + + ret = avio_read(s->pb, pkt->data + offset, size - offset); + if (ret < size - offset) { + av_packet_unref(pkt); + return ret < 0 ? ret : AVERROR_EOF; + } + + return pkt->size; +} + +static int dss_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DSSDemuxContext *ctx = s->priv_data; + + if (ctx->audio_codec == DSS_ACODEC_DSS_SP) + return dss_sp_read_packet(s, pkt); + else + return dss_723_1_read_packet(s, pkt); +} + +static int dss_read_close(AVFormatContext *s) +{ + DSSDemuxContext *ctx = s->priv_data; + + av_free(ctx->dss_sp_buf); + + return 0; +} + +AVInputFormat ff_dss_demuxer = { + .name = "dss", + .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard (DSS)"), + .priv_data_size = sizeof(DSSDemuxContext), + .read_probe = dss_probe, + .read_header = dss_read_header, + .read_packet = dss_read_packet, + .read_close = dss_read_close, + .extensions = "dss" +}; diff --git a/libavformat/dtsdec.c b/libavformat/dtsdec.c index 9010711..90e9d38 100644 --- a/libavformat/dtsdec.c +++ b/libavformat/dtsdec.c @@ -20,14 +20,11 @@ */ #include "libavcodec/bytestream.h" +#include "libavcodec/dca_syncwords.h" + #include "avformat.h" #include "rawdec.h" -#define DCA_MARKER_14B_BE 0x1FFFE800 -#define DCA_MARKER_14B_LE 0xFF1F00E8 -#define DCA_MARKER_RAW_BE 0x7FFE8001 -#define DCA_MARKER_RAW_LE 0xFE7F0180 - static int dts_probe(AVProbeData *p) { const uint8_t *buf, *bufp; @@ -42,16 +39,16 @@ static int dts_probe(AVProbeData *p) state = (state << 16) | bytestream_get_be16(&bufp); /* regular bitstream */ - if (state == DCA_MARKER_RAW_BE || state == DCA_MARKER_RAW_LE) + if (state == DCA_SYNCWORD_CORE_BE || state == DCA_SYNCWORD_CORE_LE) markers[0]++; /* 14 bits big-endian bitstream */ - if (state == DCA_MARKER_14B_BE) + if (state == DCA_SYNCWORD_CORE_14B_BE) if ((bytestream_get_be16(&bufp) & 0xFFF0) == 0x07F0) markers[1]++; /* 14 bits little-endian bitstream */ - if (state == DCA_MARKER_14B_LE) + if (state == DCA_SYNCWORD_CORE_14B_LE) if ((bytestream_get_be16(&bufp) & 0xF0FF) == 0xF007) markers[2]++; } diff --git a/libavformat/dump.c b/libavformat/dump.c index 58ed654..3b50f5d 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -116,11 +116,11 @@ static void print_fps(double d, const char *postfix) { uint64_t v = lrintf(d * 100); if (v % 100) - av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix); + av_log(NULL, AV_LOG_INFO, "%3.2f %s", d, postfix); else if (v % (100 * 1000)) - av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix); + av_log(NULL, AV_LOG_INFO, "%1.0f %s", d, postfix); else - av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d / 1000, postfix); + av_log(NULL, AV_LOG_INFO, "%1.0fk %s", d / 1000, postfix); } static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) @@ -241,38 +241,69 @@ static void dump_stereo3d(void *ctx, AVPacketSideData *sd) stereo = (AVStereo3D *)sd->data; - switch (stereo->type) { - case AV_STEREO3D_2D: - av_log(ctx, AV_LOG_INFO, "2D"); + av_log(ctx, AV_LOG_INFO, "%s", av_stereo3d_type_name(stereo->type)); + + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + av_log(ctx, AV_LOG_INFO, " (inverted)"); +} + +static void dump_audioservicetype(void *ctx, AVPacketSideData *sd) +{ + enum AVAudioServiceType *ast = (enum AVAudioServiceType *)sd->data; + + if (sd->size < sizeof(*ast)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + switch (*ast) { + case AV_AUDIO_SERVICE_TYPE_MAIN: + av_log(ctx, AV_LOG_INFO, "main"); + break; + case AV_AUDIO_SERVICE_TYPE_EFFECTS: + av_log(ctx, AV_LOG_INFO, "effects"); break; - case AV_STEREO3D_SIDEBYSIDE: - av_log(ctx, AV_LOG_INFO, "side by side"); + case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: + av_log(ctx, AV_LOG_INFO, "visually impaired"); break; - case AV_STEREO3D_TOPBOTTOM: - av_log(ctx, AV_LOG_INFO, "top and bottom"); + case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: + av_log(ctx, AV_LOG_INFO, "hearing impaired"); break; - case AV_STEREO3D_FRAMESEQUENCE: - av_log(ctx, AV_LOG_INFO, "frame alternate"); + case AV_AUDIO_SERVICE_TYPE_DIALOGUE: + av_log(ctx, AV_LOG_INFO, "dialogue"); break; - case AV_STEREO3D_CHECKERBOARD: - av_log(ctx, AV_LOG_INFO, "checkerboard"); + case AV_AUDIO_SERVICE_TYPE_COMMENTARY: + av_log(ctx, AV_LOG_INFO, "comentary"); break; - case AV_STEREO3D_LINES: - av_log(ctx, AV_LOG_INFO, "interleaved lines"); + case AV_AUDIO_SERVICE_TYPE_EMERGENCY: + av_log(ctx, AV_LOG_INFO, "emergency"); break; - case AV_STEREO3D_COLUMNS: - av_log(ctx, AV_LOG_INFO, "interleaved columns"); + case AV_AUDIO_SERVICE_TYPE_VOICE_OVER: + av_log(ctx, AV_LOG_INFO, "voice over"); break; - case AV_STEREO3D_SIDEBYSIDE_QUINCUNX: - av_log(ctx, AV_LOG_INFO, "side by side (quincunx subsampling)"); + case AV_AUDIO_SERVICE_TYPE_KARAOKE: + av_log(ctx, AV_LOG_INFO, "karaoke"); break; default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; } +} - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - av_log(ctx, AV_LOG_INFO, " (inverted)"); +static void dump_cpb(void *ctx, AVPacketSideData *sd) +{ + AVCPBProperties *cpb = (AVCPBProperties *)sd->data; + + if (sd->size < sizeof(*cpb)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + av_log(ctx, AV_LOG_INFO, + "bitrate max/min/avg: %d/%d/%d buffer size: %d vbv_delay: %"PRId64, + cpb->max_bitrate, cpb->min_bitrate, cpb->avg_bitrate, + cpb->buffer_size, + cpb->vbv_delay); } static void dump_sidedata(void *ctx, AVStream *st, const char *indent) @@ -298,7 +329,7 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) dump_paramchange(ctx, &sd); break; case AV_PKT_DATA_H263_MB_INFO: - av_log(ctx, AV_LOG_INFO, "h263 macroblock info"); + av_log(ctx, AV_LOG_INFO, "H.263 macroblock info"); break; case AV_PKT_DATA_REPLAYGAIN: av_log(ctx, AV_LOG_INFO, "replaygain: "); @@ -312,6 +343,17 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) av_log(ctx, AV_LOG_INFO, "stereo3d: "); dump_stereo3d(ctx, &sd); break; + case AV_PKT_DATA_AUDIO_SERVICE_TYPE: + av_log(ctx, AV_LOG_INFO, "audio service type: "); + dump_audioservicetype(ctx, &sd); + break; + case AV_PKT_DATA_QUALITY_FACTOR: + av_log(ctx, AV_LOG_INFO, "quality factor: %d", *(int *)sd.data); + break; + case AV_PKT_DATA_CPB_PROPERTIES: + av_log(ctx, AV_LOG_INFO, "cpb: "); + dump_cpb(ctx, &sd); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd.type, sd.size); @@ -330,9 +372,23 @@ static void dump_stream_format(AVFormatContext *ic, int i, int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); AVStream *st = ic->streams[i]; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); + AVCodecContext *avctx; + int ret; - avcodec_string(buf, sizeof(buf), st->codec, is_output); - av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); + avctx = avcodec_alloc_context3(NULL); + if (!avctx) + return; + + ret = avcodec_parameters_to_context(avctx, st->codecpar); + if (ret < 0) { + avcodec_free_context(&avctx); + return; + } + + avcodec_string(buf, sizeof(buf), avctx, is_output); + avcodec_free_context(&avctx); + + 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 */ @@ -344,25 +400,27 @@ static void dump_stream_format(AVFormatContext *ic, int i, st->time_base.num, st->time_base.den); av_log(NULL, AV_LOG_INFO, ": %s", buf); - if (st->sample_aspect_ratio.num && // default - av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) { + if (st->sample_aspect_ratio.num) { AVRational display_aspect_ratio; av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, - st->codec->width * st->sample_aspect_ratio.num, - st->codec->height * st->sample_aspect_ratio.den, + st->codecpar->width * st->sample_aspect_ratio.num, + st->codecpar->height * st->sample_aspect_ratio.den, 1024 * 1024); av_log(NULL, AV_LOG_INFO, ", PAR %d:%d DAR %d:%d", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, display_aspect_ratio.num, display_aspect_ratio.den); } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (st->avg_frame_rate.den && st->avg_frame_rate.num) - print_fps(av_q2d(st->avg_frame_rate), "fps"); - if (st->time_base.den && st->time_base.num) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + int fps = st->avg_frame_rate.den && st->avg_frame_rate.num; + int tbn = st->time_base.den && st->time_base.num; + + if (fps || tbn) + av_log(NULL, AV_LOG_INFO, "\n "); + if (fps) + print_fps(av_q2d(st->avg_frame_rate), tbn ? "fps, " : "fps"); + if (tbn) print_fps(1 / av_q2d(st->time_base), "tbn"); - if (st->codec->time_base.den && st->codec->time_base.num) - print_fps(1 / av_q2d(st->codec->time_base), "tbc"); } if (st->disposition & AV_DISPOSITION_DEFAULT) @@ -426,7 +484,7 @@ void av_dump_format(AVFormatContext *ic, int index, int secs, us; av_log(NULL, AV_LOG_INFO, ", start: "); secs = ic->start_time / AV_TIME_BASE; - us = abs(ic->start_time % AV_TIME_BASE); + us = llabs(ic->start_time % AV_TIME_BASE); av_log(NULL, AV_LOG_INFO, "%d.%06d", secs, (int) av_rescale(us, 1000000, AV_TIME_BASE)); } @@ -440,7 +498,7 @@ void av_dump_format(AVFormatContext *ic, int index, for (i = 0; i < ic->nb_chapters; i++) { AVChapter *ch = ic->chapters[i]; - av_log(NULL, AV_LOG_INFO, " Chapter #%d.%d: ", index, i); + av_log(NULL, AV_LOG_INFO, " Chapter #%d:%d: ", index, i); av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base)); av_log(NULL, AV_LOG_INFO, diff --git a/libavformat/dv.c b/libavformat/dv.c index da201a3..d4e5180 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -102,11 +102,11 @@ static const int dv_audio_frequency[3] = { /* * There's a couple of assumptions being made here: - * 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples. + * 1. By default we silence erroneous (0x8000/16-bit 0x800/12-bit) audio samples. * We can pass them upwards when libavcodec 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. + * 3. Audio is always returned as 16-bit linear samples: 12-bit nonlinear samples + * are converted into 16-bit linear ones. */ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, const AVDVProfile *sys) @@ -122,7 +122,7 @@ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ freq = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ - quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ + quant = as_pack[4] & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */ if (quant > 1) return -1; /* unsupported quantization */ @@ -148,7 +148,7 @@ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, 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) */ + /* next stereo channel (12-bit mode only) */ pcm = ppcm[ipcm++]; if (!pcm) break; @@ -157,7 +157,7 @@ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, /* for each AV sequence */ for (j = 0; j < 9; j++) { for (d = 8; d < 80; d += 2) { - if (quant == 0) { /* 16bit quantization */ + if (quant == 0) { /* 16-bit quantization */ of = sys->audio_shuffle[i][j] + (d - 8) / 2 * sys->audio_stride; if (of * 2 >= size) @@ -170,7 +170,7 @@ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, if (pcm[of * 2 + 1] == 0x80 && pcm[of * 2] == 0x00) pcm[of * 2 + 1] = 0; - } else { /* 12bit quantization */ + } else { /* 12-bit quantization */ lc = ((uint16_t)frame[d] << 4) | ((uint16_t)frame[d + 2] >> 4); rc = ((uint16_t)frame[d + 1] << 4) | @@ -219,7 +219,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame) smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ freq = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ stype = as_pack[3] & 0x1f; /* 0 - 2CH, 2 - 4CH, 3 - 8CH */ - quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ + quant = as_pack[4] & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */ if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) { av_log(c->fctx, AV_LOG_ERROR, @@ -245,8 +245,8 @@ static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame) if (!c->ast[i]) break; avpriv_set_pts_info(c->ast[i], 64, 1, 30000); - c->ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO; - c->ast[i]->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + c->ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; av_init_packet(&c->audio_pkt[i]); c->audio_pkt[i].size = 0; @@ -254,10 +254,10 @@ static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame) c->audio_pkt[i].stream_index = c->ast[i]->index; c->audio_pkt[i].flags |= AV_PKT_FLAG_KEY; } - c->ast[i]->codec->sample_rate = dv_audio_frequency[freq]; - c->ast[i]->codec->channels = 2; - c->ast[i]->codec->channel_layout = AV_CH_LAYOUT_STEREO; - c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16; + c->ast[i]->codecpar->sample_rate = dv_audio_frequency[freq]; + c->ast[i]->codecpar->channels = 2; + c->ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + c->ast[i]->codecpar->bit_rate = 2 * dv_audio_frequency[freq] * 16; c->ast[i]->start_time = 0; } c->ach = i; @@ -268,21 +268,20 @@ static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame) 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; + AVCodecParameters *par = c->vst->codecpar; avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num, c->sys->time_base.den); c->vst->avg_frame_rate = av_inv_q(c->vst->time_base); - if (!avctx->width) { - avctx->width = c->sys->width; - avctx->height = c->sys->height; + if (!par->width) { + par->width = c->sys->width; + par->height = c->sys->height; } - avctx->pix_fmt = c->sys->pix_fmt; + par->format = c->sys->pix_fmt; /* finding out SAR is a little bit messy */ vsc_pack = dv_extract_pack(frame, dv_video_control); @@ -290,9 +289,9 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t *frame) is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07))); c->vst->sample_aspect_ratio = c->sys->sar[is16_9]; - avctx->bit_rate = av_rescale_q(c->sys->frame_size, - (AVRational) { 8, 1 }, - c->sys->time_base); + par->bit_rate = av_rescale_q(c->sys->frame_size, + (AVRational) { 8, 1 }, + c->sys->time_base); size = c->sys->frame_size; } return size; @@ -315,9 +314,9 @@ DVDemuxContext *avpriv_dv_init_demux(AVFormatContext *s) } c->fctx = s; - c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - c->vst->codec->codec_id = AV_CODEC_ID_DVVIDEO; - c->vst->codec->bit_rate = 25000000; + c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + c->vst->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; + c->vst->codecpar->bit_rate = 25000000; c->vst->start_time = 0; return c; @@ -358,7 +357,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, 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; + c->ast[i]->codecpar->bit_rate; ppcm[i] = c->audio_buf[i]; } if (c->ach) @@ -395,10 +394,10 @@ 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 AVDVProfile *sys = av_dv_codec_profile(c->vst->codec->width, c->vst->codec->height, - c->vst->codec->pix_fmt); + const AVDVProfile *sys = av_dv_codec_profile(c->vst->codecpar->width, c->vst->codecpar->height, + c->vst->codecpar->format); int64_t offset; - int64_t size = avio_size(s->pb) - s->data_offset; + int64_t size = avio_size(s->pb) - s->internal->data_offset; int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size; offset = sys->frame_size * timestamp; @@ -408,7 +407,7 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, else if (offset < 0) offset = 0; - return offset + s->data_offset; + return offset + s->internal->data_offset; } void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) @@ -416,7 +415,7 @@ void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) c->frames = frame_offset; if (c->ach) c->abytes = av_rescale_q(c->frames, c->sys->time_base, - (AVRational) { 8, c->ast[0]->codec->bit_rate }); + (AVRational) { 8, c->ast[0]->codecpar->bit_rate }); c->audio_pkt[0].size = c->audio_pkt[1].size = 0; c->audio_pkt[2].size = c->audio_pkt[3].size = 0; diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index a33973f..cf79534 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -38,7 +38,7 @@ #include "libavutil/fifo.h" #include "libavutil/mathematics.h" -#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio +#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32-bit audio struct DVMuxContext { const AVDVProfile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ @@ -124,7 +124,7 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu 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 */ + 0; /* quantization: 0 -- 16-bit linear, 1 -- 12-bit nonlinear */ va_end(ap); break; case dv_audio_control: @@ -236,7 +236,8 @@ static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame) * The following 3 functions constitute our interface to the world */ -static int dv_assemble_frame(DVMuxContext *c, AVStream* st, +static int dv_assemble_frame(AVFormatContext *s, + DVMuxContext *c, AVStream* st, uint8_t* data, int data_size, uint8_t** frame) { int i, reqasize; @@ -244,11 +245,16 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st, *frame = &c->frame_buf[0]; reqasize = 4 * dv_audio_frame_size(c->sys, c->frames); - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_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); + av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); + if (data_size != c->sys->frame_size) { + av_log(s, AV_LOG_ERROR, "Unexpected frame size, %d != %d\n", + data_size, c->sys->frame_size); + return AVERROR(ENOSYS); + } memcpy(*frame, data, c->sys->frame_size); c->has_video = 1; @@ -258,7 +264,7 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st, /* FIXME: we have to have more sensible approach than this one */ if (av_fifo_size(c->audio_data[i]) + data_size >= 100*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_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); av_fifo_generic_write(c->audio_data[i], data, data_size, NULL); /* Let us see if we've got enough audio for one DV frame. */ @@ -305,7 +311,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) /* We have to sort out where audio and where video stream is */ for (i=0; inb_streams; i++) { - switch (s->streams[i]->codec->codec_type) { + switch (s->streams[i]->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: if (vst) return NULL; vst = s->streams[i]; @@ -320,15 +326,15 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) } /* Some checks -- DV format is very picky about its incoming streams */ - if (!vst || vst->codec->codec_id != AV_CODEC_ID_DVVIDEO) + if (!vst || vst->codecpar->codec_id != AV_CODEC_ID_DVVIDEO) goto bail_out; for (i=0; in_ast; i++) { - if (c->ast[i] && (c->ast[i]->codec->codec_id != AV_CODEC_ID_PCM_S16LE || - c->ast[i]->codec->sample_rate != 48000 || - c->ast[i]->codec->channels != 2)) + if (c->ast[i] && (c->ast[i]->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE || + c->ast[i]->codecpar->sample_rate != 48000 || + c->ast[i]->codecpar->channels != 2)) goto bail_out; } - c->sys = av_dv_codec_profile(vst->codec->width, vst->codec->height, vst->codec->pix_fmt); + c->sys = av_dv_codec_profile(vst->codecpar->width, vst->codecpar->height, vst->codecpar->format); if (!c->sys) goto bail_out; @@ -384,7 +390,7 @@ static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt) uint8_t* frame; int fsize; - fsize = dv_assemble_frame(s->priv_data, s->streams[pkt->stream_index], + fsize = dv_assemble_frame(s, s->priv_data, s->streams[pkt->stream_index], pkt->data, pkt->size, &frame); if (fsize > 0) { avio_write(s->pb, frame, fsize); diff --git a/libavformat/dxa.c b/libavformat/dxa.c index 78e7290..a86b90e 100644 --- a/libavformat/dxa.c +++ b/libavformat/dxa.c @@ -28,7 +28,7 @@ #define DXA_EXTRA_SIZE 9 -typedef struct{ +typedef struct DXAContext { int frames; int has_sound; int bpc; @@ -106,11 +106,11 @@ static int dxa_read_header(AVFormatContext *s) ast = avformat_new_stream(s, NULL); if (!ast) return -1; - ret = ff_get_wav_header(pb, ast->codec, fsize); + ret = ff_get_wav_header(s, pb, ast->codecpar, fsize); if (ret < 0) return ret; - if (ast->codec->sample_rate > 0) - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + if (ast->codecpar->sample_rate > 0) + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); // find 'data' chunk while(avio_tell(pb) < c->vidpos && !pb->eof_reached){ tag = avio_rl32(pb); @@ -119,18 +119,18 @@ static int dxa_read_header(AVFormatContext *s) avio_skip(pb, fsize); } c->bpc = (fsize + c->frames - 1) / c->frames; - if(ast->codec->block_align) - c->bpc = ((c->bpc + ast->codec->block_align - 1) / ast->codec->block_align) * ast->codec->block_align; + if(ast->codecpar->block_align) + c->bpc = ((c->bpc + ast->codecpar->block_align - 1) / ast->codecpar->block_align) * ast->codecpar->block_align; c->bytes_left = fsize; c->wavpos = avio_tell(pb); avio_seek(pb, c->vidpos, SEEK_SET); } /* now we are ready: build format streams */ - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DXA; - st->codec->width = w; - st->codec->height = h; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DXA; + st->codecpar->width = w; + st->codecpar->height = h; av_reduce(&den, &num, den, num, (1UL<<31)-1); avpriv_set_pts_info(st, 33, num, den); /* flags & 0x80 means that image is interlaced, @@ -138,7 +138,7 @@ static int dxa_read_header(AVFormatContext *s) * either way set true height */ if(flags & 0xC0){ - st->codec->height >>= 1; + st->codecpar->height >>= 1; } c->readvid = !c->has_sound; c->vidpos = avio_tell(pb); @@ -201,7 +201,7 @@ static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt) memcpy(pkt->data + pal_size, buf, DXA_EXTRA_SIZE); ret = avio_read(s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size); if(ret != size){ - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } if(pal_size) memcpy(pkt->data, pal, pal_size); diff --git a/libavformat/eacdata.c b/libavformat/eacdata.c index b56ba1c..d3f27a4 100644 --- a/libavformat/eacdata.c +++ b/libavformat/eacdata.c @@ -31,7 +31,7 @@ #include "avformat.h" #include "internal.h" -typedef struct { +typedef struct CdataDemuxContext { unsigned int channels; unsigned int audio_pts; } CdataDemuxContext; @@ -68,11 +68,11 @@ static int cdata_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->codec_id = AV_CODEC_ID_ADPCM_EA_XAS; - st->codec->channels = cdata->channels; - st->codec->sample_rate = sample_rate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_EA_XAS; + st->codecpar->channels = cdata->channels; + st->codecpar->sample_rate = sample_rate; avpriv_set_pts_info(st, 64, 1, sample_rate); cdata->audio_pts = 0; diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c index adcd45a..2df27e4 100644 --- a/libavformat/electronicarts.c +++ b/libavformat/electronicarts.c @@ -1,5 +1,5 @@ /* Electronic Arts Multimedia File Demuxer - * Copyright (c) 2004 The ffmpeg Project + * Copyright (c) 2004 The FFmpeg project * Copyright (c) 2006-2008 Peter Ross * * This file is part of Libav. @@ -394,14 +394,18 @@ static int process_ea_header(AVFormatContext *s) case pQGT_TAG: case TGQs_TAG: ea->video_codec = AV_CODEC_ID_TGQ; + ea->time_base = (AVRational) { 1, 15 }; break; case pIQT_TAG: ea->video_codec = AV_CODEC_ID_TQI; + ea->time_base = (AVRational) { 1, 15 }; break; case MADk_TAG: ea->video_codec = AV_CODEC_ID_MAD; + avio_skip(pb, 6); + ea->time_base = (AVRational) { avio_rl16(pb), 1000 }; break; case MVhd_TAG: @@ -458,11 +462,11 @@ static int ea_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); ea->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ea->video_codec; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = ea->width; - st->codec->height = ea->height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = ea->video_codec; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = ea->width; + st->codecpar->height = ea->height; avpriv_set_pts_info(st, 33, ea->time_base.num, ea->time_base.den); st->avg_frame_rate = (AVRational) { ea->time_base.den, ea->time_base.num }; @@ -493,17 +497,17 @@ static int ea_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, ea->sample_rate); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = ea->audio_codec; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = ea->num_channels; - st->codec->sample_rate = ea->sample_rate; - st->codec->bits_per_coded_sample = ea->bytes * 8; - st->codec->bit_rate = st->codec->channels * - st->codec->sample_rate * - st->codec->bits_per_coded_sample / 4; - st->codec->block_align = st->codec->channels * - st->codec->bits_per_coded_sample; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = ea->audio_codec; + st->codecpar->codec_tag = 0; /* no tag */ + st->codecpar->channels = ea->num_channels; + st->codecpar->sample_rate = ea->sample_rate; + st->codecpar->bits_per_coded_sample = ea->bytes * 8; + st->codecpar->bit_rate = st->codecpar->channels * + st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample / 4; + st->codecpar->block_align = st->codecpar->channels * + st->codecpar->bits_per_coded_sample; ea->audio_stream_index = st->index; st->start_time = 0; } @@ -563,7 +567,7 @@ static int ea_read_packet(AVFormatContext *s, AVPacket *pkt) case AV_CODEC_ID_ADPCM_EA_R3: if (pkt->size < 4) { av_log(s, AV_LOG_ERROR, "Packet is too short\n"); - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR_INVALIDDATA; } if (ea->audio_codec == AV_CODEC_ID_ADPCM_EA_R3) diff --git a/libavformat/ffmetadec.c b/libavformat/ffmetadec.c index 7dbf7ed..42fc98f 100644 --- a/libavformat/ffmetadec.c +++ b/libavformat/ffmetadec.c @@ -137,8 +137,8 @@ static int read_header(AVFormatContext *s) if (!st) return -1; - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = AV_CODEC_ID_FFMETADATA; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_FFMETADATA; m = &st->metadata; } else if (!memcmp(line, ID_CHAPTER, strlen(ID_CHAPTER))) { diff --git a/libavformat/file.c b/libavformat/file.c index 2837e9f..27ce4de 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -42,10 +42,12 @@ typedef struct FileContext { const AVClass *class; int fd; int trunc; + int follow; } FileContext; static const AVOption file_options[] = { { "truncate", "Truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, + { "follow", "Follow a file as it is being written", offsetof(FileContext, follow), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { NULL } }; @@ -59,13 +61,17 @@ static const AVClass file_class = { static int file_read(URLContext *h, unsigned char *buf, int size) { FileContext *c = h->priv_data; - return read(c->fd, buf, size); + int ret = read(c->fd, buf, size); + if (ret == 0 && c->follow) + return AVERROR(EAGAIN); + return (ret == -1) ? AVERROR(errno) : ret; } static int file_write(URLContext *h, const unsigned char *buf, int size) { FileContext *c = h->priv_data; - return write(c->fd, buf, size); + int ret = write(c->fd, buf, size); + return (ret == -1) ? AVERROR(errno) : ret; } static int file_get_handle(URLContext *h) @@ -76,8 +82,13 @@ static int file_get_handle(URLContext *h) static int file_check(URLContext *h, int mask) { + const char *filename = h->filename; struct stat st; - int ret = stat(h->filename, &st); + int ret; + + av_strstart(filename, "file:", &filename); + + ret = stat(filename, &st); if (ret < 0) return AVERROR(errno); @@ -142,7 +153,7 @@ static int file_close(URLContext *h) return close(c->fd); } -URLProtocol ff_file_protocol = { +const URLProtocol ff_file_protocol = { .name = "file", .url_open = file_open, .url_read = file_read, @@ -182,7 +193,7 @@ static int pipe_open(URLContext *h, const char *filename, int flags) return 0; } -URLProtocol ff_pipe_protocol = { +const URLProtocol ff_pipe_protocol = { .name = "pipe", .url_open = pipe_open, .url_read = file_read, diff --git a/libavformat/filmstripdec.c b/libavformat/filmstripdec.c index 3fa6842..b029d80 100644 --- a/libavformat/filmstripdec.c +++ b/libavformat/filmstripdec.c @@ -30,7 +30,7 @@ #define RAND_TAG MKBETAG('R','a','n','d') -typedef struct { +typedef struct FilmstripDemuxContext { int leading; } FilmstripDemuxContext; @@ -60,12 +60,12 @@ static int read_header(AVFormatContext *s) } avio_skip(pb, 2); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->pix_fmt = AV_PIX_FMT_RGBA; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = avio_rb16(pb); - st->codec->height = avio_rb16(pb); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->format = AV_PIX_FMT_RGBA; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = avio_rb16(pb); + st->codecpar->height = avio_rb16(pb); film->leading = avio_rb16(pb); avpriv_set_pts_info(st, 64, 1, avio_rb16(pb)); @@ -82,9 +82,9 @@ static int read_packet(AVFormatContext *s, if (s->pb->eof_reached) return AVERROR(EIO); - pkt->dts = avio_tell(s->pb) / (st->codec->width * (st->codec->height + film->leading) * 4); - pkt->size = av_get_packet(s->pb, pkt, st->codec->width * st->codec->height * 4); - avio_skip(s->pb, st->codec->width * film->leading * 4); + pkt->dts = avio_tell(s->pb) / (st->codecpar->width * (st->codecpar->height + film->leading) * 4); + pkt->size = av_get_packet(s->pb, pkt, st->codecpar->width * st->codecpar->height * 4); + avio_skip(s->pb, st->codecpar->width * (int64_t) film->leading * 4); if (pkt->size < 0) return pkt->size; pkt->flags |= AV_PKT_FLAG_KEY; @@ -94,7 +94,7 @@ static int read_packet(AVFormatContext *s, static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { AVStream *st = s->streams[stream_index]; - if (avio_seek(s->pb, FFMAX(timestamp, 0) * st->codec->width * st->codec->height * 4, SEEK_SET) < 0) + if (avio_seek(s->pb, FFMAX(timestamp, 0) * st->codecpar->width * st->codecpar->height * 4, SEEK_SET) < 0) return -1; return 0; } diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c index 8d1d2d8..5a09691 100644 --- a/libavformat/filmstripenc.c +++ b/libavformat/filmstripenc.c @@ -29,13 +29,13 @@ #define RAND_TAG MKBETAG('R','a','n','d') -typedef struct { +typedef struct FilmstripMuxContext { int nb_frames; } FilmstripMuxContext; static int write_header(AVFormatContext *s) { - if (s->streams[0]->codec->pix_fmt != AV_PIX_FMT_RGBA) { + if (s->streams[0]->codecpar->format != AV_PIX_FMT_RGBA) { av_log(s, AV_LOG_ERROR, "only AV_PIX_FMT_RGBA is supported\n"); return AVERROR_INVALIDDATA; } @@ -61,8 +61,8 @@ static int write_trailer(AVFormatContext *s) avio_wb32(pb, film->nb_frames); avio_wb16(pb, 0); // packing method avio_wb16(pb, 0); // reserved - avio_wb16(pb, st->codec->width); - avio_wb16(pb, st->codec->height); + avio_wb16(pb, st->codecpar->width); + avio_wb16(pb, st->codecpar->height); avio_wb16(pb, 0); // leading // TODO: should be avg_frame_rate avio_wb16(pb, 1/av_q2d(st->time_base)); diff --git a/libavformat/flac_picture.c b/libavformat/flac_picture.c index 69d2724..1381a28 100644 --- a/libavformat/flac_picture.c +++ b/libavformat/flac_picture.c @@ -31,8 +31,8 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) uint8_t mimetype[64], *desc = NULL; AVIOContext *pb = NULL; AVStream *st; - int type, width, height; - int len, ret = 0; + int width, height, ret = 0; + unsigned int type, len; pb = avio_alloc_context(buf, buf_size, 0, NULL, NULL, NULL, NULL); if (!pb) @@ -40,7 +40,7 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) /* read the picture type */ type = avio_rb32(pb); - if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { + if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) { av_log(s, AV_LOG_ERROR, "Invalid picture type: %d.\n", type); if (s->error_recognition & AV_EF_EXPLODE) { ret = AVERROR_INVALIDDATA; @@ -51,7 +51,7 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) /* picture mimetype */ len = avio_rb32(pb); - if (len <= 0 || + if (!len || len >= 64 || avio_read(pb, mimetype, FFMIN(len, sizeof(mimetype) - 1)) != len) { av_log(s, AV_LOG_ERROR, "Could not read mimetype from an attached " "picture.\n"); @@ -100,7 +100,7 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) /* picture data */ len = avio_rb32(pb); - if (len <= 0) { + if (!len) { av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); if (s->error_recognition & AV_EF_EXPLODE) ret = AVERROR_INVALIDDATA; @@ -131,10 +131,10 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) st->attached_pic.flags |= AV_PKT_FLAG_KEY; st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = id; - st->codec->width = width; - st->codec->height = height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = id; + st->codecpar->width = width; + st->codecpar->height = height; av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0); if (desc) av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c index e044fd0..2f4ac56 100644 --- a/libavformat/flacdec.c +++ b/libavformat/flacdec.c @@ -27,7 +27,6 @@ #include "oggdec.h" #include "vorbiscomment.h" #include "replaygain.h" -#include "libavcodec/bytestream.h" static int flac_read_header(AVFormatContext *s) { @@ -37,8 +36,8 @@ static int flac_read_header(AVFormatContext *s) AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_FLAC; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_FLAC; st->need_parsing = AVSTREAM_PARSE_FULL; /* the parameters will be extracted from the compressed bitstream */ @@ -59,7 +58,7 @@ static int flac_read_header(AVFormatContext *s) case FLAC_METADATA_TYPE_CUESHEET: case FLAC_METADATA_TYPE_PICTURE: case FLAC_METADATA_TYPE_VORBIS_COMMENT: - buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE); + buffer = av_mallocz(metadata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!buffer) { return AVERROR(ENOMEM); } @@ -76,7 +75,9 @@ static int flac_read_header(AVFormatContext *s) } if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) { - FLACStreaminfo si; + uint32_t samplerate; + uint64_t samples; + /* STREAMINFO can only occur once */ if (found_streaminfo) { av_freep(&buffer); @@ -87,18 +88,20 @@ static int flac_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } found_streaminfo = 1; - st->codec->extradata = buffer; - st->codec->extradata_size = metadata_size; + st->codecpar->extradata = buffer; + st->codecpar->extradata_size = metadata_size; buffer = NULL; - /* get codec params from STREAMINFO header */ - avpriv_flac_parse_streaminfo(st->codec, &si, st->codec->extradata); + /* get sample rate and sample count from STREAMINFO header; + * other parameters will be extracted by the parser */ + samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4; + samples = (AV_RB64(st->codecpar->extradata + 13) >> 24) & ((1ULL << 36) - 1); /* set time base and duration */ - if (si.samplerate > 0) { - avpriv_set_pts_info(st, 64, 1, si.samplerate); - if (si.samples > 0) - st->duration = si.samples; + if (samplerate > 0) { + avpriv_set_pts_info(st, 64, 1, samplerate); + if (samples > 0) + st->duration = samples; } } else if (metadata_type == FLAC_METADATA_TYPE_CUESHEET) { uint8_t isrc[13]; @@ -156,7 +159,7 @@ static int flac_read_header(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); } else { - st->codec->channel_layout = mask; + st->codecpar->channel_layout = mask; av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); } } @@ -174,9 +177,24 @@ static int flac_read_header(AVFormatContext *s) static int flac_probe(AVProbeData *p) { - if (p->buf_size < 4 || memcmp(p->buf, "fLaC", 4)) - return 0; - return AVPROBE_SCORE_EXTENSION; + /* file header + metadata header + checked bytes of streaminfo */ + if (p->buf_size >= 4 + 4 + 13) { + int type = p->buf[4] & 0x7f; + int size = AV_RB24(p->buf + 5); + int min_block_size = AV_RB16(p->buf + 8); + int max_block_size = AV_RB16(p->buf + 10); + int sample_rate = AV_RB24(p->buf + 18) >> 4; + + if (!memcmp(p->buf, "fLaC", 4) && + type == FLAC_METADATA_TYPE_STREAMINFO && + size == FLAC_STREAMINFO_SIZE && + min_block_size >= 16 && + max_block_size >= min_block_size && + sample_rate && sample_rate <= 655350) + return AVPROBE_SCORE_MAX; + } + + return 0; } AVInputFormat ff_flac_demuxer = { diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index a686826..3cee668 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -77,21 +77,21 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m, static int flac_write_header(struct AVFormatContext *s) { int ret; - AVCodecContext *codec = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; FlacMuxerContext *c = s->priv_data; if (!c->write_header) return 0; - ret = ff_flac_write_header(s->pb, codec->extradata, - codec->extradata_size, 0); + ret = ff_flac_write_header(s->pb, par->extradata, + par->extradata_size, 0); if (ret) return ret; /* add the channel layout tag */ - if (codec->channel_layout && - !(codec->channel_layout & ~0x3ffffULL) && - !ff_flac_is_native_layout(codec->channel_layout)) { + if (par->channel_layout && + !(par->channel_layout & ~0x3ffffULL) && + !ff_flac_is_native_layout(par->channel_layout)) { AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); @@ -100,7 +100,7 @@ static int flac_write_header(struct AVFormatContext *s) "already present, this muxer will not overwrite it.\n"); } else { uint8_t buf[32]; - snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout); + snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout); av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); } } @@ -125,7 +125,7 @@ static int flac_write_trailer(struct AVFormatContext *s) int64_t file_size; FlacMuxerContext *c = s->priv_data; uint8_t *streaminfo = c->streaminfo ? c->streaminfo : - s->streams[0]->codec->extradata; + s->streams[0]->codecpar->extradata; if (!c->write_header || !streaminfo) return 0; diff --git a/libavformat/flic.c b/libavformat/flic.c index 2eb6f05..85e4790 100644 --- a/libavformat/flic.c +++ b/libavformat/flic.c @@ -1,6 +1,6 @@ /* * FLI/FLC Animation File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -109,25 +109,25 @@ static int flic_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); flic->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_FLIC; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = AV_RL16(&header[0x08]); - st->codec->height = AV_RL16(&header[0x0A]); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_FLIC; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = AV_RL16(&header[0x08]); + st->codecpar->height = AV_RL16(&header[0x0A]); - if (!st->codec->width || !st->codec->height) { + if (!st->codecpar->width || !st->codecpar->height) { /* Ugly hack needed for the following sample: */ /* http://samples.libav.org/fli-flc/fli-bugs/specular.flc */ av_log(s, AV_LOG_WARNING, "File with no specified width/height. Trying 640x480.\n"); - st->codec->width = 640; - st->codec->height = 480; + st->codecpar->width = 640; + st->codecpar->height = 480; } /* 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); + st->codecpar->extradata_size = FLIC_HEADER_SIZE; + st->codecpar->extradata = av_malloc(FLIC_HEADER_SIZE); + memcpy(st->codecpar->extradata, header, FLIC_HEADER_SIZE); /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */ if (avio_read(pb, preamble, FLIC_PREAMBLE_SIZE) != FLIC_PREAMBLE_SIZE) { @@ -152,22 +152,22 @@ static int flic_read_header(AVFormatContext *s) flic->audio_stream_index = ast->index; /* all audio frames are the same size, so use the size of the first chunk for block_align */ - ast->codec->block_align = AV_RL32(&preamble[0]); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; - ast->codec->codec_tag = 0; - ast->codec->sample_rate = FLIC_TFTD_SAMPLE_RATE; - ast->codec->channels = 1; - ast->codec->sample_fmt = AV_SAMPLE_FMT_U8; - ast->codec->bit_rate = st->codec->sample_rate * 8; - ast->codec->bits_per_coded_sample = 8; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; - ast->codec->extradata_size = 0; + ast->codecpar->block_align = AV_RL32(&preamble[0]); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->codec_tag = 0; + ast->codecpar->sample_rate = FLIC_TFTD_SAMPLE_RATE; + ast->codecpar->channels = 1; + ast->codecpar->format = AV_SAMPLE_FMT_U8; + ast->codecpar->bit_rate = st->codecpar->sample_rate * 8; + ast->codecpar->bits_per_coded_sample = 8; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->extradata_size = 0; /* Since the header information is incorrect we have to figure out the * framerate using block_align and the fact that the audio is 22050 Hz. * We usually have two cases: 2205 -> 10 fps and 1470 -> 15 fps */ - avpriv_set_pts_info(st, 64, ast->codec->block_align, FLIC_TFTD_SAMPLE_RATE); + avpriv_set_pts_info(st, 64, ast->codecpar->block_align, FLIC_TFTD_SAMPLE_RATE); avpriv_set_pts_info(ast, 64, 1, FLIC_TFTD_SAMPLE_RATE); } else if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) { avpriv_set_pts_info(st, 64, FLIC_MC_SPEED, 70); @@ -176,10 +176,10 @@ static int flic_read_header(AVFormatContext *s) avio_seek(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); + av_free(st->codecpar->extradata); + st->codecpar->extradata_size = 12; + st->codecpar->extradata = av_malloc(12); + memcpy(st->codecpar->extradata, header, 12); } else if (magic_number == FLIC_FILE_MAGIC_1) { avpriv_set_pts_info(st, 64, speed, 70); @@ -228,7 +228,7 @@ static int flic_read_packet(AVFormatContext *s, ret = avio_read(pb, pkt->data + FLIC_PREAMBLE_SIZE, size - FLIC_PREAMBLE_SIZE); if (ret != size - FLIC_PREAMBLE_SIZE) { - av_free_packet(pkt); + av_packet_unref(pkt); ret = AVERROR(EIO); } packet_read = 1; @@ -246,7 +246,7 @@ static int flic_read_packet(AVFormatContext *s, ret = avio_read(pb, pkt->data, size); if (ret != size) { - av_free_packet(pkt); + av_packet_unref(pkt); ret = AVERROR(EIO); } diff --git a/libavformat/flv.h b/libavformat/flv.h index fe0fc90..7c08117 100644 --- a/libavformat/flv.h +++ b/libavformat/flv.h @@ -51,7 +51,7 @@ enum { FLV_HEADER_FLAG_HASAUDIO = 4, }; -enum { +enum FlvTagType { FLV_TAG_TYPE_AUDIO = 0x08, FLV_TAG_TYPE_VIDEO = 0x09, FLV_TAG_TYPE_META = 0x12, diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 56c932c..c26f180 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -4,8 +4,8 @@ * * 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 + * - upper 4 bits: difference between encoded width and visible width + * - lower 4 bits: difference between encoded height and visible height * * This file is part of Libav. * @@ -43,7 +43,7 @@ #define VALIDATE_INDEX_TS_THRESH 2500 -typedef struct { +typedef struct FLVContext { const AVClass *class; ///< Class for private options. int trust_metadata; ///< configure streams according onMetaData int wrong_dts; ///< wrong dts due to negative cts @@ -57,6 +57,7 @@ typedef struct { } validate_index[2]; int validate_next; int validate_count; + int searched_for_end; } FLVContext; static int flv_probe(AVProbeData *p) @@ -79,21 +80,21 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type) AVStream *st = avformat_new_stream(s, NULL); if (!st) return NULL; - st->codec->codec_type = codec_type; + st->codecpar->codec_type = codec_type; avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ return st; } -static int flv_same_audio_codec(AVCodecContext *acodec, int flags) +static int flv_same_audio_codec(AVCodecParameters *apar, int flags) { int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; int flv_codecid = flags & FLV_AUDIO_CODECID_MASK; int codec_id; - if (!acodec->codec_id && !acodec->codec_tag) + if (!apar->codec_id && !apar->codec_tag) return 1; - if (acodec->bits_per_coded_sample != bits_per_coded_sample) + if (apar->bits_per_coded_sample != bits_per_coded_sample) return 0; switch (flv_codecid) { @@ -106,42 +107,42 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags) #else : AV_CODEC_ID_PCM_S16LE; #endif - return codec_id == acodec->codec_id; + return codec_id == apar->codec_id; case FLV_CODECID_PCM_LE: codec_id = bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE; - return codec_id == acodec->codec_id; + return codec_id == apar->codec_id; case FLV_CODECID_AAC: - return acodec->codec_id == AV_CODEC_ID_AAC; + return apar->codec_id == AV_CODEC_ID_AAC; case FLV_CODECID_ADPCM: - return acodec->codec_id == AV_CODEC_ID_ADPCM_SWF; + return apar->codec_id == AV_CODEC_ID_ADPCM_SWF; case FLV_CODECID_SPEEX: - return acodec->codec_id == AV_CODEC_ID_SPEEX; + return apar->codec_id == AV_CODEC_ID_SPEEX; case FLV_CODECID_MP3: - return acodec->codec_id == AV_CODEC_ID_MP3; + return apar->codec_id == AV_CODEC_ID_MP3; case FLV_CODECID_NELLYMOSER_8KHZ_MONO: case FLV_CODECID_NELLYMOSER_16KHZ_MONO: case FLV_CODECID_NELLYMOSER: - return acodec->codec_id == AV_CODEC_ID_NELLYMOSER; + return apar->codec_id == AV_CODEC_ID_NELLYMOSER; case FLV_CODECID_PCM_MULAW: - return acodec->sample_rate == 8000 && - acodec->codec_id == AV_CODEC_ID_PCM_MULAW; + return apar->sample_rate == 8000 && + apar->codec_id == AV_CODEC_ID_PCM_MULAW; case FLV_CODECID_PCM_ALAW: - return acodec->sample_rate == 8000 && - acodec->codec_id == AV_CODEC_ID_PCM_ALAW; + return apar->sample_rate == 8000 && + apar->codec_id == AV_CODEC_ID_PCM_ALAW; default: - return acodec->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET); + return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET); } } static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, - AVCodecContext *acodec, int flv_codecid) + AVCodecParameters *apar, int flv_codecid) { switch (flv_codecid) { // no distinction between S16 and S8 PCM codec flags case FLV_CODECID_PCM: - acodec->codec_id = acodec->bits_per_coded_sample == 8 + apar->codec_id = apar->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 #if HAVE_BIGENDIAN : AV_CODEC_ID_PCM_S16BE; @@ -150,113 +151,113 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, #endif break; case FLV_CODECID_PCM_LE: - acodec->codec_id = acodec->bits_per_coded_sample == 8 + apar->codec_id = apar->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE; break; case FLV_CODECID_AAC: - acodec->codec_id = AV_CODEC_ID_AAC; + apar->codec_id = AV_CODEC_ID_AAC; break; case FLV_CODECID_ADPCM: - acodec->codec_id = AV_CODEC_ID_ADPCM_SWF; + apar->codec_id = AV_CODEC_ID_ADPCM_SWF; break; case FLV_CODECID_SPEEX: - acodec->codec_id = AV_CODEC_ID_SPEEX; - acodec->sample_rate = 16000; + apar->codec_id = AV_CODEC_ID_SPEEX; + apar->sample_rate = 16000; break; case FLV_CODECID_MP3: - acodec->codec_id = AV_CODEC_ID_MP3; + apar->codec_id = AV_CODEC_ID_MP3; astream->need_parsing = AVSTREAM_PARSE_FULL; break; case FLV_CODECID_NELLYMOSER_8KHZ_MONO: // in case metadata does not otherwise declare samplerate - acodec->sample_rate = 8000; - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + apar->sample_rate = 8000; + apar->codec_id = AV_CODEC_ID_NELLYMOSER; break; case FLV_CODECID_NELLYMOSER_16KHZ_MONO: - acodec->sample_rate = 16000; - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + apar->sample_rate = 16000; + apar->codec_id = AV_CODEC_ID_NELLYMOSER; break; case FLV_CODECID_NELLYMOSER: - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + apar->codec_id = AV_CODEC_ID_NELLYMOSER; break; case FLV_CODECID_PCM_MULAW: - acodec->sample_rate = 8000; - acodec->codec_id = AV_CODEC_ID_PCM_MULAW; + apar->sample_rate = 8000; + apar->codec_id = AV_CODEC_ID_PCM_MULAW; break; case FLV_CODECID_PCM_ALAW: - acodec->sample_rate = 8000; - acodec->codec_id = AV_CODEC_ID_PCM_ALAW; + apar->sample_rate = 8000; + apar->codec_id = AV_CODEC_ID_PCM_ALAW; break; default: av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET); - acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; + apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; } } -static int flv_same_video_codec(AVCodecContext *vcodec, int flags) +static int flv_same_video_codec(AVCodecParameters *vpar, int flags) { int flv_codecid = flags & FLV_VIDEO_CODECID_MASK; - if (!vcodec->codec_id && !vcodec->codec_tag) + if (!vpar->codec_id && !vpar->codec_tag) return 1; switch (flv_codecid) { case FLV_CODECID_H263: - return vcodec->codec_id == AV_CODEC_ID_FLV1; + return vpar->codec_id == AV_CODEC_ID_FLV1; case FLV_CODECID_SCREEN: - return vcodec->codec_id == AV_CODEC_ID_FLASHSV; + return vpar->codec_id == AV_CODEC_ID_FLASHSV; case FLV_CODECID_SCREEN2: - return vcodec->codec_id == AV_CODEC_ID_FLASHSV2; + return vpar->codec_id == AV_CODEC_ID_FLASHSV2; case FLV_CODECID_VP6: - return vcodec->codec_id == AV_CODEC_ID_VP6F; + return vpar->codec_id == AV_CODEC_ID_VP6F; case FLV_CODECID_VP6A: - return vcodec->codec_id == AV_CODEC_ID_VP6A; + return vpar->codec_id == AV_CODEC_ID_VP6A; case FLV_CODECID_H264: - return vcodec->codec_id == AV_CODEC_ID_H264; + return vpar->codec_id == AV_CODEC_ID_H264; default: - return vcodec->codec_tag == flv_codecid; + return vpar->codec_tag == flv_codecid; } } static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid, int read) { - AVCodecContext *vcodec = vstream->codec; + AVCodecParameters *par = vstream->codecpar; switch (flv_codecid) { case FLV_CODECID_H263: - vcodec->codec_id = AV_CODEC_ID_FLV1; + par->codec_id = AV_CODEC_ID_FLV1; break; case FLV_CODECID_SCREEN: - vcodec->codec_id = AV_CODEC_ID_FLASHSV; + par->codec_id = AV_CODEC_ID_FLASHSV; break; case FLV_CODECID_SCREEN2: - vcodec->codec_id = AV_CODEC_ID_FLASHSV2; + par->codec_id = AV_CODEC_ID_FLASHSV2; break; case FLV_CODECID_VP6: - vcodec->codec_id = AV_CODEC_ID_VP6F; + par->codec_id = AV_CODEC_ID_VP6F; case FLV_CODECID_VP6A: if (flv_codecid == FLV_CODECID_VP6A) - vcodec->codec_id = AV_CODEC_ID_VP6A; + par->codec_id = AV_CODEC_ID_VP6A; if (read) { - if (vcodec->extradata_size != 1) { - vcodec->extradata = av_malloc(1); - if (vcodec->extradata) - vcodec->extradata_size = 1; + if (par->extradata_size != 1) { + par->extradata = av_malloc(1); + if (par->extradata) + par->extradata_size = 1; } - if (vcodec->extradata) - vcodec->extradata[0] = avio_r8(s->pb); + if (par->extradata) + par->extradata[0] = avio_r8(s->pb); else avio_skip(s->pb, 1); } return 1; // 1 byte body size adjustment for flv_read_packet() case FLV_CODECID_H264: - vcodec->codec_id = AV_CODEC_ID_H264; + par->codec_id = AV_CODEC_ID_H264; return 3; // not 4, reading packet type will consume one byte default: av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); - vcodec->codec_tag = flv_codecid; + par->codec_tag = flv_codecid; } return 0; @@ -367,7 +368,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, int64_t max_pos, int depth) { - AVCodecContext *acodec, *vcodec; + AVCodecParameters *apar, *vpar; FLVContext *flv = s->priv_data; AVIOContext *ioc; AMFDataType amf_type; @@ -441,43 +442,43 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, if (key) { // stream info doesn't live any deeper than the first object if (depth == 1) { - acodec = astream ? astream->codec : NULL; - vcodec = vstream ? vstream->codec : NULL; + apar = astream ? astream->codecpar : NULL; + vpar = vstream ? vstream->codecpar : NULL; if (amf_type == AMF_DATA_TYPE_NUMBER || amf_type == AMF_DATA_TYPE_BOOL) { if (!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE; - else if (!strcmp(key, "videodatarate") && vcodec && + else if (!strcmp(key, "videodatarate") && vpar && 0 <= (int)(num_val * 1024.0)) - vcodec->bit_rate = num_val * 1024.0; - else if (!strcmp(key, "audiodatarate") && acodec && + vpar->bit_rate = num_val * 1024.0; + else if (!strcmp(key, "audiodatarate") && apar && 0 <= (int)(num_val * 1024.0)) - acodec->bit_rate = num_val * 1024.0; + apar->bit_rate = num_val * 1024.0; else if (!strcmp(key, "datastream")) { AVStream *st = create_stream(s, AVMEDIA_TYPE_DATA); if (!st) return AVERROR(ENOMEM); - st->codec->codec_id = AV_CODEC_ID_TEXT; + st->codecpar->codec_id = AV_CODEC_ID_TEXT; } else if (flv->trust_metadata) { - if (!strcmp(key, "videocodecid") && vcodec) { + if (!strcmp(key, "videocodecid") && vpar) { flv_set_video_codec(s, vstream, num_val, 0); - } else if (!strcmp(key, "audiocodecid") && acodec) { + } else if (!strcmp(key, "audiocodecid") && apar) { int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET; - flv_set_audio_codec(s, astream, acodec, id); - } else if (!strcmp(key, "audiosamplerate") && acodec) { - acodec->sample_rate = num_val; - } else if (!strcmp(key, "audiosamplesize") && acodec) { - acodec->bits_per_coded_sample = num_val; - } else if (!strcmp(key, "stereo") && acodec) { - acodec->channels = num_val + 1; - acodec->channel_layout = acodec->channels == 2 ? - AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; - } else if (!strcmp(key, "width") && vcodec) { - vcodec->width = num_val; - } else if (!strcmp(key, "height") && vcodec) { - vcodec->height = num_val; + flv_set_audio_codec(s, astream, apar, id); + } else if (!strcmp(key, "audiosamplerate") && apar) { + apar->sample_rate = num_val; + } else if (!strcmp(key, "audiosamplesize") && apar) { + apar->bits_per_coded_sample = num_val; + } else if (!strcmp(key, "stereo") && apar) { + apar->channels = num_val + 1; + apar->channel_layout = apar->channels == 2 ? + AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + } else if (!strcmp(key, "width") && vpar) { + vpar->width = num_val; + } else if (!strcmp(key, "height") && vpar) { + vpar->height = num_val; } } } @@ -543,9 +544,9 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) // the lookup every time it is called. for (i = 0; i < s->nb_streams; i++) { stream = s->streams[i]; - if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) astream = stream; - else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) + else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vstream = stream; } @@ -558,20 +559,13 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) static int flv_read_header(AVFormatContext *s) { - int offset, flags; + int offset; avio_skip(s->pb, 4); - flags = avio_r8(s->pb); + avio_r8(s->pb); // flags s->ctx_flags |= AVFMTCTX_NOHEADER; - if (flags & FLV_HEADER_FLAG_HASVIDEO) - if (!create_stream(s, AVMEDIA_TYPE_VIDEO)) - return AVERROR(ENOMEM); - if (flags & FLV_HEADER_FLAG_HASAUDIO) - if (!create_stream(s, AVMEDIA_TYPE_AUDIO)) - return AVERROR(ENOMEM); - offset = avio_rb32(s->pb); avio_seek(s->pb, offset, SEEK_SET); avio_skip(s->pb, 4); @@ -591,12 +585,12 @@ static int flv_read_close(AVFormatContext *s) static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size) { - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = size; - avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); + st->codecpar->extradata_size = size; + avio_read(s->pb, st->codecpar->extradata, st->codecpar->extradata_size); return 0; } @@ -605,7 +599,7 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream, { av_free(flv->new_extradata[stream]); flv->new_extradata[stream] = av_mallocz(size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!flv->new_extradata[stream]) return AVERROR(ENOMEM); flv->new_extradata_size[stream] = size; @@ -710,15 +704,15 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_DATA) + if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) break; } if (i == s->nb_streams) { st = create_stream(s, AVMEDIA_TYPE_DATA); if (!st) - return AVERROR_INVALIDDATA; - st->codec->codec_id = AV_CODEC_ID_TEXT; + return AVERROR(ENOMEM); + st->codecpar->codec_id = AV_CODEC_ID_TEXT; } pkt->dts = dts; @@ -737,7 +731,8 @@ skip: static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) { FLVContext *flv = s->priv_data; - int ret, i, type, size, flags, is_audio; + int ret, i, size, flags, is_audio; + enum FlvTagType type; int64_t next, pos; int64_t dts, pts = AV_NOPTS_VALUE; int sample_rate = 0, channels = 0; @@ -750,7 +745,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) size = avio_rb24(s->pb); dts = avio_rb24(s->pb); dts |= avio_r8(s->pb) << 24; - av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); + av_log(s, AV_LOG_TRACE, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); if (s->pb->eof_reached) return AVERROR_EOF; avio_skip(s->pb, 3); /* stream id, always 0 */ @@ -808,19 +803,22 @@ skip: /* now find stream */ for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (is_audio && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (flv_same_audio_codec(st->codec, flags)) + if (is_audio && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (flv_same_audio_codec(st->codecpar, flags)) break; } else if (!is_audio && - st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (flv_same_video_codec(st->codec, flags)) + st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (flv_same_video_codec(st->codecpar, flags)) break; } } - if (i == s->nb_streams) + if (i == s->nb_streams) { st = create_stream(s, is_audio ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_VIDEO); - av_dlog(s, "%d %X %d \n", is_audio, flags, st->discard); + if (!st) + return AVERROR(ENOMEM); + } + av_log(s, AV_LOG_TRACE, "%d %X %d \n", is_audio, flags, st->discard); if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio) @@ -839,19 +837,27 @@ skip: // if not streamed and no duration from metadata then seek to end to find // the duration from the timestamps - if (s->pb->seekable && (!s->duration || s->duration == AV_NOPTS_VALUE)) { + if (s->pb->seekable && (!s->duration || s->duration == AV_NOPTS_VALUE) && + !flv->searched_for_end) { int size; const int64_t pos = avio_tell(s->pb); + // Read the last 4 bytes of the file, this should be the size of the + // previous FLV tag. Use the timestamp of its payload as duration. const int64_t fsize = avio_size(s->pb); avio_seek(s->pb, fsize - 4, SEEK_SET); size = avio_rb32(s->pb); - avio_seek(s->pb, fsize - 3 - size, SEEK_SET); - if (size == avio_rb24(s->pb) + 11) { - uint32_t ts = avio_rb24(s->pb); - ts |= avio_r8(s->pb) << 24; - s->duration = ts * (int64_t)AV_TIME_BASE / 1000; + if (size > 0 && size < fsize) { + // Seek to the start of the last FLV tag at position (fsize - 4 - size) + // but skip the byte indicating the type. + avio_seek(s->pb, fsize - 3 - size, SEEK_SET); + if (size == avio_rb24(s->pb) + 11) { + uint32_t ts = avio_rb24(s->pb); + ts |= avio_r8(s->pb) << 24; + s->duration = ts * (int64_t)AV_TIME_BASE / 1000; + } } avio_seek(s->pb, pos, SEEK_SET); + flv->searched_for_end = 1; } if (is_audio) { @@ -860,37 +866,49 @@ skip: sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3; bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; - if (!st->codec->channels || !st->codec->sample_rate || - !st->codec->bits_per_coded_sample) { - st->codec->channels = channels; - st->codec->channel_layout = channels == 1 + if (!st->codecpar->channels || !st->codecpar->sample_rate || + !st->codecpar->bits_per_coded_sample) { + st->codecpar->channels = channels; + st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = sample_rate; - st->codec->bits_per_coded_sample = bits_per_coded_sample; + st->codecpar->sample_rate = sample_rate; + st->codecpar->bits_per_coded_sample = bits_per_coded_sample; } - if (!st->codec->codec_id) { - flv_set_audio_codec(s, st, st->codec, + if (!st->codecpar->codec_id) { + flv_set_audio_codec(s, st, st->codecpar, flags & FLV_AUDIO_CODECID_MASK); flv->last_sample_rate = - sample_rate = st->codec->sample_rate; + sample_rate = st->codecpar->sample_rate; flv->last_channels = - channels = st->codec->channels; + channels = st->codecpar->channels; } else { - AVCodecContext ctx; - ctx.sample_rate = sample_rate; - flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK); - sample_rate = ctx.sample_rate; + AVCodecParameters *par = avcodec_parameters_alloc(); + if (!par) { + ret = AVERROR(ENOMEM); + goto leave; + } + par->sample_rate = sample_rate; + par->bits_per_coded_sample = bits_per_coded_sample; + flv_set_audio_codec(s, st, par, flags & FLV_AUDIO_CODECID_MASK); + sample_rate = par->sample_rate; + avcodec_parameters_free(&par); } } else { size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1); } - if (st->codec->codec_id == AV_CODEC_ID_AAC || - st->codec->codec_id == AV_CODEC_ID_H264) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC || + st->codecpar->codec_id == AV_CODEC_ID_H264) { int type = avio_r8(s->pb); size--; - if (st->codec->codec_id == AV_CODEC_ID_H264) { + + if (size < 0) { + ret = AVERROR_INVALIDDATA; + goto leave; + } + + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = dts + cts; @@ -901,7 +919,7 @@ skip: } } if (type == 0) { - if (st->codec->extradata) { + if (st->codecpar->extradata) { if ((ret = flv_queue_extradata(flv, s->pb, is_audio, size)) < 0) return ret; ret = AVERROR(EAGAIN); @@ -909,24 +927,24 @@ skip: } if ((ret = flv_get_extradata(s, st, size)) < 0) return ret; - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { MPEG4AudioConfig cfg; /* Workaround for buggy Omnia A/XE encoder */ AVDictionaryEntry *t = av_dict_get(s->metadata, "Encoder", NULL, 0); if (t && !strcmp(t->value, "Omnia A/XE")) - st->codec->extradata_size = 2; + st->codecpar->extradata_size = 2; - avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata, - st->codec->extradata_size * 8, 1); - st->codec->channels = cfg.channels; - st->codec->channel_layout = 0; + avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata, + st->codecpar->extradata_size * 8, 1); + st->codecpar->channels = cfg.channels; + st->codecpar->channel_layout = 0; if (cfg.ext_sample_rate) - st->codec->sample_rate = cfg.ext_sample_rate; + st->codecpar->sample_rate = cfg.ext_sample_rate; else - st->codec->sample_rate = cfg.sample_rate; - av_dlog(s, "mp4a config channels %d sample rate %d\n", - st->codec->channels, st->codec->sample_rate); + st->codecpar->sample_rate = cfg.sample_rate; + av_log(s, AV_LOG_TRACE, "mp4a config channels %d sample rate %d\n", + st->codecpar->channels, st->codecpar->sample_rate); } ret = AVERROR(EAGAIN); diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index cc4c782..00bd65c 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -21,6 +21,7 @@ #include "libavutil/dict.h" #include "libavutil/intfloat.h" +#include "libavutil/mathematics.h" #include "avc.h" #include "avformat.h" #include "flv.h" @@ -60,33 +61,38 @@ typedef struct FLVContext { int64_t filesize_offset; int64_t duration; int64_t delay; ///< first dts delay (needed for AVC & Speex) + + AVCodecParameters *audio_par; + AVCodecParameters *video_par; + double framerate; + AVCodecParameters *data_par; } FLVContext; typedef struct FLVStreamContext { int64_t last_ts; ///< last timestamp for each stream } FLVStreamContext; -static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc) +static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) { - int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT + int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV_SAMPLESSIZE_8BIT; - if (enc->codec_id == AV_CODEC_ID_AAC) // specs force these parameters + if (par->codec_id == AV_CODEC_ID_AAC) // specs force these parameters return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT | FLV_STEREO; - else if (enc->codec_id == AV_CODEC_ID_SPEEX) { - if (enc->sample_rate != 16000) { + else if (par->codec_id == AV_CODEC_ID_SPEEX) { + if (par->sample_rate != 16000) { av_log(s, AV_LOG_ERROR, "flv only supports wideband (16kHz) Speex audio\n"); return -1; } - if (enc->channels != 1) { + if (par->channels != 1) { av_log(s, AV_LOG_ERROR, "flv only supports mono Speex audio\n"); return -1; } return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT; } else { - switch (enc->sample_rate) { + switch (par->sample_rate) { case 44100: flags |= FLV_SAMPLERATE_44100HZ; break; @@ -99,7 +105,7 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc) case 16000: // nellymoser only case 8000: // nellymoser only case 5512: // not MP3 - if (enc->codec_id != AV_CODEC_ID_MP3) { + if (par->codec_id != AV_CODEC_ID_MP3) { flags |= FLV_SAMPLERATE_SPECIAL; break; } @@ -111,10 +117,10 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc) } } - if (enc->channels > 1) + if (par->channels > 1) flags |= FLV_STEREO; - switch (enc->codec_id) { + switch (par->codec_id) { case AV_CODEC_ID_MP3: flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT; break; @@ -131,9 +137,9 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc) flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT; break; case AV_CODEC_ID_NELLYMOSER: - if (enc->sample_rate == 8000) + if (par->sample_rate == 8000) flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT; - else if (enc->sample_rate == 16000) + else if (par->sample_rate == 16000) flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT; else flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT; @@ -145,7 +151,7 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc) flags = FLV_CODECID_PCM_ALAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT; break; case 0: - flags |= enc->codec_tag << 4; + flags |= par->codec_tag << 4; break; default: av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); @@ -187,90 +193,19 @@ static void put_amf_bool(AVIOContext *pb, int b) avio_w8(pb, !!b); } -static int flv_write_header(AVFormatContext *s) +static void write_metadata(AVFormatContext *s, unsigned int ts) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; - AVCodecContext *audio_enc = NULL, *video_enc = NULL, *data_enc = NULL; - int i, metadata_count = 0; - double framerate = 0.0; + int metadata_count = 0; int64_t metadata_size_pos, data_size, metadata_count_pos; AVDictionaryEntry *tag = NULL; - for (i = 0; i < s->nb_streams; i++) { - AVCodecContext *enc = s->streams[i]->codec; - FLVStreamContext *sc; - switch (enc->codec_type) { - case AVMEDIA_TYPE_VIDEO: - if (s->streams[i]->avg_frame_rate.den && - s->streams[i]->avg_frame_rate.num) { - framerate = av_q2d(s->streams[i]->avg_frame_rate); - } - if (video_enc) { - av_log(s, AV_LOG_ERROR, - "at most one video stream is supported in flv\n"); - return AVERROR(EINVAL); - } - video_enc = enc; - if (enc->codec_tag == 0) { - av_log(s, AV_LOG_ERROR, "video codec not compatible with flv\n"); - return -1; - } - break; - case AVMEDIA_TYPE_AUDIO: - if (audio_enc) { - av_log(s, AV_LOG_ERROR, - "at most one audio stream is supported in flv\n"); - return AVERROR(EINVAL); - } - audio_enc = enc; - if (get_audio_flags(s, enc) < 0) - return AVERROR_INVALIDDATA; - break; - case AVMEDIA_TYPE_DATA: - if (enc->codec_id != AV_CODEC_ID_TEXT) { - av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); - return AVERROR_INVALIDDATA; - } - data_enc = enc; - break; - default: - av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); - return -1; - } - avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ - - sc = av_mallocz(sizeof(FLVStreamContext)); - if (!sc) - return AVERROR(ENOMEM); - s->streams[i]->priv_data = sc; - sc->last_ts = -1; - } - - flv->delay = AV_NOPTS_VALUE; - - avio_write(pb, "FLV", 3); - avio_w8(pb, 1); - avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc + - FLV_HEADER_FLAG_HASVIDEO * !!video_enc); - avio_wb32(pb, 9); - avio_wb32(pb, 0); - - for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->codec->codec_tag == 5) { - avio_w8(pb, 8); // message type - avio_wb24(pb, 0); // include flags - avio_wb24(pb, 0); // time stamp - avio_wb32(pb, 0); // reserved - avio_wb32(pb, 11); // size - flv->reserved = 5; - } - /* write meta_tag */ avio_w8(pb, 18); // tag type META metadata_size_pos = avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) - avio_wb24(pb, 0); // timestamp + avio_wb24(pb, ts); // timestamp avio_wb32(pb, 0); // reserved /* now data of data_size size */ @@ -282,57 +217,57 @@ static int flv_write_header(AVFormatContext *s) /* mixed array (hash) with size and string/type/data tuples */ avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); metadata_count_pos = avio_tell(pb); - metadata_count = 4 * !!video_enc + - 5 * !!audio_enc + - 1 * !!data_enc + + metadata_count = 4 * !!flv->video_par + + 5 * !!flv->audio_par + + 1 * !!flv->data_par + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); - flv->duration_offset= avio_tell(pb); + flv->duration_offset = avio_tell(pb); // fill in the guessed duration, it'll be corrected later if incorrect put_amf_double(pb, s->duration / AV_TIME_BASE); - if (video_enc) { + if (flv->video_par) { put_amf_string(pb, "width"); - put_amf_double(pb, video_enc->width); + put_amf_double(pb, flv->video_par->width); put_amf_string(pb, "height"); - put_amf_double(pb, video_enc->height); + put_amf_double(pb, flv->video_par->height); put_amf_string(pb, "videodatarate"); - put_amf_double(pb, video_enc->bit_rate / 1024.0); + put_amf_double(pb, flv->video_par->bit_rate / 1024.0); - if (framerate != 0.0) { + if (flv->framerate != 0.0) { put_amf_string(pb, "framerate"); - put_amf_double(pb, framerate); + put_amf_double(pb, flv->framerate); metadata_count++; } put_amf_string(pb, "videocodecid"); - put_amf_double(pb, video_enc->codec_tag); + put_amf_double(pb, flv->video_par->codec_tag); } - if (audio_enc) { + if (flv->audio_par) { put_amf_string(pb, "audiodatarate"); - put_amf_double(pb, audio_enc->bit_rate / 1024.0); + put_amf_double(pb, flv->audio_par->bit_rate / 1024.0); put_amf_string(pb, "audiosamplerate"); - put_amf_double(pb, audio_enc->sample_rate); + put_amf_double(pb, flv->audio_par->sample_rate); put_amf_string(pb, "audiosamplesize"); - put_amf_double(pb, audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); + put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); - put_amf_bool(pb, audio_enc->channels == 2); + put_amf_bool(pb, flv->audio_par->channels == 2); put_amf_string(pb, "audiocodecid"); - put_amf_double(pb, audio_enc->codec_tag); + put_amf_double(pb, flv->audio_par->codec_tag); } - if (data_enc) { + if (flv->data_par) { put_amf_string(pb, "datastream"); put_amf_double(pb, 0.0); } @@ -361,27 +296,113 @@ static int flv_write_header(AVFormatContext *s) avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); +} + +static int unsupported_codec(AVFormatContext *s, + const char* type, int codec_id) +{ + const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); + av_log(s, AV_LOG_ERROR, + "%s codec %s not compatible with flv\n", + type, + desc ? desc->name : "unknown"); + return AVERROR(ENOSYS); +} + +static int flv_write_header(AVFormatContext *s) +{ + int i; + AVIOContext *pb = s->pb; + FLVContext *flv = s->priv_data; + int64_t data_size; + + for (i = 0; i < s->nb_streams; i++) { + AVCodecParameters *par = s->streams[i]->codecpar; + FLVStreamContext *sc; + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (s->streams[i]->avg_frame_rate.den && + s->streams[i]->avg_frame_rate.num) { + flv->framerate = av_q2d(s->streams[i]->avg_frame_rate); + } + if (flv->video_par) { + av_log(s, AV_LOG_ERROR, + "at most one video stream is supported in flv\n"); + return AVERROR(EINVAL); + } + flv->video_par = par; + if (!ff_codec_get_tag(flv_video_codec_ids, par->codec_id)) + return unsupported_codec(s, "Video", par->codec_id); + break; + case AVMEDIA_TYPE_AUDIO: + if (flv->audio_par) { + av_log(s, AV_LOG_ERROR, + "at most one audio stream is supported in flv\n"); + return AVERROR(EINVAL); + } + flv->audio_par = par; + if (get_audio_flags(s, par) < 0) + return unsupported_codec(s, "Audio", par->codec_id); + break; + case AVMEDIA_TYPE_DATA: + if (par->codec_id != AV_CODEC_ID_TEXT) + return unsupported_codec(s, "Data", par->codec_id); + flv->data_par = par; + break; + default: + av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n"); + return -1; + } + avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ + + sc = av_mallocz(sizeof(FLVStreamContext)); + if (!sc) + return AVERROR(ENOMEM); + s->streams[i]->priv_data = sc; + sc->last_ts = -1; + } + + flv->delay = AV_NOPTS_VALUE; + + avio_write(pb, "FLV", 3); + avio_w8(pb, 1); + avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par + + FLV_HEADER_FLAG_HASVIDEO * !!flv->video_par); + avio_wb32(pb, 9); + avio_wb32(pb, 0); + + for (i = 0; i < s->nb_streams; i++) + if (s->streams[i]->codecpar->codec_tag == 5) { + avio_w8(pb, 8); // message type + avio_wb24(pb, 0); // include flags + avio_wb24(pb, 0); // time stamp + avio_wb32(pb, 0); // reserved + avio_wb32(pb, 11); // size + flv->reserved = 5; + } + + write_metadata(s, 0); for (i = 0; i < s->nb_streams; i++) { - AVCodecContext *enc = s->streams[i]->codec; - if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264) { + AVCodecParameters *par = s->streams[i]->codecpar; + if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264) { int64_t pos; - avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ? + avio_w8(pb, par->codec_type == AVMEDIA_TYPE_VIDEO ? FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); avio_wb24(pb, 0); // size patched later avio_wb24(pb, 0); // ts avio_w8(pb, 0); // ts ext avio_wb24(pb, 0); // streamid pos = avio_tell(pb); - if (enc->codec_id == AV_CODEC_ID_AAC) { - avio_w8(pb, get_audio_flags(s, enc)); + if (par->codec_id == AV_CODEC_ID_AAC) { + avio_w8(pb, get_audio_flags(s, par)); avio_w8(pb, 0); // AAC sequence header - avio_write(pb, enc->extradata, enc->extradata_size); + avio_write(pb, par->extradata, par->extradata_size); } else { - avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY); // flags + avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header avio_wb24(pb, 0); // composition time - ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); + ff_isom_write_avcc(pb, par->extradata, par->extradata_size); } data_size = avio_tell(pb) - pos; avio_seek(pb, -data_size - 10, SEEK_CUR); @@ -404,10 +425,10 @@ static int flv_write_trailer(AVFormatContext *s) /* Add EOS tag */ for (i = 0; i < s->nb_streams; i++) { - AVCodecContext *enc = s->streams[i]->codec; + AVCodecParameters *par = s->streams[i]->codecpar; FLVStreamContext *sc = s->streams[i]->priv_data; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO && - enc->codec_id == AV_CODEC_ID_H264) + if (par->codec_type == AVMEDIA_TYPE_VIDEO && + par->codec_id == AV_CODEC_ID_H264) put_avc_eos_tag(pb, sc->last_ts); } @@ -430,7 +451,7 @@ static int flv_write_trailer(AVFormatContext *s) static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[pkt->stream_index]->codec; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; FLVContext *flv = s->priv_data; FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data; unsigned ts; @@ -438,30 +459,43 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) uint8_t *data = NULL; int flags = 0, flags_size; - if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A || - enc->codec_id == AV_CODEC_ID_AAC) + if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A || + par->codec_id == AV_CODEC_ID_AAC) flags_size = 2; - else if (enc->codec_id == AV_CODEC_ID_H264) + else if (par->codec_id == AV_CODEC_ID_H264) flags_size = 5; else flags_size = 1; - switch (enc->codec_type) { + if (flv->delay == AV_NOPTS_VALUE) + flv->delay = -pkt->dts; + + if (pkt->dts < -flv->delay) { + av_log(s, AV_LOG_WARNING, + "Packets are not in the proper order with respect to DTS\n"); + return AVERROR(EINVAL); + } + + ts = pkt->dts + flv->delay; // add delay to force positive dts + + if (s->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) { + write_metadata(s, ts); + s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED; + } + + avio_write_marker(pb, av_rescale(ts, AV_TIME_BASE, 1000), + pkt->flags & AV_PKT_FLAG_KEY && (flv->video_par ? par->codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); + + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: avio_w8(pb, FLV_TAG_TYPE_VIDEO); - flags = enc->codec_tag; - if (flags == 0) { - av_log(s, AV_LOG_ERROR, - "video codec %X not compatible with flv\n", - enc->codec_id); - return -1; - } + flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id); flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; break; case AVMEDIA_TYPE_AUDIO: - flags = get_audio_flags(s, enc); + flags = get_audio_flags(s, par); assert(size); @@ -474,25 +508,14 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } - if (enc->codec_id == AV_CODEC_ID_H264) + if (par->codec_id == AV_CODEC_ID_H264) /* check if extradata looks like MP4 */ - if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) + if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0) return -1; - if (flv->delay == AV_NOPTS_VALUE) - flv->delay = -pkt->dts; - - if (pkt->dts < -flv->delay) { - av_log(s, AV_LOG_WARNING, - "Packets are not in the proper order with respect to DTS\n"); - return AVERROR(EINVAL); - } - - ts = pkt->dts + flv->delay; // add delay to force positive dts - /* check Speex packet duration */ - if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) + if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than " "8 frames per packet. Adobe Flash " "Player cannot handle this!\n"); @@ -505,7 +528,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_ avio_wb24(pb, flv->reserved); - if (enc->codec_type == AVMEDIA_TYPE_DATA) { + if (par->codec_type == AVMEDIA_TYPE_DATA) { int data_size; int64_t metadata_size_pos = avio_tell(pb); avio_w8(pb, AMF_DATA_TYPE_STRING); @@ -528,15 +551,15 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_wb32(pb, data_size + 11); } else { avio_w8(pb,flags); - if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A) { - if (enc->extradata_size) - avio_w8(pb, enc->extradata[0]); + if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) { + if (par->extradata_size) + avio_w8(pb, par->extradata[0]); else - avio_w8(pb, ((FFALIGN(enc->width, 16) - enc->width) << 4) | - (FFALIGN(enc->height, 16) - enc->height)); - } else if (enc->codec_id == AV_CODEC_ID_AAC) + avio_w8(pb, ((FFALIGN(par->width, 16) - par->width) << 4) | + (FFALIGN(par->height, 16) - par->height)); + } else if (par->codec_id == AV_CODEC_ID_AAC) avio_w8(pb, 1); // AAC raw - else if (enc->codec_id == AV_CODEC_ID_H264) { + else if (par->codec_id == AV_CODEC_ID_H264) { avio_w8(pb, 1); // AVC NALU avio_wb24(pb, pkt->pts - pkt->dts); } diff --git a/libavformat/format.c b/libavformat/format.c index c5a57d5..24b7205 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -196,7 +196,7 @@ AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, score = AVPROBE_SCORE_EXTENSION; } if (av_match_name(lpd.mime_type, fmt1->mime_type)) - score = FFMAX(score, AVPROBE_SCORE_EXTENSION); + score = FFMAX(score, AVPROBE_SCORE_MIME); if (score > *score_max) { *score_max = score; fmt = fmt1; @@ -242,6 +242,7 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, AVProbeData pd = { filename ? filename : "" }; uint8_t *buf = NULL; int ret = 0, probe_size; + uint8_t *mime_type_opt = NULL; if (!max_probe_size) max_probe_size = PROBE_BUF_MAX; @@ -254,8 +255,11 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, return AVERROR(EINVAL); avio_skip(pb, offset); max_probe_size -= offset; - if (pb->av_class) - av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &pd.mime_type); + if (pb->av_class) { + av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type_opt); + pd.mime_type = (const char *)mime_type_opt; + mime_type_opt = NULL; + } for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt; probe_size = FFMIN(probe_size << 1, FFMAX(max_probe_size, probe_size + 1))) { @@ -301,6 +305,6 @@ fail: (ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0) { av_free(buf); } - av_free(pd.mime_type); + av_freep(&pd.mime_type); return ret; } diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c index 4d5483a..470442e 100644 --- a/libavformat/framecrcenc.c +++ b/libavformat/framecrcenc.c @@ -30,7 +30,7 @@ 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, %10"PRId64", %10"PRId64", %8d, %8d, 0x%08"PRIx32"\n", + snprintf(buf, sizeof(buf), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, 0x%08"PRIx32"\n", pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size, crc); avio_write(s->pb, buf, strlen(buf)); return 0; diff --git a/libavformat/g722.c b/libavformat/g722.c index 8052939..7e60e4e 100644 --- a/libavformat/g722.c +++ b/libavformat/g722.c @@ -31,17 +31,17 @@ static int g722_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_G722; - st->codec->sample_rate = 16000; - st->codec->channels = 1; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_G722; + st->codecpar->sample_rate = 16000; + st->codecpar->channels = 1; - st->codec->bits_per_coded_sample = - av_get_bits_per_sample(st->codec->codec_id); + st->codecpar->bits_per_coded_sample = + av_get_bits_per_sample(st->codecpar->codec_id); - assert(st->codec->bits_per_coded_sample > 0); + assert(st->codecpar->bits_per_coded_sample > 0); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; } diff --git a/libavformat/g723_1.c b/libavformat/g723_1.c index b67c07c..9eca3f9 100644 --- a/libavformat/g723_1.c +++ b/libavformat/g723_1.c @@ -39,13 +39,13 @@ static av_cold int g723_1_init(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_G723_1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->channels = 1; - st->codec->sample_rate = 8000; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_G723_1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->sample_rate = 8000; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->start_time = 0; return 0; @@ -69,7 +69,7 @@ static int g723_1_read_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_read(s->pb, pkt->data + 1, size - 1); if (ret < size - 1) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret < 0 ? ret : AVERROR_EOF; } diff --git a/libavformat/g729dec.c b/libavformat/g729dec.c new file mode 100644 index 0000000..c2beb60 --- /dev/null +++ b/libavformat/g729dec.c @@ -0,0 +1,105 @@ +/* + * G.729 raw format demuxer + * Copyright (c) 2011 Vladimir Voroshilov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/log.h" +#include "libavutil/opt.h" + +#include "avformat.h" +#include "internal.h" + +typedef struct G729DemuxerContext { + AVClass *class; + + int bit_rate; +} G729DemuxerContext; + +static int g729_read_header(AVFormatContext *s) +{ + AVStream* st; + G729DemuxerContext *s1 = s->priv_data; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_G729; + st->codecpar->sample_rate = 8000; + st->codecpar->channels = 1; + + if (s1 && s1->bit_rate) + s->bit_rate = s1->bit_rate; + + switch(s->bit_rate) { + case 6400: + st->codecpar->block_align = 8; + break; + case 8000: + st->codecpar->block_align = 10; + break; + default: + av_log(s, AV_LOG_ERROR, "Invalid bit_rate value %d. " + "Only 6400 and 8000 b/s are supported.", s->bit_rate); + return AVERROR(EINVAL); + } + + avpriv_set_pts_info(st, st->codecpar->block_align << 3, 1, + st->codecpar->sample_rate); + + return 0; +} + +static int g729_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVStream *st = s->streams[0]; + int ret = av_get_packet(s->pb, pkt, st->codecpar->block_align); + if (ret < 0) + return ret; + + pkt->stream_index = 0; + pkt->dts = pkt->pts = pkt->pos / st->codecpar->block_align; + + return 0; +} + +#define OFFSET(x) offsetof(G729DemuxerContext, x) +static const AVOption g729_options[] = { + { "bit_rate", "", OFFSET(bit_rate), AV_OPT_TYPE_INT, { .i64 = 8000 }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass g729_demuxer_class = { + .class_name = "g729 demuxer", + .item_name = av_default_item_name, + .option = g729_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_g729_demuxer = { + .name = "g729", + .long_name = NULL_IF_CONFIG_SMALL("G.729 raw format demuxer"), + .priv_data_size = sizeof(G729DemuxerContext), + .read_header = g729_read_header, + .read_packet = g729_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "g729", + .priv_class = &g729_demuxer_class, +}; diff --git a/libavformat/gif.c b/libavformat/gif.c index 085c2e0..e7fa37c 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -58,7 +58,7 @@ * (byte 19) in the app_header */ #define GIF_ADD_APP_HEADER // required to enable looping of animated gif -typedef struct { +typedef struct rgb_triplet { unsigned char r; unsigned char g; unsigned char b; @@ -253,7 +253,7 @@ static int gif_image_write_image(AVIOContext *pb, return 0; } -typedef struct { +typedef struct GIFContext { AVClass *class; /** Class for private options. */ int64_t time, file_time; uint8_t buffer[100]; /* data chunks */ @@ -264,7 +264,7 @@ static int gif_write_header(AVFormatContext *s) { GIFContext *gif = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *enc, *video_enc; + AVCodecParameters *par, *video_par; int i, width, height /*, rate*/; /* XXX: do we reject audio streams or just ignore them ? @@ -274,23 +274,23 @@ static int gif_write_header(AVFormatContext *s) gif->time = 0; gif->file_time = 0; - video_enc = NULL; + video_par = NULL; for (i = 0; i < s->nb_streams; i++) { - enc = s->streams[i]->codec; - if (enc->codec_type != AVMEDIA_TYPE_AUDIO) - video_enc = enc; + par = s->streams[i]->codecpar; + if (par->codec_type != AVMEDIA_TYPE_AUDIO) + video_par = par; } - if (!video_enc) { + if (!video_par) { av_free(gif); return -1; } else { - width = video_enc->width; - height = video_enc->height; + width = video_par->width; + height = video_par->height; // rate = video_enc->time_base.den; } - if (video_enc->pix_fmt != AV_PIX_FMT_RGB24) { + if (video_par->format != AV_PIX_FMT_RGB24) { av_log(s, AV_LOG_ERROR, "ERROR: gif only handles the rgb24 pixel format. Use -pix_fmt rgb24.\n"); return AVERROR(EIO); @@ -302,9 +302,10 @@ static int gif_write_header(AVFormatContext *s) return 0; } -static int gif_write_video(AVFormatContext *s, AVCodecContext *enc, +static int gif_write_video(AVFormatContext *s, AVStream *st, const uint8_t *buf, int size) { + AVCodecParameters *par = st->codecpar; AVIOContext *pb = s->pb; int jiffies; @@ -319,26 +320,26 @@ static int gif_write_video(AVFormatContext *s, AVCodecContext *enc, /* 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; + jiffies = (70 * st->time_base.num / st->time_base.den) - 1; avio_wl16(pb, jiffies); avio_w8(pb, 0x1f); /* transparent color index */ avio_w8(pb, 0x00); - gif_image_write_image(pb, 0, 0, enc->width, enc->height, - buf, enc->width * 3, AV_PIX_FMT_RGB24); + gif_image_write_image(pb, 0, 0, par->width, par->height, + buf, par->width * 3, AV_PIX_FMT_RGB24); return 0; } static int gif_write_packet(AVFormatContext *s, AVPacket *pkt) { - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + if (par->codec_type == AVMEDIA_TYPE_AUDIO) return 0; /* just ignore audio */ else - return gif_write_video(s, codec, pkt->data, pkt->size); + return gif_write_video(s, s->streams[pkt->stream_index], pkt->data, pkt->size); } static int gif_write_trailer(AVFormatContext *s) diff --git a/libavformat/gopher.c b/libavformat/gopher.c index a149f7f..6d9fc38 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -28,7 +28,7 @@ #include "network.h" #include "url.h" -typedef struct { +typedef struct GopherContext { URLContext *hd; } GopherContext; @@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags) s->hd = NULL; err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols, h); if (err < 0) goto fail; @@ -114,7 +114,7 @@ static int gopher_read(URLContext *h, uint8_t *buf, int size) } -URLProtocol ff_gopher_protocol = { +const URLProtocol ff_gopher_protocol = { .name = "gopher", .url_open = gopher_open, .url_read = gopher_read, diff --git a/libavformat/gsmdec.c b/libavformat/gsmdec.c index f9ecbaf..d13327d 100644 --- a/libavformat/gsmdec.c +++ b/libavformat/gsmdec.c @@ -29,7 +29,7 @@ #define GSM_BLOCK_SAMPLES 160 #define GSM_SAMPLE_RATE 8000 -typedef struct { +typedef struct GSMDemuxerContext { AVClass *class; int sample_rate; } GSMDemuxerContext; @@ -45,7 +45,7 @@ static int gsm_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(s->pb, pkt, size); if (ret < GSM_BLOCK_SIZE) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } pkt->size = ret; @@ -62,12 +62,12 @@ static int gsm_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = c->sample_rate; - st->codec->bit_rate = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->iformat->raw_codec_id; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = c->sample_rate; + st->codecpar->bit_rate = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES; avpriv_set_pts_info(st, 64, GSM_BLOCK_SAMPLES, GSM_SAMPLE_RATE); diff --git a/libavformat/gxf.c b/libavformat/gxf.c index 1895840..e6ebb27 100644 --- a/libavformat/gxf.c +++ b/libavformat/gxf.c @@ -92,69 +92,69 @@ static int get_sindex(AVFormatContext *s, int id, int format) { switch (format) { case 3: case 4: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MJPEG; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MJPEG; break; case 13: case 15: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DVVIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; break; case 14: case 16: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DVVIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; break; case 11: case 12: case 20: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2VIDEO; st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc. break; case 22: case 23: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG1VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG1VIDEO; st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc. break; case 9: - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_S24LE; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = 48000; - st->codec->bit_rate = 3 * 1 * 48000 * 8; - st->codec->block_align = 3 * 1; - st->codec->bits_per_coded_sample = 24; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = 48000; + st->codecpar->bit_rate = 3 * 1 * 48000 * 8; + st->codecpar->block_align = 3 * 1; + st->codecpar->bits_per_coded_sample = 24; break; case 10: - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = 48000; - st->codec->bit_rate = 2 * 1 * 48000 * 8; - st->codec->block_align = 2 * 1; - st->codec->bits_per_coded_sample = 16; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = 48000; + st->codecpar->bit_rate = 2 * 1 * 48000 * 8; + st->codecpar->block_align = 2 * 1; + st->codecpar->bits_per_coded_sample = 16; break; case 17: - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_AC3; - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = 48000; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AC3; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = 48000; break; // timecode tracks: case 7: case 8: case 24: - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = AV_CODEC_ID_NONE; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_NONE; break; default: - st->codec->codec_type = AVMEDIA_TYPE_UNKNOWN; - st->codec->codec_id = AV_CODEC_ID_NONE; + st->codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN; + st->codecpar->codec_id = AV_CODEC_ID_NONE; break; } return s->nb_streams - 1; @@ -479,11 +479,11 @@ static int gxf_packet(AVFormatContext *s, AVPacket *pkt) { avio_rb32(pb); // "timeline" field number avio_r8(pb); // flags avio_r8(pb); // reserved - if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE || - st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) { + if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE || + st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) { int first = field_info >> 16; int last = field_info & 0xffff; // last is exclusive - int bps = av_get_bits_per_sample(st->codec->codec_id)>>3; + int bps = av_get_bits_per_sample(st->codecpar->codec_id)>>3; if (first <= last && last*bps <= pkt_len) { avio_skip(pb, first*bps); skip = pkt_len - last*bps; @@ -498,7 +498,7 @@ static int gxf_packet(AVFormatContext *s, AVPacket *pkt) { pkt->dts = field_nr; //set duration manually for DV or else lavf misdetects the frame rate - if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) + if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) pkt->duration = si->fields_per_frame; return ret; diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index fea1d5d..60f88fd 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -42,7 +42,7 @@ typedef struct GXFStreamContext { int pframes; int bframes; int p_per_gop; - int b_per_i_or_p; ///< number of B frames per I frame or P frame + int b_per_i_or_p; ///< number of B-frames per I-frame or P-frame int first_gop_closed; unsigned order; ///< interleaving order } GXFStreamContext; @@ -107,7 +107,7 @@ static int gxf_find_lines_index(AVStream *st) int i; for (i = 0; i < 6; ++i) { - if (st->codec->height == gxf_lines_tab[i].height) { + if (st->codecpar->height == gxf_lines_tab[i].height) { sc->lines_index = gxf_lines_tab[i].index; return 0; } @@ -181,18 +181,18 @@ static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st) if (sc->b_per_i_or_p > 9) sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */ } - if (st->codec->height == 512 || st->codec->height == 608) + if (st->codecpar->height == 512 || st->codecpar->height == 608) starting_line = 7; // VBI - else if (st->codec->height == 480) + else if (st->codecpar->height == 480) starting_line = 20; else starting_line = 23; // default PAL size = snprintf(buffer, 1024, "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n" "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n", - (float)st->codec->bit_rate, sc->p_per_gop, sc->b_per_i_or_p, - st->codec->pix_fmt == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1, - starting_line, (st->codec->height + 15) / 16); + (float)st->codecpar->bit_rate, sc->p_per_gop, sc->b_per_i_or_p, + st->codecpar->format == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1, + starting_line, (st->codecpar->height + 15) / 16); avio_w8(pb, TRACK_MPG_AUX); avio_w8(pb, size + 1); avio_write(pb, (uint8_t *)buffer, size + 1); @@ -472,7 +472,7 @@ static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st) { GXFStreamContext *sc = st->priv_data; - if (st->codec->pix_fmt == AV_PIX_FMT_YUV422P) + if (st->codecpar->format == AV_PIX_FMT_YUV422P) avio_wl32(pb, 2); else avio_wl32(pb, 1); /* default to 420 */ @@ -481,9 +481,9 @@ static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st) avio_wl32(pb, 1); /* I picture per GOP */ avio_wl32(pb, sc->p_per_gop); avio_wl32(pb, sc->b_per_i_or_p); - if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) avio_wl32(pb, 2); - else if (st->codec->codec_id == AV_CODEC_ID_MPEG1VIDEO) + else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG1VIDEO) avio_wl32(pb, 1); else avio_wl32(pb, 0); @@ -565,7 +565,7 @@ static int gxf_write_umf_media_description(AVFormatContext *s) gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ else { AVStream *st = s->streams[i]; - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: gxf_write_umf_media_mpeg(pb, st); @@ -646,22 +646,22 @@ static int gxf_write_header(AVFormatContext *s) return AVERROR(ENOMEM); st->priv_data = sc; - sc->media_type = ff_codec_get_tag(gxf_media_types, st->codec->codec_id); - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE) { + sc->media_type = ff_codec_get_tag(gxf_media_types, st->codecpar->codec_id); + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_id != AV_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) { + if (st->codecpar->sample_rate != 48000) { av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n"); return -1; } - if (st->codec->channels != 1) { + if (st->codecpar->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; + sc->sample_rate = st->codecpar->sample_rate; avpriv_set_pts_info(st, 64, 1, sc->sample_rate); sc->sample_size = 16; sc->frame_rate_index = -2; @@ -670,18 +670,18 @@ static int gxf_write_header(AVFormatContext *s) gxf->audio_tracks++; gxf->flags |= 0x04000000; /* audio is 16 bit pcm */ media_info = 'A'; - } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (i != 0) { av_log(s, AV_LOG_ERROR, "video stream must be the first track\n"); return -1; } /* FIXME check from time_base ? */ - if (st->codec->height == 480 || st->codec->height == 512) { /* NTSC or NTSC+VBI */ + if (st->codecpar->height == 480 || st->codecpar->height == 512) { /* NTSC or NTSC+VBI */ sc->frame_rate_index = 5; sc->sample_rate = 60; gxf->flags |= 0x00000080; gxf->time_base = (AVRational){ 1001, 60000 }; - } else if (st->codec->height == 576 || st->codec->height == 608) { /* PAL or PAL+VBI */ + } else if (st->codecpar->height == 576 || st->codecpar->height == 608) { /* PAL or PAL+VBI */ sc->frame_rate_index = 6; sc->media_type++; sc->sample_rate = 50; @@ -695,12 +695,12 @@ static int gxf_write_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den); if (gxf_find_lines_index(st) < 0) sc->lines_index = -1; - sc->sample_size = st->codec->bit_rate; + sc->sample_size = st->codecpar->bit_rate; sc->fields = 2; /* interlaced */ vsc = sc; - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_MJPEG: sc->track_type = 1; gxf->flags |= 0x00004000; @@ -719,7 +719,7 @@ static int gxf_write_header(AVFormatContext *s) media_info = 'M'; break; case AV_CODEC_ID_DVVIDEO: - if (st->codec->pix_fmt == AV_PIX_FMT_YUV422P) { + if (st->codecpar->format == AV_PIX_FMT_YUV422P) { sc->media_type += 2; sc->track_type = 6; gxf->flags |= 0x00002000; @@ -818,7 +818,7 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size) /* If the video is frame-encoded, the frame numbers shall be represented by * even field numbers. * see SMPTE360M-2004 6.4.2.1.3 Media field number */ - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { field_nb = gxf->nb_fields; } else { field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den, @@ -828,10 +828,10 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size) avio_w8(pb, sc->media_type); avio_w8(pb, st->index); avio_wb32(pb, field_nb); - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wb16(pb, 0); avio_wb16(pb, size / 2); - } else if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) { int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size); if (frame_type == AV_PICTURE_TYPE_I) { avio_w8(pb, 0x0d); @@ -844,7 +844,7 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size) sc->pframes++; } avio_wb24(pb, size); - } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) { avio_w8(pb, size / 4096); avio_wb24(pb, 0); } else @@ -865,15 +865,15 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt) int packet_start_offset = avio_tell(pb) / 1024; gxf_write_packet_header(pb, PKT_MEDIA); - if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */ + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */ padding = 4 - pkt->size % 4; - else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) padding = GXF_AUDIO_PACKET_SIZE - pkt->size; gxf_write_media_preamble(s, pkt, pkt->size + padding); avio_write(pb, pkt->data, pkt->size); gxf_write_padding(pb, padding); - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (!(gxf->flt_entries_nb % 500)) { int err; if ((err = av_reallocp_array(&gxf->flt_entries, @@ -909,7 +909,7 @@ static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cu for (i = 0; i < 2; i++) { AVStream *st = s->streams[pkt[i]->stream_index]; sc[i] = st->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den, (int64_t)48000*gxf->time_base.num, AV_ROUND_UP); field_nb[i] &= ~1; // compare against even field number because audio must be before video @@ -923,7 +923,7 @@ static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cu static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - if (pkt && s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (pkt && s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) pkt->duration = 2; // enforce 2 fields return ff_audio_rechunk_interleave(s, out, pkt, flush, ff_interleave_packet_per_dts, gxf_compare_field_nb); diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index 3a0f36d..e32c365 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -140,8 +140,7 @@ static void hds_free(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; if (os->out) - avio_close(os->out); - os->out = NULL; + ff_format_io_close(s, &os->out); if (os->ctx && os->ctx_inited) av_write_trailer(os->ctx); if (os->ctx && os->ctx->pb) @@ -171,10 +170,9 @@ static int write_manifest(AVFormatContext *s, int final) snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename); snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename); - ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL); + ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", filename); + av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); return ret; } avio_printf(out, "\n"); @@ -190,7 +188,7 @@ static int write_manifest(AVFormatContext *s, int final) int b64_size = AV_BASE64_SIZE(os->metadata_size); char *base64 = av_malloc(b64_size); if (!base64) { - avio_close(out); + ff_format_io_close(s, &out); return AVERROR(ENOMEM); } av_base64_encode(base64, b64_size, os->metadata, os->metadata_size); @@ -203,7 +201,7 @@ static int write_manifest(AVFormatContext *s, int final) } avio_printf(out, "\n"); avio_flush(out); - avio_close(out); + ff_format_io_close(s, &out); return ff_rename(temp_filename, filename); } @@ -240,8 +238,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final) "%s/stream%d.abst", s->filename, index); snprintf(temp_filename, sizeof(temp_filename), "%s/stream%d.abst.tmp", s->filename, index); - ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL); + ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); return ret; @@ -284,15 +281,14 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final) } update_size(out, afrt_pos); update_size(out, 0); - avio_close(out); + ff_format_io_close(s, &out); return ff_rename(temp_filename, filename); } static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts) { int ret, i; - ret = avio_open2(&os->out, os->temp_filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL); + ret = s->io_open(s, &os->out, os->temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) return ret; avio_wb32(os->out, 0); @@ -305,14 +301,13 @@ static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts) return 0; } -static void close_file(OutputStream *os) +static void close_file(AVFormatContext *s, OutputStream *os) { int64_t pos = avio_tell(os->out); avio_seek(os->out, 0, SEEK_SET); avio_wb32(os->out, pos); avio_flush(os->out); - avio_close(os->out); - os->out = NULL; + ff_format_io_close(s, &os->out); } static int hds_write_header(AVFormatContext *s) @@ -321,7 +316,10 @@ static int hds_write_header(AVFormatContext *s) int ret = 0, i; AVOutputFormat *oformat; - mkdir(s->filename, 0777); + if (mkdir(s->filename, 0777) == -1 && errno != EEXIST) { + ret = AVERROR(errno); + goto fail; + } oformat = av_guess_format("flv", NULL, NULL); if (!oformat) { @@ -340,18 +338,18 @@ static int hds_write_header(AVFormatContext *s) AVFormatContext *ctx; AVStream *st = s->streams[i]; - if (!st->codec->bit_rate) { + if (!st->codecpar->bit_rate) { av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i); ret = AVERROR(EINVAL); goto fail; } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (os->has_video) { c->nb_streams++; os++; } os->has_video = 1; - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { if (os->has_audio) { c->nb_streams++; os++; @@ -362,7 +360,7 @@ static int hds_write_header(AVFormatContext *s) ret = AVERROR(EINVAL); goto fail; } - os->bitrate += s->streams[i]->codec->bit_rate; + os->bitrate += s->streams[i]->codecpar->bit_rate; if (!os->ctx) { os->first_stream = i; @@ -391,8 +389,10 @@ static int hds_write_header(AVFormatContext *s) ret = AVERROR(ENOMEM); goto fail; } - avcodec_copy_context(st->codec, s->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); + st->codecpar->codec_tag = 0; st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->time_base = s->streams[i]->time_base; } if (c->streams[c->nb_streams].ctx) c->nb_streams++; @@ -471,7 +471,7 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, int final, avio_flush(os->ctx->pb); os->packets_written = 0; - close_file(os); + close_file(s, os); snprintf(target_filename, sizeof(target_filename), "%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index); @@ -517,7 +517,7 @@ static int hds_write_packet(AVFormatContext *s, AVPacket *pkt) if (st->first_dts == AV_NOPTS_VALUE) st->first_dts = pkt->dts; - if ((!os->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + if ((!os->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && av_compare_ts(pkt->dts - st->first_dts, st->time_base, end_dts, AV_TIME_BASE_Q) >= 0 && pkt->flags & AV_PKT_FLAG_KEY && os->packets_written) { diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 37b35b4..c835f22 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -636,7 +636,7 @@ static uint8_t *nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len, uint8_t *dst; uint32_t i, len; - dst = av_malloc(src_len); + dst = av_malloc(src_len + AV_INPUT_BUFFER_PADDING_SIZE); if (!dst) return NULL; @@ -799,7 +799,7 @@ static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc) /* * Initialize this field with an invalid value which can be used to detect - * whether we didn't see any VUI (in wich case it should be reset to zero). + * whether we didn't see any VUI (in which case it should be reset to zero). */ hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1; } @@ -849,51 +849,51 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) hvcc->avgFrameRate = 0; hvcc->constantFrameRate = 0; - av_dlog(NULL, "configurationVersion: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", hvcc->configurationVersion); - av_dlog(NULL, "general_profile_space: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n", hvcc->general_profile_space); - av_dlog(NULL, "general_tier_flag: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "general_tier_flag: %"PRIu8"\n", hvcc->general_tier_flag); - av_dlog(NULL, "general_profile_idc: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "general_profile_idc: %"PRIu8"\n", hvcc->general_profile_idc); - av_dlog(NULL, "general_profile_compatibility_flags: 0x%08"PRIx32"\n", + av_log(NULL, AV_LOG_TRACE, "general_profile_compatibility_flags: 0x%08"PRIx32"\n", hvcc->general_profile_compatibility_flags); - av_dlog(NULL, "general_constraint_indicator_flags: 0x%012"PRIx64"\n", + av_log(NULL, AV_LOG_TRACE, "general_constraint_indicator_flags: 0x%012"PRIx64"\n", hvcc->general_constraint_indicator_flags); - av_dlog(NULL, "general_level_idc: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n", hvcc->general_level_idc); - av_dlog(NULL, "min_spatial_segmentation_idc: %"PRIu16"\n", + av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n", hvcc->min_spatial_segmentation_idc); - av_dlog(NULL, "parallelismType: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n", hvcc->parallelismType); - av_dlog(NULL, "chromaFormat: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n", hvcc->chromaFormat); - av_dlog(NULL, "bitDepthLumaMinus8: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n", hvcc->bitDepthLumaMinus8); - av_dlog(NULL, "bitDepthChromaMinus8: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "bitDepthChromaMinus8: %"PRIu8"\n", hvcc->bitDepthChromaMinus8); - av_dlog(NULL, "avgFrameRate: %"PRIu16"\n", + av_log(NULL, AV_LOG_TRACE, "avgFrameRate: %"PRIu16"\n", hvcc->avgFrameRate); - av_dlog(NULL, "constantFrameRate: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n", hvcc->constantFrameRate); - av_dlog(NULL, "numTemporalLayers: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n", hvcc->numTemporalLayers); - av_dlog(NULL, "temporalIdNested: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n", hvcc->temporalIdNested); - av_dlog(NULL, "lengthSizeMinusOne: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", hvcc->lengthSizeMinusOne); - av_dlog(NULL, "numOfArrays: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n", hvcc->numOfArrays); for (i = 0; i < hvcc->numOfArrays; i++) { - av_dlog(NULL, "array_completeness[%"PRIu8"]: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "array_completeness[%"PRIu8"]: %"PRIu8"\n", i, hvcc->array[i].array_completeness); - av_dlog(NULL, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n", + av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n", i, hvcc->array[i].NAL_unit_type); - av_dlog(NULL, "numNalus[%"PRIu8"]: %"PRIu16"\n", + av_log(NULL, AV_LOG_TRACE, "numNalus[%"PRIu8"]: %"PRIu16"\n", i, hvcc->array[i].numNalus); for (j = 0; j < hvcc->array[i].numNalus; j++) - av_dlog(NULL, + av_log(NULL, AV_LOG_TRACE, "nalUnitLength[%"PRIu8"][%"PRIu16"]: %"PRIu16"\n", i, j, hvcc->array[i].nalUnitLength[j]); } diff --git a/libavformat/hls.c b/libavformat/hls.c index 290f12e..3b8e280 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -34,7 +34,6 @@ #include "avformat.h" #include "internal.h" #include "avio_internal.h" -#include "url.h" #define INITIAL_BUFFER_SIZE 32768 @@ -73,7 +72,7 @@ struct variant { char url[MAX_URL_SIZE]; AVIOContext pb; uint8_t* read_buffer; - URLContext *input; + AVIOContext *input; AVFormatContext *parent; int index; AVFormatContext *ctx; @@ -94,6 +93,7 @@ struct variant { }; typedef struct HLSContext { + AVFormatContext *ctx; int n_variants; struct variant **variants; int cur_seq_no; @@ -103,6 +103,7 @@ typedef struct HLSContext { int64_t seek_timestamp; int seek_flags; AVIOInterruptCB *interrupt_callback; + AVDictionary *avio_opts; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -128,10 +129,10 @@ static void free_variant_list(HLSContext *c) for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; free_segment_list(var); - av_free_packet(&var->pkt); + av_packet_unref(&var->pkt); av_free(var->pb.buffer); if (var->input) - ffurl_close(var->input); + ff_format_io_close(c->ctx, &var->input); if (var->ctx) { var->ctx->pb = NULL; avformat_close_input(&var->ctx); @@ -199,6 +200,34 @@ static void handle_key_args(struct key_info *info, const char *key, } } +static int open_in(HLSContext *c, AVIOContext **in, const char *url) +{ + AVDictionary *tmp = NULL; + int ret; + + av_dict_copy(&tmp, c->avio_opts, 0); + + ret = c->ctx->io_open(c->ctx, in, url, AVIO_FLAG_READ, &tmp); + + av_dict_free(&tmp); + return ret; +} + +static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, + const AVDictionary *opts) +{ + AVDictionary *tmp = NULL; + int ret; + + av_dict_copy(&tmp, opts, 0); + + ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); + + av_dict_free(&tmp); + + return ret; +} + static int parse_playlist(HLSContext *c, const char *url, struct variant *var, AVIOContext *in) { @@ -214,10 +243,10 @@ static int parse_playlist(HLSContext *c, const char *url, uint8_t *new_url = NULL; if (!in) { - close_in = 1; - if ((ret = avio_open2(&in, url, AVIO_FLAG_READ, - c->interrupt_callback, NULL)) < 0) + ret = open_in(c, &in, url); + if (ret < 0) return ret; + close_in = 1; } if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) @@ -320,34 +349,34 @@ static int parse_playlist(HLSContext *c, const char *url, } } if (var) - var->last_load_time = av_gettime(); + var->last_load_time = av_gettime_relative(); fail: av_free(new_url); if (close_in) - avio_close(in); + ff_format_io_close(c->ctx, &in); return ret; } static int open_input(struct variant *var) { + HLSContext *c = var->parent->priv_data; struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; if (seg->key_type == KEY_NONE) { - return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ, - &var->parent->interrupt_callback, NULL); + return open_url(var->parent, &var->input, seg->url, c->avio_opts); } else if (seg->key_type == KEY_AES_128) { + AVDictionary *opts = NULL; char iv[33], key[33], url[MAX_URL_SIZE]; int ret; if (strcmp(seg->key, var->key_url)) { - URLContext *uc; - if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, - &var->parent->interrupt_callback, NULL) == 0) { - if (ffurl_read_complete(uc, var->key, sizeof(var->key)) - != sizeof(var->key)) { + AVIOContext *pb; + if (open_url(var->parent, &pb, seg->key, c->avio_opts) == 0) { + ret = avio_read(pb, var->key, sizeof(var->key)); + if (ret != sizeof(var->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", seg->key); } - ffurl_close(uc); + ff_format_io_close(var->parent, &pb); } else { av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", seg->key); @@ -361,17 +390,14 @@ static int open_input(struct variant *var) snprintf(url, sizeof(url), "crypto+%s", seg->url); else snprintf(url, sizeof(url), "crypto:%s", seg->url); - if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ, - &var->parent->interrupt_callback)) < 0) - return ret; - av_opt_set(var->input->priv_data, "key", key, 0); - av_opt_set(var->input->priv_data, "iv", iv, 0); - if ((ret = ffurl_connect(var->input, NULL)) < 0) { - ffurl_close(var->input); - var->input = NULL; - return ret; - } - return 0; + + av_dict_copy(&opts, c->avio_opts, 0); + av_dict_set(&opts, "key", key, 0); + av_dict_set(&opts, "iv", iv, 0); + + ret = open_url(var->parent, &var->input, url, opts); + av_dict_free(&opts); + return ret; } return AVERROR(ENOSYS); } @@ -392,7 +418,7 @@ restart: reload: if (!v->finished && - av_gettime() - v->last_load_time >= reload_interval) { + av_gettime_relative() - v->last_load_time >= reload_interval) { if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) return ret; /* If we need to reload the playlist again below (if @@ -409,7 +435,7 @@ reload: if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { if (v->finished) return AVERROR_EOF; - while (av_gettime() - v->last_load_time < reload_interval) { + while (av_gettime_relative() - v->last_load_time < reload_interval) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); @@ -422,11 +448,10 @@ reload: if (ret < 0) return ret; } - ret = ffurl_read(v->input, buf, buf_size); + ret = avio_read(v->input, buf, buf_size); if (ret > 0) return ret; - ffurl_close(v->input); - v->input = NULL; + ff_format_io_close(c->ctx, &v->input); v->cur_seq_no++; c->end_of_segment = 1; @@ -449,16 +474,51 @@ reload: goto restart; } +static int save_avio_options(AVFormatContext *s) +{ + HLSContext *c = s->priv_data; + static const char *opts[] = { "headers", "user_agent", NULL }; + const char **opt = opts; + uint8_t *buf; + int ret = 0; + + while (*opt) { + if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { + ret = av_dict_set(&c->avio_opts, *opt, buf, + AV_DICT_DONT_STRDUP_VAL); + if (ret < 0) + return ret; + } + opt++; + } + + return ret; +} + +static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, + int flags, AVDictionary **opts) +{ + av_log(s, AV_LOG_ERROR, + "A HLS playlist item '%s' referred to an external file '%s'. " + "Opening this file was forbidden for security reasons\n", + s->filename, url); + return AVERROR(EPERM); +} + static int hls_read_header(AVFormatContext *s) { HLSContext *c = s->priv_data; int ret = 0, i, j, stream_offset = 0; + c->ctx = s; c->interrupt_callback = &s->interrupt_callback; if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) goto fail; + if ((ret = save_avio_options(s)) < 0) + goto fail; + if (c->n_variants == 0) { av_log(NULL, AV_LOG_WARNING, "Empty playlist\n"); ret = AVERROR_EOF; @@ -530,6 +590,7 @@ static int hls_read_header(AVFormatContext *s) goto fail; } v->ctx->pb = &v->pb; + v->ctx->io_open = nested_io_open; v->stream_offset = stream_offset; ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL); if (ret < 0) @@ -557,7 +618,7 @@ static int hls_read_header(AVFormatContext *s) ff_program_add_stream_index(s, i, stream_offset + j); st->id = i; avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den); - avcodec_copy_context(st->codec, v->ctx->streams[j]->codec); + avcodec_parameters_copy(st->codecpar, v->ctx->streams[j]->codecpar); if (v->bandwidth) av_dict_set(&st->metadata, "variant_bitrate", bitrate_str, 0); @@ -600,8 +661,7 @@ static int recheck_discard_flags(AVFormatContext *s, int first) av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i); } else if (first && !v->cur_needed && v->needed) { if (v->input) - ffurl_close(v->input); - v->input = NULL; + ff_format_io_close(s, &v->input); v->needed = 0; changed = 1; av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i); @@ -661,7 +721,7 @@ start: c->seek_timestamp = AV_NOPTS_VALUE; break; } - av_free_packet(&var->pkt); + av_packet_unref(&var->pkt); reset_packet(&var->pkt); } } @@ -712,6 +772,9 @@ static int hls_close(AVFormatContext *s) HLSContext *c = s->priv_data; free_variant_list(c); + + av_dict_free(&c->avio_opts); + return 0; } @@ -745,11 +808,9 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, struct variant *var = c->variants[i]; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : c->first_timestamp; - if (var->input) { - ffurl_close(var->input); - var->input = NULL; - } - av_free_packet(&var->pkt); + if (var->input) + ff_format_io_close(s, &var->input); + av_packet_unref(&var->pkt); reset_packet(&var->pkt); var->pb.eof_reached = 0; /* Clear any buffered data */ diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index aa38d05..96b780f 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -33,7 +33,7 @@ typedef struct ListEntry { char name[1024]; - int duration; + int64_t duration; // segment duration in AV_TIME_BASE units struct ListEntry *next; } ListEntry; @@ -47,17 +47,19 @@ typedef struct HLSContext { float time; // Set by a private option. int size; // Set by a private option. int wrap; // Set by a private option. + int version; // Set by a private option. + int allowcache; int64_t recording_time; int has_video; + // The following timestamps are in AV_TIME_BASE units. int64_t start_pts; int64_t end_pts; - int64_t duration; // last segment duration computed so far, in seconds + int64_t duration; // last segment duration computed so far. int nb_entries; ListEntry *list; ListEntry *end_list; char *basename; char *baseurl; - AVIOContext *pb; } HLSContext; static int hls_mux_init(AVFormatContext *s) @@ -72,19 +74,23 @@ static int hls_mux_init(AVFormatContext *s) oc->oformat = hls->oformat; oc->interrupt_callback = s->interrupt_callback; + oc->opaque = s->opaque; + oc->io_open = s->io_open; + oc->io_close = s->io_close; for (i = 0; i < s->nb_streams; i++) { AVStream *st; if (!(st = avformat_new_stream(oc, NULL))) return AVERROR(ENOMEM); - avcodec_copy_context(st->codec, s->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->time_base = s->streams[i]->time_base; } return 0; } -static int append_entry(HLSContext *hls, uint64_t duration) +static int append_entry(HLSContext *hls, int64_t duration) { ListEntry *en = av_malloc(sizeof(*en)); @@ -130,12 +136,14 @@ static int hls_window(AVFormatContext *s, int last) { HLSContext *hls = s->priv_data; ListEntry *en; - int target_duration = 0; + int64_t target_duration = 0; int ret = 0; + AVIOContext *out = NULL; + char temp_filename[1024]; int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->size); - if ((ret = avio_open2(&hls->pb, s->filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename); + if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL)) < 0) goto fail; for (en = hls->list; en; en = en->next) { @@ -143,26 +151,38 @@ static int hls_window(AVFormatContext *s, int last) target_duration = en->duration; } - avio_printf(hls->pb, "#EXTM3U\n"); - avio_printf(hls->pb, "#EXT-X-VERSION:3\n"); - avio_printf(hls->pb, "#EXT-X-TARGETDURATION:%d\n", target_duration); - avio_printf(hls->pb, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); + avio_printf(out, "#EXTM3U\n"); + avio_printf(out, "#EXT-X-VERSION:%d\n", hls->version); + if (hls->allowcache == 0 || hls->allowcache == 1) { + avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES"); + } + avio_printf(out, "#EXT-X-TARGETDURATION:%"PRId64"\n", + av_rescale_rnd(target_duration, 1, AV_TIME_BASE, + AV_ROUND_UP)); + avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); for (en = hls->list; en; en = en->next) { - avio_printf(hls->pb, "#EXTINF:%d,\n", en->duration); + if (hls->version > 2) + avio_printf(out, "#EXTINF:%f\n", + (double)en->duration / AV_TIME_BASE); + else + avio_printf(out, "#EXTINF:%"PRId64",\n", + av_rescale(en->duration, 1, AV_TIME_BASE)); if (hls->baseurl) - avio_printf(hls->pb, "%s", hls->baseurl); - avio_printf(hls->pb, "%s\n", en->name); + avio_printf(out, "%s", hls->baseurl); + avio_printf(out, "%s\n", en->name); } if (last) - avio_printf(hls->pb, "#EXT-X-ENDLIST\n"); + avio_printf(out, "#EXT-X-ENDLIST\n"); fail: - avio_closep(&hls->pb); + ff_format_io_close(s, &out); + if (ret >= 0) + ff_rename(temp_filename, s->filename); return ret; } @@ -177,8 +197,7 @@ static int hls_start(AVFormatContext *s) return AVERROR(EINVAL); c->number++; - if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) return err; if (oc->oformat->priv_class && oc->priv_data) @@ -201,7 +220,7 @@ static int hls_write_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) hls->has_video += - s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO; + s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; if (hls->has_video > 1) av_log(s, AV_LOG_WARNING, @@ -256,34 +275,33 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) AVFormatContext *oc = hls->avf; AVStream *st = s->streams[pkt->stream_index]; int64_t end_pts = hls->recording_time * hls->number; + int64_t pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); int ret, can_split = 1; if (hls->start_pts == AV_NOPTS_VALUE) { - hls->start_pts = pkt->pts; - hls->end_pts = pkt->pts; + hls->start_pts = pts; + hls->end_pts = pts; } if (hls->has_video) { - can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->flags & AV_PKT_FLAG_KEY; } if (pkt->pts == AV_NOPTS_VALUE) can_split = 0; else - hls->duration = av_rescale(pkt->pts - hls->end_pts, - st->time_base.num, st->time_base.den); + hls->duration = pts - hls->end_pts; - if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, - end_pts, AV_TIME_BASE_Q) >= 0) { + if (can_split && pts - hls->start_pts >= end_pts) { ret = append_entry(hls, hls->duration); if (ret) return ret; - hls->end_pts = pkt->pts; + hls->end_pts = pts; hls->duration = 0; av_write_frame(oc, NULL); /* Flush any buffered data */ - avio_close(oc->pb); + ff_format_io_close(s, &oc->pb); ret = hls_start(s); @@ -307,14 +325,13 @@ static int hls_write_trailer(struct AVFormatContext *s) AVFormatContext *oc = hls->avf; av_write_trailer(oc); - avio_closep(&oc->pb); + ff_format_io_close(s, &oc->pb); avformat_free_context(oc); av_free(hls->basename); append_entry(hls, hls->duration); hls_window(s, 1); free_entries(hls); - avio_close(hls->pb); return 0; } @@ -325,7 +342,9 @@ static const AVOption options[] = { {"hls_time", "segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E}, {"hls_list_size", "maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, {"hls_wrap", "number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, + {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E}, {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"hls_version", "protocol version", OFFSET(version), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 3, E}, { NULL }, }; diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c index ec357de..4c3048a 100644 --- a/libavformat/hlsproto.c +++ b/libavformat/hlsproto.c @@ -121,8 +121,10 @@ static int parse_playlist(URLContext *h, const char *url) return ret; read_chomp_line(in, line, sizeof(line)); - if (strcmp(line, "#EXTM3U")) - return AVERROR_INVALIDDATA; + if (strcmp(line, "#EXTM3U")) { + ret = AVERROR_INVALIDDATA; + goto fail; + } free_segment_list(s); s->finished = 0; @@ -169,7 +171,7 @@ static int parse_playlist(URLContext *h, const char *url) } } } - s->last_load_time = av_gettime(); + s->last_load_time = av_gettime_relative(); fail: avio_close(in); @@ -273,7 +275,7 @@ start: s->target_duration; retry: if (!s->finished) { - int64_t now = av_gettime(); + int64_t now = av_gettime_relative(); if (now - s->last_load_time >= reload_interval) { if ((ret = parse_playlist(h, s->playlisturl)) < 0) return ret; @@ -292,7 +294,7 @@ retry: if (s->cur_seq_no - s->start_seq_no >= s->n_segments) { if (s->finished) return AVERROR_EOF; - while (av_gettime() - s->last_load_time < reload_interval) { + while (av_gettime_relative() - s->last_load_time < reload_interval) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); @@ -302,7 +304,7 @@ retry: url = s->segments[s->cur_seq_no - s->start_seq_no]->url, av_log(h, AV_LOG_DEBUG, "opening %s\n", url); ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols, h); if (ret < 0) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; @@ -313,7 +315,7 @@ retry: goto start; } -URLProtocol ff_hls_protocol = { +const URLProtocol ff_hls_protocol = { .name = "hls", .url_open = hls_open, .url_read = hls_read, diff --git a/libavformat/hnm.c b/libavformat/hnm.c index 54ac6c2..8476e51 100644 --- a/libavformat/hnm.c +++ b/libavformat/hnm.c @@ -108,15 +108,15 @@ static int hnm_read_header(AVFormatContext *s) if (!(vst = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_HNM4_VIDEO; - vst->codec->codec_tag = 0; - vst->codec->width = hnm->width; - vst->codec->height = hnm->height; - vst->codec->extradata = av_mallocz(1); + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_HNM4_VIDEO; + vst->codecpar->codec_tag = 0; + vst->codecpar->width = hnm->width; + vst->codecpar->height = hnm->height; + vst->codecpar->extradata = av_mallocz(1); - vst->codec->extradata_size = 1; - memcpy(vst->codec->extradata, &hnm->version, 1); + vst->codecpar->extradata_size = 1; + memcpy(vst->codecpar->extradata, &hnm->version, 1); vst->start_time = 0; @@ -190,7 +190,7 @@ static int hnm_read_close(AVFormatContext *s) Hnm4DemuxContext *hnm = s->priv_data; if (hnm->vpkt.size > 0) - av_free_packet(&hnm->vpkt); + av_packet_unref(&hnm->vpkt); return 0; } diff --git a/libavformat/http.c b/libavformat/http.c index f82002c..00cf295 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -45,7 +45,7 @@ #define BUFFER_SIZE MAX_URL_SIZE #define MAX_REDIRECTS 8 -typedef struct { +typedef struct HTTPContext { const AVClass *class; URLContext *hd; unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end; @@ -181,7 +181,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) if (!s->hd) { err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, options); + &h->interrupt_callback, options, h->protocols, h); if (err < 0) return err; } @@ -287,9 +287,16 @@ static int http_open(URLContext *h, const char *uri, int flags, if (s->headers) { int len = strlen(s->headers); - if (len < 2 || strcmp("\r\n", s->headers + len - 2)) + if (len < 2 || strcmp("\r\n", s->headers + len - 2)) { av_log(h, AV_LOG_WARNING, "No trailing CRLF found in HTTP header.\n"); + ret = av_reallocp(&s->headers, len + 3); + if (ret < 0) + return ret; + s->headers[len] = '\r'; + s->headers[len + 1] = '\n'; + s->headers[len + 2] = '\0'; + } } ret = http_open_cnx(h, options); @@ -460,7 +467,7 @@ static int process_line(URLContext *h, char *line, int line_count, p++; s->http_code = strtol(p, &end, 10); - av_dlog(NULL, "http_code=%d\n", s->http_code); + av_log(NULL, AV_LOG_TRACE, "http_code=%d\n", s->http_code); if ((ret = check_http_code(h, s->http_code, end)) < 0) return ret; @@ -535,7 +542,7 @@ static int http_read_header(URLContext *h, int *new_location) if ((err = http_get_line(s, line, sizeof(line))) < 0) return err; - av_dlog(NULL, "header='%s'\n", line); + av_log(NULL, AV_LOG_TRACE, "header='%s'\n", line); err = process_line(h, line, s->line_count, new_location); if (err < 0) @@ -775,10 +782,11 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) s->chunksize = strtoll(line, NULL, 16); - av_dlog(NULL, "Chunked encoding data size: %"PRId64"'\n", + av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n", s->chunksize); - - if (!s->chunksize) + if (s->chunksize < 0) + return AVERROR_INVALIDDATA; + else if (!s->chunksize) return 0; break; } @@ -1006,7 +1014,7 @@ static const AVClass flavor ## _context_class = { \ #if CONFIG_HTTP_PROTOCOL HTTP_CLASS(http); -URLProtocol ff_http_protocol = { +const URLProtocol ff_http_protocol = { .name = "http", .url_open2 = http_open, .url_read = http_read, @@ -1024,7 +1032,7 @@ URLProtocol ff_http_protocol = { #if CONFIG_HTTPS_PROTOCOL HTTP_CLASS(https); -URLProtocol ff_https_protocol = { +const URLProtocol ff_https_protocol = { .name = "https", .url_open2 = http_open, .url_read = http_read, @@ -1072,7 +1080,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) NULL); redo: ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols, h); if (ret < 0) return ret; @@ -1135,7 +1143,7 @@ static int http_proxy_write(URLContext *h, const uint8_t *buf, int size) return ffurl_write(s->hd, buf, size); } -URLProtocol ff_httpproxy_protocol = { +const URLProtocol ff_httpproxy_protocol = { .name = "httpproxy", .url_open = http_proxy_open, .url_read = http_buf_read, diff --git a/libavformat/http.h b/libavformat/http.h index 3d301a7..b8fe33b 100644 --- a/libavformat/http.h +++ b/libavformat/http.h @@ -40,7 +40,7 @@ void ff_http_init_auth_state(URLContext *dest, const URLContext *src); /** * Send a new HTTP request, reusing the old connection. * - * @param h pointer to the ressource + * @param h pointer to the resource * @param uri uri used to perform the request * @return a negative value if an error condition occurred, 0 * otherwise diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index b96da3e..b0d3c0c 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -220,18 +220,19 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, /* TODO: Escape the quoted strings properly. */ av_strlcatf(authstr, len, "username=\"%s\"", username); - av_strlcatf(authstr, len, ",realm=\"%s\"", state->realm); - av_strlcatf(authstr, len, ",nonce=\"%s\"", digest->nonce); - av_strlcatf(authstr, len, ",uri=\"%s\"", uri); - av_strlcatf(authstr, len, ",response=\"%s\"", response); + av_strlcatf(authstr, len, ", realm=\"%s\"", state->realm); + av_strlcatf(authstr, len, ", nonce=\"%s\"", digest->nonce); + av_strlcatf(authstr, len, ", uri=\"%s\"", uri); + av_strlcatf(authstr, len, ", response=\"%s\"", response); + if (digest->algorithm[0]) - av_strlcatf(authstr, len, ",algorithm=%s", digest->algorithm); + av_strlcatf(authstr, len, ", algorithm=%s", digest->algorithm); if (digest->opaque[0]) - av_strlcatf(authstr, len, ",opaque=\"%s\"", digest->opaque); + av_strlcatf(authstr, len, ", opaque=\"%s\"", digest->opaque); if (digest->qop[0]) { - av_strlcatf(authstr, len, ",qop=\"%s\"", digest->qop); - av_strlcatf(authstr, len, ",cnonce=\"%s\"", cnonce); - av_strlcatf(authstr, len, ",nc=%s", nc); + av_strlcatf(authstr, len, ", qop=\"%s\"", digest->qop); + av_strlcatf(authstr, len, ", cnonce=\"%s\"", cnonce); + av_strlcatf(authstr, len, ", nc=%s", nc); } av_strlcatf(authstr, len, "\r\n"); diff --git a/libavformat/httpauth.h b/libavformat/httpauth.h index 99bf43f..9bfbc52 100644 --- a/libavformat/httpauth.h +++ b/libavformat/httpauth.h @@ -62,7 +62,7 @@ typedef struct HTTPAuthState { */ char realm[200]; /** - * The parameters specifiec to digest authentication. + * The parameters specific to digest authentication. */ DigestParams digest_params; /** diff --git a/libavformat/icecast.c b/libavformat/icecast.c index 155396f..820681b 100644 --- a/libavformat/icecast.c +++ b/libavformat/icecast.c @@ -127,8 +127,11 @@ static int icecast_open(URLContext *h, const char *uri, int flags) av_dict_set(&opt_dict, "auth_type", "basic", 0); av_dict_set(&opt_dict, "headers", headers, 0); av_dict_set(&opt_dict, "chunked_post", "0", 0); + av_dict_set(&opt_dict, "send_expect_100", s->legacy_icecast ? "0" : "1", 0); if (NOT_EMPTY(s->content_type)) av_dict_set(&opt_dict, "content_type", s->content_type, 0); + else + av_dict_set(&opt_dict, "content_type", "audio/mpeg", 0); if (NOT_EMPTY(s->user_agent)) av_dict_set(&opt_dict, "user_agent", s->user_agent, 0); @@ -173,7 +176,8 @@ static int icecast_open(URLContext *h, const char *uri, int flags) // Build new URI for passing to http protocol ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path); // Finally open http proto handler - ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict); + ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict, + h->protocols, h); cleanup: // Free variables @@ -218,7 +222,7 @@ static const AVClass icecast_context_class = { .version = LIBAVUTIL_VERSION_INT, }; -URLProtocol ff_icecast_protocol = { +const URLProtocol ff_icecast_protocol = { .name = "icecast", .url_open = icecast_open, .url_write = icecast_write, diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index e5f7486..5e9825d 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -207,8 +207,8 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, case ID3v2_ENCODING_UTF16BOM: if ((left -= 2) < 0) { av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n"); - avio_close_dyn_buf(dynbuf, dst); - av_freep(dst); + ffio_free_dyn_buf(&dynbuf); + *dst = NULL; return AVERROR_INVALIDDATA; } switch (avio_rb16(pb)) { @@ -218,8 +218,8 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, break; default: av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n"); - avio_close_dyn_buf(dynbuf, dst); - av_freep(dst); + ffio_free_dyn_buf(&dynbuf); + *dst = NULL; *maxread = left; return AVERROR_INVALIDDATA; } @@ -300,7 +300,8 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct. */ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, - char *tag, ID3v2ExtraMeta **extra_meta) + const char *tag, ID3v2ExtraMeta **extra_meta, + int isv34) { ID3v2ExtraMetaGEOB *geob_data = NULL; ID3v2ExtraMeta *new_extra = NULL; @@ -432,7 +433,8 @@ static void free_apic(void *obj) } static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, - char *tag, ID3v2ExtraMeta **extra_meta) + const char *tag, ID3v2ExtraMeta **extra_meta, + int isv34) { int enc, pic_type; char mimetype[64]; @@ -442,7 +444,7 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, ID3v2ExtraMeta *new_extra = NULL; int64_t end = avio_tell(pb) + taglen; - if (taglen <= 4) + if (taglen <= 4 || (!isv34 && taglen <= 6)) goto fail; new_extra = av_mallocz(sizeof(*new_extra)); @@ -454,7 +456,14 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, taglen--; /* mimetype */ - taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype)); + if (isv34) { + taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype)); + } else { + avio_read(pb, mimetype, 3); + mimetype[3] = 0; + taglen -= 3; + } + while (mime->id != AV_CODEC_ID_NONE) { if (!av_strncasecmp(mime->str, mimetype, sizeof(mimetype))) { id = mime->id; @@ -486,10 +495,10 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, goto fail; } - apic->buf = av_buffer_alloc(taglen + FF_INPUT_BUFFER_PADDING_SIZE); + apic->buf = av_buffer_alloc(taglen + AV_INPUT_BUFFER_PADDING_SIZE); if (!apic->buf || avio_read(pb, apic->buf->data, taglen) != taglen) goto fail; - memset(apic->buf->data + taglen, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(apic->buf->data + taglen, 0, AV_INPUT_BUFFER_PADDING_SIZE); new_extra->tag = "APIC"; new_extra->data = apic; @@ -508,8 +517,9 @@ fail: typedef struct ID3v2EMFunc { const char *tag3; const char *tag4; - void (*read)(AVFormatContext *, AVIOContext *, int, char *, - ID3v2ExtraMeta **); + void (*read)(AVFormatContext *s, AVIOContext *pb, int taglen, + const char *tag, ID3v2ExtraMeta **extra_meta, + int isv34); void (*free)(void *obj); } ID3v2EMFunc; @@ -664,7 +674,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, read_ttag(s, pbx, tlen, tag); else /* parse special meta tag */ - extra_func->read(s, pbx, tlen, tag, extra_meta); + extra_func->read(s, pbx, tlen, tag, extra_meta, isv34); } else if (!tag[0]) { if (tag[1]) av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding"); @@ -751,15 +761,18 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) return AVERROR(ENOMEM); st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = apic->id; - av_dict_set(&st->metadata, "title", apic->description, 0); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = apic->id; + + if (apic->description[0]) + av_dict_set(&st->metadata, "title", apic->description, 0); + av_dict_set(&st->metadata, "comment", apic->type, 0); av_init_packet(&st->attached_pic); st->attached_pic.buf = apic->buf; st->attached_pic.data = apic->buf->data; - st->attached_pic.size = apic->buf->size - FF_INPUT_BUFFER_PADDING_SIZE; + st->attached_pic.size = apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index 89181c2..3f9bd4e 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -83,7 +83,7 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char * len = avio_close_dyn_buf(dyn_buf, &pb); avio_wb32(avioc, tag); - /* ID3v2.3 frame size is not synchsafe */ + /* ID3v2.3 frame size is not sync-safe */ if (id3->version == 3) avio_wb32(avioc, len); else @@ -171,7 +171,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) /* get the mimetype*/ while (mime->id != AV_CODEC_ID_NONE) { - if (mime->id == st->codec->codec_id) { + if (mime->id == st->codecpar->codec_id) { mimetype = mime->str; break; } diff --git a/libavformat/idcin.c b/libavformat/idcin.c index 2536e8b..86e9f41 100644 --- a/libavformat/idcin.c +++ b/libavformat/idcin.c @@ -1,6 +1,6 @@ /* * id Quake II CIN File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -33,7 +33,7 @@ * 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 + * Probabilistically, 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. * @@ -189,16 +189,16 @@ static int idcin_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 33, 1, IDCIN_FPS); st->start_time = 0; idcin->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_IDCIN; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = width; - st->codec->height = height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_IDCIN; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = width; + st->codecpar->height = height; /* load up the Huffman tables into extradata */ - st->codec->extradata_size = HUFFMAN_TABLE_SIZE; - st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); - ret = avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE); + st->codecpar->extradata_size = HUFFMAN_TABLE_SIZE; + st->codecpar->extradata = av_malloc(HUFFMAN_TABLE_SIZE); + ret = avio_read(pb, st->codecpar->extradata, HUFFMAN_TABLE_SIZE); if (ret < 0) { return ret; } else if (ret != HUFFMAN_TABLE_SIZE) { @@ -214,19 +214,19 @@ static int idcin_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 63, 1, sample_rate); st->start_time = 0; idcin->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 1; - st->codec->channels = channels; - st->codec->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; - st->codec->sample_rate = sample_rate; - st->codec->bits_per_coded_sample = bytes_per_sample * 8; - st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels; - st->codec->block_align = idcin->block_align = bytes_per_sample * channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 1; + st->codecpar->channels = channels; + st->codecpar->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = sample_rate; + st->codecpar->bits_per_coded_sample = bytes_per_sample * 8; + st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels; + st->codecpar->block_align = idcin->block_align = bytes_per_sample * channels; if (bytes_per_sample == 1) - st->codec->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; else - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; if (sample_rate % 14 != 0) { idcin->audio_chunk_size1 = (sample_rate / 14) * @@ -309,7 +309,7 @@ static int idcin_read_packet(AVFormatContext *s, return ret; else if (ret != chunk_size) { av_log(s, AV_LOG_ERROR, "incomplete packet\n"); - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } if (command == 1) { @@ -317,9 +317,9 @@ static int idcin_read_packet(AVFormatContext *s, pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); - if (ret < 0) { - av_free_packet(pkt); - return ret; + if (!pal) { + av_packet_unref(pkt); + return AVERROR(ENOMEM); } memcpy(pal, palette, AVPALETTE_SIZE); pkt->flags |= AV_PKT_FLAG_KEY; diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c index 82eff24..a408946 100644 --- a/libavformat/idroqdec.c +++ b/libavformat/idroqdec.c @@ -1,6 +1,6 @@ /* * id RoQ (.roq) File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -127,14 +127,14 @@ static int roq_read_packet(AVFormatContext *s, return AVERROR(ENOMEM); avpriv_set_pts_info(st, 63, 1, roq->frame_rate); roq->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_ROQ; - st->codec->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_ROQ; + st->codecpar->codec_tag = 0; /* no fourcc */ if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); - st->codec->width = roq->width = AV_RL16(preamble); - st->codec->height = roq->height = AV_RL16(preamble + 2); + st->codecpar->width = roq->width = AV_RL16(preamble); + st->codecpar->height = roq->height = AV_RL16(preamble + 2); break; } /* don't care about this chunk anymore */ @@ -175,22 +175,22 @@ static int roq_read_packet(AVFormatContext *s, return AVERROR(ENOMEM); avpriv_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE); roq->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ROQ_DPCM; - st->codec->codec_tag = 0; /* no tag */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ROQ_DPCM; + st->codecpar->codec_tag = 0; /* no tag */ if (chunk_type == RoQ_SOUND_STEREO) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - roq->audio_channels = st->codec->channels; - st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE; - st->codec->bits_per_coded_sample = 16; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + roq->audio_channels = st->codecpar->channels; + st->codecpar->sample_rate = RoQ_AUDIO_SAMPLE_RATE; + st->codecpar->bits_per_coded_sample = 16; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; } case RoQ_QUAD_VQ: if (chunk_type == RoQ_QUAD_VQ) { diff --git a/libavformat/iff.c b/libavformat/iff.c index 6be0fb7..52c7e97 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -74,7 +74,7 @@ typedef enum { BITMAP_BYTERUN1 } bitmap_compression_type; -typedef struct { +typedef struct IffDemuxContext { uint64_t body_pos; uint32_t body_size; uint32_t sent_bytes; @@ -122,11 +122,11 @@ static int iff_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; avio_skip(pb, 8); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content - st->codec->codec_tag = avio_rl32(pb); + st->codecpar->codec_tag = avio_rl32(pb); while(!pb->eof_reached) { uint64_t orig_pos; @@ -138,12 +138,12 @@ static int iff_read_header(AVFormatContext *s) switch(chunk_id) { case ID_VHDR: - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); - st->codec->sample_rate = avio_rb16(pb); + st->codecpar->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); compression = avio_r8(pb); @@ -159,11 +159,11 @@ static int iff_read_header(AVFormatContext *s) if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rb32(pb) < 6) { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } else { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } break; @@ -173,28 +173,28 @@ static int iff_read_header(AVFormatContext *s) data_size); return AVERROR_INVALIDDATA; } - st->codec->extradata_size = data_size; - st->codec->extradata = av_malloc(data_size); - if (!st->codec->extradata) + st->codecpar->extradata_size = data_size; + st->codecpar->extradata = av_malloc(data_size); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - if (avio_read(pb, st->codec->extradata, data_size) < 0) + if (avio_read(pb, st->codecpar->extradata, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; - st->codec->width = avio_rb16(pb); - st->codec->height = avio_rb16(pb); + st->codecpar->width = avio_rb16(pb); + st->codecpar->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset - st->codec->bits_per_coded_sample = avio_r8(pb); + st->codecpar->bits_per_coded_sample = avio_r8(pb); if (data_size >= 11) { avio_skip(pb, 1); // masking compression = avio_r8(pb); } if (data_size >= 16) { - avio_skip(pb, 3); // paddding, transparent + avio_skip(pb, 3); // padding, transparent st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } @@ -229,37 +229,37 @@ static int iff_read_header(AVFormatContext *s) avio_seek(pb, iff->body_pos, SEEK_SET); - switch(st->codec->codec_type) { + switch(st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: - avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); switch(compression) { case COMP_NONE: - st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: - st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; + st->codecpar->codec_id = AV_CODEC_ID_8SVX_FIB; break; case COMP_EXP: - st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; + st->codecpar->codec_id = AV_CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "unknown compression method\n"); return -1; } - st->codec->bits_per_coded_sample = 8; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + st->codecpar->bits_per_coded_sample = 8; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: switch (compression) { case BITMAP_RAW: - st->codec->codec_id = AV_CODEC_ID_IFF_ILBM; + st->codecpar->codec_id = AV_CODEC_ID_IFF_ILBM; break; case BITMAP_BYTERUN1: - st->codec->codec_id = AV_CODEC_ID_IFF_BYTERUN1; + st->codecpar->codec_id = AV_CODEC_ID_IFF_BYTERUN1; break; default: av_log(s, AV_LOG_ERROR, "unknown compression method\n"); diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c index e44af48..b8549f3 100644 --- a/libavformat/ilbc.c +++ b/libavformat/ilbc.c @@ -28,22 +28,22 @@ static const char mode30_header[] = "#!iLBC30\n"; static int ilbc_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - AVCodecContext *enc; + AVCodecParameters *par; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n"); return AVERROR(EINVAL); } - enc = s->streams[0]->codec; + par = s->streams[0]->codecpar; - if (enc->codec_id != AV_CODEC_ID_ILBC) { + if (par->codec_id != AV_CODEC_ID_ILBC) { av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); return AVERROR(EINVAL); } - if (enc->block_align == 50) { + if (par->block_align == 50) { avio_write(pb, mode30_header, sizeof(mode30_header) - 1); - } else if (enc->block_align == 38) { + } else if (par->block_align == 38) { avio_write(pb, mode20_header, sizeof(mode20_header) - 1); } else { av_log(s, AV_LOG_ERROR, "Unsupported mode\n"); @@ -79,18 +79,18 @@ static int ilbc_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_id = AV_CODEC_ID_ILBC; - st->codec->sample_rate = 8000; - st->codec->channels = 1; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ILBC; + st->codecpar->sample_rate = 8000; + st->codecpar->channels = 1; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->start_time = 0; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) { - st->codec->block_align = 38; - st->codec->bit_rate = 15200; + st->codecpar->block_align = 38; + st->codecpar->bit_rate = 15200; } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) { - st->codec->block_align = 50; - st->codec->bit_rate = 13333; + st->codecpar->block_align = 50; + st->codecpar->bit_rate = 13333; } else { av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n"); return AVERROR_INVALIDDATA; @@ -102,17 +102,17 @@ static int ilbc_read_header(AVFormatContext *s) static int ilbc_read_packet(AVFormatContext *s, AVPacket *pkt) { - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; int ret; - if ((ret = av_new_packet(pkt, enc->block_align)) < 0) + if ((ret = av_new_packet(pkt, par->block_align)) < 0) return ret; pkt->stream_index = 0; pkt->pos = avio_tell(s->pb); - pkt->duration = enc->block_align == 38 ? 160 : 240; - if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) { - av_free_packet(pkt); + pkt->duration = par->block_align == 38 ? 160 : 240; + if ((ret = avio_read(s->pb, pkt->data, par->block_align)) != par->block_align) { + av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } diff --git a/libavformat/img2.c b/libavformat/img2.c index 847c613..3cfc08e 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -23,7 +23,7 @@ #include "libavutil/avstring.h" #include "internal.h" -typedef struct { +typedef struct IdStrMap { enum AVCodecID id; const char *str; } IdStrMap; @@ -44,6 +44,7 @@ static const IdStrMap img_tags[] = { { AV_CODEC_ID_PBM, "pbm" }, { AV_CODEC_ID_PAM, "pam" }, { AV_CODEC_ID_ALIAS_PIX, "pix" }, + { AV_CODEC_ID_DDS, "dds" }, { AV_CODEC_ID_MPEG1VIDEO, "mpg1-img" }, { AV_CODEC_ID_MPEG2VIDEO, "mpg2-img" }, { AV_CODEC_ID_MPEG4, "mpg4-img" }, @@ -58,6 +59,9 @@ static const IdStrMap img_tags[] = { { AV_CODEC_ID_PTX, "ptx" }, { AV_CODEC_ID_BRENDER_PIX,"pix" }, { AV_CODEC_ID_PCX, "pcx" }, + { AV_CODEC_ID_QDRAW, "pic" }, + { AV_CODEC_ID_QDRAW, "pct" }, + { AV_CODEC_ID_QDRAW, "pict" }, { AV_CODEC_ID_SUNRAST, "sun" }, { AV_CODEC_ID_SUNRAST, "ras" }, { AV_CODEC_ID_SUNRAST, "rs" }, @@ -78,7 +82,7 @@ static const IdStrMap img_tags[] = { { AV_CODEC_ID_NONE, NULL } }; -static enum AVCodecID av_str2id(const IdStrMap *tags, const char *str) +static enum AVCodecID str2id(const IdStrMap *tags, const char *str) { str = strrchr(str, '.'); if (!str) @@ -96,5 +100,5 @@ static enum AVCodecID av_str2id(const IdStrMap *tags, const char *str) enum AVCodecID ff_guess_image2_codec(const char *filename) { - return av_str2id(img_tags, filename); + return str2id(img_tags, filename); } diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index b73554e..3d23831 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -28,7 +28,7 @@ #include "avformat.h" #include "internal.h" -typedef struct { +typedef struct VideoDemuxData { const AVClass *class; /**< Class for private options. */ int img_first; int img_last; @@ -184,8 +184,8 @@ static int img_read_header(AVFormatContext *s1) avpriv_set_pts_info(st, 60, framerate.den, framerate.num); if (width && height) { - st->codec->width = width; - st->codec->height = height; + st->codecpar->width = width; + st->codecpar->height = height; } if (!s->is_pipe) { @@ -201,18 +201,18 @@ static int img_read_header(AVFormatContext *s1) } if (s1->video_codec_id) { - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = s1->video_codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = s1->video_codec_id; } else if (s1->audio_codec_id) { - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s1->audio_codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s1->audio_codec_id; } else { - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ff_guess_image2_codec(s->path); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = ff_guess_image2_codec(s->path); } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != AV_PIX_FMT_NONE) - st->codec->pix_fmt = pix_fmt; + st->codecpar->format = pix_fmt; return 0; } @@ -224,7 +224,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) int i, res; int size[3] = { 0 }, ret[3] = { 0 }; AVIOContext *f[3] = { NULL }; - AVCodecContext *codec = s1->streams[0]->codec; + AVCodecParameters *par = s1->streams[0]->codecpar; if (!s->is_pipe) { /* loop over input */ @@ -238,8 +238,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) s->img_number) < 0 && s->img_number > 1) return AVERROR(EIO); for (i = 0; i < 3; i++) { - if (avio_open2(&f[i], filename, AVIO_FLAG_READ, - &s1->interrupt_callback, NULL) < 0) { + if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) { if (i >= 1) break; av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n", @@ -248,13 +247,13 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) } size[i] = avio_size(f[i]); - if (codec->codec_id != AV_CODEC_ID_RAWVIDEO) + if (par->codec_id != AV_CODEC_ID_RAWVIDEO) break; filename[strlen(filename) - 1] = 'U' + i; } - if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width) - infer_size(&codec->width, &codec->height, size[0]); + if (par->codec_id == AV_CODEC_ID_RAWVIDEO && !par->width) + infer_size(&par->width, &par->height, size[0]); } else { f[0] = s1->pb; if (f[0]->eof_reached) @@ -273,14 +272,14 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) if (f[i]) { ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]); if (!s->is_pipe) - avio_close(f[i]); + ff_format_io_close(s1, &f[i]); if (ret[i] > 0) pkt->size += ret[i]; } } if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); /* signal EOF */ } else { s->img_count++; diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 13e6828..a365771 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -28,7 +28,13 @@ #include "internal.h" #include "libavutil/opt.h" -typedef struct { +typedef struct RenameIO { + AVIOContext *pb; + char filename[1024]; + char tmp[1024]; +} RenameIO; + +typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ int img_number; int is_pipe; @@ -51,12 +57,30 @@ static int write_header(AVFormatContext *s) return 0; } +static int open_temporary(AVFormatContext *s, RenameIO *out, const char *filename) +{ + snprintf(out->tmp, sizeof(out->tmp), "%s.tmp", filename); + av_strlcpy(out->filename, filename, sizeof(out->filename)); + if (s->io_open(s, &out->pb, out->tmp, AVIO_FLAG_WRITE, NULL) < 0) { + av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", out->tmp); + return AVERROR(EIO); + } + + return 0; +} + +static void close_and_rename(AVFormatContext *s, RenameIO *out) +{ + ff_format_io_close(s, &out->pb); + ff_rename(out->tmp, out->filename); +} + static int write_packet(AVFormatContext *s, AVPacket *pkt) { VideoMuxData *img = s->priv_data; - AVIOContext *pb[3]; + RenameIO out[3]; char filename[1024]; - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; int i; if (!img->is_pipe) { @@ -70,57 +94,54 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); } for (i = 0; i < 3; i++) { - if (avio_open2(&pb[i], filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL) < 0) { - av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", filename); - return AVERROR(EIO); - } - - if (codec->codec_id != AV_CODEC_ID_RAWVIDEO) + int ret = open_temporary(s, &out[i], filename); + if (ret < 0) + return ret; + if (par->codec_id != AV_CODEC_ID_RAWVIDEO) break; filename[strlen(filename) - 1] = 'U' + i; } } else { - pb[0] = s->pb; + out[0].pb = s->pb; } - if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) { - int ysize = codec->width * codec->height; - avio_write(pb[0], pkt->data, ysize); - avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize) / 2); - avio_write(pb[2], pkt->data + ysize + (pkt->size - ysize) / 2, (pkt->size - ysize) / 2); - avio_close(pb[1]); - avio_close(pb[2]); + if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { + int ysize = par->width * par->height; + avio_write(out[0].pb, pkt->data, ysize); + avio_write(out[1].pb, pkt->data + ysize, (pkt->size - ysize) / 2); + avio_write(out[2].pb, pkt->data + ysize + (pkt->size - ysize) / 2, (pkt->size - ysize) / 2); + close_and_rename(s, &out[1]); + close_and_rename(s, &out[2]); } else { if (ff_guess_image2_codec(s->filename) == AV_CODEC_ID_JPEG2000) { AVStream *st = s->streams[0]; - if (st->codec->extradata_size > 8 && - AV_RL32(st->codec->extradata + 4) == MKTAG('j', 'p', '2', 'h')) { + if (st->codecpar->extradata_size > 8 && + AV_RL32(st->codecpar->extradata + 4) == MKTAG('j', 'p', '2', 'h')) { if (pkt->size < 8 || AV_RL32(pkt->data + 4) != MKTAG('j', 'p', '2', 'c')) goto error; - avio_wb32(pb[0], 12); - ffio_wfourcc(pb[0], "jP "); - avio_wb32(pb[0], 0x0D0A870A); // signature - avio_wb32(pb[0], 20); - ffio_wfourcc(pb[0], "ftyp"); - ffio_wfourcc(pb[0], "jp2 "); - avio_wb32(pb[0], 0); - ffio_wfourcc(pb[0], "jp2 "); - avio_write(pb[0], st->codec->extradata, st->codec->extradata_size); + avio_wb32(out[0].pb, 12); + ffio_wfourcc(out[0].pb, "jP "); + avio_wb32(out[0].pb, 0x0D0A870A); // signature + avio_wb32(out[0].pb, 20); + ffio_wfourcc(out[0].pb, "ftyp"); + ffio_wfourcc(out[0].pb, "jp2 "); + avio_wb32(out[0].pb, 0); + ffio_wfourcc(out[0].pb, "jp2 "); + avio_write(out[0].pb, st->codecpar->extradata, st->codecpar->extradata_size); } else if (pkt->size < 8 || - (!st->codec->extradata_size && + (!st->codecpar->extradata_size && AV_RL32(pkt->data + 4) != MKTAG('j', 'P', ' ', ' '))) { // signature error: av_log(s, AV_LOG_ERROR, "malformed JPEG 2000 codestream\n"); return -1; } } - avio_write(pb[0], pkt->data, pkt->size); + avio_write(out[0].pb, pkt->data, pkt->size); } - avio_flush(pb[0]); + avio_flush(out[0].pb); if (!img->is_pipe) { - avio_close(pb[0]); + close_and_rename(s, &out[0]); } img->img_number++; diff --git a/libavformat/ingenientdec.c b/libavformat/ingenientdec.c index 42b29ef..2bb70e7 100644 --- a/libavformat/ingenientdec.c +++ b/libavformat/ingenientdec.c @@ -51,7 +51,7 @@ static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; ret = avio_read(s->pb, pkt->data, size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } pkt->size = ret; diff --git a/libavformat/internal.h b/libavformat/internal.h index 8a9a88f..de55af5 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -23,6 +23,7 @@ #include #include "avformat.h" +#include "os_support.h" #define MAX_URL_SIZE 4096 @@ -48,6 +49,75 @@ struct AVFormatInternal { * Muxing only. */ int nb_interleaved_streams; + + /** + * 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; + struct AVPacketList *packet_buffer_end; + + /* av_seek_frame() support */ + int64_t data_offset; /**< offset of the first packet */ + + /** + * Raw packets from the demuxer, prior to parsing and decoding. + * This buffer is used for buffering packets until the codec can + * be identified, as parsing cannot be done without knowing the + * codec. + */ + struct AVPacketList *raw_packet_buffer; + struct AVPacketList *raw_packet_buffer_end; + /** + * Packets split by the parser get queued here. + */ + struct AVPacketList *parse_queue; + struct AVPacketList *parse_queue_end; + /** + * Remaining size available for raw_packet_buffer, in bytes. + */ +#define RAW_PACKET_BUFFER_SIZE 2500000 + int raw_packet_buffer_remaining_size; + + /** + * Offset to remap timestamps to be non-negative. + * Expressed in timebase units. + */ + int64_t offset; + + /** + * Timebase for the timestamp offset. + */ + AVRational offset_timebase; + +#if FF_API_COMPUTE_PKT_FIELDS2 + int missing_ts_warning; +#endif +}; + +struct AVStreamInternal { + /** + * Set to 1 if the codec allows reordering, so pts can be different + * from dts. + */ + int reorder; + /** + * The codec context used by avformat_find_stream_info, the parser, etc. + */ + AVCodecContext *avctx; + /** + * 1 if avctx has been initialized with the values from the codec parameters + */ + int avctx_inited; + + enum AVCodecID orig_codec_id; + +#if FF_API_LAVF_AVCTX + // whether the deprecated stream codec context needs + // to be filled from the codec parameters + int need_codec_update; +#endif }; void ff_dynarray_add(intptr_t **tab_ptr, int *nb_ptr, intptr_t elem); @@ -306,7 +376,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt); * 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 that calling av_free_packet() + * function, so they cannot be used after it. Note that calling av_packet_unref() * on them is still safe. * * @param s media file handle @@ -323,11 +393,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, /** * Return the frame duration in seconds. Return 0 if not available. */ -void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st, +void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st, AVCodecParserContext *pc, AVPacket *pkt); -int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux); - unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id); enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag); @@ -367,4 +435,21 @@ static inline int ff_rename(const char *oldpath, const char *newpath) return 0; } +/** + * A wrapper around AVFormatContext.io_close that should be used + * instead of calling the pointer directly. + */ +void ff_format_io_close(AVFormatContext *s, AVIOContext **pb); + +/** + * Find the next packet in the interleaving queue for the given stream. + * The pkt parameter is filled in with the queued packet, including + * references to the data (which the caller is not allowed to keep or + * modify). + * + * @return 0 if a packet was found, a negative value if no packet was found + */ +int ff_interleaved_peek(AVFormatContext *s, int stream, + AVPacket *pkt, int add_offset); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index 60ae939..b719fed 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -1,6 +1,6 @@ /* * Interplay MVE File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -147,7 +147,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, s->audio_frame_count += (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels; - av_dlog(NULL, "sending audio frame with pts %"PRId64" (%d audio frames)\n", + av_log(NULL, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n", pkt->pts, s->audio_frame_count); chunk_type = CHUNK_VIDEO; @@ -180,7 +180,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, if (avio_read(pb, pkt->data, s->decode_map_chunk_size) != s->decode_map_chunk_size) { - av_free_packet(pkt); + av_packet_unref(pkt); return CHUNK_EOF; } @@ -189,14 +189,14 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, if (avio_read(pb, pkt->data + s->decode_map_chunk_size, s->video_chunk_size) != s->video_chunk_size) { - av_free_packet(pkt); + av_packet_unref(pkt); return CHUNK_EOF; } pkt->stream_index = s->video_stream_index; pkt->pts = s->video_pts; - av_dlog(NULL, "sending video frame with pts %"PRId64"\n", pkt->pts); + av_log(NULL, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts); s->video_pts += s->frame_pts_inc; @@ -245,36 +245,36 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, chunk_size = AV_RL16(&chunk_preamble[0]); chunk_type = AV_RL16(&chunk_preamble[2]); - av_dlog(NULL, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size); + av_log(NULL, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size); switch (chunk_type) { case CHUNK_INIT_AUDIO: - av_dlog(NULL, "initialize audio\n"); + av_log(NULL, AV_LOG_TRACE, "initialize audio\n"); break; case CHUNK_AUDIO_ONLY: - av_dlog(NULL, "audio only\n"); + av_log(NULL, AV_LOG_TRACE, "audio only\n"); break; case CHUNK_INIT_VIDEO: - av_dlog(NULL, "initialize video\n"); + av_log(NULL, AV_LOG_TRACE, "initialize video\n"); break; case CHUNK_VIDEO: - av_dlog(NULL, "video (and audio)\n"); + av_log(NULL, AV_LOG_TRACE, "video (and audio)\n"); break; case CHUNK_SHUTDOWN: - av_dlog(NULL, "shutdown\n"); + av_log(NULL, AV_LOG_TRACE, "shutdown\n"); break; case CHUNK_END: - av_dlog(NULL, "end\n"); + av_log(NULL, AV_LOG_TRACE, "end\n"); break; default: - av_dlog(NULL, "invalid chunk\n"); + av_log(NULL, AV_LOG_TRACE, "invalid chunk\n"); chunk_type = CHUNK_BAD; break; @@ -300,29 +300,29 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, chunk_size -= OPCODE_PREAMBLE_SIZE; chunk_size -= opcode_size; if (chunk_size < 0) { - av_dlog(NULL, "chunk_size countdown just went negative\n"); + av_log(NULL, AV_LOG_TRACE, "chunk_size countdown just went negative\n"); chunk_type = CHUNK_BAD; break; } - av_dlog(NULL, " opcode type %02X, version %d, 0x%04X bytes: ", + av_log(NULL, AV_LOG_TRACE, " opcode type %02X, version %d, 0x%04X bytes: ", opcode_type, opcode_version, opcode_size); switch (opcode_type) { case OPCODE_END_OF_STREAM: - av_dlog(NULL, "end of stream\n"); + av_log(NULL, AV_LOG_TRACE, "end of stream\n"); avio_skip(pb, opcode_size); break; case OPCODE_END_OF_CHUNK: - av_dlog(NULL, "end of chunk\n"); + av_log(NULL, AV_LOG_TRACE, "end of chunk\n"); avio_skip(pb, opcode_size); break; case OPCODE_CREATE_TIMER: - av_dlog(NULL, "create timer\n"); + av_log(NULL, AV_LOG_TRACE, "create timer\n"); if ((opcode_version > 0) || (opcode_size > 6)) { - av_dlog(NULL, "bad create_timer opcode\n"); + av_log(NULL, AV_LOG_TRACE, "bad create_timer opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -332,15 +332,15 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; } s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]); - av_dlog(NULL, " %.2f frames/second (timer div = %d, subdiv = %d)\n", + av_log(NULL, AV_LOG_TRACE, " %.2f frames/second (timer div = %d, subdiv = %d)\n", 1000000.0 / s->frame_pts_inc, AV_RL32(&scratch[0]), AV_RL16(&scratch[4])); break; case OPCODE_INIT_AUDIO_BUFFERS: - av_dlog(NULL, "initialize audio buffers\n"); + av_log(NULL, AV_LOG_TRACE, "initialize audio buffers\n"); if ((opcode_version > 1) || (opcode_size > 10)) { - av_dlog(NULL, "bad init_audio_buffers opcode\n"); + av_log(NULL, AV_LOG_TRACE, "bad init_audio_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -362,7 +362,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, s->audio_type = AV_CODEC_ID_PCM_S16LE; else s->audio_type = AV_CODEC_ID_PCM_U8; - av_dlog(NULL, "audio: %d bits, %d Hz, %s, %s format\n", + av_log(NULL, AV_LOG_TRACE, "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 == AV_CODEC_ID_INTERPLAY_DPCM) ? @@ -370,14 +370,14 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_START_STOP_AUDIO: - av_dlog(NULL, "start/stop audio\n"); + av_log(NULL, AV_LOG_TRACE, "start/stop audio\n"); avio_skip(pb, opcode_size); break; case OPCODE_INIT_VIDEO_BUFFERS: - av_dlog(NULL, "initialize video buffers\n"); + av_log(NULL, AV_LOG_TRACE, "initialize video buffers\n"); if ((opcode_version > 2) || (opcode_size > 8)) { - av_dlog(NULL, "bad init_video_buffers opcode\n"); + av_log(NULL, AV_LOG_TRACE, "bad init_video_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -401,7 +401,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, } else { s->video_bpp = 16; } - av_dlog(NULL, "video resolution: %d x %d\n", + av_log(NULL, AV_LOG_TRACE, "video resolution: %d x %d\n", s->video_width, s->video_height); break; @@ -412,17 +412,17 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, case OPCODE_UNKNOWN_13: case OPCODE_UNKNOWN_14: case OPCODE_UNKNOWN_15: - av_dlog(NULL, "unknown (but documented) opcode %02X\n", opcode_type); + av_log(NULL, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type); avio_skip(pb, opcode_size); break; case OPCODE_SEND_BUFFER: - av_dlog(NULL, "send buffer\n"); + av_log(NULL, AV_LOG_TRACE, "send buffer\n"); avio_skip(pb, opcode_size); break; case OPCODE_AUDIO_FRAME: - av_dlog(NULL, "audio frame\n"); + av_log(NULL, AV_LOG_TRACE, "audio frame\n"); /* log position and move on for now */ s->audio_chunk_offset = avio_tell(pb); @@ -431,26 +431,26 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_SILENCE_FRAME: - av_dlog(NULL, "silence frame\n"); + av_log(NULL, AV_LOG_TRACE, "silence frame\n"); avio_skip(pb, opcode_size); break; case OPCODE_INIT_VIDEO_MODE: - av_dlog(NULL, "initialize video mode\n"); + av_log(NULL, AV_LOG_TRACE, "initialize video mode\n"); avio_skip(pb, opcode_size); break; case OPCODE_CREATE_GRADIENT: - av_dlog(NULL, "create gradient\n"); + av_log(NULL, AV_LOG_TRACE, "create gradient\n"); avio_skip(pb, opcode_size); break; case OPCODE_SET_PALETTE: - av_dlog(NULL, "set palette\n"); + av_log(NULL, AV_LOG_TRACE, "set palette\n"); /* check for the logical maximum palette size * (3 * 256 + 4 bytes) */ if (opcode_size > 0x304) { - av_dlog(NULL, "demux_ipmovie: set_palette opcode too large\n"); + av_log(NULL, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode too large\n"); chunk_type = CHUNK_BAD; break; } @@ -464,7 +464,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, last_color = first_color + AV_RL16(&scratch[2]) - 1; /* sanity check (since they are 16 bit values) */ if ((first_color > 0xFF) || (last_color > 0xFF)) { - av_dlog(NULL, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n", + av_log(NULL, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n", first_color, last_color); chunk_type = CHUNK_BAD; break; @@ -482,12 +482,12 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_SET_PALETTE_COMPRESSED: - av_dlog(NULL, "set palette compressed\n"); + av_log(NULL, AV_LOG_TRACE, "set palette compressed\n"); avio_skip(pb, opcode_size); break; case OPCODE_SET_DECODING_MAP: - av_dlog(NULL, "set decoding map\n"); + av_log(NULL, AV_LOG_TRACE, "set decoding map\n"); /* log position and move on for now */ s->decode_map_chunk_offset = avio_tell(pb); @@ -496,7 +496,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_VIDEO_DATA: - av_dlog(NULL, "set video data\n"); + av_log(NULL, AV_LOG_TRACE, "set video data\n"); /* log position and move on for now */ s->video_chunk_offset = avio_tell(pb); @@ -505,7 +505,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; default: - av_dlog(NULL, "*** unknown opcode type\n"); + av_log(NULL, AV_LOG_TRACE, "*** unknown opcode type\n"); chunk_type = CHUNK_BAD; break; @@ -584,12 +584,12 @@ static int ipmovie_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 63, 1, 1000000); ipmovie->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = ipmovie->video_width; - st->codec->height = ipmovie->video_height; - st->codec->bits_per_coded_sample = ipmovie->video_bpp; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = ipmovie->video_width; + st->codecpar->height = ipmovie->video_height; + st->codecpar->bits_per_coded_sample = ipmovie->video_bpp; if (ipmovie->audio_type) { st = avformat_new_stream(s, NULL); @@ -597,19 +597,19 @@ static int ipmovie_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate); ipmovie->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = ipmovie->audio_type; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = ipmovie->audio_channels; - st->codec->channel_layout = st->codec->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = ipmovie->audio_sample_rate; - st->codec->bits_per_coded_sample = ipmovie->audio_bits; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample; - if (st->codec->codec_id == AV_CODEC_ID_INTERPLAY_DPCM) - st->codec->bit_rate /= 2; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = ipmovie->audio_type; + st->codecpar->codec_tag = 0; /* no tag */ + st->codecpar->channels = ipmovie->audio_channels; + st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = ipmovie->audio_sample_rate; + st->codecpar->bits_per_coded_sample = ipmovie->audio_bits; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM) + st->codecpar->bit_rate /= 2; + st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; } return 0; diff --git a/libavformat/isom.c b/libavformat/isom.c index 5d10dca..0183563 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -38,15 +38,15 @@ const AVCodecTag ff_mp4_obj_type[] = { { AV_CODEC_ID_HEVC , 0x23 }, { AV_CODEC_ID_AAC , 0x40 }, { AV_CODEC_ID_MP4ALS , 0x40 }, /* 14496-3 ALS */ - { AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG2 Main */ - { AV_CODEC_ID_MPEG2VIDEO , 0x60 }, /* MPEG2 Simple */ - { AV_CODEC_ID_MPEG2VIDEO , 0x62 }, /* MPEG2 SNR */ - { AV_CODEC_ID_MPEG2VIDEO , 0x63 }, /* MPEG2 Spatial */ - { AV_CODEC_ID_MPEG2VIDEO , 0x64 }, /* MPEG2 High */ - { AV_CODEC_ID_MPEG2VIDEO , 0x65 }, /* MPEG2 422 */ - { AV_CODEC_ID_AAC , 0x66 }, /* MPEG2 AAC Main */ - { AV_CODEC_ID_AAC , 0x67 }, /* MPEG2 AAC Low */ - { AV_CODEC_ID_AAC , 0x68 }, /* MPEG2 AAC SSR */ + { AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG-2 Main */ + { AV_CODEC_ID_MPEG2VIDEO , 0x60 }, /* MPEG-2 Simple */ + { AV_CODEC_ID_MPEG2VIDEO , 0x62 }, /* MPEG-2 SNR */ + { AV_CODEC_ID_MPEG2VIDEO , 0x63 }, /* MPEG-2 Spatial */ + { AV_CODEC_ID_MPEG2VIDEO , 0x64 }, /* MPEG-2 High */ + { AV_CODEC_ID_MPEG2VIDEO , 0x65 }, /* MPEG-2 422 */ + { AV_CODEC_ID_AAC , 0x66 }, /* MPEG-2 AAC Main */ + { AV_CODEC_ID_AAC , 0x67 }, /* MPEG-2 AAC Low */ + { AV_CODEC_ID_AAC , 0x68 }, /* MPEG-2 AAC SSR */ { AV_CODEC_ID_MP3 , 0x69 }, /* 13818-3 */ { AV_CODEC_ID_MP2 , 0x69 }, /* 11172-3 */ { AV_CODEC_ID_MPEG1VIDEO , 0x6A }, /* 11172-2 */ @@ -58,8 +58,9 @@ const AVCodecTag ff_mp4_obj_type[] = { { AV_CODEC_ID_DIRAC , 0xA4 }, { AV_CODEC_ID_AC3 , 0xA5 }, { AV_CODEC_ID_DTS , 0xA9 }, /* mp4ra.org */ - { AV_CODEC_ID_VORBIS , 0xDD }, /* non standard, gpac uses it */ - { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* non standard, see unsupported-embedded-subs-2.mp4 */ + { AV_CODEC_ID_TSCC2 , 0xD0 }, /* nonstandard, camtasia uses it */ + { AV_CODEC_ID_VORBIS , 0xDD }, /* nonstandard, gpac uses it */ + { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* nonstandard, see unsupported-embedded-subs-2.mp4 */ { AV_CODEC_ID_QCELP , 0xE1 }, { AV_CODEC_ID_MPEG4SYSTEMS, 0x01 }, { AV_CODEC_ID_MPEG4SYSTEMS, 0x02 }, @@ -69,11 +70,11 @@ const AVCodecTag ff_mp4_obj_type[] = { const AVCodecTag ff_codec_movvideo_tags[] = { /* { AV_CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* Uncompressed RGB */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* Uncompressed YUV422 */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, /* YUV with alpha-channel (AVID Uncompressed) */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2vuy but byte swapped */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* uncompressed RGB */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* uncompressed YUV422 */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, /* YUV with alpha-channel (AVID uncompressed) */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* uncompressed 8-bit 4:2:2 */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2VUY but byte-swapped */ { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '5', '5') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '6', '5') }, @@ -92,12 +93,12 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '2', '0') }, /* Radius DV YUV PAL */ { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '1', '1') }, /* Radius DV YUV NTSC */ - { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'k') }, /* UNCOMPRESSED 10BIT RGB */ - { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'g') }, /* UNCOMPRESSED 10BIT RGB */ - { AV_CODEC_ID_R210, MKTAG('r', '2', '1', '0') }, /* UNCOMPRESSED 10BIT RGB */ - { AV_CODEC_ID_V210, MKTAG('v', '2', '1', '0') }, /* UNCOMPRESSED 10BIT 4:2:2 */ - { AV_CODEC_ID_V210, MKTAG('b', 'x', 'y', '2') }, /* BOXX 10BIT 4:2:2 */ - { AV_CODEC_ID_V410, MKTAG('v', '4', '1', '0') }, /* UNCOMPRESSED 10BIT 4:4:4 */ + { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'k') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'g') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_R210, MKTAG('r', '2', '1', '0') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_V210, MKTAG('v', '2', '1', '0') }, /* uncompressed 10-bit 4:2:2 */ + { AV_CODEC_ID_V210, MKTAG('b', 'x', 'y', '2') }, /* BOXX 10-bit 4:2:2 */ + { AV_CODEC_ID_V410, MKTAG('v', '4', '1', '0') }, /* uncompressed 10-bit 4:4:4 */ { AV_CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */ { AV_CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */ @@ -116,8 +117,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, { AV_CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */ - { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */ - { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */ + { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H.263 */ + { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H.263 ?? works */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */ @@ -164,28 +165,30 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '5') }, /* AVC-Intra 100M 1080i50 */ { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '6') }, /* AVC-Intra 100M 1080i60 */ { AV_CODEC_ID_H264, MKTAG('A', 'V', 'i', 'n') }, /* AVC-Intra with implicit SPS/PPS */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 4:2:2 10bit */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 10-bit 4:2:2 */ + { AV_CODEC_ID_H264, MKTAG('r', 'v', '6', '4') }, /* X-Com Radvision */ { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') }, { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple MPEG-1 Camcorder */ { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */ + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '1', 'v') }, /* CoreMedia CMVideoCodecType */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', '2', 'v', '1') }, /* Apple MPEG-2 Camcorder */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG2 HDV 720p30 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 HDV 1080i60 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG2 HDV 1080i50 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG2 HDV 720p24 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG2 HDV 720p25 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG2 HDV 1080p24 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG2 HDV 1080p25 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG2 HDV 1080p30 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG2 HDV 720p60 JVC */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG2 HDV 720p50 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG2 IMX PAL 625/50 40mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG-2 HDV 720p30 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG-2 HDV 1080i60 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG-2 HDV 1080i50 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG-2 HDV 720p24 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG-2 HDV 720p25 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG-2 HDV 1080p24 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG-2 HDV 1080p25 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG-2 HDV 1080p30 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG-2 HDV 720p60 JVC */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG-2 HDV 720p50 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG-2 IMX NTSC 525/60 50mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG-2 IMX PAL 625/50 50mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG-2 IMX NTSC 525/60 40mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG-2 IMX PAL 625/50 40mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG-2 IMX NTSC 525/60 30mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG-2 IMX PAL 625/50 30mb/s produced by FCP */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '1') }, /* XDCAM HD422 720p30 CBR */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '4') }, /* XDCAM HD422 720p24 CBR */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '5') }, /* XDCAM HD422 720p25 CBR */ @@ -242,10 +245,26 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 's') }, /* Apple ProRes 422 LT */ { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'o') }, /* Apple ProRes 422 Proxy */ { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'h') }, /* Apple ProRes 4444 */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'x') }, /* Apple ProRes 4444 XQ */ { AV_CODEC_ID_FLIC, MKTAG('f', 'l', 'i', 'c') }, { AV_CODEC_ID_AIC, MKTAG('i', 'c', 'o', 'd') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '1') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '5') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'Y') }, + + { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', '3') }, + { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', 'I') }, + + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'G') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'A') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'G', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') }, + { AV_CODEC_ID_NONE, 0 }, }; @@ -310,7 +329,7 @@ const AVCodecTag ff_codec_movsubtitle_tags[] = { /* 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 */ +/* deprecated by putting the code as 3*5 bits ASCII */ static const char mov_mdhd_language_map[][4] = { /* 0-9 */ "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor", @@ -348,7 +367,7 @@ int ff_mov_iso639_to_lang(const char lang[4], int mp4) /* handle undefined as such */ if (lang[0] == '\0') lang = "und"; - /* 5bit ascii */ + /* 5 bits ASCII */ for (i = 0; i < 3; i++) { uint8_t c = lang[i]; c -= 0x60; @@ -400,7 +419,7 @@ int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag) int len; *tag = avio_r8(pb); len = ff_mp4_read_descr_len(pb); - av_dlog(fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len); + av_log(fc, AV_LOG_TRACE, "MPEG-4 description: tag=0x%02x len=%d\n", *tag, len); return len; } @@ -438,37 +457,37 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext avio_rb32(pb); /* max bitrate */ avio_rb32(pb); /* avg bitrate */ - st->codec->codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id); - av_dlog(fc, "esds object type id 0x%02x\n", object_type_id); + st->codecpar->codec_id = ff_codec_get_id(ff_mp4_obj_type, object_type_id); + av_log(fc, AV_LOG_TRACE, "esds object type id 0x%02x\n", object_type_id); len = ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4DecSpecificDescrTag) { - av_dlog(fc, "Specific MPEG4 header len=%d\n", len); + av_log(fc, AV_LOG_TRACE, "Specific MPEG-4 header len=%d\n", len); if (!len || (uint64_t)len > (1<<30)) return -1; - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(len + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - avio_read(pb, st->codec->extradata, len); - st->codec->extradata_size = len; - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + avio_read(pb, st->codecpar->extradata, len); + st->codecpar->extradata_size = len; + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { MPEG4AudioConfig cfg; - avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata, - st->codec->extradata_size * 8, 1); - st->codec->channels = cfg.channels; + avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata, + st->codecpar->extradata_size * 8, 1); + st->codecpar->channels = cfg.channels; if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 - st->codec->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index]; + st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index]; else if (cfg.ext_sample_rate) - st->codec->sample_rate = cfg.ext_sample_rate; + st->codecpar->sample_rate = cfg.ext_sample_rate; else - st->codec->sample_rate = cfg.sample_rate; - av_dlog(fc, "mp4a config channels %d obj %d ext obj %d " - "sample rate %d ext sample rate %d\n", st->codec->channels, + st->codecpar->sample_rate = cfg.sample_rate; + av_log(fc, AV_LOG_TRACE, "mp4a config channels %d obj %d ext obj %d " + "sample rate %d ext sample rate %d\n", st->codecpar->channels, cfg.object_type, cfg.ext_object_type, cfg.sample_rate, cfg.ext_sample_rate); - if (!(st->codec->codec_id = ff_codec_get_id(mp4_audio_types, + if (!(st->codecpar->codec_id = ff_codec_get_id(mp4_audio_types, cfg.object_type))) - st->codec->codec_id = AV_CODEC_ID_AAC; + st->codecpar->codec_id = AV_CODEC_ID_AAC; } } return 0; diff --git a/libavformat/isom.h b/libavformat/isom.h index 0bc912a..58f0a20 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -105,6 +105,8 @@ typedef struct MOVStreamContext { MOVStts *ctts_data; unsigned int stsc_count; MOVStsc *stsc_data; + int stsc_index; + int stsc_sample; unsigned int stps_count; unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop int ctts_index; @@ -126,7 +128,6 @@ typedef struct MOVStreamContext { unsigned drefs_count; MOVDref *drefs; int dref_id; - int wrong_dts; ///< dts are wrong due to huge ctts offset (iMovie files) int width; ///< tkhd width int height; ///< tkhd height int dts_shift; ///< dts shift when ctts is negative @@ -137,10 +138,17 @@ typedef struct MOVStreamContext { unsigned int rap_group_count; MOVSbgp *rap_group; + /** extradata array (and size) for multiple stsd */ + uint8_t **extradata; + int *extradata_size; + int last_stsd_index; + int stsd_count; + int32_t *display_matrix; } MOVStreamContext; typedef struct MOVContext { + const AVClass *class; ///< class for private options AVFormatContext *fc; int time_scale; int64_t duration; ///< duration of the longest track @@ -154,7 +162,11 @@ typedef struct MOVContext { unsigned trex_count; int itunes_metadata; ///< metadata are itunes style int chapter_track; + int seek_individually; int64_t next_root_atom; ///< offset of the next root atom + int export_all; + int export_xmp; + int enable_drefs; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/libavformat/iss.c b/libavformat/iss.c index 3f7f4fe..1653b27 100644 --- a/libavformat/iss.c +++ b/libavformat/iss.c @@ -35,7 +35,7 @@ #define ISS_SIG_LEN 15 #define MAX_TOKEN_SIZE 20 -typedef struct { +typedef struct IssDemuxContext { int packet_size; int sample_start_pos; } IssDemuxContext; @@ -93,23 +93,23 @@ static av_cold int iss_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS; if (stereo) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - st->codec->sample_rate = 44100; + st->codecpar->sample_rate = 44100; if(rate_divisor > 0) - st->codec->sample_rate /= rate_divisor; - st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate - * st->codec->bits_per_coded_sample; - st->codec->block_align = iss->packet_size; - avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); + st->codecpar->sample_rate /= rate_divisor; + st->codecpar->bits_per_coded_sample = 4; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate + * st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = iss->packet_size; + avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); return 0; } @@ -124,8 +124,8 @@ static int iss_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; pkt->pts = avio_tell(s->pb) - iss->sample_start_pos; - if(s->streams[0]->codec->channels > 0) - pkt->pts /= s->streams[0]->codec->channels*2; + if(s->streams[0]->codecpar->channels > 0) + pkt->pts /= s->streams[0]->codecpar->channels*2; return 0; } diff --git a/libavformat/iv8.c b/libavformat/iv8.c index 56909e3..1fa88c4 100644 --- a/libavformat/iv8.c +++ b/libavformat/iv8.c @@ -45,8 +45,8 @@ static int read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG4; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG4; st->need_parsing = AVSTREAM_PARSE_FULL; avpriv_set_pts_info(st, 64, 1, 90000); @@ -92,7 +92,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_append_packet(s->pb, pkt, size); if (ret < 0) { av_log(s, AV_LOG_ERROR, "failed to grow packet\n"); - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } } diff --git a/libavformat/ivfdec.c b/libavformat/ivfdec.c index b3555f4..a602f7c 100644 --- a/libavformat/ivfdec.c +++ b/libavformat/ivfdec.c @@ -46,11 +46,11 @@ static int read_header(AVFormatContext *s) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = avio_rl32(s->pb); - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codec->codec_tag); - st->codec->width = avio_rl16(s->pb); - st->codec->height = avio_rl16(s->pb); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = avio_rl32(s->pb); + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codecpar->codec_tag); + st->codecpar->width = avio_rl16(s->pb); + st->codecpar->height = avio_rl16(s->pb); time_base.den = avio_rl32(s->pb); time_base.num = avio_rl32(s->pb); st->duration = avio_rl64(s->pb); diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 3cd1616..1e57106 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -22,24 +22,24 @@ static int ivf_write_header(AVFormatContext *s) { - AVCodecContext *ctx; + AVCodecParameters *par; AVIOContext *pb = s->pb; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "Format supports only exactly one video stream\n"); return AVERROR(EINVAL); } - ctx = s->streams[0]->codec; - if (ctx->codec_type != AVMEDIA_TYPE_VIDEO || ctx->codec_id != AV_CODEC_ID_VP8) { + par = s->streams[0]->codecpar; + if (par->codec_type != AVMEDIA_TYPE_VIDEO || par->codec_id != AV_CODEC_ID_VP8) { av_log(s, AV_LOG_ERROR, "Currently only VP8 is supported!\n"); return AVERROR(EINVAL); } avio_write(pb, "DKIF", 4); avio_wl16(pb, 0); // version avio_wl16(pb, 32); // header length - avio_wl32(pb, ctx->codec_tag ? ctx->codec_tag : AV_RL32("VP80")); - avio_wl16(pb, ctx->width); - avio_wl16(pb, ctx->height); + avio_wl32(pb, par->codec_tag ? par->codec_tag : AV_RL32("VP80")); + avio_wl16(pb, par->width); + avio_wl16(pb, par->height); avio_wl32(pb, s->streams[0]->time_base.den); avio_wl32(pb, s->streams[0]->time_base.num); avio_wl64(pb, s->streams[0]->duration); // TODO: duration or number of frames?!? diff --git a/libavformat/jvdec.c b/libavformat/jvdec.c index 84d55da..7fc3131 100644 --- a/libavformat/jvdec.c +++ b/libavformat/jvdec.c @@ -33,14 +33,14 @@ #define JV_PREAMBLE_SIZE 5 -typedef struct { +typedef struct JVFrame { int audio_size; /** audio packet size (bytes) */ int video_size; /** video packet size (bytes) */ int palette_size; /** palette size (bytes) */ int video_type; /** per-frame video compression type */ } JVFrame; -typedef struct { +typedef struct JVDemuxContext { JVFrame *frames; enum { JV_AUDIO = 0, @@ -85,11 +85,11 @@ static int read_header(AVFormatContext *s) if (!ast || !vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_JV; - vst->codec->codec_tag = 0; /* no fourcc */ - vst->codec->width = avio_rl16(pb); - vst->codec->height = avio_rl16(pb); + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_JV; + vst->codecpar->codec_tag = 0; /* no fourcc */ + vst->codecpar->width = avio_rl16(pb); + vst->codecpar->height = avio_rl16(pb); vst->duration = vst->nb_frames = ast->nb_index_entries = avio_rl16(pb); @@ -97,13 +97,13 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 4); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; - ast->codec->codec_tag = 0; /* no fourcc */ - ast->codec->sample_rate = avio_rl16(pb); - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->codec_tag = 0; /* no fourcc */ + ast->codecpar->sample_rate = avio_rl16(pb); + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); avio_skip(pb, 10); @@ -196,7 +196,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) return ret; if (ret < size) { memset(pkt->data + JV_PREAMBLE_SIZE + ret, 0, - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); pkt->flags |= AV_PKT_FLAG_CORRUPT; } pkt->size = ret + JV_PREAMBLE_SIZE; diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index e5e2f87..a98a6ff 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -26,7 +26,7 @@ #include "libavutil/opt.h" #include "avformat.h" -typedef struct { +typedef struct LATMContext { AVClass *av_class; int off; int channel_conf; @@ -74,10 +74,10 @@ static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) static int latm_write_header(AVFormatContext *s) { LATMContext *ctx = s->priv_data; - AVCodecContext *avctx = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; - if (avctx->extradata_size > 0 && - latm_decode_extradata(ctx, avctx->extradata, avctx->extradata_size) < 0) + if (par->extradata_size > 0 && + latm_decode_extradata(ctx, par->extradata, par->extradata_size) < 0) return AVERROR_INVALIDDATA; return 0; @@ -86,7 +86,7 @@ static int latm_write_header(AVFormatContext *s) static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) { LATMContext *ctx = s->priv_data; - AVCodecContext *avctx = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; GetBitContext gb; int header_size; @@ -94,7 +94,7 @@ static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) put_bits(bs, 1, !!ctx->counter); if (!ctx->counter) { - init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8); + init_get_bits(&gb, par->extradata, par->extradata_size * 8); /* StreamMuxConfig */ put_bits(bs, 1, 0); /* audioMuxVersion */ @@ -105,10 +105,10 @@ static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) /* AudioSpecificConfig */ if (ctx->object_type == AOT_ALS) { - header_size = avctx->extradata_size-(ctx->off + 7) >> 3; - avpriv_copy_bits(bs, &avctx->extradata[ctx->off], header_size); + header_size = par->extradata_size-(ctx->off + 7) >> 3; + avpriv_copy_bits(bs, &par->extradata[ctx->off], header_size); } else { - avpriv_copy_bits(bs, avctx->extradata, ctx->off + 3); + avpriv_copy_bits(bs, par->extradata, ctx->off + 3); if (!ctx->channel_conf) { avpriv_copy_pce_data(bs, &gb); diff --git a/libavformat/libavformat.v b/libavformat/libavformat.v index 6f11d60..47d5ddc 100644 --- a/libavformat/libavformat.v +++ b/libavformat/libavformat.v @@ -1,4 +1,6 @@ -LIBAVFORMAT_$MAJOR { - global: av*; - local: *; +LIBAVFORMAT_MAJOR { + global: + av*; + local: + *; }; diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index fac3a35..97c8ad6 100644 --- a/libavformat/librtmp.c +++ b/libavformat/librtmp.c @@ -189,6 +189,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) if (sep) p = sep + 1; + else + break; } } if (ctx->playpath) { @@ -320,7 +322,7 @@ static const AVClass lib ## flavor ## _class = {\ }; RTMP_CLASS(rtmp) -URLProtocol ff_librtmp_protocol = { +const URLProtocol ff_librtmp_protocol = { .name = "rtmp", .url_open = rtmp_open, .url_read = rtmp_read, @@ -335,7 +337,7 @@ URLProtocol ff_librtmp_protocol = { }; RTMP_CLASS(rtmpt) -URLProtocol ff_librtmpt_protocol = { +const URLProtocol ff_librtmpt_protocol = { .name = "rtmpt", .url_open = rtmp_open, .url_read = rtmp_read, @@ -350,7 +352,7 @@ URLProtocol ff_librtmpt_protocol = { }; RTMP_CLASS(rtmpe) -URLProtocol ff_librtmpe_protocol = { +const URLProtocol ff_librtmpe_protocol = { .name = "rtmpe", .url_open = rtmp_open, .url_read = rtmp_read, @@ -365,7 +367,7 @@ URLProtocol ff_librtmpe_protocol = { }; RTMP_CLASS(rtmpte) -URLProtocol ff_librtmpte_protocol = { +const URLProtocol ff_librtmpte_protocol = { .name = "rtmpte", .url_open = rtmp_open, .url_read = rtmp_read, @@ -380,7 +382,7 @@ URLProtocol ff_librtmpte_protocol = { }; RTMP_CLASS(rtmps) -URLProtocol ff_librtmps_protocol = { +const URLProtocol ff_librtmps_protocol = { .name = "rtmps", .url_open = rtmp_open, .url_read = rtmp_read, diff --git a/libavformat/lmlm4.c b/libavformat/lmlm4.c index b67b68e..447b3d3 100644 --- a/libavformat/lmlm4.c +++ b/libavformat/lmlm4.c @@ -23,6 +23,7 @@ */ #include "libavutil/intreadwrite.h" + #include "avformat.h" #include "internal.h" @@ -34,23 +35,23 @@ #define LMLM4_MAX_PACKET_SIZE 1024 * 1024 -static int lmlm4_probe(AVProbeData * pd) { +static int lmlm4_probe(AVProbeData *pd) +{ unsigned char *buf = pd->buf; unsigned int frame_type, packet_size; - frame_type = AV_RB16(buf+2); - packet_size = AV_RB32(buf+4); + frame_type = AV_RB16(buf + 2); + packet_size = AV_RB32(buf + 4); if (!AV_RB16(buf) && frame_type <= LMLM4_MPEG1L2 && packet_size && frame_type != LMLM4_INVALID && packet_size <= LMLM4_MAX_PACKET_SIZE) { - if (frame_type == LMLM4_MPEG1L2) { - if ((AV_RB16(buf+8) & 0xfffe) != 0xfffc) + if ((AV_RB16(buf + 8) & 0xfffe) != 0xfffc) return 0; /* I could calculate the audio framesize and compare with * packet_size-8, but that seems overkill */ return AVPROBE_SCORE_MAX / 3; - } else if (AV_RB24(buf+8) == 0x000001) { /* PES Signal */ + } else if (AV_RB24(buf + 8) == 0x000001) { /* PES Signal */ return AVPROBE_SCORE_MAX / 5; } } @@ -58,27 +59,29 @@ static int lmlm4_probe(AVProbeData * pd) { return 0; } -static int lmlm4_read_header(AVFormatContext *s) { +static int lmlm4_read_header(AVFormatContext *s) +{ AVStream *st; if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG4; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG4; st->need_parsing = AVSTREAM_PARSE_HEADERS; avpriv_set_pts_info(st, 64, 1001, 30000); if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MP2; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MP2; st->need_parsing = AVSTREAM_PARSE_HEADERS; /* the parameters will be extracted from the compressed bitstream */ return 0; } -static int lmlm4_read_packet(AVFormatContext *s, AVPacket *pkt) { +static int lmlm4_read_packet(AVFormatContext *s, AVPacket *pkt) +{ AVIOContext *pb = s->pb; int ret; unsigned int frame_type, packet_size, padding, frame_size; @@ -104,15 +107,15 @@ static int lmlm4_read_packet(AVFormatContext *s, AVPacket *pkt) { avio_skip(pb, padding); switch (frame_type) { - case LMLM4_I_FRAME: - pkt->flags = AV_PKT_FLAG_KEY; - case LMLM4_P_FRAME: - case LMLM4_B_FRAME: - pkt->stream_index = 0; - break; - case LMLM4_MPEG1L2: - pkt->stream_index = 1; - break; + case LMLM4_I_FRAME: + pkt->flags = AV_PKT_FLAG_KEY; + case LMLM4_P_FRAME: + case LMLM4_B_FRAME: + pkt->stream_index = 0; + break; + case LMLM4_MPEG1L2: + pkt->stream_index = 1; + break; } return ret; diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c index 192d4b0..9c884ba 100644 --- a/libavformat/lxfdec.c +++ b/libavformat/lxfdec.c @@ -46,7 +46,7 @@ static const AVCodecTag lxf_tags[] = { { AV_CODEC_ID_NONE, 0 }, }; -typedef struct { +typedef struct LXFDemuxContext { int channels; ///< number of audio channels. zero means no audio int frame_number; ///< current video frame uint32_t video_format, packet_type, extended_size; @@ -130,7 +130,7 @@ static int get_packet_header(AVFormatContext *s) version = bytestream_get_le32(&p); header_size = bytestream_get_le32(&p); if (version > 1) - avpriv_request_sample(s, "Unknown format version %"PRIu32"\n", version); + avpriv_request_sample(s, "Format version %"PRIu32, version); if (header_size < (version ? 72 : 60) || header_size > LXF_MAX_PACKET_HEADER_SIZE || @@ -177,25 +177,25 @@ static int get_packet_header(AVFormatContext *s) //set codec based on specified audio bitdepth //we only support tightly packed 16-, 20-, 24- and 32-bit PCM at the moment - st->codec->bits_per_coded_sample = (audio_format >> 6) & 0x3F; + st->codecpar->bits_per_coded_sample = (audio_format >> 6) & 0x3F; - if (st->codec->bits_per_coded_sample != (audio_format & 0x3F)) { + if (st->codecpar->bits_per_coded_sample != (audio_format & 0x3F)) { av_log(s, AV_LOG_WARNING, "only tightly packed PCM currently supported\n"); return AVERROR_PATCHWELCOME; } - switch (st->codec->bits_per_coded_sample) { - case 16: st->codec->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break; - case 20: st->codec->codec_id = AV_CODEC_ID_PCM_LXF; break; - case 24: st->codec->codec_id = AV_CODEC_ID_PCM_S24LE_PLANAR; break; - case 32: st->codec->codec_id = AV_CODEC_ID_PCM_S32LE_PLANAR; break; + switch (st->codecpar->bits_per_coded_sample) { + case 16: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break; + case 20: st->codecpar->codec_id = AV_CODEC_ID_PCM_LXF; break; + case 24: st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE_PLANAR; break; + case 32: st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE_PLANAR; break; default: av_log(s, AV_LOG_WARNING, "only 16-, 20-, 24- and 32-bit PCM currently supported\n"); return AVERROR_PATCHWELCOME; } - samples = track_size * 8 / st->codec->bits_per_coded_sample; + samples = track_size * 8 / st->codecpar->bits_per_coded_sample; //use audio packet size to determine video standard //for NTSC we have one 8008-sample audio frame per five video frames @@ -256,10 +256,10 @@ static int lxf_read_header(AVFormatContext *s) expiration_date = AV_RL16(&header_data[58]); disk_params = AV_RL32(&header_data[116]); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->bit_rate = 1000000 * ((video_params >> 14) & 0xFF); - st->codec->codec_tag = video_params & 0xF; - st->codec->codec_id = ff_codec_get_id(lxf_tags, st->codec->codec_tag); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->bit_rate = 1000000 * ((video_params >> 14) & 0xFF); + st->codecpar->codec_tag = video_params & 0xF; + st->codecpar->codec_id = ff_codec_get_id(lxf_tags, st->codecpar->codec_tag); av_log(s, AV_LOG_DEBUG, "record: %x = %i-%02i-%02i\n", record_date, 1900 + (record_date & 0x7F), (record_date >> 7) & 0xF, @@ -276,11 +276,11 @@ static int lxf_read_header(AVFormatContext *s) if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->sample_rate = LXF_SAMPLERATE; - st->codec->channels = lxf->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->sample_rate = LXF_SAMPLERATE; + st->codecpar->channels = lxf->channels; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); } avio_skip(s->pb, lxf->extended_size); @@ -315,7 +315,7 @@ static int lxf_read_packet(AVFormatContext *s, AVPacket *pkt) return ret2; if ((ret2 = avio_read(pb, pkt->data, ret)) != ret) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret2 < 0 ? ret2 : AVERROR_EOF; } diff --git a/libavformat/m4vdec.c b/libavformat/m4vdec.c index 04bd062..9d69dcc 100644 --- a/libavformat/m4vdec.c +++ b/libavformat/m4vdec.c @@ -27,26 +27,34 @@ static int mpeg4video_probe(AVProbeData *probe_packet) { - uint32_t temp_buffer= -1; - int VO=0, VOL=0, VOP = 0, VISO = 0, res=0; + uint32_t temp_buffer = -1; + int VO = 0, VOL = 0, VOP = 0, VISO = 0, res = 0; int i; - for(i=0; ibuf_size; i++){ - temp_buffer = (temp_buffer<<8) + probe_packet->buf[i]; - if ((temp_buffer & 0xffffff00) != 0x100) + for (i = 0; i < probe_packet->buf_size; i++) { + temp_buffer = (temp_buffer << 8) + probe_packet->buf[i]; + if (temp_buffer & 0xfffffe00) + continue; + if (temp_buffer < 2) continue; - if (temp_buffer == VOP_START_CODE) VOP++; - else if (temp_buffer == VISUAL_OBJECT_START_CODE) VISO++; - else if (temp_buffer < 0x120) VO++; - else if (temp_buffer < 0x130) VOL++; - else if ( !(0x1AF < temp_buffer && temp_buffer < 0x1B7) - && !(0x1B9 < temp_buffer && temp_buffer < 0x1C4)) res++; + if (temp_buffer == VOP_START_CODE) + VOP++; + else if (temp_buffer == VISUAL_OBJECT_START_CODE) + VISO++; + else if (temp_buffer >= 0x100 && temp_buffer < 0x120) + VO++; + else if (temp_buffer >= 0x120 && temp_buffer < 0x130) + VOL++; + else if (!(0x1AF < temp_buffer && temp_buffer < 0x1B7) && + !(0x1B9 < temp_buffer && temp_buffer < 0x1C4)) + res++; } - if (VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res==0) + if (VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res == 0) return AVPROBE_SCORE_EXTENSION; return 0; } -FF_DEF_RAWVIDEO_DEMUXER(m4v, "raw MPEG-4 video", mpeg4video_probe, "m4v", AV_CODEC_ID_MPEG4) +FF_DEF_RAWVIDEO_DEMUXER(m4v, "raw MPEG-4 video", mpeg4video_probe, "m4v", + AV_CODEC_ID_MPEG4) diff --git a/libavformat/matroska.c b/libavformat/matroska.c index 237f26f..8842d7c 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -1,6 +1,6 @@ /* * Matroska common data - * Copyright (c) 2003-2004 The ffmpeg Project + * Copyright (c) 2003-2004 The FFmpeg project * * This file is part of Libav. * @@ -55,16 +55,18 @@ const CodecTags ff_mkv_codec_tags[]={ {"A_VORBIS" , AV_CODEC_ID_VORBIS}, {"A_WAVPACK4" , AV_CODEC_ID_WAVPACK}, - {"S_TEXT/UTF8" , AV_CODEC_ID_TEXT}, {"S_TEXT/UTF8" , AV_CODEC_ID_SRT}, + {"S_TEXT/UTF8" , AV_CODEC_ID_TEXT}, {"S_TEXT/ASCII" , AV_CODEC_ID_TEXT}, {"S_TEXT/ASS" , AV_CODEC_ID_SSA}, {"S_TEXT/SSA" , AV_CODEC_ID_SSA}, {"S_ASS" , AV_CODEC_ID_SSA}, {"S_SSA" , AV_CODEC_ID_SSA}, {"S_VOBSUB" , AV_CODEC_ID_DVD_SUBTITLE}, + {"S_DVBSUB" , AV_CODEC_ID_DVB_SUBTITLE}, {"S_HDMV/PGS" , AV_CODEC_ID_HDMV_PGS_SUBTITLE}, + {"V_AV1" , AV_CODEC_ID_AV1}, {"V_DIRAC" , AV_CODEC_ID_DIRAC}, {"V_MJPEG" , AV_CODEC_ID_MJPEG}, {"V_MPEG1" , AV_CODEC_ID_MPEG1VIDEO}, @@ -88,12 +90,17 @@ const CodecTags ff_mkv_codec_tags[]={ {"" , AV_CODEC_ID_NONE} }; -const CodecMime ff_mkv_mime_tags[] = { - {"text/plain" , AV_CODEC_ID_TEXT}, +const CodecMime ff_mkv_image_mime_tags[] = { {"image/gif" , AV_CODEC_ID_GIF}, {"image/jpeg" , AV_CODEC_ID_MJPEG}, {"image/png" , AV_CODEC_ID_PNG}, {"image/tiff" , AV_CODEC_ID_TIFF}, + + {"" , AV_CODEC_ID_NONE} +}; + +const CodecMime ff_mkv_mime_tags[] = { + {"text/plain" , AV_CODEC_ID_TEXT}, {"application/x-truetype-font", AV_CODEC_ID_TTF}, {"application/x-font" , AV_CODEC_ID_TTF}, diff --git a/libavformat/matroska.h b/libavformat/matroska.h index d8f4f8e..91bb978 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -1,6 +1,6 @@ /* * Matroska constants - * Copyright (c) 2003-2004 The ffmpeg Project + * Copyright (c) 2003-2004 The FFmpeg project * * This file is part of Libav. * @@ -113,6 +113,7 @@ #define MATROSKA_ID_VIDEOPIXELCROPR 0x54DD #define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2 #define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A +#define MATROSKA_ID_VIDEOFIELDORDER 0x9D #define MATROSKA_ID_VIDEOSTEREOMODE 0x53B8 #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524 @@ -222,6 +223,21 @@ typedef enum { } MatroskaTrackEncodingCompAlgo; typedef enum { + MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED = 0, + MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED = 1, + MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE = 2 +} MatroskaVideoInterlaceFlag; + +typedef enum { + MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE = 0, + MATROSKA_VIDEO_FIELDORDER_UNDETERMINED = 2, + MATROSKA_VIDEO_FIELDORDER_TT = 1, + MATROSKA_VIDEO_FIELDORDER_BB = 6, + MATROSKA_VIDEO_FIELDORDER_TB = 9, + MATROSKA_VIDEO_FIELDORDER_BT = 14, +} MatroskaVideoFieldOrder; + +typedef enum { MATROSKA_VIDEO_STEREOMODE_TYPE_MONO = 0, MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT = 1, MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP = 2, @@ -254,6 +270,7 @@ typedef struct CodecTags{ extern const CodecTags ff_mkv_codec_tags[]; extern const CodecMime ff_mkv_mime_tags[]; +extern const CodecMime ff_mkv_image_mime_tags[]; extern const AVMetadataConv ff_mkv_metadata_conv[]; int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 67df4b34..54c2b9a 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -86,18 +86,18 @@ typedef const struct EbmlSyntax { } def; } EbmlSyntax; -typedef struct { +typedef struct EbmlList { int nb_elem; void *elem; } EbmlList; -typedef struct { +typedef struct EbmlBin { int size; uint8_t *data; int64_t pos; } EbmlBin; -typedef struct { +typedef struct Ebml { uint64_t version; uint64_t max_size; uint64_t id_length; @@ -105,28 +105,30 @@ typedef struct { uint64_t doctype_version; } Ebml; -typedef struct { +typedef struct MatroskaTrackCompression { uint64_t algo; EbmlBin settings; } MatroskaTrackCompression; -typedef struct { +typedef struct MatroskaTrackEncoding { uint64_t scope; uint64_t type; MatroskaTrackCompression compression; } MatroskaTrackEncoding; -typedef struct { +typedef struct MatroskaTrackVideo { double frame_rate; uint64_t display_width; uint64_t display_height; uint64_t pixel_width; uint64_t pixel_height; uint64_t fourcc; + uint64_t interlaced; + uint64_t field_order; uint64_t stereo_mode; } MatroskaTrackVideo; -typedef struct { +typedef struct MatroskaTrackAudio { double samplerate; double out_samplerate; uint64_t bitdepth; @@ -143,7 +145,7 @@ typedef struct { uint8_t *buf; } MatroskaTrackAudio; -typedef struct { +typedef struct MatroskaTrack { uint64_t num; uint64_t uid; uint64_t type; @@ -165,7 +167,7 @@ typedef struct { int ms_compat; } MatroskaTrack; -typedef struct { +typedef struct MatroskaAttachment { uint64_t uid; char *filename; char *mime; @@ -174,7 +176,7 @@ typedef struct { AVStream *stream; } MatroskaAttachment; -typedef struct { +typedef struct MatroskaChapter { uint64_t start; uint64_t end; uint64_t uid; @@ -183,17 +185,17 @@ typedef struct { AVChapter *chapter; } MatroskaChapter; -typedef struct { +typedef struct MatroskaIndexPos { uint64_t track; uint64_t pos; } MatroskaIndexPos; -typedef struct { +typedef struct MatroskaIndex { uint64_t time; EbmlList pos; } MatroskaIndex; -typedef struct { +typedef struct MatroskaTag { char *name; char *string; char *lang; @@ -201,7 +203,7 @@ typedef struct { EbmlList sub; } MatroskaTag; -typedef struct { +typedef struct MatroskaTagTarget { char *type; uint64_t typevalue; uint64_t trackuid; @@ -209,27 +211,27 @@ typedef struct { uint64_t attachuid; } MatroskaTagTarget; -typedef struct { +typedef struct MatroskaTags { MatroskaTagTarget target; EbmlList tag; } MatroskaTags; -typedef struct { +typedef struct MatroskaSeekhead { uint64_t id; uint64_t pos; } MatroskaSeekhead; -typedef struct { +typedef struct MatroskaLevel { uint64_t start; uint64_t length; } MatroskaLevel; -typedef struct { +typedef struct MatroskaCluster { uint64_t timecode; EbmlList blocks; } MatroskaCluster; -typedef struct { +typedef struct MatroskaDemuxContext { AVFormatContext *ctx; /* EBML stuff */ @@ -273,7 +275,7 @@ typedef struct { int contains_ssa; } MatroskaDemuxContext; -typedef struct { +typedef struct MatroskaBlock { uint64_t duration; int64_t reference; uint64_t non_simple; @@ -319,7 +321,8 @@ static EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, - { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE }, + { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, + { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, { 0 } @@ -747,16 +750,19 @@ static int ebml_read_ascii(AVIOContext *pb, int size, char **str) static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) { av_free(bin->data); - if (!(bin->data = av_mallocz(length + FF_INPUT_BUFFER_PADDING_SIZE))) + bin->size = 0; + + if (!(bin->data = av_mallocz(length + AV_INPUT_BUFFER_PADDING_SIZE))) return AVERROR(ENOMEM); - bin->size = length; bin->pos = avio_tell(pb); if (avio_read(pb, bin->data, length) != length) { av_freep(&bin->data); return AVERROR(EIO); } + bin->size = length; + return 0; } @@ -1205,7 +1211,7 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, es = ec / 100; ec -= 100 * es; *ptr++ = '\0'; - len = 50 + end - ptr + FF_INPUT_BUFFER_PADDING_SIZE; + len = 50 + end - ptr + AV_INPUT_BUFFER_PADDING_SIZE; if (!(line = av_buffer_alloc(len))) return; snprintf(line->data, len, @@ -1227,7 +1233,7 @@ static int matroska_merge_packets(AVPacket *out, AVPacket *in) memcpy(out->data + old_size, in->data, in->size); - av_free_packet(in); + av_packet_unref(in); av_free(in); return 0; } @@ -1276,24 +1282,55 @@ static void matroska_convert_tags(AVFormatContext *s) for (i = 0; i < matroska->tags.nb_elem; i++) { if (tags[i].target.attachuid) { MatroskaAttachment *attachment = matroska->attachments.elem; - for (j = 0; j < matroska->attachments.nb_elem; j++) + int found = 0; + for (j = 0; j < matroska->attachments.nb_elem; j++) { if (attachment[j].uid == tags[i].target.attachuid && - attachment[j].stream) + attachment[j].stream) { matroska_convert_tag(s, &tags[i].tag, &attachment[j].stream->metadata, NULL); + found = 1; + } + } + if (!found) { + av_log(NULL, AV_LOG_WARNING, + "The tags at index %d refer to a " + "non-existent attachment %"PRId64".\n", + i, tags[i].target.attachuid); + } } else if (tags[i].target.chapteruid) { MatroskaChapter *chapter = matroska->chapters.elem; - for (j = 0; j < matroska->chapters.nb_elem; j++) + int found = 0; + for (j = 0; j < matroska->chapters.nb_elem; j++) { if (chapter[j].uid == tags[i].target.chapteruid && - chapter[j].chapter) + chapter[j].chapter) { matroska_convert_tag(s, &tags[i].tag, &chapter[j].chapter->metadata, NULL); + found = 1; + } + } + if (!found) { + av_log(NULL, AV_LOG_WARNING, + "The tags at index %d refer to a non-existent chapter " + "%"PRId64".\n", + i, tags[i].target.chapteruid); + } } else if (tags[i].target.trackuid) { MatroskaTrack *track = matroska->tracks.elem; - for (j = 0; j < matroska->tracks.nb_elem; j++) - if (track[j].uid == tags[i].target.trackuid && track[j].stream) + int found = 0; + for (j = 0; j < matroska->tracks.nb_elem; j++) { + if (track[j].uid == tags[i].target.trackuid && + track[j].stream) { matroska_convert_tag(s, &tags[i].tag, &track[j].stream->metadata, NULL); + found = 1; + } + } + if (!found) { + av_log(NULL, AV_LOG_WARNING, + "The tags at index %d refer to a non-existent track " + "%"PRId64".\n", + i, tags[i].target.trackuid); + } } else { matroska_convert_tag(s, &tags[i].tag, &s->metadata, tags[i].target.type); @@ -1482,7 +1519,7 @@ static int matroska_parse_flac(AVFormatContext *s, av_log(s, AV_LOG_WARNING, "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); } else - st->codec->channel_layout = mask; + st->codecpar->channel_layout = mask; } av_dict_free(&dict); } @@ -1494,6 +1531,51 @@ static int matroska_parse_flac(AVFormatContext *s, return 0; } +static int mkv_field_order(int64_t field_order) +{ + switch (field_order) { + case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: + return AV_FIELD_PROGRESSIVE; + case MATROSKA_VIDEO_FIELDORDER_UNDETERMINED: + return AV_FIELD_UNKNOWN; + case MATROSKA_VIDEO_FIELDORDER_TT: + return AV_FIELD_TT; + case MATROSKA_VIDEO_FIELDORDER_BB: + return AV_FIELD_BB; + case MATROSKA_VIDEO_FIELDORDER_BT: + return AV_FIELD_BT; + case MATROSKA_VIDEO_FIELDORDER_TB: + return AV_FIELD_TB; + default: + return AV_FIELD_UNKNOWN; + } +} + +static void mkv_stereo_mode_display_mul(int stereo_mode, + int *h_width, int *h_height) +{ + switch (stereo_mode) { + case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: + case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR: + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR: + break; + case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT: + case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT: + case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR: + *h_width = 2; + break; + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP: + case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM: + case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR: + *h_height = 2; + break; + } +} + static int matroska_parse_tracks(AVFormatContext *s) { MatroskaDemuxContext *matroska = s->priv_data; @@ -1597,17 +1679,30 @@ static int matroska_parse_tracks(AVFormatContext *s) ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size, 0, NULL, NULL, NULL, NULL); - ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size); + ret = ff_get_wav_header(s, &b, st->codecpar, track->codec_priv.size); if (ret < 0) return ret; - codec_id = st->codec->codec_id; + codec_id = st->codecpar->codec_id; extradata_offset = FFMIN(track->codec_priv.size, 18); } else if (!strcmp(track->codec_id, "V_QUICKTIME") && (track->codec_priv.size >= 86) && (track->codec_priv.data)) { - track->video.fourcc = AV_RL32(track->codec_priv.data); - codec_id = ff_codec_get_id(ff_codec_movvideo_tags, - track->video.fourcc); + if (track->codec_priv.size == AV_RB32(track->codec_priv.data)) { + track->video.fourcc = AV_RL32(track->codec_priv.data + 4); + codec_id = ff_codec_get_id(ff_codec_movvideo_tags, + track->video.fourcc); + } + if (codec_id == AV_CODEC_ID_NONE) { + track->video.fourcc = AV_RL32(track->codec_priv.data); + codec_id = ff_codec_get_id(ff_codec_movvideo_tags, + track->video.fourcc); + } + if (codec_id == AV_CODEC_ID_NONE) { + char buf[32]; + av_get_codec_tag_string(buf, sizeof(buf), track->video.fourcc); + av_log(matroska->ctx, AV_LOG_ERROR, + "mov FourCC not found %s.\n", buf); + } } else if (codec_id == AV_CODEC_ID_PCM_S16BE) { switch (track->audio.bitdepth) { case 8: @@ -1638,7 +1733,7 @@ static int matroska_parse_tracks(AVFormatContext *s) } else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) { int profile = matroska_aac_profile(track->codec_id); int sri = matroska_aac_sri(track->audio.samplerate); - extradata = av_mallocz(5 + FF_INPUT_BUFFER_PADDING_SIZE); + extradata = av_mallocz(5 + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) return AVERROR(ENOMEM); extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1); @@ -1657,7 +1752,7 @@ static int matroska_parse_tracks(AVFormatContext *s) * decoder expects manually. */ extradata_size = 12 + track->codec_priv.size; extradata = av_mallocz(extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) return AVERROR(ENOMEM); AV_WB32(extradata, extradata_size); @@ -1710,16 +1805,18 @@ static int matroska_parse_tracks(AVFormatContext *s) return AVERROR_INVALIDDATA; track->audio.buf = av_malloc(track->audio.frame_size * track->audio.sub_packet_h); + if (!track->audio.buf) + return AVERROR(ENOMEM); if (codec_id == AV_CODEC_ID_RA_288) { - st->codec->block_align = track->audio.coded_framesize; + st->codecpar->block_align = track->audio.coded_framesize; track->codec_priv.size = 0; } else { if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) { - const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; + static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; track->audio.sub_packet_size = ff_sipr_subpk_size[flavor]; - st->codec->bit_rate = sipr_bit_rate[flavor]; + st->codecpar->bit_rate = sipr_bit_rate[flavor]; } - st->codec->block_align = track->audio.sub_packet_size; + st->codecpar->block_align = track->audio.sub_packet_size; extradata_offset = 78; } } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) { @@ -1738,12 +1835,19 @@ static int matroska_parse_tracks(AVFormatContext *s) avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale, 1000 * 1000 * 1000); /* 64 bit pts in ns */ + if (track->type == MATROSKA_TRACK_TYPE_AUDIO && + track->audio.out_samplerate) { + st->codecpar->initial_padding = av_rescale_q(track->codec_delay, + (AVRational){ 1, 1000000000 }, + (AVRational){ 1, track->audio.out_samplerate }); + } + /* convert the delay from ns to the track timebase */ track->codec_delay = av_rescale_q(track->codec_delay, (AVRational){ 1, 1000000000 }, st->time_base); - st->codec->codec_id = codec_id; + st->codecpar->codec_id = codec_id; st->start_time = 0; if (strcmp(track->language, "und")) av_dict_set(&st->metadata, "language", track->language, 0); @@ -1754,34 +1858,44 @@ static int matroska_parse_tracks(AVFormatContext *s) if (track->flag_forced) st->disposition |= AV_DISPOSITION_FORCED; - if (!st->codec->extradata) { + if (!st->codecpar->extradata) { if (extradata) { - st->codec->extradata = extradata; - st->codec->extradata_size = extradata_size; + st->codecpar->extradata = extradata; + st->codecpar->extradata_size = extradata_size; } else if (track->codec_priv.data && track->codec_priv.size > 0) { - st->codec->extradata = av_mallocz(track->codec_priv.size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_mallocz(track->codec_priv.size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = track->codec_priv.size; - memcpy(st->codec->extradata, + st->codecpar->extradata_size = track->codec_priv.size; + memcpy(st->codecpar->extradata, track->codec_priv.data + extradata_offset, track->codec_priv.size); } } if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = track->video.fourcc; - st->codec->width = track->video.pixel_width; - st->codec->height = track->video.pixel_height; + int display_width_mul = 1; + int display_height_mul = 1; + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = track->video.fourcc; + st->codecpar->width = track->video.pixel_width; + st->codecpar->height = track->video.pixel_height; + + if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED) + st->codecpar->field_order = mkv_field_order(track->video.field_order); + + if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) + mkv_stereo_mode_display_mul(track->video.stereo_mode, &display_width_mul, &display_height_mul); + av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den, - st->codec->height * track->video.display_width, - st->codec->width * track->video.display_height, + st->codecpar->height * track->video.display_width * display_width_mul, + st->codecpar->width * track->video.display_height * display_height_mul, 255); - if (st->codec->codec_id != AV_CODEC_ID_H264 && - st->codec->codec_id != AV_CODEC_ID_HEVC) + if (st->codecpar->codec_id != AV_CODEC_ID_H264 && + st->codecpar->codec_id != AV_CODEC_ID_HEVC) st->need_parsing = AVSTREAM_PARSE_HEADERS; if (track->default_duration) { av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, @@ -1795,14 +1909,16 @@ static int matroska_parse_tracks(AVFormatContext *s) return ret; } } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->sample_rate = track->audio.out_samplerate; - st->codec->channels = track->audio.channels; - if (st->codec->codec_id != AV_CODEC_ID_AAC) + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->sample_rate = track->audio.out_samplerate; + st->codecpar->channels = track->audio.channels; + if (st->codecpar->codec_id != AV_CODEC_ID_AAC) st->need_parsing = AVSTREAM_PARSE_HEADERS; + if (st->codecpar->codec_id == AV_CODEC_ID_MP3) + st->need_parsing = AVSTREAM_PARSE_FULL; } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - if (st->codec->codec_id == AV_CODEC_ID_SSA) + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + if (st->codecpar->codec_id == AV_CODEC_ID_SSA) matroska->contains_ssa = 1; } } @@ -1888,23 +2004,46 @@ static int matroska_read_header(AVFormatContext *s) break; av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); - st->codec->codec_id = AV_CODEC_ID_NONE; - st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; - st->codec->extradata = av_malloc(attachments[j].bin.size); - if (!st->codec->extradata) - break; - st->codec->extradata_size = attachments[j].bin.size; - memcpy(st->codec->extradata, attachments[j].bin.data, - attachments[j].bin.size); - - for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { - if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime, - strlen(ff_mkv_mime_tags[i].str))) { - st->codec->codec_id = ff_mkv_mime_tags[i].id; + st->codecpar->codec_id = AV_CODEC_ID_NONE; + + for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { + if (!strncmp(ff_mkv_image_mime_tags[i].str, attachments[j].mime, + strlen(ff_mkv_image_mime_tags[i].str))) { + st->codecpar->codec_id = ff_mkv_image_mime_tags[i].id; break; } } + attachments[j].stream = st; + + if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { + st->disposition |= AV_DISPOSITION_ATTACHED_PIC; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + + av_init_packet(&st->attached_pic); + if ((res = av_new_packet(&st->attached_pic, attachments[j].bin.size)) < 0) + return res; + memcpy(st->attached_pic.data, attachments[j].bin.data, attachments[j].bin.size); + st->attached_pic.stream_index = st->index; + st->attached_pic.flags |= AV_PKT_FLAG_KEY; + } else { + st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; + st->codecpar->extradata = av_malloc(attachments[j].bin.size); + if (!st->codecpar->extradata) + break; + + st->codecpar->extradata_size = attachments[j].bin.size; + memcpy(st->codecpar->extradata, attachments[j].bin.data, + attachments[j].bin.size); + + for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { + if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime, + strlen(ff_mkv_mime_tags[i].str))) { + st->codecpar->codec_id = ff_mkv_mime_tags[i].id; + break; + } + } + } } } @@ -1966,7 +2105,7 @@ static void matroska_clear_queue(MatroskaDemuxContext *matroska) if (matroska->packets) { int n; for (n = 0; n < matroska->num_packets; n++) { - av_free_packet(matroska->packets[n]); + av_packet_unref(matroska->packets[n]); av_free(matroska->packets[n]); } av_freep(&matroska->packets); @@ -2088,7 +2227,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, uint8_t *data, int size, uint64_t timecode, uint64_t duration, int64_t pos) { - int a = st->codec->block_align; + int a = st->codecpar->block_align; int sps = track->audio.sub_packet_size; int cfs = track->audio.coded_framesize; int h = track->audio.sub_packet_h; @@ -2099,7 +2238,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, if (!track->audio.pkt_cnt) { if (track->audio.sub_packet_cnt == 0) track->audio.buf_timecode = timecode; - if (st->codec->codec_id == AV_CODEC_ID_RA_288) { + if (st->codecpar->codec_id == AV_CODEC_ID_RA_288) { if (size < cfs * h / 2) { av_log(matroska->ctx, AV_LOG_ERROR, "Corrupt int4 RM-style audio packet size\n"); @@ -2108,7 +2247,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, for (x = 0; x < h / 2; x++) memcpy(track->audio.buf + x * 2 * w + y * cfs, data + x * cfs, cfs); - } else if (st->codec->codec_id == AV_CODEC_ID_SIPR) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) { if (size < w) { av_log(matroska->ctx, AV_LOG_ERROR, "Corrupt sipr RM-style audio packet size\n"); @@ -2128,7 +2267,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, } if (++track->audio.sub_packet_cnt >= h) { - if (st->codec->codec_id == AV_CODEC_ID_SIPR) + if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) ff_rm_reorder_sipr_data(track->audio.buf, h, w); track->audio.sub_packet_cnt = 0; track->audio.pkt_cnt = h * w / a; @@ -2136,8 +2275,16 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, } while (track->audio.pkt_cnt) { + int ret; AVPacket *pkt = av_mallocz(sizeof(AVPacket)); - av_new_packet(pkt, a); + if (!pkt) + return AVERROR(ENOMEM); + + ret = av_new_packet(pkt, a); + if (ret < 0) { + av_free(pkt); + return ret; + } memcpy(pkt->data, track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--), a); @@ -2162,10 +2309,10 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, uint16_t ver; int ret, offset = 0; - if (srclen < 12 || track->stream->codec->extradata_size < 2) + if (srclen < 12 || track->stream->codecpar->extradata_size < 2) return AVERROR_INVALIDDATA; - ver = AV_RL16(track->stream->codec->extradata); + ver = AV_RL16(track->stream->codecpar->extradata); samples = AV_RL32(src); src += 4; @@ -2249,7 +2396,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, return res; } - if (st->codec->codec_id == AV_CODEC_ID_WAVPACK) { + if (st->codecpar->codec_id == AV_CODEC_ID_WAVPACK) { uint8_t *wv_data; res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size); if (res < 0) { @@ -2262,17 +2409,22 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt_data = wv_data; } - if (st->codec->codec_id == AV_CODEC_ID_PRORES) + if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) offset = 8; pkt = av_mallocz(sizeof(AVPacket)); + if (!pkt) { + av_freep(&pkt_data); + return AVERROR(ENOMEM); + } /* XXX: prevent data copy... */ if (av_new_packet(pkt, pkt_size + offset) < 0) { av_free(pkt); + av_freep(&pkt_data); return AVERROR(ENOMEM); } - if (st->codec->codec_id == AV_CODEC_ID_PRORES) { + if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) { uint8_t *buf = pkt->data; bytestream_put_be32(&buf, pkt_size); bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f')); @@ -2291,19 +2443,23 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, else pkt->pts = timecode; pkt->pos = pos; - if (st->codec->codec_id == AV_CODEC_ID_TEXT) - pkt->convergence_duration = duration; - else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE) + if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE || st->codecpar->codec_id == AV_CODEC_ID_SRT) pkt->duration = duration; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS + if (st->codecpar->codec_id == AV_CODEC_ID_SRT) + pkt->convergence_duration = duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (st->codec->codec_id == AV_CODEC_ID_SSA) + if (st->codecpar->codec_id == AV_CODEC_ID_SSA) matroska_fix_ass_packet(matroska, pkt, duration); if (matroska->prev_pkt && timecode != AV_NOPTS_VALUE && matroska->prev_pkt->pts == timecode && matroska->prev_pkt->stream_index == st->index && - st->codec->codec_id == AV_CODEC_ID_SSA) + st->codecpar->codec_id == AV_CODEC_ID_SSA) matroska_merge_packets(matroska->prev_pkt, pkt); else { dynarray_add(&matroska->packets, &matroska->num_packets, pkt); @@ -2397,11 +2553,11 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, FFMAX(track->end_timecode, timecode + block_duration); for (n = 0; n < laces; n++) { - if ((st->codec->codec_id == AV_CODEC_ID_RA_288 || - st->codec->codec_id == AV_CODEC_ID_COOK || - st->codec->codec_id == AV_CODEC_ID_SIPR || - st->codec->codec_id == AV_CODEC_ID_ATRAC3) && - st->codec->block_align && track->audio.sub_packet_size) { + if ((st->codecpar->codec_id == AV_CODEC_ID_RA_288 || + st->codecpar->codec_id == AV_CODEC_ID_COOK || + st->codecpar->codec_id == AV_CODEC_ID_SIPR || + st->codecpar->codec_id == AV_CODEC_ID_ATRAC3) && + st->codecpar->block_align && track->audio.sub_packet_size) { res = matroska_parse_rm_audio(matroska, track, st, data, lace_size[n], timecode, duration, pos); diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index b39d1b2..dd5552c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -67,19 +67,19 @@ typedef struct mkv_seekhead { int num_entries; } mkv_seekhead; -typedef struct { +typedef struct mkv_cuepoint { uint64_t pts; int tracknum; int64_t cluster_pos; ///< file offset of the cluster containing the block } mkv_cuepoint; -typedef struct { +typedef struct mkv_cues { int64_t segment_offset; mkv_cuepoint *entries; int num_entries; } mkv_cues; -typedef struct { +typedef struct mkv_track { int write_dts; int64_t ts_offset; } mkv_track; @@ -105,6 +105,7 @@ typedef struct MatroskaMuxContext { AVPacket cur_audio_pkt; int have_attachments; + int have_video; int reserve_cues_space; int cluster_size_limit; @@ -439,19 +440,19 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, int num_tracks) return currentpos; } -static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecContext *codec) +static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par) { uint8_t *header_start[3]; int header_len[3]; int first_header_size; int j; - if (codec->codec_id == AV_CODEC_ID_VORBIS) + if (par->codec_id == AV_CODEC_ID_VORBIS) first_header_size = 30; else first_header_size = 42; - if (avpriv_split_xiph_headers(codec->extradata, codec->extradata_size, + if (avpriv_split_xiph_headers(par->extradata, par->extradata_size, first_header_size, header_start, header_len) < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); return -1; @@ -467,22 +468,22 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecContex return 0; } -static int put_wv_codecpriv(AVIOContext *pb, AVCodecContext *codec) +static int put_wv_codecpriv(AVIOContext *pb, AVCodecParameters *par) { - if (codec->extradata && codec->extradata_size == 2) - avio_write(pb, codec->extradata, 2); + if (par->extradata && par->extradata_size == 2) + avio_write(pb, par->extradata, 2); else avio_wl16(pb, 0x403); // fallback to the version mentioned in matroska specs return 0; } static int put_flac_codecpriv(AVFormatContext *s, - AVIOContext *pb, AVCodecContext *codec) + AVIOContext *pb, AVCodecParameters *par) { - int write_comment = (codec->channel_layout && - !(codec->channel_layout & ~0x3ffffULL) && - !ff_flac_is_native_layout(codec->channel_layout)); - int ret = ff_flac_write_header(pb, codec->extradata, codec->extradata_size, + int write_comment = (par->channel_layout && + !(par->channel_layout & ~0x3ffffULL) && + !ff_flac_is_native_layout(par->channel_layout)); + int ret = ff_flac_write_header(pb, par->extradata, par->extradata_size, !write_comment); if (ret < 0) @@ -495,7 +496,7 @@ static int put_flac_codecpriv(AVFormatContext *s, uint8_t buf[32], *data, *p; int len; - snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout); + snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout); av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); len = ff_vorbiscomment_length(dict, vendor); @@ -520,61 +521,62 @@ static int put_flac_codecpriv(AVFormatContext *s, return 0; } -static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, - int *sample_rate, int *output_sample_rate) +static int get_aac_sample_rates(AVFormatContext *s, AVCodecParameters *par, + int *sample_rate, int *output_sample_rate) { MPEG4AudioConfig mp4ac; - if (avpriv_mpeg4audio_get_config(&mp4ac, codec->extradata, - codec->extradata_size * 8, 1) < 0) { - av_log(s, AV_LOG_WARNING, + if (avpriv_mpeg4audio_get_config(&mp4ac, par->extradata, + par->extradata_size * 8, 1) < 0) { + av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n"); - return; + return AVERROR(EINVAL); } *sample_rate = mp4ac.sample_rate; *output_sample_rate = mp4ac.ext_sample_rate; + return 0; } static int mkv_write_native_codecprivate(AVFormatContext *s, - AVCodecContext *codec, + AVCodecParameters *par, AVIOContext *dyn_cp) { - switch (codec->codec_id) { + switch (par->codec_id) { case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: - return put_xiph_codecpriv(s, dyn_cp, codec); + return put_xiph_codecpriv(s, dyn_cp, par); case AV_CODEC_ID_FLAC: - return put_flac_codecpriv(s, dyn_cp, codec); + return put_flac_codecpriv(s, dyn_cp, par); case AV_CODEC_ID_WAVPACK: - return put_wv_codecpriv(dyn_cp, codec); + return put_wv_codecpriv(dyn_cp, par); case AV_CODEC_ID_H264: - return ff_isom_write_avcc(dyn_cp, codec->extradata, - codec->extradata_size); + return ff_isom_write_avcc(dyn_cp, par->extradata, + par->extradata_size); case AV_CODEC_ID_HEVC: - return ff_isom_write_hvcc(dyn_cp, codec->extradata, - codec->extradata_size, 0); + return ff_isom_write_hvcc(dyn_cp, par->extradata, + par->extradata_size, 0); case AV_CODEC_ID_ALAC: - if (codec->extradata_size < 36) { + if (par->extradata_size < 36) { av_log(s, AV_LOG_ERROR, "Invalid extradata found, ALAC expects a 36-byte " "QuickTime atom."); return AVERROR_INVALIDDATA; } else - avio_write(dyn_cp, codec->extradata + 12, - codec->extradata_size - 12); + avio_write(dyn_cp, par->extradata + 12, + par->extradata_size - 12); break; default: - if (codec->extradata_size) - avio_write(dyn_cp, codec->extradata, codec->extradata_size); + if (par->extradata_size) + avio_write(dyn_cp, par->extradata, par->extradata_size); } return 0; } static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, - AVCodecContext *codec, int native_id, - int qt_id) + AVCodecParameters *par, + int native_id, int qt_id) { AVIOContext *dyn_cp; uint8_t *codecpriv; @@ -585,36 +587,36 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, return ret; if (native_id) { - ret = mkv_write_native_codecprivate(s, codec, dyn_cp); - } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = mkv_write_native_codecprivate(s, par, dyn_cp); + } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { if (qt_id) { - if (!codec->codec_tag) - codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, - codec->codec_id); - if (codec->extradata_size) - avio_write(dyn_cp, codec->extradata, codec->extradata_size); + if (!par->codec_tag) + par->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, + par->codec_id); + if (par->extradata_size) + avio_write(dyn_cp, par->extradata, par->extradata_size); } else { - if (!codec->codec_tag) - codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, - codec->codec_id); - if (!codec->codec_tag) { + if (!par->codec_tag) + par->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, + par->codec_id); + if (!par->codec_tag) { av_log(s, AV_LOG_ERROR, "No bmp codec ID found.\n"); ret = -1; } - ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0); + ff_put_bmp_header(dyn_cp, par, ff_codec_bmp_tags, 0); } - } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned int tag; - tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id); + tag = ff_codec_get_tag(ff_codec_wav_tags, par->codec_id); if (!tag) { av_log(s, AV_LOG_ERROR, "No wav codec ID found.\n"); ret = -1; } - if (!codec->codec_tag) - codec->codec_tag = tag; + if (!par->codec_tag) + par->codec_tag = tag; - ff_put_wav_header(dyn_cp, codec); + ff_put_wav_header(s, dyn_cp, par); } codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv); @@ -625,13 +627,52 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, return ret; } +static void mkv_write_field_order(AVIOContext *pb, + enum AVFieldOrder field_order) +{ + switch (field_order) { + case AV_FIELD_UNKNOWN: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, + MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED); + break; + case AV_FIELD_PROGRESSIVE: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, + MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE); + break; + case AV_FIELD_TT: + case AV_FIELD_BB: + case AV_FIELD_TB: + case AV_FIELD_BT: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, + MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED); + switch (field_order) { + case AV_FIELD_TT: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_TT); + break; + case AV_FIELD_BB: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_BB); + break; + case AV_FIELD_TB: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_TB); + break; + case AV_FIELD_BT: + put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_BT); + break; + } + } +} + static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, AVStream *st, int mode) { int i; int display_width, display_height; int h_width = 1, h_height = 1; - AVCodecContext *codec = st->codec; + AVCodecParameters *par = st->codecpar; AVDictionaryEntry *tag; MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB; @@ -708,8 +749,8 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, // write DisplayWidth and DisplayHeight, they contain the size of // a single source view and/or the display aspect ratio - display_width = codec->width / h_width; - display_height = codec->height / h_height; + display_width = par->width / h_width; + display_height = par->height / h_height; if (st->sample_aspect_ratio.num) { display_width *= av_q2d(st->sample_aspect_ratio); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3); // DAR @@ -727,12 +768,12 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, int i, AVIOContext *pb) { AVStream *st = s->streams[i]; - AVCodecContext *codec = st->codec; + AVCodecParameters *par = st->codecpar; ebml_master subinfo, track; int native_id = 0; int qt_id = 0; - int bit_depth = av_get_bits_per_sample(codec->codec_id); - int sample_rate = codec->sample_rate; + int bit_depth = av_get_bits_per_sample(par->codec_id); + int sample_rate = par->sample_rate; int output_sample_rate = 0; int j, ret; AVDictionaryEntry *tag; @@ -740,16 +781,19 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, // ms precision is the de-facto standard timescale for mkv files avpriv_set_pts_info(st, 64, 1, 1000); - if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { + if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) { mkv->have_attachments = 1; return 0; } if (!bit_depth) - bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; + bit_depth = av_get_bytes_per_sample(par->format) << 3; - if (codec->codec_id == AV_CODEC_ID_AAC) - get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); + if (par->codec_id == AV_CODEC_ID_AAC) { + ret = get_aac_sample_rates(s, par, &sample_rate, &output_sample_rate); + if (ret < 0) + return ret; + } track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); @@ -765,48 +809,52 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, // if we need to clear it. if (!(st->disposition & AV_DISPOSITION_DEFAULT)) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT)); + if (st->disposition & AV_DISPOSITION_FORCED) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, !!(st->disposition & AV_DISPOSITION_FORCED)); - if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->delay) { - mkv->tracks[i].ts_offset = av_rescale_q(codec->delay, - (AVRational){ 1, codec->sample_rate }, + if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->initial_padding) { + mkv->tracks[i].ts_offset = av_rescale_q(par->initial_padding, + (AVRational){ 1, par->sample_rate }, st->time_base); put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, - av_rescale_q(codec->delay, (AVRational){ 1, codec->sample_rate }, + av_rescale_q(par->initial_padding, + (AVRational){ 1, par->sample_rate }, (AVRational){ 1, 1000000000 })); } // look for a codec ID string specific to mkv to use, // if none are found, use AVI codes for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { - if (ff_mkv_codec_tags[j].id == codec->codec_id) { + if (ff_mkv_codec_tags[j].id == par->codec_id) { put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); native_id = 1; break; } } - if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 || - codec->codec_id == AV_CODEC_ID_VP9 || - codec->codec_id == AV_CODEC_ID_OPUS || - codec->codec_id == AV_CODEC_ID_VORBIS)) { + if (mkv->mode == MODE_WEBM && !(par->codec_id == AV_CODEC_ID_VP8 || + par->codec_id == AV_CODEC_ID_VP9 || + par->codec_id == AV_CODEC_ID_OPUS || + par->codec_id == AV_CODEC_ID_VORBIS)) { av_log(s, AV_LOG_ERROR, "Only VP8 or VP9 video and Vorbis or Opus audio are supported for WebM.\n"); return AVERROR(EINVAL); } - switch (codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: + mkv->have_video = 1; put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0) put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9 / av_q2d(st->avg_frame_rate)); if (!native_id && - ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) && - (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id) || - codec->codec_id == AV_CODEC_ID_SVQ1 || - codec->codec_id == AV_CODEC_ID_SVQ3 || - codec->codec_id == AV_CODEC_ID_CINEPAK)) + ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) && + (!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id) || + par->codec_id == AV_CODEC_ID_SVQ1 || + par->codec_id == AV_CODEC_ID_SVQ3 || + par->codec_id == AV_CODEC_ID_CINEPAK)) qt_id = 1; if (qt_id) @@ -818,9 +866,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); - // XXX: interlace flag? - put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); - put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); + + put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , par->width); + put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height); + + mkv_write_field_order(pb, par->field_order); // check both side data and metadata for stereo information, // write the result to the bitstream if any is found @@ -839,7 +889,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM"); subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0); - put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels); + put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , par->channels); put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); if (output_sample_rate) put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); @@ -851,7 +901,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, case AVMEDIA_TYPE_SUBTITLE: put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE); if (!native_id) { - av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id); + av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id); return AVERROR(ENOSYS); } break; @@ -859,7 +909,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n"); break; } - ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); + ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id); if (ret < 0) return ret; @@ -910,14 +960,20 @@ static int mkv_write_chapters(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { ebml_master chapteratom, chapterdisplay; AVChapter *c = s->chapters[i]; + int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale); + int64_t chapterend = av_rescale_q(c->end, c->time_base, scale); AVDictionaryEntry *t = NULL; + if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) { + av_log(s, AV_LOG_ERROR, + "Invalid chapter start (%"PRId64") or end (%"PRId64").\n", + chapterstart, chapterend); + return AVERROR_INVALIDDATA; + } chapteratom = start_ebml_master(pb, MATROSKA_ID_CHAPTERATOM, 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id); - put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMESTART, - av_rescale_q(c->start, c->time_base, scale)); - put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMEEND, - av_rescale_q(c->end, c->time_base, scale)); + put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); + put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMEEND, chapterend); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGHIDDEN , 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGENABLED, 1); if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { @@ -935,13 +991,16 @@ static int mkv_write_chapters(AVFormatContext *s) return 0; } -static void mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) +static int mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) { uint8_t *key = av_strdup(t->key); uint8_t *p = key; const uint8_t *lang = NULL; ebml_master tag; + if (!key) + return AVERROR(ENOMEM); + if ((p = strrchr(p, '-')) && (lang = av_convert_lang_to(p + 1, AV_LANG_ISO639_2_BIBL))) *p = 0; @@ -963,6 +1022,7 @@ static void mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) end_ebml_master(pb, tag); av_freep(&key); + return 0; } static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int elementid, @@ -986,10 +1046,16 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int eleme put_ebml_uint(s->pb, elementid, uid); end_ebml_master(s->pb, targets); - while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { if (av_strcasecmp(t->key, "title") && - av_strcasecmp(t->key, "encoding_tool")) - mkv_write_simpletag(s->pb, t); + av_strcasecmp(t->key, "encoding_tool") && + (elementid != MATROSKA_ID_TAGTARGETS_TRACKUID || + av_strcasecmp(t->key, "language"))) { + ret = mkv_write_simpletag(s->pb, t); + if (ret < 0) + return ret; + } + } end_ebml_master(s->pb, tag); return 0; @@ -1056,7 +1122,7 @@ static int mkv_write_attachments(AVFormatContext *s) AVDictionaryEntry *t; const char *mimetype = NULL; - if (st->codec->codec_type != AVMEDIA_TYPE_ATTACHMENT) + if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) continue; attached_file = start_ebml_master(pb, MATROSKA_ID_ATTACHEDFILE, 0); @@ -1070,13 +1136,18 @@ static int mkv_write_attachments(AVFormatContext *s) put_ebml_string(pb, MATROSKA_ID_FILENAME, t->value); if (t = av_dict_get(st->metadata, "mimetype", NULL, 0)) mimetype = t->value; - else if (st->codec->codec_id != AV_CODEC_ID_NONE ) { + else if (st->codecpar->codec_id != AV_CODEC_ID_NONE ) { int i; for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) - if (ff_mkv_mime_tags[i].id == st->codec->codec_id) { + if (ff_mkv_mime_tags[i].id == st->codecpar->codec_id) { mimetype = ff_mkv_mime_tags[i].str; break; } + for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) + if (ff_mkv_image_mime_tags[i].id == st->codecpar->codec_id) { + mimetype = ff_mkv_image_mime_tags[i].str; + break; + } } if (!mimetype) { av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and " @@ -1085,7 +1156,7 @@ static int mkv_write_attachments(AVFormatContext *s) } put_ebml_string(pb, MATROSKA_ID_FILEMIMETYPE, mimetype); - put_ebml_binary(pb, MATROSKA_ID_FILEDATA, st->codec->extradata, st->codec->extradata_size); + put_ebml_binary(pb, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size); put_ebml_uint(pb, MATROSKA_ID_FILEUID, av_lfg_get(&c)); end_ebml_master(pb, attached_file); } @@ -1117,7 +1188,7 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); put_ebml_string (pb, EBML_ID_DOCTYPE , s->oformat->name); - put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); + put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 4); put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); end_ebml_master(pb, ebml_header); @@ -1226,7 +1297,7 @@ static int mkv_blockgroup_size(int pkt_size) return size; } -static int ass_get_duration(const uint8_t *p) +static int ass_get_duration(AVFormatContext *s, const uint8_t *p) { int sh, sm, ss, sc, eh, em, es, ec; uint64_t start, end; @@ -1234,8 +1305,25 @@ static int ass_get_duration(const uint8_t *p) if (sscanf(p, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d", &sh, &sm, &ss, &sc, &eh, &em, &es, &ec) != 8) return 0; + + if (sh > 9 || sm > 59 || ss > 59 || sc > 99 || + eh > 9 || em > 59 || es > 59 || ec > 99) { + av_log(s, AV_LOG_WARNING, + "Non-standard time reference %d:%d:%d.%d,%d:%d:%d.%d\n", + sh, sm, ss, sc, eh, em, es, ec); + return 0; + } + start = 3600000 * sh + 60000 * sm + 1000 * ss + 10 * sc; end = 3600000 * eh + 60000 * em + 1000 * es + 10 * ec; + + if (start > end) { + av_log(s, AV_LOG_WARNING, + "Unexpected time reference %d:%d:%d.%d,%d:%d:%d.%d\n", + sh, sm, ss, sc, eh, em, es, ec); + return 0; + } + return end - start; } @@ -1249,7 +1337,7 @@ static int mkv_write_ass_blocks(AVFormatContext *s, AVIOContext *pb, char buffer[2048]; while (data_size) { - int duration = ass_get_duration(data); + int duration = ass_get_duration(s, data); max_duration = FFMAX(duration, max_duration); end = memchr(data, '\n', data_size); size = line_size = end ? end - data + 1 : data_size; @@ -1345,22 +1433,22 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, unsigned int blockid, AVPacket *pkt, int flags) { MatroskaMuxContext *mkv = s->priv_data; - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; uint8_t *data = NULL; int offset = 0, size = pkt->size; int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " - "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", + "pts %" PRId64 ", dts %" PRId64 ", duration %" PRId64 ", flags %d\n", avio_tell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); - if (codec->codec_id == AV_CODEC_ID_H264 && codec->extradata_size > 0 && - (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) + if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) ff_avc_parse_nal_units_buf(pkt->data, &data, &size); - else if (codec->codec_id == AV_CODEC_ID_HEVC && codec->extradata_size > 6 && - (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) + else if (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6 && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) /* extradata is Annex B, assume the bitstream is too and convert it */ ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL); - else if (codec->codec_id == AV_CODEC_ID_WAVPACK) { + else if (par->codec_id == AV_CODEC_ID_WAVPACK) { int ret = mkv_strip_wavpack(pkt->data, &data, &size); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Error stripping a WavPack packet.\n"); @@ -1369,7 +1457,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, } else data = pkt->data; - if (codec->codec_id == AV_CODEC_ID_PRORES) { + if (par->codec_id == AV_CODEC_ID_PRORES) { /* Matroska specification requires to remove the first QuickTime atom */ size -= 8; @@ -1447,7 +1535,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); int duration = pkt->duration; int ret; @@ -1460,8 +1548,11 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) ts += mkv->tracks[pkt->stream_index].ts_offset; if (!s->pb->seekable) { - if (!mkv->dyn_bc) - avio_open_dyn_buf(&mkv->dyn_bc); + if (!mkv->dyn_bc) { + ret = avio_open_dyn_buf(&mkv->dyn_bc); + if (ret < 0) + return ret; + } pb = mkv->dyn_bc; } @@ -1472,22 +1563,28 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) mkv->cluster_pts = FFMAX(0, ts); } - if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { + if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); - } else if (codec->codec_id == AV_CODEC_ID_SSA) { + } else if (par->codec_id == AV_CODEC_ID_SSA) { duration = mkv_write_ass_blocks(s, pb, pkt); - } else if (codec->codec_id == AV_CODEC_ID_SRT) { + } else if (par->codec_id == AV_CODEC_ID_SRT) { duration = mkv_write_srt_blocks(s, pb, pkt); } else { ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size)); - duration = pkt->convergence_duration; + duration = pkt->duration; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS + if (pkt->convergence_duration) + duration = pkt->convergence_duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 0); put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); end_ebml_master(pb, blockgroup); } - if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) { + if (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) { ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos); if (ret < 0) @@ -1501,7 +1598,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; - int codec_type = s->streams[pkt->stream_index]->codec->codec_type; + int codec_type = s->streams[pkt->stream_index]->codecpar->codec_type; int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); int cluster_size; int64_t cluster_time; @@ -1540,10 +1637,15 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_flush(s->pb); } + if (!mkv->cluster_pos) + avio_write_marker(s->pb, + av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, AV_TIME_BASE_Q), + keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); + // check if we have an audio packet cached if (mkv->cur_audio_pkt.size > 0) { ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); - av_free_packet(&mkv->cur_audio_pkt); + av_packet_unref(&mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); @@ -1554,12 +1656,7 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) // buffer an audio packet to ensure the packet containing the video // keyframe's timecode is contained in the same cluster for WebM if (codec_type == AVMEDIA_TYPE_AUDIO) { - mkv->cur_audio_pkt = *pkt; - if (pkt->buf) { - mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf); - ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); - } else - ret = av_dup_packet(&mkv->cur_audio_pkt); + ret = av_packet_ref(&mkv->cur_audio_pkt, pkt); } else ret = mkv_write_packet_internal(s, pkt); return ret; @@ -1584,7 +1681,7 @@ static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt) mkv_flush_dynbuf(s); avio_flush(s->pb); } - return 0; + return 1; } return mkv_write_packet(s, pkt); } @@ -1599,7 +1696,7 @@ static int mkv_write_trailer(AVFormatContext *s) // check if we have an audio packet cached if (mkv->cur_audio_pkt.size > 0) { ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); - av_free_packet(&mkv->cur_audio_pkt); + av_packet_unref(&mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); @@ -1744,8 +1841,8 @@ AVOutputFormat ff_webm_muxer = { .mime_type = "video/webm", .extensions = "webm", .priv_data_size = sizeof(MatroskaMuxContext), - .audio_codec = AV_CODEC_ID_VORBIS, - .video_codec = AV_CODEC_ID_VP8, + .audio_codec = CONFIG_LIBOPUS_ENCODER ? AV_CODEC_ID_OPUS : AV_CODEC_ID_VORBIS, + .video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, diff --git a/libavformat/md5enc.c b/libavformat/md5enc.c index 9249704..bd10df7 100644 --- a/libavformat/md5enc.c +++ b/libavformat/md5enc.c @@ -104,7 +104,7 @@ static int framemd5_write_packet(struct AVFormatContext *s, AVPacket *pkt) av_md5_init(c->md5); av_md5_update(c->md5, pkt->data, pkt->size); - snprintf(buf, sizeof(buf) - 64, "%d, %10"PRId64", %10"PRId64", %8d, %8d, ", + snprintf(buf, sizeof(buf) - 64, "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ", pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size); md5_finish(s, buf); return 0; diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index 12ddde3..08cdd71 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -70,7 +70,8 @@ static int md5_close(URLContext *h) if (*filename) { err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, + h->protocols, h); if (err) return err; err = ffurl_write(out, buf, i*2+1); @@ -86,7 +87,7 @@ static int md5_close(URLContext *h) } -URLProtocol ff_md5_protocol = { +const URLProtocol ff_md5_protocol = { .name = "md5", .url_open = md5_open, .url_write = md5_write, diff --git a/libavformat/mm.c b/libavformat/mm.c index 8c9cbd7..a94d261 100644 --- a/libavformat/mm.c +++ b/libavformat/mm.c @@ -54,7 +54,7 @@ #define MM_PALETTE_COUNT 128 #define MM_PALETTE_SIZE (MM_PALETTE_COUNT*3) -typedef struct { +typedef struct MmDemuxContext { unsigned int audio_pts, video_pts; } MmDemuxContext; @@ -109,11 +109,11 @@ static int read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MMVIDEO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = width; - st->codec->height = height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MMVIDEO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = width; + st->codecpar->height = height; avpriv_set_pts_info(st, 64, 1, frame_rate); /* audio stream */ @@ -121,12 +121,12 @@ static int read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->codec_id = AV_CODEC_ID_PCM_U8; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = 8000; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = 8000; avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */ } @@ -174,6 +174,12 @@ static int read_packet(AVFormatContext *s, return 0; case MM_TYPE_AUDIO : + if (s->nb_streams != 2) { + av_log(s, AV_LOG_ERROR, + "Unexpected audio packet, skipping\n"); + avio_skip(pb, length); + return AVERROR_INVALIDDATA; + } if (av_get_packet(s->pb, pkt, length)<0) return AVERROR(ENOMEM); pkt->size = length; diff --git a/libavformat/mmf.c b/libavformat/mmf.c index 61f1d7a..55aeff4 100644 --- a/libavformat/mmf.c +++ b/libavformat/mmf.c @@ -26,7 +26,7 @@ #include "pcm.h" #include "riff.h" -typedef struct { +typedef struct MMFContext { int64_t atrpos, atsqpos, awapos; int64_t data_size; } MMFContext; @@ -68,10 +68,10 @@ static int mmf_write_header(AVFormatContext *s) int64_t pos; int rate; - rate = mmf_rate_code(s->streams[0]->codec->sample_rate); + rate = mmf_rate_code(s->streams[0]->codecpar->sample_rate); if (rate < 0) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d\n", - s->streams[0]->codec->sample_rate); + s->streams[0]->codecpar->sample_rate); return -1; } @@ -107,7 +107,7 @@ static int mmf_write_header(AVFormatContext *s) mmf->awapos = ff_start_tag(pb, "Awa\x01"); - avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); + avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate); avio_flush(pb); @@ -155,7 +155,7 @@ static int mmf_write_trailer(AVFormatContext *s) /* "play wav" */ avio_w8(pb, 0); /* start time */ avio_w8(pb, 1); /* (channel << 6) | wavenum */ - gatetime = size * 500 / s->streams[0]->codec->sample_rate; + gatetime = size * 500 / s->streams[0]->codecpar->sample_rate; put_varlength(pb, gatetime); /* duration */ /* "nop" */ @@ -255,16 +255,16 @@ static int mmf_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_YAMAHA; - st->codec->sample_rate = rate; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = st->codec->sample_rate * - st->codec->bits_per_coded_sample; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_YAMAHA; + st->codecpar->sample_rate = rate; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->bits_per_coded_sample = 4; + st->codecpar->bit_rate = st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; } @@ -292,7 +292,7 @@ static int mmf_read_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_read(s->pb, pkt->data, pkt->size); if (ret < 0) - av_free_packet(pkt); + av_packet_unref(pkt); mmf->data_size -= ret; diff --git a/libavformat/mms.c b/libavformat/mms.c index fb16a3c..fc967c1 100644 --- a/libavformat/mms.c +++ b/libavformat/mms.c @@ -97,13 +97,15 @@ int ff_mms_asf_header_parser(MMSContext *mms) flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24); stream_id = flags & 0x7F; //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size, - //we can calcuate the packet size by stream_num. + //we can calculate the packet size by stream_num. //Please see function send_stream_selection_request(). if (mms->stream_num < MMS_MAX_STREAMS && 46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) { mms->streams = av_fast_realloc(mms->streams, &mms->nb_streams_allocated, (mms->stream_num + 1) * sizeof(MMSStream)); + if (!mms->streams) + return AVERROR(ENOMEM); mms->streams[mms->stream_num].id = stream_id; mms->stream_num++; } else { diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 5e9d0bc..4029b86 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -41,7 +41,7 @@ // see Ref 2.2.1.8 #define USERAGENT "User-Agent: NSPlayer/4.1.0.3856\r\n" // see Ref 2.2.1.4.33 -// the guid value can be changed to any valid value. +// the GUID value can be changed to any valid value. #define CLIENTGUID "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}\r\n" // see Ref 2.2.3 for packet type define: @@ -54,7 +54,7 @@ typedef enum { CHUNK_TYPE_STREAM_CHANGE = 0x4324, } ChunkType; -typedef struct { +typedef struct MMSHContext { MMSContext mms; int request_seq; ///< request packet sequence int chunk_seq; ///< data packet sequence @@ -123,7 +123,7 @@ static int read_data_packet(MMSHContext *mmsh, const int len) return AVERROR(EIO); } res = ffurl_read_complete(mms->mms_hd, mms->in_buffer, len); - av_dlog(NULL, "Data packet len = %d\n", len); + av_log(NULL, AV_LOG_TRACE, "Data packet len = %d\n", len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Read data packet failed!\n"); return AVERROR(EIO); @@ -157,7 +157,7 @@ static int get_http_header_data(MMSHContext *mmsh) if (mms->asf_header) { if (len != mms->asf_header_size) { mms->asf_header_size = len; - av_dlog(NULL, "Header len changed from %d to %d\n", + av_log(NULL, AV_LOG_TRACE, "Header len changed from %d to %d\n", mms->asf_header_size, len); av_freep(&mms->asf_header); } @@ -202,7 +202,7 @@ static int get_http_header_data(MMSHContext *mmsh) av_log(NULL, AV_LOG_ERROR, "Read other chunk type data failed!\n"); return AVERROR(EIO); } else { - av_dlog(NULL, "Skip chunk type %d \n", chunk_type); + av_log(NULL, AV_LOG_TRACE, "Skip chunk type %d \n", chunk_type); continue; } } @@ -230,7 +230,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path); if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, - &h->interrupt_callback) < 0) { + &h->interrupt_callback, h->protocols) < 0) { return AVERROR(EIO); } @@ -259,7 +259,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) ffurl_close(mms->mms_hd); memset(headers, 0, sizeof(headers)); if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, - &h->interrupt_callback)) < 0) { + &h->interrupt_callback, h->protocols)) < 0) { goto fail; } stream_selection = av_mallocz(mms->stream_num * 19 + 1); @@ -289,7 +289,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) av_log(NULL, AV_LOG_ERROR, "Build play request failed!\n"); goto fail; } - av_dlog(NULL, "out_buffer is %s", headers); + av_log(NULL, AV_LOG_TRACE, "out_buffer is %s", headers); av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); err = ffurl_connect(mms->mms_hd, NULL); @@ -303,12 +303,12 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) goto fail; } - av_dlog(NULL, "Connection successfully open\n"); + av_log(NULL, AV_LOG_TRACE, "Connection successfully open\n"); return 0; fail: av_freep(&stream_selection); mmsh_close(h); - av_dlog(NULL, "Connection failed with error %d\n", err); + av_log(NULL, AV_LOG_TRACE, "Connection failed with error %d\n", err); return err; } @@ -358,7 +358,7 @@ static int mmsh_read(URLContext *h, uint8_t *buf, int size) return res; } -URLProtocol ff_mmsh_protocol = { +const URLProtocol ff_mmsh_protocol = { .name = "mmsh", .url_open = mmsh_open, .url_read = mmsh_read, diff --git a/libavformat/mmst.c b/libavformat/mmst.c index 4f896e0..f3a5157 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -85,7 +85,7 @@ typedef enum { /*@}*/ } MMSSCPacketType; -typedef struct { +typedef struct MMSTContext { MMSContext mms; int outgoing_packet_seq; ///< Outgoing packet sequence number. char path[256]; ///< Path of the resource being asked for. @@ -208,11 +208,11 @@ static int send_media_file_request(MMSTContext *mmst) static void handle_packet_stream_changing_type(MMSTContext *mmst) { MMSContext *mms = &mmst->mms; - av_dlog(NULL, "Stream changing!\n"); + av_log(NULL, AV_LOG_TRACE, "Stream changing!\n"); // 40 is the packet header size, 7 is the prefix size. mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); - av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id); + av_log(NULL, AV_LOG_TRACE, "Changed header prefix to 0x%x", mmst->header_packet_id); } static int send_keepalive_packet(MMSTContext *mmst) @@ -272,7 +272,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) } length_remaining= AV_RL32(mms->in_buffer+8) + 4; - av_dlog(NULL, "Length remaining is %d\n", length_remaining); + av_log(NULL, AV_LOG_TRACE, "Length remaining is %d\n", length_remaining); // read the rest of the packet. if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { @@ -351,7 +351,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) } else if(packet_id_type == mmst->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { - av_dlog(NULL, "packet id type %d is old.", packet_id_type); + av_log(NULL, AV_LOG_TRACE, "packet id type %d is old.", packet_id_type); continue; } } @@ -377,7 +377,7 @@ static int mms_safe_send_recv(MMSTContext *mmst, if(send_fun) { int ret = send_fun(mmst); if (ret < 0) { - av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type); + av_log(NULL, AV_LOG_TRACE, "Send Packet error before expecting recv packet %d\n", expect_type); return ret; } } @@ -419,7 +419,7 @@ static int send_startup_packet(MMSTContext *mmst) char data_string[256]; MMSContext *mms = &mmst->mms; // SubscriberName is defined in MS specification linked below. - // The guid value can be any valid value. + // The GUID value can be any valid value. // http://download.microsoft.com/ // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf snprintf(data_string, sizeof(data_string), @@ -515,12 +515,12 @@ static int mms_open(URLContext *h, const char *uri, int flags) sizeof(mmst->path), uri); if(port<0) - port = 1755; // defaut mms protocol port + port = 1755; // default MMS protocol port // establish tcp connection. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols, h); if (err) goto fail; @@ -552,7 +552,7 @@ static int mms_open(URLContext *h, const char *uri, int flags) } err = ff_mms_asf_header_parser(mms); if (err) { - av_dlog(NULL, "asf header parsed failed!\n"); + av_log(NULL, AV_LOG_TRACE, "asf header parsed failed!\n"); goto fail; } mms->header_parsed = 1; @@ -569,11 +569,11 @@ static int mms_open(URLContext *h, const char *uri, int flags) if (err) { goto fail; } - av_dlog(NULL, "Leaving open (success)\n"); + av_log(NULL, AV_LOG_TRACE, "Leaving open (success)\n"); return 0; fail: mms_close(h); - av_dlog(NULL, "Leaving open (failure: %d)\n", err); + av_log(NULL, AV_LOG_TRACE, "Leaving open (failure: %d)\n", err); return err; } @@ -606,12 +606,12 @@ static int mms_read(URLContext *h, uint8_t *buf, int size) // copy the data to the packet buffer. result = ff_mms_read_data(mms, buf, size); if (result == 0) { - av_dlog(NULL, "Read ASF media packet size is zero!\n"); + av_log(NULL, AV_LOG_TRACE, "Read ASF media packet size is zero!\n"); break; } } } else { - av_dlog(NULL, "read packet error!\n"); + av_log(NULL, AV_LOG_TRACE, "read packet error!\n"); break; } } @@ -619,7 +619,7 @@ static int mms_read(URLContext *h, uint8_t *buf, int size) return result; } -URLProtocol ff_mmst_protocol = { +const URLProtocol ff_mmst_protocol = { .name = "mmst", .url_open = mms_open, .url_read = mms_read, diff --git a/libavformat/mov.c b/libavformat/mov.c index 60d171d..2ff5211 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -27,15 +27,16 @@ #include #include -//#define MOV_EXPORT_ALL_METADATA - #include "libavutil/attributes.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" +#include "libavutil/time_internal.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "libavcodec/ac3tab.h" #include "avformat.h" #include "internal.h" @@ -54,9 +55,6 @@ #include "qtpalette.h" -#undef NDEBUG -#include - /* those functions parse an atom */ /* links atom IDs to parse functions */ typedef struct MOVParseTableEntry { @@ -161,7 +159,11 @@ static int mov_read_mac_string(MOVContext *c, AVIOContext *pb, int len, for (i = 0; i < len; i++) { uint8_t t, c = avio_r8(pb); - if (c < 0x80 && p < end) + + if (p >= end) + continue; + + if (c < 0x80) *p++ = c; else PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;); @@ -200,47 +202,68 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len) if (ret < 0) return ret; + if (pkt.size >= 8 && id != AV_CODEC_ID_BMP) { + if (AV_RB64(pkt.data) == 0x89504e470d0a1a0a) { + id = AV_CODEC_ID_PNG; + } else { + id = AV_CODEC_ID_MJPEG; + } + } + st->disposition |= AV_DISPOSITION_ATTACHED_PIC; st->attached_pic = pkt; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = id; return 0; } +// 3GPP TS 26.244 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len) { char language[4] = { 0 }; - char buf[100]; + char buf[200], place[100]; uint16_t langcode = 0; - double longitude, latitude; + double longitude, latitude, altitude; const char *key = "location"; - if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) + if (len < 4 + 2 + 1 + 1 + 4 + 4 + 4) { + av_log(c->fc, AV_LOG_ERROR, "loci too short\n"); return AVERROR_INVALIDDATA; + } avio_skip(pb, 4); // version+flags langcode = avio_rb16(pb); ff_mov_lang_to_iso639(langcode, language); len -= 6; - len -= avio_get_str(pb, len, buf, sizeof(buf)); // place name - if (len < 1) + len -= avio_get_str(pb, len, place, sizeof(place)); + if (len < 1) { + av_log(c->fc, AV_LOG_ERROR, "place name too long\n"); return AVERROR_INVALIDDATA; + } avio_skip(pb, 1); // role len -= 1; - if (len < 14) + if (len < 12) { + av_log(c->fc, AV_LOG_ERROR, + "loci too short (%u bytes left, need at least %d)\n", len, 12); return AVERROR_INVALIDDATA; + } longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16); latitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16); + altitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16); // Try to output in the same format as the ?xyz field - snprintf(buf, sizeof(buf), "%+08.4f%+09.4f/", latitude, longitude); + snprintf(buf, sizeof(buf), "%+08.4f%+09.4f", latitude, longitude); + if (altitude) + av_strlcatf(buf, sizeof(buf), "%+f", altitude); + av_strlcatf(buf, sizeof(buf), "/%s", place); + if (*language && strcmp(language, "und")) { char key2[16]; snprintf(key2, sizeof(key2), "%s-%s", key, language); @@ -252,55 +275,99 @@ static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len) static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) { -#ifdef MOV_EXPORT_ALL_METADATA char tmp_key[5]; -#endif - char str[1024], key2[16], language[4] = {0}; + char *str, key2[32], language[4] = {0}; const char *key = NULL; uint16_t langcode = 0; - uint32_t data_type = 0, str_size; + uint32_t data_type = 0, str_size, str_size_alloc; int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL; + int raw = 0; switch (atom.type) { - case MKTAG(0xa9,'n','a','m'): key = "title"; break; - case MKTAG(0xa9,'a','u','t'): - case MKTAG(0xa9,'A','R','T'): key = "artist"; break; + case MKTAG( '@','P','R','M'): key = "premiere_version"; raw = 1; break; + case MKTAG( '@','P','R','Q'): key = "quicktime_version"; raw = 1; break; + case MKTAG( 'X','M','P','_'): + if (c->export_xmp) { key = "xmp"; raw = 1; } break; case MKTAG( 'a','A','R','T'): key = "album_artist"; break; - case MKTAG(0xa9,'w','r','t'): key = "composer"; break; - case MKTAG( 'c','p','r','t'): - case MKTAG(0xa9,'c','p','y'): key = "copyright"; break; - case MKTAG(0xa9,'c','m','t'): - case MKTAG(0xa9,'i','n','f'): key = "comment"; break; - case MKTAG(0xa9,'a','l','b'): key = "album"; break; - case MKTAG(0xa9,'d','a','y'): key = "date"; break; - case MKTAG(0xa9,'g','e','n'): key = "genre"; break; + case MKTAG( 'a','k','I','D'): key = "account_type"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 'a','p','I','D'): key = "account_id"; break; + case MKTAG( 'c','a','t','g'): key = "category"; break; + case MKTAG( 'c','p','i','l'): key = "compilation"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 'c','p','r','t'): key = "copyright"; break; + case MKTAG( 'd','e','s','c'): key = "description"; break; + case MKTAG( 'd','i','s','k'): key = "disc"; + parse = mov_metadata_track_or_disc_number; break; + case MKTAG( 'e','g','i','d'): key = "episode_uid"; + parse = mov_metadata_int8_no_padding; break; case MKTAG( 'g','n','r','e'): key = "genre"; parse = mov_metadata_gnre; break; - case MKTAG(0xa9,'t','o','o'): - case MKTAG(0xa9,'s','w','r'): key = "encoder"; break; - case MKTAG(0xa9,'e','n','c'): key = "encoder"; break; - case MKTAG(0xa9,'x','y','z'): key = "location"; break; - case MKTAG( 'd','e','s','c'): key = "description";break; + case MKTAG( 'h','d','v','d'): key = "hd_video"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 'k','e','y','w'): key = "keywords"; break; case MKTAG( 'l','d','e','s'): key = "synopsis"; break; - case MKTAG( 't','v','s','h'): key = "show"; break; - case MKTAG( 't','v','e','n'): key = "episode_id";break; - case MKTAG( 't','v','n','n'): key = "network"; break; + case MKTAG( 'l','o','c','i'): + return mov_metadata_loci(c, pb, atom.size); + case MKTAG( 'p','c','s','t'): key = "podcast"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 'p','g','a','p'): key = "gapless_playback"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 'p','u','r','d'): key = "purchase_date"; break; + case MKTAG( 'r','t','n','g'): key = "rating"; + parse = mov_metadata_int8_no_padding; break; + case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break; + case MKTAG( 's','o','a','l'): key = "sort_album"; break; + case MKTAG( 's','o','a','r'): key = "sort_artist"; break; + case MKTAG( 's','o','c','o'): key = "sort_composer"; break; + case MKTAG( 's','o','n','m'): key = "sort_name"; break; + case MKTAG( 's','o','s','n'): key = "sort_show"; break; + case MKTAG( 's','t','i','k'): key = "media_type"; + parse = mov_metadata_int8_no_padding; break; case MKTAG( 't','r','k','n'): key = "track"; parse = mov_metadata_track_or_disc_number; break; - case MKTAG( 'd','i','s','k'): key = "disc"; - parse = mov_metadata_track_or_disc_number; break; + case MKTAG( 't','v','e','n'): key = "episode_id"; break; case MKTAG( 't','v','e','s'): key = "episode_sort"; parse = mov_metadata_int8_bypass_padding; break; + case MKTAG( 't','v','n','n'): key = "network"; break; + case MKTAG( 't','v','s','h'): key = "show"; break; case MKTAG( 't','v','s','n'): key = "season_number"; parse = mov_metadata_int8_bypass_padding; break; - case MKTAG( 's','t','i','k'): key = "media_type"; - parse = mov_metadata_int8_no_padding; break; - case MKTAG( 'h','d','v','d'): key = "hd_video"; - parse = mov_metadata_int8_no_padding; break; - case MKTAG( 'p','g','a','p'): key = "gapless_playback"; - parse = mov_metadata_int8_no_padding; break; - case MKTAG( 'l','o','c','i'): - return mov_metadata_loci(c, pb, atom.size); + case MKTAG(0xa9,'A','R','T'): key = "artist"; break; + case MKTAG(0xa9,'P','R','D'): key = "producer"; break; + case MKTAG(0xa9,'a','l','b'): key = "album"; break; + case MKTAG(0xa9,'a','u','t'): key = "artist"; break; + case MKTAG(0xa9,'c','h','p'): key = "chapter"; break; + case MKTAG(0xa9,'c','m','t'): key = "comment"; break; + case MKTAG(0xa9,'c','o','m'): key = "composer"; break; + case MKTAG(0xa9,'c','p','y'): key = "copyright"; break; + case MKTAG(0xa9,'d','a','y'): key = "date"; break; + case MKTAG(0xa9,'d','i','r'): key = "director"; break; + case MKTAG(0xa9,'d','i','s'): key = "disclaimer"; break; + case MKTAG(0xa9,'e','d','1'): key = "edit_date"; break; + case MKTAG(0xa9,'e','n','c'): key = "encoder"; break; + case MKTAG(0xa9,'f','m','t'): key = "original_format"; break; + case MKTAG(0xa9,'g','e','n'): key = "genre"; break; + case MKTAG(0xa9,'g','r','p'): key = "grouping"; break; + case MKTAG(0xa9,'h','s','t'): key = "host_computer"; break; + case MKTAG(0xa9,'i','n','f'): key = "comment"; break; + case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break; + case MKTAG(0xa9,'m','a','k'): key = "make"; break; + case MKTAG(0xa9,'m','o','d'): key = "model"; break; + case MKTAG(0xa9,'n','a','m'): key = "title"; break; + case MKTAG(0xa9,'o','p','e'): key = "original_artist"; break; + case MKTAG(0xa9,'p','r','d'): key = "producer"; break; + case MKTAG(0xa9,'p','r','f'): key = "performers"; break; + case MKTAG(0xa9,'r','e','q'): key = "playback_requirements"; break; + case MKTAG(0xa9,'s','r','c'): key = "original_source"; break; + case MKTAG(0xa9,'s','t','3'): key = "subtitle"; break; + case MKTAG(0xa9,'s','w','r'): key = "encoder"; break; + case MKTAG(0xa9,'t','o','o'): key = "encoder"; break; + case MKTAG(0xa9,'t','r','k'): key = "track"; break; + case MKTAG(0xa9,'u','r','l'): key = "URL"; break; + case MKTAG(0xa9,'w','r','n'): key = "warning"; break; + case MKTAG(0xa9,'w','r','t'): key = "composer"; break; + case MKTAG(0xa9,'x','y','z'): key = "location"; break; } if (c->itunes_metadata && atom.size > 8) { @@ -320,7 +387,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } } else return 0; - } else if (atom.size > 4 && key && !c->itunes_metadata) { + } else if (atom.size > 4 && key && !c->itunes_metadata && !raw) { str_size = avio_rb16(pb); // string length langcode = avio_rb16(pb); ff_mov_lang_to_iso639(langcode, language); @@ -328,27 +395,33 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) } else str_size = atom.size; -#ifdef MOV_EXPORT_ALL_METADATA - if (!key) { + if (c->export_all && !key) { snprintf(tmp_key, 5, "%.4s", (char*)&atom.type); key = tmp_key; } -#endif if (!key) return 0; if (atom.size < 0) return AVERROR_INVALIDDATA; - str_size = FFMIN3(sizeof(str)-1, str_size, atom.size); + // allocate twice as much as worst-case + str_size_alloc = (raw ? str_size : str_size * 2) + 1; + str = av_malloc(str_size_alloc); + if (!str) + return AVERROR(ENOMEM); if (parse) parse(c, pb, str_size, key); else { - if (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff))) { // MAC Encoded - mov_read_mac_string(c, pb, str_size, str, sizeof(str)); + if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded + mov_read_mac_string(c, pb, str_size, str, str_size_alloc); } else { - avio_read(pb, str, str_size); + int ret = ffio_read_size(pb, str, str_size); + if (ret < 0) { + av_free(str); + return ret; + } str[str_size] = 0; } c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; @@ -358,10 +431,11 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_dict_set(&c->fc->metadata, key2, str, 0); } } - av_dlog(c->fc, "lang \"%3s\" ", language); - av_dlog(c->fc, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %"PRId64"\n", - key, str, (char*)&atom.type, str_size, atom.size); + av_log(c->fc, AV_LOG_TRACE, "lang \"%3s\" ", language); + av_log(c->fc, AV_LOG_TRACE, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %"PRId64"\n", + key, str, (char*)&atom.type, str_size_alloc, atom.size); + av_freep(&str); return 0; } @@ -370,6 +444,7 @@ static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom) int64_t start; int i, nb_chapters, str_len, version; char str[256+1]; + int ret; if ((atom.size -= 5) < 0) return 0; @@ -390,7 +465,9 @@ static int mov_read_chpl(MOVContext *c, AVIOContext *pb, MOVAtom atom) if ((atom.size -= 9+str_len) < 0) return 0; - avio_read(pb, str, str_len); + ret = ffio_read_size(pb, str, str_len); + if (ret < 0) + return ret; str[str_len] = 0; avpriv_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str); } @@ -411,16 +488,18 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb32(pb); // version + flags entries = avio_rb32(pb); - if (entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 || + if (!entries || + entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 || entries >= UINT_MAX / sizeof(*sc->drefs)) return AVERROR_INVALIDDATA; + sc->drefs_count = 0; av_free(sc->drefs); sc->drefs = av_mallocz(entries * sizeof(*sc->drefs)); if (!sc->drefs) return AVERROR(ENOMEM); sc->drefs_count = entries; - for (i = 0; i < sc->drefs_count; i++) { + for (i = 0; i < entries; i++) { MOVDref *dref = &sc->drefs[i]; uint32_t size = avio_rb32(pb); int64_t next = avio_tell(pb) + size - 4; @@ -430,18 +509,21 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) dref->type = avio_rl32(pb); avio_rb32(pb); // version + flags - av_dlog(c->fc, "type %.4s size %d\n", (char*)&dref->type, size); + av_log(c->fc, AV_LOG_TRACE, "type %.4s size %d\n", (char*)&dref->type, size); if (dref->type == MKTAG('a','l','i','s') && size > 150) { /* macintosh alias record */ uint16_t volume_len, len; int16_t type; + int ret; avio_skip(pb, 10); volume_len = avio_r8(pb); volume_len = FFMIN(volume_len, 27); - avio_read(pb, dref->volume, 27); + ret = ffio_read_size(pb, dref->volume, 27); + if (ret < 0) + return ret; dref->volume[volume_len] = 0; av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len); @@ -449,7 +531,9 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) len = avio_r8(pb); len = FFMIN(len, 63); - avio_read(pb, dref->filename, 63); + ret = ffio_read_size(pb, dref->filename, 63); + if (ret < 0) + return ret; dref->filename[len] = 0; av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len); @@ -476,14 +560,26 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) dref->path = av_mallocz(len+1); if (!dref->path) return AVERROR(ENOMEM); - avio_read(pb, dref->path, len); + + ret = ffio_read_size(pb, dref->path, len); + if (ret < 0) { + av_freep(&dref->path); + return ret; + } if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) { len -= volume_len; memmove(dref->path, dref->path+volume_len, len); dref->path[len] = 0; } + // trim string of any ending zeros + for (j = len - 1; j >= 0; j--) { + if (dref->path[j] == 0) + len--; + else + break; + } for (j = 0; j < len; j++) - if (dref->path[j] == ':') + if (dref->path[j] == ':' || dref->path[j] == 0) dref->path[j] = '/'; av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path); } else if (type == 0) { // directory name @@ -491,7 +587,12 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) dref->dir = av_malloc(len+1); if (!dref->dir) return AVERROR(ENOMEM); - avio_read(pb, dref->dir, len); + + ret = ffio_read_size(pb, dref->dir, len); + if (ret < 0) { + av_freep(&dref->dir); + return ret; + } dref->dir[len] = 0; for (j = 0; j < len; j++) if (dref->dir[j] == ':') @@ -500,6 +601,11 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) } else avio_skip(pb, len); } + } else { + av_log(c->fc, AV_LOG_DEBUG, "Unknown dref type 0x08%x size %d\n", + dref->type, size); + entries--; + i--; } avio_seek(pb, next, SEEK_SET); } @@ -511,6 +617,9 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st; uint32_t type; uint32_t av_unused ctype; + int64_t title_size; + char *title_str; + int ret; if (c->fc->nb_streams < 1) // meta before first trak return 0; @@ -524,22 +633,41 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom) ctype = avio_rl32(pb); type = avio_rl32(pb); /* component subtype */ - av_dlog(c->fc, "ctype= %.4s (0x%08x)\n", (char*)&ctype, ctype); - av_dlog(c->fc, "stype= %.4s\n", (char*)&type); + av_log(c->fc, AV_LOG_TRACE, "ctype= %.4s (0x%08x)\n", (char*)&ctype, ctype); + av_log(c->fc, AV_LOG_TRACE, "stype= %.4s\n", (char*)&type); if (type == MKTAG('v','i','d','e')) - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; else if (type == MKTAG('s','o','u','n')) - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; else if (type == MKTAG('m','1','a',' ')) - st->codec->codec_id = AV_CODEC_ID_MP2; + st->codecpar->codec_id = AV_CODEC_ID_MP2; else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p'))) - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; avio_rb32(pb); /* component manufacture */ avio_rb32(pb); /* component flags */ avio_rb32(pb); /* component flags mask */ + title_size = atom.size - 24; + if (title_size > 0) { + title_str = av_malloc(title_size + 1); /* Add null terminator */ + if (!title_str) + return AVERROR(ENOMEM); + + ret = ffio_read_size(pb, title_str, title_size); + if (ret < 0) { + av_freep(&title_str); + return ret; + } + title_str[title_size] = 0; + if (title_str[0]) { + int off = (!c->isom && title_str[0] == title_size - 1); + av_dict_set(&st->metadata, "handler_name", title_str + off, 0); + } + av_freep(&title_str); + } + return 0; } @@ -573,23 +701,35 @@ static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + enum AVAudioServiceType *ast; int ac3info, acmod, lfeon, bsmod; if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; + ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, + sizeof(*ast)); + if (!ast) + return AVERROR(ENOMEM); + ac3info = avio_rb24(pb); bsmod = (ac3info >> 14) & 0x7; acmod = (ac3info >> 11) & 0x7; lfeon = (ac3info >> 10) & 0x1; - st->codec->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; - st->codec->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; + st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; if (lfeon) - st->codec->channel_layout |= AV_CH_LOW_FREQUENCY; - st->codec->audio_service_type = bsmod; - if (st->codec->channels > 1 && bsmod == 0x7) - st->codec->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; + st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; + *ast = bsmod; + if (st->codecpar->channels > 1 && bsmod == 0x7) + *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE; + +#if FF_API_LAVF_AVCTX + FF_DISABLE_DEPRECATION_WARNINGS + st->codec->audio_service_type = *ast; + FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -597,12 +737,18 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + enum AVAudioServiceType *ast; int eac3info, acmod, lfeon, bsmod; if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; + ast = (enum AVAudioServiceType*)av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, + sizeof(*ast)); + if (!ast) + return AVERROR(ENOMEM); + /* No need to parse fields for additional independent substreams and its * associated dependent substreams since libavcodec's E-AC-3 decoder * does not support them yet. */ @@ -611,13 +757,19 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) bsmod = (eac3info >> 12) & 0x1f; acmod = (eac3info >> 9) & 0x7; lfeon = (eac3info >> 8) & 0x1; - st->codec->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; if (lfeon) - st->codec->channel_layout |= AV_CH_LOW_FREQUENCY; - st->codec->channels = av_get_channel_layout_nb_channels(st->codec->channel_layout); - st->codec->audio_service_type = bsmod; - if (st->codec->channels > 1 && bsmod == 0x7) - st->codec->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; + st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; + st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); + *ast = bsmod; + if (st->codecpar->channels > 1 && bsmod == 0x7) + *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE; + +#if FF_API_LAVF_AVCTX + FF_DISABLE_DEPRECATION_WARNINGS + st->codec->audio_service_type = *ast; + FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -633,6 +785,9 @@ static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (atom.size < 16) return 0; + /* skip version and flags */ + avio_skip(pb, 4); + ff_mov_read_chan(c->fc, pb, st, atom.size - 4); return 0; @@ -646,9 +801,7 @@ static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - ff_get_wav_header(pb, st->codec, atom.size); - - return 0; + return ff_get_wav_header(c->fc, pb, st->codecpar, atom.size); } static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom) @@ -691,8 +844,10 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) char minor_ver_str[11]; /* 32 bit integer -> 10 digits + null */ char* comp_brands_str; uint8_t type[5] = {0}; + int ret = ffio_read_size(pb, type, 4); + if (ret < 0) + return ret; - avio_read(pb, type, 4); if (strcmp(type, "qt ")) c->isom = 1; av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); @@ -707,7 +862,12 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */ if (!comp_brands_str) return AVERROR(ENOMEM); - avio_read(pb, comp_brands_str, comp_brand_size); + + ret = ffio_read_size(pb, comp_brands_str, comp_brand_size); + if (ret < 0) { + av_freep(&comp_brands_str); + return ret; + } comp_brands_str[comp_brand_size] = 0; av_dict_set(&c->fc->metadata, "compatible_brands", comp_brands_str, 0); av_freep(&comp_brands_str); @@ -731,7 +891,7 @@ static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) { c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8; - av_dlog(c->fc, "moof offset %"PRIx64"\n", c->fragment.moof_offset); + av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset); return mov_read_default(c, pb, atom); } @@ -739,12 +899,12 @@ static void mov_metadata_creation_time(AVDictionary **metadata, time_t time) { char buffer[32]; if (time) { - struct tm *ptm; + struct tm *ptm, tmbuf; time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ - ptm = gmtime(&time); + ptm = gmtime_r(&time, &tmbuf); if (!ptm) return; - strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm); - av_dict_set(metadata, "creation_time", buffer, 0); + if (strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm)) + av_dict_set(metadata, "creation_time", buffer, 0); } } @@ -809,7 +969,7 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) mov_metadata_creation_time(&c->fc->metadata, creation_time); c->time_scale = avio_rb32(pb); /* time scale */ - av_dlog(c->fc, "time scale = %i\n", c->time_scale); + av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale); c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */ avio_rb32(pb); /* preferred scale */ @@ -834,6 +994,7 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_smi(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -844,14 +1005,18 @@ static int mov_read_smi(MOVContext *c, AVIOContext *pb, MOVAtom atom) // 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 = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(atom.size + 0x5a + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = 0x5a + atom.size; - memcpy(st->codec->extradata, "SVQ3", 4); // fake - avio_read(pb, st->codec->extradata + 0x5a, atom.size); - av_dlog(c->fc, "Reading SMI %"PRId64" %s\n", atom.size, st->codec->extradata + 0x5a); + st->codecpar->extradata_size = 0x5a + atom.size; + memcpy(st->codecpar->extradata, "SVQ3", 4); // fake + + ret = ffio_read_size(pb, st->codecpar->extradata + 0x5a, atom.size); + if (ret < 0) + return ret; + + av_log(c->fc, AV_LOG_TRACE, "Reading SMI %"PRId64" %s\n", atom.size, st->codecpar->extradata + 0x5a); return 0; } @@ -865,20 +1030,20 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = c->fc->streams[c->fc->nb_streams-1]; little_endian = !!avio_rb16(pb); - av_dlog(c->fc, "enda %d\n", little_endian); + av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian); if (little_endian == 1) { - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_PCM_S24BE: - st->codec->codec_id = AV_CODEC_ID_PCM_S24LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; break; case AV_CODEC_ID_PCM_S32BE: - st->codec->codec_id = AV_CODEC_ID_PCM_S32LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; break; case AV_CODEC_ID_PCM_F32BE: - st->codec->codec_id = AV_CODEC_ID_PCM_F32LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; break; case AV_CODEC_ID_PCM_F64BE: - st->codec->codec_id = AV_CODEC_ID_PCM_F64LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE; break; default: break; @@ -887,6 +1052,82 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + char color_parameter_type[5] = { 0 }; + uint16_t color_primaries, color_trc, color_matrix; + int ret; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams - 1]; + + ret = ffio_read_size(pb, color_parameter_type, 4); + if (ret < 0) + return ret; + if (strncmp(color_parameter_type, "nclx", 4) && + strncmp(color_parameter_type, "nclc", 4)) { + av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n", + color_parameter_type); + return 0; + } + + color_primaries = avio_rb16(pb); + color_trc = avio_rb16(pb); + color_matrix = avio_rb16(pb); + + av_log(c->fc, AV_LOG_TRACE, + "%s: pri %"PRIu16" trc %"PRIu16" matrix %"PRIu16"", + color_parameter_type, color_primaries, color_trc, color_matrix); + + if (!strncmp(color_parameter_type, "nclx", 4)) { + uint8_t color_range = avio_r8(pb) >> 7; + av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range); + if (color_range) + st->codecpar->color_range = AVCOL_RANGE_JPEG; + else + st->codecpar->color_range = AVCOL_RANGE_MPEG; + + if (!av_color_primaries_name(color_primaries)) + color_primaries = AVCOL_PRI_UNSPECIFIED; + if (!av_color_transfer_name(color_trc)) + color_trc = AVCOL_TRC_UNSPECIFIED; + if (!av_color_space_name(color_matrix)) + color_matrix = AVCOL_SPC_UNSPECIFIED; + + st->codecpar->color_primaries = color_primaries; + st->codecpar->color_trc = color_trc; + st->codecpar->color_space = color_matrix; + } else if (!strncmp(color_parameter_type, "nclc", 4)) { + /* color primaries, Table 4-4 */ + switch (color_primaries) { + case 1: st->codecpar->color_primaries = AVCOL_PRI_BT709; break; + case 5: st->codecpar->color_primaries = AVCOL_PRI_SMPTE170M; break; + case 6: st->codecpar->color_primaries = AVCOL_PRI_SMPTE240M; break; + case 9: st->codecpar->color_primaries = AVCOL_PRI_BT2020; break; + case 10: st->codecpar->color_primaries = AVCOL_PRI_SMPTE431; break; + case 11: st->codecpar->color_primaries = AVCOL_PRI_SMPTE432; break; + } + /* color transfer, Table 4-5 */ + switch (color_trc) { + case 1: st->codecpar->color_trc = AVCOL_TRC_BT709; break; + case 7: st->codecpar->color_trc = AVCOL_TRC_SMPTE240M; break; + case 17: st->codecpar->color_trc = AVCOL_TRC_SMPTE428; break; + } + /* color matrix, Table 4-6 */ + switch (color_matrix) { + case 1: st->codecpar->color_space = AVCOL_SPC_BT709; break; + case 6: st->codecpar->color_space = AVCOL_SPC_BT470BG; break; + case 7: st->codecpar->color_space = AVCOL_SPC_SMPTE240M; break; + case 9: st->codecpar->color_space = AVCOL_SPC_BT2020_NCL; break; + } + } + av_log(c->fc, AV_LOG_TRACE, "\n"); + + return 0; +} + static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -916,12 +1157,12 @@ static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) { av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order); } - st->codec->field_order = decoded_field_order; + st->codecpar->field_order = decoded_field_order; return 0; } -/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */ +/* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */ static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -932,24 +1173,29 @@ static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (c->fc->nb_streams < 1) // will happen with jp2 files return 0; st= c->fc->streams[c->fc->nb_streams-1]; - size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE; + size= (uint64_t)st->codecpar->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE; if (size > INT_MAX || (uint64_t)atom.size > INT_MAX) return AVERROR_INVALIDDATA; - if ((err = av_reallocp(&st->codec->extradata, size)) < 0) { - st->codec->extradata_size = 0; + if ((err = av_reallocp(&st->codecpar->extradata, size)) < 0) { + st->codecpar->extradata_size = 0; return err; } - buf = st->codec->extradata + st->codec->extradata_size; - st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE; + buf = st->codecpar->extradata + st->codecpar->extradata_size; + st->codecpar->extradata_size= size - AV_INPUT_BUFFER_PADDING_SIZE; AV_WB32( buf , atom.size + 8); AV_WL32( buf + 4, atom.type); - avio_read(pb, buf + 8, atom.size); + + err = ffio_read_size(pb, buf + 8, atom.size); + if (err < 0) + return err; + return 0; } static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -958,16 +1204,18 @@ static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom) if ((uint64_t)atom.size > (1<<30)) return AVERROR_INVALIDDATA; - if (st->codec->codec_id == AV_CODEC_ID_QDM2 || st->codec->codec_id == AV_CODEC_ID_QDMC) { + if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 || st->codecpar->codec_id == AV_CODEC_ID_QDMC) { // pass all frma atom to codec, needed at least for QDMC and QDM2 - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(atom.size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = atom.size; - avio_read(pb, st->codec->extradata, atom.size); + st->codecpar->extradata_size = atom.size; + + ret = ffio_read_size(pb, st->codecpar->extradata, atom.size); + if (ret < 0) + return ret; } else if (atom.size > 8) { /* to read frma, esds atoms */ - int ret; if ((ret = mov_read_default(c, pb, atom)) < 0) return ret; } else @@ -982,6 +1230,7 @@ static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -999,12 +1248,16 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (type == MKTAG('f','i','e','l') && size == atom.size) return mov_read_default(c, pb, atom); } - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(atom.size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = atom.size; - avio_read(pb, st->codec->extradata, atom.size); + st->codecpar->extradata_size = atom.size; + + ret = ffio_read_size(pb, st->codecpar->extradata, atom.size); + if (ret < 0) + return ret; + return 0; } @@ -1012,6 +1265,7 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; uint8_t profile_level; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -1024,13 +1278,17 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) if ((profile_level & 0xf0) != 0xc0) return 0; - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(atom.size - 7 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(atom.size - 7 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = atom.size - 7; + st->codecpar->extradata_size = atom.size - 7; avio_seek(pb, 6, SEEK_CUR); - avio_read(pb, st->codec->extradata, st->codec->extradata_size); + + ret = ffio_read_size(pb, st->codecpar->extradata, st->codecpar->extradata_size); + if (ret < 0) + return ret; + return 0; } @@ -1042,6 +1300,7 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -1052,13 +1311,17 @@ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom) if ((uint64_t)atom.size > (1<<30)) return AVERROR_INVALIDDATA; - av_free(st->codec->extradata); - st->codec->extradata = av_mallocz(atom.size - 40 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_free(st->codecpar->extradata); + st->codecpar->extradata = av_mallocz(atom.size - 40 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = atom.size - 40; + st->codecpar->extradata_size = atom.size - 40; avio_skip(pb, 40); - avio_read(pb, st->codec->extradata, atom.size - 40); + + ret = ffio_read_size(pb, st->codecpar->extradata, atom.size - 40); + if (ret < 0) + return ret; + return 0; } @@ -1128,24 +1391,24 @@ static int mov_codec_id(AVStream *st, uint32_t format) (format & 0xFFFF) == 'T' + ('S' << 8))) id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF); - if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) { - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - } else if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO && - /* skip old asf mpeg4 tag */ + if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) { + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && + /* skip old ASF MPEG-4 tag */ format && format != MKTAG('m','p','4','s')) { id = ff_codec_get_id(ff_codec_movvideo_tags, format); if (id <= 0) id = ff_codec_get_id(ff_codec_bmp_tags, format); if (id > 0) - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { id = ff_codec_get_id(ff_codec_movsubtitle_tags, format); if (id > 0) - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; } } - st->codec->codec_tag = format; + st->codecpar->codec_tag = format; return id; } @@ -1164,8 +1427,8 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, avio_rb32(pb); /* temporal quality */ avio_rb32(pb); /* spatial quality */ - st->codec->width = avio_rb16(pb); /* width */ - st->codec->height = avio_rb16(pb); /* height */ + st->codecpar->width = avio_rb16(pb); /* width */ + st->codecpar->height = avio_rb16(pb); /* height */ avio_rb32(pb); /* horiz resolution */ avio_rb32(pb); /* vert resolution */ @@ -1184,19 +1447,19 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, /* codec_tag YV12 triggers an UV swap in rawdec.c */ if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) - st->codec->codec_tag = MKTAG('I', '4', '2', '0'); - /* Flash Media Server uses tag H263 with Sorenson Spark */ - if (st->codec->codec_tag == MKTAG('H','2','6','3') && + st->codecpar->codec_tag = MKTAG('I', '4', '2', '0'); + /* Flash Media Server uses tag H.263 with Sorenson Spark */ + if (st->codecpar->codec_tag == MKTAG('H','2','6','3') && !memcmp(codec_name, "Sorenson H263", 13)) - st->codec->codec_id = AV_CODEC_ID_FLV1; + st->codecpar->codec_id = AV_CODEC_ID_FLV1; - st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */ + st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */ color_table_id = avio_rb16(pb); /* colortable id */ - av_dlog(c->fc, "depth %d, ctab id %d\n", - st->codec->bits_per_coded_sample, color_table_id); + av_log(c->fc, AV_LOG_TRACE, "depth %d, ctab id %d\n", + st->codecpar->bits_per_coded_sample, color_table_id); /* figure out the palette situation */ - color_depth = st->codec->bits_per_coded_sample & 0x1F; - color_greyscale = st->codec->bits_per_coded_sample & 0x20; + color_depth = st->codecpar->bits_per_coded_sample & 0x1F; + color_greyscale = st->codecpar->bits_per_coded_sample & 0x20; /* if the depth is 2, 4, or 8 bpp, file is palettized */ if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) { @@ -1207,7 +1470,7 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, if (color_greyscale) { int color_index, color_dec; /* compute the greyscale palette */ - st->codec->bits_per_coded_sample = color_depth; + st->codecpar->bits_per_coded_sample = color_depth; color_count = 1 << color_depth; color_index = 255; color_dec = 256 / (color_count - 1); @@ -1270,17 +1533,17 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, avio_rb16(pb); /* revision level */ avio_rb32(pb); /* vendor */ - st->codec->channels = avio_rb16(pb); /* channel count */ - st->codec->bits_per_coded_sample = avio_rb16(pb); /* sample size */ - av_dlog(c->fc, "audio channels %d\n", st->codec->channels); + st->codecpar->channels = avio_rb16(pb); /* channel count */ + st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */ + av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels); sc->audio_cid = avio_rb16(pb); avio_rb16(pb); /* packet size = 0 */ - st->codec->sample_rate = ((avio_rb32(pb) >> 16)); + st->codecpar->sample_rate = ((avio_rb32(pb) >> 16)); // Read QT version 1 fields. In version 0 these do not exist. - av_dlog(c->fc, "version =%d, isom =%d\n", version, c->isom); + av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom); if (!c->isom) { if (version == 1) { sc->samples_per_frame = avio_rb32(pb); @@ -1289,48 +1552,57 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, avio_rb32(pb); /* bytes per sample */ } else if (version == 2) { avio_rb32(pb); /* sizeof struct only */ - st->codec->sample_rate = av_int2double(avio_rb64(pb)); - st->codec->channels = avio_rb32(pb); + st->codecpar->sample_rate = av_int2double(avio_rb64(pb)); + st->codecpar->channels = avio_rb32(pb); avio_rb32(pb); /* always 0x7F000000 */ - st->codec->bits_per_coded_sample = avio_rb32(pb); + st->codecpar->bits_per_coded_sample = avio_rb32(pb); flags = avio_rb32(pb); /* lpcm format specific flag */ sc->bytes_per_frame = avio_rb32(pb); sc->samples_per_frame = avio_rb32(pb); - if (st->codec->codec_tag == MKTAG('l','p','c','m')) - st->codec->codec_id = - ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, + if (st->codecpar->codec_tag == MKTAG('l','p','c','m')) + st->codecpar->codec_id = + ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample, flags); } + if (version == 0 || (version == 1 && sc->audio_cid != -2)) { + /* can't correctly handle variable sized packet as audio unit */ + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_MP2: + case AV_CODEC_ID_MP3: + st->need_parsing = AVSTREAM_PARSE_FULL; + break; + } + } } - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_PCM_S8: case AV_CODEC_ID_PCM_U8: - if (st->codec->bits_per_coded_sample == 16) - st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; + if (st->codecpar->bits_per_coded_sample == 16) + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: - if (st->codec->bits_per_coded_sample == 8) - st->codec->codec_id = AV_CODEC_ID_PCM_S8; - else if (st->codec->bits_per_coded_sample == 24) - st->codec->codec_id = - st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ? + if (st->codecpar->bits_per_coded_sample == 8) + st->codecpar->codec_id = AV_CODEC_ID_PCM_S8; + else if (st->codecpar->bits_per_coded_sample == 24) + st->codecpar->codec_id = + st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE; break; /* set values for old format before stsd version 1 appeared */ case AV_CODEC_ID_MACE3: sc->samples_per_frame = 6; - sc->bytes_per_frame = 2 * st->codec->channels; + sc->bytes_per_frame = 2 * st->codecpar->channels; break; case AV_CODEC_ID_MACE6: sc->samples_per_frame = 6; - sc->bytes_per_frame = 1 * st->codec->channels; + sc->bytes_per_frame = 1 * st->codecpar->channels; break; case AV_CODEC_ID_ADPCM_IMA_QT: sc->samples_per_frame = 64; - sc->bytes_per_frame = 34 * st->codec->channels; + sc->bytes_per_frame = 34 * st->codecpar->channels; break; case AV_CODEC_ID_GSM: sc->samples_per_frame = 160; @@ -1340,25 +1612,25 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, break; } - bits_per_sample = av_get_bits_per_sample(st->codec->codec_id); + bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id); if (bits_per_sample) { - st->codec->bits_per_coded_sample = bits_per_sample; - sc->sample_size = (bits_per_sample >> 3) * st->codec->channels; + st->codecpar->bits_per_coded_sample = bits_per_sample; + sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels; } } static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb, AVStream *st, MOVStreamContext *sc, - int size) + int64_t size) { // ttxt stsd contains display flags, justification, background // color, fonts, and default styles, so fake an atom to read it MOVAtom fake_atom = { .size = size }; // mp4s contains a regular esds atom - if (st->codec->codec_tag != AV_RL32("mp4s")) + if (st->codecpar->codec_tag != AV_RL32("mp4s")) mov_read_glbl(c, pb, fake_atom); - st->codec->width = sc->width; - st->codec->height = sc->height; + st->codecpar->width = sc->width; + st->codecpar->height = sc->height; } static uint32_t yuv_to_rgba(uint32_t ycbcr) @@ -1380,15 +1652,15 @@ static uint32_t yuv_to_rgba(uint32_t ycbcr) static int mov_rewrite_dvd_sub_extradata(AVStream *st) { char buf[256] = {0}; - uint8_t *src = st->codec->extradata; + uint8_t *src = st->codecpar->extradata; int i; - if (st->codec->extradata_size != 64) + if (st->codecpar->extradata_size != 64) return 0; - if (st->codec->width > 0 && st->codec->height > 0) + if (st->codecpar->width > 0 && st->codecpar->height > 0) snprintf(buf, sizeof(buf), "size: %dx%d\n", - st->codec->width, st->codec->height); + st->codecpar->width, st->codecpar->height); av_strlcat(buf, "palette: ", sizeof(buf)); for (i = 0; i < 16; i++) { @@ -1401,27 +1673,31 @@ static int mov_rewrite_dvd_sub_extradata(AVStream *st) if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf)) return 0; - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; - st->codec->extradata = av_mallocz(strlen(buf) + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; + st->codecpar->extradata = av_mallocz(strlen(buf) + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = strlen(buf); - memcpy(st->codec->extradata, buf, st->codec->extradata_size); + st->codecpar->extradata_size = strlen(buf); + memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size); return 0; } static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb, AVStream *st, MOVStreamContext *sc, - int size) + int64_t size) { - if (st->codec->codec_tag == MKTAG('t','m','c','d')) { - st->codec->extradata_size = size; - st->codec->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + int ret; + + if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) { + st->codecpar->extradata_size = size; + st->codecpar->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - avio_read(pb, st->codec->extradata, size); + ret = ffio_read_size(pb, st->codecpar->extradata, size); + if (ret < 0) + return ret; } else { /* other codec type, just skip (rtp, mp4s ...) */ avio_skip(pb, size); @@ -1432,56 +1708,59 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb, static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, AVStream *st, MOVStreamContext *sc) { - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - !st->codec->sample_rate && sc->time_scale > 1) - st->codec->sample_rate = sc->time_scale; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + !st->codecpar->sample_rate && sc->time_scale > 1) + st->codecpar->sample_rate = sc->time_scale; /* special codec parameters handling */ - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { #if CONFIG_DV_DEMUXER case AV_CODEC_ID_DVAUDIO: - c->dv_fctx = avformat_alloc_context(); + c->dv_fctx = avformat_alloc_context(); + if (!c->dv_fctx) { + av_log(c->fc, AV_LOG_ERROR, "dv demux context alloc error\n"); + return AVERROR(ENOMEM); + } c->dv_demux = avpriv_dv_init_demux(c->dv_fctx); if (!c->dv_demux) { av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n"); return AVERROR(ENOMEM); } sc->dv_audio_container = 1; - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; #endif /* no ifdef since parameters are always those */ case AV_CODEC_ID_QCELP: - st->codec->channels = 1; + st->codecpar->channels = 1; // force sample rate for qcelp when not stored in mov - if (st->codec->codec_tag != MKTAG('Q','c','l','p')) - st->codec->sample_rate = 8000; + if (st->codecpar->codec_tag != MKTAG('Q','c','l','p')) + st->codecpar->sample_rate = 8000; break; case AV_CODEC_ID_AMR_NB: - st->codec->channels = 1; + st->codecpar->channels = 1; /* force sample rate for amr, stsd in 3gp does not store sample rate */ - st->codec->sample_rate = 8000; + st->codecpar->sample_rate = 8000; break; case AV_CODEC_ID_AMR_WB: - st->codec->channels = 1; - st->codec->sample_rate = 16000; + st->codecpar->channels = 1; + st->codecpar->sample_rate = 16000; break; case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: /* force type after stsd for m1a hdlr */ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->need_parsing = AVSTREAM_PARSE_FULL; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; break; case AV_CODEC_ID_GSM: case AV_CODEC_ID_ADPCM_MS: case AV_CODEC_ID_ADPCM_IMA_WAV: case AV_CODEC_ID_ILBC: - st->codec->block_align = sc->bytes_per_frame; + st->codecpar->block_align = sc->bytes_per_frame; break; case AV_CODEC_ID_ALAC: - if (st->codec->extradata_size == 36) { - st->codec->channels = AV_RB8 (st->codec->extradata + 21); - st->codec->sample_rate = AV_RB32(st->codec->extradata + 32); + if (st->codecpar->extradata_size == 36) { + st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21); + st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32); } break; case AV_CODEC_ID_VC1: @@ -1495,15 +1774,16 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb, int codec_tag, int format, - int size) + int64_t size) { int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format); if (codec_tag && - (codec_tag == AV_RL32("avc1") || - codec_tag == AV_RL32("hvc1") || + (codec_tag == AV_RL32("hvc1") || codec_tag == AV_RL32("hev1") || (codec_tag != format && + // prores is allowed to have differing data format and codec tag + codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") && (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id : codec_tag != MKTAG('j','p','e','g'))))) { /* Multiple fourcc, we skip JPEG. This is not correct, we should @@ -1537,7 +1817,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) int ret, dref_id = 1; MOVAtom a = { AV_RL32("stsd") }; int64_t start_pos = avio_tell(pb); - uint32_t size = avio_rb32(pb); /* size */ + int64_t size = avio_rb32(pb); /* size */ uint32_t format = avio_rl32(pb); /* data format */ if (size >= 16) { @@ -1545,31 +1825,32 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) avio_rb16(pb); /* reserved */ dref_id = avio_rb16(pb); } else { - av_log(c->fc, AV_LOG_ERROR, "invalid size %"PRIu32" in stsd\n", size); + av_log(c->fc, AV_LOG_ERROR, + "invalid size %"PRId64" in stsd\n", size); return AVERROR_INVALIDDATA; } - if (mov_skip_multiple_stsd(c, pb, st->codec->codec_tag, format, + if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format, size - (avio_tell(pb) - start_pos))) continue; - sc->pseudo_stream_id = st->codec->codec_tag ? -1 : pseudo_stream_id; + sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id; sc->dref_id= dref_id; id = mov_codec_id(st, format); - av_dlog(c->fc, "size=%"PRIu32" 4CC= %"PRIu8"%"PRIu8"%"PRIu8"%"PRIu8" codec_type=%d\n", size, - (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, - (format >> 24) & 0xff, st->codec->codec_type); + av_log(c->fc, AV_LOG_TRACE, + "size=%"PRId64" format=0x%08x codec_type=%d\n", + size, format, st->codecpar->codec_type); - if (st->codec->codec_type==AVMEDIA_TYPE_VIDEO) { - st->codec->codec_id = id; + if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) { + st->codecpar->codec_id = id; mov_parse_stsd_video(c, pb, st, sc); - } else if (st->codec->codec_type==AVMEDIA_TYPE_AUDIO) { - st->codec->codec_id = id; + } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) { + st->codecpar->codec_id = id; mov_parse_stsd_audio(c, pb, st, sc); - } else if (st->codec->codec_type==AVMEDIA_TYPE_SUBTITLE){ - st->codec->codec_id = id; + } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){ + st->codecpar->codec_id = id; mov_parse_stsd_subtitle(c, pb, st, sc, size - (avio_tell(pb) - start_pos)); } else { @@ -1585,6 +1866,19 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) return ret; } else if (a.size > 0) avio_skip(pb, a.size); + + if (sc->extradata) { + int extra_size = st->codecpar->extradata_size; + + /* Move the current stream extradata to the stream context one. */ + sc->extradata_size[pseudo_stream_id] = extra_size; + sc->extradata[pseudo_stream_id] = av_malloc(extra_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!sc->extradata[pseudo_stream_id]) + return AVERROR(ENOMEM); + memcpy(sc->extradata[pseudo_stream_id], st->codecpar->extradata, extra_size); + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; + } } if (pb->eof_reached) @@ -1595,13 +1889,48 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int entries; + AVStream *st; + MOVStreamContext *sc; + int ret, entries; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams - 1]; + sc = st->priv_data; avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ entries = avio_rb32(pb); - return ff_mov_read_stsd_entries(c, pb, entries); + if (sc->extradata) { + av_log(c->fc, AV_LOG_ERROR, + "Duplicate stsd found in this track.\n"); + return AVERROR_INVALIDDATA; + } + + /* Prepare space for hosting multiple extradata. */ + sc->extradata = av_mallocz_array(entries, sizeof(*sc->extradata)); + if (!sc->extradata) + return AVERROR(ENOMEM); + + sc->stsd_count = entries; + sc->extradata_size = av_mallocz_array(sc->stsd_count, sizeof(*sc->extradata_size)); + if (!sc->extradata_size) + return AVERROR(ENOMEM); + + ret = ff_mov_read_stsd_entries(c, pb, sc->stsd_count); + if (ret < 0) + return ret; + + /* Restore back the primary extradata. */ + av_free(st->codecpar->extradata); + st->codecpar->extradata_size = sc->extradata_size[0]; + st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]); + + return 0; } static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) @@ -1620,7 +1949,7 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) entries = avio_rb32(pb); - av_dlog(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); + av_log(c->fc, AV_LOG_TRACE, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries); if (!entries) return 0; @@ -1634,6 +1963,13 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stsc_data[i].first = avio_rb32(pb); sc->stsc_data[i].count = avio_rb32(pb); sc->stsc_data[i].id = avio_rb32(pb); + if (sc->stsc_data[i].id <= 0 || sc->stsc_data[i].id > sc->stsd_count) { + sc->stsc_data[i].id = 1; + if (c->fc->error_recognition & AV_EF_EXPLODE) { + av_log(c->fc, AV_LOG_ERROR, "Invalid stsc index.\n"); + return AVERROR_INVALIDDATA; + } + } } sc->stsc_count = i; @@ -1644,6 +1980,24 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static inline int mov_stsc_index_valid(int index, int count) +{ + return index + 1 < count; +} + +/* Compute the samples value for the stsc entry at the given index. */ +static inline int mov_get_stsc_samples(MOVStreamContext *sc, int index) +{ + int chunk_count; + + if (mov_stsc_index_valid(index, sc->stsc_count)) + chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first; + else + chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1); + + return sc->stsc_data[index].count * chunk_count; +} + static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -1666,7 +2020,7 @@ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < entries && !pb->eof_reached; i++) { sc->stps_data[i] = avio_rb32(pb); - //av_dlog(c->fc, "stps %d\n", sc->stps_data[i]); + //av_log(c->fc, AV_LOG_TRACE, "stps %d\n", sc->stps_data[i]); } sc->stps_count = i; @@ -1693,7 +2047,7 @@ static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom) entries = avio_rb32(pb); - av_dlog(c->fc, "keyframe_count = %d\n", entries); + av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %d\n", entries); if (!entries) { @@ -1709,7 +2063,7 @@ static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < entries && !pb->eof_reached; i++) { sc->keyframes[i] = avio_rb32(pb); - //av_dlog(c->fc, "keyframes[]=%d\n", sc->keyframes[i]); + //av_log(c->fc, AV_LOG_TRACE, "keyframes[]=%d\n", sc->keyframes[i]); } sc->keyframe_count = i; @@ -1727,6 +2081,7 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned int i, entries, sample_size, field_size, num_bytes; GetBitContext gb; unsigned char* buf; + int ret; if (c->fc->nb_streams < 1) return 0; @@ -1748,7 +2103,7 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) } entries = avio_rb32(pb); - av_dlog(c->fc, "sample_size = %d sample_count = %d\n", sc->sample_size, entries); + av_log(c->fc, AV_LOG_TRACE, "sample_size = %d sample_count = %d\n", sc->sample_size, entries); sc->sample_count = entries; if (sample_size) @@ -1769,16 +2124,17 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) num_bytes = (entries*field_size+4)>>3; - buf = av_malloc(num_bytes+FF_INPUT_BUFFER_PADDING_SIZE); + buf = av_malloc(num_bytes+AV_INPUT_BUFFER_PADDING_SIZE); if (!buf) { av_freep(&sc->sample_sizes); return AVERROR(ENOMEM); } - if (avio_read(pb, buf, num_bytes) < num_bytes) { + ret = ffio_read_size(pb, buf, num_bytes); + if (ret < 0) { av_freep(&sc->sample_sizes); av_free(buf); - return AVERROR_INVALIDDATA; + return ret; } init_get_bits(&gb, buf, 8*num_bytes); @@ -1790,10 +2146,11 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->sample_count = i; + av_free(buf); + if (pb->eof_reached) return AVERROR_EOF; - av_free(buf); return 0; } @@ -1814,7 +2171,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb24(pb); /* flags */ entries = avio_rb32(pb); - av_dlog(c->fc, "track[%i].stts.entries = %i\n", + av_log(c->fc, AV_LOG_TRACE, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries); if (!entries) @@ -1840,7 +2197,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stts_data[i].count= sample_count; sc->stts_data[i].duration= sample_duration; - av_dlog(c->fc, "sample_count=%d, sample_duration=%d\n", + av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n", sample_count, sample_duration); duration+=(int64_t)sample_duration*sample_count; @@ -1874,13 +2231,15 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb24(pb); /* flags */ entries = avio_rb32(pb); - av_dlog(c->fc, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries); + av_log(c->fc, AV_LOG_TRACE, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries); + + av_freep(&sc->ctts_data); if (!entries) return 0; if (entries >= UINT_MAX / sizeof(*sc->ctts_data)) return AVERROR_INVALIDDATA; - sc->ctts_data = av_malloc(entries * sizeof(*sc->ctts_data)); + sc->ctts_data = av_realloc(NULL, entries * sizeof(*sc->ctts_data)); if (!sc->ctts_data) return AVERROR(ENOMEM); @@ -1899,7 +2258,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (pb->eof_reached) return AVERROR_EOF; - av_dlog(c->fc, "dts shift %d\n", sc->dts_shift); + av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift); return 0; } @@ -1961,17 +2320,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (sc->time_offset < 0) sc->time_offset = av_rescale(sc->time_offset, sc->time_scale, mov->time_scale); current_dts = -sc->time_offset; - if (sc->ctts_data && sc->stts_data && sc->stts_data[0].duration && - sc->ctts_data[0].duration / sc->stts_data[0].duration > 16) { - /* more than 16 frames delay, dts are likely wrong - this happens with files created by iMovie */ - sc->wrong_dts = 1; - st->codec->has_b_frames = 1; - } } /* only use old uncompressed audio chunk demuxing when stts specifies it */ - if (!(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && + if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && sc->stts_count == 1 && sc->stts_data[0].duration == 1)) { unsigned int current_sample = 0; unsigned int stts_sample = 0; @@ -1998,7 +2350,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) for (i = 0; i < sc->chunk_count; i++) { current_offset = sc->chunk_offsets[i]; - while (stsc_index + 1 < sc->stsc_count && + while (mov_stsc_index_valid(stsc_index, sc->stsc_count) && i + 1 == sc->stsc_data[stsc_index + 1].first) stsc_index++; for (j = 0; j < sc->stsc_data[stsc_index].count; j++) { @@ -2036,7 +2388,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) e->size = sample_size; e->min_distance = distance; e->flags = keyframe ? AVINDEX_KEYFRAME : 0; - av_dlog(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " + av_log(mov->fc, AV_LOG_TRACE, "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); } @@ -2054,7 +2406,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } } if (st->duration > 0) - st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration; + st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration; } else { unsigned chunk_samples, total = 0; @@ -2078,14 +2430,14 @@ static void mov_build_index(MOVContext *mov, AVStream *st) count = (chunk_samples+1023) / 1024; } - if (i < sc->stsc_count - 1) + if (mov_stsc_index_valid(i, sc->stsc_count)) chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first; else chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1); total += chunk_count * count; } - av_dlog(mov->fc, "chunk count %d\n", total); + av_log(mov->fc, AV_LOG_TRACE, "chunk count %d\n", total); if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries) return; if (av_reallocp_array(&st->index_entries, @@ -2099,7 +2451,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) // populate index for (i = 0; i < sc->chunk_count; i++) { current_offset = sc->chunk_offsets[i]; - if (stsc_index + 1 < sc->stsc_count && + if (mov_stsc_index_valid(stsc_index, sc->stsc_count) && i + 1 == sc->stsc_data[stsc_index + 1].first) stsc_index++; chunk_samples = sc->stsc_data[stsc_index].count; @@ -2108,6 +2460,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st) AVIndexEntry *e; unsigned size, samples; + if (sc->samples_per_frame > 1 && !sc->bytes_per_frame) { + avpriv_request_sample(mov->fc, + "Zero bytes per frame, but %d samples per frame", + sc->samples_per_frame); + return; + } + if (sc->samples_per_frame >= 160) { // gsm samples = sc->samples_per_frame; size = sc->bytes_per_frame; @@ -2132,7 +2491,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) e->size = size; e->min_distance = 0; e->flags = AVINDEX_KEYFRAME; - av_dlog(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", " + av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", " "size %d, duration %d\n", st->index, i, current_offset, current_dts, size, samples); @@ -2144,8 +2503,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } } -static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref, - AVIOInterruptCB *int_cb) +static int mov_open_dref(AVFormatContext *s, AVIOContext **pb, char *src, + MOVDref *ref) { /* try relative path, we do not try the absolute because it can leak information about our system to an attacker */ @@ -2180,7 +2539,7 @@ static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref, av_strlcat(filename, ref->path + l + 1, 1024); - if (!avio_open2(pb, filename, AVIO_FLAG_READ, int_cb, NULL)) + if (!s->io_open(s, pb, filename, AVIO_FLAG_READ, NULL)) return 0; } } @@ -2201,7 +2560,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (!sc) return AVERROR(ENOMEM); st->priv_data = sc; - st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; sc->ffindex = st->index; if ((ret = mov_read_default(c, pb, atom)) < 0) @@ -2228,32 +2587,42 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { MOVDref *dref = &sc->drefs[sc->dref_id - 1]; - if (mov_open_dref(&sc->pb, c->fc->filename, dref, &c->fc->interrupt_callback) < 0) - av_log(c->fc, AV_LOG_ERROR, - "stream %d, error opening alias: path='%s', dir='%s', " - "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n", + if (c->enable_drefs) { + if (mov_open_dref(c->fc, &sc->pb, c->fc->filename, dref) < 0) + av_log(c->fc, AV_LOG_ERROR, + "stream %d, error opening alias: path='%s', dir='%s', " + "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n", + st->index, dref->path, dref->dir, dref->filename, + dref->volume, dref->nlvl_from, dref->nlvl_to); + } else { + av_log(c->fc, AV_LOG_WARNING, + "Skipped opening external track: " + "stream %d, alias: path='%s', dir='%s', " + "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d." + "Set enable_drefs to allow this.\n", st->index, dref->path, dref->dir, dref->filename, dref->volume, dref->nlvl_from, dref->nlvl_to); + } } else sc->pb = c->fc->pb; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (!st->sample_aspect_ratio.num && - (st->codec->width != sc->width || st->codec->height != sc->height)) { - st->sample_aspect_ratio = av_d2q(((double)st->codec->height * sc->width) / - ((double)st->codec->width * sc->height), INT_MAX); + (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) { + st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) / + ((double)st->codecpar->width * sc->height), INT_MAX); } } // done for ai5q, ai52, ai55, ai1q, ai12 and ai15. - if (!st->codec->extradata_size && st->codec->codec_id == AV_CODEC_ID_H264 && - TAG_IS_AVCI(st->codec->codec_tag)) { + if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 && + TAG_IS_AVCI(st->codecpar->codec_tag)) { ret = ff_generate_avci_extradata(st); if (ret < 0) return ret; } - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { #if CONFIG_H261_DECODER case AV_CODEC_ID_H261: #endif @@ -2263,14 +2632,16 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) #if CONFIG_MPEG4_DECODER case AV_CODEC_ID_MPEG4: #endif - st->codec->width = 0; /* let decoder init width/height */ - st->codec->height= 0; + st->codecpar->width = 0; /* let decoder init width/height */ + st->codecpar->height= 0; + break; + case AV_CODEC_ID_MP3: + st->need_parsing = AVSTREAM_PARSE_FULL; break; } /* Do not need those anymore. */ av_freep(&sc->chunk_offsets); - av_freep(&sc->stsc_data); av_freep(&sc->sample_sizes); av_freep(&sc->keyframes); av_freep(&sc->stts_data); @@ -2289,7 +2660,7 @@ static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } -static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size) +static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int64_t size) { int64_t end = avio_tell(pb) + size; uint8_t *key = NULL, *val = NULL; @@ -2298,6 +2669,7 @@ static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size) for (i = 0; i < 2; i++) { uint8_t **p; uint32_t len, tag; + int ret; if (end - avio_tell(pb) <= 12) break; @@ -2322,7 +2694,11 @@ static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size) *p = av_malloc(len + 1); if (!*p) break; - avio_read(pb, *p, len); + ret = ffio_read_size(pb, *p, len); + if (ret < 0) { + av_freep(p); + return ret; + } (*p)[len] = 0; } @@ -2457,19 +2833,13 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) - sc->display_matrix[i * 3 + j] = display_matrix[j][i]; + sc->display_matrix[i * 3 + j] = display_matrix[i][j]; } // transform the display width/height according to the matrix - // skip this if the display matrix is the default identity matrix - // or if it is rotating the picture, ex iPhone 3GS + // skip this when the display matrix is the identity one // to keep the same scale, use [width height 1<<16] - if (width && height && - ((display_matrix[0][0] != 65536 || - display_matrix[1][1] != 65536) && - !display_matrix[0][1] && - !display_matrix[1][0] && - !display_matrix[2][0] && !display_matrix[2][1])) { + if (width && height && sc->display_matrix) { for (i = 0; i < 2; i++) disp_transform[i] = (int64_t) width * display_matrix[0][i] + @@ -2477,9 +2847,10 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ((int64_t) display_matrix[2][i] << 16); //sample aspect ratio is new width/height divided by old width/height - st->sample_aspect_ratio = av_d2q( - ((double) disp_transform[0] * height) / - ((double) disp_transform[1] * width), INT_MAX); + if (disp_transform[0] > 0 && disp_transform[1] > 0) + st->sample_aspect_ratio = av_d2q( + ((double) disp_transform[0] * height) / + ((double) disp_transform[1] * width), INT_MAX); } return 0; } @@ -2518,7 +2889,7 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb32(pb) : trex->size; frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ? avio_rb32(pb) : trex->flags; - av_dlog(c->fc, "frag flags 0x%x\n", frag->flags); + av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags); return 0; } @@ -2551,6 +2922,36 @@ static int mov_read_trex(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + MOVFragment *frag = &c->fragment; + AVStream *st = NULL; + MOVStreamContext *sc; + int version, i; + + for (i = 0; i < c->fc->nb_streams; i++) { + if (c->fc->streams[i]->id == frag->track_id) { + st = c->fc->streams[i]; + break; + } + } + if (!st) { + av_log(c->fc, AV_LOG_ERROR, "could not find corresponding track id %d\n", frag->track_id); + return AVERROR_INVALIDDATA; + } + sc = st->priv_data; + if (sc->pseudo_stream_id + 1 != frag->stsd_id) + return 0; + version = avio_r8(pb); + avio_rb24(pb); /* flags */ + if (version) { + sc->track_end = avio_rb64(pb); + } else { + sc->track_end = avio_rb32(pb); + } + return 0; +} + static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVFragment *frag = &c->fragment; @@ -2561,7 +2962,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) int64_t dts; int data_offset = 0; unsigned entries, first_sample_flags = frag->flags; - int flags, distance, i, found_keyframe = 0, err; + int flags, distance, i, err; for (i = 0; i < c->fc->nb_streams; i++) { if (c->fc->streams[i]->id == frag->track_id) { @@ -2579,7 +2980,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_r8(pb); /* version */ flags = avio_rb24(pb); entries = avio_rb32(pb); - av_dlog(c->fc, "flags 0x%x entries %d\n", flags, entries); + av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %d\n", flags, entries); /* Always assume the presence of composition time offsets. * Without this assumption, for instance, we cannot deal with a track in fragmented movies that meet the following. @@ -2609,7 +3010,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) dts = sc->track_end - sc->time_offset; offset = frag->base_data_offset + data_offset; distance = 0; - av_dlog(c->fc, "first sample flags 0x%x\n", first_sample_flags); + av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags); for (i = 0; i < entries && !pb->eof_reached; i++) { unsigned sample_size = frag->size; int sample_flags = i ? frag->flags : first_sample_flags; @@ -2623,17 +3024,17 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->ctts_data[sc->ctts_count].duration = (flags & MOV_TRUN_SAMPLE_CTS) ? avio_rb32(pb) : 0; sc->ctts_count++; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) keyframe = 1; - else if (!found_keyframe) - keyframe = found_keyframe = + else + keyframe = !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC | MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES)); if (keyframe) distance = 0; av_add_index_entry(st, offset, dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0); - av_dlog(c->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " + av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " "size %d, distance %d, keyframe %d\n", st->index, sc->sample_count+i, offset, dts, sample_size, distance, keyframe); distance++; @@ -2703,7 +3104,10 @@ static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_free(cmov_data); return AVERROR(ENOMEM); } - avio_read(pb, cmov_data, cmov_len); + ret = ffio_read_size(pb, cmov_data, cmov_len); + if (ret < 0) + goto free_and_return; + if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) goto free_and_return; if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) @@ -2758,7 +3162,7 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_WARNING, "multiple edit list entries, " "a/v desync might occur, patch welcome\n"); - av_dlog(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count); + av_log(c->fc, AV_LOG_TRACE, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count); return 0; } @@ -2766,6 +3170,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('a','v','s','s'), mov_read_extradata }, { MKTAG('c','h','p','l'), mov_read_chpl }, { MKTAG('c','o','6','4'), mov_read_stco }, +{ MKTAG('c','o','l','r'), mov_read_colr }, { MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */ { MKTAG('d','i','n','f'), mov_read_default }, { MKTAG('d','r','e','f'), mov_read_dref }, @@ -2802,6 +3207,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('s','t','t','s'), mov_read_stts }, { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */ { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */ +{ MKTAG('t','f','d','t'), mov_read_tfdt }, { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ { MKTAG('t','r','a','k'), mov_read_trak }, { MKTAG('t','r','a','f'), mov_read_default }, @@ -2841,7 +3247,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) a.size = avio_rb32(pb); a.type = avio_rl32(pb); } - av_dlog(c->fc, "type: %08x '%.4s' parent:'%.4s' sz: %"PRId64" %"PRId64" %"PRId64"\n", + av_log(c->fc, AV_LOG_TRACE, "type: %08x '%.4s' parent:'%.4s' sz: %"PRId64" %"PRId64" %"PRId64"\n", a.type, (char*)&a.type, (char*)&atom.type, a.size, total_size, atom.size); total_size += 8; if (a.size == 1) { /* 64 bit extended size */ @@ -3034,7 +3440,7 @@ static int mov_read_close(AVFormatContext *s) } av_freep(&sc->drefs); if (sc->pb && sc->pb != s->pb) - avio_close(sc->pb); + ff_format_io_close(s, &sc->pb); av_freep(&sc->chunk_offsets); av_freep(&sc->stsc_data); @@ -3044,6 +3450,11 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->stps_data); av_freep(&sc->rap_group); av_freep(&sc->display_matrix); + + for (j = 0; j < sc->stsd_count; j++) + av_free(sc->extradata[j]); + av_freep(&sc->extradata); + av_freep(&sc->extradata_size); } if (mov->dv_demux) { @@ -3082,7 +3493,7 @@ static int mov_read_header(AVFormatContext *s) mov_read_close(s); return AVERROR_INVALIDDATA; } - av_dlog(mov->fc, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb)); + av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb)); if (pb->seekable && mov->chapter_track > 0) mov_read_chapters(s); @@ -3091,12 +3502,12 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - if (st->codec->width <= 0 || st->codec->height <= 0) { - st->codec->width = sc->width; - st->codec->height = sc->height; + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (st->codecpar->width <= 0 || st->codecpar->height <= 0) { + st->codecpar->width = sc->width; + st->codecpar->height = sc->height; } - if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) { + if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) { if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0) return err; } @@ -3108,7 +3519,7 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; if (st->duration > 0) - st->codec->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration; + st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration; } } @@ -3116,7 +3527,7 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: err = ff_replaygain_export(st, s->metadata); if (err < 0) { @@ -3160,7 +3571,7 @@ static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st) if (msc->pb && msc->current_sample < avst->nb_index_entries) { AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample]; int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale); - av_dlog(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); + av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); if (!sample || (!s->pb->seekable && current_sample->pos < sample->pos) || (s->pb->seekable && ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && @@ -3175,6 +3586,29 @@ static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st) return sample; } +static int mov_change_extradata(MOVStreamContext *sc, AVPacket *pkt) +{ + uint8_t *side, *extradata; + int extradata_size; + + /* Save the current index. */ + sc->last_stsd_index = sc->stsc_data[sc->stsc_index].id - 1; + + /* Notify the decoder that extradata changed. */ + extradata_size = sc->extradata_size[sc->last_stsd_index]; + extradata = sc->extradata[sc->last_stsd_index]; + if (extradata_size > 0 && extradata) { + side = av_packet_new_side_data(pkt, + AV_PKT_DATA_NEW_EXTRADATA, + extradata_size); + if (!side) + return AVERROR(ENOMEM); + memcpy(side, extradata, extradata_size); + } + + return 0; +} + static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) { MOVContext *mov = s->priv_data; @@ -3193,7 +3627,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || s->pb->eof_reached) return AVERROR_EOF; - av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb)); + av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb)); goto retry; } sc = st->priv_data; @@ -3243,8 +3677,6 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) sc->ctts_index++; sc->ctts_sample = 0; } - if (sc->wrong_dts) - pkt->dts = AV_NOPTS_VALUE; } else { int64_t next_dts = (sc->current_sample < st->nb_index_entries) ? st->index_entries[sc->current_sample].timestamp : st->duration; @@ -3255,8 +3687,26 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) goto retry; pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0; pkt->pos = sample->pos; - av_dlog(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", + av_log(s, AV_LOG_TRACE, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %"PRId64"\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration); + + /* Multiple stsd handling. */ + if (sc->stsc_data) { + /* Keep track of the stsc index for the given sample, then check + * if the stsd index is different from the last used one. */ + sc->stsc_sample++; + if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) && + mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) { + sc->stsc_index++; + sc->stsc_sample = 0; + /* Do not check indexes after a switch. */ + } else if (sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) { + ret = mov_change_extradata(sc, pkt); + if (ret < 0) + return ret; + } + } + return 0; } @@ -3267,13 +3717,13 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int i; sample = av_index_search_timestamp(st, timestamp, flags); - av_dlog(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); + av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp) sample = 0; if (sample < 0) /* not sure what to do */ return AVERROR_INVALIDDATA; sc->current_sample = sample; - av_dlog(s, "stream %d, found sample %d\n", st->index, sc->current_sample); + av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample); /* adjust ctts index */ if (sc->ctts_data) { time_sample = 0; @@ -3287,13 +3737,26 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, time_sample = next; } } + + /* adjust stsd index */ + time_sample = 0; + for (i = 0; i < sc->stsc_count; i++) { + int next = time_sample + mov_get_stsc_samples(sc, i); + if (next > sc->current_sample) { + sc->stsc_index = i; + sc->stsc_sample = sc->current_sample - time_sample; + break; + } + time_sample = next; + } + return sample; } static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) { + MOVContext *mc = s->priv_data; AVStream *st; - int64_t seek_timestamp, timestamp; int sample; int i; @@ -3307,23 +3770,67 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti if (sample < 0) return sample; - /* adjust seek timestamp to found sample timestamp */ - seek_timestamp = st->index_entries[sample].timestamp; + if (mc->seek_individually) { + /* adjust seek timestamp to found sample timestamp */ + int64_t seek_timestamp = st->index_entries[sample].timestamp; - for (i = 0; i < s->nb_streams; i++) { - st = s->streams[i]; - if (stream_index == i) - continue; + for (i = 0; i < s->nb_streams; i++) { + int64_t timestamp; + st = s->streams[i]; + if (stream_index == i) + continue; - timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base); - mov_seek_stream(s, st, timestamp, flags); + timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base); + mov_seek_stream(s, st, timestamp, flags); + } + } else { + for (i = 0; i < s->nb_streams; i++) { + MOVStreamContext *sc; + st = s->streams[i]; + sc = st->priv_data; + sc->current_sample = 0; + } + while (1) { + MOVStreamContext *sc; + AVIndexEntry *entry = mov_find_next_sample(s, &st); + if (!entry) + return AVERROR_INVALIDDATA; + sc = st->priv_data; + if (sc->ffindex == stream_index && sc->current_sample == sample) + break; + sc->current_sample++; + } } return 0; } +#define OFFSET(x) offsetof(MOVContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption mov_options[] = { + {"seek_streams_individually", + "Seek each stream individually to the to the closest point", + OFFSET(seek_individually), AV_OPT_TYPE_INT, { .i64 = 1 }, + 0, 1, FLAGS}, + { "export_all", "Export unrecognized metadata entries", OFFSET(export_all), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS }, + { "export_xmp", "Export full XMP metadata", OFFSET(export_xmp), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS }, + { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS }, + { NULL }, +}; + +static const AVClass mov_class = { + .class_name = "mov,mp4,m4a,3gp,3g2,mj2", + .item_name = av_default_item_name, + .option = mov_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_mov_demuxer = { .name = "mov,mp4,m4a,3gp,3g2,mj2", .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), + .priv_class = &mov_class, .priv_data_size = sizeof(MOVContext), .extensions = "mov,mp4,m4a,3gp,3g2,mj2", .read_probe = mov_probe, diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c index aa7ba10..19f657a 100644 --- a/libavformat/mov_chan.c +++ b/libavformat/mov_chan.c @@ -556,7 +556,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, bitmap = avio_rb32(pb); num_descr = avio_rb32(pb); - av_dlog(s, "chan: layout=%u bitmap=%u num_descr=%u\n", + av_log(s, AV_LOG_TRACE, "chan: layout=%u bitmap=%u num_descr=%u\n", layout_tag, bitmap, num_descr); if (size < 12ULL + num_descr * 20ULL) @@ -565,6 +565,11 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, label_mask = 0; for (i = 0; i < num_descr; i++) { uint32_t label; + if (pb->eof_reached) { + av_log(s, AV_LOG_ERROR, + "reached EOF while reading channel layout\n"); + return AVERROR_INVALIDDATA; + } label = avio_rb32(pb); // mChannelLabel avio_rb32(pb); // mChannelFlags avio_rl32(pb); // mCoordinates[0] @@ -581,9 +586,9 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, } if (layout_tag == 0) { if (label_mask) - st->codec->channel_layout = label_mask; + st->codecpar->channel_layout = label_mask; } else - st->codec->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap); + st->codecpar->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap); return 0; } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 8af3c34..31b940a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -33,7 +33,7 @@ #include "avc.h" #include "libavcodec/get_bits.h" #include "libavcodec/put_bits.h" -#include "libavcodec/vc1.h" +#include "libavcodec/vc1_common.h" #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/intfloat.h" @@ -44,13 +44,10 @@ #include "rtpenc.h" #include "mov_chan.h" -#undef NDEBUG -#include - static const AVOption options[] = { { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, - { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, @@ -58,6 +55,12 @@ static const AVOption options[] = { { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, @@ -67,6 +70,9 @@ static const AVOption options[] = { { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; @@ -282,8 +288,8 @@ static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track) */ static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track) { - avio_write(pb, track->enc->extradata, track->enc->extradata_size); - return track->enc->extradata_size; + avio_write(pb, track->par->extradata, track->par->extradata_size); + return track->par->extradata_size; } static void put_descr(AVIOContext *pb, int tag, unsigned int size) @@ -297,6 +303,7 @@ static void put_descr(AVIOContext *pb, int tag, unsigned int size) static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic { + AVCPBProperties *props; int64_t pos = avio_tell(pb); int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0; @@ -313,30 +320,32 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic put_descr(pb, 0x04, 13 + decoder_specific_info_len); // Object type indication - if ((track->enc->codec_id == AV_CODEC_ID_MP2 || - track->enc->codec_id == AV_CODEC_ID_MP3) && - track->enc->sample_rate > 24000) + if ((track->par->codec_id == AV_CODEC_ID_MP2 || + track->par->codec_id == AV_CODEC_ID_MP3) && + track->par->sample_rate > 24000) avio_w8(pb, 0x6B); // 11172-3 else - avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id)); + avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->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_id == AV_CODEC_ID_DVD_SUBTITLE) + if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream) - else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) avio_w8(pb, 0x15); // flags (= Audiostream) else avio_w8(pb, 0x11); // flags (= Visualstream) - avio_wb24(pb, track->enc->rc_buffer_size >> 3); // Buffersize DB + props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, + NULL); + + avio_wb24(pb, props ? props->buffer_size / 8 : 0); // Buffersize DB - avio_wb32(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) + avio_wb32(pb, props ? FFMAX(props->max_bitrate, props->avg_bitrate) : track->par->bit_rate); // maxbitrate (FIXME should be max rate in any 1 sec window) + if (!props || !props->min_bitrate || props->max_bitrate != props->min_bitrate) avio_wb32(pb, 0); // vbr else - avio_wb32(pb, track->enc->rc_max_rate); // avg bitrate + avio_wb32(pb, props->max_bitrate); // avg bitrate if (track->vos_len) { // DecoderSpecific info descriptor @@ -350,35 +359,35 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic return update_size(pb, pos); } -static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); avio_wl32(pb, track->tag); // store it byteswapped - track->enc->codec_tag = av_bswap16(track->tag >> 16); - ff_put_wav_header(pb, track->enc); + track->par->codec_tag = av_bswap16(track->tag >> 16); + ff_put_wav_header(s, pb, track->st->codecpar); return update_size(pb, pos); } -static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); ffio_wfourcc(pb, "wfex"); - ff_put_wav_header(pb, track->enc); + ff_put_wav_header(s, pb, track->st->codecpar); return update_size(pb, pos); } -static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { uint32_t layout_tag, bitmap; int64_t pos = avio_tell(pb); - layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id, - track->enc->channel_layout, + layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id, + track->par->channel_layout, &bitmap); if (!layout_tag) { - av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to " + av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " "lack of channel information\n"); return 0; } @@ -394,7 +403,7 @@ static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track) return update_size(pb, pos); } -static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); @@ -405,21 +414,21 @@ static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "frma"); avio_wl32(pb, track->tag); - if (track->enc->codec_id == AV_CODEC_ID_AAC) { + if (track->par->codec_id == AV_CODEC_ID_AAC) { /* useless atom needed by mplayer, ipod, not needed by quicktime */ avio_wb32(pb, 12); /* size */ ffio_wfourcc(pb, "mp4a"); avio_wb32(pb, 0); mov_write_esds_tag(pb, track); - } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) { + } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) { mov_write_amr_tag(pb, track); - } else if (track->enc->codec_id == AV_CODEC_ID_AC3) { + } else if (track->par->codec_id == AV_CODEC_ID_AC3) { mov_write_ac3_tag(pb, track); - } else if (track->enc->codec_id == AV_CODEC_ID_ALAC) { + } else if (track->par->codec_id == AV_CODEC_ID_ALAC) { mov_write_extradata_tag(pb, track); - } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS || - track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { - mov_write_ms_tag(pb, track); + } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS || + track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { + mov_write_ms_tag(s, pb, track); } avio_wb32(pb, 8); /* size */ @@ -441,12 +450,14 @@ static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf) if (track->start_dts == AV_NOPTS_VALUE) { /* No packets written yet, vc1_info isn't authoritative yet. */ - /* Assume inline sequence and entry headers. This will be - * overwritten at the end if the file is seekable. */ + /* Assume inline sequence and entry headers. */ packet_seq = packet_entry = 1; + av_log(NULL, AV_LOG_WARNING, + "moov atom written before any packets, unable to write correct " + "dvc1 atom. Set the delay_moov flag to fix this.\n"); } - unescaped = av_mallocz(track->vos_len + FF_INPUT_BUFFER_PADDING_SIZE); + unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); if (!unescaped) return AVERROR(ENOMEM); start = find_next_marker(track->vos_data, end); @@ -519,7 +530,6 @@ static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->vos_len + 8 + sizeof(buf)); ffio_wfourcc(pb, "dvc1"); - track->vc1_info.struct_offset = avio_tell(pb); avio_write(pb, buf, sizeof(buf)); avio_write(pb, track->vos_data, track->vos_len); @@ -597,14 +607,14 @@ static int get_samples_per_packet(MOVTrack *track) return first_duration; } -static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); int version = 0; uint32_t tag = track->tag; if (track->mode == MODE_MOV) { - if (mov_get_lpcm_flags(track->enc->codec_id)) + if (mov_get_lpcm_flags(track->par->codec_id)) tag = AV_RL32("lpcm"); version = 2; } @@ -627,11 +637,11 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); avio_wb32(pb, 0x00010000); avio_wb32(pb, 72); - avio_wb64(pb, av_double2int(track->enc->sample_rate)); - avio_wb32(pb, track->enc->channels); + avio_wb64(pb, av_double2int(track->par->sample_rate)); + avio_wb32(pb, track->par->channels); avio_wb32(pb, 0x7F000000); - avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id)); - avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id)); + avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id)); + avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id)); avio_wb32(pb, track->sample_size); avio_wb32(pb, get_samples_per_packet(track)); } else { @@ -641,34 +651,34 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); avio_wb16(pb, 0); /* packet size (= 0) */ - avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ? - track->enc->sample_rate : 0); + avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ? + track->par->sample_rate : 0); avio_wb16(pb, 0); /* Reserved */ } if (track->mode == MODE_MOV && - (track->enc->codec_id == AV_CODEC_ID_AAC || - track->enc->codec_id == AV_CODEC_ID_AC3 || - track->enc->codec_id == AV_CODEC_ID_AMR_NB || - track->enc->codec_id == AV_CODEC_ID_ALAC || - track->enc->codec_id == AV_CODEC_ID_ADPCM_MS || - track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV)) - mov_write_wave_tag(pb, track); + (track->par->codec_id == AV_CODEC_ID_AAC || + track->par->codec_id == AV_CODEC_ID_AC3 || + track->par->codec_id == AV_CODEC_ID_AMR_NB || + track->par->codec_id == AV_CODEC_ID_ALAC || + track->par->codec_id == AV_CODEC_ID_ADPCM_MS || + track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV)) + mov_write_wave_tag(s, pb, track); else if (track->tag == MKTAG('m','p','4','a')) mov_write_esds_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) + else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) mov_write_amr_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_AC3) + else if (track->par->codec_id == AV_CODEC_ID_AC3) mov_write_ac3_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_ALAC) + else if (track->par->codec_id == AV_CODEC_ID_ALAC) mov_write_extradata_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) - mov_write_wfex_tag(pb, track); + else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) + mov_write_wfex_tag(s, pb, track); else if (track->vos_len > 0) mov_write_glbl_tag(pb, track); - if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO) - mov_write_chan_tag(pb, track); + if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO) + mov_write_chan_tag(s, pb, track); return update_size(pb, pos); } @@ -741,18 +751,18 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "ARES"); ffio_wfourcc(pb, "0001"); avio_wb32(pb, AV_RB32(track->vos_data + 0x28)); /* dnxhd cid, some id ? */ - avio_wb32(pb, track->enc->width); + avio_wb32(pb, track->par->width); /* values below are based on samples created with quicktime and avid codecs */ if (track->vos_data[5] & 2) { // interlaced - avio_wb32(pb, track->enc->height / 2); + avio_wb32(pb, track->par->height / 2); avio_wb32(pb, 2); /* unknown */ avio_wb32(pb, 0); /* unknown */ avio_wb32(pb, 4); /* unknown */ } else { - avio_wb32(pb, track->enc->height); + avio_wb32(pb, track->par->height); avio_wb32(pb, 1); /* unknown */ avio_wb32(pb, 0); /* unknown */ - if (track->enc->height == 1080) + if (track->par->height == 1080) avio_wb32(pb, 5); /* unknown */ else avio_wb32(pb, 6); /* unknown */ @@ -768,20 +778,20 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) { - int tag = track->enc->codec_tag; + int tag = track->par->codec_tag; - if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id)) + if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)) return 0; - if (track->enc->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); - else if (track->enc->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); - else if (track->enc->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); - else if (track->enc->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); - else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); - else if (track->enc->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); - else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); - else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); - else if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); + if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); + else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); + else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); + else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); + else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); + else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); + else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); + else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); + else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); return tag; } @@ -799,13 +809,13 @@ static const AVCodecTag codec_ipod_tags[] = { static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) { - int tag = track->enc->codec_tag; + int tag = track->par->codec_tag; // keep original tag for subs, ipod supports both formats - if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE && + if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE && (tag == MKTAG('t', 'x', '3', 'g') || tag == MKTAG('t', 'e', 'x', 't')))) - tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id); + tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id); if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v")) av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " @@ -818,17 +828,17 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; - if (track->enc->width == 720) /* SD */ - if (track->enc->height == 480) /* NTSC */ - if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n'); + if (track->par->width == 720) /* SD */ + if (track->par->height == 480) /* NTSC */ + if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n'); else tag = MKTAG('d','v','c',' '); - else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p'); - else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p'); + else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p'); + else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p'); else tag = MKTAG('d','v','p','p'); - else if (track->enc->height == 720) /* HD 720 line */ + else if (track->par->height == 720) /* HD 720 line */ if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q'); else tag = MKTAG('d','v','h','p'); - else if (track->enc->height == 1080) /* HD 1080 line */ + else if (track->par->height == 1080) /* HD 1080 line */ if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5'); else tag = MKTAG('d','v','h','6'); else { @@ -862,13 +872,13 @@ static const struct { static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) { - int tag = track->enc->codec_tag; + int tag = track->par->codec_tag; int i; for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) { - if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) { + if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) { tag = mov_pix_fmt_tags[i].tag; - track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps; + track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps; break; } } @@ -878,37 +888,37 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) { - int tag = track->enc->codec_tag; - - if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL && - (track->enc->codec_id == AV_CODEC_ID_DVVIDEO || - track->enc->codec_id == AV_CODEC_ID_RAWVIDEO || - track->enc->codec_id == AV_CODEC_ID_H263 || - av_get_bits_per_sample(track->enc->codec_id)))) { // pcm audio - if (track->enc->codec_id == AV_CODEC_ID_DVVIDEO) + int tag = track->par->codec_tag; + + if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL && + (track->par->codec_id == AV_CODEC_ID_DVVIDEO || + track->par->codec_id == AV_CODEC_ID_RAWVIDEO || + track->par->codec_id == AV_CODEC_ID_H263 || + av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio + if (track->par->codec_id == AV_CODEC_ID_DVVIDEO) tag = mov_get_dv_codec_tag(s, track); - else if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) + else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) tag = mov_get_rawvideo_codec_tag(s, track); - else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { - tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->enc->codec_id); + else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { + tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id); if (!tag) { // if no mac fcc found, try with Microsoft tags - tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id); + tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id); if (tag) av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, " "the file may be unplayable!\n"); } - } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) { - tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->enc->codec_id); + } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { + tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id); if (!tag) { // if no mac fcc found, try with Microsoft tags - int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id); + int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id); if (ms_tag) { tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff)); av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, " "the file may be unplayable!\n"); } } - } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) - tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id); + } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) + tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id); } return tag; @@ -942,14 +952,14 @@ static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) tag = mp4_get_codec_tag(s, track); else if (track->mode == MODE_ISM) { tag = mp4_get_codec_tag(s, track); - if (!tag && track->enc->codec_id == AV_CODEC_ID_WMAPRO) + if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO) tag = MKTAG('w', 'm', 'a', ' '); } else if (track->mode == MODE_IPOD) tag = ipod_get_codec_tag(s, track); else if (track->mode & MODE_3GP) - tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id); + tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id); else if (track->mode == MODE_F4V) - tag = ff_codec_get_tag(codec_f4v_tags, track->enc->codec_id); + tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id); else tag = mov_get_codec_tag(s, track); @@ -979,8 +989,8 @@ static const uint16_t fiel_data[] = { static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track) { unsigned mov_field_order = 0; - if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data)) - mov_field_order = fiel_data[track->enc->field_order]; + if (track->par->field_order < FF_ARRAY_ELEMS(fiel_data)) + mov_field_order = fiel_data[track->par->field_order]; else return 0; avio_wb32(pb, 10); @@ -998,10 +1008,10 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); /* Reserved */ avio_wb16(pb, 1); /* Data-reference index */ - if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE) + if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) mov_write_esds_tag(pb, track); - else if (track->enc->extradata_size) - avio_write(pb, track->enc->extradata, track->enc->extradata_size); + else if (track->par->extradata_size) + avio_write(pb, track->par->extradata, track->par->extradata_size); return update_size(pb, pos); } @@ -1009,8 +1019,8 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) { AVRational sar; - av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num, - track->enc->sample_aspect_ratio.den, INT_MAX); + av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num, + track->par->sample_aspect_ratio.den, INT_MAX); avio_wb32(pb, 16); ffio_wfourcc(pb, "pasp"); @@ -1035,7 +1045,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); /* Codec stream revision (=0) */ if (track->mode == MODE_MOV) { ffio_wfourcc(pb, "FFMP"); /* Vendor */ - if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) { + if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) { avio_wb32(pb, 0); /* Temporal Quality */ avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/ } else { @@ -1047,7 +1057,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); /* Reserved */ avio_wb32(pb, 0); /* Reserved */ } - avio_wb16(pb, track->enc->width); /* Video width */ + avio_wb16(pb, track->par->width); /* Video width */ avio_wb16(pb, track->height); /* Video height */ avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */ avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */ @@ -1061,38 +1071,38 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) avio_w8(pb, strlen(compressor_name)); avio_write(pb, compressor_name, 31); - if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample) - avio_wb16(pb, track->enc->bits_per_coded_sample); + if (track->mode == MODE_MOV && track->par->bits_per_coded_sample) + avio_wb16(pb, track->par->bits_per_coded_sample); else avio_wb16(pb, 0x18); /* Reserved */ avio_wb16(pb, 0xffff); /* Reserved */ if (track->tag == MKTAG('m','p','4','v')) mov_write_esds_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_H263) + else if (track->par->codec_id == AV_CODEC_ID_H263) mov_write_d263_tag(pb); - else if (track->enc->codec_id == AV_CODEC_ID_SVQ3) + else if (track->par->codec_id == AV_CODEC_ID_SVQ3) mov_write_svq3_tag(pb); - else if (track->enc->codec_id == AV_CODEC_ID_DNXHD) + else if (track->par->codec_id == AV_CODEC_ID_DNXHD) mov_write_avid_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_HEVC) + else if (track->par->codec_id == AV_CODEC_ID_HEVC) mov_write_hvcc_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_H264) { + else if (track->par->codec_id == AV_CODEC_ID_H264) { mov_write_avcc_tag(pb, track); if (track->mode == MODE_IPOD) mov_write_uuid_tag_ipod(pb); - } else if (track->enc->field_order != AV_FIELD_UNKNOWN) + } else if (track->par->field_order != AV_FIELD_UNKNOWN) mov_write_fiel_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0) + else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0) mov_write_dvc1_tag(pb, track); - else if (track->enc->codec_id == AV_CODEC_ID_VP6F || - track->enc->codec_id == AV_CODEC_ID_VP6A) { + else if (track->par->codec_id == AV_CODEC_ID_VP6F || + track->par->codec_id == AV_CODEC_ID_VP6A) { /* Don't write any potential extradata here - the cropping * is signalled via the normal width/height fields. */ } else if (track->vos_len > 0) mov_write_glbl_tag(pb, track); - if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num && - track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) { + if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num && + track->par->sample_aspect_ratio.den != track->par->sample_aspect_ratio.num) { mov_write_pasp_tag(pb, track); } @@ -1127,27 +1137,27 @@ static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "tmcd"); /* Data format */ avio_wb32(pb, 0); /* Reserved */ avio_wb32(pb, 1); /* Data reference index */ - if (track->enc->extradata_size) - avio_write(pb, track->enc->extradata, track->enc->extradata_size); + if (track->par->extradata_size) + avio_write(pb, track->par->extradata, track->par->extradata_size); return update_size(pb, pos); } -static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "stsd"); avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, 1); /* entry count */ - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) mov_write_video_tag(pb, track); - else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) - mov_write_audio_tag(pb, track); - else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) + else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) + mov_write_audio_tag(s, pb, track); + else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) mov_write_subtitle_tag(pb, track); - else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) + else if (track->par->codec_tag == MKTAG('r','t','p',' ')) mov_write_rtp_tag(pb, track); - else if (track->enc->codec_tag == MKTAG('t','m','c','d')) + else if (track->par->codec_tag == MKTAG('t','m','c','d')) mov_write_tmcd_tag(pb, track); return update_size(pb, pos); } @@ -1160,6 +1170,8 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) int i; ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */ + if (!ctts_entries) + return AVERROR(ENOMEM); ctts_entries[0].count = 1; ctts_entries[0].duration = track->cluster[0].cts; for (i = 1; i < track->entry; i++) { @@ -1188,20 +1200,24 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) /* Time to sample atom */ static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track) { - MOVStts *stts_entries; + MOVStts *stts_entries = NULL; uint32_t entries = -1; uint32_t atom_size; int i; - if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) { + if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) { stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */ + if (!stts_entries) + return AVERROR(ENOMEM); stts_entries[0].count = track->sample_count; stts_entries[0].duration = 1; entries = 1; } else { - stts_entries = track->entry ? - av_malloc(track->entry * sizeof(*stts_entries)) : /* worst case */ - NULL; + if (track->entry) { + stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */ + if (!stts_entries) + return AVERROR(ENOMEM); + } for (i = 0; i < track->entry; i++) { int duration = get_cluster_duration(track, i); if (i && duration == stts_entries[entries].duration) { @@ -1241,21 +1257,21 @@ static int mov_write_dref_tag(AVIOContext *pb) return 28; } -static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "stbl"); - mov_write_stsd_tag(pb, track); + mov_write_stsd_tag(s, pb, track); mov_write_stts_tag(pb, track); - if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO || - track->enc->codec_tag == MKTAG('r','t','p',' ')) && + if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO || + track->par->codec_tag == MKTAG('r','t','p',' ')) && track->has_keyframes && track->has_keyframes < track->entry) mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && - track->flags & MOV_TRACK_CTTS) + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && + track->flags & MOV_TRACK_CTTS && track->entry) mov_write_ctts_tag(pb, track); mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); @@ -1321,7 +1337,7 @@ static int is_clcp_track(MOVTrack *track) track->tag == MKTAG('c','6','0','8'); } -static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { const char *hdlr, *descr = NULL, *hdlr_type = NULL; int64_t pos = avio_tell(pb); @@ -1332,13 +1348,13 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) if (track) { hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0"; - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { hdlr_type = "vide"; descr = "VideoHandler"; - } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { hdlr_type = "soun"; descr = "SoundHandler"; - } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { + } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (track->tag == MKTAG('t','x','3','g')) { hdlr_type = "sbtl"; } else if (track->tag == MKTAG('m','p','4','s')) { @@ -1349,20 +1365,20 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) hdlr_type = "text"; } descr = "SubtitleHandler"; - } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) { + } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) { hdlr_type = "hint"; descr = "HintHandler"; - } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) { + } else if (track->par->codec_tag == MKTAG('t','m','c','d')) { hdlr_type = "tmcd"; descr = "TimeCodeHandler"; } else { char tag_buf[32]; av_get_codec_tag_string(tag_buf, sizeof(tag_buf), - track->enc->codec_tag); + track->par->codec_tag); - av_log(track->enc, AV_LOG_WARNING, + av_log(s, AV_LOG_WARNING, "Unknown hldr_type for %s / 0x%04X, writing dummy values\n", - tag_buf, track->enc->codec_tag); + tag_buf, track->par->codec_tag); } if (track->st) { // hdlr.name is used by some players to identify the content title @@ -1406,16 +1422,16 @@ static int mov_write_hmhd_tag(AVIOContext *pb) return 28; } -static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "minf"); - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) mov_write_vmhd_tag(pb); - else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) mov_write_smhd_tag(pb); - else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { + else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) { mov_write_gmhd_tag(pb); } else { @@ -1427,13 +1443,14 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) mov_write_gmhd_tag(pb); } if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */ - mov_write_hdlr_tag(pb, NULL); + mov_write_hdlr_tag(s, pb, NULL); mov_write_dinf_tag(pb); - mov_write_stbl_tag(pb, track); + mov_write_stbl_tag(s, pb, track); return update_size(pb, pos); } -static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, + MOVTrack *track) { int version = track->track_duration < INT32_MAX ? 0 : 1; @@ -1452,8 +1469,10 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->time); /* modification time */ } avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */ - if (!track->entry) + if (!track->entry && mov->mode == MODE_ISM) (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); + else if (!track->entry) + (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0); else (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */ avio_wb16(pb, track->language); /* language */ @@ -1469,14 +1488,15 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) return 32; } -static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb, + MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "mdia"); - mov_write_mdhd_tag(pb, track); - mov_write_hdlr_tag(pb, track); - mov_write_minf_tag(pb, track); + mov_write_mdhd_tag(pb, mov, track); + mov_write_hdlr_tag(s, pb, track); + mov_write_minf_tag(s, pb, track); return update_size(pb, pos); } @@ -1489,12 +1509,19 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, int flags = MOV_TKHD_FLAG_IN_MOVIE; int group = 0; + uint32_t *display_matrix = NULL; + int display_matrix_size, i; if (st) { if (mov->per_stream_grouping) group = st->index; else - group = st->codec->codec_type; + group = st->codecpar->codec_type; + + display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, + &display_matrix_size); + if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix)) + display_matrix = NULL; } if (track->flags & MOV_TRACK_ENABLED) @@ -1516,8 +1543,10 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, } avio_wb32(pb, track->track_id); /* track-id */ avio_wb32(pb, 0); /* reserved */ - if (!track->entry) + if (!track->entry && mov->mode == MODE_ISM) (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); + else if (!track->entry) + (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0); else (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); @@ -1526,34 +1555,39 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb16(pb, 0); /* layer */ avio_wb16(pb, group); /* alternate group) */ /* Volume, only for audio */ - if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) avio_wb16(pb, 0x0100); else avio_wb16(pb, 0); avio_wb16(pb, 0); /* reserved */ /* Matrix structure */ - avio_wb32(pb, 0x00010000); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x00010000); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x0); /* reserved */ - avio_wb32(pb, 0x40000000); /* reserved */ + if (display_matrix) { + for (i = 0; i < 9; i++) + avio_wb32(pb, display_matrix[i]); + } else { + avio_wb32(pb, 0x00010000); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x00010000); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x0); /* reserved */ + avio_wb32(pb, 0x40000000); /* reserved */ + } /* Track width and height, for visual only */ - if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO || - track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) { + if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO || + track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) { if (track->mode == MODE_MOV) { - avio_wb32(pb, track->enc->width << 16); + avio_wb32(pb, track->par->width << 16); avio_wb32(pb, track->height << 16); } else { double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); - if (!sample_aspect_ratio || track->height != track->enc->height) + if (!sample_aspect_ratio || track->height != track->par->height) sample_aspect_ratio = 1; - avio_wb32(pb, sample_aspect_ratio * track->enc->width * 0x10000); + avio_wb32(pb, sample_aspect_ratio * track->par->width * 0x10000); avio_wb32(pb, track->height * 0x10000); } } else { @@ -1565,8 +1599,8 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track) { - int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width, - track->enc->sample_aspect_ratio.den); + int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width, + track->par->sample_aspect_ratio.den); int64_t pos = avio_tell(pb); @@ -1577,32 +1611,33 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "clef"); avio_wb32(pb, 0); avio_wb32(pb, width << 16); - avio_wb32(pb, track->enc->height << 16); + avio_wb32(pb, track->par->height << 16); avio_wb32(pb, 20); ffio_wfourcc(pb, "prof"); avio_wb32(pb, 0); avio_wb32(pb, width << 16); - avio_wb32(pb, track->enc->height << 16); + avio_wb32(pb, track->par->height << 16); avio_wb32(pb, 20); ffio_wfourcc(pb, "enof"); avio_wb32(pb, 0); - avio_wb32(pb, track->enc->width << 16); - avio_wb32(pb, track->enc->height << 16); + avio_wb32(pb, track->par->width << 16); + avio_wb32(pb, track->par->height << 16); return update_size(pb, pos); } // This box seems important for the psp playback ... without it the movie seems to hang -static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, + MOVTrack *track) { int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, track->timescale, AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; int entry_size, entry_count, size; - int64_t delay, start_ct = track->cluster[0].cts; - delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE, + int64_t delay, start_ct = track->start_cts; + delay = av_rescale_rnd(track->start_dts + start_ct, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN); version |= delay < INT32_MAX ? 0 : 1; @@ -1620,6 +1655,11 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, entry_count); if (delay > 0) { /* add an empty edit to delay presentation */ + /* In the positive delay case, the delay includes the cts + * offset, and the second edit list entry below trims out + * the same amount from the actual content. This makes sure + * that the offset last sample is included in the edit + * list duration as well. */ if (version == 1) { avio_wb64(pb, delay); avio_wb64(pb, -1); @@ -1628,8 +1668,25 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, -1); } avio_wb32(pb, 0x00010000); + } else { + /* Avoid accidentally ending up with start_ct = -1 which has got a + * special meaning. Normally start_ct should end up positive or zero + * here, but use FFMIN in case dts is a a small positive integer + * rounded to 0 when represented in MOV_TIMESCALE units. */ + start_ct = -FFMIN(track->start_dts, 0); + /* Note, this delay is calculated from the pts of the first sample, + * ensuring that we don't reduce the duration for cases with + * dts<0 pts=0. */ + duration += delay; } + /* For fragmented files, we don't know the full length yet. Setting + * duration to 0 allows us to only specify the offset, including + * the rest of the content (from all future fragments) without specifying + * an explicit duration. */ + if (mov->flags & FF_MOV_FLAG_FRAGMENT) + duration = 0; + /* duration */ if (version == 1) { avio_wb64(pb, duration); @@ -1713,7 +1770,7 @@ static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov, int ret, size; uint8_t *buf; - if (!st || mov->fc->flags & AVFMT_FLAG_BITEXACT) + if (!st) return 0; ret = avio_open_dyn_buf(&pb_buf); @@ -1737,24 +1794,33 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st) { int64_t pos = avio_tell(pb); + int entry_backup = track->entry; + /* If we want to have an empty moov, but some samples already have been + * buffered (delay_moov), pretend that no samples have been written yet. */ + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) + track->entry = 0; + avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "trak"); mov_write_tkhd_tag(pb, mov, track, st); - if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || - (track->entry && track->cluster[0].dts) || - is_clcp_track(track)) { - if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) - mov_write_edts_tag(pb, track); // PSP Movies require edts box + if (track->start_dts != AV_NOPTS_VALUE && + (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || + track->start_dts || is_clcp_track(track))) { + if (mov->use_editlist) + mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box + else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track)) + av_log(mov->fc, AV_LOG_WARNING, + "Not writing any edit list even though one would have been required\n"); } if (track->tref_tag) mov_write_tref_tag(pb, track); - mov_write_mdia_tag(pb, track); + mov_write_mdia_tag(mov->fc, pb, mov, track); if (track->mode == MODE_PSP) mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box if (track->tag == MKTAG('r','t','p',' ')) mov_write_udta_sdp(pb, track); if (track->mode == MODE_MOV) { - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); if ((0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio)) { mov_write_tapt_tag(pb, track); @@ -1765,6 +1831,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, } } mov_write_track_udta_tag(pb, mov, st); + track->entry = entry_backup; return update_size(pb, pos); } @@ -1775,9 +1842,9 @@ static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov) int audio_profile = mov->iods_audio_profile; int video_profile = mov->iods_video_profile; for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].entry > 0) { - has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO; - has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO; + if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { + has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO; + has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO; } } if (audio_profile < 0) @@ -1839,6 +1906,12 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) max_track_id = mov->tracks[i].track_id; } } + /* If using delay_moov, make sure the output is the same as if no + * samples had been written yet. */ + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { + max_track_len = 0; + max_track_id = 1; + } version = max_track_len < UINT32_MAX ? 0 : 1; (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108); /* size */ @@ -1932,16 +2005,17 @@ static int mov_write_string_tag(AVIOContext *pb, const char *name, return size; } -static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, - const char *name, const char *tag, - int long_style) +static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s, + const char *tag, int *lang) { - int l, lang = 0, len, len2; + int l, len, len2; AVDictionaryEntry *t, *t2 = NULL; char tag2[16]; + *lang = 0; + if (!(t = av_dict_get(s->metadata, tag, NULL, 0))) - return 0; + return NULL; len = strlen(t->key); snprintf(tag2, sizeof(tag2), "%s-", tag); @@ -1949,13 +2023,75 @@ static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, len2 = strlen(t2->key); if (len2 == len + 4 && !strcmp(t->value, t2->value) && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) { - lang = l; - break; + *lang = l; + return t; } } + return t; +} + +static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, + const char *name, const char *tag, + int long_style) +{ + int lang; + AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang); + if (!t) + return 0; return mov_write_string_tag(pb, name, t->value, lang, long_style); } +/* 3GPP TS 26.244 */ +static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb) +{ + int lang; + int64_t pos = avio_tell(pb); + double latitude, longitude, altitude; + int32_t latitude_fix, longitude_fix, altitude_fix; + AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang); + const char *ptr, *place = ""; + char *end; + const char *astronomical_body = "earth"; + if (!t) + return 0; + + ptr = t->value; + longitude = strtod(ptr, &end); + if (end == ptr) { + av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); + return 0; + } + ptr = end; + latitude = strtod(ptr, &end); + if (end == ptr) { + av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); + return 0; + } + ptr = end; + altitude = strtod(ptr, &end); + /* If no altitude was present, the default 0 should be fine */ + if (*end == '/') + place = end + 1; + + latitude_fix = (int32_t) ((1 << 16) * latitude); + longitude_fix = (int32_t) ((1 << 16) * longitude); + altitude_fix = (int32_t) ((1 << 16) * altitude); + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "loci"); /* type */ + avio_wb32(pb, 0); /* version + flags */ + avio_wb16(pb, lang); + avio_write(pb, place, strlen(place) + 1); + avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */ + avio_wb32(pb, latitude_fix); + avio_wb32(pb, longitude_fix); + avio_wb32(pb, altitude_fix); + avio_write(pb, astronomical_body, strlen(astronomical_body) + 1); + avio_w8(pb, 0); /* additional notes, null terminated string */ + + return update_size(pb, pos); +} + /* iTunes track number */ static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) @@ -1991,8 +2127,10 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1); mov_write_string_metadata(s, pb, "\251alb", "album" , 1); mov_write_string_metadata(s, pb, "\251day", "date" , 1); - if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) - mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1); + if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) { + if (!(s->flags & AVFMT_FLAG_BITEXACT)) + mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1); + } mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1); mov_write_string_metadata(s, pb, "\251gen", "genre" , 1); mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1); @@ -2095,9 +2233,6 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, int ret, size; uint8_t *buf; - if (s->flags & AVFMT_FLAG_BITEXACT) - return 0; - ret = avio_open_dyn_buf(&pb_buf); if (ret < 0) return ret; @@ -2111,19 +2246,25 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_3gp_udta_tag(pb_buf, s, "albm", "album"); mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright"); mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date"); + mov_write_loci_tag(s, pb_buf); } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4 mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0); mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0); mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0); mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0); mov_write_string_metadata(s, pb_buf, "\251day", "date", 0); - mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0); + if (!(s->flags & AVFMT_FLAG_BITEXACT)) + mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0); mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0); mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0); mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0); + mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0); + mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0); + mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0); } else { /* iTunes meta data */ mov_write_meta_tag(pb_buf, mov, s); + mov_write_loci_tag(s, pb_buf); } if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL)) @@ -2211,10 +2352,21 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id; } for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) { - mov->tracks[i].tref_tag = MKTAG('h','i','n','t'); - mov->tracks[i].tref_id = - mov->tracks[mov->tracks[i].src_track].track_id; + MOVTrack *track = &mov->tracks[i]; + if (track->tag == MKTAG('r','t','p',' ')) { + track->tref_tag = MKTAG('h','i','n','t'); + track->tref_id = mov->tracks[track->src_track].track_id; + } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { + int * fallback, size; + fallback = (int*)av_stream_get_side_data(track->st, + AV_PKT_DATA_FALLBACK_TRACK, + &size); + if (fallback != NULL && size == sizeof(int)) { + if (*fallback >= 0 && *fallback < mov->nb_streams) { + track->tref_tag = MKTAG('f','a','l','l'); + track->tref_id = mov->tracks[*fallback].track_id; + } + } } } @@ -2260,7 +2412,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov) { int64_t pos = avio_tell(pb); int i; - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }; @@ -2285,53 +2437,53 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov) * here yet */ int track_id = i + 1; - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { type = "video"; - } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { type = "audio"; } else { continue; } avio_printf(pb, "<%s systemBitrate=\"%d\">\n", type, - track->enc->bit_rate); - param_write_int(pb, "systemBitrate", track->enc->bit_rate); + track->par->bit_rate); + param_write_int(pb, "systemBitrate", track->par->bit_rate); param_write_int(pb, "trackID", track_id); - if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { - if (track->enc->codec_id == AV_CODEC_ID_H264) { + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { + if (track->par->codec_id == AV_CODEC_ID_H264) { uint8_t *ptr; - int size = track->enc->extradata_size; - if (!ff_avc_write_annexb_extradata(track->enc->extradata, &ptr, + int size = track->par->extradata_size; + if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr, &size)) { param_write_hex(pb, "CodecPrivateData", - ptr ? ptr : track->enc->extradata, + ptr ? ptr : track->par->extradata, size); av_free(ptr); } param_write_string(pb, "FourCC", "H264"); - } else if (track->enc->codec_id == AV_CODEC_ID_VC1) { + } else if (track->par->codec_id == AV_CODEC_ID_VC1) { param_write_string(pb, "FourCC", "WVC1"); - param_write_hex(pb, "CodecPrivateData", track->enc->extradata, - track->enc->extradata_size); + param_write_hex(pb, "CodecPrivateData", track->par->extradata, + track->par->extradata_size); } - param_write_int(pb, "MaxWidth", track->enc->width); - param_write_int(pb, "MaxHeight", track->enc->height); - param_write_int(pb, "DisplayWidth", track->enc->width); - param_write_int(pb, "DisplayHeight", track->enc->height); + param_write_int(pb, "MaxWidth", track->par->width); + param_write_int(pb, "MaxHeight", track->par->height); + param_write_int(pb, "DisplayWidth", track->par->width); + param_write_int(pb, "DisplayHeight", track->par->height); } else { - if (track->enc->codec_id == AV_CODEC_ID_AAC) { + if (track->par->codec_id == AV_CODEC_ID_AAC) { param_write_string(pb, "FourCC", "AACL"); - } else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) { + } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) { param_write_string(pb, "FourCC", "WMAP"); } - param_write_hex(pb, "CodecPrivateData", track->enc->extradata, - track->enc->extradata_size); + param_write_hex(pb, "CodecPrivateData", track->par->extradata, + track->par->extradata_size); param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags, - track->enc->codec_id)); - param_write_int(pb, "Channels", track->enc->channels); - param_write_int(pb, "SamplingRate", track->enc->sample_rate); + track->par->codec_id)); + param_write_int(pb, "Channels", track->par->channels); + param_write_int(pb, "SamplingRate", track->par->sample_rate); param_write_int(pb, "BitsPerSample", 16); - param_write_int(pb, "PacketSize", track->enc->block_align ? - track->enc->block_align : 4); + param_write_int(pb, "PacketSize", track->par->block_align ? + track->par->block_align : 4); } avio_printf(pb, "\n", type); } @@ -2351,6 +2503,12 @@ static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov) return 0; } +static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) +{ + return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO : + (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC); +} + static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset) { @@ -2364,6 +2522,10 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, } if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET) flags &= ~MOV_TFHD_BASE_DATA_OFFSET; + if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) { + flags &= ~MOV_TFHD_BASE_DATA_OFFSET; + flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF; + } /* Don't set a default sample size, the silverlight player refuses * to play files with that set. Don't set a default sample duration, @@ -2392,38 +2554,39 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, track->default_size = -1; if (flags & MOV_TFHD_DEFAULT_FLAGS) { - track->default_sample_flags = - track->enc->codec_type == AVMEDIA_TYPE_VIDEO ? - (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) : - MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO; + /* Set the default flags based on the second sample, if available. + * If the first sample is different, that can be signaled via a separate field. */ + if (track->entry > 1) + track->default_sample_flags = get_sample_flags(track, &track->cluster[1]); + else + track->default_sample_flags = + track->par->codec_type == AVMEDIA_TYPE_VIDEO ? + (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) : + MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO; avio_wb32(pb, track->default_sample_flags); } return update_size(pb, pos); } -static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) -{ - return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO : - (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC); -} - static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, - MOVTrack *track, int moof_size) + MOVTrack *track, int moof_size, + int first, int end) { int64_t pos = avio_tell(pb); uint32_t flags = MOV_TRUN_DATA_OFFSET; int i; - for (i = 0; i < track->entry; i++) { + for (i = first; i < end; i++) { if (get_cluster_duration(track, i) != track->default_duration) flags |= MOV_TRUN_SAMPLE_DURATION; if (track->cluster[i].size != track->default_size) flags |= MOV_TRUN_SAMPLE_SIZE; - if (i > 0 && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags) + if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags) flags |= MOV_TRUN_SAMPLE_FLAGS; } - if (!(flags & MOV_TRUN_SAMPLE_FLAGS)) + if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 && + get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags) flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS; if (track->flags & MOV_TRACK_CTTS) flags |= MOV_TRUN_SAMPLE_CTS; @@ -2433,18 +2596,18 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, avio_w8(pb, 0); /* version */ avio_wb24(pb, flags); - avio_wb32(pb, track->entry); /* sample count */ + avio_wb32(pb, end - first); /* sample count */ if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET && - !(mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) && - track->track_id != 1) + !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) && + !mov->first_trun) avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */ else avio_wb32(pb, moof_size + 8 + track->data_offset + - track->cluster[0].pos); /* data offset */ + track->cluster[first].pos); /* data offset */ if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) - avio_wb32(pb, get_sample_flags(track, &track->cluster[0])); + avio_wb32(pb, get_sample_flags(track, &track->cluster[first])); - for (i = 0; i < track->entry; i++) { + for (i = first; i < end; i++) { if (flags & MOV_TRUN_SAMPLE_DURATION) avio_wb32(pb, get_cluster_duration(track, i)); if (flags & MOV_TRUN_SAMPLE_SIZE) @@ -2455,13 +2618,14 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb32(pb, track->cluster[i].cts); } + mov->first_trun = 0; return update_size(pb, pos); } static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 }; @@ -2471,9 +2635,10 @@ static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track) avio_write(pb, uuid, sizeof(uuid)); avio_w8(pb, 1); avio_wb24(pb, 0); - avio_wb64(pb, track->frag_start); - avio_wb64(pb, track->start_dts + track->track_duration - - track->cluster[0].dts); + avio_wb64(pb, track->start_dts + track->frag_start + + track->cluster[0].cts); + avio_wb64(pb, track->end_pts - + (track->cluster[0].dts + track->cluster[0].cts)); return update_size(pb, pos); } @@ -2483,7 +2648,7 @@ static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, { int n = track->nb_frag_info - 1 - entry, i; int size = 8 + 16 + 4 + 1 + 16*n; - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95, 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f }; @@ -2528,23 +2693,102 @@ static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov, return 0; } +static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks, + int size) +{ + int i; + for (i = 0; i < mov->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + MOVFragmentInfo *info; + if ((tracks >= 0 && i != tracks) || !track->entry) + continue; + track->nb_frag_info++; + if (track->nb_frag_info >= track->frag_info_capacity) { + unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT; + if (av_reallocp_array(&track->frag_info, + new_capacity, + sizeof(*track->frag_info))) + return AVERROR(ENOMEM); + track->frag_info_capacity = new_capacity; + } + info = &track->frag_info[track->nb_frag_info - 1]; + info->offset = avio_tell(pb); + info->size = size; + // Try to recreate the original pts for the first packet + // from the fields we have stored + info->time = track->start_dts + track->frag_start + + track->cluster[0].cts; + info->duration = track->end_pts - + (track->cluster[0].dts + track->cluster[0].cts); + // If the pts is less than zero, we will have trimmed + // away parts of the media track using an edit list, + // and the corresponding start presentation time is zero. + if (info->time < 0) { + info->duration += info->time; + info->time = 0; + } + info->tfrf_offset = 0; + mov_write_tfrf_tags(pb, mov, track); + } + return 0; +} + +static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max) +{ + int i; + for (i = 0; i < mov->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + if ((tracks >= 0 && i != tracks) || !track->entry) + continue; + if (track->nb_frag_info > max) { + memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info)); + track->nb_frag_info = max; + } + } +} + +static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "tfdt"); + avio_w8(pb, 1); /* version */ + avio_wb24(pb, 0); + avio_wb64(pb, track->frag_start); + return update_size(pb, pos); +} + static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, int64_t moof_offset, int moof_size) { int64_t pos = avio_tell(pb); + int i, start = 0; avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "traf"); mov_write_tfhd_tag(pb, mov, track, moof_offset); - mov_write_trun_tag(pb, mov, track, moof_size); + if (mov->mode != MODE_ISM) + mov_write_tfdt_tag(pb, track); + for (i = 1; i < track->entry; i++) { + if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) { + mov_write_trun_tag(pb, mov, track, moof_size, start, i); + start = i; + } + } + mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry); if (mov->mode == MODE_ISM) { mov_write_tfxd_tag(pb, track); if (mov->ism_lookahead) { int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead; - track->tfrf_offset = avio_tell(pb); + if (track->nb_frag_info > 0) { + MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1]; + if (!info->tfrf_offset) + info->tfrf_offset = avio_tell(pb); + } avio_wb32(pb, 8 + size); ffio_wfourcc(pb, "free"); for (i = 0; i < size; i++) @@ -2563,6 +2807,7 @@ static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov, avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "moof"); + mov->first_trun = 1; mov_write_mfhd_tag(pb, mov); for (i = 0; i < mov->nb_streams; i++) { @@ -2577,7 +2822,104 @@ static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov, return update_size(pb, pos); } -static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks) +static int mov_write_sidx_tag(AVIOContext *pb, + MOVTrack *track, int ref_size, int total_sidx_size) +{ + int64_t pos = avio_tell(pb), offset_pos, end_pos; + int64_t presentation_time, duration, offset; + int starts_with_SAP, i, entries; + + if (track->entry) { + entries = 1; + presentation_time = track->start_dts + track->frag_start + + track->cluster[0].cts; + duration = track->end_pts - + (track->cluster[0].dts + track->cluster[0].cts); + starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE; + + // pts<0 should be cut away using edts + if (presentation_time < 0) { + duration += presentation_time; + presentation_time = 0; + } + } else { + entries = track->nb_frag_info; + if (entries <= 0) + return 0; + presentation_time = track->frag_info[0].time; + } + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "sidx"); + avio_w8(pb, 1); /* version */ + avio_wb24(pb, 0); + avio_wb32(pb, track->track_id); /* reference_ID */ + avio_wb32(pb, track->timescale); /* timescale */ + avio_wb64(pb, presentation_time); /* earliest_presentation_time */ + offset_pos = avio_tell(pb); + avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */ + avio_wb16(pb, 0); /* reserved */ + + avio_wb16(pb, entries); /* reference_count */ + for (i = 0; i < entries; i++) { + if (!track->entry) { + if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) { + av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n"); + } + duration = track->frag_info[i].duration; + ref_size = track->frag_info[i].size; + starts_with_SAP = 1; + } + avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */ + avio_wb32(pb, duration); /* subsegment_duration */ + avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */ + } + + end_pos = avio_tell(pb); + offset = pos + total_sidx_size - end_pos; + avio_seek(pb, offset_pos, SEEK_SET); + avio_wb64(pb, offset); + avio_seek(pb, end_pos, SEEK_SET); + return update_size(pb, pos); +} + +static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov, + int tracks, int ref_size) +{ + int i, round, ret; + AVIOContext *avio_buf; + int total_size = 0; + for (round = 0; round < 2; round++) { + // First run one round to calculate the total size of all + // sidx atoms. + // This would be much simpler if we'd only write one sidx + // atom, for the first track in the moof. + if (round == 0) { + if ((ret = ffio_open_null_buf(&avio_buf)) < 0) + return ret; + } else { + avio_buf = pb; + } + for (i = 0; i < mov->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + if (tracks >= 0 && i != tracks) + continue; + // When writing a sidx for the full file, entry is 0, but + // we want to include all tracks. ref_size is 0 in this case, + // since we read it from frag_info instead. + if (!track->entry && ref_size > 0) + continue; + total_size -= mov_write_sidx_tag(avio_buf, track, ref_size, + total_size); + } + if (round == 0) + total_size = ffio_close_null_buf(avio_buf); + } + return 0; +} + +static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, + int64_t mdat_size) { AVIOContext *avio_buf; int ret, moof_size; @@ -2586,6 +2928,21 @@ static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks) return ret; mov_write_moof_tag_internal(avio_buf, mov, tracks, 0); moof_size = ffio_close_null_buf(avio_buf); + + if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) + mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size); + + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX || + !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) || + mov->ism_lookahead) { + if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0) + return ret; + if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) && + mov->flags & FF_MOV_FLAG_SKIP_TRAILER) { + mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1); + } + } + return mov_write_moof_tag_internal(pb, mov, tracks, moof_size); } @@ -2604,7 +2961,7 @@ static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->nb_frag_info); for (i = 0; i < track->nb_frag_info; i++) { avio_wb64(pb, track->frag_info[i].time); - avio_wb64(pb, track->frag_info[i].offset); + avio_wb64(pb, track->frag_info[i].offset + track->data_offset); avio_w8(pb, 1); /* traf number */ avio_w8(pb, 1); /* trun number */ avio_w8(pb, 1); /* sample number */ @@ -2661,9 +3018,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) has_video = 1; - if (st->codec->codec_id == AV_CODEC_ID_H264) + if (st->codecpar->codec_id == AV_CODEC_ID_H264) has_h264 = 1; } @@ -2680,6 +3037,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) minor = has_h264 ? 0x20000 : 0x10000; } else if (mov->mode == MODE_PSP) ffio_wfourcc(pb, "MSNV"); + else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) + ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof else if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "isom"); else if (mov->mode == MODE_IPOD) @@ -2697,14 +3056,18 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "qt "); else if (mov->mode == MODE_ISM) { ffio_wfourcc(pb, "piff"); - ffio_wfourcc(pb, "iso2"); - } else { + } else if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) { ffio_wfourcc(pb, "isom"); ffio_wfourcc(pb, "iso2"); if (has_h264) ffio_wfourcc(pb, "avc1"); } + // We add tfdt atoms when fragmenting, signal this with the iso6 compatible + // brand. This is compatible with users that don't understand tfdt. + if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->mode != MODE_ISM) + ffio_wfourcc(pb, "iso6"); + if (mov->mode == MODE_3GP) ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4"); else if (mov->mode & MODE_3G2) @@ -2713,19 +3076,23 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "MSNV"); else if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "mp41"); + + if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) + ffio_wfourcc(pb, "dash"); + return update_size(pb, pos); } static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) { AVStream *video_st = s->streams[0]; - AVCodecContext *video_codec = s->streams[0]->codec; - AVCodecContext *audio_codec = s->streams[1]->codec; - int audio_rate = audio_codec->sample_rate; + AVCodecParameters *video_par = s->streams[0]->codecpar; + AVCodecParameters *audio_par = s->streams[1]->codecpar; + int audio_rate = audio_par->sample_rate; // TODO: should be avg_frame_rate int frame_rate = ((video_st->time_base.den) * (0x10000)) / (video_st->time_base.num); - int audio_kbitrate = audio_codec->bit_rate / 1000; - int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate); + int audio_kbitrate = audio_par->bit_rate / 1000; + int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate); avio_wb32(pb, 0x94); /* size */ ffio_wfourcc(pb, "uuid"); @@ -2754,13 +3121,13 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) avio_wb32(pb, audio_kbitrate); avio_wb32(pb, audio_kbitrate); avio_wb32(pb, audio_rate); - avio_wb32(pb, audio_codec->channels); + avio_wb32(pb, audio_par->channels); avio_wb32(pb, 0x34); /* size */ ffio_wfourcc(pb, "VPRF"); /* video */ avio_wb32(pb, 0x0); avio_wb32(pb, 0x1); /* TrackID */ - if (video_codec->codec_id == AV_CODEC_ID_H264) { + if (video_par->codec_id == AV_CODEC_ID_H264) { ffio_wfourcc(pb, "avc1"); avio_wb16(pb, 0x014D); avio_wb16(pb, 0x0015); @@ -2774,11 +3141,25 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) avio_wb32(pb, video_kbitrate); avio_wb32(pb, frame_rate); avio_wb32(pb, frame_rate); - avio_wb16(pb, video_codec->width); - avio_wb16(pb, video_codec->height); + avio_wb16(pb, video_par->width); + avio_wb16(pb, video_par->height); avio_wb32(pb, 0x010001); /* ? */ } +static int mov_write_identification(AVIOContext *pb, AVFormatContext *s) +{ + MOVMuxContext *mov = s->priv_data; + 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 AVERROR(EINVAL); + } + mov_write_uuidprof_tag(pb, s); + } + return 0; +} + static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) { uint32_t c = -1; @@ -2800,7 +3181,7 @@ static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) return 0; } -static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) +static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk) { const uint8_t *start, *next, *end = pkt->data + pkt->size; int seq = 0, entry = 0; @@ -2820,10 +3201,13 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) break; } } - if (!trk->entry && !fragment) { + if (!trk->entry && trk->vc1_info.first_packet_seen) + trk->vc1_info.first_frag_written = 1; + if (!trk->entry && !trk->vc1_info.first_frag_written) { /* First packet in first fragment */ trk->vc1_info.first_packet_seq = seq; trk->vc1_info.first_packet_entry = entry; + trk->vc1_info.first_packet_seen = 1; } else if ((seq && !trk->vc1_info.packet_seq) || (entry && !trk->vc1_info.packet_entry)) { int i; @@ -2834,7 +3218,7 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) trk->vc1_info.packet_seq = 1; if (entry) trk->vc1_info.packet_entry = 1; - if (!fragment) { + if (!trk->vc1_info.first_frag_written) { /* First fragment */ if ((!seq || trk->vc1_info.first_packet_seq) && (!entry || trk->vc1_info.first_packet_entry)) { @@ -2857,16 +3241,89 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) } } -static int mov_flush_fragment(AVFormatContext *s) +static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track) +{ + MOVMuxContext *mov = s->priv_data; + int ret, buf_size; + uint8_t *buf; + int i, offset; + + if (!track->mdat_buf) + return 0; + if (!mov->mdat_buf) { + if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0) + return ret; + } + buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); + track->mdat_buf = NULL; + + offset = avio_tell(mov->mdat_buf); + avio_write(mov->mdat_buf, buf, buf_size); + av_free(buf); + + for (i = track->entries_flushed; i < track->entry; i++) + track->cluster[i].pos += offset; + track->entries_flushed = track->entry; + return 0; +} + +static int mov_flush_fragment(AVFormatContext *s, int force) { MOVMuxContext *mov = s->priv_data; int i, first_track = -1; int64_t mdat_size = 0; + int has_video = 0, starts_with_key = 0, first_video_track = 1; if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) return 0; - if (!(mov->flags & FF_MOV_FLAG_EMPTY_MOOV) && mov->fragments == 0) { + // Try to fill in the duration of the last packet in each stream + // from queued packets in the interleave queues. If the flushing + // of fragments was triggered automatically by an AVPacket, we + // already have reliable info for the end of that track, but other + // tracks may need to be filled in. + for (i = 0; i < s->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + if (!track->end_reliable) { + AVPacket pkt; + if (!ff_interleaved_peek(s, i, &pkt, 1)) { + track->track_duration = pkt.dts - track->start_dts; + if (pkt.pts != AV_NOPTS_VALUE) + track->end_pts = pkt.pts; + else + track->end_pts = pkt.dts; + } + } + } + + for (i = 0; i < mov->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + if (track->entry <= 1) + continue; + // Sample durations are calculated as the diff of dts values, + // but for the last sample in a fragment, we don't know the dts + // of the first sample in the next fragment, so we have to rely + // on what was set as duration in the AVPacket. Not all callers + // set this though, so we might want to replace it with an + // estimate if it currently is zero. + if (get_cluster_duration(track, track->entry - 1) != 0) + continue; + // Use the duration (i.e. dts diff) of the second last sample for + // the last one. This is a wild guess (and fatal if it turns out + // to be too long), but probably the best we can do - having a zero + // duration is bad as well. + track->track_duration += get_cluster_duration(track, track->entry - 2); + track->end_pts += get_cluster_duration(track, track->entry - 2); + if (!mov->missing_duration_warned) { + av_log(s, AV_LOG_WARNING, + "Estimating the duration of the last packet in a " + "fragment, consider setting the duration field in " + "AVPacket instead.\n"); + mov->missing_duration_warned = 1; + } + } + + if (!mov->moov_written) { int64_t pos = avio_tell(s->pb); int ret; AVIOContext *moov_buf; @@ -2877,7 +3334,7 @@ static int mov_flush_fragment(AVFormatContext *s) if (!mov->tracks[i].entry) break; /* Don't write the initial moov unless all tracks have data */ - if (i < mov->nb_streams) + if (i < mov->nb_streams && !force) return 0; if ((ret = ffio_open_null_buf(&moov_buf)) < 0) @@ -2887,8 +3344,19 @@ static int mov_flush_fragment(AVFormatContext *s) for (i = 0; i < mov->nb_streams; i++) mov->tracks[i].data_offset = pos + buf_size + 8; + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); + if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) + mov_write_identification(s->pb, s); mov_write_moov_tag(s->pb, mov, s); + if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) { + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) + mov->reserved_header_pos = avio_tell(s->pb); + avio_flush(s->pb); + mov->moov_written = 1; + return 0; + } + buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf); mov->mdat_buf = NULL; avio_wb32(s->pb, buf_size + 8); @@ -2896,7 +3364,10 @@ static int mov_flush_fragment(AVFormatContext *s) avio_write(s->pb, buf, buf_size); av_free(buf); - mov->fragments++; + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) + mov->reserved_header_pos = avio_tell(s->pb); + + mov->moov_written = 1; mov->mdat_size = 0; for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].entry) @@ -2904,20 +3375,43 @@ static int mov_flush_fragment(AVFormatContext *s) mov->tracks[i].track_duration - mov->tracks[i].cluster[0].dts; mov->tracks[i].entry = 0; + mov->tracks[i].end_reliable = 0; } avio_flush(s->pb); return 0; } + if (mov->frag_interleave) { + for (i = 0; i < mov->nb_streams; i++) { + MOVTrack *track = &mov->tracks[i]; + int ret; + if ((ret = mov_flush_fragment_interleaving(s, track)) < 0) + return ret; + } + + if (!mov->mdat_buf) + return 0; + mdat_size = avio_tell(mov->mdat_buf); + } + for (i = 0; i < mov->nb_streams; i++) { MOVTrack *track = &mov->tracks[i]; - if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) + if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave) track->data_offset = 0; else track->data_offset = mdat_size; - if (!track->mdat_buf) + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { + has_video = 1; + if (first_video_track) { + if (track->entry) + starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE; + first_video_track = 0; + } + } + if (!track->entry) continue; - mdat_size += avio_tell(track->mdat_buf); + if (track->mdat_buf) + mdat_size += avio_tell(track->mdat_buf); if (first_track < 0) first_track = i; } @@ -2925,6 +3419,10 @@ static int mov_flush_fragment(AVFormatContext *s) if (!mdat_size) return 0; + avio_write_marker(s->pb, + av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale), + (has_video ? starts_with_key : mov->tracks[first_track].cluster[0].flags & MOV_SYNC_SAMPLE) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); + for (i = 0; i < mov->nb_streams; i++) { MOVTrack *track = &mov->tracks[i]; int buf_size, write_moof = 1, moof_tracks = -1; @@ -2944,25 +3442,9 @@ static int mov_flush_fragment(AVFormatContext *s) } if (write_moof) { - MOVFragmentInfo *info; avio_flush(s->pb); - track->nb_frag_info++; - if (track->nb_frag_info >= track->frag_info_capacity) { - unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT; - if (av_reallocp_array(&track->frag_info, - new_capacity, - sizeof(*track->frag_info))) - return AVERROR(ENOMEM); - track->frag_info_capacity = new_capacity; - } - info = &track->frag_info[track->nb_frag_info - 1]; - info->offset = avio_tell(s->pb); - info->time = mov->tracks[i].frag_start; - info->duration = duration; - mov_write_tfrf_tags(s->pb, mov, track); - - mov_write_moof_tag(s->pb, mov, moof_tracks); - info->tfrf_offset = track->tfrf_offset; + + mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size); mov->fragments++; avio_wb32(s->pb, mdat_size + 8); @@ -2972,10 +3454,19 @@ static int mov_flush_fragment(AVFormatContext *s) if (track->entry) track->frag_start += duration; track->entry = 0; - if (!track->mdat_buf) - continue; - buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); - track->mdat_buf = NULL; + track->entries_flushed = 0; + track->end_reliable = 0; + if (!mov->frag_interleave) { + if (!track->mdat_buf) + continue; + buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); + track->mdat_buf = NULL; + } else { + if (!mov->mdat_buf) + continue; + buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf); + mov->mdat_buf = NULL; + } avio_write(s->pb, buf, buf_size); av_free(buf); @@ -2987,19 +3478,40 @@ static int mov_flush_fragment(AVFormatContext *s) return 0; } +static int mov_auto_flush_fragment(AVFormatContext *s, int force) +{ + MOVMuxContext *mov = s->priv_data; + int had_moov = mov->moov_written; + int ret = mov_flush_fragment(s, force); + if (ret < 0) + return ret; + // If using delay_moov, the first flush only wrote the moov, + // not the actual moof+mdat pair, thus flush once again. + if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV) + ret = mov_flush_fragment(s, force); + return ret; +} + int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) { MOVMuxContext *mov = s->priv_data; AVIOContext *pb = s->pb; MOVTrack *trk = &mov->tracks[pkt->stream_index]; - AVCodecContext *enc = trk->enc; + AVCodecParameters *par = trk->par; unsigned int samples_in_chunk = 0; - int size = pkt->size; + int size = pkt->size, ret = 0; uint8_t *reformatted_data = NULL; if (mov->flags & FF_MOV_FLAG_FRAGMENT) { int ret; - if (mov->fragments > 0) { + if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { + if (mov->frag_interleave && mov->fragments > 0) { + if (trk->entry - trk->entries_flushed >= mov->frag_interleave) { + if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0) + return ret; + } + } + if (!trk->mdat_buf) { if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0) return ret; @@ -3014,7 +3526,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } } - if (enc->codec_id == AV_CODEC_ID_AMR_NB) { + if (par->codec_id == AV_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, 1}; @@ -3034,15 +3546,19 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) samples_in_chunk = 1; /* copy extradata if it exists */ - if (trk->vos_len == 0 && enc->extradata_size > 0) { - trk->vos_len = enc->extradata_size; + if (trk->vos_len == 0 && par->extradata_size > 0) { + trk->vos_len = par->extradata_size; trk->vos_data = av_malloc(trk->vos_len); - memcpy(trk->vos_data, enc->extradata, trk->vos_len); + if (!trk->vos_data) { + ret = AVERROR(ENOMEM); + goto err; + } + memcpy(trk->vos_data, par->extradata, trk->vos_len); } - if (enc->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1) { - /* from x264 or from bytestream h264 */ - /* nal reformating needed */ + if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1) { + /* from x264 or from bytestream H.264 */ + /* NAL reformatting needed */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data, &size); @@ -3050,7 +3566,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } else { size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size); } - } else if (enc->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 && + } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 && (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { @@ -3063,21 +3579,25 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) avio_write(pb, pkt->data, size); } - if ((enc->codec_id == AV_CODEC_ID_DNXHD || - enc->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { + if ((par->codec_id == AV_CODEC_ID_DNXHD || + par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { /* copy frame to create needed atoms */ trk->vos_len = size; trk->vos_data = av_malloc(size); - if (!trk->vos_data) - return AVERROR(ENOMEM); + if (!trk->vos_data) { + ret = AVERROR(ENOMEM); + goto err; + } memcpy(trk->vos_data, pkt->data, size); } if (trk->entry >= trk->cluster_capacity) { unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE); if (av_reallocp_array(&trk->cluster, new_capacity, - sizeof(*trk->cluster))) - return AVERROR(ENOMEM); + sizeof(*trk->cluster))) { + ret = AVERROR(ENOMEM); + goto err; + } trk->cluster_capacity = new_capacity; } @@ -3087,14 +3607,61 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->cluster[trk->entry].entries = samples_in_chunk; trk->cluster[trk->entry].dts = pkt->dts; if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) { - /* First packet of a new fragment. We already wrote the duration - * of the last packet of the previous fragment based on track_duration, - * which might not exactly match our dts. Therefore adjust the dts - * of this packet to be what the previous packets duration implies. */ - trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; + if (!trk->frag_discont) { + /* First packet of a new fragment. We already wrote the duration + * of the last packet of the previous fragment based on track_duration, + * which might not exactly match our dts. Therefore adjust the dts + * of this packet to be what the previous packets duration implies. */ + trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; + /* We also may have written the pts and the corresponding duration + * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with + * the next fragment. This means the cts of the first sample must + * be the same in all fragments, unless end_pts was updated by + * the packet causing the fragment to be written. */ + if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) || + mov->mode == MODE_ISM) + pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts; + } else { + /* New fragment, but discontinuous from previous fragments. + * Pretend the duration sum of the earlier fragments is + * pkt->dts - trk->start_dts. */ + trk->frag_start = pkt->dts - trk->start_dts; + trk->end_pts = AV_NOPTS_VALUE; + trk->frag_discont = 0; + } } - if (trk->start_dts == AV_NOPTS_VALUE) + if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist && + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { + /* Not using edit lists and shifting the first track to start from zero. + * If the other streams start from a later timestamp, we won't be able + * to signal the difference in starting time without an edit list. + * Thus move the timestamp for this first sample to 0, increasing + * its duration instead. */ + trk->cluster[trk->entry].dts = trk->start_dts = 0; + } + if (trk->start_dts == AV_NOPTS_VALUE) { trk->start_dts = pkt->dts; + if (trk->frag_discont) { + if (mov->use_editlist) { + /* Pretend the whole stream started at pts=0, with earlier fragments + * already written. If the stream started at pts=0, the duration sum + * of earlier fragments would have been pkt->pts. */ + trk->frag_start = pkt->pts; + trk->start_dts = pkt->dts - pkt->pts; + } else { + /* Pretend the whole stream started at dts=0, with earlier fragments + * already written, with a duration summing up to pkt->dts. */ + trk->frag_start = pkt->dts; + trk->start_dts = 0; + } + trk->frag_discont = 0; + } else if (pkt->dts && mov->moov_written) + av_log(s, AV_LOG_WARNING, + "Track %d starts with a nonzero dts %"PRId64", while the moov " + "already has been written. Set the delay_moov flag to handle " + "this case.\n", + pkt->stream_index, pkt->dts); + } trk->track_duration = pkt->dts - trk->start_dts + pkt->duration; if (pkt->pts == AV_NOPTS_VALUE) { @@ -3105,10 +3672,20 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->flags |= MOV_TRACK_CTTS; trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; trk->cluster[trk->entry].flags = 0; - if (enc->codec_id == AV_CODEC_ID_VC1) { - mov_parse_vc1_frame(pkt, trk, mov->fragments); + if (trk->start_cts == AV_NOPTS_VALUE) + trk->start_cts = pkt->pts - pkt->dts; + if (trk->end_pts == AV_NOPTS_VALUE) + trk->end_pts = trk->cluster[trk->entry].dts + + trk->cluster[trk->entry].cts + pkt->duration; + else + trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts + + trk->cluster[trk->entry].cts + + pkt->duration); + + if (par->codec_id == AV_CODEC_ID_VC1) { + mov_parse_vc1_frame(pkt, trk); } else if (pkt->flags & AV_PKT_FLAG_KEY) { - if (mov->mode == MODE_MOV && enc->codec_id == AV_CODEC_ID_MPEG2VIDEO && + if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO && trk->entry > 0) { // force sync sample for the first key frame mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags); if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE) @@ -3126,24 +3703,42 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry, reformatted_data, size); + +err: av_free(reformatted_data); - return 0; + return ret; } static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) { if (!pkt) { - mov_flush_fragment(s); + mov_flush_fragment(s, 1); return 1; } else { MOVMuxContext *mov = s->priv_data; MOVTrack *trk = &mov->tracks[pkt->stream_index]; - AVCodecContext *enc = trk->enc; + AVCodecParameters *par = trk->par; int64_t frag_duration = 0; int size = pkt->size; - if (!pkt->size) + if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) { + int i; + for (i = 0; i < s->nb_streams; i++) + mov->tracks[i].frag_discont = 1; + mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; + } + + if (!pkt->size) { + if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { + trk->start_dts = pkt->dts; + if (pkt->pts != AV_NOPTS_VALUE) + trk->start_cts = pkt->pts - pkt->dts; + else + trk->start_cts = 0; + } + return 0; /* Discard 0 sized packets */ + } if (trk->entry) frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, @@ -3153,10 +3748,21 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) frag_duration >= mov->max_fragment_duration) || (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) || (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME && - enc->codec_type == AVMEDIA_TYPE_VIDEO && + par->codec_type == AVMEDIA_TYPE_VIDEO && trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) { - if (frag_duration >= mov->min_fragment_duration) - mov_flush_fragment(s); + if (frag_duration >= mov->min_fragment_duration) { + // Set the duration of this track to line up with the next + // sample in this track. This avoids relying on AVPacket + // duration, but only helps for this particular track, not + // for the other ones that are flushed at the same time. + trk->track_duration = pkt->dts - trk->start_dts; + if (pkt->pts != AV_NOPTS_VALUE) + trk->end_pts = pkt->pts; + else + trk->end_pts = pkt->dts; + trk->end_reliable = 1; + mov_auto_flush_fragment(s, 0); + } } return ff_mov_write_packet(s, pkt); @@ -3177,15 +3783,15 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) track->mode = mov->mode; track->tag = MKTAG('t','e','x','t'); track->timescale = MOV_TIMESCALE; - track->enc = avcodec_alloc_context3(NULL); - if (!track->enc) + track->par = avcodec_parameters_alloc(); + if (!track->par) return AVERROR(ENOMEM); - track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE; - track->enc->extradata = av_malloc(sizeof(chapter_properties)); - if (!track->enc->extradata) + track->par->codec_type = AVMEDIA_TYPE_SUBTITLE; + track->par->extradata = av_malloc(sizeof(chapter_properties)); + if (!track->par->extradata) return AVERROR(ENOMEM); - track->enc->extradata_size = sizeof(chapter_properties); - memcpy(track->enc->extradata, chapter_properties, sizeof(chapter_properties)); + track->par->extradata_size = sizeof(chapter_properties); + memcpy(track->par->extradata, chapter_properties, sizeof(chapter_properties)); for (i = 0; i < s->nb_chapters; i++) { AVChapter *c = s->chapters[i]; @@ -3196,7 +3802,7 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) pkt.duration = end - pkt.dts; if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { - const char encd[12] = { + static const char encd[12] = { 0x00, 0x00, 0x00, 0x0C, 'e', 'n', 'c', 'd', 0x00, 0x00, 0x01, 0x00 }; @@ -3242,15 +3848,15 @@ static void enable_tracks(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type <= AVMEDIA_TYPE_UNKNOWN || - st->codec->codec_type >= AVMEDIA_TYPE_NB) + if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN || + st->codecpar->codec_type >= AVMEDIA_TYPE_NB) continue; - if (first[st->codec->codec_type] < 0) - first[st->codec->codec_type] = i; + if (first[st->codecpar->codec_type] < 0) + first[st->codecpar->codec_type] = i; if (st->disposition & AV_DISPOSITION_DEFAULT) { mov->tracks[i].flags |= MOV_TRACK_ENABLED; - enabled[st->codec->codec_type]++; + enabled[st->codecpar->codec_type]++; } } @@ -3273,11 +3879,8 @@ static void mov_free(AVFormatContext *s) MOVMuxContext *mov = s->priv_data; int i; - if (mov->chapter_track) { - if (mov->tracks[mov->chapter_track].enc) - av_free(mov->tracks[mov->chapter_track].enc->extradata); - av_freep(&mov->tracks[mov->chapter_track].enc); - } + if (mov->chapter_track) + avcodec_parameters_free(&mov->tracks[mov->chapter_track].par); for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) @@ -3314,7 +3917,7 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, int i, width = 720, height = 480; int have_palette = 0, have_size = 0; uint32_t palette[16]; - char *cur = st->codec->extradata; + char *cur = st->codecpar->extradata; while (cur && *cur) { if (strncmp("palette:", cur, 8) == 0) { @@ -3351,8 +3954,8 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, } track->vos_len = 16 * 4; } - st->codec->width = width; - st->codec->height = track->height = height; + st->codecpar->width = width; + st->codecpar->height = track->height = height; return 0; } @@ -3362,7 +3965,7 @@ static int mov_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; MOVMuxContext *mov = s->priv_data; AVDictionaryEntry *t; - int i, hint_track = 0; + int i, ret, hint_track = 0; mov->fc = s; @@ -3379,6 +3982,9 @@ static int mov_write_header(AVFormatContext *s) else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; } + if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) + mov->flags |= FF_MOV_FLAG_EMPTY_MOOV; + /* Set the FRAGMENT flag if any of the fragmentation methods are * enabled. */ if (mov->max_fragment_duration || mov->max_fragment_size || @@ -3391,16 +3997,43 @@ static int mov_write_header(AVFormatContext *s) if (mov->mode == MODE_ISM) mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF | FF_MOV_FLAG_FRAGMENT; + if (mov->flags & FF_MOV_FLAG_DASH) + mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | + FF_MOV_FLAG_DEFAULT_BASE_MOOF; - /* faststart: moov at the beginning of the file, if supported */ - if (mov->flags & FF_MOV_FLAG_FASTSTART) { - if ((mov->flags & FF_MOV_FLAG_FRAGMENT) || - (s->flags & AVFMT_FLAG_CUSTOM_IO)) { - av_log(s, AV_LOG_WARNING, "The faststart flag is incompatible " - "with fragmentation and custom IO, disabling faststart\n"); - mov->flags &= ~FF_MOV_FLAG_FASTSTART; + if (mov->use_editlist < 0) { + mov->use_editlist = 1; + if (mov->flags & FF_MOV_FLAG_FRAGMENT && + !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { + // If we can avoid needing an edit list by shifting the + // tracks, prefer that over (trying to) write edit lists + // in fragmented output. + if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO || + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) + mov->use_editlist = 0; } } + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && + !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist) + av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n"); + + if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO; + + /* Clear the omit_tfhd_offset flag if default_base_moof is set; + * if the latter is set that's enough and omit_tfhd_offset doesn't + * add anything extra on top of that. */ + if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET && + mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) + mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET; + + if (mov->frag_interleave && + mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) { + av_log(s, AV_LOG_ERROR, + "Sample interleaving in fragments is mutually exclusive with " + "omit_tfhd_offset and separate_moof\n"); + return AVERROR(EINVAL); + } /* Non-seekable output is ok if using fragmentation. If ism_lookahead * is enabled, we don't support non-seekable output at all. */ @@ -3411,13 +4044,9 @@ static int mov_write_header(AVFormatContext *s) } - 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 AVERROR(EINVAL); - } - mov_write_uuidprof_tag(pb, s); + if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { + if ((ret = mov_write_identification(pb, s)) < 0) + return ret; } mov->nb_streams = s->nb_streams; @@ -3429,8 +4058,8 @@ static int mov_write_header(AVFormatContext *s) hint_track = mov->nb_streams; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { mov->nb_streams++; } } @@ -3448,7 +4077,7 @@ static int mov_write_header(AVFormatContext *s) AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); track->st = st; - track->enc = st->codec; + track->par = st->codecpar; track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV); if (track->language < 0) track->language = 0; @@ -3463,11 +4092,13 @@ static int mov_write_header(AVFormatContext *s) * this is updated. */ track->hint_track = -1; track->start_dts = AV_NOPTS_VALUE; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + track->start_cts = AV_NOPTS_VALUE; + track->end_pts = AV_NOPTS_VALUE; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') || track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') || track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) { - if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) { + if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) { av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n"); goto error; } @@ -3479,34 +4110,34 @@ static int mov_write_header(AVFormatContext *s) "WARNING codec timebase is very high. If duration is too long,\n" "file may not be playable by quicktime. Specify a shorter timebase\n" "or choose different container.\n"); - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - track->timescale = st->codec->sample_rate; + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + track->timescale = st->codecpar->sample_rate; /* set sample_size for PCM and ADPCM */ - if (av_get_bits_per_sample(st->codec->codec_id) || - st->codec->codec_id == AV_CODEC_ID_ILBC) { - if (!st->codec->block_align) { + if (av_get_bits_per_sample(st->codecpar->codec_id) || + st->codecpar->codec_id == AV_CODEC_ID_ILBC) { + if (!st->codecpar->block_align) { av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set\n", i); goto error; } - track->sample_size = st->codec->block_align; + track->sample_size = st->codecpar->block_align; } /* set audio_vbr for compressed audio */ - if (av_get_bits_per_sample(st->codec->codec_id) < 8) { + if (av_get_bits_per_sample(st->codecpar->codec_id) < 8) { track->audio_vbr = 1; } if (track->mode != MODE_MOV && - track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) { + track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) { av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n", - i, track->enc->sample_rate); + i, track->par->sample_rate); goto error; } - } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { track->timescale = st->time_base.den; - } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { track->timescale = st->time_base.den; } if (!track->height) - track->height = st->codec->height; + track->height = st->codecpar->height; /* The ism specific timescale isn't mandatory, but is assumed by * some tools, such as mp4split. */ if (mov->mode == MODE_ISM) @@ -3515,13 +4146,15 @@ static int mov_write_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, track->timescale); /* copy extradata if it exists */ - if (st->codec->extradata_size) { - if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) + if (st->codecpar->extradata_size) { + if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) mov_create_dvd_sub_decoder_specific_info(track, st); else { - track->vos_len = st->codec->extradata_size; + track->vos_len = st->codecpar->extradata_size; track->vos_data = av_malloc(track->vos_len); - memcpy(track->vos_data, st->codec->extradata, track->vos_len); + if (!track->vos_data) + goto error; + memcpy(track->vos_data, st->codecpar->extradata, track->vos_len); } } } @@ -3536,7 +4169,7 @@ static int mov_write_header(AVFormatContext *s) mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME; } else { if (mov->flags & FF_MOV_FLAG_FASTSTART) - mov->reserved_moov_pos = avio_tell(pb); + mov->reserved_header_pos = avio_tell(pb); mov_write_mdat_tag(pb, mov); } @@ -3553,8 +4186,8 @@ static int mov_write_header(AVFormatContext *s) /* Initialize the hint tracks for each audio and video stream */ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { ff_mov_init_hinting(s, hint_track, i); hint_track++; } @@ -3566,9 +4199,13 @@ static int mov_write_header(AVFormatContext *s) if (mov->flags & FF_MOV_FLAG_ISML) mov_write_isml_manifest(pb, mov); - if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && + !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { mov_write_moov_tag(pb, mov, s); - mov->fragments++; + avio_flush(pb); + mov->moov_written = 1; + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) + mov->reserved_header_pos = avio_tell(pb); } return 0; @@ -3589,6 +4226,18 @@ static int get_moov_size(AVFormatContext *s) return ffio_close_null_buf(moov_buf); } +static int get_sidx_size(AVFormatContext *s) +{ + int ret; + AVIOContext *buf; + MOVMuxContext *mov = s->priv_data; + + if ((ret = ffio_open_null_buf(&buf)) < 0) + return ret; + mov_write_sidx_tags(buf, mov, -1, 0); + return ffio_close_null_buf(buf); +} + /* * This function gets the moov size if moved to the top of the file: the chunk * offset table can switch between stco (32-bit entries) to co64 (64-bit @@ -3620,6 +4269,21 @@ static int compute_moov_size(AVFormatContext *s) return moov_size2; } +static int compute_sidx_size(AVFormatContext *s) +{ + int i, sidx_size; + MOVMuxContext *mov = s->priv_data; + + sidx_size = get_sidx_size(s); + if (sidx_size < 0) + return sidx_size; + + for (i = 0; i < mov->nb_streams; i++) + mov->tracks[i].data_offset += sidx_size; + + return sidx_size; +} + static int shift_data(AVFormatContext *s) { int ret = 0, moov_size; @@ -3630,7 +4294,10 @@ static int shift_data(AVFormatContext *s) int read_size[2]; AVIOContext *read_pb; - moov_size = compute_moov_size(s); + if (mov->flags & FF_MOV_FLAG_FRAGMENT) + moov_size = compute_sidx_size(s); + else + moov_size = compute_moov_size(s); if (moov_size < 0) return moov_size; @@ -3644,7 +4311,7 @@ static int shift_data(AVFormatContext *s) * writing, so we re-open the same output, but for reading. It also avoids * a read/seek/write/seek back and forth. */ avio_flush(s->pb); - ret = avio_open(&read_pb, s->filename, AVIO_FLAG_READ); + ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " "the second pass (faststart)\n", s->filename); @@ -3654,10 +4321,10 @@ static int shift_data(AVFormatContext *s) /* mark the end of the shift to up to the last data we wrote, and get ready * for writing */ pos_end = avio_tell(s->pb); - avio_seek(s->pb, mov->reserved_moov_pos + moov_size, SEEK_SET); + avio_seek(s->pb, mov->reserved_header_pos + moov_size, SEEK_SET); /* start reading at where the new moov will be placed */ - avio_seek(read_pb, mov->reserved_moov_pos, SEEK_SET); + avio_seek(read_pb, mov->reserved_header_pos, SEEK_SET); pos = avio_tell(read_pb); #define READ_BLOCK do { \ @@ -3676,7 +4343,7 @@ static int shift_data(AVFormatContext *s) avio_write(s->pb, read_buf[read_buf_id], n); pos += n; } while (pos < pos_end); - avio_close(read_pb); + ff_format_io_close(s, &read_pb); end: av_free(buf); @@ -3724,27 +4391,30 @@ static int mov_write_trailer(AVFormatContext *s) av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n"); res = shift_data(s); if (res == 0) { - avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET); + avio_seek(pb, mov->reserved_header_pos, SEEK_SET); mov_write_moov_tag(pb, mov, s); } } else { mov_write_moov_tag(pb, mov, s); } } else { - mov_flush_fragment(s); - mov_write_mfra_tag(pb, mov); - } - - for (i = 0; i < mov->nb_streams; i++) { - if (mov->flags & FF_MOV_FLAG_FRAGMENT && - mov->tracks[i].vc1_info.struct_offset && s->pb->seekable) { - int64_t off = avio_tell(pb); - uint8_t buf[7]; - if (mov_write_dvc1_structs(&mov->tracks[i], buf) >= 0) { - avio_seek(pb, mov->tracks[i].vc1_info.struct_offset, SEEK_SET); - avio_write(pb, buf, 7); - avio_seek(pb, off, SEEK_SET); + mov_auto_flush_fragment(s, 1); + for (i = 0; i < mov->nb_streams; i++) + mov->tracks[i].data_offset = 0; + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) { + av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n"); + res = shift_data(s); + if (res == 0) { + int64_t end = avio_tell(pb); + avio_seek(pb, mov->reserved_header_pos, SEEK_SET); + mov_write_sidx_tags(pb, mov, -1, 0); + avio_seek(pb, end, SEEK_SET); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); + mov_write_mfra_tag(pb, mov); } + } else if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) { + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); + mov_write_mfra_tag(pb, mov); } } diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 2f2c09c..f4ed188 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -73,6 +73,7 @@ typedef struct MOVFragmentInfo { int64_t time; int64_t duration; int64_t tfrf_offset; + int size; } MOVFragmentInfo; typedef struct MOVTrack { @@ -92,7 +93,7 @@ typedef struct MOVTrack { int track_id; int tag; ///< stsd fourcc AVStream *st; - AVCodecContext *enc; + AVCodecParameters *par; int vos_len; uint8_t *vos_data; @@ -103,6 +104,9 @@ typedef struct MOVTrack { uint32_t tref_tag; int tref_id; ///< trackID of the referenced track int64_t start_dts; + int64_t start_cts; + int64_t end_pts; + int end_reliable; int hint_track; ///< the track that hints this track, -1 if no hint track is set int src_track; ///< the track that this hint track describes @@ -120,16 +124,18 @@ typedef struct MOVTrack { AVIOContext *mdat_buf; int64_t data_offset; int64_t frag_start; - int64_t tfrf_offset; + int frag_discont; + int entries_flushed; int nb_frag_info; MOVFragmentInfo *frag_info; unsigned frag_info_capacity; struct { - int64_t struct_offset; int first_packet_seq; int first_packet_entry; + int first_packet_seen; + int first_frag_written; int packet_seq; int packet_entry; int slices; @@ -152,31 +158,43 @@ typedef struct MOVMuxContext { int iods_video_profile; int iods_audio_profile; + int moov_written; int fragments; int max_fragment_duration; int min_fragment_duration; int max_fragment_size; int ism_lookahead; AVIOContext *mdat_buf; + int first_trun; - int64_t reserved_moov_pos; + int64_t reserved_header_pos; char *major_brand; int per_stream_grouping; AVFormatContext *fc; + + int use_editlist; + int frag_interleave; + int missing_duration_warned; } MOVMuxContext; -#define FF_MOV_FLAG_RTP_HINT 1 -#define FF_MOV_FLAG_FRAGMENT 2 -#define FF_MOV_FLAG_EMPTY_MOOV 4 -#define FF_MOV_FLAG_FRAG_KEYFRAME 8 -#define FF_MOV_FLAG_SEPARATE_MOOF 16 -#define FF_MOV_FLAG_FRAG_CUSTOM 32 -#define FF_MOV_FLAG_ISML 64 -#define FF_MOV_FLAG_FASTSTART 128 -#define FF_MOV_FLAG_OMIT_TFHD_OFFSET 256 -#define FF_MOV_FLAG_DISABLE_CHPL 512 +#define FF_MOV_FLAG_RTP_HINT (1 << 0) +#define FF_MOV_FLAG_FRAGMENT (1 << 1) +#define FF_MOV_FLAG_EMPTY_MOOV (1 << 2) +#define FF_MOV_FLAG_FRAG_KEYFRAME (1 << 3) +#define FF_MOV_FLAG_SEPARATE_MOOF (1 << 4) +#define FF_MOV_FLAG_FRAG_CUSTOM (1 << 5) +#define FF_MOV_FLAG_ISML (1 << 6) +#define FF_MOV_FLAG_FASTSTART (1 << 7) +#define FF_MOV_FLAG_OMIT_TFHD_OFFSET (1 << 8) +#define FF_MOV_FLAG_DISABLE_CHPL (1 << 9) +#define FF_MOV_FLAG_DEFAULT_BASE_MOOF (1 << 10) +#define FF_MOV_FLAG_DASH (1 << 11) +#define FF_MOV_FLAG_FRAG_DISCONT (1 << 12) +#define FF_MOV_FLAG_DELAY_MOOV (1 << 13) +#define FF_MOV_FLAG_GLOBAL_SIDX (1 << 14) +#define FF_MOV_FLAG_SKIP_TRAILER (1 << 15) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); diff --git a/libavformat/movenchint.c b/libavformat/movenchint.c index a8f5f34..58ad9e4 100644 --- a/libavformat/movenchint.c +++ b/libavformat/movenchint.c @@ -37,11 +37,11 @@ int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index) track->tag = MKTAG('r','t','p',' '); track->src_track = src_index; - track->enc = avcodec_alloc_context3(NULL); - if (!track->enc) + track->par = avcodec_parameters_alloc(); + if (!track->par) goto fail; - track->enc->codec_type = AVMEDIA_TYPE_DATA; - track->enc->codec_tag = track->tag; + track->par->codec_type = AVMEDIA_TYPE_DATA; + track->par->codec_tag = track->tag; ret = ff_rtp_chain_mux_open(&track->rtp_ctx, s, src_st, NULL, RTP_MAX_PACKET_SIZE, src_index); @@ -58,7 +58,7 @@ int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index) fail: av_log(s, AV_LOG_WARNING, "Unable to initialize hinting of stream %d\n", src_index); - av_freep(&track->enc); + avcodec_parameters_free(&track->par); /* Set a default timescale, to avoid crashes in av_dump_format */ track->timescale = 90000; return ret; @@ -458,16 +458,14 @@ done: void ff_mov_close_hinting(MOVTrack *track) { AVFormatContext *rtp_ctx = track->rtp_ctx; - uint8_t *ptr; - av_freep(&track->enc); + avcodec_parameters_free(&track->par); sample_queue_free(&track->sample_queue); if (!rtp_ctx) return; if (rtp_ctx->pb) { av_write_trailer(rtp_ctx); - avio_close_dyn_buf(rtp_ctx->pb, &ptr); - av_free(ptr); + ffio_free_dyn_buf(&rtp_ctx->pb); } avformat_free_context(rtp_ctx); } diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index cba6778..e282218 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -53,13 +53,9 @@ typedef struct MP3DecContext { static int mp3_read_probe(AVProbeData *p) { int max_frames, first_frames = 0; - int fsize, frames, sample_rate; + int frames, ret; uint32_t header; uint8_t *buf, *buf0, *buf2, *end; - AVCodecContext *avctx = avcodec_alloc_context3(NULL); - - if (!avctx) - return AVERROR(ENOMEM); buf0 = p->buf; end = p->buf + p->buf_size - sizeof(uint32_t); @@ -73,19 +69,18 @@ static int mp3_read_probe(AVProbeData *p) buf2 = buf; for(frames = 0; buf2 < end; frames++) { + MPADecodeHeader h; + header = AV_RB32(buf2); - fsize = avpriv_mpa_decode_header(avctx, header, &sample_rate, - &sample_rate, &sample_rate, - &sample_rate); - if(fsize < 0) + ret = avpriv_mpegaudio_decode_header(&h, header); + if (ret != 0) break; - buf2 += fsize; + buf2 += h.frame_size; } max_frames = FFMAX(max_frames, frames); if(buf == buf0) first_frames= frames; } - avcodec_free_context(&avctx); // keep this in sync with ac3 probe, both need to avoid // issues with MPEG-files! if (first_frames >= 10) @@ -148,7 +143,7 @@ static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, #define MIDDLE_BITS(k, m, n) LAST_BITS((k) >> (m), ((n) - (m))) uint16_t crc; - uint32_t v; + uint32_t v, delays; char version[10]; @@ -156,7 +151,7 @@ static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, int32_t r_gain = INT32_MIN, a_gain = INT32_MIN; MP3DecContext *mp3 = s->priv_data; - const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}}; + static const int64_t xing_offtbl[2][2] = { { 32, 17 }, { 17, 9 } }; /* Check for Xing / Info tag */ avio_skip(s->pb, xing_offtbl[c->lsf == 1][c->nb_channels == 1]); @@ -220,7 +215,9 @@ static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, avio_r8(s->pb); /* Encoder delays */ - avio_rb24(s->pb); + delays = avio_rb24(s->pb); + st->codecpar->initial_padding = delays >> 12; + st->codecpar->trailing_padding = delays & ((1 << 12) - 1); /* Misc */ avio_r8(s->pb); @@ -275,14 +272,16 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) MPADecodeHeader c; int vbrtag_size = 0; MP3DecContext *mp3 = s->priv_data; + int ret; ffio_init_checksum(s->pb, ff_crcA001_update, 0); v = avio_rb32(s->pb); - if(ff_mpa_check_header(v) < 0) - return -1; - if (avpriv_mpegaudio_decode_header(&c, v) == 0) + ret = avpriv_mpegaudio_decode_header(&c, v); + if (ret < 0) + return ret; + else if (ret == 0) vbrtag_size = c.frame_size; if(c.layer != 3) return -1; @@ -305,7 +304,7 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate}, st->time_base); if (mp3->size && mp3->frames && !mp3->is_cbr) - st->codec->bit_rate = av_rescale(mp3->size, 8 * c.sample_rate, mp3->frames * (int64_t)spf); + st->codecpar->bit_rate = av_rescale(mp3->size, 8 * c.sample_rate, mp3->frames * (int64_t)spf); return 0; } @@ -320,8 +319,8 @@ static int mp3_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MP3; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MP3; st->need_parsing = AVSTREAM_PARSE_FULL; st->start_time = 0; @@ -366,6 +365,69 @@ static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; } +#define SEEK_PACKETS 4 +#define SEEK_WINDOW (SEEK_PACKETS * MP3_PACKET_SIZE) + +/* The toc entry can position to the wrong byte offset, try to pick + * the closest frame by probing the data in a window of 4 packets. + */ + +static int check(AVIOContext *pb, int64_t pos, int64_t *out_pos) +{ + MPADecodeHeader mh = { 0 }; + int i; + uint32_t header; + int64_t off = 0; + + + for (i = 0; i < SEEK_PACKETS; i++) { + off = avio_seek(pb, pos + mh.frame_size, SEEK_SET); + if (off < 0) + break; + + header = avio_rb32(pb); + + + if (avpriv_mpegaudio_decode_header(&mh, header)) + break; + out_pos[i] = off; + } + + return i; +} + +static int reposition(AVFormatContext *s, int64_t pos) +{ + int ret, best_valid = -1; + int64_t p, best_pos = -1; + + for (p = FFMAX(pos - SEEK_WINDOW / 2, 0); p < pos + SEEK_WINDOW / 2; p++) { + int64_t out_pos[SEEK_PACKETS]; + ret = check(s->pb, p, out_pos); + + if (best_valid < ret) { + int i; + for (i = 0; i < ret; i++) { + if (llabs(best_pos - pos) > llabs(out_pos[i] - pos)) { + best_pos = out_pos[i]; + best_valid = ret; + } + } + if (best_pos == pos && best_valid == SEEK_PACKETS) + break; + } + } + + if (best_valid <= 0) + return AVERROR(ENOSYS); + + p = avio_seek(s->pb, best_pos, SEEK_SET); + if (p < 0) + return p; + + return 0; +} + static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { @@ -373,7 +435,6 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, AVIndexEntry *ie; AVStream *st = s->streams[0]; int64_t ret = av_index_search_timestamp(st, timestamp, flags); - uint32_t header = 0; if (!mp3->xing_toc) return AVERROR(ENOSYS); @@ -382,20 +443,14 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, return ret; ie = &st->index_entries[ret]; - ret = avio_seek(s->pb, ie->pos, SEEK_SET); + + ret = reposition(s, ie->pos); if (ret < 0) return ret; - while (!s->pb->eof_reached) { - header = (header << 8) + avio_r8(s->pb); - if (ff_mpa_check_header(header) >= 0) { - ff_update_cur_dts(s, st, ie->timestamp); - ret = avio_seek(s->pb, -4, SEEK_CUR); - return (ret >= 0) ? 0 : ret; - } - } + ff_update_cur_dts(s, st, ie->timestamp); - return AVERROR_EOF; + return 0; } AVInputFormat ff_mp3_demuxer = { diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 1eaa585..1e2ff1a 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -32,6 +32,9 @@ #include "libavutil/opt.h" #include "libavutil/dict.h" #include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/mathematics.h" +#include "libavutil/replaygain.h" static int id3v1_set_string(AVFormatContext *s, const char *key, uint8_t *buf, int buf_size) @@ -76,8 +79,8 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf) #define XING_NUM_BAGS 400 #define XING_TOC_SIZE 100 -// maximum size of the xing frame: offset/Xing/flags/frames/size/TOC -#define XING_MAX_SIZE (32 + 4 + 4 + 4 + 4 + XING_TOC_SIZE) +// size of the XING/LAME data, starting from the Xing tag +#define XING_SIZE 156 typedef struct MP3Context { const AVClass *class; @@ -87,7 +90,18 @@ typedef struct MP3Context { int write_xing; /* xing header */ - int64_t xing_offset; + // a buffer containing the whole XING/LAME frame + uint8_t *xing_frame; + int xing_frame_size; + + AVCRC audio_crc; // CRC of the audio data + uint32_t audio_size; // total size of the audio data + + // offset of the XING/LAME frame in the file + int64_t xing_frame_offset; + // offset of the XING/INFO tag in the frame + int xing_offset; + int32_t frames; int32_t size; uint32_t want; @@ -114,14 +128,16 @@ static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}}; static void mp3_write_xing(AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec; + AVCodecParameters *par = s->streams[mp3->audio_stream_idx]->codecpar; + AVDictionaryEntry *enc = av_dict_get(s->streams[mp3->audio_stream_idx]->metadata, "encoder", NULL, 0); + AVIOContext *dyn_ctx; int32_t header; MPADecodeHeader mpah; int srate_idx, i, channels; int bitrate_idx; int best_bitrate_idx; int best_bitrate_error = INT_MAX; - int xing_offset; + int ret; int ver = 0; int lsf, bytes_needed; @@ -131,9 +147,9 @@ static void mp3_write_xing(AVFormatContext *s) for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) { const uint16_t base_freq = avpriv_mpa_freq_tab[i]; - if (codec->sample_rate == base_freq) ver = 0x3; // MPEG 1 - else if (codec->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 - else if (codec->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5 + if (par->sample_rate == base_freq) ver = 0x3; // MPEG 1 + else if (par->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 + else if (par->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5 else continue; srate_idx = i; @@ -145,7 +161,7 @@ static void mp3_write_xing(AVFormatContext *s) return; } - switch (codec->channels) { + switch (par->channels) { case 1: channels = MPA_MONO; break; case 2: channels = MPA_STEREO; break; default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, " @@ -161,18 +177,12 @@ static void mp3_write_xing(AVFormatContext *s) lsf = !((header & (1 << 20) && header & (1 << 19))); - xing_offset = xing_offtbl[ver != 3][channels == 1]; - bytes_needed = 4 // header - + xing_offset - + 4 // xing tag - + 4 // frames/size/toc flags - + 4 // frames - + 4 // size - + XING_TOC_SIZE; // toc + mp3->xing_offset = xing_offtbl[ver != 3][channels == 1] + 4; + bytes_needed = mp3->xing_offset + XING_SIZE; for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) { int bit_rate = 1000 * avpriv_mpa_bitrate_tab[lsf][3 - 1][bitrate_idx]; - int error = FFABS(bit_rate - codec->bit_rate); + int error = FFABS(bit_rate - par->bit_rate); if (error < best_bitrate_error){ best_bitrate_error = error; @@ -192,28 +202,73 @@ static void mp3_write_xing(AVFormatContext *s) header &= ~mask; } - avio_wb32(s->pb, header); + ret = avio_open_dyn_buf(&dyn_ctx); + if (ret < 0) + return; + + avio_wb32(dyn_ctx, header); avpriv_mpegaudio_decode_header(&mpah, header); av_assert0(mpah.frame_size >= bytes_needed); - ffio_fill(s->pb, 0, xing_offset); - mp3->xing_offset = avio_tell(s->pb); - ffio_wfourcc(s->pb, "Xing"); - avio_wb32(s->pb, 0x01 | 0x02 | 0x04); // frames / size / TOC + ffio_fill(dyn_ctx, 0, mp3->xing_offset - 4); + ffio_wfourcc(dyn_ctx, "Xing"); + avio_wb32(dyn_ctx, 0x01 | 0x02 | 0x04 | 0x08); // frames / size / TOC / vbr scale mp3->size = mpah.frame_size; mp3->want = 1; - avio_wb32(s->pb, 0); // frames - avio_wb32(s->pb, 0); // size + avio_wb32(dyn_ctx, 0); // frames + avio_wb32(dyn_ctx, 0); // size // TOC for (i = 0; i < XING_TOC_SIZE; i++) - avio_w8(s->pb, 255 * i / XING_TOC_SIZE); + avio_w8(dyn_ctx, 255 * i / XING_TOC_SIZE); + + // vbr quality + // we write it, because some (broken) tools always expect it to be present + avio_wb32(dyn_ctx, 0); + + // encoder short version string + if (enc) { + uint8_t encoder_str[9] = { 0 }; + memcpy(encoder_str, enc->value, FFMIN(strlen(enc->value), sizeof(encoder_str))); + avio_write(dyn_ctx, encoder_str, sizeof(encoder_str)); + } else + ffio_fill(dyn_ctx, 0, 9); + + avio_w8(dyn_ctx, 0); // tag revision 0 / unknown vbr method + avio_w8(dyn_ctx, 0); // unknown lowpass filter value + ffio_fill(dyn_ctx, 0, 8); // empty replaygain fields + avio_w8(dyn_ctx, 0); // unknown encoding flags + avio_w8(dyn_ctx, 0); // unknown abr/minimal bitrate + + // encoder delay + if (par->initial_padding >= 1 << 12 || + par->trailing_padding >= 1 << 12) { + av_log(s, AV_LOG_WARNING, "Too many samples of padding.\n"); + avio_wb24(dyn_ctx, 0); + } else { + avio_wb24(dyn_ctx, par->initial_padding << 12 | par->trailing_padding); + } - ffio_fill(s->pb, 0, mpah.frame_size - bytes_needed); + avio_w8(dyn_ctx, 0); // misc + avio_w8(dyn_ctx, 0); // mp3gain + avio_wb16(dyn_ctx, 0); // preset + + // audio length and CRCs (will be updated later) + avio_wb32(dyn_ctx, 0); // music length + avio_wb16(dyn_ctx, 0); // music crc + avio_wb16(dyn_ctx, 0); // tag crc + + ffio_fill(dyn_ctx, 0, mpah.frame_size - bytes_needed); + + mp3->xing_frame_size = avio_close_dyn_buf(dyn_ctx, &mp3->xing_frame); + mp3->xing_frame_offset = avio_tell(s->pb); + avio_write(s->pb, mp3->xing_frame, mp3->xing_frame_size); + + mp3->audio_size = mp3->xing_frame_size; } /* @@ -252,11 +307,12 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt) if (mp3->xing_offset && pkt->size >= 4) { MPADecodeHeader c; + int ret; uint32_t h; h = AV_RB32(pkt->data); - if (ff_mpa_check_header(h) == 0) { - avpriv_mpegaudio_decode_header(&c, h); + ret = avpriv_mpegaudio_decode_header(&c, h); + if (ret >= 0) { if (!mp3->initial_bitrate) mp3->initial_bitrate = c.bit_rate; if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate)) @@ -264,6 +320,12 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt) } mp3_xing_add_frame(mp3, pkt); + + if (mp3->xing_offset) { + mp3->audio_size += pkt->size; + mp3->audio_crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), + mp3->audio_crc, pkt->data, pkt->size); + } } return ff_raw_write_packet(s, pkt); @@ -281,7 +343,7 @@ static int mp3_queue_flush(AVFormatContext *s) while ((pktl = mp3->queue)) { if (write && (ret = mp3_write_audio_packet(s, &pktl->pkt)) < 0) write = 0; - av_free_packet(&pktl->pkt); + av_packet_unref(&pktl->pkt); mp3->queue = pktl->next; av_freep(&pktl); } @@ -292,26 +354,58 @@ static int mp3_queue_flush(AVFormatContext *s) static void mp3_update_xing(AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - int i; + AVReplayGain *rg; + uint16_t tag_crc; + uint8_t *toc; + int i, rg_size; /* replace "Xing" identification string with "Info" for CBR files. */ - if (!mp3->has_variable_bitrate) { - avio_seek(s->pb, mp3->xing_offset, SEEK_SET); - ffio_wfourcc(s->pb, "Info"); - } - - avio_seek(s->pb, mp3->xing_offset + 8, SEEK_SET); - avio_wb32(s->pb, mp3->frames); - avio_wb32(s->pb, mp3->size); + if (!mp3->has_variable_bitrate) + AV_WL32(mp3->xing_frame + mp3->xing_offset, MKTAG('I', 'n', 'f', 'o')); - avio_w8(s->pb, 0); // first toc entry has to be zero. + AV_WB32(mp3->xing_frame + mp3->xing_offset + 8, mp3->frames); + AV_WB32(mp3->xing_frame + mp3->xing_offset + 12, mp3->size); + toc = mp3->xing_frame + mp3->xing_offset + 16; + toc[0] = 0; // first toc entry has to be zero. for (i = 1; i < XING_TOC_SIZE; ++i) { int j = i * mp3->pos / XING_TOC_SIZE; int seek_point = 256LL * mp3->bag[j] / mp3->size; - avio_w8(s->pb, FFMIN(seek_point, 255)); + toc[i] = FFMIN(seek_point, 255); + } + + /* write replaygain */ + rg = (AVReplayGain*)av_stream_get_side_data(s->streams[0], AV_PKT_DATA_REPLAYGAIN, + &rg_size); + if (rg && rg_size >= sizeof(*rg)) { + uint16_t val; + + AV_WB32(mp3->xing_frame + mp3->xing_offset + 131, + av_rescale(rg->track_peak, 1 << 23, 100000)); + + if (rg->track_gain != INT32_MIN) { + val = FFABS(rg->track_gain / 10000) & ((1 << 9) - 1); + val |= (rg->track_gain < 0) << 9; + val |= 1 << 13; + AV_WB16(mp3->xing_frame + mp3->xing_offset + 135, val); + } + + if (rg->album_gain != INT32_MIN) { + val = FFABS(rg->album_gain / 10000) & ((1 << 9) - 1); + val |= (rg->album_gain < 0) << 9; + val |= 1 << 14; + AV_WB16(mp3->xing_frame + mp3->xing_offset + 137, val); + } } + AV_WB32(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 8, mp3->audio_size); + AV_WB16(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 4, mp3->audio_crc); + + tag_crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), 0, mp3->xing_frame, 190); + AV_WB16(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 2, tag_crc); + + avio_seek(s->pb, mp3->xing_frame_offset, SEEK_SET); + avio_write(s->pb, mp3->xing_frame, mp3->xing_frame_size); avio_seek(s->pb, 0, SEEK_END); } @@ -334,24 +428,11 @@ static int mp3_write_trailer(struct AVFormatContext *s) if (mp3->xing_offset) mp3_update_xing(s); + av_freep(&mp3->xing_frame); + return 0; } -#if CONFIG_MP2_MUXER -AVOutputFormat ff_mp2_muxer = { - .name = "mp2", - .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .mime_type = "audio/x-mpeg", - .extensions = "mp2,m2a,mpa", - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_NONE, - .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, -}; -#endif - -#if CONFIG_MP3_MUXER - static const AVOption options[] = { { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.", offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.i64 = 4}, 0, 4, AV_OPT_FLAG_ENCODING_PARAM}, @@ -440,14 +521,14 @@ static int mp3_write_header(struct AVFormatContext *s) mp3->audio_stream_idx = -1; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (mp3->audio_stream_idx >= 0 || st->codec->codec_id != AV_CODEC_ID_MP3) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (mp3->audio_stream_idx >= 0 || st->codecpar->codec_id != AV_CODEC_ID_MP3) { av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one MP3 " "audio stream is required.\n"); return AVERROR(EINVAL); } mp3->audio_stream_idx = i; - } else if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO) { + } else if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in MP3.\n"); return AVERROR(EINVAL); } @@ -483,7 +564,7 @@ static int mp3_write_header(struct AVFormatContext *s) AVOutputFormat ff_mp3_muxer = { .name = "mp3", .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), - .mime_type = "audio/x-mpeg", + .mime_type = "audio/mpeg", .extensions = "mp3", .priv_data_size = sizeof(MP3Context), .audio_codec = AV_CODEC_ID_MP3, @@ -494,4 +575,3 @@ AVOutputFormat ff_mp3_muxer = { .flags = AVFMT_NOTIMESTAMPS, .priv_class = &mp3_muxer_class, }; -#endif diff --git a/libavformat/mpc.c b/libavformat/mpc.c index 5e771ae..cf8fe1e 100644 --- a/libavformat/mpc.c +++ b/libavformat/mpc.c @@ -20,7 +20,7 @@ */ #include "libavutil/channel_layout.h" -#include "libavcodec/get_bits.h" + #include "avformat.h" #include "internal.h" #include "apetag.h" @@ -31,12 +31,12 @@ #define DELAY_FRAMES 32 static const int mpc_rate[4] = { 44100, 48000, 37800, 32000 }; -typedef struct { +typedef struct MPCFrame { int64_t pos; int size, skip; }MPCFrame; -typedef struct { +typedef struct MPCContext { int ver; uint32_t curframe, lastframe; uint32_t fcount; @@ -89,17 +89,17 @@ static int mpc_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MUSEPACK7; - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->bits_per_coded_sample = 16; - - st->codec->extradata_size = 16; - st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); - avio_read(s->pb, st->codec->extradata, 16); - st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3]; - avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->bits_per_coded_sample = 16; + + st->codecpar->extradata_size = 16; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size+AV_INPUT_BUFFER_PADDING_SIZE); + avio_read(s->pb, st->codecpar->extradata, 16); + st->codecpar->sample_rate = mpc_rate[st->codecpar->extradata[2] & 3]; + avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codecpar->sample_rate); /* scan for seekpoints */ st->start_time = 0; st->duration = c->fcount; @@ -167,7 +167,7 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt) if(c->curbits) avio_seek(s->pb, -4, SEEK_CUR); if(ret < size){ - av_free_packet(pkt); + av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } pkt->size = ret + 4; @@ -218,7 +218,7 @@ static int mpc_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp c->curframe = lastframe; return ret; } - av_free_packet(pkt); + av_packet_unref(pkt); } return 0; } diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c index 3564e81..2349ea5 100644 --- a/libavformat/mpc8.c +++ b/libavformat/mpc8.c @@ -47,7 +47,7 @@ enum MPCPacketTags{ static const int mpc8_rate[8] = { 44100, 48000, 37800, 32000, -1, -1, -1, -1 }; -typedef struct { +typedef struct MPCContext { int ver; int64_t header_pos; int64_t samples; @@ -154,7 +154,7 @@ static void mpc8_parse_seektable(AVFormatContext *s, int64_t off) av_log(s, AV_LOG_ERROR, "Bad seek table size\n"); return; } - if(!(buf = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE))) + if(!(buf = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE))) return; avio_read(s->pb, buf, size); init_get_bits(&gb, buf, size * 8); @@ -237,19 +237,19 @@ static int mpc8_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MUSEPACK8; - st->codec->bits_per_coded_sample = 16; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK8; + st->codecpar->bits_per_coded_sample = 16; - st->codec->extradata_size = 2; - st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - avio_read(pb, st->codec->extradata, st->codec->extradata_size); + st->codecpar->extradata_size = 2; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + avio_read(pb, st->codecpar->extradata, st->codecpar->extradata_size); - st->codec->channels = (st->codec->extradata[1] >> 4) + 1; - st->codec->sample_rate = mpc8_rate[st->codec->extradata[0] >> 5]; - avpriv_set_pts_info(st, 32, 1152 << (st->codec->extradata[1]&3)*2, st->codec->sample_rate); + st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1; + st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5]; + avpriv_set_pts_info(st, 32, 1152 << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate); st->start_time = 0; - st->duration = c->samples / (1152 << (st->codec->extradata[1]&3)*2); + st->duration = c->samples / (1152 << (st->codecpar->extradata[1]&3)*2); size -= avio_tell(pb) - pos; if (pb->seekable) { diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 7c87517..f63e79f 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -1,5 +1,5 @@ /* - * MPEG1/2 demuxer + * MPEG-1/2 demuxer * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * * This file is part of Libav. @@ -23,9 +23,6 @@ #include "internal.h" #include "mpeg.h" -#undef NDEBUG -#include - /*********************************************/ /* demux code */ @@ -290,7 +287,7 @@ redo: goto error_redo; c = avio_r8(s->pb); len--; - /* XXX: for mpeg1, should test only bit 7 */ + /* XXX: for MPEG-1, should test only bit 7 */ if (c != 0xff) break; } @@ -517,8 +514,8 @@ skip: if (!st) goto skip; st->id = startcode; - st->codec->codec_type = type; - st->codec->codec_id = codec_id; + st->codecpar->codec_type = type; + st->codecpar->codec_id = codec_id; st->need_parsing = AVSTREAM_PARSE_FULL; found: @@ -530,7 +527,7 @@ found: pkt->dts = dts; pkt->pos = dummy_pos; pkt->stream_index = st->index; - av_dlog(s, "%d: pts=%0.3f dts=%0.3f size=%d\n", + av_log(s, AV_LOG_TRACE, "%d: pts=%0.3f dts=%0.3f size=%d\n", pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size); @@ -550,7 +547,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, for (;;) { len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) { - av_dlog(s, "none (ret=%d)\n", len); + av_log(s, AV_LOG_TRACE, "none (ret=%d)\n", len); return AV_NOPTS_VALUE; } if (startcode == s->streams[stream_index]->id && @@ -559,7 +556,7 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, } avio_skip(s->pb, len); } - av_dlog(s, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", + av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0); *ppos = pos; return dts; diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h index 629f2f0..7f7f830 100644 --- a/libavformat/mpeg.h +++ b/libavformat/mpeg.h @@ -1,5 +1,5 @@ /* - * MPEG1/2 muxer and demuxer common defines + * MPEG-1/2 muxer and demuxer common defines * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * * This file is part of Libav. @@ -40,6 +40,7 @@ #define AUDIO_ID 0xc0 #define VIDEO_ID 0xe0 +#define H264_ID 0xe2 #define AC3_ID 0x80 #define DTS_ID 0x8a #define LPCM_ID 0xa0 diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index 8a62c54..1507e0e 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -1,5 +1,5 @@ /* - * MPEG1/2 muxer + * MPEG-1/2 muxer * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * * This file is part of Libav. @@ -43,11 +43,10 @@ typedef struct PacketDesc { int64_t dts; int size; int unwritten_size; - int flags; struct PacketDesc *next; } PacketDesc; -typedef struct { +typedef struct StreamInfo { AVFifoBuffer *fifo; uint8_t id; int max_buffer_size; /* in bytes */ @@ -63,7 +62,7 @@ typedef struct { int64_t vobu_start_pts; } StreamInfo; -typedef struct { +typedef struct MpegMuxContext { const AVClass *class; int packet_size; /* required packet size */ int packet_number; @@ -154,7 +153,7 @@ static int put_system_header(AVFormatContext *ctx, uint8_t *buf, put_bits(&pb, 1, 1); } else { put_bits(&pb, 1, 0); /* variable bitrate */ - put_bits(&pb, 1, 0); /* non constrainted bit stream */ + put_bits(&pb, 1, 0); /* nonconstrained bitstream */ } if (s->is_vcd || s->is_dvd) { @@ -301,7 +300,7 @@ static int get_system_header_size(AVFormatContext *ctx) static av_cold 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; + int bitrate, i, mpa_id, mpv_id, h264_id, mps_id, ac3_id, dts_id, lpcm_id, j; AVStream *st; StreamInfo *stream; int audio_bitrate; @@ -337,10 +336,13 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) ac3_id = AC3_ID; dts_id = DTS_ID; mpv_id = VIDEO_ID; + h264_id = H264_ID; mps_id = SUB_ID; lpcm_id = LPCM_ID; for (i = 0; i < ctx->nb_streams; i++) { + AVCPBProperties *props; + st = ctx->streams[i]; stream = av_mallocz(sizeof(StreamInfo)); if (!stream) @@ -349,26 +351,26 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) avpriv_set_pts_info(st, 64, 1, 90000); - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: - if (st->codec->codec_id == AV_CODEC_ID_AC3) { + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { stream->id = ac3_id++; - } else if (st->codec->codec_id == AV_CODEC_ID_DTS) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_DTS) { stream->id = dts_id++; - } else if (st->codec->codec_id == AV_CODEC_ID_PCM_S16BE) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) { stream->id = lpcm_id++; for (j = 0; j < 4; j++) { - if (lpcm_freq_tab[j] == st->codec->sample_rate) + if (lpcm_freq_tab[j] == st->codecpar->sample_rate) break; } if (j == 4) goto fail; - if (st->codec->channels > 8) + if (st->codecpar->channels > 8) return -1; stream->lpcm_header[0] = 0x0c; - stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4); + stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4); stream->lpcm_header[2] = 0x80; - stream->lpcm_align = st->codec->channels * 2; + stream->lpcm_align = st->codecpar->channels * 2; } else { stream->id = mpa_id++; } @@ -379,9 +381,14 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) s->audio_bound++; break; case AVMEDIA_TYPE_VIDEO: - stream->id = mpv_id++; - if (st->codec->rc_buffer_size) - stream->max_buffer_size = 6 * 1024 + st->codec->rc_buffer_size / 8; + if (st->codecpar->codec_id == AV_CODEC_ID_H264) + stream->id = h264_id++; + else + stream->id = mpv_id++; + + props = (AVCPBProperties*)av_stream_get_side_data(st, AV_PKT_DATA_CPB_PROPERTIES, NULL); + if (props && props->buffer_size) + stream->max_buffer_size = 6 * 1024 + props->buffer_size / 8; else { av_log(ctx, AV_LOG_WARNING, "VBV buffer size not set, muxing may fail\n"); @@ -405,14 +412,16 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) audio_bitrate = 0; video_bitrate = 0; for (i = 0; i < ctx->nb_streams; i++) { + AVCPBProperties *props; 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; + props = (AVCPBProperties*)av_stream_get_side_data(st, AV_PKT_DATA_CPB_PROPERTIES, NULL); + if (props) + codec_rate = props->max_bitrate; else - codec_rate = st->codec->bit_rate; + codec_rate = st->codecpar->bit_rate; if (!codec_rate) codec_rate = (1 << 21) * 8 * 50 / ctx->nb_streams; @@ -421,7 +430,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) if ((stream->id & 0xe0) == AUDIO_ID) audio_bitrate += codec_rate; - else if (stream->id == VIDEO_ID) + else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) video_bitrate += codec_rate; } @@ -582,7 +591,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, id = stream->id; - av_dlog(ctx, "packet ID=%2x PTS=%0.3f\n", id, pts / 90000.0); + av_log(ctx, AV_LOG_TRACE, "packet ID=%2x PTS=%0.3f\n", id, pts / 90000.0); buf_ptr = buffer; @@ -954,7 +963,7 @@ retry: /* 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 != AVMEDIA_TYPE_SUBTITLE) + && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) return 0; if (avail_data == 0) continue; @@ -984,7 +993,7 @@ retry: best_dts = pkt_desc->dts; } - av_dlog(ctx, "bumping scr, scr:%f, dts:%f\n", + av_log(ctx, AV_LOG_TRACE, "bumping scr, scr:%f, dts:%f\n", scr / 90000.0, best_dts / 90000.0); if (best_dts == INT64_MAX) return 0; @@ -1018,7 +1027,7 @@ retry: } if (timestamp_packet) { - av_dlog(ctx, "dts:%f pts:%f scr:%f stream:%d\n", + av_log(ctx, AV_LOG_TRACE, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts / 90000.0, timestamp_packet->pts / 90000.0, scr / 90000.0, best_i); @@ -1072,7 +1081,7 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) int64_t pts, dts; PacketDesc *pkt_desc; int preload; - const int is_iframe = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + const int is_iframe = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY); preload = av_rescale(s->preload, 90000, AV_TIME_BASE); @@ -1088,7 +1097,7 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) dts += 2 * preload; } - av_dlog(ctx, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", + av_log(ctx, AV_LOG_TRACE, "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) @@ -1139,7 +1148,7 @@ static int mpeg_mux_end(AVFormatContext *ctx) break; } - /* End header according to MPEG1 systems standard. We do not write + /* End header according to MPEG-1 systems standard. We do not write * it as it is usually not needed by decoders and because it * complicates MPEG stream concatenation. */ // avio_wb32(ctx->pb, ISO_11172_END_CODE); diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 57efabd..40672ae 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1,5 +1,5 @@ /* - * MPEG2 transport stream (aka DVB) demuxer + * MPEG-2 transport stream (aka DVB) demuxer * Copyright (c) 2002-2003 Fabrice Bellard * * This file is part of Libav. @@ -28,16 +28,16 @@ #include "libavutil/opt.h" #include "libavcodec/bytestream.h" #include "libavcodec/get_bits.h" +#include "libavcodec/opus.h" #include "avformat.h" #include "mpegts.h" #include "internal.h" #include "avio_internal.h" -#include "seek.h" #include "mpeg.h" #include "isom.h" -/* maximum size in which we look for synchronisation if - * synchronisation is lost */ +/* maximum size in which we look for synchronization if + * synchronization is lost */ #define MAX_RESYNC_SIZE 65536 #define MAX_PES_PAYLOAD 200 * 1024 @@ -127,6 +127,8 @@ struct MpegTSContext { /** to detect seek */ int64_t last_pos; + int resync_size; + /******************************************/ /* private mpegts data */ /* scan context */ @@ -138,7 +140,23 @@ struct MpegTSContext { MpegTSFilter *pids[NB_PID_MAX]; }; +#define MPEGTS_OPTIONS \ + { "resync_size", "Size limit for looking up a new synchronization.", offsetof(MpegTSContext, resync_size), AV_OPT_TYPE_INT, { .i64 = MAX_RESYNC_SIZE}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM } + static const AVOption options[] = { + MPEGTS_OPTIONS, + { NULL }, +}; + +static const AVClass mpegts_class = { + .class_name = "mpegts demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVOption raw_options[] = { + MPEGTS_OPTIONS, { "compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, @@ -152,7 +170,7 @@ static const AVOption options[] = { static const AVClass mpegtsraw_class = { .class_name = "mpegtsraw demuxer", .item_name = av_default_item_name, - .option = options, + .option = raw_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -336,7 +354,7 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, MpegTSFilter *filter; MpegTSSectionFilter *sec; - av_dlog(ts->stream, "Filter: pid=0x%x\n", pid); + av_log(ts->stream, AV_LOG_TRACE, "Filter: pid=0x%x\n", pid); if (pid >= NB_PID_MAX || ts->pids[pid]) return NULL; @@ -410,7 +428,8 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) ts->pids[pid] = NULL; } -static int analyze(const uint8_t *buf, int size, int packet_size, int *index) +static int analyze(const uint8_t *buf, int size, int packet_size, int *index, + int probe) { int stat[TS_MAX_PACKET_SIZE]; int i; @@ -420,7 +439,8 @@ static int analyze(const uint8_t *buf, int size, int packet_size, int *index) memset(stat, 0, packet_size * sizeof(int)); for (x = i = 0; i < size - 3; i++) { - if (buf[i] == 0x47 && !(buf[i + 1] & 0x80) && (buf[i + 3] & 0x30)) { + if (buf[i] == 0x47 && + (!probe || (!(buf[i + 1] & 0x80) && (buf[i + 3] & 0x30)))) { stat[x]++; if (stat[x] > best_score) { best_score = stat[x]; @@ -445,10 +465,10 @@ static int get_packet_size(const uint8_t *buf, int size) if (size < (TS_FEC_PACKET_SIZE * 5 + 1)) return AVERROR_INVALIDDATA; - 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_dlog(NULL, "score: %d, dvhs_score: %d, fec_score: %d \n", + score = analyze(buf, size, TS_PACKET_SIZE, NULL, 0); + dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL, 0); + fec_score = analyze(buf, size, TS_FEC_PACKET_SIZE, NULL, 0); + av_log(NULL, AV_LOG_TRACE, "score: %d, dvhs_score: %d, fec_score: %d \n", score, dvhs_score, fec_score); if (score > fec_score && score > dvhs_score) @@ -548,7 +568,7 @@ static int parse_section_header(SectionHeader *h, return 0; } -typedef struct { +typedef struct StreamType { uint32_t stream_type; enum AVMediaType codec_type; enum AVCodecID codec_id; @@ -563,6 +583,7 @@ static const StreamType ISO_types[] = { { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */ { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, + { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 }, { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, @@ -598,6 +619,7 @@ static const StreamType REGD_types[] = { { MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, + { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS }, { 0 }, }; @@ -617,8 +639,8 @@ static void mpegts_find_stream_type(AVStream *st, { for (; types->stream_type; types++) if (stream_type == types->stream_type) { - st->codec->codec_type = types->codec_type; - st->codec->codec_id = types->codec_id; + st->codecpar->codec_type = types->codec_type; + st->codecpar->codec_id = types->codec_id; return; } } @@ -628,8 +650,8 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, { avpriv_set_pts_info(st, 33, 1, 90000); st->priv_data = pes; - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = AV_CODEC_ID_NONE; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_NONE; st->need_parsing = AVSTREAM_PARSE_FULL; pes->st = st; pes->stream_type = stream_type; @@ -638,11 +660,11 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, "stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s\n", st->index, pes->stream_type, pes->pid, (char *)&prog_reg_desc); - st->codec->codec_tag = pes->stream_type; + st->codecpar->codec_tag = pes->stream_type; mpegts_find_stream_type(st, pes->stream_type, ISO_types); if (prog_reg_desc == AV_RL32("HDMV") && - st->codec->codec_id == AV_CODEC_ID_NONE) { + st->codecpar->codec_id == AV_CODEC_ID_NONE) { mpegts_find_stream_type(st, pes->stream_type, HDMV_types); if (pes->stream_type == 0x83) { // HDMV TrueHD streams also contain an AC3 coded version of the @@ -663,13 +685,13 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, sub_st->id = pes->pid; avpriv_set_pts_info(sub_st, 33, 1, 90000); sub_st->priv_data = sub_pes; - sub_st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - sub_st->codec->codec_id = AV_CODEC_ID_AC3; + sub_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + sub_st->codecpar->codec_id = AV_CODEC_ID_AC3; sub_st->need_parsing = AVSTREAM_PARSE_FULL; sub_pes->sub_st = pes->sub_st = sub_st; } } - if (st->codec->codec_id == AV_CODEC_ID_NONE) + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) mpegts_find_stream_type(st, pes->stream_type, MISC_types); return 0; @@ -689,7 +711,7 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) av_log(pes->stream, AV_LOG_WARNING, "PES packet size mismatch\n"); pes->flags |= AV_PKT_FLAG_CORRUPT; } - memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); // Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76) @@ -814,9 +836,9 @@ static int mpegts_push_data(MpegTSFilter *filter, * decide */ if (pes->header[0] == 0x00 && pes->header[1] == 0x00 && pes->header[2] == 0x01) { - /* it must be an mpeg2 PES stream */ + /* it must be an MPEG-2 PES stream */ code = pes->header[3] | 0x100; - av_dlog(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, + av_log(pes->stream, AV_LOG_TRACE, "pid=%x pes_code=%#x\n", pes->pid, code); if ((pes->st && pes->st->discard == AVDISCARD_ALL && @@ -842,7 +864,7 @@ static int mpegts_push_data(MpegTSFilter *filter, /* allocate pes buffer */ pes->buffer = av_buffer_alloc(pes->total_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!pes->buffer) return AVERROR(ENOMEM); @@ -851,12 +873,12 @@ static int mpegts_push_data(MpegTSFilter *filter, code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */ code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */ pes->state = MPEGTS_PESHEADER; - if (pes->st->codec->codec_id == AV_CODEC_ID_NONE) { - av_dlog(pes->stream, + if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE) { + av_log(pes->stream, AV_LOG_TRACE, "pid=%x stream_type=%x probing\n", pes->pid, pes->stream_type); - pes->st->codec->codec_id = AV_CODEC_ID_PROBE; + pes->st->codecpar->codec_id = AV_CODEC_ID_PROBE; } } else { pes->state = MPEGTS_PAYLOAD; @@ -949,7 +971,7 @@ skip: new_pes_packet(pes, ts->pkt); pes->total_size = MAX_PES_PAYLOAD; pes->buffer = av_buffer_alloc(pes->total_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!pes->buffer) return AVERROR(ENOMEM); ts->stop_parse = 1; @@ -1008,7 +1030,7 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid) } #define MAX_LEVEL 4 -typedef struct { +typedef struct MP4DescrParseContext { AVFormatContext *s; AVIOContext pb; Mp4Descr *descr; @@ -1090,6 +1112,8 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len) static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) { int es_id = 0; + int ret = 0; + if (d->descr_count >= d->max_descr_count) return AVERROR_INVALIDDATA; ff_mp4_parse_es_descr(&d->pb, &es_id); @@ -1097,12 +1121,13 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) d->active_descr->es_id = es_id; update_offsets(&d->pb, &off, &len); - parse_mp4_descr(d, off, len, MP4DecConfigDescrTag); + if ((ret = parse_mp4_descr(d, off, len, MP4DecConfigDescrTag)) < 0) + return ret; update_offsets(&d->pb, &off, &len); if (len > 0) - parse_mp4_descr(d, off, len, MP4SLDescrTag); + ret = parse_mp4_descr(d, off, len, MP4SLDescrTag); d->active_descr = NULL; - return 0; + return ret; } static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, @@ -1146,6 +1171,11 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len) descr->sl.degr_prior_len = lengths >> 12; descr->sl.au_seq_num_len = (lengths >> 7) & 0x1f; descr->sl.packet_seq_num_len = (lengths >> 2) & 0x1f; + if (descr->sl.timestamp_len >= 64 || + descr->sl.ocr_len >= 64 || + descr->sl.au_len >= 32) { + return AVERROR_INVALIDDATA; + } } else { avpriv_report_missing_feature(d->s, "Predefined SLConfigDescriptor"); } @@ -1157,6 +1187,8 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, { int tag; int len1 = ff_mp4_read_descr(d->s, &d->pb, &tag); + int ret = 0; + update_offsets(&d->pb, &off, &len); if (len < 0 || len1 > len || len1 <= 0) { av_log(d->s, AV_LOG_ERROR, @@ -1167,30 +1199,32 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, if (d->level++ >= MAX_LEVEL) { av_log(d->s, AV_LOG_ERROR, "Maximum MP4 descriptor level exceeded\n"); + ret = AVERROR_INVALIDDATA; goto done; } if (target_tag && tag != target_tag) { av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag, target_tag); + ret = AVERROR_INVALIDDATA; goto done; } switch (tag) { case MP4IODescrTag: - parse_MP4IODescrTag(d, off, len1); + ret = parse_MP4IODescrTag(d, off, len1); break; case MP4ODescrTag: - parse_MP4ODescrTag(d, off, len1); + ret = parse_MP4ODescrTag(d, off, len1); break; case MP4ESDescrTag: - parse_MP4ESDescrTag(d, off, len1); + ret = parse_MP4ESDescrTag(d, off, len1); break; case MP4DecConfigDescrTag: - parse_MP4DecConfigDescrTag(d, off, len1); + ret = parse_MP4DecConfigDescrTag(d, off, len1); break; case MP4SLDescrTag: - parse_MP4SLDescrTag(d, off, len1); + ret = parse_MP4SLDescrTag(d, off, len1); break; } @@ -1198,7 +1232,7 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, done: d->level--; avio_seek(&d->pb, off + len1, SEEK_SET); - return 0; + return ret; } static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, @@ -1282,34 +1316,46 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL); ff_mp4_read_dec_config_descr(s, st, &pb); - if (st->codec->codec_id == AV_CODEC_ID_AAC && - st->codec->extradata_size > 0) + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) st->need_parsing = 0; - if (st->codec->codec_id == AV_CODEC_ID_H264 && - st->codec->extradata_size > 0) + if (st->codecpar->codec_id == AV_CODEC_ID_H264 && + st->codecpar->extradata_size > 0) st->need_parsing = 0; - if (st->codec->codec_id <= AV_CODEC_ID_NONE) { - // do nothing - } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_AUDIO) - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - else if (st->codec->codec_id < AV_CODEC_ID_FIRST_SUBTITLE) - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - else if (st->codec->codec_id < AV_CODEC_ID_FIRST_UNKNOWN) - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_type = avcodec_get_type(st->codecpar->codec_id); } } for (i = 0; i < mp4_descr_count; i++) av_free(mp4_descr[i].dec_config_descr); } +static const uint8_t opus_coupled_stream_cnt[9] = { + 1, 0, 1, 1, 2, 2, 2, 3, 3 +}; + +static const uint8_t opus_stream_cnt[9] = { + 1, 1, 1, 2, 2, 3, 4, 4, 5, +}; + +static const uint8_t opus_channel_map[8][8] = { + { 0 }, + { 0,1 }, + { 0,2,1 }, + { 0,1,2,3 }, + { 0,4,1,2,3 }, + { 0,4,1,2,3,5 }, + { 0,4,1,2,3,5,6 }, + { 0,6,1,2,3,4,5,7 }, +}; + int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, const uint8_t **pp, const uint8_t *desc_list_end, Mp4Descr *mp4_descr, int mp4_descr_count, int pid, MpegTSContext *ts) { const uint8_t *desc_end; - int desc_len, desc_tag, desc_es_id; + int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code; char language[252]; int i; @@ -1323,15 +1369,17 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type if (desc_end > desc_list_end) return AVERROR_INVALIDDATA; - av_dlog(fc, "tag: 0x%02x len=%d\n", desc_tag, desc_len); + av_log(fc, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len); - if (st->codec->codec_id == AV_CODEC_ID_NONE && + if (st->codecpar->codec_id == AV_CODEC_ID_NONE && stream_type == STREAM_TYPE_PRIVATE_DATA) mpegts_find_stream_type(st, desc_tag, DESC_types); switch (desc_tag) { case 0x1E: /* SL descriptor */ desc_es_id = get16(pp, desc_end); + if (desc_es_id < 0) + break; if (ts && ts->pids[pid]) ts->pids[pid]->es_id = desc_es_id; for (i = 0; i < mp4_descr_count; i++) @@ -1342,25 +1390,26 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL); ff_mp4_read_dec_config_descr(fc, st, &pb); - if (st->codec->codec_id == AV_CODEC_ID_AAC && - st->codec->extradata_size > 0) + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) st->need_parsing = 0; - if (st->codec->codec_id == AV_CODEC_ID_MPEG4SYSTEMS) + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4SYSTEMS) mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1); } break; case 0x1F: /* FMC descriptor */ - get16(pp, desc_end); + if (get16(pp, desc_end) < 0) + break; if (mp4_descr_count > 0 && - st->codec->codec_id == AV_CODEC_ID_AAC_LATM && + st->codecpar->codec_id == AV_CODEC_ID_AAC_LATM && mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) { AVIOContext pb; ffio_init_context(&pb, mp4_descr->dec_config_descr, mp4_descr->dec_config_descr_len, 0, NULL, NULL, NULL, NULL); ff_mp4_read_dec_config_descr(fc, st, &pb); - if (st->codec->codec_id == AV_CODEC_ID_AAC && - st->codec->extradata_size > 0) + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) st->need_parsing = 0; } break; @@ -1387,15 +1436,15 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; break; } - if (st->codec->extradata) { - if (st->codec->extradata_size == 4 && - memcmp(st->codec->extradata, *pp, 4)) + if (st->codecpar->extradata) { + if (st->codecpar->extradata_size == 4 && + memcmp(st->codecpar->extradata, *pp, 4)) avpriv_request_sample(fc, "DVB sub with multiple IDs"); } else { - st->codec->extradata = av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE); - if (st->codec->extradata) { - st->codec->extradata_size = 4; - memcpy(st->codec->extradata, *pp, 4); + st->codecpar->extradata = av_malloc(4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (st->codecpar->extradata) { + st->codecpar->extradata_size = 4; + memcpy(st->codecpar->extradata, *pp, 4); } } *pp += 4; @@ -1425,10 +1474,41 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } break; case 0x05: /* registration descriptor */ - st->codec->codec_tag = bytestream_get_le32(pp); - av_dlog(fc, "reg_desc=%.4s\n", (char *)&st->codec->codec_tag); - if (st->codec->codec_id == AV_CODEC_ID_NONE) - mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types); + st->codecpar->codec_tag = bytestream_get_le32(pp); + av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag); + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) + mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types); + break; + case 0x7f: /* DVB extension descriptor */ + ext_desc_tag = get8(pp, desc_end); + if (ext_desc_tag < 0) + return AVERROR_INVALIDDATA; + if (st->codecpar->codec_id == AV_CODEC_ID_OPUS && + ext_desc_tag == 0x80) { /* User defined (provisional Opus) */ + if (!st->codecpar->extradata) { + st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + + st->codecpar->extradata_size = sizeof(opus_default_extradata); + memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); + + channel_config_code = get8(pp, desc_end); + if (channel_config_code < 0) + return AVERROR_INVALIDDATA; + if (channel_config_code <= 0x8) { + st->codecpar->extradata[9] = channels = channel_config_code ? channel_config_code : 2; + st->codecpar->extradata[18] = channel_config_code ? (channels > 2) : 255; + st->codecpar->extradata[19] = opus_stream_cnt[channel_config_code]; + st->codecpar->extradata[20] = opus_coupled_stream_cnt[channel_config_code]; + memcpy(&st->codecpar->extradata[21], opus_channel_map[channels - 1], channels); + } else { + avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8"); + } + st->need_parsing = AVSTREAM_PARSE_FULL; + } + } break; default: break; @@ -1453,7 +1533,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; int i; - av_dlog(ts->stream, "PMT: len %i\n", section_len); + av_log(ts->stream, AV_LOG_TRACE, "PMT: len %i\n", section_len); hex_dump_debug(ts->stream, section, section_len); p_end = section + section_len - 4; @@ -1464,7 +1544,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; tssf->last_ver = h->version; - av_dlog(ts->stream, "sid=0x%x sec_num=%d/%d\n", + av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d\n", h->id, h->sec_num, h->last_sec_num); if (h->tid != PMT_TID) @@ -1477,7 +1557,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len pcr_pid &= 0x1fff; add_pid_to_pmt(ts, h->id, pcr_pid); - av_dlog(ts->stream, "pcr_pid=0x%x\n", pcr_pid); + av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid); program_info_length = get16(&p, p_end); if (program_info_length < 0) @@ -1488,7 +1568,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len tag = get8(&p, p_end); len = get8(&p, p_end); - av_dlog(ts->stream, "program tag: 0x%02x len=%d\n", tag, len); + av_log(ts->stream, AV_LOG_TRACE, "program tag: 0x%02x len=%d\n", tag, len); if (len > program_info_length - 2) // something else is broken, exit the program_descriptors_loop @@ -1549,7 +1629,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len } else { st = avformat_new_stream(ts->stream, NULL); st->id = pid; - st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; } } @@ -1580,7 +1660,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len stream_type == 0x83 && pes->sub_st) { ff_program_add_stream_index(ts->stream, h->id, pes->sub_st->index); - pes->sub_st->codec->codec_tag = st->codec->codec_tag; + pes->sub_st->codecpar->codec_tag = st->codecpar->codec_tag; } } p = desc_list_end; @@ -1599,7 +1679,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len const uint8_t *p, *p_end; int sid, pmt_pid; - av_dlog(ts->stream, "PAT:\n"); + av_log(ts->stream, AV_LOG_TRACE, "PAT:\n"); hex_dump_debug(ts->stream, section, section_len); p_end = section + section_len - 4; @@ -1622,7 +1702,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len break; pmt_pid &= 0x1fff; - av_dlog(ts->stream, "sid=0x%x pid=0x%x\n", sid, pmt_pid); + av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x pid=0x%x\n", sid, pmt_pid); if (sid == 0x0000) { /* NIT info */ @@ -1647,7 +1727,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type; char *name, *provider_name; - av_dlog(ts->stream, "SDT:\n"); + av_log(ts->stream, AV_LOG_TRACE, "SDT:\n"); hex_dump_debug(ts->stream, section, section_len); p_end = section + section_len - 4; @@ -1689,7 +1769,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (desc_end > desc_list_end) break; - av_dlog(ts->stream, "tag: 0x%02x len=%d\n", + av_log(ts->stream, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len); switch (desc_tag) { @@ -1825,10 +1905,11 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) * get_packet_size() ?) */ static int mpegts_resync(AVFormatContext *s) { + MpegTSContext *ts = s->priv_data; AVIOContext *pb = s->pb; int c, i; - for (i = 0; i < MAX_RESYNC_SIZE; i++) { + for (i = 0; i < ts->resync_size; i++) { c = avio_r8(pb); if (pb->eof_reached) return AVERROR_EOF; @@ -1880,13 +1961,13 @@ static void finished_reading_packet(AVFormatContext *s, int raw_packet_size) static int handle_packets(MpegTSContext *ts, int nb_packets) { AVFormatContext *s = ts->stream; - uint8_t packet[TS_PACKET_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + uint8_t packet[TS_PACKET_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; const uint8_t *data; int packet_num, ret = 0; if (avio_tell(s->pb) != ts->last_pos) { int i; - av_dlog(ts->stream, "Skipping after seek\n"); + av_log(ts->stream, AV_LOG_TRACE, "Skipping after seek\n"); /* seek detected, flush pes buffer */ for (i = 0; i < NB_PID_MAX; i++) { if (ts->pids[i]) { @@ -1903,7 +1984,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) ts->stop_parse = 0; packet_num = 0; - memset(packet + TS_PACKET_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(packet + TS_PACKET_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); for (;;) { if (ts->stop_parse > 0) break; @@ -1933,12 +2014,12 @@ static int mpegts_probe(AVProbeData *p) return AVERROR_INVALIDDATA; score = analyze(p->buf, TS_PACKET_SIZE * check_count, - TS_PACKET_SIZE, NULL) * CHECK_COUNT / check_count; + TS_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count; dvhs_score = analyze(p->buf, TS_DVHS_PACKET_SIZE * check_count, - TS_DVHS_PACKET_SIZE, NULL) * CHECK_COUNT / check_count; + TS_DVHS_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count; fec_score = analyze(p->buf, TS_FEC_PACKET_SIZE * check_count, - TS_FEC_PACKET_SIZE, NULL) * CHECK_COUNT / check_count; - av_dlog(NULL, "score: %d, dvhs_score: %d, fec_score: %d \n", + TS_FEC_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count; + av_log(NULL, AV_LOG_TRACE, "score: %d, dvhs_score: %d, fec_score: %d \n", score, dvhs_score, fec_score); /* we need a clear definition for the returned score otherwise @@ -2018,7 +2099,7 @@ static int mpegts_read_header(AVFormatContext *s) ts->auto_guess = 1; - av_dlog(ts->stream, "tuning done\n"); + av_log(ts->stream, AV_LOG_TRACE, "tuning done\n"); s->ctx_flags |= AVFMTCTX_NOHEADER; } else { @@ -2035,8 +2116,8 @@ static int mpegts_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 60, 1, 27000000); - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = AV_CODEC_ID_MPEG2TS; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; /* we iterate until we find two PCRs to estimate the bitrate */ pcr_pid = -1; @@ -2067,9 +2148,9 @@ static int mpegts_read_header(AVFormatContext *s) 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->codecpar->bit_rate = s->bit_rate; st->start_time = ts->cur_pcr; - av_dlog(ts->stream, "start=%0.3f pcr=%0.3f incr=%d\n", + av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%d\n", st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } @@ -2093,7 +2174,7 @@ static int mpegts_raw_read_packet(AVFormatContext *s, AVPacket *pkt) ret = read_packet(s, pkt->data, ts->raw_packet_size, &data); pkt->pos = avio_tell(s->pb); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } if (data != pkt->data) @@ -2305,6 +2386,7 @@ AVInputFormat ff_mpegts_demuxer = { .read_seek = read_seek, .read_timestamp = mpegts_get_pcr, .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, + .priv_class = &mpegts_class, }; AVInputFormat ff_mpegtsraw_demuxer = { diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h index 7dbbf8d..9f374c6 100644 --- a/libavformat/mpegts.h +++ b/libavformat/mpegts.h @@ -1,5 +1,5 @@ /* - * MPEG2 transport stream defines + * MPEG-2 transport stream defines * Copyright (c) 2003 Fabrice Bellard * * This file is part of Libav. diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 7621103..a52e684 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1,5 +1,5 @@ /* - * MPEG2 transport stream (aka DVB) muxer + * MPEG-2 transport stream (aka DVB) muxer * Copyright (c) 2003 Fabrice Bellard * * This file is part of Libav. @@ -29,6 +29,7 @@ #include "libavcodec/internal.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "mpegts.h" @@ -36,6 +37,8 @@ /* write DVB SI sections */ +#define DVB_PRIVATE_NETWORK_START 0xff01 + /*********************************************/ /* mpegts section writer */ @@ -47,7 +50,7 @@ typedef struct MpegTSSection { } MpegTSSection; typedef struct MpegTSService { - MpegTSSection pmt; /* MPEG2 pmt table context */ + MpegTSSection pmt; /* MPEG-2 PMT table context */ int sid; /* service ID */ char *name; char *provider_name; @@ -58,8 +61,8 @@ typedef struct MpegTSService { typedef struct MpegTSWrite { const AVClass *av_class; - MpegTSSection pat; /* MPEG2 pat table */ - MpegTSSection sdt; /* MPEG2 sdt table context */ + MpegTSSection pat; /* MPEG-2 PAT table */ + MpegTSSection sdt; /* MPEG-2 SDT table context */ MpegTSService **services; int sdt_packet_count; int sdt_packet_period; @@ -78,12 +81,14 @@ typedef struct MpegTSWrite { int pmt_start_pid; int start_pid; + int m2ts_mode; int reemit_pat_pmt; // backward compatibility int pcr_period; #define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01 #define MPEGTS_FLAG_AAC_LATM 0x02 +#define MPEGTS_FLAG_SYSTEM_B 0x04 int flags; } MpegTSWrite; @@ -249,7 +254,7 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) err = 1; break; } - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: stream_type = STREAM_TYPE_VIDEO_MPEG2; @@ -282,7 +287,9 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) stream_type = STREAM_TYPE_AUDIO_AAC_LATM; break; case AV_CODEC_ID_AC3: - stream_type = STREAM_TYPE_AUDIO_AC3; + stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) + ? STREAM_TYPE_PRIVATE_DATA + : STREAM_TYPE_AUDIO_AC3; break; default: stream_type = STREAM_TYPE_PRIVATE_DATA; @@ -294,8 +301,14 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) q += 2; /* patched after */ /* write optional descriptors here */ - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: + if (st->codecpar->codec_id == AV_CODEC_ID_AC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) { + *q++ = 0x6a; /* ETSI EN 300 468 AC-3 descriptor */ + *q++ = 1; + *q++ = 0x00; + } + if (lang) { char *p; char *next = lang->value; @@ -350,8 +363,8 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) break; } - if (st->codec->extradata_size == 4) { - memcpy(q, st->codec->extradata, 4); + if (st->codecpar->extradata_size == 4) { + memcpy(q, st->codecpar->extradata, 4); q += 4; } else { put16(&q, 1); /* page id */ @@ -465,9 +478,28 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts, int sid, return service; } +static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb) +{ + return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) + + ts->first_pcr; +} + +static void mpegts_prefix_m2ts_header(AVFormatContext *s) +{ + MpegTSWrite *ts = s->priv_data; + if (ts->m2ts_mode) { + int64_t pcr = get_pcr(s->priv_data, s->pb); + uint32_t tp_extra_header = pcr % 0x3fffffff; + tp_extra_header = AV_RB32(&tp_extra_header); + avio_write(s->pb, (unsigned char *) &tp_extra_header, + sizeof(tp_extra_header)); + } +} + static void section_write_packet(MpegTSSection *s, const uint8_t *packet) { AVFormatContext *ctx = s->opaque; + mpegts_prefix_m2ts_header(ctx); avio_write(ctx->pb, packet, TS_PACKET_SIZE); } @@ -577,13 +609,13 @@ static int mpegts_write_header(AVFormatContext *s) ts_st->first_pts_check = 1; ts_st->cc = 15; /* update PCR pid by using the first video stream */ - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && service->pcr_pid == 0x1fff) { service->pcr_pid = ts_st->pid; pcr_st = st; } - if (st->codec->codec_id == AV_CODEC_ID_AAC && - st->codec->extradata_size > 0) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) { AVStream *ast; ts_st->amux = avformat_alloc_context(); if (!ts_st->amux) { @@ -601,9 +633,10 @@ static int mpegts_write_header(AVFormatContext *s) ret = AVERROR(ENOMEM); goto fail; } - ret = avcodec_copy_context(ast->codec, st->codec); + ret = avcodec_parameters_copy(ast->codecpar, st->codecpar); if (ret != 0) goto fail; + ast->time_base = st->time_base; ret = avformat_write_header(ts_st->amux, NULL); if (ret < 0) goto fail; @@ -633,14 +666,15 @@ static int mpegts_write_header(AVFormatContext *s) /* Arbitrary values, PAT/PMT could be written on key frames */ ts->sdt_packet_period = 200; ts->pat_packet_period = 40; - if (pcr_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (!pcr_st->codec->frame_size) { + if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0); + if (!frame_size) { av_log(s, AV_LOG_WARNING, "frame size not set\n"); service->pcr_packet_period = - pcr_st->codec->sample_rate / (10 * 512); + pcr_st->codecpar->sample_rate / (10 * 512); } else { service->pcr_packet_period = - pcr_st->codec->sample_rate / (10 * pcr_st->codec->frame_size); + pcr_st->codecpar->sample_rate / (10 * frame_size); } } else { // max delta PCR 0.1s @@ -664,6 +698,14 @@ static int mpegts_write_header(AVFormatContext *s) service->pcr_packet_period, ts->sdt_packet_period, ts->pat_packet_period); + if (ts->m2ts_mode == -1) { + if (av_match_ext(s->filename, "m2ts")) { + ts->m2ts_mode = 1; + } else { + ts->m2ts_mode = 0; + } + } + avio_flush(s->pb); return 0; @@ -686,7 +728,7 @@ fail: return ret; } -/* send SDT, PAT and PMT tables regulary */ +/* send SDT, PAT and PMT tables regularly */ static void retransmit_si_info(AVFormatContext *s) { MpegTSWrite *ts = s->priv_data; @@ -704,12 +746,6 @@ static void retransmit_si_info(AVFormatContext *s) } } -static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb) -{ - return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) + - ts->first_pcr; -} - static int write_pcr_bits(uint8_t *buf, int64_t pcr) { int64_t pcr_low = pcr % 300, pcr_high = pcr / 300; @@ -736,6 +772,7 @@ static void mpegts_insert_null_packet(AVFormatContext *s) *q++ = 0xff; *q++ = 0x10; memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf)); + mpegts_prefix_m2ts_header(s); avio_write(s->pb, buf, TS_PACKET_SIZE); } @@ -761,6 +798,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) /* stuffing bytes */ memset(q, 0xFF, TS_PACKET_SIZE - (q - buf)); + mpegts_prefix_m2ts_header(s); avio_write(s->pb, buf, TS_PACKET_SIZE); } @@ -891,19 +929,19 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, *q++ = 0x00; *q++ = 0x01; private_code = 0; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (st->codec->codec_id == AV_CODEC_ID_DIRAC) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC) *q++ = 0xfd; else *q++ = 0xe0; - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - (st->codec->codec_id == AV_CODEC_ID_MP2 || - st->codec->codec_id == AV_CODEC_ID_MP3 || - st->codec->codec_id == AV_CODEC_ID_AAC)) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + (st->codecpar->codec_id == AV_CODEC_ID_MP2 || + st->codecpar->codec_id == AV_CODEC_ID_MP3 || + st->codecpar->codec_id == AV_CODEC_ID_AAC)) { *q++ = 0xc0; } else { *q++ = 0xbd; - if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) private_code = 0x20; } header_len = 0; @@ -916,8 +954,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, header_len += 5; flags |= 0x40; } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - st->codec->codec_id == AV_CODEC_ID_DIRAC) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + st->codecpar->codec_id == AV_CODEC_ID_DIRAC) { /* set PES_extension_flag */ pes_extension = 1; flags |= 0x01; @@ -936,7 +974,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, *q++ = len; val = 0x80; /* data alignment indicator is required for subtitle data */ - if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) val |= 0x04; *q++ = val; *q++ = flags; @@ -949,7 +987,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, write_pts(q, 1, dts); q += 5; } - if (pes_extension && st->codec->codec_id == AV_CODEC_ID_DIRAC) { + if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) { flags = 0x01; /* set PES_extension_flag_2 */ *q++ = flags; *q++ = 0x80 | 0x01; /* marker bit + extension length */ @@ -992,6 +1030,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, memcpy(buf + TS_PACKET_SIZE - len, payload, len); payload += len; payload_size -= len; + mpegts_prefix_m2ts_header(s); avio_write(s->pb, buf, TS_PACKET_SIZE); } avio_flush(s->pb); @@ -1032,7 +1071,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) } ts_st->first_pts_check = 0; - if (st->codec->codec_id == AV_CODEC_ID_H264) { + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { const uint8_t *p = buf, *buf_end = p + size; uint32_t state = -1; @@ -1044,7 +1083,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) do { p = avpriv_find_start_code(p, buf_end, &state); - av_dlog(s, "nal %d\n", state & 0x1f); + av_log(s, AV_LOG_TRACE, "nal %d\n", state & 0x1f); } while (p < buf_end && (state & 0x1f) != 9 && (state & 0x1f) != 5 && (state & 0x1f) != 1); @@ -1059,7 +1098,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) buf = data; size = pkt->size + 6; } - } else if (st->codec->codec_id == AV_CODEC_ID_AAC) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size < 2) { av_log(s, AV_LOG_ERROR, "AAC packet too short\n"); return AVERROR_INVALIDDATA; @@ -1084,9 +1123,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) ret = av_write_frame(ts_st->amux, &pkt2); if (ret < 0) { - avio_close_dyn_buf(ts_st->amux->pb, &data); - ts_st->amux->pb = NULL; - av_free(data); + ffio_free_dyn_buf(&ts_st->amux->pb); return ret; } size = avio_close_dyn_buf(ts_st->amux->pb, &data); @@ -1095,7 +1132,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) } } - if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { // for video and subtitle, write a single pes packet mpegts_write_pes(s, st, buf, size, pts, dts, pkt->flags & AV_PKT_FLAG_KEY); @@ -1103,7 +1140,10 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) return 0; } - if (ts_st->payload_size + size > ts->pes_payload_size) { + if (ts_st->payload_size + size > ts->pes_payload_size || + (dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE && + av_compare_ts(dts - ts_st->payload_dts, st->time_base, + s->max_delay, AV_TIME_BASE_Q) >= 0)) { if (ts_st->payload_size) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size, ts_st->payload_pts, ts_st->payload_dts, @@ -1166,7 +1206,8 @@ static int mpegts_write_end(AVFormatContext *s) MpegTSService *service; int i; - mpegts_write_flush(s); + if (s->pb) + mpegts_write_flush(s); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -1195,7 +1236,7 @@ static const AVOption options[] = { { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, { "mpegts_original_network_id", "Set original_network_id field.", offsetof(MpegTSWrite, original_network_id), AV_OPT_TYPE_INT, - { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, { "mpegts_service_id", "Set service_id field.", offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, @@ -1205,6 +1246,9 @@ static const AVOption options[] = { { "mpegts_start_pid", "Set the first pid.", offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM }, + {"mpegts_m2ts_mode", "Enable m2ts mode.", + offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "muxrate", NULL, offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, @@ -1220,6 +1264,9 @@ static const AVOption options[] = { { "latm", "Use LATM packetization for AAC", 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "system_b", "Conform to System B (DVB) instead of System A (ATSC)", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, + AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, // backward compatibility { "resend_headers", "Reemit PAT/PMT before writing the next packet", offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, @@ -1240,14 +1287,14 @@ static const AVClass mpegts_muxer_class = { AVOutputFormat ff_mpegts_muxer = { .name = "mpegts", .long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), - .mime_type = "video/x-mpegts", - .extensions = "ts,m2t", + .mime_type = "video/MP2T", + .extensions = "ts,m2t,m2ts,mts", .priv_data_size = sizeof(MpegTSWrite), .audio_codec = AV_CODEC_ID_MP2, .video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = mpegts_write_header, .write_packet = mpegts_write_packet, .write_trailer = mpegts_write_end, - .flags = AVFMT_ALLOW_FLUSH, + .flags = AVFMT_ALLOW_FLUSH | AVFMT_VARIABLE_FPS, .priv_class = &mpegts_muxer_class, }; diff --git a/libavformat/mpjpeg.c b/libavformat/mpjpeg.c index 9e21099..1a78c32 100644 --- a/libavformat/mpjpeg.c +++ b/libavformat/mpjpeg.c @@ -26,24 +26,20 @@ static int mpjpeg_write_header(AVFormatContext *s) { - uint8_t buf1[256]; - - snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG); - avio_write(s->pb, buf1, strlen(buf1)); + avio_printf(s->pb, "--%s\n", BOUNDARY_TAG); avio_flush(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"); - avio_write(s->pb, buf1, strlen(buf1)); + avio_printf(s->pb, + "Content-length: %i\n" + "Content-type: image/jpeg\n\n", + pkt->size); avio_write(s->pb, pkt->data, pkt->size); - snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG); - avio_write(s->pb, buf1, strlen(buf1)); + avio_printf(s->pb, "\n--%s\n", BOUNDARY_TAG); return 0; } diff --git a/libavformat/mpjpegdec.c b/libavformat/mpjpegdec.c new file mode 100644 index 0000000..886bdfc --- /dev/null +++ b/libavformat/mpjpegdec.c @@ -0,0 +1,232 @@ +/* + * Multipart JPEG format + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" + +#include "avformat.h" +#include "internal.h" + +static int get_line(AVIOContext *pb, char *line, int line_size) +{ + int i = ff_get_line(pb, line, line_size); + + if (i > 1 && line[i - 2] == '\r') + line[i - 2] = '\0'; + + if (pb->error) + return pb->error; + + if (pb->eof_reached) + return AVERROR_EOF; + + return 0; +} + +static int split_tag_value(char **tag, char **value, char *line) +{ + char *p = line; + + while (*p != '\0' && *p != ':') + p++; + if (*p != ':') + return AVERROR_INVALIDDATA; + + *p = '\0'; + *tag = line; + + p++; + + while (av_isspace(*p)) + p++; + + *value = p; + + return 0; +} + +static int check_content_type(char *line) +{ + char *tag, *value; + int ret = split_tag_value(&tag, &value, line); + + if (ret < 0) + return ret; + + if (av_strcasecmp(tag, "Content-type") || + av_strcasecmp(value, "image/jpeg")) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int mpjpeg_read_probe(AVProbeData *p) +{ + AVIOContext *pb; + char line[128] = { 0 }; + int ret = 0; + + if (p->buf_size < 2 || p->buf[0] != '-' || p->buf[1] != '-') + return 0; + + pb = avio_alloc_context(p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL); + if (!pb) + return AVERROR(ENOMEM); + + while (!pb->eof_reached) { + ret = get_line(pb, line, sizeof(line)); + if (ret < 0) + break; + + ret = check_content_type(line); + if (!ret) { + ret = AVPROBE_SCORE_MAX; + break; + } + } + + av_free(pb); + + return ret; +} + +static int mpjpeg_read_header(AVFormatContext *s) +{ + AVStream *st; + char boundary[70 + 2 + 1]; + int64_t pos = avio_tell(s->pb); + int ret; + + + ret = get_line(s->pb, boundary, sizeof(boundary)); + if (ret < 0) + return ret; + + if (strncmp(boundary, "--", 2)) + return AVERROR_INVALIDDATA; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MJPEG; + + avpriv_set_pts_info(st, 60, 1, 25); + + avio_seek(s->pb, pos, SEEK_SET); + + return 0; +} + +static int parse_content_length(const char *value) +{ + long int val = strtol(value, NULL, 10); + + if (val == LONG_MIN || val == LONG_MAX) + return AVERROR(errno); + if (val > INT_MAX) + return AVERROR(ERANGE); + return val; +} + +static int parse_multipart_header(AVFormatContext *s) +{ + char line[128]; + int found_content_type = 0; + int ret, size = -1; + + // get the CRLF as empty string + ret = get_line(s->pb, line, sizeof(line)); + if (ret < 0) + return ret; + + /* some implementation do not provide the required + * initial CRLF (see rfc1341 7.2.1) + */ + if (!line[0]) { + ret = get_line(s->pb, line, sizeof(line)); + if (ret < 0) + return ret; + } + + if (strncmp(line, "--", 2)) + return AVERROR_INVALIDDATA; + + while (!s->pb->eof_reached) { + char *tag, *value; + + ret = get_line(s->pb, line, sizeof(line)); + if (ret < 0) + return ret; + + if (line[0] == '\0') + break; + + ret = split_tag_value(&tag, &value, line); + if (ret < 0) + return ret; + + if (!av_strcasecmp(tag, "Content-type")) { + if (av_strcasecmp(value, "image/jpeg")) { + av_log(s, AV_LOG_ERROR, + "Unexpected %s : %s\n", + tag, value); + return AVERROR_INVALIDDATA; + } else + found_content_type = 1; + } else if (!av_strcasecmp(tag, "Content-Length")) { + size = parse_content_length(value); + if (size < 0) + return size; + } + } + + if (!found_content_type || size < 0) { + return AVERROR_INVALIDDATA; + } + + return size; +} + +static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + int size = parse_multipart_header(s); + + if (size < 0) + return size; + + ret = av_get_packet(s->pb, pkt, size); + if (ret < 0) + return ret; + + return 0; +} + +AVInputFormat ff_mpjpeg_demuxer = { + .name = "mpjpeg", + .long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"), + .mime_type = "multipart/x-mixed-replace", + .extensions = "mjpg", + .read_probe = mpjpeg_read_probe, + .read_header = mpjpeg_read_header, + .read_packet = mpjpeg_read_packet, +}; diff --git a/libavformat/msnwc_tcp.c b/libavformat/msnwc_tcp.c index b6d30fe..6b9589d 100644 --- a/libavformat/msnwc_tcp.c +++ b/libavformat/msnwc_tcp.c @@ -40,25 +40,26 @@ static int msnwc_tcp_probe(AVProbeData *p) { int i; - for(i = 0 ; i + HEADER_SIZE <= p->buf_size ; i++) { + for (i = 0; i + HEADER_SIZE <= p->buf_size; i++) { uint16_t width, height; uint32_t fourcc; - const uint8_t *bytestream = p->buf+i; + const uint8_t *bytestream = p->buf + i; - if(bytestream_get_le16(&bytestream) != HEADER_SIZE) + if (bytestream_get_le16(&bytestream) != HEADER_SIZE) continue; width = bytestream_get_le16(&bytestream); height = bytestream_get_le16(&bytestream); - if(!(width==320 && height==240) && !(width==160 && height==120)) + if (!(width == 320 && + height == 240) && !(width == 160 && height == 120)) continue; bytestream += 2; // keyframe bytestream += 4; // size - fourcc = bytestream_get_le32(&bytestream); - if(fourcc != MKTAG('M', 'L', '2', '0')) + fourcc = bytestream_get_le32(&bytestream); + if (fourcc != MKTAG('M', 'L', '2', '0')) continue; - if(i) { - if(i < 14) /* starts with SwitchBoard connection info */ + if (i) { + if (i < 14) /* starts with SwitchBoard connection info */ return AVPROBE_SCORE_MAX / 2; else /* starts in the middle of stream */ return AVPROBE_SCORE_MAX / 3; @@ -67,33 +68,33 @@ static int msnwc_tcp_probe(AVProbeData *p) } } - return -1; + return 0; } static int msnwc_tcp_read_header(AVFormatContext *ctx) { AVIOContext *pb = ctx->pb; - AVCodecContext *codec; + AVCodecParameters *par; AVStream *st; st = avformat_new_stream(ctx, NULL); - if(!st) + if (!st) return AVERROR(ENOMEM); - codec = st->codec; - codec->codec_type = AVMEDIA_TYPE_VIDEO; - codec->codec_id = AV_CODEC_ID_MIMIC; - codec->codec_tag = MKTAG('M', 'L', '2', '0'); + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_VIDEO; + par->codec_id = AV_CODEC_ID_MIMIC; + par->codec_tag = MKTAG('M', 'L', '2', '0'); avpriv_set_pts_info(st, 32, 1, 1000); /* Some files start with "connected\r\n\r\n". * So skip until we find the first byte of struct size */ - while(avio_r8(pb) != HEADER_SIZE && !pb->eof_reached); + while (avio_r8(pb) != HEADER_SIZE && !pb->eof_reached) ; - if(pb->eof_reached) { + if (pb->eof_reached) { av_log(ctx, AV_LOG_ERROR, "Could not find valid start."); - return -1; + return AVERROR_INVALIDDATA; } return 0; @@ -104,37 +105,41 @@ static int msnwc_tcp_read_packet(AVFormatContext *ctx, AVPacket *pkt) AVIOContext *pb = ctx->pb; uint16_t keyframe; uint32_t size, timestamp; + int ret; avio_skip(pb, 1); /* one byte has been read ahead */ avio_skip(pb, 2); avio_skip(pb, 2); keyframe = avio_rl16(pb); - size = avio_rl32(pb); + size = avio_rl32(pb); avio_skip(pb, 4); avio_skip(pb, 4); timestamp = avio_rl32(pb); - if(!size || av_get_packet(pb, pkt, size) != size) - return -1; + if (!size) + return AVERROR_INVALIDDATA; + + if ((ret = av_get_packet(pb, pkt, size)) < 0) + return ret; avio_skip(pb, 1); /* Read ahead one byte of struct size like read_header */ - pkt->pts = timestamp; - pkt->dts = timestamp; + pkt->pts = timestamp; + pkt->dts = timestamp; pkt->stream_index = 0; /* Some aMsn generated videos (or was it Mercury Messenger?) don't set * this bit and rely on the codec to get keyframe information */ - if(keyframe&1) + if (keyframe & 1) pkt->flags |= AV_PKT_FLAG_KEY; return HEADER_SIZE + size; } AVInputFormat ff_msnwc_tcp_demuxer = { - .name = "msnwctcp", - .long_name = NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"), - .read_probe = msnwc_tcp_probe, - .read_header = msnwc_tcp_read_header, - .read_packet = msnwc_tcp_read_packet, + .name = "msnwctcp", + .long_name = NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"), + .read_probe = msnwc_tcp_probe, + .read_header = msnwc_tcp_read_header, + .read_packet = msnwc_tcp_read_packet, }; diff --git a/libavformat/mtv.c b/libavformat/mtv.c index 7ad7618..fdf13bb 100644 --- a/libavformat/mtv.c +++ b/libavformat/mtv.c @@ -131,13 +131,13 @@ static int mtv_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, mtv->video_fps); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codec->pix_fmt = AV_PIX_FMT_RGB565BE; - st->codec->width = mtv->img_width; - st->codec->height = mtv->img_height; - st->codec->extradata = av_strdup("BottomUp"); - st->codec->extradata_size = 9; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->format = AV_PIX_FMT_RGB565BE; + st->codecpar->width = mtv->img_width; + st->codecpar->height = mtv->img_height; + st->codecpar->extradata = av_strdup("BottomUp"); + st->codecpar->extradata_size = 9; // audio - mp3 @@ -146,10 +146,10 @@ static int mtv_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MP3; - st->codec->bit_rate = mtv->audio_br; - st->need_parsing = AVSTREAM_PARSE_FULL; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MP3; + st->codecpar->bit_rate = mtv->audio_br; + st->need_parsing = AVSTREAM_PARSE_FULL; // Jump over header @@ -166,7 +166,7 @@ static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; int ret; - if((avio_tell(pb) - s->data_offset + mtv->img_segment_size) % mtv->full_segment_size) + if((avio_tell(pb) - s->internal->data_offset + mtv->img_segment_size) % mtv->full_segment_size) { avio_skip(pb, MTV_AUDIO_PADDING_SIZE); diff --git a/libavformat/mux.c b/libavformat/mux.c index d4492d1..37c4541 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -29,7 +29,6 @@ #include "libavutil/pixdesc.h" #include "metadata.h" #include "id3v2.h" -#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" @@ -67,19 +66,19 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st) for (n = 0; s->oformat->codec_tag[n]; n++) { avctag = s->oformat->codec_tag[n]; while (avctag->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codec->codec_tag)) { + if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codecpar->codec_tag)) { id = avctag->id; - if (id == st->codec->codec_id) + if (id == st->codecpar->codec_id) return 1; } - if (avctag->id == st->codec->codec_id) + if (avctag->id == st->codecpar->codec_id) tag = avctag->tag; avctag++; } } if (id != AV_CODEC_ID_NONE) return 0; - if (tag && (st->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL)) + if (tag && (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL)) return 0; return 1; } @@ -90,8 +89,9 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) int ret = 0, i; AVStream *st; AVDictionary *tmp = NULL; - AVCodecContext *codec = NULL; + AVCodecParameters *par = NULL; AVOutputFormat *of = s->oformat; + const AVCodecDescriptor *desc; if (options) av_dict_copy(&tmp, *options, 0); @@ -99,9 +99,11 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; -#if FF_API_LAVF_BITEXACT - if (s->nb_streams && s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT) +#if FF_API_LAVF_BITEXACT && FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (s->nb_streams && s->streams[0]->codec->flags & AV_CODEC_FLAG_BITEXACT) s->flags |= AVFMT_FLAG_BITEXACT; +FF_ENABLE_DEPRECATION_WARNINGS #endif // some sanity checks @@ -112,41 +114,55 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } for (i = 0; i < s->nb_streams; i++) { - st = s->streams[i]; - codec = st->codec; + st = s->streams[i]; + par = st->codecpar; -#if FF_API_LAVF_CODEC_TB +#if FF_API_LAVF_CODEC_TB && FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS - if (!st->time_base.num && codec->time_base.num) { + if (!st->time_base.num && st->codec->time_base.num) { av_log(s, AV_LOG_WARNING, "Using AVStream.codec.time_base as a " "timebase hint to the muxer is deprecated. Set " "AVStream.time_base instead.\n"); - avpriv_set_pts_info(st, 64, codec->time_base.num, codec->time_base.den); + avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && + st->codec->codec_type != AVMEDIA_TYPE_UNKNOWN) { + av_log(s, AV_LOG_WARNING, "Using AVStream.codec to pass codec " + "parameters to muxers is deprecated, use AVStream.codecpar " + "instead.\n"); + ret = avcodec_parameters_from_context(st->codecpar, st->codec); + if (ret < 0) + goto fail; } FF_ENABLE_DEPRECATION_WARNINGS #endif if (!st->time_base.num) { /* fall back on the default timebase values */ - if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->sample_rate) - avpriv_set_pts_info(st, 64, 1, codec->sample_rate); + if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate) + avpriv_set_pts_info(st, 64, 1, par->sample_rate); else avpriv_set_pts_info(st, 33, 1, 90000); } - switch (codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: - if (codec->sample_rate <= 0) { + if (par->sample_rate <= 0) { av_log(s, AV_LOG_ERROR, "sample rate not set\n"); ret = AVERROR(EINVAL); goto fail; } - if (!codec->block_align) - codec->block_align = codec->channels * - av_get_bits_per_sample(codec->codec_id) >> 3; + if (!par->block_align) + par->block_align = par->channels * + av_get_bits_per_sample(par->codec_id) >> 3; break; case AVMEDIA_TYPE_VIDEO: - if ((codec->width <= 0 || codec->height <= 0) && + if ((par->width <= 0 || par->height <= 0) && !(of->flags & AVFMT_NODIMENSIONS)) { av_log(s, AV_LOG_ERROR, "dimensions not set\n"); ret = AVERROR(EINVAL); @@ -154,16 +170,16 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (av_cmp_q(st->sample_aspect_ratio, - codec->sample_aspect_ratio)) { + par->sample_aspect_ratio)) { if (st->sample_aspect_ratio.num != 0 && st->sample_aspect_ratio.den != 0 && - codec->sample_aspect_ratio.den != 0 && - codec->sample_aspect_ratio.den != 0) { + par->sample_aspect_ratio.den != 0 && + par->sample_aspect_ratio.den != 0) { av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer " "(%d/%d) and encoder layer (%d/%d)\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, - codec->sample_aspect_ratio.num, - codec->sample_aspect_ratio.den); + par->sample_aspect_ratio.num, + par->sample_aspect_ratio.den); ret = AVERROR(EINVAL); goto fail; } @@ -171,36 +187,34 @@ FF_ENABLE_DEPRECATION_WARNINGS break; } + desc = avcodec_descriptor_get(par->codec_id); + if (desc && desc->props & AV_CODEC_PROP_REORDER) + st->internal->reorder = 1; + if (of->codec_tag) { - if (codec->codec_tag && - codec->codec_id == AV_CODEC_ID_RAWVIDEO && - !av_codec_get_tag(of->codec_tag, codec->codec_id) && + if (par->codec_tag && + par->codec_id == AV_CODEC_ID_RAWVIDEO && + !av_codec_get_tag(of->codec_tag, par->codec_id) && !validate_codec_tag(s, st)) { // the current rawvideo encoding system ends up setting // the wrong codec_tag for avi, we override it here - codec->codec_tag = 0; + par->codec_tag = 0; } - if (codec->codec_tag) { + if (par->codec_tag) { if (!validate_codec_tag(s, st)) { char tagbuf[32]; - av_get_codec_tag_string(tagbuf, sizeof(tagbuf), codec->codec_tag); + av_get_codec_tag_string(tagbuf, sizeof(tagbuf), par->codec_tag); av_log(s, AV_LOG_ERROR, "Tag %s/0x%08x incompatible with output codec id '%d'\n", - tagbuf, codec->codec_tag, codec->codec_id); + tagbuf, par->codec_tag, par->codec_id); ret = AVERROR_INVALIDDATA; goto fail; } } else - codec->codec_tag = av_codec_get_tag(of->codec_tag, codec->codec_id); + par->codec_tag = av_codec_get_tag(of->codec_tag, par->codec_id); } - if (of->flags & AVFMT_GLOBALHEADER && - !(codec->flags & CODEC_FLAG_GLOBAL_HEADER)) - av_log(s, AV_LOG_WARNING, - "Codec for stream %d does not use global headers " - "but container format requires global headers\n", i); - - if (codec->codec_type != AVMEDIA_TYPE_ATTACHMENT) + if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) s->internal->nb_interleaved_streams++; } @@ -242,22 +256,45 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if (ret = init_muxer(s, options)) return ret; + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); if (s->oformat->write_header) { ret = s->oformat->write_header(s); if (ret < 0) return ret; } + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN); + + if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) { + if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { + s->avoid_negative_ts = 0; + } else + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; + } return 0; } +#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS //FIXME merge with compute_pkt_fields static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) { int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames); int num, den, i; - av_dlog(s, "compute_pkt_fields2: pts:%" PRId64 " dts:%" PRId64 " cur_dts:%" PRId64 " b:%d size:%d st:%d\n", + if (!s->internal->missing_ts_warning && + !(s->oformat->flags & AVFMT_NOTIMESTAMPS) && + (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE)) { + av_log(s, AV_LOG_WARNING, + "Timestamps are unset in a packet for stream %d. " + "This is deprecated and will stop working in the future. " + "Fix your code to set the timestamps properly\n", st->index); + s->internal->missing_ts_warning = 1; + } + + av_log(s, AV_LOG_TRACE, "compute_pkt_fields2: 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) @@ -265,7 +302,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) /* duration field */ if (pkt->duration == 0) { - ff_compute_frame_duration(&num, &den, st, NULL, pkt); + ff_compute_frame_duration(s, &num, &den, st, NULL, pkt); if (den && num) { pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num); } @@ -294,16 +331,21 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) return AVERROR(EINVAL); } if (pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts) { - av_log(s, AV_LOG_ERROR, "pts < dts in stream %d\n", st->index); + av_log(s, AV_LOG_ERROR, + "pts %" PRId64 " < dts %" PRId64 " in stream %d\n", + pkt->pts, pkt->dts, + st->index); return AVERROR(EINVAL); } - av_dlog(s, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", + av_log(s, AV_LOG_TRACE, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts); st->cur_dts = pkt->dts; return 0; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* * FIXME: this function should NEVER get undefined pts/dts beside when the @@ -315,26 +357,41 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) static int write_packet(AVFormatContext *s, AVPacket *pkt) { int ret; - if (!(s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS))) { + // If the timestamp offsetting below is adjusted, adjust + // ff_interleaved_peek similarly. + if (s->avoid_negative_ts > 0) { AVRational time_base = s->streams[pkt->stream_index]->time_base; int64_t offset = 0; - if (!s->offset && pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) { - s->offset = -pkt->dts; - s->offset_timebase = time_base; + if (s->internal->offset == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && + (pkt->dts < 0 || s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)) { + s->internal->offset = -pkt->dts; + s->internal->offset_timebase = time_base; } - if (s->offset) - offset = av_rescale_q(s->offset, s->offset_timebase, time_base); + if (s->internal->offset != AV_NOPTS_VALUE) + offset = av_rescale_q(s->internal->offset, s->internal->offset_timebase, time_base); if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += offset; if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; + + if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) { + av_log(s, AV_LOG_WARNING, + "Packets poorly interleaved, failed to avoid negative " + "timestamp %"PRId64" in stream %d.\n" + "Try -max_interleave_delta 0 as a possible workaround.\n", + pkt->dts, pkt->stream_index); + } } ret = s->oformat->write_packet(s, pkt); - if (s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) - avio_flush(s->pb); + if (s->pb && ret >= 0) { + if (s->flags & AVFMT_FLAG_FLUSH_PACKETS) + avio_flush(s->pb); + if (s->pb->error < 0) + ret = s->pb->error; + } return ret; } @@ -350,7 +407,7 @@ static int check_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } - if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { + if (s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) { av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n"); return AVERROR(EINVAL); } @@ -358,7 +415,7 @@ static int check_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -int av_write_frame(AVFormatContext *s, AVPacket *pkt) +static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) { int ret; @@ -366,16 +423,70 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; +#if !FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX + /* sanitize the timestamps */ + if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { + AVStream *st = s->streams[pkt->stream_index]; + + /* when there is no reordering (so dts is equal to pts), but + * only one of them is set, set the other as well */ + if (!st->internal->reorder) { + if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) + pkt->pts = pkt->dts; + if (pkt->dts == AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) + pkt->dts = pkt->pts; + } + + /* check that the timestamps are set */ + if (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE) { + av_log(s, AV_LOG_ERROR, + "Timestamps are unset in a packet for stream %d\n", st->index); + return AVERROR(EINVAL); + } + + /* check that the dts are increasing (or at least non-decreasing, + * if the format allows it */ + if (st->cur_dts != AV_NOPTS_VALUE && + ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->cur_dts >= pkt->dts) || + st->cur_dts > pkt->dts)) { + av_log(s, AV_LOG_ERROR, + "Application provided invalid, non monotonically increasing " + "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n", + st->index, st->cur_dts, pkt->dts); + return AVERROR(EINVAL); + } + + if (pkt->pts < pkt->dts) { + av_log(s, AV_LOG_ERROR, "pts %" PRId64 " < dts %" PRId64 " in stream %d\n", + pkt->pts, pkt->dts, st->index); + return AVERROR(EINVAL); + } + } +#endif + + return 0; +} + +int av_write_frame(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + + ret = prepare_input_packet(s, pkt); + if (ret < 0) + return ret; + if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) return s->oformat->write_packet(s, pkt); return 1; } +#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt); if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; +#endif ret = write_packet(s, pkt); @@ -393,17 +504,8 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, this_pktl = av_mallocz(sizeof(AVPacketList)); if (!this_pktl) return AVERROR(ENOMEM); - this_pktl->pkt = *pkt; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = NULL; // do not free original but only the copy -FF_ENABLE_DEPRECATION_WARNINGS -#endif - pkt->buf = NULL; - pkt->side_data = NULL; - pkt->side_data_elems = 0; - // Duplicate the packet if it uses non-allocated memory - if ((ret = av_dup_packet(&this_pktl->pkt)) < 0) { + + if ((ret = av_packet_ref(&this_pktl->pkt, pkt)) < 0) { av_free(this_pktl); return ret; } @@ -411,20 +513,20 @@ FF_ENABLE_DEPRECATION_WARNINGS if (s->streams[pkt->stream_index]->last_in_packet_buffer) { next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next); } else - next_point = &s->packet_buffer; + next_point = &s->internal->packet_buffer; if (*next_point) { - if (compare(s, &s->packet_buffer_end->pkt, pkt)) { + if (compare(s, &s->internal->packet_buffer_end->pkt, pkt)) { while (!compare(s, &(*next_point)->pkt, pkt)) next_point = &(*next_point)->next; goto next_non_null; } else { - next_point = &(s->packet_buffer_end->next); + next_point = &(s->internal->packet_buffer_end->next); } } assert(!*next_point); - s->packet_buffer_end = this_pktl; + s->internal->packet_buffer_end = this_pktl; next_non_null: this_pktl->next = *next_point; @@ -432,6 +534,8 @@ next_non_null: s->streams[pkt->stream_index]->last_in_packet_buffer = *next_point = this_pktl; + av_packet_unref(pkt); + return 0; } @@ -460,8 +564,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, return ret; } - if (s->max_interleave_delta > 0 && s->packet_buffer && !flush) { - AVPacket *top_pkt = &s->packet_buffer->pkt; + if (s->max_interleave_delta > 0 && s->internal->packet_buffer && !flush) { + AVPacket *top_pkt = &s->internal->packet_buffer->pkt; int64_t delta_dts = INT64_MIN; int64_t top_dts = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -495,12 +599,12 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, if (stream_count && (s->internal->nb_interleaved_streams == stream_count || flush)) { - pktl = s->packet_buffer; + pktl = s->internal->packet_buffer; *out = pktl->pkt; - s->packet_buffer = pktl->next; - if (!s->packet_buffer) - s->packet_buffer_end = NULL; + s->internal->packet_buffer = pktl->next; + if (!s->internal->packet_buffer) + s->internal->packet_buffer_end = NULL; if (s->streams[out->stream_index]->last_in_packet_buffer == pktl) s->streams[out->stream_index]->last_in_packet_buffer = NULL; @@ -512,6 +616,29 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, } } +int ff_interleaved_peek(AVFormatContext *s, int stream, + AVPacket *pkt, int add_offset) +{ + AVPacketList *pktl = s->internal->packet_buffer; + while (pktl) { + if (pktl->pkt.stream_index == stream) { + *pkt = pktl->pkt; + if (add_offset && s->internal->offset != AV_NOPTS_VALUE) { + int64_t offset = av_rescale_q(s->internal->offset, + s->internal->offset_timebase, + s->streams[stream]->time_base); + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + } + return 0; + } + pktl = pktl->next; + } + return AVERROR(ENOENT); +} + /** * Interleave an AVPacket correctly so it can be muxed. * @param out the interleaved packet will be output here @@ -526,7 +653,7 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in if (s->oformat->interleave_packet) { int ret = s->oformat->interleave_packet(s, out, in, flush); if (in) - av_free_packet(in); + av_packet_unref(in); return ret; } else return ff_interleave_packet_per_dts(s, out, in, flush); @@ -536,24 +663,26 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret, flush = 0; - ret = check_packet(s, pkt); + ret = prepare_input_packet(s, pkt); if (ret < 0) goto fail; if (pkt) { +#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX AVStream *st = s->streams[pkt->stream_index]; - av_dlog(s, "av_interleaved_write_frame size:%d dts:%" PRId64 " pts:%" PRId64 "\n", + av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame size:%d dts:%" PRId64 " pts:%" PRId64 "\n", pkt->size, pkt->dts, pkt->pts); if ((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) goto fail; +#endif if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { ret = AVERROR(EINVAL); goto fail; } } else { - av_dlog(s, "av_interleaved_write_frame FLUSH\n"); + av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); flush = 1; } @@ -572,7 +701,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret >= 0) s->streams[opkt.stream_index]->nb_frames++; - av_free_packet(&opkt); + av_packet_unref(&opkt); if (ret < 0) return ret; @@ -598,16 +727,18 @@ int av_write_trailer(AVFormatContext *s) if (ret >= 0) s->streams[pkt.stream_index]->nb_frames++; - av_free_packet(&pkt); + av_packet_unref(&pkt); if (ret < 0) goto fail; } + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); if (s->oformat->write_trailer) ret = s->oformat->write_trailer(s); - if (!(s->oformat->flags & AVFMT_NOFILE)) + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_flush(s->pb); fail: diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index e21ec06..f13359c 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -101,9 +101,9 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels); return AVERROR_INVALIDDATA; } - st->codec->channels = channels; - st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; + st->codecpar->channels = channels; + st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO + : AV_CH_LAYOUT_STEREO; return 0; } @@ -151,10 +151,10 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st, } else if (!strcmp(name, "NUM_CHANNELS")) { return set_channels(avctx, st, var_read_int(pb, size)); } else if (!strcmp(name, "SAMPLE_RATE")) { - st->codec->sample_rate = var_read_int(pb, size); - avpriv_set_pts_info(st, 33, 1, st->codec->sample_rate); + st->codecpar->sample_rate = var_read_int(pb, size); + avpriv_set_pts_info(st, 33, 1, st->codecpar->sample_rate); } else if (!strcmp(name, "SAMPLE_WIDTH")) { - st->codec->bits_per_coded_sample = var_read_int(pb, size) * 8; + st->codecpar->bits_per_coded_sample = var_read_int(pb, size) * 8; } else return AVERROR_INVALIDDATA; @@ -176,16 +176,16 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st, if (!str) return AVERROR_INVALIDDATA; if (!strcmp(str, "1")) { - st->codec->codec_id = AV_CODEC_ID_MVC1; + st->codecpar->codec_id = AV_CODEC_ID_MVC1; } else if (!strcmp(str, "2")) { - st->codec->pix_fmt = AV_PIX_FMT_ABGR; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->format = AV_PIX_FMT_ABGR; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; } else if (!strcmp(str, "3")) { - st->codec->codec_id = AV_CODEC_ID_SGIRLE; + st->codecpar->codec_id = AV_CODEC_ID_SGIRLE; } else if (!strcmp(str, "10")) { - st->codec->codec_id = AV_CODEC_ID_MJPEG; + st->codecpar->codec_id = AV_CODEC_ID_MJPEG; } else if (!strcmp(str, "MVC2")) { - st->codec->codec_id = AV_CODEC_ID_MVC2; + st->codecpar->codec_id = AV_CODEC_ID_MVC2; } else { avpriv_request_sample(avctx, "Video compression %s", str); } @@ -195,18 +195,18 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st, avpriv_set_pts_info(st, 64, fps.den, fps.num); st->avg_frame_rate = fps; } else if (!strcmp(name, "HEIGHT")) { - st->codec->height = var_read_int(pb, size); + st->codecpar->height = var_read_int(pb, size); } else if (!strcmp(name, "PIXEL_ASPECT")) { st->sample_aspect_ratio = var_read_float(pb, size); av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, INT_MAX); } else if (!strcmp(name, "WIDTH")) { - st->codec->width = var_read_int(pb, size); + st->codecpar->width = var_read_int(pb, size); } else if (!strcmp(name, "ORIENTATION")) { if (var_read_int(pb, size) == 1101) { - st->codec->extradata = av_strdup("BottomUp"); - st->codec->extradata_size = 9; + st->codecpar->extradata = av_strdup("BottomUp"); + st->codecpar->extradata_size = 9; } } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) { var_read_metadata(avctx, name, size); @@ -249,8 +249,8 @@ static void read_index(AVIOContext *pb, AVStream *st) uint32_t size = avio_rb32(pb); avio_skip(pb, 8); av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME); - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - timestamp += size / (st->codec->channels * 2); + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + timestamp += size / (st->codecpar->channels * 2); } else { timestamp++; } @@ -282,37 +282,37 @@ static int mv_read_header(AVFormatContext *avctx) if (!vst) return AVERROR(ENOMEM); avpriv_set_pts_info(vst, 64, 1, 15); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->avg_frame_rate = av_inv_q(vst->time_base); vst->nb_frames = avio_rb32(pb); v = avio_rb32(pb); switch (v) { case 1: - vst->codec->codec_id = AV_CODEC_ID_MVC1; + vst->codecpar->codec_id = AV_CODEC_ID_MVC1; break; case 2: - vst->codec->pix_fmt = AV_PIX_FMT_ARGB; - vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + vst->codecpar->format = AV_PIX_FMT_ARGB; + vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; break; default: avpriv_request_sample(avctx, "Video compression %i", v); break; } - vst->codec->codec_tag = 0; - vst->codec->width = avio_rb32(pb); - vst->codec->height = avio_rb32(pb); + vst->codecpar->codec_tag = 0; + vst->codecpar->width = avio_rb32(pb); + vst->codecpar->height = avio_rb32(pb); avio_skip(pb, 12); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->nb_frames = vst->nb_frames; - ast->codec->sample_rate = avio_rb32(pb); - avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate); + ast->codecpar->sample_rate = avio_rb32(pb); + avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); if (set_channels(avctx, ast, avio_rb32(pb)) < 0) return AVERROR_INVALIDDATA; v = avio_rb32(pb); if (v == AUDIO_FORMAT_SIGNED) { - ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; } else { avpriv_request_sample(avctx, "Audio compression (format %i)", v); } @@ -330,7 +330,7 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 8); av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codec->channels * 2); + timestamp += asize / (ast->codecpar->channels * 2); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); @@ -344,20 +344,20 @@ static int mv_read_header(AVFormatContext *avctx) ast = avformat_new_stream(avctx, NULL); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; read_table(avctx, ast, parse_audio_var); if (mv->acompression == 100 && mv->aformat == AUDIO_FORMAT_SIGNED && - ast->codec->bits_per_coded_sample == 16) { - ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE; + ast->codecpar->bits_per_coded_sample == 16) { + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; } else { avpriv_request_sample(avctx, "Audio compression %i (format %i, sr %i)", mv->acompression, mv->aformat, - ast->codec->bits_per_coded_sample); - ast->codec->codec_id = AV_CODEC_ID_NONE; + ast->codecpar->bits_per_coded_sample); + ast->codecpar->codec_id = AV_CODEC_ID_NONE; } - if (ast->codec->channels <= 0) { + if (ast->codecpar->channels <= 0) { av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n"); return AVERROR_INVALIDDATA; } @@ -370,7 +370,7 @@ static int mv_read_header(AVFormatContext *avctx) vst = avformat_new_stream(avctx, NULL); if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; read_table(avctx, vst, parse_video_var); } diff --git a/libavformat/mvi.c b/libavformat/mvi.c index 03a1f40..1874074 100644 --- a/libavformat/mvi.c +++ b/libavformat/mvi.c @@ -54,18 +54,18 @@ static int read_header(AVFormatContext *s) if (!vst) return AVERROR(ENOMEM); - vst->codec->extradata_size = 2; - vst->codec->extradata = av_mallocz(2 + FF_INPUT_BUFFER_PADDING_SIZE); + vst->codecpar->extradata_size = 2; + vst->codecpar->extradata = av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE); version = avio_r8(pb); - vst->codec->extradata[0] = avio_r8(pb); - vst->codec->extradata[1] = avio_r8(pb); + vst->codecpar->extradata[0] = avio_r8(pb); + vst->codecpar->extradata[1] = avio_r8(pb); frames_count = avio_rl32(pb); msecs_per_frame = avio_rl32(pb); - vst->codec->width = avio_rl16(pb); - vst->codec->height = avio_rl16(pb); + vst->codecpar->width = avio_rl16(pb); + vst->codecpar->height = avio_rl16(pb); avio_r8(pb); - ast->codec->sample_rate = avio_rl16(pb); + ast->codecpar->sample_rate = avio_rl16(pb); mvi->audio_data_size = avio_rl32(pb); avio_r8(pb); player_version = avio_rl32(pb); @@ -80,20 +80,20 @@ static int read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; - ast->codec->bits_per_coded_sample = 8; - ast->codec->bit_rate = ast->codec->sample_rate * 8; + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->bits_per_coded_sample = 8; + ast->codecpar->bit_rate = ast->codecpar->sample_rate * 8; avpriv_set_pts_info(vst, 64, msecs_per_frame, 1000000); vst->avg_frame_rate = av_inv_q(vst->time_base); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_MOTIONPIXELS; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_MOTIONPIXELS; - mvi->get_int = (vst->codec->width * vst->codec->height < (1 << 16)) ? avio_rl16 : avio_rl24; + mvi->get_int = (vst->codecpar->width * vst->codecpar->height < (1 << 16)) ? avio_rl16 : avio_rl24; mvi->audio_frame_size = ((uint64_t)mvi->audio_data_size << MVI_FRAC_BITS) / frames_count; if (mvi->audio_frame_size <= 1 << MVI_FRAC_BITS - 1) { @@ -103,7 +103,7 @@ static int read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - mvi->audio_size_counter = (ast->codec->sample_rate * 830 / mvi->audio_frame_size - 1) * mvi->audio_frame_size; + mvi->audio_size_counter = (ast->codecpar->sample_rate * 830 / mvi->audio_frame_size - 1) * mvi->audio_frame_size; mvi->audio_size_left = mvi->audio_data_size; return 0; diff --git a/libavformat/mxf.c b/libavformat/mxf.c index 19ee35f..0b7e9823 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -39,17 +39,17 @@ const MXFCodecUL ff_mxf_codec_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* 422P@HL I-Frame */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, 14, AV_CODEC_ID_MPEG4 }, /* XDCAM proxy_pal030926.mxf */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13, AV_CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, 15, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed 422 8-bit */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG 2000 code stream */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_RAWVIDEO }, /* uncompressed */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, 15, AV_CODEC_ID_RAWVIDEO }, /* uncompressed 422 8-bit */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x71,0x00,0x00,0x00 }, 13, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x03,0x02,0x00,0x00 }, 14, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC SPS/PPS in-band */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, 15, AV_CODEC_ID_V210 }, /* V210 */ /* SoundEssenceCompression */ - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG2 AAC ADTS (legacy) */ - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* uncompressed */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15, AV_CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */ diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 9aedd47..449af95 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -72,7 +72,7 @@ typedef enum { OPSonyOpt, /* FATE sample, violates the spec in places */ } MXFOP; -typedef struct { +typedef struct MXFPartition { int closed; int complete; MXFPartitionType type; @@ -88,13 +88,13 @@ typedef struct { int pack_length; } MXFPartition; -typedef struct { +typedef struct MXFCryptoContext { UID uid; enum MXFMetadataSetType type; UID source_container_ul; } MXFCryptoContext; -typedef struct { +typedef struct MXFStructuralComponent { UID uid; enum MXFMetadataSetType type; UID source_package_uid; @@ -104,7 +104,7 @@ typedef struct { int source_track_id; } MXFStructuralComponent; -typedef struct { +typedef struct MXFSequence { UID uid; enum MXFMetadataSetType type; UID data_definition_ul; @@ -114,7 +114,7 @@ typedef struct { uint8_t origin; } MXFSequence; -typedef struct { +typedef struct MXFTrack { UID uid; enum MXFMetadataSetType type; MXFSequence *sequence; /* mandatory, and only one */ @@ -127,7 +127,7 @@ typedef struct { int64_t original_duration; /* st->duration in SampleRate/EditRate units */ } MXFTrack; -typedef struct { +typedef struct MXFDescriptor { UID uid; enum MXFMetadataSetType type; UID essence_container_ul; @@ -153,7 +153,7 @@ typedef struct { enum AVPixelFormat pix_fmt; } MXFDescriptor; -typedef struct { +typedef struct MXFIndexTableSegment { UID uid; enum MXFMetadataSetType type; int edit_unit_byte_count; @@ -168,7 +168,7 @@ typedef struct { int nb_index_entries; } MXFIndexTableSegment; -typedef struct { +typedef struct MXFPackage { UID uid; enum MXFMetadataSetType type; UID package_uid; @@ -178,13 +178,13 @@ typedef struct { UID descriptor_ref; } MXFPackage; -typedef struct { +typedef struct MXFMetadataSet { UID uid; enum MXFMetadataSetType type; } MXFMetadataSet; /* decoded index table */ -typedef struct { +typedef struct MXFIndexTable { int index_sid; int body_sid; int nb_ptses; /* number of PTSes or total duration of index */ @@ -195,7 +195,7 @@ typedef struct { AVIndexEntry *fake_index; /* used for calling ff_index_search_timestamp() */ } MXFIndexTable; -typedef struct { +typedef struct MXFContext { MXFPartition *partitions; unsigned partitions_count; MXFOP op; @@ -230,7 +230,7 @@ enum MXFWrappingScheme { /* NOTE: klv_offset is not set (-1) for local keys */ typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset); -typedef struct { +typedef struct MXFMetadataReadTableEntry { const UID key; MXFMetadataReadFunc *read; int ctx_size; @@ -320,15 +320,15 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, data_ptr = pkt->data; end_ptr = pkt->data + length; buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */ - for (; end_ptr - buf_ptr >= st->codec->channels * 4; ) { - for (i = 0; i < st->codec->channels; i++) { + for (; end_ptr - buf_ptr >= st->codecpar->channels * 4; ) { + for (i = 0; i < st->codecpar->channels; i++) { uint32_t sample = bytestream_get_le32(&buf_ptr); - if (st->codec->bits_per_coded_sample == 24) + if (st->codecpar->bits_per_coded_sample == 24) bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff); else bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff); } - buf_ptr += 32 - st->codec->channels*4; // always 8 channels stored SMPTE 331M + buf_ptr += 32 - st->codecpar->channels*4; // always 8 channels stored SMPTE 331M } av_shrink_packet(pkt, data_ptr - pkt->data); return 0; @@ -499,7 +499,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size partition->previous_partition); } - /* some files don'thave FooterPartition set in every partition */ + /* some files don't have FooterPartition set in every partition */ if (footer_partition) { if (mxf->footer_partition && mxf->footer_partition != footer_partition) { av_log(mxf->fc, AV_LOG_ERROR, @@ -510,7 +510,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size } } - av_dlog(mxf->fc, + av_log(mxf->fc, AV_LOG_TRACE, "PartitionPack: ThisPartition = 0x%"PRIX64 ", PreviousPartition = 0x%"PRIX64", " "FooterPartition = 0x%"PRIX64", IndexSID = %i, BodySID = %i\n", @@ -775,32 +775,32 @@ static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int switch(tag) { case 0x3F05: segment->edit_unit_byte_count = avio_rb32(pb); - av_dlog(NULL, "EditUnitByteCount %d\n", segment->edit_unit_byte_count); + av_log(NULL, AV_LOG_TRACE, "EditUnitByteCount %d\n", segment->edit_unit_byte_count); break; case 0x3F06: segment->index_sid = avio_rb32(pb); - av_dlog(NULL, "IndexSID %d\n", segment->index_sid); + av_log(NULL, AV_LOG_TRACE, "IndexSID %d\n", segment->index_sid); break; case 0x3F07: segment->body_sid = avio_rb32(pb); - av_dlog(NULL, "BodySID %d\n", segment->body_sid); + av_log(NULL, AV_LOG_TRACE, "BodySID %d\n", segment->body_sid); break; case 0x3F0A: - av_dlog(NULL, "IndexEntryArray found\n"); + av_log(NULL, AV_LOG_TRACE, "IndexEntryArray found\n"); return mxf_read_index_entry_array(pb, segment); case 0x3F0B: segment->index_edit_rate.num = avio_rb32(pb); segment->index_edit_rate.den = avio_rb32(pb); - av_dlog(NULL, "IndexEditRate %d/%d\n", segment->index_edit_rate.num, + av_log(NULL, AV_LOG_TRACE, "IndexEditRate %d/%d\n", segment->index_edit_rate.num, segment->index_edit_rate.den); break; case 0x3F0C: segment->index_start_position = avio_rb64(pb); - av_dlog(NULL, "IndexStartPosition %"PRId64"\n", segment->index_start_position); + av_log(NULL, AV_LOG_TRACE, "IndexStartPosition %"PRId64"\n", segment->index_start_position); break; case 0x3F0D: segment->index_duration = avio_rb64(pb); - av_dlog(NULL, "IndexDuration %"PRId64"\n", segment->index_duration); + av_log(NULL, AV_LOG_TRACE, "IndexDuration %"PRId64"\n", segment->index_duration); break; } return 0; @@ -814,9 +814,9 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) do { code = avio_r8(pb); value = avio_r8(pb); - av_dlog(NULL, "pixel layout: code %#x\n", code); + av_log(NULL, AV_LOG_TRACE, "pixel layout: code %#x\n", code); - if (ofs < 16) { + if (ofs <= 14) { layout[ofs++] = code; layout[ofs++] = value; } @@ -895,7 +895,7 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) { av_free(descriptor->extradata); descriptor->extradata_size = 0; - descriptor->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + descriptor->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!descriptor->extradata) return AVERROR(ENOMEM); descriptor->extradata_size = size; @@ -947,22 +947,22 @@ static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe static const MXFCodecUL mxf_picture_essence_container_uls[] = { // video essence container uls - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES frame-wrapped */ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */ - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO }, /* uncompressed picture */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; /* EC ULs for intra-only formats */ static const MXFCodecUL mxf_intra_only_essence_container_uls[] = { - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 Mappings */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 mappings */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; /* intra-only PictureEssenceCoding ULs, where no corresponding EC UL exists */ static const MXFCodecUL mxf_intra_only_picture_essence_coding_uls[] = { { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */ - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG 2000 code stream */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; @@ -972,7 +972,7 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = { { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, AV_CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */ { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */ - { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG2 AAC ADTS (legacy) */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; @@ -1369,7 +1369,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) MXFPackage *temp_package = NULL; int i, j, k, ret; - av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count); + av_log(mxf->fc, AV_LOG_TRACE, "metadata sets count %d\n", mxf->metadata_sets_count); /* TODO: handle multiple material packages (OP3x) */ for (i = 0; i < mxf->packages_count; i++) { material_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], MaterialPackage); @@ -1420,7 +1420,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) } } if (!source_package) { - av_dlog(mxf->fc, "material track %d: no corresponding source package found\n", material_track->track_id); + av_log(mxf->fc, AV_LOG_TRACE, "material track %d: no corresponding source package found\n", material_track->track_id); break; } for (k = 0; k < source_package->tracks_count; k++) { @@ -1484,7 +1484,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); - st->codec->codec_type = codec_ul->id; + st->codecpar->codec_type = codec_ul->id; source_package->descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor_ref, AnyType); if (source_package->descriptor) { @@ -1526,16 +1526,16 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); - st->codec->codec_id = codec_ul->id; + st->codecpar->codec_id = codec_ul->id; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { source_track->intra_only = mxf_is_intra_only(descriptor); container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul); - if (st->codec->codec_id == AV_CODEC_ID_NONE) - st->codec->codec_id = container_ul->id; - st->codec->width = descriptor->width; + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) + st->codecpar->codec_id = container_ul->id; + st->codecpar->width = descriptor->width; /* Field height, not frame height */ - st->codec->height = descriptor->height; + st->codecpar->height = descriptor->height; switch (descriptor->frame_layout) { case SegmentedFrame: /* This one is a weird layout I don't fully understand. */ @@ -1543,7 +1543,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) "SegmentedFrame layout isn't currently supported\n"); break; case FullFrame: - st->codec->field_order = AV_FIELD_PROGRESSIVE; + st->codecpar->field_order = AV_FIELD_PROGRESSIVE; break; case OneField: /* Every other line is stored and needs to be duplicated. */ @@ -1558,10 +1558,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) case MixedFields: switch (descriptor->field_dominance) { case MXF_TFF: - st->codec->field_order = AV_FIELD_TT; + st->codecpar->field_order = AV_FIELD_TT; break; case MXF_BFF: - st->codec->field_order = AV_FIELD_BB; + st->codecpar->field_order = AV_FIELD_BB; break; default: avpriv_request_sample(mxf->fc, @@ -1570,26 +1570,26 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) break; } /* Turn field height into frame height. */ - st->codec->height *= 2; + st->codecpar->height *= 2; break; default: av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout); } - if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO) { - st->codec->pix_fmt = descriptor->pix_fmt; - if (st->codec->pix_fmt == AV_PIX_FMT_NONE) { + if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { + st->codecpar->format = descriptor->pix_fmt; + if (st->codecpar->format == AV_PIX_FMT_NONE) { pix_fmt_ul = mxf_get_codec_ul(ff_mxf_pixel_format_uls, &descriptor->essence_codec_ul); - st->codec->pix_fmt = pix_fmt_ul->id; - if (st->codec->pix_fmt == AV_PIX_FMT_NONE) { + st->codecpar->format = pix_fmt_ul->id; + if (st->codecpar->format == AV_PIX_FMT_NONE) { /* support files created before RP224v10 by defaulting to UYVY422 if subsampling is 4:2:2 and component depth is 8-bit */ if (descriptor->horiz_subsampling == 2 && descriptor->vert_subsampling == 1 && descriptor->component_depth == 8) { - st->codec->pix_fmt = AV_PIX_FMT_UYVY422; + st->codecpar->format = AV_PIX_FMT_UYVY422; } } } @@ -1605,15 +1605,15 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) snprintf(source_origin, sizeof(source_origin), "%d", source_track->sequence->origin); av_dict_set(&st->metadata, "source_track_origin", source_origin, 0); } - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul); - if (st->codec->codec_id == AV_CODEC_ID_NONE) - st->codec->codec_id = container_ul->id; - st->codec->channels = descriptor->channels; - st->codec->bits_per_coded_sample = descriptor->bits_per_sample; + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) + st->codecpar->codec_id = container_ul->id; + st->codecpar->channels = descriptor->channels; + st->codecpar->bits_per_coded_sample = descriptor->bits_per_sample; if (descriptor->sample_rate.den > 0) { - st->codec->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den; + st->codecpar->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den; avpriv_set_pts_info(st, 64, descriptor->sample_rate.den, descriptor->sample_rate.num); } else { av_log(mxf->fc, AV_LOG_WARNING, "invalid sample rate (%d/%d) " @@ -1630,20 +1630,20 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) st->time_base); /* TODO: implement AV_CODEC_ID_RAWAUDIO */ - if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) { + if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) { if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24) - st->codec->codec_id = AV_CODEC_ID_PCM_S24LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; else if (descriptor->bits_per_sample == 32) - st->codec->codec_id = AV_CODEC_ID_PCM_S32LE; - } else if (st->codec->codec_id == AV_CODEC_ID_PCM_S16BE) { + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; + } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) { if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24) - st->codec->codec_id = AV_CODEC_ID_PCM_S24BE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE; else if (descriptor->bits_per_sample == 32) - st->codec->codec_id = AV_CODEC_ID_PCM_S32BE; - } else if (st->codec->codec_id == AV_CODEC_ID_MP2) { + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { st->need_parsing = AVSTREAM_PARSE_FULL; } - } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { int codec_id = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul)->id; if (codec_id >= 0 && @@ -1653,17 +1653,17 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) } } if (descriptor->extradata) { - st->codec->extradata = av_mallocz(descriptor->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (st->codec->extradata) { - memcpy(st->codec->extradata, descriptor->extradata, descriptor->extradata_size); - st->codec->extradata_size = descriptor->extradata_size; + st->codecpar->extradata = av_mallocz(descriptor->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (st->codecpar->extradata) { + memcpy(st->codecpar->extradata, descriptor->extradata, descriptor->extradata_size); + st->codecpar->extradata_size = descriptor->extradata_size; } - } else if (st->codec->codec_id == AV_CODEC_ID_H264) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) { ret = ff_generate_avci_extradata(st); if (ret < 0) return ret; } - if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { + if (st->codecpar->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { /* TODO: decode timestamps */ st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; } @@ -1735,7 +1735,8 @@ static int mxf_timestamp_to_str(uint64_t timestamp, char **str) *str = av_mallocz(32); if (!*str) return AVERROR(ENOMEM); - strftime(*str, 32, "%Y-%m-%d %H:%M:%S", &time); + if (!strftime(*str, 32, "%Y-%m-%d %H:%M:%S", &time)) + (*str)[0] = '\0'; return 0; } @@ -1848,7 +1849,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF uint64_t next = avio_tell(pb) + size; UID uid = {0}; - av_dlog(mxf->fc, "local tag %#04x size %d\n", tag, size); + av_log(mxf->fc, AV_LOG_TRACE, "local tag %#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 %#04x with 0 size\n", tag); continue; @@ -1859,7 +1860,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF int local_tag = AV_RB16(mxf->local_tags+i*18); if (local_tag == tag) { memcpy(uid, mxf->local_tags+i*18+2, 16); - av_dlog(mxf->fc, "local tag %#04x\n", local_tag); + av_log(mxf->fc, AV_LOG_TRACE, "local tag %#04x\n", local_tag); PRINT_KEY(mxf->fc, "uid", uid); } } @@ -1902,7 +1903,7 @@ static int mxf_seek_to_previous_partition(MXFContext *mxf) avio_seek(pb, mxf->run_in + mxf->current_partition->previous_partition, SEEK_SET); mxf->current_partition = NULL; - av_dlog(mxf->fc, "seeking to previous partition\n"); + av_log(mxf->fc, AV_LOG_TRACE, "seeking to previous partition\n"); return 1; } @@ -1923,11 +1924,11 @@ static int mxf_parse_handle_essence(MXFContext *mxf) : mxf->last_partition; if (!offset) { - av_dlog(mxf->fc, "no last partition\n"); + av_log(mxf->fc, AV_LOG_TRACE, "no last partition\n"); return 0; } - av_dlog(mxf->fc, "seeking to last partition\n"); + av_log(mxf->fc, AV_LOG_TRACE, "seeking to last partition\n"); /* remember where we were so we don't end up seeking further back than this */ mxf->last_forward_tell = avio_tell(pb); @@ -2058,8 +2059,8 @@ static void mxf_handle_small_eubc(AVFormatContext *s) /* expect PCM with exactly one index table segment and a small (< 32) EUBC */ if (s->nb_streams != 1 || - s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO || - !is_pcm(s->streams[0]->codec->codec_id) || + s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || + !is_pcm(s->streams[0]->codecpar->codec_id) || mxf->nb_index_tables != 1 || mxf->index_tables[0].nb_segments != 1 || mxf->index_tables[0].segments[0]->edit_unit_byte_count >= 32) @@ -2133,7 +2134,7 @@ static int mxf_read_header(AVFormatContext *s) } PRINT_KEY(s, "read header", klv.key); - av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); + av_log(s, AV_LOG_TRACE, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key) || @@ -2314,21 +2315,21 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, return 0; } -static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, +static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par, AVPacket *pkt) { MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data; - int64_t bits_per_sample = codec->bits_per_coded_sample; + int64_t bits_per_sample = par->bits_per_coded_sample; if (!bits_per_sample) - bits_per_sample = av_get_bits_per_sample(codec->codec_id); + bits_per_sample = av_get_bits_per_sample(par->codec_id); pkt->pts = track->sample_count; - if (codec->channels <= 0 || codec->channels * bits_per_sample < 8) + if (par->channels <= 0 || par->channels * bits_per_sample < 8) return AVERROR_INVALIDDATA; - track->sample_count += pkt->size / (codec->channels * bits_per_sample / 8); + track->sample_count += pkt->size / (par->channels * bits_per_sample / 8); return 0; } @@ -2342,7 +2343,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) if ((ret = klv_read_packet(&klv, s->pb)) < 0) return ret; PRINT_KEY(s, "read packet", klv.key); - av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); + av_log(s, AV_LOG_TRACE, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { ret = mxf_decrypt_triplet(s, pkt, &klv); if (ret < 0) { @@ -2357,7 +2358,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) int64_t next_ofs, next_klv; AVStream *st; MXFTrack *track; - AVCodecContext *codec; + AVCodecParameters *par; if (index < 0) { av_log(s, AV_LOG_ERROR, @@ -2403,9 +2404,9 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = index; pkt->pos = klv.offset; - codec = s->streams[index]->codec; + par = s->streams[index]->codecpar; - if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { + if (par->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { /* mxf->current_edit_unit good - see if we have an * index table to derive timestamps from */ MXFIndexTable *t = &mxf->index_tables[0]; @@ -2420,8 +2421,8 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) * < PTS if low_delay = 0 (Sony IMX30) */ pkt->pts = mxf->current_edit_unit; } - } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { - ret = mxf_set_audio_pts(mxf, codec, pkt); + } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = mxf_set_audio_pts(mxf, par, pkt); if (ret < 0) return ret; } @@ -2478,17 +2479,17 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) if ((ret64 = avio_seek(s->pb, pos, SEEK_SET)) < 0) return ret64; - if ((ret = av_get_packet(s->pb, pkt, size)) != size) - return ret < 0 ? ret : AVERROR_EOF; + if ((ret = av_get_packet(s->pb, pkt, size)) != size) + return ret < 0 ? ret : AVERROR_EOF; pkt->stream_index = 0; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses && + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses && mxf->current_edit_unit >= 0 && mxf->current_edit_unit < t->nb_ptses) { pkt->dts = mxf->current_edit_unit + t->first_dts; pkt->pts = t->ptses[mxf->current_edit_unit]; - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - int ret = mxf_set_audio_pts(mxf, st->codec, pkt); + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int ret = mxf_set_audio_pts(mxf, st->codecpar, pkt); if (ret < 0) return ret; } @@ -2580,7 +2581,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti MXFTrack *source_track = st->priv_data; /* if audio then truncate sample_time to EditRate */ - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) sample_time = av_rescale_q(sample_time, st->time_base, av_inv_q(source_track->edit_rate)); @@ -2627,7 +2628,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti AVStream *cur_st = s->streams[i]; MXFTrack *cur_track = cur_st->priv_data; uint64_t current_sample_count = 0; - if (cur_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (cur_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { ret = mxf_compute_sample_count(mxf, i, ¤t_sample_count); if (ret < 0) return ret; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 841e727..1431fc6 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -35,6 +35,7 @@ #include #include "libavutil/random_seed.h" +#include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" #include "audiointerleave.h" #include "avformat.h" @@ -49,19 +50,19 @@ extern AVOutputFormat ff_mxf_d10_muxer; #define EDIT_UNITS_PER_BODY 250 #define KAG_SIZE 512 -typedef struct { +typedef struct MXFLocalTagPair { int local_tag; UID uid; } MXFLocalTagPair; -typedef struct { +typedef struct MXFIndexEntry { uint8_t flags; uint64_t offset; unsigned slice_offset; ///< offset of audio slice uint16_t temporal_ref; } MXFIndexEntry; -typedef struct { +typedef struct MXFStreamContext { AudioInterleaveContext aic; UID track_essence_element_key; int index; ///< index in mxf_essence_container_uls table @@ -73,7 +74,7 @@ typedef struct { int closed_gop; ///< gop is closed, used in mpeg-2 frame parsing } MXFStreamContext; -typedef struct { +typedef struct MXFContainerEssenceEntry { UID container_ul; UID element_ul; UID codec_ul; @@ -447,7 +448,7 @@ static void mxf_write_preface(AVFormatContext *s) mxf_write_metadata_key(pb, 0x012f00); PRINT_KEY(s, "preface key", pb->buf_ptr - 16); - klv_encode_ber_length(pb, 130 + 16 * mxf->essence_container_count); + klv_encode_ber_length(pb, 130 + 16LL * mxf->essence_container_count); // write preface set uid mxf_write_local_tag(pb, 16, 0x3C0A); @@ -610,7 +611,7 @@ static void mxf_write_common_fields(AVFormatContext *s, AVStream *st) if (st == mxf->timecode_track) avio_write(pb, smpte_12m_timecode_track_data_ul, 16); else { - const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type); + const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type); avio_write(pb, data_def_ul->uid, 16); } @@ -720,7 +721,7 @@ static void mxf_write_multi_descriptor(AVFormatContext *s) mxf_write_metadata_key(pb, 0x014400); PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16); - klv_encode_ber_length(pb, 64 + 16 * s->nb_streams); + klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams); mxf_write_local_tag(pb, 16, 0x3C0A); mxf_write_uuid(pb, MultipleDescriptor, 0); @@ -781,27 +782,27 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke { MXFStreamContext *sc = st->priv_data; AVIOContext *pb = s->pb; - int stored_height = (st->codec->height+15)/16*16; + int stored_height = (st->codecpar->height+15)/16*16; int display_height; int f1, f2; mxf_write_generic_desc(s, st, key, size+8+8+8+8+8+8+5+16+sc->interlaced*4+12+20); mxf_write_local_tag(pb, 4, 0x3203); - avio_wb32(pb, st->codec->width); + avio_wb32(pb, st->codecpar->width); mxf_write_local_tag(pb, 4, 0x3202); avio_wb32(pb, stored_height>>sc->interlaced); mxf_write_local_tag(pb, 4, 0x3209); - avio_wb32(pb, st->codec->width); + avio_wb32(pb, st->codecpar->width); - if (st->codec->height == 608) // PAL + VBI + if (st->codecpar->height == 608) // PAL + VBI display_height = 576; - else if (st->codec->height == 512) // NTSC + VBI + else if (st->codecpar->height == 512) // NTSC + VBI display_height = 486; else - display_height = st->codec->height; + display_height = st->codecpar->height; mxf_write_local_tag(pb, 4, 0x3208); avio_wb32(pb, display_height>>sc->interlaced); @@ -819,7 +820,7 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke avio_w8(pb, sc->interlaced); // video line map - switch (st->codec->height) { + switch (st->codecpar->height) { case 576: f1 = 23; f2 = 336; break; case 608: f1 = 7; f2 = 320; break; case 480: f1 = 20; f2 = 283; break; @@ -857,17 +858,17 @@ static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st) static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st) { AVIOContext *pb = s->pb; - int profile_and_level = (st->codec->profile<<4) | st->codec->level; + int profile_and_level = (st->codecpar->profile<<4) | st->codecpar->level; mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5); // bit rate mxf_write_local_tag(pb, 4, 0x8000); - avio_wb32(pb, st->codec->bit_rate); + avio_wb32(pb, st->codecpar->bit_rate); // profile and level mxf_write_local_tag(pb, 1, 0x8007); - if (!st->codec->profile) + if (!st->codecpar->profile) profile_and_level |= 0x80; // escape bit avio_w8(pb, profile_and_level); } @@ -884,14 +885,14 @@ static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, con // write audio sampling rate mxf_write_local_tag(pb, 8, 0x3D03); - avio_wb32(pb, st->codec->sample_rate); + avio_wb32(pb, st->codecpar->sample_rate); avio_wb32(pb, 1); mxf_write_local_tag(pb, 4, 0x3D07); - avio_wb32(pb, st->codec->channels); + avio_wb32(pb, st->codecpar->channels); mxf_write_local_tag(pb, 4, 0x3D01); - avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id)); + avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id)); } static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size) @@ -901,11 +902,11 @@ static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key mxf_write_generic_sound_common(s, st, key, size+6+8); mxf_write_local_tag(pb, 2, 0x3D0A); - avio_wb16(pb, st->codec->block_align); + avio_wb16(pb, st->codecpar->block_align); // avg bytes per sec mxf_write_local_tag(pb, 4, 0x3D09); - avio_wb32(pb, st->codec->block_align*st->codec->sample_rate); + avio_wb32(pb, st->codecpar->block_align*st->codecpar->sample_rate); } static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st) @@ -1053,8 +1054,8 @@ static void mxf_write_index_table_segment(AVFormatContext *s) if (mxf->edit_unit_byte_count) { klv_encode_ber_length(pb, 80); } else { - klv_encode_ber_length(pb, 85 + 12+(s->nb_streams+1)*6 + - 12+mxf->edit_units_count*(11+mxf->slice_count*4)); + klv_encode_ber_length(pb, 85 + 12+(s->nb_streams+1LL)*6 + + 12+mxf->edit_units_count*(11+mxf->slice_count*4LL)); } // instance id @@ -1126,7 +1127,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s) for (i = 0; i < mxf->edit_units_count; i++) { int temporal_offset = 0; - if (!(mxf->index_entries[i].flags & 0x33)) { // I frame + if (!(mxf->index_entries[i].flags & 0x33)) { // I-frame mxf->last_key_index = key_index; key_index = i; } @@ -1153,7 +1154,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s) mxf->last_key_index = key_index; } - if (!(mxf->index_entries[i].flags & 0x33) && // I frame + if (!(mxf->index_entries[i].flags & 0x33) && // I-frame mxf->index_entries[i].flags & 0x40 && !temporal_offset) mxf->index_entries[i].flags |= 0x80; // random access avio_w8(pb, mxf->index_entries[i].flags); @@ -1216,7 +1217,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, // write klv avio_write(pb, key, 16); - klv_encode_ber_length(pb, 88 + 16 * mxf->essence_container_count); + klv_encode_ber_length(pb, 88 + 16LL * mxf->essence_container_count); // write partition value avio_wb16(pb, 1); // majorVersion @@ -1292,21 +1293,21 @@ static const UID mxf_mpeg2_codec_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x03,0x00 }, // MP@H-14 Long GOP }; -static const UID *mxf_get_mpeg2_codec_ul(AVCodecContext *avctx) +static const UID *mxf_get_mpeg2_codec_ul(AVCodecParameters *par) { - int long_gop = avctx->gop_size > 1 || avctx->has_b_frames; + int long_gop = 1; - if (avctx->profile == 4) { // Main - if (avctx->level == 8) // Main + if (par->profile == 4) { // Main + if (par->level == 8) // Main return &mxf_mpeg2_codec_uls[0+long_gop]; - else if (avctx->level == 4) // High + else if (par->level == 4) // High return &mxf_mpeg2_codec_uls[4+long_gop]; - else if (avctx->level == 6) // High 14 + else if (par->level == 6) // High 14 return &mxf_mpeg2_codec_uls[8+long_gop]; - } else if (avctx->profile == 0) { // 422 - if (avctx->level == 5) // Main + } else if (par->profile == 0) { // 422 + if (par->level == 5) // Main return &mxf_mpeg2_codec_uls[2+long_gop]; - else if (avctx->level == 2) // High + else if (par->level == 2) // High return &mxf_mpeg2_codec_uls[6+long_gop]; } return NULL; @@ -1324,8 +1325,8 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, c = (c<<8) + pkt->data[i]; if (c == 0x1b5) { if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext - st->codec->profile = pkt->data[i+1] & 0x07; - st->codec->level = pkt->data[i+2] >> 4; + st->codecpar->profile = pkt->data[i+1] & 0x07; + st->codecpar->level = pkt->data[i+2] >> 4; } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame break; @@ -1359,15 +1360,15 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, case 4: sc->aspect_ratio = (AVRational){221,100}; break; default: av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, - st->codec->width, st->codec->height, 1024*1024); + st->codecpar->width, st->codecpar->height, 1024*1024); } } else if (c == 0x100) { // pic int pict_type = (pkt->data[i+2]>>3) & 0x07; e->temporal_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6); - if (pict_type == 2) { // P frame + if (pict_type == 2) { // P-frame e->flags |= 0x22; - sc->closed_gop = 0; // reset closed gop, don't matter anymore - } else if (pict_type == 3) { // B frame + sc->closed_gop = 0; // reset closed GOP, don't matter anymore + } else if (pict_type == 3) { // B-frame if (sc->closed_gop) e->flags |= 0x13; // only backward prediction else @@ -1380,13 +1381,14 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, } } if (s->oformat != &ff_mxf_d10_muxer) - sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codec); + sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar); return !!sc->codec_ul; } static uint64_t mxf_parse_timestamp(time_t timestamp) { - struct tm *time = gmtime(×tamp); + struct tm tmbuf; + struct tm *time = gmtime_r(×tamp, &tmbuf); if (!time) return 0; return (uint64_t)(time->tm_year+1900) << 48 | @@ -1428,7 +1430,7 @@ static int mxf_write_header(AVFormatContext *s) return AVERROR(ENOMEM); st->priv_data = sc; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (i != 0) { av_log(s, AV_LOG_ERROR, "video stream must be first track\n"); return -1; @@ -1448,13 +1450,13 @@ static int mxf_write_header(AVFormatContext *s) } avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den); if (s->oformat == &ff_mxf_d10_muxer) { - if (st->codec->bit_rate == 50000000) + if (st->codecpar->bit_rate == 50000000) if (mxf->time_base.den == 25) sc->index = 3; else sc->index = 5; - else if (st->codec->bit_rate == 40000000) + else if (st->codecpar->bit_rate == 40000000) if (mxf->time_base.den == 25) sc->index = 7; else sc->index = 9; - else if (st->codec->bit_rate == 30000000) + else if (st->codecpar->bit_rate == 30000000) if (mxf->time_base.den == 25) sc->index = 11; else sc->index = 13; else { @@ -1463,25 +1465,25 @@ static int mxf_write_header(AVFormatContext *s) } mxf->edit_unit_byte_count = KAG_SIZE; // system element - mxf->edit_unit_byte_count += 16 + 4 + (uint64_t)st->codec->bit_rate * + mxf->edit_unit_byte_count += 16 + 4 + (uint64_t)st->codecpar->bit_rate * mxf->time_base.num / (8*mxf->time_base.den); mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count); mxf->edit_unit_byte_count += 16 + 4 + 4 + samples_per_frame[0]*8*4; mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count); } - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->sample_rate != 48000) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->sample_rate != 48000) { av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n"); return -1; } - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); if (s->oformat == &ff_mxf_d10_muxer) { if (st->index != 1) { av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n"); return -1; } - if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE && - st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) { + if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE && + st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) { av_log(s, AV_LOG_ERROR, "MXF D-10 only support 16 or 24 bits le audio\n"); } sc->index = ((MXFStreamContext*)s->streams[0]->priv_data)->index + 1; @@ -1490,7 +1492,7 @@ static int mxf_write_header(AVFormatContext *s) } if (!sc->index) { - sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id); + sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id); if (sc->index == -1) { av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, " "codec not currently supported in container\n", i); @@ -1613,7 +1615,7 @@ static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacke { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; - int packet_size = (uint64_t)st->codec->bit_rate*mxf->time_base.num / + int packet_size = (uint64_t)st->codecpar->bit_rate*mxf->time_base.num / (8*mxf->time_base.den); // frame size int pad; @@ -1643,7 +1645,7 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; - int frame_size = pkt->size / st->codec->block_align; + int frame_size = pkt->size / st->codecpar->block_align; uint8_t *samples = pkt->data; uint8_t *end = pkt->data + pkt->size; int i; @@ -1652,12 +1654,12 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1)); avio_wl16(pb, frame_size); - avio_w8(pb, (1<codec->channels)-1); + avio_w8(pb, (1<codecpar->channels)-1); while (samples < end) { - for (i = 0; i < st->codec->channels; i++) { + for (i = 0; i < st->codecpar->channels; i++) { uint32_t sample; - if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) { + if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) { sample = AV_RL24(samples)<< 4; samples += 3; } else { @@ -1689,7 +1691,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) } } - if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) { av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n"); return -1; @@ -1712,7 +1714,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) if (st->index == 0) { if (!mxf->edit_unit_byte_count && (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) && - !(ie.flags & 0x33)) { // I frame, Gop start + !(ie.flags & 0x33)) { // I-frame, GOP start mxf_write_klv_fill(s); if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0) return err; @@ -1738,7 +1740,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) mxf_write_klv_fill(s); avio_write(pb, sc->track_essence_element_key, 16); // write key if (s->oformat == &ff_mxf_d10_muxer) { - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) mxf_write_d10_video_packet(s, st, pkt); else mxf_write_d10_audio_packet(s, st, pkt); @@ -1761,7 +1763,7 @@ static void mxf_write_random_index_pack(AVFormatContext *s) int i; avio_write(pb, random_index_pack_key, 16); - klv_encode_ber_length(pb, 28 + 12*mxf->body_partitions_count); + klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count); if (mxf->edit_unit_byte_count) avio_wb32(pb, 1); // BodySID of header partition @@ -1836,7 +1838,7 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket stream_count += !!s->streams[i]->last_in_packet_buffer; if (stream_count && (s->nb_streams == stream_count || flush)) { - AVPacketList *pktl = s->packet_buffer; + AVPacketList *pktl = s->internal->packet_buffer; if (s->nb_streams != stream_count) { AVPacketList *last = NULL; // find last packet in edit unit @@ -1853,27 +1855,27 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl) s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL; - av_free_packet(&pktl->pkt); + av_packet_unref(&pktl->pkt); av_freep(&pktl); pktl = next; } if (last) last->next = NULL; else { - s->packet_buffer = NULL; - s->packet_buffer_end= NULL; + s->internal->packet_buffer = NULL; + s->internal->packet_buffer_end= NULL; goto out; } - pktl = s->packet_buffer; + pktl = s->internal->packet_buffer; } *out = pktl->pkt; - av_dlog(s, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); - s->packet_buffer = pktl->next; + av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); + s->internal->packet_buffer = pktl->next; if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl) s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL; - if(!s->packet_buffer) - s->packet_buffer_end= NULL; + if(!s->internal->packet_buffer) + s->internal->packet_buffer_end= NULL; av_freep(&pktl); return 1; } else { diff --git a/libavformat/mxg.c b/libavformat/mxg.c index 1d1488c..245afb4 100644 --- a/libavformat/mxg.c +++ b/libavformat/mxg.c @@ -48,20 +48,20 @@ static int mxg_read_header(AVFormatContext *s) video_st = avformat_new_stream(s, NULL); if (!video_st) return AVERROR(ENOMEM); - video_st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - video_st->codec->codec_id = AV_CODEC_ID_MXPEG; + video_st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + video_st->codecpar->codec_id = AV_CODEC_ID_MXPEG; avpriv_set_pts_info(video_st, 64, 1, 1000000); audio_st = avformat_new_stream(s, NULL); if (!audio_st) return AVERROR(ENOMEM); - audio_st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - audio_st->codec->codec_id = AV_CODEC_ID_PCM_ALAW; - audio_st->codec->channels = 1; - audio_st->codec->channel_layout = AV_CH_LAYOUT_MONO; - audio_st->codec->sample_rate = 8000; - audio_st->codec->bits_per_coded_sample = 8; - audio_st->codec->block_align = 1; + audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + audio_st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; + audio_st->codecpar->channels = 1; + audio_st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + audio_st->codecpar->sample_rate = 8000; + audio_st->codecpar->bits_per_coded_sample = 8; + audio_st->codecpar->block_align = 1; avpriv_set_pts_info(audio_st, 64, 1, 1000000); mxg->soi_ptr = mxg->buffer_ptr = mxg->buffer = 0; @@ -110,7 +110,7 @@ static int mxg_update_cache(AVFormatContext *s, unsigned int cache_size) if (mxg->soi_ptr) soi_pos = mxg->soi_ptr - mxg->buffer; mxg->buffer = av_fast_realloc(mxg->buffer, &mxg->buffer_size, current_pos + cache_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!mxg->buffer) return AVERROR(ENOMEM); mxg->buffer_ptr = mxg->buffer + current_pos; @@ -169,11 +169,6 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = pkt->dts = mxg->dts; pkt->stream_index = 0; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif pkt->buf = NULL; pkt->size = mxg->buffer_ptr - mxg->soi_ptr; pkt->data = mxg->soi_ptr; @@ -212,11 +207,6 @@ FF_ENABLE_DEPRECATION_WARNINGS /* time (GMT) of first sample in usec since 1970, little-endian */ pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8); pkt->stream_index = 1; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif pkt->buf = NULL; pkt->size = size - 14; pkt->data = startmarker_ptr + 16; diff --git a/libavformat/ncdec.c b/libavformat/ncdec.c index 40d8dac..d726a2e 100644 --- a/libavformat/ncdec.c +++ b/libavformat/ncdec.c @@ -51,8 +51,8 @@ static int nc_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG4; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG4; st->need_parsing = AVSTREAM_PARSE_FULL; avpriv_set_pts_info(st, 64, 1, 100); @@ -83,7 +83,7 @@ static int nc_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(s->pb, pkt, size); if (ret != size) { - if (ret > 0) av_free_packet(pkt); + if (ret > 0) av_packet_unref(pkt); return AVERROR(EIO); } diff --git a/libavformat/network.c b/libavformat/network.c index 6d308eb..2c34b4a 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -20,102 +20,29 @@ #include #include "network.h" +#include "tls.h" #include "url.h" #include "libavcodec/internal.h" #include "libavutil/mem.h" -#if HAVE_THREADS -#if HAVE_PTHREADS -#include -#else -#include "compat/w32pthreads.h" -#endif -#endif - -#if CONFIG_OPENSSL -#include -static int openssl_init; -#if HAVE_THREADS -#include -#include "libavutil/avutil.h" -pthread_mutex_t *openssl_mutexes; -static void openssl_lock(int mode, int type, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&openssl_mutexes[type]); - else - pthread_mutex_unlock(&openssl_mutexes[type]); -} -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 -static unsigned long openssl_thread_id(void) -{ - return (intptr_t) pthread_self(); -} -#endif -#endif -#endif -#if CONFIG_GNUTLS -#include -#if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00 -#include -#include -GCRY_THREAD_OPTION_PTHREAD_IMPL; -#endif -#endif - void ff_tls_init(void) { - avpriv_lock_avformat(); -#if CONFIG_OPENSSL - if (!openssl_init) { - SSL_library_init(); - SSL_load_error_strings(); -#if HAVE_THREADS - if (!CRYPTO_get_locking_callback()) { - int i; - openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&openssl_mutexes[i], NULL); - CRYPTO_set_locking_callback(openssl_lock); -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 - CRYPTO_set_id_callback(openssl_thread_id); -#endif - } -#endif - } - openssl_init++; +#if CONFIG_TLS_OPENSSL_PROTOCOL + ff_openssl_init(); #endif -#if CONFIG_GNUTLS -#if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 - if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); +#if CONFIG_TLS_GNUTLS_PROTOCOL + ff_gnutls_init(); #endif - gnutls_global_init(); -#endif - avpriv_unlock_avformat(); } void ff_tls_deinit(void) { - avpriv_lock_avformat(); -#if CONFIG_OPENSSL - openssl_init--; - if (!openssl_init) { -#if HAVE_THREADS - if (CRYPTO_get_locking_callback() == openssl_lock) { - int i; - CRYPTO_set_locking_callback(NULL); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&openssl_mutexes[i]); - av_free(openssl_mutexes); - } +#if CONFIG_TLS_OPENSSL_PROTOCOL + ff_openssl_deinit(); #endif - } +#if CONFIG_TLS_GNUTLS_PROTOCOL + ff_gnutls_deinit(); #endif -#if CONFIG_GNUTLS - gnutls_global_deinit(); -#endif - avpriv_unlock_avformat(); } int ff_network_inited_globally; @@ -226,6 +153,10 @@ int ff_socket(int af, int type, int proto) fcntl(fd, F_SETFD, FD_CLOEXEC); #endif } +#ifdef SO_NOSIGPIPE + if (fd != -1) + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int)); +#endif return fd; } diff --git a/libavformat/network.h b/libavformat/network.h index 9d8c92f..09cee58 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -98,6 +98,10 @@ struct sockaddr_storage { }; #endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + #if !HAVE_STRUCT_ADDRINFO struct addrinfo { int ai_flags; diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c index 670b867..30a5eae 100644 --- a/libavformat/nsvdec.c +++ b/libavformat/nsvdec.c @@ -56,14 +56,14 @@ * (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, + * Then, about NSVf[12-15], faster.nsf has 179700. When viewing 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. + * except for nsvtrailer (which doesn't have an NSVf header), it reports correct time. * * nsvtrailer.nsv (S1) does not have any NSVf header, only NSVs chunks, * so the header seems to not be mandatory. (for streaming). @@ -165,7 +165,7 @@ typedef struct NSVStream { int cum_len; /* temporary storage (used during seek) */ } NSVStream; -typedef struct { +typedef struct NSVContext { int base_offset; int NSVf_end; uint32_t *nsvs_file_offset; @@ -179,7 +179,6 @@ typedef struct { int16_t avsync; AVRational framerate; uint32_t *nsvs_timestamps; - //DVDemuxContext* dv_demux; } NSVContext; static const AVCodecTag nsv_codec_video_tags[] = { @@ -214,7 +213,7 @@ static const AVCodecTag nsv_codec_audio_tags[] = { static int nsv_read_chunk(AVFormatContext *s, int fill_header); #define print_tag(str, tag, size) \ - av_dlog(NULL, "%s: tag=%c%c%c%c\n", \ + av_log(NULL, AV_LOG_TRACE, "%s: tag=%c%c%c%c\n", \ str, tag & 0xff, \ (tag >> 8) & 0xff, \ (tag >> 16) & 0xff, \ @@ -228,41 +227,39 @@ static int nsv_resync(AVFormatContext *s) uint32_t v = 0; int i; - av_dlog(s, "%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, avio_tell(pb), nsv->state); - - //nsv->state = NSV_UNSYNC; + av_log(s, AV_LOG_TRACE, "%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, avio_tell(pb), nsv->state); for (i = 0; i < NSV_MAX_RESYNC; i++) { if (pb->eof_reached) { - av_dlog(s, "NSV EOF\n"); + av_log(s, AV_LOG_TRACE, "NSV EOF\n"); nsv->state = NSV_UNSYNC; return -1; } v <<= 8; v |= avio_r8(pb); if (i < 8) { - av_dlog(s, "NSV resync: [%d] = %02x\n", i, v & 0x0FF); + av_log(s, AV_LOG_TRACE, "NSV resync: [%d] = %02x\n", i, v & 0x0FF); } if ((v & 0x0000ffff) == 0xefbe) { /* BEEF */ - av_dlog(s, "NSV resynced on BEEF after %d bytes\n", i+1); + av_log(s, AV_LOG_TRACE, "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 */ - av_dlog(s, "NSV resynced on NSVf after %d bytes\n", i+1); + av_log(s, AV_LOG_TRACE, "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 */ - av_dlog(s, "NSV resynced on NSVs after %d bytes\n", i+1); + av_log(s, AV_LOG_TRACE, "NSV resynced on NSVs after %d bytes\n", i+1); nsv->state = NSV_FOUND_NSVS; return 0; } } - av_dlog(s, "NSV sync lost\n"); + av_log(s, AV_LOG_TRACE, "NSV sync lost\n"); return -1; } @@ -277,7 +274,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) int table_entries; int table_entries_used; - av_dlog(s, "%s()\n", __FUNCTION__); + av_log(s, AV_LOG_TRACE, "%s()\n", __FUNCTION__); nsv->state = NSV_UNSYNC; /* in case we fail */ @@ -286,24 +283,23 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) return -1; nsv->NSVf_end = size; - //s->file_size = (uint32_t)avio_rl32(pb); file_size = (uint32_t)avio_rl32(pb); - av_dlog(s, "NSV NSVf chunk_size %u\n", size); - av_dlog(s, "NSV NSVf file_size %u\n", file_size); + av_log(s, AV_LOG_TRACE, "NSV NSVf chunk_size %u\n", size); + av_log(s, AV_LOG_TRACE, "NSV NSVf file_size %u\n", file_size); nsv->duration = duration = avio_rl32(pb); /* in ms */ - av_dlog(s, "NSV NSVf duration %"PRId64" ms\n", duration); + av_log(s, AV_LOG_TRACE, "NSV NSVf duration %"PRId64" ms\n", duration); // XXX: store it in AVStreams strings_size = avio_rl32(pb); table_entries = avio_rl32(pb); table_entries_used = avio_rl32(pb); - av_dlog(s, "NSV NSVf info-strings size: %d, table entries: %d, bis %d\n", + av_log(s, AV_LOG_TRACE, "NSV NSVf info-strings size: %d, table entries: %d, bis %d\n", strings_size, table_entries, table_entries_used); if (pb->eof_reached) return -1; - av_dlog(s, "NSV got header; filepos %"PRId64"\n", avio_tell(pb)); + av_log(s, AV_LOG_TRACE, "NSV got header; filepos %"PRId64"\n", avio_tell(pb)); if (strings_size > 0) { char *strings; /* last byte will be '\0' to play safe with str*() */ @@ -332,7 +328,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) if (!p || p >= endp) break; *p++ = '\0'; - av_dlog(s, "NSV NSVf INFO: %s='%s'\n", token, value); + av_log(s, AV_LOG_TRACE, "NSV NSVf INFO: %s='%s'\n", token, value); av_dict_set(&s->metadata, token, value, 0); } av_free(strings); @@ -340,7 +336,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) if (pb->eof_reached) return -1; - av_dlog(s, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb)); + av_log(s, AV_LOG_TRACE, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb)); if (table_entries_used > 0) { int i; @@ -365,7 +361,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) } } - av_dlog(s, "NSV got index; filepos %"PRId64"\n", avio_tell(pb)); + av_log(s, AV_LOG_TRACE, "NSV got index; filepos %"PRId64"\n", avio_tell(pb)); avio_seek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */ @@ -385,7 +381,7 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) int i; AVStream *st; NSVStream *nst; - av_dlog(s, "%s()\n", __FUNCTION__); + av_log(s, AV_LOG_TRACE, "%s()\n", __FUNCTION__); vtag = avio_rl32(pb); atag = avio_rl32(pb); @@ -393,7 +389,7 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) vheight = avio_rl16(pb); i = avio_r8(pb); - av_dlog(s, "NSV NSVs framerate code %2x\n", i); + av_log(s, AV_LOG_TRACE, "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}; @@ -416,7 +412,7 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) print_tag("NSV NSVs vtag", vtag, 0); print_tag("NSV NSVs atag", atag, 0); - av_dlog(s, "NSV NSVs vsize %dx%d\n", vwidth, vheight); + av_log(s, AV_LOG_TRACE, "NSV NSVs vsize %dx%d\n", vwidth, vheight); /* XXX change to ap != NULL ? */ if (s->nb_streams == 0) { /* streams not yet published, let's do that */ @@ -435,12 +431,12 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) if (!nst) goto fail; st->priv_data = nst; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = vtag; - st->codec->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag); - st->codec->width = vwidth; - st->codec->height = vheight; - st->codec->bits_per_coded_sample = 24; /* depth XXX */ + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = vtag; + st->codecpar->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag); + st->codecpar->width = vwidth; + st->codecpar->height = vheight; + st->codecpar->bits_per_coded_sample = 24; /* depth XXX */ avpriv_set_pts_info(st, 64, framerate.den, framerate.num); st->start_time = 0; @@ -466,9 +462,9 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) if (!nst) goto fail; st->priv_data = nst; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = atag; - st->codec->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = atag; + st->codecpar->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag); st->need_parsing = AVSTREAM_PARSE_FULL; /* for PCM we will read a chunk later and put correct info */ @@ -479,7 +475,7 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) } } else { if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) { - av_dlog(s, "NSV NSVs header values differ from the first one!!!\n"); + av_log(s, AV_LOG_TRACE, "NSV NSVs header values differ from the first one!!!\n"); //return -1; } } @@ -497,8 +493,8 @@ static int nsv_read_header(AVFormatContext *s) NSVContext *nsv = s->priv_data; int i, err; - av_dlog(s, "%s()\n", __FUNCTION__); - av_dlog(s, "filename '%s'\n", s->filename); + av_log(s, AV_LOG_TRACE, "%s()\n", __FUNCTION__); + av_log(s, AV_LOG_TRACE, "filename '%s'\n", s->filename); nsv->state = NSV_UNSYNC; nsv->ahead[0].data = nsv->ahead[1].data = NULL; @@ -524,7 +520,7 @@ static int nsv_read_header(AVFormatContext *s) /* now read the first chunk, so we can attempt to decode more info */ err = nsv_read_chunk(s, 1); - av_dlog(s, "parsed header\n"); + av_log(s, AV_LOG_TRACE, "parsed header\n"); return err; } @@ -540,8 +536,9 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header) uint32_t vsize; uint16_t asize; uint16_t auxsize; + int ret; - av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header); + av_log(s, AV_LOG_TRACE, "%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! */ @@ -566,20 +563,20 @@ null_chunk_retry: asize = avio_rl16(pb); vsize = (vsize << 4) | (auxcount >> 4); auxcount &= 0x0f; - av_dlog(s, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize); + av_log(s, AV_LOG_TRACE, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize); /* skip aux stuff */ for (i = 0; i < auxcount; i++) { uint32_t av_unused auxtag; auxsize = avio_rl16(pb); auxtag = avio_rl32(pb); - av_dlog(s, "NSV aux data: '%c%c%c%c', %d bytes\n", + av_log(s, AV_LOG_TRACE, "NSV aux data: '%c%c%c%c', %d bytes\n", (auxtag & 0x0ff), ((auxtag >> 8) & 0x0ff), ((auxtag >> 16) & 0x0ff), ((auxtag >> 24) & 0x0ff), auxsize); avio_skip(pb, auxsize); - vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming braindead */ + vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming brain-dead */ } if (pb->eof_reached) @@ -598,12 +595,13 @@ null_chunk_retry: 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); + if ((ret = av_get_packet(pb, pkt, vsize)) < 0) + return ret; pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO; pkt->dts = nst->frame_offset; pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ for (i = 0; i < FFMIN(8, vsize); i++) - av_dlog(s, "NSV video: [%d] = %02x\n", i, pkt->data[i]); + av_log(s, AV_LOG_TRACE, "NSV video: [%d] = %02x\n", i, pkt->data[i]); } if(st[NSV_ST_VIDEO]) ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++; @@ -613,31 +611,34 @@ null_chunk_retry: 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*/) { + if (asize && st[NSV_ST_AUDIO]->codecpar->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) { uint8_t bps; uint8_t channels; uint16_t samplerate; bps = avio_r8(pb); channels = avio_r8(pb); samplerate = avio_rl16(pb); + if (!channels || !samplerate) + return AVERROR_INVALIDDATA; asize-=4; - av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate); + av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate); if (fill_header) { st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE; /* we know everything */ if (bps != 16) { - av_dlog(s, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps); + av_log(s, AV_LOG_TRACE, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps); } bps /= channels; // ??? if (bps == 8) - st[NSV_ST_AUDIO]->codec->codec_id = AV_CODEC_ID_PCM_U8; + st[NSV_ST_AUDIO]->codecpar->codec_id = AV_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; - av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate); + st[NSV_ST_AUDIO]->codecpar->channels = channels; + st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate; + av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate); } } - av_get_packet(pb, pkt, asize); + if ((ret = av_get_packet(pb, pkt, asize)) < 0) + return ret; pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO; pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) { @@ -645,7 +646,7 @@ null_chunk_retry: pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1); pkt->dts *= (int64_t)1000 * nsv->framerate.den; pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num; - av_dlog(s, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts); + av_log(s, AV_LOG_TRACE, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts); } nst->frame_offset++; } @@ -660,7 +661,7 @@ static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt) NSVContext *nsv = s->priv_data; int i, err = 0; - av_dlog(s, "%s()\n", __FUNCTION__); + av_log(s, AV_LOG_TRACE, "%s()\n", __FUNCTION__); /* in case we don't already have something to eat ... */ if (!nsv->ahead[0].data && !nsv->ahead[1].data) @@ -671,7 +672,7 @@ static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt) /* now pick one of the plates */ for (i = 0; i < 2; i++) { if (nsv->ahead[i].data) { - av_dlog(s, "%s: using cached packet[%d]\n", __FUNCTION__, i); + av_log(s, AV_LOG_TRACE, "%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 */ @@ -679,7 +680,7 @@ static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt) } } - /* this restaurant is not approvisionned :^] */ + /* this restaurant is not provisioned :^] */ return -1; } @@ -709,9 +710,9 @@ static int nsv_read_close(AVFormatContext *s) av_freep(&nsv->nsvs_file_offset); av_freep(&nsv->nsvs_timestamps); if (nsv->ahead[0].data) - av_free_packet(&nsv->ahead[0]); + av_packet_unref(&nsv->ahead[0]); if (nsv->ahead[1].data) - av_free_packet(&nsv->ahead[1]); + av_packet_unref(&nsv->ahead[1]); return 0; } @@ -721,7 +722,7 @@ static int nsv_probe(AVProbeData *p) int score; int vsize, asize, auxcount; score = 0; - av_dlog(NULL, "nsv_probe(), buf_size %d\n", p->buf_size); + av_log(NULL, AV_LOG_TRACE, "nsv_probe(), buf_size %d\n", p->buf_size); /* check file header */ /* streamed files might not have any header */ if (p->buf[0] == 'N' && p->buf[1] == 'S' && diff --git a/libavformat/nullenc.c b/libavformat/nullenc.c index 829f2a8..0da5940 100644 --- a/libavformat/nullenc.c +++ b/libavformat/nullenc.c @@ -30,7 +30,7 @@ AVOutputFormat ff_null_muxer = { .name = "null", .long_name = NULL_IF_CONFIG_SMALL("raw null video"), .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_RAWVIDEO, + .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_packet = null_write_packet, - .flags = AVFMT_NOFILE | AVFMT_NOTIMESTAMPS | AVFMT_RAWPICTURE, + .flags = AVFMT_NOFILE | AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/nut.c b/libavformat/nut.c index 43ae8a0..828d9ca 100644 --- a/libavformat/nut.c +++ b/libavformat/nut.c @@ -149,6 +149,7 @@ const AVCodecTag ff_nut_audio_tags[] = { { AV_CODEC_ID_PCM_U32BE, MKTAG(32, 'D', 'U', 'P') }, { AV_CODEC_ID_PCM_U32LE, MKTAG('P', 'U', 'D', 32) }, { AV_CODEC_ID_PCM_U8, MKTAG('P', 'U', 'D', 8) }, + { AV_CODEC_ID_PCM_S16BE_PLANAR, MKTAG(16 , 'P', 'S', 'P') }, { AV_CODEC_ID_PCM_S16LE_PLANAR, MKTAG('P', 'S', 'P', 16) }, { AV_CODEC_ID_PCM_S24LE_PLANAR, MKTAG('P', 'S', 'P', 24) }, { AV_CODEC_ID_PCM_S32LE_PLANAR, MKTAG('P', 'S', 'P', 32) }, diff --git a/libavformat/nut.h b/libavformat/nut.h index 16f3c12..52ce8fc 100644 --- a/libavformat/nut.h +++ b/libavformat/nut.h @@ -41,17 +41,17 @@ #define NUT_MIN_VERSION 2 typedef enum{ - FLAG_KEY = 1, ///time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational)); nut->time_base = av_malloc(nut->time_base_count * sizeof(AVRational)); + if (!nut->time_base) + return AVERROR(ENOMEM); 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 (av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1) { - av_log(s, AV_LOG_ERROR, "time base invalid\n"); + av_log(s, AV_LOG_ERROR, "invalid time base %d/%d\n", + nut->time_base[i].num, + nut->time_base[i].den); return AVERROR_INVALIDDATA; } } @@ -279,7 +283,8 @@ static int decode_main_header(NUTContext *nut) return AVERROR_INVALIDDATA; } if (tmp_stream >= stream_count) { - av_log(s, AV_LOG_ERROR, "illegal stream number\n"); + av_log(s, AV_LOG_ERROR, "illegal stream number %d >= %d\n", + tmp_stream, stream_count); return AVERROR_INVALIDDATA; } @@ -307,11 +312,13 @@ static int decode_main_header(NUTContext *nut) for (i = 1; i < nut->header_count; i++) { uint8_t *hdr; GET_V(nut->header_len[i], tmp > 0 && tmp < 256); - rem -= nut->header_len[i]; - if (rem < 0) { - av_log(s, AV_LOG_ERROR, "invalid elision header\n"); + if (rem < nut->header_len[i]) { + av_log(s, AV_LOG_ERROR, + "invalid elision header %d : %d > %d\n", + i, nut->header_len[i], rem); return AVERROR_INVALIDDATA; } + rem -= nut->header_len[i]; hdr = av_malloc(nut->header_len[i]); if (!hdr) return AVERROR(ENOMEM); @@ -332,6 +339,8 @@ static int decode_main_header(NUTContext *nut) } nut->stream = av_mallocz(sizeof(StreamContext) * stream_count); + if (!nut->stream) + return AVERROR(ENOMEM); for (i = 0; i < stream_count; i++) avformat_new_stream(s, NULL); @@ -358,11 +367,11 @@ static int decode_stream_header(NUTContext *nut) class = ffio_read_varlen(bc); tmp = get_fourcc(bc); - st->codec->codec_tag = tmp; + st->codecpar->codec_tag = tmp; switch (class) { case 0: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = av_codec_get_id((const AVCodecTag * const []) { + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = av_codec_get_id((const AVCodecTag * const []) { ff_nut_video_tags, ff_codec_bmp_tags, 0 @@ -370,8 +379,8 @@ static int decode_stream_header(NUTContext *nut) tmp); break; case 1: - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = av_codec_get_id((const AVCodecTag * const []) { + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = av_codec_get_id((const AVCodecTag * const []) { ff_nut_audio_tags, ff_codec_wav_tags, 0 @@ -379,18 +388,18 @@ static int decode_stream_header(NUTContext *nut) tmp); break; case 2: - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp); + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp); break; case 3: - st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id = ff_codec_get_id(ff_nut_data_tags, tmp); + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = ff_codec_get_id(ff_nut_data_tags, tmp); break; default: av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class); return AVERROR(ENOSYS); } - if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE) + if (class < 3 && st->codecpar->codec_id == AV_CODEC_ID_NONE) av_log(s, AV_LOG_ERROR, "Unknown codec tag '0x%04x' for stream number %d\n", (unsigned int) tmp, stream_id); @@ -399,19 +408,20 @@ static int decode_stream_header(NUTContext *nut) GET_V(stc->msb_pts_shift, tmp < 16); stc->max_pts_distance = ffio_read_varlen(bc); GET_V(stc->decode_delay, tmp < 1000); // sanity limit, raise this if Moore's law is true - st->codec->has_b_frames = stc->decode_delay; ffio_read_varlen(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); - avio_read(bc, st->codec->extradata, st->codec->extradata_size); + GET_V(st->codecpar->extradata_size, tmp < (1 << 30)); + if (st->codecpar->extradata_size) { + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + avio_read(bc, st->codecpar->extradata, st->codecpar->extradata_size); } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - GET_V(st->codec->width, tmp > 0); - GET_V(st->codec->height, tmp > 0); + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + GET_V(st->codecpar->width, tmp > 0); + GET_V(st->codecpar->height, tmp > 0); st->sample_aspect_ratio.num = ffio_read_varlen(bc); st->sample_aspect_ratio.den = ffio_read_varlen(bc); if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) { @@ -420,10 +430,10 @@ static int decode_stream_header(NUTContext *nut) return AVERROR_INVALIDDATA; } ffio_read_varlen(bc); /* csp type */ - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - GET_V(st->codec->sample_rate, tmp > 0); + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + GET_V(st->codecpar->sample_rate, tmp > 0); ffio_read_varlen(bc); // samplerate_den - GET_V(st->codec->channels, tmp > 0); + GET_V(st->codecpar->channels, tmp > 0); } if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, @@ -461,7 +471,7 @@ static int decode_info_header(NUTContext *nut) int64_t value, end; char name[256], str_value[1024], type_str[256]; const char *type; - int *event_flags; + int *event_flags = NULL; AVChapter *chapter = NULL; AVStream *st = NULL; AVDictionary **metadata = NULL; @@ -522,7 +532,9 @@ static int decode_info_header(NUTContext *nut) } if (stream_id_plus1 > s->nb_streams) { - av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n"); + av_log(s, AV_LOG_WARNING, + "invalid stream id %d for info packet\n", + stream_id_plus1); continue; } @@ -533,7 +545,8 @@ static int decode_info_header(NUTContext *nut) } if (metadata && av_strcasecmp(name, "Uses") && av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces")) { - *event_flags |= metadata_flag; + if (event_flags) + *event_flags |= metadata_flag; av_dict_set(metadata, name, str_value, 0); } } @@ -602,7 +615,7 @@ static int find_and_decode_index(NUTContext *nut) avio_seek(bc, filesize - 12, SEEK_SET); avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET); if (avio_rb64(bc) != INDEX_STARTCODE) { - av_log(s, AV_LOG_ERROR, "no index at the end\n"); + av_log(s, AV_LOG_WARNING, "no index at the end\n"); return ret; } @@ -613,6 +626,10 @@ static int find_and_decode_index(NUTContext *nut) 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)); + if (!syncpoints || !has_keyframe) { + ret = AVERROR(ENOMEM); + goto fail; + } for (i = 0; i < syncpoint_count; i++) { syncpoints[i] = ffio_read_varlen(bc); if (syncpoints[i] <= 0) @@ -746,7 +763,7 @@ static int nut_read_header(AVFormatContext *s) decode_info_header(nut); } - s->data_offset = pos - 8; + s->internal->data_offset = pos - 8; if (bc->seekable) { int64_t orig_pos = avio_tell(bc); @@ -873,7 +890,8 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code) ret = av_new_packet(pkt, size + nut->header_len[header_idx]); if (ret < 0) return ret; - memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]); + if (nut->header[header_idx]) + memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]); pkt->pos = avio_tell(bc); // FIXME avio_read(bc, pkt->data + nut->header_len[header_idx], size); diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index b68e00e..bf23b58 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -33,32 +33,32 @@ #include "avio_internal.h" #include "riff.h" -static int find_expected_header(AVCodecContext *c, int size, int key_frame, +static int find_expected_header(AVCodecParameters *p, int size, int key_frame, uint8_t out[64]) { - int sample_rate = c->sample_rate; + int sample_rate = p->sample_rate; if (size > 4096) return 0; AV_WB24(out, 1); - if (c->codec_id == AV_CODEC_ID_MPEG4) { + if (p->codec_id == AV_CODEC_ID_MPEG4) { if (key_frame) { return 3; } else { out[3] = 0xB6; return 4; } - } else if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO || - c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + } else if (p->codec_id == AV_CODEC_ID_MPEG1VIDEO || + p->codec_id == AV_CODEC_ID_MPEG2VIDEO) { return 3; - } else if (c->codec_id == AV_CODEC_ID_H264) { + } else if (p->codec_id == AV_CODEC_ID_H264) { return 3; - } else if (c->codec_id == AV_CODEC_ID_MP3 || - c->codec_id == AV_CODEC_ID_MP2) { + } else if (p->codec_id == AV_CODEC_ID_MP3 || + p->codec_id == AV_CODEC_ID_MP2) { int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size; - int layer = c->codec_id == AV_CODEC_ID_MP3 ? 3 : 2; + int layer = p->codec_id == AV_CODEC_ID_MP3 ? 3 : 2; unsigned int header = 0xFFF00000; lsf = sample_rate < (24000 + 32000) / 2; @@ -103,13 +103,13 @@ static int find_expected_header(AVCodecContext *c, int size, int key_frame, return 0; } -static int find_header_idx(AVFormatContext *s, AVCodecContext *c, int size, +static int find_header_idx(AVFormatContext *s, AVCodecParameters *p, int size, int frame_type) { NUTContext *nut = s->priv_data; uint8_t out[64]; int i; - int len = find_expected_header(c, size, frame_type, out); + int len = find_expected_header(p, size, frame_type, out); for (i = 1; i < nut->header_count; i++) { if (len == nut->header_len[i] && !memcmp(out, nut->header[i], len)) { @@ -169,8 +169,9 @@ static void build_frame_code(AVFormatContext *s) 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 == AVMEDIA_TYPE_AUDIO; + AVCodecParameters *par = s->streams[stream_id]->codecpar; + const AVCodecDescriptor *desc = avcodec_descriptor_get(par->codec_id); + int is_audio = par->codec_type == AVMEDIA_TYPE_AUDIO; int intra_only = /*codec->intra_only || */ is_audio; int pred_count; @@ -182,16 +183,23 @@ static void build_frame_code(AVFormatContext *s) ft->stream_id = stream_id; ft->size_mul = 1; if (is_audio) - ft->header_idx = find_header_idx(s, codec, -1, key_frame); + ft->header_idx = find_header_idx(s, par, -1, key_frame); start2++; } } key_frame = intra_only; if (is_audio) { - int frame_bytes = codec->frame_size * (int64_t)codec->bit_rate / - (8 * codec->sample_rate); + int frame_bytes; int pts; + + if (par->block_align > 0) { + frame_bytes = par->block_align; + } else { + int frame_size = av_get_audio_frame_duration2(par, 0); + frame_bytes = frame_size * (int64_t)par->bit_rate / (8 * par->sample_rate); + } + for (pts = 0; pts < 2; pts++) for (pred = 0; pred < 2; pred++) { FrameCode *ft = &nut->frame_code[start2]; @@ -200,7 +208,7 @@ static void build_frame_code(AVFormatContext *s) ft->size_mul = frame_bytes + 2; ft->size_lsb = frame_bytes + pred; ft->pts_delta = pts; - ft->header_idx = find_header_idx(s, codec, frame_bytes + pred, key_frame); + ft->header_idx = find_header_idx(s, par, frame_bytes + pred, key_frame); start2++; } } else { @@ -212,14 +220,14 @@ static void build_frame_code(AVFormatContext *s) start2++; } - if (codec->has_b_frames) { + if (desc && desc->props & AV_CODEC_PROP_REORDER) { 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 == AV_CODEC_ID_VORBIS) { + } else if (par->codec_id == AV_CODEC_ID_VORBIS) { pred_count = 3; pred_table[0] = 2; pred_table[1] = 9; @@ -243,7 +251,7 @@ static void build_frame_code(AVFormatContext *s) ft->size_lsb = index - start3; ft->pts_delta = pred_table[pred]; if (is_audio) - ft->header_idx = find_header_idx(s, codec, -1, key_frame); + ft->header_idx = find_header_idx(s, par, -1, key_frame); } } } @@ -416,11 +424,12 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, AVStream *st, int i) { NUTContext *nut = avctx->priv_data; - AVCodecContext *codec = st->codec; - unsigned codec_tag = av_codec_get_tag(ff_nut_codec_tags, codec->codec_id); + AVCodecParameters *par = st->codecpar; + const AVCodecDescriptor *desc = avcodec_descriptor_get(par->codec_id); + unsigned codec_tag = av_codec_get_tag(ff_nut_codec_tags, par->codec_id); ff_put_v(bc, i); - switch (codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: ff_put_v(bc, 0); break; @@ -436,8 +445,9 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, } ff_put_v(bc, 4); - if (!codec_tag || codec->codec_id == AV_CODEC_ID_RAWVIDEO) - codec_tag = codec->codec_tag; + if (av_codec_get_id(ff_nut_codec_tags, par->codec_tag) == par->codec_id || + !codec_tag || par->codec_id == AV_CODEC_ID_RAWVIDEO) + codec_tag = par->codec_tag; if (codec_tag) { avio_wl32(bc, codec_tag); @@ -449,21 +459,21 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, ff_put_v(bc, nut->stream[i].time_base - nut->time_base); ff_put_v(bc, nut->stream[i].msb_pts_shift); ff_put_v(bc, nut->stream[i].max_pts_distance); - ff_put_v(bc, codec->has_b_frames); + ff_put_v(bc, (desc && desc->props & AV_CODEC_PROP_REORDER) ? 16 : 0); avio_w8(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */ - ff_put_v(bc, codec->extradata_size); - avio_write(bc, codec->extradata, codec->extradata_size); + ff_put_v(bc, par->extradata_size); + avio_write(bc, par->extradata, par->extradata_size); - switch (codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: - ff_put_v(bc, codec->sample_rate); + ff_put_v(bc, par->sample_rate); ff_put_v(bc, 1); - ff_put_v(bc, codec->channels); + ff_put_v(bc, par->channels); break; case AVMEDIA_TYPE_VIDEO: - ff_put_v(bc, codec->width); - ff_put_v(bc, codec->height); + ff_put_v(bc, par->width); + ff_put_v(bc, par->height); if (st->sample_aspect_ratio.num <= 0 || st->sample_aspect_ratio.den <= 0) { @@ -614,11 +624,8 @@ static int write_headers(AVFormatContext *avctx, AVIOContext *bc) return ret; if (ret > 0) put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); - else { - uint8_t *buf; - avio_close_dyn_buf(dyn_bc, &buf); - av_free(buf); - } + else + ffio_free_dyn_buf(&dyn_bc); } for (i = 0; i < nut->avf->nb_chapters; i++) { @@ -627,9 +634,7 @@ static int write_headers(AVFormatContext *avctx, AVIOContext *bc) return ret; ret = write_chapter(nut, dyn_bc, i); if (ret < 0) { - uint8_t *buf; - avio_close_dyn_buf(dyn_bc, &buf); - av_freep(&buf); + ffio_free_dyn_buf(&dyn_bc); return ret; } put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); @@ -906,7 +911,10 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) frame_code = i; } } - assert(frame_code != -1); + + if (frame_code < 0) + return AVERROR_BUG; + fc = &nut->frame_code[frame_code]; flags = fc->flags; needed_flags = get_needed_flags(nut, nus, fc, pkt); diff --git a/libavformat/nuv.c b/libavformat/nuv.c index 9336912..492f68f 100644 --- a/libavformat/nuv.c +++ b/libavformat/nuv.c @@ -20,6 +20,7 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "avformat.h" @@ -32,7 +33,7 @@ static const AVCodecTag nuv_audio_tags[] = { { AV_CODEC_ID_NONE, 0 }, }; -typedef struct { +typedef struct NUVContext { int v_id; int a_id; int rtjpg_video; @@ -82,15 +83,15 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst, avio_skip(pb, 6); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { - if (vst->codec->extradata) { - av_freep(&vst->codec->extradata); - vst->codec->extradata_size = 0; + if (vst->codecpar->extradata) { + av_freep(&vst->codecpar->extradata); + vst->codecpar->extradata_size = 0; } - vst->codec->extradata = av_malloc(size); - if (!vst->codec->extradata) + vst->codecpar->extradata = av_malloc(size); + if (!vst->codecpar->extradata) return AVERROR(ENOMEM); - vst->codec->extradata_size = size; - avio_read(pb, vst->codec->extradata, size); + vst->codecpar->extradata_size = size; + avio_read(pb, vst->codecpar->extradata, size); size = 0; if (!myth) return 0; @@ -103,32 +104,32 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst, break; avio_rl32(pb); // version if (vst) { - vst->codec->codec_tag = avio_rl32(pb); - vst->codec->codec_id = - ff_codec_get_id(ff_codec_bmp_tags, vst->codec->codec_tag); - if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G')) - vst->codec->codec_id = AV_CODEC_ID_NUV; + vst->codecpar->codec_tag = avio_rl32(pb); + vst->codecpar->codec_id = + ff_codec_get_id(ff_codec_bmp_tags, vst->codecpar->codec_tag); + if (vst->codecpar->codec_tag == MKTAG('R', 'J', 'P', 'G')) + vst->codecpar->codec_id = AV_CODEC_ID_NUV; } else avio_skip(pb, 4); if (ast) { int id; - ast->codec->codec_tag = avio_rl32(pb); - ast->codec->sample_rate = avio_rl32(pb); - ast->codec->bits_per_coded_sample = avio_rl32(pb); - ast->codec->channels = avio_rl32(pb); - ast->codec->channel_layout = 0; + ast->codecpar->codec_tag = avio_rl32(pb); + ast->codecpar->sample_rate = avio_rl32(pb); + ast->codecpar->bits_per_coded_sample = avio_rl32(pb); + ast->codecpar->channels = avio_rl32(pb); + ast->codecpar->channel_layout = 0; - id = ff_wav_codec_get_id(ast->codec->codec_tag, - ast->codec->bits_per_coded_sample); + id = ff_wav_codec_get_id(ast->codecpar->codec_tag, + ast->codecpar->bits_per_coded_sample); if (id == AV_CODEC_ID_NONE) { - id = ff_codec_get_id(nuv_audio_tags, ast->codec->codec_tag); + id = ff_codec_get_id(nuv_audio_tags, ast->codecpar->codec_tag); if (id == AV_CODEC_ID_PCM_S16LE) - id = ff_get_pcm_codec_id(ast->codec->bits_per_coded_sample, + id = ff_get_pcm_codec_id(ast->codecpar->bits_per_coded_sample, 0, 0, ~1); } - ast->codec->codec_id = id; + ast->codecpar->codec_id = id; ast->need_parsing = AVSTREAM_PARSE_FULL; } else @@ -174,6 +175,15 @@ static int nuv_header(AVFormatContext *s) if (aspect > 0.9999 && aspect < 1.0001) aspect = 4.0 / 3.0; fps = av_int2double(avio_rl64(pb)); + if (fps < 0.0f) { + if (s->error_recognition & AV_EF_EXPLODE) { + av_log(s, AV_LOG_ERROR, "Invalid frame rate %f\n", fps); + return AVERROR_INVALIDDATA; + } else { + av_log(s, AV_LOG_WARNING, "Invalid frame rate %f, setting to 0.\n", fps); + fps = 0.0f; + } + } // number of packets per stream type, -1 means unknown, e.g. streaming v_packs = avio_rl32(pb); @@ -188,11 +198,15 @@ static int nuv_header(AVFormatContext *s) return AVERROR(ENOMEM); ctx->v_id = vst->index; - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_NUV; - vst->codec->width = width; - vst->codec->height = height; - vst->codec->bits_per_coded_sample = 10; + ret = av_image_check_size(width, height, 0, s); + if (ret < 0) + return ret; + + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_NUV; + vst->codecpar->width = width; + vst->codecpar->height = height; + vst->codecpar->bits_per_coded_sample = 10; vst->sample_aspect_ratio = av_d2q(aspect * height / width, 10000); vst->avg_frame_rate = av_d2q(fps, 60000); @@ -206,14 +220,14 @@ static int nuv_header(AVFormatContext *s) return AVERROR(ENOMEM); ctx->a_id = ast->index; - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_S16LE; - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; - ast->codec->sample_rate = 44100; - ast->codec->bit_rate = 2 * 2 * 44100 * 8; - ast->codec->block_align = 2 * 2; - ast->codec->bits_per_coded_sample = 16; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->sample_rate = 44100; + ast->codecpar->bit_rate = 2 * 2 * 44100 * 8; + ast->codecpar->block_align = 2 * 2; + ast->codecpar->bits_per_coded_sample = 16; avpriv_set_pts_info(ast, 32, 1, 1000); } else ctx->a_id = -1; @@ -221,7 +235,7 @@ static int nuv_header(AVFormatContext *s) if ((ret = get_codec_data(pb, vst, ast, is_mythtv)) < 0) return ret; - ctx->rtjpg_video = vst && vst->codec->codec_id == AV_CODEC_ID_NUV; + ctx->rtjpg_video = vst && vst->codecpar->codec_id == AV_CODEC_ID_NUV; return 0; } @@ -271,7 +285,7 @@ static int nuv_packet(AVFormatContext *s, AVPacket *pkt) memcpy(pkt->data, hdr, copyhdrsize); ret = avio_read(pb, pkt->data + copyhdrsize, size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } if (ret < size) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index ae9da3a..9ec2497 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -47,6 +47,7 @@ static const struct ogg_codec * const ogg_codecs[] = { &ff_flac_codec, &ff_celt_codec, &ff_opus_codec, + &ff_vp8_codec, &ff_old_dirac_codec, &ff_old_flac_codec, &ff_ogm_video_codec, @@ -63,6 +64,8 @@ static int ogg_save(AVFormatContext *s) struct ogg_state *ost = av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams)); int i; + if (!ost) + return AVERROR(ENOMEM); ost->pos = avio_tell(s->pb); ost->curidx = ogg->curidx; ost->next = ogg->state; @@ -71,7 +74,7 @@ static int ogg_save(AVFormatContext *s) for (i = 0; i < ogg->nstreams; i++) { struct ogg_stream *os = ogg->streams + i; - os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); + os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); memcpy(os->buf, ost->streams[i].buf, os->bufpos); } @@ -169,7 +172,7 @@ static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream) os = ogg->streams + idx; os->serial = serial; os->bufsize = DECODER_BUFFER_SIZE; - os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); + os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); os->header = -1; os->start_granule = OGG_NOGRANULE_VALUE; @@ -188,9 +191,12 @@ static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream) static int ogg_new_buf(struct ogg *ogg, int idx) { struct ogg_stream *os = ogg->streams + idx; - uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); + uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); int size = os->bufpos - os->pstart; + if (!nb) + return AVERROR(ENOMEM); + if (os->buf) { memcpy(nb, os->buf + os->pstart, size); av_free(os->buf); @@ -276,8 +282,11 @@ static int ogg_read_page(AVFormatContext *s, int *str) os = ogg->streams + idx; os->page_pos = avio_tell(bc) - 27; - if (os->psize > 0) - ogg_new_buf(ogg, idx); + if (os->psize > 0) { + ret = ogg_new_buf(ogg, idx); + if (ret < 0) + return ret; + } ret = avio_read(bc, os->segments, nsegs); if (ret < nsegs) @@ -306,7 +315,7 @@ static int ogg_read_page(AVFormatContext *s, int *str) } if (os->bufsize - os->bufpos < size) { - uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE); + uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE); if (!nb) return AVERROR(ENOMEM); memcpy(nb, os->buf, os->bufpos); @@ -322,7 +331,7 @@ static int ogg_read_page(AVFormatContext *s, int *str) os->granule = gp; os->flags = flags; - memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (str) *str = idx; @@ -338,7 +347,7 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, int complete = 0; int segp = 0, psize = 0; - av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx); + av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx); do { idx = ogg->curidx; @@ -351,7 +360,7 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, os = ogg->streams + idx; - av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", + av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", idx, os->pstart, os->psize, os->segp, os->nsegs); if (!os->codec) { @@ -389,7 +398,7 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, } } while (!complete); - av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n", + av_log(s, AV_LOG_TRACE, "ogg_packet: idx %i, frame size %i, start %i\n", idx, os->psize, os->pstart); if (os->granule == -1) @@ -413,8 +422,8 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, // Update the header state for all streams and // compute the data_offset. - if (!s->data_offset) - s->data_offset = os->sync_pos; + if (!s->internal->data_offset) + s->internal->data_offset = os->sync_pos; for (i = 0; i < ogg->nstreams; i++) { struct ogg_stream *cur_os = ogg->streams + i; @@ -422,7 +431,7 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, // if we have a partial non-header packet, its start is // obviously at or after the data start if (cur_os->incomplete) - s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos); + s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos); } } else { os->nb_header++; @@ -489,7 +498,7 @@ static int ogg_get_headers(AVFormatContext *s) os->lastpts = s->streams[i]->start_time = ogg_gptopts(s, i, os->start_granule, NULL); } - av_dlog(s, "found headers\n"); + av_log(s, AV_LOG_TRACE, "found headers\n"); return 0; } @@ -497,7 +506,7 @@ static int ogg_get_headers(AVFormatContext *s) static int ogg_get_length(AVFormatContext *s) { struct ogg *ogg = s->priv_data; - int i; + int i, ret; int64_t size, end; if (!s->pb->seekable) @@ -512,7 +521,9 @@ static int ogg_get_length(AVFormatContext *s) return 0; end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0; - ogg_save(s); + ret = ogg_save(s); + if (ret < 0) + return ret; avio_seek(s->pb, end, SEEK_SET); while (!ogg_read_page(s, &i)) { @@ -564,7 +575,11 @@ static int ogg_read_header(AVFormatContext *s) ogg->streams[i].codec = NULL; //linear granulepos seek from end - ogg_get_length(s); + ret = ogg_get_length(s); + if (ret < 0) { + ogg_read_close(s); + return ret; + } //fill the extradata in the per codec callbacks return 0; @@ -676,7 +691,7 @@ static int ogg_read_seek(AVFormatContext *s, int stream_index, // Try seeking to a keyframe first. If this fails (very possible), // av_seek_frame will fall back to ignoring keyframes - if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO + if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !(flags & AVSEEK_FLAG_ANY)) os->keyframe_seek = 1; diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index b8f0a8b..807ac4a 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -121,6 +121,7 @@ extern const struct ogg_codec ff_skeleton_codec; extern const struct ogg_codec ff_speex_codec; extern const struct ogg_codec ff_theora_codec; extern const struct ogg_codec ff_vorbis_codec; +extern const struct ogg_codec ff_vp8_codec; int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, const uint8_t *buf, int size, int parse_picture); diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 19c7759..2fef74a 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -35,7 +35,7 @@ #define MAX_PAGE_SIZE 65025 -typedef struct { +typedef struct OGGPage { int64_t start_granule; int64_t granule; int stream_index; @@ -46,7 +46,7 @@ typedef struct { uint16_t size; } OGGPage; -typedef struct { +typedef struct OGGStreamContext { unsigned page_counter; uint8_t *header[3]; int header_len[3]; @@ -66,17 +66,20 @@ typedef struct OGGPageList { struct OGGPageList *next; } OGGPageList; -typedef struct { +typedef struct OGGContext { const AVClass *class; OGGPageList *page_list; int pref_size; ///< preferred page size (0 => fill all segments) int64_t pref_duration; ///< preferred page duration (0 => fill all segments) + int serial_offset; } OGGContext; #define OFFSET(x) offsetof(OGGContext, x) #define PARAM AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { + { "serial_offset", "serial number offset", + OFFSET(serial_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, PARAM }, { "pagesize", "preferred page size in bytes (deprecated)", OFFSET(pref_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_PAGE_SIZE, PARAM }, { "page_duration", "preferred page duration, in microseconds", @@ -84,14 +87,14 @@ static const AVOption options[] = { { NULL }, }; -static const AVClass ogg_muxer_class = { - .class_name = "Ogg muxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, +#define OGG_CLASS(flavor)\ +static const AVClass flavor ## _muxer_class = {\ + .class_name = #flavor " muxer",\ + .item_name = av_default_item_name,\ + .option = options,\ + .version = LIBAVUTIL_VERSION_INT,\ }; - static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset) { int64_t pos = avio_tell(pb); @@ -209,7 +212,7 @@ static int ogg_buffer_data(AVFormatContext *s, AVStream *st, int i, segments, len, flush = 0; // Handles VFR by flushing page because this frame needs to have a timestamp - if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header && + if (st->codecpar->codec_id == AV_CODEC_ID_THEORA && !header && ogg_granule_to_timestamp(oggstream, granule) > ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1) { if (oggstream->page.granule != -1) @@ -291,16 +294,14 @@ static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, return p0; } -static int ogg_build_flac_headers(AVCodecContext *avctx, +static int ogg_build_flac_headers(AVCodecParameters *par, OGGStreamContext *oggstream, int bitexact, AVDictionary **m) { - enum FLACExtradataFormat format; - uint8_t *streaminfo; uint8_t *p; - if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo)) - return -1; + if (par->extradata_size < FLAC_STREAMINFO_SIZE) + return AVERROR(EINVAL); // first packet: STREAMINFO oggstream->header_len[0] = 51; @@ -316,7 +317,7 @@ static int ogg_build_flac_headers(AVCodecContext *avctx, bytestream_put_buffer(&p, "fLaC", 4); bytestream_put_byte(&p, 0x00); // streaminfo bytestream_put_be24(&p, 34); - bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); + bytestream_put_buffer(&p, par->extradata, FLAC_STREAMINFO_SIZE); // second packet: VorbisComment p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0); @@ -331,13 +332,13 @@ static int ogg_build_flac_headers(AVCodecContext *avctx, #define SPEEX_HEADER_SIZE 80 -static int ogg_build_speex_headers(AVCodecContext *avctx, +static int ogg_build_speex_headers(AVCodecParameters *par, OGGStreamContext *oggstream, int bitexact, AVDictionary **m) { uint8_t *p; - if (avctx->extradata_size < SPEEX_HEADER_SIZE) + if (par->extradata_size < SPEEX_HEADER_SIZE) return -1; // first packet: Speex header @@ -346,7 +347,7 @@ static int ogg_build_speex_headers(AVCodecContext *avctx, return AVERROR(ENOMEM); oggstream->header[0] = p; oggstream->header_len[0] = SPEEX_HEADER_SIZE; - bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); + bytestream_put_buffer(&p, par->extradata, SPEEX_HEADER_SIZE); AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 // second packet: VorbisComment @@ -360,22 +361,22 @@ static int ogg_build_speex_headers(AVCodecContext *avctx, #define OPUS_HEADER_SIZE 19 -static int ogg_build_opus_headers(AVCodecContext *avctx, +static int ogg_build_opus_headers(AVCodecParameters *par, OGGStreamContext *oggstream, int bitexact, AVDictionary **m) { uint8_t *p; - if (avctx->extradata_size < OPUS_HEADER_SIZE) + if (par->extradata_size < OPUS_HEADER_SIZE) return -1; /* first packet: Opus header */ - p = av_mallocz(avctx->extradata_size); + p = av_mallocz(par->extradata_size); if (!p) return AVERROR(ENOMEM); oggstream->header[0] = p; - oggstream->header_len[0] = avctx->extradata_size; - bytestream_put_buffer(&p, avctx->extradata, avctx->extradata_size); + oggstream->header_len[0] = par->extradata_size; + bytestream_put_buffer(&p, par->extradata, par->extradata_size); /* second packet: VorbisComment */ p = ogg_write_vorbiscomment(8, bitexact, &oggstream->header_len[1], m, 0); @@ -420,29 +421,31 @@ static int ogg_write_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - unsigned serial_num = i; + unsigned serial_num = i + ogg->serial_offset; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - if (st->codec->codec_id == AV_CODEC_ID_OPUS) + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) /* Opus requires a fixed 48kHz clock */ avpriv_set_pts_info(st, 64, 1, 48000); else - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); - if (st->codec->codec_id != AV_CODEC_ID_VORBIS && - st->codec->codec_id != AV_CODEC_ID_THEORA && - st->codec->codec_id != AV_CODEC_ID_SPEEX && - st->codec->codec_id != AV_CODEC_ID_FLAC && - st->codec->codec_id != AV_CODEC_ID_OPUS) { + if (st->codecpar->codec_id != AV_CODEC_ID_VORBIS && + st->codecpar->codec_id != AV_CODEC_ID_THEORA && + st->codecpar->codec_id != AV_CODEC_ID_SPEEX && + st->codecpar->codec_id != AV_CODEC_ID_FLAC && + st->codecpar->codec_id != AV_CODEC_ID_OPUS) { av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i); return -1; } - if (!st->codec->extradata || !st->codec->extradata_size) { + if (!st->codecpar->extradata || !st->codecpar->extradata_size) { av_log(s, AV_LOG_ERROR, "No extradata present\n"); return -1; } oggstream = av_mallocz(sizeof(*oggstream)); + if (!oggstream) + return AVERROR(ENOMEM); oggstream->page.stream_index = i; if (!(s->flags & AVFMT_FLAG_BITEXACT)) @@ -457,8 +460,8 @@ static int ogg_write_header(AVFormatContext *s) oggstream->serial_num = serial_num; st->priv_data = oggstream; - if (st->codec->codec_id == AV_CODEC_ID_FLAC) { - int err = ogg_build_flac_headers(st->codec, oggstream, + if (st->codecpar->codec_id == AV_CODEC_ID_FLAC) { + int err = ogg_build_flac_headers(st->codecpar, oggstream, s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { @@ -466,8 +469,8 @@ static int ogg_write_header(AVFormatContext *s) av_freep(&st->priv_data); return err; } - } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) { - int err = ogg_build_speex_headers(st->codec, oggstream, + } else if (st->codecpar->codec_id == AV_CODEC_ID_SPEEX) { + int err = ogg_build_speex_headers(st->codecpar, oggstream, s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { @@ -475,8 +478,8 @@ static int ogg_write_header(AVFormatContext *s) av_freep(&st->priv_data); return err; } - } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) { - int err = ogg_build_opus_headers(st->codec, oggstream, + } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { + int err = ogg_build_opus_headers(st->codecpar, oggstream, s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { @@ -486,12 +489,12 @@ static int ogg_write_header(AVFormatContext *s) } } else { uint8_t *p; - const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora"; - int header_type = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81; - int framing_bit = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0; + const char *cstr = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora"; + int header_type = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81; + int framing_bit = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0; - if (avpriv_split_xiph_headers(st->codec->extradata, st->codec->extradata_size, - st->codec->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42, + if (avpriv_split_xiph_headers(st->codecpar->extradata, st->codecpar->extradata_size, + st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42, oggstream->header, oggstream->header_len) < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); av_freep(&st->priv_data); @@ -508,7 +511,7 @@ static int ogg_write_header(AVFormatContext *s) bytestream_put_byte(&p, header_type); bytestream_put_buffer(&p, cstr, 6); - if (st->codec->codec_id == AV_CODEC_ID_THEORA) { + if (st->codecpar->codec_id == AV_CODEC_ID_THEORA) { /** KFGSHIFT is the width of the less significant section of the granule position The less significant section is the frame count since the last keyframe */ oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5); @@ -530,7 +533,7 @@ static int ogg_write_header(AVFormatContext *s) AVStream *st = s->streams[j]; OGGStreamContext *oggstream = st->priv_data; for (i = 1; i < 3; i++) { - if (oggstream && oggstream->header_len[i]) + if (oggstream->header_len[i]) ogg_buffer_data(s, st, oggstream->header[i], oggstream->header_len[i], 0, 1); } @@ -551,7 +554,7 @@ static int ogg_write_packet_internal(AVFormatContext *s, AVPacket *pkt) int ret; int64_t granule; - if (st->codec->codec_id == AV_CODEC_ID_THEORA) { + if (st->codecpar->codec_id == AV_CODEC_ID_THEORA) { int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration; int pframe_count; if (pkt->flags & AV_PKT_FLAG_KEY) @@ -563,8 +566,11 @@ static int ogg_write_packet_internal(AVFormatContext *s, AVPacket *pkt) pframe_count = 0; } granule = (oggstream->last_kf_pts<kfgshift) | pframe_count; - } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) - granule = pkt->pts + pkt->duration + av_rescale_q(st->codec->delay, (AVRational){ 1, st->codec->sample_rate }, st->time_base); + } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) + granule = pkt->pts + pkt->duration + + av_rescale_q(st->codecpar->initial_padding, + (AVRational){ 1, st->codecpar->sample_rate }, + st->time_base); else granule = pkt->pts + pkt->duration; @@ -616,9 +622,9 @@ static int ogg_write_trailer(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; OGGStreamContext *oggstream = st->priv_data; - if (st->codec->codec_id == AV_CODEC_ID_FLAC || - st->codec->codec_id == AV_CODEC_ID_SPEEX || - st->codec->codec_id == AV_CODEC_ID_OPUS) { + if (st->codecpar->codec_id == AV_CODEC_ID_FLAC || + st->codecpar->codec_id == AV_CODEC_ID_SPEEX || + st->codecpar->codec_id == AV_CODEC_ID_OPUS) { av_free(oggstream->header[0]); } av_freep(&oggstream->header[1]); @@ -627,11 +633,13 @@ static int ogg_write_trailer(AVFormatContext *s) return 0; } +#if CONFIG_OGG_MUXER +OGG_CLASS(ogg) AVOutputFormat ff_ogg_muxer = { .name = "ogg", .long_name = NULL_IF_CONFIG_SMALL("Ogg"), .mime_type = "application/ogg", - .extensions = "ogg,ogv,spx,opus", + .extensions = "ogg,ogv", .priv_data_size = sizeof(OGGContext), .audio_codec = CONFIG_LIBVORBIS_ENCODER ? AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC, @@ -642,3 +650,56 @@ AVOutputFormat ff_ogg_muxer = { .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, .priv_class = &ogg_muxer_class, }; +#endif + +#if CONFIG_OGA_MUXER +OGG_CLASS(oga) +AVOutputFormat ff_oga_muxer = { + .name = "oga", + .long_name = NULL_IF_CONFIG_SMALL("Ogg Audio"), + .mime_type = "audio/ogg", + .extensions = "oga", + .priv_data_size = sizeof(OGGContext), + .audio_codec = CONFIG_LIBVORBIS_ENCODER ? + AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC, + .write_header = ogg_write_header, + .write_packet = ogg_write_packet, + .write_trailer = ogg_write_trailer, + .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .priv_class = &oga_muxer_class, +}; +#endif + +#if CONFIG_SPX_MUXER +OGG_CLASS(spx) +AVOutputFormat ff_spx_muxer = { + .name = "spx", + .long_name = NULL_IF_CONFIG_SMALL("Ogg Speex"), + .mime_type = "audio/ogg", + .extensions = "spx", + .priv_data_size = sizeof(OGGContext), + .audio_codec = AV_CODEC_ID_SPEEX, + .write_header = ogg_write_header, + .write_packet = ogg_write_packet, + .write_trailer = ogg_write_trailer, + .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .priv_class = &spx_muxer_class, +}; +#endif + +#if CONFIG_OPUS_MUXER +OGG_CLASS(opus) +AVOutputFormat ff_opus_muxer = { + .name = "opus", + .long_name = NULL_IF_CONFIG_SMALL("Ogg Opus"), + .mime_type = "audio/ogg", + .extensions = "opus", + .priv_data_size = sizeof(OGGContext), + .audio_codec = AV_CODEC_ID_OPUS, + .write_header = ogg_write_header, + .write_packet = ogg_write_packet, + .write_trailer = ogg_write_trailer, + .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .priv_class = &opus_muxer_class, +}; +#endif diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c index 7084e76..291a6b5 100644 --- a/libavformat/oggparsecelt.c +++ b/libavformat/oggparsecelt.c @@ -47,7 +47,7 @@ static int celt_header(AVFormatContext *s, int idx) uint8_t *extradata; extradata = av_malloc(2 * sizeof(uint32_t) + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); priv = av_malloc(sizeof(struct oggcelt_private)); if (!extradata || !priv) { av_free(extradata); @@ -62,13 +62,13 @@ static int celt_header(AVFormatContext *s, int idx) /* unused bytes per packet field skipped */ extra_headers = AV_RL32(p + 56); av_free(os->private); - av_free(st->codec->extradata); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_CELT; - st->codec->sample_rate = sample_rate; - st->codec->channels = nb_channels; - st->codec->extradata = extradata; - st->codec->extradata_size = 2 * sizeof(uint32_t); + av_free(st->codecpar->extradata); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_CELT; + st->codecpar->sample_rate = sample_rate; + st->codecpar->channels = nb_channels; + st->codecpar->extradata = extradata; + st->codecpar->extradata_size = 2 * sizeof(uint32_t); if (sample_rate) avpriv_set_pts_info(st, 64, 1, sample_rate); priv->extra_headers_left = 1 + extra_headers; diff --git a/libavformat/oggparsedirac.c b/libavformat/oggparsedirac.c index 55a0b59..b0a3796 100644 --- a/libavformat/oggparsedirac.c +++ b/libavformat/oggparsedirac.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/get_bits.h" +#include "libavutil/intreadwrite.h" #include "libavcodec/dirac.h" #include "avformat.h" #include "internal.h" @@ -29,25 +29,38 @@ static int dirac_header(AVFormatContext *s, int idx) struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; - dirac_source_params source; - GetBitContext gb; + AVDiracSeqHeader *dsh; + int ret; // already parsed the header - if (st->codec->codec_id == AV_CODEC_ID_DIRAC) + if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC) return 0; - init_get_bits(&gb, os->buf + os->pstart + 13, (os->psize - 13) * 8); - if (avpriv_dirac_parse_sequence_header(st->codec, &gb, &source) < 0) - return -1; + ret = av_dirac_parse_sequence_header(&dsh, os->buf + os->pstart + 13, (os->psize - 13) * 8, s); + if (ret < 0) + return ret; + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DIRAC; + st->codecpar->width = dsh->width; + st->codecpar->height = dsh->height; + st->codecpar->format = dsh->pix_fmt; + st->codecpar->color_range = dsh->color_range; + st->codecpar->color_trc = dsh->color_trc; + st->codecpar->color_primaries = dsh->color_primaries; + st->codecpar->color_space = dsh->colorspace; + st->codecpar->profile = dsh->profile; + st->codecpar->level = dsh->level; + + // Dirac in Ogg always stores timestamps as though the video were interlaced + avpriv_set_pts_info(st, 64, dsh->framerate.den, 2 * dsh->framerate.num); + + av_freep(&dsh); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DIRAC; - // dirac in ogg always stores timestamps as though the video were interlaced - avpriv_set_pts_info(st, 64, st->codec->time_base.num, 2*st->codec->time_base.den); return 1; } -// various undocument things: granule is signed (only for dirac!) +// various undocumented things: granule is signed (only for Dirac!) static uint64_t dirac_gptopts(AVFormatContext *s, int idx, uint64_t granule, int64_t *dts_out) { @@ -78,8 +91,8 @@ static int old_dirac_header(AVFormatContext *s, int idx) if (buf[0] != 'K') return 0; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DIRAC; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_DIRAC; avpriv_set_pts_info(st, 64, AV_RB32(buf+12), AV_RB32(buf+8)); return 1; } diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index f9c15f9..dab1040 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -34,7 +34,6 @@ flac_header (AVFormatContext * s, int idx) struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; GetBitContext gb; - FLACStreaminfo si; int mdt; if (os->buf[os->pstart] == 0xff) @@ -46,6 +45,8 @@ flac_header (AVFormatContext * s, int idx) if (mdt == OGG_FLAC_METADATA_TYPE_STREAMINFO) { uint8_t *streaminfo_start = os->buf + os->pstart + 5 + 4 + 4 + 4; + uint32_t samplerate; + skip_bits_long(&gb, 4*8); /* "FLAC" */ if(get_bits(&gb, 8) != 1) /* unsupported major version */ return -1; @@ -56,18 +57,20 @@ flac_header (AVFormatContext * s, int idx) if (get_bits_long(&gb, 32) != FLAC_STREAMINFO_SIZE) return -1; - avpriv_flac_parse_streaminfo(st->codec, &si, streaminfo_start); - - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_FLAC; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_FLAC; st->need_parsing = AVSTREAM_PARSE_HEADERS; - st->codec->extradata = - av_malloc(FLAC_STREAMINFO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(st->codec->extradata, streaminfo_start, FLAC_STREAMINFO_SIZE); - st->codec->extradata_size = FLAC_STREAMINFO_SIZE; + st->codecpar->extradata = + av_malloc(FLAC_STREAMINFO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(st->codecpar->extradata, streaminfo_start, FLAC_STREAMINFO_SIZE); + st->codecpar->extradata_size = FLAC_STREAMINFO_SIZE; + + samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4; + if (!samplerate) + return AVERROR_INVALIDDATA; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, samplerate); } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 4, os->psize - 4); } @@ -79,8 +82,8 @@ static int old_flac_header (AVFormatContext * s, int idx) { AVStream *st = s->streams[idx]; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_FLAC; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_FLAC; return 0; } diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 913282a..6278465 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -23,9 +23,11 @@ **/ #include + #include "libavutil/intreadwrite.h" -#include "libavcodec/get_bits.h" + #include "libavcodec/bytestream.h" + #include "avformat.h" #include "internal.h" #include "oggdec.h" @@ -50,24 +52,24 @@ ogm_header(AVFormatContext *s, int idx) if (bytestream2_peek_byte(&p) == 'v'){ int tag; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; bytestream2_skip(&p, 8); tag = bytestream2_get_le32(&p); - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); - st->codec->codec_tag = tag; + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); + st->codecpar->codec_tag = tag; } else if (bytestream2_peek_byte(&p) == 't') { - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = AV_CODEC_ID_TEXT; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_TEXT; bytestream2_skip(&p, 12); } else { uint8_t acid[5] = { 0 }; int cid; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; bytestream2_skip(&p, 8); bytestream2_get_buffer(&p, acid, 4); acid[4] = 0; cid = strtol(acid, NULL, 16); - st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid); + st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid); st->need_parsing = AVSTREAM_PARSE_FULL; } @@ -83,16 +85,16 @@ ogm_header(AVFormatContext *s, int idx) bytestream2_skip(&p, 4); /* default_len */ bytestream2_skip(&p, 8); /* buffersize + bits_per_sample */ - if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ - st->codec->width = bytestream2_get_le32(&p); - st->codec->height = bytestream2_get_le32(&p); + if(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ + st->codecpar->width = bytestream2_get_le32(&p); + st->codecpar->height = bytestream2_get_le32(&p); avpriv_set_pts_info(st, 64, time_unit, spu * 10000000); } else { - st->codec->channels = bytestream2_get_le16(&p); + st->codecpar->channels = bytestream2_get_le16(&p); bytestream2_skip(&p, 2); /* block_align */ - st->codec->bit_rate = bytestream2_get_le32(&p) * 8; - st->codec->sample_rate = spu * 10000000 / time_unit; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + st->codecpar->bit_rate = bytestream2_get_le32(&p) * 8; + st->codecpar->sample_rate = spu * 10000000 / time_unit; + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); } } else if (bytestream2_peek_byte(&p) == 3) { bytestream2_skip(&p, 7); @@ -120,17 +122,17 @@ ogm_dshow_header(AVFormatContext *s, int idx) t = AV_RL32(p + 96); if(t == 0x05589f80){ - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68)); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68)); avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000); - st->codec->width = AV_RL32(p + 176); - st->codec->height = AV_RL32(p + 180); + st->codecpar->width = AV_RL32(p + 176); + st->codecpar->height = AV_RL32(p + 180); } else if(t == 0x05589f81){ - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124)); - st->codec->channels = AV_RL16(p + 126); - st->codec->sample_rate = AV_RL32(p + 128); - st->codec->bit_rate = AV_RL32(p + 132) * 8; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124)); + st->codecpar->channels = AV_RL16(p + 126); + st->codecpar->sample_rate = AV_RL32(p + 128); + st->codecpar->bit_rate = AV_RL32(p + 132) * 8; } return 1; diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c index 5931ab5..915ef42 100644 --- a/libavformat/oggparseopus.c +++ b/libavformat/oggparseopus.c @@ -52,20 +52,22 @@ static int opus_header(AVFormatContext *avf, int idx) if (os->psize < OPUS_HEAD_SIZE || (AV_RL8(packet + 8) & 0xF0) != 0) return AVERROR_INVALIDDATA; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_OPUS; - st->codec->channels = AV_RL8(packet + 9); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_OPUS; + st->codecpar->channels = AV_RL8(packet + 9); priv->pre_skip = AV_RL16(packet + 10); - extradata = av_malloc(os->psize + FF_INPUT_BUFFER_PADDING_SIZE); + st->codecpar->initial_padding = priv->pre_skip; + + extradata = av_malloc(os->psize + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) return AVERROR(ENOMEM); memcpy(extradata, packet, os->psize); - st->codec->extradata = extradata; - st->codec->extradata_size = os->psize; + st->codecpar->extradata = extradata; + st->codecpar->extradata_size = os->psize; - st->codec->sample_rate = 48000; + st->codecpar->sample_rate = 48000; avpriv_set_pts_info(st, 64, 1, 48000); priv->need_comments = 1; return 1; diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c index 5333e17..bcbfe73 100644 --- a/libavformat/oggparseskeleton.c +++ b/libavformat/oggparseskeleton.c @@ -34,7 +34,7 @@ static int skeleton_header(AVFormatContext *s, int idx) uint64_t start_granule; int target_idx, start_time; - st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; if (os->psize < 8) return -1; diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c index b2779e7..2430cd7 100644 --- a/libavformat/oggparsespeex.c +++ b/libavformat/oggparsespeex.c @@ -23,11 +23,13 @@ **/ #include + #include "libavutil/bswap.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" -#include "libavcodec/get_bits.h" + #include "libavcodec/bytestream.h" + #include "avformat.h" #include "internal.h" #include "oggdec.h" @@ -47,6 +49,8 @@ static int speex_header(AVFormatContext *s, int idx) { if (!spxp) { spxp = av_mallocz(sizeof(*spxp)); + if (!spxp) + return AVERROR(ENOMEM); os->private = spxp; } @@ -55,29 +59,29 @@ static int speex_header(AVFormatContext *s, int idx) { if (spxp->seq == 0) { int frames_per_packet; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_SPEEX; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_SPEEX; - st->codec->sample_rate = AV_RL32(p + 36); - st->codec->channels = AV_RL32(p + 48); - if (st->codec->channels < 1 || st->codec->channels > 2) { + st->codecpar->sample_rate = AV_RL32(p + 36); + st->codecpar->channels = AV_RL32(p + 48); + if (st->codecpar->channels < 1 || st->codecpar->channels > 2) { av_log(s, AV_LOG_ERROR, "invalid channel count. Speex must be mono or stereo.\n"); return AVERROR_INVALIDDATA; } - st->codec->channel_layout = st->codec->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; spxp->packet_size = AV_RL32(p + 56); frames_per_packet = AV_RL32(p + 64); if (frames_per_packet) spxp->packet_size *= frames_per_packet; - st->codec->extradata_size = os->psize; - st->codec->extradata = av_malloc(st->codec->extradata_size - + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(st->codec->extradata, p, st->codec->extradata_size); + st->codecpar->extradata_size = os->psize; + st->codecpar->extradata = av_malloc(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(st->codecpar->extradata, p, st->codecpar->extradata_size); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); } else ff_vorbis_stream_comment(s, st, p, os->psize); diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index d78f02d..1e7a776 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -41,7 +41,7 @@ static int theora_header(AVFormatContext *s, int idx) struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; TheoraParams *thp = os->private; - int cds = st->codec->extradata_size + os->psize + 2; + int cds = st->codecpar->extradata_size + os->psize + 2; int err; uint8_t *cdp; @@ -72,8 +72,8 @@ static int theora_header(AVFormatContext *s, int idx) return AVERROR(ENOSYS); } - st->codec->width = get_bits(&gb, 16) << 4; - st->codec->height = get_bits(&gb, 16) << 4; + st->codecpar->width = get_bits(&gb, 16) << 4; + st->codecpar->height = get_bits(&gb, 16) << 4; if (thp->version >= 0x030400) skip_bits(&gb, 100); @@ -81,10 +81,10 @@ static int theora_header(AVFormatContext *s, int idx) if (thp->version >= 0x030200) { int width = get_bits_long(&gb, 24); int height = get_bits_long(&gb, 24); - if (width <= st->codec->width && width > st->codec->width - 16 && - height <= st->codec->height && height > st->codec->height - 16) { - st->codec->width = width; - st->codec->height = height; + if (width <= st->codecpar->width && width > st->codecpar->width - 16 && + height <= st->codecpar->height && height > st->codecpar->height - 16) { + st->codecpar->width = width; + st->codecpar->height = height; } skip_bits(&gb, 16); @@ -110,8 +110,8 @@ static int theora_header(AVFormatContext *s, int idx) thp->gpshift = get_bits(&gb, 5); thp->gpmask = (1 << thp->gpshift) - 1; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_THEORA; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_THEORA; st->need_parsing = AVSTREAM_PARSE_HEADERS; } break; @@ -125,16 +125,16 @@ static int theora_header(AVFormatContext *s, int idx) return AVERROR_INVALIDDATA; } - if ((err = av_reallocp(&st->codec->extradata, - cds + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) { - st->codec->extradata_size = 0; + if ((err = av_reallocp(&st->codecpar->extradata, + cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { + st->codecpar->extradata_size = 0; return err; } - cdp = st->codec->extradata + st->codec->extradata_size; + cdp = st->codecpar->extradata + st->codecpar->extradata_size; *cdp++ = os->psize >> 8; *cdp++ = os->psize & 0xff; memcpy(cdp, os->buf + os->pstart, os->psize); - st->codec->extradata_size = cds; + st->codecpar->extradata_size = cds; return 1; } diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 6bd1411..95fe082 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -28,9 +28,10 @@ #include "libavutil/base64.h" #include "libavutil/bswap.h" #include "libavutil/dict.h" + #include "libavcodec/bytestream.h" -#include "libavcodec/get_bits.h" #include "libavcodec/vorbis_parser.h" + #include "avformat.h" #include "flac_picture.h" #include "internal.h" @@ -208,7 +209,7 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, struct oggvorbis_private { unsigned int len[3]; unsigned char *packet[3]; - VorbisParseContext vp; + AVVorbisParseContext *vp; int64_t final_pts; int final_duration; }; @@ -234,7 +235,7 @@ static int fixup_vorbis_headers(AVFormatContext *as, offset += priv->len[i]; av_freep(&priv->packet[i]); } - if ((err = av_reallocp(buf, offset + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) + if ((err = av_reallocp(buf, offset + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) return err; return offset; } @@ -245,9 +246,11 @@ static void vorbis_cleanup(AVFormatContext *s, int idx) struct ogg_stream *os = ogg->streams + idx; struct oggvorbis_private *priv = os->private; int i; - if (os->private) + if (os->private) { + av_vorbis_parse_free(&priv->vp); for (i = 0; i < 3; i++) av_freep(&priv->packet[i]); + } } static int vorbis_header(AVFormatContext *s, int idx) @@ -293,10 +296,10 @@ static int vorbis_header(AVFormatContext *s, int idx) if (bytestream_get_le32(&p) != 0) /* vorbis_version */ return AVERROR_INVALIDDATA; - st->codec->channels = bytestream_get_byte(&p); + st->codecpar->channels = bytestream_get_byte(&p); srate = bytestream_get_le32(&p); p += 4; // skip maximum bitrate - st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate + st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate p += 4; // skip minimum bitrate blocksize = bytestream_get_byte(&p); @@ -311,11 +314,11 @@ static int vorbis_header(AVFormatContext *s, int idx) if (bytestream_get_byte(&p) != 1) /* framing_flag */ return AVERROR_INVALIDDATA; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_VORBIS; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_VORBIS; if (srate > 0) { - st->codec->sample_rate = srate; + st->codecpar->sample_rate = srate; avpriv_set_pts_info(st, 64, 1, srate); } } else if (os->buf[os->pstart] == 3) { @@ -337,15 +340,17 @@ static int vorbis_header(AVFormatContext *s, int idx) } } } else { - int ret = fixup_vorbis_headers(s, priv, &st->codec->extradata); + int ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata); if (ret < 0) { - st->codec->extradata_size = 0; + st->codecpar->extradata_size = 0; return ret; } - st->codec->extradata_size = ret; - if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) { - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; + st->codecpar->extradata_size = ret; + + priv->vp = av_vorbis_parse_init(st->codecpar->extradata, st->codecpar->extradata_size); + if (!priv->vp) { + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; return ret; } } @@ -360,6 +365,9 @@ static int vorbis_packet(AVFormatContext *s, int idx) struct oggvorbis_private *priv = os->private; int duration; + if (!priv->vp) + return AVERROR_INVALIDDATA; + /* first packet handling * here we parse the duration of each packet in the first page and compare * the total duration to the page granule to find the encoder delay and @@ -370,11 +378,11 @@ static int vorbis_packet(AVFormatContext *s, int idx) uint8_t *next_pkt = last_pkt; int first_duration = 0; - avpriv_vorbis_parse_reset(&priv->vp); + av_vorbis_parse_reset(priv->vp); duration = 0; for (seg = 0; seg < os->nsegs; seg++) { if (os->segments[seg] < 255) { - int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1); + int d = av_vorbis_parse_frame(priv->vp, last_pkt, 1); if (d < 0) { duration = os->granule; break; @@ -393,12 +401,12 @@ static int vorbis_packet(AVFormatContext *s, int idx) s->streams[idx]->duration -= s->streams[idx]->start_time; s->streams[idx]->cur_dts = AV_NOPTS_VALUE; priv->final_pts = AV_NOPTS_VALUE; - avpriv_vorbis_parse_reset(&priv->vp); + av_vorbis_parse_reset(priv->vp); } /* parse packet duration */ if (os->psize > 0) { - duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1); + duration = av_vorbis_parse_frame(priv->vp, os->buf + os->pstart, 1); if (duration <= 0) { os->pflags |= AV_PKT_FLAG_CORRUPT; return 0; diff --git a/libavformat/oggparsevp8.c b/libavformat/oggparsevp8.c new file mode 100644 index 0000000..f38cc56 --- /dev/null +++ b/libavformat/oggparsevp8.c @@ -0,0 +1,142 @@ +/* + * On2 VP8 parser for Ogg + * Copyright (C) 2013 James Almer + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "internal.h" +#include "oggdec.h" + +#define VP8_HEADER_SIZE 26 + +static int vp8_header(AVFormatContext *s, int idx) +{ + struct ogg *ogg = s->priv_data; + struct ogg_stream *os = ogg->streams + idx; + uint8_t *p = os->buf + os->pstart; + AVStream *st = s->streams[idx]; + AVRational framerate; + + if (os->psize < 7 || p[0] != 0x4f) + return 0; + + switch (p[5]){ + case 0x01: + if (os->psize < VP8_HEADER_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid OggVP8 header packet"); + return AVERROR_INVALIDDATA; + } + + if (p[6] != 1) { + av_log(s, AV_LOG_WARNING, + "Unknown OggVP8 version %d.%d\n", p[6], p[7]); + return AVERROR_INVALIDDATA; + } + + st->codecpar->width = AV_RB16(p + 8); + st->codecpar->height = AV_RB16(p + 10); + st->sample_aspect_ratio.num = AV_RB24(p + 12); + st->sample_aspect_ratio.den = AV_RB24(p + 15); + framerate.num = AV_RB32(p + 18); + framerate.den = AV_RB32(p + 22); + + avpriv_set_pts_info(st, 64, framerate.den, framerate.num); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_VP8; + st->need_parsing = AVSTREAM_PARSE_HEADERS; + break; + case 0x02: + if (p[6] != 0x20) + return AVERROR_INVALIDDATA; + ff_vorbis_stream_comment(s, st, p + 7, os->psize - 7); + break; + default: + av_log(s, AV_LOG_ERROR, "Unknown VP8 header type 0x%02X\n", p[5]); + return AVERROR_INVALIDDATA; + } + + return 1; +} + +static uint64_t vp8_gptopts(AVFormatContext *s, int idx, + uint64_t granule, int64_t *dts) +{ + struct ogg *ogg = s->priv_data; + struct ogg_stream *os = ogg->streams + idx; + + uint64_t pts = (granule >> 32); + uint32_t dist = (granule >> 3) & 0x07ffffff; + + if (!dist) + os->pflags |= AV_PKT_FLAG_KEY; + + if (dts) + *dts = pts; + + return pts; +} + +static int vp8_packet(AVFormatContext *s, int idx) +{ + struct ogg *ogg = s->priv_data; + struct ogg_stream *os = ogg->streams + idx; + uint8_t *p = os->buf + os->pstart; + + if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && + !(os->flags & OGG_FLAG_EOS)) { + int seg; + int duration; + uint8_t *last_pkt = p; + uint8_t *next_pkt; + + seg = os->segp; + duration = (last_pkt[0] >> 4) & 1; + next_pkt = last_pkt += os->psize; + for (; seg < os->nsegs; seg++) { + if (os->segments[seg] < 255) { + duration += (last_pkt[0] >> 4) & 1; + last_pkt = next_pkt + os->segments[seg]; + } + next_pkt += os->segments[seg]; + } + os->lastpts = + os->lastdts = vp8_gptopts(s, idx, os->granule, NULL) - duration; + if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { + s->streams[idx]->start_time = os->lastpts; + if (s->streams[idx]->duration) + s->streams[idx]->duration -= s->streams[idx]->start_time; + } + } + + if (os->psize > 0) + os->pduration = (p[0] >> 4) & 1; + + return 0; +} + +const struct ogg_codec ff_vp8_codec = { + .magic = "OVP80", + .magicsize = 5, + .header = vp8_header, + .packet = vp8_packet, + .gptopts = vp8_gptopts, + .nb_header = 1, +}; diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 9d9c726..e29b93e 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -47,6 +47,7 @@ #include "internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/des.h" +#include "libavutil/mathematics.h" #include "oma.h" #include "pcm.h" #include "id3v2.h" @@ -73,7 +74,7 @@ typedef struct OMAContext { uint8_t sm_val[8]; uint8_t e_val[8]; uint8_t iv[8]; - struct AVDES av_des; + struct AVDES *av_des; } OMAContext; static void hex_log(AVFormatContext *s, int level, @@ -124,28 +125,34 @@ static int rprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, { OMAContext *oc = s->priv_data; unsigned int pos; - struct AVDES av_des; + struct AVDES *av_des; if (!enc_header || !r_val || size < OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size + oc->i_size || size < OMA_RPROBE_M_VAL) return -1; + av_des = av_des_alloc(); + if (!av_des) + return AVERROR(ENOMEM); + /* m_val */ - av_des_init(&av_des, r_val, 192, 1); - av_des_crypt(&av_des, oc->m_val, &enc_header[48], 1, NULL, 1); + av_des_init(av_des, r_val, 192, 1); + av_des_crypt(av_des, oc->m_val, &enc_header[48], 1, NULL, 1); /* s_val */ - av_des_init(&av_des, oc->m_val, 64, 0); - av_des_crypt(&av_des, oc->s_val, NULL, 1, NULL, 0); + av_des_init(av_des, oc->m_val, 64, 0); + av_des_crypt(av_des, oc->s_val, NULL, 1, NULL, 0); /* sm_val */ pos = OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size; - av_des_init(&av_des, oc->s_val, 64, 0); - av_des_mac(&av_des, oc->sm_val, &enc_header[pos], (oc->i_size >> 3)); + av_des_init(av_des, oc->s_val, 64, 0); + av_des_mac(av_des, oc->sm_val, &enc_header[pos], (oc->i_size >> 3)); pos += oc->i_size; + av_free(av_des); + return memcmp(&enc_header[pos], oc->sm_val, 8) ? -1 : 0; } @@ -155,7 +162,7 @@ static int nprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, OMAContext *oc = s->priv_data; uint64_t pos; uint32_t taglen, datalen; - struct AVDES av_des; + struct AVDES *av_des; if (!enc_header || !n_val || size < OMA_ENC_HEADER_SIZE + oc->k_size + 4) @@ -183,15 +190,22 @@ static int nprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, if (datalen << 4 > size - pos) return -1; - av_des_init(&av_des, n_val, 192, 1); + av_des = av_des_alloc(); + if (!av_des) + return AVERROR(ENOMEM); + + av_des_init(av_des, n_val, 192, 1); while (datalen-- > 0) { - av_des_crypt(&av_des, oc->r_val, &enc_header[pos], 2, NULL, 1); + av_des_crypt(av_des, oc->r_val, &enc_header[pos], 2, NULL, 1); kset(s, oc->r_val, NULL, 16); - if (!rprobe(s, enc_header, size, oc->r_val)) + if (!rprobe(s, enc_header, size, oc->r_val)) { + av_free(av_des); return 0; + } pos += 16; } + av_free(av_des); return -1; } @@ -276,14 +290,18 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) } } + oc->av_des = av_des_alloc(); + if (!oc->av_des) + return AVERROR(ENOMEM); + /* e_val */ - av_des_init(&oc->av_des, oc->m_val, 64, 0); - av_des_crypt(&oc->av_des, oc->e_val, + av_des_init(oc->av_des, oc->m_val, 64, 0); + av_des_crypt(oc->av_des, oc->e_val, &gdata[OMA_ENC_HEADER_SIZE + 40], 1, NULL, 0); hex_log(s, AV_LOG_DEBUG, "EK", oc->e_val, 8); /* init e_val */ - av_des_init(&oc->av_des, oc->e_val, 64, 1); + av_des_init(oc->av_des, oc->e_val, 64, 1); return 0; } @@ -328,10 +346,10 @@ static int oma_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->start_time = 0; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = buf[32]; - st->codec->codec_id = ff_codec_get_id(ff_oma_codec_tags, - st->codec->codec_tag); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = buf[32]; + st->codecpar->codec_id = ff_codec_get_id(ff_oma_codec_tags, + st->codecpar->codec_tag); switch (buf[32]) { case OMA_CODECID_ATRAC3: @@ -348,19 +366,19 @@ static int oma_read_header(AVFormatContext *s) /* get stereo coding mode, 1 for joint-stereo */ jsflag = (codec_params >> 17) & 1; - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = samplerate; - st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = samplerate; + st->codecpar->bit_rate = st->codecpar->sample_rate * framesize * 8 / 1024; /* fake the ATRAC3 extradata * (wav format, makes stream copy to wav work) */ - st->codec->extradata_size = 14; - edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); + st->codecpar->extradata_size = 14; + edata = av_mallocz(14 + AV_INPUT_BUFFER_PADDING_SIZE); if (!edata) return AVERROR(ENOMEM); - st->codec->extradata = edata; + st->codecpar->extradata = edata; AV_WL16(&edata[0], 1); // always 1 AV_WL32(&edata[2], samplerate); // samples rate AV_WL16(&edata[6], jsflag); // coding mode @@ -368,7 +386,7 @@ static int oma_read_header(AVFormatContext *s) AV_WL16(&edata[10], 1); // always 1 // AV_WL16(&edata[12], 0); // always 0 - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); break; case OMA_CODECID_ATRAC3P: channel_id = (codec_params >> 10) & 7; @@ -377,16 +395,16 @@ static int oma_read_header(AVFormatContext *s) "Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id); return AVERROR_INVALIDDATA; } - st->codec->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1]; - st->codec->channels = ff_oma_chid_to_num_channels[channel_id - 1]; + st->codecpar->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1]; + st->codecpar->channels = ff_oma_chid_to_num_channels[channel_id - 1]; framesize = ((codec_params & 0x3FF) * 8) + 8; samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; if (!samplerate) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); return AVERROR_INVALIDDATA; } - st->codec->sample_rate = samplerate; - st->codec->bit_rate = samplerate * framesize * 8 / 2048; + st->codecpar->sample_rate = samplerate; + st->codecpar->bit_rate = samplerate * framesize * 8 / 2048; avpriv_set_pts_info(st, 64, 1, samplerate); break; case OMA_CODECID_MP3: @@ -395,22 +413,22 @@ static int oma_read_header(AVFormatContext *s) break; case OMA_CODECID_LPCM: /* PCM 44.1 kHz 16 bit stereo big-endian */ - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = 44100; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = 44100; framesize = 1024; /* bit rate = sample rate x PCM block align (= 4) x 8 */ - st->codec->bit_rate = st->codec->sample_rate * 32; - st->codec->bits_per_coded_sample = - av_get_bits_per_sample(st->codec->codec_id); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + st->codecpar->bit_rate = st->codecpar->sample_rate * 32; + st->codecpar->bits_per_coded_sample = + av_get_bits_per_sample(st->codecpar->codec_id); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); break; default: av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n", buf[32]); return AVERROR(ENOSYS); } - st->codec->block_align = framesize; + st->codecpar->block_align = framesize; return 0; } @@ -418,9 +436,12 @@ static int oma_read_header(AVFormatContext *s) static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) { - OMAContext *oc = s->priv_data; - int packet_size = s->streams[0]->codec->block_align; - int ret = av_get_packet(s->pb, pkt, packet_size); + OMAContext *oc = s->priv_data; + AVStream *st = s->streams[0]; + int packet_size = st->codecpar->block_align; + int byte_rate = st->codecpar->bit_rate >> 3; + int64_t pos = avio_tell(s->pb); + int ret = av_get_packet(s->pb, pkt, packet_size); if (ret < packet_size) pkt->flags |= AV_PKT_FLAG_CORRUPT; @@ -432,11 +453,17 @@ static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; + if (pos > 0) { + pkt->pts = + pkt->dts = av_rescale(pos, st->time_base.den, + byte_rate * (int64_t)st->time_base.num); + } + if (oc->encrypted) { /* previous unencrypted block saved in IV for * the next packet (CBC mode) */ if (ret == packet_size) - av_des_crypt(&oc->av_des, pkt->data, pkt->data, + av_des_crypt(oc->av_des, pkt->data, pkt->data, (packet_size >> 3), oc->iv, 1); else memset(oc->iv, 0, 8); @@ -492,6 +519,13 @@ wipe: return err; } +static int oma_read_close(AVFormatContext *s) +{ + OMAContext *oc = s->priv_data; + av_free(oc->av_des); + return 0; +} + AVInputFormat ff_oma_demuxer = { .name = "oma", .long_name = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), @@ -500,6 +534,7 @@ AVInputFormat ff_oma_demuxer = { .read_header = oma_read_header, .read_packet = oma_read_packet, .read_seek = oma_read_seek, + .read_close = oma_read_close, .flags = AVFMT_GENERIC_INDEX, .extensions = "oma,omg,aa3", .codec_tag = (const AVCodecTag* const []){ff_oma_codec_tags, 0}, diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index bfd552a..50f369d 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -30,21 +30,21 @@ static av_cold int oma_write_header(AVFormatContext *s) { int i; - AVCodecContext *format; + AVCodecParameters *par; int srate_index; int isjointstereo; - format = s->streams[0]->codec; + par = s->streams[0]->codecpar; /* check for support of the format first */ for (srate_index = 0; ; srate_index++) { if (ff_oma_srate_tab[srate_index] == 0) { av_log(s, AV_LOG_ERROR, "Sample rate %d not supported in OpenMG audio\n", - format->sample_rate); + par->sample_rate); return AVERROR(EINVAL); } - if (ff_oma_srate_tab[srate_index] * 100 == format->sample_rate) + if (ff_oma_srate_tab[srate_index] * 100 == par->sample_rate) break; } @@ -58,16 +58,16 @@ static av_cold int oma_write_header(AVFormatContext *s) for (i = 0; i < 6; i++) avio_wl32(s->pb, 0); /* Padding + DRM id */ - switch(format->codec_tag) { + switch (par->codec_tag) { case OMA_CODECID_ATRAC3: - if (format->channels != 2) { + if (par->channels != 2) { av_log(s, AV_LOG_ERROR, "ATRAC3 in OMA is only supported with 2 channels"); return AVERROR(EINVAL); } - if (format->extradata_size == 14) /* WAV format extradata */ - isjointstereo = format->extradata[6] != 0; - else if(format->extradata_size == 10) /* RM format extradata */ - isjointstereo = format->extradata[8] == 0x12; + if (par->extradata_size == 14) /* WAV format extradata */ + isjointstereo = par->extradata[6] != 0; + else if(par->extradata_size == 10) /* RM format extradata */ + isjointstereo = par->extradata[8] == 0x12; else { av_log(s, AV_LOG_ERROR, "ATRAC3: Unsupported extradata size\n"); return AVERROR(EINVAL); @@ -75,17 +75,17 @@ static av_cold int oma_write_header(AVFormatContext *s) avio_wb32(s->pb, (OMA_CODECID_ATRAC3 << 24) | (isjointstereo << 17) | (srate_index << 13) | - (format->block_align/8)); + (par->block_align/8)); break; case OMA_CODECID_ATRAC3P: avio_wb32(s->pb, (OMA_CODECID_ATRAC3P << 24) | (srate_index << 13) | - (format->channels << 10) | - (format->block_align/8 - 1)); + (par->channels << 10) | + (par->block_align/8 - 1)); break; default: av_log(s, AV_LOG_ERROR, "OMA: unsupported codec tag %d for write\n", - format->codec_tag); + par->codec_tag); } for (i = 0; i < (EA3_HEADER_SIZE - 36)/4; i++) avio_wl32(s->pb, 0); /* Padding */ diff --git a/libavformat/options.c b/libavformat/options.c index a5646df..f0d2c47 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -20,6 +20,9 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "url.h" + +#include "libavutil/internal.h" #include "libavutil/opt.h" /** @@ -27,7 +30,9 @@ * Options definition for AVFormatContext. */ +FF_DISABLE_DEPRECATION_WARNINGS #include "options_table.h" +FF_ENABLE_DEPRECATION_WARNINGS static const char* format_to_name(void* ptr) { @@ -55,7 +60,7 @@ static const AVClass *format_child_class_next(const AVClass *prev) AVOutputFormat *ofmt = NULL; if (!prev) - return &ffio_url_class; + return &ff_avio_class; while ((ifmt = av_iformat_next(ifmt))) if (ifmt->priv_class == prev) @@ -86,12 +91,45 @@ static const AVClass av_format_context_class = { .child_class_next = format_child_class_next, }; +static int io_open_default(AVFormatContext *s, AVIOContext **pb, + const char *url, int flags, AVDictionary **options) +{ + AVDictionary *opts_local = NULL; + int ret; + + if (!options) + options = &opts_local; + + if (s->protocol_whitelist) { + ret = av_dict_set(options, "protocol_whitelist", s->protocol_whitelist, 0); + if (ret < 0) + goto finish; + } + if (s->protocol_blacklist) { + ret = av_dict_set(options, "protocol_blacklist", s->protocol_blacklist, 0); + if (ret < 0) + goto finish; + } + ret = avio_open2(pb, url, flags, &s->interrupt_callback, options); +finish: + av_dict_free(&opts_local); + return ret; +} + +static void io_close_default(AVFormatContext *s, AVIOContext *pb) +{ + avio_close(pb); +} + static void avformat_get_context_defaults(AVFormatContext *s) { memset(s, 0, sizeof(AVFormatContext)); s->av_class = &av_format_context_class; + s->io_open = io_open_default; + s->io_close = io_close_default; + av_opt_set_defaults(s); } @@ -107,6 +145,7 @@ AVFormatContext *avformat_alloc_context(void) avformat_free_context(ic); return NULL; } + ic->internal->offset = AV_NOPTS_VALUE; return ic; } diff --git a/libavformat/options_table.h b/libavformat/options_table.h index ac052c8..b566da6 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -65,6 +65,15 @@ static const AVOption avformat_options[] = { {"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, D|E, "strict"}, {"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, D|E, "strict"}, {"experimental", "allow non-standardized experimental variants", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, D|E, "strict"}, +{"max_ts_probe", "maximum number of packets to read while waiting for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT, { .i64 = 50 }, 0, INT_MAX, D }, +{"avoid_negative_ts", "shift timestamps so they start at 0", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, E, "avoid_negative_ts"}, +{"auto", "enabled when required by target format", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_AUTO }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, +{"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, +{"make_zero", "shift timestamps so they start at 0", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_ZERO }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, +{"protocol_blacklist", "A comma-separated list of blacklisted protocols used for opening files internally by lavf", + OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = "concat" }, .flags = E | D }, +{"protocol_whitelist", "A comma-separated list of whitelisted protocols used for opening files internally by lavf", + OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E | D }, {NULL}, }; diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 650baea..e9b1f88 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -204,16 +204,9 @@ int ff_getnameinfo(const struct sockaddr *sa, int salen, } if (serv && servlen > 0) { - struct servent *ent = NULL; -#if HAVE_GETSERVBYPORT if (!(flags & NI_NUMERICSERV)) - ent = getservbyport(sin->sin_port, flags & NI_DGRAM ? "udp" : "tcp"); -#endif /* HAVE_GETSERVBYPORT */ - - if (ent) - snprintf(serv, servlen, "%s", ent->s_name); - else - snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); + return EAI_FAIL; + snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); } return 0; diff --git a/libavformat/os_support.h b/libavformat/os_support.h index ae8cef7..6cc6d9a 100644 --- a/libavformat/os_support.h +++ b/libavformat/os_support.h @@ -31,24 +31,25 @@ #include -#if defined(_WIN32) && !defined(__MINGW32CE__) -# include -# define lseek(f,p,w) _lseeki64((f), (p), (w)) -# define stat _stati64 -# define fstat(f,s) _fstati64((f), (s)) -#endif /* defined(__MINGW32__) && !defined(__MINGW32CE__) */ - #ifdef _WIN32 #if HAVE_DIRECT_H #include -#elif HAVE_IO_H +#endif +#if HAVE_IO_H #include #endif -#define mkdir(a, b) _mkdir(a) -#else -#include #endif +#if defined(_WIN32) && !defined(__MINGW32CE__) +# include +# undef lseek +# define lseek(f,p,w) _lseeki64((f), (p), (w)) +# undef stat +# define stat _stati64 +# undef fstat +# define fstat(f,s) _fstati64((f), (s)) +#endif /* defined(_WIN32) && !defined(__MINGW32CE__) */ + static inline int is_dos_path(const char *path) { #if HAVE_DOS_PATHS @@ -121,4 +122,99 @@ int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout); #endif /* HAVE_POLL_H */ #endif /* CONFIG_NETWORK */ +#if defined(__MINGW32CE__) +#define mkdir(a, b) _mkdir(a) +#elif defined(_WIN32) +#include +#include +#include "libavutil/wchar_filename.h" + +#ifdef WINAPI_FAMILY +#include +// If a WINAPI_FAMILY is defined, check that the desktop API subset +// is enabled +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#define USE_MOVEFILEEXA +#endif +#else +// If no WINAPI_FAMILY is defined, assume the full API subset +#define USE_MOVEFILEEXA +#endif + +#define DEF_FS_FUNCTION(name, wfunc, afunc) \ +static inline int win32_##name(const char *filename_utf8) \ +{ \ + wchar_t *filename_w; \ + int ret; \ + \ + if (utf8towchar(filename_utf8, &filename_w)) \ + return -1; \ + if (!filename_w) \ + goto fallback; \ + \ + ret = wfunc(filename_w); \ + av_free(filename_w); \ + return ret; \ + \ +fallback: \ + /* filename may be be in CP_ACP */ \ + return afunc(filename_utf8); \ +} + +DEF_FS_FUNCTION(unlink, _wunlink, _unlink) +DEF_FS_FUNCTION(mkdir, _wmkdir, _mkdir) +DEF_FS_FUNCTION(rmdir, _wrmdir , _rmdir) + +static inline int win32_rename(const char *src_utf8, const char *dest_utf8) +{ + wchar_t *src_w, *dest_w; + int ret; + + if (utf8towchar(src_utf8, &src_w)) + return -1; + if (utf8towchar(dest_utf8, &dest_w)) { + av_free(src_w); + return -1; + } + if (!src_w || !dest_w) { + av_free(src_w); + av_free(dest_w); + goto fallback; + } + + ret = MoveFileExW(src_w, dest_w, MOVEFILE_REPLACE_EXISTING); + av_free(src_w); + av_free(dest_w); + // Lacking proper mapping from GetLastError() error codes to errno codes + if (ret) + errno = EPERM; + return ret; + +fallback: + /* filename may be be in CP_ACP */ +#ifdef USE_MOVEFILEEXA + ret = MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING); + if (ret) + errno = EPERM; +#else + /* Windows Phone doesn't have MoveFileExA, and for Windows Store apps, + * it is available but not allowed by the app certification kit. However, + * it's unlikely that anybody would input filenames in CP_ACP there, so this + * fallback is kept mostly for completeness. Alternatively we could + * do MultiByteToWideChar(CP_ACP) and use MoveFileExW, but doing + * explicit conversions with CP_ACP is allegedly forbidden in windows + * store apps (or windows phone), and the notion of a native code page + * doesn't make much sense there. */ + ret = rename(src_utf8, dest_utf8); +#endif + return ret; +} + +#define mkdir(a, b) win32_mkdir(a) +#define rename win32_rename +#define rmdir win32_rmdir +#define unlink win32_unlink + +#endif + #endif /* AVFORMAT_OS_SUPPORT_H */ diff --git a/libavformat/paf.c b/libavformat/paf.c index 18bf353..81a45ce 100644 --- a/libavformat/paf.c +++ b/libavformat/paf.c @@ -28,7 +28,7 @@ #define PAF_SOUND_SAMPLES 2205 #define PAF_SOUND_FRAME_SIZE ((256 + PAF_SOUND_SAMPLES) * 2) -typedef struct { +typedef struct PAFDemuxContext { uint32_t buffer_size; uint32_t frame_blks; uint32_t nb_frames; @@ -106,13 +106,13 @@ static int read_header(AVFormatContext *s) p->nb_frames = avio_rl32(pb); avio_skip(pb, 4); - vst->codec->width = avio_rl32(pb); - vst->codec->height = avio_rl32(pb); + vst->codecpar->width = avio_rl32(pb); + vst->codecpar->height = avio_rl32(pb); avio_skip(pb, 4); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_tag = 0; - vst->codec->codec_id = AV_CODEC_ID_PAF_VIDEO; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_tag = 0; + vst->codecpar->codec_id = AV_CODEC_ID_PAF_VIDEO; avpriv_set_pts_info(vst, 64, 1, 10); ast = avformat_new_stream(s, 0); @@ -120,12 +120,12 @@ static int read_header(AVFormatContext *s) return AVERROR(ENOMEM); ast->start_time = 0; - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_tag = 0; - ast->codec->codec_id = AV_CODEC_ID_PAF_AUDIO; - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; - ast->codec->sample_rate = 22050; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_tag = 0; + ast->codecpar->codec_id = AV_CODEC_ID_PAF_AUDIO; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->sample_rate = 22050; avpriv_set_pts_info(ast, 64, 1, 22050); p->buffer_size = avio_rl32(pb); diff --git a/libavformat/pcm.c b/libavformat/pcm.c index 892e8ca..c506edd 100644 --- a/libavformat/pcm.c +++ b/libavformat/pcm.c @@ -21,6 +21,7 @@ #include "libavutil/mathematics.h" #include "avformat.h" +#include "internal.h" #include "pcm.h" int ff_pcm_read_seek(AVFormatContext *s, @@ -32,10 +33,10 @@ int ff_pcm_read_seek(AVFormatContext *s, 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; + block_align = st->codecpar->block_align ? st->codecpar->block_align : + (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3; + byte_rate = st->codecpar->bit_rate ? st->codecpar->bit_rate >> 3 : + block_align * st->codecpar->sample_rate; if (block_align <= 0 || byte_rate <= 0) return -1; @@ -50,7 +51,7 @@ int ff_pcm_read_seek(AVFormatContext *s, /* recompute exact position */ st->cur_dts = av_rescale(pos, st->time_base.den, byte_rate * (int64_t)st->time_base.num); - if ((ret = avio_seek(s->pb, pos + s->data_offset, SEEK_SET)) < 0) + if ((ret = avio_seek(s->pb, pos + s->internal->data_offset, SEEK_SET)) < 0) return ret; return 0; } diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c index 1bbbc66..69789b6 100644 --- a/libavformat/pcmdec.c +++ b/libavformat/pcmdec.c @@ -43,20 +43,20 @@ static int pcm_read_header(AVFormatContext *s) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; - st->codec->sample_rate = s1->sample_rate; - st->codec->channels = s1->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->iformat->raw_codec_id; + st->codecpar->sample_rate = s1->sample_rate; + st->codecpar->channels = s1->channels; - st->codec->bits_per_coded_sample = - av_get_bits_per_sample(st->codec->codec_id); + st->codecpar->bits_per_coded_sample = + av_get_bits_per_sample(st->codecpar->codec_id); - assert(st->codec->bits_per_coded_sample > 0); + assert(st->codecpar->bits_per_coded_sample > 0); - st->codec->block_align = - st->codec->bits_per_coded_sample * st->codec->channels / 8; + st->codecpar->block_align = + st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; } @@ -65,7 +65,7 @@ static int pcm_read_packet(AVFormatContext *s, AVPacket *pkt) int ret, size, bps; // AVStream *st = s->streams[0]; - size= RAW_SAMPLES*s->streams[0]->codec->block_align; + size= RAW_SAMPLES*s->streams[0]->codecpar->block_align; ret= av_get_packet(s->pb, pkt, size); @@ -73,14 +73,14 @@ static int pcm_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; - bps= av_get_bits_per_sample(s->streams[0]->codec->codec_id); + bps= av_get_bits_per_sample(s->streams[0]->codecpar->codec_id); if (!bps) { av_log(s, AV_LOG_ERROR, "Unknown number of bytes per sample.\n"); return AVERROR(EINVAL); } pkt->dts= - pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codec->channels); + pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codecpar->channels); return ret; } diff --git a/libavformat/pmpdec.c b/libavformat/pmpdec.c index 8ae147f..e2709bb 100644 --- a/libavformat/pmpdec.c +++ b/libavformat/pmpdec.c @@ -52,22 +52,22 @@ static int pmp_header(AVFormatContext *s) AVStream *vst = avformat_new_stream(s, NULL); if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; avio_skip(pb, 8); switch (avio_rl32(pb)) { case 0: - vst->codec->codec_id = AV_CODEC_ID_MPEG4; + vst->codecpar->codec_id = AV_CODEC_ID_MPEG4; break; case 1: - vst->codec->codec_id = AV_CODEC_ID_H264; + vst->codecpar->codec_id = AV_CODEC_ID_H264; break; default: av_log(s, AV_LOG_ERROR, "Unsupported video format\n"); break; } index_cnt = avio_rl32(pb); - vst->codec->width = avio_rl32(pb); - vst->codec->height = avio_rl32(pb); + vst->codecpar->width = avio_rl32(pb); + vst->codecpar->height = avio_rl32(pb); tb_num = avio_rl32(pb); tb_den = avio_rl32(pb); @@ -95,10 +95,10 @@ static int pmp_header(AVFormatContext *s) AVStream *ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = audio_codec_id; - ast->codec->channels = channels; - ast->codec->sample_rate = srate; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = audio_codec_id; + ast->codecpar->channels = channels; + ast->codecpar->sample_rate = srate; avpriv_set_pts_info(ast, 32, 1, srate); } pos = avio_tell(pb) + 4 * index_cnt; diff --git a/libavformat/protocols.c b/libavformat/protocols.c new file mode 100644 index 0000000..d254540 --- /dev/null +++ b/libavformat/protocols.c @@ -0,0 +1,120 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/avstring.h" +#include "libavutil/mem.h" + +#include "url.h" + +extern const URLProtocol ff_concat_protocol; +extern const URLProtocol ff_crypto_protocol; +extern const URLProtocol ff_ffrtmpcrypt_protocol; +extern const URLProtocol ff_ffrtmphttp_protocol; +extern const URLProtocol ff_file_protocol; +extern const URLProtocol ff_gopher_protocol; +extern const URLProtocol ff_hls_protocol; +extern const URLProtocol ff_http_protocol; +extern const URLProtocol ff_httpproxy_protocol; +extern const URLProtocol ff_https_protocol; +extern const URLProtocol ff_icecast_protocol; +extern const URLProtocol ff_mmsh_protocol; +extern const URLProtocol ff_mmst_protocol; +extern const URLProtocol ff_md5_protocol; +extern const URLProtocol ff_pipe_protocol; +extern const URLProtocol ff_rtmp_protocol; +extern const URLProtocol ff_rtmpe_protocol; +extern const URLProtocol ff_rtmps_protocol; +extern const URLProtocol ff_rtmpt_protocol; +extern const URLProtocol ff_rtmpte_protocol; +extern const URLProtocol ff_rtmpts_protocol; +extern const URLProtocol ff_rtp_protocol; +extern const URLProtocol ff_sctp_protocol; +extern const URLProtocol ff_srtp_protocol; +extern const URLProtocol ff_tcp_protocol; +extern const URLProtocol ff_tls_gnutls_protocol; +extern const URLProtocol ff_tls_openssl_protocol; +extern const URLProtocol ff_udp_protocol; +extern const URLProtocol ff_unix_protocol; +extern const URLProtocol ff_librtmp_protocol; +extern const URLProtocol ff_librtmpe_protocol; +extern const URLProtocol ff_librtmps_protocol; +extern const URLProtocol ff_librtmpt_protocol; +extern const URLProtocol ff_librtmpte_protocol; + +#include "libavformat/protocol_list.c" + +const AVClass *ff_urlcontext_child_class_next(const AVClass *prev) +{ + int i; + + /* find the protocol that corresponds to prev */ + for (i = 0; url_protocols[i]; i++) { + if (url_protocols[i]->priv_data_class == prev) { + i++; + break; + } + } + + /* find next protocol with priv options */ + for (; url_protocols[i]; i++) + if (url_protocols[i]->priv_data_class) + return url_protocols[i]->priv_data_class; + return NULL; +} + + +const char *avio_enum_protocols(void **opaque, int output) +{ + const URLProtocol **p = *opaque; + + p = p ? p + 1 : url_protocols; + *opaque = p; + if (!*p) { + *opaque = NULL; + return NULL; + } + if ((output && (*p)->url_write) || (!output && (*p)->url_read)) + return (*p)->name; + return avio_enum_protocols(opaque, output); +} + +const URLProtocol **ffurl_get_protocols(const char *whitelist, + const char *blacklist) +{ + const URLProtocol **ret; + int i, ret_idx = 0; + + ret = av_mallocz_array(FF_ARRAY_ELEMS(url_protocols), sizeof(*ret)); + if (!ret) + return NULL; + + for (i = 0; url_protocols[i]; i++) { + const URLProtocol *up = url_protocols[i]; + + if (whitelist && *whitelist && !av_match_name(up->name, whitelist)) + continue; + if (blacklist && *blacklist && av_match_name(up->name, blacklist)) + continue; + + ret[ret_idx++] = up; + } + + return ret; +} diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c index e662ed7..6897f26 100644 --- a/libavformat/psxstr.c +++ b/libavformat/psxstr.c @@ -1,6 +1,6 @@ /* * Sony Playstation (PSX) STR File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -171,11 +171,11 @@ static int str_read_packet(AVFormatContext *s, str->channels[channel].video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MDEC; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = AV_RL16(§or[0x28]); - st->codec->height = AV_RL16(§or[0x2A]); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MDEC; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = AV_RL16(§or[0x28]); + st->codecpar->height = AV_RL16(§or[0x2A]); } /* if this is the first sector of the frame, allocate a pkt */ @@ -184,7 +184,7 @@ static int str_read_packet(AVFormatContext *s, if(pkt->size != sector_count*VIDEO_DATA_CHUNK_SIZE){ if(pkt->data) av_log(s, AV_LOG_ERROR, "missmatching sector_count\n"); - av_free_packet(pkt); + av_packet_unref(pkt); if (av_new_packet(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE)) return AVERROR(EIO); @@ -203,11 +203,6 @@ static int str_read_packet(AVFormatContext *s, pkt->data= NULL; pkt->size= -1; pkt->buf = NULL; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - pkt->destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif return 0; } @@ -224,22 +219,22 @@ FF_ENABLE_DEPRECATION_WARNINGS str->channels[channel].audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_XA; - st->codec->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA; + st->codecpar->codec_tag = 0; /* no fourcc */ if (fmt & 1) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - st->codec->sample_rate = (fmt&4)?18900:37800; - // st->codec->bit_rate = 0; //FIXME; - st->codec->block_align = 128; + st->codecpar->sample_rate = (fmt&4)?18900:37800; + // st->codecpar->bit_rate = 0; //FIXME; + st->codecpar->block_align = 128; - avpriv_set_pts_info(st, 64, 18 * 224 / st->codec->channels, - st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->channels, + st->codecpar->sample_rate); st->start_time = 0; } pkt = ret_pkt; @@ -268,7 +263,7 @@ static int str_read_close(AVFormatContext *s) int i; for(i=0; i<32; i++){ if(str->channels[i].tmp_pkt.data) - av_free_packet(&str->channels[i].tmp_pkt); + av_packet_unref(&str->channels[i].tmp_pkt); } return 0; diff --git a/libavformat/pva.c b/libavformat/pva.c index 3abfc18..458d219 100644 --- a/libavformat/pva.c +++ b/libavformat/pva.c @@ -28,7 +28,7 @@ #define PVA_AUDIO_PAYLOAD 0x02 #define PVA_MAGIC (('A' << 8) + 'V') -typedef struct { +typedef struct PVAContext { int continue_pes; } PVAContext; @@ -46,16 +46,16 @@ static int pva_read_header(AVFormatContext *s) { if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2VIDEO; st->need_parsing = AVSTREAM_PARSE_FULL; avpriv_set_pts_info(st, 32, 1, 90000); av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME); if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MP2; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MP2; st->need_parsing = AVSTREAM_PARSE_FULL; avpriv_set_pts_info(st, 33, 1, 90000); av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME); diff --git a/libavformat/qcp.c b/libavformat/qcp.c index 30d362f..4069dbe 100644 --- a/libavformat/qcp.c +++ b/libavformat/qcp.c @@ -31,7 +31,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" -typedef struct { +typedef struct QCPContext { uint32_t data_size; ///< size of data chunk #define QCP_MAX_MODE 4 @@ -95,12 +95,12 @@ static int qcp_read_header(AVFormatContext *s) avio_rb32(pb); // "RIFF" avio_skip(pb, 4 + 8 + 4 + 1 + 1); // filesize + "QLCMfmt " + chunk-size + major-version + minor-version - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; avio_read(pb, buf, 16); if (is_qcelp_13k_guid(buf)) { - st->codec->codec_id = AV_CODEC_ID_QCELP; + st->codecpar->codec_id = AV_CODEC_ID_QCELP; } else if (!memcmp(buf, guid_evrc, 16)) { av_log(s, AV_LOG_ERROR, "EVRC codec is not supported.\n"); return AVERROR_PATCHWELCOME; @@ -112,11 +112,11 @@ static int qcp_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } avio_skip(pb, 2 + 80); // codec-version + codec-name - st->codec->bit_rate = avio_rl16(pb); + st->codecpar->bit_rate = avio_rl16(pb); s->packet_size = avio_rl16(pb); avio_skip(pb, 2); // block-size - st->codec->sample_rate = avio_rl16(pb); + st->codecpar->sample_rate = avio_rl16(pb); avio_skip(pb, 2); // sample-size memset(c->rates_per_mode, -1, sizeof(c->rates_per_mode)); diff --git a/libavformat/r3d.c b/libavformat/r3d.c index 74a1f2b..4b28379 100644 --- a/libavformat/r3d.c +++ b/libavformat/r3d.c @@ -25,13 +25,15 @@ #include "avformat.h" #include "internal.h" -typedef struct { +typedef struct R3DContext { unsigned video_offsets_count; unsigned *video_offsets; unsigned rdvo_offset; + + int audio_channels; } R3DContext; -typedef struct { +typedef struct Atom { unsigned size; uint32_t tag; uint64_t offset; @@ -44,7 +46,7 @@ static int read_atom(AVFormatContext *s, Atom *atom) if (atom->size < 8) return -1; atom->tag = avio_rl32(s->pb); - av_dlog(s, "atom %u %.4s offset %#"PRIx64"\n", + av_log(s, AV_LOG_TRACE, "atom %u %.4s offset %#"PRIx64"\n", atom->size, (char*)&atom->tag, atom->offset); return atom->size; } @@ -52,6 +54,7 @@ static int read_atom(AVFormatContext *s, Atom *atom) static int r3d_read_red1(AVFormatContext *s) { AVStream *st = avformat_new_stream(s, NULL); + R3DContext *r3d = s->priv_data; char filename[258]; int tmp; int av_unused tmp2; @@ -59,29 +62,29 @@ static int r3d_read_red1(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_JPEG2000; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_JPEG2000; tmp = avio_r8(s->pb); // major version tmp2 = avio_r8(s->pb); // minor version - av_dlog(s, "version %d.%d\n", tmp, tmp2); + av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2); tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown1 %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown1 %d\n", tmp); tmp = avio_rb32(s->pb); avpriv_set_pts_info(st, 32, 1, tmp); tmp = avio_rb32(s->pb); // filenum - av_dlog(s, "filenum %d\n", tmp); + av_log(s, AV_LOG_TRACE, "filenum %d\n", tmp); avio_skip(s->pb, 32); // unknown - st->codec->width = avio_rb32(s->pb); - st->codec->height = avio_rb32(s->pb); + st->codecpar->width = avio_rb32(s->pb); + st->codecpar->height = avio_rb32(s->pb); tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown2 %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown2 %d\n", tmp); framerate.num = avio_rb16(s->pb); framerate.den = avio_rb16(s->pb); @@ -89,26 +92,17 @@ static int r3d_read_red1(AVFormatContext *s) st->avg_frame_rate = framerate; } - tmp = avio_r8(s->pb); // audio channels - av_dlog(s, "audio channels %d\n", tmp); - if (tmp > 0) { - AVStream *ast = avformat_new_stream(s, NULL); - if (!ast) - return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_S32BE; - ast->codec->channels = tmp; - avpriv_set_pts_info(ast, 32, 1, st->time_base.den); - } + r3d->audio_channels = avio_r8(s->pb); // audio channels + av_log(s, AV_LOG_TRACE, "audio channels %d\n", tmp); avio_read(s->pb, filename, 257); filename[sizeof(filename)-1] = 0; av_dict_set(&st->metadata, "filename", filename, 0); - av_dlog(s, "filename %s\n", filename); - av_dlog(s, "resolution %dx%d\n", st->codec->width, st->codec->height); - av_dlog(s, "timescale %d\n", st->time_base.den); - av_dlog(s, "frame rate %d/%d\n", + av_log(s, AV_LOG_TRACE, "filename %s\n", filename); + av_log(s, AV_LOG_TRACE, "resolution %dx%d\n", st->codecpar->width, st->codecpar->height); + av_log(s, AV_LOG_TRACE, "timescale %d\n", st->time_base.den); + av_log(s, AV_LOG_TRACE, "frame rate %d/%d\n", framerate.num, framerate.den); return 0; @@ -131,7 +125,7 @@ static int r3d_read_rdvo(AVFormatContext *s, Atom *atom) r3d->video_offsets_count = i; break; } - av_dlog(s, "video offset %d: %#x\n", i, r3d->video_offsets[i]); + av_log(s, AV_LOG_TRACE, "video offset %d: %#x\n", i, r3d->video_offsets[i]); } if (st->avg_frame_rate.num) @@ -139,7 +133,7 @@ static int r3d_read_rdvo(AVFormatContext *s, Atom *atom) (AVRational){st->avg_frame_rate.den, st->avg_frame_rate.num}, st->time_base); - av_dlog(s, "duration %"PRId64"\n", st->duration); + av_log(s, AV_LOG_TRACE, "duration %"PRId64"\n", st->duration); return 0; } @@ -155,10 +149,10 @@ static void r3d_read_reos(AVFormatContext *s) avio_rb32(s->pb); // rdas offset tmp = avio_rb32(s->pb); - av_dlog(s, "num video chunks %d\n", tmp); + av_log(s, AV_LOG_TRACE, "num video chunks %d\n", tmp); tmp = avio_rb32(s->pb); - av_dlog(s, "num audio chunks %d\n", tmp); + av_log(s, AV_LOG_TRACE, "num audio chunks %d\n", tmp); avio_skip(s->pb, 6*4); } @@ -183,8 +177,13 @@ static int r3d_read_header(AVFormatContext *s) return -1; } - s->data_offset = avio_tell(s->pb); - av_dlog(s, "data offset %#"PRIx64"\n", s->data_offset); + /* we cannot create the audio stream now because we do not know the + * sample rate */ + if (r3d->audio_channels) + s->ctx_flags |= AVFMTCTX_NOHEADER; + + s->internal->data_offset = avio_tell(s->pb); + av_log(s, AV_LOG_TRACE, "data offset %#"PRIx64"\n", s->internal->data_offset); if (!s->pb->seekable) return 0; // find REOB/REOF/REOS to load index @@ -210,7 +209,7 @@ static int r3d_read_header(AVFormatContext *s) } out: - avio_seek(s->pb, s->data_offset, SEEK_SET); + avio_seek(s->pb, s->internal->data_offset, SEEK_SET); return 0; } @@ -219,36 +218,36 @@ static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) AVStream *st = s->streams[0]; int tmp; int av_unused tmp2; - uint64_t pos = avio_tell(s->pb); + int64_t pos = avio_tell(s->pb); unsigned dts; int ret; dts = avio_rb32(s->pb); tmp = avio_rb32(s->pb); - av_dlog(s, "frame num %d\n", tmp); + av_log(s, AV_LOG_TRACE, "frame num %d\n", tmp); tmp = avio_r8(s->pb); // major version tmp2 = avio_r8(s->pb); // minor version - av_dlog(s, "version %d.%d\n", tmp, tmp2); + av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2); tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp); if (tmp > 4) { tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp); tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp); tmp = avio_rb32(s->pb); - av_dlog(s, "width %d\n", tmp); + av_log(s, AV_LOG_TRACE, "width %d\n", tmp); tmp = avio_rb32(s->pb); - av_dlog(s, "height %d\n", tmp); + av_log(s, AV_LOG_TRACE, "height %d\n", tmp); tmp = avio_rb32(s->pb); - av_dlog(s, "metadata len %d\n", tmp); + av_log(s, AV_LOG_TRACE, "metadata len %d\n", tmp); } tmp = atom->size - 8 - (avio_tell(s->pb) - pos); if (tmp < 0) @@ -264,24 +263,37 @@ static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) if (st->avg_frame_rate.num) pkt->duration = (uint64_t)st->time_base.den* st->avg_frame_rate.den/st->avg_frame_rate.num; - av_dlog(s, "pkt dts %"PRId64" duration %d\n", pkt->dts, pkt->duration); + av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64"\n", pkt->dts, pkt->duration); return 0; } static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) { - AVStream *st = s->streams[1]; + R3DContext *r3d = s->priv_data; + AVStream *st; int av_unused tmp, tmp2; int samples, size; - uint64_t pos = avio_tell(s->pb); + int64_t pos = avio_tell(s->pb); unsigned dts; int ret; + if (s->nb_streams < 2) { + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; + st->codecpar->channels = r3d->audio_channels; + avpriv_set_pts_info(st, 32, 1, s->streams[0]->time_base.den); + } else { + st = s->streams[1]; + } + dts = avio_rb32(s->pb); - st->codec->sample_rate = avio_rb32(s->pb); - if (st->codec->sample_rate <= 0) { + st->codecpar->sample_rate = avio_rb32(s->pb); + if (st->codecpar->sample_rate <= 0) { av_log(s, AV_LOG_ERROR, "Bad sample rate\n"); return AVERROR_INVALIDDATA; } @@ -289,17 +301,17 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) samples = avio_rb32(s->pb); tmp = avio_rb32(s->pb); - av_dlog(s, "packet num %d\n", tmp); + av_log(s, AV_LOG_TRACE, "packet num %d\n", tmp); tmp = avio_rb16(s->pb); // unknown - av_dlog(s, "unknown %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp); tmp = avio_r8(s->pb); // major version tmp2 = avio_r8(s->pb); // minor version - av_dlog(s, "version %d.%d\n", tmp, tmp2); + av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2); tmp = avio_rb32(s->pb); // unknown - av_dlog(s, "unknown %d\n", tmp); + av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp); size = atom->size - 8 - (avio_tell(s->pb) - pos); if (size < 0) @@ -312,15 +324,16 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) pkt->stream_index = 1; pkt->dts = dts; - pkt->duration = av_rescale(samples, st->time_base.den, st->codec->sample_rate); - av_dlog(s, "pkt dts %"PRId64" duration %d samples %d sample rate %d\n", - pkt->dts, pkt->duration, samples, st->codec->sample_rate); + pkt->duration = av_rescale(samples, st->time_base.den, st->codecpar->sample_rate); + av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64" samples %d sample rate %d\n", + pkt->dts, pkt->duration, samples, st->codecpar->sample_rate); return 0; } static int r3d_read_packet(AVFormatContext *s, AVPacket *pkt) { + R3DContext *r3d = s->priv_data; Atom atom; int err = 0; @@ -337,9 +350,9 @@ static int r3d_read_packet(AVFormatContext *s, AVPacket *pkt) return 0; break; case MKTAG('R','E','D','A'): - if (s->nb_streams < 2) + if (!r3d->audio_channels) return -1; - if (s->streams[1]->discard == AVDISCARD_ALL) + if (s->nb_streams >= 2 && s->streams[1]->discard == AVDISCARD_ALL) goto skip; if (!(err = r3d_read_reda(s, pkt, &atom))) return 0; @@ -370,7 +383,7 @@ static int r3d_seek(AVFormatContext *s, int stream_index, int64_t sample_time, i frame_num = av_rescale_q(sample_time, st->time_base, (AVRational){st->avg_frame_rate.den, st->avg_frame_rate.num}); - av_dlog(s, "seek frame num %d timestamp %"PRId64"\n", + av_log(s, AV_LOG_TRACE, "seek frame num %d timestamp %"PRId64"\n", frame_num, sample_time); if (frame_num < r3d->video_offsets_count) { diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index 65cb6bb..3b1bea6 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -44,12 +44,12 @@ int ff_raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; ret = ffio_read_partial(s->pb, pkt->data, size); if (ret < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } else if (ret < size) { /* initialize end of packet for partial reads to avoid reading * uninitialized data on allowed overreads */ - memset(pkt->data + ret, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(pkt->data + ret, 0, AV_INPUT_BUFFER_PADDING_SIZE); } pkt->size = ret; return ret; @@ -60,8 +60,8 @@ int ff_raw_audio_read_header(AVFormatContext *s) AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = s->iformat->raw_codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->iformat->raw_codec_id; st->need_parsing = AVSTREAM_PARSE_FULL; st->start_time = 0; /* the parameters will be extracted from the compressed bitstream */ @@ -84,8 +84,8 @@ int ff_raw_video_read_header(AVFormatContext *s) goto fail; } - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = s->iformat->raw_codec_id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = s->iformat->raw_codec_id; st->need_parsing = AVSTREAM_PARSE_FULL; if ((ret = av_parse_video_rate(&framerate, s1->framerate)) < 0) { diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index eb50626..60740fb 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -131,6 +131,19 @@ AVOutputFormat ff_g722_muxer = { }; #endif +#if CONFIG_G723_1_MUXER +AVOutputFormat ff_g723_1_muxer = { + .name = "g723_1", + .long_name = NULL_IF_CONFIG_SMALL("raw G.723.1"), + .mime_type = "audio/g723", + .extensions = "tco,rco", + .audio_codec = AV_CODEC_ID_G723_1, + .video_codec = AV_CODEC_ID_NONE, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_H261_MUXER AVOutputFormat ff_h261_muxer = { .name = "h261", @@ -218,11 +231,24 @@ AVOutputFormat ff_mlp_muxer = { }; #endif +#if CONFIG_MP2_MUXER +AVOutputFormat ff_mp2_muxer = { + .name = "mp2", + .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .mime_type = "audio/mpeg", + .extensions = "mp2,m2a,mpa", + .audio_codec = AV_CODEC_ID_MP2, + .video_codec = AV_CODEC_ID_NONE, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_MPEG1VIDEO_MUXER AVOutputFormat ff_mpeg1video_muxer = { .name = "mpeg1video", .long_name = NULL_IF_CONFIG_SMALL("raw MPEG-1 video"), - .mime_type = "video/x-mpeg", + .mime_type = "video/mpeg", .extensions = "mpg,mpeg,m1v", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MPEG1VIDEO, diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 5f372c9..cea1b0b 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" @@ -45,9 +46,9 @@ static int rawvideo_read_header(AVFormatContext *ctx) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ctx->iformat->raw_codec_id; + st->codecpar->codec_id = ctx->iformat->raw_codec_id; if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) { @@ -69,9 +70,9 @@ static int rawvideo_read_header(AVFormatContext *ctx) avpriv_set_pts_info(st, 64, framerate.den, framerate.num); - st->codec->width = width; - st->codec->height = height; - st->codec->pix_fmt = pix_fmt; + st->codecpar->width = width; + st->codecpar->height = height; + st->codecpar->format = pix_fmt; return 0; } @@ -82,10 +83,10 @@ 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; + width = st->codecpar->width; + height = st->codecpar->height; - packet_size = avpicture_get_size(st->codec->pix_fmt, width, height); + packet_size = av_image_get_buffer_size(st->codecpar->format, width, height, 1); if (packet_size < 0) return -1; diff --git a/libavformat/rdt.c b/libavformat/rdt.c index cc30694..eb718cf 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -44,7 +44,7 @@ struct RDTDemuxContext { * in the AVFormatContext, and this variable points to the offset in * that array such that the first is the first stream of this set. */ AVStream **streams; - int n_streams; /**< streams with identifical content in this set */ + int n_streams; /**< streams with identical content in this set */ void *dynamic_protocol_context; DynamicPayloadPacketHandlerProc parse_packet; uint32_t prev_timestamp; @@ -86,7 +86,7 @@ struct PayloadContext { RMStream **rmst; uint8_t *mlti_data; unsigned int mlti_data_size; - char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE]; + char buffer[RTP_MAX_PACKET_LENGTH + AV_INPUT_BUFFER_PADDING_SIZE]; int audio_pkt_cnt; /**< remaining audio packets in rmdec */ }; @@ -98,7 +98,7 @@ ff_rdt_calc_response_and_checksum(char response[41], char chksum[9], unsigned char zres[16], buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 }; #define XOR_TABLE_SIZE 37 - const unsigned char xor_table[XOR_TABLE_SIZE] = { + static const unsigned char xor_table[XOR_TABLE_SIZE] = { 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53, 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70, 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09, @@ -299,17 +299,17 @@ rdt_parse_packet (AVFormatContext *ctx, PayloadContext *rdt, AVStream *st, AVIOContext pb; if (rdt->audio_pkt_cnt == 0) { - int pos; + int pos, rmflags; ffio_init_context(&pb, buf, len, 0, NULL, NULL, NULL, NULL); - flags = (flags & RTP_FLAG_KEY) ? 2 : 0; + rmflags = (flags & RTP_FLAG_KEY) ? 2 : 0; res = ff_rm_parse_packet (rdt->rmctx, &pb, st, rdt->rmst[st->index], len, pkt, - &seq, flags, *timestamp); + &seq, rmflags, *timestamp); pos = avio_tell(&pb); if (res < 0) return res; if (res > 0) { - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { memcpy (rdt->buffer, buf + pos, len - pos); rdt->rmctx->pb = avio_alloc_context (rdt->buffer, len - pos, 0, NULL, NULL, NULL, NULL); @@ -322,7 +322,7 @@ get_cache: ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb, st, rdt->rmst[st->index], pkt); if (rdt->audio_pkt_cnt == 0 && - st->codec->codec_id == AV_CODEC_ID_AAC) + st->codecpar->codec_id == AV_CODEC_ID_AAC) av_freep(&rdt->rmctx->pb); } pkt->stream_index = st->index; @@ -398,7 +398,7 @@ rdt_parse_b64buf (unsigned int *target_len, const char *p) len -= 2; /* skip embracing " at start/end */ } *target_len = len * 3 / 4; - target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE); + target = av_mallocz(*target_len + AV_INPUT_BUFFER_PADDING_SIZE); if (!target) return NULL; av_base64_decode(target, p, *target_len); @@ -434,6 +434,8 @@ rdt_parse_sdp_line (AVFormatContext *s, int st_index, rdt->nb_rmst = count; } rdt->rmst[s->streams[n]->index] = ff_rm_alloc_rmstream(); + if (!rdt->rmst[s->streams[n]->index]) + return AVERROR(ENOMEM); rdt_load_mdpr(rdt, s->streams[n], (n - first) * 2); } } @@ -446,7 +448,7 @@ real_parse_asm_rule(AVStream *st, const char *p, const char *end) { do { /* can be either averagebandwidth= or AverageBandwidth= */ - if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codec->bit_rate) == 1) + if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codecpar->bit_rate) == 1) break; if (!(p = strchr(p, ',')) || p > end) p = end; @@ -462,7 +464,7 @@ add_dstream(AVFormatContext *s, AVStream *orig_st) if (!(st = avformat_new_stream(s, NULL))) return NULL; st->id = orig_st->id; - st->codec->codec_type = orig_st->codec->codec_type; + st->codecpar->codec_type = orig_st->codecpar->codec_type; st->first_dts = orig_st->first_dts; return st; @@ -519,24 +521,13 @@ ff_real_parse_sdp_a_line (AVFormatContext *s, int stream_index, real_parse_asm_rulebook(s, s->streams[stream_index], p); } -static PayloadContext * -rdt_new_context (void) +static av_cold int rdt_init(AVFormatContext *s, int st_index, PayloadContext *rdt) { - PayloadContext *rdt = av_mallocz(sizeof(PayloadContext)); - int ret; - if (!rdt) - return NULL; - ret = avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL); - if (ret < 0) { - av_free(rdt); - return NULL; - } - - return rdt; + return avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL); } static void -rdt_free_context (PayloadContext *rdt) +rdt_close_context (PayloadContext *rdt) { int i; @@ -549,7 +540,6 @@ rdt_free_context (PayloadContext *rdt) avformat_close_input(&rdt->rmctx); av_freep(&rdt->mlti_data); av_freep(&rdt->rmst); - av_free(rdt); } #define RDT_HANDLER(n, s, t) \ @@ -557,9 +547,10 @@ static RTPDynamicProtocolHandler rdt_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ + .priv_data_size = sizeof(PayloadContext), \ + .init = rdt_init, \ .parse_sdp_a_line = rdt_parse_sdp_line, \ - .alloc = rdt_new_context, \ - .free = rdt_free_context, \ + .close = rdt_close_context, \ .parse_packet = rdt_parse_packet \ } diff --git a/libavformat/replaygain.c b/libavformat/replaygain.c index 6c5b582..3188b15 100644 --- a/libavformat/replaygain.c +++ b/libavformat/replaygain.c @@ -33,6 +33,7 @@ #include "libavutil/replaygain.h" #include "avformat.h" +#include "internal.h" #include "replaygain.h" static int32_t parse_value(const char *value, int32_t min) @@ -69,36 +70,16 @@ static int32_t parse_value(const char *value, int32_t min) int ff_replaygain_export_raw(AVStream *st, int32_t tg, uint32_t tp, int32_t ag, uint32_t ap) { - AVPacketSideData *sd, *tmp; AVReplayGain *replaygain; if (tg == INT32_MIN && ag == INT32_MIN) return 0; - for (int i = 0; i < st->nb_side_data; i++) { - AVPacketSideData *src_sd = &st->side_data[i]; - - if (src_sd->type == AV_PKT_DATA_REPLAYGAIN) - return 0; - } - - replaygain = av_mallocz(sizeof(*replaygain)); + replaygain = (AVReplayGain*)av_stream_new_side_data(st, AV_PKT_DATA_REPLAYGAIN, + sizeof(*replaygain)); if (!replaygain) return AVERROR(ENOMEM); - tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); - if (!tmp) { - av_freep(&replaygain); - return AVERROR(ENOMEM); - } - st->side_data = tmp; - st->nb_side_data++; - - sd = &st->side_data[st->nb_side_data - 1]; - sd->type = AV_PKT_DATA_REPLAYGAIN; - sd->data = (uint8_t*)replaygain; - sd->size = sizeof(*replaygain); - replaygain->track_gain = tg; replaygain->track_peak = tp; replaygain->album_gain = ag; diff --git a/libavformat/riff.c b/libavformat/riff.c index 0e16ec7..54bef83 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -39,6 +39,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_H264, MKTAG('V', '2', '6', '4') }, /* CCTV recordings */ { AV_CODEC_ID_H264, MKTAG('G', 'A', 'V', 'C') }, /* GeoVision camera */ { AV_CODEC_ID_H264, MKTAG('U', 'M', 'S', 'V') }, + { AV_CODEC_ID_H264, MKTAG('t', 's', 'h', 'd') }, { AV_CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, { AV_CODEC_ID_H263, MKTAG('X', '2', '6', '3') }, { AV_CODEC_ID_H263, MKTAG('T', '2', '6', '3') }, @@ -107,6 +108,9 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_MPEG4, MKTAG('D', 'r', 'e', 'X') }, { AV_CODEC_ID_MPEG4, MKTAG('Q', 'M', 'P', '4') }, /* QNAP Systems */ { AV_CODEC_ID_MPEG4, MKTAG('P', 'L', 'V', '1') }, /* Pelco DVR MPEG-4 */ + { AV_CODEC_ID_MPEG4, MKTAG('G', 'L', 'V', '4') }, + { AV_CODEC_ID_MPEG4, MKTAG('G', 'M', 'P', '4') }, /* GeoVision camera */ + { AV_CODEC_ID_MPEG4, MKTAG('M', 'N', 'M', '4') }, /* March Networks DVR */ { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, { AV_CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') }, @@ -161,10 +165,12 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_MPEG2VIDEO, MKTAG('E', 'M', '2', 'V') }, /* Matrox MPEG-2 intra-only */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('M', '7', '0', '1') }, + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('M', '7', '0', '5') }, { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', 'v') }, { AV_CODEC_ID_MPEG1VIDEO, MKTAG('B', 'W', '1', '0') }, { AV_CODEC_ID_MPEG1VIDEO, MKTAG('X', 'M', 'P', 'G') }, /* Xing MPEG intra only */ { AV_CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') }, + { AV_CODEC_ID_MJPEG, MKTAG('M', 'S', 'C', '2') }, /* Multiscope II */ { AV_CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') }, { AV_CODEC_ID_MJPEG, MKTAG('d', 'm', 'b', '1') }, { AV_CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, @@ -234,10 +240,12 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', 'U', '9') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('a', 'u', 'v', '2') }, { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', 'Y', 'U') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', 'V') }, { AV_CODEC_ID_FRWU, MKTAG('F', 'R', 'W', 'U') }, { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'k') }, { AV_CODEC_ID_R210, MKTAG('r', '2', '1', '0') }, { AV_CODEC_ID_V210, MKTAG('v', '2', '1', '0') }, + { AV_CODEC_ID_V210, MKTAG('C', '2', '1', '0') }, { AV_CODEC_ID_V410, MKTAG('v', '4', '1', '0') }, { AV_CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') }, { AV_CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') }, @@ -301,6 +309,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') }, { AV_CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') }, { AV_CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') }, + { AV_CODEC_ID_TRUEMOTION2RT,MKTAG('T', 'R', '2', '0') }, { AV_CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') }, { AV_CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') }, { AV_CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') }, @@ -310,10 +319,12 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_JPEG2000, MKTAG('L', 'J', '2', 'C') }, { AV_CODEC_ID_JPEG2000, MKTAG('L', 'J', '2', 'K') }, { AV_CODEC_ID_JPEG2000, MKTAG('I', 'P', 'J', '2') }, + { AV_CODEC_ID_JPEG2000, MKTAG('A', 'V', 'j', '2') }, /* Avid jpeg2000 */ { AV_CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') }, { AV_CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, { AV_CODEC_ID_PNG, MKTAG('M', 'P', 'N', 'G') }, { AV_CODEC_ID_PNG, MKTAG('P', 'N', 'G', '1') }, + { AV_CODEC_ID_PNG, MKTAG('p', 'n', 'g', ' ') }, /* ImageJ */ { AV_CODEC_ID_CLJR, MKTAG('C', 'L', 'J', 'R') }, { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') }, { AV_CODEC_ID_RPZA, MKTAG('a', 'z', 'p', 'r') }, @@ -346,7 +357,17 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '2') }, { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '3') }, { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '4') }, + { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '5') }, { AV_CODEC_ID_FIC, MKTAG('F', 'I', 'C', 'V') }, + { AV_CODEC_ID_HQX, MKTAG('C', 'H', 'Q', 'X') }, + { AV_CODEC_ID_TDSC, MKTAG('T', 'D', 'S', 'C') }, + { AV_CODEC_ID_HQ_HQA, MKTAG('C', 'U', 'V', 'C') }, + { AV_CODEC_ID_RV40, MKTAG('R', 'V', '4', '0') }, + { AV_CODEC_ID_SCREENPRESSO, MKTAG('S', 'P', 'V', '1') }, + { AV_CODEC_ID_RSCC, MKTAG('R', 'S', 'C', 'C') }, + { AV_CODEC_ID_RSCC, MKTAG('I', 'S', 'C', 'C') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', 'A', 'G', 'Y') }, + { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, { AV_CODEC_ID_NONE, 0 } }; diff --git a/libavformat/riff.h b/libavformat/riff.h index ddfb0fa..e5f4645 100644 --- a/libavformat/riff.h +++ b/libavformat/riff.h @@ -41,14 +41,15 @@ void ff_end_tag(AVIOContext *pb, int64_t start); /** * Read BITMAPINFOHEADER structure and set AVStream codec width, height and * bits_per_encoded_sample fields. Does not read extradata. + * Writes the size of the BMP file to *size. * @return codec tag */ -int ff_get_bmp_header(AVIOContext *pb, AVStream *st); +int ff_get_bmp_header(AVIOContext *pb, AVStream *st, uint32_t *size); -void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf); -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc); +void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, const AVCodecTag *tags, int for_asf); +int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par); enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps); -int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size); +int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int size); extern const AVCodecTag ff_codec_bmp_tags[]; extern const AVCodecTag ff_codec_wav_tags[]; diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c index 74f93ac..db83b32 100644 --- a/libavformat/riffdec.c +++ b/libavformat/riffdec.c @@ -54,65 +54,73 @@ enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) * an openended structure. */ -static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) +static void parse_waveformatex(AVIOContext *pb, AVCodecParameters *par) { ff_asf_guid subformat; - c->bits_per_coded_sample = avio_rl16(pb); - c->channel_layout = avio_rl32(pb); /* dwChannelMask */ + int bps; + + bps = avio_rl16(pb); + if (bps) + par->bits_per_coded_sample = bps; + par->channel_layout = avio_rl32(pb); /* dwChannelMask */ ff_get_guid(pb, &subformat); if (!memcmp(subformat + 4, (const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) { - c->codec_tag = AV_RL32(subformat); - c->codec_id = ff_wav_codec_get_id(c->codec_tag, - c->bits_per_coded_sample); + par->codec_tag = AV_RL32(subformat); + par->codec_id = ff_wav_codec_get_id(par->codec_tag, + par->bits_per_coded_sample); } else { - c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); - if (!c->codec_id) - av_log(c, AV_LOG_WARNING, + par->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); + if (!par->codec_id) + av_log(pb, AV_LOG_WARNING, "unknown subformat:"FF_PRI_GUID"\n", FF_ARG_GUID(subformat)); } } -int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) +int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, + AVCodecParameters *par, int size) { int id; + uint64_t bitrate; + + if (size < 14) + return AVERROR_INVALIDDATA; id = avio_rl16(pb); - codec->codec_type = AVMEDIA_TYPE_AUDIO; - codec->channels = avio_rl16(pb); - codec->sample_rate = avio_rl32(pb); - codec->bit_rate = avio_rl32(pb) * 8; - codec->block_align = avio_rl16(pb); + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->channels = avio_rl16(pb); + par->sample_rate = avio_rl32(pb); + bitrate = avio_rl32(pb) * 8; + par->block_align = avio_rl16(pb); if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ - codec->bits_per_coded_sample = 8; + par->bits_per_coded_sample = 8; } else - codec->bits_per_coded_sample = avio_rl16(pb); + par->bits_per_coded_sample = avio_rl16(pb); if (id == 0xFFFE) { - codec->codec_tag = 0; + par->codec_tag = 0; } else { - codec->codec_tag = id; - codec->codec_id = ff_wav_codec_get_id(id, - codec->bits_per_coded_sample); + par->codec_tag = id; + par->codec_id = ff_wav_codec_get_id(id, par->bits_per_coded_sample); } if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ int cbSize = avio_rl16(pb); /* cbSize */ size -= 18; cbSize = FFMIN(size, cbSize); if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ - parse_waveformatex(pb, codec); + parse_waveformatex(pb, par); cbSize -= 22; size -= 22; } - codec->extradata_size = cbSize; + par->extradata_size = cbSize; if (cbSize > 0) { - av_free(codec->extradata); - codec->extradata = av_mallocz(codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!codec->extradata) + av_free(par->extradata); + par->extradata = av_mallocz(par->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) return AVERROR(ENOMEM); - avio_read(pb, codec->extradata, codec->extradata_size); + avio_read(pb, par->extradata, par->extradata_size); size -= cbSize; } @@ -120,20 +128,37 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) if (size > 0) avio_skip(pb, size); } - if (codec->sample_rate <= 0) { - av_log(NULL, AV_LOG_ERROR, - "Invalid sample rate: %d\n", codec->sample_rate); + + if (bitrate > INT_MAX) { + if (s->error_recognition & AV_EF_EXPLODE) { + av_log(s, AV_LOG_ERROR, + "The bitrate %"PRIu64" is too large.\n", + bitrate); + return AVERROR_INVALIDDATA; + } else { + av_log(s, AV_LOG_WARNING, + "The bitrate %"PRIu64" is too large, resetting to 0.", + bitrate); + par->bit_rate = 0; + } + } else { + par->bit_rate = bitrate; + } + + if (par->sample_rate <= 0) { + av_log(s, AV_LOG_ERROR, + "Invalid sample rate: %d\n", par->sample_rate); return AVERROR_INVALIDDATA; } - if (codec->codec_id == AV_CODEC_ID_AAC_LATM) { + if (par->codec_id == AV_CODEC_ID_AAC_LATM) { /* Channels and sample_rate values are those prior to applying SBR * and/or PS. */ - codec->channels = 0; - codec->sample_rate = 0; + par->channels = 0; + par->sample_rate = 0; } /* override bits_per_coded_sample for G.726 */ - if (codec->codec_id == AV_CODEC_ID_ADPCM_G726) - codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate; + if (par->codec_id == AV_CODEC_ID_ADPCM_G726) + par->bits_per_coded_sample = par->bit_rate / par->sample_rate; return 0; } @@ -155,15 +180,17 @@ enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps) return id; } -int ff_get_bmp_header(AVIOContext *pb, AVStream *st) +int ff_get_bmp_header(AVIOContext *pb, AVStream *st, uint32_t *size) { int tag1; - avio_rl32(pb); /* size */ - st->codec->width = avio_rl32(pb); - st->codec->height = (int32_t)avio_rl32(pb); + uint32_t size_ = avio_rl32(pb); + if (size) + *size = size_; + st->codecpar->width = avio_rl32(pb); + st->codecpar->height = (int32_t)avio_rl32(pb); avio_rl16(pb); /* planes */ - st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ - tag1 = avio_rl32(pb); + st->codecpar->bits_per_coded_sample = avio_rl16(pb); /* depth */ + tag1 = avio_rl32(pb); avio_rl32(pb); /* ImageSize */ avio_rl32(pb); /* XPelsPerMeter */ avio_rl32(pb); /* YPelsPerMeter */ diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index b83533a..e6b8411 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -47,7 +47,8 @@ void ff_end_tag(AVIOContext *pb, int64_t start) /* WAVEFORMATEX header */ /* returns the size or -1 on error */ -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) +int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, + AVCodecParameters *par) { int bps, blkalign, bytespersec, frame_size; int hdrsize = 18; @@ -56,86 +57,82 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) uint8_t *riff_extradata = temp; uint8_t *riff_extradata_start = temp; - if (!enc->codec_tag || enc->codec_tag > 0xffff) + if (!par->codec_tag || par->codec_tag > 0xffff) return -1; /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ - frame_size = av_get_audio_frame_duration(enc, enc->block_align); - if (!frame_size) - frame_size = enc->frame_size; + frame_size = av_get_audio_frame_duration2(par, par->block_align); - waveformatextensible = (enc->channels > 2 && enc->channel_layout) || - enc->sample_rate > 48000 || - av_get_bits_per_sample(enc->codec_id) > 16; + waveformatextensible = (par->channels > 2 && par->channel_layout) || + par->sample_rate > 48000 || + av_get_bits_per_sample(par->codec_id) > 16; if (waveformatextensible) avio_wl16(pb, 0xfffe); else - avio_wl16(pb, enc->codec_tag); + avio_wl16(pb, par->codec_tag); - avio_wl16(pb, enc->channels); - avio_wl32(pb, enc->sample_rate); - if (enc->codec_id == AV_CODEC_ID_MP2 || - enc->codec_id == AV_CODEC_ID_MP3 || - enc->codec_id == AV_CODEC_ID_GSM_MS) { + avio_wl16(pb, par->channels); + avio_wl32(pb, par->sample_rate); + if (par->codec_id == AV_CODEC_ID_MP2 || + par->codec_id == AV_CODEC_ID_MP3 || + par->codec_id == AV_CODEC_ID_GSM_MS) { bps = 0; } else { - if (!(bps = av_get_bits_per_sample(enc->codec_id))) { - if (enc->bits_per_coded_sample) - bps = enc->bits_per_coded_sample; + if (!(bps = av_get_bits_per_sample(par->codec_id))) { + if (par->bits_per_coded_sample) + bps = par->bits_per_coded_sample; else bps = 16; // default to 16 } } - if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { - av_log(enc, AV_LOG_WARNING, + if (bps != par->bits_per_coded_sample && par->bits_per_coded_sample) { + av_log(s, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) " "and actually stored (%d) differ\n", - enc->bits_per_coded_sample, bps); + par->bits_per_coded_sample, bps); } - if (enc->codec_id == AV_CODEC_ID_MP2 || - enc->codec_id == AV_CODEC_ID_MP3) { - /* This is wrong, but it seems many demuxers do not work if this - * is set correctly. */ + if (par->codec_id == AV_CODEC_ID_MP2) { blkalign = frame_size; - // blkalign = 144 * enc->bit_rate/enc->sample_rate; - } else if (enc->codec_id == AV_CODEC_ID_AC3) { + } else if (par->codec_id == AV_CODEC_ID_MP3) { + blkalign = 576 * (par->sample_rate <= 24000 ? 1 : 2); + } else if (par->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; /* maximum bytes per frame */ - } else if (enc->block_align != 0) { /* specified by the codec */ - blkalign = enc->block_align; + } else if (par->block_align != 0) { /* specified by the codec */ + blkalign = par->block_align; } else - blkalign = bps * enc->channels / av_gcd(8, bps); - if (enc->codec_id == AV_CODEC_ID_PCM_U8 || - enc->codec_id == AV_CODEC_ID_PCM_S24LE || - enc->codec_id == AV_CODEC_ID_PCM_S32LE || - enc->codec_id == AV_CODEC_ID_PCM_F32LE || - enc->codec_id == AV_CODEC_ID_PCM_F64LE || - enc->codec_id == AV_CODEC_ID_PCM_S16LE) { - bytespersec = enc->sample_rate * blkalign; + blkalign = bps * par->channels / av_gcd(8, bps); + if (par->codec_id == AV_CODEC_ID_PCM_U8 || + par->codec_id == AV_CODEC_ID_PCM_S24LE || + par->codec_id == AV_CODEC_ID_PCM_S32LE || + par->codec_id == AV_CODEC_ID_PCM_F32LE || + par->codec_id == AV_CODEC_ID_PCM_F64LE || + par->codec_id == AV_CODEC_ID_PCM_S16LE) { + bytespersec = par->sample_rate * blkalign; } else { - bytespersec = enc->bit_rate / 8; + bytespersec = par->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ - if (enc->codec_id == AV_CODEC_ID_MP3) { + if (par->codec_id == AV_CODEC_ID_MP3) { hdrsize += 12; bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ - } else if (enc->codec_id == AV_CODEC_ID_MP2) { + } else if (par->codec_id == AV_CODEC_ID_MP2) { hdrsize += 22; /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* dwHeadBitrate */ - bytestream_put_le32(&riff_extradata, enc->bit_rate); + bytestream_put_le32(&riff_extradata, par->bit_rate); /* fwHeadMode */ - bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); + bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* wHeadEmphasis */ @@ -146,15 +143,15 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); - } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || - enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { + } else if (par->codec_id == AV_CODEC_ID_GSM_MS || + par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { hdrsize += 2; /* wSamplesPerBlock */ bytestream_put_le16(&riff_extradata, frame_size); - } else if (enc->extradata_size) { - riff_extradata_start = enc->extradata; - riff_extradata = enc->extradata + enc->extradata_size; - hdrsize += enc->extradata_size; + } else if (par->extradata_size) { + riff_extradata_start = par->extradata; + riff_extradata = par->extradata + par->extradata_size; + hdrsize += par->extradata_size; } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { @@ -164,9 +161,9 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ - avio_wl32(pb, enc->channel_layout); + avio_wl32(pb, par->channel_layout); /* GUID + next 3 */ - avio_wl32(pb, enc->codec_tag); + avio_wl32(pb, par->codec_tag); avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); @@ -183,59 +180,54 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) } /* BITMAPINFOHEADER header */ -void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, +void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, const AVCodecTag *tags, int for_asf) { /* size */ - avio_wl32(pb, 40 + enc->extradata_size); - avio_wl32(pb, enc->width); + avio_wl32(pb, 40 + par->extradata_size); + avio_wl32(pb, par->width); //We always store RGB TopDown - avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height); + avio_wl32(pb, par->codec_tag ? par->height : -par->height); /* planes */ avio_wl16(pb, 1); /* depth */ - avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24); + avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24); /* compression type */ - avio_wl32(pb, enc->codec_tag); - avio_wl32(pb, enc->width * enc->height * 3); + avio_wl32(pb, par->codec_tag); + avio_wl32(pb, par->width * par->height * 3); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); - avio_write(pb, enc->extradata, enc->extradata_size); + avio_write(pb, par->extradata, par->extradata_size); - if (!for_asf && enc->extradata_size & 1) + if (!for_asf && par->extradata_size & 1) avio_w8(pb, 0); } void ff_parse_specific_params(AVStream *st, int *au_rate, int *au_ssize, int *au_scale) { - AVCodecContext *codec = st->codec; + AVCodecParameters *par = st->codecpar; int gcd; int audio_frame_size; - /* We use the known constant frame size for the codec if known, otherwise - * fall back on using AVCodecContext.frame_size, which is not as reliable - * for indicating packet duration. */ - audio_frame_size = av_get_audio_frame_duration(codec, 0); - if (!audio_frame_size) - audio_frame_size = codec->frame_size; + audio_frame_size = av_get_audio_frame_duration2(par, 0); - *au_ssize = codec->block_align; - if (audio_frame_size && codec->sample_rate) { + *au_ssize = par->block_align; + if (audio_frame_size && par->sample_rate) { *au_scale = audio_frame_size; - *au_rate = codec->sample_rate; - } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO || - codec->codec_type == AVMEDIA_TYPE_DATA || - codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + *au_rate = par->sample_rate; + } else if (par->codec_type == AVMEDIA_TYPE_VIDEO || + par->codec_type == AVMEDIA_TYPE_DATA || + par->codec_type == AVMEDIA_TYPE_SUBTITLE) { *au_scale = st->time_base.num; *au_rate = st->time_base.den; } else { - *au_scale = codec->block_align ? codec->block_align * 8 : 8; - *au_rate = codec->bit_rate ? codec->bit_rate : - 8 * codec->sample_rate; + *au_scale = par->block_align ? par->block_align * 8 : 8; + *au_rate = par->bit_rate ? par->bit_rate : + 8 * par->sample_rate; } gcd = av_gcd(*au_scale, *au_rate); *au_scale /= gcd; diff --git a/libavformat/rl2.c b/libavformat/rl2.c index 5d30bf8..0e8d346 100644 --- a/libavformat/rl2.c +++ b/libavformat/rl2.c @@ -104,7 +104,7 @@ static av_cold int rl2_read_header(AVFormatContext *s) if(back_size > INT_MAX/2 || frame_count > INT_MAX / sizeof(uint32_t)) return AVERROR_INVALIDDATA; - avio_skip(pb, 2); /* encoding mentod */ + avio_skip(pb, 2); /* encoding method */ sound_rate = avio_rl16(pb); rate = avio_rl16(pb); channels = avio_rl16(pb); @@ -119,25 +119,25 @@ static av_cold int rl2_read_header(AVFormatContext *s) if(!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RL2; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = 320; - st->codec->height = 200; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RL2; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = 320; + st->codecpar->height = 200; /** allocate and fill extradata */ - st->codec->extradata_size = EXTRADATA1_SIZE; + st->codecpar->extradata_size = EXTRADATA1_SIZE; if(signature == RLV3_TAG && back_size > 0) - st->codec->extradata_size += back_size; + st->codecpar->extradata_size += back_size; - st->codec->extradata = av_mallocz(st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if(!st->codec->extradata) + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if(!st->codecpar->extradata) return AVERROR(ENOMEM); - if(avio_read(pb,st->codec->extradata,st->codec->extradata_size) != - st->codec->extradata_size) + if(avio_read(pb,st->codecpar->extradata,st->codecpar->extradata_size) != + st->codecpar->extradata_size) return AVERROR(EIO); /** setup audio stream if present */ @@ -148,16 +148,16 @@ static av_cold int rl2_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_U8; - st->codec->codec_tag = 1; - st->codec->channels = channels; - st->codec->bits_per_coded_sample = 8; - st->codec->sample_rate = rate; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample; - st->codec->block_align = st->codec->channels * - st->codec->bits_per_coded_sample / 8; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->codec_tag = 1; + st->codecpar->channels = channels; + st->codecpar->bits_per_coded_sample = 8; + st->codecpar->sample_rate = rate; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = st->codecpar->channels * + st->codecpar->bits_per_coded_sample / 8; avpriv_set_pts_info(st,32,1,rate); } @@ -245,7 +245,7 @@ static int rl2_read_packet(AVFormatContext *s, /** fill the packet */ ret = av_get_packet(pb, pkt, sample->size); if(ret != sample->size){ - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index dae1235..9774194 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -54,7 +54,7 @@ struct RMStream { int32_t deint_id; ///< deinterleaver used in audio stream }; -typedef struct { +typedef struct RMDemuxContext { int nb_packets; int old_format; int current_stream; @@ -82,15 +82,15 @@ static void get_str8(AVIOContext *pb, char *buf, int buf_size) get_strl(pb, buf, buf_size, avio_r8(pb)); } -static int rm_read_extradata(AVIOContext *pb, AVCodecContext *avctx, unsigned size) +static int rm_read_extradata(AVIOContext *pb, AVCodecParameters *par, unsigned size) { if (size >= 1<<24) return -1; - avctx->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) + par->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) return AVERROR(ENOMEM); - avctx->extradata_size = avio_read(pb, avctx->extradata, size); - if (avctx->extradata_size != size) + par->extradata_size = avio_read(pb, par->extradata, size); + if (par->extradata_size != size) return AVERROR(EIO); return 0; } @@ -109,13 +109,15 @@ static void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide) RMStream *ff_rm_alloc_rmstream (void) { RMStream *rms = av_mallocz(sizeof(RMStream)); + if (!rms) + return NULL; rms->curpic_num = -1; return rms; } void ff_rm_free_rmstream (RMStream *rms) { - av_free_packet(&rms->pkt); + av_packet_unref(&rms->pkt); } static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, @@ -140,11 +142,11 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, // Skip extra header crap (this should never happen) if ((startpos + header_size) > avio_tell(pb)) avio_skip(pb, header_size + startpos - avio_tell(pb)); - st->codec->sample_rate = 8000; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_RA_144; + st->codecpar->sample_rate = 8000; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_RA_144; ast->deint_id = DEINT_ID_INT0; } else { int flavor, sub_packet_h, coded_framesize, sub_packet_size; @@ -161,15 +163,15 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, avio_rb32(pb); /* ??? */ avio_rb32(pb); /* ??? */ ast->sub_packet_h = sub_packet_h = avio_rb16(pb); /* 1 */ - st->codec->block_align= avio_rb16(pb); /* frame size */ + st->codecpar->block_align= avio_rb16(pb); /* frame size */ ast->sub_packet_size = sub_packet_size = avio_rb16(pb); /* sub packet size */ avio_rb16(pb); /* ??? */ if (version == 5) { avio_rb16(pb); avio_rb16(pb); avio_rb16(pb); } - st->codec->sample_rate = avio_rb16(pb); + st->codecpar->sample_rate = avio_rb16(pb); avio_rb32(pb); - st->codec->channels = avio_rb16(pb); + st->codecpar->channels = avio_rb16(pb); if (version == 5) { ast->deint_id = avio_rl32(pb); avio_read(pb, buf, 4); @@ -179,19 +181,19 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, ast->deint_id = AV_RL32(buf); get_str8(pb, buf, sizeof(buf)); /* desc */ } - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = AV_RL32(buf); - st->codec->codec_id = ff_codec_get_id(ff_rm_codec_tags, - st->codec->codec_tag); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = AV_RL32(buf); + st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, + st->codecpar->codec_tag); - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_AC3: st->need_parsing = AVSTREAM_PARSE_FULL; break; case AV_CODEC_ID_RA_288: - st->codec->extradata_size= 0; - ast->audio_framesize = st->codec->block_align; - st->codec->block_align = coded_framesize; + st->codecpar->extradata_size= 0; + ast->audio_framesize = st->codecpar->block_align; + st->codecpar->block_align = coded_framesize; break; case AV_CODEC_ID_COOK: st->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -201,27 +203,27 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } - ast->audio_framesize = st->codec->block_align; - if (st->codec->codec_id == AV_CODEC_ID_SIPR) { + ast->audio_framesize = st->codecpar->block_align; + if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) { if (flavor > 3) { av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n", flavor); return -1; } - st->codec->block_align = ff_sipr_subpk_size[flavor]; + st->codecpar->block_align = ff_sipr_subpk_size[flavor]; } else { if(sub_packet_size <= 0){ av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n"); return -1; } - st->codec->block_align = ast->sub_packet_size; + st->codecpar->block_align = ast->sub_packet_size; } - if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0) + if ((ret = rm_read_extradata(pb, st->codecpar, codecdata_length)) < 0) return ret; break; case AV_CODEC_ID_AAC: @@ -229,13 +231,13 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } if (codecdata_length >= 1) { avio_r8(pb); - if ((ret = rm_read_extradata(pb, st->codec, codecdata_length - 1)) < 0) + if ((ret = rm_read_extradata(pb, st->codecpar, codecdata_length - 1)) < 0) return ret; } break; @@ -243,9 +245,9 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, if (ast->deint_id == DEINT_ID_INT4 || ast->deint_id == DEINT_ID_GENR || ast->deint_id == DEINT_ID_SIPR) { - if (st->codec->block_align <= 0 || + if (st->codecpar->block_align <= 0 || ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX || - ast->audio_framesize * sub_packet_h < st->codec->block_align) + ast->audio_framesize * sub_packet_h < st->codecpar->block_align) return AVERROR_INVALIDDATA; if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0) return AVERROR(ENOMEM); @@ -300,35 +302,35 @@ int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb, return -1; } else if (v == MKBETAG('L', 'S', 'D', ':')) { avio_seek(pb, -4, SEEK_CUR); - if ((ret = rm_read_extradata(pb, st->codec, codec_data_size)) < 0) + if ((ret = rm_read_extradata(pb, st->codecpar, codec_data_size)) < 0) return ret; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = AV_RL32(st->codec->extradata); - st->codec->codec_id = ff_codec_get_id(ff_rm_codec_tags, - st->codec->codec_tag); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = AV_RL32(st->codecpar->extradata); + st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, + st->codecpar->codec_tag); } else { int fps; if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) { fail1: - av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); + av_log(s, AV_LOG_WARNING, "Unsupported stream type %08x\n", v); goto skip; } - st->codec->codec_tag = avio_rl32(pb); - st->codec->codec_id = ff_codec_get_id(ff_rm_codec_tags, - st->codec->codec_tag); - av_dlog(s, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); - if (st->codec->codec_id == AV_CODEC_ID_NONE) + st->codecpar->codec_tag = avio_rl32(pb); + st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, + st->codecpar->codec_tag); + av_log(s, AV_LOG_TRACE, "%X %X\n", st->codecpar->codec_tag, MKTAG('R', 'V', '2', '0')); + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) goto fail1; - st->codec->width = avio_rb16(pb); - st->codec->height = avio_rb16(pb); + st->codecpar->width = avio_rb16(pb); + st->codecpar->height = avio_rb16(pb); avio_skip(pb, 2); // looks like bits per sample avio_skip(pb, 4); // always zero? - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; fps = avio_rb32(pb); - if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) + if ((ret = rm_read_extradata(pb, st->codecpar, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) return ret; if (fps > 0) { @@ -416,6 +418,8 @@ static int rm_read_header_old(AVFormatContext *s) if (!st) return -1; st->priv_data = ff_rm_alloc_rmstream(); + if (!st->priv_data) + return AVERROR(ENOMEM); return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1); } @@ -448,7 +452,7 @@ static int rm_read_header(AVFormatContext *s) tag = avio_rl32(pb); tag_size = avio_rb32(pb); avio_rb16(pb); - av_dlog(s, "tag=%c%c%c%c (%08x) size=%d\n", + av_log(s, AV_LOG_TRACE, "tag=%c%c%c%c (%08x) size=%d\n", (tag ) & 0xff, (tag >> 8) & 0xff, (tag >> 16) & 0xff, @@ -481,7 +485,7 @@ static int rm_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->id = avio_rb16(pb); avio_rb32(pb); /* max bit rate */ - st->codec->bit_rate = avio_rb32(pb); /* bit rate */ + st->codecpar->bit_rate = avio_rb32(pb); /* bit rate */ avio_rb32(pb); /* max packet size */ avio_rb32(pb); /* avg packet size */ start_time = avio_rb32(pb); /* start time */ @@ -491,8 +495,10 @@ static int rm_read_header(AVFormatContext *s) st->duration = duration; get_str8(pb, buf, sizeof(buf)); /* desc */ get_str8(pb, buf, sizeof(buf)); /* mimetype */ - st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; st->priv_data = ff_rm_alloc_rmstream(); + if (!st->priv_data) + return AVERROR(ENOMEM); if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, avio_rb32(pb)) < 0) return -1; @@ -653,7 +659,7 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){ vst->slices = ((hdr & 0x3F) << 1) + 1; vst->videobufsize = len2 + 8*vst->slices + 1; - av_free_packet(&vst->pkt); //FIXME this should be output. + av_packet_unref(&vst->pkt); //FIXME this should be output. if(av_new_packet(&vst->pkt, vst->videobufsize) < 0) return AVERROR(ENOMEM); vst->videobufpos = 8*vst->slices + 1; @@ -681,11 +687,6 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, vst->pkt.data= NULL; vst->pkt.size= 0; vst->pkt.buf = NULL; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - vst->pkt.destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, vst->videobufpos - 1 - 8*vst->slices); @@ -705,7 +706,7 @@ rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt) uint8_t *ptr; int j; - if (st->codec->codec_id == AV_CODEC_ID_AC3) { + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { ptr = pkt->data; for (j=0;jsize;j+=2) { FFSWAP(int, ptr[0], ptr[1]); @@ -721,11 +722,11 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, { RMDemuxContext *rm = s->priv_data; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { rm->current_stream= st->id; if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp)) return -1; //got partial frame - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { if ((ast->deint_id == DEINT_ID_GENR) || (ast->deint_id == DEINT_ID_INT4) || (ast->deint_id == DEINT_ID_SIPR)) { @@ -762,7 +763,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, ast->sub_packet_cnt = 0; rm->audio_stream_num = st->index; - rm->audio_pkt_cnt = h * w / st->codec->block_align; + rm->audio_pkt_cnt = h * w / st->codecpar->block_align; } else if ((ast->deint_id == DEINT_ID_VBRF) || (ast->deint_id == DEINT_ID_VBRS)) { int x; @@ -784,24 +785,11 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, pkt->stream_index = st->index; -#if 0 - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if(st->codec->codec_id == AV_CODEC_ID_RV20){ - int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1); - av_log(s, 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 |= AV_PKT_FLAG_KEY; - return st->codec->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0; + return st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0; } int @@ -816,12 +804,12 @@ ff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb, ast->deint_id == DEINT_ID_VBRS) av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); else { - int ret = av_new_packet(pkt, st->codec->block_align); + int ret = av_new_packet(pkt, st->codecpar->block_align); if (ret < 0) return ret; - memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this - (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), - st->codec->block_align); + memcpy(pkt->data, ast->pkt.data + st->codecpar->block_align * //FIXME avoid this + (ast->sub_packet_h * ast->audio_framesize / st->codecpar->block_align - rm->audio_pkt_cnt), + st->codecpar->block_align); } rm->audio_pkt_cnt--; if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) { @@ -865,7 +853,7 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) st = s->streams[i]; } - if(len<0 || s->pb->eof_reached) + if (len <= 0 || s->pb->eof_reached) return AVERROR(EIO); res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt, @@ -878,7 +866,7 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) || st->discard >= AVDISCARD_ALL){ - av_free_packet(pkt); + av_packet_unref(pkt); } else break; } @@ -932,7 +920,7 @@ static int64_t rm_read_dts(AVFormatContext *s, int stream_index, return AV_NOPTS_VALUE; st = s->streams[stream_index2]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { h= avio_r8(s->pb); len--; if(!(h & 0x40)){ seq = avio_r8(s->pb); len--; @@ -940,7 +928,7 @@ static int64_t rm_read_dts(AVFormatContext *s, int stream_index, } if((flags&2) && (seq&0x7F) == 1){ - av_dlog(s, "%d %d-%d %"PRId64" %d\n", + av_log(s, AV_LOG_TRACE, "%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) diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index adaae5d..59118c9 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -23,7 +23,7 @@ #include "rm.h" #include "libavutil/dict.h" -typedef struct { +typedef struct StreamInfo { int nb_packets; int packet_total_size; int packet_max_size; @@ -33,10 +33,10 @@ typedef struct { int nb_frames; /* current frame number */ int total_frames; /* total number of frames */ int num; - AVCodecContext *enc; + AVCodecParameters *par; } StreamInfo; -typedef struct { +typedef struct RMMuxContext { StreamInfo streams[2]; StreamInfo *audio_stream, *video_stream; int data_pos; /* position of the data after the header */ @@ -147,7 +147,7 @@ static int rv10_write_header(AVFormatContext *ctx, stream = &rm->streams[i]; - if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { + if (stream->par->codec_type == AVMEDIA_TYPE_AUDIO) { desc = "The Audio Stream"; mimetype = "audio/x-pn-realaudio"; codec_data_size = 73; @@ -183,11 +183,12 @@ static int rv10_write_header(AVFormatContext *ctx, put_str8(s, mimetype); avio_wb32(s, codec_data_size); - if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { + if (stream->par->codec_type == AVMEDIA_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); + int frame_size = av_get_audio_frame_duration2(stream->par, 0); + sample_rate = stream->par->sample_rate; + coded_frame_size = (stream->par->bit_rate * + frame_size) / (8 * sample_rate); /* audio codec info */ avio_write(s, ".ra", 3); avio_w8(s, 0xfd); @@ -227,13 +228,13 @@ static int rv10_write_header(AVFormatContext *ctx, /* frame length : seems to be very important */ avio_wb16(s, coded_frame_size); avio_wb32(s, 0); /* unknown */ - avio_wb16(s, stream->enc->sample_rate); /* sample rate */ + avio_wb16(s, stream->par->sample_rate); /* sample rate */ avio_wb32(s, 0x10); /* unknown */ - avio_wb16(s, stream->enc->channels); + avio_wb16(s, stream->par->channels); put_str8(s, "Int0"); /* codec name */ - if (stream->enc->codec_tag) { + if (stream->par->codec_tag) { avio_w8(s, 4); /* tag length */ - avio_wl32(s, stream->enc->codec_tag); + avio_wl32(s, stream->par->codec_tag); } else { av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n"); return -1; @@ -246,21 +247,21 @@ static int rv10_write_header(AVFormatContext *ctx, /* video codec info */ avio_wb32(s,34); /* size */ ffio_wfourcc(s, "VIDO"); - if(stream->enc->codec_id == AV_CODEC_ID_RV10) + if(stream->par->codec_id == AV_CODEC_ID_RV10) ffio_wfourcc(s,"RV10"); else ffio_wfourcc(s,"RV20"); - avio_wb16(s, stream->enc->width); - avio_wb16(s, stream->enc->height); + avio_wb16(s, stream->par->width); + avio_wb16(s, stream->par->height); avio_wb16(s, (int) stream->frame_rate); /* frames per seconds ? */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, (int) stream->frame_rate); /* unknown meaning */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(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 == AV_CODEC_ID_RV10) + /* Seems to be the codec version: only use basic H.263. The next + versions seems to add a differential DC coding as in + MPEG... nothing new under the sun. */ + if(stream->par->codec_id == AV_CODEC_ID_RV10) avio_wb32(s,0x10000000); else avio_wb32(s,0x20103001); @@ -311,23 +312,25 @@ static int rm_write_header(AVFormatContext *s) RMMuxContext *rm = s->priv_data; StreamInfo *stream; int n; - AVCodecContext *codec; + AVCodecParameters *par; for(n=0;nnb_streams;n++) { AVStream *st = s->streams[n]; + int frame_size; s->streams[n]->id = n; - codec = s->streams[n]->codec; + par = s->streams[n]->codecpar; stream = &rm->streams[n]; memset(stream, 0, sizeof(StreamInfo)); stream->num = n; - stream->bit_rate = codec->bit_rate; - stream->enc = codec; + stream->bit_rate = par->bit_rate; + stream->par = par; - switch(codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: rm->audio_stream = stream; - stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size; + frame_size = av_get_audio_frame_duration2(par, 0); + stream->frame_rate = (float)par->sample_rate / (float)frame_size; /* XXX: dummy values */ stream->packet_max_size = 1024; stream->nb_packets = 0; @@ -355,29 +358,23 @@ static int rm_write_header(AVFormatContext *s) static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags) { - uint8_t *buf1; RMMuxContext *rm = s->priv_data; AVIOContext *pb = s->pb; StreamInfo *stream = rm->audio_stream; int i; - /* XXX: suppress this malloc */ - buf1 = av_malloc(size * sizeof(uint8_t)); - write_packet_header(s, stream, size, !!(flags & AV_PKT_FLAG_KEY)); - if (stream->enc->codec_id == AV_CODEC_ID_AC3) { + if (stream->par->codec_id == AV_CODEC_ID_AC3) { /* for AC-3, the words seem to be reversed */ - for(i=0;inb_frames++; - av_free(buf1); return 0; } @@ -392,7 +389,6 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int /* Well, I spent some time finding the meaning of these bits. I am not sure I understood everything, but it works !! */ -#if 1 if (size > MAX_PACKET_SIZE) { avpriv_report_missing_feature(s, "Muxing packets larger than 64 kB"); return AVERROR(ENOSYS); @@ -400,7 +396,7 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame); /* bit 7: '1' if final packet of a frame converted in several packets */ avio_w8(pb, 0x81); - /* bit 7: '1' if I frame. bits 6..0 : sequence number in current + /* bit 7: '1' if I-frame. bits 6..0 : sequence number in current frame starting from 1 */ if (key_frame) { avio_w8(pb, 0x81); @@ -414,13 +410,6 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int avio_wb16(pb, 0x4000 | size); /* total frame size */ avio_wb16(pb, 0x4000 | size); /* offset from the start or the end */ } -#else - /* full frame */ - write_packet_header(s, size + 6); - avio_w8(pb, 0xc0); - avio_wb16(pb, 0x4000 + size); /* total frame size */ - avio_wb16(pb, 0x4000 + packet_number * 126); /* position in stream */ -#endif avio_w8(pb, stream->nb_frames & 0xff); avio_write(pb, buf, size); @@ -431,7 +420,7 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int static int rm_write_packet(AVFormatContext *s, AVPacket *pkt) { - if (s->streams[pkt->stream_index]->codec->codec_type == + if (s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) return rm_write_audio(s, pkt->data, pkt->size, pkt->flags); else diff --git a/libavformat/rpl.c b/libavformat/rpl.c index b72b8d0..0fa940e 100644 --- a/libavformat/rpl.c +++ b/libavformat/rpl.c @@ -145,35 +145,35 @@ static int rpl_read_header(AVFormatContext *s) vst = avformat_new_stream(s, NULL); if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_tag = read_line_and_int(pb, &error); // video format - vst->codec->width = read_line_and_int(pb, &error); // video width - vst->codec->height = read_line_and_int(pb, &error); // video height - vst->codec->bits_per_coded_sample = read_line_and_int(pb, &error); // video bits per sample + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_tag = read_line_and_int(pb, &error); // video format + vst->codecpar->width = read_line_and_int(pb, &error); // video width + vst->codecpar->height = read_line_and_int(pb, &error); // video height + vst->codecpar->bits_per_coded_sample = read_line_and_int(pb, &error); // video bits per sample error |= read_line(pb, line, sizeof(line)); // video frames per second fps = read_fps(line, &error); avpriv_set_pts_info(vst, 32, fps.den, fps.num); // Figure out the video codec - switch (vst->codec->codec_tag) { + switch (vst->codecpar->codec_tag) { #if 0 case 122: - vst->codec->codec_id = AV_CODEC_ID_ESCAPE122; + vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE122; break; #endif case 124: - vst->codec->codec_id = AV_CODEC_ID_ESCAPE124; + vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE124; // The header is wrong here, at least sometimes - vst->codec->bits_per_coded_sample = 16; + vst->codecpar->bits_per_coded_sample = 16; break; case 130: - vst->codec->codec_id = AV_CODEC_ID_ESCAPE130; + vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE130; break; default: av_log(s, AV_LOG_WARNING, "RPL video format %i not supported yet!\n", - vst->codec->codec_tag); - vst->codec->codec_id = AV_CODEC_ID_NONE; + vst->codecpar->codec_tag); + vst->codecpar->codec_id = AV_CODEC_ID_NONE; } // Audio headers @@ -185,59 +185,59 @@ static int rpl_read_header(AVFormatContext *s) ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_tag = audio_format; - ast->codec->sample_rate = read_line_and_int(pb, &error); // audio bitrate - ast->codec->channels = read_line_and_int(pb, &error); // number of audio channels - ast->codec->bits_per_coded_sample = read_line_and_int(pb, &error); // audio bits per sample + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_tag = audio_format; + ast->codecpar->sample_rate = read_line_and_int(pb, &error); // audio bitrate + ast->codecpar->channels = read_line_and_int(pb, &error); // number of audio channels + ast->codecpar->bits_per_coded_sample = read_line_and_int(pb, &error); // audio bits per sample // At least one sample uses 0 for ADPCM, which is really 4 bits // per sample. - if (ast->codec->bits_per_coded_sample == 0) - ast->codec->bits_per_coded_sample = 4; + if (ast->codecpar->bits_per_coded_sample == 0) + ast->codecpar->bits_per_coded_sample = 4; - ast->codec->bit_rate = ast->codec->sample_rate * - ast->codec->bits_per_coded_sample * - ast->codec->channels; + ast->codecpar->bit_rate = ast->codecpar->sample_rate * + ast->codecpar->bits_per_coded_sample * + ast->codecpar->channels; - ast->codec->codec_id = AV_CODEC_ID_NONE; + ast->codecpar->codec_id = AV_CODEC_ID_NONE; switch (audio_format) { case 1: - if (ast->codec->bits_per_coded_sample == 16) { + if (ast->codecpar->bits_per_coded_sample == 16) { // 16-bit audio is always signed - ast->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; } // There are some other formats listed as legal per the spec; // samples needed. break; case 101: - if (ast->codec->bits_per_coded_sample == 8) { + if (ast->codecpar->bits_per_coded_sample == 8) { // The samples with this kind of audio that I have // are all unsigned. - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; break; - } else if (ast->codec->bits_per_coded_sample == 4) { - ast->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD; + } else if (ast->codecpar->bits_per_coded_sample == 4) { + ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD; break; } break; } - if (ast->codec->codec_id == AV_CODEC_ID_NONE) { + if (ast->codecpar->codec_id == AV_CODEC_ID_NONE) { av_log(s, AV_LOG_WARNING, "RPL audio format %"PRId32" not supported yet!\n", audio_format); } - avpriv_set_pts_info(ast, 32, 1, ast->codec->bit_rate); + avpriv_set_pts_info(ast, 32, 1, ast->codecpar->bit_rate); } else { for (i = 0; i < 3; i++) error |= read_line(pb, line, sizeof(line)); } rpl->frames_per_chunk = read_line_and_int(pb, &error); // video frames per chunk - if (rpl->frames_per_chunk > 1 && vst->codec->codec_tag != 124) + if (rpl->frames_per_chunk > 1 && vst->codecpar->codec_tag != 124) av_log(s, AV_LOG_WARNING, "Don't know how to split frames for video format %i. " - "Video stream will be broken!\n", vst->codec->codec_tag); + "Video stream will be broken!\n", vst->codecpar->codec_tag); number_of_chunks = read_line_and_int(pb, &error); // number of chunks in the file // The number in the header is actually the index of the last chunk. @@ -297,8 +297,8 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt) if (avio_seek(pb, index_entry->pos, SEEK_SET) < 0) return AVERROR(EIO); - if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && - stream->codec->codec_tag == 124) { + if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + stream->codecpar->codec_tag == 124) { // We have to split Escape 124 frames because there are // multiple frames per chunk in Escape 124 samples. uint32_t frame_size; @@ -310,7 +310,7 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(pb, pkt, frame_size); if (ret != frame_size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } pkt->duration = 1; @@ -325,11 +325,11 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt) } else { ret = av_get_packet(pb, pkt, index_entry->size); if (ret != index_entry->size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } - if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { // frames_per_chunk should always be one here; the header // parsing will warn if it isn't. pkt->duration = rpl->frames_per_chunk; diff --git a/libavformat/rsodec.c b/libavformat/rsodec.c index 1612572..6f352af 100644 --- a/libavformat/rsodec.c +++ b/libavformat/rsodec.c @@ -59,12 +59,12 @@ static int rso_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->duration = (size * 8) / bps; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = id; - st->codec->codec_id = codec; - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = rate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = id; + st->codecpar->codec_id = codec; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = rate; avpriv_set_pts_info(st, 64, 1, rate); @@ -75,7 +75,7 @@ static int rso_read_header(AVFormatContext *s) static int rso_read_packet(AVFormatContext *s, AVPacket *pkt) { - int bps = av_get_bits_per_sample(s->streams[0]->codec->codec_id); + int bps = av_get_bits_per_sample(s->streams[0]->codecpar->codec_id); int ret = av_get_packet(s->pb, pkt, BLOCK_SIZE * bps >> 3); if (ret < 0) diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c index 8ebcf81..dd0fbf8 100644 --- a/libavformat/rsoenc.c +++ b/libavformat/rsoenc.c @@ -28,12 +28,12 @@ static int rso_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; - if (!enc->codec_tag) + if (!par->codec_tag) return AVERROR_INVALIDDATA; - if (enc->channels != 1) { + if (par->channels != 1) { av_log(s, AV_LOG_ERROR, "RSO only supports mono\n"); return AVERROR_INVALIDDATA; } @@ -44,20 +44,20 @@ static int rso_write_header(AVFormatContext *s) } /* XXX: find legal sample rates (if any) */ - if (enc->sample_rate >= 1u<<16) { + if (par->sample_rate >= 1u<<16) { av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n"); return AVERROR_INVALIDDATA; } - if (enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { + if (par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n"); return AVERROR_PATCHWELCOME; } /* format header */ - avio_wb16(pb, enc->codec_tag); /* codec ID */ + avio_wb16(pb, par->codec_tag); /* codec ID */ avio_wb16(pb, 0); /* data size, will be written at EOF */ - avio_wb16(pb, enc->sample_rate); + avio_wb16(pb, par->sample_rate); avio_wb16(pb, 0x0000); /* play mode ? (0x0000 = don't loop) */ avio_flush(pb); diff --git a/libavformat/rtmp.h b/libavformat/rtmp.h index dc7ba5b..f3390a1 100644 --- a/libavformat/rtmp.h +++ b/libavformat/rtmp.h @@ -29,9 +29,6 @@ #define RTMP_HANDSHAKE_PACKET_SIZE 1536 -#define HMAC_IPAD_VAL 0x36 -#define HMAC_OPAD_VAL 0x5C - /** * emulated Flash client version - 9.0.124.2 on Linux * @{ diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c index df101a4..cf121c6 100644 --- a/libavformat/rtmpcrypt.c +++ b/libavformat/rtmpcrypt.c @@ -50,38 +50,38 @@ typedef struct RTMPEContext { } RTMPEContext; static const uint8_t rtmpe8_keys[16][16] = { - { 0xbf, 0xf0, 0x34, 0xb2, 0x11, 0xd9, 0x08, 0x1f, - 0xcc, 0xdf, 0xb7, 0x95, 0x74, 0x8d, 0xe7, 0x32 }, - { 0x08, 0x6a, 0x5e, 0xb6, 0x17, 0x43, 0x09, 0x0e, - 0x6e, 0xf0, 0x5a, 0xb8, 0xfe, 0x5a, 0x39, 0xe2 }, - { 0x7b, 0x10, 0x95, 0x6f, 0x76, 0xce, 0x05, 0x21, - 0x23, 0x88, 0xa7, 0x3a, 0x44, 0x01, 0x49, 0xa1 }, - { 0xa9, 0x43, 0xf3, 0x17, 0xeb, 0xf1, 0x1b, 0xb2, - 0xa6, 0x91, 0xa5, 0xee, 0x17, 0xf3, 0x63, 0x39 }, - { 0x7a, 0x30, 0xe0, 0x0a, 0xb5, 0x29, 0xe2, 0x2c, - 0xa0, 0x87, 0xae, 0xa5, 0xc0, 0xcb, 0x79, 0xac }, - { 0xbd, 0xce, 0x0c, 0x23, 0x2f, 0xeb, 0xde, 0xff, - 0x1c, 0xfa, 0xae, 0x16, 0x11, 0x23, 0x23, 0x9d }, - { 0x55, 0xdd, 0x3f, 0x7b, 0x77, 0xe7, 0xe6, 0x2e, - 0x9b, 0xb8, 0xc4, 0x99, 0xc9, 0x48, 0x1e, 0xe4 }, - { 0x40, 0x7b, 0xb6, 0xb4, 0x71, 0xe8, 0x91, 0x36, - 0xa7, 0xae, 0xbf, 0x55, 0xca, 0x33, 0xb8, 0x39 }, - { 0xfc, 0xf6, 0xbd, 0xc3, 0xb6, 0x3c, 0x36, 0x97, - 0x7c, 0xe4, 0xf8, 0x25, 0x04, 0xd9, 0x59, 0xb2 }, - { 0x28, 0xe0, 0x91, 0xfd, 0x41, 0x95, 0x4c, 0x4c, - 0x7f, 0xb7, 0xdb, 0x00, 0xe3, 0xa0, 0x66, 0xf8 }, - { 0x57, 0x84, 0x5b, 0x76, 0x4f, 0x25, 0x1b, 0x03, - 0x46, 0xd4, 0x5b, 0xcd, 0xa2, 0xc3, 0x0d, 0x29 }, - { 0x0a, 0xcc, 0xee, 0xf8, 0xda, 0x55, 0xb5, 0x46, - 0x03, 0x47, 0x34, 0x52, 0x58, 0x63, 0x71, 0x3b }, - { 0xb8, 0x20, 0x75, 0xdc, 0xa7, 0x5f, 0x1f, 0xee, - 0xd8, 0x42, 0x68, 0xe8, 0xa7, 0x2a, 0x44, 0xcc }, - { 0x07, 0xcf, 0x6e, 0x9e, 0xa1, 0x6d, 0x7b, 0x25, - 0x9f, 0xa7, 0xae, 0x6c, 0xd9, 0x2f, 0x56, 0x29 }, - { 0xfe, 0xb1, 0xea, 0xe4, 0x8c, 0x8c, 0x3c, 0xe1, - 0x4e, 0x00, 0x64, 0xa7, 0x6a, 0x38, 0x7c, 0x2a }, - { 0x89, 0x3a, 0x94, 0x27, 0xcc, 0x30, 0x13, 0xa2, - 0xf1, 0x06, 0x38, 0x5b, 0xa8, 0x29, 0xf9, 0x27 } + { 0xb2, 0x34, 0xf0, 0xbf, 0x1f, 0x08, 0xd9, 0x11, + 0x95, 0xb7, 0xdf, 0xcc, 0x32, 0xe7, 0x8d, 0x74 }, + { 0xb6, 0x5e, 0x6a, 0x08, 0x0e, 0x09, 0x43, 0x17, + 0xb8, 0x5a, 0xf0, 0x6e, 0xe2, 0x39, 0x5a, 0xfe }, + { 0x6f, 0x95, 0x10, 0x7b, 0x21, 0x05, 0xce, 0x76, + 0x3a, 0xa7, 0x88, 0x23, 0xa1, 0x49, 0x01, 0x44 }, + { 0x17, 0xf3, 0x43, 0xa9, 0xb2, 0x1b, 0xf1, 0xeb, + 0xee, 0xa5, 0x91, 0xa6, 0x39, 0x63, 0xf3, 0x17 }, + { 0x0a, 0xe0, 0x30, 0x7a, 0x2c, 0xe2, 0x29, 0xb5, + 0xa5, 0xae, 0x87, 0xa0, 0xac, 0x79, 0xcb, 0xc0 }, + { 0x23, 0x0c, 0xce, 0xbd, 0xff, 0xde, 0xeb, 0x2f, + 0x16, 0xae, 0xfa, 0x1c, 0x9d, 0x23, 0x23, 0x11 }, + { 0x7b, 0x3f, 0xdd, 0x55, 0x2e, 0xe6, 0xe7, 0x77, + 0x99, 0xc4, 0xb8, 0x9b, 0xe4, 0x1e, 0x48, 0xc9 }, + { 0xb4, 0xb6, 0x7b, 0x40, 0x36, 0x91, 0xe8, 0x71, + 0x55, 0xbf, 0xae, 0xa7, 0x39, 0xb8, 0x33, 0xca }, + { 0xc3, 0xbd, 0xf6, 0xfc, 0x97, 0x36, 0x3c, 0xb6, + 0x25, 0xf8, 0xe4, 0x7c, 0xb2, 0x59, 0xd9, 0x04 }, + { 0xfd, 0x91, 0xe0, 0x28, 0x4c, 0x4c, 0x95, 0x41, + 0x00, 0xdb, 0xb7, 0x7f, 0xf8, 0x66, 0xa0, 0xe3 }, + { 0x76, 0x5b, 0x84, 0x57, 0x03, 0x1b, 0x25, 0x4f, + 0xcd, 0x5b, 0xd4, 0x46, 0x29, 0x0d, 0xc3, 0xa2 }, + { 0xf8, 0xee, 0xcc, 0x0a, 0x46, 0xb5, 0x55, 0xda, + 0x52, 0x34, 0x47, 0x03, 0x3b, 0x71, 0x63, 0x58 }, + { 0xdc, 0x75, 0x20, 0xb8, 0xee, 0x1f, 0x5f, 0xa7, + 0xe8, 0x68, 0x42, 0xd8, 0xcc, 0x44, 0x2a, 0xa7 }, + { 0x9e, 0x6e, 0xcf, 0x07, 0x25, 0x7b, 0x6d, 0xa1, + 0x6c, 0xae, 0xa7, 0x9f, 0x29, 0x56, 0x2f, 0xd9 }, + { 0xe4, 0xea, 0xb1, 0xfe, 0xe1, 0x3c, 0x8c, 0x8c, + 0xa7, 0x64, 0x00, 0x4e, 0x2a, 0x7c, 0x38, 0x6a }, + { 0x27, 0x94, 0x3a, 0x89, 0xa2, 0x13, 0x30, 0xcc, + 0x5b, 0x38, 0x06, 0xf1, 0x27, 0xf9, 0x29, 0xa8 } }; static const uint8_t rtmpe9_keys[16][24] = { @@ -163,7 +163,7 @@ int ff_rtmpe_compute_secret_key(URLContext *h, const uint8_t *serverdata, /* compute the shared secret secret in order to compute RC4 keys */ if ((ret = ff_dh_compute_shared_secret_key(rt->dh, serverdata + server_pos, - 128, secret_key)) < 0) + 128, secret_key, sizeof(secret_key))) < 0) return ret; /* set output key */ @@ -184,14 +184,9 @@ int ff_rtmpe_compute_secret_key(URLContext *h, const uint8_t *serverdata, static void rtmpe8_sig(const uint8_t *in, uint8_t *out, int key_id) { struct AVXTEA ctx; - uint8_t tmpbuf[8]; - - av_xtea_init(&ctx, rtmpe8_keys[key_id]); - AV_WB32(tmpbuf, AV_RL32(in)); - AV_WB32(tmpbuf + 4, AV_RL32(in + 4)); - av_xtea_crypt(&ctx, tmpbuf, tmpbuf, 1, NULL, 0); - AV_WL32(out, AV_RB32(tmpbuf)); - AV_WL32(out + 4, AV_RB32(tmpbuf + 4)); + + av_xtea_le_init(&ctx, rtmpe8_keys[key_id]); + av_xtea_le_crypt(&ctx, out, in, 1, NULL, 0); } static void rtmpe9_sig(const uint8_t *in, uint8_t *out, int key_id) @@ -270,7 +265,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags) /* open the tcp or ffrtmphttp connection */ if ((ret = ffurl_open(&rt->stream, url, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL)) < 0) { + &h->interrupt_callback, NULL, h->protocols, h)) < 0) { rtmpe_close(h); return ret; } @@ -329,7 +324,7 @@ static const AVClass ffrtmpcrypt_class = { .version = LIBAVUTIL_VERSION_INT, }; -URLProtocol ff_ffrtmpcrypt_protocol = { +const URLProtocol ff_ffrtmpcrypt_protocol = { .name = "ffrtmpcrypt", .url_open = rtmpe_open, .url_read = rtmpe_read, diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c index 38c2f3d..e7a83e1 100644 --- a/libavformat/rtmpdh.c +++ b/libavformat/rtmpdh.c @@ -26,10 +26,18 @@ * RTMP Diffie-Hellmann utilities */ +#include +#include + #include "config.h" -#include "rtmpdh.h" + +#include "libavutil/attributes.h" +#include "libavutil/error.h" +#include "libavutil/mem.h" #include "libavutil/random_seed.h" +#include "rtmpdh.h" + #define P1024 \ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ @@ -46,8 +54,8 @@ "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \ "FFFFFFFFFFFFFFFF" -#if CONFIG_NETTLE || CONFIG_GCRYPT -#if CONFIG_NETTLE +#if CONFIG_GMP || CONFIG_GCRYPT +#if CONFIG_GMP #define bn_new(bn) \ do { \ bn = av_malloc(sizeof(*bn)); \ @@ -65,27 +73,36 @@ #define bn_sub_word(bn, w) mpz_sub_ui(bn, bn, w) #define bn_cmp_1(bn) mpz_cmp_ui(bn, 1) #define bn_num_bytes(bn) (mpz_sizeinbase(bn, 2) + 7) / 8 -#define bn_bn2bin(bn, buf, len) nettle_mpz_get_str_256(len, buf, bn) +#define bn_bn2bin(bn, buf, len) \ + do { \ + memset(buf, 0, len); \ + if (bn_num_bytes(bn) <= len) \ + mpz_export(buf, NULL, 1, 1, 0, 0, bn); \ + } while (0) #define bn_bin2bn(bn, buf, len) \ do { \ bn_new(bn); \ if (bn) \ - nettle_mpz_set_str_256_u(bn, len, buf); \ + mpz_import(bn, len, 1, 1, 0, 0, buf); \ } while (0) #define bn_hex2bn(bn, buf, ret) \ do { \ bn_new(bn); \ if (bn) \ ret = (mpz_set_str(bn, buf, 16) == 0); \ + else \ + ret = 1; \ } while (0) #define bn_modexp(bn, y, q, p) mpz_powm(bn, y, q, p) -#define bn_random(bn, num_bytes) \ - do { \ - gmp_randstate_t rs; \ - gmp_randinit_mt(rs); \ - gmp_randseed_ui(rs, av_get_random_seed()); \ - mpz_urandomb(bn, rs, num_bytes); \ - gmp_randclear(rs); \ +#define bn_random(bn, num_bits) \ + do { \ + int bits = num_bits; \ + mpz_set_ui(bn, 0); \ + for (bits = num_bits; bits > 0; bits -= 32) { \ + mpz_mul_2exp(bn, bn, 32); \ + mpz_add_ui(bn, bn, av_get_random_seed()); \ + } \ + mpz_fdiv_r_2exp(bn, bn, num_bits); \ } while (0) #elif CONFIG_GCRYPT #define bn_new(bn) bn = gcry_mpi_new(1) @@ -100,7 +117,7 @@ #define bn_bin2bn(bn, buf, len) gcry_mpi_scan(&bn, GCRYMPI_FMT_USG, buf, len, NULL) #define bn_hex2bn(bn, buf, ret) ret = (gcry_mpi_scan(&bn, GCRYMPI_FMT_HEX, buf, 0, 0) == 0) #define bn_modexp(bn, y, q, p) gcry_mpi_powm(bn, y, q, p) -#define bn_random(bn, num_bytes) gcry_mpi_randomize(bn, num_bytes, GCRY_WEAK_RANDOM) +#define bn_random(bn, num_bits) gcry_mpi_randomize(bn, num_bits, GCRY_WEAK_RANDOM) #endif #define MAX_BYTES 18000 @@ -118,7 +135,7 @@ static FFBigNum dh_generate_key(FF_DH *dh) bn_new(dh->priv_key); if (!dh->priv_key) return NULL; - bn_random(dh->priv_key, num_bytes); + bn_random(dh->priv_key, 8 * num_bytes); bn_new(dh->pub_key); if (!dh->pub_key) { @@ -132,29 +149,26 @@ static FFBigNum dh_generate_key(FF_DH *dh) } static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn, - uint32_t pub_key_len, uint8_t *secret_key) + uint32_t secret_key_len, uint8_t *secret_key) { FFBigNum k; - int num_bytes; - - num_bytes = bn_num_bytes(dh->p); - if (num_bytes <= 0 || num_bytes > MAX_BYTES) - return -1; bn_new(k); if (!k) return -1; bn_modexp(k, pub_key_bn, dh->priv_key, dh->p); - bn_bn2bin(k, secret_key, pub_key_len); + bn_bn2bin(k, secret_key, secret_key_len); bn_free(k); /* return the length of the shared secret key like DH_compute_key */ - return pub_key_len; + return secret_key_len; } void ff_dh_free(FF_DH *dh) { + if (!dh) + return; bn_free(dh->p); bn_free(dh->g); bn_free(dh->pub_key); @@ -187,10 +201,19 @@ void ff_dh_free(FF_DH *dh) #define dh_new() DH_new() #define dh_generate_key(dh) DH_generate_key(dh) -#define dh_compute_key(dh, pub, len, secret) DH_compute_key(secret, pub, dh) + +static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn, + uint32_t secret_key_len, uint8_t *secret_key) +{ + if (secret_key_len < DH_size(dh)) + return AVERROR(EINVAL); + return DH_compute_key(secret_key, pub_key_bn, dh); +} void ff_dh_free(FF_DH *dh) { + if (!dh) + return; DH_free(dh); } #endif @@ -304,7 +327,8 @@ int ff_dh_write_public_key(FF_DH *dh, uint8_t *pub_key, int pub_key_len) } int ff_dh_compute_shared_secret_key(FF_DH *dh, const uint8_t *pub_key, - int pub_key_len, uint8_t *secret_key) + int pub_key_len, uint8_t *secret_key, + int secret_key_len) { FFBigNum q1 = NULL, pub_key_bn = NULL; int ret; @@ -324,7 +348,7 @@ int ff_dh_compute_shared_secret_key(FF_DH *dh, const uint8_t *pub_key, /* when the public key is valid we have to compute the shared secret key */ if ((ret = dh_is_valid_public_key(pub_key_bn, dh->p, q1)) < 0) { goto fail; - } else if ((ret = dh_compute_key(dh, pub_key_bn, pub_key_len, + } else if ((ret = dh_compute_key(dh, pub_key_bn, secret_key_len, secret_key)) < 0) { ret = AVERROR(EINVAL); goto fail; @@ -336,4 +360,3 @@ fail: return ret; } - diff --git a/libavformat/rtmpdh.h b/libavformat/rtmpdh.h index 5de8bde..eb742dd 100644 --- a/libavformat/rtmpdh.h +++ b/libavformat/rtmpdh.h @@ -22,13 +22,13 @@ #ifndef AVFORMAT_RTMPDH_H #define AVFORMAT_RTMPDH_H -#include "avformat.h" +#include + #include "config.h" -#if CONFIG_NETTLE || CONFIG_GCRYPT -#if CONFIG_NETTLE +#if CONFIG_GMP || CONFIG_GCRYPT +#if CONFIG_GMP #include -#include typedef mpz_ptr FFBigNum; #elif CONFIG_GCRYPT @@ -38,11 +38,11 @@ typedef gcry_mpi_t FFBigNum; #endif typedef struct FF_DH { - FFBigNum p; - FFBigNum g; - FFBigNum pub_key; - FFBigNum priv_key; - long length; + FFBigNum p; + FFBigNum g; + FFBigNum pub_key; + FFBigNum priv_key; + long length; } FF_DH; #elif CONFIG_OPENSSL @@ -92,11 +92,13 @@ int ff_dh_write_public_key(FF_DH *dh, uint8_t *pub_key, int pub_key_len); * * @param dh a Diffie-Hellmann context, containing the private key * @param pub_key the buffer containing the public key - * @param pub_key_len the length of the buffer + * @param pub_key_len the length of the public key buffer * @param secret_key the buffer where the secret key is written + * @param secret_key_len the length of the secret key buffer * @return length of the shared secret key on success, negative value otherwise */ int ff_dh_compute_shared_secret_key(FF_DH *dh, const uint8_t *pub_key, - int pub_key_len, uint8_t *secret_key); + int pub_key_len, uint8_t *secret_key, + int secret_key_len); #endif /* AVFORMAT_RTMPDH_H */ diff --git a/libavformat/rtmphttp.c b/libavformat/rtmphttp.c index 34c68fb..5b27ade 100644 --- a/libavformat/rtmphttp.c +++ b/libavformat/rtmphttp.c @@ -129,7 +129,7 @@ static int rtmp_http_read(URLContext *h, uint8_t *buf, int size) } else { if (rt->nb_bytes_read == 0) { /* Wait 50ms before retrying to read a server reply in - * order to reduce the number of idle requets. */ + * order to reduce the number of idle requests. */ av_usleep(50000); } @@ -208,7 +208,7 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags) } /* alloc the http context */ - if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL)) < 0) + if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL, h->protocols)) < 0) goto fail; /* set options */ @@ -265,7 +265,7 @@ static const AVClass ffrtmphttp_class = { .version = LIBAVUTIL_VERSION_INT, }; -URLProtocol ff_ffrtmphttp_protocol = { +const URLProtocol ff_ffrtmphttp_protocol = { .name = "ffrtmphttp", .url_open = rtmp_http_open, .url_read = rtmp_http_read, diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index 37fbb5f..1cb3078 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -235,6 +235,14 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, if (hdr != RTMP_PS_TWELVEBYTES) timestamp += prev_pkt[channel_id].timestamp; + if (prev_pkt[channel_id].read && size != prev_pkt[channel_id].size) { + av_log(h, AV_LOG_ERROR, "RTMP packet size mismatch %d != %d\n", + size, prev_pkt[channel_id].size); + ff_rtmp_packet_destroy(&prev_pkt[channel_id]); + prev_pkt[channel_id].read = 0; + return AVERROR_INVALIDDATA; + } + if (!prev_pkt[channel_id].read) { if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp, size)) < 0) @@ -386,6 +394,13 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, if ((ret = ffurl_write(h, &marker, 1)) < 0) return ret; written++; + if (pkt->ts_field == 0xFFFFFF) { + uint8_t ts_header[4]; + AV_WB32(ts_header, timestamp); + if ((ret = ffurl_write(h, ts_header, 4)) < 0) + return ret; + written += 4; + } } } return written; @@ -395,7 +410,7 @@ int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size) { if (size) { - pkt->data = av_malloc(size); + pkt->data = av_realloc(NULL, size); if (!pkt->data) return AVERROR(ENOMEM); } diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 4aaa420..4107b46 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -27,12 +27,12 @@ #include "libavcodec/bytestream.h" #include "libavutil/avstring.h" #include "libavutil/base64.h" +#include "libavutil/hmac.h" #include "libavutil/intfloat.h" #include "libavutil/lfg.h" #include "libavutil/md5.h" #include "libavutil/opt.h" #include "libavutil/random_seed.h" -#include "libavutil/sha.h" #include "avformat.h" #include "internal.h" @@ -96,6 +96,7 @@ typedef struct RTMPContext { uint32_t client_report_size; ///< number of bytes after which client should report to server uint32_t bytes_read; ///< number of bytes read from server uint32_t last_bytes_read; ///< number of bytes read last reported to server + uint32_t last_timestamp; ///< last timestamp received in a packet int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call int has_audio; ///< presence of audio data int has_video; ///< presence of video data @@ -123,6 +124,7 @@ typedef struct RTMPContext { int listen; ///< listen mode flag int listen_timeout; ///< listen timeout to wait for new connections int nb_streamid; ///< The next stream id to return on createStream calls + double duration; ///< Duration of the stream in seconds as returned by the server (only valid if non-zero) char username[50]; char password[50]; char auth_params[500]; @@ -274,9 +276,6 @@ static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p) *value = '\0'; value++; - if (!field || !value) - goto fail; - ff_amf_write_field_name(p, field); } else { goto fail; @@ -452,7 +451,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) tmpstr, rt->app); ff_rtmp_packet_destroy(&pkt); - // Send Window Acknowledgement Size (as defined in speficication) + // Send Window Acknowledgement Size (as defined in specification) if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4)) < 0) return ret; @@ -493,7 +492,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) return ret; // Chunk size - if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, + if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_CHUNK_SIZE, 0, 4)) < 0) return ret; @@ -505,7 +504,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) if (ret < 0) return ret; - // Send result_ NetConnection.Connect.Success to connect + // Send _result NetConnection.Connect.Success to connect if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, RTMP_PKTDATA_DEFAULT_SIZE)) < 0) @@ -582,7 +581,7 @@ static int gen_release_stream(URLContext *s, RTMPContext *rt) /** * Generate 'FCPublish' call and send it to the server. It should make - * the server preapare for receiving media streams. + * the server prepare for receiving media streams. */ static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt) { @@ -679,6 +678,30 @@ static int gen_delete_stream(URLContext *s, RTMPContext *rt) } /** + * Generate 'getStreamLength' call and send it to the server. If the server + * knows the duration of the selected stream, it will reply with the duration + * in seconds. + */ +static int gen_get_stream_length(URLContext *s, RTMPContext *rt) +{ + RTMPPacket pkt; + uint8_t *p; + int ret; + + if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, + 0, 31 + strlen(rt->playpath))) < 0) + return ret; + + p = pkt.data; + ff_amf_write_string(&p, "getStreamLength"); + ff_amf_write_number(&p, ++rt->nb_invokes); + ff_amf_write_null(&p); + ff_amf_write_string(&p, rt->playpath); + + return rtmp_send_packet(rt, &pkt, 1); +} + +/** * Generate client buffer time and send it to the server. */ static int gen_buffer_time(URLContext *s, RTMPContext *rt) @@ -751,6 +774,33 @@ static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp) } /** + * Generate a pause packet that either pauses or unpauses the current stream. + */ +static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp) +{ + RTMPPacket pkt; + uint8_t *p; + int ret; + + av_log(s, AV_LOG_DEBUG, "Sending pause command for timestamp %d\n", + timestamp); + + if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 29)) < 0) + return ret; + + pkt.extra = rt->stream_id; + + p = pkt.data; + ff_amf_write_string(&p, "pause"); + ff_amf_write_number(&p, 0); //no tracking back responses + ff_amf_write_null(&p); //as usual, the first null param + ff_amf_write_bool(&p, pause); // pause or unpause + ff_amf_write_number(&p, timestamp); //where we pause the stream + + return rtmp_send_packet(rt, &pkt, 1); +} + +/** * Generate 'publish' call and send it to the server. */ static int gen_publish(URLContext *s, RTMPContext *rt) @@ -906,41 +956,22 @@ static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, const uint8_t *key, int keylen, uint8_t *dst) { - struct AVSHA *sha; - uint8_t hmac_buf[64+32] = {0}; - int i; + AVHMAC *hmac; - sha = av_sha_alloc(); - if (!sha) + hmac = av_hmac_alloc(AV_HMAC_SHA256); + if (!hmac) return AVERROR(ENOMEM); - if (keylen < 64) { - memcpy(hmac_buf, key, keylen); - } else { - av_sha_init(sha, 256); - av_sha_update(sha,key, keylen); - av_sha_final(sha, hmac_buf); - } - for (i = 0; i < 64; i++) - hmac_buf[i] ^= HMAC_IPAD_VAL; - - av_sha_init(sha, 256); - av_sha_update(sha, hmac_buf, 64); + av_hmac_init(hmac, key, keylen); if (gap <= 0) { - av_sha_update(sha, src, len); + av_hmac_update(hmac, src, len); } else { //skip 32 bytes used for storing digest - av_sha_update(sha, src, gap); - av_sha_update(sha, src + gap + 32, len - gap - 32); + av_hmac_update(hmac, src, gap); + av_hmac_update(hmac, src + gap + 32, len - gap - 32); } - av_sha_final(sha, hmac_buf + 64); - - for (i = 0; i < 64; i++) - hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad - av_sha_init(sha, 256); - av_sha_update(sha, hmac_buf, 64+32); - av_sha_final(sha, dst); + av_hmac_final(hmac, dst, 32); - av_free(sha); + av_hmac_free(hmac); return 0; } @@ -1088,7 +1119,7 @@ static int rtmp_calc_swfhash(URLContext *s) /* Get the SWF player file. */ if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ, - &s->interrupt_callback, NULL)) < 0) { + &s->interrupt_callback, NULL, s->protocols, s)) < 0) { av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify); goto fail; } @@ -1766,6 +1797,9 @@ static int handle_invoke_error(URLContext *s, RTMPPacket *pkt) /* Gracefully ignore Adobe-specific historical artifact errors. */ level = AV_LOG_WARNING; ret = 0; + } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) { + level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING; + ret = 0; } else if (tracked_method && !strcmp(tracked_method, "connect")) { ret = handle_connect_error(s, tmpstr); if (!ret) { @@ -1857,7 +1891,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; double seqnum; - char filename[64]; + char filename[128]; char command[64]; int stringlen; char *pchar; @@ -1884,6 +1918,13 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) !strcmp(command, "publish")) { ret = ff_amf_read_string(&gbc, filename, sizeof(filename), &stringlen); + if (ret) { + if (ret == AVERROR(EINVAL)) + av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n"); + else + av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n"); + return ret; + } // check with url if (s->filename) { pchar = strrchr(s->filename, '/'); @@ -1953,6 +1994,45 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) return ret; } +/** + * Read the AMF_NUMBER response ("_result") to a function call + * (e.g. createStream()). This response should be made up of the AMF_STRING + * "result", a NULL object and then the response encoded as AMF_NUMBER. On a + * successful response, we will return set the value to number (otherwise number + * will not be changed). + * + * @return 0 if reading the value succeeds, negative value otherwise + */ +static int read_number_result(RTMPPacket *pkt, double *number) +{ + // We only need to fit "_result" in this. + uint8_t strbuffer[8]; + int stringlen; + double numbuffer; + GetByteContext gbc; + + bytestream2_init(&gbc, pkt->data, pkt->size); + + // Value 1/4: "_result" as AMF_STRING + if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen)) + return AVERROR_INVALIDDATA; + if (strcmp(strbuffer, "_result")) + return AVERROR_INVALIDDATA; + // Value 2/4: The callee reference number + if (ff_amf_read_number(&gbc, &numbuffer)) + return AVERROR_INVALIDDATA; + // Value 3/4: Null + if (ff_amf_read_null(&gbc)) + return AVERROR_INVALIDDATA; + // Value 4/4: The response as AMF_NUMBER + if (ff_amf_read_number(&gbc, &numbuffer)) + return AVERROR_INVALIDDATA; + else + *number = numbuffer; + + return 0; +} + static int handle_invoke_result(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; @@ -1994,22 +2074,30 @@ static int handle_invoke_result(URLContext *s, RTMPPacket *pkt) } } } else if (!strcmp(tracked_method, "createStream")) { - //extract a number from the result - if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) { + double stream_id; + if (read_number_result(pkt, &stream_id)) { av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n"); } else { - rt->stream_id = av_int2double(AV_RB64(pkt->data + 21)); + rt->stream_id = stream_id; } if (!rt->is_input) { if ((ret = gen_publish(s, rt)) < 0) goto fail; } else { + if (rt->live != -1) { + if ((ret = gen_get_stream_length(s, rt)) < 0) + goto fail; + } if ((ret = gen_play(s, rt)) < 0) goto fail; if ((ret = gen_buffer_time(s, rt)) < 0) goto fail; } + } else if (!strcmp(tracked_method, "getStreamLength")) { + if (read_number_result(pkt, &rt->duration)) { + av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n"); + } } fail: @@ -2132,7 +2220,7 @@ static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip) bytestream2_put_byte(&pbc, ts >> 24); bytestream2_put_be24(&pbc, 0); bytestream2_put_buffer(&pbc, data, size); - bytestream2_put_be32(&pbc, 0); + bytestream2_put_be32(&pbc, size + RTMP_HEADER); return 0; } @@ -2210,7 +2298,7 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt) switch (pkt->type) { case RTMP_PT_BYTES_READ: - av_dlog(s, "received bytes read report\n"); + av_log(s, AV_LOG_TRACE, "received bytes read report\n"); break; case RTMP_PT_CHUNK_SIZE: if ((ret = handle_chunk_size(s, pkt)) < 0) @@ -2282,8 +2370,9 @@ static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt) bytestream_put_be24(&p, ts); bytestream_put_byte(&p, ts >> 24); memcpy(p, next, size + 3 + 4); + p += size + 3; + bytestream_put_be32(&p, size + RTMP_HEADER); next += size + 3 + 4; - p += size + 3 + 4; } if (p != rt->flv_data + rt->flv_size) { av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in " @@ -2324,6 +2413,10 @@ static int get_packet(URLContext *s, int for_header) return AVERROR(EIO); } } + + // Track timestamp for later use + rt->last_timestamp = rpkt.timestamp; + rt->bytes_read += ret; if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) { av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n"); @@ -2411,6 +2504,70 @@ static int rtmp_close(URLContext *h) } /** + * Insert a fake onMetadata packet into the FLV stream to notify the FLV + * demuxer about the duration of the stream. + * + * This should only be done if there was no real onMetadata packet sent by the + * server at the start of the stream and if we were able to retrieve a valid + * duration via a getStreamLength call. + * + * @return 0 for successful operation, negative value in case of error + */ +static int inject_fake_duration_metadata(RTMPContext *rt) +{ + // We need to insert the metadata packet directly after the FLV + // header, i.e. we need to move all other already read data by the + // size of our fake metadata packet. + + uint8_t* p; + // Keep old flv_data pointer + uint8_t* old_flv_data = rt->flv_data; + // Allocate a new flv_data pointer with enough space for the additional package + if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) { + rt->flv_data = old_flv_data; + return AVERROR(ENOMEM); + } + + // Copy FLV header + memcpy(rt->flv_data, old_flv_data, 13); + // Copy remaining packets + memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13); + // Increase the size by the injected packet + rt->flv_size += 55; + // Delete the old FLV data + av_free(old_flv_data); + + p = rt->flv_data + 13; + bytestream_put_byte(&p, FLV_TAG_TYPE_META); + bytestream_put_be24(&p, 40); // size of data part (sum of all parts below) + bytestream_put_be24(&p, 0); // timestamp + bytestream_put_be32(&p, 0); // reserved + + // first event name as a string + bytestream_put_byte(&p, AMF_DATA_TYPE_STRING); + // "onMetaData" as AMF string + bytestream_put_be16(&p, 10); + bytestream_put_buffer(&p, "onMetaData", 10); + + // mixed array (hash) with size and string/type/data tuples + bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY); + bytestream_put_be32(&p, 1); // metadata_count + + // "duration" as AMF string + bytestream_put_be16(&p, 8); + bytestream_put_buffer(&p, "duration", 8); + bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER); + bytestream_put_be64(&p, av_double2int(rt->duration)); + + // Finalise object + bytestream_put_be16(&p, 0); // Empty string + bytestream_put_byte(&p, AMF_END_OF_OBJECT); + bytestream_put_be32(&p, 40 + RTMP_HEADER); // size of data part (sum of all parts above) + + return 0; +} + +/** * Open RTMP connection and verify that the stream can be played. * * URL syntax: rtmp://server[:port][/app][/playpath] @@ -2491,7 +2648,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) reconnect: if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, &opts)) < 0) { + &s->interrupt_callback, &opts, s->protocols, s)) < 0) { av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf); goto fail; } @@ -2524,8 +2681,8 @@ reconnect: qmark = strchr(path, '?'); if (qmark && strstr(qmark, "slist=")) { char* amp; - // After slist we have the playpath, before the params, the app - av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH)); + // After slist we have the playpath, the full path is used as app + av_strlcpy(rt->app, path + 1, APP_MAX_LENGTH); fname = strstr(path, "slist=") + 6; // Strip any further query parameters from fname amp = strchr(fname, '&'); @@ -2617,6 +2774,7 @@ reconnect: rt->received_metadata = 0; rt->last_bytes_read = 0; rt->server_bw = 2500000; + rt->duration = 0; av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n", proto, path, rt->app, rt->playpath); @@ -2648,11 +2806,10 @@ reconnect: } if (rt->is_input) { - int err; // generate FLV header for demuxer rt->flv_size = 13; - if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) - return err; + if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) + goto fail; rt->flv_off = 0; memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size); @@ -2663,7 +2820,7 @@ reconnect: // audio or video packet arrives. while (!rt->has_audio && !rt->has_video && !rt->received_metadata) { if ((ret = get_packet(s, 0)) < 0) - return ret; + goto fail; } // Either after we have read the metadata or (if there is none) the @@ -2675,6 +2832,14 @@ reconnect: if (rt->has_video) { rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO; } + + // If we received the first packet of an A/V stream and no metadata but + // the server returned a valid duration, create a fake metadata packet + // to inform the FLV decoder about the duration. + if (!rt->received_metadata && rt->duration > 0) { + if ((ret = inject_fake_duration_metadata(rt)) < 0) + goto fail; + } } else { rt->flv_size = 0; rt->flv_data = NULL; @@ -2739,11 +2904,25 @@ static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp, return timestamp; } +static int rtmp_pause(URLContext *s, int pause) +{ + RTMPContext *rt = s->priv_data; + int ret; + av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n", + rt->last_timestamp); + if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) { + av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n", + rt->last_timestamp); + return ret; + } + return 0; +} + static int rtmp_write(URLContext *s, const uint8_t *buf, int size) { RTMPContext *rt = s->priv_data; int size_temp = size; - int pktsize, pkttype; + int pktsize, pkttype, copy; uint32_t ts; const uint8_t *buf_temp = buf; uint8_t c; @@ -2760,8 +2939,8 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) if (rt->flv_header_bytes < RTMP_HEADER) { const uint8_t *header = rt->flv_header; - int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp); int channel = RTMP_AUDIO_CHANNEL; + copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp); bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy); rt->flv_header_bytes += copy; size_temp -= copy; @@ -2778,15 +2957,15 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) if (pkttype == RTMP_PT_VIDEO) channel = RTMP_VIDEO_CHANNEL; - //force 12bytes header if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) || pkttype == RTMP_PT_NOTIFY) { - if (pkttype == RTMP_PT_NOTIFY) - pktsize += 16; if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1], &rt->nb_prev_pkt[1], channel)) < 0) return ret; + // Force sending a full 12 bytes header by clearing the + // channel id, to make it not match a potential earlier + // packet in the same channel. rt->prev_pkt[1][channel].channel_id = 0; } @@ -2797,24 +2976,43 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) rt->out_pkt.extra = rt->stream_id; rt->flv_data = rt->out_pkt.data; - - if (pkttype == RTMP_PT_NOTIFY) - ff_amf_write_string(&rt->flv_data, "@setDataFrame"); } - if (rt->flv_size - rt->flv_off > size_temp) { - bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp); - rt->flv_off += size_temp; - size_temp = 0; - } else { - bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off); - size_temp -= rt->flv_size - rt->flv_off; - rt->flv_off += rt->flv_size - rt->flv_off; - } + copy = FFMIN(rt->flv_size - rt->flv_off, size_temp); + bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy); + rt->flv_off += copy; + size_temp -= copy; if (rt->flv_off == rt->flv_size) { rt->skip_bytes = 4; + if (rt->out_pkt.type == RTMP_PT_NOTIFY) { + // For onMetaData and |RtmpSampleAccess packets, we want + // @setDataFrame prepended to the packet before it gets sent. + // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData + // and onCuePoint). + uint8_t commandbuffer[64]; + int stringlen = 0; + GetByteContext gbc; + + bytestream2_init(&gbc, rt->flv_data, rt->flv_size); + if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer), + &stringlen)) { + if (!strcmp(commandbuffer, "onMetaData") || + !strcmp(commandbuffer, "|RtmpSampleAccess")) { + uint8_t *ptr; + if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) { + rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0; + return ret; + } + memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size); + rt->out_pkt.size += 16; + ptr = rt->out_pkt.data; + ff_amf_write_string(&ptr, "@setDataFrame"); + } + } + } + if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0) return ret; rt->flv_size = 0; @@ -2896,11 +3094,12 @@ static const AVClass flavor##_class = { \ .version = LIBAVUTIL_VERSION_INT, \ }; \ \ -URLProtocol ff_##flavor##_protocol = { \ +const URLProtocol ff_##flavor##_protocol = { \ .name = #flavor, \ .url_open = rtmp_open, \ .url_read = rtmp_read, \ .url_read_seek = rtmp_seek, \ + .url_read_pause = rtmp_pause, \ .url_write = rtmp_write, \ .url_close = rtmp_close, \ .priv_data_size = sizeof(RTMPContext), \ diff --git a/libavformat/rtp.c b/libavformat/rtp.c index 0a3c411..5eb92e4 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -67,19 +67,19 @@ static const struct { {-1, "", AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1} }; -int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type) +int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type) { int i = 0; for (i = 0; rtp_payload_types[i].pt >= 0; i++) if (rtp_payload_types[i].pt == payload_type) { if (rtp_payload_types[i].codec_id != AV_CODEC_ID_NONE) { - codec->codec_type = rtp_payload_types[i].codec_type; - codec->codec_id = rtp_payload_types[i].codec_id; + par->codec_type = rtp_payload_types[i].codec_type; + par->codec_id = rtp_payload_types[i].codec_id; if (rtp_payload_types[i].audio_channels > 0) - codec->channels = rtp_payload_types[i].audio_channels; + par->channels = rtp_payload_types[i].audio_channels; if (rtp_payload_types[i].clock_rate > 0) - codec->sample_rate = rtp_payload_types[i].clock_rate; + par->sample_rate = rtp_payload_types[i].clock_rate; return 0; } } @@ -87,7 +87,7 @@ int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type) } int ff_rtp_get_payload_type(AVFormatContext *fmt, - AVCodecContext *codec, int idx) + AVCodecParameters *par, int idx) { int i; AVOutputFormat *ofmt = fmt ? fmt->oformat : NULL; @@ -102,27 +102,27 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt, /* static payload type */ for (i = 0; rtp_payload_types[i].pt >= 0; ++i) - if (rtp_payload_types[i].codec_id == codec->codec_id) { - if (codec->codec_id == AV_CODEC_ID_H263 && (!fmt || !fmt->oformat || + if (rtp_payload_types[i].codec_id == par->codec_id) { + if (par->codec_id == AV_CODEC_ID_H263 && (!fmt || !fmt->oformat || !fmt->oformat->priv_class || !fmt->priv_data || !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190"))) continue; /* G722 has 8000 as nominal rate even if the sample rate is 16000, * see section 4.5.2 in RFC 3551. */ - if (codec->codec_id == AV_CODEC_ID_ADPCM_G722 && - codec->sample_rate == 16000 && codec->channels == 1) + if (par->codec_id == AV_CODEC_ID_ADPCM_G722 && + par->sample_rate == 16000 && par->channels == 1) return rtp_payload_types[i].pt; - if (codec->codec_type == AVMEDIA_TYPE_AUDIO && + if (par->codec_type == AVMEDIA_TYPE_AUDIO && ((rtp_payload_types[i].clock_rate > 0 && - codec->sample_rate != rtp_payload_types[i].clock_rate) || + par->sample_rate != rtp_payload_types[i].clock_rate) || (rtp_payload_types[i].audio_channels > 0 && - codec->channels != rtp_payload_types[i].audio_channels))) + par->channels != rtp_payload_types[i].audio_channels))) continue; return rtp_payload_types[i].pt; } if (idx < 0) - idx = codec->codec_type == AVMEDIA_TYPE_AUDIO; + idx = par->codec_type == AVMEDIA_TYPE_AUDIO; /* dynamic payload type */ return RTP_PT_PRIVATE + idx; diff --git a/libavformat/rtp.h b/libavformat/rtp.h index feaf167..01b83df 100644 --- a/libavformat/rtp.h +++ b/libavformat/rtp.h @@ -32,11 +32,11 @@ * The format context private option payload_type overrides both. * * @param fmt The context of the format - * @param codec The context of the codec + * @param par The codec parameters * @param idx The stream index * @return The payload type (the 'PT' field in the RTP header). */ -int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecContext *codec, +int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecParameters *par, int idx); /** @@ -46,12 +46,12 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecContext *codec, * information depending on the payload type; for audio codecs, the * channels and sample_rate fields are also filled. * - * @param codec The context of the codec + * @param par The codec parameters * @param payload_type The payload type (the 'PT' field in the RTP header) * @return In case of unknown payload type or dynamic payload type, a * negative value is returned; otherwise, 0 is returned */ -int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type); +int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type); /** * Return the encoding name (as defined in diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 308a48a..4eae626 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -21,8 +21,9 @@ #include "libavutil/mathematics.h" #include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" #include "libavutil/time.h" -#include "libavcodec/get_bits.h" + #include "avformat.h" #include "network.h" #include "srtp.h" @@ -50,6 +51,12 @@ static RTPDynamicProtocolHandler opus_dynamic_handler = { .codec_id = AV_CODEC_ID_OPUS, }; +static RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */ + .enc_name = "t140", + .codec_type = AVMEDIA_TYPE_DATA, + .codec_id = AV_CODEC_ID_TEXT, +}; + static RTPDynamicProtocolHandler *rtp_first_dynamic_payload_handler = NULL; void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler) @@ -60,21 +67,26 @@ void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler) void ff_register_rtp_dynamic_payload_handlers(void) { + ff_register_dynamic_payload_handler(&ff_ac3_dynamic_handler); ff_register_dynamic_payload_handler(&ff_amr_nb_dynamic_handler); ff_register_dynamic_payload_handler(&ff_amr_wb_dynamic_handler); + ff_register_dynamic_payload_handler(&ff_dv_dynamic_handler); ff_register_dynamic_payload_handler(&ff_g726_16_dynamic_handler); ff_register_dynamic_payload_handler(&ff_g726_24_dynamic_handler); ff_register_dynamic_payload_handler(&ff_g726_32_dynamic_handler); ff_register_dynamic_payload_handler(&ff_g726_40_dynamic_handler); + ff_register_dynamic_payload_handler(&ff_h261_dynamic_handler); ff_register_dynamic_payload_handler(&ff_h263_1998_dynamic_handler); ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler); ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler); ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler); + ff_register_dynamic_payload_handler(&ff_hevc_dynamic_handler); ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler); ff_register_dynamic_payload_handler(&ff_jpeg_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mp4a_latm_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mp4v_es_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpeg_audio_dynamic_handler); + ff_register_dynamic_payload_handler(&ff_mpeg_audio_robust_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpeg_video_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler); @@ -90,9 +102,11 @@ void ff_register_rtp_dynamic_payload_handlers(void) ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler); ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler); ff_register_dynamic_payload_handler(&ff_vp8_dynamic_handler); + ff_register_dynamic_payload_handler(&ff_vp9_dynamic_handler); ff_register_dynamic_payload_handler(&opus_dynamic_handler); ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler); ff_register_dynamic_payload_handler(&speex_dynamic_handler); + ff_register_dynamic_payload_handler(&t140_dynamic_handler); } RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, @@ -101,7 +115,8 @@ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, RTPDynamicProtocolHandler *handler; for (handler = rtp_first_dynamic_payload_handler; handler; handler = handler->next) - if (!av_strcasecmp(name, handler->enc_name) && + if (handler->enc_name && + !av_strcasecmp(name, handler->enc_name) && codec_type == handler->codec_type) return handler; return NULL; @@ -129,19 +144,18 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, switch (buf[1]) { case RTCP_SR: if (payload_len < 20) { - av_log(NULL, AV_LOG_ERROR, - "Invalid length for RTCP SR packet\n"); + av_log(s->ic, AV_LOG_ERROR, "Invalid RTCP SR packet length\n"); return AVERROR_INVALIDDATA; } - s->last_rtcp_reception_time = av_gettime(); + s->last_rtcp_reception_time = av_gettime_relative(); s->last_rtcp_ntp_time = AV_RB64(buf + 8); s->last_rtcp_timestamp = AV_RB32(buf + 16); if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) { s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; if (!s->base_timestamp) s->base_timestamp = s->last_rtcp_timestamp; - s->rtcp_ts_offset = s->last_rtcp_timestamp - s->base_timestamp; + s->rtcp_ts_offset = (int32_t)(s->last_rtcp_timestamp - s->base_timestamp); } break; @@ -314,7 +328,7 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, avio_wb32(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 = av_rescale(av_gettime() - s->last_rtcp_reception_time, + uint32_t delay_since_last = av_rescale(av_gettime_relative() - s->last_rtcp_reception_time, 65536, AV_TIME_BASE); avio_wb32(pb, middle_32_bits); /* last SR timestamp */ @@ -341,9 +355,9 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, len = avio_close_dyn_buf(pb, &buf); if ((len > 0) && buf) { int av_unused result; - av_dlog(s->ic, "sending %d bytes of RR\n", len); + av_log(s->ic, AV_LOG_TRACE, "sending %d bytes of RR\n", len); result = ffurl_write(fd, buf, len); - av_dlog(s->ic, "result from ffurl_write: %d\n", result); + av_log(s->ic, AV_LOG_TRACE, "result from ffurl_write: %d\n", result); av_free(buf); } return 0; @@ -439,7 +453,7 @@ int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd, /* Send new feedback if enough time has elapsed since the last * feedback packet. */ - now = av_gettime(); + now = av_gettime_relative(); if (s->last_feedback_time && (now - s->last_feedback_time) < MIN_FEEDBACK_INTERVAL) return 0; @@ -483,7 +497,7 @@ int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd, /** * open a new RTP parse context for stream 'st'. 'st' can be NULL for - * MPEG2-TS streams. + * MPEG-2 TS streams. */ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_type, int queue_size) @@ -499,14 +513,18 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, s->ic = s1; s->st = st; s->queue_size = queue_size; + + av_log(s->ic, AV_LOG_VERBOSE, "setting jitter buffer size to %d\n", + s->queue_size); + rtp_init_statistics(&s->statistics, 0); if (st) { - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_ADPCM_G722: /* According to RFC 3551, the stream clock rate is 8000 * even if the sample rate is 16000. */ - if (st->codec->sample_rate == 8000) - st->codec->sample_rate = 16000; + if (st->codecpar->sample_rate == 8000) + st->codecpar->sample_rate = 16000; break; default: break; @@ -598,7 +616,7 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, 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, + av_log(s->ic, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n", payload_type, seq, ((s->seq + 1) & 0xffff)); return -1; @@ -666,7 +684,7 @@ void ff_rtp_reset_packet_queue(RTPDemuxContext *s) s->prev_ret = 0; } -static void enqueue_packet(RTPDemuxContext *s, uint8_t *buf, int len) +static int enqueue_packet(RTPDemuxContext *s, uint8_t *buf, int len) { uint16_t seq = AV_RB16(buf + 2); RTPPacket **cur = &s->queue, *packet; @@ -681,14 +699,16 @@ static void enqueue_packet(RTPDemuxContext *s, uint8_t *buf, int len) packet = av_mallocz(sizeof(*packet)); if (!packet) - return; - packet->recvtime = av_gettime(); + return AVERROR(ENOMEM); + packet->recvtime = av_gettime_relative(); packet->seq = seq; packet->len = len; packet->buf = buf; packet->next = *cur; *cur = packet; s->queue_len++; + + return 0; } static int has_next_packet(RTPDemuxContext *s) @@ -710,7 +730,7 @@ static int rtp_parse_queued_packet(RTPDemuxContext *s, AVPacket *pkt) return -1; if (!has_next_packet(s)) - av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING, + av_log(s->ic, AV_LOG_WARNING, "RTP: missed %d packets\n", s->queue->seq - s->seq - 1); /* Parse the first packet in the queue, and dequeue it */ @@ -760,7 +780,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt, } if (s->st) { - int64_t received = av_gettime(); + int64_t received = av_gettime_relative(); uint32_t arrival_ts = av_rescale_q(received, AV_TIME_BASE_Q, s->st->time_base); timestamp = AV_RB32(buf + 4); @@ -777,7 +797,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt, int16_t diff = seq - s->seq; if (diff < 0) { /* Packet older than the previously emitted one, drop */ - av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING, + av_log(s->ic, AV_LOG_WARNING, "RTP: dropping old packet received too late\n"); return -1; } else if (diff <= 1) { @@ -786,12 +806,16 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt, return rv; } else { /* Still missing some packet, enqueue this one. */ - enqueue_packet(s, buf, len); + rv = enqueue_packet(s, buf, len); + if (rv < 0) + return rv; *bufptr = NULL; /* Return the first enqueued packet if the queue is full, * even if we're missing something */ - if (s->queue_len >= s->queue_size) + if (s->queue_len >= s->queue_size) { + av_log(s->ic, AV_LOG_WARNING, "jitter buffer full\n"); return rtp_parse_queued_packet(s, pkt); + } return -1; } } @@ -814,7 +838,7 @@ int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, return -1; rv = rtp_parse_one_packet(s, pkt, bufptr, len); s->prev_ret = rv; - while (rv == AVERROR(EAGAIN) && has_next_packet(s)) + while (rv < 0 && has_next_packet(s)) rv = rtp_parse_queued_packet(s, pkt); return rv ? rv : has_next_packet(s); } @@ -831,7 +855,7 @@ int ff_parse_fmtp(AVFormatContext *s, int (*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value)) + const char *attr, const char *value)) { char attr[256]; char *value; @@ -839,7 +863,7 @@ int ff_parse_fmtp(AVFormatContext *s, int value_size = strlen(p) + 1; if (!(value = av_malloc(value_size))) { - av_log(NULL, AV_LOG_ERROR, "Failed to allocate data for FMTP."); + av_log(s, AV_LOG_ERROR, "Failed to allocate data for FMTP."); return AVERROR(ENOMEM); } diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 46b08ce..a0c5f77 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -35,7 +35,7 @@ typedef struct RTPDynamicProtocolHandler RTPDynamicProtocolHandler; #define RTP_MIN_PACKET_LENGTH 12 #define RTP_MAX_PACKET_LENGTH 8192 -#define RTP_REORDER_QUEUE_DEFAULT_SIZE 10 +#define RTP_REORDER_QUEUE_DEFAULT_SIZE 500 #define RTP_NOTS_VALUE ((uint32_t)-1) @@ -113,22 +113,24 @@ typedef int (*DynamicPayloadPacketHandlerProc)(AVFormatContext *ctx, int len, uint16_t seq, int flags); struct RTPDynamicProtocolHandler { - const char enc_name[50]; + const char *enc_name; enum AVMediaType codec_type; enum AVCodecID codec_id; + enum AVStreamParseType need_parsing; int static_payload_id; /* 0 means no payload id is set. 0 is a valid * payload ID (PCMU), too, but that format doesn't * require any custom depacketization code. */ + int priv_data_size; /** Initialize dynamic protocol handler, called after the full rtpmap line is parsed, may be null */ int (*init)(AVFormatContext *s, int st_index, PayloadContext *priv_data); /** Parse the a= line from the sdp field */ int (*parse_sdp_a_line)(AVFormatContext *s, int st_index, PayloadContext *priv_data, const char *line); - /** Allocate any data needed by the rtp parsing for this dynamic data. */ - PayloadContext *(*alloc)(void); - /** Free any data needed by the rtp parsing for this dynamic data. */ - void (*free)(PayloadContext *protocol_data); + /** Free any data needed by the rtp parsing for this dynamic data. + * Don't free the protocol_data pointer itself, that is freed by the + * caller. This is called even if the init method failed. */ + void (*close)(PayloadContext *protocol_data); /** Parse handler for this dynamic packet */ DynamicPayloadPacketHandlerProc parse_packet; int (*need_keyframe)(PayloadContext *context); @@ -205,7 +207,7 @@ int ff_parse_fmtp(AVFormatContext *s, int (*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value)); + const char *attr, const char *value)); void ff_register_rtp_dynamic_payload_handlers(void); diff --git a/libavformat/rtpdec_ac3.c b/libavformat/rtpdec_ac3.c new file mode 100644 index 0000000..e519b28 --- /dev/null +++ b/libavformat/rtpdec_ac3.c @@ -0,0 +1,133 @@ +/* + * RTP parser for AC3 payload format (RFC 4184) + * Copyright (c) 2015 Gilles Chanteperdrix + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "avio_internal.h" +#include "rtpdec_formats.h" + +#define RTP_AC3_PAYLOAD_HEADER_SIZE 2 + +struct PayloadContext { + unsigned nr_frames; + unsigned last_frame; + uint32_t timestamp; + AVIOContext *fragment; +}; + +static void ac3_close_context(PayloadContext *data) +{ + ffio_free_dyn_buf(&data->fragment); +} + +static int ac3_handle_packet(AVFormatContext *ctx, PayloadContext *data, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, uint16_t seq, + int flags) +{ + unsigned frame_type; + unsigned nr_frames; + int err; + + if (len < RTP_AC3_PAYLOAD_HEADER_SIZE + 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid %d bytes packet\n", len); + return AVERROR_INVALIDDATA; + } + + frame_type = buf[0] & 0x3; + nr_frames = buf[1]; + buf += RTP_AC3_PAYLOAD_HEADER_SIZE; + len -= RTP_AC3_PAYLOAD_HEADER_SIZE; + + switch (frame_type) { + case 0: /* One or more complete frames */ + if (!nr_frames) { + av_log(ctx, AV_LOG_ERROR, "Invalid AC3 packet data\n"); + return AVERROR_INVALIDDATA; + } + if (av_new_packet(pkt, len)) { + av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); + return AVERROR(ENOMEM); + } + + pkt->stream_index = st->index; + memcpy(pkt->data, buf, len); + return 0; + + case 1: + case 2: /* First fragment */ + ffio_free_dyn_buf(&data->fragment); + + data->last_frame = 1; + data->nr_frames = nr_frames; + err = avio_open_dyn_buf(&data->fragment); + if (err < 0) + return err; + + avio_write(data->fragment, buf, len); + data->timestamp = *timestamp; + return AVERROR(EAGAIN); + + case 3: /* Fragment other than first */ + if (!data->fragment) { + av_log(ctx, AV_LOG_WARNING, + "Received packet without a start fragment; dropping.\n"); + return AVERROR(EAGAIN); + } + if (nr_frames != data->nr_frames || + data->timestamp != *timestamp) { + ffio_free_dyn_buf(&data->fragment); + av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); + return AVERROR_INVALIDDATA; + } + + avio_write(data->fragment, buf, len); + data->last_frame++; + } + + if (!(flags & RTP_FLAG_MARKER)) + return AVERROR(EAGAIN); + + if (data->last_frame != data->nr_frames) { + ffio_free_dyn_buf(&data->fragment); + av_log(ctx, AV_LOG_ERROR, "Missed %d packets\n", + data->nr_frames - data->last_frame); + return AVERROR_INVALIDDATA; + } + + err = ff_rtp_finalize_packet(pkt, &data->fragment, st->index); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error occurred when getting fragment buffer.\n"); + return err; + } + + return 0; +} + +RTPDynamicProtocolHandler ff_ac3_dynamic_handler = { + .enc_name = "ac3", + .codec_type = AVMEDIA_TYPE_AUDIO, + .codec_id = AV_CODEC_ID_AC3, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), + .close = ac3_close_context, + .parse_packet = ac3_handle_packet, +}; diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c index 86348bb..baf4de9 100644 --- a/libavformat/rtpdec_amr.c +++ b/libavformat/rtpdec_amr.c @@ -38,17 +38,10 @@ struct PayloadContext { int channels; }; -static PayloadContext *amr_new_context(void) +static av_cold int amr_init(AVFormatContext *s, int st_index, PayloadContext *data) { - PayloadContext *data = av_mallocz(sizeof(PayloadContext)); - if(!data) return data; data->channels = 1; - return data; -} - -static void amr_free_context(PayloadContext *data) -{ - av_free(data); + return 0; } static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, @@ -62,20 +55,20 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, const uint8_t *speech_data; uint8_t *ptr; - if (st->codec->codec_id == AV_CODEC_ID_AMR_NB) { + if (st->codecpar->codec_id == AV_CODEC_ID_AMR_NB) { frame_sizes = frame_sizes_nb; - } else if (st->codec->codec_id == AV_CODEC_ID_AMR_WB) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_AMR_WB) { frame_sizes = frame_sizes_wb; } else { av_log(ctx, AV_LOG_ERROR, "Bad codec ID\n"); return AVERROR_INVALIDDATA; } - if (st->codec->channels != 1) { + if (st->codecpar->channels != 1) { av_log(ctx, AV_LOG_ERROR, "Only mono AMR is supported\n"); return AVERROR_INVALIDDATA; } - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; /* The AMR RTP packet consists of one header byte, followed * by one TOC byte for each AMR frame in the packet, followed @@ -141,7 +134,7 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, static int amr_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value) + const char *attr, const char *value) { /* Some AMR SDP configurations contain "octet-align", without * the trailing =1. Therefore, if the value is empty, @@ -150,7 +143,7 @@ static int amr_parse_fmtp(AVFormatContext *s, if (!strcmp(value, "")) { av_log(s, AV_LOG_WARNING, "AMR fmtp attribute %s had " "nonstandard empty value\n", attr); - strcpy(value, "1"); + value = "1"; } if (!strcmp(attr, "octet-align")) data->octet_align = atoi(value); @@ -193,9 +186,9 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = { .enc_name = "AMR", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AMR_NB, + .priv_data_size = sizeof(PayloadContext), + .init = amr_init, .parse_sdp_a_line = amr_parse_sdp_line, - .alloc = amr_new_context, - .free = amr_free_context, .parse_packet = amr_handle_packet, }; @@ -203,8 +196,8 @@ RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = { .enc_name = "AMR-WB", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AMR_WB, + .priv_data_size = sizeof(PayloadContext), + .init = amr_init, .parse_sdp_a_line = amr_parse_sdp_line, - .alloc = amr_new_context, - .free = amr_free_context, .parse_packet = amr_handle_packet, }; diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index 61b1419..d4972bd 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -102,6 +102,9 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p) AVDictionary *opts = NULL; int len = strlen(p) * 6 / 8; char *buf = av_mallocz(len); + + if (!buf) + return AVERROR(ENOMEM); av_base64_decode(buf, p, len); if (rtp_asf_fix_header(buf, len) < 0) @@ -111,14 +114,19 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p) if (rt->asf_ctx) { avformat_close_input(&rt->asf_ctx); } - if (!(rt->asf_ctx = avformat_alloc_context())) + rt->asf_ctx = avformat_alloc_context(); + if (!rt->asf_ctx) { + av_free(buf); return AVERROR(ENOMEM); + } rt->asf_ctx->pb = &pb; av_dict_set(&opts, "no_resync_search", "1", 0); ret = avformat_open_input(&rt->asf_ctx, "", &ff_asf_demuxer, &opts); av_dict_free(&opts); - if (ret < 0) + if (ret < 0) { + av_free(buf); return ret; + } av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0); rt->asf_pb_pos = avio_tell(&pb); av_free(buf); @@ -142,12 +150,10 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index, for (i = 0; i < rt->asf_ctx->nb_streams; i++) { if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) { - *s->streams[stream_index]->codec = - *rt->asf_ctx->streams[i]->codec; + avcodec_parameters_copy(s->streams[stream_index]->codecpar, + rt->asf_ctx->streams[i]->codecpar); s->streams[stream_index]->need_parsing = rt->asf_ctx->streams[i]->need_parsing; - rt->asf_ctx->streams[i]->codec->extradata_size = 0; - rt->asf_ctx->streams[i]->codec->extradata = NULL; avpriv_set_pts_info(s->streams[stream_index], 32, 1, 1000); } } @@ -194,8 +200,6 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf, int start_off = avio_tell(pb); mflags = avio_r8(pb); - if (mflags & 0x80) - flags |= RTP_FLAG_KEY; len_off = avio_rb24(pb); if (mflags & 0x20) /**< relative timestamp */ avio_skip(pb, 4); @@ -213,10 +217,7 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf, * multiple RTP packets. */ if (asf->pktbuf && len_off != avio_tell(asf->pktbuf)) { - uint8_t *p; - avio_close_dyn_buf(asf->pktbuf, &p); - asf->pktbuf = NULL; - av_free(p); + ffio_free_dyn_buf(&asf->pktbuf); } if (!len_off && !asf->pktbuf && (res = avio_open_dyn_buf(&asf->pktbuf)) < 0) @@ -271,27 +272,16 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf, return 1; // FIXME: return 0 if last packet } } - av_free_packet(pkt); + av_packet_unref(pkt); } return res == 1 ? -1 : res; } -static PayloadContext *asfrtp_new_context(void) +static void asfrtp_close_context(PayloadContext *asf) { - return av_mallocz(sizeof(PayloadContext)); -} - -static void asfrtp_free_context(PayloadContext *asf) -{ - if (asf->pktbuf) { - uint8_t *p = NULL; - avio_close_dyn_buf(asf->pktbuf, &p); - asf->pktbuf = NULL; - av_free(p); - } + ffio_free_dyn_buf(&asf->pktbuf); av_freep(&asf->buf); - av_free(asf); } #define RTP_ASF_HANDLER(n, s, t) \ @@ -299,9 +289,9 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ + .priv_data_size = sizeof(PayloadContext), \ .parse_sdp_a_line = asfrtp_parse_sdp_line, \ - .alloc = asfrtp_new_context, \ - .free = asfrtp_free_context, \ + .close = asfrtp_close_context, \ .parse_packet = asfrtp_parse_packet, \ } diff --git a/libavformat/rtpdec_dv.c b/libavformat/rtpdec_dv.c new file mode 100644 index 0000000..09d497a --- /dev/null +++ b/libavformat/rtpdec_dv.c @@ -0,0 +1,143 @@ +/* + * RTP parser for DV payload format (RFC 6469) + * Copyright (c) 2015 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" + +#include "libavcodec/bytestream.h" + +#include "avio_internal.h" +#include "rtpdec_formats.h" + +struct PayloadContext { + AVIOContext *buf; + uint32_t timestamp; + int bundled_audio; +}; + +static av_cold void dv_close_context(PayloadContext *data) +{ + ffio_free_dyn_buf(&data->buf); +} + +static av_cold int dv_sdp_parse_fmtp_config(AVFormatContext *s, + AVStream *stream, + PayloadContext *dv_data, + const char *attr, const char *value) +{ + /* does the DV stream include audio? */ + if (!strcmp(attr, "audio") && !strcmp(value, "bundled")) + dv_data->bundled_audio = 1; + + /* extract the DV profile */ + if (!strcmp(attr, "encode")) { + /* SD-VCR/525-60 */ + /* SD-VCR/625-50 */ + /* HD-VCR/1125-60 */ + /* HD-VCR/1250-50 */ + /* SDL-VCR/525-60 */ + /* SDL-VCR/625-50 */ + /* 314M-25/525-60 */ + /* 314M-25/625-50 */ + /* 314M-50/525-60 */ + /* 314M-50/625-50 */ + /* 370M/1080-60i */ + /* 370M/1080-50i */ + /* 370M/720-60p */ + /* 370M/720-50p */ + /* 306M/525-60 (for backward compatibility) */ + /* 306M/625-50 (for backward compatibility) */ + } + + return 0; +} + +static av_cold int dv_parse_sdp_line(AVFormatContext *ctx, int st_index, + PayloadContext *dv_data, const char *line) +{ + AVStream *current_stream; + const char *sdp_line_ptr = line; + + if (st_index < 0) + return 0; + + current_stream = ctx->streams[st_index]; + + if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) { + return ff_parse_fmtp(ctx, current_stream, dv_data, sdp_line_ptr, + dv_sdp_parse_fmtp_config); + } + + return 0; +} + +static int dv_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_dv_ctx, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, uint16_t seq, + int flags) +{ + int res = 0; + + /* drop data of previous packets in case of non-continuous (lossy) packet stream */ + if (rtp_dv_ctx->buf && rtp_dv_ctx->timestamp != *timestamp) { + ffio_free_dyn_buf(&rtp_dv_ctx->buf); + } + + /* sanity check for size of input packet: 1 byte payload at least */ + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/DV packet, got %d bytes\n", len); + return AVERROR_INVALIDDATA; + } + + /* start frame buffering with new dynamic buffer */ + if (!rtp_dv_ctx->buf) { + res = avio_open_dyn_buf(&rtp_dv_ctx->buf); + if (res < 0) + return res; + /* update the timestamp in the frame packet with the one from the RTP packet */ + rtp_dv_ctx->timestamp = *timestamp; + } + + /* write the fragment to the dyn. buffer */ + avio_write(rtp_dv_ctx->buf, buf, len); + + /* RTP marker bit means: last fragment of current frame was received; + otherwise, an additional fragment is needed for the current frame */ + if (!(flags & RTP_FLAG_MARKER)) + return AVERROR(EAGAIN); + + /* close frame buffering and create resulting A/V packet */ + res = ff_rtp_finalize_packet(pkt, &rtp_dv_ctx->buf, st->index); + if (res < 0) + return res; + + return 0; +} + +RTPDynamicProtocolHandler ff_dv_dynamic_handler = { + .enc_name = "DV", + .codec_type = AVMEDIA_TYPE_VIDEO, + .codec_id = AV_CODEC_ID_DVVIDEO, + .need_parsing = AVSTREAM_PARSE_FULL, + .parse_sdp_a_line = dv_parse_sdp_line, + .priv_data_size = sizeof(PayloadContext), + .close = dv_close_context, + .parse_packet = dv_handle_packet, +}; diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h index e5f4ccb..5424c17 100644 --- a/libavformat/rtpdec_formats.h +++ b/libavformat/rtpdec_formats.h @@ -35,21 +35,38 @@ int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags); +int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, + uint8_t **data_ptr, int *size_ptr, + const char *value); +int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, AVPacket *pkt, + const uint8_t *buf, int len, + int start_skip, int *nal_counters, + int nal_mask); +int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, + int start_bit, const uint8_t *nal_header, + int nal_header_len); +void ff_h264_parse_framesize(AVCodecParameters *par, const char *p); + +extern RTPDynamicProtocolHandler ff_ac3_dynamic_handler; extern RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler; extern RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler; +extern RTPDynamicProtocolHandler ff_dv_dynamic_handler; extern RTPDynamicProtocolHandler ff_g726_16_dynamic_handler; extern RTPDynamicProtocolHandler ff_g726_24_dynamic_handler; extern RTPDynamicProtocolHandler ff_g726_32_dynamic_handler; extern RTPDynamicProtocolHandler ff_g726_40_dynamic_handler; +extern RTPDynamicProtocolHandler ff_h261_dynamic_handler; extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler; extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; extern RTPDynamicProtocolHandler ff_h264_dynamic_handler; +extern RTPDynamicProtocolHandler ff_hevc_dynamic_handler; extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler; extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; extern RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler; +extern RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler; extern RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler; extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; extern RTPDynamicProtocolHandler ff_mpegts_dynamic_handler; @@ -65,5 +82,6 @@ extern RTPDynamicProtocolHandler ff_svq3_dynamic_handler; extern RTPDynamicProtocolHandler ff_theora_dynamic_handler; extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler; extern RTPDynamicProtocolHandler ff_vp8_dynamic_handler; +extern RTPDynamicProtocolHandler ff_vp9_dynamic_handler; #endif /* AVFORMAT_RTPDEC_FORMATS_H */ diff --git a/libavformat/rtpdec_g726.c b/libavformat/rtpdec_g726.c index 7b3f6cb..53889bf 100644 --- a/libavformat/rtpdec_g726.c +++ b/libavformat/rtpdec_g726.c @@ -27,10 +27,10 @@ static av_cold int g726_ ## bitrate ##_init(AVFormatContext *s, int st_index, \ PayloadContext *data) \ { \ AVStream *stream = s->streams[st_index]; \ - AVCodecContext *codec = stream->codec; \ + AVCodecParameters *par = stream->codecpar; \ \ - codec->bits_per_coded_sample = bitrate/8; \ - codec->bit_rate = codec->bits_per_coded_sample * codec->sample_rate; \ + par->bits_per_coded_sample = bitrate/8; \ + par->bit_rate = par->bits_per_coded_sample * par->sample_rate; \ \ return 0; \ } \ diff --git a/libavformat/rtpdec_h261.c b/libavformat/rtpdec_h261.c new file mode 100644 index 0000000..00086c2 --- /dev/null +++ b/libavformat/rtpdec_h261.c @@ -0,0 +1,174 @@ +/* + * RTP parser for H.261 payload format (RFC 4587) + * Copyright (c) 2014 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/get_bits.h" +#include "avformat.h" +#include "avio_internal.h" +#include "rtpdec_formats.h" + +#define RTP_H261_PAYLOAD_HEADER_SIZE 4 + +struct PayloadContext { + AVIOContext *buf; + uint8_t endbyte; + int endbyte_bits; + uint32_t timestamp; +}; + +static av_cold void h261_close_context(PayloadContext *pl_ctx) +{ + /* return if context is invalid */ + if (!pl_ctx) + return; + + /* free buffer if it is valid */ + ffio_free_dyn_buf(&pl_ctx->buf); +} + +static int h261_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_h261_ctx, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, uint16_t seq, + int flags) +{ + int sbit, ebit, gobn, mbap, quant; + int res; + + /* drop data of previous packets in case of non-continuous (lossy) packet stream */ + if (rtp_h261_ctx->buf && rtp_h261_ctx->timestamp != *timestamp) { + ffio_free_dyn_buf(&rtp_h261_ctx->buf); + rtp_h261_ctx->endbyte_bits = 0; + } + + /* sanity check for size of input packet: 1 byte payload at least */ + if (len < RTP_H261_PAYLOAD_HEADER_SIZE + 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/H.261 packet, got %d bytes\n", len); + return AVERROR_INVALIDDATA; + } + + /* + * decode the H.261 payload header according to section 4.1 of RFC 4587: + * (uses 4 bytes between RTP header and H.261 stream per packet) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Start bit position (SBIT): 3 bits + * End bit position (EBIT): 3 bits + * INTRA-frame encoded data (I): 1 bit + * Motion Vector flag (V): 1 bit + * GOB number (GOBN): 4 bits + * Macroblock address predictor (MBAP): 5 bits + * Quantizer (QUANT): 5 bits + * Horizontal motion vector data (HMVD): 5 bits + * Vertical motion vector data (VMVD): 5 bits + */ + sbit = (buf[0] >> 5) & 0x07; + ebit = (buf[0] >> 2) & 0x07; + gobn = (buf[1] >> 4) & 0x0f; + mbap = ((buf[1] << 1) & 0x1e) | ((buf[2] >> 7) & 0x01); + quant = (buf[2] >> 2) & 0x1f; + + /* pass the H.261 payload header and continue with the actual payload */ + buf += RTP_H261_PAYLOAD_HEADER_SIZE; + len -= RTP_H261_PAYLOAD_HEADER_SIZE; + + /* start frame buffering with new dynamic buffer */ + if (!rtp_h261_ctx->buf) { + /* sanity check: a new frame starts with gobn=0, sbit=0, mbap=0, quant=0 */ + if (!gobn && !sbit && !mbap && !quant) { + res = avio_open_dyn_buf(&rtp_h261_ctx->buf); + if (res < 0) + return res; + /* update the timestamp in the frame packet with the one from the RTP packet */ + rtp_h261_ctx->timestamp = *timestamp; + } else { + /* frame not started yet, need more packets */ + return AVERROR(EAGAIN); + } + } + + /* do the "byte merging" at the boundaries of two consecutive frame fragments */ + if (rtp_h261_ctx->endbyte_bits || sbit) { + if (rtp_h261_ctx->endbyte_bits == sbit) { + rtp_h261_ctx->endbyte |= buf[0] & (0xff >> sbit); + rtp_h261_ctx->endbyte_bits = 0; + buf++; + len--; + avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte); + } else { + /* ebit/sbit values inconsistent, assuming packet loss */ + GetBitContext gb; + init_get_bits(&gb, buf, len*8 - ebit); + skip_bits(&gb, sbit); + if (rtp_h261_ctx->endbyte_bits) { + rtp_h261_ctx->endbyte |= get_bits(&gb, 8 - rtp_h261_ctx->endbyte_bits); + avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte); + } + while (get_bits_left(&gb) >= 8) + avio_w8(rtp_h261_ctx->buf, get_bits(&gb, 8)); + rtp_h261_ctx->endbyte_bits = get_bits_left(&gb); + if (rtp_h261_ctx->endbyte_bits) + rtp_h261_ctx->endbyte = get_bits(&gb, rtp_h261_ctx->endbyte_bits) << + (8 - rtp_h261_ctx->endbyte_bits); + ebit = 0; + len = 0; + } + } + if (ebit) { + if (len > 0) + avio_write(rtp_h261_ctx->buf, buf, len - 1); + rtp_h261_ctx->endbyte_bits = 8 - ebit; + rtp_h261_ctx->endbyte = buf[len - 1] & (0xff << ebit); + } else { + avio_write(rtp_h261_ctx->buf, buf, len); + } + + /* RTP marker bit means: last fragment of current frame was received; + otherwise, an additional fragment is needed for the current frame */ + if (!(flags & RTP_FLAG_MARKER)) + return AVERROR(EAGAIN); + + /* write the completed last byte from the "byte merging" */ + if (rtp_h261_ctx->endbyte_bits) + avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte); + rtp_h261_ctx->endbyte_bits = 0; + + /* close frame buffering and create resulting A/V packet */ + res = ff_rtp_finalize_packet(pkt, &rtp_h261_ctx->buf, st->index); + if (res < 0) + return res; + + return 0; +} + +RTPDynamicProtocolHandler ff_h261_dynamic_handler = { + .enc_name = "H261", + .codec_type = AVMEDIA_TYPE_VIDEO, + .codec_id = AV_CODEC_ID_H261, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), + .close = h261_close_context, + .parse_packet = h261_handle_packet, + .static_payload_id = 31, +}; diff --git a/libavformat/rtpdec_h263.c b/libavformat/rtpdec_h263.c index b371491..710cfd2 100644 --- a/libavformat/rtpdec_h263.c +++ b/libavformat/rtpdec_h263.c @@ -24,15 +24,6 @@ #include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" -static av_cold int h263_init(AVFormatContext *ctx, int st_index, - PayloadContext *data) -{ - if (st_index < 0) - return 0; - ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; -} - int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags) @@ -102,7 +93,7 @@ RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { .enc_name = "H263-1998", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, - .init = h263_init, + .need_parsing = AVSTREAM_PARSE_FULL, .parse_packet = ff_h263_handle_packet, }; @@ -110,6 +101,6 @@ RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler = { .enc_name = "H263-2000", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, - .init = h263_init, + .need_parsing = AVSTREAM_PARSE_FULL, .parse_packet = ff_h263_handle_packet, }; diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c index d507ef7..019eea7 100644 --- a/libavformat/rtpdec_h263_rfc2190.c +++ b/libavformat/rtpdec_h263_rfc2190.c @@ -26,6 +26,7 @@ */ #include "avformat.h" +#include "avio_internal.h" #include "rtpdec_formats.h" #include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" @@ -39,29 +40,9 @@ struct PayloadContext { int newformat; }; -static PayloadContext *h263_new_context(void) +static void h263_close_context(PayloadContext *data) { - return av_mallocz(sizeof(PayloadContext)); -} - -static void h263_free_context(PayloadContext *data) -{ - if (!data) - return; - if (data->buf) { - uint8_t *p; - avio_close_dyn_buf(data->buf, &p); - av_free(p); - } - av_free(data); -} - -static av_cold int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) -{ - if (st_index < 0) - return 0; - ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; + ffio_free_dyn_buf(&data->buf); } static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, @@ -79,10 +60,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, if (data->buf && data->timestamp != *timestamp) { /* Dropping old buffered, unfinished data */ - uint8_t *p; - avio_close_dyn_buf(data->buf, &p); - av_free(p); - data->buf = NULL; + ffio_free_dyn_buf(&data->buf); data->endbyte_bits = 0; } @@ -129,7 +107,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, /* Invalid src for this format, and bits that should be zero * according to RFC 2190 aren't zero. */ av_log(ctx, AV_LOG_WARNING, - "Interpreting H263 RTP data as RFC 2429/4629 even though " + "Interpreting H.263 RTP data as RFC 2429/4629 even though " "signalled with a static payload type.\n"); data->newformat = 1; return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf, @@ -208,9 +186,9 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = { .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, - .init = h263_init, + .need_parsing = AVSTREAM_PARSE_FULL, .parse_packet = h263_handle_packet, - .alloc = h263_new_context, - .free = h263_free_context, + .priv_data_size = sizeof(PayloadContext), + .close = h263_close_context, .static_payload_id = 34, }; diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index abf1f39..401d6f6 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -1,5 +1,5 @@ /* - * RTP H264 Protocol (RFC3984) + * RTP H.264 Protocol (RFC3984) * Copyright (c) 2006 Ryan Martell * * This file is part of Libav. @@ -35,13 +35,10 @@ #include "libavutil/attributes.h" #include "libavutil/base64.h" +#include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" -#include "libavcodec/get_bits.h" #include "avformat.h" -#include "network.h" -#include - #include "rtpdec.h" #include "rtpdec_formats.h" @@ -58,20 +55,98 @@ struct PayloadContext { #ifdef DEBUG #define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++ +#define NAL_COUNTERS data->packet_types_received #else #define COUNT_NAL_TYPE(data, nal) do { } while (0) +#define NAL_COUNTERS NULL #endif +#define NAL_MASK 0x1f static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; +static void parse_profile_level_id(AVFormatContext *s, + PayloadContext *h264_data, + const char *value) +{ + 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); + + av_log(s, AV_LOG_DEBUG, + "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; +} + +int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, + uint8_t **data_ptr, int *size_ptr, + const char *value) +{ + char base64packet[1024]; + uint8_t decoded_packet[1024]; + int packet_size; + + while (*value) { + 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 > 0) { + uint8_t *dest = av_realloc(*data_ptr, + packet_size + sizeof(start_sequence) + + *size_ptr + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!dest) { + av_log(s, AV_LOG_ERROR, + "Unable to allocate memory for extradata!\n"); + return AVERROR(ENOMEM); + } + *data_ptr = dest; + + memcpy(dest + *size_ptr, start_sequence, + sizeof(start_sequence)); + memcpy(dest + *size_ptr + sizeof(start_sequence), + decoded_packet, packet_size); + memset(dest + *size_ptr + sizeof(start_sequence) + + packet_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + *size_ptr += sizeof(start_sequence) + packet_size; + } + } + + return 0; +} + static int sdp_parse_fmtp_config_h264(AVFormatContext *s, AVStream *stream, PayloadContext *h264_data, - char *attr, char *value) + const char *attr, const char *value) { - AVCodecContext *codec = stream->codec; - assert(codec->codec_id == AV_CODEC_ID_H264); - assert(h264_data != NULL); + AVCodecParameters *par = stream->codecpar; if (!strcmp(attr, "packetization-mode")) { av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); @@ -87,83 +162,148 @@ static int sdp_parse_fmtp_config_h264(AVFormatContext *s, av_log(s, AV_LOG_ERROR, "Interleaved RTP mode is not supported yet.\n"); } 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); - - av_log(s, AV_LOG_DEBUG, - "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; - } + if (strlen(value) == 6) + parse_profile_level_id(s, h264_data, value); } else if (!strcmp(attr, "sprop-parameter-sets")) { - codec->extradata_size = 0; - av_freep(&codec->extradata); - - while (*value) { - char base64packet[1024]; - uint8_t decoded_packet[1024]; - int 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 > 0) { - uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) + - codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!dest) { - av_log(s, AV_LOG_ERROR, - "Unable to allocate memory for extradata!\n"); - return AVERROR(ENOMEM); - } - if (codec->extradata_size) { - memcpy(dest, codec->extradata, codec->extradata_size); - av_free(codec->extradata); - } + int ret; + par->extradata_size = 0; + av_freep(&par->extradata); + ret = ff_h264_parse_sprop_parameter_sets(s, &par->extradata, + &par->extradata_size, value); + av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n", + par->extradata, par->extradata_size); + return ret; + } + return 0; +} + +void ff_h264_parse_framesize(AVCodecParameters *par, const char *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 != '-' && (dst - buf1) < sizeof(buf1) - 1) + *dst++ = *p++; + *dst = '\0'; + + // a='framesize:96 320-240' + // set our parameters + par->width = atoi(buf1); + par->height = atoi(p + 1); // skip the - +} + +int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, AVPacket *pkt, + const uint8_t *buf, int len, + int skip_between, int *nal_counters, + int nal_mask) +{ + int pass = 0; + int total_length = 0; + uint8_t *dst = NULL; + int ret; + + // first we are going to figure out the total size + for (pass = 0; pass < 2; pass++) { + const uint8_t *src = buf; + int src_len = len; + + while (src_len > 2) { + uint16_t nal_size = AV_RB16(src); - memcpy(dest + codec->extradata_size, start_sequence, - sizeof(start_sequence)); - memcpy(dest + codec->extradata_size + sizeof(start_sequence), - decoded_packet, packet_size); - memset(dest + codec->extradata_size + sizeof(start_sequence) + - packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + // consume the length of the aggregate + src += 2; + src_len -= 2; - codec->extradata = dest; - codec->extradata_size += sizeof(start_sequence) + packet_size; + if (nal_size <= src_len) { + if (pass == 0) { + // counting + total_length += sizeof(start_sequence) + nal_size; + } else { + // copying + memcpy(dst, start_sequence, sizeof(start_sequence)); + dst += sizeof(start_sequence); + memcpy(dst, src, nal_size); + if (nal_counters) + nal_counters[(*src) & nal_mask]++; + dst += nal_size; + } + } else { + av_log(ctx, AV_LOG_ERROR, + "nal size exceeds length: %d %d\n", nal_size, src_len); + return AVERROR_INVALIDDATA; } + + // eat what we handled + src += nal_size + skip_between; + src_len -= nal_size + skip_between; } - av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n", - codec->extradata, codec->extradata_size); + + if (pass == 0) { + /* now we know the total size of the packet (with the + * start sequences added) */ + if ((ret = av_new_packet(pkt, total_length)) < 0) + return ret; + dst = pkt->data; + } + } + + return 0; +} + +int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, + int start_bit, const uint8_t *nal_header, + int nal_header_len) +{ + int ret; + int tot_len = len; + int pos = 0; + if (start_bit) + tot_len += sizeof(start_sequence) + nal_header_len; + if ((ret = av_new_packet(pkt, tot_len)) < 0) + return ret; + if (start_bit) { + memcpy(pkt->data + pos, start_sequence, sizeof(start_sequence)); + pos += sizeof(start_sequence); + memcpy(pkt->data + pos, nal_header, nal_header_len); + pos += nal_header_len; } + memcpy(pkt->data + pos, buf, len); return 0; } +static int h264_handle_packet_fu_a(AVFormatContext *ctx, AVPacket *pkt, + const uint8_t *buf, int len, + int *nal_counters, int nal_mask) +{ + uint8_t fu_indicator, fu_header, start_bit, nal_type, nal; + + if (len < 3) { + av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H.264 RTP packet\n"); + return AVERROR_INVALIDDATA; + } + + fu_indicator = buf[0]; + fu_header = buf[1]; + start_bit = fu_header >> 7; + nal_type = fu_header & 0x1f; + nal = fu_indicator & 0xe0 | nal_type; + + // skip the fu_indicator and fu_header + buf += 2; + len -= 2; + + if (start_bit && nal_counters) + nal_counters[nal_type & nal_mask]++; + return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1); +} + // return 0 on packet, no more left, 1 on packet, 1 on partial packet static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, @@ -175,17 +315,14 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, int result = 0; if (!len) { - av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n"); + av_log(ctx, AV_LOG_ERROR, "Empty H.264 RTP packet\n"); return AVERROR_INVALIDDATA; } nal = buf[0]; type = nal & 0x1f; - assert(data); - assert(buf); - - /* Simplify the case (these are all the nal types used internally by - * the h264 codec). */ + /* Simplify the case (these are all the NAL types used internally by + * the H.264 codec). */ if (type >= 1 && type <= 23) type = 1; switch (type) { @@ -202,113 +339,21 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, // 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; - - while (src_len > 2) { - uint16_t nal_size = AV_RB16(src); - - // 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); - COUNT_NAL_TYPE(data, *src); - dst += nal_size; - } - } else { - av_log(ctx, 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(ctx, AV_LOG_ERROR, - "Consumed more bytes than we got! (%d)\n", src_len); - } - - if (pass == 0) { - /* now we know the total size of the packet (with the - * start sequences added) */ - if ((result = av_new_packet(pkt, total_length)) < 0) - return result; - dst = pkt->data; - } else { - assert(dst - pkt->data == total_length); - } - } - } + result = ff_h264_handle_aggregated_packet(ctx, pkt, buf, len, 0, + NAL_COUNTERS, NAL_MASK); break; case 25: // STAP-B case 26: // MTAP-16 case 27: // MTAP-24 case 29: // FU-B - av_log(ctx, AV_LOG_ERROR, - "Unhandled type (%d) (See RFC for implementation details\n", - type); - result = AVERROR(ENOSYS); + avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type); + result = AVERROR_PATCHWELCOME; break; case 28: // FU-A (fragmented nal) - buf++; - len--; // skip the fu_indicator - if (len > 1) { - // these are the same as above, we just redo them here for clarity - uint8_t fu_indicator = nal; - uint8_t fu_header = *buf; - uint8_t start_bit = fu_header >> 7; - uint8_t av_unused 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. - /* The original nal forbidden bit and NRI are stored in this - * packet's nal. */ - reconstructed_nal = fu_indicator & 0xe0; - reconstructed_nal |= nal_type; - - // skip the fu_header - buf++; - len--; - - if (start_bit) - COUNT_NAL_TYPE(data, nal_type); - if (start_bit) { - /* copy in the start sequence, and the reconstructed nal */ - if ((result = av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len)) < 0) - return result; - 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 { - if ((result = av_new_packet(pkt, len)) < 0) - return result; - memcpy(pkt->data, buf, len); - } - } else { - av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n"); - result = AVERROR_INVALIDDATA; - } + result = h264_handle_packet_fu_a(ctx, pkt, buf, len, + NAL_COUNTERS, NAL_MASK); break; case 30: // undefined @@ -324,12 +369,7 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, return result; } -static PayloadContext *h264_new_context(void) -{ - return av_mallocz(sizeof(PayloadContext) + FF_INPUT_BUFFER_PADDING_SIZE); -} - -static void h264_free_context(PayloadContext *data) +static void h264_close_context(PayloadContext *data) { #ifdef DEBUG int ii; @@ -340,51 +380,21 @@ static void h264_free_context(PayloadContext *data) data->packet_types_received[ii], ii); } #endif - - av_free(data); -} - -static av_cold int h264_init(AVFormatContext *s, int st_index, - PayloadContext *data) -{ - if (st_index < 0) - return 0; - s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; } static int parse_h264_sdp_line(AVFormatContext *s, int st_index, PayloadContext *h264_data, const char *line) { AVStream *stream; - AVCodecContext *codec; const char *p = line; if (st_index < 0) return 0; stream = s->streams[st_index]; - codec = stream->codec; if (av_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 != '-' && (dst - buf1) < 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 - + ff_h264_parse_framesize(stream->codecpar, p); } else if (av_strstart(p, "fmtp:", &p)) { return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264); } else if (av_strstart(p, "cliprect:", &p)) { @@ -398,9 +408,9 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = { .enc_name = "H264", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H264, - .init = h264_init, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = parse_h264_sdp_line, - .alloc = h264_new_context, - .free = h264_free_context, - .parse_packet = h264_handle_packet + .close = h264_close_context, + .parse_packet = h264_handle_packet, }; diff --git a/libavformat/rtpdec_hevc.c b/libavformat/rtpdec_hevc.c new file mode 100644 index 0000000..97f87ae --- /dev/null +++ b/libavformat/rtpdec_hevc.c @@ -0,0 +1,350 @@ +/* + * RTP parser for HEVC/H.265 payload format (draft version 6) + * Copyright (c) 2014 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/base64.h" + +#include "avformat.h" +#include "rtpdec.h" +#include "rtpdec_formats.h" + +#define RTP_HEVC_PAYLOAD_HEADER_SIZE 2 +#define RTP_HEVC_FU_HEADER_SIZE 1 +#define RTP_HEVC_DONL_FIELD_SIZE 2 +#define RTP_HEVC_DOND_FIELD_SIZE 1 +#define HEVC_SPECIFIED_NAL_UNIT_TYPES 48 + +/* SDP out-of-band signaling data */ +struct PayloadContext { + int using_donl_field; + int profile_id; + uint8_t *sps, *pps, *vps, *sei; + int sps_size, pps_size, vps_size, sei_size; +}; + +static const uint8_t start_sequence[] = { 0x00, 0x00, 0x00, 0x01 }; + +static av_cold int hevc_sdp_parse_fmtp_config(AVFormatContext *s, + AVStream *stream, + PayloadContext *hevc_data, + const char *attr, const char *value) +{ + /* profile-space: 0-3 */ + /* profile-id: 0-31 */ + if (!strcmp(attr, "profile-id")) { + hevc_data->profile_id = atoi(value); + av_log(s, AV_LOG_TRACE, "SDP: found profile-id: %d\n", hevc_data->profile_id); + } + + /* tier-flag: 0-1 */ + /* level-id: 0-255 */ + /* interop-constraints: [base16] */ + /* profile-compatibility-indicator: [base16] */ + /* sprop-sub-layer-id: 0-6, defines highest possible value for TID, default: 6 */ + /* recv-sub-layer-id: 0-6 */ + /* max-recv-level-id: 0-255 */ + /* tx-mode: MSM,SSM */ + /* sprop-vps: [base64] */ + /* sprop-sps: [base64] */ + /* sprop-pps: [base64] */ + /* sprop-sei: [base64] */ + if (!strcmp(attr, "sprop-vps") || !strcmp(attr, "sprop-sps") || + !strcmp(attr, "sprop-pps") || !strcmp(attr, "sprop-sei")) { + uint8_t **data_ptr = NULL; + int *size_ptr = NULL; + if (!strcmp(attr, "sprop-vps")) { + data_ptr = &hevc_data->vps; + size_ptr = &hevc_data->vps_size; + } else if (!strcmp(attr, "sprop-sps")) { + data_ptr = &hevc_data->sps; + size_ptr = &hevc_data->sps_size; + } else if (!strcmp(attr, "sprop-pps")) { + data_ptr = &hevc_data->pps; + size_ptr = &hevc_data->pps_size; + } else if (!strcmp(attr, "sprop-sei")) { + data_ptr = &hevc_data->sei; + size_ptr = &hevc_data->sei_size; + } + + ff_h264_parse_sprop_parameter_sets(s, data_ptr, + size_ptr, value); + } + + /* max-lsr, max-lps, max-cpb, max-dpb, max-br, max-tr, max-tc */ + /* max-fps */ + + /* sprop-max-don-diff: 0-32767 + + When the RTP stream depends on one or more other RTP + streams (in this case tx-mode MUST be equal to "MSM" and + MSM is in use), this parameter MUST be present and the + value MUST be greater than 0. + */ + if (!strcmp(attr, "sprop-max-don-diff")) { + if (atoi(value) > 0) + hevc_data->using_donl_field = 1; + av_log(s, AV_LOG_TRACE, "Found sprop-max-don-diff in SDP, DON field usage is: %d\n", + hevc_data->using_donl_field); + } + + /* sprop-depack-buf-nalus: 0-32767 */ + if (!strcmp(attr, "sprop-depack-buf-nalus")) { + if (atoi(value) > 0) + hevc_data->using_donl_field = 1; + av_log(s, AV_LOG_TRACE, "Found sprop-depack-buf-nalus in SDP, DON field usage is: %d\n", + hevc_data->using_donl_field); + } + + /* sprop-depack-buf-bytes: 0-4294967295 */ + /* depack-buf-cap */ + /* sprop-segmentation-id: 0-3 */ + /* sprop-spatial-segmentation-idc: [base16] */ + /* dec-parallel-ca: */ + /* include-dph */ + + return 0; +} + +static av_cold int hevc_parse_sdp_line(AVFormatContext *ctx, int st_index, + PayloadContext *hevc_data, const char *line) +{ + AVStream *current_stream; + AVCodecParameters *par; + const char *sdp_line_ptr = line; + + if (st_index < 0) + return 0; + + current_stream = ctx->streams[st_index]; + par = current_stream->codecpar; + + if (av_strstart(sdp_line_ptr, "framesize:", &sdp_line_ptr)) { + ff_h264_parse_framesize(par, sdp_line_ptr); + } else if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) { + int ret = ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr, + hevc_sdp_parse_fmtp_config); + if (hevc_data->vps_size || hevc_data->sps_size || + hevc_data->pps_size || hevc_data->sei_size) { + av_freep(&par->extradata); + par->extradata_size = hevc_data->vps_size + hevc_data->sps_size + + hevc_data->pps_size + hevc_data->sei_size; + par->extradata = av_malloc(par->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) { + ret = AVERROR(ENOMEM); + par->extradata_size = 0; + } else { + int pos = 0; + memcpy(par->extradata + pos, hevc_data->vps, hevc_data->vps_size); + pos += hevc_data->vps_size; + memcpy(par->extradata + pos, hevc_data->sps, hevc_data->sps_size); + pos += hevc_data->sps_size; + memcpy(par->extradata + pos, hevc_data->pps, hevc_data->pps_size); + pos += hevc_data->pps_size; + memcpy(par->extradata + pos, hevc_data->sei, hevc_data->sei_size); + pos += hevc_data->sei_size; + memset(par->extradata + pos, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + + av_freep(&hevc_data->vps); + av_freep(&hevc_data->sps); + av_freep(&hevc_data->pps); + av_freep(&hevc_data->sei); + hevc_data->vps_size = 0; + hevc_data->sps_size = 0; + hevc_data->pps_size = 0; + hevc_data->sei_size = 0; + } + return ret; + } + + return 0; +} + +static int hevc_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_hevc_ctx, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, uint16_t seq, + int flags) +{ + const uint8_t *rtp_pl = buf; + int tid, lid, nal_type; + int first_fragment, last_fragment, fu_type; + uint8_t new_nal_header[2]; + int res = 0; + + /* sanity check for size of input packet: 1 byte payload at least */ + if (len < RTP_HEVC_PAYLOAD_HEADER_SIZE + 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/HEVC packet, got %d bytes\n", len); + return AVERROR_INVALIDDATA; + } + + /* + * decode the HEVC payload header according to section 4 of draft version 6: + * + * 0 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |F| Type | LayerId | TID | + * +-------------+-----------------+ + * + * Forbidden zero (F): 1 bit + * NAL unit type (Type): 6 bits + * NUH layer ID (LayerId): 6 bits + * NUH temporal ID plus 1 (TID): 3 bits + */ + nal_type = (buf[0] >> 1) & 0x3f; + lid = ((buf[0] << 5) & 0x20) | ((buf[1] >> 3) & 0x1f); + tid = buf[1] & 0x07; + + /* sanity check for correct layer ID */ + if (lid) { + /* future scalable or 3D video coding extensions */ + avpriv_report_missing_feature(ctx, "Multi-layer HEVC coding"); + return AVERROR_PATCHWELCOME; + } + + /* sanity check for correct temporal ID */ + if (!tid) { + av_log(ctx, AV_LOG_ERROR, "Illegal temporal ID in RTP/HEVC packet\n"); + return AVERROR_INVALIDDATA; + } + + /* sanity check for correct NAL unit type */ + if (nal_type > 50) { + av_log(ctx, AV_LOG_ERROR, "Unsupported (HEVC) NAL type (%d)\n", nal_type); + return AVERROR_INVALIDDATA; + } + + switch (nal_type) { + /* video parameter set (VPS) */ + case 32: + /* sequence parameter set (SPS) */ + case 33: + /* picture parameter set (PPS) */ + case 34: + /* supplemental enhancement information (SEI) */ + case 39: + /* single NAL unit packet */ + default: + /* create A/V packet */ + if ((res = av_new_packet(pkt, sizeof(start_sequence) + len)) < 0) + return res; + /* A/V packet: copy start sequence */ + memcpy(pkt->data, start_sequence, sizeof(start_sequence)); + /* A/V packet: copy NAL unit data */ + memcpy(pkt->data + sizeof(start_sequence), buf, len); + + break; + /* aggregated packet (AP) - with two or more NAL units */ + case 48: + /* pass the HEVC payload header */ + buf += RTP_HEVC_PAYLOAD_HEADER_SIZE; + len -= RTP_HEVC_PAYLOAD_HEADER_SIZE; + + /* pass the HEVC DONL field */ + if (rtp_hevc_ctx->using_donl_field) { + buf += RTP_HEVC_DONL_FIELD_SIZE; + len -= RTP_HEVC_DONL_FIELD_SIZE; + } + + res = ff_h264_handle_aggregated_packet(ctx, pkt, buf, len, + rtp_hevc_ctx->using_donl_field ? + RTP_HEVC_DOND_FIELD_SIZE : 0, + NULL, 0); + if (res < 0) + return res; + break; + /* fragmentation unit (FU) */ + case 49: + /* pass the HEVC payload header */ + buf += RTP_HEVC_PAYLOAD_HEADER_SIZE; + len -= RTP_HEVC_PAYLOAD_HEADER_SIZE; + + /* + * decode the FU header + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |S|E| FuType | + * +---------------+ + * + * Start fragment (S): 1 bit + * End fragment (E): 1 bit + * FuType: 6 bits + */ + first_fragment = buf[0] & 0x80; + last_fragment = buf[0] & 0x40; + fu_type = buf[0] & 0x3f; + + /* pass the HEVC FU header */ + buf += RTP_HEVC_FU_HEADER_SIZE; + len -= RTP_HEVC_FU_HEADER_SIZE; + + /* pass the HEVC DONL field */ + if (rtp_hevc_ctx->using_donl_field) { + buf += RTP_HEVC_DONL_FIELD_SIZE; + len -= RTP_HEVC_DONL_FIELD_SIZE; + } + + av_log(ctx, AV_LOG_TRACE, " FU type %d with %d bytes\n", fu_type, len); + + if (len <= 0) { + /* sanity check for size of input packet: 1 byte payload at least */ + av_log(ctx, AV_LOG_ERROR, + "Too short RTP/HEVC packet, got %d bytes of NAL unit type %d\n", + len, nal_type); + return AVERROR_INVALIDDATA; + } + + if (first_fragment && last_fragment) { + av_log(ctx, AV_LOG_ERROR, "Illegal combination of S and E bit in RTP/HEVC packet\n"); + return AVERROR_INVALIDDATA; + } + + new_nal_header[0] = (rtp_pl[0] & 0x81) | (fu_type << 1); + new_nal_header[1] = rtp_pl[1]; + + res = ff_h264_handle_frag_packet(pkt, buf, len, first_fragment, + new_nal_header, sizeof(new_nal_header)); + + break; + /* PACI packet */ + case 50: + /* Temporal scalability control information (TSCI) */ + avpriv_report_missing_feature(ctx, "PACI packets for RTP/HEVC"); + res = AVERROR_PATCHWELCOME; + break; + } + + pkt->stream_index = st->index; + + return res; +} + +RTPDynamicProtocolHandler ff_hevc_dynamic_handler = { + .enc_name = "H265", + .codec_type = AVMEDIA_TYPE_VIDEO, + .codec_id = AV_CODEC_ID_HEVC, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), + .parse_sdp_a_line = hevc_parse_sdp_line, + .parse_packet = hevc_handle_packet, +}; diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c index bff47c7..798ae36 100644 --- a/libavformat/rtpdec_ilbc.c +++ b/libavformat/rtpdec_ilbc.c @@ -25,16 +25,16 @@ static int ilbc_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value) + const char *attr, const char *value) { if (!strcmp(attr, "mode")) { int mode = atoi(value); switch (mode) { case 20: - stream->codec->block_align = 38; + stream->codecpar->block_align = 38; break; case 30: - stream->codec->block_align = 50; + stream->codecpar->block_align = 50; break; default: av_log(s, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode); @@ -58,7 +58,7 @@ static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index, int ret = ff_parse_fmtp(s, st, data, p, ilbc_parse_fmtp); if (ret < 0) return ret; - if (!st->codec->block_align) { + if (!st->codecpar->block_align) { av_log(s, AV_LOG_ERROR, "No iLBC mode set\n"); return AVERROR(EINVAL); } diff --git a/libavformat/rtpdec_jpeg.c b/libavformat/rtpdec_jpeg.c index ed9c86c..bc86b15 100644 --- a/libavformat/rtpdec_jpeg.c +++ b/libavformat/rtpdec_jpeg.c @@ -20,9 +20,11 @@ */ #include "avformat.h" +#include "avio_internal.h" #include "rtpdec.h" #include "rtpdec_formats.h" #include "libavutil/intreadwrite.h" +#include "libavcodec/jpegtables.h" #include "libavcodec/mjpeg.h" #include "libavcodec/bytestream.h" @@ -59,25 +61,9 @@ static const uint8_t default_quantizers[128] = { 99, 99, 99, 99, 99, 99, 99, 99 }; -static PayloadContext *jpeg_new_context(void) +static void jpeg_close_context(PayloadContext *jpeg) { - return av_mallocz(sizeof(PayloadContext)); -} - -static inline void free_frame_if_needed(PayloadContext *jpeg) -{ - if (jpeg->frame) { - uint8_t *p; - avio_close_dyn_buf(jpeg->frame, &p); - av_free(p); - jpeg->frame = NULL; - } -} - -static void jpeg_free_context(PayloadContext *jpeg) -{ - free_frame_if_needed(jpeg); - av_free(jpeg); + ffio_free_dyn_buf(&jpeg->frame); } static int jpeg_create_huffman_table(PutByteContext *p, int table_class, @@ -200,16 +186,17 @@ static void create_default_qtables(uint8_t *qtables, uint8_t q) { int factor = q; int i; + uint16_t S; factor = av_clip(q, 1, 99); if (q < 50) - q = 5000 / factor; + S = 5000 / factor; else - q = 200 - factor * 2; + S = 200 - factor * 2; for (i = 0; i < 128; i++) { - int val = (default_quantizers[i] * q + 50) / 100; + int val = (default_quantizers[i] * S + 50) / 100; /* Limit the quantizers to 1 <= q <= 255. */ val = av_clip(val, 1, 255); @@ -242,12 +229,6 @@ static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, buf += 8; len -= 8; - /* Parse the restart marker header. */ - if (type > 63) { - av_log(ctx, AV_LOG_ERROR, - "Unimplemented RTP/JPEG restart marker header.\n"); - return AVERROR_PATCHWELCOME; - } if (type > 1) { av_log(ctx, AV_LOG_ERROR, "Unimplemented RTP/JPEG type %d\n", type); return AVERROR_PATCHWELCOME; @@ -321,7 +302,7 @@ static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, /* Skip the current frame in case of the end packet * has been lost somewhere. */ - free_frame_if_needed(jpeg); + ffio_free_dyn_buf(&jpeg->frame); if ((ret = avio_open_dyn_buf(&jpeg->frame)) < 0) return ret; @@ -347,7 +328,7 @@ static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, if (jpeg->timestamp != *timestamp) { /* Skip the current frame if timestamp is incorrect. * A start packet has been lost somewhere. */ - free_frame_if_needed(jpeg); + ffio_free_dyn_buf(&jpeg->frame); av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match.\n"); return AVERROR_INVALIDDATA; } @@ -385,8 +366,8 @@ RTPDynamicProtocolHandler ff_jpeg_dynamic_handler = { .enc_name = "JPEG", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MJPEG, - .alloc = jpeg_new_context, - .free = jpeg_free_context, + .priv_data_size = sizeof(PayloadContext), + .close = jpeg_close_context, .parse_packet = jpeg_parse_packet, .static_payload_id = 26, }; diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index 6ab3f78..6be0a25 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avio_internal.h" #include "rtpdec_formats.h" #include "internal.h" #include "libavutil/avstring.h" @@ -31,22 +32,10 @@ struct PayloadContext { uint32_t timestamp; }; -static PayloadContext *latm_new_context(void) +static void latm_close_context(PayloadContext *data) { - return av_mallocz(sizeof(PayloadContext)); -} - -static void latm_free_context(PayloadContext *data) -{ - if (!data) - return; - if (data->dyn_buf) { - uint8_t *p; - avio_close_dyn_buf(data->dyn_buf, &p); - av_free(p); - } + ffio_free_dyn_buf(&data->dyn_buf); av_free(data->buf); - av_free(data); } static int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data, @@ -59,10 +48,7 @@ static int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data, if (buf) { if (!data->dyn_buf || data->timestamp != *timestamp) { av_freep(&data->buf); - if (data->dyn_buf) - avio_close_dyn_buf(data->dyn_buf, &data->buf); - data->dyn_buf = NULL; - av_freep(&data->buf); + ffio_free_dyn_buf(&data->dyn_buf); data->timestamp = *timestamp; if ((ret = avio_open_dyn_buf(&data->dyn_buf)) < 0) @@ -103,7 +89,7 @@ static int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data, return data->pos < data->len; } -static int parse_fmtp_config(AVStream *st, char *value) +static int parse_fmtp_config(AVStream *st, const char *value) { int len = ff_hex_to_data(NULL, value), i, ret = 0; GetBitContext gb; @@ -111,7 +97,7 @@ static int parse_fmtp_config(AVStream *st, char *value) int audio_mux_version, same_time_framing, num_programs, num_layers; /* Pad this buffer, too, to avoid out of bounds reads with get_bits below */ - config = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); + config = av_mallocz(len + AV_INPUT_BUFFER_PADDING_SIZE); if (!config) return AVERROR(ENOMEM); ff_hex_to_data(config, value); @@ -129,16 +115,16 @@ static int parse_fmtp_config(AVStream *st, char *value) ret = AVERROR_PATCHWELCOME; goto end; } - av_freep(&st->codec->extradata); - st->codec->extradata_size = (get_bits_left(&gb) + 7)/8; - st->codec->extradata = av_mallocz(st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) { + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = (get_bits_left(&gb) + 7)/8; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) { ret = AVERROR(ENOMEM); goto end; } - for (i = 0; i < st->codec->extradata_size; i++) - st->codec->extradata[i] = get_bits(&gb, 8); + for (i = 0; i < st->codecpar->extradata_size; i++) + st->codecpar->extradata[i] = get_bits(&gb, 8); end: av_free(config); @@ -147,7 +133,7 @@ end: static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value) + const char *attr, const char *value) { int res; @@ -183,8 +169,8 @@ RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = { .enc_name = "MP4A-LATM", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = latm_parse_sdp_line, - .alloc = latm_new_context, - .free = latm_free_context, - .parse_packet = latm_parse_packet + .close = latm_close_context, + .parse_packet = latm_parse_packet, }; diff --git a/libavformat/rtpdec_mpa_robust.c b/libavformat/rtpdec_mpa_robust.c new file mode 100644 index 0000000..a65e139 --- /dev/null +++ b/libavformat/rtpdec_mpa_robust.c @@ -0,0 +1,200 @@ +/* + * RTP parser for loss tolerant payload format for MP3 audio (RFC 5219) + * Copyright (c) 2015 Gilles Chanteperdrix + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" + +#include "avio_internal.h" +#include "rtpdec_formats.h" + +struct PayloadContext { + unsigned adu_size; + unsigned cur_size; + uint32_t timestamp; + uint8_t *split_buf; + int split_pos, split_buf_size, split_pkts; + AVIOContext *fragment; +}; + +static void mpa_robust_close_context(PayloadContext *data) +{ + ffio_free_dyn_buf(&data->fragment); + av_free(data->split_buf); +} + +static int mpa_robust_parse_rtp_header(AVFormatContext *ctx, + const uint8_t *buf, int len, + unsigned *adu_size, unsigned *cont) +{ + unsigned header_size; + + if (len < 2) { + av_log(ctx, AV_LOG_ERROR, "Invalid %d bytes packet\n", len); + return AVERROR_INVALIDDATA; + } + + *cont = !!(buf[0] & 0x80); + if (!(buf[0] & 0x40)) { + header_size = 1; + *adu_size = buf[0] & ~0xc0; + } else { + header_size = 2; + *adu_size = AV_RB16(buf) & ~0xc000; + } + + return header_size; +} + +static int mpa_robust_parse_packet(AVFormatContext *ctx, PayloadContext *data, + AVStream *st, AVPacket *pkt, + uint32_t *timestamp, const uint8_t *buf, + int len, uint16_t seq, int flags) +{ + unsigned adu_size, continuation; + int err, header_size; + + if (!buf) { + buf = &data->split_buf[data->split_pos]; + len = data->split_buf_size - data->split_pos; + + header_size = mpa_robust_parse_rtp_header(ctx, buf, len, &adu_size, + &continuation); + if (header_size < 0) { + av_freep(&data->split_buf); + return header_size; + } + buf += header_size; + len -= header_size; + + if (continuation || adu_size > len) { + av_freep(&data->split_buf); + av_log(ctx, AV_LOG_ERROR, "Invalid frame\n"); + return AVERROR_INVALIDDATA; + } + + if (av_new_packet(pkt, adu_size)) { + av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); + return AVERROR(ENOMEM); + } + + pkt->stream_index = st->index; + memcpy(pkt->data, buf, adu_size); + + data->split_pos += header_size + adu_size; + + if (data->split_pos == data->split_buf_size) { + av_freep(&data->split_buf); + return 0; + } + + return 1; + } + + + header_size = mpa_robust_parse_rtp_header(ctx, buf, len, &adu_size, + &continuation); + if (header_size < 0) + return header_size; + + buf += header_size; + len -= header_size; + + if (!continuation && adu_size <= len) { + /* One or more complete frames */ + + if (av_new_packet(pkt, adu_size)) { + av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); + return AVERROR(ENOMEM); + } + + pkt->stream_index = st->index; + memcpy(pkt->data, buf, adu_size); + + buf += adu_size; + len -= adu_size; + if (len) { + data->split_buf_size = len; + data->split_buf = av_malloc(data->split_buf_size); + data->split_pos = 0; + if (!data->split_buf) { + av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); + av_packet_unref(pkt); + return AVERROR(ENOMEM); + } + memcpy(data->split_buf, buf, data->split_buf_size); + return 1; + } + return 0; + } else if (!continuation) { /* && adu_size > len */ + /* First fragment */ + ffio_free_dyn_buf(&data->fragment); + + data->adu_size = adu_size; + data->cur_size = len; + data->timestamp = *timestamp; + + err = avio_open_dyn_buf(&data->fragment); + if (err < 0) + return err; + + avio_write(data->fragment, buf, len); + return AVERROR(EAGAIN); + } + /* else continuation == 1 */ + + /* Fragment other than first */ + if (!data->fragment) { + av_log(ctx, AV_LOG_WARNING, + "Received packet without a start fragment; dropping.\n"); + return AVERROR(EAGAIN); + } + if (adu_size = data->adu_size || + data->timestamp != *timestamp) { + ffio_free_dyn_buf(&data->fragment); + av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); + return AVERROR_INVALIDDATA; + } + + avio_write(data->fragment, buf, len); + data->cur_size += len; + + if (data->cur_size < data->adu_size) + return AVERROR(EAGAIN); + + err = ff_rtp_finalize_packet(pkt, &data->fragment, st->index); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error occurred when getting fragment buffer.\n"); + return err; + } + + return 0; +} + +RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler = { + .enc_name = "mpa-robust", + .codec_type = AVMEDIA_TYPE_AUDIO, + .codec_id = AV_CODEC_ID_MP3ADU, + .need_parsing = AVSTREAM_PARSE_HEADERS, + .priv_data_size = sizeof(PayloadContext), + .close = mpa_robust_close_context, + .parse_packet = mpa_robust_parse_packet, +}; diff --git a/libavformat/rtpdec_mpeg12.c b/libavformat/rtpdec_mpeg12.c index b059fcf..89ecd30 100644 --- a/libavformat/rtpdec_mpeg12.c +++ b/libavformat/rtpdec_mpeg12.c @@ -23,14 +23,6 @@ #include "libavutil/intreadwrite.h" #include "rtpdec_formats.h" -static av_cold int mpeg_init(AVFormatContext *ctx, int st_index, PayloadContext *data) -{ - if (st_index < 0) - return 0; - ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; -} - static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, @@ -42,7 +34,7 @@ static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data, h = AV_RB32(buf); buf += 4; len -= 4; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && h & (1 << 26)) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && h & (1 << 26)) { /* MPEG-2 */ if (len <= 4) return AVERROR_INVALIDDATA; @@ -59,7 +51,7 @@ static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data, RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_MP3, - .init = mpeg_init, + .need_parsing = AVSTREAM_PARSE_FULL, .parse_packet = mpeg_parse_packet, .static_payload_id = 14, }; @@ -67,7 +59,7 @@ RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler = { .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MPEG2VIDEO, - .init = mpeg_init, + .need_parsing = AVSTREAM_PARSE_FULL, .parse_packet = mpeg_parse_packet, .static_payload_id = 32, }; diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index 4aedeea..bc50da2 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -22,7 +22,7 @@ /** * @file - * @brief MPEG4 / RTP Code + * @brief MPEG-4 / RTP Code * @author Fabrice Bellard * @author Romain Degez */ @@ -33,6 +33,8 @@ #include "libavutil/avstring.h" #include "libavcodec/get_bits.h" +#define MAX_AAC_HBR_FRAME_SIZE 8191 + /** Structure listing useful vars to parse RTP packet payload */ struct PayloadContext { int sizelength; @@ -59,11 +61,12 @@ struct PayloadContext { int au_headers_length_bytes; int cur_au_index; - uint8_t buf[RTP_MAX_PACKET_LENGTH]; + uint8_t buf[FFMAX(RTP_MAX_PACKET_LENGTH, MAX_AAC_HBR_FRAME_SIZE)]; int buf_pos, buf_size; + uint32_t timestamp; }; -typedef struct { +typedef struct AttrNameMap { const char *str; uint16_t type; uint32_t offset; @@ -88,28 +91,22 @@ static const AttrNameMap attr_names[] = { { NULL, -1, -1 }, }; -static PayloadContext *new_context(void) -{ - return av_mallocz(sizeof(PayloadContext)); -} - -static void free_context(PayloadContext *data) +static void close_context(PayloadContext *data) { av_free(data->au_headers); av_free(data->mode); - av_free(data); } -static int parse_fmtp_config(AVCodecContext *codec, char *value) +static int parse_fmtp_config(AVCodecParameters *par, char *value) { /* decode the hexa encoded parameter */ int len = ff_hex_to_data(NULL, value); - av_free(codec->extradata); - codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); - if (!codec->extradata) + av_free(par->extradata); + par->extradata = av_mallocz(len + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) return AVERROR(ENOMEM); - codec->extradata_size = len; - ff_hex_to_data(codec->extradata, value); + par->extradata_size = len; + ff_hex_to_data(par->extradata, value); return 0; } @@ -139,7 +136,7 @@ static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len) init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8); - /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */ + /* XXX: Wrong if optional additional sections are present (cts, dts etc...) */ au_header_size = data->sizelength + data->indexlength; if (au_header_size <= 0 || (au_headers_length % au_header_size != 0)) return -1; @@ -171,29 +168,93 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data, int ret; if (!buf) { - if (data->cur_au_index > data->nb_au_headers) + if (data->cur_au_index > data->nb_au_headers) { + av_log(ctx, AV_LOG_ERROR, "Invalid parser state\n"); return AVERROR_INVALIDDATA; - if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) + } + if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) { + av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n"); return AVERROR_INVALIDDATA; - if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) + } + if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Out of memory\n"); return ret; + } memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size); data->buf_pos += data->au_headers[data->cur_au_index].size; pkt->stream_index = st->index; data->cur_au_index++; - return data->cur_au_index < data->nb_au_headers; + + if (data->cur_au_index == data->nb_au_headers) { + data->buf_pos = 0; + return 0; + } + + return 1; } - if (rtp_parse_mp4_au(data, buf, len)) + if (rtp_parse_mp4_au(data, buf, len)) { + av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n"); return -1; + } buf += data->au_headers_length_bytes + 2; len -= data->au_headers_length_bytes + 2; + if (data->nb_au_headers == 1 && len < data->au_headers[0].size) { + /* Packet is fragmented */ + + if (!data->buf_pos) { + if (data->au_headers[0].size > MAX_AAC_HBR_FRAME_SIZE) { + av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n"); + return AVERROR_INVALIDDATA; + } + + data->buf_size = data->au_headers[0].size; + data->timestamp = *timestamp; + } + + if (data->timestamp != *timestamp || + data->au_headers[0].size != data->buf_size || + data->buf_pos + len > MAX_AAC_HBR_FRAME_SIZE) { + data->buf_pos = 0; + data->buf_size = 0; + av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); + return AVERROR_INVALIDDATA; + } + + memcpy(&data->buf[data->buf_pos], buf, len); + data->buf_pos += len; + + if (!(flags & RTP_FLAG_MARKER)) + return AVERROR(EAGAIN); - if (len < data->au_headers[0].size) + if (data->buf_pos != data->buf_size) { + data->buf_pos = 0; + av_log(ctx, AV_LOG_ERROR, "Missed some packets, discarding frame\n"); + return AVERROR_INVALIDDATA; + } + + data->buf_pos = 0; + ret = av_new_packet(pkt, data->buf_size); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Out of memory\n"); + return ret; + } + pkt->stream_index = st->index; + + memcpy(pkt->data, data->buf, data->buf_size); + + return 0; + } + + if (len < data->au_headers[0].size) { + av_log(ctx, AV_LOG_ERROR, "First AU larger than packet size\n"); return AVERROR_INVALIDDATA; - if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) + } + if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Out of memory\n"); return ret; + } memcpy(pkt->data, buf, data->au_headers[0].size); len -= data->au_headers[0].size; buf += data->au_headers[0].size; @@ -212,28 +273,39 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data, static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, - char *attr, char *value) + const char *attr, const char *value) { - AVCodecContext *codec = stream->codec; + AVCodecParameters *par = stream->codecpar; int res, i; if (!strcmp(attr, "config")) { - res = parse_fmtp_config(codec, value); + res = parse_fmtp_config(par, value); if (res < 0) return res; } - if (codec->codec_id == AV_CODEC_ID_AAC) { + if (par->codec_id == AV_CODEC_ID_AAC) { /* Looking for a known attribute */ for (i = 0; attr_names[i].str; ++i) { if (!av_strcasecmp(attr, attr_names[i].str)) { if (attr_names[i].type == ATTR_NAME_TYPE_INT) { + int val = atoi(value); + if (val > 32) { + av_log(s, AV_LOG_ERROR, + "The %s field size is invalid (%d).", + attr, val); + return AVERROR_INVALIDDATA; + } *(int *)((char *)data+ - attr_names[i].offset) = atoi(value); - } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) + attr_names[i].offset) = val; + } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) { + char *val = av_strdup(value); + if (!val) + return AVERROR(ENOMEM); *(char **)((char *)data+ - attr_names[i].offset) = av_strdup(value); + attr_names[i].offset) = val; + } } } } @@ -254,20 +326,12 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -static av_cold int init_video(AVFormatContext *s, int st_index, - PayloadContext *data) -{ - if (st_index < 0) - return 0; - s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; -} - RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { .enc_name = "MP4V-ES", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MPEG4, - .init = init_video, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = parse_sdp_line, }; @@ -275,8 +339,8 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { .enc_name = "mpeg4-generic", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = parse_sdp_line, - .alloc = new_context, - .free = free_context, - .parse_packet = aac_parse_packet + .close = close_context, + .parse_packet = aac_parse_packet, }; diff --git a/libavformat/rtpdec_mpegts.c b/libavformat/rtpdec_mpegts.c index b3ef261..0fb0a0d 100644 --- a/libavformat/rtpdec_mpegts.c +++ b/libavformat/rtpdec_mpegts.c @@ -30,18 +30,12 @@ struct PayloadContext { uint8_t buf[RTP_MAX_PACKET_LENGTH]; }; -static PayloadContext *mpegts_new_context(void) -{ - return av_mallocz(sizeof(PayloadContext)); -} - -static void mpegts_free_context(PayloadContext *data) +static void mpegts_close_context(PayloadContext *data) { if (!data) return; if (data->ts) ff_mpegts_parse_close(data->ts); - av_free(data); } static av_cold int mpegts_init(AVFormatContext *ctx, int st_index, @@ -66,9 +60,6 @@ static int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data, // different ranges. *timestamp = RTP_NOTS_VALUE; - if (!data->ts) - return AVERROR(EINVAL); - if (!buf) { if (data->read_buf_index >= data->read_buf_size) return AVERROR(EAGAIN); @@ -100,9 +91,9 @@ static int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data, RTPDynamicProtocolHandler ff_mpegts_dynamic_handler = { .codec_type = AVMEDIA_TYPE_DATA, + .priv_data_size = sizeof(PayloadContext), .parse_packet = mpegts_handle_packet, - .alloc = mpegts_new_context, .init = mpegts_init, - .free = mpegts_free_context, + .close = mpegts_close_context, .static_payload_id = 33, }; diff --git a/libavformat/rtpdec_qcelp.c b/libavformat/rtpdec_qcelp.c index 45a89ae..d5322d6 100644 --- a/libavformat/rtpdec_qcelp.c +++ b/libavformat/rtpdec_qcelp.c @@ -25,7 +25,7 @@ static const uint8_t frame_sizes[] = { 1, 4, 8, 17, 35 }; -typedef struct { +typedef struct InterleavePacket { int pos; int size; /* The largest frame is 35 bytes, only 10 frames are allowed per @@ -47,16 +47,6 @@ struct PayloadContext { uint32_t next_timestamp; }; -static PayloadContext *qcelp_new_context(void) -{ - return av_mallocz(sizeof(PayloadContext)); -} - -static void qcelp_free_context(PayloadContext *data) -{ - av_free(data); -} - static int return_stored_frame(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len); @@ -223,8 +213,7 @@ RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = { .enc_name = "x-Purevoice", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_QCELP, + .priv_data_size = sizeof(PayloadContext), .static_payload_id = 12, - .alloc = qcelp_new_context, - .free = qcelp_free_context, - .parse_packet = qcelp_parse_packet + .parse_packet = qcelp_parse_packet, }; diff --git a/libavformat/rtpdec_qdm2.c b/libavformat/rtpdec_qdm2.c index 0d7b5bb..9a77a70 100644 --- a/libavformat/rtpdec_qdm2.c +++ b/libavformat/rtpdec_qdm2.c @@ -102,20 +102,20 @@ static int qdm2_parse_config(PayloadContext *qdm, AVStream *st, case 4: /* stream with extradata */ if (item_len < 30) return AVERROR_INVALIDDATA; - av_freep(&st->codec->extradata); - st->codec->extradata_size = 26 + item_len; - if (!(st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE))) { - st->codec->extradata_size = 0; + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 26 + item_len; + if (!(st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE))) { + st->codecpar->extradata_size = 0; return AVERROR(ENOMEM); } - AV_WB32(st->codec->extradata, 12); - memcpy(st->codec->extradata + 4, "frma", 4); - memcpy(st->codec->extradata + 8, "QDM2", 4); - AV_WB32(st->codec->extradata + 12, 6 + item_len); - memcpy(st->codec->extradata + 16, "QDCA", 4); - memcpy(st->codec->extradata + 20, p + 2, item_len - 2); - AV_WB32(st->codec->extradata + 18 + item_len, 8); - AV_WB32(st->codec->extradata + 22 + item_len, 0); + AV_WB32(st->codecpar->extradata, 12); + memcpy(st->codecpar->extradata + 4, "frma", 4); + memcpy(st->codecpar->extradata + 8, "QDM2", 4); + AV_WB32(st->codecpar->extradata + 12, 6 + item_len); + memcpy(st->codecpar->extradata + 16, "QDCA", 4); + memcpy(st->codecpar->extradata + 20, p + 2, item_len - 2); + AV_WB32(st->codecpar->extradata + 18 + item_len, 8); + AV_WB32(st->codecpar->extradata + 22 + item_len, 0); qdm->block_size = AV_RB32(p + 26); break; @@ -265,9 +265,9 @@ static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm, * carried within the RTP stream, not SDP. Here, * by setting codec_id to AV_CODEC_ID_QDM2, we are signalling * to the decoder that it is OK to initialize. */ - st->codec->codec_id = AV_CODEC_ID_QDM2; + st->codecpar->codec_id = AV_CODEC_ID_QDM2; } - if (st->codec->codec_id == AV_CODEC_ID_NONE) + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) return AVERROR(EAGAIN); /* subpackets */ @@ -298,21 +298,10 @@ static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm, return (qdm->cache > 0) ? 1 : 0; } -static PayloadContext *qdm2_extradata_new(void) -{ - return av_mallocz(sizeof(PayloadContext)); -} - -static void qdm2_extradata_free(PayloadContext *qdm) -{ - av_free(qdm); -} - RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = { .enc_name = "X-QDM", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_NONE, - .alloc = qdm2_extradata_new, - .free = qdm2_extradata_free, + .priv_data_size = sizeof(PayloadContext), .parse_packet = qdm2_parse_packet, }; diff --git a/libavformat/rtpdec_qt.c b/libavformat/rtpdec_qt.c index 2d9c603..97df210 100644 --- a/libavformat/rtpdec_qt.c +++ b/libavformat/rtpdec_qt.c @@ -47,7 +47,8 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, AVIOContext pb; GetBitContext gb; int packing_scheme, has_payload_desc, has_packet_info, alen, - has_marker_bit = flags & RTP_FLAG_MARKER; + has_marker_bit = flags & RTP_FLAG_MARKER, + keyframe; if (qt->remaining) { int num = qt->pkt.size / qt->bytes_per_frame; @@ -79,8 +80,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, skip_bits(&gb, 4); // version if ((packing_scheme = get_bits(&gb, 2)) == 0) return AVERROR_INVALIDDATA; - if (get_bits1(&gb)) - flags |= RTP_FLAG_KEY; + keyframe = get_bits1(&gb); has_payload_desc = get_bits1(&gb); has_packet_info = get_bits1(&gb); skip_bits(&gb, 23); // reserved:7, cache payload info:1, payload ID:15 @@ -93,7 +93,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, if (pos + 12 > len) return AVERROR_INVALIDDATA; - skip_bits(&gb, 2); // has non-I frames:1, is sparse:1 + skip_bits(&gb, 2); // has non-I-frames:1, is sparse:1 is_start = get_bits1(&gb); is_finish = get_bits1(&gb); if (!is_start || !is_finish) { @@ -106,9 +106,9 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, avio_seek(&pb, pos + 4, SEEK_SET); tag = avio_rl32(&pb); - if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && tag != MKTAG('v','i','d','e')) || - (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && + (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && tag != MKTAG('s','o','u','n'))) return AVERROR_INVALIDDATA; avpriv_set_pts_info(st, 32, 1, avio_rb32(&pb)); @@ -174,14 +174,14 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, if (qt->pkt.size > 0 && qt->timestamp == *timestamp) { int err; if ((err = av_reallocp(&qt->pkt.data, qt->pkt.size + alen + - FF_INPUT_BUFFER_PADDING_SIZE)) < 0) { + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { qt->pkt.size = 0; return err; } } else { av_freep(&qt->pkt.data); av_init_packet(&qt->pkt); - qt->pkt.data = av_realloc(NULL, alen + FF_INPUT_BUFFER_PADDING_SIZE); + qt->pkt.data = av_realloc(NULL, alen + AV_INPUT_BUFFER_PADDING_SIZE); if (!qt->pkt.data) return AVERROR(ENOMEM); qt->pkt.size = 0; @@ -196,9 +196,9 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, qt->pkt.size = 0; qt->pkt.data = NULL; - pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0; + pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0; pkt->stream_index = st->index; - memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); return 0; } return AVERROR(EAGAIN); @@ -211,13 +211,13 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, if (av_new_packet(pkt, qt->bytes_per_frame)) return AVERROR(ENOMEM); memcpy(pkt->data, buf + avio_tell(&pb), qt->bytes_per_frame); - pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0; + pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0; pkt->stream_index = st->index; if (qt->remaining > 0) { av_freep(&qt->pkt.data); qt->pkt.data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame); if (!qt->pkt.data) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } qt->pkt.size = qt->remaining * qt->bytes_per_frame; @@ -235,15 +235,9 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, } } -static PayloadContext *qt_rtp_new(void) -{ - return av_mallocz(sizeof(PayloadContext)); -} - -static void qt_rtp_free(PayloadContext *qt) +static void qt_rtp_close(PayloadContext *qt) { av_freep(&qt->pkt.data); - av_free(qt); } #define RTP_QT_HANDLER(m, n, s, t) \ @@ -251,8 +245,8 @@ RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ - .alloc = qt_rtp_new, \ - .free = qt_rtp_free, \ + .priv_data_size = sizeof(PayloadContext), \ + .close = qt_rtp_close, \ .parse_packet = qt_rtp_parse_packet, \ } diff --git a/libavformat/rtpdec_svq3.c b/libavformat/rtpdec_svq3.c index aa880e5..267d9db 100644 --- a/libavformat/rtpdec_svq3.c +++ b/libavformat/rtpdec_svq3.c @@ -28,6 +28,7 @@ #include #include "libavutil/intreadwrite.h" +#include "avio_internal.h" #include "rtp.h" #include "rtpdec.h" #include "rtpdec_formats.h" @@ -57,24 +58,24 @@ static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, if (config_packet) { - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; - if (len < 2 || !(st->codec->extradata = - av_malloc(len + 8 + FF_INPUT_BUFFER_PADDING_SIZE))) + if (len < 2 || !(st->codecpar->extradata = + av_malloc(len + 8 + AV_INPUT_BUFFER_PADDING_SIZE))) return AVERROR_INVALIDDATA; - st->codec->extradata_size = len + 8; - memcpy(st->codec->extradata, "SEQH", 4); - AV_WB32(st->codec->extradata + 4, len); - memcpy(st->codec->extradata + 8, buf, len); + st->codecpar->extradata_size = len + 8; + memcpy(st->codecpar->extradata, "SEQH", 4); + AV_WB32(st->codecpar->extradata + 4, len); + memcpy(st->codecpar->extradata + 8, buf, len); /* We set codec_id to AV_CODEC_ID_NONE initially to * delay decoder initialization since extradata is * carried within the RTP stream, not SDP. Here, * by setting codec_id to AV_CODEC_ID_SVQ3, we are signalling * to the decoder that it is OK to initialize. */ - st->codec->codec_id = AV_CODEC_ID_SVQ3; + st->codecpar->codec_id = AV_CODEC_ID_SVQ3; return AVERROR(EAGAIN); } @@ -82,11 +83,7 @@ static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, if (start_packet) { int res; - if (sv->pktbuf) { - uint8_t *tmp; - avio_close_dyn_buf(sv->pktbuf, &tmp); - av_free(tmp); - } + ffio_free_dyn_buf(&sv->pktbuf); if ((res = avio_open_dyn_buf(&sv->pktbuf)) < 0) return res; sv->timestamp = *timestamp; @@ -109,26 +106,16 @@ static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, return AVERROR(EAGAIN); } -static PayloadContext *svq3_extradata_new(void) +static void svq3_close_context(PayloadContext *sv) { - return av_mallocz(sizeof(PayloadContext)); -} - -static void svq3_extradata_free(PayloadContext *sv) -{ - if (sv->pktbuf) { - uint8_t *buf; - avio_close_dyn_buf(sv->pktbuf, &buf); - av_free(buf); - } - av_free(sv); + ffio_free_dyn_buf(&sv->pktbuf); } RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { .enc_name = "X-SV3V-ES", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_NONE, // see if (config_packet) above - .alloc = svq3_extradata_new, - .free = svq3_extradata_free, + .priv_data_size = sizeof(PayloadContext), + .close = svq3_close_context, .parse_packet = svq3_parse_packet, }; diff --git a/libavformat/rtpdec_vp8.c b/libavformat/rtpdec_vp8.c index fc86ac1..b7f9939 100644 --- a/libavformat/rtpdec_vp8.c +++ b/libavformat/rtpdec_vp8.c @@ -29,6 +29,7 @@ #include "libavcodec/bytestream.h" +#include "avio_internal.h" #include "rtpdec_formats.h" struct PayloadContext { @@ -45,29 +46,19 @@ struct PayloadContext { int prev_pictureid; int broken_frame; /* If sequence_dirty is set, we have lost some data (critical or - * non-critical) and decoding will have some sort of artefacts, and + * non-critical) and decoding will have some sort of artifacts, and * we thus should request a new keyframe. */ int sequence_dirty; int got_keyframe; }; -static void vp8_free_buffer(PayloadContext *vp8) -{ - uint8_t *tmp; - if (!vp8->data) - return; - avio_close_dyn_buf(vp8->data, &tmp); - av_free(tmp); - vp8->data = NULL; -} - static int vp8_broken_sequence(AVFormatContext *ctx, PayloadContext *vp8, const char *msg) { vp8->sequence_ok = 0; av_log(ctx, AV_LOG_WARNING, "%s", msg); - vp8_free_buffer(vp8); + ffio_free_dyn_buf(&vp8->data); return AVERROR(EAGAIN); } @@ -150,7 +141,7 @@ static int vp8_handle_packet(AVFormatContext *ctx, PayloadContext *vp8, int res; int non_key = buf[0] & 0x01; if (!non_key) { - vp8_free_buffer(vp8); + ffio_free_dyn_buf(&vp8->data); // Keyframe, decoding ok again vp8->sequence_ok = 1; vp8->sequence_dirty = 0; @@ -205,7 +196,7 @@ static int vp8_handle_packet(AVFormatContext *ctx, PayloadContext *vp8, old_timestamp = vp8->timestamp; } else { // Shouldn't happen - vp8_free_buffer(vp8); + ffio_free_dyn_buf(&vp8->data); } } } @@ -261,25 +252,23 @@ static int vp8_handle_packet(AVFormatContext *ctx, PayloadContext *vp8, return ret; if (vp8->sequence_dirty) pkt->flags |= AV_PKT_FLAG_CORRUPT; + if (vp8->is_keyframe) + pkt->flags |= AV_PKT_FLAG_KEY; return 0; } return AVERROR(EAGAIN); } -static PayloadContext *vp8_new_context(void) +static av_cold int vp8_init(AVFormatContext *s, int st_index, PayloadContext *vp8) { - PayloadContext *vp8 = av_mallocz(sizeof(PayloadContext)); - if (!vp8) - return NULL; vp8->sequence_ok = 1; - return vp8; + return 0; } -static void vp8_free_context(PayloadContext *vp8) +static void vp8_close_context(PayloadContext *vp8) { - vp8_free_buffer(vp8); - av_free(vp8); + ffio_free_dyn_buf(&vp8->data); } static int vp8_need_keyframe(PayloadContext *vp8) @@ -291,8 +280,9 @@ RTPDynamicProtocolHandler ff_vp8_dynamic_handler = { .enc_name = "VP8", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_VP8, - .alloc = vp8_new_context, - .free = vp8_free_context, + .priv_data_size = sizeof(PayloadContext), + .init = vp8_init, + .close = vp8_close_context, .parse_packet = vp8_handle_packet, .need_keyframe = vp8_need_keyframe, }; diff --git a/libavformat/rtpdec_vp9.c b/libavformat/rtpdec_vp9.c new file mode 100644 index 0000000..c0e6217 --- /dev/null +++ b/libavformat/rtpdec_vp9.c @@ -0,0 +1,341 @@ +/* + * RTP parser for VP9 payload format (draft version 02) - experimental + * Copyright (c) 2015 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avio_internal.h" +#include "rtpdec_formats.h" + +#define RTP_VP9_DESC_REQUIRED_SIZE 1 + +struct PayloadContext { + AVIOContext *buf; + uint32_t timestamp; +}; + +static av_cold int vp9_init(AVFormatContext *ctx, int st_index, + PayloadContext *data) +{ + av_log(ctx, AV_LOG_WARNING, + "RTP/VP9 support is still experimental\n"); + + return 0; +} + +static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx, + AVStream *st, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, uint16_t seq, + int flags) +{ + int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data; + av_unused int pic_id = 0, non_key_frame = 0, inter_picture_layer_frame; + av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1; + int ref_fields = 0, has_ref_field_ext_pic_id = 0; + int first_fragment, last_fragment; + int rtp_m; + int res = 0; + + /* drop data of previous packets in case of non-continuous (lossy) packet stream */ + if (rtp_vp9_ctx->buf && rtp_vp9_ctx->timestamp != *timestamp) + ffio_free_dyn_buf(&rtp_vp9_ctx->buf); + + /* sanity check for size of input packet: 1 byte payload at least */ + if (len < RTP_VP9_DESC_REQUIRED_SIZE + 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet, got %d bytes\n", len); + return AVERROR_INVALIDDATA; + } + + /* + * decode the required VP9 payload descriptor according to section 4.2 of the spec.: + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |I|P|L|F|B|E|V|-| (REQUIRED) + * +-+-+-+-+-+-+-+-+ + * + * I: PictureID present + * P: Inter-picture predicted layer frame + * L: Layer indices present + * F: Flexible mode + * B: Start of VP9 frame + * E: End of picture + * V: Scalability Structure (SS) present + */ + has_pic_id = !!(buf[0] & 0x80); + inter_picture_layer_frame = !!(buf[0] & 0x40); + has_layer_idc = !!(buf[0] & 0x20); + has_ref_idc = !!(buf[0] & 0x10); + first_fragment = !!(buf[0] & 0x08); + last_fragment = !!(buf[0] & 0x04); + has_ss_data = !!(buf[0] & 0x02); + + rtp_m = !!(flags & RTP_FLAG_MARKER); + + /* sanity check for markers: B should always be equal to the RTP M marker */ + if (last_fragment != rtp_m) { + av_log(ctx, AV_LOG_ERROR, "Invalid combination of B and M marker (%d != %d)\n", last_fragment, rtp_m); + return AVERROR_INVALIDDATA; + } + + /* pass the extensions field */ + buf += RTP_VP9_DESC_REQUIRED_SIZE; + len -= RTP_VP9_DESC_REQUIRED_SIZE; + + /* + * decode the 1-byte/2-byte picture ID: + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * I: |M|PICTURE ID | (RECOMMENDED) + * +-+-+-+-+-+-+-+-+ + * M: | EXTENDED PID | (RECOMMENDED) + * +-+-+-+-+-+-+-+-+ + * + * M: The most significant bit of the first octet is an extension flag. + * PictureID: 8 or 16 bits including the M bit. + */ + if (has_pic_id) { + /* check for 1-byte or 2-byte picture index */ + if (buf[0] & 0x80) { + if (len < 2) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + pic_id = AV_RB16(buf) & 0x7fff; + buf += 2; + len -= 2; + } else { + pic_id = buf[0] & 0x7f; + buf++; + len--; + } + } + + /* + * decode layer indices + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * L: | T | S | Q | R | (CONDITIONALLY RECOMMENDED) + * +-+-+-+-+-+-+-+-+ + * + * T, S and Q are 2-bit indices for temporal, spatial, and quality layers. + * If "F" is set in the initial octet, R is 2 bits representing the number + * of reference fields this frame refers to. + */ + if (has_layer_idc) { + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + layer_temporal = buf[0] & 0xC0; + layer_spatial = buf[0] & 0x30; + layer_quality = buf[0] & 0x0C; + if (has_ref_idc) { + ref_fields = buf[0] & 0x03; + if (ref_fields) + non_key_frame = 1; + } + buf++; + len--; + } + + /* + * decode the reference fields + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ -\ + * F: | PID |X| RS| RQ| (OPTIONAL) . + * +-+-+-+-+-+-+-+-+ . - R times + * X: | EXTENDED PID | (OPTIONAL) . + * +-+-+-+-+-+-+-+-+ -/ + * + * PID: The relative Picture ID referred to by this frame. + * RS and RQ: The spatial and quality layer IDs. + * X: 1 if this layer index has an extended relative Picture ID. + */ + if (has_ref_idc) { + while (ref_fields) { + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + + has_ref_field_ext_pic_id = buf[0] & 0x10; + + /* pass ref. field */ + if (has_ref_field_ext_pic_id) { + if (len < 2) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + + /* ignore ref. data */ + + buf += 2; + len -= 2; + } else { + + /* ignore ref. data */ + + buf++; + len--; + } + ref_fields--; + } + } + + /* + * decode the scalability structure (SS) + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * V: | PATTERN LENGTH| + * +-+-+-+-+-+-+-+-+ -\ + * | T | S | Q | R | (OPTIONAL) . + * +-+-+-+-+-+-+-+-+ -\ . + * | PID |X| RS| RQ| (OPTIONAL) . . - PAT. LEN. times + * +-+-+-+-+-+-+-+-+ . - R times . + * X: | EXTENDED PID | (OPTIONAL) . . + * +-+-+-+-+-+-+-+-+ -/ -/ + * + * PID: The relative Picture ID referred to by this frame. + * RS and RQ: The spatial and quality layer IDs. + * X: 1 if this layer index has an extended relative Picture ID. + */ + if (has_ss_data) { + int n_s, y, g, i; + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + n_s = buf[0] >> 5; + y = !!(buf[0] & 0x10); + g = !!(buf[0] & 0x08); + buf++; + len--; + if (n_s > 0) { + avpriv_report_missing_feature(ctx, "VP9 scalability structure with multiple layers"); + return AVERROR_PATCHWELCOME; + } + if (y) { + if (len < 4 * (n_s + 1)) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < n_s + 1; i++) { + av_unused int w, h; + w = AV_RB16(buf); + h = AV_RB16(buf + 2); + buf += 4; + len -= 4; + } + } + if (g) { + int n_g; + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + n_g = buf[0]; + buf++; + len--; + for (i = 0; i < n_g; i++) { + av_unused int t, u, r, j; + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + t = buf[0] >> 5; + u = !!(buf[0] & 0x10); + r = (buf[0] >> 2) & 0x03; + buf++; + len--; + if (len < r) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + for (j = 0; j < r; j++) { + av_unused int p_diff = buf[0]; + buf++; + len--; + } + } + } + } + + /* + * decode the VP9 payload header + * + * spec. is tbd + */ + //XXX: implement when specified + + /* sanity check: 1 byte payload as minimum */ + if (len < 1) { + av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n"); + return AVERROR_INVALIDDATA; + } + + /* start frame buffering with new dynamic buffer */ + if (!rtp_vp9_ctx->buf) { + /* sanity check: a new frame should have started */ + if (first_fragment) { + res = avio_open_dyn_buf(&rtp_vp9_ctx->buf); + if (res < 0) + return res; + /* update the timestamp in the frame packet with the one from the RTP packet */ + rtp_vp9_ctx->timestamp = *timestamp; + } else { + /* frame not started yet, need more packets */ + return AVERROR(EAGAIN); + } + } + + /* write the fragment to the dyn. buffer */ + avio_write(rtp_vp9_ctx->buf, buf, len); + + /* do we need more fragments? */ + if (!last_fragment) + return AVERROR(EAGAIN); + + /* close frame buffering and create resulting A/V packet */ + res = ff_rtp_finalize_packet(pkt, &rtp_vp9_ctx->buf, st->index); + if (res < 0) + return res; + + return 0; +} + +static void vp9_close_context(PayloadContext *vp9) +{ + ffio_free_dyn_buf(&vp9->buf); +} + +RTPDynamicProtocolHandler ff_vp9_dynamic_handler = { + .enc_name = "VP9", + .codec_type = AVMEDIA_TYPE_VIDEO, + .codec_id = AV_CODEC_ID_VP9, + .priv_data_size = sizeof(PayloadContext), + .init = vp9_init, + .close = vp9_close_context, + .parse_packet = vp9_handle_packet +}; diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c index 9e4fbc5..5ad6974 100644 --- a/libavformat/rtpdec_xiph.c +++ b/libavformat/rtpdec_xiph.c @@ -34,6 +34,7 @@ #include +#include "avio_internal.h" #include "rtpdec.h" #include "rtpdec_formats.h" @@ -49,35 +50,10 @@ struct PayloadContext { int split_pkts; }; -static PayloadContext *xiph_new_context(void) +static void xiph_close_context(PayloadContext * data) { - return av_mallocz(sizeof(PayloadContext)); -} - -static inline void free_fragment_if_needed(PayloadContext * data) -{ - if (data->fragment) { - uint8_t* p; - avio_close_dyn_buf(data->fragment, &p); - av_free(p); - data->fragment = NULL; - } -} - -static void xiph_free_context(PayloadContext * data) -{ - free_fragment_if_needed(data); + ffio_free_dyn_buf(&data->fragment); av_free(data->split_buf); - av_free(data); -} - -static av_cold int xiph_vorbis_init(AVFormatContext *ctx, int st_index, - PayloadContext *data) -{ - if (st_index < 0) - return 0; - ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_HEADERS; - return 0; } @@ -165,7 +141,7 @@ static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, data->split_buf = av_malloc(data->split_buf_size); if (!data->split_buf) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } } @@ -183,7 +159,7 @@ static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, int res; // end packet has been lost somewhere, so drop buffered data - free_fragment_if_needed(data); + ffio_free_dyn_buf(&data->fragment); if((res = avio_open_dyn_buf(&data->fragment)) < 0) return res; @@ -196,7 +172,7 @@ static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, if (data->timestamp != *timestamp) { // skip if fragmented timestamp is incorrect; // a start packet has been lost somewhere - free_fragment_if_needed(data); + ffio_free_dyn_buf(&data->fragment); av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match!\n"); return AVERROR_INVALIDDATA; } @@ -246,16 +222,17 @@ static int get_base128(const uint8_t ** buf, const uint8_t * buf_end) * Based off parse_packed_headers in Vorbis RTP */ static int -parse_packed_headers(const uint8_t * packed_headers, +parse_packed_headers(AVFormatContext *s, + const uint8_t * packed_headers, const uint8_t * packed_headers_end, - AVCodecContext * codec, PayloadContext * xiph_data) + AVCodecParameters *par, PayloadContext * xiph_data) { unsigned num_packed, num_headers, length, length1, length2, extradata_alloc; uint8_t *ptr; if (packed_headers_end - packed_headers < 9) { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Invalid %td byte packed header.", packed_headers_end - packed_headers); return AVERROR_INVALIDDATA; @@ -269,7 +246,7 @@ parse_packed_headers(const uint8_t * packed_headers, length2 = get_base128(&packed_headers, packed_headers_end); if (num_packed != 1 || num_headers > 3) { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Unimplemented number of headers: %d packed headers, %d headers\n", num_packed, num_headers); return AVERROR_PATCHWELCOME; @@ -277,7 +254,7 @@ parse_packed_headers(const uint8_t * packed_headers, if (packed_headers_end - packed_headers != length || length1 > length || length2 > length - length1) { - av_log(codec, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Bad packed header lengths (%d,%d,%td,%d)\n", length1, length2, packed_headers_end - packed_headers, length); return AVERROR_INVALIDDATA; @@ -286,12 +263,12 @@ parse_packed_headers(const uint8_t * packed_headers, /* allocate extra space: * -- length/255 +2 for xiphlacing * -- one for the '2' marker - * -- FF_INPUT_BUFFER_PADDING_SIZE required */ - extradata_alloc = length + length/255 + 3 + FF_INPUT_BUFFER_PADDING_SIZE; + * -- AV_INPUT_BUFFER_PADDING_SIZE required */ + extradata_alloc = length + length/255 + 3 + AV_INPUT_BUFFER_PADDING_SIZE; - ptr = codec->extradata = av_malloc(extradata_alloc); + ptr = par->extradata = av_malloc(extradata_alloc); if (!ptr) { - av_log(codec, AV_LOG_ERROR, "Out of memory\n"); + av_log(s, AV_LOG_ERROR, "Out of memory\n"); return AVERROR(ENOMEM); } *ptr++ = 2; @@ -299,9 +276,9 @@ parse_packed_headers(const uint8_t * packed_headers, ptr += av_xiphlacing(ptr, length2); memcpy(ptr, packed_headers, length); ptr += length; - codec->extradata_size = ptr - codec->extradata; + par->extradata_size = ptr - par->extradata; // clear out remaining parts of the buffer - memset(ptr, 0, extradata_alloc - codec->extradata_size); + memset(ptr, 0, extradata_alloc - par->extradata_size); return 0; } @@ -309,18 +286,18 @@ parse_packed_headers(const uint8_t * packed_headers, static int xiph_parse_fmtp_pair(AVFormatContext *s, AVStream* stream, PayloadContext *xiph_data, - char *attr, char *value) + const char *attr, const char *value) { - AVCodecContext *codec = stream->codec; + AVCodecParameters *par = stream->codecpar; int result = 0; if (!strcmp(attr, "sampling")) { if (!strcmp(value, "YCbCr-4:2:0")) { - codec->pix_fmt = AV_PIX_FMT_YUV420P; + par->format = AV_PIX_FMT_YUV420P; } else if (!strcmp(value, "YCbCr-4:4:2")) { - codec->pix_fmt = AV_PIX_FMT_YUV422P; + par->format = AV_PIX_FMT_YUV422P; } else if (!strcmp(value, "YCbCr-4:4:4")) { - codec->pix_fmt = AV_PIX_FMT_YUV444P; + par->format = AV_PIX_FMT_YUV444P; } else { av_log(s, AV_LOG_ERROR, "Unsupported pixel format %s\n", attr); @@ -329,12 +306,12 @@ static int xiph_parse_fmtp_pair(AVFormatContext *s, } else if (!strcmp(attr, "width")) { /* This is an integer between 1 and 1048561 * and MUST be in multiples of 16. */ - codec->width = atoi(value); + par->width = atoi(value); return 0; } else if (!strcmp(attr, "height")) { /* This is an integer between 1 and 1048561 * and MUST be in multiples of 16. */ - codec->height = atoi(value); + par->height = atoi(value); return 0; } else if (!strcmp(attr, "delivery-method")) { /* Possible values are: inline, in_band, out_band/specific_name. */ @@ -358,7 +335,7 @@ static int xiph_parse_fmtp_pair(AVFormatContext *s, av_base64_decode(decoded_packet, value, decoded_alloc); result = parse_packed_headers - (decoded_packet, decoded_packet + packet_size, codec, + (s, decoded_packet, decoded_packet + packet_size, par, xiph_data); } else { av_log(s, AV_LOG_ERROR, @@ -394,19 +371,19 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = { .enc_name = "theora", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_THEORA, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = xiph_parse_sdp_line, - .alloc = xiph_new_context, - .free = xiph_free_context, - .parse_packet = xiph_handle_packet + .close = xiph_close_context, + .parse_packet = xiph_handle_packet, }; RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = { .enc_name = "vorbis", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_VORBIS, - .init = xiph_vorbis_init, + .need_parsing = AVSTREAM_PARSE_HEADERS, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = xiph_parse_sdp_line, - .alloc = xiph_new_context, - .free = xiph_free_context, - .parse_packet = xiph_handle_packet + .close = xiph_close_context, + .parse_packet = xiph_handle_packet, }; diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 7bc7373..2cae839 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -49,9 +49,11 @@ static const AVClass rtp_muxer_class = { static int is_supported(enum AVCodecID id) { switch(id) { + case AV_CODEC_ID_H261: case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: case AV_CODEC_ID_H264: + case AV_CODEC_ID_HEVC: case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MPEG4: @@ -87,7 +89,7 @@ static int is_supported(enum AVCodecID id) static int rtp_write_header(AVFormatContext *s1) { RTPMuxContext *s = s1->priv_data; - int n; + int n, ret = AVERROR(EINVAL); AVStream *st; if (s1->nb_streams != 1) { @@ -95,8 +97,8 @@ static int rtp_write_header(AVFormatContext *s1) return AVERROR(EINVAL); } st = s1->streams[0]; - if (!is_supported(st->codec->codec_id)) { - av_log(s1, AV_LOG_ERROR, "Unsupported codec %x\n", st->codec->codec_id); + if (!is_supported(st->codecpar->codec_id)) { + av_log(s1, AV_LOG_ERROR, "Unsupported codec %x\n", st->codecpar->codec_id); return -1; } @@ -104,7 +106,7 @@ static int rtp_write_header(AVFormatContext *s1) if (s->payload_type < 0) { /* Re-validate non-dynamic payload types */ if (st->id < RTP_PT_PRIVATE) - st->id = ff_rtp_get_payload_type(s1, st->codec, -1); + st->id = ff_rtp_get_payload_type(s1, st->codecpar, -1); s->payload_type = st->id; } else { @@ -147,38 +149,17 @@ static int rtp_write_header(AVFormatContext *s1) } s->max_payload_size = s1->packet_size - 12; - s->max_frames_per_packet = 0; - if (s1->max_delay > 0) { - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - int frame_size = av_get_audio_frame_duration(st->codec, 0); - if (!frame_size) - frame_size = st->codec->frame_size; - if (frame_size == 0) { - av_log(s1, AV_LOG_ERROR, "Cannot respect max delay: frame size = 0\n"); - } else { - s->max_frames_per_packet = - av_rescale_q_rnd(s1->max_delay, - AV_TIME_BASE_Q, - (AVRational){ frame_size, st->codec->sample_rate }, - AV_ROUND_DOWN); - } - } - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - /* FIXME: We should round down here... */ - if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0) { - s->max_frames_per_packet = av_rescale_q(s1->max_delay, - (AVRational){1, 1000000}, - av_inv_q(st->avg_frame_rate)); - } else - s->max_frames_per_packet = 1; - } + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); + } else { + avpriv_set_pts_info(st, 32, 1, 90000); } - - avpriv_set_pts_info(st, 32, 1, 90000); - switch(st->codec->codec_id) { + s->buf_ptr = s->buf; + switch(st->codecpar->codec_id) { case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: s->buf_ptr = s->buf + 4; + avpriv_set_pts_info(st, 32, 1, 90000); break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: @@ -188,28 +169,44 @@ static int rtp_write_header(AVFormatContext *s1) if (n < 1) n = 1; s->max_payload_size = n * TS_PACKET_SIZE; - s->buf_ptr = s->buf; + break; + case AV_CODEC_ID_H261: + if (s1->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(s, AV_LOG_ERROR, + "Packetizing H.261 is experimental and produces incorrect " + "packetization for cases where GOBs don't fit into packets " + "(even though most receivers may handle it just fine). " + "Please set -f_strict experimental in order to enable it.\n"); + ret = AVERROR_EXPERIMENTAL; + goto fail; + } break; case AV_CODEC_ID_H264: /* check for H.264 MP4 syntax */ - if (st->codec->extradata_size > 4 && st->codec->extradata[0] == 1) { - s->nal_length_size = (st->codec->extradata[4] & 0x03) + 1; + if (st->codecpar->extradata_size > 4 && st->codecpar->extradata[0] == 1) { + s->nal_length_size = (st->codecpar->extradata[4] & 0x03) + 1; + } + break; + case AV_CODEC_ID_HEVC: + /* Only check for the standardized hvcC version of extradata, keeping + * things simple and similar to the avcC/H.264 case above, instead + * of trying to handle the pre-standardization versions (as in + * libavcodec/hevc.c). */ + if (st->codecpar->extradata_size > 21 && st->codecpar->extradata[0] == 1) { + s->nal_length_size = (st->codecpar->extradata[21] & 0x03) + 1; } break; case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: - if (!s->max_frames_per_packet) s->max_frames_per_packet = 15; - s->max_frames_per_packet = av_clip(s->max_frames_per_packet, 1, 15); - s->max_payload_size -= 6; // ident+frag+tdt/vdt+pkt_num+pkt_length - s->num_frames = 0; - goto defaultcase; + s->max_frames_per_packet = 15; + break; case AV_CODEC_ID_ADPCM_G722: /* Due to a historical error, the clock rate for G722 in RTP is * 8000, even if the sample rate is 16000. See RFC 3551. */ avpriv_set_pts_info(st, 32, 1, 8000); break; case AV_CODEC_ID_OPUS: - if (st->codec->channels > 2) { + if (st->codecpar->channels > 2) { av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n"); goto fail; } @@ -219,20 +216,16 @@ static int rtp_write_header(AVFormatContext *s1) avpriv_set_pts_info(st, 32, 1, 48000); break; case AV_CODEC_ID_ILBC: - if (st->codec->block_align != 38 && st->codec->block_align != 50) { + if (st->codecpar->block_align != 38 && st->codecpar->block_align != 50) { av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n"); goto fail; } - if (!s->max_frames_per_packet) - s->max_frames_per_packet = 1; - s->max_frames_per_packet = FFMIN(s->max_frames_per_packet, - s->max_payload_size / st->codec->block_align); - goto defaultcase; + s->max_frames_per_packet = s->max_payload_size / st->codecpar->block_align; + break; case AV_CODEC_ID_AMR_NB: case AV_CODEC_ID_AMR_WB: - if (!s->max_frames_per_packet) - s->max_frames_per_packet = 12; - if (st->codec->codec_id == AV_CODEC_ID_AMR_NB) + s->max_frames_per_packet = 50; + if (st->codecpar->codec_id == AV_CODEC_ID_AMR_NB) n = 31; else n = 61; @@ -241,18 +234,15 @@ static int rtp_write_header(AVFormatContext *s1) av_log(s1, AV_LOG_ERROR, "RTP max payload size too small for AMR\n"); goto fail; } - if (st->codec->channels != 1) { + if (st->codecpar->channels != 1) { av_log(s1, AV_LOG_ERROR, "Only mono is supported\n"); goto fail; } + break; case AV_CODEC_ID_AAC: - s->num_frames = 0; + s->max_frames_per_packet = 50; + break; default: -defaultcase: - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); - } - s->buf_ptr = s->buf; break; } @@ -260,7 +250,7 @@ defaultcase: fail: av_freep(&s->buf); - return AVERROR(EINVAL); + return ret; } /* send an rtcp sender report packet */ @@ -269,7 +259,7 @@ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time, int bye) RTPMuxContext *s = s1->priv_data; uint32_t rtp_ts; - av_dlog(s1, "RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); + av_log(s1, AV_LOG_TRACE, "RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); s->last_rtcp_ntp_time = ntp_time; rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, (AVRational){1, 1000000}, @@ -314,7 +304,7 @@ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m) { RTPMuxContext *s = s1->priv_data; - av_dlog(s1, "rtp_send_data size=%d\n", len); + av_log(s1, AV_LOG_TRACE, "rtp_send_data size=%d\n", len); /* build the RTP header */ avio_w8(s1->pb, RTP_VERSION << 6); @@ -442,6 +432,7 @@ static void rtp_send_mpegts_raw(AVFormatContext *s1, RTPMuxContext *s = s1->priv_data; int len, out_len; + s->timestamp = s->cur_timestamp; while (size >= TS_PACKET_SIZE) { len = s->max_payload_size - (s->buf_ptr - s->buf); if (len > size) @@ -463,23 +454,28 @@ static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size) { RTPMuxContext *s = s1->priv_data; AVStream *st = s1->streams[0]; - int frame_duration = av_get_audio_frame_duration(st->codec, 0); - int frame_size = st->codec->block_align; + int frame_duration = av_get_audio_frame_duration2(st->codecpar, 0); + int frame_size = st->codecpar->block_align; int frames = size / frame_size; while (frames > 0) { - int n = FFMIN(s->max_frames_per_packet - s->num_frames, frames); + if (s->num_frames > 0 && + av_compare_ts(s->cur_timestamp - s->timestamp, st->time_base, + s1->max_delay, AV_TIME_BASE_Q) >= 0) { + ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1); + s->num_frames = 0; + } if (!s->num_frames) { s->buf_ptr = s->buf; s->timestamp = s->cur_timestamp; } - memcpy(s->buf_ptr, buf, n * frame_size); - frames -= n; - s->num_frames += n; - s->buf_ptr += n * frame_size; - buf += n * frame_size; - s->cur_timestamp += n * frame_duration; + memcpy(s->buf_ptr, buf, frame_size); + frames--; + s->num_frames++; + s->buf_ptr += frame_size; + buf += frame_size; + s->cur_timestamp += frame_duration; if (s->num_frames == s->max_frames_per_packet) { ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1); @@ -496,7 +492,7 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) int rtcp_bytes; int size= pkt->size; - av_dlog(s1, "%d: write len=%d\n", pkt->stream_index, size); + av_log(s1, AV_LOG_TRACE, "%d: write len=%d\n", pkt->stream_index, size); rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / RTCP_TX_RATIO_DEN; @@ -509,26 +505,26 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) } s->cur_timestamp = s->base_timestamp + pkt->pts; - switch(st->codec->codec_id) { + switch(st->codecpar->codec_id) { case AV_CODEC_ID_PCM_MULAW: case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_U8: case AV_CODEC_ID_PCM_S8: - return rtp_send_samples(s1, pkt->data, size, 8 * st->codec->channels); + return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels); case AV_CODEC_ID_PCM_U16BE: case AV_CODEC_ID_PCM_U16LE: case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16LE: - return rtp_send_samples(s1, pkt->data, size, 16 * st->codec->channels); + return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->channels); case AV_CODEC_ID_ADPCM_G722: /* The actual sample size is half a byte per sample, but since the * stream clock rate is 8000 Hz while the sample rate is 16000 Hz, * the correct parameter for send_samples_bits is 8 bits per stream * clock. */ - return rtp_send_samples(s1, pkt->data, size, 8 * st->codec->channels); + return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels); case AV_CODEC_ID_ADPCM_G726: return rtp_send_samples(s1, pkt->data, size, - st->codec->bits_per_coded_sample * st->codec->channels); + st->codecpar->bits_per_coded_sample * st->codecpar->channels); case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: rtp_send_mpegaudio(s1, pkt->data, size); @@ -551,7 +547,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) rtp_send_mpegts_raw(s1, pkt->data, size); break; case AV_CODEC_ID_H264: - ff_rtp_send_h264(s1, pkt->data, size); + ff_rtp_send_h264_hevc(s1, pkt->data, size); + break; + case AV_CODEC_ID_H261: + ff_rtp_send_h261(s1, pkt->data, size); break; case AV_CODEC_ID_H263: if (s->flags & FF_RTP_FLAG_RFC2190) { @@ -566,6 +565,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_H263P: ff_rtp_send_h263(s1, pkt->data, size); break; + case AV_CODEC_ID_HEVC: + ff_rtp_send_h264_hevc(s1, pkt->data, size); + break; case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: ff_rtp_send_xiph(s1, pkt->data, size); @@ -618,4 +620,5 @@ AVOutputFormat ff_rtp_muxer = { .write_packet = rtp_write_packet, .write_trailer = rtp_write_trailer, .priv_class = &rtp_muxer_class, + .flags = AVFMT_TS_NONSTRICT, }; diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index 35ee151..c4b27f0 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -56,6 +56,7 @@ struct RTPMuxContext { * (1, 2 or 4) */ int nal_length_size; + int buffered_nals; int flags; @@ -75,12 +76,13 @@ typedef struct RTPMuxContext RTPMuxContext; { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ { "rfc2190", "Use RFC 2190 packetization instead of RFC 4629 for H.263", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_RFC2190}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ { "skip_rtcp", "Don't send RTCP sender reports", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_SKIP_RTCP}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ - { "h264_mode0", "Use mode 0 for H264 in RTP", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_H264_MODE0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ + { "h264_mode0", "Use mode 0 for H.264 in RTP", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_H264_MODE0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ { "send_bye", "Send RTCP BYE packets when finishing", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_SEND_BYE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" } \ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); -void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); +void ff_rtp_send_h264_hevc(AVFormatContext *s1, const uint8_t *buf1, int size); +void ff_rtp_send_h261(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf1, int size, const uint8_t *mb_info, int mb_info_size); diff --git a/libavformat/rtpenc_aac.c b/libavformat/rtpenc_aac.c index 1b2fa0a..ee01b04 100644 --- a/libavformat/rtpenc_aac.c +++ b/libavformat/rtpenc_aac.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" + #include "avformat.h" #include "rtpenc.h" @@ -25,21 +27,24 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size) { RTPMuxContext *s = s1->priv_data; - int len, max_packet_size; + AVStream *st = s1->streams[0]; + const int max_au_headers_size = 2 + 2 * s->max_frames_per_packet; + int len, max_packet_size = s->max_payload_size - max_au_headers_size; uint8_t *p; - const int max_frames_per_packet = s->max_frames_per_packet ? s->max_frames_per_packet : 5; - const int max_au_headers_size = 2 + 2 * max_frames_per_packet; /* skip ADTS header, if present */ - if ((s1->streams[0]->codec->extradata_size) == 0) { + if ((s1->streams[0]->codecpar->extradata_size) == 0) { size -= 7; buff += 7; } - max_packet_size = s->max_payload_size - max_au_headers_size; /* test if the packet must be sent */ len = (s->buf_ptr - s->buf); - if ((s->num_frames == max_frames_per_packet) || (len && (len + size) > s->max_payload_size)) { + if (s->num_frames && + (s->num_frames == s->max_frames_per_packet || + (len + size) > s->max_payload_size || + av_compare_ts(s->cur_timestamp - s->timestamp, st->time_base, + s1->max_delay, AV_TIME_BASE_Q) >= 0)) { int au_size = s->num_frames * 2; p = s->buf + max_au_headers_size - au_size - 2; @@ -47,8 +52,7 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size) memmove(p + 2, s->buf + 2, au_size); } /* Write the AU header size */ - p[0] = au_size >> 5; - p[1] = (au_size & 0x1F) << 3; + AV_WB16(p, au_size * 8); ff_rtp_send_data(s1, p, s->buf_ptr - p, 1); @@ -61,8 +65,7 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size) if (size <= max_packet_size) { p = s->buf + s->num_frames++ * 2 + 2; - *p++ = size >> 5; - *p = (size & 0x1F) << 3; + AV_WB16(p, size * 8); memcpy(s->buf_ptr, buff, size); s->buf_ptr += size; } else { @@ -70,12 +73,10 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size) max_packet_size = s->max_payload_size - 4; p = s->buf; - p[0] = 0; - p[1] = 16; + AV_WB16(p, 2 * 8); while (size > 0) { len = FFMIN(size, max_packet_size); - p[2] = au_size >> 5; - p[3] = (au_size & 0x1F) << 3; + AV_WB16(&p[2], au_size * 8); memcpy(p + 4, buff, len); ff_rtp_send_data(s1, p, len + 4, len == size); size -= len; diff --git a/libavformat/rtpenc_amr.c b/libavformat/rtpenc_amr.c index 73da8c8..0adbf49 100644 --- a/libavformat/rtpenc_amr.c +++ b/libavformat/rtpenc_amr.c @@ -30,13 +30,18 @@ void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size) { RTPMuxContext *s = s1->priv_data; + AVStream *st = s1->streams[0]; int max_header_toc_size = 1 + s->max_frames_per_packet; uint8_t *p; int len; /* Test if the packet must be sent. */ len = s->buf_ptr - s->buf; - if (s->num_frames == s->max_frames_per_packet || (len && len + size - 1 > s->max_payload_size)) { + if (s->num_frames && + (s->num_frames == s->max_frames_per_packet || + len + size - 1 > s->max_payload_size || + av_compare_ts(s->cur_timestamp - s->timestamp, st->time_base, + s1->max_delay, AV_TIME_BASE_Q) >= 0)) { int header_size = s->num_frames + 1; p = s->buf + max_header_toc_size - header_size; if (p != s->buf) diff --git a/libavformat/rtpenc_chain.c b/libavformat/rtpenc_chain.c index 10c4020..7b06130 100644 --- a/libavformat/rtpenc_chain.c +++ b/libavformat/rtpenc_chain.c @@ -62,7 +62,7 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, /* Get the payload type from the codec */ if (st->id < RTP_PT_PRIVATE) rtpctx->streams[0]->id = - ff_rtp_get_payload_type(s, st->codec, idx); + ff_rtp_get_payload_type(s, st->codecpar, idx); else rtpctx->streams[0]->id = st->id; @@ -72,7 +72,8 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, /* Set the synchronized start time. */ rtpctx->start_time_realtime = s->start_time_realtime; - avcodec_copy_context(rtpctx->streams[0]->codec, st->codec); + avcodec_parameters_copy(rtpctx->streams[0]->codecpar, st->codecpar); + rtpctx->streams[0]->time_base = st->time_base; if (handle) { ret = ffio_fdopen(&rtpctx->pb, handle); @@ -88,9 +89,7 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, if (handle && rtpctx->pb) { avio_close(rtpctx->pb); } else if (rtpctx->pb) { - uint8_t *ptr; - avio_close_dyn_buf(rtpctx->pb, &ptr); - av_free(ptr); + ffio_free_dyn_buf(&rtpctx->pb); } avformat_free_context(rtpctx); return ret; diff --git a/libavformat/rtpenc_h261.c b/libavformat/rtpenc_h261.c new file mode 100644 index 0000000..550f04f --- /dev/null +++ b/libavformat/rtpenc_h261.c @@ -0,0 +1,102 @@ +/* + * RTP packetization for H.261 video (RFC 4587) + * Copyright (c) 2014 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rtpenc.h" + +#define RTP_H261_HEADER_SIZE 4 + +static const uint8_t *find_resync_marker_reverse(const uint8_t *restrict start, + const uint8_t *restrict end) +{ + const uint8_t *p = end - 1; + start += 1; /* Make sure we never return the original start. */ + for (; p > start; p--) { + if (p[0] == 0 && p[1] == 1) + return p; + } + return end; +} + +void ff_rtp_send_h261(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size) +{ + int cur_frame_size; + int last_packet_of_frame; + RTPMuxContext *rtp_ctx = ctx->priv_data; + + /* use the default 90 KHz time stamp */ + rtp_ctx->timestamp = rtp_ctx->cur_timestamp; + + /* continue as long as not all frame data is processed */ + while (frame_size > 0) { + /* + * encode the H.261 payload header according to section 4.1 of RFC 4587: + * (uses 4 bytes between RTP header and H.261 stream per packet) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Start bit position (SBIT): 3 bits + * End bit position (EBIT): 3 bits + * INTRA-frame encoded data (I): 1 bit + * Motion Vector flag (V): 1 bit + * GOB number (GOBN): 4 bits + * Macroblock address predictor (MBAP): 5 bits + * Quantizer (QUANT): 5 bits + * Horizontal motion vector data (HMVD): 5 bits + * Vertical motion vector data (VMVD): 5 bits + */ + rtp_ctx->buf[0] = 1; /* sbit=0, ebit=0, i=0, v=1 */ + rtp_ctx->buf[1] = 0; /* gobn=0, mbap=0 */ + rtp_ctx->buf[2] = 0; /* quant=0, hmvd=5 */ + rtp_ctx->buf[3] = 0; /* vmvd=0 */ + if (frame_size < 2 || frame_buf[0] != 0 || frame_buf[1] != 1) { + /* A full, correct fix for this would be to make the H.261 encoder + * support inserting extra GOB headers (triggered by setting e.g. + * "-ps 1"), and including information about macroblock boundaries + * (such as for h263_rfc2190). */ + av_log(ctx, AV_LOG_WARNING, + "RTP/H.261 packet not cut at a GOB boundary, not signaled correctly\n"); + } + + cur_frame_size = FFMIN(rtp_ctx->max_payload_size - RTP_H261_HEADER_SIZE, frame_size); + + /* look for a better place to split the frame into packets */ + if (cur_frame_size < frame_size) { + const uint8_t *packet_end = find_resync_marker_reverse(frame_buf, + frame_buf + cur_frame_size); + cur_frame_size = packet_end - frame_buf; + } + + /* calculate the "marker" bit for the RTP header */ + last_packet_of_frame = cur_frame_size == frame_size; + + /* complete and send RTP packet */ + memcpy(&rtp_ctx->buf[RTP_H261_HEADER_SIZE], frame_buf, cur_frame_size); + ff_rtp_send_data(ctx, rtp_ctx->buf, RTP_H261_HEADER_SIZE + cur_frame_size, last_packet_of_frame); + + frame_buf += cur_frame_size; + frame_size -= cur_frame_size; + } +} diff --git a/libavformat/rtpenc_h263_rfc2190.c b/libavformat/rtpenc_h263_rfc2190.c index f714d01..b8d7a0a 100644 --- a/libavformat/rtpenc_h263_rfc2190.c +++ b/libavformat/rtpenc_h263_rfc2190.c @@ -114,7 +114,7 @@ void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf, int size, init_get_bits(&gb, buf, size*8); if (get_bits(&gb, 22) == 0x20) { /* Picture Start Code */ info.tr = get_bits(&gb, 8); - skip_bits(&gb, 2); /* PTYPE start, H261 disambiguation */ + skip_bits(&gb, 2); /* PTYPE start, H.261 disambiguation */ skip_bits(&gb, 3); /* Split screen, document camera, freeze picture release */ info.src = get_bits(&gb, 3); info.i = get_bits(&gb, 1); @@ -165,11 +165,11 @@ void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf, int size, mb_info_pos++; } else { av_log(s1, AV_LOG_ERROR, - "Unable to split H263 packet, use -mb_info %d " + "Unable to split H.263 packet, use -mb_info %d " "or lower.\n", s->max_payload_size - 8); } } else { - av_log(s1, AV_LOG_ERROR, "Unable to split H263 packet, " + av_log(s1, AV_LOG_ERROR, "Unable to split H.263 packet, " "use -mb_info %d or -ps 1.\n", s->max_payload_size - 8); } diff --git a/libavformat/rtpenc_h264.c b/libavformat/rtpenc_h264.c deleted file mode 100644 index 206d9ba..0000000 --- a/libavformat/rtpenc_h264.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * RTP packetization for H.264 (RFC3984) - * Copyright (c) 2008 Luca Abeni - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * @brief H.264 packetization - * @author Luca Abeni - */ - -#include "avformat.h" -#include "avc.h" -#include "rtpenc.h" - -static const uint8_t *avc_mp4_find_startcode(const uint8_t *start, const uint8_t *end, int nal_length_size) -{ - unsigned int res = 0; - - if (end - start < nal_length_size) - return NULL; - while (nal_length_size--) - res = (res << 8) | *start++; - - if (res > end - start) - return NULL; - - return start + res; -} - -static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last) -{ - RTPMuxContext *s = s1->priv_data; - - av_log(s1, AV_LOG_DEBUG, "Sending NAL %x of len %d M=%d\n", buf[0] & 0x1F, size, last); - if (size <= s->max_payload_size) { - ff_rtp_send_data(s1, buf, size, last); - } else { - uint8_t type = buf[0] & 0x1F; - uint8_t nri = buf[0] & 0x60; - - if (s->flags & FF_RTP_FLAG_H264_MODE0) { - av_log(s1, AV_LOG_ERROR, - "NAL size %d > %d, try -slice-max-size %d\n", size, - s->max_payload_size, s->max_payload_size); - return; - } - av_log(s1, AV_LOG_DEBUG, "NAL size %d > %d\n", size, s->max_payload_size); - s->buf[0] = 28; /* FU Indicator; Type = 28 ---> FU-A */ - s->buf[0] |= nri; - s->buf[1] = type; - s->buf[1] |= 1 << 7; - buf += 1; - size -= 1; - while (size + 2 > s->max_payload_size) { - memcpy(&s->buf[2], buf, s->max_payload_size - 2); - ff_rtp_send_data(s1, s->buf, s->max_payload_size, 0); - buf += s->max_payload_size - 2; - size -= s->max_payload_size - 2; - s->buf[1] &= ~(1 << 7); - } - s->buf[1] |= 1 << 6; - memcpy(&s->buf[2], buf, size); - ff_rtp_send_data(s1, s->buf, size + 2, last); - } -} - -void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size) -{ - const uint8_t *r, *end = buf1 + size; - RTPMuxContext *s = s1->priv_data; - - s->timestamp = s->cur_timestamp; - if (s->nal_length_size) - r = avc_mp4_find_startcode(buf1, end, s->nal_length_size) ? buf1 : end; - else - r = ff_avc_find_startcode(buf1, end); - while (r < end) { - const uint8_t *r1; - - if (s->nal_length_size) { - r1 = avc_mp4_find_startcode(r, end, s->nal_length_size); - if (!r1) - r1 = end; - r += s->nal_length_size; - } else { - while (!*(r++)); - r1 = ff_avc_find_startcode(r, end); - } - nal_send(s1, r, r1 - r, r1 == end); - r = r1; - } -} diff --git a/libavformat/rtpenc_h264_hevc.c b/libavformat/rtpenc_h264_hevc.c new file mode 100644 index 0000000..9f329a6 --- /dev/null +++ b/libavformat/rtpenc_h264_hevc.c @@ -0,0 +1,207 @@ +/* + * RTP packetization for H.264 (RFC3984) + * RTP packetizer for HEVC/H.265 payload format (draft version 6) + * Copyright (c) 2008 Luca Abeni + * Copyright (c) 2014 Thomas Volkert + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @brief H.264/HEVC packetization + * @author Luca Abeni + */ + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "avc.h" +#include "rtpenc.h" + +static void flush_buffered(AVFormatContext *s1, int last) +{ + RTPMuxContext *s = s1->priv_data; + if (s->buf_ptr != s->buf) { + // If we're only sending one single NAL unit, send it as such, skip + // the STAP-A/AP framing + if (s->buffered_nals == 1) { + enum AVCodecID codec = s1->streams[0]->codecpar->codec_id; + if (codec == AV_CODEC_ID_H264) + ff_rtp_send_data(s1, s->buf + 3, s->buf_ptr - s->buf - 3, last); + else + ff_rtp_send_data(s1, s->buf + 4, s->buf_ptr - s->buf - 4, last); + } else + ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, last); + } + s->buf_ptr = s->buf; + s->buffered_nals = 0; +} + +static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last) +{ + RTPMuxContext *s = s1->priv_data; + enum AVCodecID codec = s1->streams[0]->codecpar->codec_id; + + av_log(s1, AV_LOG_DEBUG, "Sending NAL %x of len %d M=%d\n", buf[0] & 0x1F, size, last); + if (size <= s->max_payload_size) { + int buffered_size = s->buf_ptr - s->buf; + int header_size; + int skip_aggregate = 0; + + if (codec == AV_CODEC_ID_H264) { + header_size = 1; + skip_aggregate = s->flags & FF_RTP_FLAG_H264_MODE0; + } else { + header_size = 2; + } + + // Flush buffered NAL units if the current unit doesn't fit + if (buffered_size + 2 + size > s->max_payload_size) { + flush_buffered(s1, 0); + buffered_size = 0; + } + // If we aren't using mode 0, and the NAL unit fits including the + // framing (2 bytes length, plus 1/2 bytes for the STAP-A/AP marker), + // write the unit to the buffer as a STAP-A/AP packet, otherwise flush + // and send as single NAL. + if (buffered_size + 2 + header_size + size <= s->max_payload_size && + !skip_aggregate) { + if (buffered_size == 0) { + if (codec == AV_CODEC_ID_H264) { + *s->buf_ptr++ = 24; + } else { + *s->buf_ptr++ = 48 << 1; + *s->buf_ptr++ = 1; + } + } + AV_WB16(s->buf_ptr, size); + s->buf_ptr += 2; + memcpy(s->buf_ptr, buf, size); + s->buf_ptr += size; + s->buffered_nals++; + } else { + flush_buffered(s1, 0); + ff_rtp_send_data(s1, buf, size, last); + } + } else { + int flag_byte, header_size; + flush_buffered(s1, 0); + if (codec == AV_CODEC_ID_H264 && (s->flags & FF_RTP_FLAG_H264_MODE0)) { + av_log(s1, AV_LOG_ERROR, + "NAL size %d > %d, try -slice-max-size %d\n", size, + s->max_payload_size, s->max_payload_size); + return; + } + av_log(s1, AV_LOG_DEBUG, "NAL size %d > %d\n", size, s->max_payload_size); + if (codec == AV_CODEC_ID_H264) { + uint8_t type = buf[0] & 0x1F; + uint8_t nri = buf[0] & 0x60; + + s->buf[0] = 28; /* FU Indicator; Type = 28 ---> FU-A */ + s->buf[0] |= nri; + s->buf[1] = type; + s->buf[1] |= 1 << 7; + buf += 1; + size -= 1; + + flag_byte = 1; + header_size = 2; + } else { + uint8_t nal_type = (buf[0] >> 1) & 0x3F; + /* + * create the HEVC payload header and transmit the buffer as fragmentation units (FU) + * + * 0 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |F| Type | LayerId | TID | + * +-------------+-----------------+ + * + * F = 0 + * Type = 49 (fragmentation unit (FU)) + * LayerId = 0 + * TID = 1 + */ + s->buf[0] = 49 << 1; + s->buf[1] = 1; + + /* + * create the FU header + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |S|E| FuType | + * +---------------+ + * + * S = variable + * E = variable + * FuType = NAL unit type + */ + s->buf[2] = nal_type; + /* set the S bit: mark as start fragment */ + s->buf[2] |= 1 << 7; + + /* pass the original NAL header */ + buf += 2; + size -= 2; + + flag_byte = 2; + header_size = 3; + } + + while (size + header_size > s->max_payload_size) { + memcpy(&s->buf[header_size], buf, s->max_payload_size - header_size); + ff_rtp_send_data(s1, s->buf, s->max_payload_size, 0); + buf += s->max_payload_size - header_size; + size -= s->max_payload_size - header_size; + s->buf[flag_byte] &= ~(1 << 7); + } + s->buf[flag_byte] |= 1 << 6; + memcpy(&s->buf[header_size], buf, size); + ff_rtp_send_data(s1, s->buf, size + header_size, last); + } +} + +void ff_rtp_send_h264_hevc(AVFormatContext *s1, const uint8_t *buf1, int size) +{ + const uint8_t *r, *end = buf1 + size; + RTPMuxContext *s = s1->priv_data; + + s->timestamp = s->cur_timestamp; + s->buf_ptr = s->buf; + if (s->nal_length_size) + r = ff_avc_mp4_find_startcode(buf1, end, s->nal_length_size) ? buf1 : end; + else + r = ff_avc_find_startcode(buf1, end); + while (r < end) { + const uint8_t *r1; + + if (s->nal_length_size) { + r1 = ff_avc_mp4_find_startcode(r, end, s->nal_length_size); + if (!r1) + r1 = end; + r += s->nal_length_size; + } else { + while (!*(r++)); + r1 = ff_avc_find_startcode(r, end); + } + nal_send(s1, r, r1 - r, r1 == end); + r = r1; + } + flush_buffered(s1, 1); +} diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c index b8c880a..9f22a09 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -40,24 +40,24 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) s->timestamp = s->cur_timestamp; /* convert video pixel dimensions from pixels to blocks */ - w = (s1->streams[0]->codec->width + 7) >> 3; - h = (s1->streams[0]->codec->height + 7) >> 3; + w = (s1->streams[0]->codecpar->width + 7) >> 3; + h = (s1->streams[0]->codecpar->height + 7) >> 3; /* get the pixel format type or fail */ - if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ422P || - (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && - s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV422P)) { + if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ422P || + (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && + s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV422P)) { type = 0; - } else if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ420P || - (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG && - s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV420P)) { + } else if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ420P || + (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && + s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV420P)) { type = 1; } else { av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); return; } - /* preparse the header for getting some infos */ + /* preparse the header for getting some info */ for (i = 0; i < size; i++) { if (buf[i] != 0xff) continue; diff --git a/libavformat/rtpenc_latm.c b/libavformat/rtpenc_latm.c index 6467677..d07dd52 100644 --- a/libavformat/rtpenc_latm.c +++ b/libavformat/rtpenc_latm.c @@ -34,7 +34,7 @@ void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size) int len = 0; /* skip ADTS header, if present */ - if ((s1->streams[0]->codec->extradata_size) == 0) { + if ((s1->streams[0]->codecpar->extradata_size) == 0) { size -= 7; buff += 7; } diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c new file mode 100644 index 0000000..d93a26a --- /dev/null +++ b/libavformat/rtpenc_mpegts.c @@ -0,0 +1,155 @@ +/* + * RTP/mpegts muxer + * Copyright (c) 2011 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/mathematics.h" +#include "avformat.h" +#include "avio_internal.h" + +struct MuxChain { + AVFormatContext *mpegts_ctx; + AVFormatContext *rtp_ctx; +}; + +static int rtp_mpegts_write_close(AVFormatContext *s) +{ + struct MuxChain *chain = s->priv_data; + + if (chain->mpegts_ctx) { + av_write_trailer(chain->mpegts_ctx); + ffio_free_dyn_buf(&chain->mpegts_ctx->pb); + avformat_free_context(chain->mpegts_ctx); + } + if (chain->rtp_ctx) { + av_write_trailer(chain->rtp_ctx); + avformat_free_context(chain->rtp_ctx); + } + return 0; +} + +static int rtp_mpegts_write_header(AVFormatContext *s) +{ + struct MuxChain *chain = s->priv_data; + AVFormatContext *mpegts_ctx = NULL, *rtp_ctx = NULL; + AVOutputFormat *mpegts_format = av_guess_format("mpegts", NULL, NULL); + AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL); + int i, ret = AVERROR(ENOMEM); + AVStream *st; + + if (!mpegts_format || !rtp_format) + return AVERROR(ENOSYS); + mpegts_ctx = avformat_alloc_context(); + if (!mpegts_ctx) + return AVERROR(ENOMEM); + mpegts_ctx->oformat = mpegts_format; + mpegts_ctx->max_delay = s->max_delay; + for (i = 0; i < s->nb_streams; i++) { + AVStream* st = avformat_new_stream(mpegts_ctx, NULL); + if (!st) + goto fail; + st->time_base = s->streams[i]->time_base; + st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); + } + if ((ret = avio_open_dyn_buf(&mpegts_ctx->pb)) < 0) + goto fail; + if ((ret = avformat_write_header(mpegts_ctx, NULL)) < 0) + goto fail; + for (i = 0; i < s->nb_streams; i++) + s->streams[i]->time_base = mpegts_ctx->streams[i]->time_base; + + chain->mpegts_ctx = mpegts_ctx; + mpegts_ctx = NULL; + + rtp_ctx = avformat_alloc_context(); + if (!rtp_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + rtp_ctx->oformat = rtp_format; + st = avformat_new_stream(rtp_ctx, NULL); + st->time_base.num = 1; + st->time_base.den = 90000; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; + rtp_ctx->pb = s->pb; + if ((ret = avformat_write_header(rtp_ctx, NULL)) < 0) + goto fail; + chain->rtp_ctx = rtp_ctx; + + return 0; + +fail: + if (mpegts_ctx) { + ffio_free_dyn_buf(&mpegts_ctx->pb); + avformat_free_context(mpegts_ctx); + } + if (rtp_ctx) + avformat_free_context(rtp_ctx); + rtp_mpegts_write_close(s); + return ret; +} + +static int rtp_mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + struct MuxChain *chain = s->priv_data; + int ret = 0, size; + uint8_t *buf; + AVPacket local_pkt; + + if (!chain->mpegts_ctx->pb) { + if ((ret = avio_open_dyn_buf(&chain->mpegts_ctx->pb)) < 0) + return ret; + } + if ((ret = av_write_frame(chain->mpegts_ctx, pkt)) < 0) + return ret; + size = avio_close_dyn_buf(chain->mpegts_ctx->pb, &buf); + chain->mpegts_ctx->pb = NULL; + if (size == 0) { + av_free(buf); + return 0; + } + av_init_packet(&local_pkt); + local_pkt.data = buf; + local_pkt.size = size; + local_pkt.stream_index = 0; + if (pkt->pts != AV_NOPTS_VALUE) + local_pkt.pts = av_rescale_q(pkt->pts, + s->streams[pkt->stream_index]->time_base, + chain->rtp_ctx->streams[0]->time_base); + if (pkt->dts != AV_NOPTS_VALUE) + local_pkt.dts = av_rescale_q(pkt->dts, + s->streams[pkt->stream_index]->time_base, + chain->rtp_ctx->streams[0]->time_base); + ret = av_write_frame(chain->rtp_ctx, &local_pkt); + av_free(buf); + + return ret; +} + +AVOutputFormat ff_rtp_mpegts_muxer = { + .name = "rtp_mpegts", + .long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts output format"), + .priv_data_size = sizeof(struct MuxChain), + .audio_codec = AV_CODEC_ID_AAC, + .video_codec = AV_CODEC_ID_MPEG4, + .write_header = rtp_mpegts_write_header, + .write_packet = rtp_mpegts_write_packet, + .write_trailer = rtp_mpegts_write_close, +}; diff --git a/libavformat/rtpenc_xiph.c b/libavformat/rtpenc_xiph.c index 07086b1..f6ab77f 100644 --- a/libavformat/rtpenc_xiph.c +++ b/libavformat/rtpenc_xiph.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" + #include "avformat.h" #include "rtpenc.h" @@ -30,10 +32,11 @@ void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size) { RTPMuxContext *s = s1->priv_data; + AVStream *st = s1->streams[0]; int max_pkt_size, xdt, frag; uint8_t *q; - max_pkt_size = s->max_payload_size; + max_pkt_size = s->max_payload_size - 6; // ident+frag+tdt/vdt+pkt_num+pkt_length // set xiph data type switch (*buff) { @@ -64,7 +67,7 @@ void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size) // 0 - whole frame (possibly multiple frames) // 1 - first fragment // 2 - fragment continuation - // 3 - last fragmement + // 3 - last fragment frag = size <= max_pkt_size ? 0 : 1; if (!frag && !xdt) { // do we have a whole frame of raw data? @@ -73,24 +76,29 @@ void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size) int remaining = end_ptr - ptr; assert(s->num_frames <= s->max_frames_per_packet); - if ((s->num_frames > 0 && remaining < 0) || - s->num_frames == s->max_frames_per_packet) { - // send previous packets now; no room for new data + if (s->num_frames > 0 && + (remaining < 0 || + s->num_frames == s->max_frames_per_packet || + av_compare_ts(s->cur_timestamp - s->timestamp, st->time_base, + s1->max_delay, AV_TIME_BASE_Q) >= 0)) { + // send previous packets now; no room for new data, or too much delay ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); s->num_frames = 0; } // buffer current frame to send later - if (0 == s->num_frames) s->timestamp = s->cur_timestamp; + if (0 == s->num_frames) + s->timestamp = s->cur_timestamp; s->num_frames++; // Set packet header. Normally, this is OR'd with frag and xdt, // but those are zero, so omitted here *q++ = s->num_frames; - if (s->num_frames > 1) q = s->buf_ptr; // jump ahead if needed - *q++ = (size >> 8) & 0xff; - *q++ = size & 0xff; + if (s->num_frames > 1) + q = s->buf_ptr; // jump ahead if needed + AV_WB16(q, size); + q += 2; memcpy(q, buff, size); q += size; s->buf_ptr = q; @@ -111,8 +119,8 @@ void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size) // set packet headers *q++ = (frag << 6) | (xdt << 4); // num_frames = 0 - *q++ = (len >> 8) & 0xff; - *q++ = len & 0xff; + AV_WB16(q, len); + q += 2; // set packet body memcpy(q, buff, len); q += len; diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 0f31539..6582e4a 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -26,6 +26,7 @@ #include "libavutil/parseutils.h" #include "libavutil/avstring.h" +#include "libavutil/opt.h" #include "avformat.h" #include "avio_internal.h" #include "rtp.h" @@ -42,14 +43,46 @@ #endif typedef struct RTPContext { + const AVClass *class; URLContext *rtp_hd, *rtcp_hd; int rtp_fd, rtcp_fd, nb_ssm_include_addrs, nb_ssm_exclude_addrs; struct sockaddr_storage **ssm_include_addrs, **ssm_exclude_addrs; int write_to_source; struct sockaddr_storage last_rtp_source, last_rtcp_source; socklen_t last_rtp_source_len, last_rtcp_source_len; + int ttl; + int buffer_size; + int rtcp_port, local_rtpport, local_rtcpport; + int connect; + int pkt_size; + char *sources; + char *block; } RTPContext; +#define OFFSET(x) offsetof(RTPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "ttl", "Time to live (in milliseconds, multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "buffer_size", "Send/Receive buffer size (in bytes)", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "rtcp_port", "Custom rtcp port", OFFSET(rtcp_port), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "local_rtpport", "Local rtp port", OFFSET(local_rtpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "local_rtcpport", "Local rtcp port", OFFSET(local_rtcpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "connect", "Connect socket", OFFSET(connect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { NULL } +}; + +static const AVClass rtp_class = { + .class_name = "rtp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /** * 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 @@ -188,21 +221,23 @@ static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const va_end(ap); } -static void build_udp_url(char *buf, int buf_size, - const char *hostname, int port, - int local_port, int ttl, - int max_packet_size, int connect, +static void build_udp_url(RTPContext *s, + char *buf, int buf_size, + const char *hostname, + int port, int local_port, const char *include_sources, const char *exclude_sources) { ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL); if (local_port >= 0) url_add_option(buf, buf_size, "localport=%d", local_port); - if (ttl >= 0) - url_add_option(buf, buf_size, "ttl=%d", ttl); - if (max_packet_size >=0) - url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size); - if (connect) + if (s->ttl >= 0) + url_add_option(buf, buf_size, "ttl=%d", s->ttl); + if (s->buffer_size >= 0) + url_add_option(buf, buf_size, "buffer_size=%d", s->buffer_size); + if (s->pkt_size >= 0) + url_add_option(buf, buf_size, "pkt_size=%d", s->pkt_size); + if (s->connect) url_add_option(buf, buf_size, "connect=1"); if (include_sources && include_sources[0]) url_add_option(buf, buf_size, "sources=%s", include_sources); @@ -231,8 +266,10 @@ static void rtp_parse_addr_list(URLContext *h, char *buf, ai = rtp_resolve_host(p, 0, SOCK_DGRAM, AF_UNSPEC, 0); if (ai) { source_addr = av_mallocz(sizeof(struct sockaddr_storage)); - if (!source_addr) + if (!source_addr) { + freeaddrinfo(ai); break; + } memcpy(source_addr, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); @@ -273,10 +310,9 @@ static void rtp_parse_addr_list(URLContext *h, char *buf, static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s = h->priv_data; - int rtp_port, rtcp_port, - ttl, connect, - local_rtp_port, local_rtcp_port, max_packet_size; + int rtp_port; char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; + char *sources = include_sources, *block = exclude_sources; char buf[1024]; char path[1024]; const char *p; @@ -284,61 +320,64 @@ static int rtp_open(URLContext *h, const char *uri, int flags) av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); /* extract parameters */ - ttl = -1; - rtcp_port = rtp_port+1; - local_rtp_port = -1; - local_rtcp_port = -1; - max_packet_size = -1; - connect = 0; + if (s->rtcp_port < 0) + s->rtcp_port = rtp_port + 1; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { - ttl = strtol(buf, NULL, 10); + s->ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { - rtcp_port = strtol(buf, NULL, 10); + s->rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { - local_rtp_port = strtol(buf, NULL, 10); + s->local_rtpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { - local_rtp_port = strtol(buf, NULL, 10); + s->local_rtpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { - local_rtcp_port = strtol(buf, NULL, 10); + s->local_rtcpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { - max_packet_size = strtol(buf, NULL, 10); + s->pkt_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { - connect = strtol(buf, NULL, 10); + s->connect = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { s->write_to_source = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { av_strlcpy(include_sources, buf, sizeof(include_sources)); + rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); + } else { + rtp_parse_addr_list(h, s->sources, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); + sources = s->sources; } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); + } else { + rtp_parse_addr_list(h, s->block, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); + block = s->block; } } - build_udp_url(buf, sizeof(buf), - hostname, rtp_port, local_rtp_port, ttl, max_packet_size, - connect, include_sources, exclude_sources); - if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) + build_udp_url(s, buf, sizeof(buf), + hostname, rtp_port, s->local_rtpport, sources, block); + if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols, h) < 0) goto fail; - if (local_rtp_port>=0 && local_rtcp_port<0) - local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1; + if (s->local_rtpport >= 0 && s->local_rtcpport < 0) + s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1; - build_udp_url(buf, sizeof(buf), - hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, - connect, include_sources, exclude_sources); - if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) + build_udp_url(s, buf, sizeof(buf), + hostname, s->rtcp_port, s->local_rtcpport, sources, block); + if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols, h) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle @@ -409,6 +448,10 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size) if (size < 2) return AVERROR(EINVAL); + if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) + av_log(h, AV_LOG_WARNING, "Data doesn't look like RTP packets, " + "make sure the RTP muxer is used\n"); + if (s->write_to_source) { int fd; struct sockaddr_storage *source, temp_source; @@ -532,7 +575,7 @@ static int rtp_get_multi_file_handle(URLContext *h, int **handles, return 0; } -URLProtocol ff_rtp_protocol = { +const URLProtocol ff_rtp_protocol = { .name = "rtp", .url_open = rtp_open, .url_read = rtp_read, @@ -542,4 +585,5 @@ URLProtocol ff_rtp_protocol = { .url_get_multi_file_handle = rtp_get_multi_file_handle, .priv_data_size = sizeof(RTPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &rtp_class, }; diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 3d040d3..84b912f 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -72,8 +72,10 @@ { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \ { "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" } -#define RTSP_REORDERING_OPTS() \ - { "reorder_queue_size", "Number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC } +#define COMMON_OPTS() \ + { "reorder_queue_size", "Number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \ + { "buffer_size", "Underlying protocol send/receive buffer size", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC|ENC } \ + const AVOption ff_rtsp_options[] = { { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, @@ -89,7 +91,7 @@ const AVOption ff_rtsp_options[] = { { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC }, { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { NULL }, }; @@ -98,16 +100,28 @@ static const AVOption sdp_options[] = { { "custom_io", "Use custom IO", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, { "rtcp_to_source", "Send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"), - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { NULL }, }; static const AVOption rtp_options[] = { RTSP_FLAG_OPTS("rtp_flags", "RTP flags"), - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { NULL }, }; + +static AVDictionary *map_to_opts(RTSPState *rt) +{ + AVDictionary *opts = NULL; + char buf[256]; + + snprintf(buf, sizeof(buf), "%d", rt->buffer_size); + av_dict_set(&opts, "buffer_size", buf, 0); + + return opts; +} + static void get_word_until_chars(char *buf, int buf_size, const char *sep, const char **pp) { @@ -155,7 +169,8 @@ static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) *end = AV_NOPTS_VALUE; get_word_sep(buf, sizeof(buf), "-", &p); - av_parse_time(start, buf, 1); + if (av_parse_time(start, buf, 1) < 0) + return; if (*p == '-') { p++; get_word_sep(buf, sizeof(buf), "-", &p); @@ -163,12 +178,19 @@ static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) } } -static int get_sockaddr(const char *buf, struct sockaddr_storage *sock) +static int get_sockaddr(AVFormatContext *s, + const char *buf, struct sockaddr_storage *sock) { struct addrinfo hints = { 0 }, *ai = NULL; + int ret; + hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(buf, NULL, &hints, &ai)) + if ((ret = getaddrinfo(buf, NULL, &hints, &ai))) { + av_log(s, AV_LOG_ERROR, "getaddrinfo(%s): %s\n", + buf, + gai_strerror(ret)); return -1; + } memcpy(sock, ai->ai_addr, FFMIN(sizeof(*sock), ai->ai_addrlen)); freeaddrinfo(ai); return 0; @@ -176,29 +198,51 @@ static int get_sockaddr(const char *buf, struct sockaddr_storage *sock) #if CONFIG_RTPDEC static void init_rtp_handler(RTPDynamicProtocolHandler *handler, - RTSPStream *rtsp_st, AVCodecContext *codec) + RTSPStream *rtsp_st, AVStream *st) { + AVCodecParameters *par = st ? st->codecpar : NULL; if (!handler) return; - if (codec) - codec->codec_id = handler->codec_id; + if (par) + par->codec_id = handler->codec_id; rtsp_st->dynamic_handler = handler; - if (handler->alloc) { - rtsp_st->dynamic_protocol_context = handler->alloc(); + if (st) + st->need_parsing = handler->need_parsing; + if (handler->priv_data_size) { + rtsp_st->dynamic_protocol_context = av_mallocz(handler->priv_data_size); if (!rtsp_st->dynamic_protocol_context) rtsp_st->dynamic_handler = NULL; } } +static void finalize_rtp_handler_init(AVFormatContext *s, RTSPStream *rtsp_st, + AVStream *st) +{ + if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->init) { + int ret = rtsp_st->dynamic_handler->init(s, st ? st->index : -1, + rtsp_st->dynamic_protocol_context); + if (ret < 0) { + if (rtsp_st->dynamic_protocol_context) { + if (rtsp_st->dynamic_handler->close) + rtsp_st->dynamic_handler->close( + rtsp_st->dynamic_protocol_context); + av_free(rtsp_st->dynamic_protocol_context); + } + rtsp_st->dynamic_protocol_context = NULL; + rtsp_st->dynamic_handler = NULL; + } + } +} + /* parse the rtpmap description: /[/] */ static int sdp_parse_rtpmap(AVFormatContext *s, AVStream *st, RTSPStream *rtsp_st, int payload_type, const char *p) { - AVCodecContext *codec = st->codec; + AVCodecParameters *par = st->codecpar; char buf[256]; int i; - AVCodec *c; + const AVCodecDescriptor *desc; const char *c_name; /* See if we can handle this kind of payload. @@ -209,46 +253,46 @@ static int sdp_parse_rtpmap(AVFormatContext *s, if (payload_type < RTP_PT_PRIVATE) { /* We are in a standard case * (from http://www.iana.org/assignments/rtp-parameters). */ - codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type); + par->codec_id = ff_rtp_codec_id(buf, par->codec_type); } - if (codec->codec_id == AV_CODEC_ID_NONE) { + if (par->codec_id == AV_CODEC_ID_NONE) { RTPDynamicProtocolHandler *handler = - ff_rtp_handler_find_by_name(buf, codec->codec_type); - init_rtp_handler(handler, rtsp_st, codec); + ff_rtp_handler_find_by_name(buf, par->codec_type); + init_rtp_handler(handler, rtsp_st, st); /* If no dynamic handler was found, check with the list of standard * allocated types, if such a stream for some reason happens to * use a private payload type. This isn't handled in rtpdec.c, since * the format name from the rtpmap line never is passed into rtpdec. */ if (!rtsp_st->dynamic_handler) - codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type); + par->codec_id = ff_rtp_codec_id(buf, par->codec_type); } - c = avcodec_find_decoder(codec->codec_id); - if (c && c->name) - c_name = c->name; + desc = avcodec_descriptor_get(par->codec_id); + if (desc && desc->name) + c_name = desc->name; else c_name = "(null)"; get_word_sep(buf, sizeof(buf), "/", &p); i = atoi(buf); - switch (codec->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: av_log(s, 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; + par->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE; + par->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS; if (i > 0) { - codec->sample_rate = i; - avpriv_set_pts_info(st, 32, 1, codec->sample_rate); + par->sample_rate = i; + avpriv_set_pts_info(st, 32, 1, par->sample_rate); get_word_sep(buf, sizeof(buf), "/", &p); i = atoi(buf); if (i > 0) - codec->channels = i; + par->channels = i; } av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n", - codec->sample_rate); + par->sample_rate); av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n", - codec->channels); + par->channels); break; case AVMEDIA_TYPE_VIDEO: av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name); @@ -258,9 +302,7 @@ static int sdp_parse_rtpmap(AVFormatContext *s, default: break; } - if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->init) - rtsp_st->dynamic_handler->init(s, st->index, - rtsp_st->dynamic_protocol_context); + finalize_rtp_handler_init(s, rtsp_st, st); return 0; } @@ -323,7 +365,7 @@ static void parse_fmtp(AVFormatContext *s, RTSPState *rt, rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, - rtsp_st->dynamic_protocol_context, line); + rtsp_st->dynamic_protocol_context, line); } } } @@ -342,7 +384,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, struct sockaddr_storage sdp_ip; int ttl; - av_dlog(s, "sdp: %c='%s'\n", letter, buf); + av_log(s, AV_LOG_TRACE, "sdp: %c='%s'\n", letter, buf); p = buf; if (s1->skip_media && letter != 'm') @@ -356,7 +398,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6")) return; get_word_sep(buf1, sizeof(buf1), "/", &p); - if (get_sockaddr(buf1, &sdp_ip)) + if (get_sockaddr(s, buf1, &sdp_ip)) return; ttl = 16; if (*p == '/') { @@ -393,7 +435,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, codec_type = AVMEDIA_TYPE_AUDIO; } else if (!strcmp(st_type, "video")) { codec_type = AVMEDIA_TYPE_VIDEO; - } else if (!strcmp(st_type, "application")) { + } else if (!strcmp(st_type, "application") || !strcmp(st_type, "text")) { codec_type = AVMEDIA_TYPE_DATA; } if (codec_type == AVMEDIA_TYPE_UNKNOWN || !(rt->media_type_mask & (1 << codec_type))) { @@ -434,15 +476,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { /* no corresponding stream */ if (rt->transport == RTSP_TRANSPORT_RAW) { - if (!rt->ts && CONFIG_RTPDEC) + if (CONFIG_RTPDEC && !rt->ts) rt->ts = ff_mpegts_parse_open(s); } else { RTPDynamicProtocolHandler *handler; handler = ff_rtp_handler_find_by_id( rtsp_st->sdp_payload_type, AVMEDIA_TYPE_DATA); init_rtp_handler(handler, rtsp_st, NULL); - if (handler && handler->init) - handler->init(s, -1, rtsp_st->dynamic_protocol_context); + finalize_rtp_handler_init(s, rtsp_st, NULL); } } else if (rt->server_type == RTSP_SERVER_WMS && codec_type == AVMEDIA_TYPE_DATA) { @@ -454,22 +495,22 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, return; st->id = rt->nb_rtsp_streams - 1; rtsp_st->stream_index = st->index; - st->codec->codec_type = codec_type; + st->codecpar->codec_type = codec_type; if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) { RTPDynamicProtocolHandler *handler; /* if standard payload type, we can find the codec right now */ - ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type); - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - st->codec->sample_rate > 0) - avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); + ff_rtp_get_codec_info(st->codecpar, rtsp_st->sdp_payload_type); + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->sample_rate > 0) + avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); /* Even static payload types may need a custom depacketizer */ handler = ff_rtp_handler_find_by_id( - rtsp_st->sdp_payload_type, st->codec->codec_type); - init_rtp_handler(handler, rtsp_st, st->codec); - if (handler && handler->init) - handler->init(s, st->index, - rtsp_st->dynamic_protocol_context); + rtsp_st->sdp_payload_type, st->codecpar->codec_type); + init_rtp_handler(handler, rtsp_st, st); + finalize_rtp_handler_init(s, rtsp_st, st); } + if (rt->default_lang[0]) + av_dict_set(&st->metadata, "language", rt->default_lang, 0); } /* put a default control url */ av_strlcpy(rtsp_st->control_url, rt->control_uri, @@ -524,6 +565,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, s1->seen_fmtp = 1; av_strlcpy(s1->delayed_fmtp, buf, sizeof(s1->delayed_fmtp)); } + } else if (av_strstart(p, "ssrc:", &p) && s->nb_streams > 0) { + rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + get_word(buf1, sizeof(buf1), &p); + rtsp_st->ssrc = strtoll(buf1, NULL, 10); } else if (av_strstart(p, "range:", &p)) { int64_t start, end; @@ -533,13 +578,23 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, /* AV_NOPTS_VALUE means live broadcast (and can't seek) */ s->duration = (end == AV_NOPTS_VALUE) ? AV_NOPTS_VALUE : end - start; + } else if (av_strstart(p, "lang:", &p)) { + if (s->nb_streams > 0) { + get_word(buf1, sizeof(buf1), &p); + rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + if (rtsp_st->stream_index >= 0) { + st = s->streams[rtsp_st->stream_index]; + av_dict_set(&st->metadata, "language", buf1, 0); + } + } else + get_word(rt->default_lang, sizeof(rt->default_lang), &p); } else if (av_strstart(p, "IsRealDataType:integer;",&p)) { if (atoi(p) == 1) rt->transport = RTSP_TRANSPORT_RDT; } else if (av_strstart(p, "SampleRate:integer;", &p) && s->nb_streams > 0) { st = s->streams[s->nb_streams - 1]; - st->codec->sample_rate = atoi(p); + st->codecpar->sample_rate = atoi(p); } else if (av_strstart(p, "crypto:", &p) && s->nb_streams > 0) { // RFC 4568 rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; @@ -674,18 +729,16 @@ void ff_rtsp_undo_setup(AVFormatContext *s, int send_packets) AVFormatContext *rtpctx = rtsp_st->transport_priv; av_write_trailer(rtpctx); if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { - uint8_t *ptr; if (CONFIG_RTSP_MUXER && rtpctx->pb && send_packets) ff_rtsp_tcp_write_packet(s, rtsp_st); - avio_close_dyn_buf(rtpctx->pb, &ptr); - av_free(ptr); + ffio_free_dyn_buf(&rtpctx->pb); } else { avio_close(rtpctx->pb); } avformat_free_context(rtpctx); - } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) + } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT) ff_rdt_parse_close(rtsp_st->transport_priv); - else if (rt->transport == RTSP_TRANSPORT_RTP && CONFIG_RTPDEC) + else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RTP) ff_rtp_parse_close(rtsp_st->transport_priv); } rtsp_st->transport_priv = NULL; @@ -706,9 +759,12 @@ void ff_rtsp_close_streams(AVFormatContext *s) for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st) { - if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) - rtsp_st->dynamic_handler->free( - rtsp_st->dynamic_protocol_context); + if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) { + if (rtsp_st->dynamic_handler->close) + rtsp_st->dynamic_handler->close( + rtsp_st->dynamic_protocol_context); + av_free(rtsp_st->dynamic_protocol_context); + } for (j = 0; j < rtsp_st->nb_include_source_addrs; j++) av_free(rtsp_st->include_source_addrs[j]); av_freep(&rtsp_st->include_source_addrs); @@ -723,8 +779,9 @@ void ff_rtsp_close_streams(AVFormatContext *s) if (rt->asf_ctx) { avformat_close_input(&rt->asf_ctx); } - if (rt->ts && CONFIG_RTPDEC) + if (CONFIG_RTPDEC && rt->ts) ff_mpegts_parse_close(rt->ts); + av_freep(&rt->protocols); av_free(rt->p); av_free(rt->recvbuf); } @@ -747,7 +804,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) if (!st) s->ctx_flags |= AVFMTCTX_NOHEADER; - if (s->oformat && CONFIG_RTSP_MUXER) { + if (CONFIG_RTSP_MUXER && s->oformat) { int ret = ff_rtp_chain_mux_open((AVFormatContext **)&rtsp_st->transport_priv, s, st, rtsp_st->rtp_handle, RTSP_TCP_MAX_PACKET_SIZE, @@ -759,7 +816,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) st->time_base = ((AVFormatContext*)rtsp_st->transport_priv)->streams[0]->time_base; } else if (rt->transport == RTSP_TRANSPORT_RAW) { return 0; // Don't need to open any parser here - } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) + } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT) rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, rtsp_st->dynamic_protocol_context, rtsp_st->dynamic_handler); @@ -770,7 +827,10 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) if (!rtsp_st->transport_priv) { return AVERROR(ENOMEM); - } else if (rt->transport == RTSP_TRANSPORT_RTP && CONFIG_RTPDEC) { + } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RTP && + s->iformat) { + RTPDemuxContext *rtpctx = rtsp_st->transport_priv; + rtpctx->ssrc = rtsp_st->ssrc; if (rtsp_st->dynamic_handler) { ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, rtsp_st->dynamic_protocol_context, @@ -808,7 +868,8 @@ static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp) } /* XXX: only one transport specification is parsed */ -static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p) +static void rtsp_parse_transport(AVFormatContext *s, + RTSPMessageHeader *reply, const char *p) { char transport_protocol[16]; char profile[16]; @@ -900,7 +961,7 @@ static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p) if (*p == '=') { p++; get_word_sep(buf, sizeof(buf), ";,", &p); - get_sockaddr(buf, &th->destination); + get_sockaddr(s, buf, &th->destination); } } else if (!strcmp(parameter, "source")) { if (*p == '=') { @@ -987,7 +1048,8 @@ static void rtsp_parse_rtp_info(RTSPState *rt, const char *p) handle_rtp_info(rt, url, seq, rtptime); } -void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, +void ff_rtsp_parse_line(AVFormatContext *s, + RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method) { const char *p; @@ -1004,7 +1066,7 @@ void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, } else if (av_stristart(p, "Content-Length:", &p)) { reply->content_length = strtol(p, NULL, 10); } else if (av_stristart(p, "Transport:", &p)) { - rtsp_parse_transport(reply, p); + rtsp_parse_transport(s, reply, p); } else if (av_stristart(p, "CSeq:", &p)) { reply->seq = strtol(p, NULL, 10); } else if (av_stristart(p, "Range:", &p)) { @@ -1060,7 +1122,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) return; len = AV_RB16(buf + 1); - av_dlog(s, "skipping RTP packet len=%d\n", len); + av_log(s, AV_LOG_TRACE, "skipping RTP packet len=%d\n", len); /* skip payload */ while (len > 0) { @@ -1097,13 +1159,12 @@ start: q = buf; for (;;) { ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); - av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); + av_log(s, AV_LOG_TRACE, "ret=%d c=%02x [%c]\n", ret, ch, ch); if (ret != 1) return AVERROR_EOF; if (ch == '\n') break; - if (ch == '$') { - /* XXX: only parse it if first char on line ? */ + if (ch == '$' && q == buf) { if (return_on_interleaved_data) { return 1; } else @@ -1115,7 +1176,7 @@ start: } *q = '\0'; - av_dlog(s, "line='%s'\n", buf); + av_log(s, AV_LOG_TRACE, "line='%s'\n", buf); /* test if last line */ if (buf[0] == '\0') @@ -1134,7 +1195,7 @@ start: request = 1; } } else { - ff_rtsp_parse_line(reply, p, rt, method); + ff_rtsp_parse_line(s, reply, p, rt, method); av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply)); } @@ -1181,7 +1242,7 @@ start: } ffurl_write(rt->rtsp_hd_out, ptr, strlen(ptr)); - rt->last_cmd_time = av_gettime(); + rt->last_cmd_time = av_gettime_relative(); /* Even if the request from the server had data, it is not the data * that the caller wants or expects. The memory could also be leaked * if the actual following reply has content data. */ @@ -1267,7 +1328,7 @@ static int rtsp_send_cmd_with_content_async(AVFormatContext *s, out_buf = base64buf; } - av_dlog(s, "Sending:\n%s--\n", buf); + av_log(s, AV_LOG_TRACE, "Sending:\n%s--\n", buf); ffurl_write(rt->rtsp_hd_out, out_buf, strlen(out_buf)); if (send_content_length > 0 && send_content) { @@ -1278,7 +1339,7 @@ static int rtsp_send_cmd_with_content_async(AVFormatContext *s, } ffurl_write(rt->rtsp_hd_out, send_content, send_content_length); } - rt->last_cmd_time = av_gettime(); + rt->last_cmd_time = av_gettime_relative(); return 0; } @@ -1405,12 +1466,18 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, /* first try in specified port range */ while (j <= rt->rtp_port_max) { + AVDictionary *opts = map_to_opts(rt); + ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1, "?localport=%d", j); /* we will use two ports per rtp stream (rtp and rtcp) */ j += 2; - if (!ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL)) + err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, &opts, rt->protocols, NULL); + + av_dict_free(&opts); + + if (!err) goto rtp_opened; } @@ -1439,7 +1506,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, * will return an error. Therefore, we skip those streams. */ if (rt->server_type == RTSP_SERVER_WMS && (rtsp_st->stream_index < 0 || - s->streams[rtsp_st->stream_index]->codec->codec_type == + s->streams[rtsp_st->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_DATA)) continue; snprintf(transport, sizeof(transport) - 1, @@ -1466,7 +1533,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, transport); if (rt->accept_dynamic_rate) av_strlcat(cmd, "x-Dynamic-Rate: 0\r\n", sizeof(cmd)); - if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) { + if (CONFIG_RTPDEC && i == 0 && rt->server_type == RTSP_SERVER_REAL) { char real_res[41], real_csum[9]; ff_rdt_calc_response_and_checksum(real_res, real_csum, real_challenge); @@ -1527,13 +1594,6 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, err = AVERROR_INVALIDDATA; goto fail; } - /* Try to initialize the connection state in a - * potential NAT router by sending dummy packets. - * RTP/RTCP dummy packets are used for RDT, too. - */ - if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat && - CONFIG_RTPDEC) - ff_rtp_send_punch_packets(rtsp_st->rtp_handle); break; } case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { @@ -1557,7 +1617,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "%s", optbuf); if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + &s->interrupt_callback, NULL, rt->protocols, NULL) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1593,10 +1653,13 @@ void ff_rtsp_close_connections(AVFormatContext *s) int ff_rtsp_connect(AVFormatContext *s) { RTSPState *rt = s->priv_data; - char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128]; + char proto[128], host[1024], path[1024]; + char tcpname[1024], cmd[2048], auth[128]; + const char *lower_rtsp_proto = "tcp"; int port, err, tcp_fd; RTSPMessageHeader reply1 = {0}, *reply = &reply1; int lower_transport_mask = 0; + int default_port = RTSP_DEFAULT_PORT; char real_challenge[64] = ""; struct sockaddr_storage peer; socklen_t peer_len = sizeof(peer); @@ -1611,6 +1674,13 @@ int ff_rtsp_connect(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0; @@ -1623,15 +1693,23 @@ int ff_rtsp_connect(AVFormatContext *s) rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1; redirect: - lower_transport_mask = rt->lower_transport_mask; /* extract hostname and port */ - av_url_split(NULL, 0, auth, sizeof(auth), + av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->filename); + + if (!strcmp(proto, "rtsps")) { + lower_rtsp_proto = "tls"; + default_port = RTSPS_DEFAULT_PORT; + rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP; + } + if (*auth) { av_strlcpy(rt->auth, auth, sizeof(rt->auth)); } if (port < 0) - port = RTSP_DEFAULT_PORT; + port = default_port; + + lower_transport_mask = rt->lower_transport_mask; if (!lower_transport_mask) lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1; @@ -1651,7 +1729,7 @@ redirect: /* Construct the URI used in request; this is similar to s->filename, * but with authentication credentials removed and RTSP specific options * stripped out. */ - ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL, + ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, port, "%s", path); if (rt->control_transport == RTSP_MODE_TUNNEL) { @@ -1666,7 +1744,7 @@ redirect: /* GET requests */ if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, rt->protocols) < 0) { err = AVERROR(EIO); goto fail; } @@ -1688,7 +1766,7 @@ redirect: /* POST requests */ if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE, - &s->interrupt_callback) < 0 ) { + &s->interrupt_callback, rt->protocols) < 0 ) { err = AVERROR(EIO); goto fail; } @@ -1730,9 +1808,10 @@ redirect: } } else { /* open the tcp connection */ - ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); + ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL, + host, port, NULL); if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + &s->interrupt_callback, NULL, rt->protocols, NULL) < 0) { err = AVERROR(EIO); goto fail; } @@ -1741,6 +1820,10 @@ redirect: rt->seq = 0; tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); + if (tcp_fd < 0) { + err = tcp_fd; + goto fail; + } if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) { getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); @@ -1783,7 +1866,7 @@ redirect: break; } - if (s->iformat && CONFIG_RTSP_DEMUXER) + if (CONFIG_RTSP_DEMUXER && s->iformat) err = ff_rtsp_setup_input_streams(s, reply); else if (CONFIG_RTSP_MUXER) err = ff_rtsp_setup_output_streams(s, host); @@ -1816,6 +1899,7 @@ redirect: ff_rtsp_close_connections(s); if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) { av_strlcpy(s->filename, reply->location, sizeof(s->filename)); + rt->session_id[0] = '\0'; av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", reply->status_code, s->filename); @@ -1840,7 +1924,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for (;;) { if (ff_check_interrupt(&s->interrupt_callback)) return AVERROR_EXIT; - if (wait_end && wait_end - av_gettime() < 0) + if (wait_end && wait_end - av_gettime_relative() < 0) return AVERROR(EAGAIN); max_p = 0; if (rt->rtsp_hd) { @@ -1976,7 +2060,7 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); } else if (rt->transport == RTSP_TRANSPORT_RTP) { ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); - } else if (rt->ts && CONFIG_RTPDEC) { + } else if (CONFIG_RTPDEC && rt->ts) { ret = ff_mpegts_parse_packet(rt->ts, pkt, rt->recvbuf + rt->recvbuf_pos, rt->recvbuf_len - rt->recvbuf_pos); if (ret >= 0) { rt->recvbuf_pos += ret; @@ -2039,7 +2123,7 @@ redo: break; case RTSP_LOWER_TRANSPORT_CUSTOM: if (first_queue_st && rt->transport == RTSP_TRANSPORT_RTP && - wait_end && wait_end < av_gettime()) + wait_end && wait_end < av_gettime_relative()) len = AVERROR(EAGAIN); else len = ffio_read_partial(s->pb, rt->recvbuf, RECVBUF_SIZE); @@ -2050,6 +2134,8 @@ redo: } if (len == AVERROR(EAGAIN) && first_queue_st && rt->transport == RTSP_TRANSPORT_RTP) { + av_log(s, AV_LOG_WARNING, + "max delay reached. need to consume packet\n"); rtsp_st = first_queue_st; ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0); goto end; @@ -2105,7 +2191,7 @@ redo: return AVERROR_EOF; } } - } else if (rt->ts && CONFIG_RTPDEC) { + } else if (CONFIG_RTPDEC && rt->ts) { ret = ff_mpegts_parse_packet(rt->ts, pkt, rt->recvbuf, len); if (ret >= 0) { if (ret < len) { @@ -2173,6 +2259,13 @@ static int sdp_read_header(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = DEFAULT_REORDERING_DELAY; if (rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO) @@ -2181,6 +2274,8 @@ static int sdp_read_header(AVFormatContext *s) /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); + if (!content) + return AVERROR(ENOMEM); size = avio_read(s->pb, content, SDP_MAX_SIZE - 1); if (size <= 0) { av_free(content); @@ -2198,8 +2293,17 @@ static int sdp_read_header(AVFormatContext *s) rtsp_st = rt->rtsp_streams[i]; if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { - getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), - namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); + AVDictionary *opts = map_to_opts(rt); + + err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, + sizeof(rtsp_st->sdp_ip), + namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); + if (err) { + av_log(s, AV_LOG_ERROR, "getnameinfo: %s\n", gai_strerror(err)); + err = AVERROR(EIO); + av_dict_free(&opts); + goto fail; + } ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, rtsp_st->sdp_port, "?localport=%d&ttl=%d&connect=%d&write_to_source=%d", @@ -2213,8 +2317,12 @@ static int sdp_read_header(AVFormatContext *s) append_source_addrs(url, sizeof(url), "block", rtsp_st->nb_exclude_source_addrs, rtsp_st->exclude_source_addrs); - if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, &opts, rt->protocols, NULL); + + av_dict_free(&opts); + + if (err < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -2270,7 +2378,7 @@ static int rtp_read_header(AVFormatContext *s) int ret, port; URLContext* in = NULL; int payload_type; - AVCodecContext codec = { 0 }; + AVCodecParameters *par = NULL; struct sockaddr_storage addr; AVIOContext pb; socklen_t addrlen = sizeof(addr); @@ -2279,8 +2387,15 @@ static int rtp_read_header(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ, - &s->interrupt_callback, NULL); + &s->interrupt_callback, NULL, rt->protocols, NULL); if (ret) goto fail; @@ -2311,13 +2426,19 @@ static int rtp_read_header(AVFormatContext *s) ffurl_close(in); in = NULL; - if (ff_rtp_get_codec_info(&codec, payload_type)) { + par = avcodec_parameters_alloc(); + if (!par) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (ff_rtp_get_codec_info(par, payload_type)) { av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d " "without an SDP file describing it\n", payload_type); goto fail; } - if (codec.codec_type != AVMEDIA_TYPE_DATA) { + if (par->codec_type != AVMEDIA_TYPE_DATA) { av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received " "properly you need an SDP file " "describing it\n"); @@ -2329,10 +2450,11 @@ static int rtp_read_header(AVFormatContext *s) snprintf(sdp, sizeof(sdp), "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n", addr.ss_family == AF_INET ? 4 : 6, host, - codec.codec_type == AVMEDIA_TYPE_DATA ? "application" : - codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio", + par->codec_type == AVMEDIA_TYPE_DATA ? "application" : + par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio", port, payload_type); av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); + avcodec_parameters_free(&par); ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL); s->pb = &pb; @@ -2347,6 +2469,7 @@ static int rtp_read_header(AVFormatContext *s) return ret; fail: + avcodec_parameters_free(&par); if (in) ffurl_close(in); ff_network_close(); diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 7a910b0..ff5b532 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -70,6 +70,7 @@ enum RTSPControlTransport { }; #define RTSP_DEFAULT_PORT 554 +#define RTSPS_DEFAULT_PORT 322 #define RTSP_MAX_TRANSPORTS 8 #define RTSP_TCP_MAX_PACKET_SIZE 1472 #define RTSP_DEFAULT_NB_AUDIO_CHANNELS 1 @@ -394,6 +395,11 @@ typedef struct RTSPState { * Size of RTP packet reordering queue. */ int reordering_queue_size; + + char default_lang[4]; + int buffer_size; + + const URLProtocol **protocols; } RTSPState; #define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - @@ -451,11 +457,15 @@ typedef struct RTSPStream { /** Enable sending RTCP feedback messages according to RFC 4585 */ int feedback; + /** SSRC for this stream, to allow identifying RTCP packets before the first RTP packet */ + uint32_t ssrc; + char crypto_suite[40]; char crypto_params[100]; } RTSPStream; -void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, +void ff_rtsp_parse_line(AVFormatContext *s, + RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method); /** diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index a14ec57..03374dc 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -32,6 +32,7 @@ #include "rtpproto.h" #include "rtsp.h" #include "rdt.h" +#include "tls.h" #include "url.h" static const struct RTSPStatusMessage { @@ -113,8 +114,8 @@ static int rtsp_send_reply(AVFormatContext *s, enum RTSPStatusCode code, if (extracontent) av_strlcat(message, extracontent, sizeof(message)); av_strlcat(message, "\r\n", sizeof(message)); - av_dlog(s, "Sending response:\n%s", message); - ffurl_write(rt->rtsp_hd, message, strlen(message)); + av_log(s, AV_LOG_TRACE, "Sending response:\n%s", message); + ffurl_write(rt->rtsp_hd_out, message, strlen(message)); return 0; } @@ -149,8 +150,8 @@ static inline int rtsp_read_request(AVFormatContext *s, if (ret) return ret; if (rbuflen > 1) { - av_dlog(s, "Parsing[%d]: %s\n", rbuflen, rbuf); - ff_rtsp_parse_line(request, rbuf, rt, method); + av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf); + ff_rtsp_parse_line(s, request, rbuf, rt, method); } } while (rbuflen > 0); if (request->seq != rt->seq + 1) { @@ -287,10 +288,15 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl) request.transports[0].interleaved_max); } else { do { + AVDictionary *opts = NULL; + char buf[256]; + snprintf(buf, sizeof(buf), "%d", rt->buffer_size); + av_dict_set(&opts, "buffer_size", buf, 0); ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); - av_dlog(s, "Opening: %s", url); + av_log(s, AV_LOG_TRACE, "Opening: %s", url); ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL); + &s->interrupt_callback, &opts, rt->protocols, NULL); + av_dict_free(&opts); if (ret) localport += 2; } while (ret || localport > rt->rtp_port_max); @@ -299,7 +305,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl) return ret; } - av_dlog(s, "Listening on: %d", + av_log(s, AV_LOG_TRACE, "Listening on: %d", ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle)); if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); @@ -360,6 +366,10 @@ static inline int parse_command_line(AVFormatContext *s, const char *line, RTSPState *rt = s->priv_data; const char *linept, *searchlinept; linept = strchr(line, ' '); + + if (!linept) + return AVERROR_INVALIDDATA; + if (linept - line > methodsize - 1) { av_log(s, AV_LOG_ERROR, "Method string too long\n"); return AVERROR(EIO); @@ -500,6 +510,18 @@ static int rtsp_read_play(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); rt->nb_byes = 0; + if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP) { + for (i = 0; i < rt->nb_rtsp_streams; i++) { + RTSPStream *rtsp_st = rt->rtsp_streams[i]; + /* Try to initialize the connection state in a + * potential NAT router by sending dummy packets. + * RTP/RTCP dummy packets are used for RDT, too. + */ + if (rtsp_st->rtp_handle && + !(rt->server_type == RTSP_SERVER_WMS && i > 1)) + ff_rtp_send_punch_packets(rtsp_st->rtp_handle); + } + } if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { if (rt->transport == RTSP_TRANSPORT_RTP) { for (i = 0; i < rt->nb_rtsp_streams; i++) { @@ -605,33 +627,47 @@ int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply) static int rtsp_listen(AVFormatContext *s) { RTSPState *rt = s->priv_data; - char host[128], path[512], auth[128]; + char proto[128], host[128], path[512], auth[128]; char uri[500]; int port; + int default_port = RTSP_DEFAULT_PORT; char tcpname[500]; + const char *lower_proto = "tcp"; unsigned char rbuf[4096]; unsigned char method[10]; int rbuflen = 0; int ret; enum RTSPMethod methodcode; + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + /* extract hostname and port */ - av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port, - path, sizeof(path), s->filename); + av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), + &port, path, sizeof(path), s->filename); /* ff_url_join. No authorization by now (NULL) */ - ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL, host, + ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, port, "%s", path); + if (!strcmp(proto, "rtsps")) { + lower_proto = "tls"; + default_port = RTSPS_DEFAULT_PORT; + } + if (port < 0) - port = RTSP_DEFAULT_PORT; + port = default_port; /* Create TCP connection */ - ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, + ff_url_join(tcpname, sizeof(tcpname), lower_proto, NULL, host, port, "?listen&listen_timeout=%d", rt->initial_timeout * 1000); if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL)) { + &s->interrupt_callback, NULL, rt->protocols, NULL)) { av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n"); return ret; } @@ -669,7 +705,11 @@ static int rtsp_listen(AVFormatContext *s) static int rtsp_probe(AVProbeData *p) { - if (av_strstart(p->filename, "rtsp:", NULL)) + if ( +#if CONFIG_TLS_PROTOCOL + av_strstart(p->filename, "rtsps:", NULL) || +#endif + av_strstart(p->filename, "rtsp:", NULL)) return AVPROBE_SCORE_MAX; return 0; } @@ -718,7 +758,7 @@ int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, int id, len, i, ret; RTSPStream *rtsp_st; - av_dlog(s, "tcp_read_packet:\n"); + av_log(s, AV_LOG_TRACE, "tcp_read_packet:\n"); redo: for (;;) { RTSPMessageHeader reply; @@ -737,7 +777,7 @@ redo: return -1; id = buf[0]; len = AV_RB16(buf + 1); - av_dlog(s, "id=%d len=%d\n", id, len); + av_log(s, AV_LOG_TRACE, "id=%d len=%d\n", id, len); if (len > buf_size || len < 12) goto redo; /* get the data */ @@ -870,7 +910,7 @@ retry: if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) { /* send dummy request to keep TCP connection alive */ - if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 || + if ((av_gettime_relative() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 || rt->auth_state.stale) { if (rt->server_type == RTSP_SERVER_WMS || (rt->server_type != RTSP_SERVER_REAL && diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index 0280cea..ce0ceaa 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -39,6 +39,8 @@ struct SAPState { uint16_t hash; char *sdp; int eof; + + const URLProtocol **protocols; }; static int sap_probe(AVProbeData *p) @@ -55,6 +57,7 @@ static int sap_read_close(AVFormatContext *s) avformat_close_input(&sap->sdp_ctx); if (sap->ann_fd) ffurl_close(sap->ann_fd); + av_freep(&sap->protocols); av_freep(&sap->sdp); ff_network_close(); return 0; @@ -82,10 +85,17 @@ static int sap_read_header(AVFormatContext *s) av_strlcpy(host, "224.2.127.254", sizeof(host)); } + sap->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!sap->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d", port); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, - &s->interrupt_callback, NULL); + &s->interrupt_callback, NULL, sap->protocols, NULL); if (ret) goto fail; @@ -170,7 +180,7 @@ static int sap_read_header(AVFormatContext *s) goto fail; } st->id = i; - avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, sap->sdp_ctx->streams[i]->codecpar); st->time_base = sap->sdp_ctx->streams[i]->time_base; } @@ -215,11 +225,11 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt) int i = s->nb_streams; AVStream *st = avformat_new_stream(s, NULL); if (!st) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } st->id = i; - avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, sap->sdp_ctx->streams[i]->codecpar); st->time_base = sap->sdp_ctx->streams[i]->time_base; } } diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 246b7cf..ed3a024 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -37,6 +37,8 @@ struct SAPState { int ann_size; URLContext *ann_fd; int64_t last_time; + + const URLProtocol **protocols; }; static int sap_write_close(AVFormatContext *s) @@ -59,6 +61,8 @@ static int sap_write_close(AVFormatContext *s) ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); } + av_freep(&sap->protocols); + av_freep(&sap->ann); if (sap->ann_fd) ffurl_close(sap->ann_fd); @@ -134,6 +138,13 @@ static int sap_write_header(AVFormatContext *s) freeaddrinfo(ai); } + sap->protocols = ffurl_get_protocols(s->protocol_whitelist, + s->protocol_blacklist); + if (!sap->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams); if (!contexts) { ret = AVERROR(ENOMEM); @@ -148,7 +159,8 @@ static int sap_write_header(AVFormatContext *s) "?ttl=%d", ttl); if (!same_port) base_port += 2; - ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); + ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, + sap->protocols, NULL); if (ret) { ret = AVERROR(EIO); goto fail; @@ -167,7 +179,7 @@ static int sap_write_header(AVFormatContext *s) ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL); + &s->interrupt_callback, NULL, sap->protocols, NULL); if (ret) { ret = AVERROR(EIO); goto fail; @@ -245,7 +257,7 @@ static int sap_write_packet(AVFormatContext *s, AVPacket *pkt) { AVFormatContext *rtpctx; struct SAPState *sap = s->priv_data; - int64_t now = av_gettime(); + int64_t now = av_gettime_relative(); if (!sap->last_time || now - sap->last_time > 5000000) { int ret = ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); diff --git a/libavformat/sauce.c b/libavformat/sauce.c index a125241..335c989 100644 --- a/libavformat/sauce.c +++ b/libavformat/sauce.c @@ -65,18 +65,18 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g if (got_width && datatype && filetype) { if ((datatype == 1 && filetype <=2) || (datatype == 5 && filetype == 255) || datatype == 6) { if (t1) { - avctx->streams[0]->codec->width = t1<<3; + avctx->streams[0]->codecpar->width = t1<<3; *got_width = 1; } if (get_height && t2) - avctx->streams[0]->codec->height = t2<<4; + avctx->streams[0]->codecpar->height = t2<<4; } else if (datatype == 5) { if (filetype > 1) { - avctx->streams[0]->codec->width = (filetype == 1 ? t1 : filetype) << 4; + avctx->streams[0]->codecpar->width = (filetype == 1 ? t1 : filetype) << 4; *got_width = 1; } if (get_height && t2) - avctx->streams[0]->codec->height = t2<<4; + avctx->streams[0]->codecpar->height = t2<<4; } } diff --git a/libavformat/sctp.c b/libavformat/sctp.c index 66b31cc..b321139 100644 --- a/libavformat/sctp.c +++ b/libavformat/sctp.c @@ -48,6 +48,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" +#include "libavutil/opt.h" #include "avformat.h" #include "internal.h" #include "network.h" @@ -115,7 +116,7 @@ static int ff_sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from, static int ff_sctp_send(int s, const void *msg, size_t len, const struct sctp_sndrcvinfo *sinfo, int flags) { - struct msghdr outmsg; + struct msghdr outmsg = { 0 }; struct iovec iov; outmsg.msg_name = NULL; @@ -143,16 +144,37 @@ static int ff_sctp_send(int s, const void *msg, size_t len, memcpy(CMSG_DATA(cmsg), sinfo, sizeof(struct sctp_sndrcvinfo)); } - return sendmsg(s, &outmsg, flags); + return sendmsg(s, &outmsg, flags | MSG_NOSIGNAL); } typedef struct SCTPContext { + const AVClass *class; int fd; + int listen; + int timeout; + int listen_timeout; int max_streams; struct sockaddr_storage dest_addr; - socklen_t dest_addr_len; } SCTPContext; +#define OFFSET(x) offsetof(SCTPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "listen", "Listen for incoming connections", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "timeout", "Connection timeout (in milliseconds)", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = 10000 }, INT_MIN, INT_MAX, .flags = D|E }, + { "listen_timeout", "Bind timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, .flags = D|E }, + { "max_streams", "Max stream to allocate", OFFSET(max_streams), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT16_MAX, .flags = D|E }, + { NULL } +}; + +static const AVClass sctp_class = { + .class_name = "sctp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + static int sctp_open(URLContext *h, const char *uri, int flags) { struct addrinfo *ai, *cur_ai; @@ -164,7 +186,7 @@ static int sctp_open(URLContext *h, const char *uri, int flags) SCTPContext *s = h->priv_data; const char *p; char buf[256]; - int ret, listen_socket = 0; + int ret; char hostname[1024], proto[1024], path[1024]; char portstr[10]; @@ -177,11 +199,10 @@ static int sctp_open(URLContext *h, const char *uri, int flags) return AVERROR(EINVAL); } - s->max_streams = 0; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) - listen_socket = 1; + s->listen = 1; if (av_find_info_tag(buf, sizeof(buf), "max_streams", p)) s->max_streams = strtol(buf, NULL, 10); } @@ -198,23 +219,29 @@ static int sctp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; +restart: fd = ff_socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP); - if (fd < 0) + if (fd < 0) { + ret = ff_neterrno(); goto fail; + } - s->dest_addr_len = sizeof(s->dest_addr); - - if (listen_socket) { - int fd1; - ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); - listen(fd, 100); - fd1 = accept(fd, NULL, NULL); - closesocket(fd); - fd = fd1; - } else - ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); - - ff_socket_nonblock(fd, 1); + if (s->listen) { + if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->listen_timeout, h)) < 0) { + ret = fd; + goto fail1; + } + } else { + if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->timeout, h, !!cur_ai->ai_next)) < 0) { + + if (ret == AVERROR_EXIT) + goto fail1; + else + goto fail; + } + } event.sctp_data_io_event = 1; /* TODO: Subscribe to more event types and handle them */ @@ -223,17 +250,20 @@ static int sctp_open(URLContext *h, const char *uri, int flags) sizeof(event)) != 0) { av_log(h, AV_LOG_ERROR, "SCTP ERROR: Unable to subscribe to events\n"); - goto fail; + goto fail1; } if (s->max_streams) { initparams.sinit_max_instreams = s->max_streams; initparams.sinit_num_ostreams = s->max_streams; if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initparams, - sizeof(initparams)) < 0) + sizeof(initparams)) < 0) { av_log(h, AV_LOG_ERROR, "SCTP ERROR: Unable to initialize socket max streams %d\n", s->max_streams); + ret = ff_neterrno(); + goto fail1; + } } h->priv_data = s; @@ -243,6 +273,15 @@ static int sctp_open(URLContext *h, const char *uri, int flags) return 0; fail: + if (cur_ai->ai_next) { + /* Retry with the next sockaddr */ + cur_ai = cur_ai->ai_next; + if (fd >= 0) + closesocket(fd); + ret = 0; + goto restart; + } +fail1: ret = AVERROR(EIO); freeaddrinfo(ai); return ret; @@ -297,10 +336,10 @@ static int sctp_write(URLContext *h, const uint8_t *buf, int size) struct sctp_sndrcvinfo info = { 0 }; info.sinfo_stream = AV_RB16(buf); if (info.sinfo_stream > s->max_streams) - abort(); + return AVERROR_BUG; ret = ff_sctp_send(s->fd, buf + 2, size - 2, &info, MSG_EOR); } else - ret = send(s->fd, buf, size, 0); + ret = send(s->fd, buf, size, MSG_NOSIGNAL); return ret < 0 ? ff_neterrno() : ret; } @@ -318,7 +357,7 @@ static int sctp_get_file_handle(URLContext *h) return s->fd; } -URLProtocol ff_sctp_protocol = { +const URLProtocol ff_sctp_protocol = { .name = "sctp", .url_open = sctp_open, .url_read = sctp_read, @@ -327,4 +366,5 @@ URLProtocol ff_sctp_protocol = { .url_get_file_handle = sctp_get_file_handle, .priv_data_size = sizeof(SCTPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &sctp_class, }; diff --git a/libavformat/sdp.c b/libavformat/sdp.c index a690219..be6c95d 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -29,6 +29,7 @@ #include "avformat.h" #include "internal.h" #include "avc.h" +#include "hevc.h" #include "rtp.h" #if CONFIG_NETWORK #include "network.h" @@ -150,60 +151,45 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url) } #define MAX_PSET_SIZE 1024 -static char *extradata2psets(AVCodecContext *c) +static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) { char *psets, *p; const uint8_t *r; static const char pset_string[] = "; sprop-parameter-sets="; static const char profile_string[] = "; profile-level-id="; - uint8_t *orig_extradata = NULL; - int orig_extradata_size = 0; + uint8_t *extradata = par->extradata; + int extradata_size = par->extradata_size; + uint8_t *tmpbuf = NULL; const uint8_t *sps = NULL, *sps_end; - if (c->extradata_size > MAX_EXTRADATA_SIZE) { - av_log(c, AV_LOG_ERROR, "Too much extradata!\n"); + if (par->extradata_size > MAX_EXTRADATA_SIZE) { + av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); return NULL; } - if (c->extradata[0] == 1) { - uint8_t *dummy_p; - int dummy_int; - AVBitStreamFilterContext *bsfc= av_bitstream_filter_init("h264_mp4toannexb"); - - if (!bsfc) { - av_log(c, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n"); - - return NULL; - } - - orig_extradata_size = c->extradata_size; - orig_extradata = av_mallocz(orig_extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!orig_extradata) { - av_bitstream_filter_close(bsfc); + if (par->extradata[0] == 1) { + if (ff_avc_write_annexb_extradata(par->extradata, &extradata, + &extradata_size)) return NULL; - } - memcpy(orig_extradata, c->extradata, orig_extradata_size); - av_bitstream_filter_filter(bsfc, c, NULL, &dummy_p, &dummy_int, NULL, 0, 0); - av_bitstream_filter_close(bsfc); + tmpbuf = extradata; } psets = av_mallocz(MAX_PSET_SIZE); if (!psets) { - av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n"); - av_free(orig_extradata); + av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n"); + av_free(tmpbuf); return NULL; } memcpy(psets, pset_string, strlen(pset_string)); p = psets + strlen(pset_string); - r = ff_avc_find_startcode(c->extradata, c->extradata + c->extradata_size); - while (r < c->extradata + c->extradata_size) { + r = ff_avc_find_startcode(extradata, extradata + extradata_size); + while (r < extradata + extradata_size) { const uint8_t *r1; uint8_t nal_type; while (!*(r++)); nal_type = *r & 0x1f; - r1 = ff_avc_find_startcode(r, c->extradata + c->extradata_size); + r1 = ff_avc_find_startcode(r, extradata + extradata_size); if (nal_type != 7 && nal_type != 8) { /* Only output SPS and PPS */ r = r1; continue; @@ -217,8 +203,9 @@ static char *extradata2psets(AVCodecContext *c) sps_end = r1; } if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) { - av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r); + av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r); av_free(psets); + av_free(tmpbuf); return NULL; } @@ -231,44 +218,141 @@ static char *extradata2psets(AVCodecContext *c) ff_data_to_hex(p, sps + 1, 3, 0); p[6] = '\0'; } - if (orig_extradata) { - av_free(c->extradata); - c->extradata = orig_extradata; - c->extradata_size = orig_extradata_size; + av_free(tmpbuf); + + return psets; +} + +static char *extradata2psets_hevc(AVCodecParameters *par) +{ + char *psets; + uint8_t *extradata = par->extradata; + int extradata_size = par->extradata_size; + uint8_t *tmpbuf = NULL; + int ps_pos[3] = { 0 }; + static const char * const ps_names[3] = { "vps", "sps", "pps" }; + int num_arrays, num_nalus; + int pos, i, j; + + // Convert to hvcc format. Since we need to group multiple NALUs of + // the same type, and we might need to convert from one format to the + // other anyway, we get away with a little less work by using the hvcc + // format. + if (par->extradata[0] != 1) { + AVIOContext *pb; + if (avio_open_dyn_buf(&pb) < 0) + return NULL; + if (ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0) < 0) { + avio_close_dyn_buf(pb, &tmpbuf); + goto err; + } + extradata_size = avio_close_dyn_buf(pb, &extradata); + tmpbuf = extradata; + } + + if (extradata_size < 23) + goto err; + + num_arrays = extradata[22]; + pos = 23; + for (i = 0; i < num_arrays; i++) { + int num_nalus, nalu_type; + if (pos + 3 > extradata_size) + goto err; + nalu_type = extradata[pos] & 0x3f; + // Not including libavcodec/hevc.h to avoid confusion between + // NAL_* with the same name for both H.264 and HEVC. + if (nalu_type == 32) // VPS + ps_pos[0] = pos; + else if (nalu_type == 33) // SPS + ps_pos[1] = pos; + else if (nalu_type == 34) // PPS + ps_pos[2] = pos; + num_nalus = AV_RB16(&extradata[pos + 1]); + pos += 3; + for (j = 0; j < num_nalus; j++) { + int len; + if (pos + 2 > extradata_size) + goto err; + len = AV_RB16(&extradata[pos]); + pos += 2; + if (pos + len > extradata_size) + goto err; + pos += len; + } + } + if (!ps_pos[0] || !ps_pos[1] || !ps_pos[2]) + goto err; + + psets = av_mallocz(MAX_PSET_SIZE); + if (!psets) + goto err; + psets[0] = '\0'; + + for (i = 0; i < 3; i++) { + pos = ps_pos[i]; + + if (i > 0) + av_strlcat(psets, "; ", MAX_PSET_SIZE); + av_strlcatf(psets, MAX_PSET_SIZE, "sprop-%s=", ps_names[i]); + + // Skipping boundary checks in the input here; we've already traversed + // the whole hvcc structure above without issues + num_nalus = AV_RB16(&extradata[pos + 1]); + pos += 3; + for (j = 0; j < num_nalus; j++) { + int len = AV_RB16(&extradata[pos]); + int strpos; + pos += 2; + if (j > 0) + av_strlcat(psets, ",", MAX_PSET_SIZE); + strpos = strlen(psets); + if (!av_base64_encode(psets + strpos, MAX_PSET_SIZE - strpos, + &extradata[pos], len)) { + av_free(psets); + goto err; + } + pos += len; + } } + av_free(tmpbuf); return psets; + +err: + av_free(tmpbuf); + return NULL; } -static char *extradata2config(AVCodecContext *c) +static char *extradata2config(AVFormatContext *s, AVCodecParameters *par) { char *config; - if (c->extradata_size > MAX_EXTRADATA_SIZE) { - av_log(c, AV_LOG_ERROR, "Too much extradata!\n"); + if (par->extradata_size > MAX_EXTRADATA_SIZE) { + av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); return NULL; } - config = av_malloc(10 + c->extradata_size * 2); + config = av_malloc(10 + par->extradata_size * 2); if (!config) { - av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); + av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); return NULL; } memcpy(config, "; config=", 9); - ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0); - config[9 + c->extradata_size * 2] = 0; + ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0); + config[9 + par->extradata_size * 2] = 0; return config; } -static char *xiph_extradata2config(AVCodecContext *c) +static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par) { char *config, *encoded_config; uint8_t *header_start[3]; int headers_len, header_len[3], config_len; int first_header_size; - switch (c->codec_id) { + switch (par->codec_id) { case AV_CODEC_ID_THEORA: first_header_size = 42; break; @@ -276,14 +360,14 @@ static char *xiph_extradata2config(AVCodecContext *c) first_header_size = 30; break; default: - av_log(c, AV_LOG_ERROR, "Unsupported Xiph codec ID\n"); + av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n"); return NULL; } - if (avpriv_split_xiph_headers(c->extradata, c->extradata_size, + if (avpriv_split_xiph_headers(par->extradata, par->extradata_size, first_header_size, header_start, header_len) < 0) { - av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n"); + av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); return NULL; } @@ -325,12 +409,12 @@ static char *xiph_extradata2config(AVCodecContext *c) return encoded_config; xiph_fail: - av_log(c, AV_LOG_ERROR, + av_log(s, AV_LOG_ERROR, "Not enough memory for configuration string\n"); return NULL; } -static int latm_context2profilelevel(AVCodecContext *c) +static int latm_context2profilelevel(AVCodecParameters *par) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -341,17 +425,17 @@ static int latm_context2profilelevel(AVCodecContext *c) /* TODO: AAC Profile only supports AAC LC Object Type. * Different Object Types should implement different Profile Levels */ - if (c->sample_rate <= 24000) { - if (c->channels <= 2) + if (par->sample_rate <= 24000) { + if (par->channels <= 2) profile_level = 0x28; // AAC Profile, Level 1 - } else if (c->sample_rate <= 48000) { - if (c->channels <= 2) { + } else if (par->sample_rate <= 48000) { + if (par->channels <= 2) { profile_level = 0x29; // AAC Profile, Level 2 - } else if (c->channels <= 5) { + } else if (par->channels <= 5) { profile_level = 0x2A; // AAC Profile, Level 4 } - } else if (c->sample_rate <= 96000) { - if (c->channels <= 5) { + } else if (par->sample_rate <= 96000) { + if (par->channels <= 5) { profile_level = 0x2B; // AAC Profile, Level 5 } } @@ -359,7 +443,7 @@ static int latm_context2profilelevel(AVCodecContext *c) return profile_level; } -static char *latm_context2config(AVCodecContext *c) +static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -370,23 +454,23 @@ static char *latm_context2config(AVCodecContext *c) char *config; for (rate_index = 0; rate_index < 16; rate_index++) - if (avpriv_mpeg4audio_sample_rates[rate_index] == c->sample_rate) + if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate) break; if (rate_index == 16) { - av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n"); + av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); return NULL; } config_byte[0] = 0x40; config_byte[1] = 0; config_byte[2] = 0x20 | rate_index; - config_byte[3] = c->channels << 4; + config_byte[3] = par->channels << 4; config_byte[4] = 0x3f; config_byte[5] = 0xc0; config = av_malloc(6*2+1); if (!config) { - av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); + av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); return NULL; } ff_data_to_hex(config, config_byte, 6, 1); @@ -395,18 +479,18 @@ static char *latm_context2config(AVCodecContext *c) return config; } -static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt) +static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters *p, int payload_type, AVFormatContext *fmt) { char *config = NULL; - switch (c->codec_id) { + switch (p->codec_id) { case AV_CODEC_ID_H264: { int mode = 1; if (fmt && fmt->oformat && fmt->oformat->priv_class && av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) mode = 0; - if (c->extradata_size) { - config = extradata2psets(c); + if (p->extradata_size) { + config = extradata2psets(fmt, p); } av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" "a=fmtp:%d packetization-mode=%d%s\r\n", @@ -414,6 +498,20 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, payload_type, mode, config ? config : ""); break; } + case AV_CODEC_ID_H261: + { + const char *pic_fmt = NULL; + /* only QCIF and CIF are specified as supported in RFC 4587 */ + if (p->width == 176 && p->height == 144) + pic_fmt = "QCIF=1"; + else if (p->width == 352 && p->height == 288) + pic_fmt = "CIF=1"; + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); + if (pic_fmt) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); + break; + } case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: /* a=framesize is required by 3GPP TS 26.234 (PSS). It @@ -422,15 +520,23 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, * stagefright and on Samsung bada. */ if (!fmt || !fmt->oformat->priv_class || !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || - c->codec_id == AV_CODEC_ID_H263P) + p->codec_id == AV_CODEC_ID_H263P) av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" "a=framesize:%d %d-%d\r\n", payload_type, - payload_type, c->width, c->height); + payload_type, p->width, p->height); + break; + case AV_CODEC_ID_HEVC: + if (p->extradata_size) + config = extradata2psets_hevc(p); + av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); + if (config) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", + payload_type, config); break; case AV_CODEC_ID_MPEG4: - if (c->extradata_size) { - config = extradata2config(c); + if (p->extradata_size) { + config = extradata2config(fmt, p); } av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" "a=fmtp:%d profile-level-id=1%s\r\n", @@ -440,21 +546,21 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, case AV_CODEC_ID_AAC: if (fmt && fmt->oformat->priv_class && av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { - config = latm_context2config(c); + config = latm_context2config(fmt, p); if (!config) return NULL; av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", - payload_type, c->sample_rate, c->channels, - payload_type, latm_context2profilelevel(c), config); + payload_type, p->sample_rate, p->channels, + payload_type, latm_context2profilelevel(p), config); } else { - if (c->extradata_size) { - config = extradata2config(c); + if (p->extradata_size) { + config = extradata2config(fmt, p); } else { /* FIXME: maybe we can forge config information based on the * codec parameters... */ - av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); + av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); return NULL; } if (!config) { @@ -464,7 +570,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, "a=fmtp:%d profile-level-id=1;" "mode=AAC-hbr;sizelength=13;indexlength=3;" "indexdeltalength=3%s\r\n", - payload_type, c->sample_rate, c->channels, + payload_type, p->sample_rate, p->channels, payload_type, config); } break; @@ -472,48 +578,48 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n", payload_type, - c->sample_rate, c->channels); + p->sample_rate, p->channels); break; case AV_CODEC_ID_PCM_MULAW: if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", payload_type, - c->sample_rate, c->channels); + p->sample_rate, p->channels); break; case AV_CODEC_ID_PCM_ALAW: if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n", payload_type, - c->sample_rate, c->channels); + p->sample_rate, p->channels); break; case AV_CODEC_ID_AMR_NB: av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n" "a=fmtp:%d octet-align=1\r\n", - payload_type, c->sample_rate, c->channels, + payload_type, p->sample_rate, p->channels, payload_type); break; case AV_CODEC_ID_AMR_WB: av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n" "a=fmtp:%d octet-align=1\r\n", - payload_type, c->sample_rate, c->channels, + payload_type, p->sample_rate, p->channels, payload_type); break; case AV_CODEC_ID_VORBIS: - if (c->extradata_size) - config = xiph_extradata2config(c); + if (p->extradata_size) + config = xiph_extradata2config(fmt, p); else - av_log(c, AV_LOG_ERROR, "Vorbis configuration info missing\n"); + av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); if (!config) return NULL; av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" "a=fmtp:%d configuration=%s\r\n", - payload_type, c->sample_rate, c->channels, + payload_type, p->sample_rate, p->channels, payload_type, config); break; case AV_CODEC_ID_THEORA: { const char *pix_fmt; - switch (c->pix_fmt) { + switch (p->format) { case AV_PIX_FMT_YUV420P: pix_fmt = "YCbCr-4:2:0"; break; @@ -524,14 +630,14 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, pix_fmt = "YCbCr-4:4:4"; break; default: - av_log(c, AV_LOG_ERROR, "Unsupported pixel format.\n"); + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); return NULL; } - if (c->extradata_size) - config = xiph_extradata2config(c); + if (p->extradata_size) + config = xiph_extradata2config(fmt, p); else - av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n"); + av_log(fmt, AV_LOG_ERROR, "Theora configuation info missing\n"); if (!config) return NULL; @@ -540,7 +646,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, "width=%d; height=%d; sampling=%s; " "configuration=%s\r\n", payload_type, payload_type, - c->width, c->height, pix_fmt, config); + p->width, p->height, pix_fmt, config); break; } case AV_CODEC_ID_VP8: @@ -556,29 +662,39 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", payload_type, - 8000, c->channels); + 8000, p->channels); break; case AV_CODEC_ID_ADPCM_G726: { if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", payload_type, - c->bits_per_coded_sample*8, - c->sample_rate); + p->bits_per_coded_sample*8, + p->sample_rate); break; } case AV_CODEC_ID_ILBC: av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" "a=fmtp:%d mode=%d\r\n", - payload_type, c->sample_rate, - payload_type, c->block_align == 38 ? 20 : 30); + payload_type, p->sample_rate, + payload_type, p->block_align == 38 ? 20 : 30); break; case AV_CODEC_ID_SPEEX: av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", - payload_type, c->sample_rate); + payload_type, p->sample_rate); break; case AV_CODEC_ID_OPUS: - av_strlcatf(buff, size, "a=rtpmap:%d opus/48000\r\n", + /* The opus RTP draft says that all opus streams MUST be declared + as stereo, to avoid negotiation failures. The actual number of + channels can change on a packet-by-packet basis. The number of + channels a receiver prefers to receive or a sender plans to send + can be declared via fmtp parameters (both default to mono), but + receivers MUST be able to receive and process stereo packets. */ + av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n", payload_type); + if (p->channels == 2) { + av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", + payload_type); + } break; default: /* Nothing special to do here... */ @@ -594,13 +710,13 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt) { - AVCodecContext *c = st->codec; + AVCodecParameters *p = st->codecpar; const char *type; int payload_type; - payload_type = ff_rtp_get_payload_type(fmt, c, idx); + payload_type = ff_rtp_get_payload_type(fmt, st->codecpar, idx); - switch (c->codec_type) { + switch (p->codec_type) { case AVMEDIA_TYPE_VIDEO : type = "video" ; break; case AVMEDIA_TYPE_AUDIO : type = "audio" ; break; case AVMEDIA_TYPE_SUBTITLE: type = "text" ; break; @@ -609,11 +725,11 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type); sdp_write_address(buff, size, dest_addr, dest_type, ttl); - if (c->bit_rate) { - av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000); + if (p->bit_rate) { + av_strlcatf(buff, size, "b=AS:%d\r\n", p->bit_rate / 1000); } - sdp_write_media_attributes(buff, size, c, payload_type, fmt); + sdp_write_media_attributes(buff, size, p, payload_type, fmt); } int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) diff --git a/libavformat/seek.c b/libavformat/seek.c deleted file mode 100644 index 9be8db9..0000000 --- a/libavformat/seek.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * seek utility functions for use within format handlers - * - * Copyright (c) 2009 Ivan Schreter - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "seek.h" -#include "libavutil/mathematics.h" -#include "libavutil/mem.h" -#include "internal.h" - -// NOTE: implementation should be moved here in another patch, to keep patches -// separated. - -/** - * helper structure describing keyframe search state of one stream - */ -typedef struct { - int64_t pos_lo; ///< position of the frame with low timestamp in file or INT64_MAX if not found (yet) - int64_t ts_lo; ///< frame presentation timestamp or same as pos_lo for byte seeking - - int64_t pos_hi; ///< position of the frame with high timestamp in file or INT64_MAX if not found (yet) - int64_t ts_hi; ///< frame presentation timestamp or same as pos_hi for byte seeking - - int64_t last_pos; ///< last known position of a frame, for multi-frame packets - - int64_t term_ts; ///< termination timestamp (which TS we already read) - AVRational term_ts_tb; ///< timebase for term_ts - int64_t first_ts; ///< first packet timestamp in this iteration (to fill term_ts later) - AVRational first_ts_tb; ///< timebase for first_ts - - int terminated; ///< termination flag for the current iteration -} AVSyncPoint; - -/** - * Compute a distance between timestamps. - * - * Distances are only comparable, if same time bases are used for computing - * distances. - * - * @param ts_hi high timestamp - * @param tb_hi high timestamp time base - * @param ts_lo low timestamp - * @param tb_lo low timestamp time base - * @return representation of distance between high and low timestamps - */ -static int64_t ts_distance(int64_t ts_hi, - AVRational tb_hi, - int64_t ts_lo, - AVRational tb_lo) -{ - int64_t hi, lo; - - hi = ts_hi * tb_hi.num * tb_lo.den; - lo = ts_lo * tb_lo.num * tb_hi.den; - - return hi - lo; -} - -/** - * Partial search for keyframes in multiple streams. - * - * This routine searches in each stream for the next lower and the next higher - * timestamp compared to the given target timestamp. The search starts at the current - * file position and ends at the file position, where all streams have already been - * examined (or when all higher key frames are found in the first iteration). - * - * This routine is called iteratively with an exponential backoff to find the lower - * timestamp. - * - * @param s format context - * @param timestamp target timestamp (or position, if AVSEEK_FLAG_BYTE) - * @param timebase time base for timestamps - * @param flags seeking flags - * @param sync array with information per stream - * @param keyframes_to_find count of keyframes to find in total - * @param found_lo ptr to the count of already found low timestamp keyframes - * @param found_hi ptr to the count of already found high timestamp keyframes - * @param first_iter flag for first iteration - */ -static void search_hi_lo_keyframes(AVFormatContext *s, - int64_t timestamp, - AVRational timebase, - int flags, - AVSyncPoint *sync, - int keyframes_to_find, - int *found_lo, - int *found_hi, - int first_iter) -{ - AVPacket pkt; - AVSyncPoint *sp; - AVStream *st; - int idx; - int flg; - int terminated_count = 0; - int64_t pos; - int64_t pts, dts; // PTS/DTS from stream - int64_t ts; // PTS in stream-local time base or position for byte seeking - AVRational ts_tb; // Time base of the stream or 1:1 for byte seeking - - for (;;) { - if (av_read_frame(s, &pkt) < 0) { - // EOF or error, make sure high flags are set - for (idx = 0; idx < s->nb_streams; ++idx) { - if (s->streams[idx]->discard < AVDISCARD_ALL) { - sp = &sync[idx]; - if (sp->pos_hi == INT64_MAX) { - // no high frame exists for this stream - (*found_hi)++; - sp->ts_hi = INT64_MAX; - sp->pos_hi = INT64_MAX - 1; - } - } - } - break; - } - - idx = pkt.stream_index; - st = s->streams[idx]; - if (st->discard >= AVDISCARD_ALL) - // this stream is not active, skip packet - continue; - - sp = &sync[idx]; - - flg = pkt.flags; - pos = pkt.pos; - pts = pkt.pts; - dts = pkt.dts; - if (pts == AV_NOPTS_VALUE) - // some formats don't provide PTS, only DTS - pts = dts; - - av_free_packet(&pkt); - - // Multi-frame packets only return position for the very first frame. - // Other frames are read with position == -1. Therefore, we note down - // last known position of a frame and use it if a frame without - // position arrives. In this way, it's possible to seek to proper - // position. Additionally, for parsers not providing position at all, - // an approximation will be used (starting position of this iteration). - if (pos < 0) - pos = sp->last_pos; - else - sp->last_pos = pos; - - // Evaluate key frames with known TS (or any frames, if AVSEEK_FLAG_ANY set). - if (pts != AV_NOPTS_VALUE && - ((flg & AV_PKT_FLAG_KEY) || (flags & AVSEEK_FLAG_ANY))) { - if (flags & AVSEEK_FLAG_BYTE) { - // for byte seeking, use position as timestamp - ts = pos; - ts_tb.num = 1; - ts_tb.den = 1; - } else { - // otherwise, get stream time_base - ts = pts; - ts_tb = st->time_base; - } - - if (sp->first_ts == AV_NOPTS_VALUE) { - // Note down termination timestamp for the next iteration - when - // we encounter a packet with the same timestamp, we will ignore - // any further packets for this stream in next iteration (as they - // are already evaluated). - sp->first_ts = ts; - sp->first_ts_tb = ts_tb; - } - - if (sp->term_ts != AV_NOPTS_VALUE && - av_compare_ts(ts, ts_tb, sp->term_ts, sp->term_ts_tb) > 0) { - // past the end position from last iteration, ignore packet - if (!sp->terminated) { - sp->terminated = 1; - ++terminated_count; - if (sp->pos_hi == INT64_MAX) { - // no high frame exists for this stream - (*found_hi)++; - sp->ts_hi = INT64_MAX; - sp->pos_hi = INT64_MAX - 1; - } - if (terminated_count == keyframes_to_find) - break; // all terminated, iteration done - } - continue; - } - - if (av_compare_ts(ts, ts_tb, timestamp, timebase) <= 0) { - // keyframe found before target timestamp - if (sp->pos_lo == INT64_MAX) { - // found first keyframe lower than target timestamp - (*found_lo)++; - sp->ts_lo = ts; - sp->pos_lo = pos; - } else if (sp->ts_lo < ts) { - // found a better match (closer to target timestamp) - sp->ts_lo = ts; - sp->pos_lo = pos; - } - } - if (av_compare_ts(ts, ts_tb, timestamp, timebase) >= 0) { - // keyframe found after target timestamp - if (sp->pos_hi == INT64_MAX) { - // found first keyframe higher than target timestamp - (*found_hi)++; - sp->ts_hi = ts; - sp->pos_hi = pos; - if (*found_hi >= keyframes_to_find && first_iter) { - // We found high frame for all. They may get updated - // to TS closer to target TS in later iterations (which - // will stop at start position of previous iteration). - break; - } - } else if (sp->ts_hi > ts) { - // found a better match (actually, shouldn't happen) - sp->ts_hi = ts; - sp->pos_hi = pos; - } - } - } - } - - // Clean up the parser. - ff_read_frame_flush(s); -} - -int64_t ff_gen_syncpoint_search(AVFormatContext *s, - int stream_index, - int64_t pos, - int64_t ts_min, - int64_t ts, - int64_t ts_max, - int flags) -{ - AVSyncPoint *sync, *sp; - AVStream *st; - int i; - int keyframes_to_find = 0; - int64_t curpos; - int64_t step; - int found_lo = 0, found_hi = 0; - int64_t min_distance, distance; - int64_t min_pos = 0; - int first_iter = 1; - AVRational time_base; - - if (flags & AVSEEK_FLAG_BYTE) { - // for byte seeking, we have exact 1:1 "timestamps" - positions - time_base.num = 1; - time_base.den = 1; - } else { - if (stream_index >= 0) { - // we have a reference stream, which time base we use - st = s->streams[stream_index]; - time_base = st->time_base; - } else { - // no reference stream, use AV_TIME_BASE as reference time base - time_base.num = 1; - time_base.den = AV_TIME_BASE; - } - } - - // Initialize syncpoint structures for each stream. - sync = av_malloc(s->nb_streams * sizeof(AVSyncPoint)); - if (!sync) - // cannot allocate helper structure - return -1; - - for (i = 0; i < s->nb_streams; ++i) { - st = s->streams[i]; - sp = &sync[i]; - - sp->pos_lo = INT64_MAX; - sp->ts_lo = INT64_MAX; - sp->pos_hi = INT64_MAX; - sp->ts_hi = INT64_MAX; - sp->terminated = 0; - sp->first_ts = AV_NOPTS_VALUE; - sp->term_ts = ts_max; - sp->term_ts_tb = time_base; - sp->last_pos = pos; - - st->cur_dts = AV_NOPTS_VALUE; - - if (st->discard < AVDISCARD_ALL) - ++keyframes_to_find; - } - - if (!keyframes_to_find) { - // no stream active, error - av_free(sync); - return -1; - } - - // Find keyframes in all active streams with timestamp/position just before - // and just after requested timestamp/position. - step = s->pb->buffer_size; - curpos = FFMAX(pos - step / 2, 0); - for (;;) { - avio_seek(s->pb, curpos, SEEK_SET); - search_hi_lo_keyframes(s, - ts, time_base, - flags, - sync, - keyframes_to_find, - &found_lo, &found_hi, - first_iter); - if (found_lo == keyframes_to_find && found_hi == keyframes_to_find) - break; // have all keyframes we wanted - if (!curpos) - break; // cannot go back anymore - - curpos = pos - step; - if (curpos < 0) - curpos = 0; - step *= 2; - - // switch termination positions - for (i = 0; i < s->nb_streams; ++i) { - st = s->streams[i]; - st->cur_dts = AV_NOPTS_VALUE; - - sp = &sync[i]; - if (sp->first_ts != AV_NOPTS_VALUE) { - sp->term_ts = sp->first_ts; - sp->term_ts_tb = sp->first_ts_tb; - sp->first_ts = AV_NOPTS_VALUE; - } - sp->terminated = 0; - sp->last_pos = curpos; - } - first_iter = 0; - } - - // Find actual position to start decoding so that decoder synchronizes - // closest to ts and between ts_min and ts_max. - pos = INT64_MAX; - - for (i = 0; i < s->nb_streams; ++i) { - st = s->streams[i]; - if (st->discard < AVDISCARD_ALL) { - sp = &sync[i]; - min_distance = INT64_MAX; - // Find timestamp closest to requested timestamp within min/max limits. - if (sp->pos_lo != INT64_MAX - && av_compare_ts(ts_min, time_base, sp->ts_lo, st->time_base) <= 0 - && av_compare_ts(sp->ts_lo, st->time_base, ts_max, time_base) <= 0) { - // low timestamp is in range - min_distance = ts_distance(ts, time_base, sp->ts_lo, st->time_base); - min_pos = sp->pos_lo; - } - if (sp->pos_hi != INT64_MAX - && av_compare_ts(ts_min, time_base, sp->ts_hi, st->time_base) <= 0 - && av_compare_ts(sp->ts_hi, st->time_base, ts_max, time_base) <= 0) { - // high timestamp is in range, check distance - distance = ts_distance(sp->ts_hi, st->time_base, ts, time_base); - if (distance < min_distance) { - min_distance = distance; - min_pos = sp->pos_hi; - } - } - if (min_distance == INT64_MAX) { - // no timestamp is in range, cannot seek - av_free(sync); - return -1; - } - if (min_pos < pos) - pos = min_pos; - } - } - - avio_seek(s->pb, pos, SEEK_SET); - av_free(sync); - return pos; -} - -AVParserState *ff_store_parser_state(AVFormatContext *s) -{ - int i; - AVStream *st; - AVParserStreamState *ss; - AVParserState *state = av_malloc(sizeof(AVParserState)); - if (!state) - return NULL; - - state->stream_states = av_malloc(sizeof(AVParserStreamState) * s->nb_streams); - if (!state->stream_states) { - av_free(state); - return NULL; - } - - state->fpos = avio_tell(s->pb); - - // copy context structures - state->packet_buffer = s->packet_buffer; - state->parse_queue = s->parse_queue; - state->raw_packet_buffer = s->raw_packet_buffer; - state->raw_packet_buffer_remaining_size = s->raw_packet_buffer_remaining_size; - - s->packet_buffer = NULL; - s->parse_queue = NULL; - s->raw_packet_buffer = NULL; - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; - - // copy stream structures - state->nb_streams = s->nb_streams; - for (i = 0; i < s->nb_streams; i++) { - st = s->streams[i]; - ss = &state->stream_states[i]; - - ss->parser = st->parser; - ss->last_IP_pts = st->last_IP_pts; - ss->cur_dts = st->cur_dts; - ss->probe_packets = st->probe_packets; - - st->parser = NULL; - st->last_IP_pts = AV_NOPTS_VALUE; - st->cur_dts = AV_NOPTS_VALUE; - st->probe_packets = MAX_PROBE_PACKETS; - } - - return state; -} - -void ff_restore_parser_state(AVFormatContext *s, AVParserState *state) -{ - int i; - AVStream *st; - AVParserStreamState *ss; - ff_read_frame_flush(s); - - if (!state) - return; - - avio_seek(s->pb, state->fpos, SEEK_SET); - - // copy context structures - s->packet_buffer = state->packet_buffer; - s->parse_queue = state->parse_queue; - s->raw_packet_buffer = state->raw_packet_buffer; - s->raw_packet_buffer_remaining_size = state->raw_packet_buffer_remaining_size; - - // copy stream structures - for (i = 0; i < state->nb_streams; i++) { - st = s->streams[i]; - ss = &state->stream_states[i]; - - st->parser = ss->parser; - st->last_IP_pts = ss->last_IP_pts; - st->cur_dts = ss->cur_dts; - st->probe_packets = ss->probe_packets; - } - - av_free(state->stream_states); - av_free(state); -} - -static void free_packet_list(AVPacketList *pktl) -{ - AVPacketList *cur; - while (pktl) { - cur = pktl; - pktl = cur->next; - av_free_packet(&cur->pkt); - av_free(cur); - } -} - -void ff_free_parser_state(AVFormatContext *s, AVParserState *state) -{ - int i; - AVParserStreamState *ss; - - if (!state) - return; - - for (i = 0; i < state->nb_streams; i++) { - ss = &state->stream_states[i]; - if (ss->parser) - av_parser_close(ss->parser); - } - - free_packet_list(state->packet_buffer); - free_packet_list(state->parse_queue); - free_packet_list(state->raw_packet_buffer); - - av_free(state->stream_states); - av_free(state); -} diff --git a/libavformat/seek.h b/libavformat/seek.h deleted file mode 100644 index 44cd369..0000000 --- a/libavformat/seek.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * seek utility functions for use within format handlers - * - * Copyright (c) 2009 Ivan Schreter - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFORMAT_SEEK_H -#define AVFORMAT_SEEK_H - -#include "avformat.h" - -/** - * structure to store parser state of one AVStream - */ -typedef struct AVParserStreamState { - // saved members of AVStream - AVCodecParserContext *parser; - int64_t last_IP_pts; - int64_t cur_dts; - int probe_packets; -} AVParserStreamState; - -/** - * structure to store parser state of AVFormat - */ -typedef struct AVParserState { - int64_t fpos; ///< file position at the time of call - - // saved members of AVFormatContext - AVPacketList *packet_buffer; ///< packet buffer of original state - AVPacketList *parse_queue; ///< parse queue of original state - AVPacketList *raw_packet_buffer; ///< raw packet buffer of original state - int raw_packet_buffer_remaining_size; ///< remaining space in raw_packet_buffer - - // saved info for streams - int nb_streams; ///< number of streams with stored state - AVParserStreamState *stream_states; ///< states of individual streams (array) -} AVParserState; - -/** - * Search for the sync point of all active streams. - * - * This routine is not supposed to be called directly by a user application, - * but by demuxers. - * - * A sync point is defined as a point in stream, such that, when decoding start - * from this point, the decoded output of all streams synchronizes closest - * to the given timestamp ts. This routine also takes timestamp limits into account. - * Thus, the output will synchronize no sooner than ts_min and no later than ts_max. - * - * @param stream_index stream index for time base reference of timestamps - * @param pos approximate position where to start searching for key frames - * @param min_ts minimum allowed timestamp (position, if AVSEEK_FLAG_BYTE set) - * @param ts target timestamp (or position, if AVSEEK_FLAG_BYTE set in flags) - * @param max_ts maximum allowed timestamp (position, if AVSEEK_FLAG_BYTE set) - * @param flags if AVSEEK_FLAG_ANY is set, seek to any frame, otherwise only - * to a keyframe. If AVSEEK_FLAG_BYTE is set, search by - * position, not by timestamp. - * @return -1 if no such sync point could be found, otherwise stream position - * (stream is repositioned to this position) - */ -int64_t ff_gen_syncpoint_search(AVFormatContext *s, - int stream_index, - int64_t pos, - int64_t min_ts, - int64_t ts, - int64_t max_ts, - int flags); - -/** - * Store current parser state and file position. - * - * This function can be used by demuxers before a destructive seeking algorithm - * to store the parser state. Depending on the outcome of the seek, either the original - * state can be restored or the new state kept and the original state freed. - * - * @note As a side effect, the original parser state is reset, since structures - * are relinked to the stored state instead of being deeply-copied (for - * performance reasons and to keep the code simple). - * - * @param s context from which to save state - * @return parser state object or NULL if memory could not be allocated - */ -AVParserState *ff_store_parser_state(AVFormatContext *s); - -/** - * Restore previously saved parser state and file position. - * - * Saved state will be invalidated and freed by this call, since internal - * structures will be relinked back to the stored state instead of being - * deeply-copied. - * - * @param s context to which to restore state (same as used for storing state) - * @param state state to restore - */ -void ff_restore_parser_state(AVFormatContext *s, AVParserState *state); - -/** - * Free previously saved parser state. - * - * @param s context to which the state belongs (same as used for storing state) - * @param state state to free - */ -void ff_free_parser_state(AVFormatContext *s, AVParserState *state); - -#endif /* AVFORMAT_SEEK_H */ diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c index 53e2066..16500b4 100644 --- a/libavformat/segafilm.c +++ b/libavformat/segafilm.c @@ -1,6 +1,6 @@ /* * Sega FILM Format (CPK) Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -37,7 +37,7 @@ #define CVID_TAG MKBETAG('c', 'v', 'i', 'd') #define RAW_TAG MKBETAG('r', 'a', 'w', ' ') -typedef struct { +typedef struct film_sample { int stream; int64_t sample_offset; unsigned int sample_size; @@ -61,10 +61,6 @@ typedef struct FilmDemuxContext { unsigned int base_clock; unsigned int version; - - /* buffer used for interleaving stereo PCM data */ - unsigned char *stereo_buffer; - int stereo_buffer_size; } FilmDemuxContext; static int film_probe(AVProbeData *p) @@ -80,7 +76,6 @@ static int film_read_close(AVFormatContext *s) FilmDemuxContext *film = s->priv_data; av_freep(&film->sample_table); - av_freep(&film->stereo_buffer); return 0; } @@ -94,10 +89,9 @@ static int film_read_header(AVFormatContext *s) int i, ret; unsigned int data_offset; unsigned int audio_frame_counter; + unsigned int video_frame_counter; film->sample_table = NULL; - film->stereo_buffer = NULL; - film->stereo_buffer_size = 0; /* load the main FILM header */ if (avio_read(pb, scratch, 16) != 16) @@ -131,9 +125,9 @@ static int film_read_header(AVFormatContext *s) film->audio_type = AV_CODEC_ID_ADPCM_ADX; else if (film->audio_channels > 0) { if (film->audio_bits == 8) - film->audio_type = AV_CODEC_ID_PCM_S8; + film->audio_type = AV_CODEC_ID_PCM_S8_PLANAR; else if (film->audio_bits == 16) - film->audio_type = AV_CODEC_ID_PCM_S16BE; + film->audio_type = AV_CODEC_ID_PCM_S16BE_PLANAR; else film->audio_type = AV_CODEC_ID_NONE; } else @@ -157,15 +151,15 @@ static int film_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); film->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = film->video_type; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = AV_RB32(&scratch[16]); - st->codec->height = AV_RB32(&scratch[12]); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = film->video_type; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = AV_RB32(&scratch[16]); + st->codecpar->height = AV_RB32(&scratch[12]); if (film->video_type == AV_CODEC_ID_RAWVIDEO) { if (scratch[20] == 24) { - st->codec->pix_fmt = AV_PIX_FMT_RGB24; + st->codecpar->format = AV_PIX_FMT_RGB24; } else { av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]); return -1; @@ -178,24 +172,24 @@ static int film_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); film->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = film->audio_type; - st->codec->codec_tag = 1; - st->codec->channels = film->audio_channels; - st->codec->sample_rate = film->audio_samplerate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = film->audio_type; + st->codecpar->codec_tag = 1; + st->codecpar->channels = film->audio_channels; + st->codecpar->sample_rate = film->audio_samplerate; if (film->audio_type == AV_CODEC_ID_ADPCM_ADX) { - st->codec->bits_per_coded_sample = 18 * 8 / 32; - st->codec->block_align = st->codec->channels * 18; + st->codecpar->bits_per_coded_sample = 18 * 8 / 32; + st->codecpar->block_align = st->codecpar->channels * 18; st->need_parsing = AVSTREAM_PARSE_FULL; } else { - st->codec->bits_per_coded_sample = film->audio_bits; - st->codec->block_align = st->codec->channels * - st->codec->bits_per_coded_sample / 8; + st->codecpar->bits_per_coded_sample = film->audio_bits; + st->codecpar->block_align = st->codecpar->channels * + st->codecpar->bits_per_coded_sample / 8; } - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; } /* load the sample table */ @@ -213,13 +207,13 @@ static int film_read_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) avpriv_set_pts_info(st, 33, 1, film->base_clock); else avpriv_set_pts_info(st, 64, 1, film->audio_samplerate); } - audio_frame_counter = 0; + audio_frame_counter = video_frame_counter = 0; for (i = 0; i < film->sample_count; i++) { /* load the next sample record and transfer it to an internal struct */ if (avio_read(pb, scratch, 16) != 16) { @@ -247,9 +241,21 @@ static int film_read_header(AVFormatContext *s) film->sample_table[i].stream = film->video_stream_index; film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF; film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1; + video_frame_counter++; + av_add_index_entry(s->streams[film->video_stream_index], + film->sample_table[i].sample_offset, + film->sample_table[i].pts, + film->sample_table[i].sample_size, 0, + film->sample_table[i].keyframe); } } + if (film->audio_type) + s->streams[film->audio_stream_index]->duration = audio_frame_counter; + + if (film->video_type) + s->streams[film->video_stream_index]->duration = video_frame_counter; + film->current_sample = 0; return 0; @@ -265,8 +271,6 @@ static int film_read_packet(AVFormatContext *s, AVIOContext *pb = s->pb; film_sample *sample; int ret = 0; - int i; - int left, right; if (film->current_sample >= film->sample_count) return AVERROR(EIO); @@ -276,55 +280,9 @@ static int film_read_packet(AVFormatContext *s, /* position the stream (will probably be there anyway) */ avio_seek(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 == AV_CODEC_ID_CINEPAK)) { - pkt->pos= avio_tell(pb); - if (av_new_packet(pkt, sample->sample_size)) - return AVERROR(ENOMEM); - avio_read(pb, pkt->data, sample->sample_size); - } else if ((sample->stream == film->audio_stream_index) && - (film->audio_channels == 2) && - (film->audio_type != AV_CODEC_ID_ADPCM_ADX)) { - /* stereo PCM needs to be interleaved */ - - if (av_new_packet(pkt, sample->sample_size)) - return AVERROR(ENOMEM); - - /* 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); - if (!film->stereo_buffer) { - film->stereo_buffer_size = 0; - return AVERROR(ENOMEM); - } - } - - pkt->pos= avio_tell(pb); - ret = avio_read(pb, film->stereo_buffer, sample->sample_size); - if (ret != sample->sample_size) - ret = AVERROR(EIO); - - 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(EIO); - } + ret = av_get_packet(pb, pkt, sample->sample_size); + if (ret < 0) + return ret; pkt->stream_index = sample->stream; pkt->pts = sample->pts; @@ -334,6 +292,24 @@ static int film_read_packet(AVFormatContext *s, return ret; } +static int film_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + FilmDemuxContext *film = s->priv_data; + AVStream *st = s->streams[stream_index]; + int64_t pos; + int ret = av_index_search_timestamp(st, timestamp, flags); + if (ret < 0) + return ret; + + pos = avio_seek(s->pb, st->index_entries[ret].pos, SEEK_SET); + if (pos < 0) + return pos; + + film->current_sample = ret; + + return 0; +} + AVInputFormat ff_segafilm_demuxer = { .name = "film_cpk", .long_name = NULL_IF_CONFIG_SMALL("Sega FILM / CPK"), @@ -342,4 +318,5 @@ AVInputFormat ff_segafilm_demuxer = { .read_header = film_read_header, .read_packet = film_read_packet, .read_close = film_read_close, + .read_seek = film_read_seek, }; diff --git a/libavformat/segment.c b/libavformat/segment.c index 61ec93f..fd68a9f 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -30,7 +30,7 @@ #include "libavutil/parseutils.h" #include "libavutil/mathematics.h" -typedef struct { +typedef struct SegmentContext { const AVClass *class; /**< Class for private options. */ int number; AVOutputFormat *oformat; @@ -67,13 +67,17 @@ static int segment_mux_init(AVFormatContext *s) oc->oformat = seg->oformat; oc->interrupt_callback = s->interrupt_callback; + oc->opaque = s->opaque; + oc->io_close = s->io_close; + oc->io_open = s->io_open; for (i = 0; i < s->nb_streams; i++) { AVStream *st; if (!(st = avformat_new_stream(oc, NULL))) return AVERROR(ENOMEM); - avcodec_copy_context(st->codec, s->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->time_base = s->streams[i]->time_base; } return 0; @@ -85,8 +89,7 @@ static int segment_hls_window(AVFormatContext *s, int last) int i, ret = 0; char buf[1024]; - if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) < 0) goto fail; avio_printf(seg->pb, "#EXTM3U\n"); @@ -104,14 +107,19 @@ static int segment_hls_window(AVFormatContext *s, int last) if (seg->entry_prefix) { avio_printf(seg->pb, "%s", seg->entry_prefix); } - av_get_frame_filename(buf, sizeof(buf), s->filename, i); + ret = av_get_frame_filename(buf, sizeof(buf), s->filename, i); + if (ret < 0) { + ret = AVERROR(EINVAL); + goto fail; + } avio_printf(seg->pb, "%s\n", buf); } if (last) avio_printf(seg->pb, "#EXT-X-ENDLIST\n"); fail: - avio_closep(&seg->pb); + ff_format_io_close(s, &seg->pb); + return ret; } @@ -136,8 +144,7 @@ static int segment_start(AVFormatContext *s, int write_header) s->filename, c->number++) < 0) return AVERROR(EINVAL); - if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) return err; if (oc->oformat->priv_class && oc->priv_data) @@ -158,7 +165,7 @@ static int segment_end(AVFormatContext *oc, int write_trailer) av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */ if (write_trailer) av_write_trailer(oc); - avio_close(oc->pb); + ff_format_io_close(oc, &oc->pb); return ret; } @@ -185,7 +192,7 @@ static void close_null_ctx(AVIOContext *pb) static void seg_free_context(SegmentContext *seg) { - avio_closep(&seg->pb); + ff_format_io_close(seg->avf, &seg->pb); avformat_free_context(seg->avf); seg->avf = NULL; } @@ -203,13 +210,12 @@ static int seg_write_header(AVFormatContext *s) seg->individual_header_trailer = 0; if (seg->list && seg->list_type != LIST_HLS) - if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) < 0) goto fail; for (i = 0; i < s->nb_streams; i++) seg->has_video += - (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO); + (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO); if (seg->has_video > 1) av_log(s, AV_LOG_WARNING, @@ -240,8 +246,7 @@ static int seg_write_header(AVFormatContext *s) } if (seg->write_header_trailer) { - if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) goto fail; } else { if ((ret = open_null_ctx(&oc->pb)) < 0) @@ -249,14 +254,13 @@ static int seg_write_header(AVFormatContext *s) } if ((ret = avformat_write_header(oc, NULL)) < 0) { - avio_close(oc->pb); + ff_format_io_close(oc, &oc->pb); goto fail; } if (!seg->write_header_trailer) { close_null_ctx(oc->pb); - if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) goto fail; } @@ -289,7 +293,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); if (seg->has_video) { - can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->flags & AV_PKT_FLAG_KEY; } @@ -316,9 +320,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) avio_printf(seg->pb, "%s\n", oc->filename); avio_flush(seg->pb); if (seg->size && !(seg->number % seg->size)) { - avio_closep(&seg->pb); - if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE, - &s->interrupt_callback, NULL)) < 0) + ff_format_io_close(s, &seg->pb); + if ((ret = s->io_open(s, &seg->pb, seg->list, + AVIO_FLAG_WRITE, NULL)) < 0) goto fail; } } @@ -346,7 +350,8 @@ static int seg_write_trailer(struct AVFormatContext *s) if (!seg->write_header_trailer) { if ((ret = segment_end(oc, 0)) < 0) goto fail; - open_null_ctx(&oc->pb); + if ((ret = open_null_ctx(&oc->pb)) < 0) + goto fail; ret = av_write_trailer(oc); close_null_ctx(oc->pb); } else { @@ -362,7 +367,7 @@ static int seg_write_trailer(struct AVFormatContext *s) } fail: - avio_close(seg->pb); + ff_format_io_close(s, &seg->pb); avformat_free_context(oc); return ret; } diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c index 8316388..604ab6b 100644 --- a/libavformat/sierravmd.c +++ b/libavformat/sierravmd.c @@ -1,6 +1,6 @@ /* * Sierra VMD Format Demuxer - * Copyright (c) 2004 The ffmpeg Project + * Copyright (c) 2004 The FFmpeg project * * This file is part of Libav. * @@ -35,7 +35,7 @@ #define VMD_HEADER_SIZE 0x0330 #define BYTES_PER_FRAME_RECORD 16 -typedef struct { +typedef struct vmd_frame { int stream_index; int64_t frame_offset; unsigned int frame_size; @@ -110,18 +110,18 @@ static int vmd_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(vst, 33, 1, 10); vmd->video_stream_index = vst->index; - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO; - vst->codec->codec_tag = 0; /* no fourcc */ - vst->codec->width = AV_RL16(&vmd->vmd_header[12]); - vst->codec->height = AV_RL16(&vmd->vmd_header[14]); - if(vmd->is_indeo3 && vst->codec->width > 320){ - vst->codec->width >>= 1; - vst->codec->height >>= 1; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO; + vst->codecpar->codec_tag = 0; /* no fourcc */ + vst->codecpar->width = AV_RL16(&vmd->vmd_header[12]); + vst->codecpar->height = AV_RL16(&vmd->vmd_header[14]); + if(vmd->is_indeo3 && vst->codecpar->width > 320){ + vst->codecpar->width >>= 1; + vst->codecpar->height >>= 1; } - 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); + vst->codecpar->extradata_size = VMD_HEADER_SIZE; + vst->codecpar->extradata = av_mallocz(VMD_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(vst->codecpar->extradata, vmd->vmd_header, VMD_HEADER_SIZE); /* if sample rate is 0, assume no audio */ vmd->sample_rate = AV_RL16(&vmd->vmd_header[804]); @@ -130,30 +130,30 @@ static int vmd_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); vmd->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_VMDAUDIO; - st->codec->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_VMDAUDIO; + st->codecpar->codec_tag = 0; /* no fourcc */ if (vmd->vmd_header[811] & 0x80) { - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - st->codec->sample_rate = vmd->sample_rate; - st->codec->block_align = AV_RL16(&vmd->vmd_header[806]); - if (st->codec->block_align & 0x8000) { - st->codec->bits_per_coded_sample = 16; - st->codec->block_align = -(st->codec->block_align - 0x10000); + st->codecpar->sample_rate = vmd->sample_rate; + st->codecpar->block_align = AV_RL16(&vmd->vmd_header[806]); + if (st->codecpar->block_align & 0x8000) { + st->codecpar->bits_per_coded_sample = 16; + st->codecpar->block_align = -(st->codecpar->block_align - 0x10000); } else { - st->codec->bits_per_coded_sample = 8; + st->codecpar->bits_per_coded_sample = 8; } - st->codec->bit_rate = st->codec->sample_rate * - st->codec->bits_per_coded_sample * st->codec->channels; + st->codecpar->bit_rate = st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample * st->codecpar->channels; /* calculate pts */ - num = st->codec->block_align; - den = st->codec->sample_rate * st->codec->channels; + num = st->codecpar->block_align; + den = st->codecpar->sample_rate * st->codecpar->channels; av_reduce(&den, &num, den, num, (1UL<<31)-1); avpriv_set_pts_info(vst, 33, num, den); avpriv_set_pts_info(st, 33, num, den); @@ -271,7 +271,7 @@ static int vmd_read_packet(AVFormatContext *s, frame->frame_size); if (ret != frame->frame_size) { - av_free_packet(pkt); + av_packet_unref(pkt); ret = AVERROR(EIO); } pkt->stream_index = frame->stream_index; diff --git a/libavformat/siff.c b/libavformat/siff.c index 8ba7c60..e11d5bd 100644 --- a/libavformat/siff.c +++ b/libavformat/siff.c @@ -21,10 +21,11 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" + #include "avformat.h" #include "internal.h" -enum SIFFTags{ +enum SIFFTags { TAG_SIFF = MKTAG('S', 'I', 'F', 'F'), TAG_BODY = MKTAG('B', 'O', 'D', 'Y'), TAG_VBHD = MKTAG('V', 'B', 'H', 'D'), @@ -33,7 +34,7 @@ enum SIFFTags{ TAG_SOUN = MKTAG('S', 'O', 'U', 'N'), }; -enum VBFlags{ +enum VBFlags { VB_HAS_GMC = 0x01, VB_HAS_AUDIO = 0x04, VB_HAS_VIDEO = 0x08, @@ -41,7 +42,7 @@ enum VBFlags{ VB_HAS_LENGTH = 0x20 }; -typedef struct SIFFContext{ +typedef struct SIFFContext { int frames; int cur_frame; int rate; @@ -52,13 +53,13 @@ typedef struct SIFFContext{ int has_audio; int curstrm; - int pktsize; + unsigned int pktsize; int gmcsize; int sndsize; - int flags; + unsigned int flags; uint8_t gmc[4]; -}SIFFContext; +} SIFFContext; static int siff_probe(AVProbeData *p) { @@ -75,15 +76,15 @@ static int create_audio_stream(AVFormatContext *s, SIFFContext *c) AVStream *ast; ast = avformat_new_stream(s, NULL); if (!ast) - return -1; - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; - ast->codec->bits_per_coded_sample = 8; - ast->codec->sample_rate = c->rate; + return AVERROR(ENOMEM); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->bits_per_coded_sample = 8; + ast->codecpar->sample_rate = c->rate; avpriv_set_pts_info(ast, 16, 1, c->rate); - ast->start_time = 0; + ast->start_time = 0; return 0; } @@ -92,65 +93,65 @@ static int siff_parse_vbv1(AVFormatContext *s, SIFFContext *c, AVIOContext *pb) AVStream *st; int width, height; - if (avio_rl32(pb) != TAG_VBHD){ + if (avio_rl32(pb) != TAG_VBHD) { av_log(s, AV_LOG_ERROR, "Header chunk is missing\n"); - return -1; + return AVERROR_INVALIDDATA; } - if(avio_rb32(pb) != 32){ + if (avio_rb32(pb) != 32) { av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n"); - return -1; + return AVERROR_INVALIDDATA; } - if(avio_rl16(pb) != 1){ + if (avio_rl16(pb) != 1) { av_log(s, AV_LOG_ERROR, "Incorrect header version\n"); - return -1; + return AVERROR_INVALIDDATA; } - width = avio_rl16(pb); + width = avio_rl16(pb); height = avio_rl16(pb); avio_skip(pb, 4); c->frames = avio_rl16(pb); - if(!c->frames){ + if (!c->frames) { av_log(s, AV_LOG_ERROR, "File contains no frames ???\n"); - return -1; + return AVERROR_INVALIDDATA; } - c->bits = avio_rl16(pb); - c->rate = avio_rl16(pb); + c->bits = avio_rl16(pb); + c->rate = avio_rl16(pb); c->block_align = c->rate * (c->bits >> 3); - avio_skip(pb, 16); //zeroes + avio_skip(pb, 16); // zeroes st = avformat_new_stream(s, NULL); if (!st) - return -1; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_VB; - st->codec->codec_tag = MKTAG('V', 'B', 'V', '1'); - st->codec->width = width; - st->codec->height = height; - st->codec->pix_fmt = AV_PIX_FMT_PAL8; + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_VB; + st->codecpar->codec_tag = MKTAG('V', 'B', 'V', '1'); + st->codecpar->width = width; + st->codecpar->height = height; + st->codecpar->format = AV_PIX_FMT_PAL8; avpriv_set_pts_info(st, 16, 1, 12); c->cur_frame = 0; c->has_video = 1; c->has_audio = !!c->rate; - c->curstrm = -1; - if (c->has_audio && create_audio_stream(s, c) < 0) - return -1; + c->curstrm = -1; + if (c->has_audio) + return create_audio_stream(s, c); return 0; } static int siff_parse_soun(AVFormatContext *s, SIFFContext *c, AVIOContext *pb) { - if (avio_rl32(pb) != TAG_SHDR){ + if (avio_rl32(pb) != TAG_SHDR) { av_log(s, AV_LOG_ERROR, "Header chunk is missing\n"); - return -1; + return AVERROR_INVALIDDATA; } - if(avio_rb32(pb) != 8){ + if (avio_rb32(pb) != 8) { av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n"); - return -1; + return AVERROR_INVALIDDATA; } - avio_skip(pb, 4); //unknown value - c->rate = avio_rl16(pb); - c->bits = avio_rl16(pb); + avio_skip(pb, 4); // unknown value + c->rate = avio_rl16(pb); + c->bits = avio_rl16(pb); c->block_align = c->rate * (c->bits >> 3); return create_audio_stream(s, c); } @@ -158,28 +159,29 @@ static int siff_parse_soun(AVFormatContext *s, SIFFContext *c, AVIOContext *pb) static int siff_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - SIFFContext *c = s->priv_data; + SIFFContext *c = s->priv_data; uint32_t tag; + int ret; if (avio_rl32(pb) != TAG_SIFF) - return -1; - avio_skip(pb, 4); //ignore size + return AVERROR_INVALIDDATA; + avio_skip(pb, 4); // ignore size tag = avio_rl32(pb); - if (tag != TAG_VBV1 && tag != TAG_SOUN){ + if (tag != TAG_VBV1 && tag != TAG_SOUN) { av_log(s, AV_LOG_ERROR, "Not a VBV file\n"); - return -1; + return AVERROR_INVALIDDATA; } - if (tag == TAG_VBV1 && siff_parse_vbv1(s, c, pb) < 0) - return -1; - if (tag == TAG_SOUN && siff_parse_soun(s, c, pb) < 0) - return -1; - if (avio_rl32(pb) != MKTAG('B', 'O', 'D', 'Y')){ + if (tag == TAG_VBV1 && (ret = siff_parse_vbv1(s, c, pb)) < 0) + return ret; + if (tag == TAG_SOUN && (ret = siff_parse_soun(s, c, pb)) < 0) + return ret; + if (avio_rl32(pb) != MKTAG('B', 'O', 'D', 'Y')) { av_log(s, AV_LOG_ERROR, "'BODY' chunk is missing\n"); - return -1; + return AVERROR_INVALIDDATA; } - avio_skip(pb, 4); //ignore size + avio_skip(pb, 4); // ignore size return 0; } @@ -187,22 +189,22 @@ static int siff_read_header(AVFormatContext *s) static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) { SIFFContext *c = s->priv_data; - int size; - if (c->has_video){ + if (c->has_video) { + unsigned int size; if (c->cur_frame >= c->frames) return AVERROR(EIO); - if (c->curstrm == -1){ + if (c->curstrm == -1) { c->pktsize = avio_rl32(s->pb) - 4; - c->flags = avio_rl16(s->pb); + c->flags = avio_rl16(s->pb); c->gmcsize = (c->flags & VB_HAS_GMC) ? 4 : 0; if (c->gmcsize) avio_read(s->pb, c->gmc, c->gmcsize); - c->sndsize = (c->flags & VB_HAS_AUDIO) ? avio_rl32(s->pb): 0; + c->sndsize = (c->flags & VB_HAS_AUDIO) ? avio_rl32(s->pb) : 0; c->curstrm = !!(c->flags & VB_HAS_AUDIO); } - if (!c->curstrm){ + if (!c->curstrm) { size = c->pktsize - c->sndsize; if (av_new_packet(pkt, size) < 0) return AVERROR(ENOMEM); @@ -211,23 +213,24 @@ static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) memcpy(pkt->data + 2, c->gmc, c->gmcsize); avio_read(s->pb, pkt->data + 2 + c->gmcsize, size - c->gmcsize - 2); pkt->stream_index = 0; - c->curstrm = -1; - }else{ - if ((size = av_get_packet(s->pb, pkt, c->sndsize - 4)) < 0) + c->curstrm = -1; + } else { + int pktsize = av_get_packet(s->pb, pkt, c->sndsize - 4); + if (pktsize < 0) return AVERROR(EIO); pkt->stream_index = 1; - pkt->duration = size; - c->curstrm = 0; + pkt->duration = pktsize; + c->curstrm = 0; } - if(!c->cur_frame || c->curstrm) + if (!c->cur_frame || c->curstrm) pkt->flags |= AV_PKT_FLAG_KEY; if (c->curstrm == -1) c->cur_frame++; - }else{ - size = av_get_packet(s->pb, pkt, c->block_align); - if(size <= 0) + } else { + int pktsize = av_get_packet(s->pb, pkt, c->block_align); + if (pktsize <= 0) return AVERROR(EIO); - pkt->duration = size; + pkt->duration = pktsize; } return pkt->size; } diff --git a/libavformat/smacker.c b/libavformat/smacker.c index 2fa531b..eb4b63f 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -162,12 +162,12 @@ static int smacker_read_header(AVFormatContext *s) if (!st) return -1; smk->videoindex = st->index; - st->codec->width = smk->width; - st->codec->height = smk->height; - st->codec->pix_fmt = AV_PIX_FMT_PAL8; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_SMACKVIDEO; - st->codec->codec_tag = smk->magic; + st->codecpar->width = smk->width; + st->codecpar->height = smk->height; + st->codecpar->format = AV_PIX_FMT_PAL8; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_SMACKVIDEO; + st->codecpar->codec_tag = smk->magic; /* Smacker uses 100000 as internal timebase */ if(smk->pts_inc < 0) smk->pts_inc = -smk->pts_inc; @@ -183,39 +183,39 @@ static int smacker_read_header(AVFormatContext *s) if (smk->rates[i]) { ast[i] = avformat_new_stream(s, NULL); smk->indexes[i] = ast[i]->index; - ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; if (smk->aflags[i] & SMK_AUD_BINKAUD) { - ast[i]->codec->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT; + ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT; } else if (smk->aflags[i] & SMK_AUD_USEDCT) { - ast[i]->codec->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; + ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; } else if (smk->aflags[i] & SMK_AUD_PACKED){ - ast[i]->codec->codec_id = AV_CODEC_ID_SMACKAUDIO; - ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A'); + ast[i]->codecpar->codec_id = AV_CODEC_ID_SMACKAUDIO; + ast[i]->codecpar->codec_tag = MKTAG('S', 'M', 'K', 'A'); } else { - ast[i]->codec->codec_id = AV_CODEC_ID_PCM_U8; + ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_U8; } if (smk->aflags[i] & SMK_AUD_STEREO) { - ast[i]->codec->channels = 2; - ast[i]->codec->channel_layout = AV_CH_LAYOUT_STEREO; + ast[i]->codecpar->channels = 2; + ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - ast[i]->codec->channels = 1; - ast[i]->codec->channel_layout = AV_CH_LAYOUT_MONO; + ast[i]->codecpar->channels = 1; + ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - ast[i]->codec->sample_rate = smk->rates[i]; - ast[i]->codec->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8; - if(ast[i]->codec->bits_per_coded_sample == 16 && ast[i]->codec->codec_id == AV_CODEC_ID_PCM_U8) - ast[i]->codec->codec_id = AV_CODEC_ID_PCM_S16LE; - avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate - * ast[i]->codec->channels * ast[i]->codec->bits_per_coded_sample / 8); + ast[i]->codecpar->sample_rate = smk->rates[i]; + ast[i]->codecpar->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8; + if(ast[i]->codecpar->bits_per_coded_sample == 16 && ast[i]->codecpar->codec_id == AV_CODEC_ID_PCM_U8) + ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codecpar->sample_rate + * ast[i]->codecpar->channels * ast[i]->codecpar->bits_per_coded_sample / 8); } } /* load trees to extradata, they will be unpacked by decoder */ - st->codec->extradata = av_mallocz(smk->treesize + 16 + - FF_INPUT_BUFFER_PADDING_SIZE); - st->codec->extradata_size = smk->treesize + 16; - if(!st->codec->extradata){ + st->codecpar->extradata = av_mallocz(smk->treesize + 16 + + AV_INPUT_BUFFER_PADDING_SIZE); + st->codecpar->extradata_size = smk->treesize + 16; + if (!st->codecpar->extradata) { av_log(s, AV_LOG_ERROR, "Cannot allocate %"PRIu32" bytes of extradata\n", smk->treesize + 16); @@ -223,16 +223,16 @@ static int smacker_read_header(AVFormatContext *s) av_free(smk->frm_flags); return -1; } - ret = avio_read(pb, st->codec->extradata + 16, st->codec->extradata_size - 16); - if(ret != st->codec->extradata_size - 16){ + ret = avio_read(pb, st->codecpar->extradata + 16, st->codecpar->extradata_size - 16); + if(ret != st->codecpar->extradata_size - 16){ av_free(smk->frm_size); av_free(smk->frm_flags); return AVERROR(EIO); } - ((int32_t*)st->codec->extradata)[0] = av_le2ne32(smk->mmap_size); - ((int32_t*)st->codec->extradata)[1] = av_le2ne32(smk->mclr_size); - ((int32_t*)st->codec->extradata)[2] = av_le2ne32(smk->full_size); - ((int32_t*)st->codec->extradata)[3] = av_le2ne32(smk->type_size); + ((int32_t*)st->codecpar->extradata)[0] = av_le2ne32(smk->mmap_size); + ((int32_t*)st->codecpar->extradata)[1] = av_le2ne32(smk->mclr_size); + ((int32_t*)st->codecpar->extradata)[2] = av_le2ne32(smk->full_size); + ((int32_t*)st->codecpar->extradata)[3] = av_le2ne32(smk->type_size); smk->curstream = -1; smk->nextpos = avio_tell(pb); diff --git a/libavformat/smjpegdec.c b/libavformat/smjpegdec.c index a9ed28e..bc69c89 100644 --- a/libavformat/smjpegdec.c +++ b/libavformat/smjpegdec.c @@ -88,13 +88,13 @@ static int smjpeg_read_header(AVFormatContext *s) ast = avformat_new_stream(s, 0); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->sample_rate = avio_rb16(pb); - ast->codec->bits_per_coded_sample = avio_r8(pb); - ast->codec->channels = avio_r8(pb); - ast->codec->codec_tag = avio_rl32(pb); - ast->codec->codec_id = ff_codec_get_id(ff_codec_smjpeg_audio_tags, - ast->codec->codec_tag); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->sample_rate = avio_rb16(pb); + ast->codecpar->bits_per_coded_sample = avio_r8(pb); + ast->codecpar->channels = avio_r8(pb); + ast->codecpar->codec_tag = avio_rl32(pb); + ast->codecpar->codec_id = ff_codec_get_id(ff_codec_smjpeg_audio_tags, + ast->codecpar->codec_tag); ast->duration = duration; sc->audio_stream_index = ast->index; avpriv_set_pts_info(ast, 32, 1, 1000); @@ -112,12 +112,12 @@ static int smjpeg_read_header(AVFormatContext *s) vst = avformat_new_stream(s, 0); if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->width = avio_rb16(pb); - vst->codec->height = avio_rb16(pb); - vst->codec->codec_tag = avio_rl32(pb); - vst->codec->codec_id = ff_codec_get_id(ff_codec_smjpeg_video_tags, - vst->codec->codec_tag); + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->width = avio_rb16(pb); + vst->codecpar->height = avio_rb16(pb); + vst->codecpar->codec_tag = avio_rl32(pb); + vst->codecpar->codec_id = ff_codec_get_id(ff_codec_smjpeg_video_tags, + vst->codecpar->codec_tag); vst->duration = duration; sc->video_stream_index = vst->index; avpriv_set_pts_info(vst, 32, 1, 1000); diff --git a/libavformat/smjpegenc.c b/libavformat/smjpegenc.c index 551af89..2a95059 100644 --- a/libavformat/smjpegenc.c +++ b/libavformat/smjpegenc.c @@ -56,22 +56,22 @@ static int smjpeg_write_header(AVFormatContext *s) for (n = 0; n < s->nb_streams; n++) { AVStream *st = s->streams[n]; - AVCodecContext *codec = st->codec; - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { - tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, codec->codec_id); + AVCodecParameters *par = st->codecpar; + if (par->codec_type == AVMEDIA_TYPE_AUDIO) { + tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, par->codec_id); if (!tag) { av_log(s, AV_LOG_ERROR, "unsupported audio codec\n"); return AVERROR(EINVAL); } avio_wl32(pb, SMJPEG_SND); avio_wb32(pb, 8); - avio_wb16(pb, codec->sample_rate); - avio_w8(pb, av_get_bits_per_sample(codec->codec_id)); - avio_w8(pb, codec->channels); + avio_wb16(pb, par->sample_rate); + avio_w8(pb, av_get_bits_per_sample(par->codec_id)); + avio_w8(pb, par->channels); avio_wl32(pb, tag); avpriv_set_pts_info(st, 32, 1, 1000); - } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { - tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, codec->codec_id); + } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { + tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, par->codec_id); if (!tag) { av_log(s, AV_LOG_ERROR, "unsupported video codec\n"); return AVERROR(EINVAL); @@ -79,8 +79,8 @@ static int smjpeg_write_header(AVFormatContext *s) avio_wl32(pb, SMJPEG_VID); avio_wb32(pb, 12); avio_wb32(pb, 0); - avio_wb16(pb, codec->width); - avio_wb16(pb, codec->height); + avio_wb16(pb, par->width); + avio_wb16(pb, par->height); avio_wl32(pb, tag); avpriv_set_pts_info(st, 32, 1, 1000); } @@ -97,11 +97,11 @@ static int smjpeg_write_packet(AVFormatContext *s, AVPacket *pkt) SMJPEGMuxContext *smc = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[pkt->stream_index]; - AVCodecContext *codec = st->codec; + AVCodecParameters *par = st->codecpar; - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) + if (par->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl32(pb, SMJPEG_SNDD); - else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) + else if (par->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl32(pb, SMJPEG_VIDD); else return 0; diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 137d8fd..065ecc2 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -38,7 +38,7 @@ #include "libavutil/mathematics.h" #include "libavutil/intreadwrite.h" -typedef struct { +typedef struct Fragment { char file[1024]; char infofile[1024]; int64_t start_time, duration; @@ -46,7 +46,7 @@ typedef struct { int64_t start_pos, size; } Fragment; -typedef struct { +typedef struct OutputStream { AVFormatContext *ctx; int ctx_inited; char dirname[1024]; @@ -64,9 +64,11 @@ typedef struct { char *private_str; int packet_size; int audio_tag; + + const URLProtocol **protocols; } OutputStream; -typedef struct { +typedef struct SmoothStreamingContext { const AVClass *class; /* Class for private options. */ int window_size; int extra_window_size; @@ -76,6 +78,8 @@ typedef struct { OutputStream *streams; int has_video, has_audio; int nb_fragments; + + const URLProtocol **protocols; } SmoothStreamingContext; static int ism_write(void *opaque, uint8_t *buf, int buf_size) @@ -121,7 +125,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence) AVDictionary *opts = NULL; os->tail_out = os->out; av_dict_set(&opts, "truncate", "0", 0); - ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_READ_WRITE, &os->ctx->interrupt_callback, &opts); + ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts, + os->protocols, NULL); av_dict_free(&opts); if (ret < 0) { os->out = os->tail_out; @@ -129,7 +134,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence) return ret; } av_dict_set(&opts, "truncate", "0", 0); - ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_READ_WRITE, &os->ctx->interrupt_callback, &opts); + ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts, + os->protocols, NULL); av_dict_free(&opts); ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET); if (os->out2) @@ -143,14 +149,14 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence) static void get_private_data(OutputStream *os) { - AVCodecContext *codec = os->ctx->streams[0]->codec; - uint8_t *ptr = codec->extradata; - int size = codec->extradata_size; + AVCodecParameters *par = os->ctx->streams[0]->codecpar; + uint8_t *ptr = par->extradata; + int size = par->extradata_size; int i; - if (codec->codec_id == AV_CODEC_ID_H264) { + if (par->codec_id == AV_CODEC_ID_H264) { ff_avc_write_annexb_extradata(ptr, &ptr, &size); if (!ptr) - ptr = codec->extradata; + ptr = par->extradata; } if (!ptr) return; @@ -160,7 +166,7 @@ static void get_private_data(OutputStream *os) for (i = 0; i < size; i++) snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]); fail: - if (ptr != codec->extradata) + if (ptr != par->extradata) av_free(ptr); } @@ -168,6 +174,9 @@ static void ism_free(AVFormatContext *s) { SmoothStreamingContext *c = s->priv_data; int i, j; + + av_freep(&c->protocols); + if (!c->streams) return; for (i = 0; i < s->nb_streams; i++) { @@ -220,7 +229,7 @@ static int write_manifest(AVFormatContext *s, int final) snprintf(filename, sizeof(filename), "%s/Manifest", s->filename); snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename); - ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); + ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); return ret; @@ -232,7 +241,7 @@ static int write_manifest(AVFormatContext *s, int final) Fragment *last = os->fragments[os->nb_fragments - 1]; duration = last->start_time + last->duration; } - if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_chunks = os->nb_fragments; video_streams++; } else { @@ -257,10 +266,10 @@ static int write_manifest(AVFormatContext *s, int final) avio_printf(out, "\n", video_streams, video_chunks); for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; - if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO) + if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) continue; last = i; - avio_printf(out, "\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->width, s->streams[i]->codec->height, os->private_str); + avio_printf(out, "\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height, os->private_str); index++; } output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size); @@ -271,10 +280,10 @@ static int write_manifest(AVFormatContext *s, int final) avio_printf(out, "\n", audio_streams, audio_chunks); for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; - if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO) + if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) continue; last = i; - avio_printf(out, "\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->sample_rate, s->streams[i]->codec->channels, os->packet_size, os->audio_tag, os->private_str); + avio_printf(out, "\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, s->streams[i]->codecpar->channels, os->packet_size, os->audio_tag, os->private_str); index++; } output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size); @@ -282,7 +291,7 @@ static int write_manifest(AVFormatContext *s, int final) } avio_printf(out, "\n"); avio_flush(out); - avio_close(out); + ff_format_io_close(s, &out); return ff_rename(temp_filename, filename); } @@ -292,7 +301,10 @@ static int ism_write_header(AVFormatContext *s) int ret = 0, i; AVOutputFormat *oformat; - mkdir(s->filename, 0777); + if (mkdir(s->filename, 0777) == -1 && errno != EEXIST) { + ret = AVERROR(errno); + goto fail; + } oformat = av_guess_format("ismv", NULL, NULL); if (!oformat) { @@ -300,6 +312,12 @@ static int ism_write_header(AVFormatContext *s) goto fail; } + c->protocols = ffurl_get_protocols(s->protocol_whitelist, s->protocol_blacklist); + if (!c->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); if (!c->streams) { ret = AVERROR(ENOMEM); @@ -313,13 +331,18 @@ static int ism_write_header(AVFormatContext *s) AVDictionary *opts = NULL; char buf[10]; - if (!s->streams[i]->codec->bit_rate) { + if (!s->streams[i]->codecpar->bit_rate) { av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i); ret = AVERROR(EINVAL); goto fail; } - snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%d)", s->filename, s->streams[i]->codec->bit_rate); - mkdir(os->dirname, 0777); + snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%d)", s->filename, s->streams[i]->codecpar->bit_rate); + if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) { + ret = AVERROR(errno); + goto fail; + } + + os->protocols = c->protocols; ctx = avformat_alloc_context(); if (!ctx) { @@ -334,8 +357,9 @@ static int ism_write_header(AVFormatContext *s) ret = AVERROR(ENOMEM); goto fail; } - avcodec_copy_context(st->codec, s->streams[i]->codec); + avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->time_base = s->streams[i]->time_base; ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); if (!ctx->pb) { @@ -353,12 +377,12 @@ static int ism_write_header(AVFormatContext *s) avio_flush(ctx->pb); av_dict_free(&opts); s->streams[i]->time_base = st->time_base; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { c->has_video = 1; os->stream_type_tag = "video"; - if (st->codec->codec_id == AV_CODEC_ID_H264) { + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { os->fourcc = "H264"; - } else if (st->codec->codec_id == AV_CODEC_ID_VC1) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_VC1) { os->fourcc = "WVC1"; } else { av_log(s, AV_LOG_ERROR, "Unsupported video codec\n"); @@ -368,10 +392,10 @@ static int ism_write_header(AVFormatContext *s) } else { c->has_audio = 1; os->stream_type_tag = "audio"; - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { os->fourcc = "AACL"; os->audio_tag = 0xff; - } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) { os->fourcc = "WMAP"; os->audio_tag = 0x0162; } else { @@ -379,7 +403,7 @@ static int ism_write_header(AVFormatContext *s) ret = AVERROR(EINVAL); goto fail; } - os->packet_size = st->codec->block_align ? st->codec->block_align : 4; + os->packet_size = st->codecpar->block_align ? st->codecpar->block_align : 4; } get_private_data(os); } @@ -387,6 +411,7 @@ static int ism_write_header(AVFormatContext *s) if (!c->has_video && c->min_frag_duration <= 0) { av_log(s, AV_LOG_WARNING, "no video stream and no min frag duration set\n"); ret = AVERROR(EINVAL); + goto fail; } ret = write_manifest(s, 0); @@ -401,7 +426,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta AVIOContext *in; int ret; uint32_t len; - if ((ret = avio_open2(&in, filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &in, filename, AVIO_FLAG_READ, NULL)) < 0) return ret; ret = AVERROR(EIO); *moof_size = avio_rb32(in); @@ -425,7 +450,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta if (len < 8 || len >= *moof_size) goto fail; if (tag == MKTAG('u','u','i','d')) { - const uint8_t tfxd[] = { + static const uint8_t tfxd[] = { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 }; @@ -442,7 +467,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta avio_seek(in, end, SEEK_SET); } fail: - avio_close(in); + ff_format_io_close(s, &in); return ret; } @@ -478,10 +503,10 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile { AVIOContext *in, *out; int ret = 0; - if ((ret = avio_open2(&in, infile, AVIO_FLAG_READ, &s->interrupt_callback, NULL)) < 0) + if ((ret = s->io_open(s, &in, infile, AVIO_FLAG_READ, NULL)) < 0) return ret; - if ((ret = avio_open2(&out, outfile, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL)) < 0) { - avio_close(in); + if ((ret = s->io_open(s, &out, outfile, AVIO_FLAG_WRITE, NULL)) < 0) { + ff_format_io_close(s, &in); return ret; } while (size > 0) { @@ -496,8 +521,8 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile size -= n; } avio_flush(out); - avio_close(out); - avio_close(in); + ff_format_io_close(s, &out); + ff_format_io_close(s, &in); return ret; } @@ -509,13 +534,14 @@ static int ism_flush(AVFormatContext *s, int final) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; char filename[1024], target_filename[1024], header_filename[1024]; - int64_t start_pos = os->tail_pos, size; + int64_t size; int64_t start_ts, duration, moof_size; if (!os->packets_written) continue; snprintf(filename, sizeof(filename), "%s/temp", os->dirname); - ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); + ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, + c->protocols, NULL); if (ret < 0) break; os->cur_start_pos = os->tail_pos; @@ -527,7 +553,7 @@ static int ism_flush(AVFormatContext *s, int final) ffurl_close(os->out); os->out = NULL; - size = os->tail_pos - start_pos; + size = os->tail_pos - os->cur_start_pos; if ((ret = parse_fragment(s, filename, &start_ts, &duration, &moof_size, size)) < 0) break; snprintf(header_filename, sizeof(header_filename), "%s/FragmentInfo(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts); @@ -571,13 +597,13 @@ static int ism_write_packet(AVFormatContext *s, AVPacket *pkt) SmoothStreamingContext *c = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; OutputStream *os = &c->streams[pkt->stream_index]; - int64_t end_dts = (c->nb_fragments + 1) * c->min_frag_duration; + int64_t end_dts = (c->nb_fragments + 1) * (int64_t) c->min_frag_duration; int ret; if (st->first_dts == AV_NOPTS_VALUE) st->first_dts = pkt->dts; - if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && av_compare_ts(pkt->dts - st->first_dts, st->time_base, end_dts, AV_TIME_BASE_Q) >= 0 && pkt->flags & AV_PKT_FLAG_KEY && os->packets_written) { diff --git a/libavformat/smush.c b/libavformat/smush.c index 1615b45..262b941 100644 --- a/libavformat/smush.c +++ b/libavformat/smush.c @@ -151,23 +151,23 @@ static int smush_read_header(AVFormatContext *ctx) vst->duration = vst->nb_frames = nframes; vst->avg_frame_rate = av_inv_q(vst->time_base); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_SANM; - vst->codec->codec_tag = 0; - vst->codec->width = width; - vst->codec->height = height; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_SANM; + vst->codecpar->codec_tag = 0; + vst->codecpar->width = width; + vst->codecpar->height = height; if (!smush->version) { - av_free(vst->codec->extradata); - vst->codec->extradata_size = 1024 + 2; - vst->codec->extradata = av_malloc(vst->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!vst->codec->extradata) + av_free(vst->codecpar->extradata); + vst->codecpar->extradata_size = 1024 + 2; + vst->codecpar->extradata = av_malloc(vst->codecpar->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!vst->codecpar->extradata) return AVERROR(ENOMEM); - AV_WL16(vst->codec->extradata, subversion); + AV_WL16(vst->codecpar->extradata, subversion); for (i = 0; i < 256; i++) - AV_WL32(vst->codec->extradata + 2 + i * 4, palette[i]); + AV_WL32(vst->codecpar->extradata + 2 + i * 4, palette[i]); } if (got_audio) { @@ -178,13 +178,13 @@ static int smush_read_header(AVFormatContext *ctx) smush->audio_stream_index = ast->index; ast->start_time = 0; - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_ADPCM_VIMA; - ast->codec->codec_tag = 0; - ast->codec->sample_rate = sample_rate; - ast->codec->channels = channels; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_VIMA; + ast->codecpar->codec_tag = 0; + ast->codecpar->sample_rate = sample_rate; + ast->codecpar->channels = channels; - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); } return 0; diff --git a/libavformat/sol.c b/libavformat/sol.c index 92599b1..5c7f43d 100644 --- a/libavformat/sol.c +++ b/libavformat/sol.c @@ -50,18 +50,15 @@ static int sol_probe(AVProbeData *p) static enum AVCodecID sol_codec_id(int magic, int type) { - if (magic == 0x0B8D) - { - if (type & SOL_DPCM) return AV_CODEC_ID_SOL_DPCM; - else return AV_CODEC_ID_PCM_U8; - } if (type & SOL_DPCM) - { - if (type & SOL_16BIT) return AV_CODEC_ID_SOL_DPCM; - else if (magic == 0x0C8D) return AV_CODEC_ID_SOL_DPCM; - else return AV_CODEC_ID_SOL_DPCM; - } - if (type & SOL_16BIT) return AV_CODEC_ID_PCM_S16LE; + return AV_CODEC_ID_SOL_DPCM; + + if (magic == 0x0B8D) + return AV_CODEC_ID_PCM_U8; + + if (type & SOL_16BIT) + return AV_CODEC_ID_PCM_S16LE; + return AV_CODEC_ID_PCM_U8; } @@ -113,13 +110,13 @@ static int sol_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return -1; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = id; - st->codec->codec_id = codec; - st->codec->channels = channels; - st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = rate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = id; + st->codecpar->codec_id = codec; + st->codecpar->channels = channels; + st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = rate; avpriv_set_pts_info(st, 64, 1, rate); return 0; } diff --git a/libavformat/soxdec.c b/libavformat/soxdec.c index ec94675..ee3d1dc 100644 --- a/libavformat/soxdec.c +++ b/libavformat/soxdec.c @@ -55,21 +55,21 @@ static int sox_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; if (avio_rl32(pb) == SOX_TAG) { - st->codec->codec_id = AV_CODEC_ID_PCM_S32LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; header_size = avio_rl32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rl64(pb)); - st->codec->channels = avio_rl32(pb); + st->codecpar->channels = avio_rl32(pb); comment_size = avio_rl32(pb); } else { - st->codec->codec_id = AV_CODEC_ID_PCM_S32BE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; header_size = avio_rb32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rb64(pb)); - st->codec->channels = avio_rb32(pb); + st->codecpar->channels = avio_rb32(pb); comment_size = avio_rb32(pb); } @@ -90,7 +90,7 @@ static int sox_read_header(AVFormatContext *s) sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size - || st->codec->channels > 65535) /* Reserve top 16 bits */ { + || st->codecpar->channels > 65535) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return -1; } @@ -109,15 +109,15 @@ static int sox_read_header(AVFormatContext *s) avio_skip(pb, header_size - SOX_FIXED_HDR - comment_size); - st->codec->sample_rate = sample_rate; - st->codec->bits_per_coded_sample = 32; - st->codec->bit_rate = st->codec->sample_rate * - st->codec->bits_per_coded_sample * - st->codec->channels; - st->codec->block_align = st->codec->bits_per_coded_sample * - st->codec->channels / 8; + st->codecpar->sample_rate = sample_rate; + st->codecpar->bits_per_coded_sample = 32; + st->codecpar->bit_rate = st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample * + st->codecpar->channels; + st->codecpar->block_align = st->codecpar->bits_per_coded_sample * + st->codecpar->channels / 8; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; } @@ -132,7 +132,7 @@ static int sox_read_packet(AVFormatContext *s, if (s->pb->eof_reached) return AVERROR_EOF; - size = SOX_SAMPLES*s->streams[0]->codec->block_align; + size = SOX_SAMPLES*s->streams[0]->codecpar->block_align; ret = av_get_packet(s->pb, pkt, size); if (ret < 0) return AVERROR(EIO); diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c index 4b8955c..ea05f36 100644 --- a/libavformat/soxenc.c +++ b/libavformat/soxenc.c @@ -36,7 +36,7 @@ #include "avio_internal.h" #include "sox.h" -typedef struct { +typedef struct SoXContext { int64_t header_size; } SoXContext; @@ -44,7 +44,7 @@ static int sox_write_header(AVFormatContext *s) { SoXContext *sox = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; AVDictionaryEntry *comment; size_t comment_len = 0, comment_size; @@ -55,19 +55,19 @@ static int sox_write_header(AVFormatContext *s) sox->header_size = SOX_FIXED_HDR + comment_size; - if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) { + if (par->codec_id == AV_CODEC_ID_PCM_S32LE) { ffio_wfourcc(pb, ".SoX"); avio_wl32(pb, sox->header_size); avio_wl64(pb, 0); /* number of samples */ - avio_wl64(pb, av_double2int(enc->sample_rate)); - avio_wl32(pb, enc->channels); + avio_wl64(pb, av_double2int(par->sample_rate)); + avio_wl32(pb, par->channels); avio_wl32(pb, comment_size); - } else if (enc->codec_id == AV_CODEC_ID_PCM_S32BE) { + } else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) { ffio_wfourcc(pb, "XoS."); avio_wb32(pb, sox->header_size); avio_wb64(pb, 0); /* number of samples */ - avio_wb64(pb, av_double2int(enc->sample_rate)); - avio_wb32(pb, enc->channels); + avio_wb64(pb, av_double2int(par->sample_rate)); + avio_wb32(pb, par->channels); avio_wb32(pb, comment_size); } else { av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n"); @@ -96,14 +96,14 @@ static int sox_write_trailer(AVFormatContext *s) { SoXContext *sox = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; if (s->pb->seekable) { /* update number of samples */ int64_t file_size = avio_tell(pb); int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL; avio_seek(pb, 8, SEEK_SET); - if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) { + if (par->codec_id == AV_CODEC_ID_PCM_S32LE) { avio_wl64(pb, num_samples); } else avio_wb64(pb, num_samples); diff --git a/libavformat/spdif.h b/libavformat/spdif.h index f5b15eb..5ebfd91 100644 --- a/libavformat/spdif.h +++ b/libavformat/spdif.h @@ -53,8 +53,8 @@ enum IEC61937DataType { static const uint16_t spdif_mpeg_pkt_offset[2][3] = { //LAYER1 LAYER2 LAYER3 - { 3072, 9216, 4608 }, // MPEG2 LSF - { 1536, 4608, 4608 }, // MPEG1 + { 3072, 9216, 4608 }, // MPEG-2 LSF + { 1536, 4608, 4608 }, // MPEG-1 }; void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w); diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c index 2fb9477..7c21235 100644 --- a/libavformat/spdifdec.c +++ b/libavformat/spdifdec.c @@ -188,7 +188,7 @@ static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR_EOF; } ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); @@ -196,7 +196,7 @@ static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt) ret = spdif_get_offset_and_codec(s, data_type, pkt->data, &offset, &codec_id); if (ret) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } @@ -207,20 +207,20 @@ static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt) /* first packet, create a stream */ AVStream *st = avformat_new_stream(s, NULL); if (!st) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = codec_id; - } else if (codec_id != s->streams[0]->codec->codec_id) { + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = codec_id; + } else if (codec_id != s->streams[0]->codecpar->codec_id) { avpriv_report_missing_feature(s, "Codec change in IEC 61937"); return AVERROR_PATCHWELCOME; } - if (!s->bit_rate && s->streams[0]->codec->sample_rate) + if (!s->bit_rate && s->streams[0]->codecpar->sample_rate) /* stream bitrate matches 16-bit stereo PCM bitrate for currently supported codecs */ - s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate; + s->bit_rate = 2 * 16 * s->streams[0]->codecpar->sample_rate; return 0; } diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index f3acf48..a19bcab 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -32,7 +32,7 @@ /* * Terminology used in specification: * data-burst - IEC61937 frame, contains header and encapsuled frame - * burst-preambule - IEC61937 frame header, contains 16-bits words named Pa, Pb, Pc and Pd + * burst-preamble - IEC61937 frame header, contains 16-bit words named Pa, Pb, Pc and Pd * burst-payload - encapsuled frame * Pa, Pb - syncword - 0xF872, 0x4E1F * Pc - burst-info, contains data-type (bits 0-6), error flag (bit 7), data-type-dependent info (bits 8-12) @@ -51,6 +51,7 @@ #include "spdif.h" #include "libavcodec/ac3.h" #include "libavcodec/dca.h" +#include "libavcodec/dca_syncwords.h" #include "libavcodec/aacadtsdec.h" #include "libavutil/opt.h" @@ -146,7 +147,7 @@ static int spdif_header_eac3(AVFormatContext *s, AVPacket *pkt) * DTS type IV (DTS-HD) can be transmitted with various frame repetition * periods; longer repetition periods allow for longer packets and therefore * higher bitrate. Longer repetition periods mean that the constant bitrate of - * the outputted IEC 61937 stream is higher. + * the output IEC 61937 stream is higher. * The repetition period is measured in IEC 60958 frames (4 bytes). */ static int spdif_dts4_subtype(int period) @@ -251,25 +252,25 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) return AVERROR_INVALIDDATA; switch (syncword_dts) { - case DCA_MARKER_RAW_BE: + case DCA_SYNCWORD_CORE_BE: blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f; core_size = ((AV_RB24(pkt->data + 5) >> 4) & 0x3fff) + 1; sample_rate = avpriv_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; break; - case DCA_MARKER_RAW_LE: + case DCA_SYNCWORD_CORE_LE: blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f; ctx->extra_bswap = 1; break; - case DCA_MARKER_14B_BE: + case DCA_SYNCWORD_CORE_14B_BE: blocks = (((pkt->data[5] & 0x07) << 4) | ((pkt->data[6] & 0x3f) >> 2)); break; - case DCA_MARKER_14B_LE: + case DCA_SYNCWORD_CORE_14B_LE: blocks = (((pkt->data[4] & 0x07) << 4) | ((pkt->data[7] & 0x3f) >> 2)); ctx->extra_bswap = 1; break; - case DCA_HD_MARKER: + case DCA_SYNCWORD_SUBSTREAM: /* We only handle HD frames that are paired with core. However, sometimes DTS-HD streams with core have a stray HD frame without core in the beginning of the stream. */ @@ -318,8 +319,8 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) static const enum IEC61937DataType mpeg_data_type[2][3] = { // LAYER1 LAYER2 LAYER3 - { IEC61937_MPEG2_LAYER1_LSF, IEC61937_MPEG2_LAYER2_LSF, IEC61937_MPEG2_LAYER3_LSF },//MPEG2 LSF - { IEC61937_MPEG1_LAYER1, IEC61937_MPEG1_LAYER23, IEC61937_MPEG1_LAYER23 }, //MPEG1 + { IEC61937_MPEG2_LAYER1_LSF, IEC61937_MPEG2_LAYER2_LSF, IEC61937_MPEG2_LAYER3_LSF }, // MPEG-2 LSF + { IEC61937_MPEG1_LAYER1, IEC61937_MPEG1_LAYER23, IEC61937_MPEG1_LAYER23 }, // MPEG-1 }; static int spdif_header_mpeg(AVFormatContext *s, AVPacket *pkt) @@ -397,15 +398,15 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt) { IEC61937Context *ctx = s->priv_data; int mat_code_length = 0; - const char mat_end_code[16] = { 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11 }; + static const char mat_end_code[16] = { 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11 }; if (!ctx->hd_buf_count) { - const char mat_start_code[20] = { 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, 0x49, 0x80, 0x77, 0xE0 }; + static const char mat_start_code[20] = { 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, 0x49, 0x80, 0x77, 0xE0 }; mat_code_length = sizeof(mat_start_code) + BURST_HEADER_SIZE; memcpy(ctx->hd_buf, mat_start_code, sizeof(mat_start_code)); } else if (ctx->hd_buf_count == 12) { - const char mat_middle_code[12] = { 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0 }; + static const char mat_middle_code[12] = { 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0 }; mat_code_length = sizeof(mat_middle_code) + MAT_MIDDLE_CODE_OFFSET; memcpy(&ctx->hd_buf[12 * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + MAT_MIDDLE_CODE_OFFSET], mat_middle_code, sizeof(mat_middle_code)); @@ -443,7 +444,7 @@ static int spdif_write_header(AVFormatContext *s) { IEC61937Context *ctx = s->priv_data; - switch (s->streams[0]->codec->codec_id) { + switch (s->streams[0]->codecpar->codec_id) { case AV_CODEC_ID_AC3: ctx->header_info = spdif_header_ac3; break; @@ -524,7 +525,7 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (ctx->extra_bswap ^ (ctx->spdif_flags & SPDIF_FLAG_BIGENDIAN)) { avio_write(s->pb, ctx->out_buf, ctx->out_bytes & ~1); } else { - av_fast_malloc(&ctx->buffer, &ctx->buffer_size, ctx->out_bytes + FF_INPUT_BUFFER_PADDING_SIZE); + av_fast_malloc(&ctx->buffer, &ctx->buffer_size, ctx->out_bytes + AV_INPUT_BUFFER_PADDING_SIZE); if (!ctx->buffer) return AVERROR(ENOMEM); ff_spdif_bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)ctx->out_buf, ctx->out_bytes >> 1); diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c index 9db5133..6f8206c 100644 --- a/libavformat/srtdec.c +++ b/libavformat/srtdec.c @@ -46,8 +46,8 @@ static int srt_read_header(AVFormatContext *s) if (!st) return -1; avpriv_set_pts_info(st, 64, 1, 1000); - st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = AV_CODEC_ID_SRT; + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_SRT; return 0; } diff --git a/libavformat/srtp.c b/libavformat/srtp.c index 6659bfc..e054fcc 100644 --- a/libavformat/srtp.c +++ b/libavformat/srtp.c @@ -323,150 +323,3 @@ int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, len += hmac_size; return buf + len - out; } - -#ifdef TEST -#include - -static const char *aes128_80_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; - -static const uint8_t rtp_aes128_80[] = { - // RTP header - 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0x62, 0x69, 0x76, 0xca, 0xc5, - // HMAC - 0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99, -}; - -static const uint8_t rtcp_aes128_80[] = { - // RTCP header - 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda, - 0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35, - // RTCP index - 0x80, 0x00, 0x00, 0x03, - // HMAC - 0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde, -}; - -static const char *aes128_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; - -static const uint8_t rtp_aes128_32[] = { - // RTP header - 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0x62, 0x69, 0x76, 0xca, 0xc5, - // HMAC - 0xa1, 0xac, 0x1b, 0xb4, -}; - -static const uint8_t rtcp_aes128_32[] = { - // RTCP header - 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b, - 0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34, - // RTCP index - 0x80, 0x00, 0x00, 0x04, - // HMAC - 0x5b, 0xd2, 0xa9, 0x9d, -}; - -static const char *aes128_80_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; - -static const uint8_t rtp_aes128_80_32[] = { - // RTP header - 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0x62, 0x69, 0x76, 0xca, 0xc5, - // HMAC - 0xa1, 0xac, 0x1b, 0xb4, -}; - -static const uint8_t rtcp_aes128_80_32[] = { - // RTCP header - 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, - // encrypted payload - 0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53, - 0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9, - // RTCP index - 0x80, 0x00, 0x00, 0x05, - // HMAC - 0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10, -}; - -static void print_data(const uint8_t *buf, int len) -{ - int i; - for (i = 0; i < len; i++) - printf("%02x", buf[i]); - printf("\n"); -} - -static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len, - uint8_t *out) -{ - memcpy(out, in, len); - if (!ff_srtp_decrypt(srtp, out, &len)) { - print_data(out, len); - return len; - } else - return -1; -} - -static void test_encrypt(const uint8_t *data, int in_len, const char *suite, - const char *key) -{ - struct SRTPContext enc = { 0 }, dec = { 0 }; - int len; - char buf[RTP_MAX_PACKET_LENGTH]; - ff_srtp_set_crypto(&enc, suite, key); - ff_srtp_set_crypto(&dec, suite, key); - len = ff_srtp_encrypt(&enc, data, in_len, buf, sizeof(buf)); - if (!ff_srtp_decrypt(&dec, buf, &len)) { - if (len == in_len && !memcmp(buf, data, len)) - printf("Decrypted content matches input\n"); - else - printf("Decrypted content doesn't match input\n"); - } else { - printf("Decryption failed\n"); - } - ff_srtp_free(&enc); - ff_srtp_free(&dec); -} - -int main(void) -{ - static const char *aes128_80_suite = "AES_CM_128_HMAC_SHA1_80"; - static const char *aes128_32_suite = "AES_CM_128_HMAC_SHA1_32"; - static const char *aes128_80_32_suite = "SRTP_AES128_CM_HMAC_SHA1_32"; - static const char *test_key = "abcdefghijklmnopqrstuvwxyz1234567890ABCD"; - uint8_t buf[RTP_MAX_PACKET_LENGTH]; - struct SRTPContext srtp = { 0 }; - int len; - ff_srtp_set_crypto(&srtp, aes128_80_suite, aes128_80_key); - len = test_decrypt(&srtp, rtp_aes128_80, sizeof(rtp_aes128_80), buf); - test_encrypt(buf, len, aes128_80_suite, test_key); - test_encrypt(buf, len, aes128_32_suite, test_key); - test_encrypt(buf, len, aes128_80_32_suite, test_key); - test_decrypt(&srtp, rtcp_aes128_80, sizeof(rtcp_aes128_80), buf); - test_encrypt(buf, len, aes128_80_suite, test_key); - test_encrypt(buf, len, aes128_32_suite, test_key); - test_encrypt(buf, len, aes128_80_32_suite, test_key); - ff_srtp_free(&srtp); - - memset(&srtp, 0, sizeof(srtp)); // Clear the context - ff_srtp_set_crypto(&srtp, aes128_32_suite, aes128_32_key); - test_decrypt(&srtp, rtp_aes128_32, sizeof(rtp_aes128_32), buf); - test_decrypt(&srtp, rtcp_aes128_32, sizeof(rtcp_aes128_32), buf); - ff_srtp_free(&srtp); - - memset(&srtp, 0, sizeof(srtp)); // Clear the context - ff_srtp_set_crypto(&srtp, aes128_80_32_suite, aes128_80_32_key); - test_decrypt(&srtp, rtp_aes128_80_32, sizeof(rtp_aes128_80_32), buf); - test_decrypt(&srtp, rtcp_aes128_80_32, sizeof(rtcp_aes128_80_32), buf); - ff_srtp_free(&srtp); - return 0; -} -#endif /* TEST */ diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c index f9b94d7..e6e035a 100644 --- a/libavformat/srtpproto.c +++ b/libavformat/srtpproto.c @@ -42,8 +42,8 @@ typedef struct SRTPProtoContext { static const AVOption options[] = { { "srtp_out_suite", "", offsetof(SRTPProtoContext, out_suite), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "srtp_out_params", "", offsetof(SRTPProtoContext, out_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, - { "srtp_in_suite", "", offsetof(SRTPProtoContext, in_suite), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, - { "srtp_in_params", "", offsetof(SRTPProtoContext, in_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, + { "srtp_in_suite", "", offsetof(SRTPProtoContext, in_suite), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, + { "srtp_in_params", "", offsetof(SRTPProtoContext, in_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, { NULL } }; @@ -80,7 +80,8 @@ static int srtp_open(URLContext *h, const char *uri, int flags) av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path); - if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL)) < 0) + if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols, h)) < 0) goto fail; h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size, @@ -131,7 +132,7 @@ static int srtp_get_multi_file_handle(URLContext *h, int **handles, return ffurl_get_multi_file_handle(s->rtp_hd, handles, numhandles); } -URLProtocol ff_srtp_protocol = { +const URLProtocol ff_srtp_protocol = { .name = "srtp", .url_open = srtp_open, .url_read = srtp_read, diff --git a/libavformat/swf.h b/libavformat/swf.h index 8eb3f70..9b90251 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -23,6 +23,12 @@ #ifndef AVFORMAT_SWF_H #define AVFORMAT_SWF_H +#include "config.h" + +#if CONFIG_ZLIB +#include +#endif + #include "libavutil/fifo.h" #include "avformat.h" #include "avio.h" @@ -61,9 +67,6 @@ #define VIDEO_ID 0 #define SHAPE_ID 1 -#undef NDEBUG -#include - typedef struct SWFContext { int64_t duration_pos; int64_t tag_pos; @@ -75,8 +78,15 @@ typedef struct SWFContext { int frame_rate; int tag; AVFifoBuffer *audio_fifo; - AVCodecContext *audio_enc, *video_enc; + AVCodecParameters *audio_par, *video_par; AVStream *video_st; +#if CONFIG_ZLIB +#define ZBUF_SIZE 4096 + AVIOContext *zpb; + uint8_t *zbuf_in; + uint8_t *zbuf_out; + z_stream zstream; +#endif } SWFContext; extern const AVCodecTag ff_swf_codec_tags[]; diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index d7a5314..7bb67de 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -20,6 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + +#if CONFIG_ZLIB +#include +#endif + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "swf.h" @@ -61,6 +67,39 @@ static int swf_probe(AVProbeData *p) return 0; } +#if CONFIG_ZLIB +static int zlib_refill(void *opaque, uint8_t *buf, int buf_size) +{ + AVFormatContext *s = opaque; + SWFContext *swf = s->priv_data; + z_stream *z = &swf->zstream; + int ret; + +retry: + if (!z->avail_in) { + int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE); + if (n < 0) + return n; + z->next_in = swf->zbuf_in; + z->avail_in = n; + } + + z->next_out = buf; + z->avail_out = buf_size; + + ret = inflate(z, Z_NO_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + av_log(s, AV_LOG_ERROR, "Inflate error: %d\n", ret); + return AVERROR_UNKNOWN; + } + + if (buf_size - z->avail_out == 0) + goto retry; + + return buf_size - z->avail_out; +} +#endif + static int swf_read_header(AVFormatContext *s) { SWFContext *swf = s->priv_data; @@ -68,14 +107,33 @@ static int swf_read_header(AVFormatContext *s) int nbits, len, tag; tag = avio_rb32(pb) & 0xffffff00; + avio_rl32(pb); if (tag == MKBETAG('C', 'W', 'S', 0)) { - av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n"); + av_log(s, AV_LOG_INFO, "Compressed SWF file detected\n"); +#if CONFIG_ZLIB + if (inflateInit(&swf->zstream) != Z_OK) { + av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n"); + return AVERROR(EINVAL); + } + swf->zbuf_in = av_malloc(ZBUF_SIZE); + swf->zbuf_out = av_malloc(ZBUF_SIZE); + swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s, + zlib_refill, NULL, NULL); + if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb) { + av_freep(&swf->zbuf_in); + av_freep(&swf->zbuf_out); + av_freep(&swf->zpb); + return AVERROR(ENOMEM); + } + swf->zpb->seekable = 0; + pb = swf->zpb; +#else + av_log(s, AV_LOG_ERROR, "missing zlib support, unable to open\n"); return AVERROR(EIO); - } - if (tag != MKBETAG('F', 'W', 'S', 0)) +#endif + } else if (tag != MKBETAG('F', 'W', 'S', 0)) return AVERROR(EIO); - avio_rl32(pb); /* skip rectangle size */ nbits = avio_r8(pb) >> 3; len = (4 * nbits - 3 + 7) / 8; @@ -95,6 +153,11 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) AVStream *vst = NULL, *ast = NULL, *st = 0; int tag, len, i, frame, v, res; +#if CONFIG_ZLIB + if (swf->zpb) + pb = swf->zpb; +#endif + for(;;) { uint64_t pos = avio_tell(pb); tag = get_swf_tag(pb, &len); @@ -110,7 +173,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) for (i=0; inb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) goto skip; } @@ -123,8 +186,8 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) if (!vst) return -1; vst->id = ch_id; - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb)); + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb)); avpriv_set_pts_info(vst, 16, 256, swf->frame_rate); len -= 8; } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) { @@ -133,7 +196,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) for (i=0; inb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) goto skip; } @@ -145,25 +208,25 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) return -1; ast->id = -1; /* -1 to avoid clash with video stream ch_id */ if (v & 1) { - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15); ast->need_parsing = AVSTREAM_PARSE_FULL; sample_rate_code= (v>>2) & 3; - ast->codec->sample_rate = 44100 >> (3 - sample_rate_code); - avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate); + ast->codecpar->sample_rate = 44100 >> (3 - sample_rate_code); + avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); len -= 4; } else if (tag == TAG_VIDEOFRAME) { int ch_id = avio_rl16(pb); len -= 2; for(i=0; inb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) { frame = avio_rl16(pb); len -= 2; if (len <= 0) @@ -179,8 +242,8 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) } else if (tag == TAG_STREAMBLOCK) { for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) { - if (st->codec->codec_id == AV_CODEC_ID_MP3) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) { + if (st->codecpar->codec_id == AV_CODEC_ID_MP3) { avio_skip(pb, 4); len -= 4; if (len <= 0) @@ -201,7 +264,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) } else if (tag == TAG_JPEG2) { for (i=0; inb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2) + if (st->codecpar->codec_id == AV_CODEC_ID_MJPEG && st->id == -2) break; } if (i == s->nb_streams) { @@ -209,8 +272,8 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) if (!vst) return -1; vst->id = -2; /* -2 to avoid clash with video stream and audio stream */ - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_MJPEG; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_MJPEG; avpriv_set_pts_info(vst, 64, 256, swf->frame_rate); st = vst; } @@ -240,6 +303,18 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) } } +#if CONFIG_ZLIB +static av_cold int swf_read_close(AVFormatContext *avctx) +{ + SWFContext *s = avctx->priv_data; + inflateEnd(&s->zstream); + av_freep(&s->zbuf_in); + av_freep(&s->zbuf_out); + av_freep(&s->zpb); + return 0; +} +#endif + AVInputFormat ff_swf_demuxer = { .name = "swf", .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"), @@ -247,4 +322,7 @@ AVInputFormat ff_swf_demuxer = { .read_probe = swf_probe, .read_header = swf_read_header, .read_packet = swf_read_packet, +#if CONFIG_ZLIB + .read_close = swf_read_close, +#endif }; diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index a1fc7b3..f8db3e9 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -184,14 +184,14 @@ static int swf_write_header(AVFormatContext *s) swf->video_frame_number = 0; for(i=0;inb_streams;i++) { - AVCodecContext *enc = s->streams[i]->codec; - if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { - if (swf->audio_enc) { + AVCodecParameters *par = s->streams[i]->codecpar; + if (par->codec_type == AVMEDIA_TYPE_AUDIO) { + if (swf->audio_par) { av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 audio stream\n"); return AVERROR_INVALIDDATA; } - if (enc->codec_id == AV_CODEC_ID_MP3) { - swf->audio_enc = enc; + if (par->codec_id == AV_CODEC_ID_MP3) { + swf->audio_par = par; swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE); if (!swf->audio_fifo) return AVERROR(ENOMEM); @@ -200,15 +200,15 @@ static int swf_write_header(AVFormatContext *s) return -1; } } else { - if (swf->video_enc) { + if (swf->video_par) { av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 video stream\n"); return AVERROR_INVALIDDATA; } - if (enc->codec_id == AV_CODEC_ID_VP6F || - enc->codec_id == AV_CODEC_ID_FLV1 || - enc->codec_id == AV_CODEC_ID_MJPEG) { + if (par->codec_id == AV_CODEC_ID_VP6F || + par->codec_id == AV_CODEC_ID_FLV1 || + par->codec_id == AV_CODEC_ID_MJPEG) { swf->video_st = s->streams[i]; - swf->video_enc = enc; + swf->video_par = par; } else { av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); return -1; @@ -216,32 +216,32 @@ static int swf_write_header(AVFormatContext *s) } } - if (!swf->video_enc) { + if (!swf->video_par) { /* currently, cannot work correctly if audio only */ width = 320; height = 200; rate = 10; rate_base= 1; } else { - width = swf->video_enc->width; - height = swf->video_enc->height; + width = swf->video_par->width; + height = swf->video_par->height; // TODO: should be avg_frame_rate rate = swf->video_st->time_base.den; rate_base = swf->video_st->time_base.num; } - if (!swf->audio_enc) + if (!swf->audio_par) swf->samples_per_frame = (44100.0 * rate_base) / rate; else - swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate; + swf->samples_per_frame = (swf->audio_par->sample_rate * rate_base) / rate; avio_write(pb, "FWS", 3); if (!strcmp("avm2", s->oformat->name)) version = 9; - else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_VP6F) + else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_VP6F) version = 8; /* version 8 and above support VP6 codec */ - else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_FLV1) + else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLV1) version = 6; /* version 6 and above support FLV1 codec */ else version = 4; /* version 4 for mpeg audio support */ @@ -263,7 +263,7 @@ static int swf_write_header(AVFormatContext *s) } /* define a shape with the jpeg inside */ - if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_MJPEG) { + if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_MJPEG) { put_swf_tag(s, TAG_DEFINESHAPE); avio_wl16(pb, SHAPE_ID); /* ID of shape */ @@ -306,12 +306,12 @@ static int swf_write_header(AVFormatContext *s) put_swf_end_tag(s); } - if (swf->audio_enc && swf->audio_enc->codec_id == AV_CODEC_ID_MP3) { + if (swf->audio_par && swf->audio_par->codec_id == AV_CODEC_ID_MP3) { int v = 0; /* start sound */ put_swf_tag(s, TAG_STREAMHEAD2); - switch(swf->audio_enc->sample_rate) { + switch(swf->audio_par->sample_rate) { case 11025: v |= 1 << 2; break; case 22050: v |= 2 << 2; break; case 44100: v |= 3 << 2; break; @@ -321,7 +321,7 @@ static int swf_write_header(AVFormatContext *s) return -1; } v |= 0x02; /* 16 bit playback */ - if (swf->audio_enc->channels == 2) + if (swf->audio_par->channels == 2) v |= 0x01; /* stereo playback */ avio_w8(s->pb, v); v |= 0x20; /* mp3 compressed */ @@ -337,27 +337,27 @@ static int swf_write_header(AVFormatContext *s) } static int swf_write_video(AVFormatContext *s, - AVCodecContext *enc, const uint8_t *buf, int size) + AVCodecParameters *par, const uint8_t *buf, int size) { SWFContext *swf = s->priv_data; AVIOContext *pb = s->pb; /* Flash Player limit */ if (swf->swf_frame_number == 16000) - av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); + av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); - if (enc->codec_id == AV_CODEC_ID_VP6F || - enc->codec_id == AV_CODEC_ID_FLV1) { + if (par->codec_id == AV_CODEC_ID_VP6F || + par->codec_id == AV_CODEC_ID_FLV1) { if (swf->video_frame_number == 0) { /* create a new video object */ put_swf_tag(s, TAG_VIDEOSTREAM); avio_wl16(pb, VIDEO_ID); swf->vframes_pos = avio_tell(pb); avio_wl16(pb, 15000); /* hard flash player limit */ - avio_wl16(pb, enc->width); - avio_wl16(pb, enc->height); + avio_wl16(pb, par->width); + avio_wl16(pb, par->height); avio_w8(pb, 0); - avio_w8(pb,ff_codec_get_tag(ff_swf_codec_tags, enc->codec_id)); + avio_w8(pb,ff_codec_get_tag(ff_swf_codec_tags, par->codec_id)); put_swf_end_tag(s); /* place the video object for the first time */ @@ -385,7 +385,7 @@ static int swf_write_video(AVFormatContext *s, avio_wl16(pb, swf->video_frame_number++); avio_write(pb, buf, size); put_swf_end_tag(s); - } else if (enc->codec_id == AV_CODEC_ID_MJPEG) { + } else if (par->codec_id == AV_CODEC_ID_MJPEG) { if (swf->swf_frame_number > 0) { /* remove the shape */ put_swf_tag(s, TAG_REMOVEOBJECT); @@ -422,12 +422,13 @@ static int swf_write_video(AVFormatContext *s, swf->swf_frame_number++; /* streaming sound always should be placed just before showframe tags */ - if (swf->audio_enc && av_fifo_size(swf->audio_fifo)) { + if (swf->audio_par && av_fifo_size(swf->audio_fifo)) { int frame_size = av_fifo_size(swf->audio_fifo); put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG); avio_wl16(pb, swf->sound_samples); avio_wl16(pb, 0); // seek samples - av_fifo_generic_read(swf->audio_fifo, pb, frame_size, &avio_write); + av_fifo_generic_read(swf->audio_fifo, pb, frame_size, + (void (*)(void *, void *, int)) &avio_write); put_swf_end_tag(s); /* update FIFO */ @@ -442,13 +443,13 @@ static int swf_write_video(AVFormatContext *s, } static int swf_write_audio(AVFormatContext *s, - AVCodecContext *enc, uint8_t *buf, int size) + AVCodecParameters *par, uint8_t *buf, int size) { SWFContext *swf = s->priv_data; /* Flash Player limit */ if (swf->swf_frame_number == 16000) - av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); + av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); if (av_fifo_size(swf->audio_fifo) + size > AUDIO_FIFO_SIZE) { av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n"); @@ -456,36 +457,36 @@ static int swf_write_audio(AVFormatContext *s, } av_fifo_generic_write(swf->audio_fifo, buf, size, NULL); - swf->sound_samples += av_get_audio_frame_duration(enc, size); + swf->sound_samples += av_get_audio_frame_duration2(par, size); /* if audio only stream make sure we add swf frames */ - if (!swf->video_enc) - swf_write_video(s, enc, 0, 0); + if (!swf->video_par) + swf_write_video(s, par, 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 == AVMEDIA_TYPE_AUDIO) - return swf_write_audio(s, codec, pkt->data, pkt->size); + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + if (par->codec_type == AVMEDIA_TYPE_AUDIO) + return swf_write_audio(s, par, pkt->data, pkt->size); else - return swf_write_video(s, codec, pkt->data, pkt->size); + return swf_write_video(s, par, pkt->data, pkt->size); } static int swf_write_trailer(AVFormatContext *s) { SWFContext *swf = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *enc, *video_enc; + AVCodecParameters *par, *video_par; int file_size, i; - video_enc = NULL; + video_par = NULL; for(i=0;inb_streams;i++) { - enc = s->streams[i]->codec; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) - video_enc = enc; + par = s->streams[i]->codecpar; + if (par->codec_type == AVMEDIA_TYPE_VIDEO) + video_par = par; else av_fifo_free(swf->audio_fifo); } @@ -494,7 +495,7 @@ static int swf_write_trailer(AVFormatContext *s) put_swf_end_tag(s); /* patch file size and number of frames if not streamed */ - if (s->pb->seekable && video_enc) { + if (s->pb->seekable && video_par) { file_size = avio_tell(pb); avio_seek(pb, 4, SEEK_SET); avio_wl32(pb, file_size); diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 584cbcc..b28d44c 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -19,11 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define BITSTREAM_READER_LE #include "libavcodec/tak.h" + +#include "apetag.h" #include "avformat.h" #include "internal.h" #include "rawdec.h" -#include "apetag.h" typedef struct TAKDemuxContext { int mlast_frame; @@ -50,8 +52,8 @@ static int tak_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_TAK; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_TAK; st->need_parsing = AVSTREAM_PARSE_FULL; tc->mlast_frame = 0; @@ -71,7 +73,7 @@ static int tak_read_header(AVFormatContext *s) case TAK_METADATA_STREAMINFO: case TAK_METADATA_LAST_FRAME: case TAK_METADATA_ENCODER: - buffer = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + buffer = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!buffer) return AVERROR(ENOMEM); @@ -119,15 +121,15 @@ static int tak_read_header(AVFormatContext *s) avpriv_tak_parse_streaminfo(&gb, &ti); if (ti.samples > 0) st->duration = ti.samples; - st->codec->bits_per_coded_sample = ti.bps; + st->codecpar->bits_per_coded_sample = ti.bps; if (ti.ch_layout) - st->codec->channel_layout = ti.ch_layout; - st->codec->sample_rate = ti.sample_rate; - st->codec->channels = ti.channels; + st->codecpar->channel_layout = ti.ch_layout; + st->codecpar->sample_rate = ti.sample_rate; + st->codecpar->channels = ti.channels; st->start_time = 0; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - st->codec->extradata = buffer; - st->codec->extradata_size = size; + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + st->codecpar->extradata = buffer; + st->codecpar->extradata_size = size; buffer = NULL; } else if (type == TAK_METADATA_LAST_FRAME) { if (size != 11) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index cbd5142..1498c26 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -20,6 +20,8 @@ */ #include "avformat.h" #include "libavutil/parseutils.h" +#include "libavutil/opt.h" + #include "internal.h" #include "network.h" #include "os_support.h" @@ -29,20 +31,39 @@ #endif typedef struct TCPContext { + const AVClass *class; int fd; + int listen; + int timeout; + int listen_timeout; } TCPContext; +#define OFFSET(x) offsetof(TCPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "listen", "Listen for incoming connections", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "timeout", "Connection timeout (in milliseconds)", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = D|E }, + { "listen_timeout", "Bind timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, .flags = D|E }, + { NULL } +}; + +static const AVClass tcp_class = { + .class_name = "tcp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; - int listen_socket = 0; const char *p; char buf[256]; int ret; - int timeout = 100, listen_timeout = -1; char hostname[1024],proto[1024],path[1024]; char portstr[10]; @@ -57,18 +78,22 @@ static int tcp_open(URLContext *h, const char *uri, int flags) p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) - listen_socket = 1; + s->listen = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { - timeout = strtol(buf, NULL, 10); + s->timeout = strtol(buf, NULL, 10) * 100; } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { - listen_timeout = strtol(buf, NULL, 10); + s->listen_timeout = strtol(buf, NULL, 10); } } + if (!s->timeout) + s->timeout = h->rw_timeout ? h->rw_timeout / 1000 : 10000; + if (h->rw_timeout && s->listen_timeout < 0) + s->listen_timeout = h->rw_timeout / 1000; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); - if (listen_socket) + if (s->listen) hints.ai_flags |= AI_PASSIVE; if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); @@ -92,15 +117,15 @@ static int tcp_open(URLContext *h, const char *uri, int flags) goto fail; } - if (listen_socket) { - if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, - listen_timeout, h)) < 0) { - ret = fd; + if (s->listen) { + if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->listen_timeout, h)) < 0) { goto fail1; } + fd = ret; } else { if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, - timeout * 100, h, !!cur_ai->ai_next)) < 0) { + s->timeout, h, !!cur_ai->ai_next)) < 0) { if (ret == AVERROR_EXIT) goto fail1; @@ -154,7 +179,7 @@ static int tcp_write(URLContext *h, const uint8_t *buf, int size) if (ret < 0) return ret; } - ret = send(s->fd, buf, size, 0); + ret = send(s->fd, buf, size, MSG_NOSIGNAL); return ret < 0 ? ff_neterrno() : ret; } @@ -187,7 +212,7 @@ static int tcp_get_file_handle(URLContext *h) return s->fd; } -URLProtocol ff_tcp_protocol = { +const URLProtocol ff_tcp_protocol = { .name = "tcp", .url_open = tcp_open, .url_read = tcp_read, @@ -197,4 +222,5 @@ URLProtocol ff_tcp_protocol = { .url_shutdown = tcp_shutdown, .priv_data_size = sizeof(TCPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &tcp_class, }; diff --git a/libavformat/tests/.gitignore b/libavformat/tests/.gitignore new file mode 100644 index 0000000..cfd51f2 --- /dev/null +++ b/libavformat/tests/.gitignore @@ -0,0 +1,5 @@ +/movenc +/noproxy +/seek +/srtp +/url diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c new file mode 100644 index 0000000..05432eb --- /dev/null +++ b/libavformat/tests/movenc.c @@ -0,0 +1,748 @@ +/* + * Copyright (c) 2015 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/md5.h" + +#include "libavformat/avformat.h" + +#if HAVE_UNISTD_H +#include +#endif + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +#define HASH_SIZE 16 + +static const uint8_t h264_extradata[] = { + 0x01, 0x4d, 0x40, 0x1e, 0xff, 0xe1, 0x00, 0x02, 0x67, 0x4d, 0x01, 0x00, 0x02, 0x68, 0xef +}; +static const uint8_t aac_extradata[] = { + 0x12, 0x10 +}; + + +const char *format = "mp4"; +AVFormatContext *ctx; +uint8_t iobuf[32768]; +AVDictionary *opts; + +int write_file; +const char *cur_name; +FILE* out; +int out_size; +struct AVMD5* md5; +uint8_t hash[HASH_SIZE]; + +AVStream *video_st, *audio_st; +int64_t audio_dts, video_dts; + +int bframes; +int64_t duration; +int64_t audio_duration; +int frames; +int gop_size; +int64_t next_p_pts; +enum AVPictureType last_picture; +int skip_write; +int skip_write_audio; +int clear_duration; +int force_iobuf_size; +int do_interleave; +int fake_pkt_duration; + +int num_warnings; + +int check_faults; + + +static void count_warnings(void *avcl, int level, const char *fmt, va_list vl) +{ + if (level == AV_LOG_WARNING) + num_warnings++; +} + +static void init_count_warnings(void) +{ + av_log_set_callback(count_warnings); + num_warnings = 0; +} + +static void reset_count_warnings(void) +{ + av_log_set_callback(av_log_default_callback); +} + +static int io_write(void *opaque, uint8_t *buf, int size) +{ + out_size += size; + av_md5_update(md5, buf, size); + if (out) + fwrite(buf, 1, size, out); + return size; +} + +static int io_write_data_type(void *opaque, uint8_t *buf, int size, + enum AVIODataMarkerType type, int64_t time) +{ + char timebuf[30], content[5] = { 0 }; + const char *str; + switch (type) { + case AVIO_DATA_MARKER_HEADER: str = "header"; break; + case AVIO_DATA_MARKER_SYNC_POINT: str = "sync"; break; + case AVIO_DATA_MARKER_BOUNDARY_POINT: str = "boundary"; break; + case AVIO_DATA_MARKER_UNKNOWN: str = "unknown"; break; + case AVIO_DATA_MARKER_TRAILER: str = "trailer"; break; + } + if (time == AV_NOPTS_VALUE) + snprintf(timebuf, sizeof(timebuf), "nopts"); + else + snprintf(timebuf, sizeof(timebuf), "%"PRId64, time); + // There can be multiple header/trailer callbacks, only log the box type + // for header at out_size == 0 + if (type != AVIO_DATA_MARKER_UNKNOWN && + type != AVIO_DATA_MARKER_TRAILER && + (type != AVIO_DATA_MARKER_HEADER || out_size == 0) && + size >= 8) + memcpy(content, &buf[4], 4); + else + snprintf(content, sizeof(content), "-"); + printf("write_data len %d, time %s, type %s atom %s\n", size, timebuf, str, content); + return io_write(opaque, buf, size); +} + +static void init_out(const char *name) +{ + char buf[100]; + cur_name = name; + snprintf(buf, sizeof(buf), "%s.%s", cur_name, format); + + av_md5_init(md5); + if (write_file) { + out = fopen(buf, "wb"); + if (!out) + perror(buf); + } + out_size = 0; +} + +static void close_out(void) +{ + int i; + av_md5_final(md5, hash); + for (i = 0; i < HASH_SIZE; i++) + printf("%02x", hash[i]); + printf(" %d %s\n", out_size, cur_name); + if (out) + fclose(out); + out = NULL; +} + +static void check_func(int value, int line, const char *msg, ...) +{ + if (!value) { + va_list ap; + va_start(ap, msg); + printf("%d: ", line); + vprintf(msg, ap); + printf("\n"); + check_faults++; + va_end(ap); + } +} +#define check(value, ...) check_func(value, __LINE__, __VA_ARGS__) + +static void init_fps(int bf, int audio_preroll, int fps) +{ + AVStream *st; + int iobuf_size = force_iobuf_size ? force_iobuf_size : sizeof(iobuf); + ctx = avformat_alloc_context(); + if (!ctx) + exit(1); + ctx->oformat = av_guess_format(format, NULL, NULL); + if (!ctx->oformat) + exit(1); + ctx->pb = avio_alloc_context(iobuf, iobuf_size, AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL); + if (!ctx->pb) + exit(1); + ctx->pb->write_data_type = io_write_data_type; + ctx->flags |= AVFMT_FLAG_BITEXACT; + + st = avformat_new_stream(ctx, NULL); + if (!st) + exit(1); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_H264; + st->codecpar->width = 640; + st->codecpar->height = 480; + st->time_base.num = 1; + st->time_base.den = 30; + st->codecpar->extradata_size = sizeof(h264_extradata); + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + exit(1); + memcpy(st->codecpar->extradata, h264_extradata, sizeof(h264_extradata)); + video_st = st; + + st = avformat_new_stream(ctx, NULL); + if (!st) + exit(1); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AAC; + st->codecpar->sample_rate = 44100; + st->codecpar->channels = 2; + st->time_base.num = 1; + st->time_base.den = 44100; + st->codecpar->extradata_size = sizeof(aac_extradata); + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + exit(1); + memcpy(st->codecpar->extradata, aac_extradata, sizeof(aac_extradata)); + audio_st = st; + + if (avformat_write_header(ctx, &opts) < 0) + exit(1); + av_dict_free(&opts); + + frames = 0; + gop_size = 30; + duration = video_st->time_base.den / fps; + audio_duration = 1024LL * audio_st->time_base.den / audio_st->codecpar->sample_rate; + if (audio_preroll) + audio_preroll = 2048LL * audio_st->time_base.den / audio_st->codecpar->sample_rate; + + bframes = bf; + video_dts = bframes ? -duration : 0; + audio_dts = -audio_preroll; +} + +static void init(int bf, int audio_preroll) +{ + init_fps(bf, audio_preroll, 30); +} + +static void mux_frames(int n) +{ + int end_frames = frames + n; + while (1) { + AVPacket pkt; + uint8_t pktdata[4]; + av_init_packet(&pkt); + + if (av_compare_ts(audio_dts, audio_st->time_base, video_dts, video_st->time_base) < 0) { + pkt.dts = pkt.pts = audio_dts; + pkt.stream_index = 1; + pkt.duration = audio_duration; + audio_dts += audio_duration; + } else { + if (frames == end_frames) + break; + pkt.dts = video_dts; + pkt.stream_index = 0; + pkt.duration = duration; + if ((frames % gop_size) == 0) { + pkt.flags |= AV_PKT_FLAG_KEY; + last_picture = AV_PICTURE_TYPE_I; + pkt.pts = pkt.dts + duration; + video_dts = pkt.pts; + } else { + if (last_picture == AV_PICTURE_TYPE_P) { + last_picture = AV_PICTURE_TYPE_B; + pkt.pts = pkt.dts; + video_dts = next_p_pts; + } else { + last_picture = AV_PICTURE_TYPE_P; + if (((frames + 1) % gop_size) == 0) { + pkt.pts = pkt.dts + duration; + video_dts = pkt.pts; + } else { + next_p_pts = pkt.pts = pkt.dts + 2 * duration; + video_dts += duration; + } + } + } + if (!bframes) + pkt.pts = pkt.dts; + if (fake_pkt_duration) + pkt.duration = fake_pkt_duration; + frames++; + } + + if (clear_duration) + pkt.duration = 0; + AV_WB32(pktdata, pkt.pts); + pkt.data = pktdata; + pkt.size = 4; + if (skip_write) + continue; + if (skip_write_audio && pkt.stream_index == 1) + continue; + if (do_interleave) + av_interleaved_write_frame(ctx, &pkt); + else + av_write_frame(ctx, &pkt); + } +} + +static void mux_gops(int n) +{ + mux_frames(gop_size * n); +} + +static void skip_gops(int n) +{ + skip_write = 1; + mux_gops(n); + skip_write = 0; +} + +static void signal_init_ts(void) +{ + AVPacket pkt; + av_init_packet(&pkt); + pkt.size = 0; + pkt.data = NULL; + + pkt.stream_index = 0; + pkt.dts = video_dts; + pkt.pts = 0; + av_write_frame(ctx, &pkt); + + pkt.stream_index = 1; + pkt.dts = pkt.pts = audio_dts; + av_write_frame(ctx, &pkt); +} + +static void finish(void) +{ + av_write_trailer(ctx); + av_free(ctx->pb); + avformat_free_context(ctx); + ctx = NULL; +} + +static void help(void) +{ + printf("movenc-test [-w]\n" + "-w write output into files\n"); +} + +int main(int argc, char **argv) +{ + int c; + uint8_t header[HASH_SIZE]; + uint8_t content[HASH_SIZE]; + int empty_moov_pos; + int prev_pos; + + for (;;) { + c = getopt(argc, argv, "wh"); + if (c == -1) + break; + switch (c) { + case 'w': + write_file = 1; + break; + default: + case 'h': + help(); + return 0; + } + } + + av_register_all(); + + md5 = av_md5_alloc(); + if (!md5) + return 1; + + // Write a fragmented file with an initial moov that actually contains some + // samples. One moov+mdat with 1 second of data and one moof+mdat with 1 + // second of data. + init_out("non-empty-moov"); + av_dict_set(&opts, "movflags", "frag_keyframe", 0); + init(0, 0); + mux_gops(2); + finish(); + close_out(); + + // Write a similar file, but with B-frames and audio preroll, handled + // via an edit list. + init_out("non-empty-moov-elst"); + av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "use_editlist", "1", 0); + init(1, 1); + mux_gops(2); + finish(); + close_out(); + + // Use B-frames but no audio-preroll, but without an edit list. + // Due to avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO, the dts + // of the first audio packet is > 0, but it is set to zero since edit + // lists aren't used, increasing the duration of the first packet instead. + init_out("non-empty-moov-no-elst"); + av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "use_editlist", "0", 0); + init(1, 0); + mux_gops(2); + finish(); + close_out(); + + format = "ismv"; + // Write an ISMV, with B-frames and audio preroll. + init_out("ismv"); + av_dict_set(&opts, "movflags", "frag_keyframe", 0); + init(1, 1); + mux_gops(2); + finish(); + close_out(); + format = "mp4"; + + // An initial moov that doesn't contain any samples, followed by two + // moof+mdat pairs. + init_out("empty-moov"); + av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + init(0, 0); + mux_gops(2); + finish(); + close_out(); + memcpy(content, hash, HASH_SIZE); + + // Similar to the previous one, but with input that doesn't start at + // pts/dts 0. avoid_negative_ts behaves in the same way as + // in non-empty-moov-no-elst above. + init_out("empty-moov-no-elst"); + av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + init(1, 0); + mux_gops(2); + finish(); + close_out(); + + // Same as the previous one, but disable avoid_negative_ts (which + // would require using an edit list, but with empty_moov, one can't + // write a sensible edit list, when the start timestamps aren't known). + // This should trigger a warning - we check that the warning is produced. + init_count_warnings(); + init_out("empty-moov-no-elst-no-adjust"); + av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + av_dict_set(&opts, "avoid_negative_ts", "0", 0); + init(1, 0); + mux_gops(2); + finish(); + close_out(); + + reset_count_warnings(); + check(num_warnings > 0, "No warnings printed for unhandled start offset"); + + // Verify that delay_moov produces the same as empty_moov for + // simple input + init_out("delay-moov"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + init(0, 0); + mux_gops(2); + finish(); + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "delay_moov differs from empty_moov"); + + // Test writing content that requires an edit list using delay_moov + init_out("delay-moov-elst"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + init(1, 1); + mux_gops(2); + finish(); + close_out(); + + // Test writing a file with one track lacking packets, with delay_moov. + skip_write_audio = 1; + init_out("delay-moov-empty-track"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + init(0, 0); + mux_gops(2); + // The automatic flushing shouldn't output anything, since we're still + // waiting for data for some tracks + check(out_size == 0, "delay_moov flushed prematurely"); + // When closed (or manually flushed), all the written data should still + // be output. + finish(); + close_out(); + check(out_size > 0, "delay_moov didn't output anything"); + + // Check that manually flushing still outputs things as expected. This + // produces two fragments, while the one above produces only one. + init_out("delay-moov-empty-track-flush"); + av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0); + init(0, 0); + mux_gops(1); + av_write_frame(ctx, NULL); // Force writing the moov + check(out_size > 0, "No moov written"); + av_write_frame(ctx, NULL); + mux_gops(1); + av_write_frame(ctx, NULL); + finish(); + close_out(); + + skip_write_audio = 0; + + + + // Verify that the header written by delay_moov when manually flushed + // is identical to the one by empty_moov. + init_out("empty-moov-header"); + av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + init(0, 0); + close_out(); + memcpy(header, hash, HASH_SIZE); + init_out("empty-moov-content"); + mux_gops(2); + // Written 2 seconds of content, with an automatic flush after 1 second. + check(out_size > 0, "No automatic flush?"); + empty_moov_pos = prev_pos = out_size; + // Manually flush the second fragment + av_write_frame(ctx, NULL); + check(out_size > prev_pos, "No second fragment flushed?"); + prev_pos = out_size; + // Check that an extra flush doesn't output any more data + av_write_frame(ctx, NULL); + check(out_size == prev_pos, "More data written?"); + close_out(); + memcpy(content, hash, HASH_SIZE); + // Ignore the trailer written here + finish(); + + init_out("delay-moov-header"); + av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0); + init(0, 0); + check(out_size == 0, "Output written during init with delay_moov"); + mux_gops(1); // Write 1 second of content + av_write_frame(ctx, NULL); // Force writing the moov + close_out(); + check(!memcmp(hash, header, HASH_SIZE), "delay_moov header differs from empty_moov"); + init_out("delay-moov-content"); + av_write_frame(ctx, NULL); // Flush the first fragment + check(out_size == empty_moov_pos, "Manually flushed content differs from automatically flushed, %d vs %d", out_size, empty_moov_pos); + mux_gops(1); // Write the rest of the content + av_write_frame(ctx, NULL); // Flush the second fragment + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "delay_moov content differs from empty_moov"); + finish(); + + + // Verify that we can produce an identical second fragment without + // writing the first one. First write the reference fragments that + // we want to reproduce. + av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash", 0); + init(0, 0); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the first fragment + init_out("empty-moov-second-frag"); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + memcpy(content, hash, HASH_SIZE); + finish(); + + // Produce the same second fragment without actually writing the first + // one before. + av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0); + av_dict_set(&opts, "fragment_index", "2", 0); + av_dict_set(&opts, "avoid_negative_ts", "0", 0); + av_dict_set(&opts, "use_editlist", "0", 0); + init(0, 0); + skip_gops(1); + init_out("empty-moov-second-frag-discont"); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs"); + finish(); + + // Produce the same thing by using delay_moov, which requires a slightly + // different call sequence. + av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "fragment_index", "2", 0); + init(0, 0); + skip_gops(1); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the moov + init_out("delay-moov-second-frag-discont"); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs"); + finish(); + + + // Test discontinuously written fragments with B-frames (where the + // assumption of starting at pts=0 works) but not with audio preroll + // (which can't be guessed). + av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0); + init(1, 0); + mux_gops(1); + init_out("delay-moov-elst-init"); + av_write_frame(ctx, NULL); // Output the moov + close_out(); + memcpy(header, hash, HASH_SIZE); + av_write_frame(ctx, NULL); // Output the first fragment + init_out("delay-moov-elst-second-frag"); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + memcpy(content, hash, HASH_SIZE); + finish(); + + av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "fragment_index", "2", 0); + init(1, 0); + skip_gops(1); + mux_gops(1); // Write the second fragment + init_out("delay-moov-elst-init-discont"); + av_write_frame(ctx, NULL); // Output the moov + close_out(); + check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs"); + init_out("delay-moov-elst-second-frag-discont"); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs"); + finish(); + + + // Test discontinuously written fragments with B-frames and audio preroll, + // properly signaled. + av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0); + init(1, 1); + mux_gops(1); + init_out("delay-moov-elst-signal-init"); + av_write_frame(ctx, NULL); // Output the moov + close_out(); + memcpy(header, hash, HASH_SIZE); + av_write_frame(ctx, NULL); // Output the first fragment + init_out("delay-moov-elst-signal-second-frag"); + mux_gops(1); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + memcpy(content, hash, HASH_SIZE); + finish(); + + av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "fragment_index", "2", 0); + init(1, 1); + signal_init_ts(); + skip_gops(1); + mux_gops(1); // Write the second fragment + init_out("delay-moov-elst-signal-init-discont"); + av_write_frame(ctx, NULL); // Output the moov + close_out(); + check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs"); + init_out("delay-moov-elst-signal-second-frag-discont"); + av_write_frame(ctx, NULL); // Output the second fragment + close_out(); + check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs"); + finish(); + + + // Test VFR content, with sidx atoms (which declare the pts duration + // of a fragment, forcing overriding the start pts of the next one). + // Here, the fragment duration in pts is significantly different from + // the duration in dts. The video stream starts at dts=-10,pts=0, and + // the second fragment starts at dts=155,pts=156. The trun duration sum + // of the first fragment is 165, which also is written as + // baseMediaDecodeTime in the tfdt in the second fragment. The sidx for + // the first fragment says earliest_presentation_time = 0 and + // subsegment_duration = 156, which also matches the sidx in the second + // fragment. For the audio stream, the pts and dts durations also don't + // match - the input stream starts at pts=-2048, but that part is excluded + // by the edit list. + init_out("vfr"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0); + init_fps(1, 1, 3); + mux_frames(gop_size/2); + duration /= 10; + mux_frames(gop_size/2); + mux_gops(1); + finish(); + close_out(); + + // Test VFR content, with cleared duration fields. In these cases, + // the muxer must guess the duration of the last packet of each + // fragment. As long as the framerate doesn't vary (too much) at the + // fragment edge, it works just fine. Additionally, when automatically + // cutting fragments, the muxer already know the timestamps of the next + // packet for one stream (in most cases the video stream), avoiding + // having to use guesses for that one. + init_count_warnings(); + clear_duration = 1; + init_out("vfr-noduration"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0); + init_fps(1, 1, 3); + mux_frames(gop_size/2); + duration /= 10; + mux_frames(gop_size/2); + mux_gops(1); + finish(); + close_out(); + clear_duration = 0; + reset_count_warnings(); + check(num_warnings > 0, "No warnings printed for filled in durations"); + + // Test with an IO buffer size that is too small to hold a full fragment; + // this will cause write_data_type to be called with the type unknown. + force_iobuf_size = 1500; + init_out("large_frag"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + init_fps(1, 1, 3); + mux_gops(2); + finish(); + close_out(); + force_iobuf_size = 0; + + // Test VFR content with bframes with interleaving. + // Here, using av_interleaved_write_frame allows the muxer to get the + // fragment end durations right. We always set the packet duration to + // the expected, but we simulate dropped frames at one point. + do_interleave = 1; + init_out("vfr-noduration-interleave"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "frag_duration", "650000", 0); + init_fps(1, 1, 30); + mux_frames(gop_size/2); + // Pretend that the packet duration is the normal, even if + // we actually skip a bunch of frames. (I.e., simulate that + // we don't know of the framedrop in advance.) + fake_pkt_duration = duration; + duration *= 10; + mux_frames(1); + fake_pkt_duration = 0; + duration /= 10; + mux_frames(gop_size/2 - 1); + mux_gops(1); + finish(); + close_out(); + clear_duration = 0; + do_interleave = 0; + + + av_free(md5); + + return check_faults > 0 ? 1 : 0; +} diff --git a/libavformat/noproxy-test.c b/libavformat/tests/noproxy.c similarity index 97% rename from libavformat/noproxy-test.c rename to libavformat/tests/noproxy.c index e6cc421..9daee05 100644 --- a/libavformat/noproxy-test.c +++ b/libavformat/tests/noproxy.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "network.h" +#include "libavformat/network.h" static void test(const char *pattern, const char *host) { diff --git a/libavformat/tests/rtmpdh.c b/libavformat/tests/rtmpdh.c new file mode 100644 index 0000000..c25ca91 --- /dev/null +++ b/libavformat/tests/rtmpdh.c @@ -0,0 +1,158 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavformat/rtmpdh.c" + +#include + +static int test_random_shared_secret(void) +{ + FF_DH *peer1 = NULL, *peer2 = NULL; + int ret; + uint8_t pubkey1[128], pubkey2[128]; + uint8_t sharedkey1[128], sharedkey2[128]; + + peer1 = ff_dh_init(1024); + peer2 = ff_dh_init(1024); + if (!peer1 || !peer2) { + ret = AVERROR(ENOMEM); + goto fail; + } + if ((ret = ff_dh_generate_public_key(peer1)) < 0) + goto fail; + if ((ret = ff_dh_generate_public_key(peer2)) < 0) + goto fail; + if ((ret = ff_dh_write_public_key(peer1, pubkey1, sizeof(pubkey1))) < 0) + goto fail; + if ((ret = ff_dh_write_public_key(peer2, pubkey2, sizeof(pubkey2))) < 0) + goto fail; + if ((ret = ff_dh_compute_shared_secret_key(peer1, pubkey2, sizeof(pubkey2), + sharedkey1, sizeof(sharedkey1))) < 0) + goto fail; + if ((ret = ff_dh_compute_shared_secret_key(peer2, pubkey1, sizeof(pubkey1), + sharedkey2, sizeof(sharedkey2))) < 0) + goto fail; + if (memcmp(sharedkey1, sharedkey2, sizeof(sharedkey1))) { + printf("Mismatched generated shared key\n"); + ret = AVERROR_INVALIDDATA; + } else { + printf("Generated shared key ok\n"); + } +fail: + ff_dh_free(peer1); + ff_dh_free(peer2); + return ret; +} + +static const char *private_key = + "976C18FCADC255B456564F74F3EEDA59D28AF6B744D743F2357BFD2404797EF896EF1A" + "7C1CBEAAA3AB60AF3192D189CFF3F991C9CBBFD78119FCA2181384B94011943B6D6F28" + "9E1B708E2D1A0C7771169293F03DA27E561F15F16F0AC9BC858C77A80FA98FD088A232" + "19D08BE6F165DE0B02034B18705829FAD0ACB26A5B75EF"; +static const char *public_key = + "F272ECF8362257C5D2C3CC2229CF9C0A03225BC109B1DBC76A68C394F256ACA3EF5F64" + "FC270C26382BF315C19E97A76104A716FC998A651E8610A3AE6CF65D8FAE5D3F32EEA0" + "0B32CB9609B494116A825D7142D17B88E3D20EDD98743DE29CF37A23A9F6A58B960591" + "3157D5965FCB46DDA73A1F08DD897BAE88DFE6FC937CBA"; +static const uint8_t public_key_bin[] = { + 0xf2, 0x72, 0xec, 0xf8, 0x36, 0x22, 0x57, 0xc5, 0xd2, 0xc3, 0xcc, 0x22, + 0x29, 0xcf, 0x9c, 0x0a, 0x03, 0x22, 0x5b, 0xc1, 0x09, 0xb1, 0xdb, 0xc7, + 0x6a, 0x68, 0xc3, 0x94, 0xf2, 0x56, 0xac, 0xa3, 0xef, 0x5f, 0x64, 0xfc, + 0x27, 0x0c, 0x26, 0x38, 0x2b, 0xf3, 0x15, 0xc1, 0x9e, 0x97, 0xa7, 0x61, + 0x04, 0xa7, 0x16, 0xfc, 0x99, 0x8a, 0x65, 0x1e, 0x86, 0x10, 0xa3, 0xae, + 0x6c, 0xf6, 0x5d, 0x8f, 0xae, 0x5d, 0x3f, 0x32, 0xee, 0xa0, 0x0b, 0x32, + 0xcb, 0x96, 0x09, 0xb4, 0x94, 0x11, 0x6a, 0x82, 0x5d, 0x71, 0x42, 0xd1, + 0x7b, 0x88, 0xe3, 0xd2, 0x0e, 0xdd, 0x98, 0x74, 0x3d, 0xe2, 0x9c, 0xf3, + 0x7a, 0x23, 0xa9, 0xf6, 0xa5, 0x8b, 0x96, 0x05, 0x91, 0x31, 0x57, 0xd5, + 0x96, 0x5f, 0xcb, 0x46, 0xdd, 0xa7, 0x3a, 0x1f, 0x08, 0xdd, 0x89, 0x7b, + 0xae, 0x88, 0xdf, 0xe6, 0xfc, 0x93, 0x7c, 0xba +}; +static const uint8_t peer_public_key[] = { + 0x58, 0x66, 0x05, 0x49, 0x94, 0x23, 0x2b, 0x66, 0x52, 0x13, 0xff, 0x46, + 0xf2, 0xb3, 0x79, 0xa9, 0xee, 0xae, 0x1a, 0x13, 0xf0, 0x71, 0x52, 0xfb, + 0x93, 0x4e, 0xee, 0x97, 0x05, 0x73, 0x50, 0x7d, 0xaf, 0x02, 0x07, 0x72, + 0xac, 0xdc, 0xa3, 0x95, 0x78, 0xee, 0x9a, 0x19, 0x71, 0x7e, 0x99, 0x9f, + 0x2a, 0xd4, 0xb3, 0xe2, 0x0c, 0x1d, 0x1a, 0x78, 0x4c, 0xde, 0xf1, 0xad, + 0xb4, 0x60, 0xa8, 0x51, 0xac, 0x71, 0xec, 0x86, 0x70, 0xa2, 0x63, 0x36, + 0x92, 0x7c, 0xe3, 0x87, 0xee, 0xe4, 0xf1, 0x62, 0x24, 0x74, 0xb4, 0x04, + 0xfa, 0x5c, 0xdf, 0xba, 0xfa, 0xa3, 0xc2, 0xbb, 0x62, 0x27, 0xd0, 0xf4, + 0xe4, 0x43, 0xda, 0x8a, 0x88, 0x69, 0x60, 0xe2, 0xdb, 0x75, 0x2a, 0x98, + 0x9d, 0xb5, 0x50, 0xe3, 0x99, 0xda, 0xe0, 0xa6, 0x14, 0xc9, 0x80, 0x12, + 0xf9, 0x3c, 0xac, 0x06, 0x02, 0x7a, 0xde, 0x74 +}; +static const uint8_t shared_secret[] = { + 0xb2, 0xeb, 0xcb, 0x71, 0xf3, 0x61, 0xfb, 0x5b, 0x4e, 0x5c, 0x4c, 0xcf, + 0x5c, 0x08, 0x5f, 0x96, 0x26, 0x77, 0x1d, 0x31, 0xf1, 0xe1, 0xf7, 0x4b, + 0x92, 0xac, 0x82, 0x2a, 0x88, 0xc7, 0x83, 0xe1, 0xc7, 0xf3, 0xd3, 0x1a, + 0x7d, 0xc8, 0x31, 0xe3, 0x97, 0xe4, 0xec, 0x31, 0x0e, 0x8f, 0x73, 0x1a, + 0xe4, 0xf6, 0xd8, 0xc8, 0x94, 0xff, 0xa0, 0x03, 0x84, 0x03, 0x0f, 0xa5, + 0x30, 0x5d, 0x67, 0xe0, 0x7a, 0x3b, 0x5f, 0xed, 0x4c, 0xf5, 0xbc, 0x18, + 0xea, 0xd4, 0x77, 0xa9, 0x07, 0xb3, 0x54, 0x0b, 0x02, 0xd9, 0xc6, 0xb8, + 0x66, 0x5e, 0xec, 0xa4, 0xcd, 0x47, 0xed, 0xc9, 0x38, 0xc6, 0x91, 0x08, + 0xf3, 0x85, 0x9b, 0x69, 0x16, 0x78, 0x0d, 0xb7, 0x74, 0x51, 0xaa, 0x5b, + 0x4d, 0x74, 0xe4, 0x29, 0x2e, 0x9e, 0x8e, 0xf7, 0xe5, 0x42, 0x83, 0xb0, + 0x65, 0xb0, 0xce, 0xc6, 0xb2, 0x8f, 0x5b, 0xb0 +}; + +static int test_ref_data(void) +{ + FF_DH *dh; + int ret = AVERROR(ENOMEM); + uint8_t pubkey_test[128]; + uint8_t sharedkey_test[128]; + + dh = ff_dh_init(1024); + if (!dh) + goto fail; + bn_hex2bn(dh->priv_key, private_key, ret); + if (!ret) + goto fail; + bn_hex2bn(dh->pub_key, public_key, ret); + if (!ret) + goto fail; + if ((ret = ff_dh_write_public_key(dh, pubkey_test, sizeof(pubkey_test))) < 0) + goto fail; + if (memcmp(pubkey_test, public_key_bin, sizeof(pubkey_test))) { + printf("Mismatched generated public key\n"); + ret = AVERROR_INVALIDDATA; + goto fail; + } else { + printf("Generated public key ok\n"); + } + if ((ret = ff_dh_compute_shared_secret_key(dh, peer_public_key, sizeof(peer_public_key), + sharedkey_test, sizeof(sharedkey_test))) < 0) + goto fail; + if (memcmp(shared_secret, sharedkey_test, sizeof(sharedkey_test))) { + printf("Mismatched generated shared key\n"); + ret = AVERROR_INVALIDDATA; + } else { + printf("Generated shared key ok\n"); + } +fail: + ff_dh_free(dh); + return ret; +} + +int main(void) +{ + if (test_random_shared_secret() < 0) + return 1; + if (test_ref_data() < 0) + return 1; + return 0; +} diff --git a/libavformat/seek-test.c b/libavformat/tests/seek.c similarity index 99% rename from libavformat/seek-test.c rename to libavformat/tests/seek.c index 143f0b5..82da374 100644 --- a/libavformat/seek-test.c +++ b/libavformat/tests/seek.c @@ -26,6 +26,7 @@ #include "libavutil/common.h" #include "libavutil/mathematics.h" + #include "libavformat/avformat.h" static char buffer[20]; @@ -102,7 +103,7 @@ int main(int argc, char **argv) ts_str(dts_buf, pkt.dts, st->time_base); ts_str(ts_buf, pkt.pts, st->time_base); printf("ret:%-10s st:%2d flags:%d dts:%s pts:%s pos:%7" PRId64 " size:%6d", ret_str(ret), pkt.stream_index, pkt.flags, dts_buf, ts_buf, pkt.pos, pkt.size); - av_free_packet(&pkt); + av_packet_unref(&pkt); } else printf("ret:%s", ret_str(ret)); // necessary to avoid trailing whitespace printf("\n"); diff --git a/libavformat/tests/srtp.c b/libavformat/tests/srtp.c new file mode 100644 index 0000000..1703193 --- /dev/null +++ b/libavformat/tests/srtp.c @@ -0,0 +1,167 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavformat/rtpdec.h" +#include "libavformat/srtp.h" + +static const char *aes128_80_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; + +static const uint8_t rtp_aes128_80[] = { + // RTP header + 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0x62, 0x69, 0x76, 0xca, 0xc5, + // HMAC + 0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99, +}; + +static const uint8_t rtcp_aes128_80[] = { + // RTCP header + 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda, + 0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35, + // RTCP index + 0x80, 0x00, 0x00, 0x03, + // HMAC + 0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde, +}; + +static const char *aes128_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; + +static const uint8_t rtp_aes128_32[] = { + // RTP header + 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0x62, 0x69, 0x76, 0xca, 0xc5, + // HMAC + 0xa1, 0xac, 0x1b, 0xb4, +}; + +static const uint8_t rtcp_aes128_32[] = { + // RTCP header + 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b, + 0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34, + // RTCP index + 0x80, 0x00, 0x00, 0x04, + // HMAC + 0x5b, 0xd2, 0xa9, 0x9d, +}; + +static const char *aes128_80_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"; + +static const uint8_t rtp_aes128_80_32[] = { + // RTP header + 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0x62, 0x69, 0x76, 0xca, 0xc5, + // HMAC + 0xa1, 0xac, 0x1b, 0xb4, +}; + +static const uint8_t rtcp_aes128_80_32[] = { + // RTCP header + 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, + // encrypted payload + 0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53, + 0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9, + // RTCP index + 0x80, 0x00, 0x00, 0x05, + // HMAC + 0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10, +}; + +static void print_data(const uint8_t *buf, int len) +{ + int i; + for (i = 0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); +} + +static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len, + uint8_t *out) +{ + memcpy(out, in, len); + if (!ff_srtp_decrypt(srtp, out, &len)) { + print_data(out, len); + return len; + } else + return -1; +} + +static void test_encrypt(const uint8_t *data, int in_len, const char *suite, + const char *key) +{ + struct SRTPContext enc = { 0 }, dec = { 0 }; + int len; + char buf[RTP_MAX_PACKET_LENGTH]; + ff_srtp_set_crypto(&enc, suite, key); + ff_srtp_set_crypto(&dec, suite, key); + len = ff_srtp_encrypt(&enc, data, in_len, buf, sizeof(buf)); + if (!ff_srtp_decrypt(&dec, buf, &len)) { + if (len == in_len && !memcmp(buf, data, len)) + printf("Decrypted content matches input\n"); + else + printf("Decrypted content doesn't match input\n"); + } else { + printf("Decryption failed\n"); + } + ff_srtp_free(&enc); + ff_srtp_free(&dec); +} + +int main(void) +{ + static const char *aes128_80_suite = "AES_CM_128_HMAC_SHA1_80"; + static const char *aes128_32_suite = "AES_CM_128_HMAC_SHA1_32"; + static const char *aes128_80_32_suite = "SRTP_AES128_CM_HMAC_SHA1_32"; + static const char *test_key = "abcdefghijklmnopqrstuvwxyz1234567890ABCD"; + uint8_t buf[RTP_MAX_PACKET_LENGTH]; + struct SRTPContext srtp = { 0 }; + int len; + ff_srtp_set_crypto(&srtp, aes128_80_suite, aes128_80_key); + len = test_decrypt(&srtp, rtp_aes128_80, sizeof(rtp_aes128_80), buf); + test_encrypt(buf, len, aes128_80_suite, test_key); + test_encrypt(buf, len, aes128_32_suite, test_key); + test_encrypt(buf, len, aes128_80_32_suite, test_key); + test_decrypt(&srtp, rtcp_aes128_80, sizeof(rtcp_aes128_80), buf); + test_encrypt(buf, len, aes128_80_suite, test_key); + test_encrypt(buf, len, aes128_32_suite, test_key); + test_encrypt(buf, len, aes128_80_32_suite, test_key); + ff_srtp_free(&srtp); + + memset(&srtp, 0, sizeof(srtp)); // Clear the context + ff_srtp_set_crypto(&srtp, aes128_32_suite, aes128_32_key); + test_decrypt(&srtp, rtp_aes128_32, sizeof(rtp_aes128_32), buf); + test_decrypt(&srtp, rtcp_aes128_32, sizeof(rtcp_aes128_32), buf); + ff_srtp_free(&srtp); + + memset(&srtp, 0, sizeof(srtp)); // Clear the context + ff_srtp_set_crypto(&srtp, aes128_80_32_suite, aes128_80_32_key); + test_decrypt(&srtp, rtp_aes128_80_32, sizeof(rtp_aes128_80_32), buf); + test_decrypt(&srtp, rtcp_aes128_80_32, sizeof(rtcp_aes128_80_32), buf); + ff_srtp_free(&srtp); + return 0; +} diff --git a/libavformat/url-test.c b/libavformat/tests/url.c similarity index 98% rename from libavformat/url-test.c rename to libavformat/tests/url.c index 503b36e..ec33173 100644 --- a/libavformat/url-test.c +++ b/libavformat/tests/url.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "url.h" +#include "libavformat/url.h" static void test(const char *base, const char *rel) { diff --git a/libavformat/thp.c b/libavformat/thp.c index e8ca04f..c9ec5c1 100644 --- a/libavformat/thp.c +++ b/libavformat/thp.c @@ -101,12 +101,12 @@ static int thp_read_header(AVFormatContext *s) /* The denominator and numerator are switched because 1/fps is required. */ avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_THP; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = avio_rb32(pb); - st->codec->height = avio_rb32(pb); - st->codec->sample_rate = av_q2d(thp->fps); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_THP; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = avio_rb32(pb); + st->codecpar->height = avio_rb32(pb); + st->codecpar->sample_rate = av_q2d(thp->fps); thp->vst = st; thp->video_stream_index = st->index; @@ -121,13 +121,14 @@ static int thp_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_THP; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->channels = avio_rb32(pb); /* numChannels. */ - st->codec->sample_rate = avio_rb32(pb); /* Frequency. */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->channels = avio_rb32(pb); /* numChannels. */ + st->codecpar->sample_rate = avio_rb32(pb); /* Frequency. */ + st->duration = avio_rb32(pb); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); thp->audio_stream_index = st->index; thp->has_audio = 1; @@ -168,7 +169,7 @@ static int thp_read_packet(AVFormatContext *s, ret = av_get_packet(pb, pkt, size); if (ret != size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } @@ -176,7 +177,7 @@ static int thp_read_packet(AVFormatContext *s, } else { ret = av_get_packet(pb, pkt, thp->audiosize); if (ret != thp->audiosize) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } diff --git a/libavformat/tiertexseq.c b/libavformat/tiertexseq.c index 45300f9..8427f92 100644 --- a/libavformat/tiertexseq.c +++ b/libavformat/tiertexseq.c @@ -214,11 +214,11 @@ static int seq_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 32, 1, SEQ_FRAME_RATE); seq->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = SEQ_FRAME_W; - st->codec->height = SEQ_FRAME_H; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = SEQ_FRAME_W; + st->codecpar->height = SEQ_FRAME_H; /* initialize the audio decoder stream */ st = avformat_new_stream(s, NULL); @@ -228,15 +228,15 @@ static int seq_read_header(AVFormatContext *s) st->start_time = 0; avpriv_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE); seq->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->sample_rate = SEQ_SAMPLE_RATE; - st->codec->bits_per_coded_sample = 16; - st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample / 8; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + st->codecpar->codec_tag = 0; /* no tag */ + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = SEQ_SAMPLE_RATE; + st->codecpar->bits_per_coded_sample = 16; + st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels; + st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8; return 0; } diff --git a/libavformat/tls.c b/libavformat/tls.c index 7c78fda..fab243e 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -20,150 +20,48 @@ */ #include "avformat.h" +#include "internal.h" +#include "network.h" +#include "os_support.h" #include "url.h" +#include "tls.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" -#if CONFIG_GNUTLS -#include -#include -#define TLS_read(c, buf, size) gnutls_record_recv(c->session, buf, size) -#define TLS_write(c, buf, size) gnutls_record_send(c->session, buf, size) -#define TLS_shutdown(c) gnutls_bye(c->session, GNUTLS_SHUT_RDWR) -#define TLS_free(c) do { \ - if (c->session) \ - gnutls_deinit(c->session); \ - if (c->cred) \ - gnutls_certificate_free_credentials(c->cred); \ - } while (0) -#elif CONFIG_OPENSSL -#include -#include -#include -#define TLS_read(c, buf, size) SSL_read(c->ssl, buf, size) -#define TLS_write(c, buf, size) SSL_write(c->ssl, buf, size) -#define TLS_shutdown(c) SSL_shutdown(c->ssl) -#define TLS_free(c) do { \ - if (c->ssl) \ - SSL_free(c->ssl); \ - if (c->ctx) \ - SSL_CTX_free(c->ctx); \ - } while (0) -#endif -#include "network.h" -#include "os_support.h" -#include "internal.h" -#if HAVE_POLL_H -#include -#endif - -typedef struct { - const AVClass *class; - URLContext *tcp; -#if CONFIG_GNUTLS - gnutls_session_t session; - gnutls_certificate_credentials_t cred; -#elif CONFIG_OPENSSL - SSL_CTX *ctx; - SSL *ssl; -#endif - int fd; - char *ca_file; - int verify; - char *cert_file; - char *key_file; - int listen; -} TLSContext; - -#define OFFSET(x) offsetof(TLSContext, x) -#define D AV_OPT_FLAG_DECODING_PARAM -#define E AV_OPT_FLAG_ENCODING_PARAM -static const AVOption options[] = { - {"ca_file", "Certificate Authority database file", OFFSET(ca_file), AV_OPT_TYPE_STRING, .flags = D|E }, - {"tls_verify", "Verify the peer certificate", OFFSET(verify), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, - {"cert_file", "Certificate file", OFFSET(cert_file), AV_OPT_TYPE_STRING, .flags = D|E }, - {"key_file", "Private key file", OFFSET(key_file), AV_OPT_TYPE_STRING, .flags = D|E }, - {"listen", "Listen for incoming connections", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, - { NULL } -}; - -static const AVClass tls_class = { - .class_name = "tls", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -static int do_tls_poll(URLContext *h, int ret) -{ - TLSContext *c = h->priv_data; - struct pollfd p = { c->fd, 0, 0 }; -#if CONFIG_GNUTLS - switch (ret) { - case GNUTLS_E_AGAIN: - case GNUTLS_E_INTERRUPTED: - break; - case GNUTLS_E_WARNING_ALERT_RECEIVED: - av_log(h, AV_LOG_WARNING, "%s\n", gnutls_strerror(ret)); - break; - default: - av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); - return AVERROR(EIO); - } - if (gnutls_record_get_direction(c->session)) - p.events = POLLOUT; - else - p.events = POLLIN; -#elif CONFIG_OPENSSL - ret = SSL_get_error(c->ssl, ret); - if (ret == SSL_ERROR_WANT_READ) { - p.events = POLLIN; - } else if (ret == SSL_ERROR_WANT_WRITE) { - p.events = POLLOUT; - } else { - av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); - return AVERROR(EIO); - } -#endif - if (h->flags & AVIO_FLAG_NONBLOCK) - return AVERROR(EAGAIN); - while (1) { - int n = poll(&p, 1, 100); - if (n > 0) - break; - if (ff_check_interrupt(&h->interrupt_callback)) - return AVERROR(EINTR); - } - return 0; -} -static int tls_open(URLContext *h, const char *uri, int flags) +int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) { - TLSContext *c = h->priv_data; - int ret; int port; - char buf[200], host[200], opts[50] = ""; - int numerichost = 0; + const char *p; + char buf[200], opts[50] = ""; struct addrinfo hints = { 0 }, *ai = NULL; const char *proxy_path; int use_proxy; - ff_tls_init(); - if (c->listen) snprintf(opts, sizeof(opts), "?listen=1"); - av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri); - ff_url_join(buf, sizeof(buf), "tcp", NULL, host, port, "%s", opts); + av_url_split(NULL, 0, NULL, 0, c->host, sizeof(c->host), &port, NULL, 0, uri); + + p = strchr(uri, '?'); + + if (!p) { + p = opts; + } else { + if (av_find_info_tag(opts, sizeof(opts), "listen", p)) + c->listen = 1; + } + + ff_url_join(buf, sizeof(buf), "tcp", NULL, c->host, port, "%s", p); hints.ai_flags = AI_NUMERICHOST; - if (!getaddrinfo(host, NULL, &hints, &ai)) { - numerichost = 1; + if (!getaddrinfo(c->host, NULL, &hints, &ai)) { + c->numerichost = 1; freeaddrinfo(ai); } proxy_path = getenv("http_proxy"); - use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), host) && + use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->host) && proxy_path && av_strstart(proxy_path, "http://", NULL); if (use_proxy) { @@ -172,188 +70,11 @@ static int tls_open(URLContext *h, const char *uri, int flags) av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, proxy_path); - ff_url_join(dest, sizeof(dest), NULL, NULL, host, port, NULL); + ff_url_join(dest, sizeof(dest), NULL, NULL, c->host, port, NULL); ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, proxy_port, "/%s", dest); } - ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); - if (ret) - goto fail; - c->fd = ffurl_get_file_handle(c->tcp); - -#if CONFIG_GNUTLS - gnutls_init(&c->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT); - if (!c->listen && !numerichost) - gnutls_server_name_set(c->session, GNUTLS_NAME_DNS, host, strlen(host)); - gnutls_certificate_allocate_credentials(&c->cred); - if (c->ca_file) - gnutls_certificate_set_x509_trust_file(c->cred, c->ca_file, GNUTLS_X509_FMT_PEM); -#if GNUTLS_VERSION_MAJOR >= 3 - else - gnutls_certificate_set_x509_system_trust(c->cred); -#endif - gnutls_certificate_set_verify_flags(c->cred, c->verify ? - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0); - if (c->cert_file && c->key_file) { - ret = gnutls_certificate_set_x509_key_file(c->cred, - c->cert_file, c->key_file, - GNUTLS_X509_FMT_PEM); - if (ret < 0) { - av_log(h, AV_LOG_ERROR, - "Unable to set cert/key files %s and %s: %s\n", - c->cert_file, c->key_file, gnutls_strerror(ret)); - ret = AVERROR(EIO); - goto fail; - } - } - gnutls_credentials_set(c->session, GNUTLS_CRD_CERTIFICATE, c->cred); - gnutls_transport_set_ptr(c->session, (gnutls_transport_ptr_t) - (intptr_t) c->fd); - gnutls_priority_set_direct(c->session, "NORMAL", NULL); - while (1) { - ret = gnutls_handshake(c->session); - if (ret == 0) - break; - if ((ret = do_tls_poll(h, ret)) < 0) - goto fail; - } - if (c->verify) { - unsigned int status, cert_list_size; - gnutls_x509_crt_t cert; - const gnutls_datum_t *cert_list; - if ((ret = gnutls_certificate_verify_peers2(c->session, &status)) < 0) { - av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n", - gnutls_strerror(ret)); - ret = AVERROR(EIO); - goto fail; - } - if (status & GNUTLS_CERT_INVALID) { - av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n"); - ret = AVERROR(EIO); - goto fail; - } - if (gnutls_certificate_type_get(c->session) != GNUTLS_CRT_X509) { - av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n"); - ret = AVERROR(EIO); - goto fail; - } - gnutls_x509_crt_init(&cert); - cert_list = gnutls_certificate_get_peers(c->session, &cert_list_size); - gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER); - ret = gnutls_x509_crt_check_hostname(cert, host); - gnutls_x509_crt_deinit(cert); - if (!ret) { - av_log(h, AV_LOG_ERROR, - "The certificate's owner does not match hostname %s\n", host); - ret = AVERROR(EIO); - goto fail; - } - } -#elif CONFIG_OPENSSL - c->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method()); - if (!c->ctx) { - av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); - ret = AVERROR(EIO); - goto fail; - } - if (c->ca_file) - SSL_CTX_load_verify_locations(c->ctx, c->ca_file, NULL); - if (c->cert_file && !SSL_CTX_use_certificate_chain_file(c->ctx, c->cert_file)) { - av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", - c->cert_file, ERR_error_string(ERR_get_error(), NULL)); - ret = AVERROR(EIO); - goto fail; - } - if (c->key_file && !SSL_CTX_use_PrivateKey_file(c->ctx, c->key_file, SSL_FILETYPE_PEM)) { - av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", - c->key_file, ERR_error_string(ERR_get_error(), NULL)); - ret = AVERROR(EIO); - goto fail; - } - // Note, this doesn't check that the peer certificate actually matches - // the requested hostname. - if (c->verify) - SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER, NULL); - c->ssl = SSL_new(c->ctx); - if (!c->ssl) { - av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); - ret = AVERROR(EIO); - goto fail; - } - SSL_set_fd(c->ssl, c->fd); - if (!c->listen && !numerichost) - SSL_set_tlsext_host_name(c->ssl, host); - while (1) { - ret = c->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl); - if (ret > 0) - break; - if (ret == 0) { - av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); - ret = AVERROR(EIO); - goto fail; - } - if ((ret = do_tls_poll(h, ret)) < 0) - goto fail; - } -#endif - return 0; -fail: - TLS_free(c); - if (c->tcp) - ffurl_close(c->tcp); - ff_tls_deinit(); - return ret; + return ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, + &parent->interrupt_callback, options, parent->protocols, parent); } - -static int tls_read(URLContext *h, uint8_t *buf, int size) -{ - TLSContext *c = h->priv_data; - while (1) { - int ret = TLS_read(c, buf, size); - if (ret > 0) - return ret; - if (ret == 0) - return AVERROR_EOF; - if ((ret = do_tls_poll(h, ret)) < 0) - return ret; - } - return 0; -} - -static int tls_write(URLContext *h, const uint8_t *buf, int size) -{ - TLSContext *c = h->priv_data; - while (1) { - int ret = TLS_write(c, buf, size); - if (ret > 0) - return ret; - if (ret == 0) - return AVERROR_EOF; - if ((ret = do_tls_poll(h, ret)) < 0) - return ret; - } - return 0; -} - -static int tls_close(URLContext *h) -{ - TLSContext *c = h->priv_data; - TLS_shutdown(c); - TLS_free(c); - ffurl_close(c->tcp); - ff_tls_deinit(); - return 0; -} - -URLProtocol ff_tls_protocol = { - .name = "tls", - .url_open = tls_open, - .url_read = tls_read, - .url_write = tls_write, - .url_close = tls_close, - .priv_data_size = sizeof(TLSContext), - .flags = URL_PROTOCOL_FLAG_NETWORK, - .priv_data_class = &tls_class, -}; diff --git a/libavformat/tls.h b/libavformat/tls.h new file mode 100644 index 0000000..22cb625 --- /dev/null +++ b/libavformat/tls.h @@ -0,0 +1,60 @@ +/* + * TLS/SSL Protocol + * Copyright (c) 2011 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_TLS_H +#define AVFORMAT_TLS_H + +#include "config.h" +#include "url.h" +#include "libavutil/opt.h" + +#define CONFIG_TLS_PROTOCOL (CONFIG_TLS_GNUTLS_PROTOCOL | CONFIG_TLS_OPENSSL_PROTOCOL) + +typedef struct TLSShared { + char *ca_file; + int verify; + char *cert_file; + char *key_file; + int listen; + + char host[200]; + int numerichost; + + URLContext *tcp; +} TLSShared; + +#define TLS_OPTFL (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +#define TLS_COMMON_OPTIONS(pstruct, options_field) \ + {"ca_file", "Certificate Authority database file", offsetof(pstruct, options_field . ca_file), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ + {"tls_verify", "Verify the peer certificate", offsetof(pstruct, options_field . verify), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = TLS_OPTFL }, \ + {"cert_file", "Certificate file", offsetof(pstruct, options_field . cert_file), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ + {"key_file", "Private key file", offsetof(pstruct, options_field . key_file), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ + {"listen", "Listen for incoming connections", offsetof(pstruct, options_field . listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = TLS_OPTFL } + +int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options); + +void ff_gnutls_init(void); +void ff_gnutls_deinit(void); + +void ff_openssl_init(void); +void ff_openssl_deinit(void); + +#endif /* AVFORMAT_TLS_H */ diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c new file mode 100644 index 0000000..3e29a45 --- /dev/null +++ b/libavformat/tls_gnutls.c @@ -0,0 +1,255 @@ +/* + * TLS/SSL Protocol + * Copyright (c) 2011 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "avformat.h" +#include "internal.h" +#include "network.h" +#include "os_support.h" +#include "url.h" +#include "tls.h" +#include "libavcodec/internal.h" +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" + +#if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00 +#include +#include "libavutil/thread.h" +GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif + +typedef struct TLSContext { + const AVClass *class; + TLSShared tls_shared; + gnutls_session_t session; + gnutls_certificate_credentials_t cred; + int need_shutdown; +} TLSContext; + +void ff_gnutls_init(void) +{ + avpriv_lock_avformat(); +#if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 + if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); +#endif + gnutls_global_init(); + avpriv_unlock_avformat(); +} + +void ff_gnutls_deinit(void) +{ + avpriv_lock_avformat(); + gnutls_global_deinit(); + avpriv_unlock_avformat(); +} + +static int print_tls_error(URLContext *h, int ret) +{ + switch (ret) { + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + break; + case GNUTLS_E_WARNING_ALERT_RECEIVED: + av_log(h, AV_LOG_WARNING, "%s\n", gnutls_strerror(ret)); + break; + default: + av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); + break; + } + return AVERROR(EIO); +} + +static int tls_close(URLContext *h) +{ + TLSContext *c = h->priv_data; + if (c->need_shutdown) + gnutls_bye(c->session, GNUTLS_SHUT_WR); + if (c->session) + gnutls_deinit(c->session); + if (c->cred) + gnutls_certificate_free_credentials(c->cred); + if (c->tls_shared.tcp) + ffurl_close(c->tls_shared.tcp); + ff_gnutls_deinit(); + return 0; +} + +static ssize_t gnutls_url_pull(gnutls_transport_ptr_t transport, + void *buf, size_t len) +{ + URLContext *h = (URLContext*) transport; + int ret = ffurl_read(h, buf, len); + if (ret >= 0) + return ret; + if (ret == AVERROR_EXIT) + return 0; + errno = EIO; + return -1; +} + +static ssize_t gnutls_url_push(gnutls_transport_ptr_t transport, + const void *buf, size_t len) +{ + URLContext *h = (URLContext*) transport; + int ret = ffurl_write(h, buf, len); + if (ret >= 0) + return ret; + if (ret == AVERROR_EXIT) + return 0; + errno = EIO; + return -1; +} + +static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) +{ + TLSContext *p = h->priv_data; + TLSShared *c = &p->tls_shared; + int ret; + + ff_gnutls_init(); + + if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) + goto fail; + + gnutls_init(&p->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT); + if (!c->listen && !c->numerichost) + gnutls_server_name_set(p->session, GNUTLS_NAME_DNS, c->host, strlen(c->host)); + gnutls_certificate_allocate_credentials(&p->cred); + if (c->ca_file) + gnutls_certificate_set_x509_trust_file(p->cred, c->ca_file, GNUTLS_X509_FMT_PEM); +#if GNUTLS_VERSION_MAJOR >= 3 + else + gnutls_certificate_set_x509_system_trust(p->cred); +#endif + gnutls_certificate_set_verify_flags(p->cred, c->verify ? + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0); + if (c->cert_file && c->key_file) { + ret = gnutls_certificate_set_x509_key_file(p->cred, + c->cert_file, c->key_file, + GNUTLS_X509_FMT_PEM); + if (ret < 0) { + av_log(h, AV_LOG_ERROR, + "Unable to set cert/key files %s and %s: %s\n", + c->cert_file, c->key_file, gnutls_strerror(ret)); + ret = AVERROR(EIO); + goto fail; + } + } + gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, p->cred); + gnutls_transport_set_pull_function(p->session, gnutls_url_pull); + gnutls_transport_set_push_function(p->session, gnutls_url_push); + gnutls_transport_set_ptr(p->session, c->tcp); + gnutls_priority_set_direct(p->session, "NORMAL", NULL); + ret = gnutls_handshake(p->session); + if (ret) { + ret = print_tls_error(h, ret); + goto fail; + } + p->need_shutdown = 1; + if (c->verify) { + unsigned int status, cert_list_size; + gnutls_x509_crt_t cert; + const gnutls_datum_t *cert_list; + if ((ret = gnutls_certificate_verify_peers2(p->session, &status)) < 0) { + av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n", + gnutls_strerror(ret)); + ret = AVERROR(EIO); + goto fail; + } + if (status & GNUTLS_CERT_INVALID) { + av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n"); + ret = AVERROR(EIO); + goto fail; + } + if (gnutls_certificate_type_get(p->session) != GNUTLS_CRT_X509) { + av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n"); + ret = AVERROR(EIO); + goto fail; + } + gnutls_x509_crt_init(&cert); + cert_list = gnutls_certificate_get_peers(p->session, &cert_list_size); + gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER); + ret = gnutls_x509_crt_check_hostname(cert, c->host); + gnutls_x509_crt_deinit(cert); + if (!ret) { + av_log(h, AV_LOG_ERROR, + "The certificate's owner does not match hostname %s\n", c->host); + ret = AVERROR(EIO); + goto fail; + } + } + + return 0; +fail: + tls_close(h); + return ret; +} + +static int tls_read(URLContext *h, uint8_t *buf, int size) +{ + TLSContext *c = h->priv_data; + int ret = gnutls_record_recv(c->session, buf, size); + if (ret > 0) + return ret; + if (ret == 0) + return AVERROR_EOF; + return print_tls_error(h, ret); +} + +static int tls_write(URLContext *h, const uint8_t *buf, int size) +{ + TLSContext *c = h->priv_data; + int ret = gnutls_record_send(c->session, buf, size); + if (ret > 0) + return ret; + if (ret == 0) + return AVERROR_EOF; + return print_tls_error(h, ret); +} + +static const AVOption options[] = { + TLS_COMMON_OPTIONS(TLSContext, tls_shared), + { NULL } +}; + +static const AVClass tls_class = { + .class_name = "tls", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_tls_gnutls_protocol = { + .name = "tls", + .url_open2 = tls_open, + .url_read = tls_read, + .url_write = tls_write, + .url_close = tls_close, + .priv_data_size = sizeof(TLSContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &tls_class, +}; diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c new file mode 100644 index 0000000..a75674e --- /dev/null +++ b/libavformat/tls_openssl.c @@ -0,0 +1,297 @@ +/* + * TLS/SSL Protocol + * Copyright (c) 2011 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "internal.h" +#include "network.h" +#include "os_support.h" +#include "url.h" +#include "tls.h" +#include "libavcodec/internal.h" +#include "libavutil/avstring.h" +#include "libavutil/avutil.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/thread.h" + +#include +#include +#include + +static int openssl_init; + +typedef struct TLSContext { + const AVClass *class; + TLSShared tls_shared; + SSL_CTX *ctx; + SSL *ssl; +} TLSContext; + +#if HAVE_THREADS +#include +pthread_mutex_t *openssl_mutexes; +static void openssl_lock(int mode, int type, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&openssl_mutexes[type]); + else + pthread_mutex_unlock(&openssl_mutexes[type]); +} +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 +static unsigned long openssl_thread_id(void) +{ + return (intptr_t) pthread_self(); +} +#endif +#endif + +void ff_openssl_init(void) +{ + avpriv_lock_avformat(); + if (!openssl_init) { + SSL_library_init(); + SSL_load_error_strings(); +#if HAVE_THREADS + if (!CRYPTO_get_locking_callback()) { + int i; + openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&openssl_mutexes[i], NULL); + CRYPTO_set_locking_callback(openssl_lock); +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 + CRYPTO_set_id_callback(openssl_thread_id); +#endif + } +#endif + } + openssl_init++; + avpriv_unlock_avformat(); +} + +void ff_openssl_deinit(void) +{ + avpriv_lock_avformat(); + openssl_init--; + if (!openssl_init) { +#if HAVE_THREADS + if (CRYPTO_get_locking_callback() == openssl_lock) { + int i; + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&openssl_mutexes[i]); + av_free(openssl_mutexes); + } +#endif + } + avpriv_unlock_avformat(); +} + +static int print_tls_error(URLContext *h, int ret) +{ + av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + return AVERROR(EIO); +} + +static int tls_close(URLContext *h) +{ + TLSContext *c = h->priv_data; + if (c->ssl) { + SSL_shutdown(c->ssl); + SSL_free(c->ssl); + } + if (c->ctx) + SSL_CTX_free(c->ctx); + if (c->tls_shared.tcp) + ffurl_close(c->tls_shared.tcp); + ff_openssl_deinit(); + return 0; +} + +static int url_bio_create(BIO *b) +{ + b->init = 1; + b->ptr = NULL; + b->flags = 0; + return 1; +} + +static int url_bio_destroy(BIO *b) +{ + return 1; +} + +static int url_bio_bread(BIO *b, char *buf, int len) +{ + URLContext *h = b->ptr; + int ret = ffurl_read(h, buf, len); + if (ret >= 0) + return ret; + BIO_clear_retry_flags(b); + if (ret == AVERROR_EXIT) + return 0; + return -1; +} + +static int url_bio_bwrite(BIO *b, const char *buf, int len) +{ + URLContext *h = b->ptr; + int ret = ffurl_write(h, buf, len); + if (ret >= 0) + return ret; + BIO_clear_retry_flags(b); + if (ret == AVERROR_EXIT) + return 0; + return -1; +} + +static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + if (cmd == BIO_CTRL_FLUSH) { + BIO_clear_retry_flags(b); + return 1; + } + return 0; +} + +static int url_bio_bputs(BIO *b, const char *str) +{ + return url_bio_bwrite(b, str, strlen(str)); +} + +static BIO_METHOD url_bio_method = { + .type = BIO_TYPE_SOURCE_SINK, + .name = "urlprotocol bio", + .bwrite = url_bio_bwrite, + .bread = url_bio_bread, + .bputs = url_bio_bputs, + .bgets = NULL, + .ctrl = url_bio_ctrl, + .create = url_bio_create, + .destroy = url_bio_destroy, +}; + +static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) +{ + TLSContext *p = h->priv_data; + TLSShared *c = &p->tls_shared; + BIO *bio; + int ret; + + ff_openssl_init(); + + if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) + goto fail; + + p->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method()); + if (!p->ctx) { + av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + ret = AVERROR(EIO); + goto fail; + } + if (c->ca_file) + SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL); + if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) { + av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", + c->cert_file, ERR_error_string(ERR_get_error(), NULL)); + ret = AVERROR(EIO); + goto fail; + } + if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM)) { + av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", + c->key_file, ERR_error_string(ERR_get_error(), NULL)); + ret = AVERROR(EIO); + goto fail; + } + // Note, this doesn't check that the peer certificate actually matches + // the requested hostname. + if (c->verify) + SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER, NULL); + p->ssl = SSL_new(p->ctx); + if (!p->ssl) { + av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + ret = AVERROR(EIO); + goto fail; + } + bio = BIO_new(&url_bio_method); + bio->ptr = c->tcp; + SSL_set_bio(p->ssl, bio, bio); + if (!c->listen && !c->numerichost) + SSL_set_tlsext_host_name(p->ssl, c->host); + ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl); + if (ret == 0) { + av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); + ret = AVERROR(EIO); + goto fail; + } else if (ret < 0) { + ret = print_tls_error(h, ret); + goto fail; + } + + return 0; +fail: + tls_close(h); + return ret; +} + +static int tls_read(URLContext *h, uint8_t *buf, int size) +{ + TLSContext *c = h->priv_data; + int ret = SSL_read(c->ssl, buf, size); + if (ret > 0) + return ret; + if (ret == 0) + return AVERROR_EOF; + return print_tls_error(h, ret); +} + +static int tls_write(URLContext *h, const uint8_t *buf, int size) +{ + TLSContext *c = h->priv_data; + int ret = SSL_write(c->ssl, buf, size); + if (ret > 0) + return ret; + if (ret == 0) + return AVERROR_EOF; + return print_tls_error(h, ret); +} + +static const AVOption options[] = { + TLS_COMMON_OPTIONS(TLSContext, tls_shared), + { NULL } +}; + +static const AVClass tls_class = { + .class_name = "tls", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_tls_openssl_protocol = { + .name = "tls", + .url_open2 = tls_open, + .url_read = tls_read, + .url_write = tls_write, + .url_close = tls_close, + .priv_data_size = sizeof(TLSContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &tls_class, +}; diff --git a/libavformat/tmv.c b/libavformat/tmv.c index 103ac4a..0283dda 100644 --- a/libavformat/tmv.c +++ b/libavformat/tmv.c @@ -81,8 +81,8 @@ static int tmv_read_header(AVFormatContext *s) if (!(ast = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); - ast->codec->sample_rate = avio_rl16(pb); - if (!ast->codec->sample_rate) { + ast->codecpar->sample_rate = avio_rl16(pb); + if (!ast->codecpar->sample_rate) { av_log(s, AV_LOG_ERROR, "invalid sample rate\n"); return -1; } @@ -111,29 +111,29 @@ static int tmv_read_header(AVFormatContext *s) return -1; } - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; if (features & TMV_STEREO) { - ast->codec->channels = 2; - ast->codec->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->channels = 2; + ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; } else { - ast->codec->channels = 1; - ast->codec->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - ast->codec->bits_per_coded_sample = 8; - ast->codec->bit_rate = ast->codec->sample_rate * - ast->codec->bits_per_coded_sample; - avpriv_set_pts_info(ast, 32, 1, ast->codec->sample_rate); + ast->codecpar->bits_per_coded_sample = 8; + ast->codecpar->bit_rate = ast->codecpar->sample_rate * + ast->codecpar->bits_per_coded_sample; + avpriv_set_pts_info(ast, 32, 1, ast->codecpar->sample_rate); - fps.num = ast->codec->sample_rate * ast->codec->channels; + fps.num = ast->codecpar->sample_rate * ast->codecpar->channels; fps.den = tmv->audio_chunk_size; av_reduce(&fps.num, &fps.den, fps.num, fps.den, 0xFFFFFFFFLL); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_TMV; - vst->codec->pix_fmt = AV_PIX_FMT_PAL8; - vst->codec->width = char_cols * 8; - vst->codec->height = char_rows * 8; + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_TMV; + vst->codecpar->format = AV_PIX_FMT_PAL8; + vst->codecpar->width = char_cols * 8; + vst->codecpar->height = char_rows * 8; avpriv_set_pts_info(vst, 32, fps.den, fps.num); if (features & TMV_PADDING) @@ -141,8 +141,8 @@ static int tmv_read_header(AVFormatContext *s) ((tmv->video_chunk_size + tmv->audio_chunk_size + 511) & ~511) - (tmv->video_chunk_size + tmv->audio_chunk_size); - vst->codec->bit_rate = ((tmv->video_chunk_size + tmv->padding) * - fps.num * 8) / fps.den; + vst->codecpar->bit_rate = ((tmv->video_chunk_size + tmv->padding) * + fps.num * 8) / fps.den; return 0; } diff --git a/libavformat/tta.c b/libavformat/tta.c index e5e6e71..091b502 100644 --- a/libavformat/tta.c +++ b/libavformat/tta.c @@ -19,13 +19,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/get_bits.h" +#include "libavutil/dict.h" +#include "libavutil/intreadwrite.h" + #include "avformat.h" #include "internal.h" #include "id3v1.h" -#include "libavutil/dict.h" -typedef struct { +typedef struct TTAContext { int totalframes, currentframe; int frame_size; int last_frame_size; @@ -45,12 +46,14 @@ static int tta_read_header(AVFormatContext *s) TTAContext *c = s->priv_data; AVStream *st; int i, channels, bps, samplerate, datalen; - uint64_t framepos, start_offset; + int64_t framepos, start_offset; if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); start_offset = avio_tell(s->pb); + if (start_offset < 0) + return start_offset; if (avio_rl32(s->pb) != AV_RL32("TTA1")) return -1; // not tta file @@ -91,7 +94,10 @@ static int tta_read_header(AVFormatContext *s) st->start_time = 0; st->duration = datalen; - framepos = avio_tell(s->pb) + 4*c->totalframes + 4; + framepos = avio_tell(s->pb); + if (framepos < 0) + return framepos; + framepos += 4 * c->totalframes + 4; for (i = 0; i < c->totalframes; i++) { uint32_t size = avio_rl32(s->pb); @@ -101,25 +107,25 @@ static int tta_read_header(AVFormatContext *s) } avio_skip(s->pb, 4); // seektable crc - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_TTA; - st->codec->channels = channels; - st->codec->sample_rate = samplerate; - st->codec->bits_per_coded_sample = bps; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_TTA; + st->codecpar->channels = channels; + st->codecpar->sample_rate = samplerate; + st->codecpar->bits_per_coded_sample = bps; - st->codec->extradata_size = avio_tell(s->pb) - start_offset; - if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ + st->codecpar->extradata_size = avio_tell(s->pb) - start_offset; + if (st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codecpar->extradata_size) { //this check is redundant as avio_read 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); - if (!st->codec->extradata) { - st->codec->extradata_size = 0; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) { + st->codecpar->extradata_size = 0; return AVERROR(ENOMEM); } avio_seek(s->pb, start_offset, SEEK_SET); - avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); + avio_read(s->pb, st->codecpar->extradata, st->codecpar->extradata_size); return 0; } diff --git a/libavformat/tty.c b/libavformat/tty.c index 0ae1510..d4c4873 100644 --- a/libavformat/tty.c +++ b/libavformat/tty.c @@ -34,7 +34,7 @@ #include "internal.h" #include "sauce.h" -typedef struct { +typedef struct TtyDemuxContext { AVClass *class; int chars_per_frame; uint64_t fsize; /**< file size less metadata buffer */ @@ -83,9 +83,9 @@ static int read_header(AVFormatContext *avctx) ret = AVERROR(ENOMEM); goto fail; } - st->codec->codec_tag = 0; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_ANSI; + st->codecpar->codec_tag = 0; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_ANSI; if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) { av_log (avctx, AV_LOG_ERROR, "Couldn't parse video size.\n"); @@ -95,8 +95,8 @@ static int read_header(AVFormatContext *avctx) av_log(avctx, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate); goto fail; } - st->codec->width = width; - st->codec->height = height; + st->codecpar->width = width; + st->codecpar->height = height; avpriv_set_pts_info(st, 60, framerate.den, framerate.num); st->avg_frame_rate = framerate; diff --git a/libavformat/txd.c b/libavformat/txd.c index e6522c3..809ec33 100644 --- a/libavformat/txd.c +++ b/libavformat/txd.c @@ -44,8 +44,8 @@ static int txd_read_header(AVFormatContext *s) { st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_TXD; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_TXD; avpriv_set_pts_info(st, 64, 1, 5); st->avg_frame_rate = av_inv_q(st->time_base); /* the parameters will be extracted from the compressed bitstream */ diff --git a/libavformat/udp.c b/libavformat/udp.c index bfa8cf2..9d4c130 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -30,6 +30,7 @@ #include "avio_internal.h" #include "libavutil/parseutils.h" #include "libavutil/avstring.h" +#include "libavutil/opt.h" #include "internal.h" #include "network.h" #include "os_support.h" @@ -40,21 +41,49 @@ #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif -typedef struct { +typedef struct UDPContext { + const AVClass *class; int udp_fd; int ttl; int buffer_size; + int pkt_size; int is_multicast; int local_port; int reuse_socket; struct sockaddr_storage dest_addr; int dest_addr_len; int is_connected; + char *localaddr; + char *sources; + char *block; } UDPContext; #define UDP_TX_BUF_SIZE 32768 #define UDP_MAX_PKT_SIZE 65536 +#define OFFSET(x) offsetof(UDPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "ttl", "Time to live (in milliseconds, multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, .flags = D|E }, + { "buffer_size", "System data size (in bytes)", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "local_port", "Local port", OFFSET(local_port), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "reuse_socket", "Reuse socket", OFFSET(reuse_socket), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "connect", "Connect socket", OFFSET(is_connected), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "localaddr", "Local address", OFFSET(localaddr), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { NULL } +}; + +static const AVClass udp_class = { + .class_name = "udp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + static void log_net_error(void *ctx, int level, const char* prefix) { char errbuf[100]; @@ -142,7 +171,8 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr) return 0; } -static struct addrinfo* udp_resolve_host(const char *hostname, int port, +static struct addrinfo *udp_resolve_host(URLContext *h, + const char *hostname, int port, int type, int family, int flags) { struct addrinfo hints = { 0 }, *res = 0; @@ -162,13 +192,17 @@ static struct addrinfo* udp_resolve_host(const char *hostname, int port, hints.ai_flags = flags; if ((error = getaddrinfo(node, service, &hints, &res))) { res = NULL; - av_log(NULL, AV_LOG_ERROR, "udp_resolve_host: %s\n", gai_strerror(error)); + av_log(h, AV_LOG_ERROR, "getaddrinfo(%s, %s): %s\n", + node ? node : "unknown", + service ? service : "unknown", + gai_strerror(error)); } return res; } -static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, +static int udp_set_multicast_sources(URLContext *h, + int sockfd, struct sockaddr *addr, int addr_len, char **sources, int nb_sources, int include) { @@ -179,7 +213,7 @@ static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, for (i = 0; i < nb_sources; i++) { struct group_source_req mreqs; int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; - struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0, + struct addrinfo *sourceaddr = udp_resolve_host(h, sources[i], 0, SOCK_DGRAM, AF_UNSPEC, 0); if (!sourceaddr) @@ -209,7 +243,7 @@ static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, } for (i = 0; i < nb_sources; i++) { struct ip_mreq_source mreqs; - struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0, + struct addrinfo *sourceaddr = udp_resolve_host(h, sources[i], 0, SOCK_DGRAM, AF_UNSPEC, 0); if (!sourceaddr) @@ -241,13 +275,14 @@ static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, #endif return 0; } -static int udp_set_url(struct sockaddr_storage *addr, +static int udp_set_url(URLContext *h, + struct sockaddr_storage *addr, const char *hostname, int port) { struct addrinfo *res0; int addr_len; - res0 = udp_resolve_host(hostname, port, SOCK_DGRAM, AF_UNSPEC, 0); + res0 = udp_resolve_host(h, hostname, port, SOCK_DGRAM, AF_UNSPEC, 0); if (res0 == 0) return AVERROR(EIO); memcpy(addr, res0->ai_addr, res0->ai_addrlen); addr_len = res0->ai_addrlen; @@ -256,16 +291,18 @@ static int udp_set_url(struct sockaddr_storage *addr, return addr_len; } -static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, +static int udp_socket_create(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len, const char *localaddr) { + UDPContext *s = h->priv_data; int udp_fd = -1; struct addrinfo *res0 = NULL, *res = NULL; int family = AF_UNSPEC; if (((struct sockaddr *) &s->dest_addr)->sa_family) family = ((struct sockaddr *) &s->dest_addr)->sa_family; - res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port, + res0 = udp_resolve_host(h, (localaddr && localaddr[0]) ? localaddr : NULL, + s->local_port, SOCK_DGRAM, family, AI_PASSIVE); if (res0 == 0) goto fail; @@ -332,7 +369,7 @@ int ff_udp_set_remote_url(URLContext *h, const char *uri) av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* set the destination address */ - s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port); + s->dest_addr_len = udp_set_url(h, &s->dest_addr, hostname, port); if (s->dest_addr_len < 0) { return AVERROR(EIO); } @@ -411,7 +448,6 @@ static int udp_open(URLContext *h, const char *uri, int flags) char buf[256]; struct sockaddr_storage my_addr; socklen_t len; - int reuse_specified = 0; int i, num_include_sources = 0, num_exclude_sources = 0; char *include_sources[32], *exclude_sources[32]; @@ -420,8 +456,24 @@ static int udp_open(URLContext *h, const char *uri, int flags) is_output = !(flags & AVIO_FLAG_READ); - s->ttl = 16; - s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; + if (s->buffer_size < 0) + s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; + + if (s->sources) { + if (parse_source_list(s->sources, include_sources, + &num_include_sources, + FF_ARRAY_ELEMS(include_sources))) + goto fail; + } + + if (s->block) { + if (parse_source_list(s->block, exclude_sources, &num_exclude_sources, + FF_ARRAY_ELEMS(exclude_sources))) + goto fail; + } + + if (s->pkt_size > 0) + h->max_packet_size = s->pkt_size; p = strchr(uri, '?'); if (p) { @@ -431,7 +483,6 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->reuse_socket = 1; - reuse_specified = 1; } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); @@ -476,16 +527,20 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } - if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ)) + if ((s->is_multicast || s->local_port < 0) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; - udp_fd = udp_socket_create(s, &my_addr, &len, localaddr); + + if (localaddr[0]) + udp_fd = udp_socket_create(h, &my_addr, &len, localaddr); + else + udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); if (udp_fd < 0) goto fail; /* Follow the requested reuse option, unless it's multicast in which * case enable reuse unless explicitly disabled. */ - if (s->reuse_socket || (s->is_multicast && !reuse_specified)) { + if (s->reuse_socket > 0 || (s->is_multicast && s->reuse_socket < 0)) { s->reuse_socket = 1; if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) goto fail; @@ -523,14 +578,22 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } if (num_include_sources) { - if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0) + if (udp_set_multicast_sources(h, udp_fd, + (struct sockaddr *)&s->dest_addr, + s->dest_addr_len, + include_sources, + num_include_sources, 1) < 0) goto fail; } else { if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } if (num_exclude_sources) { - if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0) + if (udp_set_multicast_sources(h, udp_fd, + (struct sockaddr *)&s->dest_addr, + s->dest_addr_len, + exclude_sources, + num_exclude_sources, 0) < 0) goto fail; } } @@ -622,7 +685,7 @@ static int udp_close(URLContext *h) return 0; } -URLProtocol ff_udp_protocol = { +const URLProtocol ff_udp_protocol = { .name = "udp", .url_open = udp_open, .url_read = udp_read, @@ -631,4 +694,5 @@ URLProtocol ff_udp_protocol = { .url_get_file_handle = udp_get_file_handle, .priv_data_size = sizeof(UDPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &udp_class, }; diff --git a/libavformat/unix.c b/libavformat/unix.c index ab57c68..647e7e8 100644 --- a/libavformat/unix.c +++ b/libavformat/unix.c @@ -23,7 +23,6 @@ * @file * * Unix socket url_protocol - * */ #include @@ -74,13 +73,15 @@ static int unix_open(URLContext *h, const char *filename, int flags) if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) return ff_neterrno(); + if (s->timeout < 0 && h->rw_timeout) + s->timeout = h->rw_timeout / 1000; + if (s->listen) { - fd = ff_listen_bind(fd, (struct sockaddr *)&s->addr, - sizeof(s->addr), s->timeout, h); - if (fd < 0) { - ret = fd; + ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr, + sizeof(s->addr), s->timeout, h); + if (ret < 0) goto fail; - } + fd = ret; } else { ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h, 0); @@ -124,7 +125,7 @@ static int unix_write(URLContext *h, const uint8_t *buf, int size) if (ret < 0) return ret; } - ret = send(s->fd, buf, size, 0); + ret = send(s->fd, buf, size, MSG_NOSIGNAL); return ret < 0 ? ff_neterrno() : ret; } @@ -143,7 +144,7 @@ static int unix_get_file_handle(URLContext *h) return s->fd; } -URLProtocol ff_unix_protocol = { +const URLProtocol ff_unix_protocol = { .name = "unix", .url_open = unix_open, .url_read = unix_read, diff --git a/libavformat/url.h b/libavformat/url.h index 40be4d5..5853ffe 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -34,13 +33,15 @@ #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ #define URL_PROTOCOL_FLAG_NETWORK 2 /*< The protocol uses network */ -extern int (*url_interrupt_cb)(void); - extern const AVClass ffurl_context_class; typedef struct URLContext { const AVClass *av_class; /**< information for av_log(). Set by url_open(). */ - struct URLProtocol *prot; + const struct URLProtocol *prot; + /** + * A NULL-terminated list of protocols usable by the child contexts. + */ + const struct URLProtocol **protocols; void *priv_data; char *filename; /**< specified URL */ int flags; @@ -48,6 +49,7 @@ typedef struct URLContext { int is_streamed; /**< true if streamed (no seek possible), default = false */ int is_connected; AVIOInterruptCB interrupt_callback; + int64_t rw_timeout; /**< maximum time to wait for (network) read/write operation completion, in microseconds */ } URLContext; typedef struct URLProtocol { @@ -76,7 +78,6 @@ typedef struct URLProtocol { int (*url_write)(URLContext *h, const unsigned char *buf, int size); int64_t (*url_seek)( URLContext *h, int64_t pos, int whence); int (*url_close)(URLContext *h); - struct URLProtocol *next; int (*url_read_pause)(URLContext *h, int pause); int64_t (*url_read_seek)(URLContext *h, int stream_index, int64_t timestamp, int flags); @@ -100,11 +101,15 @@ typedef struct URLProtocol { * is to be opened * @param int_cb interrupt callback to use for the URLContext, may be * NULL + * @param protocols a NULL-terminate list of protocols available for use by + * this context and its children. The caller must ensure this + * list remains valid until the context is closed. * @return 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ int ffurl_alloc(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb); + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols); /** * Connect an URLContext that has been allocated by ffurl_alloc @@ -129,11 +134,17 @@ int ffurl_connect(URLContext *uc, AVDictionary **options); * @param options A dictionary filled with protocol-private options. On return * this parameter will be destroyed and replaced with a dict containing options * that were not found. May be NULL. + * @param protocols a NULL-terminate list of protocols available for use by + * this context and its children. The caller must ensure this + * list remains valid until the context is closed. + * @param parent An enclosing URLContext, whose generic options should + * be applied to this URLContext as well. * @return 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb, AVDictionary **options); + const AVIOInterruptCB *int_cb, AVDictionary **options, + const URLProtocol **protocols, URLContext *parent); /** * Read up to size bytes from the resource accessed by h, and store @@ -223,23 +234,11 @@ int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles); int ffurl_shutdown(URLContext *h, int flags); /** - * Register the URLProtocol protocol. - */ -int ffurl_register_protocol(URLProtocol *protocol); - -/** - * Check if the user has requested to interrup a blocking function + * Check if the user has requested to interrupt a blocking function * associated with cb. */ int ff_check_interrupt(AVIOInterruptCB *cb); -/** - * Iterate over all available protocols. - * - * @param prev result of the previous call to this functions or NULL. - */ -URLProtocol *ffurl_protocol_next(const URLProtocol *prev); - /* udp.c */ int ff_udp_set_remote_url(URLContext *h, const char *uri); int ff_udp_get_local_port(URLContext *h); @@ -280,5 +279,22 @@ int ff_url_join(char *str, int size, const char *proto, void ff_make_absolute_url(char *buf, int size, const char *base, const char *rel); +const AVClass *ff_urlcontext_child_class_next(const AVClass *prev); + +/** + * Construct a list of protocols matching a given whitelist and/or blacklist. + * + * @param whitelist a comma-separated list of allowed protocol names or NULL. If + * this is a non-empty string, only protocols in this list will + * be included. + * @param blacklist a comma-separated list of forbidden protocol names or NULL. + * If this is a non-empty string, all protocols in this list + * will be excluded. + * + * @return a NULL-terminated array of matching protocols. The array must be + * freed by the caller. + */ +const URLProtocol **ffurl_get_protocols(const char *whitelist, + const char *blacklist); #endif /* AVFORMAT_URL_H */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 94431e1..60c534d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -110,7 +110,7 @@ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size) pkt->pos = orig_pos; if (!pkt->size) - av_free_packet(pkt); + av_packet_unref(pkt); return pkt->size > orig_size ? pkt->size - orig_size : ret; } @@ -167,8 +167,14 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, fmt->name, score); for (i = 0; fmt_id_type[i].name; i++) { if (!strcmp(fmt->name, fmt_id_type[i].name)) { - st->codec->codec_id = fmt_id_type[i].id; - st->codec->codec_type = fmt_id_type[i].type; + st->codecpar->codec_id = fmt_id_type[i].id; + st->codecpar->codec_type = fmt_id_type[i].type; +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + st->codec->codec_type = st->codecpar->codec_type; + st->codec->codec_id = st->codecpar->codec_id; +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; } } @@ -200,8 +206,8 @@ static int init_input(AVFormatContext *s, const char *filename, (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) return 0; - if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, - &s->interrupt_callback, options)) < 0) + ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ, options); + if (ret < 0) return ret; if (s->iformat) return 0; @@ -209,12 +215,23 @@ static int init_input(AVFormatContext *s, const char *filename, s, 0, s->probesize); } -static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, - AVPacketList **plast_pktl) +static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, + AVPacketList **plast_pktl, int ref) { AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); + int ret; + if (!pktl) - return NULL; + return AVERROR(ENOMEM); + + if (ref) { + if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) { + av_free(pktl); + return ret; + } + } else { + pktl->pkt = *pkt; + } if (*packet_buffer) (*plast_pktl)->next = pktl; @@ -223,32 +240,52 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, /* Add the packet in the buffered packet list. */ *plast_pktl = pktl; - pktl->pkt = *pkt; - return &pktl->pkt; + return 0; } static int queue_attached_pictures(AVFormatContext *s) { - int i; + int i, ret; for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && s->streams[i]->discard < AVDISCARD_ALL) { - AVPacket copy = s->streams[i]->attached_pic; - copy.buf = av_buffer_ref(copy.buf); - if (!copy.buf) - return AVERROR(ENOMEM); - add_to_pktbuf(&s->raw_packet_buffer, ©, - &s->raw_packet_buffer_end); + ret = add_to_pktbuf(&s->internal->raw_packet_buffer, + &s->streams[i]->attached_pic, + &s->internal->raw_packet_buffer_end, 1); + if (ret < 0) + return ret; } return 0; } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS +static int update_stream_avctx(AVFormatContext *s) +{ + int i, ret; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + + if (!st->internal->need_codec_update) + continue; + + ret = avcodec_parameters_to_context(st->codec, st->codecpar); + if (ret < 0) + return ret; + + st->internal->need_codec_update = 0; + } + return 0; +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) { AVFormatContext *s = *ps; - int ret = 0; + int i, ret = 0; AVDictionary *tmp = NULL; ID3v2ExtraMeta *id3v2_extra_meta = NULL; @@ -307,10 +344,17 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, if ((ret = queue_attached_pictures(s)) < 0) goto fail; - if (s->pb && !s->data_offset) - s->data_offset = avio_tell(s->pb); + if (s->pb && !s->internal->data_offset) + s->internal->data_offset = avio_tell(s->pb); + + s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; +#if FF_API_LAVF_AVCTX + update_stream_avctx(s); +#endif + + for (i = 0; i < s->nb_streams; i++) + s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id; if (options) { av_dict_free(options); @@ -333,7 +377,7 @@ fail: static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) { - if (st->codec->codec_id == AV_CODEC_ID_PROBE) { + if (st->codecpar->codec_id == AV_CODEC_ID_PROBE) { AVProbeData *pd = &st->probe_data; av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index); --st->probe_packets; @@ -359,7 +403,7 @@ static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) { set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX / 4 : 0); - if (st->codec->codec_id != AV_CODEC_ID_PROBE) { + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE) { pd->buf_size = 0; av_freep(&pd->buf); av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index); @@ -375,14 +419,14 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) AVStream *st; for (;;) { - AVPacketList *pktl = s->raw_packet_buffer; + AVPacketList *pktl = s->internal->raw_packet_buffer; if (pktl) { *pkt = pktl->pkt; st = s->streams[pkt->stream_index]; - if (st->codec->codec_id != AV_CODEC_ID_PROBE || + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE || !st->probe_packets || - s->raw_packet_buffer_remaining_size < pkt->size) { + s->internal->raw_packet_buffer_remaining_size < pkt->size) { AVProbeData *pd; if (st->probe_packets) if ((err = probe_codec(s, st, NULL)) < 0) @@ -390,8 +434,8 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) pd = &st->probe_data; av_freep(&pd->buf); pd->buf_size = 0; - s->raw_packet_buffer = pktl->next; - s->raw_packet_buffer_remaining_size += pkt->size; + s->internal->raw_packet_buffer = pktl->next; + s->internal->raw_packet_buffer_remaining_size += pkt->size; av_free(pktl); return 0; } @@ -413,38 +457,49 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } + if (!pkt->buf) { + AVPacket tmp = { 0 }; + ret = av_packet_ref(&tmp, pkt); + if (ret < 0) + return ret; + *pkt = tmp; + } + if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) && (pkt->flags & AV_PKT_FLAG_CORRUPT)) { av_log(s, AV_LOG_WARNING, "Dropped corrupted packet (stream = %d)\n", pkt->stream_index); - av_free_packet(pkt); + av_packet_unref(pkt); continue; } st = s->streams[pkt->stream_index]; - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: if (s->video_codec_id) - st->codec->codec_id = s->video_codec_id; + st->codecpar->codec_id = s->video_codec_id; break; case AVMEDIA_TYPE_AUDIO: if (s->audio_codec_id) - st->codec->codec_id = s->audio_codec_id; + st->codecpar->codec_id = s->audio_codec_id; break; case AVMEDIA_TYPE_SUBTITLE: if (s->subtitle_codec_id) - st->codec->codec_id = s->subtitle_codec_id; + st->codecpar->codec_id = s->subtitle_codec_id; break; } - if (!pktl && (st->codec->codec_id != AV_CODEC_ID_PROBE || + if (!pktl && (st->codecpar->codec_id != AV_CODEC_ID_PROBE || !st->probe_packets)) return ret; - add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end); - s->raw_packet_buffer_remaining_size -= pkt->size; + err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt, + &s->internal->raw_packet_buffer_end, 0); + if (err) + return err; + s->internal->raw_packet_buffer_remaining_size -= pkt->size; if ((err = probe_codec(s, st, pkt)) < 0) return err; @@ -454,37 +509,18 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) /**********************************************************/ /** - * Get the number of samples of an audio frame. Return -1 on error. - */ -int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux) -{ - int frame_size; - - /* give frame_size priority if demuxing */ - if (!mux && enc->frame_size > 1) - return enc->frame_size; - - if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0) - return frame_size; - - /* Fall back on using frame_size if muxing. */ - if (enc->frame_size > 1) - return enc->frame_size; - - return -1; -} - -/** * Return the frame duration in seconds. Return 0 if not available. */ -void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st, +void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st, AVCodecParserContext *pc, AVPacket *pkt) { + AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate : + (AVRational){ 0, 1 }; int frame_size; *pnum = 0; *pden = 0; - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: if (st->avg_frame_rate.num) { *pnum = st->avg_frame_rate.den; @@ -492,9 +528,9 @@ void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st, } else 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; + } else if (codec_framerate.den * 1000LL > codec_framerate.num) { + *pnum = codec_framerate.den; + *pden = codec_framerate.num; if (pc && pc->repeat_pict) { if (*pnum > INT_MAX / (1 + pc->repeat_pict)) *pden /= 1 + pc->repeat_pict; @@ -504,16 +540,16 @@ void ff_compute_frame_duration(int *pnum, int *pden, AVStream *st, /* If this codec can be interlaced or progressive then we need * a parser to compute duration of a packet. Thus if we have * no parser in such case leave duration undefined. */ - if (st->codec->ticks_per_frame > 1 && !pc) + if (st->internal->avctx->ticks_per_frame > 1 && !pc) *pnum = *pden = 0; } break; case AVMEDIA_TYPE_AUDIO: - frame_size = ff_get_audio_frame_size(st->codec, pkt->size, 0); - if (frame_size <= 0 || st->codec->sample_rate <= 0) + frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size); + if (frame_size <= 0 || st->codecpar->sample_rate <= 0) break; *pnum = frame_size; - *pden = st->codec->sample_rate; + *pden = st->codecpar->sample_rate; break; default: break; @@ -534,7 +570,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, int64_t dts, int64_t pts) { AVStream *st = s->streams[stream_index]; - AVPacketList *pktl = s->packet_buffer; + AVPacketList *pktl = s->internal->packet_buffer; if (st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || @@ -564,7 +600,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, static void update_initial_durations(AVFormatContext *s, AVStream *st, int stream_index, int duration) { - AVPacketList *pktl = s->packet_buffer; + AVPacketList *pktl = s->internal->packet_buffer; int64_t cur_dts = 0; if (st->first_dts != AV_NOPTS_VALUE) { @@ -578,7 +614,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, cur_dts -= duration; } } - pktl = s->packet_buffer; + pktl = s->internal->packet_buffer; st->first_dts = cur_dts; } else if (st->cur_dts) return; @@ -590,10 +626,10 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, pktl->pkt.dts == AV_NOPTS_VALUE && !pktl->pkt.duration) { pktl->pkt.dts = cur_dts; - if (!st->codec->has_b_frames) + if (!st->internal->avctx->has_b_frames) pktl->pkt.pts = cur_dts; cur_dts += duration; - if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) pktl->pkt.duration = duration; } else break; @@ -615,7 +651,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->dts = AV_NOPTS_VALUE; /* do we have a video B-frame ? */ - delay = st->codec->has_b_frames; + delay = st->internal->avctx->has_b_frames; presentation_delayed = 0; /* XXX: need has_b_frame, but cannot get it if the codec is @@ -637,17 +673,17 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if (delay == 1 && pkt->dts == pkt->pts && pkt->dts != AV_NOPTS_VALUE && presentation_delayed) { av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination\n"); - pkt->dts = pkt->pts = AV_NOPTS_VALUE; + pkt->dts = AV_NOPTS_VALUE; } - if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { - ff_compute_frame_duration(&num, &den, st, pc, pkt); + if (pkt->duration == 0 && st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { + ff_compute_frame_duration(s, &num, &den, st, pc, pkt); if (den && num) { pkt->duration = av_rescale_rnd(1, num * (int64_t) st->time_base.den, den * (int64_t) st->time_base.num, AV_ROUND_DOWN); - if (pkt->duration != 0 && s->packet_buffer) + if (pkt->duration != 0 && s->internal->packet_buffer) update_initial_durations(s, st, pkt->stream_index, pkt->duration); } @@ -670,7 +706,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->pts > pkt->dts) presentation_delayed = 1; - av_dlog(NULL, + av_log(NULL, AV_LOG_TRACE, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" " "cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, @@ -678,7 +714,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, /* Interpolate PTS and DTS if they are not present. We skip H.264 * currently because delay and has_b_frames are not reliably set. */ if ((delay == 0 || (delay == 1 && pc)) && - st->codec->codec_id != AV_CODEC_ID_H264) { + st->codecpar->codec_id != AV_CODEC_ID_H264) { if (presentation_delayed) { /* DTS = decompression timestamp */ /* PTS = presentation timestamp */ @@ -701,16 +737,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } else if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = pkt->duration; - if (!duration && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - ff_compute_frame_duration(&num, &den, st, pc, pkt); + if (!duration && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + ff_compute_frame_duration(s, &num, &den, st, pc, pkt); if (den && num) { duration = av_rescale_rnd(1, num * (int64_t) st->time_base.den, den * (int64_t) st->time_base.num, AV_ROUND_DOWN); - if (duration != 0 && s->packet_buffer) + if (duration != 0 && s->internal->packet_buffer) update_initial_durations(s, st, pkt->stream_index, duration); } @@ -739,22 +775,26 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if (pkt->dts == AV_NOPTS_VALUE) pkt->dts = st->pts_buffer[0]; // We skipped it above so we try here. - if (st->codec->codec_id == AV_CODEC_ID_H264) + if (st->codecpar->codec_id == AV_CODEC_ID_H264) // This should happen on the first packet update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); if (pkt->dts > st->cur_dts) st->cur_dts = pkt->dts; } - av_dlog(NULL, + av_log(NULL, AV_LOG_TRACE, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts); /* update flags */ - if (is_intra_only(st->codec->codec_id)) + if (is_intra_only(st->codecpar->codec_id)) pkt->flags |= AV_PKT_FLAG_KEY; +#if FF_API_CONVERGENCE_DURATION +FF_DISABLE_DEPRECATION_WARNINGS if (pc) pkt->convergence_duration = pc->convergence_duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) @@ -762,7 +802,7 @@ static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_en while (*pkt_buf) { AVPacketList *pktl = *pkt_buf; *pkt_buf = pktl->next; - av_free_packet(&pktl->pkt); + av_packet_unref(&pktl->pkt); av_freep(&pktl); } *pkt_buf_end = NULL; @@ -791,7 +831,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) int len; av_init_packet(&out_pkt); - len = av_parser_parse2(st->parser, st->codec, + len = av_parser_parse2(st->parser, st->internal->avctx, &out_pkt.data, &out_pkt.size, data, size, pkt->pts, pkt->dts, pkt->pos); @@ -814,11 +854,11 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) /* set the duration */ out_pkt.duration = 0; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->sample_rate > 0) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->internal->avctx->sample_rate > 0) { out_pkt.duration = av_rescale_q_rnd(st->parser->duration, - (AVRational) { 1, st->codec->sample_rate }, + (AVRational) { 1, st->internal->avctx->sample_rate }, st->time_base, AV_ROUND_DOWN); } @@ -843,22 +883,10 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) 0, 0, AVINDEX_KEYFRAME); } - if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) { - out_pkt.buf = pkt->buf; - pkt->buf = NULL; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - out_pkt.destruct = pkt->destruct; - pkt->destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - } - if ((ret = av_dup_packet(&out_pkt)) < 0) - goto fail; - - if (!add_to_pktbuf(&s->parse_queue, &out_pkt, &s->parse_queue_end)) { - av_free_packet(&out_pkt); - ret = AVERROR(ENOMEM); + if ((ret = add_to_pktbuf(&s->internal->parse_queue, &out_pkt, + &s->internal->parse_queue_end, + 1))) { + av_packet_unref(&out_pkt); goto fail; } } @@ -870,7 +898,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } fail: - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } @@ -896,7 +924,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) av_init_packet(pkt); - while (!got_packet && !s->parse_queue) { + while (!got_packet && !s->internal->parse_queue) { AVStream *st; AVPacket cur_pkt; @@ -930,12 +958,12 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", " - "size=%d, duration=%d, flags=%d\n", + "size=%d, duration=%"PRId64", flags=%d\n", cur_pkt.stream_index, cur_pkt.pts, cur_pkt.dts, cur_pkt.size, cur_pkt.duration, cur_pkt.flags); if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { - st->parser = av_parser_init(st->codec->codec_id); + st->parser = av_parser_init(st->codecpar->codec_id); if (!st->parser) /* no parser available: just output the raw packets */ st->need_parsing = AVSTREAM_PARSE_NONE; @@ -961,12 +989,12 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; } else { /* free packet */ - av_free_packet(&cur_pkt); + av_packet_unref(&cur_pkt); } } - if (!got_packet && s->parse_queue) - ret = read_from_packet_buffer(&s->parse_queue, &s->parse_queue_end, pkt); + if (!got_packet && s->internal->parse_queue) + ret = read_from_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata); if (metadata) { @@ -976,10 +1004,14 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN); } +#if FF_API_LAVF_AVCTX + update_stream_avctx(s); +#endif + if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", " - "size=%d, duration=%d, flags=%d\n", + "size=%d, duration=%"PRId64", flags=%d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->size, pkt->duration, pkt->flags); @@ -992,14 +1024,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) int eof = 0; if (!genpts) - return s->packet_buffer - ? read_from_packet_buffer(&s->packet_buffer, - &s->packet_buffer_end, pkt) + return s->internal->packet_buffer + ? read_from_packet_buffer(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, pkt) : read_frame_internal(s, pkt); for (;;) { int ret; - AVPacketList *pktl = s->packet_buffer; + AVPacketList *pktl = s->internal->packet_buffer; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1015,14 +1047,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } pktl = pktl->next; } - pktl = s->packet_buffer; + pktl = s->internal->packet_buffer; } /* read packet from packet buffer, if there is data */ if (!(next_pkt->pts == AV_NOPTS_VALUE && next_pkt->dts != AV_NOPTS_VALUE && !eof)) - return read_from_packet_buffer(&s->packet_buffer, - &s->packet_buffer_end, pkt); + return read_from_packet_buffer(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, pkt); } ret = read_frame_internal(s, pkt); @@ -1034,20 +1066,21 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - if (av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt, - &s->packet_buffer_end)) < 0) - return AVERROR(ENOMEM); + ret = add_to_pktbuf(&s->internal->packet_buffer, pkt, + &s->internal->packet_buffer_end, 1); + if (ret < 0) + return ret; } } /* XXX: suppress the packet queue */ static void flush_packet_queue(AVFormatContext *s) { - free_packet_buffer(&s->parse_queue, &s->parse_queue_end); - free_packet_buffer(&s->packet_buffer, &s->packet_buffer_end); - free_packet_buffer(&s->raw_packet_buffer, &s->raw_packet_buffer_end); + free_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end); + free_packet_buffer(&s->internal->packet_buffer, &s->internal->packet_buffer_end); + free_packet_buffer(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } /*******************************************************/ @@ -1063,12 +1096,12 @@ int av_find_default_stream_index(AVFormatContext *s) return -1; for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { return i; } if (first_audio_index < 0 && - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) first_audio_index = i; } return first_audio_index >= 0 ? first_audio_index : 0; @@ -1238,7 +1271,7 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, if (stream_index < 0) return -1; - av_dlog(s, "read_seek: %d %"PRId64"\n", stream_index, target_ts); + av_log(s, AV_LOG_TRACE, "read_seek: %d %"PRId64"\n", stream_index, target_ts); ts_max = ts_min = AV_NOPTS_VALUE; @@ -1258,7 +1291,7 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, if (e->timestamp <= target_ts || e->pos == e->min_distance) { pos_min = e->pos; ts_min = e->timestamp; - av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", + av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", pos_min, ts_min); } else { assert(index == 0); @@ -1273,7 +1306,7 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, pos_max = e->pos; ts_max = e->timestamp; pos_limit = pos_max - e->min_distance; - av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64 + av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64 " dts_max=%"PRId64"\n", pos_max, pos_limit, ts_max); } } @@ -1303,10 +1336,10 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t start_pos, filesize; int no_change; - av_dlog(s, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); + av_log(s, AV_LOG_TRACE, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); if (ts_min == AV_NOPTS_VALUE) { - pos_min = s->data_offset; + pos_min = s->internal->data_offset; ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); if (ts_min == AV_NOPTS_VALUE) return -1; @@ -1346,7 +1379,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, no_change = 0; while (pos_min < pos_limit) { - av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64 + av_log(s, AV_LOG_TRACE, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64 " dts_max=%"PRId64"\n", pos_min, pos_max, ts_min, ts_max); assert(pos_limit <= pos_max); @@ -1376,7 +1409,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, no_change++; else no_change = 0; - av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64 + av_log(s, AV_LOG_TRACE, "%"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); @@ -1402,7 +1435,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, 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_dlog(s, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", + av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", pos, ts_min, target_ts, ts_max); *ts_ret = ts; return pos; @@ -1413,7 +1446,7 @@ static int seek_frame_byte(AVFormatContext *s, int stream_index, { int64_t pos_min, pos_max; - pos_min = s->data_offset; + pos_min = s->internal->data_offset; pos_max = avio_size(s->pb) - 1; if (pos < pos_min) @@ -1452,7 +1485,7 @@ static int seek_frame_generic(AVFormatContext *s, int stream_index, return ret; ff_update_cur_dts(s, st, ie->timestamp); } else { - if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0) + if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0) return ret; } for (;;) { @@ -1462,7 +1495,7 @@ static int seek_frame_generic(AVFormatContext *s, int stream_index, } while (read_status == AVERROR(EAGAIN)); if (read_status < 0) break; - av_free_packet(&pkt); + av_packet_unref(&pkt); if (stream_index == pkt.stream_index) if ((pkt.flags & AV_PKT_FLAG_KEY) && pkt.dts > timestamp) break; @@ -1671,12 +1704,12 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic) int bit_rate = 0; for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - if (st->codec->bit_rate > 0) { - if (INT_MAX - st->codec->bit_rate < bit_rate) { + if (st->codecpar->bit_rate > 0) { + if (INT_MAX - st->codecpar->bit_rate < bit_rate) { bit_rate = 0; break; } - bit_rate += st->codec->bit_rate; + bit_rate += st->codecpar->bit_rate; } } ic->bit_rate = bit_rate; @@ -1718,7 +1751,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->start_time == AV_NOPTS_VALUE && st->first_dts == AV_NOPTS_VALUE) - av_log(st->codec, AV_LOG_WARNING, + av_log(ic, AV_LOG_WARNING, "start time is not set in estimate_timings_from_pts\n"); if (st->parser) { @@ -1764,7 +1797,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) st->duration = duration; } } - av_free_packet(pkt); + av_packet_unref(pkt); } } while (end_time == AV_NOPTS_VALUE && filesize > (DURATION_MAX_READ_SIZE << retry) && @@ -1814,11 +1847,11 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) AVStream av_unused *st; for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - av_dlog(ic, "%d: start_time: %0.3f duration: %0.3f\n", i, + av_log(ic, AV_LOG_TRACE, "%d: start_time: %0.3f duration: %0.3f\n", i, (double) st->start_time / AV_TIME_BASE, (double) st->duration / AV_TIME_BASE); } - av_dlog(ic, + av_log(ic, AV_LOG_TRACE, "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, @@ -1828,7 +1861,7 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) static int has_codec_parameters(AVStream *st) { - AVCodecContext *avctx = st->codec; + AVCodecContext *avctx = st->internal->avctx; int val; switch (avctx->codec_type) { @@ -1852,14 +1885,15 @@ static int has_codec_parameters(AVStream *st) static int has_decode_delay_been_guessed(AVStream *st) { - return st->codec->codec_id != AV_CODEC_ID_H264 || + return st->internal->avctx->codec_id != AV_CODEC_ID_H264 || st->info->nb_decoded_frames >= 6; } /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ -static int try_decode_frame(AVStream *st, AVPacket *avpkt, +static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, AVDictionary **options) { + AVCodecContext *avctx = st->internal->avctx; const AVCodec *codec; int got_picture = 1, ret = 0; AVFrame *frame = av_frame_alloc(); @@ -1868,11 +1902,17 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, if (!frame) return AVERROR(ENOMEM); - if (!avcodec_is_open(st->codec) && !st->info->found_decoder) { + if (!avcodec_is_open(avctx) && !st->info->found_decoder) { AVDictionary *thread_opt = NULL; +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS codec = st->codec->codec ? st->codec->codec - : avcodec_find_decoder(st->codec->codec_id); + : avcodec_find_decoder(st->codecpar->codec_id); +FF_ENABLE_DEPRECATION_WARNINGS +#else + codec = avcodec_find_decoder(st->codecpar->codec_id); +#endif if (!codec) { st->info->found_decoder = -1; @@ -1883,7 +1923,7 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, /* Force thread count to 1 since the H.264 decoder will not extract * SPS and PPS to extradata during multi-threaded decoding. */ av_dict_set(options ? options : &thread_opt, "threads", "1", 0); - ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt); + ret = avcodec_open2(avctx, codec, options ? options : &thread_opt); if (!options) av_dict_free(&thread_opt); if (ret < 0) { @@ -1903,24 +1943,24 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, ret >= 0 && (!has_codec_parameters(st) || !has_decode_delay_been_guessed(st) || (!st->codec_info_nb_frames && - st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) { + (avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) { got_picture = 0; - switch (st->codec->codec_type) { - case AVMEDIA_TYPE_VIDEO: - ret = avcodec_decode_video2(st->codec, frame, - &got_picture, &pkt); - break; - case AVMEDIA_TYPE_AUDIO: - ret = avcodec_decode_audio4(st->codec, frame, &got_picture, &pkt); - break; - default: - break; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || + avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = avcodec_send_packet(avctx, &pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + break; + if (ret >= 0) + pkt.size = 0; + ret = avcodec_receive_frame(avctx, frame); + if (ret >= 0) + got_picture = 1; + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; } if (ret >= 0) { if (got_picture) st->info->nb_decoded_frames++; - pkt.data += ret; - pkt.size -= ret; ret = got_picture; } } @@ -2053,6 +2093,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { int i, count, ret, read_size, j; AVStream *st; + AVCodecContext *avctx; AVPacket pkt1, *pkt; int64_t old_offset = avio_tell(ic->pb); // new streams might appear, no options for those @@ -2062,30 +2103,58 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) const AVCodec *codec; AVDictionary *thread_opt = NULL; st = ic->streams[i]; + avctx = st->internal->avctx; // only for the split stuff if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) { - st->parser = av_parser_init(st->codec->codec_id); + st->parser = av_parser_init(st->codecpar->codec_id); if (st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser) st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } + + /* check if the caller has overridden the codec id */ +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (st->codec->codec_id != st->internal->orig_codec_id) { + st->codecpar->codec_id = st->codec->codec_id; + st->codecpar->codec_type = st->codec->codec_type; + st->internal->orig_codec_id = st->codec->codec_id; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (st->codecpar->codec_id != st->internal->orig_codec_id) + st->internal->orig_codec_id = st->codecpar->codec_id; + + ret = avcodec_parameters_to_context(avctx, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + if (st->codecpar->codec_id != AV_CODEC_ID_PROBE && + st->codecpar->codec_id != AV_CODEC_ID_NONE) + st->internal->avctx_inited = 1; + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS codec = st->codec->codec ? st->codec->codec - : avcodec_find_decoder(st->codec->codec_id); + : avcodec_find_decoder(st->codecpar->codec_id); +FF_ENABLE_DEPRECATION_WARNINGS +#else + codec = avcodec_find_decoder(st->codecpar->codec_id); +#endif /* Force thread count to 1 since the H.264 decoder will not extract * SPS and PPS to extradata during multi-threaded decoding. */ av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0); /* Ensure that subtitle_header is properly set. */ - if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE - && codec && !st->codec->codec) - avcodec_open2(st->codec, codec, + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE + && codec && !avctx->codec) + avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt); // Try to just open decoders, in case this is enough to get parameters. if (!has_codec_parameters(st)) { - if (codec && !st->codec->codec) - avcodec_open2(st->codec, codec, + if (codec && !avctx->codec) + avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt); } if (!options) @@ -2123,14 +2192,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* variable fps and no guess at the real fps */ if (!st->avg_frame_rate.num && st->codec_info_nb_frames < fps_analyze_framecount && - st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) break; if (st->parser && st->parser->parser->split && - !st->codec->extradata) + !st->codecpar->extradata) break; if (st->first_dts == AV_NOPTS_VALUE && - (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO)) + st->codec_info_nb_frames < ic->max_ts_probe && + (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) break; } if (i == ic->nb_streams) { @@ -2171,7 +2241,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* flush the decoders */ if (st->info->found_decoder == 1) { do { - err = try_decode_frame(st, &empty_pkt, + err = try_decode_frame(ic, st, &empty_pkt, (options && i < orig_nb_streams) ? &options[i] : NULL); } while (err > 0 && !has_codec_parameters(st)); @@ -2182,7 +2252,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) "decoding for stream %d failed\n", st->index); } else if (!has_codec_parameters(st)) { char buf[256]; - avcodec_string(buf, sizeof(buf), st->codec, 0); + avcodec_string(buf, sizeof(buf), st->internal->avctx, 0); av_log(ic, AV_LOG_WARNING, "Could not find codec parameters (%s)\n", buf); } else { @@ -2192,18 +2262,26 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } - if (ic->flags & AVFMT_FLAG_NOBUFFER) { - pkt = &pkt1; - } else { - pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1, - &ic->packet_buffer_end); - if ((ret = av_dup_packet(pkt)) < 0) + pkt = &pkt1; + + if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { + ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, + &ic->internal->packet_buffer_end, 0); + if (ret < 0) goto find_stream_info_err; } read_size += pkt->size; st = ic->streams[pkt->stream_index]; + avctx = st->internal->avctx; + if (!st->internal->avctx_inited) { + ret = avcodec_parameters_to_context(avctx, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + st->internal->avctx_inited = 1; + } + if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) { /* check for non-increasing dts */ if (st->info->fps_last_dts != AV_NOPTS_VALUE && @@ -2248,19 +2326,21 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) AV_TIME_BASE_Q) >= ic->max_analyze_duration) { av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached\n", ic->max_analyze_duration); + if (ic->flags & AVFMT_FLAG_NOBUFFER) + av_packet_unref(pkt); break; } } - if (st->parser && st->parser->parser->split && !st->codec->extradata) { - int i = st->parser->parser->split(st->codec, pkt->data, pkt->size); + if (st->parser && st->parser->parser->split && !avctx->extradata) { + int i = st->parser->parser->split(avctx, pkt->data, pkt->size); if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) { - st->codec->extradata_size = i; - st->codec->extradata = av_mallocz(st->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + avctx->extradata_size = i; + avctx->extradata = av_mallocz(avctx->extradata_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) return AVERROR(ENOMEM); - memcpy(st->codec->extradata, pkt->data, - st->codec->extradata_size); + memcpy(avctx->extradata, pkt->data, + avctx->extradata_size); } } @@ -2269,25 +2349,24 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) * it takes longer and uses more memory. For MPEG-4, we need to * decompress for QuickTime. * - * If CODEC_CAP_CHANNEL_CONF is set this will force decoding of at + * If AV_CODEC_CAP_CHANNEL_CONF is set this will force decoding of at * least one frame of codec data, this makes sure the codec initializes * the channel configuration and does not only trust the values from * the container. */ - try_decode_frame(st, pkt, + try_decode_frame(ic, st, pkt, (options && i < orig_nb_streams) ? &options[i] : NULL); + if (ic->flags & AVFMT_FLAG_NOBUFFER) + av_packet_unref(pkt); + st->codec_info_nb_frames++; count++; } - // close codecs which were opened in try_decode_frame() for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - avcodec_close(st->codec); - } - for (i = 0; i < ic->nb_streams; i++) { - st = ic->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + avctx = st->internal->avctx; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { /* estimate average framerate if not set by demuxer */ if (!st->avg_frame_rate.num && st->info->fps_last_dts != st->info->fps_first_dts) { @@ -2322,12 +2401,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, best_fps, 12 * 1001, INT_MAX); } - } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (!st->codec->bits_per_coded_sample) - st->codec->bits_per_coded_sample = - av_get_bits_per_sample(st->codec->codec_id); + } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + if (!avctx->bits_per_coded_sample) + avctx->bits_per_coded_sample = + av_get_bits_per_sample(avctx->codec_id); // set stream disposition based on audio service type - switch (st->codec->audio_service_type) { + switch (avctx->audio_service_type) { case AV_AUDIO_SERVICE_TYPE_EFFECTS: st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; break; @@ -2347,13 +2426,43 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } } - estimate_timings(ic, old_offset); - compute_chapters_end(ic); + /* update the stream parameters from the internal codec contexts */ + for (i = 0; i < ic->nb_streams; i++) { + st = ic->streams[i]; + if (!st->internal->avctx_inited) + continue; + + ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx); + if (ret < 0) + goto find_stream_info_err; + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + ret = avcodec_parameters_to_context(st->codec, st->codecpar); + if (ret < 0) + goto find_stream_info_err; + + if (st->internal->avctx->subtitle_header) { + st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size); + if (!st->codec->subtitle_header) + goto find_stream_info_err; + st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size; + memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header, + st->codec->subtitle_header_size); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + st->internal->avctx_inited = 0; + } + + estimate_timings(ic, old_offset); + find_stream_info_err: for (i = 0; i < ic->nb_streams; i++) { - ic->streams[i]->codec->thread_count = 0; + avcodec_close(ic->streams[i]->internal->avctx); av_freep(&ic->streams[i]->info); } return ret; @@ -2389,8 +2498,8 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, for (i = 0; i < nb_streams; i++) { int real_stream_index = program ? program[i] : i; AVStream *st = ic->streams[real_stream_index]; - AVCodecContext *avctx = st->codec; - if (avctx->codec_type != type) + AVCodecParameters *par = st->codecpar; + if (par->codec_type != type) continue; if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb) continue; @@ -2398,7 +2507,7 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, AV_DISPOSITION_VISUAL_IMPAIRED)) continue; if (decoder_ret) { - decoder = avcodec_find_decoder(st->codec->codec_id); + decoder = avcodec_find_decoder(par->codec_id); if (!decoder) { if (ret < 0) ret = AVERROR_DECODER_NOT_FOUND; @@ -2442,10 +2551,49 @@ int av_read_pause(AVFormatContext *s) return AVERROR(ENOSYS); } +static void free_stream(AVStream **pst) +{ + AVStream *st = *pst; + int i; + + if (!st) + return; + + for (i = 0; i < st->nb_side_data; i++) + av_freep(&st->side_data[i].data); + av_freep(&st->side_data); + + if (st->parser) + av_parser_close(st->parser); + + if (st->attached_pic.data) + av_packet_unref(&st->attached_pic); + + if (st->internal) { + avcodec_free_context(&st->internal->avctx); + } + av_freep(&st->internal); + + av_dict_free(&st->metadata); + avcodec_parameters_free(&st->codecpar); + av_freep(&st->probe_data.buf); + av_free(st->index_entries); +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + av_free(st->codec->extradata); + av_free(st->codec->subtitle_header); + av_free(st->codec); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_free(st->priv_data); + av_free(st->info); + + av_freep(pst); +} + void avformat_free_context(AVFormatContext *s) { - int i, j; - AVStream *st; + int i; if (!s) return; @@ -2454,30 +2602,9 @@ void avformat_free_context(AVFormatContext *s) if (s->iformat && s->iformat->priv_class && s->priv_data) av_opt_free(s->priv_data); - for (i = 0; i < s->nb_streams; i++) { - /* free all data in a stream component */ - st = s->streams[i]; - - for (j = 0; j < st->nb_side_data; j++) - av_freep(&st->side_data[j].data); - av_freep(&st->side_data); - st->nb_side_data = 0; + for (i = 0; i < s->nb_streams; i++) + free_stream(&s->streams[i]); - if (st->parser) { - av_parser_close(st->parser); - } - if (st->attached_pic.data) - av_free_packet(&st->attached_pic); - av_dict_free(&st->metadata); - av_freep(&st->probe_data.buf); - av_free(st->index_entries); - av_free(st->codec->extradata); - av_free(st->codec->subtitle_header); - av_free(st->codec); - av_free(st->priv_data); - av_free(st->info); - av_free(st); - } for (i = s->nb_programs - 1; i >= 0; i--) { av_dict_free(&s->programs[i]->metadata); av_freep(&s->programs[i]->stream_index); @@ -2537,28 +2664,51 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) return NULL; } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS st->codec = avcodec_alloc_context3(c); if (!st->codec) { av_free(st->info); av_free(st); return NULL; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + st->internal = av_mallocz(sizeof(*st->internal)); + if (!st->internal) + goto fail; + if (s->iformat) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS /* no default bitrate if decoding */ st->codec->bit_rate = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* default pts setting is MPEG-like */ avpriv_set_pts_info(st, 33, 1, 90000); + /* we set the current DTS to 0 so that formats without any timestamps + * but durations get some timestamps, formats with some unknown + * timestamps have their first few packets buffered and the + * timestamps corrected before they are returned to the user */ + st->cur_dts = 0; + } else { + st->cur_dts = AV_NOPTS_VALUE; } + st->codecpar = avcodec_parameters_alloc(); + if (!st->codecpar) + goto fail; + + st->internal->avctx = avcodec_alloc_context3(NULL); + if (!st->internal->avctx) + goto fail; + st->index = s->nb_streams; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; - /* we set the current DTS to 0 so that formats without any timestamps - * but durations get some timestamps, formats with some unknown - * timestamps have their first few packets buffered and the - * timestamps corrected before they are returned to the user */ - st->cur_dts = 0; st->first_dts = AV_NOPTS_VALUE; st->probe_packets = MAX_PROBE_PACKETS; @@ -2571,8 +2721,15 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->info->fps_first_dts = AV_NOPTS_VALUE; st->info->fps_last_dts = AV_NOPTS_VALUE; +#if FF_API_LAVF_AVCTX + st->internal->need_codec_update = 1; +#endif + s->streams[s->nb_streams++] = st; return st; +fail: + free_stream(&st); + return NULL; } AVProgram *av_new_program(AVFormatContext *ac, int id) @@ -2580,7 +2737,7 @@ AVProgram *av_new_program(AVFormatContext *ac, int id) AVProgram *program = NULL; int i; - av_dlog(ac, "new_program: id=0x%04x\n", id); + av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id); for (i = 0; i < ac->nb_programs; i++) if (ac->programs[i]->id == id) @@ -2914,21 +3071,14 @@ int ff_find_stream_index(AVFormatContext *s, int id) int64_t ff_iso8601_to_unix_time(const char *datestr) { -#if HAVE_STRPTIME struct tm time1 = { 0 }, time2 = { 0 }; - char *ret1, *ret2; - ret1 = strptime(datestr, "%Y - %m - %d %T", &time1); - ret2 = strptime(datestr, "%Y - %m - %dT%T", &time2); + const char *ret1, *ret2; + ret1 = av_small_strptime(datestr, "%Y - %m - %d %T", &time1); + ret2 = av_small_strptime(datestr, "%Y - %m - %dT%T", &time2); if (ret2 && !ret1) return av_timegm(&time2); else return av_timegm(&time1); -#else - av_log(NULL, AV_LOG_WARNING, - "strptime() unavailable on this system, cannot convert " - "the date string.\n"); - return 0; -#endif } int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, @@ -3081,18 +3231,18 @@ int ff_generate_avci_extradata(AVStream *st) const uint8_t *data = NULL; int size = 0; - if (st->codec->width == 1920) { - if (st->codec->field_order == AV_FIELD_PROGRESSIVE) { + if (st->codecpar->width == 1920) { + if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { data = avci100_1080p_extradata; size = sizeof(avci100_1080p_extradata); } else { data = avci100_1080i_extradata; size = sizeof(avci100_1080i_extradata); } - } else if (st->codec->width == 1440) { + } else if (st->codecpar->width == 1440) { data = avci50_1080i_extradata; size = sizeof(avci50_1080i_extradata); - } else if (st->codec->width == 1280) { + } else if (st->codecpar->width == 1280) { data = avci100_720p_extradata; size = sizeof(avci100_720p_extradata); } @@ -3100,14 +3250,14 @@ int ff_generate_avci_extradata(AVStream *st) if (!size) return 0; - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; - st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; + st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - memcpy(st->codec->extradata, data, size); - st->codec->extradata_size = size; + memcpy(st->codecpar->extradata, data, size); + st->codecpar->extradata_size = size; return 0; } @@ -3126,3 +3276,47 @@ uint8_t *av_stream_get_side_data(AVStream *st, enum AVPacketSideDataType type, } return NULL; } + +uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, + int size) +{ + AVPacketSideData *sd, *tmp; + int i; + uint8_t *data = av_malloc(size); + + if (!data) + return NULL; + + for (i = 0; i < st->nb_side_data; i++) { + sd = &st->side_data[i]; + + if (sd->type == type) { + av_freep(&sd->data); + sd->data = data; + sd->size = size; + return sd->data; + } + } + + tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) { + av_freep(&data); + return NULL; + } + + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = type; + sd->data = data; + sd->size = size; + return data; +} + +void ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +{ + if (*pb) + s->io_close(s, *pb); + *pb = NULL; +} diff --git a/libavformat/vc1test.c b/libavformat/vc1test.c index f302c2b..e127941 100644 --- a/libavformat/vc1test.c +++ b/libavformat/vc1test.c @@ -58,16 +58,16 @@ static int vc1t_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_WMV3; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_WMV3; - st->codec->extradata = av_malloc(VC1_EXTRADATA_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata = av_malloc(VC1_EXTRADATA_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - st->codec->extradata_size = VC1_EXTRADATA_SIZE; - avio_read(pb, st->codec->extradata, VC1_EXTRADATA_SIZE); - st->codec->height = avio_rl32(pb); - st->codec->width = avio_rl32(pb); + st->codecpar->extradata_size = VC1_EXTRADATA_SIZE; + avio_read(pb, st->codecpar->extradata, VC1_EXTRADATA_SIZE); + st->codecpar->height = avio_rl32(pb); + st->codecpar->width = avio_rl32(pb); if(avio_rl32(pb) != 0xC) return AVERROR_INVALIDDATA; avio_skip(pb, 8); diff --git a/libavformat/vc1testenc.c b/libavformat/vc1testenc.c index 9d55fee..dc23c14 100644 --- a/libavformat/vc1testenc.c +++ b/libavformat/vc1testenc.c @@ -27,19 +27,19 @@ typedef struct RCVContext { static int vc1test_write_header(AVFormatContext *s) { - AVCodecContext *avc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; AVIOContext *pb = s->pb; - if (avc->codec_id != AV_CODEC_ID_WMV3) { + if (par->codec_id != AV_CODEC_ID_WMV3) { av_log(s, AV_LOG_ERROR, "Only WMV3 is accepted!\n"); return -1; } avio_wl24(pb, 0); //frames count will be here avio_w8(pb, 0xC5); avio_wl32(pb, 4); - avio_write(pb, avc->extradata, 4); - avio_wl32(pb, avc->height); - avio_wl32(pb, avc->width); + avio_write(pb, par->extradata, 4); + avio_wl32(pb, par->height); + avio_wl32(pb, par->width); avio_wl32(pb, 0xC); avio_wl24(pb, 0); // hrd_buffer avio_w8(pb, 0x80); // level|cbr|res1 diff --git a/libavformat/version.h b/libavformat/version.h index 181d268..2cb8077 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -29,9 +29,9 @@ #include "libavutil/version.h" -#define LIBAVFORMAT_VERSION_MAJOR 56 -#define LIBAVFORMAT_VERSION_MINOR 1 -#define LIBAVFORMAT_VERSION_MICRO 0 +#define LIBAVFORMAT_VERSION_MAJOR 57 +#define LIBAVFORMAT_VERSION_MINOR 7 +#define LIBAVFORMAT_VERSION_MICRO 2 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ @@ -49,13 +49,22 @@ * the public API and may change, break or disappear at any time. */ #ifndef FF_API_LAVF_BITEXACT -#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 57) +#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 58) #endif #ifndef FF_API_LAVF_FRAC -#define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 57) +#define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 58) #endif #ifndef FF_API_LAVF_CODEC_TB -#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 57) +#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_LAVF_FMT_RAWPICTURE +#define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_COMPUTE_PKT_FIELDS2 +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_LAVF_AVCTX +#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 58) #endif #endif /* AVFORMAT_VERSION_H */ diff --git a/libavformat/voc_packet.c b/libavformat/voc_packet.c new file mode 100644 index 0000000..ff48d50 --- /dev/null +++ b/libavformat/voc_packet.c @@ -0,0 +1,119 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "internal.h" +#include "voc.h" + +int +ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) +{ + VocDecContext *voc = s->priv_data; + AVCodecParameters *par = st->codecpar; + AVIOContext *pb = s->pb; + VocType type; + int size, tmp_codec=-1; + int sample_rate = 0; + int channels = 1; + + while (!voc->remaining_size) { + type = avio_r8(pb); + if (type == VOC_TYPE_EOF) + return AVERROR(EIO); + voc->remaining_size = avio_rl24(pb); + if (!voc->remaining_size) { + if (!s->pb->seekable) + return AVERROR(EIO); + voc->remaining_size = avio_size(pb) - avio_tell(pb); + } + max_size -= 4; + + switch (type) { + case VOC_TYPE_VOICE_DATA: + if (!par->sample_rate) { + par->sample_rate = 1000000 / (256 - avio_r8(pb)); + if (sample_rate) + par->sample_rate = sample_rate; + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + par->channels = channels; + par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); + } else + avio_skip(pb, 1); + tmp_codec = avio_r8(pb); + voc->remaining_size -= 2; + max_size -= 2; + channels = 1; + break; + + case VOC_TYPE_VOICE_DATA_CONT: + break; + + case VOC_TYPE_EXTENDED: + sample_rate = avio_rl16(pb); + avio_r8(pb); + channels = avio_r8(pb) + 1; + sample_rate = 256000000 / (channels * (65536 - sample_rate)); + voc->remaining_size = 0; + max_size -= 4; + break; + + case VOC_TYPE_NEW_VOICE_DATA: + if (!par->sample_rate) { + par->sample_rate = avio_rl32(pb); + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + par->bits_per_coded_sample = avio_r8(pb); + par->channels = avio_r8(pb); + } else + avio_skip(pb, 6); + tmp_codec = avio_rl16(pb); + avio_skip(pb, 4); + voc->remaining_size -= 12; + max_size -= 12; + break; + + default: + avio_skip(pb, voc->remaining_size); + max_size -= voc->remaining_size; + voc->remaining_size = 0; + break; + } + } + + if (tmp_codec >= 0) { + tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec); + if (par->codec_id == AV_CODEC_ID_NONE) + par->codec_id = tmp_codec; + else if (par->codec_id != tmp_codec) + av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n"); + if (par->codec_id == AV_CODEC_ID_NONE) { + if (s->audio_codec_id == AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "unknown codec tag\n"); + return AVERROR(EINVAL); + } + av_log(s, AV_LOG_WARNING, "unknown codec tag\n"); + } + } + + par->bit_rate = par->sample_rate * par->bits_per_coded_sample; + + if (max_size <= 0) + max_size = 2048; + size = FFMIN(voc->remaining_size, max_size); + voc->remaining_size -= size; + return av_get_packet(pb, pkt, size); +} diff --git a/libavformat/vocdec.c b/libavformat/vocdec.c index 2fb8440..5ed7117 100644 --- a/libavformat/vocdec.c +++ b/libavformat/vocdec.c @@ -23,7 +23,6 @@ #include "voc.h" #include "internal.h" - static int voc_probe(AVProbeData *p) { int version, check; @@ -43,7 +42,6 @@ static int voc_read_header(AVFormatContext *s) VocDecContext *voc = s->priv_data; AVIOContext *pb = s->pb; int header_size; - AVStream *st; avio_skip(pb, 20); header_size = avio_rl16(pb) - 22; @@ -52,115 +50,21 @@ static int voc_read_header(AVFormatContext *s) return AVERROR(ENOSYS); } avio_skip(pb, header_size); - st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + + s->ctx_flags |= AVFMTCTX_NOHEADER; voc->remaining_size = 0; return 0; } -int -ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) -{ - VocDecContext *voc = s->priv_data; - AVCodecContext *dec = st->codec; - AVIOContext *pb = s->pb; - VocType type; - int size, tmp_codec=-1; - int sample_rate = 0; - int channels = 1; - - while (!voc->remaining_size) { - type = avio_r8(pb); - if (type == VOC_TYPE_EOF) - return AVERROR(EIO); - voc->remaining_size = avio_rl24(pb); - if (!voc->remaining_size) { - if (!s->pb->seekable) - return AVERROR(EIO); - voc->remaining_size = avio_size(pb) - avio_tell(pb); - } - max_size -= 4; - - switch (type) { - case VOC_TYPE_VOICE_DATA: - if (!dec->sample_rate) { - dec->sample_rate = 1000000 / (256 - avio_r8(pb)); - if (sample_rate) - dec->sample_rate = sample_rate; - avpriv_set_pts_info(st, 64, 1, dec->sample_rate); - dec->channels = channels; - dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id); - } else - avio_skip(pb, 1); - tmp_codec = avio_r8(pb); - voc->remaining_size -= 2; - max_size -= 2; - channels = 1; - break; - - case VOC_TYPE_VOICE_DATA_CONT: - break; - - case VOC_TYPE_EXTENDED: - sample_rate = avio_rl16(pb); - avio_r8(pb); - channels = avio_r8(pb) + 1; - sample_rate = 256000000 / (channels * (65536 - sample_rate)); - voc->remaining_size = 0; - max_size -= 4; - break; - - case VOC_TYPE_NEW_VOICE_DATA: - if (!dec->sample_rate) { - dec->sample_rate = avio_rl32(pb); - avpriv_set_pts_info(st, 64, 1, dec->sample_rate); - dec->bits_per_coded_sample = avio_r8(pb); - dec->channels = avio_r8(pb); - } else - avio_skip(pb, 6); - tmp_codec = avio_rl16(pb); - avio_skip(pb, 4); - voc->remaining_size -= 12; - max_size -= 12; - break; - - default: - avio_skip(pb, voc->remaining_size); - max_size -= voc->remaining_size; - voc->remaining_size = 0; - break; - } - } - - if (tmp_codec >= 0) { - tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec); - if (dec->codec_id == AV_CODEC_ID_NONE) - dec->codec_id = tmp_codec; - else if (dec->codec_id != tmp_codec) - av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n"); - if (dec->codec_id == AV_CODEC_ID_NONE) { - if (s->audio_codec_id == AV_CODEC_ID_NONE) { - av_log(s, AV_LOG_ERROR, "unknown codec tag\n"); - return AVERROR(EINVAL); - } - av_log(s, AV_LOG_WARNING, "unknown codec tag\n"); - } - } - - dec->bit_rate = dec->sample_rate * dec->bits_per_coded_sample; - - if (max_size <= 0) - max_size = 2048; - 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) { + if (!s->nb_streams) { + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + } return ff_voc_get_packet(s, pkt, s->streams[0], 0); } diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c index ed10a96..033fc56 100644 --- a/libavformat/vocenc.c +++ b/libavformat/vocenc.c @@ -34,7 +34,7 @@ static int voc_write_header(AVFormatContext *s) const int version = 0x0114; if (s->nb_streams != 1 - || s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) + || s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) return AVERROR_PATCHWELCOME; avio_write(pb, ff_voc_magic, sizeof(ff_voc_magic) - 1); @@ -48,30 +48,30 @@ static int voc_write_header(AVFormatContext *s) static int voc_write_packet(AVFormatContext *s, AVPacket *pkt) { VocEncContext *voc = s->priv_data; - AVCodecContext *enc = s->streams[0]->codec; + AVCodecParameters *par = s->streams[0]->codecpar; AVIOContext *pb = s->pb; if (!voc->param_written) { - if (enc->codec_tag > 0xFF) { + if (par->codec_tag > 0xFF) { avio_w8(pb, VOC_TYPE_NEW_VOICE_DATA); avio_wl24(pb, pkt->size + 12); - avio_wl32(pb, enc->sample_rate); - avio_w8(pb, enc->bits_per_coded_sample); - avio_w8(pb, enc->channels); - avio_wl16(pb, enc->codec_tag); + avio_wl32(pb, par->sample_rate); + avio_w8(pb, par->bits_per_coded_sample); + avio_w8(pb, par->channels); + avio_wl16(pb, par->codec_tag); avio_wl32(pb, 0); } else { - if (s->streams[0]->codec->channels > 1) { + if (s->streams[0]->codecpar->channels > 1) { avio_w8(pb, VOC_TYPE_EXTENDED); avio_wl24(pb, 4); - avio_wl16(pb, 65536-256000000/(enc->sample_rate*enc->channels)); - avio_w8(pb, enc->codec_tag); - avio_w8(pb, enc->channels - 1); + avio_wl16(pb, 65536-256000000/(par->sample_rate*par->channels)); + avio_w8(pb, par->codec_tag); + avio_w8(pb, par->channels - 1); } avio_w8(pb, VOC_TYPE_VOICE_DATA); avio_wl24(pb, pkt->size + 2); - avio_w8(pb, 256 - 1000000 / enc->sample_rate); - avio_w8(pb, enc->codec_tag); + avio_w8(pb, 256 - 1000000 / par->sample_rate); + avio_w8(pb, par->codec_tag); } voc->param_written = 1; } else { diff --git a/libavformat/vqf.c b/libavformat/vqf.c index a43829b..c3a6a97 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -104,8 +104,8 @@ static int vqf_read_header(AVFormatContext *s) header_size = avio_rb32(s->pb); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_TWINVQ; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_TWINVQ; st->start_time = 0; do { @@ -127,12 +127,12 @@ static int vqf_read_header(AVFormatContext *s) switch(chunk_tag){ case MKTAG('C','O','M','M'): avio_read(s->pb, comm_chunk, 12); - st->codec->channels = AV_RB32(comm_chunk ) + 1; + st->codecpar->channels = AV_RB32(comm_chunk ) + 1; read_bitrate = AV_RB32(comm_chunk + 4); rate_flag = AV_RB32(comm_chunk + 8); avio_skip(s->pb, len-12); - st->codec->bit_rate = read_bitrate*1000; + st->codecpar->bit_rate = read_bitrate * 1000; break; case MKTAG('D','S','I','Z'): // size of compressed data { @@ -165,32 +165,32 @@ static int vqf_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "COMM tag not found!\n"); return -1; case 44: - st->codec->sample_rate = 44100; + st->codecpar->sample_rate = 44100; break; case 22: - st->codec->sample_rate = 22050; + st->codecpar->sample_rate = 22050; break; case 11: - st->codec->sample_rate = 11025; + st->codecpar->sample_rate = 11025; break; default: if (rate_flag < 8 || rate_flag > 44) { av_log(s, AV_LOG_ERROR, "Invalid rate flag %d\n", rate_flag); return AVERROR_INVALIDDATA; } - st->codec->sample_rate = rate_flag*1000; + st->codecpar->sample_rate = rate_flag*1000; break; } - if (read_bitrate / st->codec->channels < 8 || - read_bitrate / st->codec->channels > 48) { + if (read_bitrate / st->codecpar->channels < 8 || + read_bitrate / st->codecpar->channels > 48) { av_log(s, AV_LOG_ERROR, "Invalid bitrate per channel %d\n", - read_bitrate / st->codec->channels); + read_bitrate / st->codecpar->channels); return AVERROR_INVALIDDATA; } - switch (((st->codec->sample_rate/1000) << 8) + - read_bitrate/st->codec->channels) { + switch (((st->codecpar->sample_rate/1000) << 8) + + read_bitrate/st->codecpar->channels) { case (11<<8) + 8 : case (8 <<8) + 8 : case (11<<8) + 10: @@ -208,17 +208,17 @@ static int vqf_read_header(AVFormatContext *s) break; default: av_log(s, AV_LOG_ERROR, "Mode not suported: %d Hz, %d kb/s.\n", - st->codec->sample_rate, st->codec->bit_rate); + st->codecpar->sample_rate, st->codecpar->bit_rate); return -1; } - c->frame_bit_len = st->codec->bit_rate*size/st->codec->sample_rate; - avpriv_set_pts_info(st, 64, size, st->codec->sample_rate); + c->frame_bit_len = st->codecpar->bit_rate*size/st->codecpar->sample_rate; + avpriv_set_pts_info(st, 64, size, st->codecpar->sample_rate); /* put first 12 bytes of COMM chunk in extradata */ - if (!(st->codec->extradata = av_malloc(12 + FF_INPUT_BUFFER_PADDING_SIZE))) + if (!(st->codecpar->extradata = av_malloc(12 + AV_INPUT_BUFFER_PADDING_SIZE))) return AVERROR(ENOMEM); - st->codec->extradata_size = 12; - memcpy(st->codec->extradata, comm_chunk, 12); + st->codecpar->extradata_size = 12; + memcpy(st->codecpar->extradata, comm_chunk, 12); ff_metadata_conv_ctx(s, NULL, vqf_metadata_conv); @@ -243,7 +243,7 @@ static int vqf_read_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_read(s->pb, pkt->data+2, size); if (ret<=0) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } @@ -262,7 +262,7 @@ static int vqf_read_seek(AVFormatContext *s, int64_t pos; st = s->streams[stream_index]; - pos = av_rescale_rnd(timestamp * st->codec->bit_rate, + pos = av_rescale_rnd(timestamp * st->codecpar->bit_rate, st->time_base.num, st->time_base.den * (int64_t)c->frame_bit_len, (flags & AVSEEK_FLAG_BACKWARD) ? @@ -270,9 +270,9 @@ static int vqf_read_seek(AVFormatContext *s, pos *= c->frame_bit_len; st->cur_dts = av_rescale(pos, st->time_base.den, - st->codec->bit_rate * (int64_t)st->time_base.num); + st->codecpar->bit_rate * (int64_t)st->time_base.num); - if ((ret = avio_seek(s->pb, ((pos-7) >> 3) + s->data_offset, SEEK_SET)) < 0) + if ((ret = avio_seek(s->pb, ((pos-7) >> 3) + s->internal->data_offset, SEEK_SET)) < 0) return ret; c->remaining_bits = -7 - ((pos-7)&7); diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index f65a66a..4bd2642 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -102,12 +102,12 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) if (!*st) return AVERROR(ENOMEM); - ret = ff_get_wav_header(pb, (*st)->codec, size); + ret = ff_get_wav_header(s, pb, (*st)->codecpar, size); if (ret < 0) return ret; (*st)->need_parsing = AVSTREAM_PARSE_FULL; - avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate); + avpriv_set_pts_info(*st, 64, 1, (*st)->codecpar->sample_rate); return 0; } @@ -328,11 +328,11 @@ break_loop: avio_seek(pb, data_ofs, SEEK_SET); - if (!sample_count && st->codec->channels && - av_get_bits_per_sample(st->codec->codec_id)) + if (!sample_count && st->codecpar->channels && + av_get_bits_per_sample(st->codecpar->codec_id)) sample_count = (data_size << 3) / - (st->codec->channels * - (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); + (st->codecpar->channels * + (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id)); if (sample_count) st->duration = sample_count; @@ -391,10 +391,10 @@ static int wav_read_packet(AVFormatContext *s, AVPacket *pkt) } 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; + if (st->codecpar->block_align > 1) { + if (size < st->codecpar->block_align) + size = st->codecpar->block_align; + size = (size / st->codecpar->block_align) * st->codecpar->block_align; } size = FFMIN(size, left); ret = av_get_packet(s->pb, pkt, size); @@ -411,7 +411,7 @@ static int wav_read_seek(AVFormatContext *s, AVStream *st; st = s->streams[0]; - switch (st->codec->codec_id) { + switch (st->codecpar->codec_id) { case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: case AV_CODEC_ID_AC3: @@ -498,14 +498,14 @@ static int w64_read_header(AVFormatContext *s) return AVERROR(ENOMEM); /* subtract chunk header size - normal wav file doesn't count it */ - ret = ff_get_wav_header(pb, st->codec, size - 24); + ret = ff_get_wav_header(s, pb, st->codecpar, size - 24); if (ret < 0) return ret; avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); st->need_parsing = AVSTREAM_PARSE_FULL; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); size = find_guid(pb, guid_data); if (size < 0) { diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 25f6ffc..32d4bc1 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -109,15 +109,15 @@ static int wav_write_header(AVFormatContext *s) /* format header */ fmt = ff_start_tag(pb, "fmt "); - if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) { - const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codec->codec_id); + if (ff_put_wav_header(s, pb, s->streams[0]->codecpar) < 0) { + const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codecpar->codec_id); av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n", desc ? desc->name : "unknown"); return AVERROR(ENOSYS); } ff_end_tag(pb, fmt); - if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ + if (s->streams[0]->codecpar->codec_tag != 0x01 /* hence for all other than PCM */ && s->pb->seekable) { wav->fact_pos = ff_start_tag(pb, "fact"); avio_wl32(pb, 0); @@ -127,7 +127,7 @@ static int wav_write_header(AVFormatContext *s) if (wav->write_bext) bwf_write_bext_chunk(s); - avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); + avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate); wav->maxpts = wav->last_duration = 0; wav->minpts = INT64_MAX; @@ -175,11 +175,11 @@ static int wav_write_trailer(AVFormatContext *s) avio_flush(pb); - if(s->streams[0]->codec->codec_tag != 0x01) { + if(s->streams[0]->codecpar->codec_tag != 0x01) { /* Update num_samps in fact chunk */ int number_of_samples; number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration, - s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num, + s->streams[0]->codecpar->sample_rate * (int64_t)s->streams[0]->time_base.num, s->streams[0]->time_base.den); avio_seek(pb, wav->fact_pos, SEEK_SET); avio_wl32(pb, number_of_samples); diff --git a/libavformat/wc3movie.c b/libavformat/wc3movie.c index c894253..f46b8c2 100644 --- a/libavformat/wc3movie.c +++ b/libavformat/wc3movie.c @@ -1,6 +1,6 @@ /* * Wing Commander III Movie (.mve) File Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -169,27 +169,27 @@ static int wc3_read_header(AVFormatContext *s) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_XAN_WC3; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = wc3->width; - st->codec->height = wc3->height; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_XAN_WC3; + st->codecpar->codec_tag = 0; /* no fourcc */ + st->codecpar->width = wc3->width; + st->codecpar->height = wc3->height; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->audio_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codec->codec_tag = 1; - st->codec->channels = WC3_AUDIO_CHANNELS; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; - st->codec->bits_per_coded_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_coded_sample; - st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_tag = 1; + st->codecpar->channels = WC3_AUDIO_CHANNELS; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->bits_per_coded_sample = WC3_AUDIO_BITS; + st->codecpar->sample_rate = WC3_SAMPLE_RATE; + st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; return 0; } @@ -241,9 +241,6 @@ static int wc3_read_packet(AVFormatContext *s, case TEXT_TAG: /* subtitle chunk */ -#if 0 - avio_skip(pb, size); -#else if ((unsigned)size > sizeof(text) || (ret = avio_read(pb, text, size)) != size) ret = AVERROR(EIO); else { @@ -255,7 +252,6 @@ static int wc3_read_packet(AVFormatContext *s, i += text[i] + 1; av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]); } -#endif break; case AUDI_TAG: @@ -288,7 +284,7 @@ static int wc3_read_close(AVFormatContext *s) Wc3DemuxContext *wc3 = s->priv_data; if (wc3->vpkt.size > 0) - av_free_packet(&wc3->vpkt); + av_packet_unref(&wc3->vpkt); return 0; } diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 611d223..1bfc010 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -1,6 +1,6 @@ /* * Westwood Studios AUD Format Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -107,23 +107,23 @@ static int wsaud_read_header(AVFormatContext *s) avpriv_request_sample(s, "Stereo WS-SND1"); return AVERROR_PATCHWELCOME; } - st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1; + st->codecpar->codec_id = AV_CODEC_ID_WESTWOOD_SND1; break; case 99: - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; - st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = channels * sample_rate * 4; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; + st->codecpar->bits_per_coded_sample = 4; + st->codecpar->bit_rate = channels * sample_rate * 4; break; default: avpriv_request_sample(s, "Unknown codec: %d", codec); return AVERROR_PATCHWELCOME; } avpriv_set_pts_info(st, 64, 1, sample_rate); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->channels = channels; - st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = sample_rate; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->channels = channels; + st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = sample_rate; return 0; } @@ -147,7 +147,7 @@ static int wsaud_read_packet(AVFormatContext *s, chunk_size = AV_RL16(&preamble[0]); - if (st->codec->codec_id == AV_CODEC_ID_WESTWOOD_SND1) { + if (st->codecpar->codec_id == AV_CODEC_ID_WESTWOOD_SND1) { /* For Westwood SND1 audio we need to add the output size and input size to the start of the packet to match what is in VQA. Specifically, this is needed to signal when a packet should be @@ -167,7 +167,7 @@ static int wsaud_read_packet(AVFormatContext *s, return AVERROR(EIO); /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ - pkt->duration = (chunk_size * 2) / st->codec->channels; + pkt->duration = (chunk_size * 2) / st->codecpar->channels; } pkt->stream_index = st->index; diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 77da375..8bd647e 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -1,6 +1,6 @@ /* * Westwood Studios VQA Format Demuxer - * Copyright (c) 2003 The ffmpeg Project + * Copyright (c) 2003 The FFmpeg project * * This file is part of Libav. * @@ -93,23 +93,23 @@ static int wsvqa_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->start_time = 0; wsvqa->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_WS_VQA; - st->codec->codec_tag = 0; /* no fourcc */ + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_WS_VQA; + st->codecpar->codec_tag = 0; /* no fourcc */ /* skip to the start of the VQA header */ avio_seek(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 (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) != + st->codecpar->extradata_size = VQA_HEADER_SIZE; + st->codecpar->extradata = av_mallocz(VQA_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + header = (unsigned char *)st->codecpar->extradata; + if (avio_read(pb, st->codecpar->extradata, VQA_HEADER_SIZE) != VQA_HEADER_SIZE) { return AVERROR(EIO); } - st->codec->width = AV_RL16(&header[6]); - st->codec->height = AV_RL16(&header[8]); + st->codecpar->width = AV_RL16(&header[6]); + st->codecpar->height = AV_RL16(&header[8]); fps = header[12]; st->nb_frames = st->duration = AV_RL16(&header[4]); @@ -136,7 +136,7 @@ static int wsvqa_read_header(AVFormatContext *s) chunk_tag = AV_RB32(&scratch[0]); chunk_size = AV_RB32(&scratch[4]); - /* catch any unknown header tags, for curiousity */ + /* catch any unknown header tags, for curiosity */ switch (chunk_tag) { case CINF_TAG: case CINH_TAG: @@ -184,7 +184,7 @@ static int wsvqa_read_packet(AVFormatContext *s, return AVERROR(EIO); ret = avio_read(pb, pkt->data, chunk_size); if (ret != chunk_size) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } @@ -204,30 +204,30 @@ static int wsvqa_read_packet(AVFormatContext *s, wsvqa->channels = 1; if (!wsvqa->bps) wsvqa->bps = 8; - st->codec->sample_rate = wsvqa->sample_rate; - st->codec->bits_per_coded_sample = wsvqa->bps; - st->codec->channels = wsvqa->channels; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->sample_rate = wsvqa->sample_rate; + st->codecpar->bits_per_coded_sample = wsvqa->bps; + st->codecpar->channels = wsvqa->channels; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); switch (chunk_type) { case SND0_TAG: if (wsvqa->bps == 16) - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; else - st->codec->codec_id = AV_CODEC_ID_PCM_U8; + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; break; case SND1_TAG: - st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1; + st->codecpar->codec_id = AV_CODEC_ID_WESTWOOD_SND1; break; case SND2_TAG: - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; - st->codec->extradata_size = 2; - st->codec->extradata = av_mallocz(2 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; + st->codecpar->extradata_size = 2; + st->codecpar->extradata = av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); - AV_WL16(st->codec->extradata, wsvqa->version); + AV_WL16(st->codecpar->extradata, wsvqa->version); break; } } diff --git a/libavformat/wtv.c b/libavformat/wtv.c index c85f374..272b317 100644 --- a/libavformat/wtv.c +++ b/libavformat/wtv.c @@ -31,13 +31,14 @@ #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/dict.h" +#include "libavutil/time_internal.h" #include "avformat.h" #include "internal.h" #include "riff.h" #include "asf.h" #include "mpegts.h" -/* Macros for formating GUIDs */ +/* Macros for formatting GUIDs */ #define PRI_PRETTY_GUID \ "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x" #define ARG_PRETTY_GUID(g) \ @@ -45,9 +46,7 @@ #define LEN_PRETTY_GUID 34 /* - * * File system routines - * */ #define WTV_SECTOR_BITS 12 @@ -56,7 +55,7 @@ #define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS) -typedef struct { +typedef struct WtvFile { AVIOContext *pb_filesystem; /** file system (AVFormatContext->pb) */ int sector_bits; /** sector shift bits; used to convert sector number into pb_filesystem offset */ @@ -318,20 +317,18 @@ static void wtvfile_close(AVIOContext *pb) } /* - * * Main demuxer - * */ -typedef struct { +typedef struct WtvStream { int seen_data; } WtvStream; -typedef struct { +typedef struct WtvContext { AVIOContext *pb; /** timeline file */ int64_t epoch; int64_t pts; /** pts for next data chunk */ - int64_t last_valid_pts; /** latest valid pts, used for interative seeking */ + int64_t last_valid_pts; /** latest valid pts, used for interactive seeking */ /* maintain private seek index, as the AVIndexEntry->pos is relative to the start of the 'timeline' file, not the file system (AVFormatContext->pb) */ @@ -428,10 +425,12 @@ static int read_probe(AVProbeData *p) static void filetime_to_iso8601(char *buf, int buf_size, int64_t value) { time_t t = (value / 10000000LL) - 11644473600LL; - struct tm *tm = gmtime(&t); - if (tm) - strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); - else + struct tm tmbuf; + struct tm *tm = gmtime_r(&t, &tmbuf); + if (tm) { + if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm)) + buf[0] = '\0'; + } else buf[0] = '\0'; } @@ -441,10 +440,12 @@ static void filetime_to_iso8601(char *buf, int buf_size, int64_t value) static void crazytime_to_iso8601(char *buf, int buf_size, int64_t value) { time_t t = (value / 10000000LL) - 719162LL*86400LL; - struct tm *tm = gmtime(&t); - if (tm) - strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); - else + struct tm tmbuf; + struct tm *tm = gmtime_r(&t, &tmbuf); + if (tm) { + if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm)) + buf[0] = '\0'; + } else buf[0] = '\0'; } @@ -454,10 +455,12 @@ static void crazytime_to_iso8601(char *buf, int buf_size, int64_t value) static void oledate_to_iso8601(char *buf, int buf_size, int64_t value) { time_t t = 631112400LL + 86400*av_int2double(value); - struct tm *tm = gmtime(&t); - if (tm) - strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); - else + struct tm tmbuf; + struct tm *tm = gmtime_r(&t, &tmbuf); + if (tm) { + if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm)) + buf[0] = '\0'; + } else buf[0] = '\0'; } @@ -483,14 +486,14 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length) if (!st) goto done; av_dict_set(&st->metadata, "title", description, 0); - st->codec->codec_id = AV_CODEC_ID_MJPEG; - st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; - st->codec->extradata = av_mallocz(filesize); + st->codecpar->codec_id = AV_CODEC_ID_MJPEG; + st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; + st->codecpar->extradata = av_mallocz(filesize); st->id = -1; - if (!st->codec->extradata) + if (!st->codecpar->extradata) goto done; - st->codec->extradata_size = filesize; - avio_read(pb, st->codec->extradata, filesize); + st->codecpar->extradata_size = filesize; + avio_read(pb, st->codecpar->extradata, filesize); done: avio_seek(pb, pos + length, SEEK_SET); } @@ -583,7 +586,7 @@ static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st) AVIOContext *pb = wtv->pb; avio_skip(pb, 72); // picture aspect ratio is unreliable - ff_get_bmp_header(pb, st); + ff_get_bmp_header(pb, st, NULL); return 72 + 40; } @@ -594,23 +597,23 @@ static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st) static void parse_mpeg1waveformatex(AVStream *st) { /* fwHeadLayer */ - switch (AV_RL16(st->codec->extradata)) { - case 0x0001 : st->codec->codec_id = AV_CODEC_ID_MP1; break; - case 0x0002 : st->codec->codec_id = AV_CODEC_ID_MP2; break; - case 0x0004 : st->codec->codec_id = AV_CODEC_ID_MP3; break; + switch (AV_RL16(st->codecpar->extradata)) { + case 0x0001 : st->codecpar->codec_id = AV_CODEC_ID_MP1; break; + case 0x0002 : st->codecpar->codec_id = AV_CODEC_ID_MP2; break; + case 0x0004 : st->codecpar->codec_id = AV_CODEC_ID_MP3; break; } - st->codec->bit_rate = AV_RL32(st->codec->extradata + 2); /* dwHeadBitrate */ + st->codecpar->bit_rate = AV_RL32(st->codecpar->extradata + 2); /* dwHeadBitrate */ /* dwHeadMode */ - switch (AV_RL16(st->codec->extradata + 6)) { + switch (AV_RL16(st->codecpar->extradata + 6)) { case 1 : case 2 : - case 4 : st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + case 4 : st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; break; - case 8 : st->codec->channels = 1; - st->codec->channel_layout = AV_CH_LAYOUT_MONO; + case 8 : st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; break; } } @@ -623,21 +626,23 @@ static void parse_mpeg1waveformatex(AVStream *st) static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int codec_type) { if (st) { - if (st->codec->extradata) { - av_freep(&st->codec->extradata); - st->codec->extradata_size = 0; + if (st->codecpar->extradata) { + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; } } else { WtvStream *wst = av_mallocz(sizeof(WtvStream)); if (!wst) return NULL; st = avformat_new_stream(s, NULL); - if (!st) + if (!st) { + av_free(wst); return NULL; + } st->id = sid; st->priv_data = wst; } - st->codec->codec_type = codec_type; + st->codecpar->codec_type = codec_type; st->need_parsing = AVSTREAM_PARSE_FULL; avpriv_set_pts_info(st, 64, 1, 10000000); return st; @@ -682,7 +687,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (!st) return NULL; if (!ff_guidcmp(formattype, format_waveformatex)) { - int ret = ff_get_wav_header(pb, st->codec, size); + int ret = ff_get_wav_header(s, pb, st->codecpar, size); if (ret < 0) return NULL; } else { @@ -692,15 +697,15 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, } if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) { - st->codec->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codec->bits_per_coded_sample); + st->codecpar->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codecpar->bits_per_coded_sample); } else if (!ff_guidcmp(subtype, mediasubtype_mpeg1payload)) { - if (st->codec->extradata && st->codec->extradata_size >= 22) + if (st->codecpar->extradata && st->codecpar->extradata_size >= 22) parse_mpeg1waveformatex(st); else av_log(s, AV_LOG_WARNING, "MPEG1WAVEFORMATEX underflow\n"); } else { - st->codec->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype); - if (st->codec->codec_id == AV_CODEC_ID_NONE) + st->codecpar->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype); + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype)); } return st; @@ -721,11 +726,11 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, } if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) { - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype)); + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype)); } else { - st->codec->codec_id = ff_codec_guid_get_id(video_guids, subtype); + st->codecpar->codec_id = ff_codec_guid_get_id(video_guids, subtype); } - if (st->codec->codec_id == AV_CODEC_ID_NONE) + if (st->codecpar->codec_id == AV_CODEC_ID_NONE) av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype)); return st; } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_pes) && @@ -736,7 +741,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (ff_guidcmp(formattype, format_none)) av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); - st->codec->codec_id = AV_CODEC_ID_DVB_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_DVB_SUBTITLE; return st; } else if (!ff_guidcmp(mediatype, mediatype_mstvcaption) && (!ff_guidcmp(subtype, mediasubtype_teletext) || !ff_guidcmp(subtype, mediasubtype_dtvccdata))) { @@ -746,7 +751,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (ff_guidcmp(formattype, format_none)) av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); - st->codec->codec_id = AV_CODEC_ID_DVB_TELETEXT; + st->codecpar->codec_id = AV_CODEC_ID_DVB_TELETEXT; return st; } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) && !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) { @@ -972,7 +977,9 @@ static int read_header(AVFormatContext *s) avio_skip(s->pb, 4); root_sector = avio_rl32(s->pb); - seek_by_sector(s->pb, root_sector, 0); + ret = seek_by_sector(s->pb, root_sector, 0); + if (ret < 0) + return ret; root_size = avio_read(s->pb, root, root_size); if (root_size < 0) return AVERROR_INVALIDDATA; diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c index 1a2a722..c78bac1 100644 --- a/libavformat/wvdec.c +++ b/libavformat/wvdec.c @@ -47,7 +47,7 @@ static const int wv_rates[16] = { 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 }; -typedef struct { +typedef struct WVContext { uint8_t block_header[WV_HEADER_SIZE]; WvHeader header; int rate, chan, bpp; @@ -227,12 +227,12 @@ static int wv_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_WAVPACK; - st->codec->channels = wc->chan; - st->codec->channel_layout = wc->chmask; - st->codec->sample_rate = wc->rate; - st->codec->bits_per_coded_sample = wc->bpp; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_WAVPACK; + st->codecpar->channels = wc->chan; + st->codecpar->channel_layout = wc->chmask; + st->codecpar->sample_rate = wc->rate; + st->codecpar->bits_per_coded_sample = wc->bpp; avpriv_set_pts_info(st, 64, 1, wc->rate); st->start_time = 0; st->duration = wc->header.total_samples; @@ -269,25 +269,25 @@ static int wv_read_packet(AVFormatContext *s, AVPacket *pkt) memcpy(pkt->data, wc->block_header, WV_HEADER_SIZE); ret = avio_read(s->pb, pkt->data + WV_HEADER_SIZE, wc->header.blocksize); if (ret != wc->header.blocksize) { - av_free_packet(pkt); + av_packet_unref(pkt); return AVERROR(EIO); } while (!(wc->header.flags & WV_FLAG_FINAL_BLOCK)) { if ((ret = wv_read_block_header(s, s->pb)) < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } off = pkt->size; if ((ret = av_grow_packet(pkt, WV_HEADER_SIZE + wc->header.blocksize)) < 0) { - av_free_packet(pkt); + av_packet_unref(pkt); return ret; } memcpy(pkt->data + off, wc->block_header, WV_HEADER_SIZE); ret = avio_read(s->pb, pkt->data + off + WV_HEADER_SIZE, wc->header.blocksize); if (ret != wc->header.blocksize) { - av_free_packet(pkt); + av_packet_unref(pkt); return (ret < 0) ? ret : AVERROR_EOF; } } @@ -334,7 +334,7 @@ static int wv_read_seek(AVFormatContext *s, int stream_index, return ret; } pts = pkt->pts; - av_free_packet(pkt); + av_packet_unref(pkt); } while(pts < timestamp); return 0; } diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c index 2e150e1..a753c19 100644 --- a/libavformat/wvenc.c +++ b/libavformat/wvenc.c @@ -29,7 +29,7 @@ typedef struct WvMuxContext { static av_cold int wv_write_header(AVFormatContext *ctx) { if (ctx->nb_streams > 1 || - ctx->streams[0]->codec->codec_id != AV_CODEC_ID_WAVPACK) { + ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) { av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n"); return AVERROR(EINVAL); } diff --git a/libavformat/xa.c b/libavformat/xa.c index 57a36bc..06b9c3f 100644 --- a/libavformat/xa.c +++ b/libavformat/xa.c @@ -73,21 +73,21 @@ static int xa_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_EA_MAXIS_XA; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_EA_MAXIS_XA; avio_skip(pb, 4); /* Skip the XA ID */ xa->out_size = avio_rl32(pb); avio_skip(pb, 2); /* Skip the tag */ - st->codec->channels = avio_rl16(pb); - st->codec->sample_rate = avio_rl32(pb); + st->codecpar->channels = avio_rl16(pb); + st->codecpar->sample_rate = avio_rl32(pb); avio_skip(pb, 4); /* Skip average byte rate */ avio_skip(pb, 2); /* Skip block align */ avio_skip(pb, 2); /* Skip bits-per-sample */ - st->codec->bit_rate = av_clip(15LL * st->codec->channels * 8 * - st->codec->sample_rate / 28, 0, INT_MAX); + st->codecpar->bit_rate = av_clip(15LL * st->codecpar->channels * 8 * + st->codecpar->sample_rate / 28, 0, INT_MAX); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->start_time = 0; return 0; @@ -105,7 +105,7 @@ static int xa_read_packet(AVFormatContext *s, if (xa->sent_bytes >= xa->out_size) return AVERROR_EOF; /* 1 byte header and 14 bytes worth of samples * number channels per block */ - packet_size = 15*st->codec->channels; + packet_size = 15*st->codecpar->channels; ret = av_get_packet(pb, pkt, packet_size); if(ret < 0) diff --git a/libavformat/xmv.c b/libavformat/xmv.c index bcb17f8..b2112b0 100644 --- a/libavformat/xmv.c +++ b/libavformat/xmv.c @@ -169,11 +169,11 @@ static int xmv_read_header(AVFormatContext *s) avpriv_set_pts_info(vst, 32, 1, 1000); - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_WMV2; - vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2'); - vst->codec->width = avio_rl32(pb); - vst->codec->height = avio_rl32(pb); + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_id = AV_CODEC_ID_WMV2; + vst->codecpar->codec_tag = MKBETAG('W', 'M', 'V', '2'); + vst->codecpar->width = avio_rl32(pb); + vst->codecpar->height = avio_rl32(pb); vst->duration = avio_rl32(pb); @@ -240,14 +240,14 @@ static int xmv_read_header(AVFormatContext *s) goto fail; } - ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codec->codec_id = track->codec_id; - ast->codec->codec_tag = track->compression; - ast->codec->channels = track->channels; - ast->codec->sample_rate = track->sample_rate; - ast->codec->bits_per_coded_sample = track->bits_per_sample; - ast->codec->bit_rate = track->bit_rate; - ast->codec->block_align = 36 * track->channels; + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_id = track->codec_id; + ast->codecpar->codec_tag = track->compression; + ast->codecpar->channels = track->channels; + ast->codecpar->sample_rate = track->sample_rate; + ast->codecpar->bits_per_coded_sample = track->bits_per_sample; + ast->codecpar->bit_rate = track->bit_rate; + ast->codecpar->block_align = 36 * track->channels; avpriv_set_pts_info(ast, 32, track->block_samples, track->sample_rate); @@ -389,15 +389,15 @@ static int xmv_process_packet_header(AVFormatContext *s) assert(xmv->video.stream_index < s->nb_streams); - if (vst->codec->extradata_size < 4) { - av_free(vst->codec->extradata); + if (vst->codecpar->extradata_size < 4) { + av_free(vst->codecpar->extradata); - vst->codec->extradata = - av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE); - vst->codec->extradata_size = 4; + vst->codecpar->extradata = + av_malloc(4 + AV_INPUT_BUFFER_PADDING_SIZE); + vst->codecpar->extradata_size = 4; } - memcpy(vst->codec->extradata, xmv->video.extradata, 4); + memcpy(vst->codecpar->extradata, xmv->video.extradata, 4); } } } diff --git a/libavformat/xwma.c b/libavformat/xwma.c index af916ad..e6e72d9 100644 --- a/libavformat/xwma.c +++ b/libavformat/xwma.c @@ -30,7 +30,7 @@ * Demuxer for xWMA, a Microsoft audio container used by XAudio 2. */ -typedef struct { +typedef struct XWMAContext { int64_t data_end; } XWMAContext; @@ -75,7 +75,7 @@ static int xwma_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - ret = ff_get_wav_header(pb, st->codec, size); + ret = ff_get_wav_header(s, pb, st->codecpar, size); if (ret < 0) return ret; st->need_parsing = AVSTREAM_PARSE_NONE; @@ -85,9 +85,9 @@ static int xwma_read_header(AVFormatContext *s) * extradata for that. Thus, ask the user for feedback, but try to go on * anyway. */ - if (st->codec->codec_id != AV_CODEC_ID_WMAV2) { + if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2) { avpriv_request_sample(s, "Unexpected codec (tag 0x04%x; id %d)", - st->codec->codec_tag, st->codec->codec_id); + st->codecpar->codec_tag, st->codecpar->codec_id); } else { /* In all xWMA files I have seen, there is no extradata. But the WMA * codecs require extradata, so we provide our own fake extradata. @@ -96,37 +96,37 @@ static int xwma_read_header(AVFormatContext *s) * there was, then try to use it, after asking the user to provide a * sample of this unusual file. */ - if (st->codec->extradata_size != 0) { + if (st->codecpar->extradata_size != 0) { /* Surprise, surprise: We *did* get some extradata. No idea * if it will work, but just go on and try it, after asking * the user for a sample. */ avpriv_request_sample(s, "Unexpected extradata (%d bytes)", - st->codec->extradata_size); + st->codecpar->extradata_size); } else { - st->codec->extradata_size = 6; - st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) + st->codecpar->extradata_size = 6; + st->codecpar->extradata = av_mallocz(6 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) return AVERROR(ENOMEM); /* setup extradata with our experimentally obtained value */ - st->codec->extradata[4] = 31; + st->codecpar->extradata[4] = 31; } } - if (!st->codec->channels) { + if (!st->codecpar->channels) { av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n", - st->codec->channels); + st->codecpar->channels); return AVERROR_INVALIDDATA; } - if (!st->codec->bits_per_coded_sample) { + if (!st->codecpar->bits_per_coded_sample) { av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n", - st->codec->bits_per_coded_sample); + st->codecpar->bits_per_coded_sample); return AVERROR_INVALIDDATA; } /* set the sample rate */ - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); /* parse the remaining RIFF chunks */ for (;;) { @@ -146,7 +146,7 @@ static int xwma_read_header(AVFormatContext *s) * number of bytes accumulated after the corresponding xWMA packet * is decoded in order." * - * Each packet has size equal to st->codec->block_align, which in + * Each packet has size equal to st->codecpar->block_align, which in * all cases I saw so far was always 2230. Thus, we can use the * dpds data to compute a seeking index. */ @@ -200,7 +200,7 @@ static int xwma_read_header(AVFormatContext *s) if (dpds_table && dpds_table_size) { int64_t cur_pos; const uint32_t bytes_per_sample - = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3; + = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3; /* Estimate the duration from the total number of output bytes. */ const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; @@ -208,7 +208,7 @@ static int xwma_read_header(AVFormatContext *s) if (!bytes_per_sample) { av_log(s, AV_LOG_ERROR, "Invalid bits_per_coded_sample %d for %d channels\n", - st->codec->bits_per_coded_sample, st->codec->channels); + st->codecpar->bits_per_coded_sample, st->codecpar->channels); ret = AVERROR_INVALIDDATA; goto fail; } @@ -231,18 +231,18 @@ static int xwma_read_header(AVFormatContext *s) * an offset / timestamp pair. */ av_add_index_entry(st, - cur_pos + (i+1) * st->codec->block_align, /* pos */ - dpds_table[i] / bytes_per_sample, /* timestamp */ - st->codec->block_align, /* size */ - 0, /* duration */ + cur_pos + (i+1) * st->codecpar->block_align, /* pos */ + dpds_table[i] / bytes_per_sample, /* timestamp */ + st->codecpar->block_align, /* size */ + 0, /* duration */ AVINDEX_KEYFRAME); } - } else if (st->codec->bit_rate) { + } else if (st->codecpar->bit_rate) { /* No dpds chunk was present (or only an empty one), so estimate * the total duration using the average bits per sample and the * total data length. */ - st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate; + st->duration = (size<<3) * st->codecpar->sample_rate / st->codecpar->bit_rate; } fail: @@ -266,7 +266,7 @@ static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt) } /* read a single block; the default block size is 2230. */ - size = (st->codec->block_align > 1) ? st->codec->block_align : 2230; + size = (st->codecpar->block_align > 1) ? st->codecpar->block_align : 2230; size = FFMIN(size, left); ret = av_get_packet(s->pb, pkt, size); diff --git a/libavformat/yop.c b/libavformat/yop.c index ea3175e..c782ecd 100644 --- a/libavformat/yop.c +++ b/libavformat/yop.c @@ -53,7 +53,7 @@ static int yop_read_header(AVFormatContext *s) YopDecContext *yop = s->priv_data; AVIOContext *pb = s->pb; - AVCodecContext *audio_dec, *video_dec; + AVCodecParameters *audio_par, *video_par; AVStream *audio_stream, *video_stream; int frame_rate, ret; @@ -63,40 +63,40 @@ static int yop_read_header(AVFormatContext *s) // Extra data that will be passed to the decoder - video_stream->codec->extradata = av_mallocz(8 + FF_INPUT_BUFFER_PADDING_SIZE); + video_stream->codecpar->extradata = av_mallocz(8 + AV_INPUT_BUFFER_PADDING_SIZE); - if (!video_stream->codec->extradata) + if (!video_stream->codecpar->extradata) return AVERROR(ENOMEM); - video_stream->codec->extradata_size = 8; + video_stream->codecpar->extradata_size = 8; // Audio - audio_dec = audio_stream->codec; - audio_dec->codec_type = AVMEDIA_TYPE_AUDIO; - audio_dec->codec_id = AV_CODEC_ID_ADPCM_IMA_APC; - audio_dec->channels = 1; - audio_dec->channel_layout = AV_CH_LAYOUT_MONO; - audio_dec->sample_rate = 22050; + audio_par = audio_stream->codecpar; + audio_par->codec_type = AVMEDIA_TYPE_AUDIO; + audio_par->codec_id = AV_CODEC_ID_ADPCM_IMA_APC; + audio_par->channels = 1; + audio_par->channel_layout = AV_CH_LAYOUT_MONO; + audio_par->sample_rate = 22050; // Video - video_dec = video_stream->codec; - video_dec->codec_type = AVMEDIA_TYPE_VIDEO; - video_dec->codec_id = AV_CODEC_ID_YOP; + video_par = video_stream->codecpar; + video_par->codec_type = AVMEDIA_TYPE_VIDEO; + video_par->codec_id = AV_CODEC_ID_YOP; avio_skip(pb, 6); frame_rate = avio_r8(pb); yop->frame_size = avio_r8(pb) * 2048; - video_dec->width = avio_rl16(pb); - video_dec->height = avio_rl16(pb); + video_par->width = avio_rl16(pb); + video_par->height = avio_rl16(pb); video_stream->sample_aspect_ratio = (AVRational){1, 2}; - ret = avio_read(pb, video_dec->extradata, 8); + ret = avio_read(pb, video_par->extradata, 8); if (ret < 8) return ret < 0 ? ret : AVERROR_EOF; - yop->palette_size = video_dec->extradata[0] * 3 + 4; - yop->audio_block_length = AV_RL16(video_dec->extradata + 6); + yop->palette_size = video_par->extradata[0] * 3 + 4; + yop->audio_block_length = AV_RL16(video_par->extradata + 6); // 1840 samples per frame, 1 nibble per sample; hence 1840/2 = 920 if (yop->audio_block_length < 920 || @@ -127,11 +127,6 @@ static int yop_read_packet(AVFormatContext *s, AVPacket *pkt) *pkt = yop->video_packet; yop->video_packet.data = NULL; yop->video_packet.buf = NULL; -#if FF_API_DESTRUCT_PACKET -FF_DISABLE_DEPRECATION_WARNINGS - yop->video_packet.destruct = NULL; -FF_ENABLE_DEPRECATION_WARNINGS -#endif yop->video_packet.size = 0; pkt->data[0] = yop->odd_frame; pkt->flags |= AV_PKT_FLAG_KEY; @@ -173,14 +168,14 @@ FF_ENABLE_DEPRECATION_WARNINGS return yop->audio_block_length; err_out: - av_free_packet(&yop->video_packet); + av_packet_unref(&yop->video_packet); return ret; } static int yop_read_close(AVFormatContext *s) { YopDecContext *yop = s->priv_data; - av_free_packet(&yop->video_packet); + av_packet_unref(&yop->video_packet); return 0; } @@ -194,7 +189,7 @@ static int yop_read_seek(AVFormatContext *s, int stream_index, if (!stream_index) return -1; - pos_min = s->data_offset; + pos_min = s->internal->data_offset; pos_max = avio_size(s->pb) - yop->frame_size; frame_count = (pos_max - pos_min) / yop->frame_size; @@ -205,7 +200,7 @@ static int yop_read_seek(AVFormatContext *s, int stream_index, if (avio_seek(s->pb, frame_pos, SEEK_SET) < 0) return -1; - av_free_packet(&yop->video_packet); + av_packet_unref(&yop->video_packet); yop->odd_frame = timestamp & 1; return 0; diff --git a/libavformat/yuv4mpegdec.c b/libavformat/yuv4mpegdec.c index e5c4456..f30e188 100644 --- a/libavformat/yuv4mpegdec.c +++ b/libavformat/yuv4mpegdec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" + #include "avformat.h" #include "internal.h" #include "yuv4mpeg.h" @@ -38,8 +40,8 @@ static int yuv4_read_header(AVFormatContext *s) rated = 0, aspectn = 0, aspectd = 0; enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE, alt_pix_fmt = AV_PIX_FMT_NONE; enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; + enum AVFieldOrder field_order = AV_FIELD_UNKNOWN; AVStream *st; - enum AVFieldOrder field_order; for (i = 0; i < MAX_YUV4_HEADER; i++) { header[i] = avio_r8(pb); @@ -184,17 +186,17 @@ static int yuv4_read_header(AVFormatContext *s) st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codec->width = width; - st->codec->height = height; + st->codecpar->width = width; + st->codecpar->height = height; av_reduce(&raten, &rated, raten, rated, (1UL << 31) - 1); avpriv_set_pts_info(st, 64, rated, raten); - st->avg_frame_rate = av_inv_q(st->time_base); - st->codec->pix_fmt = pix_fmt; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - st->sample_aspect_ratio = (AVRational){ aspectn, aspectd }; - st->codec->chroma_sample_location = chroma_sample_location; - st->codec->field_order = field_order; + st->avg_frame_rate = av_inv_q(st->time_base); + st->codecpar->format = pix_fmt; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->sample_aspect_ratio = (AVRational){ aspectn, aspectd }; + st->codecpar->chroma_location = chroma_sample_location; + st->codecpar->field_order = field_order; return 0; } @@ -223,10 +225,11 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt) if (strncmp(header, Y4M_FRAME_MAGIC, strlen(Y4M_FRAME_MAGIC))) return AVERROR_INVALIDDATA; - width = st->codec->width; - height = st->codec->height; + width = st->codecpar->width; + height = st->codecpar->height; - packet_size = avpicture_get_size(st->codec->pix_fmt, width, height); + packet_size = av_image_get_buffer_size(st->codecpar->format, + width, height, 1); if (packet_size < 0) return packet_size; diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index 2caa364..8721c21 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -35,8 +35,8 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf) const char *colorspace = ""; st = s->streams[0]; - width = st->codec->width; - height = st->codec->height; + width = st->codecpar->width; + height = st->codecpar->height; // TODO: should be avg_frame_rate av_reduce(&raten, &rated, st->time_base.den, @@ -48,13 +48,13 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf) if (aspectn == 0 && aspectd == 1) aspectd = 0; // 0:0 means unknown - switch (st->codec->field_order) { + switch (st->codecpar->field_order) { case AV_FIELD_TT: inter = 't'; break; case AV_FIELD_BB: inter = 'b'; break; default: inter = 'p'; break; } - switch (st->codec->pix_fmt) { + switch (st->codecpar->format) { case AV_PIX_FMT_GRAY8: colorspace = " Cmono"; break; @@ -62,7 +62,7 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf) colorspace = " C411 XYSCSS=411"; break; case AV_PIX_FMT_YUV420P: - switch (st->codec->chroma_sample_location) { + switch (st->codecpar->chroma_location) { case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break; case AVCHROMA_LOC_LEFT: colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break; default: colorspace = " C420jpeg XYSCSS=420JPEG"; break; @@ -88,7 +88,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; AVIOContext *pb = s->pb; - AVPicture *picture; + AVFrame *frame; int* first_pkt = s->priv_data; int width, height, h_chroma_shift, v_chroma_shift; int i; @@ -96,7 +96,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) char buf1[20]; uint8_t *ptr, *ptr1, *ptr2; - picture = (AVPicture *)pkt->data; + frame = (AVFrame *)pkt->data; /* for the first packet we have to output the header as well */ if (*first_pkt) { @@ -115,32 +115,32 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); avio_write(pb, buf1, strlen(buf1)); - width = st->codec->width; - height = st->codec->height; + width = st->codecpar->width; + height = st->codecpar->height; - ptr = picture->data[0]; + ptr = frame->data[0]; for (i = 0; i < height; i++) { avio_write(pb, ptr, width); - ptr += picture->linesize[0]; + ptr += frame->linesize[0]; } - if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8) { + if (st->codecpar->format != AV_PIX_FMT_GRAY8) { // Adjust for smaller Cb and Cr planes - av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, + av_pix_fmt_get_chroma_sub_sample(st->codecpar->format, &h_chroma_shift, &v_chroma_shift); // Shift right, rounding up - width = -(-width >> h_chroma_shift); - height = -(-height >> v_chroma_shift); + width = AV_CEIL_RSHIFT(width, h_chroma_shift); + height = AV_CEIL_RSHIFT(height, v_chroma_shift); - ptr1 = picture->data[1]; - ptr2 = picture->data[2]; + ptr1 = frame->data[1]; + ptr2 = frame->data[2]; for (i = 0; i < height; i++) { /* Cb */ avio_write(pb, ptr1, width); - ptr1 += picture->linesize[1]; + ptr1 += frame->linesize[1]; } for (i = 0; i < height; i++) { /* Cr */ avio_write(pb, ptr2, width); - ptr2 += picture->linesize[2]; + ptr2 += frame->linesize[2]; } } return 0; @@ -153,18 +153,18 @@ static int yuv4_write_header(AVFormatContext *s) if (s->nb_streams != 1) return AVERROR(EIO); - if (s->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) { - av_log(s, AV_LOG_ERROR, "ERROR: Only rawvideo supported.\n"); + if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) { + av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n"); return AVERROR_INVALIDDATA; } - if (s->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV411P) { + if (s->streams[0]->codecpar->format == AV_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 != AV_PIX_FMT_YUV420P) && - (s->streams[0]->codec->pix_fmt != AV_PIX_FMT_YUV422P) && - (s->streams[0]->codec->pix_fmt != AV_PIX_FMT_GRAY8) && - (s->streams[0]->codec->pix_fmt != AV_PIX_FMT_YUV444P)) { + } else if ((s->streams[0]->codecpar->format != AV_PIX_FMT_YUV420P) && + (s->streams[0]->codecpar->format != AV_PIX_FMT_YUV422P) && + (s->streams[0]->codecpar->format != AV_PIX_FMT_GRAY8) && + (s->streams[0]->codecpar->format != AV_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"); @@ -182,8 +182,7 @@ AVOutputFormat ff_yuv4mpegpipe_muxer = { .extensions = "y4m", .priv_data_size = sizeof(int), .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_header = yuv4_write_header, .write_packet = yuv4_write_packet, - .flags = AVFMT_RAWPICTURE, }; diff --git a/libavresample/aarch64/Makefile b/libavresample/aarch64/Makefile index 1d9e5f8..f92699e 100644 --- a/libavresample/aarch64/Makefile +++ b/libavresample/aarch64/Makefile @@ -1,7 +1,7 @@ -OBJS += aarch64/audio_convert_init.o \ - aarch64/resample_init.o \ +OBJS += aarch64/audio_convert_init.o \ + aarch64/resample_init.o \ OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o -NEON-OBJS += aarch64/audio_convert_neon.o \ - aarch64/resample_neon.o \ +NEON-OBJS += aarch64/audio_convert_neon.o \ + aarch64/resample_neon.o \ diff --git a/libavresample/aarch64/resample_init.c b/libavresample/aarch64/resample_init.c index 9ef9977..ec321a3 100644 --- a/libavresample/aarch64/resample_init.c +++ b/libavresample/aarch64/resample_init.c @@ -45,8 +45,8 @@ void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0, int dst_index, const void *src0, unsigned int index, int frac); -void ff_audio_resample_init_aarch64(ResampleContext *c, - enum AVSampleFormat sample_fmt) +av_cold void ff_audio_resample_init_aarch64(ResampleContext *c, + enum AVSampleFormat sample_fmt) { int cpu_flags = av_get_cpu_flags(); diff --git a/libavresample/arm/Makefile b/libavresample/arm/Makefile index 60f3f6d..352d1a8 100644 --- a/libavresample/arm/Makefile +++ b/libavresample/arm/Makefile @@ -1,5 +1,7 @@ -OBJS += arm/audio_convert_init.o +OBJS += arm/audio_convert_init.o \ + arm/resample_init.o OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o -NEON-OBJS += arm/audio_convert_neon.o +NEON-OBJS += arm/audio_convert_neon.o \ + arm/resample_neon.o diff --git a/libavresample/arm/asm-offsets.h b/libavresample/arm/asm-offsets.h new file mode 100644 index 0000000..a1623ed --- /dev/null +++ b/libavresample/arm/asm-offsets.h @@ -0,0 +1,29 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVRESAMPLE_ARM_ASM_OFFSETS_H +#define AVRESAMPLE_ARM_ASM_OFFSETS_H + +/* struct ResampleContext */ +#define FILTER_BANK 0x08 +#define FILTER_LENGTH 0x0c +#define SRC_INCR 0x20 +#define PHASE_SHIFT 0x28 +#define PHASE_MASK (PHASE_SHIFT + 0x04) + +#endif /* AVRESAMPLE_ARM_ASM_OFFSETS_H */ diff --git a/libavresample/arm/resample_init.c b/libavresample/arm/resample_init.c new file mode 100644 index 0000000..540177e --- /dev/null +++ b/libavresample/arm/resample_init.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavutil/internal.h" +#include "libavutil/samplefmt.h" + +#include "libavresample/resample.h" + +#include "asm-offsets.h" + +AV_CHECK_OFFSET(struct ResampleContext, filter_bank, FILTER_BANK); +AV_CHECK_OFFSET(struct ResampleContext, filter_length, FILTER_LENGTH); +AV_CHECK_OFFSET(struct ResampleContext, src_incr, SRC_INCR); +AV_CHECK_OFFSET(struct ResampleContext, phase_shift, PHASE_SHIFT); +AV_CHECK_OFFSET(struct ResampleContext, phase_mask, PHASE_MASK); + +void ff_resample_one_flt_neon(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); +void ff_resample_one_s16_neon(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); +void ff_resample_one_s32_neon(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); + +void ff_resample_linear_flt_neon(struct ResampleContext *c, void *dst0, + int dst_index, const void *src0, + unsigned int index, int frac); + +av_cold void ff_audio_resample_init_arm(ResampleContext *c, + enum AVSampleFormat sample_fmt) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_neon(cpu_flags)) { + switch (sample_fmt) { + case AV_SAMPLE_FMT_FLTP: + if (c->linear) + c->resample_one = ff_resample_linear_flt_neon; + else + c->resample_one = ff_resample_one_flt_neon; + break; + case AV_SAMPLE_FMT_S16P: + if (!c->linear) + c->resample_one = ff_resample_one_s16_neon; + break; + case AV_SAMPLE_FMT_S32P: + if (!c->linear) + c->resample_one = ff_resample_one_s32_neon; + break; + } + } +} diff --git a/libavresample/arm/resample_neon.S b/libavresample/arm/resample_neon.S new file mode 100644 index 0000000..a8181e5 --- /dev/null +++ b/libavresample/arm/resample_neon.S @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2014 Peter Meerwald + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +#include "asm-offsets.h" + +.macro resample_one fmt, es=2 +function ff_resample_one_\fmt\()_neon, export=1 + push {r4, r5} + add r1, r1, r2, lsl #\es + + ldr r2, [r0, #PHASE_SHIFT+4] /* phase_mask */ + ldr ip, [sp, #8] /* index */ + ldr r5, [r0, #FILTER_LENGTH] + and r2, ip, r2 /* (index & phase_mask) */ + ldr r4, [r0, #PHASE_SHIFT] + lsr r4, ip, r4 /* compute sample_index */ + mul r2, r2, r5 + + ldr ip, [r0, #FILTER_BANK] + add r3, r3, r4, lsl #\es /* &src[sample_index] */ + + cmp r5, #8 + add r0, ip, r2, lsl #\es /* filter = &filter_bank[...] */ + + blt 5f +8: + subs r5, r5, #8 + LOAD4 + MUL4 +7: + LOAD4 + beq 6f + cmp r5, #8 + MLA4 + blt 4f + subs r5, r5, #8 + LOAD4 + MLA4 + b 7b +6: + MLA4 + STORE + pop {r4, r5} + bx lr +5: + INIT4 +4: /* remaining filter_length 1 to 7 */ + cmp r5, #4 + blt 2f + subs r5, r5, #4 + LOAD4 + MLA4 + beq 0f +2: /* remaining filter_length 1 to 3 */ + cmp r5, #2 + blt 1f + subs r5, r5, #2 + LOAD2 + MLA2 + beq 0f +1: /* remaining filter_length 1 */ + LOAD1 + MLA1 +0: + STORE + pop {r4, r5} + bx lr +endfunc + +.purgem LOAD1 +.purgem LOAD2 +.purgem LOAD4 +.purgem MLA1 +.purgem MLA2 +.purgem MLA4 +.purgem MUL4 +.purgem INIT4 +.purgem STORE +.endm + + +/* float32 */ +.macro LOAD1 + veor.32 d0, d0 + vld1.32 {d0[0]}, [r0]! /* load filter */ + vld1.32 {d4[0]}, [r3]! /* load src */ +.endm +.macro LOAD2 + vld1.32 {d0}, [r0]! /* load filter */ + vld1.32 {d4}, [r3]! /* load src */ +.endm +.macro LOAD4 + vld1.32 {d0,d1}, [r0]! /* load filter */ + vld1.32 {d4,d5}, [r3]! /* load src */ +.endm +.macro MLA1 + vmla.f32 d16, d0, d4[0] +.endm +.macro MLA2 + vmla.f32 d16, d0, d4 +.endm +.macro MLA4 + vmla.f32 d16, d0, d4 + vmla.f32 d17, d1, d5 +.endm +.macro MUL4 + vmul.f32 d16, d0, d4 + vmul.f32 d17, d1, d5 +.endm +.macro INIT4 + veor.f32 q8, q8 +.endm +.macro STORE + vpadd.f32 d16, d16, d17 + vpadd.f32 d16, d16, d16 + vst1.32 d16[0], [r1] +.endm + +resample_one flt, 2 + + +/* s32 */ +.macro LOAD1 + veor.32 d0, d0 + vld1.32 {d0[0]}, [r0]! /* load filter */ + vld1.32 {d4[0]}, [r3]! /* load src */ +.endm +.macro LOAD2 + vld1.32 {d0}, [r0]! /* load filter */ + vld1.32 {d4}, [r3]! /* load src */ +.endm +.macro LOAD4 + vld1.32 {d0,d1}, [r0]! /* load filter */ + vld1.32 {d4,d5}, [r3]! /* load src */ +.endm +.macro MLA1 + vmlal.s32 q8, d0, d4[0] +.endm +.macro MLA2 + vmlal.s32 q8, d0, d4 +.endm +.macro MLA4 + vmlal.s32 q8, d0, d4 + vmlal.s32 q9, d1, d5 +.endm +.macro MUL4 + vmull.s32 q8, d0, d4 + vmull.s32 q9, d1, d5 +.endm +.macro INIT4 + veor.s64 q8, q8 + veor.s64 q9, q9 +.endm +.macro STORE + vadd.s64 q8, q8, q9 + vadd.s64 d16, d16, d17 + vqrshrn.s64 d16, q8, #30 + vst1.32 d16[0], [r1] +.endm + +resample_one s32, 2 + + +/* s16 */ +.macro LOAD1 + veor.16 d0, d0 + vld1.16 {d0[0]}, [r0]! /* load filter */ + vld1.16 {d4[0]}, [r3]! /* load src */ +.endm +.macro LOAD2 + veor.16 d0, d0 + vld1.32 {d0[0]}, [r0]! /* load filter */ + veor.16 d4, d4 + vld1.32 {d4[0]}, [r3]! /* load src */ +.endm +.macro LOAD4 + vld1.16 {d0}, [r0]! /* load filter */ + vld1.16 {d4}, [r3]! /* load src */ +.endm +.macro MLA1 + vmlal.s16 q8, d0, d4[0] +.endm +.macro MLA2 + vmlal.s16 q8, d0, d4 +.endm +.macro MLA4 + vmlal.s16 q8, d0, d4 +.endm +.macro MUL4 + vmull.s16 q8, d0, d4 +.endm +.macro INIT4 + veor.s32 q8, q8 +.endm +.macro STORE + vpadd.s32 d16, d16, d17 + vpadd.s32 d16, d16, d16 + vqrshrn.s32 d16, q8, #15 + vst1.16 d16[0], [r1] +.endm + +resample_one s16, 1 + + +.macro resample_linear fmt, es=2 +function ff_resample_linear_\fmt\()_neon, export=1 + push {r4, r5} + add r1, r1, r2, lsl #\es + + ldr r2, [r0, #PHASE_SHIFT+4] /* phase_mask */ + ldr ip, [sp, #8] /* index */ + ldr r5, [r0, #FILTER_LENGTH] + and r2, ip, r2 /* (index & phase_mask) */ + ldr r4, [r0, #PHASE_SHIFT] + lsr r4, ip, r4 /* compute sample_index */ + mul r2, r2, r5 + + ldr ip, [r0, #FILTER_BANK] + add r3, r3, r4, lsl #\es /* &src[sample_index] */ + + cmp r5, #8 + ldr r4, [r0, #SRC_INCR] + add r0, ip, r2, lsl #\es /* filter = &filter_bank[...] */ + add r2, r0, r5, lsl #\es /* filter[... + c->filter_length] */ + + blt 5f +8: + subs r5, r5, #8 + LOAD4 + MUL4 +7: + LOAD4 + beq 6f + cmp r5, #8 + MLA4 + blt 4f + subs r5, r5, #8 + LOAD4 + MLA4 + b 7b +6: + MLA4 + STORE + pop {r4, r5} + bx lr +5: + INIT4 +4: /* remaining filter_length 1 to 7 */ + cmp r5, #4 + blt 2f + subs r5, r5, #4 + LOAD4 + MLA4 + beq 0f +2: /* remaining filter_length 1 to 3 */ + cmp r5, #2 + blt 1f + subs r5, r5, #2 + LOAD2 + MLA2 + beq 0f +1: /* remaining filter_length 1 */ + LOAD1 + MLA1 +0: + STORE + pop {r4, r5} + bx lr +endfunc + +.purgem LOAD1 +.purgem LOAD2 +.purgem LOAD4 +.purgem MLA1 +.purgem MLA2 +.purgem MLA4 +.purgem MUL4 +.purgem INIT4 +.purgem STORE +.endm + + +/* float32 linear */ +.macro LOAD1 + veor.32 d0, d0 + veor.32 d2, d2 + vld1.32 {d0[0]}, [r0]! /* load filter */ + vld1.32 {d2[0]}, [r2]! /* load filter */ + vld1.32 {d4[0]}, [r3]! /* load src */ +.endm +.macro LOAD2 + vld1.32 {d0}, [r0]! /* load filter */ + vld1.32 {d2}, [r2]! /* load filter */ + vld1.32 {d4}, [r3]! /* load src */ +.endm +.macro LOAD4 + vld1.32 {d0,d1}, [r0]! /* load filter */ + vld1.32 {d2,d3}, [r2]! /* load filter */ + vld1.32 {d4,d5}, [r3]! /* load src */ +.endm +.macro MLA1 + vmla.f32 d18, d0, d4[0] + vmla.f32 d16, d2, d4[0] +.endm +.macro MLA2 + vmla.f32 d18, d0, d4 + vmla.f32 d16, d2, d4 +.endm +.macro MLA4 + vmla.f32 q9, q0, q2 + vmla.f32 q8, q1, q2 +.endm +.macro MUL4 + vmul.f32 q9, q0, q2 + vmul.f32 q8, q1, q2 +.endm +.macro INIT4 + veor.f32 q9, q9 + veor.f32 q8, q8 +.endm +.macro STORE + vldr s0, [sp, #12] /* frac */ + vmov s1, r4 + vcvt.f32.s32 d0, d0 + + vsub.f32 q8, q8, q9 /* v2 - val */ + vpadd.f32 d18, d18, d19 + vpadd.f32 d16, d16, d17 + vpadd.f32 d2, d18, d18 + vpadd.f32 d1, d16, d16 + + vmul.f32 s2, s2, s0 /* (v2 - val) * frac */ + vdiv.f32 s2, s2, s1 /* / c->src_incr */ + vadd.f32 s4, s4, s2 + + vstr s4, [r1] +.endm + +resample_linear flt, 2 diff --git a/libavresample/audio_convert.c b/libavresample/audio_convert.c index ef23912..eabcd86 100644 --- a/libavresample/audio_convert.c +++ b/libavresample/audio_convert.c @@ -319,7 +319,7 @@ int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) if (ac->dc) { /* dithered conversion */ - av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (dithered)\n", + av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt)); @@ -337,7 +337,7 @@ int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) use_generic = 0; } } - av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len, + av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic : ac->func_descr); diff --git a/libavresample/audio_data.c b/libavresample/audio_data.c index 7a6fe74..2d01b8c 100644 --- a/libavresample/audio_data.c +++ b/libavresample/audio_data.c @@ -70,9 +70,10 @@ int ff_audio_data_set_channels(AudioData *a, int channels) return 0; } -int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels, - int nb_samples, enum AVSampleFormat sample_fmt, - int read_only, const char *name) +int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size, + int channels, int nb_samples, + enum AVSampleFormat sample_fmt, int read_only, + const char *name) { int p; diff --git a/libavresample/audio_data.h b/libavresample/audio_data.h index 1541976..a478592 100644 --- a/libavresample/audio_data.h +++ b/libavresample/audio_data.h @@ -76,9 +76,10 @@ int ff_audio_data_set_channels(AudioData *a, int channels); * @param name name for debug logging (can be NULL) * @return 0 on success, negative AVERROR value on error */ -int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels, - int nb_samples, enum AVSampleFormat sample_fmt, - int read_only, const char *name); +int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size, + int channels, int nb_samples, + enum AVSampleFormat sample_fmt, int read_only, + const char *name); /** * Allocate AudioData. diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c index 8619c1a..8ff82a2 100644 --- a/libavresample/audio_mix.c +++ b/libavresample/audio_mix.c @@ -441,7 +441,7 @@ int ff_audio_mix(AudioMix *am, AudioData *src) use_generic = 0; } } - av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n", + av_log(am->avr, AV_LOG_TRACE, "audio_mix: %d samples - %d to %d channels (%s)\n", src->nb_samples, am->in_channels, am->out_channels, use_generic ? am->func_descr_generic : am->func_descr); diff --git a/libavresample/avresample.h b/libavresample/avresample.h index b705a45..c66798c 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -167,9 +167,13 @@ AVAudioResampleContext *avresample_alloc_context(void); /** * Initialize AVAudioResampleContext. * @note The context must be configured using the AVOption API. + * @note The fields "in_channel_layout", "out_channel_layout", + * "in_sample_rate", "out_sample_rate", "in_sample_fmt", + * "out_sample_fmt" must be set. * * @see av_opt_set_int() * @see av_opt_set_dict() + * @see av_get_default_channel_layout() * * @param avr audio resample context * @return 0 on success, negative AVERROR code on failure @@ -373,8 +377,9 @@ int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples); * output FIFO */ int avresample_convert(AVAudioResampleContext *avr, uint8_t **output, - int out_plane_size, int out_samples, uint8_t **input, - int in_plane_size, int in_samples); + int out_plane_size, int out_samples, + uint8_t * const *input, int in_plane_size, + int in_samples); /** * Return the number of samples currently in the resampling delay buffer. diff --git a/libavresample/dither.h b/libavresample/dither.h index 8db3714..5e42401 100644 --- a/libavresample/dither.h +++ b/libavresample/dither.h @@ -37,8 +37,8 @@ typedef struct DitherDSPContext { */ void (*quantize)(int16_t *dst, const float *src, float *dither, int len); - int ptr_align; ///< src and dst constraits for quantize() - int samples_align; ///< len constraits for quantize() + int ptr_align; ///< src and dst constraints for quantize() + int samples_align; ///< len constraints for quantize() /** * Convert dither noise from int to float with triangular distribution. diff --git a/libavresample/internal.h b/libavresample/internal.h index e59758c..b88b758 100644 --- a/libavresample/internal.h +++ b/libavresample/internal.h @@ -110,4 +110,7 @@ struct AVAudioResampleContext { void ff_audio_resample_init_aarch64(ResampleContext *c, enum AVSampleFormat sample_fmt); +void ff_audio_resample_init_arm(ResampleContext *c, + enum AVSampleFormat sample_fmt); + #endif /* AVRESAMPLE_INTERNAL_H */ diff --git a/libavresample/libavresample.v b/libavresample/libavresample.v index b8c7c7d..d6fc751 100644 --- a/libavresample/libavresample.v +++ b/libavresample/libavresample.v @@ -1,4 +1,6 @@ -LIBAVRESAMPLE_$MAJOR { - global: av*; - local: *; +LIBAVRESAMPLE_MAJOR { + global: + av*; + local: + *; }; diff --git a/libavresample/resample.c b/libavresample/resample.c index 679e9e9..be344b6 100644 --- a/libavresample/resample.c +++ b/libavresample/resample.c @@ -46,7 +46,7 @@ #include "resample_template.c" -/* 0th order modified bessel function of the first kind. */ +/* 0th order modified Bessel function of the first kind. */ static double bessel(double x) { double v = 1; @@ -172,6 +172,8 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) if (ARCH_AARCH64) ff_audio_resample_init_aarch64(c, avr->internal_sample_fmt); + if (ARCH_ARM) + ff_audio_resample_init_arm(c, avr->internal_sample_fmt); felem_size = av_get_bytes_per_sample(avr->internal_sample_fmt); c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * felem_size); @@ -232,8 +234,6 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, int compensation_distance) { ResampleContext *c; - AudioData *fifo_buf = NULL; - int ret = 0; if (compensation_distance < 0) return AVERROR(EINVAL); @@ -241,62 +241,8 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, return AVERROR(EINVAL); if (!avr->resample_needed) { -#if FF_API_RESAMPLE_CLOSE_OPEN - /* if resampling was not enabled previously, re-initialize the - AVAudioResampleContext and force resampling */ - int fifo_samples; - int restore_matrix = 0; - double matrix[AVRESAMPLE_MAX_CHANNELS * AVRESAMPLE_MAX_CHANNELS] = { 0 }; - - /* buffer any remaining samples in the output FIFO before closing */ - fifo_samples = av_audio_fifo_size(avr->out_fifo); - if (fifo_samples > 0) { - fifo_buf = ff_audio_data_alloc(avr->out_channels, fifo_samples, - avr->out_sample_fmt, NULL); - if (!fifo_buf) - return AVERROR(EINVAL); - ret = ff_audio_data_read_from_fifo(avr->out_fifo, fifo_buf, - fifo_samples); - if (ret < 0) - goto reinit_fail; - } - /* save the channel mixing matrix */ - if (avr->am) { - ret = avresample_get_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS); - if (ret < 0) - goto reinit_fail; - restore_matrix = 1; - } - - /* close the AVAudioResampleContext */ - avresample_close(avr); - - avr->force_resampling = 1; - - /* restore the channel mixing matrix */ - if (restore_matrix) { - ret = avresample_set_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS); - if (ret < 0) - goto reinit_fail; - } - - /* re-open the AVAudioResampleContext */ - ret = avresample_open(avr); - if (ret < 0) - goto reinit_fail; - - /* restore buffered samples to the output FIFO */ - if (fifo_samples > 0) { - ret = ff_audio_data_add_to_fifo(avr->out_fifo, fifo_buf, 0, - fifo_samples); - if (ret < 0) - goto reinit_fail; - ff_audio_data_free(&fifo_buf); - } -#else av_log(avr, AV_LOG_ERROR, "Unable to set resampling compensation\n"); return AVERROR(EINVAL); -#endif } c = avr->resample; c->compensation_distance = compensation_distance; @@ -306,11 +252,8 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, } else { c->dst_incr = c->ideal_dst_incr; } - return 0; -reinit_fail: - ff_audio_data_free(&fifo_buf); - return ret; + return 0; } static int resample(ResampleContext *c, void *dst, const void *src, @@ -485,7 +428,7 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) ff_audio_data_drain(c->buffer, consumed); c->initial_padding_samples = FFMAX(c->initial_padding_samples - consumed, 0); - av_dlog(c->avr, "resampled %d in + %d leftover to %d out + %d leftover\n", + av_log(c->avr, AV_LOG_TRACE, "resampled %d in + %d leftover to %d out + %d leftover\n", in_samples, in_leftover, out_samples, c->buffer->nb_samples); dst->nb_samples = out_samples; diff --git a/libavresample/tests/.gitignore b/libavresample/tests/.gitignore new file mode 100644 index 0000000..1e15871 --- /dev/null +++ b/libavresample/tests/.gitignore @@ -0,0 +1 @@ +/avresample diff --git a/libavresample/avresample-test.c b/libavresample/tests/avresample.c similarity index 99% rename from libavresample/avresample-test.c rename to libavresample/tests/avresample.c index 697b4ba..7759996 100644 --- a/libavresample/avresample-test.c +++ b/libavresample/tests/avresample.c @@ -30,7 +30,8 @@ #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/samplefmt.h" -#include "avresample.h" + +#include "libavresample/avresample.h" static double dbl_rand(AVLFG *lfg) { diff --git a/libavresample/utils.c b/libavresample/utils.c index 5d095c0..bab2153 100644 --- a/libavresample/utils.c +++ b/libavresample/utils.c @@ -127,46 +127,46 @@ int avresample_open(AVAudioResampleContext *avr) if (avr->use_channel_map) { if (avr->in_copy_needed) { avr->remap_point = REMAP_IN_COPY; - av_dlog(avr, "remap channels during in_copy\n"); + av_log(avr, AV_LOG_TRACE, "remap channels during in_copy\n"); } else if (avr->in_convert_needed) { avr->remap_point = REMAP_IN_CONVERT; - av_dlog(avr, "remap channels during in_convert\n"); + av_log(avr, AV_LOG_TRACE, "remap channels during in_convert\n"); } else if (avr->out_convert_needed) { avr->remap_point = REMAP_OUT_CONVERT; - av_dlog(avr, "remap channels during out_convert\n"); + av_log(avr, AV_LOG_TRACE, "remap channels during out_convert\n"); } else { avr->remap_point = REMAP_OUT_COPY; - av_dlog(avr, "remap channels during out_copy\n"); + av_log(avr, AV_LOG_TRACE, "remap channels during out_copy\n"); } #ifdef DEBUG { int ch; - av_dlog(avr, "output map: "); + av_log(avr, AV_LOG_TRACE, "output map: "); if (avr->ch_map_info.do_remap) for (ch = 0; ch < avr->in_channels; ch++) - av_dlog(avr, " % 2d", avr->ch_map_info.channel_map[ch]); + av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_map[ch]); else - av_dlog(avr, "n/a"); - av_dlog(avr, "\n"); - av_dlog(avr, "copy map: "); + av_log(avr, AV_LOG_TRACE, "n/a"); + av_log(avr, AV_LOG_TRACE, "\n"); + av_log(avr, AV_LOG_TRACE, "copy map: "); if (avr->ch_map_info.do_copy) for (ch = 0; ch < avr->in_channels; ch++) - av_dlog(avr, " % 2d", avr->ch_map_info.channel_copy[ch]); + av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_copy[ch]); else - av_dlog(avr, "n/a"); - av_dlog(avr, "\n"); - av_dlog(avr, "zero map: "); + av_log(avr, AV_LOG_TRACE, "n/a"); + av_log(avr, AV_LOG_TRACE, "\n"); + av_log(avr, AV_LOG_TRACE, "zero map: "); if (avr->ch_map_info.do_zero) for (ch = 0; ch < avr->in_channels; ch++) - av_dlog(avr, " % 2d", avr->ch_map_info.channel_zero[ch]); + av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_zero[ch]); else - av_dlog(avr, "n/a"); - av_dlog(avr, "\n"); - av_dlog(avr, "input map: "); + av_log(avr, AV_LOG_TRACE, "n/a"); + av_log(avr, AV_LOG_TRACE, "\n"); + av_log(avr, AV_LOG_TRACE, "input map: "); for (ch = 0; ch < avr->in_channels; ch++) - av_dlog(avr, " % 2d", avr->ch_map_info.input_map[ch]); - av_dlog(avr, "\n"); + av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.input_map[ch]); + av_log(avr, AV_LOG_TRACE, "\n"); } #endif } else @@ -295,7 +295,7 @@ static int handle_buffered_output(AVAudioResampleContext *avr, /* if there are any samples in the output FIFO or if the user-supplied output buffer is not large enough for all samples, we add to the output FIFO */ - av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name); + av_log(avr, AV_LOG_TRACE, "[FIFO] add %s to out_fifo\n", converted->name); ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0, converted->nb_samples); if (ret < 0) @@ -305,31 +305,32 @@ static int handle_buffered_output(AVAudioResampleContext *avr, /* if the user specified an output buffer, read samples from the output FIFO to the user output */ if (output && output->allocated_samples > 0) { - av_dlog(avr, "[FIFO] read from out_fifo to output\n"); - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[FIFO] read from out_fifo to output\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return ff_audio_data_read_from_fifo(avr->out_fifo, output, output->allocated_samples); } } else if (converted) { /* copy directly to output if it is large enough or there is not any data in the output FIFO */ - av_dlog(avr, "[copy] %s to output\n", converted->name); + av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", converted->name); output->nb_samples = 0; ret = ff_audio_data_copy(output, converted, avr->remap_point == REMAP_OUT_COPY ? &avr->ch_map_info : NULL); if (ret < 0) return ret; - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return output->nb_samples; } - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return 0; } int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, - int out_samples, uint8_t **input, + int out_samples, + uint8_t * const *input, int in_plane_size, int in_samples) { AudioData input_buffer; @@ -354,7 +355,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, avr->out_buffer->allocated_channels); } - av_dlog(avr, "[start conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[start conversion]\n"); /* initialize output_buffer with output data */ direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0; @@ -380,7 +381,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, !avr->out_convert_needed && direct_output && out_samples >= in_samples) { /* in some rare cases we can copy input to output and upmix directly in the output buffer */ - av_dlog(avr, "[copy] %s to output\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", current_buffer->name); ret = ff_audio_data_copy(&output_buffer, current_buffer, avr->remap_point == REMAP_OUT_COPY ? &avr->ch_map_info : NULL); @@ -392,7 +393,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, /* if remapping channels during output copy, we may need to * use an intermediate buffer in order to remap before adding * samples to the output fifo */ - av_dlog(avr, "[copy] %s to out_buffer\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[copy] %s to out_buffer\n", current_buffer->name); ret = ff_audio_data_copy(avr->out_buffer, current_buffer, &avr->ch_map_info); if (ret < 0) @@ -406,13 +407,13 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, current_buffer->nb_samples); if (ret < 0) return ret; - av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[convert] %s to in_buffer\n", current_buffer->name); ret = ff_audio_convert(avr->ac_in, avr->in_buffer, current_buffer); if (ret < 0) return ret; } else { - av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[copy] %s to in_buffer\n", current_buffer->name); ret = ff_audio_data_copy(avr->in_buffer, current_buffer, avr->remap_point == REMAP_IN_COPY ? &avr->ch_map_info : NULL); @@ -421,7 +422,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, } ff_audio_data_set_channels(avr->in_buffer, avr->in_channels); if (avr->downmix_needed) { - av_dlog(avr, "[downmix] in_buffer\n"); + av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n"); ret = ff_audio_mix(avr->am, avr->in_buffer); if (ret < 0) return ret; @@ -443,7 +444,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, resample_out = &output_buffer; else resample_out = avr->resample_out_buffer; - av_dlog(avr, "[resample] %s to %s\n", + av_log(avr, AV_LOG_TRACE, "[resample] %s to %s\n", current_buffer ? current_buffer->name : "null", resample_out->name); ret = ff_audio_resample(avr->resample, resample_out, @@ -453,7 +454,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, /* if resampling did not produce any samples, just return 0 */ if (resample_out->nb_samples == 0) { - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return 0; } @@ -461,7 +462,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, } if (avr->upmix_needed) { - av_dlog(avr, "[upmix] %s\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[upmix] %s\n", current_buffer->name); ret = ff_audio_mix(avr->am, current_buffer); if (ret < 0) return ret; @@ -469,26 +470,26 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, /* if we resampled or upmixed directly to output, return here */ if (current_buffer == &output_buffer) { - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return current_buffer->nb_samples; } if (avr->out_convert_needed) { if (direct_output && out_samples >= current_buffer->nb_samples) { /* convert directly to output */ - av_dlog(avr, "[convert] %s to output\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[convert] %s to output\n", current_buffer->name); ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer); if (ret < 0) return ret; - av_dlog(avr, "[end conversion]\n"); + av_log(avr, AV_LOG_TRACE, "[end conversion]\n"); return output_buffer.nb_samples; } else { ret = ff_audio_data_realloc(avr->out_buffer, current_buffer->nb_samples); if (ret < 0) return ret; - av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name); + av_log(avr, AV_LOG_TRACE, "[convert] %s to out_buffer\n", current_buffer->name); ret = ff_audio_convert(avr->ac_out, avr->out_buffer, current_buffer); if (ret < 0) @@ -585,9 +586,12 @@ static inline int convert_frame(AVAudioResampleContext *avr, static inline int available_samples(AVFrame *out) { + int samples; int bytes_per_sample = av_get_bytes_per_sample(out->format); - int samples = out->linesize[0] / bytes_per_sample; + if (!bytes_per_sample) + return AVERROR(EINVAL); + samples = out->linesize[0] / bytes_per_sample; if (av_sample_fmt_is_planar(out->format)) { return samples; } else { diff --git a/libavresample/version.h b/libavresample/version.h index 34623a1..2f204e0 100644 --- a/libavresample/version.h +++ b/libavresample/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" -#define LIBAVRESAMPLE_VERSION_MAJOR 2 -#define LIBAVRESAMPLE_VERSION_MINOR 1 +#define LIBAVRESAMPLE_VERSION_MAJOR 3 +#define LIBAVRESAMPLE_VERSION_MINOR 0 #define LIBAVRESAMPLE_VERSION_MICRO 0 #define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \ @@ -47,8 +47,4 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_RESAMPLE_CLOSE_OPEN -#define FF_API_RESAMPLE_CLOSE_OPEN (LIBAVRESAMPLE_VERSION_MAJOR < 3) -#endif - #endif /* AVRESAMPLE_VERSION_H */ diff --git a/libavresample/x86/audio_convert.asm b/libavresample/x86/audio_convert.asm index 1af1429..28f05a2 100644 --- a/libavresample/x86/audio_convert.asm +++ b/libavresample/x86/audio_convert.asm @@ -36,7 +36,7 @@ pb_interleave_words: SHUFFLE_MASK_W 0, 4, 1, 5, 2, 6, 3, 7 pb_deinterleave_words: SHUFFLE_MASK_W 0, 2, 4, 6, 1, 3, 5, 7 pw_zero_even: times 4 dw 0x0000, 0xffff -SECTION_TEXT +SECTION .text ;------------------------------------------------------------------------------ ; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len); diff --git a/libavresample/x86/audio_convert_init.c b/libavresample/x86/audio_convert_init.c index d85ca84..ae6c319 100644 --- a/libavresample/x86/audio_convert_init.c +++ b/libavresample/x86/audio_convert_init.c @@ -226,11 +226,13 @@ av_cold void ff_audio_convert_init_x86(AudioConvert *ac) ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, 6, 16, 4, "SSE4", ff_conv_fltp_to_flt_6ch_sse4); } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32, 0, 32, 16, "AVX", ff_conv_s32_to_flt_avx); ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, 0, 32, 32, "AVX", ff_conv_flt_to_s32_avx); + } + if (EXTERNAL_AVX(cpu_flags)) { ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, 2, 16, 16, "AVX", ff_conv_s16p_to_s16_2ch_avx); ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, diff --git a/libavresample/x86/audio_mix.asm b/libavresample/x86/audio_mix.asm index 2c657b5..13a04c6 100644 --- a/libavresample/x86/audio_mix.asm +++ b/libavresample/x86/audio_mix.asm @@ -22,7 +22,7 @@ %include "libavutil/x86/x86util.asm" %include "util.asm" -SECTION_TEXT +SECTION .text ;----------------------------------------------------------------------------- ; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len, diff --git a/libavresample/x86/audio_mix_init.c b/libavresample/x86/audio_mix_init.c index 7fc530e..e14a540 100644 --- a/libavresample/x86/audio_mix_init.c +++ b/libavresample/x86/audio_mix_init.c @@ -195,11 +195,13 @@ av_cold void ff_audio_mix_init_x86(AudioMix *am) ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT, 1, 2, 16, 8, "SSE4", ff_mix_1_to_2_s16p_flt_sse4); } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT, 2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx); ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT, 1, 2, 32, 8, "AVX", ff_mix_1_to_2_fltp_flt_avx); + } + if (EXTERNAL_AVX(cpu_flags)) { ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT, 1, 2, 16, 8, "AVX", ff_mix_1_to_2_s16p_flt_avx); } diff --git a/libavresample/x86/dither.asm b/libavresample/x86/dither.asm index 2192e98..67af203 100644 --- a/libavresample/x86/dither.asm +++ b/libavresample/x86/dither.asm @@ -28,7 +28,7 @@ pf_dither_scale: times 8 dd 2.32830643762e-10 pf_s16_scale: times 4 dd 32753.0 -SECTION_TEXT +SECTION .text ;------------------------------------------------------------------------------ ; void ff_quantize(int16_t *dst, float *src, float *dither, int len); diff --git a/libavresample/x86/dither_init.c b/libavresample/x86/dither_init.c index 8349d5e..2a351c5 100644 --- a/libavresample/x86/dither_init.c +++ b/libavresample/x86/dither_init.c @@ -46,14 +46,14 @@ av_cold void ff_dither_init_x86(DitherDSPContext *ddsp, if (EXTERNAL_SSE2(cpu_flags)) { ddsp->dither_int_to_float = ff_dither_int_to_float_rectangular_sse2; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { ddsp->dither_int_to_float = ff_dither_int_to_float_rectangular_avx; } } else { if (EXTERNAL_SSE2(cpu_flags)) { ddsp->dither_int_to_float = ff_dither_int_to_float_triangular_sse2; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { ddsp->dither_int_to_float = ff_dither_int_to_float_triangular_avx; } } diff --git a/libavutil/.gitignore b/libavutil/.gitignore new file mode 100644 index 0000000..e2ac949 --- /dev/null +++ b/libavutil/.gitignore @@ -0,0 +1 @@ +/avconfig.h diff --git a/libavutil/Makefile b/libavutil/Makefile index 0f8ed08..b10b4d2 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -4,7 +4,6 @@ HEADERS = adler32.h \ aes.h \ attributes.h \ audio_fifo.h \ - audioconvert.h \ avassert.h \ avstring.h \ avutil.h \ @@ -16,6 +15,7 @@ HEADERS = adler32.h \ common.h \ cpu.h \ crc.h \ + dict.h \ display.h \ downmix_info.h \ error.h \ @@ -24,6 +24,12 @@ HEADERS = adler32.h \ file.h \ frame.h \ hmac.h \ + hwcontext.h \ + hwcontext_cuda.h \ + hwcontext_dxva2.h \ + hwcontext_qsv.h \ + hwcontext_vaapi.h \ + hwcontext_vdpau.h \ imgutils.h \ intfloat.h \ intreadwrite.h \ @@ -33,15 +39,13 @@ HEADERS = adler32.h \ mathematics.h \ md5.h \ mem.h \ - dict.h \ - old_pix_fmts.h \ opt.h \ parseutils.h \ pixdesc.h \ pixfmt.h \ random_seed.h \ - replaygain.h \ rational.h \ + replaygain.h \ samplefmt.h \ sha.h \ stereo3d.h \ @@ -70,6 +74,7 @@ OBJS = adler32.o \ cpu.o \ crc.o \ des.o \ + dict.o \ display.o \ downmix_info.o \ error.o \ @@ -80,6 +85,7 @@ OBJS = adler32.o \ float_dsp.o \ frame.o \ hmac.o \ + hwcontext.o \ imgutils.o \ intmath.o \ lfg.o \ @@ -89,7 +95,6 @@ OBJS = adler32.o \ mathematics.o \ md5.o \ mem.o \ - dict.o \ opt.o \ parseutils.o \ pixdesc.o \ @@ -104,12 +109,20 @@ OBJS = adler32.o \ utils.o \ xtea.o \ +OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o +OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o +OBJS-$(CONFIG_LIBMFX) += hwcontext_qsv.o OBJS-$(CONFIG_LZO) += lzo.o +OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o +OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o OBJS += $(COMPAT_OBJS:%=../compat/%) -SKIPHEADERS = old_pix_fmts.h - +SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda.h +SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h +SKIPHEADERS-$(CONFIG_LIBMFX) += hwcontext_qsv.h +SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h +SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h SKIPHEADERS-$(HAVE_ATOMICS_GCC) += atomic_gcc.h SKIPHEADERS-$(HAVE_ATOMICS_SUNCC) += atomic_suncc.h SKIPHEADERS-$(HAVE_ATOMICS_WIN32) += atomic_win32.h diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index b766e67..6a7f506 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -52,12 +52,18 @@ FUNC .func \name .endif .endm -.macro const name, align=2 +.macro const name, align=2, relocate=0 .macro endconst ELF .size \name, . - \name .purgem endconst .endm -#ifndef __MACH__ +#if HAVE_SECTION_DATA_REL_RO +.if \relocate + .section .data.rel.ro +.else + .section .rodata +.endif +#elif !defined(__MACH__) .section .rodata #else .const_data diff --git a/libavutil/aarch64/timer.h b/libavutil/aarch64/timer.h new file mode 100644 index 0000000..382cfd9 --- /dev/null +++ b/libavutil/aarch64/timer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AARCH64_TIMER_H +#define AVUTIL_AARCH64_TIMER_H + +#include +#include "config.h" + +#if HAVE_INLINE_ASM + +#define AV_READ_TIME read_time + +static inline uint64_t read_time(void) +{ + uint64_t cycle_counter; + __asm__ volatile( + "isb \t\n" + "mrs %0, pmccntr_el0 " + : "=r"(cycle_counter) :: "memory" ); + + return cycle_counter; +} + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVUTIL_AARCH64_TIMER_H */ diff --git a/libavutil/adler32.c b/libavutil/adler32.c index 8a8065c..8dfe2ce 100644 --- a/libavutil/adler32.c +++ b/libavutil/adler32.c @@ -63,36 +63,3 @@ unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf, } return (s2 << 16) | s1; } - -#ifdef TEST -#include -#include "log.h" -#include "timer.h" -#define LEN 7001 - -static volatile int checksum; - -int main(int argc, char **argv) -{ - int i; - char data[LEN]; - - av_log_set_level(AV_LOG_DEBUG); - - for (i = 0; i < LEN; i++) - data[i] = ((i * i) >> 3) + 123 * i; - - if (argc > 1 && !strcmp(argv[1], "-t")) { - for (i = 0; i < 1000; i++) { - START_TIMER; - checksum = av_adler32_update(1, data, LEN); - STOP_TIMER("adler"); - } - } else { - checksum = av_adler32_update(1, data, LEN); - } - - av_log(NULL, AV_LOG_DEBUG, "%X (expected 50E6E508)\n", checksum); - return checksum == 0x50e6e508 ? 0 : 1; -} -#endif diff --git a/libavutil/aes.c b/libavutil/aes.c index 3ba5e9a..e93fb05 100644 --- a/libavutil/aes.c +++ b/libavutil/aes.c @@ -21,9 +21,9 @@ */ #include "common.h" -#include "aes.h" #include "intreadwrite.h" #include "timer.h" +#include "aes.h" typedef union { uint64_t u64[2]; @@ -40,17 +40,13 @@ typedef struct AVAES { int rounds; } AVAES; -#if FF_API_CONTEXT_SIZE -const int av_aes_size= sizeof(AVAES); -#endif - struct AVAES *av_aes_alloc(void) { return av_mallocz(sizeof(struct AVAES)); } static const uint8_t rcon[10] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; static uint8_t sbox[256]; @@ -113,7 +109,8 @@ static void subshift(av_aes_block s0[2], int s, const uint8_t *box) s3[0].u8[ 5] = box[s3[1].u8[ 1]]; } -static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d){ +static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d) +{ #if CONFIG_SMALL return multbl[0][a] ^ ROT(multbl[0][b], 8) ^ ROT(multbl[0][c], 16) ^ ROT(multbl[0][d], 24); #else @@ -121,12 +118,13 @@ static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d){ #endif } -static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3){ +static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3) +{ uint8_t (*src)[4] = state[1].u8x4; - state[0].u32[0] = mix_core(multbl, src[0][0], src[s1 ][1], src[2][2], src[s3 ][3]); - state[0].u32[1] = mix_core(multbl, src[1][0], src[s3-1][1], src[3][2], src[s1-1][3]); - state[0].u32[2] = mix_core(multbl, src[2][0], src[s3 ][1], src[0][2], src[s1 ][3]); - state[0].u32[3] = mix_core(multbl, src[3][0], src[s1-1][1], src[1][2], src[s3-1][3]); + state[0].u32[0] = mix_core(multbl, src[0][0], src[s1 ][1], src[2][2], src[s3 ][3]); + state[0].u32[1] = mix_core(multbl, src[1][0], src[s3 - 1][1], src[3][2], src[s1 - 1][3]); + state[0].u32[2] = mix_core(multbl, src[2][0], src[s3 ][1], src[0][2], src[s1 ][3]); + state[0].u32[3] = mix_core(multbl, src[3][0], src[s1 - 1][1], src[1][2], src[s3 - 1][3]); } static inline void crypt(AVAES *a, int s, const uint8_t *sbox, @@ -182,7 +180,7 @@ static void init_multbl2(uint32_t tbl[][256], const int c[4], l = alog8[x + log8[c[1]]]; m = alog8[x + log8[c[2]]]; n = alog8[x + log8[c[3]]]; - tbl[0][i] = AV_NE(MKBETAG(k,l,m,n), MKTAG(k,l,m,n)); + tbl[0][i] = AV_NE(MKBETAG(k, l, m, n), MKTAG(k, l, m, n)); #if !CONFIG_SMALL tbl[1][i] = ROT(tbl[0][i], 8); tbl[2][i] = ROT(tbl[0][i], 16); @@ -202,7 +200,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) uint8_t log8[256]; uint8_t alog8[512]; - if (!enc_multbl[FF_ARRAY_ELEMS(enc_multbl)-1][FF_ARRAY_ELEMS(enc_multbl[0])-1]) { + if (!enc_multbl[FF_ARRAY_ELEMS(enc_multbl) - 1][FF_ARRAY_ELEMS(enc_multbl[0]) - 1]) { j = 1; for (i = 0; i < 255; i++) { alog8[i] = alog8[i + 255] = j; @@ -216,7 +214,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) j ^= (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4); j = (j ^ (j >> 8) ^ 99) & 255; inv_sbox[j] = i; - sbox[i] = j; + sbox[i] = j; } init_multbl2(dec_multbl, (const int[4]) { 0xe, 0x9, 0xd, 0xb }, log8, alog8, inv_sbox); @@ -258,85 +256,9 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) a->round_key[i] = tmp[0]; } } else { - for (i = 0; i < (rounds + 1) >> 1; i++) { - FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds-i]); - } + for (i = 0; i < (rounds + 1) >> 1; i++) + FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds - i]); } return 0; } - -#ifdef TEST -#include -#include "lfg.h" -#include "log.h" - -int main(int argc, char **argv) -{ - int i, j; - AVAES b; - uint8_t rkey[2][16] = { - { 0 }, - { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, - 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 } - }; - uint8_t pt[16], rpt[2][16]= { - { 0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad, - 0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3 }, - { 0 } - }; - uint8_t rct[2][16]= { - { 0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7, - 0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf }, - { 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, - 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65 } - }; - uint8_t temp[16]; - int err = 0; - - av_log_set_level(AV_LOG_DEBUG); - - for (i = 0; i < 2; i++) { - av_aes_init(&b, rkey[i], 128, 1); - av_aes_crypt(&b, temp, rct[i], 1, NULL, 1); - for (j = 0; j < 16; j++) { - if (rpt[i][j] != temp[j]) { - av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n", - j, rpt[i][j], temp[j]); - err = 1; - } - } - } - - if (argc > 1 && !strcmp(argv[1], "-t")) { - AVAES ae, ad; - AVLFG prng; - - av_aes_init(&ae, "PI=3.141592654..", 128, 0); - av_aes_init(&ad, "PI=3.141592654..", 128, 1); - av_lfg_init(&prng, 1); - - for (i = 0; i < 10000; i++) { - for (j = 0; j < 16; j++) { - pt[j] = av_lfg_get(&prng); - } - { - START_TIMER; - av_aes_crypt(&ae, temp, pt, 1, NULL, 0); - if (!(i & (i - 1))) - av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n", - temp[0], temp[5], temp[10], temp[15]); - av_aes_crypt(&ad, temp, temp, 1, NULL, 1); - STOP_TIMER("aes"); - } - for (j = 0; j < 16; j++) { - if (pt[j] != temp[j]) { - av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n", - i, j, pt[j], temp[j]); - } - } - } - } - return err; -} -#endif diff --git a/libavutil/aes.h b/libavutil/aes.h index edff275..5b45124 100644 --- a/libavutil/aes.h +++ b/libavutil/aes.h @@ -32,10 +32,6 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_aes_size; -#endif - struct AVAES; /** diff --git a/libavutil/arm/asm.S b/libavutil/arm/asm.S index 61c8b1b..1a048b5 100644 --- a/libavutil/arm/asm.S +++ b/libavutil/arm/asm.S @@ -40,6 +40,12 @@ # define FUNC @ #endif +#if HAVE_AS_FPU_DIRECTIVE +# define FPU +#else +# define FPU @ +#endif + #if HAVE_NEON .arch armv7-a #elif HAVE_ARMV6T2 @@ -54,11 +60,11 @@ ELF .object_arch armv4 #endif #if HAVE_NEON - .fpu neon +FPU .fpu neon ELF .eabi_attribute 10, 0 @ suppress Tag_FP_arch ELF .eabi_attribute 12, 0 @ suppress Tag_Advanced_SIMD_arch #elif HAVE_VFP - .fpu vfp +FPU .fpu vfp ELF .eabi_attribute 10, 0 @ suppress Tag_FP_arch #endif @@ -95,12 +101,16 @@ FUNC .func \name .endif .endm -.macro const name, align=2 +.macro const name, align=2, relocate=0 .macro endconst ELF .size \name, . - \name .purgem endconst .endm +.if HAVE_SECTION_DATA_REL_RO && \relocate + .section .data.rel.ro +.else .section .rodata +.endif .align \align \name: .endm diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c index 8bdaa88..2effb72 100644 --- a/libavutil/arm/cpu.c +++ b/libavutil/arm/cpu.c @@ -131,6 +131,10 @@ int ff_get_cpu_flags_arm(void) if (flags & AV_CPU_FLAG_ARMV6T2) flags |= AV_CPU_FLAG_ARMV6; + /* set the virtual VFPv2 vector mode flag */ + if ((flags & AV_CPU_FLAG_VFP) && !(flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))) + flags |= AV_CPU_FLAG_VFP_VM; + return flags; } diff --git a/libavutil/arm/cpu.h b/libavutil/arm/cpu.h index 224409a..127993e 100644 --- a/libavutil/arm/cpu.h +++ b/libavutil/arm/cpu.h @@ -30,6 +30,11 @@ #define have_vfpv3(flags) CPUEXT(flags, VFPV3) #define have_neon(flags) CPUEXT(flags, NEON) +/* some functions use the VFPv2 vector mode which is deprecated in ARMv7-A + * and might trap on such CPU depending on the OS configuration */ +#define have_vfp_vm(flags) \ + (HAVE_VFP && ((flags) & AV_CPU_FLAG_VFP_VM)) + /* Some functions use the 'setend' instruction which is deprecated on ARMv8 * and serializing on some ARMv7 cores. This macro ensures such functions * are only enabled on ARMv6. */ diff --git a/libavutil/arm/intmath.h b/libavutil/arm/intmath.h index 56fcdb3..2b15ba0 100644 --- a/libavutil/arm/intmath.h +++ b/libavutil/arm/intmath.h @@ -62,6 +62,14 @@ static av_always_inline av_const int av_clip_int16_arm(int a) return x; } +#define av_clip_intp2 av_clip_intp2_arm +static av_always_inline av_const int av_clip_intp2_arm(int a, int p) +{ + unsigned x; + __asm__ ("ssat %0, %2, %1" : "=r"(x) : "r"(a), "i"(p+1)); + return x; +} + #define av_clip_uintp2 av_clip_uintp2_arm static av_always_inline av_const unsigned av_clip_uintp2_arm(int a, int p) { diff --git a/libavutil/atomic.c b/libavutil/atomic.c index 8374039..e175a9f 100644 --- a/libavutil/atomic.c +++ b/libavutil/atomic.c @@ -107,21 +107,3 @@ void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval) #endif /* HAVE_PTHREADS */ #endif /* !HAVE_ATOMICS_NATIVE */ - -#ifdef TEST -#include - -int main(void) -{ - volatile int val = 1; - int res; - - res = avpriv_atomic_int_add_and_fetch(&val, 1); - assert(res == 2); - avpriv_atomic_int_set(&val, 3); - res = avpriv_atomic_int_get(&val); - assert(res == 3); - - return 0; -} -#endif diff --git a/libavutil/atomic_suncc.h b/libavutil/atomic_suncc.h index 5c11b57..b78c377 100644 --- a/libavutil/atomic_suncc.h +++ b/libavutil/atomic_suncc.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or diff --git a/libavutil/attributes.h b/libavutil/attributes.h index d7f2bb5..c770f52 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -80,7 +80,7 @@ # define attribute_deprecated #endif -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) # define av_unused __attribute__((unused)) #else # define av_unused @@ -91,7 +91,7 @@ * away. This is useful for variables accessed only from inline * assembler without the compiler being aware. */ -#if AV_GCC_VERSION_AT_LEAST(3,1) +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) # define av_used __attribute__((used)) #else # define av_used diff --git a/libavutil/audioconvert.h b/libavutil/audioconvert.h deleted file mode 100644 index 300a67c..0000000 --- a/libavutil/audioconvert.h +++ /dev/null @@ -1,6 +0,0 @@ - -#include "version.h" - -#if FF_API_AUDIOCONVERT -#include "channel_layout.h" -#endif diff --git a/libavutil/avassert.h b/libavutil/avassert.h index b223d26..e57b2ae 100644 --- a/libavutil/avassert.h +++ b/libavutil/avassert.h @@ -45,7 +45,7 @@ /** * assert() equivalent, that does not lie in speed critical code. - * These asserts() thus can be enabled without fearing speedloss. + * These asserts() thus can be enabled without fearing speed loss. */ #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0 #define av_assert1(cond) av_assert0(cond) diff --git a/libavutil/avr32/intreadwrite.h b/libavutil/avr32/intreadwrite.h index e0049fe..23a7d9f 100644 --- a/libavutil/avr32/intreadwrite.h +++ b/libavutil/avr32/intreadwrite.h @@ -27,7 +27,7 @@ /* * AVR32 does not support unaligned memory accesses, except for the AP - * series which suppports unaligned 32-bit loads and stores. 16-bit + * series which supports unaligned 32-bit loads and stores. 16-bit * and 64-bit accesses must be aligned to 16 and 32 bits, respectively. * This means we cannot use the byte-swapping load/store instructions * here. diff --git a/libavutil/avstring.c b/libavutil/avstring.c index eb5c95a..bc7d0bc 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -212,28 +212,6 @@ const char *av_dirname(char *path) return path; } -int av_isdigit(int c) -{ - return c >= '0' && c <= '9'; -} - -int av_isgraph(int c) -{ - return c > 32 && c < 127; -} - -int av_isspace(int c) -{ - return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || - c == '\v'; -} - -int av_isxdigit(int c) -{ - c = av_tolower(c); - return av_isdigit(c) || (c >= 'a' && c <= 'f'); -} - int av_match_name(const char *name, const char *names) { const char *p; @@ -251,55 +229,3 @@ int av_match_name(const char *name, const char *names) } return !av_strcasecmp(name, names); } - - - -#ifdef TEST - -int main(void) -{ - int i; - const char *strings[] = { - "''", - "", - ":", - "\\", - "'", - " '' :", - " '' '' :", - "foo '' :", - "'foo'", - "foo ", - " ' foo ' ", - "foo\\", - "foo': blah:blah", - "foo\\: blah:blah", - "foo\'", - "'foo : ' :blahblah", - "\\ :blah", - " foo", - " foo ", - " foo \\ ", - "foo ':blah", - " foo bar : blahblah", - "\\f\\o\\o", - "'foo : \\ \\ ' : blahblah", - "'\\fo\\o:': blahblah", - "\\'fo\\o\\:': foo ' :blahblah" - }; - - printf("Testing av_get_token()\n"); - for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) { - const char *p = strings[i]; - char *q; - printf("|%s|", p); - q = av_get_token(&p, ":"); - printf(" -> |%s|", q); - printf(" + |%s|\n", p); - av_free(q); - } - - return 0; -} - -#endif /* TEST */ diff --git a/libavutil/avstring.h b/libavutil/avstring.h index 9a18ddd..780f109 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -154,22 +154,32 @@ char *av_get_token(const char **buf, const char *term); /** * Locale-independent conversion of ASCII isdigit. */ -int av_isdigit(int c); +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} /** * Locale-independent conversion of ASCII isgraph. */ -int av_isgraph(int c); +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} /** * Locale-independent conversion of ASCII isspace. */ -int av_isspace(int c); +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} /** * Locale-independent conversion of ASCII characters to uppercase. */ -static inline int av_toupper(int c) +static inline av_const int av_toupper(int c) { if (c >= 'a' && c <= 'z') c ^= 0x20; @@ -179,7 +189,7 @@ static inline int av_toupper(int c) /** * Locale-independent conversion of ASCII characters to lowercase. */ -static inline int av_tolower(int c) +static inline av_const int av_tolower(int c) { if (c >= 'A' && c <= 'Z') c ^= 0x20; @@ -189,7 +199,11 @@ static inline int av_tolower(int c) /** * Locale-independent conversion of ASCII isxdigit. */ -int av_isxdigit(int c); +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} /* * Locale-independent case-insensitive compare. diff --git a/libavutil/avutil.h b/libavutil/avutil.h index f056415..c49685a 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -164,6 +164,13 @@ unsigned avutil_version(void); /** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** * Return the libavutil build-time configuration. */ const char *avutil_configuration(void); @@ -253,7 +260,7 @@ enum AVPictureType { AV_PICTURE_TYPE_I = 1, ///< Intra AV_PICTURE_TYPE_P, ///< Predicted AV_PICTURE_TYPE_B, ///< Bi-dir predicted - AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG4 + AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4 AV_PICTURE_TYPE_SI, ///< Switching Intra AV_PICTURE_TYPE_SP, ///< Switching Predicted AV_PICTURE_TYPE_BI, ///< BI type diff --git a/libavutil/base64.c b/libavutil/base64.c index 725b035..29677a6 100644 --- a/libavutil/base64.c +++ b/libavutil/base64.c @@ -98,68 +98,3 @@ char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size) return ret; } - -#ifdef TEST - -#define MAX_DATA_SIZE 1024 -#define MAX_ENCODED_SIZE 2048 - -static int test_encode_decode(const uint8_t *data, unsigned int data_size, - const char *encoded_ref) -{ - char encoded[MAX_ENCODED_SIZE]; - uint8_t data2[MAX_DATA_SIZE]; - int data2_size, max_data2_size = MAX_DATA_SIZE; - - if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) { - printf("Failed: cannot encode the input data\n"); - return 1; - } - if (encoded_ref && strcmp(encoded, encoded_ref)) { - printf("Failed: encoded string differs from reference\n" - "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref); - return 1; - } - - if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) { - printf("Failed: cannot decode the encoded string\n" - "Encoded:\n%s\n", encoded); - return 1; - } - if (memcmp(data2, data, data_size)) { - printf("Failed: encoded/decoded data differs from original data\n"); - return 1; - } - - printf("Passed!\n"); - return 0; -} - -int main(void) -{ - int i, error_count = 0; - struct test { - const uint8_t *data; - const char *encoded_ref; - } tests[] = { - { "", ""}, - { "1", "MQ=="}, - { "22", "MjI="}, - { "333", "MzMz"}, - { "4444", "NDQ0NA=="}, - { "55555", "NTU1NTU="}, - { "666666", "NjY2NjY2"}, - { "abc:def", "YWJjOmRlZg=="}, - }; - - printf("Encoding/decoding tests\n"); - for (i = 0; i < FF_ARRAY_ELEMS(tests); i++) - error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref); - - if (error_count) - printf("Error Count: %d.\n", error_count); - - return !!error_count; -} - -#endif diff --git a/libavutil/blowfish.c b/libavutil/blowfish.c index 8437dd6..8731576 100644 --- a/libavutil/blowfish.c +++ b/libavutil/blowfish.c @@ -24,8 +24,18 @@ #include "avutil.h" #include "common.h" #include "intreadwrite.h" +#include "mem.h" #include "blowfish.h" +#if !FF_API_CRYPTO_CONTEXT +#define AV_BF_ROUNDS 16 + +struct AVBlowfish { + uint32_t p[AV_BF_ROUNDS + 2]; + uint32_t s[4][256]; +}; +#endif + static const uint32_t orig_p[AV_BF_ROUNDS + 2] = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, @@ -312,6 +322,11 @@ static void F(AVBlowfish *ctx, uint32_t *xl, uint32_t *xr, int i) *xr = Xl; } +AVBlowfish *av_blowfish_alloc(void) +{ + return av_mallocz(sizeof(struct AVBlowfish)); +} + av_cold void av_blowfish_init(AVBlowfish *ctx, const uint8_t *key, int key_len) { uint32_t data, data_l, data_r; @@ -424,173 +439,3 @@ void av_blowfish_crypt(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src, } } } - -#ifdef TEST -#include - -#define NUM_VARIABLE_KEY_TESTS 34 - -/* plaintext bytes -- left halves */ -static const uint32_t plaintext_l[NUM_VARIABLE_KEY_TESTS] = { - 0x00000000, 0xFFFFFFFF, 0x10000000, 0x11111111, 0x11111111, - 0x01234567, 0x00000000, 0x01234567, 0x01A1D6D0, 0x5CD54CA8, - 0x0248D438, 0x51454B58, 0x42FD4430, 0x059B5E08, 0x0756D8E0, - 0x762514B8, 0x3BDD1190, 0x26955F68, 0x164D5E40, 0x6B056E18, - 0x004BD6EF, 0x480D3900, 0x437540C8, 0x072D43A0, 0x02FE5577, - 0x1D9D5C50, 0x30553228, 0x01234567, 0x01234567, 0x01234567, - 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF -}; - -/* plaintext bytes -- right halves */ -static const uint32_t plaintext_r[NUM_VARIABLE_KEY_TESTS] = { - 0x00000000, 0xFFFFFFFF, 0x00000001, 0x11111111, 0x11111111, - 0x89ABCDEF, 0x00000000, 0x89ABCDEF, 0x39776742, 0x3DEF57DA, - 0x06F67172, 0x2DDF440A, 0x59577FA2, 0x51CF143A, 0x774761D2, - 0x29BF486A, 0x49372802, 0x35AF609A, 0x4F275232, 0x759F5CCA, - 0x09176062, 0x6EE762F2, 0x698F3CFA, 0x77075292, 0x8117F12A, - 0x18F728C2, 0x6D6F295A, 0x89ABCDEF, 0x89ABCDEF, 0x89ABCDEF, - 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF -}; - -/* key bytes for variable key tests */ -static const uint8_t variable_key[NUM_VARIABLE_KEY_TESTS][8] = { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 }, - { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E }, - { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 }, - { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E }, - { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 }, - { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE }, - { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 }, - { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE }, - { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 }, - { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F }, - { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 }, - { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E }, - { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 }, - { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 }, - { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F }, - { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 }, - { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF }, - { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 }, - { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, - { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } -}; - -/* ciphertext bytes -- left halves */ -static const uint32_t ciphertext_l[NUM_VARIABLE_KEY_TESTS] = { - 0x4EF99745, 0x51866FD5, 0x7D856F9A, 0x2466DD87, 0x61F9C380, - 0x7D0CC630, 0x4EF99745, 0x0ACEAB0F, 0x59C68245, 0xB1B8CC0B, - 0x1730E577, 0xA25E7856, 0x353882B1, 0x48F4D088, 0x432193B7, - 0x13F04154, 0x2EEDDA93, 0xD887E039, 0x5F99D04F, 0x4A057A3B, - 0x452031C1, 0x7555AE39, 0x53C55F9C, 0x7A8E7BFA, 0xCF9C5D7A, - 0xD1ABB290, 0x55CB3774, 0xFA34EC48, 0xA7907951, 0xC39E072D, - 0x014933E0, 0xF21E9A77, 0x24594688, 0x6B5C5A9C -}; - -/* ciphertext bytes -- right halves */ -static const uint32_t ciphertext_r[NUM_VARIABLE_KEY_TESTS] = { - 0x6198DD78, 0xB85ECB8A, 0x613063F2, 0x8B963C9D, 0x2281B096, - 0xAFDA1EC7, 0x6198DD78, 0xC6A0A28D, 0xEB05282B, 0x250F09A0, - 0x8BEA1DA4, 0xCF2651EB, 0x09CE8F1A, 0x4C379918, 0x8951FC98, - 0xD69D1AE5, 0xFFD39C79, 0x3C2DA6E3, 0x5B163969, 0x24D3977B, - 0xE4FADA8E, 0xF59B87BD, 0xB49FC019, 0x937E89A3, 0x4986ADB5, - 0x658BC778, 0xD13EF201, 0x47B268B2, 0x08EA3CAE, 0x9FAC631D, - 0xCDAFF6E4, 0xB71C49BC, 0x5754369A, 0x5D9E0A5A -}; - -/* plaintext bytes */ -static const uint8_t plaintext[8] = "BLOWFISH"; - -static const uint8_t plaintext2[16] = "BLOWFISHBLOWFISH"; - -/* ciphertext bytes */ -static const uint8_t ciphertext[8] = { - 0x32, 0x4E, 0xD0, 0xFE, 0xF4, 0x13, 0xA2, 0x03 -}; - -static const uint8_t ciphertext2[16] = { - 0x53, 0x00, 0x40, 0x06, 0x63, 0xf2, 0x1d, 0x99, - 0x3b, 0x9b, 0x27, 0x64, 0x46, 0xfd, 0x20, 0xc1, -}; - -#define IV "blowfish" - -static void test_blowfish(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src, - const uint8_t *ref, int len, uint8_t *iv, int dir, - const char *test) -{ - av_blowfish_crypt(ctx, dst, src, len, iv, dir); - if (memcmp(dst, ref, 8*len)) { - int i; - printf("%s failed\ngot ", test); - for (i = 0; i < 8*len; i++) - printf("%02x ", dst[i]); - printf("\nexpected "); - for (i = 0; i < 8*len; i++) - printf("%02x ", ref[i]); - printf("\n"); - exit(1); - } -} - -int main(void) -{ - AVBlowfish ctx; - uint32_t tmptext_l[NUM_VARIABLE_KEY_TESTS]; - uint32_t tmptext_r[NUM_VARIABLE_KEY_TESTS]; - uint8_t tmp[16], iv[8]; - int i; - - av_blowfish_init(&ctx, "abcdefghijklmnopqrstuvwxyz", 26); - - test_blowfish(&ctx, tmp, plaintext, ciphertext, 1, NULL, 0, "encryption"); - test_blowfish(&ctx, tmp, ciphertext, plaintext, 1, NULL, 1, "decryption"); - test_blowfish(&ctx, tmp, tmp, ciphertext, 1, NULL, 0, "Inplace encryption"); - test_blowfish(&ctx, tmp, tmp, plaintext, 1, NULL, 1, "Inplace decryption"); - memcpy(iv, IV, 8); - test_blowfish(&ctx, tmp, plaintext2, ciphertext2, 2, iv, 0, "CBC encryption"); - memcpy(iv, IV, 8); - test_blowfish(&ctx, tmp, ciphertext2, plaintext2, 2, iv, 1, "CBC decryption"); - memcpy(iv, IV, 8); - test_blowfish(&ctx, tmp, tmp, ciphertext2, 2, iv, 0, "Inplace CBC encryption"); - memcpy(iv, IV, 8); - test_blowfish(&ctx, tmp, tmp, plaintext2, 2, iv, 1, "Inplace CBC decryption"); - - memcpy(tmptext_l, plaintext_l, sizeof(*plaintext_l) * NUM_VARIABLE_KEY_TESTS); - memcpy(tmptext_r, plaintext_r, sizeof(*plaintext_r) * NUM_VARIABLE_KEY_TESTS); - - for (i = 0; i < NUM_VARIABLE_KEY_TESTS; i++) { - av_blowfish_init(&ctx, variable_key[i], 8); - - av_blowfish_crypt_ecb(&ctx, &tmptext_l[i], &tmptext_r[i], 0); - if (tmptext_l[i] != ciphertext_l[i] || tmptext_r[i] != ciphertext_r[i]) { - printf("Test encryption failed.\n"); - return 1; - } - - av_blowfish_crypt_ecb(&ctx, &tmptext_l[i], &tmptext_r[i], 1); - if (tmptext_l[i] != plaintext_l[i] || tmptext_r[i] != plaintext_r[i]) { - printf("Test decryption failed.\n"); - return 1; - } - } - printf("Test encryption/decryption success.\n"); - - return 0; -} - -#endif diff --git a/libavutil/blowfish.h b/libavutil/blowfish.h index 8c29536..4f86bf7 100644 --- a/libavutil/blowfish.h +++ b/libavutil/blowfish.h @@ -22,6 +22,7 @@ #define AVUTIL_BLOWFISH_H #include +#include "version.h" /** * @defgroup lavu_blowfish Blowfish @@ -29,12 +30,21 @@ * @{ */ +#if FF_API_CRYPTO_CONTEXT #define AV_BF_ROUNDS 16 typedef struct AVBlowfish { uint32_t p[AV_BF_ROUNDS + 2]; uint32_t s[4][256]; } AVBlowfish; +#else +typedef struct AVBlowfish AVBlowfish; +#endif + +/** + * Allocate an AVBlowfish context. + */ +AVBlowfish *av_blowfish_alloc(void); /** * Initialize an AVBlowfish context. diff --git a/libavutil/buffer.c b/libavutil/buffer.c index 1bc4a93..49a1f2d 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -170,7 +170,7 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) return 0; if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) || - !av_buffer_is_writable(buf)) { + !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) { /* cannot realloc, allocate a new reallocable buffer and copy data */ AVBufferRef *new = NULL; @@ -194,6 +194,26 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) return 0; } +AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), + void (*pool_free)(void *opaque)) +{ + AVBufferPool *pool = av_mallocz(sizeof(*pool)); + if (!pool) + return NULL; + + ff_mutex_init(&pool->mutex, NULL); + + pool->size = size; + pool->opaque = opaque; + pool->alloc2 = alloc; + pool->pool_free = pool_free; + + avpriv_atomic_int_set(&pool->refcount, 1); + + return pool; +} + AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) { AVBufferPool *pool = av_mallocz(sizeof(*pool)); @@ -224,6 +244,10 @@ static void buffer_pool_free(AVBufferPool *pool) av_freep(&buf); } ff_mutex_destroy(&pool->mutex); + + if (pool->pool_free) + pool->pool_free(pool->opaque); + av_freep(&pool); } @@ -261,7 +285,8 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) BufferPoolEntry *buf; AVBufferRef *ret; - ret = pool->alloc(pool->size); + ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) : + pool->alloc(pool->size); if (!ret) return NULL; diff --git a/libavutil/buffer.h b/libavutil/buffer.h index 56b4d02..58def6f 100644 --- a/libavutil/buffer.h +++ b/libavutil/buffer.h @@ -242,13 +242,30 @@ typedef struct AVBufferPool AVBufferPool; AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); /** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), + void (*pool_free)(void *opaque)); + +/** * Mark the pool as being available for freeing. It will actually be freed only * once all the allocated buffers associated with the pool are released. Thus it * is safe to call this function while some of the allocated buffers are still * in use. * * @param pool pointer to the pool to be freed. It will be set to NULL. - * @see av_buffer_pool_can_uninit() */ void av_buffer_pool_uninit(AVBufferPool **pool); diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h index 1032a54..64344d8 100644 --- a/libavutil/buffer_internal.h +++ b/libavutil/buffer_internal.h @@ -88,7 +88,10 @@ struct AVBufferPool { volatile int refcount; int size; + void *opaque; AVBufferRef* (*alloc)(int size); + AVBufferRef* (*alloc2)(void *opaque, int size); + void (*pool_free)(void *opaque); }; #endif /* AVUTIL_BUFFER_INTERNAL_H */ diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c index 253c495..41340ec 100644 --- a/libavutil/channel_layout.c +++ b/libavutil/channel_layout.c @@ -97,6 +97,7 @@ static const struct { { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE }, { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK }, { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL }, + { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL }, { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, }, { 0 } }; @@ -193,6 +194,7 @@ uint64_t av_get_default_channel_layout(int nb_channels) case 6: return AV_CH_LAYOUT_5POINT1; case 7: return AV_CH_LAYOUT_6POINT1; case 8: return AV_CH_LAYOUT_7POINT1; + case 16: return AV_CH_LAYOUT_HEXADECAGONAL; default: return 0; } } diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h index 6a1f830..5bd0c2c 100644 --- a/libavutil/channel_layout.h +++ b/libavutil/channel_layout.h @@ -100,6 +100,7 @@ #define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) #define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) #define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) #define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) enum AVMatrixEncoding { diff --git a/libavutil/colorspace.h b/libavutil/colorspace.h index 8757566..cc27f38 100644 --- a/libavutil/colorspace.h +++ b/libavutil/colorspace.h @@ -41,6 +41,17 @@ b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\ } +#define YUV_TO_RGB1_CCIR_BT709(cb1, cr1) \ + { \ + cb = (cb1) - 128; \ + cr = (cr1) - 128; \ + r_add = ONE_HALF + FIX(1.5747 * 255.0 / 224.0) * cr; \ + g_add = ONE_HALF - FIX(0.1873 * 255.0 / 224.0) * cb - \ + FIX(0.4682 * 255.0 / 224.0) * cr; \ + b_add = ONE_HALF + FIX(1.8556 * 255.0 / 224.0) * cb; \ + } + +// To be used for the BT709 variant as well #define YUV_TO_RGB2_CCIR(r, g, b, y1)\ {\ y = ((y1) - 16) * FIX(255.0/219.0);\ diff --git a/libavutil/common.h b/libavutil/common.h index eb40e12..d2ddcba 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -36,6 +36,7 @@ #include #include "attributes.h" +#include "macros.h" #include "version.h" #include "libavutil/avconfig.h" @@ -49,6 +50,14 @@ #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)) + +/** + * Fast a / (1 << b) rounded toward +inf, assuming a >= 0 and b >= 0. + */ +#define AV_CEIL_RSHIFT(a, b) \ + (av_builtin_constant_p(b) ? ((a) + (1 << (b)) - 1) >> (b) \ + : -((-(a)) >> (b))) + #define FFABS(a) ((a) >= 0 ? (a) : (-(a))) #define FFSIGN(a) ((a) > 0 ? 1 : -1) @@ -59,14 +68,9 @@ #define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) #define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) /* misc math functions */ -#if FF_API_AV_REVERSE -extern attribute_deprecated const uint8_t av_reverse[256]; -#endif - #ifdef HAVE_AV_CONFIG_H # include "config.h" # include "intmath.h" @@ -153,6 +157,20 @@ static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) } /** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if ((a + (1 << p)) & ~((1 << (p + 1)) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** * Clip a signed integer to an unsigned power of two range. * @param a value to clip * @param p bit position to clip at @@ -386,6 +404,9 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) #ifndef av_clipl_int32 # define av_clipl_int32 av_clipl_int32_c #endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif #ifndef av_clip_uintp2 # define av_clip_uintp2 av_clip_uintp2_c #endif diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 354d21e..7d7390a 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -86,12 +86,12 @@ int av_parse_cpu_flags(const char *s) #define CPUFLAG_SSE4 (AV_CPU_FLAG_SSE4 | CPUFLAG_SSSE3) #define CPUFLAG_SSE42 (AV_CPU_FLAG_SSE42 | CPUFLAG_SSE4) #define CPUFLAG_AVX (AV_CPU_FLAG_AVX | CPUFLAG_SSE42) +#define CPUFLAG_AVXSLOW (AV_CPU_FLAG_AVXSLOW | CPUFLAG_AVX) #define CPUFLAG_XOP (AV_CPU_FLAG_XOP | CPUFLAG_AVX) #define CPUFLAG_FMA3 (AV_CPU_FLAG_FMA3 | CPUFLAG_AVX) #define CPUFLAG_FMA4 (AV_CPU_FLAG_FMA4 | CPUFLAG_AVX) #define CPUFLAG_AVX2 (AV_CPU_FLAG_AVX2 | CPUFLAG_AVX) -#define CPUFLAG_BMI1 (AV_CPU_FLAG_BMI1) -#define CPUFLAG_BMI2 (AV_CPU_FLAG_BMI2 | CPUFLAG_BMI1) +#define CPUFLAG_BMI2 (AV_CPU_FLAG_BMI2 | AV_CPU_FLAG_BMI1) static const AVOption cpuflags_opts[] = { { "flags" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, #if ARCH_PPC @@ -109,11 +109,12 @@ int av_parse_cpu_flags(const char *s) { "sse4.1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE4 }, .unit = "flags" }, { "sse4.2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE42 }, .unit = "flags" }, { "avx" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX }, .unit = "flags" }, + { "avxslow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVXSLOW }, .unit = "flags" }, { "xop" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_XOP }, .unit = "flags" }, { "fma3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_FMA3 }, .unit = "flags" }, { "fma4" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_FMA4 }, .unit = "flags" }, { "avx2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX2 }, .unit = "flags" }, - { "bmi1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_BMI1 }, .unit = "flags" }, + { "bmi1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_BMI1 }, .unit = "flags" }, { "bmi2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_BMI2 }, .unit = "flags" }, { "3dnow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_3DNOW }, .unit = "flags" }, { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_3DNOWEXT }, .unit = "flags" }, @@ -123,6 +124,7 @@ int av_parse_cpu_flags(const char *s) { "armv6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6 }, .unit = "flags" }, { "armv6t2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6T2 }, .unit = "flags" }, { "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" }, + { "vfp_vm", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP_VM }, .unit = "flags" }, { "vfpv3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFPV3 }, .unit = "flags" }, { "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" }, #elif ARCH_AARCH64 @@ -176,120 +178,3 @@ int av_cpu_count(void) return nb_cpus; } - -#ifdef TEST - -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "avstring.h" - -#if !HAVE_GETOPT -#include "compat/getopt.c" -#endif - -static const struct { - int flag; - const char *name; -} cpu_flag_tab[] = { -#if ARCH_AARCH64 - { AV_CPU_FLAG_ARMV8, "armv8" }, - { AV_CPU_FLAG_NEON, "neon" }, - { AV_CPU_FLAG_VFP, "vfp" }, -#elif ARCH_ARM - { AV_CPU_FLAG_ARMV5TE, "armv5te" }, - { AV_CPU_FLAG_ARMV6, "armv6" }, - { AV_CPU_FLAG_ARMV6T2, "armv6t2" }, - { AV_CPU_FLAG_VFP, "vfp" }, - { AV_CPU_FLAG_VFPV3, "vfpv3" }, - { AV_CPU_FLAG_NEON, "neon" }, -#elif ARCH_PPC - { AV_CPU_FLAG_ALTIVEC, "altivec" }, -#elif ARCH_X86 - { AV_CPU_FLAG_MMX, "mmx" }, - { AV_CPU_FLAG_MMXEXT, "mmxext" }, - { AV_CPU_FLAG_SSE, "sse" }, - { AV_CPU_FLAG_SSE2, "sse2" }, - { AV_CPU_FLAG_SSE2SLOW, "sse2(slow)" }, - { AV_CPU_FLAG_SSE3, "sse3" }, - { AV_CPU_FLAG_SSE3SLOW, "sse3(slow)" }, - { AV_CPU_FLAG_SSSE3, "ssse3" }, - { AV_CPU_FLAG_ATOM, "atom" }, - { AV_CPU_FLAG_SSE4, "sse4.1" }, - { AV_CPU_FLAG_SSE42, "sse4.2" }, - { AV_CPU_FLAG_AVX, "avx" }, - { AV_CPU_FLAG_XOP, "xop" }, - { AV_CPU_FLAG_FMA3, "fma3" }, - { AV_CPU_FLAG_FMA4, "fma4" }, - { AV_CPU_FLAG_3DNOW, "3dnow" }, - { AV_CPU_FLAG_3DNOWEXT, "3dnowext" }, - { AV_CPU_FLAG_CMOV, "cmov" }, - { AV_CPU_FLAG_AVX2, "avx2" }, - { AV_CPU_FLAG_BMI1, "bmi1" }, - { AV_CPU_FLAG_BMI2, "bmi2" }, -#endif - { 0 } -}; - -static void print_cpu_flags(int cpu_flags, const char *type) -{ - int i; - - fprintf(stderr, "cpu_flags(%s) = 0x%08X\n", type, cpu_flags); - fprintf(stderr, "cpu_flags_str(%s) =", type); - for (i = 0; cpu_flag_tab[i].flag; i++) - if (cpu_flags & cpu_flag_tab[i].flag) - fprintf(stderr, " %s", cpu_flag_tab[i].name); - fprintf(stderr, "\n"); -} - - -int main(int argc, char **argv) -{ - int cpu_flags_raw = av_get_cpu_flags(); - int cpu_flags_eff; - int cpu_count = av_cpu_count(); - char threads[5] = "auto"; - - if (cpu_flags_raw < 0) - return 1; - - for (;;) { - int c = getopt(argc, argv, "c:t:"); - if (c == -1) - break; - switch (c) { - case 'c': - { - int cpuflags = av_parse_cpu_flags(optarg); - if (cpuflags < 0) - return 2; - av_set_cpu_flags_mask(cpuflags); - break; - } - case 't': - { - int len = av_strlcpy(threads, optarg, sizeof(threads)); - if (len >= sizeof(threads)) { - fprintf(stderr, "Invalid thread count '%s'\n", optarg); - return 2; - } - } - } - } - - cpu_flags_eff = av_get_cpu_flags(); - - if (cpu_flags_eff < 0) - return 3; - - print_cpu_flags(cpu_flags_raw, "raw"); - print_cpu_flags(cpu_flags_eff, "effective"); - fprintf(stderr, "threads = %s (cpu_count = %d)\n", threads, cpu_count); - - return 0; -} - -#endif diff --git a/libavutil/cpu.h b/libavutil/cpu.h index 7cecccc..deff4cc 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -28,9 +28,6 @@ /* lower 16 bits - CPU features */ #define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX #define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext -#if FF_API_CPU_FLAG_MMX2 -#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext -#endif #define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW #define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions #define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions @@ -41,10 +38,12 @@ #define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster ///< than regular MMX/SSE (e.g. Core1) #define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions +#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster #define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower #define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions #define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions #define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer) #define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions #define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions #define AV_CPU_FLAG_CMOV 0x1000 ///< i686 cmov @@ -54,6 +53,8 @@ #define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2 #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard +#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 +#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07 #define AV_CPU_FLAG_ARMV5TE (1 << 0) #define AV_CPU_FLAG_ARMV6 (1 << 1) @@ -62,6 +63,7 @@ #define AV_CPU_FLAG_VFPV3 (1 << 4) #define AV_CPU_FLAG_NEON (1 << 5) #define AV_CPU_FLAG_ARMV8 (1 << 6) +#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations /** * Return the flags which specify extensions supported by the CPU. diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 3bfe8a8..49c7b07 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -24,7 +24,17 @@ #define CPUEXT_SUFFIX(flags, suffix, cpuext) \ (HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext)) +#define CPUEXT_SUFFIX_FAST(flags, suffix, cpuext) \ + (HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \ + !((flags) & AV_CPU_FLAG_ ## cpuext ## SLOW)) + +#define CPUEXT_SUFFIX_SLOW(flags, suffix, cpuext) \ + (HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \ + ((flags) & AV_CPU_FLAG_ ## cpuext ## SLOW)) + #define CPUEXT(flags, cpuext) CPUEXT_SUFFIX(flags, , cpuext) +#define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext) +#define CPUEXT_SLOW(flags, cpuext) CPUEXT_SUFFIX_SLOW(flags, , cpuext) int ff_get_cpu_flags_aarch64(void); int ff_get_cpu_flags_arm(void); diff --git a/libavutil/crc.c b/libavutil/crc.c index eb22e33..5428f8c 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -19,8 +19,9 @@ */ #include "config.h" -#include "common.h" + #include "bswap.h" +#include "common.h" #include "crc.h" #if CONFIG_HARDCODED_TABLES @@ -287,7 +288,7 @@ int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) 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 + 1) + i] = (ctx[256 * j + i] >> 8) ^ ctx[ctx[256 * j + i] & 0xFF]; #endif @@ -332,27 +333,3 @@ uint32_t av_crc(const AVCRC *ctx, uint32_t crc, return crc; } - -#ifdef TEST -int main(void) -{ - uint8_t buf[1999]; - int i; - int p[5][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, - { AV_CRC_32_IEEE , 0x04C11DB7, 0xC0F5BAE0 }, - { AV_CRC_16_ANSI_LE, 0xA001 , 0xBFD8 }, - { AV_CRC_16_ANSI , 0x8005 , 0x1FBB }, - { AV_CRC_8_ATM , 0x07 , 0xE3 } - }; - const AVCRC *ctx; - - for (i = 0; i < sizeof(buf); i++) - buf[i] = i + i * i; - - for (i = 0; i < 5; i++) { - ctx = av_crc_get_table(p[i][0]); - printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf))); - } - return 0; -} -#endif diff --git a/libavutil/des.c b/libavutil/des.c index ab0fc2f..75a5d89 100644 --- a/libavutil/des.c +++ b/libavutil/des.c @@ -18,15 +18,23 @@ * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include + +#include + #include "avutil.h" #include "common.h" #include "intreadwrite.h" +#include "mem.h" #include "des.h" -typedef struct AVDES AVDES; +#if !FF_API_CRYPTO_CONTEXT +struct AVDES { + uint64_t round_keys[3][16]; + int triple_des; +}; +#endif -#define T(a, b, c, d, e, f, g, h) 64-a,64-b,64-c,64-d,64-e,64-f,64-g,64-h +#define T(a, b, c, d, e, f, g, h) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g, 64 - h static const uint8_t IP_shuffle[] = { T(58, 50, 42, 34, 26, 18, 10, 2), T(60, 52, 44, 36, 28, 20, 12, 4), @@ -40,7 +48,7 @@ static const uint8_t IP_shuffle[] = { #undef T #if CONFIG_SMALL || defined(GENTABLES) -#define T(a, b, c, d) 32-a,32-b,32-c,32-d +#define T(a, b, c, d) 32 - a, 32 - b, 32 - c, 32 - d static const uint8_t P_shuffle[] = { T(16, 7, 20, 21), T(29, 12, 28, 17), @@ -54,7 +62,7 @@ static const uint8_t P_shuffle[] = { #undef T #endif -#define T(a, b, c, d, e, f, g) 64-a,64-b,64-c,64-d,64-e,64-f,64-g +#define T(a, b, c, d, e, f, g) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g static const uint8_t PC1_shuffle[] = { T(57, 49, 41, 33, 25, 17, 9), T( 1, 58, 50, 42, 34, 26, 18), @@ -67,7 +75,7 @@ static const uint8_t PC1_shuffle[] = { }; #undef T -#define T(a, b, c, d, e, f) 56-a,56-b,56-c,56-d,56-e,56-f +#define T(a, b, c, d, e, f) 56 - a, 56 - b, 56 - c, 56 - d, 56 - e, 56 - f static const uint8_t PC2_shuffle[] = { T(14, 17, 11, 24, 1, 5), T( 3, 28, 15, 6, 21, 10), @@ -82,122 +90,99 @@ static const uint8_t PC2_shuffle[] = { #if CONFIG_SMALL static const uint8_t S_boxes[8][32] = { - { - 0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87, - 0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0, - }, { - 0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a, - 0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f, - }, { - 0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18, - 0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7, - }, { - 0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f, - 0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4, - }, { - 0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69, - 0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e, - }, { - 0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b, - 0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6, - }, { - 0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61, - 0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2, - }, { - 0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27, - 0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8, + { 0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87, + 0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0, }, + { 0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a, + 0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f, }, + { 0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18, + 0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7, }, + { 0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f, + 0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4, }, + { 0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69, + 0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e, }, + { 0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b, + 0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6, }, + { 0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61, + 0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2, }, + { 0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27, + 0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8, } }; #else /** * This table contains the results of applying both the S-box and P-shuffle. - * It can be regenerated by compiling this file with -DCONFIG_SMALL -DTEST -DGENTABLES + * It can be regenerated by compiling tests/des.c with "-DCONFIG_SMALL -DGENTABLES". */ static const uint32_t S_boxes_P_shuffle[8][64] = { - { - 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, - }, - { - 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, - }, - { - 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, - }, - { - 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, - }, - { - 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, - }, - { - 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, - }, - { - 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, - }, - { - 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800, - }, + { 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, + 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, + 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, + 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, + 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, + 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, }, + { 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, + 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, + 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, + 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, + 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, + 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, }, + { 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, + 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, + 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, + 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, + 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, + 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, }, + { 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, + 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, + 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, + 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, + 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, + 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, }, + { 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, + 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, + 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, + 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, + 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, + 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, }, + { 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, + 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, + 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, + 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, + 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, + 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, }, + { 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, + 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, + 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, + 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, + 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, + 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, }, + { 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, + 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, + 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, + 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, + 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, + 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800, }, }; #endif -static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) { +static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) +{ int i; uint64_t res = 0; for (i = 0; i < shuffle_len; i++) @@ -205,7 +190,8 @@ static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) { return res; } -static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) { +static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) +{ int i; uint64_t res = 0; shuffle += shuffle_len - 1; @@ -216,7 +202,8 @@ static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len return res; } -static uint32_t f_func(uint32_t r, uint64_t k) { +static uint32_t f_func(uint32_t r, uint64_t k) +{ int i; uint32_t out = 0; // rotate to get first part of E-shuffle in the lowest 6 bits @@ -226,13 +213,14 @@ static uint32_t f_func(uint32_t r, uint64_t k) { uint8_t tmp = (r ^ k) & 0x3f; #if CONFIG_SMALL uint8_t v = S_boxes[i][tmp >> 1]; - if (tmp & 1) v >>= 4; + if (tmp & 1) + v >>= 4; out = (out >> 4) | (v << 28); #else out |= S_boxes_P_shuffle[i][tmp]; #endif // get next 6 bits of E-shuffle and round key k into the lowest bits - r = (r >> 4) | (r << 28); + r = (r >> 4) | (r << 28); k >>= 6; } #if CONFIG_SMALL @@ -247,15 +235,17 @@ static uint32_t f_func(uint32_t r, uint64_t k) { * Note: the specification calls this "shift", so I kept it although * it is confusing. */ -static uint64_t key_shift_left(uint64_t CDn) { +static uint64_t key_shift_left(uint64_t CDn) +{ uint64_t carries = (CDn >> 27) & 0x10000001; CDn <<= 1; - CDn &= ~0x10000001; - CDn |= carries; + CDn &= ~0x10000001; + CDn |= carries; return CDn; } -static void gen_roundkeys(uint64_t K[16], uint64_t key) { +static void gen_roundkeys(uint64_t K[16], uint64_t key) +{ int i; // discard parity bits from key and shuffle it into C and D parts uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle)); @@ -268,7 +258,8 @@ static void gen_roundkeys(uint64_t K[16], uint64_t key) { } } -static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) { +static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) +{ int i; // used to apply round keys in reverse order for decryption decrypt = decrypt ? 15 : 0; @@ -277,8 +268,8 @@ static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) { for (i = 0; i < 16; i++) { uint32_t f_res; f_res = f_func(in, K[decrypt ^ i]); - in = (in << 32) | (in >> 32); - in ^= f_res; + in = (in << 32) | (in >> 32); + in ^= f_res; } in = (in << 32) | (in >> 32); // reverse shuffle used to ease hardware implementations @@ -286,7 +277,13 @@ static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) { return in; } -int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) { +AVDES *av_des_alloc(void) +{ + return av_mallocz(sizeof(struct AVDES)); +} + +int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) +{ if (key_bits != 64 && key_bits != 192) return -1; d->triple_des = key_bits > 64; @@ -298,7 +295,9 @@ int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) { return 0; } -static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt, int mac) { +static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt, int mac) +{ uint64_t iv_val = iv ? AV_RB64(iv) : 0; while (count-- > 0) { uint64_t dst_val; @@ -310,7 +309,7 @@ static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int cou src_val = des_encdec(src_val, d->round_keys[1], 0); } dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val; - iv_val = iv ? tmp : 0; + iv_val = iv ? tmp : 0; } else { dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0); if (d->triple_des) { @@ -328,116 +327,13 @@ static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int cou AV_WB64(iv, iv_val); } -void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) { +void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt) +{ av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0); } -void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) { - av_des_crypt_mac(d, dst, src, count, (uint8_t[8]){0}, 0, 1); -} - -#ifdef TEST -#include -#include - -#include "time.h" - -static uint64_t rand64(void) { - uint64_t r = rand(); - r = (r << 32) | rand(); - return r; -} - -static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; -static const DECLARE_ALIGNED(8, uint8_t, plain)[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; -static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18}; -static DECLARE_ALIGNED(8, uint8_t, tmp)[8]; -static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8]; -static const uint8_t cbc_key[] = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, - 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 -}; - -static int run_test(int cbc, int decrypt) { - AVDES d; - int delay = cbc && !decrypt ? 2 : 1; - uint64_t res; - AV_WB64(large_buffer[0], 0x4e6f772069732074ULL); - AV_WB64(large_buffer[1], 0x1234567890abcdefULL); - AV_WB64(tmp, 0x1234567890abcdefULL); - av_des_init(&d, cbc_key, 192, decrypt); - av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt); - res = AV_RB64(large_buffer[9999 + delay]); - if (cbc) { - if (decrypt) - return res == 0xc5cecf63ecec514cULL; - else - return res == 0xcb191f85d1ed8439ULL; - } else { - if (decrypt) - return res == 0x8325397644091a0aULL; - else - return res == 0xdd17e8b8b437d232ULL; - } +void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) +{ + av_des_crypt_mac(d, dst, src, count, (uint8_t[8]) { 0 }, 0, 1); } - -int main(void) { - AVDES d; - int i; -#ifdef GENTABLES - int j; -#endif - uint64_t key[3]; - uint64_t data; - uint64_t ct; - uint64_t roundkeys[16]; - srand(av_gettime()); - key[0] = AV_RB64(test_key); - data = AV_RB64(plain); - gen_roundkeys(roundkeys, key[0]); - if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) { - printf("Test 1 failed\n"); - return 1; - } - av_des_init(&d, test_key, 64, 0); - av_des_crypt(&d, tmp, plain, 1, NULL, 0); - if (memcmp(tmp, crypt, sizeof(crypt))) { - printf("Public API decryption failed\n"); - return 1; - } - if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) { - printf("Partial Monte-Carlo test failed\n"); - return 1; - } - for (i = 0; i < 1000; i++) { - key[0] = rand64(); key[1] = rand64(); key[2] = rand64(); - data = rand64(); - av_des_init(&d, key, 192, 0); - av_des_crypt(&d, &ct, &data, 1, NULL, 0); - av_des_init(&d, key, 192, 1); - av_des_crypt(&d, &ct, &ct, 1, NULL, 1); - if (ct != data) { - printf("Test 2 failed\n"); - return 1; - } - } -#ifdef GENTABLES - printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n"); - for (i = 0; i < 8; i++) { - printf(" {"); - for (j = 0; j < 64; j++) { - uint32_t v = S_boxes[i][j >> 1]; - v = j & 1 ? v >> 4 : v & 0xf; - v <<= 28 - 4 * i; - v = shuffle(v, P_shuffle, sizeof(P_shuffle)); - printf((j & 7) == 0 ? "\n " : " "); - printf("0x%08X,", v); - } - printf("\n },\n"); - } - printf("};\n"); -#endif - return 0; -} -#endif diff --git a/libavutil/des.h b/libavutil/des.h index cda9812..1470d35 100644 --- a/libavutil/des.h +++ b/libavutil/des.h @@ -23,17 +23,34 @@ #define AVUTIL_DES_H #include +#include "version.h" -struct AVDES { +/** + * @defgroup lavu_des DES + * @ingroup lavu_crypto + * @{ + */ + +#if FF_API_CRYPTO_CONTEXT +typedef struct AVDES { uint64_t round_keys[3][16]; int triple_des; -}; +} AVDES; +#else +typedef struct AVDES AVDES; +#endif + +/** + * Allocate an AVDES context. + */ +AVDES *av_des_alloc(void); /** * @brief Initializes an AVDES context. * * @param key_bits must be 64 or 192 * @param decrypt 0 for encryption/CBC-MAC, 1 for decryption + * @return zero on success, negative value otherwise */ int av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt); @@ -58,4 +75,8 @@ void av_des_crypt(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count, */ void av_des_mac(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count); +/** + * @} + */ + #endif /* AVUTIL_DES_H */ diff --git a/libavutil/dict.c b/libavutil/dict.c index e4ea776..7213bf2 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -71,9 +71,12 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, AVDictionary *m = *pm; AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags); char *oldval = NULL; + int allocated = !!m; if (!m) m = *pm = av_mallocz(sizeof(*m)); + if (!m) + return AVERROR(ENOMEM); if (tag) { if (flags & AV_DICT_DONT_OVERWRITE) { @@ -88,12 +91,14 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, av_free(tag->key); *tag = m->elems[--m->count]; } else { - AVDictionaryEntry *tmp = av_realloc(m->elems, - (m->count + 1) * sizeof(*m->elems)); - if (tmp) - m->elems = tmp; - else - return AVERROR(ENOMEM); + int ret = av_reallocp_array(&m->elems, + m->count + 1, sizeof(*m->elems)); + if (ret < 0) { + if (allocated) + av_freep(pm); + + return ret; + } } if (value) { if (flags & AV_DICT_DONT_STRDUP_KEY) @@ -181,10 +186,15 @@ void av_dict_free(AVDictionary **pm) av_freep(pm); } -void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags) +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags) { AVDictionaryEntry *t = NULL; - while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) - av_dict_set(dst, t->key, t->value, flags); + while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) { + int ret = av_dict_set(dst, t->key, t->value, flags); + if (ret < 0) + return ret; + } + + return 0; } diff --git a/libavutil/dict.h b/libavutil/dict.h index e4aee27..3593e3a 100644 --- a/libavutil/dict.h +++ b/libavutil/dict.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -55,7 +54,6 @@ } av_dict_free(&d); @endcode - * */ #define AV_DICT_MATCH_CASE 1 @@ -63,7 +61,7 @@ #define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been allocated with av_malloc() and children. */ #define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been - allocated with av_malloc() and chilren. */ + allocated with av_malloc() and children. */ #define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. #define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no delimiter is added, the strings are simply concatenated. */ @@ -130,8 +128,10 @@ int av_dict_parse_string(AVDictionary **pm, const char *str, * @param src pointer to source AVDictionary struct * @param flags flags to use when setting entries in *dst * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. */ -void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); /** * Free all the memory allocated for an AVDictionary struct diff --git a/libavutil/display.c b/libavutil/display.c index 74aceb2..f750094 100644 --- a/libavutil/display.c +++ b/libavutil/display.c @@ -46,12 +46,12 @@ double av_display_rotation_get(const int32_t matrix[9]) rotation = atan2(CONV_FP(matrix[1]) / scale[1], CONV_FP(matrix[0]) / scale[0]) * 180 / M_PI; - return rotation; + return -rotation; } void av_display_rotation_set(int32_t matrix[9], double angle) { - double radians = angle * M_PI / 180.0f; + double radians = -angle * M_PI / 180.0f; double c = cos(radians); double s = sin(radians); diff --git a/libavutil/display.h b/libavutil/display.h index 7e37627..dba3b1e 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -55,9 +55,9 @@ * Extract the rotation component of the transformation matrix. * * @param matrix the transformation matrix - * @return the angle (in degrees) by which the transformation rotates the frame. - * The angle will be in range [-180.0, 180.0], or NaN if the matrix is - * singular. + * @return the angle (in degrees) by which the transformation rotates the frame + * counterclockwise. The angle will be in range [-180.0, 180.0], + * or NaN if the matrix is singular. * * @note floating point numbers are inherently inexact, so callers are * recommended to round the return value to nearest integer before use. @@ -65,8 +65,8 @@ double av_display_rotation_get(const int32_t matrix[9]); /** - * Initialize a transformation matrix describing a pure rotation by the - * specified angle (in degrees). + * Initialize a transformation matrix describing a pure counterclockwise + * rotation by the specified angle (in degrees). * * @param matrix an allocated transformation matrix (will be fully overwritten * by this function) diff --git a/libavutil/eval.c b/libavutil/eval.c index 31e9ebb..b5d71c6 100644 --- a/libavutil/eval.c +++ b/libavutil/eval.c @@ -565,127 +565,3 @@ int av_expr_parse_and_eval(double *d, const char *s, av_expr_free(e); return isnan(*d) ? AVERROR(EINVAL) : 0; } - -#ifdef TEST -#include - -static const double const_values[] = { - M_PI, - M_E, - 0 -}; - -static const char *const const_names[] = { - "PI", - "E", - 0 -}; - -int main(int argc, char **argv) -{ - int i; - double d; - const char *const *expr; - static const char *const exprs[] = { - "", - "1;2", - "-20", - "-PI", - "+PI", - "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", - "80G/80Gi", - "1k", - "1Gi", - "1gi", - "1GiFoo", - "1k+1k", - "1Gi*3foo", - "foo", - "foo(", - "foo()", - "foo)", - "sin", - "sin(", - "sin()", - "sin)", - "sin 10", - "sin(1,2,3)", - "sin(1 )", - "1", - "1foo", - "bar + PI + E + 100f*2 + foo", - "13k + 12f - foo(1, 2)", - "1gi", - "1Gi", - "st(0, 123)", - "st(1, 123); ld(1)", - "lte(0, 1)", - "lte(1, 1)", - "lte(1, 0)", - "lt(0, 1)", - "lt(1, 1)", - "gt(1, 0)", - "gt(2, 7)", - "gte(122, 122)", - /* compute 1+2+...+N */ - "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)", - /* compute Fib(N) */ - "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)", - "while(0, 10)", - "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))", - "isnan(1)", - "isnan(NAN)", - "isnan(INF)", - "isinf(1)", - "isinf(NAN)", - "isinf(INF)", - "floor(NAN)", - "floor(123.123)", - "floor(-123.123)", - "trunc(123.123)", - "trunc(-123.123)", - "ceil(123.123)", - "ceil(-123.123)", - "sqrt(1764)", - "isnan(sqrt(-1))", - "not(1)", - "not(NAN)", - "not(0)", - "6.0206dB", - "-3.0103dB", - NULL - }; - - for (expr = exprs; *expr; expr++) { - printf("Evaluating '%s'\n", *expr); - av_expr_parse_and_eval(&d, *expr, - const_names, const_values, - NULL, NULL, NULL, NULL, NULL, 0, NULL); - if (isnan(d)) - printf("'%s' -> nan\n\n", *expr); - else - printf("'%s' -> %f\n\n", *expr, d); - } - - av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", - const_names, const_values, - NULL, NULL, NULL, NULL, NULL, 0, NULL); - printf("%f == 12.7\n", d); - av_expr_parse_and_eval(&d, "80G/80Gi", - const_names, const_values, - NULL, NULL, NULL, NULL, NULL, 0, NULL); - printf("%f == 0.931322575\n", d); - - if (argc > 1 && !strcmp(argv[1], "-t")) { - for (i = 0; i < 1050; i++) { - START_TIMER; - av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", - const_names, const_values, - NULL, NULL, NULL, NULL, NULL, 0, NULL); - STOP_TIMER("av_expr_parse_and_eval"); - } - } - - return 0; -} -#endif diff --git a/libavutil/fifo.c b/libavutil/fifo.c index dffaf54..a42899c 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -131,37 +131,3 @@ void av_fifo_drain(AVFifoBuffer *f, int size) f->rptr -= f->end - f->buffer; f->rndx += size; } - -#ifdef TEST - -int main(void) -{ - /* create a FIFO buffer */ - AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int)); - int i, j, n; - - /* fill data */ - for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) - av_fifo_generic_write(fifo, &i, sizeof(int), NULL); - - /* peek at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); - for (i = -n + 1; i < n; i++) { - int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int)); - printf("%d: %d\n", i, *v); - } - printf("\n"); - - /* read data */ - for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { - av_fifo_generic_read(fifo, &j, sizeof(int), NULL); - printf("%d ", j); - } - printf("\n"); - - av_fifo_free(fifo); - - return 0; -} - -#endif diff --git a/libavutil/file.c b/libavutil/file.c index d2765b8..18a110a 100644 --- a/libavutil/file.c +++ b/libavutil/file.c @@ -35,7 +35,7 @@ #include #endif -typedef struct { +typedef struct FileLogContext { const AVClass *class; int log_offset; void *log_ctx; diff --git a/libavutil/file_open.c b/libavutil/file_open.c index 765eb60..f14ea70 100644 --- a/libavutil/file_open.c +++ b/libavutil/file_open.c @@ -37,23 +37,18 @@ #include #include #include +#include "wchar_filename.h" static int win32_open(const char *filename_utf8, int oflag, int pmode) { int fd; - int num_chars; wchar_t *filename_w; /* convert UTF-8 to wide chars */ - num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); - if (num_chars <= 0) - goto fallback; - filename_w = av_mallocz(sizeof(wchar_t) * num_chars); - if (!filename_w) { - errno = ENOMEM; + if (utf8towchar(filename_utf8, &filename_w)) return -1; - } - MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, filename_w, num_chars); + if (!filename_w) + goto fallback; fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode); av_freep(&filename_w); diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c index aabc800..d31fc3d 100644 --- a/libavutil/float_dsp.c +++ b/libavutil/float_dsp.c @@ -133,288 +133,3 @@ av_cold void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact) if (ARCH_X86) ff_float_dsp_init_x86(fdsp); } - -#ifdef TEST - -#include -#include -#include -#include -#include - -#include "common.h" -#include "cpu.h" -#include "internal.h" -#include "lfg.h" -#include "log.h" -#include "mem.h" -#include "random_seed.h" - -#define LEN 240 - -static void fill_float_array(AVLFG *lfg, float *a, int len) -{ - int i; - double bmg[2], stddev = 10.0, mean = 0.0; - - for (i = 0; i < len; i += 2) { - av_bmg_get(lfg, bmg); - a[i] = bmg[0] * stddev + mean; - a[i + 1] = bmg[1] * stddev + mean; - } -} -static int compare_floats(const float *a, const float *b, int len, - float max_diff) -{ - int i; - for (i = 0; i < len; i++) { - if (fabsf(a[i] - b[i]) > max_diff) { - av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n", - i, a[i], b[i], a[i] - b[i]); - return -1; - } - } - return 0; -} - -static void fill_double_array(AVLFG *lfg, double *a, int len) -{ - int i; - double bmg[2], stddev = 10.0, mean = 0.0; - - for (i = 0; i < len; i += 2) { - av_bmg_get(lfg, bmg); - a[i] = bmg[0] * stddev + mean; - a[i + 1] = bmg[1] * stddev + mean; - } -} - -static int compare_doubles(const double *a, const double *b, int len, - double max_diff) -{ - int i; - - for (i = 0; i < len; i++) { - if (fabs(a[i] - b[i]) > max_diff) { - av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n", - i, a[i], b[i], a[i] - b[i]); - return -1; - } - } - return 0; -} - -static int test_vector_fmul(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - cdsp->vector_fmul(cdst, v1, v2, LEN); - fdsp->vector_fmul(odst, v1, v2, LEN); - - if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) - av_log(NULL, AV_LOG_ERROR, "vector_fmul failed\n"); - - return ret; -} - -#define ARBITRARY_FMAC_SCALAR_CONST 0.005 -static int test_vector_fmac_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *src0, float scale) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - memcpy(cdst, v1, LEN * sizeof(*v1)); - memcpy(odst, v1, LEN * sizeof(*v1)); - - cdsp->vector_fmac_scalar(cdst, src0, scale, LEN); - fdsp->vector_fmac_scalar(odst, src0, scale, LEN); - - if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMAC_SCALAR_CONST)) - av_log(NULL, AV_LOG_ERROR, "vector_fmac_scalar failed\n"); - - return ret; -} - -static int test_vector_fmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, float scale) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - cdsp->vector_fmul_scalar(cdst, v1, scale, LEN); - fdsp->vector_fmul_scalar(odst, v1, scale, LEN); - - if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) - av_log(NULL, AV_LOG_ERROR, "vector_fmul_scalar failed\n"); - - return ret; -} - -static int test_vector_dmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const double *v1, double scale) -{ - LOCAL_ALIGNED(32, double, cdst, [LEN]); - LOCAL_ALIGNED(32, double, odst, [LEN]); - int ret; - - cdsp->vector_dmul_scalar(cdst, v1, scale, LEN); - fdsp->vector_dmul_scalar(odst, v1, scale, LEN); - - if (ret = compare_doubles(cdst, odst, LEN, DBL_EPSILON)) - av_log(NULL, AV_LOG_ERROR, "vector_dmul_scalar failed\n"); - - return ret; -} - -#define ARBITRARY_FMUL_WINDOW_CONST 0.008 -static int test_vector_fmul_window(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2, const float *v3) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - cdsp->vector_fmul_window(cdst, v1, v2, v3, LEN / 2); - fdsp->vector_fmul_window(odst, v1, v2, v3, LEN / 2); - - if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_WINDOW_CONST)) - av_log(NULL, AV_LOG_ERROR, "vector_fmul_window failed\n"); - - return ret; -} - -#define ARBITRARY_FMUL_ADD_CONST 0.005 -static int test_vector_fmul_add(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2, const float *v3) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - cdsp->vector_fmul_add(cdst, v1, v2, v3, LEN); - fdsp->vector_fmul_add(odst, v1, v2, v3, LEN); - - if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_ADD_CONST)) - av_log(NULL, AV_LOG_ERROR, "vector_fmul_add failed\n"); - - return ret; -} - -static int test_vector_fmul_reverse(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2) -{ - LOCAL_ALIGNED(32, float, cdst, [LEN]); - LOCAL_ALIGNED(32, float, odst, [LEN]); - int ret; - - cdsp->vector_fmul_reverse(cdst, v1, v2, LEN); - fdsp->vector_fmul_reverse(odst, v1, v2, LEN); - - if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) - av_log(NULL, AV_LOG_ERROR, "vector_fmul_reverse failed\n"); - - return ret; -} - -static int test_butterflies_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2) -{ - LOCAL_ALIGNED(32, float, cv1, [LEN]); - LOCAL_ALIGNED(32, float, cv2, [LEN]); - LOCAL_ALIGNED(32, float, ov1, [LEN]); - LOCAL_ALIGNED(32, float, ov2, [LEN]); - int ret; - - memcpy(cv1, v1, LEN * sizeof(*v1)); - memcpy(cv2, v2, LEN * sizeof(*v2)); - memcpy(ov1, v1, LEN * sizeof(*v1)); - memcpy(ov2, v2, LEN * sizeof(*v2)); - - cdsp->butterflies_float(cv1, cv2, LEN); - fdsp->butterflies_float(ov1, ov2, LEN); - - if ((ret = compare_floats(cv1, ov1, LEN, FLT_EPSILON)) || - (ret = compare_floats(cv2, ov2, LEN, FLT_EPSILON))) - av_log(NULL, AV_LOG_ERROR, "butterflies_float failed\n"); - - return ret; -} - -#define ARBITRARY_SCALARPRODUCT_CONST 0.2 -static int test_scalarproduct_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, - const float *v1, const float *v2) -{ - float cprod, oprod; - int ret; - - cprod = cdsp->scalarproduct_float(v1, v2, LEN); - oprod = fdsp->scalarproduct_float(v1, v2, LEN); - - if (ret = compare_floats(&cprod, &oprod, 1, ARBITRARY_SCALARPRODUCT_CONST)) - av_log(NULL, AV_LOG_ERROR, "scalarproduct_float failed\n"); - - return ret; -} - -int main(int argc, char **argv) -{ - int ret = 0; - uint32_t seed; - AVFloatDSPContext fdsp, cdsp; - AVLFG lfg; - - LOCAL_ALIGNED(32, float, src0, [LEN]); - LOCAL_ALIGNED(32, float, src1, [LEN]); - LOCAL_ALIGNED(32, float, src2, [LEN]); - LOCAL_ALIGNED(32, double, dbl_src0, [LEN]); - LOCAL_ALIGNED(32, double, dbl_src1, [LEN]); - - if (argc > 2 && !strcmp(argv[1], "-s")) - seed = strtoul(argv[2], NULL, 10); - else - seed = av_get_random_seed(); - - av_log(NULL, AV_LOG_INFO, "float_dsp-test: random seed %u\n", seed); - - av_lfg_init(&lfg, seed); - - fill_float_array(&lfg, src0, LEN); - fill_float_array(&lfg, src1, LEN); - fill_float_array(&lfg, src2, LEN); - - fill_double_array(&lfg, dbl_src0, LEN); - fill_double_array(&lfg, dbl_src1, LEN); - - avpriv_float_dsp_init(&fdsp, 1); - av_set_cpu_flags_mask(0); - avpriv_float_dsp_init(&cdsp, 1); - - if (test_vector_fmul(&fdsp, &cdsp, src0, src1)) - ret -= 1 << 0; - if (test_vector_fmac_scalar(&fdsp, &cdsp, src2, src0, src1[0])) - ret -= 1 << 1; - if (test_vector_fmul_scalar(&fdsp, &cdsp, src0, src1[0])) - ret -= 1 << 2; - if (test_vector_fmul_window(&fdsp, &cdsp, src0, src1, src2)) - ret -= 1 << 3; - if (test_vector_fmul_add(&fdsp, &cdsp, src0, src1, src2)) - ret -= 1 << 4; - if (test_vector_fmul_reverse(&fdsp, &cdsp, src0, src1)) - ret -= 1 << 5; - if (test_butterflies_float(&fdsp, &cdsp, src0, src1)) - ret -= 1 << 6; - if (test_scalarproduct_float(&fdsp, &cdsp, src0, src1)) - ret -= 1 << 7; - if (test_vector_dmul_scalar(&fdsp, &cdsp, dbl_src0, dbl_src1[0])) - ret -= 1 << 8; - - return ret; -} - -#endif /* TEST */ diff --git a/libavutil/frame.c b/libavutil/frame.c index 48df311..1c14f5f 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -54,6 +53,18 @@ static void free_side_data(AVFrameSideData **ptr_sd) av_freep(ptr_sd); } +static void wipe_side_data(AVFrame *frame) +{ + int i; + + for (i = 0; i < frame->nb_side_data; i++) { + free_side_data(&frame->side_data[i]); + } + frame->nb_side_data = 0; + + av_freep(&frame->side_data); +} + AVFrame *av_frame_alloc(void) { AVFrame *frame = av_mallocz(sizeof(*frame)); @@ -99,7 +110,7 @@ static int get_video_buffer(AVFrame *frame, int align) for (i = 0; i < 4 && frame->linesize[i]; i++) { int h = frame->height; if (i == 1 || i == 2) - h = -((-h) >> desc->log2_chroma_h); + h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h); if (!frame->buf[i]) @@ -239,6 +250,14 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) } } + if (src->hw_frames_ctx) { + dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); + if (!dst->hw_frames_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + /* duplicate extended data */ if (src->extended_data != src->data) { int ch = av_get_channel_layout_nb_channels(src->channel_layout); @@ -284,16 +303,16 @@ void av_frame_unref(AVFrame *frame) { int i; - for (i = 0; i < frame->nb_side_data; i++) { - free_side_data(&frame->side_data[i]); - } - av_freep(&frame->side_data); + wipe_side_data(frame); for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) av_buffer_unref(&frame->buf[i]); for (i = 0; i < frame->nb_extended_buf; i++) av_buffer_unref(&frame->extended_buf[i]); av_freep(&frame->extended_buf); + + av_buffer_unref(&frame->hw_frames_ctx); + get_frame_defaults(frame); } @@ -378,7 +397,11 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) dst->palette_has_changed = src->palette_has_changed; dst->sample_rate = src->sample_rate; dst->opaque = src->opaque; +#if FF_API_PKT_PTS +FF_DISABLE_DEPRECATION_WARNINGS dst->pkt_pts = src->pkt_pts; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->pkt_dts = src->pkt_dts; dst->reordered_opaque = src->reordered_opaque; dst->quality = src->quality; @@ -391,17 +414,18 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) dst->color_range = src->color_range; dst->chroma_location = src->chroma_location; +#if FF_API_ERROR_FRAME +FF_DISABLE_DEPRECATION_WARNINGS memcpy(dst->error, src->error, sizeof(dst->error)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif for (i = 0; i < src->nb_side_data; i++) { const AVFrameSideData *sd_src = src->side_data[i]; AVFrameSideData *sd_dst = av_frame_new_side_data(dst, sd_src->type, sd_src->size); if (!sd_dst) { - for (i = 0; i < dst->nb_side_data; i++) { - free_side_data(&dst->side_data[i]); - } - av_freep(&dst->side_data); + wipe_side_data(dst); return AVERROR(ENOMEM); } memcpy(sd_dst->data, sd_src->data, sd_src->size); diff --git a/libavutil/frame.h b/libavutil/frame.h index d3360c4..12624d7 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -87,6 +86,12 @@ enum AVFrameSideDataType { * in ETSI TS 101 154 using enum AVActiveFormatDescription. */ AV_FRAME_DATA_AFD, + + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, }; enum AVActiveFormatDescription { @@ -195,11 +200,6 @@ typedef struct AVFrame { */ enum AVPictureType pict_type; -#if FF_API_AVFRAME_LAVC - attribute_deprecated - uint8_t *base[AV_NUM_DATA_POINTERS]; -#endif - /** * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. */ @@ -210,10 +210,14 @@ typedef struct AVFrame { */ int64_t pts; +#if FF_API_PKT_PTS /** * PTS copied from the AVPacket that was decoded to produce this frame. + * @deprecated use the pts field instead */ + attribute_deprecated int64_t pkt_pts; +#endif /** * DTS copied from the AVPacket that triggered returning this frame. @@ -234,78 +238,17 @@ typedef struct AVFrame { */ int quality; -#if FF_API_AVFRAME_LAVC - attribute_deprecated - int reference; - - /** - * QP table - */ - attribute_deprecated - int8_t *qscale_table; - /** - * QP store stride - */ - attribute_deprecated - int qstride; - - attribute_deprecated - int qscale_type; - - /** - * mbskip_table[mb]>=1 if MB didn't change - * stride= mb_width = (width+15)>>4 - */ - attribute_deprecated - 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 - */ - attribute_deprecated - int16_t (*motion_val[2])[2]; - - /** - * macroblock type table - * mb_type_base + mb_width + 2 - */ - attribute_deprecated - uint32_t *mb_type; - - /** - * DCT coefficients - */ - attribute_deprecated - short *dct_coeff; - - /** - * motion reference frame index - * the order in which these are stored can depend on the codec. - */ - attribute_deprecated - int8_t *ref_index[2]; -#endif - /** * for some private data of the user */ void *opaque; +#if FF_API_ERROR_FRAME /** - * error + * @deprecated unused */ - uint64_t error[AV_NUM_DATA_POINTERS]; - -#if FF_API_AVFRAME_LAVC attribute_deprecated - int type; + uint64_t error[AV_NUM_DATA_POINTERS]; #endif /** @@ -329,19 +272,8 @@ typedef struct AVFrame { */ int palette_has_changed; -#if FF_API_AVFRAME_LAVC - attribute_deprecated - int buffer_hints; - - /** - * Pan scan. - */ - attribute_deprecated - struct AVPanScan *pan_scan; -#endif - /** - * reordered opaque 64bit (generally an integer or a double precision float + * reordered opaque 64 bits (generally an integer or a double precision float * PTS but can be anything). * The user sets AVCodecContext.reordered_opaque to represent the input at * that time, @@ -351,25 +283,6 @@ typedef struct AVFrame { */ int64_t reordered_opaque; -#if FF_API_AVFRAME_LAVC - /** - * @deprecated this field is unused - */ - attribute_deprecated void *hwaccel_picture_private; - - attribute_deprecated - struct AVCodecContext *owner; - attribute_deprecated - void *thread_opaque; - - /** - * log2 of the size of the block which a single vector in motion_val represents: - * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2) - */ - attribute_deprecated - uint8_t motion_subsample_log2; -#endif - /** * Sample rate of the audio data. */ @@ -382,7 +295,9 @@ typedef struct AVFrame { /** * AVBuffer references backing the data for this frame. If all elements of - * this array are NULL, then this frame is not reference counted. + * this array are NULL, then this frame is not reference counted. This array + * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must + * also be non-NULL for all j < i. * * There may be at most one AVBuffer per data plane, so for video this array * always contains all the references. For planar audio with more than @@ -442,6 +357,12 @@ typedef struct AVFrame { enum AVColorSpace colorspace; enum AVChromaLocation chroma_location; + + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; } AVFrame; /** @@ -474,6 +395,10 @@ void av_frame_free(AVFrame **frame); * If src is not reference counted, new buffers are allocated and the data is * copied. * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * * @return 0 on success, a negative AVERROR on error */ int av_frame_ref(AVFrame *dst, const AVFrame *src); @@ -493,7 +418,11 @@ AVFrame *av_frame_clone(const AVFrame *src); void av_frame_unref(AVFrame *frame); /** - * Move everythnig contained in src to dst and reset src. + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. */ void av_frame_move_ref(AVFrame *dst, AVFrame *src); @@ -509,6 +438,10 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src); * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. * For planar formats, one buffer will be allocated for each plane. * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * * @param frame frame in which to store the new buffers. * @param align required buffer size alignment * diff --git a/libavutil/hmac.c b/libavutil/hmac.c index f87728e..378be62 100644 --- a/libavutil/hmac.c +++ b/libavutil/hmac.c @@ -26,7 +26,7 @@ #include "sha.h" #include "mem.h" -#define MAX_HASHLEN 20 +#define MAX_HASHLEN 32 #define MAX_BLOCKLEN 64 struct AVHMAC { @@ -39,11 +39,16 @@ struct AVHMAC { int keylen; }; -static av_cold void sha1_init(void *ctx) -{ - av_sha_init(ctx, 160); +#define DEFINE_SHA(bits) \ +static av_cold void sha ## bits ##_init(void *ctx) \ +{ \ + av_sha_init(ctx, bits); \ } +DEFINE_SHA(160) +DEFINE_SHA(224) +DEFINE_SHA(256) + AVHMAC *av_hmac_alloc(enum AVHMACType type) { AVHMAC *c = av_mallocz(sizeof(*c)); @@ -61,7 +66,23 @@ AVHMAC *av_hmac_alloc(enum AVHMACType type) case AV_HMAC_SHA1: c->blocklen = 64; c->hashlen = 20; - c->init = sha1_init; + c->init = sha160_init; + c->update = av_sha_update; + c->final = av_sha_final; + c->hash = av_sha_alloc(); + break; + case AV_HMAC_SHA224: + c->blocklen = 64; + c->hashlen = 28; + c->init = sha224_init; + c->update = av_sha_update; + c->final = av_sha_final; + c->hash = av_sha_alloc(); + break; + case AV_HMAC_SHA256: + c->blocklen = 64; + c->hashlen = 32; + c->init = sha256_init; c->update = av_sha_update; c->final = av_sha_final; c->hash = av_sha_alloc(); @@ -137,51 +158,3 @@ int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len, av_hmac_update(c, data, len); return av_hmac_final(c, out, outlen); } - -#ifdef TEST -#include - -static void test(AVHMAC *hmac, const uint8_t *key, int keylen, - const uint8_t *data, int datalen) -{ - uint8_t buf[MAX_HASHLEN]; - int out, i; - // Some of the test vectors are strings, where sizeof() includes the - // trailing null byte - remove that. - if (!key[keylen - 1]) - keylen--; - if (!data[datalen - 1]) - datalen--; - out = av_hmac_calc(hmac, data, datalen, key, keylen, buf, sizeof(buf)); - for (i = 0; i < out; i++) - printf("%02x", buf[i]); - printf("\n"); -} - -int main(void) -{ - uint8_t key1[16], key3[16], data3[50], key4[63], key5[64], key6[65]; - const uint8_t key2[] = "Jefe"; - const uint8_t data1[] = "Hi There"; - const uint8_t data2[] = "what do ya want for nothing?"; - AVHMAC *hmac = av_hmac_alloc(AV_HMAC_MD5); - if (!hmac) - return 1; - memset(key1, 0x0b, sizeof(key1)); - memset(key3, 0xaa, sizeof(key3)); - memset(key4, 0x44, sizeof(key4)); - memset(key5, 0x55, sizeof(key5)); - memset(key6, 0x66, sizeof(key6)); - memset(data3, 0xdd, sizeof(data3)); - // RFC 2104 test vectors - test(hmac, key1, sizeof(key1), data1, sizeof(data1)); - test(hmac, key2, sizeof(key2), data2, sizeof(data2)); - test(hmac, key3, sizeof(key3), data3, sizeof(data3)); - // Additional tests, to test cases where the key is too long - test(hmac, key4, sizeof(key4), data1, sizeof(data1)); - test(hmac, key5, sizeof(key5), data2, sizeof(data2)); - test(hmac, key6, sizeof(key6), data3, sizeof(data3)); - av_hmac_free(hmac); - return 0; -} -#endif /* TEST */ diff --git a/libavutil/hmac.h b/libavutil/hmac.h index 28c2062..1ed5626 100644 --- a/libavutil/hmac.h +++ b/libavutil/hmac.h @@ -32,6 +32,8 @@ enum AVHMACType { AV_HMAC_MD5, AV_HMAC_SHA1, + AV_HMAC_SHA224, + AV_HMAC_SHA256, }; typedef struct AVHMAC AVHMAC; diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c new file mode 100644 index 0000000..b47ef44 --- /dev/null +++ b/libavutil/hwcontext.c @@ -0,0 +1,497 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "imgutils.h" +#include "log.h" +#include "mem.h" +#include "pixdesc.h" +#include "pixfmt.h" + +static const HWContextType *hw_table[] = { +#if CONFIG_CUDA + &ff_hwcontext_type_cuda, +#endif +#if CONFIG_DXVA2 + &ff_hwcontext_type_dxva2, +#endif +#if CONFIG_LIBMFX + &ff_hwcontext_type_qsv, +#endif +#if CONFIG_VAAPI + &ff_hwcontext_type_vaapi, +#endif +#if CONFIG_VDPAU + &ff_hwcontext_type_vdpau, +#endif + NULL, +}; + +static const AVClass hwdevice_ctx_class = { + .class_name = "AVHWDeviceContext", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +static void hwdevice_ctx_free(void *opaque, uint8_t *data) +{ + AVHWDeviceContext *ctx = (AVHWDeviceContext*)data; + + /* uninit might still want access the hw context and the user + * free() callback might destroy it, so uninit has to be called first */ + if (ctx->internal->hw_type->device_uninit) + ctx->internal->hw_type->device_uninit(ctx); + + if (ctx->free) + ctx->free(ctx); + + av_freep(&ctx->hwctx); + av_freep(&ctx->internal->priv); + av_freep(&ctx->internal); + av_freep(&ctx); +} + +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) +{ + AVHWDeviceContext *ctx; + AVBufferRef *buf; + const HWContextType *hw_type = NULL; + int i; + + for (i = 0; hw_table[i]; i++) { + if (hw_table[i]->type == type) { + hw_type = hw_table[i]; + break; + } + } + if (!hw_type) + return NULL; + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return NULL; + + ctx->internal = av_mallocz(sizeof(*ctx->internal)); + if (!ctx->internal) + goto fail; + + if (hw_type->device_priv_size) { + ctx->internal->priv = av_mallocz(hw_type->device_priv_size); + if (!ctx->internal->priv) + goto fail; + } + + if (hw_type->device_hwctx_size) { + ctx->hwctx = av_mallocz(hw_type->device_hwctx_size); + if (!ctx->hwctx) + goto fail; + } + + buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), + hwdevice_ctx_free, NULL, + AV_BUFFER_FLAG_READONLY); + if (!buf) + goto fail; + + ctx->type = type; + ctx->av_class = &hwdevice_ctx_class; + + ctx->internal->hw_type = hw_type; + + return buf; + +fail: + if (ctx->internal) + av_freep(&ctx->internal->priv); + av_freep(&ctx->internal); + av_freep(&ctx->hwctx); + av_freep(&ctx); + return NULL; +} + +int av_hwdevice_ctx_init(AVBufferRef *ref) +{ + AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; + int ret; + + if (ctx->internal->hw_type->device_init) { + ret = ctx->internal->hw_type->device_init(ctx); + if (ret < 0) + goto fail; + } + + return 0; +fail: + if (ctx->internal->hw_type->device_uninit) + ctx->internal->hw_type->device_uninit(ctx); + return ret; +} + +static const AVClass hwframe_ctx_class = { + .class_name = "AVHWFramesContext", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +static void hwframe_ctx_free(void *opaque, uint8_t *data) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)data; + + if (ctx->internal->pool_internal) + av_buffer_pool_uninit(&ctx->internal->pool_internal); + + if (ctx->internal->hw_type->frames_uninit) + ctx->internal->hw_type->frames_uninit(ctx); + + if (ctx->free) + ctx->free(ctx); + + av_buffer_unref(&ctx->device_ref); + + av_freep(&ctx->hwctx); + av_freep(&ctx->internal->priv); + av_freep(&ctx->internal); + av_freep(&ctx); +} + +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in) +{ + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data; + const HWContextType *hw_type = device_ctx->internal->hw_type; + AVHWFramesContext *ctx; + AVBufferRef *buf, *device_ref = NULL;; + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return NULL; + + ctx->internal = av_mallocz(sizeof(*ctx->internal)); + if (!ctx->internal) + goto fail; + + if (hw_type->frames_priv_size) { + ctx->internal->priv = av_mallocz(hw_type->frames_priv_size); + if (!ctx->internal->priv) + goto fail; + } + + if (hw_type->frames_hwctx_size) { + ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size); + if (!ctx->hwctx) + goto fail; + } + + device_ref = av_buffer_ref(device_ref_in); + if (!device_ref) + goto fail; + + buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), + hwframe_ctx_free, NULL, + AV_BUFFER_FLAG_READONLY); + if (!buf) + goto fail; + + ctx->av_class = &hwframe_ctx_class; + ctx->device_ref = device_ref; + ctx->device_ctx = device_ctx; + ctx->format = AV_PIX_FMT_NONE; + ctx->sw_format = AV_PIX_FMT_NONE; + + ctx->internal->hw_type = hw_type; + + return buf; + +fail: + if (device_ref) + av_buffer_unref(&device_ref); + if (ctx->internal) + av_freep(&ctx->internal->priv); + av_freep(&ctx->internal); + av_freep(&ctx->hwctx); + av_freep(&ctx); + return NULL; +} + +static int hwframe_pool_prealloc(AVBufferRef *ref) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; + AVFrame **frames; + int i, ret = 0; + + frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames)); + if (!frames) + return AVERROR(ENOMEM); + + for (i = 0; i < ctx->initial_pool_size; i++) { + frames[i] = av_frame_alloc(); + if (!frames[i]) + goto fail; + + ret = av_hwframe_get_buffer(ref, frames[i], 0); + if (ret < 0) + goto fail; + } + +fail: + for (i = 0; i < ctx->initial_pool_size; i++) + av_frame_free(&frames[i]); + av_freep(&frames); + + return ret; +} + +int av_hwframe_ctx_init(AVBufferRef *ref) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; + const enum AVPixelFormat *pix_fmt; + int ret; + + /* validate the pixel format */ + for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) { + if (*pix_fmt == ctx->format) + break; + } + if (*pix_fmt == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, + "The hardware pixel format '%s' is not supported by the device type '%s'\n", + av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name); + return AVERROR(ENOSYS); + } + + /* validate the dimensions */ + ret = av_image_check_size(ctx->width, ctx->height, 0, ctx); + if (ret < 0) + return ret; + + /* format-specific init */ + if (ctx->internal->hw_type->frames_init) { + ret = ctx->internal->hw_type->frames_init(ctx); + if (ret < 0) + goto fail; + } + + if (ctx->internal->pool_internal && !ctx->pool) + ctx->pool = ctx->internal->pool_internal; + + /* preallocate the frames in the pool, if requested */ + if (ctx->initial_pool_size > 0) { + ret = hwframe_pool_prealloc(ref); + if (ret < 0) + goto fail; + } + + return 0; +fail: + if (ctx->internal->hw_type->frames_uninit) + ctx->internal->hw_type->frames_uninit(ctx); + return ret; +} + +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; + + if (!ctx->internal->hw_type->transfer_get_formats) + return AVERROR(ENOSYS); + + return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats); +} + +static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; + AVFrame *frame_tmp; + int ret = 0; + + frame_tmp = av_frame_alloc(); + if (!frame_tmp) + return AVERROR(ENOMEM); + + /* if the format is set, use that + * otherwise pick the first supported one */ + if (dst->format >= 0) { + frame_tmp->format = dst->format; + } else { + enum AVPixelFormat *formats; + + ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx, + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + &formats, 0); + if (ret < 0) + goto fail; + frame_tmp->format = formats[0]; + av_freep(&formats); + } + frame_tmp->width = ctx->width; + frame_tmp->height = ctx->height; + + ret = av_frame_get_buffer(frame_tmp, 32); + if (ret < 0) + goto fail; + + ret = av_hwframe_transfer_data(frame_tmp, src, flags); + if (ret < 0) + goto fail; + + frame_tmp->width = src->width; + frame_tmp->height = src->height; + + av_frame_move_ref(dst, frame_tmp); + +fail: + av_frame_free(&frame_tmp); + return ret; +} + +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) +{ + AVHWFramesContext *ctx; + int ret; + + if (!dst->buf[0]) + return transfer_data_alloc(dst, src, flags); + + if (src->hw_frames_ctx) { + ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; + + ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src); + if (ret < 0) + return ret; + } else if (dst->hw_frames_ctx) { + ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data; + + ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src); + if (ret < 0) + return ret; + } else + return AVERROR(ENOSYS); + + return 0; +} + +int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; + int ret; + + if (!ctx->internal->hw_type->frames_get_buffer) + return AVERROR(ENOSYS); + + if (!ctx->pool) + return AVERROR(EINVAL); + + frame->hw_frames_ctx = av_buffer_ref(hwframe_ref); + if (!frame->hw_frames_ctx) + return AVERROR(ENOMEM); + + ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame); + if (ret < 0) { + av_buffer_unref(&frame->hw_frames_ctx); + return ret; + } + + return 0; +} + +void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref) +{ + AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; + const HWContextType *hw_type = ctx->internal->hw_type; + + if (hw_type->device_hwconfig_size == 0) + return NULL; + + return av_mallocz(hw_type->device_hwconfig_size); +} + +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig) +{ + AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; + const HWContextType *hw_type = ctx->internal->hw_type; + AVHWFramesConstraints *constraints; + + if (!hw_type->frames_get_constraints) + return NULL; + + constraints = av_mallocz(sizeof(*constraints)); + if (!constraints) + return NULL; + + constraints->min_width = constraints->min_height = 0; + constraints->max_width = constraints->max_height = INT_MAX; + + if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) { + return constraints; + } else { + av_hwframe_constraints_free(&constraints); + return NULL; + } +} + +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints) +{ + if (*constraints) { + av_freep(&(*constraints)->valid_hw_formats); + av_freep(&(*constraints)->valid_sw_formats); + } + av_freep(constraints); +} + +int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags) +{ + AVBufferRef *device_ref = NULL; + AVHWDeviceContext *device_ctx; + int ret = 0; + + device_ref = av_hwdevice_ctx_alloc(type); + if (!device_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + device_ctx = (AVHWDeviceContext*)device_ref->data; + + if (!device_ctx->internal->hw_type->device_create) { + ret = AVERROR(ENOSYS); + goto fail; + } + + ret = device_ctx->internal->hw_type->device_create(device_ctx, device, + opts, flags); + if (ret < 0) + goto fail; + + ret = av_hwdevice_ctx_init(device_ref); + if (ret < 0) + goto fail; + + *pdevice_ref = device_ref; + return 0; +fail: + av_buffer_unref(&device_ref); + *pdevice_ref = NULL; + return ret; +} diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h new file mode 100644 index 0000000..0b12fe2 --- /dev/null +++ b/libavutil/hwcontext.h @@ -0,0 +1,437 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, +}; + +typedef struct AVHWDeviceInternal AVHWDeviceInternal; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWDeviceInternal *internal; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +typedef struct AVHWFramesInternal AVHWFramesInternal; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWFramesInternal *internal; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwframe_*.h) and filled as described in the + * documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Allocate an AVHWDeviceContext for a given pixel format. + * + * @param format a hwaccel pixel format (AV_PIX_FMT_FLAG_HWACCEL must be set + * on the corresponding format descriptor) + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c new file mode 100644 index 0000000..b8781ce --- /dev/null +++ b/libavutil/hwcontext_cuda.c @@ -0,0 +1,314 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_cuda.h" +#include "mem.h" +#include "pixdesc.h" +#include "pixfmt.h" + +typedef struct CUDAFramesContext { + int shift_width, shift_height; +} CUDAFramesContext; + +static const enum AVPixelFormat supported_formats[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV444P, +}; + +static void cuda_buffer_free(void *opaque, uint8_t *data) +{ + AVHWFramesContext *ctx = opaque; + AVCUDADeviceContext *hwctx = ctx->device_ctx->hwctx; + + CUcontext dummy; + + cuCtxPushCurrent(hwctx->cuda_ctx); + + cuMemFree((CUdeviceptr)data); + + cuCtxPopCurrent(&dummy); +} + +static AVBufferRef *cuda_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *ctx = opaque; + AVCUDADeviceContext *hwctx = ctx->device_ctx->hwctx; + + AVBufferRef *ret = NULL; + CUcontext dummy = NULL; + CUdeviceptr data; + CUresult err; + + err = cuCtxPushCurrent(hwctx->cuda_ctx); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Error setting current CUDA context\n"); + return NULL; + } + + err = cuMemAlloc(&data, size); + if (err != CUDA_SUCCESS) + goto fail; + + ret = av_buffer_create((uint8_t*)data, size, cuda_buffer_free, ctx, 0); + if (!ret) { + cuMemFree(data); + goto fail; + } + +fail: + cuCtxPopCurrent(&dummy); + return ret; +} + +static int cuda_frames_init(AVHWFramesContext *ctx) +{ + CUDAFramesContext *priv = ctx->internal->priv; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { + if (ctx->sw_format == supported_formats[i]) + break; + } + if (i == FF_ARRAY_ELEMS(supported_formats)) { + av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n", + av_get_pix_fmt_name(ctx->sw_format)); + return AVERROR(ENOSYS); + } + + av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height); + + if (!ctx->pool) { + int size; + + switch (ctx->sw_format) { + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_YUV420P: + size = ctx->width * ctx->height * 3 / 2; + break; + case AV_PIX_FMT_YUV444P: + size = ctx->width * ctx->height * 3; + break; + } + + ctx->internal->pool_internal = av_buffer_pool_init2(size, ctx, cuda_pool_alloc, NULL); + if (!ctx->internal->pool_internal) + return AVERROR(ENOMEM); + } + + return 0; +} + +static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + switch (ctx->sw_format) { + case AV_PIX_FMT_NV12: + frame->data[0] = frame->buf[0]->data; + frame->data[1] = frame->data[0] + ctx->width * ctx->height; + frame->linesize[0] = ctx->width; + frame->linesize[1] = ctx->width; + break; + case AV_PIX_FMT_YUV420P: + frame->data[0] = frame->buf[0]->data; + frame->data[2] = frame->data[0] + ctx->width * ctx->height; + frame->data[1] = frame->data[2] + ctx->width * ctx->height / 4; + frame->linesize[0] = ctx->width; + frame->linesize[1] = ctx->width / 2; + frame->linesize[2] = ctx->width / 2; + break; + case AV_PIX_FMT_YUV444P: + frame->data[0] = frame->buf[0]->data; + frame->data[1] = frame->data[0] + ctx->width * ctx->height; + frame->data[2] = frame->data[1] + ctx->width * ctx->height; + frame->linesize[0] = ctx->width; + frame->linesize[1] = ctx->width; + frame->linesize[2] = ctx->width; + break; + default: + av_frame_unref(frame); + return AVERROR_BUG; + } + + frame->format = AV_PIX_FMT_CUDA; + frame->width = ctx->width; + frame->height = ctx->height; + + return 0; +} + +static int cuda_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts; + + fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = ctx->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + + return 0; +} + +static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + CUDAFramesContext *priv = ctx->internal->priv; + AVCUDADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + + CUcontext dummy; + CUresult err; + int i; + + err = cuCtxPushCurrent(device_hwctx->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) { + CUDA_MEMCPY2D cpy = { + .srcMemoryType = CU_MEMORYTYPE_DEVICE, + .dstMemoryType = CU_MEMORYTYPE_HOST, + .srcDevice = (CUdeviceptr)src->data[i], + .dstHost = dst->data[i], + .srcPitch = src->linesize[i], + .dstPitch = dst->linesize[i], + .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]), + .Height = src->height >> (i ? priv->shift_height : 0), + }; + + err = cuMemcpy2D(&cpy); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Error transferring the data from the CUDA frame\n"); + return AVERROR_UNKNOWN; + } + } + + cuCtxPopCurrent(&dummy); + + return 0; +} + +static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + CUDAFramesContext *priv = ctx->internal->priv; + AVCUDADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + + CUcontext dummy; + CUresult err; + int i; + + err = cuCtxPushCurrent(device_hwctx->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) { + CUDA_MEMCPY2D cpy = { + .srcMemoryType = CU_MEMORYTYPE_HOST, + .dstMemoryType = CU_MEMORYTYPE_DEVICE, + .srcHost = src->data[i], + .dstDevice = (CUdeviceptr)dst->data[i], + .srcPitch = src->linesize[i], + .dstPitch = dst->linesize[i], + .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]), + .Height = src->height >> (i ? priv->shift_height : 0), + }; + + err = cuMemcpy2D(&cpy); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Error transferring the data from the CUDA frame\n"); + return AVERROR_UNKNOWN; + } + } + + cuCtxPopCurrent(&dummy); + + return 0; +} + +static void cuda_device_free(AVHWDeviceContext *ctx) +{ + AVCUDADeviceContext *hwctx = ctx->hwctx; + cuCtxDestroy(hwctx->cuda_ctx); +} + +static int cuda_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVCUDADeviceContext *hwctx = ctx->hwctx; + CUdevice cu_device; + CUcontext dummy; + CUresult err; + int device_idx = 0; + + if (device) + device_idx = strtol(device, NULL, 0); + + err = cuInit(0); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n"); + return AVERROR_UNKNOWN; + } + + err = cuDeviceGet(&cu_device, device_idx); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", device_idx); + return AVERROR_UNKNOWN; + } + + err = cuCtxCreate(&hwctx->cuda_ctx, 0, cu_device); + if (err != CUDA_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n"); + return AVERROR_UNKNOWN; + } + + cuCtxPopCurrent(&dummy); + + ctx->free = cuda_device_free; + + return 0; +} + +const HWContextType ff_hwcontext_type_cuda = { + .type = AV_HWDEVICE_TYPE_CUDA, + .name = "CUDA", + + .device_hwctx_size = sizeof(AVCUDADeviceContext), + .frames_priv_size = sizeof(CUDAFramesContext), + + .device_create = cuda_device_create, + .frames_init = cuda_frames_init, + .frames_get_buffer = cuda_get_buffer, + .transfer_get_formats = cuda_transfer_get_formats, + .transfer_data_to = cuda_transfer_data_to, + .transfer_data_from = cuda_transfer_data_from, + + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE }, +}; diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h new file mode 100644 index 0000000..7f067c7 --- /dev/null +++ b/libavutil/hwcontext_cuda.h @@ -0,0 +1,46 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef AVUTIL_HWCONTEXT_CUDA_H +#define AVUTIL_HWCONTEXT_CUDA_H + +#include + +#include "pixfmt.h" + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_CUDA. + * + * This API supports dynamic frame pools. AVHWFramesContext.pool must return + * AVBufferRefs whose data pointer is a CUdeviceptr. + */ + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVCUDADeviceContext { + CUcontext cuda_ctx; +} AVCUDADeviceContext; + +/** + * AVHWFramesContext.hwctx is currently not used + */ + +#endif /* AVUTIL_HWCONTEXT_CUDA_H */ diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c new file mode 100644 index 0000000..f66c0fa --- /dev/null +++ b/libavutil/hwcontext_dxva2.c @@ -0,0 +1,428 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#define DXVA2API_USE_BITFIELDS +#define COBJMACROS + +#include +#include +#include + +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_dxva2.h" +#include "hwcontext_internal.h" +#include "imgutils.h" +#include "pixdesc.h" +#include "pixfmt.h" + +typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT); +typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **); + +typedef struct DXVA2FramesContext { + IDirect3DSurface9 **surfaces_internal; + int nb_surfaces_used; + + HANDLE device_handle; + IDirectXVideoAccelerationService *service; + + D3DFORMAT format; +} DXVA2FramesContext; + +typedef struct DXVA2DevicePriv { + HMODULE d3dlib; + HMODULE dxva2lib; + + HANDLE device_handle; + + IDirect3D9 *d3d9; + IDirect3DDevice9 *d3d9device; +} DXVA2DevicePriv; + +static const struct { + D3DFORMAT d3d_format; + enum AVPixelFormat pix_fmt; +} supported_formats[] = { + { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 }, + { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 }, +}; + +DEFINE_GUID(video_decoder_service, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); +DEFINE_GUID(video_processor_service, 0xfc51a552, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); + +static void dxva2_frames_uninit(AVHWFramesContext *ctx) +{ + AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx; + AVDXVA2FramesContext *frames_hwctx = ctx->hwctx; + DXVA2FramesContext *s = ctx->internal->priv; + int i; + + if (frames_hwctx->decoder_to_release) + IDirectXVideoDecoder_Release(frames_hwctx->decoder_to_release); + + if (s->surfaces_internal) { + for (i = 0; i < frames_hwctx->nb_surfaces; i++) { + if (s->surfaces_internal[i]) + IDirect3DSurface9_Release(s->surfaces_internal[i]); + } + } + av_freep(&s->surfaces_internal); + + if (s->service) { + IDirectXVideoAccelerationService_Release(s->service); + s->service = NULL; + } + + if (s->device_handle != INVALID_HANDLE_VALUE) { + IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, s->device_handle); + s->device_handle = INVALID_HANDLE_VALUE; + } +} + +static AVBufferRef *dxva2_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; + DXVA2FramesContext *s = ctx->internal->priv; + AVDXVA2FramesContext *hwctx = ctx->hwctx; + + if (s->nb_surfaces_used < hwctx->nb_surfaces) { + s->nb_surfaces_used++; + return av_buffer_create((uint8_t*)s->surfaces_internal[s->nb_surfaces_used - 1], + sizeof(*hwctx->surfaces), NULL, 0, 0); + } + + return NULL; +} + +static int dxva2_init_pool(AVHWFramesContext *ctx) +{ + AVDXVA2FramesContext *frames_hwctx = ctx->hwctx; + AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx; + DXVA2FramesContext *s = ctx->internal->priv; + int decode = (frames_hwctx->surface_type == DXVA2_VideoDecoderRenderTarget); + + int i; + HRESULT hr; + + if (ctx->initial_pool_size <= 0) + return 0; + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &s->device_handle); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); + return AVERROR_UNKNOWN; + } + + hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, + s->device_handle, + decode ? &video_decoder_service : &video_processor_service, + (void **)&s->service); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to create the video service\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { + if (ctx->sw_format == supported_formats[i].pix_fmt) { + s->format = supported_formats[i].d3d_format; + break; + } + } + if (i == FF_ARRAY_ELEMS(supported_formats)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", + av_get_pix_fmt_name(ctx->sw_format)); + return AVERROR(EINVAL); + } + + s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size, + sizeof(*s->surfaces_internal)); + if (!s->surfaces_internal) + return AVERROR(ENOMEM); + + hr = IDirectXVideoAccelerationService_CreateSurface(s->service, + ctx->width, ctx->height, + ctx->initial_pool_size - 1, + s->format, D3DPOOL_DEFAULT, 0, + frames_hwctx->surface_type, + s->surfaces_internal, NULL); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Could not create the surfaces\n"); + return AVERROR_UNKNOWN; + } + + ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(*s->surfaces_internal), + ctx, dxva2_pool_alloc, NULL); + if (!ctx->internal->pool_internal) + return AVERROR(ENOMEM); + + frames_hwctx->surfaces = s->surfaces_internal; + frames_hwctx->nb_surfaces = ctx->initial_pool_size; + + return 0; +} + +static int dxva2_frames_init(AVHWFramesContext *ctx) +{ + AVDXVA2FramesContext *hwctx = ctx->hwctx; + DXVA2FramesContext *s = ctx->internal->priv; + int ret; + + if (hwctx->surface_type != DXVA2_VideoDecoderRenderTarget && + hwctx->surface_type != DXVA2_VideoProcessorRenderTarget) { + av_log(ctx, AV_LOG_ERROR, "Unknown surface type: %lu\n", + hwctx->surface_type); + return AVERROR(EINVAL); + } + + s->device_handle = INVALID_HANDLE_VALUE; + + /* init the frame pool if the caller didn't provide one */ + if (!ctx->pool) { + ret = dxva2_init_pool(ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n"); + return ret; + } + } + + return 0; +} + +static int dxva2_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[3] = frame->buf[0]->data; + frame->format = AV_PIX_FMT_DXVA2_VLD; + frame->width = ctx->width; + frame->height = ctx->height; + + return 0; +} + +static int dxva2_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts; + + fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = ctx->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + + return 0; +} + +static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + IDirect3DSurface9 *surface; + D3DSURFACE_DESC surfaceDesc; + D3DLOCKED_RECT LockedRect; + HRESULT hr; + + uint8_t *surf_data[4] = { NULL }; + int surf_linesize[4] = { 0 }; + int i; + + int download = !!src->hw_frames_ctx; + + surface = (IDirect3DSurface9*)(download ? src->data[3] : dst->data[3]); + + hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n"); + return AVERROR_UNKNOWN; + } + + hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, + download ? D3DLOCK_READONLY : D3DLOCK_DISCARD); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; download ? dst->data[i] : src->data[i]; i++) + surf_linesize[i] = LockedRect.Pitch; + + av_image_fill_pointers(surf_data, ctx->sw_format, surfaceDesc.Height, + (uint8_t*)LockedRect.pBits, surf_linesize); + + if (download) { + av_image_copy(dst->data, dst->linesize, surf_data, surf_linesize, + ctx->sw_format, src->width, src->height); + } else { + av_image_copy(surf_data, surf_linesize, src->data, src->linesize, + ctx->sw_format, src->width, src->height); + } + + IDirect3DSurface9_UnlockRect(surface); + + return 0; +} + +static void dxva2_device_free(AVHWDeviceContext *ctx) +{ + AVDXVA2DeviceContext *hwctx = ctx->hwctx; + DXVA2DevicePriv *priv = ctx->user_opaque; + + if (hwctx->devmgr && priv->device_handle != INVALID_HANDLE_VALUE) + IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->device_handle); + + if (hwctx->devmgr) + IDirect3DDeviceManager9_Release(hwctx->devmgr); + + if (priv->d3d9device) + IDirect3DDevice9_Release(priv->d3d9device); + + if (priv->d3d9) + IDirect3D9_Release(priv->d3d9); + + if (priv->d3dlib) + FreeLibrary(priv->d3dlib); + + if (priv->dxva2lib) + FreeLibrary(priv->dxva2lib); + + av_freep(&ctx->user_opaque); +} + +static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVDXVA2DeviceContext *hwctx = ctx->hwctx; + DXVA2DevicePriv *priv; + + pDirect3DCreate9 *createD3D = NULL; + pCreateDeviceManager9 *createDeviceManager = NULL; + D3DPRESENT_PARAMETERS d3dpp = {0}; + D3DDISPLAYMODE d3ddm; + unsigned resetToken = 0; + UINT adapter = D3DADAPTER_DEFAULT; + HRESULT hr; + + if (device) + adapter = atoi(device); + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + ctx->user_opaque = priv; + ctx->free = dxva2_device_free; + + priv->device_handle = INVALID_HANDLE_VALUE; + + priv->d3dlib = LoadLibrary("d3d9.dll"); + if (!priv->d3dlib) { + av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n"); + return AVERROR_UNKNOWN; + } + priv->dxva2lib = LoadLibrary("dxva2.dll"); + if (!priv->dxva2lib) { + av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n"); + return AVERROR_UNKNOWN; + } + + createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9"); + if (!createD3D) { + av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n"); + return AVERROR_UNKNOWN; + } + createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(priv->dxva2lib, + "DXVA2CreateDirect3DDeviceManager9"); + if (!createDeviceManager) { + av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); + return AVERROR_UNKNOWN; + } + + priv->d3d9 = createD3D(D3D_SDK_VERSION); + if (!priv->d3d9) { + av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n"); + return AVERROR_UNKNOWN; + } + + IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm); + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = 640; + d3dpp.BackBufferHeight = 480; + d3dpp.BackBufferCount = 0; + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.Flags = D3DPRESENTFLAG_VIDEO; + + hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, + &d3dpp, &priv->d3d9device); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n"); + return AVERROR_UNKNOWN; + } + + hr = createDeviceManager(&resetToken, &hwctx->devmgr); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n"); + return AVERROR_UNKNOWN; + } + + hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n"); + return AVERROR_UNKNOWN; + } + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +const HWContextType ff_hwcontext_type_dxva2 = { + .type = AV_HWDEVICE_TYPE_DXVA2, + .name = "DXVA2", + + .device_hwctx_size = sizeof(AVDXVA2DeviceContext), + .frames_hwctx_size = sizeof(AVDXVA2FramesContext), + .frames_priv_size = sizeof(DXVA2FramesContext), + + .device_create = dxva2_device_create, + .frames_init = dxva2_frames_init, + .frames_uninit = dxva2_frames_uninit, + .frames_get_buffer = dxva2_get_buffer, + .transfer_get_formats = dxva2_transfer_get_formats, + .transfer_data_to = dxva2_transfer_data, + .transfer_data_from = dxva2_transfer_data, + + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_DXVA2_VLD, AV_PIX_FMT_NONE }, +}; diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h new file mode 100644 index 0000000..2290c26 --- /dev/null +++ b/libavutil/hwcontext_dxva2.h @@ -0,0 +1,72 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef AVUTIL_HWCONTEXT_DXVA2_H +#define AVUTIL_HWCONTEXT_DXVA2_H + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_DXVA2. + * + * Only fixed-size pools are supported. + * + * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer set to a pointer to IDirect3DSurface9. + */ + +#include +#include + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVDXVA2DeviceContext { + IDirect3DDeviceManager9 *devmgr; +} AVDXVA2DeviceContext; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVDXVA2FramesContext { + /** + * The surface type (e.g. DXVA2_VideoProcessorRenderTarget or + * DXVA2_VideoDecoderRenderTarget). Must be set by the caller. + */ + DWORD surface_type; + + /** + * The surface pool. When an external pool is not provided by the caller, + * this will be managed (allocated and filled on init, freed on uninit) by + * libavutil. + */ + IDirect3DSurface9 **surfaces; + int nb_surfaces; + + /** + * Certain drivers require the decoder to be destroyed before the surfaces. + * To allow internally managed pools to work properly in such cases, this + * field is provided. + * + * If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on + * it just before the internal surface pool is freed. + */ + IDirectXVideoDecoder *decoder_to_release; +} AVDXVA2FramesContext; + +#endif /* AVUTIL_HWCONTEXT_DXVA2_H */ diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h new file mode 100644 index 0000000..a391e25 --- /dev/null +++ b/libavutil/hwcontext_internal.h @@ -0,0 +1,108 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_INTERNAL_H +#define AVUTIL_HWCONTEXT_INTERNAL_H + +#include + +#include "buffer.h" +#include "hwcontext.h" +#include "frame.h" +#include "pixfmt.h" + +typedef struct HWContextType { + enum AVHWDeviceType type; + const char *name; + + /** + * An array of pixel formats supported by the AVHWFramesContext instances + * Terminated by AV_PIX_FMT_NONE. + */ + const enum AVPixelFormat *pix_fmts; + + /** + * size of the public hardware-specific context, + * i.e. AVHWDeviceContext.hwctx + */ + size_t device_hwctx_size; + /** + * size of the private data, i.e. + * AVHWDeviceInternal.priv + */ + size_t device_priv_size; + + /** + * Size of the hardware-specific device configuration. + * (Used to query hwframe constraints.) + */ + size_t device_hwconfig_size; + + /** + * size of the public frame pool hardware-specific context, + * i.e. AVHWFramesContext.hwctx + */ + size_t frames_hwctx_size; + /** + * size of the private data, i.e. + * AVHWFramesInternal.priv + */ + size_t frames_priv_size; + + int (*device_create)(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags); + + int (*device_init)(AVHWDeviceContext *ctx); + void (*device_uninit)(AVHWDeviceContext *ctx); + + int (*frames_get_constraints)(AVHWDeviceContext *ctx, + const void *hwconfig, + AVHWFramesConstraints *constraints); + + int (*frames_init)(AVHWFramesContext *ctx); + void (*frames_uninit)(AVHWFramesContext *ctx); + + int (*frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame); + int (*transfer_get_formats)(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats); + int (*transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src); + int (*transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src); +} HWContextType; + +struct AVHWDeviceInternal { + const HWContextType *hw_type; + void *priv; +}; + +struct AVHWFramesInternal { + const HWContextType *hw_type; + void *priv; + + AVBufferPool *pool_internal; +}; + +extern const HWContextType ff_hwcontext_type_cuda; +extern const HWContextType ff_hwcontext_type_dxva2; +extern const HWContextType ff_hwcontext_type_qsv; +extern const HWContextType ff_hwcontext_type_vaapi; +extern const HWContextType ff_hwcontext_type_vdpau; + +#endif /* AVUTIL_HWCONTEXT_INTERNAL_H */ diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c new file mode 100644 index 0000000..f2c8086 --- /dev/null +++ b/libavutil/hwcontext_qsv.c @@ -0,0 +1,792 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +#include "config.h" + +#if CONFIG_VAAPI +#include "hwcontext_vaapi.h" +#endif +#if CONFIG_DXVA2 +#include "hwcontext_dxva2.h" +#endif + +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_qsv.h" +#include "mem.h" +#include "pixfmt.h" +#include "pixdesc.h" +#include "time.h" + +typedef struct QSVDevicePriv { + AVBufferRef *child_device_ctx; +} QSVDevicePriv; + +typedef struct QSVDeviceContext { + mfxHDL handle; + mfxHandleType handle_type; + mfxVersion ver; + mfxIMPL impl; + + enum AVHWDeviceType child_device_type; + enum AVPixelFormat child_pix_fmt; +} QSVDeviceContext; + +typedef struct QSVFramesContext { + mfxSession session_download; + mfxSession session_upload; + + AVBufferRef *child_frames_ref; + mfxFrameSurface1 *surfaces_internal; + int nb_surfaces_used; + + // used in the frame allocator for non-opaque surfaces + mfxMemId *mem_ids; + // used in the opaque alloc request for opaque surfaces + mfxFrameSurface1 **surface_ptrs; + + mfxExtOpaqueSurfaceAlloc opaque_alloc; + mfxExtBuffer *ext_buffers[1]; +} QSVFramesContext; + +static const struct { + mfxHandleType handle_type; + enum AVHWDeviceType device_type; + enum AVPixelFormat pix_fmt; +} supported_handle_types[] = { +#if CONFIG_VAAPI + { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI }, +#endif +#if CONFIG_DXVA2 + { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD }, +#endif + { 0 }, +}; + +static const struct { + enum AVPixelFormat pix_fmt; + uint32_t fourcc; +} supported_pixel_formats[] = { + { AV_PIX_FMT_NV12, MFX_FOURCC_NV12 }, + { AV_PIX_FMT_P010, MFX_FOURCC_P010 }, +}; + +static int qsv_device_init(AVHWDeviceContext *ctx) +{ + AVQSVDeviceContext *hwctx = ctx->hwctx; + QSVDeviceContext *s = ctx->internal->priv; + + mfxStatus err; + int i; + + for (i = 0; supported_handle_types[i].handle_type; i++) { + err = MFXVideoCORE_GetHandle(hwctx->session, supported_handle_types[i].handle_type, + &s->handle); + if (err == MFX_ERR_NONE) { + s->handle_type = supported_handle_types[i].handle_type; + s->child_device_type = supported_handle_types[i].device_type; + s->child_pix_fmt = supported_handle_types[i].pix_fmt; + break; + } + } + if (!s->handle) { + av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved " + "from the session\n"); + } + + err = MFXQueryIMPL(hwctx->session, &s->impl); + if (err == MFX_ERR_NONE) + err = MFXQueryVersion(hwctx->session, &s->ver); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static void qsv_frames_uninit(AVHWFramesContext *ctx) +{ + QSVFramesContext *s = ctx->internal->priv; + + if (s->session_download) { + MFXVideoVPP_Close(s->session_download); + MFXClose(s->session_download); + } + s->session_download = NULL; + + if (s->session_upload) { + MFXVideoVPP_Close(s->session_upload); + MFXClose(s->session_upload); + } + s->session_upload = NULL; + + av_freep(&s->mem_ids); + av_freep(&s->surface_ptrs); + av_freep(&s->surfaces_internal); + av_buffer_unref(&s->child_frames_ref); +} + +static void qsv_pool_release_dummy(void *opaque, uint8_t *data) +{ +} + +static AVBufferRef *qsv_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; + QSVFramesContext *s = ctx->internal->priv; + AVQSVFramesContext *hwctx = ctx->hwctx; + + if (s->nb_surfaces_used < hwctx->nb_surfaces) { + s->nb_surfaces_used++; + return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), + sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0); + } + + return NULL; +} + +static int qsv_init_child_ctx(AVHWFramesContext *ctx) +{ + AVQSVFramesContext *hwctx = ctx->hwctx; + QSVFramesContext *s = ctx->internal->priv; + QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv; + + AVBufferRef *child_device_ref = NULL; + AVBufferRef *child_frames_ref = NULL; + + AVHWDeviceContext *child_device_ctx; + AVHWFramesContext *child_frames_ctx; + + int i, ret = 0; + + if (!device_priv->handle) { + av_log(ctx, AV_LOG_ERROR, + "Cannot create a non-opaque internal surface pool without " + "a hardware handle\n"); + return AVERROR(EINVAL); + } + + child_device_ref = av_hwdevice_ctx_alloc(device_priv->child_device_type); + if (!child_device_ref) + return AVERROR(ENOMEM); + child_device_ctx = (AVHWDeviceContext*)child_device_ref->data; + +#if CONFIG_VAAPI + if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { + AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; + child_device_hwctx->display = (VADisplay)device_priv->handle; + } +#endif +#if CONFIG_DXVA2 + if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; + child_device_hwctx->devmgr = (IDirect3DDeviceManager9*)device_priv->handle; + } +#endif + + ret = av_hwdevice_ctx_init(child_device_ref); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error initializing a child device context\n"); + goto fail; + } + + child_frames_ref = av_hwframe_ctx_alloc(child_device_ref); + if (!child_frames_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + child_frames_ctx = (AVHWFramesContext*)child_frames_ref->data; + + child_frames_ctx->format = device_priv->child_pix_fmt; + child_frames_ctx->sw_format = ctx->sw_format; + child_frames_ctx->initial_pool_size = ctx->initial_pool_size; + child_frames_ctx->width = ctx->width; + child_frames_ctx->height = ctx->height; + +#if CONFIG_DXVA2 + if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx; + if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) + child_frames_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget; + else + child_frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; + } +#endif + + ret = av_hwframe_ctx_init(child_frames_ref); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error initializing a child frames context\n"); + goto fail; + } + +#if CONFIG_VAAPI + if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { + AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx; + for (i = 0; i < ctx->initial_pool_size; i++) + s->surfaces_internal[i].Data.MemId = child_frames_hwctx->surface_ids + i; + hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + } +#endif +#if CONFIG_DXVA2 + if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx; + for (i = 0; i < ctx->initial_pool_size; i++) + s->surfaces_internal[i].Data.MemId = (mfxMemId)child_frames_hwctx->surfaces[i]; + if (child_frames_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget) + hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; + else + hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + } +#endif + + s->child_frames_ref = child_frames_ref; + child_frames_ref = NULL; + +fail: + av_buffer_unref(&child_device_ref); + av_buffer_unref(&child_frames_ref); + return ret; +} + +static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) +{ + QSVFramesContext *s = ctx->internal->priv; + AVQSVFramesContext *frames_hwctx = ctx->hwctx; + const AVPixFmtDescriptor *desc; + + int i, ret = 0; + + desc = av_pix_fmt_desc_get(ctx->sw_format); + if (!desc) + return AVERROR_BUG; + + if (ctx->initial_pool_size <= 0) { + av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n"); + return AVERROR(EINVAL); + } + + s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size, + sizeof(*s->surfaces_internal)); + if (!s->surfaces_internal) + return AVERROR(ENOMEM); + + for (i = 0; i < ctx->initial_pool_size; i++) { + mfxFrameSurface1 *surf = &s->surfaces_internal[i]; + + surf->Info.BitDepthLuma = desc->comp[0].depth; + surf->Info.BitDepthChroma = desc->comp[0].depth; + surf->Info.Shift = desc->comp[0].depth > 8; + + if (desc->log2_chroma_w && desc->log2_chroma_h) + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + else if (desc->log2_chroma_w) + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422; + else + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; + + surf->Info.FourCC = fourcc; + surf->Info.Width = ctx->width; + surf->Info.CropW = ctx->width; + surf->Info.Height = ctx->height; + surf->Info.CropH = ctx->height; + surf->Info.FrameRateExtN = 25; + surf->Info.FrameRateExtD = 1; + } + + if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) { + ret = qsv_init_child_ctx(ctx); + if (ret < 0) + return ret; + } + + ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1), + ctx, qsv_pool_alloc, NULL); + if (!ctx->internal->pool_internal) + return AVERROR(ENOMEM); + + frames_hwctx->surfaces = s->surfaces_internal; + frames_hwctx->nb_surfaces = ctx->initial_pool_size; + + return 0; +} + +static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + AVHWFramesContext *ctx = pthis; + QSVFramesContext *s = ctx->internal->priv; + AVQSVFramesContext *hwctx = ctx->hwctx; + mfxFrameInfo *i = &req->Info; + mfxFrameInfo *i1 = &hwctx->surfaces[0].Info; + + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || + !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || + !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) + return MFX_ERR_UNSUPPORTED; + if (i->Width != i1->Width || i->Height != i1->Height || + i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) { + av_log(ctx, AV_LOG_ERROR, "Mismatching surface properties in an " + "allocation request: %dx%d %d %d vs %dx%d %d %d\n", + i->Width, i->Height, i->FourCC, i->ChromaFormat, + i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat); + return MFX_ERR_UNSUPPORTED; + } + + resp->mids = s->mem_ids; + resp->NumFrameActual = hwctx->nb_surfaces; + + return MFX_ERR_NONE; +} + +static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + return MFX_ERR_NONE; +} + +static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +static int qsv_init_internal_session(AVHWFramesContext *ctx, + mfxSession *session, int upload) +{ + QSVFramesContext *s = ctx->internal->priv; + AVQSVFramesContext *frames_hwctx = ctx->hwctx; + QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv; + int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); + + mfxFrameAllocator frame_allocator = { + .pthis = ctx, + .Alloc = frame_alloc, + .Lock = frame_lock, + .Unlock = frame_unlock, + .GetHDL = frame_get_hdl, + .Free = frame_free, + }; + + mfxVideoParam par; + mfxStatus err; + + err = MFXInit(device_priv->impl, &device_priv->ver, session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n"); + return AVERROR_UNKNOWN; + } + + if (device_priv->handle) { + err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type, + device_priv->handle); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + if (!opaque) { + err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + memset(&par, 0, sizeof(par)); + + if (opaque) { + par.ExtParam = s->ext_buffers; + par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); + par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY : + MFX_IOPATTERN_IN_OPAQUE_MEMORY; + } else { + par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY : + MFX_IOPATTERN_IN_VIDEO_MEMORY; + } + + par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY : + MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + par.AsyncDepth = 1; + + par.vpp.In = frames_hwctx->surfaces[0].Info; + + /* Apparently VPP requires the frame rate to be set to some value, otherwise + * init will fail (probably for the framerate conversion filter). Since we + * are only doing data upload/download here, we just invent an arbitrary + * value */ + par.vpp.In.FrameRateExtN = 25; + par.vpp.In.FrameRateExtD = 1; + par.vpp.Out = par.vpp.In; + + err = MFXVideoVPP_Init(*session, &par); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error opening the internal VPP session\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int qsv_frames_init(AVHWFramesContext *ctx) +{ + QSVFramesContext *s = ctx->internal->priv; + AVQSVFramesContext *frames_hwctx = ctx->hwctx; + + int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); + + uint32_t fourcc = 0; + int i, ret; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { + if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) { + fourcc = supported_pixel_formats[i].fourcc; + break; + } + } + if (!fourcc) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n"); + return AVERROR(ENOSYS); + } + + if (!ctx->pool) { + ret = qsv_init_pool(ctx, fourcc); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n"); + return ret; + } + } + + if (opaque) { + s->surface_ptrs = av_mallocz_array(frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs)); + if (!s->surface_ptrs) + return AVERROR(ENOMEM); + + for (i = 0; i < frames_hwctx->nb_surfaces; i++) + s->surface_ptrs[i] = frames_hwctx->surfaces + i; + + s->opaque_alloc.In.Surfaces = s->surface_ptrs; + s->opaque_alloc.In.NumSurface = frames_hwctx->nb_surfaces; + s->opaque_alloc.In.Type = frames_hwctx->frame_type; + + s->opaque_alloc.Out = s->opaque_alloc.In; + + s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; + s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); + + s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; + } else { + s->mem_ids = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids)); + if (!s->mem_ids) + return AVERROR(ENOMEM); + + for (i = 0; i < frames_hwctx->nb_surfaces; i++) + s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId; + } + + ret = qsv_init_internal_session(ctx, &s->session_download, 0); + if (ret < 0) + return ret; + + ret = qsv_init_internal_session(ctx, &s->session_upload, 1); + if (ret < 0) + return ret; + + return 0; +} + +static int qsv_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[3] = frame->buf[0]->data; + frame->format = AV_PIX_FMT_QSV; + frame->width = ctx->width; + frame->height = ctx->height; + + return 0; +} + +static int qsv_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts; + + fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = ctx->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + + return 0; +} + +static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + QSVFramesContext *s = ctx->internal->priv; + mfxFrameSurface1 out = {{ 0 }}; + mfxFrameSurface1 *in = (mfxFrameSurface1*)src->data[3]; + + mfxSyncPoint sync = NULL; + mfxStatus err; + + out.Info = in->Info; + out.Data.PitchLow = dst->linesize[0]; + out.Data.Y = dst->data[0]; + out.Data.U = dst->data[1]; + out.Data.V = dst->data[2]; + out.Data.A = dst->data[3]; + + do { + err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, &out, NULL, &sync); + if (err == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + } while (err == MFX_WRN_DEVICE_BUSY); + + if (err < 0 || !sync) { + av_log(ctx, AV_LOG_ERROR, "Error downloading the surface\n"); + return AVERROR_UNKNOWN; + } + + do { + err = MFXVideoCORE_SyncOperation(s->session_download, sync, 1000); + } while (err == MFX_WRN_IN_EXECUTION); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + QSVFramesContext *s = ctx->internal->priv; + mfxFrameSurface1 in = {{ 0 }}; + mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; + + mfxSyncPoint sync = NULL; + mfxStatus err; + + in.Info = out->Info; + in.Data.PitchLow = src->linesize[0]; + in.Data.Y = src->data[0]; + in.Data.U = src->data[1]; + in.Data.V = src->data[2]; + in.Data.A = src->data[3]; + + do { + err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync); + if (err == MFX_WRN_DEVICE_BUSY) + av_usleep(1); + } while (err == MFX_WRN_DEVICE_BUSY); + + if (err < 0 || !sync) { + av_log(ctx, AV_LOG_ERROR, "Error uploading the surface\n"); + return AVERROR_UNKNOWN; + } + + do { + err = MFXVideoCORE_SyncOperation(s->session_upload, sync, 1000); + } while (err == MFX_WRN_IN_EXECUTION); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + int i; + + constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_pixel_formats) + 1, + sizeof(*constraints->valid_sw_formats)); + if (!constraints->valid_sw_formats) + return AVERROR(ENOMEM); + + for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) + constraints->valid_sw_formats[i] = supported_pixel_formats[i].pix_fmt; + constraints->valid_sw_formats[FF_ARRAY_ELEMS(supported_pixel_formats)] = AV_PIX_FMT_NONE; + + constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); + if (!constraints->valid_hw_formats) + return AVERROR(ENOMEM); + + constraints->valid_hw_formats[0] = AV_PIX_FMT_QSV; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + return 0; +} + +static void qsv_device_free(AVHWDeviceContext *ctx) +{ + AVQSVDeviceContext *hwctx = ctx->hwctx; + QSVDevicePriv *priv = ctx->user_opaque; + + if (hwctx->session) + MFXClose(hwctx->session); + + av_buffer_unref(&priv->child_device_ctx); + av_freep(&priv); +} + +static mfxIMPL choose_implementation(const char *device) +{ + static const struct { + const char *name; + mfxIMPL impl; + } impl_map[] = { + { "auto", MFX_IMPL_AUTO }, + { "sw", MFX_IMPL_SOFTWARE }, + { "hw", MFX_IMPL_HARDWARE }, + { "auto_any", MFX_IMPL_AUTO_ANY }, + { "hw_any", MFX_IMPL_HARDWARE_ANY }, + { "hw2", MFX_IMPL_HARDWARE2 }, + { "hw3", MFX_IMPL_HARDWARE3 }, + { "hw4", MFX_IMPL_HARDWARE4 }, + }; + + mfxIMPL impl = MFX_IMPL_AUTO_ANY; + int i; + + if (device) { + for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++) + if (!strcmp(device, impl_map[i].name)) { + impl = impl_map[i].impl; + break; + } + if (i == FF_ARRAY_ELEMS(impl_map)) + impl = strtol(device, NULL, 0); + } + + return impl; +} + +static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVQSVDeviceContext *hwctx = ctx->hwctx; + QSVDevicePriv *priv; + enum AVHWDeviceType child_device_type; + AVDictionaryEntry *e; + + mfxVersion ver = { { 3, 1 } }; + mfxIMPL impl; + mfxHDL handle; + mfxHandleType handle_type; + mfxStatus err; + int ret; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + ctx->user_opaque = priv; + ctx->free = qsv_device_free; + + e = av_dict_get(opts, "child_device", NULL, 0); + + if (CONFIG_VAAPI) + child_device_type = AV_HWDEVICE_TYPE_VAAPI; + else if (CONFIG_DXVA2) + child_device_type = AV_HWDEVICE_TYPE_DXVA2; + else { + av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); + return AVERROR(ENOSYS); + } + + ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type, + e ? e->value : NULL, NULL, 0); + if (ret < 0) + return ret; + + { + AVHWDeviceContext *child_device_ctx = (AVHWDeviceContext*)priv->child_device_ctx->data; +#if CONFIG_VAAPI + AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; + handle_type = MFX_HANDLE_VA_DISPLAY; + handle = (mfxHDL)child_device_hwctx->display; +#elif CONFIG_DXVA2 + AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; + handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; + handle = (mfxHDL)child_device_hwctx->devmgr; +#endif + } + + impl = choose_implementation(device); + + err = MFXInit(impl, &ver, &hwctx->session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); + return AVERROR_UNKNOWN; + } + + err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + + return 0; +} + +const HWContextType ff_hwcontext_type_qsv = { + .type = AV_HWDEVICE_TYPE_QSV, + .name = "QSV", + + .device_hwctx_size = sizeof(AVQSVDeviceContext), + .device_priv_size = sizeof(QSVDeviceContext), + .frames_hwctx_size = sizeof(AVQSVFramesContext), + .frames_priv_size = sizeof(QSVFramesContext), + + .device_create = qsv_device_create, + .device_init = qsv_device_init, + .frames_get_constraints = qsv_frames_get_constraints, + .frames_init = qsv_frames_init, + .frames_uninit = qsv_frames_uninit, + .frames_get_buffer = qsv_get_buffer, + .transfer_get_formats = qsv_transfer_get_formats, + .transfer_data_to = qsv_transfer_data_to, + .transfer_data_from = qsv_transfer_data_from, + + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, +}; diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h new file mode 100644 index 0000000..8f9d3d2 --- /dev/null +++ b/libavutil/hwcontext_qsv.h @@ -0,0 +1,53 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_QSV_H +#define AVUTIL_HWCONTEXT_QSV_H + +#include + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_QSV. + * + * This API does not support dynamic frame pools. AVHWFramesContext.pool must + * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct. + */ + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVQSVDeviceContext { + mfxSession session; +} AVQSVDeviceContext; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVQSVFramesContext { + mfxFrameSurface1 *surfaces; + int nb_surfaces; + + /** + * A combination of MFX_MEMTYPE_* describing the frame pool. + */ + int frame_type; +} AVQSVFramesContext; + +#endif /* AVUTIL_HWCONTEXT_QSV_H */ + diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c new file mode 100644 index 0000000..e13c0de --- /dev/null +++ b/libavutil/hwcontext_vaapi.c @@ -0,0 +1,999 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#if HAVE_VAAPI_X11 +# include +#endif +#if HAVE_VAAPI_DRM +# include +#endif + +#include +#if HAVE_UNISTD_H +# include +#endif + + +#include "avassert.h" +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_vaapi.h" +#include "mem.h" +#include "pixdesc.h" +#include "pixfmt.h" + +typedef struct VAAPIDevicePriv { +#if HAVE_VAAPI_X11 + Display *x11_display; +#endif + + int drm_fd; +} VAAPIDevicePriv; + +typedef struct VAAPISurfaceFormat { + enum AVPixelFormat pix_fmt; + VAImageFormat image_format; +} VAAPISurfaceFormat; + +typedef struct VAAPIDeviceContext { + // Surface formats which can be used with this device. + VAAPISurfaceFormat *formats; + int nb_formats; +} VAAPIDeviceContext; + +typedef struct VAAPIFramesContext { + // Surface attributes set at create time. + VASurfaceAttrib *attributes; + int nb_attributes; + // RT format of the underlying surface (Intel driver ignores this anyway). + unsigned int rt_format; + // Whether vaDeriveImage works. + int derive_works; +} VAAPIFramesContext; + +enum { + VAAPI_MAP_READ = 0x01, + VAAPI_MAP_WRITE = 0x02, + VAAPI_MAP_DIRECT = 0x04, +}; + +typedef struct VAAPISurfaceMap { + // The source hardware frame of this mapping (with hw_frames_ctx set). + const AVFrame *source; + // VAAPI_MAP_* flags which apply to this mapping. + int flags; + // Handle to the derived or copied image which is mapped. + VAImage image; +} VAAPISurfaceMap; + +#define MAP(va, rt, av) { \ + VA_FOURCC_ ## va, \ + VA_RT_FORMAT_ ## rt, \ + AV_PIX_FMT_ ## av \ + } +// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V +// plane swap cases. The frame handling below tries to hide these. +static struct { + unsigned int fourcc; + unsigned int rt_format; + enum AVPixelFormat pix_fmt; +} vaapi_format_map[] = { + MAP(NV12, YUV420, NV12), + MAP(YV12, YUV420, YUV420P), // With U/V planes swapped. + MAP(IYUV, YUV420, YUV420P), + //MAP(I420, YUV420, YUV420P), // Not in libva but used by Intel driver. +#ifdef VA_FOURCC_YV16 + MAP(YV16, YUV422, YUV422P), // With U/V planes swapped. +#endif + MAP(422H, YUV422, YUV422P), + MAP(UYVY, YUV422, UYVY422), + MAP(YUY2, YUV422, YUYV422), + MAP(Y800, YUV400, GRAY8), +#ifdef VA_FOURCC_P010 + //MAP(P010, YUV420_10BPP, P010), +#endif + MAP(BGRA, RGB32, BGRA), + //MAP(BGRX, RGB32, BGR0), + MAP(RGBA, RGB32, RGBA), + //MAP(RGBX, RGB32, RGB0), + MAP(ABGR, RGB32, ABGR), + //MAP(XBGR, RGB32, 0BGR), + MAP(ARGB, RGB32, ARGB), + //MAP(XRGB, RGB32, 0RGB), +}; +#undef MAP + +static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) + if (vaapi_format_map[i].fourcc == fourcc) + return vaapi_format_map[i].pix_fmt; + return AV_PIX_FMT_NONE; +} + +static int vaapi_get_image_format(AVHWDeviceContext *hwdev, + enum AVPixelFormat pix_fmt, + VAImageFormat **image_format) +{ + VAAPIDeviceContext *ctx = hwdev->internal->priv; + int i; + + for (i = 0; i < ctx->nb_formats; i++) { + if (ctx->formats[i].pix_fmt == pix_fmt) { + *image_format = &ctx->formats[i].image_format; + return 0; + } + } + return AVERROR(EINVAL); +} + +static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + AVVAAPIDeviceContext *hwctx = hwdev->hwctx; + const AVVAAPIHWConfig *config = hwconfig; + VAAPIDeviceContext *ctx = hwdev->internal->priv; + VASurfaceAttrib *attr_list = NULL; + VAStatus vas; + enum AVPixelFormat pix_fmt; + unsigned int fourcc; + int err, i, j, attr_count, pix_fmt_count; + + if (config) { + attr_count = 0; + vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, + 0, &attr_count); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(ENOSYS); + goto fail; + } + + attr_list = av_malloc(attr_count * sizeof(*attr_list)); + if (!attr_list) { + err = AVERROR(ENOMEM); + goto fail; + } + + vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, + attr_list, &attr_count); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(ENOSYS); + goto fail; + } + + pix_fmt_count = 0; + for (i = 0; i < attr_count; i++) { + switch (attr_list[i].type) { + case VASurfaceAttribPixelFormat: + fourcc = attr_list[i].value.value.i; + pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); + if (pix_fmt != AV_PIX_FMT_NONE) { + ++pix_fmt_count; + } else { + // Something unsupported - ignore. + } + break; + case VASurfaceAttribMinWidth: + constraints->min_width = attr_list[i].value.value.i; + break; + case VASurfaceAttribMinHeight: + constraints->min_height = attr_list[i].value.value.i; + break; + case VASurfaceAttribMaxWidth: + constraints->max_width = attr_list[i].value.value.i; + break; + case VASurfaceAttribMaxHeight: + constraints->max_height = attr_list[i].value.value.i; + break; + } + } + if (pix_fmt_count == 0) { + // Nothing usable found. Presumably there exists something which + // works, so leave the set null to indicate unknown. + constraints->valid_sw_formats = NULL; + } else { + constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1, + sizeof(pix_fmt)); + if (!constraints->valid_sw_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (i = j = 0; i < attr_count; i++) { + if (attr_list[i].type != VASurfaceAttribPixelFormat) + continue; + fourcc = attr_list[i].value.value.i; + pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); + if (pix_fmt != AV_PIX_FMT_NONE) + constraints->valid_sw_formats[j++] = pix_fmt; + } + av_assert0(j == pix_fmt_count); + constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE; + } + } else { + // No configuration supplied. + // Return the full set of image formats known by the implementation. + constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1, + sizeof(pix_fmt)); + if (!constraints->valid_sw_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + for (i = 0; i < ctx->nb_formats; i++) + constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt; + constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE; + } + + constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt)); + if (!constraints->valid_hw_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + err = 0; +fail: + av_freep(&attr_list); + return err; +} + +static const struct { + const char *friendly_name; + const char *match_string; + unsigned int quirks; +} vaapi_driver_quirks_table[] = { + { + "Intel i965 (Quick Sync)", + "i965", + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS, + }, +}; + +static int vaapi_device_init(AVHWDeviceContext *hwdev) +{ + VAAPIDeviceContext *ctx = hwdev->internal->priv; + AVVAAPIDeviceContext *hwctx = hwdev->hwctx; + VAImageFormat *image_list = NULL; + VAStatus vas; + const char *vendor_string; + int err, i, image_count; + enum AVPixelFormat pix_fmt; + unsigned int fourcc; + + image_count = vaMaxNumImageFormats(hwctx->display); + if (image_count <= 0) { + err = AVERROR(EIO); + goto fail; + } + image_list = av_malloc(image_count * sizeof(*image_list)); + if (!image_list) { + err = AVERROR(ENOMEM); + goto fail; + } + vas = vaQueryImageFormats(hwctx->display, image_list, &image_count); + if (vas != VA_STATUS_SUCCESS) { + err = AVERROR(EIO); + goto fail; + } + + ctx->formats = av_malloc(image_count * sizeof(*ctx->formats)); + if (!ctx->formats) { + err = AVERROR(ENOMEM); + goto fail; + } + ctx->nb_formats = 0; + for (i = 0; i < image_count; i++) { + fourcc = image_list[i].fourcc; + pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); + if (pix_fmt == AV_PIX_FMT_NONE) { + av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n", + fourcc); + } else { + av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n", + fourcc, av_get_pix_fmt_name(pix_fmt)); + ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt; + ctx->formats[ctx->nb_formats].image_format = image_list[i]; + ++ctx->nb_formats; + } + } + + if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) { + av_log(hwdev, AV_LOG_VERBOSE, "Not detecting driver: " + "quirks set by user.\n"); + } else { + // Detect the driver in use and set quirk flags if necessary. + vendor_string = vaQueryVendorString(hwctx->display); + hwctx->driver_quirks = 0; + if (vendor_string) { + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) { + if (strstr(vendor_string, + vaapi_driver_quirks_table[i].match_string)) { + av_log(hwdev, AV_LOG_VERBOSE, "Matched \"%s\" as known " + "driver \"%s\".\n", vendor_string, + vaapi_driver_quirks_table[i].friendly_name); + hwctx->driver_quirks |= + vaapi_driver_quirks_table[i].quirks; + break; + } + } + if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) { + av_log(hwdev, AV_LOG_VERBOSE, "Unknown driver \"%s\", " + "assuming standard behaviour.\n", vendor_string); + } + } + } + + av_free(image_list); + return 0; +fail: + av_freep(&ctx->formats); + av_free(image_list); + return err; +} + +static void vaapi_device_uninit(AVHWDeviceContext *hwdev) +{ + VAAPIDeviceContext *ctx = hwdev->internal->priv; + + av_freep(&ctx->formats); +} + +static void vaapi_buffer_free(void *opaque, uint8_t *data) +{ + AVHWFramesContext *hwfc = opaque; + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VASurfaceID surface_id; + VAStatus vas; + + surface_id = (VASurfaceID)(uintptr_t)data; + + vas = vaDestroySurfaces(hwctx->display, &surface_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: " + "%d (%s).\n", surface_id, vas, vaErrorStr(vas)); + } +} + +static AVBufferRef *vaapi_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *hwfc = opaque; + VAAPIFramesContext *ctx = hwfc->internal->priv; + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVVAAPIFramesContext *avfc = hwfc->hwctx; + VASurfaceID surface_id; + VAStatus vas; + AVBufferRef *ref; + + if (hwfc->initial_pool_size > 0 && + avfc->nb_surfaces >= hwfc->initial_pool_size) + return NULL; + + vas = vaCreateSurfaces(hwctx->display, ctx->rt_format, + hwfc->width, hwfc->height, + &surface_id, 1, + ctx->attributes, ctx->nb_attributes); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return NULL; + } + av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id); + + ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id, + sizeof(surface_id), &vaapi_buffer_free, + hwfc, AV_BUFFER_FLAG_READONLY); + if (!ref) { + vaDestroySurfaces(hwctx->display, &surface_id, 1); + return NULL; + } + + if (hwfc->initial_pool_size > 0) { + // This is a fixed-size pool, so we must still be in the initial + // allocation sequence. + av_assert0(avfc->nb_surfaces < hwfc->initial_pool_size); + avfc->surface_ids[avfc->nb_surfaces] = surface_id; + ++avfc->nb_surfaces; + } + + return ref; +} + +static int vaapi_frames_init(AVHWFramesContext *hwfc) +{ + AVVAAPIFramesContext *avfc = hwfc->hwctx; + VAAPIFramesContext *ctx = hwfc->internal->priv; + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAImageFormat *expected_format; + AVBufferRef *test_surface = NULL; + VASurfaceID test_surface_id; + VAImage test_image; + VAStatus vas; + int err, i; + unsigned int fourcc, rt_format; + + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) { + if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) { + fourcc = vaapi_format_map[i].fourcc; + rt_format = vaapi_format_map[i].rt_format; + break; + } + } + if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) { + av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n", + av_get_pix_fmt_name(hwfc->sw_format)); + return AVERROR(EINVAL); + } + + if (!hwfc->pool) { + int need_memory_type = 1, need_pixel_format = 1; + for (i = 0; i < avfc->nb_attributes; i++) { + if (ctx->attributes[i].type == VASurfaceAttribMemoryType) + need_memory_type = 0; + if (ctx->attributes[i].type == VASurfaceAttribPixelFormat) + need_pixel_format = 0; + } + ctx->nb_attributes = + avfc->nb_attributes + need_memory_type + need_pixel_format; + + ctx->attributes = av_malloc(ctx->nb_attributes * + sizeof(*ctx->attributes)); + if (!ctx->attributes) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (i = 0; i < avfc->nb_attributes; i++) + ctx->attributes[i] = avfc->attributes[i]; + if (need_memory_type) { + ctx->attributes[i++] = (VASurfaceAttrib) { + .type = VASurfaceAttribMemoryType, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA, + }; + } + if (need_pixel_format) { + ctx->attributes[i++] = (VASurfaceAttrib) { + .type = VASurfaceAttribPixelFormat, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = fourcc, + }; + } + av_assert0(i == ctx->nb_attributes); + + ctx->rt_format = rt_format; + + if (hwfc->initial_pool_size > 0) { + // This pool will be usable as a render target, so we need to store + // all of the surface IDs somewhere that vaCreateContext() calls + // will be able to access them. + avfc->nb_surfaces = 0; + avfc->surface_ids = av_malloc(hwfc->initial_pool_size * + sizeof(*avfc->surface_ids)); + if (!avfc->surface_ids) { + err = AVERROR(ENOMEM); + goto fail; + } + } else { + // This pool allows dynamic sizing, and will not be usable as a + // render target. + avfc->nb_surfaces = 0; + avfc->surface_ids = NULL; + } + + hwfc->internal->pool_internal = + av_buffer_pool_init2(sizeof(VASurfaceID), hwfc, + &vaapi_pool_alloc, NULL); + if (!hwfc->internal->pool_internal) { + av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + } + + // Allocate a single surface to test whether vaDeriveImage() is going + // to work for the specific configuration. + if (hwfc->pool) { + test_surface = av_buffer_pool_get(hwfc->pool); + if (!test_surface) { + av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " + "user-configured buffer pool.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + } else { + test_surface = av_buffer_pool_get(hwfc->internal->pool_internal); + if (!test_surface) { + av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " + "internal buffer pool.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + } + test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data; + + ctx->derive_works = 0; + + err = vaapi_get_image_format(hwfc->device_ctx, + hwfc->sw_format, &expected_format); + if (err == 0) { + vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image); + if (vas == VA_STATUS_SUCCESS) { + if (expected_format->fourcc == test_image.format.fourcc) { + av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n"); + ctx->derive_works = 1; + } else { + av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " + "derived image format %08x does not match " + "expected format %08x.\n", + expected_format->fourcc, test_image.format.fourcc); + } + vaDestroyImage(hwctx->display, test_image.image_id); + } else { + av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " + "deriving image does not work: " + "%d (%s).\n", vas, vaErrorStr(vas)); + } + } else { + av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " + "image format is not supported.\n"); + } + + av_buffer_unref(&test_surface); + return 0; + +fail: + av_buffer_unref(&test_surface); + av_freep(&avfc->surface_ids); + av_freep(&ctx->attributes); + return err; +} + +static void vaapi_frames_uninit(AVHWFramesContext *hwfc) +{ + AVVAAPIFramesContext *avfc = hwfc->hwctx; + VAAPIFramesContext *ctx = hwfc->internal->priv; + + av_freep(&avfc->surface_ids); + av_freep(&ctx->attributes); +} + +static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(hwfc->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[3] = frame->buf[0]->data; + frame->format = AV_PIX_FMT_VAAPI; + frame->width = hwfc->width; + frame->height = hwfc->height; + + return 0; +} + +static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + VAAPIDeviceContext *ctx = hwfc->device_ctx->internal->priv; + enum AVPixelFormat *pix_fmts, preferred_format; + int i, k; + + preferred_format = hwfc->sw_format; + + pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts)); + if (!pix_fmts) + return AVERROR(ENOMEM); + + pix_fmts[0] = preferred_format; + k = 1; + for (i = 0; i < ctx->nb_formats; i++) { + if (ctx->formats[i].pix_fmt == preferred_format) + continue; + av_assert0(k < ctx->nb_formats); + pix_fmts[k++] = ctx->formats[i].pix_fmt; + } + av_assert0(k == ctx->nb_formats); + pix_fmts[k] = AV_PIX_FMT_NONE; + + *formats = pix_fmts; + return 0; +} + +static void vaapi_unmap_frame(void *opaque, uint8_t *data) +{ + AVHWFramesContext *hwfc = opaque; + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPISurfaceMap *map = (VAAPISurfaceMap*)data; + const AVFrame *src; + VASurfaceID surface_id; + VAStatus vas; + + src = map->source; + surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id); + + vas = vaUnmapBuffer(hwctx->display, map->image.buf); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + } + + if ((map->flags & VAAPI_MAP_WRITE) && + !(map->flags & VAAPI_MAP_DIRECT)) { + vas = vaPutImage(hwctx->display, surface_id, map->image.image_id, + 0, 0, hwfc->width, hwfc->height, + 0, 0, hwfc->width, hwfc->height); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + } + } + + vas = vaDestroyImage(hwctx->display, map->image.image_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + } + + av_free(map); +} + +static int vaapi_map_frame(AVHWFramesContext *hwfc, + AVFrame *dst, const AVFrame *src, int flags) +{ + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPIFramesContext *ctx = hwfc->internal->priv; + VASurfaceID surface_id; + VAImageFormat *image_format; + VAAPISurfaceMap *map; + VAStatus vas; + void *address = NULL; + int err, i; + + surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id); + + if (!ctx->derive_works && (flags & VAAPI_MAP_DIRECT)) { + // Requested direct mapping but it is not possible. + return AVERROR(EINVAL); + } + if (dst->format == AV_PIX_FMT_NONE) + dst->format = hwfc->sw_format; + if (dst->format != hwfc->sw_format && (flags & VAAPI_MAP_DIRECT)) { + // Requested direct mapping but the formats do not match. + return AVERROR(EINVAL); + } + + err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format); + if (err < 0) { + // Requested format is not a valid output format. + return AVERROR(EINVAL); + } + + map = av_malloc(sizeof(VAAPISurfaceMap)); + if (!map) + return AVERROR(ENOMEM); + + map->source = src; + map->flags = flags; + map->image.image_id = VA_INVALID_ID; + + vas = vaSyncSurface(hwctx->display, surface_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + // The memory which we map using derive need not be connected to the CPU + // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the + // memory is mappable but not cached, so normal memcpy()-like access is + // very slow to read it (but writing is ok). It is possible to read much + // faster with a copy routine which is aware of the limitation, but we + // assume for now that the user is not aware of that and would therefore + // prefer not to be given direct-mapped memory if they request read access. + if (ctx->derive_works && + ((flags & VAAPI_MAP_DIRECT) || !(flags & VAAPI_MAP_READ))) { + vas = vaDeriveImage(hwctx->display, surface_id, &map->image); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + if (map->image.format.fourcc != image_format->fourcc) { + av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x " + "is in wrong format: expected %#08x, got %#08x.\n", + surface_id, image_format->fourcc, map->image.format.fourcc); + err = AVERROR(EIO); + goto fail; + } + map->flags |= VAAPI_MAP_DIRECT; + } else { + vas = vaCreateImage(hwctx->display, image_format, + hwfc->width, hwfc->height, &map->image); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to create image for " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + if (flags & VAAPI_MAP_READ) { + vas = vaGetImage(hwctx->display, surface_id, 0, 0, + hwfc->width, hwfc->height, map->image.image_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to read image from " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + } + } + + vas = vaMapBuffer(hwctx->display, map->image.buf, &address); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + dst->width = src->width; + dst->height = src->height; + + for (i = 0; i < map->image.num_planes; i++) { + dst->data[i] = (uint8_t*)address + map->image.offsets[i]; + dst->linesize[i] = map->image.pitches[i]; + } + if ( +#ifdef VA_FOURCC_YV16 + map->image.format.fourcc == VA_FOURCC_YV16 || +#endif + map->image.format.fourcc == VA_FOURCC_YV12) { + // Chroma planes are YVU rather than YUV, so swap them. + FFSWAP(uint8_t*, dst->data[1], dst->data[2]); + } + + dst->buf[0] = av_buffer_create((uint8_t*)map, sizeof(*map), + &vaapi_unmap_frame, hwfc, 0); + if (!dst->buf[0]) { + err = AVERROR(ENOMEM); + goto fail; + } + + return 0; + +fail: + if (map) { + if (address) + vaUnmapBuffer(hwctx->display, map->image.buf); + if (map->image.image_id != VA_INVALID_ID) + vaDestroyImage(hwctx->display, map->image.image_id); + av_free(map); + } + return err; +} + +static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, + AVFrame *dst, const AVFrame *src) +{ + AVFrame *map; + int err; + + if (dst->width > hwfc->width || dst->height > hwfc->height) + return AVERROR(EINVAL); + + map = av_frame_alloc(); + if (!map) + return AVERROR(ENOMEM); + map->format = dst->format; + + err = vaapi_map_frame(hwfc, map, src, VAAPI_MAP_READ); + if (err) + goto fail; + + map->width = dst->width; + map->height = dst->height; + + err = av_frame_copy(dst, map); + if (err) + goto fail; + + err = 0; +fail: + av_frame_free(&map); + return err; +} + +static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, + AVFrame *dst, const AVFrame *src) +{ + AVFrame *map; + int err; + + if (src->width > hwfc->width || src->height > hwfc->height) + return AVERROR(EINVAL); + + map = av_frame_alloc(); + if (!map) + return AVERROR(ENOMEM); + map->format = src->format; + + err = vaapi_map_frame(hwfc, map, dst, VAAPI_MAP_WRITE); + if (err) + goto fail; + + map->width = src->width; + map->height = src->height; + + err = av_frame_copy(map, src); + if (err) + goto fail; + + err = 0; +fail: + av_frame_free(&map); + return err; +} + +static void vaapi_device_free(AVHWDeviceContext *ctx) +{ + AVVAAPIDeviceContext *hwctx = ctx->hwctx; + VAAPIDevicePriv *priv = ctx->user_opaque; + + if (hwctx->display) + vaTerminate(hwctx->display); + +#if HAVE_VAAPI_X11 + if (priv->x11_display) + XCloseDisplay(priv->x11_display); +#endif + + if (priv->drm_fd >= 0) + close(priv->drm_fd); + + av_freep(&priv); +} + +static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVVAAPIDeviceContext *hwctx = ctx->hwctx; + VAAPIDevicePriv *priv; + VADisplay display = 0; + VAStatus vas; + int major, minor; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + priv->drm_fd = -1; + + ctx->user_opaque = priv; + ctx->free = vaapi_device_free; + +#if HAVE_VAAPI_X11 + if (!display && !(device && device[0] == '/')) { + // Try to open the device as an X11 display. + priv->x11_display = XOpenDisplay(device); + if (!priv->x11_display) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display " + "%s.\n", XDisplayName(device)); + } else { + display = vaGetDisplay(priv->x11_display); + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from X11 display %s.\n", XDisplayName(device)); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "X11 display %s.\n", XDisplayName(device)); + } + } +#endif + +#if HAVE_VAAPI_DRM + if (!display) { + // Try to open the device as a DRM path. + // Default to using the first render node if the user did not + // supply a path. + const char *path = device ? device : "/dev/dri/renderD128"; + priv->drm_fd = open(path, O_RDWR); + if (priv->drm_fd < 0) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n", + path); + } else { + display = vaGetDisplayDRM(priv->drm_fd); + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from DRM device %s.\n", path); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "DRM device %s.\n", path); + } + } +#endif + + if (!display) { + av_log(ctx, AV_LOG_ERROR, "No VA display found for " + "device: %s.\n", device ? device : ""); + return AVERROR(EINVAL); + } + + hwctx->display = display; + + vas = vaInitialize(display, &major, &minor); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI " + "connection: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: " + "version %d.%d\n", major, minor); + + return 0; +} + +const HWContextType ff_hwcontext_type_vaapi = { + .type = AV_HWDEVICE_TYPE_VAAPI, + .name = "VAAPI", + + .device_hwctx_size = sizeof(AVVAAPIDeviceContext), + .device_priv_size = sizeof(VAAPIDeviceContext), + .device_hwconfig_size = sizeof(AVVAAPIHWConfig), + .frames_hwctx_size = sizeof(AVVAAPIFramesContext), + .frames_priv_size = sizeof(VAAPIFramesContext), + + .device_create = &vaapi_device_create, + .device_init = &vaapi_device_init, + .device_uninit = &vaapi_device_uninit, + .frames_get_constraints = &vaapi_frames_get_constraints, + .frames_init = &vaapi_frames_init, + .frames_uninit = &vaapi_frames_uninit, + .frames_get_buffer = &vaapi_get_buffer, + .transfer_get_formats = &vaapi_transfer_get_formats, + .transfer_data_to = &vaapi_transfer_data_to, + .transfer_data_from = &vaapi_transfer_data_from, + + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE + }, +}; diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h new file mode 100644 index 0000000..0ac4caa --- /dev/null +++ b/libavutil/hwcontext_vaapi.h @@ -0,0 +1,104 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_VAAPI_H +#define AVUTIL_HWCONTEXT_VAAPI_H + +#include + +/** + * @file + * API-specific header for AV_HWDEVICE_TYPE_VAAPI. + * + * Dynamic frame pools are supported, but note that any pool used as a render + * target is required to be of fixed size in order to be be usable as an + * argument to vaCreateContext(). + * + * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer set to a VASurfaceID. + */ + +enum { + /** + * The quirks field has been set by the user and should not be detected + * automatically by av_hwdevice_ctx_init(). + */ + AV_VAAPI_DRIVER_QUIRK_USER_SET = (1 << 0), + /** + * The driver does not destroy parameter buffers when they are used by + * vaRenderPicture(). Additional code will be required to destroy them + * separately afterwards. + */ + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS = (1 << 1), +}; + +/** + * VAAPI connection details. + * + * Allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVVAAPIDeviceContext { + /** + * The VADisplay handle, to be filled by the user. + */ + VADisplay display; + /** + * Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), + * with reference to a table of known drivers, unless the + * AV_VAAPI_DRIVER_QUIRK_USER_SET bit is already present. The user + * may need to refer to this field when performing any later + * operations using VAAPI with the same VADisplay. + */ + unsigned int driver_quirks; +} AVVAAPIDeviceContext; + +/** + * VAAPI-specific data associated with a frame pool. + * + * Allocated as AVHWFramesContext.hwctx. + */ +typedef struct AVVAAPIFramesContext { + /** + * Set by the user to apply surface attributes to all surfaces in + * the frame pool. If null, default settings are used. + */ + VASurfaceAttrib *attributes; + int nb_attributes; + /** + * The surfaces IDs of all surfaces in the pool after creation. + * Only valid if AVHWFramesContext.initial_pool_size was positive. + * These are intended to be used as the render_targets arguments to + * vaCreateContext(). + */ + VASurfaceID *surface_ids; + int nb_surfaces; +} AVVAAPIFramesContext; + +/** + * VAAPI hardware pipeline configuration details. + * + * Allocated with av_hwdevice_hwconfig_alloc(). + */ +typedef struct AVVAAPIHWConfig { + /** + * ID of a VAAPI pipeline configuration. + */ + VAConfigID config_id; +} AVVAAPIHWConfig; + +#endif /* AVUTIL_HWCONTEXT_VAAPI_H */ diff --git a/libavutil/hwcontext_vdpau.c b/libavutil/hwcontext_vdpau.c new file mode 100644 index 0000000..9722c10 --- /dev/null +++ b/libavutil/hwcontext_vdpau.c @@ -0,0 +1,489 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include + +#include + +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_vdpau.h" +#include "mem.h" +#include "pixfmt.h" +#include "pixdesc.h" + +typedef struct VDPAUDeviceContext { + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *get_transfer_caps; + VdpVideoSurfaceGetBitsYCbCr *get_data; + VdpVideoSurfacePutBitsYCbCr *put_data; + VdpVideoSurfaceCreate *surf_create; + VdpVideoSurfaceDestroy *surf_destroy; + + enum AVPixelFormat *pix_fmts[3]; + int nb_pix_fmts[3]; +} VDPAUDeviceContext; + +typedef struct VDPAUFramesContext { + VdpVideoSurfaceGetBitsYCbCr *get_data; + VdpVideoSurfacePutBitsYCbCr *put_data; + VdpChromaType chroma_type; + int chroma_idx; + + const enum AVPixelFormat *pix_fmts; + int nb_pix_fmts; +} VDPAUFramesContext; + +typedef struct VDPAUPixFmtMap { + VdpYCbCrFormat vdpau_fmt; + enum AVPixelFormat pix_fmt; +} VDPAUPixFmtMap; + +static const VDPAUPixFmtMap pix_fmts_420[] = { + { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV12 }, + { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV420P }, + { 0, AV_PIX_FMT_NONE, }, +}; + +static const VDPAUPixFmtMap pix_fmts_422[] = { + { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV16 }, + { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV422P }, + { VDP_YCBCR_FORMAT_UYVY, AV_PIX_FMT_UYVY422 }, + { VDP_YCBCR_FORMAT_YUYV, AV_PIX_FMT_YUYV422 }, + { 0, AV_PIX_FMT_NONE, }, +}; + +static const VDPAUPixFmtMap pix_fmts_444[] = { + { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV444P }, + { 0, AV_PIX_FMT_NONE, }, +}; + +static const struct { + VdpChromaType chroma_type; + const VDPAUPixFmtMap *map; +} vdpau_pix_fmts[] = { + { VDP_CHROMA_TYPE_420, pix_fmts_420 }, + { VDP_CHROMA_TYPE_422, pix_fmts_422 }, + { VDP_CHROMA_TYPE_444, pix_fmts_444 }, +}; + +static int count_pixfmts(const VDPAUPixFmtMap *map) +{ + int count = 0; + while (map->pix_fmt != AV_PIX_FMT_NONE) { + map++; + count++; + } + return count; +} + +static int vdpau_init_pixmfts(AVHWDeviceContext *ctx) +{ + AVVDPAUDeviceContext *hwctx = ctx->hwctx; + VDPAUDeviceContext *priv = ctx->internal->priv; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(priv->pix_fmts); i++) { + const VDPAUPixFmtMap *map = vdpau_pix_fmts[i].map; + int nb_pix_fmts; + + nb_pix_fmts = count_pixfmts(map); + priv->pix_fmts[i] = av_malloc_array(nb_pix_fmts + 1, sizeof(*priv->pix_fmts[i])); + if (!priv->pix_fmts[i]) + return AVERROR(ENOMEM); + + nb_pix_fmts = 0; + while (map->pix_fmt != AV_PIX_FMT_NONE) { + VdpBool supported; + VdpStatus err = priv->get_transfer_caps(hwctx->device, vdpau_pix_fmts[i].chroma_type, + map->vdpau_fmt, &supported); + if (err == VDP_STATUS_OK && supported) + priv->pix_fmts[i][nb_pix_fmts++] = map->pix_fmt; + map++; + } + priv->pix_fmts[i][nb_pix_fmts++] = AV_PIX_FMT_NONE; + priv->nb_pix_fmts[i] = nb_pix_fmts; + } + + return 0; +} + +static int vdpau_device_init(AVHWDeviceContext *ctx) +{ + AVVDPAUDeviceContext *hwctx = ctx->hwctx; + VDPAUDeviceContext *priv = ctx->internal->priv; + VdpStatus err; + int ret; + +#define GET_CALLBACK(id, result) \ +do { \ + void *tmp; \ + err = hwctx->get_proc_address(hwctx->device, id, &tmp); \ + if (err != VDP_STATUS_OK) { \ + av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n"); \ + return AVERROR_UNKNOWN; \ + } \ + priv->result = tmp; \ +} while (0) + + GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + get_transfer_caps); + GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, get_data); + GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, put_data); + GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_CREATE, surf_create); + GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, surf_destroy); + + ret = vdpau_init_pixmfts(ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error querying the supported pixel formats\n"); + return ret; + } + + return 0; +} + +static void vdpau_device_uninit(AVHWDeviceContext *ctx) +{ + VDPAUDeviceContext *priv = ctx->internal->priv; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(priv->pix_fmts); i++) + av_freep(&priv->pix_fmts[i]); +} + +static void vdpau_buffer_free(void *opaque, uint8_t *data) +{ + AVHWFramesContext *ctx = opaque; + VDPAUDeviceContext *device_priv = ctx->device_ctx->internal->priv; + VdpVideoSurface surf = (VdpVideoSurface)(uintptr_t)data; + + device_priv->surf_destroy(surf); +} + +static AVBufferRef *vdpau_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *ctx = opaque; + VDPAUFramesContext *priv = ctx->internal->priv; + AVVDPAUDeviceContext *device_hwctx = ctx->device_ctx->hwctx; + VDPAUDeviceContext *device_priv = ctx->device_ctx->internal->priv; + + AVBufferRef *ret; + VdpVideoSurface surf; + VdpStatus err; + + err = device_priv->surf_create(device_hwctx->device, priv->chroma_type, + ctx->width, ctx->height, &surf); + if (err != VDP_STATUS_OK) { + av_log(ctx, AV_LOG_ERROR, "Error allocating a VDPAU video surface\n"); + return NULL; + } + + ret = av_buffer_create((uint8_t*)(uintptr_t)surf, sizeof(surf), + vdpau_buffer_free, ctx, AV_BUFFER_FLAG_READONLY); + if (!ret) { + device_priv->surf_destroy(surf); + return NULL; + } + + return ret; +} + +static int vdpau_frames_init(AVHWFramesContext *ctx) +{ + VDPAUDeviceContext *device_priv = ctx->device_ctx->internal->priv; + VDPAUFramesContext *priv = ctx->internal->priv; + + int i; + + switch (ctx->sw_format) { + case AV_PIX_FMT_YUV420P: priv->chroma_type = VDP_CHROMA_TYPE_420; break; + case AV_PIX_FMT_YUV422P: priv->chroma_type = VDP_CHROMA_TYPE_422; break; + case AV_PIX_FMT_YUV444P: priv->chroma_type = VDP_CHROMA_TYPE_444; break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported data layout: %s\n", + av_get_pix_fmt_name(ctx->sw_format)); + return AVERROR(ENOSYS); + } + + for (i = 0; i < FF_ARRAY_ELEMS(vdpau_pix_fmts); i++) { + if (vdpau_pix_fmts[i].chroma_type == priv->chroma_type) { + priv->chroma_idx = i; + priv->pix_fmts = device_priv->pix_fmts[i]; + priv->nb_pix_fmts = device_priv->nb_pix_fmts[i]; + break; + } + } + if (!priv->pix_fmts) { + av_log(ctx, AV_LOG_ERROR, "Unsupported chroma type: %d\n", priv->chroma_type); + return AVERROR(ENOSYS); + } + + if (!ctx->pool) { + ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(VdpVideoSurface), ctx, + vdpau_pool_alloc, NULL); + if (!ctx->internal->pool_internal) + return AVERROR(ENOMEM); + } + + priv->get_data = device_priv->get_data; + priv->put_data = device_priv->put_data; + + return 0; +} + +static int vdpau_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[3] = frame->buf[0]->data; + frame->format = AV_PIX_FMT_VDPAU; + frame->width = ctx->width; + frame->height = ctx->height; + + return 0; +} + +static int vdpau_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + VDPAUFramesContext *priv = ctx->internal->priv; + + enum AVPixelFormat *fmts; + + if (priv->nb_pix_fmts == 1) { + av_log(ctx, AV_LOG_ERROR, + "No target formats are supported for this chroma type\n"); + return AVERROR(ENOSYS); + } + + fmts = av_malloc_array(priv->nb_pix_fmts, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + memcpy(fmts, priv->pix_fmts, sizeof(*fmts) * (priv->nb_pix_fmts)); + *formats = fmts; + + return 0; +} + +static int vdpau_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + VDPAUFramesContext *priv = ctx->internal->priv; + VdpVideoSurface surf = (VdpVideoSurface)(uintptr_t)src->data[3]; + + void *data[3]; + uint32_t linesize[3]; + + const VDPAUPixFmtMap *map; + VdpYCbCrFormat vdpau_format; + VdpStatus err; + int i; + + for (i = 0; i< FF_ARRAY_ELEMS(data) && dst->data[i]; i++) { + data[i] = dst->data[i]; + if (dst->linesize[i] < 0 || (uint64_t)dst->linesize > UINT32_MAX) { + av_log(ctx, AV_LOG_ERROR, + "The linesize %d cannot be represented as uint32\n", + dst->linesize[i]); + return AVERROR(ERANGE); + } + linesize[i] = dst->linesize[i]; + } + + map = vdpau_pix_fmts[priv->chroma_idx].map; + for (i = 0; map[i].pix_fmt != AV_PIX_FMT_NONE; i++) { + if (map[i].pix_fmt == dst->format) { + vdpau_format = map[i].vdpau_fmt; + break; + } + } + if (map[i].pix_fmt == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, + "Unsupported target pixel format: %s\n", + av_get_pix_fmt_name(dst->format)); + return AVERROR(EINVAL); + } + + if (vdpau_format == VDP_YCBCR_FORMAT_YV12) + FFSWAP(void*, data[1], data[2]); + + err = priv->get_data(surf, vdpau_format, data, linesize); + if (err != VDP_STATUS_OK) { + av_log(ctx, AV_LOG_ERROR, "Error retrieving the data from a VDPAU surface\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int vdpau_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + VDPAUFramesContext *priv = ctx->internal->priv; + VdpVideoSurface surf = (VdpVideoSurface)(uintptr_t)dst->data[3]; + + const void *data[3]; + uint32_t linesize[3]; + + const VDPAUPixFmtMap *map; + VdpYCbCrFormat vdpau_format; + VdpStatus err; + int i; + + for (i = 0; i< FF_ARRAY_ELEMS(data) && src->data[i]; i++) { + data[i] = src->data[i]; + if (src->linesize[i] < 0 || (uint64_t)src->linesize > UINT32_MAX) { + av_log(ctx, AV_LOG_ERROR, + "The linesize %d cannot be represented as uint32\n", + src->linesize[i]); + return AVERROR(ERANGE); + } + linesize[i] = src->linesize[i]; + } + + map = vdpau_pix_fmts[priv->chroma_idx].map; + for (i = 0; map[i].pix_fmt != AV_PIX_FMT_NONE; i++) { + if (map[i].pix_fmt == src->format) { + vdpau_format = map[i].vdpau_fmt; + break; + } + } + if (map[i].pix_fmt == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, + "Unsupported source pixel format: %s\n", + av_get_pix_fmt_name(src->format)); + return AVERROR(EINVAL); + } + + if (vdpau_format == VDP_YCBCR_FORMAT_YV12) + FFSWAP(const void*, data[1], data[2]); + + err = priv->put_data(surf, vdpau_format, data, linesize); + if (err != VDP_STATUS_OK) { + av_log(ctx, AV_LOG_ERROR, "Error uploading the data to a VDPAU surface\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +#if HAVE_VDPAU_X11 +#include +#include + +typedef struct VDPAUDevicePriv { + VdpDeviceDestroy *device_destroy; + Display *dpy; +} VDPAUDevicePriv; + +static void vdpau_device_free(AVHWDeviceContext *ctx) +{ + AVVDPAUDeviceContext *hwctx = ctx->hwctx; + VDPAUDevicePriv *priv = ctx->user_opaque; + + if (priv->device_destroy) + priv->device_destroy(hwctx->device); + if (priv->dpy) + XCloseDisplay(priv->dpy); + av_freep(&priv); +} + +static int vdpau_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVVDPAUDeviceContext *hwctx = ctx->hwctx; + + VDPAUDevicePriv *priv; + VdpStatus err; + VdpGetInformationString *get_information_string; + const char *display, *vendor; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + ctx->user_opaque = priv; + ctx->free = vdpau_device_free; + + priv->dpy = XOpenDisplay(device); + if (!priv->dpy) { + av_log(ctx, AV_LOG_ERROR, "Cannot open the X11 display %s.\n", + XDisplayName(device)); + return AVERROR_UNKNOWN; + } + display = XDisplayString(priv->dpy); + + err = vdp_device_create_x11(priv->dpy, XDefaultScreen(priv->dpy), + &hwctx->device, &hwctx->get_proc_address); + if (err != VDP_STATUS_OK) { + av_log(ctx, AV_LOG_ERROR, "VDPAU device creation on X11 display %s failed.\n", + display); + return AVERROR_UNKNOWN; + } + +#define GET_CALLBACK(id, result) \ +do { \ + void *tmp; \ + err = hwctx->get_proc_address(hwctx->device, id, &tmp); \ + if (err != VDP_STATUS_OK) { \ + av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n"); \ + return AVERROR_UNKNOWN; \ + } \ + result = tmp; \ +} while (0) + + GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string); + GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, priv->device_destroy); + + get_information_string(&vendor); + av_log(ctx, AV_LOG_VERBOSE, "Successfully created a VDPAU device (%s) on " + "X11 display %s\n", vendor, display); + + return 0; +} +#endif + +const HWContextType ff_hwcontext_type_vdpau = { + .type = AV_HWDEVICE_TYPE_VDPAU, + .name = "VDPAU", + + .device_hwctx_size = sizeof(AVVDPAUDeviceContext), + .device_priv_size = sizeof(VDPAUDeviceContext), + .frames_priv_size = sizeof(VDPAUFramesContext), + +#if HAVE_VDPAU_X11 + .device_create = vdpau_device_create, +#endif + .device_init = vdpau_device_init, + .device_uninit = vdpau_device_uninit, + .frames_init = vdpau_frames_init, + .frames_get_buffer = vdpau_get_buffer, + .transfer_get_formats = vdpau_transfer_get_formats, + .transfer_data_to = vdpau_transfer_data_to, + .transfer_data_from = vdpau_transfer_data_from, + + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU, AV_PIX_FMT_NONE }, +}; diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h new file mode 100644 index 0000000..358e942 --- /dev/null +++ b/libavutil/hwcontext_vdpau.h @@ -0,0 +1,44 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_VDPAU_H +#define AVUTIL_HWCONTEXT_VDPAU_H + +#include + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_VDPAU. + * + * This API supports dynamic frame pools. AVHWFramesContext.pool must return + * AVBufferRefs whose data pointer is a VdpVideoSurface. + */ + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVVDPAUDeviceContext { + VdpDevice device; + VdpGetProcAddress *get_proc_address; +} AVVDPAUDeviceContext; + +/** + * AVHWFramesContext.hwctx is currently not used + */ + +#endif /* AVUTIL_HWCONTEXT_VDPAU_H */ diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index fc367d9..6c58139 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -24,6 +24,7 @@ #include "common.h" #include "imgutils.h" #include "internal.h" +#include "intreadwrite.h" #include "log.h" #include "mathematics.h" #include "pixdesc.h" @@ -39,8 +40,8 @@ void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], for (i = 0; i < 4; i++) { const AVComponentDescriptor *comp = &(pixdesc->comp[i]); - if ((comp->step_minus1+1) > max_pixsteps[comp->plane]) { - max_pixsteps[comp->plane] = comp->step_minus1+1; + if (comp->step > max_pixsteps[comp->plane]) { + max_pixsteps[comp->plane] = comp->step; if (max_pixstep_comps) max_pixstep_comps[comp->plane] = i; } @@ -58,7 +59,7 @@ int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane) return AVERROR(EINVAL); if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) - return (width * (desc->comp[0].step_minus1+1) + 7) >> 3; + return (width * desc->comp[0].step + 7) >> 3; av_image_fill_max_pixsteps(max_step, max_step_comp, desc); s = (max_step_comp[plane] == 1 || max_step_comp[plane] == 2) ? desc->log2_chroma_w : 0; @@ -78,9 +79,9 @@ int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int wi return AVERROR(EINVAL); if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) { - if (width > (INT_MAX -7) / (desc->comp[0].step_minus1+1)) + if (width > (INT_MAX - 7) / desc->comp[0].step) return AVERROR(EINVAL); - linesizes[0] = (width * (desc->comp[0].step_minus1+1) + 7) >> 3; + linesizes[0] = (width * desc->comp[0].step + 7) >> 3; return 0; } @@ -290,7 +291,7 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], int h = height; int bwidth = av_image_get_linesize(pix_fmt, width, i); if (i == 1 || i == 2) { - h= -((-height)>>desc->log2_chroma_h); + h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); } av_image_copy_plane(dst_data[i], dst_linesizes[i], src_data[i], src_linesizes[i], @@ -298,3 +299,83 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], } } } + +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, enum AVPixelFormat pix_fmt, + int width, int height, int align) +{ + int ret, i; + + ret = av_image_check_size(width, height, 0, NULL); + if (ret < 0) + return ret; + + ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width); + if (ret < 0) + return ret; + + for (i = 0; i < 4; i++) + dst_linesize[i] = FFALIGN(dst_linesize[i], align); + + return av_image_fill_pointers(dst_data, pix_fmt, height, src, dst_linesize); +} + +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, + int width, int height, int align) +{ + uint8_t *data[4]; + int linesize[4]; + int ret; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + if (!desc) + return AVERROR_BUG; + + ret = av_image_check_size(width, height, 0, NULL); + if (ret < 0) + return ret; + + // do not include palette for these pseudo-paletted formats + if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + return width * height; + + return av_image_fill_arrays(data, linesize, NULL, pix_fmt, + width, height, align); +} + +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], + const int src_linesize[4], + enum AVPixelFormat pix_fmt, + int width, int height, int align) +{ + int i, j, nb_planes = 0, linesize[4]; + int size = av_image_get_buffer_size(pix_fmt, width, height, align); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + + if (size > dst_size || size < 0 || !desc) + return AVERROR(EINVAL); + + for (i = 0; i < desc->nb_components; i++) + nb_planes = FFMAX(desc->comp[i].plane, nb_planes); + + nb_planes++; + + av_image_fill_linesizes(linesize, pix_fmt, width); + for (i = 0; i < nb_planes; i++) { + int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + const uint8_t *src = src_data[i]; + h = (height + (1 << shift) - 1) >> shift; + + for (j = 0; j < h; j++) { + memcpy(dst, src, linesize[i]); + dst += FFALIGN(linesize[i], align); + src += src_linesize[i]; + } + } + + if (desc->flags & AV_PIX_FMT_FLAG_PAL) + memcpy((unsigned char *)(((size_t)dst + 3) & ~3), + src_data[1], 256 * 4); + + return size; +} diff --git a/libavutil/imgutils.h b/libavutil/imgutils.h index 50fa815..04d6138 100644 --- a/libavutil/imgutils.h +++ b/libavutil/imgutils.h @@ -118,6 +118,65 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height); /** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesizes linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param[in] align the assumed linesize alignment + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** * Check if the given dimension of an image is valid, meaning that all * bytes of the image can be addressed with a signed int. * diff --git a/libavutil/internal.h b/libavutil/internal.h index aed9925..d96762c 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -37,6 +37,7 @@ #include "config.h" #include "attributes.h" #include "dict.h" +#include "macros.h" #include "pixfmt.h" #if ARCH_X86 @@ -77,10 +78,6 @@ # define FF_ENABLE_DEPRECATION_WARNINGS #endif -#ifndef INT_BIT -# define INT_BIT (CHAR_BIT * sizeof(int)) -#endif - // Some broken preprocessors need a second expansion // to be forced to tokenize __VA_ARGS__ #define E1(x) x @@ -114,6 +111,12 @@ # define LOCAL_ALIGNED_16(t, v, ...) LOCAL_ALIGNED(16, t, v, __VA_ARGS__) #endif +#if HAVE_LOCAL_ALIGNED_32 +# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_D(32, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_32(t, v, ...) LOCAL_ALIGNED(32, t, v, __VA_ARGS__) +#endif + #define FF_ALLOC_OR_GOTO(ctx, p, size, label)\ {\ p = av_malloc(size);\ @@ -134,11 +137,6 @@ #include "libm.h" -#if defined(_MSC_VER) -#pragma comment(linker, "/include:"EXTERN_PREFIX"avpriv_strtod") -#pragma comment(linker, "/include:"EXTERN_PREFIX"avpriv_snprintf") -#endif - /** * Return NULL if CONFIG_SMALL is true, otherwise the argument * without modification. Used to disable the definition of strings @@ -212,6 +210,12 @@ void avpriv_request_sample(void *avc, const char *msg, ...) av_printf_format(2, 3); #if HAVE_LIBC_MSVCRT +#include +#if defined(_VC_CRT_MAJOR_VERSION) && _VC_CRT_MAJOR_VERSION < 14 +#pragma comment(linker, "/include:"EXTERN_PREFIX"avpriv_strtod") +#pragma comment(linker, "/include:"EXTERN_PREFIX"avpriv_snprintf") +#endif + #define avpriv_open ff_open #endif diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index f77fd60..fdb91d6 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -197,6 +197,11 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; # define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) # define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) +#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64)) && AV_HAVE_FAST_UNALIGNED + +# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) +# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) + #elif AV_HAVE_FAST_UNALIGNED # define AV_RN(s, p) (((const av_alias##s*)(p))->u##s) @@ -210,7 +215,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[1]) #endif #ifndef AV_WB16 -# define AV_WB16(p, d) do { \ +# define AV_WB16(p, val) do { \ + uint16_t d = val; \ ((uint8_t*)(p))[1] = (d); \ ((uint8_t*)(p))[0] = (d)>>8; \ } while(0) @@ -222,7 +228,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[0]) #endif #ifndef AV_WL16 -# define AV_WL16(p, d) do { \ +# define AV_WL16(p, val) do { \ + uint16_t d = val; \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ } while(0) @@ -236,7 +243,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[3]) #endif #ifndef AV_WB32 -# define AV_WB32(p, d) do { \ +# define AV_WB32(p, val) do { \ + uint32_t d = val; \ ((uint8_t*)(p))[3] = (d); \ ((uint8_t*)(p))[2] = (d)>>8; \ ((uint8_t*)(p))[1] = (d)>>16; \ @@ -252,7 +260,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[0]) #endif #ifndef AV_WL32 -# define AV_WL32(p, d) do { \ +# define AV_WL32(p, val) do { \ + uint32_t d = val; \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ ((uint8_t*)(p))[2] = (d)>>16; \ @@ -272,7 +281,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; (uint64_t)((const uint8_t*)(x))[7]) #endif #ifndef AV_WB64 -# define AV_WB64(p, d) do { \ +# define AV_WB64(p, val) do { \ + uint64_t d = val; \ ((uint8_t*)(p))[7] = (d); \ ((uint8_t*)(p))[6] = (d)>>8; \ ((uint8_t*)(p))[5] = (d)>>16; \ @@ -296,7 +306,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; (uint64_t)((const uint8_t*)(x))[0]) #endif #ifndef AV_WL64 -# define AV_WL64(p, d) do { \ +# define AV_WL64(p, val) do { \ + uint64_t d = val; \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ ((uint8_t*)(p))[2] = (d)>>16; \ diff --git a/libavutil/lfg.c b/libavutil/lfg.c index 4221e62..2090057 100644 --- a/libavutil/lfg.c +++ b/libavutil/lfg.c @@ -58,43 +58,3 @@ void av_bmg_get(AVLFG *lfg, double out[2]) out[0] = x1 * w; out[1] = x2 * w; } - -#ifdef TEST -#include "log.h" -#include "timer.h" - -int main(void) -{ - int x = 0; - int i, j; - AVLFG state; - - av_lfg_init(&state, 0xdeadbeef); - for (j = 0; j < 10000; j++) { - START_TIMER - for (i = 0; i < 624; i++) - x += av_lfg_get(&state); - STOP_TIMER("624 calls of av_lfg_get"); - } - av_log(NULL, AV_LOG_ERROR, "final value:%X\n", x); - - /* BMG usage example */ - { - double mean = 1000; - double stddev = 53; - - av_lfg_init(&state, 42); - - for (i = 0; i < 1000; i += 2) { - double bmg_out[2]; - av_bmg_get(&state, bmg_out); - av_log(NULL, AV_LOG_INFO, - "%f\n%f\n", - bmg_out[0] * stddev + mean, - bmg_out[1] * stddev + mean); - } - } - - return 0; -} -#endif diff --git a/libavutil/libavutil.v b/libavutil/libavutil.v index e9f04cb..fb17058 100644 --- a/libavutil/libavutil.v +++ b/libavutil/libavutil.v @@ -1,4 +1,6 @@ -LIBAVUTIL_$MAJOR { - global: av*; - local: *; +LIBAVUTIL_MAJOR { + global: + av*; + local: + *; }; diff --git a/libavutil/lls.c b/libavutil/lls.c index f87c2cd..97bffb4 100644 --- a/libavutil/lls.c +++ b/libavutil/lls.c @@ -29,6 +29,7 @@ #include #include "attributes.h" +#include "internal.h" #include "version.h" #include "lls.h" @@ -120,60 +121,3 @@ av_cold void avpriv_init_lls(LLSModel *m, int indep_count) if (ARCH_X86) ff_init_lls_x86(m); } - -#if FF_API_LLS_PRIVATE -av_cold void av_init_lls(LLSModel *m, int indep_count) -{ - avpriv_init_lls(m, indep_count); -} -void av_update_lls(LLSModel *m, double *param, double decay) -{ - m->update_lls(m, param); -} -void av_solve_lls(LLSModel *m, double threshold, int min_order) -{ - avpriv_solve_lls(m, threshold, min_order); -} -double av_evaluate_lls(LLSModel *m, double *param, int order) -{ - return m->evaluate_lls(m, param, order); -} -#endif /* FF_API_LLS_PRIVATE */ - -#ifdef TEST - -#include -#include -#include "lfg.h" - -int main(void) -{ - LLSModel m; - int i, order; - AVLFG lfg; - - av_lfg_init(&lfg, 1); - avpriv_init_lls(&m, 3); - - for (i = 0; i < 100; i++) { - LOCAL_ALIGNED(32, double, var, [4]); - double eval; - - var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2; - var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; - var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; - var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; - m.update_lls(&m, var); - avpriv_solve_lls(&m, 0.001, 0); - for (order = 0; order < 3; order++) { - eval = m.evaluate_lls(&m, var + 1, order); - printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\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/libavutil/lls.h b/libavutil/lls.h index 27c0d5e..3977e97 100644 --- a/libavutil/lls.h +++ b/libavutil/lls.h @@ -23,7 +23,7 @@ #ifndef AVUTIL_LLS_H #define AVUTIL_LLS_H -#include "common.h" +#include "macros.h" #include "mem.h" #include "version.h" @@ -61,11 +61,4 @@ void avpriv_init_lls(LLSModel *m, int indep_count); void ff_init_lls_x86(LLSModel *m); void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order); -#if FF_API_LLS_PRIVATE -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 /* FF_API_LLS_PRIVATE */ - #endif /* AVUTIL_LLS_H */ diff --git a/libavutil/log.c b/libavutil/log.c index d38e40b..37427ef 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -40,19 +40,28 @@ #include "internal.h" #include "log.h" +#if HAVE_VALGRIND_VALGRIND_H +#include +/* this is the log level at which valgrind will output a full backtrace */ +#define BACKTRACE_LOGLEVEL AV_LOG_ERROR +#endif + static int av_log_level = AV_LOG_INFO; static int flags; +#define NB_LEVELS 8 #if HAVE_SETCONSOLETEXTATTRIBUTE #include -static const uint8_t color[] = { 12, 12, 12, 14, 7, 10, 11 }; +static const uint8_t color[NB_LEVELS] = { 12, 12, 12, 14, 7, 10, 11, 8}; static int16_t background, attr_orig; static HANDLE con; #define set_color(x) SetConsoleTextAttribute(con, background | color[x]) #define reset_color() SetConsoleTextAttribute(con, attr_orig) #define print_256color(x) #else -static const uint8_t color[] = { 0x41, 0x41, 0x11, 0x03, 9, 0x02, 0x06 }; +static const uint8_t color[NB_LEVELS] = { + 0x41, 0x41, 0x11, 0x03, 9, 0x02, 0x06, 0x07 +}; #define set_color(x) fprintf(stderr, "\033[%d;3%dm", color[x] >> 4, color[x]&15) #define print_256color(x) fprintf(stderr, "\033[38;5;%dm", x) #define reset_color() fprintf(stderr, "\033[0m") @@ -159,8 +168,13 @@ void av_log_default_callback(void *avcl, int level, const char *fmt, va_list vl) fprintf(stderr, " Last message repeated %d times\n", count); count = 0; } - colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, line); + colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, line); av_strlcpy(prev, line, sizeof line); + +#if CONFIG_VALGRIND_BACKTRACE + if (level <= BACKTRACE_LOGLEVEL) + VALGRIND_PRINTF_BACKTRACE(""); +#endif } static void (*av_log_callback)(void*, int, const char*, va_list) = diff --git a/libavutil/log.h b/libavutil/log.h index 4e4424a..d4daea9 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -24,6 +24,7 @@ #include #include "avutil.h" #include "attributes.h" +#include "version.h" /** * Describe the class of an AVClass context structure. That is an @@ -144,6 +145,11 @@ typedef struct AVClass { #define AV_LOG_DEBUG 48 /** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +/** * @} */ @@ -243,8 +249,10 @@ void av_log_default_callback(void *avcl, int level, const char *fmt, */ const char* av_default_item_name(void* ctx); +#if FF_API_DLOG /** * av_dlog macros + * @deprecated unused * Useful to print debug messages that shouldn't get compiled in normally. */ @@ -253,6 +261,7 @@ const char* av_default_item_name(void* ctx); #else # define av_dlog(pctx, ...) #endif +#endif /* FF_API_DLOG */ /** * Skip repeated messages, this requires the user app to use av_log() instead of diff --git a/libavutil/macros.h b/libavutil/macros.h index bf3eb9b..3e7b005 100644 --- a/libavutil/macros.h +++ b/libavutil/macros.h @@ -45,4 +45,6 @@ #define AV_PRAGMA(s) _Pragma(#s) +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + #endif /* AVUTIL_MACROS_H */ diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index f36623a..617726d 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -29,27 +29,6 @@ #include "mathematics.h" #include "version.h" -#if FF_API_AV_REVERSE -const uint8_t av_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, -}; -#endif - int64_t av_gcd(int64_t a, int64_t b) { if (b) @@ -79,7 +58,6 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) 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; @@ -103,14 +81,6 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) } 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) diff --git a/libavutil/md5.c b/libavutil/md5.c index efb993e..94f0681 100644 --- a/libavutil/md5.c +++ b/libavutil/md5.c @@ -8,7 +8,7 @@ * * 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. + * 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. @@ -31,21 +31,18 @@ */ #include + #include "bswap.h" #include "intreadwrite.h" -#include "md5.h" #include "mem.h" +#include "md5.h" -typedef struct AVMD5{ +typedef struct AVMD5 { uint64_t len; uint8_t block[64]; uint32_t ABCD[4]; } AVMD5; -#if FF_API_CONTEXT_SIZE -const int av_md5_size = sizeof(AVMD5); -#endif - struct AVMD5 *av_md5_alloc(void) { return av_mallocz(sizeof(struct AVMD5)); @@ -80,16 +77,21 @@ static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32) 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; -#define CORE(i, a, b, c, d) do { \ - t = S[i >> 4][i & 3]; \ +#define CORE(i, a, b, c, d) \ + do { \ + t = S[i >> 4][i & 3]; \ a += T[i]; \ \ if (i < 32) { \ - if (i < 16) a += (d ^ (b & (c ^ d))) + X[ i & 15]; \ - else a += (c ^ (d & (c ^ b))) + X[(1 + 5*i) & 15]; \ + if (i < 16) \ + a += (d ^ (b & (c ^ d))) + X[i & 15]; \ + else \ + a += (c ^ (d & (c ^ b))) + X[(1 + 5 * i) & 15]; \ } else { \ - if (i < 48) a += (b ^ c ^ d) + X[(5 + 3*i) & 15]; \ - else a += (c ^ (b | ~d)) + X[( 7*i) & 15]; \ + if (i < 48) \ + a += (b ^ c ^ d) + X[(5 + 3 * i) & 15]; \ + else \ + a += (c ^ (b | ~d)) + X[(7 * i) & 15]; \ } \ a = b + (a << t | a >> (32 - t)); \ } while (0) @@ -119,10 +121,13 @@ static void body(uint32_t ABCD[4], uint32_t X[16]) } #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); + 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; @@ -145,7 +150,7 @@ void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len) { int i, j; - j = ctx->len & 63; + j = ctx->len & 63; ctx->len += len; for (i = 0; i < len; i++) { @@ -166,10 +171,10 @@ void av_md5_final(AVMD5 *ctx, uint8_t *dst) while ((ctx->len & 63) != 56) av_md5_update(ctx, "", 1); - av_md5_update(ctx, (uint8_t *)&finalcount, 8); + av_md5_update(ctx, (uint8_t *) &finalcount, 8); for (i = 0; i < 4; i++) - AV_WL32(dst + 4*i, ctx->ABCD[3 - i]); + AV_WL32(dst + 4 * i, ctx->ABCD[3 - i]); } void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len) @@ -180,33 +185,3 @@ void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len) av_md5_update(&ctx, src, len); av_md5_final(&ctx, dst); } - -#ifdef TEST -#include - -static void print_md5(uint8_t *md5) -{ - int i; - for (i = 0; i < 16; i++) - printf("%02x", md5[i]); - printf("\n"); -} - -int main(void){ - uint8_t md5val[16]; - int i; - uint8_t in[1000]; - - for (i = 0; i < 1000; i++) - in[i] = i * i; - av_md5_sum(md5val, in, 1000); print_md5(md5val); - av_md5_sum(md5val, in, 63); print_md5(md5val); - av_md5_sum(md5val, in, 64); print_md5(md5val); - av_md5_sum(md5val, in, 65); print_md5(md5val); - for (i = 0; i < 1000; i++) - in[i] = i % 127; - av_md5_sum(md5val, in, 999); print_md5(md5val); - - return 0; -} -#endif diff --git a/libavutil/md5.h b/libavutil/md5.h index 29e4e7c..c26318c 100644 --- a/libavutil/md5.h +++ b/libavutil/md5.h @@ -32,10 +32,6 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_md5_size; -#endif - struct AVMD5; struct AVMD5 *av_md5_alloc(void); diff --git a/libavutil/mem.c b/libavutil/mem.c index b7bb65c..15c2880 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -139,21 +139,22 @@ void *av_realloc(void *ptr, size_t size) int av_reallocp(void *ptr, size_t size) { - void **ptrptr = ptr; - void *ret; + void *val; if (!size) { av_freep(ptr); return 0; } - ret = av_realloc(*ptrptr, size); - if (!ret) { + memcpy(&val, ptr, sizeof(val)); + val = av_realloc(val, size); + + if (!val) { av_freep(ptr); return AVERROR(ENOMEM); } - *ptrptr = ret; + memcpy(ptr, &val, sizeof(val)); return 0; } @@ -166,20 +167,23 @@ void *av_realloc_array(void *ptr, size_t nmemb, size_t size) int av_reallocp_array(void *ptr, size_t nmemb, size_t size) { - void **ptrptr = ptr; - void *ret; + void *val; + if (!size || nmemb >= INT_MAX / size) return AVERROR(ENOMEM); if (!nmemb) { av_freep(ptr); return 0; } - ret = av_realloc(*ptrptr, nmemb * size); - if (!ret) { + + memcpy(&val, ptr, sizeof(val)); + val = av_realloc(val, nmemb * size); + if (!val) { av_freep(ptr); return AVERROR(ENOMEM); } - *ptrptr = ret; + + memcpy(ptr, &val, sizeof(val)); return 0; } @@ -197,9 +201,11 @@ void av_free(void *ptr) void av_freep(void *arg) { - void **ptr = (void **)arg; - av_free(*ptr); - *ptr = NULL; + void *val; + + memcpy(&val, arg, sizeof(val)); + memcpy(arg, &(void *){ NULL }, sizeof(val)); + av_free(val); } void *av_mallocz(size_t size) diff --git a/libavutil/mem.h b/libavutil/mem.h index 9f667c2..f3cf56c 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -48,7 +48,7 @@ #define DECLARE_ASM_CONST(n,t,v) \ AV_PRAGMA(DATA_ALIGN(v,n)) \ static const t __attribute__((aligned(n))) v -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__clang__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v #elif defined(_MSC_VER) diff --git a/libavutil/old_pix_fmts.h b/libavutil/old_pix_fmts.h deleted file mode 100644 index d3e1e5b..0000000 --- a/libavutil/old_pix_fmts.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_OLD_PIX_FMTS_H -#define AVUTIL_OLD_PIX_FMTS_H - -/* - * This header exists to prevent new pixel formats from being accidentally added - * to the deprecated list. - * Do not include it directly. It will be removed on next major bump - * - * Do not add new items to this list. Use the AVPixelFormat enum instead. - */ - PIX_FMT_NONE = AV_PIX_FMT_NONE, - 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_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_GRAY8, ///< Y , 8bpp - PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb - PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb - PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette - PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range - PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range - PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range -#if FF_API_XVMC - PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing - PIX_FMT_XVMC_MPEG2_IDCT, -#endif /* FF_API_XVMC */ - 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_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) - PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits - 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 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits - PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) - PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) - PIX_FMT_NV21, ///< as above, but U and V bytes are swapped - - PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... - PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... - PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... - PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... - - PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian - PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian - PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) - PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range - PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) -#if FF_API_VDPAU - PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers -#endif - PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian - PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian - - PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian - PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian - PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0 - PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0 - - PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian - PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian - PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 - PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 - - PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers - PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers - PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - - PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian - PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian - PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian - PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian - PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian - PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian -#if FF_API_VDPAU - PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers -#endif - PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer - - PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 - PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 - PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 - PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 - PIX_FMT_Y400A, ///< 8bit gray, 8bit alpha - PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian - PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian - PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian - PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian - PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian - PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian - PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian - PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian - PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian - PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian - PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian - PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian - PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian - PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian - PIX_FMT_VDA_VLD, ///< hardware decoding through VDA - PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp - PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian - PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian - PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian - PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian - PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian - PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, 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 - -#endif /* AVUTIL_OLD_PIX_FMTS_H */ diff --git a/libavutil/opt.c b/libavutil/opt.c index 059c525..7cb3d66 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -25,18 +25,18 @@ * @author Michael Niedermayer */ -#include "avutil.h" #include "avstring.h" +#include "avutil.h" #include "common.h" -#include "opt.h" -#include "eval.h" #include "dict.h" +#include "eval.h" #include "log.h" #include "mathematics.h" +#include "opt.h" -const AVOption *av_opt_next(void *obj, const AVOption *last) +const AVOption *av_opt_next(const void *obj, const AVOption *last) { - AVClass *class = *(AVClass**)obj; + AVClass *class = *(AVClass **)obj; if (!last && class->option && class->option[0].name) return class->option; if (last && last[1].name) @@ -44,17 +44,28 @@ const AVOption *av_opt_next(void *obj, const AVOption *last) return NULL; } -static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum) +static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum) { switch (o->type) { - case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0; - case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0; - case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0; - case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0; - case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0; - case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num; - *den = ((AVRational*)dst)->den; - return 0; + case AV_OPT_TYPE_FLAGS: + *intnum = *(unsigned int *)dst; + return 0; + case AV_OPT_TYPE_INT: + *intnum = *(int *)dst; + return 0; + case AV_OPT_TYPE_INT64: + *intnum = *(int64_t *)dst; + return 0; + case AV_OPT_TYPE_FLOAT: + *num = *(float *)dst; + return 0; + case AV_OPT_TYPE_DOUBLE: + *num = *(double *)dst; + return 0; + case AV_OPT_TYPE_RATIONAL: + *intnum = ((AVRational *)dst)->num; + *den = ((AVRational *)dst)->den; + return 0; } return AVERROR(EINVAL); } @@ -64,19 +75,29 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int if (o->type != AV_OPT_TYPE_FLAGS && (o->max * den < num * intnum || o->min * den > num * intnum)) { av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n", - num*intnum/den, o->name); + num * intnum / den, o->name); return AVERROR(ERANGE); } switch (o->type) { case AV_OPT_TYPE_FLAGS: - case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break; - case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break; - case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break; - case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break; + case AV_OPT_TYPE_INT: + *(int *)dst = llrint(num / den) * intnum; + break; + case AV_OPT_TYPE_INT64: + *(int64_t *)dst = llrint(num / den) * intnum; + break; + case AV_OPT_TYPE_FLOAT: + *(float *)dst = num * intnum / den; + break; + case AV_OPT_TYPE_DOUBLE: + *(double *)dst = num * intnum / den; + break; case AV_OPT_TYPE_RATIONAL: - if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den}; - else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24); + if ((int) num == num) + *(AVRational *)dst = (AVRational) { num *intnum, den }; + else + *(AVRational *)dst = av_d2q(num * intnum / den, 1 << 24); break; default: return AVERROR(EINVAL); @@ -91,17 +112,21 @@ static const double const_values[] = { 0 }; -static const char * const const_names[] = { +static const char *const const_names[] = { "PI", "E", "QP2LAMBDA", 0 }; -static int hexchar2int(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; +static int hexchar2int(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; return -1; } @@ -130,7 +155,7 @@ static int set_string_binary(void *obj, const AVOption *o, const char *val, uint } *ptr++ = (a << 4) | b; } - *dst = bin; + *dst = bin; *lendst = len; return 0; @@ -140,14 +165,15 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d { av_freep(dst); *dst = av_strdup(val); - return 0; + return *dst ? 0 : AVERROR(ENOMEM); } #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \ opt->type == AV_OPT_TYPE_CONST || \ opt->type == AV_OPT_TYPE_FLAGS || \ - opt->type == AV_OPT_TYPE_INT) ? \ - opt->default_val.i64 : opt->default_val.dbl) + opt->type == AV_OPT_TYPE_INT) \ + ? opt->default_val.i64 \ + : opt->default_val.dbl) static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst) { @@ -175,11 +201,16 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con const AVOption *o_named = av_opt_find(target_obj, buf, o->unit, 0, 0); if (o_named && o_named->type == AV_OPT_TYPE_CONST) d = DEFAULT_NUMVAL(o_named); - else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o); - else if (!strcmp(buf, "max" )) d = o->max; - else if (!strcmp(buf, "min" )) d = o->min; - else if (!strcmp(buf, "none" )) d = 0; - else if (!strcmp(buf, "all" )) d = ~0; + else if (!strcmp(buf, "default")) + d = DEFAULT_NUMVAL(o); + else if (!strcmp(buf, "max")) + d = o->max; + else if (!strcmp(buf, "min")) + d = o->min; + else if (!strcmp(buf, "none")) + d = 0; + else if (!strcmp(buf, "all")) + d = ~0; else { int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj); if (res < 0) { @@ -190,12 +221,16 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con } if (o->type == AV_OPT_TYPE_FLAGS) { read_number(o, dst, NULL, NULL, &intnum); - if (cmd == '+') d = intnum | (int64_t)d; - else if (cmd == '-') d = intnum &~(int64_t)d; + if (cmd == '+') + d = intnum | (int64_t)d; + else if (cmd == '-') + d = intnum & ~(int64_t)d; } else { read_number(o, dst, &num, &den, &intnum); - if (cmd == '+') d = notfirst*num*intnum/den + d; - else if (cmd == '-') d = notfirst*num*intnum/den - d; + if (cmd == '+') + d = notfirst * num * intnum / den + d; + else if (cmd == '-') + d = notfirst * num * intnum / den - d; } if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0) @@ -218,29 +253,33 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags) if (!val || o->flags & AV_OPT_FLAG_READONLY) return AVERROR(EINVAL); - dst = ((uint8_t*)target_obj) + o->offset; + dst = ((uint8_t *)target_obj) + o->offset; switch (o->type) { - case AV_OPT_TYPE_STRING: return set_string(obj, o, val, dst); - case AV_OPT_TYPE_BINARY: return set_string_binary(obj, o, val, dst); + case AV_OPT_TYPE_STRING: + return set_string(obj, o, val, dst); + case AV_OPT_TYPE_BINARY: + return set_string_binary(obj, o, val, dst); case AV_OPT_TYPE_FLAGS: case AV_OPT_TYPE_INT: case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_FLOAT: case AV_OPT_TYPE_DOUBLE: - case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, target_obj, o, val, dst); + case AV_OPT_TYPE_RATIONAL: + return set_string_number(obj, target_obj, o, val, dst); } av_log(obj, AV_LOG_ERROR, "Invalid option type.\n"); return AVERROR(EINVAL); } -#define OPT_EVAL_NUMBER(name, opttype, vartype)\ - int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\ - {\ - if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY)\ - return AVERROR(EINVAL);\ - return set_string_number(obj, obj, o, val, name ## _out);\ - } +#define OPT_EVAL_NUMBER(name, opttype, vartype) \ +int av_opt_eval_ ## name(void *obj, const AVOption *o, \ + const char *val, vartype *name ## _out) \ +{ \ + if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY) \ + return AVERROR(EINVAL); \ + return set_string_number(obj, obj, o, val, name ## _out); \ +} OPT_EVAL_NUMBER(flags, AV_OPT_TYPE_FLAGS, int) OPT_EVAL_NUMBER(int, AV_OPT_TYPE_INT, int) @@ -250,7 +289,7 @@ OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double) OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational) static int set_number(void *obj, const char *name, double num, int den, int64_t intnum, - int search_flags) + int search_flags) { void *dst, *target_obj; const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); @@ -261,7 +300,7 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t if (o->flags & AV_OPT_FLAG_READONLY) return AVERROR(EINVAL); - dst = ((uint8_t*)target_obj) + o->offset; + dst = ((uint8_t *)target_obj) + o->offset; return write_number(obj, o, dst, num, den, intnum); } @@ -298,18 +337,19 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int if (!ptr) return AVERROR(ENOMEM); - dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset); + dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset); lendst = (int *)(dst + 1); av_free(*dst); - *dst = ptr; + *dst = ptr; *lendst = len; memcpy(ptr, val, len); return 0; } -int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, + int search_flags) { void *target_obj; AVDictionary **dst; @@ -337,31 +377,44 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) if (!o || !target_obj) return AVERROR_OPTION_NOT_FOUND; - dst = (uint8_t*)target_obj + o->offset; + dst = (uint8_t *)target_obj + o->offset; buf[0] = 0; switch (o->type) { - case AV_OPT_TYPE_FLAGS: ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);break; - case AV_OPT_TYPE_INT: ret = snprintf(buf, sizeof(buf), "%d" , *(int *)dst);break; - case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break; - case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break; - case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break; - case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; + case AV_OPT_TYPE_FLAGS: + ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst); + break; + case AV_OPT_TYPE_INT: + ret = snprintf(buf, sizeof(buf), "%d", *(int *)dst); + break; + case AV_OPT_TYPE_INT64: + ret = snprintf(buf, sizeof(buf), "%" PRId64, *(int64_t *)dst); + break; + case AV_OPT_TYPE_FLOAT: + ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst); + break; + case AV_OPT_TYPE_DOUBLE: + ret = snprintf(buf, sizeof(buf), "%f", *(double *)dst); + break; + case AV_OPT_TYPE_RATIONAL: + ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational *)dst)->num, + ((AVRational *)dst)->den); + break; case AV_OPT_TYPE_STRING: - if (*(uint8_t**)dst) - *out_val = av_strdup(*(uint8_t**)dst); + if (*(uint8_t **)dst) + *out_val = av_strdup(*(uint8_t **)dst); else *out_val = av_strdup(""); - return 0; + return *out_val ? 0 : AVERROR(ENOMEM); case AV_OPT_TYPE_BINARY: - len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *)); - if ((uint64_t)len*2 + 1 > INT_MAX) + len = *(int *)(((uint8_t *)dst) + sizeof(uint8_t *)); + if ((uint64_t)len * 2 + 1 > INT_MAX) return AVERROR(EINVAL); - if (!(*out_val = av_malloc(len*2 + 1))) + if (!(*out_val = av_malloc(len * 2 + 1))) return AVERROR(ENOMEM); - bin = *(uint8_t**)dst; + bin = *(uint8_t **)dst; for (i = 0; i < len; i++) - snprintf(*out_val + i*2, 3, "%02X", bin[i]); + snprintf(*out_val + i * 2, 3, "%02X", bin[i]); return 0; default: return AVERROR(EINVAL); @@ -370,7 +423,7 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) if (ret >= sizeof(buf)) return AVERROR(EINVAL); *out_val = av_strdup(buf); - return 0; + return *out_val ? 0 : AVERROR(ENOMEM); } static int get_number(void *obj, const char *name, double *num, int *den, int64_t *intnum, @@ -381,52 +434,53 @@ static int get_number(void *obj, const char *name, double *num, int *den, int64_ if (!o || !target_obj) goto error; - dst = ((uint8_t*)target_obj) + o->offset; + dst = ((uint8_t *)target_obj) + o->offset; return read_number(o, dst, num, den, intnum); error: - *den=*intnum=0; + *den = + *intnum = 0; return -1; } int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val) { int64_t intnum = 1; - double num = 1; - int ret, den = 1; + double num = 1; + int ret, den = 1; if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; - *out_val = num*intnum/den; + *out_val = num * intnum / den; return 0; } int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val) { int64_t intnum = 1; - double num = 1; - int ret, den = 1; + double num = 1; + int ret, den = 1; if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; - *out_val = num*intnum/den; + *out_val = num * intnum / den; return 0; } int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val) { int64_t intnum = 1; - double num = 1; - int ret, den = 1; + double num = 1; + int ret, den = 1; if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) return ret; if (num == 1.0 && (int)intnum == intnum) - *out_val = (AVRational){intnum, den}; + *out_val = (AVRational) { intnum, den }; else - *out_val = av_d2q(num*intnum/den, 1<<24); + *out_val = av_d2q(num * intnum / den, 1 << 24); return 0; } @@ -463,7 +517,7 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) static void opt_list(void *obj, void *av_log_obj, const char *unit, int req_flags, int rej_flags) { - const AVOption *opt=NULL; + const AVOption *opt = NULL; while ((opt = av_opt_next(obj, opt))) { if (!(opt->flags & req_flags) || (opt->flags & rej_flags)) @@ -473,11 +527,11 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, * Don't print anything but CONST's on level two. * Only print items from the requested unit. */ - if (!unit && opt->type==AV_OPT_TYPE_CONST) + if (!unit && opt->type == AV_OPT_TYPE_CONST) continue; - else if (unit && opt->type!=AV_OPT_TYPE_CONST) + else if (unit && opt->type != AV_OPT_TYPE_CONST) continue; - else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit)) + else if (unit && opt->type == AV_OPT_TYPE_CONST && strcmp(unit, opt->unit)) continue; else if (unit && opt->type == AV_OPT_TYPE_CONST) av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); @@ -485,39 +539,39 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name); switch (opt->type) { - case AV_OPT_TYPE_FLAGS: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_INT: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_INT64: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_DOUBLE: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_FLOAT: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_STRING: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_RATIONAL: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_BINARY: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; - case AV_OPT_TYPE_CONST: - default: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); - break; + case AV_OPT_TYPE_FLAGS: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_INT: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_INT64: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_DOUBLE: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_FLOAT: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_STRING: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_RATIONAL: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_OPT_TYPE_BINARY: + av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + break; + case AV_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_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' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT) ? 'X' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY) ? 'R' : '.'); @@ -525,9 +579,8 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, 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 != AV_OPT_TYPE_CONST) { + if (opt->unit && opt->type != AV_OPT_TYPE_CONST) opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags); - } } } @@ -536,7 +589,7 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) if (!obj) return -1; - av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name); + av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass **)obj)->class_name); opt_list(obj, av_log_obj, NULL, req_flags, rej_flags); @@ -551,36 +604,39 @@ void av_opt_set_defaults(void *s) continue; switch (opt->type) { - case AV_OPT_TYPE_CONST: - /* Nothing to be done here */ + case AV_OPT_TYPE_CONST: + /* Nothing to be done here */ break; - case AV_OPT_TYPE_FLAGS: - case AV_OPT_TYPE_INT: - case AV_OPT_TYPE_INT64: - av_opt_set_int(s, opt->name, opt->default_val.i64, 0); + case AV_OPT_TYPE_FLAGS: + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: + av_opt_set_int(s, opt->name, opt->default_val.i64, 0); break; - case AV_OPT_TYPE_DOUBLE: - case AV_OPT_TYPE_FLOAT: { - double val; - val = opt->default_val.dbl; - av_opt_set_double(s, opt->name, val, 0); - } - break; - case AV_OPT_TYPE_RATIONAL: { - AVRational val; - val = av_d2q(opt->default_val.dbl, INT_MAX); - av_opt_set_q(s, opt->name, val, 0); - } + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: + { + double val; + val = opt->default_val.dbl; + av_opt_set_double(s, opt->name, val, 0); + } + break; + case AV_OPT_TYPE_RATIONAL: + { + AVRational val; + val = av_d2q(opt->default_val.dbl, INT_MAX); + av_opt_set_q(s, opt->name, val, 0); + } + break; + case AV_OPT_TYPE_STRING: + av_opt_set(s, opt->name, opt->default_val.str, 0); break; - case AV_OPT_TYPE_STRING: - av_opt_set(s, opt->name, opt->default_val.str, 0); - break; - case AV_OPT_TYPE_BINARY: - case AV_OPT_TYPE_DICT: - /* Cannot set defaults for these types */ + case AV_OPT_TYPE_BINARY: + case AV_OPT_TYPE_DICT: + /* Cannot set defaults for these types */ break; - default: - av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name); + default: + av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", + opt->type, opt->name); } } } @@ -706,7 +762,7 @@ const AVOption *av_opt_find(void *obj, const char *name, const char *unit, const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void **target_obj) { - const AVClass *c = *(AVClass**)obj; + const AVClass *c = *(AVClass **)obj; const AVOption *o = NULL; if (!c) @@ -729,7 +785,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, while (o = av_opt_next(obj, o)) { if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags && ((!unit && o->type != AV_OPT_TYPE_CONST) || - (unit && o->unit && !strcmp(o->unit, unit)))) { + (unit && o->unit && !strcmp(o->unit, unit)))) { if (target_obj) { if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ)) *target_obj = obj; @@ -744,7 +800,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, void *av_opt_child_next(void *obj, void *prev) { - const AVClass *c = *(AVClass**)obj; + const AVClass *c = *(AVClass **)obj; if (c->child_next) return c->child_next(obj, prev); return NULL; @@ -757,91 +813,75 @@ const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *pre return NULL; } -#ifdef TEST - -typedef struct TestContext +static int opt_size(enum AVOptionType type) { - const AVClass *class; - int num; - int toggle; - char *string; - int flags; - AVRational rational; -} TestContext; - -#define OFFSET(x) offsetof(TestContext, x) - -#define TEST_FLAG_COOL 01 -#define TEST_FLAG_LAME 02 -#define TEST_FLAG_MU 04 - -static const AVOption test_options[]= { -{"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 100 }, -{"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1 }, -{"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10 }, -{"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {0}, CHAR_MIN, CHAR_MAX }, -{"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" }, -{"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" }, -{"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" }, -{"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" }, -{NULL}, -}; + switch (type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_FLAGS: + return sizeof(int); + case AV_OPT_TYPE_INT64: + return sizeof(int64_t); + case AV_OPT_TYPE_DOUBLE: + return sizeof(double); + case AV_OPT_TYPE_FLOAT: + return sizeof(float); + case AV_OPT_TYPE_STRING: + return sizeof(uint8_t *); + case AV_OPT_TYPE_RATIONAL: + return sizeof(AVRational); + case AV_OPT_TYPE_BINARY: + return sizeof(uint8_t *) + sizeof(int); + } + return AVERROR(EINVAL); +} -static const char *test_get_name(void *ctx) +int av_opt_copy(void *dst, const void *src) { - return "test"; -} + const AVOption *o = NULL; + const AVClass *c; + int ret = 0; -static const AVClass test_class = { - "TestContext", - test_get_name, - test_options -}; + if (!src) + return AVERROR(EINVAL); -int main(void) -{ - int i; - - printf("\nTesting av_set_options_string()\n"); - { - TestContext test_ctx; - const char *options[] = { - "", - ":", - "=", - "foo=:", - ":=foo", - "=foo", - "foo=", - "foo", - "foo=val", - "foo==val", - "toggle=:", - "string=:", - "toggle=1 : foo", - "toggle=100", - "toggle==1", - "flags=+mu-lame : num=42: toggle=0", - "num=42 : string=blahblah", - "rational=0 : rational=1/2 : rational=1/-1", - "rational=-1/0", - }; - - test_ctx.class = &test_class; - av_opt_set_defaults(&test_ctx); - test_ctx.string = av_strdup("default"); - - av_log_set_level(AV_LOG_DEBUG); - - for (i=0; i < FF_ARRAY_ELEMS(options); i++) { - av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); - if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0) - av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); - printf("\n"); + c = *(AVClass **)src; + if (!c || c != *(AVClass **)dst) + return AVERROR(EINVAL); + + while ((o = av_opt_next(src, o))) { + void *field_dst = (uint8_t *)dst + o->offset; + void *field_src = (uint8_t *)src + o->offset; + uint8_t **field_dst8 = (uint8_t **)field_dst; + uint8_t **field_src8 = (uint8_t **)field_src; + + if (o->type == AV_OPT_TYPE_STRING) { + set_string(dst, o, *field_src8, field_dst8); + if (*field_src8 && !*field_dst8) + ret = AVERROR(ENOMEM); + } else if (o->type == AV_OPT_TYPE_BINARY) { + int len = *(int *)(field_src8 + 1); + if (*field_dst8 != *field_src8) + av_freep(field_dst8); + if (len) { + *field_dst8 = av_malloc(len); + if (!*field_dst8) { + ret = AVERROR(ENOMEM); + len = 0; + } + memcpy(*field_dst8, *field_src8, len); + } else { + *field_dst8 = NULL; + } + *(int *)(field_dst8 + 1) = len; + } else if (o->type == AV_OPT_TYPE_CONST) { + // do nothing + } else { + int size = opt_size(o->type); + if (size < 0) + ret = size; + else + memcpy(field_dst, field_src, size); } } - - return 0; + return ret; } - -#endif diff --git a/libavutil/opt.h b/libavutil/opt.h index ac722ee..a65c4f4 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -270,7 +270,7 @@ typedef struct AVOption { #define AV_OPT_FLAG_VIDEO_PARAM 16 #define AV_OPT_FLAG_SUBTITLE_PARAM 32 /** - * The option is inteded for exporting values to the caller. + * The option is intended for exporting values to the caller. */ #define AV_OPT_FLAG_EXPORT 64 /** @@ -319,7 +319,7 @@ void av_opt_set_defaults(void *s); * @return the number of successfully set key/value pairs, or a negative * value corresponding to an AVERROR code in case of error: * AVERROR(EINVAL) if opts cannot be parsed, - * the error code issued by av_set_string3() if a key/value pair + * the error code issued by av_opt_set() if a key/value pair * cannot be set */ int av_set_options_string(void *ctx, const char *opts, @@ -408,7 +408,7 @@ int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational * was found. * * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable - * directly with av_set_string3(). Use special calls which take an options + * directly with av_opt_set(). Use special calls which take an options * AVDictionary (e.g. avformat_open_input()) to set options found with this * flag. */ @@ -448,7 +448,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, * or NULL * @return next AVOption or NULL */ -const AVOption *av_opt_next(void *obj, const AVOption *prev); +const AVOption *av_opt_next(const void *obj, const AVOption *prev); /** * Iterate over AVOptions-enabled children of obj. @@ -530,6 +530,19 @@ int av_opt_get_q (void *obj, const char *name, int search_flags, AVRationa * be freed with av_dict_free() by the caller */ int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); + +/** + * Copy options from src object into dest object. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + /** * @} * @} diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 414cd47..f424811 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -29,14 +29,15 @@ #include "eval.h" #include "log.h" #include "random_seed.h" +#include "time_internal.h" #include "parseutils.h" -typedef struct { +typedef struct VideoSizeAbbr { const char *abbr; int width, height; } VideoSizeAbbr; -typedef struct { +typedef struct VideoRateAbbr { const char *abbr; AVRational rate; } VideoRateAbbr; @@ -79,6 +80,10 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, + { "2kdci", 2048,1080 }, + { "4kdci", 4096,2160 }, + { "uhd2160", 3840,2160 }, + { "uhd4320", 7680,4320 }, }; static const VideoRateAbbr video_rate_abbrs[]= { @@ -142,7 +147,7 @@ int av_parse_video_rate(AVRational *rate, const char *arg) return 0; } -typedef struct { +typedef struct ColorEntry { const char *name; ///< a string representing the name of the color uint8_t rgb_color[3]; ///< RGB values for the color } ColorEntry; @@ -399,65 +404,73 @@ static int date_get_num(const char **pp, return val; } -static const char *small_strptime(const char *p, const char *fmt, struct tm *dt) +const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) { int c, val; - for(;;) { + while((c = *fmt++)) { + if (c != '%') { + if (av_isspace(c)) + for (; *p && av_isspace(*p); p++); + else if (*p != c) + return NULL; + else p++; + continue; + } + 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: + switch(c) { + case 'H': + val = date_get_num(&p, 0, 23, 2); + if (val == -1) return NULL; - } - } else { - match: - if (c != *p) + dt->tm_hour = val; + break; + case 'M': + val = date_get_num(&p, 0, 59, 2); + if (val == -1) return NULL; - p++; + 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 'T': + p = av_small_strptime(p, "%H:%M:%S", dt); + if (!p) + return NULL; + break; + case '%': + if (*p++ != '%') + return NULL; + break; + default: + return NULL; } } + + return p; } time_t av_timegm(struct tm *tm) @@ -483,7 +496,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) { const char *p; int64_t t; - struct tm dt = { 0 }; + struct tm dt = { 0 }, tmbuf; int i; static const char * const date_fmt[] = { "%Y-%m-%d", @@ -517,7 +530,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) /* parse the year-month-day part */ for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) { - q = small_strptime(p, date_fmt[i], &dt); + q = av_small_strptime(p, date_fmt[i], &dt); if (q) { break; } @@ -527,9 +540,9 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) * current year-month-day time */ if (!q) { if (is_utc) { - dt = *gmtime(&now); + dt = *gmtime_r(&now, &tmbuf); } else { - dt = *localtime(&now); + dt = *localtime_r(&now, &tmbuf); } dt.tm_hour = dt.tm_min = dt.tm_sec = 0; } else { @@ -541,7 +554,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) /* parse the hour-minute-second part */ for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) { - q = small_strptime(p, time_fmt[i], &dt); + q = av_small_strptime(p, time_fmt[i], &dt); if (q) { break; } @@ -553,7 +566,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) ++p; } /* parse timestr as HH:MM:SS */ - q = small_strptime(p, time_fmt[0], &dt); + q = av_small_strptime(p, time_fmt[0], &dt); if (!q) { char *o; /* parse timestr as S+ */ @@ -641,102 +654,3 @@ int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info } return 0; } - -#ifdef TEST - -int main(void) -{ - printf("Testing av_parse_video_rate()\n"); - { - int i; - static const char *const rates[] = { - "-inf", - "inf", - "nan", - "123/0", - "-123 / 0", - "", - "/", - " 123 / 321", - "foo/foo", - "foo/1", - "1/foo", - "0/0", - "/0", - "1/", - "1", - "0", - "-123/123", - "-foo", - "123.23", - ".23", - "-.23", - "-0.234", - "-0.0000001", - " 21332.2324 ", - " -21332.2324 ", - }; - - for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) { - int ret; - AVRational q = { 0, 0 }; - ret = av_parse_video_rate(&q, rates[i]); - printf("'%s' -> %d/%d %s\n", - rates[i], q.num, q.den, ret ? "ERROR" : "OK"); - } - } - - printf("\nTesting av_parse_color()\n"); - { - int i; - uint8_t rgba[4]; - static const char *const color_names[] = { - "foo", - "red", - "Red ", - "RED", - "Violet", - "Yellow", - "Red", - "0x000000", - "0x0000000", - "0xff000000", - "0x3e34ff", - "0x3e34ffaa", - "0xffXXee", - "0xfoobar", - "0xffffeeeeeeee", - "#ff0000", - "#ffXX00", - "ff0000", - "ffXX00", - "red@foo", - "random@10", - "0xff0000@1.0", - "red@", - "red@0xfff", - "red@0xf", - "red@2", - "red@0.1", - "red@-1", - "red@0.5", - "red@1.0", - "red@256", - "red@10foo", - "red@-1.0", - "red@-0.0", - }; - - av_log_set_level(AV_LOG_DEBUG); - - for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) { - if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0) - printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", - color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]); - } - } - - return 0; -} - -#endif /* TEST */ diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h index 0844abb..8e99634 100644 --- a/libavutil/parseutils.h +++ b/libavutil/parseutils.h @@ -117,6 +117,37 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration); int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); /** + * Simplified version of strptime + * + * Parse the input string p according to the format string fmt and + * store its results in the structure dt. + * + * Neither text and locale's alternative representation are supported. + * + * The supported input field descriptors are listed below. + * - %H: the hour as a decimal number, using a 24-hour clock, in the + * range '00' through '23' + * - %M: the minute as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %S: the second as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %Y: the year as a decimal number, using the Gregorian calendar + * - %m: the month as a decimal number, in the range '1' through '12' + * - %d: the day of the month as a decimal number, in the range '1' + * through '31' + * - %T: alias for '%H:%M:%S' + * - %%: a literal '%' + * + * @return a pointer to the first character not processed in this function + * call. In case the input string contains more characters than + * required by the format string the return value points right after + * the last consumed input character. In case the whole input string + * is consumed the return value points to the null byte at the end of + * the string. On failure NULL is returned. + */ +const char *av_small_strptime(const char *p, const char *fmt, struct tm *dt); + +/** * Convert the decomposed UTC time in tm to a time_t value. */ time_t av_timegm(struct tm *tm); diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 3215276..cf2ea9c 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -38,14 +38,14 @@ void av_read_image_line(uint16_t *dst, { AVComponentDescriptor comp = desc->comp[c]; int plane = comp.plane; - int depth = comp.depth_minus1 + 1; + int depth = comp.depth; int mask = (1 << depth) - 1; int shift = comp.shift; - int step = comp.step_minus1 + 1; + int step = comp.step; int flags = desc->flags; if (flags & AV_PIX_FMT_FLAG_BITSTREAM) { - int skip = x * step + comp.offset_plus1 - 1; + int skip = x * step + comp.offset; const uint8_t *p = data[plane] + y * linesize[plane] + (skip >> 3); int shift = 8 - depth - (skip & 7); @@ -60,7 +60,7 @@ void av_read_image_line(uint16_t *dst, } } else { const uint8_t *p = data[plane] + y * linesize[plane] + - x * step + comp.offset_plus1 - 1; + x * step + comp.offset; int is_8bit = shift + depth <= 8; if (is_8bit) @@ -85,12 +85,12 @@ void av_write_image_line(const uint16_t *src, { AVComponentDescriptor comp = desc->comp[c]; int plane = comp.plane; - int depth = comp.depth_minus1 + 1; - int step = comp.step_minus1 + 1; + int depth = comp.depth; + int step = comp.step; int flags = desc->flags; if (flags & AV_PIX_FMT_FLAG_BITSTREAM) { - int skip = x * step + comp.offset_plus1 - 1; + int skip = x * step + comp.offset; uint8_t *p = data[plane] + y * linesize[plane] + (skip >> 3); int shift = 8 - depth - (skip & 7); @@ -103,7 +103,7 @@ void av_write_image_line(const uint16_t *src, } else { int shift = comp.shift; uint8_t *p = data[plane] + y * linesize[plane] + - x * step + comp.offset_plus1 - 1; + x * step + comp.offset; if (shift + depth <= 8) { p += !!(flags & AV_PIX_FMT_FLAG_BE); @@ -126,19 +126,19 @@ void av_write_image_line(const uint16_t *src, } } -#if !FF_API_PIX_FMT_DESC -static +#if FF_API_PLUS1_MINUS1 +FF_DISABLE_DEPRECATION_WARNINGS #endif -const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { +static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { [AV_PIX_FMT_YUV420P] = { .name = "yuv420p", .nb_components = 3, .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -148,9 +148,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 7 }, /* Y */ - { 0, 3, 2, 0, 7 }, /* U */ - { 0, 3, 4, 0, 7 }, /* V */ + { 0, 2, 0, 0, 8, 1, 7, 1 }, /* Y */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* U */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* V */ }, }, [AV_PIX_FMT_YVYU422] = { @@ -159,9 +159,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 7 }, /* Y */ - { 0, 3, 2, 0, 7 }, /* V */ - { 0, 3, 4, 0, 7 }, /* U */ + { 0, 2, 0, 0, 8, 1, 7, 1 }, /* Y */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* U */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* V */ }, }, [AV_PIX_FMT_RGB24] = { @@ -170,9 +170,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 2, 1, 0, 7 }, /* R */ - { 0, 2, 2, 0, 7 }, /* G */ - { 0, 2, 3, 0, 7 }, /* B */ + { 0, 3, 0, 0, 8, 2, 7, 1 }, /* R */ + { 0, 3, 1, 0, 8, 2, 7, 2 }, /* G */ + { 0, 3, 2, 0, 8, 2, 7, 3 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -182,9 +182,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 2, 1, 0, 7 }, /* B */ - { 0, 2, 2, 0, 7 }, /* G */ - { 0, 2, 3, 0, 7 }, /* R */ + { 0, 3, 2, 0, 8, 2, 7, 3 }, /* R */ + { 0, 3, 1, 0, 8, 2, 7, 2 }, /* G */ + { 0, 3, 0, 0, 8, 2, 7, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -194,9 +194,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -206,9 +206,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -218,9 +218,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 2, .log2_chroma_h = 2, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -230,9 +230,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 2, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -242,7 +242,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ }, .flags = AV_PIX_FMT_FLAG_PSEUDOPAL, .alias = "gray8,y8", @@ -253,7 +253,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 0 }, /* Y */ + { 0, 1, 0, 0, 1, 0, 0, 1 }, /* Y */ }, .flags = AV_PIX_FMT_FLAG_BITSTREAM, }, @@ -263,7 +263,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 7, 0 }, /* Y */ + { 0, 1, 0, 7, 1, 0, 0, 1 }, /* Y */ }, .flags = AV_PIX_FMT_FLAG_BITSTREAM, }, @@ -273,7 +273,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, + { 0, 1, 0, 0, 8, 0, 7, 1 }, }, .flags = AV_PIX_FMT_FLAG_PAL, }, @@ -283,9 +283,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -295,9 +295,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -307,9 +307,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - {0, 0, 1, 0, 7}, /* Y */ - {1, 0, 1, 0, 7}, /* U */ - {2, 0, 1, 0, 7}, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -329,9 +329,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 0, 7 }, /* Y */ - { 0, 3, 1, 0, 7 }, /* U */ - { 0, 3, 3, 0, 7 }, /* V */ + { 0, 2, 1, 0, 8, 1, 7, 2 }, /* Y */ + { 0, 4, 0, 0, 8, 3, 7, 1 }, /* U */ + { 0, 4, 2, 0, 8, 3, 7, 3 }, /* V */ }, }, [AV_PIX_FMT_UYYVYY411] = { @@ -340,9 +340,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 2, .log2_chroma_h = 0, .comp = { - { 0, 3, 2, 0, 7 }, /* Y */ - { 0, 5, 1, 0, 7 }, /* U */ - { 0, 5, 4, 0, 7 }, /* V */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* Y */ + { 0, 6, 0, 0, 8, 5, 7, 1 }, /* U */ + { 0, 6, 3, 0, 8, 5, 7, 4 }, /* V */ }, }, [AV_PIX_FMT_BGR8] = { @@ -351,9 +351,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 6, 1 }, /* B */ - { 0, 0, 1, 3, 2 }, /* G */ - { 0, 0, 1, 0, 2 }, /* R */ + { 0, 1, 0, 0, 3, 0, 2, 1 }, /* R */ + { 0, 1, 0, 3, 3, 0, 2, 1 }, /* G */ + { 0, 1, 0, 6, 2, 0, 1, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -363,9 +363,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 0 }, /* B */ - { 0, 3, 2, 0, 1 }, /* G */ - { 0, 3, 4, 0, 0 }, /* R */ + { 0, 4, 3, 0, 1, 3, 0, 4 }, /* R */ + { 0, 4, 1, 0, 2, 3, 1, 2 }, /* G */ + { 0, 4, 0, 0, 1, 3, 0, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_RGB, }, @@ -375,9 +375,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 3, 0 }, /* B */ - { 0, 0, 1, 1, 1 }, /* G */ - { 0, 0, 1, 0, 0 }, /* R */ + { 0, 1, 0, 0, 1, 0, 0, 1 }, /* R */ + { 0, 1, 0, 1, 2, 0, 1, 1 }, /* G */ + { 0, 1, 0, 3, 1, 0, 0, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -387,9 +387,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 6, 1 }, /* R */ - { 0, 0, 1, 3, 2 }, /* G */ - { 0, 0, 1, 0, 2 }, /* B */ + { 0, 1, 0, 6, 2, 0, 1, 1 }, /* R */ + { 0, 1, 0, 3, 3, 0, 2, 1 }, /* G */ + { 0, 1, 0, 0, 3, 0, 2, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -399,9 +399,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 0 }, /* R */ - { 0, 3, 2, 0, 1 }, /* G */ - { 0, 3, 4, 0, 0 }, /* B */ + { 0, 4, 0, 0, 1, 3, 0, 1 }, /* R */ + { 0, 4, 1, 0, 2, 3, 1, 2 }, /* G */ + { 0, 4, 3, 0, 1, 3, 0, 4 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_RGB, }, @@ -411,9 +411,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 3, 0 }, /* R */ - { 0, 0, 1, 1, 1 }, /* G */ - { 0, 0, 1, 0, 0 }, /* B */ + { 0, 1, 0, 3, 1, 0, 0, 1 }, /* R */ + { 0, 1, 0, 1, 2, 0, 1, 1 }, /* G */ + { 0, 1, 0, 0, 1, 0, 0, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -423,9 +423,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 1, 1, 0, 7 }, /* U */ - { 1, 1, 2, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 2, 0, 0, 8, 1, 7, 1 }, /* U */ + { 1, 2, 1, 0, 8, 1, 7, 2 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -435,9 +435,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 1, 1, 0, 7 }, /* V */ - { 1, 1, 2, 0, 7 }, /* U */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 2, 1, 0, 8, 1, 7, 2 }, /* U */ + { 1, 2, 0, 0, 8, 1, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -447,10 +447,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* A */ - { 0, 3, 2, 0, 7 }, /* R */ - { 0, 3, 3, 0, 7 }, /* G */ - { 0, 3, 4, 0, 7 }, /* B */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* R */ + { 0, 4, 2, 0, 8, 3, 7, 3 }, /* G */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* B */ + { 0, 4, 0, 0, 8, 3, 7, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -460,10 +460,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* R */ - { 0, 3, 2, 0, 7 }, /* G */ - { 0, 3, 3, 0, 7 }, /* B */ - { 0, 3, 4, 0, 7 }, /* A */ + { 0, 4, 0, 0, 8, 3, 7, 1 }, /* R */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* G */ + { 0, 4, 2, 0, 8, 3, 7, 3 }, /* B */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -473,10 +473,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* A */ - { 0, 3, 2, 0, 7 }, /* B */ - { 0, 3, 3, 0, 7 }, /* G */ - { 0, 3, 4, 0, 7 }, /* R */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* R */ + { 0, 4, 2, 0, 8, 3, 7, 3 }, /* G */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* B */ + { 0, 4, 0, 0, 8, 3, 7, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -486,10 +486,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* B */ - { 0, 3, 2, 0, 7 }, /* G */ - { 0, 3, 3, 0, 7 }, /* R */ - { 0, 3, 4, 0, 7 }, /* A */ + { 0, 4, 2, 0, 8, 3, 7, 3 }, /* R */ + { 0, 4, 1, 0, 8, 3, 7, 2 }, /* G */ + { 0, 4, 0, 0, 8, 3, 7, 1 }, /* B */ + { 0, 4, 3, 0, 8, 3, 7, 4 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -499,7 +499,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ }, .flags = AV_PIX_FMT_FLAG_BE, .alias = "y16be", @@ -510,7 +510,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ }, .alias = "y16le", }, @@ -520,9 +520,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -532,9 +532,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -544,10 +544,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ - { 3, 0, 1, 0, 7 }, /* A */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ + { 3, 1, 0, 0, 8, 0, 7, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -557,10 +557,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ - { 3, 0, 1, 0, 7 }, /* A */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ + { 3, 1, 0, 0, 8, 0, 7, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -570,10 +570,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 0, 1, 0, 7 }, /* U */ - { 2, 0, 1, 0, 7 }, /* V */ - { 3, 0, 1, 0, 7 }, /* A */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ + { 3, 1, 0, 0, 8, 0, 7, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -583,12 +583,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, - .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, [AV_PIX_FMT_YUVA420P9LE] = { .name = "yuva420p9le", @@ -596,10 +596,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -609,10 +609,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -622,10 +622,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -635,10 +635,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -648,10 +648,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ - { 3, 1, 1, 0, 8 }, /* A */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ + { 3, 2, 0, 0, 9, 1, 8, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -661,10 +661,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -674,10 +674,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -687,10 +687,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -700,10 +700,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -713,10 +713,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -726,10 +726,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ - { 3, 1, 1, 0, 9 }, /* A */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -739,10 +739,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -752,10 +752,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -765,10 +765,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -778,10 +778,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -791,10 +791,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -804,10 +804,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ - { 3, 1, 1, 0, 15 }, /* A */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, @@ -855,9 +855,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* R */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* B */ + { 0, 6, 0, 0, 16, 5, 15, 1 }, /* R */ + { 0, 6, 2, 0, 16, 5, 15, 3 }, /* G */ + { 0, 6, 4, 0, 16, 5, 15, 5 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BE, }, @@ -867,9 +867,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* R */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* B */ + { 0, 6, 0, 0, 16, 5, 15, 1 }, /* R */ + { 0, 6, 2, 0, 16, 5, 15, 3 }, /* G */ + { 0, 6, 4, 0, 16, 5, 15, 5 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -879,10 +879,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 7, 1, 0, 15 }, /* R */ - { 0, 7, 3, 0, 15 }, /* G */ - { 0, 7, 5, 0, 15 }, /* B */ - { 0, 7, 7, 0, 15 }, /* A */ + { 0, 8, 0, 0, 16, 7, 15, 1 }, /* R */ + { 0, 8, 2, 0, 16, 7, 15, 3 }, /* G */ + { 0, 8, 4, 0, 16, 7, 15, 5 }, /* B */ + { 0, 8, 6, 0, 16, 7, 15, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -892,10 +892,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 7, 1, 0, 15 }, /* R */ - { 0, 7, 3, 0, 15 }, /* G */ - { 0, 7, 5, 0, 15 }, /* B */ - { 0, 7, 7, 0, 15 }, /* A */ + { 0, 8, 0, 0, 16, 7, 15, 1 }, /* R */ + { 0, 8, 2, 0, 16, 7, 15, 3 }, /* G */ + { 0, 8, 4, 0, 16, 7, 15, 5 }, /* B */ + { 0, 8, 6, 0, 16, 7, 15, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -905,9 +905,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 3, 4 }, /* R */ - { 0, 1, 1, 5, 5 }, /* G */ - { 0, 1, 1, 0, 4 }, /* B */ + { 0, 2, -1, 3, 5, 1, 4, 0 }, /* R */ + { 0, 2, 0, 5, 6, 1, 5, 1 }, /* G */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -917,9 +917,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 3, 4 }, /* R */ - { 0, 1, 1, 5, 5 }, /* G */ - { 0, 1, 1, 0, 4 }, /* B */ + { 0, 2, 1, 3, 5, 1, 4, 2 }, /* R */ + { 0, 2, 0, 5, 6, 1, 5, 1 }, /* G */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -929,9 +929,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 2, 4 }, /* R */ - { 0, 1, 1, 5, 4 }, /* G */ - { 0, 1, 1, 0, 4 }, /* B */ + { 0, 2, -1, 2, 5, 1, 4, 0 }, /* R */ + { 0, 2, 0, 5, 5, 1, 4, 1 }, /* G */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -941,9 +941,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 2, 4 }, /* R */ - { 0, 1, 1, 5, 4 }, /* G */ - { 0, 1, 1, 0, 4 }, /* B */ + { 0, 2, 1, 2, 5, 1, 4, 2 }, /* R */ + { 0, 2, 0, 5, 5, 1, 4, 1 }, /* G */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -953,9 +953,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 0, 3 }, /* R */ - { 0, 1, 1, 4, 3 }, /* G */ - { 0, 1, 1, 0, 3 }, /* B */ + { 0, 2, -1, 0, 4, 1, 3, 0 }, /* R */ + { 0, 2, 0, 4, 4, 1, 3, 1 }, /* G */ + { 0, 2, 0, 0, 4, 1, 3, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -965,9 +965,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 0, 3 }, /* R */ - { 0, 1, 1, 4, 3 }, /* G */ - { 0, 1, 1, 0, 3 }, /* B */ + { 0, 2, 1, 0, 4, 1, 3, 2 }, /* R */ + { 0, 2, 0, 4, 4, 1, 3, 1 }, /* G */ + { 0, 2, 0, 0, 4, 1, 3, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -977,9 +977,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ + { 0, 6, 4, 0, 16, 5, 15, 5 }, /* R */ + { 0, 6, 2, 0, 16, 5, 15, 3 }, /* G */ + { 0, 6, 0, 0, 16, 5, 15, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -989,9 +989,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ + { 0, 6, 4, 0, 16, 5, 15, 5 }, /* R */ + { 0, 6, 2, 0, 16, 5, 15, 3 }, /* G */ + { 0, 6, 0, 0, 16, 5, 15, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1001,10 +1001,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ - { 0, 5, 7, 0, 15 }, /* A */ + { 0, 8, 4, 0, 16, 7, 15, 5 }, /* R */ + { 0, 8, 2, 0, 16, 7, 15, 3 }, /* G */ + { 0, 8, 0, 0, 16, 7, 15, 1 }, /* B */ + { 0, 8, 6, 0, 16, 7, 15, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -1014,10 +1014,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ - { 0, 5, 7, 0, 15 }, /* A */ + { 0, 8, 4, 0, 16, 7, 15, 5 }, /* R */ + { 0, 8, 2, 0, 16, 7, 15, 3 }, /* G */ + { 0, 8, 0, 0, 16, 7, 15, 1 }, /* B */ + { 0, 8, 6, 0, 16, 7, 15, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -1027,9 +1027,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 3, 4 }, /* B */ - { 0, 1, 1, 5, 5 }, /* G */ - { 0, 1, 1, 0, 4 }, /* R */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* R */ + { 0, 2, 0, 5, 6, 1, 5, 1 }, /* G */ + { 0, 2, -1, 3, 5, 1, 4, 0 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1039,9 +1039,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 3, 4 }, /* B */ - { 0, 1, 1, 5, 5 }, /* G */ - { 0, 1, 1, 0, 4 }, /* R */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* R */ + { 0, 2, 0, 5, 6, 1, 5, 1 }, /* G */ + { 0, 2, 1, 3, 5, 1, 4, 2 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1051,9 +1051,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 2, 4 }, /* B */ - { 0, 1, 1, 5, 4 }, /* G */ - { 0, 1, 1, 0, 4 }, /* R */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* R */ + { 0, 2, 0, 5, 5, 1, 4, 1 }, /* G */ + { 0, 2, -1, 2, 5, 1, 4, 0 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1063,9 +1063,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 2, 4 }, /* B */ - { 0, 1, 1, 5, 4 }, /* G */ - { 0, 1, 1, 0, 4 }, /* R */ + { 0, 2, 0, 0, 5, 1, 4, 1 }, /* R */ + { 0, 2, 0, 5, 5, 1, 4, 1 }, /* G */ + { 0, 2, 1, 2, 5, 1, 4, 2 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1075,9 +1075,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 0, 3 }, /* B */ - { 0, 1, 1, 4, 3 }, /* G */ - { 0, 1, 1, 0, 3 }, /* R */ + { 0, 2, 0, 0, 4, 1, 3, 1 }, /* R */ + { 0, 2, 0, 4, 4, 1, 3, 1 }, /* G */ + { 0, 2, -1, 0, 4, 1, 3, 0 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1087,12 +1087,13 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 0, 3 }, /* B */ - { 0, 1, 1, 4, 3 }, /* G */ - { 0, 1, 1, 0, 3 }, /* R */ + { 0, 2, 0, 0, 4, 1, 3, 1 }, /* R */ + { 0, 2, 0, 4, 4, 1, 3, 1 }, /* G */ + { 0, 2, 1, 0, 4, 1, 3, 2 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, +#if FF_API_VAAPI [AV_PIX_FMT_VAAPI_MOCO] = { .name = "vaapi_moco", .log2_chroma_w = 1, @@ -1111,6 +1112,14 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_h = 1, .flags = AV_PIX_FMT_FLAG_HWACCEL, }, +#else + [AV_PIX_FMT_VAAPI] = { + .name = "vaapi", + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, +#endif [AV_PIX_FMT_VDA_VLD] = { .name = "vda_vld", .log2_chroma_w = 1, @@ -1123,9 +1132,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1135,9 +1144,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1147,9 +1156,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1159,9 +1168,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1171,9 +1180,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1183,9 +1192,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 1, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1195,9 +1204,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1207,9 +1216,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1219,9 +1228,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1231,9 +1240,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1243,9 +1252,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1255,9 +1264,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1267,9 +1276,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1279,9 +1288,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* Y */ - { 1, 1, 1, 0, 15 }, /* U */ - { 2, 1, 1, 0, 15 }, /* V */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* Y */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* U */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1291,9 +1300,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1303,9 +1312,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 1, 1, 0, 9 }, /* U */ - { 2, 1, 1, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* U */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, @@ -1315,9 +1324,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1327,12 +1336,18 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* Y */ - { 1, 1, 1, 0, 8 }, /* U */ - { 2, 1, 1, 0, 8 }, /* V */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* Y */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* U */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_D3D11VA_VLD] = { + .name = "d3d11va_vld", + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, [AV_PIX_FMT_DXVA2_VLD] = { .name = "dxva2_vld", .log2_chroma_w = 1, @@ -1343,8 +1358,8 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "ya8", .nb_components = 2, .comp = { - { 0, 1, 1, 0, 7 }, /* Y */ - { 0, 1, 2, 0, 7 }, /* A */ + { 0, 2, 0, 0, 8, 1, 7, 1 }, /* Y */ + { 0, 2, 1, 0, 8, 1, 7, 2 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_ALPHA, .alias = "gray8a", @@ -1353,8 +1368,8 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "ya16le", .nb_components = 2, .comp = { - { 0, 3, 1, 0, 15 }, /* Y */ - { 0, 3, 3, 0, 15 }, /* A */ + { 0, 4, 0, 0, 16, 3, 15, 1 }, /* Y */ + { 0, 4, 2, 0, 16, 3, 15, 3 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_ALPHA, }, @@ -1362,8 +1377,8 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "ya16be", .nb_components = 2, .comp = { - { 0, 3, 1, 0, 15 }, /* Y */ - { 0, 3, 3, 0, 15 }, /* A */ + { 0, 4, 0, 0, 16, 3, 15, 1 }, /* Y */ + { 0, 4, 2, 0, 16, 3, 15, 3 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_ALPHA, }, @@ -1373,9 +1388,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* G */ - { 1, 0, 1, 0, 7 }, /* B */ - { 2, 0, 1, 0, 7 }, /* R */ + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* R */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* G */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1385,9 +1400,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* G */ - { 1, 1, 1, 0, 8 }, /* B */ - { 2, 1, 1, 0, 8 }, /* R */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* R */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* G */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1397,9 +1412,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 8 }, /* G */ - { 1, 1, 1, 0, 8 }, /* B */ - { 2, 1, 1, 0, 8 }, /* R */ + { 2, 2, 0, 0, 9, 1, 8, 1 }, /* R */ + { 0, 2, 0, 0, 9, 1, 8, 1 }, /* G */ + { 1, 2, 0, 0, 9, 1, 8, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1409,9 +1424,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* G */ - { 1, 1, 1, 0, 9 }, /* B */ - { 2, 1, 1, 0, 9 }, /* R */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* R */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* G */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1421,9 +1436,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* G */ - { 1, 1, 1, 0, 9 }, /* B */ - { 2, 1, 1, 0, 9 }, /* R */ + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* R */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* G */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1433,9 +1448,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* G */ - { 1, 1, 1, 0, 15 }, /* B */ - { 2, 1, 1, 0, 15 }, /* R */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* R */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* G */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1445,12 +1460,54 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 15 }, /* G */ - { 1, 1, 1, 0, 15 }, /* B */ - { 2, 1, 1, 0, 15 }, /* R */ + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* R */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* G */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, + [AV_PIX_FMT_GBRAP] = { + .name = "gbrap", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 0, 0, 8, 0, 7, 1 }, /* R */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* G */ + { 1, 1, 0, 0, 8, 0, 7, 1 }, /* B */ + { 3, 1, 0, 0, 8, 0, 7, 1 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | + AV_PIX_FMT_FLAG_ALPHA, + }, + [AV_PIX_FMT_GBRAP16LE] = { + .name = "gbrap16le", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* R */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* G */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* B */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | + AV_PIX_FMT_FLAG_ALPHA, + }, + [AV_PIX_FMT_GBRAP16BE] = { + .name = "gbrap16be", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 2, 0, 0, 16, 1, 15, 1 }, /* R */ + { 0, 2, 0, 0, 16, 1, 15, 1 }, /* G */ + { 1, 2, 0, 0, 16, 1, 15, 1 }, /* B */ + { 3, 2, 0, 0, 16, 1, 15, 1 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | + AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, + }, [AV_PIX_FMT_VDPAU] = { .name = "vdpau", .log2_chroma_w = 1, @@ -1463,9 +1520,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 4, 11 }, /* X */ - { 0, 5, 3, 4, 11 }, /* Y */ - { 0, 5, 5, 4, 11 }, /* Z */ + { 0, 6, 0, 4, 12, 5, 11, 1 }, /* X */ + { 0, 6, 2, 4, 12, 5, 11, 3 }, /* Y */ + { 0, 6, 4, 4, 12, 5, 11, 5 }, /* Z */ }, /*.flags = -- not used*/ }, @@ -1475,9 +1532,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 4, 11 }, /* X */ - { 0, 5, 3, 4, 11 }, /* Y */ - { 0, 5, 5, 4, 11 }, /* Z */ + { 0, 6, 0, 4, 12, 5, 11, 1 }, /* X */ + { 0, 6, 2, 4, 12, 5, 11, 3 }, /* Y */ + { 0, 6, 4, 4, 12, 5, 11, 5 }, /* Z */ }, .flags = AV_PIX_FMT_FLAG_BE, }, @@ -1487,9 +1544,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 1, 1, 0, 7 }, /* U */ - { 1, 1, 2, 0, 7 }, /* V */ + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 2, 0, 0, 8, 1, 7, 1 }, /* U */ + { 1, 2, 1, 0, 8, 1, 7, 2 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1499,9 +1556,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 3, 1, 0, 9 }, /* U */ - { 1, 3, 3, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 4, 0, 0, 10, 3, 9, 1 }, /* U */ + { 1, 4, 2, 0, 10, 3, 9, 3 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -1511,9 +1568,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 1, .log2_chroma_h = 0, .comp = { - { 0, 1, 1, 0, 9 }, /* Y */ - { 1, 3, 1, 0, 9 }, /* U */ - { 1, 3, 3, 0, 9 }, /* V */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* Y */ + { 1, 4, 0, 0, 10, 3, 9, 1 }, /* U */ + { 1, 4, 2, 0, 10, 3, 9, 3 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, }, @@ -1521,9 +1578,116 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "vda", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, + [AV_PIX_FMT_QSV] = { + .name = "qsv", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, + [AV_PIX_FMT_MMAL] = { + .name = "mmal", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, + [AV_PIX_FMT_CUDA] = { + .name = "cuda", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, + [AV_PIX_FMT_P010LE] = { + .name = "p010le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 2, 0, 6, 10, 1, 9, 1 }, /* Y */ + { 1, 4, 0, 6, 10, 3, 9, 1 }, /* U */ + { 1, 4, 2, 6, 10, 3, 9, 3 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P010BE] = { + .name = "p010be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 2, 0, 6, 10, 1, 9, 1 }, /* Y */ + { 1, 4, 0, 6, 10, 3, 9, 1 }, /* U */ + { 1, 4, 2, 6, 10, 3, 9, 3 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, +}; +#if FF_API_PLUS1_MINUS1 +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +static const char *color_range_names[] = { + [AVCOL_RANGE_UNSPECIFIED] = "unknown", + [AVCOL_RANGE_MPEG] = "tv", + [AVCOL_RANGE_JPEG] = "pc", +}; + +static const char *color_primaries_names[] = { + [AVCOL_PRI_RESERVED0] = "reserved", + [AVCOL_PRI_BT709] = "bt709", + [AVCOL_PRI_UNSPECIFIED] = "unknown", + [AVCOL_PRI_RESERVED] = "reserved", + [AVCOL_PRI_BT470M] = "bt470m", + [AVCOL_PRI_BT470BG] = "bt470bg", + [AVCOL_PRI_SMPTE170M] = "smpte170m", + [AVCOL_PRI_SMPTE240M] = "smpte240m", + [AVCOL_PRI_FILM] = "film", + [AVCOL_PRI_BT2020] = "bt2020", + [AVCOL_PRI_SMPTE428] = "smpte428", + [AVCOL_PRI_SMPTE431] = "smpte431", + [AVCOL_PRI_SMPTE432] = "smpte432", +}; + +static const char *color_transfer_names[] = { + [AVCOL_TRC_RESERVED0] = "reserved", + [AVCOL_TRC_BT709] = "bt709", + [AVCOL_TRC_UNSPECIFIED] = "unknown", + [AVCOL_TRC_RESERVED] = "reserved", + [AVCOL_TRC_GAMMA22] = "bt470m", + [AVCOL_TRC_GAMMA28] = "bt470bg", + [AVCOL_TRC_SMPTE170M] = "smpte170m", + [AVCOL_TRC_SMPTE240M] = "smpte240m", + [AVCOL_TRC_LINEAR] = "linear", + [AVCOL_TRC_LOG] = "log100", + [AVCOL_TRC_LOG_SQRT] = "log316", + [AVCOL_TRC_IEC61966_2_4] = "iec61966-2-4", + [AVCOL_TRC_BT1361_ECG] = "bt1361e", + [AVCOL_TRC_IEC61966_2_1] = "iec61966-2-1", + [AVCOL_TRC_BT2020_10] = "bt2020-10", + [AVCOL_TRC_BT2020_12] = "bt2020-12", + [AVCOL_TRC_SMPTE2084] = "smpte2084", + [AVCOL_TRC_SMPTE428] = "smpte428", + [AVCOL_TRC_ARIB_STD_B67] = "arib-std-b67", +}; + +static const char *color_space_names[] = { + [AVCOL_SPC_RGB] = "gbr", + [AVCOL_SPC_BT709] = "bt709", + [AVCOL_SPC_UNSPECIFIED] = "unknown", + [AVCOL_SPC_RESERVED] = "reserved", + [AVCOL_SPC_FCC] = "fcc", + [AVCOL_SPC_BT470BG] = "bt470bg", + [AVCOL_SPC_SMPTE170M] = "smpte170m", + [AVCOL_SPC_SMPTE240M] = "smpte240m", + [AVCOL_SPC_YCOCG] = "ycgco", + [AVCOL_SPC_BT2020_NCL] = "bt2020nc", + [AVCOL_SPC_BT2020_CL] = "bt2020c", + [AVCOL_SPC_SMPTE2085] = "smpte2085", +}; + +static const char *chroma_location_names[] = { + [AVCHROMA_LOC_UNSPECIFIED] = "unspecified", + [AVCHROMA_LOC_LEFT] = "left", + [AVCHROMA_LOC_CENTER] = "center", + [AVCHROMA_LOC_TOPLEFT] = "topleft", + [AVCHROMA_LOC_TOP] = "top", + [AVCHROMA_LOC_BOTTOMLEFT] = "bottomleft", + [AVCHROMA_LOC_BOTTOM] = "bottom", }; -FF_DISABLE_DEPRECATION_WARNINGS static enum AVPixelFormat get_pix_fmt_internal(const char *name) { enum AVPixelFormat pix_fmt; @@ -1565,6 +1729,11 @@ enum AVPixelFormat av_get_pix_fmt(const char *name) snprintf(name2, sizeof(name2), "%s%s", name, X_NE("be", "le")); pix_fmt = get_pix_fmt_internal(name2); } + +#if FF_API_VAAPI + if (pix_fmt == AV_PIX_FMT_NONE && !strcmp(name, "vaapi")) + pix_fmt = AV_PIX_FMT_VAAPI; +#endif return pix_fmt; } @@ -1575,7 +1744,7 @@ int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc) for (c = 0; c < pixdesc->nb_components; c++) { int s = c == 1 || c == 2 ? 0 : log2_pixels; - bits += (pixdesc->comp[c].depth_minus1 + 1) << s; + bits += pixdesc->comp[c].depth << s; } return bits >> log2_pixels; @@ -1620,7 +1789,6 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc) return desc - av_pix_fmt_descriptors; } -FF_ENABLE_DEPRECATION_WARNINGS int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) @@ -1700,3 +1868,34 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) } #undef PIX_FMT_SWAP_ENDIANNESS } + +const char *av_color_range_name(enum AVColorRange range) +{ + return (unsigned) range < AVCOL_RANGE_NB ? + color_range_names[range] : NULL; +} + +const char *av_color_primaries_name(enum AVColorPrimaries primaries) +{ + return (unsigned) primaries < AVCOL_PRI_NB ? + color_primaries_names[primaries] : NULL; +} + +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer) +{ + return (unsigned) transfer < AVCOL_TRC_NB ? + color_transfer_names[transfer] : NULL; +} + +const char *av_color_space_name(enum AVColorSpace space) +{ + return (unsigned) space < AVCOL_SPC_NB ? + color_space_names[space] : NULL; +} + +const char *av_chroma_location_name(enum AVChromaLocation location) +{ + return (unsigned) location < AVCHROMA_LOC_NB ? + chroma_location_names[location] : NULL; +} + diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index 1c9e0af..3bb10f7 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -31,30 +31,41 @@ typedef struct AVComponentDescriptor { /** * Which of the 4 planes contains the component. */ - uint16_t plane : 2; + int plane; /** - * Number of elements between 2 horizontally consecutive pixels minus 1. + * Number of elements between 2 horizontally consecutive pixels. * Elements are bits for bitstream formats, bytes otherwise. */ - uint16_t step_minus1 : 3; + int step; /** - * Number of elements before the component of the first pixel plus 1. + * Number of elements before the component of the first pixel. * Elements are bits for bitstream formats, bytes otherwise. */ - uint16_t offset_plus1 : 3; + int offset; /** * Number of least significant bits that must be shifted away * to get the value. */ - uint16_t shift : 3; + int shift; /** - * Number of bits in the component minus 1. + * Number of bits in the component. */ - uint16_t depth_minus1 : 4; + int depth; + +#if FF_API_PLUS1_MINUS1 + /** deprecated, use step instead */ + attribute_deprecated int step_minus1; + + /** deprecated, use depth instead */ + attribute_deprecated int depth_minus1; + + /** deprecated, use offset instead */ + attribute_deprecated int offset_plus1; +#endif } AVComponentDescriptor; /** @@ -73,26 +84,37 @@ typedef struct AVPixFmtDescriptor { /** * Amount to shift the luma width right to find the chroma width. * For YV12 this is 1 for example. - * chroma_width = -((-luma_width) >> log2_chroma_w) + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) * The note above is needed to ensure rounding up. * This value only refers to the chroma components. */ - uint8_t log2_chroma_w; ///< chroma_width = -((-luma_width )>>log2_chroma_w) + uint8_t log2_chroma_w; /** * Amount to shift the luma height right to find the chroma height. * For YV12 this is 1 for example. - * chroma_height= -((-luma_height) >> log2_chroma_h) + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) * The note above is needed to ensure rounding up. * This value only refers to the chroma components. */ uint8_t log2_chroma_h; - uint8_t flags; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; /** * Parameters that describe how pixels are packed. If the format * has chroma components, they must be stored in comp[1] and * comp[2]. + * If the format is RGB-like, the first component is R, followed + * by G and B. + * + * If the format is YUV-like, the first component is Y, followed + * by U and V. + * + * If present, the Alpha channel is always the last component. */ AVComponentDescriptor comp[4]; @@ -137,27 +159,6 @@ typedef struct AVPixFmtDescriptor { */ #define AV_PIX_FMT_FLAG_ALPHA (1 << 7) -#if FF_API_PIX_FMT -/** - * @deprecated use the AV_PIX_FMT_FLAG_* flags - */ -#define PIX_FMT_BE AV_PIX_FMT_FLAG_BE -#define PIX_FMT_PAL AV_PIX_FMT_FLAG_PAL -#define PIX_FMT_BITSTREAM AV_PIX_FMT_FLAG_BITSTREAM -#define PIX_FMT_HWACCEL AV_PIX_FMT_FLAG_HWACCEL -#define PIX_FMT_PLANAR AV_PIX_FMT_FLAG_PLANAR -#define PIX_FMT_RGB AV_PIX_FMT_FLAG_RGB -#define PIX_FMT_PSEUDOPAL AV_PIX_FMT_FLAG_PSEUDOPAL -#define PIX_FMT_ALPHA AV_PIX_FMT_FLAG_ALPHA -#endif - -#if FF_API_PIX_FMT_DESC -/** - * The array of all the pixel format descriptors. - */ -extern attribute_deprecated const AVPixFmtDescriptor av_pix_fmt_descriptors[]; -#endif - /** * Read a line from an image, and write the values of the * pixel format component c to dst. @@ -267,8 +268,8 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); * the pixel format AVPixFmtDescriptor. * * @param[in] pix_fmt the pixel format - * @param[out] h_shift store log2_chroma_h - * @param[out] v_shift store log2_chroma_w + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) * * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format */ @@ -291,4 +292,29 @@ int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); */ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + #endif /* AVUTIL_PIXDESC_H */ diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 47951e0..8a8d624 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -24,7 +24,6 @@ /** * @file * pixel format definitions - * */ #include "libavutil/avconfig.h" @@ -34,31 +33,26 @@ * Pixel format. * * @note - * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An 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. * * @par - * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized + * When the pixel format is palettized RGB (AV_PIX_FMT_PAL8), the palettized * image data is stored in AVFrame.data[0]. The palette is transported in * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is - * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is + * formatted the same as in AV_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. * * @par - * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like * for pal8. This palette is filled in automatically by the function * allocating the picture. - * - * @note - * Make sure that all newly added big-endian formats have pix_fmt & 1 == 1 - * and that all newly added little-endian formats have pix_fmt & 1 == 0. - * This allows simpler detection of big vs little-endian. */ enum AVPixelFormat { AV_PIX_FMT_NONE = -1, @@ -73,10 +67,10 @@ enum AVPixelFormat { AV_PIX_FMT_GRAY8, ///< Y , 8bpp AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb - AV_PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette - AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range - AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range - AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range #if FF_API_XVMC AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing AV_PIX_FMT_XVMC_MPEG2_IDCT, @@ -100,7 +94,7 @@ enum AVPixelFormat { AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) - AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) #if FF_API_VDPAU AV_PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers @@ -122,9 +116,14 @@ enum AVPixelFormat { AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 +#if FF_API_VAAPI AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers - AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID + AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD, +#else + AV_PIX_FMT_VAAPI, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID +#endif AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian @@ -133,7 +132,7 @@ enum AVPixelFormat { AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian #if FF_API_VDPAU - AV_PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VDPAU_MPEG4, ///< MPEG-4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers #endif AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer @@ -141,7 +140,7 @@ enum AVPixelFormat { AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 - AV_PIX_FMT_YA8, ///< 8bit gray, 8bit alpha + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 @@ -203,14 +202,35 @@ enum AVPixelFormat { AV_PIX_FMT_VDA, ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef - AV_PIX_FMT_YA16BE, ///< 16bit gray, 16bit alpha (big-endian) - AV_PIX_FMT_YA16LE, ///< 16bit gray, 16bit alpha (little-endian) + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian AV_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 - -#if FF_API_PIX_FMT -#include "old_pix_fmts.h" -#endif }; #if AV_HAVE_BIGENDIAN @@ -251,6 +271,8 @@ enum AVPixelFormat { #define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) #define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + #define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) #define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) #define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) @@ -263,56 +285,27 @@ enum AVPixelFormat { #define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) #define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) - - -#if FF_API_PIX_FMT -#define PixelFormat AVPixelFormat - -#define PIX_FMT_NE(be, le) AV_PIX_FMT_NE(be, le) - -#define PIX_FMT_RGB32 AV_PIX_FMT_RGB32 -#define PIX_FMT_RGB32_1 AV_PIX_FMT_RGB32_1 -#define PIX_FMT_BGR32 AV_PIX_FMT_BGR32 -#define PIX_FMT_BGR32_1 AV_PIX_FMT_BGR32_1 - -#define PIX_FMT_GRAY16 AV_PIX_FMT_GRAY16 -#define PIX_FMT_RGB48 AV_PIX_FMT_RGB48 -#define PIX_FMT_RGB565 AV_PIX_FMT_RGB565 -#define PIX_FMT_RGB555 AV_PIX_FMT_RGB555 -#define PIX_FMT_RGB444 AV_PIX_FMT_RGB444 -#define PIX_FMT_BGR48 AV_PIX_FMT_BGR48 -#define PIX_FMT_BGR565 AV_PIX_FMT_BGR565 -#define PIX_FMT_BGR555 AV_PIX_FMT_BGR555 -#define PIX_FMT_BGR444 AV_PIX_FMT_BGR444 - -#define PIX_FMT_YUV420P9 AV_PIX_FMT_YUV420P9 -#define PIX_FMT_YUV422P9 AV_PIX_FMT_YUV422P9 -#define PIX_FMT_YUV444P9 AV_PIX_FMT_YUV444P9 -#define PIX_FMT_YUV420P10 AV_PIX_FMT_YUV420P10 -#define PIX_FMT_YUV422P10 AV_PIX_FMT_YUV422P10 -#define PIX_FMT_YUV444P10 AV_PIX_FMT_YUV444P10 -#define PIX_FMT_YUV420P16 AV_PIX_FMT_YUV420P16 -#define PIX_FMT_YUV422P16 AV_PIX_FMT_YUV422P16 -#define PIX_FMT_YUV444P16 AV_PIX_FMT_YUV444P16 - -#define PIX_FMT_GBRP9 AV_PIX_FMT_GBRP9 -#define PIX_FMT_GBRP10 AV_PIX_FMT_GBRP10 -#define PIX_FMT_GBRP16 AV_PIX_FMT_GBRP16 -#endif +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) /** * Chromaticity coordinates of the source primaries. */ enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B AVCOL_PRI_UNSPECIFIED = 2, AVCOL_PRI_RESERVED = 3, - AVCOL_PRI_BT470M = 4, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above - AVCOL_PRI_FILM = 8, + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 D65 (2010) AVCOL_PRI_NB, ///< Not part of ABI }; @@ -320,6 +313,7 @@ enum AVColorPrimaries { * Color Transfer Characteristic. */ enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 AVCOL_TRC_UNSPECIFIED = 2, AVCOL_TRC_RESERVED = 3, @@ -333,8 +327,13 @@ enum AVColorTransferCharacteristic { AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) - AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10 bit system - AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12 bit system + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" AVCOL_TRC_NB, ///< Not part of ABI }; @@ -342,17 +341,18 @@ enum AVColorTransferCharacteristic { * YUV colorspace type. */ enum AVColorSpace { - AVCOL_SPC_RGB = 0, + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B AVCOL_SPC_UNSPECIFIED = 2, AVCOL_SPC_RESERVED = 3, - AVCOL_SPC_FCC = 4, + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 - AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above - AVCOL_SPC_SMPTE240M = 7, + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x AVCOL_SPC_NB, ///< Not part of ABI }; @@ -375,8 +375,8 @@ enum AVColorRange { */ enum AVChromaLocation { AVCHROMA_LOC_UNSPECIFIED = 0, - AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default - AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4, H.264 default + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1, JPEG, H.263 AVCHROMA_LOC_TOPLEFT = 3, ///< DV AVCHROMA_LOC_TOP = 4, AVCHROMA_LOC_BOTTOMLEFT = 5, diff --git a/libavutil/ppc/Makefile b/libavutil/ppc/Makefile index 4fd8d6d..a0febf8 100644 --- a/libavutil/ppc/Makefile +++ b/libavutil/ppc/Makefile @@ -2,3 +2,5 @@ OBJS += ppc/cpu.o \ ppc/float_dsp_init.o \ ALTIVEC-OBJS += ppc/float_dsp_altivec.o \ + +VSX-OBJS += ppc/float_dsp_vsx.o \ diff --git a/libavutil/ppc/cpu.c b/libavutil/ppc/cpu.c index 50107e1..2981856 100644 --- a/libavutil/ppc/cpu.c +++ b/libavutil/ppc/cpu.c @@ -18,6 +18,11 @@ #ifdef __APPLE__ #include +#elif defined(__linux__) +#include +#include +#include +#include #elif defined(__OpenBSD__) #include #include @@ -62,18 +67,73 @@ int ff_get_cpu_flags_ppc(void) if (err == 0) return has_vu ? AV_CPU_FLAG_ALTIVEC : 0; return 0; +#elif defined(__linux__) + // The linux kernel could have the altivec support disabled + // even if the cpu has it. + int i, ret = 0; + int fd = open("/proc/self/auxv", O_RDONLY); + unsigned long buf[64] = { 0 }; + ssize_t count; + + if (fd < 0) + return 0; + + while ((count = read(fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < count / sizeof(*buf); i += 2) { + if (buf[i] == AT_NULL) + goto out; + if (buf[i] == AT_HWCAP) { + if (buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC) + ret = AV_CPU_FLAG_ALTIVEC; +#ifdef PPC_FEATURE_HAS_VSX + if (buf[i + 1] & PPC_FEATURE_HAS_VSX) + ret |= AV_CPU_FLAG_VSX; +#endif +#ifdef PPC_FEATURE_ARCH_2_07 + if (buf[i + 1] & PPC_FEATURE_HAS_POWER8) + ret |= AV_CPU_FLAG_POWER8; +#endif + goto out; + } + } + } + +out: + close(fd); + return ret; #elif CONFIG_RUNTIME_CPUDETECT +#define PVR_G4_7400 0x000C +#define PVR_G5_970 0x0039 +#define PVR_G5_970FX 0x003C +#define PVR_G5_970MP 0x0044 +#define PVR_G5_970GX 0x0045 +#define PVR_POWER6 0x003E +#define PVR_POWER7 0x003F +#define PVR_POWER8 0x004B +#define PVR_CELL_PPU 0x0070 + int ret = 0; int proc_ver; // Support of mfspr PVR emulation added in Linux 2.6.17. __asm__ volatile("mfspr %0, 287" : "=r" (proc_ver)); proc_ver >>= 16; if (proc_ver & 0x8000 || - proc_ver == 0x000c || - proc_ver == 0x0039 || proc_ver == 0x003c || - proc_ver == 0x0044 || proc_ver == 0x0045 || - proc_ver == 0x0070) - return AV_CPU_FLAG_ALTIVEC; - return 0; + proc_ver == PVR_G4_7400 || + proc_ver == PVR_G5_970 || + proc_ver == PVR_G5_970FX || + proc_ver == PVR_G5_970MP || + proc_ver == PVR_G5_970GX || + proc_ver == PVR_POWER6 || + proc_ver == PVR_POWER7 || + proc_ver == PVR_POWER8 || + proc_ver == PVR_CELL_PPU) + ret = AV_CPU_FLAG_ALTIVEC; + if (proc_ver == PVR_POWER7 || + proc_ver == PVR_POWER8) + ret |= AV_CPU_FLAG_VSX; + if (proc_ver == PVR_POWER8) + ret |= AV_CPU_FLAG_POWER8; + + return ret; #else // Since we were compiled for AltiVec, just assume we have it // until someone comes up with a proper way (not involving signal hacks). diff --git a/libavutil/ppc/cpu.h b/libavutil/ppc/cpu.h index f8fae58..a8b823f 100644 --- a/libavutil/ppc/cpu.h +++ b/libavutil/ppc/cpu.h @@ -24,5 +24,7 @@ #include "libavutil/cpu_internal.h" #define PPC_ALTIVEC(flags) CPUEXT(flags, ALTIVEC) +#define PPC_VSX(flags) CPUEXT(flags, VSX) +#define PPC_POWER8(flags) CPUEXT(flags, POWER8) #endif /* AVUTIL_PPC_CPU_H */ diff --git a/libavutil/ppc/float_dsp_altivec.c b/libavutil/ppc/float_dsp_altivec.c index fee4e7c..f6918e1 100644 --- a/libavutil/ppc/float_dsp_altivec.c +++ b/libavutil/ppc/float_dsp_altivec.c @@ -25,7 +25,7 @@ void ff_vector_fmul_altivec(float *dst, const float *src0, const float *src1, int len) { int i; - vector float d0, d1, s, zero = (vector float)vec_splat_u32(0); + vec_f d0, d1, s, zero = (vec_f)vec_splat_u32(0); for (i = 0; i < len - 7; i += 8) { d0 = vec_ld( 0, src0 + i); s = vec_ld( 0, src1 + i); @@ -40,15 +40,15 @@ void ff_vector_fmul_altivec(float *dst, const float *src0, const float *src1, void ff_vector_fmul_window_altivec(float *dst, const float *src0, const float *src1, const float *win, int len) { - vector float zero, t0, t1, s0, s1, wi, wj; - const vector unsigned char reverse = vcprm(3, 2, 1, 0); + vec_f zero, t0, t1, s0, s1, wi, wj; + const vec_u8 reverse = vcprm(3, 2, 1, 0); int i, j; dst += len; win += len; src0 += len; - zero = (vector float)vec_splat_u32(0); + zero = (vec_f)vec_splat_u32(0); for (i = -len * 4, j = len * 4 - 16; i < 0; i += 16, j -= 16) { s0 = vec_ld(i, src0); @@ -75,9 +75,9 @@ void ff_vector_fmul_add_altivec(float *dst, const float *src0, int len) { int i; - vector float d, s0, s1, s2, t0, t1, edges; - vector unsigned char align = vec_lvsr(0,dst), - mask = vec_lvsl(0, dst); + vec_f d, s0, s1, s2, t0, t1, edges; + vec_u8 align = vec_lvsr(0, dst); + vec_u8 mask = vec_lvsl(0, dst); for (i = 0; i < len - 3; i += 4) { t0 = vec_ld(0, dst + i); @@ -98,8 +98,8 @@ void ff_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); + vec_f d, s0, s1, h0, l0, s2, s3; + vec_f zero = (vec_f)vec_splat_u32(0); src1 += len-4; for(i = 0; i < len - 7; i += 8) { diff --git a/libavutil/ppc/float_dsp_init.c b/libavutil/ppc/float_dsp_init.c index 60d0f19..4407962 100644 --- a/libavutil/ppc/float_dsp_init.c +++ b/libavutil/ppc/float_dsp_init.c @@ -24,17 +24,26 @@ #include "libavutil/float_dsp.h" #include "libavutil/ppc/cpu.h" #include "float_dsp_altivec.h" +#include "float_dsp_vsx.h" av_cold void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int bit_exact) { - if (!PPC_ALTIVEC(av_get_cpu_flags())) - return; + if (HAVE_BIGENDIAN && PPC_ALTIVEC(av_get_cpu_flags())) { + fdsp->vector_fmul = ff_vector_fmul_altivec; + fdsp->vector_fmul_add = ff_vector_fmul_add_altivec; + fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_altivec; - fdsp->vector_fmul = ff_vector_fmul_altivec; - fdsp->vector_fmul_add = ff_vector_fmul_add_altivec; - fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_altivec; + if (!bit_exact) { + fdsp->vector_fmul_window = ff_vector_fmul_window_altivec; + } + } + if (PPC_VSX(av_get_cpu_flags())) { + fdsp->vector_fmul = ff_vector_fmul_vsx; + fdsp->vector_fmul_add = ff_vector_fmul_add_vsx; + fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vsx; - if (!bit_exact) { - fdsp->vector_fmul_window = ff_vector_fmul_window_altivec; + if (!bit_exact) { + fdsp->vector_fmul_window = ff_vector_fmul_window_vsx; + } } } diff --git a/libavutil/ppc/float_dsp_vsx.c b/libavutil/ppc/float_dsp_vsx.c new file mode 100644 index 0000000..4135db1 --- /dev/null +++ b/libavutil/ppc/float_dsp_vsx.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "util_altivec.h" +#include "float_dsp_vsx.h" + +void ff_vector_fmul_vsx(float *dst, + const float *src0, const float *src1, + int len) +{ + int i; + vec_f d0, d1, zero = (vec_f)vec_splat_u32(0); + for (i = 0; i < len - 7; i += 8) { + d0 = vec_vsx_ld( 0, src0 + i); + d1 = vec_vsx_ld(16, src0 + i); + d0 = vec_madd(d0, vec_vsx_ld( 0, src1 + i), zero); + d1 = vec_madd(d1, vec_vsx_ld(16, src1 + i), zero); + vec_vsx_st(d0, 0, dst + i); + vec_vsx_st(d1, 16, dst + i); + } +} + +void ff_vector_fmul_window_vsx(float *dst, const float *src0, + const float *src1, const float *win, + int len) +{ + vec_f zero, t0, t1, s0, s1, wi, wj; + const vec_u8 reverse = vcprm(3, 2, 1, 0); + int i, j; + + dst += len; + win += len; + src0 += len; + + zero = (vec_f)vec_splat_u32(0); + + for (i = -len * 4, j = len * 4 - 16; i < 0; i += 16, j -= 16) { + s0 = vec_vsx_ld(i, src0); + s1 = vec_vsx_ld(j, src1); + wi = vec_vsx_ld(i, win); + wj = vec_vsx_ld(j, win); + + s1 = vec_perm(s1, s1, reverse); + wj = vec_perm(wj, wj, reverse); + + t0 = vec_madd(s0, wj, zero); + t0 = vec_nmsub(s1, wi, t0); + t1 = vec_madd(s0, wi, zero); + t1 = vec_madd(s1, wj, t1); + t1 = vec_perm(t1, t1, reverse); + + vec_vsx_st(t0, i, dst); + vec_vsx_st(t1, j, dst); + } +} + +void ff_vector_fmul_add_vsx(float *dst, const float *src0, + const float *src1, const float *src2, + int len) +{ + int i; + vec_f d, s0, s1, s2; + + for (i = 0; i < len - 3; i += 4) { + s0 = vec_vsx_ld(0, src0 + i); + s1 = vec_vsx_ld(0, src1 + i); + s2 = vec_vsx_ld(0, src2 + i); + d = vec_madd(s0, s1, s2); + vec_vsx_st(d, 0, dst + i); + } +} + +void ff_vector_fmul_reverse_vsx(float *dst, const float *src0, + const float *src1, int len) +{ + int i; + vec_f d, s0, s1, h0, l0, s2, s3; + vec_f zero = (vec_f)vec_splat_u32(0); + + src1 += len - 4; + for (i = 0; i < len - 7; i += 8) { + s1 = vec_vsx_ld(0, src1 - i); // [a,b,c,d] + s0 = vec_vsx_ld(0, src0 + i); + l0 = vec_mergel(s1, s1); // [c,c,d,d] + s3 = vec_vsx_ld(-16, src1 - i); + h0 = vec_mergeh(s1, s1); // [a,a,b,b] + s2 = vec_vsx_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_vsx_st(d, 0, dst + i); + s3 = vec_mergeh(vec_mergel(l0, h0), + vec_mergeh(l0, h0)); + d = vec_madd(s2, s3, zero); + vec_vsx_st(d, 16, dst + i); + } +} diff --git a/libavutil/ppc/float_dsp_vsx.h b/libavutil/ppc/float_dsp_vsx.h new file mode 100644 index 0000000..32860dc --- /dev/null +++ b/libavutil/ppc/float_dsp_vsx.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Luca Barbato + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PPC_FLOAT_DSP_VSX_H +#define AVUTIL_PPC_FLOAT_DSP_VSX_H + +void ff_vector_fmul_vsx(float *dst, const float *src0, + const float *src1, int len); + +void ff_vector_fmul_window_vsx(float *dst, const float *src0, + const float *src1, const float *win, + int len); + +void ff_vector_fmul_add_vsx(float *dst, const float *src0, + const float *src1, const float *src2, + int len); + +void ff_vector_fmul_reverse_vsx(float *dst, const float *src0, + const float *src1, int len); + +#endif /* AVUTIL_PPC_FLOAT_DSP_VSX_H */ diff --git a/libavutil/ppc/intreadwrite.h b/libavutil/ppc/intreadwrite.h index fec54e6..8f8078d 100644 --- a/libavutil/ppc/intreadwrite.h +++ b/libavutil/ppc/intreadwrite.h @@ -26,54 +26,65 @@ #if HAVE_XFORM_ASM -#define AV_RL16 AV_RL16 -static av_always_inline uint16_t AV_RL16(const void *p) +#if HAVE_BIGENDIAN +#define AV_RL16 av_read_bswap16 +#define AV_WL16 av_write_bswap16 +#define AV_RL32 av_read_bswap32 +#define AV_WL32 av_write_bswap32 +#define AV_RL64 av_read_bswap64 +#define AV_WL64 av_write_bswap64 + +#else +#define AV_RB16 av_read_bswap16 +#define AV_WB16 av_write_bswap16 +#define AV_RB32 av_read_bswap32 +#define AV_WB32 av_write_bswap32 +#define AV_RB64 av_read_bswap64 +#define AV_WB64 av_write_bswap64 + +#endif + +static av_always_inline uint16_t av_read_bswap16(const void *p) { uint16_t v; __asm__ ("lhbrx %0, %y1" : "=r"(v) : "Z"(*(const uint16_t*)p)); return v; } -#define AV_WL16 AV_WL16 -static av_always_inline void AV_WL16(void *p, uint16_t v) +static av_always_inline void av_write_bswap16(void *p, uint16_t v) { __asm__ ("sthbrx %1, %y0" : "=Z"(*(uint16_t*)p) : "r"(v)); } -#define AV_RL32 AV_RL32 -static av_always_inline uint32_t AV_RL32(const void *p) +static av_always_inline uint32_t av_read_bswap32(const void *p) { uint32_t v; __asm__ ("lwbrx %0, %y1" : "=r"(v) : "Z"(*(const uint32_t*)p)); return v; } -#define AV_WL32 AV_WL32 -static av_always_inline void AV_WL32(void *p, uint32_t v) +static av_always_inline void av_write_bswap32(void *p, uint32_t v) { __asm__ ("stwbrx %1, %y0" : "=Z"(*(uint32_t*)p) : "r"(v)); } #if HAVE_LDBRX -#define AV_RL64 AV_RL64 -static av_always_inline uint64_t AV_RL64(const void *p) +static av_always_inline uint64_t av_read_bswap64(const void *p) { uint64_t v; __asm__ ("ldbrx %0, %y1" : "=r"(v) : "Z"(*(const uint64_t*)p)); return v; } -#define AV_WL64 AV_WL64 -static av_always_inline void AV_WL64(void *p, uint64_t v) +static av_always_inline void av_write_bswap64(void *p, uint64_t v) { __asm__ ("stdbrx %1, %y0" : "=Z"(*(uint64_t*)p) : "r"(v)); } #else -#define AV_RL64 AV_RL64 -static av_always_inline uint64_t AV_RL64(const void *p) +static av_always_inline uint64_t av_read_bswap64(const void *p) { union { uint64_t v; uint32_t hl[2]; } v; __asm__ ("lwbrx %0, %y2 \n\t" @@ -83,8 +94,7 @@ static av_always_inline uint64_t AV_RL64(const void *p) return v.v; } -#define AV_WL64 AV_WL64 -static av_always_inline void AV_WL64(void *p, uint64_t v) +static av_always_inline void av_write_bswap64(void *p, uint64_t v) { union { uint64_t v; uint32_t hl[2]; } vv = { v }; __asm__ ("stwbrx %2, %y0 \n\t" @@ -97,12 +107,4 @@ static av_always_inline void AV_WL64(void *p, uint64_t v) #endif /* HAVE_XFORM_ASM */ -/* - * GCC fails miserably on the packed struct version which is used by - * default, so we override it here. - */ - -#define AV_RB64(p) (*(const uint64_t *)(p)) -#define AV_WB64(p, v) (*(uint64_t *)(p) = (v)) - #endif /* AVUTIL_PPC_INTREADWRITE_H */ diff --git a/libavutil/ppc/util_altivec.h b/libavutil/ppc/util_altivec.h index 5624ac5..02cff18 100644 --- a/libavutil/ppc/util_altivec.h +++ b/libavutil/ppc/util_altivec.h @@ -47,14 +47,14 @@ #define WORD_s2 0x18,0x19,0x1a,0x1b #define WORD_s3 0x1c,0x1d,0x1e,0x1f -#define vcprm(a,b,c,d) (const vector unsigned char){WORD_ ## a, WORD_ ## b, WORD_ ## c, WORD_ ## d} +#define vcprm(a,b,c,d) (const vec_u8){WORD_ ## a, WORD_ ## b, WORD_ ## c, WORD_ ## d} // 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; \ + vec_s16 A1, B1, C1, D1, E1, F1, G1, H1; \ + vec_s16 A2, B2, C2, D2, E2, F2, G2, H2; \ \ A1 = vec_mergeh (a, e); \ B1 = vec_mergel (a, e); \ @@ -87,11 +87,11 @@ do { \ /** @brief loads unaligned vector @a *src with offset @a offset and returns it */ -static inline vector unsigned char unaligned_load(int offset, uint8_t *src) +static inline vec_u8 unaligned_load(int offset, uint8_t *src) { - register vector unsigned char first = vec_ld(offset, src); - register vector unsigned char second = vec_ld(offset+15, src); - register vector unsigned char mask = vec_lvsl(offset, src); + register vec_u8 first = vec_ld(offset, src); + register vec_u8 second = vec_ld(offset + 15, src); + register vec_u8 mask = vec_lvsl(offset, src); return vec_perm(first, second, mask); } @@ -102,7 +102,7 @@ static inline vector unsigned char unaligned_load(int offset, uint8_t *src) static inline vec_u8 load_with_perm_vec(int offset, uint8_t *src, vec_u8 perm_vec) { vec_u8 a = vec_ld(offset, src); - vec_u8 b = vec_ld(offset+15, src); + vec_u8 b = vec_ld(offset + 15, src); return vec_perm(a, b, perm_vec); } @@ -111,4 +111,16 @@ static inline vec_u8 load_with_perm_vec(int offset, uint8_t *src, vec_u8 perm_ve #endif /* HAVE_ALTIVEC */ +#if HAVE_VSX +#if HAVE_BIGENDIAN +#define vsx_ld_u8_s16(off, p) \ + ((vec_s16)vec_mergeh((vec_u8)vec_splat_u8(0), \ + (vec_u8)vec_vsx_ld((off), (p)))) +#else +#define vsx_ld_u8_s16(off, p) \ + ((vec_s16)vec_mergeh((vec_u8)vec_vsx_ld((off), (p)), \ + (vec_u8)vec_splat_u8(0))) +#endif /* HAVE_BIGENDIAN */ +#endif /* HAVE_VSX */ + #endif /* AVUTIL_PPC_UTIL_ALTIVEC_H */ diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 26884cb..5bbdf38 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -79,7 +79,7 @@ static uint32_t get_generic_seed(void) if (!sha) { uint32_t seed = 0; int j; - // Unable to allocate an sha context, just xor the buffer together + // Unable to allocate an SHA context, just XOR the buffer together // to create something hopefully unique. for (j = 0; j < 512; j++) seed ^= buffer[j]; diff --git a/libavutil/rc4.c b/libavutil/rc4.c index 3bf710f..36b0de9 100644 --- a/libavutil/rc4.c +++ b/libavutil/rc4.c @@ -22,9 +22,20 @@ */ #include "avutil.h" #include "common.h" +#include "mem.h" #include "rc4.h" -typedef struct AVRC4 AVRC4; +#if !FF_API_CRYPTO_CONTEXT +struct AVRC4 { + uint8_t state[256]; + int x, y; +}; +#endif + +AVRC4 *av_rc4_alloc(void) +{ + return av_mallocz(sizeof(struct AVRC4)); +} int av_rc4_init(AVRC4 *r, const uint8_t *key, int key_bits, int decrypt) { int i, j; diff --git a/libavutil/rc4.h b/libavutil/rc4.h index ec3b47c..38ae52f 100644 --- a/libavutil/rc4.h +++ b/libavutil/rc4.h @@ -22,17 +22,34 @@ #define AVUTIL_RC4_H #include +#include "version.h" -struct AVRC4 { +/** + * @defgroup lavu_rc4 RC4 + * @ingroup lavu_crypto + * @{ + */ + +#if FF_API_CRYPTO_CONTEXT +typedef struct AVRC4 { uint8_t state[256]; int x, y; -}; +} AVRC4; +#else +typedef struct AVRC4 AVRC4; +#endif + +/** + * Allocate an AVRC4 context. + */ +AVRC4 *av_rc4_alloc(void); /** * @brief Initializes an AVRC4 context. * * @param key_bits must be a multiple of 8 * @param decrypt 0 for encryption, 1 for decryption, currently has no effect + * @return zero on success, negative value otherwise */ int av_rc4_init(struct AVRC4 *d, const uint8_t *key, int key_bits, int decrypt); @@ -47,4 +64,8 @@ int av_rc4_init(struct AVRC4 *d, const uint8_t *key, int key_bits, int decrypt); */ void av_rc4_crypt(struct AVRC4 *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); +/** + * @} + */ + #endif /* AVUTIL_RC4_H */ diff --git a/libavutil/replaygain.h b/libavutil/replaygain.h index 7871d2c..15da873 100644 --- a/libavutil/replaygain.h +++ b/libavutil/replaygain.h @@ -1,5 +1,4 @@ /* - * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index 8347fac..a770746 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -32,7 +32,6 @@ * * Audio sample format enumeration and related convenience functions. * @{ - * */ /** diff --git a/libavutil/sha.c b/libavutil/sha.c index 2d9b58c..404effa 100644 --- a/libavutil/sha.c +++ b/libavutil/sha.c @@ -40,10 +40,6 @@ typedef struct AVSHA { void (*transform)(uint32_t *state, const uint8_t buffer[64]); } AVSHA; -#if FF_API_CONTEXT_SIZE -const int av_sha_size = sizeof(AVSHA); -#endif - struct AVSHA *av_sha_alloc(void) { return av_mallocz(sizeof(struct AVSHA)); @@ -333,55 +329,3 @@ void av_sha_final(AVSHA* ctx, uint8_t *digest) for (i = 0; i < ctx->digest_len; i++) AV_WB32(digest + i*4, ctx->state[i]); } - -#ifdef TEST -#include - -int main(void) -{ - int i, j, k; - AVSHA ctx; - unsigned char digest[32]; - const int lengths[3] = { 160, 224, 256 }; - - for (j = 0; j < 3; j++) { - printf("Testing SHA-%d\n", lengths[j]); - for (k = 0; k < 3; k++) { - av_sha_init(&ctx, lengths[j]); - if (k == 0) - av_sha_update(&ctx, "abc", 3); - else if (k == 1) - av_sha_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); - else - for (i = 0; i < 1000*1000; i++) - av_sha_update(&ctx, "a", 1); - av_sha_final(&ctx, digest); - for (i = 0; i < lengths[j] >> 3; i++) - printf("%02X", digest[i]); - putchar('\n'); - } - switch (j) { - case 0: - //test vectors (from FIPS PUB 180-1) - printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n" - "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n" - "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n"); - break; - case 1: - //test vectors (from FIPS PUB 180-2 Appendix A) - printf("23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7\n" - "75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525\n" - "20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67\n"); - break; - case 2: - //test vectors (from FIPS PUB 180-2) - printf("ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad\n" - "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1\n" - "cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0\n"); - break; - } - } - - return 0; -} -#endif diff --git a/libavutil/sha.h b/libavutil/sha.h index 4c9a0c9..86ea0b0 100644 --- a/libavutil/sha.h +++ b/libavutil/sha.h @@ -32,10 +32,6 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_sha_size; -#endif - struct AVSHA; /** diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c index 2dcfddf..0d72609 100644 --- a/libavutil/stereo3d.c +++ b/libavutil/stereo3d.c @@ -21,6 +21,7 @@ #include #include +#include "common.h" #include "mem.h" #include "stereo3d.h" @@ -41,3 +42,35 @@ AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame) return (AVStereo3D *)side_data->data; } + +static const char *stereo3d_type_names[] = { + [AV_STEREO3D_2D] = "2D", + [AV_STEREO3D_SIDEBYSIDE] = "side by side", + [AV_STEREO3D_TOPBOTTOM] = "top and bottom", + [AV_STEREO3D_FRAMESEQUENCE] = "frame alternate", + [AV_STEREO3D_CHECKERBOARD] = "checkerboard", + [AV_STEREO3D_SIDEBYSIDE_QUINCUNX] = "side by side (quincunx subsampling)", + [AV_STEREO3D_LINES] = "interleaved lines", + [AV_STEREO3D_COLUMNS] = "interleaved columns", +}; + +const char *av_stereo3d_type_name(unsigned int type) +{ + if (type >= FF_ARRAY_ELEMS(stereo3d_type_names)) + return "unknown"; + + return stereo3d_type_names[type]; +} + +int av_stereo3d_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(stereo3d_type_names); i++) { + size_t len = strlen(stereo3d_type_names[i]); + if (!strncmp(stereo3d_type_names[i], name, len)) + return i; + } + + return -1; +} diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h index b1910b1..aea1b70 100644 --- a/libavutil/stereo3d.h +++ b/libavutil/stereo3d.h @@ -149,4 +149,22 @@ AVStereo3D *av_stereo3d_alloc(void); */ AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame); +/** + * Provide a human-readable name of a given stereo3d type. + * + * @param type The input stereo3d type value. + * + * @return The name of the stereo3d value, or "unknown". + */ +const char *av_stereo3d_type_name(unsigned int type); + +/** + * Get the AVStereo3DType form a human-readable name. + * + * @param type The input string. + * + * @return The AVStereo3DType value, or -1 if not found. + */ +int av_stereo3d_from_name(const char *name); + #endif /* AVUTIL_STEREO3D_H */ diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore new file mode 100644 index 0000000..c4d1d06 --- /dev/null +++ b/libavutil/tests/.gitignore @@ -0,0 +1,21 @@ +/adler32 +/aes +/atomic +/avstring +/base64 +/blowfish +/cpu +/crc +/des +/eval +/fifo +/float_dsp +/hmac +/lfg +/lls +/md5 +/opt +/parseutils +/sha +/tree +/xtea diff --git a/libavutil/tests/adler32.c b/libavutil/tests/adler32.c new file mode 100644 index 0000000..3236900 --- /dev/null +++ b/libavutil/tests/adler32.c @@ -0,0 +1,51 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/log.h" +#include "libavutil/timer.h" +#include "libavutil/adler32.h" + +#define LEN 7001 + +static volatile int checksum; + +int main(int argc, char **argv) +{ + int i; + char data[LEN]; + + av_log_set_level(AV_LOG_DEBUG); + + for (i = 0; i < LEN; i++) + data[i] = ((i * i) >> 3) + 123 * i; + + if (argc > 1 && !strcmp(argv[1], "-t")) { + for (i = 0; i < 1000; i++) { + START_TIMER; + checksum = av_adler32_update(1, data, LEN); + STOP_TIMER("adler"); + } + } else { + checksum = av_adler32_update(1, data, LEN); + } + + av_log(NULL, AV_LOG_DEBUG, "%X (expected 50E6E508)\n", checksum); + return checksum == 0x50e6e508 ? 0 : 1; +} diff --git a/libavutil/tests/aes.c b/libavutil/tests/aes.c new file mode 100644 index 0000000..49ca553 --- /dev/null +++ b/libavutil/tests/aes.c @@ -0,0 +1,92 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aes.c" + +#include + +#include "libavutil/lfg.h" +#include "libavutil/log.h" + +int main(int argc, char **argv) +{ + int i, j; + AVAES b; + static const uint8_t rkey[2][16] = { + { 0 }, + { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, + 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 } + }; + static const uint8_t rpt[2][16] = { + { 0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad, + 0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3 }, + { 0 } + }; + static const uint8_t rct[2][16] = { + { 0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7, + 0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf }, + { 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, + 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65 } + }; + uint8_t pt[16], temp[16]; + int err = 0; + + av_log_set_level(AV_LOG_DEBUG); + + for (i = 0; i < 2; i++) { + av_aes_init(&b, rkey[i], 128, 1); + av_aes_crypt(&b, temp, rct[i], 1, NULL, 1); + for (j = 0; j < 16; j++) { + if (rpt[i][j] != temp[j]) { + av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n", + j, rpt[i][j], temp[j]); + err = 1; + } + } + } + + if (argc > 1 && !strcmp(argv[1], "-t")) { + AVAES ae, ad; + AVLFG prng; + + av_aes_init(&ae, "PI=3.141592654..", 128, 0); + av_aes_init(&ad, "PI=3.141592654..", 128, 1); + av_lfg_init(&prng, 1); + + for (i = 0; i < 10000; i++) { + for (j = 0; j < 16; j++) + pt[j] = av_lfg_get(&prng); + { + START_TIMER; + av_aes_crypt(&ae, temp, pt, 1, NULL, 0); + if (!(i & (i - 1))) + av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n", + temp[0], temp[5], temp[10], temp[15]); + av_aes_crypt(&ad, temp, temp, 1, NULL, 1); + STOP_TIMER("aes"); + } + for (j = 0; j < 16; j++) { + if (pt[j] != temp[j]) { + av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n", + i, j, pt[j], temp[j]); + } + } + } + } + return err; +} diff --git a/libavutil/tests/atomic.c b/libavutil/tests/atomic.c new file mode 100644 index 0000000..70636f4 --- /dev/null +++ b/libavutil/tests/atomic.c @@ -0,0 +1,35 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/atomic.h" + +int main(void) +{ + volatile int val = 1; + int res; + + res = avpriv_atomic_int_add_and_fetch(&val, 1); + assert(res == 2); + avpriv_atomic_int_set(&val, 3); + res = avpriv_atomic_int_get(&val); + assert(res == 3); + + return 0; +} diff --git a/libavutil/tests/avstring.c b/libavutil/tests/avstring.c new file mode 100644 index 0000000..2e5ee2d --- /dev/null +++ b/libavutil/tests/avstring.c @@ -0,0 +1,69 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "libavutil/avstring.h" + +int main(void) +{ + int i; + static const char *strings[] = { + "''", + "", + ":", + "\\", + "'", + " '' :", + " '' '' :", + "foo '' :", + "'foo'", + "foo ", + " ' foo ' ", + "foo\\", + "foo': blah:blah", + "foo\\: blah:blah", + "foo\'", + "'foo : ' :blahblah", + "\\ :blah", + " foo", + " foo ", + " foo \\ ", + "foo ':blah", + " foo bar : blahblah", + "\\f\\o\\o", + "'foo : \\ \\ ' : blahblah", + "'\\fo\\o:': blahblah", + "\\'fo\\o\\:': foo ' :blahblah" + }; + + printf("Testing av_get_token()\n"); + for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) { + const char *p = strings[i]; + char *q; + printf("|%s|", p); + q = av_get_token(&p, ":"); + printf(" -> |%s|", q); + printf(" + |%s|\n", p); + av_free(q); + } + + return 0; +} diff --git a/libavutil/tests/base64.c b/libavutil/tests/base64.c new file mode 100644 index 0000000..16ea399 --- /dev/null +++ b/libavutil/tests/base64.c @@ -0,0 +1,84 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/base64.h" + +#define MAX_DATA_SIZE 1024 +#define MAX_ENCODED_SIZE 2048 + +static int test_encode_decode(const uint8_t *data, unsigned int data_size, + const char *encoded_ref) +{ + char encoded[MAX_ENCODED_SIZE]; + uint8_t data2[MAX_DATA_SIZE]; + int data2_size, max_data2_size = MAX_DATA_SIZE; + + if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) { + printf("Failed: cannot encode the input data\n"); + return 1; + } + if (encoded_ref && strcmp(encoded, encoded_ref)) { + printf("Failed: encoded string differs from reference\n" + "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref); + return 1; + } + + if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) { + printf("Failed: cannot decode the encoded string\n" + "Encoded:\n%s\n", encoded); + return 1; + } + if (memcmp(data2, data, data_size)) { + printf("Failed: encoded/decoded data differs from original data\n"); + return 1; + } + + printf("Passed!\n"); + return 0; +} + +int main(void) +{ + int i, error_count = 0; + struct test { + const uint8_t *data; + const char *encoded_ref; + } tests[] = { + { "", ""}, + { "1", "MQ=="}, + { "22", "MjI="}, + { "333", "MzMz"}, + { "4444", "NDQ0NA=="}, + { "55555", "NTU1NTU="}, + { "666666", "NjY2NjY2"}, + { "abc:def", "YWJjOmRlZg=="}, + }; + + printf("Encoding/decoding tests\n"); + for (i = 0; i < FF_ARRAY_ELEMS(tests); i++) + error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref); + + if (error_count) + printf("Error Count: %d.\n", error_count); + + return !!error_count; +} diff --git a/libavutil/tests/blowfish.c b/libavutil/tests/blowfish.c new file mode 100644 index 0000000..301c616 --- /dev/null +++ b/libavutil/tests/blowfish.c @@ -0,0 +1,194 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "libavutil/mem.h" +#include "libavutil/blowfish.h" + +#define NUM_VARIABLE_KEY_TESTS 34 + +/* plaintext bytes -- left halves */ +static const uint32_t plaintext_l[NUM_VARIABLE_KEY_TESTS] = { + 0x00000000, 0xFFFFFFFF, 0x10000000, 0x11111111, 0x11111111, + 0x01234567, 0x00000000, 0x01234567, 0x01A1D6D0, 0x5CD54CA8, + 0x0248D438, 0x51454B58, 0x42FD4430, 0x059B5E08, 0x0756D8E0, + 0x762514B8, 0x3BDD1190, 0x26955F68, 0x164D5E40, 0x6B056E18, + 0x004BD6EF, 0x480D3900, 0x437540C8, 0x072D43A0, 0x02FE5577, + 0x1D9D5C50, 0x30553228, 0x01234567, 0x01234567, 0x01234567, + 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF +}; + +/* plaintext bytes -- right halves */ +static const uint32_t plaintext_r[NUM_VARIABLE_KEY_TESTS] = { + 0x00000000, 0xFFFFFFFF, 0x00000001, 0x11111111, 0x11111111, + 0x89ABCDEF, 0x00000000, 0x89ABCDEF, 0x39776742, 0x3DEF57DA, + 0x06F67172, 0x2DDF440A, 0x59577FA2, 0x51CF143A, 0x774761D2, + 0x29BF486A, 0x49372802, 0x35AF609A, 0x4F275232, 0x759F5CCA, + 0x09176062, 0x6EE762F2, 0x698F3CFA, 0x77075292, 0x8117F12A, + 0x18F728C2, 0x6D6F295A, 0x89ABCDEF, 0x89ABCDEF, 0x89ABCDEF, + 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF +}; + +/* key bytes for variable key tests */ +static const uint8_t variable_key[NUM_VARIABLE_KEY_TESTS][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 }, + { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E }, + { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 }, + { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E }, + { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 }, + { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE }, + { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 }, + { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE }, + { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 }, + { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F }, + { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 }, + { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E }, + { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 }, + { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 }, + { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F }, + { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 }, + { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF }, + { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 }, + { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 } +}; + +/* ciphertext bytes -- left halves */ +static const uint32_t ciphertext_l[NUM_VARIABLE_KEY_TESTS] = { + 0x4EF99745, 0x51866FD5, 0x7D856F9A, 0x2466DD87, 0x61F9C380, + 0x7D0CC630, 0x4EF99745, 0x0ACEAB0F, 0x59C68245, 0xB1B8CC0B, + 0x1730E577, 0xA25E7856, 0x353882B1, 0x48F4D088, 0x432193B7, + 0x13F04154, 0x2EEDDA93, 0xD887E039, 0x5F99D04F, 0x4A057A3B, + 0x452031C1, 0x7555AE39, 0x53C55F9C, 0x7A8E7BFA, 0xCF9C5D7A, + 0xD1ABB290, 0x55CB3774, 0xFA34EC48, 0xA7907951, 0xC39E072D, + 0x014933E0, 0xF21E9A77, 0x24594688, 0x6B5C5A9C +}; + +/* ciphertext bytes -- right halves */ +static const uint32_t ciphertext_r[NUM_VARIABLE_KEY_TESTS] = { + 0x6198DD78, 0xB85ECB8A, 0x613063F2, 0x8B963C9D, 0x2281B096, + 0xAFDA1EC7, 0x6198DD78, 0xC6A0A28D, 0xEB05282B, 0x250F09A0, + 0x8BEA1DA4, 0xCF2651EB, 0x09CE8F1A, 0x4C379918, 0x8951FC98, + 0xD69D1AE5, 0xFFD39C79, 0x3C2DA6E3, 0x5B163969, 0x24D3977B, + 0xE4FADA8E, 0xF59B87BD, 0xB49FC019, 0x937E89A3, 0x4986ADB5, + 0x658BC778, 0xD13EF201, 0x47B268B2, 0x08EA3CAE, 0x9FAC631D, + 0xCDAFF6E4, 0xB71C49BC, 0x5754369A, 0x5D9E0A5A +}; + +/* plaintext bytes */ +static const uint8_t plaintext[8] = "BLOWFISH"; + +static const uint8_t plaintext2[16] = "BLOWFISHBLOWFISH"; + +/* ciphertext bytes */ +static const uint8_t ciphertext[8] = { + 0x32, 0x4E, 0xD0, 0xFE, 0xF4, 0x13, 0xA2, 0x03 +}; + +static const uint8_t ciphertext2[16] = { + 0x53, 0x00, 0x40, 0x06, 0x63, 0xf2, 0x1d, 0x99, + 0x3b, 0x9b, 0x27, 0x64, 0x46, 0xfd, 0x20, 0xc1, +}; + +#define IV "blowfish" + +static void test_blowfish(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src, + const uint8_t *ref, int len, uint8_t *iv, int dir, + const char *test) +{ + av_blowfish_crypt(ctx, dst, src, len, iv, dir); + if (memcmp(dst, ref, 8*len)) { + int i; + printf("%s failed\ngot ", test); + for (i = 0; i < 8*len; i++) + printf("%02x ", dst[i]); + printf("\nexpected "); + for (i = 0; i < 8*len; i++) + printf("%02x ", ref[i]); + printf("\n"); + exit(1); + } +} + +int main(void) +{ + uint32_t tmptext_l[NUM_VARIABLE_KEY_TESTS]; + uint32_t tmptext_r[NUM_VARIABLE_KEY_TESTS]; + uint8_t tmp[16], iv[8]; + int i; + AVBlowfish *ctx = av_blowfish_alloc(); + if (!ctx) + return 1; + + av_blowfish_init(ctx, "abcdefghijklmnopqrstuvwxyz", 26); + + test_blowfish(ctx, tmp, plaintext, ciphertext, 1, NULL, 0, "encryption"); + test_blowfish(ctx, tmp, ciphertext, plaintext, 1, NULL, 1, "decryption"); + test_blowfish(ctx, tmp, tmp, ciphertext, 1, NULL, 0, "Inplace encryption"); + test_blowfish(ctx, tmp, tmp, plaintext, 1, NULL, 1, "Inplace decryption"); + memcpy(iv, IV, 8); + test_blowfish(ctx, tmp, plaintext2, ciphertext2, 2, iv, 0, "CBC encryption"); + memcpy(iv, IV, 8); + test_blowfish(ctx, tmp, ciphertext2, plaintext2, 2, iv, 1, "CBC decryption"); + memcpy(iv, IV, 8); + test_blowfish(ctx, tmp, tmp, ciphertext2, 2, iv, 0, "Inplace CBC encryption"); + memcpy(iv, IV, 8); + test_blowfish(ctx, tmp, tmp, plaintext2, 2, iv, 1, "Inplace CBC decryption"); + + memcpy(tmptext_l, plaintext_l, sizeof(*plaintext_l) * NUM_VARIABLE_KEY_TESTS); + memcpy(tmptext_r, plaintext_r, sizeof(*plaintext_r) * NUM_VARIABLE_KEY_TESTS); + + for (i = 0; i < NUM_VARIABLE_KEY_TESTS; i++) { + av_blowfish_init(ctx, variable_key[i], 8); + + av_blowfish_crypt_ecb(ctx, &tmptext_l[i], &tmptext_r[i], 0); + if (tmptext_l[i] != ciphertext_l[i] || tmptext_r[i] != ciphertext_r[i]) { + printf("Test encryption failed.\n"); + return 2; + } + + av_blowfish_crypt_ecb(ctx, &tmptext_l[i], &tmptext_r[i], 1); + if (tmptext_l[i] != plaintext_l[i] || tmptext_r[i] != plaintext_r[i]) { + printf("Test decryption failed.\n"); + return 3; + } + } + printf("Test encryption/decryption success.\n"); + av_free(ctx); + + return 0; +} + diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c new file mode 100644 index 0000000..176b7eb --- /dev/null +++ b/libavutil/tests/cpu.c @@ -0,0 +1,136 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#if HAVE_UNISTD_H +#include +#elif !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +#include +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/cpu.h" + +static const struct { + int flag; + const char *name; +} cpu_flag_tab[] = { +#if ARCH_AARCH64 + { AV_CPU_FLAG_ARMV8, "armv8" }, + { AV_CPU_FLAG_NEON, "neon" }, + { AV_CPU_FLAG_VFP, "vfp" }, +#elif ARCH_ARM + { AV_CPU_FLAG_ARMV5TE, "armv5te" }, + { AV_CPU_FLAG_ARMV6, "armv6" }, + { AV_CPU_FLAG_ARMV6T2, "armv6t2" }, + { AV_CPU_FLAG_VFP, "vfp" }, + { AV_CPU_FLAG_VFP_VM, "vfp_vm" }, + { AV_CPU_FLAG_VFPV3, "vfpv3" }, + { AV_CPU_FLAG_NEON, "neon" }, +#elif ARCH_PPC + { AV_CPU_FLAG_ALTIVEC, "altivec" }, +#elif ARCH_X86 + { AV_CPU_FLAG_MMX, "mmx" }, + { AV_CPU_FLAG_MMXEXT, "mmxext" }, + { AV_CPU_FLAG_SSE, "sse" }, + { AV_CPU_FLAG_SSE2, "sse2" }, + { AV_CPU_FLAG_SSE2SLOW, "sse2(slow)" }, + { AV_CPU_FLAG_SSE3, "sse3" }, + { AV_CPU_FLAG_SSE3SLOW, "sse3(slow)" }, + { AV_CPU_FLAG_SSSE3, "ssse3" }, + { AV_CPU_FLAG_ATOM, "atom" }, + { AV_CPU_FLAG_SSE4, "sse4.1" }, + { AV_CPU_FLAG_SSE42, "sse4.2" }, + { AV_CPU_FLAG_AVX, "avx" }, + { AV_CPU_FLAG_AVXSLOW, "avxslow" }, + { AV_CPU_FLAG_XOP, "xop" }, + { AV_CPU_FLAG_FMA3, "fma3" }, + { AV_CPU_FLAG_FMA4, "fma4" }, + { AV_CPU_FLAG_3DNOW, "3dnow" }, + { AV_CPU_FLAG_3DNOWEXT, "3dnowext" }, + { AV_CPU_FLAG_CMOV, "cmov" }, + { AV_CPU_FLAG_AVX2, "avx2" }, + { AV_CPU_FLAG_BMI1, "bmi1" }, + { AV_CPU_FLAG_BMI2, "bmi2" }, +#endif + { 0 } +}; + +static void print_cpu_flags(int cpu_flags, const char *type) +{ + int i; + + fprintf(stderr, "cpu_flags(%s) = 0x%08X\n", type, cpu_flags); + fprintf(stderr, "cpu_flags_str(%s) =", type); + for (i = 0; cpu_flag_tab[i].flag; i++) + if (cpu_flags & cpu_flag_tab[i].flag) + fprintf(stderr, " %s", cpu_flag_tab[i].name); + fprintf(stderr, "\n"); +} + + +int main(int argc, char **argv) +{ + int cpu_flags_raw = av_get_cpu_flags(); + int cpu_flags_eff; + int cpu_count = av_cpu_count(); + char threads[5] = "auto"; + + if (cpu_flags_raw < 0) + return 1; + + for (;;) { + int c = getopt(argc, argv, "c:t:"); + if (c == -1) + break; + switch (c) { + case 'c': + { + int cpuflags = av_parse_cpu_flags(optarg); + if (cpuflags < 0) + return 2; + av_set_cpu_flags_mask(cpuflags); + break; + } + case 't': + { + int len = av_strlcpy(threads, optarg, sizeof(threads)); + if (len >= sizeof(threads)) { + fprintf(stderr, "Invalid thread count '%s'\n", optarg); + return 2; + } + } + } + } + + cpu_flags_eff = av_get_cpu_flags(); + + if (cpu_flags_eff < 0) + return 3; + + print_cpu_flags(cpu_flags_raw, "raw"); + print_cpu_flags(cpu_flags_eff, "effective"); + fprintf(stderr, "threads = %s (cpu_count = %d)\n", threads, cpu_count); + + return 0; +} diff --git a/libavutil/tests/crc.c b/libavutil/tests/crc.c new file mode 100644 index 0000000..c2c609f --- /dev/null +++ b/libavutil/tests/crc.c @@ -0,0 +1,45 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/crc.h" + +int main(void) +{ + uint8_t buf[1999]; + int i; + static const int p[5][3] = { + { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, + { AV_CRC_32_IEEE, 0x04C11DB7, 0xC0F5BAE0 }, + { AV_CRC_16_ANSI_LE, 0xA001, 0xBFD8 }, + { AV_CRC_16_ANSI, 0x8005, 0x1FBB }, + { AV_CRC_8_ATM, 0x07, 0xE3 } + }; + const AVCRC *ctx; + + for (i = 0; i < sizeof(buf); i++) + buf[i] = i + i * i; + + for (i = 0; i < 5; i++) { + ctx = av_crc_get_table(p[i][0]); + printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf))); + } + return 0; +} diff --git a/libavutil/tests/des.c b/libavutil/tests/des.c new file mode 100644 index 0000000..1e7a2fa --- /dev/null +++ b/libavutil/tests/des.c @@ -0,0 +1,128 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/des.c" + +#include +#include +#include +#include + +#include "libavutil/time.h" + +static uint64_t rand64(void) +{ + uint64_t r = rand(); + r = (r << 32) | rand(); + return r; +} + +static const uint8_t test_key[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; +static const DECLARE_ALIGNED(8, uint8_t, plain)[] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }; +static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = { 0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18 }; +static DECLARE_ALIGNED(8, uint8_t, tmp)[8]; +static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8]; +static const uint8_t cbc_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; + +static int run_test(int cbc, int decrypt) +{ + AVDES d; + int delay = cbc && !decrypt ? 2 : 1; + uint64_t res; + AV_WB64(large_buffer[0], 0x4e6f772069732074ULL); + AV_WB64(large_buffer[1], 0x1234567890abcdefULL); + AV_WB64(tmp, 0x1234567890abcdefULL); + av_des_init(&d, cbc_key, 192, decrypt); + av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt); + res = AV_RB64(large_buffer[9999 + delay]); + if (cbc) { + if (decrypt) + return res == 0xc5cecf63ecec514cULL; + else + return res == 0xcb191f85d1ed8439ULL; + } else { + if (decrypt) + return res == 0x8325397644091a0aULL; + else + return res == 0xdd17e8b8b437d232ULL; + } +} + +int main(void) +{ + AVDES d; + int i; + uint64_t key[3]; + uint64_t data; + uint64_t ct; + uint64_t roundkeys[16]; + srand(av_gettime()); + key[0] = AV_RB64(test_key); + data = AV_RB64(plain); + gen_roundkeys(roundkeys, key[0]); + if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) { + printf("Test 1 failed\n"); + return 1; + } + av_des_init(&d, test_key, 64, 0); + av_des_crypt(&d, tmp, plain, 1, NULL, 0); + if (memcmp(tmp, crypt, sizeof(crypt))) { + printf("Public API decryption failed\n"); + return 1; + } + if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) { + printf("Partial Monte-Carlo test failed\n"); + return 1; + } + for (i = 0; i < 1000; i++) { + key[0] = rand64(); + key[1] = rand64(); + key[2] = rand64(); + data = rand64(); + av_des_init(&d, key, 192, 0); + av_des_crypt(&d, &ct, &data, 1, NULL, 0); + av_des_init(&d, key, 192, 1); + av_des_crypt(&d, &ct, &ct, 1, NULL, 1); + if (ct != data) { + printf("Test 2 failed\n"); + return 1; + } + } +#ifdef GENTABLES + printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n"); + for (i = 0; i < 8; i++) { + int j; + printf(" {"); + for (j = 0; j < 64; j++) { + uint32_t v = S_boxes[i][j >> 1]; + v = j & 1 ? v >> 4 : v & 0xf; + v <<= 28 - 4 * i; + v = shuffle(v, P_shuffle, sizeof(P_shuffle)); + printf((j & 7) == 0 ? "\n " : " "); + printf("0x%08X,", v); + } + printf("\n },\n"); + } + printf("};\n"); +#endif + return 0; +} diff --git a/libavutil/tests/eval.c b/libavutil/tests/eval.c new file mode 100644 index 0000000..818c59c --- /dev/null +++ b/libavutil/tests/eval.c @@ -0,0 +1,145 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/libm.h" +#include "libavutil/timer.h" +#include "libavutil/eval.h" + +static const double const_values[] = { + M_PI, + M_E, + 0 +}; + +static const char *const const_names[] = { + "PI", + "E", + 0 +}; + +int main(int argc, char **argv) +{ + int i; + double d; + const char *const *expr; + static const char *const exprs[] = { + "", + "1;2", + "-20", + "-PI", + "+PI", + "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", + "80G/80Gi", + "1k", + "1Gi", + "1gi", + "1GiFoo", + "1k+1k", + "1Gi*3foo", + "foo", + "foo(", + "foo()", + "foo)", + "sin", + "sin(", + "sin()", + "sin)", + "sin 10", + "sin(1,2,3)", + "sin(1 )", + "1", + "1foo", + "bar + PI + E + 100f*2 + foo", + "13k + 12f - foo(1, 2)", + "1gi", + "1Gi", + "st(0, 123)", + "st(1, 123); ld(1)", + "lte(0, 1)", + "lte(1, 1)", + "lte(1, 0)", + "lt(0, 1)", + "lt(1, 1)", + "gt(1, 0)", + "gt(2, 7)", + "gte(122, 122)", + /* compute 1+2+...+N */ + "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)", + /* compute Fib(N) */ + "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)", + "while(0, 10)", + "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))", + "isnan(1)", + "isnan(NAN)", + "isnan(INF)", + "isinf(1)", + "isinf(NAN)", + "isinf(INF)", + "floor(NAN)", + "floor(123.123)", + "floor(-123.123)", + "trunc(123.123)", + "trunc(-123.123)", + "ceil(123.123)", + "ceil(-123.123)", + "sqrt(1764)", + "isnan(sqrt(-1))", + "not(1)", + "not(NAN)", + "not(0)", + "6.0206dB", + "-3.0103dB", + NULL + }; + + for (expr = exprs; *expr; expr++) { + printf("Evaluating '%s'\n", *expr); + av_expr_parse_and_eval(&d, *expr, + const_names, const_values, + NULL, NULL, NULL, NULL, NULL, 0, NULL); + if (isnan(d)) + printf("'%s' -> nan\n\n", *expr); + else + printf("'%s' -> %f\n\n", *expr, d); + } + + av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", + const_names, const_values, + NULL, NULL, NULL, NULL, NULL, 0, NULL); + printf("%f == 12.7\n", d); + av_expr_parse_and_eval(&d, "80G/80Gi", + const_names, const_values, + NULL, NULL, NULL, NULL, NULL, 0, NULL); + printf("%f == 0.931322575\n", d); + + if (argc > 1 && !strcmp(argv[1], "-t")) { + for (i = 0; i < 1050; i++) { + START_TIMER; + av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", + const_names, const_values, + NULL, NULL, NULL, NULL, NULL, 0, NULL); + STOP_TIMER("av_expr_parse_and_eval"); + } + } + + return 0; +} diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c new file mode 100644 index 0000000..4c4b37a --- /dev/null +++ b/libavutil/tests/fifo.c @@ -0,0 +1,51 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/fifo.h" + +int main(void) +{ + /* create a FIFO buffer */ + AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int)); + int i, j, n; + + /* fill data */ + for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) + av_fifo_generic_write(fifo, &i, sizeof(int), NULL); + + /* peek at FIFO */ + n = av_fifo_size(fifo) / sizeof(int); + for (i = -n + 1; i < n; i++) { + int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int)); + printf("%d: %d\n", i, *v); + } + printf("\n"); + + /* read data */ + for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { + av_fifo_generic_read(fifo, &j, sizeof(int), NULL); + printf("%d ", j); + } + printf("\n"); + + av_fifo_free(fifo); + + return 0; +} diff --git a/libavutil/tests/float_dsp.c b/libavutil/tests/float_dsp.c new file mode 100644 index 0000000..ab6bf6a --- /dev/null +++ b/libavutil/tests/float_dsp.c @@ -0,0 +1,296 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "libavutil/cpu.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/log.h" +#include "libavutil/random_seed.h" +#include "libavutil/float_dsp.h" + +#define LEN 240 + +static void fill_float_array(AVLFG *lfg, float *a, int len) +{ + int i; + double bmg[2], stddev = 10.0, mean = 0.0; + + for (i = 0; i < len; i += 2) { + av_bmg_get(lfg, bmg); + a[i] = bmg[0] * stddev + mean; + a[i + 1] = bmg[1] * stddev + mean; + } +} +static int compare_floats(const float *a, const float *b, int len, + float max_diff) +{ + int i; + for (i = 0; i < len; i++) { + if (fabsf(a[i] - b[i]) > max_diff) { + av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n", + i, a[i], b[i], a[i] - b[i]); + return -1; + } + } + return 0; +} + +static void fill_double_array(AVLFG *lfg, double *a, int len) +{ + int i; + double bmg[2], stddev = 10.0, mean = 0.0; + + for (i = 0; i < len; i += 2) { + av_bmg_get(lfg, bmg); + a[i] = bmg[0] * stddev + mean; + a[i + 1] = bmg[1] * stddev + mean; + } +} + +static int compare_doubles(const double *a, const double *b, int len, + double max_diff) +{ + int i; + + for (i = 0; i < len; i++) { + if (fabs(a[i] - b[i]) > max_diff) { + av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n", + i, a[i], b[i], a[i] - b[i]); + return -1; + } + } + return 0; +} + +static int test_vector_fmul(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + cdsp->vector_fmul(cdst, v1, v2, LEN); + fdsp->vector_fmul(odst, v1, v2, LEN); + + if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) + av_log(NULL, AV_LOG_ERROR, "vector_fmul failed\n"); + + return ret; +} + +#define ARBITRARY_FMAC_SCALAR_CONST 0.005 +static int test_vector_fmac_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *src0, float scale) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + memcpy(cdst, v1, LEN * sizeof(*v1)); + memcpy(odst, v1, LEN * sizeof(*v1)); + + cdsp->vector_fmac_scalar(cdst, src0, scale, LEN); + fdsp->vector_fmac_scalar(odst, src0, scale, LEN); + + if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMAC_SCALAR_CONST)) + av_log(NULL, AV_LOG_ERROR, "vector_fmac_scalar failed\n"); + + return ret; +} + +static int test_vector_fmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, float scale) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + cdsp->vector_fmul_scalar(cdst, v1, scale, LEN); + fdsp->vector_fmul_scalar(odst, v1, scale, LEN); + + if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) + av_log(NULL, AV_LOG_ERROR, "vector_fmul_scalar failed\n"); + + return ret; +} + +static int test_vector_dmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const double *v1, double scale) +{ + LOCAL_ALIGNED(32, double, cdst, [LEN]); + LOCAL_ALIGNED(32, double, odst, [LEN]); + int ret; + + cdsp->vector_dmul_scalar(cdst, v1, scale, LEN); + fdsp->vector_dmul_scalar(odst, v1, scale, LEN); + + if (ret = compare_doubles(cdst, odst, LEN, DBL_EPSILON)) + av_log(NULL, AV_LOG_ERROR, "vector_dmul_scalar failed\n"); + + return ret; +} + +#define ARBITRARY_FMUL_WINDOW_CONST 0.008 +static int test_vector_fmul_window(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2, const float *v3) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + cdsp->vector_fmul_window(cdst, v1, v2, v3, LEN / 2); + fdsp->vector_fmul_window(odst, v1, v2, v3, LEN / 2); + + if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_WINDOW_CONST)) + av_log(NULL, AV_LOG_ERROR, "vector_fmul_window failed\n"); + + return ret; +} + +#define ARBITRARY_FMUL_ADD_CONST 0.005 +static int test_vector_fmul_add(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2, const float *v3) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + cdsp->vector_fmul_add(cdst, v1, v2, v3, LEN); + fdsp->vector_fmul_add(odst, v1, v2, v3, LEN); + + if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_ADD_CONST)) + av_log(NULL, AV_LOG_ERROR, "vector_fmul_add failed\n"); + + return ret; +} + +static int test_vector_fmul_reverse(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2) +{ + LOCAL_ALIGNED(32, float, cdst, [LEN]); + LOCAL_ALIGNED(32, float, odst, [LEN]); + int ret; + + cdsp->vector_fmul_reverse(cdst, v1, v2, LEN); + fdsp->vector_fmul_reverse(odst, v1, v2, LEN); + + if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON)) + av_log(NULL, AV_LOG_ERROR, "vector_fmul_reverse failed\n"); + + return ret; +} + +static int test_butterflies_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2) +{ + LOCAL_ALIGNED(32, float, cv1, [LEN]); + LOCAL_ALIGNED(32, float, cv2, [LEN]); + LOCAL_ALIGNED(32, float, ov1, [LEN]); + LOCAL_ALIGNED(32, float, ov2, [LEN]); + int ret; + + memcpy(cv1, v1, LEN * sizeof(*v1)); + memcpy(cv2, v2, LEN * sizeof(*v2)); + memcpy(ov1, v1, LEN * sizeof(*v1)); + memcpy(ov2, v2, LEN * sizeof(*v2)); + + cdsp->butterflies_float(cv1, cv2, LEN); + fdsp->butterflies_float(ov1, ov2, LEN); + + if ((ret = compare_floats(cv1, ov1, LEN, FLT_EPSILON)) || + (ret = compare_floats(cv2, ov2, LEN, FLT_EPSILON))) + av_log(NULL, AV_LOG_ERROR, "butterflies_float failed\n"); + + return ret; +} + +#define ARBITRARY_SCALARPRODUCT_CONST 0.2 +static int test_scalarproduct_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp, + const float *v1, const float *v2) +{ + float cprod, oprod; + int ret; + + cprod = cdsp->scalarproduct_float(v1, v2, LEN); + oprod = fdsp->scalarproduct_float(v1, v2, LEN); + + if (ret = compare_floats(&cprod, &oprod, 1, ARBITRARY_SCALARPRODUCT_CONST)) + av_log(NULL, AV_LOG_ERROR, "scalarproduct_float failed\n"); + + return ret; +} + +int main(int argc, char **argv) +{ + int ret = 0; + uint32_t seed; + AVFloatDSPContext fdsp, cdsp; + AVLFG lfg; + + LOCAL_ALIGNED(32, float, src0, [LEN]); + LOCAL_ALIGNED(32, float, src1, [LEN]); + LOCAL_ALIGNED(32, float, src2, [LEN]); + LOCAL_ALIGNED(32, double, dbl_src0, [LEN]); + LOCAL_ALIGNED(32, double, dbl_src1, [LEN]); + + if (argc > 2 && !strcmp(argv[1], "-s")) + seed = strtoul(argv[2], NULL, 10); + else + seed = av_get_random_seed(); + + av_log(NULL, AV_LOG_INFO, "float_dsp-test: random seed %u\n", seed); + + av_lfg_init(&lfg, seed); + + fill_float_array(&lfg, src0, LEN); + fill_float_array(&lfg, src1, LEN); + fill_float_array(&lfg, src2, LEN); + + fill_double_array(&lfg, dbl_src0, LEN); + fill_double_array(&lfg, dbl_src1, LEN); + + avpriv_float_dsp_init(&fdsp, 1); + av_set_cpu_flags_mask(0); + avpriv_float_dsp_init(&cdsp, 1); + + if (test_vector_fmul(&fdsp, &cdsp, src0, src1)) + ret -= 1 << 0; + if (test_vector_fmac_scalar(&fdsp, &cdsp, src2, src0, src1[0])) + ret -= 1 << 1; + if (test_vector_fmul_scalar(&fdsp, &cdsp, src0, src1[0])) + ret -= 1 << 2; + if (test_vector_fmul_window(&fdsp, &cdsp, src0, src1, src2)) + ret -= 1 << 3; + if (test_vector_fmul_add(&fdsp, &cdsp, src0, src1, src2)) + ret -= 1 << 4; + if (test_vector_fmul_reverse(&fdsp, &cdsp, src0, src1)) + ret -= 1 << 5; + if (test_butterflies_float(&fdsp, &cdsp, src0, src1)) + ret -= 1 << 6; + if (test_scalarproduct_float(&fdsp, &cdsp, src0, src1)) + ret -= 1 << 7; + if (test_vector_dmul_scalar(&fdsp, &cdsp, dbl_src0, dbl_src1[0])) + ret -= 1 << 8; + + return ret; +} diff --git a/libavutil/tests/hmac.c b/libavutil/tests/hmac.c new file mode 100644 index 0000000..600240f --- /dev/null +++ b/libavutil/tests/hmac.c @@ -0,0 +1,92 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/hmac.c" + +#include +#include + +static void test(AVHMAC *hmac, const uint8_t *key, int keylen, + const uint8_t *data, int datalen) +{ + uint8_t buf[MAX_HASHLEN]; + int out, i; + // Some of the test vectors are strings, where sizeof() includes the + // trailing null byte - remove that. + if (!key[keylen - 1]) + keylen--; + if (!data[datalen - 1]) + datalen--; + out = av_hmac_calc(hmac, data, datalen, key, keylen, buf, sizeof(buf)); + for (i = 0; i < out; i++) + printf("%02x", buf[i]); + printf("\n"); +} + +int main(void) +{ + uint8_t key1[20], key3[131], data3[50]; + enum AVHMACType i = AV_HMAC_SHA224; + static const uint8_t key2[] = "Jefe"; + static const uint8_t data1[] = "Hi There"; + static const uint8_t data2[] = "what do ya want for nothing?"; + static const uint8_t data4[] = "Test Using Larger Than Block-Size Key - Hash Key First"; + static const uint8_t data5[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"; + static const uint8_t data6[] = "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being used" + " by the HMAC algorithm."; + AVHMAC *hmac = av_hmac_alloc(AV_HMAC_MD5); + if (!hmac) + return 1; + memset(key1, 0x0b, sizeof(key1)); + memset(key3, 0xaa, sizeof(key3)); + memset(data3, 0xdd, sizeof(data3)); + // RFC 2202 test vectors + test(hmac, key1, 16, data1, sizeof(data1)); + test(hmac, key2, sizeof(key2), data2, sizeof(data2)); + test(hmac, key3, 16, data3, sizeof(data3)); + test(hmac, key3, 80, data4, sizeof(data4)); + test(hmac, key3, 80, data5, sizeof(data5)); + av_hmac_free(hmac); + + /* SHA-1 */ + hmac = av_hmac_alloc(AV_HMAC_SHA1); + if (!hmac) + return 1; + // RFC 2202 test vectors + test(hmac, key1, sizeof(key1), data1, sizeof(data1)); + test(hmac, key2, sizeof(key2), data2, sizeof(data2)); + test(hmac, key3, 20, data3, sizeof(data3)); + test(hmac, key3, 80, data4, sizeof(data4)); + test(hmac, key3, 80, data5, sizeof(data5)); + av_hmac_free(hmac); + + /* SHA-2 */ + while (i <= AV_HMAC_SHA256) { + hmac = av_hmac_alloc(i); + // RFC 4231 test vectors + test(hmac, key1, sizeof(key1), data1, sizeof(data1)); + test(hmac, key2, sizeof(key2), data2, sizeof(data2)); + test(hmac, key3, 20, data3, sizeof(data3)); + test(hmac, key3, sizeof(key3), data4, sizeof(data4)); + test(hmac, key3, sizeof(key3), data6, sizeof(data6)); + av_hmac_free(hmac); + i++; + } + return 0; +} diff --git a/libavutil/tests/lfg.c b/libavutil/tests/lfg.c new file mode 100644 index 0000000..9a0c47c --- /dev/null +++ b/libavutil/tests/lfg.c @@ -0,0 +1,56 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/log.h" +#include "libavutil/timer.h" +#include "libavutil/lfg.h" + +int main(void) +{ + int x = 0; + int i, j; + AVLFG state; + + av_lfg_init(&state, 0xdeadbeef); + for (j = 0; j < 10000; j++) { + START_TIMER + for (i = 0; i < 624; i++) + x += av_lfg_get(&state); + STOP_TIMER("624 calls of av_lfg_get"); + } + av_log(NULL, AV_LOG_ERROR, "final value:%X\n", x); + + /* BMG usage example */ + { + double mean = 1000; + double stddev = 53; + + av_lfg_init(&state, 42); + + for (i = 0; i < 1000; i += 2) { + double bmg_out[2]; + av_bmg_get(&state, bmg_out); + av_log(NULL, AV_LOG_INFO, + "%f\n%f\n", + bmg_out[0] * stddev + mean, + bmg_out[1] * stddev + mean); + } + } + + return 0; +} diff --git a/libavutil/tests/lls.c b/libavutil/tests/lls.c new file mode 100644 index 0000000..7866b38 --- /dev/null +++ b/libavutil/tests/lls.c @@ -0,0 +1,54 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/lls.h" + +int main(void) +{ + LLSModel m; + int i, order; + AVLFG lfg; + + av_lfg_init(&lfg, 1); + avpriv_init_lls(&m, 3); + + for (i = 0; i < 100; i++) { + LOCAL_ALIGNED(32, double, var, [4]); + double eval; + + var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2; + var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + m.update_lls(&m, var); + avpriv_solve_lls(&m, 0.001, 0); + for (order = 0; order < 3; order++) { + eval = m.evaluate_lls(&m, var + 1, order); + printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\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; +} diff --git a/libavutil/tests/md5.c b/libavutil/tests/md5.c new file mode 100644 index 0000000..9fb7006 --- /dev/null +++ b/libavutil/tests/md5.c @@ -0,0 +1,54 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/md5.h" + +static void print_md5(uint8_t *md5) +{ + int i; + for (i = 0; i < 16; i++) + printf("%02x", md5[i]); + printf("\n"); +} + +int main(void) +{ + uint8_t md5val[16]; + int i; + uint8_t in[1000]; + + for (i = 0; i < 1000; i++) + in[i] = i * i; + av_md5_sum(md5val, in, 1000); + print_md5(md5val); + av_md5_sum(md5val, in, 63); + print_md5(md5val); + av_md5_sum(md5val, in, 64); + print_md5(md5val); + av_md5_sum(md5val, in, 65); + print_md5(md5val); + for (i = 0; i < 1000; i++) + in[i] = i % 127; + av_md5_sum(md5val, in, 999); + print_md5(md5val); + + return 0; +} diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c new file mode 100644 index 0000000..350ce3d --- /dev/null +++ b/libavutil/tests/opt.c @@ -0,0 +1,110 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/rational.h" +#include "libavutil/opt.h" + +typedef struct TestContext { + const AVClass *class; + int num; + int toggle; + char *string; + int flags; + AVRational rational; +} TestContext; + +#define OFFSET(x) offsetof(TestContext, x) + +#define TEST_FLAG_COOL 01 +#define TEST_FLAG_LAME 02 +#define TEST_FLAG_MU 04 + +static const AVOption test_options[] = { + { "num", "set num", OFFSET(num), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100 }, + { "toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 }, + { "rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, 10 }, + { "string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, { 0 }, CHAR_MIN, CHAR_MAX }, + { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, 0, "flags"}, + { "cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, { .i64 = TEST_FLAG_COOL }, INT_MIN, INT_MAX, 0, "flags"}, + { "lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, { .i64 = TEST_FLAG_LAME }, INT_MIN, INT_MAX, 0, "flags"}, + { "mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, { .i64 = TEST_FLAG_MU }, INT_MIN, INT_MAX, 0, "flags"}, + { NULL }, +}; + +static const char *test_get_name(void *ctx) +{ + return "test"; +} + +static const AVClass test_class = { + "TestContext", + test_get_name, + test_options +}; + +int main(void) +{ + int i; + TestContext test_ctx = { .class = &test_class }; + static const char *options[] = { + "", + ":", + "=", + "foo=:", + ":=foo", + "=foo", + "foo=", + "foo", + "foo=val", + "foo==val", + "toggle=:", + "string=:", + "toggle=1 : foo", + "toggle=100", + "toggle==1", + "flags=+mu-lame : num=42: toggle=0", + "num=42 : string=blahblah", + "rational=0 : rational=1/2 : rational=1/-1", + "rational=-1/0", + }; + + printf("\nTesting av_set_options_string()\n"); + + av_opt_set_defaults(&test_ctx); + test_ctx.string = av_strdup("default"); + if (!test_ctx.string) + return AVERROR(ENOMEM); + + av_log_set_level(AV_LOG_DEBUG); + + for (i = 0; i < FF_ARRAY_ELEMS(options); i++) { + av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); + if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0) + av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); + printf("\n"); + } + + return 0; +} diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c new file mode 100644 index 0000000..805c01f --- /dev/null +++ b/libavutil/tests/parseutils.c @@ -0,0 +1,116 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/log.h" +#include "libavutil/rational.h" +#include "libavutil/parseutils.h" + +int main(void) +{ + int i; + uint8_t rgba[4]; + static const char *const rates[] = { + "-inf", + "inf", + "nan", + "123/0", + "-123 / 0", + "", + "/", + " 123 / 321", + "foo/foo", + "foo/1", + "1/foo", + "0/0", + "/0", + "1/", + "1", + "0", + "-123/123", + "-foo", + "123.23", + ".23", + "-.23", + "-0.234", + "-0.0000001", + " 21332.2324 ", + " -21332.2324 ", + }; + static const char *const color_names[] = { + "foo", + "red", + "Red ", + "RED", + "Violet", + "Yellow", + "Red", + "0x000000", + "0x0000000", + "0xff000000", + "0x3e34ff", + "0x3e34ffaa", + "0xffXXee", + "0xfoobar", + "0xffffeeeeeeee", + "#ff0000", + "#ffXX00", + "ff0000", + "ffXX00", + "red@foo", + "random@10", + "0xff0000@1.0", + "red@", + "red@0xfff", + "red@0xf", + "red@2", + "red@0.1", + "red@-1", + "red@0.5", + "red@1.0", + "red@256", + "red@10foo", + "red@-1.0", + "red@-0.0", + }; + + printf("Testing av_parse_video_rate()\n"); + + for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) { + int ret; + AVRational q = { 0, 0 }; + ret = av_parse_video_rate(&q, rates[i]); + printf("'%s' -> %d/%d %s\n", + rates[i], q.num, q.den, ret ? "ERROR" : "OK"); + } + + printf("\nTesting av_parse_color()\n"); + + av_log_set_level(AV_LOG_DEBUG); + + for (i = 0; i < FF_ARRAY_ELEMS(color_names); i++) { + if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0) + printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", + color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]); + } + + return 0; +} diff --git a/libavutil/tests/sha.c b/libavutil/tests/sha.c new file mode 100644 index 0000000..0f1d514 --- /dev/null +++ b/libavutil/tests/sha.c @@ -0,0 +1,69 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/sha.c" + +#include + +int main(void) +{ + int i, j, k; + AVSHA ctx; + unsigned char digest[32]; + static const int lengths[3] = { 160, 224, 256 }; + + for (j = 0; j < 3; j++) { + printf("Testing SHA-%d\n", lengths[j]); + for (k = 0; k < 3; k++) { + av_sha_init(&ctx, lengths[j]); + if (k == 0) + av_sha_update(&ctx, "abc", 3); + else if (k == 1) + av_sha_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); + else + for (i = 0; i < 1000*1000; i++) + av_sha_update(&ctx, "a", 1); + av_sha_final(&ctx, digest); + for (i = 0; i < lengths[j] >> 3; i++) + printf("%02X", digest[i]); + putchar('\n'); + } + switch (j) { + case 0: + //test vectors (from FIPS PUB 180-1) + printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n" + "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n" + "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n"); + break; + case 1: + //test vectors (from FIPS PUB 180-2 Appendix A) + printf("23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7\n" + "75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525\n" + "20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67\n"); + break; + case 2: + //test vectors (from FIPS PUB 180-2) + printf("ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad\n" + "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1\n" + "cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0\n"); + break; + } + } + + return 0; +} diff --git a/libavutil/tests/tree.c b/libavutil/tests/tree.c new file mode 100644 index 0000000..fb19b27 --- /dev/null +++ b/libavutil/tests/tree.c @@ -0,0 +1,110 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/tree.c" + +#include + +#include "libavutil/common.h" +#include "libavutil/lfg.h" +#include "libavutil/log.h" + +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 %p\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"); +} + +static int cmp(void *a, const void *b) +{ + return (uint8_t *) a - (const uint8_t *) b; +} + +int main(void) +{ + int i; + AVTreeNode *root = NULL, *node = NULL; + AVLFG prng; + + av_lfg_init(&prng, 1); + + for (i = 0; i < 10000; i++) { + AVTreeNode *node2 = NULL; + intptr_t j = av_lfg_get(&prng) % 86294; + void *ret, *jj = (void *)(j + 1); + + while (ret = av_tree_find(root, jj, cmp, NULL)) { + j = av_lfg_get(&prng) % 86294; + jj = (void *)(j + 1); + } + + if (check(root) > 999) { + av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i); + print(root, 0); + return 1; + } + + if (!node) + node = av_tree_node_alloc(); + if (!node) { + av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n"); + return 1; + } + av_tree_insert(&root, jj, cmp, &node); + + while (ret = av_tree_find(root, jj, cmp, NULL)) { + j = av_lfg_get(&prng) % 86294; + jj = (void *)(j + 1); + } + + ret = av_tree_insert(&root, jj, cmp, &node2); + if (ret != jj) + av_tree_destroy(node2); + ret = av_tree_find(root, jj, cmp, NULL); + if (ret) + av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i); + } + + av_tree_destroy(root); + + return 0; +} diff --git a/libavutil/tests/xtea.c b/libavutil/tests/xtea.c new file mode 100644 index 0000000..8fd76dd --- /dev/null +++ b/libavutil/tests/xtea.c @@ -0,0 +1,124 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "libavutil/xtea.h" + +#define XTEA_NUM_TESTS 6 + +static const uint8_t xtea_test_key[XTEA_NUM_TESTS][16] = { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const uint8_t xtea_test_pt[XTEA_NUM_TESTS][8] = { + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const uint8_t xtea_test_ct[XTEA_NUM_TESTS][8] = { + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +static void test_xtea(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + const uint8_t *ref, int len, uint8_t *iv, int dir, + const char *test, + void (*crypt)(AVXTEA *, uint8_t *, const uint8_t *, int, uint8_t *, int)) +{ + crypt(ctx, dst, src, len, iv, dir); + if (memcmp(dst, ref, 8*len)) { + int i; + printf("%s failed\ngot ", test); + for (i = 0; i < 8*len; i++) + printf("%02x ", dst[i]); + printf("\nexpected "); + for (i = 0; i < 8*len; i++) + printf("%02x ", ref[i]); + printf("\n"); + exit(1); + } +} + +int main(void) +{ + uint8_t buf[16], iv[8]; + int i, j; + static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld"; + uint8_t ct[32]; + uint8_t pl[32]; + AVXTEA *ctx = av_xtea_alloc(); + if (!ctx) + return 1; + + for (i = 0; i < XTEA_NUM_TESTS; i++) { + av_xtea_init(ctx, xtea_test_key[i]); + + test_xtea(ctx, buf, xtea_test_pt[i], xtea_test_ct[i], 1, NULL, 0, "encryption", av_xtea_crypt); + test_xtea(ctx, buf, xtea_test_ct[i], xtea_test_pt[i], 1, NULL, 1, "decryption", av_xtea_crypt); + + for (j = 0; j < 4; j++) + AV_WL32(&buf[4*j], AV_RB32(&xtea_test_key[i][4*j])); + av_xtea_le_init(ctx, buf); + for (j = 0; j < 2; j++) { + AV_WL32(&ct[4*j], AV_RB32(&xtea_test_ct[i][4*j])); + AV_WL32(&pl[4*j], AV_RB32(&xtea_test_pt[i][4*j])); + } + test_xtea(ctx, buf, pl, ct, 1, NULL, 0, "encryption", av_xtea_le_crypt); + test_xtea(ctx, buf, ct, pl, 1, NULL, 1, "decryption", av_xtea_le_crypt); + + /* encrypt */ + memcpy(iv, "HALLO123", 8); + av_xtea_crypt(ctx, ct, src, 4, iv, 0); + + /* decrypt into pl */ + memcpy(iv, "HALLO123", 8); + test_xtea(ctx, pl, ct, src, 4, iv, 1, "CBC decryption", av_xtea_crypt); + + memcpy(iv, "HALLO123", 8); + test_xtea(ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption", av_xtea_crypt); + } + printf("Test encryption/decryption success.\n"); + av_free(ctx); + + return 0; +} diff --git a/libavutil/thread.h b/libavutil/thread.h index 07e3d4a..cf0fbdd 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -29,7 +29,7 @@ #if HAVE_PTHREADS #include #else -#include +#include "compat/w32pthreads.h" #endif #define AVMutex pthread_mutex_t @@ -39,6 +39,11 @@ #define ff_mutex_unlock pthread_mutex_unlock #define ff_mutex_destroy pthread_mutex_destroy +#define AVOnce pthread_once_t +#define AV_ONCE_INIT PTHREAD_ONCE_INIT + +#define ff_thread_once(control, routine) pthread_once(control, routine) + #else #define AVMutex char @@ -48,6 +53,18 @@ #define ff_mutex_unlock(mutex) (0) #define ff_mutex_destroy(mutex) (0) +#define AVOnce char +#define AV_ONCE_INIT 0 + +static inline int ff_thread_once(char *control, void (*routine)(void)) +{ + if (!*control) { + routine(); + *control = 1; + } + return 0; +} + #endif #endif /* AVUTIL_THREAD_H */ diff --git a/libavutil/time.c b/libavutil/time.c index 62cd445..7a3604e 100644 --- a/libavutil/time.c +++ b/libavutil/time.c @@ -21,6 +21,9 @@ #include #include #include +#if HAVE_CLOCK_GETTIME +#include +#endif #if HAVE_GETTIMEOFDAY #include #endif @@ -51,6 +54,17 @@ int64_t av_gettime(void) #endif } +int64_t av_gettime_relative(void) +{ +#if HAVE_CLOCK_GETTIME + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +#else + return av_gettime() + 42 * 60 * 60 * INT64_C(1000000); +#endif +} + int av_usleep(unsigned usec) { #if HAVE_NANOSLEEP diff --git a/libavutil/time.h b/libavutil/time.h index b01a97d..463bcfc 100644 --- a/libavutil/time.h +++ b/libavutil/time.h @@ -27,6 +27,15 @@ int64_t av_gettime(void); /** + * Get the current time in microseconds since some unspecified starting point. + * On platforms that support it, the time comes from a monotonic clock + * This property makes this time source ideal for measuring relative time. + * The returned values may not be monotonic on platforms where a monotonic + * clock is not available. + */ +int64_t av_gettime_relative(void); + +/** * Sleep for a period of time. Although the duration is expressed in * microseconds, the actual delay may be rounded to the precision of the * system timer. diff --git a/libavutil/time_internal.h b/libavutil/time_internal.h new file mode 100644 index 0000000..829fefb --- /dev/null +++ b/libavutil/time_internal.h @@ -0,0 +1,47 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_TIME_INTERNAL_H +#define AVUTIL_TIME_INTERNAL_H + +#include +#include "config.h" + +#if !HAVE_GMTIME_R +static inline struct tm *gmtime_r(const time_t* clock, struct tm *result) +{ + struct tm *ptr = gmtime(clock); + if (!ptr) + return NULL; + *result = *ptr; + return result; +} +#endif + +#if !HAVE_LOCALTIME_R +static inline struct tm *localtime_r(const time_t* clock, struct tm *result) +{ + struct tm *ptr = localtime(clock); + if (!ptr) + return NULL; + *result = *ptr; + return result; +} +#endif + +#endif /* AVUTIL_TIME_INTERNAL_H */ diff --git a/libavutil/timer.h b/libavutil/timer.h index 0d93d7c..cc4c5a5 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -38,7 +38,9 @@ #include "log.h" -#if ARCH_ARM +#if ARCH_AARCH64 +# include "aarch64/timer.h" +#elif ARCH_ARM # include "arm/timer.h" #elif ARCH_BFIN # include "bfin/timer.h" diff --git a/libavutil/tree.c b/libavutil/tree.c index d48d01a..a65d728 100644 --- a/libavutil/tree.c +++ b/libavutil/tree.c @@ -19,7 +19,6 @@ */ #include "error.h" -#include "log.h" #include "mem.h" #include "tree.h" @@ -29,10 +28,6 @@ typedef struct AVTreeNode { int state; } AVTreeNode; -#if FF_API_CONTEXT_SIZE -const int av_tree_node_size = sizeof(AVTreeNode); -#endif - struct AVTreeNode *av_tree_node_alloc(void) { return av_mallocz(sizeof(struct AVTreeNode)); @@ -168,94 +163,3 @@ void av_tree_enumerate(AVTreeNode *t, void *opaque, av_tree_enumerate(t->child[1], opaque, cmp, enu); } } - -#ifdef TEST - -#include "common.h" -#include "lfg.h" - -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 %p\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"); -} - -static int cmp(void *a, const void *b) -{ - return (uint8_t *) a - (const uint8_t *) b; -} - -int main(void) -{ - int i; - AVTreeNode *root = NULL, *node = NULL; - AVLFG prng; - - av_lfg_init(&prng, 1); - - for (i = 0; i < 10000; i++) { - AVTreeNode *node2 = NULL; - intptr_t j = av_lfg_get(&prng) % 86294; - void *ret, *jj = (void *)(j + 1); - - while (ret = av_tree_find(root, jj, cmp, NULL)) { - j = av_lfg_get(&prng) % 86294; - jj = (void *)(j + 1); - } - - if (check(root) > 999) { - av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i); - print(root, 0); - return 1; - } - - if (!node) - node = av_tree_node_alloc(); - if (!node) { - av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n"); - return 1; - } - av_tree_insert(&root, jj, cmp, &node); - - while (ret = av_tree_find(root, jj, cmp, NULL)) { - j = av_lfg_get(&prng) % 86294; - jj = (void *)(j + 1); - } - - ret = av_tree_insert(&root, jj, cmp, &node2); - if (ret != jj) - av_tree_destroy(node2); - ret = av_tree_find(root, jj, cmp, NULL); - if (ret) - av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i); - } - - av_tree_destroy(root); - - return 0; -} -#endif diff --git a/libavutil/tree.h b/libavutil/tree.h index 424656e..e2f191c 100644 --- a/libavutil/tree.h +++ b/libavutil/tree.h @@ -43,9 +43,6 @@ struct AVTreeNode; -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_tree_node_size; -#endif /** * Allocate an AVTreeNode. diff --git a/libavutil/utils.c b/libavutil/utils.c index c8c161d..8dcf3b6 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -19,11 +19,18 @@ #include "config.h" #include "avutil.h" +#include "avversion.h" + /** * @file * various utility functions */ +const char *av_version_info(void) +{ + return LIBAV_VERSION; +} + unsigned avutil_version(void) { return LIBAVUTIL_VERSION_INT; diff --git a/libavutil/version.h b/libavutil/version.h index c22d0c5..5cbc0e8 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -53,8 +53,8 @@ * @{ */ -#define LIBAVUTIL_VERSION_MAJOR 54 -#define LIBAVUTIL_VERSION_MINOR 3 +#define LIBAVUTIL_VERSION_MAJOR 55 +#define LIBAVUTIL_VERSION_MINOR 20 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -78,38 +78,32 @@ * @{ */ -#ifndef FF_API_PIX_FMT -#define FF_API_PIX_FMT (LIBAVUTIL_VERSION_MAJOR < 55) -#endif -#ifndef FF_API_CONTEXT_SIZE -#define FF_API_CONTEXT_SIZE (LIBAVUTIL_VERSION_MAJOR < 55) -#endif -#ifndef FF_API_PIX_FMT_DESC -#define FF_API_PIX_FMT_DESC (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_VDPAU +#define FF_API_VDPAU (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_AV_REVERSE -#define FF_API_AV_REVERSE (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_XVMC +#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_AUDIOCONVERT -#define FF_API_AUDIOCONVERT (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_OPT_TYPE_METADATA +#define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_CPU_FLAG_MMX2 -#define FF_API_CPU_FLAG_MMX2 (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_DLOG +#define FF_API_DLOG (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_LLS_PRIVATE -#define FF_API_LLS_PRIVATE (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_CRYPTO_CONTEXT +#define FF_API_CRYPTO_CONTEXT (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_AVFRAME_LAVC -#define FF_API_AVFRAME_LAVC (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_PLUS1_MINUS1 +#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_VDPAU -#define FF_API_VDPAU (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_ERROR_FRAME +#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_XVMC -#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_VAAPI +#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_OPT_TYPE_METADATA -#define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 55) +#ifndef FF_API_PKT_PTS +#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 56) #endif diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h new file mode 100644 index 0000000..2781773 --- /dev/null +++ b/libavutil/wchar_filename.h @@ -0,0 +1,44 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_WCHAR_FILENAME_H +#define AVUTIL_WCHAR_FILENAME_H + +#if defined(_WIN32) && !defined(__MINGW32CE__) +#include +#include "mem.h" + +static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w) +{ + int num_chars; + num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); + if (num_chars <= 0) { + *filename_w = NULL; + return 0; + } + *filename_w = av_mallocz(sizeof(wchar_t) * num_chars); + if (!*filename_w) { + errno = ENOMEM; + return -1; + } + MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars); + return 0; +} +#endif + +#endif /* AVUTIL_WCHAR_FILENAME_H */ diff --git a/libavutil/x86/asm.h b/libavutil/x86/asm.h index e30f5db..f005a3a 100644 --- a/libavutil/x86/asm.h +++ b/libavutil/x86/asm.h @@ -25,47 +25,48 @@ #include "config.h" typedef struct xmm_reg { uint64_t a, b; } xmm_reg; +typedef struct ymm_reg { uint64_t a, b, c, d; } ymm_reg; #if ARCH_X86_64 -# define OPSIZE "q" -# 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 FF_OPSIZE "q" +# define FF_REG_a "rax" +# define FF_REG_b "rbx" +# define FF_REG_c "rcx" +# define FF_REG_d "rdx" +# define FF_REG_D "rdi" +# define FF_REG_S "rsi" +# define FF_PTR_SIZE "8" typedef int64_t x86_reg; -# define REG_SP "rsp" -# define REG_BP "rbp" -# define REGBP rbp -# define REGa rax -# define REGb rbx -# define REGc rcx -# define REGd rdx -# define REGSP rsp +# define FF_REG_SP "rsp" +# define FF_REG_BP "rbp" +# define FF_REGBP rbp +# define FF_REGa rax +# define FF_REGb rbx +# define FF_REGc rcx +# define FF_REGd rdx +# define FF_REGSP rsp #elif ARCH_X86_32 -# define OPSIZE "l" -# 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 FF_OPSIZE "l" +# define FF_REG_a "eax" +# define FF_REG_b "ebx" +# define FF_REG_c "ecx" +# define FF_REG_d "edx" +# define FF_REG_D "edi" +# define FF_REG_S "esi" +# define FF_PTR_SIZE "4" typedef int32_t x86_reg; -# define REG_SP "esp" -# define REG_BP "ebp" -# define REGBP ebp -# define REGa eax -# define REGb ebx -# define REGc ecx -# define REGd edx -# define REGSP esp +# define FF_REG_SP "esp" +# define FF_REG_BP "ebp" +# define FF_REGBP ebp +# define FF_REGa eax +# define FF_REGb ebx +# define FF_REGc ecx +# define FF_REGd edx +# define FF_REGSP esp #else typedef int x86_reg; #endif diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 8be6d94..3b085e7 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -41,9 +41,9 @@ /* 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 \ + "mov %%"FF_REG_b", %%"FF_REG_S" \n\t" \ + "cpuid \n\t" \ + "xchg %%"FF_REG_b", %%"FF_REG_S \ : "=a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx) \ : "0" (index)) @@ -167,6 +167,7 @@ int ff_get_cpu_flags_x86(void) if (ext_caps & (1 << 22)) rval |= AV_CPU_FLAG_MMXEXT; + if (!strncmp(vendor.c, "AuthenticAMD", 12)) { /* Allow for selectively disabling SSE2 functions on AMD processors with SSE2 support but not SSE4a. This includes Athlon64, some Opteron, and some Sempron processors. MMX, SSE, or 3DNow! are faster @@ -174,9 +175,19 @@ int ff_get_cpu_flags_x86(void) AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case so that SSE2 is used unless explicitly disabled by checking AV_CPU_FLAG_SSE2SLOW. */ - if (!strncmp(vendor.c, "AuthenticAMD", 12) && - rval & AV_CPU_FLAG_SSE2 && !(ecx & 0x00000040)) { - rval |= AV_CPU_FLAG_SSE2SLOW; + if (rval & AV_CPU_FLAG_SSE2 && !(ecx & 0x00000040)) + rval |= AV_CPU_FLAG_SSE2SLOW; + + /* Similar to the above but for AVX functions on AMD processors. + This is necessary only for functions using YMM registers on Bulldozer + based CPUs as they lack 256-bit execution units. SSE/AVX functions + using XMM registers are always faster on them. + AV_CPU_FLAG_AVX and AV_CPU_FLAG_AVXSLOW are both set so that AVX is + used unless explicitly disabled by checking AV_CPU_FLAG_AVXSLOW. + TODO: Confirm if Excavator is affected or not by this once it's + released, and update the check if necessary. Same for btver2. */ + if (family == 0x15 && (rval & AV_CPU_FLAG_AVX)) + rval |= AV_CPU_FLAG_AVXSLOW; } /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be @@ -210,6 +221,12 @@ int ff_get_cpu_flags_x86(void) * functions on the Atom. */ if (family == 6 && model == 28) rval |= AV_CPU_FLAG_ATOM; + + /* Conroe has a slow shuffle unit. Check the model number to ensure not + * to include crippled low-end Penryns and Nehalems that lack SSE4. */ + if ((rval & AV_CPU_FLAG_SSSE3) && !(rval & AV_CPU_FLAG_SSE4) && + family == 6 && model < 23) + rval |= AV_CPU_FLAG_SSSE3SLOW; } #endif /* cpuid */ diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index 50da30e..c0a525d 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -32,11 +32,19 @@ #define X86_MMXEXT(flags) CPUEXT(flags, MMXEXT) #define X86_SSE(flags) CPUEXT(flags, SSE) #define X86_SSE2(flags) CPUEXT(flags, SSE2) +#define X86_SSE2_FAST(flags) CPUEXT_FAST(flags, SSE2) +#define X86_SSE2_SLOW(flags) CPUEXT_SLOW(flags, SSE2) #define X86_SSE3(flags) CPUEXT(flags, SSE3) +#define X86_SSE3_FAST(flags) CPUEXT_FAST(flags, SSE3) +#define X86_SSE3_SLOW(flags) CPUEXT_SLOW(flags, SSE3) #define X86_SSSE3(flags) CPUEXT(flags, SSSE3) +#define X86_SSSE3_FAST(flags) CPUEXT_FAST(flags, SSSE3) +#define X86_SSSE3_SLOW(flags) CPUEXT_SLOW(flags, SSSE3) #define X86_SSE4(flags) CPUEXT(flags, SSE4) #define X86_SSE42(flags) CPUEXT(flags, SSE42) #define X86_AVX(flags) CPUEXT(flags, AVX) +#define X86_AVX_FAST(flags) CPUEXT_FAST(flags, AVX) +#define X86_AVX_SLOW(flags) CPUEXT_SLOW(flags, AVX) #define X86_XOP(flags) CPUEXT(flags, XOP) #define X86_FMA3(flags) CPUEXT(flags, FMA3) #define X86_FMA4(flags) CPUEXT(flags, FMA4) @@ -48,11 +56,19 @@ #define EXTERNAL_MMXEXT(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, MMXEXT) #define EXTERNAL_SSE(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE) #define EXTERNAL_SSE2(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE2) +#define EXTERNAL_SSE2_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSE2) +#define EXTERNAL_SSE2_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSE2) #define EXTERNAL_SSE3(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE3) +#define EXTERNAL_SSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSE3) +#define EXTERNAL_SSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSE3) #define EXTERNAL_SSSE3(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSSE3) +#define EXTERNAL_SSSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSSE3) +#define EXTERNAL_SSSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSSE3) #define EXTERNAL_SSE4(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE4) #define EXTERNAL_SSE42(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, SSE42) #define EXTERNAL_AVX(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AVX) +#define EXTERNAL_AVX_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, AVX) +#define EXTERNAL_AVX_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, AVX) #define EXTERNAL_XOP(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, XOP) #define EXTERNAL_FMA3(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, FMA3) #define EXTERNAL_FMA4(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, FMA4) @@ -64,11 +80,19 @@ #define INLINE_MMXEXT(flags) CPUEXT_SUFFIX(flags, _INLINE, MMXEXT) #define INLINE_SSE(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE) #define INLINE_SSE2(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE2) +#define INLINE_SSE2_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, SSE2) +#define INLINE_SSE2_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSE2) #define INLINE_SSE3(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE3) +#define INLINE_SSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, SSE3) +#define INLINE_SSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSE3) #define INLINE_SSSE3(flags) CPUEXT_SUFFIX(flags, _INLINE, SSSE3) +#define INLINE_SSSE3_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, SSSE3) +#define INLINE_SSSE3_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSSE3) #define INLINE_SSE4(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE4) #define INLINE_SSE42(flags) CPUEXT_SUFFIX(flags, _INLINE, SSE42) #define INLINE_AVX(flags) CPUEXT_SUFFIX(flags, _INLINE, AVX) +#define INLINE_AVX_FAST(flags) CPUEXT_SUFFIX_FAST(flags, _INLINE, AVX) +#define INLINE_AVX_SLOW(flags) CPUEXT_SUFFIX_SLOW(flags, _INLINE, AVX) #define INLINE_XOP(flags) CPUEXT_SUFFIX(flags, _INLINE, XOP) #define INLINE_FMA3(flags) CPUEXT_SUFFIX(flags, _INLINE, FMA3) #define INLINE_FMA4(flags) CPUEXT_SUFFIX(flags, _INLINE, FMA4) diff --git a/libavutil/x86/float_dsp_init.c b/libavutil/x86/float_dsp_init.c index a04d91c..b704330 100644 --- a/libavutil/x86/float_dsp_init.c +++ b/libavutil/x86/float_dsp_init.c @@ -146,7 +146,7 @@ av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) if (EXTERNAL_SSE2(cpu_flags)) { fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_sse2; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_avx; fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_avx; fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_avx; diff --git a/libavutil/x86/lls_init.c b/libavutil/x86/lls_init.c index 888bc54..80cda29 100644 --- a/libavutil/x86/lls_init.c +++ b/libavutil/x86/lls_init.c @@ -35,7 +35,7 @@ av_cold void ff_init_lls_x86(LLSModel *m) if (m->indep_count >= 4) m->evaluate_lls = ff_evaluate_lls_sse2; } - if (EXTERNAL_AVX(cpu_flags)) { + if (EXTERNAL_AVX_FAST(cpu_flags)) { m->update_lls = ff_update_lls_avx; } } diff --git a/libavutil/x86/timer.h b/libavutil/x86/timer.h index cdd67dd..bb7c341 100644 --- a/libavutil/x86/timer.h +++ b/libavutil/x86/timer.h @@ -30,7 +30,12 @@ static inline uint64_t read_time(void) { uint32_t a, d; - __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); + __asm__ volatile( +#if ARCH_X86_64 || defined(__SSE2__) + "lfence \n\t" +#endif + "rdtsc \n\t" + : "=a" (a), "=d" (d)); return ((uint64_t)d << 32) + a; } diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 2d4d1d3..dca1f78 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -1,7 +1,7 @@ ;***************************************************************************** ;* x86inc.asm: x264asm abstraction layer ;***************************************************************************** -;* Copyright (C) 2005-2013 x264 project +;* Copyright (C) 2005-2016 x264 project ;* ;* Authors: Loren Merritt ;* Anton Mitrofanov @@ -42,6 +42,17 @@ %define public_prefix private_prefix %endif +%if HAVE_ALIGNED_STACK + %define STACK_ALIGNMENT 16 +%endif +%ifndef STACK_ALIGNMENT + %if ARCH_X86_64 + %define STACK_ALIGNMENT 16 + %else + %define STACK_ALIGNMENT 4 + %endif +%endif + %define WIN64 0 %define UNIX64 0 %if ARCH_X86_64 @@ -56,6 +67,15 @@ %endif %endif +%define FORMAT_ELF 0 +%ifidn __OUTPUT_FORMAT__,elf + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf32 + %define FORMAT_ELF 1 +%elifidn __OUTPUT_FORMAT__,elf64 + %define FORMAT_ELF 1 +%endif + %ifdef PREFIX %define mangle(x) _ %+ x %else @@ -73,14 +93,6 @@ %endif %endmacro -%macro SECTION_TEXT 0-1 16 - %ifidn __OUTPUT_FORMAT__,aout - SECTION .text - %else - SECTION .text align=%1 - %endif -%endmacro - %if WIN64 %define PIC %elif ARCH_X86_64 == 0 @@ -99,9 +111,6 @@ %endif %endmacro -; Always use long nops (reduces 0x90 spam in disassembly on x86_32) -CPUNOP amdnop - ; Macros to eliminate most code duplication between x86_32 and x86_64: ; Currently this works only for leaf functions which load all their arguments ; into registers at the start, and make no other use of the stack. Luckily that @@ -111,8 +120,9 @@ CPUNOP amdnop ; %1 = number of arguments. loads them from stack if needed. ; %2 = number of registers used. pushes callee-saved regs if needed. ; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed. -; %4 = (optional) stack size to be allocated. If not aligned (x86-32 ICC 10.x, -; MSVC or YMM), the stack will be manually aligned (to 16 or 32 bytes), +; %4 = (optional) stack size to be allocated. The stack will be aligned before +; allocating the specified stack size. If the required stack alignment is +; larger than the known stack alignment the stack will be manually aligned ; and an extra register will be allocated to hold the original stack ; pointer (to not invalidate r0m etc.). To prevent the use of an extra ; register as stack pointer, request a negative stack size. @@ -120,8 +130,10 @@ CPUNOP amdnop ; PROLOGUE can also be invoked by adding the same options to cglobal ; e.g. -; cglobal foo, 2,3,0, dst, src, tmp -; declares a function (foo), taking two args (dst and src) and one local variable (tmp) +; cglobal foo, 2,3,7,0x40, dst, src, tmp +; declares a function (foo) that automatically loads two arguments (dst and +; src) into registers, uses one additional register (tmp) plus 7 vector +; registers (m0-m6) and allocates 0x40 bytes of stack space. ; TODO Some functions can use some args directly from the stack. If they're the ; last args then you can just not declare them, but if they're in the middle @@ -171,9 +183,9 @@ CPUNOP amdnop %define e%1h %3 %define r%1b %2 %define e%1b %2 -%if ARCH_X86_64 == 0 - %define r%1 e%1 -%endif + %if ARCH_X86_64 == 0 + %define r%1 e%1 + %endif %endmacro DECLARE_REG_SIZE ax, al, ah @@ -283,7 +295,7 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %macro ASSERT 1 %if (%1) == 0 - %error assert failed + %error assertion ``%1'' failed %endif %endmacro @@ -322,26 +334,28 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %assign n_arg_names %0 %endmacro +%define required_stack_alignment ((mmsize + 15) & ~15) + %macro ALLOC_STACK 1-2 0 ; stack_size, n_xmm_regs (for win64 only) %ifnum %1 %if %1 != 0 - %assign %%stack_alignment ((mmsize + 15) & ~15) + %assign %%pad 0 %assign stack_size %1 %if stack_size < 0 %assign stack_size -stack_size %endif - %assign stack_size_padded stack_size %if WIN64 - %assign stack_size_padded stack_size_padded + 32 ; reserve 32 bytes for shadow space + %assign %%pad %%pad + 32 ; shadow space %if mmsize != 8 %assign xmm_regs_used %2 %if xmm_regs_used > 8 - %assign stack_size_padded stack_size_padded + (xmm_regs_used-8)*16 + %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers %endif %endif %endif - %if mmsize <= 16 && HAVE_ALIGNED_STACK - %assign stack_size_padded stack_size_padded + %%stack_alignment - gprsize - (stack_offset & (%%stack_alignment - 1)) + %if required_stack_alignment <= STACK_ALIGNMENT + ; maintain the current stack alignment + %assign stack_size_padded stack_size + %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) SUB rsp, stack_size_padded %else %assign %%reg_num (regs_used - 1) @@ -350,17 +364,17 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 ; it, i.e. in [rsp+stack_size_padded], so we can restore the ; stack in a single instruction (i.e. mov rsp, rstk or mov ; rsp, [rsp+stack_size_padded]) - mov rstk, rsp %if %1 < 0 ; need to store rsp on stack - sub rsp, gprsize+stack_size_padded - and rsp, ~(%%stack_alignment-1) - %xdefine rstkm [rsp+stack_size_padded] - mov rstkm, rstk + %xdefine rstkm [rsp + stack_size + %%pad] + %assign %%pad %%pad + gprsize %else ; can keep rsp in rstk during whole function - sub rsp, stack_size_padded - and rsp, ~(%%stack_alignment-1) %xdefine rstkm rstk %endif + %assign stack_size_padded stack_size + ((%%pad + required_stack_alignment-1) & ~(required_stack_alignment-1)) + mov rstk, rsp + and rsp, ~(required_stack_alignment-1) + sub rsp, stack_size_padded + movifnidn rstkm, rstk %endif WIN64_PUSH_XMM %endif @@ -369,11 +383,14 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %macro SETUP_STACK_POINTER 1 %ifnum %1 - %if %1 != 0 && (HAVE_ALIGNED_STACK == 0 || mmsize == 32) + %if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT %if %1 > 0 %assign regs_used (regs_used + 1) - %elif ARCH_X86_64 && regs_used == num_args && num_args <= 4 + UNIX64 * 2 - %warning "Stack pointer will overwrite register argument" + %endif + %if ARCH_X86_64 && regs_used < 5 + UNIX64 * 3 + ; Ensure that we don't clobber any registers containing arguments. For UNIX64 we also preserve r6 (rax) + ; since it's used as a hidden argument in vararg functions to specify the number of vector registers used. + %assign regs_used 5 + UNIX64 * 3 %endif %endif %endif @@ -443,7 +460,9 @@ DECLARE_REG 14, R15, 120 %assign xmm_regs_used %1 ASSERT xmm_regs_used <= 16 %if xmm_regs_used > 8 - %assign stack_size_padded (xmm_regs_used-8)*16 + (~stack_offset&8) + 32 + ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. + %assign %%pad (xmm_regs_used-8)*16 + 32 + %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) SUB rsp, stack_size_padded %endif WIN64_PUSH_XMM @@ -459,7 +478,7 @@ DECLARE_REG 14, R15, 120 %endrep %endif %if stack_size_padded > 0 - %if stack_size > 0 && (mmsize == 32 || HAVE_ALIGNED_STACK == 0) + %if stack_size > 0 && required_stack_alignment > STACK_ALIGNMENT mov rsp, rstkm %else add %1, stack_size_padded @@ -485,9 +504,9 @@ DECLARE_REG 14, R15, 120 %macro RET 0 WIN64_RESTORE_XMM_INTERNAL rsp POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7 -%if mmsize == 32 - vzeroupper -%endif + %if mmsize == 32 + vzeroupper + %endif AUTO_REP_RET %endmacro @@ -524,17 +543,17 @@ DECLARE_REG 14, R15, 72 %define has_epilogue regs_used > 9 || mmsize == 32 || stack_size > 0 %macro RET 0 -%if stack_size_padded > 0 -%if mmsize == 32 || HAVE_ALIGNED_STACK == 0 - mov rsp, rstkm -%else - add rsp, stack_size_padded -%endif -%endif + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif POP_IF_USED 14, 13, 12, 11, 10, 9 -%if mmsize == 32 - vzeroupper -%endif + %if mmsize == 32 + vzeroupper + %endif AUTO_REP_RET %endmacro @@ -580,29 +599,29 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 %define has_epilogue regs_used > 3 || mmsize == 32 || stack_size > 0 %macro RET 0 -%if stack_size_padded > 0 -%if mmsize == 32 || HAVE_ALIGNED_STACK == 0 - mov rsp, rstkm -%else - add rsp, stack_size_padded -%endif -%endif + %if stack_size_padded > 0 + %if required_stack_alignment > STACK_ALIGNMENT + mov rsp, rstkm + %else + add rsp, stack_size_padded + %endif + %endif POP_IF_USED 6, 5, 4, 3 -%if mmsize == 32 - vzeroupper -%endif + %if mmsize == 32 + vzeroupper + %endif AUTO_REP_RET %endmacro %endif ;====================================================================== %if WIN64 == 0 -%macro WIN64_SPILL_XMM 1 -%endmacro -%macro WIN64_RESTORE_XMM 1 -%endmacro -%macro WIN64_PUSH_XMM 0 -%endmacro + %macro WIN64_SPILL_XMM 1 + %endmacro + %macro WIN64_RESTORE_XMM 1 + %endmacro + %macro WIN64_PUSH_XMM 0 + %endmacro %endif ; On AMD cpus <=K10, an ordinary ret is slow if it immediately follows either @@ -615,24 +634,26 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 %else rep ret %endif + annotate_function_size %endmacro %define last_branch_adr $$ %macro AUTO_REP_RET 0 - %ifndef cpuflags - times ((last_branch_adr-$)>>31)+1 rep ; times 1 iff $ != last_branch_adr. - %elif notcpuflag(ssse3) - times ((last_branch_adr-$)>>31)+1 rep + %if notcpuflag(ssse3) + times ((last_branch_adr-$)>>31)+1 rep ; times 1 iff $ == last_branch_adr. %endif ret + annotate_function_size %endmacro %macro BRANCH_INSTR 0-* %rep %0 %macro %1 1-2 %1 %2 %1 - %%branch_instr: - %xdefine last_branch_adr %%branch_instr + %if notcpuflag(ssse3) + %%branch_instr equ $ + %xdefine last_branch_adr %%branch_instr + %endif %endmacro %rotate 1 %endrep @@ -647,6 +668,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %elif %2 jmp %1 %endif + annotate_function_size %endmacro ;============================================================================= @@ -668,6 +690,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, cglobal_internal 0, %1 %+ SUFFIX, %2 %endmacro %macro cglobal_internal 2-3+ + annotate_function_size %if %1 %xdefine %%FUNCTION_PREFIX private_prefix %xdefine %%VISIBILITY hidden @@ -681,7 +704,8 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, CAT_XDEFINE cglobaled_, %2, 1 %endif %xdefine current_function %2 - %ifidn __OUTPUT_FORMAT__,elf + %xdefine current_function_section __SECT__ + %if FORMAT_ELF global %2:function %%VISIBILITY %else global %2 @@ -707,14 +731,16 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, ; like cextern, but without the prefix %macro cextern_naked 1 - %xdefine %1 mangle(%1) + %ifdef PREFIX + %xdefine %1 mangle(%1) + %endif CAT_XDEFINE cglobaled_, %1, 1 extern %1 %endmacro %macro const 1-2+ %xdefine %1 mangle(private_prefix %+ _ %+ %1) - %ifidn __OUTPUT_FORMAT__,elf + %if FORMAT_ELF global %1:data hidden %else global %1 @@ -722,12 +748,29 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %1: %2 %endmacro -; This is needed for ELF, otherwise the GNU linker assumes the stack is -; executable by default. -%ifidn __OUTPUT_FORMAT__,elf -SECTION .note.GNU-stack noalloc noexec nowrite progbits +; This is needed for ELF, otherwise the GNU linker assumes the stack is executable by default. +%if FORMAT_ELF + [SECTION .note.GNU-stack noalloc noexec nowrite progbits] %endif +; Tell debuggers how large the function was. +; This may be invoked multiple times per function; we rely on later instances overriding earlier ones. +; This is invoked by RET and similar macros, and also cglobal does it for the previous function, +; but if the last function in a source file doesn't use any of the standard macros for its epilogue, +; then its size might be unspecified. +%macro annotate_function_size 0 + %ifdef __YASM_VER__ + %ifdef current_function + %if FORMAT_ELF + current_function_section + %%ecf equ $ + size current_function %%ecf - current_function + __SECT__ + %endif + %endif + %endif +%endmacro + ; cpuflags %assign cpuflags_mmx (1<<0) @@ -744,8 +787,8 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %assign cpuflags_avx (1<<11)| cpuflags_sse42 %assign cpuflags_xop (1<<12)| cpuflags_avx %assign cpuflags_fma4 (1<<13)| cpuflags_avx -%assign cpuflags_avx2 (1<<14)| cpuflags_avx -%assign cpuflags_fma3 (1<<15)| cpuflags_avx +%assign cpuflags_fma3 (1<<14)| cpuflags_avx +%assign cpuflags_avx2 (1<<15)| cpuflags_fma3 %assign cpuflags_cache32 (1<<16) %assign cpuflags_cache64 (1<<17) @@ -756,22 +799,30 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %assign cpuflags_bmi1 (1<<22)|cpuflags_lzcnt %assign cpuflags_bmi2 (1<<23)|cpuflags_bmi1 -%define cpuflag(x) ((cpuflags & (cpuflags_ %+ x)) == (cpuflags_ %+ x)) -%define notcpuflag(x) ((cpuflags & (cpuflags_ %+ x)) != (cpuflags_ %+ x)) +; Returns a boolean value expressing whether or not the specified cpuflag is enabled. +%define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) +%define notcpuflag(x) (cpuflag(x) ^ 1) -; Takes up to 2 cpuflags from the above list. +; Takes an arbitrary number of cpuflags from the above list. ; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu. ; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co. -%macro INIT_CPUFLAGS 0-2 - CPUNOP amdnop +%macro INIT_CPUFLAGS 0-* + %xdefine SUFFIX + %undef cpuname + %assign cpuflags 0 + %if %0 >= 1 - %xdefine cpuname %1 - %assign cpuflags cpuflags_%1 - %if %0 >= 2 - %xdefine cpuname %1_%2 - %assign cpuflags cpuflags | cpuflags_%2 - %endif + %rep %0 + %ifdef cpuname + %xdefine cpuname cpuname %+ _%1 + %else + %xdefine cpuname %1 + %endif + %assign cpuflags cpuflags | cpuflags_%1 + %rotate 1 + %endrep %xdefine SUFFIX _ %+ cpuname + %if cpuflag(avx) %assign avx_enabled 1 %endif @@ -782,23 +833,22 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %endif %if cpuflag(aligned) %define movu mova - %elifidn %1, sse3 + %elif cpuflag(sse3) && notcpuflag(ssse3) %define movu lddqu %endif - %if notcpuflag(sse2) - CPUNOP basicnop - %endif + %endif + + %if ARCH_X86_64 || cpuflag(sse2) + CPUNOP amdnop %else - %xdefine SUFFIX - %undef cpuname - %undef cpuflags + CPUNOP basicnop %endif %endmacro ; Merge mmx and sse* -; m# is a simd regsiter of the currently selected size -; xm# is the corresponding xmmreg (if selcted xmm or ymm size), or mmreg (if selected mmx) -; ym# is the corresponding ymmreg (if selcted xmm or ymm size), or mmreg (if selected mmx) +; m# is a simd register of the currently selected size +; xm# is the corresponding xmm register if mmsize >= 16, otherwise the same as m# +; ym# is the corresponding ymm register if mmsize >= 32, otherwise the same as m# ; (All 3 remain in sync through SWAP.) %macro CAT_XDEFINE 3 @@ -820,14 +870,14 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define movnta movntq %assign %%i 0 %rep 8 - CAT_XDEFINE m, %%i, mm %+ %%i - CAT_XDEFINE nmm, %%i, %%i - %assign %%i %%i+1 + CAT_XDEFINE m, %%i, mm %+ %%i + CAT_XDEFINE nnmm, %%i, %%i + %assign %%i %%i+1 %endrep %rep 8 - CAT_UNDEF m, %%i - CAT_UNDEF nmm, %%i - %assign %%i %%i+1 + CAT_UNDEF m, %%i + CAT_UNDEF nnmm, %%i + %assign %%i %%i+1 %endrep INIT_CPUFLAGS %1 %endmacro @@ -838,7 +888,7 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define mmsize 16 %define num_mmregs 8 %if ARCH_X86_64 - %define num_mmregs 16 + %define num_mmregs 16 %endif %define mova movdqa %define movu movdqu @@ -846,9 +896,9 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define movnta movntdq %assign %%i 0 %rep num_mmregs - CAT_XDEFINE m, %%i, xmm %+ %%i - CAT_XDEFINE nxmm, %%i, %%i - %assign %%i %%i+1 + CAT_XDEFINE m, %%i, xmm %+ %%i + CAT_XDEFINE nnxmm, %%i, %%i + %assign %%i %%i+1 %endrep INIT_CPUFLAGS %1 %endmacro @@ -859,7 +909,7 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define mmsize 32 %define num_mmregs 8 %if ARCH_X86_64 - %define num_mmregs 16 + %define num_mmregs 16 %endif %define mova movdqa %define movu movdqu @@ -867,9 +917,9 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define movnta movntdq %assign %%i 0 %rep num_mmregs - CAT_XDEFINE m, %%i, ymm %+ %%i - CAT_XDEFINE nymm, %%i, %%i - %assign %%i %%i+1 + CAT_XDEFINE m, %%i, ymm %+ %%i + CAT_XDEFINE nnymm, %%i, %%i + %assign %%i %%i+1 %endrep INIT_CPUFLAGS %1 %endmacro @@ -884,7 +934,7 @@ INIT_XMM %define xmmxmm%1 xmm%1 %define xmmymm%1 xmm%1 %define ymmmm%1 mm%1 - %define ymmxmm%1 ymm%1 + %define ymmxmm%1 xmm%1 %define ymmymm%1 ymm%1 %define xm%1 xmm %+ m%1 %define ym%1 ymm %+ m%1 @@ -893,7 +943,7 @@ INIT_XMM %assign i 0 %rep 16 DECLARE_MMCAST i -%assign i i+1 + %assign i i+1 %endrep ; I often want to use macros that permute their arguments. e.g. there's no @@ -911,23 +961,23 @@ INIT_XMM ; doesn't cost any cycles. %macro PERMUTE 2-* ; takes a list of pairs to swap -%rep %0/2 - %xdefine %%tmp%2 m%2 - %rotate 2 -%endrep -%rep %0/2 - %xdefine m%1 %%tmp%2 - CAT_XDEFINE n, m%1, %1 - %rotate 2 -%endrep + %rep %0/2 + %xdefine %%tmp%2 m%2 + %rotate 2 + %endrep + %rep %0/2 + %xdefine m%1 %%tmp%2 + CAT_XDEFINE nn, m%1, %1 + %rotate 2 + %endrep %endmacro %macro SWAP 2+ ; swaps a single chain (sometimes more concise than pairs) -%ifnum %1 ; SWAP 0, 1, ... - SWAP_INTERNAL_NUM %1, %2 -%else ; SWAP m0, m1, ... - SWAP_INTERNAL_NAME %1, %2 -%endif + %ifnum %1 ; SWAP 0, 1, ... + SWAP_INTERNAL_NUM %1, %2 + %else ; SWAP m0, m1, ... + SWAP_INTERNAL_NAME %1, %2 + %endif %endmacro %macro SWAP_INTERNAL_NUM 2-* @@ -935,17 +985,17 @@ INIT_XMM %xdefine %%tmp m%1 %xdefine m%1 m%2 %xdefine m%2 %%tmp - CAT_XDEFINE n, m%1, %1 - CAT_XDEFINE n, m%2, %2 - %rotate 1 + CAT_XDEFINE nn, m%1, %1 + CAT_XDEFINE nn, m%2, %2 + %rotate 1 %endrep %endmacro %macro SWAP_INTERNAL_NAME 2-* - %xdefine %%args n %+ %1 + %xdefine %%args nn %+ %1 %rep %0-1 - %xdefine %%args %%args, n %+ %2 - %rotate 1 + %xdefine %%args %%args, nn %+ %2 + %rotate 1 %endrep SWAP_INTERNAL_NUM %%args %endmacro @@ -962,7 +1012,7 @@ INIT_XMM %assign %%i 0 %rep num_mmregs CAT_XDEFINE %%f, %%i, m %+ %%i - %assign %%i %%i+1 + %assign %%i %%i+1 %endrep %endmacro @@ -971,8 +1021,8 @@ INIT_XMM %assign %%i 0 %rep num_mmregs CAT_XDEFINE m, %%i, %1_m %+ %%i - CAT_XDEFINE n, m %+ %%i, %%i - %assign %%i %%i+1 + CAT_XDEFINE nn, m %+ %%i, %%i + %assign %%i %%i+1 %endrep %endif %endmacro @@ -1028,7 +1078,7 @@ INIT_XMM %endif CAT_XDEFINE sizeofxmm, i, 16 CAT_XDEFINE sizeofymm, i, 32 -%assign i i+1 + %assign i i+1 %endrep %undef i @@ -1044,15 +1094,16 @@ INIT_XMM %endmacro ;%1 == instruction -;%2 == 1 if float, 0 if int -;%3 == 1 if non-destructive or 4-operand (xmm, xmm, xmm, imm), 0 otherwise -;%4 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not -;%5+: operands -%macro RUN_AVX_INSTR 5-8+ - %ifnum sizeof%6 +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +;%6+: operands +%macro RUN_AVX_INSTR 6-9+ + %ifnum sizeof%7 + %assign __sizeofreg sizeof%7 + %elifnum sizeof%6 %assign __sizeofreg sizeof%6 - %elifnum sizeof%5 - %assign __sizeofreg sizeof%5 %else %assign __sizeofreg mmsize %endif @@ -1061,325 +1112,344 @@ INIT_XMM %xdefine __instr v%1 %else %xdefine __instr %1 - %if %0 >= 7+%3 + %if %0 >= 8+%4 %assign __emulate_avx 1 %endif %endif + %ifnidn %2, fnord + %ifdef cpuname + %if notcpuflag(%2) + %error use of ``%1'' %2 instruction in cpuname function: current_function + %elif cpuflags_%2 < cpuflags_sse && notcpuflag(sse2) && __sizeofreg > 8 + %error use of ``%1'' sse2 instruction in cpuname function: current_function + %endif + %endif + %endif %if __emulate_avx - %xdefine __src1 %6 - %xdefine __src2 %7 - %ifnidn %5, %6 - %if %0 >= 8 - CHECK_AVX_INSTR_EMU {%1 %5, %6, %7, %8}, %5, %7, %8 - %else - CHECK_AVX_INSTR_EMU {%1 %5, %6, %7}, %5, %7 - %endif - %if %4 && %3 == 0 - %ifnid %7 + %xdefine __src1 %7 + %xdefine __src2 %8 + %if %5 && %4 == 0 + %ifnidn %6, %7 + %ifidn %6, %8 + %xdefine __src1 %8 + %xdefine __src2 %7 + %elifnnum sizeof%8 ; 3-operand AVX instructions with a memory arg can only have it in src2, ; whereas SSE emulation prefers to have it in src1 (i.e. the mov). ; So, if the instruction is commutative with a memory arg, swap them. - %xdefine __src1 %7 - %xdefine __src2 %6 + %xdefine __src1 %8 + %xdefine __src2 %7 %endif %endif + %endif + %ifnidn %6, __src1 + %if %0 >= 9 + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, __src2, %9 + %else + CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, __src2 + %endif %if __sizeofreg == 8 - MOVQ %5, __src1 - %elif %2 - MOVAPS %5, __src1 + MOVQ %6, __src1 + %elif %3 + MOVAPS %6, __src1 %else - MOVDQA %5, __src1 + MOVDQA %6, __src1 %endif %endif - %if %0 >= 8 - %1 %5, __src2, %8 + %if %0 >= 9 + %1 %6, __src2, %9 %else - %1 %5, __src2 + %1 %6, __src2 %endif - %elif %0 >= 8 - __instr %5, %6, %7, %8 + %elif %0 >= 9 + __instr %6, %7, %8, %9 + %elif %0 == 8 + __instr %6, %7, %8 %elif %0 == 7 - __instr %5, %6, %7 - %elif %0 == 6 - __instr %5, %6 + __instr %6, %7 %else - __instr %5 + __instr %6 %endif %endmacro ;%1 == instruction -;%2 == 1 if float, 0 if int -;%3 == 1 if non-destructive or 4-operand (xmm, xmm, xmm, imm), 0 otherwise -;%4 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not -%macro AVX_INSTR 1-4 0, 1, 0 - %macro %1 1-9 fnord, fnord, fnord, fnord, %1, %2, %3, %4 +;%2 == minimal instruction set +;%3 == 1 if float, 0 if int +;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation) +;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not +%macro AVX_INSTR 1-5 fnord, 0, 255, 0 + %macro %1 1-10 fnord, fnord, fnord, fnord, %1, %2, %3, %4, %5 %ifidn %2, fnord - RUN_AVX_INSTR %6, %7, %8, %9, %1 + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1 %elifidn %3, fnord - RUN_AVX_INSTR %6, %7, %8, %9, %1, %2 + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2 %elifidn %4, fnord - RUN_AVX_INSTR %6, %7, %8, %9, %1, %2, %3 + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3 %elifidn %5, fnord - RUN_AVX_INSTR %6, %7, %8, %9, %1, %2, %3, %4 + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4 %else - RUN_AVX_INSTR %6, %7, %8, %9, %1, %2, %3, %4, %5 + RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4, %5 %endif %endmacro %endmacro ; Instructions with both VEX and non-VEX encodings ; Non-destructive instructions are written without parameters -AVX_INSTR addpd, 1, 0, 1 -AVX_INSTR addps, 1, 0, 1 -AVX_INSTR addsd, 1, 0, 1 -AVX_INSTR addss, 1, 0, 1 -AVX_INSTR addsubpd, 1, 0, 0 -AVX_INSTR addsubps, 1, 0, 0 -AVX_INSTR aesdec, 0, 0, 0 -AVX_INSTR aesdeclast, 0, 0, 0 -AVX_INSTR aesenc, 0, 0, 0 -AVX_INSTR aesenclast, 0, 0, 0 +AVX_INSTR addpd, sse2, 1, 0, 1 +AVX_INSTR addps, sse, 1, 0, 1 +AVX_INSTR addsd, sse2, 1, 0, 0 +AVX_INSTR addss, sse, 1, 0, 0 +AVX_INSTR addsubpd, sse3, 1, 0, 0 +AVX_INSTR addsubps, sse3, 1, 0, 0 +AVX_INSTR aesdec, fnord, 0, 0, 0 +AVX_INSTR aesdeclast, fnord, 0, 0, 0 +AVX_INSTR aesenc, fnord, 0, 0, 0 +AVX_INSTR aesenclast, fnord, 0, 0, 0 AVX_INSTR aesimc AVX_INSTR aeskeygenassist -AVX_INSTR andnpd, 1, 0, 0 -AVX_INSTR andnps, 1, 0, 0 -AVX_INSTR andpd, 1, 0, 1 -AVX_INSTR andps, 1, 0, 1 -AVX_INSTR blendpd, 1, 0, 0 -AVX_INSTR blendps, 1, 0, 0 -AVX_INSTR blendvpd, 1, 0, 0 -AVX_INSTR blendvps, 1, 0, 0 -AVX_INSTR cmppd, 1, 1, 0 -AVX_INSTR cmpps, 1, 1, 0 -AVX_INSTR cmpsd, 1, 1, 0 -AVX_INSTR cmpss, 1, 1, 0 -AVX_INSTR comisd -AVX_INSTR comiss -AVX_INSTR cvtdq2pd -AVX_INSTR cvtdq2ps -AVX_INSTR cvtpd2dq -AVX_INSTR cvtpd2ps -AVX_INSTR cvtps2dq -AVX_INSTR cvtps2pd -AVX_INSTR cvtsd2si -AVX_INSTR cvtsd2ss -AVX_INSTR cvtsi2sd -AVX_INSTR cvtsi2ss -AVX_INSTR cvtss2sd -AVX_INSTR cvtss2si -AVX_INSTR cvttpd2dq -AVX_INSTR cvttps2dq -AVX_INSTR cvttsd2si -AVX_INSTR cvttss2si -AVX_INSTR divpd, 1, 0, 0 -AVX_INSTR divps, 1, 0, 0 -AVX_INSTR divsd, 1, 0, 0 -AVX_INSTR divss, 1, 0, 0 -AVX_INSTR dppd, 1, 1, 0 -AVX_INSTR dpps, 1, 1, 0 -AVX_INSTR extractps -AVX_INSTR haddpd, 1, 0, 0 -AVX_INSTR haddps, 1, 0, 0 -AVX_INSTR hsubpd, 1, 0, 0 -AVX_INSTR hsubps, 1, 0, 0 -AVX_INSTR insertps, 1, 1, 0 -AVX_INSTR lddqu -AVX_INSTR ldmxcsr -AVX_INSTR maskmovdqu -AVX_INSTR maxpd, 1, 0, 1 -AVX_INSTR maxps, 1, 0, 1 -AVX_INSTR maxsd, 1, 0, 1 -AVX_INSTR maxss, 1, 0, 1 -AVX_INSTR minpd, 1, 0, 1 -AVX_INSTR minps, 1, 0, 1 -AVX_INSTR minsd, 1, 0, 1 -AVX_INSTR minss, 1, 0, 1 -AVX_INSTR movapd -AVX_INSTR movaps -AVX_INSTR movd -AVX_INSTR movddup -AVX_INSTR movdqa -AVX_INSTR movdqu -AVX_INSTR movhlps, 1, 0, 0 -AVX_INSTR movhpd, 1, 0, 0 -AVX_INSTR movhps, 1, 0, 0 -AVX_INSTR movlhps, 1, 0, 0 -AVX_INSTR movlpd, 1, 0, 0 -AVX_INSTR movlps, 1, 0, 0 -AVX_INSTR movmskpd -AVX_INSTR movmskps -AVX_INSTR movntdq -AVX_INSTR movntdqa -AVX_INSTR movntpd -AVX_INSTR movntps -AVX_INSTR movq -AVX_INSTR movsd, 1, 0, 0 -AVX_INSTR movshdup -AVX_INSTR movsldup -AVX_INSTR movss, 1, 0, 0 -AVX_INSTR movupd -AVX_INSTR movups -AVX_INSTR mpsadbw, 0, 1, 0 -AVX_INSTR mulpd, 1, 0, 1 -AVX_INSTR mulps, 1, 0, 1 -AVX_INSTR mulsd, 1, 0, 1 -AVX_INSTR mulss, 1, 0, 1 -AVX_INSTR orpd, 1, 0, 1 -AVX_INSTR orps, 1, 0, 1 -AVX_INSTR pabsb -AVX_INSTR pabsd -AVX_INSTR pabsw -AVX_INSTR packsswb, 0, 0, 0 -AVX_INSTR packssdw, 0, 0, 0 -AVX_INSTR packuswb, 0, 0, 0 -AVX_INSTR packusdw, 0, 0, 0 -AVX_INSTR paddb, 0, 0, 1 -AVX_INSTR paddw, 0, 0, 1 -AVX_INSTR paddd, 0, 0, 1 -AVX_INSTR paddq, 0, 0, 1 -AVX_INSTR paddsb, 0, 0, 1 -AVX_INSTR paddsw, 0, 0, 1 -AVX_INSTR paddusb, 0, 0, 1 -AVX_INSTR paddusw, 0, 0, 1 -AVX_INSTR palignr, 0, 1, 0 -AVX_INSTR pand, 0, 0, 1 -AVX_INSTR pandn, 0, 0, 0 -AVX_INSTR pavgb, 0, 0, 1 -AVX_INSTR pavgw, 0, 0, 1 -AVX_INSTR pblendvb, 0, 0, 0 -AVX_INSTR pblendw, 0, 1, 0 -AVX_INSTR pclmulqdq, 0, 1, 0 -AVX_INSTR pcmpestri -AVX_INSTR pcmpestrm -AVX_INSTR pcmpistri -AVX_INSTR pcmpistrm -AVX_INSTR pcmpeqb, 0, 0, 1 -AVX_INSTR pcmpeqw, 0, 0, 1 -AVX_INSTR pcmpeqd, 0, 0, 1 -AVX_INSTR pcmpeqq, 0, 0, 1 -AVX_INSTR pcmpgtb, 0, 0, 0 -AVX_INSTR pcmpgtw, 0, 0, 0 -AVX_INSTR pcmpgtd, 0, 0, 0 -AVX_INSTR pcmpgtq, 0, 0, 0 -AVX_INSTR pextrb -AVX_INSTR pextrd -AVX_INSTR pextrq -AVX_INSTR pextrw -AVX_INSTR phaddw, 0, 0, 0 -AVX_INSTR phaddd, 0, 0, 0 -AVX_INSTR phaddsw, 0, 0, 0 -AVX_INSTR phminposuw -AVX_INSTR phsubw, 0, 0, 0 -AVX_INSTR phsubd, 0, 0, 0 -AVX_INSTR phsubsw, 0, 0, 0 -AVX_INSTR pinsrb, 0, 1, 0 -AVX_INSTR pinsrd, 0, 1, 0 -AVX_INSTR pinsrq, 0, 1, 0 -AVX_INSTR pinsrw, 0, 1, 0 -AVX_INSTR pmaddwd, 0, 0, 1 -AVX_INSTR pmaddubsw, 0, 0, 0 -AVX_INSTR pmaxsb, 0, 0, 1 -AVX_INSTR pmaxsw, 0, 0, 1 -AVX_INSTR pmaxsd, 0, 0, 1 -AVX_INSTR pmaxub, 0, 0, 1 -AVX_INSTR pmaxuw, 0, 0, 1 -AVX_INSTR pmaxud, 0, 0, 1 -AVX_INSTR pminsb, 0, 0, 1 -AVX_INSTR pminsw, 0, 0, 1 -AVX_INSTR pminsd, 0, 0, 1 -AVX_INSTR pminub, 0, 0, 1 -AVX_INSTR pminuw, 0, 0, 1 -AVX_INSTR pminud, 0, 0, 1 -AVX_INSTR pmovmskb -AVX_INSTR pmovsxbw -AVX_INSTR pmovsxbd -AVX_INSTR pmovsxbq -AVX_INSTR pmovsxwd -AVX_INSTR pmovsxwq -AVX_INSTR pmovsxdq -AVX_INSTR pmovzxbw -AVX_INSTR pmovzxbd -AVX_INSTR pmovzxbq -AVX_INSTR pmovzxwd -AVX_INSTR pmovzxwq -AVX_INSTR pmovzxdq -AVX_INSTR pmuldq, 0, 0, 1 -AVX_INSTR pmulhrsw, 0, 0, 1 -AVX_INSTR pmulhuw, 0, 0, 1 -AVX_INSTR pmulhw, 0, 0, 1 -AVX_INSTR pmullw, 0, 0, 1 -AVX_INSTR pmulld, 0, 0, 1 -AVX_INSTR pmuludq, 0, 0, 1 -AVX_INSTR por, 0, 0, 1 -AVX_INSTR psadbw, 0, 0, 1 -AVX_INSTR pshufb, 0, 0, 0 -AVX_INSTR pshufd -AVX_INSTR pshufhw -AVX_INSTR pshuflw -AVX_INSTR psignb, 0, 0, 0 -AVX_INSTR psignw, 0, 0, 0 -AVX_INSTR psignd, 0, 0, 0 -AVX_INSTR psllw, 0, 0, 0 -AVX_INSTR pslld, 0, 0, 0 -AVX_INSTR psllq, 0, 0, 0 -AVX_INSTR pslldq, 0, 0, 0 -AVX_INSTR psraw, 0, 0, 0 -AVX_INSTR psrad, 0, 0, 0 -AVX_INSTR psrlw, 0, 0, 0 -AVX_INSTR psrld, 0, 0, 0 -AVX_INSTR psrlq, 0, 0, 0 -AVX_INSTR psrldq, 0, 0, 0 -AVX_INSTR psubb, 0, 0, 0 -AVX_INSTR psubw, 0, 0, 0 -AVX_INSTR psubd, 0, 0, 0 -AVX_INSTR psubq, 0, 0, 0 -AVX_INSTR psubsb, 0, 0, 0 -AVX_INSTR psubsw, 0, 0, 0 -AVX_INSTR psubusb, 0, 0, 0 -AVX_INSTR psubusw, 0, 0, 0 -AVX_INSTR ptest -AVX_INSTR punpckhbw, 0, 0, 0 -AVX_INSTR punpckhwd, 0, 0, 0 -AVX_INSTR punpckhdq, 0, 0, 0 -AVX_INSTR punpckhqdq, 0, 0, 0 -AVX_INSTR punpcklbw, 0, 0, 0 -AVX_INSTR punpcklwd, 0, 0, 0 -AVX_INSTR punpckldq, 0, 0, 0 -AVX_INSTR punpcklqdq, 0, 0, 0 -AVX_INSTR pxor, 0, 0, 1 -AVX_INSTR rcpps, 1, 0, 0 -AVX_INSTR rcpss, 1, 0, 0 -AVX_INSTR roundpd -AVX_INSTR roundps -AVX_INSTR roundsd -AVX_INSTR roundss -AVX_INSTR rsqrtps, 1, 0, 0 -AVX_INSTR rsqrtss, 1, 0, 0 -AVX_INSTR shufpd, 1, 1, 0 -AVX_INSTR shufps, 1, 1, 0 -AVX_INSTR sqrtpd, 1, 0, 0 -AVX_INSTR sqrtps, 1, 0, 0 -AVX_INSTR sqrtsd, 1, 0, 0 -AVX_INSTR sqrtss, 1, 0, 0 -AVX_INSTR stmxcsr -AVX_INSTR subpd, 1, 0, 0 -AVX_INSTR subps, 1, 0, 0 -AVX_INSTR subsd, 1, 0, 0 -AVX_INSTR subss, 1, 0, 0 -AVX_INSTR ucomisd -AVX_INSTR ucomiss -AVX_INSTR unpckhpd, 1, 0, 0 -AVX_INSTR unpckhps, 1, 0, 0 -AVX_INSTR unpcklpd, 1, 0, 0 -AVX_INSTR unpcklps, 1, 0, 0 -AVX_INSTR xorpd, 1, 0, 1 -AVX_INSTR xorps, 1, 0, 1 +AVX_INSTR andnpd, sse2, 1, 0, 0 +AVX_INSTR andnps, sse, 1, 0, 0 +AVX_INSTR andpd, sse2, 1, 0, 1 +AVX_INSTR andps, sse, 1, 0, 1 +AVX_INSTR blendpd, sse4, 1, 1, 0 +AVX_INSTR blendps, sse4, 1, 1, 0 +AVX_INSTR blendvpd, sse4 ; can't be emulated +AVX_INSTR blendvps, sse4 ; can't be emulated +AVX_INSTR cmppd, sse2, 1, 1, 0 +AVX_INSTR cmpps, sse, 1, 1, 0 +AVX_INSTR cmpsd, sse2, 1, 1, 0 +AVX_INSTR cmpss, sse, 1, 1, 0 +AVX_INSTR comisd, sse2 +AVX_INSTR comiss, sse +AVX_INSTR cvtdq2pd, sse2 +AVX_INSTR cvtdq2ps, sse2 +AVX_INSTR cvtpd2dq, sse2 +AVX_INSTR cvtpd2ps, sse2 +AVX_INSTR cvtps2dq, sse2 +AVX_INSTR cvtps2pd, sse2 +AVX_INSTR cvtsd2si, sse2 +AVX_INSTR cvtsd2ss, sse2, 1, 0, 0 +AVX_INSTR cvtsi2sd, sse2, 1, 0, 0 +AVX_INSTR cvtsi2ss, sse, 1, 0, 0 +AVX_INSTR cvtss2sd, sse2, 1, 0, 0 +AVX_INSTR cvtss2si, sse +AVX_INSTR cvttpd2dq, sse2 +AVX_INSTR cvttps2dq, sse2 +AVX_INSTR cvttsd2si, sse2 +AVX_INSTR cvttss2si, sse +AVX_INSTR divpd, sse2, 1, 0, 0 +AVX_INSTR divps, sse, 1, 0, 0 +AVX_INSTR divsd, sse2, 1, 0, 0 +AVX_INSTR divss, sse, 1, 0, 0 +AVX_INSTR dppd, sse4, 1, 1, 0 +AVX_INSTR dpps, sse4, 1, 1, 0 +AVX_INSTR extractps, sse4 +AVX_INSTR haddpd, sse3, 1, 0, 0 +AVX_INSTR haddps, sse3, 1, 0, 0 +AVX_INSTR hsubpd, sse3, 1, 0, 0 +AVX_INSTR hsubps, sse3, 1, 0, 0 +AVX_INSTR insertps, sse4, 1, 1, 0 +AVX_INSTR lddqu, sse3 +AVX_INSTR ldmxcsr, sse +AVX_INSTR maskmovdqu, sse2 +AVX_INSTR maxpd, sse2, 1, 0, 1 +AVX_INSTR maxps, sse, 1, 0, 1 +AVX_INSTR maxsd, sse2, 1, 0, 0 +AVX_INSTR maxss, sse, 1, 0, 0 +AVX_INSTR minpd, sse2, 1, 0, 1 +AVX_INSTR minps, sse, 1, 0, 1 +AVX_INSTR minsd, sse2, 1, 0, 0 +AVX_INSTR minss, sse, 1, 0, 0 +AVX_INSTR movapd, sse2 +AVX_INSTR movaps, sse +AVX_INSTR movd, mmx +AVX_INSTR movddup, sse3 +AVX_INSTR movdqa, sse2 +AVX_INSTR movdqu, sse2 +AVX_INSTR movhlps, sse, 1, 0, 0 +AVX_INSTR movhpd, sse2, 1, 0, 0 +AVX_INSTR movhps, sse, 1, 0, 0 +AVX_INSTR movlhps, sse, 1, 0, 0 +AVX_INSTR movlpd, sse2, 1, 0, 0 +AVX_INSTR movlps, sse, 1, 0, 0 +AVX_INSTR movmskpd, sse2 +AVX_INSTR movmskps, sse +AVX_INSTR movntdq, sse2 +AVX_INSTR movntdqa, sse4 +AVX_INSTR movntpd, sse2 +AVX_INSTR movntps, sse +AVX_INSTR movq, mmx +AVX_INSTR movsd, sse2, 1, 0, 0 +AVX_INSTR movshdup, sse3 +AVX_INSTR movsldup, sse3 +AVX_INSTR movss, sse, 1, 0, 0 +AVX_INSTR movupd, sse2 +AVX_INSTR movups, sse +AVX_INSTR mpsadbw, sse4, 0, 1, 0 +AVX_INSTR mulpd, sse2, 1, 0, 1 +AVX_INSTR mulps, sse, 1, 0, 1 +AVX_INSTR mulsd, sse2, 1, 0, 0 +AVX_INSTR mulss, sse, 1, 0, 0 +AVX_INSTR orpd, sse2, 1, 0, 1 +AVX_INSTR orps, sse, 1, 0, 1 +AVX_INSTR pabsb, ssse3 +AVX_INSTR pabsd, ssse3 +AVX_INSTR pabsw, ssse3 +AVX_INSTR packsswb, mmx, 0, 0, 0 +AVX_INSTR packssdw, mmx, 0, 0, 0 +AVX_INSTR packuswb, mmx, 0, 0, 0 +AVX_INSTR packusdw, sse4, 0, 0, 0 +AVX_INSTR paddb, mmx, 0, 0, 1 +AVX_INSTR paddw, mmx, 0, 0, 1 +AVX_INSTR paddd, mmx, 0, 0, 1 +AVX_INSTR paddq, sse2, 0, 0, 1 +AVX_INSTR paddsb, mmx, 0, 0, 1 +AVX_INSTR paddsw, mmx, 0, 0, 1 +AVX_INSTR paddusb, mmx, 0, 0, 1 +AVX_INSTR paddusw, mmx, 0, 0, 1 +AVX_INSTR palignr, ssse3, 0, 1, 0 +AVX_INSTR pand, mmx, 0, 0, 1 +AVX_INSTR pandn, mmx, 0, 0, 0 +AVX_INSTR pavgb, mmx2, 0, 0, 1 +AVX_INSTR pavgw, mmx2, 0, 0, 1 +AVX_INSTR pblendvb, sse4 ; can't be emulated +AVX_INSTR pblendw, sse4, 0, 1, 0 +AVX_INSTR pclmulqdq, fnord, 0, 1, 0 +AVX_INSTR pclmulhqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmulhqlqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqhqdq, fnord, 0, 0, 0 +AVX_INSTR pclmullqlqdq, fnord, 0, 0, 0 +AVX_INSTR pcmpestri, sse42 +AVX_INSTR pcmpestrm, sse42 +AVX_INSTR pcmpistri, sse42 +AVX_INSTR pcmpistrm, sse42 +AVX_INSTR pcmpeqb, mmx, 0, 0, 1 +AVX_INSTR pcmpeqw, mmx, 0, 0, 1 +AVX_INSTR pcmpeqd, mmx, 0, 0, 1 +AVX_INSTR pcmpeqq, sse4, 0, 0, 1 +AVX_INSTR pcmpgtb, mmx, 0, 0, 0 +AVX_INSTR pcmpgtw, mmx, 0, 0, 0 +AVX_INSTR pcmpgtd, mmx, 0, 0, 0 +AVX_INSTR pcmpgtq, sse42, 0, 0, 0 +AVX_INSTR pextrb, sse4 +AVX_INSTR pextrd, sse4 +AVX_INSTR pextrq, sse4 +AVX_INSTR pextrw, mmx2 +AVX_INSTR phaddw, ssse3, 0, 0, 0 +AVX_INSTR phaddd, ssse3, 0, 0, 0 +AVX_INSTR phaddsw, ssse3, 0, 0, 0 +AVX_INSTR phminposuw, sse4 +AVX_INSTR phsubw, ssse3, 0, 0, 0 +AVX_INSTR phsubd, ssse3, 0, 0, 0 +AVX_INSTR phsubsw, ssse3, 0, 0, 0 +AVX_INSTR pinsrb, sse4, 0, 1, 0 +AVX_INSTR pinsrd, sse4, 0, 1, 0 +AVX_INSTR pinsrq, sse4, 0, 1, 0 +AVX_INSTR pinsrw, mmx2, 0, 1, 0 +AVX_INSTR pmaddwd, mmx, 0, 0, 1 +AVX_INSTR pmaddubsw, ssse3, 0, 0, 0 +AVX_INSTR pmaxsb, sse4, 0, 0, 1 +AVX_INSTR pmaxsw, mmx2, 0, 0, 1 +AVX_INSTR pmaxsd, sse4, 0, 0, 1 +AVX_INSTR pmaxub, mmx2, 0, 0, 1 +AVX_INSTR pmaxuw, sse4, 0, 0, 1 +AVX_INSTR pmaxud, sse4, 0, 0, 1 +AVX_INSTR pminsb, sse4, 0, 0, 1 +AVX_INSTR pminsw, mmx2, 0, 0, 1 +AVX_INSTR pminsd, sse4, 0, 0, 1 +AVX_INSTR pminub, mmx2, 0, 0, 1 +AVX_INSTR pminuw, sse4, 0, 0, 1 +AVX_INSTR pminud, sse4, 0, 0, 1 +AVX_INSTR pmovmskb, mmx2 +AVX_INSTR pmovsxbw, sse4 +AVX_INSTR pmovsxbd, sse4 +AVX_INSTR pmovsxbq, sse4 +AVX_INSTR pmovsxwd, sse4 +AVX_INSTR pmovsxwq, sse4 +AVX_INSTR pmovsxdq, sse4 +AVX_INSTR pmovzxbw, sse4 +AVX_INSTR pmovzxbd, sse4 +AVX_INSTR pmovzxbq, sse4 +AVX_INSTR pmovzxwd, sse4 +AVX_INSTR pmovzxwq, sse4 +AVX_INSTR pmovzxdq, sse4 +AVX_INSTR pmuldq, sse4, 0, 0, 1 +AVX_INSTR pmulhrsw, ssse3, 0, 0, 1 +AVX_INSTR pmulhuw, mmx2, 0, 0, 1 +AVX_INSTR pmulhw, mmx, 0, 0, 1 +AVX_INSTR pmullw, mmx, 0, 0, 1 +AVX_INSTR pmulld, sse4, 0, 0, 1 +AVX_INSTR pmuludq, sse2, 0, 0, 1 +AVX_INSTR por, mmx, 0, 0, 1 +AVX_INSTR psadbw, mmx2, 0, 0, 1 +AVX_INSTR pshufb, ssse3, 0, 0, 0 +AVX_INSTR pshufd, sse2 +AVX_INSTR pshufhw, sse2 +AVX_INSTR pshuflw, sse2 +AVX_INSTR psignb, ssse3, 0, 0, 0 +AVX_INSTR psignw, ssse3, 0, 0, 0 +AVX_INSTR psignd, ssse3, 0, 0, 0 +AVX_INSTR psllw, mmx, 0, 0, 0 +AVX_INSTR pslld, mmx, 0, 0, 0 +AVX_INSTR psllq, mmx, 0, 0, 0 +AVX_INSTR pslldq, sse2, 0, 0, 0 +AVX_INSTR psraw, mmx, 0, 0, 0 +AVX_INSTR psrad, mmx, 0, 0, 0 +AVX_INSTR psrlw, mmx, 0, 0, 0 +AVX_INSTR psrld, mmx, 0, 0, 0 +AVX_INSTR psrlq, mmx, 0, 0, 0 +AVX_INSTR psrldq, sse2, 0, 0, 0 +AVX_INSTR psubb, mmx, 0, 0, 0 +AVX_INSTR psubw, mmx, 0, 0, 0 +AVX_INSTR psubd, mmx, 0, 0, 0 +AVX_INSTR psubq, sse2, 0, 0, 0 +AVX_INSTR psubsb, mmx, 0, 0, 0 +AVX_INSTR psubsw, mmx, 0, 0, 0 +AVX_INSTR psubusb, mmx, 0, 0, 0 +AVX_INSTR psubusw, mmx, 0, 0, 0 +AVX_INSTR ptest, sse4 +AVX_INSTR punpckhbw, mmx, 0, 0, 0 +AVX_INSTR punpckhwd, mmx, 0, 0, 0 +AVX_INSTR punpckhdq, mmx, 0, 0, 0 +AVX_INSTR punpckhqdq, sse2, 0, 0, 0 +AVX_INSTR punpcklbw, mmx, 0, 0, 0 +AVX_INSTR punpcklwd, mmx, 0, 0, 0 +AVX_INSTR punpckldq, mmx, 0, 0, 0 +AVX_INSTR punpcklqdq, sse2, 0, 0, 0 +AVX_INSTR pxor, mmx, 0, 0, 1 +AVX_INSTR rcpps, sse +AVX_INSTR rcpss, sse, 1, 0, 0 +AVX_INSTR roundpd, sse4 +AVX_INSTR roundps, sse4 +AVX_INSTR roundsd, sse4, 1, 1, 0 +AVX_INSTR roundss, sse4, 1, 1, 0 +AVX_INSTR rsqrtps, sse +AVX_INSTR rsqrtss, sse, 1, 0, 0 +AVX_INSTR shufpd, sse2, 1, 1, 0 +AVX_INSTR shufps, sse, 1, 1, 0 +AVX_INSTR sqrtpd, sse2 +AVX_INSTR sqrtps, sse +AVX_INSTR sqrtsd, sse2, 1, 0, 0 +AVX_INSTR sqrtss, sse, 1, 0, 0 +AVX_INSTR stmxcsr, sse +AVX_INSTR subpd, sse2, 1, 0, 0 +AVX_INSTR subps, sse, 1, 0, 0 +AVX_INSTR subsd, sse2, 1, 0, 0 +AVX_INSTR subss, sse, 1, 0, 0 +AVX_INSTR ucomisd, sse2 +AVX_INSTR ucomiss, sse +AVX_INSTR unpckhpd, sse2, 1, 0, 0 +AVX_INSTR unpckhps, sse, 1, 0, 0 +AVX_INSTR unpcklpd, sse2, 1, 0, 0 +AVX_INSTR unpcklps, sse, 1, 0, 0 +AVX_INSTR xorpd, sse2, 1, 0, 1 +AVX_INSTR xorps, sse, 1, 0, 1 ; 3DNow instructions, for sharing code between AVX, SSE and 3DN -AVX_INSTR pfadd, 1, 0, 1 -AVX_INSTR pfsub, 1, 0, 0 -AVX_INSTR pfmul, 1, 0, 1 +AVX_INSTR pfadd, 3dnow, 1, 0, 1 +AVX_INSTR pfsub, 3dnow, 1, 0, 0 +AVX_INSTR pfmul, 3dnow, 1, 0, 1 ; base-4 constants for shuffles %assign i 0 @@ -1394,7 +1464,7 @@ AVX_INSTR pfmul, 1, 0, 1 %else CAT_XDEFINE q, j, i %endif -%assign i i+1 + %assign i i+1 %endrep %undef i %undef j @@ -1403,70 +1473,72 @@ AVX_INSTR pfmul, 1, 0, 1 %macro %1 4-7 %1, %2, %3 %if cpuflag(xop) v%5 %1, %2, %3, %4 - %else + %elifnidn %1, %4 %6 %1, %2, %3 %7 %1, %4 + %else + %error non-xop emulation of ``%5 %1, %2, %3, %4'' is not supported %endif %endmacro %endmacro -FMA_INSTR pmacsdd, pmulld, paddd FMA_INSTR pmacsww, pmullw, paddw +FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation +FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation FMA_INSTR pmadcswd, pmaddwd, paddd ; tzcnt is equivalent to "rep bsf" and is backwards-compatible with bsf. ; This lets us use tzcnt without bumping the yasm version requirement yet. %define tzcnt rep bsf -; convert FMA4 to FMA3 if possible -%macro FMA4_INSTR 4 - %macro %1 4-8 %1, %2, %3, %4 - %if cpuflag(fma4) - v%5 %1, %2, %3, %4 - %elifidn %1, %2 - v%6 %1, %4, %3 ; %1 = %1 * %3 + %4 - %elifidn %1, %3 - v%7 %1, %2, %4 ; %1 = %2 * %1 + %4 - %elifidn %1, %4 - v%8 %1, %2, %3 ; %1 = %2 * %3 + %1 - %else - %error fma3 emulation of ``%5 %1, %2, %3, %4'' is not supported - %endif - %endmacro -%endmacro - -FMA4_INSTR fmaddpd, fmadd132pd, fmadd213pd, fmadd231pd -FMA4_INSTR fmaddps, fmadd132ps, fmadd213ps, fmadd231ps -FMA4_INSTR fmaddsd, fmadd132sd, fmadd213sd, fmadd231sd -FMA4_INSTR fmaddss, fmadd132ss, fmadd213ss, fmadd231ss - -FMA4_INSTR fmaddsubpd, fmaddsub132pd, fmaddsub213pd, fmaddsub231pd -FMA4_INSTR fmaddsubps, fmaddsub132ps, fmaddsub213ps, fmaddsub231ps -FMA4_INSTR fmsubaddpd, fmsubadd132pd, fmsubadd213pd, fmsubadd231pd -FMA4_INSTR fmsubaddps, fmsubadd132ps, fmsubadd213ps, fmsubadd231ps - -FMA4_INSTR fmsubpd, fmsub132pd, fmsub213pd, fmsub231pd -FMA4_INSTR fmsubps, fmsub132ps, fmsub213ps, fmsub231ps -FMA4_INSTR fmsubsd, fmsub132sd, fmsub213sd, fmsub231sd -FMA4_INSTR fmsubss, fmsub132ss, fmsub213ss, fmsub231ss - -FMA4_INSTR fnmaddpd, fnmadd132pd, fnmadd213pd, fnmadd231pd -FMA4_INSTR fnmaddps, fnmadd132ps, fnmadd213ps, fnmadd231ps -FMA4_INSTR fnmaddsd, fnmadd132sd, fnmadd213sd, fnmadd231sd -FMA4_INSTR fnmaddss, fnmadd132ss, fnmadd213ss, fnmadd231ss - -FMA4_INSTR fnmsubpd, fnmsub132pd, fnmsub213pd, fnmsub231pd -FMA4_INSTR fnmsubps, fnmsub132ps, fnmsub213ps, fnmsub231ps -FMA4_INSTR fnmsubsd, fnmsub132sd, fnmsub213sd, fnmsub231sd -FMA4_INSTR fnmsubss, fnmsub132ss, fnmsub213ss, fnmsub231ss - -; workaround: vpbroadcastq is broken in x86_32 due to a yasm bug -%if ARCH_X86_64 == 0 -%macro vpbroadcastq 2 -%if sizeof%1 == 16 - movddup %1, %2 -%else - vbroadcastsd %1, %2 -%endif -%endmacro +; Macros for consolidating FMA3 and FMA4 using 4-operand (dst, src1, src2, src3) syntax. +; FMA3 is only possible if dst is the same as one of the src registers. +; Either src2 or src3 can be a memory operand. +%macro FMA4_INSTR 2-* + %push fma4_instr + %xdefine %$prefix %1 + %rep %0 - 1 + %macro %$prefix%2 4-6 %$prefix, %2 + %if notcpuflag(fma3) && notcpuflag(fma4) + %error use of ``%5%6'' fma instruction in cpuname function: current_function + %elif cpuflag(fma4) + v%5%6 %1, %2, %3, %4 + %elifidn %1, %2 + ; If %3 or %4 is a memory operand it needs to be encoded as the last operand. + %ifnum sizeof%3 + v%{5}213%6 %2, %3, %4 + %else + v%{5}132%6 %2, %4, %3 + %endif + %elifidn %1, %3 + v%{5}213%6 %3, %2, %4 + %elifidn %1, %4 + v%{5}231%6 %4, %2, %3 + %else + %error fma3 emulation of ``%5%6 %1, %2, %3, %4'' is not supported + %endif + %endmacro + %rotate 1 + %endrep + %pop +%endmacro + +FMA4_INSTR fmadd, pd, ps, sd, ss +FMA4_INSTR fmaddsub, pd, ps +FMA4_INSTR fmsub, pd, ps, sd, ss +FMA4_INSTR fmsubadd, pd, ps +FMA4_INSTR fnmadd, pd, ps, sd, ss +FMA4_INSTR fnmsub, pd, ps, sd, ss + +; workaround: vpbroadcastq is broken in x86_32 due to a yasm bug (fixed in 1.3.0) +%ifdef __YASM_VER__ + %if __YASM_VERSION_ID__ < 0x01030000 && ARCH_X86_64 == 0 + %macro vpbroadcastq 2 + %if sizeof%1 == 16 + movddup %1, %2 + %else + vbroadcastsd %1, %2 + %endif + %endmacro + %endif %endif diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index 11779cf..16a9bae 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -552,7 +552,9 @@ %endmacro %macro SPLATW 2-3 0 -%if mmsize == 16 +%if cpuflag(avx2) && %3 == 0 + vpbroadcastw %1, %2 +%elif mmsize == 16 pshuflw %1, %2, (%3)*0x55 punpcklqdq %1, %1 %elif cpuflag(mmxext) @@ -584,6 +586,11 @@ %endif %endmacro +%macro CLIPUB 3 ;(dst, min, max) + pmaxub %1, %2 + pminub %1, %3 +%endmacro + %macro CLIPW 3 ;(dst, min, max) pmaxsw %1, %2 pminsw %1, %3 diff --git a/libavutil/xtea.c b/libavutil/xtea.c index 53c0bfe..3e22236 100644 --- a/libavutil/xtea.c +++ b/libavutil/xtea.c @@ -31,8 +31,20 @@ #include "avutil.h" #include "common.h" #include "intreadwrite.h" +#include "mem.h" #include "xtea.h" +#if !FF_API_CRYPTO_CONTEXT +struct AVXTEA { + uint32_t key[16]; +}; +#endif + +AVXTEA *av_xtea_alloc(void) +{ + return av_mallocz(sizeof(struct AVXTEA)); +} + void av_xtea_init(AVXTEA *ctx, const uint8_t key[16]) { int i; @@ -41,6 +53,14 @@ void av_xtea_init(AVXTEA *ctx, const uint8_t key[16]) ctx->key[i] = AV_RB32(key + (i << 2)); } +void av_xtea_le_init(AVXTEA *ctx, const uint8_t key[16]) +{ + int i; + + for (i = 0; i < 4; i++) + ctx->key[i] = AV_RL32(key + (i << 2)); +} + static void xtea_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int decrypt, uint8_t *iv) { @@ -77,14 +97,51 @@ static void xtea_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, AV_WB32(dst + 4, v1); } -void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, - uint8_t *iv, int decrypt) +static void xtea_le_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + int decrypt, uint8_t *iv) +{ + uint32_t v0, v1; + int i; + + v0 = AV_RL32(src); + v1 = AV_RL32(src + 4); + + if (decrypt) { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for (i = 0; i < 32; i++) { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); + } + if (iv) { + v0 ^= AV_RL32(iv); + v1 ^= AV_RL32(iv + 4); + memcpy(iv, src, 8); + } + } else { + uint32_t sum = 0, delta = 0x9E3779B9; + + for (i = 0; i < 32; i++) { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); + } + } + + AV_WL32(dst, v0); + AV_WL32(dst + 4, v1); +} + +static void xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, + uint8_t *iv, int decrypt, + void (*crypt)(AVXTEA *, uint8_t *, const uint8_t *, int, uint8_t *)) { int i; if (decrypt) { while (count--) { - xtea_crypt_ecb(ctx, dst, src, decrypt, iv); + crypt(ctx, dst, src, decrypt, iv); src += 8; dst += 8; @@ -94,10 +151,10 @@ void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, if (iv) { for (i = 0; i < 8; i++) dst[i] = src[i] ^ iv[i]; - xtea_crypt_ecb(ctx, dst, dst, decrypt, NULL); + crypt(ctx, dst, dst, decrypt, NULL); memcpy(iv, dst, 8); } else { - xtea_crypt_ecb(ctx, dst, src, decrypt, NULL); + crypt(ctx, dst, src, decrypt, NULL); } src += 8; dst += 8; @@ -105,91 +162,14 @@ void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, } } -#ifdef TEST -#include - -#define XTEA_NUM_TESTS 6 - -static const uint8_t xtea_test_key[XTEA_NUM_TESTS][16] = { - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const uint8_t xtea_test_pt[XTEA_NUM_TESTS][8] = { - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } -}; - -static const uint8_t xtea_test_ct[XTEA_NUM_TESTS][8] = { - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } -}; - -static void test_xtea(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, - const uint8_t *ref, int len, uint8_t *iv, int dir, - const char *test) +void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, + uint8_t *iv, int decrypt) { - av_xtea_crypt(ctx, dst, src, len, iv, dir); - if (memcmp(dst, ref, 8*len)) { - int i; - printf("%s failed\ngot ", test); - for (i = 0; i < 8*len; i++) - printf("%02x ", dst[i]); - printf("\nexpected "); - for (i = 0; i < 8*len; i++) - printf("%02x ", ref[i]); - printf("\n"); - exit(1); - } + xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_crypt_ecb); } -int main(void) +void av_xtea_le_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, + uint8_t *iv, int decrypt) { - AVXTEA ctx; - uint8_t buf[8], iv[8]; - int i; - const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld"; - uint8_t ct[32]; - uint8_t pl[32]; - - for (i = 0; i < XTEA_NUM_TESTS; i++) { - av_xtea_init(&ctx, xtea_test_key[i]); - - test_xtea(&ctx, buf, xtea_test_pt[i], xtea_test_ct[i], 1, NULL, 0, "encryption"); - test_xtea(&ctx, buf, xtea_test_ct[i], xtea_test_pt[i], 1, NULL, 1, "decryption"); - - /* encrypt */ - memcpy(iv, "HALLO123", 8); - av_xtea_crypt(&ctx, ct, src, 4, iv, 0); - - /* decrypt into pl */ - memcpy(iv, "HALLO123", 8); - test_xtea(&ctx, pl, ct, src, 4, iv, 1, "CBC decryption"); - - memcpy(iv, "HALLO123", 8); - test_xtea(&ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption"); - } - printf("Test encryption/decryption success.\n"); - - return 0; + xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_le_crypt_ecb); } - -#endif diff --git a/libavutil/xtea.h b/libavutil/xtea.h index 0fc3810..78b1f37 100644 --- a/libavutil/xtea.h +++ b/libavutil/xtea.h @@ -22,6 +22,7 @@ #define AVUTIL_XTEA_H #include +#include "version.h" /** * @file @@ -31,20 +32,40 @@ * @{ */ +#if FF_API_CRYPTO_CONTEXT typedef struct AVXTEA { uint32_t key[16]; } AVXTEA; +#else +typedef struct AVXTEA AVXTEA; +#endif + +/** + * Allocate an AVXTEA context. + */ +AVXTEA *av_xtea_alloc(void); /** * Initialize an AVXTEA context. * * @param ctx an AVXTEA context - * @param key a key of 16 bytes used for encryption/decryption + * @param key a key of 16 bytes used for encryption/decryption, + * interpreted as big endian 32 bit numbers */ void av_xtea_init(struct AVXTEA *ctx, const uint8_t key[16]); /** - * Encrypt or decrypt a buffer using a previously initialized context. + * Initialize an AVXTEA context. + * + * @param ctx an AVXTEA context + * @param key a key of 16 bytes used for encryption/decryption, + * interpreted as little endian 32 bit numbers + */ +void av_xtea_le_init(struct AVXTEA *ctx, const uint8_t key[16]); + +/** + * Encrypt or decrypt a buffer using a previously initialized context, + * in big endian format. * * @param ctx an AVXTEA context * @param dst destination array, can be equal to src @@ -57,6 +78,20 @@ void av_xtea_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); /** + * Encrypt or decrypt a buffer using a previously initialized context, + * in little endian format. + * + * @param ctx an AVXTEA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_xtea_le_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** * @} */ diff --git a/library.mak b/library.mak old mode 100755 new mode 100644 index 3da14b6..44087aa --- a/library.mak +++ b/library.mak @@ -10,18 +10,6 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%) all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME) all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) -$(SUBDIR)%-test.o: $(SUBDIR)%-test.c - $(COMPILE_C) - -$(SUBDIR)%-test.o: $(SUBDIR)%.c - $(COMPILE_C) - -$(SUBDIR)%-test.i: $(SUBDIR)%-test.c - $(CC) $(CCFLAGS) $(CC_E) $< - -$(SUBDIR)%-test.i: $(SUBDIR)%.c - $(CC) $(CCFLAGS) $(CC_E) $< - $(SUBDIR)x86/%.o: $(SUBDIR)x86/%.asm $(DEPYASM) $(YASMFLAGS) -I $( $(@:.o=.d) $(YASM) $(YASMFLAGS) -I $( $$@ + $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR) $(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME) @@ -57,11 +47,12 @@ $(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver $(DEP_LIBS) $(SLIB_EXTRA_CMD) clean:: - $(RM) $(addprefix $(SUBDIR),*-test$(EXESUF) $(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \ - $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) + $(RM) $(addprefix $(SUBDIR),$(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \ + $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) $(CLEANSUFFIXES:%=$(SUBDIR)tests/%) distclean:: clean - $(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) + $(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) \ + $(DISTCLEANSUFFIXES:%=$(SUBDIR)tests/%) install-lib$(NAME)-shared: $(SUBDIR)$(SLIBNAME) $(Q)mkdir -p "$(SHLIBDIR)" diff --git a/libswscale/Makefile b/libswscale/Makefile index 3e8614d..c9b2fc9 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -3,14 +3,14 @@ NAME = swscale HEADERS = swscale.h \ version.h \ -OBJS = input.o \ - options.o \ - output.o \ - rgb2rgb.o \ - swscale.o \ - swscale_unscaled.o \ - utils.o \ - yuv2rgb.o \ +OBJS = input.o \ + options.o \ + output.o \ + rgb2rgb.o \ + swscale.o \ + swscale_unscaled.o \ + utils.o \ + yuv2rgb.o \ TESTPROGS = colorspace \ swscale \ diff --git a/libswscale/input.c b/libswscale/input.c index f583b3f..9a4fd77 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -496,6 +496,44 @@ static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV, nvXXtoUV_c(dstV, dstU, src1, width); } +static void p010LEToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused) +{ + int i; + for (i = 0; i < width; i++) { + AV_WN16(dst + i * 2, AV_RL16(src + i * 2) >> 6); + } +} + +static void p010BEToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused) +{ + int i; + for (i = 0; i < width; i++) { + AV_WN16(dst + i * 2, AV_RB16(src + i * 2) >> 6); + } +} + +static void p010LEToUV_c(uint8_t *dstU, uint8_t *dstV, + const uint8_t *src1, const uint8_t *src2, + int width, uint32_t *unused) +{ + int i; + for (i = 0; i < width; i++) { + AV_WN16(dstU + i * 2, AV_RL16(src1 + i * 4 + 0) >> 6); + AV_WN16(dstV + i * 2, AV_RL16(src1 + i * 4 + 2) >> 6); + } +} + +static void p010BEToUV_c(uint8_t *dstU, uint8_t *dstV, + const uint8_t *src1, const uint8_t *src2, + int width, uint32_t *unused) +{ + int i; + for (i = 0; i < width; i++) { + AV_WN16(dstU + i * 2, AV_RB16(src1 + i * 4 + 0) >> 6); + AV_WN16(dstV + i * 2, AV_RB16(src1 + i * 4 + 2) >> 6); + } +} + #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos)) static void bgr24ToY_c(uint8_t *dst, const uint8_t *src, @@ -596,6 +634,13 @@ static void planar_rgb_to_y(uint8_t *dst, const uint8_t *src[4], int width) } } +static void planar_rgb_to_a(uint8_t *dst, const uint8_t *src[4], int width) +{ + int i; + for (i = 0; i < width; i++) + dst[i] = src[3][i]; +} + static void planar_rgb_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width) { int i; @@ -745,6 +790,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP10LE: c->readChrPlanar = planar_rgb10le_to_uv; break; + case AV_PIX_FMT_GBRAP16LE: case AV_PIX_FMT_GBRP16LE: c->readChrPlanar = planar_rgb16le_to_uv; break; @@ -754,9 +800,11 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP10BE: c->readChrPlanar = planar_rgb10be_to_uv; break; + case AV_PIX_FMT_GBRAP16BE: case AV_PIX_FMT_GBRP16BE: c->readChrPlanar = planar_rgb16be_to_uv; break; + case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: c->readChrPlanar = planar_rgb_to_uv; break; @@ -803,6 +851,12 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->chrToYV12 = bswap16UV_c; break; #endif + case AV_PIX_FMT_P010LE: + c->chrToYV12 = p010LEToUV_c; + break; + case AV_PIX_FMT_P010BE: + c->chrToYV12 = p010BEToUV_c; + break; } if (c->chrSrcHSubSample) { switch (srcFormat) { @@ -953,6 +1007,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP10LE: c->readLumPlanar = planar_rgb10le_to_y; break; + case AV_PIX_FMT_GBRAP16LE: case AV_PIX_FMT_GBRP16LE: c->readLumPlanar = planar_rgb16le_to_y; break; @@ -962,9 +1017,12 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP10BE: c->readLumPlanar = planar_rgb10be_to_y; break; + case AV_PIX_FMT_GBRAP16BE: case AV_PIX_FMT_GBRP16BE: c->readLumPlanar = planar_rgb16be_to_y; break; + case AV_PIX_FMT_GBRAP: + c->readAlpPlanar = planar_rgb_to_a; case AV_PIX_FMT_GBRP: c->readLumPlanar = planar_rgb_to_y; break; @@ -1114,6 +1172,12 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY_c; break; + case AV_PIX_FMT_P010LE: + c->lumToYV12 = p010LEToY_c; + break; + case AV_PIX_FMT_P010BE: + c->lumToYV12 = p010BEToY_c; + break; } if (c->alpPixBuf) { switch (srcFormat) { diff --git a/libswscale/libswscale.v b/libswscale/libswscale.v index 8b9a96a..96170a1 100644 --- a/libswscale/libswscale.v +++ b/libswscale/libswscale.v @@ -1,4 +1,7 @@ -LIBSWSCALE_$MAJOR { - global: swscale_*; sws_*; - local: *; +LIBSWSCALE_MAJOR { + global: + swscale_*; + sws_*; + local: + *; }; diff --git a/libswscale/options.c b/libswscale/options.c index e7765d6..2371b67 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -66,9 +66,9 @@ static const AVOption swscale_options[] = { { NULL } }; -const AVClass sws_context_class = { "SWScaler", sws_context_to_name, swscale_options }; +const AVClass ff_sws_context_class = { "SWScaler", sws_context_to_name, swscale_options }; const AVClass *sws_get_class(void) { - return &sws_context_class; + return &ff_sws_context_class; } diff --git a/libswscale/output.c b/libswscale/output.c index 125d998..93b3db6 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -18,7 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include @@ -613,7 +612,7 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, V += chrVSrc[j][i] * chrFilter[j]; } - // 8bit: 12+15=27; 16-bit: 12+19=31 + // 8 bits: 12+15=27; 16 bits: 12+19=31 Y1 >>= 14; // 10 Y1 += 0x10000; Y2 >>= 14; @@ -621,20 +620,20 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, U >>= 14; V >>= 14; - // 8bit: 27 -> 17bit, 16bit: 31 - 14 = 17bit + // 8 bits: 27 -> 17 bits, 16 bits: 31 - 14 = 17 bits Y1 -= c->yuv2rgb_y_offset; Y2 -= c->yuv2rgb_y_offset; Y1 *= c->yuv2rgb_y_coeff; Y2 *= c->yuv2rgb_y_coeff; Y1 += 1 << 13; // 21 Y2 += 1 << 13; - // 8bit: 17 + 13bit = 30bit, 16bit: 17 + 13bit = 30bit + // 8 bits: 17 + 13 bits = 30 bits, 16 bits: 17 + 13 bits = 30 bits R = V * c->yuv2rgb_v2r_coeff; G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff; B = U * c->yuv2rgb_u2b_coeff; - // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit + // 8 bits: 30 - 22 = 8 bits, 16 bits: 30 bits - 14 = 16 bits output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14); output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14); output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); @@ -896,7 +895,7 @@ yuv2rgb_write(uint8_t *_dest, int i, unsigned Y1, unsigned Y2, dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1]; dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]; - } else /* 8/4-bit */ { + } else /* 8/4 bits */ { uint8_t *dest = (uint8_t *) _dest; const uint8_t *r = (const uint8_t *) _r; const uint8_t *g = (const uint8_t *) _g; @@ -1277,9 +1276,9 @@ yuv2gbrp_full_X_c(SwsContext *c, const int16_t *lumFilter, { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); int i; - int hasAlpha = 0; + int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrc; uint16_t **dest16 = (uint16_t**)dest; - int SH = 22 + 7 - desc->comp[0].depth_minus1; + int SH = 22 + 8 - desc->comp[0].depth; for (i = 0; i < dstW; i++) { int j; @@ -1329,10 +1328,14 @@ yuv2gbrp_full_X_c(SwsContext *c, const int16_t *lumFilter, dest16[0][i] = G >> SH; dest16[1][i] = B >> SH; dest16[2][i] = R >> SH; + if (hasAlpha) + dest16[3][i] = A; } else { dest[0][i] = G >> 22; dest[1][i] = B >> 22; dest[2][i] = R >> 22; + if (hasAlpha) + dest[3][i] = A; } } if (SH != 22 && (!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) { @@ -1340,6 +1343,8 @@ yuv2gbrp_full_X_c(SwsContext *c, const int16_t *lumFilter, dest16[0][i] = av_bswap16(dest16[0][i]); dest16[1][i] = av_bswap16(dest16[1][i]); dest16[2][i] = av_bswap16(dest16[2][i]); + if (hasAlpha) + dest16[3][i] = av_bswap16(dest16[3][i]); } } } @@ -1360,7 +1365,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; } else if (is9_OR_10BPS(dstFormat)) { - if (desc->comp[0].depth_minus1 == 8) { + if (desc->comp[0].depth == 9) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_9BE_c : yuv2planeX_9LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_9BE_c : yuv2plane1_9LE_c; } else { @@ -1445,6 +1450,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, case AV_PIX_FMT_GBRP10LE: case AV_PIX_FMT_GBRP16BE: case AV_PIX_FMT_GBRP16LE: + case AV_PIX_FMT_GBRAP: *yuv2anyX = yuv2gbrp_full_X_c; break; } diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 7e00488..004b385 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -289,7 +289,7 @@ static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW, av_cold void ff_sws_init_swscale_ppc(SwsContext *c) { -#if HAVE_ALTIVEC +#if HAVE_ALTIVEC && HAVE_BIGENDIAN enum AVPixelFormat dstFormat = c->dstFormat; if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c index 74b0f18..622469a 100644 --- a/libswscale/ppc/yuv2rgb_altivec.c +++ b/libswscale/ppc/yuv2rgb_altivec.c @@ -89,7 +89,6 @@ #include #include #include -#include #include "config.h" #include "libswscale/rgb2rgb.h" @@ -141,7 +140,6 @@ typedef signed char sbyte; * brgb|rgbr|gbrg|brgb * 1001 0010 0100 1001 * a67b 89cA BdCD eEFf - * */ static const vector unsigned char perm_rgb_0 = { 0x00, 0x01, 0x10, 0x02, 0x03, 0x11, 0x04, 0x05, diff --git a/libswscale/rgb2rgb.c b/libswscale/rgb2rgb.c index 3fb3921..030416d 100644 --- a/libswscale/rgb2rgb.c +++ b/libswscale/rgb2rgb.c @@ -129,11 +129,11 @@ void (*yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, * 32-bit C version, and and&add trick by Michael Niedermayer */ -av_cold void sws_rgb2rgb_init(void) +av_cold void ff_rgb2rgb_init(void) { rgb2rgb_init_c(); if (ARCH_X86) - rgb2rgb_init_x86(); + ff_rgb2rgb_init_x86(); } void rgb32to24(const uint8_t *src, uint8_t *dst, int src_size) diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h index f47b04e..f827e60 100644 --- a/libswscale/rgb2rgb.h +++ b/libswscale/rgb2rgb.h @@ -158,8 +158,8 @@ extern void (*yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const u int width, int height, int lumStride, int chromStride, int srcStride); -void sws_rgb2rgb_init(void); +void ff_rgb2rgb_init(void); -void rgb2rgb_init_x86(void); +void ff_rgb2rgb_init_x86(void); #endif /* SWSCALE_RGB2RGB_H */ diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c index 693c7f2..4027d57 100644 --- a/libswscale/rgb2rgb_template.c +++ b/libswscale/rgb2rgb_template.c @@ -856,7 +856,7 @@ static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int lumStride, int chromStride, int srcStride) { int y; - const int chromWidth = -((-width) >> 1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y = 0; y < height; y++) { extract_even_c(src, ydst, width); @@ -876,7 +876,7 @@ static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int lumStride, int chromStride, int srcStride) { int y; - const int chromWidth = -((-width) >> 1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y = 0; y < height; y++) { extract_even_c(src, ydst, width); @@ -894,7 +894,7 @@ static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int lumStride, int chromStride, int srcStride) { int y; - const int chromWidth = -((-width) >> 1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y = 0; y < height; y++) { extract_even_c(src + 1, ydst, width); @@ -914,7 +914,7 @@ static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int lumStride, int chromStride, int srcStride) { int y; - const int chromWidth = -((-width) >> 1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y = 0; y < height; y++) { extract_even_c(src + 1, ydst, width); diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 7756e1b..1319808 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -91,7 +91,7 @@ static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW, int i; int32_t *dst = (int32_t *) _dst; const uint16_t *src = (const uint16_t *) _src; - int bits = desc->comp[0].depth_minus1; + int bits = desc->comp[0].depth - 1; int sh = bits - 4; for (i = 0; i < dstW; i++) { @@ -114,7 +114,7 @@ static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW, const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); int i; const uint16_t *src = (const uint16_t *) _src; - int sh = desc->comp[0].depth_minus1; + int sh = desc->comp[0].depth - 1; for (i = 0; i < dstW; i++) { int j; @@ -269,6 +269,9 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth, } else if (c->readLumPlanar && !isAlpha) { c->readLumPlanar(formatConvBuffer, src_in, srcW); src = formatConvBuffer; + } else if (c->readAlpPlanar && isAlpha) { + c->readAlpPlanar(formatConvBuffer, src_in, srcW); + src = formatConvBuffer; } if (!c->hyscale_fast) { @@ -381,8 +384,8 @@ static int swscale(SwsContext *c, const uint8_t *src[], yuv2packed2_fn yuv2packed2 = c->yuv2packed2; yuv2packedX_fn yuv2packedX = c->yuv2packedX; yuv2anyX_fn yuv2anyX = c->yuv2anyX; - const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample; - const int chrSrcSliceH = -((-srcSliceH) >> c->chrSrcVSubSample); + const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample; + const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample); int should_dither = is9_OR_10BPS(c->srcFormat) || is16BPS(c->srcFormat); int lastDstY; @@ -481,7 +484,7 @@ static int swscale(SwsContext *c, const uint8_t *src[], // Do we have enough lines in this slice to output the dstY line enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && - lastChrSrcY < -((-srcSliceY - srcSliceH) >> c->chrSrcVSubSample); + lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample); if (!enough_lines) { lastLumSrcY = srcSliceY + srcSliceH - 1; @@ -696,8 +699,7 @@ static int swscale(SwsContext *c, const uint8_t *src[], if (is9_OR_10BPS(dstFormat)) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); fill_plane9or10(dst[3], dstStride[3], length, height, lastDstY, - 255, desc->comp[3].depth_minus1 + 1, - isBE(dstFormat)); + 255, desc->comp[3].depth, isBE(dstFormat)); } else fillPlane(dst[3], dstStride[3], length, height, lastDstY, 255); } diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 8abbac4..68ca100 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -74,7 +74,7 @@ const char *swscale_license(void); #define SWS_PRINT_INFO 0x1000 //the following 3 flags are not completely implemented -//internal chrominace subsampling info +//internal chrominance subsampling info #define SWS_FULL_CHR_H_INT 0x2000 //input subsampling info #define SWS_FULL_CHR_H_INP 0x4000 @@ -82,22 +82,6 @@ const char *swscale_license(void); #define SWS_ACCURATE_RND 0x40000 #define SWS_BITEXACT 0x80000 -#if FF_API_SWS_CPU_CAPS -/** - * CPU caps are autodetected now, those flags - * are only provided for API compatibility. - */ -#define SWS_CPU_CAPS_MMX 0x80000000 -#define SWS_CPU_CAPS_MMXEXT 0x20000000 -#define SWS_CPU_CAPS_MMX2 0x20000000 -#define SWS_CPU_CAPS_3DNOW 0x40000000 -#define SWS_CPU_CAPS_ALTIVEC 0x10000000 -#if FF_API_ARCH_BFIN -#define SWS_CPU_CAPS_BFIN 0x01000000 -#endif -#define SWS_CPU_CAPS_SSE2 0x02000000 -#endif - #define SWS_MAX_REDUCE_CUTOFF 0.002 #define SWS_CS_ITU709 1 diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index a0daa07..84f8dd3 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -66,9 +66,9 @@ typedef int (*SwsFunc)(struct SwsContext *context, const uint8_t *src[], * Write one line of horizontally scaled data to planar output * without any additional vertical scaling (or point-scaling). * - * @param src scaled source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param dest pointer to the output plane. For >8bit + * @param src scaled source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param dest pointer to the output plane. For >8-bit * output, this is in uint16_t * @param dstW width of destination in pixels * @param dither ordered dither array of type int16_t and size 8 @@ -81,11 +81,11 @@ typedef void (*yuv2planar1_fn)(const int16_t *src, uint8_t *dest, int dstW, * Write one line of horizontally scaled data to planar output * with multi-point vertical scaling between input pixels. * - * @param filter vertical luma/alpha scaling coefficients, 12bit [0,4096] - * @param src scaled luma (Y) or alpha (A) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param filter vertical luma/alpha scaling coefficients, 12 bits [0,4096] + * @param src scaled luma (Y) or alpha (A) source data, 15 bits for + * 8-10-bit output, 19 bits for 16-bit output (in int32_t) * @param filterSize number of vertical input lines to scale - * @param dest pointer to output plane. For >8bit + * @param dest pointer to output plane. For >8-bit * output, this is in uint16_t * @param dstW width of destination pixels * @param offset Dither offset @@ -99,13 +99,13 @@ typedef void (*yuv2planarX_fn)(const int16_t *filter, int filterSize, * with multi-point vertical scaling between input pixels. * * @param c SWS scaling context - * @param chrFilter vertical chroma scaling coefficients, 12bit [0,4096] - * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param chrFilter vertical chroma scaling coefficients, 12 bits [0,4096] + * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit + * output, 19 bits for 16-bit output (in int32_t) + * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit + * output, 19 bits for 16-bit output (in int32_t) * @param chrFilterSize number of vertical chroma input lines to scale - * @param dest pointer to the output plane. For >8bit + * @param dest pointer to the output plane. For >8-bit * output, this is in uint16_t * @param dstW width of chroma planes */ @@ -122,15 +122,15 @@ typedef void (*yuv2interleavedX_fn)(struct SwsContext *c, * that this function may do chroma scaling, see the "uvalpha" argument. * * @param c SWS scaling context - * @param lumSrc scaled luma (Y) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param alpSrc scaled alpha (A) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param dest pointer to the output plane. For 16bit output, this is + * @param lumSrc scaled luma (Y) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param alpSrc scaled alpha (A) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param dest pointer to the output plane. For 16-bit output, this is * uint16_t * @param dstW width of lumSrc and alpSrc in pixels, number of pixels * to write into dest[] @@ -155,15 +155,15 @@ typedef void (*yuv2packed1_fn)(struct SwsContext *c, const int16_t *lumSrc, * output by doing bilinear scaling between two input lines. * * @param c SWS scaling context - * @param lumSrc scaled luma (Y) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param alpSrc scaled alpha (A) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param dest pointer to the output plane. For 16bit output, this is + * @param lumSrc scaled luma (Y) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param alpSrc scaled alpha (A) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param dest pointer to the output plane. For 16-bit output, this is * uint16_t * @param dstW width of lumSrc and alpSrc in pixels, number of pixels * to write into dest[] @@ -189,19 +189,19 @@ typedef void (*yuv2packed2_fn)(struct SwsContext *c, const int16_t *lumSrc[2], * output by doing multi-point vertical scaling between input pixels. * * @param c SWS scaling context - * @param lumFilter vertical luma/alpha scaling coefficients, 12bit [0,4096] - * @param lumSrc scaled luma (Y) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param lumFilter vertical luma/alpha scaling coefficients, 12 bits [0,4096] + * @param lumSrc scaled luma (Y) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) * @param lumFilterSize number of vertical luma/alpha input lines to scale - * @param chrFilter vertical chroma scaling coefficients, 12bit [0,4096] - * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param chrFilter vertical chroma scaling coefficients, 12 bits [0,4096] + * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) * @param chrFilterSize number of vertical chroma input lines to scale - * @param alpSrc scaled alpha (A) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param dest pointer to the output plane. For 16bit output, this is + * @param alpSrc scaled alpha (A) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param dest pointer to the output plane. For 16-bit output, this is * uint16_t * @param dstW width of lumSrc and alpSrc in pixels, number of pixels * to write into dest[] @@ -223,19 +223,19 @@ typedef void (*yuv2packedX_fn)(struct SwsContext *c, const int16_t *lumFilter, * output by doing multi-point vertical scaling between input pixels. * * @param c SWS scaling context - * @param lumFilter vertical luma/alpha scaling coefficients, 12bit [0,4096] - * @param lumSrc scaled luma (Y) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param lumFilter vertical luma/alpha scaling coefficients, 12 bits [0,4096] + * @param lumSrc scaled luma (Y) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) * @param lumFilterSize number of vertical luma/alpha input lines to scale - * @param chrFilter vertical chroma scaling coefficients, 12bit [0,4096] - * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) + * @param chrFilter vertical chroma scaling coefficients, 12 bits [0,4096] + * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) * @param chrFilterSize number of vertical chroma input lines to scale - * @param alpSrc scaled alpha (A) source data, 15bit for 8-10bit output, - * 19-bit for 16bit output (in int32_t) - * @param dest pointer to the output planes. For 16bit output, this is + * @param alpSrc scaled alpha (A) source data, 15 bits for 8-10-bit output, + * 19 bits for 16-bit output (in int32_t) + * @param dest pointer to the output planes. For 16-bit output, this is * uint16_t * @param dstW width of lumSrc and alpSrc in pixels, number of pixels * to write into dest[] @@ -458,19 +458,20 @@ typedef struct SwsContext { /** * Functions to read planar input, such as planar RGB, and convert - * internally to Y/UV. + * internally to Y/UV/A. */ /** @{ */ void (*readLumPlanar)(uint8_t *dst, const uint8_t *src[4], int width); void (*readChrPlanar)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width); + void (*readAlpPlanar)(uint8_t *dst, const uint8_t *src[4], int width); /** @} */ /** * Scale one horizontal line of input data using a bilinear filter * to produce one line of output data. Compared to SwsContext->hScale(), * please take note of the following caveats when using these: - * - Scaling is done using only 7bit instead of 14bit coefficients. + * - Scaling is done using only 7 bits instead of 14-bit coefficients. * - You can use no more than 5 input pixels to produce 4 output * pixels. Therefore, this filter should not be used for downscaling * by more than ~20% in width (because that equals more than 5/4th @@ -501,15 +502,15 @@ typedef struct SwsContext { * @param dst pointer to destination buffer for horizontally scaled * data. If the number of bits per component of one * destination pixel (SwsContext->dstBpc) is <= 10, data - * will be 15bpc in 16bits (int16_t) width. Else (i.e. + * will be 15 bpc in 16 bits (int16_t) width. Else (i.e. * SwsContext->dstBpc == 16), data will be 19bpc in - * 32bits (int32_t) width. + * 32 bits (int32_t) width. * @param dstW width of destination image * @param src pointer to source data to be scaled. If the number of * bits per component of a source pixel (SwsContext->srcBpc) - * is 8, this is 8bpc in 8bits (uint8_t) width. Else + * is 8, this is 8bpc in 8 bits (uint8_t) width. Else * (i.e. SwsContext->dstBpc > 8), this is native depth - * in 16bits (uint16_t) width. In other words, for 9-bit + * in 16 bits (uint16_t) width. In other words, for 9-bit * YUV input, this is 9bpc, for 10-bit YUV input, this is * 10bpc, and for 16-bit RGB or YUV, this is 16bpc. * @param filter filter coefficients to be used per output pixel for @@ -561,14 +562,14 @@ static av_always_inline int is16BPS(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); av_assert0(desc); - return desc->comp[0].depth_minus1 == 15; + return desc->comp[0].depth == 16; } static av_always_inline int is9_OR_10BPS(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); av_assert0(desc); - return desc->comp[0].depth_minus1 == 8 || desc->comp[0].depth_minus1 == 9; + return desc->comp[0].depth == 9 || desc->comp[0].depth == 10; } static av_always_inline int isBE(enum AVPixelFormat pix_fmt) @@ -599,11 +600,6 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) return (desc->flags & AV_PIX_FMT_FLAG_RGB); } -#if 0 // FIXME -#define isGray(x) \ - (!(av_pix_fmt_descriptors[x].flags & AV_PIX_FMT_FLAG_PAL) && \ - av_pix_fmt_descriptors[x].nb_components <= 2) -#else #define isGray(x) \ ((x) == AV_PIX_FMT_GRAY8 || \ (x) == AV_PIX_FMT_YA8 || \ @@ -611,7 +607,6 @@ static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) (x) == AV_PIX_FMT_GRAY16LE || \ (x) == AV_PIX_FMT_YA16BE || \ (x) == AV_PIX_FMT_YA16LE) -#endif #define isRGBinInt(x) \ ((x) == AV_PIX_FMT_RGB48BE || \ @@ -713,7 +708,7 @@ extern const uint8_t ff_dither_8x8_220[8][8]; extern const int32_t ff_yuv2rgb_coeffs[8][4]; -extern const AVClass sws_context_class; +extern const AVClass ff_sws_context_class; /** * Set c->swscale to an unscaled converter if one exists for the specific diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index ffc813e..0e6be51 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -488,6 +488,23 @@ static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } +static int planarRgbToplanarRgbWrapper(SwsContext *c, + const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dst[0], dstStride[0]); + copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW, + dst[1], dstStride[1]); + copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW, + dst[2], dstStride[2]); + if (dst[3]) + fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + + return srcSliceH; +} + static void packedtogbr24p(const uint8_t *src, int srcStride, uint8_t *dst[], int dstStride[], int srcSliceH, int alpha_first, int inc_size, int width) @@ -781,11 +798,12 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); int plane, i, j; for (plane = 0; plane < 4; plane++) { - int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample); - int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample); - int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample); + int length = (plane == 0 || plane == 3) ? c->srcW : AV_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); + int y = (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); + int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); const uint8_t *srcPtr = src[plane]; uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; + int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0); if (!dst[plane]) continue; @@ -798,27 +816,38 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], if (is9_OR_10BPS(c->dstFormat)) { fill_plane9or10(dst[plane], dstStride[plane], length, height, y, val, - desc_dst->comp[plane].depth_minus1 + 1, + desc_dst->comp[plane].depth, isBE(c->dstFormat)); } else fillPlane(dst[plane], dstStride[plane], length, height, y, val); } else { if (is9_OR_10BPS(c->srcFormat)) { - const int src_depth = desc_src->comp[plane].depth_minus1 + 1; - const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1; + const int src_depth = desc_src->comp[plane].depth; + const int dst_depth = desc_dst->comp[plane].depth; const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; if (is16BPS(c->dstFormat)) { uint16_t *dstPtr2 = (uint16_t *) dstPtr; #define COPY9_OR_10TO16(rfunc, wfunc) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < length; j++) { \ - int srcpx = rfunc(&srcPtr2[j]); \ - wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \ + if (shiftonly) { \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < length; j++) { \ + int srcpx = rfunc(&srcPtr2[j]); \ + wfunc(&dstPtr2[j], srcpx << (16 - src_depth)); \ + } \ + dstPtr2 += dstStride[plane] / 2; \ + srcPtr2 += srcStride[plane] / 2; \ + } \ + } else { \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < length; j++) { \ + int srcpx = rfunc(&srcPtr2[j]); \ + wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \ + } \ + dstPtr2 += dstStride[plane] / 2; \ + srcPtr2 += srcStride[plane] / 2; \ } \ - dstPtr2 += dstStride[plane] / 2; \ - srcPtr2 += srcStride[plane] / 2; \ } if (isBE(c->dstFormat)) { if (isBE(c->srcFormat)) { @@ -886,7 +915,7 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], } } } else if (is9_OR_10BPS(c->dstFormat)) { - const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1; + const int dst_depth = desc_dst->comp[plane].depth; uint16_t *dstPtr2 = (uint16_t *) dstPtr; if (is16BPS(c->srcFormat)) { @@ -914,15 +943,26 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], COPY16TO9_OR_10(AV_RL16, AV_WL16); } } - } else /* 8bit */ { + } else /* 8 bits */ { #define COPY8TO9_OR_10(wfunc) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < length; j++) { \ - const int srcpx = srcPtr[j]; \ - wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \ + if (shiftonly) { \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < length; j++) { \ + const int srcpx = srcPtr[j]; \ + wfunc(&dstPtr2[j], srcpx << (dst_depth - 8)); \ + } \ + dstPtr2 += dstStride[plane] / 2; \ + srcPtr += srcStride[plane]; \ + } \ + } else { \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < length; j++) { \ + const int srcpx = srcPtr[j]; \ + wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \ + } \ + dstPtr2 += dstStride[plane] / 2; \ + srcPtr += srcStride[plane]; \ } \ - dstPtr2 += dstStride[plane] / 2; \ - srcPtr += srcStride[plane]; \ } if (isBE(c->dstFormat)) { COPY8TO9_OR_10(AV_WB16); @@ -966,7 +1006,7 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], } else { if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) length *= 2; - else if (!desc_src->comp[0].depth_minus1) + else if (desc_src->comp[0].depth == 1) length >>= 3; // monowhite/black for (i = 0; i < height; i++) { memcpy(dstPtr, srcPtr, length); @@ -1031,6 +1071,11 @@ void ff_get_unscaled_swscale(SwsContext *c) && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) c->swscale = rgbToRgbWrapper; + /* RGB to planar RGB */ + if ((srcFormat == AV_PIX_FMT_GBRP && dstFormat == AV_PIX_FMT_GBRAP) || + (srcFormat == AV_PIX_FMT_GBRAP && dstFormat == AV_PIX_FMT_GBRP)) + c->swscale = planarRgbToplanarRgbWrapper; + #define isByteRGB(f) ( \ f == AV_PIX_FMT_RGB32 || \ f == AV_PIX_FMT_RGB32_1 || \ @@ -1042,7 +1087,7 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat)) c->swscale = planarRgbToRgbWrapper; - if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 && + if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth == 8 && isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP) c->swscale = rgbToPlanarRgbWrapper; @@ -1054,6 +1099,7 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16)|| IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || @@ -1110,7 +1156,9 @@ void ff_get_unscaled_swscale(SwsContext *c) c->chrDstHSubSample == c->chrSrcHSubSample && c->chrDstVSubSample == c->chrSrcVSubSample && dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && - srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21)) + dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE && + srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 && + srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE)) { if (isPacked(c->srcFormat)) c->swscale = packedCopyWrapper; @@ -1122,7 +1170,7 @@ void ff_get_unscaled_swscale(SwsContext *c) ff_get_unscaled_swscale_ppc(c); } -static void reset_ptr(const uint8_t *src[], int format) +static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format) { if (!isALPHA(format)) src[3] = NULL; diff --git a/libswscale/tests/.gitignore b/libswscale/tests/.gitignore new file mode 100644 index 0000000..0ac3691 --- /dev/null +++ b/libswscale/tests/.gitignore @@ -0,0 +1,2 @@ +/colorspace +/swscale diff --git a/libswscale/colorspace-test.c b/libswscale/tests/colorspace.c similarity index 98% rename from libswscale/colorspace-test.c rename to libswscale/tests/colorspace.c index fbf595d..23a1945 100644 --- a/libswscale/colorspace-test.c +++ b/libswscale/tests/colorspace.c @@ -23,10 +23,11 @@ #include #include -#include "swscale.h" -#include "rgb2rgb.h" #include "libavutil/mem.h" +#include "libswscale/rgb2rgb.h" +#include "libswscale/swscale.h" + #define SIZE 1000 #define srcByte 0x55 #define dstByte 0xBB @@ -45,7 +46,7 @@ int main(void) return -1; av_log(NULL, AV_LOG_INFO, "memory corruption test ...\n"); - sws_rgb2rgb_init(); + ff_rgb2rgb_init(); for (funcNum = 0; ; funcNum++) { struct func_info_s { diff --git a/libswscale/swscale-test.c b/libswscale/tests/swscale.c similarity index 99% rename from libswscale/swscale-test.c rename to libswscale/tests/swscale.c index 8063519..309ef81 100644 --- a/libswscale/swscale-test.c +++ b/libswscale/tests/swscale.c @@ -31,7 +31,8 @@ #include "libavutil/crc.h" #include "libavutil/pixdesc.h" #include "libavutil/lfg.h" -#include "swscale.h" + +#include "libswscale/swscale.h" /* HACK Duplicated from swscale_internal.h. * Should be removed when a cleaner pixel format system exists. */ diff --git a/libswscale/utils.c b/libswscale/utils.c index 32e304c..c4fb745 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -180,8 +180,13 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_GBRP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRP16LE] = { 1, 0 }, [AV_PIX_FMT_GBRP16BE] = { 1, 0 }, + [AV_PIX_FMT_GBRAP] = { 1, 1 }, + [AV_PIX_FMT_GBRAP16LE] = { 1, 0 }, + [AV_PIX_FMT_GBRAP16BE] = { 1, 0 }, [AV_PIX_FMT_XYZ12BE] = { 0, 0, 1 }, [AV_PIX_FMT_XYZ12LE] = { 0, 0, 1 }, + [AV_PIX_FMT_P010LE] = { 1, 0 }, + [AV_PIX_FMT_P010BE] = { 1, 0 }, }; int sws_isSupportedInput(enum AVPixelFormat pix_fmt) @@ -367,13 +372,6 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, } coeff *= fone >> (30 + 24); } -#if 0 - else if (flags & SWS_X) { - double p = param ? param * 0.01 : 0.3; - coeff = d ? sin(d * M_PI) / (d * M_PI) : 1.0; - coeff *= pow(2.0, -p * d * d); - } -#endif else if (flags & SWS_X) { double A = param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0; double c; @@ -646,9 +644,9 @@ static av_cold int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode, "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" + "movq (%%"FF_REG_d", %%"FF_REG_a"), %%mm3 \n\t" + "movd (%%"FF_REG_c", %%"FF_REG_S"), %%mm0 \n\t" + "movd 1(%%"FF_REG_c", %%"FF_REG_S"), %%mm1 \n\t" "punpcklbw %%mm7, %%mm1 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" "pshufw $0xFF, %%mm1, %%mm1 \n\t" @@ -656,14 +654,14 @@ static av_cold int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode, "pshufw $0xFF, %%mm0, %%mm0 \n\t" "2: \n\t" "psubw %%mm1, %%mm0 \n\t" - "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t" + "movl 8(%%"FF_REG_b", %%"FF_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" + "movq %%mm0, (%%"FF_REG_D", %%"FF_REG_a") \n\t" - "add $8, %%"REG_a" \n\t" + "add $8, %%"FF_REG_a" \n\t" // End "9: \n\t" // "int $3 \n\t" @@ -686,22 +684,22 @@ static av_cold int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode, "jmp 9f \n\t" // Begin "0: \n\t" - "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t" - "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t" + "movq (%%"FF_REG_d", %%"FF_REG_a"), %%mm3 \n\t" + "movd (%%"FF_REG_c", %%"FF_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" + "movl 8(%%"FF_REG_b", %%"FF_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" + "movq %%mm0, (%%"FF_REG_D", %%"FF_REG_a") \n\t" - "add $8, %%"REG_a" \n\t" + "add $8, %%"FF_REG_a" \n\t" // End "9: \n\t" // "int $3 \n\t" @@ -862,7 +860,7 @@ SwsContext *sws_alloc_context(void) SwsContext *c = av_mallocz(sizeof(SwsContext)); if (c) { - c->av_class = &sws_context_class; + c->av_class = &ff_sws_context_class; av_opt_set_defaults(c); } @@ -892,7 +890,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, flags = c->flags; emms_c(); if (!rgb15to16) - sws_rgb2rgb_init(); + ff_rgb2rgb_init(); unscaled = (srcW == dstW && srcH == dstH); @@ -1016,11 +1014,11 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, (flags & SWS_FAST_BILINEAR))) c->chrSrcHSubSample = 1; - // Note the -((-x)>>y) is so that we always round toward +inf. - c->chrSrcW = -((-srcW) >> c->chrSrcHSubSample); - c->chrSrcH = -((-srcH) >> c->chrSrcVSubSample); - c->chrDstW = -((-dstW) >> c->chrDstHSubSample); - c->chrDstH = -((-dstH) >> c->chrDstVSubSample); + // Note the AV_CEIL_RSHIFT is so that we always round toward +inf. + c->chrSrcW = AV_CEIL_RSHIFT(srcW, c->chrSrcHSubSample); + c->chrSrcH = AV_CEIL_RSHIFT(srcH, c->chrSrcVSubSample); + c->chrDstW = AV_CEIL_RSHIFT(dstW, c->chrDstHSubSample); + c->chrDstH = AV_CEIL_RSHIFT(dstH, c->chrDstVSubSample); /* unscaled special cases */ if (unscaled && !usesHFilter && !usesVFilter && @@ -1036,10 +1034,10 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, } } - c->srcBpc = 1 + desc_src->comp[0].depth_minus1; + c->srcBpc = desc_src->comp[0].depth; if (c->srcBpc < 8) c->srcBpc = 8; - c->dstBpc = 1 + desc_dst->comp[0].depth_minus1; + c->dstBpc = desc_dst->comp[0].depth; if (c->dstBpc < 8) c->dstBpc = 8; if (c->dstBpc == 16) @@ -1379,8 +1377,13 @@ SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, filter->chrV = sws_getIdentityVec(); } + if (!filter->lumH || !filter->lumV || !filter->chrH || !filter->chrV) + goto fail; + if (chromaSharpen != 0.0) { SwsVector *id = sws_getIdentityVec(); + if (!id) + goto fail; sws_scaleVec(filter->chrH, -chromaSharpen); sws_scaleVec(filter->chrV, -chromaSharpen); sws_addVec(filter->chrH, id); @@ -1390,6 +1393,8 @@ SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, if (lumaSharpen != 0.0) { SwsVector *id = sws_getIdentityVec(); + if (!id) + goto fail; sws_scaleVec(filter->lumH, -lumaSharpen); sws_scaleVec(filter->lumV, -lumaSharpen); sws_addVec(filter->lumH, id); @@ -1414,6 +1419,14 @@ SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG); return filter; + +fail: + sws_freeVec(filter->lumH); + sws_freeVec(filter->lumV); + sws_freeVec(filter->chrH); + sws_freeVec(filter->chrV); + av_freep(&filter); + return NULL; } SwsVector *sws_allocVec(int length) diff --git a/libswscale/version.h b/libswscale/version.h index fdde657..701ce1b 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -26,7 +26,7 @@ #include "libavutil/version.h" -#define LIBSWSCALE_VERSION_MAJOR 3 +#define LIBSWSCALE_VERSION_MAJOR 4 #define LIBSWSCALE_VERSION_MINOR 0 #define LIBSWSCALE_VERSION_MICRO 0 @@ -46,11 +46,4 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_SWS_CPU_CAPS -#define FF_API_SWS_CPU_CAPS (LIBSWSCALE_VERSION_MAJOR < 4) -#endif -#ifndef FF_API_ARCH_BFIN -#define FF_API_ARCH_BFIN (LIBSWSCALE_VERSION_MAJOR < 4) -#endif - #endif /* SWSCALE_VERSION_H */ diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index e1ceded..71cd72e 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -50,8 +50,8 @@ SECTION .text ; const uint8_t *dither, int offset) ; ; Scale one or $filterSize lines of source data to generate one line of output -; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in -; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple +; data. The input is 15 bits in int16_t if $output_size is [8,10] and 19 bits in +; int32_t if $output_size is 16. $filter is 12 bits. $filterSize is a multiple ; of 2. $offset is either 0 or 3. $dither holds 8 values. ;----------------------------------------------------------------------------- @@ -125,10 +125,10 @@ cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset .pixelloop: %assign %%i 0 - ; the rep here is for the 8bit output mmx case, where dither covers + ; the rep here is for the 8-bit output MMX case, where dither covers ; 8 pixels but we can only handle 2 pixels per register, and thus 4 ; pixels per iteration. In order to not have to keep track of where - ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2. + ; we are w.r.t. dithering, we unroll the MMX/8-bit loop x2. %if %1 == 8 %assign %%repcnt 16/mmsize %else diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c index 9cfe831..c6635b4 100644 --- a/libswscale/x86/rgb2rgb.c +++ b/libswscale/x86/rgb2rgb.c @@ -27,7 +27,6 @@ #include "config.h" #include "libavutil/attributes.h" -#include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavutil/cpu.h" #include "libavutil/bswap.h" @@ -138,7 +137,7 @@ DECLARE_ASM_CONST(8, uint64_t, blue_15mask) = 0x0000001f0000001fULL; #endif /* HAVE_INLINE_ASM */ -av_cold void rgb2rgb_init_x86(void) +av_cold void ff_rgb2rgb_init_x86(void) { #if HAVE_INLINE_ASM int cpu_flags = av_get_cpu_flags(); diff --git a/libswscale/x86/rgb2rgb_template.c b/libswscale/x86/rgb2rgb_template.c index 5d34c21..3b9c82b 100644 --- a/libswscale/x86/rgb2rgb_template.c +++ b/libswscale/x86/rgb2rgb_template.c @@ -1109,43 +1109,43 @@ static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, int sr unsigned i; x86_reg mmx_size= 23 - src_size; __asm__ volatile ( - "test %%"REG_a", %%"REG_a" \n\t" + "test %%"FF_REG_a", %%"FF_REG_a" \n\t" "jns 2f \n\t" "movq "MANGLE(mask24r)", %%mm5 \n\t" "movq "MANGLE(mask24g)", %%mm6 \n\t" "movq "MANGLE(mask24b)", %%mm7 \n\t" ".p2align 4 \n\t" "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 + PREFETCH" 32(%1, %%"FF_REG_a") \n\t" + "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" // BGR BGR BG + "movq (%1, %%"FF_REG_a"), %%mm1 \n\t" // BGR BGR BG + "movq 2(%1, %%"FF_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 + "movq 6(%1, %%"FF_REG_a"), %%mm0 \n\t" // BGR BGR BG + MOVNTQ" %%mm1, (%2, %%"FF_REG_a") \n\t" // RGB RGB RG + "movq 8(%1, %%"FF_REG_a"), %%mm1 \n\t" // R BGR BGR B + "movq 10(%1, %%"FF_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 + "movq 14(%1, %%"FF_REG_a"), %%mm0 \n\t" // R BGR BGR B + MOVNTQ" %%mm1, 8(%2, %%"FF_REG_a")\n\t" // B RGB RGB R + "movq 16(%1, %%"FF_REG_a"), %%mm1 \n\t" // GR BGR BGR + "movq 18(%1, %%"FF_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" + MOVNTQ" %%mm1, 16(%2, %%"FF_REG_a")\n\t" + "add $24, %%"FF_REG_a" \n\t" " js 1b \n\t" "2: \n\t" : "+a" (mmx_size) @@ -1180,20 +1180,20 @@ static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *u for (y=0; y>1; for (y=0; y>1; for (y=0; y>1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y=0; y>1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y=0; y>1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y=0; y>1); + const int chromWidth = AV_CEIL_RSHIFT(width, 1); for (y=0; yredDither), \ "m" (dummy), "m" (dummy), "m" (dummy),\ "r" (dest), "m" (dstW_reg), "m"(uv_off) \ - : "%"REG_a, "%"REG_d, "%"REG_S \ + : "%"FF_REG_a, "%"FF_REG_d, "%"FF_REG_S \ ); #define YSCALEYUV2PACKEDX_ACCURATE_UV \ __asm__ volatile(\ - "xor %%"REG_a", %%"REG_a" \n\t"\ + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\ ".p2align 4 \n\t"\ "nop \n\t"\ "1: \n\t"\ - "lea "CHR_MMX_FILTER_OFFSET"(%0), %%"REG_d" \n\t"\ - "mov (%%"REG_d"), %%"REG_S" \n\t"\ + "lea "CHR_MMX_FILTER_OFFSET"(%0), %%"FF_REG_d" \n\t"\ + "mov (%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ "pxor %%mm4, %%mm4 \n\t"\ "pxor %%mm5, %%mm5 \n\t"\ "pxor %%mm6, %%mm6 \n\t"\ "pxor %%mm7, %%mm7 \n\t"\ ".p2align 4 \n\t"\ "2: \n\t"\ - "movq (%%"REG_S", %%"REG_a"), %%mm0 \n\t" /* UsrcData */\ - "add %6, %%"REG_S" \n\t" \ - "movq (%%"REG_S", %%"REG_a"), %%mm2 \n\t" /* VsrcData */\ - "mov "STR(APCK_PTR2)"(%%"REG_d"), %%"REG_S" \n\t"\ - "movq (%%"REG_S", %%"REG_a"), %%mm1 \n\t" /* UsrcData */\ + "movq (%%"FF_REG_S", %%"FF_REG_a"), %%mm0 \n\t" /* UsrcData */\ + "add %6, %%"FF_REG_S" \n\t" \ + "movq (%%"FF_REG_S", %%"FF_REG_a"), %%mm2 \n\t" /* VsrcData */\ + "mov "STR(APCK_PTR2)"(%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ + "movq (%%"FF_REG_S", %%"FF_REG_a"), %%mm1 \n\t" /* UsrcData */\ "movq %%mm0, %%mm3 \n\t"\ "punpcklwd %%mm1, %%mm0 \n\t"\ "punpckhwd %%mm1, %%mm3 \n\t"\ - "movq "STR(APCK_COEF)"(%%"REG_d"),%%mm1 \n\t" /* filterCoeff */\ + "movq "STR(APCK_COEF)"(%%"FF_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"\ - "add %6, %%"REG_S" \n\t" \ - "movq (%%"REG_S", %%"REG_a"), %%mm3 \n\t" /* VsrcData */\ - "mov "STR(APCK_SIZE)"(%%"REG_d"), %%"REG_S" \n\t"\ - "add $"STR(APCK_SIZE)", %%"REG_d" \n\t"\ - "test %%"REG_S", %%"REG_S" \n\t"\ + "add %6, %%"FF_REG_S" \n\t"\ + "movq (%%"FF_REG_S", %%"FF_REG_a"), %%mm3 \n\t" /* VsrcData */\ + "mov "STR(APCK_SIZE)"(%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ + "add $"STR(APCK_SIZE)", %%"FF_REG_d" \n\t"\ + "test %%"FF_REG_S", %%"FF_REG_S" \n\t"\ "movq %%mm2, %%mm0 \n\t"\ "punpcklwd %%mm3, %%mm2 \n\t"\ "punpckhwd %%mm3, %%mm0 \n\t"\ @@ -148,30 +148,30 @@ "movq %%mm6, "V_TEMP"(%0) \n\t"\ #define YSCALEYUV2PACKEDX_ACCURATE_YA(offset) \ - "lea "offset"(%0), %%"REG_d" \n\t"\ - "mov (%%"REG_d"), %%"REG_S" \n\t"\ + "lea "offset"(%0), %%"FF_REG_d" \n\t"\ + "mov (%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ "pxor %%mm1, %%mm1 \n\t"\ "pxor %%mm5, %%mm5 \n\t"\ "pxor %%mm7, %%mm7 \n\t"\ "pxor %%mm6, %%mm6 \n\t"\ ".p2align 4 \n\t"\ "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 "STR(APCK_PTR2)"(%%"REG_d"), %%"REG_S" \n\t"\ - "movq (%%"REG_S", %%"REG_a", 2), %%mm4 \n\t" /* Y1srcData */\ + "movq (%%"FF_REG_S", %%"FF_REG_a", 2), %%mm0 \n\t" /* Y1srcData */\ + "movq 8(%%"FF_REG_S", %%"FF_REG_a", 2), %%mm2 \n\t" /* Y2srcData */\ + "mov "STR(APCK_PTR2)"(%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ + "movq (%%"FF_REG_S", %%"FF_REG_a", 2), %%mm4 \n\t" /* Y1srcData */\ "movq %%mm0, %%mm3 \n\t"\ "punpcklwd %%mm4, %%mm0 \n\t"\ "punpckhwd %%mm4, %%mm3 \n\t"\ - "movq "STR(APCK_COEF)"(%%"REG_d"), %%mm4 \n\t" /* filterCoeff */\ + "movq "STR(APCK_COEF)"(%%"FF_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 "STR(APCK_SIZE)"(%%"REG_d"), %%"REG_S" \n\t"\ - "add $"STR(APCK_SIZE)", %%"REG_d" \n\t"\ - "test %%"REG_S", %%"REG_S" \n\t"\ + "movq 8(%%"FF_REG_S", %%"FF_REG_a", 2), %%mm3 \n\t" /* Y2srcData */\ + "mov "STR(APCK_SIZE)"(%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ + "add $"STR(APCK_SIZE)", %%"FF_REG_d" \n\t"\ + "test %%"FF_REG_S", %%"FF_REG_S" \n\t"\ "movq %%mm2, %%mm0 \n\t"\ "punpcklwd %%mm3, %%mm2 \n\t"\ "punpckhwd %%mm3, %%mm0 \n\t"\ @@ -278,13 +278,13 @@ static void RENAME(yuv2rgb32_X_ar)(SwsContext *c, const int16_t *lumFilter, "psraw $3, %%mm1 \n\t" "psraw $3, %%mm7 \n\t" "packuswb %%mm7, %%mm1 \n\t" - WRITEBGR32(%4, %5, %%REGa, %%mm3, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm2, %%mm6) + WRITEBGR32(%4, %5, %%FF_REGa, %%mm3, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm2, %%mm6) YSCALEYUV2PACKEDX_END } else { YSCALEYUV2PACKEDX_ACCURATE YSCALEYUV2RGBX "pcmpeqd %%mm7, %%mm7 \n\t" - WRITEBGR32(%4, %5, %%REGa, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + WRITEBGR32(%4, %5, %%FF_REGa, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) YSCALEYUV2PACKEDX_END } } @@ -307,13 +307,13 @@ static void RENAME(yuv2rgb32_X)(SwsContext *c, const int16_t *lumFilter, "psraw $3, %%mm1 \n\t" "psraw $3, %%mm7 \n\t" "packuswb %%mm7, %%mm1 \n\t" - WRITEBGR32(%4, %5, %%REGa, %%mm2, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm3, %%mm6) + WRITEBGR32(%4, %5, %%FF_REGa, %%mm2, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm3, %%mm6) YSCALEYUV2PACKEDX_END } else { YSCALEYUV2PACKEDX YSCALEYUV2RGBX "pcmpeqd %%mm7, %%mm7 \n\t" - WRITEBGR32(%4, %5, %%REGa, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + WRITEBGR32(%4, %5, %%FF_REGa, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) YSCALEYUV2PACKEDX_END } } @@ -366,7 +366,7 @@ static void RENAME(yuv2rgb565_X_ar)(SwsContext *c, const int16_t *lumFilter, "paddusb "GREEN_DITHER"(%0), %%mm4\n\t" "paddusb "RED_DITHER"(%0), %%mm5\n\t" #endif - WRITERGB16(%4, %5, %%REGa) + WRITERGB16(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -390,7 +390,7 @@ static void RENAME(yuv2rgb565_X)(SwsContext *c, const int16_t *lumFilter, "paddusb "GREEN_DITHER"(%0), %%mm4 \n\t" "paddusb "RED_DITHER"(%0), %%mm5 \n\t" #endif - WRITERGB16(%4, %5, %%REGa) + WRITERGB16(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -443,7 +443,7 @@ static void RENAME(yuv2rgb555_X_ar)(SwsContext *c, const int16_t *lumFilter, "paddusb "GREEN_DITHER"(%0), %%mm4\n\t" "paddusb "RED_DITHER"(%0), %%mm5\n\t" #endif - WRITERGB15(%4, %5, %%REGa) + WRITERGB15(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -467,7 +467,7 @@ static void RENAME(yuv2rgb555_X)(SwsContext *c, const int16_t *lumFilter, "paddusb "GREEN_DITHER"(%0), %%mm4 \n\t" "paddusb "RED_DITHER"(%0), %%mm5 \n\t" #endif - WRITERGB15(%4, %5, %%REGa) + WRITERGB15(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -593,14 +593,14 @@ static void RENAME(yuv2bgr24_X_ar)(SwsContext *c, const int16_t *lumFilter, YSCALEYUV2PACKEDX_ACCURATE YSCALEYUV2RGBX - "pxor %%mm7, %%mm7 \n\t" - "lea (%%"REG_a", %%"REG_a", 2), %%"REG_c"\n\t" //FIXME optimize - "add %4, %%"REG_c" \n\t" - WRITEBGR24(%%REGc, %5, %%REGa) + "pxor %%mm7, %%mm7 \n\t" + "lea (%%"FF_REG_a", %%"FF_REG_a", 2), %%"FF_REG_c" \n\t" // FIXME optimize + "add %4, %%"FF_REG_c" \n\t" + WRITEBGR24(%%FF_REGc, %5, %%FF_REGa) :: "r" (&c->redDither), "m" (dummy), "m" (dummy), "m" (dummy), "r" (dest), "m" (dstW_reg), "m"(uv_off) - : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S + : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S ); } @@ -617,14 +617,14 @@ static void RENAME(yuv2bgr24_X)(SwsContext *c, const int16_t *lumFilter, YSCALEYUV2PACKEDX YSCALEYUV2RGBX - "pxor %%mm7, %%mm7 \n\t" - "lea (%%"REG_a", %%"REG_a", 2), %%"REG_c" \n\t" //FIXME optimize - "add %4, %%"REG_c" \n\t" - WRITEBGR24(%%REGc, %5, %%REGa) + "pxor %%mm7, %%mm7 \n\t" + "lea (%%"FF_REG_a", %%"FF_REG_a", 2), %%"FF_REG_c" \n\t" // FIXME optimize + "add %4, %%"FF_REG_c" \n\t" + WRITEBGR24(%%FF_REGc, %5, %%FF_REGa) :: "r" (&c->redDither), "m" (dummy), "m" (dummy), "m" (dummy), "r" (dest), "m" (dstW_reg), "m"(uv_off) - : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S + : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S ); } @@ -662,7 +662,7 @@ static void RENAME(yuv2yuyv422_X_ar)(SwsContext *c, const int16_t *lumFilter, "psraw $3, %%mm4 \n\t" "psraw $3, %%mm1 \n\t" "psraw $3, %%mm7 \n\t" - WRITEYUY2(%4, %5, %%REGa) + WRITEYUY2(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -683,7 +683,7 @@ static void RENAME(yuv2yuyv422_X)(SwsContext *c, const int16_t *lumFilter, "psraw $3, %%mm4 \n\t" "psraw $3, %%mm1 \n\t" "psraw $3, %%mm7 \n\t" - WRITEYUY2(%4, %5, %%REGa) + WRITEYUY2(%4, %5, %%FF_REGa) YSCALEYUV2PACKEDX_END } @@ -794,37 +794,37 @@ static void RENAME(yuv2rgb32_2)(SwsContext *c, const int16_t *buf[2], *(const uint16_t **)(&c->u_temp)=abuf0; *(const uint16_t **)(&c->v_temp)=abuf1; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB(%%FF_REGBP, %5) "push %0 \n\t" "push %1 \n\t" "mov "U_TEMP"(%5), %0 \n\t" "mov "V_TEMP"(%5), %1 \n\t" - YSCALEYUV2RGB_YA(%%REGBP, %5, %0, %1) + YSCALEYUV2RGB_YA(%%FF_REGBP, %5, %0, %1) "psraw $3, %%mm1 \n\t" /* abuf0[eax] - abuf1[eax] >>7*/ "psraw $3, %%mm7 \n\t" /* abuf0[eax] - abuf1[eax] >>7*/ "packuswb %%mm7, %%mm1 \n\t" "pop %1 \n\t" "pop %0 \n\t" - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm1, %%mm0, %%mm7, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); #endif } else { __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB(%%FF_REGBP, %5) "pcmpeqd %%mm7, %%mm7 \n\t" - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -841,14 +841,14 @@ static void RENAME(yuv2bgr24_2)(SwsContext *c, const int16_t *buf[2], //Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :( __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" - WRITEBGR24(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR24(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -864,10 +864,10 @@ static void RENAME(yuv2rgb555_2)(SwsContext *c, const int16_t *buf[2], //Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :( __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -875,9 +875,9 @@ static void RENAME(yuv2rgb555_2)(SwsContext *c, const int16_t *buf[2], "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB15(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB15(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -893,10 +893,10 @@ static void RENAME(yuv2rgb565_2)(SwsContext *c, const int16_t *buf[2], //Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :( __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -904,9 +904,9 @@ static void RENAME(yuv2rgb565_2)(SwsContext *c, const int16_t *buf[2], "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB16(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB16(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -962,13 +962,13 @@ static void RENAME(yuv2yuyv422_2)(SwsContext *c, const int16_t *buf[2], //Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :( __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" + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2PACKED(%%FF_REGBP, %5) + WRITEYUY2(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1104,27 +1104,27 @@ static void RENAME(yuv2rgb32_1)(SwsContext *c, const int16_t *buf0, const int16_t *ubuf1 = ubuf[0]; if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) { __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1(%%REGBP, %5) - YSCALEYUV2RGB1_ALPHA(%%REGBP) - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1(%%FF_REGBP, %5) + YSCALEYUV2RGB1_ALPHA(%%FF_REGBP) + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (abuf0), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1(%%FF_REGBP, %5) "pcmpeqd %%mm7, %%mm7 \n\t" - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1133,27 +1133,27 @@ static void RENAME(yuv2rgb32_1)(SwsContext *c, const int16_t *buf0, const int16_t *ubuf1 = ubuf[1]; if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) { __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1b(%%REGBP, %5) - YSCALEYUV2RGB1_ALPHA(%%REGBP) - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1b(%%FF_REGBP, %5) + YSCALEYUV2RGB1_ALPHA(%%FF_REGBP) + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (abuf0), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1b(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1b(%%FF_REGBP, %5) "pcmpeqd %%mm7, %%mm7 \n\t" - WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR32(%%FF_REGb, 8280(%5), %%FF_REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1172,28 +1172,28 @@ static void RENAME(yuv2bgr24_1)(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster const int16_t *ubuf1 = ubuf[0]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" - WRITEBGR24(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR24(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { const int16_t *ubuf1 = ubuf[1]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1b(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1b(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" - WRITEBGR24(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITEBGR24(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1211,10 +1211,10 @@ static void RENAME(yuv2rgb555_1)(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster const int16_t *ubuf1 = ubuf[0]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -1222,19 +1222,19 @@ static void RENAME(yuv2rgb555_1)(SwsContext *c, const int16_t *buf0, "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB15(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB15(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { const int16_t *ubuf1 = ubuf[1]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1b(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1b(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -1242,9 +1242,9 @@ static void RENAME(yuv2rgb555_1)(SwsContext *c, const int16_t *buf0, "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB15(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB15(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1262,10 +1262,10 @@ static void RENAME(yuv2rgb565_1)(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster const int16_t *ubuf1 = ubuf[0]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -1273,19 +1273,19 @@ static void RENAME(yuv2rgb565_1)(SwsContext *c, const int16_t *buf0, "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB16(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB16(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { const int16_t *ubuf1 = ubuf[1]; __asm__ volatile( - "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t" - "mov %4, %%"REG_b" \n\t" - "push %%"REG_BP" \n\t" - YSCALEYUV2RGB1b(%%REGBP, %5) + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2RGB1b(%%FF_REGBP, %5) "pxor %%mm7, %%mm7 \n\t" /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP @@ -1293,9 +1293,9 @@ static void RENAME(yuv2rgb565_1)(SwsContext *c, const int16_t *buf0, "paddusb "GREEN_DITHER"(%5), %%mm4 \n\t" "paddusb "RED_DITHER"(%5), %%mm5 \n\t" #endif - WRITERGB16(%%REGb, 8280(%5), %%REGBP) - "pop %%"REG_BP" \n\t" - "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t" + WRITERGB16(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1350,26 +1350,26 @@ static void RENAME(yuv2yuyv422_1)(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster const int16_t *ubuf1 = ubuf[0]; __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" + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2PACKED1(%%FF_REGBP, %5) + WRITEYUY2(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); } else { const int16_t *ubuf1 = ubuf[1]; __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" + "mov %%"FF_REG_b", "ESP_OFFSET"(%5) \n\t" + "mov %4, %%"FF_REG_b" \n\t" + "push %%"FF_REG_BP" \n\t" + YSCALEYUV2PACKED1b(%%FF_REGBP, %5) + WRITEYUY2(%%FF_REGb, 8280(%5), %%FF_REGBP) + "pop %%"FF_REG_BP" \n\t" + "mov "ESP_OFFSET"(%5), %%"FF_REG_b" \n\t" :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest), "a" (&c->redDither) ); @@ -1394,43 +1394,43 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, __asm__ volatile( #if defined(PIC) - "mov %%"REG_b", %5 \n\t" + "mov %%"FF_REG_b", %5 \n\t" #if ARCH_X86_64 - "mov -8(%%rsp), %%"REG_a" \n\t" - "mov %%"REG_a", %6 \n\t" + "mov -8(%%rsp), %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", %6 \n\t" #endif #else #if ARCH_X86_64 - "mov -8(%%rsp), %%"REG_a" \n\t" - "mov %%"REG_a", %5 \n\t" + "mov -8(%%rsp), %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", %5 \n\t" #endif #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" + "pxor %%mm7, %%mm7 \n\t" + "mov %0, %%"FF_REG_c" \n\t" + "mov %1, %%"FF_REG_D" \n\t" + "mov %2, %%"FF_REG_d" \n\t" + "mov %3, %%"FF_REG_b" \n\t" + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" // i + PREFETCH" (%%"FF_REG_c") \n\t" + PREFETCH" 32(%%"FF_REG_c") \n\t" + PREFETCH" 64(%%"FF_REG_c") \n\t" #if ARCH_X86_64 #define CALL_MMXEXT_FILTER_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"\ + "movl (%%"FF_REG_b"), %%esi \n\t"\ + "call *%4 \n\t"\ + "movl (%%"FF_REG_b", %%"FF_REG_a"), %%esi \n\t"\ + "add %%"FF_REG_S", %%"FF_REG_c" \n\t"\ + "add %%"FF_REG_a", %%"FF_REG_D" \n\t"\ + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\ #else #define CALL_MMXEXT_FILTER_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"\ + "movl (%%"FF_REG_b"), %%esi \n\t"\ + "call *%4 \n\t"\ + "addl (%%"FF_REG_b", %%"FF_REG_a"), %%"FF_REG_c" \n\t"\ + "add %%"FF_REG_a", %%"FF_REG_D" \n\t"\ + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\ #endif /* ARCH_X86_64 */ @@ -1444,15 +1444,15 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, CALL_MMXEXT_FILTER_CODE #if defined(PIC) - "mov %5, %%"REG_b" \n\t" + "mov %5, %%"FF_REG_b" \n\t" #if ARCH_X86_64 - "mov %6, %%"REG_a" \n\t" - "mov %%"REG_a", -8(%%rsp) \n\t" + "mov %6, %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", -8(%%rsp) \n\t" #endif #else #if ARCH_X86_64 - "mov %5, %%"REG_a" \n\t" - "mov %%"REG_a", -8(%%rsp) \n\t" + "mov %5, %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", -8(%%rsp) \n\t" #endif #endif :: "m" (src), "m" (dst), "m" (filter), "m" (filterPos), @@ -1463,9 +1463,9 @@ static void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst, #if ARCH_X86_64 ,"m"(retsave) #endif - : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D + : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S, "%"FF_REG_D #if !defined(PIC) - ,"%"REG_b + ,"%"FF_REG_b #endif ); @@ -1490,37 +1490,37 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2, __asm__ volatile( #if defined(PIC) - "mov %%"REG_b", %7 \n\t" + "mov %%"FF_REG_b", %7 \n\t" #if ARCH_X86_64 - "mov -8(%%rsp), %%"REG_a" \n\t" - "mov %%"REG_a", %8 \n\t" + "mov -8(%%rsp), %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", %8 \n\t" #endif #else #if ARCH_X86_64 - "mov -8(%%rsp), %%"REG_a" \n\t" - "mov %%"REG_a", %7 \n\t" + "mov -8(%%rsp), %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", %7 \n\t" #endif #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" + "pxor %%mm7, %%mm7 \n\t" + "mov %0, %%"FF_REG_c" \n\t" + "mov %1, %%"FF_REG_D" \n\t" + "mov %2, %%"FF_REG_d" \n\t" + "mov %3, %%"FF_REG_b" \n\t" + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" // i + PREFETCH" (%%"FF_REG_c") \n\t" + PREFETCH" 32(%%"FF_REG_c") \n\t" + PREFETCH" 64(%%"FF_REG_c") \n\t" CALL_MMXEXT_FILTER_CODE CALL_MMXEXT_FILTER_CODE CALL_MMXEXT_FILTER_CODE CALL_MMXEXT_FILTER_CODE - "xor %%"REG_a", %%"REG_a" \n\t" // i - "mov %5, %%"REG_c" \n\t" // src - "mov %6, %%"REG_D" \n\t" // buf2 - PREFETCH" (%%"REG_c") \n\t" - PREFETCH" 32(%%"REG_c") \n\t" - PREFETCH" 64(%%"REG_c") \n\t" + "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" // i + "mov %5, %%"FF_REG_c" \n\t" // src + "mov %6, %%"FF_REG_D" \n\t" // buf2 + PREFETCH" (%%"FF_REG_c") \n\t" + PREFETCH" 32(%%"FF_REG_c") \n\t" + PREFETCH" 64(%%"FF_REG_c") \n\t" CALL_MMXEXT_FILTER_CODE CALL_MMXEXT_FILTER_CODE @@ -1528,15 +1528,15 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2, CALL_MMXEXT_FILTER_CODE #if defined(PIC) - "mov %7, %%"REG_b" \n\t" + "mov %7, %%"FF_REG_b" \n\t" #if ARCH_X86_64 - "mov %8, %%"REG_a" \n\t" - "mov %%"REG_a", -8(%%rsp) \n\t" + "mov %8, %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", -8(%%rsp) \n\t" #endif #else #if ARCH_X86_64 - "mov %7, %%"REG_a" \n\t" - "mov %%"REG_a", -8(%%rsp) \n\t" + "mov %7, %%"FF_REG_a" \n\t" + "mov %%"FF_REG_a", -8(%%rsp) \n\t" #endif #endif :: "m" (src1), "m" (dst1), "m" (filter), "m" (filterPos), @@ -1547,9 +1547,9 @@ static void RENAME(hcscale_fast)(SwsContext *c, int16_t *dst1, int16_t *dst2, #if ARCH_X86_64 ,"m"(retsave) #endif - : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D + : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S, "%"FF_REG_D #if !defined(PIC) - ,"%"REG_b + ,"%"FF_REG_b #endif ); diff --git a/libswscale/x86/yuv2rgb.c b/libswscale/x86/yuv2rgb.c index bacc87f..68d3bc2 100644 --- a/libswscale/x86/yuv2rgb.c +++ b/libswscale/x86/yuv2rgb.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "config.h" #include "libswscale/rgb2rgb.h" diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index a4f7a11..fca3242 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -35,6 +35,17 @@ #include "swscale.h" #include "swscale_internal.h" +/* Color space conversion coefficients for YCbCr -> RGB mapping. + * + * Entries are {crv, cbu, cgu, cgv} + * + * crv = (255 / 224) * 65536 * (1 - cr) / 0.5 + * cbu = (255 / 224) * 65536 * (1 - cb) / 0.5 + * cgu = (255 / 224) * 65536 * (cb / cg) * (1 - cb) / 0.5 + * cgv = (255 / 224) * 65536 * (cr / cg) * (1 - cr) / 0.5 + * + * where Y = cr * R + cg * G + cb * B and cr + cg + cb = 1. + */ const int32_t ff_yuv2rgb_coeffs[8][4] = { { 117504, 138453, 13954, 34903 }, /* no sequence_display_extension */ { 117504, 138453, 13954, 34903 }, /* ITU-R Rec. 709 (1990) */ diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..7ddaca2 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,8 @@ +/audiogen +/base64 +/data/ +/pixfmts.mak +/rotozoom +/tiny_psnr +/videogen +/vsynth1/ diff --git a/tests/Makefile b/tests/Makefile index 2f9f1c9..36a3a72 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -58,6 +58,7 @@ PARSERDEMDEC = $(call ALLYES, $(1)_PARSER $(2)_DEMUXER $(3)_DECODER) include $(SRC_PATH)/tests/fate/acodec.mak include $(SRC_PATH)/tests/fate/vcodec.mak + include $(SRC_PATH)/tests/fate/avformat.mak include $(SRC_PATH)/tests/fate/seek.mak @@ -71,16 +72,18 @@ include $(SRC_PATH)/tests/fate/amrwb.mak include $(SRC_PATH)/tests/fate/atrac.mak include $(SRC_PATH)/tests/fate/audio.mak include $(SRC_PATH)/tests/fate/bmp.mak +include $(SRC_PATH)/tests/fate/canopus.mak include $(SRC_PATH)/tests/fate/cdxl.mak +include $(SRC_PATH)/tests/fate/checkasm.mak include $(SRC_PATH)/tests/fate/cover-art.mak include $(SRC_PATH)/tests/fate/demux.mak include $(SRC_PATH)/tests/fate/dfa.mak include $(SRC_PATH)/tests/fate/dpcm.mak include $(SRC_PATH)/tests/fate/ea.mak +include $(SRC_PATH)/tests/fate/fft.mak include $(SRC_PATH)/tests/fate/filter-audio.mak include $(SRC_PATH)/tests/fate/filter-video.mak include $(SRC_PATH)/tests/fate/flac.mak -include $(SRC_PATH)/tests/fate/fft.mak include $(SRC_PATH)/tests/fate/h264.mak include $(SRC_PATH)/tests/fate/hevc.mak include $(SRC_PATH)/tests/fate/image.mak @@ -96,6 +99,7 @@ include $(SRC_PATH)/tests/fate/microsoft.mak include $(SRC_PATH)/tests/fate/monkeysaudio.mak include $(SRC_PATH)/tests/fate/mp3.mak include $(SRC_PATH)/tests/fate/mpc.mak +include $(SRC_PATH)/tests/fate/mpeg4.mak include $(SRC_PATH)/tests/fate/opus.mak include $(SRC_PATH)/tests/fate/pcm.mak include $(SRC_PATH)/tests/fate/probe.mak @@ -128,7 +132,7 @@ $(FATE_AVCONV) $(FATE_SAMPLES_AVCONV): avconv$(EXESUF) ifdef SAMPLES FATE += $(FATE_SAMPLES) fate-rsync: - rsync -vaLW rsync://fate-suite.libav.org/fate-suite-11/ $(SAMPLES) + rsync -vaLW rsync://fate-suite.libav.org/fate-suite/ $(SAMPLES) else fate-rsync: @echo "use 'make fate-rsync SAMPLES=/path/to/samples' to sync the fate suite" @@ -142,7 +146,7 @@ fate: $(FATE) $(FATE): $(FATE_UTILS:%=tests/%$(HOSTEXESUF)) @echo "TEST $(@:fate-%=%)" - $(Q)$(SRC_PATH)/tests/fate-run.sh $@ "$(SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" '$(CMD)' '$(CMP)' '$(REF)' '$(FUZZ)' '$(THREADS)' '$(THREAD_TYPE)' '$(CPUFLAGS)' '$(CMP_SHIFT)' '$(CMP_TARGET)' '$(SIZE_TOLERANCE)' '$(CMP_UNIT)' '$(GEN)' + $(Q)$(SRC_PATH)/tests/fate-run.sh $@ "$(SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" '$(CMD)' '$(CMP)' '$(REF)' '$(FUZZ)' '$(THREADS)' '$(THREAD_TYPE)' '$(CPUFLAGS)' '$(CMP_SHIFT)' '$(CMP_TARGET)' '$(SIZE_TOLERANCE)' '$(CMP_UNIT)' '$(GEN)' '$(HWACCEL)' fate-list: @printf '%s\n' $(sort $(FATE)) @@ -159,7 +163,7 @@ lcov: coverage.info lcov-reset: TAG = LCOV lcov-reset: - $(M)lcov -d $(CURDIR) --zerocounters + $(M)lcov -q -d $(CURDIR) --zerocounters $(Q)$(RM) -f coverage.info clean:: testclean @@ -172,5 +176,7 @@ testclean: -include $(wildcard tests/*.d) +include $(SRC_PATH)/tests/checkasm/Makefile + .PHONY: fate* lcov lcov-reset .INTERMEDIATE: coverage.info diff --git a/tests/checkasm/.gitignore b/tests/checkasm/.gitignore new file mode 100644 index 0000000..9ee0e5c --- /dev/null +++ b/tests/checkasm/.gitignore @@ -0,0 +1 @@ +/checkasm diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile new file mode 100644 index 0000000..8d3d03a --- /dev/null +++ b/tests/checkasm/Makefile @@ -0,0 +1,42 @@ +# libavcodec tests +# subsystems +AVCODECOBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o +AVCODECOBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o +AVCODECOBJS-$(CONFIG_H264DSP) += h264dsp.o +AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o +AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o +AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o + +# decoders/encoders +AVCODECOBJS-$(CONFIG_DCA_DECODER) += dcadsp.o synth_filter.o +AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_mc.o hevc_idct.o +AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o +AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o + +CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) + + +-include $(SRC_PATH)/tests/checkasm/$(ARCH)/Makefile + +CHECKASMOBJS += $(CHECKASMOBJS-yes) checkasm.o +CHECKASMOBJS := $(sort $(CHECKASMOBJS:%=tests/checkasm/%)) + +-include $(CHECKASMOBJS:.o=.d) + +CHECKASMDIRS := $(sort $(dir $(CHECKASMOBJS))) +$(CHECKASMOBJS): | $(CHECKASMDIRS) +OBJDIRS += $(CHECKASMDIRS) + +CHECKASM := tests/checkasm/checkasm$(EXESUF) + +$(CHECKASM): $(EXEOBJS) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS) + +checkasm: $(CHECKASM) + +clean:: checkasmclean + +checkasmclean: + $(RM) $(CHECKASM) $(CLEANSUFFIXES:%=tests/checkasm/%) $(CLEANSUFFIXES:%=tests/checkasm/$(ARCH)/%) + +.PHONY: checkasm diff --git a/tests/checkasm/aarch64/Makefile b/tests/checkasm/aarch64/Makefile new file mode 100644 index 0000000..02ba6ca --- /dev/null +++ b/tests/checkasm/aarch64/Makefile @@ -0,0 +1 @@ +CHECKASMOBJS += aarch64/checkasm.o diff --git a/tests/checkasm/aarch64/checkasm.S b/tests/checkasm/aarch64/checkasm.S new file mode 100644 index 0000000..9668518 --- /dev/null +++ b/tests/checkasm/aarch64/checkasm.S @@ -0,0 +1,148 @@ +/**************************************************************************** + * Assembly testing and benchmarking tool + * Copyright (c) 2015 Martin Storsjo + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 02111, USA. + *****************************************************************************/ + +#include "libavutil/aarch64/asm.S" + +const register_init + .quad 0x21f86d66c8ca00ce + .quad 0x75b6ba21077c48ad + .quad 0xed56bb2dcb3c7736 + .quad 0x8bda43d3fd1a7e06 + .quad 0xb64a9c9e5d318408 + .quad 0xdf9a54b303f1d3a3 + .quad 0x4a75479abd64e097 + .quad 0x249214109d5d1c88 + .quad 0x1a1b2550a612b48c + .quad 0x79445c159ce79064 + .quad 0x2eed899d5a28ddcd + .quad 0x86b2536fcd8cf636 + .quad 0xb0856806085e7943 + .quad 0x3f2bf84fc0fcca4e + .quad 0xacbd382dcf5b8de2 + .quad 0xd229e1f5b281303f + .quad 0x71aeaff20b095fd9 + .quad 0xab63e2e11fa38ed9 +endconst + + +const error_message + .asciz "failed to preserve register" +endconst + + +// max number of args used by any asm function. +#define MAX_ARGS 15 + +#define ARG_STACK ((8*(MAX_ARGS - 7) + 15) & ~15) + +function checkasm_checked_call, export=1 + stp x29, x30, [sp, #-16]! + mov x29, sp + stp x19, x20, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp d8, d9, [sp, #-16]! + stp d10, d11, [sp, #-16]! + stp d12, d13, [sp, #-16]! + stp d14, d15, [sp, #-16]! + + movrel x9, register_init + ldp d8, d9, [x9], #16 + ldp d10, d11, [x9], #16 + ldp d12, d13, [x9], #16 + ldp d14, d15, [x9], #16 + ldp x19, x20, [x9], #16 + ldp x21, x22, [x9], #16 + ldp x23, x24, [x9], #16 + ldp x25, x26, [x9], #16 + ldp x27, x28, [x9], #16 + + sub sp, sp, #ARG_STACK +.equ pos, 0 +// the first stacked arg is copied to x7 +.rept MAX_ARGS-7 + ldr x9, [x29, #16 + 8 + pos] + str x9, [sp, #pos] +.equ pos, pos + 8 +.endr + + mov x12, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + mov x6, x7 + ldr x7, [x29, #16] + blr x12 + add sp, sp, #ARG_STACK + stp x0, x1, [sp, #-16]! + movrel x9, register_init + movi v3.8h, #0 + +.macro check_reg_neon reg1, reg2 + ldr q0, [x9], #16 + uzp1 v1.2d, v\reg1\().2d, v\reg2\().2d + eor v0.16b, v0.16b, v1.16b + orr v3.16b, v3.16b, v0.16b +.endm + check_reg_neon 8, 9 + check_reg_neon 10, 11 + check_reg_neon 12, 13 + check_reg_neon 14, 15 + uqxtn v3.8b, v3.8h + umov x3, v3.d[0] + +.macro check_reg reg1, reg2 + ldp x0, x1, [x9], #16 + eor x0, x0, \reg1 + eor x1, x1, \reg2 + orr x3, x3, x0 + orr x3, x3, x1 +.endm + check_reg x19, x20 + check_reg x21, x22 + check_reg x23, x24 + check_reg x25, x26 + check_reg x27, x28 + + cbz x3, 0f + + movrel x0, error_message + bl X(checkasm_fail_func) +0: + ldp x0, x1, [sp], #16 + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x19, x20, [sp], #16 + ldp x29, x30, [sp], #16 + ret +endfunc diff --git a/tests/checkasm/arm/Makefile b/tests/checkasm/arm/Makefile new file mode 100644 index 0000000..55f2383 --- /dev/null +++ b/tests/checkasm/arm/Makefile @@ -0,0 +1 @@ +CHECKASMOBJS-$(HAVE_ARMV5TE_EXTERNAL) += arm/checkasm.o diff --git a/tests/checkasm/arm/checkasm.S b/tests/checkasm/arm/checkasm.S new file mode 100644 index 0000000..098f22e --- /dev/null +++ b/tests/checkasm/arm/checkasm.S @@ -0,0 +1,168 @@ +/**************************************************************************** + * Assembly testing and benchmarking tool + * Copyright (c) 2015 Martin Storsjo + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 02111, USA. + *****************************************************************************/ + +#include "libavutil/arm/asm.S" + +/* override fpu so that NEON instructions are rejected */ +#if HAVE_VFP +FPU .fpu vfp +ELF .eabi_attribute 10, 0 @ suppress Tag_FP_arch +#endif + +const register_init, align=3 + .quad 0x21f86d66c8ca00ce + .quad 0x75b6ba21077c48ad + .quad 0xed56bb2dcb3c7736 + .quad 0x8bda43d3fd1a7e06 + .quad 0xb64a9c9e5d318408 + .quad 0xdf9a54b303f1d3a3 + .quad 0x4a75479abd64e097 + .quad 0x249214109d5d1c88 +endconst + +const error_message_fpscr + .asciz "failed to preserve register FPSCR, changed bits: %x" +error_message_gpr: + .asciz "failed to preserve register r%d" +error_message_vfp: + .asciz "failed to preserve register d%d" +endconst + +@ max number of args used by any asm function. +#define MAX_ARGS 15 + +#define ARG_STACK 4*(MAX_ARGS - 2) + +@ align the used stack space to 8 to preserve the stack alignment +#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed) + +.macro clobbercheck variant +.equ pushed, 4*9 +function checkasm_checked_call_\variant, export=1 + push {r4-r11, lr} +.ifc \variant, vfp + vpush {d8-d15} + fmrx r4, FPSCR + push {r4} +.equ pushed, pushed + 16*4 + 4 +.endif + + movrel r12, register_init +.ifc \variant, vfp + vldm r12, {d8-d15} +.endif + ldm r12, {r4-r11} + + sub sp, sp, #ARG_STACK_A +.equ pos, 0 +.rept MAX_ARGS-2 + ldr r12, [sp, #ARG_STACK_A + pushed + 8 + pos] + str r12, [sp, #pos] +.equ pos, pos + 4 +.endr + + mov r12, r0 + mov r0, r2 + mov r1, r3 + ldrd r2, r3, [sp, #ARG_STACK_A + pushed] + blx r12 + add sp, sp, #ARG_STACK_A + + push {r0, r1} + movrel r12, register_init +.ifc \variant, vfp +.macro check_reg_vfp, dreg, offset + ldrd r2, r3, [r12, #8 * (\offset)] + vmov r0, lr, \dreg + eor r2, r2, r0 + eor r3, r3, lr + orrs r2, r2, r3 + bne 4f +.endm + +.irp n, 8, 9, 10, 11, 12, 13, 14, 15 + @ keep track of the checked double/SIMD register + mov r1, #\n + check_reg_vfp d\n, \n-8 +.endr +.purgem check_reg_vfp + + fmrx r1, FPSCR + ldr r3, [sp, #8] + eor r1, r1, r3 + @ Ignore changes in bits 0-4 and 7 + bic r1, r1, #0x9f + @ Ignore changes in the topmost 5 bits + bics r1, r1, #0xf8000000 + bne 3f +.endif + + @ keep track of the checked GPR + mov r1, #4 +.macro check_reg reg1, reg2= + ldrd r2, r3, [r12], #8 + eors r2, r2, \reg1 + bne 2f + add r1, r1, #1 +.ifnb \reg2 + eors r3, r3, \reg2 + bne 2f +.endif + add r1, r1, #1 +.endm + check_reg r4, r5 + check_reg r6, r7 +@ r9 is a volatile register in the ios ABI +#ifdef __APPLE__ + check_reg r8 +#else + check_reg r8, r9 +#endif + check_reg r10, r11 +.purgem check_reg + + b 0f +4: + movrel r0, error_message_vfp + b 1f +3: + movrel r0, error_message_fpscr + b 1f +2: + movrel r0, error_message_gpr +1: + blx X(checkasm_fail_func) +0: + pop {r0, r1} +.ifc \variant, vfp + pop {r2} + fmxr FPSCR, r2 + vpop {d8-d15} +.endif + pop {r4-r11, pc} +endfunc +.endm + +#if HAVE_VFP || HAVE_NEON +clobbercheck vfp +#endif +clobbercheck novfp diff --git a/tests/checkasm/bswapdsp.c b/tests/checkasm/bswapdsp.c new file mode 100644 index 0000000..829ebaa --- /dev/null +++ b/tests/checkasm/bswapdsp.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 Henrik Gramner + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/bswapdsp.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +#define BUF_SIZE 512 + +#define randomize_buffers() \ + do { \ + int i; \ + for (i = 0; i < BUF_SIZE; i += 4) { \ + uint32_t r = rnd(); \ + AV_WN32A(src0 + i, r); \ + AV_WN32A(src1 + i, r); \ + r = rnd(); \ + AV_WN32A(dst0 + i, r); \ + AV_WN32A(dst1 + i, r); \ + } \ + } while (0) + +#define check_bswap(type) \ + do { \ + int w; \ + declare_func(void, type *dst, const type *src, int w); \ + \ + for (w = 0; w < BUF_SIZE / sizeof(type); w++) { \ + int offset = (BUF_SIZE / sizeof(type) - w) & 15; /* Test various alignments */ \ + randomize_buffers(); \ + call_ref((type *)dst0 + offset, (type *)src0 + offset, w); \ + call_new((type *)dst1 + offset, (type *)src1 + offset, w); \ + if (memcmp(src0, src1, BUF_SIZE) || memcmp(dst0, dst1, BUF_SIZE)) \ + fail(); \ + bench_new((type *)dst1 + offset, (type *)src1 + offset, w); \ + } \ + } while (0) + +void checkasm_check_bswapdsp(void) +{ + LOCAL_ALIGNED_16(uint8_t, src0, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, src1, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dst1, [BUF_SIZE]); + BswapDSPContext h; + + ff_bswapdsp_init(&h); + + if (check_func(h.bswap_buf, "bswap_buf")) + check_bswap(uint32_t); + + if (check_func(h.bswap16_buf, "bswap16_buf")) + check_bswap(uint16_t); + + report("bswap"); +} diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c new file mode 100644 index 0000000..86d3bab --- /dev/null +++ b/tests/checkasm/checkasm.c @@ -0,0 +1,650 @@ +/* + * Assembly testing and benchmarking tool + * Copyright (c) 2015 Henrik Gramner + * Copyright (c) 2008 Loren Merritt + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include "checkasm.h" +#include "libavutil/common.h" +#include "libavutil/cpu.h" +#include "libavutil/intfloat.h" +#include "libavutil/random_seed.h" + +#if HAVE_IO_H +#include +#endif + +#if HAVE_SETCONSOLETEXTATTRIBUTE +#include +#define COLOR_RED FOREGROUND_RED +#define COLOR_GREEN FOREGROUND_GREEN +#define COLOR_YELLOW (FOREGROUND_RED|FOREGROUND_GREEN) +#else +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#endif + +#if HAVE_UNISTD_H +#include +#endif + +#if !HAVE_ISATTY +#define isatty(fd) 1 +#endif + +#if ARCH_ARM && HAVE_ARMV5TE_EXTERNAL +#include "libavutil/arm/cpu.h" + +void (*checkasm_checked_call)(void *func, int dummy, ...) = checkasm_checked_call_novfp; +#endif + +/* List of tests to invoke */ +static const struct { + const char *name; + void (*func)(void); +} tests[] = { +#if CONFIG_BSWAPDSP + { "bswapdsp", checkasm_check_bswapdsp }, +#endif +#if CONFIG_DCA_DECODER + { "dcadsp", checkasm_check_dcadsp }, + { "synth_filter", checkasm_check_synth_filter }, +#endif +#if CONFIG_FMTCONVERT + { "fmtconvert", checkasm_check_fmtconvert }, +#endif +#if CONFIG_H264DSP + { "h264dsp", checkasm_check_h264dsp }, +#endif +#if CONFIG_H264PRED + { "h264pred", checkasm_check_h264pred }, +#endif +#if CONFIG_H264QPEL + { "h264qpel", checkasm_check_h264qpel }, +#endif +#if CONFIG_HEVC_DECODER + { "hevc_mc", checkasm_check_hevc_mc }, + { "hevc_idct", checkasm_check_hevc_idct }, +#endif +#if CONFIG_V210_ENCODER + { "v210enc", checkasm_check_v210enc }, +#endif +#if CONFIG_VP8DSP + { "vp8dsp", checkasm_check_vp8dsp }, +#endif +#if CONFIG_VP9_DECODER + { "vp9dsp", checkasm_check_vp9dsp }, +#endif + { NULL } +}; + +/* List of cpu flags to check */ +static const struct { + const char *name; + const char *suffix; + int flag; +} cpus[] = { +#if ARCH_AARCH64 + { "ARMV8", "armv8", AV_CPU_FLAG_ARMV8 }, + { "NEON", "neon", AV_CPU_FLAG_NEON }, +#elif ARCH_ARM + { "ARMV5TE", "armv5te", AV_CPU_FLAG_ARMV5TE }, + { "ARMV6", "armv6", AV_CPU_FLAG_ARMV6 }, + { "ARMV6T2", "armv6t2", AV_CPU_FLAG_ARMV6T2 }, + { "VFP", "vfp", AV_CPU_FLAG_VFP }, + { "VFP_VM", "vfp_vm", AV_CPU_FLAG_VFP_VM }, + { "VFPV3", "vfp3", AV_CPU_FLAG_VFPV3 }, + { "NEON", "neon", AV_CPU_FLAG_NEON }, +#elif ARCH_PPC + { "ALTIVEC", "altivec", AV_CPU_FLAG_ALTIVEC }, + { "VSX", "vsx", AV_CPU_FLAG_VSX }, + { "POWER8", "power8", AV_CPU_FLAG_POWER8 }, +#elif ARCH_X86 + { "MMX", "mmx", AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV }, + { "MMXEXT", "mmxext", AV_CPU_FLAG_MMXEXT }, + { "3DNOW", "3dnow", AV_CPU_FLAG_3DNOW }, + { "3DNOWEXT", "3dnowext", AV_CPU_FLAG_3DNOWEXT }, + { "SSE", "sse", AV_CPU_FLAG_SSE }, + { "SSE2", "sse2", AV_CPU_FLAG_SSE2|AV_CPU_FLAG_SSE2SLOW }, + { "SSE3", "sse3", AV_CPU_FLAG_SSE3|AV_CPU_FLAG_SSE3SLOW }, + { "SSSE3", "ssse3", AV_CPU_FLAG_SSSE3|AV_CPU_FLAG_ATOM }, + { "SSE4.1", "sse4", AV_CPU_FLAG_SSE4 }, + { "SSE4.2", "sse42", AV_CPU_FLAG_SSE42 }, + { "AVX", "avx", AV_CPU_FLAG_AVX }, + { "XOP", "xop", AV_CPU_FLAG_XOP }, + { "FMA3", "fma3", AV_CPU_FLAG_FMA3 }, + { "FMA4", "fma4", AV_CPU_FLAG_FMA4 }, + { "AVX2", "avx2", AV_CPU_FLAG_AVX2 }, +#endif + { NULL } +}; + +typedef struct CheckasmFuncVersion { + struct CheckasmFuncVersion *next; + void *func; + int ok; + int cpu; + int iterations; + uint64_t cycles; +} CheckasmFuncVersion; + +/* Binary search tree node */ +typedef struct CheckasmFunc { + struct CheckasmFunc *child[2]; + CheckasmFuncVersion versions; + uint8_t color; /* 0 = red, 1 = black */ + char name[1]; +} CheckasmFunc; + +/* Internal state */ +static struct { + CheckasmFunc *funcs; + CheckasmFunc *current_func; + CheckasmFuncVersion *current_func_ver; + const char *current_test_name; + const char *bench_pattern; + int bench_pattern_len; + int num_checked; + int num_failed; + int nop_time; + int cpu_flag; + const char *cpu_flag_name; +} state; + +/* PRNG state */ +AVLFG checkasm_lfg; + +/* float compare support code */ +static int is_negative(union av_intfloat32 u) +{ + return u.i >> 31; +} + +int float_near_ulp(float a, float b, unsigned max_ulp) +{ + union av_intfloat32 x, y; + + x.f = a; + y.f = b; + + if (is_negative(x) != is_negative(y)) { + // handle -0.0 == +0.0 + return a == b; + } + + if (llabs((int64_t)x.i - y.i) <= max_ulp) + return 1; + + return 0; +} + +int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, + unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_ulp(a[i], b[i], max_ulp)) + return 0; + } + return 1; +} + +int float_near_abs_eps(float a, float b, float eps) +{ + float abs_diff = fabsf(a - b); + + return abs_diff < eps; +} + +int float_near_abs_eps_array(const float *a, const float *b, float eps, + unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_abs_eps(a[i], b[i], eps)) + return 0; + } + return 1; +} + +int float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp) +{ + return float_near_ulp(a, b, max_ulp) || float_near_abs_eps(a, b, eps); +} + +int float_near_abs_eps_array_ulp(const float *a, const float *b, float eps, + unsigned max_ulp, unsigned len) +{ + unsigned i; + + for (i = 0; i < len; i++) { + if (!float_near_abs_eps_ulp(a[i], b[i], eps, max_ulp)) + return 0; + } + return 1; +} + +/* Print colored text to stderr if the terminal supports it */ +static void color_printf(int color, const char *fmt, ...) +{ + static int use_color = -1; + va_list arg; + +#if HAVE_SETCONSOLETEXTATTRIBUTE + static HANDLE con; + static WORD org_attributes; + + if (use_color < 0) { + CONSOLE_SCREEN_BUFFER_INFO con_info; + con = GetStdHandle(STD_ERROR_HANDLE); + if (con && con != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(con, &con_info)) { + org_attributes = con_info.wAttributes; + use_color = 1; + } else + use_color = 0; + } + if (use_color) + SetConsoleTextAttribute(con, (org_attributes & 0xfff0) | (color & 0x0f)); +#else + if (use_color < 0) { + const char *term = getenv("TERM"); + use_color = term && strcmp(term, "dumb") && isatty(2); + } + if (use_color) + fprintf(stderr, "\x1b[%d;3%dm", (color & 0x08) >> 3, color & 0x07); +#endif + + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + + if (use_color) { +#if HAVE_SETCONSOLETEXTATTRIBUTE + SetConsoleTextAttribute(con, org_attributes); +#else + fprintf(stderr, "\x1b[0m"); +#endif + } +} + +/* Deallocate a tree */ +static void destroy_func_tree(CheckasmFunc *f) +{ + if (f) { + CheckasmFuncVersion *v = f->versions.next; + while (v) { + CheckasmFuncVersion *next = v->next; + free(v); + v = next; + } + + destroy_func_tree(f->child[0]); + destroy_func_tree(f->child[1]); + free(f); + } +} + +/* Allocate a zero-initialized block, clean up and exit on failure */ +static void *checkasm_malloc(size_t size) +{ + void *ptr = calloc(1, size); + if (!ptr) { + fprintf(stderr, "checkasm: malloc failed\n"); + destroy_func_tree(state.funcs); + exit(1); + } + return ptr; +} + +/* Get the suffix of the specified cpu flag */ +static const char *cpu_suffix(int cpu) +{ + int i = FF_ARRAY_ELEMS(cpus); + + while (--i >= 0) + if (cpu & cpus[i].flag) + return cpus[i].suffix; + + return "c"; +} + +#ifdef AV_READ_TIME +static int cmp_nop(const void *a, const void *b) +{ + return *(const uint16_t*)a - *(const uint16_t*)b; +} + +/* Measure the overhead of the timing code (in decicycles) */ +static int measure_nop_time(void) +{ + uint16_t nops[10000]; + int i, nop_sum = 0; + + for (i = 0; i < 10000; i++) { + uint64_t t = AV_READ_TIME(); + nops[i] = AV_READ_TIME() - t; + } + + qsort(nops, 10000, sizeof(uint16_t), cmp_nop); + for (i = 2500; i < 7500; i++) + nop_sum += nops[i]; + + return nop_sum / 500; +} + +/* Print benchmark results */ +static void print_benchs(CheckasmFunc *f) +{ + if (f) { + print_benchs(f->child[0]); + + /* Only print functions with at least one assembly version */ + if (f->versions.cpu || f->versions.next) { + CheckasmFuncVersion *v = &f->versions; + do { + if (v->iterations) { + int decicycles = (10*v->cycles/v->iterations - state.nop_time) / 4; + printf("%s_%s: %d.%d\n", f->name, cpu_suffix(v->cpu), decicycles/10, decicycles%10); + } + } while ((v = v->next)); + } + + print_benchs(f->child[1]); + } +} +#endif + +/* ASCIIbetical sort except preserving natural order for numbers */ +static int cmp_func_names(const char *a, const char *b) +{ + const char *start = a; + int ascii_diff, digit_diff; + + for (; !(ascii_diff = *(const unsigned char*)a - *(const unsigned char*)b) && *a; a++, b++); + for (; av_isdigit(*a) && av_isdigit(*b); a++, b++); + + if (a > start && av_isdigit(a[-1]) && (digit_diff = av_isdigit(*a) - av_isdigit(*b))) + return digit_diff; + + return ascii_diff; +} + +/* Perform a tree rotation in the specified direction and return the new root */ +static CheckasmFunc *rotate_tree(CheckasmFunc *f, int dir) +{ + CheckasmFunc *r = f->child[dir^1]; + f->child[dir^1] = r->child[dir]; + r->child[dir] = f; + r->color = f->color; + f->color = 0; + return r; +} + +#define is_red(f) ((f) && !(f)->color) + +/* Balance a left-leaning red-black tree at the specified node */ +static void balance_tree(CheckasmFunc **root) +{ + CheckasmFunc *f = *root; + + if (is_red(f->child[0]) && is_red(f->child[1])) { + f->color ^= 1; + f->child[0]->color = f->child[1]->color = 1; + } + + if (!is_red(f->child[0]) && is_red(f->child[1])) + *root = rotate_tree(f, 0); /* Rotate left */ + else if (is_red(f->child[0]) && is_red(f->child[0]->child[0])) + *root = rotate_tree(f, 1); /* Rotate right */ +} + +/* Get a node with the specified name, creating it if it doesn't exist */ +static CheckasmFunc *get_func(CheckasmFunc **root, const char *name) +{ + CheckasmFunc *f = *root; + + if (f) { + /* Search the tree for a matching node */ + int cmp = cmp_func_names(name, f->name); + if (cmp) { + f = get_func(&f->child[cmp > 0], name); + + /* Rebalance the tree on the way up if a new node was inserted */ + if (!f->versions.func) + balance_tree(root); + } + } else { + /* Allocate and insert a new node into the tree */ + int name_length = strlen(name); + f = *root = checkasm_malloc(sizeof(CheckasmFunc) + name_length); + memcpy(f->name, name, name_length + 1); + } + + return f; +} + +/* Perform tests and benchmarks for the specified cpu flag if supported by the host */ +static void check_cpu_flag(const char *name, int flag) +{ + int old_cpu_flag = state.cpu_flag; + + flag |= old_cpu_flag; + av_set_cpu_flags_mask(flag); + state.cpu_flag = av_get_cpu_flags(); + + if (!flag || state.cpu_flag != old_cpu_flag) { + int i; + + state.cpu_flag_name = name; + for (i = 0; tests[i].func; i++) { + state.current_test_name = tests[i].name; + tests[i].func(); + } + } +} + +/* Print the name of the current CPU flag, but only do it once */ +static void print_cpu_name(void) +{ + if (state.cpu_flag_name) { + color_printf(COLOR_YELLOW, "%s:\n", state.cpu_flag_name); + state.cpu_flag_name = NULL; + } +} + +int main(int argc, char *argv[]) +{ + int i, seed, ret = 0; + +#if ARCH_ARM && HAVE_ARMV5TE_EXTERNAL + if (have_vfp(av_get_cpu_flags()) || have_neon(av_get_cpu_flags())) + checkasm_checked_call = checkasm_checked_call_vfp; +#endif + + if (!tests[0].func || !cpus[0].flag) { + fprintf(stderr, "checkasm: no tests to perform\n"); + return 0; + } + + if (argc > 1 && !strncmp(argv[1], "--bench", 7)) { +#ifndef AV_READ_TIME + fprintf(stderr, "checkasm: --bench is not supported on your system\n"); + return 1; +#endif + if (argv[1][7] == '=') { + state.bench_pattern = argv[1] + 8; + state.bench_pattern_len = strlen(state.bench_pattern); + } else + state.bench_pattern = ""; + + argc--; + argv++; + } + + seed = (argc > 1) ? atoi(argv[1]) : av_get_random_seed(); + fprintf(stderr, "checkasm: using random seed %u\n", seed); + av_lfg_init(&checkasm_lfg, seed); + + check_cpu_flag(NULL, 0); + for (i = 0; cpus[i].flag; i++) + check_cpu_flag(cpus[i].name, cpus[i].flag); + + if (state.num_failed) { + fprintf(stderr, "checkasm: %d of %d tests have failed\n", state.num_failed, state.num_checked); + ret = 1; + } else { + fprintf(stderr, "checkasm: all %d tests passed\n", state.num_checked); +#ifdef AV_READ_TIME + if (state.bench_pattern) { + state.nop_time = measure_nop_time(); + printf("nop: %d.%d\n", state.nop_time/10, state.nop_time%10); + print_benchs(state.funcs); + } +#endif + } + + destroy_func_tree(state.funcs); + return ret; +} + +/* Decide whether or not the specified function needs to be tested and + * allocate/initialize data structures if needed. Returns a pointer to a + * reference function if the function should be tested, otherwise NULL */ +void *checkasm_check_func(void *func, const char *name, ...) +{ + char name_buf[256]; + void *ref = func; + CheckasmFuncVersion *v; + int name_length; + va_list arg; + + va_start(arg, name); + name_length = vsnprintf(name_buf, sizeof(name_buf), name, arg); + va_end(arg); + + if (!func || name_length <= 0 || name_length >= sizeof(name_buf)) + return NULL; + + state.current_func = get_func(&state.funcs, name_buf); + state.funcs->color = 1; + v = &state.current_func->versions; + + if (v->func) { + CheckasmFuncVersion *prev; + do { + /* Only test functions that haven't already been tested */ + if (v->func == func) + return NULL; + + if (v->ok) + ref = v->func; + + prev = v; + } while ((v = v->next)); + + v = prev->next = checkasm_malloc(sizeof(CheckasmFuncVersion)); + } + + v->func = func; + v->ok = 1; + v->cpu = state.cpu_flag; + state.current_func_ver = v; + + if (state.cpu_flag) + state.num_checked++; + + return ref; +} + +/* Decide whether or not the current function needs to be benchmarked */ +int checkasm_bench_func(void) +{ + return !state.num_failed && state.bench_pattern && + !strncmp(state.current_func->name, state.bench_pattern, state.bench_pattern_len); +} + +/* Indicate that the current test has failed */ +void checkasm_fail_func(const char *msg, ...) +{ + if (state.current_func_ver->cpu && state.current_func_ver->ok) { + va_list arg; + + print_cpu_name(); + fprintf(stderr, " %s_%s (", state.current_func->name, cpu_suffix(state.current_func_ver->cpu)); + va_start(arg, msg); + vfprintf(stderr, msg, arg); + va_end(arg); + fprintf(stderr, ")\n"); + + state.current_func_ver->ok = 0; + state.num_failed++; + } +} + +/* Update benchmark results of the current function */ +void checkasm_update_bench(int iterations, uint64_t cycles) +{ + state.current_func_ver->iterations += iterations; + state.current_func_ver->cycles += cycles; +} + +/* Print the outcome of all tests performed since the last time this function was called */ +void checkasm_report(const char *name, ...) +{ + static int prev_checked, prev_failed, max_length; + + if (state.num_checked > prev_checked) { + int pad_length = max_length + 4; + va_list arg; + + print_cpu_name(); + pad_length -= fprintf(stderr, " - %s.", state.current_test_name); + va_start(arg, name); + pad_length -= vfprintf(stderr, name, arg); + va_end(arg); + fprintf(stderr, "%*c", FFMAX(pad_length, 0) + 2, '['); + + if (state.num_failed == prev_failed) + color_printf(COLOR_GREEN, "OK"); + else + color_printf(COLOR_RED, "FAILED"); + fprintf(stderr, "]\n"); + + prev_checked = state.num_checked; + prev_failed = state.num_failed; + } else if (!state.cpu_flag) { + /* Calculate the amount of padding required to make the output vertically aligned */ + int length = strlen(state.current_test_name); + va_list arg; + + va_start(arg, name); + length += vsnprintf(NULL, 0, name, arg); + va_end(arg); + + if (length > max_length) + max_length = length; + } +} diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h new file mode 100644 index 0000000..5e67b7d --- /dev/null +++ b/tests/checkasm/checkasm.h @@ -0,0 +1,176 @@ +/* + * Assembly testing and benchmarking tool + * Copyright (c) 2015 Henrik Gramner + * Copyright (c) 2008 Loren Merritt + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TESTS_CHECKASM_CHECKASM_H +#define TESTS_CHECKASM_CHECKASM_H + +#include +#include "config.h" +#include "libavutil/avstring.h" +#include "libavutil/cpu.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/timer.h" + +void checkasm_check_bswapdsp(void); +void checkasm_check_dcadsp(void); +void checkasm_check_fmtconvert(void); +void checkasm_check_h264dsp(void); +void checkasm_check_h264pred(void); +void checkasm_check_h264qpel(void); +void checkasm_check_hevc_idct(void); +void checkasm_check_hevc_mc(void); +void checkasm_check_synth_filter(void); +void checkasm_check_v210enc(void); +void checkasm_check_vp8dsp(void); +void checkasm_check_vp9dsp(void); + +void *checkasm_check_func(void *func, const char *name, ...) av_printf_format(2, 3); +int checkasm_bench_func(void); +void checkasm_fail_func(const char *msg, ...) av_printf_format(1, 2); +void checkasm_update_bench(int iterations, uint64_t cycles); +void checkasm_report(const char *name, ...) av_printf_format(1, 2); + +/* float compare utilities */ +int float_near_ulp(float a, float b, unsigned max_ulp); +int float_near_abs_eps(float a, float b, float eps); +int float_near_abs_eps_ulp(float a, float b, float eps, unsigned max_ulp); +int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, + unsigned len); +int float_near_abs_eps_array(const float *a, const float *b, float eps, + unsigned len); +int float_near_abs_eps_array_ulp(const float *a, const float *b, float eps, + unsigned max_ulp, unsigned len); + +extern AVLFG checkasm_lfg; +#define rnd() av_lfg_get(&checkasm_lfg) + +static av_unused void *func_ref, *func_new; + +#define BENCH_RUNS 1000 /* Trade-off between accuracy and speed */ + +/* Decide whether or not the specified function needs to be tested */ +#define check_func(func, ...) (func_ref = checkasm_check_func((func_new = func), __VA_ARGS__)) + +/* Declare the function prototype. The first argument is the return value, the remaining + * arguments are the function parameters. Naming parameters is optional. */ +#define declare_func(ret, ...) declare_new(ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__) +#define declare_func_emms(cpu_flags, ret, ...) declare_new_emms(cpu_flags, ret, __VA_ARGS__) typedef ret func_type(__VA_ARGS__) + +/* Indicate that the current test has failed */ +#define fail() checkasm_fail_func("%s:%d", av_basename(__FILE__), __LINE__) + +/* Print the test outcome */ +#define report checkasm_report + +/* Call the reference function */ +#define call_ref(...) ((func_type *)func_ref)(__VA_ARGS__) + +#if ARCH_X86 && HAVE_YASM +/* Verifies that clobbered callee-saved registers are properly saved and restored + * and that either no MMX registers are touched or emms is issued */ +void checkasm_checked_call(void *func, ...); +/* Verifies that clobbered callee-saved registers are properly saved and restored + * and issues emms for asm functions which are not required to do so */ +void checkasm_checked_call_emms(void *func, ...); + +#if ARCH_X86_64 +/* Evil hack: detect incorrect assumptions that 32-bit ints are zero-extended to 64-bit. + * This is done by clobbering the stack with junk around the stack pointer and calling the + * assembly function through checked_call() with added dummy arguments which forces all + * real arguments to be passed on the stack and not in registers. For 32-bit arguments the + * upper half of the 64-bit register locations on the stack will now contain junk which will + * cause misbehaving functions to either produce incorrect output or segfault. Note that + * even though this works extremely well in practice, it's technically not guaranteed + * and false negatives is theoretically possible, but there can never be any false positives. + */ +void checkasm_stack_clobber(uint64_t clobber, ...); +#define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__)\ + = (void *)checkasm_checked_call; +#define declare_new_emms(cpu_flags, ret, ...) \ + ret (*checked_call)(void *, int, int, int, int, int, __VA_ARGS__) = \ + ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \ + (void *)checkasm_checked_call; +#define CLOB (UINT64_C(0xdeadbeefdeadbeef)) +#define call_new(...) (checkasm_stack_clobber(CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,\ + CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB),\ + checked_call(func_new, 0, 0, 0, 0, 0, __VA_ARGS__)) +#elif ARCH_X86_32 +#define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call; +#define declare_new_emms(cpu_flags, ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = \ + ((cpu_flags) & av_get_cpu_flags()) ? (void *)checkasm_checked_call_emms : \ + (void *)checkasm_checked_call; +#define call_new(...) checked_call(func_new, __VA_ARGS__) +#endif +#elif ARCH_ARM && HAVE_ARMV5TE_EXTERNAL +/* Use a dummy argument, to offset the real parameters by 2, not only 1. + * This makes sure that potential 8-byte-alignment of parameters is kept the same + * even when the extra parameters have been removed. */ +void checkasm_checked_call_vfp(void *func, int dummy, ...); +void checkasm_checked_call_novfp(void *func, int dummy, ...); +extern void (*checkasm_checked_call)(void *func, int dummy, ...); +#define declare_new(ret, ...) ret (*checked_call)(void *, int dummy, __VA_ARGS__) = (void *)checkasm_checked_call; +#define call_new(...) checked_call(func_new, 0, __VA_ARGS__) +#elif ARCH_AARCH64 && !defined(__APPLE__) +void checkasm_checked_call(void *func, ...); +#define declare_new(ret, ...) ret (*checked_call)(void *, __VA_ARGS__) = (void *)checkasm_checked_call; +#define call_new(...) checked_call(func_new, __VA_ARGS__) +#else +#define declare_new(ret, ...) +#define declare_new_emms(cpu_flags, ret, ...) +/* Call the function */ +#define call_new(...) ((func_type *)func_new)(__VA_ARGS__) +#endif + +#ifndef declare_new_emms +#define declare_new_emms(cpu_flags, ret, ...) declare_new(ret, __VA_ARGS__) +#endif + +/* Benchmark the function */ +#ifdef AV_READ_TIME +#define bench_new(...)\ + do {\ + if (checkasm_bench_func()) {\ + func_type *tfunc = func_new;\ + uint64_t tsum = 0;\ + int ti, tcount = 0;\ + for (ti = 0; ti < BENCH_RUNS; ti++) {\ + uint64_t t = AV_READ_TIME();\ + tfunc(__VA_ARGS__);\ + tfunc(__VA_ARGS__);\ + tfunc(__VA_ARGS__);\ + tfunc(__VA_ARGS__);\ + t = AV_READ_TIME() - t;\ + if (t*tcount <= tsum*4 && ti > 0) {\ + tsum += t;\ + tcount++;\ + }\ + }\ + emms_c();\ + checkasm_update_bench(tcount, tsum);\ + }\ + } while (0) +#else +#define bench_new(...) while(0) +#endif + +#endif /* TESTS_CHECKASM_CHECKASM_H */ diff --git a/tests/checkasm/dcadsp.c b/tests/checkasm/dcadsp.c new file mode 100644 index 0000000..7251362 --- /dev/null +++ b/tests/checkasm/dcadsp.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intfloat.h" +#include "libavcodec/dca.h" +#include "libavcodec/dcadsp.h" +#include "libavcodec/dcadata.h" + +#include "checkasm.h" + +#define randomize_lfe_fir(size) \ + do { \ + int i; \ + for (i = 0; i < size; i++) { \ + float f = (float)rnd() / (UINT_MAX >> 1) - 1.0f; \ + in[i] = f; \ + } \ + for (i = 0; i < 256; i++) { \ + float f = (float)rnd() / (UINT_MAX >> 1) - 1.0f; \ + coeffs[i] = f; \ + } \ + } while (0) + +#define check_lfe_fir(decifactor, eps) \ + do { \ + LOCAL_ALIGNED_16(float, in, [256 / decifactor]); \ + LOCAL_ALIGNED_16(float, out0, [decifactor * 2]); \ + LOCAL_ALIGNED_16(float, out1, [decifactor * 2]); \ + LOCAL_ALIGNED_16(float, coeffs, [256]); \ + int i; \ + const float * in_ptr = in + (256 / decifactor) - 1; \ + declare_func(void, float *out, const float *in, const float *coeffs); \ + /* repeat the test several times */ \ + for (i = 0; i < 32; i++) { \ + int j; \ + memset(out0, 0, sizeof(*out0) * 2 * decifactor); \ + memset(out1, 0xFF, sizeof(*out1) * 2 * decifactor); \ + randomize_lfe_fir(256 / decifactor); \ + call_ref(out0, in_ptr, coeffs); \ + call_new(out1, in_ptr, coeffs); \ + for (j = 0; j < 2 * decifactor; j++) { \ + if (!float_near_abs_eps(out0[j], out1[j], eps)) { \ + if (0) { \ + union av_intfloat32 x, y; x.f = out0[j]; y.f = out1[j]; \ + fprintf(stderr, "%3d: %11g (0x%08x); %11g (0x%08x)\n", \ + j, x.f, x.i, y.f, y.i); \ + } \ + fail(); \ + break; \ + } \ + } \ + bench_new(out1, in_ptr, coeffs); \ + } \ + } while (0) + +void checkasm_check_dcadsp(void) +{ + DCADSPContext c; + + ff_dcadsp_init(&c); + + /* values are limited to {-8, 8} so absolute epsilon is good enough */ + if (check_func(c.lfe_fir[0], "dca_lfe_fir0")) + check_lfe_fir(32, 1.0e-6f); + + if (check_func(c.lfe_fir[1], "dca_lfe_fir1")) + check_lfe_fir(64, 1.0e-6f); + + report("dcadsp"); +} diff --git a/tests/checkasm/fmtconvert.c b/tests/checkasm/fmtconvert.c new file mode 100644 index 0000000..1a843b0 --- /dev/null +++ b/tests/checkasm/fmtconvert.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/common.h" +#include "libavcodec/fmtconvert.h" + +#include "checkasm.h" + +#define BUF_SIZE 1024 + +#define randomize_input(len) \ + do { \ + int k; \ + for (k = 0; k < len; k++) { \ + in[k] = rnd() - INT32_MAX; \ + } \ + for ( ; k < BUF_SIZE; k++) { \ + in[k] = INT32_MAX; \ + } \ + } while (0) + +void checkasm_check_fmtconvert(void) +{ + FmtConvertContext c; + LOCAL_ALIGNED(32, float, dst0, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, dst1, [BUF_SIZE]); + LOCAL_ALIGNED(32, int32_t, in, [BUF_SIZE]); + float scale_arr[128]; + int length[] = {8, 16, 24, 56, 72, 128, 512, 520, 656, 768, 992}; + int i, j; + + for (i = 0; i < FF_ARRAY_ELEMS(scale_arr); i++) + scale_arr[i] = (FF_ARRAY_ELEMS(scale_arr) - FF_ARRAY_ELEMS(scale_arr) / 2) / 13; + + ff_fmt_convert_init(&c, NULL); + + memset(dst0, 0, sizeof(*dst0) * BUF_SIZE); + memset(dst1, 0, sizeof(*dst1) * BUF_SIZE); + + if (check_func(c.int32_to_float_fmul_scalar, "int32_to_float_fmul_scalar")) { + declare_func(void, float *, const int32_t *, float, int); + + for (i = 0; i < FF_ARRAY_ELEMS(scale_arr); i++) { + for (j = 0; j < FF_ARRAY_ELEMS(length); j++) { + + randomize_input(length[j]); + + call_ref(dst0, in, scale_arr[i], length[j]); + call_new(dst1, in, scale_arr[i], length[j]); + + if (!float_near_ulp_array(dst0, dst1, 3, length[j])) { + fail(); + break; + } + + bench_new(dst1, in, scale_arr[i], length[j]); + } + } + } + if (check_func(c.int32_to_float_fmul_array8, "int32_to_float_fmul_array8")) { + declare_func(void, FmtConvertContext *, float *, const int32_t *, + const float *, int); + + for (i = 0; i < 4; i++) { + for (j = 0; j < FF_ARRAY_ELEMS(length); j++) { + + randomize_input(length[j]); + + call_ref(&c, dst0, in, scale_arr, length[j]); + call_new(&c, dst1, in, scale_arr, length[j]); + + if (!float_near_ulp_array(dst0, dst1, 3, length[j])) { + fail(); + fprintf(stderr, "int32_to_float_fmul_array8: len: %d\n", length[j]); + break; + } + + bench_new(&c, dst1, in, scale_arr, length[j]); + } + } + } + report("fmtconvert"); +} diff --git a/tests/checkasm/h264dsp.c b/tests/checkasm/h264dsp.c new file mode 100644 index 0000000..c9ddd52 --- /dev/null +++ b/tests/checkasm/h264dsp.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2016 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/h264dsp.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define SIZEOF_COEF (2 * ((bit_depth + 7) / 8)) +#define PIXEL_STRIDE 16 + +#define randomize_buffers() \ + do { \ + int x, y; \ + uint32_t mask = pixel_mask[bit_depth - 8]; \ + for (y = 0; y < sz; y++) { \ + for (x = 0; x < PIXEL_STRIDE; x += 4) { \ + AV_WN32A(src + y * PIXEL_STRIDE + x, rnd() & mask); \ + AV_WN32A(dst + y * PIXEL_STRIDE + x, rnd() & mask); \ + } \ + for (x = 0; x < sz; x++) { \ + if (bit_depth == 8) { \ + coef[y * sz + x] = src[y * PIXEL_STRIDE + x] - \ + dst[y * PIXEL_STRIDE + x]; \ + } else { \ + ((int32_t *)coef)[y * sz + x] = \ + ((uint16_t *)src)[y * (PIXEL_STRIDE/2) + x] - \ + ((uint16_t *)dst)[y * (PIXEL_STRIDE/2) + x]; \ + } \ + } \ + } \ + } while (0) + +#define dct4x4_impl(size, dctcoef) \ +static void dct4x4_##size(dctcoef *coef) \ +{ \ + int i, y, x; \ + dctcoef tmp[16]; \ + for (i = 0; i < 4; i++) { \ + const int z0 = coef[i*4 + 0] + coef[i*4 + 3]; \ + const int z1 = coef[i*4 + 1] + coef[i*4 + 2]; \ + const int z2 = coef[i*4 + 0] - coef[i*4 + 3]; \ + const int z3 = coef[i*4 + 1] - coef[i*4 + 2]; \ + tmp[i + 4*0] = z0 + z1; \ + tmp[i + 4*1] = 2*z2 + z3; \ + tmp[i + 4*2] = z0 - z1; \ + tmp[i + 4*3] = z2 - 2*z3; \ + } \ + for (i = 0; i < 4; i++) { \ + const int z0 = tmp[i*4 + 0] + tmp[i*4 + 3]; \ + const int z1 = tmp[i*4 + 1] + tmp[i*4 + 2]; \ + const int z2 = tmp[i*4 + 0] - tmp[i*4 + 3]; \ + const int z3 = tmp[i*4 + 1] - tmp[i*4 + 2]; \ + coef[i*4 + 0] = z0 + z1; \ + coef[i*4 + 1] = 2*z2 + z3; \ + coef[i*4 + 2] = z0 - z1; \ + coef[i*4 + 3] = z2 - 2*z3; \ + } \ + for (y = 0; y < 4; y++) { \ + for (x = 0; x < 4; x++) { \ + static const int scale[] = { 13107 * 10, 8066 * 13, 5243 * 16 }; \ + const int idx = (y & 1) + (x & 1); \ + coef[y*4 + x] = (coef[y*4 + x] * scale[idx] + (1 << 14)) >> 15; \ + } \ + } \ +} + +#define DCT8_1D(src, srcstride, dst, dststride) do { \ + const int a0 = (src)[srcstride * 0] + (src)[srcstride * 7]; \ + const int a1 = (src)[srcstride * 0] - (src)[srcstride * 7]; \ + const int a2 = (src)[srcstride * 1] + (src)[srcstride * 6]; \ + const int a3 = (src)[srcstride * 1] - (src)[srcstride * 6]; \ + const int a4 = (src)[srcstride * 2] + (src)[srcstride * 5]; \ + const int a5 = (src)[srcstride * 2] - (src)[srcstride * 5]; \ + const int a6 = (src)[srcstride * 3] + (src)[srcstride * 4]; \ + const int a7 = (src)[srcstride * 3] - (src)[srcstride * 4]; \ + const int b0 = a0 + a6; \ + const int b1 = a2 + a4; \ + const int b2 = a0 - a6; \ + const int b3 = a2 - a4; \ + const int b4 = a3 + a5 + (a1 + (a1 >> 1)); \ + const int b5 = a1 - a7 - (a5 + (a5 >> 1)); \ + const int b6 = a1 + a7 - (a3 + (a3 >> 1)); \ + const int b7 = a3 - a5 + (a7 + (a7 >> 1)); \ + (dst)[dststride * 0] = b0 + b1; \ + (dst)[dststride * 1] = b4 + (b7 >> 2); \ + (dst)[dststride * 2] = b2 + (b3 >> 1); \ + (dst)[dststride * 3] = b5 + (b6 >> 2); \ + (dst)[dststride * 4] = b0 - b1; \ + (dst)[dststride * 5] = b6 - (b5 >> 2); \ + (dst)[dststride * 6] = (b2 >> 1) - b3; \ + (dst)[dststride * 7] = (b4 >> 2) - b7; \ +} while (0) + +#define dct8x8_impl(size, dctcoef) \ +static void dct8x8_##size(dctcoef *coef) \ +{ \ + int i, x, y; \ + dctcoef tmp[64]; \ + for (i = 0; i < 8; i++) \ + DCT8_1D(coef + i, 8, tmp + i, 8); \ + \ + for (i = 0; i < 8; i++) \ + DCT8_1D(tmp + 8*i, 1, coef + i, 8); \ + \ + for (y = 0; y < 8; y++) { \ + for (x = 0; x < 8; x++) { \ + static const int scale[] = { \ + 13107 * 20, 11428 * 18, 20972 * 32, \ + 12222 * 19, 16777 * 25, 15481 * 24, \ + }; \ + static const int idxmap[] = { \ + 0, 3, 4, 3, \ + 3, 1, 5, 1, \ + 4, 5, 2, 5, \ + 3, 1, 5, 1, \ + }; \ + const int idx = idxmap[(y & 3) * 4 + (x & 3)]; \ + coef[y*8 + x] = ((int64_t)coef[y*8 + x] * \ + scale[idx] + (1 << 17)) >> 18; \ + } \ + } \ +} + +dct4x4_impl(16, int16_t) +dct4x4_impl(32, int32_t) + +dct8x8_impl(16, int16_t) +dct8x8_impl(32, int32_t) + +static void dct4x4(int16_t *coef, int bit_depth) +{ + if (bit_depth == 8) + dct4x4_16(coef); + else + dct4x4_32((int32_t *) coef); +} + +static void dct8x8(int16_t *coef, int bit_depth) +{ + if (bit_depth == 8) { + dct8x8_16(coef); + } else { + dct8x8_32((int32_t *) coef); + } +} + + +static void check_idct(void) +{ + LOCAL_ALIGNED_16(uint8_t, src, [8 * 8 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst, [8 * 8 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst0, [8 * 8 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst1_base, [8 * 8 * 2 + 32]); + LOCAL_ALIGNED_16(int16_t, coef, [8 * 8 * 2]); + LOCAL_ALIGNED_16(int16_t, subcoef0, [8 * 8 * 2]); + LOCAL_ALIGNED_16(int16_t, subcoef1, [8 * 8 * 2]); + H264DSPContext h; + int bit_depth, sz, align, dc; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t *block, int stride); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_h264dsp_init(&h, bit_depth, 1); + for (sz = 4; sz <= 8; sz += 4) { + randomize_buffers(); + + if (sz == 4) + dct4x4(coef, bit_depth); + else + dct8x8(coef, bit_depth); + + for (dc = 0; dc <= 1; dc++) { + void (*idct)(uint8_t *, int16_t *, int) = NULL; + switch ((sz << 1) | dc) { + case (4 << 1) | 0: idct = h.h264_idct_add; break; + case (4 << 1) | 1: idct = h.h264_idct_dc_add; break; + case (8 << 1) | 0: idct = h.h264_idct8_add; break; + case (8 << 1) | 1: idct = h.h264_idct8_dc_add; break; + } + if (check_func(idct, "h264_idct%d_add%s_%dbpp", sz, dc ? "_dc" : "", bit_depth)) { + for (align = 0; align < 16; align += sz * SIZEOF_PIXEL) { + uint8_t *dst1 = dst1_base + align; + if (dc) { + memset(subcoef0, 0, sz * sz * SIZEOF_COEF); + memcpy(subcoef0, coef, SIZEOF_COEF); + } else { + memcpy(subcoef0, coef, sz * sz * SIZEOF_COEF); + } + memcpy(dst0, dst, sz * PIXEL_STRIDE); + memcpy(dst1, dst, sz * PIXEL_STRIDE); + memcpy(subcoef1, subcoef0, sz * sz * SIZEOF_COEF); + call_ref(dst0, subcoef0, PIXEL_STRIDE); + call_new(dst1, subcoef1, PIXEL_STRIDE); + if (memcmp(dst0, dst1, sz * PIXEL_STRIDE) || + memcmp(subcoef0, subcoef1, sz * sz * SIZEOF_COEF)) + fail(); + bench_new(dst1, subcoef1, sz * SIZEOF_PIXEL); + } + } + } + } + } + report("idct"); +} + +void checkasm_check_h264dsp(void) +{ + check_idct(); +} diff --git a/tests/checkasm/h264pred.c b/tests/checkasm/h264pred.c new file mode 100644 index 0000000..4994947 --- /dev/null +++ b/tests/checkasm/h264pred.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2015 Henrik Gramner + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/h264pred.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +static const int codec_ids[4] = { AV_CODEC_ID_H264, AV_CODEC_ID_VP8, AV_CODEC_ID_RV40, AV_CODEC_ID_SVQ3 }; + +static const char * const pred4x4_modes[4][15] = { + { /* H.264 */ + [VERT_PRED ] = "vertical", + [HOR_PRED ] = "horizontal", + [DC_PRED ] = "dc", + [DIAG_DOWN_LEFT_PRED ] = "down_left", + [DIAG_DOWN_RIGHT_PRED] = "down_right", + [VERT_RIGHT_PRED ] = "vertical_right", + [HOR_DOWN_PRED ] = "horizontal_right", + [VERT_LEFT_PRED ] = "vertical_left", + [HOR_UP_PRED ] = "horizontal_up", + [LEFT_DC_PRED ] = "left_dc", + [TOP_DC_PRED ] = "top_dc", + [DC_128_PRED ] = "dc_128", + }, + { /* VP8 */ + [VERT_PRED ] = "vertical_vp8", + [HOR_PRED ] = "horizontal_vp8", + [VERT_LEFT_PRED] = "vertical_left_vp8", + [TM_VP8_PRED ] = "tm_vp8", + [DC_127_PRED ] = "dc_127_vp8", + [DC_129_PRED ] = "dc_129_vp8", + }, + { /* RV40 */ + [DIAG_DOWN_LEFT_PRED ] = "down_left_rv40", + [VERT_LEFT_PRED ] = "vertical_left_rv40", + [HOR_UP_PRED ] = "horizontal_up_rv40", + [DIAG_DOWN_LEFT_PRED_RV40_NODOWN] = "down_left_nodown_rv40", + [HOR_UP_PRED_RV40_NODOWN ] = "horizontal_up_nodown_rv40", + [VERT_LEFT_PRED_RV40_NODOWN ] = "vertical_left_nodown_rv40", + }, + { /* SVQ3 */ + [DIAG_DOWN_LEFT_PRED] = "down_left_svq3", + }, +}; + +static const char * const pred8x8_modes[4][11] = { + { /* H.264 */ + [DC_PRED8x8 ] = "dc", + [HOR_PRED8x8 ] = "horizontal", + [VERT_PRED8x8 ] = "vertical", + [PLANE_PRED8x8 ] = "plane", + [LEFT_DC_PRED8x8 ] = "left_dc", + [TOP_DC_PRED8x8 ] = "top_dc", + [DC_128_PRED8x8 ] = "dc_128", + [ALZHEIMER_DC_L0T_PRED8x8] = "mad_cow_dc_l0t", + [ALZHEIMER_DC_0LT_PRED8x8] = "mad_cow_dc_0lt", + [ALZHEIMER_DC_L00_PRED8x8] = "mad_cow_dc_l00", + [ALZHEIMER_DC_0L0_PRED8x8] = "mad_cow_dc_0l0", + }, + { /* VP8 */ + [PLANE_PRED8x8 ] = "tm_vp8", + [DC_127_PRED8x8] = "dc_127_vp8", + [DC_129_PRED8x8] = "dc_129_vp8", + }, + { /* RV40 */ + [DC_PRED8x8 ] = "dc_rv40", + [LEFT_DC_PRED8x8] = "left_dc_rv40", + [TOP_DC_PRED8x8 ] = "top_dc_rv40", + }, + /* nothing for SVQ3 */ +}; + +static const char * const pred16x16_modes[4][9] = { + { /* H.264 */ + [DC_PRED8x8 ] = "dc", + [HOR_PRED8x8 ] = "horizontal", + [VERT_PRED8x8 ] = "vertical", + [PLANE_PRED8x8 ] = "plane", + [LEFT_DC_PRED8x8] = "left_dc", + [TOP_DC_PRED8x8 ] = "top_dc", + [DC_128_PRED8x8 ] = "dc_128", + }, + { /* VP8 */ + [PLANE_PRED8x8 ] = "tm_vp8", + [DC_127_PRED8x8] = "dc_127_vp8", + [DC_129_PRED8x8] = "dc_129_vp8", + }, + { /* RV40 */ + [PLANE_PRED8x8] = "plane_rv40", + }, + { /* SVQ3 */ + [PLANE_PRED8x8] = "plane_svq3", + }, +}; + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_SIZE (3 * 16 * 17) + +#define check_pred_func(func, name, mode_name) \ + (mode_name && ((codec_ids[codec] == AV_CODEC_ID_H264) ? \ + check_func(func, "pred%s_%s_%d", name, mode_name, bit_depth) : \ + check_func(func, "pred%s_%s", name, mode_name))) + +#define randomize_buffers() \ + do { \ + uint32_t mask = pixel_mask[bit_depth - 8]; \ + int i; \ + for (i = 0; i < BUF_SIZE; i += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + i, r); \ + AV_WN32A(buf1 + i, r); \ + } \ + } while (0) + +#define src0 (buf0 + 4 * 16) /* Offset to allow room for top and left */ +#define src1 (buf1 + 4 * 16) + +static void check_pred4x4(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, + int codec, int chroma_format, int bit_depth) +{ + if (chroma_format == 1) { + uint8_t *topright = buf0 + 2*16; + int pred_mode; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, const uint8_t *topright, ptrdiff_t stride); + + for (pred_mode = 0; pred_mode < 15; pred_mode++) { + if (check_pred_func(h->pred4x4[pred_mode], "4x4", pred4x4_modes[codec][pred_mode])) { + randomize_buffers(); + call_ref(src0, topright, 12*SIZEOF_PIXEL); + call_new(src1, topright, 12*SIZEOF_PIXEL); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + bench_new(src1, topright, 12*SIZEOF_PIXEL); + } + } + } +} + +static void check_pred8x8(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, + int codec, int chroma_format, int bit_depth) +{ + int pred_mode; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, ptrdiff_t stride); + + for (pred_mode = 0; pred_mode < 11; pred_mode++) { + if (check_pred_func(h->pred8x8[pred_mode], (chroma_format == 2) ? "8x16" : "8x8", + pred8x8_modes[codec][pred_mode])) { + randomize_buffers(); + call_ref(src0, 24*SIZEOF_PIXEL); + call_new(src1, 24*SIZEOF_PIXEL); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + bench_new(src1, 24*SIZEOF_PIXEL); + } + } +} + +static void check_pred16x16(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, + int codec, int chroma_format, int bit_depth) +{ + if (chroma_format == 1) { + int pred_mode; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, ptrdiff_t stride); + + for (pred_mode = 0; pred_mode < 9; pred_mode++) { + if (check_pred_func(h->pred16x16[pred_mode], "16x16", pred16x16_modes[codec][pred_mode])) { + randomize_buffers(); + call_ref(src0, 48); + call_new(src1, 48); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + bench_new(src1, 48); + } + } + } +} + +static void check_pred8x8l(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, + int codec, int chroma_format, int bit_depth) +{ + if (chroma_format == 1 && codec_ids[codec] == AV_CODEC_ID_H264) { + int pred_mode; + declare_func_emms(AV_CPU_FLAG_MMXEXT, void, uint8_t *src, int topleft, int topright, ptrdiff_t stride); + + for (pred_mode = 0; pred_mode < 12; pred_mode++) { + if (check_pred_func(h->pred8x8l[pred_mode], "8x8l", pred4x4_modes[codec][pred_mode])) { + int neighbors; + for (neighbors = 0; neighbors <= 0xc000; neighbors += 0x4000) { + int has_topleft = neighbors & 0x8000; + int has_topright = neighbors & 0x4000; + + if ((pred_mode == DIAG_DOWN_RIGHT_PRED || pred_mode == VERT_RIGHT_PRED) && !has_topleft) + continue; /* Those aren't allowed according to the spec */ + + randomize_buffers(); + call_ref(src0, has_topleft, has_topright, 24*SIZEOF_PIXEL); + call_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + bench_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL); + } + } + } + } +} + +/* TODO: Add tests for H.264 lossless H/V prediction */ + +void checkasm_check_h264pred(void) +{ + static const struct { + void (*func)(H264PredContext*, uint8_t*, uint8_t*, int, int, int); + const char *name; + } tests[] = { + { check_pred4x4, "pred4x4" }, + { check_pred8x8, "pred8x8" }, + { check_pred16x16, "pred16x16" }, + { check_pred8x8l, "pred8x8l" }, + }; + + LOCAL_ALIGNED_16(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, buf1, [BUF_SIZE]); + H264PredContext h; + int test, codec, chroma_format, bit_depth; + + for (test = 0; test < FF_ARRAY_ELEMS(tests); test++) { + for (codec = 0; codec < 4; codec++) { + int codec_id = codec_ids[codec]; + for (bit_depth = 8; bit_depth <= (codec_id == AV_CODEC_ID_H264 ? 10 : 8); bit_depth++) + for (chroma_format = 1; chroma_format <= (codec_id == AV_CODEC_ID_H264 ? 2 : 1); chroma_format++) { + ff_h264_pred_init(&h, codec_id, bit_depth, chroma_format); + tests[test].func(&h, buf0, buf1, codec, chroma_format, bit_depth); + } + } + report("%s", tests[test].name); + } +} diff --git a/tests/checkasm/h264qpel.c b/tests/checkasm/h264qpel.c new file mode 100644 index 0000000..d92f223 --- /dev/null +++ b/tests/checkasm/h264qpel.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Henrik Gramner + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/h264qpel.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_SIZE (2 * 16 * (16 + 3 + 4)) + +#define randomize_buffers() \ + do { \ + uint32_t mask = pixel_mask[bit_depth - 8]; \ + int k; \ + for (k = 0; k < BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + r = rnd(); \ + AV_WN32A(dst0 + k, r); \ + AV_WN32A(dst1 + k, r); \ + } \ + } while (0) + +#define src0 (buf0 + 3 * 2 * 16) /* h264qpel functions read data from negative src pointer offsets */ +#define src1 (buf1 + 3 * 2 * 16) + +void checkasm_check_h264qpel(void) +{ + LOCAL_ALIGNED_16(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dst1, [BUF_SIZE]); + H264QpelContext h; + int op, bit_depth, i, j; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, const uint8_t *src, ptrdiff_t stride); + + for (op = 0; op < 2; op++) { + qpel_mc_func (*tab)[16] = op ? h.avg_h264_qpel_pixels_tab : h.put_h264_qpel_pixels_tab; + const char *op_name = op ? "avg" : "put"; + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_h264qpel_init(&h, bit_depth); + for (i = 0; i < (op ? 3 : 4); i++) { + int size = 16 >> i; + for (j = 0; j < 16; j++) + if (check_func(tab[i][j], "%s_h264_qpel_%d_mc%d%d_%d", op_name, size, j & 3, j >> 2, bit_depth)) { + randomize_buffers(); + call_ref(dst0, src0, size * SIZEOF_PIXEL); + call_new(dst1, src1, size * SIZEOF_PIXEL); + if (memcmp(buf0, buf1, BUF_SIZE) || memcmp(dst0, dst1, BUF_SIZE)) + fail(); + bench_new(dst1, src1, size * SIZEOF_PIXEL); + } + } + } + report("%s", op_name); + } +} diff --git a/tests/checkasm/hevc_idct.c b/tests/checkasm/hevc_idct.c new file mode 100644 index 0000000..84760b9 --- /dev/null +++ b/tests/checkasm/hevc_idct.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Alexandra Hájková + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/intreadwrite.h" + +#include "libavcodec/hevcdsp.h" + +#include "checkasm.h" + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + for (j = 0; j < size; j++) { \ + int16_t r = rnd(); \ + AV_WN16A(buf + j, r); \ + } \ + } while (0) + +static void check_idct_dc(HEVCDSPContext h, int bit_depth) +{ + int i; + LOCAL_ALIGNED(32, int16_t, coeffs0, [32 * 32]); + LOCAL_ALIGNED(32, int16_t, coeffs1, [32 * 32]); + + for (i = 2; i <= 5; i++) { + int block_size = 1 << i; + int size = block_size * block_size; + declare_func_emms(AV_CPU_FLAG_MMXEXT, void, int16_t *coeffs); + + randomize_buffers(coeffs0, size); + memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size); + + if (check_func(h.idct_dc[i - 2], "idct_%dx%d_dc_%d", block_size, block_size, bit_depth)) { + call_ref(coeffs0); + call_new(coeffs1); + if (memcmp(coeffs0, coeffs1, sizeof(*coeffs0) * size)) + fail(); + bench_new(coeffs1); + } + } +} + +void checkasm_check_hevc_idct(void) +{ + int bit_depth; + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + HEVCDSPContext h; + + ff_hevc_dsp_init(&h, bit_depth); + check_idct_dc(h, bit_depth); + } + report("idct_dc"); +} diff --git a/tests/checkasm/hevc_mc.c b/tests/checkasm/hevc_mc.c new file mode 100644 index 0000000..385c33e --- /dev/null +++ b/tests/checkasm/hevc_mc.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2015 Anton Khirnov + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "checkasm.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/hevcdsp.h" + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +// max PU size + interpolation stencil +#define BUF_SIZE (FFALIGN(64 + 7, 16) * (64 + 7) * 2) + +#define PIXEL_SIZE(depth) ((depth + 7) / 8) + +#define randomize_buffers(buf, size, depth) \ + do { \ + uint32_t mask = pixel_mask[depth - 8]; \ + int i; \ + for (i = 0; i < size; i += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf + i, r); \ + } \ + } while (0) + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; + +static const int pred_heights[][7] = { + [2] = { 8, 4, 2, 0 }, + [4] = { 16, 8, 4, 2, 0 }, + [6] = { 8, 0 }, + [8] = { 32, 16, 8, 4, 2, 0 }, + [12] = { 16, 0 }, + [16] = { 64, 32, 16, 12, 8, 4, 0 }, + [24] = { 32, 0 }, + [32] = { 64, 32, 24, 16, 8, 0 }, + [48] = { 64, 0 }, + [64] = { 64, 48, 32, 16, 0 }, +}; + +static const int pred_widths[] = { 4, 8, 12, 16, 24, 32, 48, 64 }; + +static const char *interp_names[2][2] = { { "pixels", "h" }, { "v", "hv" } }; + +#define UNWEIGHTED_PRED(dst0, dst1, src0, width, bit_depth) \ +do { \ + int i; \ + for (i = 0; i < FF_ARRAY_ELEMS(pred_heights[i]); i++) { \ + int height = pred_heights[width][i]; \ + if (!height) \ + break; \ + call_ref(dst0, dststride, src0, srcstride, height); \ + call_new(dst1, dststride, src0, srcstride, height); \ + if (memcmp(dst0, dst1, dststride * height)) \ + fail(); \ + bench_new(dst1, dststride, src0, srcstride, height); \ + } \ +} while (0) + +#define UNWEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth) \ +do { \ + int i; \ + for (i = 0; i < FF_ARRAY_ELEMS(pred_heights[i]); i++) { \ + int height = pred_heights[width][i]; \ + if (!height) \ + break; \ + call_ref(dst0, dststride, src0, src1, srcstride, height); \ + call_new(dst1, dststride, src0, src1, srcstride, height); \ + if (memcmp(dst0, dst1, dststride * height)) \ + fail(); \ + bench_new(dst1, dststride, src0, src1, srcstride, height); \ + } \ +} while (0) + +static void check_unweighted_pred(HEVCDSPContext *h, uint8_t *dst0, uint8_t *dst1, + int16_t *src0, int16_t *src1, int bit_depth) +{ + int i; + + randomize_buffers(src0, BUF_SIZE, 8); + randomize_buffers(src1, BUF_SIZE, 8); + + memset(dst0, 0, BUF_SIZE * sizeof(*dst0)); + memset(dst1, 0, BUF_SIZE * sizeof(*dst1)); + + for (i = 0; i < FF_ARRAY_ELEMS(pred_widths); i++) { + const int width = pred_widths[i]; + const int srcstride = FFALIGN(width, 16) * sizeof(*src0); + const int dststride = FFALIGN(width, 16) * PIXEL_SIZE(bit_depth); + + { + declare_func(void, uint8_t *dst, ptrdiff_t dststride, int16_t *src, ptrdiff_t srcstride, int height); + if (check_func(h->put_unweighted_pred[i], "put_unweighted_pred_%d_%d", width, bit_depth)) + UNWEIGHTED_PRED(dst0, dst1, src0, width, bit_depth); + if (check_func(h->put_unweighted_pred_chroma[i], "put_unweighted_pred_%d_%d", width / 2, bit_depth)) + UNWEIGHTED_PRED(dst0, dst1, src0, width, bit_depth); + } + { + declare_func(void, uint8_t *dst, ptrdiff_t dststride, + int16_t *src0, int16_t *src1, ptrdiff_t srcstride, int height); + if (check_func(h->put_unweighted_pred_avg[i], "put_unweighted_pred_avg_%d_%d", width, bit_depth)) + UNWEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth); + if (check_func(h->put_unweighted_pred_avg_chroma[i], "put_unweighted_pred_avg_%d_%d", width / 2, bit_depth)) + UNWEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth); + } + } +} + +#define WEIGHTED_PRED(dst0, dst1, src0, width, bit_depth) \ +do { \ + int i; \ + for (i = 0; i < FF_ARRAY_ELEMS(pred_heights[i]); i++) { \ + int height = pred_heights[width][i]; \ + if (!height) \ + break; \ + call_ref(denom, weight0, offset0, dst0, dststride, src0, srcstride, height); \ + call_new(denom, weight0, offset0, dst1, dststride, src0, srcstride, height); \ + if (memcmp(dst0, dst1, dststride * height)) \ + fail(); \ + bench_new(denom, weight0, offset0, dst1, dststride, src0, srcstride, height); \ + } \ +} while (0) + +#define WEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth) \ +do { \ + int i; \ + for (i = 0; i < FF_ARRAY_ELEMS(pred_heights[i]); i++) { \ + int height = pred_heights[width][i]; \ + if (!height) \ + break; \ + call_ref(denom, weight0, weight1, offset0, offset1, dst0, dststride, src0, src1, srcstride, height); \ + call_new(denom, weight0, weight1, offset0, offset1, dst1, dststride, src0, src1, srcstride, height); \ + if (memcmp(dst0, dst1, dststride * height)) \ + fail(); \ + bench_new(denom, weight0, weight1, offset0, offset1, dst1, dststride, src0, src1, srcstride, height); \ + } \ +} while (0) + +static void check_weighted_pred(HEVCDSPContext *h, uint8_t *dst0, uint8_t *dst1, + int16_t *src0, int16_t *src1, int bit_depth) +{ + uint8_t denom; + int16_t weight0, weight1, offset0, offset1; + int i; + + randomize_buffers(src0, BUF_SIZE, 8); + randomize_buffers(src1, BUF_SIZE, 8); + + denom = rnd() & 7; + weight0 = denom + ((rnd() & 255) - 128); + weight1 = denom + ((rnd() & 255) - 128); + offset0 = (rnd() & 255) - 128; + offset1 = (rnd() & 255) - 128; + + memset(dst0, 0, BUF_SIZE * sizeof(*dst0)); + memset(dst1, 0, BUF_SIZE * sizeof(*dst1)); + + for (i = 0; i < FF_ARRAY_ELEMS(pred_widths); i++) { + const int width = pred_widths[i]; + const int srcstride = FFALIGN(width, 16) * sizeof(*src0); + const int dststride = FFALIGN(width, 16) * PIXEL_SIZE(bit_depth); + + { + declare_func(void, uint8_t denom, int16_t weight, int16_t offset, + uint8_t *dst, ptrdiff_t dststride, int16_t *src, ptrdiff_t srcstride, int height); + if (check_func(h->weighted_pred[i], "weighted_pred_%d_%d", width, bit_depth)) + WEIGHTED_PRED(dst0, dst1, src0, width, bit_depth); + if (check_func(h->weighted_pred_chroma[i], "weighted_pred_%d_%d", width / 2, bit_depth)) + WEIGHTED_PRED(dst0, dst1, src0, width, bit_depth); + } + { + declare_func(void, uint8_t denom, int16_t weight0, int16_t weight1, int16_t offset0, int16_t offset1, + uint8_t *dst, ptrdiff_t dststride, int16_t *src0, int16_t *src1, ptrdiff_t srcstride, int height); + if (check_func(h->weighted_pred_avg[i], "weighted_pred_avg_%d_%d", width, bit_depth)) + WEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth); + if (check_func(h->weighted_pred_avg_chroma[i], "weighted_pred_avg_%d_%d", width / 2, bit_depth)) + WEIGHTED_PRED_AVG(dst0, dst1, src0, src1, width, bit_depth); + } + } +} + +static void check_epel(HEVCDSPContext *h, int16_t *dst0, int16_t *dst1, + uint8_t *src, int16_t *mcbuffer, int bit_depth) +{ + int i, j, k, l, mx, my; + + declare_func(void, int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my, int16_t *mcbuffer); + + randomize_buffers(src, BUF_SIZE, bit_depth); + + memset(dst0, 0, BUF_SIZE * sizeof(*dst0)); + memset(dst1, 0, BUF_SIZE * sizeof(*dst1)); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < FF_ARRAY_ELEMS(h->put_hevc_epel[i][j]); k++) { + int width = pred_widths[k] / 2; + int dststride = FFALIGN(width, 16) * sizeof(*dst0); + int srcstride = FFALIGN(width + 3, 8) * PIXEL_SIZE(bit_depth); + + if (!check_func(h->put_hevc_epel[i][j][k], "epel_%s_%d_%d", interp_names[i][j], width, bit_depth)) + continue; + + for (l = 0; l < FF_ARRAY_ELEMS(pred_heights[0]); l++) { + int height = pred_heights[width][l]; + + if (!height) + continue; + + for (my = i; my < (i ? 8 : 1); my++) + for (mx = j; mx < (j ? 8 : 1); mx++) { + call_ref(dst0, dststride, src + srcstride + PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + call_new(dst1, dststride, src + srcstride + PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + + if (memcmp(dst0, dst1, dststride * height * sizeof(*dst0))) + fail(); + + bench_new(dst1, dststride, src + srcstride + PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + } + } + } + } + } +} + +static void check_qpel(HEVCDSPContext *h, int16_t *dst0, int16_t *dst1, + uint8_t *src, int16_t *mcbuffer, int bit_depth) +{ + int i, j, k, l, mx, my; + + declare_func(void, int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my, int16_t *mcbuffer); + + randomize_buffers(src, BUF_SIZE, bit_depth); + + memset(dst0, 0, BUF_SIZE * sizeof(*dst0)); + memset(dst1, 0, BUF_SIZE * sizeof(*dst1)); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < FF_ARRAY_ELEMS(h->put_hevc_qpel[i][j]); k++) { + int width = pred_widths[k]; + int dststride = FFALIGN(width, 16) * sizeof(*dst0); + int srcstride = FFALIGN(width + 7, 8) * PIXEL_SIZE(bit_depth); + + if (!check_func(h->put_hevc_qpel[i][j][k], "qpel_%s_%d_%d", interp_names[i][j], width, bit_depth)) + continue; + + for (l = 0; l < FF_ARRAY_ELEMS(pred_heights[0]); l++) { + int height = pred_heights[width][l]; + + if (!height) + continue; + + for (my = i; my < (i ? 2 : 1); my++) + for (mx = j; mx < (j ? 2 : 1); mx++) { + call_ref(dst0, dststride, src + 3 * srcstride + 3 * PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + call_new(dst1, dststride, src + 3 * srcstride + 3 * PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + + if (memcmp(dst0, dst1, dststride * height * sizeof(*dst0))) + fail(); + + bench_new(dst1, dststride, src + 3 * srcstride + 3 * PIXEL_SIZE(bit_depth), srcstride, height, mx, my, mcbuffer); + } + } + } + } + } +} + +void checkasm_check_hevc_mc(void) +{ + DECLARE_ALIGNED(16, uint8_t, buf8_0)[BUF_SIZE]; + DECLARE_ALIGNED(16, uint8_t, buf8_1)[BUF_SIZE]; + + DECLARE_ALIGNED(16, int16_t, buf16_0)[BUF_SIZE]; + DECLARE_ALIGNED(16, int16_t, buf16_1)[BUF_SIZE]; + + DECLARE_ALIGNED(16, int16_t, mcbuffer)[BUF_SIZE]; + + HEVCDSPContext h; + int bit_depth; + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + check_qpel(&h, buf16_0, buf16_1, buf8_0, mcbuffer, bit_depth); + } + report("qpel"); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + check_epel(&h, buf16_0, buf16_1, buf8_0, mcbuffer, bit_depth); + } + report("epel"); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + check_unweighted_pred(&h, buf8_0, buf8_1, buf16_0, buf16_1, bit_depth); + } + report("unweighted_pred"); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + check_weighted_pred(&h, buf8_0, buf8_1, buf16_0, buf16_1, bit_depth); + } + report("weighted_pred"); +} diff --git a/tests/checkasm/synth_filter.c b/tests/checkasm/synth_filter.c new file mode 100644 index 0000000..157400b --- /dev/null +++ b/tests/checkasm/synth_filter.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015 Janne Grunau + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intfloat.h" +#include "libavcodec/dcadata.h" +#include "libavcodec/synth_filter.h" + +#include "checkasm.h" + +#define BUF_SIZE 32 + +#define randomize_input() \ + do { \ + int i; \ + for (i = 0; i < BUF_SIZE; i++) { \ + float f = (float)rnd() / (UINT_MAX >> 5) - 16.0f; \ + in[i] = f; \ + } \ + } while (0) + +void checkasm_check_synth_filter(void) +{ + FFTContext imdct; + SynthFilterContext synth; + + ff_mdct_init(&imdct, 6, 1, 1.0); + ff_synth_filter_init(&synth); + + if (check_func(synth.synth_filter_float, "synth_filter_float")) { + LOCAL_ALIGNED(32, float, out0, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, out1, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, out_b, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, in, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, buf2_0, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, buf2_1, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, buf2_b, [BUF_SIZE]); + LOCAL_ALIGNED(32, float, buf0, [512]); + LOCAL_ALIGNED(32, float, buf1, [512]); + LOCAL_ALIGNED(32, float, buf_b, [512]); + float scale = 1.0f; + int i, offset0 = 0, offset1 = 0, offset_b = 0; + + declare_func(void, FFTContext *, float *, int *, float[32], const float[512], + float[32], float[32], float); + + memset(buf2_0, 0, sizeof(*buf2_0) * BUF_SIZE); + memset(buf2_1, 0, sizeof(*buf2_1) * BUF_SIZE); + memset(buf2_b, 0, sizeof(*buf2_b) * BUF_SIZE); + memset(buf0, 0, sizeof(*buf2_0) * 512); + memset(buf1, 0, sizeof(*buf2_1) * 512); + memset(buf_b, 0, sizeof(*buf2_b) * 512); + + /* more than 1 synth_buf_offset wrap-around */ + for (i = 0; i < 20; i++) { + int j; + const float * window = (i & 1) ? ff_dca_fir_32bands_perfect : ff_dca_fir_32bands_nonperfect; + + memset(out0, 0, sizeof(*out0) * BUF_SIZE); + memset(out1, 0, sizeof(*out1) * BUF_SIZE); + memset(out_b, 0, sizeof(*out_b) * BUF_SIZE); + + randomize_input(); + + call_ref(&imdct, buf0, &offset0, buf2_0, window, + out0, in, scale); + call_new(&imdct, buf1, &offset1, buf2_1, window, + out1, in, scale); + + if (offset0 != offset1) { + fail(); + fprintf(stderr, "offsets do not match: %d, %d", offset0, offset1); + break; + } + + for (j = 0; j < BUF_SIZE; j++) { + if (!float_near_abs_eps_ulp(out0[j], out1[j], 7.0e-7, 16) || + !float_near_abs_eps_ulp(buf2_0[j], buf2_1[j], 7.0e-7, 16)) { + union av_intfloat32 o0, o1, b0, b1; + + fail(); + o0.f = out0[j]; o1.f = out1[j]; + b0.f = buf2_0[j], b1.f = buf2_1[j]; + fprintf(stderr, "out: %11g (0x%08x); %11g (0x%08x); abs diff %11g\n", + o0.f, o0.i, o1.f, o1.i, fabsf(o0.f - o1.f)); + fprintf(stderr, "buf2: %11g (0x%08x); %11g (0x%08x); abs diff %11g\n", + b0.f, b0.i, b1.f, b1.i, fabsf(b0.f - b1.f)); + break; + } + } + + bench_new(&imdct, buf_b, &offset_b, buf2_b, window, + out_b, in, scale); + } + } + ff_mdct_end(&imdct); + + report("synth_filter"); +} diff --git a/tests/checkasm/v210enc.c b/tests/checkasm/v210enc.c new file mode 100644 index 0000000..4f5f6ba --- /dev/null +++ b/tests/checkasm/v210enc.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015 Henrik Gramner + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/v210enc.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +#define BUF_SIZE 512 + +#define randomize_buffers(mask) \ + do { \ + int i, size = sizeof(*y0); \ + for (i = 0; i < BUF_SIZE; i += 4 / size) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(y0 + i, r); \ + AV_WN32A(y1 + i, r); \ + } \ + for (i = 0; i < BUF_SIZE / 2; i += 4 / size) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(u0 + i, r); \ + AV_WN32A(u1 + i, r); \ + r = rnd() & mask; \ + AV_WN32A(v0 + i, r); \ + AV_WN32A(v1 + i, r); \ + } \ + for (i = 0; i < width * 8 / 3; i += 4) { \ + uint32_t r = rnd(); \ + AV_WN32A(dst0 + i, r); \ + AV_WN32A(dst1 + i, r); \ + } \ + } while (0) + +#define check_pack_line(type, mask) \ + do { \ + LOCAL_ALIGNED_16(type, y0, [BUF_SIZE]); \ + LOCAL_ALIGNED_16(type, y1, [BUF_SIZE]); \ + LOCAL_ALIGNED_16(type, u0, [BUF_SIZE / 2]); \ + LOCAL_ALIGNED_16(type, u1, [BUF_SIZE / 2]); \ + LOCAL_ALIGNED_16(type, v0, [BUF_SIZE / 2]); \ + LOCAL_ALIGNED_16(type, v1, [BUF_SIZE / 2]); \ + LOCAL_ALIGNED_16(uint8_t, dst0, [BUF_SIZE * 8 / 3]); \ + LOCAL_ALIGNED_16(uint8_t, dst1, [BUF_SIZE * 8 / 3]); \ + \ + declare_func(void, const type * y, const type * u, const type * v, \ + uint8_t * dst, ptrdiff_t width); \ + ptrdiff_t width, step = 12 / sizeof(type); \ + \ + for (width = step; width < BUF_SIZE - 15; width += step) { \ + int y_offset = rnd() & 15; \ + int uv_offset = y_offset / 2; \ + randomize_buffers(mask); \ + call_ref(y0 + y_offset, u0 + uv_offset, v0 + uv_offset, dst0, width); \ + call_new(y1 + y_offset, u1 + uv_offset, v1 + uv_offset, dst1, width); \ + if (memcmp(y0, y1, BUF_SIZE) || memcmp(u0, u1, BUF_SIZE / 2) || \ + memcmp(v0, v1, BUF_SIZE / 2) || memcmp(dst0, dst1, width * 8 / 3)) \ + fail(); \ + bench_new(y1 + y_offset, u1 + uv_offset, v1 + uv_offset, dst1, width); \ + } \ + } while (0) + +void checkasm_check_v210enc(void) +{ + V210EncContext h; + + ff_v210enc_init(&h); + + if (check_func(h.pack_line_8, "v210_planar_pack_8")) + check_pack_line(uint8_t, 0xffffffff); + + if (check_func(h.pack_line_10, "v210_planar_pack_10")) + check_pack_line(uint16_t, 0x03ff03ff); + + report("planar_pack"); +} diff --git a/tests/checkasm/vp8dsp.c b/tests/checkasm/vp8dsp.c new file mode 100644 index 0000000..40e4061 --- /dev/null +++ b/tests/checkasm/vp8dsp.c @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2016 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavcodec/avcodec.h" +#include "libavcodec/vp8dsp.h" + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#include "checkasm.h" + +#define PIXEL_STRIDE 16 + +#define randomize_buffers(src, dst, stride, coef) \ + do { \ + int x, y; \ + for (y = 0; y < 4; y++) { \ + AV_WN32A((src) + y * (stride), rnd()); \ + AV_WN32A((dst) + y * (stride), rnd()); \ + for (x = 0; x < 4; x++) \ + (coef)[y * 4 + x] = (src)[y * (stride) + x] - \ + (dst)[y * (stride) + x]; \ + } \ + } while (0) + +static void dct4x4(int16_t *coef) +{ + int i; + for (i = 0; i < 4; i++) { + const int a1 = (coef[i*4 + 0] + coef[i*4 + 3]) * 8; + const int b1 = (coef[i*4 + 1] + coef[i*4 + 2]) * 8; + const int c1 = (coef[i*4 + 1] - coef[i*4 + 2]) * 8; + const int d1 = (coef[i*4 + 0] - coef[i*4 + 3]) * 8; + coef[i*4 + 0] = a1 + b1; + coef[i*4 + 1] = (c1 * 2217 + d1 * 5352 + 14500) >> 12; + coef[i*4 + 2] = a1 - b1; + coef[i*4 + 3] = (d1 * 2217 - c1 * 5352 + 7500) >> 12; + } + for (i = 0; i < 4; i++) { + const int a1 = coef[i + 0*4] + coef[i + 3*4]; + const int b1 = coef[i + 1*4] + coef[i + 2*4]; + const int c1 = coef[i + 1*4] - coef[i + 2*4]; + const int d1 = coef[i + 0*4] - coef[i + 3*4]; + coef[i + 0*4] = (a1 + b1 + 7) >> 4; + coef[i + 1*4] = ((c1 * 2217 + d1 * 5352 + 12000) >> 16) + !!d1; + coef[i + 2*4] = (a1 - b1 + 7) >> 4; + coef[i + 3*4] = (d1 * 2217 - c1 * 5352 + 51000) >> 16; + } +} + +static void wht4x4(int16_t *coef) +{ + int i; + for (i = 0; i < 4; i++) { + int a1 = coef[0 * 4 + i]; + int b1 = coef[1 * 4 + i]; + int c1 = coef[2 * 4 + i]; + int d1 = coef[3 * 4 + i]; + int e1; + a1 += b1; + d1 -= c1; + e1 = (a1 - d1) >> 1; + b1 = e1 - b1; + c1 = e1 - c1; + a1 -= c1; + d1 += b1; + coef[0 * 4 + i] = a1; + coef[1 * 4 + i] = c1; + coef[2 * 4 + i] = d1; + coef[3 * 4 + i] = b1; + } + for (i = 0; i < 4; i++) { + int a1 = coef[i * 4 + 0]; + int b1 = coef[i * 4 + 1]; + int c1 = coef[i * 4 + 2]; + int d1 = coef[i * 4 + 3]; + int e1; + a1 += b1; + d1 -= c1; + e1 = (a1 - d1) >> 1; + b1 = e1 - b1; + c1 = e1 - c1; + a1 -= c1; + d1 += b1; + coef[i * 4 + 0] = a1 * 2; + coef[i * 4 + 1] = c1 * 2; + coef[i * 4 + 2] = d1 * 2; + coef[i * 4 + 3] = b1 * 2; + } +} + +static void check_idct(void) +{ + LOCAL_ALIGNED_16(uint8_t, src, [4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst, [4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst0, [4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst1, [4 * 4]); + LOCAL_ALIGNED_16(int16_t, coef, [4 * 4]); + LOCAL_ALIGNED_16(int16_t, subcoef0, [4 * 4]); + LOCAL_ALIGNED_16(int16_t, subcoef1, [4 * 4]); + VP8DSPContext d; + int dc; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t *block, ptrdiff_t stride); + + ff_vp8dsp_init(&d); + randomize_buffers(src, dst, 4, coef); + + dct4x4(coef); + + for (dc = 0; dc <= 1; dc++) { + void (*idct)(uint8_t *, int16_t *, ptrdiff_t) = dc ? d.vp8_idct_dc_add : d.vp8_idct_add; + + if (check_func(idct, "vp8_idct_%sadd", dc ? "dc_" : "")) { + if (dc) { + memset(subcoef0, 0, 4 * 4 * sizeof(int16_t)); + subcoef0[0] = coef[0]; + } else { + memcpy(subcoef0, coef, 4 * 4 * sizeof(int16_t)); + } + memcpy(dst0, dst, 4 * 4); + memcpy(dst1, dst, 4 * 4); + memcpy(subcoef1, subcoef0, 4 * 4 * sizeof(int16_t)); + // Note, this uses a pixel stride of 4, even though the real decoder uses a stride as a + // multiple of 16. If optimizations want to take advantage of that, this test needs to be + // updated to make it more like the h264dsp tests. + call_ref(dst0, subcoef0, 4); + call_new(dst1, subcoef1, 4); + if (memcmp(dst0, dst1, 4 * 4) || + memcmp(subcoef0, subcoef1, 4 * 4 * sizeof(int16_t))) + fail(); + + bench_new(dst1, subcoef1, 4); + } + } +} + +static void check_idct_dc4(void) +{ + LOCAL_ALIGNED_16(uint8_t, src, [4 * 4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst, [4 * 4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst0, [4 * 4 * 4]); + LOCAL_ALIGNED_16(uint8_t, dst1, [4 * 4 * 4]); + LOCAL_ALIGNED_16(int16_t, coef, [4], [4 * 4]); + LOCAL_ALIGNED_16(int16_t, subcoef0, [4], [4 * 4]); + LOCAL_ALIGNED_16(int16_t, subcoef1, [4], [4 * 4]); + VP8DSPContext d; + int i, chroma; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); + + ff_vp8dsp_init(&d); + + for (chroma = 0; chroma <= 1; chroma++) { + void (*idct4dc)(uint8_t *, int16_t[4][16], ptrdiff_t) = chroma ? d.vp8_idct_dc_add4uv : d.vp8_idct_dc_add4y; + if (check_func(idct4dc, "vp8_idct_dc_add4%s", chroma ? "uv" : "y")) { + ptrdiff_t stride = chroma ? 8 : 16; + int w = chroma ? 2 : 4; + for (i = 0; i < 4; i++) { + int blockx = 4 * (i % w); + int blocky = 4 * (i / w); + randomize_buffers(src + stride * blocky + blockx, dst + stride * blocky + blockx, stride, coef[i]); + dct4x4(coef[i]); + memset(&coef[i][1], 0, 15 * sizeof(int16_t)); + } + + memcpy(dst0, dst, 4 * 4 * 4); + memcpy(dst1, dst, 4 * 4 * 4); + memcpy(subcoef0, coef, 4 * 4 * 4 * sizeof(int16_t)); + memcpy(subcoef1, coef, 4 * 4 * 4 * sizeof(int16_t)); + call_ref(dst0, subcoef0, stride); + call_new(dst1, subcoef1, stride); + if (memcmp(dst0, dst1, 4 * 4 * 4) || + memcmp(subcoef0, subcoef1, 4 * 4 * 4 * sizeof(int16_t))) + fail(); + bench_new(dst1, subcoef1, stride); + } + } + +} + +static void check_luma_dc_wht(void) +{ + LOCAL_ALIGNED_16(int16_t, dc, [4 * 4]); + LOCAL_ALIGNED_16(int16_t, dc0, [4 * 4]); + LOCAL_ALIGNED_16(int16_t, dc1, [4 * 4]); + int16_t block[4][4][16]; + LOCAL_ALIGNED_16(int16_t, block0, [4], [4][16]); + LOCAL_ALIGNED_16(int16_t, block1, [4], [4][16]); + VP8DSPContext d; + int dc_only; + int blockx, blocky; + declare_func_emms(AV_CPU_FLAG_MMX, void, int16_t block[4][4][16], int16_t dc[16]); + + ff_vp8dsp_init(&d); + + for (blocky = 0; blocky < 4; blocky++) { + for (blockx = 0; blockx < 4; blockx++) { + uint8_t src[16], dst[16]; + randomize_buffers(src, dst, 4, block[blocky][blockx]); + + dct4x4(block[blocky][blockx]); + dc[blocky * 4 + blockx] = block[blocky][blockx][0]; + block[blocky][blockx][0] = rnd(); + } + } + wht4x4(dc); + + for (dc_only = 0; dc_only <= 1; dc_only++) { + void (*idct)(int16_t [4][4][16], int16_t [16]) = dc_only ? d.vp8_luma_dc_wht_dc : d.vp8_luma_dc_wht; + + if (check_func(idct, "vp8_luma_dc_wht%s", dc_only ? "_dc" : "")) { + if (dc_only) { + memset(dc0, 0, 16 * sizeof(int16_t)); + dc0[0] = dc[0]; + } else { + memcpy(dc0, dc, 16 * sizeof(int16_t)); + } + memcpy(dc1, dc0, 16 * sizeof(int16_t)); + memcpy(block0, block, 4 * 4 * 16 * sizeof(int16_t)); + memcpy(block1, block, 4 * 4 * 16 * sizeof(int16_t)); + call_ref(block0, dc0); + call_new(block1, dc1); + if (memcmp(block0, block1, 4 * 4 * 16 * sizeof(int16_t)) || + memcmp(dc0, dc1, 16 * sizeof(int16_t))) + fail(); + bench_new(block1, dc1); + } + } +} + +#define SRC_BUF_STRIDE 32 +#define SRC_BUF_SIZE (((size << (size < 16)) + 5) * SRC_BUF_STRIDE) +// The mc subpixel interpolation filter needs the 2 previous pixels in either +// direction, the +1 is to make sure the actual load addresses always are +// unaligned. +#define src (buf + 2 * SRC_BUF_STRIDE + 2 + 1) + +#undef randomize_buffers +#define randomize_buffers() \ + do { \ + int k; \ + for (k = 0; k < SRC_BUF_SIZE; k += 4) { \ + AV_WN32A(buf + k, rnd()); \ + } \ + } while (0) + +static void check_mc(void) +{ + LOCAL_ALIGNED_16(uint8_t, buf, [32 * 32]); + LOCAL_ALIGNED_16(uint8_t, dst0, [16 * 16]); + LOCAL_ALIGNED_16(uint8_t, dst1, [16 * 16]); + VP8DSPContext d; + int type, k, dx, dy; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, uint8_t *, ptrdiff_t, int, int, int); + + ff_vp78dsp_init(&d); + + for (type = 0; type < 2; type++) { + vp8_mc_func (*tab)[3][3] = type ? d.put_vp8_bilinear_pixels_tab : d.put_vp8_epel_pixels_tab; + for (k = 1; k < 8; k++) { + int hsize = k / 3; + int size = 16 >> hsize; + int height = (size << 1) >> (k % 3); + for (dy = 0; dy < 3; dy++) { + for (dx = 0; dx < 3; dx++) { + char str[100]; + if (dx || dy) { + if (type == 0) { + static const char *dx_names[] = { "", "h4", "h6" }; + static const char *dy_names[] = { "", "v4", "v6" }; + snprintf(str, sizeof(str), "epel%d_%s%s", size, dx_names[dx], dy_names[dy]); + } else { + snprintf(str, sizeof(str), "bilin%d_%s%s", size, dx ? "h" : "", dy ? "v" : ""); + } + } else { + snprintf(str, sizeof(str), "pixels%d", size); + } + if (check_func(tab[hsize][dy][dx], "vp8_put_%s", str)) { + int mx, my; + int i; + if (type == 0) { + mx = dx == 2 ? 2 + 2 * (rnd() % 3) : dx == 1 ? 1 + 2 * (rnd() % 4) : 0; + my = dy == 2 ? 2 + 2 * (rnd() % 3) : dy == 1 ? 1 + 2 * (rnd() % 4) : 0; + } else { + mx = dx ? 1 + (rnd() % 7) : 0; + my = dy ? 1 + (rnd() % 7) : 0; + } + randomize_buffers(); + for (i = -2; i <= 3; i++) { + int val = (i == -1 || i == 2) ? 0 : 0xff; + // Set pixels in the first row and column to the maximum pattern, + // to test for potential overflows in the filter. + src[i ] = val; + src[i * SRC_BUF_STRIDE] = val; + } + call_ref(dst0, size, src, SRC_BUF_STRIDE, height, mx, my); + call_new(dst1, size, src, SRC_BUF_STRIDE, height, mx, my); + if (memcmp(dst0, dst1, size * height)) + fail(); + bench_new(dst1, size, src, SRC_BUF_STRIDE, height, mx, my); + } + } + } + } + } +} + +#undef randomize_buffers + +#define setpx(a, b, c) buf[(a) + (b) * jstride] = av_clip_uint8(c) +// Set the pixel to c +/- [0,d] +#define setdx(a, b, c, d) setpx(a, b, c - (d) + (rnd() % ((d) * 2 + 1))) +// Set the pixel to c +/- [d,d+e] (making sure it won't be clipped) +#define setdx2(a, b, o, c, d, e) setpx(a, b, o = c + ((d) + (rnd() % (e))) * (c >= 128 ? -1 : 1)) + +static void randomize_loopfilter_buffers(int lineoff, int str, + int dir, int flim_E, int flim_I, + int hev_thresh, uint8_t *buf, + int force_hev) +{ + uint32_t mask = 0xff; + int off = dir ? lineoff : lineoff * str; + int istride = dir ? 1 : str; + int jstride = dir ? str : 1; + int i; + for (i = 0; i < 8; i += 2) { + // Row 0 will trigger hev for q0/q1, row 2 will trigger hev for p0/p1, + // rows 4 and 6 will not trigger hev. + // force_hev 1 will make sure all rows trigger hev, while force_hev -1 + // makes none of them trigger it. + int idx = off + i * istride, p2, p1, p0, q0, q1, q2; + setpx(idx, 0, q0 = rnd() & mask); + if (i == 0 && force_hev >= 0 || force_hev > 0) + setdx2(idx, 1, q1, q0, hev_thresh + 1, flim_I - hev_thresh - 1); + else + setdx(idx, 1, q1 = q0, hev_thresh); + setdx(idx, 2, q2 = q1, flim_I); + setdx(idx, 3, q2, flim_I); + setdx(idx, -1, p0 = q0, flim_E >> 2); + if (i == 2 && force_hev >= 0 || force_hev > 0) + setdx2(idx, -2, p1, p0, hev_thresh + 1, flim_I - hev_thresh - 1); + else + setdx(idx, -2, p1 = p0, hev_thresh); + setdx(idx, -3, p2 = p1, flim_I); + setdx(idx, -4, p2, flim_I); + } +} + +// Fill the buffer with random pixels +static void fill_loopfilter_buffers(uint8_t *buf, ptrdiff_t stride, int w, int h) +{ + int x, y; + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + buf[y * stride + x] = rnd() & 0xff; +} + +#define randomize_buffers(buf, lineoff, str, force_hev) \ + randomize_loopfilter_buffers(lineoff, str, dir, flim_E, flim_I, hev_thresh, buf, force_hev) + +static void check_loopfilter_16y(void) +{ + LOCAL_ALIGNED_16(uint8_t, base0, [32 + 16 * 16]); + LOCAL_ALIGNED_16(uint8_t, base1, [32 + 16 * 16]); + VP8DSPContext d; + int dir, edge, force_hev; + int flim_E = 20, flim_I = 10, hev_thresh = 7; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int, int, int); + + ff_vp8dsp_init(&d); + + for (dir = 0; dir < 2; dir++) { + int midoff = dir ? 4 * 16 : 4; + int midoff_aligned = dir ? 4 * 16 : 16; + uint8_t *buf0 = base0 + midoff_aligned; + uint8_t *buf1 = base1 + midoff_aligned; + for (edge = 0; edge < 2; edge++) { + void (*func)(uint8_t *, ptrdiff_t, int, int, int) = NULL; + switch (dir << 1 | edge) { + case (0 << 1) | 0: func = d.vp8_h_loop_filter16y; break; + case (1 << 1) | 0: func = d.vp8_v_loop_filter16y; break; + case (0 << 1) | 1: func = d.vp8_h_loop_filter16y_inner; break; + case (1 << 1) | 1: func = d.vp8_v_loop_filter16y_inner; break; + } + if (check_func(func, "vp8_loop_filter16y%s_%s", edge ? "_inner" : "", dir ? "v" : "h")) { + for (force_hev = -1; force_hev <= 1; force_hev++) { + fill_loopfilter_buffers(buf0 - midoff, 16, 16, 16); + randomize_buffers(buf0, 0, 16, force_hev); + randomize_buffers(buf0, 8, 16, force_hev); + memcpy(buf1 - midoff, buf0 - midoff, 16 * 16); + call_ref(buf0, 16, flim_E, flim_I, hev_thresh); + call_new(buf1, 16, flim_E, flim_I, hev_thresh); + if (memcmp(buf0 - midoff, buf1 - midoff, 16 * 16)) + fail(); + } + fill_loopfilter_buffers(buf0 - midoff, 16, 16, 16); + randomize_buffers(buf0, 0, 16, 0); + randomize_buffers(buf0, 8, 16, 0); + bench_new(buf0, 16, flim_E, flim_I, hev_thresh); + } + } + } +} + +static void check_loopfilter_8uv(void) +{ + LOCAL_ALIGNED_16(uint8_t, base0u, [32 + 16 * 16]); + LOCAL_ALIGNED_16(uint8_t, base0v, [32 + 16 * 16]); + LOCAL_ALIGNED_16(uint8_t, base1u, [32 + 16 * 16]); + LOCAL_ALIGNED_16(uint8_t, base1v, [32 + 16 * 16]); + VP8DSPContext d; + int dir, edge, force_hev; + int flim_E = 20, flim_I = 10, hev_thresh = 7; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, uint8_t *, ptrdiff_t, int, int, int); + + ff_vp8dsp_init(&d); + + for (dir = 0; dir < 2; dir++) { + int midoff = dir ? 4 * 16 : 4; + int midoff_aligned = dir ? 4 * 16 : 16; + uint8_t *buf0u = base0u + midoff_aligned; + uint8_t *buf0v = base0v + midoff_aligned; + uint8_t *buf1u = base1u + midoff_aligned; + uint8_t *buf1v = base1v + midoff_aligned; + for (edge = 0; edge < 2; edge++) { + void (*func)(uint8_t *, uint8_t *, ptrdiff_t, int, int, int) = NULL; + switch (dir << 1 | edge) { + case (0 << 1) | 0: func = d.vp8_h_loop_filter8uv; break; + case (1 << 1) | 0: func = d.vp8_v_loop_filter8uv; break; + case (0 << 1) | 1: func = d.vp8_h_loop_filter8uv_inner; break; + case (1 << 1) | 1: func = d.vp8_v_loop_filter8uv_inner; break; + } + if (check_func(func, "vp8_loop_filter8uv%s_%s", edge ? "_inner" : "", dir ? "v" : "h")) { + for (force_hev = -1; force_hev <= 1; force_hev++) { + fill_loopfilter_buffers(buf0u - midoff, 16, 16, 16); + fill_loopfilter_buffers(buf0v - midoff, 16, 16, 16); + randomize_buffers(buf0u, 0, 16, force_hev); + randomize_buffers(buf0v, 0, 16, force_hev); + memcpy(buf1u - midoff, buf0u - midoff, 16 * 16); + memcpy(buf1v - midoff, buf0v - midoff, 16 * 16); + + call_ref(buf0u, buf0v, 16, flim_E, flim_I, hev_thresh); + call_new(buf1u, buf1v, 16, flim_E, flim_I, hev_thresh); + if (memcmp(buf0u - midoff, buf1u - midoff, 16 * 16) || + memcmp(buf0v - midoff, buf1v - midoff, 16 * 16)) + fail(); + } + fill_loopfilter_buffers(buf0u - midoff, 16, 16, 16); + fill_loopfilter_buffers(buf0v - midoff, 16, 16, 16); + randomize_buffers(buf0u, 0, 16, 0); + randomize_buffers(buf0v, 0, 16, 0); + bench_new(buf0u, buf0v, 16, flim_E, flim_I, hev_thresh); + } + } + } +} + +static void check_loopfilter_simple(void) +{ + LOCAL_ALIGNED_16(uint8_t, base0, [32 + 16 * 16]); + LOCAL_ALIGNED_16(uint8_t, base1, [32 + 16 * 16]); + VP8DSPContext d; + int dir; + int flim_E = 20, flim_I = 30, hev_thresh = 0; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int); + + ff_vp8dsp_init(&d); + + for (dir = 0; dir < 2; dir++) { + int midoff = dir ? 4 * 16 : 4; + int midoff_aligned = dir ? 4 * 16 : 16; + uint8_t *buf0 = base0 + midoff_aligned; + uint8_t *buf1 = base1 + midoff_aligned; + void (*func)(uint8_t *, ptrdiff_t, int) = dir ? d.vp8_v_loop_filter_simple : d.vp8_h_loop_filter_simple; + if (check_func(func, "vp8_loop_filter_simple_%s", dir ? "v" : "h")) { + fill_loopfilter_buffers(buf0 - midoff, 16, 16, 16); + randomize_buffers(buf0, 0, 16, -1); + randomize_buffers(buf0, 8, 16, -1); + memcpy(buf1 - midoff, buf0 - midoff, 16 * 16); + call_ref(buf0, 16, flim_E); + call_new(buf1, 16, flim_E); + if (memcmp(buf0 - midoff, buf1 - midoff, 16 * 16)) + fail(); + bench_new(buf0, 16, flim_E); + } + } +} + +void checkasm_check_vp8dsp(void) +{ + check_idct(); + check_idct_dc4(); + check_luma_dc_wht(); + report("idct"); + check_mc(); + report("mc"); + check_loopfilter_16y(); + check_loopfilter_8uv(); + check_loopfilter_simple(); + report("loopfilter"); +} diff --git a/tests/checkasm/vp9dsp.c b/tests/checkasm/vp9dsp.c new file mode 100644 index 0000000..dd37077 --- /dev/null +++ b/tests/checkasm/vp9dsp.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015 Ronald S. Bultje + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Libav; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +#include "libavcodec/vp9.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; + +#define BIT_DEPTH 8 +#define SIZEOF_PIXEL ((BIT_DEPTH + 7) / 8) +#define DST_BUF_SIZE (size * size * SIZEOF_PIXEL) +#define SRC_BUF_STRIDE 72 +#define SRC_BUF_SIZE ((size + 7) * SRC_BUF_STRIDE * SIZEOF_PIXEL) +#define src (buf + 3 * SIZEOF_PIXEL * (SRC_BUF_STRIDE + 1)) + +#define randomize_buffers() \ + do { \ + uint32_t mask = pixel_mask[(BIT_DEPTH - 8) >> 1]; \ + int k; \ + for (k = 0; k < SRC_BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf + k, r); \ + } \ + if (op == 1) { \ + for (k = 0; k < DST_BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(dst0 + k, r); \ + AV_WN32A(dst1 + k, r); \ + } \ + } \ + } while (0) + +static void check_mc(void) +{ + static const char *const filter_names[4] = { + "8tap_smooth", "8tap_regular", "8tap_sharp", "bilin" + }; + static const char *const subpel_names[2][2] = { { "", "h" }, { "v", "hv" } }; + static const char *const op_names[2] = { "put", "avg" }; + + LOCAL_ALIGNED_32(uint8_t, buf, [72 * 72 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst0, [64 * 64 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst1, [64 * 64 * 2]); + char str[256]; + VP9DSPContext dsp; + int op, hsize, filter, dx, dy; + + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, + void, uint8_t *dst, const uint8_t *ref, + ptrdiff_t dst_stride, ptrdiff_t ref_stride, + int h, int mx, int my); + + for (op = 0; op < 2; op++) { + ff_vp9dsp_init(&dsp); + for (hsize = 0; hsize < 5; hsize++) { + int size = 64 >> hsize; + + for (filter = 0; filter < 4; filter++) { + for (dx = 0; dx < 2; dx++) { + for (dy = 0; dy < 2; dy++) { + if (dx || dy) { + snprintf(str, sizeof(str), "%s_%s_%d%s", op_names[op], + filter_names[filter], size, + subpel_names[dy][dx]); + } else { + snprintf(str, sizeof(str), "%s%d", op_names[op], size); + } + if (check_func(dsp.mc[hsize][filter][op][dx][dy], + "vp9_%s", str)) { + int mx = dx ? 1 + (rnd() % 14) : 0; + int my = dy ? 1 + (rnd() % 14) : 0; + randomize_buffers(); + call_ref(dst0, src, + size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + call_new(dst1, src, + size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + if (memcmp(dst0, dst1, DST_BUF_SIZE)) + fail(); + + // SIMD implementations for each filter of subpel + // functions are identical + if (filter >= 1 && filter <= 2) continue; + + bench_new(dst1, src, size * SIZEOF_PIXEL, + SRC_BUF_STRIDE * SIZEOF_PIXEL, + size, mx, my); + } + } + } + } + } + } + report("mc"); +} + +void checkasm_check_vp9dsp(void) +{ + check_mc(); +} diff --git a/tests/checkasm/x86/Makefile b/tests/checkasm/x86/Makefile new file mode 100644 index 0000000..0254c61 --- /dev/null +++ b/tests/checkasm/x86/Makefile @@ -0,0 +1,6 @@ +CHECKASMOBJS-$(HAVE_YASM) += x86/checkasm.o + +tests/checkasm/x86/%.o: tests/checkasm/x86/%.asm + $(DEPYASM) $(YASMFLAGS) -I $( $(@:.o=.d) + $(YASM) $(YASMFLAGS) -I $( $3) r = 1; r" | bc + awk "BEGIN { v = $1 - $2; printf ((v < 0 ? -v : v) > $3) }" } do_tiny_psnr(){ @@ -76,7 +77,7 @@ probefmt(){ } avconv(){ - dec_opts="-threads $threads -thread_type $thread_type" + dec_opts="-hwaccel $hwaccel -threads $threads -thread_type $thread_type" avconv_args="-nostats -cpuflags $cpuflags" for arg in $@; do [ x${arg} = x-i ] && avconv_args="${avconv_args} ${dec_opts}" @@ -159,14 +160,14 @@ video_filter(){ raw_src="${target_path}/tests/vsynth1/%02d.pgm" printf '%-20s' $label avconv $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src \ - $FLAGS $ENC_OPTS -vf "$filters" -vcodec rawvideo $* -f nut md5: + $FLAGS $ENC_OPTS -vf "$filters" -vcodec rawvideo -frames:v 5 $* -f nut md5: } pixfmts(){ filter=${test#filter-pixfmts-} filter_args=$1 - showfiltfmts="$target_exec $target_path/libavfilter/filtfmts-test" + showfiltfmts="$target_exec $target_path/libavfilter/tests/filtfmts" exclude_fmts=${outfile}${filter}_exclude_fmts out_fmts=${outfile}${filter}_out_fmts @@ -175,12 +176,15 @@ pixfmts(){ $showfiltfmts scale | awk -F '[ \r]' '/^OUTPUT/{ print $3 }' | sort | comm -23 - $exclude_fmts >$out_fmts pix_fmts=$($showfiltfmts $filter | awk -F '[ \r]' '/^INPUT/{ print $3 }' | sort | comm -12 - $out_fmts) + + outertest=$test for pix_fmt in $pix_fmts; do test=$pix_fmt - video_filter "format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt + video_filter "format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt -frames:v 1 done rm $exclude_fmts $out_fmts + test=$outertest } mkdir -p "$outdir" @@ -210,7 +214,13 @@ else err=1 fi -echo "${test}:${sig:-$err}:$($base64 <$cmpfile):$($base64 <$errfile)" >$repfile +if [ $err -eq 0 ]; then + unset cmpo erro +else + cmpo="$($base64 <$cmpfile)" + erro="$($base64 <$errfile)" +fi +echo "${test}:${sig:-$err}:$cmpo:$erro" >$repfile if test $err != 0 && test $gen != "no" ; then echo "GEN $ref" diff --git a/tests/fate.sh b/tests/fate.sh index af0f6c0..b8ee1ae 100755 --- a/tests/fate.sh +++ b/tests/fate.sh @@ -37,7 +37,7 @@ checkout(){ update()( cd ${src} || return case "$repo" in - git:*) git fetch --force; git reset --hard "origin/$branch" ;; + git:*) git fetch --quiet --force; git reset --quiet --hard "origin/$branch" ;; esac ) @@ -49,6 +49,7 @@ configure()( --enable-gpl \ ${arch:+--arch=$arch} \ ${cpu:+--cpu="$cpu"} \ + ${toolchain:+--toolchain="$toolchain"} \ ${cross_prefix:+--cross-prefix="$cross_prefix"} \ ${as:+--as="$as"} \ ${cc:+--cc="$cc"} \ @@ -82,7 +83,7 @@ clean(){ report(){ date=$(date -u +%Y%m%d%H%M%S) echo "fate:1:${date}:${slot}:${version}:$1:$2:${branch}:${comment}" >report - cat ${build}/config.fate ${build}/tests/data/fate/*.rep >>report + cat ${build}/config.fate ${build}/tests/data/fate/*.rep >>report 2>/dev/null test -n "$fate_recv" && $tar report *.log | gzip | $fate_recv } diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak index b3f07cb..63ea06c 100644 --- a/tests/fate/aac.mak +++ b/tests/fate/aac.mak @@ -66,6 +66,10 @@ FATE_AAC += fate-aac-er_eld2000np_48_ep0 fate-aac-er_eld2000np_48_ep0: CMD = pcm -i $(TARGET_SAMPLES)/aac/er_eld2000np_48_ep0.mp4 fate-aac-er_eld2000np_48_ep0: REF = $(SAMPLES)/aac/er_eld2000np_48_ep0.s16 +FATE_AAC += fate-aac-er_eld2100np_48_ep0 +fate-aac-er_eld2100np_48_ep0: CMD = pcm -i $(TARGET_SAMPLES)/aac/er_eld2100np_48_ep0.mp4 +fate-aac-er_eld2100np_48_ep0: REF = $(SAMPLES)/aac/er_eld2100np_48.s16 + fate-aac-ct%: CMD = pcm -i $(TARGET_SAMPLES)/aac/CT_DecoderCheck/$(@:fate-aac-ct-%=%) fate-aac-ct%: REF = $(SAMPLES)/aac/CT_DecoderCheck/aacPlusv2.wav diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index 3841240..fee4567 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -6,12 +6,14 @@ FATE_AC3 += fate-ac3-4.0 fate-ac3-4.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0: REF = $(SAMPLES)/ac3/millers_crossing_4.0_v2.pcm +#request_channel_layout 4 -> front channel FATE_AC3 += fate-ac3-4.0-downmix-mono -fate-ac3-4.0-downmix-mono: CMD = pcm -request_channels 1 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm +#request_channel_layout 3 -> left channel + right channel FATE_AC3 += fate-ac3-4.0-downmix-stereo -fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channels 2 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-stereo: REF = $(SAMPLES)/ac3/millers_crossing_4.0_stereo_v2.pcm FATE_AC3 += fate-ac3-5.1 @@ -19,11 +21,11 @@ fate-ac3-5.1: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-mono -fate-ac3-5.1-downmix-mono: CMD = pcm -request_channels 1 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-stereo -fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channels 2 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_EAC3 += fate-eac3-1 diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak index d6ca58e..cf11e9d 100644 --- a/tests/fate/audio.mak +++ b/tests/fate/audio.mak @@ -16,13 +16,25 @@ fate-binkaudio: $(FATE_BINKAUDIO-yes) FATE_SAMPLES_AVCONV-$(call DEMDEC, BMV, BMV_AUDIO) += fate-bmv-audio fate-bmv-audio: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -vn +FATE_DCA-$(CONFIG_MPEGTS_DEMUXER) += fate-dca-core +fate-dca-core: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts +fate-dca-core: CMP = oneoff +fate-dca-core: REF = $(SAMPLES)/dts/dts.pcm + +FATE_DCA-$(CONFIG_DTS_DEMUXER) += fate-dca-xll +fate-dca-xll: CMD = pcm -disable_xll 0 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts +fate-dca-xll: CMP = oneoff +fate-dca-xll: REF = $(SAMPLES)/dts/master_audio_7.1_24bit_2.pcm + +FATE_SAMPLES_AVCONV-$(CONFIG_DCA_DECODER) += $(FATE_DCA-yes) +fate-dca: $(FATE_DCA-yes) + FATE_SAMPLES_AVCONV-$(call DEMDEC, DSICIN, DSICINAUDIO) += fate-delphine-cin-audio fate-delphine-cin-audio: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -vn -FATE_SAMPLES_AVCONV-$(call DEMDEC, MPEGTS, DCA) += fate-dts -fate-dts: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts -fate-dts: CMP = oneoff -fate-dts: REF = $(SAMPLES)/dts/dts.pcm +FATE_SAMPLES_AVCONV-$(call DEMDEC, DSS, DSS_SP) += fate-dss-lp fate-dss-sp +fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30 +fate-dss-sp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/sp.dss -frames 30 FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, IMC) += fate-imc fate-imc: CMD = pcm -i $(TARGET_SAMPLES)/imc/imc.avi diff --git a/tests/fate/canopus.mak b/tests/fate/canopus.mak new file mode 100644 index 0000000..1f24a4c --- /dev/null +++ b/tests/fate/canopus.mak @@ -0,0 +1,34 @@ +#lossless +FATE_CANOPUS_CLLC += fate-canopus-cllc-argb +fate-canopus-cllc-argb: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-argb.avi + +FATE_CANOPUS_CLLC += fate-canopus-cllc-rgb +fate-canopus-cllc-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-rgb.avi + +FATE_CANOPUS_CLLC += fate-canopus-cllc-yuy2-noblock +fate-canopus-cllc-yuy2-noblock: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-yuy2-noblock.avi + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, CLLC) += $(FATE_CANOPUS_CLLC) +fate-canopus-cllc: $(FATE_CANOPUS_CLLC) + +#lossy +FATE_CANOPUS_HQ_HQA += fate-canopus-hq_hqa-hq +fate-canopus-hq_hqa-hq: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hq.avi + +FATE_CANOPUS_HQ_HQA += fate-canopus-hq_hqa-hqa +fate-canopus-hq_hqa-hqa: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqa.avi + +FATE_CANOPUS_HQ_HQA += fate-canopus-hq_hqa-inter +fate-canopus-hq_hqa-inter: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hq25i.avi + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, HQ_HQA) += $(FATE_CANOPUS_HQ_HQA) +fate-canopus-hq_hqa: $(FATE_CANOPUS_HQ_HQA) + +FATE_CANOPUS_HQX += fate-canopus-hqx422 +fate-canopus-hqx422: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422.avi -pix_fmt yuv422p16be -an + +FATE_CANOPUS_HQX += fate-canopus-hqx422a +fate-canopus-hqx422a: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422a.avi -pix_fmt yuv422p16be -an + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, HQX) += $(FATE_CANOPUS_HQX) +fate-canopus-hqx: $(FATE_CANOPUS_HQX) diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak new file mode 100644 index 0000000..daefe69 --- /dev/null +++ b/tests/fate/checkasm.mak @@ -0,0 +1,5 @@ +fate-checkasm: tests/checkasm/checkasm$(EXESUF) +fate-checkasm: CMD = run tests/checkasm/checkasm +fate-checkasm: REF = /dev/null + +FATE += fate-checkasm diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 2446b90..d529341 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -1,4 +1,4 @@ -FATE_SAMPLES_AVCONV-$(CONFIG_AAC_DEMUXER) += fate-adts-demux +FATE_SAMPLES_AVCONV-$(call DEMDEC, AAC, AAC) += fate-adts-demux fate-adts-demux: CMD = crc -i $(TARGET_SAMPLES)/aac/ct_faac-adts.aac -acodec copy FATE_SAMPLES_AVCONV-$(CONFIG_AEA_DEMUXER) += fate-aea-demux @@ -16,10 +16,10 @@ fate-cdxl-demux: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -vcodec co FATE_SAMPLES_AVCONV-$(CONFIG_DAUD_DEMUXER) += fate-d-cinema-demux fate-d-cinema-demux: CMD = framecrc -i $(TARGET_SAMPLES)/d-cinema/THX_Science_FLT_1920-partial.302 -acodec copy -FATE_SAMPLES_AVCONV-$(CONFIG_IV8_DEMUXER) += fate-iv8-demux +FATE_SAMPLES_AVCONV-$(call ALLYES, IV8_DEMUXER MPEG4VIDEO_PARSER) += fate-iv8-demux fate-iv8-demux: CMD = framecrc -i $(TARGET_SAMPLES)/iv8/zzz-partial.mpg -vcodec copy -FATE_SAMPLES_AVCONV-$(CONFIG_LMLM4_DEMUXER) += fate-lmlm4-demux +FATE_SAMPLES_AVCONV-$(call ALLYES, LMLM4_DEMUXER MPEG4VIDEO_PARSER) += fate-lmlm4-demux fate-lmlm4-demux: CMD = framecrc -i $(TARGET_SAMPLES)/lmlm4/LMLM4_CIFat30fps.divx -t 3 -acodec copy -vcodec copy FATE_SAMPLES_AVCONV-$(CONFIG_XA_DEMUXER) += fate-maxis-xa @@ -28,10 +28,10 @@ fate-maxis-xa: CMD = framecrc -i $(TARGET_SAMPLES)/maxis-xa/SC2KBUG.XA -frames:a FATE_SAMPLES_AVCONV-$(CONFIG_MTV_DEMUXER) += fate-mtv fate-mtv: CMD = framecrc -i $(TARGET_SAMPLES)/mtv/comedian_auto-partial.mtv -c copy -FATE_SAMPLES_AVCONV-$(CONFIG_MXF_DEMUXER) += fate-mxf-demux +FATE_SAMPLES_AVCONV-$(call DEMDEC, MXF, MPEG4) += fate-mxf-demux fate-mxf-demux: CMD = framecrc -i $(TARGET_SAMPLES)/mxf/C0023S01.mxf -acodec copy -vcodec copy -FATE_SAMPLES_AVCONV-$(CONFIG_NC_DEMUXER) += fate-nc-demux +FATE_SAMPLES_AVCONV-$(call ALLYES, NC_DEMUXER MPEG4VIDEO_PARSER) += fate-nc-demux fate-nc-demux: CMD = framecrc -i $(TARGET_SAMPLES)/nc-camera/nc-sample-partial -vcodec copy FATE_SAMPLES_AVCONV-$(CONFIG_NSV_DEMUXER) += fate-nsv-demux @@ -61,7 +61,7 @@ fate-smjpeg-demux: CMD = framecrc -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -c co FATE_SAMPLES_AVCONV-$(CONFIG_WSAUD_DEMUXER) += fate-westwood-aud fate-westwood-aud: CMD = framecrc -i $(TARGET_SAMPLES)/westwood-aud/excellent.aud -c copy -FATE_SAMPLES_AVCONV-$(CONFIG_WTV_DEMUXER) += fate-wtv-demux +FATE_SAMPLES_AVCONV-$(call ALLYES, WTV_DEMUXER MPEGVIDEO_PARSER) += fate-wtv-demux fate-wtv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/wtv/law-and-order-partial.wtv -vcodec copy -acodec copy FATE_SAMPLES_AVCONV-$(CONFIG_XMV_DEMUXER) += fate-xmv-demux diff --git a/tests/fate/fft.mak b/tests/fate/fft.mak index d2a3904..3360a07 100644 --- a/tests/fate/fft.mak +++ b/tests/fate/fft.mak @@ -1,8 +1,8 @@ define DEF_FFT -FATE_FFT-$(CONFIG_DCT) += fate-dct1d-$(1) fate-idct1d-$(1) -FATE_FFT-$(CONFIG_FFT) += fate-fft-$(1) fate-ifft-$(1) -FATE_FFT-$(CONFIG_MDCT) += fate-mdct-$(1) fate-imdct-$(1) -FATE_FFT-$(CONFIG_RDFT) += fate-rdft-$(1) fate-irdft-$(1) +FATE_DCT-$(CONFIG_DCT) += fate-dct1d-$(1) fate-idct1d-$(1) +FATE_FFT-$(CONFIG_FFT) += fate-fft-$(1) fate-ifft-$(1) +FATE_MDCT-$(CONFIG_MDCT) += fate-mdct-$(1) fate-imdct-$(1) +FATE_RDFT-$(CONFIG_RDFT) += fate-rdft-$(1) fate-irdft-$(1) fate-fft-$(N): ARGS = -n$(1) fate-ifft-$(N): ARGS = -n$(1) -i @@ -16,14 +16,19 @@ endef $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT,$(N)))) +fate-dct-float: $(FATE_DCT-yes) fate-fft-float: $(FATE_FFT-yes) -$(FATE_FFT-yes): libavcodec/fft-test$(EXESUF) -$(FATE_FFT-yes): CMD = run libavcodec/fft-test $(CPUFLAGS:%=-c%) $(ARGS) -$(FATE_FFT-yes): REF = /dev/null +fate-mdct-float: $(FATE_MDCT-yes) +fate-rdft-float: $(FATE_RDFT-yes) + +FATE_FFT_ALL = $(FATE_DCT-yes) $(FATE_FFT-yes) $(FATE_MDCT-yes) $(FATE_RDFT-yes) + +$(FATE_FFT_ALL): libavcodec/tests/fft$(EXESUF) +$(FATE_FFT_ALL): CMD = run libavcodec/tests/fft $(CPUFLAGS:%=-c%) $(ARGS) define DEF_FFT_FIXED -FATE_FFT_FIXED-$(CONFIG_FFT) += fate-fft-fixed-$(1) fate-ifft-fixed-$(1) -FATE_FFT_FIXED-$(CONFIG_MDCT) += fate-mdct-fixed-$(1) fate-imdct-fixed-$(1) +FATE_FFT_FIXED-$(CONFIG_FFT) += fate-fft-fixed-$(1) fate-ifft-fixed-$(1) +FATE_MDCT_FIXED-$(CONFIG_MDCT) += fate-mdct-fixed-$(1) fate-imdct-fixed-$(1) fate-fft-fixed-$(1): ARGS = -n$(1) fate-ifft-fixed-$(1): ARGS = -n$(1) -i @@ -34,9 +39,19 @@ endef $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT_FIXED,$(N)))) fate-fft-fixed: $(FATE_FFT_FIXED-yes) -$(FATE_FFT_FIXED-yes): libavcodec/fft-fixed-test$(EXESUF) -$(FATE_FFT_FIXED-yes): CMD = run libavcodec/fft-fixed-test $(CPUFLAGS:%=-c%) $(ARGS) -$(FATE_FFT_FIXED-yes): REF = /dev/null +fate-mdct-fixed: $(FATE_MDCT_FIXED-yes) + +FATE_FFT_FIXED_ALL = $(FATE_FFT_FIXED-yes) $(FATE_MDCT_FIXED-yes) + +$(FATE_FFT_FIXED_ALL): libavcodec/tests/fft-fixed$(EXESUF) +$(FATE_FFT_FIXED_ALL): CMD = run libavcodec/tests/fft-fixed $(CPUFLAGS:%=-c%) $(ARGS) + +$(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL): REF = /dev/null + +fate-dct: fate-dct-float +fate-fft: fate-fft-float fate-fft-fixed +fate-mdct: fate-mdct-float fate-mdct-fixed +fate-rdft: fate-rdft-float -FATE-$(CONFIG_AVCODEC) += $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) -fate-fft: $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) +FATE-$(CONFIG_AVCODEC) += $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) +fate-fft-all: $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 42fb063..d931548 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -160,7 +160,7 @@ fate-filter-pixfmts-scale: CMD = pixfmts "200:100" FATE_FILTER_PIXFMTS += fate-filter-pixfmts-vflip fate-filter-pixfmts-vflip: CMD = pixfmts -$(FATE_FILTER_PIXFMTS): libavfilter/filtfmts-test$(EXESUF) +$(FATE_FILTER_PIXFMTS): libavfilter/tests/filtfmts$(EXESUF) FATE_FILTER_VSYNTH-$(CONFIG_FORMAT_FILTER) += $(FATE_FILTER_PIXFMTS) diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index 34d03bf..ff1dd15 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -180,11 +180,27 @@ FATE_H264_REINIT_TESTS := large_420_8-to-small_420_8 \ FATE_H264 := $(FATE_H264:%=fate-h264-conformance-%) \ $(FATE_H264_REINIT_TESTS:%=fate-h264-reinit-%) \ fate-h264-extreme-plane-pred \ + fate-h264-intra-refresh-recovery \ fate-h264-lossless \ FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264) FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-crop-to-container FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-interlace-crop + +# this sample has invalid reference list modification, but decodes fine +# by using a previous ref frame instead of a missing one +FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-invalid-ref-mod + +# this sample gives an explicit size for a single NAL unit, but contains +# several NAL units +FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-mixed-nal-coding + +# this sample has invalid extradata that is not escaped +FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-unescaped-extradata + +# this sample contains field-coded frames, with both fields in a single packet +FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-twofields-packet + FATE_H264-$(call ALLYES, MOV_DEMUXER H264_MP4TOANNEXB_BSF) += fate-h264-bsf-mp4toannexb FATE_H264-$(call DEMDEC, MATROSKA, H264) += fate-h264-direct-bff @@ -367,9 +383,14 @@ fate-h264-conformance-sva_nl2_e: CMD = framecrc -i $(TARGET_SAM fate-h264-bsf-mp4toannexb: CMD = md5 -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 -vcodec copy -bsf h264_mp4toannexb -f h264 fate-h264-crop-to-container: CMD = framemd5 -i $(TARGET_SAMPLES)/h264/crop-to-container-dims-canon.mov +fate-h264-direct-bff: CMD = framecrc -i $(TARGET_SAMPLES)/h264/direct-bff.mkv fate-h264-extreme-plane-pred: CMD = framemd5 -i $(TARGET_SAMPLES)/h264/extreme-plane-pred.h264 fate-h264-interlace-crop: CMD = framecrc -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 -vframes 3 +fate-h264-intra-refresh-recovery: CMD = framecrc -i $(TARGET_SAMPLES)/h264/intra_refresh.h264 -frames:v 10 +fate-h264-invalid-ref-mod: CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le fate-h264-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/h264/lossless.h264 -fate-h264-direct-bff: CMD = framecrc -i $(TARGET_SAMPLES)/h264/direct-bff.mkv +fate-h264-mixed-nal-coding: CMD = framecrc -i $(TARGET_SAMPLES)/h264/mixed-nal-coding.mp4 +fate-h264-twofields-packet: CMD = framecrc -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -an -frames 30 +fate-h264-unescaped-extradata: CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10 fate-h264-reinit-%: CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf format=yuv444p10le,scale=w=352:h=288 diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 9afe717..fc4ce23 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -155,6 +155,9 @@ endef $(foreach N,$(HEVC_SAMPLES),$(eval $(call FATE_HEVC_TEST,$(N)))) $(foreach N,$(HEVC_SAMPLES_10BIT),$(eval $(call FATE_HEVC_TEST_10BIT,$(N)))) +fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc +FATE_HEVC += fate-hevc-paramchange-yuv420p-yuv420p10 + FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += $(FATE_HEVC) FATE_SAMPLES_AVCONV += $(FATE_HEVC-yes) diff --git a/tests/fate/image.mak b/tests/fate/image.mak index f91ee69..83fa71a 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -30,9 +30,73 @@ fate-brenderpix: $(FATE_BRENDERPIX-yes) FATE_SAMPLES_AVCONV-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP) += fate-bmpparser fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/libav_4x_concat.bmp -pix_fmt rgb24 +define FATE_IMGSUITE_DDS +FATE_DDS += fate-dds-$(1) +fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/libav_$(1).dds $(DDS_OPTS_$(1)) +endef + +DDS_OPTS_pal = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba +DDS_OPTS_pal-ati = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba +DDS_FMT = alpha8 \ + argb \ + argb-aexp \ + dx10-bc1 \ + dx10-bc1a \ + dx10-bc2 \ + dx10-bc3 \ + dx10-bc4 \ + dx10-bc5 \ + dxt1 \ + dxt1a \ + dxt1-normalmap \ + dxt2 \ + dxt3 \ + dxt4 \ + dxt5 \ + dxt5-aexp \ + dxt5-normalmap \ + dxt5-normalmap-ati \ + dxt5-rbxg \ + dxt5-rgxb \ + dxt5-rxbg \ + dxt5-rxgb \ + dxt5-xgbr \ + dxt5-xgxr \ + dxt5-xrbg \ + dxt5-ycocg \ + dxt5-ycocg-scaled \ + monob \ + pal \ + pal-ati \ + rgb1555 \ + rgb16 \ + rgb24 \ + rgb555 \ + rgba \ + rgtc1s \ + rgtc1u \ + rgtc2s \ + rgtc2u \ + rgtc2u-xy \ + uyvy \ + xbgr \ + xrgb \ + y \ + ya \ + ycocg \ + yuyv +$(foreach FMT,$(DDS_FMT),$(eval $(call FATE_IMGSUITE_DDS,$(FMT)))) + +FATE_DDS-$(call DEMDEC, IMAGE2, DDS) += $(FATE_DDS) +FATE_SAMPLES_AVCONV += $(FATE_DDS-yes) +fate-dds: $(FATE_DDS-yes) + FATE_SAMPLES_AVCONV-$(call DEMDEC, IMAGE2, DPX) += fate-dpx fate-dpx: CMD = framecrc -i $(TARGET_SAMPLES)/dpx/lighthouse_rgb48.dpx +FATE_SAMPLES_AVCONV-$(call PARSERDEMDEC, DPX, IMAGE2PIPE, DPX) += fate-dpxparser +fate-dpxparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/dpx/libav_4x_concat.dpx -sws_flags +accurate_rnd+bitexact + FATE_EXR += fate-exr-slice-raw fate-exr-slice-raw: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_raw.exr -pix_fmt rgba64le @@ -53,8 +117,11 @@ FATE_EXR-$(call DEMDEC, IMAGE2, EXR) += $(FATE_EXR) FATE_SAMPLES_AVCONV += $(FATE_EXR-yes) fate-exr: $(FATE_EXR-yes) +FATE_SAMPLES_AVCONV-$(call DEMDEC, IMAGE2, QDRAW) += fate-pict +fate-pict: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/TRU256.PCT -pix_fmt rgb24 + FATE_SAMPLES_AVCONV-$(call DEMDEC, IMAGE2, PICTOR) += fate-pictor -fate-pictor: CMD = framecrc -i $(TARGET_SAMPLES)/pictor/MFISH.PIC -pix_fmt rgb24 +fate-pictor: CMD = framecrc -c pictor -i $(TARGET_SAMPLES)/pictor/MFISH.PIC -pix_fmt rgb24 FATE_SAMPLES_AVCONV-$(call PARSERDEMDEC, PNG, IMAGE2PIPE, PNG) += fate-pngparser fate-pngparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/png1/libav_4x_concat.png -pix_fmt rgba @@ -74,35 +141,16 @@ fate-png: $(FATE_PNG-yes) FATE_SAMPLES_AVCONV-$(call DEMDEC, IMAGE2, PTX) += fate-ptx fate-ptx: CMD = framecrc -i $(TARGET_SAMPLES)/ptx/_113kw_pic.ptx -pix_fmt rgb24 -FATE_SGI += fate-sgi-gray -fate-sgi-gray: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_gray.sgi -pix_fmt gray - -FATE_SGI += fate-sgi-gray16 -fate-sgi-gray16: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_gray16.sgi -pix_fmt gray16le - -FATE_SGI += fate-sgi-rgb24 -fate-sgi-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_rgb24.sgi -pix_fmt rgb24 - -FATE_SGI += fate-sgi-rgb24-rle -fate-sgi-rgb24-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/uvmap_rgb24_rle.sgi -pix_fmt rgb24 - -FATE_SGI += fate-sgi-rgb48 -fate-sgi-rgb48: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_rgb48.sgi -pix_fmt rgb48be - -FATE_SGI += fate-sgi-rgb48-rle -fate-sgi-rgb48-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/uvmap_rgb48_rle.sgi -pix_fmt rgb48be - -FATE_SGI += fate-sgi-rgba -fate-sgi-rgba: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_rgba.sgi -pix_fmt rgba - -FATE_SGI += fate-sgi-rgba64 -fate-sgi-rgba64: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/vulap_rgba64.sgi -pix_fmt rgba64be +define FATE_IMGSUITE_SGI +FATE_SGI += fate-sgi-$(1) fate-sgi-$(1)-rle +fate-sgi-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/sgi/libav_$(1).sgi -sws_flags +accurate_rnd+bitexact +fate-sgi-$(1)-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/libav_$(1)_rle.sgi -sws_flags +accurate_rnd+bitexact +endef -FATE_SGI += fate-sgi-rgba64-rle -fate-sgi-rgba64-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sgi/maya_rgba64_rle.sgi -pix_fmt rgba64be +SGI_COLORSPACES = gray8 gray16 rgb24 rgb48 rgba rgba64 +$(foreach CLSP,$(SGI_COLORSPACES),$(eval $(call FATE_IMGSUITE_SGI,$(CLSP)))) FATE_SGI-$(call DEMDEC, IMAGE2, SGI) += $(FATE_SGI) - FATE_SAMPLES_AVCONV += $(FATE_SGI-yes) fate-sgi: $(FATE_SGI-yes) @@ -175,6 +223,9 @@ FATE_TIFF-$(call DEMDEC, IMAGE2, TIFF) += $(FATE_TIFF) FATE_SAMPLES_AVCONV += $(FATE_TIFF-yes) fate-tiff: $(FATE_TIFF-yes) +FATE_SAMPLES_AVCONV-$(call DEMDEC, IMAGE2, WEBP) += fate-webp +fate-webp: CMD = framecrc -i $(TARGET_SAMPLES)/webp/image_small.webp + FATE_XBM += fate-xbm10 fate-xbm10: CMD = framecrc -i $(TARGET_SAMPLES)/xbm/xl.xbm diff --git a/tests/fate/indeo.mak b/tests/fate/indeo.mak index e725a6b..bb3c154 100644 --- a/tests/fate/indeo.mak +++ b/tests/fate/indeo.mak @@ -1,12 +1,21 @@ -FATE_INDEO-$(call DEMDEC, AVI, INDEO2) += fate-indeo2 -fate-indeo2: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/VPAR0026.AVI +FATE_INDEO2 += fate-indeo2-delta +fate-indeo2-delta: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/ISKATE.AVI -an -FATE_INDEO-$(call DEMDEC, MOV, INDEO3) += fate-indeo3 -fate-indeo3: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/cubes.mov +FATE_INDEO2 += fate-indeo2-intra +fate-indeo2-intra: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/VPAR0026.AVI -FATE_INDEO-$(call DEMDEC, AVI, INDEO3) += fate-indeo3-2 +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, INDEO2) += $(FATE_INDEO2) +fate-indeo2: $(FATE_INDEO2) + +FATE_INDEO3-$(CONFIG_MOV_DEMUXER) += fate-indeo3-1 +fate-indeo3-1: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/cubes.mov + +FATE_INDEO3-$(CONFIG_AVI_DEMUXER) += fate-indeo3-2 fate-indeo3-2: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/OPENINGH.avi +FATE_SAMPLES_AVCONV-$(CONFIG_INDEO3_DECODER) += $(FATE_INDEO3-yes) +fate-indeo3: $(FATE_INDEO3-yes) + FATE_INDEO-$(call DEMDEC, AVI, INDEO4) += fate-indeo4 fate-indeo4: CMD = framecrc -i $(TARGET_SAMPLES)/iv41/indeo41-partial.avi -an @@ -14,4 +23,4 @@ FATE_INDEO-$(call DEMDEC, AVI, INDEO5) += fate-indeo5 fate-indeo5: CMD = framecrc -i $(TARGET_SAMPLES)/iv50/Educ_Movie_DeadlyForce.avi -an FATE_SAMPLES_AVCONV += $(FATE_INDEO-yes) -fate-indeo: $(FATE_INDEO-yes) +fate-indeo: $(FATE_INDEO2) $(FATE_INDEO3-yes) $(FATE_INDEO-yes) diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak index 138a1b2..d656ace 100644 --- a/tests/fate/libavcodec.mak +++ b/tests/fate/libavcodec.mak @@ -1,21 +1,21 @@ FATE_LIBAVCODEC-$(CONFIG_GOLOMB) += fate-golomb -fate-golomb: libavcodec/golomb-test$(EXESUF) -fate-golomb: CMD = run libavcodec/golomb-test +fate-golomb: libavcodec/tests/golomb$(EXESUF) +fate-golomb: CMD = run libavcodec/tests/golomb fate-golomb: REF = /dev/null FATE_LIBAVCODEC-$(CONFIG_IDCTDSP) += fate-idct8x8 -fate-idct8x8: libavcodec/dct-test$(EXESUF) -fate-idct8x8: CMD = run libavcodec/dct-test -i +fate-idct8x8: libavcodec/tests/dct$(EXESUF) +fate-idct8x8: CMD = run libavcodec/tests/dct -i fate-idct8x8: CMP = null fate-idct8x8: REF = /dev/null FATE_LIBAVCODEC-$(CONFIG_IIRFILTER) += fate-iirfilter -fate-iirfilter: libavcodec/iirfilter-test$(EXESUF) -fate-iirfilter: CMD = run libavcodec/iirfilter-test +fate-iirfilter: libavcodec/tests/iirfilter$(EXESUF) +fate-iirfilter: CMD = run libavcodec/tests/iirfilter FATE_LIBAVCODEC-$(CONFIG_RANGECODER) += fate-rangecoder -fate-rangecoder: libavcodec/rangecoder-test$(EXESUF) -fate-rangecoder: CMD = run libavcodec/rangecoder-test +fate-rangecoder: libavcodec/tests/rangecoder$(EXESUF) +fate-rangecoder: CMD = run libavcodec/tests/rangecoder fate-rangecoder: CMP = null fate-rangecoder: REF = /dev/null diff --git a/tests/fate/libavdevice.mak b/tests/fate/libavdevice.mak index cb6af51..e983327 100644 --- a/tests/fate/libavdevice.mak +++ b/tests/fate/libavdevice.mak @@ -1,6 +1,6 @@ -FATE_LIBAVDEVICE-yes += fate-timefilter -fate-timefilter: libavdevice/timefilter-test$(EXESUF) -fate-timefilter: CMD = run libavdevice/timefilter-test +FATE_LIBAVDEVICE-$(CONFIG_JACK_INDEV) += fate-timefilter +fate-timefilter: libavdevice/tests/timefilter$(EXESUF) +fate-timefilter: CMD = run libavdevice/tests/timefilter FATE-$(CONFIG_AVDEVICE) += $(FATE_LIBAVDEVICE-yes) fate-libavdevice: $(FATE_LIBAVDEVICE-yes) diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak index d532adc..30f0e03 100644 --- a/tests/fate/libavformat.mak +++ b/tests/fate/libavformat.mak @@ -1,14 +1,22 @@ FATE_LIBAVFORMAT-$(CONFIG_NETWORK) += fate-noproxy -fate-noproxy: libavformat/noproxy-test$(EXESUF) -fate-noproxy: CMD = run libavformat/noproxy-test +fate-noproxy: libavformat/tests/noproxy$(EXESUF) +fate-noproxy: CMD = run libavformat/tests/noproxy -FATE_LIBAVFORMAT-yes += fate-srtp -fate-srtp: libavformat/srtp-test$(EXESUF) -fate-srtp: CMD = run libavformat/srtp-test +FATE_LIBAVFORMAT-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += fate-rtmpdh +fate-rtmpdh: libavformat/tests/rtmpdh$(EXESUF) +fate-rtmpdh: CMD = run libavformat/tests/rtmpdh + +FATE_LIBAVFORMAT-$(CONFIG_SRTP) += fate-srtp +fate-srtp: libavformat/tests/srtp$(EXESUF) +fate-srtp: CMD = run libavformat/tests/srtp FATE_LIBAVFORMAT-yes += fate-url -fate-url: libavformat/url-test$(EXESUF) -fate-url: CMD = run libavformat/url-test +fate-url: libavformat/tests/url$(EXESUF) +fate-url: CMD = run libavformat/tests/url + +FATE_LIBAVFORMAT-$(CONFIG_MOV_MUXER) += fate-movenc +fate-movenc: libavformat/tests/movenc$(EXESUF) +fate-movenc: CMD = run libavformat/tests/movenc FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT-yes) fate-libavformat: $(FATE_LIBAVFORMAT) diff --git a/tests/fate/libavresample.mak b/tests/fate/libavresample.mak index 4a48c9c..cb61f2a 100644 --- a/tests/fate/libavresample.mak +++ b/tests/fate/libavresample.mak @@ -1,7 +1,7 @@ -CROSS_TEST = $(foreach I,$(1), \ - $(foreach J,$(1), \ - $(if $(filter-out $(I),$(J)), \ - $(eval $(call $(2),$(I),$(J),$(3),$(4),$(5))), \ +CROSS_TEST = $(foreach I,$(1), \ + $(foreach J,$(1), \ + $(if $(filter-out $(I),$(J)), \ + $(eval $(call $(2),$(I),$(J),$(3),$(4),$(5))), \ ))) MIX_CHANNELS = 1 2 3 4 5 6 7 8 @@ -38,7 +38,7 @@ fate-lavr-resample-$(3)-$(1)-$(2): CMD = avconv -i $(TARGET_PATH)/tests/data/asy fate-lavr-resample-$(3)-$(1)-$(2): CMP = oneoff fate-lavr-resample-$(3)-$(1)-$(2): CMP_UNIT = $(5) fate-lavr-resample-$(3)-$(1)-$(2): FUZZ = 6 -fate-lavr-resample-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-resample-$(3)-$(1)-$(2)-v2 +fate-lavr-resample-$(3)-$(1)-$(2): REF = $(SAMPLES)/lavr/lavr-resample-$(3)-$(1)-$(2)-v3 endef $(call CROSS_TEST,$(SAMPLERATES),RESAMPLE,s16p,s16le,s16) diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index 7f3329b..69e4042 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -1,82 +1,82 @@ FATE_LIBAVUTIL += fate-adler32 -fate-adler32: libavutil/adler32-test$(EXESUF) -fate-adler32: CMD = run libavutil/adler32-test +fate-adler32: libavutil/tests/adler32$(EXESUF) +fate-adler32: CMD = run libavutil/tests/adler32 fate-adler32: REF = /dev/null FATE_LIBAVUTIL += fate-aes -fate-aes: libavutil/aes-test$(EXESUF) -fate-aes: CMD = run libavutil/aes-test +fate-aes: libavutil/tests/aes$(EXESUF) +fate-aes: CMD = run libavutil/tests/aes fate-aes: REF = /dev/null FATE_LIBAVUTIL += fate-atomic -fate-atomic: libavutil/atomic-test$(EXESUF) -fate-atomic: CMD = run libavutil/atomic-test +fate-atomic: libavutil/tests/atomic$(EXESUF) +fate-atomic: CMD = run libavutil/tests/atomic fate-atomic: REF = /dev/null FATE_LIBAVUTIL += fate-avstring -fate-avstring: libavutil/avstring-test$(EXESUF) -fate-avstring: CMD = run libavutil/avstring-test +fate-avstring: libavutil/tests/avstring$(EXESUF) +fate-avstring: CMD = run libavutil/tests/avstring FATE_LIBAVUTIL += fate-base64 -fate-base64: libavutil/base64-test$(EXESUF) -fate-base64: CMD = run libavutil/base64-test +fate-base64: libavutil/tests/base64$(EXESUF) +fate-base64: CMD = run libavutil/tests/base64 FATE_LIBAVUTIL += fate-blowfish -fate-blowfish: libavutil/blowfish-test$(EXESUF) -fate-blowfish: CMD = run libavutil/blowfish-test +fate-blowfish: libavutil/tests/blowfish$(EXESUF) +fate-blowfish: CMD = run libavutil/tests/blowfish FATE_LIBAVUTIL += fate-cpu -fate-cpu: libavutil/cpu-test$(EXESUF) -fate-cpu: CMD = run libavutil/cpu-test $(CPUFLAGS:%=-c%) $(THREADS:%=-t%) +fate-cpu: libavutil/tests/cpu$(EXESUF) +fate-cpu: CMD = run libavutil/tests/cpu $(CPUFLAGS:%=-c%) $(THREADS:%=-t%) fate-cpu: REF = /dev/null FATE_LIBAVUTIL += fate-crc -fate-crc: libavutil/crc-test$(EXESUF) -fate-crc: CMD = run libavutil/crc-test +fate-crc: libavutil/tests/crc$(EXESUF) +fate-crc: CMD = run libavutil/tests/crc FATE_LIBAVUTIL += fate-des -fate-des: libavutil/des-test$(EXESUF) -fate-des: CMD = run libavutil/des-test +fate-des: libavutil/tests/des$(EXESUF) +fate-des: CMD = run libavutil/tests/des fate-des: REF = /dev/null FATE_LIBAVUTIL += fate-eval -fate-eval: libavutil/eval-test$(EXESUF) -fate-eval: CMD = run libavutil/eval-test +fate-eval: libavutil/tests/eval$(EXESUF) +fate-eval: CMD = run libavutil/tests/eval FATE_LIBAVUTIL += fate-fifo -fate-fifo: libavutil/fifo-test$(EXESUF) -fate-fifo: CMD = run libavutil/fifo-test +fate-fifo: libavutil/tests/fifo$(EXESUF) +fate-fifo: CMD = run libavutil/tests/fifo FATE_LIBAVUTIL += fate-float-dsp -fate-float-dsp: libavutil/float_dsp-test$(EXESUF) -fate-float-dsp: CMD = run libavutil/float_dsp-test +fate-float-dsp: libavutil/tests/float_dsp$(EXESUF) +fate-float-dsp: CMD = run libavutil/tests/float_dsp fate-float-dsp: CMP = null fate-float-dsp: REF = /dev/null FATE_LIBAVUTIL += fate-hmac -fate-hmac: libavutil/hmac-test$(EXESUF) -fate-hmac: CMD = run libavutil/hmac-test +fate-hmac: libavutil/tests/hmac$(EXESUF) +fate-hmac: CMD = run libavutil/tests/hmac FATE_LIBAVUTIL += fate-md5 -fate-md5: libavutil/md5-test$(EXESUF) -fate-md5: CMD = run libavutil/md5-test +fate-md5: libavutil/tests/md5$(EXESUF) +fate-md5: CMD = run libavutil/tests/md5 FATE_LIBAVUTIL += fate-parseutils -fate-parseutils: libavutil/parseutils-test$(EXESUF) -fate-parseutils: CMD = run libavutil/parseutils-test +fate-parseutils: libavutil/tests/parseutils$(EXESUF) +fate-parseutils: CMD = run libavutil/tests/parseutils FATE_LIBAVUTIL += fate-sha -fate-sha: libavutil/sha-test$(EXESUF) -fate-sha: CMD = run libavutil/sha-test +fate-sha: libavutil/tests/sha$(EXESUF) +fate-sha: CMD = run libavutil/tests/sha FATE_LIBAVUTIL += fate-tree -fate-tree: libavutil/tree-test$(EXESUF) -fate-tree: CMD = run libavutil/tree-test +fate-tree: libavutil/tests/tree$(EXESUF) +fate-tree: CMD = run libavutil/tests/tree fate-tree: REF = /dev/null FATE_LIBAVUTIL += fate-xtea -fate-xtea: libavutil/xtea-test$(EXESUF) -fate-xtea: CMD = run libavutil/xtea-test +fate-xtea: libavutil/tests/xtea$(EXESUF) +fate-xtea: CMD = run libavutil/tests/xtea FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL) fate-libavutil: $(FATE_LIBAVUTIL) diff --git a/tests/fate/lossless-audio.mak b/tests/fate/lossless-audio.mak index 3638f17..b4eadda 100644 --- a/tests/fate/lossless-audio.mak +++ b/tests/fate/lossless-audio.mak @@ -15,8 +15,14 @@ fate-lossless-tak: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-part fate-lossless-tak: CMP = oneline fate-lossless-tak: REF = a28d4e5f2192057f7d4bece870f40bd0 +FATE_TRUEHD = fate-lossless-truehd-5.1 fate-lossless-truehd-5.1-downmix-2.0 +fate-lossless-truehd-5.1: CMD = md5 -f truehd -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le +fate-lossless-truehd-5.1-downmix-2.0: CMD = md5 -f truehd -request_channel_layout 2 -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le +fate-lossless-truehd: $(FATE_TRUEHD) +FATE_SAMPLES_AVCONV-$(call DEMDEC, TRUEHD, TRUEHD) += $(FATE_TRUEHD) + FATE_SAMPLES_AVCONV-$(call DEMDEC, TTA, TTA) += fate-lossless-tta fate-lossless-tta: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/inside.tta FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, WMALOSSLESS) += fate-lossless-wma -fate-lossless-wma: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.wma -f s16le +fate-lossless-wma: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.wma -f s16le -frames 209 diff --git a/tests/fate/lossless-video.mak b/tests/fate/lossless-video.mak index bf1a971..f039492 100644 --- a/tests/fate/lossless-video.mak +++ b/tests/fate/lossless-video.mak @@ -1,15 +1,3 @@ -FATE_CLLC += fate-cllc-argb -fate-cllc-argb: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-argb.avi - -FATE_CLLC += fate-cllc-rgb -fate-cllc-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-rgb.avi - -FATE_CLLC += fate-cllc-yuy2-noblock -fate-cllc-yuy2-noblock: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-yuy2-noblock.avi - -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, CLLC) += $(FATE_CLLC) -fate-cllc: $(FATE_CLLC) - FATE_LAGARITH += fate-lagarith-rgb24 fate-lagarith-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb24.avi diff --git a/tests/fate/microsoft.mak b/tests/fate/microsoft.mak index ea41c42..de53f00 100644 --- a/tests/fate/microsoft.mak +++ b/tests/fate/microsoft.mak @@ -1,6 +1,9 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, MSMPEG4V1) += fate-msmpeg4v1 fate-msmpeg4v1: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/msmpeg4v1/mpg4.avi -an +FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MSS1) += fate-mss1 +fate-mss1: CMD = framecrc -i $(TARGET_SAMPLES)/mss1/screen_codec.wmv -an -pix_fmt rgb24 + FATE_MSS2 += fate-mss2-pal fate-mss2-pal: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rlepal.wmv @@ -28,6 +31,9 @@ fate-msvideo1-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/clock-cram16.avi - FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, MSVIDEO1) += $(FATE_MSVIDEO1) fate-msvideo1: $(FATE_MSVIDEO1) +FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MTS2) += fate-mts2 +fate-mts2: CMD = framecrc -i $(TARGET_SAMPLES)/mts2/ScreenCapture.xesc + FATE_WMV8_DRM += fate-wmv8-drm # discard last packet to avoid fails due to overread of VC-1 decoder fate-wmv8-drm: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -an -frames:v 129 @@ -38,6 +44,9 @@ fate-wmv8-drm-nodec: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c34 FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, WMV3) += $(FATE_WMV8_DRM) fate-wmv8_drm: $(FATE_WMV8_DRM) +FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, WMV2) += fate-wmv8-intrax8 +fate-wmv8-intrax8: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/wmv8/wmv8_x8intra.wmv -an + FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa00040 fate-vc1_sa00040: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA00040.vc1 @@ -53,8 +62,14 @@ fate-vc1_sa10143: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA10143.vc1 FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa20021 fate-vc1_sa20021: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA20021.vc1 +FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_ilaced_twomv +fate-vc1_ilaced_twomv: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vc1/ilaced_twomv.vc1 + FATE_VC1-$(CONFIG_MOV_DEMUXER) += fate-vc1-ism fate-vc1-ism: CMD = framecrc -i $(TARGET_SAMPLES)/isom/vc1-wmapro.ism -an FATE_SAMPLES_AVCONV-$(CONFIG_VC1_DECODER) += $(FATE_VC1-yes) fate-vc1: $(FATE_VC1-yes) + +FATE_SAMPLES_AVCONV-$(CONFIG_ASF_DEMUXER) += fate-asf-repldata +fate-asf-repldata: CMD = framecrc -i $(TARGET_SAMPLES)/asf/bug821-2.asf -c copy diff --git a/tests/fate/mp3.mak b/tests/fate/mp3.mak index fe6a0e1..78832cb 100644 --- a/tests/fate/mp3.mak +++ b/tests/fate/mp3.mak @@ -1,37 +1,38 @@ FATE_MP3 += fate-mp3-float-conf-compl -fate-mp3-float-conf-compl: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/compl.bit -fate-mp3-float-conf-compl: REF = $(SAMPLES)/mp3-conformance/compl.pcm +fate-mp3-float-conf-compl: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/compl.bit -f f32le - +fate-mp3-float-conf-compl: REF = $(SAMPLES)/mp3-conformance/compl.f32 FATE_MP3 += fate-mp3-float-conf-he_32khz -fate-mp3-float-conf-he_32khz: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_32khz.bit -fs 343296 -fate-mp3-float-conf-he_32khz: REF = $(SAMPLES)/mp3-conformance/he_32khz.pcm +fate-mp3-float-conf-he_32khz: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_32khz.bit -af atrim=end_sample=171648 -f f32le - +fate-mp3-float-conf-he_32khz: REF = $(SAMPLES)/mp3-conformance/he_32khz.f32 FATE_MP3 += fate-mp3-float-conf-he_44khz -fate-mp3-float-conf-he_44khz: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_44khz.bit -fs 942336 -fate-mp3-float-conf-he_44khz: REF = $(SAMPLES)/mp3-conformance/he_44khz.pcm +fate-mp3-float-conf-he_44khz: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_44khz.bit -af atrim=end_sample=471168 -f f32le - +fate-mp3-float-conf-he_44khz: REF = $(SAMPLES)/mp3-conformance/he_44khz.f32 FATE_MP3 += fate-mp3-float-conf-he_48khz -fate-mp3-float-conf-he_48khz: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_48khz.bit -fs 343296 -fate-mp3-float-conf-he_48khz: REF = $(SAMPLES)/mp3-conformance/he_48khz.pcm +fate-mp3-float-conf-he_48khz: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_48khz.bit -af atrim=end_sample=171648 -f f32le - +fate-mp3-float-conf-he_48khz: REF = $(SAMPLES)/mp3-conformance/he_48khz.f32 FATE_MP3 += fate-mp3-float-conf-hecommon -fate-mp3-float-conf-hecommon: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/hecommon.bit -fs 133632 -fate-mp3-float-conf-hecommon: REF = $(SAMPLES)/mp3-conformance/hecommon.pcm +fate-mp3-float-conf-hecommon: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/hecommon.bit -af atrim=end_sample=33408 -f f32le - +fate-mp3-float-conf-hecommon: REF = $(SAMPLES)/mp3-conformance/hecommon.f32 FATE_MP3 += fate-mp3-float-conf-si -fate-mp3-float-conf-si: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si.bit -fs 269568 -fate-mp3-float-conf-si: REF = $(SAMPLES)/mp3-conformance/si.pcm +fate-mp3-float-conf-si: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si.bit -af atrim=end_sample=134784 -f f32le - +fate-mp3-float-conf-si: REF = $(SAMPLES)/mp3-conformance/si.f32 FATE_MP3 += fate-mp3-float-conf-si_block -fate-mp3-float-conf-si_block: CMD = pcm -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si_block.bit -fs 145152 -fate-mp3-float-conf-si_block: REF = $(SAMPLES)/mp3-conformance/si_block.pcm +fate-mp3-float-conf-si_block: CMD = avconv -acodec mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si_block.bit -af atrim=end_sample=72576 -f f32le - +fate-mp3-float-conf-si_block: REF = $(SAMPLES)/mp3-conformance/si_block.f32 FATE_MP3 += fate-mp3-float-extra_overread -fate-mp3-float-extra_overread: CMD = pcm -c:a mp3float -i $(TARGET_SAMPLES)/mpegaudio/extra_overread.mp3 -fate-mp3-float-extra_overread: REF = $(SAMPLES)/mpegaudio/extra_overread.pcm +fate-mp3-float-extra_overread: CMD = avconv -c:a mp3float -i $(TARGET_SAMPLES)/mpegaudio/extra_overread.mp3 -f f32le - +fate-mp3-float-extra_overread: REF = $(SAMPLES)/mpegaudio/extra_overread.f32 -$(FATE_MP3): CMP = stddev -$(FATE_MP3): FUZZ = 0.07 +$(FATE_MP3): CMP = oneoff +$(FATE_MP3): CMP_UNIT = f32 +$(FATE_MP3): FUZZ = 17 FATE_MP3-$(call DEMDEC, MP3, MP3FLOAT) += $(FATE_MP3) diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak new file mode 100644 index 0000000..f9b94e6 --- /dev/null +++ b/tests/fate/mpeg4.mak @@ -0,0 +1,9 @@ + +MPEG4_RESOLUTION_CHANGE = down-down down-up up-down up-up + +fate-mpeg4-resolution-change-%: CMD = framemd5 -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/resize_$(@:fate-mpeg4-resolution-change-%=%).h263 + +FATE_MPEG4-$(call DEMDEC, H263, H263) := $(addprefix fate-mpeg4-resolution-change-, $(MPEG4_RESOLUTION_CHANGE)) + +FATE_SAMPLES_AVCONV += $(FATE_MPEG4-yes) +fate-mpeg4: $(FATE_MPEG4-yes) diff --git a/tests/fate/qt.mak b/tests/fate/qt.mak index ac95d64..97537f9 100644 --- a/tests/fate/qt.mak +++ b/tests/fate/qt.mak @@ -46,5 +46,8 @@ fate-rpza: CMD = framecrc -i $(TARGET_SAMPLES)/rpza/rpza2.mov -t 2 -pix_fmt rgb2 FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, SVQ1) += fate-svq1 fate-svq1: CMD = framecrc -i $(TARGET_SAMPLES)/svq1/marymary-shackles.mov -an -t 10 +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, SVQ1) += fate-svq1-headerswap +fate-svq1-headerswap: CMD = framecrc -i $(TARGET_SAMPLES)/svq1/ct_ending_cut.mov -frames 4 + FATE_SAMPLES_AVCONV-$(call ALLYES, MOV_DEMUXER SVQ3_DECODER ZLIB) += fate-svq3 fate-svq3: CMD = framecrc -i $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov -t 6 -an diff --git a/tests/fate/real.mak b/tests/fate/real.mak index 612f771..f119ce9 100644 --- a/tests/fate/real.mak +++ b/tests/fate/real.mak @@ -1,3 +1,11 @@ +FATE_REALAUDIO-$(call DEMDEC, RM, RA_144) += fate-ra3-144 +fate-ra3-144: CMD = framecrc -i $(TARGET_SAMPLES)/realaudio/ra3.ra + +FATE_REALAUDIO-$(call DEMDEC, RM, RA_288) += fate-ra4-288 +fate-ra4-288: CMD = pcm -i $(TARGET_SAMPLES)/realaudio/ra4_288.ra +fate-ra4-288: REF = $(SAMPLES)/realaudio/ra4_288.pcm +fate-ra4-288: CMP = oneoff + FATE_REALMEDIA_AUDIO-$(call DEMDEC, RM, RA_144) += fate-ra-144 fate-ra-144: CMD = md5 -i $(TARGET_SAMPLES)/real/ra3_in_rm_file.rm -f s16le @@ -39,8 +47,10 @@ $(FATE_SIPR): CMP = oneoff FATE_REALMEDIA_AUDIO-$(call DEMDEC, RM, SIPR) += $(FATE_SIPR) fate-sipr: $(FATE_SIPR) +fate-realaudio: $(FATE_REALAUDIO-yes) fate-realmedia-audio: $(FATE_REALMEDIA_AUDIO-yes) fate-realmedia-video: $(FATE_REALMEDIA_VIDEO-yes) fate-realmedia: fate-realmedia-audio fate-realmedia-video +fate-real: fate-realaudio fate-realmedia -FATE_SAMPLES_AVCONV += $(FATE_REALMEDIA_AUDIO-yes) $(FATE_REALMEDIA_VIDEO-yes) +FATE_SAMPLES_AVCONV += $(FATE_REALAUDIO-yes) $(FATE_REALMEDIA_AUDIO-yes) $(FATE_REALMEDIA_VIDEO-yes) diff --git a/tests/fate/screen.mak b/tests/fate/screen.mak index bd6ace6..7e91f19 100644 --- a/tests/fate/screen.mak +++ b/tests/fate/screen.mak @@ -3,7 +3,7 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, CSCD) += fate-cscd fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fmt rgb24 FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, DXTORY) += fate-dxtory -fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi +fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi -an FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FIC) += fate-fic-avi fate-fic-avi: CMD = framecrc -i $(TARGET_SAMPLES)/fic/fic-partial-2MB.avi -an @@ -29,6 +29,48 @@ fate-fraps-v5: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/fraps-v5-bouncing-balls FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FRAPS) += $(FATE_FRAPS) fate-fraps: $(FATE_FRAPS) +FATE_G2M += fate-g2m2 +fate-g2m2: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m2.asf -an + +FATE_G2M += fate-g2m3 +fate-g2m3: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m3.asf -frames:v 20 -an + +FATE_G2M += fate-g2m4 +fate-g2m4: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m4.asf + +FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, G2M) += $(FATE_G2M) +fate-g2m: $(FATE_G2M) + +FATE_RSCC += fate-iscc +fate-iscc: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/pip.avi -an + +FATE_RSCC += fate-rscc-16bit +fate-rscc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/16bpp_555.avi -an + +FATE_RSCC += fate-rscc-24bit +fate-rscc-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/24bpp.avi -an + +FATE_RSCC += fate-rscc-32bit +fate-rscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/32bpp.avi -an + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, RSCC) += $(FATE_RSCC) +fate-rscc: $(FATE_RSCC) + +FATE_SCREENPRESSO += fate-screenpresso-16bit +fate-screenpresso-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/16bpp_555.avi -an + +FATE_SCREENPRESSO += fate-screenpresso-24bit +fate-screenpresso-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/bunny.avi -an + +FATE_SCREENPRESSO += fate-screenpresso-32bit +fate-screenpresso-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/32bpp.avi -an + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, SCREENPRESSO) += $(FATE_SCREENPRESSO) +fate-screenpresso: $(FATE_SCREENPRESSO) + +FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, TDSC) += fate-tdsc +fate-tdsc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/tdsc/tdsc.asf -an -pix_fmt bgr24 + FATE_TSCC += fate-tscc-15bit fate-tscc-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/oneminute.avi -t 15 -pix_fmt rgb24 @@ -38,8 +80,14 @@ fate-tscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/2004-12-17-uebung9-par FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TSCC) += $(FATE_TSCC) fate-tscc: $(FATE_TSCC) -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TSCC2) += fate-tscc2 -fate-tscc2: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/tsc2_16bpp.avi +FATE_TSCC2-$(CONFIG_AVI_DEMUXER) += fate-tscc2-avi +fate-tscc2-avi: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/tsc2_16bpp.avi + +FATE_TSCC2-$(CONFIG_MOV_DEMUXER) += fate-tscc2-mov +fate-tscc2-mov: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/rec.trec + +FATE_SAMPLES_AVCONV-$(CONFIG_TSCC2_DECODER) += $(FATE_TSCC2-yes) +fate-tscc2: $(FATE_TSCC2-yes) FATE_VMNC += fate-vmnc-16bit fate-vmnc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/test.avi -pix_fmt rgb24 diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak index be06f0f..60adab2 100644 --- a/tests/fate/seek.mak +++ b/tests/fate/seek.mak @@ -69,16 +69,16 @@ FATE_SEEK_VSYNTH2-$(call ENCDEC, JPEGLS, AVI) += jpegls FATE_SEEK_VSYNTH2-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg FATE_SEEK_VSYNTH2-$(call ENCDEC, MJPEG, AVI) += mjpeg -FATE_SEEK_VSYNTH2-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) += \ - mpeg1 \ +FATE_SEEK_VSYNTH2-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) += \ + mpeg1 \ mpeg1b -FATE_SEEK_VSYNTH2-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) += \ - mpeg2-422 \ - mpeg2-idct-int \ - mpeg2-ilace \ - mpeg2-ivlc-qprd \ - mpeg2-thread \ +FATE_SEEK_VSYNTH2-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) += \ + mpeg2-422 \ + mpeg2-idct-int \ + mpeg2-ilace \ + mpeg2-ivlc-qprd \ + mpeg2-thread \ mpeg2-thread-ivlc FATE_SEEK_VSYNTH2-$(call ENCDEC, MPEG4, MP4 MOV) += mpeg4 @@ -218,8 +218,8 @@ fate-seek-lavf-yuv4mpeg: SRC = lavf/lavf.y4m FATE_SEEK += $(FATE_SEEK_LAVF-yes:%=fate-seek-lavf-%) -$(FATE_SEEK): libavformat/seek-test$(EXESUF) -$(FATE_SEEK): CMD = run libavformat/seek-test$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC) +$(FATE_SEEK): libavformat/tests/seek$(EXESUF) +$(FATE_SEEK): CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC) $(FATE_SEEK): fate-seek-%: fate-% fate-seek-%: REF = $(SRC_PATH)/tests/ref/seek/$(@:fate-seek-%=%) diff --git a/tests/fate/utvideo.mak b/tests/fate/utvideo.mak index e1ef7ec..4c0c6bf 100644 --- a/tests/fate/utvideo.mak +++ b/tests/fate/utvideo.mak @@ -37,7 +37,7 @@ FATE_UTVIDEOENC += fate-utvideoenc_rgba_median fate-utvideoenc_rgba_median: OPTS = -pix_fmt rgba -pred median FATE_UTVIDEOENC += fate-utvideoenc_rgba_none -fate-utvideoenc_rgba_none: OPTS = -pix_fmt rgba -pred 3 +fate-utvideoenc_rgba_none: OPTS = -pix_fmt rgba -pred none FATE_UTVIDEOENC += fate-utvideoenc_rgb_left fate-utvideoenc_rgb_left: OPTS = -pix_fmt rgb24 -pred left @@ -46,7 +46,7 @@ FATE_UTVIDEOENC += fate-utvideoenc_rgb_median fate-utvideoenc_rgb_median: OPTS = -pix_fmt rgb24 -pred median FATE_UTVIDEOENC += fate-utvideoenc_rgb_none -fate-utvideoenc_rgb_none: OPTS = -pix_fmt rgb24 -pred 3 +fate-utvideoenc_rgb_none: OPTS = -pix_fmt rgb24 -pred none FATE_UTVIDEOENC += fate-utvideoenc_yuv420_left fate-utvideoenc_yuv420_left: OPTS = -pix_fmt yuv420p -pred left @@ -55,7 +55,7 @@ FATE_UTVIDEOENC += fate-utvideoenc_yuv420_median fate-utvideoenc_yuv420_median: OPTS = -pix_fmt yuv420p -pred median FATE_UTVIDEOENC += fate-utvideoenc_yuv420_none -fate-utvideoenc_yuv420_none: OPTS = -pix_fmt yuv420p -pred 3 +fate-utvideoenc_yuv420_none: OPTS = -pix_fmt yuv420p -pred none FATE_UTVIDEOENC += fate-utvideoenc_yuv422_left fate-utvideoenc_yuv422_left: OPTS = -pix_fmt yuv422p -pred left @@ -64,7 +64,7 @@ FATE_UTVIDEOENC += fate-utvideoenc_yuv422_median fate-utvideoenc_yuv422_median: OPTS = -pix_fmt yuv422p -pred median FATE_UTVIDEOENC += fate-utvideoenc_yuv422_none -fate-utvideoenc_yuv422_none: OPTS = -pix_fmt yuv422p -pred 3 +fate-utvideoenc_yuv422_none: OPTS = -pix_fmt yuv422p -pred none $(FATE_UTVIDEOENC): $(VREF) diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index ed9fa2e..e195254 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -114,8 +114,8 @@ fate-vsynth%-mpeg2: ENCOPTS = -qscale 10 fate-vsynth%-mpeg2-422: ENCOPTS = -b:v 1000k \ -bf 2 \ -trellis 1 \ - -flags +mv0+ildct+ilme \ - -mpv_flags +qp_rd \ + -flags +ildct+ilme \ + -mpv_flags +qp_rd+mv0 \ -intra_vlc 1 \ -mbd rd \ -pix_fmt yuv422p @@ -124,8 +124,7 @@ fate-vsynth%-mpeg2-ilace: ENCOPTS = -qscale 10 -flags +ildct+ilme fate-vsynth%-mpeg2-ivlc-qprd: ENCOPTS = -b:v 500k \ -bf 2 \ -trellis 1 \ - -flags +mv0 \ - -mpv_flags +qp_rd \ + -mpv_flags +qp_rd+mv0 \ -intra_vlc 1 \ -cmp 2 -subcmp 2 \ -mbd rd @@ -150,9 +149,10 @@ FATE_VCODEC-$(call ENCDEC, MPEG4, AVI) += $(FATE_MPEG4_AVI) fate-vsynth%-mpeg4: ENCOPTS = -qscale 10 -flags +mv4 -mbd bits fate-vsynth%-mpeg4: FMT = mp4 -fate-vsynth%-mpeg4-adap: ENCOPTS = -b 550k -bf 2 -flags +mv4+mv0 \ +fate-vsynth%-mpeg4-adap: ENCOPTS = -b 550k -bf 2 -flags +mv4 \ -trellis 1 -cmp 1 -subcmp 2 \ - -mbd rd -scplx_mask 0.3 + -mbd rd -scplx_mask 0.3 \ + -mpv_flags +mv0 fate-vsynth%-mpeg4-adv: ENCOPTS = -qscale 9 -flags +mv4+aic \ -data_partitioning 1 -trellis 1 \ @@ -160,15 +160,16 @@ fate-vsynth%-mpeg4-adv: ENCOPTS = -qscale 9 -flags +mv4+aic \ fate-vsynth%-mpeg4-error: ENCOPTS = -qscale 7 -flags +mv4+aic \ -data_partitioning 1 -mbd rd \ - -ps 250 -error 10 + -ps 250 -error_rate 10 -fate-vsynth%-mpeg4-nr: ENCOPTS = -qscale 8 -flags +mv4 -mbd rd -nr 200 +fate-vsynth%-mpeg4-nr: ENCOPTS = -qscale 8 -flags +mv4 -mbd rd \ + -noise_reduction 200 fate-vsynth%-mpeg4-qpel: ENCOPTS = -qscale 7 -flags +mv4+qpel -mbd 2 \ -bf 2 -cmp 1 -subcmp 2 fate-vsynth%-mpeg4-qprd: ENCOPTS = -b 450k -bf 2 -trellis 1 \ - -flags +mv4+mv0 -mpv_flags +qp_rd \ + -flags +mv4 -mpv_flags +qp_rd+mv0 \ -cmp 2 -subcmp 2 -mbd rd fate-vsynth%-mpeg4-rc: ENCOPTS = -b 400k -bf 2 @@ -212,7 +213,8 @@ FATE_VCODEC-$(call ENCDEC, SVQ1, MOV) += svq1 fate-vsynth%-svq1: ENCOPTS = -qscale 3 -pix_fmt yuv410p fate-vsynth%-svq1: FMT = mov -FATE_VCODEC-$(call ENCDEC, V210, AVI) += v210 +FATE_VCODEC-$(call ENCDEC, V210, AVI) += v210 v210-10 +fate-vsynth%-v210-10: ENCOPTS = -pix_fmt yuv422p10 FATE_VCODEC-$(call ENCDEC, WMV1, AVI) += wmv1 fate-vsynth%-wmv1: ENCOPTS = -qscale 10 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index 5a48e10..18366e8 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -10,6 +10,9 @@ fate-4xm: $(FATE_4XM) FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, AASC) += fate-aasc fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24 +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, AIC) += fate-aic-oddsize +fate-aic-oddsize: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/aic_odd_dimensions.mov + FATE_SAMPLES_AVCONV-$(call DEMDEC, MM, MMVIDEO) += fate-alg-mm fate-alg-mm: CMD = framecrc -i $(TARGET_SAMPLES)/alg-mm/ibmlogo.mm -an -pix_fmt rgb24 @@ -91,18 +94,6 @@ fate-delphine-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-p FATE_SAMPLES_AVCONV-$(call DEMDEC, ANM, ANM) += fate-deluxepaint-anm fate-deluxepaint-anm: CMD = framecrc -i $(TARGET_SAMPLES)/deluxepaint-anm/INTRO1.ANM -pix_fmt rgb24 -FATE_TRUEMOTION1 += fate-truemotion1-15 -fate-truemotion1-15: CMD = framecrc -i $(TARGET_SAMPLES)/duck/phant2-940.duk -pix_fmt rgb24 -an - -FATE_TRUEMOTION1 += fate-truemotion1-24 -fate-truemotion1-24: CMD = framecrc -i $(TARGET_SAMPLES)/duck/sonic3dblast_intro-partial.avi -pix_fmt rgb24 -an - -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION1) += $(FATE_TRUEMOTION1) -fate-truemotion1: $(FATE_TRUEMOTION1) - -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION2) += fate-truemotion2 -fate-truemotion2: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tm20.avi - FATE_DXA += fate-dxa-feeble fate-dxa-feeble: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/meetsquid.dxa -t 2 -pix_fmt rgb24 -an @@ -112,6 +103,21 @@ fate-dxa-scummvm: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/scummvm.dxa -pix_fmt r FATE_SAMPLES_AVCONV-$(call DEMDEC, DXA, DXA) += $(FATE_DXA) fate-dxa: $(FATE_DXA) +FATE_DXV += fate-dxv-dxt1 +fate-dxv-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv-na.mov + +FATE_DXV += fate-dxv-dxt5 +fate-dxv-dxt5: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv-wa.mov + +FATE_DXV += fate-dxv3-dxt1 +fate-dxv3-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqna.mov + +FATE_DXV += fate-dxv3-dxt5 +fate-dxv3-dxt5: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqwa.mov + +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, DXV) += $(FATE_DXV) +fate-dxv: $(FATE_DXV) + FATE_SAMPLES_AVCONV-$(call DEMDEC, SEGAFILM, CINEPAK) += fate-film-cvid fate-film-cvid: CMD = framecrc -i $(TARGET_SAMPLES)/film/logo-capcom.cpk -an @@ -136,6 +142,21 @@ fate-id-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/idcin/idlog-2MB.cin -pix_ FATE_SAMPLES_AVCONV-$(call ENCDEC, ROQ PGMYUV, ROQ IMAGE2) += fate-idroq-video-encode fate-idroq-video-encode: CMD = md5 -f image2 -vcodec pgmyuv -i $(TARGET_SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -sws_flags +bitexact -vf pad=512:512:80:112 -f roq -t 0.2 +FATE_HAP += fate-hap1 +fate-hap1: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap1.mov + +FATE_HAP += fate-hap5 +fate-hap5: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap5.mov + +FATE_HAP += fate-hapy +fate-hapy: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy.mov + +FATE_HAP += fate-hap-chunk +fate-hap-chunk: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy-12-chunks.mov + +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) +fate-hap: $(FATE_HAP) + FATE_IFF-$(CONFIG_IFF_BYTERUN1_DECODER) += fate-iff-byterun1 fate-iff-byterun1: CMD = framecrc -i $(TARGET_SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 @@ -166,6 +187,25 @@ fate-kgv1: CMD = framecrc -i $(TARGET_SAMPLES)/kega/kgv1.avi -pix_fmt rgb555le - FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, KMVC) += fate-kmvc fate-kmvc: CMD = framecrc -i $(TARGET_SAMPLES)/KMVC/LOGO1.AVI -an -t 3 -pix_fmt rgb24 +FATE_MAGICYUV += fate-magicyuv-y4444i \ + fate-magicyuv-y400i \ + fate-magicyuv-y420 \ + fate-magicyuv-y422i \ + fate-magicyuv-y444 \ + fate-magicyuv-rgba \ + fate-magicyuv-rgb + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, MAGICYUV) += $(FATE_MAGICYUV) +fate-magicyuv: $(FATE_MAGICYUV) + +fate-magicyuv-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_rgb_median.avi +fate-magicyuv-rgba: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_rgba_gradient.avi +fate-magicyuv-y400i: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv400_gradient_interlaced.avi +fate-magicyuv-y420: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv420_median.avi +fate-magicyuv-y422i: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv422_median_interlaced.avi +fate-magicyuv-y4444i: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv4444_left_interlaced.avi +fate-magicyuv-y444: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv444_left.avi + FATE_SAMPLES_AVCONV-$(call DEMDEC, EA, MDEC) += fate-mdec fate-mdec: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/ea-dct/NFS2Esprit-partial.dct -an @@ -246,7 +286,10 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, TMV, TMV) += fate-tmv fate-tmv: CMD = framecrc -i $(TARGET_SAMPLES)/tmv/pop-partial.tmv -pix_fmt rgb24 FATE_TXD += fate-txd-16bpp -fate-txd-16bpp: CMD = framecrc -i $(TARGET_SAMPLES)/txd/misc.txd -pix_fmt bgra -an +fate-txd-16bpp: CMD = framecrc -i $(TARGET_SAMPLES)/txd/misc.txd -an + +FATE_TXD += fate-txd-odd +fate-txd-odd: CMD = framecrc -i $(TARGET_SAMPLES)/txd/odd.txd -an FATE_TXD += fate-txd-pal8 fate-txd-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/txd/outro.txd -pix_fmt rgb24 -an diff --git a/tests/fate/voice.mak b/tests/fate/voice.mak index 975936c..84f380d 100644 --- a/tests/fate/voice.mak +++ b/tests/fate/voice.mak @@ -1,13 +1,13 @@ -FATE_G722 += fate-g722dec-1 +FATE_G722-$(call DEMDEC, G722, ADPCM_G722) += fate-g722dec-1 fate-g722dec-1: CMD = framecrc -i $(TARGET_SAMPLES)/g722/conf-adminmenu-162.g722 -FATE_G722 += fate-g722-encode +FATE_G722-$(call ENCDEC, ADPCM_G722, G722) += fate-g722-encode fate-g722-encode: tests/data/asynth-16000-1.wav fate-g722-encode: SRC = tests/data/asynth-16000-1.wav fate-g722-encode: CMD = enc_dec_pcm wav md5 s16le $(SRC) -c:a g722 -FATE_SAMPLES_AVCONV += $(FATE_G722) -fate-g722: $(FATE_G722) +FATE_SAMPLES_AVCONV += $(FATE_G722-yes) +fate-g722: $(FATE_G722-yes) FATE_G723_1 += fate-g723_1-dec-1 fate-g723_1-dec-1: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/ineqd53.tco @@ -33,7 +33,7 @@ fate-g723_1-dec-7: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx6 FATE_G723_1 += fate-g723_1-dec-8 fate-g723_1-dec-8: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63e.tco -FATE_SAMPLES_AVCONV += $(FATE_G723_1) +FATE_SAMPLES_AVCONV-$(call DEMDEC, G723_1, G723_1) += $(FATE_G723_1) fate-g723_1: $(FATE_G723_1) FATE_G726 += fate-g726-encode-2bit @@ -51,24 +51,24 @@ fate-g726-encode-5bit: CMD = enc_dec_pcm wav md5 s16le $(SRC) -c:a g726 -b:a 40k $(FATE_G726): tests/data/asynth-8000-1.wav $(FATE_G726): SRC = tests/data/asynth-8000-1.wav -FATE_SAMPLES_AVCONV += $(FATE_G726) +FATE_SAMPLES_AVCONV-$(call ENCDEC, ADPCM_G726, WAV) += $(FATE_G726) fate-g726: $(FATE_G726) -FATE_GSM += fate-gsm-ms +FATE_GSM-$(call DEMDEC, WAV, GSM_MS) += fate-gsm-ms fate-gsm-ms: CMD = framecrc -i $(TARGET_SAMPLES)/gsm/ciao.wav -FATE_GSM += fate-gsm-toast +FATE_GSM-$(call DEMDEC, MOV, GSM) += fate-gsm-toast fate-gsm-toast: CMD = framecrc -i $(TARGET_SAMPLES)/gsm/sample-gsm-8000.mov -t 10 -FATE_SAMPLES_AVCONV += $(FATE_GSM) -fate-gsm: $(FATE_GSM) +FATE_SAMPLES_AVCONV += $(FATE_GSM-yes) +fate-gsm: $(FATE_GSM-yes) -FATE_SAMPLES_AVCONV += fate-qcelp +FATE_SAMPLES_AVCONV-$(call DEMDEC, QCP, QCELP) += fate-qcelp fate-qcelp: CMD = pcm -i $(TARGET_SAMPLES)/qcp/0036580847.QCP fate-qcelp: CMP = oneoff fate-qcelp: REF = $(SAMPLES)/qcp/0036580847.pcm -FATE_SAMPLES_AVCONV += fate-truespeech +FATE_SAMPLES_AVCONV-$(call DEMDEC, WAV, TRUESPEECH) += fate-truespeech fate-truespeech: CMD = pcm -i $(TARGET_SAMPLES)/truespeech/a6.wav fate-truespeech: CMP = oneoff fate-truespeech: REF = $(SAMPLES)/truespeech/a6.pcm diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak index f8c25e5..75248ec 100644 --- a/tests/fate/vpx.mak +++ b/tests/fate/vpx.mak @@ -1,6 +1,33 @@ +FATE_TRUEMOTION1 += fate-truemotion1-15 +fate-truemotion1-15: CMD = framecrc -i $(TARGET_SAMPLES)/duck/phant2-940.duk -pix_fmt rgb24 -an + +FATE_TRUEMOTION1 += fate-truemotion1-24 +fate-truemotion1-24: CMD = framecrc -i $(TARGET_SAMPLES)/duck/sonic3dblast_intro-partial.avi -pix_fmt rgb24 -an + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION1) += $(FATE_TRUEMOTION1) +fate-truemotion1: $(FATE_TRUEMOTION1) + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION2) += fate-truemotion2 +fate-truemotion2: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tm20.avi + +FATE_TRUEMOTION2RT += fate-truemotion2rt-low +fate-truemotion2rt-low: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tr20_low.avi -an + +FATE_TRUEMOTION2RT += fate-truemotion2rt-mid +fate-truemotion2rt-mid: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tr20_mid.avi -an + +FATE_TRUEMOTION2RT += fate-truemotion2rt-high +fate-truemotion2rt-high: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tr20_high.avi -an + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION2RT) += $(FATE_TRUEMOTION2RT) +fate-truemotion2rt: $(FATE_TRUEMOTION2RT) + FATE_VP3-$(call DEMDEC, MATROSKA, THEORA) += fate-theora-coeff-level64 fate-theora-coeff-level64: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/coeff_level64.mkv +FATE_VP3-$(call DEMDEC, OGG, THEORA) += fate-theora-offset +fate-theora-offset: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/offset_test.ogv + FATE_VP3-$(call DEMDEC, AVI, VP3) += fate-vp31 fate-vp31: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/vp31.avi diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak index 3432cc6..05538f0 100644 --- a/tests/fate/wavpack.mak +++ b/tests/fate/wavpack.mak @@ -91,12 +91,12 @@ fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matros FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono fate-wavpack-matroska_mux-mono: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-mono: CMP = oneline -fate-wavpack-matroska_mux-mono: REF = 6bd769b3f0e9d7fa6261c3b73a53eb7d +fate-wavpack-matroska_mux-mono: REF = f87d2356f34e1ac0d6a873fac8bc0453 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61 fate-wavpack-matroska_mux-61: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-61: CMP = oneline -fate-wavpack-matroska_mux-61: REF = 2d2f1e7f81a8b1983fcffc7f24de8a11 +fate-wavpack-matroska_mux-61: REF = 6926fde4cb74ec63a5f21a26bec62688 FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes) fate-wavpack: $(FATE_WAVPACK-yes) diff --git a/tests/fate/wma.mak b/tests/fate/wma.mak index 1b8c5f9..d2cf4a2 100644 --- a/tests/fate/wma.mak +++ b/tests/fate/wma.mak @@ -1,10 +1,10 @@ FATE_WMAPRO-$(call DEMDEC, ASF, WMAPRO) += fate-wmapro-2ch -fate-wmapro-2ch: CMD = pcm -i $(TARGET_SAMPLES)/wmapro/Beethovens_9th-1_small.wma -fate-wmapro-2ch: REF = $(SAMPLES)/wmapro/Beethovens_9th-1_small.pcm +fate-wmapro-2ch: CMD = pcm -i $(TARGET_SAMPLES)/wmapro/Beethovens_9th-1_small.wma -frames 43 +fate-wmapro-2ch: REF = $(SAMPLES)/wmapro/Beethovens_9th-1_small_v2.pcm FATE_WMAPRO-$(call DEMDEC, ASF, WMAPRO) += fate-wmapro-5.1 -fate-wmapro-5.1: CMD = pcm -i $(TARGET_SAMPLES)/wmapro/latin_192_mulitchannel_cut.wma -fate-wmapro-5.1: REF = $(SAMPLES)/wmapro/latin_192_mulitchannel_cut.pcm +fate-wmapro-5.1: CMD = pcm -i $(TARGET_SAMPLES)/wmapro/latin_192_mulitchannel_cut.wma -frames 101 +fate-wmapro-5.1: REF = $(SAMPLES)/wmapro/latin_192_mulitchannel_cut_v2.pcm FATE_WMAPRO-$(call DEMDEC, MOV, WMAPRO) += fate-wmapro-ism fate-wmapro-ism: CMD = pcm -i $(TARGET_SAMPLES)/isom/vc1-wmapro.ism -vn diff --git a/tests/fate/xvid.mak b/tests/fate/xvid.mak index 68f01b5..877b2a1 100644 --- a/tests/fate/xvid.mak +++ b/tests/fate/xvid.mak @@ -1,8 +1,7 @@ fate-xvid-custom-matrix: CMD = framemd5 -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/xvid_vlc_trac7411.h263 -fate-xvid-idctmmx: CMD = framemd5 -flags +bitexact -cpuflags all -i $(TARGET_SAMPLES)/mpeg4/xvid_vlc_trac7411.h263 +fate-xvid-idct: CMD = framemd5 -flags +bitexact -cpuflags all -i $(TARGET_SAMPLES)/mpeg4/xvid_vlc_trac7411.h263 -FATE_XVID-$(call DEMDEC, M4V, MPEG4) += fate-xvid-custom-matrix -FATE_XVID-$(filter $(HAVE_MMX_INLINE), $(call DEMDEC, M4V, MPEG4)) += fate-xvid-idctmmx +FATE_XVID-$(call DEMDEC, M4V, MPEG4) += fate-xvid-custom-matrix fate-xvid-idct FATE_SAMPLES_AVCONV += $(FATE_XVID-yes) diff --git a/tests/ref/fate/aasc b/tests/ref/fate/aasc index 57d59a9..83f83b9 100644 --- a/tests/ref/fate/aasc +++ b/tests/ref/fate/aasc @@ -22,3 +22,4 @@ 0, 20, 20, 1, 168000, 0x7a2b1006 0, 21, 21, 1, 168000, 0xc7ca1345 0, 22, 22, 1, 168000, 0x8841c413 +0, 23, 23, 1, 168000, 0xbaed0290 diff --git a/tests/ref/fate/aic-oddsize b/tests/ref/fate/aic-oddsize new file mode 100644 index 0000000..ba4a625 --- /dev/null +++ b/tests/ref/fate/aic-oddsize @@ -0,0 +1,58 @@ +#tb 0: 1/14587 +0, 0, 0, 0, 174243, 0xa40491e1 +0, 1000, 1000, 0, 174243, 0xa12cbb56 +0, 2000, 2000, 0, 174243, 0xa12cbb56 +0, 3000, 3000, 0, 174243, 0xa12cbb56 +0, 4000, 4000, 0, 174243, 0xa12cbb56 +0, 5000, 5000, 0, 174243, 0xa12cbb56 +0, 6000, 6000, 0, 174243, 0xa12cbb56 +0, 7000, 7000, 0, 174243, 0xa12cbb56 +0, 8000, 8000, 0, 174243, 0xa12cbb56 +0, 9000, 9000, 0, 174243, 0x4e7b7299 +0, 10000, 10000, 0, 174243, 0x31573b99 +0, 11000, 11000, 0, 174243, 0x013397b6 +0, 12000, 12000, 0, 174243, 0xdd988ab8 +0, 13000, 13000, 0, 174243, 0xd6d96b1e +0, 14000, 14000, 0, 174243, 0xd6d96b1e +0, 15000, 15000, 0, 174243, 0xd6d96b1e +0, 16000, 16000, 0, 174243, 0x111627d3 +0, 17000, 17000, 0, 174243, 0x284d9ab7 +0, 18000, 18000, 0, 174243, 0xa348c492 +0, 19000, 19000, 0, 174243, 0xa348c492 +0, 20000, 20000, 0, 174243, 0xa348c492 +0, 21000, 21000, 0, 174243, 0xa348c492 +0, 22000, 22000, 0, 174243, 0x2d22c3b8 +0, 23000, 23000, 0, 174243, 0x2d22c3b8 +0, 24000, 24000, 0, 174243, 0x2d22c3b8 +0, 25000, 25000, 0, 174243, 0x2d22c3b8 +0, 26000, 26000, 0, 174243, 0xa6d7c890 +0, 27000, 27000, 0, 174243, 0x8068bfbb +0, 28000, 28000, 0, 174243, 0x420ae647 +0, 29000, 29000, 0, 174243, 0xc5467756 +0, 30000, 30000, 0, 174243, 0x238a13dd +0, 31000, 31000, 0, 174243, 0x5bab75dc +0, 32000, 32000, 0, 174243, 0x14d7f61f +0, 33000, 33000, 0, 174243, 0x2e1d334f +0, 34000, 34000, 0, 174243, 0xeade7dc0 +0, 35000, 35000, 0, 174243, 0xeade7dc0 +0, 36000, 36000, 0, 174243, 0xeade7dc0 +0, 37000, 37000, 0, 174243, 0xeade7dc0 +0, 38000, 38000, 0, 174243, 0x088c7ef9 +0, 39000, 39000, 0, 174243, 0x70a3554e +0, 40000, 40000, 0, 174243, 0x0753d1d4 +0, 41000, 41000, 0, 174243, 0x8266bd6d +0, 42000, 42000, 0, 174243, 0x4ce3cda9 +0, 43000, 43000, 0, 174243, 0x4ce3cda9 +0, 44000, 44000, 0, 174243, 0x4ce3cda9 +0, 45000, 45000, 0, 174243, 0x4ce3cda9 +0, 46000, 46000, 0, 174243, 0xe5f7cd98 +0, 47000, 47000, 0, 174243, 0xe5f7cd98 +0, 48000, 48000, 0, 174243, 0xe5f7cd98 +0, 49000, 49000, 0, 174243, 0xe5f7cd98 +0, 50000, 50000, 0, 174243, 0x78c5cdb7 +0, 51000, 51000, 0, 174243, 0x78c5cdb7 +0, 52000, 52000, 0, 174243, 0x78c5cdb7 +0, 53000, 53000, 0, 174243, 0xce7ccd92 +0, 54000, 54000, 0, 174243, 0xce7ccd92 +0, 55000, 55000, 0, 174243, 0xce7ccd92 +0, 56000, 56000, 0, 174243, 0xce7ccd92 diff --git a/tests/ref/fate/asf-repldata b/tests/ref/fate/asf-repldata new file mode 100644 index 0000000..5abc9da --- /dev/null +++ b/tests/ref/fate/asf-repldata @@ -0,0 +1,15 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 23374, 0x8725b3b8 +0, 122, 122, 0, 13732, 0x3ac8531a +0, 245, 245, 0, 615, 0xd31641b4 +0, 367, 367, 0, 6361, 0xf263af54 +0, 490, 490, 0, 320, 0xd6f2d6b8 +0, 612, 612, 0, 3750, 0xfcf1d501 +0, 735, 735, 0, 2541, 0xd9fc04f9 +0, 857, 857, 0, 205, 0x4d38a947 +0, 980, 980, 0, 2166, 0x2f1e7d74 +0, 1102, 1102, 0, 1667, 0x0cd84b61 +0, 1224, 1224, 0, 13645, 0x543bd032 +0, 1347, 1347, 0, 5953, 0xc3037c73 +0, 1469, 1469, 0, 36169, 0xca9f716d +0, 1592, 1592, 0, 3030, 0x9aba5683 diff --git a/tests/ref/fate/cllc-argb b/tests/ref/fate/canopus-cllc-argb similarity index 81% rename from tests/ref/fate/cllc-argb rename to tests/ref/fate/canopus-cllc-argb index 0283863..4a5dce5 100644 --- a/tests/ref/fate/cllc-argb +++ b/tests/ref/fate/canopus-cllc-argb @@ -3,3 +3,4 @@ 0, 1, 1, 1, 3686400, 0x66a45032 0, 2, 2, 1, 3686400, 0xdf0c861f 0, 3, 3, 1, 3686400, 0xa4a68cdb +0, 4, 4, 1, 3686400, 0xb5f9526e diff --git a/tests/ref/fate/cllc-rgb b/tests/ref/fate/canopus-cllc-rgb similarity index 93% rename from tests/ref/fate/cllc-rgb rename to tests/ref/fate/canopus-cllc-rgb index 06d54da..b4ca055 100644 --- a/tests/ref/fate/cllc-rgb +++ b/tests/ref/fate/canopus-cllc-rgb @@ -13,3 +13,4 @@ 0, 11, 11, 1, 921600, 0x4d7488fa 0, 12, 12, 1, 921600, 0x16b9c9c9 0, 13, 13, 1, 921600, 0xa0a4f77f +0, 14, 14, 1, 921600, 0xf61a5501 diff --git a/tests/ref/fate/cllc-yuy2-noblock b/tests/ref/fate/canopus-cllc-yuy2-noblock similarity index 93% rename from tests/ref/fate/cllc-yuy2-noblock rename to tests/ref/fate/canopus-cllc-yuy2-noblock index 2cb9e78..6ad59d5 100644 --- a/tests/ref/fate/cllc-yuy2-noblock +++ b/tests/ref/fate/canopus-cllc-yuy2-noblock @@ -14,3 +14,4 @@ 0, 12, 12, 1, 614400, 0x2d8fd7cc 0, 13, 13, 1, 614400, 0xd9dfc2ef 0, 14, 14, 1, 614400, 0xaf95cef0 +0, 15, 15, 1, 614400, 0x6dcf5ed6 diff --git a/tests/ref/fate/canopus-hq_hqa-hq b/tests/ref/fate/canopus-hq_hqa-hq new file mode 100644 index 0000000..ca376dc --- /dev/null +++ b/tests/ref/fate/canopus-hq_hqa-hq @@ -0,0 +1,9 @@ +#tb 0: 1/25 +0, 0, 0, 1, 829440, 0x8b6b2f6d +0, 1, 1, 1, 829440, 0x70382bf0 +0, 2, 2, 1, 829440, 0xbfdf1f8d +0, 3, 3, 1, 829440, 0x27587282 +0, 4, 4, 1, 829440, 0x54655f5d +0, 5, 5, 1, 829440, 0xe31bff92 +0, 6, 6, 1, 829440, 0x10ec4a8b +0, 7, 7, 1, 829440, 0x0a5773e7 diff --git a/tests/ref/fate/canopus-hq_hqa-hqa b/tests/ref/fate/canopus-hq_hqa-hqa new file mode 100644 index 0000000..0996500 --- /dev/null +++ b/tests/ref/fate/canopus-hq_hqa-hqa @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 6220800, 0x2b2b17cc diff --git a/tests/ref/fate/canopus-hq_hqa-inter b/tests/ref/fate/canopus-hq_hqa-inter new file mode 100644 index 0000000..2880c95 --- /dev/null +++ b/tests/ref/fate/canopus-hq_hqa-inter @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 4147200, 0x418ecfe5 diff --git a/tests/ref/fate/canopus-hqx422 b/tests/ref/fate/canopus-hqx422 new file mode 100644 index 0000000..2e1fdf1 --- /dev/null +++ b/tests/ref/fate/canopus-hqx422 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 1658880, 0x823fcbac diff --git a/tests/ref/fate/canopus-hqx422a b/tests/ref/fate/canopus-hqx422a new file mode 100644 index 0000000..0fd2577 --- /dev/null +++ b/tests/ref/fate/canopus-hqx422a @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 8294400, 0x9a22bebf diff --git a/tests/ref/fate/cvid-partial b/tests/ref/fate/cvid-partial index 71596b4..907ef4a 100644 --- a/tests/ref/fate/cvid-partial +++ b/tests/ref/fate/cvid-partial @@ -77,3 +77,4 @@ 0, 75, 75, 1, 112400, 0xe4394f1f 0, 76, 76, 1, 112400, 0x8ca8649f 0, 77, 77, 1, 112400, 0x804d44eb +0, 78, 78, 1, 112400, 0x3864488b diff --git a/tests/ref/fate/dds-alpha8 b/tests/ref/fate/dds-alpha8 new file mode 100644 index 0000000..fbda288 --- /dev/null +++ b/tests/ref/fate/dds-alpha8 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 14884, 0xf81c47f5 diff --git a/tests/ref/fate/dds-argb b/tests/ref/fate/dds-argb new file mode 100644 index 0000000..fbde424 --- /dev/null +++ b/tests/ref/fate/dds-argb @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 56320, 0xfcaa920b diff --git a/tests/ref/fate/dds-argb-aexp b/tests/ref/fate/dds-argb-aexp new file mode 100644 index 0000000..f52410f --- /dev/null +++ b/tests/ref/fate/dds-argb-aexp @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xfdd37c43 diff --git a/tests/ref/fate/dds-dx10-bc1 b/tests/ref/fate/dds-dx10-bc1 new file mode 100644 index 0000000..84efd9f --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc1 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xed2f850f diff --git a/tests/ref/fate/dds-dx10-bc1a b/tests/ref/fate/dds-dx10-bc1a new file mode 100644 index 0000000..8cb4589 --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc1a @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x473b484b diff --git a/tests/ref/fate/dds-dx10-bc2 b/tests/ref/fate/dds-dx10-bc2 new file mode 100644 index 0000000..a25180d --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc2 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x2bce3baa diff --git a/tests/ref/fate/dds-dx10-bc3 b/tests/ref/fate/dds-dx10-bc3 new file mode 100644 index 0000000..296c945 --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc3 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xb91d3c62 diff --git a/tests/ref/fate/dds-dx10-bc4 b/tests/ref/fate/dds-dx10-bc4 new file mode 100644 index 0000000..4583d25 --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc4 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xfdfd1751 diff --git a/tests/ref/fate/dds-dx10-bc5 b/tests/ref/fate/dds-dx10-bc5 new file mode 100644 index 0000000..bf595eb --- /dev/null +++ b/tests/ref/fate/dds-dx10-bc5 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x79bd207e diff --git a/tests/ref/fate/dds-dxt1 b/tests/ref/fate/dds-dxt1 new file mode 100644 index 0000000..2477406 --- /dev/null +++ b/tests/ref/fate/dds-dxt1 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 32768, 0xf52adc80 diff --git a/tests/ref/fate/dds-dxt1-normalmap b/tests/ref/fate/dds-dxt1-normalmap new file mode 100644 index 0000000..3f77547 --- /dev/null +++ b/tests/ref/fate/dds-dxt1-normalmap @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x2b411855 diff --git a/tests/ref/fate/dds-dxt1a b/tests/ref/fate/dds-dxt1a new file mode 100644 index 0000000..05be314 --- /dev/null +++ b/tests/ref/fate/dds-dxt1a @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xcabb50ea diff --git a/tests/ref/fate/dds-dxt2 b/tests/ref/fate/dds-dxt2 new file mode 100644 index 0000000..40bcf6e --- /dev/null +++ b/tests/ref/fate/dds-dxt2 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x11cebeb0 diff --git a/tests/ref/fate/dds-dxt3 b/tests/ref/fate/dds-dxt3 new file mode 100644 index 0000000..41401da --- /dev/null +++ b/tests/ref/fate/dds-dxt3 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x729b74ba diff --git a/tests/ref/fate/dds-dxt4 b/tests/ref/fate/dds-dxt4 new file mode 100644 index 0000000..dc5d73f --- /dev/null +++ b/tests/ref/fate/dds-dxt4 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x31aaacd6 diff --git a/tests/ref/fate/dds-dxt5 b/tests/ref/fate/dds-dxt5 new file mode 100644 index 0000000..399d6d9 --- /dev/null +++ b/tests/ref/fate/dds-dxt5 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xfd3166aa diff --git a/tests/ref/fate/dds-dxt5-aexp b/tests/ref/fate/dds-dxt5-aexp new file mode 100644 index 0000000..ff91afd --- /dev/null +++ b/tests/ref/fate/dds-dxt5-aexp @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x3c987914 diff --git a/tests/ref/fate/dds-dxt5-normalmap b/tests/ref/fate/dds-dxt5-normalmap new file mode 100644 index 0000000..680d1b7 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-normalmap @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xd29b1ea1 diff --git a/tests/ref/fate/dds-dxt5-normalmap-ati b/tests/ref/fate/dds-dxt5-normalmap-ati new file mode 100644 index 0000000..7f088f7 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-normalmap-ati @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x54cb212f diff --git a/tests/ref/fate/dds-dxt5-rbxg b/tests/ref/fate/dds-dxt5-rbxg new file mode 100644 index 0000000..7dbecf4 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-rbxg @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x37588d12 diff --git a/tests/ref/fate/dds-dxt5-rgxb b/tests/ref/fate/dds-dxt5-rgxb new file mode 100644 index 0000000..137913d --- /dev/null +++ b/tests/ref/fate/dds-dxt5-rgxb @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xfb6b91cf diff --git a/tests/ref/fate/dds-dxt5-rxbg b/tests/ref/fate/dds-dxt5-rxbg new file mode 100644 index 0000000..b6e12d3 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-rxbg @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xc6cb8cbe diff --git a/tests/ref/fate/dds-dxt5-rxgb b/tests/ref/fate/dds-dxt5-rxgb new file mode 100644 index 0000000..a4190d5 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-rxgb @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xb67d936a diff --git a/tests/ref/fate/dds-dxt5-xgbr b/tests/ref/fate/dds-dxt5-xgbr new file mode 100644 index 0000000..95404f2 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-xgbr @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xb0e69293 diff --git a/tests/ref/fate/dds-dxt5-xgxr b/tests/ref/fate/dds-dxt5-xgxr new file mode 100644 index 0000000..3ed73c3 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-xgxr @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xa93de1ad diff --git a/tests/ref/fate/dds-dxt5-xrbg b/tests/ref/fate/dds-dxt5-xrbg new file mode 100644 index 0000000..f647955 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-xrbg @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xf20d8b69 diff --git a/tests/ref/fate/dds-dxt5-ycocg b/tests/ref/fate/dds-dxt5-ycocg new file mode 100644 index 0000000..1dd8bef --- /dev/null +++ b/tests/ref/fate/dds-dxt5-ycocg @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x0d0c8d20 diff --git a/tests/ref/fate/dds-dxt5-ycocg-scaled b/tests/ref/fate/dds-dxt5-ycocg-scaled new file mode 100644 index 0000000..5a70b49 --- /dev/null +++ b/tests/ref/fate/dds-dxt5-ycocg-scaled @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x5a089973 diff --git a/tests/ref/fate/dds-monob b/tests/ref/fate/dds-monob new file mode 100644 index 0000000..370a431 --- /dev/null +++ b/tests/ref/fate/dds-monob @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 1952, 0x716498a1 diff --git a/tests/ref/fate/dds-pal b/tests/ref/fate/dds-pal new file mode 100644 index 0000000..575a4bd --- /dev/null +++ b/tests/ref/fate/dds-pal @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 65536, 0x4287e5cd diff --git a/tests/ref/fate/dds-pal-ati b/tests/ref/fate/dds-pal-ati new file mode 100644 index 0000000..6de8adb --- /dev/null +++ b/tests/ref/fate/dds-pal-ati @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x6ac18060 diff --git a/tests/ref/fate/dds-rgb1555 b/tests/ref/fate/dds-rgb1555 new file mode 100644 index 0000000..a23d0e5 --- /dev/null +++ b/tests/ref/fate/dds-rgb1555 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 29768, 0xbdc099db diff --git a/tests/ref/fate/dds-rgb16 b/tests/ref/fate/dds-rgb16 new file mode 100644 index 0000000..40a9938 --- /dev/null +++ b/tests/ref/fate/dds-rgb16 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xc8910265 diff --git a/tests/ref/fate/dds-rgb24 b/tests/ref/fate/dds-rgb24 new file mode 100644 index 0000000..3eeb1eb --- /dev/null +++ b/tests/ref/fate/dds-rgb24 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 24576, 0xef0f9653 diff --git a/tests/ref/fate/dds-rgb555 b/tests/ref/fate/dds-rgb555 new file mode 100644 index 0000000..65ac119 --- /dev/null +++ b/tests/ref/fate/dds-rgb555 @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 29768, 0x277d8628 diff --git a/tests/ref/fate/dds-rgba b/tests/ref/fate/dds-rgba new file mode 100644 index 0000000..803b40a --- /dev/null +++ b/tests/ref/fate/dds-rgba @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 25600, 0xa2a47b2f diff --git a/tests/ref/fate/dds-rgtc1s b/tests/ref/fate/dds-rgtc1s new file mode 100644 index 0000000..5085962 --- /dev/null +++ b/tests/ref/fate/dds-rgtc1s @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xcda652a4 diff --git a/tests/ref/fate/dds-rgtc1u b/tests/ref/fate/dds-rgtc1u new file mode 100644 index 0000000..b7cff66 --- /dev/null +++ b/tests/ref/fate/dds-rgtc1u @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x629a1b44 diff --git a/tests/ref/fate/dds-rgtc2s b/tests/ref/fate/dds-rgtc2s new file mode 100644 index 0000000..7227602 --- /dev/null +++ b/tests/ref/fate/dds-rgtc2s @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0xa0135ca8 diff --git a/tests/ref/fate/dds-rgtc2u b/tests/ref/fate/dds-rgtc2u new file mode 100644 index 0000000..0b6678b --- /dev/null +++ b/tests/ref/fate/dds-rgtc2u @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x38cb221a diff --git a/tests/ref/fate/dds-rgtc2u-xy b/tests/ref/fate/dds-rgtc2u-xy new file mode 100644 index 0000000..bf595eb --- /dev/null +++ b/tests/ref/fate/dds-rgtc2u-xy @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x79bd207e diff --git a/tests/ref/fate/dds-uyvy b/tests/ref/fate/dds-uyvy new file mode 100644 index 0000000..2bcbaa0 --- /dev/null +++ b/tests/ref/fate/dds-uyvy @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 8192, 0x3c658750 diff --git a/tests/ref/fate/dds-xbgr b/tests/ref/fate/dds-xbgr new file mode 100644 index 0000000..eb7a024 --- /dev/null +++ b/tests/ref/fate/dds-xbgr @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x70336a28 diff --git a/tests/ref/fate/dds-xrgb b/tests/ref/fate/dds-xrgb new file mode 100644 index 0000000..63e5225 --- /dev/null +++ b/tests/ref/fate/dds-xrgb @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x702f6a28 diff --git a/tests/ref/fate/dds-y b/tests/ref/fate/dds-y new file mode 100644 index 0000000..ae62091 --- /dev/null +++ b/tests/ref/fate/dds-y @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 8192, 0x56eca90f diff --git a/tests/ref/fate/dds-ya b/tests/ref/fate/dds-ya new file mode 100644 index 0000000..01f7894 --- /dev/null +++ b/tests/ref/fate/dds-ya @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 28160, 0x5aa41fcb diff --git a/tests/ref/fate/dds-ycocg b/tests/ref/fate/dds-ycocg new file mode 100644 index 0000000..f3dd727 --- /dev/null +++ b/tests/ref/fate/dds-ycocg @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 16384, 0x4cb08d0a diff --git a/tests/ref/fate/dds-yuyv b/tests/ref/fate/dds-yuyv new file mode 100644 index 0000000..e65c950 --- /dev/null +++ b/tests/ref/fate/dds-yuyv @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 8192, 0xc1108750 diff --git a/tests/ref/fate/dpxparser b/tests/ref/fate/dpxparser new file mode 100644 index 0000000..025c87d --- /dev/null +++ b/tests/ref/fate/dpxparser @@ -0,0 +1,5 @@ +#tb 0: 1/25 +0, 0, 0, 1, 203280, 0xa7d03ff5 +0, 1, 1, 1, 203280, 0xb908d8d4 +0, 2, 2, 1, 203280, 0xf7900408 +0, 3, 3, 1, 203280, 0xb74ed6a8 diff --git a/tests/ref/fate/dss-lp b/tests/ref/fate/dss-lp new file mode 100644 index 0000000..b5bee18 --- /dev/null +++ b/tests/ref/fate/dss-lp @@ -0,0 +1,31 @@ +#tb 0: 1/8000 +0, 0, 0, 240, 480, 0xf1107658 +0, 240, 240, 240, 480, 0x50dee179 +0, 480, 480, 240, 480, 0x40090802 +0, 720, 720, 240, 480, 0x3ef9f6ff +0, 960, 960, 240, 480, 0x5b7df231 +0, 1200, 1200, 240, 480, 0xe266efd1 +0, 1440, 1440, 240, 480, 0xfbe6e658 +0, 1680, 1680, 240, 480, 0xde84f311 +0, 1920, 1920, 240, 480, 0x5854ec2f +0, 2160, 2160, 240, 480, 0x4901cdea +0, 2400, 2400, 240, 480, 0x03f3e619 +0, 2640, 2640, 240, 480, 0x47abfe87 +0, 2880, 2880, 240, 480, 0x69dddf34 +0, 3120, 3120, 240, 480, 0x1cfeee2c +0, 3360, 3360, 240, 480, 0x1860ef1c +0, 3600, 3600, 240, 480, 0x8f86e8ed +0, 3840, 3840, 240, 480, 0x307deaf8 +0, 4080, 4080, 240, 480, 0xeca7eca0 +0, 4320, 4320, 240, 480, 0x1835ee1c +0, 4560, 4560, 240, 480, 0x6676ed66 +0, 4800, 4800, 240, 480, 0x49c2fd04 +0, 5040, 5040, 240, 480, 0xc463db75 +0, 5280, 5280, 240, 480, 0x1931ed7d +0, 5520, 5520, 240, 480, 0xc99ff886 +0, 5760, 5760, 240, 480, 0xcd3ae8de +0, 6000, 6000, 240, 480, 0x2294ecfa +0, 6240, 6240, 240, 480, 0xcf5ef14b +0, 6480, 6480, 240, 480, 0x6325d4fe +0, 6720, 6720, 240, 480, 0x3790dcf2 +0, 6960, 6960, 240, 480, 0x0fbee6c0 diff --git a/tests/ref/fate/dss-sp b/tests/ref/fate/dss-sp new file mode 100644 index 0000000..111c621 --- /dev/null +++ b/tests/ref/fate/dss-sp @@ -0,0 +1,31 @@ +#tb 0: 1/11025 +0, 0, 0, 264, 528, 0xa2579e96 +0, 264, 264, 264, 528, 0xf9b23172 +0, 528, 528, 264, 528, 0x5571a0fe +0, 792, 792, 264, 528, 0x2c989245 +0, 1056, 1056, 264, 528, 0xc4d3b5b5 +0, 1320, 1320, 264, 528, 0x0becb08d +0, 1584, 1584, 264, 528, 0x71537374 +0, 1848, 1848, 264, 528, 0xed6e4784 +0, 2112, 2112, 264, 528, 0x8dc73f7e +0, 2376, 2376, 264, 528, 0x20804ba8 +0, 2640, 2640, 264, 528, 0xcfdd4803 +0, 2904, 2904, 264, 528, 0x6fad0da5 +0, 3168, 3168, 264, 528, 0xeaa41f45 +0, 3432, 3432, 264, 528, 0x99ef463e +0, 3696, 3696, 264, 528, 0x5a8c256a +0, 3960, 3960, 264, 528, 0x668c253a +0, 4224, 4224, 264, 528, 0x29890b2e +0, 4488, 4488, 264, 528, 0x6cd51639 +0, 4752, 4752, 264, 528, 0x6cc95342 +0, 5016, 5016, 264, 528, 0x2bdc59ea +0, 5280, 5280, 264, 528, 0x72ff263d +0, 5544, 5544, 264, 528, 0xb5bd3592 +0, 5808, 5808, 264, 528, 0x16de4402 +0, 6072, 6072, 264, 528, 0x80195ab4 +0, 6336, 6336, 264, 528, 0x425c594c +0, 6600, 6600, 264, 528, 0x04b32203 +0, 6864, 6864, 264, 528, 0x688a38ec +0, 7128, 7128, 264, 528, 0x34531167 +0, 7392, 7392, 264, 528, 0xdef83475 +0, 7656, 7656, 264, 528, 0xf5fe3fe5 diff --git a/tests/ref/fate/dxtory b/tests/ref/fate/dxtory index 7d3ecbd..8cee5ef 100644 --- a/tests/ref/fate/dxtory +++ b/tests/ref/fate/dxtory @@ -1,3 +1,2 @@ #tb 0: 1/25 -#tb 1: 1/48000 0, 0, 0, 1, 1382400, 0x44373645 diff --git a/tests/ref/fate/dxv-dxt1 b/tests/ref/fate/dxv-dxt1 new file mode 100644 index 0000000..9b49380 --- /dev/null +++ b/tests/ref/fate/dxv-dxt1 @@ -0,0 +1,2 @@ +#tb 0: 1/30000 +0, 0, 0, 0, 8294400, 0x0797cd53 diff --git a/tests/ref/fate/dxv-dxt5 b/tests/ref/fate/dxv-dxt5 new file mode 100644 index 0000000..9b49380 --- /dev/null +++ b/tests/ref/fate/dxv-dxt5 @@ -0,0 +1,2 @@ +#tb 0: 1/30000 +0, 0, 0, 0, 8294400, 0x0797cd53 diff --git a/tests/ref/fate/dxv3-dxt1 b/tests/ref/fate/dxv3-dxt1 new file mode 100644 index 0000000..c65ead9 --- /dev/null +++ b/tests/ref/fate/dxv3-dxt1 @@ -0,0 +1,2 @@ +#tb 0: 1/30000 +0, 0, 0, 0, 8294400, 0x98bbcc85 diff --git a/tests/ref/fate/dxv3-dxt5 b/tests/ref/fate/dxv3-dxt5 new file mode 100644 index 0000000..9b49380 --- /dev/null +++ b/tests/ref/fate/dxv3-dxt5 @@ -0,0 +1,2 @@ +#tb 0: 1/30000 +0, 0, 0, 0, 8294400, 0x0797cd53 diff --git a/tests/ref/fate/ea-mad b/tests/ref/fate/ea-mad index ce1df4a..1ea92fd 100644 --- a/tests/ref/fate/ea-mad +++ b/tests/ref/fate/ea-mad @@ -1,97 +1,97 @@ -#tb 0: 1/90000 -0, 0, 0, 0, 535680, 0x889c32cf -0, 2970, 2970, 0, 535680, 0x0b1ef044 -0, 5940, 5940, 0, 535680, 0xa7d0818b -0, 8910, 8910, 0, 535680, 0xf392e4e1 -0, 11880, 11880, 0, 535680, 0x08480c69 -0, 14850, 14850, 0, 535680, 0x2b8af1ed -0, 17820, 17820, 0, 535680, 0x0d58e062 -0, 20790, 20790, 0, 535680, 0xd140ced0 -0, 23760, 23760, 0, 535680, 0xbd0e6652 -0, 26730, 26730, 0, 535680, 0xdc2f2a6b -0, 29700, 29700, 0, 535680, 0x97c31a38 -0, 32670, 32670, 0, 535680, 0x1a2bdf38 -0, 35640, 35640, 0, 535680, 0xb3af3ac4 -0, 38610, 38610, 0, 535680, 0x07a52577 -0, 41580, 41580, 0, 535680, 0x78407368 -0, 44550, 44550, 0, 535680, 0xd2a9efc3 -0, 47520, 47520, 0, 535680, 0x36df2f29 -0, 50490, 50490, 0, 535680, 0x9821d8f7 -0, 53460, 53460, 0, 535680, 0xf64321aa -0, 56430, 56430, 0, 535680, 0x53e4d9aa -0, 59400, 59400, 0, 535680, 0xdbd6f853 -0, 62370, 62370, 0, 535680, 0x5d40cf8b -0, 65340, 65340, 0, 535680, 0xe624af9d -0, 68310, 68310, 0, 535680, 0xd9dbb4cd -0, 71280, 71280, 0, 535680, 0xf14e72ec -0, 74250, 74250, 0, 535680, 0xb35c18f6 -0, 77220, 77220, 0, 535680, 0xc96d7757 -0, 80190, 80190, 0, 535680, 0xdfb937df -0, 83160, 83160, 0, 535680, 0x40cd71d7 -0, 86130, 86130, 0, 535680, 0x15e176d6 -0, 89100, 89100, 0, 535680, 0x7f891b24 -0, 92070, 92070, 0, 535680, 0xb87a8c32 -0, 95040, 95040, 0, 535680, 0x0c01541f -0, 98010, 98010, 0, 535680, 0x9eee99b3 -0, 100980, 100980, 0, 535680, 0xd65eb689 -0, 103950, 103950, 0, 535680, 0x6e733cfa -0, 106920, 106920, 0, 535680, 0xac536670 -0, 109890, 109890, 0, 535680, 0x002275b8 -0, 112860, 112860, 0, 535680, 0x6a5385cb -0, 115830, 115830, 0, 535680, 0xd129ade3 -0, 118800, 118800, 0, 535680, 0x32cab5d7 -0, 121770, 121770, 0, 535680, 0x08be1c8f -0, 124740, 124740, 0, 535680, 0x59e1fba0 -0, 127710, 127710, 0, 535680, 0x138aee3a -0, 130680, 130680, 0, 535680, 0x4cfbcd5e -0, 133650, 133650, 0, 535680, 0xf6cf0fb4 -0, 136620, 136620, 0, 535680, 0xb13a06de -0, 139590, 139590, 0, 535680, 0x59176f00 -0, 142560, 142560, 0, 535680, 0xf84b4ca3 -0, 145530, 145530, 0, 535680, 0x7fd09f73 -0, 148500, 148500, 0, 535680, 0x3be383b8 -0, 151470, 151470, 0, 535680, 0xa7118e51 -0, 154440, 154440, 0, 535680, 0xbd83120c -0, 157410, 157410, 0, 535680, 0x3bc9d256 -0, 160380, 160380, 0, 535680, 0xb6c87f87 -0, 163350, 163350, 0, 535680, 0xe80d110a -0, 166320, 166320, 0, 535680, 0xb3a83362 -0, 169290, 169290, 0, 535680, 0xfb39eb52 -0, 172260, 172260, 0, 535680, 0xbf6e1220 -0, 175230, 175230, 0, 535680, 0x9ecdfbae -0, 178200, 178200, 0, 535680, 0x069a65f5 -0, 181170, 181170, 0, 535680, 0x206e372c -0, 184140, 184140, 0, 535680, 0x58c83dd4 -0, 187110, 187110, 0, 535680, 0xc3562b03 -0, 190080, 190080, 0, 535680, 0xd1ed85a0 -0, 193050, 193050, 0, 535680, 0xb6205f4b -0, 196020, 196020, 0, 535680, 0xaedf8bfa -0, 198990, 198990, 0, 535680, 0xa48d5dea -0, 201960, 201960, 0, 535680, 0xff82e7c1 -0, 204930, 204930, 0, 535680, 0xc9560222 -0, 207900, 207900, 0, 535680, 0x0fafa549 -0, 210870, 210870, 0, 535680, 0x8d556ccb -0, 213840, 213840, 0, 535680, 0x802aac1f -0, 216810, 216810, 0, 535680, 0x7d0fa168 -0, 219780, 219780, 0, 535680, 0x1a9255c9 -0, 222750, 222750, 0, 535680, 0xb4ec7e35 -0, 225720, 225720, 0, 535680, 0x48fac072 -0, 228690, 228690, 0, 535680, 0x1e260135 -0, 231660, 231660, 0, 535680, 0xce4d5079 -0, 234630, 234630, 0, 535680, 0x13e5e4ed -0, 237600, 237600, 0, 535680, 0x592305ec -0, 240570, 240570, 0, 535680, 0x9e227508 -0, 243540, 243540, 0, 535680, 0x1d37e5ea -0, 246510, 246510, 0, 535680, 0x7eae7692 -0, 249480, 249480, 0, 535680, 0xf452e4b9 -0, 252450, 252450, 0, 535680, 0x1460e7e9 -0, 255420, 255420, 0, 535680, 0xc6d8a638 -0, 258390, 258390, 0, 535680, 0x854f5fb0 -0, 261360, 261360, 0, 535680, 0x854f5fb0 -0, 264330, 264330, 0, 535680, 0x70a02d87 -0, 267300, 267300, 0, 535680, 0x9a4ad464 -0, 270270, 270270, 0, 535680, 0x9a4ad464 -0, 273240, 273240, 0, 535680, 0x9a4ad464 -0, 276210, 276210, 0, 535680, 0x9a4ad464 -0, 279180, 279180, 0, 535680, 0x9a4ad464 -0, 282150, 282150, 0, 535680, 0x9a4ad464 +#tb 0: 33/1000 +0, 0, 0, 1, 535680, 0x889c32cf +0, 1, 1, 1, 535680, 0x0b1ef044 +0, 2, 2, 1, 535680, 0xa7d0818b +0, 3, 3, 1, 535680, 0xf392e4e1 +0, 4, 4, 1, 535680, 0x08480c69 +0, 5, 5, 1, 535680, 0x2b8af1ed +0, 6, 6, 1, 535680, 0x0d58e062 +0, 7, 7, 1, 535680, 0xd140ced0 +0, 8, 8, 1, 535680, 0xbd0e6652 +0, 9, 9, 1, 535680, 0xdc2f2a6b +0, 10, 10, 1, 535680, 0x97c31a38 +0, 11, 11, 1, 535680, 0x1a2bdf38 +0, 12, 12, 1, 535680, 0xb3af3ac4 +0, 13, 13, 1, 535680, 0x07a52577 +0, 14, 14, 1, 535680, 0x78407368 +0, 15, 15, 1, 535680, 0xd2a9efc3 +0, 16, 16, 1, 535680, 0x36df2f29 +0, 17, 17, 1, 535680, 0x9821d8f7 +0, 18, 18, 1, 535680, 0xf64321aa +0, 19, 19, 1, 535680, 0x53e4d9aa +0, 20, 20, 1, 535680, 0xdbd6f853 +0, 21, 21, 1, 535680, 0x5d40cf8b +0, 22, 22, 1, 535680, 0xe624af9d +0, 23, 23, 1, 535680, 0xd9dbb4cd +0, 24, 24, 1, 535680, 0xf14e72ec +0, 25, 25, 1, 535680, 0xb35c18f6 +0, 26, 26, 1, 535680, 0xc96d7757 +0, 27, 27, 1, 535680, 0xdfb937df +0, 28, 28, 1, 535680, 0x40cd71d7 +0, 29, 29, 1, 535680, 0x15e176d6 +0, 30, 30, 1, 535680, 0x7f891b24 +0, 31, 31, 1, 535680, 0xb87a8c32 +0, 32, 32, 1, 535680, 0x0c01541f +0, 33, 33, 1, 535680, 0x9eee99b3 +0, 34, 34, 1, 535680, 0xd65eb689 +0, 35, 35, 1, 535680, 0x6e733cfa +0, 36, 36, 1, 535680, 0xac536670 +0, 37, 37, 1, 535680, 0x002275b8 +0, 38, 38, 1, 535680, 0x6a5385cb +0, 39, 39, 1, 535680, 0xd129ade3 +0, 40, 40, 1, 535680, 0x32cab5d7 +0, 41, 41, 1, 535680, 0x08be1c8f +0, 42, 42, 1, 535680, 0x59e1fba0 +0, 43, 43, 1, 535680, 0x138aee3a +0, 44, 44, 1, 535680, 0x4cfbcd5e +0, 45, 45, 1, 535680, 0xf6cf0fb4 +0, 46, 46, 1, 535680, 0xb13a06de +0, 47, 47, 1, 535680, 0x59176f00 +0, 48, 48, 1, 535680, 0xf84b4ca3 +0, 49, 49, 1, 535680, 0x7fd09f73 +0, 50, 50, 1, 535680, 0x3be383b8 +0, 51, 51, 1, 535680, 0xa7118e51 +0, 52, 52, 1, 535680, 0xbd83120c +0, 53, 53, 1, 535680, 0x3bc9d256 +0, 54, 54, 1, 535680, 0xb6c87f87 +0, 55, 55, 1, 535680, 0xe80d110a +0, 56, 56, 1, 535680, 0xb3a83362 +0, 57, 57, 1, 535680, 0xfb39eb52 +0, 58, 58, 1, 535680, 0xbf6e1220 +0, 59, 59, 1, 535680, 0x9ecdfbae +0, 60, 60, 1, 535680, 0x069a65f5 +0, 61, 61, 1, 535680, 0x206e372c +0, 62, 62, 1, 535680, 0x58c83dd4 +0, 63, 63, 1, 535680, 0xc3562b03 +0, 64, 64, 1, 535680, 0xd1ed85a0 +0, 65, 65, 1, 535680, 0xb6205f4b +0, 66, 66, 1, 535680, 0xaedf8bfa +0, 67, 67, 1, 535680, 0xa48d5dea +0, 68, 68, 1, 535680, 0xff82e7c1 +0, 69, 69, 1, 535680, 0xc9560222 +0, 70, 70, 1, 535680, 0x0fafa549 +0, 71, 71, 1, 535680, 0x8d556ccb +0, 72, 72, 1, 535680, 0x802aac1f +0, 73, 73, 1, 535680, 0x7d0fa168 +0, 74, 74, 1, 535680, 0x1a9255c9 +0, 75, 75, 1, 535680, 0xb4ec7e35 +0, 76, 76, 1, 535680, 0x48fac072 +0, 77, 77, 1, 535680, 0x1e260135 +0, 78, 78, 1, 535680, 0xce4d5079 +0, 79, 79, 1, 535680, 0x13e5e4ed +0, 80, 80, 1, 535680, 0x592305ec +0, 81, 81, 1, 535680, 0x9e227508 +0, 82, 82, 1, 535680, 0x1d37e5ea +0, 83, 83, 1, 535680, 0x7eae7692 +0, 84, 84, 1, 535680, 0xf452e4b9 +0, 85, 85, 1, 535680, 0x1460e7e9 +0, 86, 86, 1, 535680, 0xc6d8a638 +0, 87, 87, 1, 535680, 0x854f5fb0 +0, 88, 88, 1, 535680, 0x854f5fb0 +0, 89, 89, 1, 535680, 0x70a02d87 +0, 90, 90, 1, 535680, 0x9a4ad464 +0, 91, 91, 1, 535680, 0x9a4ad464 +0, 92, 92, 1, 535680, 0x9a4ad464 +0, 93, 93, 1, 535680, 0x9a4ad464 +0, 94, 94, 1, 535680, 0x9a4ad464 +0, 95, 95, 1, 535680, 0x9a4ad464 diff --git a/tests/ref/fate/ea-tgq b/tests/ref/fate/ea-tgq index edb04fa..5c0648d 100644 --- a/tests/ref/fate/ea-tgq +++ b/tests/ref/fate/ea-tgq @@ -1,279 +1,279 @@ -#tb 0: 1/90000 -0, 0, 0, 0, 34944, 0xe33671a4 -0, 6000, 6000, 0, 34944, 0xe33671a4 -0, 12000, 12000, 0, 34944, 0xe33671a4 -0, 18000, 18000, 0, 34944, 0xe33671a4 -0, 24000, 24000, 0, 34944, 0xe33671a4 -0, 30000, 30000, 0, 34944, 0xe33671a4 -0, 36000, 36000, 0, 34944, 0xe33671a4 -0, 42000, 42000, 0, 34944, 0xe33671a4 -0, 48000, 48000, 0, 34944, 0xe33671a4 -0, 54000, 54000, 0, 34944, 0xe33671a4 -0, 60000, 60000, 0, 34944, 0xe33671a4 -0, 66000, 66000, 0, 34944, 0xe33671a4 -0, 72000, 72000, 0, 34944, 0xe33671a4 -0, 78000, 78000, 0, 34944, 0xe33671a4 -0, 84000, 84000, 0, 34944, 0xe33671a4 -0, 90000, 90000, 0, 34944, 0x63196b41 -0, 96000, 96000, 0, 34944, 0x308d6f10 -0, 102000, 102000, 0, 34944, 0x86026ced -0, 108000, 108000, 0, 34944, 0xaa6a6bc9 -0, 114000, 114000, 0, 34944, 0x58276ee3 -0, 120000, 120000, 0, 34944, 0x402d70c2 -0, 126000, 126000, 0, 34944, 0x948d74bf -0, 132000, 132000, 0, 34944, 0x3d31759c -0, 138000, 138000, 0, 34944, 0x638c734e -0, 144000, 144000, 0, 34944, 0xe218768a -0, 150000, 150000, 0, 34944, 0xed6678ff -0, 156000, 156000, 0, 34944, 0x381b7dda -0, 162000, 162000, 0, 34944, 0x216680e7 -0, 168000, 168000, 0, 34944, 0xaca5810f -0, 174000, 174000, 0, 34944, 0xf70b81eb -0, 180000, 180000, 0, 34944, 0x3675858b -0, 186000, 186000, 0, 34944, 0xa51188c3 -0, 192000, 192000, 0, 34944, 0x3a848bf1 -0, 198000, 198000, 0, 34944, 0x67608d4d -0, 204000, 204000, 0, 34944, 0xafe49165 -0, 210000, 210000, 0, 34944, 0x7e8a94a7 -0, 216000, 216000, 0, 34944, 0x3b889432 -0, 222000, 222000, 0, 34944, 0x97e89623 -0, 228000, 228000, 0, 34944, 0x07819793 -0, 234000, 234000, 0, 34944, 0xdac39b87 -0, 240000, 240000, 0, 34944, 0x4d8c9d93 -0, 246000, 246000, 0, 34944, 0xcf009fa7 -0, 252000, 252000, 0, 34944, 0x2f109f6e -0, 258000, 258000, 0, 34944, 0xcedda4eb -0, 264000, 264000, 0, 34944, 0xfe89a6df -0, 270000, 270000, 0, 34944, 0x195ea7a9 -0, 276000, 276000, 0, 34944, 0x9287ab92 -0, 282000, 282000, 0, 34944, 0x6d21af54 -0, 288000, 288000, 0, 34944, 0xd627b28b -0, 294000, 294000, 0, 34944, 0x3ad5b6fd -0, 300000, 300000, 0, 34944, 0x5101b64d -0, 306000, 306000, 0, 34944, 0xb968b8ca -0, 312000, 312000, 0, 34944, 0xa105b74a -0, 318000, 318000, 0, 34944, 0xc056bdd6 -0, 324000, 324000, 0, 34944, 0xec7fc1d9 -0, 330000, 330000, 0, 34944, 0x92c3c3e0 -0, 336000, 336000, 0, 34944, 0x9bffc45c -0, 342000, 342000, 0, 34944, 0x5aabca4b -0, 348000, 348000, 0, 34944, 0xcbdacb26 -0, 354000, 354000, 0, 34944, 0xed6cce3f -0, 360000, 360000, 0, 34944, 0xcc61cfb8 -0, 366000, 366000, 0, 34944, 0x7a97d427 -0, 372000, 372000, 0, 34944, 0x7cdbd5ec -0, 378000, 378000, 0, 34944, 0x5851d9c4 -0, 384000, 384000, 0, 34944, 0x69d5dd1d -0, 390000, 390000, 0, 34944, 0xdf30dcf4 -0, 396000, 396000, 0, 34944, 0x2359e084 -0, 402000, 402000, 0, 34944, 0xe0bae491 -0, 408000, 408000, 0, 34944, 0xa716e4fd -0, 414000, 414000, 0, 34944, 0xe48aeaf4 -0, 420000, 420000, 0, 34944, 0x0a0deb21 -0, 426000, 426000, 0, 34944, 0xe8a56e12 -0, 432000, 432000, 0, 34944, 0x0d72c98e -0, 438000, 438000, 0, 34944, 0x71a7bb9d -0, 444000, 444000, 0, 34944, 0xc0c8c108 -0, 450000, 450000, 0, 34944, 0x1d1fc3ba -0, 456000, 456000, 0, 34944, 0xebcfc67f -0, 462000, 462000, 0, 34944, 0x2921cb5b -0, 468000, 468000, 0, 34944, 0x793ed099 -0, 474000, 474000, 0, 34944, 0xefebd9e8 -0, 480000, 480000, 0, 34944, 0x163c2330 -0, 486000, 486000, 0, 34944, 0x35155672 -0, 492000, 492000, 0, 34944, 0x05474e2e -0, 498000, 498000, 0, 34944, 0x9433542f -0, 504000, 504000, 0, 34944, 0x777d5a13 -0, 510000, 510000, 0, 34944, 0x87526776 -0, 516000, 516000, 0, 34944, 0x4c3c72c1 -0, 522000, 522000, 0, 34944, 0x70407b87 -0, 528000, 528000, 0, 34944, 0x2358861d -0, 534000, 534000, 0, 34944, 0xec61923f -0, 540000, 540000, 0, 34944, 0x0bb2a0d4 -0, 546000, 546000, 0, 34944, 0x6b6d8624 -0, 552000, 552000, 0, 34944, 0x624761ec -0, 558000, 558000, 0, 34944, 0xff23b926 -0, 564000, 564000, 0, 34944, 0x07fc7ca5 -0, 570000, 570000, 0, 34944, 0xa8d3ffda -0, 576000, 576000, 0, 34944, 0xa2d31265 -0, 582000, 582000, 0, 34944, 0x5e58225e -0, 588000, 588000, 0, 34944, 0x284b2fb0 -0, 594000, 594000, 0, 34944, 0x205b3cb1 -0, 600000, 600000, 0, 34944, 0x3fa64a09 -0, 606000, 606000, 0, 34944, 0xa5de5097 -0, 612000, 612000, 0, 34944, 0x00686cea -0, 618000, 618000, 0, 34944, 0x465a8282 -0, 624000, 624000, 0, 34944, 0x4ceb8189 -0, 630000, 630000, 0, 34944, 0x14698509 -0, 636000, 636000, 0, 34944, 0x232c830d -0, 642000, 642000, 0, 34944, 0x0739807c -0, 648000, 648000, 0, 34944, 0x83b0861e -0, 654000, 654000, 0, 34944, 0xbdc094b1 -0, 660000, 660000, 0, 34944, 0xc4c0a605 -0, 666000, 666000, 0, 34944, 0x8376b059 -0, 672000, 672000, 0, 34944, 0x2035b939 -0, 678000, 678000, 0, 34944, 0xb6bfc812 -0, 684000, 684000, 0, 34944, 0xc5d4d5c4 -0, 690000, 690000, 0, 34944, 0x492c954e -0, 696000, 696000, 0, 34944, 0xd23f0dcc -0, 702000, 702000, 0, 34944, 0x22d7ff6c -0, 708000, 708000, 0, 34944, 0xd08b4168 -0, 714000, 714000, 0, 34944, 0xa82e4062 -0, 720000, 720000, 0, 34944, 0xcc4f2f31 -0, 726000, 726000, 0, 34944, 0x964b0307 -0, 732000, 732000, 0, 34944, 0xe8130606 -0, 738000, 738000, 0, 34944, 0x5fb744bf -0, 744000, 744000, 0, 34944, 0x1546a88b -0, 750000, 750000, 0, 34944, 0xe6e4d94d -0, 756000, 756000, 0, 34944, 0x8d1ea97e -0, 762000, 762000, 0, 34944, 0x3bb1fb55 -0, 768000, 768000, 0, 34944, 0x3c37e9cc -0, 774000, 774000, 0, 34944, 0xe2d22521 -0, 780000, 780000, 0, 34944, 0x7c0ec8cc -0, 786000, 786000, 0, 34944, 0x7c2dc956 -0, 792000, 792000, 0, 34944, 0x7fe3c263 -0, 798000, 798000, 0, 34944, 0x9a65b813 -0, 804000, 804000, 0, 34944, 0x7ea7cb14 -0, 810000, 810000, 0, 34944, 0x31ded64e -0, 816000, 816000, 0, 34944, 0x50f30ad1 -0, 822000, 822000, 0, 34944, 0x12eac45c -0, 828000, 828000, 0, 34944, 0x984b6335 -0, 834000, 834000, 0, 34944, 0x3b9b02f0 -0, 840000, 840000, 0, 34944, 0x4629d2a4 -0, 846000, 846000, 0, 34944, 0x38687e89 -0, 852000, 852000, 0, 34944, 0xb76620fe -0, 858000, 858000, 0, 34944, 0x66347155 -0, 864000, 864000, 0, 34944, 0x6e6bc297 -0, 870000, 870000, 0, 34944, 0x452a653a -0, 876000, 876000, 0, 34944, 0x8c8a0683 -0, 882000, 882000, 0, 34944, 0xaf5d7c2d -0, 888000, 888000, 0, 34944, 0x3064a7e1 -0, 894000, 894000, 0, 34944, 0xc0657fc4 -0, 900000, 900000, 0, 34944, 0x1f129266 -0, 906000, 906000, 0, 34944, 0x35adedfb -0, 912000, 912000, 0, 34944, 0x40a3db0d -0, 918000, 918000, 0, 34944, 0x87bebb37 -0, 924000, 924000, 0, 34944, 0x04d7ffed -0, 930000, 930000, 0, 34944, 0x9bde3180 -0, 936000, 936000, 0, 34944, 0xc35c25bd -0, 942000, 942000, 0, 34944, 0x820bf4bb -0, 948000, 948000, 0, 34944, 0x876163ef -0, 954000, 954000, 0, 34944, 0x3ab6dac0 -0, 960000, 960000, 0, 34944, 0x69a9ef73 -0, 966000, 966000, 0, 34944, 0x0df3813c -0, 972000, 972000, 0, 34944, 0x1bba0947 -0, 978000, 978000, 0, 34944, 0x0b7883d4 -0, 984000, 984000, 0, 34944, 0xa9972f7e -0, 990000, 990000, 0, 34944, 0x603d08fe -0, 996000, 996000, 0, 34944, 0x05f4f111 -0, 1002000, 1002000, 0, 34944, 0xb24fdb42 -0, 1008000, 1008000, 0, 34944, 0xfe2ad344 -0, 1014000, 1014000, 0, 34944, 0xda4bcb8f -0, 1020000, 1020000, 0, 34944, 0xd28aca6b -0, 1026000, 1026000, 0, 34944, 0x9486c260 -0, 1032000, 1032000, 0, 34944, 0xad9fc04d -0, 1038000, 1038000, 0, 34944, 0x9333c0ca -0, 1044000, 1044000, 0, 34944, 0x96e9c226 -0, 1050000, 1050000, 0, 34944, 0x3e89bd6f -0, 1056000, 1056000, 0, 34944, 0x7a2dbd32 -0, 1062000, 1062000, 0, 34944, 0xe578ba53 -0, 1068000, 1068000, 0, 34944, 0xb77ebab1 -0, 1074000, 1074000, 0, 34944, 0xd8bfbcb1 -0, 1080000, 1080000, 0, 34944, 0x15d9bc97 -0, 1086000, 1086000, 0, 34944, 0x09c3b9f0 -0, 1092000, 1092000, 0, 34944, 0xd8c8b944 -0, 1098000, 1098000, 0, 34944, 0x2c2fb996 -0, 1104000, 1104000, 0, 34944, 0xd7a8b7e7 -0, 1110000, 1110000, 0, 34944, 0xce34b843 -0, 1116000, 1116000, 0, 34944, 0xba69e9fd -0, 1122000, 1122000, 0, 34944, 0x1b3f1adc -0, 1128000, 1128000, 0, 34944, 0x48f515aa -0, 1134000, 1134000, 0, 34944, 0x864e12bb -0, 1140000, 1140000, 0, 34944, 0xca571996 -0, 1146000, 1146000, 0, 34944, 0x1d5a1af0 -0, 1152000, 1152000, 0, 34944, 0x3d1e171f -0, 1158000, 1158000, 0, 34944, 0xb57417ca -0, 1164000, 1164000, 0, 34944, 0x6e6d1e9d -0, 1170000, 1170000, 0, 34944, 0xc9971899 -0, 1176000, 1176000, 0, 34944, 0xe0b112c8 -0, 1182000, 1182000, 0, 34944, 0x121b0cd9 -0, 1188000, 1188000, 0, 34944, 0x418e0eff -0, 1194000, 1194000, 0, 34944, 0x9e1b07d8 -0, 1200000, 1200000, 0, 34944, 0x5590064a -0, 1206000, 1206000, 0, 34944, 0x7a170b14 -0, 1212000, 1212000, 0, 34944, 0xf25709f0 -0, 1218000, 1218000, 0, 34944, 0x94fa099a -0, 1224000, 1224000, 0, 34944, 0x081e06ae -0, 1230000, 1230000, 0, 34944, 0xcfc40417 -0, 1236000, 1236000, 0, 34944, 0xed33096f -0, 1242000, 1242000, 0, 34944, 0xd73a07e2 -0, 1248000, 1248000, 0, 34944, 0xc512077d -0, 1254000, 1254000, 0, 34944, 0x27d7021d -0, 1260000, 1260000, 0, 34944, 0xab59fd20 -0, 1266000, 1266000, 0, 34944, 0xcc2400b7 -0, 1272000, 1272000, 0, 34944, 0xcb3bfb99 -0, 1278000, 1278000, 0, 34944, 0x0974fb1a -0, 1284000, 1284000, 0, 34944, 0xef79f8ba -0, 1290000, 1290000, 0, 34944, 0xf932f3a2 -0, 1296000, 1296000, 0, 34944, 0xa32df1bc -0, 1302000, 1302000, 0, 34944, 0xdbe0f532 -0, 1308000, 1308000, 0, 34944, 0x234cf142 -0, 1314000, 1314000, 0, 34944, 0xe68befd0 -0, 1320000, 1320000, 0, 34944, 0xe4e7ee45 -0, 1326000, 1326000, 0, 34944, 0x0283eff1 -0, 1332000, 1332000, 0, 34944, 0xc8d3f6db -0, 1338000, 1338000, 0, 34944, 0x0aa6ee88 -0, 1344000, 1344000, 0, 34944, 0xcc3de527 -0, 1350000, 1350000, 0, 34944, 0x9db0ebef -0, 1356000, 1356000, 0, 34944, 0xa207e9db -0, 1362000, 1362000, 0, 34944, 0x35b3e74a -0, 1368000, 1368000, 0, 34944, 0x1988e848 -0, 1374000, 1374000, 0, 34944, 0x727de73c -0, 1380000, 1380000, 0, 34944, 0x05d5e709 -0, 1386000, 1386000, 0, 34944, 0x3214e4b2 -0, 1392000, 1392000, 0, 34944, 0xed85e0a9 -0, 1398000, 1398000, 0, 34944, 0xf6c9e100 -0, 1404000, 1404000, 0, 34944, 0x57a8dbaf -0, 1410000, 1410000, 0, 34944, 0xc75fdf41 -0, 1416000, 1416000, 0, 34944, 0x736fde24 -0, 1422000, 1422000, 0, 34944, 0x8d4bde80 -0, 1428000, 1428000, 0, 34944, 0x3220dc86 -0, 1434000, 1434000, 0, 34944, 0xe498da85 -0, 1440000, 1440000, 0, 34944, 0x0655daed -0, 1446000, 1446000, 0, 34944, 0xb22ad874 -0, 1452000, 1452000, 0, 34944, 0x8198d411 -0, 1458000, 1458000, 0, 34944, 0xd0d2d557 -0, 1464000, 1464000, 0, 34944, 0xd740d1ff -0, 1470000, 1470000, 0, 34944, 0x2783d00e -0, 1476000, 1476000, 0, 34944, 0x7abdcd6b -0, 1482000, 1482000, 0, 34944, 0x2e47d1eb -0, 1488000, 1488000, 0, 34944, 0xfe1bcf60 -0, 1494000, 1494000, 0, 34944, 0xf0f0d5bb -0, 1500000, 1500000, 0, 34944, 0x9af7d581 -0, 1506000, 1506000, 0, 34944, 0xb325ca3d -0, 1512000, 1512000, 0, 34944, 0xd88abfbd -0, 1518000, 1518000, 0, 34944, 0xf2bab746 -0, 1524000, 1524000, 0, 34944, 0xac44a7dd -0, 1530000, 1530000, 0, 34944, 0x609e9ea3 -0, 1536000, 1536000, 0, 34944, 0xa39993b9 -0, 1542000, 1542000, 0, 34944, 0x9c948911 -0, 1548000, 1548000, 0, 34944, 0x72f8822d -0, 1554000, 1554000, 0, 34944, 0x7f3f7a8c -0, 1560000, 1560000, 0, 34944, 0x7ab475f9 -0, 1566000, 1566000, 0, 34944, 0x536f73aa -0, 1572000, 1572000, 0, 34944, 0x86cb71e5 -0, 1578000, 1578000, 0, 34944, 0x17157186 -0, 1584000, 1584000, 0, 34944, 0xe33671a4 -0, 1590000, 1590000, 0, 34944, 0xe33671a4 -0, 1596000, 1596000, 0, 34944, 0xe33671a4 -0, 1602000, 1602000, 0, 34944, 0xe33671a4 -0, 1608000, 1608000, 0, 34944, 0xe33671a4 -0, 1614000, 1614000, 0, 34944, 0xe33671a4 -0, 1620000, 1620000, 0, 34944, 0xe33671a4 -0, 1626000, 1626000, 0, 34944, 0xe33671a4 -0, 1632000, 1632000, 0, 34944, 0xe33671a4 -0, 1638000, 1638000, 0, 34944, 0xe33671a4 -0, 1644000, 1644000, 0, 34944, 0xe33671a4 -0, 1650000, 1650000, 0, 34944, 0xe33671a4 -0, 1656000, 1656000, 0, 34944, 0xe33671a4 -0, 1662000, 1662000, 0, 34944, 0xe33671a4 +#tb 0: 1/15 +0, 0, 0, 1, 34944, 0xe33671a4 +0, 1, 1, 1, 34944, 0xe33671a4 +0, 2, 2, 1, 34944, 0xe33671a4 +0, 3, 3, 1, 34944, 0xe33671a4 +0, 4, 4, 1, 34944, 0xe33671a4 +0, 5, 5, 1, 34944, 0xe33671a4 +0, 6, 6, 1, 34944, 0xe33671a4 +0, 7, 7, 1, 34944, 0xe33671a4 +0, 8, 8, 1, 34944, 0xe33671a4 +0, 9, 9, 1, 34944, 0xe33671a4 +0, 10, 10, 1, 34944, 0xe33671a4 +0, 11, 11, 1, 34944, 0xe33671a4 +0, 12, 12, 1, 34944, 0xe33671a4 +0, 13, 13, 1, 34944, 0xe33671a4 +0, 14, 14, 1, 34944, 0xe33671a4 +0, 15, 15, 1, 34944, 0x63196b41 +0, 16, 16, 1, 34944, 0x308d6f10 +0, 17, 17, 1, 34944, 0x86026ced +0, 18, 18, 1, 34944, 0xaa6a6bc9 +0, 19, 19, 1, 34944, 0x58276ee3 +0, 20, 20, 1, 34944, 0x402d70c2 +0, 21, 21, 1, 34944, 0x948d74bf +0, 22, 22, 1, 34944, 0x3d31759c +0, 23, 23, 1, 34944, 0x638c734e +0, 24, 24, 1, 34944, 0xe218768a +0, 25, 25, 1, 34944, 0xed6678ff +0, 26, 26, 1, 34944, 0x381b7dda +0, 27, 27, 1, 34944, 0x216680e7 +0, 28, 28, 1, 34944, 0xaca5810f +0, 29, 29, 1, 34944, 0xf70b81eb +0, 30, 30, 1, 34944, 0x3675858b +0, 31, 31, 1, 34944, 0xa51188c3 +0, 32, 32, 1, 34944, 0x3a848bf1 +0, 33, 33, 1, 34944, 0x67608d4d +0, 34, 34, 1, 34944, 0xafe49165 +0, 35, 35, 1, 34944, 0x7e8a94a7 +0, 36, 36, 1, 34944, 0x3b889432 +0, 37, 37, 1, 34944, 0x97e89623 +0, 38, 38, 1, 34944, 0x07819793 +0, 39, 39, 1, 34944, 0xdac39b87 +0, 40, 40, 1, 34944, 0x4d8c9d93 +0, 41, 41, 1, 34944, 0xcf009fa7 +0, 42, 42, 1, 34944, 0x2f109f6e +0, 43, 43, 1, 34944, 0xcedda4eb +0, 44, 44, 1, 34944, 0xfe89a6df +0, 45, 45, 1, 34944, 0x195ea7a9 +0, 46, 46, 1, 34944, 0x9287ab92 +0, 47, 47, 1, 34944, 0x6d21af54 +0, 48, 48, 1, 34944, 0xd627b28b +0, 49, 49, 1, 34944, 0x3ad5b6fd +0, 50, 50, 1, 34944, 0x5101b64d +0, 51, 51, 1, 34944, 0xb968b8ca +0, 52, 52, 1, 34944, 0xa105b74a +0, 53, 53, 1, 34944, 0xc056bdd6 +0, 54, 54, 1, 34944, 0xec7fc1d9 +0, 55, 55, 1, 34944, 0x92c3c3e0 +0, 56, 56, 1, 34944, 0x9bffc45c +0, 57, 57, 1, 34944, 0x5aabca4b +0, 58, 58, 1, 34944, 0xcbdacb26 +0, 59, 59, 1, 34944, 0xed6cce3f +0, 60, 60, 1, 34944, 0xcc61cfb8 +0, 61, 61, 1, 34944, 0x7a97d427 +0, 62, 62, 1, 34944, 0x7cdbd5ec +0, 63, 63, 1, 34944, 0x5851d9c4 +0, 64, 64, 1, 34944, 0x69d5dd1d +0, 65, 65, 1, 34944, 0xdf30dcf4 +0, 66, 66, 1, 34944, 0x2359e084 +0, 67, 67, 1, 34944, 0xe0bae491 +0, 68, 68, 1, 34944, 0xa716e4fd +0, 69, 69, 1, 34944, 0xe48aeaf4 +0, 70, 70, 1, 34944, 0x0a0deb21 +0, 71, 71, 1, 34944, 0xe8a56e12 +0, 72, 72, 1, 34944, 0x0d72c98e +0, 73, 73, 1, 34944, 0x71a7bb9d +0, 74, 74, 1, 34944, 0xc0c8c108 +0, 75, 75, 1, 34944, 0x1d1fc3ba +0, 76, 76, 1, 34944, 0xebcfc67f +0, 77, 77, 1, 34944, 0x2921cb5b +0, 78, 78, 1, 34944, 0x793ed099 +0, 79, 79, 1, 34944, 0xefebd9e8 +0, 80, 80, 1, 34944, 0x163c2330 +0, 81, 81, 1, 34944, 0x35155672 +0, 82, 82, 1, 34944, 0x05474e2e +0, 83, 83, 1, 34944, 0x9433542f +0, 84, 84, 1, 34944, 0x777d5a13 +0, 85, 85, 1, 34944, 0x87526776 +0, 86, 86, 1, 34944, 0x4c3c72c1 +0, 87, 87, 1, 34944, 0x70407b87 +0, 88, 88, 1, 34944, 0x2358861d +0, 89, 89, 1, 34944, 0xec61923f +0, 90, 90, 1, 34944, 0x0bb2a0d4 +0, 91, 91, 1, 34944, 0x6b6d8624 +0, 92, 92, 1, 34944, 0x624761ec +0, 93, 93, 1, 34944, 0xff23b926 +0, 94, 94, 1, 34944, 0x07fc7ca5 +0, 95, 95, 1, 34944, 0xa8d3ffda +0, 96, 96, 1, 34944, 0xa2d31265 +0, 97, 97, 1, 34944, 0x5e58225e +0, 98, 98, 1, 34944, 0x284b2fb0 +0, 99, 99, 1, 34944, 0x205b3cb1 +0, 100, 100, 1, 34944, 0x3fa64a09 +0, 101, 101, 1, 34944, 0xa5de5097 +0, 102, 102, 1, 34944, 0x00686cea +0, 103, 103, 1, 34944, 0x465a8282 +0, 104, 104, 1, 34944, 0x4ceb8189 +0, 105, 105, 1, 34944, 0x14698509 +0, 106, 106, 1, 34944, 0x232c830d +0, 107, 107, 1, 34944, 0x0739807c +0, 108, 108, 1, 34944, 0x83b0861e +0, 109, 109, 1, 34944, 0xbdc094b1 +0, 110, 110, 1, 34944, 0xc4c0a605 +0, 111, 111, 1, 34944, 0x8376b059 +0, 112, 112, 1, 34944, 0x2035b939 +0, 113, 113, 1, 34944, 0xb6bfc812 +0, 114, 114, 1, 34944, 0xc5d4d5c4 +0, 115, 115, 1, 34944, 0x492c954e +0, 116, 116, 1, 34944, 0xd23f0dcc +0, 117, 117, 1, 34944, 0x22d7ff6c +0, 118, 118, 1, 34944, 0xd08b4168 +0, 119, 119, 1, 34944, 0xa82e4062 +0, 120, 120, 1, 34944, 0xcc4f2f31 +0, 121, 121, 1, 34944, 0x964b0307 +0, 122, 122, 1, 34944, 0xe8130606 +0, 123, 123, 1, 34944, 0x5fb744bf +0, 124, 124, 1, 34944, 0x1546a88b +0, 125, 125, 1, 34944, 0xe6e4d94d +0, 126, 126, 1, 34944, 0x8d1ea97e +0, 127, 127, 1, 34944, 0x3bb1fb55 +0, 128, 128, 1, 34944, 0x3c37e9cc +0, 129, 129, 1, 34944, 0xe2d22521 +0, 130, 130, 1, 34944, 0x7c0ec8cc +0, 131, 131, 1, 34944, 0x7c2dc956 +0, 132, 132, 1, 34944, 0x7fe3c263 +0, 133, 133, 1, 34944, 0x9a65b813 +0, 134, 134, 1, 34944, 0x7ea7cb14 +0, 135, 135, 1, 34944, 0x31ded64e +0, 136, 136, 1, 34944, 0x50f30ad1 +0, 137, 137, 1, 34944, 0x12eac45c +0, 138, 138, 1, 34944, 0x984b6335 +0, 139, 139, 1, 34944, 0x3b9b02f0 +0, 140, 140, 1, 34944, 0x4629d2a4 +0, 141, 141, 1, 34944, 0x38687e89 +0, 142, 142, 1, 34944, 0xb76620fe +0, 143, 143, 1, 34944, 0x66347155 +0, 144, 144, 1, 34944, 0x6e6bc297 +0, 145, 145, 1, 34944, 0x452a653a +0, 146, 146, 1, 34944, 0x8c8a0683 +0, 147, 147, 1, 34944, 0xaf5d7c2d +0, 148, 148, 1, 34944, 0x3064a7e1 +0, 149, 149, 1, 34944, 0xc0657fc4 +0, 150, 150, 1, 34944, 0x1f129266 +0, 151, 151, 1, 34944, 0x35adedfb +0, 152, 152, 1, 34944, 0x40a3db0d +0, 153, 153, 1, 34944, 0x87bebb37 +0, 154, 154, 1, 34944, 0x04d7ffed +0, 155, 155, 1, 34944, 0x9bde3180 +0, 156, 156, 1, 34944, 0xc35c25bd +0, 157, 157, 1, 34944, 0x820bf4bb +0, 158, 158, 1, 34944, 0x876163ef +0, 159, 159, 1, 34944, 0x3ab6dac0 +0, 160, 160, 1, 34944, 0x69a9ef73 +0, 161, 161, 1, 34944, 0x0df3813c +0, 162, 162, 1, 34944, 0x1bba0947 +0, 163, 163, 1, 34944, 0x0b7883d4 +0, 164, 164, 1, 34944, 0xa9972f7e +0, 165, 165, 1, 34944, 0x603d08fe +0, 166, 166, 1, 34944, 0x05f4f111 +0, 167, 167, 1, 34944, 0xb24fdb42 +0, 168, 168, 1, 34944, 0xfe2ad344 +0, 169, 169, 1, 34944, 0xda4bcb8f +0, 170, 170, 1, 34944, 0xd28aca6b +0, 171, 171, 1, 34944, 0x9486c260 +0, 172, 172, 1, 34944, 0xad9fc04d +0, 173, 173, 1, 34944, 0x9333c0ca +0, 174, 174, 1, 34944, 0x96e9c226 +0, 175, 175, 1, 34944, 0x3e89bd6f +0, 176, 176, 1, 34944, 0x7a2dbd32 +0, 177, 177, 1, 34944, 0xe578ba53 +0, 178, 178, 1, 34944, 0xb77ebab1 +0, 179, 179, 1, 34944, 0xd8bfbcb1 +0, 180, 180, 1, 34944, 0x15d9bc97 +0, 181, 181, 1, 34944, 0x09c3b9f0 +0, 182, 182, 1, 34944, 0xd8c8b944 +0, 183, 183, 1, 34944, 0x2c2fb996 +0, 184, 184, 1, 34944, 0xd7a8b7e7 +0, 185, 185, 1, 34944, 0xce34b843 +0, 186, 186, 1, 34944, 0xba69e9fd +0, 187, 187, 1, 34944, 0x1b3f1adc +0, 188, 188, 1, 34944, 0x48f515aa +0, 189, 189, 1, 34944, 0x864e12bb +0, 190, 190, 1, 34944, 0xca571996 +0, 191, 191, 1, 34944, 0x1d5a1af0 +0, 192, 192, 1, 34944, 0x3d1e171f +0, 193, 193, 1, 34944, 0xb57417ca +0, 194, 194, 1, 34944, 0x6e6d1e9d +0, 195, 195, 1, 34944, 0xc9971899 +0, 196, 196, 1, 34944, 0xe0b112c8 +0, 197, 197, 1, 34944, 0x121b0cd9 +0, 198, 198, 1, 34944, 0x418e0eff +0, 199, 199, 1, 34944, 0x9e1b07d8 +0, 200, 200, 1, 34944, 0x5590064a +0, 201, 201, 1, 34944, 0x7a170b14 +0, 202, 202, 1, 34944, 0xf25709f0 +0, 203, 203, 1, 34944, 0x94fa099a +0, 204, 204, 1, 34944, 0x081e06ae +0, 205, 205, 1, 34944, 0xcfc40417 +0, 206, 206, 1, 34944, 0xed33096f +0, 207, 207, 1, 34944, 0xd73a07e2 +0, 208, 208, 1, 34944, 0xc512077d +0, 209, 209, 1, 34944, 0x27d7021d +0, 210, 210, 1, 34944, 0xab59fd20 +0, 211, 211, 1, 34944, 0xcc2400b7 +0, 212, 212, 1, 34944, 0xcb3bfb99 +0, 213, 213, 1, 34944, 0x0974fb1a +0, 214, 214, 1, 34944, 0xef79f8ba +0, 215, 215, 1, 34944, 0xf932f3a2 +0, 216, 216, 1, 34944, 0xa32df1bc +0, 217, 217, 1, 34944, 0xdbe0f532 +0, 218, 218, 1, 34944, 0x234cf142 +0, 219, 219, 1, 34944, 0xe68befd0 +0, 220, 220, 1, 34944, 0xe4e7ee45 +0, 221, 221, 1, 34944, 0x0283eff1 +0, 222, 222, 1, 34944, 0xc8d3f6db +0, 223, 223, 1, 34944, 0x0aa6ee88 +0, 224, 224, 1, 34944, 0xcc3de527 +0, 225, 225, 1, 34944, 0x9db0ebef +0, 226, 226, 1, 34944, 0xa207e9db +0, 227, 227, 1, 34944, 0x35b3e74a +0, 228, 228, 1, 34944, 0x1988e848 +0, 229, 229, 1, 34944, 0x727de73c +0, 230, 230, 1, 34944, 0x05d5e709 +0, 231, 231, 1, 34944, 0x3214e4b2 +0, 232, 232, 1, 34944, 0xed85e0a9 +0, 233, 233, 1, 34944, 0xf6c9e100 +0, 234, 234, 1, 34944, 0x57a8dbaf +0, 235, 235, 1, 34944, 0xc75fdf41 +0, 236, 236, 1, 34944, 0x736fde24 +0, 237, 237, 1, 34944, 0x8d4bde80 +0, 238, 238, 1, 34944, 0x3220dc86 +0, 239, 239, 1, 34944, 0xe498da85 +0, 240, 240, 1, 34944, 0x0655daed +0, 241, 241, 1, 34944, 0xb22ad874 +0, 242, 242, 1, 34944, 0x8198d411 +0, 243, 243, 1, 34944, 0xd0d2d557 +0, 244, 244, 1, 34944, 0xd740d1ff +0, 245, 245, 1, 34944, 0x2783d00e +0, 246, 246, 1, 34944, 0x7abdcd6b +0, 247, 247, 1, 34944, 0x2e47d1eb +0, 248, 248, 1, 34944, 0xfe1bcf60 +0, 249, 249, 1, 34944, 0xf0f0d5bb +0, 250, 250, 1, 34944, 0x9af7d581 +0, 251, 251, 1, 34944, 0xb325ca3d +0, 252, 252, 1, 34944, 0xd88abfbd +0, 253, 253, 1, 34944, 0xf2bab746 +0, 254, 254, 1, 34944, 0xac44a7dd +0, 255, 255, 1, 34944, 0x609e9ea3 +0, 256, 256, 1, 34944, 0xa39993b9 +0, 257, 257, 1, 34944, 0x9c948911 +0, 258, 258, 1, 34944, 0x72f8822d +0, 259, 259, 1, 34944, 0x7f3f7a8c +0, 260, 260, 1, 34944, 0x7ab475f9 +0, 261, 261, 1, 34944, 0x536f73aa +0, 262, 262, 1, 34944, 0x86cb71e5 +0, 263, 263, 1, 34944, 0x17157186 +0, 264, 264, 1, 34944, 0xe33671a4 +0, 265, 265, 1, 34944, 0xe33671a4 +0, 266, 266, 1, 34944, 0xe33671a4 +0, 267, 267, 1, 34944, 0xe33671a4 +0, 268, 268, 1, 34944, 0xe33671a4 +0, 269, 269, 1, 34944, 0xe33671a4 +0, 270, 270, 1, 34944, 0xe33671a4 +0, 271, 271, 1, 34944, 0xe33671a4 +0, 272, 272, 1, 34944, 0xe33671a4 +0, 273, 273, 1, 34944, 0xe33671a4 +0, 274, 274, 1, 34944, 0xe33671a4 +0, 275, 275, 1, 34944, 0xe33671a4 +0, 276, 276, 1, 34944, 0xe33671a4 +0, 277, 277, 1, 34944, 0xe33671a4 diff --git a/tests/ref/fate/ea-tqi b/tests/ref/fate/ea-tqi index ba0073b..72afb81 100644 --- a/tests/ref/fate/ea-tqi +++ b/tests/ref/fate/ea-tqi @@ -1,27 +1,27 @@ -#tb 0: 1/90000 -0, 0, 0, 0, 115200, 0x375ec573 -0, 6000, 6000, 0, 115200, 0x375ec573 -0, 12000, 12000, 0, 115200, 0x375ec573 -0, 18000, 18000, 0, 115200, 0x375ec573 -0, 24000, 24000, 0, 115200, 0x375ec573 -0, 30000, 30000, 0, 115200, 0x375ec573 -0, 36000, 36000, 0, 115200, 0x375ec573 -0, 42000, 42000, 0, 115200, 0x375ec573 -0, 48000, 48000, 0, 115200, 0x0b4d31bf -0, 54000, 54000, 0, 115200, 0xdd724598 -0, 60000, 60000, 0, 115200, 0xc3077e75 -0, 66000, 66000, 0, 115200, 0xbf70778a -0, 72000, 72000, 0, 115200, 0x117eb766 -0, 78000, 78000, 0, 115200, 0x4617fbad -0, 84000, 84000, 0, 115200, 0x5f5b02d2 -0, 90000, 90000, 0, 115200, 0x2a9c5325 -0, 96000, 96000, 0, 115200, 0x14a89e2a -0, 102000, 102000, 0, 115200, 0xe69aa994 -0, 108000, 108000, 0, 115200, 0xfbacf589 -0, 114000, 114000, 0, 115200, 0x1d714c6e -0, 120000, 120000, 0, 115200, 0x6eff66cb -0, 126000, 126000, 0, 115200, 0xee21c1cb -0, 132000, 132000, 0, 115200, 0xce714ada -0, 138000, 138000, 0, 115200, 0xf89d56c3 -0, 144000, 144000, 0, 115200, 0x65fd5e60 -0, 150000, 150000, 0, 115200, 0x0c256424 +#tb 0: 1/15 +0, 0, 0, 1, 115200, 0x375ec573 +0, 1, 1, 1, 115200, 0x375ec573 +0, 2, 2, 1, 115200, 0x375ec573 +0, 3, 3, 1, 115200, 0x375ec573 +0, 4, 4, 1, 115200, 0x375ec573 +0, 5, 5, 1, 115200, 0x375ec573 +0, 6, 6, 1, 115200, 0x375ec573 +0, 7, 7, 1, 115200, 0x375ec573 +0, 8, 8, 1, 115200, 0x0b4d31bf +0, 9, 9, 1, 115200, 0xdd724598 +0, 10, 10, 1, 115200, 0xc3077e75 +0, 11, 11, 1, 115200, 0xbf70778a +0, 12, 12, 1, 115200, 0x117eb766 +0, 13, 13, 1, 115200, 0x4617fbad +0, 14, 14, 1, 115200, 0x5f5b02d2 +0, 15, 15, 1, 115200, 0x2a9c5325 +0, 16, 16, 1, 115200, 0x14a89e2a +0, 17, 17, 1, 115200, 0xe69aa994 +0, 18, 18, 1, 115200, 0xfbacf589 +0, 19, 19, 1, 115200, 0x1d714c6e +0, 20, 20, 1, 115200, 0x6eff66cb +0, 21, 21, 1, 115200, 0xee21c1cb +0, 22, 22, 1, 115200, 0xce714ada +0, 23, 23, 1, 115200, 0xf89d56c3 +0, 24, 24, 1, 115200, 0x65fd5e60 +0, 25, 25, 1, 115200, 0x0c256424 diff --git a/tests/ref/fate/fic-avi b/tests/ref/fate/fic-avi index e2b26a3..cc4ea5d 100644 --- a/tests/ref/fate/fic-avi +++ b/tests/ref/fate/fic-avi @@ -119,3 +119,4 @@ 0, 117, 117, 1, 1566720, 0xfe83b964 0, 118, 118, 1, 1566720, 0x25dc30a6 0, 119, 119, 1, 1566720, 0x25dc30a6 +0, 120, 120, 1, 1566720, 0x25dc30a6 diff --git a/tests/ref/fate/filter-crop b/tests/ref/fate/filter-crop index 32041c2..b226c96 100644 --- a/tests/ref/fate/filter-crop +++ b/tests/ref/fate/filter-crop @@ -1 +1 @@ -crop 3d163f156eaddf41d2be20736f973539 +crop f3a9421392a9aa71a974c1b933c8d6ee diff --git a/tests/ref/fate/filter-crop_scale b/tests/ref/fate/filter-crop_scale index 82e5394..b80a83f 100644 --- a/tests/ref/fate/filter-crop_scale +++ b/tests/ref/fate/filter-crop_scale @@ -1 +1 @@ -crop_scale 0a3d45d58b805b8c47416b9239535f94 +crop_scale fe197338c0cb626766cb04f7d46fcc44 diff --git a/tests/ref/fate/filter-crop_scale_vflip b/tests/ref/fate/filter-crop_scale_vflip index 29574f7..b1eba7e 100644 --- a/tests/ref/fate/filter-crop_scale_vflip +++ b/tests/ref/fate/filter-crop_scale_vflip @@ -1 +1 @@ -crop_scale_vflip 3e2c7694d37733ca52e1723d5262af36 +crop_scale_vflip 1e456de396706899f3dca38ef2b43777 diff --git a/tests/ref/fate/filter-crop_vflip b/tests/ref/fate/filter-crop_vflip index a3f8200..56aa383 100644 --- a/tests/ref/fate/filter-crop_vflip +++ b/tests/ref/fate/filter-crop_vflip @@ -1 +1 @@ -crop_vflip 628542e17b6900ee79b1429183ae01b0 +crop_vflip 2527b0a2a7b4a6a732fd0e0f07b9bb74 diff --git a/tests/ref/fate/filter-null b/tests/ref/fate/filter-null index 3c3b7b7..3a1d0c1 100644 --- a/tests/ref/fate/filter-null +++ b/tests/ref/fate/filter-null @@ -1 +1 @@ -null eba2f135a08829387e2f698ff72a2939 +null 7aaf1057c0edf7d5e9700f9c8e510ea9 diff --git a/tests/ref/fate/filter-pixdesc-abgr b/tests/ref/fate/filter-pixdesc-abgr index ac8513e..691bc07 100644 --- a/tests/ref/fate/filter-pixdesc-abgr +++ b/tests/ref/fate/filter-pixdesc-abgr @@ -1 +1 @@ -pixdesc-abgr 037bf9df6a765520ad6d490066bf4b89 +pixdesc-abgr 0a96433ddadb89d577870419c0c0f122 diff --git a/tests/ref/fate/filter-pixdesc-argb b/tests/ref/fate/filter-pixdesc-argb index 3b81bfe..27531dc 100644 --- a/tests/ref/fate/filter-pixdesc-argb +++ b/tests/ref/fate/filter-pixdesc-argb @@ -1 +1 @@ -pixdesc-argb c442a8261c2265a07212ef0f72e35f5a +pixdesc-argb 29a7781fc931a8fe4847bbbd02ca966a diff --git a/tests/ref/fate/filter-pixdesc-bgr24 b/tests/ref/fate/filter-pixdesc-bgr24 index 76b6dfc..7c530b4 100644 --- a/tests/ref/fate/filter-pixdesc-bgr24 +++ b/tests/ref/fate/filter-pixdesc-bgr24 @@ -1 +1 @@ -pixdesc-bgr24 0d0cb38ab3fa0b2ec0865c14f78b217b +pixdesc-bgr24 0c8ccab8bf3055c6299f943e94e90e25 diff --git a/tests/ref/fate/filter-pixdesc-bgr444be b/tests/ref/fate/filter-pixdesc-bgr444be index e5a8819..6de43e7 100644 --- a/tests/ref/fate/filter-pixdesc-bgr444be +++ b/tests/ref/fate/filter-pixdesc-bgr444be @@ -1 +1 @@ -pixdesc-bgr444be d9ea9307d21b162225b8b2c524cf9477 +pixdesc-bgr444be 4f223284a5797b7665994cea8045bc70 diff --git a/tests/ref/fate/filter-pixdesc-bgr444le b/tests/ref/fate/filter-pixdesc-bgr444le index 8bda95c..0d3a6ed 100644 --- a/tests/ref/fate/filter-pixdesc-bgr444le +++ b/tests/ref/fate/filter-pixdesc-bgr444le @@ -1 +1 @@ -pixdesc-bgr444le 88035350e9da3a8f67387890b956f0bc +pixdesc-bgr444le fa37199bf217a5a82a628f175b375a86 diff --git a/tests/ref/fate/filter-pixdesc-bgr48be b/tests/ref/fate/filter-pixdesc-bgr48be index f87f3fa..65b2289 100644 --- a/tests/ref/fate/filter-pixdesc-bgr48be +++ b/tests/ref/fate/filter-pixdesc-bgr48be @@ -1 +1 @@ -pixdesc-bgr48be 00624e6c7ec7ab19897ba2f0a3257fe8 +pixdesc-bgr48be 728452ef75877706fddabdee386ea6a3 diff --git a/tests/ref/fate/filter-pixdesc-bgr48le b/tests/ref/fate/filter-pixdesc-bgr48le index 738a4a9..5906109 100644 --- a/tests/ref/fate/filter-pixdesc-bgr48le +++ b/tests/ref/fate/filter-pixdesc-bgr48le @@ -1 +1 @@ -pixdesc-bgr48le d02c235ebba7167881ca2d576497ff84 +pixdesc-bgr48le 82f5689e141989e7368f1057f4411040 diff --git a/tests/ref/fate/filter-pixdesc-bgr4_byte b/tests/ref/fate/filter-pixdesc-bgr4_byte index fa465d2..1995bc9 100644 --- a/tests/ref/fate/filter-pixdesc-bgr4_byte +++ b/tests/ref/fate/filter-pixdesc-bgr4_byte @@ -1 +1 @@ -pixdesc-bgr4_byte 50d23cc82d9dcef2fd12adb81fb9b806 +pixdesc-bgr4_byte dc7a43438728d94f27c495491ea6b5fc diff --git a/tests/ref/fate/filter-pixdesc-bgr555be b/tests/ref/fate/filter-pixdesc-bgr555be index 0e137bb..6624bc4 100644 --- a/tests/ref/fate/filter-pixdesc-bgr555be +++ b/tests/ref/fate/filter-pixdesc-bgr555be @@ -1 +1 @@ -pixdesc-bgr555be 49f01b1f1f0c84fd9e776dd34cc3c280 +pixdesc-bgr555be 5c247603c16194f1206cc120de268628 diff --git a/tests/ref/fate/filter-pixdesc-bgr555le b/tests/ref/fate/filter-pixdesc-bgr555le index 9c7ca5b..155cda1 100644 --- a/tests/ref/fate/filter-pixdesc-bgr555le +++ b/tests/ref/fate/filter-pixdesc-bgr555le @@ -1 +1 @@ -pixdesc-bgr555le 378d6ac4223651a1adcbf94a3d0d807b +pixdesc-bgr555le 29f6a95f0c11734ab2dfbef9e7633eaf diff --git a/tests/ref/fate/filter-pixdesc-bgr565be b/tests/ref/fate/filter-pixdesc-bgr565be index 1d71f7e..be096b2 100644 --- a/tests/ref/fate/filter-pixdesc-bgr565be +++ b/tests/ref/fate/filter-pixdesc-bgr565be @@ -1 +1 @@ -pixdesc-bgr565be 257cf78afa35dc31e9696f139c916715 +pixdesc-bgr565be 0225e9ef2a254369e0682832774dd0d5 diff --git a/tests/ref/fate/filter-pixdesc-bgr565le b/tests/ref/fate/filter-pixdesc-bgr565le index bfe2b9d..720a222 100644 --- a/tests/ref/fate/filter-pixdesc-bgr565le +++ b/tests/ref/fate/filter-pixdesc-bgr565le @@ -1 +1 @@ -pixdesc-bgr565le 1dfdd03995c287e3c754b164bf26a355 +pixdesc-bgr565le 5216493ff6c65fa86e117a4fc508c45f diff --git a/tests/ref/fate/filter-pixdesc-bgr8 b/tests/ref/fate/filter-pixdesc-bgr8 index 2aa9b9a..77ca8c4 100644 --- a/tests/ref/fate/filter-pixdesc-bgr8 +++ b/tests/ref/fate/filter-pixdesc-bgr8 @@ -1 +1 @@ -pixdesc-bgr8 24bd566170343d06fec6fccfff5abc54 +pixdesc-bgr8 cbd7b5fbc9cdc1960b99338d4b7a717f diff --git a/tests/ref/fate/filter-pixdesc-bgra b/tests/ref/fate/filter-pixdesc-bgra index 6896fbd..061d395 100644 --- a/tests/ref/fate/filter-pixdesc-bgra +++ b/tests/ref/fate/filter-pixdesc-bgra @@ -1 +1 @@ -pixdesc-bgra 76a18a5151242fa137133f604cd624d2 +pixdesc-bgra ed2e65c70afddfb5ecdcbbe84b699125 diff --git a/tests/ref/fate/filter-pixdesc-gbrap b/tests/ref/fate/filter-pixdesc-gbrap new file mode 100644 index 0000000..7b6cb9e --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-gbrap @@ -0,0 +1 @@ +pixdesc-gbrap 27d9432f970ab0858efecb5a5411cff9 diff --git a/tests/ref/fate/filter-pixdesc-gbrp b/tests/ref/fate/filter-pixdesc-gbrp index cbcaac8..b2eb19a 100644 --- a/tests/ref/fate/filter-pixdesc-gbrp +++ b/tests/ref/fate/filter-pixdesc-gbrp @@ -1 +1 @@ -pixdesc-gbrp 76204621e200a3cc633012f6720c7005 +pixdesc-gbrp 6590f4971764ad82148440354f1635d3 diff --git a/tests/ref/fate/filter-pixdesc-gbrp10be b/tests/ref/fate/filter-pixdesc-gbrp10be index b7e4976..b2f6ee8 100644 --- a/tests/ref/fate/filter-pixdesc-gbrp10be +++ b/tests/ref/fate/filter-pixdesc-gbrp10be @@ -1 +1 @@ -pixdesc-gbrp10be 2ca4a4a589a7dc461ff186913c7a69e5 +pixdesc-gbrp10be 7737f88a6ea043a5cd142afe89da3c21 diff --git a/tests/ref/fate/filter-pixdesc-gbrp10le b/tests/ref/fate/filter-pixdesc-gbrp10le index a9750f7..bc0e2b9 100644 --- a/tests/ref/fate/filter-pixdesc-gbrp10le +++ b/tests/ref/fate/filter-pixdesc-gbrp10le @@ -1 +1 @@ -pixdesc-gbrp10le 46176f1fcc6e67f9862115fe373f73d3 +pixdesc-gbrp10le a912e36ddb9380de328ef2555c303302 diff --git a/tests/ref/fate/filter-pixdesc-gbrp9be b/tests/ref/fate/filter-pixdesc-gbrp9be index 50261c4..3386eab 100644 --- a/tests/ref/fate/filter-pixdesc-gbrp9be +++ b/tests/ref/fate/filter-pixdesc-gbrp9be @@ -1 +1 @@ -pixdesc-gbrp9be 981c2c1b0ef1791824b4c7518331bc2e +pixdesc-gbrp9be 1c448e780b6e82e163e576f0ebb22522 diff --git a/tests/ref/fate/filter-pixdesc-gbrp9le b/tests/ref/fate/filter-pixdesc-gbrp9le index 9a59a9b..49b03df 100644 --- a/tests/ref/fate/filter-pixdesc-gbrp9le +++ b/tests/ref/fate/filter-pixdesc-gbrp9le @@ -1 +1 @@ -pixdesc-gbrp9le 25fb915ed11d07d631e0e7b78d54bebf +pixdesc-gbrp9le 77c2331ceb429454ff7999f771685f38 diff --git a/tests/ref/fate/filter-pixdesc-gray b/tests/ref/fate/filter-pixdesc-gray index 6900fe2..20424cd 100644 --- a/tests/ref/fate/filter-pixdesc-gray +++ b/tests/ref/fate/filter-pixdesc-gray @@ -1 +1 @@ -pixdesc-gray db08f7f0751900347e6b8649e4164d21 +pixdesc-gray 6b89bdf31cbbb19580b1edd3c65b2100 diff --git a/tests/ref/fate/filter-pixdesc-gray16be b/tests/ref/fate/filter-pixdesc-gray16be index dcf6713..8ecaf57 100644 --- a/tests/ref/fate/filter-pixdesc-gray16be +++ b/tests/ref/fate/filter-pixdesc-gray16be @@ -1 +1 @@ -pixdesc-gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 +pixdesc-gray16be d8acd9d657ad5d916cc6b016fa62044e diff --git a/tests/ref/fate/filter-pixdesc-gray16le b/tests/ref/fate/filter-pixdesc-gray16le index 9ac4dd3..d99ca61 100644 --- a/tests/ref/fate/filter-pixdesc-gray16le +++ b/tests/ref/fate/filter-pixdesc-gray16le @@ -1 +1 @@ -pixdesc-gray16le 10bd87059b5c189f3caef2837f4f2b5c +pixdesc-gray16le db884b18fd1a09c53f2cf3d6ca30e086 diff --git a/tests/ref/fate/filter-pixdesc-monob b/tests/ref/fate/filter-pixdesc-monob index 6405cb4..9f5df05 100644 --- a/tests/ref/fate/filter-pixdesc-monob +++ b/tests/ref/fate/filter-pixdesc-monob @@ -1 +1 @@ -pixdesc-monob 668ebe8b8103b9046b251b2fa8a1d88f +pixdesc-monob 48a6d35857c18e2ed20117dd9ef80fdc diff --git a/tests/ref/fate/filter-pixdesc-monow b/tests/ref/fate/filter-pixdesc-monow index 657f98f..0201f44 100644 --- a/tests/ref/fate/filter-pixdesc-monow +++ b/tests/ref/fate/filter-pixdesc-monow @@ -1 +1 @@ -pixdesc-monow 9251497f3b0634f1165d12d5a289d943 +pixdesc-monow de6cd58f5525e692981d8c8678f878c4 diff --git a/tests/ref/fate/filter-pixdesc-nv12 b/tests/ref/fate/filter-pixdesc-nv12 index f42f406..6cc824b 100644 --- a/tests/ref/fate/filter-pixdesc-nv12 +++ b/tests/ref/fate/filter-pixdesc-nv12 @@ -1 +1 @@ -pixdesc-nv12 e0af357888584d36eec5aa0f673793ef +pixdesc-nv12 d3a477a5a56d334728720ac268b1ef99 diff --git a/tests/ref/fate/filter-pixdesc-nv21 b/tests/ref/fate/filter-pixdesc-nv21 index 65e7e7b..3f8393b 100644 --- a/tests/ref/fate/filter-pixdesc-nv21 +++ b/tests/ref/fate/filter-pixdesc-nv21 @@ -1 +1 @@ -pixdesc-nv21 9a3297f3b34baa038b1f37cb202b512f +pixdesc-nv21 977c4582b5d4c7cbdda70ccabb16884b diff --git a/tests/ref/fate/filter-pixdesc-rgb24 b/tests/ref/fate/filter-pixdesc-rgb24 index dcbf91f..21a720e 100644 --- a/tests/ref/fate/filter-pixdesc-rgb24 +++ b/tests/ref/fate/filter-pixdesc-rgb24 @@ -1 +1 @@ -pixdesc-rgb24 b41eba9651e1b5fe386289b506188105 +pixdesc-rgb24 f902267656c28501c123e0bde836421b diff --git a/tests/ref/fate/filter-pixdesc-rgb444be b/tests/ref/fate/filter-pixdesc-rgb444be index cd87cc2..a8ff704 100644 --- a/tests/ref/fate/filter-pixdesc-rgb444be +++ b/tests/ref/fate/filter-pixdesc-rgb444be @@ -1 +1 @@ -pixdesc-rgb444be 9e89db334568c6b2e3d5d0540f4ba960 +pixdesc-rgb444be bc6cb36dbf15cb132ff6d8eee765a95e diff --git a/tests/ref/fate/filter-pixdesc-rgb444le b/tests/ref/fate/filter-pixdesc-rgb444le index d193db3..3b77e74 100644 --- a/tests/ref/fate/filter-pixdesc-rgb444le +++ b/tests/ref/fate/filter-pixdesc-rgb444le @@ -1 +1 @@ -pixdesc-rgb444le 0a68cb6de8bf530aa30c5c1205c25155 +pixdesc-rgb444le a425e8048218b25dad9a81506d891b6f diff --git a/tests/ref/fate/filter-pixdesc-rgb48be b/tests/ref/fate/filter-pixdesc-rgb48be index fe4c50e..f7ac2ac 100644 --- a/tests/ref/fate/filter-pixdesc-rgb48be +++ b/tests/ref/fate/filter-pixdesc-rgb48be @@ -1 +1 @@ -pixdesc-rgb48be cc139ec1dd9451f0e049c0cb3a0c8aa2 +pixdesc-rgb48be d42c8b9fb2d34df383a5f9c2388b5243 diff --git a/tests/ref/fate/filter-pixdesc-rgb48le b/tests/ref/fate/filter-pixdesc-rgb48le index b340208..ff3dee9 100644 --- a/tests/ref/fate/filter-pixdesc-rgb48le +++ b/tests/ref/fate/filter-pixdesc-rgb48le @@ -1 +1 @@ -pixdesc-rgb48le 86c5608904f75360d492dbc5c9589969 +pixdesc-rgb48le ded9e1cb5a4e40de05c0849143658daf diff --git a/tests/ref/fate/filter-pixdesc-rgb4_byte b/tests/ref/fate/filter-pixdesc-rgb4_byte index d44d559..6763c11 100644 --- a/tests/ref/fate/filter-pixdesc-rgb4_byte +++ b/tests/ref/fate/filter-pixdesc-rgb4_byte @@ -1 +1 @@ -pixdesc-rgb4_byte c93ba89b74c504e7f5ae9d9ab1546c73 +pixdesc-rgb4_byte c38cb84e03142ba79b67efa6eb435a40 diff --git a/tests/ref/fate/filter-pixdesc-rgb555be b/tests/ref/fate/filter-pixdesc-rgb555be index a15e67f..520eecc 100644 --- a/tests/ref/fate/filter-pixdesc-rgb555be +++ b/tests/ref/fate/filter-pixdesc-rgb555be @@ -1 +1 @@ -pixdesc-rgb555be 912a62c5e53bfcbac2a0340e10973cf2 +pixdesc-rgb555be 0684e7db3ed49f0fc8bb2787b44bbdf6 diff --git a/tests/ref/fate/filter-pixdesc-rgb555le b/tests/ref/fate/filter-pixdesc-rgb555le index 4a7e709..f178868 100644 --- a/tests/ref/fate/filter-pixdesc-rgb555le +++ b/tests/ref/fate/filter-pixdesc-rgb555le @@ -1 +1 @@ -pixdesc-rgb555le a937a0fc764fb57dc1b3af87cba0273c +pixdesc-rgb555le 1a890ce4ebe5f59fb53e1bf3275c799b diff --git a/tests/ref/fate/filter-pixdesc-rgb565be b/tests/ref/fate/filter-pixdesc-rgb565be index 7ed206b..c2cf284 100644 --- a/tests/ref/fate/filter-pixdesc-rgb565be +++ b/tests/ref/fate/filter-pixdesc-rgb565be @@ -1 +1 @@ -pixdesc-rgb565be 9cadf742e05ddc23a3b5b270f89aad3c +pixdesc-rgb565be c5c1ee14a373afcf4ac3fc32fc9583e1 diff --git a/tests/ref/fate/filter-pixdesc-rgb565le b/tests/ref/fate/filter-pixdesc-rgb565le index b4648dd..1766eaf 100644 --- a/tests/ref/fate/filter-pixdesc-rgb565le +++ b/tests/ref/fate/filter-pixdesc-rgb565le @@ -1 +1 @@ -pixdesc-rgb565le d39aa298bb525e9be8860351c6f62dab +pixdesc-rgb565le 3d16aef38fc165413d3aa35194151d78 diff --git a/tests/ref/fate/filter-pixdesc-rgb8 b/tests/ref/fate/filter-pixdesc-rgb8 index ccc0940..6c798c0 100644 --- a/tests/ref/fate/filter-pixdesc-rgb8 +++ b/tests/ref/fate/filter-pixdesc-rgb8 @@ -1 +1 @@ -pixdesc-rgb8 4a9d8e4f2f154e83a7e1735be6300700 +pixdesc-rgb8 cd3dd114110b48758df3410aae6dd7d3 diff --git a/tests/ref/fate/filter-pixdesc-rgba b/tests/ref/fate/filter-pixdesc-rgba index a5b64a5..2ea2c56 100644 --- a/tests/ref/fate/filter-pixdesc-rgba +++ b/tests/ref/fate/filter-pixdesc-rgba @@ -1 +1 @@ -pixdesc-rgba 93a5b3712e6eb8c5b9a09ffc7b9fbc12 +pixdesc-rgba 301a8e45ab9d14a06c5cde7bbedef0b8 diff --git a/tests/ref/fate/filter-pixdesc-uyvy422 b/tests/ref/fate/filter-pixdesc-uyvy422 index a5b3703..2d89065 100644 --- a/tests/ref/fate/filter-pixdesc-uyvy422 +++ b/tests/ref/fate/filter-pixdesc-uyvy422 @@ -1 +1 @@ -pixdesc-uyvy422 adcf64516a19fce44df77082bdb16291 +pixdesc-uyvy422 a36a7fa35ad4acc647431a51c9beec4d diff --git a/tests/ref/fate/filter-pixdesc-yuv410p b/tests/ref/fate/filter-pixdesc-yuv410p index 237603a..7522a3e 100644 --- a/tests/ref/fate/filter-pixdesc-yuv410p +++ b/tests/ref/fate/filter-pixdesc-yuv410p @@ -1 +1 @@ -pixdesc-yuv410p 2d9225153c83ee1132397d619d94d1b3 +pixdesc-yuv410p 21a5303f9ef6819bd7abe4b86dc8cdf2 diff --git a/tests/ref/fate/filter-pixdesc-yuv411p b/tests/ref/fate/filter-pixdesc-yuv411p index a1ab6e4..3e0e8a2 100644 --- a/tests/ref/fate/filter-pixdesc-yuv411p +++ b/tests/ref/fate/filter-pixdesc-yuv411p @@ -1 +1 @@ -pixdesc-yuv411p 8b298af3e43348ca1b11eb8a3252ac6c +pixdesc-yuv411p c69ecd3af68379064fddc2f75611965e diff --git a/tests/ref/fate/filter-pixdesc-yuv420p b/tests/ref/fate/filter-pixdesc-yuv420p index 7b0cfd2..ea94f8c 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p +++ b/tests/ref/fate/filter-pixdesc-yuv420p @@ -1 +1 @@ -pixdesc-yuv420p eba2f135a08829387e2f698ff72a2939 +pixdesc-yuv420p 7aaf1057c0edf7d5e9700f9c8e510ea9 diff --git a/tests/ref/fate/filter-pixdesc-yuv420p10be b/tests/ref/fate/filter-pixdesc-yuv420p10be index 4fe0371..34c2dc8 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p10be +++ b/tests/ref/fate/filter-pixdesc-yuv420p10be @@ -1 +1 @@ -pixdesc-yuv420p10be 299fe1d785a3d3dd5e70778700d7fb06 +pixdesc-yuv420p10be 05662068c354779b0c26255efe33c955 diff --git a/tests/ref/fate/filter-pixdesc-yuv420p10le b/tests/ref/fate/filter-pixdesc-yuv420p10le index f1aaedf..bec240b 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p10le +++ b/tests/ref/fate/filter-pixdesc-yuv420p10le @@ -1 +1 @@ -pixdesc-yuv420p10le 8aee004e765a5383be0954f5e916b72f +pixdesc-yuv420p10le 591af435ff8650b48824ec3705a933d5 diff --git a/tests/ref/fate/filter-pixdesc-yuv420p16be b/tests/ref/fate/filter-pixdesc-yuv420p16be index 9f7221f..3e9c4f0 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p16be +++ b/tests/ref/fate/filter-pixdesc-yuv420p16be @@ -1 +1 @@ -pixdesc-yuv420p16be 16c009a235cd52b74791a895423152a3 +pixdesc-yuv420p16be df8ed373b77222ee82f12564b5edfa77 diff --git a/tests/ref/fate/filter-pixdesc-yuv420p16le b/tests/ref/fate/filter-pixdesc-yuv420p16le index 2bd8c94..c6e5141 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p16le +++ b/tests/ref/fate/filter-pixdesc-yuv420p16le @@ -1 +1 @@ -pixdesc-yuv420p16le 2d59c4f1d0314a5a957a7cfc4b6fabcc +pixdesc-yuv420p16le 5aa9648f73f09c1a3d1c652f2285762a diff --git a/tests/ref/fate/filter-pixdesc-yuv420p9be b/tests/ref/fate/filter-pixdesc-yuv420p9be index cd2e847..00fb78e 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p9be +++ b/tests/ref/fate/filter-pixdesc-yuv420p9be @@ -1 +1 @@ -pixdesc-yuv420p9be ce880fa07830e5297c22acf6e20555ce +pixdesc-yuv420p9be 605305ba8581d63f160c7885630514a6 diff --git a/tests/ref/fate/filter-pixdesc-yuv420p9le b/tests/ref/fate/filter-pixdesc-yuv420p9le index c887495..864456b 100644 --- a/tests/ref/fate/filter-pixdesc-yuv420p9le +++ b/tests/ref/fate/filter-pixdesc-yuv420p9le @@ -1 +1 @@ -pixdesc-yuv420p9le 16543fda8f87d94a6cf857d2e8d4461a +pixdesc-yuv420p9le 73722053a27e8c5ef8aa407a2452c652 diff --git a/tests/ref/fate/filter-pixdesc-yuv422p b/tests/ref/fate/filter-pixdesc-yuv422p index e533230..b49f995 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p +++ b/tests/ref/fate/filter-pixdesc-yuv422p @@ -1 +1 @@ -pixdesc-yuv422p c9bba4529821d796a6ab09f6a5fd355a +pixdesc-yuv422p 12b097c00dd1e526186d3d7dcba204bc diff --git a/tests/ref/fate/filter-pixdesc-yuv422p10be b/tests/ref/fate/filter-pixdesc-yuv422p10be index 2e68731..1e87294 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p10be +++ b/tests/ref/fate/filter-pixdesc-yuv422p10be @@ -1 +1 @@ -pixdesc-yuv422p10be 11af7dfafe8bc025c7e3bd82b830fe8a +pixdesc-yuv422p10be f53e6d39e40e1ae35cc855716dda8dbc diff --git a/tests/ref/fate/filter-pixdesc-yuv422p10le b/tests/ref/fate/filter-pixdesc-yuv422p10le index 3b173bc..d0d845d 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p10le +++ b/tests/ref/fate/filter-pixdesc-yuv422p10le @@ -1 +1 @@ -pixdesc-yuv422p10le ec04efb76efa79bf0d02b21572371a56 +pixdesc-yuv422p10le deab1e4f7f3907ffd06ec448cf142f3f diff --git a/tests/ref/fate/filter-pixdesc-yuv422p16be b/tests/ref/fate/filter-pixdesc-yuv422p16be index 9e69199..e09298c 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p16be +++ b/tests/ref/fate/filter-pixdesc-yuv422p16be @@ -1 +1 @@ -pixdesc-yuv422p16be 5499502e1c29534a158a1fe60e889f60 +pixdesc-yuv422p16be fddc6580ccbc42d1d2d4e40f44403c54 diff --git a/tests/ref/fate/filter-pixdesc-yuv422p16le b/tests/ref/fate/filter-pixdesc-yuv422p16le index 5a865b0..eea2005 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p16le +++ b/tests/ref/fate/filter-pixdesc-yuv422p16le @@ -1 +1 @@ -pixdesc-yuv422p16le e3d61fde6978591596bc36b914386623 +pixdesc-yuv422p16le 37760ff26bcc46d7cae41be0f7aa7287 diff --git a/tests/ref/fate/filter-pixdesc-yuv422p9be b/tests/ref/fate/filter-pixdesc-yuv422p9be index 7b244db..2b38cf0 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p9be +++ b/tests/ref/fate/filter-pixdesc-yuv422p9be @@ -1 +1 @@ -pixdesc-yuv422p9be 29b71579946940a8c00fa844c9dff507 +pixdesc-yuv422p9be d29a3861d4fb85b1f14af82b6c098d10 diff --git a/tests/ref/fate/filter-pixdesc-yuv422p9le b/tests/ref/fate/filter-pixdesc-yuv422p9le index a6dbb93..154abce 100644 --- a/tests/ref/fate/filter-pixdesc-yuv422p9le +++ b/tests/ref/fate/filter-pixdesc-yuv422p9le @@ -1 +1 @@ -pixdesc-yuv422p9le 062b7f9cbb972bf36b5bdb1a7623701a +pixdesc-yuv422p9le 77d1eb4547c7f1a22977924c154d049c diff --git a/tests/ref/fate/filter-pixdesc-yuv440p b/tests/ref/fate/filter-pixdesc-yuv440p index b6b6e14..dd9a59c 100644 --- a/tests/ref/fate/filter-pixdesc-yuv440p +++ b/tests/ref/fate/filter-pixdesc-yuv440p @@ -1 +1 @@ -pixdesc-yuv440p 5a064afe2b453bb52cdb3f176b1aa1cf +pixdesc-yuv440p 7f3e289e7109a051379313933e6e430f diff --git a/tests/ref/fate/filter-pixdesc-yuv444p b/tests/ref/fate/filter-pixdesc-yuv444p index 628f0e4..2ef114a 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p +++ b/tests/ref/fate/filter-pixdesc-yuv444p @@ -1 +1 @@ -pixdesc-yuv444p 0a98447b78fd476aa39686da6a74fa2e +pixdesc-yuv444p 37edfdeae2a93c91209e806cd9e0ceee diff --git a/tests/ref/fate/filter-pixdesc-yuv444p10be b/tests/ref/fate/filter-pixdesc-yuv444p10be index b1c57fa..05c346e 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p10be +++ b/tests/ref/fate/filter-pixdesc-yuv444p10be @@ -1 +1 @@ -pixdesc-yuv444p10be 71be185a2fb7a353eb024df9bc63212d +pixdesc-yuv444p10be df6bd44006a00116c4b805e0c83a98ba diff --git a/tests/ref/fate/filter-pixdesc-yuv444p10le b/tests/ref/fate/filter-pixdesc-yuv444p10le index 16be63f..57c5161 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p10le +++ b/tests/ref/fate/filter-pixdesc-yuv444p10le @@ -1 +1 @@ -pixdesc-yuv444p10le c1c6b30a12065c7901c0a267e4861a0f +pixdesc-yuv444p10le 94c579bd8e88f271cd193be222f93694 diff --git a/tests/ref/fate/filter-pixdesc-yuv444p16be b/tests/ref/fate/filter-pixdesc-yuv444p16be index 1ed4d0b..c8f19f4 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p16be +++ b/tests/ref/fate/filter-pixdesc-yuv444p16be @@ -1 +1 @@ -pixdesc-yuv444p16be 1c6ea2c2f5e539006112ceec3d4e7d90 +pixdesc-yuv444p16be 8172616c2590bfe95fb3115684b3bf06 diff --git a/tests/ref/fate/filter-pixdesc-yuv444p16le b/tests/ref/fate/filter-pixdesc-yuv444p16le index c685b8c..f4402bf 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p16le +++ b/tests/ref/fate/filter-pixdesc-yuv444p16le @@ -1 +1 @@ -pixdesc-yuv444p16le 20f86bc2f68d2b3f1f2b48b97b2189f4 +pixdesc-yuv444p16le 0cb500e7313e15513c5510edae51d46c diff --git a/tests/ref/fate/filter-pixdesc-yuv444p9be b/tests/ref/fate/filter-pixdesc-yuv444p9be index 6f87a9a..ad8ed8b 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p9be +++ b/tests/ref/fate/filter-pixdesc-yuv444p9be @@ -1 +1 @@ -pixdesc-yuv444p9be 6ab31f4c12b533ce318ecdff83cdd054 +pixdesc-yuv444p9be 6410ac29a501711ac3d7485adbee0736 diff --git a/tests/ref/fate/filter-pixdesc-yuv444p9le b/tests/ref/fate/filter-pixdesc-yuv444p9le index 83d83f6..dcf05e9 100644 --- a/tests/ref/fate/filter-pixdesc-yuv444p9le +++ b/tests/ref/fate/filter-pixdesc-yuv444p9le @@ -1 +1 @@ -pixdesc-yuv444p9le f0606604a5c08becab6ba500124c4b7c +pixdesc-yuv444p9le ed579c47f3a0cdb481a886e2b3192c42 diff --git a/tests/ref/fate/filter-pixdesc-yuva420p b/tests/ref/fate/filter-pixdesc-yuva420p index 7194758..49d5485 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p +++ b/tests/ref/fate/filter-pixdesc-yuva420p @@ -1 +1 @@ -pixdesc-yuva420p a29884f3f3dfe1e00b961bc17bef3d47 +pixdesc-yuva420p 43d7123392af51a8716447a7dd69608b diff --git a/tests/ref/fate/filter-pixdesc-yuva420p10be b/tests/ref/fate/filter-pixdesc-yuva420p10be index 6d3723f..6ed19b1 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p10be +++ b/tests/ref/fate/filter-pixdesc-yuva420p10be @@ -1 +1 @@ -pixdesc-yuva420p10be145366ff1632de3e300d947f49844284 +pixdesc-yuva420p10beb3d4763eae9de728a4e10ddc89a18cf6 diff --git a/tests/ref/fate/filter-pixdesc-yuva420p10le b/tests/ref/fate/filter-pixdesc-yuva420p10le index 5b7f692..d4f21a0 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p10le +++ b/tests/ref/fate/filter-pixdesc-yuva420p10le @@ -1 +1 @@ -pixdesc-yuva420p10led797038552d7f698e4d1db4dfa18ceb0 +pixdesc-yuva420p10leaa8d76f2871dc8f9a20919a2f13688ec diff --git a/tests/ref/fate/filter-pixdesc-yuva420p16be b/tests/ref/fate/filter-pixdesc-yuva420p16be index 6e82b70..077eab5 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p16be +++ b/tests/ref/fate/filter-pixdesc-yuva420p16be @@ -1 +1 @@ -pixdesc-yuva420p16be25a335f66a0670911ced818aa42fb670 +pixdesc-yuva420p16beaba97863a5e670a2a6b772cf82940e04 diff --git a/tests/ref/fate/filter-pixdesc-yuva420p16le b/tests/ref/fate/filter-pixdesc-yuva420p16le index 2bedb68..3fb3a2e 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p16le +++ b/tests/ref/fate/filter-pixdesc-yuva420p16le @@ -1 +1 @@ -pixdesc-yuva420p16le97bf252e6c030f0f0412d3826c2ea259 +pixdesc-yuva420p16leb1680b05ce69447bdc53dec154addc0a diff --git a/tests/ref/fate/filter-pixdesc-yuva420p9be b/tests/ref/fate/filter-pixdesc-yuva420p9be index 3a621bd..1004d31 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p9be +++ b/tests/ref/fate/filter-pixdesc-yuva420p9be @@ -1 +1 @@ -pixdesc-yuva420p9be 06b764d85bd3c22e9b7ca4babed84d4f +pixdesc-yuva420p9be 3c9ce8191c1510b35fee892ad15d39b9 diff --git a/tests/ref/fate/filter-pixdesc-yuva420p9le b/tests/ref/fate/filter-pixdesc-yuva420p9le index 5edc34d..8ed1daf 100644 --- a/tests/ref/fate/filter-pixdesc-yuva420p9le +++ b/tests/ref/fate/filter-pixdesc-yuva420p9le @@ -1 +1 @@ -pixdesc-yuva420p9le 1f01cdd4fc46f98d4c11b2947307a0e3 +pixdesc-yuva420p9le 1955fb115953284ea0ecdc0d4b10e0ae diff --git a/tests/ref/fate/filter-pixdesc-yuva422p b/tests/ref/fate/filter-pixdesc-yuva422p index b50c2a3..df5a856 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p +++ b/tests/ref/fate/filter-pixdesc-yuva422p @@ -1 +1 @@ -pixdesc-yuva422p 92b6815f465297284cdb843711682cee +pixdesc-yuva422p 639ce1131de9b362d18b3dc7f871c1ae diff --git a/tests/ref/fate/filter-pixdesc-yuva422p10be b/tests/ref/fate/filter-pixdesc-yuva422p10be index c012d70..601e66f 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p10be +++ b/tests/ref/fate/filter-pixdesc-yuva422p10be @@ -1 +1 @@ -pixdesc-yuva422p10befb240ff9ac49b45b1b3d40df2c89e39d +pixdesc-yuva422p10bec797caa09ee483d6cc0b06eac7fc606b diff --git a/tests/ref/fate/filter-pixdesc-yuva422p10le b/tests/ref/fate/filter-pixdesc-yuva422p10le index 632cb6f..9b4b1c3 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p10le +++ b/tests/ref/fate/filter-pixdesc-yuva422p10le @@ -1 +1 @@ -pixdesc-yuva422p10lef767ede9ba1d427faadc963cf41d2412 +pixdesc-yuva422p10le61a6339e7321972ee6f45428bd55a8f3 diff --git a/tests/ref/fate/filter-pixdesc-yuva422p16be b/tests/ref/fate/filter-pixdesc-yuva422p16be index b9d5bde..1c651d1 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p16be +++ b/tests/ref/fate/filter-pixdesc-yuva422p16be @@ -1 +1 @@ -pixdesc-yuva422p16beef442b11b26e5e61f3c958fa309576dd +pixdesc-yuva422p16be01381b27508afbca57241d7431da7ba9 diff --git a/tests/ref/fate/filter-pixdesc-yuva422p16le b/tests/ref/fate/filter-pixdesc-yuva422p16le index 22ad86e..1f1f1d3 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p16le +++ b/tests/ref/fate/filter-pixdesc-yuva422p16le @@ -1 +1 @@ -pixdesc-yuva422p16le5789009759d7a44dacc6da2194e402b1 +pixdesc-yuva422p16lef5c8d306a099d594749ddebeb279b259 diff --git a/tests/ref/fate/filter-pixdesc-yuva422p9be b/tests/ref/fate/filter-pixdesc-yuva422p9be index 967b324..ff6514c 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p9be +++ b/tests/ref/fate/filter-pixdesc-yuva422p9be @@ -1 +1 @@ -pixdesc-yuva422p9be e0d2f45f7f5541eee988137c7ebb3495 +pixdesc-yuva422p9be eb35d12008a9dce4ff860951ded90edb diff --git a/tests/ref/fate/filter-pixdesc-yuva422p9le b/tests/ref/fate/filter-pixdesc-yuva422p9le index 2ce6d76..22003df 100644 --- a/tests/ref/fate/filter-pixdesc-yuva422p9le +++ b/tests/ref/fate/filter-pixdesc-yuva422p9le @@ -1 +1 @@ -pixdesc-yuva422p9le a4ec81f328efd3856dec430fb27f2f56 +pixdesc-yuva422p9le e97bd27f580cd46ee3feb2ba3c8c057d diff --git a/tests/ref/fate/filter-pixdesc-yuva444p b/tests/ref/fate/filter-pixdesc-yuva444p index 43083b1..56bc201 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p +++ b/tests/ref/fate/filter-pixdesc-yuva444p @@ -1 +1 @@ -pixdesc-yuva444p c523716e4900cfe515eaab1d7124fdd9 +pixdesc-yuva444p d78d51ee6286394b1f1839dd74d68861 diff --git a/tests/ref/fate/filter-pixdesc-yuva444p10be b/tests/ref/fate/filter-pixdesc-yuva444p10be index 2b79d4e..89df14f 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p10be +++ b/tests/ref/fate/filter-pixdesc-yuva444p10be @@ -1 +1 @@ -pixdesc-yuva444p10bef5791a75fdb86da0c243511ef9ab8fbd +pixdesc-yuva444p10be32f40553f2d8d771561d4f6f8514e1e8 diff --git a/tests/ref/fate/filter-pixdesc-yuva444p10le b/tests/ref/fate/filter-pixdesc-yuva444p10le index 80a1ed8..cb4b663 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p10le +++ b/tests/ref/fate/filter-pixdesc-yuva444p10le @@ -1 +1 @@ -pixdesc-yuva444p10le578e88dfbe4ab07f280fcc7554f3a5c4 +pixdesc-yuva444p10le1bb71c784b65cdcb06408a37c2fa2eef diff --git a/tests/ref/fate/filter-pixdesc-yuva444p16be b/tests/ref/fate/filter-pixdesc-yuva444p16be index 400010b..a9bffff 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p16be +++ b/tests/ref/fate/filter-pixdesc-yuva444p16be @@ -1 +1 @@ -pixdesc-yuva444p16beee7b9dd854e36b165d5b7cffb646ba6c +pixdesc-yuva444p16beb52b5efbad264a6a8aa7280234e0c9d6 diff --git a/tests/ref/fate/filter-pixdesc-yuva444p16le b/tests/ref/fate/filter-pixdesc-yuva444p16le index 1564007..249090c 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p16le +++ b/tests/ref/fate/filter-pixdesc-yuva444p16le @@ -1 +1 @@ -pixdesc-yuva444p16leec93b2907923d5655e9fb085479260ef +pixdesc-yuva444p16le54d4ab00bb5a0e7228a974d27b59285c diff --git a/tests/ref/fate/filter-pixdesc-yuva444p9be b/tests/ref/fate/filter-pixdesc-yuva444p9be index 4d781bc..041a57b 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p9be +++ b/tests/ref/fate/filter-pixdesc-yuva444p9be @@ -1 +1 @@ -pixdesc-yuva444p9be 03414257d78e72c28d03e3c247319b7c +pixdesc-yuva444p9be 0139f53dd39f1538648c5be2f38fb3ed diff --git a/tests/ref/fate/filter-pixdesc-yuva444p9le b/tests/ref/fate/filter-pixdesc-yuva444p9le index 646a2a2..71e4490 100644 --- a/tests/ref/fate/filter-pixdesc-yuva444p9le +++ b/tests/ref/fate/filter-pixdesc-yuva444p9le @@ -1 +1 @@ -pixdesc-yuva444p9le e421d753257e36a79c2c0ec1607ac9e6 +pixdesc-yuva444p9le 6f16075ddc120457eef912beb20ed546 diff --git a/tests/ref/fate/filter-pixdesc-yuvj420p b/tests/ref/fate/filter-pixdesc-yuvj420p index 3187f9d..d31bdfc 100644 --- a/tests/ref/fate/filter-pixdesc-yuvj420p +++ b/tests/ref/fate/filter-pixdesc-yuvj420p @@ -1 +1 @@ -pixdesc-yuvj420p 32eec78ba51857b16ce9b813a49b7189 +pixdesc-yuvj420p 6cb083afe6e0b54ba9753744194ca765 diff --git a/tests/ref/fate/filter-pixdesc-yuvj422p b/tests/ref/fate/filter-pixdesc-yuvj422p index f5f2af4..1480ae5 100644 --- a/tests/ref/fate/filter-pixdesc-yuvj422p +++ b/tests/ref/fate/filter-pixdesc-yuvj422p @@ -1 +1 @@ -pixdesc-yuvj422p 0dfa0ed434f73be51428758c69e082cb +pixdesc-yuvj422p 6b2dfa7e50dfe279cd73eeaf9b767dc0 diff --git a/tests/ref/fate/filter-pixdesc-yuvj440p b/tests/ref/fate/filter-pixdesc-yuvj440p index 9fc39cf..480017f 100644 --- a/tests/ref/fate/filter-pixdesc-yuvj440p +++ b/tests/ref/fate/filter-pixdesc-yuvj440p @@ -1 +1 @@ -pixdesc-yuvj440p 657501a28004e27a592757a7509f5189 +pixdesc-yuvj440p 278317b4ff8b272b22465481d3673a7c diff --git a/tests/ref/fate/filter-pixdesc-yuvj444p b/tests/ref/fate/filter-pixdesc-yuvj444p index c2bf052..5f6c301 100644 --- a/tests/ref/fate/filter-pixdesc-yuvj444p +++ b/tests/ref/fate/filter-pixdesc-yuvj444p @@ -1 +1 @@ -pixdesc-yuvj444p 98d3d054f2ec09a75eeed5d328dc75b7 +pixdesc-yuvj444p a56b1f49af0a7a42794d92bea3eca9c9 diff --git a/tests/ref/fate/filter-pixdesc-yuyv422 b/tests/ref/fate/filter-pixdesc-yuyv422 index 2a4980d..434a880 100644 --- a/tests/ref/fate/filter-pixdesc-yuyv422 +++ b/tests/ref/fate/filter-pixdesc-yuyv422 @@ -1 +1 @@ -pixdesc-yuyv422 f2569f2b5069a0ee0cecae33de0455e3 +pixdesc-yuyv422 d154fdb0bd0258f1a0cdeaaaefa21581 diff --git a/tests/ref/fate/filter-pixdesc-yvyu422 b/tests/ref/fate/filter-pixdesc-yvyu422 index 934df9b..cac9726 100644 --- a/tests/ref/fate/filter-pixdesc-yvyu422 +++ b/tests/ref/fate/filter-pixdesc-yvyu422 @@ -1 +1 @@ -pixdesc-yvyu422 17aef3e345d23edd3c660a91dcfc5a19 +pixdesc-yvyu422 24f0a489853ededa47cd7386c116fb3f diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index f99e8ea..2f6a71e 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -1,90 +1,91 @@ -abgr 037bf9df6a765520ad6d490066bf4b89 -argb c442a8261c2265a07212ef0f72e35f5a -bgr24 0d0cb38ab3fa0b2ec0865c14f78b217b -bgr444be d9ea9307d21b162225b8b2c524cf9477 -bgr444le 88035350e9da3a8f67387890b956f0bc -bgr48be 00624e6c7ec7ab19897ba2f0a3257fe8 -bgr48le d02c235ebba7167881ca2d576497ff84 -bgr4_byte 50d23cc82d9dcef2fd12adb81fb9b806 -bgr555be 49f01b1f1f0c84fd9e776dd34cc3c280 -bgr555le 378d6ac4223651a1adcbf94a3d0d807b -bgr565be 257cf78afa35dc31e9696f139c916715 -bgr565le 1dfdd03995c287e3c754b164bf26a355 -bgr8 24bd566170343d06fec6fccfff5abc54 -bgra 76a18a5151242fa137133f604cd624d2 -gbrp 76204621e200a3cc633012f6720c7005 -gbrp10be 2ca4a4a589a7dc461ff186913c7a69e5 -gbrp10le 46176f1fcc6e67f9862115fe373f73d3 -gbrp9be 981c2c1b0ef1791824b4c7518331bc2e -gbrp9le 25fb915ed11d07d631e0e7b78d54bebf -gray db08f7f0751900347e6b8649e4164d21 -gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 -gray16le 10bd87059b5c189f3caef2837f4f2b5c -monob 668ebe8b8103b9046b251b2fa8a1d88f -monow 9251497f3b0634f1165d12d5a289d943 -nv12 e0af357888584d36eec5aa0f673793ef -nv21 9a3297f3b34baa038b1f37cb202b512f -rgb24 b41eba9651e1b5fe386289b506188105 -rgb444be 9e89db334568c6b2e3d5d0540f4ba960 -rgb444le 0a68cb6de8bf530aa30c5c1205c25155 -rgb48be cc139ec1dd9451f0e049c0cb3a0c8aa2 -rgb48le 86c5608904f75360d492dbc5c9589969 -rgb4_byte c93ba89b74c504e7f5ae9d9ab1546c73 -rgb555be 912a62c5e53bfcbac2a0340e10973cf2 -rgb555le a937a0fc764fb57dc1b3af87cba0273c -rgb565be 9cadf742e05ddc23a3b5b270f89aad3c -rgb565le d39aa298bb525e9be8860351c6f62dab -rgb8 4a9d8e4f2f154e83a7e1735be6300700 -rgba 93a5b3712e6eb8c5b9a09ffc7b9fbc12 -uyvy422 adcf64516a19fce44df77082bdb16291 -yuv410p 2d9225153c83ee1132397d619d94d1b3 -yuv411p 8b298af3e43348ca1b11eb8a3252ac6c -yuv420p eba2f135a08829387e2f698ff72a2939 -yuv420p10be 299fe1d785a3d3dd5e70778700d7fb06 -yuv420p10le 8aee004e765a5383be0954f5e916b72f -yuv420p16be 16c009a235cd52b74791a895423152a3 -yuv420p16le 2d59c4f1d0314a5a957a7cfc4b6fabcc -yuv420p9be ce880fa07830e5297c22acf6e20555ce -yuv420p9le 16543fda8f87d94a6cf857d2e8d4461a -yuv422p c9bba4529821d796a6ab09f6a5fd355a -yuv422p10be 11af7dfafe8bc025c7e3bd82b830fe8a -yuv422p10le ec04efb76efa79bf0d02b21572371a56 -yuv422p16be 5499502e1c29534a158a1fe60e889f60 -yuv422p16le e3d61fde6978591596bc36b914386623 -yuv422p9be 29b71579946940a8c00fa844c9dff507 -yuv422p9le 062b7f9cbb972bf36b5bdb1a7623701a -yuv440p 5a064afe2b453bb52cdb3f176b1aa1cf -yuv444p 0a98447b78fd476aa39686da6a74fa2e -yuv444p10be 71be185a2fb7a353eb024df9bc63212d -yuv444p10le c1c6b30a12065c7901c0a267e4861a0f -yuv444p16be 1c6ea2c2f5e539006112ceec3d4e7d90 -yuv444p16le 20f86bc2f68d2b3f1f2b48b97b2189f4 -yuv444p9be 6ab31f4c12b533ce318ecdff83cdd054 -yuv444p9le f0606604a5c08becab6ba500124c4b7c -yuva420p a29884f3f3dfe1e00b961bc17bef3d47 -yuva420p10be 145366ff1632de3e300d947f49844284 -yuva420p10le d797038552d7f698e4d1db4dfa18ceb0 -yuva420p16be 25a335f66a0670911ced818aa42fb670 -yuva420p16le 97bf252e6c030f0f0412d3826c2ea259 -yuva420p9be 06b764d85bd3c22e9b7ca4babed84d4f -yuva420p9le 1f01cdd4fc46f98d4c11b2947307a0e3 -yuva422p 92b6815f465297284cdb843711682cee -yuva422p10be fb240ff9ac49b45b1b3d40df2c89e39d -yuva422p10le f767ede9ba1d427faadc963cf41d2412 -yuva422p16be ef442b11b26e5e61f3c958fa309576dd -yuva422p16le 5789009759d7a44dacc6da2194e402b1 -yuva422p9be e0d2f45f7f5541eee988137c7ebb3495 -yuva422p9le a4ec81f328efd3856dec430fb27f2f56 -yuva444p c523716e4900cfe515eaab1d7124fdd9 -yuva444p10be f5791a75fdb86da0c243511ef9ab8fbd -yuva444p10le 578e88dfbe4ab07f280fcc7554f3a5c4 -yuva444p16be ee7b9dd854e36b165d5b7cffb646ba6c -yuva444p16le ec93b2907923d5655e9fb085479260ef -yuva444p9be 03414257d78e72c28d03e3c247319b7c -yuva444p9le e421d753257e36a79c2c0ec1607ac9e6 -yuvj420p 32eec78ba51857b16ce9b813a49b7189 -yuvj422p 0dfa0ed434f73be51428758c69e082cb -yuvj440p 657501a28004e27a592757a7509f5189 -yuvj444p 98d3d054f2ec09a75eeed5d328dc75b7 -yuyv422 f2569f2b5069a0ee0cecae33de0455e3 -yvyu422 17aef3e345d23edd3c660a91dcfc5a19 +abgr 1250387304351fea5cc57b232bc0a5e5 +argb ee5a1e2e2d4dbd2cd978d6e3bf8dee70 +bgr24 437ea8de747009d73f41af120f0360ad +bgr444be 0a9b7c91c6f50c0ed2633aebd19d7326 +bgr444le f032368a3134918e6802922e4cde7baf +bgr48be bf24403f14d4085f970475dd17a9edcd +bgr48le 1db5661da851a44dd5b92f8dd5a0ec84 +bgr4_byte 2bf8e7fbf1179ba0543cb42d2d8a5308 +bgr555be b8b23bcfa9a850d46850d59662e6eba8 +bgr555le d72c90906cb4df818abb37fb07a67d01 +bgr565be 0fcba91cb4c55a458271173cb26e649d +bgr565le 6a0d182c7165103b2613d1805c822f9f +bgr8 36b9ef72c87da36ac547202d85a5805f +bgra 56e6e1bfde40aaa27473e01b46345c82 +gbrap 57cb1a02d6f015a4329fe367f3bdfe49 +gbrp d5f73b5d3ba7f6cadbc9b4ecbc161005 +gbrp10be eb19bda60ab7f893198364dff21342d6 +gbrp10le 546146efb36ad2605e9f74ee5e4c2a36 +gbrp9be cbe1bf8ead497a92362a749bd4b0a57e +gbrp9le f88c68df5d699a4a7f1b0152df9f25fe +gray 8c941e9bbf6da5336384c57f15a4a454 +gray16be 43bda75c197b0d59a9b87ee941553644 +gray16le a4ea1369ef1efff0e1341a1dc42dbfdf +monob e13b2cbfb93d3ed6fdc1f256662ea959 +monow 87a594c125f52af67dc1dd51d800ff31 +nv12 a0b3578ec9b28be3d6e66479df8b1995 +nv21 a9318dc58dc14b9931a00ea6cedea849 +rgb24 fc0c7ce1d5d6be1b89d4471542785508 +rgb444be cc479f17c73cd50d65475a1644c5053f +rgb444le c98bc1811d29a86471357cb2358e5a30 +rgb48be 1e2a176dadf246e376932a20303ca572 +rgb48le 57fd6d93cda99070acc4213b6958fe70 +rgb4_byte e4dcdc9adddcb3958ddd0ea3b0896140 +rgb555be 8fd499c9a6d98414ab2803ae08698651 +rgb555le a9b93f8b61e52eac76aca392dc3ebd81 +rgb565be a8c6c7817f80c8a0cee9918c3748e00c +rgb565le 510a4ce796d7cb11aba5b25b419cdf3b +rgb8 2e53d27e93554f874986fbba4f9d6354 +rgba ed87fc4907951608893b421624716f9b +uyvy422 deb3625b67a8d2a51c17a322ad2021ba +yuv410p dec949ce1d8a5f7bb1aa7640f97e05eb +yuv411p fc2f303b20ae610dce86dae4a6671881 +yuv420p a2117c3c5d4533dca311dc94a3d157bc +yuv420p10be 7756ef359f79d63ef6f983caeaba5c51 +yuv420p10le aa8abcc05010b4b0df7d924fd5887291 +yuv420p16be 7a708532d8ac26d598ac7332e38dd2de +yuv420p16le 6b868d3b0c44c6b04f39415890d6ee0b +yuv420p9be 11ffb289661f4f55347d60e99dcef632 +yuv420p9le a0c9608b2be3ca6d4e8cf625714a3833 +yuv422p b082344038849f5fd444ccf2a30e3f4f +yuv422p10be 43a6293e138d0ecfd3385df3dcf9b713 +yuv422p10le 74da030a4efb5a20986fcead50018f4d +yuv422p16be f7a0fb9e82805660317d07209e726100 +yuv422p16le 12eeb2f95bb0d655d52e8eed1cfbf771 +yuv422p9be 60daf1a7e61434b244c5a43f4449b617 +yuv422p9le 4c4885c48812f5ac0916a9509ba84345 +yuv440p 12000ce709b38aac3f7b7f59b07847ef +yuv444p 628c9d1e10c22e0e512b27c0e03b46e6 +yuv444p10be b60d77db54a592ed088ebf7964e2dd5e +yuv444p10le 1752a238eb27fb7c746e349536f60686 +yuv444p16be 8e1e2f04cb2e97f80fdfecbb2c5679a0 +yuv444p16le 5677b2caa63e0c075eac6937b03cf2a6 +yuv444p9be 5ab55576b180b2966e9ed5a1ea55508a +yuv444p9le 3d9b69b8d6e17f2d25ce92602688bcc8 +yuva420p 9e9889ad7837b0d0dde023bf931ed639 +yuva420p10be ff20f57da08f79e44e7b603e89b18d74 +yuva420p10le a2dcfa563602232d999a19b7ae272131 +yuva420p16be 63bd8a57eedfc58e8e6319913ee1064c +yuva420p16le 797dc4ff3a9a3f36cb84ddd808a1c04a +yuva420p9be d2de221d375fea605a9f81c9e0fd3661 +yuva420p9le 0dd82737677f2b604a0aaa638e65f64a +yuva422p 375465ec39a82221a4a502e92bf0453f +yuva422p10be 81144a6638bc34bd9e6790977159a754 +yuva422p10le b30c735f71275004d2d7d78ec647fd5b +yuva422p16be b7641ec1896f306065073f0348448f19 +yuva422p16le 3ab82ddf757a78f0184c01aa0259fc42 +yuva422p9be dd2a4affd2140d945c88c545cbd15794 +yuva422p9le a7a00cf6c696e8e94ce62576dbb28527 +yuva444p 8031aee1a4a13d679e3fa960b70e27c7 +yuva444p10be 62dc7423df2a90da591e313dea0f72b0 +yuva444p10le e45e36e79e39e1ed300fc93bc20a2232 +yuva444p16be c2321be5e7184b874cf4e16fff959179 +yuva444p16le 107836d19b0735f225eb7d97da98fd49 +yuva444p9be d8ba268bef3cf8d2dbd57a65b49be6db +yuva444p9le f4589d40b7514e021ec7096003907ef7 +yuvj420p 9ba65711dfe07d3078b5b874b49240fb +yuvj422p 05873ba9f14597ded3d4a2f6e1cd7e5c +yuvj440p d76a421f62d692c664cbb2d1727e77d2 +yuvj444p 787e53351113065777bd1061ddb04834 +yuyv422 48d652c76bbdebec0bf7842578b39c53 +yvyu422 b0364ee13bd574d01b23a0809e6ddca9 diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index cbbcf90..c42c620 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -1,42 +1,42 @@ -abgr cd761690872843d1b7ab0c695393c751 -argb 2ec6ef18769bcd651c2e8904d5a3ee67 -bgr24 3450fd00cf1493d1ded75544d82ba3ec -bgr48be 18ca4002732f278cc9f525215c2fca41 -bgr48le 395a4c187c4e95217d089bd3df9f3654 -bgr4_byte 2f6ac3cdd4676ab4e2982bdf0664945b -bgr555be d3a7c273604723adeb7e5f5dd1c4272b -bgr555le d22442fc13b464f9ba455b08df4e981f -bgr565be fadceef4a64ad6873fcb43ddee0deb3c -bgr565le 891664e5a54ae5968901347da92bc5e9 -bgr8 4b7159e05765bd4703180072d86423c8 -bgra 395c9f706fccda721471acaa5c96c16c -gray 8c4850e66562a587a292dc728a65ea4a -gray16be daa5a6b98fb4a280c57c57bff1a2ab5a -gray16le 84f5ea7259073edcb893113b42213c8e -rgb24 3b90ed64b687d3dc186c6ef521dc71a8 -rgb48be e6fd353c0eb9bea889423954414bea35 -rgb48le 68a1723da11ce08b502d42e204376503 -rgb4_byte 6958029f73c6cdfed4f71020d816f027 -rgb555be 41a7d1836837bc90f2cae19a9c9df3b3 -rgb555le eeb78f8ce6186fba55c941469e60ba67 -rgb565be b2d1cb525f3a0cfe27753c0d479b2fa9 -rgb565le 6a49700680be9a0d434411825a769556 -rgb8 88b0398c265d1ed7a837dc084fa0917c -rgba fd00b24c7597268c32759a84a1de2de4 -yuv410p a9f2eaa747bf988b7bebe4f442b9c67a -yuv411p 3334d3aef8dba238658090ac172375d1 -yuv420p bfea0188ddd4889787c403caae119cc7 -yuv420p16be 8365eff38b8c329aeb95fc605fa229bb -yuv420p16le 5e8dd38d973d5854abe1ad4efad20cc1 -yuv422p f2f930a91fe00d4252c4720b5ecd8961 -yuv422p16be 167e4338811a7d272925a4c6417d60da -yuv422p16le 3359395d5875d581fa1e975013d30114 -yuv440p 2472417d980e395ad6843cbb8b633b29 -yuv444p 1f151980486848c96bc5585ced99003e -yuv444p16be 1ce8fcd4712d525af983e6179d6a4f9e -yuv444p16le 5f1441e18345aadb3f881dac99c6c08a -yuva420p 7536753dfbc7932560fb50c921369a0e -yuvj420p 21f891093006d42d7683b0e1d773a657 -yuvj422p 9a43d474c407590ad8f213880586b45e -yuvj440p 977351350450ebdbf7a9d20020c6b5a5 -yuvj444p 4a50ba26859dad91dcf7000de0d0efa1 +abgr 5f70a21347bce16111a36fc41a117df8 +argb 35801018bb35dcb0ee31f66f0090b890 +bgr24 f9cc271089a5b560f29d9614f357c720 +bgr48be 8d957f7b11ed446dcea5f76c164f2368 +bgr48le 2a72cdae677d2c190b5beefd7e8a0e53 +bgr4_byte 8612d21fb5c353bdcf3eecb66a0bb0c3 +bgr555be 5c6c82ba788553cab28794c7c4707558 +bgr555le 326db2c29c70aef71b5d408dd6ca8c86 +bgr565be 035910ec94dbca6dae1e81f26852bcc3 +bgr565le 84dec346512486158c7d65299e62e924 +bgr8 e6d8896ccbe02c04d208bae55fc221c4 +bgra cfc8cdc70ed29bc206dbc907495d0869 +gray ccac69ad220529826be3d94d29157e8d +gray16be a8f761dc9e6dad62d1e4459eec9baf07 +gray16le 8b480306cb5584bc85fb51d1ea97b8f4 +rgb24 b85c0b1e6039a971bdef1d710bf7f8d3 +rgb48be 5ea361c8fbff68868e20385508b63181 +rgb48le 5966526796a37f871fd0831c41ddd3dc +rgb4_byte 774ca7852d51ae52462b0360112e143f +rgb555be c4bd32793895432e6c2f1c4e2b6c4e94 +rgb555le a320a2e210e4e9f1352ffa8af2793b27 +rgb565be dc1440a7832c7ff781bbbd62dbadf6b1 +rgb565le 64f2ebebb02c2ac8eab2ed708c297fa4 +rgb8 ebc7118d01e82b77b8aeddb1f83a2872 +rgba 32bdb0cf19af40203515fd83c6cec8c8 +yuv410p 006e5b4735797ff0e7e3c7dd27660a8e +yuv411p 894e368ed68876e357f095a8b2a7b3a7 +yuv420p d9641cbe8436380d8505ddd695b0a7d2 +yuv420p16be 8b7ad840e9079a19da1bfed79a448847 +yuv420p16le 8827ee2f20ee18bae143b9b38b0f8622 +yuv422p 31277ec25cbb0c43eb57d4f29047a267 +yuv422p16be 49cdcc490b4e87a65eef88feacdb87d2 +yuv422p16le e634bdf11b047f3641fb0de1eb0feb57 +yuv440p f9340d3797c3b3446bc830e4e198d5be +yuv444p 43bf7b75708d62f0f02fb3f6b8dd3bba +yuv444p16be 8dc374395cd1f31e52609089c54c9908 +yuv444p16le 285df61fab70499218677c1eed4db448 +yuva420p a8d2c50df5fe5808b7057727699640f3 +yuvj420p cc464c6e15079539b907414b5aaa32e0 +yuvj422p 7ee6bd168e2ae34eabb6ae617f02739e +yuvj440p 35a50b3b8ca637fbf5ad581fa742ad34 +yuvj444p 5dbd0537a42bedcf941fb27f74b54b69 diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index 3741713..d39b0ca 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -1,42 +1,42 @@ -abgr 49468c6c9ceee5d52b08b1270a909323 -argb 50ba9f16c6475530602f2983278b82d0 -bgr24 cc53d2011d097972db0d22756c3699e3 -bgr48be 815192d3757c66de97b0d51818acbe0f -bgr48le 8e4184ac6eae251b4bace51dba7d790c -bgr4_byte aac987e7d1a6a96477cfc0b48a4285de -bgr555be bc07265898440116772200390d70c092 -bgr555le ccee08679bac84a1f960c6c9070c5538 -bgr565be e088789ce46224b87c6e46610ef19add -bgr565le 3703466e19e1b52e03a34fd244a8e8e4 -bgr8 50b505a889f0428242305acb642da107 -bgra 01ca21e7e6a8d1281b4553bde8e8a404 -gray 03efcb4ab52a24c0af0e03cfd26c9377 -gray16be 9bcbca979601ddc4869f846f08f3d1dd -gray16le c1b8965adcc7f847ee343149ff507073 -rgb24 754f1722fc738590cc407ac65749bfe8 -rgb48be d690412ca5fada031b5da47b87096248 -rgb48le c901feb564232f5d0bc0eabd66dae3e7 -rgb4_byte c8a3f995fcf3e0919239ea2c413ddc29 -rgb555be 045ce8607d3910586f4d97481dda8632 -rgb555le 8778ee0cf58ce9ad1d99a1eca9f95e87 -rgb565be c8022a1b2470e72f124e4389fad4c372 -rgb565le 2cb690eb3fcb72da3771ad6a48931158 -rgb8 9e462b811b9b6173397b9cfc1f6b2f17 -rgba d3d0dc1ecef3ed72f26a2986d0efc204 -yuv410p acb543ebbbf63eefe533e6faffc006da -yuv411p c626cf6d191139b4ca7efc0155f957f1 -yuv420p 2d5c80f9ba2ddd85b2aeda3564cc7d64 -yuv420p16be 758b0c1e2113b15e7afde48da4e4d024 -yuv420p16le 480ccd951dcb806bc875d307e02e50a0 -yuv422p 6e728f4eb9eae287c224f396d84be6ea -yuv422p16be a05d43cd62b790087bd37083174557de -yuv422p16le 6954abebcbc62d81068d58d0c62bdd5b -yuv440p a99e2b57ed601f39852715c9d675d0d3 -yuv444p 947e47f7bb5fdccc659d19b7df2b6fc3 -yuv444p16be 58c012e5ab73b066ef3c2b6411a395f1 -yuv444p16le 32c12794e184042a59738ab2de608c8d -yuva420p d83ec0c01498189f179ec574918185f1 -yuvj420p df3aaaec3bb157c3bde5f0365af30f4f -yuvj422p d113871528d510a192797af59df9c05c -yuvj440p 07f5ff12ced85aba1b5cf51692fff4bb -yuvj444p 8d95f6b4d4c9b4b0389d36df686bfa46 +abgr 7b68405327d7c0862b4e3c1a2e5f8401 +argb f2d838efb97f9daa035681acf0fd7aa3 +bgr24 6428be12c092356cf9a570b43566b406 +bgr48be e776e0de8605c9db81380fddb3aa8a16 +bgr48le eba1836285756b8950981dea2c02be6a +bgr4_byte 658a71bfc3a2e9271bf60ddda03d138d +bgr555be 39d9fafcfed4f7c4ebe0a5bdfb202d67 +bgr555le 92f693be95b64dca452221747bab4f70 +bgr565be 3bb3d1918f7a9977ff3998c051159102 +bgr565le bea2b9a14a24acd7a7443fa4cdc45128 +bgr8 c07a695e1a247f753a24c08de1124eaa +bgra 2a358c075799b6e4ff56c0d4464d7f9e +gray 60c5640a7a48454c6a18375ab9c99599 +gray16be 64ba7dcd3478833d2fffd3705ef1123e +gray16le d4f370937b499c9b63c31970f409114c +rgb24 24b18acc43c119f2de1e727b32b550b1 +rgb48be 23ed645ce6c7e4cedd8045130ae07e15 +rgb48le 6918e306925438c92b8100ff9408eec9 +rgb4_byte 2c6929584add1f600e1c87a61d9450c4 +rgb555be 8b4adf81d9c9b9161891229ad79f8b66 +rgb555le 51684ecc7cf0cb11dd87909e0dfd71ac +rgb565be d9a4eafb25d103c3dd79c7d6e58e1ce4 +rgb565le 1476f867d8f1f970d51f9dd6cb51307c +rgb8 b7a090903c6f1d9c9ad6215a8e7b71cc +rgba cf8ba075a00d44599a8a49caa37d87f7 +yuv410p af26db9a0af59863c6643f21259ecc54 +yuv411p 58f0cf9d30c5604fcfe1209d281a9242 +yuv420p 0e86307c56a749cb6009ee1509d709d0 +yuv420p16be a1e2b231fe1de23fae97cb9d6d5cce2b +yuv420p16le c5a2ff8d29e25840dfabc441b4cf733f +yuv422p 52faae832987874d7cd49bdc76b08762 +yuv422p16be 5001f3a4216e895f84b78e8bfda0cb43 +yuv422p16le 90303bb96430e12d6f45b3d2e90a9dd1 +yuv440p 30da73c35a5862e39d7d43bca3dc70ce +yuv444p 3b472a790d4db3a5c404cfcc16ea44a6 +yuv444p16be 7efc49abd10868e5bfa2bf4bf5ad9ec0 +yuv444p16le 59140c4d599e80ceb75d8ae803c5f538 +yuva420p ee3499a2bc030c68f51aa11887b9fa56 +yuvj420p 75344d0547474b9198ffbae2a54c571b +yuvj422p 3b479c749d6de189735c95fe6b051c13 +yuvj440p fe56033764fadf849d73ed992a1f9010 +yuvj444p 3068acd925a73222e79a1da31496eb48 diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index f99e8ea..2f6a71e 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -1,90 +1,91 @@ -abgr 037bf9df6a765520ad6d490066bf4b89 -argb c442a8261c2265a07212ef0f72e35f5a -bgr24 0d0cb38ab3fa0b2ec0865c14f78b217b -bgr444be d9ea9307d21b162225b8b2c524cf9477 -bgr444le 88035350e9da3a8f67387890b956f0bc -bgr48be 00624e6c7ec7ab19897ba2f0a3257fe8 -bgr48le d02c235ebba7167881ca2d576497ff84 -bgr4_byte 50d23cc82d9dcef2fd12adb81fb9b806 -bgr555be 49f01b1f1f0c84fd9e776dd34cc3c280 -bgr555le 378d6ac4223651a1adcbf94a3d0d807b -bgr565be 257cf78afa35dc31e9696f139c916715 -bgr565le 1dfdd03995c287e3c754b164bf26a355 -bgr8 24bd566170343d06fec6fccfff5abc54 -bgra 76a18a5151242fa137133f604cd624d2 -gbrp 76204621e200a3cc633012f6720c7005 -gbrp10be 2ca4a4a589a7dc461ff186913c7a69e5 -gbrp10le 46176f1fcc6e67f9862115fe373f73d3 -gbrp9be 981c2c1b0ef1791824b4c7518331bc2e -gbrp9le 25fb915ed11d07d631e0e7b78d54bebf -gray db08f7f0751900347e6b8649e4164d21 -gray16be 7becf34ae825a3df3969bf4c6bfeb5e2 -gray16le 10bd87059b5c189f3caef2837f4f2b5c -monob 668ebe8b8103b9046b251b2fa8a1d88f -monow 9251497f3b0634f1165d12d5a289d943 -nv12 e0af357888584d36eec5aa0f673793ef -nv21 9a3297f3b34baa038b1f37cb202b512f -rgb24 b41eba9651e1b5fe386289b506188105 -rgb444be 9e89db334568c6b2e3d5d0540f4ba960 -rgb444le 0a68cb6de8bf530aa30c5c1205c25155 -rgb48be cc139ec1dd9451f0e049c0cb3a0c8aa2 -rgb48le 86c5608904f75360d492dbc5c9589969 -rgb4_byte c93ba89b74c504e7f5ae9d9ab1546c73 -rgb555be 912a62c5e53bfcbac2a0340e10973cf2 -rgb555le a937a0fc764fb57dc1b3af87cba0273c -rgb565be 9cadf742e05ddc23a3b5b270f89aad3c -rgb565le d39aa298bb525e9be8860351c6f62dab -rgb8 4a9d8e4f2f154e83a7e1735be6300700 -rgba 93a5b3712e6eb8c5b9a09ffc7b9fbc12 -uyvy422 adcf64516a19fce44df77082bdb16291 -yuv410p 2d9225153c83ee1132397d619d94d1b3 -yuv411p 8b298af3e43348ca1b11eb8a3252ac6c -yuv420p eba2f135a08829387e2f698ff72a2939 -yuv420p10be 299fe1d785a3d3dd5e70778700d7fb06 -yuv420p10le 8aee004e765a5383be0954f5e916b72f -yuv420p16be 16c009a235cd52b74791a895423152a3 -yuv420p16le 2d59c4f1d0314a5a957a7cfc4b6fabcc -yuv420p9be ce880fa07830e5297c22acf6e20555ce -yuv420p9le 16543fda8f87d94a6cf857d2e8d4461a -yuv422p c9bba4529821d796a6ab09f6a5fd355a -yuv422p10be 11af7dfafe8bc025c7e3bd82b830fe8a -yuv422p10le ec04efb76efa79bf0d02b21572371a56 -yuv422p16be 5499502e1c29534a158a1fe60e889f60 -yuv422p16le e3d61fde6978591596bc36b914386623 -yuv422p9be 29b71579946940a8c00fa844c9dff507 -yuv422p9le 062b7f9cbb972bf36b5bdb1a7623701a -yuv440p 5a064afe2b453bb52cdb3f176b1aa1cf -yuv444p 0a98447b78fd476aa39686da6a74fa2e -yuv444p10be 71be185a2fb7a353eb024df9bc63212d -yuv444p10le c1c6b30a12065c7901c0a267e4861a0f -yuv444p16be 1c6ea2c2f5e539006112ceec3d4e7d90 -yuv444p16le 20f86bc2f68d2b3f1f2b48b97b2189f4 -yuv444p9be 6ab31f4c12b533ce318ecdff83cdd054 -yuv444p9le f0606604a5c08becab6ba500124c4b7c -yuva420p a29884f3f3dfe1e00b961bc17bef3d47 -yuva420p10be 145366ff1632de3e300d947f49844284 -yuva420p10le d797038552d7f698e4d1db4dfa18ceb0 -yuva420p16be 25a335f66a0670911ced818aa42fb670 -yuva420p16le 97bf252e6c030f0f0412d3826c2ea259 -yuva420p9be 06b764d85bd3c22e9b7ca4babed84d4f -yuva420p9le 1f01cdd4fc46f98d4c11b2947307a0e3 -yuva422p 92b6815f465297284cdb843711682cee -yuva422p10be fb240ff9ac49b45b1b3d40df2c89e39d -yuva422p10le f767ede9ba1d427faadc963cf41d2412 -yuva422p16be ef442b11b26e5e61f3c958fa309576dd -yuva422p16le 5789009759d7a44dacc6da2194e402b1 -yuva422p9be e0d2f45f7f5541eee988137c7ebb3495 -yuva422p9le a4ec81f328efd3856dec430fb27f2f56 -yuva444p c523716e4900cfe515eaab1d7124fdd9 -yuva444p10be f5791a75fdb86da0c243511ef9ab8fbd -yuva444p10le 578e88dfbe4ab07f280fcc7554f3a5c4 -yuva444p16be ee7b9dd854e36b165d5b7cffb646ba6c -yuva444p16le ec93b2907923d5655e9fb085479260ef -yuva444p9be 03414257d78e72c28d03e3c247319b7c -yuva444p9le e421d753257e36a79c2c0ec1607ac9e6 -yuvj420p 32eec78ba51857b16ce9b813a49b7189 -yuvj422p 0dfa0ed434f73be51428758c69e082cb -yuvj440p 657501a28004e27a592757a7509f5189 -yuvj444p 98d3d054f2ec09a75eeed5d328dc75b7 -yuyv422 f2569f2b5069a0ee0cecae33de0455e3 -yvyu422 17aef3e345d23edd3c660a91dcfc5a19 +abgr 1250387304351fea5cc57b232bc0a5e5 +argb ee5a1e2e2d4dbd2cd978d6e3bf8dee70 +bgr24 437ea8de747009d73f41af120f0360ad +bgr444be 0a9b7c91c6f50c0ed2633aebd19d7326 +bgr444le f032368a3134918e6802922e4cde7baf +bgr48be bf24403f14d4085f970475dd17a9edcd +bgr48le 1db5661da851a44dd5b92f8dd5a0ec84 +bgr4_byte 2bf8e7fbf1179ba0543cb42d2d8a5308 +bgr555be b8b23bcfa9a850d46850d59662e6eba8 +bgr555le d72c90906cb4df818abb37fb07a67d01 +bgr565be 0fcba91cb4c55a458271173cb26e649d +bgr565le 6a0d182c7165103b2613d1805c822f9f +bgr8 36b9ef72c87da36ac547202d85a5805f +bgra 56e6e1bfde40aaa27473e01b46345c82 +gbrap 57cb1a02d6f015a4329fe367f3bdfe49 +gbrp d5f73b5d3ba7f6cadbc9b4ecbc161005 +gbrp10be eb19bda60ab7f893198364dff21342d6 +gbrp10le 546146efb36ad2605e9f74ee5e4c2a36 +gbrp9be cbe1bf8ead497a92362a749bd4b0a57e +gbrp9le f88c68df5d699a4a7f1b0152df9f25fe +gray 8c941e9bbf6da5336384c57f15a4a454 +gray16be 43bda75c197b0d59a9b87ee941553644 +gray16le a4ea1369ef1efff0e1341a1dc42dbfdf +monob e13b2cbfb93d3ed6fdc1f256662ea959 +monow 87a594c125f52af67dc1dd51d800ff31 +nv12 a0b3578ec9b28be3d6e66479df8b1995 +nv21 a9318dc58dc14b9931a00ea6cedea849 +rgb24 fc0c7ce1d5d6be1b89d4471542785508 +rgb444be cc479f17c73cd50d65475a1644c5053f +rgb444le c98bc1811d29a86471357cb2358e5a30 +rgb48be 1e2a176dadf246e376932a20303ca572 +rgb48le 57fd6d93cda99070acc4213b6958fe70 +rgb4_byte e4dcdc9adddcb3958ddd0ea3b0896140 +rgb555be 8fd499c9a6d98414ab2803ae08698651 +rgb555le a9b93f8b61e52eac76aca392dc3ebd81 +rgb565be a8c6c7817f80c8a0cee9918c3748e00c +rgb565le 510a4ce796d7cb11aba5b25b419cdf3b +rgb8 2e53d27e93554f874986fbba4f9d6354 +rgba ed87fc4907951608893b421624716f9b +uyvy422 deb3625b67a8d2a51c17a322ad2021ba +yuv410p dec949ce1d8a5f7bb1aa7640f97e05eb +yuv411p fc2f303b20ae610dce86dae4a6671881 +yuv420p a2117c3c5d4533dca311dc94a3d157bc +yuv420p10be 7756ef359f79d63ef6f983caeaba5c51 +yuv420p10le aa8abcc05010b4b0df7d924fd5887291 +yuv420p16be 7a708532d8ac26d598ac7332e38dd2de +yuv420p16le 6b868d3b0c44c6b04f39415890d6ee0b +yuv420p9be 11ffb289661f4f55347d60e99dcef632 +yuv420p9le a0c9608b2be3ca6d4e8cf625714a3833 +yuv422p b082344038849f5fd444ccf2a30e3f4f +yuv422p10be 43a6293e138d0ecfd3385df3dcf9b713 +yuv422p10le 74da030a4efb5a20986fcead50018f4d +yuv422p16be f7a0fb9e82805660317d07209e726100 +yuv422p16le 12eeb2f95bb0d655d52e8eed1cfbf771 +yuv422p9be 60daf1a7e61434b244c5a43f4449b617 +yuv422p9le 4c4885c48812f5ac0916a9509ba84345 +yuv440p 12000ce709b38aac3f7b7f59b07847ef +yuv444p 628c9d1e10c22e0e512b27c0e03b46e6 +yuv444p10be b60d77db54a592ed088ebf7964e2dd5e +yuv444p10le 1752a238eb27fb7c746e349536f60686 +yuv444p16be 8e1e2f04cb2e97f80fdfecbb2c5679a0 +yuv444p16le 5677b2caa63e0c075eac6937b03cf2a6 +yuv444p9be 5ab55576b180b2966e9ed5a1ea55508a +yuv444p9le 3d9b69b8d6e17f2d25ce92602688bcc8 +yuva420p 9e9889ad7837b0d0dde023bf931ed639 +yuva420p10be ff20f57da08f79e44e7b603e89b18d74 +yuva420p10le a2dcfa563602232d999a19b7ae272131 +yuva420p16be 63bd8a57eedfc58e8e6319913ee1064c +yuva420p16le 797dc4ff3a9a3f36cb84ddd808a1c04a +yuva420p9be d2de221d375fea605a9f81c9e0fd3661 +yuva420p9le 0dd82737677f2b604a0aaa638e65f64a +yuva422p 375465ec39a82221a4a502e92bf0453f +yuva422p10be 81144a6638bc34bd9e6790977159a754 +yuva422p10le b30c735f71275004d2d7d78ec647fd5b +yuva422p16be b7641ec1896f306065073f0348448f19 +yuva422p16le 3ab82ddf757a78f0184c01aa0259fc42 +yuva422p9be dd2a4affd2140d945c88c545cbd15794 +yuva422p9le a7a00cf6c696e8e94ce62576dbb28527 +yuva444p 8031aee1a4a13d679e3fa960b70e27c7 +yuva444p10be 62dc7423df2a90da591e313dea0f72b0 +yuva444p10le e45e36e79e39e1ed300fc93bc20a2232 +yuva444p16be c2321be5e7184b874cf4e16fff959179 +yuva444p16le 107836d19b0735f225eb7d97da98fd49 +yuva444p9be d8ba268bef3cf8d2dbd57a65b49be6db +yuva444p9le f4589d40b7514e021ec7096003907ef7 +yuvj420p 9ba65711dfe07d3078b5b874b49240fb +yuvj422p 05873ba9f14597ded3d4a2f6e1cd7e5c +yuvj440p d76a421f62d692c664cbb2d1727e77d2 +yuvj444p 787e53351113065777bd1061ddb04834 +yuyv422 48d652c76bbdebec0bf7842578b39c53 +yvyu422 b0364ee13bd574d01b23a0809e6ddca9 diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 03db5a7..a3d455a 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -1,17 +1,17 @@ -abgr e8e5e350c856c051d502cd435a2aa0bd -argb a98e0a1213824ee4566d4891468bb614 -bgr24 ac7417cea8d6e799a31a3c9a39b8f202 -bgra 6113a09a023cb2b08e9cad78eb1eb37a -rgb24 65eed443acc66c4f02bab6df4ebed515 -rgba 74d4158ad0c626e9a7c6923b9ca73294 -yuv410p a5210eb6a9b10c3269899b935df9a2d6 -yuv411p a23380c9698e2d80c9fa8a8b6d4f6854 -yuv420p f8733600369adaea28aa445dbdf2ed4c -yuv422p 3e0d822c11c716e7636387b1bf27c5ff -yuv440p 225dd7fbc8cceb24c26b765187d43a9e -yuv444p 45484f0411d336ce94636da0395f4692 -yuva420p 919722724765dc3a716c38fa53b20580 -yuvj420p 4f20e2799966c21a9d9e0788b0956925 -yuvj422p e4d84b0683f77a76f1c17d976eff127c -yuvj440p 33511c43339aa32533ab832861c150c3 -yuvj444p 82f0badd9d0c062bbfa0d9d73d7240a3 +abgr 3dbc32909d43adc2a00f8dc267f4954c +argb f35a99b4c7334d30d8338b5091ff42bb +bgr24 b946a53a21bee12c6bacf7c9eee0464e +bgra c12f833549d02143495031161167130e +rgb24 203a6870c2e78acdd88594204f48485c +rgba 3cae5f1cd260be32a588ad9ee00d761b +yuv410p f62c12181d4367bcd22a114288f8ab63 +yuv411p 7ed82814854efe8b6ecca1dddfcf2f4f +yuv420p 776d85a7a7f60f87bae5ac01fbefc8e6 +yuv422p 31de52cc5bc44973397e29e40a72f10b +yuv440p 87666e1ff40ef0d6145d583dc9e0593c +yuv444p 1b1e0dde6f5d663ddc80cdf69554327c +yuva420p 4a36d4bb207e898058e72f8aaf2aa86f +yuvj420p 4d1ec70f1ba1eb04b16113807c78c534 +yuvj422p fcf366fe525a5be6e488542448a10e30 +yuvj440p 2315e0d1bcd2ae6493207149abeaf97f +yuvj444p 6da403666e2d0110161ccf0737fb35aa diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index dcd73bd..fbbc1c9 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -1,90 +1,91 @@ -abgr d894cb97f6c80eb21bdbe8a4eea62d86 -argb 54346f2b2eef10919e0f247241df3b24 -bgr24 570f8d6b51a838aed022ef67535f6bdc -bgr444be 25fe04f73a3bad4140d1c4f96ca5b670 -bgr444le 2fde227e6cea6dca5decdd0b7c0866f7 -bgr48be 390d3058a12a99c2b153ed7922508bea -bgr48le 39fe06feb4ec1d9730dccc04a0cfac4c -bgr4_byte ee1d35a7baf8e9016891929a2f565c0b -bgr555be de8901c1358834fddea060fcb3a67beb -bgr555le 36b745067197f9ca8c1731cac51329c9 -bgr565be 922a2503767036ae9536f4f7823c04ee -bgr565le 3a514a298c6161a071ddf9963c06509d -bgr8 7f007fa6c153a16e808a9c51605a4016 -bgra a5e7040f9a80cccd65e5acf2ca09ace5 -gbrp 205c50f8359cb4ba2827a7711dea2cc6 -gbrp10be 30b7f9d5ef5da474fb794743146236aa -gbrp10le 2e9949a01fe4c38774728e34795165cc -gbrp9be 6bac01a7f64a381521b2149fc46f4178 -gbrp9le 4b6cba7acf7886c13db122e590ec6b1f -gray d7786a7d9d99ac74230cc045cab5632c -gray16be b554d6c1cc8da23967445be4dd3e4a86 -gray16le 715a33aa1c19cb26b14f5cc000e7a3d1 -monob 88c4c050758e64d120f50c7eff694381 -monow d31772ebaa877fc2a78565937f7f9673 -nv12 4676d59db43d657dc12841f6bc3ab452 -nv21 69c699510ff1fb777b118ebee1002f14 -rgb24 514692e28e8ff6860e415ce4fcf6eb8c -rgb444be 12254053ae93373869fca18b2afcba31 -rgb444le badbd68b59c87df6ae73248309637634 -rgb48be 8fac63787a711886030f8e056872b488 -rgb48le ab92f2763a2eb264c3870cc758f97149 -rgb4_byte d81ffd3add95842a618eec81024f0b5c -rgb555be 4607309f9f217d51cbb53d13b84b4537 -rgb555le a350ef1dc2c9688ed49e7ba018843795 -rgb565be 678ce231c4ea13629c1353b1df4ffbef -rgb565le 6f4bb711238baa762d73305213f8d035 -rgb8 091d0170b354ef0e97312b95feb5483f -rgba a3d362f222098a00e63867f612018659 -uyvy422 314bd486277111a95d9369b944fa0400 -yuv410p 7df8f6d69b56a8dcb6c7ee908e5018b5 -yuv411p 1143e7c5cc28fe0922b051b17733bc4c -yuv420p fdad2d8df8985e3d17e73c71f713cb14 -yuv420p10be 27f28a6e09b1c04d0f755035a5db1f43 -yuv420p10le a5a1692e026590ba2eddb46b9b827529 -yuv420p16be d7270efce54eb59c7b01c14157a1b890 -yuv420p16le e85abf00bad940a922b623c91c9026d7 -yuv420p9be bb87fddca65d1742412c8d2b1caf96c6 -yuv420p9le 828eec50014a41258a5423c1fe56ac97 -yuv422p 918e37701ee7377d16a8a6c119c56a40 -yuv422p10be 315654908d50718e175aae018c484732 -yuv422p10le 91bbc78a9a56f659b55abc17722dcc09 -yuv422p16be e7e34fe9264784763ab6cb406524c0f3 -yuv422p16le c435b76b08204dda6908640fb5fd4621 -yuv422p9be 82494823944912f73cebc58ad2979bbd -yuv422p9le fc69c8a21f473916a4b4225636b97e06 -yuv440p 461503fdb9b90451020aa3b25ddf041c -yuv444p 81b2eba962d12e8d64f003ac56f6faf2 -yuv444p10be fb304d77c6d2e18df5938662a22176f0 -yuv444p10le b17136913eb066dca6be6af645b9f7e8 -yuv444p16be 0da9bed80f5542682ab286f3261cf24c -yuv444p16le a0c5d3c7bf3f181db503cf8e450d1335 -yuv444p9be 9ac2643ce7f7e5c4e17c8c9fd8494d4a -yuv444p9le 896a1cc9cccca1ba410dd53942d33cc4 -yuva420p 8673a9131fb47de69788863f93a50eb7 -yuva420p10be d92a95061809f251175f5d5e3074930e -yuva420p10le bad90ba2d4c260e379a7aa6dc7760853 -yuva420p16be a61d8ddb646e2d26020fc7ed2a48c1a9 -yuva420p16le 90ef774f86ad3177ec57eca8744b4e09 -yuva420p9be f7655546446bfdc875243d7cdeb13b30 -yuva420p9le ada2b719827059d70ebc57e2a3f9da92 -yuva422p 3c76ebeca0a7d3aa5f8e31ef80a86ffe -yuva422p10be 01dd539e4a62762a3c97e965c76bb6f7 -yuva422p10le 76355d9d8fdcd085a24d48832b72e40b -yuva422p16be c21afa31ac18bd92e8e596b81552b52b -yuva422p16le 0bc3720dba6076dcce3b74b1d3c6c4b7 -yuva422p9be a60ac5b8026e9621724c033fbf79dbda -yuva422p9le c3eda8831e9b9c94a3eb487d33114103 -yuva444p 3268c6abe5e3cdbd16552a1eddced816 -yuva444p10be 856b37c1ee53459f46b9359d329ac9b5 -yuva444p10le 22790592361c007406d4ca9a9e0954a5 -yuva444p16be ed5b07fe4d5b1137604568786777af1d -yuva444p16le 3a3df23feb60d8832b566fd9765983d0 -yuva444p9be 4fc479c5b1044ad37b4e6fc6488b4f7f -yuva444p9le c41849b0134670d6f6253c337defbb04 -yuvj420p 30427bd6caf5bda93a173dbebe759e09 -yuvj422p fc8288f64fd149573f73cf8da05d8e6d -yuvj440p 508ac7a9ddeb6d1794a1100ba7a1664c -yuvj444p 73aebe144085b22d1189caf6ca07e18c -yuyv422 169e19ac91b257bd84ace0fdf56559ad -yvyu422 d0d3dbd1ae665ff0cf8b0a5d64878622 +abgr d7f91e65b25b81f43e8b4d5076116fb1 +argb 3b1964f62ab059fc8d692c63f1fc450c +bgr24 dcc565b1ffcdae2f60e9759d4d33f596 +bgr444be ba5750740f17cb862e56628683b64258 +bgr444le 2c872b0b91347a35ca00cad816ff3f89 +bgr48be 650aaa8f7db84bcf5c6f2b3da86ee803 +bgr48le 90b82c85b88296fff879c60f21182ae6 +bgr4_byte 7b4e4dc6ae1cdf9e18d9eba79a5b7d23 +bgr555be 80fb87c21c07bf833926c9675ebbe01d +bgr555le 4539913198858f1bc3899aad97ad105a +bgr565be ac67f35b6bc7835d1fbfeee3ef89fd59 +bgr565le 34438643c183ff1748cf7d71453f981c +bgr8 e731ba3dbec294e1daa7313e08e88034 +bgra 6e1f417ae41636f631de1cfe39ce1778 +gbrap eefdbfd1426765ce5e9790022533db0d +gbrp 5d14768d2ab6cbf3879966b5d5c6befb +gbrp10be 4192c246f4a52ec7a37919665190cce9 +gbrp10le 170189b2c2dd46f31165d8fa6cadef0a +gbrp9be 01c837e1def99abec205b80d21b68bf0 +gbrp9le dd982d59c3d71c3b201f2d9363d8952c +gray 4c571fb634a75f177b64cee168fbf3a1 +gray16be 9b57ff7d2090b47e4427bee79dba0d9e +gray16le 17d2c00c6ffe346dfb632d927ebbf30a +monob e28955319a03f1850c467f8fe65b2a22 +monow 69334639f5298173154b262d9054e384 +nv12 e7638156463b059aa75b1d667c89367e +nv21 adbed0790db2c85c9e777a84acf0c290 +rgb24 6187e90455674633e7d08451a99f17b1 +rgb444be 4ad70310205575f370fa7a9ebee119a2 +rgb444le db9a9973e41a0d583d9c1b536e7717b3 +rgb48be ae0836178249743c91867ee057baf7d9 +rgb48le 49564ae5cab04678889064b1132b44b8 +rgb4_byte 62269884de14b7defbdc7fb8044203c3 +rgb555be 3a1c13bbae95358f9cc23f4a138d4867 +rgb555le fbd6b3d1847ee6c9ba9033fce72ac18e +rgb565be fdbb84b9f559b4ba14c1407218c79795 +rgb565le 9cea852347ca6ba09944f577ace89d2b +rgb8 eeb820691b7fd1cb07a0fa066098f926 +rgba 68a05bdcf4abe3b92353d1e4386c94c9 +uyvy422 1d9946bcceb6d13cf0f0deda322a9868 +yuv410p 2cbf84ef9f283b00aee46883653dab8c +yuv411p 091777fdfffa2dccbfd75769d1a402c7 +yuv420p 4f0105b3f2008bff284de251fe61ce06 +yuv420p10be caaee5d071cccf50cc51c70f7a233024 +yuv420p10le 06c47286459599c62b25466e2ee3c91d +yuv420p16be 10ba255f3901b5d47d3ac803fb787bcf +yuv420p16le 38c42f658cad8546bfc465b72f6312ab +yuv420p9be 17cd0ca2d12fd972045271e06a14b711 +yuv420p9le 38289963713431c8b4a2e7c08b8564b6 +yuv422p 66f47bfad422275bd07b2881760d09a2 +yuv422p10be 00504b09c67e203fc29cac3ae2aa91db +yuv422p10le b8b38a8d1f1eec3915b628c873bf756a +yuv422p16be 2f12b4fb816afcaa77e7359b95f25532 +yuv422p16le 3913bbbd4b0aa8038e8565c7312e25be +yuv422p9be f86744d026c3a65d54c737a93e80093f +yuv422p9le ad53382760dcf7cce4317247aa0058f7 +yuv440p 4713a7b7ce80dd06923626d13589c098 +yuv444p fd733672651ad5bbffb046fd67151fee +yuv444p10be 34b38d54167df70044bdc08518d91009 +yuv444p10le 0812e3371c9589c6621408812f9e7a27 +yuv444p16be e89fe5a4624ed06603580b4a74af9170 +yuv444p16le 6944d11048ff4013c5e60359faf1bd2d +yuv444p9be 04a950e843d099eb9ade2ddcea494fb3 +yuv444p9le 918015450d5ab87600de64bbb7b33a10 +yuva420p 279eec11fe81f48a6cf2950fe097c51f +yuva420p10be b9178665f4ff9512b10552f212157a94 +yuva420p10le a627c535ced8514f2e1d1b78e73ca046 +yuva420p16be 2ec22c863c67bcba0295e125d0fa9f3e +yuva420p16le 98725d82a8cc4cf0d2c8673a4e7a7904 +yuva420p9be 44cd32fba1717fc8cf0e11e23a2b601f +yuva420p9le bcc9e4b4e78d032e2f7b7ced418ad218 +yuva422p 026c5cdefe5d34892e0bacbd0a59c71e +yuva422p10be 69926b201407ed64fc84abe878be9778 +yuva422p10le 3a4f9779467d055e85aca502fdec32d0 +yuva422p16be 7cdacc54f1fdcad30a69fffa393280e3 +yuva422p16le ab4a73cd006559cc8a276f37e481a817 +yuva422p9be e517391bb53c4b0f8399a5b3155bbbf9 +yuva422p9le 6b66e4543e1fa4583909cfb03bf842a3 +yuva444p b931c613cf41f29673cecc0d6e8c3ef6 +yuva444p10be 3ae3aca8e9d72905df4db6e48cd1aa28 +yuva444p10le 780a786f9205a40331a6ab4ae1b976f2 +yuva444p16be 48e17ea2342cd07d5c2996610f33e543 +yuva444p16le c42df24e7389fa3ee44b05dfc973a482 +yuva444p9be 26cb299ae97a75a86df04daea1d0999c +yuva444p9le c3e986b78252b413c08d77bcf9da5ab1 +yuvj420p 72ccdc3bd9a363a3b6f1072060df0518 +yuvj422p 278fd54d0e21a3958c46b7f1e680740f +yuvj440p 413af44fd797db64eb5e72ff448c9ae9 +yuvj444p 9b59dd2345672db000d8baa4a2bc1e20 +yuyv422 dcf49cd849d061a7dcec8bd72adee30f +yvyu422 c8ef92b4a717f832ff150ea6e78c7e65 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 073322d..da13b16 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -1,90 +1,91 @@ -abgr 25e72e9dbd01ab00727c976d577f7be5 -argb 19869bf1a5ac0b6af4d8bbe2c104533c -bgr24 89108a4ba00201f79b75b9305c42352d -bgr444be 9ef12c42fb791948ca4423c452dc6b9a -bgr444le 3650ecfc163abd1596c0cd29d130c4b0 -bgr48be 2f23931844f57641f3737348182d118c -bgr48le 4242a026012b6c135a6aa138a6d67031 -bgr4_byte 407fcf564ed764c38e1d748f700ab921 -bgr555be f739d2519f7e9d494359bf67a3821537 -bgr555le bd7b3ec4d684dfad075d89a606cb8b74 -bgr565be f19e9a4786395e1ddcd51399c98c9f6c -bgr565le fdb617533e1e7ff512ea5b6b6233e738 -bgr8 c60f93fd152c6903391d1fe9decd3547 -bgra 7f9b799fb48544e49ce93e91d7f9fca8 -gbrp 25c1bce192daefab910d51a56b52199e -gbrp10be 6fe980f9ca94cbcdb9e01f4e906fdf19 -gbrp10le f793a1d96d3524c6a17e53356c415c4e -gbrp9be e10dc3a2566b065260a45356ef08c1cd -gbrp9le f25105a33f18d6bcca3205c67ec106be -gray 30d9014a9d43b5f37e7aa64be3a3ecfc -gray16be 6b84b85d3326182fa1217e138249edc5 -gray16le 66bb8faa09dc149734aca3c768a6d4e1 -monob d0cf8732677a5360b6160133043590d8 -monow ff9869d067ecb94eb9d90c9750c31fea -nv12 046f00f598ce14d9854a3534a5c99114 -nv21 01ea369dd2d0d3ed7451dc5c8d61497f -rgb24 eaefabc168d0b14576bab45bc1e56e1e -rgb444be 06722e03f8404e7d2226665ed2444a32 -rgb444le 185c9a5d9c2877484310d4196ef4cd6f -rgb48be 62dd185862ed142283bd300eb6dbd216 -rgb48le dcb76353268bc5862194d131762220da -rgb4_byte 8c6ff02df0b06dd2d574836c3741b2a2 -rgb555be 40dc33cfb5cf56aac1c5a290ac486c36 -rgb555le 4f8eaad29a17e0f8e9d8ab743e76b999 -rgb565be b57623ad9df74648339311a0edcebc7b -rgb565le 73f247a3315dceaea3022ac7c197c5ef -rgb8 13a8d89ef78d8127297d899005456ff0 -rgba 1fc6e920a42ec812aaa3b2aa02f37987 -uyvy422 ffbd36720c77398d9a0d03ce2625928f -yuv410p 7bfb39d7afb49d6a6173e6b23ae321eb -yuv411p 4a90048cc3a65fac150e53289700efe1 -yuv420p 2e6d6062e8cad37fb3ab2c433b55f382 -yuv420p10be fb0772f5e2b9da20ff826e64c3893137 -yuv420p10le e95879e14c4a6805f39643964baf41f7 -yuv420p16be 539076782902664a8acf381bf4f713e8 -yuv420p16le 0f609e588e5a258644ef85170d70e030 -yuv420p9be be40ec975fb2873891643cbbbddbc3b0 -yuv420p9le 7e606310d3f5ff12badf911e8f333471 -yuv422p d7f5cb44d9b0210d66d6a8762640ab34 -yuv422p10be 0be8378c3773e1c0b394315ef4994351 -yuv422p10le 6518094fe8de6bee95af21af1e5dc1e1 -yuv422p16be 9bd8f8c961822b586fa4cf992be54acc -yuv422p16le 9c4a1239605c7952b736ac3130163f14 -yuv422p9be 7c6f1e140b3999ee7d923854e507752a -yuv422p9le 51f10d79c07989060dd06e767e6d7d60 -yuv440p 876385e96165acf51271b20e5d85a416 -yuv444p 9c3c667d1613b72d15bc6d851c5eb8f7 -yuv444p10be ee069cc6db48975eb029d72f889a7fe6 -yuv444p10le 645b3335248113cafe3c29edb1d7f3be -yuv444p16be de2dedfc6f12073ffead113f86e07ecf -yuv444p16le 8e83323cf102d6c823a03ae8a7b7e033 -yuv444p9be 6ac92b7dc9ab2fc59bee99204886899a -yuv444p9le 85aef13a654953d3455d89770b0d74bd -yuva420p c705d1cf061d8c6580ac690b55f92276 -yuva420p10be baa5e3b0ff6d0ebbb0958560cd763c6e -yuva420p10le a36dc59ad55b406e5fee475236e9753c -yuva420p16be bf3b134eb70878df9afba61d03e930b8 -yuva420p16le 105d375154329a381aa58379a0a6ec46 -yuva420p9be 8273d591e055f48990c29dd905a6cdfd -yuva420p9le 95ced0bb07e422d98db61a35cdb3fb8f -yuva422p 6aed0ea657ed51cc047a4fbdd981aec8 -yuva422p10be d69a3404984c5fd30c0fc548532bcb6b -yuva422p10le a40c8e6f50e12d94bf7484107ec98559 -yuva422p16be 39552c259ca242f2417e913ffc602fde -yuva422p16le 16faa558a34291ca32f6d94dce211ee2 -yuva422p9be a951eafb62c092c63f7566b6803f60df -yuva422p9le 00b39cfca78666e057ee527f5e174a04 -yuva444p da5d64f2b2bd2013c186456f595fad65 -yuva444p10be 00e74a9c0c7818a9bbd9fee95b961ee8 -yuva444p10le cbe30f44b63cf7ed27fc2dde40315b5e -yuva444p16be 7e9b799b057e1446dabbf0f738480cfb -yuva444p16le 556d58b91a617fe4a83af99a4aea1c2e -yuva444p9be b5a31de4fac408eeecaf3aff11f40e55 -yuva444p9le 67467f1e1d9edbd59d3984ebbfe24be6 -yuvj420p 41fd02b204da0ab62452cd14b595e2e4 -yuvj422p 7f6ca9bc1812cde02036d7d29a7cce43 -yuvj440p 25711c3c0fd15ec19c59a10784fcfb96 -yuvj444p e45dee2ac02276dfab92e8ebfbe52e00 -yuyv422 e944ff7316cd03c42c091717ce74f602 -yvyu422 02c8cd287744c94b48da7cf111e3eea0 +abgr d8d94531620310ec8a731af8d7fdb0ff +argb 8bc98feb8e990e4ff411663deb9aa566 +bgr24 0a56e4b125552a0660f85f9e3169323d +bgr444be a4c570c5a6abb38295141fb6f17670c3 +bgr444le 4ed7bb09f3f4f68a12ff2d8e7c837b5a +bgr48be 9c5191d6db9c7b1abaa9f01b06f02fd4 +bgr48le 31e97c178ad0c4a18ad6690832dbff31 +bgr4_byte 8edfbb2878970f0d44fbf589664c821f +bgr555be be4a39677809398b4299c9fbf363290d +bgr555le 15b938709fffc9348ea50cd46b918541 +bgr565be 3c48959244ef268a37e8b3732023e5aa +bgr565le 6f98ccb05e608863ef0912b9a6fd960b +bgr8 1f916a75563e6be42c056e7d973a7356 +bgra dd8eaea69683884ea45bf2fb635ce415 +gbrap 38e04cbd4dc5566586d58ffed0c6b20d +gbrp 37954476d089b5b74b06891e64ad6b9e +gbrp10be ec01c15ed248a72c42f84a2a8cfec56f +gbrp10le be52e72a59d87a43727262bcd90967cd +gbrp9be 2ae8f0d3b079d6550a2b1d4a7c4a6e4b +gbrp9le c62df0f386c957cc9cacb3c8014542eb +gray 684ba667effbbf5983f46a9bea4afaae +gray16be 112077b2f1c85cbd44907ed271901b28 +gray16le 1d7be18af19f4ff847ff4bc7c610c8cc +monob 0e4946183903fea3ef246c16385e236c +monow ba546dd99f6bbc4b7d310961df4d6d98 +nv12 2ca05c89d890eee82e1b37aac179d7d1 +nv21 4b2a85b79266097177314a6e56fd5fb5 +rgb24 fe5e3505a5019379cd0721d80ad62d05 +rgb444be 7adf5b77e454f20a02d2cc9562a21e9b +rgb444le 3f372c6d95e1299b97ea702adabcea9d +rgb48be d8520683529747778d0bd0e9a9f9e285 +rgb48le c589d81b9787f1144158a0e7f085987e +rgb4_byte 2b3fe2b3e5f98124e93422721dd03751 +rgb555be 6b82965f2334ce7f43289bbe40697ca8 +rgb555le cd883c0c198a3e045e351f4857f9846c +rgb565be bedff6bc255a9ea87f96117fd2348454 +rgb565le 500bcd27d380a51279ba0e4e64f5f1c7 +rgb8 e6121e248cb50b687451a437156924a6 +rgba e2cc3906c90ee87d863cb378bd095e18 +uyvy422 87fa53467c7267175c0336c547d8ce90 +yuv410p a8eb12c5ad15217d81e26c11a477a7c5 +yuv411p a97d81c8a515965209127cfdc718f899 +yuv420p daed3fd5e1980ccc4d4409320f16fbf6 +yuv420p10be f434af8526dcda2988f15a08cdc4bf98 +yuv420p10le 9dcbdb0206713a90fd03b313d99e9ff9 +yuv420p16be b8f1a0e4ef98903e2ef8dbce7bc812e2 +yuv420p16le 3be4223322a9d904caa2ad7d4ccf3c6a +yuv420p9be 34346f74216be11c38cdaeffaba250cc +yuv420p9le 8248d1c10aa86ef8e4b212a2d9fca937 +yuv422p 5a58e1fe687b71e28f52aeb11b999e46 +yuv422p10be adaf99408661a1dc3c667cad992c08d7 +yuv422p10le bc071b965f5a1b3c7349b71bd2b4247c +yuv422p16be 1ec214fba454c456d83de5220c867ede +yuv422p16le 9f9316d40597c9fb917d921bfbcd8421 +yuv422p9be 98e7cefa912845b488f85508a7be7e04 +yuv422p9le 54937395dce9518b2d58aadae21ff69d +yuv440p fade395d957e1e3b117ac11c09404964 +yuv444p a3c2a074c3609226bf1a0bc4de5c0e51 +yuv444p10be b02fac8bc5a564a755567a86dc3ceae0 +yuv444p10le 88860297f729c90526b157b6bf1e2fcf +yuv444p16be 26fbffad3c28aa1a6c47f2be6d146173 +yuv444p16le 3d13dcea82caec9eb563a1d7a2e4b339 +yuv444p9be df39c0778e5b13f306e9928c5b0ddbb2 +yuv444p9le 10fe4d81f58d4630e3a02863bd5071c1 +yuva420p 75d91c2de234468b5c7efd490ce40e0b +yuva420p10be 718e0f49e010934a1f2b33b691855478 +yuva420p10le 1dac68a355050b96ff8716c168f67746 +yuva420p16be 36128486b2c99d0654e8dee63a47bd5e +yuva420p16le 277b44d05a5098952c7c1a4cf2c6ff7a +yuva420p9be 1fa63062315888f0eb8b8777c51a589f +yuva420p9le 073ebffbc7201649f1c439ecf37f33cc +yuva422p 7ce9f599a8aecd744fe24f2759623661 +yuva422p10be 980ea8ddfbfc0d52ed197fa506a2435e +yuva422p10le 9f5c0b3d14679fc92120f556d00e1442 +yuva422p16be 94a4cf6182726a807a0f73b0abbf6e49 +yuva422p16le 5d5d4d216192bfb3e67d19ca61b47ae7 +yuva422p9be 57a62f219df38dc7c8138e3f65c4cf55 +yuva422p9le bdd8b63f2672315441d9a7ad5bc63021 +yuva444p 49c8ed206ed6381c9595e13ae8500296 +yuva444p10be 055adfd383003ec6ed96ae4388feb0ad +yuva444p10le a56fc4d14528637b91699d413b21d87e +yuva444p16be d2387f6d3c28dc0c3eb87b9c8e719241 +yuva444p16le 6c971dc2fe9a3044776c1eb0b40d7eb4 +yuva444p9be 6e397f5bb5de593923b317fbf5c8c390 +yuva444p9le ed156af72e6e18e7b0a27a3aa53df181 +yuvj420p db95116f6735bc0d6aa1f34479f74842 +yuvj422p 8d947806799c24f9d5a96688b20b6c6a +yuvj440p eddaebaa7ab344072364b3507407b9d9 +yuvj444p 779aef4afd317cb44a03ec15011e34f2 +yuyv422 7abd4068b7767b1639f2873c446e09ba +yvyu422 3b0fa1d775623323dbe4eb935fac37d3 diff --git a/tests/ref/fate/filter-scale200 b/tests/ref/fate/filter-scale200 index 17103a2..609a21c 100644 --- a/tests/ref/fate/filter-scale200 +++ b/tests/ref/fate/filter-scale200 @@ -1 +1 @@ -scale200 aebdc1c3e08da2a925ba7212b1fadee0 +scale200 6b5797b13531dbfc4b389f2fd89b24e6 diff --git a/tests/ref/fate/filter-scale500 b/tests/ref/fate/filter-scale500 index 93ba4f2..bd0836c 100644 --- a/tests/ref/fate/filter-scale500 +++ b/tests/ref/fate/filter-scale500 @@ -1 +1 @@ -scale500 ef865c51156e55ce1ce38c8f90a709e6 +scale500 9d01a7cb7461c1d2d4d3531bbd7c9b4c diff --git a/tests/ref/fate/filter-vflip b/tests/ref/fate/filter-vflip index 66b8732..c0bc893 100644 --- a/tests/ref/fate/filter-vflip +++ b/tests/ref/fate/filter-vflip @@ -1 +1 @@ -vflip 2e6d6062e8cad37fb3ab2c433b55f382 +vflip 8f5a94b3d651f24a628ff4465cfea131 diff --git a/tests/ref/fate/filter-vflip_crop b/tests/ref/fate/filter-vflip_crop index 6bb832f..f4e2950 100644 --- a/tests/ref/fate/filter-vflip_crop +++ b/tests/ref/fate/filter-vflip_crop @@ -1 +1 @@ -vflip_crop 72ee0d0dfc8af0cd94a466760313654d +vflip_crop eed36832b2e9a3eea0af6311399c015b diff --git a/tests/ref/fate/filter-vflip_vflip b/tests/ref/fate/filter-vflip_vflip index b719745..5899186 100644 --- a/tests/ref/fate/filter-vflip_vflip +++ b/tests/ref/fate/filter-vflip_vflip @@ -1 +1 @@ -vflip_vflip eba2f135a08829387e2f698ff72a2939 +vflip_vflip 7aaf1057c0edf7d5e9700f9c8e510ea9 diff --git a/tests/ref/fate/g2m2 b/tests/ref/fate/g2m2 new file mode 100644 index 0000000..710dbd1 --- /dev/null +++ b/tests/ref/fate/g2m2 @@ -0,0 +1,161 @@ +#tb 0: 1/1000 +0, 47, 47, 0, 2359296, 0xb4434e4f +0, 62, 62, 0, 2359296, 0x59cb5027 +0, 78, 78, 0, 2359296, 0xe9bc578d +0, 109, 109, 0, 2359296, 0x5d17554f +0, 125, 125, 0, 2359296, 0x6d685457 +0, 437, 437, 0, 2359296, 0x13205420 +0, 438, 438, 0, 2359296, 0xb8e15116 +0, 453, 453, 0, 2359296, 0x2ca55195 +0, 469, 469, 0, 2359296, 0x767d1c45 +0, 484, 484, 0, 2359296, 0x0af42016 +0, 500, 500, 0, 2359296, 0xa2083e69 +0, 516, 516, 0, 2359296, 0xb68a1308 +0, 531, 531, 0, 2359296, 0x4f334c0e +0, 547, 547, 0, 2359296, 0x98b74e4f +0, 562, 562, 0, 2359296, 0xd9de4e4f +0, 578, 578, 0, 2359296, 0xa17c4e4f +0, 594, 594, 0, 2359296, 0xa49a665d +0, 609, 609, 0, 2359296, 0xf5f87360 +0, 781, 781, 0, 2359296, 0x75747360 +0, 797, 797, 0, 2359296, 0x745d7360 +0, 812, 812, 0, 2359296, 0x33047360 +0, 828, 828, 0, 2359296, 0xf19c7360 +0, 844, 844, 0, 2359296, 0xb0437360 +0, 859, 859, 0, 2359296, 0xaf2c7360 +0, 875, 875, 0, 2359296, 0x2ea87360 +0, 891, 891, 0, 2359296, 0xee577360 +0, 953, 953, 0, 2359296, 0x6dd37360 +0, 1078, 1078, 0, 2359296, 0xab327965 +0, 1094, 1094, 0, 2359296, 0x5f8677d0 +0, 1109, 1109, 0, 2359296, 0x02135eb4 +0, 1125, 1125, 0, 2359296, 0x09784e4f +0, 1141, 1141, 0, 2359296, 0xa140a62d +0, 1156, 1156, 0, 2359296, 0xa140a62d +0, 1484, 1484, 0, 2359296, 0xa140a62d +0, 1516, 1516, 0, 2359296, 0xa140a62d +0, 1547, 1547, 0, 2359296, 0xa140a62d +0, 1641, 1641, 0, 2359296, 0xa140a62d +0, 1642, 1642, 0, 2359296, 0xa140a62d +0, 1656, 1656, 0, 2359296, 0xa140a62d +0, 1657, 1657, 0, 2359296, 0xa140a62d +0, 1672, 1672, 0, 2359296, 0xa140a62d +0, 1673, 1673, 0, 2359296, 0x92024e4f +0, 1687, 1687, 0, 2359296, 0xb1754dbe +0, 1688, 1688, 0, 2359296, 0x15ee5eb4 +0, 1703, 1703, 0, 2359296, 0xb1d9746e +0, 1719, 1719, 0, 2359296, 0xabe77360 +0, 1734, 1734, 0, 2359296, 0xaad07360 +0, 1750, 1750, 0, 2359296, 0x2a4c7360 +0, 1766, 1766, 0, 2359296, 0x69777360 +0, 1781, 1781, 0, 2359296, 0xe8e47360 +0, 2328, 2328, 0, 2359296, 0x29357360 +0, 3031, 3031, 0, 2359296, 0x69777360 +0, 3078, 3078, 0, 2359296, 0xa9b97360 +0, 3109, 3109, 0, 2359296, 0xd2697707 +0, 3141, 3141, 0, 2359296, 0x22a07965 +0, 3156, 3156, 0, 2359296, 0xf9327aa7 +0, 3172, 3172, 0, 2359296, 0xa5d277d0 +0, 3203, 3203, 0, 2359296, 0x97b6746e +0, 3328, 3328, 0, 2359296, 0x80bb746e +0, 4562, 4562, 0, 2359296, 0x530b719a +0, 4672, 4672, 0, 2359296, 0x4827665d +0, 4703, 4703, 0, 2359296, 0xc48c5eb4 +0, 5391, 5391, 0, 2359296, 0xe6465eb4 +0, 5578, 5578, 0, 2359296, 0xece455ec +0, 5594, 5594, 0, 2359296, 0xb5344dbe +0, 5609, 5609, 0, 2359296, 0xa140a62d +0, 5625, 5625, 0, 2359296, 0xa140a62d +0, 5641, 5641, 0, 2359296, 0xa140a62d +0, 5642, 5642, 0, 2359296, 0xa140a62d +0, 5656, 5656, 0, 2359296, 0xa140a62d +0, 5672, 5672, 0, 2359296, 0xa140a62d +0, 5703, 5703, 0, 2359296, 0xa140a62d +0, 5750, 5750, 0, 2359296, 0xa140a62d +0, 5766, 5766, 0, 2359296, 0xa140a62d +0, 5781, 5781, 0, 2359296, 0xa140a62d +0, 5797, 5797, 0, 2359296, 0xa140a62d +0, 5812, 5812, 0, 2359296, 0xa140a62d +0, 5875, 5875, 0, 2359296, 0xa140a62d +0, 5922, 5922, 0, 2359296, 0xa140a62d +0, 5984, 5984, 0, 2359296, 0xa140a62d +0, 6031, 6031, 0, 2359296, 0xa140a62d +0, 6047, 6047, 0, 2359296, 0xa140a62d +0, 6062, 6062, 0, 2359296, 0xa140a62d +0, 6406, 6406, 0, 2359296, 0xa140a62d +0, 6453, 6453, 0, 2359296, 0xa140a62d +0, 6469, 6469, 0, 2359296, 0xa140a62d +0, 6484, 6484, 0, 2359296, 0xa140a62d +0, 6500, 6500, 0, 2359296, 0xa140a62d +0, 6516, 6516, 0, 2359296, 0xa140a62d +0, 6531, 6531, 0, 2359296, 0xa140a62d +0, 6547, 6547, 0, 2359296, 0xa140a62d +0, 6562, 6562, 0, 2359296, 0x5c2a4cd9 +0, 6578, 6578, 0, 2359296, 0x28f94e4f +0, 6594, 6594, 0, 2359296, 0x9acb4820 +0, 6609, 6609, 0, 2359296, 0x9ec716e1 +0, 6625, 6625, 0, 2359296, 0xaf5f3fa4 +0, 6641, 6641, 0, 2359296, 0x7d633218 +0, 6642, 6642, 0, 2359296, 0x34fb2016 +0, 6656, 6656, 0, 2359296, 0x61351665 +0, 6812, 6812, 0, 2359296, 0xb23c1039 +0, 6828, 6828, 0, 2359296, 0x59290d69 +0, 6844, 6844, 0, 2359296, 0x639c132d +0, 6859, 6859, 0, 2359296, 0x0b252237 +0, 6875, 6875, 0, 2359296, 0xe66f2fc5 +0, 6891, 6891, 0, 2359296, 0xa8b33761 +0, 6906, 6906, 0, 2359296, 0x81a63f8b +0, 6969, 6969, 0, 2359296, 0x18074843 +0, 6984, 6984, 0, 2359296, 0x434a5195 +0, 7000, 7000, 0, 2359296, 0x6da15116 +0, 7001, 7001, 0, 2359296, 0xca755420 +0, 7016, 7016, 0, 2359296, 0xe6fc5457 +0, 7017, 7017, 0, 2359296, 0x271d53fd +0, 7031, 7031, 0, 2359296, 0xa15b554f +0, 7281, 7281, 0, 2359296, 0x49f6578d +0, 7282, 7282, 0, 2359296, 0x2c0c4e4f +0, 7297, 7297, 0, 2359296, 0x7e924e4f +0, 7298, 7298, 0, 2359296, 0x32ff4e4f +0, 7312, 7312, 0, 2359296, 0x23ad4e4f +0, 7313, 7313, 0, 2359296, 0x7ddc4e4f +0, 7328, 7328, 0, 2359296, 0xd0624e4f +0, 7329, 7329, 0, 2359296, 0x22f74e4f +0, 7781, 7781, 0, 2359296, 0x49fa4e4f +0, 7797, 7797, 0, 2359296, 0x6a5a5027 +0, 7812, 7812, 0, 2359296, 0x9f935027 +0, 7828, 7828, 0, 2359296, 0xc5e55027 +0, 7844, 7844, 0, 2359296, 0xd4cc5027 +0, 8250, 8250, 0, 2359296, 0xd2ab5027 +0, 8266, 8266, 0, 2359296, 0x68f04e4f +0, 8281, 8281, 0, 2359296, 0xd0b44e4f +0, 8297, 8297, 0, 2359296, 0xfced4e4f +0, 8298, 8298, 0, 2359296, 0x8b0d4e4f +0, 8312, 8312, 0, 2359296, 0x09db4e4f +0, 8328, 8328, 0, 2359296, 0x4d0f4e4f +0, 8329, 8329, 0, 2359296, 0xad824dbe +0, 8344, 8344, 0, 2359296, 0x9aca4dbe +0, 8345, 8345, 0, 2359296, 0x755a4dbe +0, 8359, 8359, 0, 2359296, 0xc6824d2d +0, 8360, 8360, 0, 2359296, 0x7c344c0e +0, 8375, 8375, 0, 2359296, 0x50f04c0e +0, 8391, 8391, 0, 2359296, 0xfa594c0e +0, 8406, 8406, 0, 2359296, 0x4d494c0e +0, 8422, 8422, 0, 2359296, 0xf6b24c0e +0, 8437, 8437, 0, 2359296, 0xcb6e4c0e +0, 8453, 8453, 0, 2359296, 0xbd024c0e +0, 8516, 8516, 0, 2359296, 0x245b4dbe +0, 8531, 8531, 0, 2359296, 0x47874e4f +0, 8547, 8547, 0, 2359296, 0xdead4e4f +0, 8562, 8562, 0, 2359296, 0x847e4e4f +0, 9344, 9344, 0, 2359296, 0x1a13e47c +0, 9345, 9345, 0, 2359296, 0x46b3e321 +0, 9876, 9876, 0, 2359296, 0x76c0e35d +0, 9922, 9922, 0, 2359296, 0xf6d9e519 +0, 9938, 9938, 0, 2359296, 0xac0fe4b3 +0, 9954, 9954, 0, 2359296, 0x3a3fe424 +0, 9955, 9955, 0, 2359296, 0xa97ce1a8 +0, 9969, 9969, 0, 2359296, 0x12fae01d +0, 9970, 9970, 0, 2359296, 0x65b4df14 +0, 9985, 9985, 0, 2359296, 0x82d0e032 +0, 9986, 9986, 0, 2359296, 0xa452e0cf +0, 10001, 10001, 0, 2359296, 0x22d6df37 diff --git a/tests/ref/fate/g2m3 b/tests/ref/fate/g2m3 new file mode 100644 index 0000000..5a6ff64 --- /dev/null +++ b/tests/ref/fate/g2m3 @@ -0,0 +1,21 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 3824640, 0x9a253d29 +0, 499, 499, 0, 3824640, 0xcb232b06 +0, 624, 624, 0, 3824640, 0xb03c288c +0, 625, 625, 0, 3824640, 0x260b284e +0, 626, 626, 0, 3824640, 0x6f391ceb +0, 627, 627, 0, 3824640, 0x03252465 +0, 628, 628, 0, 3824640, 0x5a392138 +0, 749, 749, 0, 3824640, 0x53ed2f30 +0, 750, 750, 0, 3824640, 0x00af334d +0, 751, 751, 0, 3824640, 0x2e8b29fb +0, 752, 752, 0, 3824640, 0x700a3870 +0, 753, 753, 0, 3824640, 0x5a873a09 +0, 754, 754, 0, 3824640, 0x9cd62d80 +0, 874, 874, 0, 3824640, 0x35ba3ef7 +0, 875, 875, 0, 3824640, 0x05c24e9a +0, 876, 876, 0, 3824640, 0x47b35e8b +0, 877, 877, 0, 3824640, 0x8d806478 +0, 878, 878, 0, 3824640, 0x16b4643f +0, 879, 879, 0, 3824640, 0x6c556423 +0, 880, 880, 0, 3824640, 0x3c126423 diff --git a/tests/ref/fate/g2m4 b/tests/ref/fate/g2m4 new file mode 100644 index 0000000..c2e8f61 --- /dev/null +++ b/tests/ref/fate/g2m4 @@ -0,0 +1,29 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 3932160, 0x109148ee +0, 29, 29, 0, 3932160, 0xa87b7bff +0, 129, 129, 0, 3932160, 0x00e14d16 +0, 239, 239, 0, 3932160, 0xbf8d7871 +0, 240, 240, 0, 3932160, 0x998ded98 +0, 339, 339, 0, 3932160, 0x9fcfeaaa +0, 439, 439, 0, 3932160, 0xe0d1328f +0, 440, 440, 0, 3932160, 0xde7e69a0 +0, 539, 539, 0, 3932160, 0xdbec5d90 +0, 540, 540, 0, 3932160, 0x5355cde3 +0, 649, 649, 0, 3932160, 0x4b3c6b11 +0, 739, 739, 0, 3932160, 0xcf5692b1 +0, 740, 740, 0, 3932160, 0x19d8366f +0, 949, 949, 0, 3932160, 0xf80f3663 +0, 1439, 1439, 0, 3932160, 0xe2dc1cc7 +0, 3049, 3049, 0, 3932160, 0x3ae51cc7 +0, 3050, 3050, 0, 3932160, 0x10ecd14c +0, 3149, 3149, 0, 3932160, 0xda0f1d1f +0, 3150, 3150, 0, 3932160, 0x50bd3602 +0, 3449, 3449, 0, 3932160, 0xad2083ba +0, 3450, 3450, 0, 3932160, 0xa5b388bd +0, 3549, 3549, 0, 3932160, 0x37ae6d4f +0, 3550, 3550, 0, 3932160, 0x436ee825 +0, 3749, 3749, 0, 3932160, 0x6c2ec178 +0, 3849, 3849, 0, 3932160, 0x6c3f389b +0, 3850, 3850, 0, 3932160, 0x3c0421c1 +0, 3949, 3949, 0, 3932160, 0x861b0449 +0, 4049, 4049, 0, 3932160, 0x41640723 diff --git a/tests/ref/fate/h264-intra-refresh-recovery b/tests/ref/fate/h264-intra-refresh-recovery new file mode 100644 index 0000000..4803900 --- /dev/null +++ b/tests/ref/fate/h264-intra-refresh-recovery @@ -0,0 +1,11 @@ +#tb 0: 1/25 +0, 0, 0, 1, 115200, 0x5825f1b3 +0, 1, 1, 1, 115200, 0xa6e2f328 +0, 2, 2, 1, 115200, 0xcd88e49e +0, 3, 3, 1, 115200, 0x4a17d50b +0, 4, 4, 1, 115200, 0x1283d05b +0, 5, 5, 1, 115200, 0x2747c650 +0, 6, 6, 1, 115200, 0xba23c933 +0, 7, 7, 1, 115200, 0x8a96c54b +0, 8, 8, 1, 115200, 0x748ac6d3 +0, 9, 9, 1, 115200, 0x719ca491 diff --git a/tests/ref/fate/h264-invalid-ref-mod b/tests/ref/fate/h264-invalid-ref-mod new file mode 100644 index 0000000..75bd229 --- /dev/null +++ b/tests/ref/fate/h264-invalid-ref-mod @@ -0,0 +1,11 @@ +#tb 0: 1/24000 +0, 519, 519, 0, 6220800, 0x89daa15e +0, 1520, 1520, 0, 6220800, 0xcf52e254 +0, 2521, 2521, 0, 6220800, 0x91132c13 +0, 3522, 3522, 0, 6220800, 0x37b8be91 +0, 4523, 4523, 0, 6220800, 0x2b09bafa +0, 5524, 5524, 0, 6220800, 0x06d79d8d +0, 6525, 6525, 0, 6220800, 0x8e793c1d +0, 7526, 7526, 0, 6220800, 0xea0fd885 +0, 8527, 8527, 0, 6220800, 0x7786a2ad +0, 9528, 9528, 0, 6220800, 0xed4f9dd9 diff --git a/tests/ref/fate/h264-mixed-nal-coding b/tests/ref/fate/h264-mixed-nal-coding new file mode 100644 index 0000000..6bebce6 --- /dev/null +++ b/tests/ref/fate/h264-mixed-nal-coding @@ -0,0 +1,6 @@ +#tb 0: 1/30000 +0, 0, 0, 0, 518400, 0x8f882e4d +0, 1001, 1001, 0, 518400, 0xc5694144 +0, 2002, 2002, 0, 518400, 0xcf0e9e3a +0, 3003, 3003, 0, 518400, 0xf620e459 +0, 4004, 4004, 0, 518400, 0x4566453e diff --git a/tests/ref/fate/h264-twofields-packet b/tests/ref/fate/h264-twofields-packet new file mode 100644 index 0000000..fc2b9f9 --- /dev/null +++ b/tests/ref/fate/h264-twofields-packet @@ -0,0 +1,31 @@ +#tb 0: 1/90000 +0, 0, 0, 0, 3110400, 0x48e39acd +0, 3003, 3003, 0, 3110400, 0x40d65f69 +0, 6006, 6006, 0, 3110400, 0xdcbc50bf +0, 9009, 9009, 0, 3110400, 0x73a2276a +0, 12012, 12012, 0, 3110400, 0x84a2b3c6 +0, 15015, 15015, 0, 3110400, 0x7cf3b570 +0, 18018, 18018, 0, 3110400, 0xa2d1e03a +0, 21021, 21021, 0, 3110400, 0x03220fb1 +0, 24024, 24024, 0, 3110400, 0x89cd526a +0, 27027, 27027, 0, 3110400, 0xbb4b7531 +0, 30030, 30030, 0, 3110400, 0x0a69f053 +0, 33033, 33033, 0, 3110400, 0x0187994b +0, 36036, 36036, 0, 3110400, 0x26ed49fa +0, 39039, 39039, 0, 3110400, 0xbe8966d4 +0, 42042, 42042, 0, 3110400, 0x248d203c +0, 45045, 45045, 0, 3110400, 0x3139c754 +0, 48048, 48048, 0, 3110400, 0xf22380c4 +0, 51051, 51051, 0, 3110400, 0x3e00dcc1 +0, 54054, 54054, 0, 3110400, 0x8cbe2483 +0, 57057, 57057, 0, 3110400, 0x6951cd63 +0, 60060, 60060, 0, 3110400, 0x36aca4c5 +0, 63063, 63063, 0, 3110400, 0x4d4f6fbe +0, 66066, 66066, 0, 3110400, 0x997247aa +0, 69069, 69069, 0, 3110400, 0x0fd40e06 +0, 72072, 72072, 0, 3110400, 0xa10d2d67 +0, 75075, 75075, 0, 3110400, 0x87c481da +0, 78078, 78078, 0, 3110400, 0xe3dca3cd +0, 81081, 81081, 0, 3110400, 0x5f77b078 +0, 84084, 84084, 0, 3110400, 0xf1ddd098 +0, 87087, 87087, 0, 3110400, 0xedcd1754 diff --git a/tests/ref/fate/h264-unescaped-extradata b/tests/ref/fate/h264-unescaped-extradata new file mode 100644 index 0000000..a131b6c --- /dev/null +++ b/tests/ref/fate/h264-unescaped-extradata @@ -0,0 +1,11 @@ +#tb 0: 1/44100 +0, 0, 0, 0, 84480, 0x0699eb38 +0, 1764, 1764, 0, 84480, 0xce902c32 +0, 3528, 3528, 0, 84480, 0xb6d125f7 +0, 5292, 5292, 0, 84480, 0x2555e93b +0, 7056, 7056, 0, 84480, 0xaea5c08c +0, 8820, 8820, 0, 84480, 0x848eb3da +0, 10584, 10584, 0, 84480, 0x6cfabe90 +0, 12348, 12348, 0, 84480, 0xed16cc5e +0, 14112, 14112, 0, 84480, 0xda8df8f8 +0, 15876, 15876, 0, 84480, 0x83fa054b diff --git a/tests/ref/fate/hap-chunk b/tests/ref/fate/hap-chunk new file mode 100644 index 0000000..4f09d43 --- /dev/null +++ b/tests/ref/fate/hap-chunk @@ -0,0 +1,2 @@ +#tb 0: 1/15360 +0, 0, 0, 0, 16384, 0x096d409e diff --git a/tests/ref/fate/hap1 b/tests/ref/fate/hap1 new file mode 100644 index 0000000..0cabf8b --- /dev/null +++ b/tests/ref/fate/hap1 @@ -0,0 +1,2 @@ +#tb 0: 1/2997 +0, 0, 0, 0, 1228800, 0x0fa946bc diff --git a/tests/ref/fate/hap5 b/tests/ref/fate/hap5 new file mode 100644 index 0000000..a582c39 --- /dev/null +++ b/tests/ref/fate/hap5 @@ -0,0 +1,2 @@ +#tb 0: 1/3000 +0, 0, 0, 0, 1228800, 0xb71ecf93 diff --git a/tests/ref/fate/hapy b/tests/ref/fate/hapy new file mode 100644 index 0000000..e6dd4f5 --- /dev/null +++ b/tests/ref/fate/hapy @@ -0,0 +1,2 @@ +#tb 0: 1/2997 +0, 0, 0, 0, 1228800, 0x5993522d diff --git a/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 b/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 new file mode 100644 index 0000000..16a6a3c --- /dev/null +++ b/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 @@ -0,0 +1,267 @@ +#tb 0: 1/25 +0, 0, 0, 1, 13368960, 0x830b3a1d +0, 1, 1, 1, 13368960, 0x120ca009 +0, 2, 2, 1, 13368960, 0xc94e0d86 +0, 3, 3, 1, 13368960, 0x3e97d237 +0, 4, 4, 1, 13368960, 0x1caaa873 +0, 5, 5, 1, 13368960, 0xc6af86c6 +0, 6, 6, 1, 13368960, 0x277ee61a +0, 7, 7, 1, 13368960, 0x7832ef4e +0, 8, 8, 1, 13368960, 0x328142e9 +0, 9, 9, 1, 13368960, 0xbe22f686 +0, 10, 10, 1, 13368960, 0xfdf78a41 +0, 11, 11, 1, 13368960, 0x8ea3a29e +0, 12, 12, 1, 13368960, 0x10fc932f +0, 13, 13, 1, 13368960, 0xaea485ff +0, 14, 14, 1, 13368960, 0xd545d3c9 +0, 15, 15, 1, 13368960, 0x285d23be +0, 16, 16, 1, 13368960, 0x21453f6a +0, 17, 17, 1, 13368960, 0xc997240e +0, 18, 18, 1, 13368960, 0xe4a6a4c9 +0, 19, 19, 1, 13368960, 0x645a04f4 +0, 20, 20, 1, 13368960, 0xf0868e8d +0, 21, 21, 1, 13368960, 0x53e93a3c +0, 22, 22, 1, 13368960, 0x9d0bf5c0 +0, 23, 23, 1, 13368960, 0xcff5f416 +0, 24, 24, 1, 13368960, 0xd30bf22e +0, 25, 25, 1, 13368960, 0x9db94f89 +0, 26, 26, 1, 13368960, 0x32549fde +0, 27, 27, 1, 13368960, 0xf842679a +0, 28, 28, 1, 13368960, 0x057b893b +0, 29, 29, 1, 13368960, 0x10308d96 +0, 30, 30, 1, 13368960, 0x2b92ad92 +0, 31, 31, 1, 13368960, 0xfaef4689 +0, 32, 32, 1, 13368960, 0x0d49ccb3 +0, 33, 33, 1, 13368960, 0x927f9fbf +0, 34, 34, 1, 13368960, 0x424001ca +0, 35, 35, 1, 13368960, 0x08651f52 +0, 36, 36, 1, 13368960, 0x95a60717 +0, 37, 37, 1, 13368960, 0x9571a4fc +0, 38, 38, 1, 13368960, 0x958b479a +0, 39, 39, 1, 13368960, 0xa93d2034 +0, 40, 40, 1, 13368960, 0x63568237 +0, 41, 41, 1, 13368960, 0x101fcc08 +0, 42, 42, 1, 13368960, 0xb4cd30ae +0, 43, 43, 1, 13368960, 0x6b16a36e +0, 44, 44, 1, 13368960, 0x16f462ba +0, 45, 45, 1, 13368960, 0xfc6f6a4d +0, 46, 46, 1, 13368960, 0x5801d227 +0, 47, 47, 1, 13368960, 0x4af661ba +0, 48, 48, 1, 13368960, 0xb3f78825 +0, 49, 49, 1, 13368960, 0xccc5e616 +0, 50, 50, 1, 13368960, 0xf574dd62 +0, 51, 51, 1, 13368960, 0x5f82af98 +0, 52, 52, 1, 13368960, 0xe63f2bcf +0, 53, 53, 1, 13368960, 0x407d7ee1 +0, 54, 54, 1, 13368960, 0xbdb7eeba +0, 55, 55, 1, 13368960, 0x37c001c5 +0, 56, 56, 1, 13368960, 0x619414d1 +0, 57, 57, 1, 13368960, 0x82f8cf67 +0, 58, 58, 1, 13368960, 0x464ac4f3 +0, 59, 59, 1, 13368960, 0x78f9991a +0, 60, 60, 1, 13368960, 0xeeddba5b +0, 61, 61, 1, 13368960, 0x9426f039 +0, 62, 62, 1, 13368960, 0x2b418600 +0, 63, 63, 1, 13368960, 0xfc41210c +0, 64, 64, 1, 13368960, 0xa191b118 +0, 65, 65, 1, 13368960, 0x9a3dec6a +0, 66, 66, 1, 13368960, 0xd8e8b55a +0, 67, 67, 1, 13368960, 0xb45b815a +0, 68, 68, 1, 13368960, 0x86a91143 +0, 69, 69, 1, 13368960, 0x2b03221b +0, 70, 70, 1, 13368960, 0x78aba843 +0, 71, 71, 1, 13368960, 0x6fe9268b +0, 72, 72, 1, 13368960, 0x4ebe6005 +0, 73, 73, 1, 13368960, 0x5a66f82b +0, 74, 74, 1, 13368960, 0x8a224cc6 +0, 75, 75, 1, 13368960, 0x8a224cc6 +0, 76, 76, 1, 13368960, 0x5a055a2f +0, 77, 77, 1, 13368960, 0x5a055a2f +0, 78, 78, 1, 13368960, 0x984ee1a4 +0, 79, 79, 1, 13368960, 0x0d65da82 +0, 80, 80, 1, 13368960, 0xcd7c4226 +0, 81, 81, 1, 13368960, 0x2896614e +0, 82, 82, 1, 13368960, 0x997ddce1 +0, 83, 83, 1, 13368960, 0x3018e3d9 +0, 84, 84, 1, 13368960, 0xd01cb3bc +0, 85, 85, 1, 13368960, 0x2f643612 +0, 86, 86, 1, 13368960, 0x23c2dfb3 +0, 87, 87, 1, 13368960, 0x23c2dfb3 +0, 88, 88, 1, 13368960, 0x57d69dd3 +0, 89, 89, 1, 13368960, 0xd270a0ab +0, 90, 90, 1, 13368960, 0xa24e5c1e +0, 91, 91, 1, 13368960, 0xc3c047b2 +0, 92, 92, 1, 13368960, 0x5a5b4eaa +0, 93, 93, 1, 13368960, 0xd32c7a91 +0, 94, 94, 1, 13368960, 0x87ee6217 +0, 95, 95, 1, 13368960, 0xbe1e8641 +0, 96, 96, 1, 13368960, 0x88225cf9 +0, 97, 97, 1, 13368960, 0x41c1b776 +0, 98, 98, 1, 13368960, 0xc7cde7f4 +0, 99, 99, 1, 13368960, 0x31b8ac12 +0, 100, 100, 1, 13368960, 0x6c12322d +0, 101, 101, 1, 13368960, 0xa3d4a8e4 +0, 102, 102, 1, 13368960, 0x6d62ade8 +0, 103, 103, 1, 13368960, 0x6d62ade8 +0, 104, 104, 1, 13368960, 0x3ede9b6f +0, 105, 105, 1, 13368960, 0x56924e2b +0, 106, 106, 1, 13368960, 0x8c25ee45 +0, 107, 107, 1, 13368960, 0xfc2e5e96 +0, 108, 108, 1, 13368960, 0x5fd3c9ce +0, 109, 109, 1, 13368960, 0x51e9dd4d +0, 110, 110, 1, 13368960, 0xd7b90558 +0, 111, 111, 1, 13368960, 0xfe185238 +0, 112, 112, 1, 13368960, 0x1be11174 +0, 113, 113, 1, 13368960, 0x16f9a81b +0, 114, 114, 1, 13368960, 0x8533b2be +0, 115, 115, 1, 13368960, 0xd8327426 +0, 116, 116, 1, 13368960, 0x7a6f3d80 +0, 117, 117, 1, 13368960, 0xeb879ea8 +0, 118, 118, 1, 13368960, 0x904da2b8 +0, 119, 119, 1, 13368960, 0xeed21ab9 +0, 120, 120, 1, 13368960, 0x9c5cf568 +0, 121, 121, 1, 13368960, 0x0bbe1a28 +0, 122, 122, 1, 13368960, 0xf2604543 +0, 123, 123, 1, 13368960, 0xf3d43846 +0, 124, 124, 1, 13368960, 0x9f768657 +0, 125, 125, 1, 13368960, 0x74b0d261 +0, 126, 126, 1, 13368960, 0x0f08ec8e +0, 127, 127, 1, 13368960, 0xb77f9cb8 +0, 128, 128, 1, 13368960, 0x696c5bfa +0, 129, 129, 1, 13368960, 0x4e99ddf6 +0, 130, 130, 1, 13368960, 0x229ecd66 +0, 131, 131, 1, 13368960, 0xd2b322d4 +0, 132, 132, 1, 13368960, 0x83d42180 +0, 133, 133, 1, 13368960, 0xb40d2508 +0, 134, 134, 1, 13368960, 0x35e92fa5 +0, 135, 135, 1, 13368960, 0x5aa2bec9 +0, 136, 136, 1, 13368960, 0x92be5044 +0, 137, 137, 1, 13368960, 0x6ae3f3a2 +0, 138, 138, 1, 13368960, 0xc76e7b05 +0, 139, 139, 1, 13368960, 0xc76e7b05 +0, 140, 140, 1, 13368960, 0xf04961fe +0, 141, 141, 1, 13368960, 0x44ce69d1 +0, 142, 142, 1, 13368960, 0xf659fb8f +0, 143, 143, 1, 13368960, 0x365ae456 +0, 144, 144, 1, 13368960, 0xa6dceffc +0, 145, 145, 1, 13368960, 0x2dd12c22 +0, 146, 146, 1, 13368960, 0xb896e3f3 +0, 147, 147, 1, 13368960, 0xd6615b15 +0, 148, 148, 1, 13368960, 0xc375996b +0, 149, 149, 1, 13368960, 0x89a06cbf +0, 150, 150, 1, 13368960, 0x20d54f8b +0, 151, 151, 1, 13368960, 0x955f4329 +0, 152, 152, 1, 13368960, 0x9c7e3906 +0, 153, 153, 1, 13368960, 0x449a63ea +0, 154, 154, 1, 13368960, 0x62431d75 +0, 155, 155, 1, 13368960, 0xac52d9f3 +0, 156, 156, 1, 13368960, 0x57bef208 +0, 157, 157, 1, 13368960, 0x32f604d5 +0, 158, 158, 1, 13368960, 0x55b679c9 +0, 159, 159, 1, 13368960, 0x2003c55d +0, 160, 160, 1, 13368960, 0x0e8d0111 +0, 161, 161, 1, 13368960, 0x4876f64d +0, 162, 162, 1, 13368960, 0x44514a09 +0, 163, 163, 1, 13368960, 0x7ce81efd +0, 164, 164, 1, 13368960, 0x2af740ab +0, 165, 165, 1, 13368960, 0xbc52dca2 +0, 166, 166, 1, 13368960, 0x9ba679e2 +0, 167, 167, 1, 13368960, 0x4e9195e1 +0, 168, 168, 1, 13368960, 0x5078ae80 +0, 169, 169, 1, 13368960, 0xab823be0 +0, 170, 170, 1, 13368960, 0xc45a011e +0, 171, 171, 1, 13368960, 0xb0a0beaf +0, 172, 172, 1, 13368960, 0x0f1169a6 +0, 173, 173, 1, 13368960, 0x56d53564 +0, 174, 174, 1, 13368960, 0x93874837 +0, 175, 175, 1, 13368960, 0x2e4c3acf +0, 176, 176, 1, 13368960, 0xf51f5beb +0, 177, 177, 1, 13368960, 0x5ffffae0 +0, 178, 178, 1, 13368960, 0x3b1a3df9 +0, 179, 179, 1, 13368960, 0xfecd52e1 +0, 180, 180, 1, 13368960, 0xc84ec5c6 +0, 181, 181, 1, 13368960, 0xd033a6b4 +0, 182, 182, 1, 13368960, 0x18230ce6 +0, 183, 183, 1, 13368960, 0xa240d858 +0, 184, 184, 1, 13368960, 0x058d32ec +0, 185, 185, 1, 13368960, 0x46e81bad +0, 186, 186, 1, 13368960, 0x78a89b7d +0, 187, 187, 1, 13368960, 0xf9a0b94e +0, 188, 188, 1, 13368960, 0x34fdd579 +0, 189, 189, 1, 13368960, 0xd58f5aa2 +0, 190, 190, 1, 13368960, 0x4d957a13 +0, 191, 191, 1, 13368960, 0x0b233f2c +0, 192, 192, 1, 13368960, 0xcc5471d5 +0, 193, 193, 1, 13368960, 0xcc5471d5 +0, 194, 194, 1, 13368960, 0xddccf2ea +0, 195, 195, 1, 13368960, 0xddccf2ea +0, 196, 196, 1, 13368960, 0x38290ed9 +0, 197, 197, 1, 13368960, 0x095f6f3a +0, 198, 198, 1, 13368960, 0xe4c70f9f +0, 199, 199, 1, 13368960, 0x695cd27d +0, 200, 200, 1, 13368960, 0x98a15fcb +0, 201, 201, 1, 13368960, 0x22a37600 +0, 202, 202, 1, 13368960, 0xa7bc5ddf +0, 203, 203, 1, 13368960, 0x63778def +0, 204, 204, 1, 13368960, 0xa7bc5ddf +0, 205, 205, 1, 13368960, 0xcce44a22 +0, 206, 206, 1, 13368960, 0xe9e1e769 +0, 207, 207, 1, 13368960, 0x05c652e7 +0, 208, 208, 1, 13368960, 0xc075c9b0 +0, 209, 209, 1, 13368960, 0x6d674c85 +0, 210, 210, 1, 13368960, 0x57938439 +0, 211, 211, 1, 13368960, 0x28296abd +0, 212, 212, 1, 13368960, 0xc29bd537 +0, 213, 213, 1, 13368960, 0xbb01f326 +0, 214, 214, 1, 13368960, 0x68f9366d +0, 215, 215, 1, 13368960, 0x3b8f6d9a +0, 216, 216, 1, 13368960, 0x26db944e +0, 217, 217, 1, 13368960, 0x2f975635 +0, 218, 218, 1, 13368960, 0x4f8d15a2 +0, 219, 219, 1, 13368960, 0x3b773121 +0, 220, 220, 1, 13368960, 0x0e502331 +0, 221, 221, 1, 13368960, 0xffe3a0e9 +0, 222, 222, 1, 13368960, 0x443fa9fb +0, 223, 223, 1, 13368960, 0xdc592fd0 +0, 224, 224, 1, 13368960, 0x88f537a3 +0, 225, 225, 1, 13368960, 0x99216d73 +0, 226, 226, 1, 13368960, 0x4809af2c +0, 227, 227, 1, 13368960, 0x2dd56e6a +0, 228, 228, 1, 13368960, 0x674cc602 +0, 229, 229, 1, 13368960, 0x08685038 +0, 230, 230, 1, 13368960, 0x4b4219f3 +0, 231, 231, 1, 13368960, 0xb850e27c +0, 232, 232, 1, 13368960, 0xe3aca387 +0, 233, 233, 1, 13368960, 0x11c50e02 +0, 234, 234, 1, 13368960, 0xa14f9a7f +0, 235, 235, 1, 13368960, 0x2407abdd +0, 236, 236, 1, 13368960, 0xbe8cc86b +0, 237, 237, 1, 13368960, 0x53f539b4 +0, 238, 238, 1, 13368960, 0x0d4c359c +0, 239, 239, 1, 13368960, 0x3ed14dad +0, 240, 240, 1, 13368960, 0xf4676505 +0, 241, 241, 1, 13368960, 0x6dade6bf +0, 242, 242, 1, 13368960, 0x4390f1fa +0, 243, 243, 1, 13368960, 0xd4ffd518 +0, 244, 244, 1, 13368960, 0x933b9c20 +0, 245, 245, 1, 13368960, 0xe586663a +0, 246, 246, 1, 13368960, 0x4b3f1e0f +0, 247, 247, 1, 13368960, 0xe99668e1 +0, 248, 248, 1, 13368960, 0x4967157b +0, 249, 249, 1, 13368960, 0x443314db +0, 250, 250, 1, 13368960, 0x83023744 +0, 251, 251, 1, 13368960, 0x35e8b4da +0, 252, 252, 1, 13368960, 0xc2eeb60d +0, 253, 253, 1, 13368960, 0x2df97afe +0, 254, 254, 1, 13368960, 0x4f9eeab8 +0, 255, 255, 1, 13368960, 0x5cfa523d +0, 256, 256, 1, 13368960, 0x4badc6b8 +0, 257, 257, 1, 13368960, 0xaa801786 +0, 258, 258, 1, 13368960, 0xca282526 +0, 259, 259, 1, 13368960, 0x3a93f0cc +0, 260, 260, 1, 13368960, 0x290e550c +0, 261, 261, 1, 13368960, 0x29a015d8 +0, 262, 262, 1, 13368960, 0x4e2f73d6 +0, 263, 263, 1, 13368960, 0xfa87495c +0, 264, 264, 1, 13368960, 0xaca638a5 +0, 265, 265, 1, 13368960, 0xef22830f diff --git a/tests/ref/fate/hmac b/tests/ref/fate/hmac index 7d2a437..7964305 100644 --- a/tests/ref/fate/hmac +++ b/tests/ref/fate/hmac @@ -1,6 +1,20 @@ 9294727a3638bb1c13f48ef8158bfc9d 750c783e6ab0b503eaa86e310a5db738 56be34521d144c88dbb8c733f0e8b3f6 -467cb2560355d7fa3ab2d6b939e6e47c -5a6ffd741d3e23b12f78b1baee9e609a -8b4b9d11c9e186c58f2a53b08ddfa436 +6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd +6f630fad67cda0ee1fb1f562db3aa53e +b617318655057264e28bc0b6fb378c8ef146be00 +effcdf6ae5eb2fa2d27416d5f184df9c259a7c79 +125d7342b9ac11cd91a39af48aa17b4f63f175d3 +aa4ae5e15272d00e95705637ce8a3b55ed402112 +e8e99d0f45237d786d6bbaa7965c7808bbff1a91 +896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22 +a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44 +7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea +95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e +3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1 +b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7 +5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843 +773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe +60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54 +9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2 diff --git a/tests/ref/fate/indeo2-delta b/tests/ref/fate/indeo2-delta new file mode 100644 index 0000000..c197dcc --- /dev/null +++ b/tests/ref/fate/indeo2-delta @@ -0,0 +1,115 @@ +#tb 0: 16567/250000 +0, 0, 0, 1, 21600, 0xa3e914dd +0, 1, 1, 1, 21600, 0x367eb420 +0, 2, 2, 1, 21600, 0x527488e2 +0, 3, 3, 1, 21600, 0x5e704dcb +0, 4, 4, 1, 21600, 0xfbfb35d4 +0, 5, 5, 1, 21600, 0xf6e168de +0, 6, 6, 1, 21600, 0x0b589818 +0, 7, 7, 1, 21600, 0xc67b2dbd +0, 8, 8, 1, 21600, 0x002f4994 +0, 9, 9, 1, 21600, 0xe3a476f2 +0, 10, 10, 1, 21600, 0xbc5f0f39 +0, 11, 11, 1, 21600, 0xef095e3a +0, 12, 12, 1, 21600, 0x6bb4f515 +0, 13, 13, 1, 21600, 0x1be1f0fa +0, 14, 14, 1, 21600, 0x0d855464 +0, 15, 15, 1, 21600, 0x6711b47d +0, 16, 16, 1, 21600, 0x14cb2640 +0, 17, 17, 1, 21600, 0x5b794027 +0, 18, 18, 1, 21600, 0xf8cfab3c +0, 19, 19, 1, 21600, 0xe639b0c2 +0, 20, 20, 1, 21600, 0x403b3d7b +0, 21, 21, 1, 21600, 0x364cbb6f +0, 22, 22, 1, 21600, 0xadff6c72 +0, 23, 23, 1, 21600, 0x76c85b52 +0, 24, 24, 1, 21600, 0xbe85ec80 +0, 25, 25, 1, 21600, 0x1e9f9e50 +0, 26, 26, 1, 21600, 0xbd31bd82 +0, 27, 27, 1, 21600, 0x4445a12a +0, 28, 28, 1, 21600, 0x08f25888 +0, 29, 29, 1, 21600, 0x73d45696 +0, 30, 30, 1, 21600, 0xbc681a10 +0, 31, 31, 1, 21600, 0x03f502be +0, 32, 32, 1, 21600, 0x9206a757 +0, 33, 33, 1, 21600, 0x3ed5e1be +0, 34, 34, 1, 21600, 0x76b636a9 +0, 35, 35, 1, 21600, 0x7d40ccb0 +0, 36, 36, 1, 21600, 0xa2955499 +0, 37, 37, 1, 21600, 0xf4b20c86 +0, 38, 38, 1, 21600, 0xe497d681 +0, 39, 39, 1, 21600, 0x831ef973 +0, 40, 40, 1, 21600, 0x43aa78e6 +0, 41, 41, 1, 21600, 0x26e4bdb6 +0, 42, 42, 1, 21600, 0xd04e9feb +0, 43, 43, 1, 21600, 0x08ef4b58 +0, 44, 44, 1, 21600, 0x30b84cc3 +0, 45, 45, 1, 21600, 0x04e1dec0 +0, 46, 46, 1, 21600, 0xed4f24d5 +0, 47, 47, 1, 21600, 0xcc9f8d4c +0, 48, 48, 1, 21600, 0x402ff69a +0, 49, 49, 1, 21600, 0xd77a4e7b +0, 50, 50, 1, 21600, 0xe614de71 +0, 51, 51, 1, 21600, 0x18daccbd +0, 52, 52, 1, 21600, 0x87e896d1 +0, 53, 53, 1, 21600, 0x51d76264 +0, 54, 54, 1, 21600, 0x9b910304 +0, 55, 55, 1, 21600, 0xd3a7aa30 +0, 56, 56, 1, 21600, 0x40e4e926 +0, 57, 57, 1, 21600, 0x9bb5d703 +0, 58, 58, 1, 21600, 0x63fb1ac0 +0, 59, 59, 1, 21600, 0x1b9d851e +0, 60, 60, 1, 21600, 0x36e4c0e6 +0, 61, 61, 1, 21600, 0x1f14b386 +0, 62, 62, 1, 21600, 0x01016e93 +0, 63, 63, 1, 21600, 0x8f192cc7 +0, 64, 64, 1, 21600, 0xa9caaeb0 +0, 65, 65, 1, 21600, 0xe9948a3d +0, 66, 66, 1, 21600, 0xe870fa18 +0, 67, 67, 1, 21600, 0xc083eff5 +0, 68, 68, 1, 21600, 0x2f070225 +0, 69, 69, 1, 21600, 0x89cbd954 +0, 70, 70, 1, 21600, 0x448c4fbb +0, 71, 71, 1, 21600, 0xe1ecfdbe +0, 72, 72, 1, 21600, 0x20b3749b +0, 73, 73, 1, 21600, 0x8ba8a3c6 +0, 74, 74, 1, 21600, 0x90c06421 +0, 75, 75, 1, 21600, 0x0e6bd5fc +0, 76, 76, 1, 21600, 0x194425aa +0, 77, 77, 1, 21600, 0x4038043a +0, 78, 78, 1, 21600, 0x21545ede +0, 79, 79, 1, 21600, 0x2ade8d52 +0, 80, 80, 1, 21600, 0xf504ad7e +0, 81, 81, 1, 21600, 0xc58fcf10 +0, 82, 82, 1, 21600, 0x4b0af230 +0, 83, 83, 1, 21600, 0x3ff76b0b +0, 84, 84, 1, 21600, 0x6d051bee +0, 85, 85, 1, 21600, 0xc5d59208 +0, 86, 86, 1, 21600, 0xed5f81cf +0, 87, 87, 1, 21600, 0x2c9976f9 +0, 88, 88, 1, 21600, 0xdd5b5f55 +0, 89, 89, 1, 21600, 0xcec73bc3 +0, 90, 90, 1, 21600, 0x46033a02 +0, 91, 91, 1, 21600, 0x00c6aade +0, 92, 92, 1, 21600, 0x336049b3 +0, 93, 93, 1, 21600, 0xe1939479 +0, 94, 94, 1, 21600, 0xc77ca7e7 +0, 95, 95, 1, 21600, 0x40153489 +0, 96, 96, 1, 21600, 0x33253501 +0, 97, 97, 1, 21600, 0x10a321c1 +0, 98, 98, 1, 21600, 0x8720db67 +0, 99, 99, 1, 21600, 0x185b772e +0, 100, 100, 1, 21600, 0xf4ce1986 +0, 101, 101, 1, 21600, 0x7234af91 +0, 102, 102, 1, 21600, 0x1cb75367 +0, 103, 103, 1, 21600, 0x7bc29377 +0, 104, 104, 1, 21600, 0xc3c047a1 +0, 105, 105, 1, 21600, 0xe6fb938c +0, 106, 106, 1, 21600, 0x97ca5ab5 +0, 107, 107, 1, 21600, 0x7a9fe9bf +0, 108, 108, 1, 21600, 0x53f892e4 +0, 109, 109, 1, 21600, 0x608a0bf6 +0, 110, 110, 1, 21600, 0x6052b96f +0, 111, 111, 1, 21600, 0x61f689e7 +0, 112, 112, 1, 21600, 0x02a52e81 +0, 113, 113, 1, 21600, 0x43f01ae2 diff --git a/tests/ref/fate/indeo2 b/tests/ref/fate/indeo2-intra similarity index 100% rename from tests/ref/fate/indeo2 rename to tests/ref/fate/indeo2-intra diff --git a/tests/ref/fate/indeo3 b/tests/ref/fate/indeo3-1 similarity index 100% rename from tests/ref/fate/indeo3 rename to tests/ref/fate/indeo3-1 diff --git a/tests/ref/fate/iscc b/tests/ref/fate/iscc new file mode 100644 index 0000000..69dbfe1 --- /dev/null +++ b/tests/ref/fate/iscc @@ -0,0 +1,6 @@ +#tb 0: 1/10 +0, 0, 0, 1, 6814720, 0x1365f8ef +0, 1, 1, 1, 6814720, 0x90838983 +0, 2, 2, 1, 6814720, 0xf0cc3131 +0, 3, 3, 1, 6814720, 0xc07e404d +0, 4, 4, 1, 6814720, 0x945962dd diff --git a/tests/ref/fate/iv8-demux b/tests/ref/fate/iv8-demux index 56a54a1..f13e691 100644 --- a/tests/ref/fate/iv8-demux +++ b/tests/ref/fate/iv8-demux @@ -19,8 +19,8 @@ 0, 57600, 61200, 0, 20874, 0xed0b91ec 0, 61200, 64799, 0, 20877, 0xe1623e01 0, 64799, 68399, 0, 20933, 0x19906564 -0, 68399, 72000, 3600, 20891, 0x3d064fd3 -0, 72000, 75600, 3600, 20834, 0xcb774dbc -0, 75600, 79200, 3600, 20870, 0xbc536589 -0, 79200, 82800, 3600, 21421, 0xc99a68e4 -0, 82800, 86400, 3600, 12869, 0x5684e304 +0, 68399, 72000, 0, 20891, 0x3d064fd3 +0, 72000, 75600, 0, 20834, 0xcb774dbc +0, 75600, 79200, 0, 20870, 0xbc536589 +0, 79200, 82800, 0, 21421, 0xc99a68e4 +0, 82800, 86400, 0, 12869, 0x5684e304 diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux index 0546135..95e8be5 100644 --- a/tests/ref/fate/lmlm4-demux +++ b/tests/ref/fate/lmlm4-demux @@ -1,217 +1,217 @@ #tb 0: 1001/30000 #tb 1: 1/90000 -0, 0, -9223372036854775808, 1, 5951, 0xe9118e0d +0, 0, 0, 1, 5951, 0xe9118e0d 1, 0, 0, 2160, 768, 0xaebcbebb 1, 2160, 2160, 2160, 768, 0xaebcbebb -0, 1, -9223372036854775808, 1, 1672, 0x4b80d4ca +0, 1, 1, 1, 1672, 0x4b80d4ca 1, 4320, 4320, 2160, 768, 0xaebcbebb -0, 2, -9223372036854775808, 1, 1604, 0x99e1b0a7 +0, 2, 2, 1, 1604, 0x99e1b0a7 1, 6480, 6480, 2160, 768, 0x866fe37a 1, 8640, 8640, 2160, 768, 0x05d76890 -0, 3, -9223372036854775808, 1, 1204, 0x9559038a +0, 3, 3, 1, 1204, 0x9559038a 1, 10800, 10800, 2160, 768, 0x858f5511 -0, 4, -9223372036854775808, 1, 1482, 0x60056564 +0, 4, 4, 1, 1482, 0x60056564 1, 12960, 12960, 2160, 768, 0x97cb65ef -0, 5, -9223372036854775808, 1, 1105, 0xf508cef4 +0, 5, 5, 1, 1105, 0xf508cef4 1, 15120, 15120, 2160, 768, 0xe269742c 1, 17280, 17280, 2160, 768, 0xa6015f8d -0, 6, -9223372036854775808, 1, 1193, 0xc8e0fd36 +0, 6, 6, 1, 1193, 0xc8e0fd36 1, 19440, 19440, 2160, 768, 0x759163e0 -0, 7, -9223372036854775808, 1, 1247, 0x8dd202e5 +0, 7, 7, 1, 1247, 0x8dd202e5 1, 21600, 21600, 2160, 768, 0xb1e16082 1, 23760, 23760, 2160, 768, 0x1b616429 -0, 8, -9223372036854775808, 1, 1367, 0xf59435e5 +0, 8, 8, 1, 1367, 0xf59435e5 1, 25920, 25920, 2160, 768, 0x7e4364f7 -0, 9, -9223372036854775808, 1, 1406, 0x68ba4a7e +0, 9, 9, 1, 1406, 0x68ba4a7e 1, 28080, 28080, 2160, 768, 0x59bd64f7 -0, 10, -9223372036854775808, 1, 1262, 0x82c04123 +0, 10, 10, 1, 1262, 0x82c04123 1, 30240, 30240, 2160, 768, 0xc3116fc6 1, 32400, 32400, 2160, 768, 0x6a1c6b56 -0, 11, -9223372036854775808, 1, 1381, 0x02335cf9 +0, 11, 11, 1, 1381, 0x02335cf9 1, 34560, 34560, 2160, 768, 0x285a64cf -0, 12, -9223372036854775808, 1, 1450, 0x7be46fd1 +0, 12, 12, 1, 1450, 0x7be46fd1 1, 36720, 36720, 2160, 768, 0x79b16d65 1, 38880, 38880, 2160, 768, 0x09b47635 -0, 13, -9223372036854775808, 1, 1362, 0x75cc381a +0, 13, 13, 1, 1362, 0x75cc381a 1, 41040, 41040, 2160, 768, 0x81597446 -0, 14, -9223372036854775808, 1, 1409, 0x9ed74f3f +0, 14, 14, 1, 1409, 0x9ed74f3f 1, 43200, 43200, 2160, 768, 0xfeb66eee -0, 15, -9223372036854775808, 1, 1253, 0x82400ae1 +0, 15, 15, 1, 1253, 0x82400ae1 1, 45360, 45360, 2160, 768, 0x78557618 1, 47520, 47520, 2160, 768, 0x3af170bf -0, 16, -9223372036854775808, 1, 5499, 0xed286805 +0, 16, 16, 1, 5499, 0xed286805 1, 49680, 49680, 2160, 768, 0xefbd6399 -0, 17, -9223372036854775808, 1, 1403, 0x483c4cbc +0, 17, 17, 1, 1403, 0x483c4cbc 1, 51840, 51840, 2160, 768, 0xc98e7492 1, 54000, 54000, 2160, 768, 0x010d7149 -0, 18, -9223372036854775808, 1, 1632, 0xa9ebcd6c +0, 18, 18, 1, 1632, 0xa9ebcd6c 1, 56160, 56160, 2160, 768, 0xce838b07 -0, 19, -9223372036854775808, 1, 1207, 0xc8580724 +0, 19, 19, 1, 1207, 0xc8580724 1, 58320, 58320, 2160, 768, 0xed18726c -0, 20, -9223372036854775808, 1, 1289, 0x61fb2fd2 +0, 20, 20, 1, 1289, 0x61fb2fd2 1, 60480, 60480, 2160, 768, 0x017e6712 1, 62640, 62640, 2160, 768, 0x7f9268e9 -0, 21, -9223372036854775808, 1, 1230, 0xf348f53c +0, 21, 21, 1, 1230, 0xf348f53c 1, 64800, 64800, 2160, 768, 0xf6f258fc -0, 22, -9223372036854775808, 1, 1579, 0xa260b1ac +0, 22, 22, 1, 1579, 0xa260b1ac 1, 66960, 66960, 2160, 768, 0x9a1a6f31 -0, 23, -9223372036854775808, 1, 949, 0x91849002 +0, 23, 23, 1, 949, 0x91849002 1, 69120, 69120, 2160, 768, 0x14b47b23 1, 71280, 71280, 2160, 768, 0x9bdc6a50 -0, 24, -9223372036854775808, 1, 786, 0x3e33576f +0, 24, 24, 1, 786, 0x3e33576f 1, 73440, 73440, 2160, 768, 0x0fc46dab -0, 25, -9223372036854775808, 1, 894, 0x9ac36a61 +0, 25, 25, 1, 894, 0x9ac36a61 1, 75600, 75600, 2160, 768, 0x6c387372 1, 77760, 77760, 2160, 768, 0x581e71cd -0, 26, -9223372036854775808, 1, 1186, 0x6bfc116e +0, 26, 26, 1, 1186, 0x6bfc116e 1, 79920, 79920, 2160, 768, 0x00cb785f -0, 27, -9223372036854775808, 1, 1187, 0xcfc512ae +0, 27, 27, 1, 1187, 0xcfc512ae 1, 82080, 82080, 2160, 768, 0x1dda7032 -0, 28, -9223372036854775808, 1, 1527, 0x5c2c965a +0, 28, 28, 1, 1527, 0x5c2c965a 1, 84240, 84240, 2160, 768, 0xf57c7103 1, 86400, 86400, 2160, 768, 0x2d927183 -0, 29, -9223372036854775808, 1, 1536, 0x5ba7ac29 +0, 29, 29, 1, 1536, 0x5ba7ac29 1, 88560, 88560, 2160, 768, 0xdae86cdf -0, 30, -9223372036854775808, 1, 1095, 0xce06eb96 +0, 30, 30, 1, 1095, 0xce06eb96 1, 90720, 90720, 2160, 768, 0x2a2f6c3c 1, 92880, 92880, 2160, 768, 0x44696eba -0, 31, -9223372036854775808, 1, 1402, 0x642f6b0d +0, 31, 31, 1, 1402, 0x642f6b0d 1, 95040, 95040, 2160, 768, 0xf67c71c4 -0, 32, -9223372036854775808, 1, 5551, 0xf01a9c08 +0, 32, 32, 1, 5551, 0xf01a9c08 1, 97200, 97200, 2160, 768, 0xc1ce7237 -0, 33, -9223372036854775808, 1, 1211, 0x350206f7 +0, 33, 33, 1, 1211, 0x350206f7 1, 99360, 99360, 2160, 768, 0xd9c36ef5 1, 101520, 101520, 2160, 768, 0x63b06b03 -0, 34, -9223372036854775808, 1, 887, 0x08767619 +0, 34, 34, 1, 887, 0x08767619 1, 103680, 103680, 2160, 768, 0x8de97ebe -0, 35, -9223372036854775808, 1, 1042, 0xcc81a9ed +0, 35, 35, 1, 1042, 0xcc81a9ed 1, 105840, 105840, 2160, 768, 0xbf117c32 1, 108000, 108000, 2160, 768, 0x82897497 -0, 36, -9223372036854775808, 1, 1247, 0x6f320614 +0, 36, 36, 1, 1247, 0x6f320614 1, 110160, 110160, 2160, 768, 0x7a347abb -0, 37, -9223372036854775808, 1, 1459, 0xd28975b5 +0, 37, 37, 1, 1459, 0xd28975b5 1, 112320, 112320, 2160, 768, 0xc99b691e -0, 38, -9223372036854775808, 1, 1116, 0x1ab1e9db +0, 38, 38, 1, 1116, 0x1ab1e9db 1, 114480, 114480, 2160, 768, 0xf4fc6e74 1, 116640, 116640, 2160, 768, 0x511d6ec4 -0, 39, -9223372036854775808, 1, 1110, 0x6411f66a +0, 39, 39, 1, 1110, 0x6411f66a 1, 118800, 118800, 2160, 768, 0xb8c06b5f -0, 40, -9223372036854775808, 1, 1282, 0xd468375d +0, 40, 40, 1, 1282, 0xd468375d 1, 120960, 120960, 2160, 768, 0xf1776aed 1, 123120, 123120, 2160, 768, 0xe6fe7fb4 -0, 41, -9223372036854775808, 1, 1077, 0x1273c6e3 +0, 41, 41, 1, 1077, 0x1273c6e3 1, 125280, 125280, 2160, 768, 0x36907aff -0, 42, -9223372036854775808, 1, 1043, 0x12dbd3ae +0, 42, 42, 1, 1043, 0x12dbd3ae 1, 127440, 127440, 2160, 768, 0xddf666bb -0, 43, -9223372036854775808, 1, 1087, 0x3e70d37a +0, 43, 43, 1, 1087, 0x3e70d37a 1, 129600, 129600, 2160, 768, 0x8e896ebc 1, 131760, 131760, 2160, 768, 0x0aa47dfa -0, 44, -9223372036854775808, 1, 992, 0x0651a71c +0, 44, 44, 1, 992, 0x0651a71c 1, 133920, 133920, 2160, 768, 0xc1736811 -0, 45, -9223372036854775808, 1, 1012, 0x6a069f8c +0, 45, 45, 1, 1012, 0x6a069f8c 1, 136080, 136080, 2160, 768, 0xb3e87009 -0, 46, -9223372036854775808, 1, 1320, 0x92803d69 +0, 46, 46, 1, 1320, 0x92803d69 1, 138240, 138240, 2160, 768, 0xf23e6c00 1, 140400, 140400, 2160, 768, 0x993a71d2 -0, 47, -9223372036854775808, 1, 1080, 0xe0ffbe95 +0, 47, 47, 1, 1080, 0xe0ffbe95 1, 142560, 142560, 2160, 768, 0xa53466dd -0, 48, -9223372036854775808, 1, 5639, 0x658ca26b +0, 48, 48, 1, 5639, 0x658ca26b 1, 144720, 144720, 2160, 768, 0xb43a74b0 1, 146880, 146880, 2160, 768, 0x348f615c -0, 49, -9223372036854775808, 1, 1385, 0xbcb96241 +0, 49, 49, 1, 1385, 0xbcb96241 1, 149040, 149040, 2160, 768, 0x298f6e1b -0, 50, -9223372036854775808, 1, 1142, 0x8c6df318 +0, 50, 50, 1, 1142, 0x8c6df318 1, 151200, 151200, 2160, 768, 0x5db469c8 -0, 51, -9223372036854775808, 1, 1175, 0xcac1faef +0, 51, 51, 1, 1175, 0xcac1faef 1, 153360, 153360, 2160, 768, 0x08f16c2c 1, 155520, 155520, 2160, 768, 0x4a0474cb -0, 52, -9223372036854775808, 1, 1091, 0xa937e32a +0, 52, 52, 1, 1091, 0xa937e32a 1, 157680, 157680, 2160, 768, 0x077c760b -0, 53, -9223372036854775808, 1, 1174, 0xfa50040d +0, 53, 53, 1, 1174, 0xfa50040d 1, 159840, 159840, 2160, 768, 0xa5777c2e 1, 162000, 162000, 2160, 768, 0x0d157ea6 -0, 54, -9223372036854775808, 1, 1293, 0x0c8d2740 +0, 54, 54, 1, 1293, 0x0c8d2740 1, 164160, 164160, 2160, 768, 0x9bc26f86 -0, 55, -9223372036854775808, 1, 1262, 0x502c0c35 +0, 55, 55, 1, 1262, 0x502c0c35 1, 166320, 166320, 2160, 768, 0x1a72742d -0, 56, -9223372036854775808, 1, 1038, 0x5e98c0cd +0, 56, 56, 1, 1038, 0x5e98c0cd 1, 168480, 168480, 2160, 768, 0xa5bb6bbb 1, 170640, 170640, 2160, 768, 0x48496c4c -0, 57, -9223372036854775808, 1, 1362, 0x256e43cf +0, 57, 57, 1, 1362, 0x256e43cf 1, 172800, 172800, 2160, 768, 0x800d78f0 -0, 58, -9223372036854775808, 1, 1200, 0x29e6f055 +0, 58, 58, 1, 1200, 0x29e6f055 1, 174960, 174960, 2160, 768, 0x40db840c 1, 177120, 177120, 2160, 768, 0xadc96a6b -0, 59, -9223372036854775808, 1, 1495, 0x88e9b973 +0, 59, 59, 1, 1495, 0x88e9b973 1, 179280, 179280, 2160, 768, 0xff986b03 -0, 60, -9223372036854775808, 1, 1386, 0x849297d2 +0, 60, 60, 1, 1386, 0x849297d2 1, 181440, 181440, 2160, 768, 0x152473d6 -0, 61, -9223372036854775808, 1, 1572, 0x63b7dc79 +0, 61, 61, 1, 1572, 0x63b7dc79 1, 183600, 183600, 2160, 768, 0x01567323 1, 185760, 185760, 2160, 768, 0xe5f26fe5 -0, 62, -9223372036854775808, 1, 1190, 0x32ccf4cb +0, 62, 62, 1, 1190, 0x32ccf4cb 1, 187920, 187920, 2160, 768, 0xa8fd72cd -0, 63, -9223372036854775808, 1, 1395, 0xa6ec4ae9 +0, 63, 63, 1, 1395, 0xa6ec4ae9 1, 190080, 190080, 2160, 768, 0x8857655b -0, 64, -9223372036854775808, 1, 5692, 0x81aed6f3 +0, 64, 64, 1, 5692, 0x81aed6f3 1, 192240, 192240, 2160, 768, 0x84017b13 1, 194400, 194400, 2160, 768, 0xe6a968b3 -0, 65, -9223372036854775808, 1, 1335, 0xe98a5497 +0, 65, 65, 1, 1335, 0xe98a5497 1, 196560, 196560, 2160, 768, 0xb03a7566 -0, 66, -9223372036854775808, 1, 1361, 0x8ae15ab5 +0, 66, 66, 1, 1361, 0x8ae15ab5 1, 198720, 198720, 2160, 768, 0x8bea5f62 1, 200880, 200880, 2160, 768, 0xac7570b0 -0, 67, -9223372036854775808, 1, 1525, 0xed2bc1e8 +0, 67, 67, 1, 1525, 0xed2bc1e8 1, 203040, 203040, 2160, 768, 0x11306fac -0, 68, -9223372036854775808, 1, 1570, 0xba70d74b +0, 68, 68, 1, 1570, 0xba70d74b 1, 205200, 205200, 2160, 768, 0xf2af5b28 -0, 69, -9223372036854775808, 1, 1349, 0xd97a687d +0, 69, 69, 1, 1349, 0xd97a687d 1, 207360, 207360, 2160, 768, 0x3069681f 1, 209520, 209520, 2160, 768, 0x7ff07033 -0, 70, -9223372036854775808, 1, 1270, 0xca8c3ca8 +0, 70, 70, 1, 1270, 0xca8c3ca8 1, 211680, 211680, 2160, 768, 0xd74973f2 -0, 71, -9223372036854775808, 1, 1016, 0x32d0c81a +0, 71, 71, 1, 1016, 0x32d0c81a 1, 213840, 213840, 2160, 768, 0xb3627304 1, 216000, 216000, 2160, 768, 0x11ff7589 -0, 72, -9223372036854775808, 1, 983, 0x536faa97 +0, 72, 72, 1, 983, 0x536faa97 1, 218160, 218160, 2160, 768, 0x4a156c63 -0, 73, -9223372036854775808, 1, 1111, 0x44ade015 +0, 73, 73, 1, 1111, 0x44ade015 1, 220320, 220320, 2160, 768, 0xcb036127 -0, 74, -9223372036854775808, 1, 1314, 0xce7c477d +0, 74, 74, 1, 1314, 0xce7c477d 1, 222480, 222480, 2160, 768, 0x0b796bb9 1, 224640, 224640, 2160, 768, 0x1d516c35 -0, 75, -9223372036854775808, 1, 1005, 0x0196b491 +0, 75, 75, 1, 1005, 0x0196b491 1, 226800, 226800, 2160, 768, 0xa9146da1 -0, 76, -9223372036854775808, 1, 1162, 0xb8f6ebe6 +0, 76, 76, 1, 1162, 0xb8f6ebe6 1, 228960, 228960, 2160, 768, 0x6d176392 1, 231120, 231120, 2160, 768, 0x6f966269 -0, 77, -9223372036854775808, 1, 1440, 0xfca67c72 +0, 77, 77, 1, 1440, 0xfca67c72 1, 233280, 233280, 2160, 768, 0x7ee17724 -0, 78, -9223372036854775808, 1, 1437, 0x491181b1 +0, 78, 78, 1, 1437, 0x491181b1 1, 235440, 235440, 2160, 768, 0x3f07614a -0, 79, -9223372036854775808, 1, 1261, 0xf0cd1898 +0, 79, 79, 1, 1261, 0xf0cd1898 1, 237600, 237600, 2160, 768, 0x49d56945 1, 239760, 239760, 2160, 768, 0x68eb660a -0, 80, -9223372036854775808, 1, 5638, 0x3a25a9f2 +0, 80, 80, 1, 5638, 0x3a25a9f2 1, 241920, 241920, 2160, 768, 0xe7c96677 -0, 81, -9223372036854775808, 1, 1091, 0x67d9c693 +0, 81, 81, 1, 1091, 0x67d9c693 1, 244080, 244080, 2160, 768, 0x7dc07a35 1, 246240, 246240, 2160, 768, 0x1e9c6397 -0, 82, -9223372036854775808, 1, 875, 0x52147bb1 +0, 82, 82, 1, 875, 0x52147bb1 1, 248400, 248400, 2160, 768, 0x93ef5de4 -0, 83, -9223372036854775808, 1, 1188, 0x8522000f +0, 83, 83, 1, 1188, 0x8522000f 1, 250560, 250560, 2160, 768, 0x34af6803 -0, 84, -9223372036854775808, 1, 1360, 0x89b82e7b +0, 84, 84, 1, 1360, 0x89b82e7b 1, 252720, 252720, 2160, 768, 0x77e068be 1, 254880, 254880, 2160, 768, 0x65e274de -0, 85, -9223372036854775808, 1, 1378, 0xe8644914 +0, 85, 85, 1, 1378, 0xe8644914 1, 257040, 257040, 2160, 768, 0xb7ad6a8a -0, 86, -9223372036854775808, 1, 1194, 0x89fef83d +0, 86, 86, 1, 1194, 0x89fef83d 1, 259200, 259200, 2160, 768, 0x84b3635f -0, 87, -9223372036854775808, 1, 1422, 0x99daa18b +0, 87, 87, 1, 1422, 0x99daa18b 1, 261360, 261360, 2160, 768, 0x066b78f2 1, 263520, 263520, 2160, 768, 0xda137428 -0, 88, -9223372036854775808, 1, 1049, 0x72a9cec1 +0, 88, 88, 1, 1049, 0x72a9cec1 1, 265680, 265680, 2160, 768, 0xfd6c7597 -0, 89, -9223372036854775808, 1, 1327, 0x7d15307c +0, 89, 89, 1, 1327, 0x7d15307c 1, 267840, 267840, 2160, 768, 0x8d766d40 diff --git a/tests/ref/fate/lossless-truehd-5.1 b/tests/ref/fate/lossless-truehd-5.1 new file mode 100644 index 0000000..373b917 --- /dev/null +++ b/tests/ref/fate/lossless-truehd-5.1 @@ -0,0 +1 @@ +95d8aac39dd9f0d7fb83dc7b6f88df35 diff --git a/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 b/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 new file mode 100644 index 0000000..f4afbc1 --- /dev/null +++ b/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 @@ -0,0 +1 @@ +a269aee0051d4400c9117136f08c9767 diff --git a/tests/ref/fate/lossless-wma b/tests/ref/fate/lossless-wma index 5bea19b..c4c8a37 100644 --- a/tests/ref/fate/lossless-wma +++ b/tests/ref/fate/lossless-wma @@ -1 +1 @@ -35dc840f91cbcece02178d03c8f2fe26 +ab45f262b22030e908cb03f2cc8e89b5 diff --git a/tests/ref/fate/magicyuv-rgb b/tests/ref/fate/magicyuv-rgb new file mode 100644 index 0000000..a52574a --- /dev/null +++ b/tests/ref/fate/magicyuv-rgb @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 144768, 0x497c8ce1 diff --git a/tests/ref/fate/magicyuv-rgba b/tests/ref/fate/magicyuv-rgba new file mode 100644 index 0000000..6cad8e0 --- /dev/null +++ b/tests/ref/fate/magicyuv-rgba @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 193024, 0x7e1b7233 diff --git a/tests/ref/fate/magicyuv-y400i b/tests/ref/fate/magicyuv-y400i new file mode 100644 index 0000000..4c8fe7e --- /dev/null +++ b/tests/ref/fate/magicyuv-y400i @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 48256, 0x368b93f2 diff --git a/tests/ref/fate/magicyuv-y420 b/tests/ref/fate/magicyuv-y420 new file mode 100644 index 0000000..3145e8a --- /dev/null +++ b/tests/ref/fate/magicyuv-y420 @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 72384, 0x59a87842 diff --git a/tests/ref/fate/magicyuv-y422i b/tests/ref/fate/magicyuv-y422i new file mode 100644 index 0000000..2a7af47 --- /dev/null +++ b/tests/ref/fate/magicyuv-y422i @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 96512, 0xe84751be diff --git a/tests/ref/fate/magicyuv-y444 b/tests/ref/fate/magicyuv-y444 new file mode 100644 index 0000000..ee836c2 --- /dev/null +++ b/tests/ref/fate/magicyuv-y444 @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 144768, 0xef48043f diff --git a/tests/ref/fate/magicyuv-y4444i b/tests/ref/fate/magicyuv-y4444i new file mode 100644 index 0000000..bc3c702 --- /dev/null +++ b/tests/ref/fate/magicyuv-y4444i @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 193024, 0x5292ecec diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc new file mode 100644 index 0000000..a0a1700 --- /dev/null +++ b/tests/ref/fate/movenc @@ -0,0 +1,135 @@ +write_data len 36, time nopts, type header atom ftyp +write_data len 1807, time nopts, type header atom - +write_data len 496, time 1000000, type sync atom moof +write_data len 110, time nopts, type trailer atom - +07cee26b35b140ae50268c3083e2d880 2449 non-empty-moov +write_data len 36, time nopts, type header atom ftyp +write_data len 2135, time nopts, type header atom - +write_data len 616, time 966667, type sync atom moof +write_data len 110, time nopts, type trailer atom - +c3c47c2c9566cb410e0832c37f4f8527 2897 non-empty-moov-elst +write_data len 36, time nopts, type header atom ftyp +write_data len 2055, time nopts, type header atom - +write_data len 616, time 1000000, type sync atom moof +write_data len 110, time nopts, type trailer atom - +abc910edf1fc2a205658353dfdfc9a5f 2817 non-empty-moov-no-elst +write_data len 20, time nopts, type header atom ftyp +write_data len 1195, time nopts, type header atom - +write_data len 608, time 0, type sync atom moof +write_data len 652, time nopts, type unknown atom - +write_data len 608, time 1013106, type sync atom moof +write_data len 640, time nopts, type unknown atom - +write_data len 148, time nopts, type trailer atom - +e8e0346bf20bfcb448695bd905946f78 3871 ismv +write_data len 36, time nopts, type header atom ftyp +write_data len 1147, time nopts, type header atom - +write_data len 500, time 0, type sync atom moof +write_data len 496, time 1000000, type sync atom moof +write_data len 148, time nopts, type trailer atom - +89ea214e1d1079556164664eea9a7884 2327 empty-moov +write_data len 36, time nopts, type header atom ftyp +write_data len 1147, time nopts, type header atom - +write_data len 780, time 0, type sync atom moof +write_data len 616, time 1000000, type sync atom moof +write_data len 148, time nopts, type trailer atom - +cf9eec38fe557203a37a44c8adafb1fe 2727 empty-moov-no-elst +write_data len 36, time nopts, type header atom ftyp +write_data len 1147, time nopts, type header atom - +write_data len 612, time -33333, type sync atom moof +write_data len 616, time 966667, type sync atom moof +write_data len 148, time nopts, type trailer atom - +42eca5843d98aa9a9b3275de201700b8 2559 empty-moov-no-elst-no-adjust +write_data len 1183, time nopts, type header atom ftyp +write_data len 500, time 0, type sync atom moof +write_data len 496, time 1000000, type sync atom moof +write_data len 148, time nopts, type trailer atom - +89ea214e1d1079556164664eea9a7884 2327 delay-moov +write_data len 1255, time nopts, type header atom ftyp +write_data len 620, time -33333, type sync atom moof +write_data len 616, time 966667, type sync atom moof +write_data len 148, time nopts, type trailer atom - +8fd78a5a91d73a735da53ac02f844177 2639 delay-moov-elst +write_data len 1183, time nopts, type header atom ftyp +write_data len 596, time 0, type sync atom moof +write_data len 67, time nopts, type trailer atom - +848d2fe2f27882960b8e10315460bc23 1846 delay-moov-empty-track +write_data len 1183, time nopts, type header atom ftyp +write_data len 240, time 0, type sync atom moof +write_data len 240, time 1000000, type sync atom moof +write_data len 86, time nopts, type trailer atom - +cbf60ba66c47b8506c1a724d43f12cdc 1749 delay-moov-empty-track-flush +write_data len 36, time nopts, type header atom ftyp +write_data len 1147, time nopts, type header atom - +c0b13fd47ca4c6de13c03155c38c231c 1183 empty-moov-header +write_data len 500, time 0, type sync atom moof +write_data len 496, time 1000000, type sync atom moof +f12baf7c4269695817337192c7069328 996 empty-moov-content +write_data len 148, time nopts, type trailer atom - +write_data len 1183, time nopts, type header atom ftyp +c0b13fd47ca4c6de13c03155c38c231c 1183 delay-moov-header +write_data len 500, time 0, type sync atom moof +write_data len 496, time 1000000, type sync atom moof +f12baf7c4269695817337192c7069328 996 delay-moov-content +write_data len 148, time nopts, type trailer atom - +write_data len 24, time nopts, type header atom - +write_data len 1147, time nopts, type header atom - +write_data len 588, time 0, type sync atom sidx +write_data len 584, time 1000000, type sync atom sidx +76e1081bbab7541eadcaf4b19d37eff6 584 empty-moov-second-frag +write_data len 148, time nopts, type trailer atom - +write_data len 24, time nopts, type header atom - +write_data len 1147, time nopts, type header atom - +write_data len 584, time 1000000, type sync atom sidx +76e1081bbab7541eadcaf4b19d37eff6 584 empty-moov-second-frag-discont +write_data len 110, time nopts, type trailer atom - +write_data len 1171, time nopts, type header atom - +write_data len 584, time 1000000, type sync atom sidx +76e1081bbab7541eadcaf4b19d37eff6 584 delay-moov-second-frag-discont +write_data len 110, time nopts, type trailer atom - +write_data len 1207, time nopts, type header atom ftyp +fdc08ccfb9ca1a7a63a8e82a99e28e83 1207 delay-moov-elst-init +write_data len 700, time -33333, type sync atom sidx +write_data len 704, time 966667, type sync atom sidx +41afdc44b0e376fae49a730afe0c53c2 704 delay-moov-elst-second-frag +write_data len 148, time nopts, type trailer atom - +write_data len 1207, time nopts, type header atom ftyp +fdc08ccfb9ca1a7a63a8e82a99e28e83 1207 delay-moov-elst-init-discont +write_data len 704, time 966667, type sync atom sidx +41afdc44b0e376fae49a730afe0c53c2 704 delay-moov-elst-second-frag-discont +write_data len 110, time nopts, type trailer atom - +write_data len 1243, time nopts, type header atom ftyp +57c113cd2baf7b231355eee6980fb6b5 1243 delay-moov-elst-signal-init +write_data len 708, time -33333, type sync atom sidx +write_data len 704, time 966667, type sync atom sidx +13b8487a4f004ec9f1db543aee1e5e18 704 delay-moov-elst-signal-second-frag +write_data len 148, time nopts, type trailer atom - +write_data len 1243, time nopts, type header atom ftyp +57c113cd2baf7b231355eee6980fb6b5 1243 delay-moov-elst-signal-init-discont +write_data len 704, time 966667, type sync atom sidx +13b8487a4f004ec9f1db543aee1e5e18 704 delay-moov-elst-signal-second-frag-discont +write_data len 110, time nopts, type trailer atom - +write_data len 1243, time nopts, type header atom ftyp +write_data len 1552, time -333333, type sync atom sidx +write_data len 704, time 5166667, type sync atom sidx +write_data len 148, time nopts, type trailer atom - +5e676152714f9478b5f74ce67cd7ed60 3647 vfr +write_data len 1243, time nopts, type header atom ftyp +write_data len 1552, time -333333, type sync atom sidx +write_data len 704, time 5166667, type sync atom sidx +write_data len 148, time nopts, type trailer atom - +5e676152714f9478b5f74ce67cd7ed60 3647 vfr-noduration +write_data len 1255, time nopts, type header atom ftyp +write_data len 1500, time -333333, type sync atom moof +write_data len 620, time nopts, type unknown atom - +write_data len 1500, time 9666667, type sync atom moof +write_data len 664, time nopts, type unknown atom - +write_data len 148, time nopts, type trailer atom - +03766894d839e5fcb1edb88498d812f7 5687 large_frag +write_data len 1255, time nopts, type header atom ftyp +write_data len 508, time -33333, type sync atom moof +write_data len 372, time 800000, type boundary atom moof +write_data len 328, time 1266667, type boundary atom moof +write_data len 476, time 1566667, type sync atom moof +write_data len 340, time 2233333, type boundary atom moof +write_data len 262, time nopts, type trailer atom - +a4280bdc23af2c4334ec2da3fa946d3a 3541 vfr-noduration-interleave diff --git a/tests/ref/fate/mpeg4-resolution-change-down-down b/tests/ref/fate/mpeg4-resolution-change-down-down new file mode 100644 index 0000000..137575a --- /dev/null +++ b/tests/ref/fate/mpeg4-resolution-change-down-down @@ -0,0 +1,151 @@ +#tb 0: 1/25 +0, 0, 0, 1, 460800, d65fcc79c7eb9ebd9d88dca3ebb15bf4 +0, 1, 1, 1, 460800, 6c86b8c7e8eae3d63b21342f233fb44e +0, 2, 2, 1, 460800, 7fea65fd8ee4d3fcec722f721d05ef45 +0, 3, 3, 1, 460800, 2a1d943211f8c1995cc250586f105991 +0, 4, 4, 1, 460800, 0430fa1da6a968c0936fc60a425c3b9f +0, 5, 5, 1, 460800, 1593684b29c0f394176c9fce83ebe4a3 +0, 6, 6, 1, 460800, ff8c25a20ced839a1ce33ef25d04f342 +0, 7, 7, 1, 460800, 08869a31b677080f3fb1b12e3178c1f8 +0, 8, 8, 1, 460800, 7e8d4c417698e434508663dfd851e95d +0, 9, 9, 1, 460800, 97488eafaa5db813bc9fbb13a4204240 +0, 10, 10, 1, 460800, aac8d92f678f077b560f24a74427ef33 +0, 11, 11, 1, 460800, dbb953e70f356c528e232dd90b21af99 +0, 12, 12, 1, 460800, 2f7b6c9f006ca733c159aadb78958621 +0, 13, 13, 1, 460800, 938142d358a298df924da648ff9542e2 +0, 14, 14, 1, 460800, 93cae8797e91f0ecb94782fd614ba477 +0, 15, 15, 1, 460800, 4644a98dbd46865c6c4e1ebe168b5095 +0, 16, 16, 1, 460800, cc932f281bf90456c508f58fda085658 +0, 17, 17, 1, 460800, 9280ef543c11446d7005a098d19b74a3 +0, 18, 18, 1, 460800, f5c91502bd600e1cfcd9ff7a5e683ce4 +0, 19, 19, 1, 460800, 4eda3b1d48ca986eeb14c90af947b6af +0, 20, 20, 1, 460800, 84e8398c333e76412bd310c207e131d3 +0, 21, 21, 1, 460800, 7abe283b322cc4c9aaeb56e4b2e03597 +0, 22, 22, 1, 460800, b4daa2055782c6f3769bf71cb1534124 +0, 23, 23, 1, 460800, 3deb3e2f41ef4549da3b0d89031eaa42 +0, 24, 24, 1, 460800, 73b9efcd2714b3cd65b1d8aee953cd38 +0, 25, 25, 1, 460800, 493ee5aab3a0ca22887b2b673d871efd +0, 26, 26, 1, 460800, 5fe537734707bbc050290df8c0095d0f +0, 27, 27, 1, 460800, ca337619639144e0aea0fe226e9dad63 +0, 28, 28, 1, 460800, 8fa2e0ff609d1593d34722058e56b19a +0, 29, 29, 1, 460800, be0950c431591485ed4de678f8f17187 +0, 30, 30, 1, 460800, 0ef4b6a8d2e3d455d697deaf730cf402 +0, 31, 31, 1, 460800, f74302190c8e47120b9597073525b08e +0, 32, 32, 1, 460800, 129fb2cc916aa16f8fee053ae89c31b3 +0, 33, 33, 1, 460800, 0186eacb73263bb0ae02c20f827dd650 +0, 34, 34, 1, 460800, f3c0245c28ded8d497665c87e66531de +0, 35, 35, 1, 460800, e550cae2b446a5460a7201ef20ad74fd +0, 36, 36, 1, 460800, 5fcf10d7b438dc4e29f7ec44f027170a +0, 37, 37, 1, 460800, 65be5db585be02d64238a43eabc40abe +0, 38, 38, 1, 460800, 93a9d9a64726138405db6d8865a6b71b +0, 39, 39, 1, 460800, 5af0a0d96f311fc96733c6e3e6860347 +0, 40, 40, 1, 460800, 8b6de9fe7f44a87eac573dedf8c6bbcb +0, 41, 41, 1, 460800, f8a7bb899b2643754f63317fa949c5d2 +0, 42, 42, 1, 460800, f9011d02dd844a80e477af7c497a1e56 +0, 43, 43, 1, 460800, ddae63ad8f604d5ed3d5a558fd84c6bb +0, 44, 44, 1, 460800, e815946decb3bee3f52fe4476d0f38ea +0, 45, 45, 1, 460800, c3b3e46f4f851ad16d4ce9782c3fdcca +0, 46, 46, 1, 460800, 9adcaa5ca967282f588ae184a64f15d8 +0, 47, 47, 1, 460800, 29a243a8e57c2b923c514d68c18645bf +0, 48, 48, 1, 460800, 7a1538cfa6fad69f93bf9977ce03b2df +0, 49, 49, 1, 460800, 91e042b5a26fb0a578fe8abad6a881c8 +0, 50, 50, 1, 460800, 4892c52ebd173c1c1f651ab9043bc0ae +0, 51, 51, 1, 460800, 411e8f1d0603f1bf9a6e0e2fbf139b40 +0, 52, 52, 1, 460800, a8982db63153a60d32d22e3ec52d055f +0, 53, 53, 1, 460800, eccd934107810c2360850b125c60aa20 +0, 54, 54, 1, 460800, 4ff4a75ad54f3fca7fe302fd42d8b635 +0, 55, 55, 1, 460800, 096f9c7f9605bd03a7d1a2f3707ab0cd +0, 56, 56, 1, 460800, 8b71840efcaa91b0e999b656458259e4 +0, 57, 57, 1, 460800, a316e47df5e3b815890bbe8ad28e58f7 +0, 58, 58, 1, 460800, c05734743b26b5938bbe491c5e1207bb +0, 59, 59, 1, 460800, f513bfb6d22eb6dee298bd60289d49ef +0, 60, 60, 1, 460800, 1242d643e8c4d4b758dd2e4ea934ddb1 +0, 61, 61, 1, 460800, d390abd9c75cce2847ea11929d765a97 +0, 62, 62, 1, 460800, 07c172820c57f4653db9d980f8003f05 +0, 63, 63, 1, 460800, f5121dc906185e1dad2b4d3ef036ffa2 +0, 64, 64, 1, 460800, ab9d1fcf6a5aad68d0f7f68f956a8905 +0, 65, 65, 1, 460800, a30b4e2d59c411cb8ed8b420d0e9980f +0, 66, 66, 1, 460800, a239203d87b8f6dae0b04aedb5509303 +0, 67, 67, 1, 460800, 08fe1416f25273f66354a8f4365886a9 +0, 68, 68, 1, 460800, 62a4f52f688484a633219bf2431a05a1 +0, 69, 69, 1, 460800, 4f56bbbdce274dca30ea0a6af1ad9fb5 +0, 70, 70, 1, 460800, 7cb37bb372fac6a6ed10066724bd55dc +0, 71, 71, 1, 460800, 74452850aa88ea0072e84657503d9044 +0, 72, 72, 1, 460800, e5a41bc0f20298b7ad04d5920cbd0ef9 +0, 73, 73, 1, 460800, 6bf692b510e12a1478ad701cd6b92f5f +0, 74, 74, 1, 460800, 70a990aa4e4e1cd09eb145fc5830182d +0, 75, 75, 1, 460800, d1766902072052fb820a485c382c5c38 +0, 76, 76, 1, 460800, 36959297268283e0134118a7552d5432 +0, 77, 77, 1, 460800, 907bec0f379ea9eb60a3122b8c253eeb +0, 78, 78, 1, 460800, 43f1068a583a9645245a0d60dc647b00 +0, 79, 79, 1, 460800, ee55d4619e4b10d3e931eca18a4d4586 +0, 80, 80, 1, 460800, ba6a2efc84360d701944df2236292d74 +0, 81, 81, 1, 460800, b496e4674b5eb6a60e16ec4069ffa1c2 +0, 82, 82, 1, 460800, 5ae928c45606d4665d82da353dd81a81 +0, 83, 83, 1, 460800, 3c84403932cf66e616373f0d25c9f4a8 +0, 84, 84, 1, 460800, e0b63b21cdfd96c44adeb2617ecd9022 +0, 85, 85, 1, 460800, 57e0299f7435c8bd610cba860b128001 +0, 86, 86, 1, 460800, a543a8694155a488e7cc9066a70739e5 +0, 87, 87, 1, 460800, 953d38d3b44e1564b037f83171f7f594 +0, 88, 88, 1, 460800, 3725640ec5fdaec8acc4da7a224b8137 +0, 89, 89, 1, 460800, bd1086accdf2eb9f3e8cfb1e0f09ff60 +0, 90, 90, 1, 460800, b1fc08e447396a2db10e1be8c6cda6a4 +0, 91, 91, 1, 460800, 76849824f2b9aafc850dcb9994058afb +0, 92, 92, 1, 460800, 90523973962279d4eb5ce1261f631ff0 +0, 93, 93, 1, 460800, d5c69da4109d4d41d9b7940dbed8a21a +0, 94, 94, 1, 460800, 978d8cbfe9413418d295c485225d8ac8 +0, 95, 95, 1, 460800, a917cd3dc6dd127523e972424f1f1544 +0, 96, 96, 1, 460800, 1a4889b8c72066ea90c2a66ff80cd118 +0, 97, 97, 1, 460800, 30f1792bad369f51bd90e20b8d084779 +0, 98, 98, 1, 460800, 14d67997177544d76d9ec69abe992bf5 +0, 99, 99, 1, 460800, 39ba73b642d95ab9d7d00ca9ecb276af +0, 100, 100, 1, 460800, 7614eed47fa4ab378fa95a6fa09048dd +0, 101, 101, 1, 460800, efbce233c30851726551446f2cf007d4 +0, 102, 102, 1, 460800, 4cdf067f4e0dec1d5468d73bc2fb6971 +0, 103, 103, 1, 460800, b6d5a482c97622ca0ac526e46864586c +0, 104, 104, 1, 460800, 860c1d3db436f96a29f83b25cad8a292 +0, 105, 105, 1, 460800, 3e1adea399679f5ea40539c49d63f475 +0, 106, 106, 1, 460800, 0422ac63df21baada7df73d9efb2b4a8 +0, 107, 107, 1, 460800, f372ebfd2acea1ac3d06a898bdf5ed28 +0, 108, 108, 1, 460800, 95c1bdc33fa3a9bf6fc1cf616eae4989 +0, 109, 109, 1, 460800, a8b67585ab13e9476a2075afb347e551 +0, 110, 110, 1, 460800, 6d7ff7585b172c18e9095bbf304701aa +0, 111, 111, 1, 460800, ca17a315650ecafcbff854414e832daf +0, 112, 112, 1, 460800, 0e58c300f666e2f608dde25cb4e7c6e4 +0, 113, 113, 1, 460800, 7e05f8ab2cf1fb99d11edb7dce8adb61 +0, 114, 114, 1, 460800, 5ec17032a3d98c18055eedc994d5b22c +0, 115, 115, 1, 460800, 3be2f9e9bdf62279b1d1c55af298b8bf +0, 116, 116, 1, 460800, d791c1335df7a9aac01aeb893e16ebeb +0, 117, 117, 1, 460800, b1235bfe00b13ac9d4abeb42be518de6 +0, 118, 118, 1, 460800, 770b5fc1acd72c526f7b751569f9ebdd +0, 119, 119, 1, 460800, 76988407c42beb84704e5cc8175ae3d1 +0, 120, 120, 1, 460800, 9b38739847b080d019403ad0d62505f1 +0, 121, 121, 1, 460800, 06d881fe05e16b528a056001f6162b18 +0, 122, 122, 1, 460800, 2f920d88d0ac956bb7c82c2ee1999b5d +0, 123, 123, 1, 460800, 3bda811ee889672ef9bf3b329c0d8702 +0, 124, 124, 1, 460800, 793ca50f817442d000c228bae1d34f01 +0, 125, 125, 1, 460800, 6ac43125d47508fbee2a112962d68f7f +0, 126, 126, 1, 460800, ee60676687c0a54c648f37dc5ac62934 +0, 127, 127, 1, 460800, 34c11e62e2f886fb3f86eabaf5bb8616 +0, 128, 128, 1, 460800, fbf06b77ea70076417e7dae3f05559ad +0, 129, 129, 1, 460800, 0910773159fee4579b60665961f42dff +0, 130, 130, 1, 460800, 16e2bdddb02ed137c45779915e83f8ce +0, 131, 131, 1, 460800, 36c2a8b39e39e37dfd3acaf53166d32d +0, 132, 132, 1, 460800, 86a93fca2ea3b276d8b5d7922b051635 +0, 133, 133, 1, 460800, 453eeba71c375f94cd2955a390e19aee +0, 134, 134, 1, 460800, 9b0661b42795d819909b6a10759f2ea8 +0, 135, 135, 1, 460800, 982d156baa7facd8ff90dfc896705dba +0, 136, 136, 1, 460800, 4346140eb7859cf937813b320c2afd75 +0, 137, 137, 1, 460800, cb19089d54d215ee5759fa95c995cb03 +0, 138, 138, 1, 460800, 4372a47d5c86bd7f36af8b1708d89db1 +0, 139, 139, 1, 460800, 63c1ccf9233c8ced848a536ca83fd2e2 +0, 140, 140, 1, 460800, e05f15fe8811919b514aff6d712e050b +0, 141, 141, 1, 460800, 7a0787e04d549faeb60e6c53d036fc36 +0, 142, 142, 1, 460800, a48da643d5807dc1b2c9e3768c14fa09 +0, 143, 143, 1, 460800, 18e8af2af9a6d07d0319c216f32833bd +0, 144, 144, 1, 460800, 54a4abc6dc41181dc6c4ed12ff68d9b6 +0, 145, 145, 1, 460800, 8c4bb205f07927c237134a2b43a1c75e +0, 146, 146, 1, 460800, c8fbebc0b9d1b0eef22ed22b339c29ad +0, 147, 147, 1, 460800, 0092360b69fd89eec83302f9c54e63c0 +0, 148, 148, 1, 460800, 454f705a542986ee3df10a31571bac36 +0, 149, 149, 1, 460800, 810de13c12e064d70ca6d1f1c175f0b6 diff --git a/tests/ref/fate/mpeg4-resolution-change-down-up b/tests/ref/fate/mpeg4-resolution-change-down-up new file mode 100644 index 0000000..31332c3 --- /dev/null +++ b/tests/ref/fate/mpeg4-resolution-change-down-up @@ -0,0 +1,151 @@ +#tb 0: 1/25 +0, 0, 0, 1, 460800, d65fcc79c7eb9ebd9d88dca3ebb15bf4 +0, 1, 1, 1, 460800, 6c86b8c7e8eae3d63b21342f233fb44e +0, 2, 2, 1, 460800, 7fea65fd8ee4d3fcec722f721d05ef45 +0, 3, 3, 1, 460800, 2a1d943211f8c1995cc250586f105991 +0, 4, 4, 1, 460800, 0430fa1da6a968c0936fc60a425c3b9f +0, 5, 5, 1, 460800, 1593684b29c0f394176c9fce83ebe4a3 +0, 6, 6, 1, 460800, ff8c25a20ced839a1ce33ef25d04f342 +0, 7, 7, 1, 460800, 08869a31b677080f3fb1b12e3178c1f8 +0, 8, 8, 1, 460800, 7e8d4c417698e434508663dfd851e95d +0, 9, 9, 1, 460800, 97488eafaa5db813bc9fbb13a4204240 +0, 10, 10, 1, 460800, aac8d92f678f077b560f24a74427ef33 +0, 11, 11, 1, 460800, dbb953e70f356c528e232dd90b21af99 +0, 12, 12, 1, 460800, 2f7b6c9f006ca733c159aadb78958621 +0, 13, 13, 1, 460800, 938142d358a298df924da648ff9542e2 +0, 14, 14, 1, 460800, 93cae8797e91f0ecb94782fd614ba477 +0, 15, 15, 1, 460800, 4644a98dbd46865c6c4e1ebe168b5095 +0, 16, 16, 1, 460800, cc932f281bf90456c508f58fda085658 +0, 17, 17, 1, 460800, 9280ef543c11446d7005a098d19b74a3 +0, 18, 18, 1, 460800, f5c91502bd600e1cfcd9ff7a5e683ce4 +0, 19, 19, 1, 460800, 4eda3b1d48ca986eeb14c90af947b6af +0, 20, 20, 1, 460800, 84e8398c333e76412bd310c207e131d3 +0, 21, 21, 1, 460800, 7abe283b322cc4c9aaeb56e4b2e03597 +0, 22, 22, 1, 460800, b4daa2055782c6f3769bf71cb1534124 +0, 23, 23, 1, 460800, 3deb3e2f41ef4549da3b0d89031eaa42 +0, 24, 24, 1, 460800, 73b9efcd2714b3cd65b1d8aee953cd38 +0, 25, 25, 1, 460800, 493ee5aab3a0ca22887b2b673d871efd +0, 26, 26, 1, 460800, 5fe537734707bbc050290df8c0095d0f +0, 27, 27, 1, 460800, ca337619639144e0aea0fe226e9dad63 +0, 28, 28, 1, 460800, 8fa2e0ff609d1593d34722058e56b19a +0, 29, 29, 1, 460800, be0950c431591485ed4de678f8f17187 +0, 30, 30, 1, 460800, 0ef4b6a8d2e3d455d697deaf730cf402 +0, 31, 31, 1, 460800, f74302190c8e47120b9597073525b08e +0, 32, 32, 1, 460800, 129fb2cc916aa16f8fee053ae89c31b3 +0, 33, 33, 1, 460800, 0186eacb73263bb0ae02c20f827dd650 +0, 34, 34, 1, 460800, f3c0245c28ded8d497665c87e66531de +0, 35, 35, 1, 460800, e550cae2b446a5460a7201ef20ad74fd +0, 36, 36, 1, 460800, 5fcf10d7b438dc4e29f7ec44f027170a +0, 37, 37, 1, 460800, 65be5db585be02d64238a43eabc40abe +0, 38, 38, 1, 460800, 93a9d9a64726138405db6d8865a6b71b +0, 39, 39, 1, 460800, 5af0a0d96f311fc96733c6e3e6860347 +0, 40, 40, 1, 460800, 8b6de9fe7f44a87eac573dedf8c6bbcb +0, 41, 41, 1, 460800, f8a7bb899b2643754f63317fa949c5d2 +0, 42, 42, 1, 460800, f9011d02dd844a80e477af7c497a1e56 +0, 43, 43, 1, 460800, ddae63ad8f604d5ed3d5a558fd84c6bb +0, 44, 44, 1, 460800, e815946decb3bee3f52fe4476d0f38ea +0, 45, 45, 1, 460800, c3b3e46f4f851ad16d4ce9782c3fdcca +0, 46, 46, 1, 460800, 9adcaa5ca967282f588ae184a64f15d8 +0, 47, 47, 1, 460800, 29a243a8e57c2b923c514d68c18645bf +0, 48, 48, 1, 460800, 7a1538cfa6fad69f93bf9977ce03b2df +0, 49, 49, 1, 460800, 91e042b5a26fb0a578fe8abad6a881c8 +0, 50, 50, 1, 460800, 7614eed47fa4ab378fa95a6fa09048dd +0, 51, 51, 1, 460800, efbce233c30851726551446f2cf007d4 +0, 52, 52, 1, 460800, 4cdf067f4e0dec1d5468d73bc2fb6971 +0, 53, 53, 1, 460800, b6d5a482c97622ca0ac526e46864586c +0, 54, 54, 1, 460800, 860c1d3db436f96a29f83b25cad8a292 +0, 55, 55, 1, 460800, 3e1adea399679f5ea40539c49d63f475 +0, 56, 56, 1, 460800, 0422ac63df21baada7df73d9efb2b4a8 +0, 57, 57, 1, 460800, f372ebfd2acea1ac3d06a898bdf5ed28 +0, 58, 58, 1, 460800, 95c1bdc33fa3a9bf6fc1cf616eae4989 +0, 59, 59, 1, 460800, a8b67585ab13e9476a2075afb347e551 +0, 60, 60, 1, 460800, 6d7ff7585b172c18e9095bbf304701aa +0, 61, 61, 1, 460800, ca17a315650ecafcbff854414e832daf +0, 62, 62, 1, 460800, 0e58c300f666e2f608dde25cb4e7c6e4 +0, 63, 63, 1, 460800, 7e05f8ab2cf1fb99d11edb7dce8adb61 +0, 64, 64, 1, 460800, 5ec17032a3d98c18055eedc994d5b22c +0, 65, 65, 1, 460800, 3be2f9e9bdf62279b1d1c55af298b8bf +0, 66, 66, 1, 460800, d791c1335df7a9aac01aeb893e16ebeb +0, 67, 67, 1, 460800, b1235bfe00b13ac9d4abeb42be518de6 +0, 68, 68, 1, 460800, 770b5fc1acd72c526f7b751569f9ebdd +0, 69, 69, 1, 460800, 76988407c42beb84704e5cc8175ae3d1 +0, 70, 70, 1, 460800, 9b38739847b080d019403ad0d62505f1 +0, 71, 71, 1, 460800, 06d881fe05e16b528a056001f6162b18 +0, 72, 72, 1, 460800, 2f920d88d0ac956bb7c82c2ee1999b5d +0, 73, 73, 1, 460800, 3bda811ee889672ef9bf3b329c0d8702 +0, 74, 74, 1, 460800, 793ca50f817442d000c228bae1d34f01 +0, 75, 75, 1, 460800, 6ac43125d47508fbee2a112962d68f7f +0, 76, 76, 1, 460800, ee60676687c0a54c648f37dc5ac62934 +0, 77, 77, 1, 460800, 34c11e62e2f886fb3f86eabaf5bb8616 +0, 78, 78, 1, 460800, fbf06b77ea70076417e7dae3f05559ad +0, 79, 79, 1, 460800, 0910773159fee4579b60665961f42dff +0, 80, 80, 1, 460800, 16e2bdddb02ed137c45779915e83f8ce +0, 81, 81, 1, 460800, 36c2a8b39e39e37dfd3acaf53166d32d +0, 82, 82, 1, 460800, 86a93fca2ea3b276d8b5d7922b051635 +0, 83, 83, 1, 460800, 453eeba71c375f94cd2955a390e19aee +0, 84, 84, 1, 460800, 9b0661b42795d819909b6a10759f2ea8 +0, 85, 85, 1, 460800, 982d156baa7facd8ff90dfc896705dba +0, 86, 86, 1, 460800, 4346140eb7859cf937813b320c2afd75 +0, 87, 87, 1, 460800, cb19089d54d215ee5759fa95c995cb03 +0, 88, 88, 1, 460800, 4372a47d5c86bd7f36af8b1708d89db1 +0, 89, 89, 1, 460800, 63c1ccf9233c8ced848a536ca83fd2e2 +0, 90, 90, 1, 460800, e05f15fe8811919b514aff6d712e050b +0, 91, 91, 1, 460800, 7a0787e04d549faeb60e6c53d036fc36 +0, 92, 92, 1, 460800, a48da643d5807dc1b2c9e3768c14fa09 +0, 93, 93, 1, 460800, 18e8af2af9a6d07d0319c216f32833bd +0, 94, 94, 1, 460800, 54a4abc6dc41181dc6c4ed12ff68d9b6 +0, 95, 95, 1, 460800, 8c4bb205f07927c237134a2b43a1c75e +0, 96, 96, 1, 460800, c8fbebc0b9d1b0eef22ed22b339c29ad +0, 97, 97, 1, 460800, 0092360b69fd89eec83302f9c54e63c0 +0, 98, 98, 1, 460800, 454f705a542986ee3df10a31571bac36 +0, 99, 99, 1, 460800, 810de13c12e064d70ca6d1f1c175f0b6 +0, 100, 100, 1, 460800, 4892c52ebd173c1c1f651ab9043bc0ae +0, 101, 101, 1, 460800, 411e8f1d0603f1bf9a6e0e2fbf139b40 +0, 102, 102, 1, 460800, a8982db63153a60d32d22e3ec52d055f +0, 103, 103, 1, 460800, eccd934107810c2360850b125c60aa20 +0, 104, 104, 1, 460800, 4ff4a75ad54f3fca7fe302fd42d8b635 +0, 105, 105, 1, 460800, 096f9c7f9605bd03a7d1a2f3707ab0cd +0, 106, 106, 1, 460800, 8b71840efcaa91b0e999b656458259e4 +0, 107, 107, 1, 460800, a316e47df5e3b815890bbe8ad28e58f7 +0, 108, 108, 1, 460800, c05734743b26b5938bbe491c5e1207bb +0, 109, 109, 1, 460800, f513bfb6d22eb6dee298bd60289d49ef +0, 110, 110, 1, 460800, 1242d643e8c4d4b758dd2e4ea934ddb1 +0, 111, 111, 1, 460800, d390abd9c75cce2847ea11929d765a97 +0, 112, 112, 1, 460800, 07c172820c57f4653db9d980f8003f05 +0, 113, 113, 1, 460800, f5121dc906185e1dad2b4d3ef036ffa2 +0, 114, 114, 1, 460800, ab9d1fcf6a5aad68d0f7f68f956a8905 +0, 115, 115, 1, 460800, a30b4e2d59c411cb8ed8b420d0e9980f +0, 116, 116, 1, 460800, a239203d87b8f6dae0b04aedb5509303 +0, 117, 117, 1, 460800, 08fe1416f25273f66354a8f4365886a9 +0, 118, 118, 1, 460800, 62a4f52f688484a633219bf2431a05a1 +0, 119, 119, 1, 460800, 4f56bbbdce274dca30ea0a6af1ad9fb5 +0, 120, 120, 1, 460800, 7cb37bb372fac6a6ed10066724bd55dc +0, 121, 121, 1, 460800, 74452850aa88ea0072e84657503d9044 +0, 122, 122, 1, 460800, e5a41bc0f20298b7ad04d5920cbd0ef9 +0, 123, 123, 1, 460800, 6bf692b510e12a1478ad701cd6b92f5f +0, 124, 124, 1, 460800, 70a990aa4e4e1cd09eb145fc5830182d +0, 125, 125, 1, 460800, d1766902072052fb820a485c382c5c38 +0, 126, 126, 1, 460800, 36959297268283e0134118a7552d5432 +0, 127, 127, 1, 460800, 907bec0f379ea9eb60a3122b8c253eeb +0, 128, 128, 1, 460800, 43f1068a583a9645245a0d60dc647b00 +0, 129, 129, 1, 460800, ee55d4619e4b10d3e931eca18a4d4586 +0, 130, 130, 1, 460800, ba6a2efc84360d701944df2236292d74 +0, 131, 131, 1, 460800, b496e4674b5eb6a60e16ec4069ffa1c2 +0, 132, 132, 1, 460800, 5ae928c45606d4665d82da353dd81a81 +0, 133, 133, 1, 460800, 3c84403932cf66e616373f0d25c9f4a8 +0, 134, 134, 1, 460800, e0b63b21cdfd96c44adeb2617ecd9022 +0, 135, 135, 1, 460800, 57e0299f7435c8bd610cba860b128001 +0, 136, 136, 1, 460800, a543a8694155a488e7cc9066a70739e5 +0, 137, 137, 1, 460800, 953d38d3b44e1564b037f83171f7f594 +0, 138, 138, 1, 460800, 3725640ec5fdaec8acc4da7a224b8137 +0, 139, 139, 1, 460800, bd1086accdf2eb9f3e8cfb1e0f09ff60 +0, 140, 140, 1, 460800, b1fc08e447396a2db10e1be8c6cda6a4 +0, 141, 141, 1, 460800, 76849824f2b9aafc850dcb9994058afb +0, 142, 142, 1, 460800, 90523973962279d4eb5ce1261f631ff0 +0, 143, 143, 1, 460800, d5c69da4109d4d41d9b7940dbed8a21a +0, 144, 144, 1, 460800, 978d8cbfe9413418d295c485225d8ac8 +0, 145, 145, 1, 460800, a917cd3dc6dd127523e972424f1f1544 +0, 146, 146, 1, 460800, 1a4889b8c72066ea90c2a66ff80cd118 +0, 147, 147, 1, 460800, 30f1792bad369f51bd90e20b8d084779 +0, 148, 148, 1, 460800, 14d67997177544d76d9ec69abe992bf5 +0, 149, 149, 1, 460800, 39ba73b642d95ab9d7d00ca9ecb276af diff --git a/tests/ref/fate/mpeg4-resolution-change-up-down b/tests/ref/fate/mpeg4-resolution-change-up-down new file mode 100644 index 0000000..81911f7 --- /dev/null +++ b/tests/ref/fate/mpeg4-resolution-change-up-down @@ -0,0 +1,151 @@ +#tb 0: 1/25 +0, 0, 0, 1, 180000, 9fc6302026cf2a2dd310646b83c5dfa1 +0, 1, 1, 1, 180000, b1b2646c8df579ddf8676bc2488411a5 +0, 2, 2, 1, 180000, 5aca8cdf4914a96577cffbbc18508043 +0, 3, 3, 1, 180000, d5bec8091a32a6669e76b8ab8f82db1f +0, 4, 4, 1, 180000, d8e8543d19d0d71959321ffcebf820ad +0, 5, 5, 1, 180000, 90520f273b47e423ae8f519e17b9994b +0, 6, 6, 1, 180000, 3f6b9fc1fc30804b98a16264b944ff55 +0, 7, 7, 1, 180000, 3cd3b36f6ee370c27ef86c6cd9fc7c1d +0, 8, 8, 1, 180000, 44f44f2ac0c9160d3e8ae184c7e4caa9 +0, 9, 9, 1, 180000, c7c96bf89dd79249755b9ae0af6a259e +0, 10, 10, 1, 180000, 8ba3f9677fb07be37b0964cf847cb538 +0, 11, 11, 1, 180000, 59614cce923cf836395b7628dddaba06 +0, 12, 12, 1, 180000, 6497b597654c9c90e290feec2f8b11c8 +0, 13, 13, 1, 180000, df2774f8219a29629bbda3c368ca3046 +0, 14, 14, 1, 180000, 818bed7e0e12e11bf510939e0a895421 +0, 15, 15, 1, 180000, 591377e15da046fe83cadede3c13ec0d +0, 16, 16, 1, 180000, 6dcc7dc9287054307cd67db723f4b806 +0, 17, 17, 1, 180000, 5158145404ee2eda2cad930127bc9480 +0, 18, 18, 1, 180000, 9423c3bc58b00299c762d547a98d22b1 +0, 19, 19, 1, 180000, 960dcbf47536653087afc917a99f97b4 +0, 20, 20, 1, 180000, 05f7ba88fd8a73416cfab0427db30c5f +0, 21, 21, 1, 180000, 51809dcb798fc5cc45066faf56f6b533 +0, 22, 22, 1, 180000, b637cc799280b57a770d8c3417f5a9f3 +0, 23, 23, 1, 180000, 900632153e8a06208550d62c7f327e06 +0, 24, 24, 1, 180000, fcbce1d8ee2a284e7a8a2923d878ca1a +0, 25, 25, 1, 180000, ac64fdfeef02c97bb7ee3bd8d42cda4a +0, 26, 26, 1, 180000, 528b693654f55eac5793222591fc32ca +0, 27, 27, 1, 180000, d2d23bf508c6ab797cfa9093824e7271 +0, 28, 28, 1, 180000, 249d71065ba6170ee82fffeb84489a57 +0, 29, 29, 1, 180000, ab8a7ac5bdaeb22a4cc5834ff4dbc838 +0, 30, 30, 1, 180000, bc9a0da67f7dd812e4dc29adab36c79c +0, 31, 31, 1, 180000, 4fd1c8d536616622d2acf5313ffad839 +0, 32, 32, 1, 180000, 32241cbbf06fc238ac8f852db8004788 +0, 33, 33, 1, 180000, 99cdd2026fae42d0f5de666596073c23 +0, 34, 34, 1, 180000, 9fc705da6bdf42c7f41b858185851816 +0, 35, 35, 1, 180000, 8acbd773806f2933aaadb85b4a693390 +0, 36, 36, 1, 180000, 781045116f6e6576cd53453fada887d4 +0, 37, 37, 1, 180000, 81a53875f718c706de28881c340e79a1 +0, 38, 38, 1, 180000, d183354aa17b8d65d3583264ae81bd54 +0, 39, 39, 1, 180000, 42dc484e20e9779405b205d8aa879373 +0, 40, 40, 1, 180000, d2034292cfb3a3a61b815a6a434d8f01 +0, 41, 41, 1, 180000, 625bde305548017781ed1f5bc5cb8cc4 +0, 42, 42, 1, 180000, 260544b15d99fff9e5782e30a165e5bf +0, 43, 43, 1, 180000, 7ba5b56979a3ec49e407f7fd51912dc4 +0, 44, 44, 1, 180000, 78e40b052b8773631a014692c667590d +0, 45, 45, 1, 180000, a79266a1d52b21594467f1efde654e3d +0, 46, 46, 1, 180000, 33f00d3f9dd037ab9cf4dcf8a68ab013 +0, 47, 47, 1, 180000, 91d7f5d53a0d5f37c2cf485e73db66bb +0, 48, 48, 1, 180000, 74463929bc9e7e56bd8b2f9cc194e0e9 +0, 49, 49, 1, 180000, 14c4f3cead9eda56e96dbaedce61e4c8 +0, 50, 50, 1, 180000, ba12d7a55633679bb4a9767e1c4a4c76 +0, 51, 51, 1, 180000, ad39deaa1c6a3c3dbc9a5448b9449d55 +0, 52, 52, 1, 180000, 1a59266fd8b69ecd8c0ba6894a902d9f +0, 53, 53, 1, 180000, f0229d7137bfac76273261df2eaacbaf +0, 54, 54, 1, 180000, 0655f3778ec7c64aa44b2cb7e9f4bce9 +0, 55, 55, 1, 180000, e5d0cf9f7a9c751afe09cac6f415f9a3 +0, 56, 56, 1, 180000, a103674a6d42da7bb026ddc6c21907f5 +0, 57, 57, 1, 180000, 86fd09abac435c94aacdc4e24bae5fa4 +0, 58, 58, 1, 180000, cba4362f9905f12ea415114011f634e3 +0, 59, 59, 1, 180000, adc6dc728070c97414d5681606f9509a +0, 60, 60, 1, 180000, ab105d61727de7f3234c1b4618684fff +0, 61, 61, 1, 180000, e1bb39c9fda419ce27459b3679bab6f5 +0, 62, 62, 1, 180000, 6b1b2e9e4dbf0512f5c082b950f5d1ea +0, 63, 63, 1, 180000, 58fde3d07e884461f9e535cc6af67d61 +0, 64, 64, 1, 180000, d696821896825012fdef20361ea43376 +0, 65, 65, 1, 180000, b3a15b5a8efb394dbec89ef722d02937 +0, 66, 66, 1, 180000, bbf7cc7fef6b4b37abf12dea62c190ec +0, 67, 67, 1, 180000, 19ad669ab8639d4eebd3f7217270b8d3 +0, 68, 68, 1, 180000, 1c8d1f98393cb9d0d38d43a296c47d17 +0, 69, 69, 1, 180000, 6feac439b0e0172220c87abda22c726b +0, 70, 70, 1, 180000, 9c8608262d6a6012f9dd49001e8a5c2d +0, 71, 71, 1, 180000, e79b848e3d0e323d6425a76c35a6d6f1 +0, 72, 72, 1, 180000, f2553bbaaae2e1b6898202401a085cf0 +0, 73, 73, 1, 180000, 34903147296c1d9f5c6c322a05ad1bbe +0, 74, 74, 1, 180000, 6ed277498b9cdee9591b98bf9c1d6ba2 +0, 75, 75, 1, 180000, 5d94ad871ad94c36a7b6e3cf72058c4e +0, 76, 76, 1, 180000, e380d7309b5f5c135c47773709575061 +0, 77, 77, 1, 180000, 554aa8facbaacc17eab7d2c36e2516c8 +0, 78, 78, 1, 180000, e5d7a81ec4c3244f548ad8d9225672fe +0, 79, 79, 1, 180000, 201b30fb23e71c5472b884153592846d +0, 80, 80, 1, 180000, 329bcc411f576fa4fbc7cd863e2ae459 +0, 81, 81, 1, 180000, 0b7ace1a4821d560c61053e3980b9b21 +0, 82, 82, 1, 180000, ebb2567c17350e67415e1e2259b0da8b +0, 83, 83, 1, 180000, c10b8774392c43585c69434f7d5bd94e +0, 84, 84, 1, 180000, 9f5862196d2bebc4ad09c214593b223e +0, 85, 85, 1, 180000, 300dc16fbb0f2486100ed167f1d90627 +0, 86, 86, 1, 180000, 0bec9c42aa215b0c5e73a5faf8f5c925 +0, 87, 87, 1, 180000, 779d67d3f58b5dd8094b414a830b94fc +0, 88, 88, 1, 180000, a9414e841f60cd04e414a9cad3126f22 +0, 89, 89, 1, 180000, 6b4bf1026523dd19e77705a56c9395bf +0, 90, 90, 1, 180000, 3e7f0e8db2738e287a5c1dff33bdc90b +0, 91, 91, 1, 180000, 5d8bf7db24fa21a21beaba6fb6ac3c95 +0, 92, 92, 1, 180000, 90f594797c97a10457bc1617d8e069e0 +0, 93, 93, 1, 180000, 9caa885630cd088d51a3601afa090f45 +0, 94, 94, 1, 180000, c189ea0726442a93a30466930b498aba +0, 95, 95, 1, 180000, 117422414360e8bb3b617e4118bb5699 +0, 96, 96, 1, 180000, 4ad2ffd81a6adeb21affce414fea992e +0, 97, 97, 1, 180000, 4b1f12d5a755070858d5a8218cb42ee5 +0, 98, 98, 1, 180000, 77bee2dff4ebafdea925228a870aa270 +0, 99, 99, 1, 180000, f9e4ed9fb47611084dfe1998b3a17fe2 +0, 100, 100, 1, 180000, e532cc6487cc51a7ea99d7a909f0d9d7 +0, 101, 101, 1, 180000, 79abcb269e5400f7676c869db06201f5 +0, 102, 102, 1, 180000, 5ea8363a325b8c73d8f7689234b534cb +0, 103, 103, 1, 180000, 8b92e05ce85cb879779256efb60ef56d +0, 104, 104, 1, 180000, 7319585dceaaa1dc339cba253ca7f7e1 +0, 105, 105, 1, 180000, a589ddfebfc5106268996dc641b63ed5 +0, 106, 106, 1, 180000, f1ea16230a29ab7a0c76b62119aec1f6 +0, 107, 107, 1, 180000, bf783508ccdc7ded175c240803c8ba42 +0, 108, 108, 1, 180000, 8432ceb650366458ea568d5d38f34339 +0, 109, 109, 1, 180000, e83eec0ba33fb28c2652985e3d5a5aa7 +0, 110, 110, 1, 180000, 866481b59ea1f6654c617b598218ac72 +0, 111, 111, 1, 180000, d1d5d72d11b430986d62a4976d3f440b +0, 112, 112, 1, 180000, d5bbb30019545ef298f5aedeb1e50420 +0, 113, 113, 1, 180000, 9b519b5c800734d940d5b6e1c519d2f3 +0, 114, 114, 1, 180000, 46854ea69f9de67f74d216fb46ca0d3f +0, 115, 115, 1, 180000, 43c3e53ee16e172c635bc2215e1dbe7a +0, 116, 116, 1, 180000, 76ffdd6b5630a716cea844e34f357726 +0, 117, 117, 1, 180000, 9a65251f4152bee7529d22017d75d30b +0, 118, 118, 1, 180000, 350ff9995c2287a5d6af83adaaa94692 +0, 119, 119, 1, 180000, 18c87ab4e73b5c4013e722a82015144a +0, 120, 120, 1, 180000, 45bfbaac738447afda91f1aa3b877114 +0, 121, 121, 1, 180000, 727d7b1d10b96f60593b0363a1da04a3 +0, 122, 122, 1, 180000, 77c7fff4a368cf923d442a70bef5d2b6 +0, 123, 123, 1, 180000, e021419b7c840409c8543d127c55ceef +0, 124, 124, 1, 180000, 5af4ffe289b7466c7b2ba6696e24b891 +0, 125, 125, 1, 180000, 7869c8c388f762054726a4fded34ef76 +0, 126, 126, 1, 180000, 9de7b2074944cdb6c1b28490b89b4d1b +0, 127, 127, 1, 180000, 1c65f0842787445c5a4291db5ec95306 +0, 128, 128, 1, 180000, 0836fc11e0537c64b89ca03c98e91a88 +0, 129, 129, 1, 180000, 6c0633861801dfff2464211987e199f4 +0, 130, 130, 1, 180000, 804f395636e19519f8b2c57572e2f5b9 +0, 131, 131, 1, 180000, 26119987a7cfce7146596b5119627cec +0, 132, 132, 1, 180000, bb064421d53f2aa472e189ceb1d1fb8f +0, 133, 133, 1, 180000, 8f4fe12cf1ada41bd75a8ab4e6c29daa +0, 134, 134, 1, 180000, 320803434ed72884005218c336ec616c +0, 135, 135, 1, 180000, 636d47f0af76b7caa244436b61d066ea +0, 136, 136, 1, 180000, d72bcab89102d278bdc34cc9d6d70d8d +0, 137, 137, 1, 180000, 8b97a2fd174e873c5d2f815c996307e1 +0, 138, 138, 1, 180000, 780a5d69dab54077770f038b83da3786 +0, 139, 139, 1, 180000, 49238301baf70b59bc7155c79b77812f +0, 140, 140, 1, 180000, ba9c941092f9c000935f5d0077943155 +0, 141, 141, 1, 180000, 2c91278ed0bd73a83fafa5ab373025ae +0, 142, 142, 1, 180000, e8c1ce1347e00d9a9267ec2ee2e55f88 +0, 143, 143, 1, 180000, a9d055533ee4c85f1a47dbc0e4900ee5 +0, 144, 144, 1, 180000, 37011528ef6d82c233ab81d6fa4b25c9 +0, 145, 145, 1, 180000, bec33254e1b75e5bcf9add1b016c6409 +0, 146, 146, 1, 180000, 686469d5f908c4b13f7da93accdbfe08 +0, 147, 147, 1, 180000, 175bc1a2a4b93c51f26cec24919a5e71 +0, 148, 148, 1, 180000, 7b42cf6186457f0796a5edf418c97ff1 +0, 149, 149, 1, 180000, f6dc114720002a975e5dd4c96d64eec8 diff --git a/tests/ref/fate/mpeg4-resolution-change-up-up b/tests/ref/fate/mpeg4-resolution-change-up-up new file mode 100644 index 0000000..9aac9c8 --- /dev/null +++ b/tests/ref/fate/mpeg4-resolution-change-up-up @@ -0,0 +1,151 @@ +#tb 0: 1/25 +0, 0, 0, 1, 152064, 7f952fd8bd40c32197afc21e2fa66404 +0, 1, 1, 1, 152064, 5b2cc25b04d9a9d33bcf5fe480505d68 +0, 2, 2, 1, 152064, 56d6bb0022f68fbccae81ef054a88c9a +0, 3, 3, 1, 152064, e9185c3ef0d3886f1a39b83f84da767e +0, 4, 4, 1, 152064, cac301c833ad7a916acfae8fd5e524e9 +0, 5, 5, 1, 152064, cd050aba9e0681e15294480188f4076a +0, 6, 6, 1, 152064, 6451e141b4d6360dd7bf098fa235afc7 +0, 7, 7, 1, 152064, ac242e1eb5389ce7a6ecfc34c8594383 +0, 8, 8, 1, 152064, d35ed5d3c1542a08881fc3aa729e5308 +0, 9, 9, 1, 152064, 4049e48c807e9d39b1ac03d5b9cc4647 +0, 10, 10, 1, 152064, 2c39818c50ab18982da8e29b1a95d574 +0, 11, 11, 1, 152064, adba30adcdaf3c52bb6c2595753f3bf1 +0, 12, 12, 1, 152064, 77ba6ff6f1e7380c84e4ef635dad5414 +0, 13, 13, 1, 152064, 8ee39ce5454533b610c680ef8944c369 +0, 14, 14, 1, 152064, 1785d1de2383fff0f6ba133ece182003 +0, 15, 15, 1, 152064, fe7d8c8a7ace0dabc550d6672e8e9c15 +0, 16, 16, 1, 152064, d751ad4771ab30290f01afc9c15d93ff +0, 17, 17, 1, 152064, 3a0f3e1dd11527ce6660bc5a3c846f5e +0, 18, 18, 1, 152064, 5db4cb8d1403a296d1346bc0aac7e6e6 +0, 19, 19, 1, 152064, fb8f602708055e1436b473bd00abf646 +0, 20, 20, 1, 152064, dcad983fe9d87b9597e893d05352d865 +0, 21, 21, 1, 152064, 2541aefc80d4598ab64ea8591dcf79de +0, 22, 22, 1, 152064, a80f92f508833eecd69c7f8dd21da13f +0, 23, 23, 1, 152064, 6e28ef4f6e1151861929e46afc0aad5f +0, 24, 24, 1, 152064, a9104c687097adc9d68751e508940bcc +0, 25, 25, 1, 152064, 65e90aa73b8228bda909775914453dc2 +0, 26, 26, 1, 152064, 3c068b06d02b5e4110732700b1aa146b +0, 27, 27, 1, 152064, 48f3ec3807d333774c3d031c5a9cdc50 +0, 28, 28, 1, 152064, 0d74aaa8ee4a88b4983b3e505938c962 +0, 29, 29, 1, 152064, ff1ec9697579f47fc647f56d85591207 +0, 30, 30, 1, 152064, 8052dd9c27296a2d5b2101d97af62d8e +0, 31, 31, 1, 152064, 7a253ee1c0e0aadd3e12bfb1278299fb +0, 32, 32, 1, 152064, b24126f3573811d8d6dc6db674ca8c64 +0, 33, 33, 1, 152064, b3f54900ec9a60f9d63387a24500a13e +0, 34, 34, 1, 152064, 5de1ae2d5b66906ef01190ea8dad606f +0, 35, 35, 1, 152064, d5b5458eee09aac711a2c17b7cfdc40c +0, 36, 36, 1, 152064, 94c08ac166465b9dbfed1cb67eeb3bc3 +0, 37, 37, 1, 152064, 1b1ccbe8316f625b56d94cff1d209434 +0, 38, 38, 1, 152064, 703a29b3efd7513370c8f7ca37730d1f +0, 39, 39, 1, 152064, c15f1fa6c7d595919d11f4142f1a6878 +0, 40, 40, 1, 152064, 8c6ef06f585061acdd66380493ea5c00 +0, 41, 41, 1, 152064, 35771c1c43232ba6ea87bd9d6e638b03 +0, 42, 42, 1, 152064, 01612e4027837fdce2f0ce8cc4a46be7 +0, 43, 43, 1, 152064, 02f1d688df26b1421079a72fe0d62c70 +0, 44, 44, 1, 152064, 7a5c70e39a65101e9622ebeaf62cfac8 +0, 45, 45, 1, 152064, 27af67aecb0500ead2a9a55e6365afb0 +0, 46, 46, 1, 152064, d4105deee590978600eb964e54a6bfa2 +0, 47, 47, 1, 152064, 7aa99b69eb5b2cc85ea99e246d378260 +0, 48, 48, 1, 152064, dd008e25da59d3260d089a9e3f5ca07c +0, 49, 49, 1, 152064, c76ea53f0ac9a0cc5626c0b24d818e33 +0, 50, 50, 1, 152064, 89735f9e0d3be100be93d399472815d5 +0, 51, 51, 1, 152064, e6ceaa7d2df6e7d1f0833cd0efc10762 +0, 52, 52, 1, 152064, 619768d16aed503750e36e6ad1e7da49 +0, 53, 53, 1, 152064, b0a262a526be1363c1cdae34cb963500 +0, 54, 54, 1, 152064, 367f1f0f8e7f16b60d579611705bdaf7 +0, 55, 55, 1, 152064, 32013ef82c20af9a5701ac822e758995 +0, 56, 56, 1, 152064, ed37bcd10044179ff15313ac638a6cb9 +0, 57, 57, 1, 152064, 7f396f585d454a828949a82994c07e55 +0, 58, 58, 1, 152064, 203cd9b81f324784f2d06ae5596cc141 +0, 59, 59, 1, 152064, c81977bf1603b3889285125e8fa869ab +0, 60, 60, 1, 152064, a915aac53d793ff7af3c6c073a22ab4a +0, 61, 61, 1, 152064, e100fbd898f4263eadf11f9c48b16154 +0, 62, 62, 1, 152064, 83a6ddeba2a921a8c30ce4186ae85171 +0, 63, 63, 1, 152064, ec3d156b338d5ed1c73467ba827780eb +0, 64, 64, 1, 152064, aca73a9b00ca3e79a6915f0af8ea21c3 +0, 65, 65, 1, 152064, 8575798a21a4417f368525b193b1b91b +0, 66, 66, 1, 152064, d149f32e2f7ac054d70525f2a6a95eb7 +0, 67, 67, 1, 152064, 86afd4fc9c7daaa3493e7b3690f6cfd3 +0, 68, 68, 1, 152064, 5d9e18798bb214ddf1db5b52596f564c +0, 69, 69, 1, 152064, 7dc13fe68442967746a29a83b460aacd +0, 70, 70, 1, 152064, cc53daafdf5123591c23ae81098c1910 +0, 71, 71, 1, 152064, 3e67307e26dcfc3a3670b605e2807e8d +0, 72, 72, 1, 152064, 204a839741780015879f69e5d1a14ee9 +0, 73, 73, 1, 152064, c2190591032c3a78271565a2ef2b775e +0, 74, 74, 1, 152064, 3e998a8508082402bd8fb3f233b54090 +0, 75, 75, 1, 152064, 1a8aa4f4b3762550becdc410ec15aa1e +0, 76, 76, 1, 152064, 8942b68b03d47ad70fdfab7bdd6ba6e3 +0, 77, 77, 1, 152064, 1dc3a0d8f8f9e21838a3076d37f7440e +0, 78, 78, 1, 152064, b741149b65ab4d546589ddd86eab0974 +0, 79, 79, 1, 152064, ae613ac4352122303830630aa1659bf3 +0, 80, 80, 1, 152064, 9d63f03904c4ba2d6ba9f5064fb876c0 +0, 81, 81, 1, 152064, 558613ee2d0067463955a3e0ad53300c +0, 82, 82, 1, 152064, b7dc3958e008647203699ba33eee87fa +0, 83, 83, 1, 152064, edaa3e3518609d3e74992333a82e7112 +0, 84, 84, 1, 152064, 52a6a70676e436a33ee895d84ad596bc +0, 85, 85, 1, 152064, 0e2a16eb0f92f36a8850ef1bf0036666 +0, 86, 86, 1, 152064, ae7a1bbd95a3720abe058188332c23d5 +0, 87, 87, 1, 152064, b5a96ba8cdd239f71ea3b8ba9dff2d5b +0, 88, 88, 1, 152064, 779ddc0e67b4ae2680b2cbcf7677c455 +0, 89, 89, 1, 152064, d21d0d06a337c3f15a0a14bfc690314f +0, 90, 90, 1, 152064, ad8dbde040a9d7e908b378b6ff239197 +0, 91, 91, 1, 152064, 558f727ae629c902aacec1adde0b93bf +0, 92, 92, 1, 152064, c1eb3c2cad922e3485a1dae690fa30bc +0, 93, 93, 1, 152064, 0070fda686af92eaca687066ae74c31a +0, 94, 94, 1, 152064, 363328969fd103a7860e109267211547 +0, 95, 95, 1, 152064, 2def2821815115bb3c0574c686c68231 +0, 96, 96, 1, 152064, 08c93e6efc9148b1903dc5bbb999594d +0, 97, 97, 1, 152064, 7611bd388d2ca03b2bbe0b8659cc15f5 +0, 98, 98, 1, 152064, 8f41948219f2366883896f51b208a93a +0, 99, 99, 1, 152064, efa7e5d74dbdff7cdca512c0abf7e0cd +0, 100, 100, 1, 152064, 9764d3ab383ef0964149f1e22376a8c6 +0, 101, 101, 1, 152064, c6c28e349ca4dc37d5862419e35f0786 +0, 102, 102, 1, 152064, 7a4a7315a5c4b76f8ee4704a48ec9f4d +0, 103, 103, 1, 152064, f3336a5107afcf7a797826c9bfa791d2 +0, 104, 104, 1, 152064, ef25146735a0250b737a359bd29c35fd +0, 105, 105, 1, 152064, 8b0979747f36694dd0f9d16c545f777b +0, 106, 106, 1, 152064, 23911162849aedca0136528e30784c2f +0, 107, 107, 1, 152064, 8390350c4d3065e52ba42189019889a4 +0, 108, 108, 1, 152064, 228a4f65158409f984d334e80cabe978 +0, 109, 109, 1, 152064, 3eb67bba80c7bbea6cce099f666a2ede +0, 110, 110, 1, 152064, 437966de7c15a11fdcea5c544204a0f4 +0, 111, 111, 1, 152064, bbfbb8008f1e7b002aab021082bf59c6 +0, 112, 112, 1, 152064, 388b81b3b7d6efa9e1fe2481308f23c7 +0, 113, 113, 1, 152064, efabd9424c4541c04eed3c8ba95d0596 +0, 114, 114, 1, 152064, 86ad8a0772ffaca7c23284625a7cbcee +0, 115, 115, 1, 152064, 9d7988d07bcfd36442fbf2d8e5e101f4 +0, 116, 116, 1, 152064, 80770b3dbf125e02167e79324ad1cd91 +0, 117, 117, 1, 152064, b9479f64fe9fbd98ae9abab1a6312ae8 +0, 118, 118, 1, 152064, d6c209d64d1d7126a7ec034bea9ff90d +0, 119, 119, 1, 152064, 14f93282da9b72f6b5ad48a7adbe123e +0, 120, 120, 1, 152064, 12a54bf2592e25a18c706164b6ec101d +0, 121, 121, 1, 152064, cb352e89039a04a8f16620107e8d9014 +0, 122, 122, 1, 152064, c8e116f3f3366f50bf70a51cc93be7e7 +0, 123, 123, 1, 152064, 8d7eb47f6b233a92151f2775d1978f0e +0, 124, 124, 1, 152064, 5cfab1f17edf8a84f34a349d6794f032 +0, 125, 125, 1, 152064, 6ebec5f5e1fb1edc4063be265314ad8f +0, 126, 126, 1, 152064, a49875c669e23e24ea17f2de189b21d3 +0, 127, 127, 1, 152064, 5c8d5b347ecccecb0bae9745ac6b45f0 +0, 128, 128, 1, 152064, b6dc1815dc30eaaab5df0554f0a5b56e +0, 129, 129, 1, 152064, 509a0ac070524f8c719a3c4d79fb76e5 +0, 130, 130, 1, 152064, ad13dcf1552d26a87d17101036b45c52 +0, 131, 131, 1, 152064, 2620e7fb141063ca4fbad4439f32dae7 +0, 132, 132, 1, 152064, 18d34d054c41a1423d969344af80fac4 +0, 133, 133, 1, 152064, 8599dccbb02cc59563b5afea6c193acd +0, 134, 134, 1, 152064, b53d42b366b8d7cbb4af52f8840630e4 +0, 135, 135, 1, 152064, 11747b80047ff5599dda6f9f0417478e +0, 136, 136, 1, 152064, 10f68820f282a0e89b58a1657bcf6fa8 +0, 137, 137, 1, 152064, ca0f0c0ca11c703f16cf190d52971a2a +0, 138, 138, 1, 152064, b6fb4d3ce986c503cac8ae21ad72313b +0, 139, 139, 1, 152064, 194b3f779eaddadf563b447b7b579d3c +0, 140, 140, 1, 152064, 6c248256e677d7d374b2ca2cc42f58e7 +0, 141, 141, 1, 152064, dd358dcc4e3f750b2bcc96db0c3293c7 +0, 142, 142, 1, 152064, eb0d082f192d46bc4188b892e2812eb6 +0, 143, 143, 1, 152064, f539f619df45340677c6a80db65f1795 +0, 144, 144, 1, 152064, 9d274ccc0a6e7bc52065f6d413b82d2f +0, 145, 145, 1, 152064, 18b950f15cc925d25e3ce823dea4c265 +0, 146, 146, 1, 152064, 38573a7cdfc3fdd7110ed6682d57e2b6 +0, 147, 147, 1, 152064, e41c4605b77dc0286314b318865375b7 +0, 148, 148, 1, 152064, 5080b5b6bc48d21c6445b98f42ae72e8 +0, 149, 149, 1, 152064, afc35d2de20b972087e40dbb597c888a diff --git a/tests/ref/fate/mss1 b/tests/ref/fate/mss1 new file mode 100644 index 0000000..bb1f37c --- /dev/null +++ b/tests/ref/fate/mss1 @@ -0,0 +1,137 @@ +#tb 0: 1/1000 +0, 291, 291, 0, 2359296, 0x38a6293f +0, 851, 851, 0, 2359296, 0x307ed2e0 +0, 1416, 1416, 0, 2359296, 0x8947e5d5 +0, 1961, 1961, 0, 2359296, 0xb5e92959 +0, 2346, 2346, 0, 2359296, 0x674a2218 +0, 2884, 2884, 0, 2359296, 0x83382cd6 +0, 3414, 3414, 0, 2359296, 0x5d5502ee +0, 3942, 3942, 0, 2359296, 0x031fa84e +0, 4464, 4464, 0, 2359296, 0x10ff2a13 +0, 4992, 4992, 0, 2359296, 0x2b203e2f +0, 5536, 5536, 0, 2359296, 0x6b4d8a08 +0, 6064, 6064, 0, 2359296, 0x839a632f +0, 6599, 6599, 0, 2359296, 0x5d0b70e1 +0, 7128, 7128, 0, 2359296, 0xcb0cec73 +0, 7659, 7659, 0, 2359296, 0x23951182 +0, 8736, 8736, 0, 2359296, 0x63cf93cd +0, 9278, 9278, 0, 2359296, 0x6f0a93cd +0, 10354, 10354, 0, 2359296, 0x360adb85 +0, 10883, 10883, 0, 2359296, 0x6f0a93cd +0, 11420, 11420, 0, 2359296, 0x2472fe54 +0, 12483, 12483, 0, 2359296, 0x5f2890a6 +0, 13016, 13016, 0, 2359296, 0x2f67d126 +0, 13540, 13540, 0, 2359296, 0x2a56896e +0, 14071, 14071, 0, 2359296, 0x3f148647 +0, 14593, 14593, 0, 2359296, 0xaee8923b +0, 15093, 15093, 0, 2359296, 0xa964923b +0, 15594, 15594, 0, 2359296, 0xa1cb8647 +0, 16628, 16628, 0, 2359296, 0xdce78647 +0, 17128, 17128, 0, 2359296, 0x07d4923b +0, 17635, 17635, 0, 2359296, 0xbb368647 +0, 18687, 18687, 0, 2359296, 0xd18cf0ce +0, 19208, 19208, 0, 2359296, 0xb821f0ce +0, 19757, 19757, 0, 2359296, 0xb52cf0ce +0, 20731, 20731, 0, 2359296, 0x7a10f0ce +0, 21737, 21737, 0, 2359296, 0x556af0ce +0, 22259, 22259, 0, 2359296, 0x8d513895 +0, 22815, 22815, 0, 2359296, 0x8c3508c5 +0, 23887, 23887, 0, 2359296, 0xb33808c5 +0, 24392, 24392, 0, 2359296, 0x8d513895 +0, 25478, 25478, 0, 2359296, 0xb33808c5 +0, 26028, 26028, 0, 2359296, 0x8d513895 +0, 28119, 28119, 0, 2359296, 0xb33808c5 +0, 28658, 28658, 0, 2359296, 0x8d513895 +0, 29187, 29187, 0, 2359296, 0xb33808c5 +0, 29720, 29720, 0, 2359296, 0x8d513895 +0, 30235, 30235, 0, 2359296, 0xb33808c5 +0, 30768, 30768, 0, 2359296, 0x8d513895 +0, 31292, 31292, 0, 2359296, 0x540d5a57 +0, 32360, 32360, 0, 2359296, 0xb7e3bee4 +0, 32888, 32888, 0, 2359296, 0xe10206ab +0, 33887, 33887, 0, 2359296, 0x38716431 +0, 34389, 34389, 0, 2359296, 0xc15bb1e3 +0, 35417, 35417, 0, 2359296, 0xf97f167f +0, 36418, 36418, 0, 2359296, 0x98e55e37 +0, 36946, 36946, 0, 2359296, 0x5f875136 +0, 37472, 37472, 0, 2359296, 0xfa1d3e3b +0, 38540, 38540, 0, 2359296, 0xdbb785f3 +0, 39079, 39079, 0, 2359296, 0xfa1d3e3b +0, 39607, 39607, 0, 2359296, 0xfa650277 +0, 40678, 40678, 0, 2359296, 0x22671f4c +0, 41212, 41212, 0, 2359296, 0x22671f4c +0, 41736, 41736, 0, 2359296, 0x67463924 +0, 42286, 42286, 0, 2359296, 0x53fb2b16 +0, 42819, 42819, 0, 2359296, 0xe28a1221 +0, 43846, 43846, 0, 2359296, 0xac6df810 +0, 44357, 44357, 0, 2359296, 0xd8a4bc4c +0, 44867, 44867, 0, 2359296, 0xe3dfbc4c +0, 45399, 45399, 0, 2359296, 0xe6eef5f6 +0, 45920, 45920, 0, 2359296, 0x635c0bd3 +0, 47003, 47003, 0, 2359296, 0x18a3538b +0, 47536, 47536, 0, 2359296, 0xbab6e6db +0, 48063, 48063, 0, 2359296, 0x83379929 +0, 49128, 49128, 0, 2359296, 0x85ede0e1 +0, 49646, 49646, 0, 2359296, 0x83379929 +0, 50200, 50200, 0, 2359296, 0x85ede0e1 +0, 51221, 51221, 0, 2359296, 0x85ede0e1 +0, 51737, 51737, 0, 2359296, 0xf9dab111 +0, 52836, 52836, 0, 2359296, 0x85ede0e1 +0, 53362, 53362, 0, 2359296, 0xf9dab111 +0, 53851, 53851, 0, 2359296, 0x85ede0e1 +0, 54826, 54826, 0, 2359296, 0xf9dab111 +0, 55870, 55870, 0, 2359296, 0x85ede0e1 +0, 58473, 58473, 0, 2359296, 0xf9dab111 +0, 58978, 58978, 0, 2359296, 0x85ede0e1 +0, 59461, 59461, 0, 2359296, 0xf9dab111 +0, 60369, 60369, 0, 2359296, 0x85ede0e1 +0, 61237, 61237, 0, 2359296, 0x12d62c88 +0, 62303, 62303, 0, 2359296, 0x9686dec7 +0, 63378, 63378, 0, 2359296, 0x34f15741 +0, 63884, 63884, 0, 2359296, 0x8e85fc7f +0, 64409, 64409, 0, 2359296, 0x3328a7c6 +0, 64940, 64940, 0, 2359296, 0x6ba6ef7e +0, 66011, 66011, 0, 2359296, 0x97dfd362 +0, 67096, 67096, 0, 2359296, 0x9a09da3f +0, 67629, 67629, 0, 2359296, 0xa6b19f5e +0, 68694, 68694, 0, 2359296, 0x3d8003fa +0, 69732, 69732, 0, 2359296, 0xa006925d +0, 70230, 70230, 0, 2359296, 0xb9a8f6ea +0, 71170, 71170, 0, 2359296, 0x0884f7cd +0, 71665, 71665, 0, 2359296, 0x13bff7cd +0, 72198, 72198, 0, 2359296, 0x26c2c013 +0, 73838, 73838, 0, 2359296, 0x30e9e43d +0, 74830, 74830, 0, 2359296, 0x3bc348d9 +0, 75371, 75371, 0, 2359296, 0x30e9e43d +0, 75886, 75886, 0, 2359296, 0x3097fb18 +0, 76433, 76433, 0, 2359296, 0x20f1ad66 +0, 76962, 76962, 0, 2359296, 0xd668ad66 +0, 77492, 77492, 0, 2359296, 0xea0db95a +0, 78021, 78021, 0, 2359296, 0xf6ebad66 +0, 78565, 78565, 0, 2359296, 0x95fbad66 +0, 79099, 79099, 0, 2359296, 0x1479b95a +0, 79635, 79635, 0, 2359296, 0x4046ad66 +0, 80150, 80150, 0, 2359296, 0xf7a6b95a +0, 80684, 80684, 0, 2359296, 0xdf47ad66 +0, 81662, 81662, 0, 2359296, 0x60c9ad66 +0, 82153, 82153, 0, 2359296, 0x60c9ad66 +0, 82695, 82695, 0, 2359296, 0x3d75b95a +0, 83243, 83243, 0, 2359296, 0x0b14ad66 +0, 84322, 84322, 0, 2359296, 0x23b9968b +0, 84828, 84828, 0, 2359296, 0x76d87fb0 +0, 85908, 85908, 0, 2359296, 0xe5c6c65b +0, 86456, 86456, 0, 2359296, 0x26fdd24f +0, 86957, 86957, 0, 2359296, 0x6f8ec65b +0, 87483, 87483, 0, 2359296, 0xc543c65b +0, 88525, 88525, 0, 2359296, 0x0fccc65b +0, 89022, 89022, 0, 2359296, 0xfdf2d24f +0, 89546, 89546, 0, 2359296, 0x1c35c65b +0, 90080, 90080, 0, 2359296, 0x71eac65b +0, 90611, 90611, 0, 2359296, 0xa5eec65b +0, 91155, 91155, 0, 2359296, 0xf068c65b +0, 91686, 91686, 0, 2359296, 0xb9310e22 +0, 92183, 92183, 0, 2359296, 0x5430de43 +0, 92739, 92739, 0, 2359296, 0x7b33de43 +0, 93815, 93815, 0, 2359296, 0xb9310e22 +0, 94351, 94351, 0, 2359296, 0x5fc1bd64 +0, 94875, 94875, 0, 2359296, 0x5185052b diff --git a/tests/ref/fate/mts2 b/tests/ref/fate/mts2 new file mode 100644 index 0000000..0e82f19 --- /dev/null +++ b/tests/ref/fate/mts2 @@ -0,0 +1,129 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 2995632, 0xd99bcd57 +0, 202, 202, 0, 2995632, 0xd99bcd57 +0, 268, 268, 0, 2995632, 0xd99bcd57 +0, 334, 334, 0, 2995632, 0xd99bcd57 +0, 399, 399, 0, 2995632, 0xd99bcd57 +0, 466, 466, 0, 2995632, 0xd99bcd57 +0, 532, 532, 0, 2995632, 0xd99bcd57 +0, 598, 598, 0, 2995632, 0xd99bcd57 +0, 665, 665, 0, 2995632, 0xd99bcd57 +0, 731, 731, 0, 2995632, 0xd99bcd57 +0, 798, 798, 0, 2995632, 0xd99bcd57 +0, 863, 863, 0, 2995632, 0xd99bcd57 +0, 929, 929, 0, 2995632, 0xd99bcd57 +0, 996, 996, 0, 2995632, 0xd99bcd57 +0, 1061, 1061, 0, 2995632, 0xd99bcd57 +0, 1127, 1127, 0, 2995632, 0xd99bcd57 +0, 1192, 1192, 0, 2995632, 0xd99bcd57 +0, 1258, 1258, 0, 2995632, 0xd99bcd57 +0, 1323, 1323, 0, 2995632, 0xd99bcd57 +0, 1389, 1389, 0, 2995632, 0xd99bcd57 +0, 1457, 1457, 0, 2995632, 0xd99bcd57 +0, 1522, 1522, 0, 2995632, 0xd99bcd57 +0, 1589, 1589, 0, 2995632, 0xd99bcd57 +0, 1655, 1655, 0, 2995632, 0xd99bcd57 +0, 1721, 1721, 0, 2995632, 0xd99bcd57 +0, 1788, 1788, 0, 2995632, 0xd99bcd57 +0, 1855, 1855, 0, 2995632, 0xd99bcd57 +0, 1922, 1922, 0, 2995632, 0xd99bcd57 +0, 1987, 1987, 0, 2995632, 0xbeb35375 +0, 2054, 2054, 0, 2995632, 0xbeb35375 +0, 2120, 2120, 0, 2995632, 0xbeb35375 +0, 2185, 2185, 0, 2995632, 0xbeb35375 +0, 2252, 2252, 0, 2995632, 0xbeb35375 +0, 2318, 2318, 0, 2995632, 0xbeb35375 +0, 2383, 2383, 0, 2995632, 0xbeb35375 +0, 2452, 2452, 0, 2995632, 0xcaae4108 +0, 2517, 2517, 0, 2995632, 0xcaae4108 +0, 2584, 2584, 0, 2995632, 0xcaae4108 +0, 2650, 2650, 0, 2995632, 0xcaae4108 +0, 2715, 2715, 0, 2995632, 0xcaae4108 +0, 2782, 2782, 0, 2995632, 0xcaae4108 +0, 2849, 2849, 0, 2995632, 0x8aa38ce0 +0, 2915, 2915, 0, 2995632, 0x8aa38ce0 +0, 2981, 2981, 0, 2995632, 0x8aa38ce0 +0, 3048, 3048, 0, 2995632, 0x8aa38ce0 +0, 3114, 3114, 0, 2995632, 0x8aa38ce0 +0, 3179, 3179, 0, 2995632, 0x8aa38ce0 +0, 3246, 3246, 0, 2995632, 0x05885d30 +0, 3311, 3311, 0, 2995632, 0xd3eee8e8 +0, 3378, 3378, 0, 2995632, 0x0b82ea84 +0, 3444, 3444, 0, 2995632, 0x0b82ea84 +0, 3510, 3510, 0, 2995632, 0x19f32c5e +0, 3576, 3576, 0, 2995632, 0x19f32c5e +0, 3642, 3642, 0, 2995632, 0x19f32c5e +0, 3710, 3710, 0, 2995632, 0x478b455c +0, 3777, 3777, 0, 2995632, 0x08256940 +0, 3843, 3843, 0, 2995632, 0x08256940 +0, 3909, 3909, 0, 2995632, 0x08256940 +0, 3977, 3977, 0, 2995632, 0x188c88fc +0, 4044, 4044, 0, 2995632, 0x7ff65403 +0, 4117, 4117, 0, 2995632, 0xef8686db +0, 4186, 4186, 0, 2995632, 0x8ca34321 +0, 4252, 4252, 0, 2995632, 0x722e18d1 +0, 4317, 4317, 0, 2995632, 0x722e18d1 +0, 4383, 4383, 0, 2995632, 0x0f0c1574 +0, 4449, 4449, 0, 2995632, 0x0f0c1574 +0, 4515, 4515, 0, 2995632, 0x0f0c1574 +0, 4582, 4582, 0, 2995632, 0x440c5180 +0, 4647, 4647, 0, 2995632, 0x440c5180 +0, 4714, 4714, 0, 2995632, 0x440c5180 +0, 4781, 4781, 0, 2995632, 0x440c5180 +0, 4846, 4846, 0, 2995632, 0x440c5180 +0, 4912, 4912, 0, 2995632, 0x440c5180 +0, 4977, 4977, 0, 2995632, 0x440c5180 +0, 5044, 5044, 0, 2995632, 0x440c5180 +0, 5110, 5110, 0, 2995632, 0x50b9656c +0, 5176, 5176, 0, 2995632, 0x50b9656c +0, 5243, 5243, 0, 2995632, 0x50b9656c +0, 5309, 5309, 0, 2995632, 0x50b9656c +0, 5376, 5376, 0, 2995632, 0x29c17deb +0, 5442, 5442, 0, 2995632, 0x6f868d8a +0, 5508, 5508, 0, 2995632, 0x2ea88d55 +0, 5575, 5575, 0, 2995632, 0xe0208c8d +0, 5641, 5641, 0, 2995632, 0x25084a8f +0, 5709, 5709, 0, 2995632, 0xd0e3bddd +0, 5776, 5776, 0, 2995632, 0xc9c3e0ff +0, 5842, 5842, 0, 2995632, 0xcbefe0b1 +0, 5911, 5911, 0, 2995632, 0xd7b0e00d +0, 5977, 5977, 0, 2995632, 0x2dc9dff8 +0, 6044, 6044, 0, 2995632, 0x1ea9a835 +0, 6158, 6158, 0, 2995632, 0x9be91cc7 +0, 6225, 6225, 0, 2995632, 0x27c31d09 +0, 6292, 6292, 0, 2995632, 0xc4d65c0c +0, 6358, 6358, 0, 2995632, 0xc4d65c0c +0, 6423, 6423, 0, 2995632, 0xc4d65c0c +0, 6490, 6490, 0, 2995632, 0xc4d65c0c +0, 6556, 6556, 0, 2995632, 0xc4d65c0c +0, 6623, 6623, 0, 2995632, 0xceb7bde7 +0, 6689, 6689, 0, 2995632, 0xfbace8b0 +0, 6754, 6754, 0, 2995632, 0x18ab6b35 +0, 6821, 6821, 0, 2995632, 0x18ab6b35 +0, 6887, 6887, 0, 2995632, 0x18ab6b35 +0, 6954, 6954, 0, 2995632, 0x18ab6b35 +0, 7019, 7019, 0, 2995632, 0x18ab6b35 +0, 7084, 7084, 0, 2995632, 0x18ab6b35 +0, 7150, 7150, 0, 2995632, 0x18ab6b35 +0, 7215, 7215, 0, 2995632, 0x18ab6b35 +0, 7282, 7282, 0, 2995632, 0x18ab6b35 +0, 7348, 7348, 0, 2995632, 0x18ab6b35 +0, 7415, 7415, 0, 2995632, 0x18ab6b35 +0, 7480, 7480, 0, 2995632, 0x18ab6b35 +0, 7545, 7545, 0, 2995632, 0x18ab6b35 +0, 7612, 7612, 0, 2995632, 0x18ab6b35 +0, 7678, 7678, 0, 2995632, 0x18ab6b35 +0, 7745, 7745, 0, 2995632, 0x18ab6b35 +0, 7810, 7810, 0, 2995632, 0x18ab6b35 +0, 7876, 7876, 0, 2995632, 0x18ab6b35 +0, 7943, 7943, 0, 2995632, 0x18ab6b35 +0, 8009, 8009, 0, 2995632, 0x18ab6b35 +0, 8076, 8076, 0, 2995632, 0x18ab6b35 +0, 8141, 8141, 0, 2995632, 0x18ab6b35 +0, 8206, 8206, 0, 2995632, 0x18ab6b35 +0, 8273, 8273, 0, 2995632, 0x18ab6b35 +0, 8339, 8339, 0, 2995632, 0x18ab6b35 +0, 8406, 8406, 0, 2995632, 0x18ab6b35 +0, 8472, 8472, 0, 2995632, 0x18ab6b35 +0, 8539, 8539, 0, 2995632, 0x18ab6b35 +0, 8605, 8605, 0, 2995632, 0x68f6d0e7 diff --git a/tests/ref/fate/mxf-demux b/tests/ref/fate/mxf-demux index 426afae..b4cd6f9 100644 --- a/tests/ref/fate/mxf-demux +++ b/tests/ref/fate/mxf-demux @@ -1,99 +1,99 @@ #tb 0: 1/25 #tb 1: 1/8000 -0, 0, -9223372036854775808, 1, 8468, 0xc0855553 +0, 0, 0, 1, 8468, 0xc0855553 1, 0, 0, 16000, 32000, 0x479155e6 -0, 1, -9223372036854775808, 1, 3814, 0xa10783b4 -0, 2, -9223372036854775808, 1, 3747, 0xb7bf6973 -0, 3, -9223372036854775808, 1, 3705, 0x5462a600 -0, 4, -9223372036854775808, 1, 3704, 0x1e564943 -0, 5, -9223372036854775808, 1, 3760, 0x10464b9a -0, 6, -9223372036854775808, 1, 3799, 0xd41d6dcf -0, 7, -9223372036854775808, 1, 3832, 0x5cf6999e -0, 8, -9223372036854775808, 1, 3778, 0xe5fc7b9e -0, 9, -9223372036854775808, 1, 38193, 0xd34e5dd4 -0, 10, -9223372036854775808, 1, 8520, 0x2a203e68 -0, 11, -9223372036854775808, 1, 3832, 0xe4c4b2fe -0, 12, -9223372036854775808, 1, 3787, 0x0cf95fee -0, 13, -9223372036854775808, 1, 3766, 0x9e019d14 -0, 14, -9223372036854775808, 1, 3785, 0x0ea9ae75 -0, 15, -9223372036854775808, 1, 3703, 0x11d349ff -0, 16, -9223372036854775808, 1, 3731, 0x5cf358ef -0, 17, -9223372036854775808, 1, 3785, 0x01c8962f -0, 18, -9223372036854775808, 1, 3741, 0xb2c47d53 -0, 19, -9223372036854775808, 1, 38150, 0x08fa1f55 -0, 20, -9223372036854775808, 1, 8487, 0x0c234b9a -0, 21, -9223372036854775808, 1, 3791, 0x831192ef -0, 22, -9223372036854775808, 1, 3612, 0x598944fb -0, 23, -9223372036854775808, 1, 3710, 0xccbb711a -0, 24, -9223372036854775808, 1, 3864, 0x4385966e -0, 25, -9223372036854775808, 1, 3919, 0x24e2abc3 -0, 26, -9223372036854775808, 1, 3777, 0x210c6219 -0, 27, -9223372036854775808, 1, 3811, 0x23bf68c2 -0, 28, -9223372036854775808, 1, 3802, 0x52688862 -0, 29, -9223372036854775808, 1, 38027, 0x3d5aa8b9 -0, 30, -9223372036854775808, 1, 8333, 0x617de950 -0, 31, -9223372036854775808, 1, 3831, 0x13fad8fc -0, 32, -9223372036854775808, 1, 3719, 0xbc317470 -0, 33, -9223372036854775808, 1, 3761, 0xeac460b6 -0, 34, -9223372036854775808, 1, 3637, 0x27d64b32 -0, 35, -9223372036854775808, 1, 3666, 0xf0f700a5 -0, 36, -9223372036854775808, 1, 3788, 0x1c4662a8 -0, 37, -9223372036854775808, 1, 3960, 0xef6b9e99 -0, 38, -9223372036854775808, 1, 3793, 0x3a6ca832 -0, 39, -9223372036854775808, 1, 38312, 0xce1317cc -0, 40, -9223372036854775808, 1, 8548, 0x4ca944d4 -0, 41, -9223372036854775808, 1, 3866, 0x4e85bf0f -0, 42, -9223372036854775808, 1, 3644, 0x030338e5 -0, 43, -9223372036854775808, 1, 3634, 0xa95f4512 -0, 44, -9223372036854775808, 1, 3925, 0x7583ba86 -0, 45, -9223372036854775808, 1, 3675, 0x979f423f -0, 46, -9223372036854775808, 1, 3703, 0x11375f7a -0, 47, -9223372036854775808, 1, 3705, 0xb7de5d16 -0, 48, -9223372036854775808, 1, 3688, 0x1db45852 -0, 49, -9223372036854775808, 1, 38412, 0x2ee26a63 -0, 50, -9223372036854775808, 1, 8385, 0x0bc20a27 +0, 1, 1, 1, 3814, 0xa10783b4 +0, 2, 2, 1, 3747, 0xb7bf6973 +0, 3, 3, 1, 3705, 0x5462a600 +0, 4, 4, 1, 3704, 0x1e564943 +0, 5, 5, 1, 3760, 0x10464b9a +0, 6, 6, 1, 3799, 0xd41d6dcf +0, 7, 7, 1, 3832, 0x5cf6999e +0, 8, 8, 1, 3778, 0xe5fc7b9e +0, 9, 9, 1, 38193, 0xd34e5dd4 +0, 10, 10, 1, 8520, 0x2a203e68 +0, 11, 11, 1, 3832, 0xe4c4b2fe +0, 12, 12, 1, 3787, 0x0cf95fee +0, 13, 13, 1, 3766, 0x9e019d14 +0, 14, 14, 1, 3785, 0x0ea9ae75 +0, 15, 15, 1, 3703, 0x11d349ff +0, 16, 16, 1, 3731, 0x5cf358ef +0, 17, 17, 1, 3785, 0x01c8962f +0, 18, 18, 1, 3741, 0xb2c47d53 +0, 19, 19, 1, 38150, 0x08fa1f55 +0, 20, 20, 1, 8487, 0x0c234b9a +0, 21, 21, 1, 3791, 0x831192ef +0, 22, 22, 1, 3612, 0x598944fb +0, 23, 23, 1, 3710, 0xccbb711a +0, 24, 24, 1, 3864, 0x4385966e +0, 25, 25, 1, 3919, 0x24e2abc3 +0, 26, 26, 1, 3777, 0x210c6219 +0, 27, 27, 1, 3811, 0x23bf68c2 +0, 28, 28, 1, 3802, 0x52688862 +0, 29, 29, 1, 38027, 0x3d5aa8b9 +0, 30, 30, 1, 8333, 0x617de950 +0, 31, 31, 1, 3831, 0x13fad8fc +0, 32, 32, 1, 3719, 0xbc317470 +0, 33, 33, 1, 3761, 0xeac460b6 +0, 34, 34, 1, 3637, 0x27d64b32 +0, 35, 35, 1, 3666, 0xf0f700a5 +0, 36, 36, 1, 3788, 0x1c4662a8 +0, 37, 37, 1, 3960, 0xef6b9e99 +0, 38, 38, 1, 3793, 0x3a6ca832 +0, 39, 39, 1, 38312, 0xce1317cc +0, 40, 40, 1, 8548, 0x4ca944d4 +0, 41, 41, 1, 3866, 0x4e85bf0f +0, 42, 42, 1, 3644, 0x030338e5 +0, 43, 43, 1, 3634, 0xa95f4512 +0, 44, 44, 1, 3925, 0x7583ba86 +0, 45, 45, 1, 3675, 0x979f423f +0, 46, 46, 1, 3703, 0x11375f7a +0, 47, 47, 1, 3705, 0xb7de5d16 +0, 48, 48, 1, 3688, 0x1db45852 +0, 49, 49, 1, 38412, 0x2ee26a63 +0, 50, 50, 1, 8385, 0x0bc20a27 1, 16000, 16000, 16000, 32000, 0x8f7e5009 -0, 51, -9223372036854775808, 1, 3733, 0xa3e2a9a0 -0, 52, -9223372036854775808, 1, 3773, 0x27769caa -0, 53, -9223372036854775808, 1, 3670, 0xc8335e98 -0, 54, -9223372036854775808, 1, 3596, 0xd6512fb0 -0, 55, -9223372036854775808, 1, 3579, 0xa621fbc2 -0, 56, -9223372036854775808, 1, 3641, 0x2f4f46ca -0, 57, -9223372036854775808, 1, 3686, 0x0a92385a -0, 58, -9223372036854775808, 1, 3672, 0xe65137b9 -0, 59, -9223372036854775808, 1, 39065, 0xc723bf8b -0, 60, -9223372036854775808, 1, 8611, 0x5d177f40 -0, 61, -9223372036854775808, 1, 3758, 0x33d59966 -0, 62, -9223372036854775808, 1, 3674, 0x54f37902 -0, 63, -9223372036854775808, 1, 3615, 0xa0f045fa -0, 64, -9223372036854775808, 1, 3719, 0x41cf93ff -0, 65, -9223372036854775808, 1, 3757, 0x3a1b7e8f -0, 66, -9223372036854775808, 1, 3762, 0xe7f9714d -0, 67, -9223372036854775808, 1, 3738, 0x8121805b -0, 68, -9223372036854775808, 1, 3733, 0x13e262db -0, 69, -9223372036854775808, 1, 38433, 0x3d58c500 -0, 70, -9223372036854775808, 1, 8410, 0xa4f7fd2e -0, 71, -9223372036854775808, 1, 3711, 0x0e112d3c -0, 72, -9223372036854775808, 1, 3692, 0xb46574b2 -0, 73, -9223372036854775808, 1, 3563, 0xad43343d -0, 74, -9223372036854775808, 1, 3613, 0x5cd85c4f -0, 75, -9223372036854775808, 1, 3653, 0xe15a2853 -0, 76, -9223372036854775808, 1, 3684, 0x9ddd58cb -0, 77, -9223372036854775808, 1, 3256, 0xd7f89f2e -0, 78, -9223372036854775808, 1, 3698, 0x2b82624a -0, 79, -9223372036854775808, 1, 39520, 0xd3f2b7c5 -0, 80, -9223372036854775808, 1, 8493, 0x163559be -0, 81, -9223372036854775808, 1, 3719, 0x6fa0916f -0, 82, -9223372036854775808, 1, 3655, 0xa9233de1 -0, 83, -9223372036854775808, 1, 3684, 0xa6125737 -0, 84, -9223372036854775808, 1, 3688, 0xa9da6686 -0, 85, -9223372036854775808, 1, 3685, 0x674d634e -0, 86, -9223372036854775808, 1, 3677, 0x7a85535d -0, 87, -9223372036854775808, 1, 3666, 0xce3600a2 -0, 88, -9223372036854775808, 1, 3837, 0x3a7090e1 -0, 89, -9223372036854775808, 1, 38696, 0x12c59cd2 -0, 90, -9223372036854775808, 1, 8022, 0xd343433f -0, 91, -9223372036854775808, 1, 5157, 0x440c14e5 -0, 92, -9223372036854775808, 1, 5003, 0xf8e1daff -0, 93, -9223372036854775808, 1, 4954, 0x89866344 -0, 94, -9223372036854775808, 1, 53664, 0xeb0c4c42 +0, 51, 51, 1, 3733, 0xa3e2a9a0 +0, 52, 52, 1, 3773, 0x27769caa +0, 53, 53, 1, 3670, 0xc8335e98 +0, 54, 54, 1, 3596, 0xd6512fb0 +0, 55, 55, 1, 3579, 0xa621fbc2 +0, 56, 56, 1, 3641, 0x2f4f46ca +0, 57, 57, 1, 3686, 0x0a92385a +0, 58, 58, 1, 3672, 0xe65137b9 +0, 59, 59, 1, 39065, 0xc723bf8b +0, 60, 60, 1, 8611, 0x5d177f40 +0, 61, 61, 1, 3758, 0x33d59966 +0, 62, 62, 1, 3674, 0x54f37902 +0, 63, 63, 1, 3615, 0xa0f045fa +0, 64, 64, 1, 3719, 0x41cf93ff +0, 65, 65, 1, 3757, 0x3a1b7e8f +0, 66, 66, 1, 3762, 0xe7f9714d +0, 67, 67, 1, 3738, 0x8121805b +0, 68, 68, 1, 3733, 0x13e262db +0, 69, 69, 1, 38433, 0x3d58c500 +0, 70, 70, 1, 8410, 0xa4f7fd2e +0, 71, 71, 1, 3711, 0x0e112d3c +0, 72, 72, 1, 3692, 0xb46574b2 +0, 73, 73, 1, 3563, 0xad43343d +0, 74, 74, 1, 3613, 0x5cd85c4f +0, 75, 75, 1, 3653, 0xe15a2853 +0, 76, 76, 1, 3684, 0x9ddd58cb +0, 77, 77, 1, 3256, 0xd7f89f2e +0, 78, 78, 1, 3698, 0x2b82624a +0, 79, 79, 1, 39520, 0xd3f2b7c5 +0, 80, 80, 1, 8493, 0x163559be +0, 81, 81, 1, 3719, 0x6fa0916f +0, 82, 82, 1, 3655, 0xa9233de1 +0, 83, 83, 1, 3684, 0xa6125737 +0, 84, 84, 1, 3688, 0xa9da6686 +0, 85, 85, 1, 3685, 0x674d634e +0, 86, 86, 1, 3677, 0x7a85535d +0, 87, 87, 1, 3666, 0xce3600a2 +0, 88, 88, 1, 3837, 0x3a7090e1 +0, 89, 89, 1, 38696, 0x12c59cd2 +0, 90, 90, 1, 8022, 0xd343433f +0, 91, 91, 1, 5157, 0x440c14e5 +0, 92, 92, 1, 5003, 0xf8e1daff +0, 93, 93, 1, 4954, 0x89866344 +0, 94, 94, 1, 53664, 0xeb0c4c42 diff --git a/tests/ref/fate/nc-demux b/tests/ref/fate/nc-demux index 1d00f8e..8a3c211 100644 --- a/tests/ref/fate/nc-demux +++ b/tests/ref/fate/nc-demux @@ -1,92 +1,92 @@ #tb 0: 1/100 -0, 0, -9223372036854775808, 1, 19787, 0x75e463f3 -0, 1, -9223372036854775808, 1, 11913, 0x0f429c34 -0, 2, -9223372036854775808, 1, 14225, 0xbd3c704c -0, 3, -9223372036854775808, 1, 10357, 0xbf232393 -0, 4, -9223372036854775808, 1, 9595, 0xf565d39e -0, 5, -9223372036854775808, 1, 9262, 0x2afd6ce0 -0, 6, -9223372036854775808, 1, 12214, 0x6ae81d9b -0, 7, -9223372036854775808, 1, 13920, 0x31b5b307 -0, 8, -9223372036854775808, 1, 10164, 0x141eca4e -0, 9, -9223372036854775808, 1, 9516, 0xd5f2c42b -0, 10, -9223372036854775808, 1, 10006, 0x80850a76 -0, 11, -9223372036854775808, 1, 11791, 0x10bc2dcd -0, 12, -9223372036854775808, 1, 13756, 0xda1fee08 -0, 13, -9223372036854775808, 1, 10452, 0xbb3d62b0 -0, 14, -9223372036854775808, 1, 9171, 0x64ae10f6 -0, 15, -9223372036854775808, 1, 8816, 0x31ad8fcb -0, 16, -9223372036854775808, 1, 13168, 0xea1085ac -0, 17, -9223372036854775808, 1, 12797, 0x25143d22 -0, 18, -9223372036854775808, 1, 11324, 0x3a54b38e -0, 19, -9223372036854775808, 1, 9173, 0x8b2bf552 -0, 20, -9223372036854775808, 1, 9247, 0x2e87226b -0, 21, -9223372036854775808, 1, 14140, 0x1063786c -0, 22, -9223372036854775808, 1, 14437, 0xde123a17 -0, 23, -9223372036854775808, 1, 11938, 0x3f1168f4 -0, 24, -9223372036854775808, 1, 11966, 0xdd6786ec -0, 25, -9223372036854775808, 1, 13213, 0x8ab27c58 -0, 26, -9223372036854775808, 1, 11843, 0x90415d8b -0, 27, -9223372036854775808, 1, 13345, 0x3c0e1793 -0, 28, -9223372036854775808, 1, 9977, 0x74fc7f4b -0, 29, -9223372036854775808, 1, 9158, 0x0b5426a5 -0, 30, -9223372036854775808, 1, 12715, 0x0035d569 -0, 31, -9223372036854775808, 1, 19944, 0xe2887ba8 -0, 32, -9223372036854775808, 1, 12762, 0xb0f17939 -0, 33, -9223372036854775808, 1, 10260, 0x182b27aa -0, 34, -9223372036854775808, 1, 7405, 0x227fe9bf -0, 35, -9223372036854775808, 1, 13317, 0x1a678c62 -0, 36, -9223372036854775808, 1, 11304, 0x3277af6d -0, 37, -9223372036854775808, 1, 13291, 0xe267616a -0, 38, -9223372036854775808, 1, 8975, 0xe7eeacea -0, 39, -9223372036854775808, 1, 8473, 0x8bb1cbff -0, 40, -9223372036854775808, 1, 13878, 0xfd3d55bb -0, 41, -9223372036854775808, 1, 11278, 0x61c7c55e -0, 42, -9223372036854775808, 1, 13785, 0x2acbf88f -0, 43, -9223372036854775808, 1, 9521, 0x99e2d065 -0, 44, -9223372036854775808, 1, 9340, 0xe5c96510 -0, 45, -9223372036854775808, 1, 12777, 0x4c3c7844 -0, 46, -9223372036854775808, 1, 10685, 0x39e0f42e -0, 47, -9223372036854775808, 1, 14237, 0x9398d07f -0, 48, -9223372036854775808, 1, 9021, 0x3343c7ec -0, 49, -9223372036854775808, 1, 9327, 0xad489e86 -0, 50, -9223372036854775808, 1, 13507, 0xb1344f1c -0, 51, -9223372036854775808, 1, 10199, 0x9a8868bf -0, 52, -9223372036854775808, 1, 14535, 0xddb13f41 -0, 53, -9223372036854775808, 1, 8773, 0x3d8b6a79 -0, 54, -9223372036854775808, 1, 16084, 0x5d915de4 -0, 55, -9223372036854775808, 1, 9156, 0x5cb08a6a -0, 56, -9223372036854775808, 1, 15027, 0xc23b1dc8 -0, 57, -9223372036854775808, 1, 8240, 0xd6d3526c -0, 58, -9223372036854775808, 1, 8720, 0x439c43bf -0, 59, -9223372036854775808, 1, 13684, 0x18fc82f0 -0, 60, -9223372036854775808, 1, 8829, 0xa3ebeb30 -0, 61, -9223372036854775808, 1, 14650, 0x99e8678c -0, 62, -9223372036854775808, 1, 19626, 0x80a7ee5c -0, 63, -9223372036854775808, 1, 7762, 0x7c209a12 -0, 64, -9223372036854775808, 1, 13636, 0xc89c1aa3 -0, 65, -9223372036854775808, 1, 8337, 0x749bf76a -0, 66, -9223372036854775808, 1, 15098, 0xc98bc6dc -0, 67, -9223372036854775808, 1, 9070, 0xcd4cf7f1 -0, 68, -9223372036854775808, 1, 8269, 0x90e95d54 -0, 69, -9223372036854775808, 1, 12672, 0x034888d0 -0, 70, -9223372036854775808, 1, 7519, 0x6c089672 -0, 71, -9223372036854775808, 1, 14439, 0x5d2478b9 -0, 72, -9223372036854775808, 1, 6928, 0x98fbaa67 -0, 73, -9223372036854775808, 1, 8735, 0x07643f1e -0, 74, -9223372036854775808, 1, 13522, 0x55034cdb -0, 75, -9223372036854775808, 1, 7807, 0xf5983103 -0, 76, -9223372036854775808, 1, 14484, 0xfc9cf260 -0, 77, -9223372036854775808, 1, 7193, 0x170a0fa1 -0, 78, -9223372036854775808, 1, 9444, 0x6f9be36f -0, 79, -9223372036854775808, 1, 12598, 0x69b7609d -0, 80, -9223372036854775808, 1, 7650, 0x1abaec9e -0, 81, -9223372036854775808, 1, 15162, 0x2a87f723 -0, 82, -9223372036854775808, 1, 7752, 0xcca248aa -0, 83, -9223372036854775808, 1, 9085, 0x1ca7d7e5 -0, 84, -9223372036854775808, 1, 13187, 0xababcc64 -0, 85, -9223372036854775808, 1, 7968, 0x64a28f46 -0, 86, -9223372036854775808, 1, 15474, 0xf34c587c -0, 87, -9223372036854775808, 1, 8615, 0x61301034 -0, 88, -9223372036854775808, 1, 14129, 0x42c88bea -0, 89, -9223372036854775808, 1, 7223, 0x675d7500 -0, 90, -9223372036854775808, 1, 3072, 0x4cb6254c +0, 0, 0, 1, 19787, 0x75e463f3 +0, 1, 1, 1, 11913, 0x0f429c34 +0, 2, 2, 1, 14225, 0xbd3c704c +0, 3, 3, 1, 10357, 0xbf232393 +0, 4, 4, 1, 9595, 0xf565d39e +0, 5, 5, 1, 9262, 0x2afd6ce0 +0, 6, 6, 1, 12214, 0x6ae81d9b +0, 7, 7, 1, 13920, 0x31b5b307 +0, 8, 8, 1, 10164, 0x141eca4e +0, 9, 9, 1, 9516, 0xd5f2c42b +0, 10, 10, 1, 10006, 0x80850a76 +0, 11, 11, 1, 11791, 0x10bc2dcd +0, 12, 12, 1, 13756, 0xda1fee08 +0, 13, 13, 1, 10452, 0xbb3d62b0 +0, 14, 14, 1, 9171, 0x64ae10f6 +0, 15, 15, 1, 8816, 0x31ad8fcb +0, 16, 16, 1, 13168, 0xea1085ac +0, 17, 17, 1, 12797, 0x25143d22 +0, 18, 18, 1, 11324, 0x3a54b38e +0, 19, 19, 1, 9173, 0x8b2bf552 +0, 20, 20, 1, 9247, 0x2e87226b +0, 21, 21, 1, 14140, 0x1063786c +0, 22, 22, 1, 14437, 0xde123a17 +0, 23, 23, 1, 11938, 0x3f1168f4 +0, 24, 24, 1, 11966, 0xdd6786ec +0, 25, 25, 1, 13213, 0x8ab27c58 +0, 26, 26, 1, 11843, 0x90415d8b +0, 27, 27, 1, 13345, 0x3c0e1793 +0, 28, 28, 1, 9977, 0x74fc7f4b +0, 29, 29, 1, 9158, 0x0b5426a5 +0, 30, 30, 1, 12715, 0x0035d569 +0, 31, 31, 1, 19944, 0xe2887ba8 +0, 32, 32, 1, 12762, 0xb0f17939 +0, 33, 33, 1, 10260, 0x182b27aa +0, 34, 34, 1, 7405, 0x227fe9bf +0, 35, 35, 1, 13317, 0x1a678c62 +0, 36, 36, 1, 11304, 0x3277af6d +0, 37, 37, 1, 13291, 0xe267616a +0, 38, 38, 1, 8975, 0xe7eeacea +0, 39, 39, 1, 8473, 0x8bb1cbff +0, 40, 40, 1, 13878, 0xfd3d55bb +0, 41, 41, 1, 11278, 0x61c7c55e +0, 42, 42, 1, 13785, 0x2acbf88f +0, 43, 43, 1, 9521, 0x99e2d065 +0, 44, 44, 1, 9340, 0xe5c96510 +0, 45, 45, 1, 12777, 0x4c3c7844 +0, 46, 46, 1, 10685, 0x39e0f42e +0, 47, 47, 1, 14237, 0x9398d07f +0, 48, 48, 1, 9021, 0x3343c7ec +0, 49, 49, 1, 9327, 0xad489e86 +0, 50, 50, 1, 13507, 0xb1344f1c +0, 51, 51, 1, 10199, 0x9a8868bf +0, 52, 52, 1, 14535, 0xddb13f41 +0, 53, 53, 1, 8773, 0x3d8b6a79 +0, 54, 54, 1, 16084, 0x5d915de4 +0, 55, 55, 1, 9156, 0x5cb08a6a +0, 56, 56, 1, 15027, 0xc23b1dc8 +0, 57, 57, 1, 8240, 0xd6d3526c +0, 58, 58, 1, 8720, 0x439c43bf +0, 59, 59, 1, 13684, 0x18fc82f0 +0, 60, 60, 1, 8829, 0xa3ebeb30 +0, 61, 61, 1, 14650, 0x99e8678c +0, 62, 62, 1, 19626, 0x80a7ee5c +0, 63, 63, 1, 7762, 0x7c209a12 +0, 64, 64, 1, 13636, 0xc89c1aa3 +0, 65, 65, 1, 8337, 0x749bf76a +0, 66, 66, 1, 15098, 0xc98bc6dc +0, 67, 67, 1, 9070, 0xcd4cf7f1 +0, 68, 68, 1, 8269, 0x90e95d54 +0, 69, 69, 1, 12672, 0x034888d0 +0, 70, 70, 1, 7519, 0x6c089672 +0, 71, 71, 1, 14439, 0x5d2478b9 +0, 72, 72, 1, 6928, 0x98fbaa67 +0, 73, 73, 1, 8735, 0x07643f1e +0, 74, 74, 1, 13522, 0x55034cdb +0, 75, 75, 1, 7807, 0xf5983103 +0, 76, 76, 1, 14484, 0xfc9cf260 +0, 77, 77, 1, 7193, 0x170a0fa1 +0, 78, 78, 1, 9444, 0x6f9be36f +0, 79, 79, 1, 12598, 0x69b7609d +0, 80, 80, 1, 7650, 0x1abaec9e +0, 81, 81, 1, 15162, 0x2a87f723 +0, 82, 82, 1, 7752, 0xcca248aa +0, 83, 83, 1, 9085, 0x1ca7d7e5 +0, 84, 84, 1, 13187, 0xababcc64 +0, 85, 85, 1, 7968, 0x64a28f46 +0, 86, 86, 1, 15474, 0xf34c587c +0, 87, 87, 1, 8615, 0x61301034 +0, 88, 88, 1, 14129, 0x42c88bea +0, 89, 89, 1, 7223, 0x675d7500 +0, 90, 90, 1, 3072, 0x4cb6254c diff --git a/tests/ref/fate/pict b/tests/ref/fate/pict new file mode 100644 index 0000000..0b764fc --- /dev/null +++ b/tests/ref/fate/pict @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 49152, 0x144804b0 diff --git a/tests/ref/fate/ra3-144 b/tests/ref/fate/ra3-144 new file mode 100644 index 0000000..40bcaed --- /dev/null +++ b/tests/ref/fate/ra3-144 @@ -0,0 +1,51 @@ +#tb 0: 1/8000 +0, 0, 0, 160, 320, 0x00000000 +0, 160, 160, 160, 320, 0x4cfd5d74 +0, 320, 320, 160, 320, 0xbb60fa3d +0, 480, 480, 160, 320, 0x4d75097c +0, 640, 640, 160, 320, 0x59cbd3b4 +0, 800, 800, 160, 320, 0x0bcddb40 +0, 960, 960, 160, 320, 0x3d8ec98a +0, 1120, 1120, 160, 320, 0x3612b700 +0, 1280, 1280, 160, 320, 0x23cfb9b6 +0, 1440, 1440, 160, 320, 0xd339c9a5 +0, 1600, 1600, 160, 320, 0xffb6b7c9 +0, 1760, 1760, 160, 320, 0x8730ac48 +0, 1920, 1920, 160, 320, 0x1568b279 +0, 2080, 2080, 160, 320, 0xf2229fda +0, 2240, 2240, 160, 320, 0x91c0adbf +0, 2400, 2400, 160, 320, 0xe261a238 +0, 2560, 2560, 160, 320, 0x5c0d97c6 +0, 2720, 2720, 160, 320, 0x32d492de +0, 2880, 2880, 160, 320, 0x46a3af81 +0, 3040, 3040, 160, 320, 0xf8deaa2e +0, 3200, 3200, 160, 320, 0x48649866 +0, 3360, 3360, 160, 320, 0x4cb2a03e +0, 3520, 3520, 160, 320, 0x55e9a3d7 +0, 3680, 3680, 160, 320, 0xc60d9cf8 +0, 3840, 3840, 160, 320, 0x969098b8 +0, 4000, 4000, 160, 320, 0xe00b9f43 +0, 4160, 4160, 160, 320, 0x85c6af06 +0, 4320, 4320, 160, 320, 0x2037a849 +0, 4480, 4480, 160, 320, 0xd8e09379 +0, 4640, 4640, 160, 320, 0x5df69e34 +0, 4800, 4800, 160, 320, 0x95869c06 +0, 4960, 4960, 160, 320, 0x651c95a7 +0, 5120, 5120, 160, 320, 0xd433a2f4 +0, 5280, 5280, 160, 320, 0xc6c1a0e2 +0, 5440, 5440, 160, 320, 0x6cad9e61 +0, 5600, 5600, 160, 320, 0x57f5ab36 +0, 5760, 5760, 160, 320, 0x11fd9788 +0, 5920, 5920, 160, 320, 0x805db795 +0, 6080, 6080, 160, 320, 0xb306a36b +0, 6240, 6240, 160, 320, 0xa34d9933 +0, 6400, 6400, 160, 320, 0xbc24a23c +0, 6560, 6560, 160, 320, 0x6639a03c +0, 6720, 6720, 160, 320, 0x4f20ab13 +0, 6880, 6880, 160, 320, 0xe30ca2bb +0, 7040, 7040, 160, 320, 0x51e5ac4f +0, 7200, 7200, 160, 320, 0x2a369ff4 +0, 7360, 7360, 160, 320, 0xfbffaa78 +0, 7520, 7520, 160, 320, 0xf117a04f +0, 7680, 7680, 160, 320, 0x36479938 +0, 7840, 7840, 160, 320, 0xd1269299 diff --git a/tests/ref/fate/rscc-16bit b/tests/ref/fate/rscc-16bit new file mode 100644 index 0000000..85d5494 --- /dev/null +++ b/tests/ref/fate/rscc-16bit @@ -0,0 +1,16 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 153600, 0x33759daf +0, 1, 1, 1, 153600, 0x43e0c910 +0, 2, 2, 1, 153600, 0x6c75a8f0 +0, 3, 3, 1, 153600, 0xaace1255 +0, 4, 4, 1, 153600, 0x42d3f439 +0, 5, 5, 1, 153600, 0xb225b396 +0, 6, 6, 1, 153600, 0xa615221c +0, 7, 7, 1, 153600, 0x5401f5a9 +0, 8, 8, 1, 153600, 0xd274cef3 +0, 9, 9, 1, 153600, 0x7935f992 +0, 10, 10, 1, 153600, 0x7669e7c6 +0, 11, 11, 1, 153600, 0x527bd6a1 +0, 12, 12, 1, 153600, 0x0f33b2ed +0, 13, 13, 1, 153600, 0xe62ddb32 +0, 14, 14, 1, 153600, 0x81541aa2 diff --git a/tests/ref/fate/rscc-24bit b/tests/ref/fate/rscc-24bit new file mode 100644 index 0000000..e38702c --- /dev/null +++ b/tests/ref/fate/rscc-24bit @@ -0,0 +1,2 @@ +#tb 0: 100/2997 +0, 0, 0, 1, 1229760, 0x9c99ba99 diff --git a/tests/ref/fate/rscc-32bit b/tests/ref/fate/rscc-32bit new file mode 100644 index 0000000..a443186 --- /dev/null +++ b/tests/ref/fate/rscc-32bit @@ -0,0 +1,9 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 307200, 0xe36c2c38 +0, 1, 1, 1, 307200, 0xa2e3476b +0, 2, 2, 1, 307200, 0x65167c95 +0, 3, 3, 1, 307200, 0x6acd02ac +0, 4, 4, 1, 307200, 0x37935e0b +0, 5, 5, 1, 307200, 0x8e6918bc +0, 6, 6, 1, 307200, 0x0a246578 +0, 7, 7, 1, 307200, 0x9c1a2f4c diff --git a/tests/ref/fate/rtmpdh b/tests/ref/fate/rtmpdh new file mode 100644 index 0000000..3b55665 --- /dev/null +++ b/tests/ref/fate/rtmpdh @@ -0,0 +1,3 @@ +Generated shared key ok +Generated public key ok +Generated shared key ok diff --git a/tests/ref/fate/screenpresso-16bit b/tests/ref/fate/screenpresso-16bit new file mode 100644 index 0000000..d9a7d89 --- /dev/null +++ b/tests/ref/fate/screenpresso-16bit @@ -0,0 +1,9 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 153600, 0x69a234de +0, 1, 1, 1, 153600, 0x7f43aee5 +0, 2, 2, 1, 153600, 0x81030634 +0, 3, 3, 1, 153600, 0xf570d0ef +0, 4, 4, 1, 153600, 0x386e8cec +0, 5, 5, 1, 153600, 0xbe53af8f +0, 6, 6, 1, 153600, 0xf92f48bd +0, 7, 7, 1, 153600, 0x594472c5 diff --git a/tests/ref/fate/screenpresso-24bit b/tests/ref/fate/screenpresso-24bit new file mode 100644 index 0000000..bbdffb4 --- /dev/null +++ b/tests/ref/fate/screenpresso-24bit @@ -0,0 +1,5 @@ +#tb 0: 1/15 +0, 0, 0, 1, 691200, 0xfdbdfad6 +0, 1, 1, 1, 691200, 0xc5feb961 +0, 4, 4, 1, 691200, 0x4c8c7e23 +0, 8, 8, 1, 691200, 0xd95c89f8 diff --git a/tests/ref/fate/screenpresso-32bit b/tests/ref/fate/screenpresso-32bit new file mode 100644 index 0000000..5e1a3b5 --- /dev/null +++ b/tests/ref/fate/screenpresso-32bit @@ -0,0 +1,5 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 307200, 0xa01f27cc +0, 1, 1, 1, 307200, 0x5d83c4d0 +0, 2, 2, 1, 307200, 0xb7d7919f +0, 3, 3, 1, 307200, 0x4d201450 diff --git a/tests/ref/fate/sgi-gray16 b/tests/ref/fate/sgi-gray16 index 3218edc..0908746 100644 --- a/tests/ref/fate/sgi-gray16 +++ b/tests/ref/fate/sgi-gray16 @@ -1,2 +1,2 @@ #tb 0: 1/25 -0, 0, 0, 1, 262144, 0xecdaf084 +0, 0, 0, 1, 262144, 0x6c27f084 diff --git a/tests/ref/fate/sgi-gray16-rle b/tests/ref/fate/sgi-gray16-rle new file mode 100644 index 0000000..09903d5 --- /dev/null +++ b/tests/ref/fate/sgi-gray16-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 262144, 0x65ef57ff diff --git a/tests/ref/fate/sgi-gray b/tests/ref/fate/sgi-gray8 similarity index 100% rename from tests/ref/fate/sgi-gray rename to tests/ref/fate/sgi-gray8 diff --git a/tests/ref/fate/sgi-gray8-rle b/tests/ref/fate/sgi-gray8-rle new file mode 100644 index 0000000..b0e0606 --- /dev/null +++ b/tests/ref/fate/sgi-gray8-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 131072, 0xb0702a94 diff --git a/tests/ref/fate/sgi-rgba-rle b/tests/ref/fate/sgi-rgba-rle new file mode 100644 index 0000000..058f5f9 --- /dev/null +++ b/tests/ref/fate/sgi-rgba-rle @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 524288, 0x4ee5adbb diff --git a/tests/ref/fate/sgi-rgba64-rle b/tests/ref/fate/sgi-rgba64-rle index 1dfac76..cdf5fd0 100644 --- a/tests/ref/fate/sgi-rgba64-rle +++ b/tests/ref/fate/sgi-rgba64-rle @@ -1,2 +1,2 @@ #tb 0: 1/25 -0, 0, 0, 1, 614400, 0xb92d409d +0, 0, 0, 1, 1048576, 0xb619d0f1 diff --git a/tests/ref/fate/svq1-headerswap b/tests/ref/fate/svq1-headerswap new file mode 100644 index 0000000..f5ffe4d --- /dev/null +++ b/tests/ref/fate/svq1-headerswap @@ -0,0 +1,5 @@ +#tb 0: 1/600 +0, 0, 0, 1, 58814, 0x5caad04b +0, 60, 60, 1, 58814, 0x98d8ceb8 +0, 120, 120, 1, 58814, 0x8925cdb0 +0, 180, 180, 1, 58814, 0x6ffc02c3 diff --git a/tests/ref/fate/tdsc b/tests/ref/fate/tdsc new file mode 100644 index 0000000..945933f --- /dev/null +++ b/tests/ref/fate/tdsc @@ -0,0 +1,42 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 3888000, 0x9c498657 +0, 233, 233, 0, 3888000, 0x72a2ae22 +0, 266, 266, 0, 3888000, 0x72a2ae22 +0, 333, 333, 0, 3888000, 0x72a2ae22 +0, 533, 533, 0, 3888000, 0x72a2ae22 +0, 566, 566, 0, 3888000, 0x72a2ae22 +0, 666, 666, 0, 3888000, 0x550e417b +0, 966, 966, 0, 3888000, 0x550e417b +0, 999, 999, 0, 3888000, 0x550e417b +0, 1033, 1033, 0, 3888000, 0x550e417b +0, 1066, 1066, 0, 3888000, 0x550e417b +0, 1133, 1133, 0, 3888000, 0x550e417b +0, 1166, 1166, 0, 3888000, 0x38dcde13 +0, 1566, 1566, 0, 3888000, 0x2b7c0edd +0, 1599, 1599, 0, 3888000, 0xaaaf3c7b +0, 1633, 1633, 0, 3888000, 0x26d1710f +0, 1666, 1666, 0, 3888000, 0xa6609f3f +0, 1699, 1699, 0, 3888000, 0xaa41c6f3 +0, 1733, 1733, 0, 3888000, 0xc0ffd4d5 +0, 1766, 1766, 0, 3888000, 0x44d4f383 +0, 1833, 1833, 0, 3888000, 0x517047eb +0, 1866, 1866, 0, 3888000, 0x1d5a4d5b +0, 1899, 1899, 0, 3888000, 0x7d2da2f6 +0, 1933, 1933, 0, 3888000, 0x27f7a2f6 +0, 1966, 1966, 0, 3888000, 0x9de49edb +0, 1999, 1999, 0, 3888000, 0x5ccb9f38 +0, 2033, 2033, 0, 3888000, 0x88069fb2 +0, 2066, 2066, 0, 3888000, 0x1d059fd3 +0, 2099, 2099, 0, 3888000, 0xe16d9fd3 +0, 2133, 2133, 0, 3888000, 0xb6a69fd3 +0, 2166, 2166, 0, 3888000, 0xb6a69fd3 +0, 2199, 2199, 0, 3888000, 0x61709fd3 +0, 2233, 2233, 0, 3888000, 0xb6f59fd3 +0, 2266, 2266, 0, 3888000, 0x5c7b9fd3 +0, 2299, 2299, 0, 3888000, 0x57869fd3 +0, 2333, 2333, 0, 3888000, 0x9d3f9fd3 +0, 2433, 2433, 0, 3888000, 0x5e6082a5 +0, 2466, 2466, 0, 3888000, 0x5e6082a5 +0, 2499, 2499, 0, 3888000, 0x5e6082a5 +0, 2533, 2533, 0, 3888000, 0x48ce82f3 +0, 2566, 2566, 0, 3888000, 0x4c5ebeaf diff --git a/tests/ref/fate/theora-offset b/tests/ref/fate/theora-offset new file mode 100644 index 0000000..5921657 --- /dev/null +++ b/tests/ref/fate/theora-offset @@ -0,0 +1,11 @@ +#tb 0: 1/1 +0, 0, 0, 1, 393216, 0xdc998fa2 +0, 1, 1, 1, 393216, 0x979a8fbd +0, 2, 2, 1, 393216, 0x979a8fbd +0, 3, 3, 1, 393216, 0x979a8fbd +0, 4, 4, 1, 393216, 0x979a8fbd +0, 5, 5, 1, 393216, 0x979a8fbd +0, 6, 6, 1, 393216, 0x979a8fbd +0, 7, 7, 1, 393216, 0x979a8fbd +0, 8, 8, 1, 393216, 0x979a8fbd +0, 9, 9, 1, 393216, 0x979a8fbd diff --git a/tests/ref/fate/truemotion1-24 b/tests/ref/fate/truemotion1-24 index f097ed0..73bb9e7 100644 --- a/tests/ref/fate/truemotion1-24 +++ b/tests/ref/fate/truemotion1-24 @@ -14,3 +14,4 @@ 0, 12, 12, 1, 69120, 0xf55d74c7 0, 13, 13, 1, 69120, 0xb5082ca7 0, 14, 14, 1, 69120, 0x5876d758 +0, 15, 15, 1, 69120, 0x45e7dd5c diff --git a/tests/ref/fate/truemotion2rt-high b/tests/ref/fate/truemotion2rt-high new file mode 100644 index 0000000..1b08f6f --- /dev/null +++ b/tests/ref/fate/truemotion2rt-high @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 54288, 0xbb88db84 diff --git a/tests/ref/fate/truemotion2rt-low b/tests/ref/fate/truemotion2rt-low new file mode 100644 index 0000000..5251a79 --- /dev/null +++ b/tests/ref/fate/truemotion2rt-low @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 54288, 0x94310459 diff --git a/tests/ref/fate/truemotion2rt-mid b/tests/ref/fate/truemotion2rt-mid new file mode 100644 index 0000000..f99efca --- /dev/null +++ b/tests/ref/fate/truemotion2rt-mid @@ -0,0 +1,2 @@ +#tb 0: 100/2397 +0, 0, 0, 1, 45864, 0x6c39a9e0 diff --git a/tests/ref/fate/tscc2 b/tests/ref/fate/tscc2-avi similarity index 100% rename from tests/ref/fate/tscc2 rename to tests/ref/fate/tscc2-avi diff --git a/tests/ref/fate/tscc2-mov b/tests/ref/fate/tscc2-mov new file mode 100644 index 0000000..d73ff3f --- /dev/null +++ b/tests/ref/fate/tscc2-mov @@ -0,0 +1,16 @@ +#tb 0: 1/5 +0, 0, 0, 1, 1180116, 0x01d01336 +0, 1, 1, 1, 1180116, 0x01d01336 +0, 2, 2, 1, 1180116, 0x01d01336 +0, 3, 3, 1, 1180116, 0x01d01336 +0, 4, 4, 1, 1180116, 0x01d01336 +0, 5, 5, 1, 1180116, 0x01d01336 +0, 6, 6, 1, 1180116, 0x01d01336 +0, 7, 7, 1, 1180116, 0x01d01336 +0, 8, 8, 1, 1180116, 0x01d01336 +0, 9, 9, 1, 1180116, 0x01d01336 +0, 10, 10, 1, 1180116, 0x056fdadd +0, 11, 11, 1, 1180116, 0x6f73e080 +0, 12, 12, 1, 1180116, 0x5244d9e5 +0, 13, 13, 1, 1180116, 0x629bf10f +0, 14, 14, 1, 1180116, 0x97c726cb diff --git a/tests/ref/fate/txd-16bpp b/tests/ref/fate/txd-16bpp index 9522873..33943f9 100644 --- a/tests/ref/fate/txd-16bpp +++ b/tests/ref/fate/txd-16bpp @@ -1,12 +1,12 @@ #tb 0: 1/5 -0, 0, 0, 1, 16384, 0x213f9ea8 -0, 1, 1, 1, 16384, 0x8185fdb1 -0, 2, 2, 1, 16384, 0xf03581d1 -0, 3, 3, 1, 16384, 0x629cd573 -0, 4, 4, 1, 16384, 0xfe7a5b63 -0, 5, 5, 1, 16384, 0x4afc05b2 -0, 6, 6, 1, 16384, 0x074b8515 -0, 7, 7, 1, 16384, 0x17fde900 -0, 8, 8, 1, 16384, 0x831bac76 -0, 9, 9, 1, 16384, 0x2fb579f3 -0, 10, 10, 1, 16384, 0x68762bed +0, 0, 0, 1, 16384, 0x4d39b4cb +0, 1, 1, 1, 16384, 0x2a8d14b4 +0, 2, 2, 1, 16384, 0xe26793cb +0, 3, 3, 1, 16384, 0x62b5ed43 +0, 4, 4, 1, 16384, 0x5ae86c21 +0, 5, 5, 1, 16384, 0x416d184a +0, 6, 6, 1, 16384, 0x33f59d3e +0, 7, 7, 1, 16384, 0x3d0ffd9c +0, 8, 8, 1, 16384, 0x35bac4c6 +0, 9, 9, 1, 16384, 0xa1cd8ffb +0, 10, 10, 1, 16384, 0xf7dc38d2 diff --git a/tests/ref/fate/txd-odd b/tests/ref/fate/txd-odd new file mode 100644 index 0000000..fe7c615 --- /dev/null +++ b/tests/ref/fate/txd-odd @@ -0,0 +1,2 @@ +#tb 0: 1/5 +0, 0, 0, 1, 385452, 0x055a14d6 diff --git a/tests/ref/fate/v210 b/tests/ref/fate/v210 index 2847564..7ad9dcf 100644 --- a/tests/ref/fate/v210 +++ b/tests/ref/fate/v210 @@ -1,2 +1,2 @@ #tb 0: 1/50 -0, 0, 0, 1, 3686400, 0x75ee1dde +0, 0, 0, 1, 3686400, 0x8d5c3847 diff --git a/tests/ref/fate/vc1-ism b/tests/ref/fate/vc1-ism index 4daca95..a60cb8a 100644 --- a/tests/ref/fate/vc1-ism +++ b/tests/ref/fate/vc1-ism @@ -1,121 +1,63 @@ #tb 0: 1/10000000 -0, 423334, 423334, 0, 37440, 0xd1bc5235 -0, 840000, 840000, 0, 37440, 0x158e6167 -0, 1256666, 1256666, 0, 37440, 0x0faa4481 -0, 1670000, 1670000, 0, 37440, 0x427158c5 -0, 2086666, 2086666, 0, 37440, 0x4eb53ac6 -0, 2500000, 2500000, 0, 37440, 0x99304eea -0, 2916666, 2916666, 0, 37440, 0xcc554a6f -0, 3340000, 3340000, 0, 37440, 0xabeb6c35 -0, 3756666, 3756666, 0, 37440, 0xddfc7e18 -0, 4170000, 4170000, 0, 37440, 0xaa79b504 -0, 4586666, 4586666, 0, 37440, 0x5cb1c839 -0, 5000000, 5000000, 0, 37440, 0x7e36ecca -0, 5416666, 5416666, 0, 37440, 0xf486f425 -0, 5840000, 5840000, 0, 37440, 0xf1b4138f -0, 6256666, 6256666, 0, 37440, 0x966f1a49 -0, 6670000, 6670000, 0, 37440, 0x5eff21da -0, 7086666, 7086666, 0, 37440, 0x333f39b1 -0, 7500000, 7500000, 0, 37440, 0x62e5963e -0, 7916666, 7916666, 0, 37440, 0x26930671 -0, 8340000, 8340000, 0, 37440, 0x27b4bb6c -0, 8756666, 8756666, 0, 37440, 0xdbd07766 -0, 9170000, 9170000, 0, 37440, 0x04260104 -0, 9586666, 9586666, 0, 37440, 0x9b1e078b -0, 10000000, 10000000, 0, 37440, 0xdf4e2474 -0, 10416666, 10416666, 0, 37440, 0x57d44986 -0, 10840000, 10840000, 0, 37440, 0x8780e34c -0, 11256666, 11256666, 0, 37440, 0xf80c8bc0 -0, 11670000, 11670000, 0, 37440, 0x630a7583 -0, 12086666, 12086666, 0, 37440, 0x235ae089 -0, 12500000, 12500000, 0, 37440, 0x984b8f0e -0, 12916666, 12916666, 0, 37440, 0x865cf592 -0, 13340000, 13340000, 0, 37440, 0x70f376f2 -0, 13756666, 13756666, 0, 37440, 0x8b30c035 -0, 14170000, 14170000, 0, 37440, 0xde772d79 -0, 14586666, 14586666, 0, 37440, 0x8e076be5 -0, 15000000, 15000000, 0, 37440, 0x3dc2bd9f -0, 15416666, 15416666, 0, 37440, 0xb782eb67 -0, 15840000, 15840000, 0, 37440, 0x02025d73 -0, 16256666, 16256666, 0, 37440, 0x86bbbce8 -0, 16670000, 16670000, 0, 37440, 0xd6554f62 -0, 17086666, 17086666, 0, 37440, 0xb831b917 -0, 17500000, 17500000, 0, 37440, 0x80643560 -0, 17916666, 17916666, 0, 37440, 0x4ecf9afd -0, 18340000, 18340000, 0, 37440, 0x9ce51e0b -0, 18756666, 18756666, 0, 37440, 0x179466cd -0, 19170000, 19170000, 0, 37440, 0x145fc900 -0, 19586666, 19586666, 0, 37440, 0xb1b50402 -0, 20000000, 20000000, 0, 37440, 0x0a87552a -0, 20416666, 20416666, 0, 37440, 0x8f53821d -0, 20840000, 20840000, 0, 37440, 0x1c07c825 -0, 21256666, 21256666, 0, 37440, 0x49dde82f -0, 21670000, 21670000, 0, 37440, 0xb1a32605 -0, 22086666, 22086666, 0, 37440, 0x410f3cd5 -0, 22500000, 22500000, 0, 37440, 0xff5e6696 -0, 22916666, 22916666, 0, 37440, 0x96f678c9 -0, 23340000, 23340000, 0, 37440, 0x6c9e9e68 -0, 23756666, 23756666, 0, 37440, 0x79a2a655 -0, 24170000, 24170000, 0, 37440, 0xf237bd6c -0, 24586666, 24586666, 0, 37440, 0x4051b611 -0, 25000000, 25000000, 0, 37440, 0xc7ccc918 -0, 25416666, 25416666, 0, 37440, 0xbd02c122 -0, 25840000, 25840000, 0, 37440, 0xacb3c881 -0, 26256666, 26256666, 0, 37440, 0x2abdb940 -0, 26670000, 26670000, 0, 37440, 0x19d5be85 -0, 27086666, 27086666, 0, 37440, 0xfa5fb1ba -0, 27503332, 27503332, 0, 37440, 0xdae7a7aa -0, 27919998, 27919998, 0, 37440, 0x6b0f9f69 -0, 28340000, 28340000, 0, 37440, 0x353e8201 -0, 28756666, 28756666, 0, 37440, 0xa21443aa -0, 29170000, 29170000, 0, 37440, 0x66c8d7e0 -0, 29586666, 29586666, 0, 37440, 0xc332068e -0, 30000000, 30000000, 0, 37440, 0x71431b9b -0, 30416666, 30416666, 0, 37440, 0x392f15cb -0, 30840000, 30840000, 0, 37440, 0x95a146bb -0, 31256666, 31256666, 0, 37440, 0x7c51740a -0, 31670000, 31670000, 0, 37440, 0xa3bdd43c -0, 32086666, 32086666, 0, 37440, 0xa079f965 -0, 32500000, 32500000, 0, 37440, 0xa95423ea -0, 32916666, 32916666, 0, 37440, 0xd1bd2c67 -0, 33340000, 33340000, 0, 37440, 0x6cf82844 -0, 33756666, 33756666, 0, 37440, 0xd401e128 -0, 34170000, 34170000, 0, 37440, 0x1f7db118 -0, 34586666, 34586666, 0, 37440, 0x2e0a65a9 -0, 35000000, 35000000, 0, 37440, 0x321c1c40 -0, 35416666, 35416666, 0, 37440, 0x95b2a127 -0, 35840000, 35840000, 0, 37440, 0xa1471f4b -0, 36256666, 36256666, 0, 37440, 0x29d148c0 -0, 36670000, 36670000, 0, 37440, 0x24c07107 -0, 37086666, 37086666, 0, 37440, 0x0ead678d -0, 37500000, 37500000, 0, 37440, 0xd0ca6495 -0, 37916666, 37916666, 0, 37440, 0x08f935ef -0, 38340000, 38340000, 0, 37440, 0xb5ec3c38 -0, 38756666, 38756666, 0, 37440, 0xce371628 -0, 39170000, 39170000, 0, 37440, 0x68170812 -0, 39586666, 39586666, 0, 37440, 0xe222699e -0, 40000000, 40000000, 0, 37440, 0xd688706c -0, 40416666, 40416666, 0, 37440, 0x81a033f9 -0, 40840000, 40840000, 0, 37440, 0x28bd0fbf -0, 41256666, 41256666, 0, 37440, 0xe36db7b2 -0, 41670000, 41670000, 0, 37440, 0x30559121 -0, 42086666, 42086666, 0, 37440, 0xbf2b5fc8 -0, 42500000, 42500000, 0, 37440, 0x4b427672 -0, 42916666, 42916666, 0, 37440, 0x0544b0b4 -0, 43340000, 43340000, 0, 37440, 0x38a70b06 -0, 43756666, 43756666, 0, 37440, 0x4ed62607 -0, 44170000, 44170000, 0, 37440, 0x6efe8ea6 -0, 44586666, 44586666, 0, 37440, 0x81197e11 -0, 45000000, 45000000, 0, 37440, 0xf4060050 -0, 45416666, 45416666, 0, 37440, 0xaf205f13 -0, 45840000, 45840000, 0, 37440, 0x5fa21382 -0, 46256666, 46256666, 0, 37440, 0x8627ad05 -0, 46670000, 46670000, 0, 37440, 0xf7130133 -0, 47086666, 47086666, 0, 37440, 0x76dea7ba -0, 47500000, 47500000, 0, 37440, 0x1dbae1be -0, 47916666, 47916666, 0, 37440, 0x74a933f7 -0, 48340000, 48340000, 0, 37440, 0xbdcd41a3 -0, 48756666, 48756666, 0, 37440, 0xf0fe8c1c -0, 49170000, 49170000, 0, 37440, 0xc0036222 -0, 49586666, 49586666, 0, 37440, 0x3058385c -0, 49586667, 49586667, 0, 37440, 0x68141016 +0, 4, 4, 0, 37440, 0xd1bc5235 +0, 1256670, 1256670, 0, 37440, 0x158e6167 +0, 2086670, 2086670, 0, 37440, 0x427158c5 +0, 2916670, 2916670, 0, 37440, 0x99304eea +0, 3756670, 3756670, 0, 37440, 0xabeb6c35 +0, 4586670, 4586670, 0, 37440, 0xaa79b504 +0, 5416670, 5416670, 0, 37440, 0x7e36ecca +0, 6256670, 6256670, 0, 37440, 0xf1b4138f +0, 7086670, 7086670, 0, 37440, 0x5eff21da +0, 7916670, 7916670, 0, 37440, 0x62e5963e +0, 8756670, 8756670, 0, 37440, 0x27b4bb6c +0, 9586670, 9586670, 0, 37440, 0x04260104 +0, 10416670, 10416670, 0, 37440, 0xdf4e2474 +0, 11256670, 11256670, 0, 37440, 0x8780e34c +0, 12086670, 12086670, 0, 37440, 0x630a7583 +0, 12916670, 12916670, 0, 37440, 0x984b8f0e +0, 13756670, 13756670, 0, 37440, 0x70f376f2 +0, 14586670, 14586670, 0, 37440, 0xde772d79 +0, 15416670, 15416670, 0, 37440, 0x3dc2bd9f +0, 16256670, 16256670, 0, 37440, 0x02025d73 +0, 17086670, 17086670, 0, 37440, 0xd6554f62 +0, 17916670, 17916670, 0, 37440, 0x80643560 +0, 18756670, 18756670, 0, 37440, 0x9ce51e0b +0, 19586670, 19586670, 0, 37440, 0x145fc900 +0, 20416670, 20416670, 0, 37440, 0x0a87552a +0, 21256670, 21256670, 0, 37440, 0x1c07c825 +0, 22086670, 22086670, 0, 37440, 0xb1a32605 +0, 22916670, 22916670, 0, 37440, 0xff5e6696 +0, 23756670, 23756670, 0, 37440, 0x6c9e9e68 +0, 24586670, 24586670, 0, 37440, 0xf237bd6c +0, 25416670, 25416670, 0, 37440, 0xc7ccc918 +0, 26256670, 26256670, 0, 37440, 0xacb3c881 +0, 27086670, 27086670, 0, 37440, 0x19d5be85 +0, 27506670, 27506670, 0, 37440, 0xdae7a7aa +0, 27916670, 27916670, 0, 37440, 0x6b0f9f69 +0, 28756670, 28756670, 0, 37440, 0x353e8201 +0, 29586670, 29586670, 0, 37440, 0x66c8d7e0 +0, 30416670, 30416670, 0, 37440, 0x71431b9b +0, 31256670, 31256670, 0, 37440, 0x95a146bb +0, 32086670, 32086670, 0, 37440, 0xa3bdd43c +0, 32916670, 32916670, 0, 37440, 0xa95423ea +0, 33756670, 33756670, 0, 37440, 0x6cf82844 +0, 34586670, 34586670, 0, 37440, 0x1f7db118 +0, 35416670, 35416670, 0, 37440, 0x321c1c40 +0, 36256670, 36256670, 0, 37440, 0xa1471f4b +0, 37086670, 37086670, 0, 37440, 0x24c07107 +0, 37916670, 37916670, 0, 37440, 0xd0ca6495 +0, 38756670, 38756670, 0, 37440, 0xb5ec3c38 +0, 39586670, 39586670, 0, 37440, 0x68170812 +0, 40416670, 40416670, 0, 37440, 0xd688706c +0, 41256670, 41256670, 0, 37440, 0x28bd0fbf +0, 42086670, 42086670, 0, 37440, 0x30559121 +0, 42916670, 42916670, 0, 37440, 0x4b427672 +0, 43756670, 43756670, 0, 37440, 0x38a70b06 +0, 44586670, 44586670, 0, 37440, 0x6efe8ea6 +0, 45416670, 45416670, 0, 37440, 0xf4060050 +0, 46256670, 46256670, 0, 37440, 0x5fa21382 +0, 47086670, 47086670, 0, 37440, 0xf7130133 +0, 47916670, 47916670, 0, 37440, 0x1dbae1be +0, 48756670, 48756670, 0, 37440, 0xbdcd41a3 +0, 49586670, 49586670, 0, 37440, 0xc0036222 +0, 50006670, 50006670, 0, 37440, 0x68141016 diff --git a/tests/ref/fate/vc1_ilaced_twomv b/tests/ref/fate/vc1_ilaced_twomv new file mode 100644 index 0000000..dca5fa9 --- /dev/null +++ b/tests/ref/fate/vc1_ilaced_twomv @@ -0,0 +1,14 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3110400, 0x764f8856 +0, 2, 2, 1, 3110400, 0x3b615b79 +0, 3, 3, 1, 3110400, 0x4fbb6f84 +0, 4, 4, 1, 3110400, 0xc1ca8532 +0, 5, 5, 1, 3110400, 0x53efd0f9 +0, 6, 6, 1, 3110400, 0xa9605bc9 +0, 7, 7, 1, 3110400, 0xbaa9aede +0, 8, 8, 1, 3110400, 0x602fbcd5 +0, 9, 9, 1, 3110400, 0x93d204b5 +0, 10, 10, 1, 3110400, 0x7b047286 +0, 11, 11, 1, 3110400, 0xa7cb2f84 +0, 12, 12, 1, 3110400, 0xfba20dd1 +0, 13, 13, 1, 3110400, 0x24c32a55 diff --git a/tests/ref/fate/vc1_sa10143 b/tests/ref/fate/vc1_sa10143 index 6a5137f..c0ecc3b 100644 --- a/tests/ref/fate/vc1_sa10143 +++ b/tests/ref/fate/vc1_sa10143 @@ -1,31 +1,31 @@ #tb 0: 1/25 0, 0, 0, 1, 518400, 0x89407f55 -0, 2, 2, 1, 518400, 0x8611849c +0, 2, 2, 1, 518400, 0xaa896afd 0, 3, 3, 1, 518400, 0x0e69ff59 -0, 4, 4, 1, 518400, 0xf31adb03 +0, 4, 4, 1, 518400, 0x0c30bfa0 0, 5, 5, 1, 518400, 0x1a5b6a69 -0, 6, 6, 1, 518400, 0x6ae6232e +0, 6, 6, 1, 518400, 0x23470858 0, 7, 7, 1, 518400, 0x9a4e3c54 -0, 8, 8, 1, 518400, 0xe5852b45 +0, 8, 8, 1, 518400, 0xad63160b 0, 9, 9, 1, 518400, 0x0fcfeebc -0, 10, 10, 1, 518400, 0x06e22dc3 +0, 10, 10, 1, 518400, 0x20b31777 0, 11, 11, 1, 518400, 0x9d79df09 -0, 12, 12, 1, 518400, 0xcb2c716f +0, 12, 12, 1, 518400, 0x3e86766f 0, 13, 13, 1, 518400, 0x638a8746 -0, 14, 14, 1, 518400, 0xf7032efd +0, 14, 14, 1, 518400, 0x7a6c1a0e 0, 15, 15, 1, 518400, 0x306f6cef -0, 16, 16, 1, 518400, 0xe83d2518 +0, 16, 16, 1, 518400, 0x81f81281 0, 17, 17, 1, 518400, 0x49ab5bf5 -0, 18, 18, 1, 518400, 0x6b336b6f +0, 18, 18, 1, 518400, 0x8f316e44 0, 19, 19, 1, 518400, 0x95ae00c9 -0, 20, 20, 1, 518400, 0x68ddb64f +0, 20, 20, 1, 518400, 0xf71bb7f5 0, 21, 21, 1, 518400, 0x5205ea68 -0, 22, 22, 1, 518400, 0xb088e617 +0, 22, 22, 1, 518400, 0x74a1d8b9 0, 23, 23, 1, 518400, 0xa3217616 -0, 24, 24, 1, 518400, 0x1723bc53 +0, 24, 24, 1, 518400, 0x2b28bbf8 0, 25, 25, 1, 518400, 0xf024872a -0, 26, 26, 1, 518400, 0x2e81a8bb +0, 26, 26, 1, 518400, 0x2fdbaaf3 0, 27, 27, 1, 518400, 0xa3a2418e -0, 28, 28, 1, 518400, 0xb7beffed +0, 28, 28, 1, 518400, 0x55bfe435 0, 29, 29, 1, 518400, 0x50fb6c94 0, 30, 30, 1, 518400, 0x5584bb40 diff --git a/tests/ref/fate/vp5 b/tests/ref/fate/vp5 index 791fe60..0e601ba 100644 --- a/tests/ref/fate/vp5 +++ b/tests/ref/fate/vp5 @@ -245,3 +245,4 @@ 0, 243, 243, 1, 233472, 0x6f530ac6 0, 244, 244, 1, 233472, 0x94f7466c 0, 245, 245, 1, 233472, 0xa8c1d365 +0, 246, 246, 1, 233472, 0xedcff050 diff --git a/tests/ref/fate/webp b/tests/ref/fate/webp new file mode 100644 index 0000000..ced2ead --- /dev/null +++ b/tests/ref/fate/webp @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 135200, 0xc2e0319d diff --git a/tests/ref/fate/wmv8-drm-nodec b/tests/ref/fate/wmv8-drm-nodec index d6bf15e..679bc7e 100644 --- a/tests/ref/fate/wmv8-drm-nodec +++ b/tests/ref/fate/wmv8-drm-nodec @@ -146,7 +146,6 @@ 0, 6666, 6666, 41, 1349, 0x02adaaf3 0, 6708, 6708, 41, 1464, 0x20d7cfd2 0, 6750, 6750, 41, 1377, 0x78e0b1f4 -0, 6791, 6791, 41, 289, 0x1f2e9246 1, 6878, 6878, 0, 1088, 0x678f20fd 1, 7161, 7161, 0, 1088, 0x718afa20 1, 7444, 7444, 0, 1088, 0x758f0939 diff --git a/tests/ref/fate/wmv8-intrax8 b/tests/ref/fate/wmv8-intrax8 new file mode 100644 index 0000000..103e8da --- /dev/null +++ b/tests/ref/fate/wmv8-intrax8 @@ -0,0 +1,475 @@ +#tb 0: 1/1000 +0, 0, 0, 0, 115200, 0x03fbd838 +0, 200, 200, 0, 115200, 0x8911d86f +0, 266, 266, 0, 115200, 0x7c5dd82e +0, 333, 333, 0, 115200, 0x7c5ed82e +0, 2000, 2000, 0, 115200, 0xd323d838 +0, 2066, 2066, 0, 115200, 0x6e7479ab +0, 2133, 2133, 0, 115200, 0x14674bf6 +0, 2200, 2200, 0, 115200, 0x074c2e3d +0, 2266, 2266, 0, 115200, 0x9b3025ef +0, 2333, 2333, 0, 115200, 0x76882dae +0, 2400, 2400, 0, 115200, 0xedf3421b +0, 2466, 2466, 0, 115200, 0xb5378486 +0, 2533, 2533, 0, 115200, 0xc4a53420 +0, 2600, 2600, 0, 115200, 0x559cb60f +0, 2666, 2666, 0, 115200, 0xcc034ddd +0, 2733, 2733, 0, 115200, 0xb77b7779 +0, 2800, 2800, 0, 115200, 0x0ad9c3e6 +0, 2866, 2866, 0, 115200, 0x4e673027 +0, 2933, 2933, 0, 115200, 0x54717979 +0, 3000, 3000, 0, 115200, 0xf9e557c9 +0, 3066, 3066, 0, 115200, 0xbdcf6358 +0, 3133, 3133, 0, 115200, 0xd55c7bb7 +0, 3200, 3200, 0, 115200, 0x78d171e7 +0, 3266, 3266, 0, 115200, 0x28715816 +0, 3333, 3333, 0, 115200, 0x58740b8a +0, 3400, 3400, 0, 115200, 0x86c10f18 +0, 3466, 3466, 0, 115200, 0x903918f9 +0, 3533, 3533, 0, 115200, 0x7f742394 +0, 3600, 3600, 0, 115200, 0xd3a91d44 +0, 3666, 3666, 0, 115200, 0x24452563 +0, 3733, 3733, 0, 115200, 0x1b0c320e +0, 3800, 3800, 0, 115200, 0x3a493c8e +0, 3866, 3866, 0, 115200, 0xebe445ec +0, 3933, 3933, 0, 115200, 0xd2c54c8c +0, 4000, 4000, 0, 115200, 0x4aa15593 +0, 4066, 4066, 0, 115200, 0x19a35cc1 +0, 4133, 4133, 0, 115200, 0x968c6ee7 +0, 4200, 4200, 0, 115200, 0x9f7c7808 +0, 4266, 4266, 0, 115200, 0xa23980ee +0, 4333, 4333, 0, 115200, 0xcf3089c3 +0, 4400, 4400, 0, 115200, 0x43f78d5c +0, 4466, 4466, 0, 115200, 0x43caa1d4 +0, 4533, 4533, 0, 115200, 0x025594c3 +0, 4600, 4600, 0, 115200, 0x5ec8a11c +0, 4666, 4666, 0, 115200, 0x7f2a959b +0, 4733, 4733, 0, 115200, 0xc602852d +0, 4800, 4800, 0, 115200, 0x67737ef5 +0, 4866, 4866, 0, 115200, 0x81e06efe +0, 4933, 4933, 0, 115200, 0xdb0a484f +0, 5000, 5000, 0, 115200, 0xf30e4418 +0, 5066, 5066, 0, 115200, 0xbdd1310d +0, 5133, 5133, 0, 115200, 0x0d2a58ca +0, 5200, 5200, 0, 115200, 0xa428b4ba +0, 5266, 5266, 0, 115200, 0x4b850596 +0, 5333, 5333, 0, 115200, 0x38d3ecc0 +0, 5400, 5400, 0, 115200, 0x6bb0ed23 +0, 5466, 5466, 0, 115200, 0xb56eedaf +0, 5533, 5533, 0, 115200, 0xde81f828 +0, 5600, 5600, 0, 115200, 0x334abf89 +0, 5666, 5666, 0, 115200, 0x8e8ebd78 +0, 5733, 5733, 0, 115200, 0x96ba99c8 +0, 5800, 5800, 0, 115200, 0x2c8e0abd +0, 5866, 5866, 0, 115200, 0xe1ab8f9f +0, 5933, 5933, 0, 115200, 0xb2f95da4 +0, 6000, 6000, 0, 115200, 0x2e536d62 +0, 6066, 6066, 0, 115200, 0xdd78f3ab +0, 6133, 6133, 0, 115200, 0xea1cdaaa +0, 6200, 6200, 0, 115200, 0x4e653cc0 +0, 6266, 6266, 0, 115200, 0x95e38123 +0, 6333, 6333, 0, 115200, 0x20964119 +0, 6400, 6400, 0, 115200, 0xcd08ea74 +0, 6466, 6466, 0, 115200, 0x0eee2a96 +0, 6533, 6533, 0, 115200, 0x966662c9 +0, 6600, 6600, 0, 115200, 0x975893b4 +0, 6666, 6666, 0, 115200, 0x0aa888a7 +0, 6733, 6733, 0, 115200, 0x80dab966 +0, 6800, 6800, 0, 115200, 0x78bb8f95 +0, 6866, 6866, 0, 115200, 0x9c71d03f +0, 6933, 6933, 0, 115200, 0xbe5db887 +0, 7000, 7000, 0, 115200, 0xa88e00d0 +0, 7066, 7066, 0, 115200, 0xc7b50827 +0, 7133, 7133, 0, 115200, 0xf9155ed3 +0, 7200, 7200, 0, 115200, 0x8dd72d44 +0, 7266, 7266, 0, 115200, 0xee38183a +0, 7333, 7333, 0, 115200, 0xea2b6329 +0, 7400, 7400, 0, 115200, 0xf556c2b3 +0, 7466, 7466, 0, 115200, 0x90edebf9 +0, 7533, 7533, 0, 115200, 0x4f440fdf +0, 7600, 7600, 0, 115200, 0xfdec7a9d +0, 7666, 7666, 0, 115200, 0xc7927952 +0, 7733, 7733, 0, 115200, 0xdd475704 +0, 7800, 7800, 0, 115200, 0x974a61a5 +0, 7866, 7866, 0, 115200, 0xbf2b785e +0, 7933, 7933, 0, 115200, 0x5de451fa +0, 8000, 8000, 0, 115200, 0x3fac503e +0, 8066, 8066, 0, 115200, 0xc6785643 +0, 8133, 8133, 0, 115200, 0xe6666254 +0, 8200, 8200, 0, 115200, 0x1a05130c +0, 8266, 8266, 0, 115200, 0x082cea5d +0, 8333, 8333, 0, 115200, 0x473ef142 +0, 8400, 8400, 0, 115200, 0x9769a776 +0, 8466, 8466, 0, 115200, 0xe6e841af +0, 8533, 8533, 0, 115200, 0xa44c8d1e +0, 8600, 8600, 0, 115200, 0xd03d641b +0, 8666, 8666, 0, 115200, 0x3aea3c9e +0, 8733, 8733, 0, 115200, 0x09efcf21 +0, 8800, 8800, 0, 115200, 0xeeb6ff64 +0, 8866, 8866, 0, 115200, 0xa310af6f +0, 8933, 8933, 0, 115200, 0x2488519e +0, 9000, 9000, 0, 115200, 0x48e1febf +0, 9066, 9066, 0, 115200, 0x76d00513 +0, 9133, 9133, 0, 115200, 0xa28eda81 +0, 9200, 9200, 0, 115200, 0xc2cbdcae +0, 9266, 9266, 0, 115200, 0xd976c9b2 +0, 9333, 9333, 0, 115200, 0xb0abebab +0, 9400, 9400, 0, 115200, 0x32be4765 +0, 9466, 9466, 0, 115200, 0xc0a36b11 +0, 9533, 9533, 0, 115200, 0xb6d1d47f +0, 9600, 9600, 0, 115200, 0xab7954a6 +0, 9666, 9666, 0, 115200, 0xc485789c +0, 9733, 9733, 0, 115200, 0xa07101b6 +0, 9800, 9800, 0, 115200, 0x6297780a +0, 9866, 9866, 0, 115200, 0xf550ba94 +0, 9933, 9933, 0, 115200, 0x9b77f994 +0, 10000, 10000, 0, 115200, 0xb0e870ad +0, 10066, 10066, 0, 115200, 0x2dd89b0b +0, 10133, 10133, 0, 115200, 0x36dcfe2f +0, 10200, 10200, 0, 115200, 0x3e5e1a8f +0, 10266, 10266, 0, 115200, 0xb8394740 +0, 10333, 10333, 0, 115200, 0xbfc852fc +0, 10400, 10400, 0, 115200, 0x5b3f8aa2 +0, 10466, 10466, 0, 115200, 0xc29d8e3a +0, 10533, 10533, 0, 115200, 0x7300abd8 +0, 10600, 10600, 0, 115200, 0xd1dd7a3b +0, 10666, 10666, 0, 115200, 0xe5978f39 +0, 10733, 10733, 0, 115200, 0x235c6b8d +0, 10800, 10800, 0, 115200, 0xec1b5805 +0, 10866, 10866, 0, 115200, 0x16d23946 +0, 10933, 10933, 0, 115200, 0xa8de1cf4 +0, 11000, 11000, 0, 115200, 0x5e730512 +0, 11066, 11066, 0, 115200, 0x1250feed +0, 11133, 11133, 0, 115200, 0x0928c190 +0, 11200, 11200, 0, 115200, 0xa25d9e5c +0, 11266, 11266, 0, 115200, 0x921068ea +0, 11333, 11333, 0, 115200, 0x2c974ddb +0, 11400, 11400, 0, 115200, 0x35ae4d75 +0, 11466, 11466, 0, 115200, 0xec0c6469 +0, 11533, 11533, 0, 115200, 0x22704fad +0, 11600, 11600, 0, 115200, 0x0a9a5aed +0, 11666, 11666, 0, 115200, 0x45192f2f +0, 11733, 11733, 0, 115200, 0xc07b39f4 +0, 11800, 11800, 0, 115200, 0x32c60215 +0, 11866, 11866, 0, 115200, 0xda65035e +0, 11933, 11933, 0, 115200, 0x99d0cd81 +0, 12000, 12000, 0, 115200, 0xd08ca5e3 +0, 12066, 12066, 0, 115200, 0x82cdad17 +0, 12133, 12133, 0, 115200, 0x2587a420 +0, 12200, 12200, 0, 115200, 0x85cba73d +0, 12266, 12266, 0, 115200, 0x4677bf89 +0, 12333, 12333, 0, 115200, 0x84c2e034 +0, 12400, 12400, 0, 115200, 0xd343066c +0, 12466, 12466, 0, 115200, 0xdec716a1 +0, 12533, 12533, 0, 115200, 0x93c04f5d +0, 12600, 12600, 0, 115200, 0xce126ac4 +0, 12666, 12666, 0, 115200, 0xa20098c5 +0, 12733, 12733, 0, 115200, 0x9a4ca711 +0, 12800, 12800, 0, 115200, 0xfae9c154 +0, 12866, 12866, 0, 115200, 0xb34cc431 +0, 12933, 12933, 0, 115200, 0x923cdec2 +0, 13000, 13000, 0, 115200, 0x60ffdfe8 +0, 13066, 13066, 0, 115200, 0xa3e6f9f2 +0, 13133, 13133, 0, 115200, 0x374f0a47 +0, 13200, 13200, 0, 115200, 0x8fb228f1 +0, 13266, 13266, 0, 115200, 0x4c1a24bf +0, 13333, 13333, 0, 115200, 0x768a52d1 +0, 13400, 13400, 0, 115200, 0x5bf77025 +0, 13466, 13466, 0, 115200, 0x6ca67c2a +0, 13533, 13533, 0, 115200, 0x107ca3e9 +0, 13600, 13600, 0, 115200, 0x4abeda93 +0, 13666, 13666, 0, 115200, 0x750be9ff +0, 13733, 13733, 0, 115200, 0x28c5eee3 +0, 13800, 13800, 0, 115200, 0xa1b0e4b2 +0, 13866, 13866, 0, 115200, 0x2ae7f33d +0, 13933, 13933, 0, 115200, 0xf29cdae0 +0, 14000, 14000, 0, 115200, 0xd470f9ed +0, 14066, 14066, 0, 115200, 0x2d22f832 +0, 14133, 14133, 0, 115200, 0xc5b91780 +0, 14200, 14200, 0, 115200, 0x3d8e4151 +0, 14266, 14266, 0, 115200, 0x459f58e0 +0, 14333, 14333, 0, 115200, 0x8dc198fe +0, 14400, 14400, 0, 115200, 0x2479f579 +0, 14466, 14466, 0, 115200, 0xc2040c21 +0, 14533, 14533, 0, 115200, 0x39ad60d5 +0, 14600, 14600, 0, 115200, 0x9329dd37 +0, 14666, 14666, 0, 115200, 0xa08807da +0, 14733, 14733, 0, 115200, 0xbf514cd1 +0, 14800, 14800, 0, 115200, 0x8b66a779 +0, 14866, 14866, 0, 115200, 0x865ebff5 +0, 14933, 14933, 0, 115200, 0x5967074c +0, 15000, 15000, 0, 115200, 0xd5521f60 +0, 15066, 15066, 0, 115200, 0x462c329c +0, 15133, 15133, 0, 115200, 0xbefd36fb +0, 15200, 15200, 0, 115200, 0x6f58403b +0, 15266, 15266, 0, 115200, 0xe4af2fac +0, 15333, 15333, 0, 115200, 0x46453662 +0, 15400, 15400, 0, 115200, 0x72cc59e8 +0, 15466, 15466, 0, 115200, 0xd6c67f8e +0, 15533, 15533, 0, 115200, 0xd35674a7 +0, 15600, 15600, 0, 115200, 0x65785ddb +0, 15666, 15666, 0, 115200, 0xfd7958aa +0, 15733, 15733, 0, 115200, 0x93e45607 +0, 15800, 15800, 0, 115200, 0x196a4fa5 +0, 15866, 15866, 0, 115200, 0xe33a5dac +0, 15933, 15933, 0, 115200, 0x4e66904a +0, 16000, 16000, 0, 115200, 0xc1e3a50a +0, 16066, 16066, 0, 115200, 0xa685b351 +0, 16133, 16133, 0, 115200, 0xee2fdeb7 +0, 16200, 16200, 0, 115200, 0x189cefdd +0, 16266, 16266, 0, 115200, 0xbdf90506 +0, 16333, 16333, 0, 115200, 0xe72c23d2 +0, 16400, 16400, 0, 115200, 0xa3f65e7b +0, 16466, 16466, 0, 115200, 0x8bc67eee +0, 16533, 16533, 0, 115200, 0xd305d09b +0, 16600, 16600, 0, 115200, 0xc521eba5 +0, 16666, 16666, 0, 115200, 0x16cf161f +0, 16733, 16733, 0, 115200, 0x2ce322b5 +0, 16800, 16800, 0, 115200, 0x57ce82b4 +0, 16866, 16866, 0, 115200, 0x8da896b9 +0, 16933, 16933, 0, 115200, 0xc16ad590 +0, 17000, 17000, 0, 115200, 0x8cdbe729 +0, 17066, 17066, 0, 115200, 0x69eafd96 +0, 17133, 17133, 0, 115200, 0xd9e40a03 +0, 17200, 17200, 0, 115200, 0xb91423e1 +0, 17266, 17266, 0, 115200, 0x09b516bd +0, 17333, 17333, 0, 115200, 0x20292b85 +0, 17400, 17400, 0, 115200, 0x8cbb4aeb +0, 17466, 17466, 0, 115200, 0x99b761ec +0, 17533, 17533, 0, 115200, 0x28406a14 +0, 17600, 17600, 0, 115200, 0xea368c86 +0, 17666, 17666, 0, 115200, 0xf388ab54 +0, 17733, 17733, 0, 115200, 0x263fe1de +0, 17800, 17800, 0, 115200, 0xc3410c39 +0, 17866, 17866, 0, 115200, 0xc056244d +0, 17933, 17933, 0, 115200, 0x99c51fc5 +0, 18000, 18000, 0, 115200, 0x7e4a0d07 +0, 18066, 18066, 0, 115200, 0xcd911916 +0, 18133, 18133, 0, 115200, 0x8bd0fa21 +0, 18200, 18200, 0, 115200, 0xd1a1ab71 +0, 18266, 18266, 0, 115200, 0xbc904028 +0, 18333, 18333, 0, 115200, 0xfd480acc +0, 18400, 18400, 0, 115200, 0x1cb5c8b5 +0, 18466, 18466, 0, 115200, 0xcad15709 +0, 18533, 18533, 0, 115200, 0xdd306f19 +0, 18600, 18600, 0, 115200, 0x3f975f1b +0, 18666, 18666, 0, 115200, 0x2386cd1f +0, 18733, 18733, 0, 115200, 0xcaa4f5b0 +0, 18800, 18800, 0, 115200, 0x8ce213de +0, 18866, 18866, 0, 115200, 0x5f7407c6 +0, 18932, 18932, 0, 115200, 0x01b3ee00 +0, 18998, 18998, 0, 115200, 0x92759715 +0, 19064, 19064, 0, 115200, 0x4a208e1e +0, 19133, 19133, 0, 115200, 0x6e1b80a5 +0, 19200, 19200, 0, 115200, 0xe78c7622 +0, 19266, 19266, 0, 115200, 0xcc255da9 +0, 19333, 19333, 0, 115200, 0x69e561cb +0, 19400, 19400, 0, 115200, 0x2d135227 +0, 19466, 19466, 0, 115200, 0xfc6a5e4d +0, 19533, 19533, 0, 115200, 0x81473914 +0, 19600, 19600, 0, 115200, 0xe50831b2 +0, 19666, 19666, 0, 115200, 0xe7d2228f +0, 19733, 19733, 0, 115200, 0xe6992f1a +0, 19800, 19800, 0, 115200, 0x1e533698 +0, 19866, 19866, 0, 115200, 0x0c63558c +0, 19933, 19933, 0, 115200, 0x54990104 +0, 20000, 20000, 0, 115200, 0xce14fc4d +0, 20066, 20066, 0, 115200, 0x760b5c6e +0, 20133, 20133, 0, 115200, 0x14157b61 +0, 20200, 20200, 0, 115200, 0x62ca7972 +0, 20266, 20266, 0, 115200, 0xe99573ce +0, 20333, 20333, 0, 115200, 0x36df4b8d +0, 20400, 20400, 0, 115200, 0x272238ea +0, 20466, 20466, 0, 115200, 0x606e3863 +0, 20533, 20533, 0, 115200, 0x8b143873 +0, 20600, 20600, 0, 115200, 0x2e46db9e +0, 20666, 20666, 0, 115200, 0x1131ad78 +0, 20733, 20733, 0, 115200, 0x52f34951 +0, 20800, 20800, 0, 115200, 0xd4590eea +0, 20866, 20866, 0, 115200, 0x44ddeaa2 +0, 20933, 20933, 0, 115200, 0xbc83c399 +0, 21000, 21000, 0, 115200, 0x5e9da9a7 +0, 21066, 21066, 0, 115200, 0xca6a8dfc +0, 21133, 21133, 0, 115200, 0xe17b3ff8 +0, 21200, 21200, 0, 115200, 0xea1f375c +0, 21266, 21266, 0, 115200, 0xa265143b +0, 21333, 21333, 0, 115200, 0xe788fa1e +0, 21400, 21400, 0, 115200, 0xd58be649 +0, 21466, 21466, 0, 115200, 0x740c1f19 +0, 21533, 21533, 0, 115200, 0xfab3302f +0, 21600, 21600, 0, 115200, 0x1c954fc7 +0, 21666, 21666, 0, 115200, 0xd57a5923 +0, 21733, 21733, 0, 115200, 0x099745d9 +0, 21800, 21800, 0, 115200, 0x2e61cc66 +0, 21866, 21866, 0, 115200, 0xdb3ec93a +0, 21933, 21933, 0, 115200, 0x553ba839 +0, 22000, 22000, 0, 115200, 0xfafc6b60 +0, 22066, 22066, 0, 115200, 0xa3fb39b6 +0, 22133, 22133, 0, 115200, 0x7fb9d7be +0, 22200, 22200, 0, 115200, 0x7e73cd93 +0, 22266, 22266, 0, 115200, 0xa43ec5f2 +0, 22333, 22333, 0, 115200, 0x3ec077c1 +0, 22400, 22400, 0, 115200, 0xc4275815 +0, 22466, 22466, 0, 115200, 0xf84c17bf +0, 22533, 22533, 0, 115200, 0x1f54d44d +0, 22600, 22600, 0, 115200, 0x566fa5bb +0, 22666, 22666, 0, 115200, 0x82179a82 +0, 22733, 22733, 0, 115200, 0xf8865f3d +0, 22800, 22800, 0, 115200, 0xa5fb7b80 +0, 22866, 22866, 0, 115200, 0x9aebc04d +0, 22933, 22933, 0, 115200, 0x44c705fc +0, 23000, 23000, 0, 115200, 0xd322add3 +0, 23066, 23066, 0, 115200, 0xf4230b76 +0, 23133, 23133, 0, 115200, 0xaa915069 +0, 23200, 23200, 0, 115200, 0x518d53d8 +0, 23266, 23266, 0, 115200, 0xefa7d909 +0, 23333, 23333, 0, 115200, 0x803c3c0e +0, 23400, 23400, 0, 115200, 0x5650bc0a +0, 23466, 23466, 0, 115200, 0x8b34ecab +0, 23533, 23533, 0, 115200, 0x975c4976 +0, 23600, 23600, 0, 115200, 0x700e3cb4 +0, 23666, 23666, 0, 115200, 0xef27a4ec +0, 23733, 23733, 0, 115200, 0x2b953936 +0, 23800, 23800, 0, 115200, 0xcf9b4956 +0, 23866, 23866, 0, 115200, 0xae4a8eba +0, 23933, 23933, 0, 115200, 0xf8821144 +0, 24000, 24000, 0, 115200, 0x97c2402c +0, 24066, 24066, 0, 115200, 0x209b7bb3 +0, 24133, 24133, 0, 115200, 0xd22fff2c +0, 24200, 24200, 0, 115200, 0xe85b4f16 +0, 24266, 24266, 0, 115200, 0x0659f318 +0, 24333, 24333, 0, 115200, 0x6e2bff98 +0, 24400, 24400, 0, 115200, 0xc6626f2f +0, 24466, 24466, 0, 115200, 0x123138e2 +0, 24533, 24533, 0, 115200, 0x69e680ab +0, 24600, 24600, 0, 115200, 0xe4d7cd1d +0, 24666, 24666, 0, 115200, 0x4ca10d47 +0, 24733, 24733, 0, 115200, 0x633a4c39 +0, 24800, 24800, 0, 115200, 0x64ded292 +0, 24866, 24866, 0, 115200, 0x88d2df42 +0, 24933, 24933, 0, 115200, 0x998f4c63 +0, 25000, 25000, 0, 115200, 0x753c76f9 +0, 25066, 25066, 0, 115200, 0x9d7ba0a6 +0, 25133, 25133, 0, 115200, 0x68798da5 +0, 25200, 25200, 0, 115200, 0xb5b18bc3 +0, 25266, 25266, 0, 115200, 0x20245e49 +0, 25333, 25333, 0, 115200, 0xf15d4b8f +0, 25400, 25400, 0, 115200, 0x17f83b69 +0, 25466, 25466, 0, 115200, 0xcc545783 +0, 25533, 25533, 0, 115200, 0x3dad530e +0, 25600, 25600, 0, 115200, 0x6b465c94 +0, 25666, 25666, 0, 115200, 0xbc5f3831 +0, 25733, 25733, 0, 115200, 0x1b2f042d +0, 25800, 25800, 0, 115200, 0xaec391ac +0, 25866, 25866, 0, 115200, 0x99fa8b2a +0, 25933, 25933, 0, 115200, 0xf78d3524 +0, 26000, 26000, 0, 115200, 0xe6255a24 +0, 26066, 26066, 0, 115200, 0x253542c6 +0, 26133, 26133, 0, 115200, 0xfab05365 +0, 26200, 26200, 0, 115200, 0x406a3749 +0, 26266, 26266, 0, 115200, 0xaf0f3935 +0, 26333, 26333, 0, 115200, 0x0d9ff780 +0, 26400, 26400, 0, 115200, 0xfadcfc15 +0, 26466, 26466, 0, 115200, 0x8267d5ad +0, 26533, 26533, 0, 115200, 0xd705d250 +0, 26600, 26600, 0, 115200, 0x18f9d1f2 +0, 26666, 26666, 0, 115200, 0xd92bc045 +0, 26733, 26733, 0, 115200, 0x439b9ca0 +0, 26800, 26800, 0, 115200, 0xcb80a14c +0, 26866, 26866, 0, 115200, 0xee887f49 +0, 26933, 26933, 0, 115200, 0xfba297eb +0, 27000, 27000, 0, 115200, 0x0e2f744b +0, 27066, 27066, 0, 115200, 0xaa227aa7 +0, 27133, 27133, 0, 115200, 0xd7bc6fff +0, 27200, 27200, 0, 115200, 0x295c91cf +0, 27266, 27266, 0, 115200, 0xc5678733 +0, 27333, 27333, 0, 115200, 0xc8d49120 +0, 27400, 27400, 0, 115200, 0xb14e90b9 +0, 27466, 27466, 0, 115200, 0x6a09acab +0, 27533, 27533, 0, 115200, 0xb9aec358 +0, 27600, 27600, 0, 115200, 0xeb3695b2 +0, 27666, 27666, 0, 115200, 0xc5bebd62 +0, 27733, 27733, 0, 115200, 0x2d6b1a3f +0, 27800, 27800, 0, 115200, 0x92986f49 +0, 27866, 27866, 0, 115200, 0x00c37cf9 +0, 27933, 27933, 0, 115200, 0x5a4d87a6 +0, 28000, 28000, 0, 115200, 0xe87888a2 +0, 28066, 28066, 0, 115200, 0x4ab18d6d +0, 28133, 28133, 0, 115200, 0xcb84880b +0, 28200, 28200, 0, 115200, 0x82458848 +0, 28266, 28266, 0, 115200, 0x11b477dc +0, 28333, 28333, 0, 115200, 0x56d876d3 +0, 28400, 28400, 0, 115200, 0xf5297ceb +0, 28466, 28466, 0, 115200, 0x47357713 +0, 28533, 28533, 0, 115200, 0xede562df +0, 28600, 28600, 0, 115200, 0xabf42d38 +0, 28666, 28666, 0, 115200, 0xea9225c8 +0, 28733, 28733, 0, 115200, 0x79ce1cb4 +0, 28800, 28800, 0, 115200, 0x0cd418b4 +0, 28866, 28866, 0, 115200, 0x6f7c118e +0, 28933, 28933, 0, 115200, 0xbbbc0fa4 +0, 29000, 29000, 0, 115200, 0x890514e6 +0, 29066, 29066, 0, 115200, 0x9c4d0e7d +0, 29133, 29133, 0, 115200, 0x56260e76 +0, 29200, 29200, 0, 115200, 0x7dc80258 +0, 29266, 29266, 0, 115200, 0xa990f5a3 +0, 29333, 29333, 0, 115200, 0x2174e913 +0, 29400, 29400, 0, 115200, 0x8296e674 +0, 29466, 29466, 0, 115200, 0x9e28e3b4 +0, 29533, 29533, 0, 115200, 0x404ce72b +0, 29600, 29600, 0, 115200, 0xc7cbf4ec +0, 29666, 29666, 0, 115200, 0x5ce0f5a1 +0, 29733, 29733, 0, 115200, 0x88dbf7c7 +0, 29800, 29800, 0, 115200, 0x26daf35a +0, 29866, 29866, 0, 115200, 0x5cfdfe63 +0, 29933, 29933, 0, 115200, 0xdd40fb9b +0, 30000, 30000, 0, 115200, 0x5b8df20f +0, 30066, 30066, 0, 115200, 0x4f2ce5ac +0, 30133, 30133, 0, 115200, 0xc9d0e0c2 +0, 30200, 30200, 0, 115200, 0x51c7e2a6 +0, 30266, 30266, 0, 115200, 0xb3bae109 +0, 30333, 30333, 0, 115200, 0xbd85e5b2 +0, 30400, 30400, 0, 115200, 0x1fbbdfd1 +0, 30466, 30466, 0, 115200, 0x3665dfd0 +0, 30533, 30533, 0, 115200, 0xcd29d50c +0, 30600, 30600, 0, 115200, 0xedd1c6bc +0, 30666, 30666, 0, 115200, 0xebc2d072 +0, 30733, 30733, 0, 115200, 0xe2e5fbbd +0, 30800, 30800, 0, 115200, 0x616a13dc +0, 30866, 30866, 0, 115200, 0xf64f1efc +0, 30933, 30933, 0, 115200, 0x5356235f +0, 31000, 31000, 0, 115200, 0xafc032d5 +0, 31066, 31066, 0, 115200, 0xaa034420 +0, 31133, 31133, 0, 115200, 0x007e0afa +0, 31200, 31200, 0, 115200, 0x077ad5c8 +0, 31266, 31266, 0, 115200, 0x8fc815b8 +0, 31333, 31333, 0, 115200, 0x95b85990 +0, 31400, 31400, 0, 115200, 0x46f5899f +0, 31466, 31466, 0, 115200, 0x1e37cd82 +0, 31533, 31533, 0, 115200, 0x3ce90bfd +0, 31600, 31600, 0, 115200, 0xbb95bd1d +0, 31666, 31666, 0, 115200, 0xd4aa9ba8 +0, 31733, 31733, 0, 115200, 0x0e761649 +0, 31800, 31800, 0, 115200, 0x49ad7886 +0, 31866, 31866, 0, 115200, 0x2f4184df +0, 31933, 31933, 0, 115200, 0x80b906ee +0, 32000, 32000, 0, 115200, 0x62405100 +0, 32066, 32066, 0, 115200, 0x3ece13b5 +0, 32133, 32133, 0, 115200, 0x3abd4cfc +0, 32200, 32200, 0, 115200, 0x91b418e3 +0, 32266, 32266, 0, 115200, 0xde1ce68e +0, 32333, 32333, 0, 115200, 0xfc47f912 +0, 32400, 32400, 0, 115200, 0x5b380a6f +0, 32466, 32466, 0, 115200, 0x8f35c3c0 +0, 32533, 32533, 0, 115200, 0xb26dc220 +0, 32599, 32599, 0, 115200, 0x3d5bbfce +0, 32665, 32665, 0, 115200, 0xa1f9bee6 +0, 32731, 32731, 0, 115200, 0xa87dcd24 +0, 32797, 32797, 0, 115200, 0x9374cb71 +0, 32863, 32863, 0, 115200, 0x0c7ccbd0 +0, 32929, 32929, 0, 115200, 0x9a16cc49 +0, 32995, 32995, 0, 115200, 0x4df0c28b +0, 33061, 33061, 0, 115200, 0xb5b8b866 +0, 33133, 33133, 0, 115200, 0xafcc1019 +0, 34000, 34000, 0, 115200, 0x623b0ff3 +0, 34133, 34133, 0, 115200, 0x1d6f10b5 diff --git a/tests/ref/fate/wtv-demux b/tests/ref/fate/wtv-demux index bdd6c20..ae44958 100644 --- a/tests/ref/fate/wtv-demux +++ b/tests/ref/fate/wtv-demux @@ -59,83 +59,83 @@ 0, 11486331, 11486331, 400000, 6156, 0xe168394b 1, 11519998, 11519998, 240000, 576, 0x1fea1448 1, 11759998, 11759998, 240000, 576, 0x55840a01 -0, 11886331, 13086442, 449438, 23364, 0x53164f1e +0, 11886331, 13086442, 400000, 23364, 0x53164f1e 1, 11999998, 11999998, 240000, 576, 0x6c9c24ce 1, 12239998, 12239998, 240000, 576, 0x955f1e97 -0, 12286442, 12286442, 449438, 6708, 0x89877269 +0, 12286442, 12286442, 400000, 6708, 0x89877269 1, 12479998, 12479998, 240000, 576, 0x2827134f -0, 12686442, 12686442, 449438, 6908, 0x8d62a249 +0, 12686442, 12686442, 400000, 6908, 0x8d62a249 1, 12719998, 12719998, 240000, 576, 0x34a01c29 1, 12959998, 12959998, 240000, 576, 0x7d351e52 -0, 13086442, 14286442, 449438, 38156, 0xec41f682 +0, 13086442, 14286442, 400000, 38156, 0xec41f682 1, 13199998, 13199998, 240000, 576, 0x00c91d9e 1, 13439998, 13439998, 240000, 576, 0x57ea1a97 -0, 13486331, 13486331, 449438, 5764, 0xcc04534b +0, 13486331, 13486331, 400000, 5764, 0xcc04534b 1, 13679998, 13679998, 240000, 576, 0xef3a1c74 -0, 13886331, 13886331, 449438, 5388, 0xb8a1c3c5 +0, 13886331, 13886331, 400000, 5388, 0xb8a1c3c5 1, 13919998, 13919998, 240000, 576, 0x11fc217d 1, 14159998, 14159998, 240000, 576, 0x59ce20e5 -0, 14286442, 15486331, 449438, 16764, 0x59460d96 +0, 14286442, 15486331, 400000, 16764, 0x59460d96 1, 14399998, 14399998, 240000, 576, 0xaafc1dbf 1, 14639998, 14639998, 240000, 576, 0xdd941609 -0, 14686331, 14686331, 449438, 5548, 0x5c91e93d +0, 14686331, 14686331, 400000, 5548, 0x5c91e93d 1, 14879998, 14879998, 240000, 576, 0x900420b0 -0, 15086331, 15086331, 449438, 5652, 0x5e321aed +0, 15086331, 15086331, 400000, 5652, 0x5e321aed 1, 15119998, 15119998, 240000, 576, 0x5f4f1aa1 1, 15359998, 15359998, 240000, 576, 0x7d7e18de -0, 15486331, 16686331, 449438, 15564, 0xefdf5080 +0, 15486331, 16686331, 400000, 15564, 0xefdf5080 1, 15599998, 15599998, 240000, 576, 0x986c0d9d 1, 15839998, 15839998, 240000, 576, 0xcb4c21c0 -0, 15886331, 15886331, 449438, 6492, 0xd1d5c5f8 +0, 15886331, 15886331, 400000, 6492, 0xd1d5c5f8 1, 16079998, 16079998, 240000, 576, 0xbcfb1e8b -0, 16286331, 16286331, 449438, 5604, 0xf9472b44 +0, 16286331, 16286331, 400000, 5604, 0xf9472b44 1, 16319998, 16319998, 240000, 576, 0xcb541b4c 1, 16559998, 16559998, 240000, 576, 0x980426e9 -0, 16686331, 17886331, 449438, 17924, 0x45815b7b +0, 16686331, 17886331, 400000, 17924, 0x45815b7b 1, 16799998, 16799998, 240000, 576, 0x09d00aa0 1, 17039998, 17039998, 240000, 576, 0xad591374 -0, 17086442, 17086442, 449438, 5020, 0x3cc5e554 +0, 17086442, 17086442, 400000, 5020, 0x3cc5e554 1, 17279998, 17279998, 240000, 576, 0x97bf1461 -0, 17486442, 17486442, 449438, 5276, 0xa0554c12 +0, 17486442, 17486442, 400000, 5276, 0xa0554c12 1, 17519998, 17519998, 240000, 576, 0xdc871cc4 1, 17759998, 17759998, 240000, 576, 0x56781896 -0, 17886331, 19086442, 449438, 31460, 0x5765eb5f +0, 17886331, 19086442, 400000, 31460, 0x5765eb5f 1, 17999998, 17999998, 240000, 576, 0xc77714e3 1, 18239998, 18239998, 240000, 576, 0x280e18d4 -0, 18286331, 18286331, 449438, 4972, 0x91adbab7 +0, 18286331, 18286331, 400000, 4972, 0x91adbab7 1, 18479998, 18479998, 240000, 576, 0xbc0d2302 -0, 18686442, 18686442, 449438, 5580, 0xfea707cb +0, 18686442, 18686442, 400000, 5580, 0xfea707cb 1, 18719998, 18719998, 240000, 576, 0x79191384 1, 18959998, 18959998, 240000, 576, 0x65481c97 -0, 19086442, 20286331, 449438, 17412, 0x0afe4d27 +0, 19086442, 20286331, 400000, 17412, 0x0afe4d27 1, 19199998, 19199998, 240000, 576, 0xc94d227d 1, 19439998, 19439998, 240000, 576, 0xa68a1f14 -0, 19486442, 19486442, 449438, 5236, 0x03f55309 +0, 19486442, 19486442, 400000, 5236, 0x03f55309 1, 19679998, 19679998, 240000, 576, 0x6af11a5c -0, 19886331, 19886331, 449438, 4924, 0x558e753c +0, 19886331, 19886331, 400000, 4924, 0x558e753c 1, 19919998, 19919998, 240000, 576, 0x4d1019ef 1, 20159998, 20159998, 240000, 576, 0x3b1b17b5 -0, 20286331, 21486331, 449438, 15396, 0xf145d121 +0, 20286331, 21486331, 400000, 15396, 0xf145d121 1, 20399998, 20399998, 240000, 576, 0xcdd8159f 1, 20639998, 20639998, 240000, 576, 0x97cd1d06 -0, 20686331, 20686331, 449438, 4708, 0x43066a92 +0, 20686331, 20686331, 400000, 4708, 0x43066a92 1, 20879998, 20879998, 240000, 576, 0x5d1b1123 -0, 21086442, 21086442, 449438, 4332, 0x9e22bcba +0, 21086442, 21086442, 400000, 4332, 0x9e22bcba 1, 21119998, 21119998, 240000, 576, 0x888d0cb0 1, 21359998, 21359998, 240000, 576, 0x556e1dad -0, 21486331, 22686442, 449438, 12876, 0x46ff9ef4 +0, 21486331, 22686442, 400000, 12876, 0x46ff9ef4 1, 21599998, 21599998, 240000, 576, 0xf7af0bce 1, 21839998, 21839998, 240000, 576, 0xb5da160a -0, 21886442, 21886442, 449438, 5940, 0x27cba62e +0, 21886442, 21886442, 400000, 5940, 0x27cba62e 1, 22079998, 22079998, 240000, 576, 0x4a8d0e98 -0, 22286442, 22286442, 449438, 6124, 0x6bab0a6d +0, 22286442, 22286442, 400000, 6124, 0x6bab0a6d 1, 22319998, 22319998, 240000, 576, 0x183b1c7e 1, 22559998, 22559998, 240000, 576, 0xc47120e6 -0, 22686442, 23886442, 449438, 36428, 0x942f9648 +0, 22686442, 23886442, 400000, 36428, 0x942f9648 1, 22799998, 22799998, 240000, 576, 0xb1f31346 -0, 23086331, 23086331, 449438, 6660, 0x545a0db7 -0, 23486331, 23486331, 449438, 6780, 0x2d1d4189 -0, 23886442, 25086331, 449438, 16460, 0x7c3b3ca4 -0, 24286442, 24286442, 449438, 6724, 0x8538cc6f -0, 24686442, 24686442, 449438, 7068, 0x69574fd0 -0, 25086331, 26286331, 449438, 19552, 0xf230e854 +0, 23086331, 23086331, 400000, 6660, 0x545a0db7 +0, 23486331, 23486331, 400000, 6780, 0x2d1d4189 +0, 23886442, 25086331, 400000, 16460, 0x7c3b3ca4 +0, 24286442, 24286442, 400000, 6724, 0x8538cc6f +0, 24686442, 24686442, 400000, 7068, 0x69574fd0 +0, 25086331, 26286331, 400000, 19552, 0xf230e854 diff --git a/tests/ref/fate/xvid-idctmmx b/tests/ref/fate/xvid-idct similarity index 100% rename from tests/ref/fate/xvid-idctmmx rename to tests/ref/fate/xvid-idct diff --git a/tests/ref/fate/zmbv-8bit b/tests/ref/fate/zmbv-8bit index 64dacae..9f02ae3 100644 --- a/tests/ref/fate/zmbv-8bit +++ b/tests/ref/fate/zmbv-8bit @@ -274,3 +274,4 @@ 0, 272, 272, 1, 192000, 0xd08e49d1 0, 273, 273, 1, 192000, 0xd08e49d1 0, 274, 274, 1, 192000, 0xd08e49d1 +0, 275, 275, 1, 192000, 0x1f34135f diff --git a/tests/ref/lavf/dpx b/tests/ref/lavf/dpx index a9f1169..42c0a33 100644 --- a/tests/ref/lavf/dpx +++ b/tests/ref/lavf/dpx @@ -1,3 +1,3 @@ -808ea110635774252439722a48329d61 *./tests/data/images/dpx/02.dpx +d2f0b4e854fda2d3b3bee84cef80593c *./tests/data/images/dpx/02.dpx ./tests/data/images/dpx/%02d.dpx CRC=0x28c7369b 305792 ./tests/data/images/dpx/02.dpx diff --git a/tests/ref/lavf/flv_fmt b/tests/ref/lavf/flv_fmt index 019204d..3414d13 100644 --- a/tests/ref/lavf/flv_fmt +++ b/tests/ref/lavf/flv_fmt @@ -1,3 +1,3 @@ -822735e9d25b3eb22529f444a71840c3 *./tests/data/lavf/lavf.flv +689e8e53031a2c0793fb5b99fc6f1024 *./tests/data/lavf/lavf.flv 329521 ./tests/data/lavf/lavf.flv ./tests/data/lavf/lavf.flv CRC=0x881785d1 diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index a871ea9..db0aba0 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ -268fb8f9278b0df2f87a6a9455f3cd56 *./tests/data/lavf/lavf.mkv -320380 ./tests/data/lavf/lavf.mkv +76d400179dfd6143f50ea4d19fe8ed99 *./tests/data/lavf/lavf.mkv +320383 ./tests/data/lavf/lavf.mkv ./tests/data/lavf/lavf.mkv CRC=0x36193cda diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index 5864e8e..8a62bb0 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -8cf467a910c84dd05db24848becba42e *./tests/data/lavf/lavf.mxf_d10 +96f933913835a439dd97144303dc8929 *./tests/data/lavf/lavf.mxf_d10 5330989 ./tests/data/lavf/lavf.mxf_d10 ./tests/data/lavf/lavf.mxf_d10 CRC=0x4474d480 diff --git a/tests/ref/lavf/nut b/tests/ref/lavf/nut index d7a8ab1..bdbe823 100644 --- a/tests/ref/lavf/nut +++ b/tests/ref/lavf/nut @@ -1,3 +1,3 @@ -8c9d5193a672ad0dee90f0712acc3a31 *./tests/data/lavf/lavf.nut -319680 ./tests/data/lavf/lavf.nut +d685d5af89cfddb2660f03b1dee3f9a2 *./tests/data/lavf/lavf.nut +319711 ./tests/data/lavf/lavf.nut ./tests/data/lavf/lavf.nut CRC=0x4c963cda diff --git a/tests/ref/lavf/sgi b/tests/ref/lavf/sgi index b0cd303..703b83c 100644 --- a/tests/ref/lavf/sgi +++ b/tests/ref/lavf/sgi @@ -1,3 +1,3 @@ -7054acafd275e51cec28d4518e213081 *./tests/data/images/sgi/02.sgi +d446e540a7c18da5fd3cc0e9942cd46f *./tests/data/images/sgi/02.sgi ./tests/data/images/sgi/%02d.sgi CRC=0x28c7369b -308151 ./tests/data/images/sgi/02.sgi +307287 ./tests/data/images/sgi/02.sgi diff --git a/tests/ref/lavf/ts b/tests/ref/lavf/ts index 8512d26..caf08a8 100644 --- a/tests/ref/lavf/ts +++ b/tests/ref/lavf/ts @@ -1,3 +1,3 @@ -3713c852d6ee217ae6a901619df71111 *./tests/data/lavf/lavf.ts +f74d6f4d4073f4242cec3d5fee099779 *./tests/data/lavf/lavf.ts 406456 ./tests/data/lavf/lavf.ts ./tests/data/lavf/lavf.ts CRC=0xb4ca6cdc diff --git a/tests/ref/seek/lavf-asf b/tests/ref/seek/lavf-asf index 2eade27..3da2c73 100644 --- a/tests/ref/seek/lavf-asf +++ b/tests/ref/seek/lavf-asf @@ -1,53 +1,53 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147779 size: 209 +ret: 0 st: 1 flags:1 dts: 0.261000 pts: 0.261000 pos: -1 size: 209 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.732000 pts: 0.732000 pos: -1 size: 209 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st: 1 flags:0 ts: 2.577000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147779 size: 209 +ret: 0 st: 1 flags:1 dts: 0.261000 pts: 0.261000 pos: -1 size: 209 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st: 0 flags:0 ts: 2.153000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.261000 pts: 0.261000 pos: -1 size: 209 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147779 size: 209 +ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: -1 size: 209 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.732000 pts: 0.732000 pos: -1 size: 209 ret: 0 st: 1 flags:0 ts: 1.307000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.183000 pts: 0.183000 pos: 70979 size: 209 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: 301379 size: 209 +ret: 0 st: 1 flags:1 dts: 0.732000 pts: 0.732000 pos: -1 size: 209 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 ret: 0 st: 1 flags:0 ts: 2.672000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 330179 size: 209 +ret: 0 st: 1 flags:1 dts: 0.941000 pts: 0.941000 pos: -1 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 1 flags:1 dts: 0.470000 pts: 0.470000 pos: 147779 size: 209 +ret: 0 st: 1 flags:1 dts: 0.261000 pts: 0.261000 pos: -1 size: 209 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 579 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size: 208 diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index fd4fcf1..530c8df 100644 --- a/tests/ref/seek/lavf-mkv +++ b/tests/ref/seek/lavf-mkv @@ -1,53 +1,53 @@ -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st: 1 flags:0 ts: 2.577000 ret:-EOF ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320109 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320112 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146821 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146824 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st: 0 flags:0 ts: 2.153000 ret:-EOF ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320109 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320112 size: 209 ret: 0 st:-1 flags:0 ts: 1.730004 ret:-EOF ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146821 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146824 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 1 flags:0 ts: 1.307000 ret:-EOF ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292268 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292271 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 ret: 0 st: 1 flags:0 ts: 2.672000 ret:-EOF ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320109 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320112 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146821 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146824 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 630 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 633 size: 208 diff --git a/tests/ref/seek/lavf-nut b/tests/ref/seek/lavf-nut index fc3ef63..46f1ea2 100644 --- a/tests/ref/seek/lavf-nut +++ b/tests/ref/seek/lavf-nut @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:0 ts: 0.800000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:1 ts:-0.320000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st: 1 flags:0 ts: 2.586122 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 1 flags:1 ts: 1.462857 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st: 0 flags:0 ts: 2.160000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:1 ts: 1.040000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 1 flags:0 ts:-0.052245 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st: 1 flags:1 ts: 2.847347 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:0 ts:-0.480000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st: 0 flags:1 ts: 2.400000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 1 flags:0 ts: 1.306122 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 1 flags:1 ts: 0.208980 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:0 ts: 0.880000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 0 flags:1 ts:-0.240000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 ret: 0 st: 1 flags:0 ts: 2.664490 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st: 1 flags:1 ts: 1.567347 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146329 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146353 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 279 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 295 size: 27837 diff --git a/tests/ref/seek/lavf-sgi b/tests/ref/seek/lavf-sgi index b2f605a..04c7b2b 100644 --- a/tests/ref/seek/lavf-sgi +++ b/tests/ref/seek/lavf-sgi @@ -1,4 +1,4 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size:308336 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: -1 size:307472 ret:-EINVAL st:-1 flags:0 ts:-1.000000 ret:-EINVAL st:-1 flags:1 ts: 1.894167 ret:-EINVAL st: 0 flags:0 ts: 0.800000 diff --git a/tests/ref/seek/vsynth2-ffv1 b/tests/ref/seek/vsynth2-ffv1 index 153becb..c0a8950 100644 --- a/tests/ref/seek/vsynth2-ffv1 +++ b/tests/ref/seek/vsynth2-ffv1 @@ -1,46 +1,46 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2589296 size: 81788 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2590398 size: 81816 ret: 0 st: 0 flags:0 ts: 0.800000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666112 size: 77204 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666848 size: 77232 ret:-1 st: 0 flags:1 ts:-0.320000 ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2589296 size: 81788 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2590398 size: 81816 ret: 0 st: 0 flags:0 ts: 0.360000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808352 size: 70696 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808720 size: 70724 ret:-1 st: 0 flags:1 ts:-0.760000 ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666112 size: 77204 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666848 size: 77232 ret: 0 st: 0 flags:0 ts:-0.040000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st: 0 flags:1 ts: 2.840000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3550788 size: 83738 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3552258 size: 83766 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3550788 size: 83738 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3552258 size: 83766 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808352 size: 70696 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808720 size: 70724 ret: 0 st: 0 flags:0 ts:-0.480000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st: 0 flags:1 ts: 2.400000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3550788 size: 83738 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3552258 size: 83766 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2589296 size: 81788 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2590398 size: 81816 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st: 0 flags:0 ts:-0.920000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5688 size: 71768 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5690 size: 71796 ret: 0 st: 0 flags:1 ts: 2.000000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3550788 size: 83738 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos:3552258 size: 83766 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666112 size: 77204 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:1666848 size: 77232 ret:-1 st:-1 flags:1 ts:-0.222493 ret:-1 st: 0 flags:0 ts: 2.680000 ret: 0 st: 0 flags:1 ts: 1.560000 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2589296 size: 81788 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos:2590398 size: 81816 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808352 size: 70696 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 808720 size: 70724 ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/vsynth/vsynth1-dnxhd-720p-10bit b/tests/ref/vsynth/vsynth1-dnxhd-720p-10bit index a667b9d..59423e7 100644 --- a/tests/ref/vsynth/vsynth1-dnxhd-720p-10bit +++ b/tests/ref/vsynth/vsynth1-dnxhd-720p-10bit @@ -1,4 +1,4 @@ -b5e24a055af02edec8674333260214fd *tests/data/fate/vsynth1-dnxhd-720p-10bit.dnxhd +f8c4b7aa165a80df2485d526161290a3 *tests/data/fate/vsynth1-dnxhd-720p-10bit.dnxhd 2293760 tests/data/fate/vsynth1-dnxhd-720p-10bit.dnxhd -4466ff3d73d01bbe75ea25001d379b63 *tests/data/fate/vsynth1-dnxhd-720p-10bit.out.rawvideo +790777baa4bb70c4e32cb13649cc26bf *tests/data/fate/vsynth1-dnxhd-720p-10bit.out.rawvideo stddev: 6.27 PSNR: 32.18 MAXDIFF: 64 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth1-ffv1 b/tests/ref/vsynth/vsynth1-ffv1 index a162a77..c9c4cf9 100644 --- a/tests/ref/vsynth/vsynth1-ffv1 +++ b/tests/ref/vsynth/vsynth1-ffv1 @@ -1,4 +1,4 @@ -d236e8441d7e04e24d882bb97faccd36 *tests/data/fate/vsynth1-ffv1.avi -2689718 tests/data/fate/vsynth1-ffv1.avi +a6703280a623fe42de7f7a53c2383073 *tests/data/fate/vsynth1-ffv1.avi +2691264 tests/data/fate/vsynth1-ffv1.avi c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffv1.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-flashsv b/tests/ref/vsynth/vsynth1-flashsv index a4f22ce..d9bad3e 100644 --- a/tests/ref/vsynth/vsynth1-flashsv +++ b/tests/ref/vsynth/vsynth1-flashsv @@ -1,4 +1,4 @@ -6675942f5cd6978f16eff5305578de27 *tests/data/fate/vsynth1-flashsv.flv +d0ac97a2bbf78fc02718934b70d12e70 *tests/data/fate/vsynth1-flashsv.flv 14681905 tests/data/fate/vsynth1-flashsv.flv 947cb24ec45a453348ae6fe3fa278071 *tests/data/fate/vsynth1-flashsv.out.rawvideo stddev: 2.85 PSNR: 39.03 MAXDIFF: 49 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-flv b/tests/ref/vsynth/vsynth1-flv index a92658b..2aaa32c 100644 --- a/tests/ref/vsynth/vsynth1-flv +++ b/tests/ref/vsynth/vsynth1-flv @@ -1,4 +1,4 @@ -202e8b9715f278497eb13476fc9abdac *tests/data/fate/vsynth1-flv.flv +87b9e73ada2a512ffd5abec51695e44d *tests/data/fate/vsynth1-flv.flv 636249 tests/data/fate/vsynth1-flv.flv 5ab46d8dd01dbb1d63df2a84858a4b05 *tests/data/fate/vsynth1-flv.out.rawvideo stddev: 8.02 PSNR: 30.04 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-h261 b/tests/ref/vsynth/vsynth1-h261 index b350e6f..5d667fc 100644 --- a/tests/ref/vsynth/vsynth1-h261 +++ b/tests/ref/vsynth/vsynth1-h261 @@ -1,4 +1,4 @@ -d3397557ad8a02d28cb5feeb0b51e5c8 *tests/data/fate/vsynth1-h261.avi +e7adc829541417888df4ac031768679f *tests/data/fate/vsynth1-h261.avi 707576 tests/data/fate/vsynth1-h261.avi 716e83cb51afb1246bfaa80967df48ea *tests/data/fate/vsynth1-h261.out.rawvideo stddev: 9.11 PSNR: 28.93 MAXDIFF: 113 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4 b/tests/ref/vsynth/vsynth1-mpeg4 index 38a7294..ac1ebc7 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4 +++ b/tests/ref/vsynth/vsynth1-mpeg4 @@ -1,4 +1,4 @@ -dc927acd770e19a97456ecbd4d786938 *tests/data/fate/vsynth1-mpeg4.mp4 -540180 tests/data/fate/vsynth1-mpeg4.mp4 +173f524d5cd2591709bf1d5d2818b420 *tests/data/fate/vsynth1-mpeg4.mp4 +540241 tests/data/fate/vsynth1-mpeg4.mp4 8828a375448dc5c2215163ba70656f89 *tests/data/fate/vsynth1-mpeg4.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-v210 b/tests/ref/vsynth/vsynth1-v210 index defd2f6..e2f4588 100644 --- a/tests/ref/vsynth/vsynth1-v210 +++ b/tests/ref/vsynth/vsynth1-v210 @@ -1,4 +1,4 @@ -054d7e903fb4d9e68700c56b93d45916 *tests/data/fate/vsynth1-v210.avi +a38de84bfef53ed69204480c979dd6c4 *tests/data/fate/vsynth1-v210.avi 14752448 tests/data/fate/vsynth1-v210.avi -50973792d3f1abe04a51ee0121f077f2 *tests/data/fate/vsynth1-v210.out.rawvideo -stddev: 1.85 PSNR: 42.78 MAXDIFF: 29 bytes: 7603200/ 7603200 +2ba7f4ca302f3c4147860b9dfb12b6e4 *tests/data/fate/vsynth1-v210.out.rawvideo +stddev: 1.84 PSNR: 42.81 MAXDIFF: 29 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-v210-10 b/tests/ref/vsynth/vsynth1-v210-10 new file mode 100644 index 0000000..bf6afdf --- /dev/null +++ b/tests/ref/vsynth/vsynth1-v210-10 @@ -0,0 +1,4 @@ +054d7e903fb4d9e68700c56b93d45916 *tests/data/fate/vsynth1-v210-10.avi +14752448 tests/data/fate/vsynth1-v210-10.avi +50973792d3f1abe04a51ee0121f077f2 *tests/data/fate/vsynth1-v210-10.out.rawvideo +stddev: 1.85 PSNR: 42.78 MAXDIFF: 29 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-dnxhd-720p-10bit b/tests/ref/vsynth/vsynth2-dnxhd-720p-10bit index 749d5f0..30f546a 100644 --- a/tests/ref/vsynth/vsynth2-dnxhd-720p-10bit +++ b/tests/ref/vsynth/vsynth2-dnxhd-720p-10bit @@ -1,4 +1,4 @@ -4798978f178cdb91203cda27e76ce75e *tests/data/fate/vsynth2-dnxhd-720p-10bit.dnxhd +e49cb87f69acc809aee55d64990c84a9 *tests/data/fate/vsynth2-dnxhd-720p-10bit.dnxhd 2293760 tests/data/fate/vsynth2-dnxhd-720p-10bit.dnxhd -7ce1b7e73432498b530c6aa970566757 *tests/data/fate/vsynth2-dnxhd-720p-10bit.out.rawvideo -stddev: 1.56 PSNR: 44.24 MAXDIFF: 31 bytes: 7603200/ 760320 +6354193e59c7b39a2781c41a2500c793 *tests/data/fate/vsynth2-dnxhd-720p-10bit.out.rawvideo +stddev: 1.56 PSNR: 44.25 MAXDIFF: 31 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth2-ffv1 b/tests/ref/vsynth/vsynth2-ffv1 index 4dc2169..024fafd 100644 --- a/tests/ref/vsynth/vsynth2-ffv1 +++ b/tests/ref/vsynth/vsynth2-ffv1 @@ -1,4 +1,4 @@ -4af788aeb692573717fe205f3ba20a33 *tests/data/fate/vsynth2-ffv1.avi -3716494 tests/data/fate/vsynth2-ffv1.avi +2acd1edd97eb98895bae47770b700f89 *tests/data/fate/vsynth2-ffv1.avi +3718022 tests/data/fate/vsynth2-ffv1.avi 36d7ca943916e1743cefa609eba0205c *tests/data/fate/vsynth2-ffv1.out.rawvideo stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-flashsv b/tests/ref/vsynth/vsynth2-flashsv index de7446b..75e5d8f 100644 --- a/tests/ref/vsynth/vsynth2-flashsv +++ b/tests/ref/vsynth/vsynth2-flashsv @@ -1,4 +1,4 @@ -52701f9112732b42aa425129265ef499 *tests/data/fate/vsynth2-flashsv.flv +9980ac31d9312c38e23883063c2cc269 *tests/data/fate/vsynth2-flashsv.flv 11636526 tests/data/fate/vsynth2-flashsv.flv eed2322f11b95fc7abe5356306f00d97 *tests/data/fate/vsynth2-flashsv.out.rawvideo stddev: 1.21 PSNR: 46.42 MAXDIFF: 20 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-flv b/tests/ref/vsynth/vsynth2-flv index 818b111..343ce42 100644 --- a/tests/ref/vsynth/vsynth2-flv +++ b/tests/ref/vsynth/vsynth2-flv @@ -1,4 +1,4 @@ -1be21ea941eb8b5ef5ecde9cac40ada0 *tests/data/fate/vsynth2-flv.flv +6336a28db20719d12dfd3a8a6950d0fc *tests/data/fate/vsynth2-flv.flv 174657 tests/data/fate/vsynth2-flv.flv c6e9b6c165558d052541309e48b5f551 *tests/data/fate/vsynth2-flv.out.rawvideo stddev: 6.02 PSNR: 32.53 MAXDIFF: 83 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-h261 b/tests/ref/vsynth/vsynth2-h261 index 2c3d99b..465e2f9 100644 --- a/tests/ref/vsynth/vsynth2-h261 +++ b/tests/ref/vsynth/vsynth2-h261 @@ -1,4 +1,4 @@ -b5187bd5be8b422ff220f297de90fbcb *tests/data/fate/vsynth2-h261.avi +0292ca022247f978f6e894831310682b *tests/data/fate/vsynth2-h261.avi 257928 tests/data/fate/vsynth2-h261.avi 1a9bb0d52bd24cb62162c5e3c2aed317 *tests/data/fate/vsynth2-h261.out.rawvideo stddev: 7.21 PSNR: 30.97 MAXDIFF: 96 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4 b/tests/ref/vsynth/vsynth2-mpeg4 index 1aa75a8..bd47f14 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4 +++ b/tests/ref/vsynth/vsynth2-mpeg4 @@ -1,4 +1,4 @@ -f60260ca447624a19ad8307abad7a431 *tests/data/fate/vsynth2-mpeg4.mp4 -159432 tests/data/fate/vsynth2-mpeg4.mp4 +5476cf4dc144eac67b12737fd8966641 *tests/data/fate/vsynth2-mpeg4.mp4 +159493 tests/data/fate/vsynth2-mpeg4.mp4 871fda3853f4766669ad875923920bd5 *tests/data/fate/vsynth2-mpeg4.out.rawvideo stddev: 6.02 PSNR: 32.53 MAXDIFF: 89 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-v210 b/tests/ref/vsynth/vsynth2-v210 index 5e934de..245e282 100644 --- a/tests/ref/vsynth/vsynth2-v210 +++ b/tests/ref/vsynth/vsynth2-v210 @@ -1,4 +1,4 @@ -87bb634932b3f5cacd4d08142798db17 *tests/data/fate/vsynth2-v210.avi +3aae4d5b25a4d91e4812a297c6a9ef8a *tests/data/fate/vsynth2-v210.avi 14752448 tests/data/fate/vsynth2-v210.avi -8bb1c449e1a2a94fd0d98841c04246bb *tests/data/fate/vsynth2-v210.out.rawvideo -stddev: 0.39 PSNR: 56.17 MAXDIFF: 9 bytes: 7603200/ 7603200 +99e367a50da75c2c187230889bee8e2e *tests/data/fate/vsynth2-v210.out.rawvideo +stddev: 0.40 PSNR: 56.06 MAXDIFF: 9 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-v210-10 b/tests/ref/vsynth/vsynth2-v210-10 new file mode 100644 index 0000000..b36aea6 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-v210-10 @@ -0,0 +1,4 @@ +87bb634932b3f5cacd4d08142798db17 *tests/data/fate/vsynth2-v210-10.avi +14752448 tests/data/fate/vsynth2-v210-10.avi +8bb1c449e1a2a94fd0d98841c04246bb *tests/data/fate/vsynth2-v210-10.out.rawvideo +stddev: 0.39 PSNR: 56.17 MAXDIFF: 9 bytes: 7603200/ 7603200 diff --git a/tests/tiny_psnr.c b/tests/tiny_psnr.c index 66eaf82..1afdd4d 100644 --- a/tests/tiny_psnr.c +++ b/tests/tiny_psnr.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -117,7 +116,7 @@ static double get_f64l(uint8_t *p) int main(int argc, char *argv[]) { - int i, j; + uint64_t i, j; uint64_t sse = 0; double sse_d = 0.0; FILE *f[2]; @@ -126,8 +125,8 @@ int main(int argc, char *argv[]) int64_t max; int shift = argc < 5 ? 0 : atoi(argv[4]); int skip_bytes = argc < 6 ? 0 : atoi(argv[5]); - int size0 = 0; - int size1 = 0; + uint64_t size0 = 0; + uint64_t size1 = 0; uint64_t maxdist = 0; double maxdist_d = 0.0; @@ -208,7 +207,7 @@ int main(int argc, char *argv[]) b = buf[1][j]; } sse += (a - b) * (a - b); - dist = abs(a - b); + dist = llabs(a - b); if (dist > maxdist) maxdist = dist; break; @@ -251,7 +250,7 @@ int main(int argc, char *argv[]) else psnr = 1000 * F - 1; // floating point free infinity :) - printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5"PRIu64" bytes:%9d/%9d\n", + printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5"PRIu64" bytes:%9"PRIu64"/%9"PRIu64"\n", (int)(dev / F), (int)(dev % F), (int)(psnr / F), (int)(psnr % F), maxdist, size0, size1); @@ -271,7 +270,7 @@ int main(int argc, char *argv[]) maxdist = maxdist_d * scale; - printf("stddev:%10.2f PSNR:%s MAXDIFF:%10"PRIu64" bytes:%9d/%9d\n", + printf("stddev:%10.2f PSNR:%s MAXDIFF:%10"PRIu64" bytes:%9"PRIu64"/%9"PRIu64"\n", dev * scale, psnr_str, maxdist, size0, size1); break; } diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..21202fa --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,9 @@ +/aviocat +/cws2fws +/graph2dot +/ismindex +/pktdumper +/probetest +/qt-faststart +/sidxindex +/trasher diff --git a/tools/aviocat.c b/tools/aviocat.c index 6a33a7c..59244a8 100644 --- a/tools/aviocat.c +++ b/tools/aviocat.c @@ -82,7 +82,7 @@ int main(int argc, char **argv) goto fail; } - start_time = av_gettime(); + start_time = av_gettime_relative(); while (1) { uint8_t buf[1024]; int n; @@ -93,7 +93,7 @@ int main(int argc, char **argv) stream_pos += n; if (bps) { avio_flush(output); - while ((av_gettime() - start_time) * bps / AV_TIME_BASE < stream_pos) + while ((av_gettime_relative() - start_time) * bps / AV_TIME_BASE < stream_pos) av_usleep(50 * 1000); } } diff --git a/tools/cws2fws.c b/tools/cws2fws.c index 74588c1..72980f4 100644 --- a/tools/cws2fws.c +++ b/tools/cws2fws.c @@ -31,6 +31,7 @@ int main(int argc, char *argv[]) char buf_in[1024], buf_out[65536]; z_stream zstream; struct stat statbuf; + int ret = 1; if (argc < 3) { printf("Usage: %s \n", argv[0]); @@ -52,14 +53,12 @@ int main(int argc, char *argv[]) if (read(fd_in, &buf_in, 8) != 8) { printf("Header error\n"); - close(fd_in); - close(fd_out); - return 1; + goto out; } if (buf_in[0] != 'C' || buf_in[1] != 'W' || buf_in[2] != 'S') { printf("Not a compressed flash file\n"); - return 1; + goto out; } fstat(fd_in, &statbuf); @@ -73,7 +72,7 @@ int main(int argc, char *argv[]) buf_in[0] = 'F'; if (write(fd_out, &buf_in, 8) < 8) { perror("Error writing output file"); - return 1; + goto out; } zstream.zalloc = NULL; @@ -97,7 +96,7 @@ int main(int argc, char *argv[]) if (ret != Z_STREAM_END && ret != Z_OK) { printf("Error while decompressing: %d\n", ret); inflateEnd(&zstream); - return 1; + goto out; } dbgprintf("a_in: %d t_in: %lu a_out: %d t_out: %lu -- %lu out\n", @@ -107,7 +106,8 @@ int main(int argc, char *argv[]) if (write(fd_out, &buf_out, zstream.total_out - last_out) < zstream.total_out - last_out) { perror("Error writing output file"); - return 1; + inflateEnd(&zstream); + goto out; } i += len; @@ -128,12 +128,15 @@ int main(int argc, char *argv[]) lseek(fd_out, 4, SEEK_SET); if (write(fd_out, &buf_in, 4) < 4) { perror("Error writing output file"); - return 1; + inflateEnd(&zstream); + goto out; } } + ret = 0; inflateEnd(&zstream); +out: close(fd_in); close(fd_out); - return 0; + return ret; } diff --git a/tools/graph2dot.c b/tools/graph2dot.c index 12f1066..fbf8902 100644 --- a/tools/graph2dot.c +++ b/tools/graph2dot.c @@ -28,7 +28,6 @@ #include "libavutil/channel_layout.h" #include "libavutil/mem.h" #include "libavutil/pixdesc.h" -#include "libavutil/audioconvert.h" #include "libavfilter/avfilter.h" #if !HAVE_GETOPT diff --git a/tools/ismindex.c b/tools/ismindex.c index a2eed87..3d7e082 100644 --- a/tools/ismindex.c +++ b/tools/ismindex.c @@ -25,6 +25,9 @@ * This step creates foo.ism and foo.ismc that is required by IIS for * serving it. * + * With -ismf, it also creates foo.ismf, which maps fragment names to + * start-end offsets in the ismv, for use in your own streaming server. + * * By adding -path-prefix path/, the produced foo.ism will refer to the * files foo.ismv as "path/foo.ismv" - the prefix for the generated ismc * file can be set with the -ismc-prefix option similarly. @@ -45,13 +48,14 @@ #include #include "libavformat/avformat.h" +#include "libavformat/isom.h" #include "libavformat/os_support.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" static int usage(const char *argv0, int ret) { - fprintf(stderr, "%s [-split] [-n basename] [-path-prefix prefix] " + fprintf(stderr, "%s [-split] [-ismf] [-n basename] [-path-prefix prefix] " "[-ismc-prefix prefix] [-output dir] file1 [file2] ...\n", argv0); return ret; } @@ -88,6 +92,18 @@ struct Tracks { int nb_video_tracks, nb_audio_tracks; }; +static int expect_tag(int32_t got_tag, int32_t expected_tag) { + if (got_tag != expected_tag) { + char got_tag_str[4], expected_tag_str[4]; + AV_WB32(got_tag_str, got_tag); + AV_WB32(expected_tag_str, expected_tag); + fprintf(stderr, "wanted tag %.4s, got %.4s\n", expected_tag_str, + got_tag_str); + return -1; + } + return 0; +} + static int copy_tag(AVIOContext *in, AVIOContext *out, int32_t tag_name) { int32_t size, tag; @@ -96,29 +112,50 @@ static int copy_tag(AVIOContext *in, AVIOContext *out, int32_t tag_name) tag = avio_rb32(in); avio_wb32(out, size); avio_wb32(out, tag); - if (tag != tag_name) + if (expect_tag(tag, tag_name) != 0) return -1; size -= 8; while (size > 0) { char buf[1024]; int len = FFMIN(sizeof(buf), size); - if (avio_read(in, buf, len) != len) + int got; + if ((got = avio_read(in, buf, len)) != len) { + fprintf(stderr, "short read, wanted %d, got %d\n", len, got); break; + } avio_write(out, buf, len); size -= len; } return 0; } +static int skip_tag(AVIOContext *in, int32_t tag_name) +{ + int64_t pos = avio_tell(in); + int32_t size, tag; + + size = avio_rb32(in); + tag = avio_rb32(in); + if (expect_tag(tag, tag_name) != 0) + return -1; + avio_seek(in, pos + size, SEEK_SET); + return 0; +} + static int write_fragment(const char *filename, AVIOContext *in) { AVIOContext *out = NULL; int ret; - if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, NULL, NULL)) < 0) + if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, NULL, NULL)) < 0) { + char errbuf[100]; + av_strerror(ret, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to open %s: %s\n", filename, errbuf); return ret; - copy_tag(in, out, MKBETAG('m', 'o', 'o', 'f')); - copy_tag(in, out, MKBETAG('m', 'd', 'a', 't')); + } + ret = copy_tag(in, out, MKBETAG('m', 'o', 'o', 'f')); + if (!ret) + ret = copy_tag(in, out, MKBETAG('m', 'd', 'a', 't')); avio_flush(out); avio_close(out); @@ -126,25 +163,160 @@ static int write_fragment(const char *filename, AVIOContext *in) return ret; } -static int write_fragments(struct Tracks *tracks, int start_index, - AVIOContext *in, const char *output_prefix) +static int skip_fragment(AVIOContext *in) { - char dirname[2048], filename[2048]; - int i, j; + int ret; + ret = skip_tag(in, MKBETAG('m', 'o', 'o', 'f')); + if (!ret) + ret = skip_tag(in, MKBETAG('m', 'd', 'a', 't')); + return ret; +} +static int write_fragments(struct Tracks *tracks, int start_index, + AVIOContext *in, const char *basename, + int split, int ismf, const char* output_prefix) +{ + char dirname[2048], filename[2048], idxname[2048]; + int i, j, ret = 0, fragment_ret; + FILE* out = NULL; + + if (ismf) { + snprintf(idxname, sizeof(idxname), "%s%s.ismf", output_prefix, basename); + out = fopen(idxname, "w"); + if (!out) { + ret = AVERROR(errno); + perror(idxname); + goto fail; + } + } for (i = start_index; i < tracks->nb_tracks; i++) { struct Track *track = tracks->tracks[i]; const char *type = track->is_video ? "video" : "audio"; snprintf(dirname, sizeof(dirname), "%sQualityLevels(%d)", output_prefix, track->bitrate); - mkdir(dirname, 0777); + if (split) { + if (mkdir(dirname, 0777) == -1 && errno != EEXIST) { + ret = AVERROR(errno); + perror(dirname); + goto fail; + } + } for (j = 0; j < track->chunks; j++) { snprintf(filename, sizeof(filename), "%s/Fragments(%s=%"PRId64")", dirname, type, track->offsets[j].time); avio_seek(in, track->offsets[j].offset, SEEK_SET); - write_fragment(filename, in); + if (ismf) + fprintf(out, "%s %"PRId64, filename, avio_tell(in)); + if (split) + fragment_ret = write_fragment(filename, in); + else + fragment_ret = skip_fragment(in); + if (ismf) + fprintf(out, " %"PRId64"\n", avio_tell(in)); + if (fragment_ret != 0) { + fprintf(stderr, "failed fragment %d in track %d (%s)\n", j, + track->track_id, track->name); + ret = fragment_ret; + } } } - return 0; +fail: + if (out) + fclose(out); + return ret; +} + +static int64_t read_trun_duration(AVIOContext *in, int default_duration, + int64_t end) +{ + int64_t dts = 0; + int64_t pos; + int flags, i; + int entries; + int64_t first_pts = 0; + int64_t max_pts = 0; + avio_r8(in); /* version */ + flags = avio_rb24(in); + if (default_duration <= 0 && !(flags & MOV_TRUN_SAMPLE_DURATION)) { + fprintf(stderr, "No sample duration in trun flags\n"); + return -1; + } + entries = avio_rb32(in); + + if (flags & MOV_TRUN_DATA_OFFSET) avio_rb32(in); + if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) avio_rb32(in); + + pos = avio_tell(in); + for (i = 0; i < entries && pos < end; i++) { + int sample_duration = default_duration; + int64_t pts = dts; + if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(in); + if (flags & MOV_TRUN_SAMPLE_SIZE) avio_rb32(in); + if (flags & MOV_TRUN_SAMPLE_FLAGS) avio_rb32(in); + if (flags & MOV_TRUN_SAMPLE_CTS) pts += avio_rb32(in); + if (sample_duration < 0) { + fprintf(stderr, "Negative sample duration %d\n", sample_duration); + return -1; + } + if (i == 0) + first_pts = pts; + max_pts = FFMAX(max_pts, pts + sample_duration); + dts += sample_duration; + pos = avio_tell(in); + } + + return max_pts - first_pts; +} + +static int64_t read_moof_duration(AVIOContext *in, int64_t offset) +{ + int64_t ret = -1; + int32_t moof_size, size, tag; + int64_t pos = 0; + int default_duration = 0; + + avio_seek(in, offset, SEEK_SET); + moof_size = avio_rb32(in); + tag = avio_rb32(in); + if (expect_tag(tag, MKBETAG('m', 'o', 'o', 'f')) != 0) + goto fail; + while (pos < offset + moof_size) { + pos = avio_tell(in); + size = avio_rb32(in); + tag = avio_rb32(in); + if (tag == MKBETAG('t', 'r', 'a', 'f')) { + int64_t traf_pos = pos; + int64_t traf_size = size; + while (pos < traf_pos + traf_size) { + pos = avio_tell(in); + size = avio_rb32(in); + tag = avio_rb32(in); + if (tag == MKBETAG('t', 'f', 'h', 'd')) { + int flags = 0; + avio_r8(in); /* version */ + flags = avio_rb24(in); + avio_rb32(in); /* track_id */ + if (flags & MOV_TFHD_BASE_DATA_OFFSET) + avio_rb64(in); + if (flags & MOV_TFHD_STSD_ID) + avio_rb32(in); + if (flags & MOV_TFHD_DEFAULT_DURATION) + default_duration = avio_rb32(in); + } + if (tag == MKBETAG('t', 'r', 'u', 'n')) { + return read_trun_duration(in, default_duration, + pos + size); + } + avio_seek(in, pos + size, SEEK_SET); + } + fprintf(stderr, "Couldn't find trun\n"); + goto fail; + } + avio_seek(in, pos + size, SEEK_SET); + } + fprintf(stderr, "Couldn't find traf\n"); + +fail: + return ret; } static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f) @@ -175,6 +347,8 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f) ret = AVERROR(ENOMEM); goto fail; } + // The duration here is always the difference between consecutive + // start times. for (i = 0; i < track->chunks; i++) { if (version == 1) { track->offsets[i].time = avio_rb64(f); @@ -193,9 +367,41 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f) track->offsets[i - 1].duration = track->offsets[i].time - track->offsets[i - 1].time; } - if (track->chunks > 0) - track->offsets[track->chunks - 1].duration = track->duration - + if (track->chunks > 0) { + track->offsets[track->chunks - 1].duration = track->offsets[0].time + + track->duration - track->offsets[track->chunks - 1].time; + } + // Now try and read the actual durations from the trun sample data. + for (i = 0; i < track->chunks; i++) { + int64_t duration = read_moof_duration(f, track->offsets[i].offset); + if (duration > 0 && llabs(duration - track->offsets[i].duration) > 3) { + // 3 allows for integer duration to drift a few units, + // e.g., for 1/3 durations + track->offsets[i].duration = duration; + } + } + if (track->chunks > 0) { + if (track->offsets[track->chunks - 1].duration <= 0) { + fprintf(stderr, "Calculated last chunk duration for track %d " + "was non-positive (%"PRId64"), probably due to missing " + "fragments ", track->track_id, + track->offsets[track->chunks - 1].duration); + if (track->chunks > 1) { + track->offsets[track->chunks - 1].duration = + track->offsets[track->chunks - 2].duration; + } else { + track->offsets[track->chunks - 1].duration = 1; + } + fprintf(stderr, "corrected to %"PRId64"\n", + track->offsets[track->chunks - 1].duration); + track->duration = track->offsets[track->chunks - 1].time + + track->offsets[track->chunks - 1].duration - + track->offsets[0].time; + fprintf(stderr, "Track duration corrected to %"PRId64"\n", + track->duration); + } + } ret = 0; fail: @@ -204,9 +410,11 @@ fail: } static int read_mfra(struct Tracks *tracks, int start_index, - const char *file, int split, const char *output_prefix) + const char *file, int split, int ismf, + const char *basename, const char* output_prefix) { int err = 0; + const char* err_str = ""; AVIOContext *f = NULL; int32_t mfra_size; @@ -217,59 +425,65 @@ static int read_mfra(struct Tracks *tracks, int start_index, avio_seek(f, -mfra_size, SEEK_CUR); if (avio_rb32(f) != mfra_size) { err = AVERROR_INVALIDDATA; + err_str = "mfra size mismatch"; goto fail; } if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) { err = AVERROR_INVALIDDATA; + err_str = "mfra tag mismatch"; goto fail; } while (!read_tfra(tracks, start_index, f)) { /* Empty */ } - if (split) - write_fragments(tracks, start_index, f, output_prefix); + if (split || ismf) + err = write_fragments(tracks, start_index, f, basename, split, ismf, + output_prefix); + err_str = "error in write_fragments"; fail: if (f) avio_close(f); if (err) - fprintf(stderr, "Unable to read the MFRA atom in %s\n", file); + fprintf(stderr, "Unable to read the MFRA atom in %s (%s)\n", file, err_str); return err; } -static int get_private_data(struct Track *track, AVCodecContext *codec) +static int get_private_data(struct Track *track, AVCodecParameters *codecpar) { - track->codec_private_size = codec->extradata_size; - track->codec_private = av_mallocz(codec->extradata_size); + track->codec_private_size = codecpar->extradata_size; + track->codec_private = av_mallocz(codecpar->extradata_size); if (!track->codec_private) return AVERROR(ENOMEM); - memcpy(track->codec_private, codec->extradata, codec->extradata_size); + memcpy(track->codec_private, codecpar->extradata, codecpar->extradata_size); return 0; } -static int get_video_private_data(struct Track *track, AVCodecContext *codec) +static int get_video_private_data(struct Track *track, AVCodecParameters *codecpar) { AVIOContext *io = NULL; uint16_t sps_size, pps_size; - int err = AVERROR(EINVAL); + int err; - if (codec->codec_id == AV_CODEC_ID_VC1) - return get_private_data(track, codec); + if (codecpar->codec_id == AV_CODEC_ID_VC1) + return get_private_data(track, codecpar); - avio_open_dyn_buf(&io); - if (codec->extradata_size < 11 || codec->extradata[0] != 1) + if ((err = avio_open_dyn_buf(&io)) < 0) + goto fail; + err = AVERROR(EINVAL); + if (codecpar->extradata_size < 11 || codecpar->extradata[0] != 1) goto fail; - sps_size = AV_RB16(&codec->extradata[6]); - if (11 + sps_size > codec->extradata_size) + sps_size = AV_RB16(&codecpar->extradata[6]); + if (11 + sps_size > codecpar->extradata_size) goto fail; avio_wb32(io, 0x00000001); - avio_write(io, &codec->extradata[8], sps_size); - pps_size = AV_RB16(&codec->extradata[9 + sps_size]); - if (11 + sps_size + pps_size > codec->extradata_size) + avio_write(io, &codecpar->extradata[8], sps_size); + pps_size = AV_RB16(&codecpar->extradata[9 + sps_size]); + if (11 + sps_size + pps_size > codecpar->extradata_size) goto fail; avio_wb32(io, 0x00000001); - avio_write(io, &codec->extradata[11 + sps_size], pps_size); + avio_write(io, &codecpar->extradata[11 + sps_size], pps_size); err = 0; fail: @@ -278,7 +492,8 @@ fail: } static int handle_file(struct Tracks *tracks, const char *file, int split, - const char *output_prefix) + int ismf, const char *basename, + const char* output_prefix) { AVFormatContext *ctx = NULL; int err = 0, i, orig_tracks = tracks->nb_tracks; @@ -307,6 +522,13 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, for (i = 0; i < ctx->nb_streams; i++) { struct Track **temp; AVStream *st = ctx->streams[i]; + + if (st->codecpar->bit_rate == 0) { + fprintf(stderr, "Skipping track %d in %s as it has zero bitrate\n", + st->id, file); + continue; + } + track = av_mallocz(sizeof(*track)); if (!track) { err = AVERROR(ENOMEM); @@ -326,12 +548,12 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, if ((ptr = strrchr(file, '/'))) track->name = ptr + 1; - track->bitrate = st->codec->bit_rate; + track->bitrate = st->codecpar->bit_rate; track->track_id = st->id; track->timescale = st->time_base.den; track->duration = st->duration; - track->is_audio = st->codec->codec_type == AVMEDIA_TYPE_AUDIO; - track->is_video = st->codec->codec_type == AVMEDIA_TYPE_VIDEO; + track->is_audio = st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO; + track->is_video = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; if (!track->is_audio && !track->is_video) { fprintf(stderr, @@ -349,30 +571,30 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, if (tracks->audio_track < 0) tracks->audio_track = tracks->nb_tracks; tracks->nb_audio_tracks++; - track->channels = st->codec->channels; - track->sample_rate = st->codec->sample_rate; - if (st->codec->codec_id == AV_CODEC_ID_AAC) { + track->channels = st->codecpar->channels; + track->sample_rate = st->codecpar->sample_rate; + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { track->fourcc = "AACL"; track->tag = 255; track->blocksize = 4; - } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) { track->fourcc = "WMAP"; - track->tag = st->codec->codec_tag; - track->blocksize = st->codec->block_align; + track->tag = st->codecpar->codec_tag; + track->blocksize = st->codecpar->block_align; } - get_private_data(track, st->codec); + get_private_data(track, st->codecpar); } if (track->is_video) { if (tracks->video_track < 0) tracks->video_track = tracks->nb_tracks; tracks->nb_video_tracks++; - track->width = st->codec->width; - track->height = st->codec->height; - if (st->codec->codec_id == AV_CODEC_ID_H264) + track->width = st->codecpar->width; + track->height = st->codecpar->height; + if (st->codecpar->codec_id == AV_CODEC_ID_H264) track->fourcc = "H264"; - else if (st->codec->codec_id == AV_CODEC_ID_VC1) + else if (st->codecpar->codec_id == AV_CODEC_ID_VC1) track->fourcc = "WVC1"; - get_video_private_data(track, st->codec); + get_video_private_data(track, st->codecpar); } tracks->nb_tracks++; @@ -380,7 +602,8 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, avformat_close_input(&ctx); - err = read_mfra(tracks, orig_tracks, file, split, output_prefix); + err = read_mfra(tracks, orig_tracks, file, split, ismf, basename, + output_prefix); fail: if (ctx) @@ -430,16 +653,34 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main, const char *type) { int i, j; + int64_t pos = 0; struct Track *track = tracks->tracks[main]; + int should_print_time_mismatch = 1; + for (i = 0; i < track->chunks; i++) { for (j = main + 1; j < tracks->nb_tracks; j++) { - if (tracks->tracks[j]->is_audio == track->is_audio && - track->offsets[i].duration != tracks->tracks[j]->offsets[i].duration) - fprintf(stderr, "Mismatched duration of %s chunk %d in %s and %s\n", - type, i, track->name, tracks->tracks[j]->name); + if (tracks->tracks[j]->is_audio == track->is_audio) { + if (track->offsets[i].duration != tracks->tracks[j]->offsets[i].duration) { + fprintf(stderr, "Mismatched duration of %s chunk %d in %s (%d) and %s (%d)\n", + type, i, track->name, main, tracks->tracks[j]->name, j); + should_print_time_mismatch = 1; + } + if (track->offsets[i].time != tracks->tracks[j]->offsets[i].time) { + if (should_print_time_mismatch) + fprintf(stderr, "Mismatched (start) time of %s chunk %d in %s (%d) and %s (%d)\n", + type, i, track->name, main, tracks->tracks[j]->name, j); + should_print_time_mismatch = 0; + } + } } - fprintf(out, "\t\t\n", + fprintf(out, "\t\toffsets[i].duration); + if (pos != track->offsets[i].time) { + fprintf(out, "t=\"%"PRId64"\" ", track->offsets[i].time); + pos = track->offsets[i].time; + } + pos += track->offsets[i].duration; + fprintf(out, "/>\n"); } } @@ -485,8 +726,8 @@ static void output_client_manifest(struct Tracks *tracks, const char *basename, fprintf(out, "\" />\n"); index++; if (track->chunks != first_track->chunks) - fprintf(stderr, "Mismatched number of video chunks in %s and %s\n", - track->name, first_track->name); + fprintf(stderr, "Mismatched number of video chunks in %s (id: %d, chunks %d) and %s (id: %d, chunks %d)\n", + track->name, track->track_id, track->chunks, first_track->name, first_track->track_id, first_track->chunks); } print_track_chunks(out, tracks, tracks->video_track, "video"); fprintf(out, "\t\n"); @@ -544,7 +785,7 @@ int main(int argc, char **argv) const char *path_prefix = "", *ismc_prefix = ""; const char *output_prefix = ""; char output_prefix_buf[2048]; - int split = 0, i; + int split = 0, ismf = 0, i; struct Tracks tracks = { 0, .video_track = -1, .audio_track = -1 }; av_register_all(); @@ -569,10 +810,15 @@ int main(int argc, char **argv) } } else if (!strcmp(argv[i], "-split")) { split = 1; + } else if (!strcmp(argv[i], "-ismf")) { + ismf = 1; } else if (argv[i][0] == '-') { return usage(argv[0], 1); } else { - if (handle_file(&tracks, argv[i], split, output_prefix)) + if (!basename) + ismf = 0; + if (handle_file(&tracks, argv[i], split, ismf, + basename, output_prefix)) return 1; } } diff --git a/tools/pktdumper.c b/tools/pktdumper.c index c6398fe..d71a6b5 100644 --- a/tools/pktdumper.c +++ b/tools/pktdumper.c @@ -122,7 +122,7 @@ int main(int argc, char **argv) } close(fd); } - av_free_packet(&pkt); + av_packet_unref(&pkt); pktnum++; if (maxpkts && (pktnum >= maxpkts)) break; diff --git a/tools/qt-faststart.c b/tools/qt-faststart.c index ed6de1b..0db5ca2 100644 --- a/tools/qt-faststart.c +++ b/tools/qt-faststart.c @@ -30,10 +30,14 @@ #include #ifdef __MINGW32__ +#undef fseeko #define fseeko(x, y, z) fseeko64(x, y, z) +#undef ftello #define ftello(x) ftello64(x) #elif defined(_WIN32) +#undef fseeko #define fseeko(x, y, z) _fseeki64(x, y, z) +#undef ftello #define ftello(x) _ftelli64(x) #endif diff --git a/tools/sidxindex.c b/tools/sidxindex.c new file mode 100644 index 0000000..e740a94 --- /dev/null +++ b/tools/sidxindex.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2014 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavformat/avformat.h" +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" + +static int usage(const char *argv0, int ret) +{ + fprintf(stderr, "%s -out foo.mpd file1\n", argv0); + return ret; +} + +struct Track { + const char *name; + int64_t duration; + int bitrate; + int track_id; + int is_audio, is_video; + int width, height; + int sample_rate, channels; + int timescale; + char codec_str[30]; + int64_t sidx_start, sidx_length; +}; + +struct Tracks { + int nb_tracks; + int64_t duration; + struct Track **tracks; + int multiple_tracks_per_file; +}; + +static void set_codec_str(AVCodecParameters *codecpar, char *str, int size) +{ + switch (codecpar->codec_id) { + case AV_CODEC_ID_H264: + snprintf(str, size, "avc1"); + if (codecpar->extradata_size >= 4 && codecpar->extradata[0] == 1) { + av_strlcatf(str, size, ".%02x%02x%02x", + codecpar->extradata[1], codecpar->extradata[2], + codecpar->extradata[3]); + } + break; + case AV_CODEC_ID_AAC: + snprintf(str, size, "mp4a.40"); // 0x40 is the mp4 object type for AAC + if (codecpar->extradata_size >= 2) { + int aot = codecpar->extradata[0] >> 3; + if (aot == 31) + aot = ((AV_RB16(codecpar->extradata) >> 5) & 0x3f) + 32; + av_strlcatf(str, size, ".%d", aot); + } + break; + } +} + +static int find_sidx(struct Tracks *tracks, int start_index, + const char *file) +{ + int err = 0; + AVIOContext *f = NULL; + int i; + + if ((err = avio_open2(&f, file, AVIO_FLAG_READ, NULL, NULL)) < 0) + goto fail; + + while (!f->eof_reached) { + int64_t pos = avio_tell(f); + int32_t size, tag; + + size = avio_rb32(f); + tag = avio_rb32(f); + if (size < 8) + break; + if (tag == MKBETAG('s', 'i', 'd', 'x')) { + for (i = start_index; i < tracks->nb_tracks; i++) { + struct Track *track = tracks->tracks[i]; + if (!track->sidx_start) { + track->sidx_start = pos; + track->sidx_length = size; + } else if (pos == track->sidx_start + track->sidx_length) { + track->sidx_length = pos + size - track->sidx_start; + } + } + } + if (avio_seek(f, pos + size, SEEK_SET) != pos + size) + break; + } + +fail: + if (f) + avio_close(f); + return err; +} + +static int handle_file(struct Tracks *tracks, const char *file) +{ + AVFormatContext *ctx = NULL; + int err = 0, i, orig_tracks = tracks->nb_tracks; + char errbuf[50], *ptr; + struct Track *track; + + err = avformat_open_input(&ctx, file, NULL, NULL); + if (err < 0) { + av_strerror(err, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to open %s: %s\n", file, errbuf); + return 1; + } + + err = avformat_find_stream_info(ctx, NULL); + if (err < 0) { + av_strerror(err, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to identify %s: %s\n", file, errbuf); + goto fail; + } + + if (ctx->nb_streams < 1) { + fprintf(stderr, "No streams found in %s\n", file); + goto fail; + } + if (ctx->nb_streams > 1) + tracks->multiple_tracks_per_file = 1; + + for (i = 0; i < ctx->nb_streams; i++) { + struct Track **temp; + AVStream *st = ctx->streams[i]; + + if (st->codecpar->bit_rate == 0) { + fprintf(stderr, "Skipping track %d in %s as it has zero bitrate\n", + st->id, file); + continue; + } + + track = av_mallocz(sizeof(*track)); + if (!track) { + err = AVERROR(ENOMEM); + goto fail; + } + temp = av_realloc(tracks->tracks, + sizeof(*tracks->tracks) * (tracks->nb_tracks + 1)); + if (!temp) { + av_free(track); + err = AVERROR(ENOMEM); + goto fail; + } + tracks->tracks = temp; + tracks->tracks[tracks->nb_tracks] = track; + + track->name = file; + if ((ptr = strrchr(file, '/'))) + track->name = ptr + 1; + + track->bitrate = st->codecpar->bit_rate; + track->track_id = st->id; + track->timescale = st->time_base.den; + track->duration = st->duration; + track->is_audio = st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO; + track->is_video = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; + + if (!track->is_audio && !track->is_video) { + fprintf(stderr, + "Track %d in %s is neither video nor audio, skipping\n", + track->track_id, file); + av_freep(&tracks->tracks[tracks->nb_tracks]); + continue; + } + + tracks->duration = FFMAX(tracks->duration, + av_rescale_rnd(track->duration, AV_TIME_BASE, + track->timescale, AV_ROUND_UP)); + + if (track->is_audio) { + track->channels = st->codecpar->channels; + track->sample_rate = st->codecpar->sample_rate; + } + if (track->is_video) { + track->width = st->codecpar->width; + track->height = st->codecpar->height; + } + set_codec_str(st->codecpar, track->codec_str, sizeof(track->codec_str)); + + tracks->nb_tracks++; + } + + avformat_close_input(&ctx); + + err = find_sidx(tracks, orig_tracks, file); + +fail: + if (ctx) + avformat_close_input(&ctx); + return err; +} + +static void write_time(FILE *out, int64_t time, int decimals, enum AVRounding round) +{ + int seconds = time / AV_TIME_BASE; + int fractions = time % AV_TIME_BASE; + int minutes = seconds / 60; + int hours = minutes / 60; + fractions = av_rescale_rnd(fractions, pow(10, decimals), AV_TIME_BASE, round); + seconds %= 60; + minutes %= 60; + fprintf(out, "PT"); + if (hours) + fprintf(out, "%dH", hours); + if (hours || minutes) + fprintf(out, "%dM", minutes); + fprintf(out, "%d.%0*dS", seconds, decimals, fractions); +} + +static int output_mpd(struct Tracks *tracks, const char *filename) +{ + FILE *out; + int i, j, ret = 0; + struct Track **adaptation_sets_buf[2] = { NULL }; + struct Track ***adaptation_sets; + int nb_tracks_buf[2] = { 0 }; + int *nb_tracks; + int set, nb_sets; + + if (!tracks->multiple_tracks_per_file) { + adaptation_sets = adaptation_sets_buf; + nb_tracks = nb_tracks_buf; + nb_sets = 2; + for (i = 0; i < 2; i++) { + adaptation_sets[i] = av_malloc(sizeof(*adaptation_sets[i]) * tracks->nb_tracks); + if (!adaptation_sets[i]) { + ret = AVERROR(ENOMEM); + goto err; + } + } + for (i = 0; i < tracks->nb_tracks; i++) { + int set_index = -1; + if (tracks->tracks[i]->is_video) + set_index = 0; + else if (tracks->tracks[i]->is_audio) + set_index = 1; + else + continue; + adaptation_sets[set_index][nb_tracks[set_index]++] = tracks->tracks[i]; + } + } else { + adaptation_sets = &tracks->tracks; + nb_tracks = &tracks->nb_tracks; + nb_sets = 1; + } + + out = fopen(filename, "w"); + if (!out) { + ret = AVERROR(errno); + perror(filename); + return ret; + } + fprintf(out, "\n"); + fprintf(out, "duration, 1, AV_ROUND_DOWN); + fprintf(out, "\"\n"); + fprintf(out, "\tminBufferTime=\"PT5S\">\n"); + + fprintf(out, "\t\n"); + + for (set = 0; set < nb_sets; set++) { + if (nb_tracks[set] == 0) + continue; + fprintf(out, "\t\t\n"); + if (nb_sets == 1) { + for (i = 0; i < nb_tracks[set]; i++) { + struct Track *track = adaptation_sets[set][i]; + if (strcmp(track->name, adaptation_sets[set][0]->name)) + break; + fprintf(out, "\t\t\t\n", track->track_id, track->is_audio ? "audio" : "video"); + } + } + + for (i = 0; i < nb_tracks[set]; ) { + struct Track *first_track = adaptation_sets[set][i]; + int width = 0, height = 0, sample_rate = 0, channels = 0, bitrate = 0; + fprintf(out, "\t\t\tname, first_track->name)) + break; + if (track->is_audio) { + sample_rate = track->sample_rate; + channels = track->channels; + } + if (track->is_video) { + width = track->width; + height = track->height; + } + bitrate += track->bitrate; + if (j > i) + fprintf(out, ","); + fprintf(out, "%s", track->codec_str); + } + fprintf(out, "\" mimeType=\"%s/mp4\" bandwidth=\"%d\"", + width ? "video" : "audio", bitrate); + if (width > 0 && height > 0) + fprintf(out, " width=\"%d\" height=\"%d\"", width, height); + if (sample_rate > 0) + fprintf(out, " audioSamplingRate=\"%d\"", sample_rate); + fprintf(out, ">\n"); + if (channels > 0) + fprintf(out, "\t\t\t\t\n", channels); + fprintf(out, "\t\t\t\t%s\n", first_track->name); + fprintf(out, "\t\t\t\t\n", first_track->sidx_start, first_track->sidx_start + first_track->sidx_length - 1); + fprintf(out, "\t\t\t\n"); + i = j; + } + fprintf(out, "\t\t\n"); + } + fprintf(out, "\t\n"); + fprintf(out, "\n"); + + fclose(out); +err: + for (i = 0; i < 2; i++) + av_free(adaptation_sets_buf[i]); + return ret; +} + +static void clean_tracks(struct Tracks *tracks) +{ + int i; + for (i = 0; i < tracks->nb_tracks; i++) { + av_freep(&tracks->tracks[i]); + } + av_freep(&tracks->tracks); + tracks->nb_tracks = 0; +} + +int main(int argc, char **argv) +{ + const char *out = NULL; + struct Tracks tracks = { 0 }; + int i; + + av_register_all(); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-out")) { + out = argv[i + 1]; + i++; + } else if (argv[i][0] == '-') { + return usage(argv[0], 1); + } else { + if (handle_file(&tracks, argv[i])) + return 1; + } + } + if (!tracks.nb_tracks || !out) + return usage(argv[0], 1); + + output_mpd(&tracks, out); + + clean_tracks(&tracks); + + return 0; +} -- 2.7.4